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