Skip to content

Instantly share code, notes, and snippets.

@kemingy
Created August 25, 2022 07:33
Show Gist options
  • Save kemingy/7c3f6f5ab67af961552622576c6d3ac1 to your computer and use it in GitHub Desktop.
Save kemingy/7c3f6f5ab67af961552622576c6d3ac1 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"sync"
"go.starlark.net/starlark"
"go.starlark.net/starlarkstruct"
)
var fakeFilesystem = map[string]string {
"x.star": `y = use("y"); y.foo()`,
"y.star": `
name = "starlark"
# print(name)
def foo():
print(name)
`,
}
type entry struct {
globals starlark.StringDict
err error
}
type Interpreter struct {
predeclared starlark.StringDict
context string
cache map[string]*entry
}
var interpreter *Interpreter
var once sync.Once
var import_keyword = "use"
func GetInterpreter() *Interpreter {
once.Do(func() {
interpreter = &Interpreter{
predeclared: starlark.StringDict{},
cache: make(map[string]*entry),
context: "test",
}
})
return interpreter
}
func (it *Interpreter) load(thread *starlark.Thread, module string) (starlark.StringDict, error) {
return it.execModule(thread, module)
}
func (it *Interpreter) execModule(thread *starlark.Thread, module string) (starlark.StringDict, error) {
e, ok := it.cache[module]
if e != nil {
return e.globals, e.err
}
if ok {
return nil, fmt.Errorf("[x] cycle")
}
it.cache[module] = nil
data := fakeFilesystem[module]
fmt.Printf("@ before exec %s: %s\n", module, it.predeclared)
globals, err := starlark.ExecFile(thread, module, data, it.predeclared)
fmt.Printf("> after exec %s: %s\n%s\n", module, globals, it.predeclared)
e = &entry{globals, err}
return globals, err
}
func (it *Interpreter) newThread(name string) *starlark.Thread {
thread := &starlark.Thread{
Name: name,
Load: it.load,
}
return thread
}
func (it *Interpreter) Exec(filename string) (starlark.StringDict, error) {
thread := it.newThread(filename)
return it.execModule(thread, filename)
}
func main() {
it := GetInterpreter()
starlark.Universe[import_keyword] = starlark.NewBuiltin(import_keyword, func(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
var file string
if err := starlark.UnpackArgs(import_keyword, args, kwargs, "file?", &file); err != nil {
return nil, err
}
filename := file + ".star"
globals, err := thread.Load(thread, filename)
if err != nil {
return nil, err
}
module := &starlarkstruct.Module {
Name: file,
Members: globals,
}
return module, err
})
globals, err := it.Exec("x.star")
if err != nil {
fmt.Printf("exec error: %v\n", err)
return
}
fmt.Printf(">> %s\n", globals.String())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment