forge: execute simple forge code

This commit is contained in:
Helmut Merz 2023-07-23 10:20:25 +02:00
parent 96a1bdb39f
commit c724ad89bd
3 changed files with 49 additions and 36 deletions

View file

@ -9,15 +9,22 @@ type builtins struct {
Add, Lit XT
}
func Setup(f FE) *builtins {
func Get(f FE) *builtins {
m := f.Voc().Lookup("builtins")
if m.IsNothing() {
b := setup(f)
f.Voc().Register("builtins", b)
return b
}
return m.Value().(*builtins)
}
func setup(f FE) *builtins {
r := func(name string, fct forge.Callable) XT {
return forge.Register(f.Voc(), name, fct)
}
return &builtins{
Lit: r("literal", literal),
Add: r("+", func(f FE, _ XT) { f.Push(f.Pop().(int) + f.Pop().(int)) }),
Lit: r("literal", func(f FE, _ XT) { f.Literal() }),
}
}
func literal(f FE, it XT) {
f.Push(f.IP().Next().Value())
}

View file

@ -14,19 +14,10 @@ type fitem interface{}
type fptr = ptr.Ptr[fitem]
type fstack = stack.Stack[fitem]
type fvoc = voc.Vocabulary[XT]
type fvoc = voc.Vocabulary[fitem]
type Callable func(*forgeEnv, XT)
type xitem struct {
name string
immediate bool
fct Callable
body fptr
}
type XT = *xitem
type forgeEnv struct {
ds, rs fstack
cp, ip, dp fptr
@ -38,16 +29,12 @@ type forgeEnv struct {
type FE = *forgeEnv
func NewVoc(parent *fvoc) *fvoc {
return voc.NewVoc[XT](parent)
}
func NewFE() *forgeEnv {
return newFE(NewVoc(nil))
return newFE(newVoc(nil))
}
func (f *forgeEnv) ChildFE() *forgeEnv {
return newFE(NewVoc(f.voc))
return newFE(newVoc(f.voc))
}
func newFE(voc *fvoc) *forgeEnv {
@ -60,7 +47,20 @@ func newFE(voc *fvoc) *forgeEnv {
}
}
// basic functions and methods
var newVoc = voc.NewVoc[fitem]
var newPtr = ptr.NewSlice[fitem]
// xitem (executable item) / XT (execution token)
type xitem struct {
name string
immediate bool
fct Callable
body fptr
}
type XT = *xitem
func Register(voc *fvoc, name string, fct Callable) *xitem {
it := xitem{
@ -81,7 +81,7 @@ func (it *xitem) Immediate() {
func (it *xitem) Body() fptr {
if it.body == nil {
it.body = ptr.NewSlice[fitem]()
it.body = newPtr()
}
return it.body
}
@ -90,22 +90,26 @@ func (it *xitem) Name() string {
return it.name
}
// ForgeEnv methods
// forgeEnv methods
func (f *forgeEnv) Voc() *fvoc {
return f.voc
}
func (f *forgeEnv) IP() fptr {
return f.ip
func (f *forgeEnv) Code(items ...fitem) fptr {
code := newPtr(items...)
// ... pre-process (compile) code ...
return code
}
func (f *forgeEnv) Exec(items ...fitem) {
f.ip = ptr.NewSlice[fitem](items...)
func (f *forgeEnv) Call(code fptr) {
f.rs.Push(f.ip)
f.ip = code.Clone()
for f.ip.Next() != nil {
it := f.ip.Value().(XT)
it.fct(f, it)
xt := f.ip.Value().(XT)
xt.fct(f, xt)
}
f.ip = f.rs.Pop().(fptr)
}
func (f *forgeEnv) Push(it fitem) {
@ -115,3 +119,7 @@ func (f *forgeEnv) Push(it fitem) {
func (f *forgeEnv) Pop() fitem {
return f.ds.Pop()
}
func (f *forgeEnv) Literal() {
f.Push(f.ip.Next().Value())
}

View file

@ -15,9 +15,7 @@ func TestForge(tb *tbase.T) {
func ExecTest(t *testing.T) {
fe := forge.NewFE()
b := builtins.Setup(fe)
fe.Exec(b.Lit, 4)
t.AssertEqual(fe.Pop(), 4)
// fe.Execute(forge.Code{b.Lit, 3, b.Lit, 2, b.Add})
// t.AssertEqual(fe.Pop(), 5)
b := builtins.Get(fe)
fe.Call(fe.Code(b.Lit, 4, b.Lit, 2, b.Add))
t.AssertEqual(fe.Pop(), 6)
}