Fix init of zero objects
This commit is contained in:
11
_test/a19.go
Normal file
11
_test/a19.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
var buf [bsize]byte
|
||||
println(len(buf))
|
||||
}
|
||||
|
||||
const bsize = 10
|
||||
|
||||
// Output:
|
||||
// 10
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user