Code cleaning

This commit is contained in:
Marc Vertes
2018-11-20 17:51:43 +01:00
parent 9d466c92e3
commit 0e6d068a17
4 changed files with 30 additions and 432 deletions

View File

@@ -10,11 +10,11 @@ import (
func main() {
resp, err := http.Get("http://localhost:8080/")
if err != nil {
log.Println(err)
log.Fatal(err)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println(err)
log.Fatal(err)
}
fmt.Println(string(body))
}

View File

@@ -404,116 +404,6 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
scope.size += n.fsize
}
/*
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)
n.tnext = n.child[len(n.child)-1].start

View File

@@ -26,27 +26,26 @@ var builtin = [...]BuiltinGenerator{
Dec: nop,
Equal: equal,
GetFunc: getFunc,
//GetIndex: getIndex,
Greater: greater,
Inc: inc,
Land: land,
Lor: lor,
Lower: lower,
Mul: mul,
Negate: negate,
Not: not,
NotEqual: notEqual,
Quotient: quotient,
Range: _range,
Recv: recv,
Remain: remain,
Return: _return,
Send: send,
Slice: slice,
Slice0: slice0,
Star: deref,
Sub: sub,
TypeAssert: typeAssert,
Greater: greater,
Inc: inc,
Land: land,
Lor: lor,
Lower: lower,
Mul: mul,
Negate: negate,
Not: not,
NotEqual: notEqual,
Quotient: quotient,
Range: _range,
Recv: recv,
Remain: remain,
Return: _return,
Send: send,
Slice: slice,
Slice0: slice0,
Star: deref,
Sub: sub,
TypeAssert: typeAssert,
}
func (interp *Interpreter) run(n *Node, cf *Frame) {
@@ -65,76 +64,6 @@ func (interp *Interpreter) run(n *Node, cf *Frame) {
runCfg(n.start, f)
}
/*
func Run(def *Node, cf *Frame, recv *Node, rseq []int, args []*Node, rets []int, fork bool, goroutine bool) {
//log.Println("run", def.index, def.child[1].ident, "allocate", def.flen)
// Allocate a new Frame to store local variables
anc := cf.anc
if fork {
anc = cf
} else if def.frame != nil {
anc = def.frame
}
f := Frame{anc: anc, data: make([]reflect.Value, def.flen)}
for i, t := range def.types {
if t != nil {
f.data[i] = reflect.New(t).Elem()
}
}
// Assign receiver value, if defined (for methods)
if recv != nil {
if rseq != nil {
//f.data[def.child[0].findex] = valueSeq(recv, rseq, cf) // Promoted method
} else {
//f.data[def.child[0].findex] = recv.value(cf)
}
}
// Pass func parameters by value: copy each parameter from caller frame
// Get list of param indices built by FuncType at CFG
defargs := def.child[2].child[0]
paramIndex := defargs.val.([]int)
i := 0
//for k, arg := range args {
for _, arg := range args {
// Variadic: store remaining args in array
if i < len(defargs.child) && defargs.child[i].typ.variadic {
//variadic := make([]interface{}, len(args[k:]))
//for l, a := range args[k:] {
//variadic[l] = a.value(cf)
//}
//f.data[paramIndex[i]] = variadic
break
} else {
log.Println(def.index, i, arg.index)
//f.data[paramIndex[i]] = arg.value(cf)
i++
// Handle multiple results of a function call argmument
for j := 1; j < arg.fsize; j++ {
f.data[paramIndex[i]] = cf.data[arg.findex+j]
i++
}
}
}
// Handle empty variadic arg
//if l := len(defargs.child) - 1; len(args) <= l && defargs.child[l].typ.variadic {
// f.data[paramIndex[l]] = []interface{}{}
//}
// Execute the function body
if goroutine {
go runCfg(def.child[3].start, &f)
} else {
runCfg(def.child[3].start, &f)
// Propagate return values to caller frame
for i, ret := range rets {
cf.data[ret] = f.data[i]
}
}
}
*/
// Functions set to run during execution of CFG
// runCfg executes a node AST by walking its CFG and running node builtin at each step
@@ -266,43 +195,6 @@ func and(n *Node) {
}
}
/* Optimized version of and()
func and(n *Node) Builtin {
i := n.findex
i0, v0, r0 := getValue(n.child[0])
i1, v1, r1 := getValue(n.child[1])
value0 := n.child[0].value
//value1 := n.child[1].value
next := getExec(n.tnext)
if r0 && r1 {
return func(f *Frame) Builtin {
f.data[i].SetInt(f.data[i0].Int() & f.data[i1].Int())
return next
}
} else if r0 {
iv1 := v1.Int()
return func(f *Frame) Builtin {
//f.data[i].SetInt(f.data[i0].Int() & iv1)
f.data[i].SetInt(value0(f).Int() & iv1)
return next
}
} else if r1 {
iv0 := v0.Int()
return func(f *Frame) Builtin {
f.data[i].SetInt(iv0 & f.data[i1].Int())
return next
}
} else {
v := v0.Int() & v1.Int()
return func(f *Frame) Builtin {
f.data[i].SetInt(v)
return next
}
}
}
*/
func not(n *Node) {
i := n.findex
value := genValue(n.child[0])
@@ -384,16 +276,16 @@ func _panic(n *Node) {
// wrapNode wraps a call to an interpreter node in a function that can be called from runtime
func (n *Node) wrapNode(in []reflect.Value) []reflect.Value {
def := n.val.(*Node)
//log.Println(n.index, "in wrapNode", def.index, n.frame)
var result []reflect.Value
if n.frame == nil {
n.frame = n.interp.Frame
}
log.Println(n.index, "in wrapNode", def.index, n.frame)
frame := Frame{anc: n.frame, data: make([]reflect.Value, def.flen)}
// If fucnction is a method, set its receiver data in the frame
if len(def.child[0].child) > 0 {
//frame.data[def.child[0].findex] = n.recv.value(n.frame)
//frame.data[def.child[0].findex] = n.recv.node.value(n.frame)
}
// Unwrap input arguments from their reflect value and store them in the frame
@@ -423,30 +315,15 @@ func call(n *Node) {
goroutine := n.anc.kind == GoStmt
method := n.child[0].recv != nil
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)
// 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))
// //}
//}
// Compute method receiver value
if method {
// Compute method receiver value
values = append(values, genValueRecv(n.child[0]))
}
variadic := variadicPos(n)
next := getExec(n.tnext)
value := genValue(n.child[0])
child := n.child[1:]
// compute input argument value functions
for i, c := range child {
if isRegularCall(c) {
@@ -538,58 +415,6 @@ func call(n *Node) {
}
}
// Same as callBin, but for handling f(g()) where g returns multiple values
// FIXME: handle case where func return a boolean
//func callBinX(n *Node) {
// next := getExec(n.tnext)
// value := genValue(n.child[0])
//
// n.exec = func(f *Frame) Builtin {
// l := n.child[1].fsize
// b := n.child[1].findex
// in := make([]reflect.Value, l)
// for i := 0; i < l; i++ {
// in[i] = reflect.ValueOf(f.data[b+i])
// }
// fun := value(f)
// v := fun.Call(in)
// for i := 0; i < n.fsize; i++ {
// f.data[n.findex+i] = v[i]
// }
// return next
// }
//}
// 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
// }
//}
// FIXME: handle case where func return a boolean
// Call a function from a bin import, accessible through reflect
func callBin(n *Node) {
@@ -650,94 +475,6 @@ 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
// }
//}
// Same as callBinMethod, but for handling f(g()) where g returns multiple values
// FIXME: handle case where func return a boolean
//func callBinMethodX(n *Node) Builtin {
// next := getExec(n.tnext)
//
// return func(f *Frame) Builtin {
// //fun := n.child[0].value(f).(reflect.Value)
// fun := n.child[0].value(f)
// l := n.child[1].fsize
// b := n.child[1].findex
// in := make([]reflect.Value, l+1)
// in[0] = reflect.ValueOf(n.child[0].child[0].value(f))
// for i := 0; i < l; i++ {
// in[i+1] = reflect.ValueOf(f.data[b+i])
// }
// v := fun.Call(in)
// for i := 0; i < n.fsize; i++ {
// f.data[n.findex+i] = v[i]
// }
// return next
// }
//}
//func getPtrIndexAddr(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 getPtrIndexAddr")
// //a := (*value0(f).(*interface{})).([]interface{})
// //f.data[i] = &a[value1(f).(int)]
// return next
// }
//}
func getPtrIndex(n *Node) {
i := n.findex
next := getExec(n.tnext)
@@ -762,18 +499,6 @@ func getIndexBinMethod(n *Node) {
}
}
//func getIndex(n *Node) {
// i := n.findex
// next := getExec(n.tnext)
// fi := n.child[1].val.(int)
// value := genValue(n.child[0])
//
// n.exec = func(f *Frame) Builtin {
// f.data[i] = value(f).Field(fi)
// return next
// }
//}
func getIndexArray(n *Node) {
i := n.findex
next := getExec(n.tnext)
@@ -848,32 +573,12 @@ func getPtrIndexSeq(n *Node) {
next := getExec(n.tnext)
n.exec = func(f *Frame) Builtin {
log.Println(n.index, "getPtrIndexSeq", value(f).Type())
f.data[i] = value(f).Elem().FieldByIndex(fi)
return next
}
}
//func getPtrIndexSeq(n *Node) {
// i := n.findex
// value := genValue(n.child[0])
// index := n.child[1].val.([]int)
// next := getExec(n.tnext)
//
// n.exec = func(f *Frame) Builtin {
// f.data[i] = value(f).Elem().FieldByIndex(index)
// return next
// }
//}
//func valueSeq(n *Node, seq []int, f *Frame) interface{} {
// a := f.data[n.findex].([]interface{})
// l := len(seq) - 1
// for _, i := range seq[:l] {
// a = a[i].([]interface{})
// }
// return a[seq[l]]
//}
func mul(n *Node) {
i := n.findex
value0 := genValue(n.child[0])

View File

@@ -449,6 +449,9 @@ func (t *Type) TypeOf() reflect.Type {
}
return reflect.FuncOf(in, out, false)
case InterfaceT:
return nil
case MapT:
return reflect.MapOf(t.key.TypeOf(), t.val.TypeOf())