main.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package main
  2. import (
  3. "os"
  4. "fmt"
  5. "runtime"
  6. "kumachan/standalone/qt"
  7. "kumachan/standalone/util"
  8. "kumachan/standalone/util/argv"
  9. "kumachan/standalone/util/fatal"
  10. "kumachan/lang/textual"
  11. "kumachan/lang/textual/syntax"
  12. "kumachan/interpreter"
  13. "kumachan/interpreter/core"
  14. "kumachan/interpreter/debugging"
  15. "kumachan/support/atom"
  16. )
  17. const Version = "0.0.0 experimental"
  18. const SourceFilePathPrompt = "Input a source file path or press Enter to start REPL:"
  19. type Args struct {
  20. Positional [] string `arg:"positional" hint:"[PATH [ARGUMENT]...]"`
  21. Command string `arg:"command" key:"help-0; version-0; atom-0; parse; run" default:"run" desc:"show this help; show version; start plugin backend service for the Atom Editor; parse the file at PATH; run the file or directory at PATH"`
  22. EntryNS string `arg:"value-string" key:"entry" hint:"NS" desc:"namespace of entry point"`
  23. Debug bool `arg:"flag-enable" key:"debug" desc:"enable debugger"`
  24. }
  25. var Commands = map[string] func(*Args) {
  26. "version": func(_ *Args) {
  27. fmt.Println(Version)
  28. },
  29. "atom": func(_ *Args) {
  30. var err = atom.LangServer(os.Stdin, os.Stdout, os.Stderr)
  31. if err != nil { fatal.ThrowError(err) }
  32. },
  33. "parse": func(args *Args) {
  34. var L = len(args.Positional)
  35. if L == 0 {
  36. textual.DebugParser(os.Stdin, "(stdin)", syntax.ReplRoot())
  37. } else if L >= 1 {
  38. for _, file := range args.Positional {
  39. f, err := os.Open(file)
  40. if err != nil { fatal.ThrowError(err) }
  41. textual.DebugParser(f, f.Name(), syntax.DefaultRoot())
  42. err = f.Close()
  43. if err != nil { fatal.ThrowError(err) }
  44. }
  45. }
  46. },
  47. "run": func(args *Args) {
  48. var file, file_not_specified, p_args = (func() (string, bool, ([] string)) {
  49. var L = len(args.Positional)
  50. if L == 0 {
  51. var file = ""
  52. return file, true, nil
  53. } else {
  54. var file = args.Positional[0]
  55. return file, false, args.Positional[1:]
  56. }
  57. })()
  58. if file_not_specified {
  59. fmt.Fprintf(os.Stderr, "%s\n", SourceFilePathPrompt)
  60. var line, _, err = util.WellBehavedFscanln(os.Stdin)
  61. if err != nil { fatal.ThrowError(err) }
  62. if line != "" {
  63. file = line
  64. file_not_specified = false
  65. }
  66. }
  67. var p, info, err = interpreter.Compile(file, nil)
  68. if err != nil { fatal.ThrowError(err) }
  69. var p_ns = args.EntryNS
  70. var d = (func() core.Debugger {
  71. var debugger_enabled = (args.Debug || file_not_specified)
  72. if debugger_enabled {
  73. return debugging.CreateNaiveDebugger(info)
  74. } else {
  75. return nil
  76. }
  77. })()
  78. qt.Init()
  79. { var err = interpreter.Run(p, p_ns, p_args, d, func() { qt.Exit(0) })
  80. if err != nil { fatal.ThrowError(err) }
  81. qt.Main() }
  82. },
  83. }
  84. func main() {
  85. runtime.LockOSThread()
  86. var args, help, err = argv.ParseArgs[Args](os.Args)
  87. if err != nil { fatal.ThrowBadArgsError(err, help) }
  88. if args.Command == "help" {
  89. fmt.Println(help)
  90. } else {
  91. Commands[args.Command](&args)
  92. }
  93. }