Skip to content

Commit 25f8ecb

Browse files
committed
feat: add support for else statements
1 parent 5ad2213 commit 25f8ecb

5 files changed

Lines changed: 141 additions & 1 deletion

File tree

src/chunk.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ typedef enum
2626
OP_NOT,
2727
OP_NEGATE,
2828
OP_PRINT,
29+
OP_JUMP,
2930
OP_JUMP_IF_FALSE,
3031
OP_RETURN,
3132
} OpCode;

src/compiler.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,8 +590,17 @@ static void if_statement()
590590
consume(TOKEN_RIGHT_PAREN, "Expect ')' after condition");
591591

592592
int then_jump = emit_jump(OP_JUMP_IF_FALSE);
593+
emit_byte(OP_POP);
593594
statement();
595+
596+
int else_jump = emit_jump(OP_JUMP);
594597
patch_jump(then_jump);
598+
emit_byte(OP_POP);
599+
600+
if (match(TOKEN_ELSE))
601+
statement();
602+
603+
patch_jump(else_jump);
595604
}
596605

597606
static void print_statement()
@@ -647,7 +656,7 @@ static void statement()
647656
{
648657
print_statement();
649658
}
650-
else if (TOKEN_IF)
659+
else if (match(TOKEN_IF))
651660
{
652661
if_statement();
653662
}

src/debug.c

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
static int simple_instruction(const char* name, int offset);
88
static int constant_instruction(const char* name, Chunk* chunk, int offset);
99
static int byte_instruction(const char* name, Chunk* chunk, int offset);
10+
static int jump_instruction(const char* name, int sign, Chunk* chunk,
11+
int offset);
1012

1113
void disassemble_chunk(Chunk* chunk, const char* name)
1214
{
@@ -70,6 +72,10 @@ int disassemble_instruction(Chunk* chunk, int offset)
7072
return simple_instruction("OP_NEGATE", offset);
7173
case OP_PRINT:
7274
return simple_instruction("OP_PRINT", offset);
75+
case OP_JUMP:
76+
return jump_instruction("OP_JUMP", 1, chunk, offset);
77+
case OP_JUMP_IF_FALSE:
78+
return jump_instruction("OP_JUMP_IF_FALSE", 1, chunk, offset);
7379
case OP_RETURN:
7480
return simple_instruction("OP_RETURN", offset);
7581
default:
@@ -91,6 +97,15 @@ static int byte_instruction(const char* name, Chunk* chunk, int offset)
9197
return offset + 2;
9298
}
9399

100+
static int jump_instruction(const char* name, int sign, Chunk* chunk,
101+
int offset)
102+
{
103+
u16 jump = (u16)(chunk->code[offset + 1] << 8);
104+
jump |= chunk->code[offset];
105+
printf("%-16s %4d -> %d\n", name, offset, offset + 3 + sign * jump);
106+
return offset + 3;
107+
}
108+
94109
static int constant_instruction(const char* name, Chunk* chunk, int offset)
95110
{
96111
u8 constantIndex = chunk->code[offset + 1];
@@ -99,3 +114,110 @@ static int constant_instruction(const char* name, Chunk* chunk, int offset)
99114
printf("\n");
100115
return offset + 2;
101116
}
117+
118+
static const char* token_type_to_string(TokenType type)
119+
{
120+
switch (type)
121+
{
122+
case TOKEN_LEFT_PAREN:
123+
return "LEFT_PAREN";
124+
case TOKEN_RIGHT_PAREN:
125+
return "RIGHT_PAREN";
126+
case TOKEN_LEFT_BRACE:
127+
return "LEFT_BRACE";
128+
case TOKEN_RIGHT_BRACE:
129+
return "RIGHT_BRACE";
130+
case TOKEN_COMMA:
131+
return "COMMA";
132+
case TOKEN_DOT:
133+
return "DOT";
134+
case TOKEN_MINUS:
135+
return "MINUS";
136+
case TOKEN_PLUS:
137+
return "PLUS";
138+
case TOKEN_SEMICOLON:
139+
return "SEMICOLON";
140+
case TOKEN_SLASH:
141+
return "SLASH";
142+
case TOKEN_STAR:
143+
return "STAR";
144+
145+
case TOKEN_BANG:
146+
return "BANG";
147+
case TOKEN_BANG_EQUAL:
148+
return "BANG_EQUAL";
149+
case TOKEN_EQUAL:
150+
return "EQUAL";
151+
case TOKEN_EQUAL_EQUAL:
152+
return "EQUAL_EQUAL";
153+
case TOKEN_GREATER:
154+
return "GREATER";
155+
case TOKEN_GREATER_EQUAL:
156+
return "GREATER_EQUAL";
157+
case TOKEN_LESS:
158+
return "LESS";
159+
case TOKEN_LESS_EQUAL:
160+
return "LESS_EQUAL";
161+
162+
case TOKEN_IDENTIFIER:
163+
return "IDENTIFIER";
164+
case TOKEN_STRING:
165+
return "STRING";
166+
case TOKEN_NUMBER:
167+
return "NUMBER";
168+
169+
case TOKEN_AND:
170+
return "AND";
171+
case TOKEN_CLASS:
172+
return "CLASS";
173+
case TOKEN_ELSE:
174+
return "ELSE";
175+
case TOKEN_FALSE:
176+
return "FALSE";
177+
case TOKEN_FOR:
178+
return "FOR";
179+
case TOKEN_FUN:
180+
return "FUN";
181+
case TOKEN_IF:
182+
return "IF";
183+
case TOKEN_NIL:
184+
return "NIL";
185+
case TOKEN_OR:
186+
return "OR";
187+
case TOKEN_PRINT:
188+
return "PRINT";
189+
case TOKEN_RETURN:
190+
return "RETURN";
191+
case TOKEN_SUPER:
192+
return "SUPER";
193+
case TOKEN_THIS:
194+
return "THIS";
195+
case TOKEN_TRUE:
196+
return "TRUE";
197+
case TOKEN_VAR:
198+
return "VAR";
199+
case TOKEN_VAL:
200+
return "VAL";
201+
case TOKEN_WHILE:
202+
return "WHILE";
203+
204+
case TOKEN_ERROR:
205+
return "ERROR";
206+
case TOKEN_EOF:
207+
return "EOF";
208+
}
209+
210+
return "UNKNOWN";
211+
}
212+
213+
void print_token(Token token)
214+
{
215+
printf("%-15s line %-4d '", token_type_to_string(token.type), token.line);
216+
217+
for (int i = 0; i < token.length; i++)
218+
{
219+
putchar(token.start[i]);
220+
}
221+
222+
printf("'\n");
223+
}

src/debug.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
#define clox_debug_h
33

44
#include "chunk.h"
5+
#include "scanner.h"
56

67
void disassemble_chunk(Chunk* chunk, const char* name);
78
int disassemble_instruction(Chunk* chunk, int offset);
9+
void print_token(Token token);
810

911
#endif

src/vm.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,12 @@ static InterpretResult run()
238238
printf("\n");
239239
break;
240240
}
241+
case OP_JUMP:
242+
{
243+
u16 offset = READ_SHORT();
244+
vm.ip += offset;
245+
break;
246+
}
241247
case OP_JUMP_IF_FALSE:
242248
{
243249
u16 offset = READ_SHORT();

0 commit comments

Comments
 (0)