diff --git a/src/backend/vm.nim b/src/backend/vm.nim index b43a733..74aa9e3 100644 --- a/src/backend/vm.nim +++ b/src/backend/vm.nim @@ -470,40 +470,23 @@ proc dispatch*(self: PeonVM) = discard self.popc() # Jump opcodes of Jump: - self.ip = self.readShort() + self.ip = self.readLong() of JumpForwards: - self.ip += self.readShort() + self.ip += self.readLong() of JumpBackwards: - self.ip -= self.readShort() + self.ip -= self.readLong() of JumpIfFalse: if not self.peek().boolean: - self.ip += self.readShort() + self.ip += self.readLong() of JumpIfTrue: if self.peek().boolean: - self.ip += self.readShort() + self.ip += self.readLong() of JumpIfFalsePop: + let ip = self.readLong() if not self.peek().boolean: - self.ip += self.readShort() + self.ip = ip discard self.pop() of JumpIfFalseOrPop: - if not self.peek().boolean: - self.ip += self.readShort() - else: - discard self.pop() - of LongJumpIfFalse: - if not self.peek().boolean: - self.ip += self.readLong() - of LongJumpIfFalsePop: - if not self.peek().boolean: - self.ip += self.readLong() - discard self.pop() - of LongJumpForwards: - self.ip += self.readLong() - of LongJumpBackwards: - self.ip -= self.readLong() - of LongJump: - self.ip = self.readLong() - of LongJumpIfFalseOrPop: if not self.peek().boolean: self.ip += self.readLong() else: diff --git a/src/config.nim b/src/config.nim index 12c2291..218807b 100644 --- a/src/config.nim +++ b/src/config.nim @@ -27,7 +27,7 @@ when len(PEON_COMMIT_HASH) != 40: const PEON_BRANCH* = "master" when len(PEON_BRANCH) > 255: {.fatal: "The git branch name's length must be less than or equal to 255 characters".} -const DEBUG_TRACE_VM* = false # Traces VM execution +const DEBUG_TRACE_VM* = true # Traces VM execution const DEBUG_TRACE_GC* = false # Traces the garbage collector (TODO) const DEBUG_TRACE_ALLOCATION* = false # Traces memory allocation/deallocation const DEBUG_TRACE_COMPILER* = false # Traces the compiler diff --git a/src/frontend/compiler.nim b/src/frontend/compiler.nim index fcec330..13555da 100644 --- a/src/frontend/compiler.nim +++ b/src/frontend/compiler.nim @@ -913,7 +913,7 @@ proc declareName(self: Compiler, node: Declaration) = if self.scopeDepth > 0: # Closure variables are only used in local # scopes - self.emitByte(LongJumpForwards) + self.emitByte(JumpForwards) self.emitBytes(0.toTriple()) of NodeKind.funDecl: var node = FunDecl(node) @@ -1098,6 +1098,17 @@ proc blockStmt(self: Compiler, node: BlockStmt) = proc ifStmt(self: Compiler, node: IfStmt) = ## Compiles if/else statements for conditional ## execution of code + var cond = self.inferType(node.condition) + if not self.compareTypes(cond, Type(kind: Bool)): + if cond == nil: + if node.condition.kind == identExpr: + self.error(&"reference to undeclared identifier '{IdentExpr(node.condition).name.lexeme}'") + elif node.condition.kind == callExpr and CallExpr(node.condition).callee.kind == identExpr: + self.error(&"reference to undeclared identifier '{IdentExpr(CallExpr(node.condition).callee).name.lexeme}'") + else: + self.error(&"expecting value of type 'bool', but expression has no type") + else: + self.error(&"expecting value of type 'bool', got '{self.typeToStr(cond)}' instead") self.expression(node.condition) var jumpCode: OpCode if self.enableOptimizations: @@ -1118,21 +1129,11 @@ proc ifStmt(self: Compiler, node: IfStmt) = proc emitLoop(self: Compiler, begin: int) = ## Emits a JumpBackwards instruction with the correct ## jump offset - var offset: int - case OpCode(self.chunk.code[begin + 1]): # The jump instruction - of LongJumpForwards, LongJumpBackwards, LongJumpIfFalse, - LongJumpIfFalsePop, LongJumpIfTrue: - offset = self.chunk.code.len() - begin + 4 - else: - offset = self.chunk.code.len() - begin - if offset > uint16.high().int: - if offset > 16777215: - self.error("cannot jump more than 16777215 bytecode instructions") - self.emitByte(LongJumpBackwards) - self.emitBytes(offset.toTriple()) - else: - self.emitByte(JumpBackwards) - self.emitBytes(offset.toDouble()) + var offset = self.chunk.code.len() - begin + 4 + if offset > 16777215: + self.error("cannot jump more than 16777215 bytecode instructions") + self.emitByte(JumpBackwards) + self.emitBytes(offset.toTriple()) proc whileStmt(self: Compiler, node: WhileStmt) = @@ -1299,14 +1300,10 @@ proc raiseStmt(self: Compiler, node: RaiseStmt) = proc continueStmt(self: Compiler, node: ContinueStmt) = ## Compiles continue statements. A continue statements ## jumps to the next iteration in a loop - if self.currentLoop.start <= 65535: - self.emitByte(Jump) - self.emitBytes(self.currentLoop.start.toDouble()) - else: - if self.currentLoop.start > 16777215: - self.error("too much code to jump over in continue statement") - self.emitByte(LongJump) - self.emitBytes(self.currentLoop.start.toTriple()) + if self.currentLoop.start > 16777215: + self.error("too much code to jump over in continue statement") + self.emitByte(Jump) + self.emitBytes(self.currentLoop.start.toTriple()) proc breakStmt(self: Compiler, node: BreakStmt) = @@ -1422,7 +1419,7 @@ proc funDecl(self: Compiler, node: FunDecl) = self.frames.add(self.names.high()) let fn = self.names[^(node.arguments.len() + 1)] fn.codePos = self.chunk.code.len() - let jmp = self.emitJump(LongJumpForwards) + let jmp = self.emitJump(JumpForwards) for argument in node.arguments: self.emitByte(LoadArgument) if node.returnType != nil and self.inferType(node.returnType) == nil: diff --git a/src/frontend/meta/bytecode.nim b/src/frontend/meta/bytecode.nim index ea0b340..b35fa61 100644 --- a/src/frontend/meta/bytecode.nim +++ b/src/frontend/meta/bytecode.nim @@ -110,14 +110,6 @@ type JumpIfTrue, # Jumps to a relative index in the bytecode if x is true JumpIfFalsePop, # Like JumpIfFalse, but also pops off the stack (regardless of truthyness). Optimization for if statements JumpIfFalseOrPop, # Jumps to an absolute index in the bytecode if x is false and pops otherwise (used for logical and) - ## Long variants of jumps (they use a 24-bit operand instead of a 16-bit one) - LongJump, - LongJumpIfFalse, - LongJumpIfTrue, - LongJumpIfFalsePop, - LongJumpIfFalseOrPop, - LongJumpForwards, - LongJumpBackwards, ## Functions Call, # Calls a function and initiates a new stack frame Return, # Terminates the current function @@ -175,11 +167,9 @@ const argumentTripleInstructions* = {} const callInstructions* = {Call, } # Jump instructions jump at relative or absolute bytecode offsets -const jumpInstructions* = {Jump, LongJump, JumpIfFalse, JumpIfFalsePop, +const jumpInstructions* = {Jump, JumpIfFalse, JumpIfFalsePop, JumpForwards, JumpBackwards, - LongJumpIfFalse, LongJumpIfFalsePop, - LongJumpForwards, LongJumpBackwards, - JumpIfTrue, LongJumpIfTrue} + JumpIfTrue} proc newChunk*: Chunk = diff --git a/src/main.nim b/src/main.nim index 450c44b..bdd3b58 100644 --- a/src/main.nim +++ b/src/main.nim @@ -30,7 +30,7 @@ proc getLineEditor: LineEditor # Handy dandy compile-time constants const debugLexer = false const debugParser = false -const debugCompiler = false +const debugCompiler = true const debugSerializer = false const debugRuntime = false diff --git a/src/util/debugger.nim b/src/util/debugger.nim index 5270d09..3562620 100644 --- a/src/util/debugger.nim +++ b/src/util/debugger.nim @@ -167,21 +167,12 @@ proc constantInstruction(self: Debugger, instruction: OpCode) = proc jumpInstruction(self: Debugger, instruction: OpCode) = ## Debugs jumps var orig = self.current - var jump: int - case instruction: - of Jump, JumpIfFalse, JumpIfTrue, JumpIfFalsePop, JumpForwards, JumpBackwards: - jump = [self.chunk.code[self.current + 1], self.chunk.code[self.current + 2]].fromDouble().int() - of LongJump, LongJumpIfFalse, LongJumpIfTrue, LongJumpIfFalsePop, - LongJumpForwards, LongJumpBackwards: - jump = [self.chunk.code[self.current + 1], self.chunk.code[self.current + 2], self.chunk.code[self.current + 3]].fromTriple().int() - self.current += 1 - else: - discard # Unreachable + var jump = [self.chunk.code[self.current + 1], self.chunk.code[self.current + 2], self.chunk.code[self.current + 3]].fromTriple().int() printInstruction(instruction, true) printDebug("Jump size: ") stdout.styledWrite(fgYellow, $jump) nl() - self.current += 3 + self.current += 4 for i in countup(orig, self.current + 1): self.checkFrameStart(i)