aboutsummaryrefslogtreecommitdiffstats
path: root/clox/src/compiler.c
diff options
context:
space:
mode:
Diffstat (limited to 'clox/src/compiler.c')
-rw-r--r--clox/src/compiler.c64
1 files changed, 62 insertions, 2 deletions
diff --git a/clox/src/compiler.c b/clox/src/compiler.c
index a964b79..d965f45 100644
--- a/clox/src/compiler.c
+++ b/clox/src/compiler.c
@@ -119,6 +119,13 @@ static void emitBytes(uint8_t byte1, uint8_t byte2) {
emitByte(byte2);
}
+static int emitJump(uint8_t instruction) {
+ emitByte(instruction);
+ emitByte(0xff);
+ emitByte(0xff);
+ return currentChunk()->count - 2;
+}
+
static void emitReturn() { emitByte(OP_RETURN); }
static uint8_t makeConstant(Value value) {
@@ -135,6 +142,18 @@ static void emitConstant(Value value) {
emitBytes(OP_CONSTANT, makeConstant(value));
}
+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 initCompiler(Compiler *compiler) {
compiler->localCount = 0;
compiler->scopeDepth = 0;
@@ -258,6 +277,25 @@ static void expressionStatement() {
emitByte(OP_POP);
}
+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();
+
+ int elseJump = emitJump(OP_JUMP);
+
+ patchJump(thenJump);
+ emitByte(OP_POP);
+
+ if (match(TOKEN_ELSE))
+ statement();
+ patchJump(elseJump);
+}
+
static void printStatement() {
expression();
consume(TOKEN_SEMICOLON, "Expect ';' after value.");
@@ -302,6 +340,8 @@ static void declaration() {
static void statement() {
if (match(TOKEN_PRINT)) {
printStatement();
+ } else if (match(TOKEN_IF)) {
+ ifStatement();
} else if (match(TOKEN_LEFT_BRACE)) {
beginScope();
block();
@@ -316,6 +356,26 @@ static void number(bool canAssign) {
emitConstant(NUMBER_VAL(value));
}
+static void and_(bool canAssign) {
+ int endJump = emitJump(OP_JUMP_IF_FALSE);
+
+ emitByte(OP_POP);
+ parsePrecedence(PREC_AND);
+
+ patchJump(endJump);
+}
+
+static void or_(bool canAssign) {
+ int elseJump = emitJump(OP_JUMP_IF_FALSE);
+ int endJump = emitJump(OP_JUMP);
+
+ patchJump(elseJump);
+ emitByte(OP_POP);
+
+ parsePrecedence(PREC_OR);
+ patchJump(endJump);
+}
+
static void string(bool canAssign) {
emitConstant(OBJ_VAL(
copyString(parser.previous.start + 1, parser.previous.length - 2)));
@@ -393,7 +453,7 @@ ParseRule rules[] = {
[TOKEN_IDENTIFIER] = {variable, NULL, PREC_NONE},
[TOKEN_STRING] = {string, NULL, PREC_NONE},
[TOKEN_NUMBER] = {number, NULL, PREC_NONE},
- [TOKEN_AND] = {NULL, NULL, PREC_NONE},
+ [TOKEN_AND] = {NULL, and_, PREC_AND},
[TOKEN_CLASS] = {NULL, NULL, PREC_NONE},
[TOKEN_ELSE] = {NULL, NULL, PREC_NONE},
[TOKEN_FALSE] = {literal, NULL, PREC_NONE},
@@ -401,7 +461,7 @@ ParseRule rules[] = {
[TOKEN_FUN] = {NULL, NULL, PREC_NONE},
[TOKEN_IF] = {NULL, NULL, PREC_NONE},
[TOKEN_NIL] = {literal, NULL, PREC_NONE},
- [TOKEN_OR] = {NULL, NULL, PREC_NONE},
+ [TOKEN_OR] = {NULL, or_, PREC_OR},
[TOKEN_PRINT] = {NULL, NULL, PREC_NONE},
[TOKEN_RETURN] = {NULL, NULL, PREC_NONE},
[TOKEN_SUPER] = {NULL, NULL, PREC_NONE},