diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 97ea09176..7db12fcc3 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -499,6 +499,9 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { return nil case *ast.IfStmt: + c.scope.vars.newScope() + defer c.scope.vars.dropScope() + lIf := c.newLabel() lElse := c.newLabel() lElseEnd := c.newLabel() @@ -553,6 +556,8 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { } } + c.scope.vars.newScope() + c.setLabel(lStart) last := len(cc.Body) - 1 for j, stmt := range cc.Body { @@ -564,6 +569,8 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { } emit.Jmp(c.prog.BinWriter, opcode.JMPL, switchEnd) c.setLabel(lEnd) + + c.scope.vars.dropScope() } c.setLabel(switchEnd) @@ -884,6 +891,9 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { return nil case *ast.ForStmt: + c.scope.vars.newScope() + defer c.scope.vars.dropScope() + fstart, label := c.generateLabel(labelStart) fend := c.newNamedLabel(labelEnd, label) fpost := c.newNamedLabel(labelPost, label) @@ -926,6 +936,9 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { return nil case *ast.RangeStmt: + c.scope.vars.newScope() + defer c.scope.vars.dropScope() + start, label := c.generateLabel(labelStart) end := c.newNamedLabel(labelEnd, label) post := c.newNamedLabel(labelPost, label) diff --git a/pkg/compiler/global_test.go b/pkg/compiler/global_test.go index 190d50fd5..156b6335f 100644 --- a/pkg/compiler/global_test.go +++ b/pkg/compiler/global_test.go @@ -1,6 +1,7 @@ package compiler_test import ( + "fmt" "math/big" "testing" ) @@ -55,3 +56,29 @@ func TestMultiDeclarationLocalCompound(t *testing.T) { }` eval(t, src, big.NewInt(6)) } + +func TestShadow(t *testing.T) { + srcTmpl := `package foo + func Main() int { + x := 1 + y := 10 + %s + x += 1 // increase old local + x := 30 // introduce new local + y += x // make sure is means something + } + return x+y + }` + + runCase := func(b string) func(t *testing.T) { + return func(t *testing.T) { + src := fmt.Sprintf(srcTmpl, b) + eval(t, src, big.NewInt(42)) + } + } + + t.Run("If", runCase("if true {")) + t.Run("For", runCase("for i := 0; i < 1; i++ {")) + t.Run("Range", runCase("for range []int{1} {")) + t.Run("Switch", runCase("switch true {\ncase false: x += 2\ncase true:")) +}