mirror of https://github.com/japl-lang/japl.git
Fixed numerous bugs with improper statements in the parser
This commit is contained in:
parent
b9fecca2d9
commit
faf5e6149b
|
@ -465,23 +465,63 @@ proc emitJump(self: Compiler, opcode: OpCode): int =
|
|||
|
||||
proc patchJump(self: Compiler, offset: int) =
|
||||
var jump = self.compilingChunk.code.len - offset - 2
|
||||
self.compilingChunk.code[offset] = uint8 (jump shr 8) and 0xff
|
||||
self.compilingChunk.code[offset + 1] = uint8 jump and 0xff
|
||||
if jump > (int uint16.high):
|
||||
self.compileError("too much code to jump over")
|
||||
else:
|
||||
self.compilingChunk.code[offset] = uint8 (jump shr 8) and 0xff
|
||||
self.compilingChunk.code[offset + 1] = uint8 jump and 0xff
|
||||
|
||||
|
||||
proc ifStatement(self: var Compiler) =
|
||||
self.parser.consume(LP, "The if condition must be parenthesized")
|
||||
self.expression()
|
||||
self.parser.consume(RP, "The if condition must be parenthesized")
|
||||
var jump: int = self.emitJump(OP_JUMP_IF_FALSE)
|
||||
self.emitByte(OP_POP)
|
||||
self.statement()
|
||||
var elseJump = self.emitJump(OP_JUMP)
|
||||
self.patchJump(jump)
|
||||
self.emitByte(OP_POP)
|
||||
if self.parser.match(ELSE):
|
||||
self.statement()
|
||||
self.patchJump(elseJump)
|
||||
if self.parser.peek.kind != EOF:
|
||||
self.expression()
|
||||
if self.parser.peek.kind != EOF:
|
||||
self.parser.consume(RP, "The if condition must be parenthesized")
|
||||
if self.parser.peek.kind != EOF:
|
||||
var jump: int = self.emitJump(OP_JUMP_IF_FALSE)
|
||||
self.emitByte(OP_POP)
|
||||
self.statement()
|
||||
var elseJump = self.emitJump(OP_JUMP)
|
||||
self.patchJump(jump)
|
||||
self.emitByte(OP_POP)
|
||||
if self.parser.match(ELSE):
|
||||
self.statement()
|
||||
self.patchJump(elseJump)
|
||||
else:
|
||||
self.parser.parseError(self.parser.previous, "Invalid syntax")
|
||||
else:
|
||||
self.parser.parseError(self.parser.previous, "The if condition must be parenthesized")
|
||||
|
||||
|
||||
proc emitLoop(self: var Compiler, start: int) =
|
||||
self.emitByte(OP_LOOP)
|
||||
var offset = self.compilingChunk.code.len - start + 2
|
||||
if offset > (int uint16.high):
|
||||
self.compileError("loop body is too large")
|
||||
else:
|
||||
self.emitByte(uint8 (offset shr 8) and 0xff)
|
||||
self.emitByte(uint8 offset and 0xff)
|
||||
|
||||
|
||||
proc whileStatement(self: var Compiler) =
|
||||
var loopStart = self.compilingChunk.code.len
|
||||
self.parser.consume(LP, "The loop condition must be parenthesized")
|
||||
if self.parser.peek.kind != EOF:
|
||||
self.expression()
|
||||
if self.parser.peek.kind != EOF:
|
||||
self.parser.consume(RP, "The loop condition must be parenthesized")
|
||||
if self.parser.peek.kind != EOF:
|
||||
var exitJump = self.emitJump(OP_JUMP_IF_FALSE)
|
||||
self.emitByte(OP_POP)
|
||||
self.statement()
|
||||
self.emitLoop(loopStart)
|
||||
self.patchJump(exitJump)
|
||||
self.emitByte(OP_POP)
|
||||
else:
|
||||
self.parser.parseError(self.parser.previous, "Invalid syntax")
|
||||
else:
|
||||
self.parser.parseError(self.parser.previous, "The loop condition must be parenthesized")
|
||||
|
||||
|
||||
proc parseAnd(self: Compiler, canAssign: bool) =
|
||||
|
@ -500,11 +540,14 @@ proc parseOr(self: Compiler, canAssign: bool) =
|
|||
self.patchJump(endJump)
|
||||
|
||||
|
||||
|
||||
proc statement(self: var Compiler) =
|
||||
if self.parser.match(VAR):
|
||||
self.varDeclaration()
|
||||
elif self.parser.match(IF):
|
||||
self.ifStatement()
|
||||
elif self.parser.match(WHILE):
|
||||
self.whileStatement()
|
||||
elif self.parser.match(LB):
|
||||
self.beginScope()
|
||||
self.parseBlock()
|
||||
|
|
|
@ -31,7 +31,8 @@ type
|
|||
OP_GET_LOCAL,
|
||||
OP_DELETE_LOCAL,
|
||||
OP_JUMP_IF_FALSE,
|
||||
OP_JUMP
|
||||
OP_JUMP,
|
||||
OP_LOOP
|
||||
Chunk* = ref object
|
||||
consts*: ValueArray
|
||||
code*: seq[uint8]
|
||||
|
|
|
@ -34,7 +34,7 @@ proc constantInstruction(name: string, chunk: Chunk, offset: int): int =
|
|||
return offset + 2
|
||||
|
||||
|
||||
proc jumpInstruction(name: string, sign: int, chunk: Chunk, offset: int): int =
|
||||
proc jumpInstruction(name: string, chunk: Chunk, offset: int): int =
|
||||
var jump = uint16 (chunk.code[offset + 1] shr 8)
|
||||
jump = jump or chunk.code[offset + 2]
|
||||
echo &"\tOpCode at offset: {name}\n\tJump size: {jump}\n"
|
||||
|
@ -98,9 +98,11 @@ proc disassembleInstruction*(chunk: Chunk, offset: int): int =
|
|||
elif opcode == OP_DELETE_GLOBAL:
|
||||
result = simpleInstruction("OP_DELETE_GLOBAL", offset)
|
||||
elif opcode == OP_JUMP_IF_FALSE:
|
||||
result = jumpInstruction("OP_JUMP_IF_FALSE", 1, chunk, offset)
|
||||
result = jumpInstruction("OP_JUMP_IF_FALSE", chunk, offset)
|
||||
elif opcode == OP_JUMP:
|
||||
result = jumpInstruction("OP_JUMP", 1, chunk, offset)
|
||||
result = jumpInstruction("OP_JUMP", chunk, offset)
|
||||
elif opcode == OP_LOOP:
|
||||
result = jumpInstruction("OP_LOOP", chunk, offset)
|
||||
else:
|
||||
echo &"Unknown opcode {opcode} at index {offset}"
|
||||
result = offset + 1
|
||||
|
|
|
@ -352,6 +352,9 @@ proc run(self: VM, debug, repl: bool): InterpretResult =
|
|||
of OP_JUMP:
|
||||
var offset = readShort()
|
||||
self.ip += int offset
|
||||
of OP_LOOP:
|
||||
var offset = readShort()
|
||||
self.ip -= int offset
|
||||
of OP_RETURN:
|
||||
var popped = self.lastPop
|
||||
if repl:
|
||||
|
|
Loading…
Reference in New Issue