Fixed bugs with blocks
This commit is contained in:
parent
4b6d86ad8e
commit
c0f358e956
|
@ -175,6 +175,7 @@ type
|
|||
depth: int
|
||||
breakJumps: seq[int]
|
||||
name: string
|
||||
broken: bool
|
||||
|
||||
Compiler* = ref object
|
||||
## A wrapper around the Peon compiler's state
|
||||
|
@ -2445,28 +2446,6 @@ proc continueStmt(self: Compiler, node: ContinueStmt) =
|
|||
self.emitBytes(blocks[^1].start.toTriple(), node.token.line)
|
||||
|
||||
|
||||
proc breakStmt(self: Compiler, node: BreakStmt) =
|
||||
## Compiles break statements. A break statement
|
||||
## jumps to the end of the loop
|
||||
if node.label.isNil():
|
||||
self.currentLoop.breakJumps.add(self.emitJump(OpCode.JumpForwards, node.token.line))
|
||||
if self.currentLoop.depth > self.depth:
|
||||
# Breaking out of a loop closes its scope
|
||||
self.endScope()
|
||||
else:
|
||||
var blocks: seq[NamedBlock] = @[]
|
||||
var found: bool = false
|
||||
for blk in reversed(self.namedBlocks):
|
||||
blocks.add(blk)
|
||||
if blk.name == node.label.token.lexeme:
|
||||
for blk in blocks:
|
||||
blk.breakJumps.add(self.emitJump(OpCode.JumpForwards, node.token.line))
|
||||
found = true
|
||||
break
|
||||
if not found:
|
||||
self.error(&"unknown block name '{node.label.token.lexeme}'", node.label)
|
||||
|
||||
|
||||
proc importStmt(self: Compiler, node: ImportStmt) =
|
||||
## Imports a module at compile time
|
||||
self.declare(node)
|
||||
|
@ -2505,9 +2484,32 @@ proc exportStmt(self: Compiler, node: ExportStmt) =
|
|||
discard
|
||||
|
||||
|
||||
proc breakStmt(self: Compiler, node: BreakStmt) =
|
||||
## Compiles break statements. A break statement
|
||||
## jumps to the end of the loop
|
||||
if node.label.isNil():
|
||||
self.currentLoop.breakJumps.add(self.emitJump(OpCode.JumpForwards, node.token.line))
|
||||
if self.currentLoop.depth > self.depth:
|
||||
# Breaking out of a loop closes its scope
|
||||
self.endScope()
|
||||
else:
|
||||
var blocks: seq[NamedBlock] = @[]
|
||||
var found: bool = false
|
||||
for blk in reversed(self.namedBlocks):
|
||||
blocks.add(blk)
|
||||
if blk.name == node.label.token.lexeme:
|
||||
for blk in blocks:
|
||||
blk.broken = true
|
||||
found = true
|
||||
break
|
||||
if not found:
|
||||
self.error(&"unknown block name '{node.label.token.lexeme}'", node.label)
|
||||
|
||||
|
||||
proc namedBlock(self: Compiler, node: NamedBlockStmt) =
|
||||
## Compiles named blocks
|
||||
self.beginScope()
|
||||
var blk = self.namedBlocks[^1]
|
||||
var last: Declaration
|
||||
for decl in node.code:
|
||||
if not last.isNil():
|
||||
|
@ -2516,6 +2518,8 @@ proc namedBlock(self: Compiler, node: NamedBlockStmt) =
|
|||
self.warning(UnreachableCode, &"code after '{last.token.lexeme}' statement is unreachable", nil, last)
|
||||
else:
|
||||
discard
|
||||
if blk.broken:
|
||||
blk.breakJumps.add(self.emitJump(OpCode.JumpForwards, node.token.line))
|
||||
self.declaration(decl)
|
||||
last = decl
|
||||
self.patchBreaks()
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import std;
|
||||
|
||||
fn foo {return;}
|
||||
|
||||
|
||||
block outer {
|
||||
var x = 1;
|
||||
|
@ -10,11 +12,11 @@ block outer {
|
|||
break outer;
|
||||
print("nope");
|
||||
}
|
||||
print("nope again");
|
||||
}
|
||||
var x = 3;
|
||||
print(x == 3);
|
||||
|
||||
|
||||
var count = 0;
|
||||
block loop {
|
||||
if count < 5 {
|
||||
|
|
Loading…
Reference in New Issue