diff options
Diffstat (limited to 'src/semantic.c')
-rw-r--r-- | src/semantic.c | 1592 |
1 files changed, 1141 insertions, 451 deletions
diff --git a/src/semantic.c b/src/semantic.c index fe88249..428cc53 100644 --- a/src/semantic.c +++ b/src/semantic.c | |||
@@ -1,544 +1,1234 @@ | |||
1 | #include "hashtable.h" | 1 | #include "badlib.h" |
2 | 2 | ||
3 | typedef struct Scope { | 3 | typedef enum { |
4 | size_t id; | 4 | SYM_UNKNOWN, |
5 | struct Scope *parent; | 5 | SYM_BUILTIN_FUN, |
6 | HashTable *symbols; | 6 | SYM_BUILTIN_TYPE, |
7 | HashTable *types; | 7 | SYM_FUN, |
8 | } Scope; | 8 | SYM_VAR, |
9 | SYM_PARAM, | ||
10 | SYM_ENUM, | ||
11 | SYM_ENUM_FIELD, | ||
12 | SYM_STRUCT, | ||
13 | SYM_STRUCT_FIELD, | ||
14 | } SymbolKind; | ||
9 | 15 | ||
10 | typedef struct ParseTree { | 16 | Str sym_kind_str[] = { |
11 | Root *roots; | 17 | [SYM_UNKNOWN] = cstr("UNKNOWN "), |
12 | Scope **scopes; | 18 | [SYM_BUILTIN_FUN] = cstr("BUILTIN FUN "), |
13 | } ParseTree; | 19 | [SYM_BUILTIN_TYPE] = cstr("BUILTIN TYPE "), |
14 | 20 | [SYM_FUN] = cstr("FUNCTION "), | |
15 | typedef struct Type { | 21 | [SYM_VAR] = cstr("VARIABLE "), |
16 | StringView name; | 22 | [SYM_PARAM] = cstr("PARAMETER "), |
17 | size_t size; // (bytes) | 23 | [SYM_ENUM] = cstr("ENUM "), |
18 | } Type; | 24 | [SYM_ENUM_FIELD] = cstr("ENUM FIELD "), |
19 | 25 | [SYM_STRUCT] = cstr("STRUCT "), | |
20 | typedef enum DefaultType { | 26 | [SYM_STRUCT_FIELD] = cstr("STRUCT FIELD "), |
21 | TYPE_VOID, | ||
22 | TYPE_BOOL, | ||
23 | TYPE_STR, | ||
24 | TYPE_U8, | ||
25 | TYPE_U16, | ||
26 | TYPE_U32, | ||
27 | TYPE_U64, | ||
28 | TYPE_S8, | ||
29 | TYPE_S16, | ||
30 | TYPE_S32, | ||
31 | TYPE_S64, | ||
32 | TYPE_F32, | ||
33 | TYPE_F64, | ||
34 | } DefaultType; | ||
35 | |||
36 | static Type default_types[] = { | ||
37 | [TYPE_VOID] = {STRING("void"), 0}, | ||
38 | [TYPE_BOOL] = {STRING("bool"), 1}, | ||
39 | [TYPE_STR] = {STRING("str"), 16}, // size (8) + pointer to data (8). | ||
40 | [TYPE_U8] = {STRING("u8"), 1}, | ||
41 | [TYPE_U16] = {STRING("u16"), 2}, | ||
42 | [TYPE_U32] = {STRING("u32"), 4}, | ||
43 | [TYPE_U64] = {STRING("u64"), 8}, | ||
44 | [TYPE_S8] = {STRING("s8"), 1}, | ||
45 | [TYPE_S16] = {STRING("s16"), 2}, | ||
46 | [TYPE_S32] = {STRING("s32"), 4}, | ||
47 | [TYPE_S64] = {STRING("s64"), 8}, | ||
48 | [TYPE_F32] = {STRING("f32"), 4}, | ||
49 | [TYPE_F64] = {STRING("f64"), 8}, | ||
50 | }; | 27 | }; |
51 | 28 | ||
52 | typedef enum SymbolType { | ||
53 | SYMBOL_VAR, | ||
54 | SYMBOL_PAR, | ||
55 | SYMBOL_FUN, | ||
56 | } SymbolType; | ||
57 | |||
58 | typedef struct Symbol { | 29 | typedef struct Symbol { |
59 | Node *name; | 30 | Str name; |
60 | SymbolType type; | 31 | SymbolKind kind; |
61 | |||
62 | union { | ||
63 | struct { | ||
64 | Node *type; | ||
65 | } var; | ||
66 | |||
67 | struct { | ||
68 | Node **param_types; | ||
69 | Node *return_type; | ||
70 | } fun; | ||
71 | }; | ||
72 | } Symbol; | 32 | } Symbol; |
73 | 33 | ||
74 | static size_t scope_gen_id = 0; | 34 | typedef struct Fun { |
35 | Str name; | ||
36 | Str param_type; | ||
37 | Str return_type; | ||
38 | } Fun; | ||
75 | 39 | ||
76 | Symbol * | 40 | typedef struct Enum { |
77 | alloc_symval(Node *name, SymbolType type) { | 41 | Str name; |
78 | Symbol *val = malloc(sizeof(Symbol)); | 42 | Node *val; |
79 | val->name = name; | 43 | } Enum; |
80 | val->type = type; | ||
81 | return val; | ||
82 | } | ||
83 | 44 | ||
84 | u64 sym_hash(const struct HashTable *table, void *bytes) { | 45 | typedef struct Struct { |
85 | Node *symbol = bytes; | 46 | Str name; |
86 | u64 hash = _xor_shift_hash(symbol->string.start, symbol->string.n); | 47 | Str type; |
87 | hash = _fibonacci_hash(hash, table->shift_amount); | 48 | Node *val; |
88 | return hash; | 49 | } Struct; |
89 | } | ||
90 | 50 | ||
91 | bool sym_eq(void *a, void *b) { | 51 | MAPDEF(SymbolMap, symmap, Str, Symbol, str_hash, str_eq) |
92 | Node *a_node = a; | 52 | MAPDEF(FunMap, funmap, Str, Fun, str_hash, str_eq) |
93 | Node *b_node = b; | 53 | MAPDEF(EnumMap, enummap, Str, Enum, str_hash, str_eq) |
94 | assert(a_node->type == NODE_SYMBOL); | 54 | MAPDEF(StructMap, structmap, Str, Struct, str_hash, str_eq) |
95 | assert(b_node->type == NODE_SYMBOL); | ||
96 | return sv_equal(&a_node->string, &b_node->string); | ||
97 | } | ||
98 | 55 | ||
99 | u64 type_hash(const struct HashTable *table, void *bytes) { | 56 | typedef struct Scope { |
100 | StringView *type = bytes; | 57 | sz id; |
101 | u64 hash = _xor_shift_hash(type->start, type->n); | 58 | sz depth; |
102 | hash = _fibonacci_hash(hash, table->shift_amount); | 59 | Str name; |
103 | return hash; | 60 | SymbolMap *symbols; |
104 | } | 61 | FunMap *funcs; |
62 | EnumMap *enums; | ||
63 | StructMap *structs; | ||
64 | struct Scope *parent; | ||
65 | } Scope; | ||
105 | 66 | ||
106 | bool type_eq(void *a, void *b) { | 67 | typedef struct Analyzer { |
107 | StringView *a_type = a; | 68 | Arena *storage; |
108 | StringView *b_type = b; | 69 | Str file_name; |
109 | return sv_equal(a_type, b_type); | 70 | sz typescope_gen; |
110 | } | 71 | Scope **scopes; |
72 | StrSet *numeric_types; | ||
73 | StrSet *integer_types; | ||
74 | bool err; | ||
75 | } Analyzer; | ||
111 | 76 | ||
112 | Scope * | 77 | Scope * |
113 | alloc_scope(Scope *parent) { | 78 | typescope_alloc(Analyzer *a, Scope *parent) { |
114 | Scope *scope = malloc(sizeof(Scope)); | 79 | Scope *scope = arena_calloc(sizeof(Scope), a->storage); |
115 | scope->id = scope_gen_id++; | ||
116 | scope->parent = parent; | 80 | scope->parent = parent; |
117 | scope->symbols = ht_init(sym_hash, sym_eq); | 81 | scope->id = a->typescope_gen++; |
118 | scope->types = ht_init(type_hash, type_eq); | 82 | scope->depth = parent == NULL ? 0 : parent->depth + 1; |
83 | array_push(a->scopes, scope, a->storage); | ||
119 | return scope; | 84 | return scope; |
120 | } | 85 | } |
121 | 86 | ||
122 | Type * | 87 | SymbolMap * |
123 | find_type(Scope *scope, Node *type) { | 88 | find_type(Scope *scope, Str type) { |
124 | // TODO: Normally default types will be used more often. Since we don't | ||
125 | // allow type shadowing, we should search first on the global scope. | ||
126 | while (scope != NULL) { | 89 | while (scope != NULL) { |
127 | Type *ret = ht_lookup(scope->types, &type->string); | 90 | SymbolMap *val = symmap_lookup(&scope->symbols, type); |
128 | if (ret != NULL) { | 91 | if (val != NULL) { |
129 | return ret; | 92 | return val; |
130 | } | 93 | } |
131 | scope = scope->parent; | 94 | scope = scope->parent; |
132 | } | 95 | } |
133 | push_error(ERR_TYPE_SEMANTIC, ERR_UNKNOWN_TYPE, type->line, type->col); | ||
134 | return NULL; | 96 | return NULL; |
135 | } | 97 | } |
136 | 98 | ||
137 | bool | 99 | FunMap * |
138 | insert_symbol(Scope *scope, Node *symbol, Symbol *val) { | 100 | find_fun(Scope *scope, Str type) { |
139 | // Check if symbol already exists. | 101 | while (scope != NULL) { |
140 | HashTable *symbols = scope->symbols; | 102 | FunMap *val = funmap_lookup(&scope->funcs, type); |
141 | if (ht_lookup(symbols, symbol) != NULL) { | 103 | if (val != NULL) { |
142 | push_error(ERR_TYPE_SEMANTIC, ERR_SYMBOL_REDEF, symbol->line, symbol->col); | 104 | return val; |
143 | return false; | 105 | } |
106 | scope = scope->parent; | ||
144 | } | 107 | } |
145 | ht_insert(symbols, symbol, val); | 108 | return NULL; |
146 | return true; | ||
147 | } | 109 | } |
148 | 110 | ||
149 | Type * | 111 | typedef struct FindEnumResult { |
150 | coerce_numeric_types(Type *a, Type *b) { | 112 | EnumMap *map; |
151 | // TODO: Decide what to do with mixed numeric types. What are the promotion | 113 | Scope *scope; |
152 | // rules, etc. | 114 | } FindEnumResult; |
153 | if (a == &default_types[TYPE_U8]) { | 115 | |
154 | if (b == &default_types[TYPE_U16] || | 116 | FindEnumResult |
155 | b == &default_types[TYPE_U32] || | 117 | find_enum(Scope *scope, Str type) { |
156 | b == &default_types[TYPE_U64]) { | 118 | while (scope != NULL) { |
157 | return b; | 119 | EnumMap *val = enummap_lookup(&scope->enums, type); |
158 | } | 120 | if (val != NULL) { |
159 | } else if (a == &default_types[TYPE_U16]) { | 121 | return (FindEnumResult){.map = val, .scope = scope}; |
160 | if (b == &default_types[TYPE_U32] || | ||
161 | b == &default_types[TYPE_U64]) { | ||
162 | return b; | ||
163 | } | ||
164 | } else if (a == &default_types[TYPE_U32]) { | ||
165 | if (b == &default_types[TYPE_U64]) { | ||
166 | return b; | ||
167 | } | 122 | } |
168 | } else if (a == &default_types[TYPE_S8]) { | 123 | scope = scope->parent; |
169 | if (b == &default_types[TYPE_S16] || | 124 | } |
170 | b == &default_types[TYPE_S32] || | 125 | return (FindEnumResult){0}; |
171 | b == &default_types[TYPE_S64]) { | 126 | } |
172 | return b; | 127 | |
128 | typedef struct FindStructResult { | ||
129 | StructMap *map; | ||
130 | Scope *scope; | ||
131 | } FindStructResult; | ||
132 | |||
133 | FindStructResult | ||
134 | find_struct(Scope *scope, Str type) { | ||
135 | while (scope != NULL) { | ||
136 | StructMap *val = structmap_lookup(&scope->structs, type); | ||
137 | if (val != NULL) { | ||
138 | return (FindStructResult){.map = val, .scope = scope}; | ||
173 | } | 139 | } |
174 | } else if (a == &default_types[TYPE_S16]) { | 140 | scope = scope->parent; |
175 | if (b == &default_types[TYPE_S32] || | 141 | } |
176 | b == &default_types[TYPE_S64]) { | 142 | return (FindStructResult){0}; |
177 | return b; | 143 | } |
144 | |||
145 | void | ||
146 | graph_typescope(Scope *scope, Arena a) { | ||
147 | if (!scope->symbols) { | ||
148 | return; | ||
149 | } | ||
150 | SymbolMapIter iter = symmap_iterator(scope->symbols, &a); | ||
151 | SymbolMap *type = symmap_next(&iter, &a); | ||
152 | print( | ||
153 | "%d[shape=\"none\" label=<<TABLE ALIGN=\"left\" STYLE=\"rounded\" " | ||
154 | "BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"6\" " | ||
155 | "COLUMNS=\"*\">", | ||
156 | scope->id); | ||
157 | print( | ||
158 | "<TR >" | ||
159 | "<TD ALIGN=\"left\" > NAME </TD>" | ||
160 | "<TD ALIGN=\"left\" > TYPE </TD>" | ||
161 | "</TR>"); | ||
162 | while (type) { | ||
163 | print( | ||
164 | "<TR>" | ||
165 | "<TD ALIGN=\"left\"> %s </TD>" | ||
166 | "<TD ALIGN=\"left\"> %s</TD>" | ||
167 | "</TR>", | ||
168 | type->key, type->val.name); | ||
169 | type = symmap_next(&iter, &a); | ||
170 | } | ||
171 | println("</TABLE>>];"); | ||
172 | |||
173 | sz this_id = scope->id; | ||
174 | while (scope->parent) { | ||
175 | if (scope->parent->symbols) { | ||
176 | println("%d:e->%d:w;", this_id, scope->parent->id); | ||
177 | break; | ||
178 | } else { | ||
179 | scope = scope->parent; | ||
178 | } | 180 | } |
179 | } else if (a == &default_types[TYPE_S32]) { | 181 | } |
180 | if (b == &default_types[TYPE_S64]) { | 182 | } |
181 | return b; | 183 | |
184 | void | ||
185 | graph_functions(Scope *scope, Arena a) { | ||
186 | if (!scope->funcs) { | ||
187 | return; | ||
188 | } | ||
189 | FunMapIter iter = funmap_iterator(scope->funcs, &a); | ||
190 | FunMap *func = funmap_next(&iter, &a); | ||
191 | print( | ||
192 | "fun_%d[shape=\"none\" label=<<TABLE ALIGN=\"left\" STYLE=\"rounded\" " | ||
193 | "BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"6\" " | ||
194 | "COLUMNS=\"*\">", | ||
195 | scope->id); | ||
196 | print( | ||
197 | "<TR >" | ||
198 | "<TD ALIGN=\"left\" > NAME </TD>" | ||
199 | "<TD ALIGN=\"left\" > PARAMS </TD>" | ||
200 | "<TD ALIGN=\"left\" > RETURN </TD>" | ||
201 | "</TR>"); | ||
202 | while (func) { | ||
203 | print( | ||
204 | "<TR>" | ||
205 | "<TD PORT=\"%s\" ALIGN=\"left\" > %s </TD>" | ||
206 | "<TD ALIGN=\"left\" > %s </TD>" | ||
207 | "<TD ALIGN=\"left\" > %s </TD>" | ||
208 | "</TR>", | ||
209 | func->val.name, func->val.name, func->val.param_type, | ||
210 | func->val.return_type); | ||
211 | func = funmap_next(&iter, &a); | ||
212 | } | ||
213 | println("</TABLE>>];"); | ||
214 | sz this_id = scope->id; | ||
215 | while (scope->parent) { | ||
216 | if (scope->parent->symbols) { | ||
217 | println("fun_%d:e->fun_%d:%s:w;", this_id, scope->parent->id, | ||
218 | scope->name); | ||
219 | break; | ||
220 | } else { | ||
221 | scope = scope->parent; | ||
182 | } | 222 | } |
183 | } else if (a == &default_types[TYPE_F32]) { | 223 | } |
184 | if (b == &default_types[TYPE_F64]) { | 224 | } |
185 | return b; | 225 | |
226 | void | ||
227 | graph_types(Scope **scopes, Arena a) { | ||
228 | if (scopes == NULL) return; | ||
229 | println("digraph types {"); | ||
230 | println("rankdir=LR;"); | ||
231 | println("ranksep=\"0.95 equally\";"); | ||
232 | println("nodesep=\"0.5 equally\";"); | ||
233 | println("overlap=scale;"); | ||
234 | println("bgcolor=\"transparent\";"); | ||
235 | for (sz i = 0; i < array_size(scopes); i++) { | ||
236 | Scope *scope = scopes[i]; | ||
237 | if (!scope) { | ||
238 | continue; | ||
186 | } | 239 | } |
240 | println("subgraph %d {", i); | ||
241 | graph_typescope(scope, a); | ||
242 | graph_functions(scope, a); | ||
243 | println("}"); | ||
187 | } | 244 | } |
188 | return a; | 245 | println("}"); |
246 | } | ||
247 | |||
248 | void | ||
249 | emit_semantic_error(Analyzer *a, Node *n, Str msg) { | ||
250 | eprintln("%s:%d:%d: error: %s", a->file_name, n->line, n->col, msg); | ||
251 | a->err = true; | ||
189 | } | 252 | } |
190 | 253 | ||
191 | bool | 254 | Str type_inference(Analyzer *a, Node *node, Scope *scope); |
192 | type_is_numeric(Type *t) { | 255 | |
193 | if (t == &default_types[TYPE_U8] || | 256 | void |
194 | t == &default_types[TYPE_U16] || | 257 | typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { |
195 | t == &default_types[TYPE_U32] || | 258 | if (node->field_type->kind == NODE_COMPOUND_TYPE) { |
196 | t == &default_types[TYPE_U64] || | 259 | Str field_name = str_concat(symbol, cstr("."), a->storage); |
197 | t == &default_types[TYPE_S8] || | 260 | field_name = str_concat(field_name, node->value.str, a->storage); |
198 | t == &default_types[TYPE_S16] || | 261 | if (structmap_lookup(&scope->structs, field_name)) { |
199 | t == &default_types[TYPE_S32] || | 262 | eprintln("%s:%d:%d: error: struct field '%s' already exists", |
200 | t == &default_types[TYPE_S64] || | 263 | a->file_name, node->line, node->col, field_name); |
201 | t == &default_types[TYPE_F32] || | 264 | a->err = true; |
202 | t == &default_types[TYPE_F64]) { | 265 | } |
203 | return true; | 266 | Str type = cstr("\\{ "); |
267 | for (sz i = 0; i < array_size(node->field_type->elements); i++) { | ||
268 | Node *field = node->field_type->elements[i]; | ||
269 | typecheck_field(a, field, scope, field_name); | ||
270 | type = str_concat(type, field->type, a->storage); | ||
271 | type = str_concat(type, cstr(" "), a->storage); | ||
272 | } | ||
273 | type = str_concat(type, cstr("\\}"), a->storage); | ||
274 | node->type = type; | ||
275 | } else { | ||
276 | Str field_name = str_concat(symbol, cstr("."), a->storage); | ||
277 | field_name = str_concat(field_name, node->value.str, a->storage); | ||
278 | Str field_type = node->field_type->value.str; | ||
279 | if (!find_type(scope, field_type)) { | ||
280 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, | ||
281 | node->field_type->line, node->field_type->col, field_type); | ||
282 | a->err = true; | ||
283 | } | ||
284 | if (node->field_type->is_ptr) { | ||
285 | field_type = str_concat(cstr("@"), field_type, a->storage); | ||
286 | } | ||
287 | if (node->field_type->kind == NODE_ARR_TYPE) { | ||
288 | field_type = str_concat(cstr("@"), field_type, a->storage); | ||
289 | } | ||
290 | if (structmap_lookup(&scope->structs, field_name)) { | ||
291 | eprintln("%s:%d:%d: error: struct field '%s' already exists", | ||
292 | a->file_name, node->line, node->col, field_name); | ||
293 | a->err = true; | ||
294 | } | ||
295 | if (node->field_val) { | ||
296 | Str type = type_inference(a, node->field_val, scope); | ||
297 | if (!str_eq(type, field_type)) { | ||
298 | eprintln( | ||
299 | "%s:%d:%d: error: mismatched types in struct " | ||
300 | "value " | ||
301 | "for '%s': %s expected %s", | ||
302 | a->file_name, node->line, node->col, field_name, type, | ||
303 | field_type); | ||
304 | a->err = true; | ||
305 | } | ||
306 | } | ||
307 | structmap_insert(&scope->structs, field_name, | ||
308 | (Struct){ | ||
309 | .name = field_name, | ||
310 | .type = field_type, | ||
311 | .val = node->field_val, | ||
312 | }, | ||
313 | a->storage); | ||
314 | symmap_insert(&scope->symbols, field_name, | ||
315 | (Symbol){.name = field_type, .kind = SYM_STRUCT_FIELD}, | ||
316 | a->storage); | ||
317 | node->type = field_type; | ||
204 | } | 318 | } |
205 | return false; | ||
206 | } | 319 | } |
207 | 320 | ||
208 | Symbol * | 321 | void |
209 | find_symbol(Scope *scope, Node *node) { | 322 | typecheck_lit_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { |
210 | while (scope != NULL) { | 323 | if (node->field_val->kind == NODE_COMPOUND_TYPE) { |
211 | Symbol *val = ht_lookup(scope->symbols, node); | 324 | Str type = cstr("\\{ "); |
212 | if (val != NULL) { | 325 | for (sz i = 0; i < array_size(node->field_val->elements); i++) { |
213 | return val; | 326 | Node *field = node->field_val->elements[i]; |
327 | Str field_name = str_concat(symbol, cstr("."), a->storage); | ||
328 | field_name = str_concat(field_name, field->value.str, a->storage); | ||
329 | typecheck_lit_field(a, field, scope, field_name); | ||
330 | type = str_concat(type, field->type, a->storage); | ||
331 | type = str_concat(type, cstr(" "), a->storage); | ||
214 | } | 332 | } |
215 | scope = scope->parent; | 333 | type = str_concat(type, cstr("\\}"), a->storage); |
334 | node->type = type; | ||
335 | } else { | ||
336 | StructMap *s = structmap_lookup(&scope->structs, symbol); | ||
337 | if (!s) { | ||
338 | eprintln("%s:%d:%d: error: unknown struct field '%s'", a->file_name, | ||
339 | node->line, node->col, symbol); | ||
340 | a->err = true; | ||
341 | return; | ||
342 | } | ||
343 | Str field_type = s->val.type; | ||
344 | Str type = type_inference(a, node->field_val, scope); | ||
345 | if (!str_eq(type, field_type)) { | ||
346 | eprintln( | ||
347 | "%s:%d:%d: error: mismatched types in struct " | ||
348 | "value " | ||
349 | "for '%s': %s expected %s", | ||
350 | a->file_name, node->line, node->col, symbol, type, field_type); | ||
351 | a->err = true; | ||
352 | } | ||
353 | node->type = field_type; | ||
216 | } | 354 | } |
217 | push_error(ERR_TYPE_SEMANTIC, ERR_UNKNOWN_SYMBOL, node->line, node->col); | ||
218 | return NULL; | ||
219 | } | 355 | } |
220 | 356 | ||
221 | bool | 357 | void |
222 | resolve_type(ParseTree *ast, Scope *scope, Node *node) { | 358 | typecheck_returns(Analyzer *a, Node *node, Str expected) { |
223 | if (node->expr_type != NULL) { | 359 | if (!node) { |
224 | return true; | 360 | return; |
225 | } | 361 | } |
226 | switch (node->type) { | 362 | // Traverse the tree again. |
227 | case NODE_BUILTIN: { | 363 | switch (node->kind) { |
228 | for (size_t i = 0; i < array_size(node->builtin.args); ++i) { | 364 | case NODE_COND: |
229 | Node *arg = node->builtin.args[i]; | 365 | case NODE_MATCH: { |
230 | if (!resolve_type(ast, scope, arg)) { | 366 | for (sz i = 0; i < array_size(node->match_cases); i++) { |
231 | return false; | 367 | Node *next = node->match_cases[i]; |
232 | } | 368 | typecheck_returns(a, next, expected); |
233 | } | 369 | } |
234 | switch (node->builtin.type) { | 370 | } break; |
235 | // Numbers. | 371 | case NODE_RETURN: { |
236 | case TOKEN_ADD: | 372 | bool err = !str_eq(node->type, expected); |
237 | case TOKEN_SUB: | 373 | if (err) { |
238 | case TOKEN_MUL: | 374 | eprintln( |
239 | case TOKEN_DIV: | 375 | "%s:%d:%d: error: mismatched return type %s, expected %s", |
240 | case TOKEN_MOD: { | 376 | a->file_name, node->line, node->col, node->type, expected); |
241 | Type *type = NULL; | 377 | a->err = true; |
242 | for (size_t i = 0; i < array_size(node->builtin.args); ++i) { | 378 | } |
243 | Node *arg = node->builtin.args[i]; | 379 | } break; |
244 | 380 | case NODE_BLOCK: { | |
245 | // Check that all arguments are numbers. | 381 | for (sz i = 0; i < array_size(node->elements); i++) { |
246 | if (!type_is_numeric(arg->expr_type)) { | 382 | Node *next = node->elements[i]; |
247 | push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_TYPE_NUM, | 383 | typecheck_returns(a, next, expected); |
248 | arg->line, arg->col); | 384 | } |
249 | return false; | 385 | } break; |
250 | } | 386 | case NODE_IF: { |
387 | if (node->cond_expr) { | ||
388 | typecheck_returns(a, node->cond_expr, expected); | ||
389 | } | ||
390 | if (node->cond_else) { | ||
391 | typecheck_returns(a, node->cond_else, expected); | ||
392 | } | ||
393 | } break; | ||
394 | case NODE_SET: | ||
395 | case NODE_LET: { | ||
396 | if (node->var_val) { | ||
397 | typecheck_returns(a, node->var_val, expected); | ||
398 | } | ||
399 | } break; | ||
400 | case NODE_ADD: | ||
401 | case NODE_SUB: | ||
402 | case NODE_DIV: | ||
403 | case NODE_MUL: | ||
404 | case NODE_MOD: | ||
405 | case NODE_NOT: | ||
406 | case NODE_AND: | ||
407 | case NODE_OR: | ||
408 | case NODE_EQ: | ||
409 | case NODE_NEQ: | ||
410 | case NODE_LT: | ||
411 | case NODE_GT: | ||
412 | case NODE_LE: | ||
413 | case NODE_GE: | ||
414 | case NODE_BITNOT: | ||
415 | case NODE_BITAND: | ||
416 | case NODE_BITOR: | ||
417 | case NODE_BITLSHIFT: | ||
418 | case NODE_BITRSHIFT: { | ||
419 | if (node->left) { | ||
420 | typecheck_returns(a, node->left, expected); | ||
421 | } | ||
422 | if (node->right) { | ||
423 | typecheck_returns(a, node->right, expected); | ||
424 | } | ||
425 | } break; | ||
426 | default: break; | ||
427 | } | ||
428 | } | ||
251 | 429 | ||
252 | if (type == NULL) { | 430 | Str |
253 | type = arg->expr_type; | 431 | type_inference(Analyzer *a, Node *node, Scope *scope) { |
254 | } else if (type != arg->expr_type) { | 432 | assert(a); |
255 | type = coerce_numeric_types(type, arg->expr_type); | 433 | assert(scope); |
256 | } | 434 | if (!node) { |
435 | return cstr(""); | ||
436 | } | ||
437 | // NOTE: For now we are not going to do implicit numeric conversions. | ||
438 | switch (node->kind) { | ||
439 | case NODE_LET: { | ||
440 | node->type = cstr("nil"); | ||
441 | Str symbol = node->var_name->value.str; | ||
442 | if (symmap_lookup(&scope->symbols, symbol)) { | ||
443 | eprintln( | ||
444 | "%s:%d:%d: error: symbol '%s' already exists in current " | ||
445 | "scope ", | ||
446 | a->file_name, node->var_name->line, node->var_name->col, | ||
447 | symbol); | ||
448 | a->err = true; | ||
449 | return cstr(""); | ||
450 | } | ||
451 | if (node->var_type) { | ||
452 | Str type_name = node->var_type->value.str; | ||
453 | SymbolMap *type = find_type(scope, type_name); | ||
454 | if (type == NULL) { | ||
455 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, | ||
456 | node->var_type->line, node->var_type->col, | ||
457 | type_name); | ||
458 | a->err = true; | ||
459 | return cstr(""); | ||
460 | } | ||
461 | if (node->var_type->is_ptr) { | ||
462 | type_name = str_concat(cstr("@"), type_name, a->storage); | ||
463 | } | ||
464 | if (node->var_type->kind == NODE_ARR_TYPE) { | ||
465 | type_name = str_concat(cstr("@"), type_name, a->storage); | ||
466 | // TODO: typecheck size | ||
467 | // TODO: register array in scope | ||
468 | } | ||
469 | if (node->var_val) { | ||
470 | Str type = type_inference(a, node->var_val, scope); | ||
471 | if (!type.size) { | ||
472 | eprintln( | ||
473 | "%s:%d:%d: error: can't bind `nil` to variable " | ||
474 | "'%s'", | ||
475 | a->file_name, node->var_type->line, | ||
476 | node->var_type->col, symbol); | ||
477 | a->err = true; | ||
478 | return cstr(""); | ||
257 | } | 479 | } |
258 | node->expr_type = type; | 480 | // TODO: Consider compatible types. |
259 | } break; | 481 | if (!str_eq(type, type_name)) { |
260 | // Bools. | 482 | // Special case, enums can be treated as ints. |
261 | case TOKEN_NOT: | 483 | FindEnumResult res = find_enum(scope, type_name); |
262 | // TODO: not should only take one argument and | 484 | if (!(res.map && str_eq(type, cstr("int")))) { |
263 | // return the inverse. | 485 | eprintln( |
264 | case TOKEN_AND: | 486 | "%s:%d:%d: error: type mismatch, trying to " |
265 | case TOKEN_OR: { | 487 | "assing " |
266 | // Check that all arguments are boolean. | 488 | "%s" |
267 | for (size_t i = 0; i < array_size(node->builtin.args); ++i) { | 489 | " to a variable of type %s", |
268 | Node *arg = node->builtin.args[i]; | 490 | a->file_name, node->var_type->line, |
269 | if (arg->expr_type != &default_types[TYPE_BOOL]) { | 491 | node->var_type->col, type, type_name); |
270 | push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_TYPE_BOOL, | 492 | a->err = true; |
271 | arg->line, arg->col); | 493 | return cstr(""); |
272 | return false; | ||
273 | } | 494 | } |
274 | } | 495 | } |
275 | node->expr_type = &default_types[TYPE_BOOL]; | 496 | } |
276 | } break; | 497 | symmap_insert(&scope->symbols, symbol, |
277 | case TOKEN_EQ: | 498 | (Symbol){ |
278 | case TOKEN_LT: | 499 | .name = type_name, |
279 | case TOKEN_GT: | 500 | .kind = SYM_VAR, |
280 | case TOKEN_LE: | 501 | }, |
281 | case TOKEN_GE: { | 502 | a->storage); |
282 | // Check that all arguments are nums. | 503 | return node->type; |
283 | for (size_t i = 0; i < array_size(node->builtin.args); ++i) { | 504 | } |
284 | Node *arg = node->builtin.args[i]; | 505 | |
285 | // TODO: Make sure all arguments have the same type, | 506 | // We don't know the type for this symbol, perform inference. |
286 | // like with numeric expressions. | 507 | Str type = type_inference(a, node->var_val, scope); |
287 | if (!type_is_numeric(arg->expr_type)) { | 508 | if (type.size) { |
288 | push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_TYPE_NUM, | 509 | symmap_insert(&scope->symbols, symbol, |
289 | arg->line, arg->col); | 510 | (Symbol){.name = type, .kind = SYM_VAR}, |
290 | return false; | 511 | a->storage); |
291 | } | 512 | node->var_name->type = type; |
513 | } | ||
514 | return node->type; | ||
515 | } break; | ||
516 | case NODE_SET: { | ||
517 | Str name = type_inference(a, node->var_name, scope); | ||
518 | Str val = type_inference(a, node->var_val, scope); | ||
519 | if (!str_eq(name, val)) { | ||
520 | eprintln( | ||
521 | "%s:%d:%d: error: type mismatch, trying to assing " | ||
522 | "%s" | ||
523 | " to a variable of type %s", | ||
524 | a->file_name, node->line, node->col, val, name); | ||
525 | a->err = true; | ||
526 | return cstr(""); | ||
527 | } | ||
528 | node->type = cstr("nil"); | ||
529 | return node->type; | ||
530 | } break; | ||
531 | case NODE_STRUCT: { | ||
532 | node->type = cstr("nil"); | ||
533 | Str symbol = node->value.str; | ||
534 | if (symmap_lookup(&scope->symbols, symbol) != NULL) { | ||
535 | eprintln( | ||
536 | "%s:%d:%d: error: struct '%s' already exists in current " | ||
537 | "scope", | ||
538 | a->file_name, node->line, node->col, symbol); | ||
539 | a->err = true; | ||
540 | return cstr(""); | ||
541 | } | ||
542 | structmap_insert(&scope->structs, symbol, (Struct){.name = symbol}, | ||
543 | a->storage); | ||
544 | for (sz i = 0; i < array_size(node->struct_field); i++) { | ||
545 | Node *field = node->struct_field[i]; | ||
546 | typecheck_field(a, field, scope, symbol); | ||
547 | } | ||
548 | symmap_insert(&scope->symbols, symbol, | ||
549 | (Symbol){.name = symbol, .kind = SYM_STRUCT}, | ||
550 | a->storage); | ||
551 | return node->type; | ||
552 | } break; | ||
553 | case NODE_ENUM: { | ||
554 | node->type = cstr("nil"); | ||
555 | Str symbol = node->value.str; | ||
556 | if (symmap_lookup(&scope->symbols, symbol) != NULL) { | ||
557 | eprintln( | ||
558 | "%s:%d:%d: error: enum '%s' already exists in current " | ||
559 | "scope", | ||
560 | a->file_name, node->line, node->col, symbol); | ||
561 | a->err = true; | ||
562 | return cstr(""); | ||
563 | } | ||
564 | enummap_insert(&scope->enums, symbol, | ||
565 | (Enum){ | ||
566 | .name = symbol, | ||
567 | .val = node->field_val, | ||
568 | }, | ||
569 | a->storage); | ||
570 | for (sz i = 0; i < array_size(node->struct_field); i++) { | ||
571 | Node *field = node->struct_field[i]; | ||
572 | Str field_name = str_concat(symbol, cstr("."), a->storage); | ||
573 | field_name = | ||
574 | str_concat(field_name, field->value.str, a->storage); | ||
575 | if (enummap_lookup(&scope->enums, field_name)) { | ||
576 | eprintln("%s:%d:%d: error: enum field '%s' already exists", | ||
577 | a->file_name, field->line, field->col, field_name); | ||
578 | a->err = true; | ||
579 | } | ||
580 | if (field->field_val) { | ||
581 | Str type = type_inference(a, field->field_val, scope); | ||
582 | if (!str_eq(type, cstr("int"))) { | ||
583 | eprintln( | ||
584 | "%s:%d:%d: error: non int enum value for '%s.%s'", | ||
585 | a->file_name, field->line, field->col, symbol, | ||
586 | field_name); | ||
587 | a->err = true; | ||
292 | } | 588 | } |
293 | node->expr_type = &default_types[TYPE_BOOL]; | 589 | } |
294 | } break; | 590 | enummap_insert(&scope->enums, field_name, |
295 | default: break; | 591 | (Enum){.name = field_name}, a->storage); |
592 | symmap_insert( | ||
593 | &scope->symbols, field_name, | ||
594 | (Symbol){.name = field_name, .kind = SYM_ENUM_FIELD}, | ||
595 | a->storage); | ||
596 | field->type = symbol; | ||
296 | } | 597 | } |
598 | symmap_insert(&scope->symbols, symbol, | ||
599 | (Symbol){.name = symbol, .kind = SYM_ENUM}, | ||
600 | a->storage); | ||
601 | return node->type; | ||
297 | } break; | 602 | } break; |
298 | case NODE_SYMBOL: { | 603 | case NODE_IF: { |
299 | Symbol *val = find_symbol(scope, node); | 604 | Str cond_type = type_inference(a, node->cond_if, scope); |
300 | if (val == NULL) { | 605 | if (!str_eq(cond_type, cstr("bool"))) { |
301 | return false; | 606 | emit_semantic_error( |
607 | a, node->cond_if, | ||
608 | cstr("non boolean expression on if condition")); | ||
609 | return cstr(""); | ||
302 | } | 610 | } |
303 | 611 | if (node->cond_expr->kind == NODE_BLOCK) { | |
304 | Type *type = NULL; | 612 | node->type = type_inference(a, node->cond_expr, scope); |
305 | switch (val->type) { | 613 | } else { |
306 | case SYMBOL_PAR: | 614 | Scope *next = typescope_alloc(a, scope); |
307 | case SYMBOL_VAR: { | 615 | node->type = type_inference(a, node->cond_expr, next); |
308 | type = find_type(scope, val->var.type); | ||
309 | } break; | ||
310 | case SYMBOL_FUN: { | ||
311 | type = find_type(scope, val->fun.return_type); | ||
312 | } break; | ||
313 | } | 616 | } |
314 | if (type == NULL) { | 617 | if (node->cond_else) { |
315 | return false; | 618 | Str else_type; |
619 | if (node->cond_else->kind == NODE_BLOCK) { | ||
620 | else_type = type_inference(a, node->cond_else, scope); | ||
621 | } else { | ||
622 | Scope *next = typescope_alloc(a, scope); | ||
623 | else_type = type_inference(a, node->cond_else, next); | ||
624 | } | ||
625 | if (!str_eq(node->type, else_type)) { | ||
626 | emit_semantic_error( | ||
627 | a, node, cstr("mismatch types for if/else branches")); | ||
628 | return cstr(""); | ||
629 | } | ||
316 | } | 630 | } |
317 | node->expr_type = type; | 631 | return node->type; |
318 | } break; | 632 | } break; |
319 | case NODE_FUN: { | 633 | case NODE_WHILE: { |
320 | // TODO: don't allow parameters of type void | 634 | Str cond_type = type_inference(a, node->while_cond, scope); |
321 | node->expr_type = &default_types[TYPE_VOID]; | 635 | if (!str_eq(cond_type, cstr("bool"))) { |
322 | 636 | emit_semantic_error( | |
323 | // Fill up new scope with parameters | 637 | a, node->cond_if, |
324 | scope = alloc_scope(scope); | 638 | cstr("non boolean expression on while condition")); |
325 | array_push(ast->scopes, scope); | 639 | return cstr(""); |
326 | 640 | } | |
327 | // Parameters. | 641 | if (node->while_expr->kind != NODE_BLOCK) { |
328 | for (size_t i = 0; i < array_size(node->fun.param_names); ++i) { | 642 | scope = typescope_alloc(a, scope); |
329 | Node *param = node->fun.param_names[i]; | 643 | } |
330 | Node *type = node->fun.param_types[i]; | 644 | type_inference(a, node->while_expr, scope); |
331 | Symbol *var = alloc_symval(param, SYMBOL_PAR); | 645 | node->type = cstr("nil"); |
332 | var->var.type = type; | 646 | return node->type; |
333 | if (!insert_symbol(scope, param, var)) { | 647 | } break; |
334 | return false; | 648 | case NODE_COND: { |
649 | Str previous = cstr(""); | ||
650 | for (sz i = 0; i < array_size(node->match_cases); i++) { | ||
651 | Node *expr = node->match_cases[i]; | ||
652 | Str next = type_inference(a, expr, scope); | ||
653 | if (i != 0 && !str_eq(next, previous)) { | ||
654 | emit_semantic_error( | ||
655 | a, node, | ||
656 | cstr("non-matching types for cond expressions")); | ||
657 | return cstr(""); | ||
335 | } | 658 | } |
659 | previous = next; | ||
336 | } | 660 | } |
337 | 661 | node->type = previous; | |
338 | // Body. | 662 | return node->type; |
339 | Node *body = node->fun.body; | 663 | } break; |
340 | if (body->type == NODE_BLOCK) { | 664 | case NODE_MATCH: { |
341 | for (size_t i = 0; i < array_size(body->block.expr); ++i) { | 665 | Str e = type_inference(a, node->match_expr, scope); |
342 | Node *expr = body->block.expr[i]; | 666 | if (str_eq(e, cstr("int"))) { |
343 | if (!resolve_type(ast, scope, expr)) { | 667 | // Integer matching. |
344 | return false; | 668 | for (sz i = 0; i < array_size(node->match_cases); i++) { |
669 | Node *field = node->match_cases[i]; | ||
670 | if (field->case_value) { | ||
671 | if (field->case_value->kind != NODE_NUM_INT && | ||
672 | field->case_value->kind != NODE_NUM_UINT) { | ||
673 | emit_semantic_error( | ||
674 | a, field->case_value, | ||
675 | cstr( | ||
676 | "non-integer or enum types on match case")); | ||
677 | } | ||
345 | } | 678 | } |
346 | } | 679 | } |
347 | Node *last_expr = body->block.expr[array_size(body->block.expr) - 1]; | ||
348 | node->fun.body->expr_type = last_expr->expr_type; | ||
349 | } else { | 680 | } else { |
350 | if (!resolve_type(ast, scope, body)) { | 681 | // Get enum type and de-structure the match. |
351 | return false; | 682 | FindEnumResult res = find_enum(scope, e); |
683 | Str enum_prefix = | ||
684 | str_concat(res.map->val.name, cstr("."), a->storage); | ||
685 | for (sz i = 0; i < array_size(node->match_cases); i++) { | ||
686 | Node *field = node->match_cases[i]; | ||
687 | if (field->case_value) { | ||
688 | Str field_name = str_concat( | ||
689 | enum_prefix, field->case_value->value.str, | ||
690 | a->storage); | ||
691 | if (!enummap_lookup(&res.scope->enums, field_name)) { | ||
692 | eprintln("%s:%d:%d: error: unknown enum field '%s'", | ||
693 | a->file_name, field->case_value->line, | ||
694 | field->case_value->col, field_name); | ||
695 | a->err = true; | ||
696 | } | ||
697 | } | ||
352 | } | 698 | } |
353 | } | 699 | } |
354 | 700 | Str previous = cstr(""); | |
355 | // Check that the type of body matches the return type. | 701 | for (sz i = 0; i < array_size(node->match_cases); i++) { |
356 | StringView *type_body = &node->fun.body->expr_type->name; | 702 | Node *expr = node->match_cases[i]; |
357 | StringView *return_type = &node->fun.return_type->string; | 703 | Str next = type_inference(a, expr, scope); |
358 | if (!sv_equal(type_body, return_type)) { | 704 | if (i != 0 && !str_eq(next, previous)) { |
359 | push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_RET_TYPE, node->line, node->col); | 705 | emit_semantic_error( |
360 | return false; | 706 | a, node, |
707 | cstr("non-matching types for match expressions")); | ||
708 | return cstr(""); | ||
709 | } | ||
710 | previous = next; | ||
361 | } | 711 | } |
712 | node->type = previous; | ||
713 | return node->type; | ||
362 | } break; | 714 | } break; |
363 | case NODE_BLOCK: { | 715 | case NODE_CASE_MATCH: { |
364 | scope = alloc_scope(scope); | 716 | if (node->case_expr->kind != NODE_BLOCK) { |
365 | array_push(ast->scopes, scope); | 717 | scope = typescope_alloc(a, scope); |
366 | for (size_t i = 0; i < array_size(node->block.expr); ++i) { | 718 | } |
367 | Node *expr = node->block.expr[i]; | 719 | node->type = type_inference(a, node->case_expr, scope); |
368 | if (!resolve_type(ast, scope, expr)) { | 720 | return node->type; |
369 | return false; | 721 | } break; |
722 | case NODE_CASE_COND: { | ||
723 | if (node->case_value) { | ||
724 | Str cond = type_inference(a, node->case_value, scope); | ||
725 | if (!str_eq(cond, cstr("bool"))) { | ||
726 | emit_semantic_error(a, node, | ||
727 | cstr("non-boolean case condition")); | ||
370 | } | 728 | } |
371 | } | 729 | } |
372 | Node *last_expr = node->block.expr[array_size(node->block.expr) - 1]; | 730 | if (node->case_expr->kind != NODE_BLOCK) { |
373 | node->expr_type = last_expr->expr_type; | 731 | scope = typescope_alloc(a, scope); |
732 | } | ||
733 | node->type = type_inference(a, node->case_expr, scope); | ||
734 | return node->type; | ||
374 | } break; | 735 | } break; |
375 | case NODE_IF: { | 736 | case NODE_TRUE: |
376 | // TODO: If we don't have an else, ifexpr.expr_true | 737 | case NODE_FALSE: { |
377 | // must be void for consistency. | 738 | node->type = cstr("bool"); |
378 | if (!resolve_type(ast, scope, node->ifexpr.cond)) { | 739 | return node->type; |
379 | return false; | 740 | } break; |
380 | } | 741 | case NODE_NIL: { |
381 | if (!resolve_type(ast, scope, node->ifexpr.expr_true)) { | 742 | node->type = cstr("nil"); |
382 | return false; | 743 | return node->type; |
383 | } | 744 | } break; |
384 | Type *type_true = node->ifexpr.expr_true->expr_type; | 745 | case NODE_NOT: |
385 | node->expr_type = type_true; | 746 | case NODE_AND: |
386 | if (node->ifexpr.expr_false != NULL) { | 747 | case NODE_OR: { |
387 | if (!resolve_type(ast, scope, node->ifexpr.expr_false)) { | 748 | Str left = type_inference(a, node->left, scope); |
388 | return false; | 749 | if (!str_eq(left, cstr("bool"))) { |
750 | emit_semantic_error(a, node, | ||
751 | cstr("expected bool on logic expression")); | ||
752 | return cstr(""); | ||
753 | } | ||
754 | if (node->right) { | ||
755 | Str right = type_inference(a, node->right, scope); | ||
756 | if (!str_eq(right, cstr("bool"))) { | ||
757 | emit_semantic_error( | ||
758 | a, node, cstr("expected bool on logic expression")); | ||
759 | return cstr(""); | ||
760 | } | ||
761 | } | ||
762 | node->type = cstr("bool"); | ||
763 | return node->type; | ||
764 | } break; | ||
765 | case NODE_EQ: | ||
766 | case NODE_NEQ: | ||
767 | case NODE_LT: | ||
768 | case NODE_GT: | ||
769 | case NODE_LE: | ||
770 | case NODE_GE: { | ||
771 | Str left = type_inference(a, node->left, scope); | ||
772 | Str right = type_inference(a, node->right, scope); | ||
773 | if (!str_eq(left, right)) { | ||
774 | emit_semantic_error( | ||
775 | a, node, cstr("mismatched types on binary expression")); | ||
776 | return cstr(""); | ||
777 | } | ||
778 | node->type = cstr("bool"); | ||
779 | return node->type; | ||
780 | } break; | ||
781 | case NODE_BITNOT: { | ||
782 | Str left = type_inference(a, node->left, scope); | ||
783 | if (!strset_lookup(&a->integer_types, left)) { | ||
784 | emit_semantic_error( | ||
785 | a, node, cstr("non integer type on bit twiddling expr")); | ||
786 | return cstr(""); | ||
787 | } | ||
788 | node->type = left; | ||
789 | return node->type; | ||
790 | } break; | ||
791 | case NODE_BITAND: | ||
792 | case NODE_BITOR: | ||
793 | case NODE_BITLSHIFT: | ||
794 | case NODE_BITRSHIFT: { | ||
795 | Str left = type_inference(a, node->left, scope); | ||
796 | Str right = type_inference(a, node->right, scope); | ||
797 | if (!strset_lookup(&a->integer_types, left) || | ||
798 | !strset_lookup(&a->integer_types, right)) { | ||
799 | emit_semantic_error( | ||
800 | a, node, cstr("non integer type on bit twiddling expr")); | ||
801 | return cstr(""); | ||
802 | } | ||
803 | node->type = left; | ||
804 | return node->type; | ||
805 | } break; | ||
806 | case NODE_ADD: | ||
807 | case NODE_SUB: | ||
808 | case NODE_DIV: | ||
809 | case NODE_MUL: | ||
810 | case NODE_MOD: { | ||
811 | Str left = type_inference(a, node->left, scope); | ||
812 | Str right = type_inference(a, node->right, scope); | ||
813 | if (!strset_lookup(&a->numeric_types, left) || | ||
814 | !strset_lookup(&a->numeric_types, right)) { | ||
815 | emit_semantic_error( | ||
816 | a, node, cstr("non numeric type on arithmetic expr")); | ||
817 | return cstr(""); | ||
818 | } | ||
819 | if (!str_eq(left, right)) { | ||
820 | emit_semantic_error( | ||
821 | a, node, cstr("mismatched types on binary expression")); | ||
822 | return cstr(""); | ||
823 | } | ||
824 | node->type = left; | ||
825 | return node->type; | ||
826 | } break; | ||
827 | case NODE_NUM_UINT: { | ||
828 | node->type = cstr("uint"); | ||
829 | return node->type; | ||
830 | } break; | ||
831 | case NODE_NUM_INT: { | ||
832 | node->type = cstr("int"); | ||
833 | return node->type; | ||
834 | } break; | ||
835 | case NODE_NUM_FLOAT: { | ||
836 | node->type = cstr("f64"); | ||
837 | return node->type; | ||
838 | } break; | ||
839 | case NODE_STRING: { | ||
840 | node->type = cstr("str"); | ||
841 | return node->type; | ||
842 | } break; | ||
843 | case NODE_ARR_TYPE: | ||
844 | case NODE_TYPE: { | ||
845 | SymbolMap *type = find_type(scope, node->value.str); | ||
846 | if (!type) { | ||
847 | emit_semantic_error(a, node, cstr("unknown type")); | ||
848 | return cstr(""); | ||
849 | } | ||
850 | node->type = type->val.name; | ||
851 | return node->type; | ||
852 | } break; | ||
853 | case NODE_SYMBOL_IDX: | ||
854 | case NODE_SYMBOL: { | ||
855 | Str symbol = node->value.str; | ||
856 | SymbolMap *type = find_type(scope, symbol); | ||
857 | if (!type) { | ||
858 | eprintln("%s:%d:%d: error: couldn't resolve symbol '%s'", | ||
859 | a->file_name, node->line, node->col, symbol); | ||
860 | a->err = true; | ||
861 | return cstr(""); | ||
862 | } | ||
863 | Str type_name = type->val.name; | ||
864 | if (node->kind == NODE_SYMBOL_IDX) { | ||
865 | Str idx_type = type_inference(a, node->arr_size, scope); | ||
866 | if (!strset_lookup(&a->integer_types, idx_type)) { | ||
867 | emit_semantic_error( | ||
868 | a, node, cstr("can't resolve non integer index")); | ||
869 | return cstr(""); | ||
389 | } | 870 | } |
871 | type_name = str_remove_prefix(type_name, cstr("@")); | ||
872 | } | ||
873 | if (node->is_ptr) { | ||
874 | type_name = str_concat(cstr("@"), type_name, a->storage); | ||
390 | } | 875 | } |
391 | 876 | ||
392 | // Check ifexpr.cond is a bool. | 877 | FindEnumResult e = find_enum(scope, type_name); |
393 | Type *type_cond = node->ifexpr.cond->expr_type; | 878 | if (e.map && str_eq(symbol, type_name)) { |
394 | if (!sv_equal(&type_cond->name, &default_types[TYPE_BOOL].name)) { | 879 | if (!node->next) { |
395 | push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_COND_TYPE, | 880 | eprintln( |
396 | node->line, node->col); | 881 | "%s:%d:%d: error: unspecified enum field for symbol " |
397 | return false; | 882 | "'%s'", |
883 | a->file_name, node->line, node->col, symbol); | ||
884 | a->err = true; | ||
885 | return cstr(""); | ||
886 | } | ||
887 | // Check if there is a next and it matches the enum field. | ||
888 | Str field = str_concat(type_name, cstr("."), a->storage); | ||
889 | field = str_concat(field, node->next->value.str, a->storage); | ||
890 | if (!enummap_lookup(&e.scope->enums, field)) { | ||
891 | eprintln( | ||
892 | "%s:%d:%d: error: unknown enum field for " | ||
893 | "'%s': %s", | ||
894 | a->file_name, node->line, node->col, symbol, | ||
895 | node->next->value.str); | ||
896 | a->err = true; | ||
897 | return cstr(""); | ||
898 | } | ||
899 | node->next->type = type_name; | ||
900 | node->type = type_name; | ||
901 | return node->next->type; | ||
398 | } | 902 | } |
399 | 903 | ||
400 | // Check if types of expr_true and expr_false match | 904 | FindStructResult s = find_struct(scope, type_name); |
401 | if (node->ifexpr.expr_false != NULL) { | 905 | if (s.map) { |
402 | Type *type_false = node->ifexpr.expr_false->expr_type; | 906 | if (str_eq(symbol, type_name)) { |
403 | if (type_is_numeric(type_true) && type_is_numeric(type_false)) { | 907 | eprintln( |
404 | node->expr_type = coerce_numeric_types(type_true, type_false); | 908 | "%s:%d:%d: error: struct incomplete struct literal " |
405 | } else if (!sv_equal(&type_true->name, &type_false->name)) { | 909 | "'%s', did you mean to use %s:{}?", |
406 | push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_TYPE_T_F, | 910 | a->file_name, node->line, node->col, symbol, symbol); |
407 | node->line, node->col); | 911 | a->err = true; |
408 | return false; | 912 | return cstr(""); |
913 | } else { | ||
914 | if (node->next) { | ||
915 | Str chain = type_name; | ||
916 | Node *next = node; | ||
917 | while (next->next) { | ||
918 | next = next->next; | ||
919 | chain = str_concat(chain, cstr("."), a->storage); | ||
920 | chain = | ||
921 | str_concat(chain, next->value.str, a->storage); | ||
922 | } | ||
923 | StructMap *field = | ||
924 | structmap_lookup(&s.scope->structs, chain); | ||
925 | if (!field) { | ||
926 | eprintln( | ||
927 | "%s:%d:%d: error: unknown struct field '%s'", | ||
928 | a->file_name, node->line, node->col, chain); | ||
929 | a->err = true; | ||
930 | return cstr(""); | ||
931 | } | ||
932 | Str field_type = field->val.type; | ||
933 | if (next->kind == NODE_SYMBOL_IDX) { | ||
934 | Str idx_type = | ||
935 | type_inference(a, next->arr_size, scope); | ||
936 | if (!strset_lookup(&a->integer_types, idx_type)) { | ||
937 | emit_semantic_error( | ||
938 | a, next, | ||
939 | cstr("can't resolve non integer index")); | ||
940 | return cstr(""); | ||
941 | } | ||
942 | field_type = | ||
943 | str_remove_prefix(field_type, cstr("@")); | ||
944 | } | ||
945 | node->type = field_type; | ||
946 | return node->type; | ||
947 | } | ||
409 | } | 948 | } |
410 | } | 949 | } |
950 | node->type = type_name; | ||
951 | return node->type; | ||
411 | } break; | 952 | } break; |
412 | case NODE_SET: { | 953 | case NODE_STRUCT_LIT: { |
413 | node->expr_type = &default_types[TYPE_VOID]; | 954 | Str name = node->value.str; |
414 | if (!resolve_type(ast, scope, node->set.symbol)) { | 955 | FindStructResult s = find_struct(scope, name); |
415 | return false; | 956 | if (!s.map) { |
416 | } | 957 | eprintln("%s:%d:%d: error: unknown struct type '%s'", |
417 | if (!resolve_type(ast, scope, node->set.value)) { | 958 | a->file_name, node->line, node->col, name); |
418 | return false; | 959 | a->err = true; |
419 | } | 960 | return cstr(""); |
420 | Node *symbol = node->set.symbol; | ||
421 | Node *value = node->set.value; | ||
422 | if (!sv_equal(&symbol->expr_type->name, &value->expr_type->name)) { | ||
423 | push_error(ERR_TYPE_SEMANTIC, ERR_TYPE_MISMATCH, | ||
424 | node->line, node->col); | ||
425 | return false; | ||
426 | } | ||
427 | } break; | ||
428 | case NODE_DEF: { | ||
429 | // TODO: don't allow assignment of expressions that return void | ||
430 | // Prepare value for symbol table. | ||
431 | Symbol *var = alloc_symval(node->def.symbol, SYMBOL_VAR); | ||
432 | var->var.type = node->def.type; | ||
433 | if (!insert_symbol(scope, node->def.symbol, var)) { | ||
434 | return false; | ||
435 | } | ||
436 | |||
437 | Type *type = find_type(scope, node->def.type); | ||
438 | if (type == NULL) { | ||
439 | return false; | ||
440 | } | ||
441 | node->def.symbol->expr_type = type; | ||
442 | |||
443 | node->expr_type = &default_types[TYPE_VOID]; | ||
444 | // TODO: type inference from right side when not annotated? | ||
445 | if (!resolve_type(ast, scope, node->def.value)) { | ||
446 | return false; | ||
447 | } | ||
448 | Node *symbol = node->def.symbol; | ||
449 | Node *value = node->def.value; | ||
450 | if (!sv_equal(&symbol->expr_type->name, &value->expr_type->name)) { | ||
451 | push_error(ERR_TYPE_SEMANTIC, ERR_TYPE_MISMATCH, | ||
452 | node->line, node->col); | ||
453 | return false; | ||
454 | } | ||
455 | } break; | ||
456 | case NODE_NUMBER: { | ||
457 | // TODO: Numbers are f64/s64 unless explicitely annotated. Annotated | ||
458 | // numbers must fit in the given range (e.g. no negative constants | ||
459 | // inside a u64, no numbers bigger than 255 in a u8, etc.). | ||
460 | if (node->number.fractional != 0) { | ||
461 | // TODO: 1.0 should also be checked as float. | ||
462 | node->expr_type = &default_types[TYPE_F64]; | ||
463 | } else { | ||
464 | node->expr_type = &default_types[TYPE_S64]; | ||
465 | } | 961 | } |
962 | |||
963 | StrSet *set = NULL; | ||
964 | for (sz i = 0; i < array_size(node->elements); i++) { | ||
965 | Node *next = node->elements[i]; | ||
966 | Str field_name = str_concat(name, cstr("."), a->storage); | ||
967 | field_name = | ||
968 | str_concat(field_name, next->value.str, a->storage); | ||
969 | |||
970 | if (strset_lookup(&set, field_name)) { | ||
971 | eprintln( | ||
972 | "%s:%d:%d: error: field '%s' already present in struct " | ||
973 | "literal", | ||
974 | a->file_name, next->line, next->col, field_name); | ||
975 | a->err = true; | ||
976 | } else { | ||
977 | strset_insert(&set, field_name, a->storage); | ||
978 | } | ||
979 | typecheck_lit_field(a, next, s.scope, field_name); | ||
980 | } | ||
981 | node->type = name; | ||
982 | return node->type; | ||
466 | } break; | 983 | } break; |
467 | case NODE_BOOL: { | 984 | case NODE_FUNCALL: { |
468 | node->expr_type = &default_types[TYPE_BOOL]; | 985 | Str symbol = node->value.str; |
986 | FunMap *fun = find_fun(scope, symbol); | ||
987 | if (!fun) { | ||
988 | eprintln( | ||
989 | "%s:%d:%d: error: function '%s' doesn't exist in current " | ||
990 | "scope ", | ||
991 | a->file_name, node->line, node->col, symbol); | ||
992 | a->err = true; | ||
993 | return cstr(""); | ||
994 | } | ||
995 | // Check that actual parameters typecheck | ||
996 | Str args = cstr(""); | ||
997 | for (sz i = 0; i < array_size(node->elements); i++) { | ||
998 | Node *expr = node->elements[i]; | ||
999 | Str type = type_inference(a, expr, scope); | ||
1000 | args = str_concat(args, type, a->storage); | ||
1001 | if (i != array_size(node->elements) - 1) { | ||
1002 | args = str_concat(args, cstr(","), a->storage); | ||
1003 | } | ||
1004 | } | ||
1005 | if (!args.size) { | ||
1006 | args = cstr("nil"); | ||
1007 | } | ||
1008 | Str expected = fun->val.param_type; | ||
1009 | if (!str_eq(args, expected) && !str_eq(expected, cstr("..."))) { | ||
1010 | eprintln( | ||
1011 | "%s:%d:%d: error: mismatched parameter types: %s expected " | ||
1012 | "%s", | ||
1013 | a->file_name, node->line, node->col, args, expected); | ||
1014 | a->err = true; | ||
1015 | } | ||
1016 | node->type = fun->val.return_type; | ||
1017 | return node->type; | ||
469 | } break; | 1018 | } break; |
470 | case NODE_STRING: { | 1019 | case NODE_BLOCK: { |
471 | node->expr_type = &default_types[TYPE_STR]; | 1020 | scope = typescope_alloc(a, scope); |
1021 | Str type; | ||
1022 | for (sz i = 0; i < array_size(node->elements); i++) { | ||
1023 | Node *expr = node->elements[i]; | ||
1024 | type = type_inference(a, expr, scope); | ||
1025 | } | ||
1026 | node->type = type; | ||
1027 | return node->type; | ||
472 | } break; | 1028 | } break; |
473 | case NODE_FUNCALL: { | 1029 | case NODE_RETURN: { |
474 | Symbol *val = find_symbol(scope, node->funcall.name); | 1030 | Str ret_type = cstr(""); |
475 | if (!resolve_type(ast, scope, node->funcall.name)) { | 1031 | for (sz i = 0; i < array_size(node->elements); i++) { |
476 | return false; | 1032 | Node *expr = node->elements[i]; |
477 | } | 1033 | Str type = type_inference(a, expr, scope); |
478 | if (val->type != SYMBOL_FUN) { | 1034 | ret_type = str_concat(ret_type, type, a->storage); |
479 | push_error(ERR_TYPE_SEMANTIC, ERR_WRONG_TYPE_FUN, | 1035 | if (i != array_size(node->elements) - 1) { |
480 | node->funcall.name->line, node->funcall.name->col); | 1036 | ret_type = str_concat(ret_type, cstr(","), a->storage); |
481 | return false; | 1037 | } |
482 | } | 1038 | } |
483 | if (array_size(node->funcall.args) != array_size(val->fun.param_types)) { | 1039 | if (!ret_type.size) { |
484 | push_error(ERR_TYPE_SEMANTIC, ERR_BAD_ARGS, node->line, node->col); | 1040 | ret_type = cstr("nil"); |
485 | return false; | 1041 | } |
486 | } | 1042 | node->type = ret_type; |
487 | node->expr_type = node->funcall.name->expr_type; | 1043 | return node->type; |
488 | for (size_t i = 0; i < array_size(node->funcall.args); ++i) { | 1044 | } break; |
489 | Node *arg = node->funcall.args[i]; | 1045 | case NODE_FUN: { |
490 | if (!resolve_type(ast, scope, arg)) { | 1046 | node->type = cstr("nil"); |
491 | return false; | 1047 | Scope *prev_scope = scope; |
1048 | scope = typescope_alloc(a, scope); | ||
1049 | Str param_type = cstr(""); | ||
1050 | for (sz i = 0; i < array_size(node->func_params); i++) { | ||
1051 | Node *param = node->func_params[i]; | ||
1052 | Str symbol = param->param_name->value.str; | ||
1053 | Str type = param->param_type->value.str; | ||
1054 | if (param->param_type->is_ptr) { | ||
1055 | type = str_concat(cstr("@"), type, a->storage); | ||
1056 | } | ||
1057 | if (param->param_type->kind == NODE_ARR_TYPE) { | ||
1058 | type = str_concat(cstr("@"), type, a->storage); | ||
1059 | } | ||
1060 | param->param_name->type = | ||
1061 | type_inference(a, param->param_type, scope); | ||
1062 | param->type = type; | ||
1063 | symmap_insert(&scope->symbols, symbol, | ||
1064 | (Symbol){.name = type, .kind = SYM_PARAM}, | ||
1065 | a->storage); | ||
1066 | param_type = str_concat(param_type, type, a->storage); | ||
1067 | if (i != array_size(node->func_params) - 1) { | ||
1068 | param_type = str_concat(param_type, cstr(","), a->storage); | ||
1069 | } | ||
1070 | } | ||
1071 | if (!param_type.size) { | ||
1072 | param_type = cstr("nil"); | ||
1073 | } | ||
1074 | node->fun_params = param_type; | ||
1075 | |||
1076 | Str ret_type = cstr(""); | ||
1077 | for (sz i = 0; i < array_size(node->func_ret); i++) { | ||
1078 | Node *expr = node->func_ret[i]; | ||
1079 | Str type = type_inference(a, expr, scope); | ||
1080 | if (expr->is_ptr) { | ||
1081 | type = str_concat(cstr("@"), type, a->storage); | ||
1082 | } | ||
1083 | if (expr->kind == NODE_ARR_TYPE) { | ||
1084 | type = str_concat(cstr("@"), type, a->storage); | ||
492 | } | 1085 | } |
493 | Node *expected = val->fun.param_types[i]; | 1086 | ret_type = str_concat(ret_type, type, a->storage); |
494 | if (!sv_equal(&arg->expr_type->name, &expected->string)) { | 1087 | if (i != array_size(node->func_ret) - 1) { |
495 | push_error(ERR_TYPE_SEMANTIC, ERR_TYPE_MISMATCH, | 1088 | ret_type = str_concat(ret_type, cstr(","), a->storage); |
496 | arg->line, arg->col); | ||
497 | return false; | ||
498 | } | 1089 | } |
499 | } | 1090 | } |
1091 | if (!ret_type.size) { | ||
1092 | ret_type = cstr("nil"); | ||
1093 | } | ||
1094 | node->fun_return = ret_type; | ||
1095 | |||
1096 | Str symbol = node->func_name->value.str; | ||
1097 | if (prev_scope->parent != NULL) { | ||
1098 | if (symmap_lookup(&prev_scope->symbols, symbol)) { | ||
1099 | eprintln( | ||
1100 | "%s:%d:%d: error: function '%s' already defined in " | ||
1101 | "current " | ||
1102 | "scope ", | ||
1103 | a->file_name, node->var_name->line, node->var_name->col, | ||
1104 | symbol); | ||
1105 | a->err = true; | ||
1106 | return cstr(""); | ||
1107 | } | ||
1108 | symmap_insert(&scope->symbols, symbol, | ||
1109 | (Symbol){.name = symbol, .kind = SYM_FUN}, | ||
1110 | a->storage); | ||
1111 | } | ||
1112 | scope->name = symbol; | ||
1113 | funmap_insert(&prev_scope->funcs, symbol, | ||
1114 | (Fun){.name = symbol, | ||
1115 | .param_type = param_type, | ||
1116 | .return_type = ret_type}, | ||
1117 | a->storage); | ||
1118 | |||
1119 | if (node->func_body->kind == NODE_BLOCK) { | ||
1120 | Str type; | ||
1121 | for (sz i = 0; i < array_size(node->func_body->elements); i++) { | ||
1122 | Node *expr = node->func_body->elements[i]; | ||
1123 | type = type_inference(a, expr, scope); | ||
1124 | } | ||
1125 | if (!type.size) { | ||
1126 | type = cstr("nil"); | ||
1127 | } | ||
1128 | node->func_body->type = type; | ||
1129 | } else { | ||
1130 | type_inference(a, node->func_body, scope); | ||
1131 | } | ||
1132 | |||
1133 | // Ensure main body return matches the prototype. | ||
1134 | if (!str_eq(node->func_body->type, ret_type)) { | ||
1135 | eprintln( | ||
1136 | "%s:%d:%d: error: mismatched return type %s, expected %s", | ||
1137 | a->file_name, node->line, node->col, node->func_body->type, | ||
1138 | ret_type); | ||
1139 | a->err = true; | ||
1140 | } | ||
1141 | |||
1142 | // Ensure ALL return statements match the function prototype. | ||
1143 | typecheck_returns(a, node->func_body, ret_type); | ||
1144 | |||
1145 | // TODO: should return statements be allowed on let blocks? | ||
1146 | return node->type; | ||
1147 | } break; | ||
1148 | default: { | ||
1149 | emit_semantic_error(a, node, | ||
1150 | cstr("type inference not implemented for this " | ||
1151 | "kind of expression")); | ||
1152 | println("KIND: %s", node_str[node->kind]); | ||
500 | } break; | 1153 | } break; |
501 | default: break; | ||
502 | } | 1154 | } |
503 | return true; | 1155 | return cstr(""); |
504 | } | 1156 | } |
505 | 1157 | ||
506 | ParseTree * | 1158 | void |
507 | semantic_analysis(Root *roots) { | 1159 | symbolic_analysis(Analyzer *a, Parser *parser) { |
508 | ParseTree *parse_tree = malloc(sizeof(ParseTree)); | 1160 | Scope *scope = typescope_alloc(a, NULL); |
509 | parse_tree->roots = roots; | 1161 | assert(a); |
510 | array_init(parse_tree->scopes, 0); | 1162 | assert(parser); |
511 | Scope *scope = alloc_scope(NULL); | ||
512 | array_push(parse_tree->scopes, scope); | ||
513 | |||
514 | // Fill global scope with default types. | ||
515 | HashTable *types = scope->types; | ||
516 | for (size_t i = 0; i < sizeof(default_types)/sizeof(Type); ++i) { | ||
517 | Type *type = &default_types[i]; | ||
518 | ht_insert(types, &type->name, type); | ||
519 | } | ||
520 | 1163 | ||
521 | // Fill up global function symbols. | 1164 | // Fill builtin tables. |
522 | for (size_t i = 0; i < array_size(parse_tree->roots); ++i) { | 1165 | Str builtin_functions[] = { |
523 | Node *root = parse_tree->roots[i]; | 1166 | cstr("print"), |
524 | if (root->type == NODE_FUN) { | 1167 | cstr("println"), |
525 | Node *name = root->fun.name; | 1168 | }; |
526 | Symbol *fun = alloc_symval(root->fun.name, SYMBOL_FUN); | 1169 | for (sz i = 0; i < LEN(builtin_functions); i++) { |
527 | fun->fun.param_types = root->fun.param_types; | 1170 | Str symbol = builtin_functions[i]; |
528 | fun->fun.return_type = root->fun.return_type; | 1171 | symmap_insert(&scope->symbols, symbol, |
529 | if (!insert_symbol(scope, name, fun)) { | 1172 | (Symbol){.name = symbol, .kind = SYM_BUILTIN_FUN}, |
530 | return NULL; | 1173 | a->storage); |
1174 | funmap_insert(&scope->funcs, symbol, | ||
1175 | (Fun){.name = symbol, | ||
1176 | .param_type = cstr("..."), | ||
1177 | .return_type = cstr("nil")}, | ||
1178 | a->storage); | ||
1179 | } | ||
1180 | Str builtin_types[] = { | ||
1181 | cstr("u8"), cstr("s8"), cstr("u16"), cstr("s16"), | ||
1182 | cstr("u32"), cstr("s32"), cstr("u64"), cstr("s64"), | ||
1183 | cstr("f32"), cstr("f64"), cstr("ptr"), cstr("int"), | ||
1184 | cstr("uint"), cstr("str"), cstr("bool"), cstr("nil")}; | ||
1185 | for (sz i = 0; i < LEN(builtin_types); i++) { | ||
1186 | Str type = builtin_types[i]; | ||
1187 | symmap_insert(&scope->symbols, type, | ||
1188 | (Symbol){.name = type, .kind = SYM_BUILTIN_TYPE}, | ||
1189 | a->storage); | ||
1190 | } | ||
1191 | Str numeric_types[] = { | ||
1192 | cstr("u8"), cstr("s8"), cstr("u16"), cstr("s16"), cstr("u32"), | ||
1193 | cstr("s32"), cstr("u64"), cstr("s64"), cstr("f32"), cstr("f64"), | ||
1194 | cstr("ptr"), cstr("int"), cstr("uint"), | ||
1195 | }; | ||
1196 | for (sz i = 0; i < LEN(numeric_types); i++) { | ||
1197 | Str type = numeric_types[i]; | ||
1198 | strset_insert(&a->numeric_types, type, a->storage); | ||
1199 | } | ||
1200 | Str integer_types[] = { | ||
1201 | cstr("u8"), cstr("s8"), cstr("u16"), cstr("s16"), | ||
1202 | cstr("u32"), cstr("s32"), cstr("u64"), cstr("s64"), | ||
1203 | cstr("ptr"), cstr("int"), cstr("uint"), | ||
1204 | }; | ||
1205 | for (sz i = 0; i < LEN(integer_types); i++) { | ||
1206 | Str type = integer_types[i]; | ||
1207 | strset_insert(&a->integer_types, type, a->storage); | ||
1208 | } | ||
1209 | // Find top level function declarations. | ||
1210 | for (sz i = 0; i < array_size(parser->nodes); i++) { | ||
1211 | Node *root = parser->nodes[i]; | ||
1212 | if (root->kind == NODE_FUN) { | ||
1213 | Str symbol = root->func_name->value.str; | ||
1214 | if (symmap_lookup(&scope->symbols, symbol)) { | ||
1215 | eprintln( | ||
1216 | "%s:%d:%d: error: function '%s' already defined in " | ||
1217 | "current " | ||
1218 | "scope ", | ||
1219 | a->file_name, root->var_name->line, root->var_name->col, | ||
1220 | symbol); | ||
1221 | a->err = true; | ||
531 | } | 1222 | } |
1223 | symmap_insert(&scope->symbols, symbol, | ||
1224 | (Symbol){.name = symbol, .kind = SYM_FUN}, | ||
1225 | a->storage); | ||
532 | } | 1226 | } |
533 | } | 1227 | } |
534 | 1228 | // Recursively fill symbol tables. | |
535 | for (size_t i = 0; i < array_size(parse_tree->roots); ++i) { | 1229 | for (sz i = 0; i < array_size(parser->nodes); i++) { |
536 | // Fill up symbol tables in proper scope and resolve type of expression | 1230 | Node *root = parser->nodes[i]; |
537 | // for all elements. | 1231 | type_inference(a, root, scope); |
538 | if (!resolve_type(parse_tree, scope, parse_tree->roots[i])) { | ||
539 | return NULL; | ||
540 | } | ||
541 | } | 1232 | } |
542 | |||
543 | return parse_tree; | ||
544 | } | 1233 | } |
1234 | |||