Skip to content

Commit e70bc2d

Browse files
committed
feat: add blocks and prepare for local variables
1 parent 83b6aa5 commit e70bc2d

4 files changed

Lines changed: 120 additions & 72 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ TEST_SOURCES = tests/scanner_test.c tests/compiler_test.c
99
all: clox
1010

1111
clox: src/main.c $(SOURCES)
12-
@$(CC) $(CFLAGS) -o clox src/main.c $(SOURCES) -I.
12+
@$(CC) $(CFLAGS) -o clox src/main.c $(SOURCES) -I. && echo Compiled!!!!
1313

1414
run: clox
1515
@./clox

src/common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include <stddef.h>
66
#include <stdint.h>
77

8+
#define UINT8_COUNT (UINT8_MAX + 1)
9+
810
typedef uint8_t u8;
911
typedef uint32_t u32;
1012

src/compiler.c

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,23 @@ typedef struct
4848

4949
} ParseRule;
5050

51-
Parser parser;
52-
Chunk* compiling_chunk;
51+
typedef struct
52+
{
53+
Token name;
54+
int depth;
55+
} Local;
56+
57+
typedef struct
58+
{
59+
Local locals[UINT8_COUNT];
60+
int local_count;
61+
int local_depth;
62+
63+
} Compiler;
64+
65+
Parser parser;
66+
Compiler* current;
67+
Chunk* compiling_chunk;
5368

5469
static Chunk* current_chunk()
5570
{
@@ -93,14 +108,11 @@ static void error_at_current(const char* message)
93108
static void advance()
94109
{
95110
parser.previous = parser.current;
96-
97111
for (;;)
98112
{
99113
parser.current = scan_token();
100-
101114
if (parser.current.type != TOKEN_ERROR)
102115
break;
103-
104116
error_at_current(parser.current.start);
105117
}
106118
}
@@ -112,7 +124,6 @@ static void consume(TokenType type, char* message)
112124
advance();
113125
return;
114126
}
115-
116127
error_at_current(message);
117128
}
118129

@@ -125,7 +136,6 @@ static bool match(TokenType type)
125136
{
126137
if (!check(type))
127138
return false;
128-
129139
advance();
130140
return true;
131141
}
@@ -149,13 +159,11 @@ static void emit_return()
149159
static u8 make_constant(Value value)
150160
{
151161
int constant = add_constant(current_chunk(), value);
152-
153162
if (constant > UINT8_MAX)
154163
{
155164
error("Too many constants in one chunk");
156165
return 0;
157166
}
158-
159167
return (u8)constant;
160168
}
161169

@@ -164,6 +172,13 @@ static void emit_constant(Value value)
164172
emit_bytes(OP_CONSTANT, make_constant(value));
165173
}
166174

175+
static void init_compiler(Compiler* compiler)
176+
{
177+
compiler->local_count = 0;
178+
compiler->local_depth = 0;
179+
current = compiler;
180+
}
181+
167182
static void end_compiler()
168183
{
169184
emit_return();
@@ -173,6 +188,16 @@ static void end_compiler()
173188
#endif
174189
}
175190

191+
static void begin_scope()
192+
{
193+
current->local_depth++;
194+
}
195+
196+
static void end_scope()
197+
{
198+
current->local_depth--;
199+
}
200+
176201
static void expression();
177202
static void statement();
178203
static void declaration();
@@ -284,7 +309,9 @@ static void named_variable(Token name, bool can_assign)
284309
emit_bytes(OP_SET_GLOBAL, arg);
285310
}
286311
else
312+
{
287313
emit_bytes(OP_GET_GLOBAL, arg);
314+
}
288315
}
289316

290317
static void variable(bool can_assign)
@@ -392,6 +419,16 @@ static void expression()
392419

393420
// ---------------------- statements --------------------------
394421

422+
static void block()
423+
{
424+
while (!check(TOKEN_RIGHT_BRACE) && !check(TOKEN_EOF))
425+
{
426+
declaration();
427+
}
428+
429+
consume(TOKEN_RIGHT_BRACE, "Expect '}' after block");
430+
}
431+
395432
static void var_declaration()
396433
{
397434
u8 global = parse_variable("Expect variable name");
@@ -462,9 +499,19 @@ static void declaration()
462499
static void statement()
463500
{
464501
if (match(TOKEN_PRINT))
502+
{
465503
print_statement();
504+
}
505+
else if (match(TOKEN_LEFT_BRACE))
506+
{
507+
begin_scope();
508+
block();
509+
end_scope();
510+
}
466511
else
512+
{
467513
expression_statement();
514+
}
468515
}
469516

470517
static inline void init_parser()
@@ -476,6 +523,8 @@ static inline void init_parser()
476523
bool compile(const char* source, Chunk* chunk)
477524
{
478525
init_scanner(source);
526+
Compiler compiler;
527+
init_compiler(&compiler);
479528
compiling_chunk = chunk;
480529
init_parser();
481530

src/main.c

Lines changed: 59 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4,72 +4,14 @@
44

55
#include "vm.h"
66

7-
static void repl()
8-
{
9-
char line[1024];
10-
11-
for (;;)
12-
{
13-
printf("> ");
14-
if (!fgets(line, sizeof(line), stdin))
15-
{
16-
printf("\n");
17-
break;
18-
}
19-
interpret(line);
20-
}
21-
}
22-
23-
static char* read_file(const char* path)
24-
{
25-
FILE* fd = fopen(path, "rb");
26-
if (fd == NULL)
27-
{
28-
fprintf(stderr, "Could not open file %s \n", path);
29-
exit(74);
30-
}
31-
32-
fseek(fd, 0L, SEEK_END);
33-
size_t fileSize = ftell(fd);
34-
rewind(fd);
35-
36-
char* buffer = (char*)malloc(fileSize + 1);
37-
if (buffer == NULL)
38-
{
39-
fprintf(stderr, "Not enough memory to read %s \n", path);
40-
exit(74);
41-
}
42-
43-
size_t bytesRead = fread(buffer, sizeof(char), fileSize, fd);
44-
if (bytesRead < fileSize)
45-
{
46-
fprintf(stderr, "Could not read file %s \n", path);
47-
exit(74);
48-
}
49-
50-
buffer[bytesRead] = '\0';
51-
52-
fclose(fd);
53-
54-
return buffer;
55-
}
7+
static void repl();
8+
static char* read_file(const char* path);
9+
static void run_file(const char* path);
5610

57-
static void run_file(const char* path)
58-
{
59-
char* source = read_file(path);
60-
InterpretResult result = interpret(source);
61-
free(source);
62-
63-
if (result == INTERPRET_COMPILE_ERROR)
64-
exit(65);
65-
if (result == INTERPRET_RUNTIME_ERROR)
66-
exit(70);
67-
}
6811

6912
int main(int argc, const char* argv[])
7013
{
7114
init_VM();
72-
7315
if (argc == 1)
7416
repl();
7517
else if (argc == 2)
@@ -79,7 +21,62 @@ int main(int argc, const char* argv[])
7921
fprintf(stderr, "Usage: clox [path]\n");
8022
exit(64);
8123
}
82-
8324
free_VM();
8425
return 0;
8526
}
27+
28+
static void repl()
29+
{
30+
char line[1024];
31+
for (;;)
32+
{
33+
printf("> ");
34+
if (!fgets(line, sizeof(line), stdin))
35+
{
36+
printf("\n");
37+
break;
38+
}
39+
interpret(line);
40+
}
41+
}
42+
43+
static char* read_file(const char* path)
44+
{
45+
FILE* fd = fopen(path, "rb");
46+
if (fd == NULL)
47+
{
48+
fprintf(stderr, "Could not open file %s \n", path);
49+
exit(74);
50+
}
51+
fseek(fd, 0L, SEEK_END);
52+
size_t fileSize = ftell(fd);
53+
rewind(fd);
54+
55+
char* buffer = (char*)malloc(fileSize + 1);
56+
if (buffer == NULL)
57+
{
58+
fprintf(stderr, "Not enough memory to read %s \n", path);
59+
exit(74);
60+
}
61+
size_t bytesRead = fread(buffer, sizeof(char), fileSize, fd);
62+
if (bytesRead < fileSize)
63+
{
64+
fprintf(stderr, "Could not read file %s \n", path);
65+
exit(74);
66+
}
67+
buffer[bytesRead] = '\0';
68+
fclose(fd);
69+
return buffer;
70+
}
71+
72+
static void run_file(const char* path)
73+
{
74+
char* source = read_file(path);
75+
InterpretResult result = interpret(source);
76+
free(source);
77+
78+
if (result == INTERPRET_COMPILE_ERROR)
79+
exit(65);
80+
if (result == INTERPRET_RUNTIME_ERROR)
81+
exit(70);
82+
}

0 commit comments

Comments
 (0)