/* create a hashtable using the given function and comparator */ void hash_create(gc_type *gc, hash_fn fn, hash_cmp cmp, hashtable_type **ret) { hash_internal_type *table = 0; /* register the hashtable type with the gc */ if(!hashtable_type_def) { hashtable_type_def = register_hashtable(gc); key_value_type_def = register_key_value(gc); } gc_register_root(gc, (void**)&table); gc_alloc_type(gc, 0, hashtable_type_def, (void **)&table); table->gc = gc; table->calc_hash = fn; table->compare = cmp; table->copy_on_write = false; /* resize the hashtable */ hash_resize(table, HASH_SIZE); table->key_value = key_value_type_def; *ret = (hashtable_type *)table; gc_unregister_root(gc, (void**)&table); }
/* create a cow copy of an existing hashtable */ void hash_cow(gc_type *gc, hashtable_type *src, hashtable_type **ret) { hash_internal_type **table = (hash_internal_type **)ret; /* allocate the new hashtable instance */ gc_alloc_type(gc, 0, hashtable_type_def, (void **)table); /* copy the entire contents of the hashtable into the new one */ memcpy(*table, src, sizeof(hash_internal_type)); (*table)->copy_on_write = true; }
void asm_jump(gc_type *gc, buffer_type *buf, yyscan_t *scanner, jump_type **jump_list) { static int init = 0; static gc_type_def jump_def = 0; jump_type *jump = 0; char *label = 0; /* TODO: This is a hack */ if(!init) { init = 1; jump_def = gc_register_type(gc, sizeof(jump_type)); gc_register_pointer(gc, jump_def, offsetof(jump_type, label)); gc_register_pointer(gc, jump_def, offsetof(jump_type, next)); } gc_register_root(gc, (void **)&jump); /* allocate a new jump */ gc_alloc_type(gc, 0, jump_def, (void **)&jump); /* save location of jump addr field */ jump->addr = buffer_size(buf); /* save the line number for this jump */ jump->lineno = yyget_lineno(scanner); /* make sure we have a label */ if(yylex(scanner) != LABEL_TOKEN) { assert(0); } /* save a copy of the label */ label = get_text(scanner); gc_alloc(gc, 0, strlen(label)+1, (void **)&(jump->label)); strcpy(jump->label, label); /* put this jump at the head of the list */ jump->next = *jump_list; *jump_list = jump; gc_unregister_root(gc, (void **)&jump); /* Make sure we have space to write target */ EMIT(buf, INT_64(0),8); }
/* Create an instance of the compiler */ void compiler_create(gc_type *gc, compiler_type **comp_void, char *compiler_home) { compiler_core_type *compiler = 0; static gc_type_def stream_gc_type = 0; static gc_type_def node_literal_gc_type = 0; static gc_type_def node_single_gc_type = 0; static gc_type_def node_double_gc_type = 0; static gc_type_def compiler_gc_type = 0; // setup gc types if (!compiler_gc_type) { compiler_gc_type = register_compiler_type(gc); stream_gc_type = register_stream_type(gc); node_literal_gc_type = register_node_literal_type(gc); node_single_gc_type = register_node_single_type(gc); node_double_gc_type = register_node_double_type(gc); } gc_register_root(gc, (void **)&compiler); /* create a compiler instance */ gc_alloc_type(gc, 0, compiler_gc_type, (void **)&compiler); compiler->gc = gc; compiler->label_index = 0; /*compiler->preamble = "lib/preamble.asm"; compiler->postamble = "lib/postamble.asm";*/ strcpy(compiler->home, compiler_home); /* setup gc types */ compiler->stream_gc_type = stream_gc_type; compiler->node_types[STREAM_LITERAL] = node_literal_gc_type; compiler->node_types[STREAM_SYMBOL] = node_literal_gc_type; compiler->node_types[STREAM_STRING] = node_literal_gc_type; compiler->node_types[STREAM_OP] = node_literal_gc_type; compiler->node_types[STREAM_QUOTED] = node_single_gc_type; compiler->node_types[STREAM_LOAD] = node_single_gc_type; compiler->node_types[STREAM_ASM] = node_single_gc_type; compiler->node_types[STREAM_ASM_STREAM] = node_single_gc_type; compiler->node_types[STREAM_COND] = node_single_gc_type; compiler->node_types[STREAM_AND] = node_single_gc_type; compiler->node_types[STREAM_OR] = node_single_gc_type; compiler->node_types[STREAM_RECORD_TYPE] = node_single_gc_type; compiler->node_types[STREAM_BIND] = node_double_gc_type; compiler->node_types[STREAM_STORE] = node_double_gc_type; compiler->node_types[STREAM_LET_STAR] = node_double_gc_type; compiler->node_types[STREAM_TWO_ARG] = node_double_gc_type; compiler->node_types[STREAM_IF] = node_double_gc_type; compiler->node_types[STREAM_MATH] = node_double_gc_type; compiler->node_types[STREAM_LAMBDA] = node_double_gc_type; compiler->node_types[STREAM_CALL] = node_double_gc_type; *comp_void = compiler; /* Add a stream route to the compiler object */ stream_create(compiler, &(compiler->stream)); /* Add the include stack array */ // TODO: Look at statically allocating this compiler->include_depth = -1; gc_alloc_pointer_array(gc, 0, MAX_INCLUDE_DEPTH, (void **)&(compiler->include_stack)); gc_unregister_root(gc, (void **)&compiler); }
/* locate or create a key_value_object the given key */ key_value_type *hash_find(hash_internal_type *table, void *key, hash_action_type action) { hash_type hash = (*table->calc_hash)(key); hash_type index = hash % table->size; /* calculate the search table index */ key_value_type *kv = 0; key_value_type *prev_kv = 0; /* Check for "write" operations and a COW hash */ if (table->copy_on_write && (action == CREATE || action == DELETE)) { /* resize implicitly copies everything */ hash_resize(table, table->size); table->copy_on_write = false; } /* is there anything at the given index? */ if((kv = table->table[index])) { /* search through the list of key value pairs */ while(kv) { if((*table->compare)(key, kv->key) == EQ) { /* do the delete if needed */ if(action == DELETE) { /* Do we have a chain? */ if(prev_kv) { /* Remove node from chain */ prev_kv->next = kv->next; } else { /* This node is either the head of a chain or there is no chain. */ table->table[index] = kv->next; } } return kv; } prev_kv = kv; kv = kv->next; } } /* we did not find the key, should we create it? */ if(action == CREATE) { gc_register_root(table->gc, (void**)&kv); gc_alloc_type(table->gc, 0, table->key_value, (void **)&kv); kv->key = key; /* attach kv to table */ kv->next = table->table[index]; table->table[index] = kv; table->entries++; gc_unregister_root(table->gc, (void**)&kv); return kv; } return 0; }