Added lookup of vars, start commenting
parent
398bdc9487
commit
fab7d8916e
|
@ -1,6 +1,6 @@
|
||||||
#include <vslc.h>
|
#include <vslc.h>
|
||||||
|
|
||||||
|
#define ERRPRT(format, args...) {fprintf(stderr, "[ERROR] "); fprintf(stderr ,format, ##args);}
|
||||||
|
|
||||||
|
|
||||||
// Externally visible, for the generator
|
// Externally visible, for the generator
|
||||||
|
@ -42,49 +42,13 @@ create_symbol_table ( void )
|
||||||
symbol_t **global_list = malloc(no_globals * sizeof(symbol_t));
|
symbol_t **global_list = malloc(no_globals * sizeof(symbol_t));
|
||||||
tlhash_values(global_names, (void **)global_list );
|
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++ )
|
for (uint64_t g = 0; g < no_globals; g++ )
|
||||||
{
|
{
|
||||||
if (global_list[g]->type == SYM_FUNCTION)
|
if (global_list[g]->type == SYM_FUNCTION)
|
||||||
bind_names(global_list[g], global_list[g]->node);
|
bind_names(global_list[g], global_list[g]->node);
|
||||||
}
|
}
|
||||||
free(global_list);
|
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)
|
if (!global)
|
||||||
return;
|
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)
|
if (!global->nparms && !global->locals)
|
||||||
return;
|
{putchar('\n');return;}
|
||||||
|
|
||||||
uint64_t no_locals = tlhash_size(global->locals);
|
uint64_t no_locals = tlhash_size(global->locals);
|
||||||
symbol_t **locals_list = malloc(no_locals * sizeof(symbol_t));
|
symbol_t **locals_list = malloc(no_locals * sizeof(symbol_t));
|
||||||
tlhash_values(global->locals, (void **)locals_list );
|
tlhash_values(global->locals, (void **)locals_list );
|
||||||
for (int l = 0; l < no_locals; l++)
|
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)) ? "├" : "└",
|
(l < (no_locals - 1)) ? "├" : "└",
|
||||||
symbol_names[locals_list[l]->type],
|
symbol_names[locals_list[l]->type],
|
||||||
locals_list[l]->name,
|
locals_list[l]->name,
|
||||||
locals_list[l]->seq
|
locals_list[l]->seq,
|
||||||
|
locals_list[l]->node
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
|
@ -176,27 +147,37 @@ destroy_global(symbol_t* global)
|
||||||
void
|
void
|
||||||
destroy_symbol_table ( void )
|
destroy_symbol_table ( void )
|
||||||
{
|
{
|
||||||
//return;
|
// FREE STRINGS
|
||||||
/* TODO: release memory allocated to the symbol table */
|
// Free all strings that are kept in the array
|
||||||
for (uint64_t c = 0; c < stringc; c++)
|
for (uint64_t c = 0; c < stringc; c++)
|
||||||
free(string_list[c]);
|
free(string_list[c]);
|
||||||
|
// Free the actual list
|
||||||
free(string_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(scopes);
|
||||||
|
|
||||||
|
// FREE GLOBAL NAMES
|
||||||
if (!global_names)
|
if (!global_names)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Fetch list of globals
|
||||||
uint64_t no_globals = tlhash_size(global_names);
|
uint64_t no_globals = tlhash_size(global_names);
|
||||||
symbol_t **global_list = malloc(no_globals * sizeof(symbol_t));
|
symbol_t **global_list = malloc(no_globals * sizeof(symbol_t));
|
||||||
tlhash_values(global_names, (void **)global_list );
|
tlhash_values(global_names, (void **)global_list );
|
||||||
|
|
||||||
|
// Destroy all global elements
|
||||||
for (uint64_t g = 0; g < no_globals; g++)
|
for (uint64_t g = 0; g < no_globals; g++)
|
||||||
destroy_global(global_list[g]);
|
destroy_global(global_list[g]);
|
||||||
|
|
||||||
|
// Destory the global hash table
|
||||||
tlhash_finalize(global_names);
|
tlhash_finalize(global_names);
|
||||||
|
// Free the global hash table
|
||||||
free(global_names);
|
free(global_names);
|
||||||
|
|
||||||
|
// Free the temp list
|
||||||
free(global_list);
|
free(global_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +191,6 @@ void
|
||||||
find_globals ( void )
|
find_globals ( void )
|
||||||
{
|
{
|
||||||
tlhash_init(global_names = malloc(sizeof(tlhash_t)), GLOBAL_BUCKET_SIZE);
|
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;
|
uint64_t no_functions = 0;
|
||||||
node_t *global_list = root;
|
node_t *global_list = root;
|
||||||
|
@ -311,7 +291,7 @@ push_scope(void)
|
||||||
tlhash_t **new_scopes = realloc(scopes, no_scopes * sizeof(tlhash_t));
|
tlhash_t **new_scopes = realloc(scopes, no_scopes * sizeof(tlhash_t));
|
||||||
if (!new_scopes)
|
if (!new_scopes)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "[ERROR] Could not realloc scopes!\n");
|
ERRPRT("Could not realloc scopes!\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
scopes = new_scopes;
|
scopes = new_scopes;
|
||||||
|
@ -323,7 +303,6 @@ pop_scope(void)
|
||||||
{
|
{
|
||||||
tlhash_finalize(scopes[--cur_scope_depth]);
|
tlhash_finalize(scopes[--cur_scope_depth]);
|
||||||
free(scopes[cur_scope_depth]);
|
free(scopes[cur_scope_depth]);
|
||||||
//scopes[cur_scope_depth] = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -336,10 +315,10 @@ void
|
||||||
insert_local_to_func(symbol_t *function, symbol_t *root)
|
insert_local_to_func(symbol_t *function, symbol_t *root)
|
||||||
{
|
{
|
||||||
tlhash_insert(
|
tlhash_insert(
|
||||||
function->locals, //! Insert local to the function var table
|
function->locals, //! Insert local to the function var table
|
||||||
&root->seq, //! The key is a number, unique, strictly growing
|
&root->seq, //! The key is a number, unique, strictly growing
|
||||||
sizeof(root->seq), //! Size of key
|
sizeof(root->seq), //! Size of key
|
||||||
root //! The local symbol
|
root //! The local symbol
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,7 +332,7 @@ insert_local_var(symbol_t *function, node_t *root)
|
||||||
.type = SYM_LOCAL_VAR,
|
.type = SYM_LOCAL_VAR,
|
||||||
.name = root->data,
|
.name = root->data,
|
||||||
.node = root,
|
.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,
|
.nparms = 0,
|
||||||
.locals = NULL
|
.locals = NULL
|
||||||
};
|
};
|
||||||
|
@ -377,13 +356,43 @@ collect_string(node_t *root)
|
||||||
char **new_string_list = realloc(string_list, n_string_list * sizeof(char*));
|
char **new_string_list = realloc(string_list, n_string_list * sizeof(char*));
|
||||||
if (!new_string_list)
|
if (!new_string_list)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "[ERROR] Could not realloc string list!\n");
|
ERRPRT("Could not realloc string list!\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
string_list = new_string_list;
|
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
|
void
|
||||||
bind_names ( symbol_t *function, node_t *root )
|
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++)
|
for (uint64_t i = 0; i < declarations->n_children; i++)
|
||||||
// Insert each of the local variables in the declaration
|
// Insert each of the local variables in the declaration
|
||||||
insert_local_var(function, declarations->children[i]);
|
insert_local_var(function, declarations->children[i]);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDENTIFIER_DATA:
|
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;
|
break;
|
||||||
|
|
||||||
case STRING_DATA:
|
case STRING_DATA:
|
||||||
|
|
Loading…
Reference in New Issue