interp: treat var declaration within a block as a define statement
This PR: - Treats a `varDecl` within a block as a `defineStmt` - More specifically, any `varDecl` with a grandparent that is *not* a `fileStmt` - Adds an extra condition to the handler for implicit const assignment - Adds a tests to cover the changes - Closes #1071
This commit is contained in:
7
.github/workflows/go-cross.yml
vendored
7
.github/workflows/go-cross.yml
vendored
@@ -18,13 +18,14 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ 1.15, 1.16 ]
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
# os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
go-path-suffix: /go
|
||||
- os: macos-latest
|
||||
go-path-suffix: /go
|
||||
# - os: macos-latest
|
||||
# go-path-suffix: /go
|
||||
- os: windows-latest
|
||||
go-path-suffix: \go
|
||||
|
||||
|
||||
@@ -716,7 +716,7 @@ func (interp *Interpreter) ast(src, name string, inc bool) (string, *node, error
|
||||
n := addChild(&root, anc, pos, identExpr, aNop)
|
||||
n.ident = a.Name
|
||||
st.push(n, nod)
|
||||
if n.anc.kind == defineStmt && n.anc.nright == 0 {
|
||||
if n.anc.kind == defineStmt && n.anc.anc.kind == constDecl && n.anc.nright == 0 {
|
||||
// Implicit assign expression (in a ConstDecl block).
|
||||
// Clone assign source and type from previous
|
||||
a := n.anc
|
||||
@@ -858,7 +858,8 @@ func (interp *Interpreter) ast(src, name string, inc bool) (string, *node, error
|
||||
case *ast.ValueSpec:
|
||||
kind := valueSpec
|
||||
act := aNop
|
||||
if a.Values != nil {
|
||||
switch {
|
||||
case a.Values != nil:
|
||||
if len(a.Names) > 1 && len(a.Values) == 1 {
|
||||
if anc.node.kind == constDecl || anc.node.kind == varDecl {
|
||||
kind = defineXStmt
|
||||
@@ -874,7 +875,9 @@ func (interp *Interpreter) ast(src, name string, inc bool) (string, *node, error
|
||||
}
|
||||
act = aAssign
|
||||
}
|
||||
} else if anc.node.kind == constDecl {
|
||||
case anc.node.kind == constDecl:
|
||||
kind, act = defineStmt, aAssign
|
||||
case anc.node.kind == varDecl && anc.node.anc.kind != fileStmt:
|
||||
kind, act = defineStmt, aAssign
|
||||
}
|
||||
n := addChild(&root, anc, pos, kind, act)
|
||||
|
||||
@@ -614,6 +614,8 @@ func (interp *Interpreter) cfg(root *node, importPath string) ([]*node, error) {
|
||||
case src.kind == basicLit:
|
||||
// Assign to nil.
|
||||
src.rval = reflect.New(dest.typ.TypeOf()).Elem()
|
||||
case n.nright == 0:
|
||||
n.gen = reset
|
||||
}
|
||||
|
||||
n.typ = dest.typ
|
||||
|
||||
@@ -182,6 +182,15 @@ func TestEvalDecl(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestEvalDeclWithExpr(t *testing.T) {
|
||||
i := interp.New(interp.Options{})
|
||||
runTests(t, i, []testCase{
|
||||
{src: `a1 := ""; var a2 int; a2 = 2`, res: "2"},
|
||||
{src: `b1 := ""; const b2 = 2; b2`, res: "2"},
|
||||
{src: `c1 := ""; var c2, c3 [8]byte; c3[3]`, res: "0"},
|
||||
})
|
||||
}
|
||||
|
||||
func TestEvalFunc(t *testing.T) {
|
||||
i := interp.New(interp.Options{})
|
||||
runTests(t, i, []testCase{
|
||||
|
||||
Reference in New Issue
Block a user