diff --git a/_test/bin.go b/_test/bin.go new file mode 100644 index 00000000..795be9ae --- /dev/null +++ b/_test/bin.go @@ -0,0 +1,11 @@ +package main + +import "fmt" + +func main() { + f := fmt.Println + f("Hello") +} + +// Output: +// Hello diff --git a/_test/bltn.go b/_test/bltn.go new file mode 100644 index 00000000..ecc9e1b8 --- /dev/null +++ b/_test/bltn.go @@ -0,0 +1,6 @@ +package main + +func main() { + f := println + f("Hello") +} diff --git a/_test/closure4.go b/_test/closure4.go new file mode 100644 index 00000000..61c0a77f --- /dev/null +++ b/_test/closure4.go @@ -0,0 +1,23 @@ +package main + +type T1 struct { + Name string +} + +func (t *T1) genAdd(k int) func(int) int { + return func(i int) int { + println(t.Name) + return i + k + } +} + +var t = T1{"test"} + +func main() { + f := t.genAdd(4) + println(f(5)) +} + +// Output: +// test +// 9 diff --git a/_test/closure5.go b/_test/closure5.go new file mode 100644 index 00000000..e6d3c223 --- /dev/null +++ b/_test/closure5.go @@ -0,0 +1,23 @@ +package main + +type T1 struct { + Name string +} + +func (t T1) genAdd(k int) func(int) int { + return func(i int) int { + println(t.Name) + return i + k + } +} + +var t = T1{"test"} + +func main() { + f := t.genAdd(4) + println(f(5)) +} + +// Output: +// test +// 9 diff --git a/_test/closure6.go b/_test/closure6.go new file mode 100644 index 00000000..78decc50 --- /dev/null +++ b/_test/closure6.go @@ -0,0 +1,24 @@ +package main + +type T1 struct { + Name string +} + +func (t *T1) genAdd(k int) func(int) int { + return func(i int) int { + println(t.Name) + return i + k + } +} + +var t = &T1{"test"} + +func main() { + f := t.genAdd(4) + //g := f(4) + println(g(5)) +} + +// Output: +// test +// 9 diff --git a/_test/method12.go b/_test/method12.go new file mode 100644 index 00000000..ab389490 --- /dev/null +++ b/_test/method12.go @@ -0,0 +1,16 @@ +package main + +type Coord struct { + x, y int +} + +func (c Coord) dist() int { return c.x*c.x + c.y*c.y } + +func main() { + o := Coord{3, 4} + f := o.dist + println(f()) +} + +// Output: +// 25 diff --git a/_test/src4.go b/_test/src4.go index 0174b59d..ce07a038 100644 --- a/_test/src4.go +++ b/_test/src4.go @@ -3,8 +3,9 @@ package main import "github.com/containous/dyngo/_test/provider" func main() { - provider.F1() + f := provider.Bar + f() } // Output: -// SomeString: constant string +// Hello from Foo diff --git a/_test/struct7.go b/_test/struct7.go index 1caee308..a189f83e 100644 --- a/_test/struct7.go +++ b/_test/struct7.go @@ -13,3 +13,6 @@ func main() { a := T{} println(a.i, a.opt.b) } + +// Output: +// 0 false diff --git a/_test/struct8.go b/_test/struct8.go index ebc63659..679d6e08 100644 --- a/_test/struct8.go +++ b/_test/struct8.go @@ -19,9 +19,7 @@ func f(i int) int { return i * i } func main() { a := T{5, 7, T2{8, T3{9}}} - //println(a.f, a.g, a.T2.h, a.T2.T3.k) - //fmt.Println(a.T2) - println(a.h) + println(a.f, a.g, a.T2.h, a.T2.T3.k) } // Output: diff --git a/interp/ast.go b/interp/ast.go index c59b5429..64cf685e 100644 --- a/interp/ast.go +++ b/interp/ast.go @@ -184,7 +184,6 @@ const ( Add And Call - CallF Case CompositeLit Dec @@ -224,7 +223,6 @@ var actions = [...]string{ Add: "+", And: "&", Call: "call", - CallF: "call", Case: "case", CompositeLit: "compositeLit", Dec: "--", diff --git a/interp/cfg.go b/interp/cfg.go index 678b8cc9..9dec7dc8 100644 --- a/interp/cfg.go +++ b/interp/cfg.go @@ -115,7 +115,6 @@ func (scope *Scope) inc(interp *Interpreter) int { func (interp *Interpreter) Cfg(root *Node) []*Node { scope := interp.universe var loop, loopRestart *Node - var funcDef bool // True if a function is defined in the current frame context var initNodes []*Node var exports *BinMap var expval *ValueMap @@ -173,7 +172,6 @@ func (interp *Interpreter) Cfg(root *Node) []*Node { // allocate entries for return values at start of frame scope.size += len(n.child[2].child[1].child) } - funcDef = false case If0, If1, If2, If3: scope = scope.push(0) @@ -369,7 +367,9 @@ func (interp *Interpreter) Cfg(root *Node) []*Node { case CallExpr: wireChild(n) n.findex = scope.inc(interp) + log.Println(n.index, "call", n.child[0].typ) if n.child[0].sym != nil && n.child[0].sym.kind == Bltn { + // Call an internal go builtin n.gen = n.child[0].sym.builtin n.child[0].typ = &Type{cat: BuiltinT} switch n.child[0].ident { @@ -383,7 +383,7 @@ func (interp *Interpreter) Cfg(root *Node) []*Node { n.child[1].kind = BasicLit } } else if n.child[0].isType(scope) { - // Call expression is in fact a type conversion expression + // Type conversion expression n.typ = n.child[0].typ if n.typ.cat == AliasT { n.gen = convert @@ -396,113 +396,9 @@ func (interp *Interpreter) Cfg(root *Node) []*Node { n.gen = convertBin } } - } else if n.child[0].kind == SelectorImport { - // TODO: Should process according to child type, not kind. - n.fsize = n.child[0].fsize - var rtype reflect.Type - switch t := n.child[0].val.(type) { - case reflect.Type: - rtype = n.child[0].val.(reflect.Type) - case reflect.Value: - rtype = n.child[0].val.(reflect.Value).Type() - default: - log.Printf("unexpected type %T\n", t) - } - //rtype := n.child[0].val.(reflect.Value).Type() - if rtype.NumOut() > 0 { - n.typ = &Type{cat: ValueT, rtype: rtype.Out(0)} - } - n.child[0].kind = BasicLit - for i, c := range n.child[1:] { - // Wrap function defintion so it can be called from runtime - if c.kind == FuncLit { - n.child[1+i].rval = reflect.MakeFunc(rtype.In(i), c.wrapNode) - n.child[1+i].kind = Rvalue - } else if c.ident == "nil" { - n.child[1+i].rval = reflect.New(rtype.In(i)).Elem() - n.child[1+i].kind = Rvalue - } else if c.typ != nil && c.typ.cat == FuncT { - n.child[1+i].rval = reflect.MakeFunc(rtype.In(i), c.wrapNode) - n.child[1+i].kind = Rvalue - } - } - // TODO: handle multiple return value - if len(n.child) == 2 && n.child[1].fsize > 1 { - n.gen = callBinX - } else { - n.gen = callBin - } - } else if n.child[0].kind == SelectorExpr { - if n.child[0].typ.cat == ValueT { - n.gen = callBinMethod - // TODO: handle multiple return value (_test/time2.go) - n.child[0].kind = BasicLit // Temporary hack for force value() to return n.val at run - n.typ = &Type{cat: ValueT, rtype: n.child[0].typ.rtype} - n.fsize = n.child[0].fsize - } else if n.child[0].typ.cat == PtrT && n.child[0].typ.val.cat == ValueT { - n.gen = callBinMethod - n.child[0].kind = BasicLit // Temporary hack for force value() to return n.val at run - n.fsize = n.child[0].fsize - // TODO: handle type ? - } else if n.child[0].typ.cat == SrcPkgT { - n.val = n.child[0].val - if def := n.val.(*Node); def != nil { - // Reserve as many frame entries as nb of ret values for called function - // node frame index should point to the first entry - j := len(def.child[2].child) - 1 - l := len(def.child[2].child[j].child) // Number of return values for def - if l == 1 { - // If def returns exactly one value, propagate its type in call node. - // Multiple return values will be handled differently through AssignX. - n.typ = scope.getType(def.child[2].child[j].child[0].child[0].ident) - } - n.fsize = l - } - } else { - // Get method and receiver path, store them in node static value for run - if methodDecl, ok := n.child[0].val.(*Node); ok { - // method is already resolved, use it - if len(methodDecl.child[2].child) > 1 { - // Allocate frame for method return values (if any) - n.fsize = len(methodDecl.child[2].child[1].child) - n.typ = methodDecl.typ.ret[0] - // TODO: handle multiple return values - } else { - n.fsize = 0 - } - } else { - log.Println(n.index, "unresolve call") - // method must be resolved here due to declaration after use - } - n.child[0].findex = -1 // To force reading value from node instead of frame (methods) - } - } else if sym, _, _ := scope.lookup(n.child[0].ident); sym != nil { - if sym.typ != nil && sym.typ.cat == BinT { - n.gen = callBin - n.typ = &Type{cat: ValueT} - r := sym.val.(reflect.Value) - n.child[0].fsize = r.Type().NumOut() - n.child[0].val = r - n.child[0].kind = BasicLit - } else if sym.typ != nil && sym.typ.cat == ValueT { - n.gen = callDirectBin - n.typ = &Type{cat: ValueT} - } else { - n.val = sym.node - n.fsize = len(sym.typ.ret) - if n.fsize == 1 { - // If called func returns exactly one value, propagate its type in call node. - // Multiple return values will be handled differently through AssignX. - n.typ = sym.typ.ret[0] - } - } - } else if n.child[0].kind == SelectorSrc { - // Forward type of first returned value - // Multiple return values will be handled differently through AssignX. - if len(n.child[0].typ.ret) > 0 { - n.typ = n.child[0].typ.ret[0] - n.fsize = len(n.child[0].typ.ret) - } + } else if n.child[0].typ.cat == ValueT { + log.Println(n.index, "callBin", n.child[0].val) + n.gen = callBin } // Reserve entries in frame to store results of call scope.size += n.fsize @@ -512,11 +408,117 @@ func (interp *Interpreter) Cfg(root *Node) []*Node { } else { scope.size += n.fsize } + n.recv = n.child[0].recv - if funcDef { - // Trigger frame indirection to handle nested functions - n.action = CallF - } + /* + else if n.child[0].kind == SelectorImport { + // TODO: Should process according to child type, not kind. + n.fsize = n.child[0].fsize + var rtype reflect.Type + switch t := n.child[0].val.(type) { + case reflect.Type: + rtype = n.child[0].val.(reflect.Type) + case reflect.Value: + rtype = n.child[0].val.(reflect.Value).Type() + default: + log.Printf("unexpected type %T\n", t) + } + if rtype.NumOut() > 0 { + n.typ = &Type{cat: ValueT, rtype: rtype.Out(0)} + } + n.child[0].kind = BasicLit + for i, c := range n.child[1:] { + // Wrap function defintion so it can be called from runtime + if c.kind == FuncLit { + n.child[1+i].rval = reflect.MakeFunc(rtype.In(i), c.wrapNode) + n.child[1+i].kind = Rvalue + } else if c.ident == "nil" { + n.child[1+i].rval = reflect.New(rtype.In(i)).Elem() + n.child[1+i].kind = Rvalue + } else if c.typ != nil && c.typ.cat == FuncT { + n.child[1+i].rval = reflect.MakeFunc(rtype.In(i), c.wrapNode) + n.child[1+i].kind = Rvalue + } + } + // TODO: handle multiple return value + if len(n.child) == 2 && n.child[1].fsize > 1 { + n.gen = callBinX + } else { + n.gen = callBin + } + } else if n.child[0].kind == SelectorExpr { + if n.child[0].typ.cat == ValueT { + n.gen = callBinMethod + // TODO: handle multiple return value (_test/time2.go) + n.child[0].kind = BasicLit // Temporary hack for force value() to return n.val at run + n.typ = &Type{cat: ValueT, rtype: n.child[0].typ.rtype} + n.fsize = n.child[0].fsize + } else if n.child[0].typ.cat == PtrT && n.child[0].typ.val.cat == ValueT { + n.gen = callBinMethod + n.child[0].kind = BasicLit // Temporary hack for force value() to return n.val at run + n.fsize = n.child[0].fsize + // TODO: handle type ? + } else if n.child[0].typ.cat == SrcPkgT { + n.val = n.child[0].val + if def := n.val.(*Node); def != nil { + // Reserve as many frame entries as nb of ret values for called function + // node frame index should point to the first entry + j := len(def.child[2].child) - 1 + l := len(def.child[2].child[j].child) // Number of return values for def + if l == 1 { + // If def returns exactly one value, propagate its type in call node. + // Multiple return values will be handled differently through AssignX. + n.typ = scope.getType(def.child[2].child[j].child[0].child[0].ident) + } + n.fsize = l + } + } else { + // Get method and receiver path, store them in node static value for run + if methodDecl, ok := n.child[0].val.(*Node); ok { + // method is already resolved, use it + if len(methodDecl.child[2].child) > 1 { + // Allocate frame for method return values (if any) + n.fsize = len(methodDecl.child[2].child[1].child) + n.typ = methodDecl.typ.ret[0] + // TODO: handle multiple return values + } else { + n.fsize = 0 + } + } else { + log.Println(n.index, "unresolve call") + // method must be resolved here due to declaration after use + } + n.child[0].findex = -1 // To force reading value from node instead of frame (methods) + } + } else if sym, _, _ := scope.lookup(n.child[0].ident); sym != nil { + if sym.typ != nil && sym.typ.cat == BinT { + n.gen = callBin + n.typ = &Type{cat: ValueT} + r := sym.val.(reflect.Value) + n.child[0].fsize = r.Type().NumOut() + n.child[0].val = r + n.child[0].kind = BasicLit + } else if sym.typ != nil && sym.typ.cat == ValueT { + n.gen = callDirectBin + n.typ = &Type{cat: ValueT} + } else { + n.val = sym.node + n.fsize = len(sym.typ.ret) + if n.fsize == 1 { + // If called func returns exactly one value, propagate its type in call node. + // Multiple return values will be handled differently through AssignX. + n.typ = sym.typ.ret[0] + } + } + } else if n.child[0].kind == SelectorSrc { + // Forward type of first returned value + // Multiple return values will be handled differently through AssignX. + if len(n.child[0].typ.ret) > 0 { + n.typ = n.child[0].typ.ret[0] + n.fsize = len(n.child[0].typ.ret) + } + } + */ case CaseClause: n.findex = scope.inc(interp) @@ -656,13 +658,13 @@ func (interp *Interpreter) Cfg(root *Node) []*Node { interp.scope[pkgName].sym[funcName].kind = Func interp.scope[pkgName].sym[funcName].node = n n.types = frameTypes(n, n.flen) + genFun(n) case FuncLit: n.typ = n.child[2].typ n.val = n n.flen = scope.size + 1 scope = scope.pop() - funcDef = true n.types = frameTypes(n, n.flen) n.framepos = n.child[2].framepos @@ -682,12 +684,13 @@ func (interp *Interpreter) Cfg(root *Node) []*Node { case Ident: if n.anc.kind == File || (n.anc.kind == SelectorExpr && n.anc.child[0] != n) || (n.anc.kind == KeyValueExpr && n.anc.child[0] == n) { - // skip symbol creation/lookup for idents used as key + // Skip symbol creation/lookup for idents used as key } else if l := len(n.anc.child); n.anc.kind == Field && l > 1 && n.anc.child[l-1] != n { // Create a new local symbol for func argument n.findex = scope.inc(interp) scope.sym[n.ident] = &Symbol{index: scope.size, kind: Var} } else if sym, level, ok := scope.lookup(n.ident); ok { + // Found symbol, populate node info n.typ, n.findex, n.level = sym.typ, sym.index, level if n.findex < 0 { n.val = sym.node @@ -705,7 +708,6 @@ func (interp *Interpreter) Cfg(root *Node) []*Node { n.val = nil } } - n.recv = n } else { if n.ident == "_" || n.anc.kind == Define || n.anc.kind == DefineX || n.anc.kind == RangeStmt || n.anc.kind == ValueSpec { // Create a new local symbol for func argument or local var definition @@ -803,7 +805,7 @@ func (interp *Interpreter) Cfg(root *Node) []*Node { if n.typ == nil { log.Fatal("typ should not be nil:", n.index, n.child[0]) } - //log.Println(n.index, "selector", n.child[0].ident+"."+n.child[1].ident, n.typ.cat) + log.Println(n.index, "selector", n.child[0].ident+"."+n.child[1].ident, n.typ.cat) if n.typ.cat == ValueT { // Handle object defined in runtime if method, ok := n.typ.rtype.MethodByName(n.child[1].ident); ok { @@ -843,30 +845,19 @@ func (interp *Interpreter) Cfg(root *Node) []*Node { name := n.child[1].ident pkg := n.child[0].sym.path if s, ok := interp.binValue[pkg][name]; ok { - n.kind = SelectorImport - n.val = s - if typ := s.Type(); typ.Kind() == reflect.Func { - n.typ = &Type{cat: ValueT, rtype: typ} - n.fsize = typ.NumOut() - //} else if typ.Kind() == reflect.Ptr { - // a symbol of kind pointer must be dereferenced to access type - // n.typ = &Type{cat: ValueT, rtype: typ.Elem(), rzero: n.val.(reflect.Value).Elem()} - } else { - n.typ = &Type{cat: ValueT, rtype: typ} - n.rval = n.val.(reflect.Value) - n.kind = Rvalue + n.kind = Rvalue + n.rval = s + n.typ = &Type{cat: ValueT, rtype: s.Type()} + if s.Kind() == reflect.Func { + n.fsize = n.typ.rtype.NumOut() } n.gen = nop } else if s, ok := interp.binType[pkg][name]; ok { - //n.kind = SelectorImport n.kind = Rtype n.typ = &Type{cat: ValueT, rtype: s} n.gen = nop if s.Kind() == reflect.Func { n.fsize = s.NumOut() - //} else if typ.Kind() == reflect.Ptr { - // a symbol of kind pointer must be dereferenced to access type - // n.typ = &Type{cat: ValueT, rtype: typ.Elem(), rzero: n.val.(reflect.Value).Elem()} } } } else if n.typ.cat == ArrayT { @@ -894,9 +885,12 @@ func (interp *Interpreter) Cfg(root *Node) []*Node { } else if m, lind := n.typ.lookupMethod(n.child[1].ident); m != nil { // Handle method n.gen = nop + //n.kind = BasicLit n.val = m n.child[1].val = lind n.typ = m.typ + n.recv = n.child[0] + log.Println(n.index, "method recv", m.index, n.recv.index, lind) } else { // Handle promoted field in embedded struct if ti := n.typ.lookupField(n.child[1].ident); len(ti) > 0 { @@ -1099,6 +1093,11 @@ func valueGenerator(n *Node, i int) func(*Frame) reflect.Value { } } +func genValuePtr(n *Node) func(*Frame) reflect.Value { + v := genValue(n) + return func(f *Frame) reflect.Value { return v(f).Addr() } +} + func genValue(n *Node) func(*Frame) reflect.Value { switch n.kind { case BasicLit, FuncDecl, SelectorSrc: @@ -1139,6 +1138,35 @@ func genValue(n *Node) func(*Frame) reflect.Value { return nil } +func genFun(n *Node) { + start := n.child[3].start + framepos := n.framepos + flen := n.flen + types := n.types + nout := len(n.typ.ret) + + n.fun = func(f *Frame, in []reflect.Value, goroutine bool) []reflect.Value { + // Allocate local frame + nf := Frame{anc: f, data: make([]reflect.Value, flen)} + for i, t := range types { + if t != nil { + nf.data[i] = reflect.New(t).Elem() + } + } + // Copy input parameters from caller frame to local + for i, pos := range framepos { + nf.data[pos].Set(in[i]) + } + if goroutine { + go runCfg(start, &nf) + } else { + runCfg(start, &nf) + } + // Propagate return values to caller + return nf.data[:nout] + } +} + // Experimental, temporary & incomplete func getValue(n *Node) (int, reflect.Value, bool) { var index int diff --git a/interp/interp.go b/interp/interp.go index dd334f96..4ce5fb9c 100644 --- a/interp/interp.go +++ b/interp/interp.go @@ -29,9 +29,10 @@ type Node struct { action Action // action exec Builtin // generated function to execute gen BuiltinGenerator // generator function to produce above bltn - val interface{} // static generic value (CFG execution) - rval reflect.Value // reflection value to let runtime access interpreter (CFG) - ident string // set if node is a var or func + fun func(*Frame, []reflect.Value, bool) []reflect.Value + val interface{} // static generic value (CFG execution) + rval reflect.Value // reflection value to let runtime access interpreter (CFG) + ident string // set if node is a var or func } // Frame contains values for the current execution level diff --git a/interp/interp_test.go b/interp/interp_test.go index f1d84c60..a4f4450a 100644 --- a/interp/interp_test.go +++ b/interp/interp_test.go @@ -510,8 +510,10 @@ package main type adder func(int, int) int func genAdd(k int) adder { + println("k:", k) return func(i, j int) int { - return i + j + println("#1 k:", k) + return i + j + k } } @@ -524,7 +526,7 @@ func main() { i.Eval(src) // Output: - // 7 + // 12 } func Example_closure1() { @@ -569,7 +571,8 @@ func adder() func(int) int { func main() { pos, neg := adder(), adder() for i := 0; i < 10; i++ { - println(pos(i), neg(-2*i)) + println(pos(i), neg(0-2*i)) + } }` i := NewInterpreter(Opt{Entry: "main"}) @@ -3234,10 +3237,13 @@ type T struct { func main() { a := T{} println(a.i, a.opt.b) -}` +} +` i := NewInterpreter(Opt{Entry: "main"}) i.Eval(src) + // Output: + // 0 false } func Example_struct8() { @@ -3263,9 +3269,7 @@ func f(i int) int { return i * i } func main() { a := T{5, 7, T2{8, T3{9}}} - //println(a.f, a.g, a.T2.h, a.T2.T3.k) - //fmt.Println(a.T2) - println(a.h) + println(a.f, a.g, a.T2.h, a.T2.T3.k) } ` i := NewInterpreter(Opt{Entry: "main"}) diff --git a/interp/run.go b/interp/run.go index 2fe0c6f0..09e590fe 100644 --- a/interp/run.go +++ b/interp/run.go @@ -21,7 +21,6 @@ var builtin = [...]BuiltinGenerator{ Add: add, And: and, Call: call, - CallF: call, Case: _case, CompositeLit: arrayLit, Dec: nop, @@ -453,21 +452,64 @@ func (n *Node) wrapNode(in []reflect.Value) []reflect.Value { return result } -// FIXME: handle case where func return a boolean -func call(n *Node) { - //var recv *Node - //var rseq []int - //forkFrame := n.action == CallF // add a frame indirection for closure +func call2(n *Node) { + next := getExec(n.tnext) + value := genValue(n.child[0]) + child := n.child[1:] goroutine := n.anc.kind == GoStmt + // Compute input argument value functions var values []func(*Frame) reflect.Value - var recv *Node + for _, c := range child { + values = append(values, genValue(c)) + } + + // compute frame indexes for return values + ret := make([]int, len(n.child[0].typ.ret)) + for i := range n.child[0].typ.ret { + ret[i] = n.findex + i + } + + n.exec = func(f *Frame) Builtin { + def := value(f).Interface().(*Node) + in := make([]reflect.Value, len(child)) + if def.frame != nil { + f = def.frame + } + for i, v := range values { + in[i] = v(f) + } + out := def.fun(f, in, goroutine) + log.Println(n.index, "out:", out, ret, f.data) + // Propagate return values to caller frame + for i, r := range ret { + log.Println(n.index, out[i], r) + f.data[r] = out[i] + } + return next + } +} + +// FIXME: handle case where func return a boolean +func call(n *Node) { + goroutine := n.anc.kind == GoStmt + var values []func(*Frame) reflect.Value + //var recv *Node //var rseq []int - if n.child[0].kind == SelectorExpr && n.child[0].typ.cat != SrcPkgT && n.child[0].typ.cat != BinPkgT { - // compute method object receiver - recv = n.child[0].recv - //rseq = n.child[0].child[1].val.([]int) - values = append(values, genValue(recv)) + + //if n.child[0].kind == SelectorExpr && n.child[0].typ.cat != SrcPkgT && n.child[0].typ.cat != BinPkgT { + // // compute method object receiver + // recv = n.child[0].recv + // //rseq = n.child[0].child[1].val.([]int) + // log.Println(n.index, "recv typ", recv.typ.cat, n.child[0].typ.cat) + // //if recv.typ.cat == StructT { + // // values = append(values, genValuePtr(recv)) + // //} else { + // values = append(values, genValue(recv)) + // //} + //} + if n.child[0].recv != nil { + values = append(values, genValue(n.child[0].recv)) } next := getExec(n.tnext) @@ -488,6 +530,7 @@ func call(n *Node) { n.exec = func(f *Frame) Builtin { def := value(f).Interface().(*Node) + log.Println(n.index, "def.recv:", def) anc := f if def.frame != nil { // Get closure frame context (if any) @@ -503,6 +546,7 @@ func call(n *Node) { } // copy input parameters from caller for i, v := range values { + //log.Println(n.index, i, def.framepos[i], nf.data[def.framepos[i]].Kind(), v(f).Kind()) nf.data[def.framepos[i]].Set(v(f)) } @@ -699,10 +743,12 @@ func getIndexAddr(n *Node) { } func getPtrIndex(n *Node) { - //i := n.findex + i := n.findex //value0 := n.child[0].value //value1 := n.child[1].value next := getExec(n.tnext) + fi := n.child[1].val.(int) + value := genValue(n.child[0]) n.exec = func(f *Frame) Builtin { log.Println(n.index, "in getPtrIndex") @@ -713,6 +759,7 @@ func getPtrIndex(n *Node) { // a := value0(f).([]interface{}) // f.data[i] = a[value1(f).(int)] //} + f.data[i] = value(f).Elem().Field(fi) return next } } @@ -828,13 +875,13 @@ func getIndexMap2(n *Node) { func getFunc(n *Node) { i := n.findex next := getExec(n.tnext) + genFun(n) n.exec = func(f *Frame) Builtin { + frame := *f node := *n node.val = &node - frame := *f node.frame = &frame - //n.frame = &frame f.data[i] = reflect.ValueOf(&node) return next }