compiler: implement fallthrough in switch

Closes #628.
This commit is contained in:
Evgenii Stratonikov 2020-03-10 12:34:05 +03:00
parent 4b83e9a5cd
commit 91301df161
2 changed files with 51 additions and 3 deletions

View file

@ -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 {