WIP handle runtime values as reflect.Value instead of interface{}

This commit is contained in:
Marc Vertes
2018-10-04 11:46:07 +02:00
parent 69d81e61ae
commit e1221600fd
5 changed files with 443 additions and 344 deletions

View File

@@ -1,6 +1,6 @@
package main
func myprint(i int) { println(i) }
//func myprint(i int) { println(i) }
func main() {
for a := 0; a < 20000000; a++ {

12
_test/l5.go Normal file
View File

@@ -0,0 +1,12 @@
package main
//func myprint(i int) { println(i) }
func main() {
for a := 0; a < 20000000; {
if a&0x8ffff == 0x80000 {
println(a)
}
a = a + 1
}
}

View File

@@ -164,11 +164,11 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
scope = scope.push(0)
case FuncDecl, FuncLit:
// Add a frame indirection level as we enter in a func
scope = scope.push(1)
if n.child[1].ident == "init" {
initNodes = append(initNodes, n)
}
// Add a frame indirection level as we enter in a func
scope = scope.push(1)
if len(n.child[2].child) == 2 {
// allocate entries for return values at start of frame
scope.size += len(n.child[2].child[1].child)
@@ -307,16 +307,22 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
case BinaryExpr:
wireChild(n)
n.findex = scope.inc(interp)
n.typ = n.child[0].typ
nilSym := interp.universe.sym["nil"]
if n.action == NotEqual {
switch n.action {
case NotEqual:
n.typ = scope.getType("bool")
if n.child[0].sym == nilSym || n.child[1].sym == nilSym {
n.run = isNotNil
}
} else if n.action == Equal {
case Equal:
n.typ = scope.getType("bool")
if n.child[0].sym == nilSym || n.child[1].sym == nilSym {
n.run = isNil
}
case Greater, Lower:
n.typ = scope.getType("bool")
default:
n.typ = n.child[0].typ
}
case IndexExpr:
@@ -930,7 +936,7 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
root.Walk(func(n *Node) bool {
n.value = genValue(n)
n.pvalue = genPvalue(n)
//n.pvalue = genPvalue(n)
return true
}, nil)
@@ -941,6 +947,7 @@ func genRun(n *Node) {
n.Walk(func(n *Node) bool {
if n.kind == FuncType && len(n.anc.child) == 4 {
getExec(n.anc.child[3].start)
//frameTypes(n.anc)
}
if n.kind == VarDecl || n.kind == ConstDecl {
getExec(n.start)
@@ -1051,16 +1058,16 @@ func getExec(n *Node) Builtin {
return get(n)
}
func valueGenerator(n *Node, i int) func(*Frame) interface{} {
func valueGenerator(n *Node, i int) func(*Frame) reflect.Value {
switch n.level {
case 0:
return func(f *Frame) interface{} { return f.data[i] }
return func(f *Frame) reflect.Value { return f.data[i] }
case 1:
return func(f *Frame) interface{} { return f.anc.data[i] }
return func(f *Frame) reflect.Value { return f.anc.data[i] }
case 2:
return func(f *Frame) interface{} { return f.anc.anc.data[i] }
return func(f *Frame) reflect.Value { return f.anc.anc.data[i] }
default:
return func(f *Frame) interface{} {
return func(f *Frame) reflect.Value {
for level := n.level; level > 0; level-- {
f = f.anc
}
@@ -1069,14 +1076,15 @@ func valueGenerator(n *Node, i int) func(*Frame) interface{} {
}
}
func genValue(n *Node) func(*Frame) interface{} {
func genValue(n *Node) func(*Frame) reflect.Value {
switch n.kind {
case BasicLit, FuncDecl, SelectorSrc:
v := n.val
return func(f *Frame) interface{} { return v }
//v := n.val
v := reflect.ValueOf(n.val)
return func(f *Frame) reflect.Value { return v }
case Rvalue:
v := n.rval
return func(f *Frame) interface{} { return v }
return func(f *Frame) reflect.Value { return v }
default:
if n.sym != nil {
if n.sym.index < 0 {
@@ -1084,21 +1092,41 @@ func genValue(n *Node) func(*Frame) interface{} {
}
i := n.sym.index
if n.sym.global {
return func(f *Frame) interface{} {
return func(f *Frame) reflect.Value {
return n.interp.Frame.data[i]
}
}
return valueGenerator(n, i)
}
if n.findex < 0 {
v := n.val
return func(f *Frame) interface{} { return v }
//v := n.val
v := reflect.ValueOf(n.val)
return func(f *Frame) reflect.Value { return v }
}
return valueGenerator(n, n.findex)
}
return nil
}
func frameTypes(node *Node) []*Type {
ft := make([]*Type, node.flen)
node.child[3].Walk(func(n *Node) bool {
if n.typ == nil || n.level > 0 || n.kind == BasicLit || n.kind == SelectorSrc {
return true
}
if ft[n.findex] == nil || true {
ft[n.findex] = n.typ
} else {
// TODO: Check that type is identical
}
return true
}, nil)
return ft
}
/*
func pvalueGenerator(n *Node, i int) func(*Frame) *interface{} {
switch n.level {
case 0:
@@ -1141,3 +1169,4 @@ func genPvalue(n *Node) func(*Frame) *interface{} {
}
return nil
}
*/

View File

@@ -8,36 +8,37 @@ import (
// Node structure for AST and CFG
type Node struct {
child []*Node // child subtrees (AST)
anc *Node // ancestor (AST)
start *Node // entry point in subtree (CFG)
tnext *Node // true branch successor (CFG)
fnext *Node // false branch successor (CFG)
interp *Interpreter // interpreter context
index int // node index (dot display)
findex int // index of value in frame or frame size (func def, type def)
fsize int // number of entries in frame (call expressions)
flen int // frame length (function definition)
level int // number of frame indirections to access value
kind Kind // kind of node
sym *Symbol // associated symbol
typ *Type // type of value in frame, or nil
recv *Node // method receiver node for call, or nil
frame *Frame // frame pointer, only used for script callbacks from runtime (wrapNode)
action Action // action
value func(f *Frame) interface{} // generated function which returns node value during execution
pvalue func(f *Frame) *interface{} // generated function which returns pointer on node value during execution
exec Builtin // generated function to execute
run BuiltinGenerator // generator function to produce above exec
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
child []*Node // child subtrees (AST)
anc *Node // ancestor (AST)
start *Node // entry point in subtree (CFG)
tnext *Node // true branch successor (CFG)
fnext *Node // false branch successor (CFG)
interp *Interpreter // interpreter context
index int // node index (dot display)
findex int // index of value in frame or frame size (func def, type def)
fsize int // number of entries in frame (call expressions)
flen int // frame length (function definition)
level int // number of frame indirections to access value
kind Kind // kind of node
sym *Symbol // associated symbol
typ *Type // type of value in frame, or nil
recv *Node // method receiver node for call, or nil
frame *Frame // frame pointer, only used for script callbacks from runtime (wrapNode)
action Action // action
//value func(f *Frame) interface{} // generated function which returns node value during execution
value func(f *Frame) reflect.Value // generated function which returns node value during execution
//pvalue func(f *Frame) *interface{} // generated function which returns pointer on node value during execution
exec Builtin // generated function to execute
run BuiltinGenerator // generator function to produce above exec
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
type Frame struct {
anc *Frame // ancestor frame (global space)
data []interface{} // values
anc *Frame // ancestor frame (global space)
data []reflect.Value // values
}
// BinMap stores executable symbols indexed by name
@@ -102,7 +103,7 @@ func NewInterpreter(opt Opt) *Interpreter {
Expval: make(PkgValueMap),
binValue: LibValueMap(stdlib.Value),
binType: LibTypeMap(stdlib.Type),
Frame: &Frame{data: []interface{}{}},
Frame: &Frame{data: []reflect.Value{}},
}
}
@@ -150,7 +151,7 @@ func initUniverse() *Scope {
}
func (i *Interpreter) resizeFrame() {
f := &Frame{data: make([]interface{}, i.fsize)}
f := &Frame{data: make([]reflect.Value, i.fsize)}
copy(f.data, i.Frame.data)
i.Frame = f
}

File diff suppressed because it is too large Load Diff