Code cleaning
This commit is contained in:
@@ -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))
|
||||
}
|
||||
|
||||
110
interp/cfg.go
110
interp/cfg.go
@@ -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
|
||||
|
||||
345
interp/run.go
345
interp/run.go
@@ -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])
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user