From c0f358e956950c65c4ca6a2b64ce807ad8c27406 Mon Sep 17 00:00:00 2001 From: Mattia Giambirtone Date: Mon, 5 Dec 2022 08:47:14 +0100 Subject: [PATCH] Fixed bugs with blocks --- src/frontend/compiler.nim | 48 +++++++++++++++++++++------------------ tests/blocks.pn | 4 +++- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/frontend/compiler.nim b/src/frontend/compiler.nim index 53ed8e9..f30b570 100644 --- a/src/frontend/compiler.nim +++ b/src/frontend/compiler.nim @@ -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() diff --git a/tests/blocks.pn b/tests/blocks.pn index e621348..5b1b866 100644 --- a/tests/blocks.pn +++ b/tests/blocks.pn @@ -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 {