main.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package main
  2. import (
  3. "os"
  4. "fmt"
  5. "reflect"
  6. "runtime"
  7. "kumachan/standalone/qt"
  8. "kumachan/standalone/util"
  9. "kumachan/standalone/util/gcr"
  10. "kumachan/standalone/util/argv"
  11. "kumachan/standalone/util/fatal"
  12. "kumachan/interpreter"
  13. "kumachan/interpreter/lang/textual"
  14. "kumachan/interpreter/lang/textual/syntax"
  15. "kumachan/interpreter/runtime/vm"
  16. "kumachan/interpreter/runtime/rt"
  17. "kumachan/interpreter/runtime/lib/env"
  18. "kumachan/support/atom"
  19. "kumachan/support/mnfstedit"
  20. )
  21. var Help string
  22. const Version = "0.0.0 pre-alpha"
  23. const NoProgramFilePrompt = "** No Program File or Directory Specified **\n" +
  24. "input a path or press enter to start REPL:"
  25. type Args struct {
  26. Positional [] string `arg:"positional" hint:"[PATH [ARGUMENT]...]"`
  27. Command string `arg:"command" key:"help-0; version-0; atom-0; mnfst-0; gcr-1; parse; run" default:"run" desc:"show this help; show version; start plugin backend service for the Atom Editor; start module manifest editor; exec another program with GUI-based crash report; parse the file at PATH; run the file or directory at PATH"`
  28. EnableRepl bool `arg:"flag-enable" key:"repl" desc:"enable REPL"`
  29. DebugUI bool `arg:"flag-enable" key:"debug-ui" desc:"enable ui debugging"`
  30. AsmDumpPath string `arg:"value-string" key:"asm-dump" hint:"FILE" desc:"dump assembly code to FILE"`
  31. }
  32. var Commands = map[string] func(*Args) {
  33. "help": func(_ *Args) {
  34. fmt.Fprintf(os.Stderr, "%s\n", Help)
  35. },
  36. "version": func(_ *Args) {
  37. fmt.Fprintf(os.Stderr, "%s\n", Version)
  38. },
  39. "atom": func(_ *Args) {
  40. var err = atom.LangServer(os.Stdin, os.Stdout, os.Stderr)
  41. if err != nil { fatal.CrashGoError(err, "Crashed") }
  42. },
  43. "mnfst": WithQt(func(_ *Args) {
  44. mnfstedit.Setup()
  45. }),
  46. "gcr": WithQt(func(args *Args) {
  47. var another_argv = args.Positional
  48. gcr.Exec(another_argv)
  49. }),
  50. "parse": func(args *Args) {
  51. const default_root = syntax.DefaultRootPartName
  52. const repl_root = syntax.ReplRootPartName
  53. var L = len(args.Positional)
  54. if L == 0 {
  55. textual.DebugParser(os.Stdin, "(stdin)", repl_root)
  56. } else if L >= 1 {
  57. for _, file := range args.Positional {
  58. f, err := os.Open(file)
  59. if err != nil { fatal.CrashGoError(err, "Crashed") }
  60. textual.DebugParser(f, f.Name(), default_root)
  61. err = f.Close()
  62. if err != nil { fatal.CrashGoError(err, "Crashed") }
  63. }
  64. }
  65. },
  66. "run": WithQt(func(args *Args) {
  67. var entry_path, no_file_specified, program_args =
  68. (func() (string, bool, ([] string)) {
  69. var L = len(args.Positional)
  70. if L == 0 {
  71. return "", true, nil
  72. } else {
  73. var entry_path = args.Positional[0]
  74. var program_args = args.Positional[1:]
  75. return entry_path, false, program_args
  76. }
  77. })()
  78. if no_file_specified {
  79. fmt.Fprintf(os.Stderr, "%s\n", NoProgramFilePrompt)
  80. var line, _, err = util.WellBehavedFscanln(os.Stdin)
  81. if err != nil { panic(err) }
  82. if line != "" {
  83. entry_path = line
  84. no_file_specified = false
  85. }
  86. }
  87. var options = &vm.Options {
  88. Environment: env.NewDefaultEnvironment(program_args),
  89. ExecutionOptions: vm.ExecutionOptions {},
  90. DebuggingOptions: vm.DebuggingOptions {
  91. BasicOptions: rt.DebugOptions {
  92. DebugUI: args.DebugUI,
  93. },
  94. AsmDumpPath: args.AsmDumpPath,
  95. },
  96. }
  97. var repl_enabled = (args.EnableRepl || no_file_specified)
  98. var repl_config = interpreter.ReplConfig {
  99. Input: os.Stdin,
  100. Output: os.Stderr,
  101. }
  102. var p, err = interpreter.Compile(entry_path)
  103. if err != nil {
  104. fatal.Crash(err, "Failed to Compile")
  105. }
  106. if repl_enabled {
  107. interpreter.InjectRepl(&p, repl_config)
  108. }
  109. interpreter.Run(p, options)
  110. os.Exit(0)
  111. }),
  112. }
  113. func WithQt(cmd func(*Args)) func(*Args) {
  114. return func(args *Args) {
  115. qt.Init()
  116. go cmd(args)
  117. qt.Main()
  118. }
  119. }
  120. func main() {
  121. runtime.LockOSThread() // ensures Qt event loop running on main thread
  122. var args Args
  123. var err error
  124. Help, err = argv.ParseArgs(os.Args, reflect.ValueOf(&args))
  125. if err != nil {
  126. fatal.BadArgs(err, Help)
  127. }
  128. Commands[args.Command](&args)
  129. }