Mercurial > repos > rhope
annotate interp.c @ 45:6420c35edb43
Fixed Linux makefile
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 30 Nov 2009 23:47:08 -0500 |
parents | 9ee9adc696e7 |
children | 429b5f441381 |
rev | line source |
---|---|
0 | 1 #ifdef WIN32 |
2 #include <windows.h> | |
3 #include <winsock.h> | |
4 #include <crtdbg.h> | |
5 #else | |
6 #ifdef SYLLABLE | |
7 #include <unistd.h> | |
8 #include <atheos/threads.h> | |
9 #else | |
10 #ifdef NINTENDO_DS | |
11 #include <nds.h> | |
12 #else | |
13 #include <unistd.h> | |
14 #include <pthread.h> | |
15 #endif | |
16 #endif | |
17 #endif | |
18 #include <stdio.h> | |
19 #include <stdlib.h> | |
20 #include <string.h> | |
21 #include <time.h> | |
22 #include "mt19937ar.h" | |
23 #include "interp.h" | |
24 #include "vis_threading.h" | |
25 #include "datum.h" | |
26 #include "parser.h" | |
27 #include "saveload.h" | |
28 | |
29 #ifdef TEXT_FILE_DEBUG | |
30 FILE * debugfile; | |
31 #endif | |
32 char debugbuffer[1024]; | |
33 | |
34 //extern HWND hWnd; | |
35 extern char new_name_buf[256]; | |
36 extern int buf_size; | |
37 | |
38 int lock_fail_counter; | |
39 int lock_counter; | |
40 | |
41 VIS_CRITICAL_SECTION(data_lock) | |
42 VIS_CRITICAL_SECTION(worker_queue_lock) | |
43 VIS_CRITICAL_SECTION(randlock) | |
44 VIS_Event(queue_add_event) | |
45 | |
46 int program_count=1; | |
47 VIS_CRITICAL_SECTION(program_count_lock) | |
48 | |
49 //#define ENABLE_PROFILING 1 | |
50 | |
51 #ifdef ENABLE_PROFILING | |
52 | |
53 __int64 vis_profile_start_times[NUM_PROFS]; | |
54 __int64 vis_profile_running_total[NUM_PROFS]; | |
55 int vis_profile_counts[NUM_PROFS]; | |
56 | |
57 __declspec(naked) | |
58 unsigned __int64 __cdecl rdtsc(void) | |
59 { | |
60 __asm | |
61 { | |
62 rdtsc | |
63 ret ; return value at EDX:EAX | |
64 } | |
65 } | |
66 | |
67 | |
68 #define PROF_INIT_CUSTOM 0 | |
69 #define PROF_WORKER_THREAD 1 | |
70 #define PROF_PROCESS_WORKER 2 | |
71 #define PROF_CLEANUP_CUSTOM 3 | |
72 #define PROF_SUB_CALLBACK 4 | |
73 #define PROF_CLEANUP_RELEASE_REFS 5 | |
74 #define PROF_CLEANUP_CHECK 6 | |
75 #define PROF_CLEANUP_FREELISTS 7 | |
76 #define PROF_PROCESS_OUTPUTS 8 | |
77 #define PROF_OPT_PREP_INPUT 9 | |
78 #define PROF_RUN_OPT 10 | |
79 #define PROF_ADDQUEUE 11 | |
80 #define PROF_ADDQUEUE_MALLOC 12 | |
81 #define PROF_OPT_LOOP 13 | |
82 #define PROF_EXECUTE_WORKER 14 | |
83 #define PROF_EXECUTE_OTHER 15 | |
84 #define PROF_PREP_MAGIC 16 | |
85 #define PROF_CONVERT_INPUTS 17 | |
86 #define PROF_EXECUTE_CUSTOM 18 | |
87 #define PROF_EXECUTE_BUILTIN 19 | |
88 #define PROF_EMPTYFUNC 20 | |
89 #define PROF_NOCODE 21 | |
90 #define PROF_LESSERWHOLE 22 | |
91 #define PROF_EQUALWHOLE 23 | |
92 #define PROF_PARTIAL_EXEC 24 | |
93 #define PROF_ADDWHOLE 25 | |
94 #define PROF_FULL_EXEC 26 | |
95 #define PROF_OPT_EXEC_USER 27 | |
96 #define PROF_OPT_EXEC_BUILT 28 | |
97 #define PROF_VIRTUAL_DECODE 27 | |
98 #define PROF_VIRTUAL_EXECUTE 28 | |
99 | |
100 | |
101 /*#define VIS_PROFILE_START(index) vis_profile_start_times[index] = rdtsc() | |
102 #define VIS_PROFILE_END(index) vis_profile_running_total[index] += (rdtsc()-vis_profile_start_times[index]); ++vis_profile_counts[index] | |
103 | |
104 #else | |
105 | |
106 #define VIS_PROFILE_START(index) | |
107 #define VIS_PROFILE_END(index)*/ | |
108 | |
109 #endif | |
110 | |
111 queue_entry * worker_queue; | |
112 queue_section first_section; | |
113 queue_section * current_section; | |
114 int queue_start; | |
115 int queue_len; | |
116 | |
117 BOOL execute_active=FALSE; | |
118 | |
119 char text_buf[256]; | |
120 int text_buf_size; | |
121 VIS_CRITICAL_SECTION(text_buf_lock) | |
122 | |
123 #ifdef WIN32 | |
124 WSADATA wsa_data; | |
125 #ifdef GUI_LIB | |
126 char errorbuffer[1024]; | |
127 #endif | |
128 #endif | |
129 | |
130 | |
131 worker_instance * main_instance; | |
132 | |
133 //company companylist[40]; | |
134 //int num_companies=0; | |
135 | |
136 datum * global_store_dict; | |
137 VIS_CRITICAL_SECTION(global_store_lock); | |
138 | |
139 | |
140 int empty_func(datum ** a, queue_entry * worker_entry) | |
141 { | |
142 return 0; | |
143 } | |
144 | |
145 worker_impl empty_test = empty_func; | |
146 /* | |
147 void set_in_child(worker_def * parent, int worker_num, BOOL * in_child, BOOL value, int exclude_worker) | |
148 { | |
149 int j,i = parent->workerlist[worker_num].wire_down_lookup; | |
150 if(exclude_worker >= 0 && exclude_worker == worker_num) | |
151 return; | |
152 in_child[worker_num] = value; | |
153 while(parent->wirelist[j=parent->workers_to_wires_down[i]].start_worker == worker_num && j >= 0) | |
154 set_in_child(parent, parent->wirelist[j].end_worker, in_child, value); | |
155 } | |
156 | |
157 void build_child_worker(worker_def * parent, int worker_num, int output_num) | |
158 { | |
159 int i,j, num_child_workers, num_child_wires, child_def; | |
160 BOOL * in_child = malloc(sizeof(BOOL)* parent->num_workers); | |
161 int * child_offsets = malloc(sizeof(int) * parent->num_workers); | |
162 for(i = 0; i < parent->num_workers; ++i) | |
163 { | |
164 in_child[i] = FALSE; | |
165 child_offsets[i] = -1; | |
166 } | |
167 i = parent->workerlist[worker_num].wire_down_lookup; | |
168 while(parent->wirelist[j=parent->workers_to_wires_down[i]].start_worker == worker_num && j >= 0) | |
169 { | |
170 if(parent->wirelist[j].output_num == output_num) | |
171 set_in_child(parent, parent->wirelist[j].end_worker, in_child, TRUE,-1); | |
172 } | |
173 i = parent->workerlist[worker_num].wire_down_lookup; | |
174 while(parent->wirelist[j=parent->workers_to_wires_down[i]].start_worker == worker_num && j >= 0) | |
175 { | |
176 if(parent->wirelist[j].output_num != output_num) | |
177 set_in_child(parent, parent->wirelist[j].end_worker, in_child, FALSE,-1); | |
178 } | |
179 for(i = 0; i < parent->num_workers; ++i) | |
180 { | |
181 if(i != worker_num && (parent->workerlist[i].type == 4 || (parent->workerlist[i].type == 2 && !in_child[i]))) | |
182 set_in_child(parent, i, in_child, FALSE); | |
183 } | |
184 for(i = 0; i < parent->num_workers; ++i) | |
185 { | |
186 if(in_child[i]) | |
187 child_offests[i] = num_child_workers++; | |
188 } | |
189 for(i = 0; i < parent->num_wires; ++i) | |
190 { | |
191 if(in_child[parent->wirelist[i].start_worker] || in_child[parent->wirelist[i].end_worker]) | |
192 ++num_child_wires; | |
193 } | |
194 child_def = num_defs++;//needs lock or atomic incrememnt | |
195 deflist[child_def].workerlist = malloc(sizeof(worker)*num_child_workers); | |
196 deflist[child_def].wirelist = malloc(sizeof(wire)*num_child_wires); | |
197 for(i = 0; i < parent->num_workers; ++i) | |
198 { | |
199 if(in_child[i]) | |
200 deflist[child_def].workerlist[child_offests[i]] = parent->workerlist[i]; | |
201 } | |
202 } */ | |
203 | |
204 #define MAX_TRACE_DEPTH 40 | |
205 | |
206 void print_stack_trace(worker_instance * stack_instance) | |
207 { | |
208 int i = 0; | |
209 ERRORPUTS("Stack trace:\n"); | |
210 while(stack_instance && i < MAX_TRACE_DEPTH) | |
211 { | |
212 ERRORPRINTF("%s\n", stack_instance->def->name); | |
213 stack_instance = stack_instance->caller_instance; | |
214 ++i; | |
215 } | |
216 if(stack_instance) | |
217 { | |
218 ERRORPUTS("Stack trace aborted after 40 entries\n"); | |
219 } | |
220 } | |
221 | |
222 void check_tail(worker_def * def) | |
223 { | |
224 custom_worker * worker = def->implement_func; | |
225 int i,j,k,endworker; | |
226 BOOL can_tail, outputs_handled[32]; | |
227 for(i = 0; i < worker->num_workers; ++i) | |
228 { | |
229 if(worker->workerlist[i].type == WORKER) | |
230 { | |
231 can_tail = TRUE; | |
232 for(j = 0; j < def->num_outputs; ++j) | |
233 outputs_handled[j] = FALSE; | |
234 j = worker->workerlist[i].wire_down_lookup; | |
235 while((k=worker->workers_to_wires_down[j]) >= 0 && worker->wirelist[k].start_worker == i) | |
236 { | |
237 endworker = worker->wirelist[k].end_worker; | |
238 if(worker->workerlist[endworker].type != OUTPUT || worker->workerlist[endworker].io_num != worker->wirelist[k].output_num) | |
239 { | |
240 can_tail = FALSE; | |
241 break; | |
242 } | |
243 else | |
244 outputs_handled[worker->wirelist[k].output_num] = TRUE; | |
245 ++j; | |
246 } | |
247 if(can_tail) | |
248 { | |
249 for(j = 0; j < def->num_outputs; ++j) | |
250 if(!outputs_handled[j]) | |
251 { | |
252 can_tail = FALSE; | |
253 break; | |
254 } | |
255 if(can_tail) | |
256 if(worker->workerlist[i].value_index == def) | |
257 worker->workerlist[i].type = TAIL_RECURSE; | |
258 else if(!def->num_stores) | |
259 worker->workerlist[i].type = TAIL_CALL; | |
260 } | |
261 } | |
262 } | |
263 } | |
264 | |
265 BOOL method_match(char * name, char * method_name) | |
266 { | |
267 int i = 0; | |
268 while(name[i] != '\0' && method_name[i] != '@' && method_name[i] != '\0') | |
269 { | |
270 if(name[i] != method_name[i]) | |
271 return FALSE; | |
272 ++i; | |
273 } | |
274 if(name[i] != '\0' || method_name[i] != '@') | |
275 return FALSE; | |
276 return TRUE; | |
277 } | |
278 | |
279 worker_def * find_method(int type, char * name, int num_inputs, program * prog) | |
280 { | |
281 int i; | |
282 worker_def * output = NULL; | |
283 company * companylist = prog->companylist; | |
284 VIS_EnterCriticalSection(companylist[type].lock); | |
285 for(i = 0; i < companylist[type].num_methods; ++i) | |
286 { | |
287 //DEBUGPRINTF( "Checking method %s(%d,%d)\n", companylist[type].methodlist[i]->name, companylist[type].methodlist[i]->num_inputs, companylist[type].methodlist[i]->num_outputs); | |
288 if(companylist[type].methodlist[i]->num_inputs == num_inputs && method_match(name, companylist[type].methodlist[i]->name)) | |
289 { | |
290 DEBUGPRINTF( "Found method: %s\n", companylist[type].methodlist[i]->name); | |
291 output = companylist[type].methodlist[i]; | |
292 break; | |
293 } | |
294 } | |
295 VIS_LeaveCriticalSection(companylist[type].lock); | |
296 return output; | |
297 } | |
298 | |
299 worker_def * find_method_noinputcheck(int type, char * name, program * prog) | |
300 { | |
301 int i; | |
302 worker_def * output = NULL; | |
303 company * companylist = prog->companylist; | |
304 VIS_EnterCriticalSection(companylist[type].lock); | |
305 for(i = 0; i < companylist[type].num_methods; ++i) | |
306 { | |
307 //DEBUGPRINTF( "Checking method %s(%d,%d)\n", companylist[type].methodlist[i]->name, companylist[type].methodlist[i]->num_inputs, companylist[type].methodlist[i]->num_outputs); | |
308 if(method_match(name, companylist[type].methodlist[i]->name)) | |
309 { | |
310 DEBUGPRINTF( "Found method: %s\n", companylist[type].methodlist[i]->name); | |
311 output = companylist[type].methodlist[i]; | |
312 break; | |
313 } | |
314 } | |
315 VIS_LeaveCriticalSection(companylist[type].lock); | |
316 return output; | |
317 } | |
318 | |
319 worker_def * find_converter_method(int totype, int fromtype, program * prog) | |
320 { | |
321 int i; | |
322 company * companylist = prog->companylist; | |
323 DEBUGPRINTF( "Finding converter from %s to %s\n", companylist[fromtype].name, companylist[totype].name); | |
324 //DEBUGPRINTF( "Num methods %d\n", companylist[totype].num_methods); | |
325 for(i = 0; i < companylist[totype].num_methods; ++i) | |
326 { | |
327 //DEBUGPRINTF("methodlist[i]: %X\n", companylist[totype].methodlist[i]); | |
328 DEBUGPRINTF( "Checking method %s\n", companylist[totype].methodlist[i]->name); | |
329 | |
330 if(companylist[totype].methodlist[i]->name[0] == '<' && method_match(companylist[fromtype].name, companylist[totype].methodlist[i]->name+1)) | |
331 { | |
332 DEBUGPRINTF( "Found Method %s\n", companylist[totype].methodlist[i]->name); | |
333 | |
334 return companylist[totype].methodlist[i]; | |
335 } | |
336 } | |
337 return NULL; | |
338 } | |
339 | |
340 worker_instance * init_custom_worker_type(int aworker, worker_instance * caller, worker_def * def, instance_callback callback, void * callback_data, datum ** params, int type) | |
341 { | |
342 int i, workerlist_size, j, add_index_count=0; | |
343 int add_index[32]; | |
344 datum * work_params[32]; | |
345 datum * temp_params[3]; | |
346 global_store * store; | |
347 worker_instance * instance; | |
348 BOOL release_params = TRUE; | |
349 def_make_lookup(def); | |
350 workerlist_size = sizeof(worker_instance_data)*(def->implement_func->num_workers); | |
351 //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)); | |
352 //DEBUGPRINTF("Before malloc(%d)\n",sizeof(worker_instance) + workerlist_size + sizeof(wire_instance_data)*(def->implement_func->num_wires)); | |
353 if(type == TAIL_RECURSE || type == TAIL_CALL) | |
354 { | |
355 VIS_EnterCriticalSection(caller->counter_lock); | |
356 if(caller->in_progress_count <= 1 && !caller->in_queue_count) | |
357 { | |
358 VIS_LeaveCriticalSection(caller->counter_lock); | |
359 instance = caller; | |
360 for(i = 0; i < instance->num_workers; ++i) | |
361 { | |
362 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) | |
363 release_ref(instance->workerlist[i].value); | |
364 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))) | |
365 { | |
366 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); | |
367 for(j = 0; j <= instance->def->implement_func->workerlist[i].num_inputs; ++j) | |
368 { | |
369 DEBUGPRINTF("Releasing param %d of worker %d\n", j, i); | |
370 release_ref(instance->workerlist[i].params[j]); | |
371 } | |
372 } | |
373 } | |
374 for(i = 0; i < def->num_inputs; ++i) | |
375 work_params[i] = params[i]; | |
376 params = work_params; | |
377 if(type == TAIL_RECURSE) | |
378 { | |
379 instance->in_progress_count = 0; | |
380 //TODO: adjust profile counter? | |
381 goto init_workerlist; | |
382 } | |
383 else | |
384 { | |
385 aworker = instance->worker_in_caller; | |
386 callback = instance->callback; | |
387 callback_data = instance->callback_data; | |
388 caller = instance->caller_instance; | |
389 VIS_DeleteCriticalSection(instance->counter_lock); | |
390 free(instance); | |
391 } | |
392 } | |
393 else | |
394 { | |
395 VIS_LeaveCriticalSection(caller->counter_lock); | |
396 } | |
397 } | |
398 | |
399 | |
400 instance = MALLOC(sizeof(worker_instance) + workerlist_size/* + sizeof(wire_instance_data)*(def->implement_func->num_wires) */,"instance"); | |
401 | |
402 //DEBUGPRINTF("malloc returned %X.\n", instance); | |
403 VIS_PROFILE_START(PROF_INIT_CUSTOM); | |
404 //DEBUGPRINTF("init_custom_worker, instance: %X\n", instance); | |
405 #ifdef USER_PROFILE | |
406 QueryPerformanceCounter(&(instance->start)); | |
407 #endif | |
408 instance->def = def; | |
409 instance->num_workers = def->implement_func->num_workers; | |
410 instance->workerlist = (worker_instance_data *)(((char *)instance) + sizeof(worker_instance));//malloc(sizeof(worker_instance_data)*(def->implement_func->num_workers)); | |
411 //DEBUGPRINTF("workerlist at %X\n", instance->workerlist); | |
412 | |
413 /*instance->num_wires = def->implement_func->num_wires; | |
414 instance->wirelist = (wire_instance_data *)(((char *)(instance->workerlist)) + workerlist_size);//malloc(sizeof(wire_instance_data)*(def->implement_func->num_wires)); | |
415 DEBUGPRINTF("wirelist at %X\n", instance->wirelist);*/ | |
416 | |
417 | |
418 instance->callback = callback; | |
419 instance->worker_in_caller = aworker; | |
420 instance->callback_data = callback_data; | |
421 instance->caller_instance = caller; | |
422 VIS_InitializeCriticalSection(instance->counter_lock); | |
423 instance->in_progress_count = 0; | |
424 instance->in_queue_count = 0; | |
425 | |
426 if(def->num_stores) | |
427 { | |
428 instance->trans = MALLOC(sizeof(transaction) + sizeof(global_store_use) *(def->num_stores - 1),"transaction"); | |
429 VIS_EnterCriticalSection(global_store_lock); | |
430 for(i = 0; i < def->num_stores; ++i) | |
431 { | |
432 temp_params[0] = add_ref(global_store_dict); | |
433 temp_params[1] = make_string(def->uses_stores[i], -1, def->program); | |
434 vis_dict_index(temp_params, NULL); | |
435 if(!temp_params[0]) | |
436 { | |
437 printf("Error: Global store %s is not initialized\n", def->uses_stores[i]); | |
438 DEBUGPRINTF("Error: Global store %s is not initialized\n", def->uses_stores[i]); | |
439 VIS_LeaveCriticalSection(global_store_lock); | |
440 return NULL; | |
441 } | |
442 instance->trans->stores[i].store = temp_params[0]->c.generic.data; | |
443 instance->trans->stores[i].instance_data = instance->trans->stores[i].begin_data = add_ref(instance->trans->stores[i].store->data); | |
444 VIS_InitializeCriticalSection(instance->trans->stores[i].lock); | |
445 //Is this really necessary? | |
446 release_ref(temp_params[0]); | |
447 } | |
448 VIS_LeaveCriticalSection(global_store_lock); | |
449 instance->trans->num_stores = def->num_stores; | |
450 if((def->transaction_flags & TRANSACTION_WRITE) && (def->transaction_flags & TRANSACTION_TYPE_MASK) == TRANSACTION_RETRY) | |
451 { | |
452 release_params = FALSE; | |
453 for(i = 0; i < def->num_inputs; ++i) | |
454 instance->trans->params[i] = params[i]; | |
455 } | |
456 } else { | |
457 instance->trans = NULL; | |
458 } | |
459 | |
460 | |
461 init_workerlist: | |
462 //DEBUGPUTS("init worker values\n"); | |
463 for(i = 0; i < instance->num_workers; ++i) | |
464 { | |
465 // DEBUGPRINTF("InitializeCriticalSection on workerlist[%d].worker_lock (%X)\n", i, &(instance->workerlist[i].worker_lock)); | |
466 VIS_InitializeCriticalSection(instance->workerlist[i].worker_lock); | |
467 //DEBUGPUTS("ready_count = 0\n"); | |
468 instance->workerlist[i].ready_count = 0; | |
469 if(def->implement_func->workerlist[i].type == INPUT && params) | |
470 instance->workerlist[i].value = add_ref(params[def->implement_func->workerlist[i].io_num]); | |
471 else //if(def->implement_func->workerlist[i].type != 2) | |
472 instance->workerlist[i].value = NULL; | |
473 //DEBUGPRINTF("instance->workerlist[%d].value = %X\n", i, instance->workerlist[i].value); | |
474 for(j = 0; j <= def->implement_func->workerlist[i].num_inputs; ++j) | |
475 instance->workerlist[i].params[j] = NULL; | |
476 //DEBUGPRINTF("num_inputs: %d, null_input: %d\n", def->implement_func->workerlist[i].num_inputs, def->implement_func->workerlist[i].null_input); | |
477 | |
478 //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 | |
479 //and only on custom workers that have more than 32 items that will be initially ready | |
480 if(!def->implement_func->workerlist[i].num_inputs && !def->implement_func->workerlist[i].null_input) | |
481 { | |
482 DEBUGPRINTF("adding worker %s(%d) to queue\n", def->implement_func->workerlist[i].name, i); | |
483 add_index[add_index_count++] = i; | |
484 if(add_index_count == 32) | |
485 { | |
486 add_multiple(add_index, add_index_count, instance); | |
487 add_index_count = 0; | |
488 } | |
489 //add_queue(i,instance); | |
490 } | |
491 } | |
492 | |
493 if(params) | |
494 { | |
495 if(release_params) | |
496 { | |
497 //DEBUGPUTS("release params\n"); | |
498 for(i = 0; i < def->num_inputs; ++i) | |
499 release_ref(params[i]); | |
500 } | |
501 } | |
502 if(add_index_count > 0) | |
503 add_multiple(add_index, add_index_count, instance); | |
504 VIS_PROFILE_END(PROF_INIT_CUSTOM); | |
505 | |
506 return instance; | |
507 } | |
508 | |
509 worker_instance * init_custom_worker(int aworker, worker_instance * caller, worker_def * def, instance_callback callback, void * callback_data, datum ** params) | |
510 { | |
511 return init_custom_worker_type(aworker, caller, def, callback, callback_data, params, WORKER); | |
512 } | |
513 | |
514 void cleanup_check(queue_entry aworker) | |
515 { | |
516 char msg[256]; | |
517 VIS_EnterCriticalSection(aworker.instance->counter_lock); | |
518 --(aworker.instance->in_progress_count); | |
519 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); | |
520 | |
521 if(aworker.instance->in_progress_count == 0 && aworker.instance->in_queue_count == 0) | |
522 { | |
523 VIS_LeaveCriticalSection(aworker.instance->counter_lock); | |
524 cleanup_custom_worker(aworker.instance, aworker.worker_num); | |
525 } | |
526 else | |
527 { | |
528 VIS_LeaveCriticalSection(aworker.instance->counter_lock); | |
529 } | |
530 } | |
531 | |
532 void cleanup_custom_worker(worker_instance * instance, int worker_num) | |
533 { | |
534 BOOL do_commit = TRUE; | |
535 int i,j; | |
536 queue_entry incaller; | |
537 global_store * store; | |
538 #ifdef USER_PROFILE | |
539 LARGE_INTEGER end; | |
540 LARGE_INTEGER duration; | |
541 #endif | |
542 if(instance->trans) | |
543 { | |
544 if(instance->def->transaction_flags & TRANSACTION_WRITE) | |
545 { | |
546 VIS_EnterCriticalSection(global_store_lock); | |
547 if((instance->def->transaction_flags & TRANSACTION_TYPE_MASK) != TRANSACTION_FORCE) | |
548 { | |
549 for(i = 0; i < instance->trans->num_stores; ++i) | |
550 { | |
551 if(instance->trans->stores[i].begin_data != instance->trans->stores[i].store->data) | |
552 { | |
553 do_commit = FALSE; | |
554 break; | |
555 } | |
556 } | |
557 } | |
558 if(do_commit) | |
559 { | |
560 for(i = 0; i < instance->trans->num_stores; ++i) | |
561 { | |
562 release_ref(instance->trans->stores[i].store->data); | |
563 instance->trans->stores[i].store->data = instance->trans->stores[i].instance_data; | |
564 } | |
565 } | |
566 VIS_LeaveCriticalSection(global_store_lock); | |
567 if(!do_commit)//retry transaction | |
568 { | |
569 for(i = 0; i < instance->trans->num_stores; ++i) | |
570 release_ref(instance->trans->stores[i].instance_data); | |
571 puts("retrying transaction"); | |
572 init_custom_worker(instance->worker_in_caller, instance->caller_instance, instance->def, instance->callback, instance->callback_data, instance->trans->params); | |
573 } | |
574 else if((instance->def->transaction_flags & TRANSACTION_TYPE_MASK) == TRANSACTION_RETRY) | |
575 for(i = 0; i < instance->def->num_inputs; ++i) | |
576 release_ref(instance->trans->params[i]); | |
577 } | |
578 else | |
579 { | |
580 for(i = 0; i < instance->trans->num_stores; ++i) | |
581 release_ref(instance->trans->stores[i].instance_data); | |
582 } | |
583 VIS_FREE(instance->trans, "transaction"); | |
584 } | |
585 VIS_PROFILE_START(PROF_CLEANUP_CUSTOM); | |
586 DEBUGPRINTF("Cleaning up custom worker: %s:%X\n", instance->def->name, instance); | |
587 | |
588 VIS_PROFILE_START(PROF_SUB_CALLBACK); | |
589 if(instance->callback && do_commit) | |
590 instance->callback(instance->caller_instance, instance->worker_in_caller, instance, instance->callback_data); | |
591 //DEBUGPUTS("About to release refs\n"); | |
592 VIS_PROFILE_END(PROF_SUB_CALLBACK); | |
593 VIS_PROFILE_START(PROF_CLEANUP_RELEASE_REFS); | |
594 /*for(i = 0; i < instance->def->implement_func->num_wires; ++i) | |
595 { | |
596 if(instance->wirelist[i].data) | |
597 { | |
598 DEBUGPRINTF("release_ref on wire %d\n", i); | |
599 | |
600 release_ref(instance->wirelist[i].data); | |
601 } | |
602 }*/ | |
603 for(i = 0; i < instance->num_workers; ++i) | |
604 { | |
605 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) | |
606 { | |
607 DEBUGPRINTF( "release_ref on worker %d in instance %X\n", i, instance); | |
608 release_ref(instance->workerlist[i].value); | |
609 } | |
610 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))) | |
611 { | |
612 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); | |
613 for(j = 0; j <= instance->def->implement_func->workerlist[i].num_inputs; ++j) | |
614 { | |
615 DEBUGPRINTF("Releasing param %d of worker %d\n", j, i); | |
616 release_ref(instance->workerlist[i].params[j]); | |
617 } | |
618 } | |
619 VIS_DeleteCriticalSection(instance->workerlist[i].worker_lock); | |
620 } | |
621 VIS_PROFILE_END(PROF_CLEANUP_RELEASE_REFS); | |
622 VIS_DeleteCriticalSection(instance->counter_lock); | |
623 //DEBUGPUTS("freeing lists\n"); | |
624 #ifdef USER_PROFILE | |
625 if(do_commit) | |
626 { | |
627 QueryPerformanceCounter(&end); | |
628 duration.QuadPart = end.QuadPart - instance->start.QuadPart; | |
629 VIS_EnterCriticalSection(instance->def->lock); | |
630 instance->def->total.QuadPart += duration.QuadPart; | |
631 ++instance->def->count; | |
632 if(duration.QuadPart > instance->def->worst.QuadPart) | |
633 instance->def->worst.QuadPart = duration.QuadPart; | |
634 VIS_LeaveCriticalSection(instance->def->lock); | |
635 } | |
636 #endif | |
637 /*VIS_PROFILE_START(PROF_CLEANUP_FREELISTS); | |
638 free(instance->workerlist); | |
639 free(instance->wirelist); | |
640 VIS_PROFILE_END(PROF_CLEANUP_FREELISTS);*/ | |
641 VIS_PROFILE_START(PROF_CLEANUP_CHECK); | |
642 if(instance->caller_instance && do_commit) | |
643 { | |
644 incaller.worker_num = instance->worker_in_caller; | |
645 incaller.instance = instance->caller_instance; | |
646 DEBUGPUTS("Calling cleanup_check on parent\n"); | |
647 cleanup_check(incaller); | |
648 } | |
649 if(do_commit && instance->callback == main_callback) | |
650 release_program_ref(instance->def->program); | |
651 VIS_PROFILE_END(PROF_CLEANUP_CHECK); | |
652 VIS_PROFILE_START(PROF_CLEANUP_FREELISTS); | |
653 VIS_FREE(instance, "worker instance"); | |
654 VIS_PROFILE_END(PROF_CLEANUP_FREELISTS); | |
655 VIS_PROFILE_END(PROF_CLEANUP_CUSTOM); | |
656 } | |
657 /* | |
658 void worker_complete(queue_entry aworker) | |
659 { | |
660 int i,j; | |
661 wire * wirelist; | |
662 int * workers_to_wires_down; | |
663 VIS_PROFILE_START(PROF_WORKER_COMPLETE); | |
664 DEBUGPUTS("worker_complete()\n"); | |
665 | |
666 | |
667 i = aworker.instance->def->implement_func->workerlist[aworker.worker_num].wire_down_lookup; | |
668 wirelist = aworker.instance->def->implement_func->wirelist; | |
669 workers_to_wires_down = aworker.instance->def->implement_func->workers_to_wires_down; | |
670 while(wirelist[j=workers_to_wires_down[i]].start_worker == aworker.worker_num && j >= 0) | |
671 { | |
672 if(aworker.instance->wirelist[j].data) | |
673 { | |
674 DEBUGPRINTF("end_worker: %d, wirelist[%d].data = %X\n", wirelist[j].end_worker, j, aworker.instance->wirelist[j].data); | |
675 add_if_ready(wirelist[j].end_worker, aworker.instance); | |
676 } | |
677 ++i; | |
678 } | |
679 DEBUGPUTS("worker_complete done\n"); | |
680 VIS_PROFILE_END(PROF_WORKER_COMPLETE); | |
681 }*/ | |
682 | |
683 void process_outputs(datum ** params, int aworker, worker_instance * instance) | |
684 { | |
685 BOOL flag=FALSE; | |
686 int i,j; | |
687 worker_def * def = instance->def; | |
688 //custom_worker *implement_func = def->implement_func; | |
689 wire * def_wires = def->implement_func->wirelist; | |
690 worker * def_workers = def->implement_func->workerlist; | |
691 VIS_PROFILE_START(PROF_PROCESS_OUTPUTS); | |
692 DEBUGPRINTF("Process outputs for worker %d in instance %X\n", aworker, instance); | |
693 DEBUGPRINTF("Num_inputs: %d, num_outputs: %d\n", def_workers[aworker].num_inputs, def_workers[aworker].num_outputs); | |
694 if(def_workers[aworker].num_outputs && instance->workerlist) | |
695 { | |
696 //DEBUGPRINTF("num_outputs: %d\n", def_workers[aworker].num_outputs); | |
697 i = def_workers[aworker].wire_down_lookup; | |
698 while((j=def->implement_func->workers_to_wires_down[i]) >= 0 && def_wires[j].start_worker == aworker) | |
699 { | |
700 //DEBUGPRINTF("Checking output: %d\n", def_wires[j].output_num); | |
701 DEBUGPRINTF("output[%d] = %X\n", def_wires[j].output_num, params[def_wires[j].output_num]); | |
702 DEBUGPRINTF("wire leads to worker %d, instance->workerlist: %X\n", def_wires[j].end_worker, instance->workerlist); | |
703 VIS_EnterCriticalSection(instance->workerlist[def_wires[j].end_worker].worker_lock); | |
704 if(params[def_wires[j].output_num] && !instance->workerlist[def_wires[j].end_worker].params[def_wires[j].input_num+1]) | |
705 { | |
706 //DEBUGPRINTF( "add_ref on output %d\n", def_wires[j].output_num); | |
707 instance->workerlist[def_wires[j].end_worker].params[def_wires[j].input_num+1]=add_ref(params[def_wires[j].output_num]); | |
708 //DEBUGPRINTF("Ready count was: %d, ", instance->workerlist[def_wires[j].end_worker].ready_count); | |
709 ++instance->workerlist[def_wires[j].end_worker].ready_count; | |
710 DEBUGPRINTF("Ready count is now: %d\n", instance->workerlist[def_wires[j].end_worker].ready_count); | |
711 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); | |
712 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))) | |
713 { | |
714 //DEBUGPUTS("flag = true\n"); | |
715 flag = TRUE; | |
716 instance->workerlist[def_wires[j].end_worker].ready_count=0; | |
717 } | |
718 } | |
719 VIS_LeaveCriticalSection(instance->workerlist[def_wires[j].end_worker].worker_lock); | |
720 if(flag) | |
721 { | |
722 DEBUGPUTS("add_queue\n"); | |
723 add_queue(def_wires[j].end_worker, instance); | |
724 //add_if_ready(def_wires[j].end_worker, instance); | |
725 flag = FALSE; | |
726 } | |
727 ++i; | |
728 } | |
729 //DEBUGPUTS("releasing refs\n"); | |
730 | |
731 for(i = 0; i < def_workers[aworker].num_outputs; ++i) | |
732 release_ref(params[i]); | |
733 } | |
734 VIS_PROFILE_END(PROF_PROCESS_OUTPUTS); | |
735 } | |
736 | |
737 void main_callback(worker_instance * junkinst, int junk, worker_instance * main_instance, void * data) | |
738 { | |
739 //MessageBox(NULL, "Main Callback", "Visuality Debug", MB_OK); | |
740 VIS_EnterCriticalSection(program_count_lock); | |
741 --program_count; | |
742 if(program_count <= 0) | |
743 { | |
744 execute_active = FALSE; | |
745 VIS_SetEvent(queue_add_event); | |
746 } | |
747 VIS_LeaveCriticalSection(program_count_lock); | |
748 if(data) | |
749 release_ref((datum *)data); | |
750 } | |
751 | |
752 void sub_callback(worker_instance * caller_instance, int caller_workernum, worker_instance * done_instance, void * data) | |
753 { | |
754 int i; | |
755 queue_entry incaller; | |
756 datum * params[32]; | |
757 worker_def * def = done_instance->def; | |
758 custom_worker * implement_func = def->implement_func; | |
759 | |
760 incaller.worker_num = caller_workernum; | |
761 incaller.instance = caller_instance; | |
762 for(i = 0; i < def->num_outputs; ++i) | |
763 params[i] = NULL; | |
764 for(i = 0; i < implement_func->num_workers; ++i) | |
765 { | |
766 if(implement_func->workerlist[i].type == 4) | |
767 { | |
768 if(!params[implement_func->workerlist[i].io_num]) | |
769 { | |
770 params[implement_func->workerlist[i].io_num] = done_instance->workerlist[i].value; | |
771 DEBUGPRINTF("Output[%d] = %X\n", implement_func->workerlist[i].io_num, done_instance->workerlist[i].value); | |
772 done_instance->workerlist[i].value = NULL; | |
773 } | |
774 } | |
775 } | |
776 process_outputs(params, caller_workernum, caller_instance); | |
777 //worker_complete(incaller); | |
778 } | |
779 | |
780 void pack_list_sub_callback(worker_instance * caller_instance, int caller_workernum, worker_instance * done_instance, void * data) | |
781 { | |
782 int i; | |
783 queue_entry incaller; | |
784 datum * params[32]; | |
785 datum * workparams[2]; | |
786 | |
787 incaller.worker_num = caller_workernum; | |
788 incaller.instance = caller_instance; | |
789 for(i = 0; i < done_instance->def->num_outputs; ++i) | |
790 params[i] = NULL; | |
791 for(i = 0; i < done_instance->def->implement_func->num_workers; ++i) | |
792 { | |
793 if(done_instance->def->implement_func->workerlist[i].type == 4) | |
794 { | |
795 if(!params[done_instance->def->implement_func->workerlist[i].io_num]) | |
796 { | |
797 params[done_instance->def->implement_func->workerlist[i].io_num] = done_instance->workerlist[i].value; | |
798 done_instance->workerlist[i].value = NULL; | |
799 } | |
800 } | |
801 } | |
802 workparams[0] = create_list(done_instance->def->program); | |
803 for(i = 0; i < done_instance->def->num_outputs; ++i) | |
804 { | |
805 workparams[1] = params[i]; | |
806 vis_list_append(workparams, NULL); | |
807 } | |
808 process_outputs(workparams, caller_workernum, caller_instance); | |
809 //worker_complete(incaller); | |
810 } | |
811 | |
812 void transaction_sub_callback(worker_instance * caller_instance, int caller_workernum, worker_instance * done_instance, void * data) | |
813 { | |
814 int i; | |
815 | |
816 pack_list_sub_callback(caller_instance, caller_workernum, done_instance, NULL); | |
817 } | |
818 | |
819 int global_argc; | |
820 char ** global_argv; | |
821 int spin_counter; | |
822 | |
823 void prep_program(program * prog) | |
824 { | |
825 defchunk * current; | |
826 int i,j; | |
827 make_lookup_arrays(prog); | |
828 current = prog->defs; | |
829 while(current) | |
830 { | |
831 for(i = 0; i < current->num_defs; ++i) | |
832 { | |
833 #ifdef USER_PROFILE | |
834 current->deflist[i].count = 0; | |
835 current->deflist[i].total.QuadPart = 0; | |
836 current->deflist[i].worst.QuadPart = 0; | |
837 VIS_InitializeCriticalSection(current->deflist[i].lock); | |
838 #endif // USER_PROFILE | |
839 //DEBUGPRINTF("Checking worker %s with type %X\n", current->deflist[i].name, current->deflist[i].type); | |
840 if(current->deflist[i].type & USER_FLAG && (current->deflist[i].type & TYPE_MASK) == WORKER_TYPE) | |
841 { | |
842 //DEBUGPRINTF("Checking for constants in worker %s\n", current->deflist[i].name); | |
843 for(j = 0; j < current->deflist[i].implement_func->num_workers; ++j) | |
844 if(current->deflist[i].implement_func->workerlist[j].type == CONSTANT) | |
845 { | |
846 //current->deflist[i].implement_func->workerlist[j].value_index = (int)(get_constant(current->deflist[i].implement_func->workerlist[j].name,-1, initial_prog)); | |
847 //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); | |
848 } | |
849 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) | |
850 { | |
851 current->deflist[i].implement_func->workerlist[j].num_inputs = ((worker_def *)current->deflist[i].implement_func->workerlist[j].value_index)->num_inputs; | |
852 current->deflist[i].implement_func->workerlist[j].num_outputs = ((worker_def *)current->deflist[i].implement_func->workerlist[j].value_index)->num_outputs; | |
853 } | |
854 else | |
855 current->deflist[i].implement_func->workerlist[j].value_index = 0; | |
856 //DEBUGPRINTF("optimize %d\n", i); | |
857 #ifdef ENABLE_OPT | |
858 optimize(current->deflist + i); | |
859 #endif | |
860 } | |
861 } | |
862 current = current->next; | |
863 } | |
864 } | |
865 | |
866 void interp_start(int num_threads, BOOL use_this_thread, int argc, char ** argv, program * initial_prog) | |
867 { | |
868 defchunk * current; | |
869 datum * params[2]; | |
870 int i, junk,create_threads,j; | |
871 #ifdef USER_PROFILE | |
872 LARGE_INTEGER frequency; | |
873 #endif | |
874 lock_fail_counter = 0; | |
875 lock_counter = 0; | |
876 spin_counter = 0; | |
877 | |
878 #ifdef WIN32 | |
879 //_CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_CHECK_CRT_DF | _CRTDBG_ALLOC_MEM_DF); | |
880 WSAStartup(MAKEWORD(1, 1), &wsa_data); | |
881 #endif | |
882 VIS_InitializeCriticalSection(randlock); | |
883 | |
884 DEBUGPUTS("interp_start\n"); | |
885 #ifdef ENABLE_PROFILING | |
886 for(i = 0; i < NUM_PROFS; ++i) | |
887 { | |
888 vis_profile_running_total[i] = 0; | |
889 vis_profile_counts[i] = 0; | |
890 } | |
891 VIS_PROFILE_START(PROF_EMPTYFUNC); | |
892 empty_test(NULL,NULL); | |
893 VIS_PROFILE_END(PROF_EMPTYFUNC); | |
894 VIS_PROFILE_START(PROF_NOCODE); | |
895 VIS_PROFILE_END(PROF_NOCODE); | |
896 #endif | |
897 global_argc = argc; | |
898 global_argv = argv; | |
899 init_sync_primitives(); | |
900 init_datum_storage(); | |
901 init_global_storage(initial_prog); | |
902 //init queue | |
903 current_section = &first_section; | |
904 DEBUGPRINTF("current_section = %X, ¤t_section = %X\n", current_section, ¤t_section); | |
905 worker_queue = current_section->entries; | |
906 current_section->last = NULL; | |
907 current_section->next = NULL; | |
908 queue_start = queue_len = 0; | |
909 // deflist[0].num_workers = num_workers; | |
910 // deflist[0].num_wires = num_wires; | |
911 prep_program(initial_prog); | |
912 //MessageBox(NULL, "Before fopen", "visdbg", MB_OK); | |
913 init_genrand(time(NULL)); | |
914 | |
915 execute_active = TRUE; | |
916 DEBUGPUTS("Before init_custom_worker on Main\n"); | |
917 params[0] = create_list(initial_prog); | |
918 for(i = 0; i < argc; ++i) | |
919 { | |
920 params[1] = make_string(argv[i], -1, initial_prog); | |
921 vis_list_append(params, NULL); | |
922 } | |
923 main_instance = init_custom_worker(-1, NULL, initial_prog->defs->deflist, main_callback, NULL, params); | |
924 | |
925 //num_datum = 0; | |
926 #if COMPILE_THREADS > 0 | |
927 create_threads = COMPILE_THREADS; | |
928 if(num_threads > 0) | |
929 create_threads = num_threads; | |
930 if(use_this_thread) | |
931 --create_threads; | |
932 | |
933 for(i = 0; i < create_threads; ++i) | |
934 { | |
935 #ifdef WIN32 | |
936 CreateThread(NULL, 0, worker_thread, NULL, 0, &junk); | |
937 #else | |
938 #ifdef SYLLABLE | |
939 resume_thread(spawn_thread("vis_worker", worker_thread, 1, 0, NULL)); | |
940 #else | |
941 pthread_t pid; | |
942 pthread_create(&pid, NULL, worker_thread, NULL); | |
943 #endif | |
944 #endif | |
945 } | |
946 if(use_this_thread) | |
947 worker_thread(NULL); | |
948 #else | |
949 worker_thread(NULL); | |
950 #endif | |
951 #ifdef ENABLE_PROFILING | |
952 for(i = 0; i < NUM_PROFS; ++i) | |
953 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])); | |
954 #endif | |
955 | |
956 #ifdef USER_PROFILE | |
957 printf("%-33s%12s%7s%15s%12s\n\n", "Worker", "Total", "Count", "Average", "Worst"); | |
958 current = initial_prog->defs; | |
959 while(current) | |
960 { | |
961 for(i = 0; i < current->num_defs; ++i) | |
962 { | |
963 if(current->deflist[i].count > 0) | |
964 { | |
965 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); | |
966 } | |
967 } | |
968 current = current->next; | |
969 } | |
970 QueryPerformanceFrequency(&frequency); | |
971 printf("%.0f ticks per second\n", (double)frequency.QuadPart); | |
972 #endif | |
973 interp_stop(); | |
974 } | |
975 | |
976 void interp_stop() | |
977 { | |
978 int i; | |
979 execute_active = FALSE; | |
980 close_sync_primitives(); | |
981 // Doesn't make sense in the context of multiple programs | |
982 // cleanup_custom_worker(main_instance); | |
983 #ifdef WIN32 | |
984 WSACleanup(); | |
985 #endif | |
986 #ifdef TEXT_FILE_DEBUG | |
987 fclose(debugfile); | |
988 #endif | |
989 } | |
990 | |
991 extern | |
992 void init_sync_primitives() | |
993 { | |
994 int i; | |
995 DEBUGPUTS("Initializing data_lock\n"); | |
996 VIS_InitializeCriticalSection(data_lock); | |
997 DEBUGPUTS("Initializing worker_queue_lock\n"); | |
998 VIS_InitializeCriticalSection(worker_queue_lock); | |
999 DEBUGPUTS("Initializing text_buf_lock\n"); | |
1000 VIS_InitializeCriticalSection(text_buf_lock); | |
13 | 1001 #ifdef GUI_LIB |
0 | 1002 #ifdef SYLLABLE |
1003 DEBUGPUTS("vis_window_init\n"); | |
1004 vis_window_init(); | |
1005 #endif | |
13 | 1006 #endif //GUI_LIB |
0 | 1007 VIS_CreateEvent(queue_add_event);//No security parameter, auto reset, starts signaled, no name |
1008 | |
1009 } | |
1010 | |
1011 void close_sync_primitives() | |
1012 { | |
1013 int i; | |
1014 VIS_DeleteCriticalSection(data_lock); | |
1015 VIS_DeleteCriticalSection(worker_queue_lock); | |
1016 VIS_DestroyEvent(queue_add_event); | |
1017 | |
1018 } | |
1019 | |
1020 void init_global_storage(program * prog) | |
1021 { | |
1022 VIS_InitializeCriticalSection(global_store_lock); | |
1023 global_store_dict = create_dict(prog); | |
1024 } | |
1025 | |
1026 void add_multiple(int * data, int num, worker_instance * instance) | |
1027 { | |
1028 int i, index; | |
1029 queue_section * temp; | |
1030 DEBUGPRINTF( "Adding %d workers\n", num); | |
1031 | |
1032 VIS_EnterCriticalSection(instance->counter_lock); | |
1033 instance->in_queue_count += num; | |
1034 VIS_LeaveCriticalSection(instance->counter_lock); | |
1035 VIS_EnterCriticalSection(worker_queue_lock); | |
1036 for(i = 0; i < num; ++i) | |
1037 { | |
1038 if(queue_len >= QUEUE_SIZE) | |
1039 { | |
1040 if(current_section->next) | |
1041 { | |
1042 //DEBUGPUTS("Moving to next queue_section\n"); | |
1043 current_section = current_section->next; | |
1044 } | |
1045 else | |
1046 { | |
1047 //DEBUGPUTS("Allocating new queue_section\n"); | |
1048 VIS_PROFILE_START(PROF_ADDQUEUE_MALLOC); | |
1049 temp = MALLOC(sizeof(queue_section),"queue section"); | |
1050 VIS_PROFILE_END(PROF_ADDQUEUE_MALLOC); | |
1051 temp->last = current_section; | |
1052 temp->next = NULL; | |
1053 current_section->next = temp; | |
1054 current_section = temp; | |
1055 } | |
1056 worker_queue = current_section->entries; | |
1057 queue_start = queue_len = 0; | |
1058 } | |
1059 if(queue_start+queue_len < QUEUE_SIZE) | |
1060 index = queue_start+queue_len; | |
1061 else | |
1062 index = queue_start+queue_len-QUEUE_SIZE; | |
1063 worker_queue[index].worker_num=data[i]; | |
1064 worker_queue[index].instance = instance; | |
1065 ++queue_len; | |
1066 } | |
1067 VIS_LeaveCriticalSection(worker_queue_lock); | |
1068 //DEBUGPUTS("SetEvent\n"); | |
1069 VIS_SetEvent(queue_add_event); | |
1070 } | |
1071 | |
1072 void requeue(int data, worker_instance * instance) | |
1073 { | |
1074 add_queue(data, instance); | |
1075 VIS_EnterCriticalSection(instance->counter_lock); | |
1076 --(instance->in_progress_count); | |
1077 VIS_LeaveCriticalSection(instance->counter_lock); | |
1078 } | |
1079 | |
1080 void add_queue(int data, worker_instance * instance) | |
1081 { | |
1082 int index; | |
1083 queue_section * temp; | |
1084 VIS_PROFILE_START(PROF_ADDQUEUE); | |
1085 VIS_EnterCriticalSection(instance->counter_lock); | |
1086 ++(instance->in_queue_count); | |
1087 VIS_LeaveCriticalSection(instance->counter_lock); | |
1088 VIS_EnterCriticalSection(worker_queue_lock); | |
1089 if(queue_len >= QUEUE_SIZE) | |
1090 { | |
1091 if(current_section->next) | |
1092 { | |
1093 //DEBUGPUTS("Moving to next queue_section\n"); | |
1094 current_section = current_section->next; | |
1095 } | |
1096 else | |
1097 { | |
1098 //DEBUGPUTS("Allocating new queue_section\n"); | |
1099 VIS_PROFILE_START(PROF_ADDQUEUE_MALLOC); | |
1100 temp = MALLOC(sizeof(queue_section),"queue section"); | |
1101 VIS_PROFILE_END(PROF_ADDQUEUE_MALLOC); | |
1102 temp->last = current_section; | |
1103 temp->next = NULL; | |
1104 current_section->next = temp; | |
1105 current_section = temp; | |
1106 } | |
1107 worker_queue = current_section->entries; | |
1108 queue_start = queue_len = 0; | |
1109 } | |
1110 else if(queue_len == 0) | |
1111 { | |
1112 VIS_SetEvent(queue_add_event); | |
1113 //DEBUGPUTS("SetEvent\n"); | |
1114 } | |
1115 | |
1116 if(queue_start+queue_len < QUEUE_SIZE) | |
1117 index = queue_start+queue_len; | |
1118 else | |
1119 index = queue_start+queue_len-QUEUE_SIZE; | |
1120 worker_queue[index].worker_num=data; | |
1121 worker_queue[index].instance = instance; | |
1122 ++queue_len; | |
1123 | |
1124 VIS_LeaveCriticalSection(worker_queue_lock); | |
1125 VIS_PROFILE_END(PROF_ADDQUEUE); | |
1126 } | |
1127 | |
1128 /** | |
1129 * Retrieves a ready worker from the queue | |
1130 */ | |
1131 queue_entry get_queue() | |
1132 { | |
1133 queue_entry data; | |
1134 queue_section * temp; | |
1135 //DEBUGPUTS("Begin get_queue()\n"); | |
1136 | |
1137 VIS_EnterCriticalSection(worker_queue_lock); | |
1138 while(!queue_len && execute_active) | |
1139 { | |
1140 //DEBUGPUTS("Queue empty, resetting event\n"); | |
1141 VIS_ResetEvent(queue_add_event); | |
1142 VIS_LeaveCriticalSection(worker_queue_lock); | |
1143 //DEBUGPUTS("Waiting for queue_add_event\n"); | |
1144 VIS_WaitEvent(queue_add_event); | |
1145 #ifdef NINTENDO_DS | |
1146 //TODO make the processor sleep while waiting for IRQs | |
1147 if(irq_queue_count > 0) | |
1148 run_queued_irqs(); | |
1149 #endif | |
1150 VIS_EnterCriticalSection(worker_queue_lock); | |
1151 } | |
1152 if(queue_len > 0) | |
1153 { | |
1154 data = worker_queue[queue_start]; | |
1155 //DEBUGPRINTF( "Next worker in queue: %d\n", data.worker_num); | |
1156 //DEBUGPRINTF("data.instance: %X, data.instance->workerlist: %X\n", data.instance, data.instance->workerlist); | |
1157 /*VIS_EnterCriticalSection(data.instance->workerlist[data.worker_num].worker_lock); | |
1158 DEBUGPUTS("Adjusting ready_count"); | |
1159 data.instance->workerlist[data.worker_num].ready_count=0; | |
1160 VIS_LeaveCriticalSection(data.instance->workerlist[data.worker_num].worker_lock);*/ | |
1161 ++queue_start; | |
1162 --queue_len; | |
1163 //DEBUGPUTS("Adjusted ready count.\n"); | |
1164 //DEBUGPRINTF("current_section: %X\n", current_section); | |
1165 if(queue_len == 0 && current_section->last) | |
1166 { | |
1167 if(current_section->next != NULL) | |
1168 { | |
1169 //DEBUGPUTS("Freeing current_section->next.\n"); | |
1170 VIS_FREE(current_section->next, "ready queue node"); | |
1171 current_section->next = NULL; | |
1172 } | |
1173 current_section = current_section->last; | |
1174 worker_queue = current_section->entries; | |
1175 queue_start = 0; | |
1176 queue_len = QUEUE_SIZE; | |
1177 } | |
1178 else if(queue_start == QUEUE_SIZE) | |
1179 queue_start = 0; | |
1180 } | |
1181 else | |
1182 { | |
1183 //DEBUGPUTS("Queue empty\n"); | |
1184 data.worker_num = -2; | |
1185 } | |
1186 VIS_LeaveCriticalSection(worker_queue_lock); | |
1187 //DEBUGPUTS("Left worker_queue_lock\n"); | |
1188 //MessageBox(NULL,"AfterLeave","visdbg",MB_OK); | |
1189 if(data.worker_num >= 0) | |
1190 { | |
1191 VIS_EnterCriticalSection(data.instance->counter_lock); | |
1192 //DEBUGPUTS("Adjusting in_queue/in_progress counts.\n"); | |
1193 --(data.instance->in_queue_count); | |
1194 ++(data.instance->in_progress_count); | |
1195 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); | |
1196 | |
1197 VIS_LeaveCriticalSection(data.instance->counter_lock); | |
1198 } | |
1199 //DEBUGPUTS("End get_queue()\n"); | |
1200 | |
1201 return data; | |
1202 } | |
1203 | |
1204 void def_make_lookup(worker_def * def) | |
1205 { | |
1206 int i, j, upoffset, offset; | |
1207 VIS_EnterCriticalSection(def->implement_func->lock); | |
1208 if(def->implement_func->dirty) | |
1209 { | |
1210 upoffset = offset = 0; | |
1211 for(i = 0; i < def->implement_func->num_workers; ++i) | |
1212 { | |
1213 def->implement_func->workerlist[i].wire_down_lookup=offset; | |
1214 def->implement_func->workerlist[i].wire_up_lookup=upoffset; | |
1215 for(j = 0; j < def->implement_func->num_wires; ++j) | |
1216 { | |
1217 if(def->implement_func->wirelist[j].start_worker == i) | |
1218 def->implement_func->workers_to_wires_down[offset++]=j; | |
1219 if(def->implement_func->wirelist[j].end_worker == i) | |
1220 def->implement_func->workers_to_wires_up[upoffset++]=j; | |
1221 } | |
1222 //Clear tail call info | |
1223 if(def->implement_func->workerlist[i].type == TAIL_CALL || def->implement_func->workerlist[i].type == TAIL_RECURSE) | |
1224 def->implement_func->workerlist[i].type = WORKER; | |
1225 } | |
1226 def->implement_func->workers_to_wires_down[offset]=-1; | |
1227 def->implement_func->workers_to_wires_up[upoffset]=-1; | |
1228 check_tail(def); | |
1229 def->implement_func->dirty = FALSE; | |
1230 } | |
1231 VIS_LeaveCriticalSection(def->implement_func->lock); | |
1232 } | |
1233 | |
1234 /** | |
1235 * Generates lookup array to ease navigation between workers | |
1236 */ | |
1237 void make_lookup_arrays(program * prog) | |
1238 { | |
1239 int i,j,k, offset, upoffset; | |
1240 worker_def * deflist; | |
1241 defchunk * current = prog->defs; | |
1242 while(current) | |
1243 { | |
1244 deflist = current->deflist; | |
1245 for(k = 0; k < current->num_defs; ++k) | |
1246 { | |
1247 if(deflist[k].type & USER_FLAG && (deflist[k].type & TYPE_MASK) == WORKER_TYPE) | |
1248 def_make_lookup(deflist + k); | |
1249 } | |
1250 current = current->next; | |
1251 } | |
1252 } | |
1253 extern char _end_bss[]; | |
1254 void initpredefworkers(program * prog) | |
1255 { | |
1256 int current_def = 1; | |
1257 int current_company = 0; | |
1258 int current_method; | |
1259 int comp_room; | |
1260 company * this_comp; | |
1261 worker_def * aworker; | |
1262 create_company(prog, "Any Type", 0, 0, FALSE); | |
1263 create_company(prog, "Yes No", 0, 0, FALSE); | |
1264 | |
1265 aworker = create_worker(prog, "Print", 1, 1, WORKER_TYPE); | |
1266 aworker->implement_func = (custom_worker *)vis_print; | |
1267 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1268 | |
1269 aworker = create_worker(prog, "Random", 0, 1, WORKER_TYPE); | |
1270 aworker->implement_func = (custom_worker *)vis_random; | |
1271 | |
1272 aworker = create_worker(prog, "Build", 1, 1, WORKER_TYPE); | |
1273 aworker->implement_func = (custom_worker *)vis_build; | |
1274 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1275 | |
1276 aworker = create_worker(prog, "End", 1, 0, WORKER_TYPE); | |
1277 aworker->implement_func = (custom_worker *)vis_end; | |
1278 aworker->input_types[0] = ANY_TYPE; | |
1279 | |
1280 create_worker(prog, "Append", 2, 1, MAGIC_TYPE); | |
1281 create_worker(prog, "+", 2, 1, MAGIC_TYPE); | |
1282 create_worker(prog, "-", 2, 1, MAGIC_TYPE); | |
1283 create_worker(prog, "*", 2, 1, MAGIC_TYPE); | |
1284 create_worker(prog, "/", 2, 1, MAGIC_TYPE); | |
1285 create_worker(prog, ">", 2, 1, MAGIC_TYPE); | |
1286 create_worker(prog, "<", 2, 1, MAGIC_TYPE); | |
1287 create_worker(prog, "=", 2, 1, MAGIC_TYPE); | |
1288 | |
1289 aworker = create_worker(prog, "Get Input", 0, 1, WORKER_TYPE); | |
1290 aworker->implement_func = (custom_worker *)vis_getinput; | |
1291 | |
1292 aworker = create_worker(prog, "If",1, 2, WORKER_TYPE); | |
1293 aworker->implement_func=(custom_worker *)vis_if; | |
1294 aworker->input_types[0] = BUILTIN_TYPE_YESNO; | |
1295 | |
1296 aworker = create_worker(prog, "Type Of",1, 1, WORKER_TYPE); | |
1297 aworker->implement_func=(custom_worker *)vis_type_of; | |
1298 aworker->input_types[0] = ANY_TYPE; | |
1299 | |
1300 aworker = create_worker(prog, "Init Store",1, 0, WORKER_TYPE); | |
1301 aworker->implement_func=(custom_worker *)init_global_store; | |
1302 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1303 | |
1304 aworker = create_worker(prog, "Wait Forever", 0, 0, WORKER_TYPE); | |
1305 aworker->implement_func=(custom_worker *)vis_wait_forever; | |
1306 | |
1307 #ifdef NINTENDO_DS | |
1308 aworker = create_worker(prog, "Register Handler", 2, 1, WORKER_TYPE); | |
1309 aworker->implement_func = (custom_worker *)vis_register_handler; | |
1310 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1311 aworker->input_types[1] = BUILTIN_TYPE_WORKER; | |
1312 | |
1313 aworker = create_worker(prog, "Clear Handler", 1, 1, WORKER_TYPE); | |
1314 aworker->implement_func = (custom_worker *)vis_clear_handler; | |
1315 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1316 | |
1317 aworker = create_worker(prog, "Held Keys", 0, 1, WORKER_TYPE); | |
1318 aworker->implement_func = (custom_worker *)vis_held_keys; | |
1319 | |
1320 aworker = create_worker(prog, "Touch Position", 0, 2, WORKER_TYPE); | |
1321 aworker->implement_func = (custom_worker *)vis_touch_position; | |
1322 #endif | |
1323 | |
1324 current_method = 0; | |
1325 //strcpy(companylist[current_company].name, "String"); | |
1326 #ifdef SEGA | |
1327 this_comp = create_company(prog, "String", 6, 0, FALSE); | |
1328 #else | |
1329 this_comp = create_company(prog, "String", 7, 0, FALSE); | |
1330 #endif | |
1331 aworker = create_worker(prog, "<Whole Number@String",1, 1, WORKER_TYPE); | |
1332 aworker->implement_func=(custom_worker *)vis_inttostring; | |
1333 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1334 //add_method(this_comp, aworker); | |
1335 | |
1336 #ifndef SEGA | |
1337 | |
1338 aworker = create_worker(prog, "<Real Number@String",1, 1, WORKER_TYPE); | |
1339 aworker->implement_func=(custom_worker *)vis_realtostring; | |
1340 aworker->input_types[0] = BUILTIN_TYPE_REAL; | |
1341 //add_method(this_comp, aworker); | |
1342 #endif | |
1343 | |
1344 aworker = create_worker(prog, "=@String",2, 1, WORKER_TYPE); | |
1345 aworker->implement_func=(custom_worker *)vis_stringequal; | |
1346 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1347 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1348 //add_method(this_comp, aworker); | |
1349 | |
1350 aworker = create_worker(prog, "<Yes No@String",1, 1, WORKER_TYPE); | |
1351 aworker->implement_func=(custom_worker *)vis_yesnotostring; | |
1352 aworker->input_types[0] = BUILTIN_TYPE_YESNO; | |
1353 //add_method(this_comp, aworker); | |
1354 | |
1355 aworker = create_worker(prog, ">@String",2, 1, WORKER_TYPE); | |
1356 aworker->implement_func=(custom_worker *)vis_greaterstring; | |
1357 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1358 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1359 //add_method(this_comp, aworker); | |
1360 | |
1361 aworker = create_worker(prog, "<@String",2, 1, WORKER_TYPE); | |
1362 aworker->implement_func=(custom_worker *)vis_lesserstring; | |
1363 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1364 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1365 //add_method(this_comp, aworker); | |
1366 | |
1367 aworker = create_worker(prog, "Append@String",2, 1, WORKER_TYPE); | |
1368 aworker->implement_func=(custom_worker *)vis_append; | |
1369 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1370 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1371 //add_method(this_comp, aworker); | |
1372 | |
1373 aworker = create_worker(prog, "Split@String",2, 1, WORKER_TYPE); | |
1374 aworker->implement_func=(custom_worker *)vis_string_split; | |
1375 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1376 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1377 | |
1378 aworker = create_worker(prog, "Get Raw@String",2, 2, WORKER_TYPE); | |
1379 aworker->implement_func=(custom_worker *)vis_string_get_raw; | |
1380 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1381 aworker->input_types[1] = ANY_TYPE; | |
1382 | |
1383 aworker = create_worker(prog, "Put Raw@String",2, 1, WORKER_TYPE); | |
1384 aworker->implement_func=(custom_worker *)vis_string_put_raw; | |
1385 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1386 aworker->input_types[1] = ANY_TYPE; | |
1387 | |
1388 aworker = create_worker(prog, "Slice@String",2, 2, WORKER_TYPE); | |
1389 aworker->implement_func=(custom_worker *)vis_string_slice; | |
1390 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1391 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1392 | |
1393 aworker = create_worker(prog, "Reverse@String",1, 1, WORKER_TYPE); | |
1394 aworker->implement_func=(custom_worker *)vis_string_reverse; | |
1395 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1396 | |
1397 aworker = create_worker(prog, "Length@String",1, 1, WORKER_TYPE); | |
1398 aworker->implement_func=(custom_worker *)vis_string_length; | |
1399 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1400 | |
1401 aworker = create_worker(prog, "Put Byte@String",2, 1, WORKER_TYPE); | |
1402 aworker->implement_func=(custom_worker *)vis_string_put_byte; | |
1403 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1404 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1405 | |
1406 aworker = create_worker(prog, "Get DString@String",2, 4, WORKER_TYPE); | |
1407 aworker->implement_func=(custom_worker *)vis_string_get_dstring; | |
1408 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1409 aworker->input_types[1] = ANY_TYPE; | |
1410 | |
1411 current_method = 0; | |
1412 this_comp = create_company(prog, "Whole Number", 6, 0, FALSE); | |
1413 aworker = create_worker(prog, "<String@Whole Number",1, 1, WORKER_TYPE); | |
1414 aworker->implement_func=(custom_worker *)vis_stringtoint; | |
1415 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1416 | |
1417 aworker = create_worker(prog, "From Hex@Whole Number",1, 1, WORKER_TYPE); | |
1418 aworker->implement_func=(custom_worker *)vis_whole_fromhex; | |
1419 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1420 //add_method(this_comp, aworker); | |
1421 | |
1422 aworker = create_worker(prog, "=@Whole Number",2, 1, WORKER_TYPE); | |
1423 aworker->implement_func=(custom_worker *)vis_wholeequal; | |
1424 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1425 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1426 //add_method(this_comp, aworker); | |
1427 | |
1428 aworker = create_worker(prog, ">@Whole Number",2, 1, WORKER_TYPE); | |
1429 aworker->implement_func=(custom_worker *)vis_greaterint; | |
1430 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1431 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1432 //add_method(this_comp, aworker); | |
1433 | |
1434 aworker = create_worker(prog, "<@Whole Number",2, 1, WORKER_TYPE); | |
1435 aworker->implement_func=(custom_worker *)vis_lesserint; | |
1436 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1437 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1438 | |
1439 //add_method(this_comp, aworker); | |
1440 | |
1441 aworker = create_worker(prog, "+@Whole Number", 2, 1, WORKER_TYPE); | |
1442 aworker->implement_func=(custom_worker *)vis_whole_add; | |
1443 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1444 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1445 | |
1446 //add_method(this_comp, aworker); | |
1447 | |
1448 aworker = create_worker(prog, "-@Whole Number", 2, 1, WORKER_TYPE); | |
1449 aworker->implement_func=(custom_worker *)vis_whole_subtract; | |
1450 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1451 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1452 | |
1453 aworker = create_worker(prog, "*@Whole Number", 2, 1, WORKER_TYPE); | |
1454 aworker->implement_func=(custom_worker *)vis_whole_mult; | |
1455 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1456 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1457 | |
1458 //add_method(this_comp, aworker); | |
1459 | |
1460 aworker = create_worker(prog, "/@Whole Number", 2, 1, WORKER_TYPE); | |
1461 aworker->implement_func=(custom_worker *)vis_whole_div; | |
1462 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1463 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1464 | |
1465 aworker = create_worker(prog, "&@Whole Number", 2, 1, WORKER_TYPE); | |
1466 aworker->implement_func=(custom_worker *)vis_whole_and; | |
1467 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1468 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1469 | |
1470 aworker = create_worker(prog, "|@Whole Number", 2, 1, WORKER_TYPE); | |
1471 aworker->implement_func=(custom_worker *)vis_whole_or; | |
1472 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1473 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1474 | |
1475 aworker = create_worker(prog, "LShift@Whole Number", 2, 1, WORKER_TYPE); | |
1476 aworker->implement_func=(custom_worker *)vis_whole_lsh; | |
1477 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1478 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1479 | |
1480 aworker = create_worker(prog, "RShift@Whole Number", 2, 1, WORKER_TYPE); | |
1481 aworker->implement_func=(custom_worker *)vis_whole_rsh; | |
1482 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1483 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1484 | |
1485 //add_method(this_comp, aworker); | |
1486 | |
1487 current_method = 0; | |
1488 this_comp = create_company(prog, "Real Number", 6, 0, FALSE);//<string, =, >, <, +, - | |
1489 aworker = create_worker(prog, "<String@Real Number", 1, 1, WORKER_TYPE); | |
1490 aworker->implement_func=(custom_worker *)vis_stringtoreal; | |
1491 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1492 //add_method(this_comp, aworker); | |
1493 | |
1494 aworker = create_worker(prog, "=@Real Number", 2, 1, WORKER_TYPE); | |
1495 aworker->implement_func=(custom_worker *)vis_realequal; | |
1496 aworker->input_types[0] = BUILTIN_TYPE_REAL; | |
1497 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1498 | |
1499 //add_method(this_comp, aworker); | |
1500 | |
1501 aworker = create_worker(prog, ">@Real Number", 2, 1, WORKER_TYPE); | |
1502 aworker->implement_func=(custom_worker *)vis_greaterreal; | |
1503 aworker->input_types[0] = BUILTIN_TYPE_REAL; | |
1504 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1505 | |
1506 //add_method(this_comp, aworker); | |
1507 | |
1508 aworker = create_worker(prog, "<@Real Number", 2, 1, WORKER_TYPE); | |
1509 aworker->implement_func=(custom_worker *)vis_lesserreal; | |
1510 aworker->input_types[0] = BUILTIN_TYPE_REAL; | |
1511 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1512 | |
1513 //add_method(this_comp, aworker); | |
1514 | |
1515 aworker = create_worker(prog, "+@Real Number", 2, 1, WORKER_TYPE); | |
1516 aworker->implement_func=(custom_worker *)vis_real_add; | |
1517 aworker->input_types[0] = BUILTIN_TYPE_REAL; | |
1518 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1519 | |
1520 //add_method(this_comp, aworker); | |
1521 | |
1522 aworker = create_worker(prog, "-@Real Number", 2, 1, WORKER_TYPE); | |
1523 aworker->implement_func=(custom_worker *)vis_real_subtract; | |
1524 aworker->input_types[0] = BUILTIN_TYPE_REAL; | |
1525 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1526 | |
1527 aworker = create_worker(prog, "/@Real Number", 2, 1, WORKER_TYPE); | |
1528 aworker->implement_func=(custom_worker *)vis_real_div; | |
1529 aworker->input_types[0] = BUILTIN_TYPE_REAL; | |
1530 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
28
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1531 |
29
3cc5e4a42344
Missed registration for *@Real Number in previous commit
Mike Pavone <pavone@retrodev.com>
parents:
28
diff
changeset
|
1532 aworker = create_worker(prog, "*@Real Number", 2, 1, WORKER_TYPE); |
3cc5e4a42344
Missed registration for *@Real Number in previous commit
Mike Pavone <pavone@retrodev.com>
parents:
28
diff
changeset
|
1533 aworker->implement_func=(custom_worker *)vis_real_mult; |
3cc5e4a42344
Missed registration for *@Real Number in previous commit
Mike Pavone <pavone@retrodev.com>
parents:
28
diff
changeset
|
1534 aworker->input_types[0] = BUILTIN_TYPE_REAL; |
3cc5e4a42344
Missed registration for *@Real Number in previous commit
Mike Pavone <pavone@retrodev.com>
parents:
28
diff
changeset
|
1535 aworker->input_types[1] = BUILTIN_TYPE_REAL; |
3cc5e4a42344
Missed registration for *@Real Number in previous commit
Mike Pavone <pavone@retrodev.com>
parents:
28
diff
changeset
|
1536 |
28
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1537 aworker = create_worker(prog, "Cosine@Real Number", 1, 1, WORKER_TYPE); |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1538 aworker->implement_func=(custom_worker *)vis_real_cos; |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1539 aworker->input_types[0] = BUILTIN_TYPE_REAL; |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1540 |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1541 aworker = create_worker(prog, "Sine@Real Number", 1, 1, WORKER_TYPE); |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1542 aworker->implement_func=(custom_worker *)vis_real_sin; |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1543 aworker->input_types[0] = BUILTIN_TYPE_REAL; |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1544 |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1545 aworker = create_worker(prog, "Tangent@Real Number", 1, 1, WORKER_TYPE); |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1546 aworker->implement_func=(custom_worker *)vis_real_tan; |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1547 aworker->input_types[0] = BUILTIN_TYPE_REAL; |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1548 |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1549 aworker = create_worker(prog, "Arc Cosine@Real Number", 1, 1, WORKER_TYPE); |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1550 aworker->implement_func=(custom_worker *)vis_real_arccos; |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1551 aworker->input_types[0] = BUILTIN_TYPE_REAL; |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1552 |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1553 aworker = create_worker(prog, "Arc Sine@Real Number", 1, 1, WORKER_TYPE); |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1554 aworker->implement_func=(custom_worker *)vis_real_arcsin; |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1555 aworker->input_types[0] = BUILTIN_TYPE_REAL; |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1556 |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1557 aworker = create_worker(prog, "Arc Tangent@Real Number", 1, 1, WORKER_TYPE); |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1558 aworker->implement_func=(custom_worker *)vis_real_arctan; |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1559 aworker->input_types[0] = BUILTIN_TYPE_REAL; |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1560 |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1561 aworker = create_worker(prog, "^@Real Number", 2, 1, WORKER_TYPE); |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1562 aworker->implement_func=(custom_worker *)vis_real_exp; |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1563 aworker->input_types[0] = BUILTIN_TYPE_REAL; |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1564 aworker->input_types[1] = BUILTIN_TYPE_REAL; |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1565 |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1566 aworker = create_worker(prog, "Square Root@Real Number", 1, 1, WORKER_TYPE); |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1567 aworker->implement_func=(custom_worker *)vis_real_sqrt; |
d8b4d38fceb6
Merged in the worker registration code for the math functions added for ICFP 08
Mike Pavone <pavone@retrodev.com>
parents:
26
diff
changeset
|
1568 aworker->input_types[0] = BUILTIN_TYPE_REAL; |
0 | 1569 |
1570 //add_method(this_comp, aworker); | |
1571 | |
1572 current_method = 0; | |
1573 this_comp = create_company(prog, "List", 7, 1, FALSE);//Index, Append, Swap, Insert, Remove, Set, Length, New | |
1574 comp_room = add_comp_room(this_comp, "Length", 0, 0, ROOM_NO_ACCESS, ROOM_LONG); | |
1575 | |
1576 aworker = create_worker(prog, "Index@List", 2, 2, WORKER_TYPE); | |
1577 aworker->implement_func=(custom_worker *)vis_list_index; | |
1578 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1579 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1580 | |
1581 //add_method(this_comp, aworker); | |
1582 | |
1583 aworker = create_worker(prog, "Append@List", 2, 1, WORKER_TYPE); | |
1584 aworker->implement_func=(custom_worker *)vis_list_append; | |
1585 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1586 aworker->input_types[1] = ANY_TYPE; | |
1587 | |
1588 //add_method(this_comp, aworker); | |
1589 | |
1590 aworker = create_worker(prog, "Swap@List",3, 1, WORKER_TYPE); | |
1591 aworker->implement_func=(custom_worker *)vis_list_swap; | |
1592 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1593 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1594 aworker->input_types[2] = BUILTIN_TYPE_WHOLE; | |
1595 | |
1596 //add_method(this_comp, aworker); | |
1597 | |
1598 aworker = create_worker(prog, "Insert@List",3, 1, WORKER_TYPE); | |
1599 aworker->implement_func=(custom_worker *)vis_list_insert; | |
1600 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1601 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1602 aworker->input_types[2] = ANY_TYPE; | |
1603 | |
1604 //add_method(this_comp, aworker); | |
1605 | |
1606 aworker = create_worker(prog, "Remove@List", 2, 1, WORKER_TYPE); | |
1607 aworker->implement_func=(custom_worker *)vis_list_remove; | |
1608 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1609 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1610 | |
1611 //add_method(this_comp, aworker); | |
1612 | |
1613 aworker = create_worker(prog, "Set@List",3, 1, WORKER_TYPE); | |
1614 aworker->implement_func=(custom_worker *)vis_list_set; | |
1615 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1616 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1617 aworker->input_types[2] = ANY_TYPE; | |
1618 | |
1619 //add_method(this_comp, aworker); | |
1620 | |
1621 aworker = create_worker(prog, "Length@List", 1, 1, WORKER_TYPE); | |
1622 aworker->implement_func = (custom_worker *)vis_list_length; | |
1623 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1624 //add_method(this_comp, aworker); | |
1625 | |
1626 aworker = create_worker(prog, "New@List",0, 1, WORKER_TYPE); | |
1627 aworker->implement_func=(custom_worker *)vis_list_new; | |
1628 //add_method(this_comp, aworker); | |
1629 | |
1630 aworker = create_worker(prog, "First@List", 1, 2, WORKER_TYPE); | |
1631 aworker->implement_func=(custom_worker *)vis_list_first; | |
1632 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1633 | |
1634 aworker = create_worker(prog, "Next@List", 2, 2, WORKER_TYPE); | |
1635 aworker->implement_func=(custom_worker *)vis_list_next; | |
1636 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1637 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1638 | |
1639 current_method = 0; | |
1640 this_comp = create_company(prog, "Dictionary", 5, 0, FALSE);//Index, Swap, Remove, Set, Length, New | |
1641 aworker = create_worker(prog, "Index@Dictionary", 2, 2, WORKER_TYPE); | |
1642 aworker->implement_func=(custom_worker *)vis_dict_index; | |
1643 aworker->input_types[0] = BUILTIN_TYPE_DICT; | |
1644 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1645 | |
1646 //add_method(this_comp, aworker); | |
1647 | |
1648 aworker = create_worker(prog, "Swap@Dictionary",3, 1, WORKER_TYPE); | |
1649 aworker->implement_func=(custom_worker *)vis_dict_swap; | |
1650 aworker->input_types[0] = BUILTIN_TYPE_DICT; | |
1651 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1652 aworker->input_types[2] = BUILTIN_TYPE_STRING; | |
1653 | |
1654 //add_method(this_comp, aworker); | |
1655 | |
1656 aworker = create_worker(prog, "Remove@Dictionary", 2, 1, WORKER_TYPE); | |
1657 aworker->implement_func=(custom_worker *)vis_dict_remove; | |
1658 aworker->input_types[0] = BUILTIN_TYPE_DICT; | |
1659 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1660 | |
1661 //add_method(this_comp, aworker); | |
1662 | |
1663 aworker = create_worker(prog, "Set@Dictionary",3, 1, WORKER_TYPE); | |
1664 aworker->implement_func=(custom_worker *)vis_dict_set; | |
1665 aworker->input_types[0] = BUILTIN_TYPE_DICT; | |
1666 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1667 aworker->input_types[2] = ANY_TYPE; | |
1668 | |
1669 aworker = create_worker(prog, "Length@Dictionary", 1, 1, WORKER_TYPE); | |
1670 aworker->implement_func=(custom_worker *)vis_dict_length; | |
1671 aworker->input_types[0] = BUILTIN_TYPE_DICT; | |
1672 | |
1673 //add_method(this_comp, aworker); | |
1674 | |
1675 aworker = create_worker(prog, "New@Dictionary",0, 1, WORKER_TYPE); | |
1676 aworker->implement_func=(custom_worker *)vis_dict_new; | |
1677 //add_method(this_comp, aworker); | |
1678 | |
1679 aworker = create_worker(prog, "First@Dictionary", 1, 2, WORKER_TYPE); | |
1680 aworker->implement_func=(custom_worker *)vis_dict_first; | |
1681 aworker->input_types[0] = BUILTIN_TYPE_DICT; | |
1682 | |
1683 aworker = create_worker(prog, "Next@Dictionary", 2, 2, WORKER_TYPE); | |
1684 aworker->implement_func=(custom_worker *)vis_dict_next; | |
1685 aworker->input_types[0] = BUILTIN_TYPE_DICT; | |
1686 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1687 | |
1688 current_method = 0; | |
1689 #ifdef SEGA | |
1690 this_comp = create_company(prog, "File", 0, 0, FALSE); | |
1691 #else | |
1692 | |
1693 this_comp = create_company(prog, "File", 7, 0, FALSE);//<String, Get FString, Get DString, Get Byte, Get Word, Get Long, Put String | |
1694 aworker = create_worker(prog, "<String@File", 1, 1, WORKER_TYPE); | |
1695 aworker->implement_func=(custom_worker *)vis_file_from_string; | |
1696 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1697 //add_method(this_comp, aworker); | |
1698 | |
1699 aworker = create_worker(prog, "Get FString@File", 2, 2, WORKER_TYPE); | |
1700 aworker->implement_func=(custom_worker *)vis_file_get_fstring; | |
1701 aworker->input_types[0] = BUILTIN_TYPE_FILE; | |
1702 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1703 | |
1704 //add_method(this_comp, aworker); | |
1705 | |
1706 aworker = create_worker(prog, "Get DString@File", 2, 4, WORKER_TYPE); | |
1707 aworker->implement_func=(custom_worker *)vis_file_get_dstring; | |
1708 aworker->input_types[0] = BUILTIN_TYPE_FILE; | |
1709 aworker->input_types[1] = ANY_TYPE; | |
1710 | |
1711 //add_method(this_comp, aworker); | |
1712 | |
1713 aworker = create_worker(prog, "Get Byte@File", 1, 3, WORKER_TYPE); | |
1714 aworker->implement_func=(custom_worker *)vis_file_get_byte; | |
1715 aworker->input_types[0] = BUILTIN_TYPE_FILE; | |
1716 //add_method(this_comp, aworker); | |
1717 | |
1718 aworker = create_worker(prog, "Get Word@File", 1, 3, WORKER_TYPE); | |
1719 aworker->implement_func=(custom_worker *)vis_file_get_word; | |
1720 aworker->input_types[0] = BUILTIN_TYPE_FILE; | |
1721 //add_method(this_comp, aworker); | |
1722 | |
1723 aworker = create_worker(prog, "Get Long@File", 1, 3, WORKER_TYPE); | |
1724 aworker->implement_func=(custom_worker *)vis_file_get_long; | |
1725 aworker->input_types[0] = BUILTIN_TYPE_FILE; | |
1726 //add_method(this_comp, aworker); | |
1727 | |
26 | 1728 aworker = create_worker(prog, "Get Double@File", 1, 3, WORKER_TYPE); |
1729 aworker->implement_func=(custom_worker *)vis_file_get_double; | |
1730 aworker->input_types[0] = BUILTIN_TYPE_FILE; | |
1731 | |
0 | 1732 aworker = create_worker(prog, "Put String@File", 2, 1, WORKER_TYPE); |
1733 aworker->implement_func=(custom_worker *)vis_file_put_string; | |
1734 aworker->input_types[0] = BUILTIN_TYPE_FILE; | |
1735 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1736 | |
1737 aworker = create_worker(prog, "Length@File", 1, 1, WORKER_TYPE); | |
1738 aworker->implement_func=(custom_worker *)vis_file_length; | |
1739 aworker->input_types[0] = BUILTIN_TYPE_FILE; | |
1740 | |
1741 //add_method(this_comp, aworker); | |
1742 #endif | |
1743 | |
1744 current_method = 0; | |
1745 | |
1746 this_comp = create_company(prog, "Worker", 3, 0, FALSE);//<String, Do, Later: methods for manipulating | |
1747 | |
1748 aworker = create_worker(prog, "<String@Worker", 1, 1, WORKER_TYPE); | |
1749 aworker->implement_func=(custom_worker *)vis_worker_from_string; | |
1750 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1751 //add_method(this_comp, aworker); | |
1752 | |
1753 aworker = create_worker(prog, "Do@Worker", 2, 1, WORKER_TYPE); | |
1754 aworker->implement_func=(custom_worker *)vis_worker_do; | |
1755 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1756 aworker->input_types[1] = BUILTIN_TYPE_LIST; | |
1757 | |
1758 aworker = create_worker(prog, "Set Input@Worker", 3, 1, WORKER_TYPE); | |
1759 aworker->implement_func=(custom_worker *)vis_worker_setinput; | |
1760 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1761 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1762 aworker->input_types[2] = ANY_TYPE; | |
1763 //add_method(this_comp, aworker); | |
1764 | |
1765 aworker = create_worker(prog, "Add Worker Call@Worker", 2, 2, WORKER_TYPE); | |
1766 aworker->implement_func=(custom_worker *)vis_worker_add_worker_call; | |
1767 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1768 aworker->input_types[1] = BUILTIN_TYPE_WORKER; | |
1769 | |
1770 aworker = create_worker(prog, "Add Wire@Worker", 5, 1, WORKER_TYPE); | |
1771 aworker->implement_func=(custom_worker *)vis_worker_add_wire; | |
1772 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1773 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1774 aworker->input_types[2] = BUILTIN_TYPE_WHOLE; | |
1775 aworker->input_types[3] = BUILTIN_TYPE_WHOLE; | |
1776 aworker->input_types[4] = BUILTIN_TYPE_WHOLE; | |
1777 | |
1778 aworker = create_worker(prog, "Add Constant@Worker", 2, 2, WORKER_TYPE); | |
1779 aworker->implement_func=(custom_worker *)vis_worker_add_constant; | |
1780 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1781 aworker->input_types[1] = ANY_TYPE; | |
1782 | |
1783 aworker = create_worker(prog, "Add Input@Worker", 3, 2, WORKER_TYPE); | |
1784 aworker->implement_func=(custom_worker *)vis_worker_add_input; | |
1785 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1786 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1787 aworker->input_types[2] = BUILTIN_TYPE_WHOLE; | |
1788 | |
1789 aworker = create_worker(prog, "Add Output@Worker", 3, 2, WORKER_TYPE); | |
1790 aworker->implement_func=(custom_worker *)vis_worker_add_output; | |
1791 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1792 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1793 aworker->input_types[2] = BUILTIN_TYPE_WHOLE; | |
1794 | |
1795 aworker = create_worker(prog, "Add Object Get@Worker", 2, 2, WORKER_TYPE); | |
1796 aworker->implement_func=(custom_worker *)vis_worker_add_objectget; | |
1797 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1798 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1799 | |
1800 aworker = create_worker(prog, "Add Object Set@Worker", 2, 2, WORKER_TYPE); | |
1801 aworker->implement_func=(custom_worker *)vis_worker_add_objectset; | |
1802 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1803 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1804 | |
1805 aworker = create_worker(prog, "Add Global Get@Worker", 3, 2, WORKER_TYPE); | |
1806 aworker->implement_func=(custom_worker *)vis_worker_add_globalget; | |
1807 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1808 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1809 aworker->input_types[2] = BUILTIN_TYPE_STRING; | |
1810 | |
1811 aworker = create_worker(prog, "Add Global Set@Worker", 3, 2, WORKER_TYPE); | |
1812 aworker->implement_func=(custom_worker *)vis_worker_add_globalset; | |
1813 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1814 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1815 aworker->input_types[2] = BUILTIN_TYPE_STRING; | |
1816 | |
1817 aworker = create_worker(prog, "Clear@Worker", 1, 1, WORKER_TYPE); | |
1818 aworker->implement_func=(custom_worker *)vis_worker_clear; | |
1819 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1820 | |
1821 aworker = create_worker(prog, "Uses@Worker", 2, 1, WORKER_TYPE); | |
1822 aworker->implement_func=(custom_worker *)vis_worker_uses; | |
1823 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1824 aworker->input_types[1] = BUILTIN_TYPE_LIST; | |
1825 | |
1826 aworker = create_worker(prog, "Set IO Counts@Worker", 3, 1, WORKER_TYPE); | |
1827 aworker->implement_func=(custom_worker *)vis_worker_setio_counts; | |
1828 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1829 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1830 aworker->input_types[2] = BUILTIN_TYPE_WHOLE; | |
1831 | |
1832 aworker = create_worker(prog, "New@Worker", 1, 1, WORKER_TYPE); | |
1833 aworker->implement_func=(custom_worker *)vis_worker_new; | |
1834 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1835 | |
1836 #ifdef GUI_LIB | |
1837 current_method = 0; | |
1838 | |
1839 this_comp = create_company(prog, "Window", 3, 0, FALSE); | |
1840 | |
1841 aworker = create_worker(prog, "New@Window", 3, 1, WORKER_TYPE); | |
1842 aworker->implement_func=(custom_worker *)vis_window_new; | |
1843 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1844 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1845 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
1846 //add_method(this_comp, aworker); | |
1847 | |
1848 aworker = create_worker(prog, "Add Widget@Window", 5, 1, WORKER_TYPE); | |
1849 aworker->implement_func=(custom_worker *)vis_window_add_widget; | |
1850 aworker->input_types[0] = BUILTIN_TYPE_WINDOW; | |
1851 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1852 aworker->input_types[2] = ANY_TYPE; | |
1853 aworker->input_types[3] = BUILTIN_TYPE_REAL; | |
1854 aworker->input_types[4] = BUILTIN_TYPE_REAL; | |
1855 //add_method(this_comp, aworker); | |
1856 | |
1857 aworker = create_worker(prog, "Show@Window", 3, 1, WORKER_TYPE); | |
1858 aworker->implement_func=(custom_worker *)vis_window_show; | |
1859 aworker->input_types[0] = BUILTIN_TYPE_WINDOW; | |
1860 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1861 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
1862 //add_method(this_comp, aworker); | |
1863 | |
1864 current_method = 0; | |
1865 this_comp = create_company(prog, "Screen Window", 3, 0, FALSE); | |
1866 | |
1867 aworker = create_worker(prog, "Get Value@Screen Window", 2, 1, WORKER_TYPE); | |
1868 aworker->implement_func=(custom_worker *)vis_window_get_value; | |
1869 aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN; | |
1870 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1871 //add_method(this_comp, aworker); | |
1872 | |
1873 aworker = create_worker(prog, "Set Value@Screen Window", 3, 0, WORKER_TYPE); | |
1874 aworker->implement_func=(custom_worker *)vis_window_set_value; | |
1875 aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN; | |
1876 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1877 #ifdef SYLLABLE | |
1878 aworker->input_types[2] = ANY_TYPE; | |
1879 #else | |
1880 aworker->input_types[2] = BUILTIN_TYPE_STRING; | |
1881 #endif | |
1882 //add_method(this_comp, aworker); | |
1883 | |
1884 aworker = create_worker(prog, "Wait Close@Screen Window", 1, 1, WORKER_TYPE); | |
1885 aworker->implement_func=(custom_worker *)vis_window_wait_close; | |
1886 aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN; | |
1887 //add_method(this_comp, aworker); | |
1888 | |
1889 #ifdef SYLLABLE | |
1890 aworker = create_worker(prog, "Add Widget@Screen Window", 5, 1, WORKER_TYPE); | |
1891 aworker->implement_func=(custom_worker *)vis_window_shown_addwidget; | |
1892 aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN; | |
1893 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1894 aworker->input_types[2] = ANY_TYPE; | |
1895 aworker->input_types[3] = BUILTIN_TYPE_REAL; | |
1896 aworker->input_types[4] = BUILTIN_TYPE_REAL; | |
1897 #endif | |
1898 | |
1899 current_method = 0; | |
1900 create_company(prog, "Button", 2, 0, FALSE); | |
1901 | |
1902 aworker = create_worker(prog, "New@Button", 3, 1, WORKER_TYPE); | |
1903 aworker->implement_func=(custom_worker *)vis_button_new; | |
1904 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1905 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1906 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
1907 //add_method(this_comp, aworker); | |
1908 | |
1909 aworker = create_worker(prog, "Set Handler@Button", 3, 1, WORKER_TYPE); | |
1910 aworker->implement_func=(custom_worker *)vis_button_set_handler; | |
1911 aworker->input_types[0] = BUILTIN_TYPE_BUTTON; | |
1912 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1913 aworker->input_types[2] = BUILTIN_TYPE_WORKER; | |
1914 //add_method(this_comp, aworker); | |
1915 | |
1916 current_method = 0; | |
1917 create_company(prog, "Input Box", 2, 0, FALSE); | |
1918 | |
1919 aworker = create_worker(prog, "New@Input Box", 3, 1, WORKER_TYPE); | |
1920 aworker->implement_func=(custom_worker *)vis_inputbox_new; | |
1921 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1922 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1923 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
1924 //add_method(this_comp, aworker); | |
1925 | |
1926 aworker = create_worker(prog, "Set Type@Input Box", 2, 1, WORKER_TYPE); | |
1927 aworker->implement_func=(custom_worker *)vis_inputbox_settype; | |
1928 aworker->input_types[0] = BUILTIN_TYPE_INPUTBOX; | |
1929 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1930 //add_method(this_comp, aworker); | |
1931 | |
1932 #endif | |
1933 #ifndef NO_NET | |
1934 this_comp = create_company(prog, "Net Client", 3, 0, FALSE); | |
1935 aworker = create_worker(prog, "New@Net Client", 2, 1, WORKER_TYPE); | |
1936 aworker->implement_func =(custom_worker *)net_client_new; | |
1937 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1938 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1939 | |
1940 aworker = create_worker(prog, "Put String@Net Client", 2, 2, WORKER_TYPE); | |
1941 aworker->implement_func = (custom_worker *)net_client_put_string; | |
1942 aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; | |
1943 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1944 | |
1945 aworker = create_worker(prog, "Get FString@Net Client", 2, 3, WORKER_TYPE); | |
1946 aworker->implement_func = (custom_worker *)net_client_get_fstring; | |
1947 aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; | |
1948 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1949 | |
1950 aworker = create_worker(prog, "Get DString@Net Client", 2, 4, WORKER_TYPE); | |
1951 aworker->implement_func = (custom_worker *)net_client_get_dstring; | |
1952 aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; | |
1953 aworker->input_types[1] = ANY_TYPE; | |
1954 | |
1955 aworker = create_worker(prog, "Put Raw@Net Client", 2, 2, WORKER_TYPE); | |
1956 aworker->implement_func = (custom_worker *)net_client_put_raw; | |
1957 aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; | |
1958 aworker->input_types[1] = ANY_TYPE; | |
1959 | |
1960 aworker = create_worker(prog, "Get Raw@Net Client", 2, 3, WORKER_TYPE); | |
1961 aworker->implement_func = (custom_worker *)net_client_get_raw; | |
1962 aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; | |
1963 aworker->input_types[1] = ANY_TYPE; | |
1964 | |
1965 aworker = create_worker(prog, "Listen on Port", 2, 0, WORKER_TYPE); | |
1966 aworker->implement_func = (custom_worker *)vis_net_listenport; | |
1967 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1968 aworker->input_types[1] = BUILTIN_TYPE_WORKER; | |
1969 #endif | |
1970 | |
1971 create_company(prog, "Global Store", 0, 0, FALSE); | |
1972 | |
1973 create_company(prog, "Program", 5, 0, FALSE); | |
1974 | |
1975 aworker = create_worker(prog, "New@Program", 0, 1, WORKER_TYPE); | |
1976 aworker->implement_func = (custom_worker *)vis_program_new; | |
1977 | |
1978 aworker = create_worker(prog, "New Worker@Program", 2, 2, WORKER_TYPE); | |
1979 aworker->implement_func = (custom_worker *)vis_program_new_worker; | |
1980 aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; | |
1981 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1982 | |
1983 aworker = create_worker(prog, "Add Worker@Program", 2, 2, WORKER_TYPE); | |
1984 aworker->implement_func = (custom_worker *)vis_program_add_worker; | |
1985 aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; | |
1986 aworker->input_types[1] = BUILTIN_TYPE_WORKER; | |
1987 | |
1988 aworker = create_worker(prog, "Add Builtins@Program", 1, 1, WORKER_TYPE); | |
1989 aworker->implement_func = (custom_worker *)vis_program_add_builtins; | |
1990 aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; | |
1991 | |
1992 aworker = create_worker(prog, "Run@Program", 2, 1, WORKER_TYPE); | |
1993 aworker->implement_func = (custom_worker *)vis_program_run; | |
1994 aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; | |
1995 aworker->input_types[1] = ANY_TYPE; | |
1996 | |
1997 aworker = create_worker(prog, "Find Worker@Program", 2, 2, WORKER_TYPE); | |
1998 aworker->implement_func = (custom_worker *)vis_program_find_worker; | |
1999 aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; | |
2000 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2001 | |
2002 #ifdef GUI_LIB | |
2003 #ifdef SYLLABLE | |
2004 create_company(prog, "Custom Widget", 2, 0, FALSE); | |
2005 | |
2006 aworker = create_worker(prog, "New@Custom Widget", 3, 1, WORKER_TYPE); | |
2007 aworker->implement_func=(custom_worker *)vis_customwidget_new; | |
2008 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
2009 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
2010 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
2011 //add_method(this_comp, aworker); | |
2012 | |
2013 aworker = create_worker(prog, "Set Handler@Custom Widget", 3, 1, WORKER_TYPE); | |
2014 aworker->implement_func=(custom_worker *)vis_button_set_handler; | |
2015 aworker->input_types[0] = BUILTIN_TYPE_CUSTOM_WIDGET; | |
2016 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2017 aworker->input_types[2] = BUILTIN_TYPE_WORKER; | |
2018 //add_method(this_comp, aworker); | |
2019 | |
2020 create_company(prog, "Screen Custom Widget", 3, 0, FALSE); | |
2021 | |
2022 aworker = create_worker(prog, "Default Draw@Screen Custom Widget", 1, 1, WORKER_TYPE); | |
2023 aworker->implement_func=(custom_worker *)vis_screen_custom_defaultpaint; | |
2024 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
2025 //add_method(this_comp, aworker); | |
2026 | |
2027 aworker = create_worker(prog, "Draw Line@Screen Custom Widget", 5, 1, WORKER_TYPE); | |
2028 aworker->implement_func=(custom_worker *)vis_screen_custom_drawline; | |
2029 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
2030 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
2031 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
2032 aworker->input_types[3] = BUILTIN_TYPE_REAL; | |
2033 aworker->input_types[4] = BUILTIN_TYPE_REAL; | |
2034 //add_method(this_comp, aworker); | |
2035 | |
2036 aworker = create_worker(prog, "Draw String@Screen Custom Widget", 4, 1, WORKER_TYPE); | |
2037 aworker->implement_func=(custom_worker *)vis_screen_custom_drawstring; | |
2038 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
2039 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2040 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
2041 aworker->input_types[3] = BUILTIN_TYPE_REAL; | |
2042 | |
2043 aworker = create_worker(prog, "Set Draw Color@Screen Custom Widget", 5, 1, WORKER_TYPE); | |
2044 aworker->implement_func=(custom_worker *)vis_screen_custom_setdrawcolor; | |
2045 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
2046 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2047 aworker->input_types[2] = BUILTIN_TYPE_WHOLE; | |
2048 aworker->input_types[3] = BUILTIN_TYPE_WHOLE; | |
2049 aworker->input_types[4] = BUILTIN_TYPE_WHOLE; | |
2050 | |
2051 aworker = create_worker(prog, "Move By@Screen Custom Widget", 3, 1, WORKER_TYPE); | |
2052 aworker->implement_func=(custom_worker *)vis_screen_custom_moveby; | |
2053 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
2054 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
2055 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
2056 | |
2057 aworker = create_worker(prog, "Set Handler@Screen Custom Widget", 3, 1, WORKER_TYPE); | |
2058 aworker->implement_func=(custom_worker *)vis_screen_custom_sethandler; | |
2059 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
2060 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2061 aworker->input_types[2] = BUILTIN_TYPE_WORKER; | |
2062 | |
2063 aworker = create_worker(prog, "Remove Handler@Screen Custom Widget", 2, 1, WORKER_TYPE); | |
2064 aworker->implement_func=(custom_worker *)vis_screen_custom_removehandler; | |
2065 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
2066 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2067 | |
2068 aworker = create_worker(prog, "Give Focus@Screen Custom Widget", 2, 1, WORKER_TYPE); | |
2069 aworker->implement_func=(custom_worker *)vis_screen_custom_givefocus; | |
2070 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
2071 aworker->input_types[1] = BUILTIN_TYPE_YESNO; | |
2072 | |
2073 aworker = create_worker(prog, "Add Widget@Screen Custom Widget", 5, 1, WORKER_TYPE); | |
2074 aworker->implement_func=(custom_worker *)vis_screen_custom_addwidget; | |
2075 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
2076 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2077 aworker->input_types[2] = ANY_TYPE; | |
2078 aworker->input_types[3] = BUILTIN_TYPE_REAL; | |
2079 aworker->input_types[4] = BUILTIN_TYPE_REAL; | |
2080 | |
2081 #endif | |
2082 #endif | |
2083 create_company(prog, "Buffer", 7, 0, FALSE); | |
2084 | |
2085 aworker = create_worker(prog, "New@Buffer", 1, 1, WORKER_TYPE); | |
2086 aworker->implement_func=(custom_worker *)vis_buffer_new; | |
2087 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
2088 | |
2089 aworker = create_worker(prog, "Lock@Buffer", 1, 1, WORKER_TYPE); | |
2090 aworker->implement_func=(custom_worker *)vis_buffer_lock; | |
2091 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2092 | |
2093 aworker = create_worker(prog, "Unlock@Buffer", 1, 1, WORKER_TYPE); | |
2094 aworker->implement_func=(custom_worker *)vis_buffer_unlock; | |
2095 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2096 | |
2097 aworker = create_worker(prog, "Put Byte@Buffer", 2, 1, WORKER_TYPE); | |
2098 aworker->implement_func=(custom_worker *)vis_buffer_putbyte; | |
2099 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2100 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2101 | |
2102 aworker = create_worker(prog, "Write Byte@Buffer", 2, 1, WORKER_TYPE); | |
2103 aworker->implement_func=(custom_worker *)vis_buffer_writebyte; | |
2104 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2105 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2106 | |
2107 aworker = create_worker(prog, "Put Word@Buffer", 2, 1, WORKER_TYPE); | |
2108 aworker->implement_func=(custom_worker *)vis_buffer_putshort; | |
2109 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2110 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2111 | |
2112 aworker = create_worker(prog, "Write Word@Buffer", 2, 1, WORKER_TYPE); | |
2113 aworker->implement_func=(custom_worker *)vis_buffer_writeshort; | |
2114 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2115 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2116 | |
2117 aworker = create_worker(prog, "Put Long@Buffer", 2, 1, WORKER_TYPE); | |
2118 aworker->implement_func=(custom_worker *)vis_buffer_putlong; | |
2119 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2120 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2121 | |
2122 aworker = create_worker(prog, "Write Long@Buffer", 2, 1, WORKER_TYPE); | |
2123 aworker->implement_func=(custom_worker *)vis_buffer_writelong; | |
2124 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2125 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2126 | |
2127 aworker = create_worker(prog, "Reset@Buffer", 1, 1, WORKER_TYPE); | |
2128 aworker->implement_func=(custom_worker *)vis_buffer_reset; | |
2129 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2130 | |
2131 #if defined(SEGA) || defined(NINTENDO_DS) | |
2132 | |
2133 aworker = create_worker(prog, "From Address@Buffer", 2, 1, WORKER_TYPE); | |
2134 aworker->implement_func=(custom_worker *)vis_buffer_fromaddress; | |
2135 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
2136 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2137 #endif //SEGA | |
2138 | |
2139 create_company(prog, "Blueprint", 4, 0, FALSE); | |
2140 | |
2141 aworker = create_worker(prog, "New@Blueprint", 1, 1, WORKER_TYPE); | |
2142 aworker->implement_func=(custom_worker *)vis_blueprint_new; | |
2143 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
2144 | |
2145 aworker = create_worker(prog, "Add Field@Blueprint", 3, 1, WORKER_TYPE); | |
2146 aworker->implement_func=(custom_worker *)vis_blueprint_addfield; | |
2147 aworker->input_types[0] = BUILTIN_TYPE_BLUEPRINT; | |
2148 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2149 aworker->input_types[2] = BUILTIN_TYPE_STRING; | |
2150 | |
2151 aworker = create_worker(prog, "Name@Blueprint", 1, 1, WORKER_TYPE); | |
2152 aworker->implement_func=(custom_worker *)vis_blueprint_name; | |
2153 aworker->input_types[0] = BUILTIN_TYPE_BLUEPRINT; | |
2154 | |
2155 aworker = create_worker(prog, "Get Fields@Blueprint", 1, 1, WORKER_TYPE); | |
2156 aworker->implement_func=(custom_worker *)vis_blueprint_getfields; | |
2157 aworker->input_types[0] = BUILTIN_TYPE_BLUEPRINT; | |
2158 | |
2159 aworker = create_worker(prog, "Blueprint Of", 1, 1, WORKER_TYPE); | |
2160 aworker->implement_func=(custom_worker *)vis_get_blueprint; | |
2161 aworker->input_types[0] = ANY_TYPE; | |
2162 | |
2163 aworker = create_worker(prog, "Get Field", 2, 2, WORKER_TYPE); | |
2164 aworker->implement_func=(custom_worker *)vis_get_field; | |
2165 aworker->input_types[0] = ANY_TYPE; | |
2166 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2167 | |
2168 aworker = create_worker(prog, "Set Field", 3, 1, WORKER_TYPE); | |
2169 aworker->implement_func=(custom_worker *)vis_set_field; | |
2170 aworker->input_types[0] = ANY_TYPE; | |
2171 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2172 aworker->input_types[2] = ANY_TYPE; | |
2173 | |
2174 aworker = create_worker(prog, "New Blueprint@Program", 2, 2, WORKER_TYPE); | |
2175 aworker->implement_func=(custom_worker *)vis_program_newblueprint; | |
2176 aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; | |
2177 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2178 | |
13 | 2179 #ifdef GUI_LIB |
0 | 2180 #ifdef SYLLABLE |
2181 create_company(prog, "Checkbox", 2, 0, FALSE); | |
2182 | |
2183 aworker = create_worker(prog, "New@Checkbox", 4, 1, WORKER_TYPE); | |
2184 aworker->implement_func=(custom_worker *)vis_checkbox_new; | |
2185 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
2186 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
2187 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
2188 aworker->input_types[3] = BUILTIN_TYPE_YESNO; | |
2189 | |
2190 aworker = create_worker(prog, "Set Handler@Checkbox", 3, 1, WORKER_TYPE); | |
2191 aworker->implement_func=(custom_worker *)vis_button_set_handler; | |
2192 aworker->input_types[0] = BUILTIN_TYPE_CHECKBOX; | |
2193 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2194 aworker->input_types[2] = BUILTIN_TYPE_WORKER; | |
2195 | |
2196 create_company(prog, "Dropdown", 4, 0, FALSE); | |
2197 | |
2198 aworker = create_worker(prog, "New@Dropdown", 3, 1, WORKER_TYPE); | |
2199 aworker->implement_func=(custom_worker *)vis_dropdown_new; | |
2200 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
2201 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
2202 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
2203 | |
2204 aworker = create_worker(prog, "Set Handler@Dropdown", 3, 1, WORKER_TYPE); | |
2205 aworker->implement_func=(custom_worker *)vis_button_set_handler; | |
2206 aworker->input_types[0] = BUILTIN_TYPE_DROPDOWN; | |
2207 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2208 aworker->input_types[2] = BUILTIN_TYPE_WORKER; | |
2209 | |
2210 aworker = create_worker(prog, "Set Text@Dropdown", 2, 1, WORKER_TYPE); | |
2211 aworker->implement_func=(custom_worker *)vis_dropdown_settext; | |
2212 aworker->input_types[0] = BUILTIN_TYPE_DROPDOWN; | |
2213 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2214 | |
2215 aworker = create_worker(prog, "Select@Dropdown", 2, 1, WORKER_TYPE); | |
2216 aworker->implement_func=(custom_worker *)vis_dropdown_select; | |
2217 aworker->input_types[0] = BUILTIN_TYPE_DROPDOWN; | |
2218 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2219 #endif | |
13 | 2220 #endif |
31
fab5bb137cf9
Added Unix Time worker to interpreter
Mike Pavone <pavone@retrodev.com>
parents:
29
diff
changeset
|
2221 aworker = create_worker(prog, "Unix Time", 0, 1, WORKER_TYPE); |
fab5bb137cf9
Added Unix Time worker to interpreter
Mike Pavone <pavone@retrodev.com>
parents:
29
diff
changeset
|
2222 aworker->implement_func=(custom_worker *)unix_time; |
0 | 2223 /*if(current_def > num_defs) |
2224 num_defs = current_def; | |
2225 if(current_company > num_companies) | |
2226 num_companies = current_company;*/ | |
2227 } | |
2228 | |
2229 void initworkers(program * prog) | |
2230 { | |
2231 //num_defs=0; | |
2232 //num_companies=0; | |
2233 create_worker(prog, "Main", 0, 0, USER_FLAG | WORKER_TYPE); | |
2234 | |
2235 initpredefworkers(prog); | |
2236 | |
2237 } | |
2238 /* | |
2239 void add_if_ready(int workerNum, worker_instance * instance) | |
2240 { | |
2241 //int i, j, n, old_ready_count; | |
2242 BOOL ready=FALSE; | |
2243 //int paramstore[32]; | |
2244 //int * params = paramstore; | |
2245 DEBUGPUTS("add_if_ready\n"); | |
2246 if(!instance || !instance->def) | |
2247 return; | |
2248 VIS_PROFILE_START(PROF_ADDREADY); | |
2249 DEBUGPRINTF( "add_if_ready on %s\n", instance->def->implement_func->workerlist[workerNum].name); | |
2250 VIS_EnterCriticalSection(instance->workerlist[workerNum].worker_lock); | |
2251 ++instance->workerlist[workerNum].ready_count; | |
2252 if(instance->workerlist[workerNum].ready_count >= (instance->def->implement_func->workerlist[workerNum].num_inputs + (instance->def->implement_func->workerlist[workerNum].null_input ? 1 : 0))) | |
2253 { | |
2254 ready = TRUE; | |
2255 instance->workerlist[workerNum].ready_count = 0; | |
2256 } | |
2257 VIS_LeaveCriticalSection(instance->workerlist[workerNum].worker_lock); | |
2258 if(ready) | |
2259 { | |
2260 DEBUGPRINTF("add_queue on %s\n", instance->def->implement_func->workerlist[workerNum].name); | |
2261 add_queue(workerNum, instance); | |
2262 } | |
2263 VIS_PROFILE_END(PROF_ADDREADY); | |
2264 }*/ | |
2265 #define RETURN_CODE_EXIT 0xABCE1234 | |
2266 #define RETURN_CODE_IDLE 0x00BADFAD | |
2267 #define RETURN_CODE_NORMAL 0xABBAABBA | |
2268 #define RETURN_CODE_PARALLEL 0xC001D00D | |
2269 #define GET_OP1(opcode) ((opcode & 0xF0000000) >> 28) | |
2270 #define GET_OP2(opcode) ((opcode & 0x0F000000) >> 24) | |
2271 #define GET_INST(opcode) ((opcode & 0x00FF0000) >> 16) | |
2272 | |
2273 #define MOVE_INST 0x00 | |
2274 #define ADDREF_INST 0x01 | |
2275 #define RELEASE_INST 0x02 | |
2276 #define LOAD_INST 0x03 | |
2277 #define CALL_INST 0x04 | |
2278 #define CALLB_INST 0x05 | |
2279 #define CALLP_INST 0x06 | |
2280 #define CALLBP_INST 0x07 | |
2281 #define RETURN_INST 0x08 | |
2282 #define BRANCH_INST 0x09 | |
2283 #define BRANCHT_INST 0x0A | |
2284 #define BRANCHF_INST 0x0B | |
2285 #define WAIT_INST 0x0C | |
2286 #define ADD_INST 0x0D | |
2287 #define SUB_INST 0x0E | |
2288 #define SUBR_INST 0x0F | |
2289 #define GREATER_INST 0x10 | |
2290 #define LESSER_INST 0x11 | |
2291 | |
2292 #define REGISTER_BIT 0x8 | |
2293 #define NO_OPERAND 0x7 | |
2294 #define OP_REG_MASK 0x7 | |
2295 #define GET_REGNUM1(opcode) ((opcode & 0x0000FF00) >> 8) | |
2296 #define GET_REGNUM2(opcode) (opcode & 0x000000FF) | |
2297 | |
2298 #define REG_DIRECT 0 | |
2299 #define REG_INDIRECT 1 | |
2300 #define IMMED_8 2 | |
2301 #define IMMED_32 3 | |
2302 #define STACK_8 4 | |
2303 #define REG_REL_32 5 | |
2304 #define PC_REL_8 6 | |
2305 | |
2306 #define STACK_REG 31 | |
2307 #define PC_REG 30 | |
2308 | |
2309 #define OPC(inst, op1, reg1, op2, reg2) ((op1 << 28) | (op2 << 24) | (inst << 16) | ((reg1 & 0xff) << 8) | (reg2 & 0xFF)) | |
2310 | |
2311 //unsigned long test_program[] = | |
2312 //{ | |
2313 // OPC(LOAD_INST, PC_REL_8, 8 /* Hi */, REG_DIRECT, 0), | |
2314 // OPC(CALLB_INST, IMMED_8, 1/* Print */, NO_OPERAND, 0), | |
2315 // OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0), | |
2316 // 26952//Hi | |
2317 //}; | |
2318 | |
2319 unsigned long test_program[] = | |
2320 { | |
2321 //Main: | |
2322 OPC(LOAD_INST, PC_REL_8, 20/* 10 */, REG_DIRECT, 0), | |
2323 OPC(LOAD_INST, PC_REL_8, 20/* 2 */, PC_REL_8, 28), | |
2324 OPC(LOAD_INST, PC_REL_8, 20/* 1 */, PC_REL_8, 28), | |
2325 OPC(CALL_INST, PC_REL_8, 28/* Fib: */, NO_OPERAND, 0), | |
2326 OPC(CALLB_INST, IMMED_8, 1/* Print */, NO_OPERAND, 0), | |
2327 OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0), | |
2328 0x3033,//'30' | |
2329 0x32,//'2' | |
2330 0x31,//'1' | |
2331 0,//2 storage | |
2332 0,//1 storage | |
2333 //Fib: | |
2334 OPC(ADD_INST, IMMED_8, 8, REG_DIRECT, STACK_REG), | |
2335 OPC(MOVE_INST, REG_DIRECT, 0, STACK_8, -4), | |
2336 OPC(ADDREF_INST, REG_INDIRECT, 0, NO_OPERAND, 0), | |
2337 OPC(ADDREF_INST, REG_INDIRECT, 0, NO_OPERAND, 0), | |
2338 OPC(MOVE_INST, PC_REL_8, -28/* 2 */, REG_DIRECT, 1), | |
2339 OPC(ADDREF_INST, REG_INDIRECT, 1, NO_OPERAND, 0), | |
2340 OPC(CALLB_INST, IMMED_8, 8/* < */, NO_OPERAND, 0), | |
2341 OPC(CALLB_INST, IMMED_8, 11/* If */, NO_OPERAND, 0), | |
2342 OPC(BRANCHT_INST, PC_REL_8, 64/* _Base */, REG_DIRECT, 0), | |
2343 | |
2344 OPC(RELEASE_INST, REG_INDIRECT, 1, NO_OPERAND, 0), | |
2345 OPC(MOVE_INST, STACK_8, -4, REG_DIRECT, 0), | |
2346 OPC(MOVE_INST, PC_REL_8, -56/* 2 */, REG_DIRECT, 1), | |
2347 OPC(ADDREF_INST, REG_INDIRECT, 1, NO_OPERAND, 0), | |
2348 OPC(CALLB_INST, IMMED_8, 6/* - */, NO_OPERAND, 0), | |
2349 OPC(CALL_INST, PC_REL_8, -60/* Fib */, NO_OPERAND, 0), | |
2350 OPC(MOVE_INST, REG_DIRECT, 0, STACK_8, -8), | |
2351 OPC(MOVE_INST, STACK_8, -4, REG_DIRECT, 0), | |
2352 OPC(MOVE_INST, PC_REL_8, -76/* 1 */, REG_DIRECT, 1), | |
2353 OPC(ADDREF_INST, REG_INDIRECT, 1, NO_OPERAND, 0), | |
2354 OPC(CALLB_INST, IMMED_8, 6/* - */, NO_OPERAND, 0), | |
2355 OPC(CALL_INST, PC_REL_8, -84/* Fib */, NO_OPERAND, 0), | |
2356 OPC(MOVE_INST, STACK_8, -8, REG_DIRECT, 1), | |
2357 OPC(CALLB_INST, IMMED_8, 5/* + */, NO_OPERAND, 0), | |
2358 OPC(SUBR_INST, IMMED_8, 8, REG_DIRECT, STACK_REG), | |
2359 OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0), | |
2360 //_Base: | |
2361 OPC(RELEASE_INST, REG_INDIRECT, 0, NO_OPERAND, 0), | |
2362 OPC(MOVE_INST, PC_REL_8, -112/* 1 */, REG_DIRECT, 0), | |
2363 OPC(ADDREF_INST, REG_INDIRECT, 0, NO_OPERAND, 0), | |
2364 OPC(SUBR_INST, IMMED_8, 8, REG_DIRECT, STACK_REG), | |
2365 OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0), | |
2366 | |
2367 }; | |
2368 | |
2369 unsigned long * get_effective_address(char op, unsigned short regnum, unsigned long ** pc, unsigned long * registers, unsigned long * immed) | |
2370 { | |
2371 unsigned long * add = NULL; | |
2372 unsigned long work; | |
2373 if(op != NO_OPERAND) | |
2374 { | |
2375 if(op & REGISTER_BIT) | |
2376 add = (unsigned long *)(registers[regnum] + registers[op & OP_REG_MASK]); | |
2377 else | |
2378 { | |
2379 switch(op) | |
2380 { | |
2381 case REG_DIRECT: | |
2382 add = registers + regnum; | |
2383 break; | |
2384 case REG_INDIRECT: | |
2385 add = (unsigned long *) registers[regnum]; | |
2386 break; | |
2387 case IMMED_8: | |
2388 *immed = (char)regnum; | |
2389 add = (unsigned long *)immed; | |
2390 break; | |
2391 case IMMED_32: | |
2392 *immed = *((*pc)++); | |
2393 add = (unsigned long *)immed; | |
2394 break; | |
2395 case STACK_8: | |
2396 work = (char)regnum; | |
2397 add = (unsigned long *)(registers[STACK_REG] + work); | |
2398 break; | |
2399 case REG_REL_32: | |
2400 work = *((*pc)++); | |
2401 add = (unsigned long *)(registers[regnum] + work); | |
2402 break; | |
2403 case PC_REL_8: | |
2404 work = (char)regnum; | |
2405 add = (unsigned long *)(registers[PC_REG] + work); | |
2406 break; | |
2407 default: | |
2408 break; | |
2409 } | |
2410 } | |
2411 } | |
2412 return add; | |
2413 } | |
2414 | |
2415 DWORD WINAPI virtual_processor(unsigned long * program, BOOL main) | |
2416 { | |
2417 int i; | |
2418 unsigned long **pc; | |
2419 unsigned long **stack; | |
2420 unsigned long registers[32]; | |
2421 unsigned long opcode; | |
2422 unsigned long extra, extra2; | |
2423 queue_entry entry; | |
2424 stack_segment initial_stack; | |
2425 stack_segment * current = &initial_stack; | |
2426 char slot_usage[7]; | |
2427 char op1, op2; | |
2428 char inst; | |
2429 unsigned long *add1, *add2; | |
2430 long immed1, immed2; | |
2431 initial_stack.size = MIN_STACK_SIZE; | |
2432 initial_stack.parent = initial_stack.child = NULL; | |
2433 initial_stack.data[0] = main ? RETURN_CODE_EXIT : RETURN_CODE_IDLE; | |
2434 pc = (unsigned long **)(&(registers[PC_REG])); | |
2435 stack = (unsigned long **)(&(registers[STACK_REG])); | |
2436 *pc = program; | |
2437 *stack = (unsigned long *)(initial_stack.data + 1); | |
2438 entry.instance = NULL; | |
2439 entry.worker_num = 0; | |
2440 DEBUGPRINTF("Virtual processor, Program start: %X\n", program); | |
2441 #ifdef ENABLE_PROFILING | |
2442 for(i = 0; i < NUM_PROFS; ++i) | |
2443 { | |
2444 vis_profile_running_total[i] = 0; | |
2445 vis_profile_counts[i] = 0; | |
2446 } | |
2447 VIS_PROFILE_START(PROF_EMPTYFUNC); | |
2448 empty_test(NULL,NULL); | |
2449 VIS_PROFILE_END(PROF_EMPTYFUNC); | |
2450 VIS_PROFILE_START(PROF_NOCODE); | |
2451 VIS_PROFILE_END(PROF_NOCODE); | |
2452 #endif | |
2453 while(execute_active) | |
2454 { | |
2455 VIS_PROFILE_START(PROF_VIRTUAL_DECODE); | |
2456 DEBUGPRINTF("PC: %X\n", *pc); | |
2457 opcode = *((*pc)++); | |
2458 op1 = GET_OP1(opcode); | |
2459 op2 = GET_OP2(opcode); | |
2460 add1 = get_effective_address(op1, GET_REGNUM1(opcode), pc, registers, &immed1); | |
2461 add2 = get_effective_address(op2, GET_REGNUM2(opcode), pc, registers, &immed2); | |
2462 DEBUGPRINTF("Opcode: %X, Instruction: %X, op1 %X, op2 %X\n", opcode, GET_INST(opcode), op1, op2); | |
2463 inst = GET_INST(opcode); | |
2464 VIS_PROFILE_END(PROF_VIRTUAL_DECODE); | |
2465 VIS_PROFILE_START(PROF_VIRTUAL_EXECUTE); | |
2466 switch(inst) | |
2467 { | |
2468 case MOVE_INST: | |
2469 *add2 = *add1; | |
2470 break; | |
2471 case ADDREF_INST: | |
2472 add_ref((datum *)add1); | |
2473 break; | |
2474 case RELEASE_INST: | |
2475 release_ref((datum *)add1); | |
2476 break; | |
2477 /* | |
2478 Temporarily commented out until multiple program support is finished | |
2479 case LOAD_INST: | |
2480 *add2 = (long)get_constant((char *)add1, -1); | |
2481 break; | |
2482 */ | |
2483 case CALL_INST: | |
2484 *((*stack)++) = (unsigned long)*pc; | |
2485 *((*stack)++) = RETURN_CODE_NORMAL; | |
2486 *pc = add1; | |
2487 break; | |
2488 /* | |
2489 Temporarily commented out until multiple program support is finished | |
2490 case CALLB_INST: | |
2491 //TODO: Needs to be made 100% correct | |
2492 DEBUGPRINTF("Calling builtin: %s\n", deflist[*add1].name); | |
2493 execute_def(deflist + *add1, entry, (datum **)registers, NULL); | |
2494 break;*/ | |
2495 case CALLP_INST: | |
2496 //TODO Implement me | |
2497 break; | |
2498 case CALLBP_INST: | |
2499 //TODO Implement me | |
2500 break; | |
2501 case RETURN_INST: | |
2502 switch(*(--(*stack))) | |
2503 { | |
2504 case RETURN_CODE_EXIT: | |
2505 execute_active = FALSE; | |
2506 break; | |
2507 case RETURN_CODE_IDLE: | |
2508 //TODO: Implement me | |
2509 break; | |
2510 case RETURN_CODE_NORMAL: | |
2511 *pc = (unsigned long *)*(--(*stack)); | |
2512 break; | |
2513 default: | |
2514 break; | |
2515 } | |
2516 break; | |
2517 case BRANCH_INST: | |
2518 *pc = add1; | |
2519 break; | |
2520 case BRANCHT_INST: | |
2521 if(*add2) | |
2522 *pc = add1; | |
2523 break; | |
2524 case BRANCHF_INST: | |
2525 if(!*add2) | |
2526 *pc = add1; | |
2527 break; | |
2528 case WAIT_INST: | |
2529 //TODO: Implement Me | |
2530 break; | |
2531 case ADD_INST: | |
2532 *add2 = *add1 + *add2; | |
2533 break; | |
2534 case SUB_INST: | |
2535 *add2 = *add1 - *add2; | |
2536 break; | |
2537 case SUBR_INST: | |
2538 *add2 = *add2 - *add1; | |
2539 break; | |
2540 case GREATER_INST: | |
2541 *add2 = *add1 > *add2; | |
2542 break; | |
2543 case LESSER_INST: | |
2544 *add2 = *add1 < *add2; | |
2545 break; | |
2546 default: | |
2547 break; | |
2548 } | |
2549 VIS_PROFILE_END(PROF_VIRTUAL_EXECUTE); | |
2550 } | |
2551 #ifdef ENABLE_PROFILING | |
2552 for(i = 0; i < NUM_PROFS; ++i) | |
2553 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])); | |
2554 #endif | |
2555 return 0; | |
2556 } | |
2557 | |
2558 void test_virtual() | |
2559 { | |
2560 // int i,j,k; | |
2561 program * prog = new_program(START_DEF_STORAGE, START_COMP_STORAGE); | |
2562 initpredefworkers(prog); | |
2563 init_sync_primitives(); | |
2564 init_datum_storage(); | |
2565 //TODO Uncomment me | |
2566 // init_global_storage(); | |
2567 execute_active = TRUE; | |
2568 /* for(i = MOVE_INST; i <= LESSER_INST; ++i) | |
2569 { | |
2570 for(j = 0; j < 0x10; ++j) | |
2571 { | |
2572 for(k = 0; k < 0x10; ++k) | |
2573 { | |
2574 DEBUGPRINTF("i: %X, j: %X, k: %X, OPC: %X\n", i, j, k, OPC(i, j, j, k, k)); | |
2575 } | |
2576 } | |
2577 }*/ | |
2578 virtual_processor(test_program, TRUE); | |
2579 } | |
2580 | |
2581 DWORD WINAPI worker_thread(LPVOID param) | |
2582 { | |
2583 queue_entry aworker; | |
2584 int temp_queue_len; | |
2585 while(execute_active) | |
2586 { | |
2587 VIS_PROFILE_START(PROF_WORKER_THREAD); | |
2588 #ifdef NINTENDO_DS | |
2589 if(irq_queue_count > 0) | |
2590 run_queued_irqs(); | |
2591 #endif | |
2592 //DEBUGPUTS("Before WaitForSingleObect\n"); | |
2593 /*VIS_EnterCriticalSection(worker_queue_lock); | |
2594 temp_queue_len = queue_len; | |
2595 VIS_LeaveCriticalSection(worker_queue_lock);*/ | |
2596 //DEBUGPUTS("After WaitForSingleObject\n"); | |
2597 aworker = get_queue(); | |
2598 //DEBUGPUTS("After get_queue()\n"); | |
2599 //while(execute_active && aworker.worker_num < 0)//temp_queue_len == 0 && execute_active) | |
2600 //{ | |
2601 // VIS_WaitEvent(queue_add_event); | |
2602 // aworker = get_queue(); | |
2603 /*#if COMPILE_THREADS > 0 | |
2604 #ifdef WIN32 | |
2605 Sleep(0); | |
2606 #else | |
2607 sleep(0); | |
2608 #endif | |
2609 #endif | |
2610 VIS_EnterCriticalSection(worker_queue_lock); | |
2611 temp_queue_len = queue_len; | |
2612 VIS_LeaveCriticalSection(worker_queue_lock);*/ | |
2613 //} | |
2614 | |
2615 if(aworker.worker_num >= 0) | |
2616 { | |
2617 //DEBUGPUTS("Before EnterCriticalSection\n"); | |
2618 | |
2619 /* VIS_EnterCriticalSection(worker_queue_lock); | |
2620 if(queue_len > 0) | |
2621 { | |
2622 DEBUGPUTS("SetEvent\n"); | |
2623 VIS_SetEvent(queue_add_event); | |
2624 } | |
2625 VIS_LeaveCriticalSection(worker_queue_lock);*/ | |
2626 DEBUGPRINTF( "\nExecuting: %s<%d>, Instance: %X\n", aworker.instance->def->implement_func->workerlist[aworker.worker_num].name,aworker.worker_num,aworker.instance); | |
2627 | |
2628 if(process_worker(aworker) == 0) | |
2629 { | |
2630 //worker_complete(aworker); | |
2631 cleanup_check(aworker); | |
2632 //DEBUGPUTS("After cleanup_check\n"); | |
2633 | |
2634 } | |
2635 | |
2636 } | |
2637 VIS_PROFILE_END(PROF_WORKER_THREAD); | |
2638 } | |
2639 VIS_SetEvent(queue_add_event); | |
2640 return 0; | |
2641 } | |
2642 | |
2643 int set_comp_room(datum ** params, int room_index, queue_entry * entry, program * prog) | |
2644 { | |
2645 int i; | |
2646 char * data; | |
2647 //DEBUGPRINTF("params[0]->ref_count: %d\n", params[0]->ref_count); | |
2648 params[0] = copy_datum(params[0], 0); | |
2649 data = ((char *)(params[0]->c.generic.data) + (int)params[0]->company->room_list[room_index].set_func); | |
2650 DEBUGPRINTF("Set comp room: c.generic.data = %X, +get_func = %X\n", params[0]->c.generic.data, data); | |
2651 //TODO: input conversion | |
2652 switch(params[0]->company->room_list[room_index].get_func_type) | |
2653 { | |
2654 case ROOM_BYTE: | |
2655 *data = params[1]->c.integers.num_a; | |
2656 release_ref(params[1]); | |
2657 break; | |
2658 case ROOM_SHORT: | |
2659 *((short *)data) = params[1]->c.integers.num_a; | |
2660 release_ref(params[1]); | |
2661 break; | |
2662 case ROOM_LONG: | |
2663 *((long *)data) = params[1]->c.integers.num_a; | |
2664 release_ref(params[1]); | |
2665 break; | |
2666 case ROOM_SINGLE: | |
2667 *((float *)data) = params[1]->c.real; | |
2668 release_ref(params[1]); | |
2669 break; | |
2670 case ROOM_DOUBLE: | |
2671 *((double *)data) = params[1]->c.real; | |
2672 release_ref(params[1]); | |
2673 break; | |
2674 case ROOM_VIS_REF: | |
2675 release_ref(*((datum **)data)); | |
2676 *((datum **)data) = params[1]; | |
2677 break; | |
2678 case ROOM_CSTRING: //not implemented | |
2679 case ROOM_CSTRING_STRUCT: | |
2680 case ROOM_PSTRING: | |
2681 case ROOM_PSTRING_STRUCT: | |
2682 case ROOM_WORKER://not implemented | |
2683 case ROOM_VIS_OBJECT://not implemented | |
2684 default: | |
2685 release_ref(params[0]); | |
2686 release_ref(params[1]); | |
2687 params[0] = params[1] = NULL; | |
2688 puts("unimplemented company room type\n"); | |
2689 break; | |
2690 } | |
2691 return 0; | |
2692 } | |
2693 | |
2694 int set_comp_room_by_name(datum ** company, char * name, int * room_index_ret, queue_entry * entry, program * prog) | |
2695 { | |
2696 int i; | |
2697 for (i = 0; i < company[0]->company->num_rooms; ++i) | |
2698 if(!strcmp(name,company[0]->company->room_list[i].name)) | |
2699 { | |
2700 if(room_index_ret) | |
2701 *room_index_ret = i; | |
2702 return set_comp_room(company, i, entry, prog); | |
2703 } | |
2704 if(room_index_ret) | |
2705 *room_index_ret = -1; | |
30
914ad38f9b59
Compiler now works for some simple programs
Mike Pavone <pavone@retrodev.com>
parents:
29
diff
changeset
|
2706 printf("Error: Can't set field %s on object with blueprint %s\n", name, company[0]->company); |
0 | 2707 return -1; |
2708 } | |
2709 | |
2710 int get_comp_room(datum ** company, int room_index, queue_entry * entry, program * prog) | |
2711 { | |
2712 int i; | |
2713 datum * out; | |
2714 queue_entry empty; | |
2715 char * data = ((char *)(company[0]->c.generic.data) + (int)company[0]->company->room_list[room_index].get_func); | |
2716 company[1] = NULL; | |
2717 DEBUGPRINTF("Get comp room: c.generic.data = %X, +get_func = %X\n", company[0]->c.generic.data, data); | |
2718 switch(company[0]->company->room_list[room_index].get_func_type) | |
2719 { | |
2720 case ROOM_BYTE: | |
2721 out = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, prog); | |
2722 out->c.integers.num_a = *data; | |
2723 break; | |
2724 case ROOM_SHORT: | |
2725 out = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, prog); | |
2726 out->c.integers.num_a = *((short *)data); | |
2727 break; | |
2728 case ROOM_LONG: | |
2729 out = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, prog); | |
2730 out->c.integers.num_a = *((long *)data); | |
2731 break; | |
2732 case ROOM_SINGLE: | |
2733 out = new_datum(BUILTIN_TYPE_REAL, 3, 0, prog); | |
2734 out->c.real = *((float *)data); | |
2735 break; | |
2736 case ROOM_DOUBLE: | |
2737 out = new_datum(BUILTIN_TYPE_REAL, 3, 0, prog); | |
2738 out->c.real = *((double *)data); | |
2739 break; | |
2740 case ROOM_CSTRING: | |
2741 data = *((char **)data); | |
2742 case ROOM_CSTRING_STRUCT: | |
2743 out = new_datum(BUILTIN_TYPE_STRING, 1, strlen(data)+1, prog); | |
2744 strcpy(out->c.generic.data, data); | |
2745 break; | |
2746 case ROOM_PSTRING: | |
2747 data = *((char **)data); | |
2748 case ROOM_PSTRING_STRUCT: | |
2749 out = new_datum(BUILTIN_TYPE_STRING, 1, *((unsigned char *)data), prog); | |
2750 memcpy(out->c.generic.data, data, *((unsigned char *)data)); | |
2751 ((char *)out->c.generic.data)[*((unsigned char *)data)] = '\0'; | |
2752 break; | |
2753 case ROOM_VIS_REF: | |
2754 out = add_ref(*((datum **)data)); | |
2755 if(!out) { | |
2756 company[1] = company[0]; | |
2757 company[0] = NULL; | |
2758 } | |
2759 break; | |
2760 case ROOM_WORKER: | |
2761 if(entry) | |
2762 return execute_def((worker_def *)(company[0]->company->room_list[room_index].get_func), *entry, company, sub_callback); | |
2763 else | |
2764 { | |
2765 empty.instance = NULL; | |
2766 empty.worker_num = -1; | |
2767 return execute_def((worker_def *)(company[0]->company->room_list[room_index].get_func), empty, company, sub_callback); | |
2768 } | |
2769 case ROOM_VIS_OBJECT://not implemented | |
2770 default: | |
2771 out = NULL; | |
2772 puts("unimplemented company room type\n"); | |
2773 break; | |
2774 } | |
2775 release_ref(company[0]); | |
2776 company[0] = out; | |
2777 return 0; | |
2778 } | |
2779 | |
2780 int get_comp_room_by_name(datum ** company, char * name, int * room_index_ret, queue_entry * entry, program * prog) | |
2781 { | |
2782 int i; | |
2783 for (i = 0; i < company[0]->company->num_rooms; ++i) | |
2784 if(!strcmp(name,company[0]->company->room_list[i].name)) | |
2785 { | |
2786 if(room_index_ret) | |
2787 *room_index_ret = i; | |
2788 return get_comp_room(company, i, entry, prog); | |
2789 } | |
2790 if(room_index_ret) | |
2791 *room_index_ret = -1; | |
30
914ad38f9b59
Compiler now works for some simple programs
Mike Pavone <pavone@retrodev.com>
parents:
29
diff
changeset
|
2792 printf("Error: Can't get field %s from object with blueprint %s\n", name, company[0]->company); |
914ad38f9b59
Compiler now works for some simple programs
Mike Pavone <pavone@retrodev.com>
parents:
29
diff
changeset
|
2793 print_stack_trace(entry->instance); |
0 | 2794 return -1; |
2795 } | |
2796 | |
2797 datum * literal_string(char * value, int len, program * prog) | |
2798 { | |
2799 char literalchar; | |
2800 BOOL literal; | |
2801 int i, bufpos, lenstr; | |
2802 datum * returnval; | |
2803 | |
2804 if(len < 0) { | |
2805 len = strlen(value); | |
2806 } | |
2807 | |
2808 literal = FALSE; | |
2809 lenstr = 0; | |
2810 for(i = 0; i < len; ++i) | |
2811 if(literal) | |
2812 literal = FALSE; | |
2813 else | |
2814 { | |
2815 ++lenstr; | |
2816 if(value[i] == '\\') | |
2817 literal = TRUE; | |
2818 } | |
2819 //DEBUGPRINTF("Allocating %d bytes for string constant\n", lenstr+1); | |
2820 returnval = new_datum(BUILTIN_TYPE_STRING, 1, lenstr+1, prog); | |
2821 bufpos = 0; | |
2822 for(i = 0; i < len; ++i) | |
2823 { | |
2824 if(literal) | |
2825 { | |
2826 literal = FALSE; | |
2827 switch(value[i]) | |
2828 { | |
2829 case 'n': //newline | |
2830 literalchar = '\n'; | |
2831 break; | |
2832 case 'r': //carriage return | |
2833 literalchar = '\r'; | |
2834 break; | |
2835 case 't': // tab | |
2836 literalchar = '\t'; | |
2837 break; | |
2838 case '0': //NULL | |
2839 literalchar = '\0'; | |
2840 break; | |
2841 default: | |
2842 literalchar = value[i]; | |
2843 break; | |
2844 } | |
2845 ((char *)returnval->c.generic.data)[bufpos++] = literalchar; | |
2846 } | |
2847 else | |
2848 { | |
2849 if(value[i] == '\\') | |
2850 literal = TRUE; | |
2851 else | |
2852 { | |
2853 ((char *)returnval->c.generic.data)[bufpos++] = value[i]; | |
2854 } | |
2855 } | |
2856 } | |
2857 //DEBUGPRINTF("bufpos: %d\n", bufpos); | |
2858 ((char *)returnval->c.generic.data)[bufpos] = '\0'; | |
2859 DEBUGPUTS("Constant Type: String\n"); | |
2860 return returnval; | |
2861 } | |
2862 | |
2863 datum * get_constant(char * value, int len, program * prog) | |
2864 { | |
2865 datum * params[2]; | |
2866 datum * returnval; | |
2867 int i = 0,bufpos; | |
2868 int start; | |
2869 int lenstr; | |
2870 int leftcurly; | |
2871 int dotcount = 0; | |
2872 char literalchar; | |
2873 unsigned short const_type = ANY_TYPE; | |
2874 BOOL literal; | |
2875 if((len == 3 && memcmp(value, "Yes", len) == 0) || (len < 0 && strcmp(value, "Yes") == 0)) | |
2876 { | |
2877 DEBUGPUTS("Constnat: Yes\n"); | |
2878 returnval = new_datum(BUILTIN_TYPE_YESNO, 2, 0, prog); | |
2879 returnval->c.integers.num_a = 1; | |
2880 DEBUGPRINTF("Company: %s, integers.num_a: %d\n", returnval->company->name, returnval->c.integers.num_a); | |
2881 return returnval; | |
2882 } | |
2883 else if((len == 2 && memcmp(value, "No", len) == 0) || (len < 0 && strcmp(value, "No") == 0)) | |
2884 { | |
2885 DEBUGPUTS("Constant: No\n"); | |
2886 returnval = new_datum(BUILTIN_TYPE_YESNO, 2, 0, prog); | |
2887 returnval->c.integers.num_a = 0; | |
2888 DEBUGPRINTF("Company: %s, integers.num_a: %d\n", returnval->company->name, returnval->c.integers.num_a); | |
2889 return returnval; | |
2890 } | |
2891 if(value[0] == '{') | |
2892 { | |
2893 DEBUGPUTS("Constant type: List"); | |
2894 params[0] = create_list(prog); | |
2895 i = start = 1; | |
2896 literal = FALSE; | |
2897 leftcurly = 0; | |
2898 for(;value[i] != 0 && (len < 0 || i < len); ++i) | |
2899 { | |
2900 if(literal) | |
2901 literal = FALSE; | |
2902 else | |
2903 { | |
2904 if(value[i] == '\\') | |
2905 literal = TRUE; | |
2906 else if(value[i] == '}') | |
2907 if(leftcurly) | |
2908 --leftcurly; | |
2909 else | |
2910 break; | |
2911 else if(value[i] == '{') | |
2912 ++leftcurly; | |
2913 else if(value[i] == ',' && !leftcurly) | |
2914 { | |
2915 params[1] = get_constant(value+start, i-start, prog); | |
2916 vis_list_append(params, NULL); | |
2917 start = i+1; | |
2918 } | |
2919 } | |
2920 } | |
2921 params[1]= get_constant(value+start, i-start, prog); | |
2922 vis_list_append(params, NULL); | |
2923 returnval = params[0]; | |
2924 } | |
2925 else if(value[0] == '"') | |
2926 { | |
2927 if(len < 0) { | |
2928 len = strlen(value); | |
2929 } | |
2930 len -= 2; | |
2931 returnval = literal_string(value+1, len, prog); | |
2932 | |
2933 } | |
2934 else | |
2935 { | |
2936 while(value[i] != 0 && (len < 0 || i < len)) | |
2937 { | |
2938 if(value[i] >= '0' && value[i] <= '9') | |
2939 { | |
2940 if(const_type == ANY_TYPE) | |
2941 const_type = BUILTIN_TYPE_WHOLE; | |
2942 } | |
2943 else if(value[i] == '.') | |
2944 { | |
2945 if(dotcount) | |
2946 { | |
2947 const_type = BUILTIN_TYPE_STRING; | |
2948 } | |
2949 else | |
2950 { | |
2951 ++dotcount; | |
2952 if(const_type == BUILTIN_TYPE_WHOLE) | |
2953 const_type = BUILTIN_TYPE_REAL; | |
2954 } | |
2955 } | |
2956 else | |
2957 { | |
2958 //DEBUGPRINTF("Current character: %c resulted in String\n", value[i]); | |
2959 const_type = BUILTIN_TYPE_STRING; | |
2960 break; | |
2961 } | |
2962 ++i; | |
2963 } | |
2964 | |
2965 if(const_type == BUILTIN_TYPE_WHOLE) | |
2966 { | |
2967 returnval = new_datum(const_type, 2, 0, prog); | |
2968 returnval->c.integers.num_a = atol(value); | |
2969 DEBUGPUTS("Constant Type: Whole Number\n"); | |
2970 } | |
2971 else if(const_type == BUILTIN_TYPE_REAL) | |
2972 { | |
2973 returnval = new_datum(const_type, 3, 0, prog); | |
2974 returnval->c.real = atof(value); | |
2975 DEBUGPUTS("Constant Type: Real Number\n"); | |
2976 } | |
2977 else | |
2978 { | |
2979 /* literal = FALSE; | |
2980 lenstr = 0; | |
2981 for(i = 0; (i < len || len < 0) && value[i] != 0; ++i) | |
2982 if(literal) | |
2983 literal = FALSE; | |
2984 else | |
2985 { | |
2986 ++lenstr; | |
2987 if(value[i] == '\\') | |
2988 literal = TRUE; | |
2989 } | |
2990 DEBUGPRINTF("Allocating %d bytes for string constant\n", lenstr+1); | |
2991 returnval = new_datum(BUILTIN_TYPE_STRING, 1, lenstr+1, prog); | |
2992 bufpos = 0; | |
2993 for(i = 0; (i < len || len < 0) && value[i] != 0; ++i) | |
2994 { | |
2995 DEBUGPRINTF("bufpos: %d\n", bufpos); | |
2996 if(literal) | |
2997 { | |
2998 literal = FALSE; | |
2999 switch(value[i]) | |
3000 { | |
3001 case 'n': //newline | |
3002 literalchar = '\n'; | |
3003 break; | |
3004 case 'r': //carriage return | |
3005 literalchar = '\r'; | |
3006 break; | |
3007 case 't': // tab | |
3008 literalchar = '\t'; | |
3009 break; | |
3010 case '0': //NULL | |
3011 literalchar = '\0'; | |
3012 break; | |
3013 default: | |
3014 literalchar = value[i]; | |
3015 break; | |
3016 } | |
3017 ((char *)returnval->c.generic.data)[bufpos++] = literalchar; | |
3018 } | |
3019 else | |
3020 { | |
3021 if(value[i] == '\\') | |
3022 literal = TRUE; | |
3023 else | |
3024 { | |
3025 ((char *)returnval->c.generic.data)[bufpos++] = value[i]; | |
3026 } | |
3027 } | |
3028 } | |
3029 DEBUGPRINTF("bufpos: %d\n", bufpos); | |
3030 ((char *)returnval->c.generic.data)[bufpos] = '\0'; | |
3031 DEBUGPUTS("Constant Type: String\n"); */ | |
3032 returnval = literal_string(value, len, prog); | |
3033 } | |
3034 } | |
3035 return returnval; | |
3036 } | |
3037 | |
3038 int execute_def(worker_def * process_def, queue_entry worker_entry, datum ** params, instance_callback callback) | |
3039 { | |
3040 return execute_def_type(process_def, worker_entry, params, callback, NULL, WORKER); | |
3041 } | |
3042 int execute_def_data(worker_def * process_def, queue_entry worker_entry, datum ** params, instance_callback callback, void * data) | |
3043 { | |
3044 return execute_def_type(process_def, worker_entry, params, callback, data, WORKER); | |
3045 } | |
3046 | |
3047 int execute_def_type(worker_def * process_def, queue_entry worker_entry, datum ** params, instance_callback callback, void * data, int type) | |
3048 { | |
3049 int returnval, i; | |
3050 worker_instance * stack_instance; | |
3051 worker_def *temp_def, *converter; | |
3052 worker_def *parent_def = worker_entry.instance->def; | |
3053 unsigned short magic_cache_type; | |
3054 #ifdef USER_PROFILE | |
3055 LARGE_INTEGER start, end, duration; | |
3056 #endif | |
3057 VIS_PROFILE_START(PROF_PREP_MAGIC); | |
3058 if((process_def->type & TYPE_MASK) == MAGIC_TYPE) | |
3059 { | |
3060 DEBUGPRINTF( "Magic method: %s\n", process_def->name); | |
3061 if(!params || !params[0]) | |
3062 { | |
3063 ERRORPRINTF("Error: null first parmeter or null parameter array for worker %s\n", process_def->name); | |
3064 print_stack_trace(worker_entry.instance); | |
3065 execute_active = FALSE; | |
3066 return -1; | |
3067 } | |
3068 VIS_EnterCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock); | |
3069 temp_def = parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_implement; | |
3070 magic_cache_type = parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_type; | |
3071 VIS_LeaveCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock); | |
3072 if(!temp_def || magic_cache_type != params[0]->company->type_id) | |
3073 { | |
3074 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); | |
3075 temp_def = find_method(params[0]->company->type_id,process_def->name, process_def->num_inputs, process_def->program); | |
3076 if(!temp_def) | |
3077 { | |
3078 for(i = 1; i < process_def->program->num_companies; ++i) | |
3079 { | |
3080 temp_def = find_method(i,process_def->name, process_def->num_inputs, process_def->program); | |
3081 if(temp_def) | |
3082 { | |
3083 converter = find_converter_method(temp_def->input_types[0], params[0]->company->type_id, process_def->program); | |
3084 if(converter) | |
3085 { | |
3086 ((worker_impl)converter->implement_func)(params, &worker_entry); | |
3087 break; | |
3088 } | |
3089 else | |
3090 { | |
3091 //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); | |
3092 //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); | |
3093 temp_def = NULL; | |
3094 } | |
3095 } | |
3096 } | |
3097 } | |
3098 if(temp_def) | |
3099 { | |
3100 VIS_EnterCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock); | |
3101 parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_implement = temp_def; | |
3102 parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_type = temp_def->input_types[0]; | |
3103 VIS_LeaveCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock); | |
3104 } | |
3105 else | |
3106 { | |
3107 ERRORPRINTF("Error: Company %s doesn't implement worker %s. It implements the following:\n", params[0]->company->name, process_def->name); | |
3108 for(i = 0; i < params[0]->company->num_methods; ++i) | |
3109 { | |
3110 ERRORPRINTF("%s\n", params[0]->company->methodlist[i]->name); | |
3111 } | |
3112 print_stack_trace(worker_entry.instance); | |
3113 } | |
3114 } | |
3115 process_def = temp_def; | |
3116 } | |
3117 VIS_PROFILE_END(PROF_PREP_MAGIC); | |
3118 if(!process_def) | |
3119 { | |
3120 //DEBUGPUTS("Invalid def\n"); | |
3121 VIS_PROFILE_END(PROF_EXECUTE_WORKER); | |
3122 execute_active = FALSE; | |
3123 return -2; | |
3124 } | |
3125 | |
3126 VIS_PROFILE_START(PROF_CONVERT_INPUTS); | |
3127 for(i = 0; i < process_def->num_inputs; ++i) | |
3128 { | |
3129 DEBUGPRINTF("params[%d] = %X\n", i, params[i]); | |
3130 if(process_def->input_types[i] != ANY_TYPE && process_def->input_types[i] != params[i]->company->type_id) | |
3131 { | |
3132 DEBUGPRINTF("Input %d needs conversion from %d to %d\n", i, params[i]->company->type_id, process_def->input_types[i]); | |
3133 converter = find_converter_method(process_def->input_types[i], params[i]->company->type_id, process_def->program); | |
3134 if(!converter) | |
3135 { | |
3136 if(worker_entry.instance) { | |
3137 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); | |
13 | 3138 print_stack_trace(worker_entry.instance); |
0 | 3139 } else { |
3140 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); | |
3141 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); | |
3142 } | |
3143 execute_active = FALSE; | |
3144 VIS_PROFILE_END(PROF_PROCESS_WORKER); | |
3145 return -3; | |
3146 } | |
3147 ((worker_impl)(converter->implement_func))(params+i, &worker_entry); | |
3148 } | |
3149 } | |
3150 VIS_PROFILE_END(PROF_CONVERT_INPUTS); | |
3151 | |
3152 if(process_def->type & USER_FLAG) | |
3153 { | |
3154 VIS_PROFILE_START(PROF_EXECUTE_CUSTOM); | |
3155 // | |
3156 init_custom_worker_type(worker_entry.worker_num, worker_entry.instance, process_def, callback, data, params, type); | |
3157 VIS_PROFILE_END(PROF_EXECUTE_CUSTOM); | |
3158 VIS_PROFILE_END(PROF_PROCESS_WORKER); | |
3159 VIS_PROFILE_END(PROF_EXECUTE_WORKER); | |
3160 return 1; | |
3161 } | |
3162 else | |
3163 { | |
3164 VIS_PROFILE_START(PROF_EXECUTE_BUILTIN); | |
3165 //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); | |
3166 #ifdef USER_PROFILE | |
3167 QueryPerformanceCounter(&start); | |
3168 #endif | |
3169 returnval = ((worker_impl)(process_def->implement_func))(params, &worker_entry); | |
3170 #ifdef USER_PROFILE | |
3171 if(!returnval) | |
3172 { | |
3173 QueryPerformanceCounter(&end); | |
3174 duration.QuadPart = end.QuadPart - start.QuadPart; | |
3175 VIS_EnterCriticalSection(process_def->lock); | |
3176 process_def->total.QuadPart += duration.QuadPart; | |
3177 ++process_def->count; | |
3178 if(duration.QuadPart > process_def->worst.QuadPart) | |
3179 process_def->worst.QuadPart = duration.QuadPart; | |
3180 VIS_LeaveCriticalSection(process_def->lock); | |
3181 } | |
3182 #endif | |
3183 //DEBUGPUTS("Builtin worker returned\n"); | |
3184 VIS_PROFILE_END(PROF_EXECUTE_BUILTIN); | |
3185 return returnval; | |
3186 } | |
3187 } | |
3188 | |
3189 void wait_callback(worker_instance * caller_instance, int caller_workerenum, worker_instance * done_instance, void * data) | |
3190 { | |
3191 int i; | |
3192 def_done * done = (def_done *)data; | |
3193 //DEBUGPUTS("begin wait_callback\n"); | |
3194 for(i = 0; i < done_instance->def->num_outputs; ++i) | |
3195 done->params[i] = NULL; | |
3196 for(i = 0; i < done_instance->def->implement_func->num_workers; ++i) | |
3197 { | |
3198 if(done_instance->def->implement_func->workerlist[i].type == 4) | |
3199 { | |
3200 if(!(done->params[done_instance->def->implement_func->workerlist[i].io_num])) | |
3201 { | |
3202 done->params[done_instance->def->implement_func->workerlist[i].io_num] = done_instance->workerlist[i].value; | |
3203 done_instance->workerlist[i].value = NULL; | |
3204 } | |
3205 } | |
3206 } | |
3207 //DEBUGPUTS("Before EnterCritical\n"); | |
3208 VIS_EnterCriticalSection(done->lock); | |
3209 done->done_flag = TRUE; | |
3210 VIS_LeaveCriticalSection(done->lock); | |
3211 //DEBUGPUTS("After EnterCritical\n"); | |
3212 } | |
3213 | |
3214 | |
3215 BOOL execute_def_wait(worker_def * def, datum ** params) | |
3216 { | |
3217 int val; | |
3218 def_done done; | |
3219 queue_entry entry; | |
3220 entry.worker_num = 0; | |
3221 entry.instance = NULL; | |
3222 VIS_InitializeCriticalSection(done.lock); | |
3223 done.done_flag = FALSE; | |
3224 done.params = params; | |
3225 val = execute_def_data(def, entry, params, wait_callback, &done); | |
3226 if(val == 0) | |
3227 return TRUE; | |
3228 else if (val < 0) | |
3229 return FALSE; | |
3230 while(1) | |
3231 { | |
3232 VIS_EnterCriticalSection(done.lock); | |
3233 if(done.done_flag) | |
3234 { | |
3235 VIS_DeleteCriticalSection(done.lock); | |
3236 break; | |
3237 } | |
3238 VIS_LeaveCriticalSection(done.lock); | |
3239 #if COMPILE_THREADS > 1 | |
3240 #ifdef WIN32 | |
3241 Sleep(0); | |
3242 #else | |
3243 sleep(0); | |
3244 #endif | |
3245 #endif | |
3246 } | |
3247 return TRUE; | |
3248 } | |
3249 | |
3250 int process_worker(queue_entry worker_entry) | |
3251 { | |
3252 //datum * paramstore[32]; | |
3253 datum ** params;// = paramstore; | |
3254 int i, j, start=0; | |
3255 global_store * store; | |
3256 char * varname; | |
3257 datum * varname_dat; | |
3258 datum * tempvalindex, *todelete; | |
3259 int got_params=0; | |
3260 int aworker = worker_entry.worker_num; | |
3261 worker_instance * instance = worker_entry.instance; | |
3262 worker_def * def = instance->def; | |
3263 worker_def * process_def; | |
3264 worker_def * temp_def; | |
3265 worker_def * converter; | |
3266 int returnval = 0; | |
3267 short const_type; | |
3268 char * last; | |
3269 | |
3270 VIS_PROFILE_START(PROF_PROCESS_WORKER); | |
3271 | |
3272 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); | |
3273 /*VIS_EnterCriticalSection(instance->workerlist[aworker].worker_lock); | |
3274 for(i = 0; i < def->implement_func->workerlist[aworker].num_inputs; ++i) | |
3275 { | |
3276 params[i] = instance->workerlist[aworker].params[i+1]; | |
3277 DEBUGPRINTF("params[%d] = %X\n", i, params[i]); | |
3278 instance->workerlist[aworker].params[i+1] = NULL; | |
3279 }*/ | |
3280 if(def->implement_func->workerlist[aworker].null_input) | |
3281 { | |
3282 //DEBUGPUTS("About to call release_ref\n"); | |
3283 release_ref(instance->workerlist[aworker].params[0]); | |
3284 instance->workerlist[aworker].params[0] = NULL; | |
3285 } | |
3286 //VIS_LeaveCriticalSection(instance->workerlist[aworker].worker_lock); | |
3287 //DEBUGPRINTF("Param check complete. returnval: %d, start: %d\n", returnval, start); | |
3288 params = instance->workerlist[aworker].params+1; | |
3289 | |
3290 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 | |
3291 { | |
3292 VIS_PROFILE_START(PROF_EXECUTE_WORKER); | |
3293 //DEBUGPUTS("Worker\n"); | |
3294 process_def = (worker_def *)(def->implement_func->workerlist[aworker].value_index); | |
3295 //DEBUGPUTS("Got process_def\n"); | |
3296 DEBUGPRINTF("process_def->type: %X, type & TYPE_MASK: %X\n", process_def->type, (process_def->type & TYPE_MASK)); | |
3297 | |
3298 returnval = execute_def_type(process_def, worker_entry, params, sub_callback, NULL, def->implement_func->workerlist[aworker].type); | |
3299 DEBUGPRINTF("execute_def returned %d\n", returnval); | |
3300 if(returnval != 0) | |
3301 { | |
3302 VIS_PROFILE_END(PROF_PROCESS_WORKER); | |
3303 VIS_PROFILE_END(PROF_EXECUTE_WORKER); | |
3304 return returnval; | |
3305 } | |
3306 //DEBUGPRINTF("params[0] after execute_def: %X\n", params[0]); | |
3307 | |
3308 //DEBUGPUTS("Before process_outputs\n"); | |
3309 | |
3310 process_outputs(params, aworker, instance); | |
3311 //DEBUGPUTS("After process_outputs\n"); | |
3312 | |
3313 VIS_PROFILE_END(PROF_EXECUTE_WORKER); | |
3314 | |
3315 } | |
3316 else if(def->implement_func->workerlist[aworker].type == GET_GLOBAL) | |
3317 { | |
3318 varname = def->implement_func->workerlist[aworker].name + def->implement_func->workerlist[aworker].io_num; | |
3319 varname_dat = make_string(varname, -1, def->program); | |
3320 if(def->implement_func->workerlist[aworker].value_index < 0) | |
3321 { | |
3322 for(i = 0; i < instance->trans->num_stores; ++i) | |
3323 { | |
3324 VIS_EnterCriticalSection(instance->trans->stores[i].lock); | |
3325 params[0] = add_ref(instance->trans->stores[i].instance_data); | |
3326 VIS_LeaveCriticalSection(instance->trans->stores[i].lock); | |
3327 params[1] = add_ref(varname_dat); | |
3328 vis_dict_index(params, NULL); | |
3329 | |
3330 if(params[0]) | |
3331 { | |
3332 def->implement_func->workerlist[aworker].value_index = i; | |
3333 break; | |
3334 } | |
3335 } | |
3336 if(def->implement_func->workerlist[aworker].value_index < 0) | |
3337 { | |
3338 printf("Error: Variable %s not found in any global stores used by worker %s\n", varname, def->name); | |
3339 DEBUGPRINTF("Error: Variable %s not found in any global stores used by worker %s\n", varname, def->name); | |
3340 execute_active = FALSE; | |
3341 return -1; | |
3342 } | |
3343 } | |
3344 else | |
3345 { | |
3346 VIS_EnterCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock); | |
3347 params[0] = add_ref(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].instance_data); | |
3348 VIS_LeaveCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock); | |
3349 params[1] = varname_dat; | |
3350 vis_dict_index(params, NULL); | |
3351 if(!params[0]) | |
3352 { | |
3353 printf("Error: Global variable %s not found in worker %s\n", def->implement_func->workerlist[aworker].name, def->name); | |
3354 DEBUGPRINTF("Error: Global variable %s not found in worker %s\n", def->implement_func->workerlist[aworker].name, def->name); | |
3355 execute_active = FALSE; | |
3356 return -1; | |
3357 } | |
3358 } | |
3359 process_outputs(params, aworker, instance); | |
3360 | |
3361 | |
3362 } | |
3363 else if(def->implement_func->workerlist[aworker].type == SET_GLOBAL) | |
3364 { | |
3365 varname = def->implement_func->workerlist[aworker].name + def->implement_func->workerlist[aworker].io_num; | |
3366 varname_dat = make_string(varname, -1, def->program); | |
3367 params[2] = params[0]; | |
3368 params[1] = varname_dat; | |
3369 VIS_EnterCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock); | |
3370 //no add_ref here because we'll be replacing instance_data with the result of vis_dict set | |
3371 params[0] = instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].instance_data; | |
3372 vis_dict_set(params, NULL); | |
3373 instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].instance_data = params[0]; | |
3374 VIS_LeaveCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock); | |
3375 //no outputs to process | |
3376 } | |
3377 else if(def->implement_func->workerlist[aworker].type == GET_COMP) | |
3378 { | |
3379 returnval = get_comp_room_by_name(params, def->implement_func->workerlist[aworker].name, NULL, &worker_entry, def->program); | |
3380 if(returnval) | |
3381 return returnval; | |
3382 process_outputs(params, aworker, instance); | |
3383 } | |
3384 else if(def->implement_func->workerlist[aworker].type == SET_COMP) | |
3385 { | |
3386 returnval = set_comp_room_by_name(params, def->implement_func->workerlist[aworker].name, NULL, &worker_entry, def->program); | |
3387 if(returnval) | |
3388 return returnval; | |
3389 process_outputs(params, aworker, instance); | |
3390 } | |
3391 else//Variable | |
3392 { | |
3393 VIS_PROFILE_START(PROF_EXECUTE_OTHER); | |
3394 if(def->implement_func->workerlist[aworker].num_inputs > 0 || def->implement_func->workerlist[aworker].type == INPUT) //Is this a Room or a constant? | |
3395 { | |
3396 todelete = NULL; | |
3397 VIS_EnterCriticalSection(instance->workerlist[aworker].worker_lock); | |
3398 if(def->implement_func->workerlist[aworker].type == OUTPUT) | |
3399 { | |
3400 todelete = instance->workerlist[aworker].value; | |
3401 instance->workerlist[aworker].value = params[0]; | |
3402 DEBUGPRINTF("Setting room/output at pos %d to %X in instance %X\n", aworker, params[0], instance); | |
3403 } | |
3404 //tempvalindex = instance->workerlist[aworker].value; | |
3405 VIS_LeaveCriticalSection(instance->workerlist[aworker].worker_lock); | |
3406 if(def->implement_func->workerlist[aworker].type == INPUT) | |
3407 { | |
3408 params[0] = instance->workerlist[aworker].value; | |
3409 instance->workerlist[aworker].value = NULL; | |
3410 } | |
3411 if(todelete) | |
3412 release_ref(todelete); | |
3413 if(def->implement_func->workerlist[aworker].num_outputs) | |
3414 { | |
3415 //add_ref(tempvalindex); | |
3416 process_outputs(params/*&tempvalindex*/, aworker, instance); | |
3417 } | |
3418 | |
3419 } | |
3420 else | |
3421 { | |
3422 //Hmm, do I potentially need another lock here? | |
3423 /*if(!(instance->def->implement_func->workerlist[aworker].value_index)) | |
3424 { | |
3425 instance->def->implement_func->workerlist[aworker].value_index = (int)(tempvalindex=get_constant(def->implement_func->workerlist[aworker].name,-1));//(int)tempvalindex; | |
3426 } | |
3427 else*/ | |
3428 tempvalindex = (datum *)instance->def->implement_func->workerlist[aworker].value_index; | |
3429 add_ref(tempvalindex); | |
3430 process_outputs(&tempvalindex, aworker, instance); | |
3431 } | |
3432 VIS_PROFILE_END(PROF_EXECUTE_OTHER); | |
3433 } | |
3434 VIS_PROFILE_END(PROF_PROCESS_WORKER); | |
3435 return returnval; | |
3436 } | |
3437 | |
3438 #define OPT_RESULT 0 | |
3439 #define OPT_CUST_RESULT 0x10000000 | |
3440 #define OPT_CONST 0x20000000 | |
3441 #define OPT_INPUT 0x30000000 | |
3442 | |
3443 int find_input_worker(custom_worker * cust, int aworker, int input, int *ret_output) | |
3444 { | |
3445 int o, p, wire_count; | |
3446 int out_worker; | |
3447 o = cust->workerlist[aworker].wire_up_lookup; | |
3448 wire_count = 0; | |
3449 while(cust->wirelist[p=cust->workers_to_wires_up[o]].end_worker == aworker && p >= 0) | |
3450 { | |
3451 if(cust->wirelist[p].input_num == input) | |
3452 { | |
3453 ++wire_count; | |
3454 out_worker = cust->wirelist[p].start_worker; | |
3455 DEBUGPRINTF("Input %d attached to %s(%d)\n", input, cust->workerlist[out_worker].name, out_worker); | |
3456 if(ret_output) | |
3457 *ret_output = cust->wirelist[p].output_num; | |
3458 } | |
3459 ++o; | |
3460 } | |
3461 DEBUGPRINTF("wire_count: %d\n", wire_count); | |
3462 if(wire_count == 1) | |
3463 return out_worker; | |
3464 return -1; | |
3465 } | |
3466 | |
3467 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) | |
3468 { | |
3469 /*if(in_opt[source_worker]) | |
3470 { | |
3471 if(prog->deflist[cust->workerlist[source_worker].value_index].type & USER_FLAG) | |
3472 { | |
3473 return OPT_CUST_RESULT | ((pos_in_opt[source_worker] & 0xFFFF) << 8) | (output_num & 0xFF); | |
3474 } | |
3475 else | |
3476 { | |
3477 if(strcmp(prog->deflist[cust->workerlist[source_worker].value_index].name, "If") == 0) | |
3478 { | |
3479 if(output_num == 0) | |
3480 { | |
3481 branch_flags[index] = 1; | |
3482 if(opts[pos_in_opt[source_worker]].branch1 <= index) | |
3483 opts[pos_in_opt[source_worker]].branch1 = index+1; | |
3484 } | |
3485 else | |
3486 { | |
3487 branch_flags[index] = 2; | |
3488 if(opts[pos_in_opt[source_worker]].branch2 <= index) | |
3489 opts[pos_in_opt[source_worker]].branch2 = index+1; | |
3490 } | |
3491 branch_refs[index] = opts + pos_in_opt[source_worker]; | |
3492 } | |
3493 else if(branch_flags[pos_in_opt[source_worker]]) | |
3494 { | |
3495 if(branch_flags[pos_in_opt[source_worker]] == 1) | |
3496 { | |
3497 branch_refs[pos_in_opt[source_worker]]->branch1 = index + 1; | |
3498 branch_flags[index] = 1; | |
3499 } | |
3500 else | |
3501 { | |
3502 branch_refs[pos_in_opt[source_worker]]->branch1 = index + 2; | |
3503 branch_flags[index] = 2; | |
3504 } | |
3505 branch_refs[index] = branch_refs[pos_in_opt[source_worker]]; | |
3506 } | |
3507 else | |
3508 branch_flags[index] = 0; | |
3509 if(input_num >= 0) | |
3510 ++opts[pos_in_opt[source_worker]].output_refs[output_num]; | |
3511 DEBUGPRINTF("OPT_RESULT: opt_num: %d, output_num: %d\n", pos_in_opt[source_worker], output_num); | |
3512 return OPT_RESULT | ((pos_in_opt[source_worker] & 0xFFFF) << 8) | (output_num & 0xFF); | |
3513 } | |
3514 } | |
3515 else if(cust->workerlist[source_worker].type == CONSTANT) | |
3516 { | |
3517 branch_flags[index] = 0; | |
3518 DEBUGPRINTF("OPT_CONST: %d\n", source_worker); | |
3519 return OPT_CONST | source_worker; | |
3520 } | |
3521 else if(cust->workerlist[source_worker].type == INPUT) | |
3522 { | |
3523 branch_flags[index] = 0; | |
3524 DEBUGPRINTF("OPT_INPUT: %d\n", cust->workerlist[source_worker].io_num); | |
3525 return OPT_INPUT | cust->workerlist[source_worker].io_num; | |
3526 }*/ | |
3527 return -1; | |
3528 } | |
3529 | |
3530 void optimize(worker_def * def) | |
3531 { | |
3532 /* | |
3533 int i,j,k,m,o,p; | |
3534 int * const_in; | |
3535 int num_entries = 0; | |
3536 int aworker; | |
3537 int adjust; | |
3538 int source_worker; | |
3539 int source_output; | |
3540 int source_null; | |
3541 int null_output; | |
3542 int wire_count; | |
3543 int * input_data; | |
3544 int current_null; | |
3545 int cust_result_count; | |
3546 int new_start; | |
3547 custom_worker * cust = def->implement_func; | |
3548 int start_current, end_current, new_current; | |
3549 worker_def * deflist = def->program->deflist; | |
3550 opt_entry * output = malloc(sizeof(opt_entry) * def->implement_func->num_workers); | |
3551 BOOL * in_opt = malloc(sizeof(BOOL) * cust->num_workers); | |
3552 int * branch_flags = malloc(sizeof(int) * cust->num_workers); | |
3553 opt_entry ** branch_refs = malloc(sizeof(int) * cust->num_workers); | |
3554 //BOOL * real_in_opt = malloc(sizeof(BOOL) * cust->num_workers); | |
3555 int * pos_in_opt = malloc(sizeof(int) * cust->num_workers); | |
3556 DEBUGPRINTF("deflist: %X\n", deflist); | |
3557 for(i = 0; i < cust->num_workers; ++i) | |
3558 { | |
3559 branch_flags[i] = 0; | |
3560 DEBUGPRINTF("%d: No input pass\n", i); | |
3561 DEBUGPRINTF("Examining: %s\n", cust->workerlist[i].name); | |
3562 if(cust->workerlist[i].num_inputs == 0 && !cust->workerlist[i].null_input && cust->workerlist[i].type == WORKER) | |
3563 { | |
3564 output[num_entries].def = deflist + cust->workerlist[i].value_index; | |
3565 DEBUGPRINTF("Set output[%d].def = %X\n", num_entries, output[num_entries].def); | |
3566 DEBUGPRINTF("opt: %d is %s\n\n", num_entries, cust->workerlist[i].name); | |
3567 output[num_entries].original_pos = i; | |
3568 output[num_entries].input_data = NULL; | |
3569 if(cust->workerlist[i].num_outputs) | |
3570 { | |
3571 output[num_entries].output_refs = malloc(sizeof(int)*cust->workerlist[i].num_outputs); | |
3572 for(j = 0; j < cust->workerlist[i].num_outputs; ++j) | |
3573 output[num_entries].output_refs[j] = 0; | |
3574 } | |
3575 else | |
3576 output[num_entries].output_refs = NULL; | |
3577 output[num_entries].branch1 = output[num_entries].branch2 = -1; | |
3578 //if(!(deflist[cust->workerlist[i].value_index].type & USER_FLAG)) | |
3579 //{ | |
3580 in_opt[i] = TRUE; | |
3581 pos_in_opt[i] = num_entries; | |
3582 //} | |
3583 //real_in_opt[i] = TRUE; | |
3584 ++num_entries; | |
3585 } | |
3586 else | |
3587 { | |
3588 //real_in_opt[i] = FALSE; | |
3589 in_opt[i] = FALSE; | |
3590 } | |
3591 } | |
3592 start_current = num_entries; | |
3593 for(i = 0; i < cust->num_workers; ++i) | |
3594 { | |
3595 DEBUGPRINTF("%d: Second pass\n", i); | |
3596 if(cust->workerlist[i].num_inputs == 0 && !cust->workerlist[i].null_input) | |
3597 { | |
3598 j = cust->workerlist[i].wire_down_lookup; | |
3599 while(cust->wirelist[k=cust->workers_to_wires_down[j]].start_worker == i && k >= 0) | |
3600 { | |
3601 aworker = cust->wirelist[k].end_worker; | |
3602 if(!in_opt[aworker]) | |
3603 { | |
3604 DEBUGPRINTF("Examining: %s(%d)\n", cust->workerlist[aworker].name, aworker); | |
3605 if(cust->workerlist[i].null_input) | |
3606 adjust = 1; | |
3607 else | |
3608 adjust = 0; | |
3609 input_data = malloc(sizeof(int)* (cust->workerlist[aworker].num_inputs+adjust)); | |
3610 for(m = (0-adjust); m < cust->workerlist[aworker].num_inputs; ++m) | |
3611 { | |
3612 DEBUGPRINTF("Input: %d\n", m); | |
3613 source_worker = find_input_worker(cust, aworker, m, &source_output); | |
3614 DEBUGPRINTF("source_worker: %d\n", source_worker); | |
3615 if(source_worker == -1) | |
3616 break; | |
3617 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); | |
3618 DEBUGPRINTF("input code: %X\n", source_worker); | |
3619 if(source_worker == -1) | |
3620 break; | |
3621 input_data[m+adjust] = source_worker; | |
3622 if(source_worker == -1) | |
3623 break; | |
3624 } | |
3625 if(source_worker == -1) | |
3626 free(input_data); | |
3627 else | |
3628 { | |
3629 if(cust->workerlist[aworker].type == OUTPUT) | |
3630 output[num_entries].def = NULL; | |
3631 else | |
3632 output[num_entries].def = deflist + cust->workerlist[aworker].value_index; | |
3633 DEBUGPRINTF("Set output[%d].def = %X\n", num_entries, output[num_entries].def); | |
3634 DEBUGPRINTF("opt: %d is %s\n\n", num_entries, cust->workerlist[aworker].name); | |
3635 output[num_entries].original_pos = aworker; | |
3636 output[num_entries].input_data = input_data; | |
3637 output[num_entries].null_inputs = adjust; | |
3638 output[num_entries].branch1 = output[num_entries].branch2 = -1; | |
3639 if(cust->workerlist[aworker].num_outputs) | |
3640 { | |
3641 output[num_entries].output_refs = malloc(sizeof(int)*cust->workerlist[aworker].num_outputs); | |
3642 for(m = 0; m < cust->workerlist[aworker].num_outputs; ++m) | |
3643 output[num_entries].output_refs[m] = 0; | |
3644 } | |
3645 else | |
3646 output[num_entries].output_refs = NULL; | |
3647 //if(cust->workerlist[aworker].type != OUTPUT && !(deflist[cust->workerlist[aworker].value_index].type & USER_FLAG)) | |
3648 //{ | |
3649 in_opt[aworker] = TRUE; | |
3650 pos_in_opt[aworker] = num_entries; | |
3651 //} | |
3652 //real_in_opt[aworker] = TRUE; | |
3653 ++num_entries; | |
3654 | |
3655 } | |
3656 } | |
3657 ++j; | |
3658 } | |
3659 } | |
3660 } | |
3661 DEBUGPUTS("Before While\n"); | |
3662 end_current = num_entries; | |
3663 while(start_current != end_current) | |
3664 { | |
3665 DEBUGPRINTF("start_current: %d, end_current: %d\n", start_current, end_current); | |
3666 new_start = num_entries; | |
3667 for(i = start_current; i < end_current; ++i) | |
3668 { | |
3669 DEBUGPRINTF("opt: %d, def: %X, name: %s\n", i, output[i].def, cust->workerlist[output[i].original_pos].name); | |
3670 j = cust->workerlist[output[i].original_pos].wire_down_lookup; | |
3671 DEBUGPRINTF("wire_down_lookup: %d\n", j); | |
3672 while(cust->wirelist[k=cust->workers_to_wires_down[j]].start_worker == output[i].original_pos && k >= 0) | |
3673 { | |
3674 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); | |
3675 aworker = cust->wirelist[k].end_worker; | |
3676 //FIXME: Only works if constant/input attached to only one destination | |
3677 if(cust->workerlist[aworker].type == CONSTANT || cust->workerlist[aworker].type == INPUT) | |
3678 { | |
3679 DEBUGPRINTF("Worker is of type %d, ", cust->workerlist[aworker].type); | |
3680 aworker = cust->wirelist[cust->workers_to_wires_down[cust->workerlist[aworker].wire_down_lookup]].end_worker; | |
3681 DEBUGPRINTF("reruting to worker %d\n", aworker); | |
3682 } | |
3683 if(!in_opt[aworker]) | |
3684 { | |
3685 DEBUGPRINTF("Examining: %s(%d)\n", cust->workerlist[aworker].name, aworker); | |
3686 if(cust->workerlist[i].null_input) | |
3687 adjust = 1; | |
3688 else | |
3689 adjust = 0; | |
3690 for(m = (0-adjust); m < cust->workerlist[aworker].num_inputs; ++m) | |
3691 { | |
3692 source_worker = find_input_worker(cust, aworker, m, &source_output); | |
3693 if(source_worker == -1) | |
3694 break; | |
3695 if(cust->workerlist[source_worker].null_input && cust->workerlist[source_worker].type != WORKER) | |
3696 ++adjust; | |
3697 } | |
3698 if(source_worker != -1) | |
3699 { | |
3700 current_null = 0; | |
3701 input_data = malloc(sizeof(int)* (cust->workerlist[aworker].num_inputs+adjust)); | |
3702 cust_result_count = 0; | |
3703 for(m = (cust->workerlist[i].null_input ? -1 : 0); m < cust->workerlist[aworker].num_inputs; ++m) | |
3704 { | |
3705 DEBUGPRINTF("Input: %d\n", m); | |
3706 source_worker = find_input_worker(cust, aworker, m, &source_output); | |
3707 if(cust->workerlist[source_worker].null_input && cust->workerlist[source_worker].type != WORKER) | |
3708 { | |
3709 source_null = find_input_worker(cust, source_worker, -1, &null_output); | |
3710 if(source_null == -1) | |
3711 { | |
3712 source_worker = -1; | |
3713 break; | |
3714 } | |
3715 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); | |
3716 if((source_null & 0xF0000000) == OPT_CUST_RESULT) | |
3717 ++cust_result_count; | |
3718 if(source_null == -1) | |
3719 { | |
3720 source_worker = -1; | |
3721 break; | |
3722 } | |
3723 input_data[current_null++] = source_null; | |
3724 } | |
3725 DEBUGPRINTF("source_worker: %d\n", source_worker); | |
3726 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); | |
3727 if((source_worker & 0xF0000000) == OPT_CUST_RESULT) | |
3728 ++cust_result_count; | |
3729 DEBUGPRINTF("input code: %d\n", source_worker); | |
3730 if(cust_result_count >= (cust->workerlist[aworker].num_inputs + adjust)) | |
3731 source_worker = -1; | |
3732 if(source_worker == -1) | |
3733 break; | |
3734 input_data[m+adjust] = source_worker; | |
3735 } | |
3736 if(source_worker == -1) | |
3737 free(input_data); | |
3738 else | |
3739 { | |
3740 if(cust->workerlist[aworker].type == OUTPUT) | |
3741 output[num_entries].def = NULL; | |
3742 else | |
3743 output[num_entries].def = deflist + cust->workerlist[aworker].value_index; | |
3744 DEBUGPRINTF("Set output[%d].def = %X\n", num_entries, output[num_entries].def); | |
3745 DEBUGPRINTF("opt: %d is %s\n\n", num_entries, cust->workerlist[aworker].name); | |
3746 output[num_entries].original_pos = aworker; | |
3747 output[num_entries].input_data = input_data; | |
3748 output[num_entries].null_inputs = adjust; | |
3749 output[num_entries].branch1 = output[num_entries].branch2 = -1; | |
3750 if(cust->workerlist[aworker].num_outputs) | |
3751 { | |
3752 output[num_entries].output_refs = malloc(sizeof(int)*cust->workerlist[aworker].num_outputs); | |
3753 for(m = 0; m < cust->workerlist[aworker].num_outputs; ++m) | |
3754 output[num_entries].output_refs[m] = 0; | |
3755 } | |
3756 else | |
3757 output[num_entries].output_refs = NULL; | |
3758 //if(cust->workerlist[aworker].type != OUTPUT && !(deflist[cust->workerlist[aworker].value_index].type & USER_FLAG)) | |
3759 //{ | |
3760 in_opt[aworker] = TRUE; | |
3761 pos_in_opt[aworker] = num_entries; | |
3762 //} | |
3763 //real_in_opt[aworker] = TRUE; | |
3764 ++num_entries; | |
3765 | |
3766 } | |
3767 } | |
3768 } | |
3769 ++j; | |
3770 } | |
3771 } | |
3772 start_current = new_start; | |
3773 end_current = num_entries; | |
3774 } | |
3775 def->optimized = output; | |
3776 def->opt_count = num_entries; | |
3777 DEBUGPUTS("optimize done\n\n\n"); | |
3778 */ | |
3779 } | |
3780 | |
3781 | |
3782 void run_optimized(worker_instance * instance, datum ** params) | |
3783 { | |
3784 int i = 0,j,k; | |
3785 unsigned short output, opt_num; | |
3786 datum * this_params[32]; | |
3787 queue_entry entry; | |
3788 datum * val; | |
3789 BOOL skip; | |
3790 BOOL partial_flag; | |
3791 BOOL continue_flag; | |
3792 int count; | |
3793 int ready; | |
3794 int jump_from = -1; | |
3795 int jump_to = -1; | |
3796 int tmp, addnum; | |
3797 opt_entry * exec_list = instance->def->optimized; | |
3798 datum ** results = instance->opt_results;//malloc(sizeof(datum *) * instance->def->opt_count * 32); | |
3799 VIS_PROFILE_START(PROF_RUN_OPT); | |
3800 entry.instance = instance; | |
3801 for(i = 0; i < instance->def->opt_count; ++i) | |
3802 { | |
3803 VIS_PROFILE_START(PROF_OPT_LOOP); | |
3804 skip = FALSE; | |
3805 partial_flag = FALSE; | |
3806 continue_flag = FALSE; | |
3807 DEBUGPRINTF("\nPeparing exec_list[%d]\n", i); | |
3808 if(exec_list[i].def) | |
3809 { | |
3810 DEBUGPRINTF("Name: %s\n", exec_list[i].def->name); | |
3811 count = exec_list[i].def->num_inputs; | |
3812 } | |
3813 else | |
3814 count = 1; | |
3815 count += exec_list[i].null_inputs; | |
3816 //DEBUGPRINTF("Input count: %d\n", count); | |
3817 if(count && !exec_list[i].input_data) | |
3818 puts("Runtime Error: input data is NULL\n"); | |
3819 //DEBUGPRINTF("input_data: %X\n", exec_list[i].input_data); | |
3820 VIS_PROFILE_START(PROF_OPT_PREP_INPUT); | |
3821 for(j = 0; j < count; ++j) | |
3822 { | |
3823 val = NULL; | |
3824 continue_flag = FALSE; | |
3825 switch(exec_list[i].input_data[j] & 0xF0000000) | |
3826 { | |
3827 case OPT_RESULT: | |
3828 output = exec_list[i].input_data[j] & 0xFF; | |
3829 opt_num = (exec_list[i].input_data[j] >> 8)& 0xFFFF; | |
3830 DEBUGPRINTF("OPT_RESULT for input %d, opt_num: %d, output: %d\n", j, opt_num, output); | |
3831 val = results[(opt_num * 32) | output]; | |
3832 break; | |
3833 case OPT_CUST_RESULT: | |
3834 val = NULL; | |
3835 partial_flag = TRUE; | |
3836 continue_flag = TRUE; | |
3837 break; | |
3838 case OPT_INPUT: | |
3839 DEBUGPRINTF("OPT_INPUT for input %d\n", j); | |
3840 val = add_ref(params[exec_list[i].input_data[j] & 0xFF]); | |
3841 break; | |
3842 case OPT_CONST: | |
3843 DEBUGPRINTF("OPT_CONST for input %d\n", j); | |
3844 val = add_ref((datum *)(instance->def->implement_func->workerlist[exec_list[i].input_data[j] & 0xFFFFFF].value_index)); | |
3845 break; | |
3846 default: | |
3847 puts("Runtime Error: Invalid bytecode\n"); | |
3848 val = NULL; | |
3849 break; | |
3850 } | |
3851 if(!val && !continue_flag) | |
3852 { | |
3853 for(k = exec_list[i].null_inputs; k < j; ++k) | |
3854 release_ref(this_params[k]); | |
3855 skip = TRUE; | |
3856 break; | |
3857 } | |
3858 DEBUGPRINTF("this_params[%d] = %X\n", j, val); | |
3859 if(j >= exec_list[i].null_inputs) | |
3860 if(val) | |
3861 this_params[j] = /*add_ref(*/val/*)*/; | |
3862 else | |
3863 this_params[j] = NULL; | |
3864 | |
3865 } | |
3866 VIS_PROFILE_END(PROF_OPT_PREP_INPUT); | |
3867 if(!skip) | |
3868 { | |
3869 if(partial_flag) | |
3870 { | |
3871 VIS_PROFILE_START(PROF_PARTIAL_EXEC); | |
3872 ready = 0; | |
3873 for(j = exec_list[i].null_inputs; j < count; ++j) | |
3874 if(this_params[j]) | |
3875 { | |
3876 instance->workerlist[exec_list[i].original_pos].params[j-exec_list[i].null_inputs+1] = this_params[j]; | |
3877 ++ready; | |
3878 } | |
3879 if(instance->def->implement_func->workerlist[exec_list[i].original_pos].null_input && this_params[exec_list[i].null_inputs-1]) | |
3880 ++ready; | |
3881 DEBUGPRINTF("ready: %d\n", ready); | |
3882 skip = TRUE; | |
3883 VIS_EnterCriticalSection(instance->workerlist[exec_list[i].original_pos].worker_lock); | |
3884 instance->workerlist[exec_list[i].original_pos].ready_count += ready; | |
3885 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))) | |
3886 { | |
3887 skip = FALSE; | |
3888 instance->workerlist[exec_list[i].original_pos].ready_count = 0; | |
3889 | |
3890 } | |
3891 DEBUGPRINTF("ready_count: %d\n", instance->workerlist[exec_list[i].original_pos].ready_count); | |
3892 VIS_LeaveCriticalSection(instance->workerlist[exec_list[i].original_pos].worker_lock); | |
3893 if(!skip) | |
3894 add_queue(exec_list[i].original_pos, instance); | |
3895 VIS_PROFILE_END(PROF_PARTIAL_EXEC); | |
3896 } | |
3897 else if(exec_list[i].def) | |
3898 { | |
3899 VIS_PROFILE_START(PROF_FULL_EXEC); | |
3900 DEBUGPRINTF("opt_exec: %s(%d)\n", exec_list[i].def->name, exec_list[i].original_pos); | |
3901 entry.worker_num = exec_list[i].original_pos; | |
3902 if(exec_list[i].def->type & USER_FLAG) | |
3903 { | |
3904 VIS_PROFILE_START(PROF_OPT_EXEC_USER); | |
3905 instance->workerlist[exec_list[i].original_pos].params[0] = NULL; | |
3906 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); | |
3907 add_queue(exec_list[i].original_pos, instance); | |
3908 VIS_PROFILE_END(PROF_OPT_EXEC_USER); | |
3909 } | |
3910 else | |
3911 { | |
3912 VIS_PROFILE_START(PROF_OPT_EXEC_BUILT); | |
3913 if(execute_def(exec_list[i].def, entry, this_params + exec_list[i].null_inputs, sub_callback) == 0) | |
3914 { | |
3915 DEBUGPUTS("Exectuted with reslts\n"); | |
3916 if(exec_list[i].output_refs) | |
3917 { | |
3918 for(j = exec_list[i].null_inputs; j < (exec_list[i].def->num_outputs+exec_list[i].null_inputs); ++j) | |
3919 { | |
3920 DEBUGPRINTF("output_refs[%d] = %d\n", j-exec_list[i].null_inputs, exec_list[i].output_refs[j-exec_list[i].null_inputs]); | |
3921 if(!exec_list[i].output_refs[j-exec_list[i].null_inputs]) | |
3922 release_ref(this_params[j]); | |
3923 else if(exec_list[i].output_refs[j-exec_list[i].null_inputs] > 1) | |
3924 { | |
3925 /*DEBUGPRINTF("multi_add_ref(%X): %d\n", this_params[j], exec_list[i].output_refs[j-exec_list[i].null_inputs]-1); | |
3926 tmp = (int)(&(this_params[j]->ref_count)); | |
3927 addnum = exec_list[i].output_refs[j-exec_list[i].null_inputs]-1; | |
3928 __asm | |
3929 { | |
3930 mov ebx, tmp | |
3931 mov eax, addnum | |
3932 lock xadd dword ptr [ebx], eax | |
3933 }*/ | |
3934 VIS_EnterCriticalSection(this_params[j]->lock); | |
3935 this_params[j]->ref_count += exec_list[i].output_refs[j-exec_list[i].null_inputs]-1; | |
3936 | |
3937 VIS_LeaveCriticalSection(this_params[j]->lock); | |
3938 } | |
3939 } | |
3940 memcpy(results + i*32, this_params + exec_list[i].null_inputs, sizeof(datum *) * exec_list[i].def->num_outputs); | |
3941 if(exec_list[i].branch1 >= 0) | |
3942 { | |
3943 if(this_params[exec_list[i].null_inputs]) | |
3944 { | |
3945 jump_from = exec_list[i].branch1; | |
3946 jump_to = exec_list[i].branch2; | |
3947 } | |
3948 else | |
3949 { | |
3950 i = exec_list[i].branch1-1; | |
3951 } | |
3952 } | |
3953 } | |
3954 } | |
3955 /*else | |
3956 { | |
3957 for(j = exec_list[i].null_inputs; j < (exec_list[i].def->num_outputs + exec_list[i].null_inputs); ++j) | |
3958 results[(i*32)|j] = NULL; | |
3959 }*/ | |
3960 VIS_PROFILE_END(PROF_OPT_EXEC_BUILT); | |
3961 } | |
3962 VIS_PROFILE_END(PROF_FULL_EXEC); | |
3963 DEBUGPUTS("Executed\n"); | |
3964 } | |
3965 else | |
3966 instance->workerlist[exec_list[i].original_pos].value = this_params[exec_list[i].null_inputs]; | |
3967 } | |
3968 else | |
3969 { | |
3970 DEBUGPUTS("Skipped\n"); | |
3971 if(exec_list[i].def) | |
3972 { | |
3973 for(j = 0; j < exec_list[i].def->num_outputs; ++j) | |
3974 results[(i*32)|j] = NULL; | |
3975 } | |
3976 } | |
3977 if(jump_from >= 0 && (i+1) == jump_from) | |
3978 { | |
3979 i = jump_to-1; | |
3980 jump_from = -1; | |
3981 } | |
3982 VIS_PROFILE_END(PROF_OPT_LOOP); | |
3983 } | |
3984 DEBUGPUTS("run_optimized calling cleanup_check\n"); | |
3985 for(i = 0; i < instance->def->num_inputs; ++i) | |
3986 release_ref(params[i]); | |
3987 cleanup_check(entry); | |
3988 VIS_PROFILE_END(PROF_RUN_OPT); | |
3989 } | |
3990 | |
3991 int vis_print(datum ** inputlist, queue_entry * worker_entry) | |
3992 { | |
3993 int result; | |
3994 #ifdef CONSOLE | |
3995 puts((char *)inputlist[0]->c.generic.data); | |
3996 #else | |
3997 MessageBox(NULL, (char *)inputlist[0]->c.generic.data, "Visuality Output", MB_OK); | |
3998 #endif | |
3999 result = 1; | |
4000 | |
4001 release_ref(inputlist[0]); | |
4002 inputlist[0] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program); | |
4003 //No one else knows about this new datum yet so we can skip getting a lock | |
4004 datum_set_yesno(inputlist[0], result); | |
4005 return 0; | |
4006 } | |
4007 | |
31
fab5bb137cf9
Added Unix Time worker to interpreter
Mike Pavone <pavone@retrodev.com>
parents:
29
diff
changeset
|
4008 int unix_time(datum ** inputlist, queue_entry * worker_entry) |
fab5bb137cf9
Added Unix Time worker to interpreter
Mike Pavone <pavone@retrodev.com>
parents:
29
diff
changeset
|
4009 { |
fab5bb137cf9
Added Unix Time worker to interpreter
Mike Pavone <pavone@retrodev.com>
parents:
29
diff
changeset
|
4010 inputlist[0] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); |
fab5bb137cf9
Added Unix Time worker to interpreter
Mike Pavone <pavone@retrodev.com>
parents:
29
diff
changeset
|
4011 inputlist[0]->c.integers.num_a = time(NULL); |
fab5bb137cf9
Added Unix Time worker to interpreter
Mike Pavone <pavone@retrodev.com>
parents:
29
diff
changeset
|
4012 return 0; |
fab5bb137cf9
Added Unix Time worker to interpreter
Mike Pavone <pavone@retrodev.com>
parents:
29
diff
changeset
|
4013 } |
fab5bb137cf9
Added Unix Time worker to interpreter
Mike Pavone <pavone@retrodev.com>
parents:
29
diff
changeset
|
4014 |
0 | 4015 int vis_end(datum ** inputlist, queue_entry * worker_entry) |
4016 { | |
4017 // fprintf(outfile, "End worker reached.\n"); | |
4018 execute_active=FALSE; | |
4019 release_ref(inputlist[0]); | |
4020 //interp_stop(); | |
4021 return 0; | |
4022 } | |
4023 | |
4024 #ifdef NINTENDO_DS | |
4025 const char keyLetters[15] = "ABESRLUD><XYMC"; | |
4026 #define MAX_KEY_BITS 14 | |
4027 #endif | |
4028 | |
4029 int vis_getinput(datum ** inputlist, queue_entry * worker_entry) | |
4030 { | |
4031 #ifdef NINTENDO_DS | |
4032 int held,i,pos; | |
4033 char tempstring[14]; | |
4034 scanKeys(); | |
4035 held = keysHeld(); | |
4036 if(held) | |
4037 { | |
4038 pos = 0; | |
4039 for(i = 0; i < MAX_KEY_BITS; ++i) | |
4040 if(held & (1 << i)) | |
4041 tempstring[pos++] = keyLetters[i]; | |
4042 inputlist[0] = new_datum(BUILTIN_TYPE_STRING, 1, pos+1, worker_entry->instance->def->program); | |
4043 memcpy(inputlist[0]->c.generic.data, tempstring, pos); | |
4044 ((char *)inputlist[0]->c.generic.data)[pos]='\0'; | |
4045 return 0; | |
4046 } | |
4047 else | |
4048 { | |
4049 requeue(worker_entry->worker_num, worker_entry->instance); | |
4050 return 1; | |
4051 } | |
4052 #else | |
4053 #ifdef CONSOLE | |
4054 gets(text_buf); | |
4055 text_buf_size = strlen(text_buf); | |
4056 //Nasty hack for testing until I get around to supporting command line args propery | |
4057 //text_buf_size = strlen(global_argv[1]); | |
4058 #else | |
4059 | |
4060 while(text_buf_size <= 0) | |
4061 { | |
4062 Sleep(30); //TODO: replace with I/O queue mechanism | |
4063 } | |
4064 #endif | |
4065 // VIS_EnterCriticalSection(text_buf_lock); | |
4066 DEBUGPRINTF("Allocating %d bytes\n", text_buf_size+1); | |
4067 inputlist[0] = new_datum(BUILTIN_TYPE_STRING, 1, text_buf_size+1, worker_entry->instance->def->program); | |
4068 DEBUGPUTS("Allocated datum.\n"); | |
4069 memcpy(inputlist[0]->c.generic.data, text_buf, text_buf_size); | |
4070 DEBUGPUTS("Copied string.\n"); | |
4071 ((char *)inputlist[0]->c.generic.data)[text_buf_size]='\0'; | |
4072 DEBUGPRINTF("Input is %s\n", inputlist[0]->c.generic.data); | |
4073 text_buf_size = 0; | |
4074 // VIS_LeaveCriticalSection(text_buf_lock); | |
4075 return 0; | |
4076 #endif | |
4077 } | |
4078 | |
4079 int vis_if(datum ** inputlist, queue_entry * worker_entry) | |
4080 { | |
4081 if(!(inputlist[0]->c.integers.num_a)) | |
4082 { | |
4083 inputlist[1] = inputlist[0]; | |
4084 inputlist[0] = NULL; | |
4085 } | |
4086 else | |
4087 inputlist[1] = NULL; | |
4088 return 0; | |
4089 } | |
4090 | |
4091 int vis_build(datum ** inputlist, queue_entry * worker_entry) | |
4092 { | |
4093 int i,j; | |
4094 company * companylist = worker_entry->instance->def->program->companylist; | |
4095 int num_companies = worker_entry->instance->def->program->num_companies; | |
4096 DEBUGPRINTF("Looking for company named %s\n", inputlist[0]->c.generic.data); | |
4097 for(i = 0; i < num_companies; ++i) | |
4098 { | |
4099 DEBUGPRINTF("Checking company %d:%s\n", i, companylist[i].name); | |
4100 if(!strcmp(inputlist[0]->c.generic.data, companylist[i].name)) | |
4101 break; | |
4102 } | |
4103 release_ref(inputlist[0]); | |
4104 if(i < num_companies && companylist[i].build_size > 0) | |
4105 { | |
4106 DEBUGPRINTF("Building company with size %d\n", companylist[i].build_size); | |
4107 inputlist[0] = new_datum(i, 1, companylist[i].build_size, worker_entry->instance->def->program); | |
4108 for(j = 0; j < companylist[i].build_size; ++j) | |
4109 ((char*)(inputlist[0]->c.generic.data))[j] = 0; | |
4110 } | |
4111 else | |
4112 { | |
4113 DEBUGPUTS("Could not find company\n"); | |
4114 inputlist[0] = NULL; | |
4115 } | |
4116 return 0; | |
4117 } | |
4118 | |
4119 int vis_wait_forever(datum ** inputlist, queue_entry * worker_entry) | |
4120 { | |
4121 return 1; | |
4122 } | |
4123 | |
4124 int init_global_store(datum ** inputlist, queue_entry * worker_entry) | |
4125 { | |
4126 datum * params[3]; | |
4127 global_store * store; | |
4128 datum * store_dat = new_datum(BUILTIN_TYPE_GLOBAL_STORE, 1, sizeof(global_store), worker_entry->instance->def->program); | |
4129 store = store_dat->c.generic.data; | |
4130 store->name = add_ref(inputlist[0]); | |
4131 store->data = create_dict(worker_entry->instance->def->program); | |
4132 VIS_EnterCriticalSection(global_store_lock); | |
4133 params[0] = global_store_dict; | |
4134 params[1] = inputlist[0]; | |
4135 params[2] = store_dat; | |
4136 vis_dict_set(params, NULL); | |
4137 global_store_dict = params[0]; | |
4138 DEBUGPUTS("Global store init complete\n"); | |
4139 VIS_LeaveCriticalSection(global_store_lock); | |
4140 DEBUGPUTS("Released global_store_lock\n"); | |
4141 inputlist[0] = NULL; | |
4142 return 0; | |
4143 } | |
4144 | |
4145 int vis_type_of(datum ** inputlist, queue_entry * worker_entry) | |
4146 { | |
4147 datum * output = make_string(inputlist[0]->company->name, -1, worker_entry->instance->def->program); | |
4148 release_ref(inputlist[0]); | |
4149 inputlist[0] = output; | |
4150 return 0; | |
4151 } | |
4152 | |
4153 int vis_random(datum ** inputlist, queue_entry * worker_entry) | |
4154 { | |
4155 inputlist[0] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); | |
4156 VIS_EnterCriticalSection(randlock); | |
4157 inputlist[0]->c.integers.num_a = genrand_int32(); | |
4158 VIS_LeaveCriticalSection(randlock); | |
4159 return 0; | |
4160 } |