Mercurial > repos > rhope
view interp.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 | 6202b866d72c |
children |
line wrap: on
line source
#ifdef WIN32 #include <windows.h> #include <winsock.h> #include <crtdbg.h> #else #ifdef SYLLABLE #include <unistd.h> #include <atheos/threads.h> #else #ifdef NINTENDO_DS #include <nds.h> #else #include <unistd.h> #include <pthread.h> #endif #endif #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "mt19937ar.h" #include "interp.h" #include "vis_threading.h" #include "datum.h" #include "parser.h" #include "saveload.h" #ifdef TEXT_FILE_DEBUG FILE * debugfile; #endif char debugbuffer[1024]; //extern HWND hWnd; extern char new_name_buf[256]; extern int buf_size; int lock_fail_counter; int lock_counter; VIS_CRITICAL_SECTION(data_lock) VIS_CRITICAL_SECTION(worker_queue_lock) VIS_CRITICAL_SECTION(randlock) VIS_Event(queue_add_event) int program_count=1; VIS_CRITICAL_SECTION(program_count_lock) //#define ENABLE_PROFILING 1 #ifdef ENABLE_PROFILING __int64 vis_profile_start_times[NUM_PROFS]; __int64 vis_profile_running_total[NUM_PROFS]; int vis_profile_counts[NUM_PROFS]; __declspec(naked) unsigned __int64 __cdecl rdtsc(void) { __asm { rdtsc ret ; return value at EDX:EAX } } #define PROF_INIT_CUSTOM 0 #define PROF_WORKER_THREAD 1 #define PROF_PROCESS_WORKER 2 #define PROF_CLEANUP_CUSTOM 3 #define PROF_SUB_CALLBACK 4 #define PROF_CLEANUP_RELEASE_REFS 5 #define PROF_CLEANUP_CHECK 6 #define PROF_CLEANUP_FREELISTS 7 #define PROF_PROCESS_OUTPUTS 8 #define PROF_OPT_PREP_INPUT 9 #define PROF_RUN_OPT 10 #define PROF_ADDQUEUE 11 #define PROF_ADDQUEUE_MALLOC 12 #define PROF_OPT_LOOP 13 #define PROF_EXECUTE_WORKER 14 #define PROF_EXECUTE_OTHER 15 #define PROF_PREP_MAGIC 16 #define PROF_CONVERT_INPUTS 17 #define PROF_EXECUTE_CUSTOM 18 #define PROF_EXECUTE_BUILTIN 19 #define PROF_EMPTYFUNC 20 #define PROF_NOCODE 21 #define PROF_LESSERWHOLE 22 #define PROF_EQUALWHOLE 23 #define PROF_PARTIAL_EXEC 24 #define PROF_ADDWHOLE 25 #define PROF_FULL_EXEC 26 #define PROF_OPT_EXEC_USER 27 #define PROF_OPT_EXEC_BUILT 28 #define PROF_VIRTUAL_DECODE 27 #define PROF_VIRTUAL_EXECUTE 28 /*#define VIS_PROFILE_START(index) vis_profile_start_times[index] = rdtsc() #define VIS_PROFILE_END(index) vis_profile_running_total[index] += (rdtsc()-vis_profile_start_times[index]); ++vis_profile_counts[index] #else #define VIS_PROFILE_START(index) #define VIS_PROFILE_END(index)*/ #endif queue_entry * worker_queue; queue_section first_section; queue_section * current_section; int queue_start; int queue_len; BOOL execute_active=FALSE; char text_buf[256]; int text_buf_size; VIS_CRITICAL_SECTION(text_buf_lock) #ifdef WIN32 WSADATA wsa_data; #ifdef GUI_LIB char errorbuffer[1024]; #endif #endif worker_instance * main_instance; //company companylist[40]; //int num_companies=0; datum * global_store_dict; VIS_CRITICAL_SECTION(global_store_lock); int empty_func(datum ** a, queue_entry * worker_entry) { return 0; } worker_impl empty_test = empty_func; /* void set_in_child(worker_def * parent, int worker_num, BOOL * in_child, BOOL value, int exclude_worker) { int j,i = parent->workerlist[worker_num].wire_down_lookup; if(exclude_worker >= 0 && exclude_worker == worker_num) return; in_child[worker_num] = value; while(parent->wirelist[j=parent->workers_to_wires_down[i]].start_worker == worker_num && j >= 0) set_in_child(parent, parent->wirelist[j].end_worker, in_child, value); } void build_child_worker(worker_def * parent, int worker_num, int output_num) { int i,j, num_child_workers, num_child_wires, child_def; BOOL * in_child = malloc(sizeof(BOOL)* parent->num_workers); int * child_offsets = malloc(sizeof(int) * parent->num_workers); for(i = 0; i < parent->num_workers; ++i) { in_child[i] = FALSE; child_offsets[i] = -1; } i = parent->workerlist[worker_num].wire_down_lookup; while(parent->wirelist[j=parent->workers_to_wires_down[i]].start_worker == worker_num && j >= 0) { if(parent->wirelist[j].output_num == output_num) set_in_child(parent, parent->wirelist[j].end_worker, in_child, TRUE,-1); } i = parent->workerlist[worker_num].wire_down_lookup; while(parent->wirelist[j=parent->workers_to_wires_down[i]].start_worker == worker_num && j >= 0) { if(parent->wirelist[j].output_num != output_num) set_in_child(parent, parent->wirelist[j].end_worker, in_child, FALSE,-1); } for(i = 0; i < parent->num_workers; ++i) { if(i != worker_num && (parent->workerlist[i].type == 4 || (parent->workerlist[i].type == 2 && !in_child[i]))) set_in_child(parent, i, in_child, FALSE); } for(i = 0; i < parent->num_workers; ++i) { if(in_child[i]) child_offests[i] = num_child_workers++; } for(i = 0; i < parent->num_wires; ++i) { if(in_child[parent->wirelist[i].start_worker] || in_child[parent->wirelist[i].end_worker]) ++num_child_wires; } child_def = num_defs++;//needs lock or atomic incrememnt deflist[child_def].workerlist = malloc(sizeof(worker)*num_child_workers); deflist[child_def].wirelist = malloc(sizeof(wire)*num_child_wires); for(i = 0; i < parent->num_workers; ++i) { if(in_child[i]) deflist[child_def].workerlist[child_offests[i]] = parent->workerlist[i]; } } */ #define MAX_TRACE_DEPTH 40 void print_stack_trace(worker_instance * stack_instance) { int i = 0; ERRORPUTS("Stack trace:\n"); while(stack_instance && i < MAX_TRACE_DEPTH) { ERRORPRINTF("%s\n", stack_instance->def->name); stack_instance = stack_instance->caller_instance; ++i; } if(stack_instance) { ERRORPUTS("Stack trace aborted after 40 entries\n"); } } void check_tail(worker_def * def) { custom_worker * worker = def->implement_func; int i,j,k,endworker; BOOL can_tail, outputs_handled[32]; for(i = 0; i < worker->num_workers; ++i) { if(worker->workerlist[i].type == WORKER) { can_tail = TRUE; for(j = 0; j < def->num_outputs; ++j) outputs_handled[j] = FALSE; j = worker->workerlist[i].wire_down_lookup; while((k=worker->workers_to_wires_down[j]) >= 0 && worker->wirelist[k].start_worker == i) { endworker = worker->wirelist[k].end_worker; if(worker->workerlist[endworker].type != OUTPUT || worker->workerlist[endworker].io_num != worker->wirelist[k].output_num) { can_tail = FALSE; break; } else outputs_handled[worker->wirelist[k].output_num] = TRUE; ++j; } if(can_tail) { for(j = 0; j < def->num_outputs; ++j) if(!outputs_handled[j]) { can_tail = FALSE; break; } if(can_tail) if(worker->workerlist[i].value_index == def) worker->workerlist[i].type = TAIL_RECURSE; else if(!def->num_stores) worker->workerlist[i].type = TAIL_CALL; } } } } BOOL method_match(char * name, char * method_name) { int i = 0; while(name[i] != '\0' && method_name[i] != '@' && method_name[i] != '\0') { if(name[i] != method_name[i]) return FALSE; ++i; } if(name[i] != '\0' || method_name[i] != '@') return FALSE; return TRUE; } worker_def * find_method(int type, char * name, int num_inputs, program * prog) { int i; worker_def * output = NULL; company * companylist = prog->companylist; VIS_EnterCriticalSection(companylist[type].lock); for(i = 0; i < companylist[type].num_methods; ++i) { //DEBUGPRINTF( "Checking method %s(%d,%d)\n", companylist[type].methodlist[i]->name, companylist[type].methodlist[i]->num_inputs, companylist[type].methodlist[i]->num_outputs); if(companylist[type].methodlist[i]->num_inputs == num_inputs && method_match(name, companylist[type].methodlist[i]->name)) { DEBUGPRINTF( "Found method: %s\n", companylist[type].methodlist[i]->name); output = companylist[type].methodlist[i]; break; } } VIS_LeaveCriticalSection(companylist[type].lock); return output; } worker_def * find_method_noinputcheck(int type, char * name, program * prog) { int i; worker_def * output = NULL; company * companylist = prog->companylist; VIS_EnterCriticalSection(companylist[type].lock); for(i = 0; i < companylist[type].num_methods; ++i) { //DEBUGPRINTF( "Checking method %s(%d,%d)\n", companylist[type].methodlist[i]->name, companylist[type].methodlist[i]->num_inputs, companylist[type].methodlist[i]->num_outputs); if(method_match(name, companylist[type].methodlist[i]->name)) { DEBUGPRINTF( "Found method: %s\n", companylist[type].methodlist[i]->name); output = companylist[type].methodlist[i]; break; } } VIS_LeaveCriticalSection(companylist[type].lock); return output; } worker_def * find_converter_method(int totype, int fromtype, program * prog) { int i; company * companylist = prog->companylist; DEBUGPRINTF( "Finding converter from %s to %s\n", companylist[fromtype].name, companylist[totype].name); //DEBUGPRINTF( "Num methods %d\n", companylist[totype].num_methods); for(i = 0; i < companylist[totype].num_methods; ++i) { //DEBUGPRINTF("methodlist[i]: %X\n", companylist[totype].methodlist[i]); DEBUGPRINTF( "Checking method %s\n", companylist[totype].methodlist[i]->name); if(companylist[totype].methodlist[i]->name[0] == '<' && method_match(companylist[fromtype].name, companylist[totype].methodlist[i]->name+1)) { DEBUGPRINTF( "Found Method %s\n", companylist[totype].methodlist[i]->name); return companylist[totype].methodlist[i]; } } return NULL; } worker_instance * init_custom_worker_type(int aworker, worker_instance * caller, worker_def * def, instance_callback callback, void * callback_data, datum ** params, int type) { int i, workerlist_size, j, add_index_count=0; int add_index[32]; datum * work_params[32]; datum * temp_params[3]; global_store * store; worker_instance * instance; BOOL release_params = TRUE; def_make_lookup(def); workerlist_size = sizeof(worker_instance_data)*(def->implement_func->num_workers); //DEBUGPRINTF("workerlist_size: %d * %d = %d, wirelist_size: %d * %d = %d.\n", sizeof(worker_instance_data), def->implement_func->num_workers, workerlist_size, sizeof(wire_instance_data), def->implement_func->num_wires, sizeof(wire_instance_data)*(def->implement_func->num_wires)); //DEBUGPRINTF("Before malloc(%d)\n",sizeof(worker_instance) + workerlist_size + sizeof(wire_instance_data)*(def->implement_func->num_wires)); if(type == TAIL_RECURSE || type == TAIL_CALL) { VIS_EnterCriticalSection(caller->counter_lock); if(caller->in_progress_count <= 1 && !caller->in_queue_count) { VIS_LeaveCriticalSection(caller->counter_lock); instance = caller; for(i = 0; i < instance->num_workers; ++i) { if(instance->def->implement_func->workerlist[i].type != WORKER && instance->def->implement_func->workerlist[i].type != TAIL_RECURSE && instance->def->implement_func->workerlist[i].type != TAIL_CALL && instance->workerlist[i].value) release_ref(instance->workerlist[i].value); if(instance->workerlist[i].ready_count && instance->workerlist[i].ready_count < (instance->def->implement_func->workerlist[i].num_inputs + (instance->def->implement_func->workerlist[i].null_input ? 1 : 0))) { DEBUGPRINTF("Freeing params for worker number %d, ready_count: %d, num_inputs: %d, null_input: %d, instance: %X\n", i, instance->workerlist[i].ready_count,instance->def->implement_func->workerlist[i].num_inputs, instance->def->implement_func->workerlist[i].null_input, instance); for(j = 0; j <= instance->def->implement_func->workerlist[i].num_inputs; ++j) { DEBUGPRINTF("Releasing param %d of worker %d\n", j, i); release_ref(instance->workerlist[i].params[j]); } } } for(i = 0; i < def->num_inputs; ++i) work_params[i] = params[i]; params = work_params; if(type == TAIL_RECURSE) { instance->in_progress_count = 0; //TODO: adjust profile counter? goto init_workerlist; } else { aworker = instance->worker_in_caller; callback = instance->callback; callback_data = instance->callback_data; caller = instance->caller_instance; VIS_DeleteCriticalSection(instance->counter_lock); free(instance); } } else { VIS_LeaveCriticalSection(caller->counter_lock); } } instance = MALLOC(sizeof(worker_instance) + workerlist_size/* + sizeof(wire_instance_data)*(def->implement_func->num_wires) */,"instance"); //DEBUGPRINTF("malloc returned %X.\n", instance); VIS_PROFILE_START(PROF_INIT_CUSTOM); //DEBUGPRINTF("init_custom_worker, instance: %X\n", instance); #ifdef USER_PROFILE QueryPerformanceCounter(&(instance->start)); #endif instance->def = def; instance->num_workers = def->implement_func->num_workers; instance->workerlist = (worker_instance_data *)(((char *)instance) + sizeof(worker_instance));//malloc(sizeof(worker_instance_data)*(def->implement_func->num_workers)); //DEBUGPRINTF("workerlist at %X\n", instance->workerlist); /*instance->num_wires = def->implement_func->num_wires; instance->wirelist = (wire_instance_data *)(((char *)(instance->workerlist)) + workerlist_size);//malloc(sizeof(wire_instance_data)*(def->implement_func->num_wires)); DEBUGPRINTF("wirelist at %X\n", instance->wirelist);*/ instance->callback = callback; instance->worker_in_caller = aworker; instance->callback_data = callback_data; instance->caller_instance = caller; VIS_InitializeCriticalSection(instance->counter_lock); instance->in_progress_count = 0; instance->in_queue_count = 0; if(def->num_stores) { instance->trans = MALLOC(sizeof(transaction) + sizeof(global_store_use) *(def->num_stores - 1),"transaction"); VIS_EnterCriticalSection(global_store_lock); for(i = 0; i < def->num_stores; ++i) { temp_params[0] = add_ref(global_store_dict); temp_params[1] = make_string(def->uses_stores[i], -1, def->program); vis_dict_index(temp_params, NULL); if(!temp_params[0]) { printf("Error: Global store %s is not initialized\n", def->uses_stores[i]); DEBUGPRINTF("Error: Global store %s is not initialized\n", def->uses_stores[i]); VIS_LeaveCriticalSection(global_store_lock); return NULL; } instance->trans->stores[i].store = temp_params[0]->c.generic.data; instance->trans->stores[i].instance_data = instance->trans->stores[i].begin_data = add_ref(instance->trans->stores[i].store->data); VIS_InitializeCriticalSection(instance->trans->stores[i].lock); //Is this really necessary? release_ref(temp_params[0]); } VIS_LeaveCriticalSection(global_store_lock); instance->trans->num_stores = def->num_stores; if((def->transaction_flags & TRANSACTION_WRITE) && (def->transaction_flags & TRANSACTION_TYPE_MASK) == TRANSACTION_RETRY) { release_params = FALSE; for(i = 0; i < def->num_inputs; ++i) instance->trans->params[i] = params[i]; } } else { instance->trans = NULL; } init_workerlist: //DEBUGPUTS("init worker values\n"); for(i = 0; i < instance->num_workers; ++i) { // DEBUGPRINTF("InitializeCriticalSection on workerlist[%d].worker_lock (%X)\n", i, &(instance->workerlist[i].worker_lock)); VIS_InitializeCriticalSection(instance->workerlist[i].worker_lock); //DEBUGPUTS("ready_count = 0\n"); instance->workerlist[i].ready_count = 0; if(def->implement_func->workerlist[i].type == INPUT && params) instance->workerlist[i].value = add_ref(params[def->implement_func->workerlist[i].io_num]); else //if(def->implement_func->workerlist[i].type != 2) instance->workerlist[i].value = NULL; //DEBUGPRINTF("instance->workerlist[%d].value = %X\n", i, instance->workerlist[i].value); for(j = 0; j <= def->implement_func->workerlist[i].num_inputs; ++j) instance->workerlist[i].params[j] = NULL; //DEBUGPRINTF("num_inputs: %d, null_input: %d\n", def->implement_func->workerlist[i].num_inputs, def->implement_func->workerlist[i].null_input); //There's still a potential race condition here, but it's unlikely to occur except on a system with an insane number of cores/processors //and only on custom workers that have more than 32 items that will be initially ready if(!def->implement_func->workerlist[i].num_inputs && !def->implement_func->workerlist[i].null_input) { DEBUGPRINTF("adding worker %s(%d) to queue\n", def->implement_func->workerlist[i].name, i); add_index[add_index_count++] = i; if(add_index_count == 32) { add_multiple(add_index, add_index_count, instance); add_index_count = 0; } //add_queue(i,instance); } } if(params) { if(release_params) { //DEBUGPUTS("release params\n"); for(i = 0; i < def->num_inputs; ++i) release_ref(params[i]); } } if(add_index_count > 0) add_multiple(add_index, add_index_count, instance); VIS_PROFILE_END(PROF_INIT_CUSTOM); return instance; } worker_instance * init_custom_worker(int aworker, worker_instance * caller, worker_def * def, instance_callback callback, void * callback_data, datum ** params) { return init_custom_worker_type(aworker, caller, def, callback, callback_data, params, WORKER); } void cleanup_check(queue_entry aworker) { char msg[256]; VIS_EnterCriticalSection(aworker.instance->counter_lock); --(aworker.instance->in_progress_count); DEBUGPRINTF( "Cleanup Check on %s<%d>:%X, in_progress: %d, in_queue: %d\n", aworker.instance->def->name, aworker.instance->worker_in_caller, aworker.instance, aworker.instance->in_progress_count,aworker.instance->in_queue_count); if(aworker.instance->in_progress_count == 0 && aworker.instance->in_queue_count == 0) { VIS_LeaveCriticalSection(aworker.instance->counter_lock); cleanup_custom_worker(aworker.instance, aworker.worker_num); } else { VIS_LeaveCriticalSection(aworker.instance->counter_lock); } } void cleanup_custom_worker(worker_instance * instance, int worker_num) { BOOL do_commit = TRUE; int i,j; queue_entry incaller; global_store * store; #ifdef USER_PROFILE LARGE_INTEGER end; LARGE_INTEGER duration; #endif if(instance->trans) { if(instance->def->transaction_flags & TRANSACTION_WRITE) { VIS_EnterCriticalSection(global_store_lock); if((instance->def->transaction_flags & TRANSACTION_TYPE_MASK) != TRANSACTION_FORCE) { for(i = 0; i < instance->trans->num_stores; ++i) { if(instance->trans->stores[i].begin_data != instance->trans->stores[i].store->data) { do_commit = FALSE; break; } } } if(do_commit) { for(i = 0; i < instance->trans->num_stores; ++i) { release_ref(instance->trans->stores[i].store->data); instance->trans->stores[i].store->data = instance->trans->stores[i].instance_data; } } VIS_LeaveCriticalSection(global_store_lock); if(!do_commit)//retry transaction { for(i = 0; i < instance->trans->num_stores; ++i) release_ref(instance->trans->stores[i].instance_data); puts("retrying transaction"); init_custom_worker(instance->worker_in_caller, instance->caller_instance, instance->def, instance->callback, instance->callback_data, instance->trans->params); } else if((instance->def->transaction_flags & TRANSACTION_TYPE_MASK) == TRANSACTION_RETRY) for(i = 0; i < instance->def->num_inputs; ++i) release_ref(instance->trans->params[i]); } else { for(i = 0; i < instance->trans->num_stores; ++i) release_ref(instance->trans->stores[i].instance_data); } VIS_FREE(instance->trans, "transaction"); } VIS_PROFILE_START(PROF_CLEANUP_CUSTOM); DEBUGPRINTF("Cleaning up custom worker: %s:%X\n", instance->def->name, instance); VIS_PROFILE_START(PROF_SUB_CALLBACK); if(instance->callback && do_commit) instance->callback(instance->caller_instance, instance->worker_in_caller, instance, instance->callback_data); //DEBUGPUTS("About to release refs\n"); VIS_PROFILE_END(PROF_SUB_CALLBACK); VIS_PROFILE_START(PROF_CLEANUP_RELEASE_REFS); /*for(i = 0; i < instance->def->implement_func->num_wires; ++i) { if(instance->wirelist[i].data) { DEBUGPRINTF("release_ref on wire %d\n", i); release_ref(instance->wirelist[i].data); } }*/ for(i = 0; i < instance->num_workers; ++i) { if(instance->def->implement_func->workerlist[i].type != WORKER && instance->def->implement_func->workerlist[i].type != TAIL_RECURSE && instance->def->implement_func->workerlist[i].type != TAIL_CALL && instance->workerlist[i].value) { DEBUGPRINTF( "release_ref on worker %d in instance %X\n", i, instance); release_ref(instance->workerlist[i].value); } if(instance->workerlist[i].ready_count && instance->workerlist[i].ready_count < (instance->def->implement_func->workerlist[i].num_inputs + (instance->def->implement_func->workerlist[i].null_input ? 1 : 0))) { DEBUGPRINTF("Freeing params for worker number %d, ready_count: %d, num_inputs: %d, null_input: %d, instance: %X\n", i, instance->workerlist[i].ready_count,instance->def->implement_func->workerlist[i].num_inputs, instance->def->implement_func->workerlist[i].null_input, instance); for(j = 0; j <= instance->def->implement_func->workerlist[i].num_inputs; ++j) { DEBUGPRINTF("Releasing param %d of worker %d\n", j, i); release_ref(instance->workerlist[i].params[j]); } } VIS_DeleteCriticalSection(instance->workerlist[i].worker_lock); } VIS_PROFILE_END(PROF_CLEANUP_RELEASE_REFS); VIS_DeleteCriticalSection(instance->counter_lock); //DEBUGPUTS("freeing lists\n"); #ifdef USER_PROFILE if(do_commit) { QueryPerformanceCounter(&end); duration.QuadPart = end.QuadPart - instance->start.QuadPart; VIS_EnterCriticalSection(instance->def->lock); instance->def->total.QuadPart += duration.QuadPart; ++instance->def->count; if(duration.QuadPart > instance->def->worst.QuadPart) instance->def->worst.QuadPart = duration.QuadPart; VIS_LeaveCriticalSection(instance->def->lock); } #endif /*VIS_PROFILE_START(PROF_CLEANUP_FREELISTS); free(instance->workerlist); free(instance->wirelist); VIS_PROFILE_END(PROF_CLEANUP_FREELISTS);*/ VIS_PROFILE_START(PROF_CLEANUP_CHECK); if(instance->caller_instance && do_commit) { incaller.worker_num = instance->worker_in_caller; incaller.instance = instance->caller_instance; DEBUGPUTS("Calling cleanup_check on parent\n"); cleanup_check(incaller); } if(do_commit && instance->callback == main_callback) release_program_ref(instance->def->program); VIS_PROFILE_END(PROF_CLEANUP_CHECK); VIS_PROFILE_START(PROF_CLEANUP_FREELISTS); VIS_FREE(instance, "worker instance"); VIS_PROFILE_END(PROF_CLEANUP_FREELISTS); VIS_PROFILE_END(PROF_CLEANUP_CUSTOM); } /* void worker_complete(queue_entry aworker) { int i,j; wire * wirelist; int * workers_to_wires_down; VIS_PROFILE_START(PROF_WORKER_COMPLETE); DEBUGPUTS("worker_complete()\n"); i = aworker.instance->def->implement_func->workerlist[aworker.worker_num].wire_down_lookup; wirelist = aworker.instance->def->implement_func->wirelist; workers_to_wires_down = aworker.instance->def->implement_func->workers_to_wires_down; while(wirelist[j=workers_to_wires_down[i]].start_worker == aworker.worker_num && j >= 0) { if(aworker.instance->wirelist[j].data) { DEBUGPRINTF("end_worker: %d, wirelist[%d].data = %X\n", wirelist[j].end_worker, j, aworker.instance->wirelist[j].data); add_if_ready(wirelist[j].end_worker, aworker.instance); } ++i; } DEBUGPUTS("worker_complete done\n"); VIS_PROFILE_END(PROF_WORKER_COMPLETE); }*/ void process_outputs(datum ** params, int aworker, worker_instance * instance) { BOOL flag=FALSE; int i,j; worker_def * def = instance->def; //custom_worker *implement_func = def->implement_func; wire * def_wires = def->implement_func->wirelist; worker * def_workers = def->implement_func->workerlist; VIS_PROFILE_START(PROF_PROCESS_OUTPUTS); DEBUGPRINTF("Process outputs for worker %d in instance %X\n", aworker, instance); DEBUGPRINTF("Num_inputs: %d, num_outputs: %d\n", def_workers[aworker].num_inputs, def_workers[aworker].num_outputs); if(def_workers[aworker].num_outputs && instance->workerlist) { //DEBUGPRINTF("num_outputs: %d\n", def_workers[aworker].num_outputs); i = def_workers[aworker].wire_down_lookup; while((j=def->implement_func->workers_to_wires_down[i]) >= 0 && def_wires[j].start_worker == aworker) { //DEBUGPRINTF("Checking output: %d\n", def_wires[j].output_num); DEBUGPRINTF("output[%d] = %X\n", def_wires[j].output_num, params[def_wires[j].output_num]); DEBUGPRINTF("wire leads to worker %d, instance->workerlist: %X\n", def_wires[j].end_worker, instance->workerlist); VIS_EnterCriticalSection(instance->workerlist[def_wires[j].end_worker].worker_lock); if(params[def_wires[j].output_num] && !instance->workerlist[def_wires[j].end_worker].params[def_wires[j].input_num+1]) { //DEBUGPRINTF( "add_ref on output %d\n", def_wires[j].output_num); instance->workerlist[def_wires[j].end_worker].params[def_wires[j].input_num+1]=add_ref(params[def_wires[j].output_num]); //DEBUGPRINTF("Ready count was: %d, ", instance->workerlist[def_wires[j].end_worker].ready_count); ++instance->workerlist[def_wires[j].end_worker].ready_count; DEBUGPRINTF("Ready count is now: %d\n", instance->workerlist[def_wires[j].end_worker].ready_count); DEBUGPRINTF("num inputs: %d, null input: %d\n", instance->def->implement_func->workerlist[def_wires[j].end_worker].num_inputs, instance->def->implement_func->workerlist[def_wires[j].end_worker].null_input); if(instance->workerlist[def_wires[j].end_worker].ready_count >= (instance->def->implement_func->workerlist[def_wires[j].end_worker].num_inputs + (instance->def->implement_func->workerlist[def_wires[j].end_worker].null_input ? 1 : 0))) { //DEBUGPUTS("flag = true\n"); flag = TRUE; instance->workerlist[def_wires[j].end_worker].ready_count=0; } } VIS_LeaveCriticalSection(instance->workerlist[def_wires[j].end_worker].worker_lock); if(flag) { DEBUGPUTS("add_queue\n"); add_queue(def_wires[j].end_worker, instance); //add_if_ready(def_wires[j].end_worker, instance); flag = FALSE; } ++i; } //DEBUGPUTS("releasing refs\n"); for(i = 0; i < def_workers[aworker].num_outputs; ++i) release_ref(params[i]); } VIS_PROFILE_END(PROF_PROCESS_OUTPUTS); } void main_callback(worker_instance * junkinst, int junk, worker_instance * main_instance, void * data) { //MessageBox(NULL, "Main Callback", "Visuality Debug", MB_OK); VIS_EnterCriticalSection(program_count_lock); --program_count; if(program_count <= 0) { execute_active = FALSE; VIS_SetEvent(queue_add_event); } VIS_LeaveCriticalSection(program_count_lock); if(data) release_ref((datum *)data); } void sub_callback(worker_instance * caller_instance, int caller_workernum, worker_instance * done_instance, void * data) { int i; queue_entry incaller; datum * params[32]; worker_def * def = done_instance->def; custom_worker * implement_func = def->implement_func; incaller.worker_num = caller_workernum; incaller.instance = caller_instance; for(i = 0; i < def->num_outputs; ++i) params[i] = NULL; for(i = 0; i < implement_func->num_workers; ++i) { if(implement_func->workerlist[i].type == 4) { if(!params[implement_func->workerlist[i].io_num]) { params[implement_func->workerlist[i].io_num] = done_instance->workerlist[i].value; DEBUGPRINTF("Output[%d] = %X\n", implement_func->workerlist[i].io_num, done_instance->workerlist[i].value); done_instance->workerlist[i].value = NULL; } } } process_outputs(params, caller_workernum, caller_instance); //worker_complete(incaller); } void pack_list_sub_callback(worker_instance * caller_instance, int caller_workernum, worker_instance * done_instance, void * data) { int i; queue_entry incaller; datum * params[32]; datum * workparams[2]; incaller.worker_num = caller_workernum; incaller.instance = caller_instance; for(i = 0; i < done_instance->def->num_outputs; ++i) params[i] = NULL; for(i = 0; i < done_instance->def->implement_func->num_workers; ++i) { if(done_instance->def->implement_func->workerlist[i].type == 4) { if(!params[done_instance->def->implement_func->workerlist[i].io_num]) { params[done_instance->def->implement_func->workerlist[i].io_num] = done_instance->workerlist[i].value; done_instance->workerlist[i].value = NULL; } } } workparams[0] = create_list(done_instance->def->program); for(i = 0; i < done_instance->def->num_outputs; ++i) { workparams[1] = params[i]; vis_list_append(workparams, NULL); } process_outputs(workparams, caller_workernum, caller_instance); //worker_complete(incaller); } void transaction_sub_callback(worker_instance * caller_instance, int caller_workernum, worker_instance * done_instance, void * data) { int i; pack_list_sub_callback(caller_instance, caller_workernum, done_instance, NULL); } int global_argc; char ** global_argv; int spin_counter; void prep_program(program * prog) { defchunk * current; int i,j; make_lookup_arrays(prog); current = prog->defs; while(current) { for(i = 0; i < current->num_defs; ++i) { #ifdef USER_PROFILE current->deflist[i].count = 0; current->deflist[i].total.QuadPart = 0; current->deflist[i].worst.QuadPart = 0; VIS_InitializeCriticalSection(current->deflist[i].lock); #endif // USER_PROFILE //DEBUGPRINTF("Checking worker %s with type %X\n", current->deflist[i].name, current->deflist[i].type); if(current->deflist[i].type & USER_FLAG && (current->deflist[i].type & TYPE_MASK) == WORKER_TYPE) { //DEBUGPRINTF("Checking for constants in worker %s\n", current->deflist[i].name); for(j = 0; j < current->deflist[i].implement_func->num_workers; ++j) if(current->deflist[i].implement_func->workerlist[j].type == CONSTANT) { //current->deflist[i].implement_func->workerlist[j].value_index = (int)(get_constant(current->deflist[i].implement_func->workerlist[j].name,-1, initial_prog)); //DEBUGPRINTF("Set value_index for constant to %X in worker %s at index %d\n", current->deflist[i].implement_func->workerlist[j].value_index, current->deflist[i].name, j); } else if(current->deflist[i].implement_func->workerlist[j].type == WORKER || current->deflist[i].implement_func->workerlist[j].type == TAIL_CALL || current->deflist[i].implement_func->workerlist[j].type == TAIL_RECURSE) { current->deflist[i].implement_func->workerlist[j].num_inputs = ((worker_def *)current->deflist[i].implement_func->workerlist[j].value_index)->num_inputs; current->deflist[i].implement_func->workerlist[j].num_outputs = ((worker_def *)current->deflist[i].implement_func->workerlist[j].value_index)->num_outputs; } else current->deflist[i].implement_func->workerlist[j].value_index = 0; //DEBUGPRINTF("optimize %d\n", i); #ifdef ENABLE_OPT optimize(current->deflist + i); #endif } } current = current->next; } } void interp_start(int num_threads, BOOL use_this_thread, int argc, char ** argv, program * initial_prog) { defchunk * current; datum * params[2]; int i, junk,create_threads,j; #ifdef USER_PROFILE LARGE_INTEGER frequency; #endif lock_fail_counter = 0; lock_counter = 0; spin_counter = 0; #ifdef WIN32 //_CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_CHECK_CRT_DF | _CRTDBG_ALLOC_MEM_DF); WSAStartup(MAKEWORD(1, 1), &wsa_data); #endif VIS_InitializeCriticalSection(randlock); DEBUGPUTS("interp_start\n"); #ifdef ENABLE_PROFILING for(i = 0; i < NUM_PROFS; ++i) { vis_profile_running_total[i] = 0; vis_profile_counts[i] = 0; } VIS_PROFILE_START(PROF_EMPTYFUNC); empty_test(NULL,NULL); VIS_PROFILE_END(PROF_EMPTYFUNC); VIS_PROFILE_START(PROF_NOCODE); VIS_PROFILE_END(PROF_NOCODE); #endif global_argc = argc; global_argv = argv; init_sync_primitives(); init_datum_storage(); init_global_storage(initial_prog); //init queue current_section = &first_section; DEBUGPRINTF("current_section = %X, ¤t_section = %X\n", current_section, ¤t_section); worker_queue = current_section->entries; current_section->last = NULL; current_section->next = NULL; queue_start = queue_len = 0; // deflist[0].num_workers = num_workers; // deflist[0].num_wires = num_wires; prep_program(initial_prog); //MessageBox(NULL, "Before fopen", "visdbg", MB_OK); init_genrand(time(NULL)); execute_active = TRUE; DEBUGPUTS("Before init_custom_worker on Main\n"); params[0] = create_list(initial_prog); for(i = 0; i < argc; ++i) { params[1] = make_string(argv[i], -1, initial_prog); vis_list_append(params, NULL); } main_instance = init_custom_worker(-1, NULL, initial_prog->defs->deflist, main_callback, NULL, params); //num_datum = 0; #if COMPILE_THREADS > 0 create_threads = COMPILE_THREADS; if(num_threads > 0) create_threads = num_threads; if(use_this_thread) --create_threads; for(i = 0; i < create_threads; ++i) { #ifdef WIN32 CreateThread(NULL, 0, worker_thread, NULL, 0, &junk); #else #ifdef SYLLABLE resume_thread(spawn_thread("vis_worker", worker_thread, 1, 0, NULL)); #else pthread_t pid; pthread_create(&pid, NULL, worker_thread, NULL); #endif #endif } if(use_this_thread) worker_thread(NULL); #else worker_thread(NULL); #endif #ifdef ENABLE_PROFILING for(i = 0; i < NUM_PROFS; ++i) printf("%d:\t%f,\tcount: %d,\taverage: %f\n", i, (double)vis_profile_running_total[i], vis_profile_counts[i], ((double)vis_profile_running_total[i])/((double)vis_profile_counts[i])); #endif #ifdef USER_PROFILE printf("%-33s%12s%7s%15s%12s\n\n", "Worker", "Total", "Count", "Average", "Worst"); current = initial_prog->defs; while(current) { for(i = 0; i < current->num_defs; ++i) { if(current->deflist[i].count > 0) { printf("%-33s%12.0f%7d%15.2f%12.0f\n", current->deflist[i].name, (double)current->deflist[i].total.QuadPart, current->deflist[i].count, (double)current->deflist[i].total.QuadPart / (double)current->deflist[i].count, (double)current->deflist[i].worst.QuadPart); } } current = current->next; } QueryPerformanceFrequency(&frequency); printf("%.0f ticks per second\n", (double)frequency.QuadPart); #endif interp_stop(); } void interp_stop() { int i; execute_active = FALSE; close_sync_primitives(); // Doesn't make sense in the context of multiple programs // cleanup_custom_worker(main_instance); #ifdef WIN32 WSACleanup(); #endif #ifdef TEXT_FILE_DEBUG fclose(debugfile); #endif } extern void init_sync_primitives() { int i; DEBUGPUTS("Initializing data_lock\n"); VIS_InitializeCriticalSection(data_lock); DEBUGPUTS("Initializing worker_queue_lock\n"); VIS_InitializeCriticalSection(worker_queue_lock); DEBUGPUTS("Initializing text_buf_lock\n"); VIS_InitializeCriticalSection(text_buf_lock); #ifdef GUI_LIB #ifdef SYLLABLE DEBUGPUTS("vis_window_init\n"); vis_window_init(); #endif #endif //GUI_LIB VIS_CreateEvent(queue_add_event);//No security parameter, auto reset, starts signaled, no name } void close_sync_primitives() { int i; VIS_DeleteCriticalSection(data_lock); VIS_DeleteCriticalSection(worker_queue_lock); VIS_DestroyEvent(queue_add_event); } void init_global_storage(program * prog) { VIS_InitializeCriticalSection(global_store_lock); global_store_dict = create_dict(prog); } void add_multiple(int * data, int num, worker_instance * instance) { int i, index; queue_section * temp; DEBUGPRINTF( "Adding %d workers\n", num); VIS_EnterCriticalSection(instance->counter_lock); instance->in_queue_count += num; VIS_LeaveCriticalSection(instance->counter_lock); VIS_EnterCriticalSection(worker_queue_lock); for(i = 0; i < num; ++i) { if(queue_len >= QUEUE_SIZE) { if(current_section->next) { //DEBUGPUTS("Moving to next queue_section\n"); current_section = current_section->next; } else { //DEBUGPUTS("Allocating new queue_section\n"); VIS_PROFILE_START(PROF_ADDQUEUE_MALLOC); temp = MALLOC(sizeof(queue_section),"queue section"); VIS_PROFILE_END(PROF_ADDQUEUE_MALLOC); temp->last = current_section; temp->next = NULL; current_section->next = temp; current_section = temp; } worker_queue = current_section->entries; queue_start = queue_len = 0; } if(queue_start+queue_len < QUEUE_SIZE) index = queue_start+queue_len; else index = queue_start+queue_len-QUEUE_SIZE; worker_queue[index].worker_num=data[i]; worker_queue[index].instance = instance; ++queue_len; } VIS_LeaveCriticalSection(worker_queue_lock); //DEBUGPUTS("SetEvent\n"); VIS_SetEvent(queue_add_event); } void requeue(int data, worker_instance * instance) { add_queue(data, instance); VIS_EnterCriticalSection(instance->counter_lock); --(instance->in_progress_count); VIS_LeaveCriticalSection(instance->counter_lock); } void add_queue(int data, worker_instance * instance) { int index; queue_section * temp; VIS_PROFILE_START(PROF_ADDQUEUE); VIS_EnterCriticalSection(instance->counter_lock); ++(instance->in_queue_count); VIS_LeaveCriticalSection(instance->counter_lock); VIS_EnterCriticalSection(worker_queue_lock); if(queue_len >= QUEUE_SIZE) { if(current_section->next) { //DEBUGPUTS("Moving to next queue_section\n"); current_section = current_section->next; } else { //DEBUGPUTS("Allocating new queue_section\n"); VIS_PROFILE_START(PROF_ADDQUEUE_MALLOC); temp = MALLOC(sizeof(queue_section),"queue section"); VIS_PROFILE_END(PROF_ADDQUEUE_MALLOC); temp->last = current_section; temp->next = NULL; current_section->next = temp; current_section = temp; } worker_queue = current_section->entries; queue_start = queue_len = 0; } else if(queue_len == 0) { VIS_SetEvent(queue_add_event); //DEBUGPUTS("SetEvent\n"); } if(queue_start+queue_len < QUEUE_SIZE) index = queue_start+queue_len; else index = queue_start+queue_len-QUEUE_SIZE; worker_queue[index].worker_num=data; worker_queue[index].instance = instance; ++queue_len; VIS_LeaveCriticalSection(worker_queue_lock); VIS_PROFILE_END(PROF_ADDQUEUE); } /** * Retrieves a ready worker from the queue */ queue_entry get_queue() { queue_entry data; queue_section * temp; //DEBUGPUTS("Begin get_queue()\n"); VIS_EnterCriticalSection(worker_queue_lock); while(!queue_len && execute_active) { //DEBUGPUTS("Queue empty, resetting event\n"); VIS_ResetEvent(queue_add_event); VIS_LeaveCriticalSection(worker_queue_lock); //DEBUGPUTS("Waiting for queue_add_event\n"); VIS_WaitEvent(queue_add_event); #ifdef NINTENDO_DS //TODO make the processor sleep while waiting for IRQs if(irq_queue_count > 0) run_queued_irqs(); #endif VIS_EnterCriticalSection(worker_queue_lock); } if(queue_len > 0) { data = worker_queue[queue_start]; //DEBUGPRINTF( "Next worker in queue: %d\n", data.worker_num); //DEBUGPRINTF("data.instance: %X, data.instance->workerlist: %X\n", data.instance, data.instance->workerlist); /*VIS_EnterCriticalSection(data.instance->workerlist[data.worker_num].worker_lock); DEBUGPUTS("Adjusting ready_count"); data.instance->workerlist[data.worker_num].ready_count=0; VIS_LeaveCriticalSection(data.instance->workerlist[data.worker_num].worker_lock);*/ ++queue_start; --queue_len; //DEBUGPUTS("Adjusted ready count.\n"); //DEBUGPRINTF("current_section: %X\n", current_section); if(queue_len == 0 && current_section->last) { if(current_section->next != NULL) { //DEBUGPUTS("Freeing current_section->next.\n"); VIS_FREE(current_section->next, "ready queue node"); current_section->next = NULL; } current_section = current_section->last; worker_queue = current_section->entries; queue_start = 0; queue_len = QUEUE_SIZE; } else if(queue_start == QUEUE_SIZE) queue_start = 0; } else { //DEBUGPUTS("Queue empty\n"); data.worker_num = -2; } VIS_LeaveCriticalSection(worker_queue_lock); //DEBUGPUTS("Left worker_queue_lock\n"); //MessageBox(NULL,"AfterLeave","visdbg",MB_OK); if(data.worker_num >= 0) { VIS_EnterCriticalSection(data.instance->counter_lock); //DEBUGPUTS("Adjusting in_queue/in_progress counts.\n"); --(data.instance->in_queue_count); ++(data.instance->in_progress_count); DEBUGPRINTF( "Counts for %s<%d> Instance:%X after get_queue: in_queue: %d in_progress: %d\n",data.instance->def->name, data.instance->worker_in_caller, data.instance, data.instance->in_queue_count, data.instance->in_progress_count); VIS_LeaveCriticalSection(data.instance->counter_lock); } //DEBUGPUTS("End get_queue()\n"); return data; } void def_make_lookup(worker_def * def) { int i, j, upoffset, offset; VIS_EnterCriticalSection(def->implement_func->lock); if(def->implement_func->dirty) { upoffset = offset = 0; for(i = 0; i < def->implement_func->num_workers; ++i) { def->implement_func->workerlist[i].wire_down_lookup=offset; def->implement_func->workerlist[i].wire_up_lookup=upoffset; for(j = 0; j < def->implement_func->num_wires; ++j) { if(def->implement_func->wirelist[j].start_worker == i) def->implement_func->workers_to_wires_down[offset++]=j; if(def->implement_func->wirelist[j].end_worker == i) def->implement_func->workers_to_wires_up[upoffset++]=j; } //Clear tail call info if(def->implement_func->workerlist[i].type == TAIL_CALL || def->implement_func->workerlist[i].type == TAIL_RECURSE) def->implement_func->workerlist[i].type = WORKER; } def->implement_func->workers_to_wires_down[offset]=-1; def->implement_func->workers_to_wires_up[upoffset]=-1; check_tail(def); def->implement_func->dirty = FALSE; } VIS_LeaveCriticalSection(def->implement_func->lock); } /** * Generates lookup array to ease navigation between workers */ void make_lookup_arrays(program * prog) { int i,j,k, offset, upoffset; worker_def * deflist; defchunk * current = prog->defs; while(current) { deflist = current->deflist; for(k = 0; k < current->num_defs; ++k) { if(deflist[k].type & USER_FLAG && (deflist[k].type & TYPE_MASK) == WORKER_TYPE) def_make_lookup(deflist + k); } current = current->next; } } extern char _end_bss[]; void initpredefworkers(program * prog) { int current_def = 1; int current_company = 0; int current_method; int comp_room; company * this_comp; worker_def * aworker; create_company(prog, "Any Type", 0, 0, FALSE); create_company(prog, "Yes No", 0, 0, FALSE); aworker = create_worker(prog, "Print", 1, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_print; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Random", 0, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_random; aworker = create_worker(prog, "Build", 1, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_build; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "End", 1, 0, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_end; aworker->input_types[0] = ANY_TYPE; create_worker(prog, "Append", 2, 1, MAGIC_TYPE); create_worker(prog, "+", 2, 1, MAGIC_TYPE); create_worker(prog, "-", 2, 1, MAGIC_TYPE); create_worker(prog, "*", 2, 1, MAGIC_TYPE); create_worker(prog, "/", 2, 1, MAGIC_TYPE); create_worker(prog, ">", 2, 1, MAGIC_TYPE); create_worker(prog, "<", 2, 1, MAGIC_TYPE); create_worker(prog, "=", 2, 1, MAGIC_TYPE); aworker = create_worker(prog, "Get Input", 0, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_getinput; aworker = create_worker(prog, "If",1, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_if; aworker->input_types[0] = BUILTIN_TYPE_YESNO; aworker = create_worker(prog, "Type Of",1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_type_of; aworker->input_types[0] = ANY_TYPE; aworker = create_worker(prog, "Init Store",1, 0, WORKER_TYPE); aworker->implement_func=(custom_worker *)init_global_store; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Wait Forever", 0, 0, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_wait_forever; #ifdef NINTENDO_DS aworker = create_worker(prog, "Register Handler", 2, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_register_handler; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WORKER; aworker = create_worker(prog, "Clear Handler", 1, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_clear_handler; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Held Keys", 0, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_held_keys; aworker = create_worker(prog, "Touch Position", 0, 2, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_touch_position; #endif current_method = 0; //strcpy(companylist[current_company].name, "String"); #ifdef SEGA this_comp = create_company(prog, "String", 6, 0, FALSE); #else this_comp = create_company(prog, "String", 7, 0, FALSE); #endif aworker = create_worker(prog, "<Whole Number@String",1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_inttostring; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); #ifndef SEGA aworker = create_worker(prog, "<Real Number@String",1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_realtostring; aworker->input_types[0] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); #endif aworker = create_worker(prog, "=@String",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_stringequal; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "<Yes No@String",1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_yesnotostring; aworker->input_types[0] = BUILTIN_TYPE_YESNO; //add_method(this_comp, aworker); aworker = create_worker(prog, ">@String",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_greaterstring; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "<@String",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_lesserstring; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "Append@String",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_append; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "Split@String",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_string_split; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Get Raw@String",2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_string_get_raw; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = ANY_TYPE; aworker = create_worker(prog, "Put Raw@String",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_string_put_raw; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = ANY_TYPE; aworker = create_worker(prog, "Slice@String",2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_string_slice; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Reverse@String",1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_string_reverse; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Length@String",1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_string_length; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Put Byte@String",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_string_put_byte; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Get DString@String",2, 4, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_string_get_dstring; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = ANY_TYPE; current_method = 0; this_comp = create_company(prog, "Whole Number", 6, 0, FALSE); aworker = create_worker(prog, "<String@Whole Number",1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_stringtoint; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "From Hex@Whole Number",1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_fromhex; aworker->input_types[0] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "=@Whole Number",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_wholeequal; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, ">@Whole Number",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_greaterint; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, "<@Whole Number",2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_lesserint; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, "+@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_add; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, "-@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_subtract; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "*@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_mult; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, "/@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_div; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "&@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_and; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "|@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_or; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "LShift@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_lsh; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "RShift@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_rsh; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "%@Whole Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_modulus; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); current_method = 0; this_comp = create_company(prog, "Real Number", 6, 0, FALSE);//<string, =, >, <, +, - aworker = create_worker(prog, "<String@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_stringtoreal; aworker->input_types[0] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "=@Real Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_realequal; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker->input_types[1] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, ">@Real Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_greaterreal; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker->input_types[1] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "<@Real Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_lesserreal; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker->input_types[1] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "+@Real Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_add; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker->input_types[1] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "-@Real Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_subtract; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "/@Real Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_div; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "*@Real Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_mult; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Cosine@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_cos; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Sine@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_sin; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Tangent@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_tan; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Arc Cosine@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_arccos; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Arc Sine@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_arcsin; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Arc Tangent@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_arctan; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "^@Real Number", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_exp; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Square Root@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_sqrt; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Truncate to Whole@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_whole_fromreal; aworker->input_types[0] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "<Whole Number@Real Number", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_real_fromwhole; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); current_method = 0; this_comp = create_company(prog, "List", 7, 1, FALSE);//Index, Append, Swap, Insert, Remove, Set, Length, New comp_room = add_comp_room(this_comp, "Length", 0, 0, ROOM_NO_ACCESS, ROOM_LONG); aworker = create_worker(prog, "Index@List", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_index; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Append@List", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_append; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker->input_types[1] = ANY_TYPE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Swap@List",3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_swap; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker->input_types[2] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Insert@List",3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_insert; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker->input_types[2] = ANY_TYPE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Remove@List", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_remove; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Set@List",3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_set; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker->input_types[2] = ANY_TYPE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Length@List", 1, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_list_length; aworker->input_types[0] = BUILTIN_TYPE_LIST; //add_method(this_comp, aworker); aworker = create_worker(prog, "List",0, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_new; //add_method(this_comp, aworker); aworker = create_worker(prog, "First@List", 1, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_first; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker = create_worker(prog, "Next@List", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_list_next; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; current_method = 0; this_comp = create_company(prog, "Dictionary", 5, 0, FALSE);//Index, Swap, Remove, Set, Length, New aworker = create_worker(prog, "Index@Dictionary", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dict_index; aworker->input_types[0] = BUILTIN_TYPE_DICT; aworker->input_types[1] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "Swap@Dictionary",3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dict_swap; aworker->input_types[0] = BUILTIN_TYPE_DICT; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "Remove@Dictionary", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dict_remove; aworker->input_types[0] = BUILTIN_TYPE_DICT; aworker->input_types[1] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "Set@Dictionary",3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dict_set; aworker->input_types[0] = BUILTIN_TYPE_DICT; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = ANY_TYPE; aworker = create_worker(prog, "Length@Dictionary", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dict_length; aworker->input_types[0] = BUILTIN_TYPE_DICT; //add_method(this_comp, aworker); aworker = create_worker(prog, "Dictionary",0, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dict_new; //add_method(this_comp, aworker); aworker = create_worker(prog, "First@Dictionary", 1, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dict_first; aworker->input_types[0] = BUILTIN_TYPE_DICT; aworker = create_worker(prog, "Next@Dictionary", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dict_next; aworker->input_types[0] = BUILTIN_TYPE_DICT; aworker->input_types[1] = BUILTIN_TYPE_STRING; current_method = 0; #ifdef SEGA this_comp = create_company(prog, "File", 0, 0, FALSE); #else this_comp = create_company(prog, "File", 7, 0, FALSE);//<String, Get FString, Get DString, Get Byte, Get Word, Get Long, Put String aworker = create_worker(prog, "<String@File", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_from_string; aworker->input_types[0] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "Get FString@File", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_get_fstring; aworker->input_types[0] = BUILTIN_TYPE_FILE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Get DString@File", 2, 4, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_get_dstring; aworker->input_types[0] = BUILTIN_TYPE_FILE; aworker->input_types[1] = ANY_TYPE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Get Byte@File", 1, 3, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_get_byte; aworker->input_types[0] = BUILTIN_TYPE_FILE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Get Word@File", 1, 3, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_get_word; aworker->input_types[0] = BUILTIN_TYPE_FILE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Get Long@File", 1, 3, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_get_long; aworker->input_types[0] = BUILTIN_TYPE_FILE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Get Double@File", 1, 3, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_get_double; aworker->input_types[0] = BUILTIN_TYPE_FILE; aworker = create_worker(prog, "Put String@File", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_put_string; aworker->input_types[0] = BUILTIN_TYPE_FILE; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Length@File", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_file_length; aworker->input_types[0] = BUILTIN_TYPE_FILE; //add_method(this_comp, aworker); #endif current_method = 0; this_comp = create_company(prog, "Worker", 3, 0, FALSE);//<String, Do, Later: methods for manipulating aworker = create_worker(prog, "<String@Worker", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_from_string; aworker->input_types[0] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "Do@Worker", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_do; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_LIST; aworker = create_worker(prog, "Set Input@Worker", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_setinput; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker->input_types[2] = ANY_TYPE; //add_method(this_comp, aworker); aworker = create_worker(prog, "Add Worker Call@Worker", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_worker_call; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_WORKER; aworker = create_worker(prog, "Add Wire@Worker", 5, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_wire; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker->input_types[2] = BUILTIN_TYPE_WHOLE; aworker->input_types[3] = BUILTIN_TYPE_WHOLE; aworker->input_types[4] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Add Constant@Worker", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_constant; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = ANY_TYPE; aworker = create_worker(prog, "Add Input@Worker", 3, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_input; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Add Output@Worker", 3, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_output; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Add Object Get@Worker", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_objectget; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Add Object Set@Worker", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_objectset; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Add Global Get@Worker", 3, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_globalget; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Add Global Set@Worker", 3, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_add_globalset; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Clear@Worker", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_clear; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker = create_worker(prog, "Uses@Worker", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_uses; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_LIST; aworker = create_worker(prog, "Set IO Counts@Worker", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_setio_counts; aworker->input_types[0] = BUILTIN_TYPE_WORKER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker->input_types[2] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Worker", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_worker_new; aworker->input_types[0] = BUILTIN_TYPE_STRING; #ifdef GUI_LIB current_method = 0; this_comp = create_company(prog, "Window", 3, 0, FALSE); aworker = create_worker(prog, "Window", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_window_new; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "Add Widget@Window", 5, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_window_add_widget; aworker->input_types[0] = BUILTIN_TYPE_WINDOW; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = ANY_TYPE; aworker->input_types[3] = BUILTIN_TYPE_REAL; aworker->input_types[4] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "Show@Window", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_window_show; aworker->input_types[0] = BUILTIN_TYPE_WINDOW; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); current_method = 0; this_comp = create_company(prog, "Screen Window", 3, 0, FALSE); aworker = create_worker(prog, "Get Value@Screen Window", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_window_get_value; aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN; aworker->input_types[1] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); aworker = create_worker(prog, "Set Value@Screen Window", 3, 0, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_window_set_value; aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN; aworker->input_types[1] = BUILTIN_TYPE_STRING; #ifdef SYLLABLE aworker->input_types[2] = ANY_TYPE; #else aworker->input_types[2] = BUILTIN_TYPE_STRING; #endif //add_method(this_comp, aworker); aworker = create_worker(prog, "Wait Close@Screen Window", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_window_wait_close; aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN; //add_method(this_comp, aworker); #ifdef SYLLABLE aworker = create_worker(prog, "Add Widget@Screen Window", 5, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_window_shown_addwidget; aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = ANY_TYPE; aworker->input_types[3] = BUILTIN_TYPE_REAL; aworker->input_types[4] = BUILTIN_TYPE_REAL; #endif current_method = 0; create_company(prog, "Button", 2, 0, FALSE); aworker = create_worker(prog, "Button", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_button_new; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "Set Handler@Button", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_button_set_handler; aworker->input_types[0] = BUILTIN_TYPE_BUTTON; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_WORKER; //add_method(this_comp, aworker); current_method = 0; create_company(prog, "Input Box", 2, 0, FALSE); aworker = create_worker(prog, "Input Box", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_inputbox_new; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "Set Type@Input Box", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_inputbox_settype; aworker->input_types[0] = BUILTIN_TYPE_INPUTBOX; aworker->input_types[1] = BUILTIN_TYPE_STRING; //add_method(this_comp, aworker); #endif #ifndef NO_NET this_comp = create_company(prog, "Net Client", 3, 0, FALSE); aworker = create_worker(prog, "Net Client", 2, 1, WORKER_TYPE); aworker->implement_func =(custom_worker *)net_client_new; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Put String@Net Client", 2, 2, WORKER_TYPE); aworker->implement_func = (custom_worker *)net_client_put_string; aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Get FString@Net Client", 2, 3, WORKER_TYPE); aworker->implement_func = (custom_worker *)net_client_get_fstring; aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Get DString@Net Client", 2, 4, WORKER_TYPE); aworker->implement_func = (custom_worker *)net_client_get_dstring; aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; aworker->input_types[1] = ANY_TYPE; aworker = create_worker(prog, "Put Raw@Net Client", 2, 2, WORKER_TYPE); aworker->implement_func = (custom_worker *)net_client_put_raw; aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; aworker->input_types[1] = ANY_TYPE; aworker = create_worker(prog, "Get Raw@Net Client", 2, 3, WORKER_TYPE); aworker->implement_func = (custom_worker *)net_client_get_raw; aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; aworker->input_types[1] = ANY_TYPE; aworker = create_worker(prog, "Listen on Port", 2, 0, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_net_listenport; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WORKER; #endif create_company(prog, "Global Store", 0, 0, FALSE); create_company(prog, "Program", 5, 0, FALSE); aworker = create_worker(prog, "Program", 0, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_program_new; aworker = create_worker(prog, "New Worker@Program", 2, 2, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_program_new_worker; aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Add Worker@Program", 2, 2, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_program_add_worker; aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; aworker->input_types[1] = BUILTIN_TYPE_WORKER; aworker = create_worker(prog, "Add Builtins@Program", 1, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_program_add_builtins; aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; aworker = create_worker(prog, "Run@Program", 2, 1, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_program_run; aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; aworker->input_types[1] = ANY_TYPE; aworker = create_worker(prog, "Find Worker@Program", 2, 2, WORKER_TYPE); aworker->implement_func = (custom_worker *)vis_program_find_worker; aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; aworker->input_types[1] = BUILTIN_TYPE_STRING; #ifdef GUI_LIB #ifdef SYLLABLE create_company(prog, "Custom Widget", 2, 0, FALSE); aworker = create_worker(prog, "Custom Widget", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_customwidget_new; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "Set Handler@Custom Widget", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_button_set_handler; aworker->input_types[0] = BUILTIN_TYPE_CUSTOM_WIDGET; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_WORKER; //add_method(this_comp, aworker); create_company(prog, "Screen Custom Widget", 3, 0, FALSE); aworker = create_worker(prog, "Default Draw@Screen Custom Widget", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_defaultpaint; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; //add_method(this_comp, aworker); aworker = create_worker(prog, "Draw Line@Screen Custom Widget", 5, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_drawline; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; aworker->input_types[3] = BUILTIN_TYPE_REAL; aworker->input_types[4] = BUILTIN_TYPE_REAL; //add_method(this_comp, aworker); aworker = create_worker(prog, "Draw String@Screen Custom Widget", 4, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_drawstring; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_REAL; aworker->input_types[3] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Set Draw Color@Screen Custom Widget", 5, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_setdrawcolor; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker->input_types[2] = BUILTIN_TYPE_WHOLE; aworker->input_types[3] = BUILTIN_TYPE_WHOLE; aworker->input_types[4] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Move By@Screen Custom Widget", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_moveby; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Set Handler@Screen Custom Widget", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_sethandler; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_WORKER; aworker = create_worker(prog, "Remove Handler@Screen Custom Widget", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_removehandler; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Give Focus@Screen Custom Widget", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_givefocus; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; aworker->input_types[1] = BUILTIN_TYPE_YESNO; aworker = create_worker(prog, "Add Widget@Screen Custom Widget", 5, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_screen_custom_addwidget; aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = ANY_TYPE; aworker->input_types[3] = BUILTIN_TYPE_REAL; aworker->input_types[4] = BUILTIN_TYPE_REAL; #endif #endif create_company(prog, "Buffer", 7, 0, FALSE); aworker = create_worker(prog, "Buffer", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_new; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Lock@Buffer", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_lock; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; aworker = create_worker(prog, "Unlock@Buffer", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_unlock; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; aworker = create_worker(prog, "Put Byte@Buffer", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_putbyte; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Write Byte@Buffer", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_writebyte; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Put Word@Buffer", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_putshort; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Write Word@Buffer", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_writeshort; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Put Long@Buffer", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_putlong; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Write Long@Buffer", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_writelong; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; aworker = create_worker(prog, "Reset@Buffer", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_reset; aworker->input_types[0] = BUILTIN_TYPE_BUFFER; #if defined(SEGA) || defined(NINTENDO_DS) aworker = create_worker(prog, "From Address@Buffer", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_buffer_fromaddress; aworker->input_types[0] = BUILTIN_TYPE_WHOLE; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; #endif //SEGA create_company(prog, "Blueprint", 4, 0, FALSE); aworker = create_worker(prog, "Blueprint", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_blueprint_new; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Add Field@Blueprint", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_blueprint_addfield; aworker->input_types[0] = BUILTIN_TYPE_BLUEPRINT; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Name@Blueprint", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_blueprint_name; aworker->input_types[0] = BUILTIN_TYPE_BLUEPRINT; aworker = create_worker(prog, "Get Fields@Blueprint", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_blueprint_getfields; aworker->input_types[0] = BUILTIN_TYPE_BLUEPRINT; aworker = create_worker(prog, "Blueprint Of", 1, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_get_blueprint; aworker->input_types[0] = ANY_TYPE; aworker = create_worker(prog, "Get Field", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_get_field; aworker->input_types[0] = ANY_TYPE; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Set Field", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_set_field; aworker->input_types[0] = ANY_TYPE; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = ANY_TYPE; aworker = create_worker(prog, "New Blueprint@Program", 2, 2, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_program_newblueprint; aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; aworker->input_types[1] = BUILTIN_TYPE_STRING; #ifdef GUI_LIB #ifdef SYLLABLE create_company(prog, "Checkbox", 2, 0, FALSE); aworker = create_worker(prog, "Checkbox", 4, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_checkbox_new; aworker->input_types[0] = BUILTIN_TYPE_STRING; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; aworker->input_types[3] = BUILTIN_TYPE_YESNO; aworker = create_worker(prog, "Set Handler@Checkbox", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_button_set_handler; aworker->input_types[0] = BUILTIN_TYPE_CHECKBOX; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_WORKER; create_company(prog, "Dropdown", 4, 0, FALSE); aworker = create_worker(prog, "Dropdown", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dropdown_new; aworker->input_types[0] = BUILTIN_TYPE_LIST; aworker->input_types[1] = BUILTIN_TYPE_REAL; aworker->input_types[2] = BUILTIN_TYPE_REAL; aworker = create_worker(prog, "Set Handler@Dropdown", 3, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_button_set_handler; aworker->input_types[0] = BUILTIN_TYPE_DROPDOWN; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker->input_types[2] = BUILTIN_TYPE_WORKER; aworker = create_worker(prog, "Set Text@Dropdown", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dropdown_settext; aworker->input_types[0] = BUILTIN_TYPE_DROPDOWN; aworker->input_types[1] = BUILTIN_TYPE_STRING; aworker = create_worker(prog, "Select@Dropdown", 2, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)vis_dropdown_select; aworker->input_types[0] = BUILTIN_TYPE_DROPDOWN; aworker->input_types[1] = BUILTIN_TYPE_WHOLE; #endif #endif aworker = create_worker(prog, "Unix Time", 0, 1, WORKER_TYPE); aworker->implement_func=(custom_worker *)unix_time; /*if(current_def > num_defs) num_defs = current_def; if(current_company > num_companies) num_companies = current_company;*/ } void initworkers(program * prog) { //num_defs=0; //num_companies=0; create_worker(prog, "Main", 0, 0, USER_FLAG | WORKER_TYPE); initpredefworkers(prog); } /* void add_if_ready(int workerNum, worker_instance * instance) { //int i, j, n, old_ready_count; BOOL ready=FALSE; //int paramstore[32]; //int * params = paramstore; DEBUGPUTS("add_if_ready\n"); if(!instance || !instance->def) return; VIS_PROFILE_START(PROF_ADDREADY); DEBUGPRINTF( "add_if_ready on %s\n", instance->def->implement_func->workerlist[workerNum].name); VIS_EnterCriticalSection(instance->workerlist[workerNum].worker_lock); ++instance->workerlist[workerNum].ready_count; if(instance->workerlist[workerNum].ready_count >= (instance->def->implement_func->workerlist[workerNum].num_inputs + (instance->def->implement_func->workerlist[workerNum].null_input ? 1 : 0))) { ready = TRUE; instance->workerlist[workerNum].ready_count = 0; } VIS_LeaveCriticalSection(instance->workerlist[workerNum].worker_lock); if(ready) { DEBUGPRINTF("add_queue on %s\n", instance->def->implement_func->workerlist[workerNum].name); add_queue(workerNum, instance); } VIS_PROFILE_END(PROF_ADDREADY); }*/ #define RETURN_CODE_EXIT 0xABCE1234 #define RETURN_CODE_IDLE 0x00BADFAD #define RETURN_CODE_NORMAL 0xABBAABBA #define RETURN_CODE_PARALLEL 0xC001D00D #define GET_OP1(opcode) ((opcode & 0xF0000000) >> 28) #define GET_OP2(opcode) ((opcode & 0x0F000000) >> 24) #define GET_INST(opcode) ((opcode & 0x00FF0000) >> 16) #define MOVE_INST 0x00 #define ADDREF_INST 0x01 #define RELEASE_INST 0x02 #define LOAD_INST 0x03 #define CALL_INST 0x04 #define CALLB_INST 0x05 #define CALLP_INST 0x06 #define CALLBP_INST 0x07 #define RETURN_INST 0x08 #define BRANCH_INST 0x09 #define BRANCHT_INST 0x0A #define BRANCHF_INST 0x0B #define WAIT_INST 0x0C #define ADD_INST 0x0D #define SUB_INST 0x0E #define SUBR_INST 0x0F #define GREATER_INST 0x10 #define LESSER_INST 0x11 #define REGISTER_BIT 0x8 #define NO_OPERAND 0x7 #define OP_REG_MASK 0x7 #define GET_REGNUM1(opcode) ((opcode & 0x0000FF00) >> 8) #define GET_REGNUM2(opcode) (opcode & 0x000000FF) #define REG_DIRECT 0 #define REG_INDIRECT 1 #define IMMED_8 2 #define IMMED_32 3 #define STACK_8 4 #define REG_REL_32 5 #define PC_REL_8 6 #define STACK_REG 31 #define PC_REG 30 #define OPC(inst, op1, reg1, op2, reg2) ((op1 << 28) | (op2 << 24) | (inst << 16) | ((reg1 & 0xff) << 8) | (reg2 & 0xFF)) //unsigned long test_program[] = //{ // OPC(LOAD_INST, PC_REL_8, 8 /* Hi */, REG_DIRECT, 0), // OPC(CALLB_INST, IMMED_8, 1/* Print */, NO_OPERAND, 0), // OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0), // 26952//Hi //}; unsigned long test_program[] = { //Main: OPC(LOAD_INST, PC_REL_8, 20/* 10 */, REG_DIRECT, 0), OPC(LOAD_INST, PC_REL_8, 20/* 2 */, PC_REL_8, 28), OPC(LOAD_INST, PC_REL_8, 20/* 1 */, PC_REL_8, 28), OPC(CALL_INST, PC_REL_8, 28/* Fib: */, NO_OPERAND, 0), OPC(CALLB_INST, IMMED_8, 1/* Print */, NO_OPERAND, 0), OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0), 0x3033,//'30' 0x32,//'2' 0x31,//'1' 0,//2 storage 0,//1 storage //Fib: OPC(ADD_INST, IMMED_8, 8, REG_DIRECT, STACK_REG), OPC(MOVE_INST, REG_DIRECT, 0, STACK_8, -4), OPC(ADDREF_INST, REG_INDIRECT, 0, NO_OPERAND, 0), OPC(ADDREF_INST, REG_INDIRECT, 0, NO_OPERAND, 0), OPC(MOVE_INST, PC_REL_8, -28/* 2 */, REG_DIRECT, 1), OPC(ADDREF_INST, REG_INDIRECT, 1, NO_OPERAND, 0), OPC(CALLB_INST, IMMED_8, 8/* < */, NO_OPERAND, 0), OPC(CALLB_INST, IMMED_8, 11/* If */, NO_OPERAND, 0), OPC(BRANCHT_INST, PC_REL_8, 64/* _Base */, REG_DIRECT, 0), OPC(RELEASE_INST, REG_INDIRECT, 1, NO_OPERAND, 0), OPC(MOVE_INST, STACK_8, -4, REG_DIRECT, 0), OPC(MOVE_INST, PC_REL_8, -56/* 2 */, REG_DIRECT, 1), OPC(ADDREF_INST, REG_INDIRECT, 1, NO_OPERAND, 0), OPC(CALLB_INST, IMMED_8, 6/* - */, NO_OPERAND, 0), OPC(CALL_INST, PC_REL_8, -60/* Fib */, NO_OPERAND, 0), OPC(MOVE_INST, REG_DIRECT, 0, STACK_8, -8), OPC(MOVE_INST, STACK_8, -4, REG_DIRECT, 0), OPC(MOVE_INST, PC_REL_8, -76/* 1 */, REG_DIRECT, 1), OPC(ADDREF_INST, REG_INDIRECT, 1, NO_OPERAND, 0), OPC(CALLB_INST, IMMED_8, 6/* - */, NO_OPERAND, 0), OPC(CALL_INST, PC_REL_8, -84/* Fib */, NO_OPERAND, 0), OPC(MOVE_INST, STACK_8, -8, REG_DIRECT, 1), OPC(CALLB_INST, IMMED_8, 5/* + */, NO_OPERAND, 0), OPC(SUBR_INST, IMMED_8, 8, REG_DIRECT, STACK_REG), OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0), //_Base: OPC(RELEASE_INST, REG_INDIRECT, 0, NO_OPERAND, 0), OPC(MOVE_INST, PC_REL_8, -112/* 1 */, REG_DIRECT, 0), OPC(ADDREF_INST, REG_INDIRECT, 0, NO_OPERAND, 0), OPC(SUBR_INST, IMMED_8, 8, REG_DIRECT, STACK_REG), OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0), }; unsigned long * get_effective_address(char op, unsigned short regnum, unsigned long ** pc, unsigned long * registers, unsigned long * immed) { unsigned long * add = NULL; unsigned long work; if(op != NO_OPERAND) { if(op & REGISTER_BIT) add = (unsigned long *)(registers[regnum] + registers[op & OP_REG_MASK]); else { switch(op) { case REG_DIRECT: add = registers + regnum; break; case REG_INDIRECT: add = (unsigned long *) registers[regnum]; break; case IMMED_8: *immed = (char)regnum; add = (unsigned long *)immed; break; case IMMED_32: *immed = *((*pc)++); add = (unsigned long *)immed; break; case STACK_8: work = (char)regnum; add = (unsigned long *)(registers[STACK_REG] + work); break; case REG_REL_32: work = *((*pc)++); add = (unsigned long *)(registers[regnum] + work); break; case PC_REL_8: work = (char)regnum; add = (unsigned long *)(registers[PC_REG] + work); break; default: break; } } } return add; } DWORD WINAPI virtual_processor(unsigned long * program, BOOL main) { int i; unsigned long **pc; unsigned long **stack; unsigned long registers[32]; unsigned long opcode; unsigned long extra, extra2; queue_entry entry; stack_segment initial_stack; stack_segment * current = &initial_stack; char slot_usage[7]; char op1, op2; char inst; unsigned long *add1, *add2; long immed1, immed2; initial_stack.size = MIN_STACK_SIZE; initial_stack.parent = initial_stack.child = NULL; initial_stack.data[0] = main ? RETURN_CODE_EXIT : RETURN_CODE_IDLE; pc = (unsigned long **)(&(registers[PC_REG])); stack = (unsigned long **)(&(registers[STACK_REG])); *pc = program; *stack = (unsigned long *)(initial_stack.data + 1); entry.instance = NULL; entry.worker_num = 0; DEBUGPRINTF("Virtual processor, Program start: %X\n", program); #ifdef ENABLE_PROFILING for(i = 0; i < NUM_PROFS; ++i) { vis_profile_running_total[i] = 0; vis_profile_counts[i] = 0; } VIS_PROFILE_START(PROF_EMPTYFUNC); empty_test(NULL,NULL); VIS_PROFILE_END(PROF_EMPTYFUNC); VIS_PROFILE_START(PROF_NOCODE); VIS_PROFILE_END(PROF_NOCODE); #endif while(execute_active) { VIS_PROFILE_START(PROF_VIRTUAL_DECODE); DEBUGPRINTF("PC: %X\n", *pc); opcode = *((*pc)++); op1 = GET_OP1(opcode); op2 = GET_OP2(opcode); add1 = get_effective_address(op1, GET_REGNUM1(opcode), pc, registers, &immed1); add2 = get_effective_address(op2, GET_REGNUM2(opcode), pc, registers, &immed2); DEBUGPRINTF("Opcode: %X, Instruction: %X, op1 %X, op2 %X\n", opcode, GET_INST(opcode), op1, op2); inst = GET_INST(opcode); VIS_PROFILE_END(PROF_VIRTUAL_DECODE); VIS_PROFILE_START(PROF_VIRTUAL_EXECUTE); switch(inst) { case MOVE_INST: *add2 = *add1; break; case ADDREF_INST: add_ref((datum *)add1); break; case RELEASE_INST: release_ref((datum *)add1); break; /* Temporarily commented out until multiple program support is finished case LOAD_INST: *add2 = (long)get_constant((char *)add1, -1); break; */ case CALL_INST: *((*stack)++) = (unsigned long)*pc; *((*stack)++) = RETURN_CODE_NORMAL; *pc = add1; break; /* Temporarily commented out until multiple program support is finished case CALLB_INST: //TODO: Needs to be made 100% correct DEBUGPRINTF("Calling builtin: %s\n", deflist[*add1].name); execute_def(deflist + *add1, entry, (datum **)registers, NULL); break;*/ case CALLP_INST: //TODO Implement me break; case CALLBP_INST: //TODO Implement me break; case RETURN_INST: switch(*(--(*stack))) { case RETURN_CODE_EXIT: execute_active = FALSE; break; case RETURN_CODE_IDLE: //TODO: Implement me break; case RETURN_CODE_NORMAL: *pc = (unsigned long *)*(--(*stack)); break; default: break; } break; case BRANCH_INST: *pc = add1; break; case BRANCHT_INST: if(*add2) *pc = add1; break; case BRANCHF_INST: if(!*add2) *pc = add1; break; case WAIT_INST: //TODO: Implement Me break; case ADD_INST: *add2 = *add1 + *add2; break; case SUB_INST: *add2 = *add1 - *add2; break; case SUBR_INST: *add2 = *add2 - *add1; break; case GREATER_INST: *add2 = *add1 > *add2; break; case LESSER_INST: *add2 = *add1 < *add2; break; default: break; } VIS_PROFILE_END(PROF_VIRTUAL_EXECUTE); } #ifdef ENABLE_PROFILING for(i = 0; i < NUM_PROFS; ++i) printf("%d:\t%f,\tcount: %d,\taverage: %f\n", i, (double)vis_profile_running_total[i], vis_profile_counts[i], ((double)vis_profile_running_total[i])/((double)vis_profile_counts[i])); #endif return 0; } void test_virtual() { // int i,j,k; program * prog = new_program(START_DEF_STORAGE, START_COMP_STORAGE); initpredefworkers(prog); init_sync_primitives(); init_datum_storage(); //TODO Uncomment me // init_global_storage(); execute_active = TRUE; /* for(i = MOVE_INST; i <= LESSER_INST; ++i) { for(j = 0; j < 0x10; ++j) { for(k = 0; k < 0x10; ++k) { DEBUGPRINTF("i: %X, j: %X, k: %X, OPC: %X\n", i, j, k, OPC(i, j, j, k, k)); } } }*/ virtual_processor(test_program, TRUE); } DWORD WINAPI worker_thread(LPVOID param) { queue_entry aworker; int temp_queue_len; while(execute_active) { VIS_PROFILE_START(PROF_WORKER_THREAD); #ifdef NINTENDO_DS if(irq_queue_count > 0) run_queued_irqs(); #endif //DEBUGPUTS("Before WaitForSingleObect\n"); /*VIS_EnterCriticalSection(worker_queue_lock); temp_queue_len = queue_len; VIS_LeaveCriticalSection(worker_queue_lock);*/ //DEBUGPUTS("After WaitForSingleObject\n"); aworker = get_queue(); //DEBUGPUTS("After get_queue()\n"); //while(execute_active && aworker.worker_num < 0)//temp_queue_len == 0 && execute_active) //{ // VIS_WaitEvent(queue_add_event); // aworker = get_queue(); /*#if COMPILE_THREADS > 0 #ifdef WIN32 Sleep(0); #else sleep(0); #endif #endif VIS_EnterCriticalSection(worker_queue_lock); temp_queue_len = queue_len; VIS_LeaveCriticalSection(worker_queue_lock);*/ //} if(aworker.worker_num >= 0) { //DEBUGPUTS("Before EnterCriticalSection\n"); /* VIS_EnterCriticalSection(worker_queue_lock); if(queue_len > 0) { DEBUGPUTS("SetEvent\n"); VIS_SetEvent(queue_add_event); } VIS_LeaveCriticalSection(worker_queue_lock);*/ DEBUGPRINTF( "\nExecuting: %s<%d>, Instance: %X\n", aworker.instance->def->implement_func->workerlist[aworker.worker_num].name,aworker.worker_num,aworker.instance); if(process_worker(aworker) == 0) { //worker_complete(aworker); cleanup_check(aworker); //DEBUGPUTS("After cleanup_check\n"); } } VIS_PROFILE_END(PROF_WORKER_THREAD); } VIS_SetEvent(queue_add_event); return 0; } int set_comp_room(datum ** params, int room_index, queue_entry * entry, program * prog) { int i; char * data; //DEBUGPRINTF("params[0]->ref_count: %d\n", params[0]->ref_count); params[0] = copy_datum(params[0], 0); data = ((char *)(params[0]->c.generic.data) + (int)params[0]->company->room_list[room_index].set_func); DEBUGPRINTF("Set comp room: c.generic.data = %X, +get_func = %X\n", params[0]->c.generic.data, data); //TODO: input conversion switch(params[0]->company->room_list[room_index].get_func_type) { case ROOM_BYTE: *data = params[1]->c.integers.num_a; release_ref(params[1]); break; case ROOM_SHORT: *((short *)data) = params[1]->c.integers.num_a; release_ref(params[1]); break; case ROOM_LONG: *((long *)data) = params[1]->c.integers.num_a; release_ref(params[1]); break; case ROOM_SINGLE: *((float *)data) = params[1]->c.real; release_ref(params[1]); break; case ROOM_DOUBLE: *((double *)data) = params[1]->c.real; release_ref(params[1]); break; case ROOM_VIS_REF: release_ref(*((datum **)data)); *((datum **)data) = params[1]; break; case ROOM_CSTRING: //not implemented case ROOM_CSTRING_STRUCT: case ROOM_PSTRING: case ROOM_PSTRING_STRUCT: case ROOM_WORKER://not implemented case ROOM_VIS_OBJECT://not implemented default: release_ref(params[0]); release_ref(params[1]); params[0] = params[1] = NULL; puts("unimplemented company room type\n"); break; } return 0; } int set_comp_room_by_name(datum ** company, char * name, int * room_index_ret, queue_entry * entry, program * prog) { int i; for (i = 0; i < company[0]->company->num_rooms; ++i) if(!strcmp(name,company[0]->company->room_list[i].name)) { if(room_index_ret) *room_index_ret = i; return set_comp_room(company, i, entry, prog); } if(room_index_ret) *room_index_ret = -1; printf("Error: Can't set field %s on object with blueprint %s\n", name, company[0]->company); return -1; } int get_comp_room(datum ** company, int room_index, queue_entry * entry, program * prog) { int i; datum * out; queue_entry empty; char * data = ((char *)(company[0]->c.generic.data) + (int)company[0]->company->room_list[room_index].get_func); company[1] = NULL; DEBUGPRINTF("Get comp room: c.generic.data = %X, +get_func = %X\n", company[0]->c.generic.data, data); switch(company[0]->company->room_list[room_index].get_func_type) { case ROOM_BYTE: out = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, prog); out->c.integers.num_a = *data; break; case ROOM_SHORT: out = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, prog); out->c.integers.num_a = *((short *)data); break; case ROOM_LONG: out = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, prog); out->c.integers.num_a = *((long *)data); break; case ROOM_SINGLE: out = new_datum(BUILTIN_TYPE_REAL, 3, 0, prog); out->c.real = *((float *)data); break; case ROOM_DOUBLE: out = new_datum(BUILTIN_TYPE_REAL, 3, 0, prog); out->c.real = *((double *)data); break; case ROOM_CSTRING: data = *((char **)data); case ROOM_CSTRING_STRUCT: out = new_datum(BUILTIN_TYPE_STRING, 1, strlen(data)+1, prog); strcpy(out->c.generic.data, data); break; case ROOM_PSTRING: data = *((char **)data); case ROOM_PSTRING_STRUCT: out = new_datum(BUILTIN_TYPE_STRING, 1, *((unsigned char *)data), prog); memcpy(out->c.generic.data, data, *((unsigned char *)data)); ((char *)out->c.generic.data)[*((unsigned char *)data)] = '\0'; break; case ROOM_VIS_REF: out = add_ref(*((datum **)data)); if(!out) { company[1] = company[0]; company[0] = NULL; } break; case ROOM_WORKER: if(entry) return execute_def((worker_def *)(company[0]->company->room_list[room_index].get_func), *entry, company, sub_callback); else { empty.instance = NULL; empty.worker_num = -1; return execute_def((worker_def *)(company[0]->company->room_list[room_index].get_func), empty, company, sub_callback); } case ROOM_VIS_OBJECT://not implemented default: out = NULL; puts("unimplemented company room type\n"); break; } release_ref(company[0]); company[0] = out; return 0; } int get_comp_room_by_name(datum ** company, char * name, int * room_index_ret, queue_entry * entry, program * prog) { int i; for (i = 0; i < company[0]->company->num_rooms; ++i) if(!strcmp(name,company[0]->company->room_list[i].name)) { if(room_index_ret) *room_index_ret = i; return get_comp_room(company, i, entry, prog); } if(room_index_ret) *room_index_ret = -1; printf("Error: Can't get field %s from object with blueprint %s\n", name, company[0]->company); print_stack_trace(entry->instance); return -1; } datum * literal_string(char * value, int len, program * prog) { char literalchar; BOOL literal; int i, bufpos, lenstr; datum * returnval; if(len < 0) { len = strlen(value); } literal = FALSE; lenstr = 0; for(i = 0; i < len; ++i) if(literal) literal = FALSE; else { ++lenstr; if(value[i] == '\\') literal = TRUE; } //DEBUGPRINTF("Allocating %d bytes for string constant\n", lenstr+1); returnval = new_datum(BUILTIN_TYPE_STRING, 1, lenstr+1, prog); bufpos = 0; for(i = 0; i < len; ++i) { if(literal) { literal = FALSE; switch(value[i]) { case 'n': //newline literalchar = '\n'; break; case 'r': //carriage return literalchar = '\r'; break; case 't': // tab literalchar = '\t'; break; case '0': //NULL literalchar = '\0'; break; default: literalchar = value[i]; break; } ((char *)returnval->c.generic.data)[bufpos++] = literalchar; } else { if(value[i] == '\\') literal = TRUE; else { ((char *)returnval->c.generic.data)[bufpos++] = value[i]; } } } //DEBUGPRINTF("bufpos: %d\n", bufpos); ((char *)returnval->c.generic.data)[bufpos] = '\0'; DEBUGPUTS("Constant Type: String\n"); return returnval; } datum * get_constant(char * value, int len, program * prog) { datum * params[2]; datum * returnval; int i = 0,bufpos; int start; int lenstr; int leftcurly; int dotcount = 0; char literalchar; unsigned short const_type = ANY_TYPE; BOOL literal; if((len == 3 && memcmp(value, "Yes", len) == 0) || (len < 0 && strcmp(value, "Yes") == 0)) { DEBUGPUTS("Constnat: Yes\n"); returnval = new_datum(BUILTIN_TYPE_YESNO, 2, 0, prog); returnval->c.integers.num_a = 1; DEBUGPRINTF("Company: %s, integers.num_a: %d\n", returnval->company->name, returnval->c.integers.num_a); return returnval; } else if((len == 2 && memcmp(value, "No", len) == 0) || (len < 0 && strcmp(value, "No") == 0)) { DEBUGPUTS("Constant: No\n"); returnval = new_datum(BUILTIN_TYPE_YESNO, 2, 0, prog); returnval->c.integers.num_a = 0; DEBUGPRINTF("Company: %s, integers.num_a: %d\n", returnval->company->name, returnval->c.integers.num_a); return returnval; } if(value[0] == '{') { DEBUGPUTS("Constant type: List"); params[0] = create_list(prog); i = start = 1; literal = FALSE; leftcurly = 0; for(;value[i] != 0 && (len < 0 || i < len); ++i) { if(literal) literal = FALSE; else { if(value[i] == '\\') literal = TRUE; else if(value[i] == '}') if(leftcurly) --leftcurly; else break; else if(value[i] == '{') ++leftcurly; else if(value[i] == ',' && !leftcurly) { params[1] = get_constant(value+start, i-start, prog); vis_list_append(params, NULL); start = i+1; } } } params[1]= get_constant(value+start, i-start, prog); vis_list_append(params, NULL); returnval = params[0]; } else if(value[0] == '"') { if(len < 0) { len = strlen(value); } len -= 2; returnval = literal_string(value+1, len, prog); } else { while(value[i] != 0 && (len < 0 || i < len)) { if(value[i] >= '0' && value[i] <= '9') { if(const_type == ANY_TYPE) const_type = BUILTIN_TYPE_WHOLE; } else if(value[i] == '.') { if(dotcount) { const_type = BUILTIN_TYPE_STRING; } else { ++dotcount; if(const_type == BUILTIN_TYPE_WHOLE) const_type = BUILTIN_TYPE_REAL; } } else { //DEBUGPRINTF("Current character: %c resulted in String\n", value[i]); const_type = BUILTIN_TYPE_STRING; break; } ++i; } if(const_type == BUILTIN_TYPE_WHOLE) { returnval = new_datum(const_type, 2, 0, prog); returnval->c.integers.num_a = atol(value); DEBUGPUTS("Constant Type: Whole Number\n"); } else if(const_type == BUILTIN_TYPE_REAL) { returnval = new_datum(const_type, 3, 0, prog); returnval->c.real = atof(value); DEBUGPUTS("Constant Type: Real Number\n"); } else { /* literal = FALSE; lenstr = 0; for(i = 0; (i < len || len < 0) && value[i] != 0; ++i) if(literal) literal = FALSE; else { ++lenstr; if(value[i] == '\\') literal = TRUE; } DEBUGPRINTF("Allocating %d bytes for string constant\n", lenstr+1); returnval = new_datum(BUILTIN_TYPE_STRING, 1, lenstr+1, prog); bufpos = 0; for(i = 0; (i < len || len < 0) && value[i] != 0; ++i) { DEBUGPRINTF("bufpos: %d\n", bufpos); if(literal) { literal = FALSE; switch(value[i]) { case 'n': //newline literalchar = '\n'; break; case 'r': //carriage return literalchar = '\r'; break; case 't': // tab literalchar = '\t'; break; case '0': //NULL literalchar = '\0'; break; default: literalchar = value[i]; break; } ((char *)returnval->c.generic.data)[bufpos++] = literalchar; } else { if(value[i] == '\\') literal = TRUE; else { ((char *)returnval->c.generic.data)[bufpos++] = value[i]; } } } DEBUGPRINTF("bufpos: %d\n", bufpos); ((char *)returnval->c.generic.data)[bufpos] = '\0'; DEBUGPUTS("Constant Type: String\n"); */ returnval = literal_string(value, len, prog); } } return returnval; } int execute_def(worker_def * process_def, queue_entry worker_entry, datum ** params, instance_callback callback) { return execute_def_type(process_def, worker_entry, params, callback, NULL, WORKER); } int execute_def_data(worker_def * process_def, queue_entry worker_entry, datum ** params, instance_callback callback, void * data) { return execute_def_type(process_def, worker_entry, params, callback, data, WORKER); } int execute_def_type(worker_def * process_def, queue_entry worker_entry, datum ** params, instance_callback callback, void * data, int type) { int returnval, i; worker_instance * stack_instance; worker_def *temp_def, *converter; worker_def *parent_def = worker_entry.instance->def; unsigned short magic_cache_type; #ifdef USER_PROFILE LARGE_INTEGER start, end, duration; #endif VIS_PROFILE_START(PROF_PREP_MAGIC); if((process_def->type & TYPE_MASK) == MAGIC_TYPE) { DEBUGPRINTF( "Magic method: %s\n", process_def->name); if(!params || !params[0]) { ERRORPRINTF("Error: null first parmeter or null parameter array for worker %s, params: %X, params[0]: %X\n", process_def->name, params, params[0]); print_stack_trace(worker_entry.instance); execute_active = FALSE; return -1; } VIS_EnterCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock); temp_def = parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_implement; magic_cache_type = parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_type; VIS_LeaveCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock); if(!temp_def || magic_cache_type != params[0]->company->type_id) { DEBUGPRINTF("Finding method %s with %d inputs for type %s(%d)\n", process_def->name, process_def->num_inputs, params[0]->company->name, params[0]->company->type_id); temp_def = find_method(params[0]->company->type_id,process_def->name, process_def->num_inputs, process_def->program); if(!temp_def) { for(i = 1; i < process_def->program->num_companies; ++i) { temp_def = find_method(i,process_def->name, process_def->num_inputs, process_def->program); if(temp_def) { converter = find_converter_method(temp_def->input_types[0], params[0]->company->type_id, process_def->program); if(converter) { ((worker_impl)converter->implement_func)(params, &worker_entry); break; } else { //DEBUGPRINTF("Error: Needed conversion from %s to %s for input %d of %s\n", params[0]->company->name, process_def->program->companylist[temp_def->input_types[0]].name, 0, temp_def->name); //printf("Warning: Needed conversion from %s to %s for input %d of %s for loose method call\n", params[0]->company->name, process_def->program->companylist[temp_def->input_types[0]].name, 0, temp_def->name); temp_def = NULL; } } } } if(temp_def) { VIS_EnterCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock); parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_implement = temp_def; parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_type = temp_def->input_types[0]; VIS_LeaveCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock); } else { ERRORPRINTF("Error: Company %s doesn't implement worker %s. It implements the following:\n", params[0]->company->name, process_def->name); for(i = 0; i < params[0]->company->num_methods; ++i) { ERRORPRINTF("%s\n", params[0]->company->methodlist[i]->name); } print_stack_trace(worker_entry.instance); } } process_def = temp_def; } VIS_PROFILE_END(PROF_PREP_MAGIC); if(!process_def) { //DEBUGPUTS("Invalid def\n"); VIS_PROFILE_END(PROF_EXECUTE_WORKER); execute_active = FALSE; return -2; } VIS_PROFILE_START(PROF_CONVERT_INPUTS); for(i = 0; i < process_def->num_inputs; ++i) { DEBUGPRINTF("params[%d] = %X\n", i, params[i]); if(process_def->input_types[i] != ANY_TYPE && process_def->input_types[i] != params[i]->company->type_id) { DEBUGPRINTF("Input %d needs conversion from %d to %d\n", i, params[i]->company->type_id, process_def->input_types[i]); converter = find_converter_method(process_def->input_types[i], params[i]->company->type_id, process_def->program); if(!converter) { if(worker_entry.instance) { ERRORPRINTF("Error: Needed conversion from %s to %s for input %d of %s in worker %s\n", params[i]->company->name, process_def->program->companylist[process_def->input_types[i]].name, i, process_def->name, worker_entry.instance->def->name); print_stack_trace(worker_entry.instance); } else { DEBUGPRINTF("Error: Needed conversion from %s to %s for input %d of %s\n", params[i]->company->name, process_def->program->companylist[process_def->input_types[i]].name, i, process_def->name); printf("Error: Needed conversion from %s to %s for input %d of %s", params[i]->company->name, process_def->program->companylist[process_def->input_types[i]].name, i, process_def->name); } execute_active = FALSE; VIS_PROFILE_END(PROF_PROCESS_WORKER); return -3; } ((worker_impl)(converter->implement_func))(params+i, &worker_entry); } } VIS_PROFILE_END(PROF_CONVERT_INPUTS); if(process_def->type & USER_FLAG) { VIS_PROFILE_START(PROF_EXECUTE_CUSTOM); // init_custom_worker_type(worker_entry.worker_num, worker_entry.instance, process_def, callback, data, params, type); VIS_PROFILE_END(PROF_EXECUTE_CUSTOM); VIS_PROFILE_END(PROF_PROCESS_WORKER); VIS_PROFILE_END(PROF_EXECUTE_WORKER); return 1; } else { VIS_PROFILE_START(PROF_EXECUTE_BUILTIN); //DEBUGPRINTF("%s: before deflist[%d].implement_func: %X. vis_append: %X vis_print: %X\n",def->implement_func->workerlist[aworker].name, def->implement_func->workerlist[aworker].value_index, (int)deflist[def->implement_func->workerlist[aworker].value_index].implement_func, (int)vis_append, (int)vis_print); #ifdef USER_PROFILE QueryPerformanceCounter(&start); #endif returnval = ((worker_impl)(process_def->implement_func))(params, &worker_entry); #ifdef USER_PROFILE if(!returnval) { QueryPerformanceCounter(&end); duration.QuadPart = end.QuadPart - start.QuadPart; VIS_EnterCriticalSection(process_def->lock); process_def->total.QuadPart += duration.QuadPart; ++process_def->count; if(duration.QuadPart > process_def->worst.QuadPart) process_def->worst.QuadPart = duration.QuadPart; VIS_LeaveCriticalSection(process_def->lock); } #endif //DEBUGPUTS("Builtin worker returned\n"); VIS_PROFILE_END(PROF_EXECUTE_BUILTIN); return returnval; } } void wait_callback(worker_instance * caller_instance, int caller_workerenum, worker_instance * done_instance, void * data) { int i; def_done * done = (def_done *)data; //DEBUGPUTS("begin wait_callback\n"); for(i = 0; i < done_instance->def->num_outputs; ++i) done->params[i] = NULL; for(i = 0; i < done_instance->def->implement_func->num_workers; ++i) { if(done_instance->def->implement_func->workerlist[i].type == 4) { if(!(done->params[done_instance->def->implement_func->workerlist[i].io_num])) { done->params[done_instance->def->implement_func->workerlist[i].io_num] = done_instance->workerlist[i].value; done_instance->workerlist[i].value = NULL; } } } //DEBUGPUTS("Before EnterCritical\n"); VIS_EnterCriticalSection(done->lock); done->done_flag = TRUE; VIS_LeaveCriticalSection(done->lock); //DEBUGPUTS("After EnterCritical\n"); } BOOL execute_def_wait(worker_def * def, datum ** params) { int val; def_done done; queue_entry entry; entry.worker_num = 0; entry.instance = NULL; VIS_InitializeCriticalSection(done.lock); done.done_flag = FALSE; done.params = params; val = execute_def_data(def, entry, params, wait_callback, &done); if(val == 0) return TRUE; else if (val < 0) return FALSE; while(1) { VIS_EnterCriticalSection(done.lock); if(done.done_flag) { VIS_DeleteCriticalSection(done.lock); break; } VIS_LeaveCriticalSection(done.lock); #if COMPILE_THREADS > 1 #ifdef WIN32 Sleep(0); #else sleep(0); #endif #endif } return TRUE; } int process_worker(queue_entry worker_entry) { //datum * paramstore[32]; datum ** params;// = paramstore; int i, j, start=0; global_store * store; char * varname; datum * varname_dat; datum * tempvalindex, *todelete; int got_params=0; int aworker = worker_entry.worker_num; worker_instance * instance = worker_entry.instance; worker_def * def = instance->def; worker_def * process_def; worker_def * temp_def; worker_def * converter; int returnval = 0; short const_type; char * last; VIS_PROFILE_START(PROF_PROCESS_WORKER); DEBUGPRINTF( "Processing worker %d with %d inputs and %d outputs\n", aworker,def->implement_func->workerlist[aworker].num_inputs, def->implement_func->workerlist[aworker].num_outputs); /*VIS_EnterCriticalSection(instance->workerlist[aworker].worker_lock); for(i = 0; i < def->implement_func->workerlist[aworker].num_inputs; ++i) { params[i] = instance->workerlist[aworker].params[i+1]; DEBUGPRINTF("params[%d] = %X\n", i, params[i]); instance->workerlist[aworker].params[i+1] = NULL; }*/ if(def->implement_func->workerlist[aworker].null_input) { //DEBUGPUTS("About to call release_ref\n"); release_ref(instance->workerlist[aworker].params[0]); instance->workerlist[aworker].params[0] = NULL; } //VIS_LeaveCriticalSection(instance->workerlist[aworker].worker_lock); //DEBUGPRINTF("Param check complete. returnval: %d, start: %d\n", returnval, start); params = instance->workerlist[aworker].params+1; if(def->implement_func->workerlist[aworker].type == WORKER || def->implement_func->workerlist[aworker].type == TAIL_RECURSE || def->implement_func->workerlist[aworker].type == TAIL_CALL)//Worker { VIS_PROFILE_START(PROF_EXECUTE_WORKER); //DEBUGPUTS("Worker\n"); process_def = (worker_def *)(def->implement_func->workerlist[aworker].value_index); //DEBUGPUTS("Got process_def\n"); DEBUGPRINTF("process_def->type: %X, type & TYPE_MASK: %X\n", process_def->type, (process_def->type & TYPE_MASK)); returnval = execute_def_type(process_def, worker_entry, params, sub_callback, NULL, def->implement_func->workerlist[aworker].type); DEBUGPRINTF("execute_def returned %d\n", returnval); if(returnval != 0) { VIS_PROFILE_END(PROF_PROCESS_WORKER); VIS_PROFILE_END(PROF_EXECUTE_WORKER); return returnval; } //DEBUGPRINTF("params[0] after execute_def: %X\n", params[0]); //DEBUGPUTS("Before process_outputs\n"); process_outputs(params, aworker, instance); //DEBUGPUTS("After process_outputs\n"); VIS_PROFILE_END(PROF_EXECUTE_WORKER); } else if(def->implement_func->workerlist[aworker].type == GET_GLOBAL) { varname = def->implement_func->workerlist[aworker].name + def->implement_func->workerlist[aworker].io_num; varname_dat = make_string(varname, -1, def->program); if(def->implement_func->workerlist[aworker].value_index < 0) { for(i = 0; i < instance->trans->num_stores; ++i) { VIS_EnterCriticalSection(instance->trans->stores[i].lock); params[0] = add_ref(instance->trans->stores[i].instance_data); VIS_LeaveCriticalSection(instance->trans->stores[i].lock); params[1] = add_ref(varname_dat); vis_dict_index(params, NULL); if(params[0]) { def->implement_func->workerlist[aworker].value_index = i; break; } } if(def->implement_func->workerlist[aworker].value_index < 0) { printf("Error: Variable %s not found in any global stores used by worker %s\n", varname, def->name); DEBUGPRINTF("Error: Variable %s not found in any global stores used by worker %s\n", varname, def->name); execute_active = FALSE; return -1; } } else { VIS_EnterCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock); params[0] = add_ref(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].instance_data); VIS_LeaveCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock); params[1] = varname_dat; vis_dict_index(params, NULL); if(!params[0]) { printf("Error: Global variable %s not found in worker %s\n", def->implement_func->workerlist[aworker].name, def->name); DEBUGPRINTF("Error: Global variable %s not found in worker %s\n", def->implement_func->workerlist[aworker].name, def->name); execute_active = FALSE; return -1; } } process_outputs(params, aworker, instance); } else if(def->implement_func->workerlist[aworker].type == SET_GLOBAL) { varname = def->implement_func->workerlist[aworker].name + def->implement_func->workerlist[aworker].io_num; varname_dat = make_string(varname, -1, def->program); params[2] = params[0]; params[1] = varname_dat; VIS_EnterCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock); //no add_ref here because we'll be replacing instance_data with the result of vis_dict set params[0] = instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].instance_data; vis_dict_set(params, NULL); instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].instance_data = params[0]; VIS_LeaveCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock); //no outputs to process } else if(def->implement_func->workerlist[aworker].type == GET_COMP) { returnval = get_comp_room_by_name(params, def->implement_func->workerlist[aworker].name, NULL, &worker_entry, def->program); if(returnval) return returnval; process_outputs(params, aworker, instance); } else if(def->implement_func->workerlist[aworker].type == SET_COMP) { returnval = set_comp_room_by_name(params, def->implement_func->workerlist[aworker].name, NULL, &worker_entry, def->program); if(returnval) return returnval; process_outputs(params, aworker, instance); } else//Variable { VIS_PROFILE_START(PROF_EXECUTE_OTHER); if(def->implement_func->workerlist[aworker].num_inputs > 0 || def->implement_func->workerlist[aworker].type == INPUT) //Is this a Room or a constant? { todelete = NULL; VIS_EnterCriticalSection(instance->workerlist[aworker].worker_lock); if(def->implement_func->workerlist[aworker].type == OUTPUT) { todelete = instance->workerlist[aworker].value; instance->workerlist[aworker].value = params[0]; DEBUGPRINTF("Setting room/output at pos %d to %X in instance %X\n", aworker, params[0], instance); } //tempvalindex = instance->workerlist[aworker].value; VIS_LeaveCriticalSection(instance->workerlist[aworker].worker_lock); if(def->implement_func->workerlist[aworker].type == INPUT) { params[0] = instance->workerlist[aworker].value; instance->workerlist[aworker].value = NULL; } if(todelete) release_ref(todelete); if(def->implement_func->workerlist[aworker].num_outputs) { //add_ref(tempvalindex); process_outputs(params/*&tempvalindex*/, aworker, instance); } } else { //Hmm, do I potentially need another lock here? /*if(!(instance->def->implement_func->workerlist[aworker].value_index)) { instance->def->implement_func->workerlist[aworker].value_index = (int)(tempvalindex=get_constant(def->implement_func->workerlist[aworker].name,-1));//(int)tempvalindex; } else*/ tempvalindex = (datum *)instance->def->implement_func->workerlist[aworker].value_index; add_ref(tempvalindex); process_outputs(&tempvalindex, aworker, instance); } VIS_PROFILE_END(PROF_EXECUTE_OTHER); } VIS_PROFILE_END(PROF_PROCESS_WORKER); return returnval; } #define OPT_RESULT 0 #define OPT_CUST_RESULT 0x10000000 #define OPT_CONST 0x20000000 #define OPT_INPUT 0x30000000 int find_input_worker(custom_worker * cust, int aworker, int input, int *ret_output) { int o, p, wire_count; int out_worker; o = cust->workerlist[aworker].wire_up_lookup; wire_count = 0; while(cust->wirelist[p=cust->workers_to_wires_up[o]].end_worker == aworker && p >= 0) { if(cust->wirelist[p].input_num == input) { ++wire_count; out_worker = cust->wirelist[p].start_worker; DEBUGPRINTF("Input %d attached to %s(%d)\n", input, cust->workerlist[out_worker].name, out_worker); if(ret_output) *ret_output = cust->wirelist[p].output_num; } ++o; } DEBUGPRINTF("wire_count: %d\n", wire_count); if(wire_count == 1) return out_worker; return -1; } int make_input_code(custom_worker * cust, BOOL * in_opt, int * pos_in_opt, int source_worker, int output_num, int index, opt_entry * opts, int * branch_flags, opt_entry ** branch_refs, int input_num, program * prog) { /*if(in_opt[source_worker]) { if(prog->deflist[cust->workerlist[source_worker].value_index].type & USER_FLAG) { return OPT_CUST_RESULT | ((pos_in_opt[source_worker] & 0xFFFF) << 8) | (output_num & 0xFF); } else { if(strcmp(prog->deflist[cust->workerlist[source_worker].value_index].name, "If") == 0) { if(output_num == 0) { branch_flags[index] = 1; if(opts[pos_in_opt[source_worker]].branch1 <= index) opts[pos_in_opt[source_worker]].branch1 = index+1; } else { branch_flags[index] = 2; if(opts[pos_in_opt[source_worker]].branch2 <= index) opts[pos_in_opt[source_worker]].branch2 = index+1; } branch_refs[index] = opts + pos_in_opt[source_worker]; } else if(branch_flags[pos_in_opt[source_worker]]) { if(branch_flags[pos_in_opt[source_worker]] == 1) { branch_refs[pos_in_opt[source_worker]]->branch1 = index + 1; branch_flags[index] = 1; } else { branch_refs[pos_in_opt[source_worker]]->branch1 = index + 2; branch_flags[index] = 2; } branch_refs[index] = branch_refs[pos_in_opt[source_worker]]; } else branch_flags[index] = 0; if(input_num >= 0) ++opts[pos_in_opt[source_worker]].output_refs[output_num]; DEBUGPRINTF("OPT_RESULT: opt_num: %d, output_num: %d\n", pos_in_opt[source_worker], output_num); return OPT_RESULT | ((pos_in_opt[source_worker] & 0xFFFF) << 8) | (output_num & 0xFF); } } else if(cust->workerlist[source_worker].type == CONSTANT) { branch_flags[index] = 0; DEBUGPRINTF("OPT_CONST: %d\n", source_worker); return OPT_CONST | source_worker; } else if(cust->workerlist[source_worker].type == INPUT) { branch_flags[index] = 0; DEBUGPRINTF("OPT_INPUT: %d\n", cust->workerlist[source_worker].io_num); return OPT_INPUT | cust->workerlist[source_worker].io_num; }*/ return -1; } void optimize(worker_def * def) { /* int i,j,k,m,o,p; int * const_in; int num_entries = 0; int aworker; int adjust; int source_worker; int source_output; int source_null; int null_output; int wire_count; int * input_data; int current_null; int cust_result_count; int new_start; custom_worker * cust = def->implement_func; int start_current, end_current, new_current; worker_def * deflist = def->program->deflist; opt_entry * output = malloc(sizeof(opt_entry) * def->implement_func->num_workers); BOOL * in_opt = malloc(sizeof(BOOL) * cust->num_workers); int * branch_flags = malloc(sizeof(int) * cust->num_workers); opt_entry ** branch_refs = malloc(sizeof(int) * cust->num_workers); //BOOL * real_in_opt = malloc(sizeof(BOOL) * cust->num_workers); int * pos_in_opt = malloc(sizeof(int) * cust->num_workers); DEBUGPRINTF("deflist: %X\n", deflist); for(i = 0; i < cust->num_workers; ++i) { branch_flags[i] = 0; DEBUGPRINTF("%d: No input pass\n", i); DEBUGPRINTF("Examining: %s\n", cust->workerlist[i].name); if(cust->workerlist[i].num_inputs == 0 && !cust->workerlist[i].null_input && cust->workerlist[i].type == WORKER) { output[num_entries].def = deflist + cust->workerlist[i].value_index; DEBUGPRINTF("Set output[%d].def = %X\n", num_entries, output[num_entries].def); DEBUGPRINTF("opt: %d is %s\n\n", num_entries, cust->workerlist[i].name); output[num_entries].original_pos = i; output[num_entries].input_data = NULL; if(cust->workerlist[i].num_outputs) { output[num_entries].output_refs = malloc(sizeof(int)*cust->workerlist[i].num_outputs); for(j = 0; j < cust->workerlist[i].num_outputs; ++j) output[num_entries].output_refs[j] = 0; } else output[num_entries].output_refs = NULL; output[num_entries].branch1 = output[num_entries].branch2 = -1; //if(!(deflist[cust->workerlist[i].value_index].type & USER_FLAG)) //{ in_opt[i] = TRUE; pos_in_opt[i] = num_entries; //} //real_in_opt[i] = TRUE; ++num_entries; } else { //real_in_opt[i] = FALSE; in_opt[i] = FALSE; } } start_current = num_entries; for(i = 0; i < cust->num_workers; ++i) { DEBUGPRINTF("%d: Second pass\n", i); if(cust->workerlist[i].num_inputs == 0 && !cust->workerlist[i].null_input) { j = cust->workerlist[i].wire_down_lookup; while(cust->wirelist[k=cust->workers_to_wires_down[j]].start_worker == i && k >= 0) { aworker = cust->wirelist[k].end_worker; if(!in_opt[aworker]) { DEBUGPRINTF("Examining: %s(%d)\n", cust->workerlist[aworker].name, aworker); if(cust->workerlist[i].null_input) adjust = 1; else adjust = 0; input_data = malloc(sizeof(int)* (cust->workerlist[aworker].num_inputs+adjust)); for(m = (0-adjust); m < cust->workerlist[aworker].num_inputs; ++m) { DEBUGPRINTF("Input: %d\n", m); source_worker = find_input_worker(cust, aworker, m, &source_output); DEBUGPRINTF("source_worker: %d\n", source_worker); if(source_worker == -1) break; source_worker = make_input_code(cust, in_opt, pos_in_opt, source_worker, source_output, num_entries, output, branch_flags, branch_refs, m, def->program); DEBUGPRINTF("input code: %X\n", source_worker); if(source_worker == -1) break; input_data[m+adjust] = source_worker; if(source_worker == -1) break; } if(source_worker == -1) free(input_data); else { if(cust->workerlist[aworker].type == OUTPUT) output[num_entries].def = NULL; else output[num_entries].def = deflist + cust->workerlist[aworker].value_index; DEBUGPRINTF("Set output[%d].def = %X\n", num_entries, output[num_entries].def); DEBUGPRINTF("opt: %d is %s\n\n", num_entries, cust->workerlist[aworker].name); output[num_entries].original_pos = aworker; output[num_entries].input_data = input_data; output[num_entries].null_inputs = adjust; output[num_entries].branch1 = output[num_entries].branch2 = -1; if(cust->workerlist[aworker].num_outputs) { output[num_entries].output_refs = malloc(sizeof(int)*cust->workerlist[aworker].num_outputs); for(m = 0; m < cust->workerlist[aworker].num_outputs; ++m) output[num_entries].output_refs[m] = 0; } else output[num_entries].output_refs = NULL; //if(cust->workerlist[aworker].type != OUTPUT && !(deflist[cust->workerlist[aworker].value_index].type & USER_FLAG)) //{ in_opt[aworker] = TRUE; pos_in_opt[aworker] = num_entries; //} //real_in_opt[aworker] = TRUE; ++num_entries; } } ++j; } } } DEBUGPUTS("Before While\n"); end_current = num_entries; while(start_current != end_current) { DEBUGPRINTF("start_current: %d, end_current: %d\n", start_current, end_current); new_start = num_entries; for(i = start_current; i < end_current; ++i) { DEBUGPRINTF("opt: %d, def: %X, name: %s\n", i, output[i].def, cust->workerlist[output[i].original_pos].name); j = cust->workerlist[output[i].original_pos].wire_down_lookup; DEBUGPRINTF("wire_down_lookup: %d\n", j); while(cust->wirelist[k=cust->workers_to_wires_down[j]].start_worker == output[i].original_pos && k >= 0) { DEBUGPRINTF("Wire %d is attached to worker %d output %d and worker %d input %d\n", k, cust->wirelist[k].start_worker, cust->wirelist[k].output_num, cust->wirelist[k].end_worker, cust->wirelist[k].input_num); aworker = cust->wirelist[k].end_worker; //FIXME: Only works if constant/input attached to only one destination if(cust->workerlist[aworker].type == CONSTANT || cust->workerlist[aworker].type == INPUT) { DEBUGPRINTF("Worker is of type %d, ", cust->workerlist[aworker].type); aworker = cust->wirelist[cust->workers_to_wires_down[cust->workerlist[aworker].wire_down_lookup]].end_worker; DEBUGPRINTF("reruting to worker %d\n", aworker); } if(!in_opt[aworker]) { DEBUGPRINTF("Examining: %s(%d)\n", cust->workerlist[aworker].name, aworker); if(cust->workerlist[i].null_input) adjust = 1; else adjust = 0; for(m = (0-adjust); m < cust->workerlist[aworker].num_inputs; ++m) { source_worker = find_input_worker(cust, aworker, m, &source_output); if(source_worker == -1) break; if(cust->workerlist[source_worker].null_input && cust->workerlist[source_worker].type != WORKER) ++adjust; } if(source_worker != -1) { current_null = 0; input_data = malloc(sizeof(int)* (cust->workerlist[aworker].num_inputs+adjust)); cust_result_count = 0; for(m = (cust->workerlist[i].null_input ? -1 : 0); m < cust->workerlist[aworker].num_inputs; ++m) { DEBUGPRINTF("Input: %d\n", m); source_worker = find_input_worker(cust, aworker, m, &source_output); if(cust->workerlist[source_worker].null_input && cust->workerlist[source_worker].type != WORKER) { source_null = find_input_worker(cust, source_worker, -1, &null_output); if(source_null == -1) { source_worker = -1; break; } source_null = make_input_code(cust, in_opt, pos_in_opt, source_null, null_output, num_entries, output, branch_flags, branch_refs,-2, def->program); if((source_null & 0xF0000000) == OPT_CUST_RESULT) ++cust_result_count; if(source_null == -1) { source_worker = -1; break; } input_data[current_null++] = source_null; } DEBUGPRINTF("source_worker: %d\n", source_worker); source_worker = make_input_code(cust, in_opt, pos_in_opt, source_worker, source_output, num_entries, output, branch_flags, branch_refs, m, def->program); if((source_worker & 0xF0000000) == OPT_CUST_RESULT) ++cust_result_count; DEBUGPRINTF("input code: %d\n", source_worker); if(cust_result_count >= (cust->workerlist[aworker].num_inputs + adjust)) source_worker = -1; if(source_worker == -1) break; input_data[m+adjust] = source_worker; } if(source_worker == -1) free(input_data); else { if(cust->workerlist[aworker].type == OUTPUT) output[num_entries].def = NULL; else output[num_entries].def = deflist + cust->workerlist[aworker].value_index; DEBUGPRINTF("Set output[%d].def = %X\n", num_entries, output[num_entries].def); DEBUGPRINTF("opt: %d is %s\n\n", num_entries, cust->workerlist[aworker].name); output[num_entries].original_pos = aworker; output[num_entries].input_data = input_data; output[num_entries].null_inputs = adjust; output[num_entries].branch1 = output[num_entries].branch2 = -1; if(cust->workerlist[aworker].num_outputs) { output[num_entries].output_refs = malloc(sizeof(int)*cust->workerlist[aworker].num_outputs); for(m = 0; m < cust->workerlist[aworker].num_outputs; ++m) output[num_entries].output_refs[m] = 0; } else output[num_entries].output_refs = NULL; //if(cust->workerlist[aworker].type != OUTPUT && !(deflist[cust->workerlist[aworker].value_index].type & USER_FLAG)) //{ in_opt[aworker] = TRUE; pos_in_opt[aworker] = num_entries; //} //real_in_opt[aworker] = TRUE; ++num_entries; } } } ++j; } } start_current = new_start; end_current = num_entries; } def->optimized = output; def->opt_count = num_entries; DEBUGPUTS("optimize done\n\n\n"); */ } void run_optimized(worker_instance * instance, datum ** params) { int i = 0,j,k; unsigned short output, opt_num; datum * this_params[32]; queue_entry entry; datum * val; BOOL skip; BOOL partial_flag; BOOL continue_flag; int count; int ready; int jump_from = -1; int jump_to = -1; int tmp, addnum; opt_entry * exec_list = instance->def->optimized; datum ** results = instance->opt_results;//malloc(sizeof(datum *) * instance->def->opt_count * 32); VIS_PROFILE_START(PROF_RUN_OPT); entry.instance = instance; for(i = 0; i < instance->def->opt_count; ++i) { VIS_PROFILE_START(PROF_OPT_LOOP); skip = FALSE; partial_flag = FALSE; continue_flag = FALSE; DEBUGPRINTF("\nPeparing exec_list[%d]\n", i); if(exec_list[i].def) { DEBUGPRINTF("Name: %s\n", exec_list[i].def->name); count = exec_list[i].def->num_inputs; } else count = 1; count += exec_list[i].null_inputs; //DEBUGPRINTF("Input count: %d\n", count); if(count && !exec_list[i].input_data) puts("Runtime Error: input data is NULL\n"); //DEBUGPRINTF("input_data: %X\n", exec_list[i].input_data); VIS_PROFILE_START(PROF_OPT_PREP_INPUT); for(j = 0; j < count; ++j) { val = NULL; continue_flag = FALSE; switch(exec_list[i].input_data[j] & 0xF0000000) { case OPT_RESULT: output = exec_list[i].input_data[j] & 0xFF; opt_num = (exec_list[i].input_data[j] >> 8)& 0xFFFF; DEBUGPRINTF("OPT_RESULT for input %d, opt_num: %d, output: %d\n", j, opt_num, output); val = results[(opt_num * 32) | output]; break; case OPT_CUST_RESULT: val = NULL; partial_flag = TRUE; continue_flag = TRUE; break; case OPT_INPUT: DEBUGPRINTF("OPT_INPUT for input %d\n", j); val = add_ref(params[exec_list[i].input_data[j] & 0xFF]); break; case OPT_CONST: DEBUGPRINTF("OPT_CONST for input %d\n", j); val = add_ref((datum *)(instance->def->implement_func->workerlist[exec_list[i].input_data[j] & 0xFFFFFF].value_index)); break; default: puts("Runtime Error: Invalid bytecode\n"); val = NULL; break; } if(!val && !continue_flag) { for(k = exec_list[i].null_inputs; k < j; ++k) release_ref(this_params[k]); skip = TRUE; break; } DEBUGPRINTF("this_params[%d] = %X\n", j, val); if(j >= exec_list[i].null_inputs) if(val) this_params[j] = /*add_ref(*/val/*)*/; else this_params[j] = NULL; } VIS_PROFILE_END(PROF_OPT_PREP_INPUT); if(!skip) { if(partial_flag) { VIS_PROFILE_START(PROF_PARTIAL_EXEC); ready = 0; for(j = exec_list[i].null_inputs; j < count; ++j) if(this_params[j]) { instance->workerlist[exec_list[i].original_pos].params[j-exec_list[i].null_inputs+1] = this_params[j]; ++ready; } if(instance->def->implement_func->workerlist[exec_list[i].original_pos].null_input && this_params[exec_list[i].null_inputs-1]) ++ready; DEBUGPRINTF("ready: %d\n", ready); skip = TRUE; VIS_EnterCriticalSection(instance->workerlist[exec_list[i].original_pos].worker_lock); instance->workerlist[exec_list[i].original_pos].ready_count += ready; if(instance->workerlist[exec_list[i].original_pos].ready_count >= (exec_list[i].def->num_inputs + (instance->def->implement_func->workerlist[exec_list[i].original_pos].null_input ? 1 : 0))) { skip = FALSE; instance->workerlist[exec_list[i].original_pos].ready_count = 0; } DEBUGPRINTF("ready_count: %d\n", instance->workerlist[exec_list[i].original_pos].ready_count); VIS_LeaveCriticalSection(instance->workerlist[exec_list[i].original_pos].worker_lock); if(!skip) add_queue(exec_list[i].original_pos, instance); VIS_PROFILE_END(PROF_PARTIAL_EXEC); } else if(exec_list[i].def) { VIS_PROFILE_START(PROF_FULL_EXEC); DEBUGPRINTF("opt_exec: %s(%d)\n", exec_list[i].def->name, exec_list[i].original_pos); entry.worker_num = exec_list[i].original_pos; if(exec_list[i].def->type & USER_FLAG) { VIS_PROFILE_START(PROF_OPT_EXEC_USER); instance->workerlist[exec_list[i].original_pos].params[0] = NULL; memcpy(instance->workerlist[exec_list[i].original_pos].params+1, this_params + exec_list[i].null_inputs, sizeof(datum *) * exec_list[i].def->num_inputs); add_queue(exec_list[i].original_pos, instance); VIS_PROFILE_END(PROF_OPT_EXEC_USER); } else { VIS_PROFILE_START(PROF_OPT_EXEC_BUILT); if(execute_def(exec_list[i].def, entry, this_params + exec_list[i].null_inputs, sub_callback) == 0) { DEBUGPUTS("Exectuted with reslts\n"); if(exec_list[i].output_refs) { for(j = exec_list[i].null_inputs; j < (exec_list[i].def->num_outputs+exec_list[i].null_inputs); ++j) { DEBUGPRINTF("output_refs[%d] = %d\n", j-exec_list[i].null_inputs, exec_list[i].output_refs[j-exec_list[i].null_inputs]); if(!exec_list[i].output_refs[j-exec_list[i].null_inputs]) release_ref(this_params[j]); else if(exec_list[i].output_refs[j-exec_list[i].null_inputs] > 1) { /*DEBUGPRINTF("multi_add_ref(%X): %d\n", this_params[j], exec_list[i].output_refs[j-exec_list[i].null_inputs]-1); tmp = (int)(&(this_params[j]->ref_count)); addnum = exec_list[i].output_refs[j-exec_list[i].null_inputs]-1; __asm { mov ebx, tmp mov eax, addnum lock xadd dword ptr [ebx], eax }*/ VIS_EnterCriticalSection(this_params[j]->lock); this_params[j]->ref_count += exec_list[i].output_refs[j-exec_list[i].null_inputs]-1; VIS_LeaveCriticalSection(this_params[j]->lock); } } memcpy(results + i*32, this_params + exec_list[i].null_inputs, sizeof(datum *) * exec_list[i].def->num_outputs); if(exec_list[i].branch1 >= 0) { if(this_params[exec_list[i].null_inputs]) { jump_from = exec_list[i].branch1; jump_to = exec_list[i].branch2; } else { i = exec_list[i].branch1-1; } } } } /*else { for(j = exec_list[i].null_inputs; j < (exec_list[i].def->num_outputs + exec_list[i].null_inputs); ++j) results[(i*32)|j] = NULL; }*/ VIS_PROFILE_END(PROF_OPT_EXEC_BUILT); } VIS_PROFILE_END(PROF_FULL_EXEC); DEBUGPUTS("Executed\n"); } else instance->workerlist[exec_list[i].original_pos].value = this_params[exec_list[i].null_inputs]; } else { DEBUGPUTS("Skipped\n"); if(exec_list[i].def) { for(j = 0; j < exec_list[i].def->num_outputs; ++j) results[(i*32)|j] = NULL; } } if(jump_from >= 0 && (i+1) == jump_from) { i = jump_to-1; jump_from = -1; } VIS_PROFILE_END(PROF_OPT_LOOP); } DEBUGPUTS("run_optimized calling cleanup_check\n"); for(i = 0; i < instance->def->num_inputs; ++i) release_ref(params[i]); cleanup_check(entry); VIS_PROFILE_END(PROF_RUN_OPT); } int vis_print(datum ** inputlist, queue_entry * worker_entry) { int result; #ifdef CONSOLE puts((char *)inputlist[0]->c.generic.data); #else MessageBox(NULL, (char *)inputlist[0]->c.generic.data, "Visuality Output", MB_OK); #endif result = 1; release_ref(inputlist[0]); inputlist[0] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program); //No one else knows about this new datum yet so we can skip getting a lock datum_set_yesno(inputlist[0], result); return 0; } int unix_time(datum ** inputlist, queue_entry * worker_entry) { inputlist[0] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); inputlist[0]->c.integers.num_a = time(NULL); return 0; } int vis_end(datum ** inputlist, queue_entry * worker_entry) { // fprintf(outfile, "End worker reached.\n"); execute_active=FALSE; release_ref(inputlist[0]); //interp_stop(); return 0; } #ifdef NINTENDO_DS const char keyLetters[15] = "ABESRLUD><XYMC"; #define MAX_KEY_BITS 14 #endif int vis_getinput(datum ** inputlist, queue_entry * worker_entry) { #ifdef NINTENDO_DS int held,i,pos; char tempstring[14]; scanKeys(); held = keysHeld(); if(held) { pos = 0; for(i = 0; i < MAX_KEY_BITS; ++i) if(held & (1 << i)) tempstring[pos++] = keyLetters[i]; inputlist[0] = new_datum(BUILTIN_TYPE_STRING, 1, pos+1, worker_entry->instance->def->program); memcpy(inputlist[0]->c.generic.data, tempstring, pos); ((char *)inputlist[0]->c.generic.data)[pos]='\0'; return 0; } else { requeue(worker_entry->worker_num, worker_entry->instance); return 1; } #else #ifdef CONSOLE gets(text_buf); text_buf_size = strlen(text_buf); //Nasty hack for testing until I get around to supporting command line args propery //text_buf_size = strlen(global_argv[1]); #else while(text_buf_size <= 0) { Sleep(30); //TODO: replace with I/O queue mechanism } #endif // VIS_EnterCriticalSection(text_buf_lock); DEBUGPRINTF("Allocating %d bytes\n", text_buf_size+1); inputlist[0] = new_datum(BUILTIN_TYPE_STRING, 1, text_buf_size+1, worker_entry->instance->def->program); DEBUGPUTS("Allocated datum.\n"); memcpy(inputlist[0]->c.generic.data, text_buf, text_buf_size); DEBUGPUTS("Copied string.\n"); ((char *)inputlist[0]->c.generic.data)[text_buf_size]='\0'; DEBUGPRINTF("Input is %s\n", inputlist[0]->c.generic.data); text_buf_size = 0; // VIS_LeaveCriticalSection(text_buf_lock); return 0; #endif } int vis_if(datum ** inputlist, queue_entry * worker_entry) { if(!(inputlist[0]->c.integers.num_a)) { inputlist[1] = inputlist[0]; inputlist[0] = NULL; } else inputlist[1] = NULL; return 0; } int vis_build(datum ** inputlist, queue_entry * worker_entry) { int i,j; company * companylist = worker_entry->instance->def->program->companylist; int num_companies = worker_entry->instance->def->program->num_companies; DEBUGPRINTF("Looking for company named %s\n", inputlist[0]->c.generic.data); for(i = 0; i < num_companies; ++i) { DEBUGPRINTF("Checking company %d:%s\n", i, companylist[i].name); if(!strcmp(inputlist[0]->c.generic.data, companylist[i].name)) break; } release_ref(inputlist[0]); if(i < num_companies && companylist[i].build_size > 0) { DEBUGPRINTF("Building company with size %d\n", companylist[i].build_size); inputlist[0] = new_datum(i, 1, companylist[i].build_size, worker_entry->instance->def->program); for(j = 0; j < companylist[i].build_size; ++j) ((char*)(inputlist[0]->c.generic.data))[j] = 0; } else { DEBUGPUTS("Could not find company\n"); inputlist[0] = NULL; } return 0; } int vis_wait_forever(datum ** inputlist, queue_entry * worker_entry) { return 1; } int init_global_store(datum ** inputlist, queue_entry * worker_entry) { datum * params[3]; global_store * store; datum * store_dat = new_datum(BUILTIN_TYPE_GLOBAL_STORE, 1, sizeof(global_store), worker_entry->instance->def->program); store = store_dat->c.generic.data; store->name = add_ref(inputlist[0]); store->data = create_dict(worker_entry->instance->def->program); VIS_EnterCriticalSection(global_store_lock); params[0] = global_store_dict; params[1] = inputlist[0]; params[2] = store_dat; vis_dict_set(params, NULL); global_store_dict = params[0]; DEBUGPUTS("Global store init complete\n"); VIS_LeaveCriticalSection(global_store_lock); DEBUGPUTS("Released global_store_lock\n"); inputlist[0] = NULL; return 0; } int vis_type_of(datum ** inputlist, queue_entry * worker_entry) { datum * output = make_string(inputlist[0]->company->name, -1, worker_entry->instance->def->program); release_ref(inputlist[0]); inputlist[0] = output; return 0; } int vis_random(datum ** inputlist, queue_entry * worker_entry) { inputlist[0] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); VIS_EnterCriticalSection(randlock); inputlist[0]->c.integers.num_a = genrand_int32(); VIS_LeaveCriticalSection(randlock); return 0; }