aboutsummaryrefslogtreecommitdiffstats
path: root/src/parser.c
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 /src/parser.c
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.
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c51
1 files changed, 31 insertions, 20 deletions
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);