|
|
@@ -129,6 +129,12 @@ static void emitBytes(uint8_t byte1, uint8_t byte2) {
|
|
|
emitByte(byte1);
|
|
|
emitByte(byte2);
|
|
|
}
|
|
|
+static int emitJump(uint8_t instruction) {
|
|
|
+ emitByte(instruction);
|
|
|
+ emitByte(0xff);// 占位字节,后面填入需要跳转的 offset
|
|
|
+ emitByte(0xff);//
|
|
|
+ return currentChunk()->count - 2;
|
|
|
+}
|
|
|
static void emitReturn() {
|
|
|
emitByte(OP_RETURN);
|
|
|
}
|
|
|
@@ -163,6 +169,32 @@ static void expressionStatement() {
|
|
|
consume(TOKEN_SEMICOLON, "Expect ';' after expression.");
|
|
|
emitByte(OP_POP);
|
|
|
}
|
|
|
+static void patchJump(int offset) {
|
|
|
+ // -2 to adjust for the bytecode for the jump offset itself.
|
|
|
+ int jump = currentChunk()->count - offset - 2;
|
|
|
+
|
|
|
+ if (jump > UINT16_MAX) error("Too much code to jump over.");
|
|
|
+
|
|
|
+ currentChunk()->code[offset] = (jump >> 8) & 0xFF;
|
|
|
+ currentChunk()->code[offset + 1] = jump & 0xFF;
|
|
|
+}
|
|
|
+static void ifStatement() {
|
|
|
+ consume(TOKEN_LEFT_PAREN, "Expect '(' after 'if'.");
|
|
|
+ expression();
|
|
|
+ consume(TOKEN_RIGHT_PAREN, "Expect ')' after condition.");
|
|
|
+
|
|
|
+ int thenJump = emitJump(OP_JUMP_IF_FALSE);
|
|
|
+ emitByte(OP_POP);
|
|
|
+ statement();// then branch statement
|
|
|
+
|
|
|
+ int elseJump = emitJump(OP_JUMP);
|
|
|
+
|
|
|
+ patchJump(thenJump);
|
|
|
+ emitByte(OP_POP);
|
|
|
+
|
|
|
+ if (match(TOKEN_ELSE)) statement();// else branch statement
|
|
|
+ patchJump(elseJump);
|
|
|
+}
|
|
|
static void printStatement() {
|
|
|
expression();
|
|
|
consume(TOKEN_SEMICOLON, "Expect ';' after value.");
|
|
|
@@ -218,6 +250,8 @@ static void block() {
|
|
|
static void statement() {
|
|
|
if (match(TOKEN_PRINT)) {
|
|
|
printStatement();
|
|
|
+ } else if (match(TOKEN_IF)) {
|
|
|
+ ifStatement();
|
|
|
} else if (match(TOKEN_LEFT_BRACE)) {
|
|
|
///! block → "{" declaration* "}" ;
|
|
|
beginScope();
|