Fixed if/else
This commit is contained in:
parent
72ba5c7528
commit
dfa42d994b
|
@ -470,40 +470,23 @@ proc dispatch*(self: PeonVM) =
|
||||||
discard self.popc()
|
discard self.popc()
|
||||||
# Jump opcodes
|
# Jump opcodes
|
||||||
of Jump:
|
of Jump:
|
||||||
self.ip = self.readShort()
|
self.ip = self.readLong()
|
||||||
of JumpForwards:
|
of JumpForwards:
|
||||||
self.ip += self.readShort()
|
self.ip += self.readLong()
|
||||||
of JumpBackwards:
|
of JumpBackwards:
|
||||||
self.ip -= self.readShort()
|
self.ip -= self.readLong()
|
||||||
of JumpIfFalse:
|
of JumpIfFalse:
|
||||||
if not self.peek().boolean:
|
if not self.peek().boolean:
|
||||||
self.ip += self.readShort()
|
self.ip += self.readLong()
|
||||||
of JumpIfTrue:
|
of JumpIfTrue:
|
||||||
if self.peek().boolean:
|
if self.peek().boolean:
|
||||||
self.ip += self.readShort()
|
self.ip += self.readLong()
|
||||||
of JumpIfFalsePop:
|
of JumpIfFalsePop:
|
||||||
|
let ip = self.readLong()
|
||||||
if not self.peek().boolean:
|
if not self.peek().boolean:
|
||||||
self.ip += self.readShort()
|
self.ip = ip
|
||||||
discard self.pop()
|
discard self.pop()
|
||||||
of JumpIfFalseOrPop:
|
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:
|
if not self.peek().boolean:
|
||||||
self.ip += self.readLong()
|
self.ip += self.readLong()
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -27,7 +27,7 @@ when len(PEON_COMMIT_HASH) != 40:
|
||||||
const PEON_BRANCH* = "master"
|
const PEON_BRANCH* = "master"
|
||||||
when len(PEON_BRANCH) > 255:
|
when len(PEON_BRANCH) > 255:
|
||||||
{.fatal: "The git branch name's length must be less than or equal to 255 characters".}
|
{.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_GC* = false # Traces the garbage collector (TODO)
|
||||||
const DEBUG_TRACE_ALLOCATION* = false # Traces memory allocation/deallocation
|
const DEBUG_TRACE_ALLOCATION* = false # Traces memory allocation/deallocation
|
||||||
const DEBUG_TRACE_COMPILER* = false # Traces the compiler
|
const DEBUG_TRACE_COMPILER* = false # Traces the compiler
|
||||||
|
|
|
@ -913,7 +913,7 @@ proc declareName(self: Compiler, node: Declaration) =
|
||||||
if self.scopeDepth > 0:
|
if self.scopeDepth > 0:
|
||||||
# Closure variables are only used in local
|
# Closure variables are only used in local
|
||||||
# scopes
|
# scopes
|
||||||
self.emitByte(LongJumpForwards)
|
self.emitByte(JumpForwards)
|
||||||
self.emitBytes(0.toTriple())
|
self.emitBytes(0.toTriple())
|
||||||
of NodeKind.funDecl:
|
of NodeKind.funDecl:
|
||||||
var node = FunDecl(node)
|
var node = FunDecl(node)
|
||||||
|
@ -1098,6 +1098,17 @@ proc blockStmt(self: Compiler, node: BlockStmt) =
|
||||||
proc ifStmt(self: Compiler, node: IfStmt) =
|
proc ifStmt(self: Compiler, node: IfStmt) =
|
||||||
## Compiles if/else statements for conditional
|
## Compiles if/else statements for conditional
|
||||||
## execution of code
|
## 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)
|
self.expression(node.condition)
|
||||||
var jumpCode: OpCode
|
var jumpCode: OpCode
|
||||||
if self.enableOptimizations:
|
if self.enableOptimizations:
|
||||||
|
@ -1118,21 +1129,11 @@ proc ifStmt(self: Compiler, node: IfStmt) =
|
||||||
proc emitLoop(self: Compiler, begin: int) =
|
proc emitLoop(self: Compiler, begin: int) =
|
||||||
## Emits a JumpBackwards instruction with the correct
|
## Emits a JumpBackwards instruction with the correct
|
||||||
## jump offset
|
## jump offset
|
||||||
var offset: int
|
var offset = self.chunk.code.len() - begin + 4
|
||||||
case OpCode(self.chunk.code[begin + 1]): # The jump instruction
|
if offset > 16777215:
|
||||||
of LongJumpForwards, LongJumpBackwards, LongJumpIfFalse,
|
self.error("cannot jump more than 16777215 bytecode instructions")
|
||||||
LongJumpIfFalsePop, LongJumpIfTrue:
|
self.emitByte(JumpBackwards)
|
||||||
offset = self.chunk.code.len() - begin + 4
|
self.emitBytes(offset.toTriple())
|
||||||
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())
|
|
||||||
|
|
||||||
|
|
||||||
proc whileStmt(self: Compiler, node: WhileStmt) =
|
proc whileStmt(self: Compiler, node: WhileStmt) =
|
||||||
|
@ -1299,14 +1300,10 @@ proc raiseStmt(self: Compiler, node: RaiseStmt) =
|
||||||
proc continueStmt(self: Compiler, node: ContinueStmt) =
|
proc continueStmt(self: Compiler, node: ContinueStmt) =
|
||||||
## Compiles continue statements. A continue statements
|
## Compiles continue statements. A continue statements
|
||||||
## jumps to the next iteration in a loop
|
## jumps to the next iteration in a loop
|
||||||
if self.currentLoop.start <= 65535:
|
if self.currentLoop.start > 16777215:
|
||||||
self.emitByte(Jump)
|
self.error("too much code to jump over in continue statement")
|
||||||
self.emitBytes(self.currentLoop.start.toDouble())
|
self.emitByte(Jump)
|
||||||
else:
|
self.emitBytes(self.currentLoop.start.toTriple())
|
||||||
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())
|
|
||||||
|
|
||||||
|
|
||||||
proc breakStmt(self: Compiler, node: BreakStmt) =
|
proc breakStmt(self: Compiler, node: BreakStmt) =
|
||||||
|
@ -1422,7 +1419,7 @@ proc funDecl(self: Compiler, node: FunDecl) =
|
||||||
self.frames.add(self.names.high())
|
self.frames.add(self.names.high())
|
||||||
let fn = self.names[^(node.arguments.len() + 1)]
|
let fn = self.names[^(node.arguments.len() + 1)]
|
||||||
fn.codePos = self.chunk.code.len()
|
fn.codePos = self.chunk.code.len()
|
||||||
let jmp = self.emitJump(LongJumpForwards)
|
let jmp = self.emitJump(JumpForwards)
|
||||||
for argument in node.arguments:
|
for argument in node.arguments:
|
||||||
self.emitByte(LoadArgument)
|
self.emitByte(LoadArgument)
|
||||||
if node.returnType != nil and self.inferType(node.returnType) == nil:
|
if node.returnType != nil and self.inferType(node.returnType) == nil:
|
||||||
|
|
|
@ -110,14 +110,6 @@ type
|
||||||
JumpIfTrue, # Jumps to a relative index in the bytecode if x is true
|
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
|
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)
|
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
|
## Functions
|
||||||
Call, # Calls a function and initiates a new stack frame
|
Call, # Calls a function and initiates a new stack frame
|
||||||
Return, # Terminates the current function
|
Return, # Terminates the current function
|
||||||
|
@ -175,11 +167,9 @@ const argumentTripleInstructions* = {}
|
||||||
const callInstructions* = {Call, }
|
const callInstructions* = {Call, }
|
||||||
|
|
||||||
# Jump instructions jump at relative or absolute bytecode offsets
|
# Jump instructions jump at relative or absolute bytecode offsets
|
||||||
const jumpInstructions* = {Jump, LongJump, JumpIfFalse, JumpIfFalsePop,
|
const jumpInstructions* = {Jump, JumpIfFalse, JumpIfFalsePop,
|
||||||
JumpForwards, JumpBackwards,
|
JumpForwards, JumpBackwards,
|
||||||
LongJumpIfFalse, LongJumpIfFalsePop,
|
JumpIfTrue}
|
||||||
LongJumpForwards, LongJumpBackwards,
|
|
||||||
JumpIfTrue, LongJumpIfTrue}
|
|
||||||
|
|
||||||
|
|
||||||
proc newChunk*: Chunk =
|
proc newChunk*: Chunk =
|
||||||
|
|
|
@ -30,7 +30,7 @@ proc getLineEditor: LineEditor
|
||||||
# Handy dandy compile-time constants
|
# Handy dandy compile-time constants
|
||||||
const debugLexer = false
|
const debugLexer = false
|
||||||
const debugParser = false
|
const debugParser = false
|
||||||
const debugCompiler = false
|
const debugCompiler = true
|
||||||
const debugSerializer = false
|
const debugSerializer = false
|
||||||
const debugRuntime = false
|
const debugRuntime = false
|
||||||
|
|
||||||
|
|
|
@ -167,21 +167,12 @@ proc constantInstruction(self: Debugger, instruction: OpCode) =
|
||||||
proc jumpInstruction(self: Debugger, instruction: OpCode) =
|
proc jumpInstruction(self: Debugger, instruction: OpCode) =
|
||||||
## Debugs jumps
|
## Debugs jumps
|
||||||
var orig = self.current
|
var orig = self.current
|
||||||
var jump: int
|
var jump = [self.chunk.code[self.current + 1], self.chunk.code[self.current + 2], self.chunk.code[self.current + 3]].fromTriple().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
|
|
||||||
printInstruction(instruction, true)
|
printInstruction(instruction, true)
|
||||||
printDebug("Jump size: ")
|
printDebug("Jump size: ")
|
||||||
stdout.styledWrite(fgYellow, $jump)
|
stdout.styledWrite(fgYellow, $jump)
|
||||||
nl()
|
nl()
|
||||||
self.current += 3
|
self.current += 4
|
||||||
for i in countup(orig, self.current + 1):
|
for i in countup(orig, self.current + 1):
|
||||||
self.checkFrameStart(i)
|
self.checkFrameStart(i)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue