diff --git a/exercises/04/vslc/src/ir.c b/exercises/04/vslc/src/ir.c index f79546c..2fbad61 100644 --- a/exercises/04/vslc/src/ir.c +++ b/exercises/04/vslc/src/ir.c @@ -1,6 +1,6 @@ #include - +#define ERRPRT(format, args...) {fprintf(stderr, "[ERROR] "); fprintf(stderr ,format, ##args);} // Externally visible, for the generator @@ -42,49 +42,13 @@ create_symbol_table ( void ) symbol_t **global_list = malloc(no_globals * sizeof(symbol_t)); tlhash_values(global_names, (void **)global_list ); - /* Iterate over the temporary list, printing entries */ + /* Iterate over the temporary list, bind names in each function */ for (uint64_t g = 0; g < no_globals; g++ ) { if (global_list[g]->type == SYM_FUNCTION) bind_names(global_list[g], global_list[g]->node); } free(global_list); - - /* TODO: traverse the syntax tree and create the symbol table */ - -/* - // ! Example code solely to demonstrate usage of tlhash. Make sure to remove - // ! or comment this out when implementing your solution. - - // Initialize table - tlhash_t *my_table = (tlhash_t*)malloc(sizeof(tlhash_t)); - tlhash_init(my_table, 64); - - char *my_key0 = "key"; // Keep in mind that these are stack allocated for simplicity, yours should not - char *my_val0 = "valuable"; // Also, I'm using strings as values, you will be using symbol_t pointers - char *my_key1 = "another_key"; - char *my_val1 = "more valuable"; - - // Insert some values to the table. Remember that the length of a string - // interpreted as an array is the string length plus one '\0' character - tlhash_insert(my_table, my_key0, strlen(my_key0)+1, my_val0); - tlhash_insert(my_table, my_key1, strlen(my_key1)+1, my_val1); - - // Iterate keys and lookup their values - size_t size = tlhash_size(my_table); - char **keys = (char **)malloc(size); - tlhash_keys(my_table, keys); - char *val; - for (int i = 0; i < size; i++) { - tlhash_lookup(my_table, keys[i], strlen(keys[i])+1, &val); - printf("my_table[%s] = \"%s\"\n", keys[i], val); - } - - // Free allocated memory when done with the symbol table - tlhash_finalize(my_table); - free(my_table); - free(keys); -*/ } @@ -95,21 +59,28 @@ print_global_tree(symbol_t* global) if (!global) return; - printf("─%s(%s, %ld)\n", symbol_names[global->type], global->name, global->seq); + printf("─%s(%s, nparams=%ld, seq=%ld, node=%p)\n", + symbol_names[global->type], + global->name, + global->nparms, + global->seq, + global->node + ); if (!global->nparms && !global->locals) - return; + {putchar('\n');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", + printf(" %s─%s(%s, seq=%ld, node=%p)\n", (l < (no_locals - 1)) ? "├" : "└", symbol_names[locals_list[l]->type], locals_list[l]->name, - locals_list[l]->seq + locals_list[l]->seq, + locals_list[l]->node ); } putchar('\n'); @@ -176,27 +147,37 @@ destroy_global(symbol_t* global) void destroy_symbol_table ( void ) { - //return; - /* TODO: release memory allocated to the symbol table */ + // FREE STRINGS + // Free all strings that are kept in the array for (uint64_t c = 0; c < stringc; c++) free(string_list[c]); + // Free the actual list free(string_list); + // FREE SCOPES + // At the end of program, all scopes have to be popped + // Therefore only free the list free(scopes); + // FREE GLOBAL NAMES if (!global_names) return; + // Fetch list of globals 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 ); + // Destroy all global elements for (uint64_t g = 0; g < no_globals; g++) destroy_global(global_list[g]); + // Destory the global hash table tlhash_finalize(global_names); + // Free the global hash table free(global_names); + // Free the temp list free(global_list); } @@ -210,7 +191,6 @@ void find_globals ( void ) { tlhash_init(global_names = malloc(sizeof(tlhash_t)), GLOBAL_BUCKET_SIZE); - /* TODO: Populate symbol table with global variables and functions */ uint64_t no_functions = 0; node_t *global_list = root; @@ -311,7 +291,7 @@ push_scope(void) tlhash_t **new_scopes = realloc(scopes, no_scopes * sizeof(tlhash_t)); if (!new_scopes) { - fprintf(stderr, "[ERROR] Could not realloc scopes!\n"); + ERRPRT("Could not realloc scopes!\n"); exit(EXIT_FAILURE); } scopes = new_scopes; @@ -323,7 +303,6 @@ pop_scope(void) { tlhash_finalize(scopes[--cur_scope_depth]); free(scopes[cur_scope_depth]); - //scopes[cur_scope_depth] = NULL; } void @@ -336,10 +315,10 @@ void insert_local_to_func(symbol_t *function, symbol_t *root) { tlhash_insert( - function->locals, //! Insert local to the function var table - &root->seq, //! The key is a number, unique, strictly growing - sizeof(root->seq), //! Size of key - root //! The local symbol + function->locals, //! Insert local to the function var table + &root->seq, //! The key is a number, unique, strictly growing + sizeof(root->seq), //! Size of key + root //! The local symbol ); } @@ -353,7 +332,7 @@ insert_local_var(symbol_t *function, node_t *root) .type = SYM_LOCAL_VAR, .name = root->data, .node = root, - .seq = sequence, //! Use sequence as name in var list of function, strictly growing + .seq = sequence, //! Use sequence as name in var list of function, strictly growing .nparms = 0, .locals = NULL }; @@ -377,13 +356,43 @@ collect_string(node_t *root) char **new_string_list = realloc(string_list, n_string_list * sizeof(char*)); if (!new_string_list) { - fprintf(stderr, "[ERROR] Could not realloc string list!\n"); + ERRPRT("Could not realloc string list!\n"); exit(EXIT_FAILURE); } string_list = new_string_list; } } +static symbol_t* +lookup_var(symbol_t *function, char* var) +{ + // Symbol to store the stymbol to be found + symbol_t* symbol = NULL; + // Result stores the result of the hash lookups + int result; + + // Try the local scopes first + for (int64_t d = cur_scope_depth - 1; d >= 0; d--) + { + result = tlhash_lookup(scopes[d], var, strlen(var), (void**)&symbol); + if (result == TLHASH_SUCCESS) + return symbol; + } + + // Then move to parameters + result = tlhash_lookup(function->locals, var, strlen(var), (void**)&symbol); + if (result == TLHASH_SUCCESS) + return symbol; + + // Last try global parameters + result = tlhash_lookup(global_names, var, strlen(var), (void**)&symbol); + if (result == TLHASH_SUCCESS) + return symbol; + + // If nothing is found, return NULL + return NULL; +} + void bind_names ( symbol_t *function, node_t *root ) { @@ -413,11 +422,18 @@ bind_names ( symbol_t *function, node_t *root ) for (uint64_t i = 0; i < declarations->n_children; i++) // Insert each of the local variables in the declaration insert_local_var(function, declarations->children[i]); - + break; case IDENTIFIER_DATA: + if (!root->data) + break; + if (!(root->entry = lookup_var(function, root->data))) + { + ERRPRT("Could not find %s in scope!\n", (char*)root->data) + exit(EXIT_FAILURE); + } break; case STRING_DATA: