#include #include #include #include #include "list.h" #include "env.h" #include "shared.h" #include "cmp.h" #include "mem.h" #include "intcode.h" /*creates a new environment, all by itself*/ env_t *env_init() { env_t *newEnv = (env_t*)malloc(sizeof(env_t)); //this won't work with memalloc- it gets freed early newEnv->prev = NULL; newEnv->syms = hash_init( *hash_string,*cmp_string); newEnv->num_temps = 0; newEnv->cur_size = 0; return newEnv; } /*creates a new scope within the environment. The environment returned is the env of the new scope, with * the give scope as its prev element */ env_t *env_scope_init(env_t *prevTop) { env_t *newEnv = env_init(); newEnv->prev = prevTop; if(prevTop != NULL) { newEnv->num_temps = prevTop->num_temps; } return newEnv; } //insert the given key-value pair into the current environment //it will allow you to shadow previous variables, but //will fail if the given variable is already in this environemnt's table list_entry_t *env_insert(env_t *curEnv, void *key, void *value) { //cannot have duplicate definition within a block if(hash_search(curEnv->syms,key) == NULL ) { id_type_t *val = (id_type_t*)value; if(val != NULL) { val->loc = curEnv->cur_size; //need to figure out what to do for temp variables curEnv->cur_size += sizeofidtype(val); } return hash_insert(curEnv->syms, key, value); } return NULL; } //LOOK HERE: /* HW 5: this calculates the size of the activation record for this level */ int sizeof_record(env_t *top) { assert(top != NULL); if(top->syms == NULL) { return 0; } //one int for the item count, 1 int for the location of each item int size = 4 * (1 + length_of_hash(top->syms)); //plus whatever the length of each item is size += top->cur_size; return size; } int locof_record(env_t *top, void *key) { assert(top != NULL); id_type_t *loc = (id_type_t*)hash_search(top->syms,key); if(loc == NULL) { fprintf(stderr, "record is not in the given environment\n"); return -1; } return 4 * (1+length_of_hash(top->syms)) + loc->loc; } /*pops the current environment off*/ env_t* env_pop(env_t *oldEnv) { assert(oldEnv != NULL); env_t *prev = oldEnv->prev; return prev; } /*searches the environment and all of its previous envs to find the value given * by the key. It returns the innermost one. */ void *env_search(env_t *top, void *key) { assert(top != NULL); list_entry_t *le = env_get(top, key); if(le == NULL) { return NULL; } return le->value; } int env_remove(env_t *top, void *key) { assert(top != NULL); int elem = 0; env_t *curEnv = top; while(elem == 0 && curEnv != NULL) { if(hash_search(curEnv->syms,key)) { curEnv->cur_size -= sizeofidtype((id_type_t*)hash_search(curEnv->syms,key)); elem = hash_remove(curEnv->syms,key); } curEnv = env_pop(curEnv); } return elem; } char* print_env_help(env_t *top, char* indent) { assert(top!= NULL); if(top->prev != NULL) { indent = print_env_help(top->prev, indent); } printf("%s\n",indent); list_head_t *list = hash_to_list(top->syms); list_entry_t *item = list->list; while(item != NULL) { printf("%s %s:",indent,(char*)item->key); if(item->value == NULL) { printf("NULL\n"); } else { printValue((id_type_t*)item->value); printf("\n"); } item = item->next; } printf("%s\n",indent); char *new_indent = calloc(strlen(indent) +3,sizeof(char)); sprintf(new_indent,"%s| ",indent); return new_indent; } //a function to print the current environment. //It prints the entire stack void print_env(env_t *top) { printf("{\n"); print_env_help(top, " "); printf("}\n"); } /*Get the List Entry corresponding to the given key*/ list_entry_t *env_get(env_t *top, void *key) { assert(top != NULL); void *elem = NULL; env_t *curEnv = top; while(elem == NULL && curEnv != NULL) { elem = hash_get_element(curEnv->syms,key); curEnv = curEnv->prev; } return elem; } void env_delete(env_t *top) { hash_delete(top->syms); if(top->prev != NULL) { env_delete(top->prev); } free(top); }