main.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package main
  2. import (
  3. "os"
  4. "fmt"
  5. "errors"
  6. "reflect"
  7. "runtime"
  8. "kumachan/standalone/qt"
  9. "kumachan/standalone/util"
  10. "kumachan/standalone/util/argv"
  11. "kumachan/standalone/util/fatal"
  12. "kumachan/interpreter"
  13. "kumachan/interpreter/lang/textual/syntax"
  14. "kumachan/interpreter/runtime/def"
  15. "kumachan/interpreter/runtime/vm"
  16. "kumachan/interpreter/runtime/lib/env"
  17. "kumachan/support/atom"
  18. )
  19. const Version = "KumaChan 0.0.0 pre-alpha"
  20. const NoProgramFilePrompt = "** No Program File or Directory Specified **\n" +
  21. "input a path or press enter to start REPL:"
  22. type Args struct {
  23. Positional [] string `arg:"positional" hint:"[PATH [ARGUMENT]...]"`
  24. Command string `arg:"command" key:"help; version; atom; parse; run" default:"run" desc:"show this help; show version; run Atom Editor plugin backend service; parse the file at PATH; run the file or directory at PATH"`
  25. EnableRepl bool `arg:"flag-enable" key:"repl" desc:"enable REPL"`
  26. DebugUI bool `arg:"flag-enable" key:"debug-ui" desc:"enable ui debugging"`
  27. AsmDumpPath string `arg:"value-string" key:"asm-dump" hint:"FILE" desc:"dump ASM text to FILE"`
  28. }
  29. func main() {
  30. // Qt Main should be executed on main thread to avoid unknown problems
  31. runtime.LockOSThread()
  32. // get command line options
  33. var args Args
  34. var help, err = argv.ParseArgs(os.Args, reflect.ValueOf(&args))
  35. if err != nil {
  36. fatal.BadArgs(err, help)
  37. }
  38. switch args.Command {
  39. case "help":
  40. fmt.Fprintf(os.Stderr, "%s\n", help)
  41. case "version":
  42. fmt.Fprintf(os.Stderr, "%s\n", Version)
  43. case "atom":
  44. if len(args.Positional) == 0 {
  45. var err = atom.LangServer(os.Stdin, os.Stdout, os.Stderr)
  46. if err != nil { fatal.CrashGoError(err, "Crashed") }
  47. } else {
  48. // TODO: validate quantity of positional arguments in argv.go
  49. const problem = "redundant ARGUMENT(s) in 'atom' command"
  50. fatal.BadArgs(errors.New(problem), help)
  51. }
  52. case "parse":
  53. const default_root = syntax.DefaultRootPartName
  54. const repl_root = syntax.ReplRootPartName
  55. var L = len(args.Positional)
  56. if L == 0 {
  57. interpreter.DebugParser(os.Stdin, "(stdin)", repl_root)
  58. } else if L == 1 {
  59. var file = args.Positional[0]
  60. if file == "-" {
  61. interpreter.DebugParser(os.Stdin, "(stdin)", default_root)
  62. } else {
  63. f, err := os.Open(file)
  64. if err != nil { fatal.CrashGoError(err, "Crashed") }
  65. interpreter.DebugParser(f, f.Name(), default_root)
  66. err = f.Close()
  67. if err != nil { fatal.CrashGoError(err, "Crashed") }
  68. }
  69. } else {
  70. const problem = "redundant ARGUMENT(s) in 'parse' command"
  71. fatal.BadArgs(errors.New(problem), help)
  72. }
  73. case "run":
  74. var entry_path, no_file_specified, program_args =
  75. (func() (string, bool, ([] string)) {
  76. var L = len(args.Positional)
  77. if L == 0 {
  78. return "", true, nil
  79. } else {
  80. var entry_path = args.Positional[0]
  81. var program_args = args.Positional[1:]
  82. return entry_path, false, program_args
  83. }
  84. })()
  85. if no_file_specified {
  86. fmt.Fprintf(os.Stderr, "%s\n", NoProgramFilePrompt)
  87. var line, err = util.WellBehavedReadLine(os.Stdin)
  88. if err != nil { panic(err) }
  89. if len(line) > 0 {
  90. entry_path = string(line)
  91. no_file_specified = false
  92. }
  93. }
  94. var repl_config *interpreter.ReplConfig
  95. if args.EnableRepl || no_file_specified {
  96. repl_config = &interpreter.ReplConfig {
  97. Input: os.Stdin,
  98. Output: os.Stderr,
  99. }
  100. }
  101. var options = &vm.Options {
  102. Environment: env.NewDefaultEnvironment(program_args),
  103. ExecutionOptions: vm.ExecutionOptions {},
  104. DebuggingOptions: vm.DebuggingOptions {
  105. BasicOptions: def.DebugOptions {
  106. DebugUI: args.DebugUI,
  107. },
  108. AsmDumpPath: args.AsmDumpPath,
  109. },
  110. }
  111. if options.DebuggingOptions.BasicOptions.DebugUI {
  112. qt.EnableDebug()
  113. }
  114. go (func() {
  115. interpreter.Run(entry_path, options, repl_config)
  116. qt.NotifyNotUsed()
  117. })()
  118. qt.Main()
  119. default:
  120. panic("impossible branch")
  121. }
  122. }