Fixed bugs with blocks

This commit is contained in:
Mattia Giambirtone 2022-12-05 08:47:14 +01:00
parent 4b6d86ad8e
commit c0f358e956
2 changed files with 29 additions and 23 deletions

View File

@ -175,6 +175,7 @@ type
depth: int depth: int
breakJumps: seq[int] breakJumps: seq[int]
name: string name: string
broken: bool
Compiler* = ref object Compiler* = ref object
## A wrapper around the Peon compiler's state ## 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) 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) = proc importStmt(self: Compiler, node: ImportStmt) =
## Imports a module at compile time ## Imports a module at compile time
self.declare(node) self.declare(node)
@ -2505,9 +2484,32 @@ proc exportStmt(self: Compiler, node: ExportStmt) =
discard 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) = proc namedBlock(self: Compiler, node: NamedBlockStmt) =
## Compiles named blocks ## Compiles named blocks
self.beginScope() self.beginScope()
var blk = self.namedBlocks[^1]
var last: Declaration var last: Declaration
for decl in node.code: for decl in node.code:
if not last.isNil(): 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) self.warning(UnreachableCode, &"code after '{last.token.lexeme}' statement is unreachable", nil, last)
else: else:
discard discard
if blk.broken:
blk.breakJumps.add(self.emitJump(OpCode.JumpForwards, node.token.line))
self.declaration(decl) self.declaration(decl)
last = decl last = decl
self.patchBreaks() self.patchBreaks()

View File

@ -1,5 +1,7 @@
import std; import std;
fn foo {return;}
block outer { block outer {
var x = 1; var x = 1;
@ -10,11 +12,11 @@ block outer {
break outer; break outer;
print("nope"); print("nope");
} }
print("nope again");
} }
var x = 3; var x = 3;
print(x == 3); print(x == 3);
var count = 0; var count = 0;
block loop { block loop {
if count < 5 { if count < 5 {