aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-21 15:59:32 +0200
committerBad Diode <bd@badd10de.dev>2024-06-21 15:59:32 +0200
commit59b9c661cbdf125b0a17f8f955158a1f77f163f8 (patch)
tree36c5b0abe4bb8202f6b23c30759706cd1c0f8a49 /src
parentd336498c7cf397de496fa46fccc31883480ecb1d (diff)
downloadbdl-59b9c661cbdf125b0a17f8f955158a1f77f163f8.tar.gz
bdl-59b9c661cbdf125b0a17f8f955158a1f77f163f8.zip
Add semantic checking for enum constructs
Diffstat (limited to 'src')
-rw-r--r--src/main.c56
-rw-r--r--src/parser.c5
2 files changed, 50 insertions, 11 deletions
diff --git a/src/main.c b/src/main.c
index 7cb0b87..8e177e1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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
33Str sym_kind_str[] = { 35Str 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
39typedef struct Symbol { 42typedef struct Symbol {
40 SymbolKind kind; 43 SymbolKind kind;
44 Str name;
45 struct Symbol *fields;
41} Symbol; 46} Symbol;
42 47
43MAPDEF(SymbolMap, symmap, Str, Symbol, str_hash, str_eq) 48MAPDEF(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);