aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bench/fib.bad12
-rw-r--r--bench/fib.py5
-rw-r--r--bench/life.bad71
-rw-r--r--bench/rule110.bad39
-rw-r--r--bench/rule110.py29
-rw-r--r--src/badlib.h6
-rw-r--r--src/compiler.c1462
-rw-r--r--src/lexer.c148
-rw-r--r--src/main.c98
-rw-r--r--src/parser.c395
-rw-r--r--src/semantic.c509
-rw-r--r--src/vm.c262
-rw-r--r--tests/compilation.bad57
-rw-r--r--tests/conditionals.bad4
-rw-r--r--tests/semantics.bad7
15 files changed, 2434 insertions, 670 deletions
diff --git a/bench/fib.bad b/bench/fib.bad
new file mode 100644
index 0000000..ae7c729
--- /dev/null
+++ b/bench/fib.bad
@@ -0,0 +1,12 @@
1let n = 1000
2let a = 0.0
3let b = 1.0
4let i = 0
5while i < n {
6 let tmp = a + b
7 set a = b
8 set b = tmp
9 set i = i + 1
10}
11
12a
diff --git a/bench/fib.py b/bench/fib.py
new file mode 100644
index 0000000..ceb7406
--- /dev/null
+++ b/bench/fib.py
@@ -0,0 +1,5 @@
1n = 1000
2a, b = 0.0, 1.0
3for i in range(0, n):
4 a, b = b, a + b
5print(a)
diff --git a/bench/life.bad b/bench/life.bad
new file mode 100644
index 0000000..4dcabff
--- /dev/null
+++ b/bench/life.bad
@@ -0,0 +1,71 @@
1; This board is 8 * 8 = 64 cells.
2; let n_cells = 64
3; let board_a: int[64]
4; let board_b: int[64]
5; let stride = 8
6
7; This board is 32 * 32 = 1024 cells.
8let n_cells = 1024
9let board_a: int[1024]
10let board_b: int[1024]
11let stride = 32
12
13; Storing pointers to the front/backbuffer to avoid copying the board over.
14let front = board_a
15let back = board_b
16
17; Initialize glider
18set front[stride * 2 + 5] = 1
19set front[stride * 3 + 6] = 1
20set front[stride * 4 + 4] = 1
21set front[stride * 4 + 5] = 1
22set front[stride * 4 + 6] = 1
23
24fun print_board(board: @int): nil {
25 for let i = 0 , i < n_cells , set i += 1 {
26 if i % stride == 0 {
27 println("")
28 }
29 if board[i] == 1 print("■ ")
30 else print("· ")
31 }
32 println("")
33}
34
35fun update_board(): nil {
36 for let i = 0 , i < n_cells , set i += 1 {
37 let left = if i > 0 front[i - 1] else 0
38 let right = if i < n_cells - 1 front[i + 1] else 0
39 let top = if i >= stride front[i - stride] else 0
40 let topleft = if i >= stride front[i - stride - 1] else 0
41 let topright = if i >= stride front[i - stride + 1] else 0
42 let bot = if i <= n_cells - stride front[i + stride] else 0
43 let botleft = if i <= n_cells - stride front[i + stride - 1] else 0
44 let botright = if i <= n_cells - stride front[i + stride + 1] else 0
45
46 let neig = left
47 + right
48 + top
49 + bot
50 + topleft
51 + topright
52 + botleft
53 + botright
54
55 cond {
56 front[i] == 0 && neig == 3 = set back[i] = 1
57 front[i] == 1 && (neig == 2 || neig == 3) = set back[i] = 1
58 else = set back[i] = 0
59 }
60 }
61
62 ; Swap boards.
63 let tmp = front
64 set front = back
65 set back = tmp
66}
67
68for let n_iter = 100 , n_iter > 0 , set n_iter -= 1 {
69 print_board(front)
70 update_board()
71}
diff --git a/bench/rule110.bad b/bench/rule110.bad
new file mode 100644
index 0000000..b4a2a71
--- /dev/null
+++ b/bench/rule110.bad
@@ -0,0 +1,39 @@
1; Parameters.
2let line = 0b00000000000000000000000000000001
3let max_iter = 30
4
5; Print current line.
6fun print_line(line: int): nil {
7 for let i = 0 , i < 64 , set i += 1 {
8 let val = line >> 63 - i & 0b1
9 if val == 0b1 {
10 print("■ ")
11 } else {
12 print("· ")
13 }
14 }
15 println("")
16}
17
18; Get the next line.
19fun next_line(line: int): int {
20 let next = 0
21 for let j = 0 , j < 61 , set j += 1 {
22 let val = line >> 60 - j & 0b111
23 set val = cond {
24 val == 1 = 1
25 val == 2 = 1
26 val == 3 = 1
27 val == 5 = 1
28 val == 6 = 1
29 else = 0
30 }
31 set next |= val << 61 - j
32 }
33 next | 1
34}
35
36for let iter = 0 , iter < max_iter , set iter += 1 {
37 print_line(line)
38 set line = next_line(line)
39}
diff --git a/bench/rule110.py b/bench/rule110.py
new file mode 100644
index 0000000..eddcdbe
--- /dev/null
+++ b/bench/rule110.py
@@ -0,0 +1,29 @@
1line = 0b00000000000000000000000000000001
2max_iter = 30
3
4for iter in range(0, max_iter):
5 for i in range(0, 64):
6 val = line >> 63 - i & 0b1
7 if val == 0b1:
8 print("■", end=" ")
9 else:
10 print("·", end=" ")
11 print("")
12
13 next = 0
14 for j in range(0, 61):
15 val = line >> 60 - j & 0b111
16 if val == 1:
17 val = 1
18 elif val == 2:
19 val = 1
20 elif val == 3:
21 val = 1
22 elif val == 5:
23 val = 1
24 elif val == 6:
25 val = 1
26 else:
27 val = 0
28 next = next | val << 61 - j
29 line = next | 1
diff --git a/src/badlib.h b/src/badlib.h
index 73e03db..c73b57f 100644
--- a/src/badlib.h
+++ b/src/badlib.h
@@ -347,7 +347,9 @@ str_split_fn(Str *a, StrSplitFn split_fn) {
347void 347void
348str_replace(Str *a, Str from, Str to) { 348str_replace(Str *a, Str from, Str to) {
349 assert(a != NULL); 349 assert(a != NULL);
350 assert(from.size == to.size); 350 if (from.size != to.size) {
351 return;
352 }
351 SearchResult res = array_find_next(*a, from); 353 SearchResult res = array_find_next(*a, from);
352 if (res.found) { 354 if (res.found) {
353 memcpy(a->mem + res.pos, to.mem, res.matched); 355 memcpy(a->mem + res.pos, to.mem, res.matched);
@@ -1498,7 +1500,7 @@ void
1498log_func_memory(Logger *l, void *in) { 1500log_func_memory(Logger *l, void *in) {
1499 assert(l); 1501 assert(l);
1500 Array *val = in; 1502 Array *val = in;
1501 for (sz i = 0; i < MIN(64, val->size); i++) { 1503 for (sz i = 0; i < MIN(256, val->size); i++) {
1502 Arena scratch = l->storage; 1504 Arena scratch = l->storage;
1503 log_str(l, str_from_hex(val->mem[i], 2, &scratch)); 1505 log_str(l, str_from_hex(val->mem[i], 2, &scratch));
1504 if ((i + 1) % 16 == 0) { 1506 if ((i + 1) % 16 == 0) {
diff --git a/src/compiler.c b/src/compiler.c
index 0f9607e..c2b48b3 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -25,7 +25,7 @@ typedef struct Instruction {
25typedef union Constant { 25typedef union Constant {
26 s64 i; 26 s64 i;
27 u64 u; 27 u64 u;
28 double f; 28 f64 f;
29 ptrsize ptr; 29 ptrsize ptr;
30} Constant; 30} Constant;
31 31
@@ -34,9 +34,23 @@ typedef struct LineCol {
34 sz col; 34 sz col;
35} LineCol; 35} LineCol;
36 36
37typedef struct Function {
38 Str name;
39 sz param_arity;
40 sz return_arity;
41 sz index;
42} Function;
43
44MAPDEF(FunctionMap, funcmap, Str, Function, str_hash, str_eq)
45
37typedef struct Chunk { 46typedef struct Chunk {
38 sz id; 47 sz id;
48 Str name;
49 struct Chunk *parent;
50
39 Instruction *code; 51 Instruction *code;
52 IntIntMap *labels; // label -> chunk_index
53 sz labels_idx;
40 54
41 // Constant values that fit in 64 bits. 55 // Constant values that fit in 64 bits.
42 Constant *constants; 56 Constant *constants;
@@ -52,45 +66,91 @@ typedef struct Chunk {
52 Variable *vars; 66 Variable *vars;
53 StrVarMap *varmap; 67 StrVarMap *varmap;
54 sz var_off; 68 sz var_off;
69 sz param_off;
55 70
56 // Number of registers currently used in this chunk. 71 // Number of registers currently used in this chunk.
57 sz reg_idx; 72 sz reg_idx;
58 73
74 // Number of functions currently used in this chunk.
75 struct Chunk **functions;
76 FunctionMap *funmap;
77 sz fun_idx;
78
59 // Debugging. 79 // Debugging.
60 Str file_name; 80 Str file_name;
61 Arena *storage; 81 Arena *storage;
62 LineCol *linecol; 82 LineCol *linecol;
63} Chunk; 83} Chunk;
64 84
85typedef struct Compiler {
86 Chunk main_chunk;
87 Str file_name;
88 Arena *storage;
89
90 // Tables.
91 StrSet *integer_types;
92 StrSet *numeric_types;
93
94 // Destinations.
95 sz lab_pre;
96 sz lab_post;
97} Compiler;
98
65typedef enum OpCode { 99typedef enum OpCode {
66 // OP DST A B 100 // OP DST A B
67 // --------------------------------------------------------------- 101 // ---------------------------------------------------------------
68 // VM/high level instructions. 102 // VM/high level instructions.
69 OP_HALT, // halt 103 OP_HALT, // halt
104 // NOTE: LDGVAR/STGVAR* could be obtained in terms of LDGADDR.
70 OP_STGVARI, // stgvari vx, ca 105 OP_STGVARI, // stgvari vx, ca
71 OP_STGVAR, // stgvar vx, ra 106 OP_STGVAR, // stgvar vx, ra
72 OP_LDGVAR, // ldgvar rx, vx 107 OP_LDGVAR, // ldgvar rx, va
108 OP_LDGADDR, // ldgaddr rx, va
109 OP_STLVARI, // stlvari vx, ca
110 OP_STLVAR, // stlvar vx, ra
111 OP_LDLVAR, // ldlvar rx, va
112 OP_LDLADDR, // ldladdr rx, va
113 OP_LDSTR, // ldstr rx, sa ; Stores the address of the string sa into rx
114 // Functions.
115 OP_CALL, // call fx ; Call the function fx
116 OP_RECUR, // recur ; Jump to the beginning of the function.
117 OP_RET, // ret ; Returns from current function
118 OP_RESERVE, // reserve cx ; Increments the stack pointer by cx bytes
119 OP_POP, // pop rx ; Pops the last value of the stack into rx.
120 OP_PUSH, // push rx ; Push the rx value to the stack.
121 OP_PUSHI, // pushi cx ; Push the cx value to the stack.
122 OP_PUTRET, // putret rx ; Put rx into the return value memory.
123 OP_PUTRETI, // putreti cx ; Put cx into the return value memory.
124 // Printing values with builtin print/println functions.
125 OP_PRINTSTR, // p rx
126 OP_PRINTSTRI, // p cx
127 OP_PRINTS64, // p rx
128 OP_PRINTS64I, // p cx
129 OP_PRINTF64, // p rx
130 OP_PRINTF64I, // p cx
131 OP_PRINTBOOL, // p rx
132 OP_PRINTBOOLI, // p cx
73 // Load/Store instructions. 133 // Load/Store instructions.
74 OP_LD8K, // ld8k rx, ca -> u8 rx = ca 134 OP_LD8K, // ld8k rx, ca -> u8 rx = ca
75 OP_LD16K, // ld16k rx, ca -> u16 rx = ca 135 OP_LD16K, // ld16k rx, ca -> u16 rx = ca
76 OP_LD32K, // ld32k rx, ca -> u32 rx = ca 136 OP_LD32K, // ld32k rx, ca -> u32 rx = ca
77 OP_LD64K, // ld64k rx, ca -> u64 rx = ca 137 OP_LD64K, // ld64k rx, ca -> u64 rx = ca
78 OP_LD8I, // ld8i rx, ra, cb -> u8 *p; rx = p[ra + cb] 138 OP_LD8I, // ld8i rx, ra, cb -> u8 *p = ra; rx = p[cb]
79 OP_LD16I, // ld16i rx, ra, cb -> u16 *p; rx = p[ra + cb] 139 OP_LD16I, // ld16i rx, ra, cb -> u16 *p = ra; rx = p[cb]
80 OP_LD32I, // ld32i rx, ra, cb -> u32 *p; rx = p[ra + cb] 140 OP_LD32I, // ld32i rx, ra, cb -> u32 *p = ra; rx = p[cb]
81 OP_LD64I, // ld64i rx, ra, cb -> u64 *p; rx = p[ra + cb] 141 OP_LD64I, // ld64i rx, ra, cb -> u64 *p = ra; rx = p[cb]
82 OP_LD8, // ld8 rx, ra, rb -> u8 *p; rx = p[ra + rb] 142 OP_LD8, // ld8 rx, ra, rb -> u8 *p = ra; rx = p[rb]
83 OP_LD16, // ld16 rx, ra, rb -> u16 *p; rx = p[ra + rb] 143 OP_LD16, // ld16 rx, ra, rb -> u16 *p = ra; rx = p[rb]
84 OP_LD32, // ld32 rx, ra, rb -> u32 *p; rx = p[ra + rb] 144 OP_LD32, // ld32 rx, ra, rb -> u32 *p = ra; rx = p[rb]
85 OP_LD64, // ld64 rx, ra, rb -> u64 *p; rx = p[ra + rb] 145 OP_LD64, // ld64 rx, ra, rb -> u64 *p = ra; rx = p[rb]
86 OP_ST8I, // st8i rx, ra, cb -> u8 *p; p[ra + cb] = rx 146 OP_ST8I, // st8i rx, ra, cb -> u8 *p = ra; p[cb] = rx
87 OP_ST16I, // st16i rx, ra, cb -> u16 *p; p[ra + cb] = rx 147 OP_ST16I, // st16i rx, ra, cb -> u16 *p = ra; p[cb] = rx
88 OP_ST32I, // st32i rx, ra, cb -> u32 *p; p[ra + cb] = rx 148 OP_ST32I, // st32i rx, ra, cb -> u32 *p = ra; p[cb] = rx
89 OP_ST64I, // st64i rx, ra, cb -> u64 *p; p[ra + cb] = rx 149 OP_ST64I, // st64i rx, ra, cb -> u64 *p = ra; p[cb] = rx
90 OP_ST8, // st8 rx, ra, rb -> u8 *p; p[ra + rb] = rx 150 OP_ST8, // st8 rx, ra, rb -> u8 *p = ra; p[rb] = rx
91 OP_ST16, // st16 rx, ra, rb -> u16 *p; p[ra + rb] = rx 151 OP_ST16, // st16 rx, ra, rb -> u16 *p = ra; p[rb] = rx
92 OP_ST32, // st32 rx, ra, rb -> u32 *p; p[ra + rb] = rx 152 OP_ST32, // st32 rx, ra, rb -> u32 *p = ra; p[rb] = rx
93 OP_ST64, // st64 rx, ra, rb -> u64 *p; p[ra + rb] = rx 153 OP_ST64, // st64 rx, ra, rb -> u64 *p = ra; p[rb] = rx
94 // Integer arithmetic (only int/s64 for now). 154 // Integer arithmetic (only int/s64 for now).
95 OP_ADDI, // addk rx, ra, cb 155 OP_ADDI, // addk rx, ra, cb
96 OP_SUBI, // subk rx, ra, cb 156 OP_SUBI, // subk rx, ra, cb
@@ -142,26 +202,52 @@ typedef enum OpCode {
142 OP_BITRSHIFTI, // shri rx, ra, cb 202 OP_BITRSHIFTI, // shri rx, ra, cb
143 OP_BITANDI, // bandi rx, ra, cb 203 OP_BITANDI, // bandi rx, ra, cb
144 OP_BITORI, // bori rx, ra, cb 204 OP_BITORI, // bori rx, ra, cb
205 OP_BITXORI, // bxor rx, ra, cb
145 OP_BITNOTI, // bnoti rx, ca 206 OP_BITNOTI, // bnoti rx, ca
146 OP_BITLSHIFT, // shl rx, ra, rb 207 OP_BITLSHIFT, // shl rx, ra, rb
147 OP_BITRSHIFT, // shr rx, ra, rb 208 OP_BITRSHIFT, // shr rx, ra, rb
148 OP_BITAND, // band rx, ra, rb 209 OP_BITAND, // band rx, ra, rb
149 OP_BITOR, // bor rx, ra, rb 210 OP_BITOR, // bor rx, ra, rb
211 OP_BITXOR, // bxor rx, ra, rb
150 OP_BITNOT, // bnot rx, ra 212 OP_BITNOT, // bnot rx, ra
151 // Jump instructions. 213 // Jump instructions.
152 OP_JMPI, // jmp cx ; cx := signed offset 214 OP_JMP, // jmp lx ; jmp to label lx
153 OP_JMPFI, // jmpf cx, ca ; rx := condition, ca := offset 215 OP_JMPF, // jmpf lx, rx ; jmp to label lx if rx is false
154 OP_JMPTI, // jmpt cx, ca ; rx := condition, ca := offset 216 OP_JMPT, // jmpt lx, rx ; jmp to label lx if rx is true
155 OP_JMP, // jmp rx ; rx := signed offset 217 OP_JMPFI, // jmpf lx, cx ; jmp to label lx if rx is false
156 OP_JMPF, // jmpf rx, ca ; rx := condition, ca := offset 218 OP_JMPTI, // jmpt lx, cx ; jmp to label lx if rx is true
157 OP_JMPT, // jmpt rx, ca ; rx := condition, ca := offset
158} OpCode; 219} OpCode;
159 220
160Str op_str[] = { 221Str op_str[] = {
222 // High level ops.
161 [OP_HALT] = cstr("HALT "), 223 [OP_HALT] = cstr("HALT "),
162 [OP_STGVAR] = cstr("STGVAR "), 224 [OP_STGVAR] = cstr("STGVAR "),
163 [OP_STGVARI] = cstr("STGVARI "), 225 [OP_STGVARI] = cstr("STGVARI "),
164 [OP_LDGVAR] = cstr("LDGVAR "), 226 [OP_LDGVAR] = cstr("LDGVAR "),
227 [OP_LDGADDR] = cstr("LDGADDR "),
228 [OP_STLVAR] = cstr("STLVAR "),
229 [OP_STLVARI] = cstr("STLVARI "),
230 [OP_LDLVAR] = cstr("LDLVAR "),
231 [OP_LDLADDR] = cstr("LDLADDR "),
232 [OP_LDSTR] = cstr("LDSTR "),
233 [OP_PRINTSTR] = cstr("PRNSTR "),
234 [OP_PRINTSTRI] = cstr("PRNSTRI "),
235 [OP_PRINTS64] = cstr("PRNS64 "),
236 [OP_PRINTS64I] = cstr("PRNS64I "),
237 [OP_PRINTF64] = cstr("PRNF64 "),
238 [OP_PRINTF64I] = cstr("PRNF64I "),
239 [OP_PRINTBOOL] = cstr("PRNBOOL "),
240 [OP_PRINTBOOLI] = cstr("PRNBOOLI"),
241 [OP_PUTRET] = cstr("PUTRET "),
242 [OP_PUTRETI] = cstr("PUTRETI "),
243 // Functions.
244 [OP_CALL] = cstr("CALL "),
245 [OP_RECUR] = cstr("RECUR "),
246 [OP_RET] = cstr("RET "),
247 [OP_RESERVE] = cstr("RESERVE "),
248 [OP_POP] = cstr("POP "),
249 [OP_PUSH] = cstr("PUSH "),
250 [OP_PUSHI] = cstr("PUSHI "),
165 // Load ops. 251 // Load ops.
166 [OP_LD8K] = cstr("LD8K "), 252 [OP_LD8K] = cstr("LD8K "),
167 [OP_LD16K] = cstr("LD16K "), 253 [OP_LD16K] = cstr("LD16K "),
@@ -234,19 +320,20 @@ Str op_str[] = {
234 [OP_BITRSHIFTI] = cstr("RSHI "), 320 [OP_BITRSHIFTI] = cstr("RSHI "),
235 [OP_BITANDI] = cstr("BANDI "), 321 [OP_BITANDI] = cstr("BANDI "),
236 [OP_BITORI] = cstr("BORI "), 322 [OP_BITORI] = cstr("BORI "),
323 [OP_BITXORI] = cstr("BXORI "),
237 [OP_BITNOTI] = cstr("BNOTI "), 324 [OP_BITNOTI] = cstr("BNOTI "),
238 [OP_BITLSHIFT] = cstr("LSH "), 325 [OP_BITLSHIFT] = cstr("LSH "),
239 [OP_BITRSHIFT] = cstr("RSH "), 326 [OP_BITRSHIFT] = cstr("RSH "),
240 [OP_BITAND] = cstr("BAND "), 327 [OP_BITAND] = cstr("BAND "),
241 [OP_BITOR] = cstr("BOR "), 328 [OP_BITOR] = cstr("BOR "),
329 [OP_BITXOR] = cstr("XBOR "),
242 [OP_BITNOT] = cstr("BNOT "), 330 [OP_BITNOT] = cstr("BNOT "),
243 // Jump instructions. 331 // Jump instructions.
244 [OP_JMPI] = cstr("JMPI "),
245 [OP_JMPFI] = cstr("JMPFI "),
246 [OP_JMPTI] = cstr("JMPTI "),
247 [OP_JMP] = cstr("JMP "), 332 [OP_JMP] = cstr("JMP "),
248 [OP_JMPF] = cstr("JMPF "), 333 [OP_JMPF] = cstr("JMPF "),
249 [OP_JMPT] = cstr("JMPT "), 334 [OP_JMPT] = cstr("JMPT "),
335 [OP_JMPFI] = cstr("JMPFI "),
336 [OP_JMPTI] = cstr("JMPTI "),
250}; 337};
251 338
252typedef enum { 339typedef enum {
@@ -254,6 +341,7 @@ typedef enum {
254 COMP_CONST, 341 COMP_CONST,
255 COMP_STRING, 342 COMP_STRING,
256 COMP_REG, 343 COMP_REG,
344 COMP_RET,
257 COMP_ERR, 345 COMP_ERR,
258} CompResultType; 346} CompResultType;
259 347
@@ -262,23 +350,108 @@ typedef struct CompResult {
262 CompResultType type; 350 CompResultType type;
263} CompResult; 351} CompResult;
264 352
265CompResult compile_expr(Chunk *chunk, Node *node); 353CompResult compile_expr(Compiler *compiler, Chunk *chunk, Node *node);
266 354
267#define EMIT_OP(OP, DST, A, B, NODE, CHUNK) \ 355sz
268 do { \ 356add_constant(Chunk *chunk, sz value) {
269 Instruction inst = (Instruction){ \ 357 IntIntMap *map = intintmap_lookup(&chunk->intmap, value);
270 .op = (OP), \ 358 // Make sure we don't have duplicated constants.
271 .dst = (DST), \ 359 if (!map) {
272 .a = (A), \ 360 map = intintmap_insert(&chunk->intmap, value, chunk->const_idx++,
273 .b = (B), \ 361 chunk->storage);
274 }; \ 362 Constant c = (Constant){.i = value};
275 array_push((CHUNK)->code, inst, (CHUNK)->storage); \ 363 array_push(chunk->constants, c, chunk->storage);
276 LineCol linecol = (LineCol){.line = (NODE)->line, .col = (NODE)->col}; \ 364 }
277 array_push((CHUNK)->linecol, linecol, (CHUNK)->storage); \ 365 return map->val;
278 } while (0) 366}
367
368sz
369add_string(Chunk *chunk, Str string) {
370 // Make sure we don't have duplicated string.
371 StrIntMap *map = strintmap_lookup(&chunk->strmap, string);
372 if (!map) {
373 map = strintmap_insert(&chunk->strmap, string, chunk->str_idx++,
374 chunk->storage);
375 array_push(chunk->strings, string, chunk->storage);
376 }
377 return map->val;
378}
379
380sz
381add_variable(Chunk *chunk, Str name, Str type, sz arr_size) {
382 sz idx = array_size(chunk->vars);
383 sz size = 8;
384 // TODO: get type storage from a table to consider all the basic
385 // types as well as user defined ones.
386 if (str_eq(type, cstr("str"))) {
387 size = 16;
388 }
389 if (arr_size) {
390 // TODO: get the proper storage size for the multiplication.
391 size *= arr_size;
392 // FIXME: this should be done on the static analysis, plus,
393 // we shouldn't be checking all these types by hand, but
394 // using the symbol tables.
395 type = str_remove_prefix(type, cstr("@"));
396 type = str_concat(cstr("[]"), type, chunk->storage);
397 }
398 Variable var = (Variable){
399 .name = name,
400 .type = type,
401 .size = size,
402 .offset = chunk->var_off,
403 .idx = idx,
404 };
405 varmap_insert(&chunk->varmap, name, var, chunk->storage);
406 array_push(chunk->vars, var, chunk->storage);
407 chunk->var_off += size;
408 return idx;
409}
410
411void
412emit_op(OpCode op, sz dst, sz a, sz b, Node *node, Chunk *chunk) {
413 Instruction inst = (Instruction){
414 .op = op,
415 .dst = dst,
416 .a = a,
417 .b = b,
418 };
419 array_push(chunk->code, inst, chunk->storage);
420 LineCol linecol = (LineCol){0};
421 if (node) {
422 linecol = (LineCol){.line = node->line, .col = node->col};
423 }
424 array_push(chunk->linecol, linecol, chunk->storage);
425}
426
427void
428emit_fat_copy(Chunk *chunk, Node *node, sz dst_addr, sz src_addr) {
429 sz reg_dst = chunk->reg_idx++;
430
431 // Store the fat string pointer into the variable.
432 sz zero = add_constant(chunk, 0);
433 sz one = add_constant(chunk, 1);
434
435 // Get the value for the first word of the string
436 // pointer.
437 emit_op(OP_LD64I, reg_dst, src_addr, zero, node, chunk);
438 emit_op(OP_ST64I, reg_dst, dst_addr, zero, node, chunk);
439 emit_op(OP_LD64I, reg_dst, src_addr, one, node, chunk);
440 emit_op(OP_ST64I, reg_dst, dst_addr, one, node, chunk);
441}
442
443void disassemble_chunk(Chunk chunk);
444
445void
446emit_compile_err(Compiler *compiler, Chunk *chunk, Node *node) {
447 disassemble_chunk(*chunk);
448 eprintln("%s:%d:%d: error: compilation error on: %s", compiler->file_name,
449 node->line, node->col, node_str[node->kind]);
450 exit(EXIT_FAILURE);
451}
279 452
280CompResult 453CompResult
281compile_binary(Chunk *chunk, Node *node) { 454compile_binary(Compiler *compiler, Chunk *chunk, Node *node) {
282 OpCode op = OP_HALT; 455 OpCode op = OP_HALT;
283 OpCode opi = OP_HALT; 456 OpCode opi = OP_HALT;
284 OpCode ldop = OP_LD64K; 457 OpCode ldop = OP_LD64K;
@@ -367,6 +540,10 @@ compile_binary(Chunk *chunk, Node *node) {
367 op = OP_BITOR; 540 op = OP_BITOR;
368 opi = OP_BITORI; 541 opi = OP_BITORI;
369 } break; 542 } break;
543 case NODE_BITXOR: {
544 op = OP_BITXOR;
545 opi = OP_BITXORI;
546 } break;
370 case NODE_BITAND: { 547 case NODE_BITAND: {
371 op = OP_BITAND; 548 op = OP_BITAND;
372 opi = OP_BITANDI; 549 opi = OP_BITANDI;
@@ -381,19 +558,20 @@ compile_binary(Chunk *chunk, Node *node) {
381 } break; 558 } break;
382 default: break; 559 default: break;
383 } 560 }
384 CompResult comp_a = compile_expr(chunk, node->left); 561 CompResult comp_a = compile_expr(compiler, chunk, node->binary.left);
385 CompResult comp_b = compile_expr(chunk, node->right); 562 CompResult comp_b = compile_expr(compiler, chunk, node->binary.right);
386 sz reg_a; 563 sz reg_a;
387 sz reg_b; 564 sz reg_b;
388 switch (comp_a.type) { 565 switch (comp_a.type) {
389 case COMP_CONST: { 566 case COMP_CONST: {
390 reg_a = chunk->reg_idx++; 567 reg_a = chunk->reg_idx++;
391 EMIT_OP(ldop, reg_a, comp_a.idx, 0, node, chunk); 568 emit_op(ldop, reg_a, comp_a.idx, 0, node, chunk);
392 } break; 569 } break;
393 case COMP_REG: { 570 case COMP_REG: {
394 reg_a = comp_a.idx; 571 reg_a = comp_a.idx;
395 } break; 572 } break;
396 default: { 573 default: {
574 emit_compile_err(compiler, chunk, node);
397 return (CompResult){.type = COMP_ERR}; 575 return (CompResult){.type = COMP_ERR};
398 } break; 576 } break;
399 } 577 }
@@ -406,16 +584,17 @@ compile_binary(Chunk *chunk, Node *node) {
406 reg_b = comp_b.idx; 584 reg_b = comp_b.idx;
407 } break; 585 } break;
408 default: { 586 default: {
587 emit_compile_err(compiler, chunk, node);
409 return (CompResult){.type = COMP_ERR}; 588 return (CompResult){.type = COMP_ERR};
410 } break; 589 } break;
411 } 590 }
412 sz reg_dst = chunk->reg_idx++; // Better for optimization 591 sz reg_dst = chunk->reg_idx++; // Better for optimization
413 EMIT_OP(op, reg_dst, reg_a, reg_b, node, chunk); 592 emit_op(op, reg_dst, reg_a, reg_b, node, chunk);
414 return (CompResult){.type = COMP_REG, .idx = reg_dst}; 593 return (CompResult){.type = COMP_REG, .idx = reg_dst};
415} 594}
416 595
417CompResult 596CompResult
418compile_unary(Chunk *chunk, Node *node) { 597compile_unary(Compiler *compiler, Chunk *chunk, Node *node) {
419 OpCode op = OP_HALT; 598 OpCode op = OP_HALT;
420 OpCode opi = OP_HALT; 599 OpCode opi = OP_HALT;
421 switch (node->kind) { 600 switch (node->kind) {
@@ -429,7 +608,7 @@ compile_unary(Chunk *chunk, Node *node) {
429 } break; 608 } break;
430 default: break; 609 default: break;
431 } 610 }
432 CompResult comp_a = compile_expr(chunk, node->left); 611 CompResult comp_a = compile_expr(compiler, chunk, node->binary.left);
433 sz reg_a; 612 sz reg_a;
434 switch (comp_a.type) { 613 switch (comp_a.type) {
435 case COMP_CONST: { 614 case COMP_CONST: {
@@ -440,30 +619,18 @@ compile_unary(Chunk *chunk, Node *node) {
440 reg_a = comp_a.idx; 619 reg_a = comp_a.idx;
441 } break; 620 } break;
442 default: { 621 default: {
622 emit_compile_err(compiler, chunk, node);
443 return (CompResult){.type = COMP_ERR}; 623 return (CompResult){.type = COMP_ERR};
444 } break; 624 } break;
445 } 625 }
446 sz reg_dst = chunk->reg_idx++; 626 sz reg_dst = chunk->reg_idx++;
447 EMIT_OP(op, reg_dst, reg_a, 0, node, chunk); 627 emit_op(op, reg_dst, reg_a, 0, node, chunk);
448 return (CompResult){.type = COMP_REG, .idx = reg_dst}; 628 return (CompResult){.type = COMP_REG, .idx = reg_dst};
449} 629}
450 630
451sz
452add_constant(Chunk *chunk, sz value) {
453 IntIntMap *map = intintmap_lookup(&chunk->intmap, value);
454 // Make sure we don't have duplicated constants.
455 if (!map) {
456 map = intintmap_insert(&chunk->intmap, value, chunk->const_idx++,
457 chunk->storage);
458 Constant c = (Constant){.i = value};
459 array_push(chunk->constants, c, chunk->storage);
460 }
461 return map->val;
462}
463
464CompResult 631CompResult
465compile_if(Chunk *chunk, Node *node) { 632compile_if(Compiler *compiler, Chunk *chunk, Node *node) {
466 CompResult cond = compile_expr(chunk, node->cond_if); 633 CompResult cond = compile_expr(compiler, chunk, node->ifelse.cond);
467 OpCode jmpop; 634 OpCode jmpop;
468 switch (cond.type) { 635 switch (cond.type) {
469 case COMP_CONST: { 636 case COMP_CONST: {
@@ -473,99 +640,904 @@ compile_if(Chunk *chunk, Node *node) {
473 jmpop = OP_JMPF; 640 jmpop = OP_JMPF;
474 } break; 641 } break;
475 default: { 642 default: {
643 emit_compile_err(compiler, chunk, node);
476 return (CompResult){.type = COMP_ERR}; 644 return (CompResult){.type = COMP_ERR};
477 } break; 645 } break;
478 } 646 }
479 sz jump_a = array_size(chunk->code);
480 sz reg_dst = 255;
481 bool has_value = !str_eq(node->type, cstr("nil"));
482 if (has_value) {
483 reg_dst = chunk->reg_idx++;
484 }
485 647
486 // Jump to the `false` branch. 648 if (!str_eq(node->type, cstr("nil")) &&
487 EMIT_OP(jmpop, cond.idx, 0xff, 0, node->cond_if, chunk); 649 !str_has_prefix(node->type, cstr("ret:")) &&
650 !str_has_prefix(node->type, cstr("flow:"))) {
651 sz reg_dst = chunk->reg_idx++;
488 652
489 // Condition is true. 653 // Jump to the `false` branch.
490 CompResult then_expr = compile_expr(chunk, node->cond_expr); 654 sz lab0 = chunk->labels_idx++;
491 if (has_value) { 655 emit_op(jmpop, lab0, cond.idx, 0, node->ifelse.cond, chunk);
656
657 // Condition is true.
658 CompResult then_expr =
659 compile_expr(compiler, chunk, node->ifelse.expr_true);
492 switch (then_expr.type) { 660 switch (then_expr.type) {
493 case COMP_CONST: { 661 case COMP_CONST: {
494 EMIT_OP(OP_LD64K, reg_dst, then_expr.idx, 0, node->cond_if, 662 emit_op(OP_LD64K, reg_dst, then_expr.idx, 0, node->ifelse.cond,
495 chunk); 663 chunk);
496 } break; 664 } break;
497 case COMP_REG: { 665 case COMP_REG: {
498 EMIT_OP(OP_MOV64, reg_dst, then_expr.idx, 0, node->cond_if, 666 emit_op(OP_MOV64, reg_dst, then_expr.idx, 0, node->ifelse.cond,
499 chunk); 667 chunk);
500 } break; 668 } break;
669 case COMP_RET: break;
501 default: { 670 default: {
671 emit_compile_err(compiler, chunk, node);
502 return (CompResult){.type = COMP_ERR}; 672 return (CompResult){.type = COMP_ERR};
503 } break; 673 } break;
504 } 674 }
505 }
506 675
507 if (node->cond_else) {
508 // Jump to the end of the expression. 676 // Jump to the end of the expression.
509 sz jump_b = array_size(chunk->code); 677 sz pos0 = array_size(chunk->code);
510 EMIT_OP(OP_JMPI, 0xff, 0, 0, node->cond_else, chunk); 678 sz lab1 = chunk->labels_idx++;
679 emit_op(OP_JMP, lab1, 0, 0, node->ifelse.expr_else, chunk);
511 680
512 // Else expression. 681 // Else expression.
513 CompResult else_expr = compile_expr(chunk, node->cond_else); 682 CompResult else_expr =
514 if (has_value) { 683 compile_expr(compiler, chunk, node->ifelse.expr_else);
515 switch (else_expr.type) { 684 switch (else_expr.type) {
685 case COMP_CONST: {
686 emit_op(OP_LD64K, reg_dst, else_expr.idx, 0,
687 node->ifelse.expr_else, chunk);
688 } break;
689 case COMP_REG: {
690 emit_op(OP_MOV64, reg_dst, else_expr.idx, 0,
691 node->ifelse.expr_else, chunk);
692 } break;
693 case COMP_RET: break;
694 default: {
695 emit_compile_err(compiler, chunk, node);
696 return (CompResult){.type = COMP_ERR};
697 } break;
698 }
699 sz pos1 = array_size(chunk->code);
700
701 // Update labels.
702 intintmap_insert(&chunk->labels, lab0, pos0 + 1, chunk->storage);
703 intintmap_insert(&chunk->labels, lab1, pos1, chunk->storage);
704 return (CompResult){.type = COMP_REG, .idx = reg_dst};
705 }
706
707 // Jump to the `false` branch.
708 sz lab0 = chunk->labels_idx++;
709 emit_op(jmpop, lab0, cond.idx, 0, node->ifelse.cond, chunk);
710
711 // Condition is true.
712 compile_expr(compiler, chunk, node->ifelse.expr_true);
713
714 // Jump to the end of the expression.
715 sz pos0 = array_size(chunk->code);
716 sz lab1 = chunk->labels_idx++;
717 emit_op(OP_JMP, lab1, 0, 0, node->ifelse.expr_else, chunk);
718
719 // Else expression.
720 if (node->ifelse.expr_else) {
721 compile_expr(compiler, chunk, node->ifelse.expr_else);
722 }
723 sz pos1 = array_size(chunk->code);
724
725 // Update labels.
726 intintmap_insert(&chunk->labels, lab0, pos0 + 1, chunk->storage);
727 intintmap_insert(&chunk->labels, lab1, pos1, chunk->storage);
728
729 return (CompResult){.type = COMP_NIL};
730}
731
732CompResult
733compile_cond(Compiler *compiler, Chunk *chunk, Node *node) {
734 if (str_eq(node->type, cstr("nil"))) {
735 sz lab1 = chunk->labels_idx++;
736 for (sz i = 0; i < array_size(node->match.cases); i++) {
737 // condition = expression
738 Node *expr = node->match.cases[i];
739 if (expr->case_entry.cond) {
740 CompResult cond =
741 compile_expr(compiler, chunk, expr->case_entry.cond);
742 OpCode jmpop;
743 switch (cond.type) {
744 case COMP_CONST: {
745 jmpop = OP_JMPFI;
746 } break;
747 case COMP_REG: {
748 jmpop = OP_JMPF;
749 } break;
750 default: {
751 emit_compile_err(compiler, chunk, node);
752 return (CompResult){.type = COMP_ERR};
753 } break;
754 }
755 // Jump to the `next` branch.
756 sz lab0 = chunk->labels_idx++;
757 emit_op(jmpop, lab0, cond.idx, 0, expr->case_entry.expr, chunk);
758
759 // Condition is true.
760 compile_expr(compiler, chunk, expr->case_entry.expr);
761 if (i != array_size(node->match.cases) - 1) {
762 // Jump to the end of the expression.
763 sz pos0 = array_size(chunk->code);
764 emit_op(OP_JMP, lab1, 0, 0, node->ifelse.expr_else, chunk);
765 intintmap_insert(&chunk->labels, lab0, pos0 + 1,
766 chunk->storage);
767 }
768 } else {
769 compile_expr(compiler, chunk, expr->case_entry.expr);
770 break;
771 }
772 }
773 sz pos1 = array_size(chunk->code);
774 intintmap_insert(&chunk->labels, lab1, pos1, chunk->storage);
775 return (CompResult){.type = COMP_NIL};
776 }
777
778 sz reg_dst = chunk->reg_idx++;
779 sz lab1 = chunk->labels_idx++;
780 for (sz i = 0; i < array_size(node->match.cases); i++) {
781 // condition = expression
782 Node *expr = node->match.cases[i];
783 if (expr->case_entry.cond) {
784 CompResult cond =
785 compile_expr(compiler, chunk, expr->case_entry.cond);
786 OpCode jmpop;
787 switch (cond.type) {
516 case COMP_CONST: { 788 case COMP_CONST: {
517 EMIT_OP(OP_LD64K, reg_dst, else_expr.idx, 0, 789 jmpop = OP_JMPFI;
518 node->cond_else, chunk);
519 } break; 790 } break;
520 case COMP_REG: { 791 case COMP_REG: {
521 EMIT_OP(OP_MOV64, reg_dst, else_expr.idx, 0, 792 jmpop = OP_JMPF;
522 node->cond_else, chunk);
523 } break; 793 } break;
524 default: { 794 default: {
795 emit_compile_err(compiler, chunk, node);
525 return (CompResult){.type = COMP_ERR}; 796 return (CompResult){.type = COMP_ERR};
526 } break; 797 } break;
527 } 798 }
528 } 799 // Jump to the `next` branch.
529 sz end_expr = array_size(chunk->code); 800 sz lab0 = chunk->labels_idx++;
801 emit_op(jmpop, lab0, cond.idx, 0, expr->case_entry.expr, chunk);
530 802
531 // Backpatch jumps. 803 // Condition is true.
532 sz const_a = add_constant(chunk, jump_b + 1 - jump_a); 804 CompResult then_expr =
533 sz const_b = add_constant(chunk, end_expr - jump_b); 805 compile_expr(compiler, chunk, expr->case_entry.expr);
534 chunk->code[jump_a].a = const_a; 806 switch (then_expr.type) {
535 chunk->code[jump_b].dst = const_b; 807 case COMP_CONST: {
536 } else { 808 emit_op(OP_LD64K, reg_dst, then_expr.idx, 0,
537 sz end_expr = array_size(chunk->code); 809 expr->case_entry.expr, chunk);
538 if (has_value) { 810 } break;
539 sz const_a = add_constant(chunk, end_expr + 1 - jump_a); 811 case COMP_REG: {
540 chunk->code[jump_a].a = const_a; 812 emit_op(OP_MOV64, reg_dst, then_expr.idx, 0,
541 sz zero = add_constant(chunk, 0); 813 expr->case_entry.expr, chunk);
542 sz end = add_constant(chunk, 2); 814 } break;
543 EMIT_OP(OP_JMPI, end, 0, 0, node, chunk); 815 case COMP_RET: break;
544 EMIT_OP(OP_LD64K, reg_dst, zero, 0, node, chunk); 816 default: {
817 emit_compile_err(compiler, chunk, node);
818 return (CompResult){.type = COMP_ERR};
819 } break;
820 }
821 if (i != array_size(node->match.cases) - 1) {
822 // Jump to the end of the expression.
823 sz pos0 = array_size(chunk->code);
824 emit_op(OP_JMP, lab1, 0, 0, node->ifelse.expr_else, chunk);
825 intintmap_insert(&chunk->labels, lab0, pos0 + 1,
826 chunk->storage);
827 }
545 } else { 828 } else {
546 sz const_a = add_constant(chunk, end_expr - jump_a); 829 CompResult then_expr =
547 chunk->code[jump_a].a = const_a; 830 compile_expr(compiler, chunk, expr->case_entry.expr);
831 switch (then_expr.type) {
832 case COMP_CONST: {
833 emit_op(OP_LD64K, reg_dst, then_expr.idx, 0,
834 expr->case_entry.expr, chunk);
835 } break;
836 case COMP_REG: {
837 emit_op(OP_MOV64, reg_dst, then_expr.idx, 0,
838 expr->case_entry.expr, chunk);
839 } break;
840 case COMP_RET: break;
841 default: {
842 emit_compile_err(compiler, chunk, node);
843 return (CompResult){.type = COMP_ERR};
844 } break;
845 }
846 break;
548 } 847 }
549 } 848 }
550 // TODO: does it has an else or not? Moreover, should we enforce on the 849 sz pos1 = array_size(chunk->code);
551 // semantic level that if the `if` expression returns a value we must add an 850 intintmap_insert(&chunk->labels, lab1, pos1, chunk->storage);
552 // else? 851 return (CompResult){.type = COMP_REG, .idx = reg_dst};
852}
853
854CompResult
855compile_break(Compiler *compiler, Chunk *chunk, Node *node) {
856 emit_op(OP_JMP, compiler->lab_post, 0, 0, node, chunk);
857 return (CompResult){.type = COMP_NIL};
858}
859
860CompResult
861compile_continue(Compiler *compiler, Chunk *chunk, Node *node) {
862 emit_op(OP_JMP, compiler->lab_pre, 0, 0, node, chunk);
863 return (CompResult){.type = COMP_NIL};
864}
865
866CompResult
867compile_while(Compiler *compiler, Chunk *chunk, Node *node) {
868 sz lab0 = chunk->labels_idx++;
869 sz lab1 = chunk->labels_idx++;
870 sz pos1 = array_size(chunk->code);
871 CompResult cond = compile_expr(compiler, chunk, node->loop.cond);
872 OpCode jmpop;
873 switch (cond.type) {
874 case COMP_CONST: {
875 jmpop = OP_JMPFI;
876 } break;
877 case COMP_REG: {
878 jmpop = OP_JMPF;
879 } break;
880 default: {
881 emit_compile_err(compiler, chunk, node);
882 return (CompResult){.type = COMP_ERR};
883 } break;
884 }
885
886 // Jump to the `end of the loop` branch.
887 emit_op(jmpop, lab0, cond.idx, 0, node->loop.cond, chunk);
888
889 // Condition is true.
890 compiler->lab_pre = lab1;
891 compiler->lab_post = lab0;
892 compile_expr(compiler, chunk, node->loop.expr);
893 sz pos0 = array_size(chunk->code);
894 emit_op(OP_JMP, lab1, 0, 0, node, chunk);
895
896 // Update labels.
897 intintmap_insert(&chunk->labels, lab0, pos0 + 1, chunk->storage);
898 intintmap_insert(&chunk->labels, lab1, pos1, chunk->storage);
553 899
554 // Return. 900 // Return.
555 if (has_value) { 901 return (CompResult){.type = COMP_NIL};
902}
903
904CompResult
905compile_tail_call(Compiler *compiler, Chunk *chunk, Node *node) {
906 // Update the local parameters.
907 for (sz i = 0; i < array_size(node->elements); i++) {
908 Node *expr = node->elements[i];
909 CompResult result = compile_expr(compiler, chunk, expr);
910 switch (result.type) {
911 case COMP_CONST: {
912 emit_op(OP_STLVARI, i, result.idx, 0, node, chunk);
913 } break;
914 case COMP_REG: {
915 if (str_eq(expr->type, cstr("str"))) {
916 sz var_addr = chunk->reg_idx++;
917 sz str_addr = result.idx;
918 emit_op(OP_LDLADDR, var_addr, i, 0, node, chunk);
919 emit_fat_copy(chunk, node, var_addr, str_addr);
920 } else {
921 emit_op(OP_STLVAR, i, result.idx, 0, node, chunk);
922 }
923 } break;
924 case COMP_STRING: {
925 sz var_addr = chunk->reg_idx++;
926 sz str_addr = chunk->reg_idx++;
927 emit_op(OP_LDLADDR, var_addr, i, 0, node, chunk);
928 emit_op(OP_LDSTR, str_addr, result.idx, 0, node, chunk);
929 emit_fat_copy(chunk, node, var_addr, str_addr);
930 } break;
931 default: {
932 emit_compile_err(compiler, chunk, node);
933 return (CompResult){.type = COMP_ERR};
934 } break;
935 }
936 }
937
938 emit_op(OP_RECUR, 0, 0, 0, node, chunk);
939 return (CompResult){.type = COMP_NIL};
940}
941
942CompResult
943compile_funcall(Compiler *compiler, Chunk *chunk, Node *node) {
944 Str name = node->value.str;
945
946 // Builtins.
947 if (str_eq(name, cstr("print")) || str_eq(name, cstr("println"))) {
948 for (sz i = 0; i < array_size(node->elements); i++) {
949 Node *expr = node->elements[i];
950 CompResult result = compile_expr(compiler, chunk, expr);
951 if (str_eq(expr->type, cstr("int"))) {
952 switch (result.type) {
953 case COMP_CONST: {
954 emit_op(OP_PRINTS64I, result.idx, 0, 0, expr, chunk);
955 } break;
956 case COMP_REG: {
957 emit_op(OP_PRINTS64, result.idx, 0, 0, expr, chunk);
958 } break;
959 default: {
960 emit_compile_err(compiler, chunk, node);
961 return (CompResult){.type = COMP_ERR};
962 } break;
963 }
964 } else if (str_eq(expr->type, cstr("f64"))) {
965 switch (result.type) {
966 case COMP_CONST: {
967 emit_op(OP_PRINTF64I, result.idx, 0, 0, expr, chunk);
968 } break;
969 case COMP_REG: {
970 emit_op(OP_PRINTF64, result.idx, 0, 0, expr, chunk);
971 } break;
972 default: {
973 emit_compile_err(compiler, chunk, node);
974 return (CompResult){.type = COMP_ERR};
975 } break;
976 }
977 } else if (str_eq(expr->type, cstr("str"))) {
978 switch (result.type) {
979 case COMP_STRING: {
980 emit_op(OP_PRINTSTRI, result.idx, 0, 0, expr, chunk);
981 } break;
982 case COMP_REG: {
983 emit_op(OP_PRINTSTR, result.idx, 0, 0, expr, chunk);
984 } break;
985 default: {
986 emit_compile_err(compiler, chunk, node);
987 return (CompResult){.type = COMP_ERR};
988 } break;
989 }
990 } else if (str_eq(expr->type, cstr("bool"))) {
991 switch (result.type) {
992 case COMP_CONST: {
993 emit_op(OP_PRINTBOOLI, result.idx, 0, 0, expr, chunk);
994 } break;
995 case COMP_REG: {
996 emit_op(OP_PRINTBOOL, result.idx, 0, 0, expr, chunk);
997 } break;
998 default: {
999 emit_compile_err(compiler, chunk, node);
1000 return (CompResult){.type = COMP_ERR};
1001 } break;
1002 }
1003 }
1004 }
1005 if (str_eq(name, cstr("println"))) {
1006 sz idx = add_string(chunk, cstr("\n"));
1007 emit_op(OP_PRINTSTRI, idx, 0, 0, node, chunk);
1008 }
1009 return (CompResult){.type = COMP_NIL};
1010 }
1011
1012 FunctionMap *map =
1013 funcmap_lookup(&compiler->main_chunk.funmap, node->unique_name);
1014 if (!map) {
1015 emit_compile_err(compiler, chunk, node);
1016 return (CompResult){.type = COMP_ERR};
1017 }
1018 Function fun = map->val;
1019
1020 // Check for tail recursive opportunities.
1021 if (str_eq(fun.name, node->unique_name) &&
1022 str_eq(chunk->name, node->unique_name)) {
1023 Node *parent = node->parent;
1024 Node *current = node;
1025 bool tail_recursive = true;
1026 while (parent != NULL) {
1027 switch (parent->kind) {
1028 case NODE_BLOCK: {
1029 sz idx = array_size(parent->statements) - 1;
1030 if (parent->statements[idx] != node) {
1031 tail_recursive = false;
1032 break;
1033 }
1034 } break;
1035 case NODE_WHILE: {
1036 if (current == parent->loop.cond) {
1037 tail_recursive = false;
1038 break;
1039 }
1040 } break;
1041 case NODE_IF: {
1042 if (current == parent->ifelse.cond) {
1043 tail_recursive = false;
1044 break;
1045 }
1046 } break;
1047 case NODE_FUN: {
1048 sz idx = array_size(parent->func.body->statements) - 1;
1049 if (parent->func.body->statements[idx] != current) {
1050 tail_recursive = false;
1051 break;
1052 }
1053 break;
1054 } break;
1055 case NODE_MATCH: {
1056 if (current == parent->match.expr) {
1057 tail_recursive = false;
1058 break;
1059 }
1060 } break;
1061 case NODE_COND: break;
1062 case NODE_CASE_COND: {
1063 if (current == parent->case_entry.cond) {
1064 tail_recursive = false;
1065 break;
1066 }
1067 } break;
1068 default: {
1069 tail_recursive = false;
1070 break;
1071 } break;
1072 }
1073 parent = parent->parent;
1074 current = current->parent;
1075 }
1076 if (tail_recursive) {
1077 return compile_tail_call(compiler, chunk, node);
1078 }
1079 }
1080
1081 // Reserve space for the return value if needed.
1082 if (fun.return_arity > 0) {
1083 // Put the return data into a register
1084 sz ret_size = add_constant(chunk, 8);
1085 emit_op(OP_RESERVE, ret_size, 0, 0, node, chunk);
1086 }
1087
1088 // Send parameters to the stack.
1089 for (sz i = 0; i < array_size(node->elements); i++) {
1090 Node *expr = node->elements[i];
1091 CompResult result = compile_expr(compiler, chunk, expr);
1092 switch (result.type) {
1093 case COMP_CONST: {
1094 emit_op(OP_PUSHI, result.idx, 0, 0, expr, chunk);
1095 } break;
1096 case COMP_REG: {
1097 if (str_eq(expr->type, cstr("str"))) {
1098 sz str_addr = result.idx;
1099 // Store the fat string pointer into the stack.
1100 sz reg_dst = chunk->reg_idx++;
1101 sz zero = add_constant(chunk, 0);
1102 sz one = add_constant(chunk, 1);
1103 emit_op(OP_LD64I, reg_dst, str_addr, zero, node, chunk);
1104 emit_op(OP_PUSH, reg_dst, 0, 0, expr, chunk);
1105 emit_op(OP_LD64I, reg_dst, str_addr, one, node, chunk);
1106 emit_op(OP_PUSH, reg_dst, 0, 0, expr, chunk);
1107 } else {
1108 emit_op(OP_PUSH, result.idx, 0, 0, expr, chunk);
1109 }
1110 } break;
1111 case COMP_STRING: {
1112 // Get the address for the string value variable.
1113 sz str_addr = chunk->reg_idx++;
1114 emit_op(OP_LDSTR, str_addr, result.idx, 0, node->var.val,
1115 chunk);
1116
1117 // Store the fat string pointer into the stack.
1118 sz reg_dst = chunk->reg_idx++;
1119 sz zero = add_constant(chunk, 0);
1120 sz one = add_constant(chunk, 1);
1121 emit_op(OP_LD64I, reg_dst, str_addr, zero, node, chunk);
1122 emit_op(OP_PUSH, reg_dst, 0, 0, expr, chunk);
1123 emit_op(OP_LD64I, reg_dst, str_addr, one, node, chunk);
1124 emit_op(OP_PUSH, reg_dst, 0, 0, expr, chunk);
1125 } break;
1126 default: {
1127 emit_compile_err(compiler, chunk, node);
1128 return (CompResult){.type = COMP_ERR};
1129 } break;
1130 }
1131 }
1132
1133 emit_op(OP_CALL, fun.index, 0, 0, node, chunk);
1134
1135 // Only one return parameter for now.
1136 if (fun.return_arity > 0) {
1137 // Put the return data into a register
1138 sz reg_dst = chunk->reg_idx++;
1139 emit_op(OP_POP, reg_dst, 0, 0, node, chunk);
556 return (CompResult){.type = COMP_REG, .idx = reg_dst}; 1140 return (CompResult){.type = COMP_REG, .idx = reg_dst};
557 } 1141 }
1142
1143 return (CompResult){.type = COMP_NIL};
1144}
1145
1146CompResult
1147compile_return(Compiler *compiler, Chunk *chunk, Node *node) {
1148 for (sz i = 0; i < array_size(node->elements); i++) {
1149 Node *expr = node->elements[i];
1150 CompResult res = compile_expr(compiler, chunk, expr);
1151
1152 // TODO: Only one return field for now, but this is the idea.
1153 // Put return values into memory.
1154 switch (res.type) {
1155 case COMP_CONST: {
1156 emit_op(OP_PUTRETI, res.idx, 0, 0, node, chunk);
1157 } break;
1158 case COMP_REG: {
1159 emit_op(OP_PUTRET, res.idx, 0, 0, node, chunk);
1160 } break;
1161 case COMP_NIL: break;
1162 default: {
1163 emit_compile_err(compiler, chunk, node);
1164 return (CompResult){.type = COMP_ERR};
1165 } break;
1166 }
1167 break;
1168 }
1169
1170 emit_op(OP_RET, 0, 0, 0, node, chunk);
1171 return (CompResult){.type = COMP_RET};
1172}
1173
1174Chunk *
1175chunk_alloc(Chunk *parent) {
1176 static sz chunk_idx = 1;
1177 Chunk *chunk = arena_calloc((sz)sizeof(Chunk), parent->storage);
1178 chunk->parent = parent;
1179 chunk->id = chunk_idx++;
1180 chunk->storage = parent->storage;
1181 chunk->file_name = parent->file_name;
1182 return chunk;
1183}
1184
1185void
1186verify_chunk(Chunk *chunk) {
1187 if (chunk->const_idx >= 256) {
1188 eprintln("too many constants on chunk %s", chunk->id);
1189 exit(EXIT_FAILURE);
1190 }
1191 if (chunk->str_idx >= 256) {
1192 eprintln("too many strings on chunk %s", chunk->id);
1193 exit(EXIT_FAILURE);
1194 }
1195 if (chunk->reg_idx >= 256) {
1196 eprintln("too many registers used on chunk %s", chunk->id);
1197 exit(EXIT_FAILURE);
1198 }
1199 if (chunk->labels_idx >= 256) {
1200 eprintln("too many labels used on chunk %s", chunk->id);
1201 exit(EXIT_FAILURE);
1202 }
1203 if (chunk->fun_idx >= 256) {
1204 eprintln("too many functions on chunk %s", chunk->id);
1205 exit(EXIT_FAILURE);
1206 }
1207}
1208
1209void
1210declare_function(Chunk *chunk, Node *node) {
1211 Str name = node->unique_name;
1212 FunctionMap *map = funcmap_lookup(&chunk->funmap, node->unique_name);
1213 if (map) {
1214 return;
1215 }
1216 Function fun = (Function){
1217 .name = name,
1218 .index = chunk->fun_idx++,
1219 .param_arity = array_size(node->func.params),
1220 .return_arity = array_size(node->func.ret),
1221 };
1222 funcmap_insert(&chunk->funmap, node->unique_name, fun, chunk->storage);
1223}
1224
1225CompResult
1226compile_function(Compiler *compiler, Chunk *chunk, Node *node) {
1227 // The current activation record procedure for the VM is as follows:
1228 //
1229 // [caller][callee ]
1230 // [ .... ][ RET VAL ][ PARAMS ][ LOCALS ][ REGISTERS ][ RET META ]
1231 // ^
1232 // frame pointer
1233 //
1234 // The caller is responsible for allocating the return memory and the
1235 // parameter memory and filling the param data before OP_CALL.
1236 //
1237 chunk = &compiler->main_chunk;
1238 Chunk *func = chunk_alloc(chunk);
1239 func->name = node->unique_name;
1240 declare_function(chunk, node);
1241 array_push(chunk->functions, func, chunk->storage);
1242
1243 // Push arguments as locals.
1244 for (sz i = 0; i < array_size(node->func.params); i++) {
1245 Node *param = node->func.params[i];
1246 Str name = param->unique_name;
1247 Str type = param->type;
1248 sz arr_size = 0;
1249 if (str_has_prefix(type, cstr("@"))) {
1250 if (param->var.type && param->var.type->kind == NODE_ARR_TYPE &&
1251 param->var.type->sym.arr_size->value.i > 0) {
1252 arr_size = param->var.type->sym.arr_size->value.i;
1253 }
1254 }
1255 add_variable(func, name, type, arr_size);
1256 }
1257 func->param_off = func->var_off;
1258
1259 // Compiling the body.
1260 CompResult res = compile_expr(compiler, func, node->func.body);
1261
1262 // Put return values into memory.
1263 switch (res.type) {
1264 case COMP_CONST: {
1265 emit_op(OP_PUTRETI, res.idx, 0, 0, node, func);
1266 } break;
1267 case COMP_REG: {
1268 emit_op(OP_PUTRET, res.idx, 0, 0, node, func);
1269 } break;
1270 default: break;
1271 }
1272
1273 emit_op(OP_RET, 0, 0, 0, node, func);
1274 verify_chunk(func);
1275 return (CompResult){.type = COMP_NIL};
1276}
1277
1278CompResult
1279compile_let(Compiler *compiler, Chunk *chunk, Node *node) {
1280 sz op_ldaddr = OP_LDLADDR;
1281 sz op_stvari = OP_STLVARI;
1282 sz op_stvar = OP_STLVAR;
1283 if (chunk == &compiler->main_chunk) {
1284 op_ldaddr = OP_LDGADDR;
1285 op_stvari = OP_STGVARI;
1286 op_stvar = OP_STGVAR;
1287 }
1288 Str name = node->unique_name;
1289 Str type = node->var.name->type;
1290 sz arr_size = 0;
1291 if (str_has_prefix(type, cstr("@"))) {
1292 if (node->var.type && node->var.type->kind == NODE_ARR_TYPE &&
1293 node->var.type->sym.arr_size->value.i > 0) {
1294 arr_size = node->var.type->sym.arr_size->value.i;
1295 }
1296 }
1297
1298 sz idx = add_variable(chunk, name, type, arr_size);
1299
1300 // Value.
1301 if (node->var.val) {
1302 CompResult res = compile_expr(compiler, chunk, node->var.val);
1303 switch (res.type) {
1304 case COMP_CONST: {
1305 emit_op(op_stvari, idx, res.idx, 0, node->var.val, chunk);
1306 } break;
1307 case COMP_REG: {
1308 if (str_eq(node->var.val->type, cstr("str"))) {
1309 // Get the address for the local/global storage
1310 // variable.
1311 sz var_addr = chunk->reg_idx++;
1312 emit_op(op_ldaddr, var_addr, idx, 0, node, chunk);
1313
1314 // Copy the fat pointer.
1315 emit_fat_copy(chunk, node, var_addr, res.idx);
1316 } else {
1317 emit_op(op_stvar, idx, res.idx, 0, node->var.val, chunk);
1318 }
1319 } break;
1320 case COMP_STRING: {
1321 // Get the address for the string value variable.
1322 sz str_addr = chunk->reg_idx++;
1323 emit_op(OP_LDSTR, str_addr, res.idx, 0, node->var.val, chunk);
1324
1325 // Get the address for the local/global storage
1326 // variable.
1327 sz var_addr = chunk->reg_idx++;
1328 emit_op(op_ldaddr, var_addr, idx, 0, node, chunk);
1329
1330 // Copy the fat pointer.
1331 emit_fat_copy(chunk, node, var_addr, str_addr);
1332 } break;
1333 default: {
1334 emit_compile_err(compiler, chunk, node);
1335 return (CompResult){.type = COMP_ERR};
1336 } break;
1337 }
1338 }
1339
1340 return (CompResult){.type = COMP_NIL};
1341}
1342
1343CompResult
1344compile_set(Compiler *compiler, Chunk *chunk, Node *node) {
1345 Str name = node->unique_name;
1346 StrVarMap *map = NULL;
1347 Chunk *next = chunk;
1348 while (next) {
1349 map = varmap_lookup(&next->varmap, name);
1350 if (map) {
1351 break;
1352 }
1353 next = chunk->parent;
1354 }
1355 if (!map) {
1356 emit_compile_err(compiler, chunk, node);
1357 return (CompResult){.type = COMP_ERR};
1358 }
1359 sz op_ldaddr = OP_LDLADDR;
1360 sz op_ldvar = OP_LDLVAR;
1361 sz op_stvari = OP_STLVARI;
1362 sz op_stvar = OP_STLVAR;
1363 if (next == &compiler->main_chunk) {
1364 op_ldaddr = OP_LDGADDR;
1365 op_ldvar = OP_LDGVAR;
1366 op_stvari = OP_STGVARI;
1367 op_stvar = OP_STGVAR;
1368 }
1369 CompResult res = compile_expr(compiler, chunk, node->var.val);
1370 if (node->var.name->kind == NODE_SYMBOL_IDX) {
1371 // Value.
1372 sz reg_val;
1373 switch (res.type) {
1374 case COMP_CONST: {
1375 reg_val = chunk->reg_idx++;
1376 emit_op(OP_LD64K, reg_val, res.idx, 0, node, chunk);
1377 } break;
1378 case COMP_REG: {
1379 reg_val = res.idx;
1380 } break;
1381 default: {
1382 emit_compile_err(compiler, chunk, node);
1383 return (CompResult){.type = COMP_ERR};
1384 } break;
1385 }
1386
1387 // Address.
1388 sz reg_addr = chunk->reg_idx++;
1389 // Is this a pointer access or an array access?
1390 if (str_has_prefix(map->val.type, cstr("[]"))) {
1391 emit_op(op_ldaddr, reg_addr, map->val.idx, 0, node->var.val, chunk);
1392 } else {
1393 emit_op(op_ldvar, reg_addr, map->val.idx, 0, node->var.val, chunk);
1394 }
1395
1396 // Index.
1397 CompResult idx =
1398 compile_expr(compiler, chunk, node->var.name->sym.arr_size);
1399 switch (idx.type) {
1400 case COMP_CONST: {
1401 emit_op(OP_ST64I, reg_val, reg_addr, idx.idx, node, chunk);
1402 } break;
1403 case COMP_REG: {
1404 emit_op(OP_ST64, reg_val, reg_addr, idx.idx, node, chunk);
1405 } break;
1406 default: {
1407 emit_compile_err(compiler, chunk, node);
1408 return (CompResult){.type = COMP_ERR};
1409 } break;
1410 }
1411 // TODO: offset should be in bytes, in this case we are assuming
1412 // 64bit types, hence ST64
1413 return (CompResult){.type = COMP_NIL};
1414 }
1415 switch (res.type) {
1416 case COMP_CONST: {
1417 emit_op(op_stvari, map->val.idx, res.idx, 0, node->var.val, chunk);
1418 } break;
1419 case COMP_REG: {
1420 if (str_eq(node->var.val->type, cstr("str"))) {
1421 // Get the address for the local/global storage
1422 // variable.
1423 sz var_addr = chunk->reg_idx++;
1424 emit_op(op_ldaddr, var_addr, map->val.idx, 0, node, chunk);
1425
1426 // Copy the fat pointer.
1427 emit_fat_copy(chunk, node, var_addr, res.idx);
1428 } else {
1429 emit_op(op_stvar, map->val.idx, res.idx, 0, node->var.val,
1430 chunk);
1431 }
1432 } break;
1433 default: {
1434 emit_compile_err(compiler, chunk, node);
1435 return (CompResult){.type = COMP_ERR};
1436 } break;
1437 }
558 return (CompResult){.type = COMP_NIL}; 1438 return (CompResult){.type = COMP_NIL};
559} 1439}
560 1440
561CompResult 1441CompResult
562compile_expr(Chunk *chunk, Node *node) { 1442compile_symbol(Compiler *compiler, Chunk *chunk, Node *node) {
1443 Str name = node->unique_name;
1444 StrVarMap *map = NULL;
1445 Chunk *next = chunk;
1446 while (next) {
1447 map = varmap_lookup(&next->varmap, name);
1448 if (map) {
1449 break;
1450 }
1451 next = next->parent;
1452 }
1453 if (!map) {
1454 emit_compile_err(compiler, chunk, node);
1455 return (CompResult){.type = COMP_ERR};
1456 }
1457 sz op_ldaddr = OP_LDLADDR;
1458 sz op_ldvar = OP_LDLVAR;
1459 if (next == &compiler->main_chunk) {
1460 op_ldaddr = OP_LDGADDR;
1461 op_ldvar = OP_LDGVAR;
1462 }
1463 Variable var = map->val;
1464 u8 reg_dst = chunk->reg_idx++;
1465 if (node->is_ptr || str_has_prefix(var.type, cstr("[]")) ||
1466 str_eq(var.type, cstr("str"))) {
1467 emit_op(op_ldaddr, reg_dst, var.idx, 0, node, chunk);
1468 } else {
1469 emit_op(op_ldvar, reg_dst, var.idx, 0, node, chunk);
1470 }
1471 return (CompResult){.type = COMP_REG, .idx = reg_dst};
1472}
1473
1474CompResult
1475compile_symbol_idx(Compiler *compiler, Chunk *chunk, Node *node) {
1476 Str name = node->unique_name;
1477 StrVarMap *map = NULL;
1478 Chunk *next = chunk;
1479 while (next) {
1480 map = varmap_lookup(&next->varmap, name);
1481 if (map) {
1482 break;
1483 }
1484 next = next->parent;
1485 }
1486 if (!map) {
1487 eprintln("couldn't resolve symbol name: %s", name);
1488 emit_compile_err(compiler, chunk, node);
1489 return (CompResult){.type = COMP_ERR};
1490 }
1491 sz op_ldaddr = OP_LDLADDR;
1492 sz op_ldvar = OP_LDLVAR;
1493 if (next == &compiler->main_chunk) {
1494 op_ldaddr = OP_LDGADDR;
1495 op_ldvar = OP_LDGVAR;
1496 }
1497
1498 // Destination.
1499 u8 reg_dst = chunk->reg_idx++;
1500
1501 // Address.
1502 sz reg_addr = chunk->reg_idx++;
1503 if (str_has_prefix(map->val.type, cstr("[]"))) {
1504 emit_op(op_ldaddr, reg_addr, map->val.idx, 0, node->var.val, chunk);
1505 } else {
1506 emit_op(op_ldvar, reg_addr, map->val.idx, 0, node->var.val, chunk);
1507 }
1508
1509 // Index.
1510 CompResult idx = compile_expr(compiler, chunk, node->sym.arr_size);
1511 switch (idx.type) {
1512 case COMP_CONST: {
1513 emit_op(OP_LD64I, reg_dst, reg_addr, idx.idx, node, chunk);
1514 } break;
1515 case COMP_REG: {
1516 emit_op(OP_LD64, reg_dst, reg_addr, idx.idx, node, chunk);
1517 } break;
1518 default: {
1519 emit_compile_err(compiler, chunk, node);
1520 return (CompResult){.type = COMP_ERR};
1521 } break;
1522 }
1523 // TODO: hardcoding the type size for now (LD64/LD64I).
1524 return (CompResult){.type = COMP_REG, .idx = reg_dst};
1525}
1526
1527CompResult
1528compile_expr(Compiler *compiler, Chunk *chunk, Node *node) {
563 switch (node->kind) { 1529 switch (node->kind) {
564 case NODE_IF: return compile_if(chunk, node); 1530 case NODE_BREAK: return compile_break(compiler, chunk, node);
1531 case NODE_CONTINUE: return compile_continue(compiler, chunk, node);
1532 case NODE_RETURN: return compile_return(compiler, chunk, node);
1533 case NODE_FUN: return compile_function(compiler, chunk, node);
1534 case NODE_FUNCALL: return compile_funcall(compiler, chunk, node);
1535 case NODE_WHILE: return compile_while(compiler, chunk, node);
1536 case NODE_IF: return compile_if(compiler, chunk, node);
1537 case NODE_COND: return compile_cond(compiler, chunk, node);
565 // Logic. 1538 // Logic.
566 // case NODE_XOR:
567 case NODE_BITNOT: 1539 case NODE_BITNOT:
568 case NODE_NOT: return compile_unary(chunk, node); break; 1540 case NODE_NOT: return compile_unary(compiler, chunk, node); break;
569 case NODE_AND: 1541 case NODE_AND:
570 case NODE_OR: 1542 case NODE_OR:
571 case NODE_EQ: 1543 case NODE_EQ:
@@ -576,6 +1548,7 @@ compile_expr(Chunk *chunk, Node *node) {
576 // Bitwise ops. 1548 // Bitwise ops.
577 case NODE_BITAND: 1549 case NODE_BITAND:
578 case NODE_BITOR: 1550 case NODE_BITOR:
1551 case NODE_BITXOR:
579 case NODE_BITLSHIFT: 1552 case NODE_BITLSHIFT:
580 case NODE_BITRSHIFT: 1553 case NODE_BITRSHIFT:
581 // Arithmetic. 1554 // Arithmetic.
@@ -584,7 +1557,7 @@ compile_expr(Chunk *chunk, Node *node) {
584 case NODE_SUB: 1557 case NODE_SUB:
585 case NODE_MUL: 1558 case NODE_MUL:
586 case NODE_DIV: 1559 case NODE_DIV:
587 case NODE_MOD: return compile_binary(chunk, node); break; 1560 case NODE_MOD: return compile_binary(compiler, chunk, node); break;
588 case NODE_TRUE: 1561 case NODE_TRUE:
589 case NODE_FALSE: 1562 case NODE_FALSE:
590 case NODE_NUM_FLOAT: 1563 case NODE_NUM_FLOAT:
@@ -599,105 +1572,30 @@ compile_expr(Chunk *chunk, Node *node) {
599 } break; 1572 } break;
600 case NODE_STRING: { 1573 case NODE_STRING: {
601 Str string = node->value.str; 1574 Str string = node->value.str;
602 // Make sure we don't have duplicated strings. 1575 sz str_idx = add_string(chunk, string);
603 StrIntMap *map = strintmap_lookup(&chunk->strmap, string);
604 if (!map) {
605 map = strintmap_insert(&chunk->strmap, string, chunk->str_idx++,
606 chunk->storage);
607 array_push(chunk->strings, string, chunk->storage);
608 }
609 return (CompResult){ 1576 return (CompResult){
610 .type = COMP_STRING, 1577 .type = COMP_STRING,
611 .idx = map->val, 1578 .idx = str_idx,
612 }; 1579 };
613 } break; 1580 } break;
614 case NODE_LET: { 1581 case NODE_LET: return compile_let(compiler, chunk, node);
615 sz idx = array_size(chunk->vars); 1582 case NODE_SET: return compile_set(compiler, chunk, node);
616 Str name = node->unique_name; 1583 case NODE_SYMBOL: return compile_symbol(compiler, chunk, node);
617 Str type = node->var_name->type; 1584 case NODE_SYMBOL_IDX: return compile_symbol_idx(compiler, chunk, node);
618 sz size = 8;
619 // TODO: get type storage from a table to consider all the basic
620 // types as well as user defined ones.
621 if (str_eq(type, cstr("str"))) {
622 size = 16;
623 }
624 Variable var = (Variable){
625 .name = name,
626 .type = type,
627 .size = size,
628 .offset = chunk->var_off,
629 .idx = idx,
630 };
631 varmap_insert(&chunk->varmap, name, var, chunk->storage);
632 array_push(chunk->vars, var, chunk->storage);
633 chunk->var_off += size;
634
635 // Value.
636 if (node->var_val) {
637 CompResult res = compile_expr(chunk, node->var_val);
638 switch (res.type) {
639 case COMP_CONST: {
640 EMIT_OP(OP_STGVARI, idx, res.idx, 0, node->var_val,
641 chunk);
642 } break;
643 case COMP_REG: {
644 EMIT_OP(OP_STGVAR, idx, res.idx, 0, node->var_val,
645 chunk);
646 } break;
647 default: {
648 return (CompResult){.type = COMP_ERR};
649 } break;
650 }
651 }
652
653 return (CompResult){.type = COMP_NIL};
654 } break;
655 case NODE_SET: {
656 Str name = node->unique_name;
657 StrVarMap *map = varmap_lookup(&chunk->varmap, name);
658 if (!map) {
659 println("you wot mate?: %s", name);
660 }
661 CompResult res = compile_expr(chunk, node->var_val);
662 switch (res.type) {
663 case COMP_CONST: {
664 EMIT_OP(OP_STGVARI, map->val.idx, res.idx, 0, node->var_val,
665 chunk);
666 } break;
667 case COMP_REG: {
668 EMIT_OP(OP_STGVAR, map->val.idx, res.idx, 0, node->var_val,
669 chunk);
670 } break;
671 default: {
672 return (CompResult){.type = COMP_ERR};
673 } break;
674 }
675 return (CompResult){.type = COMP_NIL};
676 } break;
677 case NODE_SYMBOL: {
678 Str name = node->unique_name;
679 StrVarMap *map = varmap_lookup(&chunk->varmap, name);
680 if (!map) {
681 println("error: unreachable... name: %s", name);
682 exit(EXIT_FAILURE);
683 }
684 Variable var = map->val;
685 u8 reg_dst = chunk->reg_idx++;
686 EMIT_OP(OP_LDGVAR, reg_dst, var.idx, 0, node, chunk);
687 return (CompResult){.type = COMP_REG, .idx = reg_dst};
688 } break;
689 case NODE_BLOCK: { 1585 case NODE_BLOCK: {
690 CompResult res; 1586 CompResult res;
691 for (sz i = 0; i < array_size(node->elements); i++) { 1587 for (sz i = 0; i < array_size(node->elements); i++) {
692 Node *root = node->elements[i]; 1588 Node *root = node->elements[i];
693 res = compile_expr(chunk, root); 1589 res = compile_expr(compiler, chunk, root);
694 } 1590 }
695 return res; 1591 return res;
696 } break; 1592 } break;
1593 case NODE_NIL: return (CompResult){.type = COMP_NIL};
697 default: { 1594 default: {
698 eprintln("error: compilation not implemented for node %s", 1595 eprintln("error: compilation not implemented for node %s",
699 node_str[node->kind]); 1596 node_str[node->kind]);
700 exit(EXIT_FAILURE); 1597 emit_compile_err(compiler, chunk, node);
1598 return (CompResult){.type = COMP_ERR};
701 } break; 1599 } break;
702 } 1600 }
703 return (CompResult){.type = COMP_ERR}; 1601 return (CompResult){.type = COMP_ERR};
@@ -706,6 +1604,10 @@ compile_expr(Chunk *chunk, Node *node) {
706void 1604void
707disassemble_instruction(Instruction instruction) { 1605disassemble_instruction(Instruction instruction) {
708 switch (instruction.op) { 1606 switch (instruction.op) {
1607 case OP_CALL:
1608 println("%s f%d", op_str[instruction.op], instruction.dst,
1609 instruction.a, instruction.b);
1610 break;
709 case OP_MOV8: 1611 case OP_MOV8:
710 case OP_MOV16: 1612 case OP_MOV16:
711 case OP_MOV32: 1613 case OP_MOV32:
@@ -713,12 +1615,15 @@ disassemble_instruction(Instruction instruction) {
713 println("%s r%d, r%d", op_str[instruction.op], instruction.dst, 1615 println("%s r%d, r%d", op_str[instruction.op], instruction.dst,
714 instruction.a, instruction.b); 1616 instruction.a, instruction.b);
715 break; 1617 break;
1618 case OP_JMPF:
1619 case OP_JMPT:
1620 println("%s l%d, r%d", op_str[instruction.op], instruction.dst,
1621 instruction.a, instruction.b);
1622 break;
716 case OP_LD8K: 1623 case OP_LD8K:
717 case OP_LD16K: 1624 case OP_LD16K:
718 case OP_LD32K: 1625 case OP_LD32K:
719 case OP_LD64K: 1626 case OP_LD64K:
720 case OP_JMPF:
721 case OP_JMPT:
722 println("%s r%d, c%d", op_str[instruction.op], instruction.dst, 1627 println("%s r%d, c%d", op_str[instruction.op], instruction.dst,
723 instruction.a, instruction.b); 1628 instruction.a, instruction.b);
724 break; 1629 break;
@@ -752,6 +1657,7 @@ disassemble_instruction(Instruction instruction) {
752 case OP_BITRSHIFTI: 1657 case OP_BITRSHIFTI:
753 case OP_BITANDI: 1658 case OP_BITANDI:
754 case OP_BITORI: 1659 case OP_BITORI:
1660 case OP_BITXORI:
755 println("%s r%d, r%d, c%d", op_str[instruction.op], instruction.dst, 1661 println("%s r%d, r%d, c%d", op_str[instruction.op], instruction.dst,
756 instruction.a, instruction.b); 1662 instruction.a, instruction.b);
757 break; 1663 break;
@@ -785,18 +1691,28 @@ disassemble_instruction(Instruction instruction) {
785 case OP_BITRSHIFT: 1691 case OP_BITRSHIFT:
786 case OP_BITAND: 1692 case OP_BITAND:
787 case OP_BITOR: 1693 case OP_BITOR:
1694 case OP_BITXOR:
788 println("%s r%d, r%d, r%d", op_str[instruction.op], instruction.dst, 1695 println("%s r%d, r%d, r%d", op_str[instruction.op], instruction.dst,
789 instruction.a, instruction.b); 1696 instruction.a, instruction.b);
790 break; 1697 break;
791 case OP_LDGVAR: 1698 case OP_LDGVAR:
1699 case OP_LDGADDR:
1700 case OP_LDLVAR:
1701 case OP_LDLADDR:
792 println("%s r%d, v%d", op_str[instruction.op], instruction.dst, 1702 println("%s r%d, v%d", op_str[instruction.op], instruction.dst,
793 instruction.a, instruction.b); 1703 instruction.a, instruction.b);
794 break; 1704 break;
1705 case OP_LDSTR:
1706 println("%s r%d, s%d", op_str[instruction.op], instruction.dst,
1707 instruction.a, instruction.b);
1708 break;
795 case OP_STGVAR: 1709 case OP_STGVAR:
1710 case OP_STLVAR:
796 println("%s v%d, r%d", op_str[instruction.op], instruction.dst, 1711 println("%s v%d, r%d", op_str[instruction.op], instruction.dst,
797 instruction.a, instruction.b); 1712 instruction.a, instruction.b);
798 break; 1713 break;
799 case OP_STGVARI: 1714 case OP_STGVARI:
1715 case OP_STLVARI:
800 println("%s v%d, c%d", op_str[instruction.op], instruction.dst, 1716 println("%s v%d, c%d", op_str[instruction.op], instruction.dst,
801 instruction.a, instruction.b); 1717 instruction.a, instruction.b);
802 break; 1718 break;
@@ -810,19 +1726,37 @@ disassemble_instruction(Instruction instruction) {
810 println("%s r%d, r%d", op_str[instruction.op], instruction.dst, 1726 println("%s r%d, r%d", op_str[instruction.op], instruction.dst,
811 instruction.a, instruction.b); 1727 instruction.a, instruction.b);
812 break; 1728 break;
813 case OP_JMPI:
814 println("%s c%d", op_str[instruction.op], instruction.dst,
815 instruction.a, instruction.b);
816 break;
817 case OP_JMP: 1729 case OP_JMP:
818 println("%s r%d", op_str[instruction.op], instruction.dst, 1730 println("%s l%d", op_str[instruction.op], instruction.dst,
819 instruction.a, instruction.b); 1731 instruction.a, instruction.b);
820 break; 1732 break;
821 case OP_JMPFI: 1733 case OP_JMPFI:
822 case OP_JMPTI: 1734 case OP_JMPTI:
823 println("%s c%d, c%d", op_str[instruction.op], instruction.dst, 1735 println("%s l%d, c%d", op_str[instruction.op], instruction.dst,
824 instruction.a, instruction.b); 1736 instruction.a, instruction.b);
825 break; 1737 break;
1738 case OP_PRINTS64:
1739 case OP_PRINTF64:
1740 case OP_PRINTSTR:
1741 case OP_PRINTBOOL:
1742 case OP_PUSH:
1743 case OP_POP:
1744 case OP_PUTRET:
1745 println("%s r%d", op_str[instruction.op], instruction.dst,
1746 instruction.a, instruction.b);
1747 break;
1748 case OP_PRINTSTRI:
1749 case OP_PRINTS64I:
1750 case OP_PRINTF64I:
1751 case OP_PRINTBOOLI:
1752 case OP_RESERVE:
1753 case OP_PUSHI:
1754 case OP_PUTRETI:
1755 println("%s c%d", op_str[instruction.op], instruction.dst,
1756 instruction.a, instruction.b);
1757 break;
1758 case OP_RET:
1759 case OP_RECUR:
826 case OP_HALT: println("%s", op_str[instruction.op]); break; 1760 case OP_HALT: println("%s", op_str[instruction.op]); break;
827 default: println("Unknown opcode %d", instruction.op); break; 1761 default: println("Unknown opcode %d", instruction.op); break;
828 } 1762 }
@@ -830,36 +1764,120 @@ disassemble_instruction(Instruction instruction) {
830 1764
831void 1765void
832disassemble_chunk(Chunk chunk) { 1766disassemble_chunk(Chunk chunk) {
833 println("%s: ============== code ==============", chunk.file_name); 1767 println("CHUNK %d: %s%s", chunk.id, chunk.file_name, chunk.name);
1768 println("n_regs: %d, n_vars: %d, n_strings: %d, n_consts: %d",
1769 chunk.reg_idx, array_size(chunk.vars), chunk.str_idx,
1770 chunk.const_idx);
1771 println("================== code ==================");
1772 println(" LINE:COL INUM LABELS OP OPERANDS ");
1773 println("------------------------------------------");
834 for (sz i = 0; i < array_size(chunk.code); i++) { 1774 for (sz i = 0; i < array_size(chunk.code); i++) {
835 print("%s: %x{4}: ", chunk.file_name, i); 1775 printf(" %.4ld:%.4ld %.4lx ", chunk.linecol[i].line,
1776 chunk.linecol[i].col, i);
1777 IntIntMapIter lab_it = intintmap_iterator(chunk.labels, chunk.storage);
1778 IntIntMap *m = intintmap_next(&lab_it, chunk.storage);
1779 Str labs = cstr("");
1780 while (m) {
1781 if (m->val == i) {
1782 labs = str_concat(labs, cstr(".L"), chunk.storage);
1783 labs = str_concat(labs, str_from_int(m->key, chunk.storage),
1784 chunk.storage);
1785 break;
1786 }
1787 m = intintmap_next(&lab_it, chunk.storage);
1788 }
1789 if (labs.size) {
1790 print("%s", labs);
1791 for (sz i = 0; i < 7 - labs.size; i++) {
1792 print(" ");
1793 }
1794 } else {
1795 printf(" ");
1796 }
836 disassemble_instruction(chunk.code[i]); 1797 disassemble_instruction(chunk.code[i]);
837 } 1798 }
838 if (array_size(chunk.constants) > 0) { 1799 if (array_size(chunk.constants) > 0) {
839 println("%s: ============ constants ===========", chunk.file_name); 1800 println("================ constants ===============", chunk.file_name);
840 for (sz i = 0; i < array_size(chunk.constants); i++) { 1801 for (sz i = 0; i < array_size(chunk.constants); i++) {
841 println("%s: %x{2}: %x{8}", chunk.file_name, i, 1802 println(" %x{2}: %x{8}", i, chunk.constants[i]);
842 chunk.constants[i]);
843 } 1803 }
844 } 1804 }
845 if (array_size(chunk.strings) > 0) { 1805 if (array_size(chunk.strings) > 0) {
846 println("%s: ============= strings ============", chunk.file_name); 1806 println("================= strings ================", chunk.file_name);
847 for (sz i = 0; i < array_size(chunk.strings); i++) { 1807 for (sz i = 0; i < array_size(chunk.strings); i++) {
848 println("%s: %x{2}: %s", chunk.file_name, i, chunk.strings[i]); 1808 println(" %x{2}: %s", i, chunk.strings[i]);
849 } 1809 }
850 } 1810 }
851 if (array_size(chunk.vars) > 0) { 1811 if (array_size(chunk.vars) > 0) {
852 println("%s: ============ variables ===========", chunk.file_name); 1812 println("================ variables ===============", chunk.file_name);
853 for (sz i = 0; i < array_size(chunk.vars); i++) { 1813 for (sz i = 0; i < array_size(chunk.vars); i++) {
854 println("%s: %x{2}: [%x{4}:%x{4}] %s: %s", chunk.file_name, i, 1814 println(" %x{2}: [%x{4}:%x{4}] %s: %s", i, chunk.vars[i].offset,
855 chunk.vars[i].offset,
856 chunk.vars[i].offset + chunk.vars[i].size, 1815 chunk.vars[i].offset + chunk.vars[i].size,
857 chunk.vars[i].name, chunk.vars[i].type); 1816 chunk.vars[i].name, chunk.vars[i].type);
858 } 1817 }
859 } 1818 }
860 println("n_regs: %d, n_vars: %d, n_strings: %d, n_consts: %d", 1819 if (array_size(chunk.functions) > 0) {
861 chunk.reg_idx, array_size(chunk.vars), chunk.str_idx, 1820 println("================ functions ===============", chunk.file_name);
862 chunk.const_idx); 1821 for (sz i = 0; i < array_size(chunk.functions); i++) {
1822 Chunk *func = chunk.functions[i];
1823 println(" %x{2}: func%d: %s", i, func->id, func->name);
1824 }
1825 }
1826 println("==========================================");
1827 for (sz i = 0; i < array_size(chunk.functions); i++) {
1828 Chunk *func = chunk.functions[i];
1829 disassemble_chunk(*func);
1830 }
1831}
1832
1833void
1834bytecode_compiler(Compiler *compiler, Parser parser) {
1835 compiler->main_chunk = (Chunk){
1836 .file_name = compiler->file_name,
1837 .storage = compiler->storage,
1838 .name = cstr(".main"),
1839 };
1840 // TODO: Fill up builtin types and tables.
1841 array_zero(compiler->main_chunk.constants, 256, compiler->storage);
1842 array_zero(compiler->main_chunk.code, 0xffff, compiler->storage);
1843 sz n_roots = array_size(parser.nodes);
1844 CompResult res = {0};
1845
1846 // Do a first pass to setup the function declarations on the main scope.
1847 Chunk *chunk = &compiler->main_chunk;
1848 for (sz i = 0; i < n_roots; i++) {
1849 Node *root = parser.nodes[i];
1850 if (root->kind == NODE_FUN) {
1851 declare_function(chunk, root);
1852 }
1853 }
1854
1855 // Compile all root expressions.
1856 for (sz i = 0; i < n_roots; i++) {
1857 Node *root = parser.nodes[i];
1858 res = compile_expr(compiler, chunk, root);
1859 }
1860
1861 // Make sure the last result is on r0.
1862 sz res_reg = 0;
1863 bool is_nil = false;
1864 switch (res.type) {
1865 case COMP_CONST: {
1866 res_reg = chunk->reg_idx++;
1867 Instruction inst =
1868 (Instruction){.op = OP_LD64K, .dst = res_reg, .a = res.idx};
1869 array_push(chunk->code, inst, chunk->storage);
1870 } break;
1871 case COMP_REG: {
1872 res_reg = res.idx;
1873 } break;
1874 case COMP_NIL: {
1875 is_nil = true;
1876 } break;
1877 default: break;
1878 }
1879 emit_op(OP_HALT, res_reg, !is_nil, 0, NULL, chunk);
1880 verify_chunk(chunk);
863} 1881}
864 1882
865#endif // COMPILER_C 1883#endif // COMPILER_C
diff --git a/src/lexer.c b/src/lexer.c
index 2feba2a..22d7edc 100644
--- a/src/lexer.c
+++ b/src/lexer.c
@@ -41,13 +41,19 @@ typedef enum TokenKind {
41 TOK_STRUCT, // struct 41 TOK_STRUCT, // struct
42 TOK_TRUE, // true 42 TOK_TRUE, // true
43 TOK_WHILE, // while 43 TOK_WHILE, // while
44 TOK_FOR, // for
44 45
45 // Arithmetic ops. 46 // Arithmetic ops.
46 TOK_ADD, // + 47 TOK_ADD, // +
47 TOK_SUB, // - 48 TOK_SUB, // -
48 TOK_MUL, // * 49 TOK_MUL, // *
49 TOK_DIV, // / 50 TOK_DIV, // /
50 TOK_MOD, // % 51 TOK_MOD, // %
52 TOK_ADD_ASSIGN, // +=
53 TOK_SUB_ASSIGN, // -=
54 TOK_MUL_ASSIGN, // *=
55 TOK_DIV_ASSIGN, // /=
56 TOK_MOD_ASSIGN, // %=
51 57
52 // Logical ops. 58 // Logical ops.
53 TOK_NOT, // ! 59 TOK_NOT, // !
@@ -61,11 +67,17 @@ typedef enum TokenKind {
61 TOK_GE, // >= 67 TOK_GE, // >=
62 68
63 // Bitwise ops. 69 // Bitwise ops.
64 TOK_BITNOT, // ~ 70 TOK_BITNOT, // ~
65 TOK_BITAND, // & 71 TOK_BITAND, // &
66 TOK_BITOR, // | 72 TOK_BITOR, // |
67 TOK_BITLSHIFT, // << 73 TOK_BITXOR, // ^
68 TOK_BITRSHIFT, // >> 74 TOK_BITLSHIFT, // <<
75 TOK_BITRSHIFT, // >>
76 TOK_BITAND_ASSIGN, // &=
77 TOK_BITOR_ASSIGN, // |=
78 TOK_BITXOR_ASSIGN, // ^=
79 TOK_BITLSHIFT_ASSIGN, // <<=
80 TOK_BITRSHIFT_ASSIGN, // >>=
69 81
70 // Special ops. 82 // Special ops.
71 TOK_COLON, // : 83 TOK_COLON, // :
@@ -113,6 +125,7 @@ Str token_str[] = {
113 [TOK_STRUCT] = cstr("STRUCT"), 125 [TOK_STRUCT] = cstr("STRUCT"),
114 [TOK_TRUE] = cstr("TRUE"), 126 [TOK_TRUE] = cstr("TRUE"),
115 [TOK_WHILE] = cstr("WHILE"), 127 [TOK_WHILE] = cstr("WHILE"),
128 [TOK_FOR] = cstr("FOR"),
116 129
117 // Arithmetic ops. 130 // Arithmetic ops.
118 [TOK_ADD] = cstr("ADD"), 131 [TOK_ADD] = cstr("ADD"),
@@ -120,6 +133,11 @@ Str token_str[] = {
120 [TOK_MUL] = cstr("MUL"), 133 [TOK_MUL] = cstr("MUL"),
121 [TOK_DIV] = cstr("DIV"), 134 [TOK_DIV] = cstr("DIV"),
122 [TOK_MOD] = cstr("MOD"), 135 [TOK_MOD] = cstr("MOD"),
136 [TOK_ADD_ASSIGN] = cstr("ADD_ASSIGN"),
137 [TOK_SUB_ASSIGN] = cstr("SUB_ASSIGN"),
138 [TOK_MUL_ASSIGN] = cstr("MUL_ASSIGN"),
139 [TOK_DIV_ASSIGN] = cstr("DIV_ASSIGN"),
140 [TOK_MOD_ASSIGN] = cstr("MOD_ASSIGN"),
123 141
124 // Logical ops. 142 // Logical ops.
125 [TOK_NOT] = cstr("NOT"), 143 [TOK_NOT] = cstr("NOT"),
@@ -136,8 +154,14 @@ Str token_str[] = {
136 [TOK_BITNOT] = cstr("BITNOT"), 154 [TOK_BITNOT] = cstr("BITNOT"),
137 [TOK_BITAND] = cstr("BITAND"), 155 [TOK_BITAND] = cstr("BITAND"),
138 [TOK_BITOR] = cstr("BITOR"), 156 [TOK_BITOR] = cstr("BITOR"),
157 [TOK_BITXOR] = cstr("BITXOR"),
139 [TOK_BITLSHIFT] = cstr("BITLSHIFT"), 158 [TOK_BITLSHIFT] = cstr("BITLSHIFT"),
140 [TOK_BITRSHIFT] = cstr("BITRSHIFT"), 159 [TOK_BITRSHIFT] = cstr("BITRSHIFT"),
160 [TOK_BITAND_ASSIGN] = cstr("BITAND_ASSIGN"),
161 [TOK_BITOR_ASSIGN] = cstr("BITOR_ASSIGN"),
162 [TOK_BITXOR_ASSIGN] = cstr("BITXOR_ASSIGN"),
163 [TOK_BITLSHIFT_ASSIGN] = cstr("BITLSHIFT_ASSIGN"),
164 [TOK_BITRSHIFT_ASSIGN] = cstr("BITRSHIFT_ASSIGN"),
141 165
142 // Special ops. 166 // Special ops.
143 [TOK_COLON] = cstr("COLON"), 167 [TOK_COLON] = cstr("COLON"),
@@ -429,22 +453,48 @@ scan_token(Scanner *scanner) {
429 case '+': { 453 case '+': {
430 char p = scan_peek(scanner); 454 char p = scan_peek(scanner);
431 if (p >= '0' && p <= '9') { 455 if (p >= '0' && p <= '9') {
432 *scanner = current; 456 scan_next(scanner);
433 return emit_token_number(scanner); 457 return emit_token_number(scanner);
434 } 458 }
459 if (p == '=') {
460 scan_next(scanner);
461 return emit_token(current, scanner, TOK_ADD_ASSIGN);
462 }
435 return emit_token(current, scanner, TOK_ADD); 463 return emit_token(current, scanner, TOK_ADD);
436 }; 464 };
437 case '-': { 465 case '-': {
438 char p = scan_peek(scanner); 466 char p = scan_peek(scanner);
439 if (p >= '0' && p <= '9') { 467 if (p >= '0' && p <= '9') {
440 *scanner = current; 468 scan_next(scanner);
441 return emit_token_number(scanner); 469 return emit_token_number(scanner);
442 } 470 }
471 if (p == '=') {
472 scan_next(scanner);
473 return emit_token(current, scanner, TOK_SUB_ASSIGN);
474 }
443 return emit_token(current, scanner, TOK_SUB); 475 return emit_token(current, scanner, TOK_SUB);
444 }; 476 };
445 case '*': return emit_token(current, scanner, TOK_MUL); 477 case '*': {
446 case '/': return emit_token(current, scanner, TOK_DIV); 478 if (scan_peek(scanner) == '=') {
447 case '%': return emit_token(current, scanner, TOK_MOD); 479 scan_next(scanner);
480 return emit_token(current, scanner, TOK_MUL_ASSIGN);
481 }
482 return emit_token(current, scanner, TOK_MUL);
483 }
484 case '/': {
485 if (scan_peek(scanner) == '=') {
486 scan_next(scanner);
487 return emit_token(current, scanner, TOK_DIV_ASSIGN);
488 }
489 return emit_token(current, scanner, TOK_DIV);
490 }
491 case '%': {
492 if (scan_peek(scanner) == '=') {
493 scan_next(scanner);
494 return emit_token(current, scanner, TOK_MOD_ASSIGN);
495 }
496 return emit_token(current, scanner, TOK_MOD);
497 }
448 case '!': { 498 case '!': {
449 if (scan_peek(scanner) == '=') { 499 if (scan_peek(scanner) == '=') {
450 scan_next(scanner); 500 scan_next(scanner);
@@ -467,6 +517,10 @@ scan_token(Scanner *scanner) {
467 } 517 }
468 if (p == '<') { 518 if (p == '<') {
469 scan_next(scanner); 519 scan_next(scanner);
520 if (scan_peek(scanner) == '=') {
521 scan_next(scanner);
522 return emit_token(current, scanner, TOK_BITLSHIFT_ASSIGN);
523 }
470 return emit_token(current, scanner, TOK_BITLSHIFT); 524 return emit_token(current, scanner, TOK_BITLSHIFT);
471 } 525 }
472 return emit_token(current, scanner, TOK_LT); 526 return emit_token(current, scanner, TOK_LT);
@@ -479,23 +533,44 @@ scan_token(Scanner *scanner) {
479 } 533 }
480 if (p == '>') { 534 if (p == '>') {
481 scan_next(scanner); 535 scan_next(scanner);
536 if (scan_peek(scanner) == '=') {
537 scan_next(scanner);
538 return emit_token(current, scanner, TOK_BITRSHIFT_ASSIGN);
539 }
482 return emit_token(current, scanner, TOK_BITRSHIFT); 540 return emit_token(current, scanner, TOK_BITRSHIFT);
483 } 541 }
484 return emit_token(current, scanner, TOK_GT); 542 return emit_token(current, scanner, TOK_GT);
485 }; 543 };
486 case '~': return emit_token(current, scanner, TOK_BITNOT); 544 case '~': return emit_token(current, scanner, TOK_BITNOT);
545 case '^': {
546 if (scan_peek(scanner) == '=') {
547 scan_next(scanner);
548 return emit_token(current, scanner, TOK_BITXOR_ASSIGN);
549 }
550 return emit_token(current, scanner, TOK_BITXOR);
551 };
487 case '&': { 552 case '&': {
488 if (scan_peek(scanner) == '&') { 553 char p = scan_peek(scanner);
554 if (p == '&') {
489 scan_next(scanner); 555 scan_next(scanner);
490 return emit_token(current, scanner, TOK_AND); 556 return emit_token(current, scanner, TOK_AND);
491 } 557 }
558 if (p == '=') {
559 scan_next(scanner);
560 return emit_token(current, scanner, TOK_BITOR_ASSIGN);
561 }
492 return emit_token(current, scanner, TOK_BITAND); 562 return emit_token(current, scanner, TOK_BITAND);
493 }; 563 };
494 case '|': { 564 case '|': {
495 if (scan_peek(scanner) == '|') { 565 char p = scan_peek(scanner);
566 if (p == '|') {
496 scan_next(scanner); 567 scan_next(scanner);
497 return emit_token(current, scanner, TOK_OR); 568 return emit_token(current, scanner, TOK_OR);
498 } 569 }
570 if (p == '=') {
571 scan_next(scanner);
572 return emit_token(current, scanner, TOK_BITOR_ASSIGN);
573 }
499 return emit_token(current, scanner, TOK_BITOR); 574 return emit_token(current, scanner, TOK_BITOR);
500 }; 575 };
501 case ':': return emit_token(current, scanner, TOK_COLON); 576 case ':': return emit_token(current, scanner, TOK_COLON);
@@ -536,77 +611,80 @@ scan_token(Scanner *scanner) {
536 } 611 }
537 switch (val.mem[0]) { 612 switch (val.mem[0]) {
538 case 'b': { 613 case 'b': {
539 if (str_has_prefix(val, cstr("break"))) { 614 if (str_eq(val, cstr("break"))) {
540 return emit_token(current, scanner, TOK_BREAK); 615 return emit_token(current, scanner, TOK_BREAK);
541 } 616 }
542 } break; 617 } break;
543 case 'c': { 618 case 'c': {
544 if (str_has_prefix(val, cstr("case"))) { 619 if (str_eq(val, cstr("case"))) {
545 return emit_token(current, scanner, TOK_CASE); 620 return emit_token(current, scanner, TOK_CASE);
546 } 621 }
547 if (str_has_prefix(val, cstr("continue"))) { 622 if (str_eq(val, cstr("continue"))) {
548 return emit_token(current, scanner, TOK_CONTINUE); 623 return emit_token(current, scanner, TOK_CONTINUE);
549 } 624 }
550 if (str_has_prefix(val, cstr("cond"))) { 625 if (str_eq(val, cstr("cond"))) {
551 return emit_token(current, scanner, TOK_COND); 626 return emit_token(current, scanner, TOK_COND);
552 } 627 }
553 } break; 628 } break;
554 case 'e': { 629 case 'e': {
555 if (str_has_prefix(val, cstr("else"))) { 630 if (str_eq(val, cstr("else"))) {
556 return emit_token(current, scanner, TOK_ELSE); 631 return emit_token(current, scanner, TOK_ELSE);
557 } 632 }
558 if (str_has_prefix(val, cstr("enum"))) { 633 if (str_eq(val, cstr("enum"))) {
559 return emit_token(current, scanner, TOK_ENUM); 634 return emit_token(current, scanner, TOK_ENUM);
560 } 635 }
561 } break; 636 } break;
562 case 'f': { 637 case 'f': {
563 if (str_has_prefix(val, cstr("false"))) { 638 if (str_eq(val, cstr("false"))) {
564 return emit_token(current, scanner, TOK_FALSE); 639 return emit_token(current, scanner, TOK_FALSE);
565 } 640 }
566 if (str_has_prefix(val, cstr("fun"))) { 641 if (str_eq(val, cstr("fun"))) {
567 return emit_token(current, scanner, TOK_FUN); 642 return emit_token(current, scanner, TOK_FUN);
568 } 643 }
644 if (str_eq(val, cstr("for"))) {
645 return emit_token(current, scanner, TOK_FOR);
646 }
569 } break; 647 } break;
570 case 'i': { 648 case 'i': {
571 if (str_has_prefix(val, cstr("if"))) { 649 if (str_eq(val, cstr("if"))) {
572 return emit_token(current, scanner, TOK_IF); 650 return emit_token(current, scanner, TOK_IF);
573 } 651 }
574 } break; 652 } break;
575 case 'l': { 653 case 'l': {
576 if (str_has_prefix(val, cstr("let"))) { 654 if (str_eq(val, cstr("let"))) {
577 return emit_token(current, scanner, TOK_LET); 655 return emit_token(current, scanner, TOK_LET);
578 } 656 }
579 } break; 657 } break;
580 case 'm': { 658 case 'm': {
581 if (str_has_prefix(val, cstr("match"))) { 659 if (str_eq(val, cstr("match"))) {
582 return emit_token(current, scanner, TOK_MATCH); 660 return emit_token(current, scanner, TOK_MATCH);
583 } 661 }
584 } break; 662 } break;
585 case 'n': { 663 case 'n': {
586 if (str_has_prefix(val, cstr("nil"))) { 664 if (str_eq(val, cstr("nil"))) {
587 return emit_token(current, scanner, TOK_NIL); 665 return emit_token(current, scanner, TOK_NIL);
588 } 666 }
589 } break; 667 } break;
590 case 'r': { 668 case 'r': {
591 if (str_has_prefix(val, cstr("return"))) { 669 if (str_eq(val, cstr("return"))) {
592 return emit_token(current, scanner, TOK_RETURN); 670 return emit_token(current, scanner, TOK_RETURN);
593 } 671 }
594 } break; 672 } break;
595 case 's': { 673 case 's': {
596 if (str_has_prefix(val, cstr("set"))) { 674 if (str_eq(val, cstr("set"))) {
597 return emit_token(current, scanner, TOK_SET); 675 return emit_token(current, scanner, TOK_SET);
598 } 676 }
599 if (str_has_prefix(val, cstr("struct"))) { 677 if (str_eq(val, cstr("struct"))) {
600 return emit_token(current, scanner, TOK_STRUCT); 678 return emit_token(current, scanner, TOK_STRUCT);
601 } 679 }
602 } break; 680 } break;
603 case 't': { 681 case 't': {
604 if (str_has_prefix(val, cstr("true"))) { 682 if (str_eq(val, cstr("true"))) {
605 return emit_token(current, scanner, TOK_TRUE); 683 return emit_token(current, scanner, TOK_TRUE);
606 } 684 }
607 } break; 685 } break;
608 case 'w': { 686 case 'w': {
609 if (str_has_prefix(val, cstr("while"))) { 687 if (str_eq(val, cstr("while"))) {
610 return emit_token(current, scanner, TOK_WHILE); 688 return emit_token(current, scanner, TOK_WHILE);
611 } 689 }
612 } break; 690 } break;
@@ -628,4 +706,4 @@ print_tokens(Str path, Token *tokens) {
628 } 706 }
629} 707}
630 708
631#endif // LEXER_C 709#endif // LEXER_C
diff --git a/src/main.c b/src/main.c
index 0e453c6..65c05ff 100644
--- a/src/main.c
+++ b/src/main.c
@@ -12,7 +12,26 @@
12// TODO: unions 12// TODO: unions
13// TODO: embed (binary file) and include (source file) 13// TODO: embed (binary file) and include (source file)
14// TODO: revisit ast parsing for pointers and arrays (I think I'm missing corner 14// TODO: revisit ast parsing for pointers and arrays (I think I'm missing corner
15// cases). 15// cases).
16// TODO: fix semantics for the following expression:
17// let b = int
18// a type shouldn't be a valid symbol name
19// TODO: consider making all tye types PascalCase: Int F64 Str...
20// TODO: add a `const` keyword that can only take literals or constexpr values.
21// TODO: "first class functions" via function pointers
22// TODO: convenient function calls per data type instead of methods:
23// fun add(a: int, b: int): int a + b
24// add(12, 34) == 12.add(34)
25// concat(str, str): str
26// "hello ".concat("world") ; "hello world"
27// TODO: more numeric types
28// TODO: structs and user defined types
29// TODO: tail-call optimization.
30// TODO: constant folding
31// TODO: constexpr evaluation
32// TODO: shortcircuit evaluation for && and || operators.
33// TODO: casting on demand (1:u16, 0x123:ptr, "hi":int ??? how to deal with
34// unsafe casts?)
16 35
17typedef enum ExecMode { 36typedef enum ExecMode {
18 RUN_NORMAL, 37 RUN_NORMAL,
@@ -44,6 +63,9 @@ process_file(Str path) {
44 sz errors = 0; 63 sz errors = 0;
45 64
46 // Lexer. 65 // Lexer.
66#if DEBUG == 1
67 println("lexing...");
68#endif
47 Scanner scanner = {.str = file.data}; 69 Scanner scanner = {.str = file.data};
48 Token *tokens = NULL; 70 Token *tokens = NULL;
49 Token tok = {0}; 71 Token tok = {0};
@@ -67,6 +89,9 @@ process_file(Str path) {
67 } 89 }
68 90
69 // Parser. 91 // Parser.
92#if DEBUG == 1
93 println("parsing...");
94#endif
70 Parser parser = { 95 Parser parser = {
71 .tokens = tokens, 96 .tokens = tokens,
72 .storage = &lexer_arena, 97 .storage = &lexer_arena,
@@ -94,6 +119,9 @@ process_file(Str path) {
94 } 119 }
95 120
96 // Semantic analysis. 121 // Semantic analysis.
122#if DEBUG == 1
123 println("semantic analysis...");
124#endif
97 Analyzer analyzer = (Analyzer){ 125 Analyzer analyzer = (Analyzer){
98 .storage = &lexer_arena, 126 .storage = &lexer_arena,
99 .file_name = path, 127 .file_name = path,
@@ -166,63 +194,27 @@ process_file(Str path) {
166 // TODO: Type checking. 194 // TODO: Type checking.
167 195
168 // Compile roots. 196 // Compile roots.
197#if DEBUG == 1
198 println("compilation...");
199#endif
169 Arena bytecode_arena = arena_create(LEXER_MEM, os_allocator); 200 Arena bytecode_arena = arena_create(LEXER_MEM, os_allocator);
170 Chunk chunk = {.file_name = path, .storage = &bytecode_arena}; 201 Compiler compiler = {
171 array_zero(chunk.constants, 256, &bytecode_arena); 202 .file_name = path,
172 array_zero(chunk.code, 0xffff, &bytecode_arena); 203 .storage = &bytecode_arena,
173 sz n_roots = array_size(parser.nodes); 204 .integer_types = analyzer.integer_types,
174 CompResult res = {0}; 205 .numeric_types = analyzer.numeric_types,
175 for (sz i = 0; i < n_roots; i++) { 206 };
176 // The parser stores the root nodes as a stack. 207 bytecode_compiler(&compiler, parser);
177 Node *root = parser.nodes[i]; 208 disassemble_chunk(compiler.main_chunk);
178 res = compile_expr(&chunk, root);
179 if (res.type == COMP_ERR) {
180 eprintln("compilation error...");
181 exit(EXIT_FAILURE);
182 }
183 }
184 sz res_reg = 0;
185 switch (res.type) {
186 case COMP_CONST: {
187 res_reg = chunk.reg_idx++;
188 Instruction inst =
189 (Instruction){.op = OP_LD64K, .dst = res_reg, .a = res.idx};
190 array_push(chunk.code, inst, chunk.storage);
191 } break;
192 case COMP_REG: {
193 res_reg = res.idx;
194 } break;
195 default: break;
196 }
197 // After we are done move the last result to r0 for printing.
198 Instruction halt = (Instruction){.op = OP_HALT, .dst = res_reg};
199 array_push(chunk.code, halt, &bytecode_arena);
200
201 if (chunk.const_idx >= 256) {
202 eprintln("too many constants on chunk %s", chunk.id);
203 exit(EXIT_FAILURE);
204 }
205 if (chunk.str_idx >= 256) {
206 eprintln("too many strings on chunk %s", chunk.id);
207 exit(EXIT_FAILURE);
208 }
209 if (chunk.reg_idx >= 256) {
210 eprintln("too many registers used on chunk %s", chunk.id);
211 exit(EXIT_FAILURE);
212 }
213
214 disassemble_chunk(chunk);
215 209
216 // Run bytecode on VM. 210 // Run bytecode on VM.
217 VM vm = {0}; 211 VM vm = {0};
218 vm_init(&vm, &chunk); 212 vm_init(&vm, &compiler.main_chunk);
219 // println("VM REGISTERS BEFORE:\n%{Mem}",
220 // &(Array){.mem = (u8 *)&vm.regs, sizeof(vm.regs)});
221 vm_run(&vm); 213 vm_run(&vm);
222 // println("VM REGISTERS AFTER:\n%{Mem}", 214#if DEBUG == 1
223 // &(Array){.mem = (u8 *)&vm.regs, sizeof(vm.regs)}); 215 println("MEMORY:\n%{Mem}",
224 // println("VM MEMORY AFTER:\n%{Mem}", 216 &(Array){.mem = (u8 *)&vm.stack, sizeof(vm.stack)});
225 // &(Array){.mem = (u8 *)&vm.stack, sizeof(vm.stack)}); 217#endif
226 218
227#if DEBUG == 1 219#if DEBUG == 1
228 println("Space used: %{Arena}", &lexer_arena); 220 println("Space used: %{Arena}", &lexer_arena);
diff --git a/src/parser.c b/src/parser.c
index 90adaf3..5253841 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -9,6 +9,7 @@
9// 9//
10 10
11typedef enum NodeKind { 11typedef enum NodeKind {
12 NODE_ERR,
12 // Arithmetic. 13 // Arithmetic.
13 NODE_ADD, 14 NODE_ADD,
14 NODE_SUB, 15 NODE_SUB,
@@ -29,6 +30,7 @@ typedef enum NodeKind {
29 NODE_BITNOT, 30 NODE_BITNOT,
30 NODE_BITAND, 31 NODE_BITAND,
31 NODE_BITOR, 32 NODE_BITOR,
33 NODE_BITXOR,
32 NODE_BITLSHIFT, 34 NODE_BITLSHIFT,
33 NODE_BITRSHIFT, 35 NODE_BITRSHIFT,
34 // Literals. 36 // Literals.
@@ -69,6 +71,7 @@ typedef enum NodeKind {
69} NodeKind; 71} NodeKind;
70 72
71Str node_str[] = { 73Str node_str[] = {
74 [NODE_ERR] = cstr("ERR"),
72 // Arithmetic. 75 // Arithmetic.
73 [NODE_ADD] = cstr("ADD"), 76 [NODE_ADD] = cstr("ADD"),
74 [NODE_SUB] = cstr("SUB"), 77 [NODE_SUB] = cstr("SUB"),
@@ -89,6 +92,7 @@ Str node_str[] = {
89 [NODE_BITNOT] = cstr("BITNOT"), 92 [NODE_BITNOT] = cstr("BITNOT"),
90 [NODE_BITAND] = cstr("BITAND"), 93 [NODE_BITAND] = cstr("BITAND"),
91 [NODE_BITOR] = cstr("BITOR"), 94 [NODE_BITOR] = cstr("BITOR"),
95 [NODE_BITXOR] = cstr("BITXOR"),
92 [NODE_BITLSHIFT] = cstr("BITLSHIFT"), 96 [NODE_BITLSHIFT] = cstr("BITLSHIFT"),
93 [NODE_BITRSHIFT] = cstr("BITRSHIFT"), 97 [NODE_BITRSHIFT] = cstr("BITRSHIFT"),
94 // Literals. 98 // Literals.
@@ -128,75 +132,102 @@ Str node_str[] = {
128 [NODE_BLOCK] = cstr("BLOCK"), 132 [NODE_BLOCK] = cstr("BLOCK"),
129}; 133};
130 134
135typedef union NodeLit {
136 f64 d;
137 sz i;
138 u64 u;
139 Str str;
140 Str sym;
141} NodeLit;
142
143typedef struct NodeBinary {
144 struct Node *left;
145 struct Node *right;
146} NodeBinary;
147
148typedef struct NodeUnary {
149 struct Node *left;
150} NodeUnary;
151
152typedef struct NodeVariable {
153 struct Node *name;
154 struct Node *type;
155 struct Node *val;
156} NodeVariable;
157
158typedef struct NodeLoop {
159 struct Node *cond;
160 struct Node *expr;
161} NodeLoop;
162
163typedef struct NodeIf {
164 struct Node *cond;
165 struct Node *expr_true;
166 struct Node *expr_else;
167} NodeIf;
168
169typedef struct NodeField {
170 struct Node *type;
171 struct Node *val;
172} NodeField;
173
174typedef struct NodeParam {
175 struct Node *name;
176 struct Node *type;
177} NodeParam;
178
179typedef struct NodeMatch {
180 struct Node *expr;
181 struct Node **cases;
182} NodeMatch;
183
184typedef struct NodeCase {
185 struct Node *cond;
186 struct Node *expr;
187} NodeCase;
188
189typedef struct NodeFunction {
190 struct Node *name;
191 struct Node **params;
192 struct Node **ret;
193 struct Node *body;
194} NodeFunction;
195
196typedef struct NodeSymbol {
197 struct Node *next;
198 struct Node *arr_size;
199} NodeSymbol;
200
131typedef struct Node { 201typedef struct Node {
132 sz id; 202 sz id;
133 sz line; 203 sz line;
134 sz col; 204 sz col;
205 struct Node *parent;
135 206
136 NodeKind kind; 207 NodeKind kind;
208 NodeLit value;
137 union { 209 union {
138 f64 d; 210 NodeBinary binary;
139 sz i; 211 NodeUnary unary;
140 u64 u; 212 NodeVariable var;
141 Str str; 213 NodeSymbol sym;
142 Str sym; 214 NodeLoop loop;
143 } value; 215 NodeIf ifelse;
144 union { 216 NodeField field;
145 struct { 217 NodeParam param;
146 struct Node *left; 218 NodeMatch match;
147 struct Node *right; 219 NodeCase case_entry;
148 }; 220 NodeFunction func;
149 struct {
150 struct Node *next;
151 struct Node *arr_size;
152 };
153 struct {
154 struct Node *var_name;
155 struct Node *var_type;
156 struct Node *var_val;
157 };
158 struct {
159 struct Node *while_cond;
160 struct Node *while_expr;
161 };
162 struct {
163 struct Node *cond_if;
164 struct Node *cond_expr;
165 struct Node *cond_else;
166 };
167 struct {
168 struct Node *field_type;
169 struct Node *field_val;
170 };
171 struct {
172 struct Node *param_name;
173 struct Node *param_type;
174 };
175 struct {
176 struct Node *match_expr;
177 struct Node **match_cases;
178 };
179 struct {
180 struct Node *case_value;
181 struct Node *case_expr;
182 };
183 struct Node **struct_field; 221 struct Node **struct_field;
184 struct Node **elements; 222 struct Node **elements;
185 struct Node **statements; 223 struct Node **statements;
186 struct Node **expressions; 224 struct Node **expressions;
187 struct Node **arguments; 225 struct Node **arguments;
188 struct {
189 struct Node *func_name;
190 struct Node **func_params;
191 struct Node **func_ret;
192 struct Node *func_body;
193 };
194 }; 226 };
195 bool is_ptr; 227 bool is_ptr;
196 struct Scope *scope;
197 Str type; 228 Str type;
198 Str fun_params; 229 Str type_params;
199 Str fun_return; 230 Str type_returns;
200 Str unique_name; 231 Str unique_name;
201} Node; 232} Node;
202 233
@@ -286,6 +317,7 @@ ParseRule parse_rules[] = {
286 [TOK_BITNOT] = {parse_unary, NULL, PREC_NONE}, 317 [TOK_BITNOT] = {parse_unary, NULL, PREC_NONE},
287 [TOK_BITAND] = {NULL, parse_binary, PREC_BITLOGIC}, 318 [TOK_BITAND] = {NULL, parse_binary, PREC_BITLOGIC},
288 [TOK_BITOR] = {NULL, parse_binary, PREC_BITLOGIC}, 319 [TOK_BITOR] = {NULL, parse_binary, PREC_BITLOGIC},
320 [TOK_BITXOR] = {NULL, parse_binary, PREC_BITLOGIC},
289 [TOK_BITLSHIFT] = {NULL, parse_binary, PREC_BITSHIFT}, 321 [TOK_BITLSHIFT] = {NULL, parse_binary, PREC_BITSHIFT},
290 [TOK_BITRSHIFT] = {NULL, parse_binary, PREC_BITSHIFT}, 322 [TOK_BITRSHIFT] = {NULL, parse_binary, PREC_BITSHIFT},
291 323
@@ -308,6 +340,7 @@ ParseRule parse_rules[] = {
308 [TOK_MATCH] = {parse_keyword, NULL, PREC_NONE}, 340 [TOK_MATCH] = {parse_keyword, NULL, PREC_NONE},
309 [TOK_COND] = {parse_keyword, NULL, PREC_NONE}, 341 [TOK_COND] = {parse_keyword, NULL, PREC_NONE},
310 [TOK_WHILE] = {parse_keyword, NULL, PREC_NONE}, 342 [TOK_WHILE] = {parse_keyword, NULL, PREC_NONE},
343 [TOK_FOR] = {parse_keyword, NULL, PREC_NONE},
311 [TOK_CONTINUE] = {parse_keyword, NULL, PREC_NONE}, 344 [TOK_CONTINUE] = {parse_keyword, NULL, PREC_NONE},
312 [TOK_BREAK] = {parse_keyword, NULL, PREC_NONE}, 345 [TOK_BREAK] = {parse_keyword, NULL, PREC_NONE},
313 [TOK_FUN] = {parse_keyword, NULL, PREC_NONE}, 346 [TOK_FUN] = {parse_keyword, NULL, PREC_NONE},
@@ -437,7 +470,7 @@ parse_unary(Parser *parser) {
437 default: break; // Unreachable. 470 default: break; // Unreachable.
438 } 471 }
439 if (!node) return; 472 if (!node) return;
440 node->left = array_pop(parser->nodes); 473 node->unary.left = array_pop(parser->nodes);
441 array_push(parser->nodes, node, parser->storage); 474 array_push(parser->nodes, node, parser->storage);
442} 475}
443 476
@@ -482,7 +515,7 @@ parse_type(Parser *parser) {
482 node->kind = NODE_ARR_TYPE, 515 node->kind = NODE_ARR_TYPE,
483 parse_consume(parser, TOK_NUM_INT, cstr("no array size given")); 516 parse_consume(parser, TOK_NUM_INT, cstr("no array size given"));
484 parse_number(parser); 517 parse_number(parser);
485 node->arr_size = array_pop(parser->nodes); 518 node->sym.arr_size = array_pop(parser->nodes);
486 parse_consume(parser, TOK_RSQUARE, 519 parse_consume(parser, TOK_RSQUARE,
487 cstr("unmatched brackets ']' in array type")); 520 cstr("unmatched brackets ']' in array type"));
488 } 521 }
@@ -510,16 +543,16 @@ parse_struct_field(Parser *parser) {
510 Node *subfield = array_pop(parser->nodes); 543 Node *subfield = array_pop(parser->nodes);
511 array_push(type->elements, subfield, parser->storage); 544 array_push(type->elements, subfield, parser->storage);
512 } 545 }
513 field->field_type = type; 546 field->field.type = type;
514 } else { 547 } else {
515 parse_type(parser); 548 parse_type(parser);
516 field->field_type = array_pop(parser->nodes); 549 field->field.type = array_pop(parser->nodes);
517 } 550 }
518 551
519 // Optional assignment. 552 // Optional assignment.
520 if (parse_match(parser, TOK_ASSIGN)) { 553 if (parse_match(parser, TOK_ASSIGN)) {
521 parse_expr(parser, PREC_LOW); 554 parse_expr(parser, PREC_LOW);
522 field->field_val = array_pop(parser->nodes); 555 field->field.val = array_pop(parser->nodes);
523 } 556 }
524 array_push(parser->nodes, field, parser->storage); 557 array_push(parser->nodes, field, parser->storage);
525} 558}
@@ -546,10 +579,10 @@ parse_struct_lit_field(Parser *parser) {
546 Node *subfield = array_pop(parser->nodes); 579 Node *subfield = array_pop(parser->nodes);
547 array_push(type->elements, subfield, parser->storage); 580 array_push(type->elements, subfield, parser->storage);
548 } 581 }
549 field->field_val = type; 582 field->field.val = type;
550 } else { 583 } else {
551 parse_expr(parser, PREC_LOW); 584 parse_expr(parser, PREC_LOW);
552 field->field_val = array_pop(parser->nodes); 585 field->field.val = array_pop(parser->nodes);
553 } 586 }
554 array_push(parser->nodes, field, parser->storage); 587 array_push(parser->nodes, field, parser->storage);
555} 588}
@@ -570,8 +603,8 @@ parse_keyword(Parser *parser) {
570 parse_consume(parser, TOK_SYMBOL, 603 parse_consume(parser, TOK_SYMBOL,
571 cstr("expected symbol name on let expression")); 604 cstr("expected symbol name on let expression"));
572 parse_symbol(parser); 605 parse_symbol(parser);
573 node->var_name = array_pop(parser->nodes); 606 node->var.name = array_pop(parser->nodes);
574 if (node->var_name->next) { 607 if (node->var.name->sym.next) {
575 parse_emit_err(parser, prev, 608 parse_emit_err(parser, prev,
576 cstr("invalid symbol name in let expression")); 609 cstr("invalid symbol name in let expression"));
577 return; 610 return;
@@ -580,16 +613,16 @@ parse_keyword(Parser *parser) {
580 // Optional type declaration. 613 // Optional type declaration.
581 if (parse_match(parser, TOK_COLON)) { 614 if (parse_match(parser, TOK_COLON)) {
582 parse_type(parser); 615 parse_type(parser);
583 node->var_type = array_pop(parser->nodes); 616 node->var.type = array_pop(parser->nodes);
584 } 617 }
585 618
586 // Optional assignment. 619 // Optional assignment.
587 if (parse_match(parser, TOK_ASSIGN)) { 620 if (parse_match(parser, TOK_ASSIGN)) {
588 parse_expr(parser, PREC_LOW); 621 parse_expr(parser, PREC_LOW);
589 node->var_val = array_pop(parser->nodes); 622 node->var.val = array_pop(parser->nodes);
590 } 623 }
591 624
592 if (node->var_type == NULL && node->var_val == NULL) { 625 if (node->var.type == NULL && node->var.val == NULL) {
593 parse_emit_err(parser, prev, 626 parse_emit_err(parser, prev,
594 cstr("variable declaration must include type or " 627 cstr("variable declaration must include type or "
595 "value information")); 628 "value information"));
@@ -599,13 +632,50 @@ parse_keyword(Parser *parser) {
599 node = node_alloc(parser, NODE_SET, prev); 632 node = node_alloc(parser, NODE_SET, prev);
600 if (!node) return; 633 if (!node) return;
601 parse_consume(parser, TOK_SYMBOL, 634 parse_consume(parser, TOK_SYMBOL,
602 cstr("expected symbol name on let expression")); 635 cstr("expected symbol name on set expression"));
603 parse_symbol(parser); 636 parse_symbol(parser);
604 node->var_name = array_pop(parser->nodes); 637 node->var.name = array_pop(parser->nodes);
605 parse_consume(parser, TOK_ASSIGN, 638
606 cstr("expected assignment on set expression")); 639 if (parse_match(parser, TOK_ADD_ASSIGN) ||
607 parse_expr(parser, PREC_LOW); 640 parse_match(parser, TOK_ADD_ASSIGN) ||
608 node->var_val = array_pop(parser->nodes); 641 parse_match(parser, TOK_SUB_ASSIGN) ||
642 parse_match(parser, TOK_MUL_ASSIGN) ||
643 parse_match(parser, TOK_DIV_ASSIGN) ||
644 parse_match(parser, TOK_MOD_ASSIGN) ||
645 parse_match(parser, TOK_BITAND_ASSIGN) ||
646 parse_match(parser, TOK_BITOR_ASSIGN) ||
647 parse_match(parser, TOK_BITXOR_ASSIGN) ||
648 parse_match(parser, TOK_BITLSHIFT_ASSIGN) ||
649 parse_match(parser, TOK_BITRSHIFT_ASSIGN)) {
650 NodeKind kind = NODE_ERR;
651 switch (parser->previous.kind) {
652 case TOK_ADD_ASSIGN: kind = NODE_ADD; break;
653 case TOK_SUB_ASSIGN: kind = NODE_SUB; break;
654 case TOK_MUL_ASSIGN: kind = NODE_MUL; break;
655 case TOK_DIV_ASSIGN: kind = NODE_DIV; break;
656 case TOK_MOD_ASSIGN: kind = NODE_MOD; break;
657 case TOK_BITAND_ASSIGN: kind = NODE_BITAND; break;
658 case TOK_BITOR_ASSIGN: kind = NODE_BITOR; break;
659 case TOK_BITXOR_ASSIGN: kind = NODE_BITXOR; break;
660 case TOK_BITLSHIFT_ASSIGN: kind = NODE_BITLSHIFT; break;
661 case TOK_BITRSHIFT_ASSIGN: kind = NODE_BITRSHIFT; break;
662 default: break;
663 }
664 parse_expr(parser, PREC_LOW);
665 Node *value = array_pop(parser->nodes);
666 Node *sym = node_alloc(parser, NODE_SYMBOL, prev);
667 Node *op = node_alloc(parser, kind, prev);
668 op->binary.left = sym;
669 op->binary.right = value;
670 node->var.val = op;
671 sym->value = node->var.name->value;
672 sym->kind = node->var.name->kind;
673 } else {
674 parse_consume(parser, TOK_ASSIGN,
675 cstr("expected assignment on set expression"));
676 parse_expr(parser, PREC_LOW);
677 node->var.val = array_pop(parser->nodes);
678 }
609 } break; 679 } break;
610 case TOK_STRUCT: { 680 case TOK_STRUCT: {
611 node = node_alloc(parser, NODE_STRUCT, prev); 681 node = node_alloc(parser, NODE_STRUCT, prev);
@@ -629,19 +699,19 @@ parse_keyword(Parser *parser) {
629 node = node_alloc(parser, NODE_IF, prev); 699 node = node_alloc(parser, NODE_IF, prev);
630 if (!node) return; 700 if (!node) return;
631 parse_expr(parser, PREC_LOW); 701 parse_expr(parser, PREC_LOW);
632 node->cond_if = array_pop(parser->nodes); 702 node->ifelse.cond = array_pop(parser->nodes);
633 parse_expr(parser, PREC_LOW); 703 parse_expr(parser, PREC_LOW);
634 node->cond_expr = array_pop(parser->nodes); 704 node->ifelse.expr_true = array_pop(parser->nodes);
635 if (parse_match(parser, TOK_ELSE)) { 705 if (parse_match(parser, TOK_ELSE)) {
636 parse_expr(parser, PREC_LOW); 706 parse_expr(parser, PREC_LOW);
637 node->cond_else = array_pop(parser->nodes); 707 node->ifelse.expr_else = array_pop(parser->nodes);
638 } 708 }
639 } break; 709 } break;
640 case TOK_MATCH: { 710 case TOK_MATCH: {
641 node = node_alloc(parser, NODE_MATCH, prev); 711 node = node_alloc(parser, NODE_MATCH, prev);
642 if (!node) return; 712 if (!node) return;
643 parse_expr(parser, PREC_LOW); 713 parse_expr(parser, PREC_LOW);
644 node->match_expr = array_pop(parser->nodes); 714 node->match.expr = array_pop(parser->nodes);
645 parse_consume(parser, TOK_LCURLY, 715 parse_consume(parser, TOK_LCURLY,
646 cstr("expected block of match cases")); 716 cstr("expected block of match cases"));
647 while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { 717 while (!parse_match(parser, TOK_RCURLY) && !parser->panic) {
@@ -653,13 +723,13 @@ parse_keyword(Parser *parser) {
653 parse_consume(parser, TOK_CASE, 723 parse_consume(parser, TOK_CASE,
654 cstr("expected case statement")); 724 cstr("expected case statement"));
655 parse_expr(parser, PREC_LOW); 725 parse_expr(parser, PREC_LOW);
656 tmp->case_value = array_pop(parser->nodes); 726 tmp->case_entry.cond = array_pop(parser->nodes);
657 } 727 }
658 parse_consume(parser, TOK_ASSIGN, 728 parse_consume(parser, TOK_ASSIGN,
659 cstr("malformed case statement")); 729 cstr("malformed case statement"));
660 parse_expr(parser, PREC_LOW); 730 parse_expr(parser, PREC_LOW);
661 tmp->case_expr = array_pop(parser->nodes); 731 tmp->case_entry.expr = array_pop(parser->nodes);
662 array_push(node->match_cases, tmp, parser->storage); 732 array_push(node->match.cases, tmp, parser->storage);
663 } 733 }
664 // TODO: Check that we only have literals on the match case, 734 // TODO: Check that we only have literals on the match case,
665 // this could be done on the analysis step, but also here... 735 // this could be done on the analysis step, but also here...
@@ -683,7 +753,7 @@ parse_keyword(Parser *parser) {
683 field->value.sym = parser->previous.val; 753 field->value.sym = parser->previous.val;
684 if (parse_match(parser, TOK_ASSIGN)) { 754 if (parse_match(parser, TOK_ASSIGN)) {
685 parse_expr(parser, PREC_LOW); 755 parse_expr(parser, PREC_LOW);
686 field->field_val = array_pop(parser->nodes); 756 field->field.val = array_pop(parser->nodes);
687 } 757 }
688 array_push(node->struct_field, field, parser->storage); 758 array_push(node->struct_field, field, parser->storage);
689 } 759 }
@@ -703,13 +773,13 @@ parse_keyword(Parser *parser) {
703 // Are we on the default case. 773 // Are we on the default case.
704 if (!parse_match(parser, TOK_ELSE)) { 774 if (!parse_match(parser, TOK_ELSE)) {
705 parse_expr(parser, PREC_LOW); 775 parse_expr(parser, PREC_LOW);
706 tmp->case_value = array_pop(parser->nodes); 776 tmp->case_entry.cond = array_pop(parser->nodes);
707 } 777 }
708 parse_consume(parser, TOK_ASSIGN, 778 parse_consume(parser, TOK_ASSIGN,
709 cstr("malformed case statement")); 779 cstr("malformed case statement"));
710 parse_expr(parser, PREC_LOW); 780 parse_expr(parser, PREC_LOW);
711 tmp->case_expr = array_pop(parser->nodes); 781 tmp->case_entry.expr = array_pop(parser->nodes);
712 array_push(node->match_cases, tmp, parser->storage); 782 array_push(node->match.cases, tmp, parser->storage);
713 } 783 }
714 } break; 784 } break;
715 case TOK_BREAK: { 785 case TOK_BREAK: {
@@ -720,13 +790,47 @@ parse_keyword(Parser *parser) {
720 node = node_alloc(parser, NODE_CONTINUE, prev); 790 node = node_alloc(parser, NODE_CONTINUE, prev);
721 if (!node) return; 791 if (!node) return;
722 } break; 792 } break;
793 case TOK_FOR: {
794 node = node_alloc(parser, NODE_BLOCK, prev);
795 if (!node) return;
796
797 Node *node_while = node_alloc(parser, NODE_WHILE, prev);
798 if (!node_while) return;
799 Node *block = node_alloc(parser, NODE_BLOCK, prev);
800 if (!block) return;
801
802 parse_expr(parser, PREC_LOW);
803 Node *pre = array_pop(parser->nodes);
804
805 parse_expr(parser, PREC_LOW);
806 Node *cond = array_pop(parser->nodes);
807
808 parse_expr(parser, PREC_LOW);
809 Node *post = array_pop(parser->nodes);
810
811 // Body.
812 parse_consume(parser, TOK_LCURLY,
813 cstr("expected '{' on for loop statement"));
814 while (!parse_match(parser, TOK_RCURLY) && !parser->panic) {
815 parse_expr(parser, PREC_LOW);
816 Node *next = array_pop(parser->nodes);
817 array_push(block->statements, next, parser->storage);
818 }
819 array_push(block->statements, post, parser->storage);
820
821 // Put everything together
822 node_while->loop.cond = cond;
823 node_while->loop.expr = block;
824 array_push(node->statements, pre, parser->storage);
825 array_push(node->statements, node_while, parser->storage);
826 } break;
723 case TOK_WHILE: { 827 case TOK_WHILE: {
724 node = node_alloc(parser, NODE_WHILE, prev); 828 node = node_alloc(parser, NODE_WHILE, prev);
725 if (!node) return; 829 if (!node) return;
726 parse_expr(parser, PREC_LOW); 830 parse_expr(parser, PREC_LOW);
727 node->while_cond = array_pop(parser->nodes); 831 node->loop.cond = array_pop(parser->nodes);
728 parse_expr(parser, PREC_LOW); 832 parse_expr(parser, PREC_LOW);
729 node->while_expr = array_pop(parser->nodes); 833 node->loop.expr = array_pop(parser->nodes);
730 } break; 834 } break;
731 case TOK_FUN: { 835 case TOK_FUN: {
732 node = node_alloc(parser, NODE_FUN, prev); 836 node = node_alloc(parser, NODE_FUN, prev);
@@ -735,7 +839,7 @@ parse_keyword(Parser *parser) {
735 Node *name = node_alloc(parser, NODE_SYMBOL, prev); 839 Node *name = node_alloc(parser, NODE_SYMBOL, prev);
736 if (!name) return; 840 if (!name) return;
737 name->value.sym = parser->previous.val; 841 name->value.sym = parser->previous.val;
738 node->func_name = name; 842 node->func.name = name;
739 parse_consume(parser, TOK_LPAREN, 843 parse_consume(parser, TOK_LPAREN,
740 cstr("expected '(' on function definition")); 844 cstr("expected '(' on function definition"));
741 // Parameters. 845 // Parameters.
@@ -747,7 +851,7 @@ parse_keyword(Parser *parser) {
747 if (!name) return; 851 if (!name) return;
748 parse_consume(parser, TOK_SYMBOL, cstr("expected symbol name")); 852 parse_consume(parser, TOK_SYMBOL, cstr("expected symbol name"));
749 name->value.sym = parser->previous.val; 853 name->value.sym = parser->previous.val;
750 param->param_name = name; 854 param->param.name = name;
751 855
752 Node *type = node_alloc(parser, NODE_TYPE, prev); 856 Node *type = node_alloc(parser, NODE_TYPE, prev);
753 if (!type) return; 857 if (!type) return;
@@ -757,17 +861,17 @@ parse_keyword(Parser *parser) {
757 } 861 }
758 parse_consume(parser, TOK_SYMBOL, cstr("expected param type")); 862 parse_consume(parser, TOK_SYMBOL, cstr("expected param type"));
759 type->value.sym = parser->previous.val; 863 type->value.sym = parser->previous.val;
760 param->param_type = type; 864 param->param.type = type;
761 if (parse_match(parser, TOK_LSQUARE)) { 865 if (parse_match(parser, TOK_LSQUARE)) {
762 type->kind = NODE_ARR_TYPE, 866 type->kind = NODE_ARR_TYPE,
763 parse_consume(parser, TOK_NUM_INT, 867 parse_consume(parser, TOK_NUM_INT,
764 cstr("no array size given")); 868 cstr("no array size given"));
765 parse_number(parser); 869 parse_number(parser);
766 type->arr_size = array_pop(parser->nodes); 870 type->sym.arr_size = array_pop(parser->nodes);
767 parse_consume(parser, TOK_RSQUARE, 871 parse_consume(parser, TOK_RSQUARE,
768 cstr("unmatched brackets ']' in array type")); 872 cstr("unmatched brackets ']' in array type"));
769 } 873 }
770 array_push(node->func_params, param, parser->storage); 874 array_push(node->func.params, param, parser->storage);
771 } 875 }
772 parse_consume(parser, TOK_COLON, cstr("expected param type")); 876 parse_consume(parser, TOK_COLON, cstr("expected param type"));
773 877
@@ -788,12 +892,12 @@ parse_keyword(Parser *parser) {
788 parse_consume(parser, TOK_NUM_INT, 892 parse_consume(parser, TOK_NUM_INT,
789 cstr("no array size given")); 893 cstr("no array size given"));
790 parse_number(parser); 894 parse_number(parser);
791 ret->arr_size = array_pop(parser->nodes); 895 ret->sym.arr_size = array_pop(parser->nodes);
792 parse_consume(parser, TOK_RSQUARE, 896 parse_consume(parser, TOK_RSQUARE,
793 cstr("unmatched brackets ']' in " 897 cstr("unmatched brackets ']' in "
794 "array type")); 898 "array type"));
795 } 899 }
796 array_push(node->func_ret, ret, parser->storage); 900 array_push(node->func.ret, ret, parser->storage);
797 } 901 }
798 } else { 902 } else {
799 Node *ret = node_alloc(parser, NODE_TYPE, prev); 903 Node *ret = node_alloc(parser, NODE_TYPE, prev);
@@ -809,18 +913,18 @@ parse_keyword(Parser *parser) {
809 parse_consume(parser, TOK_NUM_INT, 913 parse_consume(parser, TOK_NUM_INT,
810 cstr("no array size given")); 914 cstr("no array size given"));
811 parse_number(parser); 915 parse_number(parser);
812 ret->arr_size = array_pop(parser->nodes); 916 ret->sym.arr_size = array_pop(parser->nodes);
813 parse_consume( 917 parse_consume(
814 parser, TOK_RSQUARE, 918 parser, TOK_RSQUARE,
815 cstr("unmatched brackets ']' in array type")); 919 cstr("unmatched brackets ']' in array type"));
816 } 920 }
817 array_push(node->func_ret, ret, parser->storage); 921 array_push(node->func.ret, ret, parser->storage);
818 } 922 }
819 } 923 }
820 924
821 // Body. 925 // Body.
822 parse_expr(parser, PREC_LOW); 926 parse_expr(parser, PREC_LOW);
823 node->func_body = array_pop(parser->nodes); 927 node->func.body = array_pop(parser->nodes);
824 } break; 928 } break;
825 case TOK_RETURN: { 929 case TOK_RETURN: {
826 node = node_alloc(parser, NODE_RETURN, prev); 930 node = node_alloc(parser, NODE_RETURN, prev);
@@ -870,6 +974,9 @@ parse_binary(Parser *parser) {
870 case TOK_BITOR: { 974 case TOK_BITOR: {
871 node = node_alloc(parser, NODE_BITOR, prev); 975 node = node_alloc(parser, NODE_BITOR, prev);
872 } break; 976 } break;
977 case TOK_BITXOR: {
978 node = node_alloc(parser, NODE_BITXOR, prev);
979 } break;
873 case TOK_BITLSHIFT: { 980 case TOK_BITLSHIFT: {
874 node = node_alloc(parser, NODE_BITLSHIFT, prev); 981 node = node_alloc(parser, NODE_BITLSHIFT, prev);
875 } break; 982 } break;
@@ -882,8 +989,8 @@ parse_binary(Parser *parser) {
882 } 989 }
883 } 990 }
884 if (!node) return; 991 if (!node) return;
885 node->right = array_pop(parser->nodes); 992 node->binary.right = array_pop(parser->nodes);
886 node->left = array_pop(parser->nodes); 993 node->binary.left = array_pop(parser->nodes);
887 array_push(parser->nodes, node, parser->storage); 994 array_push(parser->nodes, node, parser->storage);
888} 995}
889 996
@@ -965,7 +1072,7 @@ parse_symbol(Parser *parser) {
965 parse_consume(parser, TOK_SYMBOL, 1072 parse_consume(parser, TOK_SYMBOL,
966 cstr("expected symbol after '.' operator")); 1073 cstr("expected symbol after '.' operator"));
967 parse_symbol(parser); 1074 parse_symbol(parser);
968 node->next = array_pop(parser->nodes); 1075 node->sym.next = array_pop(parser->nodes);
969 } else if (parser->current.kind == TOK_COLON && 1076 } else if (parser->current.kind == TOK_COLON &&
970 parse_peek(parser) == TOK_LCURLY) { 1077 parse_peek(parser) == TOK_LCURLY) {
971 parse_advance(parser); 1078 parse_advance(parser);
@@ -981,7 +1088,7 @@ parse_symbol(Parser *parser) {
981 } else if (parse_match(parser, TOK_LSQUARE)) { 1088 } else if (parse_match(parser, TOK_LSQUARE)) {
982 node->kind = NODE_SYMBOL_IDX; 1089 node->kind = NODE_SYMBOL_IDX;
983 parse_expr(parser, PREC_LOW); 1090 parse_expr(parser, PREC_LOW);
984 node->arr_size = array_pop(parser->nodes); 1091 node->sym.arr_size = array_pop(parser->nodes);
985 parse_consume(parser, TOK_RSQUARE, 1092 parse_consume(parser, TOK_RSQUARE,
986 cstr("unmatched brackets ']' in array type")); 1093 cstr("unmatched brackets ']' in array type"));
987 if (parse_match(parser, TOK_DOT)) { 1094 if (parse_match(parser, TOK_DOT)) {
@@ -989,7 +1096,7 @@ parse_symbol(Parser *parser) {
989 parse_consume(parser, TOK_SYMBOL, 1096 parse_consume(parser, TOK_SYMBOL,
990 cstr("expected symbol after '.' operator")); 1097 cstr("expected symbol after '.' operator"));
991 parse_symbol(parser); 1098 parse_symbol(parser);
992 node->next = array_pop(parser->nodes); 1099 node->sym.next = array_pop(parser->nodes);
993 } 1100 }
994 } else if (parse_match(parser, TOK_LPAREN)) { 1101 } else if (parse_match(parser, TOK_LPAREN)) {
995 node->kind = NODE_FUNCALL; 1102 node->kind = NODE_FUNCALL;
@@ -1003,7 +1110,7 @@ parse_symbol(Parser *parser) {
1003 parse_consume(parser, TOK_SYMBOL, 1110 parse_consume(parser, TOK_SYMBOL,
1004 cstr("expected symbol after '.' operator")); 1111 cstr("expected symbol after '.' operator"));
1005 parse_symbol(parser); 1112 parse_symbol(parser);
1006 node->next = array_pop(parser->nodes); 1113 node->sym.next = array_pop(parser->nodes);
1007 } 1114 }
1008 } 1115 }
1009 node->value.sym = prev.val; 1116 node->value.sym = prev.val;
@@ -1051,43 +1158,43 @@ graph_node(Node *node) {
1051 if (node->type.size > 0) { 1158 if (node->type.size > 0) {
1052 print("| Type: %s", node->type); 1159 print("| Type: %s", node->type);
1053 } 1160 }
1054 if (node->fun_params.size > 0) { 1161 if (node->type_params.size > 0) {
1055 print("| Params: %s", node->fun_params); 1162 print("| Params: %s", node->type_params);
1056 } 1163 }
1057 if (node->fun_return.size > 0) { 1164 if (node->type_returns.size > 0) {
1058 print("| Return: %s", node->fun_return); 1165 print("| Return: %s", node->type_returns);
1059 } 1166 }
1060 println("\"];"); 1167 println("\"];");
1061 1168
1062 switch (node->kind) { 1169 switch (node->kind) {
1063 case NODE_FUN: { 1170 case NODE_FUN: {
1064 for (sz i = 0; i < array_size(node->func_params); i++) { 1171 for (sz i = 0; i < array_size(node->func.params); i++) {
1065 Node *next = node->func_params[i]; 1172 Node *next = node->func.params[i];
1066 println("%d:e->%d:w;", node->id, next->id); 1173 println("%d:e->%d:w;", node->id, next->id);
1067 graph_node(next); 1174 graph_node(next);
1068 } 1175 }
1069 for (sz i = 0; i < array_size(node->func_ret); i++) { 1176 for (sz i = 0; i < array_size(node->func.ret); i++) {
1070 Node *next = node->func_ret[i]; 1177 Node *next = node->func.ret[i];
1071 println("%d:e->%d:w;", node->id, next->id); 1178 println("%d:e->%d:w;", node->id, next->id);
1072 graph_node(next); 1179 graph_node(next);
1073 } 1180 }
1074 if (node->func_name) { 1181 if (node->func.name) {
1075 println("%d:e->%d:w;", node->id, node->func_name->id); 1182 println("%d:e->%d:w;", node->id, node->func.name->id);
1076 graph_node(node->func_name); 1183 graph_node(node->func.name);
1077 } 1184 }
1078 if (node->func_body) { 1185 if (node->func.body) {
1079 println("%d:e->%d:w;", node->id, node->func_body->id); 1186 println("%d:e->%d:w;", node->id, node->func.body->id);
1080 graph_node(node->func_body); 1187 graph_node(node->func.body);
1081 } 1188 }
1082 } break; 1189 } break;
1083 case NODE_COND: 1190 case NODE_COND:
1084 case NODE_MATCH: { 1191 case NODE_MATCH: {
1085 if (node->match_expr) { 1192 if (node->match.expr) {
1086 println("%d:e->%d:w;", node->id, node->match_expr->id); 1193 println("%d:e->%d:w;", node->id, node->match.expr->id);
1087 graph_node(node->match_expr); 1194 graph_node(node->match.expr);
1088 } 1195 }
1089 for (sz i = 0; i < array_size(node->match_cases); i++) { 1196 for (sz i = 0; i < array_size(node->match.cases); i++) {
1090 Node *next = node->match_cases[i]; 1197 Node *next = node->match.cases[i];
1091 println("%d:e->%d:w;", node->id, next->id); 1198 println("%d:e->%d:w;", node->id, next->id);
1092 graph_node(next); 1199 graph_node(next);
1093 } 1200 }
@@ -1112,43 +1219,43 @@ graph_node(Node *node) {
1112 } 1219 }
1113 } break; 1220 } break;
1114 case NODE_IF: { 1221 case NODE_IF: {
1115 if (node->cond_if) { 1222 if (node->ifelse.cond) {
1116 println("%d:e->%d:w;", node->id, node->cond_if->id); 1223 println("%d:e->%d:w;", node->id, node->ifelse.cond->id);
1117 graph_node(node->cond_if); 1224 graph_node(node->ifelse.cond);
1118 } 1225 }
1119 if (node->cond_expr) { 1226 if (node->ifelse.expr_true) {
1120 println("%d:e->%d:w;", node->id, node->cond_expr->id); 1227 println("%d:e->%d:w;", node->id, node->ifelse.expr_true->id);
1121 graph_node(node->cond_expr); 1228 graph_node(node->ifelse.expr_true);
1122 } 1229 }
1123 if (node->cond_else) { 1230 if (node->ifelse.expr_else) {
1124 println("%d:e->%d:w;", node->id, node->cond_else->id); 1231 println("%d:e->%d:w;", node->id, node->ifelse.expr_else->id);
1125 graph_node(node->cond_else); 1232 graph_node(node->ifelse.expr_else);
1126 } 1233 }
1127 } break; 1234 } break;
1128 case NODE_FIELD: 1235 case NODE_FIELD:
1129 case NODE_SET: 1236 case NODE_SET:
1130 case NODE_LET: { 1237 case NODE_LET: {
1131 if (node->var_name) { 1238 if (node->var.name) {
1132 println("%d:e->%d:w;", node->id, node->var_name->id); 1239 println("%d:e->%d:w;", node->id, node->var.name->id);
1133 graph_node(node->var_name); 1240 graph_node(node->var.name);
1134 } 1241 }
1135 if (node->var_type) { 1242 if (node->var.type) {
1136 println("%d:e->%d:w;", node->id, node->var_type->id); 1243 println("%d:e->%d:w;", node->id, node->var.type->id);
1137 graph_node(node->var_type); 1244 graph_node(node->var.type);
1138 } 1245 }
1139 if (node->var_val) { 1246 if (node->var.val) {
1140 println("%d:e->%d:w;", node->id, node->var_val->id); 1247 println("%d:e->%d:w;", node->id, node->var.val->id);
1141 graph_node(node->var_val); 1248 graph_node(node->var.val);
1142 } 1249 }
1143 } break; 1250 } break;
1144 default: { 1251 default: {
1145 if (node->left) { 1252 if (node->binary.left) {
1146 println("%d:e->%d:w;", node->id, node->left->id); 1253 println("%d:e->%d:w;", node->id, node->binary.left->id);
1147 graph_node(node->left); 1254 graph_node(node->binary.left);
1148 } 1255 }
1149 if (node->right) { 1256 if (node->binary.right) {
1150 println("%d:e->%d:w;", node->id, node->right->id); 1257 println("%d:e->%d:w;", node->id, node->binary.right->id);
1151 graph_node(node->right); 1258 graph_node(node->binary.right);
1152 } 1259 }
1153 } break; 1260 } break;
1154 } 1261 }
diff --git a/src/semantic.c b/src/semantic.c
index 9b119df..7c44671 100644
--- a/src/semantic.c
+++ b/src/semantic.c
@@ -82,6 +82,9 @@ Scope *
82typescope_alloc(Analyzer *a, Scope *parent) { 82typescope_alloc(Analyzer *a, Scope *parent) {
83 Scope *scope = arena_calloc(sizeof(Scope), a->storage); 83 Scope *scope = arena_calloc(sizeof(Scope), a->storage);
84 scope->parent = parent; 84 scope->parent = parent;
85 if (parent != NULL) {
86 scope->name = parent->name;
87 }
85 scope->id = a->typescope_gen++; 88 scope->id = a->typescope_gen++;
86 scope->depth = parent == NULL ? 0 : parent->depth + 1; 89 scope->depth = parent == NULL ? 0 : parent->depth + 1;
87 array_push(a->scopes, scope, a->storage); 90 array_push(a->scopes, scope, a->storage);
@@ -276,7 +279,7 @@ Str type_inference(Analyzer *a, Node *node, Scope *scope);
276 279
277void 280void
278typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { 281typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) {
279 if (node->field_type->kind == NODE_COMPOUND_TYPE) { 282 if (node->field.type->kind == NODE_COMPOUND_TYPE) {
280 Str field_name = str_concat(symbol, cstr("."), a->storage); 283 Str field_name = str_concat(symbol, cstr("."), a->storage);
281 field_name = str_concat(field_name, node->value.str, a->storage); 284 field_name = str_concat(field_name, node->value.str, a->storage);
282 if (structmap_lookup(&scope->structs, field_name)) { 285 if (structmap_lookup(&scope->structs, field_name)) {
@@ -285,8 +288,8 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) {
285 a->err = true; 288 a->err = true;
286 } 289 }
287 Str type = cstr("\\{ "); 290 Str type = cstr("\\{ ");
288 for (sz i = 0; i < array_size(node->field_type->elements); i++) { 291 for (sz i = 0; i < array_size(node->field.type->elements); i++) {
289 Node *field = node->field_type->elements[i]; 292 Node *field = node->field.type->elements[i];
290 typecheck_field(a, field, scope, field_name); 293 typecheck_field(a, field, scope, field_name);
291 type = str_concat(type, field->type, a->storage); 294 type = str_concat(type, field->type, a->storage);
292 type = str_concat(type, cstr(" "), a->storage); 295 type = str_concat(type, cstr(" "), a->storage);
@@ -296,16 +299,16 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) {
296 } else { 299 } else {
297 Str field_name = str_concat(symbol, cstr("."), a->storage); 300 Str field_name = str_concat(symbol, cstr("."), a->storage);
298 field_name = str_concat(field_name, node->value.str, a->storage); 301 field_name = str_concat(field_name, node->value.str, a->storage);
299 Str field_type = node->field_type->value.str; 302 Str field_type = node->field.type->value.str;
300 if (!find_type(scope, field_type)) { 303 if (!find_type(scope, field_type)) {
301 eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, 304 eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name,
302 node->field_type->line, node->field_type->col, field_type); 305 node->field.type->line, node->field.type->col, field_type);
303 a->err = true; 306 a->err = true;
304 } 307 }
305 if (node->field_type->is_ptr) { 308 if (node->field.type->is_ptr) {
306 field_type = str_concat(cstr("@"), field_type, a->storage); 309 field_type = str_concat(cstr("@"), field_type, a->storage);
307 } 310 }
308 if (node->field_type->kind == NODE_ARR_TYPE) { 311 if (node->field.type->kind == NODE_ARR_TYPE) {
309 field_type = str_concat(cstr("@"), field_type, a->storage); 312 field_type = str_concat(cstr("@"), field_type, a->storage);
310 } 313 }
311 if (structmap_lookup(&scope->structs, field_name)) { 314 if (structmap_lookup(&scope->structs, field_name)) {
@@ -313,8 +316,8 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) {
313 a->file_name, node->line, node->col, field_name); 316 a->file_name, node->line, node->col, field_name);
314 a->err = true; 317 a->err = true;
315 } 318 }
316 if (node->field_val) { 319 if (node->field.val) {
317 Str type = type_inference(a, node->field_val, scope); 320 Str type = type_inference(a, node->field.val, scope);
318 if (!str_eq(type, field_type)) { 321 if (!str_eq(type, field_type)) {
319 eprintln( 322 eprintln(
320 "%s:%d:%d: error: mismatched types in struct " 323 "%s:%d:%d: error: mismatched types in struct "
@@ -329,7 +332,7 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) {
329 (Struct){ 332 (Struct){
330 .name = field_name, 333 .name = field_name,
331 .type = field_type, 334 .type = field_type,
332 .val = node->field_val, 335 .val = node->field.val,
333 }, 336 },
334 a->storage); 337 a->storage);
335 symmap_insert(&scope->symbols, field_name, 338 symmap_insert(&scope->symbols, field_name,
@@ -341,10 +344,10 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) {
341 344
342void 345void
343typecheck_lit_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { 346typecheck_lit_field(Analyzer *a, Node *node, Scope *scope, Str symbol) {
344 if (node->field_val->kind == NODE_COMPOUND_TYPE) { 347 if (node->field.val->kind == NODE_COMPOUND_TYPE) {
345 Str type = cstr("\\{ "); 348 Str type = cstr("\\{ ");
346 for (sz i = 0; i < array_size(node->field_val->elements); i++) { 349 for (sz i = 0; i < array_size(node->field.val->elements); i++) {
347 Node *field = node->field_val->elements[i]; 350 Node *field = node->field.val->elements[i];
348 Str field_name = str_concat(symbol, cstr("."), a->storage); 351 Str field_name = str_concat(symbol, cstr("."), a->storage);
349 field_name = str_concat(field_name, field->value.str, a->storage); 352 field_name = str_concat(field_name, field->value.str, a->storage);
350 typecheck_lit_field(a, field, scope, field_name); 353 typecheck_lit_field(a, field, scope, field_name);
@@ -362,7 +365,7 @@ typecheck_lit_field(Analyzer *a, Node *node, Scope *scope, Str symbol) {
362 return; 365 return;
363 } 366 }
364 Str field_type = s->val.type; 367 Str field_type = s->val.type;
365 Str type = type_inference(a, node->field_val, scope); 368 Str type = type_inference(a, node->field.val, scope);
366 if (!str_eq(type, field_type)) { 369 if (!str_eq(type, field_type)) {
367 eprintln( 370 eprintln(
368 "%s:%d:%d: error: mismatched types in struct " 371 "%s:%d:%d: error: mismatched types in struct "
@@ -384,17 +387,18 @@ typecheck_returns(Analyzer *a, Node *node, Str expected) {
384 switch (node->kind) { 387 switch (node->kind) {
385 case NODE_COND: 388 case NODE_COND:
386 case NODE_MATCH: { 389 case NODE_MATCH: {
387 for (sz i = 0; i < array_size(node->match_cases); i++) { 390 for (sz i = 0; i < array_size(node->match.cases); i++) {
388 Node *next = node->match_cases[i]; 391 Node *next = node->match.cases[i];
389 typecheck_returns(a, next, expected); 392 typecheck_returns(a, next, expected);
390 } 393 }
391 } break; 394 } break;
392 case NODE_RETURN: { 395 case NODE_RETURN: {
393 bool err = !str_eq(node->type, expected); 396 Str type = str_remove_prefix(node->type, cstr("ret:"));
397 bool err = !str_eq(type, expected);
394 if (err) { 398 if (err) {
395 eprintln( 399 eprintln(
396 "%s:%d:%d: error: mismatched return type %s, expected %s", 400 "%s:%d:%d: error: mismatched return type %s, expected %s",
397 a->file_name, node->line, node->col, node->type, expected); 401 a->file_name, node->line, node->col, type, expected);
398 a->err = true; 402 a->err = true;
399 } 403 }
400 } break; 404 } break;
@@ -405,17 +409,17 @@ typecheck_returns(Analyzer *a, Node *node, Str expected) {
405 } 409 }
406 } break; 410 } break;
407 case NODE_IF: { 411 case NODE_IF: {
408 if (node->cond_expr) { 412 if (node->ifelse.expr_true) {
409 typecheck_returns(a, node->cond_expr, expected); 413 typecheck_returns(a, node->ifelse.expr_true, expected);
410 } 414 }
411 if (node->cond_else) { 415 if (node->ifelse.expr_else) {
412 typecheck_returns(a, node->cond_else, expected); 416 typecheck_returns(a, node->ifelse.expr_else, expected);
413 } 417 }
414 } break; 418 } break;
415 case NODE_SET: 419 case NODE_SET:
416 case NODE_LET: { 420 case NODE_LET: {
417 if (node->var_val) { 421 if (node->var.val) {
418 typecheck_returns(a, node->var_val, expected); 422 typecheck_returns(a, node->var.val, expected);
419 } 423 }
420 } break; 424 } break;
421 case NODE_ADD: 425 case NODE_ADD:
@@ -435,13 +439,14 @@ typecheck_returns(Analyzer *a, Node *node, Str expected) {
435 case NODE_BITNOT: 439 case NODE_BITNOT:
436 case NODE_BITAND: 440 case NODE_BITAND:
437 case NODE_BITOR: 441 case NODE_BITOR:
442 case NODE_BITXOR:
438 case NODE_BITLSHIFT: 443 case NODE_BITLSHIFT:
439 case NODE_BITRSHIFT: { 444 case NODE_BITRSHIFT: {
440 if (node->left) { 445 if (node->binary.left) {
441 typecheck_returns(a, node->left, expected); 446 typecheck_returns(a, node->binary.left, expected);
442 } 447 }
443 if (node->right) { 448 if (node->binary.right) {
444 typecheck_returns(a, node->right, expected); 449 typecheck_returns(a, node->binary.right, expected);
445 } 450 }
446 } break; 451 } break;
447 default: break; 452 default: break;
@@ -452,66 +457,79 @@ Str
452type_inference(Analyzer *a, Node *node, Scope *scope) { 457type_inference(Analyzer *a, Node *node, Scope *scope) {
453 assert(a); 458 assert(a);
454 assert(scope); 459 assert(scope);
455 if (!node) { 460 if (!node || a->err) {
456 return cstr(""); 461 return cstr("");
457 } 462 }
458 // NOTE: For now we are not going to do implicit numeric conversions. 463 // NOTE: For now we are not going to do implicit numeric conversions.
459 switch (node->kind) { 464 switch (node->kind) {
460 case NODE_LET: { 465 case NODE_LET: {
461 node->type = cstr("nil"); 466 node->type = cstr("nil");
462 Str symbol = node->var_name->value.str; 467 node->var.name->parent = node;
468 Str symbol = node->var.name->value.str;
463 if (symmap_lookup(&scope->symbols, symbol)) { 469 if (symmap_lookup(&scope->symbols, symbol)) {
464 eprintln( 470 eprintln(
465 "%s:%d:%d: error: symbol '%s' already exists in current " 471 "%s:%d:%d: error: symbol '%s' already exists in current "
466 "scope ", 472 "scope ",
467 a->file_name, node->var_name->line, node->var_name->col, 473 a->file_name, node->var.name->line, node->var.name->col,
468 symbol); 474 symbol);
469 a->err = true; 475 a->err = true;
470 return cstr(""); 476 return cstr("");
471 } 477 }
472 if (node->var_type) { 478 if (node->var.type) {
473 Str type_name = node->var_type->value.str; 479 node->var.type->parent = node;
480 Str type_name = node->var.type->value.str;
474 SymbolMap *type = find_type(scope, type_name); 481 SymbolMap *type = find_type(scope, type_name);
475 if (type == NULL) { 482 if (type == NULL) {
476 eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, 483 eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name,
477 node->var_type->line, node->var_type->col, 484 node->var.type->line, node->var.type->col,
478 type_name); 485 type_name);
479 a->err = true; 486 a->err = true;
480 return cstr(""); 487 return cstr("");
481 } 488 }
482 if (node->var_type->is_ptr) { 489 if (node->var.type->is_ptr) {
483 type_name = str_concat(cstr("@"), type_name, a->storage); 490 type_name = str_concat(cstr("@"), type_name, a->storage);
484 } 491 }
485 if (node->var_type->kind == NODE_ARR_TYPE) { 492 if (node->var.type->kind == NODE_ARR_TYPE) {
486 type_name = str_concat(cstr("@"), type_name, a->storage); 493 type_name = str_concat(cstr("@"), type_name, a->storage);
487 // TODO: typecheck size 494 if (node->var.type->sym.arr_size->value.i == 0) {
495 eprintln("%s:%d:%d: error: zero sized array '%s'",
496 a->file_name, node->var.type->line,
497 node->var.type->col, symbol);
498 a->err = true;
499 return cstr("");
500 }
488 // TODO: register array in scope 501 // TODO: register array in scope
489 } 502 }
490 if (node->var_val) { 503 if (node->var.val) {
491 Str type = type_inference(a, node->var_val, scope); 504 node->var.val->parent = node;
505 Str type = type_inference(a, node->var.val, scope);
492 if (!type.size) { 506 if (!type.size) {
493 eprintln( 507 eprintln(
494 "%s:%d:%d: error: can't bind `nil` to variable " 508 "%s:%d:%d: error: can't bind `nil` to variable "
495 "'%s'", 509 "'%s'",
496 a->file_name, node->var_type->line, 510 a->file_name, node->var.type->line,
497 node->var_type->col, symbol); 511 node->var.type->col, symbol);
498 a->err = true; 512 a->err = true;
499 return cstr(""); 513 return cstr("");
500 } 514 }
501 // TODO: Consider compatible types.
502 if (!str_eq(type, type_name)) { 515 if (!str_eq(type, type_name)) {
503 // Special case, enums can be treated as ints. 516 if (!(strset_lookup(&a->integer_types, type) &&
504 FindEnumResult res = find_enum(scope, type_name); 517 strset_lookup(&a->integer_types, type_name)) &&
505 if (!(res.map && str_eq(type, cstr("int")))) { 518 !(strset_lookup(&a->numeric_types, type) &&
506 eprintln( 519 strset_lookup(&a->numeric_types, type_name))) {
507 "%s:%d:%d: error: type mismatch, trying to " 520 // Special case, enums can be treated as ints.
508 "assing " 521 FindEnumResult res = find_enum(scope, type_name);
509 "%s" 522 if (!(res.map && str_eq(type, cstr("int")))) {
510 " to a variable of type %s", 523 eprintln(
511 a->file_name, node->var_type->line, 524 "%s:%d:%d: error: type mismatch, trying to "
512 node->var_type->col, type, type_name); 525 "assing "
513 a->err = true; 526 "%s"
514 return cstr(""); 527 " to a variable of type %s",
528 a->file_name, node->var.type->line,
529 node->var.type->col, type, type_name);
530 a->err = true;
531 return cstr("");
532 }
515 } 533 }
516 } 534 }
517 } 535 }
@@ -521,17 +539,29 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
521 .kind = SYM_VAR, 539 .kind = SYM_VAR,
522 }, 540 },
523 a->storage); 541 a->storage);
542 node->var.name->type = type_name;
543 symbol = str_concat(cstr("."), symbol, a->storage);
544 symbol = str_concat(symbol, str_from_int(scope->id, a->storage),
545 a->storage);
546 node->unique_name = symbol;
524 return node->type; 547 return node->type;
525 } 548 }
526 549
527 // We don't know the type for this symbol, perform inference. 550 // We don't know the type for this symbol, perform inference.
528 Str type = type_inference(a, node->var_val, scope); 551 node->var.val->parent = node;
529 if (type.size) { 552 Str type = type_inference(a, node->var.val, scope);
530 symmap_insert(&scope->symbols, symbol, 553 if (!type.size || str_eq(type, cstr("nil")) ||
531 (Symbol){.name = type, .kind = SYM_VAR}, 554 str_has_prefix(type, cstr("ret:"))) {
532 a->storage); 555 eprintln(
533 node->var_name->type = type; 556 "%s:%d:%d: error: can't bind `nil` to variable "
557 "'%s'",
558 a->file_name, node->line, node->col, symbol);
559 a->err = true;
560 return cstr("");
534 } 561 }
562 symmap_insert(&scope->symbols, symbol,
563 (Symbol){.name = type, .kind = SYM_VAR}, a->storage);
564 node->var.name->type = type;
535 symbol = str_concat(cstr("."), symbol, a->storage); 565 symbol = str_concat(cstr("."), symbol, a->storage);
536 symbol = str_concat(symbol, str_from_int(scope->id, a->storage), 566 symbol = str_concat(symbol, str_from_int(scope->id, a->storage),
537 a->storage); 567 a->storage);
@@ -539,8 +569,10 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
539 return node->type; 569 return node->type;
540 } break; 570 } break;
541 case NODE_SET: { 571 case NODE_SET: {
542 Str name = type_inference(a, node->var_name, scope); 572 node->var.name->parent = node;
543 Str val = type_inference(a, node->var_val, scope); 573 node->var.val->parent = node;
574 Str name = type_inference(a, node->var.name, scope);
575 Str val = type_inference(a, node->var.val, scope);
544 if (!str_eq(name, val)) { 576 if (!str_eq(name, val)) {
545 eprintln( 577 eprintln(
546 "%s:%d:%d: error: type mismatch, trying to assing " 578 "%s:%d:%d: error: type mismatch, trying to assing "
@@ -550,7 +582,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
550 a->err = true; 582 a->err = true;
551 return cstr(""); 583 return cstr("");
552 } 584 }
553 Str symbol = node->var_name->value.str; 585 Str symbol = node->var.name->value.str;
554 FindSymbolResult sym = find_symbol(scope, symbol); 586 FindSymbolResult sym = find_symbol(scope, symbol);
555 node->unique_name = str_concat(cstr("."), symbol, a->storage); 587 node->unique_name = str_concat(cstr("."), symbol, a->storage);
556 node->unique_name = 588 node->unique_name =
@@ -574,6 +606,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
574 a->storage); 606 a->storage);
575 for (sz i = 0; i < array_size(node->struct_field); i++) { 607 for (sz i = 0; i < array_size(node->struct_field); i++) {
576 Node *field = node->struct_field[i]; 608 Node *field = node->struct_field[i];
609 field->parent = node;
577 typecheck_field(a, field, scope, symbol); 610 typecheck_field(a, field, scope, symbol);
578 } 611 }
579 symmap_insert(&scope->symbols, symbol, 612 symmap_insert(&scope->symbols, symbol,
@@ -595,11 +628,12 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
595 enummap_insert(&scope->enums, symbol, 628 enummap_insert(&scope->enums, symbol,
596 (Enum){ 629 (Enum){
597 .name = symbol, 630 .name = symbol,
598 .val = node->field_val, 631 .val = node->field.val,
599 }, 632 },
600 a->storage); 633 a->storage);
601 for (sz i = 0; i < array_size(node->struct_field); i++) { 634 for (sz i = 0; i < array_size(node->struct_field); i++) {
602 Node *field = node->struct_field[i]; 635 Node *field = node->struct_field[i];
636 field->parent = node;
603 Str field_name = str_concat(symbol, cstr("."), a->storage); 637 Str field_name = str_concat(symbol, cstr("."), a->storage);
604 field_name = 638 field_name =
605 str_concat(field_name, field->value.str, a->storage); 639 str_concat(field_name, field->value.str, a->storage);
@@ -608,8 +642,8 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
608 a->file_name, field->line, field->col, field_name); 642 a->file_name, field->line, field->col, field_name);
609 a->err = true; 643 a->err = true;
610 } 644 }
611 if (field->field_val) { 645 if (field->field.val) {
612 Str type = type_inference(a, field->field_val, scope); 646 Str type = type_inference(a, field->field.val, scope);
613 if (!str_eq(type, cstr("int"))) { 647 if (!str_eq(type, cstr("int"))) {
614 eprintln( 648 eprintln(
615 "%s:%d:%d: error: non int enum value for '%s.%s'", 649 "%s:%d:%d: error: non int enum value for '%s.%s'",
@@ -632,26 +666,34 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
632 return node->type; 666 return node->type;
633 } break; 667 } break;
634 case NODE_IF: { 668 case NODE_IF: {
635 Str cond_type = type_inference(a, node->cond_if, scope); 669 node->ifelse.cond->parent = node;
670 node->ifelse.expr_true->parent = node;
671 Str cond_type = type_inference(a, node->ifelse.cond, scope);
636 if (!str_eq(cond_type, cstr("bool"))) { 672 if (!str_eq(cond_type, cstr("bool"))) {
637 emit_semantic_error( 673 emit_semantic_error(
638 a, node->cond_if, 674 a, node->ifelse.cond,
639 cstr("non boolean expression on if condition")); 675 cstr("non boolean expression on if condition"));
640 return cstr(""); 676 return cstr("");
641 } 677 }
642 if (node->cond_expr->kind == NODE_BLOCK) { 678 if (node->ifelse.expr_true->kind == NODE_BLOCK) {
643 node->type = type_inference(a, node->cond_expr, scope); 679 node->type = type_inference(a, node->ifelse.expr_true, scope);
644 } else { 680 } else {
645 Scope *next = typescope_alloc(a, scope); 681 Scope *next = typescope_alloc(a, scope);
646 node->type = type_inference(a, node->cond_expr, next); 682 node->type = type_inference(a, node->ifelse.expr_true, next);
683 }
684 if (str_has_prefix(node->type, cstr("ret:")) ||
685 str_has_prefix(node->type, cstr("flow:"))) {
686 node->type = cstr("nil");
647 } 687 }
648 if (node->cond_else) { 688 if (node->ifelse.expr_else) {
689 node->ifelse.expr_else->parent = node;
649 Str else_type; 690 Str else_type;
650 if (node->cond_else->kind == NODE_BLOCK) { 691 if (node->ifelse.expr_else->kind == NODE_BLOCK) {
651 else_type = type_inference(a, node->cond_else, scope); 692 else_type =
693 type_inference(a, node->ifelse.expr_else, scope);
652 } else { 694 } else {
653 Scope *next = typescope_alloc(a, scope); 695 Scope *next = typescope_alloc(a, scope);
654 else_type = type_inference(a, node->cond_else, next); 696 else_type = type_inference(a, node->ifelse.expr_else, next);
655 } 697 }
656 if (!str_eq(node->type, else_type)) { 698 if (!str_eq(node->type, else_type)) {
657 emit_semantic_error( 699 emit_semantic_error(
@@ -659,27 +701,41 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
659 return cstr(""); 701 return cstr("");
660 } 702 }
661 } 703 }
704
705 // If it returns a value, verify it contains an `else` statement.
706 if (!str_eq(node->type, cstr("nil"))) {
707 if (!node->ifelse.expr_else) {
708 emit_semantic_error(
709 a, node,
710 cstr("missing else statement in if expression"));
711 return cstr("");
712 }
713 }
662 return node->type; 714 return node->type;
663 } break; 715 } break;
664 case NODE_WHILE: { 716 case NODE_WHILE: {
665 Str cond_type = type_inference(a, node->while_cond, scope); 717 node->loop.cond->parent = node;
718 node->loop.expr->parent = node;
719 Str cond_type = type_inference(a, node->loop.cond, scope);
666 if (!str_eq(cond_type, cstr("bool"))) { 720 if (!str_eq(cond_type, cstr("bool"))) {
667 emit_semantic_error( 721 emit_semantic_error(
668 a, node->cond_if, 722 a, node->loop.cond,
669 cstr("non boolean expression on while condition")); 723 cstr("non boolean expression on while condition"));
670 return cstr(""); 724 return cstr("");
671 } 725 }
672 if (node->while_expr->kind != NODE_BLOCK) { 726 if (node->loop.expr->kind != NODE_BLOCK) {
673 scope = typescope_alloc(a, scope); 727 scope = typescope_alloc(a, scope);
674 } 728 }
675 type_inference(a, node->while_expr, scope); 729 type_inference(a, node->loop.expr, scope);
676 node->type = cstr("nil"); 730 node->type = cstr("nil");
677 return node->type; 731 return node->type;
678 } break; 732 } break;
679 case NODE_COND: { 733 case NODE_COND: {
680 Str previous = cstr(""); 734 Str previous = cstr("");
681 for (sz i = 0; i < array_size(node->match_cases); i++) { 735 bool has_else = false;
682 Node *expr = node->match_cases[i]; 736 for (sz i = 0; i < array_size(node->match.cases); i++) {
737 Node *expr = node->match.cases[i];
738 expr->parent = node;
683 Str next = type_inference(a, expr, scope); 739 Str next = type_inference(a, expr, scope);
684 if (i != 0 && !str_eq(next, previous)) { 740 if (i != 0 && !str_eq(next, previous)) {
685 emit_semantic_error( 741 emit_semantic_error(
@@ -687,22 +743,38 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
687 cstr("non-matching types for cond expressions")); 743 cstr("non-matching types for cond expressions"));
688 return cstr(""); 744 return cstr("");
689 } 745 }
746 if (!expr->case_entry.cond) {
747 has_else = true;
748 }
690 previous = next; 749 previous = next;
691 } 750 }
751 // If it returns a value, verify it contains an `else` statement.
752 if (!str_eq(node->type, cstr("nil")) &&
753 !str_has_prefix(node->type, cstr("ret:")) &&
754 !str_has_prefix(node->type, cstr("flow:"))) {
755 if (!has_else) {
756 emit_semantic_error(
757 a, node,
758 cstr("missing else statement in cond expression"));
759 return cstr("");
760 }
761 }
692 node->type = previous; 762 node->type = previous;
693 return node->type; 763 return node->type;
694 } break; 764 } break;
695 case NODE_MATCH: { 765 case NODE_MATCH: {
696 Str e = type_inference(a, node->match_expr, scope); 766 node->match.expr->parent = node;
767 Str e = type_inference(a, node->match.expr, scope);
697 if (str_eq(e, cstr("int"))) { 768 if (str_eq(e, cstr("int"))) {
698 // Integer matching. 769 // Integer matching.
699 for (sz i = 0; i < array_size(node->match_cases); i++) { 770 for (sz i = 0; i < array_size(node->match.cases); i++) {
700 Node *field = node->match_cases[i]; 771 Node *field = node->match.cases[i];
701 if (field->case_value) { 772 field->parent = node;
702 if (field->case_value->kind != NODE_NUM_INT && 773 if (field->case_entry.cond) {
703 field->case_value->kind != NODE_NUM_UINT) { 774 if (field->case_entry.cond->kind != NODE_NUM_INT &&
775 field->case_entry.cond->kind != NODE_NUM_UINT) {
704 emit_semantic_error( 776 emit_semantic_error(
705 a, field->case_value, 777 a, field->case_entry.cond,
706 cstr( 778 cstr(
707 "non-integer or enum types on match case")); 779 "non-integer or enum types on match case"));
708 } 780 }
@@ -713,24 +785,26 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
713 FindEnumResult res = find_enum(scope, e); 785 FindEnumResult res = find_enum(scope, e);
714 Str enum_prefix = 786 Str enum_prefix =
715 str_concat(res.map->val.name, cstr("."), a->storage); 787 str_concat(res.map->val.name, cstr("."), a->storage);
716 for (sz i = 0; i < array_size(node->match_cases); i++) { 788 for (sz i = 0; i < array_size(node->match.cases); i++) {
717 Node *field = node->match_cases[i]; 789 Node *field = node->match.cases[i];
718 if (field->case_value) { 790 field->parent = node;
791 if (field->case_entry.cond) {
719 Str field_name = str_concat( 792 Str field_name = str_concat(
720 enum_prefix, field->case_value->value.str, 793 enum_prefix, field->case_entry.cond->value.str,
721 a->storage); 794 a->storage);
722 if (!enummap_lookup(&res.scope->enums, field_name)) { 795 if (!enummap_lookup(&res.scope->enums, field_name)) {
723 eprintln("%s:%d:%d: error: unknown enum field '%s'", 796 eprintln("%s:%d:%d: error: unknown enum field '%s'",
724 a->file_name, field->case_value->line, 797 a->file_name, field->case_entry.cond->line,
725 field->case_value->col, field_name); 798 field->case_entry.cond->col, field_name);
726 a->err = true; 799 a->err = true;
727 } 800 }
728 } 801 }
729 } 802 }
730 } 803 }
731 Str previous = cstr(""); 804 Str previous = cstr("");
732 for (sz i = 0; i < array_size(node->match_cases); i++) { 805 for (sz i = 0; i < array_size(node->match.cases); i++) {
733 Node *expr = node->match_cases[i]; 806 Node *expr = node->match.cases[i];
807 expr->parent = node;
734 Str next = type_inference(a, expr, scope); 808 Str next = type_inference(a, expr, scope);
735 if (i != 0 && !str_eq(next, previous)) { 809 if (i != 0 && !str_eq(next, previous)) {
736 emit_semantic_error( 810 emit_semantic_error(
@@ -744,24 +818,27 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
744 return node->type; 818 return node->type;
745 } break; 819 } break;
746 case NODE_CASE_MATCH: { 820 case NODE_CASE_MATCH: {
747 if (node->case_expr->kind != NODE_BLOCK) { 821 if (node->case_entry.expr->kind != NODE_BLOCK) {
748 scope = typescope_alloc(a, scope); 822 scope = typescope_alloc(a, scope);
749 } 823 }
750 node->type = type_inference(a, node->case_expr, scope); 824 node->case_entry.expr->parent = node;
825 node->type = type_inference(a, node->case_entry.expr, scope);
751 return node->type; 826 return node->type;
752 } break; 827 } break;
753 case NODE_CASE_COND: { 828 case NODE_CASE_COND: {
754 if (node->case_value) { 829 node->case_entry.expr->parent = node;
755 Str cond = type_inference(a, node->case_value, scope); 830 if (node->case_entry.cond) {
831 node->case_entry.cond->parent = node;
832 Str cond = type_inference(a, node->case_entry.cond, scope);
756 if (!str_eq(cond, cstr("bool"))) { 833 if (!str_eq(cond, cstr("bool"))) {
757 emit_semantic_error(a, node, 834 emit_semantic_error(a, node,
758 cstr("non-boolean case condition")); 835 cstr("non-boolean case condition"));
759 } 836 }
760 } 837 }
761 if (node->case_expr->kind != NODE_BLOCK) { 838 if (node->case_entry.expr->kind != NODE_BLOCK) {
762 scope = typescope_alloc(a, scope); 839 scope = typescope_alloc(a, scope);
763 } 840 }
764 node->type = type_inference(a, node->case_expr, scope); 841 node->type = type_inference(a, node->case_entry.expr, scope);
765 return node->type; 842 return node->type;
766 } break; 843 } break;
767 case NODE_TRUE: 844 case NODE_TRUE:
@@ -776,14 +853,16 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
776 case NODE_NOT: 853 case NODE_NOT:
777 case NODE_AND: 854 case NODE_AND:
778 case NODE_OR: { 855 case NODE_OR: {
779 Str left = type_inference(a, node->left, scope); 856 node->binary.left->parent = node;
857 Str left = type_inference(a, node->binary.left, scope);
780 if (!str_eq(left, cstr("bool"))) { 858 if (!str_eq(left, cstr("bool"))) {
781 emit_semantic_error(a, node, 859 emit_semantic_error(a, node,
782 cstr("expected bool on logic expression")); 860 cstr("expected bool on logic expression"));
783 return cstr(""); 861 return cstr("");
784 } 862 }
785 if (node->right) { 863 if (node->binary.right) {
786 Str right = type_inference(a, node->right, scope); 864 node->binary.right->parent = node;
865 Str right = type_inference(a, node->binary.right, scope);
787 if (!str_eq(right, cstr("bool"))) { 866 if (!str_eq(right, cstr("bool"))) {
788 emit_semantic_error( 867 emit_semantic_error(
789 a, node, cstr("expected bool on logic expression")); 868 a, node, cstr("expected bool on logic expression"));
@@ -799,8 +878,10 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
799 case NODE_GT: 878 case NODE_GT:
800 case NODE_LE: 879 case NODE_LE:
801 case NODE_GE: { 880 case NODE_GE: {
802 Str left = type_inference(a, node->left, scope); 881 node->binary.left->parent = node;
803 Str right = type_inference(a, node->right, scope); 882 node->binary.right->parent = node;
883 Str left = type_inference(a, node->binary.left, scope);
884 Str right = type_inference(a, node->binary.right, scope);
804 if (!str_eq(left, right)) { 885 if (!str_eq(left, right)) {
805 emit_semantic_error( 886 emit_semantic_error(
806 a, node, cstr("mismatched types on binary expression")); 887 a, node, cstr("mismatched types on binary expression"));
@@ -810,7 +891,8 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
810 return node->type; 891 return node->type;
811 } break; 892 } break;
812 case NODE_BITNOT: { 893 case NODE_BITNOT: {
813 Str left = type_inference(a, node->left, scope); 894 node->binary.left->parent = node;
895 Str left = type_inference(a, node->binary.left, scope);
814 if (!strset_lookup(&a->integer_types, left)) { 896 if (!strset_lookup(&a->integer_types, left)) {
815 emit_semantic_error( 897 emit_semantic_error(
816 a, node, cstr("non integer type on bit twiddling expr")); 898 a, node, cstr("non integer type on bit twiddling expr"));
@@ -821,10 +903,13 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
821 } break; 903 } break;
822 case NODE_BITAND: 904 case NODE_BITAND:
823 case NODE_BITOR: 905 case NODE_BITOR:
906 case NODE_BITXOR:
824 case NODE_BITLSHIFT: 907 case NODE_BITLSHIFT:
825 case NODE_BITRSHIFT: { 908 case NODE_BITRSHIFT: {
826 Str left = type_inference(a, node->left, scope); 909 node->binary.left->parent = node;
827 Str right = type_inference(a, node->right, scope); 910 node->binary.right->parent = node;
911 Str left = type_inference(a, node->binary.left, scope);
912 Str right = type_inference(a, node->binary.right, scope);
828 if (!strset_lookup(&a->integer_types, left) || 913 if (!strset_lookup(&a->integer_types, left) ||
829 !strset_lookup(&a->integer_types, right)) { 914 !strset_lookup(&a->integer_types, right)) {
830 emit_semantic_error( 915 emit_semantic_error(
@@ -839,8 +924,10 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
839 case NODE_DIV: 924 case NODE_DIV:
840 case NODE_MUL: 925 case NODE_MUL:
841 case NODE_MOD: { 926 case NODE_MOD: {
842 Str left = type_inference(a, node->left, scope); 927 node->binary.left->parent = node;
843 Str right = type_inference(a, node->right, scope); 928 node->binary.right->parent = node;
929 Str left = type_inference(a, node->binary.left, scope);
930 Str right = type_inference(a, node->binary.right, scope);
844 if (!strset_lookup(&a->numeric_types, left) || 931 if (!strset_lookup(&a->numeric_types, left) ||
845 !strset_lookup(&a->numeric_types, right)) { 932 !strset_lookup(&a->numeric_types, right)) {
846 emit_semantic_error( 933 emit_semantic_error(
@@ -856,7 +943,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
856 return node->type; 943 return node->type;
857 } break; 944 } break;
858 case NODE_NUM_UINT: { 945 case NODE_NUM_UINT: {
859 node->type = cstr("uint"); 946 node->type = cstr("int");
860 return node->type; 947 return node->type;
861 } break; 948 } break;
862 case NODE_NUM_INT: { 949 case NODE_NUM_INT: {
@@ -893,6 +980,13 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
893 } 980 }
894 981
895 FindSymbolResult sym = find_symbol(scope, symbol); 982 FindSymbolResult sym = find_symbol(scope, symbol);
983 if (!str_eq(sym.scope->name, scope->name) && sym.scope->name.size) {
984 eprintln(
985 "%s:%d:%d: error: can't capture external local symbol '%s'",
986 a->file_name, node->line, node->col, symbol);
987 a->err = true;
988 return cstr("");
989 }
896 node->unique_name = str_concat(cstr("."), symbol, a->storage); 990 node->unique_name = str_concat(cstr("."), symbol, a->storage);
897 node->unique_name = 991 node->unique_name =
898 str_concat(node->unique_name, 992 str_concat(node->unique_name,
@@ -900,7 +994,8 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
900 994
901 Str type_name = type->val.name; 995 Str type_name = type->val.name;
902 if (node->kind == NODE_SYMBOL_IDX) { 996 if (node->kind == NODE_SYMBOL_IDX) {
903 Str idx_type = type_inference(a, node->arr_size, scope); 997 node->sym.arr_size->parent = node;
998 Str idx_type = type_inference(a, node->sym.arr_size, scope);
904 if (!strset_lookup(&a->integer_types, idx_type)) { 999 if (!strset_lookup(&a->integer_types, idx_type)) {
905 emit_semantic_error( 1000 emit_semantic_error(
906 a, node, cstr("can't resolve non integer index")); 1001 a, node, cstr("can't resolve non integer index"));
@@ -914,7 +1009,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
914 1009
915 FindEnumResult e = find_enum(scope, type_name); 1010 FindEnumResult e = find_enum(scope, type_name);
916 if (e.map && str_eq(symbol, type_name)) { 1011 if (e.map && str_eq(symbol, type_name)) {
917 if (!node->next) { 1012 if (!node->sym.next) {
918 eprintln( 1013 eprintln(
919 "%s:%d:%d: error: unspecified enum field for symbol " 1014 "%s:%d:%d: error: unspecified enum field for symbol "
920 "'%s'", 1015 "'%s'",
@@ -924,20 +1019,21 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
924 } 1019 }
925 // Check if there is a next and it matches the enum field. 1020 // Check if there is a next and it matches the enum field.
926 Str field = str_concat(type_name, cstr("."), a->storage); 1021 Str field = str_concat(type_name, cstr("."), a->storage);
927 field = str_concat(field, node->next->value.str, a->storage); 1022 field =
1023 str_concat(field, node->sym.next->value.str, a->storage);
928 if (!enummap_lookup(&e.scope->enums, field)) { 1024 if (!enummap_lookup(&e.scope->enums, field)) {
929 eprintln( 1025 eprintln(
930 "%s:%d:%d: error: unknown enum field for " 1026 "%s:%d:%d: error: unknown enum field for "
931 "'%s': %s", 1027 "'%s': %s",
932 a->file_name, node->line, node->col, symbol, 1028 a->file_name, node->line, node->col, symbol,
933 node->next->value.str); 1029 node->sym.next->value.str);
934 a->err = true; 1030 a->err = true;
935 return cstr(""); 1031 return cstr("");
936 } 1032 }
937 1033
938 node->next->type = type_name; 1034 node->sym.next->type = type_name;
939 node->type = type_name; 1035 node->type = type_name;
940 return node->next->type; 1036 return node->sym.next->type;
941 } 1037 }
942 1038
943 FindStructResult s = find_struct(scope, type_name); 1039 FindStructResult s = find_struct(scope, type_name);
@@ -950,11 +1046,11 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
950 a->err = true; 1046 a->err = true;
951 return cstr(""); 1047 return cstr("");
952 } else { 1048 } else {
953 if (node->next) { 1049 if (node->sym.next) {
954 Str chain = type_name; 1050 Str chain = type_name;
955 Node *next = node; 1051 Node *next = node;
956 while (next->next) { 1052 while (next->sym.next) {
957 next = next->next; 1053 next = next->sym.next;
958 chain = str_concat(chain, cstr("."), a->storage); 1054 chain = str_concat(chain, cstr("."), a->storage);
959 chain = 1055 chain =
960 str_concat(chain, next->value.str, a->storage); 1056 str_concat(chain, next->value.str, a->storage);
@@ -970,8 +1066,9 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
970 } 1066 }
971 Str field_type = field->val.type; 1067 Str field_type = field->val.type;
972 if (next->kind == NODE_SYMBOL_IDX) { 1068 if (next->kind == NODE_SYMBOL_IDX) {
1069 node->sym.arr_size->parent = node;
973 Str idx_type = 1070 Str idx_type =
974 type_inference(a, next->arr_size, scope); 1071 type_inference(a, next->sym.arr_size, scope);
975 if (!strset_lookup(&a->integer_types, idx_type)) { 1072 if (!strset_lookup(&a->integer_types, idx_type)) {
976 emit_semantic_error( 1073 emit_semantic_error(
977 a, next, 1074 a, next,
@@ -1002,6 +1099,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
1002 StrSet *set = NULL; 1099 StrSet *set = NULL;
1003 for (sz i = 0; i < array_size(node->elements); i++) { 1100 for (sz i = 0; i < array_size(node->elements); i++) {
1004 Node *next = node->elements[i]; 1101 Node *next = node->elements[i];
1102 next->parent = node;
1005 Str field_name = str_concat(name, cstr("."), a->storage); 1103 Str field_name = str_concat(name, cstr("."), a->storage);
1006 field_name = 1104 field_name =
1007 str_concat(field_name, next->value.str, a->storage); 1105 str_concat(field_name, next->value.str, a->storage);
@@ -1031,10 +1129,17 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
1031 a->err = true; 1129 a->err = true;
1032 return cstr(""); 1130 return cstr("");
1033 } 1131 }
1132 FindSymbolResult sym = find_symbol(scope, symbol);
1133 node->unique_name = str_concat(cstr("."), symbol, a->storage);
1134 node->unique_name =
1135 str_concat(node->unique_name,
1136 str_from_int(sym.scope->id, a->storage), a->storage);
1137
1034 // Check that actual parameters typecheck 1138 // Check that actual parameters typecheck
1035 Str args = cstr(""); 1139 Str args = cstr("");
1036 for (sz i = 0; i < array_size(node->elements); i++) { 1140 for (sz i = 0; i < array_size(node->elements); i++) {
1037 Node *expr = node->elements[i]; 1141 Node *expr = node->elements[i];
1142 expr->parent = node;
1038 Str type = type_inference(a, expr, scope); 1143 Str type = type_inference(a, expr, scope);
1039 args = str_concat(args, type, a->storage); 1144 args = str_concat(args, type, a->storage);
1040 if (i != array_size(node->elements) - 1) { 1145 if (i != array_size(node->elements) - 1) {
@@ -1060,15 +1165,27 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
1060 Str type; 1165 Str type;
1061 for (sz i = 0; i < array_size(node->elements); i++) { 1166 for (sz i = 0; i < array_size(node->elements); i++) {
1062 Node *expr = node->elements[i]; 1167 Node *expr = node->elements[i];
1168 expr->parent = node;
1063 type = type_inference(a, expr, scope); 1169 type = type_inference(a, expr, scope);
1170 if (str_has_prefix(type, cstr("ret:")) ||
1171 str_has_prefix(type, cstr("flow:"))) {
1172 break;
1173 }
1064 } 1174 }
1065 node->type = type; 1175 node->type = type;
1066 return node->type; 1176 return node->type;
1067 } break; 1177 } break;
1068 case NODE_RETURN: { 1178 case NODE_RETURN: {
1069 Str ret_type = cstr(""); 1179 if (!scope->name.size) {
1180 emit_semantic_error(
1181 a, node, cstr("return statement outside a function"));
1182 a->err = true;
1183 return cstr("");
1184 }
1185 Str ret_type = cstr("ret:");
1070 for (sz i = 0; i < array_size(node->elements); i++) { 1186 for (sz i = 0; i < array_size(node->elements); i++) {
1071 Node *expr = node->elements[i]; 1187 Node *expr = node->elements[i];
1188 expr->parent = node;
1072 Str type = type_inference(a, expr, scope); 1189 Str type = type_inference(a, expr, scope);
1073 ret_type = str_concat(ret_type, type, a->storage); 1190 ret_type = str_concat(ret_type, type, a->storage);
1074 if (i != array_size(node->elements) - 1) { 1191 if (i != array_size(node->elements) - 1) {
@@ -1081,40 +1198,68 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
1081 node->type = ret_type; 1198 node->type = ret_type;
1082 return node->type; 1199 return node->type;
1083 } break; 1200 } break;
1201 case NODE_CONTINUE:
1202 case NODE_BREAK: {
1203 // Check if we are inside a loop.
1204 Node *parent = node->parent;
1205 bool inside_loop = false;
1206 while (parent != NULL) {
1207 if (parent->kind == NODE_WHILE) {
1208 inside_loop = true;
1209 break;
1210 }
1211 parent = parent->parent;
1212 }
1213 if (!inside_loop) {
1214 eprintln(
1215 "%s:%d:%d: error: control flow statement outside a loop",
1216 a->file_name, node->line, node->col);
1217 a->err = true;
1218 return cstr("");
1219 }
1220 node->type = cstr("flow:");
1221 return node->type;
1222 } break;
1084 case NODE_FUN: { 1223 case NODE_FUN: {
1085 node->type = cstr("nil"); 1224 node->type = cstr("nil");
1086 Scope *prev_scope = scope; 1225 Scope *prev_scope = scope;
1087 scope = typescope_alloc(a, scope); 1226 scope = typescope_alloc(a, scope);
1088 Str param_type = cstr(""); 1227 Str param_type = cstr("");
1089 for (sz i = 0; i < array_size(node->func_params); i++) { 1228 for (sz i = 0; i < array_size(node->func.params); i++) {
1090 Node *param = node->func_params[i]; 1229 Node *param = node->func.params[i];
1091 Str symbol = param->param_name->value.str; 1230 param->parent = node;
1092 Str type = param->param_type->value.str; 1231 Str symbol = param->param.name->value.str;
1093 if (param->param_type->is_ptr) { 1232 Str type = param->param.type->value.str;
1233 if (param->param.type->is_ptr) {
1094 type = str_concat(cstr("@"), type, a->storage); 1234 type = str_concat(cstr("@"), type, a->storage);
1095 } 1235 }
1096 if (param->param_type->kind == NODE_ARR_TYPE) { 1236 if (param->param.type->kind == NODE_ARR_TYPE) {
1097 type = str_concat(cstr("@"), type, a->storage); 1237 type = str_concat(cstr("@"), type, a->storage);
1098 } 1238 }
1099 param->param_name->type = 1239 param->param.name->type =
1100 type_inference(a, param->param_type, scope); 1240 type_inference(a, param->param.type, scope);
1101 param->type = type; 1241 param->type = type;
1102 symmap_insert(&scope->symbols, symbol, 1242 symmap_insert(&scope->symbols, symbol,
1103 (Symbol){.name = type, .kind = SYM_PARAM}, 1243 (Symbol){.name = type, .kind = SYM_PARAM},
1104 a->storage); 1244 a->storage);
1105 param_type = str_concat(param_type, type, a->storage); 1245 param_type = str_concat(param_type, type, a->storage);
1106 if (i != array_size(node->func_params) - 1) { 1246 if (i != array_size(node->func.params) - 1) {
1107 param_type = str_concat(param_type, cstr(","), a->storage); 1247 param_type = str_concat(param_type, cstr(","), a->storage);
1108 } 1248 }
1249 symbol = str_concat(cstr("."), symbol, a->storage);
1250 symbol = str_concat(symbol, str_from_int(scope->id, a->storage),
1251 a->storage);
1252 param->unique_name = symbol;
1109 } 1253 }
1110 if (!param_type.size) { 1254 if (!param_type.size) {
1111 param_type = cstr("nil"); 1255 param_type = cstr("nil");
1112 } 1256 }
1113 node->fun_params = param_type; 1257 node->type_params = param_type;
1114 1258
1115 Str ret_type = cstr(""); 1259 Str ret_type = cstr("");
1116 for (sz i = 0; i < array_size(node->func_ret); i++) { 1260 for (sz i = 0; i < array_size(node->func.ret); i++) {
1117 Node *expr = node->func_ret[i]; 1261 Node *expr = node->func.ret[i];
1262 expr->parent = node;
1118 Str type = type_inference(a, expr, scope); 1263 Str type = type_inference(a, expr, scope);
1119 if (expr->is_ptr) { 1264 if (expr->is_ptr) {
1120 type = str_concat(cstr("@"), type, a->storage); 1265 type = str_concat(cstr("@"), type, a->storage);
@@ -1123,28 +1268,28 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
1123 type = str_concat(cstr("@"), type, a->storage); 1268 type = str_concat(cstr("@"), type, a->storage);
1124 } 1269 }
1125 ret_type = str_concat(ret_type, type, a->storage); 1270 ret_type = str_concat(ret_type, type, a->storage);
1126 if (i != array_size(node->func_ret) - 1) { 1271 if (i != array_size(node->func.ret) - 1) {
1127 ret_type = str_concat(ret_type, cstr(","), a->storage); 1272 ret_type = str_concat(ret_type, cstr(","), a->storage);
1128 } 1273 }
1129 } 1274 }
1130 if (!ret_type.size) { 1275 if (!ret_type.size) {
1131 ret_type = cstr("nil"); 1276 ret_type = cstr("nil");
1132 } 1277 }
1133 node->fun_return = ret_type; 1278 node->type_returns = ret_type;
1134 1279
1135 Str symbol = node->func_name->value.str; 1280 Str symbol = node->func.name->value.str;
1136 if (prev_scope->parent != NULL) { 1281 if (prev_scope->parent != NULL) {
1137 if (symmap_lookup(&prev_scope->symbols, symbol)) { 1282 if (symmap_lookup(&prev_scope->symbols, symbol)) {
1138 eprintln( 1283 eprintln(
1139 "%s:%d:%d: error: function '%s' already defined in " 1284 "%s:%d:%d: error: function '%s' already defined in "
1140 "current " 1285 "current "
1141 "scope ", 1286 "scope ",
1142 a->file_name, node->var_name->line, node->var_name->col, 1287 a->file_name, node->var.name->line, node->var.name->col,
1143 symbol); 1288 symbol);
1144 a->err = true; 1289 a->err = true;
1145 return cstr(""); 1290 return cstr("");
1146 } 1291 }
1147 symmap_insert(&scope->symbols, symbol, 1292 symmap_insert(&prev_scope->symbols, symbol,
1148 (Symbol){.name = symbol, .kind = SYM_FUN}, 1293 (Symbol){.name = symbol, .kind = SYM_FUN},
1149 a->storage); 1294 a->storage);
1150 } 1295 }
@@ -1154,41 +1299,50 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
1154 .param_type = param_type, 1299 .param_type = param_type,
1155 .return_type = ret_type}, 1300 .return_type = ret_type},
1156 a->storage); 1301 a->storage);
1302 symbol = str_concat(cstr("."), symbol, a->storage);
1303 symbol = str_concat(
1304 symbol, str_from_int(prev_scope->id, a->storage), a->storage);
1305 node->unique_name = symbol;
1157 1306
1158 if (node->func_body->kind == NODE_BLOCK) { 1307 if (node->func.body->kind == NODE_BLOCK) {
1159 Str type; 1308 Str type;
1160 for (sz i = 0; i < array_size(node->func_body->elements); i++) { 1309 for (sz i = 0; i < array_size(node->func.body->elements); i++) {
1161 Node *expr = node->func_body->elements[i]; 1310 Node *expr = node->func.body->elements[i];
1311 expr->parent = node;
1312 // TODO: block early return.
1162 type = type_inference(a, expr, scope); 1313 type = type_inference(a, expr, scope);
1163 } 1314 }
1164 if (!type.size) { 1315 if (!type.size) {
1165 type = cstr("nil"); 1316 type = cstr("nil");
1166 } 1317 }
1167 node->func_body->type = type; 1318 node->func.body->type = type;
1168 } else { 1319 } else {
1169 type_inference(a, node->func_body, scope); 1320 node->func.body->parent = node;
1321 type_inference(a, node->func.body, scope);
1170 } 1322 }
1171 1323
1172 // Ensure main body return matches the prototype. 1324 // Ensure main body return matches the prototype.
1173 if (!str_eq(node->func_body->type, ret_type)) { 1325 Str type = str_remove_prefix(node->func.body->type, cstr("ret:"));
1326 node->func.body->type = type;
1327 if (!str_eq(type, ret_type)) {
1174 eprintln( 1328 eprintln(
1175 "%s:%d:%d: error: mismatched return type %s, expected %s", 1329 "%s:%d:%d: error: mismatched return type %s, expected %s",
1176 a->file_name, node->line, node->col, node->func_body->type, 1330 a->file_name, node->line, node->col, type, ret_type);
1177 ret_type);
1178 a->err = true; 1331 a->err = true;
1179 } 1332 }
1180 1333
1181 // Ensure ALL return statements match the function prototype. 1334 // Ensure ALL return statements match the function prototype.
1182 typecheck_returns(a, node->func_body, ret_type); 1335 typecheck_returns(a, node->func.body, ret_type);
1183 1336
1184 // TODO: should return statements be allowed on let blocks? 1337 // TODO: should return statements be allowed on let blocks?
1185 return node->type; 1338 return node->type;
1186 } break; 1339 } break;
1187 default: { 1340 default: {
1188 emit_semantic_error(a, node, 1341 eprintln(
1189 cstr("type inference not implemented for this " 1342 "%s:%d:%d: error: type inference not implemented for node "
1190 "kind of expression")); 1343 "type: %s",
1191 println("KIND: %s", node_str[node->kind]); 1344 a->file_name, node->line, node->col, node_str[node->kind]);
1345 a->err = true;
1192 } break; 1346 } break;
1193 } 1347 }
1194 return cstr(""); 1348 return cstr("");
@@ -1249,16 +1403,59 @@ symbolic_analysis(Analyzer *a, Parser *parser) {
1249 for (sz i = 0; i < array_size(parser->nodes); i++) { 1403 for (sz i = 0; i < array_size(parser->nodes); i++) {
1250 Node *root = parser->nodes[i]; 1404 Node *root = parser->nodes[i];
1251 if (root->kind == NODE_FUN) { 1405 if (root->kind == NODE_FUN) {
1252 Str symbol = root->func_name->value.str; 1406 Str symbol = root->func.name->value.str;
1253 if (symmap_lookup(&scope->symbols, symbol)) { 1407 if (symmap_lookup(&scope->symbols, symbol)) {
1254 eprintln( 1408 eprintln(
1255 "%s:%d:%d: error: function '%s' already defined in " 1409 "%s:%d:%d: error: function '%s' already defined in "
1256 "current " 1410 "current "
1257 "scope ", 1411 "scope ",
1258 a->file_name, root->var_name->line, root->var_name->col, 1412 a->file_name, root->var.name->line, root->var.name->col,
1259 symbol); 1413 symbol);
1260 a->err = true; 1414 a->err = true;
1261 } 1415 }
1416 Str param_type = cstr("");
1417 for (sz i = 0; i < array_size(root->func.params); i++) {
1418 Node *param = root->func.params[i];
1419 Str type = param->param.type->value.str;
1420 if (param->param.type->is_ptr) {
1421 type = str_concat(cstr("@"), type, a->storage);
1422 }
1423 if (param->param.type->kind == NODE_ARR_TYPE) {
1424 type = str_concat(cstr("@"), type, a->storage);
1425 }
1426 param_type = str_concat(param_type, type, a->storage);
1427 if (i != array_size(root->func.params) - 1) {
1428 param_type = str_concat(param_type, cstr(","), a->storage);
1429 }
1430 }
1431 if (!param_type.size) {
1432 param_type = cstr("nil");
1433 }
1434 root->type_params = param_type;
1435
1436 Str ret_type = cstr("");
1437 for (sz i = 0; i < array_size(root->func.ret); i++) {
1438 Node *expr = root->func.ret[i];
1439 Str type = expr->value.str;
1440 if (expr->is_ptr) {
1441 type = str_concat(cstr("@"), type, a->storage);
1442 }
1443 if (expr->kind == NODE_ARR_TYPE) {
1444 type = str_concat(cstr("@"), type, a->storage);
1445 }
1446 ret_type = str_concat(ret_type, type, a->storage);
1447 if (i != array_size(root->func.ret) - 1) {
1448 ret_type = str_concat(ret_type, cstr(","), a->storage);
1449 }
1450 }
1451 if (!ret_type.size) {
1452 ret_type = cstr("nil");
1453 }
1454 funmap_insert(&scope->funcs, symbol,
1455 (Fun){.name = symbol,
1456 .param_type = param_type,
1457 .return_type = ret_type},
1458 a->storage);
1262 symmap_insert(&scope->symbols, symbol, 1459 symmap_insert(&scope->symbols, symbol,
1263 (Symbol){.name = symbol, .kind = SYM_FUN}, 1460 (Symbol){.name = symbol, .kind = SYM_FUN},
1264 a->storage); 1461 a->storage);
diff --git a/src/vm.c b/src/vm.c
index 205c15a..0791706 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -5,12 +5,15 @@
5#include "compiler.c" 5#include "compiler.c"
6 6
7#define N_CONST 256 7#define N_CONST 256
8#define STACK_SIZE KB(64) 8#define STACK_SIZE MB(4)
9typedef struct VM { 9typedef struct VM {
10 Chunk *main;
10 Chunk *chunk; 11 Chunk *chunk;
11 Constant regs[N_CONST];
12 u8 stack[STACK_SIZE]; 12 u8 stack[STACK_SIZE];
13 Instruction *ip; 13 Instruction *ip;
14 u8 *sp;
15 u64 *fp;
16 Constant *regs;
14} VM; 17} VM;
15 18
16void 19void
@@ -18,8 +21,13 @@ vm_init(VM *vm, Chunk *chunk) {
18 assert(vm); 21 assert(vm);
19 assert(chunk); 22 assert(chunk);
20 assert(chunk->code); 23 assert(chunk->code);
24 vm->main = chunk;
21 vm->chunk = chunk; 25 vm->chunk = chunk;
22 vm->ip = vm->chunk->code; 26 vm->ip = vm->chunk->code;
27 vm->fp = (u64 *)vm->stack;
28 vm->sp = vm->stack + chunk->var_off;
29 vm->regs = (Constant *)vm->sp;
30 vm->sp += sizeof(Constant) * chunk->reg_idx;
23} 31}
24 32
25#define OP_UNARY(OP, TYPE) \ 33#define OP_UNARY(OP, TYPE) \
@@ -77,6 +85,7 @@ vm_run(VM *vm) {
77 case OP_NOT: OP_UNARY(!, i) break; 85 case OP_NOT: OP_UNARY(!, i) break;
78 case OP_BITNOT: OP_UNARY(~, i) break; 86 case OP_BITNOT: OP_UNARY(~, i) break;
79 case OP_BITOR: OP_BINARY(|, i) break; 87 case OP_BITOR: OP_BINARY(|, i) break;
88 case OP_BITXOR: OP_BINARY(^, i) break;
80 case OP_BITAND: OP_BINARY(&, i) break; 89 case OP_BITAND: OP_BINARY(&, i) break;
81 case OP_BITLSHIFT: OP_BINARY(<<, i) break; 90 case OP_BITLSHIFT: OP_BINARY(<<, i) break;
82 case OP_BITRSHIFT: OP_BINARY(>>, i) break; 91 case OP_BITRSHIFT: OP_BINARY(>>, i) break;
@@ -107,6 +116,7 @@ vm_run(VM *vm) {
107 case OP_NOTI: OP_UNARY_CONST(!, i) break; 116 case OP_NOTI: OP_UNARY_CONST(!, i) break;
108 case OP_BITNOTI: OP_UNARY_CONST(~, i) break; 117 case OP_BITNOTI: OP_UNARY_CONST(~, i) break;
109 case OP_BITORI: OP_BINARY_CONST(|, i) break; 118 case OP_BITORI: OP_BINARY_CONST(|, i) break;
119 case OP_BITXORI: OP_BINARY_CONST(^, i) break;
110 case OP_BITANDI: OP_BINARY_CONST(&, i) break; 120 case OP_BITANDI: OP_BINARY_CONST(&, i) break;
111 case OP_BITLSHIFTI: OP_BINARY_CONST(<<, i) break; 121 case OP_BITLSHIFTI: OP_BINARY_CONST(<<, i) break;
112 case OP_BITRSHIFTI: OP_BINARY_CONST(>>, i) break; 122 case OP_BITRSHIFTI: OP_BINARY_CONST(>>, i) break;
@@ -134,61 +144,121 @@ vm_run(VM *vm) {
134 vm->regs[dst].f = 144 vm->regs[dst].f =
135 fmod(vm->regs[src_a].f, vm->chunk->constants[src_b].f); 145 fmod(vm->regs[src_a].f, vm->chunk->constants[src_b].f);
136 } break; 146 } break;
147 case OP_STGVAR: {
148 u8 dst = instruction.dst;
149 u8 src = instruction.a;
150 Variable var = vm->main->vars[dst];
151 s64 *stack = (s64 *)&vm->stack[var.offset];
152 *stack = vm->regs[src].i;
153 } break;
154 case OP_STGVARI: {
155 u8 dst = instruction.dst;
156 u8 src = instruction.a;
157 Variable var = vm->main->vars[dst];
158 s64 *stack = (s64 *)&vm->stack[var.offset];
159 *stack = vm->chunk->constants[src].i;
160 } break;
137 case OP_LDGVAR: { 161 case OP_LDGVAR: {
138 u8 dst = instruction.dst; 162 u8 dst = instruction.dst;
139 u8 src = instruction.a; 163 u8 src = instruction.a;
140 Variable var = vm->chunk->vars[src]; 164 Variable var = vm->main->vars[src];
141 s64 *stack = (s64 *)&vm->stack[var.offset]; 165 s64 *stack = (s64 *)&vm->stack[var.offset];
142 vm->regs[dst].i = *stack; 166 vm->regs[dst].i = *stack;
143 } break; 167 } break;
144 case OP_STGVAR: { 168 case OP_LDGADDR: {
145 u8 dst = instruction.dst; 169 u8 dst = instruction.dst;
146 u8 src = instruction.a; 170 u8 src = instruction.a;
147 Variable var = vm->chunk->vars[dst]; 171 Variable var = vm->main->vars[src];
148 s64 *stack = (s64 *)&vm->stack[var.offset]; 172 s64 *stack = (s64 *)&vm->stack[var.offset];
149 *stack = vm->regs[src].i; 173 vm->regs[dst].ptr = (ptrsize)stack;
150 } break; 174 } break;
151 case OP_STGVARI: { 175 case OP_STLVAR: {
152 u8 dst = instruction.dst; 176 u8 dst = instruction.dst;
153 u8 src = instruction.a; 177 u8 src = instruction.a;
154 Variable var = vm->chunk->vars[dst]; 178 Variable var = vm->chunk->vars[dst];
155 s64 *stack = (s64 *)&vm->stack[var.offset]; 179 vm->fp[var.offset / 8] = vm->regs[src].i;
156 *stack = vm->chunk->constants[src].i;
157 } break; 180 } break;
158 case OP_JMPI: { 181 case OP_STLVARI: {
159 sz offset = vm->chunk->constants[instruction.dst].i; 182 u8 dst = instruction.dst;
160 vm->ip += offset - 1; 183 u8 src = instruction.a;
184 Variable var = vm->chunk->vars[dst];
185 vm->fp[var.offset / 8] = vm->chunk->constants[src].i;
186 } break;
187 case OP_LDLVAR: {
188 u8 dst = instruction.dst;
189 u8 src = instruction.a;
190 Variable var = vm->chunk->vars[src];
191 vm->regs[dst].i = vm->fp[var.offset / 8];
192 } break;
193 case OP_LDLADDR: {
194 u8 dst = instruction.dst;
195 u8 src = instruction.a;
196 Variable var = vm->chunk->vars[src];
197 vm->regs[dst].i = (ptrsize)&vm->fp[var.offset / 8];
198 } break;
199 case OP_LDSTR: {
200 u8 dst = instruction.dst;
201 u8 src = instruction.a;
202 Str *str = &vm->chunk->strings[src];
203 vm->regs[dst].ptr = (ptrsize)str;
204 } break;
205 case OP_ST64I: {
206 sz value = vm->regs[instruction.dst].ptr;
207 s64 *addr = (s64 *)vm->regs[instruction.a].ptr;
208 sz offset = vm->chunk->constants[instruction.b].i;
209 addr[offset] = value;
210 } break;
211 case OP_ST64: {
212 sz value = vm->regs[instruction.dst].i;
213 s64 *addr = (s64 *)vm->regs[instruction.a].ptr;
214 sz offset = vm->regs[instruction.b].i;
215 addr[offset] = value;
216 } break;
217 case OP_LD64I: {
218 s64 *addr = (s64 *)vm->regs[instruction.a].ptr;
219 sz offset = vm->chunk->constants[instruction.b].i;
220 vm->regs[instruction.dst].i = addr[offset];
221 } break;
222 case OP_LD64: {
223 s64 *addr = (s64 *)vm->regs[instruction.a].ptr;
224 sz offset = vm->regs[instruction.b].i;
225 vm->regs[instruction.dst].i = addr[offset];
226 } break;
227 case OP_JMP: {
228 u8 dst = instruction.dst;
229 sz pos = intintmap_lookup(&vm->chunk->labels, dst)->val;
230 vm->ip = vm->chunk->code + pos;
161 } break; 231 } break;
162 case OP_JMPFI: { 232 case OP_JMPFI: {
163 bool cond = vm->chunk->constants[instruction.dst].i; 233 u8 dst = instruction.dst;
164 sz offset = vm->chunk->constants[instruction.a].i; 234 sz pos = intintmap_lookup(&vm->chunk->labels, dst)->val;
235 bool cond = vm->chunk->constants[instruction.a].i;
165 if (!cond) { 236 if (!cond) {
166 vm->ip += offset - 1; 237 vm->ip = vm->chunk->code + pos;
167 } 238 }
168 } break; 239 } break;
169 case OP_JMPTI: { 240 case OP_JMPTI: {
170 bool cond = vm->chunk->constants[instruction.dst].i; 241 u8 dst = instruction.dst;
171 sz offset = vm->chunk->constants[instruction.a].i; 242 sz pos = intintmap_lookup(&vm->chunk->labels, dst)->val;
243 bool cond = vm->chunk->constants[instruction.a].i;
172 if (cond) { 244 if (cond) {
173 vm->ip += offset - 1; 245 vm->ip = vm->chunk->code + pos;
174 } 246 }
175 } break; 247 } break;
176 case OP_JMP: {
177 sz offset = vm->chunk->constants[instruction.dst].i;
178 vm->ip += offset - 1;
179 } break;
180 case OP_JMPF: { 248 case OP_JMPF: {
181 bool cond = vm->regs[instruction.dst].i; 249 u8 dst = instruction.dst;
182 sz offset = vm->chunk->constants[instruction.a].i; 250 sz pos = intintmap_lookup(&vm->chunk->labels, dst)->val;
251 bool cond = vm->regs[instruction.a].i;
183 if (!cond) { 252 if (!cond) {
184 vm->ip += offset - 1; 253 vm->ip = vm->chunk->code + pos;
185 } 254 }
186 } break; 255 } break;
187 case OP_JMPT: { 256 case OP_JMPT: {
188 bool cond = vm->regs[instruction.dst].i; 257 u8 dst = instruction.dst;
189 sz offset = vm->chunk->constants[instruction.a].i; 258 sz pos = intintmap_lookup(&vm->chunk->labels, dst)->val;
259 bool cond = vm->regs[instruction.a].i;
190 if (cond) { 260 if (cond) {
191 vm->ip += offset - 1; 261 vm->ip = vm->chunk->code + pos;
192 } 262 }
193 } break; 263 } break;
194 case OP_MOV64: { 264 case OP_MOV64: {
@@ -211,10 +281,140 @@ vm_run(VM *vm) {
211 u8 src = instruction.a; 281 u8 src = instruction.a;
212 vm->regs[dst].i = vm->regs[src].i & 0xFF; 282 vm->regs[dst].i = vm->regs[src].i & 0xFF;
213 } break; 283 } break;
284 case OP_PRINTS64: {
285 u8 idx = instruction.dst;
286 print("%d", vm->regs[idx].i);
287 } break;
288 case OP_PRINTS64I: {
289 u8 idx = instruction.dst;
290 print("%d", vm->chunk->constants[idx].i);
291 } break;
292 case OP_PRINTBOOL: {
293 u8 idx = instruction.dst;
294 bool val = vm->regs[idx].i;
295 if (val) {
296 print("true");
297 } else {
298 print("false");
299 }
300 } break;
301 case OP_PRINTBOOLI: {
302 u8 idx = instruction.dst;
303 bool val = vm->chunk->constants[idx].i;
304 if (val) {
305 print("true");
306 } else {
307 print("false");
308 }
309 } break;
310 case OP_PRINTF64: {
311 u8 idx = instruction.dst;
312 printf("%f", vm->regs[idx].f);
313 } break;
314 case OP_PRINTF64I: {
315 u8 idx = instruction.dst;
316 printf("%f", vm->chunk->constants[idx].f);
317 } break;
318 case OP_PRINTSTR: {
319 u8 idx = instruction.dst;
320 Str *string = (Str *)vm->regs[idx].ptr;
321 print("%s", *string);
322 } break;
323 case OP_PRINTSTRI: {
324 u8 idx = instruction.dst;
325 Str string = vm->chunk->strings[idx];
326 print("%s", string);
327 } break;
328 case OP_RESERVE: {
329 sz offset = vm->chunk->constants[instruction.dst].i;
330 vm->sp += offset;
331 } break;
332 case OP_PUSH: {
333 sz val = vm->regs[instruction.dst].i;
334 u64 *p = (u64 *)vm->sp;
335 *p = val;
336 vm->sp += sizeof(ptrsize);
337 } break;
338 case OP_PUSHI: {
339 sz val = vm->chunk->constants[instruction.dst].i;
340 u64 *p = (u64 *)vm->sp;
341 *p = val;
342 vm->sp += sizeof(ptrsize);
343 } break;
344 case OP_POP: {
345 vm->sp -= sizeof(ptrsize);
346 u64 *p = (u64 *)vm->sp;
347 vm->regs[instruction.dst].i = *p;
348 } break;
349 case OP_PUTRET: {
350 sz val = vm->regs[instruction.dst].i;
351 vm->fp[-1] = val;
352 } break;
353 case OP_PUTRETI: {
354 sz val = vm->chunk->constants[instruction.dst].i;
355 vm->fp[-1] = val;
356 } break;
357 case OP_CALL: {
358 u8 dst = instruction.dst;
359 Chunk *func = vm->main->functions[dst];
360
361 ptrsize chunk_addr = (ptrsize)vm->chunk;
362 ptrsize ip_addr = (ptrsize)vm->ip;
363 ptrsize reg_addr = (ptrsize)vm->regs;
364 ptrsize old_fp = (ptrsize)vm->fp;
365
366 // Allocate space for the locals.
367 memset(vm->sp, 0, func->var_off - func->param_off);
368 vm->fp = (u64 *)(vm->sp - func->param_off);
369 vm->sp += func->var_off - func->param_off;
370 vm->chunk = func;
371 vm->ip = func->code;
372 vm->regs = (Constant *)vm->sp;
373
374 // Allocate registers.
375 vm->sp += sizeof(Constant) * func->reg_idx;
376
377 // Store memory addresses we need to return to this function.
378 u64 *p = (u64 *)vm->sp;
379 p[0] = chunk_addr;
380 p[1] = ip_addr;
381 p[2] = reg_addr;
382 p[3] = old_fp;
383 vm->sp += sizeof(ptrsize) * 4;
384 } break;
385 case OP_RECUR: {
386 vm->ip = vm->chunk->code;
387 } break;
388 case OP_RET: {
389 u64 *p = (u64 *)vm->sp;
390 ptrsize chunk_addr = p[-4];
391 ptrsize ip_addr = p[-3];
392 ptrsize reg_addr = p[-2];
393 ptrsize old_fp = p[-1];
394 vm->sp -= sizeof(ptrsize) * 4;
395
396 // Deallocate registers.
397 vm->sp -= sizeof(Constant) * vm->chunk->reg_idx;
398
399 // Deallocate locals.
400 vm->sp -= vm->chunk->var_off;
401
402 // Restore previous activation record.
403 vm->regs = (Constant *)reg_addr;
404 vm->ip = (Instruction *)ip_addr;
405 vm->chunk = (Chunk *)chunk_addr;
406 vm->fp = (u64 *)old_fp;
407 } break;
214 case OP_HALT: { 408 case OP_HALT: {
215 println("VM HALT (int) -> %d", vm->regs[instruction.dst]); 409 println("VM halt...");
216 println("VM HALT (float) -> %f", vm->regs[instruction.dst]); 410 if (instruction.a != 0) {
217 println("VM HALT (hex) -> %x", vm->regs[instruction.dst]); 411 println("Result:");
412 Constant result = vm->regs[instruction.dst];
413 printf("\tint -> %lld\n", result.i);
414 printf("\tfloat -> %.10e\n", result.f);
415 printf("\thex -> %llx\n", (u64)result.i);
416 println("\tbinary -> %b", result.i);
417 }
218 return; 418 return;
219 } 419 }
220 default: { 420 default: {
diff --git a/tests/compilation.bad b/tests/compilation.bad
index afb2be0..5c3b7b6 100644
--- a/tests/compilation.bad
+++ b/tests/compilation.bad
@@ -1,27 +1,42 @@
1; let a = 8 1fun recur(num: int): nil {
2; let b = 16 2 println("NUM: " num)
3; let c = { 3 if num == 0 return(nil)
4; let a = 32 4 recur2(num - 1)
5; a + 8 5}
6; }
7 6
8; a + b + c 7fun recur2(num: int): nil {
8 println("NUM: " num)
9 if num == 0 return(nil)
10 recur(num - 1)
11}
9 12
10; if true { 13recur(5)
11; 2
12; }
13 14
14; if true { 15fun infrecur(msg: str num: int): nil {
15; 1 + 2 16 println("NUM: " msg " " num)
16; } else { 17 infrecur(msg num + 1)
17; 3 + 4 18}
19infrecur(" -> " 8)
20
21
22; let varint: u16 = 0x0102030405060708
23; let varfloat: f32 = 1.0
24
25; fun printer(): nil println("wowo!")
26; let y = 4
27; fun nested(): nil {
28; fun adder(a: int b: int): int {
29; fun printer(): nil println("ho!")
30; printer()
31; printer()
32; printer()
33; y + a + b
34; }
35; for let i = 0, i < 2, set i += 1 {
36; println("i: " i " " adder(i, 2))
37; }
18; } 38; }
19 39
20let a = 0 40; nested()
21if 1 != 1 { 41; printer()
22 set a = 1
23} else {
24 set a = 2
25}
26 42
27a
diff --git a/tests/conditionals.bad b/tests/conditionals.bad
index aca5c36..85de62a 100644
--- a/tests/conditionals.bad
+++ b/tests/conditionals.bad
@@ -1,8 +1,8 @@
1; Basic if expressions. 1; Basic if expressions.
2if true "hello" 2if true "hello" else "world"
3 3
4; These can produce values and the result bound to a name. 4; These can produce values and the result bound to a name.
5let a = if (2 + 2 >= 4) 42 5let a = if (2 + 2 >= 4) 42 else 0
6 6
7; We support a single if expression. 7; We support a single if expression.
8let b = if (0xff == 0x32) "hello" else "world" 8let b = if (0xff == 0x32) "hello" else "world"
diff --git a/tests/semantics.bad b/tests/semantics.bad
index acf4316..befbfab 100644
--- a/tests/semantics.bad
+++ b/tests/semantics.bad
@@ -42,6 +42,7 @@ match a {
42cond { 42cond {
43 1 == 1 = "ha" 43 1 == 1 = "ha"
44 2 != 2 = "ho" 44 2 != 2 = "ho"
45 else = "let's go"
45} 46}
46 47
47struct vec { 48struct vec {
@@ -160,9 +161,7 @@ let maybe = if (1 == 2) {
160 44 161 44
161} 162}
162 163
163let single = if (true) { 164let single = if (true) 123 else 0
164 123
165}
166 165
167while (!true) { 166while (!true) {
168 println("asjdflasdjf") 167 println("asjdflasdjf")
@@ -185,5 +184,5 @@ fun nested(): int {
185 let c = 32 184 let c = 32
186 5 + c 185 5 + c
187 } 186 }
188 } 187 } else 0
189} 188}