interpreter.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. package interpreter
  2. import (
  3. "embed"
  4. "fmt"
  5. "errors"
  6. "strconv"
  7. "kumachan/standalone/qt"
  8. "kumachan/standalone/util/richtext"
  9. "kumachan/lang/source"
  10. "kumachan/lang/textual/ast"
  11. "kumachan/interpreter/core"
  12. "kumachan/interpreter/program"
  13. "kumachan/interpreter/compiler"
  14. "kumachan/interpreter/builtin"
  15. )
  16. func Compile(file string, fs compiler.FileSystem) (*program.Program, *compiler.DebugInfo, error) {
  17. var p, info, errs1, errs2 = compile(file, fs)
  18. if errs1 != nil { return nil, nil, errs1 }
  19. if errs2 != nil { return nil, nil, errs2 }
  20. return p, info, nil
  21. }
  22. func compile(file string, fs compiler.FileSystem) (*program.Program, *compiler.DebugInfo, richtext.Errors, source.Errors) {
  23. if file == "" {
  24. file = dummyProjectFile
  25. fs = dummyProjectFileSystem
  26. }
  27. if fs == nil {
  28. fs = compiler.RealFileSystem {}
  29. }
  30. var q = [] string {
  31. file,
  32. }
  33. var visited = make(map[string] struct{})
  34. var lists = make([] [] string, 0)
  35. for len(q) > 0 {
  36. var current = q[0]
  37. q = q[1:]
  38. if _, ok := visited[current]; ok {
  39. continue
  40. }
  41. visited[current] = struct{}{}
  42. var manifest, err = compiler.ReadManifest(current, fs)
  43. if err != nil { return nil, nil, richtext.Std2Errors(err), nil }
  44. lists = append(lists, manifest.ProjectFiles)
  45. for _, dep := range manifest.DependencyFiles {
  46. q = append(q, dep)
  47. }
  48. }
  49. var groups = [] compiler.SourceFileGroup {
  50. builtinSourceFileGroup,
  51. }
  52. for _, list := range lists {
  53. groups = append(groups, compiler.SourceFileGroup {
  54. FileList: list,
  55. FileSystem: fs,
  56. })
  57. }
  58. var meta = program.Metadata {
  59. ProgramPath: file,
  60. }
  61. return compiler.Compile(groups, meta)
  62. }
  63. //go:embed builtin/builtin.km
  64. var builtinRawFileSystem embed.FS
  65. var builtinSourceFileGroup = compiler.SourceFileGroup {
  66. FileList: [] string {
  67. "builtin/builtin.km",
  68. },
  69. FileSystem: compiler.EmbeddedFileSystem {
  70. Id: "builtin",
  71. FS: builtinRawFileSystem,
  72. },
  73. }
  74. var dummyProjectFile = "dummy.manifest.json"
  75. var dummyProjectFileSystem = compiler.FileSystem(compiler.InlineFileSystem {
  76. Id: "dummy",
  77. Files: map[string] ([] byte) {
  78. "dummy.km": ([] byte)("namespace :: entry { $() }"),
  79. dummyProjectFile: ([] byte)(`{"ProjectFiles":["dummy.km"]}`),
  80. },
  81. })
  82. func Lint(file string, fs compiler.FileSystem) (richtext.Errors, source.Errors) {
  83. var _, _, errs1, errs2 = compile(file, fs)
  84. return errs1, errs2
  85. }
  86. func ParseBuiltinFiles() ([] *ast.Root, richtext.Error) {
  87. var group = builtinSourceFileGroup
  88. var result = make([] *ast.Root, len(group.FileList))
  89. for i, file := range group.FileList {
  90. var root, err = compiler.Load(file, group.FileSystem)
  91. if err != nil { return nil, err }
  92. result[i] = root
  93. }
  94. return result, nil
  95. }
  96. func Run(p *program.Program, ns string, args ([] string), d core.Debugger, k func()) error {
  97. if entry, ok := p.Executable.LookupEntry(ns); ok {
  98. go (func() {
  99. run(p, entry, args, d)
  100. qt.Schedule(k)
  101. })()
  102. return nil
  103. } else {
  104. return errors.New(fmt.Sprintf(
  105. `missing entry point for namespace "%s ::"`, ns,
  106. ))
  107. }
  108. }
  109. func run(p *program.Program, entry **program.Function, args ([] string), d core.Debugger) {
  110. var eventloop = core.CreateEventLoop()
  111. var c = &runtimeContext {
  112. program: p,
  113. arguments: args,
  114. eventloop: eventloop,
  115. debugger: nil,
  116. }
  117. var h = &runtimeHandle {
  118. context: c,
  119. frameInfo: core.TopLevelFrameInfo(),
  120. }
  121. if d != nil {
  122. c.debugger = d.CreateInstance(h)
  123. }
  124. var ctx = program.CreateEvalContext(h)
  125. var obj = (program.CallFunction { Callee: entry }).Eval(ctx)
  126. var o = core.GetObservable(obj)
  127. var E = make(chan error, 1)
  128. var T = make(chan bool)
  129. core.Run(o, eventloop, core.DataSubscriber {
  130. Error: E,
  131. Terminate: T,
  132. })
  133. if <- T {
  134. if c.debugger != nil {
  135. c.debugger.ExitNotifier().Wait()
  136. }
  137. } else {
  138. var e = <- E
  139. core.Crash(h, core.ErrorInEntryObservable, e.Error())
  140. }
  141. }
  142. type runtimeContext struct {
  143. program *program.Program
  144. arguments [] string
  145. eventloop *core.EventLoop
  146. debugger core.DebuggerInstance
  147. }
  148. type runtimeHandle struct {
  149. context *runtimeContext
  150. frameInfo *core.FrameInfo
  151. }
  152. func (h *runtimeHandle) GetFrameInfo() *core.FrameInfo {
  153. return h.frameInfo
  154. }
  155. func (h *runtimeHandle) WithFrameInfo(info *core.FrameInfo) core.RuntimeHandle {
  156. return &runtimeHandle {
  157. context: h.context,
  158. frameInfo: info,
  159. }
  160. }
  161. func (h *runtimeHandle) LibraryNativeFunction(id string) core.NativeFunction {
  162. var f, exists = builtin.LookupFunction(id)
  163. if !(exists) {
  164. var msg = fmt.Sprintf("no such native function: %s", strconv.Quote(id))
  165. core.Crash(h, core.MissingNativeFunction, msg)
  166. }
  167. return f
  168. }
  169. func (h *runtimeHandle) ProgramPath() string {
  170. return h.context.program.Metadata.ProgramPath
  171. }
  172. func (h *runtimeHandle) ProgramArgs() ([] string) {
  173. return h.context.arguments
  174. }
  175. func (h *runtimeHandle) SerializationContext() core.SerializationContext {
  176. return h.context.program.TypeInfo
  177. }
  178. func (h *runtimeHandle) EventLoop() *core.EventLoop {
  179. return h.context.eventloop
  180. }
  181. func (h *runtimeHandle) Debugger() (core.DebuggerInstance, bool) {
  182. var d = h.context.debugger
  183. return d, (d != nil)
  184. }