123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- package interpreter
- import (
- "embed"
- "fmt"
- "errors"
- "strconv"
- "kumachan/standalone/qt"
- "kumachan/standalone/util/richtext"
- "kumachan/lang/source"
- "kumachan/lang/textual/ast"
- "kumachan/interpreter/core"
- "kumachan/interpreter/program"
- "kumachan/interpreter/compiler"
- "kumachan/interpreter/builtin"
- )
- func Compile(file string, fs compiler.FileSystem) (*program.Program, *compiler.DebugInfo, error) {
- var p, info, errs1, errs2 = compile(file, fs)
- if errs1 != nil { return nil, nil, errs1 }
- if errs2 != nil { return nil, nil, errs2 }
- return p, info, nil
- }
- func compile(file string, fs compiler.FileSystem) (*program.Program, *compiler.DebugInfo, richtext.Errors, source.Errors) {
- if file == "" {
- file = dummyProjectFile
- fs = dummyProjectFileSystem
- }
- if fs == nil {
- fs = compiler.RealFileSystem {}
- }
- var q = [] string {
- file,
- }
- var visited = make(map[string] struct{})
- var lists = make([] [] string, 0)
- for len(q) > 0 {
- var current = q[0]
- q = q[1:]
- if _, ok := visited[current]; ok {
- continue
- }
- visited[current] = struct{}{}
- var manifest, err = compiler.ReadManifest(current, fs)
- if err != nil { return nil, nil, richtext.Std2Errors(err), nil }
- lists = append(lists, manifest.ProjectFiles)
- for _, dep := range manifest.DependencyFiles {
- q = append(q, dep)
- }
- }
- var groups = [] compiler.SourceFileGroup {
- builtinSourceFileGroup,
- }
- for _, list := range lists {
- groups = append(groups, compiler.SourceFileGroup {
- FileList: list,
- FileSystem: fs,
- })
- }
- var meta = program.Metadata {
- ProgramPath: file,
- }
- return compiler.Compile(groups, meta)
- }
- //go:embed builtin/builtin.km
- var builtinRawFileSystem embed.FS
- var builtinSourceFileGroup = compiler.SourceFileGroup {
- FileList: [] string {
- "builtin/builtin.km",
- },
- FileSystem: compiler.EmbeddedFileSystem {
- Id: "builtin",
- FS: builtinRawFileSystem,
- },
- }
- var dummyProjectFile = "dummy.manifest.json"
- var dummyProjectFileSystem = compiler.FileSystem(compiler.InlineFileSystem {
- Id: "dummy",
- Files: map[string] ([] byte) {
- "dummy.km": ([] byte)("namespace :: entry { $() }"),
- dummyProjectFile: ([] byte)(`{"ProjectFiles":["dummy.km"]}`),
- },
- })
- func Lint(file string, fs compiler.FileSystem) (richtext.Errors, source.Errors) {
- var _, _, errs1, errs2 = compile(file, fs)
- return errs1, errs2
- }
- func ParseBuiltinFiles() ([] *ast.Root, richtext.Error) {
- var group = builtinSourceFileGroup
- var result = make([] *ast.Root, len(group.FileList))
- for i, file := range group.FileList {
- var root, err = compiler.Load(file, group.FileSystem)
- if err != nil { return nil, err }
- result[i] = root
- }
- return result, nil
- }
- func Run(p *program.Program, ns string, args ([] string), d core.Debugger, k func()) error {
- if entry, ok := p.Executable.LookupEntry(ns); ok {
- go (func() {
- run(p, entry, args, d)
- qt.Schedule(k)
- })()
- return nil
- } else {
- return errors.New(fmt.Sprintf(
- `missing entry point for namespace "%s ::"`, ns,
- ))
- }
- }
- func run(p *program.Program, entry **program.Function, args ([] string), d core.Debugger) {
- var eventloop = core.CreateEventLoop()
- var c = &runtimeContext {
- program: p,
- arguments: args,
- eventloop: eventloop,
- debugger: nil,
- }
- var h = &runtimeHandle {
- context: c,
- frameInfo: core.TopLevelFrameInfo(),
- }
- if d != nil {
- c.debugger = d.CreateInstance(h)
- }
- var ctx = program.CreateEvalContext(h)
- var obj = (program.CallFunction { Callee: entry }).Eval(ctx)
- var o = core.GetObservable(obj)
- var E = make(chan error, 1)
- var T = make(chan bool)
- core.Run(o, eventloop, core.DataSubscriber {
- Error: E,
- Terminate: T,
- })
- if <- T {
- if c.debugger != nil {
- c.debugger.ExitNotifier().Wait()
- }
- } else {
- var e = <- E
- core.Crash(h, core.ErrorInEntryObservable, e.Error())
- }
- }
- type runtimeContext struct {
- program *program.Program
- arguments [] string
- eventloop *core.EventLoop
- debugger core.DebuggerInstance
- }
- type runtimeHandle struct {
- context *runtimeContext
- frameInfo *core.FrameInfo
- }
- func (h *runtimeHandle) GetFrameInfo() *core.FrameInfo {
- return h.frameInfo
- }
- func (h *runtimeHandle) WithFrameInfo(info *core.FrameInfo) core.RuntimeHandle {
- return &runtimeHandle {
- context: h.context,
- frameInfo: info,
- }
- }
- func (h *runtimeHandle) LibraryNativeFunction(id string) core.NativeFunction {
- var f, exists = builtin.LookupFunction(id)
- if !(exists) {
- var msg = fmt.Sprintf("no such native function: %s", strconv.Quote(id))
- core.Crash(h, core.MissingNativeFunction, msg)
- }
- return f
- }
- func (h *runtimeHandle) ProgramPath() string {
- return h.context.program.Metadata.ProgramPath
- }
- func (h *runtimeHandle) ProgramArgs() ([] string) {
- return h.context.arguments
- }
- func (h *runtimeHandle) SerializationContext() core.SerializationContext {
- return h.context.program.TypeInfo
- }
- func (h *runtimeHandle) EventLoop() *core.EventLoop {
- return h.context.eventloop
- }
- func (h *runtimeHandle) Debugger() (core.DebuggerInstance, bool) {
- var d = h.context.debugger
- return d, (d != nil)
- }
|