Mercurial > repos > rhope
view list.c @ 75:0083b2f7b3c7
Partially working implementation of List. Modified build scripts to allow use of other compilers. Fixed some bugs involving method implementations on different types returning different numbers of outputs. Added Fold to the 'builtins' in the comipler.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 06 Jul 2010 07:52:59 -0400 |
parents | 76568becd6d6 |
children |
line wrap: on
line source
#include "structs.h" #include "datum.h" #include "interp.h" #include <stdlib.h> #include <string.h> datum * create_list(program * prog) { short i; datum * dat = new_datum(BUILTIN_TYPE_LIST, 1, sizeof(list_data) + sizeof(datum *)*7, prog); dat->c.generic.len = 8; ((list_data *)dat->c.generic.data)->num_entries = 0; return dat; } int vis_list_new(datum ** inputlist, queue_entry * worker_entry) { inputlist[0] = create_list(worker_entry->instance->def->program); return 0; } int vis_list_append(datum ** inputlist, queue_entry * worker_entry) { int ref_count, new_entry_count; list_data * list, * new_list; datum * output; int i; VIS_EnterCriticalSection(inputlist[0]->lock); ref_count = inputlist[0]->ref_count; VIS_LeaveCriticalSection(inputlist[0]->lock); list = ((list_data *)inputlist[0]->c.generic.data); DEBUGPRINTF("append: generic.len = %d, list->num_entries = %d, ref_count = %d\n", inputlist[0]->c.generic.len, list->num_entries, ref_count); if(ref_count == 1) { if(inputlist[0]->c.generic.len > list->num_entries) { DEBUGPUTS("Fast append\n"); list->entries[list->num_entries] = inputlist[1]; //No need to add_ref because we're consuming the ref we wer passed ++(list->num_entries); } else { DEBUGPUTS("malloc append\n"); new_entry_count = list->num_entries + (list->num_entries > 1);//grow by half current size new_list = malloc((new_entry_count -1) * sizeof(datum *) + sizeof(list_data)); new_list->num_entries = list->num_entries+1; inputlist[0]->c.generic.len = new_entry_count; memcpy(new_list->entries, list->entries, list->num_entries * sizeof(datum *)); new_list->entries[list->num_entries] = inputlist[1]; inputlist[0]->c.generic.data = new_list; VIS_FREE(list, "List object"); } } else { DEBUGPUTS("datum copy append\n"); if(inputlist[0]->c.generic.len > list->num_entries) new_entry_count = inputlist[0]->c.generic.len; else new_entry_count = list->num_entries + (list->num_entries > 1);//grow by half current size output = new_datum_comp(inputlist[0]->company, 1, (new_entry_count -1) * sizeof(datum *) + sizeof(list_data)); new_list = output->c.generic.data; new_list->num_entries = list->num_entries+1; output->c.generic.len = new_entry_count; for(i = 0; i < list->num_entries; ++i) new_list->entries[i] = add_ref(list->entries[i]); new_list->entries[list->num_entries] = inputlist[1]; release_ref(inputlist[0]); inputlist[0] = output; } DEBUGPRINTF("append: generic.len = %d, list->num_entries = %d\n", inputlist[0]->c.generic.len, ((list_data *)inputlist[0]->c.generic.data)->num_entries); return 0; } int vis_list_swap(datum ** inputlist, queue_entry * worker_entry) { //TODO: Throw error if indices out of bounds list_data * list; datum * temp; inputlist[0] = copy_datum(inputlist[0], 0); list = ((list_data *)inputlist[0]->c.generic.data); temp = list->entries[inputlist[1]->c.integers.num_a]; list->entries[inputlist[1]->c.integers.num_a] = list->entries[inputlist[2]->c.integers.num_a]; list->entries[inputlist[2]->c.integers.num_a] = temp; release_ref(inputlist[1]); release_ref(inputlist[2]); return 0; } int vis_list_index(datum ** inputlist, queue_entry * worker_entry) { //TODO: Throw error if indices out of bounds list_data * list = ((list_data *)inputlist[0]->c.generic.data); datum * output; DEBUGPRINTF("index: generic.len = %d, list->num_entries = %d, requested index: %d\n", inputlist[0]->c.generic.len, list->num_entries, inputlist[1]->c.integers.num_a); DEBUGPRINTF("list->entries[%d] = %X\n", inputlist[1]->c.integers.num_a, list->entries[inputlist[1]->c.integers.num_a]); if(inputlist[1]->c.integers.num_a < list->num_entries && list->entries[inputlist[1]->c.integers.num_a]) { output = add_ref(list->entries[inputlist[1]->c.integers.num_a]); release_ref(inputlist[1]); inputlist[1] = NULL; } else { output = NULL; inputlist[1] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program); inputlist[1]->c.integers.num_a = 0; } release_ref(inputlist[0]); inputlist[0] = output; return 0; } int vis_list_insert(datum ** inputlist, queue_entry * worker_entry) { int ref_count, new_entry_count; list_data * list, * new_list; datum * output; int i; VIS_EnterCriticalSection(inputlist[0]->lock); ref_count = inputlist[0]->ref_count; VIS_LeaveCriticalSection(inputlist[0]->lock); list = ((list_data *)inputlist[0]->c.generic.data); if(ref_count == 1) { if(inputlist[0]->c.generic.len > list->num_entries) { memmove(list->entries + inputlist[1]->c.integers.num_a + 1, list->entries + inputlist[1]->c.integers.num_a, sizeof(datum *) * (list->num_entries-inputlist[1]->c.integers.num_a)); list->entries[inputlist[1]->c.integers.num_a] = inputlist[2]; //No need to add_ref because we're consuming the ref we wer passed ++(list->num_entries); } else { new_entry_count = list->num_entries + (list->num_entries > 1);//grow by half current size new_list = malloc((new_entry_count -1) * sizeof(datum *) + sizeof(list_data)); new_list->num_entries = list->num_entries+1; inputlist[0]->c.generic.len = new_entry_count; memcpy(new_list->entries, list->entries, list->num_entries * sizeof(datum *)); new_list->entries[list->num_entries] = inputlist[1]; inputlist[0]->c.generic.data = new_list; VIS_FREE(list, "List object"); } } else { new_entry_count = list->num_entries + (list->num_entries > 1);//grow by half current size output = new_datum_comp(inputlist[0]->company, 1, (new_entry_count -1) * sizeof(datum *) + sizeof(list_data)); new_list = output->c.generic.data; new_list->num_entries = list->num_entries+1; output->c.generic.len = new_entry_count; for(i = 0; i < inputlist[1]->c.integers.num_a; ++i) new_list->entries[i] = add_ref(list->entries[i]); for(i = inputlist[1]->c.integers.num_a; i < list->num_entries; ++i) new_list->entries[i+1] = add_ref(list->entries[i]); release_ref(inputlist[0]); new_list->entries[list->num_entries] = inputlist[2]; inputlist[0] = output; } release_ref(inputlist[1]); return 0; } int vis_list_remove(datum ** inputlist, queue_entry * worker_entry) { int ref_count, new_entry_count; list_data * list, * new_list; int i; datum * output; VIS_EnterCriticalSection(inputlist[0]->lock); ref_count = inputlist[0]->ref_count; VIS_LeaveCriticalSection(inputlist[0]->lock); list = ((list_data *)inputlist[0]->c.generic.data); if(ref_count == 1) { release_ref(list->entries[inputlist[1]->c.integers.num_a]); memmove(list->entries + inputlist[1]->c.integers.num_a, list->entries + inputlist[1]->c.integers.num_a + 1, sizeof(datum *) * (list->num_entries-(inputlist[1]->c.integers.num_a+1))); --(list->num_entries); } else { new_entry_count = list->num_entries + (list->num_entries > 1);//grow by half current size output = new_datum_comp(inputlist[0]->company, 1, (new_entry_count -1) * sizeof(datum *) + sizeof(list_data)); new_list = output->c.generic.data; new_list->num_entries = list->num_entries+1; output->c.generic.len = new_entry_count; for(i = 0; i < inputlist[1]->c.integers.num_a; ++i) new_list->entries[i] = add_ref(list->entries[i]); for(i = inputlist[1]->c.integers.num_a+1; i < list->num_entries; ++i) new_list->entries[i-1] = add_ref(list->entries[i]); release_ref(inputlist[0]); inputlist[0] = output; } release_ref(inputlist[1]); return 0; } int vis_list_set(datum ** inputlist, queue_entry * worker_entry) { int new_num_entries, new_generic_len, i; list_data * list; DEBUGPUTS("vis_list_set\n"); if(((list_data *)inputlist[0]->c.generic.data)->num_entries <= inputlist[1]->c.integers.num_a) { new_num_entries = inputlist[1]->c.integers.num_a + 1; new_generic_len = (new_num_entries + (new_num_entries>>1)-1)*sizeof(datum*) + sizeof(list_data); } else { new_num_entries = ((list_data *)inputlist[0]->c.generic.data)->num_entries; new_generic_len = 0; } DEBUGPRINTF("new_generic_len: %d, new num_entries: %d\n", new_generic_len, new_num_entries); inputlist[0] = copy_datum(inputlist[0], new_generic_len); if(new_generic_len) { inputlist[0]->c.generic.len = (new_num_entries + (new_num_entries>>1)); } DEBUGPUTS("Datum copy done\n"); list = ((list_data *)inputlist[0]->c.generic.data); DEBUGPUTS("before Null fill loop\n"); for(i = list->num_entries; i < new_num_entries; ++i) list->entries[i] = NULL; DEBUGPUTS("Before existing entry release_ref\n"); if(inputlist[1]->c.integers.num_a < list->num_entries) release_ref(list->entries[inputlist[1]->c.integers.num_a]); DEBUGPRINTF("Setting index %d to %X\n", inputlist[1]->c.integers.num_a, inputlist[2]); list->entries[inputlist[1]->c.integers.num_a] = inputlist[2]; release_ref(inputlist[1]); list->num_entries = new_num_entries; DEBUGPUTS("vis_list_set done\n"); return 0; } int vis_list_length(datum ** inputlist, queue_entry * worker_entry) { datum * output; list_data * list = ((list_data *)inputlist[0]->c.generic.data); output = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); output->c.integers.num_a = list->num_entries; release_ref(inputlist[0]); inputlist[0] = output; return 0; } int vis_list_first(datum ** inputlist, queue_entry * worker_entry) { int i; list_data * list = inputlist[0]->c.generic.data; if(!list->num_entries) { inputlist[1] = inputlist[0]; inputlist[0] = NULL; } else { i = 0; while(!list->entries[i] && i < list->num_entries) ++i; release_ref(inputlist[0]); inputlist[0] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); inputlist[0]->c.integers.num_a = i; inputlist[1] = NULL; } return 0; } int vis_list_next(datum ** inputlist, queue_entry * worker_entry) { int i; list_data * list = inputlist[0]->c.generic.data; i = inputlist[1]->c.integers.num_a + 1; while(i < list->num_entries && !list->entries[i]) ++i; if(i < list->num_entries) { release_ref(inputlist[0]); inputlist[0] = copy_datum(inputlist[1], 0); inputlist[1] = NULL; inputlist[0]->c.integers.num_a = i; } else { release_ref(inputlist[1]); inputlist[1] = inputlist[0]; inputlist[0] = NULL; } return 0; }