From 71f757ecdcece890da2ab0f60244573c9efb1175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind?= Date: Thu, 31 Mar 2022 21:33:52 +0200 Subject: [PATCH] Moved my files into project --- exercises/05/.gitignore | 14 + exercises/05/vslc/include/ir.h | 41 +- exercises/05/vslc/include/vslc.h | 1 + exercises/05/vslc/src/ir.c | 826 ++++++++++++++++++++----------- exercises/05/vslc/src/parser.y | 445 +++++++++++------ exercises/05/vslc/src/tree.c | 307 +++++++++--- exercises/05/vslc/src/vslc | Bin 111552 -> 0 bytes exercises/05/vslc/src/vslc.c | 23 +- 8 files changed, 1125 insertions(+), 532 deletions(-) create mode 100644 exercises/05/.gitignore delete mode 100644 exercises/05/vslc/src/vslc diff --git a/exercises/05/.gitignore b/exercises/05/.gitignore new file mode 100644 index 0000000..c705657 --- /dev/null +++ b/exercises/05/.gitignore @@ -0,0 +1,14 @@ +# Buildfiles +*.o +vslc/src/vslc +parser.c +scanner.c +y.tab.h + +# Submission +*.tar.xz + +# VSL treefiles +*.ast +*.sast +*.sym \ No newline at end of file diff --git a/exercises/05/vslc/include/ir.h b/exercises/05/vslc/include/ir.h index 78150e1..66224e9 100644 --- a/exercises/05/vslc/include/ir.h +++ b/exercises/05/vslc/include/ir.h @@ -10,21 +10,42 @@ typedef struct n { struct n **children; } node_t; -// Export the initializer function, it is needed by the parser -void node_init ( - node_t *nd, node_index_t type, void *data, uint64_t n_children, ... +/**Export the initializer function, it is needed by the parser + * @param *nd node to initialize + * @param type type of node (see nodetype.h) + * @param *data associated data. Declared void to allow any type + * @param n_children number of children + * @param ... variable argument list of child nodes (node_t *) + * + * @return Pointer to the initialized node + * */ +node_t* node_init ( + node_t* nd, + node_index_t type, + void* data, + uint64_t n_children, + ... ); typedef enum { - SYM_GLOBAL_VAR, SYM_FUNCTION, SYM_PARAMETER, SYM_LOCAL_VAR + SYM_GLOBAL_VAR, + SYM_FUNCTION, + SYM_PARAMETER, + SYM_LOCAL_VAR } symtype_t; typedef struct s { - char *name; - symtype_t type; - node_t *node; - size_t seq; - size_t nparms; - tlhash_t *locals; + char* name; + symtype_t type; + node_t* node; + size_t seq; + size_t nparms; + tlhash_t* locals; } symbol_t; #endif + +#define GLOBAL_BUCKET_SIZE 32 +#define LOCAL_BUCKET_SIZE 16 + +#define DEFAULT_STRING_LIST_SIZE 8 +#define DEFAULT_NO_SCOPES 1 diff --git a/exercises/05/vslc/include/vslc.h b/exercises/05/vslc/include/vslc.h index 1e4d9aa..8907763 100644 --- a/exercises/05/vslc/include/vslc.h +++ b/exercises/05/vslc/include/vslc.h @@ -25,6 +25,7 @@ int yyerror ( const char *error ); /* These are defined in the parser generated by bison */ extern int yylineno; extern int yylex ( void ); +extern int yylex_destroy( void ); extern char yytext[]; /* Global state */ diff --git a/exercises/05/vslc/src/ir.c b/exercises/05/vslc/src/ir.c index ae5ea61..33243ab 100644 --- a/exercises/05/vslc/src/ir.c +++ b/exercises/05/vslc/src/ir.c @@ -1,336 +1,602 @@ #include +#define ERRPRT(format, args...) {fprintf(stderr, "[ERROR] "); fprintf(stderr ,format, ##args);} + + // Externally visible, for the generator extern tlhash_t *global_names; extern char **string_list; extern size_t n_string_list, stringc; +// Functions from the skeleton -// Implementation choices, only relevant internally -static void find_globals ( void ); +static uint64_t find_globals ( void ); static void bind_names ( symbol_t *function, node_t *root ); -static void print_symbols ( tlhash_t *table ); -static void destroy_symtab ( void ); -// Internal details of name resolution -static size_t n_scopes = 1, scope_depth = 0; -static tlhash_t **scopes = NULL; +// Helper functions, see description in the definition -/* External interface */ +static void print_global_tree(symbol_t* global); +static void print_string_list(void); +static void destroy_global(symbol_t* global); +static void push_scope(void); +static void pop_scope(void); +static void insert_symbol(tlhash_t *hash_table, symbol_t* symbol); +static void insert_local_to_scope(symbol_t *local); +static void insert_local_to_func(symbol_t *function, symbol_t *root); +static void insert_local_var(symbol_t *function, node_t *root); +static void collect_string(node_t *root); +static symbol_t* lookup_var(symbol_t *function, char* var); +// Local "global" variables +static const char *symbol_names[4] = { + "GLOBAL_VAR", + "FUNCTION", + "PARAMETER", + "LOCAL_VAR" +}; +static uint64_t no_scopes, cur_scope_depth; +static tlhash_t **scopes; + + +/** + * Gather information and create a symbol table. + * + * Used in vslc.c + */ void create_symbol_table ( void ) { - find_globals(); - size_t n_globals = tlhash_size ( global_names ); - symbol_t *global_list[n_globals]; - tlhash_values ( global_names, (void **)&global_list ); - for ( size_t i=0; itype == SYM_FUNCTION ) - bind_names ( global_list[i], global_list[i]->node ); + + // Initialize string array + n_string_list = DEFAULT_STRING_LIST_SIZE; + string_list = malloc(n_string_list * sizeof(char*)); + stringc = 0; + + // Initialize scope array + no_scopes = DEFAULT_NO_SCOPES; + scopes = malloc(no_scopes * sizeof(tlhash_t)); + cur_scope_depth = 0; + + // Traverse the root node for globals + uint64_t no_globals = find_globals(); + + // Prepare a temp list of globals and fetch all globals + symbol_t **global_list = malloc(no_globals * sizeof(symbol_t)); + tlhash_values(global_names, (void **)global_list ); + + /* 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 the temp list + free(global_list); } +/** + * Prints the symbol table and the string array + * + * Used in vslc.c + */ void print_symbol_table ( void ) { - print_symbols ( global_names ); + /* 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 = 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++ ) + // Print the tree structure for each global + print_global_tree(global_list[g]); + + free(global_list); + + // Print strings + print_string_list(); } +/** + * Prins the tree of a global + * + * @param global pointer to the global to be printed + */ +static void +print_global_tree(symbol_t* global) +{ + // Check if null ptr + if (!global) + return; + + // Print global root + printf("─%s: %-16s [nparams=%2ld, seq=%2ld, node=%p]\n", + symbol_names[global->type], + global->name, + global->nparms, + global->seq, + global->node + ); + + // If the global does not have params or locals, return + if (!global->nparms && !global->locals) + {putchar('\n');return;} + + // Need to fetch the whole size, since nparams + // only count the params, not all locals + 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 ); + // Go through all locals + for (int l = 0; l < no_locals; l++) + { // Do some simple sorting, so seq num is in order + for (int ll = 0; ll < no_locals; ll++) + { + if (locals_list[ll]->seq == l) + { + printf(" %s─[%s]: %-22s\t[seq=%2ld, node=%p]\n", + (l < (no_locals - 1)) ? "├" : "└", + symbol_names[locals_list[ll]->type], + locals_list[ll]->name, + locals_list[ll]->seq, + locals_list[ll]->node + ); + break; + } + } + } + putchar('\n'); + free(locals_list); +} + + +/** + * Prints the array of strings + * + */ +static void +print_string_list(void) +{ // Print out all the collected strings + printf("─STRINGS [%ld]\n", stringc); + for (uint64_t i = 0; i < stringc; i++) + printf(" %s─[%ld]: %s\n", + (i < (stringc - 1)) ? "├" : "└", + i, + string_list[i] + ); +} + + +/** + * Destroys all the dynamicly allocated memory and all the hash tables. + * Frees up the array of strings as well. + * + * Used in vslc.c + */ void destroy_symbol_table ( void ) { - destroy_symtab(); -} + // 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); -/* Internal matters */ + // FREE SCOPES + // At the end of program, all scopes have to be popped + // Therefore only free the list + free(scopes); - -static void -print_symbols ( tlhash_t *table ) -{ - if ( table == NULL ) + // FREE GLOBAL NAMES + if (!global_names) return; - size_t n_entries = tlhash_size(table); - symbol_t *entry_list[n_entries]; - tlhash_values ( table, (void **)&entry_list ); - for ( size_t e=0; etype ) - { - case SYM_FUNCTION: - fprintf ( stderr, "function: %s\n", entry_list[e]->name ); - if ( entry_list[e]->type == SYM_FUNCTION ) - print_symbols ( entry_list[e]->locals ); - break; - case SYM_GLOBAL_VAR: - fprintf ( stderr, "global var: %s\n", entry_list[e]->name ); - break; - case SYM_PARAMETER: - fprintf ( stderr, "parameter: %s\n", entry_list[e]->name ); - break; - case SYM_LOCAL_VAR: - fprintf ( stderr, "local var: %s\n", entry_list[e]->name ); - break; - default: - /* This should never happen if all symbols have correct type */ - fprintf ( stderr, - "** Unknown symbol: %s\n", entry_list[e]->name - ); - break; - } - } + + // 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); } -static void -add_global ( symbol_t *symbol ) +/** + * Destroys the supplied global symbol by + * finalizing each of the local tables + * + * @param global pointer to the global symbol to be destroyed + */ +static void +destroy_global(symbol_t* global) { - tlhash_insert ( - global_names, symbol->name, strlen(symbol->name), symbol - ); + 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); } -static void +/** + * Goes trough the root node and finds all global variables and functions + * + * @return Returns the number of globals found (functions + variables) + */ +static uint64_t find_globals ( void ) { - global_names = malloc ( sizeof(tlhash_t) ); - tlhash_init ( global_names, 32 ); - string_list = malloc ( n_string_list * sizeof(char * ) ); - size_t n_functions = 0; + tlhash_init(global_names = malloc(sizeof(tlhash_t)), GLOBAL_BUCKET_SIZE); - node_t *global_list = root->children[0]; - for ( uint64_t g=0; gn_children; g++ ) + uint64_t no_functions = 0, no_global_vars = 0; + node_t *global_list = root; + + // Check if not nullptr + if (!global_list) + return 0; + + symbol_t* global_symbol; + for (uint64_t global_i = 0; global_i < global_list->n_children; global_i++) { - node_t *global = global_list->children[g], *namelist; - symbol_t *symbol; - switch ( global->type ) + node_t *current_global = global_list->children[global_i]; + switch (current_global->type) { - case FUNCTION: - symbol = malloc ( sizeof(symbol_t) ); - *symbol = (symbol_t) { - .type = SYM_FUNCTION, - .name = global->children[0]->data, - .node = global->children[2], - .seq = n_functions, - .nparms = 0, - .locals = malloc ( sizeof(tlhash_t) ) - }; - n_functions++; + case VARIABLE_LIST: - tlhash_init ( symbol->locals, 32 ); - if ( global->children[1] != NULL ) - { - symbol->nparms = global->children[1]->n_children; - for ( int p=0; pnparms; p++ ) - { - node_t *param = global->children[1]->children[p]; - symbol_t *psym = malloc ( sizeof(symbol_t) ); - *psym = (symbol_t) { - .type = SYM_PARAMETER, - .name = param->data, - .node = NULL, - .seq = p, - .nparms = 0, - .locals = NULL - }; - tlhash_insert ( - symbol->locals, psym->name, strlen(psym->name), psym - ); - } - } - add_global ( symbol ); - break; - case DECLARATION: - namelist = global->children[0]; - for ( uint64_t d=0; dn_children; d++ ) - { - symbol = malloc ( sizeof(symbol_t) ); - *symbol = (symbol_t) { - .type = SYM_GLOBAL_VAR, - .name = namelist->children[d]->data, - .node = NULL, - .seq = 0, - .nparms = 0, - .locals = NULL - }; - add_global(symbol); - } - break; - } - } -} - - -static void -push_scope ( void ) -{ - if ( scopes == NULL ) - scopes = malloc ( n_scopes * sizeof(tlhash_t *) ); - tlhash_t *new_scope = malloc ( sizeof(tlhash_t) ); - tlhash_init ( new_scope, 32 ); - scopes[scope_depth] = new_scope; - - scope_depth += 1; - if ( scope_depth >= n_scopes ) - { - n_scopes *= 2; - scopes = realloc ( scopes, n_scopes*sizeof(tlhash_t **) ); - } - -} - - -static void -add_local ( symbol_t *local ) -{ - tlhash_insert ( - scopes[scope_depth-1],local->name,strlen(local->name),local - ); -} - - -static symbol_t * -lookup_local ( char *name ) -{ - symbol_t *result = NULL; - size_t depth = scope_depth; - while ( result == NULL && depth > 0 ) - { - depth -= 1; - tlhash_lookup ( scopes[depth], name, strlen(name), (void **)&result ); - } - return result; -} - - -static void -pop_scope ( void ) -{ - scope_depth -= 1; - tlhash_finalize ( scopes[scope_depth] ); - free ( scopes[scope_depth] ); - scopes[scope_depth] = NULL; -} - - -static void -add_string ( node_t *string ) -{ - string_list[stringc] = string->data; - string->data = malloc ( sizeof(size_t) ); - *((size_t *)string->data) = stringc; - stringc++; - if ( stringc >= n_string_list ) - { - n_string_list *= 2; - string_list = realloc ( string_list, n_string_list * sizeof(char *) ); - } - -} - - -static void -bind_names ( symbol_t *function, node_t *root ) -{ - if ( root == NULL ) - return; - else switch ( root->type ) - { - node_t *namelist; - symbol_t *entry; - - case BLOCK: - push_scope(); - for ( size_t c=0; cn_children; c++ ) - bind_names ( function, root->children[c] ); - pop_scope(); - break; - - case DECLARATION: - namelist = root->children[0]; - for ( uint64_t d=0; dn_children; d++ ) + // Go through the variable list and get all the global variables + for (uint64_t var_i = 0; var_i < current_global->n_children; var_i++) { - node_t *varname = namelist->children[d]; - size_t local_num = - tlhash_size(function->locals) - function->nparms; - symbol_t *symbol = malloc ( sizeof(symbol_t) ); - *symbol = (symbol_t) { - .type = SYM_LOCAL_VAR, - .name = varname->data, - .node = NULL, - .seq = local_num, + global_symbol = malloc(sizeof(symbol_t)); + *global_symbol = (symbol_t){ + .type = SYM_GLOBAL_VAR, + .name = current_global->children[var_i]->data, + .node = current_global->children[var_i], + .seq = 0, .nparms = 0, .locals = NULL }; - tlhash_insert ( - function->locals, &local_num, sizeof(size_t), symbol - ); - add_local ( symbol ); + insert_symbol(global_names, global_symbol); + no_global_vars++; } break; + case FUNCTION: + node_t *function = current_global; - case IDENTIFIER_DATA: - entry = lookup_local ( root->data ); - if ( entry == NULL ) - tlhash_lookup ( - function->locals, root->data, - strlen(root->data), (void**)&entry - ); - if ( entry == NULL ) - tlhash_lookup ( - global_names,root->data,strlen(root->data),(void**)&entry - ); - if ( entry == NULL ) + // Function node allways have the same structure, + // [0] are the identifier + // [1] are the variable list, within a paramerer_list + // [2] are the actual block + if (!function->children[0]) + break; + + // Create the function symbol + global_symbol = malloc(sizeof(symbol_t)); + *global_symbol = (symbol_t){ + .type = SYM_FUNCTION, + .name = current_global->children[0]->data, + .node = current_global->children[2], + .seq = no_functions++, + .nparms = 0, + .locals = malloc(sizeof(tlhash_t)) + }; + + // Initialize the local variable table + tlhash_init(global_symbol->locals, LOCAL_BUCKET_SIZE); + + // Insert the pointer to the newly created symbol + insert_symbol(global_names, global_symbol); + + // If there are no parameters in function, break. + if (!current_global->children[1]->n_children) + break; + + + // Find all params and insert into hash table in global_symbol + symbol_t *param_sym; + node_t *param_list = current_global->children[1]->children[0]; + global_symbol->nparms = param_list->n_children; + + for (uint64_t param_i = 0; param_i < param_list->n_children; param_i++) { - fprintf ( stderr, "Identifier '%s' does not exist in scope\n", - (char *)root->data - ); - exit ( EXIT_FAILURE ); + param_sym = malloc(sizeof(symbol_t)); + *param_sym = (symbol_t){ + .type = SYM_PARAMETER, + .name = param_list->children[param_i]->data, + .node = param_list->children[param_i], + .seq = param_i, + .nparms = 0, + .locals = NULL + }; + + insert_symbol(global_symbol->locals, param_sym); } - root->entry = entry; break; - - case STRING_DATA: - add_string ( root ); - break; - - default: - for ( size_t c=0; cn_children; c++ ) - bind_names ( function, root->children[c] ); - break; - } -} - - -void -destroy_symtab ( void ) -{ - for ( size_t i=0; ilocals != NULL ) - { - size_t n_locals = tlhash_size ( glob->locals ); - symbol_t *locals[n_locals]; - tlhash_values ( glob->locals, (void **)&locals ); - for ( size_t l=0; llocals ); - free ( glob->locals ); } - free ( glob ); } - tlhash_finalize ( global_names ); - free ( global_names ); - free ( scopes ); + return no_functions + no_global_vars; +} + + +/** + * Inserts a symbol into a hash table, key is defined in the name field in the symbol supplied. + * + * @param hash_table pointer to the hash table the symbol is inserted into + * @param symbol pointer to the symbol to be inserted + */ +void +insert_symbol(tlhash_t *hash_table, symbol_t* symbol) +{ + tlhash_insert(hash_table, symbol->name, strlen(symbol->name), symbol); +} + + +/** + * @brief Traverse a node root, and find all variables and strings + * + * @param function pointer to the current function + * @param root pointer to the root node + */ +static void +bind_names ( symbol_t *function, node_t *root ) +{ // NULL check + if (!function) + return; + if (!root) + return; + + // Can't declare variables inside switch unless + // it is in a new scope + node_t *declarations; + // We want do top to bottom traverse, so do not + // call recusivly unless we need to go deeper + switch (root->type) + { + // If new BLOCK start, push the scope and recurse from here. + case BLOCK: + push_scope(); + for (uint64_t i = 0; i < root->n_children; i++) + bind_names(function, root->children[i]); + pop_scope(); + break; + + // If DECLARATION_LIST, find all the identifiers + // and insert local into scope and function + case DECLARATION_LIST: + if (!root->children[0]) + break; + + declarations = root->children[0]; + 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; + + // If IDENTIFIER_DATA, look up the identifier in all the scopes. + // If not found (NULL), crash the compiler with a somewhat helpful message. + 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; + + // If STRING_DATA, collect the string and point the + // data in the corresponding node to the array index + case STRING_DATA: + collect_string(root); + break; + + // If none of the above, go deeper if possible. + default: + for (uint64_t i = 0; i < root->n_children; i++) + bind_names(function, root->children[i]); + break; + } +} + +/** + * Pushes a new hash table to the scope stack. + * + * Increases the size of the stack if too small. + * + */ +static void +push_scope(void) +{ + // Allocate memory for the hash table and initialize + scopes[cur_scope_depth] = malloc(sizeof(tlhash_t)); + tlhash_init(scopes[cur_scope_depth++], LOCAL_BUCKET_SIZE); + + // Grow the amount of scopes if not enough + if (cur_scope_depth >= no_scopes) + { + no_scopes *= 2; + tlhash_t **new_scopes = realloc(scopes, no_scopes * sizeof(tlhash_t)); + if (!new_scopes) + { + ERRPRT("Could not realloc scopes!\n"); + exit(EXIT_FAILURE); + } + scopes = new_scopes; + } +} + + +/** + * Pops the dynamicy allocated hash table for the current scope depth + * + */ +static void +pop_scope(void) +{ + tlhash_finalize(scopes[--cur_scope_depth]); + free(scopes[cur_scope_depth]); +} + + +/** + * Allocates and inserts a local symbol into + * the scope stack and into the function + * + * @param function pointer to the current function + * @param root pointer to the root node for the symbol + */ +static void +insert_local_var(symbol_t *function, node_t *root) +{ // Null ptr check + if (!root->data) + return; + + // Get the sequence num, is the size + size_t sequence = tlhash_size(function->locals); + + symbol_t *variable = malloc(sizeof(symbol_t)); + *variable = (symbol_t){ + .type = SYM_LOCAL_VAR, + .name = root->data, + .node = root, + .seq = sequence, //! Use sequence as name in var list of function, strictly growing + .nparms = 0, + .locals = NULL + }; + insert_local_to_scope(variable); + insert_local_to_func(function, variable); +} + + +/** + * Inserts a symbol to the top most scope in stack + * + * @param local pointer to the local to be inserted + */ +static void +insert_local_to_scope(symbol_t *local) +{ + insert_symbol(scopes[cur_scope_depth - 1], local); +} + + +/** + * Insert local symbol to the functions table of local variables + * uses the seq num as key as this is strictly growing + * + * @param function pointer to the function to insert the symbol + * @param local pointer to the symbol to be inserted in the table + */ +void +insert_local_to_func(symbol_t *function, symbol_t *local) +{ + tlhash_insert( + function->locals, //! Insert local to the function var table + &local->seq, //! The key is a number, unique, strictly growing + sizeof(local->seq), //! Size of key + local //! The local symbol + ); +} + + +/** + * Collects strings to the string array and + * points the data in the associated node + * to the array position + * + * @param root pointer to the root node of the string + */ +static void +collect_string(node_t *root) +{ // Null ptr check + if (!root->data) + return; + + // Get the string and allocate room for array index of string + string_list[stringc] = root->data; + root->data = malloc(sizeof(size_t)); + // Set the data ptr + *((size_t*)root->data) = stringc++; + + // Grow string array if nessecary + if (stringc >= n_string_list) + { + n_string_list *= 2; + char **new_string_list = realloc(string_list, n_string_list * sizeof(char*)); + if (!new_string_list) + { + ERRPRT("Could not realloc string list!\n"); + exit(EXIT_FAILURE); + } + string_list = new_string_list; + } +} + + +/** + * Looks up a variable identifier in all the scopes. + * Start with the scopes, then the parameters and + * the the globals + * + * @param function pointer to the function + * @param var identifier to the variable + * @return Returns the pointer to the "closest" matched identifier. NULL if not found. + */ +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; } diff --git a/exercises/05/vslc/src/parser.y b/exercises/05/vslc/src/parser.y index f1abcc8..bb05a2a 100644 --- a/exercises/05/vslc/src/parser.y +++ b/exercises/05/vslc/src/parser.y @@ -1,176 +1,303 @@ %{ #include -#define N0C(n,t,d) do { \ - node_init ( n = malloc(sizeof(node_t)), t, d, 0 ); \ -} while ( false ) -#define N1C(n,t,d,a) do { \ - node_init ( n = malloc(sizeof(node_t)), t, d, 1, a ); \ -} while ( false ) -#define N2C(n,t,d,a,b) do { \ - node_init ( n = malloc(sizeof(node_t)), t, d, 2, a, b ); \ -} while ( false ) -#define N3C(n,t,d,a,b,c) do { \ - node_init ( n = malloc(sizeof(node_t)), t, d, 3, a, b, c ); \ -} while ( false ) - +#define NODE(type, data, n_children, children...) node_init(malloc(sizeof(node_t)), type, data, n_children, ##children) %} -%left '|' -%left '^' -%left '&' +%define api.value.type {node_t} +%token FUNC PRINT RETURN CONTINUE IF THEN ELSE WHILE DO OPENBLOCK CLOSEBLOCK +%token VAR NUMBER IDENTIFIER STRING + +%left '|' '&' '^' %left '+' '-' %left '*' '/' %nonassoc UMINUS %right '~' -%expect 1 +//%expect 1 -%token FUNC PRINT RETURN CONTINUE IF THEN ELSE WHILE DO OPENBLOCK CLOSEBLOCK -%token VAR NUMBER IDENTIFIER STRING +%nonassoc IF THEN +%nonassoc ELSE + +/* Tried fixing vscode complaining about the type for the non-terminals, didn't work +%union { + node_t* node; +} + +%type global_list global +%type statement_list print_list expression_list variable_list argument_list parameter_list declaration_list +%type function statement block +%type assignment_statement return_statement print_statement null_statement if_statement while_statement +%type relation expression declaration print_item identifier number string +*/ %% -program : - global_list { N1C ( root, PROGRAM, NULL, $1 ); } - ; -global_list : - global { N1C ( $$, GLOBAL_LIST, NULL, $1 ); } - | global_list global { N2C ( $$, GLOBAL_LIST, NULL, $1, $2 ); } - ; + +program: + global_list { + root = NODE(PROGRAM, NULL, 1, $1); + } + ; + +global_list: + global { + $$ = NODE(GLOBAL_LIST, NULL, 1, $1); + } + | global_list global { + $$ = NODE(GLOBAL_LIST, NULL, 2, $1, $2); + } + ; + global: - function { N1C ( $$, GLOBAL, NULL, $1 ); } - | declaration { N1C ( $$, GLOBAL, NULL, $1 ); } - ; -statement_list : - statement { N1C ( $$, STATEMENT_LIST, NULL, $1 ); } - | statement_list statement { N2C ( $$, STATEMENT_LIST, NULL, $1, $2 ); } - ; -print_list : - print_item { N1C ( $$, PRINT_LIST, NULL, $1 ); } - | print_list ',' print_item { N2C ( $$, PRINT_LIST, NULL, $1, $3 ); } - ; -expression_list : - expression { N1C ( $$, EXPRESSION_LIST, NULL, $1 ); } - | expression_list ',' expression { N2C($$, EXPRESSION_LIST, NULL, $1, $3); } - ; -variable_list : - identifier { N1C ( $$, VARIABLE_LIST, NULL, $1 ); } - | variable_list ',' identifier { N2C ( $$, VARIABLE_LIST, NULL, $1, $3 ); } - ; -argument_list : - expression_list { N1C ( $$, ARGUMENT_LIST, NULL, $1 ); } - | /* epsilon */ { $$ = NULL; } - ; -parameter_list : - variable_list { N1C ( $$, PARAMETER_LIST, NULL, $1 ); } - | /* epsilon */ { $$ = NULL; } - ; -declaration_list : - declaration { N1C ( $$, DECLARATION_LIST, NULL, $1 ); } - | declaration_list declaration { N2C ($$, DECLARATION_LIST, NULL, $1, $2); } - ; -function : - FUNC identifier '(' parameter_list ')' statement - { N3C ( $$, FUNCTION, NULL, $2, $4, $6 ); } - ; -statement : - assignment_statement { N1C ( $$, STATEMENT, NULL, $1 ); } - | return_statement { N1C ( $$, STATEMENT, NULL, $1 ); } - | print_statement { N1C ( $$, STATEMENT, NULL, $1 ); } - | if_statement { N1C ( $$, STATEMENT, NULL, $1 ); } - | while_statement { N1C ( $$, STATEMENT, NULL, $1 ); } - | null_statement { N1C ( $$, STATEMENT, NULL, $1 ); } - | block { N1C ( $$, STATEMENT, NULL, $1 ); } - ; -block : - OPENBLOCK declaration_list statement_list CLOSEBLOCK - { N2C ($$, BLOCK, NULL, $2, $3); } - | OPENBLOCK statement_list CLOSEBLOCK { N1C ($$, BLOCK, NULL, $2 ); } - ; -assignment_statement : - identifier ':' '=' expression - { N2C ( $$, ASSIGNMENT_STATEMENT, NULL, $1, $4 ); } - | identifier '+' '=' expression - { N2C ( $$, ADD_STATEMENT, NULL, $1, $4 ); } - | identifier '-' '=' expression - { N2C ( $$, SUBTRACT_STATEMENT, NULL, $1, $4 ); } - | identifier '*' '=' expression - { N2C ( $$, MULTIPLY_STATEMENT, NULL, $1, $4 ); } - | identifier '/' '=' expression - { N2C ( $$, DIVIDE_STATEMENT, NULL, $1, $4 ); } - ; -return_statement : - RETURN expression - { N1C ( $$, RETURN_STATEMENT, NULL, $2 ); } - ; -print_statement : - PRINT print_list - { N1C ( $$, PRINT_STATEMENT, NULL, $2 ); } - ; -null_statement : - CONTINUE - { N0C ( $$, NULL_STATEMENT, NULL ); } - ; -if_statement : - IF relation THEN statement - { N2C ( $$, IF_STATEMENT, NULL, $2, $4 ); } - | IF relation THEN statement ELSE statement - { N3C ( $$, IF_STATEMENT, NULL, $2, $4, $6 ); } - ; -while_statement : - WHILE relation DO statement - { N2C ( $$, WHILE_STATEMENT, NULL, $2, $4 ); } - ; + function { + $$ = NODE(GLOBAL, NULL, 1, $1); + } + | declaration { + $$ = NODE(GLOBAL, NULL, 1, $1); + } + ; + +statement_list: + statement { + $$ = NODE(STATEMENT_LIST, NULL, 1, $1); + } + | statement_list statement { + $$ = NODE(STATEMENT_LIST, NULL, 2, $1, $2); + } + ; + +print_list: + print_item { + $$ = NODE(PRINT_LIST, NULL, 1, $1); + } + | print_list ',' print_item { + $$ = NODE(PRINT_LIST, NULL, 2, $1, $3); + } + ; + +expression_list: + expression { + $$ = NODE(EXPRESSION_LIST, NULL, 1, $1); + } + | expression_list ',' expression { + $$ = NODE(EXPRESSION_LIST, NULL, 2, $1, $3); + } + ; + +variable_list: + identifier { + $$ = NODE(VARIABLE_LIST, NULL, 1, $1); + } + | variable_list ',' identifier { + $$ = NODE(VARIABLE_LIST, NULL, 2, $1, $3); + } + ; + +argument_list: + expression_list { + $$ = NODE(ARGUMENT_LIST, NULL, 1, $1); + } + | /* epsilon */ { + $$ = NODE(ARGUMENT_LIST, NULL, 0); + } + ; + +parameter_list: + variable_list { + $$ = NODE(PARAMETER_LIST, NULL, 1, $1); + } + | /* epsilon */ { + $$ = NODE(PARAMETER_LIST, NULL, 0); + } + ; + +declaration_list: + declaration { + $$ = NODE(DECLARATION_LIST, NULL, 1, $1); + } + | declaration_list declaration { + $$ = NODE(DECLARATION_LIST, NULL, 2, $1, $2); + } + ; + +function: + FUNC identifier '(' parameter_list ')' statement { + $$ = NODE(FUNCTION, NULL, 3, $2, $4, $6); + } + ; + +statement: + assignment_statement { + $$ = NODE(STATEMENT, NULL, 1, $1); + } + | return_statement { + $$ = NODE(STATEMENT, NULL, 1, $1); + } + | print_statement { + $$ = NODE(STATEMENT, NULL, 1, $1); + } + | if_statement { + $$ = NODE(STATEMENT, NULL, 1, $1); + } + | while_statement { + $$ = NODE(STATEMENT, NULL, 1, $1); + } + | null_statement { + $$ = NODE(STATEMENT, NULL, 1, $1); + } + | block { + $$ = NODE(STATEMENT, NULL, 1, $1); + } + ; + +block: + OPENBLOCK declaration_list statement_list CLOSEBLOCK { + $$ = NODE(BLOCK, NULL, 2, $2, $3); + } + | OPENBLOCK statement_list CLOSEBLOCK { + $$ = NODE(BLOCK, NULL, 1, $2); + } + ; + +assignment_statement: + identifier ':' '=' expression { + $$ = NODE(ASSIGNMENT_STATEMENT, NULL, 2, $1, $4); + } + | identifier '+' '=' expression { + $$ = NODE(ADD_STATEMENT, NULL, 2, $1, $4); + } + | identifier '-' '=' expression { + $$ = NODE(SUBTRACT_STATEMENT, NULL, 2, $1, $4); + } + | identifier '*' '=' expression { + $$ = NODE(MULTIPLY_STATEMENT, NULL, 2, $1, $4); + } + | identifier '/' '=' expression { + $$ = NODE(DIVIDE_STATEMENT, NULL, 2, $1, $4); + } + ; + +return_statement: + RETURN expression { + $$ = NODE(RETURN_STATEMENT, NULL, 1, $2); + } + ; + +print_statement: + PRINT print_list { + $$ = NODE(PRINT_STATEMENT, NULL, 1, $2); + } + ; + +null_statement: + CONTINUE { + $$ = NODE(NULL_STATEMENT, NULL, 0); + } + ; + +if_statement: + IF relation THEN statement { + $$ = NODE(IF_STATEMENT, NULL, 2, $2, $4); + } + | IF relation THEN statement ELSE statement { + $$ = NODE(IF_STATEMENT, NULL, 3, $2, $4, $6); + } + ; + +while_statement: + WHILE relation DO statement { + $$ = NODE(WHILE_STATEMENT, NULL, 2, $2, $4); + } + ; + relation: - expression '=' expression - { N2C ( $$, RELATION, strdup("="), $1, $3 ); } - | expression '<' expression - { N2C ( $$, RELATION, strdup("<"), $1, $3 ); } - | expression '>' expression - { N2C ( $$, RELATION, strdup(">"), $1, $3 ); } - ; -expression : - expression '|' expression - { N2C ( $$, EXPRESSION, strdup("|"), $1, $3 ); } - | expression '^' expression - { N2C ( $$, EXPRESSION, strdup("^"), $1, $3 ); } - | expression '&' expression - { N2C ( $$, EXPRESSION, strdup("&"), $1, $3 ); } - | expression '+' expression - { N2C ( $$, EXPRESSION, strdup("+"), $1, $3 ); } - | expression '-' expression - { N2C ( $$, EXPRESSION, strdup("-"), $1, $3 ); } - | expression '*' expression - { N2C ( $$, EXPRESSION, strdup("*"), $1, $3 ); } - | expression '/' expression - { N2C ( $$, EXPRESSION, strdup("/"), $1, $3 ); } - | '-' expression %prec UMINUS - { N1C ( $$, EXPRESSION, strdup("-"), $2 ); } - | '~' expression %prec UMINUS - { N1C ( $$, EXPRESSION, strdup("~"), $2 ); } - | '(' expression ')' { $$ = $2; } - | number { N1C ( $$, EXPRESSION, NULL, $1 ); } - | identifier - { N1C ( $$, EXPRESSION, NULL, $1 ); } - | identifier '(' argument_list ')' - { N2C ( $$, EXPRESSION, NULL, $1, $3 ); } - ; -declaration : - VAR variable_list { N1C ( $$, DECLARATION, NULL, $2 ); } - ; -print_item : - expression - { N1C ( $$, PRINT_ITEM, NULL, $1 ); } - | string - { N1C ( $$, PRINT_ITEM, NULL, $1 ); } - ; -identifier: IDENTIFIER { N0C($$, IDENTIFIER_DATA, strdup(yytext) ); } -number: NUMBER - { - int64_t *value = malloc ( sizeof(int64_t) ); - *value = strtol ( yytext, NULL, 10 ); - N0C($$, NUMBER_DATA, value ); - } -string: STRING { N0C($$, STRING_DATA, strdup(yytext) ); } + expression '=' expression { + $$ = NODE(RELATION, strdup("="), 2, $1, $3); + } + | expression '<' expression { + $$ = NODE(RELATION, strdup("<"), 2, $1, $3); + } + | expression '>' expression { + $$ = NODE(RELATION, strdup(">"), 2, $1, $3); + } + ; + +expression: + expression '|' expression { + $$ = NODE(EXPRESSION, strdup("|"), 2, $1, $3); + } + | expression '^' expression { + $$ = NODE(EXPRESSION, strdup("^"), 2, $1, $3); + } + | expression '&' expression { + $$ = NODE(EXPRESSION, strdup("&"), 2, $1, $3); + } + | expression '+' expression { + $$ = NODE(EXPRESSION, strdup("+"), 2, $1, $3); + } + | expression '-' expression { + $$ = NODE(EXPRESSION, strdup("-"), 2, $1, $3); + } + | expression '*' expression { + $$ = NODE(EXPRESSION, strdup("*"), 2, $1, $3); + } + | expression '/' expression { + $$ = NODE(EXPRESSION, strdup("/"), 2, $1, $3); + } + | '-' expression %prec UMINUS { + $$ = NODE(EXPRESSION, strdup("-"), 1, $2); + } + | '~' expression { + $$ = NODE(EXPRESSION, strdup("~"), 1, $2); + } + | '(' expression ')' { + $$ = NODE(EXPRESSION, /*NULL*/ strdup("group"), 1, $2); + } + | number { + $$ = NODE(EXPRESSION, /*NULL*/ strdup("number"), 1, $1); + } + | identifier { + $$ = NODE(EXPRESSION, /*NULL*/ strdup("identifier"), 1, $1); + } + | identifier '(' argument_list ')' { + $$ = NODE(EXPRESSION, /*NULL*/ strdup("function_call"), 2, $1, $3); + } + ; + +declaration: + VAR variable_list { + $$ = NODE(DECLARATION, NULL, 1, $2); + } + ; + +print_item: + expression { + $$ = NODE(PRINT_ITEM, NULL, 1, $1); + } + | string { + $$ = NODE(PRINT_ITEM, NULL, 1, $1); + } + ; + +identifier: + IDENTIFIER { + $$ = NODE(IDENTIFIER_DATA, strdup(yytext), 0); // Zero children + } + ; + +number: + NUMBER { + uint64_t* p_number = malloc(sizeof(uint64_t)); + *p_number = strtol(yytext, NULL, 10); + $$ = NODE(NUMBER_DATA, p_number, 0); // Zero children + } + ; + +string: + STRING { + $$ = NODE(STRING_DATA, strdup(yytext), 0); // Zero children + } + ; + %% int diff --git a/exercises/05/vslc/src/tree.c b/exercises/05/vslc/src/tree.c index 7f93eb1..00a376e 100644 --- a/exercises/05/vslc/src/tree.c +++ b/exercises/05/vslc/src/tree.c @@ -12,6 +12,10 @@ tree_print(node_t* root, stem head); static void destroy_subtree ( node_t *discard ); +static void prune_children(node_t **simplified, node_t *root); +static void resolve_constant_expressions(node_t **simplified, node_t *root); +static void flatten(node_t **simplified, node_t *root); + /* External interface */ void @@ -40,7 +44,8 @@ print_syntax_tree ( void ) } -void +// Changed so it returns the pointer to the new node, can be used as before, but makes the parser file cleaner +node_t* node_init (node_t *nd, node_index_t type, void *data, uint64_t n_children, ...) { va_list child_list; @@ -55,6 +60,8 @@ node_init (node_t *nd, node_index_t type, void *data, uint64_t n_children, ...) for ( uint64_t i=0; ichildren[i] = va_arg ( child_list, node_t * ); va_end ( child_list ); + + return nd; } @@ -82,9 +89,10 @@ tree_print(node_t* root, stem head) return; } printf("─%s", node_string[root->type]); - if ( root->type == IDENTIFIER_DATA || - root->type == STRING_DATA || - root->type == EXPRESSION ) + if ( root->type == IDENTIFIER_DATA || + root->type == STRING_DATA || + root->type == EXPRESSION || + root->type == RELATION) printf("(%s)", (char *) root->data); else if (root->type == NUMBER_DATA) printf("(%ld)", *((int64_t *)root->data)); @@ -152,82 +160,237 @@ destroy_subtree ( node_t *discard ) static void -simplify_tree ( node_t **simplified, node_t *root ) +flatten(node_t **simplified, node_t *root) { - if ( root == NULL ) + /* This will flatten left-expanded lists */ + if (!root) return; - /* Simplify subtrees before examining this node */ - for ( uint64_t i=0; in_children; i++ ) - simplify_tree ( &root->children[i], root->children[i] ); + /* Do this recursivly */ + for (int i = 0; i < root->n_children; i++) + flatten(&root->children[i], root->children[i]); - node_t *discard, *result = root; - switch ( root->type ) + node_t **new_children, *result = root; + switch (root->type) { - /* Structures of purely syntactic function */ - case PARAMETER_LIST: case ARGUMENT_LIST: - case STATEMENT: case PRINT_ITEM: case GLOBAL: - result = root->children[0]; - node_finalize ( root ); + case GLOBAL_LIST: + case STATEMENT_LIST: + case PRINT_LIST: + case EXPRESSION_LIST: + case VARIABLE_LIST: + case DECLARATION_LIST: + // Check if node have more than two children + if (root->n_children < 2) break; - case PRINT_STATEMENT: - result = root->children[0]; + + result = root->children[0]; + result->n_children++; + + // Realloc the array of children to the new size + if (!(new_children = realloc(result->children, result->n_children * sizeof(node_t*)))) + break; + // if successs, insert the new array + result->children = new_children; + + // Insert child at the end + result->children[result->n_children - 1] = root->children[1]; + + node_finalize(root); + break; + } + + *simplified = result; +} + + +static void +prune_children(node_t **simplified, node_t *root) +{ + if (!root) + return; + + /* Do this recursivly */ + for (int i = 0; i < root->n_children; i++) + prune_children(&root->children[i], root->children[i]); + + node_t *result = root; + switch (root->type) + { + case PROGRAM: + case GLOBAL: + //case ARGUMENT_LIST: // For this to work, need to change order of operations + //case PARAMETER_LIST: // For this to work, need to change order of operations + //case VARIABLE_LIST: + //case EXPRESSION_LIST: + case DECLARATION: + case STATEMENT: + case PRINT_ITEM: + case PRINT_STATEMENT: + result = root->children[0]; + + // The print_statement only contains a print_list, still need a print_statement. + if (root->type == PRINT_STATEMENT) result->type = PRINT_STATEMENT; + + node_finalize(root); + break; + } + + *simplified = result; +} + + +static void +resolve_constant_expressions(node_t **simplified, node_t *root) +{ + if (!root) + return; + + /* Do this recursivly */ + for (int i = 0; i < root->n_children; i++) + resolve_constant_expressions(&root->children[i], root->children[i]); + + if (root->type != EXPRESSION) + return; + + node_t *result = root; + + switch (root->n_children) + { + case 1: + result = root->children[0]; + + if (root->data && + result->type == NUMBER_DATA && + result->data) + { + switch (*((char*)root->data)) + { + case '-': + *((int64_t*)result->data) *= -1; + break; + case '~': + *((int64_t*)result->data) = ~*((int64_t*)result->data); + break; + } + } + + node_finalize(root); + break; + + case 2: + // Both children needs to be numbers to resolve constants + if (root->children[0]->type == NUMBER_DATA && + root->children[1]->type == NUMBER_DATA) + { + // Check if children does not contain null pointers + if (!root->children[0]->data) + break; + if (!root->children[1]->data) + break; + + // Check if data field is not null pointer + if (!root->data) + break; + + result = root->children[0]; + int64_t + *lhs = result->data, + *rhs = root->children[1]->data; + + switch (*(char*)root->data) + { + /* Assignments */ + case '|': *lhs |= *rhs; break; + case '^': *lhs ^= *rhs; break; + case '&': *lhs &= *rhs; break; + case '+': *lhs += *rhs; break; + case '-': *lhs -= *rhs; break; + case '*': *lhs *= *rhs; break; + case '/': *lhs /= *rhs; break; + } + + node_finalize(root->children[1]); node_finalize(root); - break; - /* Flatten lists: - * Take left child, append right child, substitute left for root. - */ - case STATEMENT_LIST: case DECLARATION_LIST: case GLOBAL_LIST: - case PRINT_LIST: case EXPRESSION_LIST: case VARIABLE_LIST: - if ( root->n_children >= 2 ) - { - result = root->children[0]; - result->n_children += 1; - result->children = realloc ( - result->children, result->n_children * sizeof(node_t *) - ); - result->children[result->n_children-1] = root->children[1]; - node_finalize ( root ); - } - break; - case EXPRESSION: - switch ( root->n_children ) - { - case 1: - if ( root->children[0]->type == NUMBER_DATA ) - { - result = root->children[0]; - if ( root->data != NULL ) - *((int64_t *)result->data) *= -1; - node_finalize (root); - } - else if ( root->data == NULL ) - { - result = root->children[0]; - node_finalize (root); - } - break; - case 2: - if ( root->children[0]->type == NUMBER_DATA && - root->children[1]->type == NUMBER_DATA - ) { - result = root->children[0]; - int64_t - *x = result->data, - *y = root->children[1]->data; - switch ( *((char *)root->data) ) - { - case '+': *x += *y; break; - case '-': *x -= *y; break; - case '*': *x *= *y; break; - case '/': *x /= *y; break; - } - node_finalize ( root->children[1] ); - node_finalize ( root ); - } - break; - } + } + + + break; } *simplified = result; } + + +static void +resolve_constant_relations( node_t** simplified, node_t* root) +{ + if (!root) + return; + + /* Do this recursivly */ + for (int i = 0; i < root->n_children; i++) + resolve_constant_relations(&root->children[i], root->children[i]); + + if (root->type != RELATION)//|| root->type != RELATION) + return; + + node_t *result = root; + + if (root->n_children != 2) + return; + + // Both children must be constant numbers + if (root->children[0]->type != NUMBER_DATA || + root->children[1]->type != NUMBER_DATA) + return; + + // Check if children does not contain null pointers + if (!root->children[0]->data) + return; + if (!root->children[1]->data) + return; + + // Check if data field is not null pointer + if (!root->data) + return; + + result = root->children[0]; + int64_t + *lhs = result->data, + *rhs = root->children[1]->data; + + switch (*(char*)root->data) + { + /* Relations */ + case '=': *lhs = (*lhs == *rhs); break; + case '<': *lhs = (*lhs < *rhs); break; + case '>': *lhs = (*lhs > *rhs); break; + } + + node_finalize(root->children[1]); + node_finalize(root); + + *simplified = result; +} + + +static void +simplify_tree ( node_t **simplified, node_t *root ) +{ + if (!root) + return; + + /* + Each of the functions do their operations recursivly. + This opens up for a lot more flexibility, like removing + variable list after it is flatten + */ + flatten(&root, root); + prune_children(&root, root); + resolve_constant_expressions(&root, root); + + // The following is experimental, will resolve the constant relations + resolve_constant_relations(&root, root); + + *simplified = root; +} diff --git a/exercises/05/vslc/src/vslc b/exercises/05/vslc/src/vslc deleted file mode 100644 index 6e7048b775dd26bf924ce8fef987568d1a456643..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111552 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