Fix assignement of function call, code clean
This commit is contained in:
@@ -205,62 +205,53 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
|
||||
|
||||
case Define, AssignStmt:
|
||||
wireChild(n)
|
||||
name := n.child[0].ident
|
||||
sym, level, _ := scope.lookup(name)
|
||||
dest, src := n.child[0], n.child[1]
|
||||
sym, level, _ := scope.lookup(dest.ident)
|
||||
if n.kind == Define {
|
||||
n.child[0].val = n.child[1].val
|
||||
n.child[0].typ = n.child[1].typ
|
||||
n.child[0].recv = n.child[1].recv
|
||||
n.child[0].findex = sym.index
|
||||
if n.child[1].action == GetFunc {
|
||||
dest.val = src.val
|
||||
dest.typ = src.typ
|
||||
dest.recv = src.recv
|
||||
dest.findex = sym.index
|
||||
if src.action == GetFunc {
|
||||
sym.index = -1
|
||||
sym.node = n.child[1]
|
||||
sym.node = src
|
||||
}
|
||||
if n.child[1].kind == BasicLit {
|
||||
sym.val = n.child[1].val
|
||||
} else if n.child[1].kind == CallExpr {
|
||||
if src.kind == BasicLit {
|
||||
sym.val = src.val
|
||||
} else if isRegularCall(src) || isBinCall(src) {
|
||||
// propagate call return value type
|
||||
n.child[0].typ = getReturnedType(n.child[1].child[0])
|
||||
sym.typ = n.child[0].typ
|
||||
dest.typ = getReturnedType(src.child[0])
|
||||
sym.typ = dest.typ
|
||||
}
|
||||
}
|
||||
n.findex = n.child[0].findex
|
||||
n.val = n.child[0].val
|
||||
n.findex = dest.findex
|
||||
n.val = dest.val
|
||||
// Propagate type
|
||||
// TODO: Check that existing destination type matches source type
|
||||
if n.child[1].action == Recv {
|
||||
// Assign by reading from a receiving channel
|
||||
n.gen = nop
|
||||
n.child[1].findex = n.child[0].findex // Set recv address to LHS
|
||||
n.child[0].typ = n.child[1].typ.val
|
||||
src.findex = dest.findex // Set recv address to LHS
|
||||
dest.typ = src.typ.val
|
||||
} else if n.child[1].action == CompositeLit {
|
||||
n.gen = nop
|
||||
n.child[1].findex = n.child[0].findex
|
||||
n.child[1].level = level
|
||||
src.findex = dest.findex
|
||||
src.level = level
|
||||
}
|
||||
n.typ = n.child[0].typ
|
||||
n.typ = dest.typ
|
||||
if sym != nil {
|
||||
sym.typ = n.typ
|
||||
sym.recv = n.child[1].recv
|
||||
sym.recv = src.recv
|
||||
}
|
||||
n.level = level
|
||||
//log.Println(n.index, "assign", n.child[0].ident, n.typ.cat, n.findex, n.level)
|
||||
//log.Println(n.index, "assign", dest.ident, n.typ.cat, n.findex, n.level)
|
||||
// If LHS is an indirection, get reference instead of value, to allow setting
|
||||
if n.child[0].action == GetIndex {
|
||||
if n.child[0].child[0].typ.cat == MapT {
|
||||
if dest.action == GetIndex {
|
||||
if dest.child[0].typ.cat == MapT {
|
||||
n.gen = assignMap
|
||||
n.child[0].gen = nop // skip getIndexMap
|
||||
dest.gen = nop // skip getIndexMap
|
||||
}
|
||||
}
|
||||
//} else if n.child[0].child[0].typ.cat == PtrT {
|
||||
// // Handle the case where the receiver is a pointer to an object
|
||||
// n.child[0].gen = getPtrIndexAddr
|
||||
// n.gen = assignPtrField
|
||||
//} else if n.child[0].action == Star {
|
||||
// n.findex = n.child[0].child[0].findex
|
||||
// n.level = n.child[0].child[0].level
|
||||
// n.gen = indirectAssign
|
||||
// }
|
||||
if n.anc.kind == ConstDecl {
|
||||
iotaValue++
|
||||
}
|
||||
@@ -733,7 +724,6 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
|
||||
n.kind = Rvalue
|
||||
}
|
||||
n.typ = sym.typ
|
||||
log.Println(n.index, "ident", n.ident, n.typ.rtype)
|
||||
if n.typ.rtype.Kind() == reflect.Func {
|
||||
n.fsize = n.typ.rtype.NumOut()
|
||||
}
|
||||
@@ -1090,11 +1080,12 @@ func isBuiltinCall(n *Node) bool {
|
||||
}
|
||||
|
||||
func isBinCall(n *Node) bool {
|
||||
return n.kind == CallExpr && n.child[0].typ.cat == ValueT
|
||||
return n.kind == CallExpr && n.child[0].typ.cat == ValueT &&
|
||||
n.child[0].typ.rtype.Kind() == reflect.Func
|
||||
}
|
||||
|
||||
func isRegularCall(n *Node) bool {
|
||||
return n.kind == CallExpr && n.child[0].typ.cat != ValueT && (n.child[0].sym == nil || n.child[0].sym.kind != Bltn)
|
||||
return n.kind == CallExpr && n.child[0].typ.cat == FuncT
|
||||
}
|
||||
|
||||
func variadicPos(n *Node) int {
|
||||
@@ -1295,7 +1286,10 @@ func getValue(n *Node) (int, reflect.Value, bool) {
|
||||
}
|
||||
|
||||
func getReturnedType(n *Node) *Type {
|
||||
if n.typ.cat == ValueT {
|
||||
switch n.typ.cat {
|
||||
case BuiltinT:
|
||||
return n.anc.typ
|
||||
case ValueT:
|
||||
return &Type{cat: ValueT, rtype: n.typ.rtype.Out(0)}
|
||||
}
|
||||
return n.typ.ret[0]
|
||||
|
||||
286
interp/run.go
286
interp/run.go
@@ -211,19 +211,6 @@ func assignX(n *Node) {
|
||||
}
|
||||
}
|
||||
|
||||
//func indirectAssign(n *Node) {
|
||||
// i := n.findex
|
||||
// value := genValue(n.child[1])
|
||||
// next := getExec(n.tnext)
|
||||
//
|
||||
// n.exec = func(f *Frame) Builtin {
|
||||
// //*(f.data[i].(*interface{})) = value(f)
|
||||
// log.Println(n.index, "in IndirectAssign")
|
||||
// f.data[i].Elem().Set(value(f))
|
||||
// return next
|
||||
// }
|
||||
//}
|
||||
|
||||
// assign implements single value assignement
|
||||
func assign(n *Node) {
|
||||
value := genValue(n)
|
||||
@@ -255,31 +242,6 @@ func assign0(n *Node) {
|
||||
}
|
||||
}
|
||||
|
||||
//func assignField(n *Node) Builtin {
|
||||
// i := n.findex
|
||||
// value := genValue(n.child[1])
|
||||
// next := getExec(n.tnext)
|
||||
//
|
||||
// log.Println(n.index, "gen assignField")
|
||||
// return func(f *Frame) Builtin {
|
||||
// //(*f.data[i].(*interface{})) = value(f)
|
||||
// f.data[i].Set(value(f))
|
||||
// log.Println(n.index, "in assignField", f.data[i], value(f), i, f.data, f.data[2], f.data[3])
|
||||
// return next
|
||||
// }
|
||||
//}
|
||||
|
||||
//func assignPtrField(n *Node) {
|
||||
// //i := n.findex
|
||||
// //value := n.child[1].value
|
||||
// next := getExec(n.tnext)
|
||||
//
|
||||
// n.exec = func(f *Frame) Builtin {
|
||||
// //(*f.data[i].(*interface{})) = value(f)
|
||||
// return next
|
||||
// }
|
||||
//}
|
||||
|
||||
func assignMap(n *Node) {
|
||||
value := genValue(n.child[0].child[0]) // map
|
||||
value0 := genValue(n.child[0].child[1]) // key
|
||||
@@ -458,44 +420,6 @@ func (n *Node) wrapNode(in []reflect.Value) []reflect.Value {
|
||||
return result
|
||||
}
|
||||
|
||||
//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
|
||||
// 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
|
||||
@@ -629,33 +553,33 @@ func call(n *Node) {
|
||||
|
||||
// Call a function from a bin import, accessible through reflect
|
||||
// FIXME: handle case where func return a boolean
|
||||
func callDirectBin(n *Node) {
|
||||
next := getExec(n.tnext)
|
||||
child := n.child[1:]
|
||||
value := genValue(n.child[0])
|
||||
values := make([]func(*Frame) reflect.Value, len(child))
|
||||
for i, c := range child {
|
||||
values[i] = genValue(c)
|
||||
}
|
||||
|
||||
n.exec = func(f *Frame) Builtin {
|
||||
in := make([]reflect.Value, len(n.child)-1)
|
||||
for i, v := range values {
|
||||
if child[i].kind == Rvalue {
|
||||
in[i] = v(f)
|
||||
child[i].frame = f
|
||||
} else {
|
||||
in[i] = v(f)
|
||||
}
|
||||
}
|
||||
fun := value(f)
|
||||
v := fun.Call(in)
|
||||
for i := 0; i < n.fsize; i++ {
|
||||
f.data[n.findex+i] = v[i]
|
||||
}
|
||||
return next
|
||||
}
|
||||
}
|
||||
//func callDirectBin(n *Node) {
|
||||
// next := getExec(n.tnext)
|
||||
// child := n.child[1:]
|
||||
// value := genValue(n.child[0])
|
||||
// values := make([]func(*Frame) reflect.Value, len(child))
|
||||
// for i, c := range child {
|
||||
// values[i] = genValue(c)
|
||||
// }
|
||||
//
|
||||
// n.exec = func(f *Frame) Builtin {
|
||||
// in := make([]reflect.Value, len(n.child)-1)
|
||||
// for i, v := range values {
|
||||
// if child[i].kind == Rvalue {
|
||||
// in[i] = v(f)
|
||||
// child[i].frame = f
|
||||
// } else {
|
||||
// in[i] = v(f)
|
||||
// }
|
||||
// }
|
||||
// fun := value(f)
|
||||
// v := fun.Call(in)
|
||||
// for i := 0; i < n.fsize; i++ {
|
||||
// f.data[n.findex+i] = v[i]
|
||||
// }
|
||||
// return next
|
||||
// }
|
||||
//}
|
||||
|
||||
// FIXME: handle case where func return a boolean
|
||||
// Call a function from a bin import, accessible through reflect
|
||||
@@ -695,53 +619,53 @@ func callBin(n *Node) {
|
||||
// Call a method defined by an interface type on an object returned by a bin import, through reflect.
|
||||
// In that case, the method func value can be resolved only at execution from the actual value
|
||||
// of node, not during CFG.
|
||||
func callBinInterfaceMethod(n *Node, f *Frame) {}
|
||||
|
||||
// Call a method on an object returned by a bin import function, through reflect
|
||||
// FIXME: handle case where func return a boolean
|
||||
func callBinMethod(n *Node) {
|
||||
next := getExec(n.tnext)
|
||||
child := n.child[1:]
|
||||
values := make([]func(*Frame) reflect.Value, len(child))
|
||||
for i, c := range child {
|
||||
values[i] = genValue(c)
|
||||
}
|
||||
rvalue := genValue(n.child[0].child[0])
|
||||
|
||||
log.Println(n.index, "in callBinMethod")
|
||||
n.exec = func(f *Frame) Builtin {
|
||||
fun := n.child[0].rval
|
||||
in := make([]reflect.Value, len(n.child))
|
||||
//val := n.child[0].child[0].value(f)
|
||||
//switch val.(type) {
|
||||
//case reflect.Value:
|
||||
// in[0] = val.(reflect.Value)
|
||||
//default:
|
||||
// in[0] = reflect.ValueOf(val)
|
||||
//}
|
||||
in[0] = rvalue(f)
|
||||
for i, c := range n.child[1:] {
|
||||
if c.kind == Rvalue {
|
||||
//in[i+1] = c.value(f).(reflect.Value)
|
||||
in[i+1] = values[i](f)
|
||||
c.frame = f
|
||||
} else {
|
||||
//in[i+1] = reflect.ValueOf(c.value(f))
|
||||
in[i+1] = values[i](f)
|
||||
}
|
||||
}
|
||||
//log.Println(n.index, "in callBinMethod", n.ident, in)
|
||||
if !fun.IsValid() {
|
||||
fun = in[0].MethodByName(n.child[0].child[1].ident)
|
||||
in = in[1:]
|
||||
}
|
||||
v := fun.Call(in)
|
||||
for i := 0; i < n.fsize; i++ {
|
||||
f.data[n.findex+i] = v[i]
|
||||
}
|
||||
return next
|
||||
}
|
||||
}
|
||||
//func callBinInterfaceMethod(n *Node, f *Frame) {}
|
||||
//
|
||||
//// Call a method on an object returned by a bin import function, through reflect
|
||||
//// FIXME: handle case where func return a boolean
|
||||
//func callBinMethod(n *Node) {
|
||||
// next := getExec(n.tnext)
|
||||
// child := n.child[1:]
|
||||
// values := make([]func(*Frame) reflect.Value, len(child))
|
||||
// for i, c := range child {
|
||||
// values[i] = genValue(c)
|
||||
// }
|
||||
// rvalue := genValue(n.child[0].child[0])
|
||||
//
|
||||
// log.Println(n.index, "in callBinMethod")
|
||||
// n.exec = func(f *Frame) Builtin {
|
||||
// fun := n.child[0].rval
|
||||
// in := make([]reflect.Value, len(n.child))
|
||||
// //val := n.child[0].child[0].value(f)
|
||||
// //switch val.(type) {
|
||||
// //case reflect.Value:
|
||||
// // in[0] = val.(reflect.Value)
|
||||
// //default:
|
||||
// // in[0] = reflect.ValueOf(val)
|
||||
// //}
|
||||
// in[0] = rvalue(f)
|
||||
// for i, c := range n.child[1:] {
|
||||
// if c.kind == Rvalue {
|
||||
// //in[i+1] = c.value(f).(reflect.Value)
|
||||
// in[i+1] = values[i](f)
|
||||
// c.frame = f
|
||||
// } else {
|
||||
// //in[i+1] = reflect.ValueOf(c.value(f))
|
||||
// in[i+1] = values[i](f)
|
||||
// }
|
||||
// }
|
||||
// //log.Println(n.index, "in callBinMethod", n.ident, in)
|
||||
// if !fun.IsValid() {
|
||||
// fun = in[0].MethodByName(n.child[0].child[1].ident)
|
||||
// in = in[1:]
|
||||
// }
|
||||
// v := fun.Call(in)
|
||||
// for i := 0; i < n.fsize; i++ {
|
||||
// f.data[n.findex+i] = v[i]
|
||||
// }
|
||||
// return next
|
||||
// }
|
||||
//}
|
||||
|
||||
// Same as callBinMethod, but for handling f(g()) where g returns multiple values
|
||||
// FIXME: handle case where func return a boolean
|
||||
@@ -780,36 +704,13 @@ func callBinMethod(n *Node) {
|
||||
// }
|
||||
//}
|
||||
|
||||
func getIndexAddr(n *Node) {
|
||||
//i := n.findex
|
||||
//value0 := n.child[0].value
|
||||
//value1 := n.child[1].value
|
||||
next := getExec(n.tnext)
|
||||
|
||||
n.exec = func(f *Frame) Builtin {
|
||||
log.Println(n.index, "in getIndexAddr")
|
||||
//a := value0(f).([]interface{})
|
||||
//f.data[i] = &a[value1(f).(int)]
|
||||
return next
|
||||
}
|
||||
}
|
||||
|
||||
func getPtrIndex(n *Node) {
|
||||
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 {
|
||||
// if error, fallback to getIndex, to make receiver methods work both with pointers and objects
|
||||
//if a, ok := value0(f).(*interface{}); ok {
|
||||
// f.data[i] = (*a).([]interface{})[value1(f).(int)]
|
||||
//} else {
|
||||
// a := value0(f).([]interface{})
|
||||
// f.data[i] = a[value1(f).(int)]
|
||||
//}
|
||||
f.data[i] = value(f).Elem().Field(fi)
|
||||
return next
|
||||
}
|
||||
@@ -841,34 +742,6 @@ func getIndexBinMethod(n *Node) {
|
||||
}
|
||||
}
|
||||
|
||||
func getIndexBin(n *Node) {
|
||||
i := n.findex
|
||||
fi := n.val.([]int)
|
||||
value := genValue(n.child[0])
|
||||
next := getExec(n.tnext)
|
||||
|
||||
n.exec = func(f *Frame) Builtin {
|
||||
a := reflect.ValueOf(value(f))
|
||||
f.data[i] = a.FieldByIndex(fi)
|
||||
return next
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func getIndex(n *Node) Builtin {
|
||||
//i := n.findex
|
||||
//value0 := n.child[0].value
|
||||
//value1 := n.child[1].value
|
||||
next := getExec(n.tnext)
|
||||
|
||||
return func(f *Frame) Builtin {
|
||||
//a := value0(f).([]interface{})
|
||||
//f.data[i] = a[value1(f).(int)]
|
||||
return next
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func getIndex(n *Node) {
|
||||
i := n.findex
|
||||
next := getExec(n.tnext)
|
||||
@@ -1074,17 +947,6 @@ func notEqual(n *Node) {
|
||||
}
|
||||
}
|
||||
|
||||
func indirectInc(n *Node) {
|
||||
//i := n.findex
|
||||
//value := n.child[0].value
|
||||
next := getExec(n.tnext)
|
||||
|
||||
n.exec = func(f *Frame) Builtin {
|
||||
//*(f.data[i].(*interface{})) = value(f).(int) + 1
|
||||
return next
|
||||
}
|
||||
}
|
||||
|
||||
func inc(n *Node) {
|
||||
value := genValue(n)
|
||||
value0 := genValue(n.child[0])
|
||||
|
||||
Reference in New Issue
Block a user