// get new temp temp_var * new_temp(ast_node root) { if (!root) return NULL; // get root's scope table temp list temp_list * t_list = ((symhashtable_t *)root->scope_table)->t_list; // get a new temp from the list temp_var * new_var = (temp_var *)calloc(1,sizeof(temp_var)); assert(new_var); // give unique id new_var->id = t_list->count; // make new name -- not yet char * name = make_temp_name(new_var->id); // put new temp in list t_list->list[t_list->count] = new_var; // if list is full, expand! t_list->count++; if (t_list->count == t_list->size) { t_list->size *= 2; t_list->list = realloc(t_list->list, t_list->size * sizeof(temp_var *)); assert(t_list->list); } // add that new temp to local table under the name symnode_t * new_node = insert_into_symhashtable(root->scope_table,name, NULL); // attach temp to created symnode new_var->temp_symnode = new_node; // set node type set_node_type(new_node, VAR_SYM); // set node characteristics var_symbol node_model; node_model.name = name; node_model.type = INT_TS; node_model.modifier = SINGLE_DT; node_model.specie = TEMP_VAR; node_model.byte_size = TYPE_SIZE(INT_TS); // save to symbol table set_node_var(new_node, &node_model); // return newly created temp return new_var; }
/* * instert_into_symboltable * * Insert an entry into the innermost scope of symbol table. First * make sure it's not already in that scope. Return a pointer to the * entry. */ symnode_t *insert_into_symboltable(symboltable_t *symtab, var_lookup_type type, char *name, int lineno) { assert(symtab); assert(symtab->leaf); symnode_t *node = lookup_symhashtable(symtab->leaf, name, NOHASHSLOT); /* error check!! */ if (node == NULL) { node = insert_into_symhashtable(symtab->leaf, type, name, lineno, LOCAL_VT); return node; } else { return NULL; } }
symnode_t *insert_temp(symboltable_t *symtab, var_lookup_type type, char *name, int lineno) { assert(symtab); assert(symtab->leaf); int name_len = strlen(name); char *typed_name = calloc(1, sizeof(char) * (name_len + 3)); sprintf(typed_name, "%s%s", temp_prefix, name); symnode_t *node = lookup_symhashtable(symtab->leaf, typed_name, NOHASHSLOT); if (node == NULL) { node = insert_into_symhashtable(symtab->root, type, typed_name, lineno, TEMP_VT); return node; } else { return NULL; } }
/* Insert an entry into the innermost scope of symbol table. First make sure it's not already in that scope. Return a pointer to the entry. */ symnode_t *insert_into_symboltable(symboltable_t *symtab, ast_node astnode) { char *name = astnode->value_string; assert(symtab); assert(symtab->leaf); symnode_t *node = lookup_symhashtable(symtab->leaf, name, NOHASHSLOT); /* error check!! */ if (node == NULL) { node = insert_into_symhashtable(symtab->leaf, astnode); return node; } else { return NULL; } }
void collect_literals(ast_node root, symboltable_t *symtab){ ast_node child; symnode_t *node; symhashtable_t *collection = symtab->literal_collection; assert(collection != NULL); char* name; int slot = 0; /* Recursively call the function to traverse the tree in a preorder way */ for(child = root->left_child; child != NULL; child = child->right_sibling){ collect_literals(child, symtab); } switch (root->node_type) { case STRING_LITERAL_N: name = root->value_string; // Calculate slot for this node, try to find the current node in the symbol table slot = hashPJW(name, collection->size); node = lookup_symhashtable(collection, name, slot); if(node == NULL){ insert_into_symhashtable(collection, root); } break; /* Need to hash the value differently so as to not to mistake strings and ints, (e.g. 1 vs "1") */ case INT_LITERAL_N: name = calloc(DEFAULTSTRSIZE, sizeof(char)); sprintf(name, "__%d", root->value_int); root->value_string = strdup(name); slot = hashPJW(name, collection->size); node = lookup_symhashtable(collection, name, slot); if(node == NULL){ insert_into_symhashtable(collection, root); } break; case RETURN_N: // Empty return. Create a new symnode to add to // the collection because otherwise it will give us // trouble later when trying to create quads, since // the function to create quads takes symnodes and there // is currently no symnode for this empty return. if(root->left_child != NULL){ if(root->left_child->node_type == VOID_TYPE_N){ name = calloc(DEFAULTSTRSIZE, sizeof(char)); sprintf(name, "__%s", "void"); root->left_child->value_string = calloc(DEFAULTSTRSIZE, sizeof(char)); strcpy(root->left_child->value_string, name); slot = hashPJW(name, collection->size); node = lookup_symhashtable(collection, name, slot); if(node == NULL){ insert_into_symhashtable(collection, root->left_child); } } } default: break; } }
/* * Builds the symbol table, creating scopes as needed, and linking them together. * Adds variable and function identifiers to scopes appropriately. */ void build_symbol_table(ast_node root, int level, int sibno, symboltable_t *symtab) { //calculate the scope for the variable/func declaration //calculate the parent for that variable/func declaration //need function to take as input //printf("here \n"); symhashtable_t *hash; /* Depending on node types, go deeper, create sibling scopes, add to hashtable, * or take other appropriate action. */ switch (root->node_type) { ast_node param; int param_offset = 4; int param_count = 0; case SEQ_N: // change main level when see a new sequence level++; break; case FORMAL_PARAMS_N: level++; param_count = 0; insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) ); // for(param = root->left_child; param != NULL; param = param->right_sibling){ // if(param->node_type == ARRAY_TYPE_N || param->return_type == ARRAY_TYPE_N){ // param_count += DEFAULT_ARRAY_PARAM_SIZE; // } // else{ // param_count++; // } // } // printf("PARAM COUNT!!!!! = %d\n", param_count); // // for(param = root->left_child; param != NULL; param = param->right_sibling){ // if(param->node_type == ARRAY_TYPE_N || param->return_type == ARRAY_TYPE_N){ // param->snode->offset = param_count * 4; // param->snode->offset -= DEFAULT_ARRAY_PARAM_SIZE; // } // else{ // param->snode->offset = param_count-- * 4; // } // } break; case FUNC_DECLARATION_N: // function declaraions //does hashtable exist with given lvl, siblvl (use find_hashtable) check_if_redef(root, symtab ,level, sibno); hash = find_hashtable(symtab->root, level, sibno); if(hash == NULL) { hash = make_insert_hashtable(symtab->root, level, sibno, MAX(level - 1, 0), getSibling(level) ); } insert_into_symhashtable(hash, root); // will only insert if it is empty. insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) ); break; case FUNCTION_N: check_if_declared(root, symtab ,level, sibno); insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) ); break; case ID_N: /* print the id */ check_if_redef(root, symtab ,level, sibno); //if(root->return_type != 0) { // a non-zero value means that it is a declaration, since only declarations // are assigned a return type when building the abstract syntax tree. if(root->isDecl){ hash = find_hashtable(symtab->root, level, sibno); if(hash == NULL) { hash = make_insert_hashtable(symtab->root, level, sibno, MAX(level - 1, 0), getSibling(level) ); } insert_into_symhashtable(hash, root); } else { // don't know if previously declared check_if_declared(root, symtab , level, sibno); } insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) ); break; case ARRAY_TYPE_N: // check for return types! check_if_redef(root, symtab ,level, sibno); //cif(root->return_type != 0) { if(root->isDecl){ hash = find_hashtable(symtab->root, level, sibno); if(hash == NULL) { hash = make_insert_hashtable(symtab->root, level, sibno, MAX(level - 1, 0), getSibling(level) ); } insert_into_symhashtable(hash, root); } else { check_if_declared(root, symtab , level, sibno); } insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) ); break; case RETURN_N: insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) ); break; default: // printf("at default of switch\n"); assert(symtab->root != NULL); hash = find_hashtable(symtab->root, level, sibno); if(hash == NULL) { hash = make_insert_hashtable(symtab->root, level, sibno, MAX(level - 1, 0), getSibling(level) ); } //note: cannot use insert_scope_info here because siblings[level - 1] causes invalid read as level-1 can go negative break; } if(arraylen == level) { arraylen = arraylen + DELTA; siblings = realloc(siblings, sizeof(int) * arraylen); assert(siblings != NULL); for(int k=0; k < DELTA; k++) { siblings[arraylen - (DELTA-k)] = 0; } } /* Recurse on each child of the subtree root, with a depth one greater than the root's depth. */ ast_node child; for (child = root->left_child; child != NULL; child = child->right_sibling) build_symbol_table(child, level, siblings[level], symtab); if(root->node_type == SEQ_N){//} || root->node_type == FORMAL_PARAMS_N){ siblings[level]++; // change sibling level after you're done printing all // subtrees, i.e., after done recursing. } }