diff --git a/exercises/04/vslc/src/ir.c b/exercises/04/vslc/src/ir.c index 2448e39..00f9ca7 100644 --- a/exercises/04/vslc/src/ir.c +++ b/exercises/04/vslc/src/ir.c @@ -14,6 +14,15 @@ static void find_globals ( void ); * @param root Function's root node */ static void bind_names ( symbol_t *function, node_t *root ); +/* Helper functions */ +void print_global_tree(symbol_t* global); +void insert_symbol(tlhash_t *hash_table, symbol_t* symbol); +void push_scope(void); +void pop_scope(void); + +static uint64_t no_scopes, cur_scope_depth; +static tlhash_t **scopes; + void create_symbol_table ( void ) { @@ -23,6 +32,10 @@ create_symbol_table ( void ) n_string_list = DEFAULT_STRING_LIST_SIZE; stringc = 0; + no_scopes = DEFAULT_NO_SCOPES; + cur_scope_depth = 0; + scopes = malloc(no_scopes * sizeof(tlhash_t)); + find_globals(); /* TODO: traverse the syntax tree and create the symbol table */ @@ -62,30 +75,105 @@ create_symbol_table ( void ) } +const char *symbol_names[4] = {"GLOBAL_VAR", "FUNCTION", "PARAMETER", "LOCAL_VAR"}; +void +print_global_tree(symbol_t* global) +{ + if (!global) + return; + + printf("ā”€%s(%s, %ld)\n", symbol_names[global->type], global->name, global->seq); + + if (!global->nparms && !global->locals) + return; + + uint64_t no_locals = tlhash_size(global->locals); + symbol_t **locals_list = malloc(no_locals * sizeof(symbol_t)); + tlhash_values(global->locals, (void **)locals_list ); + for (int l = 0; l < no_locals; l++) + { + printf(" %sā”€%s(%s, %ld)\n", + (l < (global->nparms - 1)) ? "ā”œ" : "ā””", + symbol_names[locals_list[l]->type], + locals_list[l]->name, + locals_list[l]->seq + ); + } + //putchar('\n'); + free(locals_list); +} + + void print_symbol_table ( void ) { /* TODO: output its contents */ /* Get the number of symbols, size up a temporary list and fill it */ uint64_t no_globals = tlhash_size(global_names); - symbol_t *global_list[no_globals]; - tlhash_values(global_names, (void **)&global_list ); + symbol_t **global_list = malloc(no_globals * sizeof(symbol_t)); + tlhash_values(global_names, (void **)global_list ); /* Iterate over the temporary list, printing entries */ for (uint64_t g = 0; g < no_globals; g++ ) { - printf("global: %s\n", global_list[g]->name ); - + //printf("global: %s\n", global_list[g]->name ); + print_global_tree(global_list[g]); } + free(global_list); +} + +void +destroy_global(symbol_t* global) +{ + if (!global) + return; + if (!global->locals) + { + free(global); + return; + } + + uint64_t no_locals = tlhash_size(global->locals); + symbol_t **locals_list = malloc(no_locals * sizeof(symbol_t)); + tlhash_values(global->locals, (void **)locals_list ); + + for (int l = 0; l < no_locals; l++) + free(locals_list[l]); + + tlhash_finalize(global->locals); + free(global->locals); + free(global); + + free(locals_list); } void destroy_symbol_table ( void ) { + //return; /* TODO: release memory allocated to the symbol table */ + for (uint64_t c = 0; c < stringc; c++) + free(string_list[c]); + free(string_list); + + if (!global_names) + return; + + uint64_t no_globals = tlhash_size(global_names); + symbol_t **global_list = malloc(no_globals * sizeof(symbol_t)); + tlhash_values(global_names, (void **)global_list ); + + for (uint64_t g = 0; g < no_globals; g++) + destroy_global(global_list[g]); + + tlhash_finalize(global_names); + free(global_names); + + free(global_list); } -void insert_symbol(tlhash_t *hash_table, symbol_t* symbol) +void +insert_symbol(tlhash_t *hash_table, symbol_t* symbol) { tlhash_insert(hash_table, symbol->name, strlen(symbol->name), symbol); } @@ -182,9 +270,67 @@ find_globals ( void ) } +void +push_scope(void) +{ + scopes[cur_scope_depth] = malloc(sizeof(tlhash_t)); + tlhash_init(scopes[cur_scope_depth++], LOCAL_BUCKET_SIZE); + + if (cur_scope_depth >= no_scopes) + { + no_scopes *= 2; + tlhash_t **new_scopes = realloc(scopes, no_scopes * sizeof(tlhash_t)); + if (!new_scopes) + { + fprintf(stderr, "[ERROR] Could not realloc scopes!\n"); + exit(EXIT_FAILURE); + } + scopes = new_scopes; + } +} + +void +pop_scope(void) +{ + tlhash_finalize(scopes[--cur_scope_depth]); + free(scopes[cur_scope_depth]); + //scopes[cur_scope_depth] = NULL; +} + void bind_names ( symbol_t *function, node_t *root ) { /* TODO: Bind names and string literals in local symbol table */ + if (!function) + return; + if (!root) + return; + + // We want do top to bottom traverse, so do not + // call recusivly unless we need to go deeper + switch (root->type) + { + case BLOCK: + push_scope(); + for (uint64_t i = 0; i < root->n_children; i++) + bind_names(function, root->children[i]); + pop_scope(); + case DECLARATION_LIST: + + /* code */ + break; + + case IDENTIFIER_DATA: + + break; + + case STRING_DATA: + break; + + default: + for (uint64_t i = 0; i < root->n_children; i++) + bind_names(function, root->children[i]); + break; + } }