Chapter 23.3
This commit is contained in:
parent
ba6ab6759e
commit
37ac05af6d
4 changed files with 36 additions and 0 deletions
|
@ -27,6 +27,7 @@ typedef enum {
|
||||||
OP_PRINT,
|
OP_PRINT,
|
||||||
OP_JUMP,
|
OP_JUMP,
|
||||||
OP_JUMP_IF_FALSE,
|
OP_JUMP_IF_FALSE,
|
||||||
|
OP_LOOP,
|
||||||
OP_RETURN,
|
OP_RETURN,
|
||||||
} OpCode;
|
} OpCode;
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,17 @@ static void emitBytes(uint8_t byte1, uint8_t byte2) {
|
||||||
emitByte(byte2);
|
emitByte(byte2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void emitLoop(int loopStart) {
|
||||||
|
emitByte(OP_LOOP);
|
||||||
|
|
||||||
|
int offset = currentChunk()->count - loopStart + 2;
|
||||||
|
if (offset > UINT16_MAX)
|
||||||
|
error("Loop body too large.");
|
||||||
|
|
||||||
|
emitByte((offset >> 8) & 0xff);
|
||||||
|
emitByte(offset & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
static int emitJump(uint8_t instruction) {
|
static int emitJump(uint8_t instruction) {
|
||||||
emitByte(instruction);
|
emitByte(instruction);
|
||||||
emitByte(0xff);
|
emitByte(0xff);
|
||||||
|
@ -302,6 +313,21 @@ static void printStatement() {
|
||||||
emitByte(OP_PRINT);
|
emitByte(OP_PRINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void whileStatement() {
|
||||||
|
int loopStart = currentChunk()->count;
|
||||||
|
consume(TOKEN_LEFT_PAREN, "Expect '(' after 'while'.");
|
||||||
|
expression();
|
||||||
|
consume(TOKEN_RIGHT_PAREN, "Expect ')' after condition.");
|
||||||
|
|
||||||
|
int exitJump = emitJump(OP_JUMP_IF_FALSE);
|
||||||
|
emitByte(OP_POP);
|
||||||
|
statement();
|
||||||
|
emitLoop(loopStart);
|
||||||
|
|
||||||
|
patchJump(exitJump);
|
||||||
|
emitByte(OP_POP);
|
||||||
|
}
|
||||||
|
|
||||||
static void synchronize() {
|
static void synchronize() {
|
||||||
parser.panicMode = false;
|
parser.panicMode = false;
|
||||||
|
|
||||||
|
@ -342,6 +368,8 @@ static void statement() {
|
||||||
printStatement();
|
printStatement();
|
||||||
} else if (match(TOKEN_IF)) {
|
} else if (match(TOKEN_IF)) {
|
||||||
ifStatement();
|
ifStatement();
|
||||||
|
} else if (match(TOKEN_WHILE)) {
|
||||||
|
whileStatement();
|
||||||
} else if (match(TOKEN_LEFT_BRACE)) {
|
} else if (match(TOKEN_LEFT_BRACE)) {
|
||||||
beginScope();
|
beginScope();
|
||||||
block();
|
block();
|
||||||
|
|
|
@ -92,6 +92,8 @@ int disassembleInstruction(Chunk *chunk, int offset) {
|
||||||
return jumpInstruction("OP_JUMP", 1, chunk, offset);
|
return jumpInstruction("OP_JUMP", 1, chunk, offset);
|
||||||
case OP_JUMP_IF_FALSE:
|
case OP_JUMP_IF_FALSE:
|
||||||
return jumpInstruction("OP_JUMP_IF_FALSE", 1, chunk, offset);
|
return jumpInstruction("OP_JUMP_IF_FALSE", 1, chunk, offset);
|
||||||
|
case OP_LOOP:
|
||||||
|
return jumpInstruction("OP_LOOP", -1, chunk, offset);
|
||||||
case OP_RETURN:
|
case OP_RETURN:
|
||||||
return simpleInstruction("OP_RETURN", offset);
|
return simpleInstruction("OP_RETURN", offset);
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -211,6 +211,11 @@ static InterpretResult run() {
|
||||||
vm.ip += offset;
|
vm.ip += offset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OP_LOOP: {
|
||||||
|
uint16_t offset = READ_SHORT();
|
||||||
|
vm.ip -= offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case OP_RETURN: {
|
case OP_RETURN: {
|
||||||
/* The book said to remove this, but when I do I get an infinite loop and
|
/* The book said to remove this, but when I do I get an infinite loop and
|
||||||
then a segfault because it keeps trying to add the constant 1 to the
|
then a segfault because it keeps trying to add the constant 1 to the
|
||||||
|
|
Loading…
Reference in a new issue