compiler: do not short-circuit in complex conditions

Current implementation of short-circuting is just plain wrong
as it uses `last` or `before-last` labels which meaning depend
on context. It doesn't even handle simple assignements like
`a := x == 1 && y == 2`.

This commit makes all jumps in such conditions local
and adds tests.

Closes #699, #700.
This commit is contained in:
Evgenii Stratonikov 2020-02-28 17:18:42 +03:00
parent 26c4e83ddf
commit b461a6ab63
2 changed files with 64 additions and 2 deletions

View file

@ -505,15 +505,27 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
case *ast.BinaryExpr:
switch n.Op {
case token.LAND:
next := c.newLabel()
end := c.newLabel()
ast.Walk(c, n.X)
emit.Jmp(c.prog.BinWriter, opcode.JMPIFNOT, uint16(len(c.l)-1))
emit.Jmp(c.prog.BinWriter, opcode.JMPIF, next)
emit.Opcode(c.prog.BinWriter, opcode.PUSHF)
emit.Jmp(c.prog.BinWriter, opcode.JMP, end)
c.setLabel(next)
ast.Walk(c, n.Y)
c.setLabel(end)
return nil
case token.LOR:
next := c.newLabel()
end := c.newLabel()
ast.Walk(c, n.X)
emit.Jmp(c.prog.BinWriter, opcode.JMPIF, uint16(len(c.l)-3))
emit.Jmp(c.prog.BinWriter, opcode.JMPIFNOT, next)
emit.Opcode(c.prog.BinWriter, opcode.PUSHT)
emit.Jmp(c.prog.BinWriter, opcode.JMP, end)
c.setLabel(next)
ast.Walk(c, n.Y)
c.setLabel(end)
return nil
default: