diff options
author | Bad Diode <bd@badd10de.dev> | 2021-11-10 16:40:29 +0100 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-11-10 16:40:29 +0100 |
commit | 69f6b03296f96a60dd7fc103ff89d187f1a29aec (patch) | |
tree | b942b1afb25f6c6db2fa6be861406c1446026f8c | |
parent | e32231ffa4dfc4b5c3c65437f03190e57ccc9678 (diff) | |
download | bdl-69f6b03296f96a60dd7fc103ff89d187f1a29aec.tar.gz bdl-69f6b03296f96a60dd7fc103ff89d187f1a29aec.zip |
Change Environment to store locals in array
This will help directly translate the locals to assembly.
-rw-r--r-- | src/compiler.h | 2 | ||||
-rw-r--r-- | src/main.c | 4 | ||||
-rw-r--r-- | src/parser.c | 51 | ||||
-rw-r--r-- | src/parser.h | 10 |
4 files changed, 42 insertions, 25 deletions
diff --git a/src/compiler.h b/src/compiler.h index d4b9e72..fe36ecf 100644 --- a/src/compiler.h +++ b/src/compiler.h | |||
@@ -405,6 +405,7 @@ compile_proc_call(Object *obj) { | |||
405 | 405 | ||
406 | void | 406 | void |
407 | compile_if(Object *obj) { | 407 | compile_if(Object *obj) { |
408 | context_printf(" ;; --> compile_if\n"); | ||
408 | char *lab_false = generate_label("BDLL"); | 409 | char *lab_false = generate_label("BDLL"); |
409 | compile_object(obj->condition); | 410 | compile_object(obj->condition); |
410 | context_printf(" pop rax\n"); | 411 | context_printf(" pop rax\n"); |
@@ -420,6 +421,7 @@ compile_if(Object *obj) { | |||
420 | } else { | 421 | } else { |
421 | context_printf("%s:\n", lab_false); | 422 | context_printf("%s:\n", lab_false); |
422 | } | 423 | } |
424 | context_printf(" ;; <-- compile_if\n"); | ||
423 | } | 425 | } |
424 | 426 | ||
425 | void | 427 | void |
@@ -33,7 +33,7 @@ process_source(const StringView *source, const char *file_name) { | |||
33 | } | 33 | } |
34 | 34 | ||
35 | // Parser. | 35 | // Parser. |
36 | Root *roots = parse(tokens, &errors); | 36 | Program program = parse(tokens, &errors); |
37 | if (errors.n != 0) { | 37 | if (errors.n != 0) { |
38 | report_errors(&errors, file_name); | 38 | report_errors(&errors, file_name); |
39 | free_objects(); | 39 | free_objects(); |
@@ -45,7 +45,7 @@ process_source(const StringView *source, const char *file_name) { | |||
45 | // TODO: Optimization. | 45 | // TODO: Optimization. |
46 | 46 | ||
47 | // Compilation. | 47 | // Compilation. |
48 | compile(roots); | 48 | compile(program.roots); |
49 | 49 | ||
50 | // Free resources. | 50 | // Free resources. |
51 | free_objects(); | 51 | free_objects(); |
diff --git a/src/parser.c b/src/parser.c index 5632e13..100916b 100644 --- a/src/parser.c +++ b/src/parser.c | |||
@@ -14,14 +14,6 @@ static char *builtins [] = { | |||
14 | "cons", "car", "cdr", | 14 | "cons", "car", "cdr", |
15 | }; | 15 | }; |
16 | 16 | ||
17 | uint64_t | ||
18 | symbol_hash(const HashTable *table, void *key) { | ||
19 | Object *obj = key; | ||
20 | uint64_t hash = _xor_shift_hash(obj->text.start, obj->text.n); | ||
21 | hash = _fibonacci_hash(hash, table->shift_amount); | ||
22 | return hash; | ||
23 | } | ||
24 | |||
25 | Token | 17 | Token |
26 | peek_token(const Parser *parser) { | 18 | peek_token(const Parser *parser) { |
27 | if (parser->current >= array_size(parser->tokens)) { | 19 | if (parser->current >= array_size(parser->tokens)) { |
@@ -436,12 +428,22 @@ parse_tree(Parser *parser, Errors *errors) { | |||
436 | return NULL; | 428 | return NULL; |
437 | } | 429 | } |
438 | 430 | ||
431 | ssize_t | ||
432 | find_local_index(Object **locals, Object *symbol) { | ||
433 | for (size_t i = 0; i < array_size(locals); i++) { | ||
434 | if (object_equal(locals[i], symbol)) { | ||
435 | return i; | ||
436 | } | ||
437 | } | ||
438 | return -1; | ||
439 | } | ||
440 | |||
439 | Object * | 441 | Object * |
440 | symbol_in_env(Environment *env, Object *symbol) { | 442 | symbol_in_env(Environment *env, Object *symbol) { |
441 | while (env != NULL) { | 443 | while (env != NULL) { |
442 | Object *found = ht_lookup(env->table, symbol); | 444 | ssize_t idx = find_local_index(env->locals, symbol); |
443 | if (found != NULL) { | 445 | if (idx != -1) { |
444 | return found; | 446 | return env->locals[idx]; |
445 | } | 447 | } |
446 | env = env->parent; | 448 | env = env->parent; |
447 | } | 449 | } |
@@ -449,6 +451,14 @@ symbol_in_env(Environment *env, Object *symbol) { | |||
449 | } | 451 | } |
450 | 452 | ||
451 | void | 453 | void |
454 | insert_local(Environment *env, Object *symbol) { | ||
455 | if (find_local_index(env->locals, symbol) != -1) { | ||
456 | return; | ||
457 | } | ||
458 | array_push(env->locals, symbol); | ||
459 | } | ||
460 | |||
461 | void | ||
452 | semantic_analysis(Environment *env, Object *obj, Errors *errors) { | 462 | semantic_analysis(Environment *env, Object *obj, Errors *errors) { |
453 | if (obj == NULL || obj->visited) { | 463 | if (obj == NULL || obj->visited) { |
454 | return; | 464 | return; |
@@ -457,7 +467,7 @@ semantic_analysis(Environment *env, Object *obj, Errors *errors) { | |||
457 | switch (obj->type) { | 467 | switch (obj->type) { |
458 | case OBJ_TYPE_SYMBOL: { | 468 | case OBJ_TYPE_SYMBOL: { |
459 | Object *found = symbol_in_env(env, obj); | 469 | Object *found = symbol_in_env(env, obj); |
460 | if (symbol_in_env(env, obj) == NULL) { | 470 | if (found == NULL) { |
461 | error_push(errors, (Error){ | 471 | error_push(errors, (Error){ |
462 | .type = ERR_TYPE_PARSER, | 472 | .type = ERR_TYPE_PARSER, |
463 | .value = ERR_SYMBOL_NOT_FOUND, | 473 | .value = ERR_SYMBOL_NOT_FOUND, |
@@ -469,7 +479,7 @@ semantic_analysis(Environment *env, Object *obj, Errors *errors) { | |||
469 | semantic_analysis(env, found, errors); | 479 | semantic_analysis(env, found, errors); |
470 | } break; | 480 | } break; |
471 | case OBJ_TYPE_DEF: { | 481 | case OBJ_TYPE_DEF: { |
472 | ht_insert(env->table, obj->var_name, obj->var_expr); | 482 | insert_local(env, obj->var_name); |
473 | semantic_analysis(env, obj->var_expr, errors); | 483 | semantic_analysis(env, obj->var_expr, errors); |
474 | } break; | 484 | } break; |
475 | case OBJ_TYPE_SET: { | 485 | case OBJ_TYPE_SET: { |
@@ -538,7 +548,7 @@ semantic_analysis(Environment *env, Object *obj, Errors *errors) { | |||
538 | } | 548 | } |
539 | } | 549 | } |
540 | 550 | ||
541 | Root * | 551 | Program |
542 | parse(Token *tokens, Errors *errors) { | 552 | parse(Token *tokens, Errors *errors) { |
543 | array_init(roots, 0); | 553 | array_init(roots, 0); |
544 | array_init(objects, 0); | 554 | array_init(objects, 0); |
@@ -552,7 +562,7 @@ parse(Token *tokens, Errors *errors) { | |||
552 | while (has_next_token(&parser)) { | 562 | while (has_next_token(&parser)) { |
553 | Object *root = parse_tree(&parser, errors); | 563 | Object *root = parse_tree(&parser, errors); |
554 | if (errors->n != 0) { | 564 | if (errors->n != 0) { |
555 | return NULL; | 565 | return (Program){0}; |
556 | } | 566 | } |
557 | array_push(roots, root); | 567 | array_push(roots, root); |
558 | } | 568 | } |
@@ -568,7 +578,7 @@ parse(Token *tokens, Errors *errors) { | |||
568 | symbol->text = (StringView){str, str_n}; | 578 | symbol->text = (StringView){str, str_n}; |
569 | 579 | ||
570 | // Insert in global table. | 580 | // Insert in global table. |
571 | ht_insert(global_env->table, symbol, symbol); | 581 | insert_local(global_env, symbol); |
572 | } | 582 | } |
573 | 583 | ||
574 | // Perform semantic analysis: | 584 | // Perform semantic analysis: |
@@ -593,7 +603,7 @@ parse(Token *tokens, Errors *errors) { | |||
593 | semantic_analysis(global_env, root, errors); | 603 | semantic_analysis(global_env, root, errors); |
594 | if (errors->n != 0) { | 604 | if (errors->n != 0) { |
595 | array_free(final_roots); | 605 | array_free(final_roots); |
596 | return NULL; | 606 | return (Program){0}; |
597 | } | 607 | } |
598 | } | 608 | } |
599 | array_free(roots); | 609 | array_free(roots); |
@@ -604,13 +614,14 @@ parse(Token *tokens, Errors *errors) { | |||
604 | // TODO: Type check basic expressions (e.g. arithmetic/numeric comparisons). | 614 | // TODO: Type check basic expressions (e.g. arithmetic/numeric comparisons). |
605 | // We can't be sure when we have functions unless the return type is known. | 615 | // We can't be sure when we have functions unless the return type is known. |
606 | 616 | ||
607 | return roots; | 617 | return (Program){roots, global_env}; |
608 | } | 618 | } |
609 | 619 | ||
610 | Environment * | 620 | Environment * |
611 | env_alloc(Environment *parent) { | 621 | env_alloc(Environment *parent) { |
612 | Environment *env = malloc(sizeof(Environment)); | 622 | Environment *env = malloc(sizeof(Environment)); |
613 | env->table = ht_init(symbol_hash, (EqFunc*)object_equal); | 623 | env->locals = NULL; |
624 | array_init(env->locals, 0); | ||
614 | env->parent = parent; | 625 | env->parent = parent; |
615 | array_push(environments, env); | 626 | array_push(environments, env); |
616 | return env; | 627 | return env; |
@@ -650,7 +661,7 @@ free_objects(void) { | |||
650 | if (environments != NULL) { | 661 | if (environments != NULL) { |
651 | for (size_t i = 0; i < array_size(environments); i++) { | 662 | for (size_t i = 0; i < array_size(environments); i++) { |
652 | Environment *env = environments[i]; | 663 | Environment *env = environments[i]; |
653 | ht_free(env->table); | 664 | array_free(env->locals); |
654 | free(env); | 665 | free(env); |
655 | } | 666 | } |
656 | array_free(environments); | 667 | array_free(environments); |
diff --git a/src/parser.h b/src/parser.h index 9414a24..c117c61 100644 --- a/src/parser.h +++ b/src/parser.h | |||
@@ -2,10 +2,9 @@ | |||
2 | #define BDL_PARSER_H | 2 | #define BDL_PARSER_H |
3 | 3 | ||
4 | #include "lexer.h" | 4 | #include "lexer.h" |
5 | #include "hashtable.h" | ||
6 | 5 | ||
7 | typedef struct Environment { | 6 | typedef struct Environment { |
8 | HashTable *table; | 7 | struct Object **locals; |
9 | struct Environment *parent; | 8 | struct Environment *parent; |
10 | } Environment; | 9 | } Environment; |
11 | 10 | ||
@@ -74,6 +73,11 @@ typedef struct Parser { | |||
74 | 73 | ||
75 | typedef Object* Root; | 74 | typedef Object* Root; |
76 | 75 | ||
76 | typedef struct Program { | ||
77 | Root *roots; | ||
78 | Environment *env; | ||
79 | } Program; | ||
80 | |||
77 | // Token scanner. | 81 | // Token scanner. |
78 | Token next_token(Parser *parser); | 82 | Token next_token(Parser *parser); |
79 | Token previous_token(Parser *parser); | 83 | Token previous_token(Parser *parser); |
@@ -91,7 +95,7 @@ Object * parse_list(Parser *parser, Errors *errors); | |||
91 | Object * parse_lambda(Parser *parser, Errors *errors); | 95 | Object * parse_lambda(Parser *parser, Errors *errors); |
92 | Object * parse_if(Parser *parser, Errors *errors); | 96 | Object * parse_if(Parser *parser, Errors *errors); |
93 | Object * parse_var(Parser *parser, Errors *errors); | 97 | Object * parse_var(Parser *parser, Errors *errors); |
94 | Root * parse(Token *tokens, Errors *errors); | 98 | Program parse(Token *tokens, Errors *errors); |
95 | 99 | ||
96 | // Object operations. | 100 | // Object operations. |
97 | void object_display(Object *obj); | 101 | void object_display(Object *obj); |