Make function calls work.

Function calls with parameters passed as value now work.
Return value handling and scopes still missing.
This commit is contained in:
Marc Vertes
2018-02-08 12:01:59 +01:00
parent f440b82788
commit e7614c95ef
3 changed files with 35 additions and 18 deletions

View File

@@ -25,8 +25,6 @@ func (e *Node) Cfg(i *Interpreter) int {
case *ast.FuncDecl:
n.findex = maxIndex
n.isConst = true
// Node value is func body entry point
n.val = n.Child[2]
i.def[n.Child[0].ident] = n
case *ast.BlockStmt:
wireChild(n)
@@ -69,6 +67,8 @@ func (e *Node) Cfg(i *Interpreter) int {
}
maxIndex++
n.findex = maxIndex
case *ast.Field:
n.findex = n.Child[0].findex
case *ast.CallExpr:
wireChild(n)
n.run = i.call
@@ -108,13 +108,15 @@ func (e *Node) Cfg(i *Interpreter) int {
}
case *ast.Ident:
// Lookup identifier in frame symbol table. If not found
// should check that ident is assign target.
// should check if ident can be defined (assign, param passing...)
// or should lookup in upper scope of variables
// For now, simply allocate a new entry in local sym table
n.ident = x.Name
if n.findex = symIndex[n.ident]; n.findex == 0 {
maxIndex++
symIndex[n.ident] = maxIndex
n.findex = symIndex[n.ident]
}
n.findex = symIndex[n.ident]
default:
println("unknown type:", reflect.TypeOf(*n.anode).String())
}

View File

@@ -34,7 +34,6 @@ type Frame struct {
// Interpreter contains global resources and state
type Interpreter struct {
size int
frame *Frame
out interface{}
def map[string]*Node // map of defined symbols
@@ -67,12 +66,12 @@ func NewInterpreter() *Interpreter {
// i.Eval(s) evaluates Go code represented as a string
func (i *Interpreter) Eval(src string) interface{} {
root := Ast(src)
root.AstDot()
i.size = root.Cfg(i)
root.CfgDot()
entry := root.Child[1].Child[2] // FIXME: entry point should be resolved from 'main' name
//root.AstDot()
root.Cfg(i)
//root.CfgDot()
entry := root.Child[1] // FIXME: entry point should be resolved from 'main' name
//entry.OptimCfg()
//entry.CfgDot()
i.Run(entry.Start)
Run(entry, nil, nil)
return i.out
}

View File

@@ -2,13 +2,25 @@ package interp
import "fmt"
func (i *Interpreter) Run(entry *Node) {
// Init Frame
f := &Frame{val: make([]interface{}, i.size)}
i.frame = f
// 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 := entry; n != nil; {
for n := body.Start; n != nil; {
n.run(n, f)
if n.fnext == nil || value(n, f).(bool) {
n = n.tnext
@@ -29,6 +41,7 @@ func value(n *Node, f *Frame) interface{} {
}
func assign(n *Node, f *Frame) {
fmt.Println("assign", n.index, n.Child[0].ident, n.findex)
f.val[n.findex] = value(n.Child[1], f)
}
@@ -48,9 +61,12 @@ func (i *Interpreter) call(n *Node, f *Frame) {
printa(n.Child[1:], f)
return
}
fn := i.def[n.Child[0].ident]
fmt.Println("call node", fn.index, fn.Child[2].findex)
panic("function not implemented")
// 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) {