Fix init of zero objects

This commit is contained in:
Marc Vertes
2018-11-28 17:27:46 +01:00
parent 3bd853988b
commit c8fa453ce4
6 changed files with 60 additions and 57 deletions

11
_test/a19.go Normal file
View File

@@ -0,0 +1,11 @@
package main
func main() {
var buf [bsize]byte
println(len(buf))
}
const bsize = 10
// Output:
// 10

View File

@@ -179,7 +179,6 @@ const (
Addr
Assign
AssignX
Assign0
Add
And
Call
@@ -216,7 +215,6 @@ var actions = [...]string{
Addr: "&",
Assign: "=",
AssignX: "X=",
Assign0: "0=",
Add: "+",
And: "&",
Call: "call",
@@ -622,8 +620,8 @@ func (interp *Interpreter) Ast(src, name string) (string, *Node) {
st.push(addChild(&root, anc, kind, action))
case *ast.ValueSpec:
var kind Kind
var action Action
kind := ValueSpec
action := Nop
if a.Values != nil {
if len(a.Names) == 1 && len(a.Values) > 1 {
if anc.kind == ConstDecl || anc.kind == VarDecl {
@@ -646,8 +644,6 @@ func (interp *Interpreter) Ast(src, name string) (string, *Node) {
}
} else if anc.kind == ConstDecl {
kind, action = Define, Assign
} else {
kind, action = ValueSpec, Assign0
}
st.push(addChild(&root, anc, kind, action))

View File

@@ -204,9 +204,6 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
case If0, If1, If2, If3:
scope = scope.push(0)
//case RangeStmt:
// log.Println(n.index, "in RangeStmt", n.child[2].typ)
case Switch0:
// Make sure default clause is in last position
c := n.child[1].child
@@ -490,7 +487,6 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
wireChild(n)
scope = scope.pop()
n.fsize = scope.size + 1
n.types = frameTypes(n, n.fsize)
case For0: // for {}
body := n.child[0]
@@ -575,14 +571,12 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
interp.scope[pkgName].sym[funcName].typ = n.typ
interp.scope[pkgName].sym[funcName].kind = Func
interp.scope[pkgName].sym[funcName].node = n
n.types = frameTypes(n, n.flen)
case FuncLit:
n.typ = n.child[2].typ
n.val = n
n.flen = scope.size + 1
scope = scope.pop()
n.types = frameTypes(n, n.flen)
n.framepos = n.child[2].framepos
case FuncType:
@@ -897,10 +891,16 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
func genRun(n *Node) {
n.Walk(func(n *Node) bool {
if n.kind == FuncType && len(n.anc.child) == 4 {
setExec(n.anc.child[3].start)
}
if n.kind == VarDecl || n.kind == ConstDecl {
switch n.kind {
case File:
n.types = frameTypes(n, n.fsize)
case FuncDecl, FuncLit:
n.types = frameTypes(n, n.flen)
case FuncType:
if len(n.anc.child) == 4 {
setExec(n.anc.child[3].start)
}
case ConstDecl, VarDecl:
setExec(n.start)
return false
}
@@ -1113,11 +1113,6 @@ func genValueRecv(n *Node) 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:
@@ -1172,7 +1167,7 @@ func getReturnedType(n *Node) *Type {
return n.typ.ret[0]
}
// frameTypes return a slice of frame types for FuncDecl or FuncLit nodes
// frameTypes returns a slice of frame types for FuncDecl or FuncLit nodes
func frameTypes(node *Node, size int) []reflect.Type {
ft := make([]reflect.Type, size)
@@ -1184,6 +1179,9 @@ func frameTypes(node *Node, size int) []reflect.Type {
return true
}
if ft[n.findex] == nil {
if n.typ.incomplete {
n.typ = n.typ.finalize()
}
if n.typ.cat == FuncT {
ft[n.findex] = reflect.TypeOf(n)
} else {

View File

@@ -222,6 +222,24 @@ func main() {
// 4
}
func Example_a19() {
src := `
package main
func main() {
var buf [bsize]byte
println(len(buf))
}
const bsize = 10
`
i := NewInterpreter(Opt{Entry: "main"}, "a19.go")
i.Eval(src)
// Output:
// 10
}
func Example_a2() {
src := `
package main

View File

@@ -16,7 +16,6 @@ var builtin = [...]BuiltinGenerator{
Addr: addr,
Assign: assign,
AssignX: assignX,
Assign0: assign0,
Add: add,
And: and,
Call: call,
@@ -135,25 +134,6 @@ func assign(n *Node) {
}
}
// assign0 implements assignement of zero value, as in a var statement
func assign0(n *Node) {
l := len(n.child) - 1
zero := n.typ.zero
s := n.child[:l]
next := getExec(n.tnext)
values := make([]func(*Frame) reflect.Value, l)
for i, c := range s {
values[i] = genValue(c)
}
n.exec = func(f *Frame) Builtin {
for _, v := range values {
v(f).Set(zero())
}
return next
}
}
func assignMap(n *Node) {
value := genValue(n.child[0].child[0]) // map
value0 := genValue(n.child[0].child[1]) // key
@@ -886,7 +866,7 @@ func arrayLit(n *Node) {
value := valueGenerator(n, n.findex)
next := getExec(n.tnext)
child := n.child[1:]
zero := n.typ.zero
a := n.typ.zero()
values := make([]func(*Frame) reflect.Value, len(child))
for i, c := range child {
convertLiteralValue(c, n.typ.val.TypeOf())
@@ -896,7 +876,6 @@ func arrayLit(n *Node) {
if n.typ.size > 0 {
// Fixed size array
n.exec = func(f *Frame) Builtin {
a := zero()
for i, v := range values {
a.Index(i).Set(v(f))
}
@@ -906,7 +885,6 @@ func arrayLit(n *Node) {
} else {
// Slice
n.exec = func(f *Frame) Builtin {
a := zero()
for _, v := range values {
a = reflect.Append(a, v(f))
}
@@ -945,6 +923,7 @@ func compositeLit(n *Node) {
value := valueGenerator(n, n.findex)
next := getExec(n.tnext)
child := n.child[1:]
a := n.typ.zero()
values := make([]func(*Frame) reflect.Value, len(child))
for i, c := range child {
convertLiteralValue(c, n.typ.field[i].typ.TypeOf())
@@ -952,7 +931,6 @@ func compositeLit(n *Node) {
}
n.exec = func(f *Frame) Builtin {
a := n.typ.zero()
for i, v := range values {
a.Field(i).Set(v(f))
}
@@ -967,13 +945,13 @@ func compositeSparse(n *Node) {
next := getExec(n.tnext)
child := n.child[1:]
values := make(map[int]func(*Frame) reflect.Value)
a := n.typ.zero()
for _, c := range child {
convertLiteralValue(c.child[1], n.typ.field[c.findex].typ.TypeOf())
values[c.findex] = genValue(c.child[1])
}
n.exec = func(f *Frame) Builtin {
a := n.typ.zero()
for i, v := range values {
a.Field(i).Set(v(f))
}

View File

@@ -116,7 +116,7 @@ type Type struct {
scope *Scope // type declaration scope (in case of re-parse incomplete type)
}
// return a type definition for the corresponding AST subtree
// nodeType returns a type definition for the corresponding AST subtree
func nodeType(interp *Interpreter, scope *Scope, n *Node) *Type {
if n.typ != nil && !n.typ.incomplete {
return n.typ
@@ -301,17 +301,21 @@ func init() {
zeroValues[UintptrT] = reflect.ValueOf(uintptr(0))
}
// zero instantiates and return a zero value object for the given type during execution
func (t *Type) zero() reflect.Value {
// if type is incomplete, re-parse it.
func (t *Type) finalize() *Type {
if t.incomplete {
// Re-parse type at execution in lazy mode. Hopefully missing info is now present
t = nodeType(t.node.interp, t.scope, t.node)
t.node.typ = t
if t.incomplete {
log.Panicln("incomplete type", t.node.index)
}
}
return t
}
// zero instantiates and return a zero value object for the given type during execution
func (t *Type) zero() reflect.Value {
t = t.finalize()
switch t.cat {
case AliasT:
return t.val.zero()
@@ -393,11 +397,11 @@ func (t *Type) getMethod(name string) *Node {
// and the list of indices to access the right struct field, in case of a promoted method
func (t *Type) lookupMethod(name string) (*Node, []int) {
if t.cat == PtrT {
m, index := t.val.lookupMethod(name)
return m, index
return t.val.lookupMethod(name)
}
var index []int
if m := t.getMethod(name); m == nil {
m := t.getMethod(name)
if m == nil {
for i, f := range t.field {
if f.embed {
if m, index2 := f.typ.lookupMethod(name); m != nil {
@@ -406,10 +410,8 @@ func (t *Type) lookupMethod(name string) (*Node, []int) {
}
}
}
} else {
return m, index
}
return nil, index
return m, index
}
// ptrTo returns the pointer type with element t.