forked from TrueCloudLab/neoneo-go
Merge pull request #738 from nspcc-dev/feature/fallthrough
compiler: implement fallthrough in switch
This commit is contained in:
commit
15a5c7f3d6
2 changed files with 51 additions and 3 deletions
|
@ -407,7 +407,6 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
return nil
|
||||
|
||||
case *ast.SwitchStmt:
|
||||
// fallthrough is not supported
|
||||
ast.Walk(c, n.Tag)
|
||||
|
||||
eqOpcode := c.getEqualityOpcode(n.Tag)
|
||||
|
@ -416,9 +415,13 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
lastSwitch := c.currentSwitch
|
||||
c.currentSwitch = label
|
||||
|
||||
startLabels := make([]uint16, len(n.Body.List))
|
||||
for i := range startLabels {
|
||||
startLabels[i] = c.newLabel()
|
||||
}
|
||||
for i := range n.Body.List {
|
||||
lEnd := c.newLabel()
|
||||
lStart := c.newLabel()
|
||||
lStart := startLabels[i]
|
||||
cc := n.Body.List[i].(*ast.CaseClause)
|
||||
|
||||
if l := len(cc.List); l != 0 { // if not `default`
|
||||
|
@ -435,7 +438,12 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
}
|
||||
|
||||
c.setLabel(lStart)
|
||||
for _, stmt := range cc.Body {
|
||||
last := len(cc.Body) - 1
|
||||
for j, stmt := range cc.Body {
|
||||
if j == last && isFallthroughStmt(stmt) {
|
||||
emit.Jmp(c.prog.BinWriter, opcode.JMP, startLabels[i+1])
|
||||
break
|
||||
}
|
||||
ast.Walk(c, stmt)
|
||||
}
|
||||
emit.Jmp(c.prog.BinWriter, opcode.JMP, switchEnd)
|
||||
|
@ -834,6 +842,11 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
return c
|
||||
}
|
||||
|
||||
func isFallthroughStmt(c ast.Node) bool {
|
||||
s, ok := c.(*ast.BranchStmt)
|
||||
return ok && s.Tok == token.FALLTHROUGH
|
||||
}
|
||||
|
||||
// emitReverse reverses top num items of the stack.
|
||||
func (c *codegen) emitReverse(num int) {
|
||||
switch num {
|
||||
|
|
|
@ -187,6 +187,41 @@ var switchTestCases = []testCase{
|
|||
}`,
|
||||
big.NewInt(2),
|
||||
},
|
||||
{
|
||||
"simple fallthrough",
|
||||
`package main
|
||||
func Main() int {
|
||||
n := 2
|
||||
switch n {
|
||||
case 1: return 5
|
||||
case 2: fallthrough
|
||||
case 3: return 6
|
||||
}
|
||||
return 7
|
||||
}`,
|
||||
big.NewInt(6),
|
||||
},
|
||||
{
|
||||
"double fallthrough",
|
||||
`package main
|
||||
func Main() int {
|
||||
n := 2
|
||||
k := 5
|
||||
switch n {
|
||||
case 0: return k
|
||||
case 1: fallthrough
|
||||
case 2:
|
||||
k++
|
||||
fallthrough
|
||||
case 3:
|
||||
case 4:
|
||||
k++
|
||||
return k
|
||||
}
|
||||
return k
|
||||
}`,
|
||||
big.NewInt(6),
|
||||
},
|
||||
}
|
||||
|
||||
func TestSwitch(t *testing.T) {
|
||||
|
|
Loading…
Reference in a new issue