Skip to content

Commit 032d4e8

Browse files
committed
Implement if expressions
1 parent 1ed7a0f commit 032d4e8

22 files changed

Lines changed: 246 additions & 1 deletion

docs/EXTENDING_LOX.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ These are the documented changes to the language/syntax from the original Lox la
1717
- `strIsEmpty`
1818
- Block expressions: `var sum = { 5 + 10 };`
1919
- New bytecode op: `OP_CLOSE_BLOCK_EXPR n`
20+
- If expressions: `print if (true) "Hello" else "World"`
2021
- Native Functions
2122
- [ ] `arrSort(array, fn)`
2223
- [ ] `arrMap(array, fn)`

src/compiler.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,31 @@ static void ifStatement(Scanner *scanner) {
642642
patchJump(elseJump);
643643
}
644644

645+
static void ifExpression(Scanner *scanner, bool canAssign) {
646+
TRACELN(" compiler.ifExpression()");
647+
648+
consume(scanner, TOKEN_LEFT_PAREN, "Expect '(' after 'if'.");
649+
expression(scanner);
650+
consume(scanner, TOKEN_RIGHT_PAREN, "Expect ')' after condition.");
651+
652+
int thenJump = emitJump(OP_JUMP_IF_FALSE);
653+
emitByte(OP_POP);
654+
expression(scanner);
655+
656+
int elseJump = emitJump(OP_JUMP);
657+
658+
patchJump(thenJump);
659+
emitByte(OP_POP);
660+
661+
if (match(scanner, TOKEN_ELSE)) {
662+
expression(scanner);
663+
} else {
664+
emitByte(OP_NIL);
665+
}
666+
667+
patchJump(elseJump);
668+
}
669+
645670
static void printStatement(Scanner *scanner) {
646671
TRACELN(" compiler.printStatement()");
647672

@@ -1121,7 +1146,7 @@ ParseRule rules[] = {
11211146
[TOKEN_FALSE] = {literal, NULL, PREC_NONE},
11221147
[TOKEN_FOR] = {NULL, NULL, PREC_NONE},
11231148
[TOKEN_FUN] = {NULL, NULL, PREC_NONE},
1124-
[TOKEN_IF] = {NULL, NULL, PREC_NONE},
1149+
[TOKEN_IF] = {ifExpression, NULL, PREC_NONE},
11251150
[TOKEN_NIL] = {literal, NULL, PREC_NONE},
11261151
[TOKEN_OR] = {NULL, or_, PREC_OR},
11271152
[TOKEN_QUESTION_QUESTION] = {NULL, nullish, PREC_OR},
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
print if (true) {
2+
"Hello"
3+
} else {
4+
"World"
5+
};
6+
7+
print if (false) {
8+
"Hello"
9+
} else {
10+
"World"
11+
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
== <script> ==
2+
0000 1 OP_NIL
3+
0001 | OP_RETURN
4+
== <script> ==
5+
0000 1 OP_TRUE
6+
0001 | OP_JUMP_IF_FALSE 1 -> 12
7+
0004 | OP_POP
8+
0005 2 OP_CONSTANT 0 'Hello'
9+
0007 3 OP_CLOSE_BLOCK 0
10+
0009 | OP_JUMP 9 -> 17
11+
0012 | OP_POP
12+
0013 4 OP_CONSTANT 1 'World'
13+
0015 5 OP_CLOSE_BLOCK 0
14+
0017 | OP_PRINT
15+
0018 7 OP_FALSE
16+
0019 | OP_JUMP_IF_FALSE 19 -> 30
17+
0022 | OP_POP
18+
0023 8 OP_CONSTANT 2 'Hello'
19+
0025 9 OP_CLOSE_BLOCK 0
20+
0027 | OP_JUMP 27 -> 35
21+
0030 | OP_POP
22+
0031 10 OP_CONSTANT 3 'World'
23+
0033 11 OP_CLOSE_BLOCK 0
24+
0035 | OP_PRINT
25+
0036 | OP_NIL
26+
0037 | OP_RETURN
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Hello
2+
World
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
print if (true) "Hello" else "World";
2+
3+
print if (false) "Hello" else "World";
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
== <script> ==
2+
0000 1 OP_NIL
3+
0001 | OP_RETURN
4+
== <script> ==
5+
0000 1 OP_TRUE
6+
0001 | OP_JUMP_IF_FALSE 1 -> 10
7+
0004 | OP_POP
8+
0005 | OP_CONSTANT 0 'Hello'
9+
0007 | OP_JUMP 7 -> 13
10+
0010 | OP_POP
11+
0011 | OP_CONSTANT 1 'World'
12+
0013 | OP_PRINT
13+
0014 3 OP_FALSE
14+
0015 | OP_JUMP_IF_FALSE 15 -> 24
15+
0018 | OP_POP
16+
0019 | OP_CONSTANT 2 'Hello'
17+
0021 | OP_JUMP 21 -> 27
18+
0024 | OP_POP
19+
0025 | OP_CONSTANT 3 'World'
20+
0027 | OP_PRINT
21+
0028 | OP_NIL
22+
0029 | OP_RETURN
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Hello
2+
World

0 commit comments

Comments
 (0)