106 lines
2.7 KiB
Go
106 lines
2.7 KiB
Go
package builtins
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"git.sr.ht/~cco/go-scopes/forge"
|
|
)
|
|
|
|
type FE = forge.FE
|
|
type XT = forge.XT
|
|
type FPtr = forge.FPtr
|
|
|
|
type builtins struct {
|
|
Add, Body, Code, Comp, Do, Dot, Drop, Dup, Get, If, IfElse, Leave, LT, Lit,
|
|
Mult, New1, Over, Put, Reg, Repeat, Sub, Swap,
|
|
Var1 XT
|
|
}
|
|
|
|
func Get(f FE) *builtins {
|
|
if v, ok := f.Voc().Lookup("builtins"); ok {
|
|
return v.(*builtins)
|
|
}
|
|
b := setup(f)
|
|
f.Voc().Register("builtins", b)
|
|
return b
|
|
}
|
|
|
|
func setup(f FE) *builtins {
|
|
voc := f.Voc()
|
|
r := func(name string, fct forge.Callable) XT {
|
|
return forge.Register(voc, forge.GoFunc(name, fct))
|
|
}
|
|
b := builtins{
|
|
Add: r("+", func(f FE) { f.Push(f.PopI() + f.PopI()) }),
|
|
Body: r("body", func(f FE) { f.Push(f.Pop().(XT).Code().New().Next()) }),
|
|
Code: r("code", func(f FE) { f.Push(f.Code()) }),
|
|
Comp: r("comp", func(f FE) { f.LatestXT().Code().Append(f.Pop()) }),
|
|
Do: r("do", func(f FE) { f.Call(f.Literal().(FPtr)) }),
|
|
Dot: r(".", func(f FE) { fmt.Println(f.Peek(0)) }),
|
|
Drop: r("drop", func(f FE) { f.Pop() }),
|
|
Dup: r("dup", func(f FE) { f.Push(f.Peek(0)) }),
|
|
Get: r("@", func(f FE) { f.Push(f.Pop().(FPtr).Value()) }),
|
|
If: r("if", func(f FE) { doif(f) }),
|
|
IfElse: r("if-else", func(f FE) { doifelse(f) }),
|
|
Leave: r("leave", func(f FE) { f.RPop() }),
|
|
Lit: r("lit", func(f FE) { f.Push(f.Literal()) }),
|
|
LT: r("<", func(f FE) { f.Push(f.PopI() > f.PopI()) }),
|
|
Mult: r("*", func(f FE) { f.Push(f.PopI() * f.PopI()) }),
|
|
New1: r("new1", func(f FE) { f.Push(f.NewVar()) }),
|
|
Over: r("over", func(f FE) { f.Push(f.Peek(1)) }),
|
|
Put: r("!", func(f FE) { f.Pop().(FPtr).Set(f.Pop()) }),
|
|
Reg: r("reg", func(f FE) { doreg(f) }),
|
|
Repeat: r("repeat", func(f FE) { f.Reset() }),
|
|
Sub: r("-", func(f FE) {
|
|
a := f.PopI()
|
|
f.Push(f.PopI() - a)
|
|
}),
|
|
Swap: r("swap", func(f FE) { doswap(f) }),
|
|
/*Append: r("append", func(f FE, _ XT) {
|
|
item := f.Pop()
|
|
f.Peek(0).(FPtr).Append(item)
|
|
}),*/
|
|
}
|
|
rf := func(name string, code ...forge.FItem) XT {
|
|
return forge.Register(voc, forge.FCode(name, f.Code(code...)))
|
|
}
|
|
b.Var1 = rf("var1", b.Code, b.Swap, b.Reg, b.New1, b.Comp)
|
|
return &b
|
|
}
|
|
|
|
func doif(f FE) {
|
|
ifBranch := f.Literal().(FPtr)
|
|
if f.Pop().(bool) {
|
|
f.Call(ifBranch)
|
|
}
|
|
}
|
|
|
|
func doifelse(f FE) {
|
|
ifBranch := f.Literal().(FPtr)
|
|
elseBranch := f.Literal().(FPtr)
|
|
if f.Pop().(bool) {
|
|
f.Call(ifBranch)
|
|
} else {
|
|
f.Call(elseBranch)
|
|
}
|
|
}
|
|
|
|
func doswap(f FE) {
|
|
a := f.Pop()
|
|
b := f.Pop()
|
|
f.Push(a)
|
|
f.Push(b)
|
|
}
|
|
|
|
func doreg(f FE) {
|
|
f.Register(forge.FCode(f.Pop().(string), f.Pop().(FPtr)))
|
|
}
|
|
|
|
func create(f FE) {
|
|
name := f.Pop().(string)
|
|
does := forge.AnonCode(f.Pop().(FPtr))
|
|
f.Register(forge.GoFunc(name, func(f FE) {
|
|
f.Register(forge.FCode(f.Pop().(string),
|
|
f.Code(f.NewVar(), does)))
|
|
}))
|
|
}
|