diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-21 15:59:32 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-21 15:59:32 +0200 |
commit | 59b9c661cbdf125b0a17f8f955158a1f77f163f8 (patch) | |
tree | 36c5b0abe4bb8202f6b23c30759706cd1c0f8a49 /src | |
parent | d336498c7cf397de496fa46fccc31883480ecb1d (diff) | |
download | bdl-59b9c661cbdf125b0a17f8f955158a1f77f163f8.tar.gz bdl-59b9c661cbdf125b0a17f8f955158a1f77f163f8.zip |
Add semantic checking for enum constructs
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 56 | ||||
-rw-r--r-- | src/parser.c | 5 |
2 files changed, 50 insertions, 11 deletions
@@ -28,16 +28,21 @@ typedef enum { | |||
28 | SYM_FUN, | 28 | SYM_FUN, |
29 | SYM_VAR, | 29 | SYM_VAR, |
30 | SYM_PARAM, | 30 | SYM_PARAM, |
31 | SYM_ENUM, | ||
32 | SYM_ENUM_FIELD, | ||
31 | } SymbolKind; | 33 | } SymbolKind; |
32 | 34 | ||
33 | Str sym_kind_str[] = { | 35 | Str sym_kind_str[] = { |
34 | [SYM_UNKNOWN] = cstr("UNKNOWN "), [SYM_BUILTIN] = cstr("BUILTIN "), | 36 | [SYM_UNKNOWN] = cstr("UNKNOWN "), [SYM_BUILTIN] = cstr("BUILTIN "), |
35 | [SYM_FUN] = cstr("FUNCTION "), [SYM_VAR] = cstr("VARIABLE "), | 37 | [SYM_FUN] = cstr("FUNCTION "), [SYM_VAR] = cstr("VARIABLE "), |
36 | [SYM_PARAM] = cstr("PARAMETER "), | 38 | [SYM_PARAM] = cstr("PARAMETER "), [SYM_ENUM] = cstr("ENUM "), |
39 | [SYM_ENUM_FIELD] = cstr("ENUM FIELD"), | ||
37 | }; | 40 | }; |
38 | 41 | ||
39 | typedef struct Symbol { | 42 | typedef struct Symbol { |
40 | SymbolKind kind; | 43 | SymbolKind kind; |
44 | Str name; | ||
45 | struct Symbol *fields; | ||
41 | } Symbol; | 46 | } Symbol; |
42 | 47 | ||
43 | MAPDEF(SymbolMap, symmap, Str, Symbol, str_hash, str_eq) | 48 | MAPDEF(SymbolMap, symmap, Str, Symbol, str_hash, str_eq) |
@@ -100,15 +105,18 @@ analyzer_symbols(Analyzer *a, Node *node, Scope *scope) { | |||
100 | node->func_name->col, symbol); | 105 | node->func_name->col, symbol); |
101 | } | 106 | } |
102 | symmap_insert(&scope->symbols, symbol, | 107 | symmap_insert(&scope->symbols, symbol, |
103 | (Symbol){.kind = SYM_FUN}, a->storage); | 108 | (Symbol){.kind = SYM_FUN, .name = symbol}, |
109 | a->storage); | ||
104 | } | 110 | } |
105 | 111 | ||
106 | scope = scope_alloc(a, scope); | 112 | scope = scope_alloc(a, scope); |
107 | node->scope = scope; | 113 | node->scope = scope; |
108 | for (sz i = 0; i < array_size(node->func_params); i++) { | 114 | for (sz i = 0; i < array_size(node->func_params); i++) { |
109 | Node *param = node->func_params[i]; | 115 | Node *param = node->func_params[i]; |
110 | symmap_insert(&scope->symbols, param->param_name->value.str, | 116 | Str param_name = param->param_name->value.str; |
111 | (Symbol){.kind = SYM_PARAM}, a->storage); | 117 | symmap_insert(&scope->symbols, param_name, |
118 | (Symbol){.kind = SYM_PARAM, .name = param_name}, | ||
119 | a->storage); | ||
112 | } | 120 | } |
113 | if (node->func_body->kind == NODE_BLOCK) { | 121 | if (node->func_body->kind == NODE_BLOCK) { |
114 | node = node->func_body; | 122 | node = node->func_body; |
@@ -150,6 +158,27 @@ analyzer_symbols(Analyzer *a, Node *node, Scope *scope) { | |||
150 | analyzer_symbols(a, expr, next); | 158 | analyzer_symbols(a, expr, next); |
151 | } | 159 | } |
152 | } break; | 160 | } break; |
161 | case NODE_ENUM: { | ||
162 | Str symbol = node->value.str; | ||
163 | if (symmap_lookup(&scope->symbols, symbol) != NULL) { | ||
164 | eprintln( | ||
165 | "%s:%d:%d: error: symbol '%s' already exists in current " | ||
166 | " scope ", | ||
167 | a->file_name, node->line, node->col, symbol); | ||
168 | } | ||
169 | SymbolMap *map = symmap_insert( | ||
170 | &scope->symbols, symbol, | ||
171 | (Symbol){.kind = SYM_ENUM, .name = symbol}, a->storage); | ||
172 | // TODO: symcheck the value expression? | ||
173 | for (sz i = 0; i < array_size(node->struct_field); i++) { | ||
174 | Node *field = node->struct_field[i]; | ||
175 | Str field_name = field->field_name->value.str; | ||
176 | field_name = str_concat(cstr("."), field_name, a->storage); | ||
177 | field_name = str_concat(symbol, field_name, a->storage); | ||
178 | Symbol s = (Symbol){.kind = SYM_ENUM_FIELD, .name = field_name}; | ||
179 | array_push(map->val.fields, s, a->storage); | ||
180 | } | ||
181 | } break; | ||
153 | case NODE_CASE: { | 182 | case NODE_CASE: { |
154 | analyzer_symbols(a, node->case_value, scope); | 183 | analyzer_symbols(a, node->case_value, scope); |
155 | if (node->case_expr) { | 184 | if (node->case_expr) { |
@@ -225,7 +254,8 @@ analyzer_symbols(Analyzer *a, Node *node, Scope *scope) { | |||
225 | a->file_name, node->var_name->line, node->var_name->col, | 254 | a->file_name, node->var_name->line, node->var_name->col, |
226 | symbol); | 255 | symbol); |
227 | } | 256 | } |
228 | symmap_insert(&scope->symbols, symbol, (Symbol){.kind = SYM_VAR}, | 257 | symmap_insert(&scope->symbols, symbol, |
258 | (Symbol){.kind = SYM_VAR, .name = symbol}, | ||
229 | a->storage); | 259 | a->storage); |
230 | } break; | 260 | } break; |
231 | // Binary ops | 261 | // Binary ops |
@@ -269,7 +299,7 @@ symbolic_analysis(Analyzer *a, Parser *parser) { | |||
269 | }; | 299 | }; |
270 | for (sz i = 0; i < LEN(builtin_functions); i++) { | 300 | for (sz i = 0; i < LEN(builtin_functions); i++) { |
271 | Str symbol = builtin_functions[i]; | 301 | Str symbol = builtin_functions[i]; |
272 | Symbol sym = (Symbol){.kind = SYM_BUILTIN}; | 302 | Symbol sym = (Symbol){.kind = SYM_BUILTIN, .name = symbol}; |
273 | symmap_insert(&scope->symbols, symbol, sym, a->storage); | 303 | symmap_insert(&scope->symbols, symbol, sym, a->storage); |
274 | } | 304 | } |
275 | 305 | ||
@@ -285,7 +315,8 @@ symbolic_analysis(Analyzer *a, Parser *parser) { | |||
285 | a->file_name, root->func_name->line, root->func_name->col, | 315 | a->file_name, root->func_name->line, root->func_name->col, |
286 | symbol); | 316 | symbol); |
287 | } | 317 | } |
288 | symmap_insert(&scope->symbols, symbol, (Symbol){.kind = SYM_FUN}, | 318 | symmap_insert(&scope->symbols, symbol, |
319 | (Symbol){.kind = SYM_FUN, .name = symbol}, | ||
289 | a->storage); | 320 | a->storage); |
290 | } | 321 | } |
291 | } | 322 | } |
@@ -376,7 +407,12 @@ process_file(Str path) { | |||
376 | SymbolMap *sym = symmap_next(&iter, &scratch); | 407 | SymbolMap *sym = symmap_next(&iter, &scratch); |
377 | while (sym) { | 408 | while (sym) { |
378 | println("%s: SCOPE: %d DEPTH: %d\t%s %s", path, scope->id, | 409 | println("%s: SCOPE: %d DEPTH: %d\t%s %s", path, scope->id, |
379 | scope->depth, sym_kind_str[sym->val.kind], sym->key); | 410 | scope->depth, sym_kind_str[sym->val.kind], sym->val.name); |
411 | for (sz i = 0; i < array_size(sym->val.fields); i++) { | ||
412 | Symbol field = sym->val.fields[i]; | ||
413 | println("%s: SCOPE: %d DEPTH: %d\t%s %s", path, scope->id, | ||
414 | scope->depth, sym_kind_str[field.kind], field.name); | ||
415 | } | ||
380 | sym = symmap_next(&iter, &lexer_arena); | 416 | sym = symmap_next(&iter, &lexer_arena); |
381 | } | 417 | } |
382 | } | 418 | } |
diff --git a/src/parser.c b/src/parser.c index 04692b3..67fc739 100644 --- a/src/parser.c +++ b/src/parser.c | |||
@@ -192,7 +192,7 @@ typedef struct Node { | |||
192 | }; | 192 | }; |
193 | }; | 193 | }; |
194 | bool is_ptr; | 194 | bool is_ptr; |
195 | struct Scope* scope; | 195 | struct Scope *scope; |
196 | } Node; | 196 | } Node; |
197 | 197 | ||
198 | // | 198 | // |
@@ -651,6 +651,9 @@ parse_keyword(Parser *parser) { | |||
651 | } | 651 | } |
652 | array_push(node->struct_field, field, parser->storage); | 652 | array_push(node->struct_field, field, parser->storage); |
653 | } | 653 | } |
654 | if (array_size(node->struct_field) == 0) { | ||
655 | parse_emit_err(parser, prev, cstr("empty enum declaration")); | ||
656 | } | ||
654 | } break; | 657 | } break; |
655 | case TOK_COND: { | 658 | case TOK_COND: { |
656 | node = node_alloc(parser, NODE_COND, prev); | 659 | node = node_alloc(parser, NODE_COND, prev); |