Files
moxa/interp/run.go
Marc Vertes b5ab905e2d Make gi a a real interpreter
Handle #! in first line to allow gi executable scripts.
Load program source from files.
Display AST and CFG graphs on command line flags.
2018-02-08 17:23:23 +01:00

84 lines
1.7 KiB
Go

package interp
import "fmt"
// Run a Go function
func Run(def *Node, uf *Frame, args []*Node) {
body := def.Child[2]
param := def.Child[1].Child[0]
// Init new Frame
f := &Frame{val: make([]interface{}, def.findex), up: uf}
if uf != nil {
uf.down = f
}
// Pass func parameters as value: copy each func parameter from old to new frame
// Frame locations were pre-computed during cfg
for i := 0; i < len(args); i++ {
f.val[param.Child[i].findex] = uf.val[args[i].findex]
}
// Start execution by runnning entry function and go to next
for n := body.Start; n != nil; {
n.run(n, f)
if n.fnext == nil || value(n, f).(bool) {
n = n.tnext
} else {
n = n.fnext
}
}
}
// Functions set to run during execution of CFG
func value(n *Node, f *Frame) interface{} {
if n.isConst {
return n.val
}
return f.val[n.findex]
}
func assign(n *Node, f *Frame) {
f.val[n.findex] = value(n.Child[1], f)
}
func and(n *Node, f *Frame) {
f.val[n.findex] = value(n.Child[0], f).(int64) & value(n.Child[1], f).(int64)
}
func printa(n []*Node, f *Frame) {
for _, m := range n {
fmt.Printf("%v", value(m, f))
}
fmt.Println("")
}
func (i *Interpreter) call(n *Node, f *Frame) {
if n.Child[0].ident == "println" {
printa(n.Child[1:], f)
return
}
// FIXME: resolve fn during compile, not exec ?
if fn := i.def[n.Child[0].ident]; fn != nil {
Run(fn, f, n.Child[1:])
} else {
panic("function not found")
}
}
func equal(n *Node, f *Frame) {
f.val[n.findex] = value(n.Child[0], f).(int64) == value(n.Child[1], f).(int64)
}
func inc(n *Node, f *Frame) {
f.val[n.findex] = value(n.Child[0], f).(int64) + 1
}
func lower(n *Node, f *Frame) {
f.val[n.findex] = value(n.Child[0], f).(int64) < value(n.Child[1], f).(int64)
}
func nop(n *Node, i *Frame) {}