aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-11-10 16:40:29 +0100
committerBad Diode <bd@badd10de.dev>2021-11-10 16:40:29 +0100
commit69f6b03296f96a60dd7fc103ff89d187f1a29aec (patch)
treeb942b1afb25f6c6db2fa6be861406c1446026f8c
parente32231ffa4dfc4b5c3c65437f03190e57ccc9678 (diff)
downloadbdl-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.h2
-rw-r--r--src/main.c4
-rw-r--r--src/parser.c51
-rw-r--r--src/parser.h10
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
406void 406void
407compile_if(Object *obj) { 407compile_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
425void 427void
diff --git a/src/main.c b/src/main.c
index cf4bfa4..8962519 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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
17uint64_t
18symbol_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
25Token 17Token
26peek_token(const Parser *parser) { 18peek_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
431ssize_t
432find_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
439Object * 441Object *
440symbol_in_env(Environment *env, Object *symbol) { 442symbol_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
451void 453void
454insert_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
461void
452semantic_analysis(Environment *env, Object *obj, Errors *errors) { 462semantic_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
541Root * 551Program
542parse(Token *tokens, Errors *errors) { 552parse(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
610Environment * 620Environment *
611env_alloc(Environment *parent) { 621env_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
7typedef struct Environment { 6typedef 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
75typedef Object* Root; 74typedef Object* Root;
76 75
76typedef struct Program {
77 Root *roots;
78 Environment *env;
79} Program;
80
77// Token scanner. 81// Token scanner.
78Token next_token(Parser *parser); 82Token next_token(Parser *parser);
79Token previous_token(Parser *parser); 83Token previous_token(Parser *parser);
@@ -91,7 +95,7 @@ Object * parse_list(Parser *parser, Errors *errors);
91Object * parse_lambda(Parser *parser, Errors *errors); 95Object * parse_lambda(Parser *parser, Errors *errors);
92Object * parse_if(Parser *parser, Errors *errors); 96Object * parse_if(Parser *parser, Errors *errors);
93Object * parse_var(Parser *parser, Errors *errors); 97Object * parse_var(Parser *parser, Errors *errors);
94Root * parse(Token *tokens, Errors *errors); 98Program parse(Token *tokens, Errors *errors);
95 99
96// Object operations. 100// Object operations.
97void object_display(Object *obj); 101void object_display(Object *obj);