diff --git a/src/compiler.nim b/src/compiler.nim index a899c09..35a8bd2 100644 --- a/src/compiler.nim +++ b/src/compiler.nim @@ -747,14 +747,15 @@ proc endLooping(self: Compiler) = if self.loop.loopEnd != -1: self.patchJump(self.loop.loopEnd) self.emitByte(OpCode.Pop) - var i = self.loop.body - while i < self.currentChunk.code.len: - if self.currentChunk.code[i] == uint OpCode.Break: - self.currentChunk.code[i] = uint8 OpCode.Jump - self.patchJump(i + 1) - i += 3 - else: - i += 1 + + for brk in self.loop.breaks: + when DEBUG_TRACE_COMPILER: + setForegroundColor(fgYellow) + write stdout, &"DEBUG - Compiler: patching break at {brk}\n" + setForegroundColor(fgDefault) + self.currentChunk.code[brk] = OpCode.Jump.uint8 + self.patchJump(brk + 1) + self.loop = self.loop.outer @@ -843,6 +844,7 @@ proc parseBreak(self: Compiler) = self.emitByte(OpCode.Pop) i -= 1 discard self.emitJump(OpCode.Break) + self.loop.breaks.add(self.currentChunk.code.len() - 3) proc parseAnd(self: Compiler, canAssign: bool) = diff --git a/src/meta/looptype.nim b/src/meta/looptype.nim index bd6608d..3f59b77 100644 --- a/src/meta/looptype.nim +++ b/src/meta/looptype.nim @@ -21,3 +21,4 @@ type Loop* = ref object alive*: bool body*: int loopEnd*: int + breaks*: seq[int] diff --git a/src/meta/opcode.nim b/src/meta/opcode.nim index ac53388..61d150d 100644 --- a/src/meta/opcode.nim +++ b/src/meta/opcode.nim @@ -83,7 +83,9 @@ const simpleInstructions* = {OpCode.Return, OpCode.Add, OpCode.Multiply, OpCode.Xor, OpCode.Not, OpCode.Equal, OpCode.Greater, OpCode.Less, OpCode.GetItem, OpCode.Slice, OpCode.Pop, OpCode.Negate, - OpCode.Is, OpCode.As, GreaterOrEqual, LessOrEqual} + OpCode.Is, OpCode.As, OpCode.GreaterOrEqual, + OpCode.LessOrEqual, OpCode.Bor, OpCode.Band, + OpCode.Bnot} const constantInstructions* = {OpCode.Constant, OpCode.DefineGlobal, OpCode.GetGlobal, OpCode.SetGlobal, OpCode.DeleteGlobal} diff --git a/tests/japl/break.jpl b/tests/japl/break.jpl new file mode 100644 index 0000000..2cd2e56 --- /dev/null +++ b/tests/japl/break.jpl @@ -0,0 +1,23 @@ +//[Test: breaks] +//[source:mixed] +var x = 5; +while (true) { + var a = 1; + x = x - a; + if (x < 0) { + break; + } + print(x); +} +//[end] +/* +[stdout] +4 +3 +2 +1 +0 +[end] +[end] +*/ +