fix: handle constant declarations inside function scopes

This commit is contained in:
Marc Vertes
2020-05-03 18:56:04 +02:00
committed by GitHub
parent 22dfc8b10a
commit 7070367d21
4 changed files with 40 additions and 13 deletions

13
_test/const11.go Normal file
View File

@@ -0,0 +1,13 @@
package main
func main() {
const (
x = 2 * iota
dim
)
var t [dim * 2]int
println(t[0], len(t))
}
// Output:
// 0 4

View File

@@ -50,7 +50,6 @@ var identifier = regexp.MustCompile(`([\pL_][\pL_\d]*)$`)
func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
sc := interp.initScopePkg(pkgID)
var initNodes []*node
var iotaValue int
var err error
root.Walk(func(n *node) bool {
@@ -370,6 +369,18 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
}
return false
case constDecl:
// Early parse of constDecl subtrees, to compute all constant
// values which may be used in further declarations.
if !sc.global {
for _, c := range n.child {
if _, err = interp.cfg(c, pkgID); err != nil {
// No error processing here, to allow recovery in subtree nodes.
err = nil
}
}
}
case arrayType, basicLit, chanType, funcType, mapType, structType:
n.typ, err = nodeType(interp, sc, n)
return false
@@ -525,7 +536,11 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
}
if n.anc.kind == constDecl {
sc.sym[dest.ident].kind = constSym
iotaValue++
if childPos(n) == len(n.anc.child)-1 {
sc.iota = 0
} else {
sc.iota++
}
}
}
@@ -715,11 +730,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
}
sc = sc.pop()
case constDecl:
iotaValue = 0
wireChild(n)
case varDecl:
case constDecl, varDecl:
wireChild(n)
case declStmt, exprStmt, sendStmt:
@@ -1020,7 +1031,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
n.rval = sym.rval
n.kind = basicLit
case n.ident == "iota":
n.rval = reflect.ValueOf(iotaValue)
n.rval = reflect.ValueOf(sc.iota)
n.kind = basicLit
case n.ident == "nil":
n.kind = basicLit

View File

@@ -9,7 +9,6 @@ import "reflect"
func (interp *Interpreter) gta(root *node, rpath, pkgID string) ([]*node, error) {
sc := interp.initScopePkg(pkgID)
var err error
var iotaValue int
var revisit []*node
root.Walk(func(n *node) bool {
@@ -18,9 +17,8 @@ func (interp *Interpreter) gta(root *node, rpath, pkgID string) ([]*node, error)
}
switch n.kind {
case constDecl:
iotaValue = 0
// Early parse of constDecl subtree, to compute all constant
// values which may be necessary in further declarations.
// values which may be used in further declarations.
if _, err = interp.cfg(n, pkgID); err != nil {
// No error processing here, to allow recovery in subtree nodes.
err = nil
@@ -47,7 +45,7 @@ func (interp *Interpreter) gta(root *node, rpath, pkgID string) ([]*node, error)
for i := 0; i < n.nleft; i++ {
dest, src := n.child[i], n.child[sbase+i]
val := reflect.ValueOf(iotaValue)
val := reflect.ValueOf(sc.iota)
if n.anc.kind == constDecl {
if _, err2 := interp.cfg(n, pkgID); err2 != nil {
// Constant value can not be computed yet.
@@ -80,7 +78,11 @@ func (interp *Interpreter) gta(root *node, rpath, pkgID string) ([]*node, error)
}
if n.anc.kind == constDecl {
sc.sym[dest.ident].kind = constSym
iotaValue++
if childPos(n) == len(n.anc.child)-1 {
sc.iota = 0
} else {
sc.iota++
}
}
}
return false

View File

@@ -83,6 +83,7 @@ type scope struct {
level int // Frame level: number of frame indirections to access var during execution
sym map[string]*symbol // Map of symbols defined in this current scope
global bool // true if scope refers to global space (single frame for universe and package level scopes)
iota int // iota value in this scope
}
// push creates a new scope and chain it to the current one