diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-26 15:27:24 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-26 15:27:24 +0200 |
commit | e40b04daf942ae01125d43e5cd402a08735075fd (patch) | |
tree | d3ff43f11d08e02afa3ffdb1521aa0cea034ec6b /src | |
parent | 3dd1208c63b69b099b718be77457852c40692ed3 (diff) | |
download | bdl-e40b04daf942ae01125d43e5cd402a08735075fd.tar.gz bdl-e40b04daf942ae01125d43e5cd402a08735075fd.zip |
Consolidate semantic analyzer functions
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 457 |
1 files changed, 65 insertions, 392 deletions
@@ -8,7 +8,7 @@ | |||
8 | #include "vm.c" | 8 | #include "vm.c" |
9 | 9 | ||
10 | // TODO: unions | 10 | // TODO: unions |
11 | // TODO: match deconstruct structs | 11 | // TODO: match deconstruct enums |
12 | // TODO: arrays and pointers | 12 | // TODO: arrays and pointers |
13 | 13 | ||
14 | typedef enum ExecMode { | 14 | typedef enum ExecMode { |
@@ -52,12 +52,6 @@ Str sym_kind_str[] = { | |||
52 | 52 | ||
53 | typedef Str Type; | 53 | typedef Str Type; |
54 | 54 | ||
55 | typedef struct Symbol { | ||
56 | SymbolKind kind; | ||
57 | Str name; | ||
58 | struct SymbolMap *fields; | ||
59 | } Symbol; | ||
60 | |||
61 | typedef struct Fun { | 55 | typedef struct Fun { |
62 | Str name; | 56 | Str name; |
63 | Str param_type; | 57 | Str param_type; |
@@ -75,21 +69,14 @@ typedef struct Struct { | |||
75 | Node *val; | 69 | Node *val; |
76 | } Struct; | 70 | } Struct; |
77 | 71 | ||
78 | MAPDEF(SymbolMap, symmap, Str, Symbol, str_hash, str_eq) | ||
79 | MAPDEF(TypeMap, typemap, Str, Type, str_hash, str_eq) | 72 | MAPDEF(TypeMap, typemap, Str, Type, str_hash, str_eq) |
80 | MAPDEF(FunMap, funmap, Str, Fun, str_hash, str_eq) | 73 | MAPDEF(FunMap, funmap, Str, Fun, str_hash, str_eq) |
81 | MAPDEF(EnumMap, enummap, Str, Enum, str_hash, str_eq) | 74 | MAPDEF(EnumMap, enummap, Str, Enum, str_hash, str_eq) |
82 | MAPDEF(StructMap, structmap, Str, Struct, str_hash, str_eq) | 75 | MAPDEF(StructMap, structmap, Str, Struct, str_hash, str_eq) |
83 | 76 | ||
84 | typedef struct Scope { | ||
85 | sz id; | ||
86 | sz depth; | ||
87 | SymbolMap *symbols; | ||
88 | struct Scope *parent; | ||
89 | } Scope; | ||
90 | |||
91 | typedef struct TypeScope { | 77 | typedef struct TypeScope { |
92 | sz id; | 78 | sz id; |
79 | sz depth; | ||
93 | Str name; | 80 | Str name; |
94 | TypeMap *types; | 81 | TypeMap *types; |
95 | FunMap *funcs; | 82 | FunMap *funcs; |
@@ -102,45 +89,21 @@ typedef struct Analyzer { | |||
102 | Arena *storage; | 89 | Arena *storage; |
103 | Str file_name; | 90 | Str file_name; |
104 | sz typescope_gen; | 91 | sz typescope_gen; |
105 | sz scope_gen; | ||
106 | Scope **scopes; | ||
107 | TypeScope **types; | 92 | TypeScope **types; |
108 | StrSet *numeric_types; | 93 | StrSet *numeric_types; |
109 | StrSet *integer_types; | 94 | StrSet *integer_types; |
110 | } Analyzer; | 95 | } Analyzer; |
111 | 96 | ||
112 | Scope * | ||
113 | scope_alloc(Analyzer *a, Scope *parent) { | ||
114 | bool is_root = parent == NULL; | ||
115 | Scope *scope = arena_calloc(sizeof(Scope), a->storage); | ||
116 | scope->id = a->scope_gen++; | ||
117 | scope->parent = parent; | ||
118 | scope->depth = is_root ? 0 : parent->depth + 1; | ||
119 | array_push(a->scopes, scope, a->storage); | ||
120 | return scope; | ||
121 | } | ||
122 | |||
123 | TypeScope * | 97 | TypeScope * |
124 | typescope_alloc(Analyzer *a, TypeScope *parent) { | 98 | typescope_alloc(Analyzer *a, TypeScope *parent) { |
125 | TypeScope *scope = arena_calloc(sizeof(TypeScope), a->storage); | 99 | TypeScope *scope = arena_calloc(sizeof(TypeScope), a->storage); |
126 | scope->parent = parent; | 100 | scope->parent = parent; |
127 | scope->id = a->typescope_gen++; | 101 | scope->id = a->typescope_gen++; |
102 | scope->depth = parent == NULL ? 0 : parent->depth + 1; | ||
128 | array_push(a->types, scope, a->storage); | 103 | array_push(a->types, scope, a->storage); |
129 | return scope; | 104 | return scope; |
130 | } | 105 | } |
131 | 106 | ||
132 | SymbolMap * | ||
133 | find_symbol(Scope *scope, Str symbol) { | ||
134 | while (scope != NULL) { | ||
135 | SymbolMap *val = symmap_lookup(&scope->symbols, symbol); | ||
136 | if (val != NULL) { | ||
137 | return val; | ||
138 | } | ||
139 | scope = scope->parent; | ||
140 | } | ||
141 | return NULL; | ||
142 | } | ||
143 | |||
144 | TypeMap * | 107 | TypeMap * |
145 | find_type(TypeScope *scope, Str type) { | 108 | find_type(TypeScope *scope, Str type) { |
146 | while (scope != NULL) { | 109 | while (scope != NULL) { |
@@ -200,60 +163,6 @@ find_struct(TypeScope *scope, Str type) { | |||
200 | } | 163 | } |
201 | 164 | ||
202 | void | 165 | void |
203 | graph_scope(Scope *scope, Arena a) { | ||
204 | if (!scope->symbols) { | ||
205 | return; | ||
206 | } | ||
207 | SymbolMapIter iter = symmap_iterator(scope->symbols, &a); | ||
208 | SymbolMap *sym = symmap_next(&iter, &a); | ||
209 | print( | ||
210 | "%d[shape=\"none\" label=<<TABLE ALIGN=\"left\" STYLE=\"rounded\" " | ||
211 | "BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"6\" " | ||
212 | "COLUMNS=\"*\">" | ||
213 | "<TR style=\"rounded\"><TD COLSPAN=\"3\">ID: %d</TD></TR>", | ||
214 | scope->id, scope->id); | ||
215 | print( | ||
216 | "<TR >" | ||
217 | "<TD ALIGN=\"left\" > NAME </TD>" | ||
218 | "<TD ALIGN=\"left\" > KIND </TD>" | ||
219 | "<TD ALIGN=\"left\" > TYPE </TD>" | ||
220 | "</TR>"); | ||
221 | while (sym) { | ||
222 | Str type_name = cstr("nil"); | ||
223 | print( | ||
224 | "<TR>" | ||
225 | "<TD ALIGN=\"left\"> %s </TD>" | ||
226 | "<TD ALIGN=\"left\"> %s </TD>" | ||
227 | "<TD ALIGN=\"left\"> %s </TD>" | ||
228 | "</TR>", | ||
229 | sym->val.name, sym_kind_str[sym->val.kind], type_name); | ||
230 | SymbolMapIter field_iter = symmap_iterator(sym->val.fields, &a); | ||
231 | SymbolMap *field = symmap_next(&field_iter, &a); | ||
232 | while (field) { | ||
233 | print( | ||
234 | "<TR>" | ||
235 | "<TD ALIGN=\"left\"> %s.%s </TD>" | ||
236 | "<TD ALIGN=\"left\"> %s " | ||
237 | "</TD>" | ||
238 | "</TR>", | ||
239 | sym->val.name, field->val.name, sym_kind_str[field->val.kind]); | ||
240 | field = symmap_next(&field_iter, &a); | ||
241 | } | ||
242 | sym = symmap_next(&iter, &a); | ||
243 | } | ||
244 | println("</TABLE>>];"); | ||
245 | sz this_id = scope->id; | ||
246 | while (scope->parent) { | ||
247 | if (scope->parent->symbols) { | ||
248 | println("%d:n->%d:s;", this_id, scope->parent->id); | ||
249 | break; | ||
250 | } else { | ||
251 | scope = scope->parent; | ||
252 | } | ||
253 | } | ||
254 | } | ||
255 | |||
256 | void | ||
257 | graph_typescope(TypeScope *scope, Arena a) { | 166 | graph_typescope(TypeScope *scope, Arena a) { |
258 | if (!scope->types) { | 167 | if (!scope->types) { |
259 | return; | 168 | return; |
@@ -335,27 +244,6 @@ graph_functions(TypeScope *scope, Arena a) { | |||
335 | } | 244 | } |
336 | 245 | ||
337 | void | 246 | void |
338 | graph_symbols(Scope **scopes, Arena a) { | ||
339 | if (scopes == NULL) return; | ||
340 | println("digraph symbols {"); | ||
341 | println("rankdir=BT;"); | ||
342 | println("ranksep=\"0.95 equally\";"); | ||
343 | println("nodesep=\"0.5 equally\";"); | ||
344 | println("overlap=scale;"); | ||
345 | println("bgcolor=\"transparent\";"); | ||
346 | for (sz i = 0; i < array_size(scopes); i++) { | ||
347 | Scope *scope = scopes[i]; | ||
348 | if (!scope) { | ||
349 | continue; | ||
350 | } | ||
351 | println("subgraph %d {", i); | ||
352 | graph_scope(scope, a); | ||
353 | println("}"); | ||
354 | } | ||
355 | println("}"); | ||
356 | } | ||
357 | |||
358 | void | ||
359 | graph_types(TypeScope **scopes, Arena a) { | 247 | graph_types(TypeScope **scopes, Arena a) { |
360 | if (scopes == NULL) return; | 248 | if (scopes == NULL) return; |
361 | println("digraph types {"); | 249 | println("digraph types {"); |
@@ -386,7 +274,6 @@ Type type_inference(Analyzer *a, Node *node, TypeScope *scope); | |||
386 | 274 | ||
387 | void | 275 | void |
388 | typecheck_field(Analyzer *a, Node *node, TypeScope *scope, Str symbol) { | 276 | typecheck_field(Analyzer *a, Node *node, TypeScope *scope, Str symbol) { |
389 | // TODO: ensure the tables are filled properly. | ||
390 | if (node->field_type->kind == NODE_COMPOUND_TYPE) { | 277 | if (node->field_type->kind == NODE_COMPOUND_TYPE) { |
391 | Str field_name = str_concat(symbol, cstr("."), a->storage); | 278 | Str field_name = str_concat(symbol, cstr("."), a->storage); |
392 | field_name = str_concat(field_name, node->value.str, a->storage); | 279 | field_name = str_concat(field_name, node->value.str, a->storage); |
@@ -476,7 +363,6 @@ typecheck_returns(Analyzer *a, Node *node, Str expected) { | |||
476 | if (!node) { | 363 | if (!node) { |
477 | return; | 364 | return; |
478 | } | 365 | } |
479 | |||
480 | // Traverse the tree again. | 366 | // Traverse the tree again. |
481 | switch (node->kind) { | 367 | switch (node->kind) { |
482 | case NODE_COND: | 368 | case NODE_COND: |
@@ -556,6 +442,14 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
556 | case NODE_LET: { | 442 | case NODE_LET: { |
557 | node->type = cstr("nil"); | 443 | node->type = cstr("nil"); |
558 | Str symbol = node->var_name->value.str; | 444 | Str symbol = node->var_name->value.str; |
445 | if (typemap_lookup(&scope->types, symbol)) { | ||
446 | eprintln( | ||
447 | "%s:%d:%d: error: symbol '%s' already exists in current " | ||
448 | "scope ", | ||
449 | a->file_name, node->var_name->line, node->var_name->col, | ||
450 | symbol); | ||
451 | return cstr(""); | ||
452 | } | ||
559 | if (node->var_type) { | 453 | if (node->var_type) { |
560 | Str type_name = node->var_type->value.str; | 454 | Str type_name = node->var_type->value.str; |
561 | TypeMap *type = find_type(scope, type_name); | 455 | TypeMap *type = find_type(scope, type_name); |
@@ -620,7 +514,13 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
620 | case NODE_STRUCT: { | 514 | case NODE_STRUCT: { |
621 | node->type = cstr("nil"); | 515 | node->type = cstr("nil"); |
622 | Str symbol = node->value.str; | 516 | Str symbol = node->value.str; |
623 | // TODO: make sure it didn't exist before. | 517 | if (typemap_lookup(&scope->types, symbol) != NULL) { |
518 | eprintln( | ||
519 | "%s:%d:%d: error: struct '%s' already exists in current " | ||
520 | "scope", | ||
521 | a->file_name, node->line, node->col, symbol); | ||
522 | return cstr(""); | ||
523 | } | ||
624 | structmap_insert(&scope->structs, symbol, (Struct){.name = symbol}, | 524 | structmap_insert(&scope->structs, symbol, (Struct){.name = symbol}, |
625 | a->storage); | 525 | a->storage); |
626 | for (sz i = 0; i < array_size(node->struct_field); i++) { | 526 | for (sz i = 0; i < array_size(node->struct_field); i++) { |
@@ -633,7 +533,13 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
633 | case NODE_ENUM: { | 533 | case NODE_ENUM: { |
634 | node->type = cstr("nil"); | 534 | node->type = cstr("nil"); |
635 | Str symbol = node->value.str; | 535 | Str symbol = node->value.str; |
636 | // TODO: make sure it didn't exist before. | 536 | if (typemap_lookup(&scope->types, symbol) != NULL) { |
537 | eprintln( | ||
538 | "%s:%d:%d: error: enum '%s' already exists in current " | ||
539 | "scope", | ||
540 | a->file_name, node->line, node->col, symbol); | ||
541 | return cstr(""); | ||
542 | } | ||
637 | enummap_insert(&scope->enums, symbol, | 543 | enummap_insert(&scope->enums, symbol, |
638 | (Enum){ | 544 | (Enum){ |
639 | .name = symbol, | 545 | .name = symbol, |
@@ -871,6 +777,7 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
871 | node->type = type->val; | 777 | node->type = type->val; |
872 | return node->type; | 778 | return node->type; |
873 | } break; | 779 | } break; |
780 | case NODE_SYMBOL_IDX: | ||
874 | case NODE_SYMBOL: { | 781 | case NODE_SYMBOL: { |
875 | Str symbol = node->value.str; | 782 | Str symbol = node->value.str; |
876 | TypeMap *type = find_type(scope, symbol); | 783 | TypeMap *type = find_type(scope, symbol); |
@@ -975,7 +882,7 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
975 | if (!fun) { | 882 | if (!fun) { |
976 | eprintln( | 883 | eprintln( |
977 | "%s:%d:%d: error: function '%s' doesn't exist in current " | 884 | "%s:%d:%d: error: function '%s' doesn't exist in current " |
978 | " scope ", | 885 | "scope ", |
979 | a->file_name, node->line, node->col, symbol); | 886 | a->file_name, node->line, node->col, symbol); |
980 | return cstr(""); | 887 | return cstr(""); |
981 | } | 888 | } |
@@ -1030,24 +937,6 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
1030 | return node->type; | 937 | return node->type; |
1031 | } break; | 938 | } break; |
1032 | case NODE_FUN: { | 939 | case NODE_FUN: { |
1033 | // TODO: we may want to do this and register a special table with | ||
1034 | // function and formals... | ||
1035 | // if (scope->parent != NULL) { | ||
1036 | // // Str symbol = node->func_name->value.str; | ||
1037 | // // if (symmap_lookup(&scope->symbols, symbol) != NULL) { | ||
1038 | // // eprintln( | ||
1039 | // // "%s:%d:%d: error: symbol '%s' already exists in " | ||
1040 | // // "current " | ||
1041 | // // "scope", | ||
1042 | // // a->file_name, node->func_name->line, | ||
1043 | // // node->func_name->col, symbol); | ||
1044 | // // return; | ||
1045 | // // } | ||
1046 | // // symmap_insert(&scope->symbols, symbol, | ||
1047 | // // (Symbol){.kind = SYM_FUN, .name = symbol}, | ||
1048 | // // a->storage); | ||
1049 | // } | ||
1050 | |||
1051 | node->type = cstr("nil"); | 940 | node->type = cstr("nil"); |
1052 | TypeScope *prev_scope = scope; | 941 | TypeScope *prev_scope = scope; |
1053 | scope = typescope_alloc(a, scope); | 942 | scope = typescope_alloc(a, scope); |
@@ -1085,7 +974,18 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
1085 | node->fun_return = ret_type; | 974 | node->fun_return = ret_type; |
1086 | 975 | ||
1087 | Str symbol = node->func_name->value.str; | 976 | Str symbol = node->func_name->value.str; |
1088 | // TODO: check it was not defined before. | 977 | if (prev_scope->parent != NULL) { |
978 | if (typemap_lookup(&prev_scope->types, symbol)) { | ||
979 | eprintln( | ||
980 | "%s:%d:%d: error: function '%s' already defined in " | ||
981 | "current " | ||
982 | "scope ", | ||
983 | a->file_name, node->var_name->line, node->var_name->col, | ||
984 | symbol); | ||
985 | return cstr(""); | ||
986 | } | ||
987 | typemap_insert(&prev_scope->types, symbol, symbol, a->storage); | ||
988 | } | ||
1089 | scope->name = symbol; | 989 | scope->name = symbol; |
1090 | funmap_insert(&prev_scope->funcs, symbol, | 990 | funmap_insert(&prev_scope->funcs, symbol, |
1091 | (Fun){.name = symbol, | 991 | (Fun){.name = symbol, |
@@ -1131,226 +1031,10 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) { | |||
1131 | } | 1031 | } |
1132 | 1032 | ||
1133 | void | 1033 | void |
1134 | analyzer_symbols(Analyzer *a, Node *node, Scope *scope) { | ||
1135 | assert(a); | ||
1136 | assert(scope); | ||
1137 | if (!node) { | ||
1138 | return; | ||
1139 | } | ||
1140 | node->scope = scope; | ||
1141 | switch (node->kind) { | ||
1142 | case NODE_FUN: { | ||
1143 | if (scope->depth != 0) { | ||
1144 | Str symbol = node->func_name->value.str; | ||
1145 | if (symmap_lookup(&scope->symbols, symbol) != NULL) { | ||
1146 | eprintln( | ||
1147 | "%s:%d:%d: error: symbol '%s' already exists in " | ||
1148 | "current " | ||
1149 | "scope", | ||
1150 | a->file_name, node->func_name->line, | ||
1151 | node->func_name->col, symbol); | ||
1152 | return; | ||
1153 | } | ||
1154 | symmap_insert(&scope->symbols, symbol, | ||
1155 | (Symbol){.kind = SYM_FUN, .name = symbol}, | ||
1156 | a->storage); | ||
1157 | } | ||
1158 | |||
1159 | scope = scope_alloc(a, scope); | ||
1160 | node->scope = scope; | ||
1161 | for (sz i = 0; i < array_size(node->func_params); i++) { | ||
1162 | Node *param = node->func_params[i]; | ||
1163 | Str param_name = param->param_name->value.str; | ||
1164 | symmap_insert(&scope->symbols, param_name, | ||
1165 | (Symbol){.kind = SYM_PARAM, .name = param_name}, | ||
1166 | a->storage); | ||
1167 | } | ||
1168 | if (node->func_body->kind == NODE_BLOCK) { | ||
1169 | node = node->func_body; | ||
1170 | for (sz i = 0; i < array_size(node->elements); i++) { | ||
1171 | Node *expr = node->elements[i]; | ||
1172 | analyzer_symbols(a, expr, scope); | ||
1173 | } | ||
1174 | } else { | ||
1175 | analyzer_symbols(a, node->func_body, scope); | ||
1176 | } | ||
1177 | } break; | ||
1178 | case NODE_COND: | ||
1179 | case NODE_MATCH: { | ||
1180 | if (node->match_expr) { | ||
1181 | analyzer_symbols(a, node->match_expr, scope); | ||
1182 | } | ||
1183 | for (sz i = 0; i < array_size(node->match_cases); i++) { | ||
1184 | Node *expr = node->match_cases[i]; | ||
1185 | analyzer_symbols(a, expr, scope); | ||
1186 | } | ||
1187 | } break; | ||
1188 | case NODE_RETURN: { | ||
1189 | for (sz i = 0; i < array_size(node->elements); i++) { | ||
1190 | Node *expr = node->elements[i]; | ||
1191 | analyzer_symbols(a, expr, scope); | ||
1192 | } | ||
1193 | } break; | ||
1194 | // TODO: | ||
1195 | // case NODE_STRUCT_LIT: | ||
1196 | case NODE_BLOCK: { | ||
1197 | Scope *next = scope_alloc(a, scope); | ||
1198 | node->scope = scope; | ||
1199 | for (sz i = 0; i < array_size(node->elements); i++) { | ||
1200 | Node *expr = node->elements[i]; | ||
1201 | analyzer_symbols(a, expr, next); | ||
1202 | } | ||
1203 | } break; | ||
1204 | case NODE_STRUCT: | ||
1205 | case NODE_ENUM: { | ||
1206 | Str symbol = node->value.str; | ||
1207 | if (symmap_lookup(&scope->symbols, symbol) != NULL) { | ||
1208 | eprintln( | ||
1209 | "%s:%d:%d: error: symbol '%s' already exists in current " | ||
1210 | " scope ", | ||
1211 | a->file_name, node->line, node->col, symbol); | ||
1212 | } | ||
1213 | SymbolMap *map = symmap_insert( | ||
1214 | &scope->symbols, symbol, | ||
1215 | (Symbol){ | ||
1216 | .kind = node->kind == NODE_ENUM ? SYM_ENUM : SYM_STRUCT, | ||
1217 | .name = symbol}, | ||
1218 | a->storage); | ||
1219 | // TODO: symcheck the value expression? | ||
1220 | for (sz i = 0; i < array_size(node->struct_field); i++) { | ||
1221 | Node *field = node->struct_field[i]; | ||
1222 | Str field_name = field->value.str; | ||
1223 | if (symmap_lookup(&map->val.fields, field_name) != NULL) { | ||
1224 | eprintln( | ||
1225 | "%s:%d:%d: error: struct field '%s.%s' already exists", | ||
1226 | a->file_name, field->line, field->col, symbol, | ||
1227 | field_name); | ||
1228 | return; | ||
1229 | } | ||
1230 | Symbol s = | ||
1231 | (Symbol){.kind = node->kind == NODE_ENUM ? SYM_ENUM_FIELD | ||
1232 | : SYM_STRUCT_FIELD, | ||
1233 | .name = field_name}; | ||
1234 | symmap_insert(&map->val.fields, field_name, s, a->storage); | ||
1235 | } | ||
1236 | } break; | ||
1237 | case NODE_CASE_MATCH: | ||
1238 | case NODE_CASE_COND: { | ||
1239 | analyzer_symbols(a, node->case_value, scope); | ||
1240 | if (node->case_expr) { | ||
1241 | if (node->case_expr->kind != NODE_BLOCK) { | ||
1242 | scope = scope_alloc(a, scope); | ||
1243 | } | ||
1244 | analyzer_symbols(a, node->case_expr, scope); | ||
1245 | } | ||
1246 | } break; | ||
1247 | case NODE_IF: { | ||
1248 | analyzer_symbols(a, node->cond_if, scope); | ||
1249 | if (node->cond_expr) { | ||
1250 | if (node->cond_expr->kind == NODE_BLOCK) { | ||
1251 | analyzer_symbols(a, node->cond_expr, scope); | ||
1252 | } else { | ||
1253 | Scope *next = scope_alloc(a, scope); | ||
1254 | analyzer_symbols(a, node->cond_expr, next); | ||
1255 | } | ||
1256 | } | ||
1257 | if (node->cond_else) { | ||
1258 | if (node->cond_else->kind == NODE_BLOCK) { | ||
1259 | analyzer_symbols(a, node->cond_else, scope); | ||
1260 | } else { | ||
1261 | Scope *next = scope_alloc(a, scope); | ||
1262 | analyzer_symbols(a, node->cond_else, next); | ||
1263 | } | ||
1264 | } | ||
1265 | } break; | ||
1266 | case NODE_WHILE: { | ||
1267 | analyzer_symbols(a, node->while_cond, scope); | ||
1268 | if (node->while_expr->kind != NODE_BLOCK) { | ||
1269 | scope = scope_alloc(a, scope); | ||
1270 | } | ||
1271 | analyzer_symbols(a, node->while_expr, scope); | ||
1272 | } break; | ||
1273 | case NODE_FUNCALL: { | ||
1274 | Str symbol = node->value.str; | ||
1275 | if (find_symbol(scope, symbol) == NULL) { | ||
1276 | eprintln( | ||
1277 | "%s:%d:%d: error: symbol '%s' doesn't exists in current " | ||
1278 | " scope ", | ||
1279 | a->file_name, node->line, node->col, symbol); | ||
1280 | return; | ||
1281 | } | ||
1282 | for (sz i = 0; i < array_size(node->elements); i++) { | ||
1283 | Node *expr = node->elements[i]; | ||
1284 | analyzer_symbols(a, expr, scope); | ||
1285 | } | ||
1286 | } break; | ||
1287 | case NODE_SYMBOL_IDX: | ||
1288 | case NODE_SYMBOL: { | ||
1289 | Str symbol = node->value.str; | ||
1290 | if (find_symbol(scope, symbol) == NULL) { | ||
1291 | eprintln( | ||
1292 | "%s:%d:%d: error: symbol '%s' doesn't exists in current " | ||
1293 | " scope ", | ||
1294 | a->file_name, node->line, node->col, symbol); | ||
1295 | return; | ||
1296 | } | ||
1297 | // TODO: Resolve symbol chains. | ||
1298 | } break; | ||
1299 | case NODE_SET: { | ||
1300 | analyzer_symbols(a, node->var_name, scope); | ||
1301 | analyzer_symbols(a, node->var_val, scope); | ||
1302 | } break; | ||
1303 | case NODE_LET: { | ||
1304 | // Check the value first to avoid recursive symbol usage. | ||
1305 | analyzer_symbols(a, node->var_val, scope); | ||
1306 | |||
1307 | Str symbol = node->var_name->value.str; | ||
1308 | if (symmap_lookup(&scope->symbols, symbol) != NULL) { | ||
1309 | eprintln( | ||
1310 | "%s:%d:%d: error: symbol '%s' already exists in current " | ||
1311 | " scope ", | ||
1312 | a->file_name, node->var_name->line, node->var_name->col, | ||
1313 | symbol); | ||
1314 | return; | ||
1315 | } | ||
1316 | symmap_insert(&scope->symbols, symbol, | ||
1317 | (Symbol){.kind = SYM_VAR, .name = symbol}, | ||
1318 | a->storage); | ||
1319 | } break; | ||
1320 | // Binary ops | ||
1321 | case NODE_ADD: | ||
1322 | case NODE_SUB: | ||
1323 | case NODE_DIV: | ||
1324 | case NODE_MUL: | ||
1325 | case NODE_MOD: | ||
1326 | case NODE_NOT: | ||
1327 | case NODE_AND: | ||
1328 | case NODE_OR: | ||
1329 | case NODE_EQ: | ||
1330 | case NODE_NEQ: | ||
1331 | case NODE_LT: | ||
1332 | case NODE_GT: | ||
1333 | case NODE_LE: | ||
1334 | case NODE_GE: | ||
1335 | case NODE_BITNOT: | ||
1336 | case NODE_BITAND: | ||
1337 | case NODE_BITOR: | ||
1338 | case NODE_BITLSHIFT: | ||
1339 | case NODE_BITRSHIFT: { | ||
1340 | analyzer_symbols(a, node->left, scope); | ||
1341 | analyzer_symbols(a, node->right, scope); | ||
1342 | } break; | ||
1343 | default: break; | ||
1344 | } | ||
1345 | } | ||
1346 | |||
1347 | void | ||
1348 | symbolic_analysis(Analyzer *a, Parser *parser) { | 1034 | symbolic_analysis(Analyzer *a, Parser *parser) { |
1349 | Scope *scope = scope_alloc(a, NULL); | ||
1350 | TypeScope *types = typescope_alloc(a, NULL); | 1035 | TypeScope *types = typescope_alloc(a, NULL); |
1351 | assert(a); | 1036 | assert(a); |
1352 | assert(parser); | 1037 | assert(parser); |
1353 | assert(scope); | ||
1354 | 1038 | ||
1355 | // Fill builtin tables. | 1039 | // Fill builtin tables. |
1356 | Str builtin_functions[] = { | 1040 | Str builtin_functions[] = { |
@@ -1359,8 +1043,12 @@ symbolic_analysis(Analyzer *a, Parser *parser) { | |||
1359 | }; | 1043 | }; |
1360 | for (sz i = 0; i < LEN(builtin_functions); i++) { | 1044 | for (sz i = 0; i < LEN(builtin_functions); i++) { |
1361 | Str symbol = builtin_functions[i]; | 1045 | Str symbol = builtin_functions[i]; |
1362 | Symbol sym = (Symbol){.kind = SYM_BUILTIN, .name = symbol}; | 1046 | typemap_insert(&types->types, symbol, symbol, a->storage); |
1363 | symmap_insert(&scope->symbols, symbol, sym, a->storage); | 1047 | funmap_insert(&types->funcs, symbol, |
1048 | (Fun){.name = symbol, | ||
1049 | .param_type = cstr("..."), | ||
1050 | .return_type = cstr("nil")}, | ||
1051 | a->storage); | ||
1364 | } | 1052 | } |
1365 | Type builtin_types[] = { | 1053 | Type builtin_types[] = { |
1366 | cstr("u8"), cstr("s8"), cstr("u16"), cstr("s16"), | 1054 | cstr("u8"), cstr("s8"), cstr("u16"), cstr("s16"), |
@@ -1389,35 +1077,27 @@ symbolic_analysis(Analyzer *a, Parser *parser) { | |||
1389 | Type type = integer_types[i]; | 1077 | Type type = integer_types[i]; |
1390 | strset_insert(&a->integer_types, type, a->storage); | 1078 | strset_insert(&a->integer_types, type, a->storage); |
1391 | } | 1079 | } |
1392 | |||
1393 | // Find top level function declarations. | 1080 | // Find top level function declarations. |
1394 | for (sz i = 0; i < array_size(parser->nodes); i++) { | 1081 | for (sz i = 0; i < array_size(parser->nodes); i++) { |
1395 | Node *root = parser->nodes[i]; | 1082 | Node *root = parser->nodes[i]; |
1396 | if (root->kind == NODE_FUN) { | 1083 | if (root->kind == NODE_FUN) { |
1397 | Str symbol = root->func_name->value.str; | 1084 | Str symbol = root->func_name->value.str; |
1398 | if (symmap_lookup(&scope->symbols, symbol) != NULL) { | 1085 | if (typemap_lookup(&types->types, symbol)) { |
1399 | eprintln( | 1086 | eprintln( |
1400 | "%s:%d:%d: error: symbol '%s' already exists in current " | 1087 | "%s:%d:%d: error: function '%s' already defined in " |
1401 | "scope", | 1088 | "current " |
1402 | a->file_name, root->func_name->line, root->func_name->col, | 1089 | "scope ", |
1090 | a->file_name, root->var_name->line, root->var_name->col, | ||
1403 | symbol); | 1091 | symbol); |
1404 | } | 1092 | } |
1405 | symmap_insert(&scope->symbols, symbol, | 1093 | typemap_insert(&types->types, symbol, symbol, a->storage); |
1406 | (Symbol){.kind = SYM_FUN, .name = symbol}, | ||
1407 | a->storage); | ||
1408 | } | 1094 | } |
1409 | } | 1095 | } |
1410 | |||
1411 | // Recursively fill symbol tables. | 1096 | // Recursively fill symbol tables. |
1412 | for (sz i = 0; i < array_size(parser->nodes); i++) { | 1097 | for (sz i = 0; i < array_size(parser->nodes); i++) { |
1413 | Node *root = parser->nodes[i]; | 1098 | Node *root = parser->nodes[i]; |
1414 | type_inference(a, root, types); | 1099 | type_inference(a, root, types); |
1415 | analyzer_symbols(a, root, scope); | ||
1416 | } | 1100 | } |
1417 | // for (sz i = 0; i < array_size(parser->nodes); i++) { | ||
1418 | // Node *root = parser->nodes[i]; | ||
1419 | // analyzer_typecheck(a, root, scope); | ||
1420 | // } | ||
1421 | } | 1101 | } |
1422 | 1102 | ||
1423 | void | 1103 | void |
@@ -1502,7 +1182,7 @@ process_file(Str path) { | |||
1502 | } | 1182 | } |
1503 | 1183 | ||
1504 | #if DEBUG == 1 | 1184 | #if DEBUG == 1 |
1505 | println("======== enums ========"); | 1185 | println("========== enums =========="); |
1506 | for (sz i = 0; i < array_size(analyzer.types); i++) { | 1186 | for (sz i = 0; i < array_size(analyzer.types); i++) { |
1507 | Arena scratch = lexer_arena; | 1187 | Arena scratch = lexer_arena; |
1508 | TypeScope *scope = analyzer.types[i]; | 1188 | TypeScope *scope = analyzer.types[i]; |
@@ -1514,7 +1194,7 @@ process_file(Str path) { | |||
1514 | m = enummap_next(&iter, &scratch); | 1194 | m = enummap_next(&iter, &scratch); |
1515 | } | 1195 | } |
1516 | } | 1196 | } |
1517 | println("======== structs ========"); | 1197 | println("========= structs ========="); |
1518 | for (sz i = 0; i < array_size(analyzer.types); i++) { | 1198 | for (sz i = 0; i < array_size(analyzer.types); i++) { |
1519 | Arena scratch = lexer_arena; | 1199 | Arena scratch = lexer_arena; |
1520 | TypeScope *scope = analyzer.types[i]; | 1200 | TypeScope *scope = analyzer.types[i]; |
@@ -1538,25 +1218,18 @@ process_file(Str path) { | |||
1538 | m = funmap_next(&iter, &scratch); | 1218 | m = funmap_next(&iter, &scratch); |
1539 | } | 1219 | } |
1540 | } | 1220 | } |
1541 | // println("======== symbols ========"); | 1221 | println("========== types =========="); |
1542 | // SymbolMapIter iter = symmap_iterator(scope->symbols, &scratch); | 1222 | for (sz i = 0; i < array_size(analyzer.types); i++) { |
1543 | // SymbolMap *sym = symmap_next(&iter, &scratch); | 1223 | Arena scratch = lexer_arena; |
1544 | // while (sym) { | 1224 | TypeScope *scope = analyzer.types[i]; |
1545 | // println("%s: SCOPE: %d DEPTH: %d\t%s %s", path, scope->id, | 1225 | TypeMapIter iter = typemap_iterator(scope->types, &scratch); |
1546 | // scope->depth, sym_kind_str[sym->val.kind], | 1226 | TypeMap *m = typemap_next(&iter, &scratch); |
1547 | // sym->val.name); | 1227 | while (m) { |
1548 | // SymbolMapIter field_iter = | 1228 | println("scope: %x{2} -- %s: type: %s: %s", scope->id, path, m->key, |
1549 | // symmap_iterator(sym->val.fields, &scratch); | 1229 | m->val); |
1550 | // SymbolMap *field = symmap_next(&field_iter, &scratch); | 1230 | m = typemap_next(&iter, &scratch); |
1551 | // while (field) { | 1231 | } |
1552 | // println("%s: SCOPE: %d DEPTH: %d\t%s %s.%s", path, scope->id, | 1232 | } |
1553 | // scope->depth, sym_kind_str[field->val.kind], | ||
1554 | // sym->val.name, field->val.name); | ||
1555 | // field = symmap_next(&field_iter, &scratch); | ||
1556 | // } | ||
1557 | // sym = symmap_next(&iter, &lexer_arena); | ||
1558 | // } | ||
1559 | // } | ||
1560 | #endif | 1233 | #endif |
1561 | 1234 | ||
1562 | // TODO: Type checking. | 1235 | // TODO: Type checking. |