fix: handle constant declarations inside function scopes
This commit is contained in:
13
_test/const11.go
Normal file
13
_test/const11.go
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user