From 69f6b03296f96a60dd7fc103ff89d187f1a29aec Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Wed, 10 Nov 2021 16:40:29 +0100 Subject: Change Environment to store locals in array This will help directly translate the locals to assembly. --- src/compiler.h | 2 ++ src/main.c | 4 ++-- src/parser.c | 51 +++++++++++++++++++++++++++++++-------------------- 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) { void compile_if(Object *obj) { + context_printf(" ;; --> compile_if\n"); char *lab_false = generate_label("BDLL"); compile_object(obj->condition); context_printf(" pop rax\n"); @@ -420,6 +421,7 @@ compile_if(Object *obj) { } else { context_printf("%s:\n", lab_false); } + context_printf(" ;; <-- compile_if\n"); } void 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) { } // Parser. - Root *roots = parse(tokens, &errors); + Program program = parse(tokens, &errors); if (errors.n != 0) { report_errors(&errors, file_name); free_objects(); @@ -45,7 +45,7 @@ process_source(const StringView *source, const char *file_name) { // TODO: Optimization. // Compilation. - compile(roots); + compile(program.roots); // Free resources. 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 [] = { "cons", "car", "cdr", }; -uint64_t -symbol_hash(const HashTable *table, void *key) { - Object *obj = key; - uint64_t hash = _xor_shift_hash(obj->text.start, obj->text.n); - hash = _fibonacci_hash(hash, table->shift_amount); - return hash; -} - Token peek_token(const Parser *parser) { if (parser->current >= array_size(parser->tokens)) { @@ -436,18 +428,36 @@ parse_tree(Parser *parser, Errors *errors) { return NULL; } +ssize_t +find_local_index(Object **locals, Object *symbol) { + for (size_t i = 0; i < array_size(locals); i++) { + if (object_equal(locals[i], symbol)) { + return i; + } + } + return -1; +} + Object * symbol_in_env(Environment *env, Object *symbol) { while (env != NULL) { - Object *found = ht_lookup(env->table, symbol); - if (found != NULL) { - return found; + ssize_t idx = find_local_index(env->locals, symbol); + if (idx != -1) { + return env->locals[idx]; } env = env->parent; } return NULL; } +void +insert_local(Environment *env, Object *symbol) { + if (find_local_index(env->locals, symbol) != -1) { + return; + } + array_push(env->locals, symbol); +} + void semantic_analysis(Environment *env, Object *obj, Errors *errors) { if (obj == NULL || obj->visited) { @@ -457,7 +467,7 @@ semantic_analysis(Environment *env, Object *obj, Errors *errors) { switch (obj->type) { case OBJ_TYPE_SYMBOL: { Object *found = symbol_in_env(env, obj); - if (symbol_in_env(env, obj) == NULL) { + if (found == NULL) { error_push(errors, (Error){ .type = ERR_TYPE_PARSER, .value = ERR_SYMBOL_NOT_FOUND, @@ -469,7 +479,7 @@ semantic_analysis(Environment *env, Object *obj, Errors *errors) { semantic_analysis(env, found, errors); } break; case OBJ_TYPE_DEF: { - ht_insert(env->table, obj->var_name, obj->var_expr); + insert_local(env, obj->var_name); semantic_analysis(env, obj->var_expr, errors); } break; case OBJ_TYPE_SET: { @@ -538,7 +548,7 @@ semantic_analysis(Environment *env, Object *obj, Errors *errors) { } } -Root * +Program parse(Token *tokens, Errors *errors) { array_init(roots, 0); array_init(objects, 0); @@ -552,7 +562,7 @@ parse(Token *tokens, Errors *errors) { while (has_next_token(&parser)) { Object *root = parse_tree(&parser, errors); if (errors->n != 0) { - return NULL; + return (Program){0}; } array_push(roots, root); } @@ -568,7 +578,7 @@ parse(Token *tokens, Errors *errors) { symbol->text = (StringView){str, str_n}; // Insert in global table. - ht_insert(global_env->table, symbol, symbol); + insert_local(global_env, symbol); } // Perform semantic analysis: @@ -593,7 +603,7 @@ parse(Token *tokens, Errors *errors) { semantic_analysis(global_env, root, errors); if (errors->n != 0) { array_free(final_roots); - return NULL; + return (Program){0}; } } array_free(roots); @@ -604,13 +614,14 @@ parse(Token *tokens, Errors *errors) { // TODO: Type check basic expressions (e.g. arithmetic/numeric comparisons). // We can't be sure when we have functions unless the return type is known. - return roots; + return (Program){roots, global_env}; } Environment * env_alloc(Environment *parent) { Environment *env = malloc(sizeof(Environment)); - env->table = ht_init(symbol_hash, (EqFunc*)object_equal); + env->locals = NULL; + array_init(env->locals, 0); env->parent = parent; array_push(environments, env); return env; @@ -650,7 +661,7 @@ free_objects(void) { if (environments != NULL) { for (size_t i = 0; i < array_size(environments); i++) { Environment *env = environments[i]; - ht_free(env->table); + array_free(env->locals); free(env); } 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 @@ #define BDL_PARSER_H #include "lexer.h" -#include "hashtable.h" typedef struct Environment { - HashTable *table; + struct Object **locals; struct Environment *parent; } Environment; @@ -74,6 +73,11 @@ typedef struct Parser { typedef Object* Root; +typedef struct Program { + Root *roots; + Environment *env; +} Program; + // Token scanner. Token next_token(Parser *parser); Token previous_token(Parser *parser); @@ -91,7 +95,7 @@ Object * parse_list(Parser *parser, Errors *errors); Object * parse_lambda(Parser *parser, Errors *errors); Object * parse_if(Parser *parser, Errors *errors); Object * parse_var(Parser *parser, Errors *errors); -Root * parse(Token *tokens, Errors *errors); +Program parse(Token *tokens, Errors *errors); // Object operations. void object_display(Object *obj); -- cgit v1.2.1