// Package forge implements a stack-based interpreter. package forge import ( "git.sr.ht/~cco/go-scopes/common/ptr" "git.sr.ht/~cco/go-scopes/common/stack" "git.sr.ht/~cco/go-scopes/common/voc" ) type fitem interface{} type FItem = fitem type fptr = ptr.Ptr[fitem] type FPtr = fptr type fstack = stack.Stack[fitem] type fvoc = voc.Vocabulary[fitem] type Callable func(*forgeEnv, XT) type forgeEnv struct { ds, rs fstack ip fptr latestxt XT voc *fvoc } type FE = *forgeEnv func NewFE() *forgeEnv { return newFE(newVoc(nil)) } func (f *forgeEnv) ChildFE() *forgeEnv { return newFE(newVoc(f.voc)) } func newFE(voc *fvoc) *forgeEnv { return &forgeEnv{ ds: stack.NewStack[fitem](), rs: stack.NewStack[fitem](), ip: ptr.NewSlice[fitem](), voc: voc, } } var newVoc = voc.NewVoc[fitem] var newScalar = ptr.NewScalar[fitem] var newPtr = ptr.NewSlice[fitem] // forgeEnv methods func (f *forgeEnv) Code(items ...fitem) fptr { code := newPtr(items...) // ... pre-process (compile) code ... return code } func (f *forgeEnv) Call(code fptr) *forgeEnv { f.rs.Push(f.ip) f.ip = code.Clone() for f.ip.Next() != nil { value := f.ip.Value() if xt, ok := value.(XT); ok { xt.Fct()(f, xt) } else { f.Push(value) } } f.ip = f.RPop() return f } func (f *forgeEnv) Exec(items ...fitem) *forgeEnv { return f.Call(f.Code(items...)) } func (f *forgeEnv) NewVar() fptr { return newScalar() } func (f *forgeEnv) Literal() fitem { return f.ip.Next().Value() } func (f *forgeEnv) Voc() *fvoc { return f.voc } func (f *forgeEnv) Push(it fitem) { f.ds.Push(it) } func (f *forgeEnv) Pop() fitem { return f.ds.Pop() } func (f *forgeEnv) PopI() int { return f.ds.Pop().(int) } func (f *forgeEnv) Peek(d int) fitem { return f.ds.Peek(d) } func (f *forgeEnv) RPop() fptr { return f.rs.Pop().(fptr) } func (f *forgeEnv) Reset() fptr { return f.ip.Reset() } func (f *forgeEnv) LatestXT() XT { return f.latestxt } func (f *forgeEnv) Register(xt XT) { Register(f.Voc(), xt) f.latestxt = xt } // basic functions for executable items func doFCode(f *forgeEnv, xt XT) { f.Call(xt.Code().New()) }