diff options
author | Bad Diode <bd@badd10de.dev> | 2022-04-19 10:41:32 -0300 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2022-04-19 10:41:32 -0300 |
commit | c69929cc501203829082b810bafe75a22947e00c (patch) | |
tree | 46dceba9e657a424626ab97f510b49d3b2b889cf /src/semantic.c | |
parent | 7cf1451ab52586ed9c4eeae1b1ec3b4ebaa83393 (diff) | |
download | bdl-c69929cc501203829082b810bafe75a22947e00c.tar.gz bdl-c69929cc501203829082b810bafe75a22947e00c.zip |
Add viz for symbol tables
Diffstat (limited to 'src/semantic.c')
-rw-r--r-- | src/semantic.c | 44 |
1 files changed, 24 insertions, 20 deletions
diff --git a/src/semantic.c b/src/semantic.c index 06958b9..6c9f290 100644 --- a/src/semantic.c +++ b/src/semantic.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #include "hashtable.h" | 1 | #include "hashtable.h" |
2 | 2 | ||
3 | typedef struct Scope { | 3 | typedef struct Scope { |
4 | size_t id; | ||
4 | struct Scope *parent; | 5 | struct Scope *parent; |
5 | HashTable *symbols; | 6 | HashTable *symbols; |
6 | HashTable *types; | 7 | HashTable *types; |
@@ -8,8 +9,7 @@ typedef struct Scope { | |||
8 | 9 | ||
9 | typedef struct ParseTree { | 10 | typedef struct ParseTree { |
10 | Root *roots; | 11 | Root *roots; |
11 | Scope *global_scope; | 12 | Scope **scopes; |
12 | Scope *current_scope; | ||
13 | } ParseTree; | 13 | } ParseTree; |
14 | 14 | ||
15 | typedef struct Type { | 15 | typedef struct Type { |
@@ -70,6 +70,7 @@ typedef struct Symbol { | |||
70 | }; | 70 | }; |
71 | } Symbol; | 71 | } Symbol; |
72 | 72 | ||
73 | static size_t scope_gen_id = 0; | ||
73 | 74 | ||
74 | Symbol * | 75 | Symbol * |
75 | alloc_symval(Node *name, SymbolType type) { | 76 | alloc_symval(Node *name, SymbolType type) { |
@@ -110,6 +111,7 @@ bool type_eq(void *a, void *b) { | |||
110 | Scope * | 111 | Scope * |
111 | alloc_scope(Scope *parent) { | 112 | alloc_scope(Scope *parent) { |
112 | Scope *scope = malloc(sizeof(Scope)); | 113 | Scope *scope = malloc(sizeof(Scope)); |
114 | scope->id = scope_gen_id++; | ||
113 | scope->parent = parent; | 115 | scope->parent = parent; |
114 | scope->symbols = ht_init(sym_hash, sym_eq); | 116 | scope->symbols = ht_init(sym_hash, sym_eq); |
115 | scope->types = ht_init(type_hash, type_eq); | 117 | scope->types = ht_init(type_hash, type_eq); |
@@ -216,7 +218,7 @@ find_symbol(Scope *scope, Node *node) { | |||
216 | } | 218 | } |
217 | 219 | ||
218 | bool | 220 | bool |
219 | resolve_type(Scope *scope, Node *node) { | 221 | resolve_type(ParseTree *ast, Scope *scope, Node *node) { |
220 | if (node->expr_type != NULL) { | 222 | if (node->expr_type != NULL) { |
221 | return true; | 223 | return true; |
222 | } | 224 | } |
@@ -224,7 +226,7 @@ resolve_type(Scope *scope, Node *node) { | |||
224 | case NODE_BUILTIN: { | 226 | case NODE_BUILTIN: { |
225 | for (size_t i = 0; i < array_size(node->builtin.args); ++i) { | 227 | for (size_t i = 0; i < array_size(node->builtin.args); ++i) { |
226 | Node *arg = node->builtin.args[i]; | 228 | Node *arg = node->builtin.args[i]; |
227 | if (!resolve_type(scope, arg)) { | 229 | if (!resolve_type(ast, scope, arg)) { |
228 | return false; | 230 | return false; |
229 | } | 231 | } |
230 | } | 232 | } |
@@ -311,6 +313,7 @@ resolve_type(Scope *scope, Node *node) { | |||
311 | case NODE_FUN: { | 313 | case NODE_FUN: { |
312 | // Fill up new scope with parameters | 314 | // Fill up new scope with parameters |
313 | scope = alloc_scope(scope); | 315 | scope = alloc_scope(scope); |
316 | array_push(ast->scopes, scope); | ||
314 | 317 | ||
315 | // Parameters. | 318 | // Parameters. |
316 | for (size_t i = 0; i < array_size(node->fun.param_names); ++i) { | 319 | for (size_t i = 0; i < array_size(node->fun.param_names); ++i) { |
@@ -328,14 +331,14 @@ resolve_type(Scope *scope, Node *node) { | |||
328 | if (body->type == NODE_BLOCK) { | 331 | if (body->type == NODE_BLOCK) { |
329 | for (size_t i = 0; i < array_size(body->block.expr); ++i) { | 332 | for (size_t i = 0; i < array_size(body->block.expr); ++i) { |
330 | Node *expr = body->block.expr[i]; | 333 | Node *expr = body->block.expr[i]; |
331 | if (!resolve_type(scope, expr)) { | 334 | if (!resolve_type(ast, scope, expr)) { |
332 | return false; | 335 | return false; |
333 | } | 336 | } |
334 | } | 337 | } |
335 | Node *last_expr = body->block.expr[array_size(body->block.expr) - 1]; | 338 | Node *last_expr = body->block.expr[array_size(body->block.expr) - 1]; |
336 | node->expr_type = last_expr->expr_type; | 339 | node->expr_type = last_expr->expr_type; |
337 | } else { | 340 | } else { |
338 | if (!resolve_type(scope, body)) { | 341 | if (!resolve_type(ast, scope, body)) { |
339 | return false; | 342 | return false; |
340 | } | 343 | } |
341 | } | 344 | } |
@@ -350,9 +353,10 @@ resolve_type(Scope *scope, Node *node) { | |||
350 | } break; | 353 | } break; |
351 | case NODE_BLOCK: { | 354 | case NODE_BLOCK: { |
352 | scope = alloc_scope(scope); | 355 | scope = alloc_scope(scope); |
356 | array_push(ast->scopes, scope); | ||
353 | for (size_t i = 0; i < array_size(node->block.expr); ++i) { | 357 | for (size_t i = 0; i < array_size(node->block.expr); ++i) { |
354 | Node *expr = node->block.expr[i]; | 358 | Node *expr = node->block.expr[i]; |
355 | if (!resolve_type(scope, expr)) { | 359 | if (!resolve_type(ast, scope, expr)) { |
356 | return false; | 360 | return false; |
357 | } | 361 | } |
358 | } | 362 | } |
@@ -360,16 +364,16 @@ resolve_type(Scope *scope, Node *node) { | |||
360 | node->expr_type = last_expr->expr_type; | 364 | node->expr_type = last_expr->expr_type; |
361 | } break; | 365 | } break; |
362 | case NODE_IF: { | 366 | case NODE_IF: { |
363 | if (!resolve_type(scope, node->ifexpr.cond)) { | 367 | if (!resolve_type(ast, scope, node->ifexpr.cond)) { |
364 | return false; | 368 | return false; |
365 | } | 369 | } |
366 | if (!resolve_type(scope, node->ifexpr.expr_true)) { | 370 | if (!resolve_type(ast, scope, node->ifexpr.expr_true)) { |
367 | return false; | 371 | return false; |
368 | } | 372 | } |
369 | Type *type_true = node->ifexpr.expr_true->expr_type; | 373 | Type *type_true = node->ifexpr.expr_true->expr_type; |
370 | node->expr_type = type_true; | 374 | node->expr_type = type_true; |
371 | if (node->ifexpr.expr_false != NULL) { | 375 | if (node->ifexpr.expr_false != NULL) { |
372 | if (!resolve_type(scope, node->ifexpr.expr_false)) { | 376 | if (!resolve_type(ast, scope, node->ifexpr.expr_false)) { |
373 | return false; | 377 | return false; |
374 | } | 378 | } |
375 | } | 379 | } |
@@ -396,10 +400,10 @@ resolve_type(Scope *scope, Node *node) { | |||
396 | } break; | 400 | } break; |
397 | case NODE_SET: { | 401 | case NODE_SET: { |
398 | node->expr_type = &default_types[TYPE_VOID]; | 402 | node->expr_type = &default_types[TYPE_VOID]; |
399 | if (!resolve_type(scope, node->set.symbol)) { | 403 | if (!resolve_type(ast, scope, node->set.symbol)) { |
400 | return false; | 404 | return false; |
401 | } | 405 | } |
402 | if (!resolve_type(scope, node->set.value)) { | 406 | if (!resolve_type(ast, scope, node->set.value)) { |
403 | return false; | 407 | return false; |
404 | } | 408 | } |
405 | Node *symbol = node->set.symbol; | 409 | Node *symbol = node->set.symbol; |
@@ -426,7 +430,7 @@ resolve_type(Scope *scope, Node *node) { | |||
426 | 430 | ||
427 | node->expr_type = &default_types[TYPE_VOID]; | 431 | node->expr_type = &default_types[TYPE_VOID]; |
428 | // TODO: type inference from right side when not annotated? | 432 | // TODO: type inference from right side when not annotated? |
429 | if (!resolve_type(scope, node->def.value)) { | 433 | if (!resolve_type(ast, scope, node->def.value)) { |
430 | return false; | 434 | return false; |
431 | } | 435 | } |
432 | Node *symbol = node->def.symbol; | 436 | Node *symbol = node->def.symbol; |
@@ -455,7 +459,7 @@ resolve_type(Scope *scope, Node *node) { | |||
455 | } break; | 459 | } break; |
456 | case NODE_FUNCALL: { | 460 | case NODE_FUNCALL: { |
457 | Symbol *val = find_symbol(scope, node->funcall.name); | 461 | Symbol *val = find_symbol(scope, node->funcall.name); |
458 | if (!resolve_type(scope, node->funcall.name)) { | 462 | if (!resolve_type(ast, scope, node->funcall.name)) { |
459 | return false; | 463 | return false; |
460 | } | 464 | } |
461 | if (val->type != SYMBOL_FUN) { | 465 | if (val->type != SYMBOL_FUN) { |
@@ -470,7 +474,7 @@ resolve_type(Scope *scope, Node *node) { | |||
470 | node->expr_type = node->funcall.name->expr_type; | 474 | node->expr_type = node->funcall.name->expr_type; |
471 | for (size_t i = 0; i < array_size(node->funcall.args); ++i) { | 475 | for (size_t i = 0; i < array_size(node->funcall.args); ++i) { |
472 | Node *arg = node->funcall.args[i]; | 476 | Node *arg = node->funcall.args[i]; |
473 | if (!resolve_type(scope, arg)) { | 477 | if (!resolve_type(ast, scope, arg)) { |
474 | return false; | 478 | return false; |
475 | } | 479 | } |
476 | Node *expected = val->fun.param_types[i]; | 480 | Node *expected = val->fun.param_types[i]; |
@@ -490,18 +494,18 @@ ParseTree * | |||
490 | semantic_analysis(Root *roots) { | 494 | semantic_analysis(Root *roots) { |
491 | ParseTree *parse_tree = malloc(sizeof(ParseTree)); | 495 | ParseTree *parse_tree = malloc(sizeof(ParseTree)); |
492 | parse_tree->roots = roots; | 496 | parse_tree->roots = roots; |
493 | parse_tree->global_scope = alloc_scope(NULL); | 497 | array_init(parse_tree->scopes, 0); |
494 | parse_tree->current_scope = parse_tree->global_scope; | 498 | Scope *scope = alloc_scope(NULL); |
499 | array_push(parse_tree->scopes, scope); | ||
495 | 500 | ||
496 | // Fill global scope with default types. | 501 | // Fill global scope with default types. |
497 | HashTable *types = parse_tree->global_scope->types; | 502 | HashTable *types = scope->types; |
498 | for (size_t i = 0; i < sizeof(default_types)/sizeof(Type); ++i) { | 503 | for (size_t i = 0; i < sizeof(default_types)/sizeof(Type); ++i) { |
499 | Type *type = &default_types[i]; | 504 | Type *type = &default_types[i]; |
500 | ht_insert(types, &type->name, type); | 505 | ht_insert(types, &type->name, type); |
501 | } | 506 | } |
502 | 507 | ||
503 | // Fill up global function symbols. | 508 | // Fill up global function symbols. |
504 | Scope *scope = parse_tree->global_scope; | ||
505 | for (size_t i = 0; i < array_size(parse_tree->roots); ++i) { | 509 | for (size_t i = 0; i < array_size(parse_tree->roots); ++i) { |
506 | Node *root = parse_tree->roots[i]; | 510 | Node *root = parse_tree->roots[i]; |
507 | if (root->type == NODE_FUN) { | 511 | if (root->type == NODE_FUN) { |
@@ -518,7 +522,7 @@ semantic_analysis(Root *roots) { | |||
518 | for (size_t i = 0; i < array_size(parse_tree->roots); ++i) { | 522 | for (size_t i = 0; i < array_size(parse_tree->roots); ++i) { |
519 | // Fill up symbol tables in proper scope and resolve type of expression | 523 | // Fill up symbol tables in proper scope and resolve type of expression |
520 | // for all elements. | 524 | // for all elements. |
521 | if (!resolve_type(scope, parse_tree->roots[i])) { | 525 | if (!resolve_type(parse_tree, scope, parse_tree->roots[i])) { |
522 | return NULL; | 526 | return NULL; |
523 | } | 527 | } |
524 | } | 528 | } |