aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bench/life.bad112
-rw-r--r--bench/rule110.bad34
-rw-r--r--bench/rule110.py12
-rw-r--r--src/compiler.c1741
-rw-r--r--src/lexer.c152
-rw-r--r--src/main.c121
-rw-r--r--src/parser.c500
-rw-r--r--src/semantic.c735
-rw-r--r--src/vm.c255
-rw-r--r--tests/compilation.bad187
-rw-r--r--tests/logic-shortcircuit.bad16
-rw-r--r--tests/nested.bad18
-rw-r--r--tests/pointers.bad36
-rw-r--r--tests/recursion.bad19
14 files changed, 2804 insertions, 1134 deletions
diff --git a/bench/life.bad b/bench/life.bad
index 3ca0697..eb5c99b 100644
--- a/bench/life.bad
+++ b/bench/life.bad
@@ -1,77 +1,71 @@
1; This board is 8 * 8 = 64 cells. 1; This board is 8 * 8 = 64 cells.
2; let n_cells = 64 2; let n_cells = 64
3; let board: int[64] 3; let board_a: int[64]
4; let new_board: int[64] 4; let board_b: int[64]
5; let stride = 8 5; let stride = 8
6 6
7; This board is 32 * 32 = 1024 cells. 7; This board is 32 * 32 = 1024 cells.
8let n_cells = 1024 8let n_cells = 1024
9let board: int[1024] 9let board_a: Int[1024]
10let new_board: int[1024] 10let board_b: Int[1024]
11let stride = 32 11let stride = 32
12 12
13; Storing pointers to the front/backbuffer to avoid copying the board over.
14let front = board_a
15let back = board_b
16
13; Initialize glider 17; Initialize glider
14set board[stride * 2 + 5] = 1 18set front[stride * 2 + 5] = 1
15set board[stride * 3 + 6] = 1 19set front[stride * 3 + 6] = 1
16set board[stride * 4 + 4] = 1 20set front[stride * 4 + 4] = 1
17set board[stride * 4 + 5] = 1 21set front[stride * 4 + 5] = 1
18set board[stride * 4 + 6] = 1 22set front[stride * 4 + 6] = 1
19 23
20let n_iter = 1000 24fun print_board(board: @Int) {
21while n_iter > 0 { 25 for let i = 0 , i < n_cells , set i += 1 {
22 set n_iter = n_iter - 1 26 if i % stride == 0 {
23 ; Print the board. 27 println("")
24 {
25 let i = 0
26 while i < n_cells {
27 if i % stride == 0 {
28 println("")
29 }
30 if board[i] == 1 print("â–  ")
31 else print("· ")
32 set i = i + 1
33 } 28 }
34 println("") 29 if board[i] == 1 print("â–  ")
30 else print("· ")
35 } 31 }
32 println("")
33}
36 34
37 ; Update the board. 35fun update_board() {
38 { 36 for let i = 0 , i < n_cells , set i += 1 {
39 let i = 0 37 let left = if i > 0 front[i - 1] else 0
40 while i < n_cells { 38 let right = if i < n_cells - 1 front[i + 1] else 0
41 let left = if i > 0 board[i - 1] else 0 39 let top = if i >= stride front[i - stride] else 0
42 let right = if i < n_cells - 1 board[i + 1] else 0 40 let topleft = if i >= stride front[i - stride - 1] else 0
43 let top = if i >= stride board[i - stride] else 0 41 let topright = if i >= stride front[i - stride + 1] else 0
44 let topleft = if i >= stride board[i - stride - 1] else 0 42 let bot = if i <= n_cells - stride front[i + stride] else 0
45 let topright = if i >= stride board[i - stride + 1] else 0 43 let botleft = if i <= n_cells - stride front[i + stride - 1] else 0
46 let bot = if i <= n_cells - stride board[i + stride] else 0 44 let botright = if i <= n_cells - stride front[i + stride + 1] else 0
47 let botleft = if i <= n_cells - stride board[i + stride - 1] else 0
48 let botright = if i <= n_cells - stride board[i + stride + 1] else 0
49
50 let neig = left
51 + right
52 + top
53 + bot
54 + topleft
55 + topright
56 + botleft
57 + botright
58
59 cond {
60 board[i] == 0 && neig == 3 = set new_board[i] = 1
61 board[i] == 1 && (neig == 2 || neig == 3) = set new_board[i] = 1
62 else = set new_board[i] = 0
63 }
64 45
65 set i = i + 1 46 let neig = left
66 } 47 + right
48 + top
49 + bot
50 + topleft
51 + topright
52 + botleft
53 + botright
67 54
68 ; Copy the new board. 55 cond {
69 { 56 front[i] == 0 and neig == 3 = set back[i] = 1
70 let i = 0 57 front[i] == 1 and (neig == 2 or neig == 3) = set back[i] = 1
71 while i < n_cells { 58 else = set back[i] = 0
72 set board[i] = new_board[i]
73 set i = i + 1
74 }
75 } 59 }
76 } 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()
77} 71}
diff --git a/bench/rule110.bad b/bench/rule110.bad
index 14aa00e..9db0da5 100644
--- a/bench/rule110.bad
+++ b/bench/rule110.bad
@@ -1,26 +1,24 @@
1; Parameters. 1; Parameters.
2let line = 0b00000000000000000000000000000001 2let line = 0b00000000000000000000000000000001
3let max_iter = 30000 3let max_iter = 30
4 4
5let iter = 0 5; Print current line.
6while iter < max_iter { 6fun print_line(line: Int) {
7 ; Print current line. 7 for let i = 0 , i < 64 , set i += 1 {
8 let i = 0 8 let val = line >> 63 - i & 0b1
9 while i < 64 {
10 let val = line >> (63 - i) & 0b1
11 if val == 0b1 { 9 if val == 0b1 {
12 print("â– ") 10 print("â–  ")
13 } else { 11 } else {
14 print(" ") 12 print("· ")
15 } 13 }
16 set i = i + 1
17 } 14 }
18 println("") 15 println("")
16}
19 17
20 ; Update next line 18; Get the next line.
19fun next_line(line: Int): Int {
21 let next = 0 20 let next = 0
22 let j = 0 21 for let j = 0 , j < 61 , set j += 1 {
23 while j < 61 {
24 let val = line >> 60 - j & 0b111 22 let val = line >> 60 - j & 0b111
25 set val = cond { 23 set val = cond {
26 val == 1 = 1 24 val == 1 = 1
@@ -30,10 +28,12 @@ while iter < max_iter {
30 val == 6 = 1 28 val == 6 = 1
31 else = 0 29 else = 0
32 } 30 }
33 set next = next | val << 61 - j 31 set next |= val << 61 - j
34 set j = j + 1
35 } 32 }
36 set line = next | 1 33 next | 1
34}
37 35
38 set iter = iter + 1 36for let iter = 0 , iter < max_iter , set iter += 1 {
37 print_line(line)
38 set line = next_line(line)
39} 39}
diff --git a/bench/rule110.py b/bench/rule110.py
index a4fed06..eddcdbe 100644
--- a/bench/rule110.py
+++ b/bench/rule110.py
@@ -1,18 +1,18 @@
1line = 0b00000000000000000000000000000001 1line = 0b00000000000000000000000000000001
2max_iter = 30000 2max_iter = 30
3 3
4for iter in range(0, max_iter): 4for iter in range(0, max_iter):
5 for i in range(0, 64): 5 for i in range(0, 64):
6 val = line >> (63 - i) & 0b1 6 val = line >> 63 - i & 0b1
7 if val == 0b1: 7 if val == 0b1:
8 print("â–", end=" ") 8 print("â– ", end=" ")
9 else: 9 else:
10 print(".", end=" ") 10 print("·", end=" ")
11 print("") 11 print("")
12 12
13 next = 0 13 next = 0
14 for j in range(0, 61): 14 for j in range(0, 61):
15 val = (line >> (61 - j - 1)) & 0b111 15 val = line >> 60 - j & 0b111
16 if val == 1: 16 if val == 1:
17 val = 1 17 val = 1
18 elif val == 2: 18 elif val == 2:
@@ -25,5 +25,5 @@ for iter in range(0, max_iter):
25 val = 1 25 val = 1
26 else: 26 else:
27 val = 0 27 val = 0
28 next = next | (val << (61 - j)) 28 next = next | val << 61 - j
29 line = next | 1 29 line = next | 1
diff --git a/src/compiler.c b/src/compiler.c
index 9b6a458..8745f6e 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -5,21 +5,58 @@
5 5
6#include "parser.c" 6#include "parser.c"
7 7
8typedef struct Type {
9 Str name;
10 Str unique_name;
11 // Size of the type in bytes or 0 if it's target dependant.
12 sz size;
13} Type;
14
8typedef struct Variable { 15typedef struct Variable {
9 Str name; 16 Str name;
10 Str type; 17 Str type_name;
11 sz size; 18 sz size;
12 sz offset; 19 sz offset;
13 sz idx; 20 sz idx;
21 Type type;
14} Variable; 22} Variable;
15 23
24#define WORD_SIZE 8
25
26Type builtin_types[] = {
27 // Nil.
28 {cstr("nil"), cstr("nil"), 0},
29
30 // Architecture dependant.
31 {cstr("Int"), cstr("Int"), 8},
32 {cstr("UInt"), cstr("UInt"), 8},
33 {cstr("Ptr"), cstr("Ptr"), 8},
34 {cstr("Str"), cstr("Str"), 16},
35
36 // Fixed integer types.
37 {cstr("Bool"), cstr("Bool"), 1},
38 {cstr("U8"), cstr("U8"), 1},
39 {cstr("S8"), cstr("S8"), 1},
40 {cstr("U16"), cstr("U16"), 2},
41 {cstr("S16"), cstr("S16"), 2},
42 {cstr("U32"), cstr("U32"), 4},
43 {cstr("S32"), cstr("S32"), 4},
44 {cstr("U64"), cstr("U64"), 8},
45 {cstr("S64"), cstr("S64"), 8},
46
47 // Fixed float types.
48 {cstr("F32"), cstr("F32"), 4},
49 {cstr("F64"), cstr("F64"), 8},
50};
51
16MAPDEF(StrVarMap, varmap, Str, Variable, str_hash, str_eq) 52MAPDEF(StrVarMap, varmap, Str, Variable, str_hash, str_eq)
53MAPDEF(StrTypeMap, strtype, Str, Type, str_hash, str_eq)
17 54
18typedef struct Instruction { 55typedef struct Instruction {
19 u8 dst; 56 u16 dst;
20 u8 a; 57 u16 a;
21 u8 b; 58 u16 b;
22 u8 op; 59 u16 op;
23} Instruction; 60} Instruction;
24 61
25typedef union Constant { 62typedef union Constant {
@@ -49,8 +86,7 @@ typedef struct Chunk {
49 struct Chunk *parent; 86 struct Chunk *parent;
50 87
51 Instruction *code; 88 Instruction *code;
52 IntIntMap *labels; // label -> chunk_index 89 IntIntMap *labels; // label -> chunk_index
53 IntIntMap *labels_rev; // chunk_index -> label
54 sz labels_idx; 90 sz labels_idx;
55 91
56 // Constant values that fit in 64 bits. 92 // Constant values that fit in 64 bits.
@@ -67,6 +103,7 @@ typedef struct Chunk {
67 Variable *vars; 103 Variable *vars;
68 StrVarMap *varmap; 104 StrVarMap *varmap;
69 sz var_off; 105 sz var_off;
106 sz param_off;
70 107
71 // Number of registers currently used in this chunk. 108 // Number of registers currently used in this chunk.
72 sz reg_idx; 109 sz reg_idx;
@@ -82,6 +119,24 @@ typedef struct Chunk {
82 LineCol *linecol; 119 LineCol *linecol;
83} Chunk; 120} Chunk;
84 121
122typedef struct Compiler {
123 Chunk main_chunk;
124 Str file_name;
125 Arena *storage;
126
127 // Tables.
128 StrSet *integer_types;
129 StrSet *signed_ints;
130 StrSet *unsigned_ints;
131 StrSet *float_types;
132 StrSet *numeric_types;
133 StrTypeMap *type_map;
134
135 // Destinations.
136 sz lab_pre;
137 sz lab_post;
138} Compiler;
139
85typedef enum OpCode { 140typedef enum OpCode {
86 // OP DST A B 141 // OP DST A B
87 // --------------------------------------------------------------- 142 // ---------------------------------------------------------------
@@ -92,8 +147,14 @@ typedef enum OpCode {
92 OP_STGVAR, // stgvar vx, ra 147 OP_STGVAR, // stgvar vx, ra
93 OP_LDGVAR, // ldgvar rx, va 148 OP_LDGVAR, // ldgvar rx, va
94 OP_LDGADDR, // ldgaddr rx, va 149 OP_LDGADDR, // ldgaddr rx, va
150 OP_STLVARI, // stlvari vx, ca
151 OP_STLVAR, // stlvar vx, ra
152 OP_LDLVAR, // ldlvar rx, va
153 OP_LDLADDR, // ldladdr rx, va
154 OP_LDSTR, // ldstr rx, sa ; Stores the address of the string sa into rx
95 // Functions. 155 // Functions.
96 OP_CALL, // call fx ; Bumps the stack pointer by cx 156 OP_CALL, // call fx ; Call the function fx
157 OP_RECUR, // recur ; Jump to the beginning of the function.
97 OP_RET, // ret ; Returns from current function 158 OP_RET, // ret ; Returns from current function
98 OP_RESERVE, // reserve cx ; Increments the stack pointer by cx bytes 159 OP_RESERVE, // reserve cx ; Increments the stack pointer by cx bytes
99 OP_POP, // pop rx ; Pops the last value of the stack into rx. 160 OP_POP, // pop rx ; Pops the last value of the stack into rx.
@@ -102,32 +163,56 @@ typedef enum OpCode {
102 OP_PUTRET, // putret rx ; Put rx into the return value memory. 163 OP_PUTRET, // putret rx ; Put rx into the return value memory.
103 OP_PUTRETI, // putreti cx ; Put cx into the return value memory. 164 OP_PUTRETI, // putreti cx ; Put cx into the return value memory.
104 // Printing values with builtin print/println functions. 165 // Printing values with builtin print/println functions.
105 OP_PRINTSTR, // p rx 166 OP_PRINTSTR, // p rx
106 OP_PRINTS64, // p rx 167 OP_PRINTSTRI, // p cx
107 OP_PRINTF64, // p rx 168 OP_PRINTS8, // p rx
108 OP_PRINTS64I, // p cx 169 OP_PRINTS8I, // p cx
109 OP_PRINTF64I, // p cx 170 OP_PRINTS16, // p rx
171 OP_PRINTS16I, // p cx
172 OP_PRINTS32, // p rx
173 OP_PRINTS32I, // p cx
174 OP_PRINTS64, // p rx
175 OP_PRINTS64I, // p cx
176 OP_PRINTU8, // p rx
177 OP_PRINTU8I, // p cx
178 OP_PRINTU16, // p rx
179 OP_PRINTU16I, // p cx
180 OP_PRINTU32, // p rx
181 OP_PRINTU32I, // p cx
182 OP_PRINTU64, // p rx
183 OP_PRINTU64I, // p cx
184 OP_PRINTF64, // p rx
185 OP_PRINTF64I, // p cx
186 OP_PRINTF32, // p cx
187 OP_PRINTF32I, // p cx
188 OP_PRINTBOOL, // p rx
189 OP_PRINTBOOLI, // p cx
110 // Load/Store instructions. 190 // Load/Store instructions.
111 OP_LD8K, // ld8k rx, ca -> u8 rx = ca 191 OP_LDCONST, // ldconst rx, ca -> u64 rx = ca
112 OP_LD16K, // ld16k rx, ca -> u16 rx = ca 192 OP_LD8K, // ld8k rx, ra -> u8 *p = ra; rx = *p
113 OP_LD32K, // ld32k rx, ca -> u32 rx = ca 193 OP_LD16K, // ld16k rx, ra -> u16 *p = ra; rx = *p
114 OP_LD64K, // ld64k rx, ca -> u64 rx = ca 194 OP_LD32K, // ld32k rx, ra -> u32 *p = ra; rx = *p
115 OP_LD8I, // ld8i rx, ra, cb -> u8 *p = ra; rx = p[cb] 195 OP_LD64K, // ld64k rx, ra -> u64 *p = ra; rx = *p
116 OP_LD16I, // ld16i rx, ra, cb -> u16 *p = ra; rx = p[cb] 196 OP_ST8K, // ld8k rx, ra -> u8 *p = ra; *p = rx
117 OP_LD32I, // ld32i rx, ra, cb -> u32 *p = ra; rx = p[cb] 197 OP_ST16K, // ld16k rx, ra -> u16 *p = ra; *p = rx
118 OP_LD64I, // ld64i rx, ra, cb -> u64 *p = ra; rx = p[cb] 198 OP_ST32K, // ld32k rx, ra -> u32 *p = ra; *p = rx
119 OP_LD8, // ld8 rx, ra, rb -> u8 *p = ra; rx = p[rb] 199 OP_ST64K, // ld64k rx, ra -> u64 *p = ra; *p = rx
120 OP_LD16, // ld16 rx, ra, rb -> u16 *p = ra; rx = p[rb] 200 OP_LD8I, // ld8i rx, ra, cb -> u8 *p = ra; rx = p[cb]
121 OP_LD32, // ld32 rx, ra, rb -> u32 *p = ra; rx = p[rb] 201 OP_LD16I, // ld16i rx, ra, cb -> u16 *p = ra; rx = p[cb]
122 OP_LD64, // ld64 rx, ra, rb -> u64 *p = ra; rx = p[rb] 202 OP_LD32I, // ld32i rx, ra, cb -> u32 *p = ra; rx = p[cb]
123 OP_ST8I, // st8i rx, ra, cb -> u8 *p = ra; p[cb] = rx 203 OP_LD64I, // ld64i rx, ra, cb -> u64 *p = ra; rx = p[cb]
124 OP_ST16I, // st16i rx, ra, cb -> u16 *p = ra; p[cb] = rx 204 OP_LD8, // ld8 rx, ra, rb -> u8 *p = ra; rx = p[rb]
125 OP_ST32I, // st32i rx, ra, cb -> u32 *p = ra; p[cb] = rx 205 OP_LD16, // ld16 rx, ra, rb -> u16 *p = ra; rx = p[rb]
126 OP_ST64I, // st64i rx, ra, cb -> u64 *p = ra; p[cb] = rx 206 OP_LD32, // ld32 rx, ra, rb -> u32 *p = ra; rx = p[rb]
127 OP_ST8, // st8 rx, ra, rb -> u8 *p = ra; p[rb] = rx 207 OP_LD64, // ld64 rx, ra, rb -> u64 *p = ra; rx = p[rb]
128 OP_ST16, // st16 rx, ra, rb -> u16 *p = ra; p[rb] = rx 208 OP_ST8I, // st8i rx, ra, cb -> u8 *p = ra; p[cb] = rx
129 OP_ST32, // st32 rx, ra, rb -> u32 *p = ra; p[rb] = rx 209 OP_ST16I, // st16i rx, ra, cb -> u16 *p = ra; p[cb] = rx
130 OP_ST64, // st64 rx, ra, rb -> u64 *p = ra; p[rb] = rx 210 OP_ST32I, // st32i rx, ra, cb -> u32 *p = ra; p[cb] = rx
211 OP_ST64I, // st64i rx, ra, cb -> u64 *p = ra; p[cb] = rx
212 OP_ST8, // st8 rx, ra, rb -> u8 *p = ra; p[rb] = rx
213 OP_ST16, // st16 rx, ra, rb -> u16 *p = ra; p[rb] = rx
214 OP_ST32, // st32 rx, ra, rb -> u32 *p = ra; p[rb] = rx
215 OP_ST64, // st64 rx, ra, rb -> u64 *p = ra; p[rb] = rx
131 // Integer arithmetic (only int/s64 for now). 216 // Integer arithmetic (only int/s64 for now).
132 OP_ADDI, // addk rx, ra, cb 217 OP_ADDI, // addk rx, ra, cb
133 OP_SUBI, // subk rx, ra, cb 218 OP_SUBI, // subk rx, ra, cb
@@ -179,11 +264,13 @@ typedef enum OpCode {
179 OP_BITRSHIFTI, // shri rx, ra, cb 264 OP_BITRSHIFTI, // shri rx, ra, cb
180 OP_BITANDI, // bandi rx, ra, cb 265 OP_BITANDI, // bandi rx, ra, cb
181 OP_BITORI, // bori rx, ra, cb 266 OP_BITORI, // bori rx, ra, cb
267 OP_BITXORI, // bxor rx, ra, cb
182 OP_BITNOTI, // bnoti rx, ca 268 OP_BITNOTI, // bnoti rx, ca
183 OP_BITLSHIFT, // shl rx, ra, rb 269 OP_BITLSHIFT, // shl rx, ra, rb
184 OP_BITRSHIFT, // shr rx, ra, rb 270 OP_BITRSHIFT, // shr rx, ra, rb
185 OP_BITAND, // band rx, ra, rb 271 OP_BITAND, // band rx, ra, rb
186 OP_BITOR, // bor rx, ra, rb 272 OP_BITOR, // bor rx, ra, rb
273 OP_BITXOR, // bxor rx, ra, rb
187 OP_BITNOT, // bnot rx, ra 274 OP_BITNOT, // bnot rx, ra
188 // Jump instructions. 275 // Jump instructions.
189 OP_JMP, // jmp lx ; jmp to label lx 276 OP_JMP, // jmp lx ; jmp to label lx
@@ -191,6 +278,7 @@ typedef enum OpCode {
191 OP_JMPT, // jmpt lx, rx ; jmp to label lx if rx is true 278 OP_JMPT, // jmpt lx, rx ; jmp to label lx if rx is true
192 OP_JMPFI, // jmpf lx, cx ; jmp to label lx if rx is false 279 OP_JMPFI, // jmpf lx, cx ; jmp to label lx if rx is false
193 OP_JMPTI, // jmpt lx, cx ; jmp to label lx if rx is true 280 OP_JMPTI, // jmpt lx, cx ; jmp to label lx if rx is true
281 _OP_NUM,
194} OpCode; 282} OpCode;
195 283
196Str op_str[] = { 284Str op_str[] = {
@@ -200,25 +288,55 @@ Str op_str[] = {
200 [OP_STGVARI] = cstr("STGVARI "), 288 [OP_STGVARI] = cstr("STGVARI "),
201 [OP_LDGVAR] = cstr("LDGVAR "), 289 [OP_LDGVAR] = cstr("LDGVAR "),
202 [OP_LDGADDR] = cstr("LDGADDR "), 290 [OP_LDGADDR] = cstr("LDGADDR "),
203 [OP_PRINTSTR] = cstr("PRNTSTR "), 291 [OP_STLVAR] = cstr("STLVAR "),
204 [OP_PRINTS64] = cstr("PRNTS64 "), 292 [OP_STLVARI] = cstr("STLVARI "),
205 [OP_PRINTF64] = cstr("PRNTF64 "), 293 [OP_LDLVAR] = cstr("LDLVAR "),
206 [OP_PRINTS64I] = cstr("PRNTS64I"), 294 [OP_LDLADDR] = cstr("LDLADDR "),
207 [OP_PRINTF64I] = cstr("PRNTF64I"), 295 [OP_LDSTR] = cstr("LDSTR "),
296 [OP_PRINTSTR] = cstr("PRNSTR "),
297 [OP_PRINTSTRI] = cstr("PRNSTRI "),
298 [OP_PRINTS8] = cstr("PRNS8 "),
299 [OP_PRINTS8I] = cstr("PRNS8I "),
300 [OP_PRINTS16] = cstr("PRNS16 "),
301 [OP_PRINTS16I] = cstr("PRNS16I "),
302 [OP_PRINTS32] = cstr("PRNS32 "),
303 [OP_PRINTS32I] = cstr("PRNS32I "),
304 [OP_PRINTS64] = cstr("PRNS64 "),
305 [OP_PRINTS64I] = cstr("PRNS64I "),
306 [OP_PRINTU8] = cstr("PRNU8 "),
307 [OP_PRINTU8I] = cstr("PRNU8I "),
308 [OP_PRINTU16] = cstr("PRNU16 "),
309 [OP_PRINTU16I] = cstr("PRNU16I "),
310 [OP_PRINTU32] = cstr("PRNU32 "),
311 [OP_PRINTU32I] = cstr("PRNU32I "),
312 [OP_PRINTU64] = cstr("PRNU64 "),
313 [OP_PRINTU64I] = cstr("PRNU64I "),
314 [OP_PRINTF32] = cstr("PRNF32 "),
315 [OP_PRINTF32I] = cstr("PRNF32I "),
316 [OP_PRINTF64] = cstr("PRNF64 "),
317 [OP_PRINTF64I] = cstr("PRNF64I "),
318 [OP_PRINTBOOL] = cstr("PRNBOOL "),
319 [OP_PRINTBOOLI] = cstr("PRNBOOLI"),
208 [OP_PUTRET] = cstr("PUTRET "), 320 [OP_PUTRET] = cstr("PUTRET "),
209 [OP_PUTRETI] = cstr("PUTRETI "), 321 [OP_PUTRETI] = cstr("PUTRETI "),
210 // Functions. 322 // Functions.
211 [OP_CALL] = cstr("CALL "), 323 [OP_CALL] = cstr("CALL "),
324 [OP_RECUR] = cstr("RECUR "),
212 [OP_RET] = cstr("RET "), 325 [OP_RET] = cstr("RET "),
213 [OP_RESERVE] = cstr("RESERVE "), 326 [OP_RESERVE] = cstr("RESERVE "),
214 [OP_POP] = cstr("POP "), 327 [OP_POP] = cstr("POP "),
215 [OP_PUSH] = cstr("PUSH "), 328 [OP_PUSH] = cstr("PUSH "),
216 [OP_PUSHI] = cstr("PUSHI "), 329 [OP_PUSHI] = cstr("PUSHI "),
217 // Load ops. 330 // Load ops.
331 [OP_LDCONST] = cstr("LDCONST "),
218 [OP_LD8K] = cstr("LD8K "), 332 [OP_LD8K] = cstr("LD8K "),
219 [OP_LD16K] = cstr("LD16K "), 333 [OP_LD16K] = cstr("LD16K "),
220 [OP_LD32K] = cstr("LD32K "), 334 [OP_LD32K] = cstr("LD32K "),
221 [OP_LD64K] = cstr("LD64K "), 335 [OP_LD64K] = cstr("LD64K "),
336 [OP_ST8K] = cstr("ST8K "),
337 [OP_ST16K] = cstr("ST6K "),
338 [OP_ST32K] = cstr("ST32K "),
339 [OP_ST64K] = cstr("ST64K "),
222 [OP_LD8I] = cstr("LD8I "), 340 [OP_LD8I] = cstr("LD8I "),
223 [OP_LD16I] = cstr("LD16I "), 341 [OP_LD16I] = cstr("LD16I "),
224 [OP_LD32I] = cstr("LD32I "), 342 [OP_LD32I] = cstr("LD32I "),
@@ -286,11 +404,13 @@ Str op_str[] = {
286 [OP_BITRSHIFTI] = cstr("RSHI "), 404 [OP_BITRSHIFTI] = cstr("RSHI "),
287 [OP_BITANDI] = cstr("BANDI "), 405 [OP_BITANDI] = cstr("BANDI "),
288 [OP_BITORI] = cstr("BORI "), 406 [OP_BITORI] = cstr("BORI "),
407 [OP_BITXORI] = cstr("BXORI "),
289 [OP_BITNOTI] = cstr("BNOTI "), 408 [OP_BITNOTI] = cstr("BNOTI "),
290 [OP_BITLSHIFT] = cstr("LSH "), 409 [OP_BITLSHIFT] = cstr("LSH "),
291 [OP_BITRSHIFT] = cstr("RSH "), 410 [OP_BITRSHIFT] = cstr("RSH "),
292 [OP_BITAND] = cstr("BAND "), 411 [OP_BITAND] = cstr("BAND "),
293 [OP_BITOR] = cstr("BOR "), 412 [OP_BITOR] = cstr("BOR "),
413 [OP_BITXOR] = cstr("XBOR "),
294 [OP_BITNOT] = cstr("BNOT "), 414 [OP_BITNOT] = cstr("BNOT "),
295 // Jump instructions. 415 // Jump instructions.
296 [OP_JMP] = cstr("JMP "), 416 [OP_JMP] = cstr("JMP "),
@@ -305,6 +425,7 @@ typedef enum {
305 COMP_CONST, 425 COMP_CONST,
306 COMP_STRING, 426 COMP_STRING,
307 COMP_REG, 427 COMP_REG,
428 COMP_RET,
308 COMP_ERR, 429 COMP_ERR,
309} CompResultType; 430} CompResultType;
310 431
@@ -313,73 +434,191 @@ typedef struct CompResult {
313 CompResultType type; 434 CompResultType type;
314} CompResult; 435} CompResult;
315 436
316CompResult compile_expr(Chunk *chunk, Node *node); 437CompResult compile_expr(Compiler *compiler, Chunk *chunk, Node *node);
317 438
318#define EMIT_OP(OP, DST, A, B, NODE, CHUNK) \ 439sz
319 do { \ 440add_constant(Chunk *chunk, sz value) {
320 Instruction inst = (Instruction){ \ 441 IntIntMap *map = intintmap_lookup(&chunk->intmap, value);
321 .op = (OP), \ 442 // Make sure we don't have duplicated constants.
322 .dst = (DST), \ 443 if (!map) {
323 .a = (A), \ 444 map = intintmap_insert(&chunk->intmap, value, chunk->const_idx++,
324 .b = (B), \ 445 chunk->storage);
325 }; \ 446 Constant c = (Constant){.i = value};
326 array_push((CHUNK)->code, inst, (CHUNK)->storage); \ 447 array_push(chunk->constants, c, chunk->storage);
327 LineCol linecol = (LineCol){0}; \ 448 }
328 if (NODE) { \ 449 return map->val;
329 Node *_node = (NODE); \ 450}
330 linecol = (LineCol){.line = _node->line, .col = _node->col}; \ 451
331 } \ 452sz
332 array_push((CHUNK)->linecol, linecol, (CHUNK)->storage); \ 453add_string(Chunk *chunk, Str string) {
333 } while (0) 454 // Make sure we don't have duplicated string.
455 StrIntMap *map = strintmap_lookup(&chunk->strmap, string);
456 if (!map) {
457 map = strintmap_insert(&chunk->strmap, string, chunk->str_idx++,
458 chunk->storage);
459 array_push(chunk->strings, string, chunk->storage);
460 }
461 return map->val;
462}
463
464sz
465add_variable(Compiler *compiler,
466 Chunk *chunk,
467 Str name,
468 Str type_name,
469 sz arr_size) {
470 sz idx = array_size(chunk->vars);
471 Str base_type = type_name;
472 if (str_has_prefix(base_type, cstr("@"))) {
473 // FIXME: this doesn't seem like the right way of handling pointer and
474 // array types.
475 base_type = str_remove_prefix(base_type, cstr("@"));
476 if (str_has_prefix(base_type, cstr("@"))) {
477 base_type = cstr("Ptr");
478 }
479 }
480 StrTypeMap *t = strtype_lookup(&compiler->type_map, base_type);
481 sz size = t->val.size;
482 // An array.
483 if (arr_size) {
484 size *= arr_size;
485 // FIXME: this should be done on the static analysis, plus,
486 // we shouldn't be checking all these types by hand, but
487 // using the symbol tables.
488 type_name = str_remove_prefix(type_name, cstr("@"));
489 type_name = str_concat(cstr("[]"), type_name, chunk->storage);
490 } else if (str_has_prefix(type_name, cstr("@"))) {
491 t = strtype_lookup(&compiler->type_map, cstr("Ptr"));
492 size = t->val.size;
493 }
494 sz padding = -size & (WORD_SIZE - 1);
495 size += padding;
496 Variable var = (Variable){
497 .name = name,
498 .type = t->val,
499 .type_name = type_name,
500 .size = size,
501 .offset = chunk->var_off,
502 .idx = idx,
503 };
504 varmap_insert(&chunk->varmap, name, var, chunk->storage);
505 array_push(chunk->vars, var, chunk->storage);
506 chunk->var_off += size;
507 return idx;
508}
509
510void
511emit_op(OpCode op, sz dst, sz a, sz b, Node *node, Chunk *chunk) {
512 Instruction inst = (Instruction){
513 .op = op,
514 .dst = dst,
515 .a = a,
516 .b = b,
517 };
518 array_push(chunk->code, inst, chunk->storage);
519 LineCol linecol = (LineCol){0};
520 if (node) {
521 linecol = (LineCol){.line = node->line, .col = node->col};
522 }
523 array_push(chunk->linecol, linecol, chunk->storage);
524}
525
526void
527emit_sized_op(sz size,
528 OpCode op64,
529 OpCode op32,
530 OpCode op16,
531 OpCode op8,
532 sz dst,
533 sz a,
534 sz b,
535 Node *node,
536 Chunk *chunk) {
537 if (size == 8) {
538 emit_op(op64, dst, a, b, node, chunk);
539 } else if (size == 4) {
540 emit_op(op32, dst, a, b, node, chunk);
541 } else if (size == 2) {
542 emit_op(op16, dst, a, b, node, chunk);
543 } else if (size == 1) {
544 emit_op(op8, dst, a, b, node, chunk);
545 }
546}
547
548void
549emit_fat_copy(Chunk *chunk, Node *node, sz dst_addr, sz src_addr) {
550 sz reg_dst = chunk->reg_idx++;
551
552 // Store the fat string pointer into the variable.
553 sz zero = add_constant(chunk, 0);
554 sz one = add_constant(chunk, 1);
555
556 // Get the value for the first word of the string
557 // pointer.
558 emit_op(OP_LD64I, reg_dst, src_addr, zero, node, chunk);
559 emit_op(OP_ST64I, reg_dst, dst_addr, zero, node, chunk);
560 emit_op(OP_LD64I, reg_dst, src_addr, one, node, chunk);
561 emit_op(OP_ST64I, reg_dst, dst_addr, one, node, chunk);
562}
563
564void disassemble_chunk(Chunk chunk);
565
566void
567emit_compile_err(Compiler *compiler, Chunk *chunk, Node *node) {
568 disassemble_chunk(*chunk);
569 eprintln("%s:%d:%d: error: compilation error on: %s", compiler->file_name,
570 node->line, node->col, node_str[node->kind]);
571 exit(EXIT_FAILURE);
572}
334 573
335CompResult 574CompResult
336compile_binary(Chunk *chunk, Node *node) { 575compile_binary(Compiler *compiler, Chunk *chunk, Node *node) {
337 OpCode op = OP_HALT; 576 OpCode op = OP_HALT;
338 OpCode opi = OP_HALT; 577 OpCode opi = OP_HALT;
339 OpCode ldop = OP_LD64K; 578 OpCode ldop = OP_LDCONST;
340 switch (node->kind) { 579 switch (node->kind) {
341 // Arithmetic. 580 // Arithmetic.
342 case NODE_ADD: { 581 case NODE_ADD: {
343 if (str_eq(node->type, cstr("int"))) { 582 if (strset_lookup(&compiler->integer_types, node->type)) {
344 op = OP_ADD; 583 op = OP_ADD;
345 opi = OP_ADDI; 584 opi = OP_ADDI;
346 } else if (str_eq(node->type, cstr("f64"))) { 585 } else if (strset_lookup(&compiler->float_types, node->type)) {
347 op = OP_ADDF; 586 op = OP_ADDF;
348 opi = OP_ADDFI; 587 opi = OP_ADDFI;
349 } 588 }
350 } break; 589 } break;
351 case NODE_SUB: { 590 case NODE_SUB: {
352 if (str_eq(node->type, cstr("int"))) { 591 if (strset_lookup(&compiler->integer_types, node->type)) {
353 op = OP_SUB; 592 op = OP_SUB;
354 opi = OP_SUBI; 593 opi = OP_SUBI;
355 } else if (str_eq(node->type, cstr("f64"))) { 594 } else if (strset_lookup(&compiler->float_types, node->type)) {
356 op = OP_SUBF; 595 op = OP_SUBF;
357 opi = OP_SUBFI; 596 opi = OP_SUBFI;
358 } 597 }
359 } break; 598 } break;
360 case NODE_MUL: { 599 case NODE_MUL: {
361 if (str_eq(node->type, cstr("int"))) { 600 if (strset_lookup(&compiler->integer_types, node->type)) {
362 op = OP_MUL; 601 op = OP_MUL;
363 opi = OP_MULI; 602 opi = OP_MULI;
364 } else if (str_eq(node->type, cstr("f64"))) { 603 } else if (strset_lookup(&compiler->float_types, node->type)) {
365 op = OP_MULF; 604 op = OP_MULF;
366 opi = OP_MULFI; 605 opi = OP_MULFI;
367 } 606 }
368 } break; 607 } break;
369 case NODE_DIV: { 608 case NODE_DIV: {
370 if (str_eq(node->type, cstr("int"))) { 609 if (strset_lookup(&compiler->integer_types, node->type)) {
371 op = OP_DIV; 610 op = OP_DIV;
372 opi = OP_DIVI; 611 opi = OP_DIVI;
373 } else if (str_eq(node->type, cstr("f64"))) { 612 } else if (strset_lookup(&compiler->float_types, node->type)) {
374 op = OP_DIVF; 613 op = OP_DIVF;
375 opi = OP_DIVFI; 614 opi = OP_DIVFI;
376 } 615 }
377 } break; 616 } break;
378 case NODE_MOD: { 617 case NODE_MOD: {
379 if (str_eq(node->type, cstr("int"))) { 618 if (strset_lookup(&compiler->integer_types, node->type)) {
380 op = OP_MOD; 619 op = OP_MOD;
381 opi = OP_MODI; 620 opi = OP_MODI;
382 } else if (str_eq(node->type, cstr("f64"))) { 621 } else if (strset_lookup(&compiler->float_types, node->type)) {
383 op = OP_MODF; 622 op = OP_MODF;
384 opi = OP_MODFI; 623 opi = OP_MODFI;
385 } 624 }
@@ -409,19 +648,15 @@ compile_binary(Chunk *chunk, Node *node) {
409 op = OP_GE; 648 op = OP_GE;
410 opi = OP_GEI; 649 opi = OP_GEI;
411 } break; 650 } break;
412 case NODE_AND: {
413 op = OP_AND;
414 opi = OP_ANDI;
415 } break;
416 case NODE_OR: {
417 op = OP_OR;
418 opi = OP_ORI;
419 } break;
420 // Bitwise. 651 // Bitwise.
421 case NODE_BITOR: { 652 case NODE_BITOR: {
422 op = OP_BITOR; 653 op = OP_BITOR;
423 opi = OP_BITORI; 654 opi = OP_BITORI;
424 } break; 655 } break;
656 case NODE_BITXOR: {
657 op = OP_BITXOR;
658 opi = OP_BITXORI;
659 } break;
425 case NODE_BITAND: { 660 case NODE_BITAND: {
426 op = OP_BITAND; 661 op = OP_BITAND;
427 opi = OP_BITANDI; 662 opi = OP_BITANDI;
@@ -436,19 +671,20 @@ compile_binary(Chunk *chunk, Node *node) {
436 } break; 671 } break;
437 default: break; 672 default: break;
438 } 673 }
439 CompResult comp_a = compile_expr(chunk, node->left); 674 CompResult comp_a = compile_expr(compiler, chunk, node->binary.left);
440 CompResult comp_b = compile_expr(chunk, node->right); 675 CompResult comp_b = compile_expr(compiler, chunk, node->binary.right);
441 sz reg_a; 676 sz reg_a;
442 sz reg_b; 677 sz reg_b;
443 switch (comp_a.type) { 678 switch (comp_a.type) {
444 case COMP_CONST: { 679 case COMP_CONST: {
445 reg_a = chunk->reg_idx++; 680 reg_a = chunk->reg_idx++;
446 EMIT_OP(ldop, reg_a, comp_a.idx, 0, node, chunk); 681 emit_op(ldop, reg_a, comp_a.idx, 0, node, chunk);
447 } break; 682 } break;
448 case COMP_REG: { 683 case COMP_REG: {
449 reg_a = comp_a.idx; 684 reg_a = comp_a.idx;
450 } break; 685 } break;
451 default: { 686 default: {
687 emit_compile_err(compiler, chunk, node);
452 return (CompResult){.type = COMP_ERR}; 688 return (CompResult){.type = COMP_ERR};
453 } break; 689 } break;
454 } 690 }
@@ -461,16 +697,99 @@ compile_binary(Chunk *chunk, Node *node) {
461 reg_b = comp_b.idx; 697 reg_b = comp_b.idx;
462 } break; 698 } break;
463 default: { 699 default: {
700 emit_compile_err(compiler, chunk, node);
464 return (CompResult){.type = COMP_ERR}; 701 return (CompResult){.type = COMP_ERR};
465 } break; 702 } break;
466 } 703 }
467 sz reg_dst = chunk->reg_idx++; // Better for optimization 704 sz reg_dst = chunk->reg_idx++; // Better for optimization
468 EMIT_OP(op, reg_dst, reg_a, reg_b, node, chunk); 705 emit_op(op, reg_dst, reg_a, reg_b, node, chunk);
706 return (CompResult){.type = COMP_REG, .idx = reg_dst};
707}
708
709CompResult
710compile_binary_logic(Compiler *compiler, Chunk *chunk, Node *node) {
711 // Logical functions have to shortcircuit once the answer is known.
712 OpCode op = OP_HALT;
713 OpCode opi = OP_HALT;
714 OpCode ldop = OP_LDCONST;
715 OpCode jmpop = OP_HALT;
716 OpCode jmpopi = OP_HALT;
717 bool default_value = false;
718 switch (node->kind) {
719 case NODE_AND: {
720 op = OP_AND;
721 opi = OP_ANDI;
722 jmpop = OP_JMPF;
723 jmpopi = OP_JMPFI;
724 default_value = false;
725 } break;
726 case NODE_OR: {
727 op = OP_OR;
728 opi = OP_ORI;
729 jmpop = OP_JMPT;
730 jmpopi = OP_JMPTI;
731 default_value = true;
732 } break;
733 default: break;
734 }
735
736 sz lab0 = chunk->labels_idx++;
737 sz lab1 = chunk->labels_idx++;
738
739 CompResult comp_a = compile_expr(compiler, chunk, node->binary.left);
740 sz reg_a;
741 switch (comp_a.type) {
742 case COMP_CONST: {
743 emit_op(jmpopi, lab0, comp_a.idx, 0, node->binary.left, chunk);
744 reg_a = chunk->reg_idx++;
745 emit_op(ldop, reg_a, comp_a.idx, 0, node, chunk);
746 } break;
747 case COMP_REG: {
748 emit_op(jmpop, lab0, comp_a.idx, 0, node->binary.left, chunk);
749 reg_a = comp_a.idx;
750 } break;
751 default: {
752 emit_compile_err(compiler, chunk, node);
753 return (CompResult){.type = COMP_ERR};
754 } break;
755 }
756
757 CompResult comp_b = compile_expr(compiler, chunk, node->binary.right);
758 sz reg_b;
759 switch (comp_b.type) {
760 case COMP_CONST: {
761 reg_b = comp_b.idx;
762 op = opi;
763 } break;
764 case COMP_REG: {
765 reg_b = comp_b.idx;
766 } break;
767 default: {
768 emit_compile_err(compiler, chunk, node);
769 return (CompResult){.type = COMP_ERR};
770 } break;
771 }
772 sz reg_dst = chunk->reg_idx++;
773 emit_op(op, reg_dst, reg_a, reg_b, node, chunk);
774
775 // Jump to the end of this comparison.
776 emit_op(OP_JMP, lab1, 0, 0, node, chunk);
777 sz pos0 = array_size(chunk->code);
778
779 // Load default value.
780 sz defaul_const = add_constant(chunk, default_value);
781 emit_op(ldop, reg_dst, defaul_const, 0, node, chunk);
782 sz pos1 = array_size(chunk->code);
783
784 // Register labels.
785 intintmap_insert(&chunk->labels, lab0, pos0, chunk->storage);
786 intintmap_insert(&chunk->labels, lab1, pos1, chunk->storage);
787
469 return (CompResult){.type = COMP_REG, .idx = reg_dst}; 788 return (CompResult){.type = COMP_REG, .idx = reg_dst};
470} 789}
471 790
472CompResult 791CompResult
473compile_unary(Chunk *chunk, Node *node) { 792compile_unary(Compiler *compiler, Chunk *chunk, Node *node) {
474 OpCode op = OP_HALT; 793 OpCode op = OP_HALT;
475 OpCode opi = OP_HALT; 794 OpCode opi = OP_HALT;
476 switch (node->kind) { 795 switch (node->kind) {
@@ -484,7 +803,7 @@ compile_unary(Chunk *chunk, Node *node) {
484 } break; 803 } break;
485 default: break; 804 default: break;
486 } 805 }
487 CompResult comp_a = compile_expr(chunk, node->left); 806 CompResult comp_a = compile_expr(compiler, chunk, node->binary.left);
488 sz reg_a; 807 sz reg_a;
489 switch (comp_a.type) { 808 switch (comp_a.type) {
490 case COMP_CONST: { 809 case COMP_CONST: {
@@ -495,42 +814,18 @@ compile_unary(Chunk *chunk, Node *node) {
495 reg_a = comp_a.idx; 814 reg_a = comp_a.idx;
496 } break; 815 } break;
497 default: { 816 default: {
817 emit_compile_err(compiler, chunk, node);
498 return (CompResult){.type = COMP_ERR}; 818 return (CompResult){.type = COMP_ERR};
499 } break; 819 } break;
500 } 820 }
501 sz reg_dst = chunk->reg_idx++; 821 sz reg_dst = chunk->reg_idx++;
502 EMIT_OP(op, reg_dst, reg_a, 0, node, chunk); 822 emit_op(op, reg_dst, reg_a, 0, node, chunk);
503 return (CompResult){.type = COMP_REG, .idx = reg_dst}; 823 return (CompResult){.type = COMP_REG, .idx = reg_dst};
504} 824}
505 825
506sz
507add_constant(Chunk *chunk, sz value) {
508 IntIntMap *map = intintmap_lookup(&chunk->intmap, value);
509 // Make sure we don't have duplicated constants.
510 if (!map) {
511 map = intintmap_insert(&chunk->intmap, value, chunk->const_idx++,
512 chunk->storage);
513 Constant c = (Constant){.i = value};
514 array_push(chunk->constants, c, chunk->storage);
515 }
516 return map->val;
517}
518
519sz
520add_string(Chunk *chunk, Str string) {
521 // Make sure we don't have duplicated string.
522 StrIntMap *map = strintmap_lookup(&chunk->strmap, string);
523 if (!map) {
524 map = strintmap_insert(&chunk->strmap, string, chunk->str_idx++,
525 chunk->storage);
526 array_push(chunk->strings, string, chunk->storage);
527 }
528 return map->val;
529}
530
531CompResult 826CompResult
532compile_if(Chunk *chunk, Node *node) { 827compile_if(Compiler *compiler, Chunk *chunk, Node *node) {
533 CompResult cond = compile_expr(chunk, node->cond_if); 828 CompResult cond = compile_expr(compiler, chunk, node->ifelse.cond);
534 OpCode jmpop; 829 OpCode jmpop;
535 switch (cond.type) { 830 switch (cond.type) {
536 case COMP_CONST: { 831 case COMP_CONST: {
@@ -540,29 +835,35 @@ compile_if(Chunk *chunk, Node *node) {
540 jmpop = OP_JMPF; 835 jmpop = OP_JMPF;
541 } break; 836 } break;
542 default: { 837 default: {
838 emit_compile_err(compiler, chunk, node);
543 return (CompResult){.type = COMP_ERR}; 839 return (CompResult){.type = COMP_ERR};
544 } break; 840 } break;
545 } 841 }
546 842
547 if (!str_eq(node->type, cstr("nil"))) { 843 if (!str_eq(node->type, cstr("nil")) &&
844 !str_has_prefix(node->type, cstr("ret:")) &&
845 !str_has_prefix(node->type, cstr("flow:"))) {
548 sz reg_dst = chunk->reg_idx++; 846 sz reg_dst = chunk->reg_idx++;
549 847
550 // Jump to the `false` branch. 848 // Jump to the `false` branch.
551 sz lab0 = chunk->labels_idx++; 849 sz lab0 = chunk->labels_idx++;
552 EMIT_OP(jmpop, lab0, cond.idx, 0, node->cond_if, chunk); 850 emit_op(jmpop, lab0, cond.idx, 0, node->ifelse.cond, chunk);
553 851
554 // Condition is true. 852 // Condition is true.
555 CompResult then_expr = compile_expr(chunk, node->cond_expr); 853 CompResult then_expr =
854 compile_expr(compiler, chunk, node->ifelse.expr_true);
556 switch (then_expr.type) { 855 switch (then_expr.type) {
557 case COMP_CONST: { 856 case COMP_CONST: {
558 EMIT_OP(OP_LD64K, reg_dst, then_expr.idx, 0, node->cond_if, 857 emit_op(OP_LDCONST, reg_dst, then_expr.idx, 0,
559 chunk); 858 node->ifelse.cond, chunk);
560 } break; 859 } break;
561 case COMP_REG: { 860 case COMP_REG: {
562 EMIT_OP(OP_MOV64, reg_dst, then_expr.idx, 0, node->cond_if, 861 emit_op(OP_MOV64, reg_dst, then_expr.idx, 0, node->ifelse.cond,
563 chunk); 862 chunk);
564 } break; 863 } break;
864 case COMP_RET: break;
565 default: { 865 default: {
866 emit_compile_err(compiler, chunk, node);
566 return (CompResult){.type = COMP_ERR}; 867 return (CompResult){.type = COMP_ERR};
567 } break; 868 } break;
568 } 869 }
@@ -570,20 +871,23 @@ compile_if(Chunk *chunk, Node *node) {
570 // Jump to the end of the expression. 871 // Jump to the end of the expression.
571 sz pos0 = array_size(chunk->code); 872 sz pos0 = array_size(chunk->code);
572 sz lab1 = chunk->labels_idx++; 873 sz lab1 = chunk->labels_idx++;
573 EMIT_OP(OP_JMP, lab1, 0, 0, node->cond_else, chunk); 874 emit_op(OP_JMP, lab1, 0, 0, node->ifelse.expr_else, chunk);
574 875
575 // Else expression. 876 // Else expression.
576 CompResult else_expr = compile_expr(chunk, node->cond_else); 877 CompResult else_expr =
878 compile_expr(compiler, chunk, node->ifelse.expr_else);
577 switch (else_expr.type) { 879 switch (else_expr.type) {
578 case COMP_CONST: { 880 case COMP_CONST: {
579 EMIT_OP(OP_LD64K, reg_dst, else_expr.idx, 0, node->cond_else, 881 emit_op(OP_LDCONST, reg_dst, else_expr.idx, 0,
580 chunk); 882 node->ifelse.expr_else, chunk);
581 } break; 883 } break;
582 case COMP_REG: { 884 case COMP_REG: {
583 EMIT_OP(OP_MOV64, reg_dst, else_expr.idx, 0, node->cond_else, 885 emit_op(OP_MOV64, reg_dst, else_expr.idx, 0,
584 chunk); 886 node->ifelse.expr_else, chunk);
585 } break; 887 } break;
888 case COMP_RET: break;
586 default: { 889 default: {
890 emit_compile_err(compiler, chunk, node);
587 return (CompResult){.type = COMP_ERR}; 891 return (CompResult){.type = COMP_ERR};
588 } break; 892 } break;
589 } 893 }
@@ -592,47 +896,44 @@ compile_if(Chunk *chunk, Node *node) {
592 // Update labels. 896 // Update labels.
593 intintmap_insert(&chunk->labels, lab0, pos0 + 1, chunk->storage); 897 intintmap_insert(&chunk->labels, lab0, pos0 + 1, chunk->storage);
594 intintmap_insert(&chunk->labels, lab1, pos1, chunk->storage); 898 intintmap_insert(&chunk->labels, lab1, pos1, chunk->storage);
595 intintmap_insert(&chunk->labels_rev, pos0 + 1, lab0, chunk->storage);
596 intintmap_insert(&chunk->labels_rev, pos1, lab1, chunk->storage);
597 return (CompResult){.type = COMP_REG, .idx = reg_dst}; 899 return (CompResult){.type = COMP_REG, .idx = reg_dst};
598 } 900 }
599 901
600 // Jump to the `false` branch. 902 // Jump to the `false` branch.
601 sz lab0 = chunk->labels_idx++; 903 sz lab0 = chunk->labels_idx++;
602 EMIT_OP(jmpop, lab0, cond.idx, 0, node->cond_if, chunk); 904 emit_op(jmpop, lab0, cond.idx, 0, node->ifelse.cond, chunk);
603 905
604 // Condition is true. 906 // Condition is true.
605 compile_expr(chunk, node->cond_expr); 907 compile_expr(compiler, chunk, node->ifelse.expr_true);
606 908
607 // Jump to the end of the expression. 909 // Jump to the end of the expression.
608 sz pos0 = array_size(chunk->code); 910 sz pos0 = array_size(chunk->code);
609 sz lab1 = chunk->labels_idx++; 911 sz lab1 = chunk->labels_idx++;
610 EMIT_OP(OP_JMP, lab1, 0, 0, node->cond_else, chunk); 912 emit_op(OP_JMP, lab1, 0, 0, node->ifelse.expr_else, chunk);
611 913
612 // Else expression. 914 // Else expression.
613 if (node->cond_else) { 915 if (node->ifelse.expr_else) {
614 compile_expr(chunk, node->cond_else); 916 compile_expr(compiler, chunk, node->ifelse.expr_else);
615 } 917 }
616 sz pos1 = array_size(chunk->code); 918 sz pos1 = array_size(chunk->code);
617 919
618 // Update labels. 920 // Update labels.
619 intintmap_insert(&chunk->labels, lab0, pos0 + 1, chunk->storage); 921 intintmap_insert(&chunk->labels, lab0, pos0 + 1, chunk->storage);
620 intintmap_insert(&chunk->labels_rev, pos0 + 1, lab0, chunk->storage);
621 intintmap_insert(&chunk->labels, lab1, pos1, chunk->storage); 922 intintmap_insert(&chunk->labels, lab1, pos1, chunk->storage);
622 intintmap_insert(&chunk->labels_rev, pos1, lab1, chunk->storage);
623 923
624 return (CompResult){.type = COMP_NIL}; 924 return (CompResult){.type = COMP_NIL};
625} 925}
626 926
627CompResult 927CompResult
628compile_cond(Chunk *chunk, Node *node) { 928compile_cond(Compiler *compiler, Chunk *chunk, Node *node) {
629 if (str_eq(node->type, cstr("nil"))) { 929 if (str_eq(node->type, cstr("nil"))) {
630 sz lab1 = chunk->labels_idx++; 930 sz lab1 = chunk->labels_idx++;
631 for (sz i = 0; i < array_size(node->match_cases); i++) { 931 for (sz i = 0; i < array_size(node->match.cases); i++) {
632 // condition = expression 932 // condition = expression
633 Node *expr = node->match_cases[i]; 933 Node *expr = node->match.cases[i];
634 if (expr->case_value) { 934 if (expr->case_entry.cond) {
635 CompResult cond = compile_expr(chunk, expr->case_value); 935 CompResult cond =
936 compile_expr(compiler, chunk, expr->case_entry.cond);
636 OpCode jmpop; 937 OpCode jmpop;
637 switch (cond.type) { 938 switch (cond.type) {
638 case COMP_CONST: { 939 case COMP_CONST: {
@@ -642,42 +943,41 @@ compile_cond(Chunk *chunk, Node *node) {
642 jmpop = OP_JMPF; 943 jmpop = OP_JMPF;
643 } break; 944 } break;
644 default: { 945 default: {
946 emit_compile_err(compiler, chunk, node);
645 return (CompResult){.type = COMP_ERR}; 947 return (CompResult){.type = COMP_ERR};
646 } break; 948 } break;
647 } 949 }
648 // Jump to the `next` branch. 950 // Jump to the `next` branch.
649 sz lab0 = chunk->labels_idx++; 951 sz lab0 = chunk->labels_idx++;
650 EMIT_OP(jmpop, lab0, cond.idx, 0, expr->case_expr, chunk); 952 emit_op(jmpop, lab0, cond.idx, 0, expr->case_entry.expr, chunk);
651 953
652 // Condition is true. 954 // Condition is true.
653 compile_expr(chunk, expr->case_expr); 955 compile_expr(compiler, chunk, expr->case_entry.expr);
654 if (i != array_size(node->match_cases) - 1) { 956 if (i != array_size(node->match.cases) - 1) {
655 // Jump to the end of the expression. 957 // Jump to the end of the expression.
656 sz pos0 = array_size(chunk->code); 958 sz pos0 = array_size(chunk->code);
657 EMIT_OP(OP_JMP, lab1, 0, 0, node->cond_else, chunk); 959 emit_op(OP_JMP, lab1, 0, 0, node->ifelse.expr_else, chunk);
658 intintmap_insert(&chunk->labels, lab0, pos0 + 1, 960 intintmap_insert(&chunk->labels, lab0, pos0 + 1,
659 chunk->storage); 961 chunk->storage);
660 intintmap_insert(&chunk->labels_rev, pos0 + 1, lab0,
661 chunk->storage);
662 } 962 }
663 } else { 963 } else {
664 compile_expr(chunk, expr->case_expr); 964 compile_expr(compiler, chunk, expr->case_entry.expr);
665 break; 965 break;
666 } 966 }
667 } 967 }
668 sz pos1 = array_size(chunk->code); 968 sz pos1 = array_size(chunk->code);
669 intintmap_insert(&chunk->labels, lab1, pos1, chunk->storage); 969 intintmap_insert(&chunk->labels, lab1, pos1, chunk->storage);
670 intintmap_insert(&chunk->labels_rev, pos1, lab1, chunk->storage);
671 return (CompResult){.type = COMP_NIL}; 970 return (CompResult){.type = COMP_NIL};
672 } 971 }
673 972
674 sz reg_dst = chunk->reg_idx++; 973 sz reg_dst = chunk->reg_idx++;
675 sz lab1 = chunk->labels_idx++; 974 sz lab1 = chunk->labels_idx++;
676 for (sz i = 0; i < array_size(node->match_cases); i++) { 975 for (sz i = 0; i < array_size(node->match.cases); i++) {
677 // condition = expression 976 // condition = expression
678 Node *expr = node->match_cases[i]; 977 Node *expr = node->match.cases[i];
679 if (expr->case_value) { 978 if (expr->case_entry.cond) {
680 CompResult cond = compile_expr(chunk, expr->case_value); 979 CompResult cond =
980 compile_expr(compiler, chunk, expr->case_entry.cond);
681 OpCode jmpop; 981 OpCode jmpop;
682 switch (cond.type) { 982 switch (cond.type) {
683 case COMP_CONST: { 983 case COMP_CONST: {
@@ -687,49 +987,54 @@ compile_cond(Chunk *chunk, Node *node) {
687 jmpop = OP_JMPF; 987 jmpop = OP_JMPF;
688 } break; 988 } break;
689 default: { 989 default: {
990 emit_compile_err(compiler, chunk, node);
690 return (CompResult){.type = COMP_ERR}; 991 return (CompResult){.type = COMP_ERR};
691 } break; 992 } break;
692 } 993 }
693 // Jump to the `next` branch. 994 // Jump to the `next` branch.
694 sz lab0 = chunk->labels_idx++; 995 sz lab0 = chunk->labels_idx++;
695 EMIT_OP(jmpop, lab0, cond.idx, 0, expr->case_expr, chunk); 996 emit_op(jmpop, lab0, cond.idx, 0, expr->case_entry.expr, chunk);
696 997
697 // Condition is true. 998 // Condition is true.
698 CompResult then_expr = compile_expr(chunk, expr->case_expr); 999 CompResult then_expr =
1000 compile_expr(compiler, chunk, expr->case_entry.expr);
699 switch (then_expr.type) { 1001 switch (then_expr.type) {
700 case COMP_CONST: { 1002 case COMP_CONST: {
701 EMIT_OP(OP_LD64K, reg_dst, then_expr.idx, 0, 1003 emit_op(OP_LDCONST, reg_dst, then_expr.idx, 0,
702 expr->case_expr, chunk); 1004 expr->case_entry.expr, chunk);
703 } break; 1005 } break;
704 case COMP_REG: { 1006 case COMP_REG: {
705 EMIT_OP(OP_MOV64, reg_dst, then_expr.idx, 0, 1007 emit_op(OP_MOV64, reg_dst, then_expr.idx, 0,
706 expr->case_expr, chunk); 1008 expr->case_entry.expr, chunk);
707 } break; 1009 } break;
1010 case COMP_RET: break;
708 default: { 1011 default: {
1012 emit_compile_err(compiler, chunk, node);
709 return (CompResult){.type = COMP_ERR}; 1013 return (CompResult){.type = COMP_ERR};
710 } break; 1014 } break;
711 } 1015 }
712 if (i != array_size(node->match_cases) - 1) { 1016 if (i != array_size(node->match.cases) - 1) {
713 // Jump to the end of the expression. 1017 // Jump to the end of the expression.
714 sz pos0 = array_size(chunk->code); 1018 sz pos0 = array_size(chunk->code);
715 EMIT_OP(OP_JMP, lab1, 0, 0, node->cond_else, chunk); 1019 emit_op(OP_JMP, lab1, 0, 0, node->ifelse.expr_else, chunk);
716 intintmap_insert(&chunk->labels, lab0, pos0 + 1, 1020 intintmap_insert(&chunk->labels, lab0, pos0 + 1,
717 chunk->storage); 1021 chunk->storage);
718 intintmap_insert(&chunk->labels_rev, pos0 + 1, lab0,
719 chunk->storage);
720 } 1022 }
721 } else { 1023 } else {
722 CompResult then_expr = compile_expr(chunk, expr->case_expr); 1024 CompResult then_expr =
1025 compile_expr(compiler, chunk, expr->case_entry.expr);
723 switch (then_expr.type) { 1026 switch (then_expr.type) {
724 case COMP_CONST: { 1027 case COMP_CONST: {
725 EMIT_OP(OP_LD64K, reg_dst, then_expr.idx, 0, 1028 emit_op(OP_LDCONST, reg_dst, then_expr.idx, 0,
726 expr->case_expr, chunk); 1029 expr->case_entry.expr, chunk);
727 } break; 1030 } break;
728 case COMP_REG: { 1031 case COMP_REG: {
729 EMIT_OP(OP_MOV64, reg_dst, then_expr.idx, 0, 1032 emit_op(OP_MOV64, reg_dst, then_expr.idx, 0,
730 expr->case_expr, chunk); 1033 expr->case_entry.expr, chunk);
731 } break; 1034 } break;
1035 case COMP_RET: break;
732 default: { 1036 default: {
1037 emit_compile_err(compiler, chunk, node);
733 return (CompResult){.type = COMP_ERR}; 1038 return (CompResult){.type = COMP_ERR};
734 } break; 1039 } break;
735 } 1040 }
@@ -738,14 +1043,27 @@ compile_cond(Chunk *chunk, Node *node) {
738 } 1043 }
739 sz pos1 = array_size(chunk->code); 1044 sz pos1 = array_size(chunk->code);
740 intintmap_insert(&chunk->labels, lab1, pos1, chunk->storage); 1045 intintmap_insert(&chunk->labels, lab1, pos1, chunk->storage);
741 intintmap_insert(&chunk->labels_rev, pos1, lab1, chunk->storage);
742 return (CompResult){.type = COMP_REG, .idx = reg_dst}; 1046 return (CompResult){.type = COMP_REG, .idx = reg_dst};
743} 1047}
744 1048
745CompResult 1049CompResult
746compile_while(Chunk *chunk, Node *node) { 1050compile_break(Compiler *compiler, Chunk *chunk, Node *node) {
1051 emit_op(OP_JMP, compiler->lab_post, 0, 0, node, chunk);
1052 return (CompResult){.type = COMP_NIL};
1053}
1054
1055CompResult
1056compile_continue(Compiler *compiler, Chunk *chunk, Node *node) {
1057 emit_op(OP_JMP, compiler->lab_pre, 0, 0, node, chunk);
1058 return (CompResult){.type = COMP_NIL};
1059}
1060
1061CompResult
1062compile_while(Compiler *compiler, Chunk *chunk, Node *node) {
1063 sz lab0 = chunk->labels_idx++;
1064 sz lab1 = chunk->labels_idx++;
747 sz pos1 = array_size(chunk->code); 1065 sz pos1 = array_size(chunk->code);
748 CompResult cond = compile_expr(chunk, node->while_cond); 1066 CompResult cond = compile_expr(compiler, chunk, node->loop.cond);
749 OpCode jmpop; 1067 OpCode jmpop;
750 switch (cond.type) { 1068 switch (cond.type) {
751 case COMP_CONST: { 1069 case COMP_CONST: {
@@ -755,69 +1073,163 @@ compile_while(Chunk *chunk, Node *node) {
755 jmpop = OP_JMPF; 1073 jmpop = OP_JMPF;
756 } break; 1074 } break;
757 default: { 1075 default: {
1076 emit_compile_err(compiler, chunk, node);
758 return (CompResult){.type = COMP_ERR}; 1077 return (CompResult){.type = COMP_ERR};
759 } break; 1078 } break;
760 } 1079 }
761 1080
762 // Jump to the `end of the loop` branch. 1081 // Jump to the `end of the loop` branch.
763 sz lab0 = chunk->labels_idx++; 1082 emit_op(jmpop, lab0, cond.idx, 0, node->loop.cond, chunk);
764 EMIT_OP(jmpop, lab0, cond.idx, 0, node->while_cond, chunk);
765 1083
766 // Condition is true. 1084 // Condition is true.
767 compile_expr(chunk, node->while_expr); 1085 compiler->lab_pre = lab1;
1086 compiler->lab_post = lab0;
1087 compile_expr(compiler, chunk, node->loop.expr);
768 sz pos0 = array_size(chunk->code); 1088 sz pos0 = array_size(chunk->code);
769 sz lab1 = chunk->labels_idx++; 1089 emit_op(OP_JMP, lab1, 0, 0, node, chunk);
770 EMIT_OP(OP_JMP, lab1, 0, 0, node, chunk);
771 1090
772 // Update labels. 1091 // Update labels.
773 intintmap_insert(&chunk->labels, lab0, pos0 + 1, chunk->storage); 1092 intintmap_insert(&chunk->labels, lab0, pos0 + 1, chunk->storage);
774 intintmap_insert(&chunk->labels_rev, pos0 + 1, lab0, chunk->storage);
775 intintmap_insert(&chunk->labels, lab1, pos1, chunk->storage); 1093 intintmap_insert(&chunk->labels, lab1, pos1, chunk->storage);
776 intintmap_insert(&chunk->labels_rev, pos1, lab1, chunk->storage);
777 1094
778 // Return. 1095 // Return.
779 return (CompResult){.type = COMP_NIL}; 1096 return (CompResult){.type = COMP_NIL};
780} 1097}
781 1098
782CompResult 1099CompResult
783compile_funcall(Chunk *chunk, Node *node) { 1100compile_tail_call(Compiler *compiler, Chunk *chunk, Node *node) {
1101 // Update the local parameters.
1102 for (sz i = 0; i < array_size(node->elements); i++) {
1103 Node *expr = node->elements[i];
1104 CompResult result = compile_expr(compiler, chunk, expr);
1105 switch (result.type) {
1106 case COMP_CONST: {
1107 emit_op(OP_STLVARI, i, result.idx, 0, node, chunk);
1108 } break;
1109 case COMP_REG: {
1110 if (str_eq(expr->type, cstr("Str"))) {
1111 sz var_addr = chunk->reg_idx++;
1112 sz str_addr = result.idx;
1113 emit_op(OP_LDLADDR, var_addr, i, 0, node, chunk);
1114 emit_fat_copy(chunk, node, var_addr, str_addr);
1115 } else {
1116 emit_op(OP_STLVAR, i, result.idx, 0, node, chunk);
1117 }
1118 } break;
1119 case COMP_STRING: {
1120 sz var_addr = chunk->reg_idx++;
1121 sz str_addr = chunk->reg_idx++;
1122 emit_op(OP_LDLADDR, var_addr, i, 0, node, chunk);
1123 emit_op(OP_LDSTR, str_addr, result.idx, 0, node, chunk);
1124 emit_fat_copy(chunk, node, var_addr, str_addr);
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_RECUR, 0, 0, 0, node, chunk);
1134 return (CompResult){.type = COMP_NIL};
1135}
1136
1137CompResult
1138compile_funcall(Compiler *compiler, Chunk *chunk, Node *node) {
784 Str name = node->value.str; 1139 Str name = node->value.str;
785 1140
786 // Builtins. 1141 // Builtins.
787 if (str_eq(name, cstr("print")) || str_eq(name, cstr("println"))) { 1142 if (str_eq(name, cstr("print")) || str_eq(name, cstr("println"))) {
788 for (sz i = 0; i < array_size(node->elements); i++) { 1143 for (sz i = 0; i < array_size(node->elements); i++) {
789 Node *expr = node->elements[i]; 1144 Node *expr = node->elements[i];
790 CompResult result = compile_expr(chunk, expr); 1145 Str type_name = expr->type;
791 if (str_eq(expr->type, cstr("int"))) { 1146 if (str_has_prefix(type_name, cstr("@"))) {
1147 type_name = cstr("Ptr");
1148 }
1149 StrTypeMap *t = strtype_lookup(&compiler->type_map, type_name);
1150 Str type = t->val.unique_name;
1151 sz size = t->val.size;
1152 CompResult result = compile_expr(compiler, chunk, expr);
1153 if (strset_lookup(&compiler->signed_ints, type)) {
792 switch (result.type) { 1154 switch (result.type) {
793 case COMP_CONST: { 1155 case COMP_CONST: {
794 EMIT_OP(OP_PRINTS64I, result.idx, 0, 0, expr, chunk); 1156 emit_sized_op(size, OP_PRINTS64I, OP_PRINTS32I,
1157 OP_PRINTS16I, OP_PRINTS8I, result.idx, 0,
1158 0, expr, chunk);
795 } break; 1159 } break;
796 case COMP_REG: { 1160 case COMP_REG: {
797 EMIT_OP(OP_PRINTS64, result.idx, 0, 0, expr, chunk); 1161 emit_sized_op(size, OP_PRINTS64, OP_PRINTS32,
1162 OP_PRINTS16, OP_PRINTS8, result.idx, 0, 0,
1163 expr, chunk);
798 } break; 1164 } break;
799 default: { 1165 default: {
1166 emit_compile_err(compiler, chunk, node);
800 return (CompResult){.type = COMP_ERR}; 1167 return (CompResult){.type = COMP_ERR};
801 } break; 1168 } break;
802 } 1169 }
803 } else if (str_eq(expr->type, cstr("f64"))) { 1170 } else if (strset_lookup(&compiler->unsigned_ints, type)) {
804 switch (result.type) { 1171 switch (result.type) {
805 case COMP_CONST: { 1172 case COMP_CONST: {
806 EMIT_OP(OP_PRINTF64I, result.idx, 0, 0, expr, chunk); 1173 emit_sized_op(size, OP_PRINTU64I, OP_PRINTU32I,
1174 OP_PRINTU16I, OP_PRINTU8I, result.idx, 0,
1175 0, expr, chunk);
807 } break; 1176 } break;
808 case COMP_REG: { 1177 case COMP_REG: {
809 EMIT_OP(OP_PRINTF64, result.idx, 0, 0, expr, chunk); 1178 emit_sized_op(size, OP_PRINTU64, OP_PRINTU32,
1179 OP_PRINTU16, OP_PRINTU8, result.idx, 0, 0,
1180 expr, chunk);
810 } break; 1181 } break;
811 default: { 1182 default: {
1183 emit_compile_err(compiler, chunk, node);
812 return (CompResult){.type = COMP_ERR}; 1184 return (CompResult){.type = COMP_ERR};
813 } break; 1185 } break;
814 } 1186 }
815 } else if (str_eq(expr->type, cstr("str"))) { 1187 } else if (strset_lookup(&compiler->float_types, type)) {
1188 switch (result.type) {
1189 case COMP_CONST: {
1190 if (size == 8) {
1191 emit_op(OP_PRINTF64I, result.idx, 0, 0, expr,
1192 chunk);
1193 } else {
1194 emit_op(OP_PRINTF32I, result.idx, 0, 0, expr,
1195 chunk);
1196 }
1197 } break;
1198 case COMP_REG: {
1199 if (size == 8) {
1200 emit_op(OP_PRINTF64, result.idx, 0, 0, expr, chunk);
1201 } else {
1202 emit_op(OP_PRINTF32, result.idx, 0, 0, expr, chunk);
1203 }
1204 } break;
1205 default: {
1206 emit_compile_err(compiler, chunk, node);
1207 return (CompResult){.type = COMP_ERR};
1208 } break;
1209 }
1210 } else if (str_eq(type, cstr("Str"))) {
816 switch (result.type) { 1211 switch (result.type) {
817 case COMP_STRING: { 1212 case COMP_STRING: {
818 EMIT_OP(OP_PRINTSTR, result.idx, 0, 0, expr, chunk); 1213 emit_op(OP_PRINTSTRI, result.idx, 0, 0, expr, chunk);
1214 } break;
1215 case COMP_REG: {
1216 emit_op(OP_PRINTSTR, result.idx, 0, 0, expr, chunk);
1217 } break;
1218 default: {
1219 emit_compile_err(compiler, chunk, node);
1220 return (CompResult){.type = COMP_ERR};
1221 } break;
1222 }
1223 } else if (str_eq(type, cstr("Bool"))) {
1224 switch (result.type) {
1225 case COMP_CONST: {
1226 emit_op(OP_PRINTBOOLI, result.idx, 0, 0, expr, chunk);
1227 } break;
1228 case COMP_REG: {
1229 emit_op(OP_PRINTBOOL, result.idx, 0, 0, expr, chunk);
819 } break; 1230 } break;
820 default: { 1231 default: {
1232 emit_compile_err(compiler, chunk, node);
821 return (CompResult){.type = COMP_ERR}; 1233 return (CompResult){.type = COMP_ERR};
822 } break; 1234 } break;
823 } 1235 }
@@ -825,75 +1237,181 @@ compile_funcall(Chunk *chunk, Node *node) {
825 } 1237 }
826 if (str_eq(name, cstr("println"))) { 1238 if (str_eq(name, cstr("println"))) {
827 sz idx = add_string(chunk, cstr("\n")); 1239 sz idx = add_string(chunk, cstr("\n"));
828 EMIT_OP(OP_PRINTSTR, idx, 0, 0, node, chunk); 1240 emit_op(OP_PRINTSTRI, idx, 0, 0, node, chunk);
829 } 1241 }
830 return (CompResult){.type = COMP_NIL}; 1242 return (CompResult){.type = COMP_NIL};
831 } 1243 }
832 1244
833 // TODO: need to find this on the parents, not just in the current chunk. 1245 FunctionMap *map =
834 FunctionMap *map = funcmap_lookup(&chunk->funmap, node->unique_name); 1246 funcmap_lookup(&compiler->main_chunk.funmap, node->unique_name);
835 if (!map) { 1247 if (!map) {
836 println("how come?"); 1248 emit_compile_err(compiler, chunk, node);
1249 return (CompResult){.type = COMP_ERR};
837 } 1250 }
838 Function fun = map->val; 1251 Function fun = map->val;
839 1252
1253 // Check for tail recursive opportunities.
1254 if (str_eq(fun.name, node->unique_name) &&
1255 str_eq(chunk->name, node->unique_name)) {
1256 Node *parent = node->parent;
1257 Node *current = node;
1258 bool tail_recursive = true;
1259 while (parent != NULL) {
1260 switch (parent->kind) {
1261 case NODE_BLOCK: {
1262 sz idx = array_size(parent->statements) - 1;
1263 if (parent->statements[idx] != node) {
1264 tail_recursive = false;
1265 break;
1266 }
1267 } break;
1268 case NODE_WHILE: {
1269 if (current == parent->loop.cond) {
1270 tail_recursive = false;
1271 break;
1272 }
1273 } break;
1274 case NODE_IF: {
1275 if (current == parent->ifelse.cond) {
1276 tail_recursive = false;
1277 break;
1278 }
1279 } break;
1280 case NODE_FUN: {
1281 sz idx = array_size(parent->func.body->statements) - 1;
1282 if (parent->func.body->statements[idx] != current) {
1283 tail_recursive = false;
1284 break;
1285 }
1286 break;
1287 } break;
1288 case NODE_MATCH: {
1289 if (current == parent->match.expr) {
1290 tail_recursive = false;
1291 break;
1292 }
1293 } break;
1294 case NODE_COND: break;
1295 case NODE_CASE_COND: {
1296 if (current == parent->case_entry.cond) {
1297 tail_recursive = false;
1298 break;
1299 }
1300 } break;
1301 default: {
1302 tail_recursive = false;
1303 break;
1304 } break;
1305 }
1306 parent = parent->parent;
1307 current = current->parent;
1308 }
1309 if (tail_recursive) {
1310 return compile_tail_call(compiler, chunk, node);
1311 }
1312 }
1313
840 // Reserve space for the return value if needed. 1314 // Reserve space for the return value if needed.
841 if (fun.return_arity > 0) { 1315 if (fun.return_arity > 0) {
842 // Put the return data into a register 1316 // Put the return data into a register
843 sz ret_size = add_constant(chunk, 8); 1317 sz ret_size = add_constant(chunk, 8);
844 EMIT_OP(OP_RESERVE, ret_size, 0, 0, node, chunk); 1318 emit_op(OP_RESERVE, ret_size, 0, 0, node, chunk);
845 } 1319 }
846 1320
847 // Send parameters to the stack. 1321 // Send parameters to the stack.
848 for (sz i = 0; i < array_size(node->elements); i++) { 1322 for (sz i = 0; i < array_size(node->elements); i++) {
849 Node *expr = node->elements[i]; 1323 Node *expr = node->elements[i];
850 CompResult result = compile_expr(chunk, expr); 1324 CompResult result = compile_expr(compiler, chunk, expr);
851 // TODO: Assuming all values are 8 bytes... again. 1325 Str type_name = expr->type;
1326 if (str_has_prefix(type_name, cstr("@"))) {
1327 type_name = cstr("Ptr");
1328 }
1329 StrTypeMap *t = strtype_lookup(&compiler->type_map, type_name);
1330 sz size = t->val.size;
852 switch (result.type) { 1331 switch (result.type) {
853 case COMP_CONST: { 1332 case COMP_CONST: {
854 EMIT_OP(OP_PUSHI, result.idx, 0, 0, expr, chunk); 1333 emit_op(OP_PUSHI, result.idx, 0, 0, expr, chunk);
855 } break; 1334 } break;
856 case COMP_REG: { 1335 case COMP_REG: {
857 EMIT_OP(OP_PUSH, result.idx, 0, 0, expr, chunk); 1336 if (str_eq(expr->type, cstr("Str"))) {
1337 sz str_addr = result.idx;
1338 // Store the fat string pointer into the stack.
1339 sz reg_dst = chunk->reg_idx++;
1340 sz zero = add_constant(chunk, 0);
1341 sz one = add_constant(chunk, 1);
1342 emit_sized_op(size, OP_LD64I, OP_LD32I, OP_LD16I, OP_LD8I,
1343 reg_dst, str_addr, zero, node, chunk);
1344 emit_op(OP_PUSH, reg_dst, 0, 0, expr, chunk);
1345 emit_sized_op(size, OP_LD64I, OP_LD32I, OP_LD16I, OP_LD8I,
1346 reg_dst, str_addr, one, node, chunk);
1347 emit_op(OP_PUSH, reg_dst, 0, 0, expr, chunk);
1348 } else {
1349 emit_op(OP_PUSH, result.idx, 0, 0, expr, chunk);
1350 }
1351 } break;
1352 case COMP_STRING: {
1353 // Get the address for the string value variable.
1354 sz str_addr = chunk->reg_idx++;
1355 emit_op(OP_LDSTR, str_addr, result.idx, 0, node->var.val,
1356 chunk);
1357
1358 // Store the fat string pointer into the stack.
1359 sz reg_dst = chunk->reg_idx++;
1360 sz zero = add_constant(chunk, 0);
1361 sz one = add_constant(chunk, 1);
1362 emit_op(OP_LD64I, reg_dst, str_addr, zero, node, chunk);
1363 emit_op(OP_PUSH, reg_dst, 0, 0, expr, chunk);
1364 emit_op(OP_LD64I, reg_dst, str_addr, one, node, chunk);
1365 emit_op(OP_PUSH, reg_dst, 0, 0, expr, chunk);
858 } break; 1366 } break;
859 default: { 1367 default: {
1368 emit_compile_err(compiler, chunk, node);
860 return (CompResult){.type = COMP_ERR}; 1369 return (CompResult){.type = COMP_ERR};
861 } break; 1370 } break;
862 } 1371 }
863 } 1372 }
864 1373
865 // // TODO: prologue (how much space do we actually need)? we need the 1374 emit_op(OP_CALL, fun.index, 0, 0, node, chunk);
866 // symbol
867 // // table, arity and return parameters boy.
868 // // FIXME: assuming all values are 8 bytes for now...
869 // sz alloc_size = (fun.param_arity + fun.return_arity) * 8;
870 // sz alloc_const = add_constant(chunk, alloc_size);
871 // if (alloc_size > 0) {
872 // // EMIT_OP(OP_RESERVE, alloc_const, 0, 0, node, chunk);
873 // }
874
875 // // println("FUNCALL: unique name: %s", node->unique_name);
876 // // println("FUN: param_arity: %d", fun.param_arity);
877 // // println("FUN: return_arity: %d", fun.return_arity);
878 EMIT_OP(OP_CALL, fun.index, 0, 0, node, chunk);
879 1375
880 // Only one return parameter for now. 1376 // Only one return parameter for now.
881 if (fun.return_arity > 0) { 1377 if (fun.return_arity > 0) {
882 // Put the return data into a register 1378 // Put the return data into a register
883 sz reg_dst = chunk->reg_idx++; 1379 sz reg_dst = chunk->reg_idx++;
884 EMIT_OP(OP_POP, reg_dst, 0, 0, node, chunk); 1380 emit_op(OP_POP, reg_dst, 0, 0, node, chunk);
885 return (CompResult){.type = COMP_REG, .idx = reg_dst}; 1381 return (CompResult){.type = COMP_REG, .idx = reg_dst};
886 } 1382 }
887 1383
888 // if (alloc_size > 0) {
889 // // EMIT_OP(OP_POP, alloc_const, 0, 0, node, chunk);
890 // }
891 // TODO: epilogue (how much space do we actually need)? we need to remove
892 // the AR data here after using it. If we only have one return parameter we
893 // can put it in a register but what if that's not actually the case?
894 return (CompResult){.type = COMP_NIL}; 1384 return (CompResult){.type = COMP_NIL};
895} 1385}
896 1386
1387CompResult
1388compile_return(Compiler *compiler, Chunk *chunk, Node *node) {
1389 for (sz i = 0; i < array_size(node->elements); i++) {
1390 Node *expr = node->elements[i];
1391 CompResult res = compile_expr(compiler, chunk, expr);
1392
1393 // TODO: Only one return field for now, but this is the idea.
1394 // Put return values into memory.
1395 switch (res.type) {
1396 case COMP_CONST: {
1397 emit_op(OP_PUTRETI, res.idx, 0, 0, node, chunk);
1398 } break;
1399 case COMP_REG: {
1400 emit_op(OP_PUTRET, res.idx, 0, 0, node, chunk);
1401 } break;
1402 case COMP_NIL: break;
1403 default: {
1404 emit_compile_err(compiler, chunk, node);
1405 return (CompResult){.type = COMP_ERR};
1406 } break;
1407 }
1408 break;
1409 }
1410
1411 emit_op(OP_RET, 0, 0, 0, node, chunk);
1412 return (CompResult){.type = COMP_RET};
1413}
1414
897Chunk * 1415Chunk *
898chunk_alloc(Chunk *parent) { 1416chunk_alloc(Chunk *parent) {
899 static sz chunk_idx = 1; 1417 static sz chunk_idx = 1;
@@ -905,50 +1423,452 @@ chunk_alloc(Chunk *parent) {
905 return chunk; 1423 return chunk;
906} 1424}
907 1425
908CompResult 1426void
909compile_function(Chunk *chunk, Node *node) { 1427verify_chunk(Chunk *chunk) {
910 Chunk *func = chunk_alloc(chunk); 1428 if (chunk->const_idx >= 256) {
911 func->name = node->unique_name; 1429 eprintln("too many constants on chunk %s", chunk->id);
1430 exit(EXIT_FAILURE);
1431 }
1432 if (chunk->str_idx >= 256) {
1433 eprintln("too many strings on chunk %s", chunk->id);
1434 exit(EXIT_FAILURE);
1435 }
1436 if (chunk->reg_idx >= 256) {
1437 eprintln("too many registers used on chunk %s", chunk->id);
1438 exit(EXIT_FAILURE);
1439 }
1440 if (chunk->labels_idx >= 256) {
1441 eprintln("too many labels used on chunk %s", chunk->id);
1442 exit(EXIT_FAILURE);
1443 }
1444 if (chunk->fun_idx >= 256) {
1445 eprintln("too many functions on chunk %s", chunk->id);
1446 exit(EXIT_FAILURE);
1447 }
1448}
1449
1450void
1451declare_function(Chunk *chunk, Node *node) {
1452 Str name = node->unique_name;
1453 FunctionMap *map = funcmap_lookup(&chunk->funmap, node->unique_name);
1454 if (map) {
1455 return;
1456 }
912 Function fun = (Function){ 1457 Function fun = (Function){
913 .name = func->name, 1458 .name = name,
914 .index = chunk->fun_idx++, 1459 .index = chunk->fun_idx++,
915 .param_arity = array_size(node->func_params), 1460 .param_arity = array_size(node->func.params),
916 .return_arity = array_size(node->func_ret), 1461 .return_arity = array_size(node->func.ret),
917 }; 1462 };
918 funcmap_insert(&chunk->funmap, func->name, fun, chunk->storage); 1463 funcmap_insert(&chunk->funmap, node->unique_name, fun, chunk->storage);
1464}
1465
1466CompResult
1467compile_function(Compiler *compiler, Chunk *chunk, Node *node) {
1468 // The current activation record procedure for the VM is as follows:
1469 //
1470 // [caller][callee ]
1471 // [ .... ][ RET VAL ][ PARAMS ][ LOCALS ][ REGISTERS ][ RET META ]
1472 // ^
1473 // frame pointer
1474 //
1475 // The caller is responsible for allocating the return memory and the
1476 // parameter memory and filling the param data before OP_CALL.
1477 //
1478 chunk = &compiler->main_chunk;
1479 Chunk *func = chunk_alloc(chunk);
1480 func->name = node->unique_name;
1481 declare_function(chunk, node);
919 array_push(chunk->functions, func, chunk->storage); 1482 array_push(chunk->functions, func, chunk->storage);
920 1483
1484 // Push arguments as locals.
1485 for (sz i = 0; i < array_size(node->func.params); i++) {
1486 Node *param = node->func.params[i];
1487 Str name = param->unique_name;
1488 Str type = param->type;
1489 sz arr_size = 0;
1490 if (str_has_prefix(type, cstr("@"))) {
1491 if (param->var.type && param->var.type->kind == NODE_ARR_TYPE &&
1492 param->var.type->sym.arr_size->value.i > 0) {
1493 arr_size = param->var.type->sym.arr_size->value.i;
1494 }
1495 }
1496 add_variable(compiler, func, name, type, arr_size);
1497 }
1498 func->param_off = func->var_off;
1499
1500 // Compiling the body.
1501 CompResult res = compile_expr(compiler, func, node->func.body);
1502
921 // Put return values into memory. 1503 // Put return values into memory.
922 CompResult res = compile_expr(func, node->func_body);
923 switch (res.type) { 1504 switch (res.type) {
924 case COMP_CONST: { 1505 case COMP_CONST: {
925 EMIT_OP(OP_PUTRETI, res.idx, 0, 0, node, func); 1506 emit_op(OP_PUTRETI, res.idx, 0, 0, node, func);
926 } break; 1507 } break;
927 case COMP_REG: { 1508 case COMP_REG: {
928 EMIT_OP(OP_PUTRET, res.idx, 0, 0, node, func); 1509 emit_op(OP_PUTRET, res.idx, 0, 0, node, func);
929 } break; 1510 } break;
930 default: break; 1511 default: break;
931 } 1512 }
932 1513
933 // TODO: handle captured locals/globals? 1514 emit_op(OP_RET, 0, 0, 0, node, func);
934 EMIT_OP(OP_RET, 0, 0, 0, node, func); 1515 verify_chunk(func);
1516 return (CompResult){.type = COMP_NIL};
1517}
1518
1519CompResult
1520compile_let(Compiler *compiler, Chunk *chunk, Node *node) {
1521 sz op_ldaddr = OP_LDLADDR;
1522 if (chunk == &compiler->main_chunk) {
1523 op_ldaddr = OP_LDGADDR;
1524 }
1525 Str name = node->unique_name;
1526 Str type_name = node->var.name->type;
1527 sz arr_size = 0;
1528 if (str_has_prefix(type_name, cstr("@"))) {
1529 if (node->var.type && node->var.type->kind == NODE_ARR_TYPE &&
1530 node->var.type->sym.arr_size->value.i > 0) {
1531 arr_size = node->var.type->sym.arr_size->value.i;
1532 }
1533 }
1534
1535 sz idx = add_variable(compiler, chunk, name, type_name, arr_size);
1536 StrVarMap *map = varmap_lookup(&chunk->varmap, name);
1537 Variable var = map->val;
1538 Type type = map->val.type;
1539
1540 // Value.
1541 if (node->var.val) {
1542 CompResult res = compile_expr(compiler, chunk, node->var.val);
1543 switch (res.type) {
1544 case COMP_CONST: {
1545 sz reg_addr = chunk->reg_idx++;
1546 sz reg_dst = chunk->reg_idx++;
1547 emit_op(op_ldaddr, reg_addr, idx, 0, node, chunk);
1548 emit_op(OP_LDCONST, reg_dst, res.idx, 0, node, chunk);
1549
1550 emit_sized_op(type.size, OP_ST64K, OP_ST32K, OP_ST16K, OP_ST8K,
1551 reg_dst, reg_addr, 0, node, chunk);
1552 } break;
1553 case COMP_REG: {
1554 sz reg_addr = chunk->reg_idx++;
1555 sz reg_val = res.idx;
1556 // FIXME: Not working properly for array copies from a pointer
1557 // because the type is Ptr instead of S32?
1558 emit_op(op_ldaddr, reg_addr, idx, 0, node, chunk);
1559 emit_sized_op(type.size, OP_ST64K, OP_ST32K, OP_ST16K, OP_ST8K,
1560 reg_val, reg_addr, 0, node, chunk);
1561 if (type.size > 8) {
1562 sz reg_dst = chunk->reg_idx++;
1563 for (sz i = 0; i < var.size / 8; i++) {
1564 sz offset = add_constant(chunk, i);
1565 emit_op(OP_LD64I, reg_dst, reg_val, offset, node,
1566 chunk);
1567 emit_op(OP_ST64I, reg_dst, reg_addr, offset, node,
1568 chunk);
1569 }
1570 }
1571 } break;
1572 case COMP_STRING: {
1573 // Get the address for the string value variable.
1574 sz str_addr = chunk->reg_idx++;
1575 emit_op(OP_LDSTR, str_addr, res.idx, 0, node->var.val, chunk);
1576
1577 // Get the address for the local/global storage
1578 // variable.
1579 sz var_addr = chunk->reg_idx++;
1580 emit_op(op_ldaddr, var_addr, idx, 0, node, chunk);
1581
1582 // Copy the fat pointer.
1583 emit_fat_copy(chunk, node, var_addr, str_addr);
1584 } break;
1585 default: {
1586 emit_compile_err(compiler, chunk, node);
1587 return (CompResult){.type = COMP_ERR};
1588 } break;
1589 }
1590 }
1591
1592 return (CompResult){.type = COMP_NIL};
1593}
1594
1595CompResult
1596compile_set(Compiler *compiler, Chunk *chunk, Node *node) {
1597 Str name = node->unique_name;
1598 StrVarMap *map = NULL;
1599 Chunk *next = chunk;
1600 while (next) {
1601 map = varmap_lookup(&next->varmap, name);
1602 if (map) {
1603 break;
1604 }
1605 next = chunk->parent;
1606 }
1607 if (!map) {
1608 emit_compile_err(compiler, chunk, node);
1609 return (CompResult){.type = COMP_ERR};
1610 }
1611 sz op_ldaddr = OP_LDLADDR;
1612 sz op_ldvar = OP_LDLVAR;
1613 if (next == &compiler->main_chunk) {
1614 op_ldaddr = OP_LDGADDR;
1615 op_ldvar = OP_LDGVAR;
1616 }
1617 Variable var = map->val;
1618 Type type = map->val.type;
1619 sz idx = map->val.idx;
1620
1621 CompResult res = compile_expr(compiler, chunk, node->var.val);
1622 if (node->var.name->kind == NODE_SYMBOL_IDX) {
1623 // Value.
1624 sz reg_val;
1625 switch (res.type) {
1626 case COMP_CONST: {
1627 reg_val = chunk->reg_idx++;
1628 emit_op(OP_LDCONST, reg_val, res.idx, 0, node, chunk);
1629 } break;
1630 case COMP_REG: {
1631 reg_val = res.idx;
1632 } break;
1633 default: {
1634 emit_compile_err(compiler, chunk, node);
1635 return (CompResult){.type = COMP_ERR};
1636 } break;
1637 }
1638
1639 // Address.
1640 sz reg_addr = chunk->reg_idx++;
1641 // Is this a pointer access or an array access?
1642 if (str_has_prefix(map->val.type_name, cstr("[]"))) {
1643 emit_op(op_ldaddr, reg_addr, map->val.idx, 0, node->var.val, chunk);
1644 } else {
1645 emit_op(op_ldvar, reg_addr, map->val.idx, 0, node->var.val, chunk);
1646 }
1647
1648 // Index.
1649 CompResult res_idx =
1650 compile_expr(compiler, chunk, node->var.name->sym.arr_size);
1651 switch (res_idx.type) {
1652 case COMP_CONST: {
1653 emit_sized_op(type.size, OP_ST64I, OP_ST32I, OP_ST16I, OP_ST8I,
1654 reg_val, reg_addr, res_idx.idx, node, chunk);
1655 } break;
1656 case COMP_REG: {
1657 emit_sized_op(type.size, OP_ST64, OP_ST32, OP_ST16, OP_ST8,
1658 reg_val, reg_addr, res_idx.idx, node, chunk);
1659 } break;
1660 case COMP_STRING: {
1661 // Get the address for the string value variable.
1662 sz str_addr = chunk->reg_idx++;
1663 emit_op(OP_LDSTR, str_addr, res.idx, 0, node->var.val, chunk);
1664
1665 // Get the address for the local/global storage
1666 // variable.
1667 sz var_addr = chunk->reg_idx++;
1668 emit_op(op_ldaddr, var_addr, idx, 0, node, chunk);
1669
1670 // Copy the fat pointer.
1671 emit_fat_copy(chunk, node, var_addr, str_addr);
1672 } break;
1673 default: {
1674 emit_compile_err(compiler, chunk, node);
1675 return (CompResult){.type = COMP_ERR};
1676 } break;
1677 }
1678 return (CompResult){.type = COMP_NIL};
1679 } else if (node->var.name->kind == NODE_DEREF) {
1680 // Value.
1681 sz reg_val;
1682 switch (res.type) {
1683 case COMP_CONST: {
1684 reg_val = chunk->reg_idx++;
1685 emit_op(OP_LDCONST, reg_val, res.idx, 0, node, chunk);
1686 } break;
1687 case COMP_REG: {
1688 reg_val = res.idx;
1689 } break;
1690 default: {
1691 emit_compile_err(compiler, chunk, node);
1692 return (CompResult){.type = COMP_ERR};
1693 } break;
1694 }
1695
1696 Node *next = node->var.name->deref.next;
1697 sz n_deref = 0;
1698 while (next) {
1699 n_deref++;
1700 if (next->kind == NODE_SYMBOL) {
1701 break;
1702 }
1703 next = next->deref.next;
1704 }
1705 CompResult res = compile_expr(compiler, chunk, next);
1706 sz reg_src = res.idx;
1707 sz reg_dst = reg_src;
1708 for (sz i = 0; i < n_deref - 1; i++) {
1709 reg_dst = chunk->reg_idx++;
1710 emit_op(OP_LD64K, reg_dst, reg_src, 0, node, chunk);
1711 reg_src = reg_dst;
1712 }
1713 emit_sized_op(type.size, OP_ST64K, OP_ST32K, OP_ST16K, OP_ST8K, reg_val,
1714 reg_dst, 0, node, chunk);
1715
1716 return (CompResult){.type = COMP_NIL};
1717 }
1718
1719 switch (res.type) {
1720 case COMP_CONST: {
1721 sz reg_addr = chunk->reg_idx++;
1722 sz reg_dst = chunk->reg_idx++;
1723 emit_op(op_ldaddr, reg_addr, idx, 0, node, chunk);
1724 emit_op(OP_LDCONST, reg_dst, res.idx, 0, node, chunk);
1725 emit_sized_op(type.size, OP_ST64K, OP_ST32K, OP_ST16K, OP_ST8K,
1726 reg_dst, reg_addr, 0, node, chunk);
1727 } break;
1728 case COMP_REG: {
1729 sz reg_addr = chunk->reg_idx++;
1730 sz reg_val = res.idx;
1731 emit_op(op_ldaddr, reg_addr, idx, 0, node, chunk);
1732 emit_sized_op(type.size, OP_ST64K, OP_ST32K, OP_ST16K, OP_ST8K,
1733 reg_val, reg_addr, 0, node, chunk);
1734 if (type.size > 8) {
1735 sz reg_dst = chunk->reg_idx++;
1736 for (sz i = 0; i < var.size / 8; i++) {
1737 sz offset = add_constant(chunk, i);
1738 emit_op(OP_LD64I, reg_dst, reg_val, offset, node, chunk);
1739 emit_op(OP_ST64I, reg_dst, reg_addr, offset, node, chunk);
1740 }
1741 }
1742 } break;
1743 case COMP_STRING: {
1744 // Get the address for the string value variable.
1745 sz str_addr = chunk->reg_idx++;
1746 emit_op(OP_LDSTR, str_addr, res.idx, 0, node->var.val, chunk);
1747
1748 // Get the address for the local/global storage
1749 // variable.
1750 sz var_addr = chunk->reg_idx++;
1751 emit_op(op_ldaddr, var_addr, idx, 0, node, chunk);
1752
1753 // Copy the fat pointer.
1754 emit_fat_copy(chunk, node, var_addr, str_addr);
1755 } break;
1756 default: {
1757 emit_compile_err(compiler, chunk, node);
1758 return (CompResult){.type = COMP_ERR};
1759 } break;
1760 }
935 return (CompResult){.type = COMP_NIL}; 1761 return (CompResult){.type = COMP_NIL};
936} 1762}
937 1763
938CompResult 1764CompResult
939compile_expr(Chunk *chunk, Node *node) { 1765compile_symbol(Compiler *compiler, Chunk *chunk, Node *node) {
1766 Str name = node->unique_name;
1767 StrVarMap *map = NULL;
1768 Chunk *next = chunk;
1769 while (next) {
1770 map = varmap_lookup(&next->varmap, name);
1771 if (map) {
1772 break;
1773 }
1774 next = next->parent;
1775 }
1776 if (!map) {
1777 emit_compile_err(compiler, chunk, node);
1778 return (CompResult){.type = COMP_ERR};
1779 }
1780 sz op_ldaddr = OP_LDLADDR;
1781 if (next == &compiler->main_chunk) {
1782 op_ldaddr = OP_LDGADDR;
1783 }
1784 Variable var = map->val;
1785 Type type = map->val.type;
1786 sz reg_dst = chunk->reg_idx++;
1787 // TODO: ...
1788 // if (node->is_ptr || str_has_prefix(var.type_name, cstr("[]")) ||
1789 // str_eq(var.type_name, cstr("Str"))) {
1790 // emit_op(op_ldaddr, reg_dst, var.idx, 0, node, chunk);
1791 // } else {
1792 sz reg_addr = chunk->reg_idx++;
1793 emit_op(op_ldaddr, reg_addr, var.idx, 0, node, chunk);
1794 emit_sized_op(type.size, OP_LD64K, OP_LD32K, OP_LD16K, OP_LD8K, reg_dst,
1795 reg_addr, 0, node, chunk);
1796 // }
1797 return (CompResult){.type = COMP_REG, .idx = reg_dst};
1798}
1799
1800CompResult
1801compile_symbol_idx(Compiler *compiler, Chunk *chunk, Node *node) {
1802 Str name = node->unique_name;
1803 StrVarMap *map = NULL;
1804 Chunk *next = chunk;
1805 while (next) {
1806 map = varmap_lookup(&next->varmap, name);
1807 if (map) {
1808 break;
1809 }
1810 next = next->parent;
1811 }
1812 if (!map) {
1813 eprintln("couldn't resolve symbol name: %s", name);
1814 emit_compile_err(compiler, chunk, node);
1815 return (CompResult){.type = COMP_ERR};
1816 }
1817 sz op_ldaddr = OP_LDLADDR;
1818 sz op_ldvar = OP_LDLVAR;
1819 if (next == &compiler->main_chunk) {
1820 op_ldaddr = OP_LDGADDR;
1821 op_ldvar = OP_LDGVAR;
1822 }
1823
1824 // Destination.
1825 sz reg_dst = chunk->reg_idx++;
1826
1827 // Address.
1828 sz reg_addr = chunk->reg_idx++;
1829 if (str_has_prefix(map->val.type_name, cstr("[]"))) {
1830 emit_op(op_ldaddr, reg_addr, map->val.idx, 0, node->var.val, chunk);
1831 } else {
1832 emit_op(op_ldvar, reg_addr, map->val.idx, 0, node->var.val, chunk);
1833 }
1834
1835 Type type = map->val.type;
1836
1837 // Index.
1838 CompResult idx = compile_expr(compiler, chunk, node->sym.arr_size);
1839 switch (idx.type) {
1840 case COMP_CONST: {
1841 emit_sized_op(type.size, OP_LD64I, OP_LD32I, OP_LD16I, OP_LD8I,
1842 reg_dst, reg_addr, idx.idx, node, chunk);
1843 } break;
1844 case COMP_REG: {
1845 emit_sized_op(type.size, OP_LD64, OP_LD32, OP_LD16, OP_LD8, reg_dst,
1846 reg_addr, idx.idx, node, chunk);
1847 } break;
1848 default: {
1849 emit_compile_err(compiler, chunk, node);
1850 return (CompResult){.type = COMP_ERR};
1851 } break;
1852 }
1853 return (CompResult){.type = COMP_REG, .idx = reg_dst};
1854}
1855
1856CompResult
1857compile_expr(Compiler *compiler, Chunk *chunk, Node *node) {
940 switch (node->kind) { 1858 switch (node->kind) {
941 case NODE_FUN: return compile_function(chunk, node); 1859 case NODE_BREAK: return compile_break(compiler, chunk, node);
942 case NODE_FUNCALL: return compile_funcall(chunk, node); 1860 case NODE_CONTINUE: return compile_continue(compiler, chunk, node);
943 case NODE_WHILE: return compile_while(chunk, node); 1861 case NODE_RETURN: return compile_return(compiler, chunk, node);
944 case NODE_IF: return compile_if(chunk, node); 1862 case NODE_FUN: return compile_function(compiler, chunk, node);
945 case NODE_COND: return compile_cond(chunk, node); 1863 case NODE_FUNCALL: return compile_funcall(compiler, chunk, node);
1864 case NODE_WHILE: return compile_while(compiler, chunk, node);
1865 case NODE_IF: return compile_if(compiler, chunk, node);
1866 case NODE_COND: return compile_cond(compiler, chunk, node);
946 // Logic. 1867 // Logic.
947 // case NODE_XOR:
948 case NODE_BITNOT: 1868 case NODE_BITNOT:
949 case NODE_NOT: return compile_unary(chunk, node); break; 1869 case NODE_NOT: return compile_unary(compiler, chunk, node); break;
950 case NODE_AND: 1870 case NODE_AND:
951 case NODE_OR: 1871 case NODE_OR: return compile_binary_logic(compiler, chunk, node); break;
952 case NODE_EQ: 1872 case NODE_EQ:
953 case NODE_NEQ: 1873 case NODE_NEQ:
954 case NODE_LT: 1874 case NODE_LT:
@@ -957,6 +1877,7 @@ compile_expr(Chunk *chunk, Node *node) {
957 // Bitwise ops. 1877 // Bitwise ops.
958 case NODE_BITAND: 1878 case NODE_BITAND:
959 case NODE_BITOR: 1879 case NODE_BITOR:
1880 case NODE_BITXOR:
960 case NODE_BITLSHIFT: 1881 case NODE_BITLSHIFT:
961 case NODE_BITRSHIFT: 1882 case NODE_BITRSHIFT:
962 // Arithmetic. 1883 // Arithmetic.
@@ -965,7 +1886,7 @@ compile_expr(Chunk *chunk, Node *node) {
965 case NODE_SUB: 1886 case NODE_SUB:
966 case NODE_MUL: 1887 case NODE_MUL:
967 case NODE_DIV: 1888 case NODE_DIV:
968 case NODE_MOD: return compile_binary(chunk, node); break; 1889 case NODE_MOD: return compile_binary(compiler, chunk, node); break;
969 case NODE_TRUE: 1890 case NODE_TRUE:
970 case NODE_FALSE: 1891 case NODE_FALSE:
971 case NODE_NUM_FLOAT: 1892 case NODE_NUM_FLOAT:
@@ -986,192 +1907,74 @@ compile_expr(Chunk *chunk, Node *node) {
986 .idx = str_idx, 1907 .idx = str_idx,
987 }; 1908 };
988 } break; 1909 } break;
989 case NODE_LET: { 1910 case NODE_LET: return compile_let(compiler, chunk, node);
990 sz idx = array_size(chunk->vars); 1911 case NODE_SET: return compile_set(compiler, chunk, node);
991 Str name = node->unique_name; 1912 case NODE_SYMBOL: return compile_symbol(compiler, chunk, node);
992 Str type = node->var_name->type; 1913 case NODE_SYMBOL_IDX: return compile_symbol_idx(compiler, chunk, node);
993 sz size = 8; 1914 case NODE_PTR: {
994 // TODO: get type storage from a table to consider all the basic 1915 // Load and return address of associated symbol.
995 // types as well as user defined ones. 1916 Str name = node->t.next->unique_name;
996 if (str_eq(type, cstr("str"))) { 1917 sz op_ldaddr = OP_LDLADDR;
997 size = 16; 1918 if (chunk == &compiler->main_chunk) {
998 } 1919 op_ldaddr = OP_LDGADDR;
999 if (str_has_prefix(type, cstr("@"))) {
1000 if (node->var_type && node->var_type->kind == NODE_ARR_TYPE &&
1001 node->var_type->arr_size->value.i > 0) {
1002 // TODO: get the proper storage size for the multiplication.
1003 size *= node->var_type->arr_size->value.i;
1004 // FIXME: this should be done on the static analysis, plus,
1005 // we shouldn't be checking all these types by hand, but
1006 // using the symbol tables.
1007 type = str_remove_prefix(type, cstr("@"));
1008 type = str_concat(cstr("[]"), type, chunk->storage);
1009 }
1010 }
1011 Variable var = (Variable){
1012 .name = name,
1013 .type = type,
1014 .size = size,
1015 .offset = chunk->var_off,
1016 .idx = idx,
1017 };
1018 varmap_insert(&chunk->varmap, name, var, chunk->storage);
1019 array_push(chunk->vars, var, chunk->storage);
1020 chunk->var_off += size;
1021
1022 // Value.
1023 if (node->var_val) {
1024 CompResult res = compile_expr(chunk, node->var_val);
1025 switch (res.type) {
1026 case COMP_CONST: {
1027 EMIT_OP(OP_STGVARI, idx, res.idx, 0, node->var_val,
1028 chunk);
1029 } break;
1030 case COMP_REG: {
1031 EMIT_OP(OP_STGVAR, idx, res.idx, 0, node->var_val,
1032 chunk);
1033 } break;
1034 default: {
1035 return (CompResult){.type = COMP_ERR};
1036 } break;
1037 }
1038 } 1920 }
1039 1921
1040 return (CompResult){.type = COMP_NIL};
1041 } break;
1042 case NODE_SET: {
1043 Str name = node->unique_name;
1044 StrVarMap *map = varmap_lookup(&chunk->varmap, name); 1922 StrVarMap *map = varmap_lookup(&chunk->varmap, name);
1045 if (!map) { 1923 if (!map) {
1046 eprintln("error: node_set: symbol name not found: %s", name); 1924 emit_compile_err(compiler, chunk, node);
1047 }
1048 CompResult res = compile_expr(chunk, node->var_val);
1049 if (node->var_name->kind == NODE_SYMBOL_IDX) {
1050 // Value.
1051 sz reg_val;
1052 switch (res.type) {
1053 case COMP_CONST: {
1054 reg_val = chunk->reg_idx++;
1055 EMIT_OP(OP_LD64K, reg_val, res.idx, 0, node, chunk);
1056 } break;
1057 case COMP_REG: {
1058 reg_val = res.idx;
1059 } break;
1060 default: {
1061 return (CompResult){.type = COMP_ERR};
1062 } break;
1063 }
1064
1065 // Address.
1066 sz reg_addr = chunk->reg_idx++;
1067 // Is this a pointer access or an array access?
1068 if (str_has_prefix(map->val.type, cstr("[]"))) {
1069 EMIT_OP(OP_LDGADDR, reg_addr, map->val.idx, 0,
1070 node->var_val, chunk);
1071 } else {
1072 EMIT_OP(OP_LDGVAR, reg_addr, map->val.idx, 0, node->var_val,
1073 chunk);
1074 }
1075
1076 // Index.
1077 CompResult idx = compile_expr(chunk, node->var_name->arr_size);
1078 switch (idx.type) {
1079 case COMP_CONST: {
1080 EMIT_OP(OP_ST64I, reg_val, reg_addr, idx.idx, node,
1081 chunk);
1082 } break;
1083 case COMP_REG: {
1084 EMIT_OP(OP_ST64, reg_val, reg_addr, idx.idx, node,
1085 chunk);
1086 } break;
1087 default: {
1088 return (CompResult){.type = COMP_ERR};
1089 } break;
1090 }
1091 // TODO: offset should be in bytes, in this case we are assuming
1092 // 64bit types, hence ST64
1093 return (CompResult){.type = COMP_NIL};
1094 }
1095 switch (res.type) {
1096 case COMP_CONST: {
1097 EMIT_OP(OP_STGVARI, map->val.idx, res.idx, 0, node->var_val,
1098 chunk);
1099 } break;
1100 case COMP_REG: {
1101 EMIT_OP(OP_STGVAR, map->val.idx, res.idx, 0, node->var_val,
1102 chunk);
1103 } break;
1104 default: {
1105 return (CompResult){.type = COMP_ERR};
1106 } break;
1107 }
1108 return (CompResult){.type = COMP_NIL};
1109 } break;
1110 case NODE_SYMBOL: {
1111 Str name = node->unique_name;
1112 StrVarMap *map = varmap_lookup(&chunk->varmap, name);
1113 if (!map) {
1114 println("error: unreachable... name: %s", name);
1115 exit(EXIT_FAILURE);
1116 } 1925 }
1117 Variable var = map->val; 1926 Variable var = map->val;
1118 u8 reg_dst = chunk->reg_idx++;
1119 if (node->is_ptr) {
1120 EMIT_OP(OP_LDGADDR, reg_dst, var.idx, 0, node, chunk);
1121 } else {
1122 EMIT_OP(OP_LDGVAR, reg_dst, var.idx, 0, node, chunk);
1123 }
1124 return (CompResult){.type = COMP_REG, .idx = reg_dst};
1125 } break;
1126 case NODE_SYMBOL_IDX: {
1127 Str name = node->unique_name;
1128 StrVarMap *map = varmap_lookup(&chunk->varmap, name);
1129 if (!map) {
1130 println("error: unreachable... name: %s", name);
1131 exit(EXIT_FAILURE);
1132 }
1133 1927
1134 // Destination.
1135 u8 reg_dst = chunk->reg_idx++;
1136
1137 // Address.
1138 sz reg_addr = chunk->reg_idx++; 1928 sz reg_addr = chunk->reg_idx++;
1139 if (str_has_prefix(map->val.type, cstr("[]"))) { 1929 emit_op(op_ldaddr, reg_addr, var.idx, 0, node, chunk);
1140 EMIT_OP(OP_LDGADDR, reg_addr, map->val.idx, 0, node->var_val, 1930 return (CompResult){.type = COMP_REG, .idx = reg_addr};
1141 chunk); 1931 } break;
1142 } else { 1932 case NODE_DEREF: {
1143 EMIT_OP(OP_LDGVAR, reg_addr, map->val.idx, 0, node->var_val, 1933 Str type_name = node->type;
1144 chunk); 1934 if (str_has_prefix(type_name, cstr("@"))) {
1935 type_name = cstr("Ptr");
1145 } 1936 }
1146 1937 StrTypeMap *t = strtype_lookup(&compiler->type_map, type_name);
1147 // Index. 1938 sz size = t->val.size;
1148 CompResult idx = compile_expr(chunk, node->arr_size); 1939
1149 switch (idx.type) { 1940 Node *next = node->deref.next;
1150 case COMP_CONST: { 1941 sz n_deref = 0;
1151 EMIT_OP(OP_LD64I, reg_dst, reg_addr, idx.idx, node, chunk); 1942 while (next) {
1152 } break; 1943 n_deref++;
1153 case COMP_REG: { 1944 if (next->kind == NODE_SYMBOL) {
1154 EMIT_OP(OP_LD64, reg_dst, reg_addr, idx.idx, node, chunk); 1945 break;
1155 } break; 1946 }
1156 default: { 1947 next = next->deref.next;
1157 return (CompResult){.type = COMP_ERR}; 1948 }
1158 } break; 1949 CompResult res = compile_symbol(compiler, chunk, next);
1950 sz reg_dst = res.idx;
1951 sz reg_src = res.idx;
1952 for (sz i = 0; i < n_deref; i++) {
1953 reg_dst = chunk->reg_idx++;
1954 if (i == n_deref - 1) {
1955 emit_sized_op(size, OP_LD64K, OP_LD32K, OP_LD16K, OP_LD8K,
1956 reg_dst, reg_src, 0, node, chunk);
1957 } else {
1958 emit_op(OP_LD64K, reg_dst, reg_src, 0, node, chunk);
1959 }
1960 reg_src = reg_dst;
1159 } 1961 }
1160 // TODO: hardcoding the type size for now (LD64/LD64I).
1161 return (CompResult){.type = COMP_REG, .idx = reg_dst}; 1962 return (CompResult){.type = COMP_REG, .idx = reg_dst};
1162 } break; 1963 } break;
1163 case NODE_BLOCK: { 1964 case NODE_BLOCK: {
1164 CompResult res; 1965 CompResult res;
1165 for (sz i = 0; i < array_size(node->elements); i++) { 1966 for (sz i = 0; i < array_size(node->elements); i++) {
1166 Node *root = node->elements[i]; 1967 Node *root = node->elements[i];
1167 res = compile_expr(chunk, root); 1968 res = compile_expr(compiler, chunk, root);
1168 } 1969 }
1169 return res; 1970 return res;
1170 } break; 1971 } break;
1972 case NODE_NIL: return (CompResult){.type = COMP_NIL};
1171 default: { 1973 default: {
1172 eprintln("error: compilation not implemented for node %s", 1974 eprintln("error: compilation not implemented for node %s",
1173 node_str[node->kind]); 1975 node_str[node->kind]);
1174 exit(EXIT_FAILURE); 1976 emit_compile_err(compiler, chunk, node);
1977 return (CompResult){.type = COMP_ERR};
1175 } break; 1978 } break;
1176 } 1979 }
1177 return (CompResult){.type = COMP_ERR}; 1980 return (CompResult){.type = COMP_ERR};
@@ -1188,6 +1991,14 @@ disassemble_instruction(Instruction instruction) {
1188 case OP_MOV16: 1991 case OP_MOV16:
1189 case OP_MOV32: 1992 case OP_MOV32:
1190 case OP_MOV64: 1993 case OP_MOV64:
1994 case OP_LD8K:
1995 case OP_LD16K:
1996 case OP_LD32K:
1997 case OP_LD64K:
1998 case OP_ST8K:
1999 case OP_ST16K:
2000 case OP_ST32K:
2001 case OP_ST64K:
1191 println("%s r%d, r%d", op_str[instruction.op], instruction.dst, 2002 println("%s r%d, r%d", op_str[instruction.op], instruction.dst,
1192 instruction.a, instruction.b); 2003 instruction.a, instruction.b);
1193 break; 2004 break;
@@ -1196,10 +2007,7 @@ disassemble_instruction(Instruction instruction) {
1196 println("%s l%d, r%d", op_str[instruction.op], instruction.dst, 2007 println("%s l%d, r%d", op_str[instruction.op], instruction.dst,
1197 instruction.a, instruction.b); 2008 instruction.a, instruction.b);
1198 break; 2009 break;
1199 case OP_LD8K: 2010 case OP_LDCONST:
1200 case OP_LD16K:
1201 case OP_LD32K:
1202 case OP_LD64K:
1203 println("%s r%d, c%d", op_str[instruction.op], instruction.dst, 2011 println("%s r%d, c%d", op_str[instruction.op], instruction.dst,
1204 instruction.a, instruction.b); 2012 instruction.a, instruction.b);
1205 break; 2013 break;
@@ -1233,6 +2041,7 @@ disassemble_instruction(Instruction instruction) {
1233 case OP_BITRSHIFTI: 2041 case OP_BITRSHIFTI:
1234 case OP_BITANDI: 2042 case OP_BITANDI:
1235 case OP_BITORI: 2043 case OP_BITORI:
2044 case OP_BITXORI:
1236 println("%s r%d, r%d, c%d", op_str[instruction.op], instruction.dst, 2045 println("%s r%d, r%d, c%d", op_str[instruction.op], instruction.dst,
1237 instruction.a, instruction.b); 2046 instruction.a, instruction.b);
1238 break; 2047 break;
@@ -1266,19 +2075,28 @@ disassemble_instruction(Instruction instruction) {
1266 case OP_BITRSHIFT: 2075 case OP_BITRSHIFT:
1267 case OP_BITAND: 2076 case OP_BITAND:
1268 case OP_BITOR: 2077 case OP_BITOR:
2078 case OP_BITXOR:
1269 println("%s r%d, r%d, r%d", op_str[instruction.op], instruction.dst, 2079 println("%s r%d, r%d, r%d", op_str[instruction.op], instruction.dst,
1270 instruction.a, instruction.b); 2080 instruction.a, instruction.b);
1271 break; 2081 break;
1272 case OP_LDGVAR: 2082 case OP_LDGVAR:
1273 case OP_LDGADDR: 2083 case OP_LDGADDR:
2084 case OP_LDLVAR:
2085 case OP_LDLADDR:
1274 println("%s r%d, v%d", op_str[instruction.op], instruction.dst, 2086 println("%s r%d, v%d", op_str[instruction.op], instruction.dst,
1275 instruction.a, instruction.b); 2087 instruction.a, instruction.b);
1276 break; 2088 break;
2089 case OP_LDSTR:
2090 println("%s r%d, s%d", op_str[instruction.op], instruction.dst,
2091 instruction.a, instruction.b);
2092 break;
1277 case OP_STGVAR: 2093 case OP_STGVAR:
2094 case OP_STLVAR:
1278 println("%s v%d, r%d", op_str[instruction.op], instruction.dst, 2095 println("%s v%d, r%d", op_str[instruction.op], instruction.dst,
1279 instruction.a, instruction.b); 2096 instruction.a, instruction.b);
1280 break; 2097 break;
1281 case OP_STGVARI: 2098 case OP_STGVARI:
2099 case OP_STLVARI:
1282 println("%s v%d, c%d", op_str[instruction.op], instruction.dst, 2100 println("%s v%d, c%d", op_str[instruction.op], instruction.dst,
1283 instruction.a, instruction.b); 2101 instruction.a, instruction.b);
1284 break; 2102 break;
@@ -1301,17 +2119,36 @@ disassemble_instruction(Instruction instruction) {
1301 println("%s l%d, c%d", op_str[instruction.op], instruction.dst, 2119 println("%s l%d, c%d", op_str[instruction.op], instruction.dst,
1302 instruction.a, instruction.b); 2120 instruction.a, instruction.b);
1303 break; 2121 break;
2122 case OP_PRINTS8:
2123 case OP_PRINTS16:
2124 case OP_PRINTS32:
1304 case OP_PRINTS64: 2125 case OP_PRINTS64:
2126 case OP_PRINTU8:
2127 case OP_PRINTU16:
2128 case OP_PRINTU32:
2129 case OP_PRINTU64:
2130 case OP_PRINTF32:
1305 case OP_PRINTF64: 2131 case OP_PRINTF64:
1306 case OP_PRINTSTR: 2132 case OP_PRINTSTR:
2133 case OP_PRINTBOOL:
1307 case OP_PUSH: 2134 case OP_PUSH:
1308 case OP_POP: 2135 case OP_POP:
1309 case OP_PUTRET: 2136 case OP_PUTRET:
1310 println("%s r%d", op_str[instruction.op], instruction.dst, 2137 println("%s r%d", op_str[instruction.op], instruction.dst,
1311 instruction.a, instruction.b); 2138 instruction.a, instruction.b);
1312 break; 2139 break;
2140 case OP_PRINTSTRI:
2141 case OP_PRINTS8I:
2142 case OP_PRINTS16I:
2143 case OP_PRINTS32I:
1313 case OP_PRINTS64I: 2144 case OP_PRINTS64I:
2145 case OP_PRINTU8I:
2146 case OP_PRINTU16I:
2147 case OP_PRINTU32I:
2148 case OP_PRINTU64I:
2149 case OP_PRINTF32I:
1314 case OP_PRINTF64I: 2150 case OP_PRINTF64I:
2151 case OP_PRINTBOOLI:
1315 case OP_RESERVE: 2152 case OP_RESERVE:
1316 case OP_PUSHI: 2153 case OP_PUSHI:
1317 case OP_PUTRETI: 2154 case OP_PUTRETI:
@@ -1319,6 +2156,7 @@ disassemble_instruction(Instruction instruction) {
1319 instruction.a, instruction.b); 2156 instruction.a, instruction.b);
1320 break; 2157 break;
1321 case OP_RET: 2158 case OP_RET:
2159 case OP_RECUR:
1322 case OP_HALT: println("%s", op_str[instruction.op]); break; 2160 case OP_HALT: println("%s", op_str[instruction.op]); break;
1323 default: println("Unknown opcode %d", instruction.op); break; 2161 default: println("Unknown opcode %d", instruction.op); break;
1324 } 2162 }
@@ -1336,11 +2174,25 @@ disassemble_chunk(Chunk chunk) {
1336 for (sz i = 0; i < array_size(chunk.code); i++) { 2174 for (sz i = 0; i < array_size(chunk.code); i++) {
1337 printf(" %.4ld:%.4ld %.4lx ", chunk.linecol[i].line, 2175 printf(" %.4ld:%.4ld %.4lx ", chunk.linecol[i].line,
1338 chunk.linecol[i].col, i); 2176 chunk.linecol[i].col, i);
1339 IntIntMap *label = intintmap_lookup(&chunk.labels_rev, i); 2177 IntIntMapIter lab_it = intintmap_iterator(chunk.labels, chunk.storage);
1340 if (label) { 2178 IntIntMap *m = intintmap_next(&lab_it, chunk.storage);
1341 printf(".L%.2ld ", label->val); 2179 Str labs = cstr("");
2180 while (m) {
2181 if (m->val == i) {
2182 labs = str_concat(labs, cstr(".L"), chunk.storage);
2183 labs = str_concat(labs, str_from_int(m->key, chunk.storage),
2184 chunk.storage);
2185 break;
2186 }
2187 m = intintmap_next(&lab_it, chunk.storage);
2188 }
2189 if (labs.size) {
2190 print("%s", labs);
2191 for (sz i = 0; i < 7 - labs.size; i++) {
2192 print(" ");
2193 }
1342 } else { 2194 } else {
1343 printf(" %2s ", ""); 2195 printf(" ");
1344 } 2196 }
1345 disassemble_instruction(chunk.code[i]); 2197 disassemble_instruction(chunk.code[i]);
1346 } 2198 }
@@ -1361,7 +2213,7 @@ disassemble_chunk(Chunk chunk) {
1361 for (sz i = 0; i < array_size(chunk.vars); i++) { 2213 for (sz i = 0; i < array_size(chunk.vars); i++) {
1362 println(" %x{2}: [%x{4}:%x{4}] %s: %s", i, chunk.vars[i].offset, 2214 println(" %x{2}: [%x{4}:%x{4}] %s: %s", i, chunk.vars[i].offset,
1363 chunk.vars[i].offset + chunk.vars[i].size, 2215 chunk.vars[i].offset + chunk.vars[i].size,
1364 chunk.vars[i].name, chunk.vars[i].type); 2216 chunk.vars[i].name, chunk.vars[i].type_name);
1365 } 2217 }
1366 } 2218 }
1367 if (array_size(chunk.functions) > 0) { 2219 if (array_size(chunk.functions) > 0) {
@@ -1378,4 +2230,75 @@ disassemble_chunk(Chunk chunk) {
1378 } 2230 }
1379} 2231}
1380 2232
2233void
2234bytecode_compiler(Compiler *compiler, Parser parser) {
2235 compiler->main_chunk = (Chunk){
2236 .file_name = compiler->file_name,
2237 .storage = compiler->storage,
2238 .name = cstr(".main"),
2239 };
2240 array_zero(compiler->main_chunk.constants, 256, compiler->storage);
2241 array_zero(compiler->main_chunk.code, 0xffff, compiler->storage);
2242 sz n_roots = array_size(parser.nodes);
2243
2244 // Fill up builtin types and tables.
2245 for (sz i = 0; i < LEN(builtin_types); i++) {
2246 Type type = builtin_types[i];
2247 strtype_insert(&compiler->type_map, type.unique_name, type,
2248 compiler->storage);
2249 }
2250 Str unsigned_ints[] = {
2251 cstr("U8"), cstr("U16"), cstr("U32"),
2252 cstr("U64"), cstr("Ptr"), cstr("UInt"),
2253 };
2254 for (sz i = 0; i < LEN(unsigned_ints); i++) {
2255 Str type = unsigned_ints[i];
2256 strset_insert(&compiler->unsigned_ints, type, compiler->storage);
2257 }
2258 Str signed_ints[] = {
2259 cstr("S8"), cstr("S16"), cstr("S32"), cstr("S64"), cstr("Int"),
2260 };
2261 for (sz i = 0; i < LEN(signed_ints); i++) {
2262 Str type = signed_ints[i];
2263 strset_insert(&compiler->signed_ints, type, compiler->storage);
2264 }
2265
2266 // Do a first pass to setup the function declarations on the main scope.
2267 Chunk *chunk = &compiler->main_chunk;
2268 for (sz i = 0; i < n_roots; i++) {
2269 Node *root = parser.nodes[i];
2270 if (root->kind == NODE_FUN) {
2271 declare_function(chunk, root);
2272 }
2273 }
2274
2275 // Compile all root expressions.
2276 CompResult res = {0};
2277 for (sz i = 0; i < n_roots; i++) {
2278 Node *root = parser.nodes[i];
2279 res = compile_expr(compiler, chunk, root);
2280 }
2281
2282 // Make sure the last result is on r0.
2283 sz res_reg = 0;
2284 bool is_nil = false;
2285 switch (res.type) {
2286 case COMP_CONST: {
2287 res_reg = chunk->reg_idx++;
2288 Instruction inst =
2289 (Instruction){.op = OP_LDCONST, .dst = res_reg, .a = res.idx};
2290 array_push(chunk->code, inst, chunk->storage);
2291 } break;
2292 case COMP_REG: {
2293 res_reg = res.idx;
2294 } break;
2295 case COMP_NIL: {
2296 is_nil = true;
2297 } break;
2298 default: break;
2299 }
2300 emit_op(OP_HALT, res_reg, !is_nil, 0, NULL, chunk);
2301 verify_chunk(chunk);
2302}
2303
1381#endif // COMPILER_C 2304#endif // COMPILER_C
diff --git a/src/lexer.c b/src/lexer.c
index 2feba2a..84b69e7 100644
--- a/src/lexer.c
+++ b/src/lexer.c
@@ -41,18 +41,24 @@ 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, // !
54 TOK_AND, // && 60 TOK_AND, // and
55 TOK_OR, // || 61 TOK_OR, // or
56 TOK_EQ, // == 62 TOK_EQ, // ==
57 TOK_NEQ, // != 63 TOK_NEQ, // !=
58 TOK_LT, // < 64 TOK_LT, // <
@@ -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"),
@@ -432,6 +456,10 @@ scan_token(Scanner *scanner) {
432 *scanner = current; 456 *scanner = current;
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 '-': {
@@ -440,11 +468,33 @@ scan_token(Scanner *scanner) {
440 *scanner = current; 468 *scanner = current;
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,22 +533,33 @@ 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 if (scan_peek(scanner) == '=') {
489 scan_next(scanner); 554 scan_next(scanner);
490 return emit_token(current, scanner, TOK_AND); 555 return emit_token(current, scanner, TOK_BITOR_ASSIGN);
491 } 556 }
492 return emit_token(current, scanner, TOK_BITAND); 557 return emit_token(current, scanner, TOK_BITAND);
493 }; 558 };
494 case '|': { 559 case '|': {
495 if (scan_peek(scanner) == '|') { 560 if (scan_peek(scanner) == '=') {
496 scan_next(scanner); 561 scan_next(scanner);
497 return emit_token(current, scanner, TOK_OR); 562 return emit_token(current, scanner, TOK_BITOR_ASSIGN);
498 } 563 }
499 return emit_token(current, scanner, TOK_BITOR); 564 return emit_token(current, scanner, TOK_BITOR);
500 }; 565 };
@@ -535,78 +600,91 @@ scan_token(Scanner *scanner) {
535 return emit_token_err(&current, cstr("unexpected character")); 600 return emit_token_err(&current, cstr("unexpected character"));
536 } 601 }
537 switch (val.mem[0]) { 602 switch (val.mem[0]) {
603 case 'a': {
604 if (str_eq(val, cstr("and"))) {
605 return emit_token(current, scanner, TOK_AND);
606 }
607 } break;
538 case 'b': { 608 case 'b': {
539 if (str_has_prefix(val, cstr("break"))) { 609 if (str_eq(val, cstr("break"))) {
540 return emit_token(current, scanner, TOK_BREAK); 610 return emit_token(current, scanner, TOK_BREAK);
541 } 611 }
542 } break; 612 } break;
543 case 'c': { 613 case 'c': {
544 if (str_has_prefix(val, cstr("case"))) { 614 if (str_eq(val, cstr("case"))) {
545 return emit_token(current, scanner, TOK_CASE); 615 return emit_token(current, scanner, TOK_CASE);
546 } 616 }
547 if (str_has_prefix(val, cstr("continue"))) { 617 if (str_eq(val, cstr("continue"))) {
548 return emit_token(current, scanner, TOK_CONTINUE); 618 return emit_token(current, scanner, TOK_CONTINUE);
549 } 619 }
550 if (str_has_prefix(val, cstr("cond"))) { 620 if (str_eq(val, cstr("cond"))) {
551 return emit_token(current, scanner, TOK_COND); 621 return emit_token(current, scanner, TOK_COND);
552 } 622 }
553 } break; 623 } break;
554 case 'e': { 624 case 'e': {
555 if (str_has_prefix(val, cstr("else"))) { 625 if (str_eq(val, cstr("else"))) {
556 return emit_token(current, scanner, TOK_ELSE); 626 return emit_token(current, scanner, TOK_ELSE);
557 } 627 }
558 if (str_has_prefix(val, cstr("enum"))) { 628 if (str_eq(val, cstr("enum"))) {
559 return emit_token(current, scanner, TOK_ENUM); 629 return emit_token(current, scanner, TOK_ENUM);
560 } 630 }
561 } break; 631 } break;
562 case 'f': { 632 case 'f': {
563 if (str_has_prefix(val, cstr("false"))) { 633 if (str_eq(val, cstr("false"))) {
564 return emit_token(current, scanner, TOK_FALSE); 634 return emit_token(current, scanner, TOK_FALSE);
565 } 635 }
566 if (str_has_prefix(val, cstr("fun"))) { 636 if (str_eq(val, cstr("fun"))) {
567 return emit_token(current, scanner, TOK_FUN); 637 return emit_token(current, scanner, TOK_FUN);
568 } 638 }
639 if (str_eq(val, cstr("for"))) {
640 return emit_token(current, scanner, TOK_FOR);
641 }
569 } break; 642 } break;
570 case 'i': { 643 case 'i': {
571 if (str_has_prefix(val, cstr("if"))) { 644 if (str_eq(val, cstr("if"))) {
572 return emit_token(current, scanner, TOK_IF); 645 return emit_token(current, scanner, TOK_IF);
573 } 646 }
574 } break; 647 } break;
575 case 'l': { 648 case 'l': {
576 if (str_has_prefix(val, cstr("let"))) { 649 if (str_eq(val, cstr("let"))) {
577 return emit_token(current, scanner, TOK_LET); 650 return emit_token(current, scanner, TOK_LET);
578 } 651 }
579 } break; 652 } break;
580 case 'm': { 653 case 'm': {
581 if (str_has_prefix(val, cstr("match"))) { 654 if (str_eq(val, cstr("match"))) {
582 return emit_token(current, scanner, TOK_MATCH); 655 return emit_token(current, scanner, TOK_MATCH);
583 } 656 }
584 } break; 657 } break;
585 case 'n': { 658 case 'n': {
586 if (str_has_prefix(val, cstr("nil"))) { 659 if (str_eq(val, cstr("nil"))) {
587 return emit_token(current, scanner, TOK_NIL); 660 return emit_token(current, scanner, TOK_NIL);
588 } 661 }
589 } break; 662 } break;
590 case 'r': { 663 case 'r': {
591 if (str_has_prefix(val, cstr("return"))) { 664 if (str_eq(val, cstr("return"))) {
592 return emit_token(current, scanner, TOK_RETURN); 665 return emit_token(current, scanner, TOK_RETURN);
593 } 666 }
594 } break; 667 } break;
595 case 's': { 668 case 's': {
596 if (str_has_prefix(val, cstr("set"))) { 669 if (str_eq(val, cstr("set"))) {
597 return emit_token(current, scanner, TOK_SET); 670 return emit_token(current, scanner, TOK_SET);
598 } 671 }
599 if (str_has_prefix(val, cstr("struct"))) { 672 if (str_eq(val, cstr("struct"))) {
600 return emit_token(current, scanner, TOK_STRUCT); 673 return emit_token(current, scanner, TOK_STRUCT);
601 } 674 }
602 } break; 675 } break;
603 case 't': { 676 case 't': {
604 if (str_has_prefix(val, cstr("true"))) { 677 if (str_eq(val, cstr("true"))) {
605 return emit_token(current, scanner, TOK_TRUE); 678 return emit_token(current, scanner, TOK_TRUE);
606 } 679 }
607 } break; 680 } break;
681 case 'o': {
682 if (str_eq(val, cstr("or"))) {
683 return emit_token(current, scanner, TOK_OR);
684 }
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 3c3dd29..b5530b3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -12,19 +12,41 @@
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: for loops? 16// []Int vs Int[], @sym vs sym@. On the right dereference, on the left
17// for i = 0 , i < 10 , i++ { 17// declaration or taking the address/reference of a variable. Similar
18// 18// to what Odin does.
19// } 19// let a: @Int ; pointer to int
20// TODO: fix semantics for the following expression: 20// let b: @@Int ; pointer to pointer to int (etc.)
21// let b = int 21// let c: [123]Int ; static array -> @Int
22// a type shouldn't be a valid symbol name 22// let d: []Int ; slice / view -> struct Slice { u8* mem ; sz size ; }
23// TODO: fix semantics for arrays: static arrays can't have size 0. 23// let e: [...]Int ; dynamic array -> struct DArry { u8* mem ; sz size ; sz cap ; }
24// TODO: consider making all tye types PascalCase: Int F64 Str... 24// let f: [123]@Int ; static array of int pointers [](@Int)
25// let g: @[123]Int ; pointer to a static array of integers @([123]Int)
26// let h: #[Str:Int] ; Hash map of string keys and integer values
27// let i: #[Str:@Int] ; Hash map of string keys and pointers to integer
28// let j: #[@Str:Int] ; Hash map of string pointers to integers
29// let k: @#[Str:Int] ; Pointer to a hash map of string to ints
30// let l: (Int Int : Int) ; Function pointer == @(fun(Int,Int):Int)
25// TODO: add a `const` keyword that can only take literals or constexpr values. 31// TODO: add a `const` keyword that can only take literals or constexpr values.
26// TODO: add assignment operators instead of `set` :=, +=, -= 32// TODO: "first class functions" via function pointers
27// TODO: add mifix operators ++ and -- 33// TODO: convenient function calls per data type instead of methods:
34// fun add(a: int, b: int): int a + b
35// add(12, 34) == 12.add(34)
36// concat(str, str): str
37// "hello ".concat("world") ; "hello world"
38// TODO: more numeric types
39// TODO: structs and user defined types
40// TODO: constant folding
41// TODO: constexpr evaluation
42// TODO: casting on demand (1:u16, 0x123:ptr, "hi":int ??? how to deal with
43// unsafe casts?)
44// TODO: for nil type returns, consider only allowing fun() {} and discarding
45// fun(): nil and fun(): (). Only one way of doing things would be preferable.
46// TODO: constexpr or const expressions could be evaluated with the bytecode
47// interpreter if we are performing compilation.
48// TODO: refactor compiler.c, the duplication is getting out of hand tbh, plus
49// there are a lot of inconsistent naming things.
28 50
29typedef enum ExecMode { 51typedef enum ExecMode {
30 RUN_NORMAL, 52 RUN_NORMAL,
@@ -56,6 +78,9 @@ process_file(Str path) {
56 sz errors = 0; 78 sz errors = 0;
57 79
58 // Lexer. 80 // Lexer.
81#if DEBUG == 1
82 println("lexing...");
83#endif
59 Scanner scanner = {.str = file.data}; 84 Scanner scanner = {.str = file.data};
60 Token *tokens = NULL; 85 Token *tokens = NULL;
61 Token tok = {0}; 86 Token tok = {0};
@@ -79,6 +104,9 @@ process_file(Str path) {
79 } 104 }
80 105
81 // Parser. 106 // Parser.
107#if DEBUG == 1
108 println("parsing...");
109#endif
82 Parser parser = { 110 Parser parser = {
83 .tokens = tokens, 111 .tokens = tokens,
84 .storage = &lexer_arena, 112 .storage = &lexer_arena,
@@ -106,6 +134,9 @@ process_file(Str path) {
106 } 134 }
107 135
108 // Semantic analysis. 136 // Semantic analysis.
137#if DEBUG == 1
138 println("semantic analysis...");
139#endif
109 Analyzer analyzer = (Analyzer){ 140 Analyzer analyzer = (Analyzer){
110 .storage = &lexer_arena, 141 .storage = &lexer_arena,
111 .file_name = path, 142 .file_name = path,
@@ -175,68 +206,26 @@ process_file(Str path) {
175 } 206 }
176#endif 207#endif
177 208
178 // TODO: Type checking.
179
180 // Compile roots. 209 // Compile roots.
210#if DEBUG == 1
211 println("compilation...");
212#endif
181 Arena bytecode_arena = arena_create(LEXER_MEM, os_allocator); 213 Arena bytecode_arena = arena_create(LEXER_MEM, os_allocator);
182 Chunk chunk = { 214 Compiler compiler = {
183 .file_name = path, 215 .file_name = path,
184 .storage = &bytecode_arena, 216 .storage = &bytecode_arena,
185 .name = cstr(".main"), 217 .integer_types = analyzer.integer_types,
218 .float_types = analyzer.float_types,
219 .numeric_types = analyzer.numeric_types,
220 .lab_pre = -1,
221 .lab_post = -1,
186 }; 222 };
187 array_zero(chunk.constants, 256, &bytecode_arena); 223 bytecode_compiler(&compiler, parser);
188 array_zero(chunk.code, 0xffff, &bytecode_arena); 224 disassemble_chunk(compiler.main_chunk);
189 sz n_roots = array_size(parser.nodes);
190 CompResult res = {0};
191 for (sz i = 0; i < n_roots; i++) {
192 // The parser stores the root nodes as a stack.
193 Node *root = parser.nodes[i];
194 res = compile_expr(&chunk, root);
195 if (res.type == COMP_ERR) {
196 eprintln("compilation error...");
197 exit(EXIT_FAILURE);
198 }
199 }
200 // Make sure the last result is on r0.
201 sz res_reg = 0;
202 bool is_nil = false;
203 switch (res.type) {
204 case COMP_CONST: {
205 res_reg = chunk.reg_idx++;
206 Instruction inst =
207 (Instruction){.op = OP_LD64K, .dst = res_reg, .a = res.idx};
208 array_push(chunk.code, inst, chunk.storage);
209 } break;
210 case COMP_REG: {
211 res_reg = res.idx;
212 } break;
213 case COMP_NIL: {
214 is_nil = true;
215 } break;
216 default: break;
217 }
218 EMIT_OP(OP_HALT, res_reg, !is_nil, 0, NULL, &chunk);
219
220 if (chunk.const_idx >= 256) {
221 eprintln("too many constants on chunk %s", chunk.id);
222 exit(EXIT_FAILURE);
223 }
224 if (chunk.str_idx >= 256) {
225 eprintln("too many strings on chunk %s", chunk.id);
226 exit(EXIT_FAILURE);
227 }
228 if (chunk.reg_idx >= 256) {
229 eprintln("too many registers used on chunk %s", chunk.id);
230 exit(EXIT_FAILURE);
231 }
232
233 disassemble_chunk(chunk);
234 225
235 // Run bytecode on VM. 226 // Run bytecode on VM.
236 VM vm = {0}; 227 VM vm = {0};
237 vm_init(&vm, &chunk); 228 vm_init(&vm, &compiler.main_chunk);
238 // println("VM REGISTERS BEFORE:\n%{Mem}",
239 // &(Array){.mem = (u8 *)&vm.regs, sizeof(vm.regs)});
240 vm_run(&vm); 229 vm_run(&vm);
241#if DEBUG == 1 230#if DEBUG == 1
242 println("MEMORY:\n%{Mem}", 231 println("MEMORY:\n%{Mem}",
diff --git a/src/parser.c b/src/parser.c
index 90adaf3..0323215 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.
@@ -66,9 +68,12 @@ typedef enum NodeKind {
66 NODE_ARR_TYPE, 68 NODE_ARR_TYPE,
67 NODE_FIELD, 69 NODE_FIELD,
68 NODE_BLOCK, 70 NODE_BLOCK,
71 NODE_PTR,
72 NODE_DEREF,
69} NodeKind; 73} NodeKind;
70 74
71Str node_str[] = { 75Str node_str[] = {
76 [NODE_ERR] = cstr("ERR"),
72 // Arithmetic. 77 // Arithmetic.
73 [NODE_ADD] = cstr("ADD"), 78 [NODE_ADD] = cstr("ADD"),
74 [NODE_SUB] = cstr("SUB"), 79 [NODE_SUB] = cstr("SUB"),
@@ -89,6 +94,7 @@ Str node_str[] = {
89 [NODE_BITNOT] = cstr("BITNOT"), 94 [NODE_BITNOT] = cstr("BITNOT"),
90 [NODE_BITAND] = cstr("BITAND"), 95 [NODE_BITAND] = cstr("BITAND"),
91 [NODE_BITOR] = cstr("BITOR"), 96 [NODE_BITOR] = cstr("BITOR"),
97 [NODE_BITXOR] = cstr("BITXOR"),
92 [NODE_BITLSHIFT] = cstr("BITLSHIFT"), 98 [NODE_BITLSHIFT] = cstr("BITLSHIFT"),
93 [NODE_BITRSHIFT] = cstr("BITRSHIFT"), 99 [NODE_BITRSHIFT] = cstr("BITRSHIFT"),
94 // Literals. 100 // Literals.
@@ -126,77 +132,115 @@ Str node_str[] = {
126 [NODE_SYMBOL_IDX] = cstr("SYMBOL[IDX]"), 132 [NODE_SYMBOL_IDX] = cstr("SYMBOL[IDX]"),
127 [NODE_FIELD] = cstr("FIELD"), 133 [NODE_FIELD] = cstr("FIELD"),
128 [NODE_BLOCK] = cstr("BLOCK"), 134 [NODE_BLOCK] = cstr("BLOCK"),
135 [NODE_PTR] = cstr("@"),
136 [NODE_DEREF] = cstr("DEREF"),
129}; 137};
130 138
139typedef union NodeLit {
140 f64 d;
141 sz i;
142 u64 u;
143 Str str;
144 Str sym;
145} NodeLit;
146
147typedef struct NodeBinary {
148 struct Node *left;
149 struct Node *right;
150} NodeBinary;
151
152typedef struct NodeUnary {
153 struct Node *left;
154} NodeUnary;
155
156typedef struct NodeVariable {
157 struct Node *name;
158 struct Node *type;
159 struct Node *val;
160} NodeVariable;
161
162typedef struct NodeLoop {
163 struct Node *cond;
164 struct Node *expr;
165} NodeLoop;
166
167typedef struct NodeIf {
168 struct Node *cond;
169 struct Node *expr_true;
170 struct Node *expr_else;
171} NodeIf;
172
173typedef struct NodeField {
174 struct Node *type;
175 struct Node *val;
176} NodeField;
177
178typedef struct NodeParam {
179 struct Node *name;
180 struct Node *type;
181} NodeParam;
182
183typedef struct NodeMatch {
184 struct Node *expr;
185 struct Node **cases;
186} NodeMatch;
187
188typedef struct NodeCase {
189 struct Node *cond;
190 struct Node *expr;
191} NodeCase;
192
193typedef struct NodeFunction {
194 struct Node *name;
195 struct Node **params;
196 struct Node **ret;
197 struct Node *body;
198} NodeFunction;
199
200typedef struct NodeSymbol {
201 struct Node *next;
202 struct Node *arr_size;
203} NodeSymbol;
204
205typedef struct NodeType {
206 struct Node *next;
207} NodeType;
208
209typedef struct NodeDeref {
210 struct Node *next;
211} NodeDeref;
212
131typedef struct Node { 213typedef struct Node {
132 sz id; 214 sz id;
133 sz line; 215 sz line;
134 sz col; 216 sz col;
217 struct Node *parent;
135 218
136 NodeKind kind; 219 NodeKind kind;
220 NodeLit value;
137 union { 221 union {
138 f64 d; 222 NodeBinary binary;
139 sz i; 223 NodeUnary unary;
140 u64 u; 224 NodeVariable var;
141 Str str; 225 NodeSymbol sym;
142 Str sym; 226 NodeLoop loop;
143 } value; 227 NodeIf ifelse;
144 union { 228 NodeField field;
145 struct { 229 NodeParam param;
146 struct Node *left; 230 NodeMatch match;
147 struct Node *right; 231 NodeCase case_entry;
148 }; 232 NodeFunction func;
149 struct { 233 NodeType t;
150 struct Node *next; 234 NodeDeref deref;
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; 235 struct Node **struct_field;
184 struct Node **elements; 236 struct Node **elements;
185 struct Node **statements; 237 struct Node **statements;
186 struct Node **expressions; 238 struct Node **expressions;
187 struct Node **arguments; 239 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 }; 240 };
195 bool is_ptr;
196 struct Scope *scope;
197 Str type; 241 Str type;
198 Str fun_params; 242 Str type_params;
199 Str fun_return; 243 Str type_returns;
200 Str unique_name; 244 Str unique_name;
201} Node; 245} Node;
202 246
@@ -286,6 +330,7 @@ ParseRule parse_rules[] = {
286 [TOK_BITNOT] = {parse_unary, NULL, PREC_NONE}, 330 [TOK_BITNOT] = {parse_unary, NULL, PREC_NONE},
287 [TOK_BITAND] = {NULL, parse_binary, PREC_BITLOGIC}, 331 [TOK_BITAND] = {NULL, parse_binary, PREC_BITLOGIC},
288 [TOK_BITOR] = {NULL, parse_binary, PREC_BITLOGIC}, 332 [TOK_BITOR] = {NULL, parse_binary, PREC_BITLOGIC},
333 [TOK_BITXOR] = {NULL, parse_binary, PREC_BITLOGIC},
289 [TOK_BITLSHIFT] = {NULL, parse_binary, PREC_BITSHIFT}, 334 [TOK_BITLSHIFT] = {NULL, parse_binary, PREC_BITSHIFT},
290 [TOK_BITRSHIFT] = {NULL, parse_binary, PREC_BITSHIFT}, 335 [TOK_BITRSHIFT] = {NULL, parse_binary, PREC_BITSHIFT},
291 336
@@ -308,6 +353,7 @@ ParseRule parse_rules[] = {
308 [TOK_MATCH] = {parse_keyword, NULL, PREC_NONE}, 353 [TOK_MATCH] = {parse_keyword, NULL, PREC_NONE},
309 [TOK_COND] = {parse_keyword, NULL, PREC_NONE}, 354 [TOK_COND] = {parse_keyword, NULL, PREC_NONE},
310 [TOK_WHILE] = {parse_keyword, NULL, PREC_NONE}, 355 [TOK_WHILE] = {parse_keyword, NULL, PREC_NONE},
356 [TOK_FOR] = {parse_keyword, NULL, PREC_NONE},
311 [TOK_CONTINUE] = {parse_keyword, NULL, PREC_NONE}, 357 [TOK_CONTINUE] = {parse_keyword, NULL, PREC_NONE},
312 [TOK_BREAK] = {parse_keyword, NULL, PREC_NONE}, 358 [TOK_BREAK] = {parse_keyword, NULL, PREC_NONE},
313 [TOK_FUN] = {parse_keyword, NULL, PREC_NONE}, 359 [TOK_FUN] = {parse_keyword, NULL, PREC_NONE},
@@ -437,7 +483,7 @@ parse_unary(Parser *parser) {
437 default: break; // Unreachable. 483 default: break; // Unreachable.
438 } 484 }
439 if (!node) return; 485 if (!node) return;
440 node->left = array_pop(parser->nodes); 486 node->unary.left = array_pop(parser->nodes);
441 array_push(parser->nodes, node, parser->storage); 487 array_push(parser->nodes, node, parser->storage);
442} 488}
443 489
@@ -472,20 +518,28 @@ parse_type(Parser *parser) {
472#endif 518#endif
473 Node *node = node_alloc(parser, NODE_TYPE, prev); 519 Node *node = node_alloc(parser, NODE_TYPE, prev);
474 if (!node) return; 520 if (!node) return;
475 if (parse_match(parser, TOK_AT)) { 521 Node *child = node;
476 node->is_ptr = true; 522 while (parse_match(parser, TOK_AT)) {
523 Node *ptr_node = node_alloc(parser, NODE_PTR, parser->previous);
524 child->t.next = ptr_node;
525 child = ptr_node;
477 } 526 }
478 parse_consume(parser, TOK_SYMBOL, cstr("no type given for struct field")); 527 // TODO: arrays
528 // TODO: slices
529 // TODO: maps
530 // TODO: function pointer syntax: : (T T : R)
531 parse_consume(parser, TOK_SYMBOL, cstr("expected type name"));
479 node->value.sym = parser->previous.val; 532 node->value.sym = parser->previous.val;
480 // Optional array value? 533 // node->value.sym = parser->previous.val;
481 if (parse_match(parser, TOK_LSQUARE)) { 534 // // Optional array value?
482 node->kind = NODE_ARR_TYPE, 535 // if (parse_match(parser, TOK_LSQUARE)) {
483 parse_consume(parser, TOK_NUM_INT, cstr("no array size given")); 536 // node->kind = NODE_ARR_TYPE,
484 parse_number(parser); 537 // parse_consume(parser, TOK_NUM_INT, cstr("no array size given"));
485 node->arr_size = array_pop(parser->nodes); 538 // parse_number(parser);
486 parse_consume(parser, TOK_RSQUARE, 539 // node->sym.arr_size = array_pop(parser->nodes);
487 cstr("unmatched brackets ']' in array type")); 540 // parse_consume(parser, TOK_RSQUARE,
488 } 541 // cstr("unmatched brackets ']' in array type"));
542 // }
489 array_push(parser->nodes, node, parser->storage); 543 array_push(parser->nodes, node, parser->storage);
490} 544}
491 545
@@ -510,16 +564,16 @@ parse_struct_field(Parser *parser) {
510 Node *subfield = array_pop(parser->nodes); 564 Node *subfield = array_pop(parser->nodes);
511 array_push(type->elements, subfield, parser->storage); 565 array_push(type->elements, subfield, parser->storage);
512 } 566 }
513 field->field_type = type; 567 field->field.type = type;
514 } else { 568 } else {
515 parse_type(parser); 569 parse_type(parser);
516 field->field_type = array_pop(parser->nodes); 570 field->field.type = array_pop(parser->nodes);
517 } 571 }
518 572
519 // Optional assignment. 573 // Optional assignment.
520 if (parse_match(parser, TOK_ASSIGN)) { 574 if (parse_match(parser, TOK_ASSIGN)) {
521 parse_expr(parser, PREC_LOW); 575 parse_expr(parser, PREC_LOW);
522 field->field_val = array_pop(parser->nodes); 576 field->field.val = array_pop(parser->nodes);
523 } 577 }
524 array_push(parser->nodes, field, parser->storage); 578 array_push(parser->nodes, field, parser->storage);
525} 579}
@@ -546,10 +600,10 @@ parse_struct_lit_field(Parser *parser) {
546 Node *subfield = array_pop(parser->nodes); 600 Node *subfield = array_pop(parser->nodes);
547 array_push(type->elements, subfield, parser->storage); 601 array_push(type->elements, subfield, parser->storage);
548 } 602 }
549 field->field_val = type; 603 field->field.val = type;
550 } else { 604 } else {
551 parse_expr(parser, PREC_LOW); 605 parse_expr(parser, PREC_LOW);
552 field->field_val = array_pop(parser->nodes); 606 field->field.val = array_pop(parser->nodes);
553 } 607 }
554 array_push(parser->nodes, field, parser->storage); 608 array_push(parser->nodes, field, parser->storage);
555} 609}
@@ -570,8 +624,8 @@ parse_keyword(Parser *parser) {
570 parse_consume(parser, TOK_SYMBOL, 624 parse_consume(parser, TOK_SYMBOL,
571 cstr("expected symbol name on let expression")); 625 cstr("expected symbol name on let expression"));
572 parse_symbol(parser); 626 parse_symbol(parser);
573 node->var_name = array_pop(parser->nodes); 627 node->var.name = array_pop(parser->nodes);
574 if (node->var_name->next) { 628 if (node->var.name->sym.next) {
575 parse_emit_err(parser, prev, 629 parse_emit_err(parser, prev,
576 cstr("invalid symbol name in let expression")); 630 cstr("invalid symbol name in let expression"));
577 return; 631 return;
@@ -580,16 +634,16 @@ parse_keyword(Parser *parser) {
580 // Optional type declaration. 634 // Optional type declaration.
581 if (parse_match(parser, TOK_COLON)) { 635 if (parse_match(parser, TOK_COLON)) {
582 parse_type(parser); 636 parse_type(parser);
583 node->var_type = array_pop(parser->nodes); 637 node->var.type = array_pop(parser->nodes);
584 } 638 }
585 639
586 // Optional assignment. 640 // Optional assignment.
587 if (parse_match(parser, TOK_ASSIGN)) { 641 if (parse_match(parser, TOK_ASSIGN)) {
588 parse_expr(parser, PREC_LOW); 642 parse_expr(parser, PREC_LOW);
589 node->var_val = array_pop(parser->nodes); 643 node->var.val = array_pop(parser->nodes);
590 } 644 }
591 645
592 if (node->var_type == NULL && node->var_val == NULL) { 646 if (node->var.type == NULL && node->var.val == NULL) {
593 parse_emit_err(parser, prev, 647 parse_emit_err(parser, prev,
594 cstr("variable declaration must include type or " 648 cstr("variable declaration must include type or "
595 "value information")); 649 "value information"));
@@ -599,13 +653,50 @@ parse_keyword(Parser *parser) {
599 node = node_alloc(parser, NODE_SET, prev); 653 node = node_alloc(parser, NODE_SET, prev);
600 if (!node) return; 654 if (!node) return;
601 parse_consume(parser, TOK_SYMBOL, 655 parse_consume(parser, TOK_SYMBOL,
602 cstr("expected symbol name on let expression")); 656 cstr("expected symbol name on set expression"));
603 parse_symbol(parser); 657 parse_symbol(parser);
604 node->var_name = array_pop(parser->nodes); 658 node->var.name = array_pop(parser->nodes);
605 parse_consume(parser, TOK_ASSIGN, 659
606 cstr("expected assignment on set expression")); 660 if (parse_match(parser, TOK_ADD_ASSIGN) ||
607 parse_expr(parser, PREC_LOW); 661 parse_match(parser, TOK_ADD_ASSIGN) ||
608 node->var_val = array_pop(parser->nodes); 662 parse_match(parser, TOK_SUB_ASSIGN) ||
663 parse_match(parser, TOK_MUL_ASSIGN) ||
664 parse_match(parser, TOK_DIV_ASSIGN) ||
665 parse_match(parser, TOK_MOD_ASSIGN) ||
666 parse_match(parser, TOK_BITAND_ASSIGN) ||
667 parse_match(parser, TOK_BITOR_ASSIGN) ||
668 parse_match(parser, TOK_BITXOR_ASSIGN) ||
669 parse_match(parser, TOK_BITLSHIFT_ASSIGN) ||
670 parse_match(parser, TOK_BITRSHIFT_ASSIGN)) {
671 NodeKind kind = NODE_ERR;
672 switch (parser->previous.kind) {
673 case TOK_ADD_ASSIGN: kind = NODE_ADD; break;
674 case TOK_SUB_ASSIGN: kind = NODE_SUB; break;
675 case TOK_MUL_ASSIGN: kind = NODE_MUL; break;
676 case TOK_DIV_ASSIGN: kind = NODE_DIV; break;
677 case TOK_MOD_ASSIGN: kind = NODE_MOD; break;
678 case TOK_BITAND_ASSIGN: kind = NODE_BITAND; break;
679 case TOK_BITOR_ASSIGN: kind = NODE_BITOR; break;
680 case TOK_BITXOR_ASSIGN: kind = NODE_BITXOR; break;
681 case TOK_BITLSHIFT_ASSIGN: kind = NODE_BITLSHIFT; break;
682 case TOK_BITRSHIFT_ASSIGN: kind = NODE_BITRSHIFT; break;
683 default: break;
684 }
685 parse_expr(parser, PREC_LOW);
686 Node *value = array_pop(parser->nodes);
687 Node *sym = node_alloc(parser, NODE_SYMBOL, prev);
688 Node *op = node_alloc(parser, kind, prev);
689 op->binary.left = sym;
690 op->binary.right = value;
691 node->var.val = op;
692 sym->value = node->var.name->value;
693 sym->kind = node->var.name->kind;
694 } else {
695 parse_consume(parser, TOK_ASSIGN,
696 cstr("expected assignment on set expression"));
697 parse_expr(parser, PREC_LOW);
698 node->var.val = array_pop(parser->nodes);
699 }
609 } break; 700 } break;
610 case TOK_STRUCT: { 701 case TOK_STRUCT: {
611 node = node_alloc(parser, NODE_STRUCT, prev); 702 node = node_alloc(parser, NODE_STRUCT, prev);
@@ -629,19 +720,19 @@ parse_keyword(Parser *parser) {
629 node = node_alloc(parser, NODE_IF, prev); 720 node = node_alloc(parser, NODE_IF, prev);
630 if (!node) return; 721 if (!node) return;
631 parse_expr(parser, PREC_LOW); 722 parse_expr(parser, PREC_LOW);
632 node->cond_if = array_pop(parser->nodes); 723 node->ifelse.cond = array_pop(parser->nodes);
633 parse_expr(parser, PREC_LOW); 724 parse_expr(parser, PREC_LOW);
634 node->cond_expr = array_pop(parser->nodes); 725 node->ifelse.expr_true = array_pop(parser->nodes);
635 if (parse_match(parser, TOK_ELSE)) { 726 if (parse_match(parser, TOK_ELSE)) {
636 parse_expr(parser, PREC_LOW); 727 parse_expr(parser, PREC_LOW);
637 node->cond_else = array_pop(parser->nodes); 728 node->ifelse.expr_else = array_pop(parser->nodes);
638 } 729 }
639 } break; 730 } break;
640 case TOK_MATCH: { 731 case TOK_MATCH: {
641 node = node_alloc(parser, NODE_MATCH, prev); 732 node = node_alloc(parser, NODE_MATCH, prev);
642 if (!node) return; 733 if (!node) return;
643 parse_expr(parser, PREC_LOW); 734 parse_expr(parser, PREC_LOW);
644 node->match_expr = array_pop(parser->nodes); 735 node->match.expr = array_pop(parser->nodes);
645 parse_consume(parser, TOK_LCURLY, 736 parse_consume(parser, TOK_LCURLY,
646 cstr("expected block of match cases")); 737 cstr("expected block of match cases"));
647 while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { 738 while (!parse_match(parser, TOK_RCURLY) && !parser->panic) {
@@ -653,13 +744,13 @@ parse_keyword(Parser *parser) {
653 parse_consume(parser, TOK_CASE, 744 parse_consume(parser, TOK_CASE,
654 cstr("expected case statement")); 745 cstr("expected case statement"));
655 parse_expr(parser, PREC_LOW); 746 parse_expr(parser, PREC_LOW);
656 tmp->case_value = array_pop(parser->nodes); 747 tmp->case_entry.cond = array_pop(parser->nodes);
657 } 748 }
658 parse_consume(parser, TOK_ASSIGN, 749 parse_consume(parser, TOK_ASSIGN,
659 cstr("malformed case statement")); 750 cstr("malformed case statement"));
660 parse_expr(parser, PREC_LOW); 751 parse_expr(parser, PREC_LOW);
661 tmp->case_expr = array_pop(parser->nodes); 752 tmp->case_entry.expr = array_pop(parser->nodes);
662 array_push(node->match_cases, tmp, parser->storage); 753 array_push(node->match.cases, tmp, parser->storage);
663 } 754 }
664 // TODO: Check that we only have literals on the match case, 755 // TODO: Check that we only have literals on the match case,
665 // this could be done on the analysis step, but also here... 756 // this could be done on the analysis step, but also here...
@@ -683,7 +774,7 @@ parse_keyword(Parser *parser) {
683 field->value.sym = parser->previous.val; 774 field->value.sym = parser->previous.val;
684 if (parse_match(parser, TOK_ASSIGN)) { 775 if (parse_match(parser, TOK_ASSIGN)) {
685 parse_expr(parser, PREC_LOW); 776 parse_expr(parser, PREC_LOW);
686 field->field_val = array_pop(parser->nodes); 777 field->field.val = array_pop(parser->nodes);
687 } 778 }
688 array_push(node->struct_field, field, parser->storage); 779 array_push(node->struct_field, field, parser->storage);
689 } 780 }
@@ -703,13 +794,13 @@ parse_keyword(Parser *parser) {
703 // Are we on the default case. 794 // Are we on the default case.
704 if (!parse_match(parser, TOK_ELSE)) { 795 if (!parse_match(parser, TOK_ELSE)) {
705 parse_expr(parser, PREC_LOW); 796 parse_expr(parser, PREC_LOW);
706 tmp->case_value = array_pop(parser->nodes); 797 tmp->case_entry.cond = array_pop(parser->nodes);
707 } 798 }
708 parse_consume(parser, TOK_ASSIGN, 799 parse_consume(parser, TOK_ASSIGN,
709 cstr("malformed case statement")); 800 cstr("malformed case statement"));
710 parse_expr(parser, PREC_LOW); 801 parse_expr(parser, PREC_LOW);
711 tmp->case_expr = array_pop(parser->nodes); 802 tmp->case_entry.expr = array_pop(parser->nodes);
712 array_push(node->match_cases, tmp, parser->storage); 803 array_push(node->match.cases, tmp, parser->storage);
713 } 804 }
714 } break; 805 } break;
715 case TOK_BREAK: { 806 case TOK_BREAK: {
@@ -720,13 +811,47 @@ parse_keyword(Parser *parser) {
720 node = node_alloc(parser, NODE_CONTINUE, prev); 811 node = node_alloc(parser, NODE_CONTINUE, prev);
721 if (!node) return; 812 if (!node) return;
722 } break; 813 } break;
814 case TOK_FOR: {
815 node = node_alloc(parser, NODE_BLOCK, prev);
816 if (!node) return;
817
818 Node *node_while = node_alloc(parser, NODE_WHILE, prev);
819 if (!node_while) return;
820 Node *block = node_alloc(parser, NODE_BLOCK, prev);
821 if (!block) return;
822
823 parse_expr(parser, PREC_LOW);
824 Node *pre = array_pop(parser->nodes);
825
826 parse_expr(parser, PREC_LOW);
827 Node *cond = array_pop(parser->nodes);
828
829 parse_expr(parser, PREC_LOW);
830 Node *post = array_pop(parser->nodes);
831
832 // Body.
833 parse_consume(parser, TOK_LCURLY,
834 cstr("expected '{' on for loop statement"));
835 while (!parse_match(parser, TOK_RCURLY) && !parser->panic) {
836 parse_expr(parser, PREC_LOW);
837 Node *next = array_pop(parser->nodes);
838 array_push(block->statements, next, parser->storage);
839 }
840 array_push(block->statements, post, parser->storage);
841
842 // Put everything together
843 node_while->loop.cond = cond;
844 node_while->loop.expr = block;
845 array_push(node->statements, pre, parser->storage);
846 array_push(node->statements, node_while, parser->storage);
847 } break;
723 case TOK_WHILE: { 848 case TOK_WHILE: {
724 node = node_alloc(parser, NODE_WHILE, prev); 849 node = node_alloc(parser, NODE_WHILE, prev);
725 if (!node) return; 850 if (!node) return;
726 parse_expr(parser, PREC_LOW); 851 parse_expr(parser, PREC_LOW);
727 node->while_cond = array_pop(parser->nodes); 852 node->loop.cond = array_pop(parser->nodes);
728 parse_expr(parser, PREC_LOW); 853 parse_expr(parser, PREC_LOW);
729 node->while_expr = array_pop(parser->nodes); 854 node->loop.expr = array_pop(parser->nodes);
730 } break; 855 } break;
731 case TOK_FUN: { 856 case TOK_FUN: {
732 node = node_alloc(parser, NODE_FUN, prev); 857 node = node_alloc(parser, NODE_FUN, prev);
@@ -735,7 +860,7 @@ parse_keyword(Parser *parser) {
735 Node *name = node_alloc(parser, NODE_SYMBOL, prev); 860 Node *name = node_alloc(parser, NODE_SYMBOL, prev);
736 if (!name) return; 861 if (!name) return;
737 name->value.sym = parser->previous.val; 862 name->value.sym = parser->previous.val;
738 node->func_name = name; 863 node->func.name = name;
739 parse_consume(parser, TOK_LPAREN, 864 parse_consume(parser, TOK_LPAREN,
740 cstr("expected '(' on function definition")); 865 cstr("expected '(' on function definition"));
741 // Parameters. 866 // Parameters.
@@ -747,39 +872,41 @@ parse_keyword(Parser *parser) {
747 if (!name) return; 872 if (!name) return;
748 parse_consume(parser, TOK_SYMBOL, cstr("expected symbol name")); 873 parse_consume(parser, TOK_SYMBOL, cstr("expected symbol name"));
749 name->value.sym = parser->previous.val; 874 name->value.sym = parser->previous.val;
750 param->param_name = name; 875 param->param.name = name;
751 876
752 Node *type = node_alloc(parser, NODE_TYPE, prev); 877 Node *type = node_alloc(parser, NODE_TYPE, prev);
753 if (!type) return; 878 if (!type) return;
754 parse_consume(parser, TOK_COLON, cstr("expected param type")); 879 parse_consume(parser, TOK_COLON, cstr("expected param type"));
755 if (parse_match(parser, TOK_AT)) { 880 // TODO: reuse parse_type
756 type->is_ptr = true; 881 // if (parse_match(parser, TOK_AT)) {
757 } 882 // type->is_ptr = true;
883 // }
758 parse_consume(parser, TOK_SYMBOL, cstr("expected param type")); 884 parse_consume(parser, TOK_SYMBOL, cstr("expected param type"));
759 type->value.sym = parser->previous.val; 885 type->value.sym = parser->previous.val;
760 param->param_type = type; 886 param->param.type = type;
761 if (parse_match(parser, TOK_LSQUARE)) { 887 if (parse_match(parser, TOK_LSQUARE)) {
762 type->kind = NODE_ARR_TYPE, 888 type->kind = NODE_ARR_TYPE,
763 parse_consume(parser, TOK_NUM_INT, 889 parse_consume(parser, TOK_NUM_INT,
764 cstr("no array size given")); 890 cstr("no array size given"));
765 parse_number(parser); 891 parse_number(parser);
766 type->arr_size = array_pop(parser->nodes); 892 type->sym.arr_size = array_pop(parser->nodes);
767 parse_consume(parser, TOK_RSQUARE, 893 parse_consume(parser, TOK_RSQUARE,
768 cstr("unmatched brackets ']' in array type")); 894 cstr("unmatched brackets ']' in array type"));
769 } 895 }
770 array_push(node->func_params, param, parser->storage); 896 array_push(node->func.params, param, parser->storage);
771 } 897 }
772 parse_consume(parser, TOK_COLON, cstr("expected param type"));
773 898
774 // Return type(s). 899 // Return type(s).
775 if (!parse_match(parser, TOK_NIL)) { 900 if (parse_match(parser, TOK_COLON) &&
901 !parse_match(parser, TOK_NIL)) {
776 if (parse_match(parser, TOK_LPAREN)) { 902 if (parse_match(parser, TOK_LPAREN)) {
777 while (!parse_match(parser, TOK_RPAREN) && !parser->panic) { 903 while (!parse_match(parser, TOK_RPAREN) && !parser->panic) {
778 Node *ret = node_alloc(parser, NODE_TYPE, prev); 904 Node *ret = node_alloc(parser, NODE_TYPE, prev);
779 if (!ret) return; 905 if (!ret) return;
780 if (parse_match(parser, TOK_AT)) { 906 // TODO: reuse parse_type
781 ret->is_ptr = true; 907 // if (parse_match(parser, TOK_AT)) {
782 } 908 // ret->is_ptr = true;
909 // }
783 parse_consume(parser, TOK_SYMBOL, 910 parse_consume(parser, TOK_SYMBOL,
784 cstr("expected type name")); 911 cstr("expected type name"));
785 ret->value.sym = parser->previous.val; 912 ret->value.sym = parser->previous.val;
@@ -788,19 +915,20 @@ parse_keyword(Parser *parser) {
788 parse_consume(parser, TOK_NUM_INT, 915 parse_consume(parser, TOK_NUM_INT,
789 cstr("no array size given")); 916 cstr("no array size given"));
790 parse_number(parser); 917 parse_number(parser);
791 ret->arr_size = array_pop(parser->nodes); 918 ret->sym.arr_size = array_pop(parser->nodes);
792 parse_consume(parser, TOK_RSQUARE, 919 parse_consume(parser, TOK_RSQUARE,
793 cstr("unmatched brackets ']' in " 920 cstr("unmatched brackets ']' in "
794 "array type")); 921 "array type"));
795 } 922 }
796 array_push(node->func_ret, ret, parser->storage); 923 array_push(node->func.ret, ret, parser->storage);
797 } 924 }
798 } else { 925 } else {
799 Node *ret = node_alloc(parser, NODE_TYPE, prev); 926 Node *ret = node_alloc(parser, NODE_TYPE, prev);
800 if (!ret) return; 927 if (!ret) return;
801 if (parse_match(parser, TOK_AT)) { 928 // TODO: reuse parse_type
802 ret->is_ptr = true; 929 // if (parse_match(parser, TOK_AT)) {
803 } 930 // ret->is_ptr = true;
931 // }
804 parse_consume(parser, TOK_SYMBOL, 932 parse_consume(parser, TOK_SYMBOL,
805 cstr("expected type name")); 933 cstr("expected type name"));
806 ret->value.sym = parser->previous.val; 934 ret->value.sym = parser->previous.val;
@@ -809,18 +937,18 @@ parse_keyword(Parser *parser) {
809 parse_consume(parser, TOK_NUM_INT, 937 parse_consume(parser, TOK_NUM_INT,
810 cstr("no array size given")); 938 cstr("no array size given"));
811 parse_number(parser); 939 parse_number(parser);
812 ret->arr_size = array_pop(parser->nodes); 940 ret->sym.arr_size = array_pop(parser->nodes);
813 parse_consume( 941 parse_consume(
814 parser, TOK_RSQUARE, 942 parser, TOK_RSQUARE,
815 cstr("unmatched brackets ']' in array type")); 943 cstr("unmatched brackets ']' in array type"));
816 } 944 }
817 array_push(node->func_ret, ret, parser->storage); 945 array_push(node->func.ret, ret, parser->storage);
818 } 946 }
819 } 947 }
820 948
821 // Body. 949 // Body.
822 parse_expr(parser, PREC_LOW); 950 parse_expr(parser, PREC_LOW);
823 node->func_body = array_pop(parser->nodes); 951 node->func.body = array_pop(parser->nodes);
824 } break; 952 } break;
825 case TOK_RETURN: { 953 case TOK_RETURN: {
826 node = node_alloc(parser, NODE_RETURN, prev); 954 node = node_alloc(parser, NODE_RETURN, prev);
@@ -870,6 +998,9 @@ parse_binary(Parser *parser) {
870 case TOK_BITOR: { 998 case TOK_BITOR: {
871 node = node_alloc(parser, NODE_BITOR, prev); 999 node = node_alloc(parser, NODE_BITOR, prev);
872 } break; 1000 } break;
1001 case TOK_BITXOR: {
1002 node = node_alloc(parser, NODE_BITXOR, prev);
1003 } break;
873 case TOK_BITLSHIFT: { 1004 case TOK_BITLSHIFT: {
874 node = node_alloc(parser, NODE_BITLSHIFT, prev); 1005 node = node_alloc(parser, NODE_BITLSHIFT, prev);
875 } break; 1006 } break;
@@ -882,8 +1013,8 @@ parse_binary(Parser *parser) {
882 } 1013 }
883 } 1014 }
884 if (!node) return; 1015 if (!node) return;
885 node->right = array_pop(parser->nodes); 1016 node->binary.right = array_pop(parser->nodes);
886 node->left = array_pop(parser->nodes); 1017 node->binary.left = array_pop(parser->nodes);
887 array_push(parser->nodes, node, parser->storage); 1018 array_push(parser->nodes, node, parser->storage);
888} 1019}
889 1020
@@ -947,25 +1078,26 @@ parse_symbol(Parser *parser) {
947 print("parsing symbol "); 1078 print("parsing symbol ");
948 print_token(prev); 1079 print_token(prev);
949#endif 1080#endif
1081 // TODO: dereference operators.
950 if (prev.kind == TOK_AT) { 1082 if (prev.kind == TOK_AT) {
1083 Node *node = node_alloc(parser, NODE_PTR, parser->previous);
1084 if (!node) return;
951 parse_consume(parser, TOK_SYMBOL, 1085 parse_consume(parser, TOK_SYMBOL,
952 cstr("expected symbol after '.' operator")); 1086 cstr("expected symbol after '@' operator"));
953 parse_symbol(parser); 1087 parse_symbol(parser);
954 Node *node = array_pop(parser->nodes); 1088 node->t.next = array_pop(parser->nodes);
955 if (node) { 1089 array_push(parser->nodes, node, parser->storage);
956 node->is_ptr = true;
957 array_push(parser->nodes, node, parser->storage);
958 }
959 return; 1090 return;
960 } 1091 }
961 Node *node = node_alloc(parser, NODE_SYMBOL, prev); 1092 Node *node = node_alloc(parser, NODE_SYMBOL, prev);
962 if (!node) return; 1093 if (!node) return;
1094 node->value.sym = prev.val;
963 if (parse_match(parser, TOK_DOT)) { 1095 if (parse_match(parser, TOK_DOT)) {
964 // Symbol chain. 1096 // Symbol chain.
965 parse_consume(parser, TOK_SYMBOL, 1097 parse_consume(parser, TOK_SYMBOL,
966 cstr("expected symbol after '.' operator")); 1098 cstr("expected symbol after '.' operator"));
967 parse_symbol(parser); 1099 parse_symbol(parser);
968 node->next = array_pop(parser->nodes); 1100 node->sym.next = array_pop(parser->nodes);
969 } else if (parser->current.kind == TOK_COLON && 1101 } else if (parser->current.kind == TOK_COLON &&
970 parse_peek(parser) == TOK_LCURLY) { 1102 parse_peek(parser) == TOK_LCURLY) {
971 parse_advance(parser); 1103 parse_advance(parser);
@@ -979,9 +1111,10 @@ parse_symbol(Parser *parser) {
979 array_push(node->elements, field, parser->storage); 1111 array_push(node->elements, field, parser->storage);
980 } 1112 }
981 } else if (parse_match(parser, TOK_LSQUARE)) { 1113 } else if (parse_match(parser, TOK_LSQUARE)) {
1114 // FIXME: desugar into deref
982 node->kind = NODE_SYMBOL_IDX; 1115 node->kind = NODE_SYMBOL_IDX;
983 parse_expr(parser, PREC_LOW); 1116 parse_expr(parser, PREC_LOW);
984 node->arr_size = array_pop(parser->nodes); 1117 node->sym.arr_size = array_pop(parser->nodes);
985 parse_consume(parser, TOK_RSQUARE, 1118 parse_consume(parser, TOK_RSQUARE,
986 cstr("unmatched brackets ']' in array type")); 1119 cstr("unmatched brackets ']' in array type"));
987 if (parse_match(parser, TOK_DOT)) { 1120 if (parse_match(parser, TOK_DOT)) {
@@ -989,7 +1122,7 @@ parse_symbol(Parser *parser) {
989 parse_consume(parser, TOK_SYMBOL, 1122 parse_consume(parser, TOK_SYMBOL,
990 cstr("expected symbol after '.' operator")); 1123 cstr("expected symbol after '.' operator"));
991 parse_symbol(parser); 1124 parse_symbol(parser);
992 node->next = array_pop(parser->nodes); 1125 node->sym.next = array_pop(parser->nodes);
993 } 1126 }
994 } else if (parse_match(parser, TOK_LPAREN)) { 1127 } else if (parse_match(parser, TOK_LPAREN)) {
995 node->kind = NODE_FUNCALL; 1128 node->kind = NODE_FUNCALL;
@@ -1003,10 +1136,20 @@ parse_symbol(Parser *parser) {
1003 parse_consume(parser, TOK_SYMBOL, 1136 parse_consume(parser, TOK_SYMBOL,
1004 cstr("expected symbol after '.' operator")); 1137 cstr("expected symbol after '.' operator"));
1005 parse_symbol(parser); 1138 parse_symbol(parser);
1006 node->next = array_pop(parser->nodes); 1139 node->sym.next = array_pop(parser->nodes);
1140 }
1141 } else if (parse_match(parser, TOK_AT)) {
1142 Node *deref = node_alloc(parser, NODE_DEREF, prev);
1143 Node *start = deref;
1144 while (parse_match(parser, TOK_AT)) {
1145 Node *next = node_alloc(parser, NODE_DEREF, prev);
1146 deref->deref.next = next;
1147 deref = next;
1007 } 1148 }
1149 deref->deref.next = node;
1150 array_push(parser->nodes, start, parser->storage);
1151 return;
1008 } 1152 }
1009 node->value.sym = prev.val;
1010 array_push(parser->nodes, node, parser->storage); 1153 array_push(parser->nodes, node, parser->storage);
1011} 1154}
1012 1155
@@ -1040,54 +1183,53 @@ graph_node(Node *node) {
1040 case NODE_ARR_TYPE: 1183 case NODE_ARR_TYPE:
1041 case NODE_FIELD: 1184 case NODE_FIELD:
1042 case NODE_TYPE: { 1185 case NODE_TYPE: {
1043 if (node->is_ptr) { 1186 print("| Name: %s", node->value.sym);
1044 print("| Name: @%s", node->value.sym);
1045 } else {
1046 print("| Name: %s", node->value.sym);
1047 }
1048 } break; 1187 } break;
1049 default: break; 1188 default: break;
1050 } 1189 }
1190 if (node->unique_name.size > 0) {
1191 print("| Unique Name: %s", node->unique_name);
1192 }
1051 if (node->type.size > 0) { 1193 if (node->type.size > 0) {
1052 print("| Type: %s", node->type); 1194 print("| Type: %s", node->type);
1053 } 1195 }
1054 if (node->fun_params.size > 0) { 1196 if (node->type_params.size > 0) {
1055 print("| Params: %s", node->fun_params); 1197 print("| Params: %s", node->type_params);
1056 } 1198 }
1057 if (node->fun_return.size > 0) { 1199 if (node->type_returns.size > 0) {
1058 print("| Return: %s", node->fun_return); 1200 print("| Return: %s", node->type_returns);
1059 } 1201 }
1060 println("\"];"); 1202 println("\"];");
1061 1203
1062 switch (node->kind) { 1204 switch (node->kind) {
1063 case NODE_FUN: { 1205 case NODE_FUN: {
1064 for (sz i = 0; i < array_size(node->func_params); i++) { 1206 for (sz i = 0; i < array_size(node->func.params); i++) {
1065 Node *next = node->func_params[i]; 1207 Node *next = node->func.params[i];
1066 println("%d:e->%d:w;", node->id, next->id); 1208 println("%d:e->%d:w;", node->id, next->id);
1067 graph_node(next); 1209 graph_node(next);
1068 } 1210 }
1069 for (sz i = 0; i < array_size(node->func_ret); i++) { 1211 for (sz i = 0; i < array_size(node->func.ret); i++) {
1070 Node *next = node->func_ret[i]; 1212 Node *next = node->func.ret[i];
1071 println("%d:e->%d:w;", node->id, next->id); 1213 println("%d:e->%d:w;", node->id, next->id);
1072 graph_node(next); 1214 graph_node(next);
1073 } 1215 }
1074 if (node->func_name) { 1216 if (node->func.name) {
1075 println("%d:e->%d:w;", node->id, node->func_name->id); 1217 println("%d:e->%d:w;", node->id, node->func.name->id);
1076 graph_node(node->func_name); 1218 graph_node(node->func.name);
1077 } 1219 }
1078 if (node->func_body) { 1220 if (node->func.body) {
1079 println("%d:e->%d:w;", node->id, node->func_body->id); 1221 println("%d:e->%d:w;", node->id, node->func.body->id);
1080 graph_node(node->func_body); 1222 graph_node(node->func.body);
1081 } 1223 }
1082 } break; 1224 } break;
1083 case NODE_COND: 1225 case NODE_COND:
1084 case NODE_MATCH: { 1226 case NODE_MATCH: {
1085 if (node->match_expr) { 1227 if (node->match.expr) {
1086 println("%d:e->%d:w;", node->id, node->match_expr->id); 1228 println("%d:e->%d:w;", node->id, node->match.expr->id);
1087 graph_node(node->match_expr); 1229 graph_node(node->match.expr);
1088 } 1230 }
1089 for (sz i = 0; i < array_size(node->match_cases); i++) { 1231 for (sz i = 0; i < array_size(node->match.cases); i++) {
1090 Node *next = node->match_cases[i]; 1232 Node *next = node->match.cases[i];
1091 println("%d:e->%d:w;", node->id, next->id); 1233 println("%d:e->%d:w;", node->id, next->id);
1092 graph_node(next); 1234 graph_node(next);
1093 } 1235 }
@@ -1112,43 +1254,43 @@ graph_node(Node *node) {
1112 } 1254 }
1113 } break; 1255 } break;
1114 case NODE_IF: { 1256 case NODE_IF: {
1115 if (node->cond_if) { 1257 if (node->ifelse.cond) {
1116 println("%d:e->%d:w;", node->id, node->cond_if->id); 1258 println("%d:e->%d:w;", node->id, node->ifelse.cond->id);
1117 graph_node(node->cond_if); 1259 graph_node(node->ifelse.cond);
1118 } 1260 }
1119 if (node->cond_expr) { 1261 if (node->ifelse.expr_true) {
1120 println("%d:e->%d:w;", node->id, node->cond_expr->id); 1262 println("%d:e->%d:w;", node->id, node->ifelse.expr_true->id);
1121 graph_node(node->cond_expr); 1263 graph_node(node->ifelse.expr_true);
1122 } 1264 }
1123 if (node->cond_else) { 1265 if (node->ifelse.expr_else) {
1124 println("%d:e->%d:w;", node->id, node->cond_else->id); 1266 println("%d:e->%d:w;", node->id, node->ifelse.expr_else->id);
1125 graph_node(node->cond_else); 1267 graph_node(node->ifelse.expr_else);
1126 } 1268 }
1127 } break; 1269 } break;
1128 case NODE_FIELD: 1270 case NODE_FIELD:
1129 case NODE_SET: 1271 case NODE_SET:
1130 case NODE_LET: { 1272 case NODE_LET: {
1131 if (node->var_name) { 1273 if (node->var.name) {
1132 println("%d:e->%d:w;", node->id, node->var_name->id); 1274 println("%d:e->%d:w;", node->id, node->var.name->id);
1133 graph_node(node->var_name); 1275 graph_node(node->var.name);
1134 } 1276 }
1135 if (node->var_type) { 1277 if (node->var.type) {
1136 println("%d:e->%d:w;", node->id, node->var_type->id); 1278 println("%d:e->%d:w;", node->id, node->var.type->id);
1137 graph_node(node->var_type); 1279 graph_node(node->var.type);
1138 } 1280 }
1139 if (node->var_val) { 1281 if (node->var.val) {
1140 println("%d:e->%d:w;", node->id, node->var_val->id); 1282 println("%d:e->%d:w;", node->id, node->var.val->id);
1141 graph_node(node->var_val); 1283 graph_node(node->var.val);
1142 } 1284 }
1143 } break; 1285 } break;
1144 default: { 1286 default: {
1145 if (node->left) { 1287 if (node->binary.left) {
1146 println("%d:e->%d:w;", node->id, node->left->id); 1288 println("%d:e->%d:w;", node->id, node->binary.left->id);
1147 graph_node(node->left); 1289 graph_node(node->binary.left);
1148 } 1290 }
1149 if (node->right) { 1291 if (node->binary.right) {
1150 println("%d:e->%d:w;", node->id, node->right->id); 1292 println("%d:e->%d:w;", node->id, node->binary.right->id);
1151 graph_node(node->right); 1293 graph_node(node->binary.right);
1152 } 1294 }
1153 } break; 1295 } break;
1154 } 1296 }
diff --git a/src/semantic.c b/src/semantic.c
index a0231d5..cebf17a 100644
--- a/src/semantic.c
+++ b/src/semantic.c
@@ -39,6 +39,8 @@ typedef struct Fun {
39 Str name; 39 Str name;
40 Str param_type; 40 Str param_type;
41 Str return_type; 41 Str return_type;
42 Str *param_types;
43 Str *return_types;
42} Fun; 44} Fun;
43 45
44typedef struct Enum { 46typedef struct Enum {
@@ -62,6 +64,7 @@ typedef struct Scope {
62 sz depth; 64 sz depth;
63 Str name; 65 Str name;
64 SymbolMap *symbols; 66 SymbolMap *symbols;
67 StrSet *types;
65 FunMap *funcs; 68 FunMap *funcs;
66 EnumMap *enums; 69 EnumMap *enums;
67 StructMap *structs; 70 StructMap *structs;
@@ -75,6 +78,7 @@ typedef struct Analyzer {
75 Scope **scopes; 78 Scope **scopes;
76 StrSet *numeric_types; 79 StrSet *numeric_types;
77 StrSet *integer_types; 80 StrSet *integer_types;
81 StrSet *float_types;
78 bool err; 82 bool err;
79} Analyzer; 83} Analyzer;
80 84
@@ -82,16 +86,19 @@ Scope *
82typescope_alloc(Analyzer *a, Scope *parent) { 86typescope_alloc(Analyzer *a, Scope *parent) {
83 Scope *scope = arena_calloc(sizeof(Scope), a->storage); 87 Scope *scope = arena_calloc(sizeof(Scope), a->storage);
84 scope->parent = parent; 88 scope->parent = parent;
89 if (parent != NULL) {
90 scope->name = parent->name;
91 }
85 scope->id = a->typescope_gen++; 92 scope->id = a->typescope_gen++;
86 scope->depth = parent == NULL ? 0 : parent->depth + 1; 93 scope->depth = parent == NULL ? 0 : parent->depth + 1;
87 array_push(a->scopes, scope, a->storage); 94 array_push(a->scopes, scope, a->storage);
88 return scope; 95 return scope;
89} 96}
90 97
91SymbolMap * 98StrSet *
92find_type(Scope *scope, Str type) { 99find_type(Scope *scope, Str type) {
93 while (scope != NULL) { 100 while (scope != NULL) {
94 SymbolMap *val = symmap_lookup(&scope->symbols, type); 101 StrSet *val = strset_lookup(&scope->types, type);
95 if (val != NULL) { 102 if (val != NULL) {
96 return val; 103 return val;
97 } 104 }
@@ -276,7 +283,7 @@ Str type_inference(Analyzer *a, Node *node, Scope *scope);
276 283
277void 284void
278typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { 285typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) {
279 if (node->field_type->kind == NODE_COMPOUND_TYPE) { 286 if (node->field.type->kind == NODE_COMPOUND_TYPE) {
280 Str field_name = str_concat(symbol, cstr("."), a->storage); 287 Str field_name = str_concat(symbol, cstr("."), a->storage);
281 field_name = str_concat(field_name, node->value.str, a->storage); 288 field_name = str_concat(field_name, node->value.str, a->storage);
282 if (structmap_lookup(&scope->structs, field_name)) { 289 if (structmap_lookup(&scope->structs, field_name)) {
@@ -285,8 +292,8 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) {
285 a->err = true; 292 a->err = true;
286 } 293 }
287 Str type = cstr("\\{ "); 294 Str type = cstr("\\{ ");
288 for (sz i = 0; i < array_size(node->field_type->elements); i++) { 295 for (sz i = 0; i < array_size(node->field.type->elements); i++) {
289 Node *field = node->field_type->elements[i]; 296 Node *field = node->field.type->elements[i];
290 typecheck_field(a, field, scope, field_name); 297 typecheck_field(a, field, scope, field_name);
291 type = str_concat(type, field->type, a->storage); 298 type = str_concat(type, field->type, a->storage);
292 type = str_concat(type, cstr(" "), a->storage); 299 type = str_concat(type, cstr(" "), a->storage);
@@ -296,16 +303,13 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) {
296 } else { 303 } else {
297 Str field_name = str_concat(symbol, cstr("."), a->storage); 304 Str field_name = str_concat(symbol, cstr("."), a->storage);
298 field_name = str_concat(field_name, node->value.str, a->storage); 305 field_name = str_concat(field_name, node->value.str, a->storage);
299 Str field_type = node->field_type->value.str; 306 Str field_type = node->field.type->value.str;
300 if (!find_type(scope, field_type)) { 307 if (!find_type(scope, field_type)) {
301 eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, 308 eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name,
302 node->field_type->line, node->field_type->col, field_type); 309 node->field.type->line, node->field.type->col, field_type);
303 a->err = true; 310 a->err = true;
304 } 311 }
305 if (node->field_type->is_ptr) { 312 if (node->field.type->kind == NODE_ARR_TYPE) {
306 field_type = str_concat(cstr("@"), field_type, a->storage);
307 }
308 if (node->field_type->kind == NODE_ARR_TYPE) {
309 field_type = str_concat(cstr("@"), field_type, a->storage); 313 field_type = str_concat(cstr("@"), field_type, a->storage);
310 } 314 }
311 if (structmap_lookup(&scope->structs, field_name)) { 315 if (structmap_lookup(&scope->structs, field_name)) {
@@ -313,8 +317,8 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) {
313 a->file_name, node->line, node->col, field_name); 317 a->file_name, node->line, node->col, field_name);
314 a->err = true; 318 a->err = true;
315 } 319 }
316 if (node->field_val) { 320 if (node->field.val) {
317 Str type = type_inference(a, node->field_val, scope); 321 Str type = type_inference(a, node->field.val, scope);
318 if (!str_eq(type, field_type)) { 322 if (!str_eq(type, field_type)) {
319 eprintln( 323 eprintln(
320 "%s:%d:%d: error: mismatched types in struct " 324 "%s:%d:%d: error: mismatched types in struct "
@@ -329,7 +333,7 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) {
329 (Struct){ 333 (Struct){
330 .name = field_name, 334 .name = field_name,
331 .type = field_type, 335 .type = field_type,
332 .val = node->field_val, 336 .val = node->field.val,
333 }, 337 },
334 a->storage); 338 a->storage);
335 symmap_insert(&scope->symbols, field_name, 339 symmap_insert(&scope->symbols, field_name,
@@ -341,10 +345,10 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) {
341 345
342void 346void
343typecheck_lit_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { 347typecheck_lit_field(Analyzer *a, Node *node, Scope *scope, Str symbol) {
344 if (node->field_val->kind == NODE_COMPOUND_TYPE) { 348 if (node->field.val->kind == NODE_COMPOUND_TYPE) {
345 Str type = cstr("\\{ "); 349 Str type = cstr("\\{ ");
346 for (sz i = 0; i < array_size(node->field_val->elements); i++) { 350 for (sz i = 0; i < array_size(node->field.val->elements); i++) {
347 Node *field = node->field_val->elements[i]; 351 Node *field = node->field.val->elements[i];
348 Str field_name = str_concat(symbol, cstr("."), a->storage); 352 Str field_name = str_concat(symbol, cstr("."), a->storage);
349 field_name = str_concat(field_name, field->value.str, a->storage); 353 field_name = str_concat(field_name, field->value.str, a->storage);
350 typecheck_lit_field(a, field, scope, field_name); 354 typecheck_lit_field(a, field, scope, field_name);
@@ -362,7 +366,7 @@ typecheck_lit_field(Analyzer *a, Node *node, Scope *scope, Str symbol) {
362 return; 366 return;
363 } 367 }
364 Str field_type = s->val.type; 368 Str field_type = s->val.type;
365 Str type = type_inference(a, node->field_val, scope); 369 Str type = type_inference(a, node->field.val, scope);
366 if (!str_eq(type, field_type)) { 370 if (!str_eq(type, field_type)) {
367 eprintln( 371 eprintln(
368 "%s:%d:%d: error: mismatched types in struct " 372 "%s:%d:%d: error: mismatched types in struct "
@@ -384,17 +388,18 @@ typecheck_returns(Analyzer *a, Node *node, Str expected) {
384 switch (node->kind) { 388 switch (node->kind) {
385 case NODE_COND: 389 case NODE_COND:
386 case NODE_MATCH: { 390 case NODE_MATCH: {
387 for (sz i = 0; i < array_size(node->match_cases); i++) { 391 for (sz i = 0; i < array_size(node->match.cases); i++) {
388 Node *next = node->match_cases[i]; 392 Node *next = node->match.cases[i];
389 typecheck_returns(a, next, expected); 393 typecheck_returns(a, next, expected);
390 } 394 }
391 } break; 395 } break;
392 case NODE_RETURN: { 396 case NODE_RETURN: {
393 bool err = !str_eq(node->type, expected); 397 Str type = str_remove_prefix(node->type, cstr("ret:"));
398 bool err = !str_eq(type, expected);
394 if (err) { 399 if (err) {
395 eprintln( 400 eprintln(
396 "%s:%d:%d: error: mismatched return type %s, expected %s", 401 "%s:%d:%d: error: mismatched return type %s, expected %s",
397 a->file_name, node->line, node->col, node->type, expected); 402 a->file_name, node->line, node->col, type, expected);
398 a->err = true; 403 a->err = true;
399 } 404 }
400 } break; 405 } break;
@@ -405,17 +410,17 @@ typecheck_returns(Analyzer *a, Node *node, Str expected) {
405 } 410 }
406 } break; 411 } break;
407 case NODE_IF: { 412 case NODE_IF: {
408 if (node->cond_expr) { 413 if (node->ifelse.expr_true) {
409 typecheck_returns(a, node->cond_expr, expected); 414 typecheck_returns(a, node->ifelse.expr_true, expected);
410 } 415 }
411 if (node->cond_else) { 416 if (node->ifelse.expr_else) {
412 typecheck_returns(a, node->cond_else, expected); 417 typecheck_returns(a, node->ifelse.expr_else, expected);
413 } 418 }
414 } break; 419 } break;
415 case NODE_SET: 420 case NODE_SET:
416 case NODE_LET: { 421 case NODE_LET: {
417 if (node->var_val) { 422 if (node->var.val) {
418 typecheck_returns(a, node->var_val, expected); 423 typecheck_returns(a, node->var.val, expected);
419 } 424 }
420 } break; 425 } break;
421 case NODE_ADD: 426 case NODE_ADD:
@@ -435,13 +440,14 @@ typecheck_returns(Analyzer *a, Node *node, Str expected) {
435 case NODE_BITNOT: 440 case NODE_BITNOT:
436 case NODE_BITAND: 441 case NODE_BITAND:
437 case NODE_BITOR: 442 case NODE_BITOR:
443 case NODE_BITXOR:
438 case NODE_BITLSHIFT: 444 case NODE_BITLSHIFT:
439 case NODE_BITRSHIFT: { 445 case NODE_BITRSHIFT: {
440 if (node->left) { 446 if (node->binary.left) {
441 typecheck_returns(a, node->left, expected); 447 typecheck_returns(a, node->binary.left, expected);
442 } 448 }
443 if (node->right) { 449 if (node->binary.right) {
444 typecheck_returns(a, node->right, expected); 450 typecheck_returns(a, node->binary.right, expected);
445 } 451 }
446 } break; 452 } break;
447 default: break; 453 default: break;
@@ -452,66 +458,56 @@ Str
452type_inference(Analyzer *a, Node *node, Scope *scope) { 458type_inference(Analyzer *a, Node *node, Scope *scope) {
453 assert(a); 459 assert(a);
454 assert(scope); 460 assert(scope);
455 if (!node) { 461 if (!node || a->err) {
456 return cstr(""); 462 return cstr("");
457 } 463 }
458 // 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;
474 SymbolMap *type = find_type(scope, type_name); 480 Str type_name = type_inference(a, node->var.type, scope);
475 if (type == NULL) { 481 if (node->var.val) {
476 eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, 482 node->var.val->parent = node;
477 node->var_type->line, node->var_type->col, 483 Str type = type_inference(a, node->var.val, scope);
478 type_name);
479 a->err = true;
480 return cstr("");
481 }
482 if (node->var_type->is_ptr) {
483 type_name = str_concat(cstr("@"), type_name, a->storage);
484 }
485 if (node->var_type->kind == NODE_ARR_TYPE) {
486 type_name = str_concat(cstr("@"), type_name, a->storage);
487 // TODO: typecheck size
488 // TODO: register array in scope
489 }
490 if (node->var_val) {
491 Str type = type_inference(a, node->var_val, scope);
492 if (!type.size) { 484 if (!type.size) {
493 eprintln( 485 eprintln(
494 "%s:%d:%d: error: can't bind `nil` to variable " 486 "%s:%d:%d: error: can't bind `nil` to variable "
495 "'%s'", 487 "'%s'",
496 a->file_name, node->var_type->line, 488 a->file_name, node->var.type->line,
497 node->var_type->col, symbol); 489 node->var.type->col, symbol);
498 a->err = true; 490 a->err = true;
499 return cstr(""); 491 return cstr("");
500 } 492 }
501 // TODO: Consider compatible types.
502 if (!str_eq(type, type_name)) { 493 if (!str_eq(type, type_name)) {
503 // Special case, enums can be treated as ints. 494 if (!(strset_lookup(&a->integer_types, type) &&
504 FindEnumResult res = find_enum(scope, type_name); 495 strset_lookup(&a->integer_types, type_name)) ||
505 if (!(res.map && str_eq(type, cstr("int")))) { 496 !(strset_lookup(&a->numeric_types, type) &&
506 eprintln( 497 strset_lookup(&a->numeric_types, type_name))) {
507 "%s:%d:%d: error: type mismatch, trying to " 498 // Special case, enums can be treated as ints.
508 "assing " 499 FindEnumResult res = find_enum(scope, type_name);
509 "%s" 500 if (!(res.map && str_eq(type, cstr("Int")))) {
510 " to a variable of type %s", 501 eprintln(
511 a->file_name, node->var_type->line, 502 "%s:%d:%d: error: type mismatch, trying to "
512 node->var_type->col, type, type_name); 503 "assing "
513 a->err = true; 504 "%s"
514 return cstr(""); 505 " to a variable of type %s",
506 a->file_name, node->var.type->line,
507 node->var.type->col, type, type_name);
508 a->err = true;
509 return cstr("");
510 }
515 } 511 }
516 } 512 }
517 } 513 }
@@ -521,7 +517,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
521 .kind = SYM_VAR, 517 .kind = SYM_VAR,
522 }, 518 },
523 a->storage); 519 a->storage);
524 node->var_name->type = type_name; 520 node->var.name->type = type_name;
525 symbol = str_concat(cstr("."), symbol, a->storage); 521 symbol = str_concat(cstr("."), symbol, a->storage);
526 symbol = str_concat(symbol, str_from_int(scope->id, a->storage), 522 symbol = str_concat(symbol, str_from_int(scope->id, a->storage),
527 a->storage); 523 a->storage);
@@ -530,13 +526,20 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
530 } 526 }
531 527
532 // We don't know the type for this symbol, perform inference. 528 // We don't know the type for this symbol, perform inference.
533 Str type = type_inference(a, node->var_val, scope); 529 node->var.val->parent = node;
534 if (type.size) { 530 Str type = type_inference(a, node->var.val, scope);
535 symmap_insert(&scope->symbols, symbol, 531 if (!type.size || str_eq(type, cstr("nil")) ||
536 (Symbol){.name = type, .kind = SYM_VAR}, 532 str_has_prefix(type, cstr("ret:"))) {
537 a->storage); 533 eprintln(
538 node->var_name->type = type; 534 "%s:%d:%d: error: can't bind `nil` to variable "
535 "'%s'",
536 a->file_name, node->line, node->col, symbol);
537 a->err = true;
538 return cstr("");
539 } 539 }
540 symmap_insert(&scope->symbols, symbol,
541 (Symbol){.name = type, .kind = SYM_VAR}, a->storage);
542 node->var.name->type = type;
540 symbol = str_concat(cstr("."), symbol, a->storage); 543 symbol = str_concat(cstr("."), symbol, a->storage);
541 symbol = str_concat(symbol, str_from_int(scope->id, a->storage), 544 symbol = str_concat(symbol, str_from_int(scope->id, a->storage),
542 a->storage); 545 a->storage);
@@ -544,18 +547,31 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
544 return node->type; 547 return node->type;
545 } break; 548 } break;
546 case NODE_SET: { 549 case NODE_SET: {
547 Str name = type_inference(a, node->var_name, scope); 550 node->var.name->parent = node;
548 Str val = type_inference(a, node->var_val, scope); 551 node->var.val->parent = node;
552 Str name = type_inference(a, node->var.name, scope);
553 Str val = type_inference(a, node->var.val, scope);
554 if (str_has_prefix(name, cstr("@"))) {
555 name = cstr("Ptr");
556 }
557 if (str_has_prefix(val, cstr("@"))) {
558 val = cstr("Ptr");
559 }
549 if (!str_eq(name, val)) { 560 if (!str_eq(name, val)) {
550 eprintln( 561 if (!(strset_lookup(&a->integer_types, name) &&
551 "%s:%d:%d: error: type mismatch, trying to assing " 562 strset_lookup(&a->integer_types, val)) ||
552 "%s" 563 !(strset_lookup(&a->numeric_types, name) &&
553 " to a variable of type %s", 564 strset_lookup(&a->numeric_types, val))) {
554 a->file_name, node->line, node->col, val, name); 565 eprintln(
555 a->err = true; 566 "%s:%d:%d: error: type mismatch, trying to assing "
556 return cstr(""); 567 "%s"
568 " to a variable of type %s",
569 a->file_name, node->line, node->col, val, name);
570 a->err = true;
571 return cstr("");
572 }
557 } 573 }
558 Str symbol = node->var_name->value.str; 574 Str symbol = node->var.name->value.str;
559 FindSymbolResult sym = find_symbol(scope, symbol); 575 FindSymbolResult sym = find_symbol(scope, symbol);
560 node->unique_name = str_concat(cstr("."), symbol, a->storage); 576 node->unique_name = str_concat(cstr("."), symbol, a->storage);
561 node->unique_name = 577 node->unique_name =
@@ -579,6 +595,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
579 a->storage); 595 a->storage);
580 for (sz i = 0; i < array_size(node->struct_field); i++) { 596 for (sz i = 0; i < array_size(node->struct_field); i++) {
581 Node *field = node->struct_field[i]; 597 Node *field = node->struct_field[i];
598 field->parent = node;
582 typecheck_field(a, field, scope, symbol); 599 typecheck_field(a, field, scope, symbol);
583 } 600 }
584 symmap_insert(&scope->symbols, symbol, 601 symmap_insert(&scope->symbols, symbol,
@@ -600,11 +617,12 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
600 enummap_insert(&scope->enums, symbol, 617 enummap_insert(&scope->enums, symbol,
601 (Enum){ 618 (Enum){
602 .name = symbol, 619 .name = symbol,
603 .val = node->field_val, 620 .val = node->field.val,
604 }, 621 },
605 a->storage); 622 a->storage);
606 for (sz i = 0; i < array_size(node->struct_field); i++) { 623 for (sz i = 0; i < array_size(node->struct_field); i++) {
607 Node *field = node->struct_field[i]; 624 Node *field = node->struct_field[i];
625 field->parent = node;
608 Str field_name = str_concat(symbol, cstr("."), a->storage); 626 Str field_name = str_concat(symbol, cstr("."), a->storage);
609 field_name = 627 field_name =
610 str_concat(field_name, field->value.str, a->storage); 628 str_concat(field_name, field->value.str, a->storage);
@@ -613,9 +631,9 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
613 a->file_name, field->line, field->col, field_name); 631 a->file_name, field->line, field->col, field_name);
614 a->err = true; 632 a->err = true;
615 } 633 }
616 if (field->field_val) { 634 if (field->field.val) {
617 Str type = type_inference(a, field->field_val, scope); 635 Str type = type_inference(a, field->field.val, scope);
618 if (!str_eq(type, cstr("int"))) { 636 if (!str_eq(type, cstr("Int"))) {
619 eprintln( 637 eprintln(
620 "%s:%d:%d: error: non int enum value for '%s.%s'", 638 "%s:%d:%d: error: non int enum value for '%s.%s'",
621 a->file_name, field->line, field->col, symbol, 639 a->file_name, field->line, field->col, symbol,
@@ -637,26 +655,34 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
637 return node->type; 655 return node->type;
638 } break; 656 } break;
639 case NODE_IF: { 657 case NODE_IF: {
640 Str cond_type = type_inference(a, node->cond_if, scope); 658 node->ifelse.cond->parent = node;
641 if (!str_eq(cond_type, cstr("bool"))) { 659 node->ifelse.expr_true->parent = node;
660 Str cond_type = type_inference(a, node->ifelse.cond, scope);
661 if (!str_eq(cond_type, cstr("Bool"))) {
642 emit_semantic_error( 662 emit_semantic_error(
643 a, node->cond_if, 663 a, node->ifelse.cond,
644 cstr("non boolean expression on if condition")); 664 cstr("non boolean expression on if condition"));
645 return cstr(""); 665 return cstr("");
646 } 666 }
647 if (node->cond_expr->kind == NODE_BLOCK) { 667 if (node->ifelse.expr_true->kind == NODE_BLOCK) {
648 node->type = type_inference(a, node->cond_expr, scope); 668 node->type = type_inference(a, node->ifelse.expr_true, scope);
649 } else { 669 } else {
650 Scope *next = typescope_alloc(a, scope); 670 Scope *next = typescope_alloc(a, scope);
651 node->type = type_inference(a, node->cond_expr, next); 671 node->type = type_inference(a, node->ifelse.expr_true, next);
672 }
673 if (str_has_prefix(node->type, cstr("ret:")) ||
674 str_has_prefix(node->type, cstr("flow:"))) {
675 node->type = cstr("nil");
652 } 676 }
653 if (node->cond_else) { 677 if (node->ifelse.expr_else) {
678 node->ifelse.expr_else->parent = node;
654 Str else_type; 679 Str else_type;
655 if (node->cond_else->kind == NODE_BLOCK) { 680 if (node->ifelse.expr_else->kind == NODE_BLOCK) {
656 else_type = type_inference(a, node->cond_else, scope); 681 else_type =
682 type_inference(a, node->ifelse.expr_else, scope);
657 } else { 683 } else {
658 Scope *next = typescope_alloc(a, scope); 684 Scope *next = typescope_alloc(a, scope);
659 else_type = type_inference(a, node->cond_else, next); 685 else_type = type_inference(a, node->ifelse.expr_else, next);
660 } 686 }
661 if (!str_eq(node->type, else_type)) { 687 if (!str_eq(node->type, else_type)) {
662 emit_semantic_error( 688 emit_semantic_error(
@@ -664,9 +690,10 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
664 return cstr(""); 690 return cstr("");
665 } 691 }
666 } 692 }
693
667 // If it returns a value, verify it contains an `else` statement. 694 // If it returns a value, verify it contains an `else` statement.
668 if (!str_eq(node->type, cstr("nil"))) { 695 if (!str_eq(node->type, cstr("nil"))) {
669 if (!node->cond_else) { 696 if (!node->ifelse.expr_else) {
670 emit_semantic_error( 697 emit_semantic_error(
671 a, node, 698 a, node,
672 cstr("missing else statement in if expression")); 699 cstr("missing else statement in if expression"));
@@ -676,25 +703,28 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
676 return node->type; 703 return node->type;
677 } break; 704 } break;
678 case NODE_WHILE: { 705 case NODE_WHILE: {
679 Str cond_type = type_inference(a, node->while_cond, scope); 706 node->loop.cond->parent = node;
680 if (!str_eq(cond_type, cstr("bool"))) { 707 node->loop.expr->parent = node;
708 Str cond_type = type_inference(a, node->loop.cond, scope);
709 if (!str_eq(cond_type, cstr("Bool"))) {
681 emit_semantic_error( 710 emit_semantic_error(
682 a, node->cond_if, 711 a, node->loop.cond,
683 cstr("non boolean expression on while condition")); 712 cstr("non boolean expression on while condition"));
684 return cstr(""); 713 return cstr("");
685 } 714 }
686 if (node->while_expr->kind != NODE_BLOCK) { 715 if (node->loop.expr->kind != NODE_BLOCK) {
687 scope = typescope_alloc(a, scope); 716 scope = typescope_alloc(a, scope);
688 } 717 }
689 type_inference(a, node->while_expr, scope); 718 type_inference(a, node->loop.expr, scope);
690 node->type = cstr("nil"); 719 node->type = cstr("nil");
691 return node->type; 720 return node->type;
692 } break; 721 } break;
693 case NODE_COND: { 722 case NODE_COND: {
694 Str previous = cstr(""); 723 Str previous = cstr("");
695 bool has_else = false; 724 bool has_else = false;
696 for (sz i = 0; i < array_size(node->match_cases); i++) { 725 for (sz i = 0; i < array_size(node->match.cases); i++) {
697 Node *expr = node->match_cases[i]; 726 Node *expr = node->match.cases[i];
727 expr->parent = node;
698 Str next = type_inference(a, expr, scope); 728 Str next = type_inference(a, expr, scope);
699 if (i != 0 && !str_eq(next, previous)) { 729 if (i != 0 && !str_eq(next, previous)) {
700 emit_semantic_error( 730 emit_semantic_error(
@@ -702,13 +732,15 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
702 cstr("non-matching types for cond expressions")); 732 cstr("non-matching types for cond expressions"));
703 return cstr(""); 733 return cstr("");
704 } 734 }
705 if (!expr->case_value) { 735 if (!expr->case_entry.cond) {
706 has_else = true; 736 has_else = true;
707 } 737 }
708 previous = next; 738 previous = next;
709 } 739 }
710 // If it returns a value, verify it contains an `else` statement. 740 // If it returns a value, verify it contains an `else` statement.
711 if (!str_eq(previous, cstr("nil"))) { 741 if (!str_eq(node->type, cstr("nil")) &&
742 !str_has_prefix(node->type, cstr("ret:")) &&
743 !str_has_prefix(node->type, cstr("flow:"))) {
712 if (!has_else) { 744 if (!has_else) {
713 emit_semantic_error( 745 emit_semantic_error(
714 a, node, 746 a, node,
@@ -720,16 +752,18 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
720 return node->type; 752 return node->type;
721 } break; 753 } break;
722 case NODE_MATCH: { 754 case NODE_MATCH: {
723 Str e = type_inference(a, node->match_expr, scope); 755 node->match.expr->parent = node;
724 if (str_eq(e, cstr("int"))) { 756 Str e = type_inference(a, node->match.expr, scope);
757 if (str_eq(e, cstr("Int"))) {
725 // Integer matching. 758 // Integer matching.
726 for (sz i = 0; i < array_size(node->match_cases); i++) { 759 for (sz i = 0; i < array_size(node->match.cases); i++) {
727 Node *field = node->match_cases[i]; 760 Node *field = node->match.cases[i];
728 if (field->case_value) { 761 field->parent = node;
729 if (field->case_value->kind != NODE_NUM_INT && 762 if (field->case_entry.cond) {
730 field->case_value->kind != NODE_NUM_UINT) { 763 if (field->case_entry.cond->kind != NODE_NUM_INT &&
764 field->case_entry.cond->kind != NODE_NUM_UINT) {
731 emit_semantic_error( 765 emit_semantic_error(
732 a, field->case_value, 766 a, field->case_entry.cond,
733 cstr( 767 cstr(
734 "non-integer or enum types on match case")); 768 "non-integer or enum types on match case"));
735 } 769 }
@@ -740,24 +774,26 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
740 FindEnumResult res = find_enum(scope, e); 774 FindEnumResult res = find_enum(scope, e);
741 Str enum_prefix = 775 Str enum_prefix =
742 str_concat(res.map->val.name, cstr("."), a->storage); 776 str_concat(res.map->val.name, cstr("."), a->storage);
743 for (sz i = 0; i < array_size(node->match_cases); i++) { 777 for (sz i = 0; i < array_size(node->match.cases); i++) {
744 Node *field = node->match_cases[i]; 778 Node *field = node->match.cases[i];
745 if (field->case_value) { 779 field->parent = node;
780 if (field->case_entry.cond) {
746 Str field_name = str_concat( 781 Str field_name = str_concat(
747 enum_prefix, field->case_value->value.str, 782 enum_prefix, field->case_entry.cond->value.str,
748 a->storage); 783 a->storage);
749 if (!enummap_lookup(&res.scope->enums, field_name)) { 784 if (!enummap_lookup(&res.scope->enums, field_name)) {
750 eprintln("%s:%d:%d: error: unknown enum field '%s'", 785 eprintln("%s:%d:%d: error: unknown enum field '%s'",
751 a->file_name, field->case_value->line, 786 a->file_name, field->case_entry.cond->line,
752 field->case_value->col, field_name); 787 field->case_entry.cond->col, field_name);
753 a->err = true; 788 a->err = true;
754 } 789 }
755 } 790 }
756 } 791 }
757 } 792 }
758 Str previous = cstr(""); 793 Str previous = cstr("");
759 for (sz i = 0; i < array_size(node->match_cases); i++) { 794 for (sz i = 0; i < array_size(node->match.cases); i++) {
760 Node *expr = node->match_cases[i]; 795 Node *expr = node->match.cases[i];
796 expr->parent = node;
761 Str next = type_inference(a, expr, scope); 797 Str next = type_inference(a, expr, scope);
762 if (i != 0 && !str_eq(next, previous)) { 798 if (i != 0 && !str_eq(next, previous)) {
763 emit_semantic_error( 799 emit_semantic_error(
@@ -771,29 +807,32 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
771 return node->type; 807 return node->type;
772 } break; 808 } break;
773 case NODE_CASE_MATCH: { 809 case NODE_CASE_MATCH: {
774 if (node->case_expr->kind != NODE_BLOCK) { 810 if (node->case_entry.expr->kind != NODE_BLOCK) {
775 scope = typescope_alloc(a, scope); 811 scope = typescope_alloc(a, scope);
776 } 812 }
777 node->type = type_inference(a, node->case_expr, scope); 813 node->case_entry.expr->parent = node;
814 node->type = type_inference(a, node->case_entry.expr, scope);
778 return node->type; 815 return node->type;
779 } break; 816 } break;
780 case NODE_CASE_COND: { 817 case NODE_CASE_COND: {
781 if (node->case_value) { 818 node->case_entry.expr->parent = node;
782 Str cond = type_inference(a, node->case_value, scope); 819 if (node->case_entry.cond) {
783 if (!str_eq(cond, cstr("bool"))) { 820 node->case_entry.cond->parent = node;
821 Str cond = type_inference(a, node->case_entry.cond, scope);
822 if (!str_eq(cond, cstr("Bool"))) {
784 emit_semantic_error(a, node, 823 emit_semantic_error(a, node,
785 cstr("non-boolean case condition")); 824 cstr("non-boolean case condition"));
786 } 825 }
787 } 826 }
788 if (node->case_expr->kind != NODE_BLOCK) { 827 if (node->case_entry.expr->kind != NODE_BLOCK) {
789 scope = typescope_alloc(a, scope); 828 scope = typescope_alloc(a, scope);
790 } 829 }
791 node->type = type_inference(a, node->case_expr, scope); 830 node->type = type_inference(a, node->case_entry.expr, scope);
792 return node->type; 831 return node->type;
793 } break; 832 } break;
794 case NODE_TRUE: 833 case NODE_TRUE:
795 case NODE_FALSE: { 834 case NODE_FALSE: {
796 node->type = cstr("bool"); 835 node->type = cstr("Bool");
797 return node->type; 836 return node->type;
798 } break; 837 } break;
799 case NODE_NIL: { 838 case NODE_NIL: {
@@ -803,21 +842,23 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
803 case NODE_NOT: 842 case NODE_NOT:
804 case NODE_AND: 843 case NODE_AND:
805 case NODE_OR: { 844 case NODE_OR: {
806 Str left = type_inference(a, node->left, scope); 845 node->binary.left->parent = node;
807 if (!str_eq(left, cstr("bool"))) { 846 Str left = type_inference(a, node->binary.left, scope);
847 if (!str_eq(left, cstr("Bool"))) {
808 emit_semantic_error(a, node, 848 emit_semantic_error(a, node,
809 cstr("expected bool on logic expression")); 849 cstr("expected bool on logic expression"));
810 return cstr(""); 850 return cstr("");
811 } 851 }
812 if (node->right) { 852 if (node->binary.right) {
813 Str right = type_inference(a, node->right, scope); 853 node->binary.right->parent = node;
814 if (!str_eq(right, cstr("bool"))) { 854 Str right = type_inference(a, node->binary.right, scope);
855 if (!str_eq(right, cstr("Bool"))) {
815 emit_semantic_error( 856 emit_semantic_error(
816 a, node, cstr("expected bool on logic expression")); 857 a, node, cstr("expected bool on logic expression"));
817 return cstr(""); 858 return cstr("");
818 } 859 }
819 } 860 }
820 node->type = cstr("bool"); 861 node->type = cstr("Bool");
821 return node->type; 862 return node->type;
822 } break; 863 } break;
823 case NODE_EQ: 864 case NODE_EQ:
@@ -826,18 +867,26 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
826 case NODE_GT: 867 case NODE_GT:
827 case NODE_LE: 868 case NODE_LE:
828 case NODE_GE: { 869 case NODE_GE: {
829 Str left = type_inference(a, node->left, scope); 870 node->binary.left->parent = node;
830 Str right = type_inference(a, node->right, scope); 871 node->binary.right->parent = node;
872 Str left = type_inference(a, node->binary.left, scope);
873 Str right = type_inference(a, node->binary.right, scope);
831 if (!str_eq(left, right)) { 874 if (!str_eq(left, right)) {
832 emit_semantic_error( 875 if (!(strset_lookup(&a->integer_types, left) &&
833 a, node, cstr("mismatched types on binary expression")); 876 strset_lookup(&a->integer_types, right)) ||
834 return cstr(""); 877 !(strset_lookup(&a->numeric_types, left) &&
878 strset_lookup(&a->numeric_types, right))) {
879 emit_semantic_error(
880 a, node, cstr("mismatched types on binary expression"));
881 return cstr("");
882 }
835 } 883 }
836 node->type = cstr("bool"); 884 node->type = cstr("Bool");
837 return node->type; 885 return node->type;
838 } break; 886 } break;
839 case NODE_BITNOT: { 887 case NODE_BITNOT: {
840 Str left = type_inference(a, node->left, scope); 888 node->binary.left->parent = node;
889 Str left = type_inference(a, node->binary.left, scope);
841 if (!strset_lookup(&a->integer_types, left)) { 890 if (!strset_lookup(&a->integer_types, left)) {
842 emit_semantic_error( 891 emit_semantic_error(
843 a, node, cstr("non integer type on bit twiddling expr")); 892 a, node, cstr("non integer type on bit twiddling expr"));
@@ -848,10 +897,13 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
848 } break; 897 } break;
849 case NODE_BITAND: 898 case NODE_BITAND:
850 case NODE_BITOR: 899 case NODE_BITOR:
900 case NODE_BITXOR:
851 case NODE_BITLSHIFT: 901 case NODE_BITLSHIFT:
852 case NODE_BITRSHIFT: { 902 case NODE_BITRSHIFT: {
853 Str left = type_inference(a, node->left, scope); 903 node->binary.left->parent = node;
854 Str right = type_inference(a, node->right, scope); 904 node->binary.right->parent = node;
905 Str left = type_inference(a, node->binary.left, scope);
906 Str right = type_inference(a, node->binary.right, scope);
855 if (!strset_lookup(&a->integer_types, left) || 907 if (!strset_lookup(&a->integer_types, left) ||
856 !strset_lookup(&a->integer_types, right)) { 908 !strset_lookup(&a->integer_types, right)) {
857 emit_semantic_error( 909 emit_semantic_error(
@@ -866,8 +918,17 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
866 case NODE_DIV: 918 case NODE_DIV:
867 case NODE_MUL: 919 case NODE_MUL:
868 case NODE_MOD: { 920 case NODE_MOD: {
869 Str left = type_inference(a, node->left, scope); 921 node->binary.left->parent = node;
870 Str right = type_inference(a, node->right, scope); 922 node->binary.right->parent = node;
923 Str left = type_inference(a, node->binary.left, scope);
924 Str right = type_inference(a, node->binary.right, scope);
925 // Enable pointer arithmetic.
926 if (str_has_prefix(left, cstr("@"))) {
927 left = cstr("Ptr");
928 }
929 if (str_has_prefix(right, cstr("@"))) {
930 right = cstr("Ptr");
931 }
871 if (!strset_lookup(&a->numeric_types, left) || 932 if (!strset_lookup(&a->numeric_types, left) ||
872 !strset_lookup(&a->numeric_types, right)) { 933 !strset_lookup(&a->numeric_types, right)) {
873 emit_semantic_error( 934 emit_semantic_error(
@@ -875,59 +936,105 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
875 return cstr(""); 936 return cstr("");
876 } 937 }
877 if (!str_eq(left, right)) { 938 if (!str_eq(left, right)) {
878 emit_semantic_error( 939 if (!((strset_lookup(&a->integer_types, left) &&
879 a, node, cstr("mismatched types on binary expression")); 940 strset_lookup(&a->integer_types, right)) ||
880 return cstr(""); 941 (strset_lookup(&a->float_types, left) &&
942 strset_lookup(&a->float_types, right)))) {
943 emit_semantic_error(
944 a, node, cstr("mismatched types on binary expression"));
945 return cstr("");
946 }
881 } 947 }
882 node->type = left; 948 node->type = left;
883 return node->type; 949 return node->type;
884 } break; 950 } break;
885 case NODE_NUM_UINT: { 951 case NODE_NUM_UINT: {
886 node->type = cstr("int"); 952 node->type = cstr("UInt");
887 return node->type; 953 return node->type;
888 } break; 954 } break;
889 case NODE_NUM_INT: { 955 case NODE_NUM_INT: {
890 node->type = cstr("int"); 956 node->type = cstr("Int");
891 return node->type; 957 return node->type;
892 } break; 958 } break;
893 case NODE_NUM_FLOAT: { 959 case NODE_NUM_FLOAT: {
894 node->type = cstr("f64"); 960 node->type = cstr("F64");
895 return node->type; 961 return node->type;
896 } break; 962 } break;
897 case NODE_STRING: { 963 case NODE_STRING: {
898 node->type = cstr("str"); 964 node->type = cstr("Str");
899 return node->type; 965 return node->type;
900 } break; 966 } break;
901 case NODE_ARR_TYPE: 967 case NODE_ARR_TYPE:
902 case NODE_TYPE: { 968 case NODE_TYPE: {
903 SymbolMap *type = find_type(scope, node->value.str); 969 Str type = node->value.str;
904 if (!type) { 970 StrSet *set = find_type(scope, node->value.str);
971 if (!set) {
905 emit_semantic_error(a, node, cstr("unknown type")); 972 emit_semantic_error(a, node, cstr("unknown type"));
906 return cstr(""); 973 return cstr("");
907 } 974 }
908 node->type = type->val.name; 975 Node *next = node->t.next;
976 while (next) {
977 if (next->kind == NODE_PTR) {
978 type = str_concat(cstr("@"), type, a->storage);
979 }
980 next = next->t.next;
981 }
982 node->type = type;
983 return node->type;
984 } break;
985 case NODE_DEREF: {
986 Node *next = node->deref.next;
987 Str amount = cstr("@");
988 while (next) {
989 if (next->kind == NODE_SYMBOL) {
990 break;
991 }
992 next = next->deref.next;
993 amount = str_concat(cstr("@"), amount, a->storage);
994 }
995 Str symbol = next->value.str;
996 Str type = type_inference(a, next, scope);
997 if (!str_has_prefix(type, amount)) {
998 eprintln(
999 "%s:%d:%d: error: invalid type dereference %s from type %s",
1000 a->file_name, node->line, node->col, str_concat(symbol, amount, a->storage), type);
1001 a->err = true;
1002 return cstr("");
1003 }
1004 type = str_remove_prefix(type, amount);
1005 node->value.str = next->value.str;
1006 node->unique_name = next->unique_name;
1007 node->type = type;
909 return node->type; 1008 return node->type;
910 } break; 1009 } break;
911 case NODE_SYMBOL_IDX: 1010 case NODE_SYMBOL_IDX:
912 case NODE_SYMBOL: { 1011 case NODE_SYMBOL: {
913 Str symbol = node->value.str; 1012 Str symbol = node->value.str;
914 SymbolMap *type = find_type(scope, symbol); 1013
915 if (!type) { 1014 FindSymbolResult sym = find_symbol(scope, symbol);
1015 if (!sym.map) {
916 eprintln("%s:%d:%d: error: couldn't resolve symbol '%s'", 1016 eprintln("%s:%d:%d: error: couldn't resolve symbol '%s'",
917 a->file_name, node->line, node->col, symbol); 1017 a->file_name, node->line, node->col, symbol);
918 a->err = true; 1018 a->err = true;
919 return cstr(""); 1019 return cstr("");
920 } 1020 }
921 1021
922 FindSymbolResult sym = find_symbol(scope, symbol); 1022 if (!str_eq(sym.scope->name, scope->name) && sym.scope->name.size) {
1023 eprintln(
1024 "%s:%d:%d: error: can't capture external local symbol '%s'",
1025 a->file_name, node->line, node->col, symbol);
1026 a->err = true;
1027 return cstr("");
1028 }
923 node->unique_name = str_concat(cstr("."), symbol, a->storage); 1029 node->unique_name = str_concat(cstr("."), symbol, a->storage);
924 node->unique_name = 1030 node->unique_name =
925 str_concat(node->unique_name, 1031 str_concat(node->unique_name,
926 str_from_int(sym.scope->id, a->storage), a->storage); 1032 str_from_int(sym.scope->id, a->storage), a->storage);
927 1033
928 Str type_name = type->val.name; 1034 Str type_name = sym.map->val.name;
929 if (node->kind == NODE_SYMBOL_IDX) { 1035 if (node->kind == NODE_SYMBOL_IDX) {
930 Str idx_type = type_inference(a, node->arr_size, scope); 1036 node->sym.arr_size->parent = node;
1037 Str idx_type = type_inference(a, node->sym.arr_size, scope);
931 if (!strset_lookup(&a->integer_types, idx_type)) { 1038 if (!strset_lookup(&a->integer_types, idx_type)) {
932 emit_semantic_error( 1039 emit_semantic_error(
933 a, node, cstr("can't resolve non integer index")); 1040 a, node, cstr("can't resolve non integer index"));
@@ -935,13 +1042,10 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
935 } 1042 }
936 type_name = str_remove_prefix(type_name, cstr("@")); 1043 type_name = str_remove_prefix(type_name, cstr("@"));
937 } 1044 }
938 if (node->is_ptr) {
939 type_name = str_concat(cstr("@"), type_name, a->storage);
940 }
941 1045
942 FindEnumResult e = find_enum(scope, type_name); 1046 FindEnumResult e = find_enum(scope, type_name);
943 if (e.map && str_eq(symbol, type_name)) { 1047 if (e.map && str_eq(symbol, type_name)) {
944 if (!node->next) { 1048 if (!node->sym.next) {
945 eprintln( 1049 eprintln(
946 "%s:%d:%d: error: unspecified enum field for symbol " 1050 "%s:%d:%d: error: unspecified enum field for symbol "
947 "'%s'", 1051 "'%s'",
@@ -951,20 +1055,21 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
951 } 1055 }
952 // Check if there is a next and it matches the enum field. 1056 // Check if there is a next and it matches the enum field.
953 Str field = str_concat(type_name, cstr("."), a->storage); 1057 Str field = str_concat(type_name, cstr("."), a->storage);
954 field = str_concat(field, node->next->value.str, a->storage); 1058 field =
1059 str_concat(field, node->sym.next->value.str, a->storage);
955 if (!enummap_lookup(&e.scope->enums, field)) { 1060 if (!enummap_lookup(&e.scope->enums, field)) {
956 eprintln( 1061 eprintln(
957 "%s:%d:%d: error: unknown enum field for " 1062 "%s:%d:%d: error: unknown enum field for "
958 "'%s': %s", 1063 "'%s': %s",
959 a->file_name, node->line, node->col, symbol, 1064 a->file_name, node->line, node->col, symbol,
960 node->next->value.str); 1065 node->sym.next->value.str);
961 a->err = true; 1066 a->err = true;
962 return cstr(""); 1067 return cstr("");
963 } 1068 }
964 1069
965 node->next->type = type_name; 1070 node->sym.next->type = type_name;
966 node->type = type_name; 1071 node->type = type_name;
967 return node->next->type; 1072 return node->sym.next->type;
968 } 1073 }
969 1074
970 FindStructResult s = find_struct(scope, type_name); 1075 FindStructResult s = find_struct(scope, type_name);
@@ -977,11 +1082,11 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
977 a->err = true; 1082 a->err = true;
978 return cstr(""); 1083 return cstr("");
979 } else { 1084 } else {
980 if (node->next) { 1085 if (node->sym.next) {
981 Str chain = type_name; 1086 Str chain = type_name;
982 Node *next = node; 1087 Node *next = node;
983 while (next->next) { 1088 while (next->sym.next) {
984 next = next->next; 1089 next = next->sym.next;
985 chain = str_concat(chain, cstr("."), a->storage); 1090 chain = str_concat(chain, cstr("."), a->storage);
986 chain = 1091 chain =
987 str_concat(chain, next->value.str, a->storage); 1092 str_concat(chain, next->value.str, a->storage);
@@ -997,8 +1102,9 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
997 } 1102 }
998 Str field_type = field->val.type; 1103 Str field_type = field->val.type;
999 if (next->kind == NODE_SYMBOL_IDX) { 1104 if (next->kind == NODE_SYMBOL_IDX) {
1105 node->sym.arr_size->parent = node;
1000 Str idx_type = 1106 Str idx_type =
1001 type_inference(a, next->arr_size, scope); 1107 type_inference(a, next->sym.arr_size, scope);
1002 if (!strset_lookup(&a->integer_types, idx_type)) { 1108 if (!strset_lookup(&a->integer_types, idx_type)) {
1003 emit_semantic_error( 1109 emit_semantic_error(
1004 a, next, 1110 a, next,
@@ -1016,6 +1122,12 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
1016 node->type = type_name; 1122 node->type = type_name;
1017 return node->type; 1123 return node->type;
1018 } break; 1124 } break;
1125 case NODE_PTR: {
1126 Str type = type_inference(a, node->t.next, scope);
1127 type = str_concat(cstr("@"), type, a->storage);
1128 node->type = type;
1129 return node->type;
1130 } break;
1019 case NODE_STRUCT_LIT: { 1131 case NODE_STRUCT_LIT: {
1020 Str name = node->value.str; 1132 Str name = node->value.str;
1021 FindStructResult s = find_struct(scope, name); 1133 FindStructResult s = find_struct(scope, name);
@@ -1029,6 +1141,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
1029 StrSet *set = NULL; 1141 StrSet *set = NULL;
1030 for (sz i = 0; i < array_size(node->elements); i++) { 1142 for (sz i = 0; i < array_size(node->elements); i++) {
1031 Node *next = node->elements[i]; 1143 Node *next = node->elements[i];
1144 next->parent = node;
1032 Str field_name = str_concat(name, cstr("."), a->storage); 1145 Str field_name = str_concat(name, cstr("."), a->storage);
1033 field_name = 1146 field_name =
1034 str_concat(field_name, next->value.str, a->storage); 1147 str_concat(field_name, next->value.str, a->storage);
@@ -1066,25 +1179,56 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
1066 1179
1067 // Check that actual parameters typecheck 1180 // Check that actual parameters typecheck
1068 Str args = cstr(""); 1181 Str args = cstr("");
1182
1183 // Check function aritiy.
1184 sz arity_fun = array_size(fun->val.param_types);
1185 sz arity_call = array_size(node->elements);
1186 if (!str_eq(fun->val.param_type, cstr("..."))) {
1187 if (arity_fun != arity_call) {
1188 eprintln(
1189 "%s:%d:%d: error: wrong number of parameters for "
1190 "funcall: "
1191 "%s "
1192 "expected "
1193 "%d"
1194 " got %d",
1195 a->file_name, node->line, node->col, symbol, arity_fun,
1196 arity_call);
1197 a->err = true;
1198 return cstr("");
1199 }
1200 }
1069 for (sz i = 0; i < array_size(node->elements); i++) { 1201 for (sz i = 0; i < array_size(node->elements); i++) {
1070 Node *expr = node->elements[i]; 1202 Node *expr = node->elements[i];
1203 expr->parent = node;
1071 Str type = type_inference(a, expr, scope); 1204 Str type = type_inference(a, expr, scope);
1072 args = str_concat(args, type, a->storage); 1205 args = str_concat(args, type, a->storage);
1073 if (i != array_size(node->elements) - 1) { 1206 if (i != array_size(node->elements) - 1) {
1074 args = str_concat(args, cstr(","), a->storage); 1207 args = str_concat(args, cstr(","), a->storage);
1075 } 1208 }
1209 if (!str_eq(fun->val.param_type, cstr("..."))) {
1210 Str expected = fun->val.param_types[i];
1211 if (!str_eq(type, expected)) {
1212 if (!(strset_lookup(&a->integer_types, type) &&
1213 strset_lookup(&a->integer_types, expected)) ||
1214 !(strset_lookup(&a->numeric_types, type) &&
1215 strset_lookup(&a->numeric_types, expected))) {
1216 eprintln(
1217 "%s:%d:%d: error: mismatched parameter types: "
1218 "%s "
1219 "expected "
1220 "%s",
1221 a->file_name, node->line, node->col, type,
1222 expected);
1223 a->err = true;
1224 return cstr("");
1225 }
1226 }
1227 }
1076 } 1228 }
1077 if (!args.size) { 1229 if (!args.size) {
1078 args = cstr("nil"); 1230 args = cstr("nil");
1079 } 1231 }
1080 Str expected = fun->val.param_type;
1081 if (!str_eq(args, expected) && !str_eq(expected, cstr("..."))) {
1082 eprintln(
1083 "%s:%d:%d: error: mismatched parameter types: %s expected "
1084 "%s",
1085 a->file_name, node->line, node->col, args, expected);
1086 a->err = true;
1087 }
1088 node->type = fun->val.return_type; 1232 node->type = fun->val.return_type;
1089 return node->type; 1233 return node->type;
1090 } break; 1234 } break;
@@ -1093,15 +1237,27 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
1093 Str type; 1237 Str type;
1094 for (sz i = 0; i < array_size(node->elements); i++) { 1238 for (sz i = 0; i < array_size(node->elements); i++) {
1095 Node *expr = node->elements[i]; 1239 Node *expr = node->elements[i];
1240 expr->parent = node;
1096 type = type_inference(a, expr, scope); 1241 type = type_inference(a, expr, scope);
1242 if (str_has_prefix(type, cstr("ret:")) ||
1243 str_has_prefix(type, cstr("flow:"))) {
1244 break;
1245 }
1097 } 1246 }
1098 node->type = type; 1247 node->type = type;
1099 return node->type; 1248 return node->type;
1100 } break; 1249 } break;
1101 case NODE_RETURN: { 1250 case NODE_RETURN: {
1102 Str ret_type = cstr(""); 1251 if (!scope->name.size) {
1252 emit_semantic_error(
1253 a, node, cstr("return statement outside a function"));
1254 a->err = true;
1255 return cstr("");
1256 }
1257 Str ret_type = cstr("ret:");
1103 for (sz i = 0; i < array_size(node->elements); i++) { 1258 for (sz i = 0; i < array_size(node->elements); i++) {
1104 Node *expr = node->elements[i]; 1259 Node *expr = node->elements[i];
1260 expr->parent = node;
1105 Str type = type_inference(a, expr, scope); 1261 Str type = type_inference(a, expr, scope);
1106 ret_type = str_concat(ret_type, type, a->storage); 1262 ret_type = str_concat(ret_type, type, a->storage);
1107 if (i != array_size(node->elements) - 1) { 1263 if (i != array_size(node->elements) - 1) {
@@ -1114,118 +1270,151 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
1114 node->type = ret_type; 1270 node->type = ret_type;
1115 return node->type; 1271 return node->type;
1116 } break; 1272 } break;
1273 case NODE_CONTINUE:
1274 case NODE_BREAK: {
1275 // Check if we are inside a loop.
1276 Node *parent = node->parent;
1277 bool inside_loop = false;
1278 while (parent != NULL) {
1279 if (parent->kind == NODE_WHILE) {
1280 inside_loop = true;
1281 break;
1282 }
1283 parent = parent->parent;
1284 }
1285 if (!inside_loop) {
1286 eprintln(
1287 "%s:%d:%d: error: control flow statement outside a "
1288 "loop",
1289 a->file_name, node->line, node->col);
1290 a->err = true;
1291 return cstr("");
1292 }
1293 node->type = cstr("flow:");
1294 return node->type;
1295 } break;
1117 case NODE_FUN: { 1296 case NODE_FUN: {
1118 node->type = cstr("nil"); 1297 node->type = cstr("nil");
1119 Scope *prev_scope = scope; 1298 Scope *prev_scope = scope;
1120 scope = typescope_alloc(a, scope); 1299 scope = typescope_alloc(a, scope);
1121 Str param_type = cstr(""); 1300 Str param_type = cstr("");
1122 for (sz i = 0; i < array_size(node->func_params); i++) { 1301 Str symbol = node->func.name->value.str;
1123 Node *param = node->func_params[i]; 1302 Fun fun = (Fun){.name = symbol};
1124 Str symbol = param->param_name->value.str; 1303 for (sz i = 0; i < array_size(node->func.params); i++) {
1125 Str type = param->param_type->value.str; 1304 Node *param = node->func.params[i];
1126 if (param->param_type->is_ptr) { 1305 param->parent = node;
1306 Str symbol = param->param.name->value.str;
1307 Str type = param->param.type->value.str;
1308 if (param->param.type->kind == NODE_ARR_TYPE) {
1127 type = str_concat(cstr("@"), type, a->storage); 1309 type = str_concat(cstr("@"), type, a->storage);
1128 } 1310 }
1129 if (param->param_type->kind == NODE_ARR_TYPE) { 1311 param->param.name->type =
1130 type = str_concat(cstr("@"), type, a->storage); 1312 type_inference(a, param->param.type, scope);
1131 }
1132 param->param_name->type =
1133 type_inference(a, param->param_type, scope);
1134 param->type = type; 1313 param->type = type;
1314 array_push(fun.param_types, type, a->storage);
1135 symmap_insert(&scope->symbols, symbol, 1315 symmap_insert(&scope->symbols, symbol,
1136 (Symbol){.name = type, .kind = SYM_PARAM}, 1316 (Symbol){.name = type, .kind = SYM_PARAM},
1137 a->storage); 1317 a->storage);
1138 param_type = str_concat(param_type, type, a->storage); 1318 param_type = str_concat(param_type, type, a->storage);
1139 if (i != array_size(node->func_params) - 1) { 1319 if (i != array_size(node->func.params) - 1) {
1140 param_type = str_concat(param_type, cstr(","), a->storage); 1320 param_type = str_concat(param_type, cstr(","), a->storage);
1141 } 1321 }
1322 symbol = str_concat(cstr("."), symbol, a->storage);
1323 symbol = str_concat(symbol, str_from_int(scope->id, a->storage),
1324 a->storage);
1325 param->unique_name = symbol;
1142 } 1326 }
1143 if (!param_type.size) { 1327 if (!param_type.size) {
1144 param_type = cstr("nil"); 1328 param_type = cstr("nil");
1145 } 1329 }
1146 node->fun_params = param_type; 1330 node->type_params = param_type;
1147 1331
1148 Str ret_type = cstr(""); 1332 Str ret_type = cstr("");
1149 for (sz i = 0; i < array_size(node->func_ret); i++) { 1333 for (sz i = 0; i < array_size(node->func.ret); i++) {
1150 Node *expr = node->func_ret[i]; 1334 Node *expr = node->func.ret[i];
1335 expr->parent = node;
1151 Str type = type_inference(a, expr, scope); 1336 Str type = type_inference(a, expr, scope);
1152 if (expr->is_ptr) {
1153 type = str_concat(cstr("@"), type, a->storage);
1154 }
1155 if (expr->kind == NODE_ARR_TYPE) { 1337 if (expr->kind == NODE_ARR_TYPE) {
1156 type = str_concat(cstr("@"), type, a->storage); 1338 type = str_concat(cstr("@"), type, a->storage);
1157 } 1339 }
1158 ret_type = str_concat(ret_type, type, a->storage); 1340 ret_type = str_concat(ret_type, type, a->storage);
1159 if (i != array_size(node->func_ret) - 1) { 1341 array_push(fun.return_types, ret_type, a->storage);
1342 if (i != array_size(node->func.ret) - 1) {
1160 ret_type = str_concat(ret_type, cstr(","), a->storage); 1343 ret_type = str_concat(ret_type, cstr(","), a->storage);
1161 } 1344 }
1162 } 1345 }
1163 if (!ret_type.size) { 1346 if (!ret_type.size) {
1164 ret_type = cstr("nil"); 1347 ret_type = cstr("nil");
1165 } 1348 }
1166 node->fun_return = ret_type; 1349 node->type_returns = ret_type;
1167 1350
1168 Str symbol = node->func_name->value.str;
1169 if (prev_scope->parent != NULL) { 1351 if (prev_scope->parent != NULL) {
1170 if (symmap_lookup(&prev_scope->symbols, symbol)) { 1352 if (symmap_lookup(&prev_scope->symbols, symbol)) {
1171 eprintln( 1353 eprintln(
1172 "%s:%d:%d: error: function '%s' already defined in " 1354 "%s:%d:%d: error: function '%s' already defined in "
1173 "current " 1355 "current "
1174 "scope ", 1356 "scope ",
1175 a->file_name, node->var_name->line, node->var_name->col, 1357 a->file_name, node->var.name->line, node->var.name->col,
1176 symbol); 1358 symbol);
1177 a->err = true; 1359 a->err = true;
1178 return cstr(""); 1360 return cstr("");
1179 } 1361 }
1180 symmap_insert(&scope->symbols, symbol, 1362 symmap_insert(&prev_scope->symbols, symbol,
1181 (Symbol){.name = symbol, .kind = SYM_FUN}, 1363 (Symbol){.name = symbol, .kind = SYM_FUN},
1182 a->storage); 1364 a->storage);
1183 } 1365 }
1184 scope->name = symbol; 1366 scope->name = symbol;
1185 funmap_insert(&prev_scope->funcs, symbol, 1367 fun.param_type = param_type;
1186 (Fun){.name = symbol, 1368 fun.return_type = ret_type;
1187 .param_type = param_type, 1369 funmap_insert(&prev_scope->funcs, symbol, fun, a->storage);
1188 .return_type = ret_type},
1189 a->storage);
1190 symbol = str_concat(cstr("."), symbol, a->storage); 1370 symbol = str_concat(cstr("."), symbol, a->storage);
1191 symbol = str_concat(symbol, str_from_int(prev_scope->id, a->storage), 1371 symbol = str_concat(
1192 a->storage); 1372 symbol, str_from_int(prev_scope->id, a->storage), a->storage);
1193 node->unique_name = symbol; 1373 node->unique_name = symbol;
1194 1374
1195 if (node->func_body->kind == NODE_BLOCK) { 1375 if (node->func.body->kind == NODE_BLOCK) {
1196 Str type; 1376 Str type;
1197 for (sz i = 0; i < array_size(node->func_body->elements); i++) { 1377 for (sz i = 0; i < array_size(node->func.body->elements); i++) {
1198 Node *expr = node->func_body->elements[i]; 1378 Node *expr = node->func.body->elements[i];
1379 expr->parent = node;
1199 type = type_inference(a, expr, scope); 1380 type = type_inference(a, expr, scope);
1200 } 1381 }
1201 if (!type.size) { 1382 if (!type.size) {
1202 type = cstr("nil"); 1383 type = cstr("nil");
1203 } 1384 }
1204 node->func_body->type = type; 1385 node->func.body->type = type;
1205 } else { 1386 } else {
1206 type_inference(a, node->func_body, scope); 1387 node->func.body->parent = node;
1388 type_inference(a, node->func.body, scope);
1207 } 1389 }
1208 1390
1209 // Ensure main body return matches the prototype. 1391 // Ensure main body return matches the prototype.
1210 if (!str_eq(node->func_body->type, ret_type)) { 1392 Str type = str_remove_prefix(node->func.body->type, cstr("ret:"));
1211 eprintln( 1393 node->func.body->type = type;
1212 "%s:%d:%d: error: mismatched return type %s, expected %s", 1394 if (!str_eq(type, ret_type)) {
1213 a->file_name, node->line, node->col, node->func_body->type, 1395 if (!(strset_lookup(&a->integer_types, type) &&
1214 ret_type); 1396 strset_lookup(&a->integer_types, ret_type)) ||
1215 a->err = true; 1397 !(strset_lookup(&a->numeric_types, type) &&
1398 strset_lookup(&a->numeric_types, ret_type))) {
1399 eprintln(
1400 "%s:%d:%d: error: mismatched return type %s, "
1401 "expected "
1402 "%s",
1403 a->file_name, node->line, node->col, type, ret_type);
1404 a->err = true;
1405 }
1216 } 1406 }
1217 1407
1218 // Ensure ALL return statements match the function prototype. 1408 // Ensure ALL return statements match the function prototype.
1219 typecheck_returns(a, node->func_body, ret_type); 1409 typecheck_returns(a, node->func.body, ret_type);
1220
1221 // TODO: should return statements be allowed on let blocks?
1222 return node->type; 1410 return node->type;
1223 } break; 1411 } break;
1224 default: { 1412 default: {
1225 emit_semantic_error(a, node, 1413 eprintln(
1226 cstr("type inference not implemented for this " 1414 "%s:%d:%d: error: type inference not implemented for node "
1227 "kind of expression")); 1415 "type: %s",
1228 println("KIND: %s", node_str[node->kind]); 1416 a->file_name, node->line, node->col, node_str[node->kind]);
1417 a->err = true;
1229 } break; 1418 } break;
1230 } 1419 }
1231 return cstr(""); 1420 return cstr("");
@@ -1254,48 +1443,92 @@ symbolic_analysis(Analyzer *a, Parser *parser) {
1254 a->storage); 1443 a->storage);
1255 } 1444 }
1256 Str builtin_types[] = { 1445 Str builtin_types[] = {
1257 cstr("u8"), cstr("s8"), cstr("u16"), cstr("s16"), 1446 cstr("U8"), cstr("S8"), cstr("U16"), cstr("S16"),
1258 cstr("u32"), cstr("s32"), cstr("u64"), cstr("s64"), 1447 cstr("U32"), cstr("S32"), cstr("U64"), cstr("S64"),
1259 cstr("f32"), cstr("f64"), cstr("ptr"), cstr("int"), 1448 cstr("F32"), cstr("F64"), cstr("Ptr"), cstr("Int"),
1260 cstr("uint"), cstr("str"), cstr("bool"), cstr("nil")}; 1449 cstr("UInt"), cstr("Str"), cstr("Bool"), cstr("Nil")};
1261 for (sz i = 0; i < LEN(builtin_types); i++) { 1450 for (sz i = 0; i < LEN(builtin_types); i++) {
1262 Str type = builtin_types[i]; 1451 Str type = builtin_types[i];
1263 symmap_insert(&scope->symbols, type, 1452 strset_insert(&scope->types, type, a->storage);
1264 (Symbol){.name = type, .kind = SYM_BUILTIN_TYPE},
1265 a->storage);
1266 } 1453 }
1267 Str numeric_types[] = { 1454 Str numeric_types[] = {
1268 cstr("u8"), cstr("s8"), cstr("u16"), cstr("s16"), cstr("u32"), 1455 cstr("U8"), cstr("S8"), cstr("U16"), cstr("S16"), cstr("U32"),
1269 cstr("s32"), cstr("u64"), cstr("s64"), cstr("f32"), cstr("f64"), 1456 cstr("S32"), cstr("U64"), cstr("S64"), cstr("F32"), cstr("F64"),
1270 cstr("ptr"), cstr("int"), cstr("uint"), 1457 cstr("Ptr"), cstr("Int"), cstr("UInt"),
1271 }; 1458 };
1272 for (sz i = 0; i < LEN(numeric_types); i++) { 1459 for (sz i = 0; i < LEN(numeric_types); i++) {
1273 Str type = numeric_types[i]; 1460 Str type = numeric_types[i];
1274 strset_insert(&a->numeric_types, type, a->storage); 1461 strset_insert(&a->numeric_types, type, a->storage);
1275 } 1462 }
1276 Str integer_types[] = { 1463 Str integer_types[] = {
1277 cstr("u8"), cstr("s8"), cstr("u16"), cstr("s16"), 1464 cstr("U8"), cstr("S8"), cstr("U16"), cstr("S16"),
1278 cstr("u32"), cstr("s32"), cstr("u64"), cstr("s64"), 1465 cstr("U32"), cstr("S32"), cstr("U64"), cstr("S64"),
1279 cstr("ptr"), cstr("int"), cstr("uint"), 1466 cstr("Ptr"), cstr("Int"), cstr("UInt"),
1280 }; 1467 };
1281 for (sz i = 0; i < LEN(integer_types); i++) { 1468 for (sz i = 0; i < LEN(integer_types); i++) {
1282 Str type = integer_types[i]; 1469 Str type = integer_types[i];
1283 strset_insert(&a->integer_types, type, a->storage); 1470 strset_insert(&a->integer_types, type, a->storage);
1284 } 1471 }
1472 Str float_types[] = {
1473 cstr("F32"),
1474 cstr("F64"),
1475 };
1476 for (sz i = 0; i < LEN(float_types); i++) {
1477 Str type = float_types[i];
1478 strset_insert(&a->float_types, type, a->storage);
1479 }
1285 // Find top level function declarations. 1480 // Find top level function declarations.
1286 for (sz i = 0; i < array_size(parser->nodes); i++) { 1481 for (sz i = 0; i < array_size(parser->nodes); i++) {
1287 Node *root = parser->nodes[i]; 1482 Node *root = parser->nodes[i];
1288 if (root->kind == NODE_FUN) { 1483 if (root->kind == NODE_FUN) {
1289 Str symbol = root->func_name->value.str; 1484 Str symbol = root->func.name->value.str;
1290 if (symmap_lookup(&scope->symbols, symbol)) { 1485 if (symmap_lookup(&scope->symbols, symbol)) {
1291 eprintln( 1486 eprintln(
1292 "%s:%d:%d: error: function '%s' already defined in " 1487 "%s:%d:%d: error: function '%s' already defined in "
1293 "current " 1488 "current "
1294 "scope ", 1489 "scope ",
1295 a->file_name, root->var_name->line, root->var_name->col, 1490 a->file_name, root->var.name->line, root->var.name->col,
1296 symbol); 1491 symbol);
1297 a->err = true; 1492 a->err = true;
1298 } 1493 }
1494 Fun fun = (Fun){.name = symbol};
1495 Str param_type = cstr("");
1496 for (sz i = 0; i < array_size(root->func.params); i++) {
1497 Node *param = root->func.params[i];
1498 Str type = param->param.type->value.str;
1499 if (param->param.type->kind == NODE_ARR_TYPE) {
1500 type = str_concat(cstr("@"), type, a->storage);
1501 }
1502 array_push(fun.param_types, type, a->storage);
1503 param_type = str_concat(param_type, type, a->storage);
1504 if (i != array_size(root->func.params) - 1) {
1505 param_type = str_concat(param_type, cstr(","), a->storage);
1506 }
1507 }
1508 if (!param_type.size) {
1509 param_type = cstr("nil");
1510 }
1511 root->type_params = param_type;
1512
1513 Str ret_type = cstr("");
1514 for (sz i = 0; i < array_size(root->func.ret); i++) {
1515 Node *expr = root->func.ret[i];
1516 Str type = expr->value.str;
1517 if (expr->kind == NODE_ARR_TYPE) {
1518 type = str_concat(cstr("@"), type, a->storage);
1519 }
1520 array_push(fun.return_types, ret_type, a->storage);
1521 ret_type = str_concat(ret_type, type, a->storage);
1522 if (i != array_size(root->func.ret) - 1) {
1523 ret_type = str_concat(ret_type, cstr(","), a->storage);
1524 }
1525 }
1526 if (!ret_type.size) {
1527 ret_type = cstr("nil");
1528 }
1529 fun.param_type = param_type;
1530 fun.return_type = ret_type;
1531 funmap_insert(&scope->funcs, symbol, fun, a->storage);
1299 symmap_insert(&scope->symbols, symbol, 1532 symmap_insert(&scope->symbols, symbol,
1300 (Symbol){.name = symbol, .kind = SYM_FUN}, 1533 (Symbol){.name = symbol, .kind = SYM_FUN},
1301 a->storage); 1534 a->storage);
diff --git a/src/vm.c b/src/vm.c
index 2992a18..ed69498 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -5,8 +5,9 @@
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 u8 stack[STACK_SIZE]; 12 u8 stack[STACK_SIZE];
12 Instruction *ip; 13 Instruction *ip;
@@ -20,6 +21,7 @@ vm_init(VM *vm, Chunk *chunk) {
20 assert(vm); 21 assert(vm);
21 assert(chunk); 22 assert(chunk);
22 assert(chunk->code); 23 assert(chunk->code);
24 vm->main = chunk;
23 vm->chunk = chunk; 25 vm->chunk = chunk;
24 vm->ip = vm->chunk->code; 26 vm->ip = vm->chunk->code;
25 vm->fp = (u64 *)vm->stack; 27 vm->fp = (u64 *)vm->stack;
@@ -75,7 +77,7 @@ vm_run(VM *vm) {
75#endif 77#endif
76 78
77 switch (instruction.op) { 79 switch (instruction.op) {
78 case OP_LD64K: { 80 case OP_LDCONST: {
79 u8 dst = instruction.dst; 81 u8 dst = instruction.dst;
80 u8 src_a = instruction.a; 82 u8 src_a = instruction.a;
81 vm->regs[dst].i = vm->chunk->constants[src_a].i; 83 vm->regs[dst].i = vm->chunk->constants[src_a].i;
@@ -83,6 +85,7 @@ vm_run(VM *vm) {
83 case OP_NOT: OP_UNARY(!, i) break; 85 case OP_NOT: OP_UNARY(!, i) break;
84 case OP_BITNOT: OP_UNARY(~, i) break; 86 case OP_BITNOT: OP_UNARY(~, i) break;
85 case OP_BITOR: OP_BINARY(|, i) break; 87 case OP_BITOR: OP_BINARY(|, i) break;
88 case OP_BITXOR: OP_BINARY(^, i) break;
86 case OP_BITAND: OP_BINARY(&, i) break; 89 case OP_BITAND: OP_BINARY(&, i) break;
87 case OP_BITLSHIFT: OP_BINARY(<<, i) break; 90 case OP_BITLSHIFT: OP_BINARY(<<, i) break;
88 case OP_BITRSHIFT: OP_BINARY(>>, i) break; 91 case OP_BITRSHIFT: OP_BINARY(>>, i) break;
@@ -113,6 +116,7 @@ vm_run(VM *vm) {
113 case OP_NOTI: OP_UNARY_CONST(!, i) break; 116 case OP_NOTI: OP_UNARY_CONST(!, i) break;
114 case OP_BITNOTI: OP_UNARY_CONST(~, i) break; 117 case OP_BITNOTI: OP_UNARY_CONST(~, i) break;
115 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;
116 case OP_BITANDI: OP_BINARY_CONST(&, i) break; 120 case OP_BITANDI: OP_BINARY_CONST(&, i) break;
117 case OP_BITLSHIFTI: OP_BINARY_CONST(<<, i) break; 121 case OP_BITLSHIFTI: OP_BINARY_CONST(<<, i) break;
118 case OP_BITRSHIFTI: OP_BINARY_CONST(>>, i) break; 122 case OP_BITRSHIFTI: OP_BINARY_CONST(>>, i) break;
@@ -140,22 +144,66 @@ vm_run(VM *vm) {
140 vm->regs[dst].f = 144 vm->regs[dst].f =
141 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);
142 } 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;
143 case OP_LDGVAR: { 161 case OP_LDGVAR: {
144 u8 dst = instruction.dst; 162 u8 dst = instruction.dst;
145 u8 src = instruction.a; 163 u8 src = instruction.a;
146 Variable var = vm->chunk->vars[src]; 164 Variable var = vm->main->vars[src];
147 s64 *stack = (s64 *)&vm->stack[var.offset]; 165 s64 *stack = (s64 *)&vm->stack[var.offset];
148 vm->regs[dst].i = *stack; 166 vm->regs[dst].i = *stack;
149 } break; 167 } break;
150 case OP_LDGADDR: { 168 case OP_LDGADDR: {
151 u8 dst = instruction.dst; 169 u8 dst = instruction.dst;
152 u8 src = instruction.a; 170 u8 src = instruction.a;
153 Variable var = vm->chunk->vars[src]; 171 Variable var = vm->main->vars[src];
154 s64 *stack = (s64 *)&vm->stack[var.offset]; 172 s64 *stack = (s64 *)&vm->stack[var.offset];
155 vm->regs[dst].ptr = (ptrsize)stack; 173 vm->regs[dst].ptr = (ptrsize)stack;
156 } break; 174 } break;
175 case OP_STLVAR: {
176 u8 dst = instruction.dst;
177 u8 src = instruction.a;
178 Variable var = vm->chunk->vars[dst];
179 vm->fp[var.offset / 8] = vm->regs[src].i;
180 } break;
181 case OP_STLVARI: {
182 u8 dst = instruction.dst;
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;
157 case OP_ST64I: { 205 case OP_ST64I: {
158 sz value = vm->regs[instruction.dst].i; 206 sz value = vm->regs[instruction.dst].ptr;
159 s64 *addr = (s64 *)vm->regs[instruction.a].ptr; 207 s64 *addr = (s64 *)vm->regs[instruction.a].ptr;
160 sz offset = vm->chunk->constants[instruction.b].i; 208 sz offset = vm->chunk->constants[instruction.b].i;
161 addr[offset] = value; 209 addr[offset] = value;
@@ -166,6 +214,42 @@ vm_run(VM *vm) {
166 sz offset = vm->regs[instruction.b].i; 214 sz offset = vm->regs[instruction.b].i;
167 addr[offset] = value; 215 addr[offset] = value;
168 } break; 216 } break;
217 case OP_ST16I: {
218 sz value = vm->regs[instruction.dst].ptr;
219 s16 *addr = (s16 *)vm->regs[instruction.a].ptr;
220 sz offset = vm->chunk->constants[instruction.b].i;
221 addr[offset] = value;
222 } break;
223 case OP_ST16: {
224 sz value = vm->regs[instruction.dst].i;
225 s16 *addr = (s16 *)vm->regs[instruction.a].ptr;
226 sz offset = vm->regs[instruction.b].i;
227 addr[offset] = value;
228 } break;
229 case OP_ST8I: {
230 sz value = vm->regs[instruction.dst].ptr;
231 s8 *addr = (s8 *)vm->regs[instruction.a].ptr;
232 sz offset = vm->chunk->constants[instruction.b].i;
233 addr[offset] = value;
234 } break;
235 case OP_ST8: {
236 sz value = vm->regs[instruction.dst].i;
237 s8 *addr = (s8 *)vm->regs[instruction.a].ptr;
238 sz offset = vm->regs[instruction.b].i;
239 addr[offset] = value;
240 } break;
241 case OP_ST32I: {
242 sz value = vm->regs[instruction.dst].ptr;
243 s32 *addr = (s32 *)vm->regs[instruction.a].ptr;
244 sz offset = vm->chunk->constants[instruction.b].i;
245 addr[offset] = value;
246 } break;
247 case OP_ST32: {
248 sz value = vm->regs[instruction.dst].i;
249 s32 *addr = (s32 *)vm->regs[instruction.a].ptr;
250 sz offset = vm->regs[instruction.b].i;
251 addr[offset] = value;
252 } break;
169 case OP_LD64I: { 253 case OP_LD64I: {
170 s64 *addr = (s64 *)vm->regs[instruction.a].ptr; 254 s64 *addr = (s64 *)vm->regs[instruction.a].ptr;
171 sz offset = vm->chunk->constants[instruction.b].i; 255 sz offset = vm->chunk->constants[instruction.b].i;
@@ -176,19 +260,67 @@ vm_run(VM *vm) {
176 sz offset = vm->regs[instruction.b].i; 260 sz offset = vm->regs[instruction.b].i;
177 vm->regs[instruction.dst].i = addr[offset]; 261 vm->regs[instruction.dst].i = addr[offset];
178 } break; 262 } break;
179 case OP_STGVAR: { 263 case OP_LD32I: {
180 u8 dst = instruction.dst; 264 s32 *addr = (s32 *)vm->regs[instruction.a].ptr;
181 u8 src = instruction.a; 265 sz offset = vm->chunk->constants[instruction.b].i;
182 Variable var = vm->chunk->vars[dst]; 266 vm->regs[instruction.dst].i = addr[offset];
183 s64 *stack = (s64 *)&vm->stack[var.offset];
184 *stack = vm->regs[src].i;
185 } break; 267 } break;
186 case OP_STGVARI: { 268 case OP_LD32: {
187 u8 dst = instruction.dst; 269 s32 *addr = (s32 *)vm->regs[instruction.a].ptr;
188 u8 src = instruction.a; 270 sz offset = vm->regs[instruction.b].i;
189 Variable var = vm->chunk->vars[dst]; 271 vm->regs[instruction.dst].i = addr[offset];
190 s64 *stack = (s64 *)&vm->stack[var.offset]; 272 } break;
191 *stack = vm->chunk->constants[src].i; 273 case OP_LD16I: {
274 s16 *addr = (s16 *)vm->regs[instruction.a].ptr;
275 sz offset = vm->chunk->constants[instruction.b].i;
276 vm->regs[instruction.dst].i = addr[offset];
277 } break;
278 case OP_LD16: {
279 s16 *addr = (s16 *)vm->regs[instruction.a].ptr;
280 sz offset = vm->regs[instruction.b].i;
281 vm->regs[instruction.dst].i = addr[offset];
282 } break;
283 case OP_LD8I: {
284 s8 *addr = (s8 *)vm->regs[instruction.a].ptr;
285 sz offset = vm->chunk->constants[instruction.b].i;
286 vm->regs[instruction.dst].i = addr[offset];
287 } break;
288 case OP_LD8: {
289 s8 *addr = (s8 *)vm->regs[instruction.a].ptr;
290 sz offset = vm->regs[instruction.b].i;
291 vm->regs[instruction.dst].i = addr[offset];
292 } break;
293 case OP_LD8K: {
294 s8 *addr = (s8 *)vm->regs[instruction.a].ptr;
295 vm->regs[instruction.dst].i = *addr;
296 } break;
297 case OP_LD16K: {
298 s16 *addr = (s16 *)vm->regs[instruction.a].ptr;
299 vm->regs[instruction.dst].i = *addr;
300 } break;
301 case OP_LD32K: {
302 s32 *addr = (s32 *)vm->regs[instruction.a].ptr;
303 vm->regs[instruction.dst].i = *addr;
304 } break;
305 case OP_LD64K: {
306 s64 *addr = (s64 *)vm->regs[instruction.a].ptr;
307 vm->regs[instruction.dst].i = *addr;
308 } break;
309 case OP_ST8K: {
310 s8 *addr = (s8 *)vm->regs[instruction.a].ptr;
311 *addr = vm->regs[instruction.dst].i;
312 } break;
313 case OP_ST16K: {
314 s16 *addr = (s16 *)vm->regs[instruction.a].ptr;
315 *addr = vm->regs[instruction.dst].i;
316 } break;
317 case OP_ST32K: {
318 s32 *addr = (s32 *)vm->regs[instruction.a].ptr;
319 *addr = vm->regs[instruction.dst].i;
320 } break;
321 case OP_ST64K: {
322 s64 *addr = (s64 *)vm->regs[instruction.a].ptr;
323 *addr = vm->regs[instruction.dst].i;
192 } break; 324 } break;
193 case OP_JMP: { 325 case OP_JMP: {
194 u8 dst = instruction.dst; 326 u8 dst = instruction.dst;
@@ -247,14 +379,88 @@ vm_run(VM *vm) {
247 u8 src = instruction.a; 379 u8 src = instruction.a;
248 vm->regs[dst].i = vm->regs[src].i & 0xFF; 380 vm->regs[dst].i = vm->regs[src].i & 0xFF;
249 } break; 381 } break;
382 case OP_PRINTS8: {
383 u8 idx = instruction.dst;
384 print("%d", vm->regs[idx].i & 0xFF);
385 } break;
386 case OP_PRINTS16: {
387 u8 idx = instruction.dst;
388 print("%d", vm->regs[idx].i & 0xFFFF);
389 } break;
390 case OP_PRINTS32: {
391 u8 idx = instruction.dst;
392 print("%d", vm->regs[idx].i & 0xFFFFFFFF);
393 } break;
250 case OP_PRINTS64: { 394 case OP_PRINTS64: {
251 u8 idx = instruction.dst; 395 u8 idx = instruction.dst;
252 print("%d", vm->regs[idx].i); 396 print("%d", vm->regs[idx].i);
253 } break; 397 } break;
398 case OP_PRINTU8: {
399 u8 idx = instruction.dst;
400 print("%x", vm->regs[idx].u & 0xFF);
401 } break;
402 case OP_PRINTU16: {
403 u8 idx = instruction.dst;
404 print("%x", vm->regs[idx].u & 0xFFFF);
405 } break;
406 case OP_PRINTU32: {
407 u8 idx = instruction.dst;
408 print("%x", vm->regs[idx].u & 0xFFFFFFFF);
409 } break;
410 case OP_PRINTU64: {
411 u8 idx = instruction.dst;
412 print("%x", vm->regs[idx].u);
413 } break;
414 case OP_PRINTS8I: {
415 u8 idx = instruction.dst;
416 print("%d", vm->chunk->constants[idx].i & 0xFF);
417 } break;
418 case OP_PRINTS16I: {
419 u8 idx = instruction.dst;
420 print("%d", vm->chunk->constants[idx].i & 0xFFFF);
421 } break;
422 case OP_PRINTS32I: {
423 u8 idx = instruction.dst;
424 print("%d", vm->chunk->constants[idx].i & 0xFFFFFFFF);
425 } break;
254 case OP_PRINTS64I: { 426 case OP_PRINTS64I: {
255 u8 idx = instruction.dst; 427 u8 idx = instruction.dst;
256 print("%d", vm->chunk->constants[idx].i); 428 print("%d", vm->chunk->constants[idx].i);
257 } break; 429 } break;
430 case OP_PRINTU8I: {
431 u8 idx = instruction.dst;
432 print("%x", vm->chunk->constants[idx].u & 0xFF);
433 } break;
434 case OP_PRINTU16I: {
435 u8 idx = instruction.dst;
436 print("%x", vm->chunk->constants[idx].u & 0xFFFF);
437 } break;
438 case OP_PRINTU32I: {
439 u8 idx = instruction.dst;
440 print("%x", vm->chunk->constants[idx].u & 0xFFFFFFFF);
441 } break;
442 case OP_PRINTU64I: {
443 u8 idx = instruction.dst;
444 print("%x", vm->chunk->constants[idx].u);
445 } break;
446 case OP_PRINTBOOL: {
447 u8 idx = instruction.dst;
448 bool val = vm->regs[idx].i;
449 if (val) {
450 print("true");
451 } else {
452 print("false");
453 }
454 } break;
455 case OP_PRINTBOOLI: {
456 u8 idx = instruction.dst;
457 bool val = vm->chunk->constants[idx].i;
458 if (val) {
459 print("true");
460 } else {
461 print("false");
462 }
463 } break;
258 case OP_PRINTF64: { 464 case OP_PRINTF64: {
259 u8 idx = instruction.dst; 465 u8 idx = instruction.dst;
260 printf("%f", vm->regs[idx].f); 466 printf("%f", vm->regs[idx].f);
@@ -265,6 +471,11 @@ vm_run(VM *vm) {
265 } break; 471 } break;
266 case OP_PRINTSTR: { 472 case OP_PRINTSTR: {
267 u8 idx = instruction.dst; 473 u8 idx = instruction.dst;
474 Str *string = (Str *)vm->regs[idx].ptr;
475 print("%s", *string);
476 } break;
477 case OP_PRINTSTRI: {
478 u8 idx = instruction.dst;
268 Str string = vm->chunk->strings[idx]; 479 Str string = vm->chunk->strings[idx];
269 print("%s", string); 480 print("%s", string);
270 } break; 481 } break;
@@ -299,7 +510,7 @@ vm_run(VM *vm) {
299 } break; 510 } break;
300 case OP_CALL: { 511 case OP_CALL: {
301 u8 dst = instruction.dst; 512 u8 dst = instruction.dst;
302 Chunk *func = vm->chunk->functions[dst]; 513 Chunk *func = vm->main->functions[dst];
303 514
304 ptrsize chunk_addr = (ptrsize)vm->chunk; 515 ptrsize chunk_addr = (ptrsize)vm->chunk;
305 ptrsize ip_addr = (ptrsize)vm->ip; 516 ptrsize ip_addr = (ptrsize)vm->ip;
@@ -307,8 +518,9 @@ vm_run(VM *vm) {
307 ptrsize old_fp = (ptrsize)vm->fp; 518 ptrsize old_fp = (ptrsize)vm->fp;
308 519
309 // Allocate space for the locals. 520 // Allocate space for the locals.
310 vm->fp = (u64 *)vm->sp; 521 memset(vm->sp, 0, func->var_off - func->param_off);
311 vm->sp += func->var_off; // FIXME: - func->n_params! 522 vm->fp = (u64 *)(vm->sp - func->param_off);
523 vm->sp += func->var_off - func->param_off;
312 vm->chunk = func; 524 vm->chunk = func;
313 vm->ip = func->code; 525 vm->ip = func->code;
314 vm->regs = (Constant *)vm->sp; 526 vm->regs = (Constant *)vm->sp;
@@ -324,6 +536,9 @@ vm_run(VM *vm) {
324 p[3] = old_fp; 536 p[3] = old_fp;
325 vm->sp += sizeof(ptrsize) * 4; 537 vm->sp += sizeof(ptrsize) * 4;
326 } break; 538 } break;
539 case OP_RECUR: {
540 vm->ip = vm->chunk->code;
541 } break;
327 case OP_RET: { 542 case OP_RET: {
328 u64 *p = (u64 *)vm->sp; 543 u64 *p = (u64 *)vm->sp;
329 ptrsize chunk_addr = p[-4]; 544 ptrsize chunk_addr = p[-4];
diff --git a/tests/compilation.bad b/tests/compilation.bad
index ea467d2..49a5492 100644
--- a/tests/compilation.bad
+++ b/tests/compilation.bad
@@ -1,93 +1,100 @@
1fun adder(a: int): int { 1let a: Int = 32
2 ; a + 1 2let ptr = @a
3 4 3println("a " a)
4} 4println("ptr " ptr)
5adder(2) 5
6; let a = 1 6set ptr@ = 12
7; let b = 8 7println("a " a)
8 8println("ptr " ptr)
9; a + b 9
10; 1 + 2 10let ptr2 = @ptr
11; fun greet(name: str): nil { 11set ptr2@@ = 6
12; fun greet(name: str): nil { 12println("a " a)
13; println("hello ") 13println("ptr " ptr)
14; } 14
15 15; let a: Int = 32
16; greet("alex") 16; let b: Int = 64
17; greet("ding") 17; let ptr = @a
18; greet() 18; println("a " a)
19; if true { 19; println("b " b)
20; 1 20; println("ptr " ptr)
21; nil 21
22; } 22; println("ptr@ " ptr@)
23; let a = 1 23
24; let p = @a 24; { ; FIXME: This doesn't work yet
25; let arr: int[8] 25; set ptr@ = 12
26; set p[0] = 2 26; println(a)
27 27; println(b)
28; let b = p[0] 28; println(ptr)
29; println("a: " a)
30; println("b: " b)
31; let i = 0
32; while i < 8 {
33; set arr[i] = i
34; set i = i + 1
35; }
36; println("arr[0]: " arr[0])
37; println("arr[1]: " arr[1])
38
39; let arr: int[8]
40; set arr[1] = 2
41
42; let idx = 3
43; set arr[idx] = 3
44
45; println("arr[0]: " arr[0])
46; println("arr[1]: " arr[1])
47; println("arr[2]: " arr[2])
48; println("arr[3]: " arr[3])
49
50; arr[0] + arr[1] + arr[2] + arr[3]
51
52; set a = 2
53
54; let a = cond {
55; 1 == 1 = 42
56; 1 == 3 = 55
57; 1 == 1 = 66
58; else = 10
59; } 29; }
60 30
31; set ptr += 8
32; println(ptr@)
33
34; let a: Int = 32
35; let b: @Int = @a
36; let c = @a
37; let d = @c
38; let e = a + b@
39; let f = d@
40
41; println("a -> " a)
42; println("b -> " b)
43; println("c -> " c)
44; println("d -> " d)
45; println("e -> " e)
46; println("f -> " f)
47; println("b@ -> " b@)
48; println("d@ -> " d@)
49; println("d@@ -> " d@@)
50; println("a == b@ and a == d@@ -> " a == b@ and a == d@@)
51; println("b == c and c == d@ -> " b == c and c == d@)
52
53; println("b[0] " b[0])
54; println("c[0] " c[0])
55; println("d[0] " d[0])
56
57; let c = @a
58; let d = @c
59; let c: Int = a@ + 1
60; let c: @@Int = @b
61; let d: @@@Int = @c
62; let static_array: [24]Int
63; let fun_ptr: (Int Int : Int)
64
65; let a: U16 = 0x0afafafafafafafafafa
66; println(a)
67; let a: U32 = -2
68; ; let a: U32 = -2 + -1
69; let b: @U32 = @a
70; ; let a = "hello"
71; ; let b = a
72; set a = 1
73; let a = "hello"
74; let b = "world"
75
76; println(a)
77; println(b)
78
79; set b = a
80; set a = "WOOWOWO"
81
82; println(a)
83; println(b)
84
85; let a: S32[4]
86; set a[0] = 1
87; set a[1] = 2
88; set a[2] = 4
89; set a[3] = 8
90; let b = a
91; println(a[0] "--" a[1] "--" a[2] "--" a[3])
92; println(b[0] "--" b[1] "--" b[2] "--" b[3])
93
94; let a = 1 + 2
61; a 95; a
62 96; let sum_int_uint: U16 = -2 + 0x5
63; let a = 8 97; ; let sum_int_uint = -2
64; let b = 16 98; println(sum_int_uint)
65; let c = { 99; let varint: U16 = 0x0102030405060708
66; let a = 32 100; let varfloat: F32 = 1.0
67; a + 8
68; }
69
70; a + b + c
71
72; let a = 1
73; if false {
74; set a = 2
75; }
76; a
77
78; if true {
79; 1 + 2
80; } else {
81; 3 + 4
82; }
83
84; let a = 0
85; while a < 10 {
86; set a = a + 1
87; }
88
89; a
90
91; print(1)
92; println(1.0 + 2.0)
93; println("hello world " 1 " " 2.0 " wow!")
diff --git a/tests/logic-shortcircuit.bad b/tests/logic-shortcircuit.bad
new file mode 100644
index 0000000..a7e315e
--- /dev/null
+++ b/tests/logic-shortcircuit.bad
@@ -0,0 +1,16 @@
1fun ret_true(): Bool {
2 print("ret_true ")
3 true
4}
5
6fun ret_false(): Bool {
7 print("ret_false ")
8 false
9}
10
11println("test1: " ret_true() and ret_false() and ret_true())
12println("test2: " ret_true() and ret_true() and ret_true())
13println("test3: " ret_false() and ret_true() and ret_true())
14println("test4: " ret_false() or ret_true() or ret_false())
15println("test5: " ret_true() or ret_true() or ret_false())
16println("test6: " ret_true() and (ret_true() or ret_false()))
diff --git a/tests/nested.bad b/tests/nested.bad
new file mode 100644
index 0000000..75eb967
--- /dev/null
+++ b/tests/nested.bad
@@ -0,0 +1,18 @@
1fun printer() println("wowo!")
2
3let y = 4
4fun nested() {
5 fun adder(a: Int b: Int): Int {
6 fun printer() println("ho!")
7 printer()
8 printer()
9 printer()
10 y + a + b
11 }
12 for let i = 0, i < 2, set i += 1 {
13 println("i: " i " " adder(i, 2))
14 }
15}
16
17nested()
18printer()
diff --git a/tests/pointers.bad b/tests/pointers.bad
new file mode 100644
index 0000000..eda44b0
--- /dev/null
+++ b/tests/pointers.bad
@@ -0,0 +1,36 @@
1{
2 let a: Int = 32
3 let b: @Int = @a
4 let c = @a
5 let d = @c
6 let e = a + b@
7 let f = d@
8
9 println("a -> " a)
10 println("b -> " b)
11 println("c -> " c)
12 println("d -> " d)
13 println("e -> " e)
14 println("f -> " f)
15 println("b@ -> " b@)
16 println("d@ -> " d@)
17 println("d@@ -> " d@@)
18 println("a == b@ and a == d@@ -> " a == b@ and a == d@@)
19 println("b == c and c == d@ -> " b == c and c == d@)
20}
21
22{
23 let a: Int = 32
24 let ptr = @a
25 println("a " a)
26 println("ptr " ptr)
27
28 set ptr@ = 12
29 println("a " a)
30 println("ptr " ptr)
31
32 let ptr2 = @ptr
33 set ptr2@@ = 6
34 println("a " a)
35 println("ptr " ptr)
36}
diff --git a/tests/recursion.bad b/tests/recursion.bad
new file mode 100644
index 0000000..0ab7fa0
--- /dev/null
+++ b/tests/recursion.bad
@@ -0,0 +1,19 @@
1fun recur(num: UInt) {
2 println("NUM: " num)
3 if num == 0 return(nil)
4 recur2(num - 1)
5}
6
7fun recur2(num: Int) {
8 println("NUM: " num)
9 if num == 0 return(nil)
10 recur(num - 1)
11}
12
13recur(5)
14
15fun infrecur(msg: Str, num: Int) {
16 println("NUM: " msg " " num)
17 infrecur(msg num + 1)
18}
19infrecur(" -> " 8)