Mercurial > repos > rhope
comparison interp.c @ 0:76568becd6d6
Rhope Alpha 2a source import
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 28 Apr 2009 23:06:07 +0000 |
parents | |
children | 23dd9c766699 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:76568becd6d6 |
---|---|
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); | |
1001 #ifdef SYLLABLE | |
1002 DEBUGPUTS("vis_window_init\n"); | |
1003 vis_window_init(); | |
1004 #endif | |
1005 VIS_CreateEvent(queue_add_event);//No security parameter, auto reset, starts signaled, no name | |
1006 | |
1007 } | |
1008 | |
1009 void close_sync_primitives() | |
1010 { | |
1011 int i; | |
1012 VIS_DeleteCriticalSection(data_lock); | |
1013 VIS_DeleteCriticalSection(worker_queue_lock); | |
1014 VIS_DestroyEvent(queue_add_event); | |
1015 | |
1016 } | |
1017 | |
1018 void init_global_storage(program * prog) | |
1019 { | |
1020 VIS_InitializeCriticalSection(global_store_lock); | |
1021 global_store_dict = create_dict(prog); | |
1022 } | |
1023 | |
1024 void add_multiple(int * data, int num, worker_instance * instance) | |
1025 { | |
1026 int i, index; | |
1027 queue_section * temp; | |
1028 DEBUGPRINTF( "Adding %d workers\n", num); | |
1029 | |
1030 VIS_EnterCriticalSection(instance->counter_lock); | |
1031 instance->in_queue_count += num; | |
1032 VIS_LeaveCriticalSection(instance->counter_lock); | |
1033 VIS_EnterCriticalSection(worker_queue_lock); | |
1034 for(i = 0; i < num; ++i) | |
1035 { | |
1036 if(queue_len >= QUEUE_SIZE) | |
1037 { | |
1038 if(current_section->next) | |
1039 { | |
1040 //DEBUGPUTS("Moving to next queue_section\n"); | |
1041 current_section = current_section->next; | |
1042 } | |
1043 else | |
1044 { | |
1045 //DEBUGPUTS("Allocating new queue_section\n"); | |
1046 VIS_PROFILE_START(PROF_ADDQUEUE_MALLOC); | |
1047 temp = MALLOC(sizeof(queue_section),"queue section"); | |
1048 VIS_PROFILE_END(PROF_ADDQUEUE_MALLOC); | |
1049 temp->last = current_section; | |
1050 temp->next = NULL; | |
1051 current_section->next = temp; | |
1052 current_section = temp; | |
1053 } | |
1054 worker_queue = current_section->entries; | |
1055 queue_start = queue_len = 0; | |
1056 } | |
1057 if(queue_start+queue_len < QUEUE_SIZE) | |
1058 index = queue_start+queue_len; | |
1059 else | |
1060 index = queue_start+queue_len-QUEUE_SIZE; | |
1061 worker_queue[index].worker_num=data[i]; | |
1062 worker_queue[index].instance = instance; | |
1063 ++queue_len; | |
1064 } | |
1065 VIS_LeaveCriticalSection(worker_queue_lock); | |
1066 //DEBUGPUTS("SetEvent\n"); | |
1067 VIS_SetEvent(queue_add_event); | |
1068 } | |
1069 | |
1070 void requeue(int data, worker_instance * instance) | |
1071 { | |
1072 add_queue(data, instance); | |
1073 VIS_EnterCriticalSection(instance->counter_lock); | |
1074 --(instance->in_progress_count); | |
1075 VIS_LeaveCriticalSection(instance->counter_lock); | |
1076 } | |
1077 | |
1078 void add_queue(int data, worker_instance * instance) | |
1079 { | |
1080 int index; | |
1081 queue_section * temp; | |
1082 VIS_PROFILE_START(PROF_ADDQUEUE); | |
1083 VIS_EnterCriticalSection(instance->counter_lock); | |
1084 ++(instance->in_queue_count); | |
1085 VIS_LeaveCriticalSection(instance->counter_lock); | |
1086 VIS_EnterCriticalSection(worker_queue_lock); | |
1087 if(queue_len >= QUEUE_SIZE) | |
1088 { | |
1089 if(current_section->next) | |
1090 { | |
1091 //DEBUGPUTS("Moving to next queue_section\n"); | |
1092 current_section = current_section->next; | |
1093 } | |
1094 else | |
1095 { | |
1096 //DEBUGPUTS("Allocating new queue_section\n"); | |
1097 VIS_PROFILE_START(PROF_ADDQUEUE_MALLOC); | |
1098 temp = MALLOC(sizeof(queue_section),"queue section"); | |
1099 VIS_PROFILE_END(PROF_ADDQUEUE_MALLOC); | |
1100 temp->last = current_section; | |
1101 temp->next = NULL; | |
1102 current_section->next = temp; | |
1103 current_section = temp; | |
1104 } | |
1105 worker_queue = current_section->entries; | |
1106 queue_start = queue_len = 0; | |
1107 } | |
1108 else if(queue_len == 0) | |
1109 { | |
1110 VIS_SetEvent(queue_add_event); | |
1111 //DEBUGPUTS("SetEvent\n"); | |
1112 } | |
1113 | |
1114 if(queue_start+queue_len < QUEUE_SIZE) | |
1115 index = queue_start+queue_len; | |
1116 else | |
1117 index = queue_start+queue_len-QUEUE_SIZE; | |
1118 worker_queue[index].worker_num=data; | |
1119 worker_queue[index].instance = instance; | |
1120 ++queue_len; | |
1121 | |
1122 VIS_LeaveCriticalSection(worker_queue_lock); | |
1123 VIS_PROFILE_END(PROF_ADDQUEUE); | |
1124 } | |
1125 | |
1126 /** | |
1127 * Retrieves a ready worker from the queue | |
1128 */ | |
1129 queue_entry get_queue() | |
1130 { | |
1131 queue_entry data; | |
1132 queue_section * temp; | |
1133 //DEBUGPUTS("Begin get_queue()\n"); | |
1134 | |
1135 VIS_EnterCriticalSection(worker_queue_lock); | |
1136 while(!queue_len && execute_active) | |
1137 { | |
1138 //DEBUGPUTS("Queue empty, resetting event\n"); | |
1139 VIS_ResetEvent(queue_add_event); | |
1140 VIS_LeaveCriticalSection(worker_queue_lock); | |
1141 //DEBUGPUTS("Waiting for queue_add_event\n"); | |
1142 VIS_WaitEvent(queue_add_event); | |
1143 #ifdef NINTENDO_DS | |
1144 //TODO make the processor sleep while waiting for IRQs | |
1145 if(irq_queue_count > 0) | |
1146 run_queued_irqs(); | |
1147 #endif | |
1148 VIS_EnterCriticalSection(worker_queue_lock); | |
1149 } | |
1150 if(queue_len > 0) | |
1151 { | |
1152 data = worker_queue[queue_start]; | |
1153 //DEBUGPRINTF( "Next worker in queue: %d\n", data.worker_num); | |
1154 //DEBUGPRINTF("data.instance: %X, data.instance->workerlist: %X\n", data.instance, data.instance->workerlist); | |
1155 /*VIS_EnterCriticalSection(data.instance->workerlist[data.worker_num].worker_lock); | |
1156 DEBUGPUTS("Adjusting ready_count"); | |
1157 data.instance->workerlist[data.worker_num].ready_count=0; | |
1158 VIS_LeaveCriticalSection(data.instance->workerlist[data.worker_num].worker_lock);*/ | |
1159 ++queue_start; | |
1160 --queue_len; | |
1161 //DEBUGPUTS("Adjusted ready count.\n"); | |
1162 //DEBUGPRINTF("current_section: %X\n", current_section); | |
1163 if(queue_len == 0 && current_section->last) | |
1164 { | |
1165 if(current_section->next != NULL) | |
1166 { | |
1167 //DEBUGPUTS("Freeing current_section->next.\n"); | |
1168 VIS_FREE(current_section->next, "ready queue node"); | |
1169 current_section->next = NULL; | |
1170 } | |
1171 current_section = current_section->last; | |
1172 worker_queue = current_section->entries; | |
1173 queue_start = 0; | |
1174 queue_len = QUEUE_SIZE; | |
1175 } | |
1176 else if(queue_start == QUEUE_SIZE) | |
1177 queue_start = 0; | |
1178 } | |
1179 else | |
1180 { | |
1181 //DEBUGPUTS("Queue empty\n"); | |
1182 data.worker_num = -2; | |
1183 } | |
1184 VIS_LeaveCriticalSection(worker_queue_lock); | |
1185 //DEBUGPUTS("Left worker_queue_lock\n"); | |
1186 //MessageBox(NULL,"AfterLeave","visdbg",MB_OK); | |
1187 if(data.worker_num >= 0) | |
1188 { | |
1189 VIS_EnterCriticalSection(data.instance->counter_lock); | |
1190 //DEBUGPUTS("Adjusting in_queue/in_progress counts.\n"); | |
1191 --(data.instance->in_queue_count); | |
1192 ++(data.instance->in_progress_count); | |
1193 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); | |
1194 | |
1195 VIS_LeaveCriticalSection(data.instance->counter_lock); | |
1196 } | |
1197 //DEBUGPUTS("End get_queue()\n"); | |
1198 | |
1199 return data; | |
1200 } | |
1201 | |
1202 void def_make_lookup(worker_def * def) | |
1203 { | |
1204 int i, j, upoffset, offset; | |
1205 VIS_EnterCriticalSection(def->implement_func->lock); | |
1206 if(def->implement_func->dirty) | |
1207 { | |
1208 upoffset = offset = 0; | |
1209 for(i = 0; i < def->implement_func->num_workers; ++i) | |
1210 { | |
1211 def->implement_func->workerlist[i].wire_down_lookup=offset; | |
1212 def->implement_func->workerlist[i].wire_up_lookup=upoffset; | |
1213 for(j = 0; j < def->implement_func->num_wires; ++j) | |
1214 { | |
1215 if(def->implement_func->wirelist[j].start_worker == i) | |
1216 def->implement_func->workers_to_wires_down[offset++]=j; | |
1217 if(def->implement_func->wirelist[j].end_worker == i) | |
1218 def->implement_func->workers_to_wires_up[upoffset++]=j; | |
1219 } | |
1220 //Clear tail call info | |
1221 if(def->implement_func->workerlist[i].type == TAIL_CALL || def->implement_func->workerlist[i].type == TAIL_RECURSE) | |
1222 def->implement_func->workerlist[i].type = WORKER; | |
1223 } | |
1224 def->implement_func->workers_to_wires_down[offset]=-1; | |
1225 def->implement_func->workers_to_wires_up[upoffset]=-1; | |
1226 check_tail(def); | |
1227 def->implement_func->dirty = FALSE; | |
1228 } | |
1229 VIS_LeaveCriticalSection(def->implement_func->lock); | |
1230 } | |
1231 | |
1232 /** | |
1233 * Generates lookup array to ease navigation between workers | |
1234 */ | |
1235 void make_lookup_arrays(program * prog) | |
1236 { | |
1237 int i,j,k, offset, upoffset; | |
1238 worker_def * deflist; | |
1239 defchunk * current = prog->defs; | |
1240 while(current) | |
1241 { | |
1242 deflist = current->deflist; | |
1243 for(k = 0; k < current->num_defs; ++k) | |
1244 { | |
1245 if(deflist[k].type & USER_FLAG && (deflist[k].type & TYPE_MASK) == WORKER_TYPE) | |
1246 def_make_lookup(deflist + k); | |
1247 } | |
1248 current = current->next; | |
1249 } | |
1250 } | |
1251 extern char _end_bss[]; | |
1252 void initpredefworkers(program * prog) | |
1253 { | |
1254 int current_def = 1; | |
1255 int current_company = 0; | |
1256 int current_method; | |
1257 int comp_room; | |
1258 company * this_comp; | |
1259 worker_def * aworker; | |
1260 create_company(prog, "Any Type", 0, 0, FALSE); | |
1261 create_company(prog, "Yes No", 0, 0, FALSE); | |
1262 | |
1263 aworker = create_worker(prog, "Print", 1, 1, WORKER_TYPE); | |
1264 aworker->implement_func = (custom_worker *)vis_print; | |
1265 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1266 | |
1267 aworker = create_worker(prog, "Random", 0, 1, WORKER_TYPE); | |
1268 aworker->implement_func = (custom_worker *)vis_random; | |
1269 | |
1270 aworker = create_worker(prog, "Build", 1, 1, WORKER_TYPE); | |
1271 aworker->implement_func = (custom_worker *)vis_build; | |
1272 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1273 | |
1274 aworker = create_worker(prog, "End", 1, 0, WORKER_TYPE); | |
1275 aworker->implement_func = (custom_worker *)vis_end; | |
1276 aworker->input_types[0] = ANY_TYPE; | |
1277 | |
1278 create_worker(prog, "Append", 2, 1, MAGIC_TYPE); | |
1279 create_worker(prog, "+", 2, 1, MAGIC_TYPE); | |
1280 create_worker(prog, "-", 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 | |
1287 aworker = create_worker(prog, "Get Input", 0, 1, WORKER_TYPE); | |
1288 aworker->implement_func = (custom_worker *)vis_getinput; | |
1289 | |
1290 aworker = create_worker(prog, "If",1, 2, WORKER_TYPE); | |
1291 aworker->implement_func=(custom_worker *)vis_if; | |
1292 aworker->input_types[0] = BUILTIN_TYPE_YESNO; | |
1293 | |
1294 aworker = create_worker(prog, "Type Of",1, 1, WORKER_TYPE); | |
1295 aworker->implement_func=(custom_worker *)vis_type_of; | |
1296 aworker->input_types[0] = ANY_TYPE; | |
1297 | |
1298 aworker = create_worker(prog, "Init Store",1, 0, WORKER_TYPE); | |
1299 aworker->implement_func=(custom_worker *)init_global_store; | |
1300 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1301 | |
1302 aworker = create_worker(prog, "Wait Forever", 0, 0, WORKER_TYPE); | |
1303 aworker->implement_func=(custom_worker *)vis_wait_forever; | |
1304 | |
1305 #ifdef NINTENDO_DS | |
1306 aworker = create_worker(prog, "Register Handler", 2, 1, WORKER_TYPE); | |
1307 aworker->implement_func = (custom_worker *)vis_register_handler; | |
1308 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1309 aworker->input_types[1] = BUILTIN_TYPE_WORKER; | |
1310 | |
1311 aworker = create_worker(prog, "Clear Handler", 1, 1, WORKER_TYPE); | |
1312 aworker->implement_func = (custom_worker *)vis_clear_handler; | |
1313 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1314 | |
1315 aworker = create_worker(prog, "Held Keys", 0, 1, WORKER_TYPE); | |
1316 aworker->implement_func = (custom_worker *)vis_held_keys; | |
1317 | |
1318 aworker = create_worker(prog, "Touch Position", 0, 2, WORKER_TYPE); | |
1319 aworker->implement_func = (custom_worker *)vis_touch_position; | |
1320 #endif | |
1321 | |
1322 current_method = 0; | |
1323 //strcpy(companylist[current_company].name, "String"); | |
1324 #ifdef SEGA | |
1325 this_comp = create_company(prog, "String", 6, 0, FALSE); | |
1326 #else | |
1327 this_comp = create_company(prog, "String", 7, 0, FALSE); | |
1328 #endif | |
1329 aworker = create_worker(prog, "<Whole Number@String",1, 1, WORKER_TYPE); | |
1330 aworker->implement_func=(custom_worker *)vis_inttostring; | |
1331 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1332 //add_method(this_comp, aworker); | |
1333 | |
1334 #ifndef SEGA | |
1335 | |
1336 aworker = create_worker(prog, "<Real Number@String",1, 1, WORKER_TYPE); | |
1337 aworker->implement_func=(custom_worker *)vis_realtostring; | |
1338 aworker->input_types[0] = BUILTIN_TYPE_REAL; | |
1339 //add_method(this_comp, aworker); | |
1340 #endif | |
1341 | |
1342 aworker = create_worker(prog, "=@String",2, 1, WORKER_TYPE); | |
1343 aworker->implement_func=(custom_worker *)vis_stringequal; | |
1344 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1345 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1346 //add_method(this_comp, aworker); | |
1347 | |
1348 aworker = create_worker(prog, "<Yes No@String",1, 1, WORKER_TYPE); | |
1349 aworker->implement_func=(custom_worker *)vis_yesnotostring; | |
1350 aworker->input_types[0] = BUILTIN_TYPE_YESNO; | |
1351 //add_method(this_comp, aworker); | |
1352 | |
1353 aworker = create_worker(prog, ">@String",2, 1, WORKER_TYPE); | |
1354 aworker->implement_func=(custom_worker *)vis_greaterstring; | |
1355 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1356 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1357 //add_method(this_comp, aworker); | |
1358 | |
1359 aworker = create_worker(prog, "<@String",2, 1, WORKER_TYPE); | |
1360 aworker->implement_func=(custom_worker *)vis_lesserstring; | |
1361 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1362 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1363 //add_method(this_comp, aworker); | |
1364 | |
1365 aworker = create_worker(prog, "Append@String",2, 1, WORKER_TYPE); | |
1366 aworker->implement_func=(custom_worker *)vis_append; | |
1367 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1368 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1369 //add_method(this_comp, aworker); | |
1370 | |
1371 aworker = create_worker(prog, "Split@String",2, 1, WORKER_TYPE); | |
1372 aworker->implement_func=(custom_worker *)vis_string_split; | |
1373 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1374 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1375 | |
1376 aworker = create_worker(prog, "Get Raw@String",2, 2, WORKER_TYPE); | |
1377 aworker->implement_func=(custom_worker *)vis_string_get_raw; | |
1378 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1379 aworker->input_types[1] = ANY_TYPE; | |
1380 | |
1381 aworker = create_worker(prog, "Put Raw@String",2, 1, WORKER_TYPE); | |
1382 aworker->implement_func=(custom_worker *)vis_string_put_raw; | |
1383 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1384 aworker->input_types[1] = ANY_TYPE; | |
1385 | |
1386 aworker = create_worker(prog, "Slice@String",2, 2, WORKER_TYPE); | |
1387 aworker->implement_func=(custom_worker *)vis_string_slice; | |
1388 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1389 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1390 | |
1391 aworker = create_worker(prog, "Reverse@String",1, 1, WORKER_TYPE); | |
1392 aworker->implement_func=(custom_worker *)vis_string_reverse; | |
1393 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1394 | |
1395 aworker = create_worker(prog, "Length@String",1, 1, WORKER_TYPE); | |
1396 aworker->implement_func=(custom_worker *)vis_string_length; | |
1397 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1398 | |
1399 aworker = create_worker(prog, "Put Byte@String",2, 1, WORKER_TYPE); | |
1400 aworker->implement_func=(custom_worker *)vis_string_put_byte; | |
1401 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1402 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1403 | |
1404 aworker = create_worker(prog, "Get DString@String",2, 4, WORKER_TYPE); | |
1405 aworker->implement_func=(custom_worker *)vis_string_get_dstring; | |
1406 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1407 aworker->input_types[1] = ANY_TYPE; | |
1408 | |
1409 current_method = 0; | |
1410 this_comp = create_company(prog, "Whole Number", 6, 0, FALSE); | |
1411 aworker = create_worker(prog, "<String@Whole Number",1, 1, WORKER_TYPE); | |
1412 aworker->implement_func=(custom_worker *)vis_stringtoint; | |
1413 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1414 | |
1415 aworker = create_worker(prog, "From Hex@Whole Number",1, 1, WORKER_TYPE); | |
1416 aworker->implement_func=(custom_worker *)vis_whole_fromhex; | |
1417 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1418 //add_method(this_comp, aworker); | |
1419 | |
1420 aworker = create_worker(prog, "=@Whole Number",2, 1, WORKER_TYPE); | |
1421 aworker->implement_func=(custom_worker *)vis_wholeequal; | |
1422 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1423 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1424 //add_method(this_comp, aworker); | |
1425 | |
1426 aworker = create_worker(prog, ">@Whole Number",2, 1, WORKER_TYPE); | |
1427 aworker->implement_func=(custom_worker *)vis_greaterint; | |
1428 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1429 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1430 //add_method(this_comp, aworker); | |
1431 | |
1432 aworker = create_worker(prog, "<@Whole Number",2, 1, WORKER_TYPE); | |
1433 aworker->implement_func=(custom_worker *)vis_lesserint; | |
1434 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1435 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1436 | |
1437 //add_method(this_comp, aworker); | |
1438 | |
1439 aworker = create_worker(prog, "+@Whole Number", 2, 1, WORKER_TYPE); | |
1440 aworker->implement_func=(custom_worker *)vis_whole_add; | |
1441 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1442 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1443 | |
1444 //add_method(this_comp, aworker); | |
1445 | |
1446 aworker = create_worker(prog, "-@Whole Number", 2, 1, WORKER_TYPE); | |
1447 aworker->implement_func=(custom_worker *)vis_whole_subtract; | |
1448 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1449 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1450 | |
1451 aworker = create_worker(prog, "*@Whole Number", 2, 1, WORKER_TYPE); | |
1452 aworker->implement_func=(custom_worker *)vis_whole_mult; | |
1453 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1454 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1455 | |
1456 //add_method(this_comp, aworker); | |
1457 | |
1458 aworker = create_worker(prog, "/@Whole Number", 2, 1, WORKER_TYPE); | |
1459 aworker->implement_func=(custom_worker *)vis_whole_div; | |
1460 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1461 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1462 | |
1463 aworker = create_worker(prog, "&@Whole Number", 2, 1, WORKER_TYPE); | |
1464 aworker->implement_func=(custom_worker *)vis_whole_and; | |
1465 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1466 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1467 | |
1468 aworker = create_worker(prog, "|@Whole Number", 2, 1, WORKER_TYPE); | |
1469 aworker->implement_func=(custom_worker *)vis_whole_or; | |
1470 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1471 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1472 | |
1473 aworker = create_worker(prog, "LShift@Whole Number", 2, 1, WORKER_TYPE); | |
1474 aworker->implement_func=(custom_worker *)vis_whole_lsh; | |
1475 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1476 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1477 | |
1478 aworker = create_worker(prog, "RShift@Whole Number", 2, 1, WORKER_TYPE); | |
1479 aworker->implement_func=(custom_worker *)vis_whole_rsh; | |
1480 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1481 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1482 | |
1483 //add_method(this_comp, aworker); | |
1484 | |
1485 current_method = 0; | |
1486 this_comp = create_company(prog, "Real Number", 6, 0, FALSE);//<string, =, >, <, +, - | |
1487 aworker = create_worker(prog, "<String@Real Number", 1, 1, WORKER_TYPE); | |
1488 aworker->implement_func=(custom_worker *)vis_stringtoreal; | |
1489 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1490 //add_method(this_comp, aworker); | |
1491 | |
1492 aworker = create_worker(prog, "=@Real Number", 2, 1, WORKER_TYPE); | |
1493 aworker->implement_func=(custom_worker *)vis_realequal; | |
1494 aworker->input_types[0] = BUILTIN_TYPE_REAL; | |
1495 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1496 | |
1497 //add_method(this_comp, aworker); | |
1498 | |
1499 aworker = create_worker(prog, ">@Real Number", 2, 1, WORKER_TYPE); | |
1500 aworker->implement_func=(custom_worker *)vis_greaterreal; | |
1501 aworker->input_types[0] = BUILTIN_TYPE_REAL; | |
1502 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1503 | |
1504 //add_method(this_comp, aworker); | |
1505 | |
1506 aworker = create_worker(prog, "<@Real Number", 2, 1, WORKER_TYPE); | |
1507 aworker->implement_func=(custom_worker *)vis_lesserreal; | |
1508 aworker->input_types[0] = BUILTIN_TYPE_REAL; | |
1509 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1510 | |
1511 //add_method(this_comp, aworker); | |
1512 | |
1513 aworker = create_worker(prog, "+@Real Number", 2, 1, WORKER_TYPE); | |
1514 aworker->implement_func=(custom_worker *)vis_real_add; | |
1515 aworker->input_types[0] = BUILTIN_TYPE_REAL; | |
1516 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1517 | |
1518 //add_method(this_comp, aworker); | |
1519 | |
1520 aworker = create_worker(prog, "-@Real Number", 2, 1, WORKER_TYPE); | |
1521 aworker->implement_func=(custom_worker *)vis_real_subtract; | |
1522 aworker->input_types[0] = BUILTIN_TYPE_REAL; | |
1523 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1524 | |
1525 aworker = create_worker(prog, "/@Real Number", 2, 1, WORKER_TYPE); | |
1526 aworker->implement_func=(custom_worker *)vis_real_div; | |
1527 aworker->input_types[0] = BUILTIN_TYPE_REAL; | |
1528 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1529 | |
1530 //add_method(this_comp, aworker); | |
1531 | |
1532 current_method = 0; | |
1533 this_comp = create_company(prog, "List", 7, 1, FALSE);//Index, Append, Swap, Insert, Remove, Set, Length, New | |
1534 comp_room = add_comp_room(this_comp, "Length", 0, 0, ROOM_NO_ACCESS, ROOM_LONG); | |
1535 | |
1536 aworker = create_worker(prog, "Index@List", 2, 2, WORKER_TYPE); | |
1537 aworker->implement_func=(custom_worker *)vis_list_index; | |
1538 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1539 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1540 | |
1541 //add_method(this_comp, aworker); | |
1542 | |
1543 aworker = create_worker(prog, "Append@List", 2, 1, WORKER_TYPE); | |
1544 aworker->implement_func=(custom_worker *)vis_list_append; | |
1545 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1546 aworker->input_types[1] = ANY_TYPE; | |
1547 | |
1548 //add_method(this_comp, aworker); | |
1549 | |
1550 aworker = create_worker(prog, "Swap@List",3, 1, WORKER_TYPE); | |
1551 aworker->implement_func=(custom_worker *)vis_list_swap; | |
1552 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1553 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1554 aworker->input_types[2] = BUILTIN_TYPE_WHOLE; | |
1555 | |
1556 //add_method(this_comp, aworker); | |
1557 | |
1558 aworker = create_worker(prog, "Insert@List",3, 1, WORKER_TYPE); | |
1559 aworker->implement_func=(custom_worker *)vis_list_insert; | |
1560 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1561 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1562 aworker->input_types[2] = ANY_TYPE; | |
1563 | |
1564 //add_method(this_comp, aworker); | |
1565 | |
1566 aworker = create_worker(prog, "Remove@List", 2, 1, WORKER_TYPE); | |
1567 aworker->implement_func=(custom_worker *)vis_list_remove; | |
1568 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1569 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1570 | |
1571 //add_method(this_comp, aworker); | |
1572 | |
1573 aworker = create_worker(prog, "Set@List",3, 1, WORKER_TYPE); | |
1574 aworker->implement_func=(custom_worker *)vis_list_set; | |
1575 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1576 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1577 aworker->input_types[2] = ANY_TYPE; | |
1578 | |
1579 //add_method(this_comp, aworker); | |
1580 | |
1581 aworker = create_worker(prog, "Length@List", 1, 1, WORKER_TYPE); | |
1582 aworker->implement_func = (custom_worker *)vis_list_length; | |
1583 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1584 //add_method(this_comp, aworker); | |
1585 | |
1586 aworker = create_worker(prog, "New@List",0, 1, WORKER_TYPE); | |
1587 aworker->implement_func=(custom_worker *)vis_list_new; | |
1588 //add_method(this_comp, aworker); | |
1589 | |
1590 aworker = create_worker(prog, "First@List", 1, 2, WORKER_TYPE); | |
1591 aworker->implement_func=(custom_worker *)vis_list_first; | |
1592 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1593 | |
1594 aworker = create_worker(prog, "Next@List", 2, 2, WORKER_TYPE); | |
1595 aworker->implement_func=(custom_worker *)vis_list_next; | |
1596 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
1597 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1598 | |
1599 current_method = 0; | |
1600 this_comp = create_company(prog, "Dictionary", 5, 0, FALSE);//Index, Swap, Remove, Set, Length, New | |
1601 aworker = create_worker(prog, "Index@Dictionary", 2, 2, WORKER_TYPE); | |
1602 aworker->implement_func=(custom_worker *)vis_dict_index; | |
1603 aworker->input_types[0] = BUILTIN_TYPE_DICT; | |
1604 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1605 | |
1606 //add_method(this_comp, aworker); | |
1607 | |
1608 aworker = create_worker(prog, "Swap@Dictionary",3, 1, WORKER_TYPE); | |
1609 aworker->implement_func=(custom_worker *)vis_dict_swap; | |
1610 aworker->input_types[0] = BUILTIN_TYPE_DICT; | |
1611 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1612 aworker->input_types[2] = BUILTIN_TYPE_STRING; | |
1613 | |
1614 //add_method(this_comp, aworker); | |
1615 | |
1616 aworker = create_worker(prog, "Remove@Dictionary", 2, 1, WORKER_TYPE); | |
1617 aworker->implement_func=(custom_worker *)vis_dict_remove; | |
1618 aworker->input_types[0] = BUILTIN_TYPE_DICT; | |
1619 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1620 | |
1621 //add_method(this_comp, aworker); | |
1622 | |
1623 aworker = create_worker(prog, "Set@Dictionary",3, 1, WORKER_TYPE); | |
1624 aworker->implement_func=(custom_worker *)vis_dict_set; | |
1625 aworker->input_types[0] = BUILTIN_TYPE_DICT; | |
1626 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1627 aworker->input_types[2] = ANY_TYPE; | |
1628 | |
1629 aworker = create_worker(prog, "Length@Dictionary", 1, 1, WORKER_TYPE); | |
1630 aworker->implement_func=(custom_worker *)vis_dict_length; | |
1631 aworker->input_types[0] = BUILTIN_TYPE_DICT; | |
1632 | |
1633 //add_method(this_comp, aworker); | |
1634 | |
1635 aworker = create_worker(prog, "New@Dictionary",0, 1, WORKER_TYPE); | |
1636 aworker->implement_func=(custom_worker *)vis_dict_new; | |
1637 //add_method(this_comp, aworker); | |
1638 | |
1639 aworker = create_worker(prog, "First@Dictionary", 1, 2, WORKER_TYPE); | |
1640 aworker->implement_func=(custom_worker *)vis_dict_first; | |
1641 aworker->input_types[0] = BUILTIN_TYPE_DICT; | |
1642 | |
1643 aworker = create_worker(prog, "Next@Dictionary", 2, 2, WORKER_TYPE); | |
1644 aworker->implement_func=(custom_worker *)vis_dict_next; | |
1645 aworker->input_types[0] = BUILTIN_TYPE_DICT; | |
1646 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1647 | |
1648 current_method = 0; | |
1649 #ifdef SEGA | |
1650 this_comp = create_company(prog, "File", 0, 0, FALSE); | |
1651 #else | |
1652 | |
1653 this_comp = create_company(prog, "File", 7, 0, FALSE);//<String, Get FString, Get DString, Get Byte, Get Word, Get Long, Put String | |
1654 aworker = create_worker(prog, "<String@File", 1, 1, WORKER_TYPE); | |
1655 aworker->implement_func=(custom_worker *)vis_file_from_string; | |
1656 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1657 //add_method(this_comp, aworker); | |
1658 | |
1659 aworker = create_worker(prog, "Get FString@File", 2, 2, WORKER_TYPE); | |
1660 aworker->implement_func=(custom_worker *)vis_file_get_fstring; | |
1661 aworker->input_types[0] = BUILTIN_TYPE_FILE; | |
1662 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1663 | |
1664 //add_method(this_comp, aworker); | |
1665 | |
1666 aworker = create_worker(prog, "Get DString@File", 2, 4, WORKER_TYPE); | |
1667 aworker->implement_func=(custom_worker *)vis_file_get_dstring; | |
1668 aworker->input_types[0] = BUILTIN_TYPE_FILE; | |
1669 aworker->input_types[1] = ANY_TYPE; | |
1670 | |
1671 //add_method(this_comp, aworker); | |
1672 | |
1673 aworker = create_worker(prog, "Get Byte@File", 1, 3, WORKER_TYPE); | |
1674 aworker->implement_func=(custom_worker *)vis_file_get_byte; | |
1675 aworker->input_types[0] = BUILTIN_TYPE_FILE; | |
1676 //add_method(this_comp, aworker); | |
1677 | |
1678 aworker = create_worker(prog, "Get Word@File", 1, 3, WORKER_TYPE); | |
1679 aworker->implement_func=(custom_worker *)vis_file_get_word; | |
1680 aworker->input_types[0] = BUILTIN_TYPE_FILE; | |
1681 //add_method(this_comp, aworker); | |
1682 | |
1683 aworker = create_worker(prog, "Get Long@File", 1, 3, WORKER_TYPE); | |
1684 aworker->implement_func=(custom_worker *)vis_file_get_long; | |
1685 aworker->input_types[0] = BUILTIN_TYPE_FILE; | |
1686 //add_method(this_comp, aworker); | |
1687 | |
1688 aworker = create_worker(prog, "Put String@File", 2, 1, WORKER_TYPE); | |
1689 aworker->implement_func=(custom_worker *)vis_file_put_string; | |
1690 aworker->input_types[0] = BUILTIN_TYPE_FILE; | |
1691 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1692 | |
1693 aworker = create_worker(prog, "Length@File", 1, 1, WORKER_TYPE); | |
1694 aworker->implement_func=(custom_worker *)vis_file_length; | |
1695 aworker->input_types[0] = BUILTIN_TYPE_FILE; | |
1696 | |
1697 //add_method(this_comp, aworker); | |
1698 #endif | |
1699 | |
1700 current_method = 0; | |
1701 | |
1702 this_comp = create_company(prog, "Worker", 3, 0, FALSE);//<String, Do, Later: methods for manipulating | |
1703 | |
1704 aworker = create_worker(prog, "<String@Worker", 1, 1, WORKER_TYPE); | |
1705 aworker->implement_func=(custom_worker *)vis_worker_from_string; | |
1706 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1707 //add_method(this_comp, aworker); | |
1708 | |
1709 aworker = create_worker(prog, "Do@Worker", 2, 1, WORKER_TYPE); | |
1710 aworker->implement_func=(custom_worker *)vis_worker_do; | |
1711 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1712 aworker->input_types[1] = BUILTIN_TYPE_LIST; | |
1713 | |
1714 aworker = create_worker(prog, "Set Input@Worker", 3, 1, WORKER_TYPE); | |
1715 aworker->implement_func=(custom_worker *)vis_worker_setinput; | |
1716 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1717 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1718 aworker->input_types[2] = ANY_TYPE; | |
1719 //add_method(this_comp, aworker); | |
1720 | |
1721 aworker = create_worker(prog, "Add Worker Call@Worker", 2, 2, WORKER_TYPE); | |
1722 aworker->implement_func=(custom_worker *)vis_worker_add_worker_call; | |
1723 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1724 aworker->input_types[1] = BUILTIN_TYPE_WORKER; | |
1725 | |
1726 aworker = create_worker(prog, "Add Wire@Worker", 5, 1, WORKER_TYPE); | |
1727 aworker->implement_func=(custom_worker *)vis_worker_add_wire; | |
1728 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1729 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1730 aworker->input_types[2] = BUILTIN_TYPE_WHOLE; | |
1731 aworker->input_types[3] = BUILTIN_TYPE_WHOLE; | |
1732 aworker->input_types[4] = BUILTIN_TYPE_WHOLE; | |
1733 | |
1734 aworker = create_worker(prog, "Add Constant@Worker", 2, 2, WORKER_TYPE); | |
1735 aworker->implement_func=(custom_worker *)vis_worker_add_constant; | |
1736 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1737 aworker->input_types[1] = ANY_TYPE; | |
1738 | |
1739 aworker = create_worker(prog, "Add Input@Worker", 3, 2, WORKER_TYPE); | |
1740 aworker->implement_func=(custom_worker *)vis_worker_add_input; | |
1741 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1742 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1743 aworker->input_types[2] = BUILTIN_TYPE_WHOLE; | |
1744 | |
1745 aworker = create_worker(prog, "Add Output@Worker", 3, 2, WORKER_TYPE); | |
1746 aworker->implement_func=(custom_worker *)vis_worker_add_output; | |
1747 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1748 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1749 aworker->input_types[2] = BUILTIN_TYPE_WHOLE; | |
1750 | |
1751 aworker = create_worker(prog, "Add Object Get@Worker", 2, 2, WORKER_TYPE); | |
1752 aworker->implement_func=(custom_worker *)vis_worker_add_objectget; | |
1753 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1754 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1755 | |
1756 aworker = create_worker(prog, "Add Object Set@Worker", 2, 2, WORKER_TYPE); | |
1757 aworker->implement_func=(custom_worker *)vis_worker_add_objectset; | |
1758 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1759 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1760 | |
1761 aworker = create_worker(prog, "Add Global Get@Worker", 3, 2, WORKER_TYPE); | |
1762 aworker->implement_func=(custom_worker *)vis_worker_add_globalget; | |
1763 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1764 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1765 aworker->input_types[2] = BUILTIN_TYPE_STRING; | |
1766 | |
1767 aworker = create_worker(prog, "Add Global Set@Worker", 3, 2, WORKER_TYPE); | |
1768 aworker->implement_func=(custom_worker *)vis_worker_add_globalset; | |
1769 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1770 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1771 aworker->input_types[2] = BUILTIN_TYPE_STRING; | |
1772 | |
1773 aworker = create_worker(prog, "Clear@Worker", 1, 1, WORKER_TYPE); | |
1774 aworker->implement_func=(custom_worker *)vis_worker_clear; | |
1775 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1776 | |
1777 aworker = create_worker(prog, "Uses@Worker", 2, 1, WORKER_TYPE); | |
1778 aworker->implement_func=(custom_worker *)vis_worker_uses; | |
1779 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1780 aworker->input_types[1] = BUILTIN_TYPE_LIST; | |
1781 | |
1782 aworker = create_worker(prog, "Set IO Counts@Worker", 3, 1, WORKER_TYPE); | |
1783 aworker->implement_func=(custom_worker *)vis_worker_setio_counts; | |
1784 aworker->input_types[0] = BUILTIN_TYPE_WORKER; | |
1785 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1786 aworker->input_types[2] = BUILTIN_TYPE_WHOLE; | |
1787 | |
1788 aworker = create_worker(prog, "New@Worker", 1, 1, WORKER_TYPE); | |
1789 aworker->implement_func=(custom_worker *)vis_worker_new; | |
1790 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1791 | |
1792 #ifdef GUI_LIB | |
1793 current_method = 0; | |
1794 | |
1795 this_comp = create_company(prog, "Window", 3, 0, FALSE); | |
1796 | |
1797 aworker = create_worker(prog, "New@Window", 3, 1, WORKER_TYPE); | |
1798 aworker->implement_func=(custom_worker *)vis_window_new; | |
1799 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1800 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1801 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
1802 //add_method(this_comp, aworker); | |
1803 | |
1804 aworker = create_worker(prog, "Add Widget@Window", 5, 1, WORKER_TYPE); | |
1805 aworker->implement_func=(custom_worker *)vis_window_add_widget; | |
1806 aworker->input_types[0] = BUILTIN_TYPE_WINDOW; | |
1807 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1808 aworker->input_types[2] = ANY_TYPE; | |
1809 aworker->input_types[3] = BUILTIN_TYPE_REAL; | |
1810 aworker->input_types[4] = BUILTIN_TYPE_REAL; | |
1811 //add_method(this_comp, aworker); | |
1812 | |
1813 aworker = create_worker(prog, "Show@Window", 3, 1, WORKER_TYPE); | |
1814 aworker->implement_func=(custom_worker *)vis_window_show; | |
1815 aworker->input_types[0] = BUILTIN_TYPE_WINDOW; | |
1816 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1817 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
1818 //add_method(this_comp, aworker); | |
1819 | |
1820 current_method = 0; | |
1821 this_comp = create_company(prog, "Screen Window", 3, 0, FALSE); | |
1822 | |
1823 aworker = create_worker(prog, "Get Value@Screen Window", 2, 1, WORKER_TYPE); | |
1824 aworker->implement_func=(custom_worker *)vis_window_get_value; | |
1825 aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN; | |
1826 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1827 //add_method(this_comp, aworker); | |
1828 | |
1829 aworker = create_worker(prog, "Set Value@Screen Window", 3, 0, WORKER_TYPE); | |
1830 aworker->implement_func=(custom_worker *)vis_window_set_value; | |
1831 aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN; | |
1832 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1833 #ifdef SYLLABLE | |
1834 aworker->input_types[2] = ANY_TYPE; | |
1835 #else | |
1836 aworker->input_types[2] = BUILTIN_TYPE_STRING; | |
1837 #endif | |
1838 //add_method(this_comp, aworker); | |
1839 | |
1840 aworker = create_worker(prog, "Wait Close@Screen Window", 1, 1, WORKER_TYPE); | |
1841 aworker->implement_func=(custom_worker *)vis_window_wait_close; | |
1842 aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN; | |
1843 //add_method(this_comp, aworker); | |
1844 | |
1845 #ifdef SYLLABLE | |
1846 aworker = create_worker(prog, "Add Widget@Screen Window", 5, 1, WORKER_TYPE); | |
1847 aworker->implement_func=(custom_worker *)vis_window_shown_addwidget; | |
1848 aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN; | |
1849 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1850 aworker->input_types[2] = ANY_TYPE; | |
1851 aworker->input_types[3] = BUILTIN_TYPE_REAL; | |
1852 aworker->input_types[4] = BUILTIN_TYPE_REAL; | |
1853 #endif | |
1854 | |
1855 current_method = 0; | |
1856 create_company(prog, "Button", 2, 0, FALSE); | |
1857 | |
1858 aworker = create_worker(prog, "New@Button", 3, 1, WORKER_TYPE); | |
1859 aworker->implement_func=(custom_worker *)vis_button_new; | |
1860 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1861 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1862 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
1863 //add_method(this_comp, aworker); | |
1864 | |
1865 aworker = create_worker(prog, "Set Handler@Button", 3, 1, WORKER_TYPE); | |
1866 aworker->implement_func=(custom_worker *)vis_button_set_handler; | |
1867 aworker->input_types[0] = BUILTIN_TYPE_BUTTON; | |
1868 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1869 aworker->input_types[2] = BUILTIN_TYPE_WORKER; | |
1870 //add_method(this_comp, aworker); | |
1871 | |
1872 current_method = 0; | |
1873 create_company(prog, "Input Box", 2, 0, FALSE); | |
1874 | |
1875 aworker = create_worker(prog, "New@Input Box", 3, 1, WORKER_TYPE); | |
1876 aworker->implement_func=(custom_worker *)vis_inputbox_new; | |
1877 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1878 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1879 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
1880 //add_method(this_comp, aworker); | |
1881 | |
1882 aworker = create_worker(prog, "Set Type@Input Box", 2, 1, WORKER_TYPE); | |
1883 aworker->implement_func=(custom_worker *)vis_inputbox_settype; | |
1884 aworker->input_types[0] = BUILTIN_TYPE_INPUTBOX; | |
1885 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1886 //add_method(this_comp, aworker); | |
1887 | |
1888 #endif | |
1889 #ifndef NO_NET | |
1890 this_comp = create_company(prog, "Net Client", 3, 0, FALSE); | |
1891 aworker = create_worker(prog, "New@Net Client", 2, 1, WORKER_TYPE); | |
1892 aworker->implement_func =(custom_worker *)net_client_new; | |
1893 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1894 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1895 | |
1896 aworker = create_worker(prog, "Put String@Net Client", 2, 2, WORKER_TYPE); | |
1897 aworker->implement_func = (custom_worker *)net_client_put_string; | |
1898 aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; | |
1899 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1900 | |
1901 aworker = create_worker(prog, "Get FString@Net Client", 2, 3, WORKER_TYPE); | |
1902 aworker->implement_func = (custom_worker *)net_client_get_fstring; | |
1903 aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; | |
1904 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
1905 | |
1906 aworker = create_worker(prog, "Get DString@Net Client", 2, 4, WORKER_TYPE); | |
1907 aworker->implement_func = (custom_worker *)net_client_get_dstring; | |
1908 aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; | |
1909 aworker->input_types[1] = ANY_TYPE; | |
1910 | |
1911 aworker = create_worker(prog, "Put Raw@Net Client", 2, 2, WORKER_TYPE); | |
1912 aworker->implement_func = (custom_worker *)net_client_put_raw; | |
1913 aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; | |
1914 aworker->input_types[1] = ANY_TYPE; | |
1915 | |
1916 aworker = create_worker(prog, "Get Raw@Net Client", 2, 3, WORKER_TYPE); | |
1917 aworker->implement_func = (custom_worker *)net_client_get_raw; | |
1918 aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT; | |
1919 aworker->input_types[1] = ANY_TYPE; | |
1920 | |
1921 aworker = create_worker(prog, "Listen on Port", 2, 0, WORKER_TYPE); | |
1922 aworker->implement_func = (custom_worker *)vis_net_listenport; | |
1923 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
1924 aworker->input_types[1] = BUILTIN_TYPE_WORKER; | |
1925 #endif | |
1926 | |
1927 create_company(prog, "Global Store", 0, 0, FALSE); | |
1928 | |
1929 create_company(prog, "Program", 5, 0, FALSE); | |
1930 | |
1931 aworker = create_worker(prog, "New@Program", 0, 1, WORKER_TYPE); | |
1932 aworker->implement_func = (custom_worker *)vis_program_new; | |
1933 | |
1934 aworker = create_worker(prog, "New Worker@Program", 2, 2, WORKER_TYPE); | |
1935 aworker->implement_func = (custom_worker *)vis_program_new_worker; | |
1936 aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; | |
1937 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1938 | |
1939 aworker = create_worker(prog, "Add Worker@Program", 2, 2, WORKER_TYPE); | |
1940 aworker->implement_func = (custom_worker *)vis_program_add_worker; | |
1941 aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; | |
1942 aworker->input_types[1] = BUILTIN_TYPE_WORKER; | |
1943 | |
1944 aworker = create_worker(prog, "Add Builtins@Program", 1, 1, WORKER_TYPE); | |
1945 aworker->implement_func = (custom_worker *)vis_program_add_builtins; | |
1946 aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; | |
1947 | |
1948 aworker = create_worker(prog, "Run@Program", 2, 1, WORKER_TYPE); | |
1949 aworker->implement_func = (custom_worker *)vis_program_run; | |
1950 aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; | |
1951 aworker->input_types[1] = ANY_TYPE; | |
1952 | |
1953 aworker = create_worker(prog, "Find Worker@Program", 2, 2, WORKER_TYPE); | |
1954 aworker->implement_func = (custom_worker *)vis_program_find_worker; | |
1955 aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; | |
1956 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1957 | |
1958 #ifdef GUI_LIB | |
1959 #ifdef SYLLABLE | |
1960 create_company(prog, "Custom Widget", 2, 0, FALSE); | |
1961 | |
1962 aworker = create_worker(prog, "New@Custom Widget", 3, 1, WORKER_TYPE); | |
1963 aworker->implement_func=(custom_worker *)vis_customwidget_new; | |
1964 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
1965 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1966 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
1967 //add_method(this_comp, aworker); | |
1968 | |
1969 aworker = create_worker(prog, "Set Handler@Custom Widget", 3, 1, WORKER_TYPE); | |
1970 aworker->implement_func=(custom_worker *)vis_button_set_handler; | |
1971 aworker->input_types[0] = BUILTIN_TYPE_CUSTOM_WIDGET; | |
1972 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1973 aworker->input_types[2] = BUILTIN_TYPE_WORKER; | |
1974 //add_method(this_comp, aworker); | |
1975 | |
1976 create_company(prog, "Screen Custom Widget", 3, 0, FALSE); | |
1977 | |
1978 aworker = create_worker(prog, "Default Draw@Screen Custom Widget", 1, 1, WORKER_TYPE); | |
1979 aworker->implement_func=(custom_worker *)vis_screen_custom_defaultpaint; | |
1980 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
1981 //add_method(this_comp, aworker); | |
1982 | |
1983 aworker = create_worker(prog, "Draw Line@Screen Custom Widget", 5, 1, WORKER_TYPE); | |
1984 aworker->implement_func=(custom_worker *)vis_screen_custom_drawline; | |
1985 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
1986 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
1987 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
1988 aworker->input_types[3] = BUILTIN_TYPE_REAL; | |
1989 aworker->input_types[4] = BUILTIN_TYPE_REAL; | |
1990 //add_method(this_comp, aworker); | |
1991 | |
1992 aworker = create_worker(prog, "Draw String@Screen Custom Widget", 4, 1, WORKER_TYPE); | |
1993 aworker->implement_func=(custom_worker *)vis_screen_custom_drawstring; | |
1994 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
1995 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
1996 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
1997 aworker->input_types[3] = BUILTIN_TYPE_REAL; | |
1998 | |
1999 aworker = create_worker(prog, "Set Draw Color@Screen Custom Widget", 5, 1, WORKER_TYPE); | |
2000 aworker->implement_func=(custom_worker *)vis_screen_custom_setdrawcolor; | |
2001 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
2002 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2003 aworker->input_types[2] = BUILTIN_TYPE_WHOLE; | |
2004 aworker->input_types[3] = BUILTIN_TYPE_WHOLE; | |
2005 aworker->input_types[4] = BUILTIN_TYPE_WHOLE; | |
2006 | |
2007 aworker = create_worker(prog, "Move By@Screen Custom Widget", 3, 1, WORKER_TYPE); | |
2008 aworker->implement_func=(custom_worker *)vis_screen_custom_moveby; | |
2009 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
2010 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
2011 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
2012 | |
2013 aworker = create_worker(prog, "Set Handler@Screen Custom Widget", 3, 1, WORKER_TYPE); | |
2014 aworker->implement_func=(custom_worker *)vis_screen_custom_sethandler; | |
2015 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
2016 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2017 aworker->input_types[2] = BUILTIN_TYPE_WORKER; | |
2018 | |
2019 aworker = create_worker(prog, "Remove Handler@Screen Custom Widget", 2, 1, WORKER_TYPE); | |
2020 aworker->implement_func=(custom_worker *)vis_screen_custom_removehandler; | |
2021 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
2022 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2023 | |
2024 aworker = create_worker(prog, "Give Focus@Screen Custom Widget", 2, 1, WORKER_TYPE); | |
2025 aworker->implement_func=(custom_worker *)vis_screen_custom_givefocus; | |
2026 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
2027 aworker->input_types[1] = BUILTIN_TYPE_YESNO; | |
2028 | |
2029 aworker = create_worker(prog, "Add Widget@Screen Custom Widget", 5, 1, WORKER_TYPE); | |
2030 aworker->implement_func=(custom_worker *)vis_screen_custom_addwidget; | |
2031 aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM; | |
2032 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2033 aworker->input_types[2] = ANY_TYPE; | |
2034 aworker->input_types[3] = BUILTIN_TYPE_REAL; | |
2035 aworker->input_types[4] = BUILTIN_TYPE_REAL; | |
2036 | |
2037 #endif | |
2038 #endif | |
2039 create_company(prog, "Buffer", 7, 0, FALSE); | |
2040 | |
2041 aworker = create_worker(prog, "New@Buffer", 1, 1, WORKER_TYPE); | |
2042 aworker->implement_func=(custom_worker *)vis_buffer_new; | |
2043 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
2044 | |
2045 aworker = create_worker(prog, "Lock@Buffer", 1, 1, WORKER_TYPE); | |
2046 aworker->implement_func=(custom_worker *)vis_buffer_lock; | |
2047 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2048 | |
2049 aworker = create_worker(prog, "Unlock@Buffer", 1, 1, WORKER_TYPE); | |
2050 aworker->implement_func=(custom_worker *)vis_buffer_unlock; | |
2051 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2052 | |
2053 aworker = create_worker(prog, "Put Byte@Buffer", 2, 1, WORKER_TYPE); | |
2054 aworker->implement_func=(custom_worker *)vis_buffer_putbyte; | |
2055 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2056 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2057 | |
2058 aworker = create_worker(prog, "Write Byte@Buffer", 2, 1, WORKER_TYPE); | |
2059 aworker->implement_func=(custom_worker *)vis_buffer_writebyte; | |
2060 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2061 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2062 | |
2063 aworker = create_worker(prog, "Put Word@Buffer", 2, 1, WORKER_TYPE); | |
2064 aworker->implement_func=(custom_worker *)vis_buffer_putshort; | |
2065 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2066 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2067 | |
2068 aworker = create_worker(prog, "Write Word@Buffer", 2, 1, WORKER_TYPE); | |
2069 aworker->implement_func=(custom_worker *)vis_buffer_writeshort; | |
2070 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2071 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2072 | |
2073 aworker = create_worker(prog, "Put Long@Buffer", 2, 1, WORKER_TYPE); | |
2074 aworker->implement_func=(custom_worker *)vis_buffer_putlong; | |
2075 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2076 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2077 | |
2078 aworker = create_worker(prog, "Write Long@Buffer", 2, 1, WORKER_TYPE); | |
2079 aworker->implement_func=(custom_worker *)vis_buffer_writelong; | |
2080 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2081 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2082 | |
2083 aworker = create_worker(prog, "Reset@Buffer", 1, 1, WORKER_TYPE); | |
2084 aworker->implement_func=(custom_worker *)vis_buffer_reset; | |
2085 aworker->input_types[0] = BUILTIN_TYPE_BUFFER; | |
2086 | |
2087 #if defined(SEGA) || defined(NINTENDO_DS) | |
2088 | |
2089 aworker = create_worker(prog, "From Address@Buffer", 2, 1, WORKER_TYPE); | |
2090 aworker->implement_func=(custom_worker *)vis_buffer_fromaddress; | |
2091 aworker->input_types[0] = BUILTIN_TYPE_WHOLE; | |
2092 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2093 #endif //SEGA | |
2094 | |
2095 create_company(prog, "Blueprint", 4, 0, FALSE); | |
2096 | |
2097 aworker = create_worker(prog, "New@Blueprint", 1, 1, WORKER_TYPE); | |
2098 aworker->implement_func=(custom_worker *)vis_blueprint_new; | |
2099 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
2100 | |
2101 aworker = create_worker(prog, "Add Field@Blueprint", 3, 1, WORKER_TYPE); | |
2102 aworker->implement_func=(custom_worker *)vis_blueprint_addfield; | |
2103 aworker->input_types[0] = BUILTIN_TYPE_BLUEPRINT; | |
2104 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2105 aworker->input_types[2] = BUILTIN_TYPE_STRING; | |
2106 | |
2107 aworker = create_worker(prog, "Name@Blueprint", 1, 1, WORKER_TYPE); | |
2108 aworker->implement_func=(custom_worker *)vis_blueprint_name; | |
2109 aworker->input_types[0] = BUILTIN_TYPE_BLUEPRINT; | |
2110 | |
2111 aworker = create_worker(prog, "Get Fields@Blueprint", 1, 1, WORKER_TYPE); | |
2112 aworker->implement_func=(custom_worker *)vis_blueprint_getfields; | |
2113 aworker->input_types[0] = BUILTIN_TYPE_BLUEPRINT; | |
2114 | |
2115 aworker = create_worker(prog, "Blueprint Of", 1, 1, WORKER_TYPE); | |
2116 aworker->implement_func=(custom_worker *)vis_get_blueprint; | |
2117 aworker->input_types[0] = ANY_TYPE; | |
2118 | |
2119 aworker = create_worker(prog, "Get Field", 2, 2, WORKER_TYPE); | |
2120 aworker->implement_func=(custom_worker *)vis_get_field; | |
2121 aworker->input_types[0] = ANY_TYPE; | |
2122 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2123 | |
2124 aworker = create_worker(prog, "Set Field", 3, 1, WORKER_TYPE); | |
2125 aworker->implement_func=(custom_worker *)vis_set_field; | |
2126 aworker->input_types[0] = ANY_TYPE; | |
2127 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2128 aworker->input_types[2] = ANY_TYPE; | |
2129 | |
2130 aworker = create_worker(prog, "New Blueprint@Program", 2, 2, WORKER_TYPE); | |
2131 aworker->implement_func=(custom_worker *)vis_program_newblueprint; | |
2132 aworker->input_types[0] = BUILTIN_TYPE_PROGRAM; | |
2133 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2134 | |
2135 #ifdef SYLLABLE | |
2136 create_company(prog, "Checkbox", 2, 0, FALSE); | |
2137 | |
2138 aworker = create_worker(prog, "New@Checkbox", 4, 1, WORKER_TYPE); | |
2139 aworker->implement_func=(custom_worker *)vis_checkbox_new; | |
2140 aworker->input_types[0] = BUILTIN_TYPE_STRING; | |
2141 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
2142 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
2143 aworker->input_types[3] = BUILTIN_TYPE_YESNO; | |
2144 | |
2145 aworker = create_worker(prog, "Set Handler@Checkbox", 3, 1, WORKER_TYPE); | |
2146 aworker->implement_func=(custom_worker *)vis_button_set_handler; | |
2147 aworker->input_types[0] = BUILTIN_TYPE_CHECKBOX; | |
2148 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2149 aworker->input_types[2] = BUILTIN_TYPE_WORKER; | |
2150 | |
2151 create_company(prog, "Dropdown", 4, 0, FALSE); | |
2152 | |
2153 aworker = create_worker(prog, "New@Dropdown", 3, 1, WORKER_TYPE); | |
2154 aworker->implement_func=(custom_worker *)vis_dropdown_new; | |
2155 aworker->input_types[0] = BUILTIN_TYPE_LIST; | |
2156 aworker->input_types[1] = BUILTIN_TYPE_REAL; | |
2157 aworker->input_types[2] = BUILTIN_TYPE_REAL; | |
2158 | |
2159 aworker = create_worker(prog, "Set Handler@Dropdown", 3, 1, WORKER_TYPE); | |
2160 aworker->implement_func=(custom_worker *)vis_button_set_handler; | |
2161 aworker->input_types[0] = BUILTIN_TYPE_DROPDOWN; | |
2162 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2163 aworker->input_types[2] = BUILTIN_TYPE_WORKER; | |
2164 | |
2165 aworker = create_worker(prog, "Set Text@Dropdown", 2, 1, WORKER_TYPE); | |
2166 aworker->implement_func=(custom_worker *)vis_dropdown_settext; | |
2167 aworker->input_types[0] = BUILTIN_TYPE_DROPDOWN; | |
2168 aworker->input_types[1] = BUILTIN_TYPE_STRING; | |
2169 | |
2170 aworker = create_worker(prog, "Select@Dropdown", 2, 1, WORKER_TYPE); | |
2171 aworker->implement_func=(custom_worker *)vis_dropdown_select; | |
2172 aworker->input_types[0] = BUILTIN_TYPE_DROPDOWN; | |
2173 aworker->input_types[1] = BUILTIN_TYPE_WHOLE; | |
2174 #endif | |
2175 | |
2176 /*if(current_def > num_defs) | |
2177 num_defs = current_def; | |
2178 if(current_company > num_companies) | |
2179 num_companies = current_company;*/ | |
2180 } | |
2181 | |
2182 void initworkers(program * prog) | |
2183 { | |
2184 //num_defs=0; | |
2185 //num_companies=0; | |
2186 create_worker(prog, "Main", 0, 0, USER_FLAG | WORKER_TYPE); | |
2187 | |
2188 initpredefworkers(prog); | |
2189 | |
2190 } | |
2191 /* | |
2192 void add_if_ready(int workerNum, worker_instance * instance) | |
2193 { | |
2194 //int i, j, n, old_ready_count; | |
2195 BOOL ready=FALSE; | |
2196 //int paramstore[32]; | |
2197 //int * params = paramstore; | |
2198 DEBUGPUTS("add_if_ready\n"); | |
2199 if(!instance || !instance->def) | |
2200 return; | |
2201 VIS_PROFILE_START(PROF_ADDREADY); | |
2202 DEBUGPRINTF( "add_if_ready on %s\n", instance->def->implement_func->workerlist[workerNum].name); | |
2203 VIS_EnterCriticalSection(instance->workerlist[workerNum].worker_lock); | |
2204 ++instance->workerlist[workerNum].ready_count; | |
2205 if(instance->workerlist[workerNum].ready_count >= (instance->def->implement_func->workerlist[workerNum].num_inputs + (instance->def->implement_func->workerlist[workerNum].null_input ? 1 : 0))) | |
2206 { | |
2207 ready = TRUE; | |
2208 instance->workerlist[workerNum].ready_count = 0; | |
2209 } | |
2210 VIS_LeaveCriticalSection(instance->workerlist[workerNum].worker_lock); | |
2211 if(ready) | |
2212 { | |
2213 DEBUGPRINTF("add_queue on %s\n", instance->def->implement_func->workerlist[workerNum].name); | |
2214 add_queue(workerNum, instance); | |
2215 } | |
2216 VIS_PROFILE_END(PROF_ADDREADY); | |
2217 }*/ | |
2218 #define RETURN_CODE_EXIT 0xABCE1234 | |
2219 #define RETURN_CODE_IDLE 0x00BADFAD | |
2220 #define RETURN_CODE_NORMAL 0xABBAABBA | |
2221 #define RETURN_CODE_PARALLEL 0xC001D00D | |
2222 #define GET_OP1(opcode) ((opcode & 0xF0000000) >> 28) | |
2223 #define GET_OP2(opcode) ((opcode & 0x0F000000) >> 24) | |
2224 #define GET_INST(opcode) ((opcode & 0x00FF0000) >> 16) | |
2225 | |
2226 #define MOVE_INST 0x00 | |
2227 #define ADDREF_INST 0x01 | |
2228 #define RELEASE_INST 0x02 | |
2229 #define LOAD_INST 0x03 | |
2230 #define CALL_INST 0x04 | |
2231 #define CALLB_INST 0x05 | |
2232 #define CALLP_INST 0x06 | |
2233 #define CALLBP_INST 0x07 | |
2234 #define RETURN_INST 0x08 | |
2235 #define BRANCH_INST 0x09 | |
2236 #define BRANCHT_INST 0x0A | |
2237 #define BRANCHF_INST 0x0B | |
2238 #define WAIT_INST 0x0C | |
2239 #define ADD_INST 0x0D | |
2240 #define SUB_INST 0x0E | |
2241 #define SUBR_INST 0x0F | |
2242 #define GREATER_INST 0x10 | |
2243 #define LESSER_INST 0x11 | |
2244 | |
2245 #define REGISTER_BIT 0x8 | |
2246 #define NO_OPERAND 0x7 | |
2247 #define OP_REG_MASK 0x7 | |
2248 #define GET_REGNUM1(opcode) ((opcode & 0x0000FF00) >> 8) | |
2249 #define GET_REGNUM2(opcode) (opcode & 0x000000FF) | |
2250 | |
2251 #define REG_DIRECT 0 | |
2252 #define REG_INDIRECT 1 | |
2253 #define IMMED_8 2 | |
2254 #define IMMED_32 3 | |
2255 #define STACK_8 4 | |
2256 #define REG_REL_32 5 | |
2257 #define PC_REL_8 6 | |
2258 | |
2259 #define STACK_REG 31 | |
2260 #define PC_REG 30 | |
2261 | |
2262 #define OPC(inst, op1, reg1, op2, reg2) ((op1 << 28) | (op2 << 24) | (inst << 16) | ((reg1 & 0xff) << 8) | (reg2 & 0xFF)) | |
2263 | |
2264 //unsigned long test_program[] = | |
2265 //{ | |
2266 // OPC(LOAD_INST, PC_REL_8, 8 /* Hi */, REG_DIRECT, 0), | |
2267 // OPC(CALLB_INST, IMMED_8, 1/* Print */, NO_OPERAND, 0), | |
2268 // OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0), | |
2269 // 26952//Hi | |
2270 //}; | |
2271 | |
2272 unsigned long test_program[] = | |
2273 { | |
2274 //Main: | |
2275 OPC(LOAD_INST, PC_REL_8, 20/* 10 */, REG_DIRECT, 0), | |
2276 OPC(LOAD_INST, PC_REL_8, 20/* 2 */, PC_REL_8, 28), | |
2277 OPC(LOAD_INST, PC_REL_8, 20/* 1 */, PC_REL_8, 28), | |
2278 OPC(CALL_INST, PC_REL_8, 28/* Fib: */, NO_OPERAND, 0), | |
2279 OPC(CALLB_INST, IMMED_8, 1/* Print */, NO_OPERAND, 0), | |
2280 OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0), | |
2281 0x3033,//'30' | |
2282 0x32,//'2' | |
2283 0x31,//'1' | |
2284 0,//2 storage | |
2285 0,//1 storage | |
2286 //Fib: | |
2287 OPC(ADD_INST, IMMED_8, 8, REG_DIRECT, STACK_REG), | |
2288 OPC(MOVE_INST, REG_DIRECT, 0, STACK_8, -4), | |
2289 OPC(ADDREF_INST, REG_INDIRECT, 0, NO_OPERAND, 0), | |
2290 OPC(ADDREF_INST, REG_INDIRECT, 0, NO_OPERAND, 0), | |
2291 OPC(MOVE_INST, PC_REL_8, -28/* 2 */, REG_DIRECT, 1), | |
2292 OPC(ADDREF_INST, REG_INDIRECT, 1, NO_OPERAND, 0), | |
2293 OPC(CALLB_INST, IMMED_8, 8/* < */, NO_OPERAND, 0), | |
2294 OPC(CALLB_INST, IMMED_8, 11/* If */, NO_OPERAND, 0), | |
2295 OPC(BRANCHT_INST, PC_REL_8, 64/* _Base */, REG_DIRECT, 0), | |
2296 | |
2297 OPC(RELEASE_INST, REG_INDIRECT, 1, NO_OPERAND, 0), | |
2298 OPC(MOVE_INST, STACK_8, -4, REG_DIRECT, 0), | |
2299 OPC(MOVE_INST, PC_REL_8, -56/* 2 */, REG_DIRECT, 1), | |
2300 OPC(ADDREF_INST, REG_INDIRECT, 1, NO_OPERAND, 0), | |
2301 OPC(CALLB_INST, IMMED_8, 6/* - */, NO_OPERAND, 0), | |
2302 OPC(CALL_INST, PC_REL_8, -60/* Fib */, NO_OPERAND, 0), | |
2303 OPC(MOVE_INST, REG_DIRECT, 0, STACK_8, -8), | |
2304 OPC(MOVE_INST, STACK_8, -4, REG_DIRECT, 0), | |
2305 OPC(MOVE_INST, PC_REL_8, -76/* 1 */, REG_DIRECT, 1), | |
2306 OPC(ADDREF_INST, REG_INDIRECT, 1, NO_OPERAND, 0), | |
2307 OPC(CALLB_INST, IMMED_8, 6/* - */, NO_OPERAND, 0), | |
2308 OPC(CALL_INST, PC_REL_8, -84/* Fib */, NO_OPERAND, 0), | |
2309 OPC(MOVE_INST, STACK_8, -8, REG_DIRECT, 1), | |
2310 OPC(CALLB_INST, IMMED_8, 5/* + */, NO_OPERAND, 0), | |
2311 OPC(SUBR_INST, IMMED_8, 8, REG_DIRECT, STACK_REG), | |
2312 OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0), | |
2313 //_Base: | |
2314 OPC(RELEASE_INST, REG_INDIRECT, 0, NO_OPERAND, 0), | |
2315 OPC(MOVE_INST, PC_REL_8, -112/* 1 */, REG_DIRECT, 0), | |
2316 OPC(ADDREF_INST, REG_INDIRECT, 0, NO_OPERAND, 0), | |
2317 OPC(SUBR_INST, IMMED_8, 8, REG_DIRECT, STACK_REG), | |
2318 OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0), | |
2319 | |
2320 }; | |
2321 | |
2322 unsigned long * get_effective_address(char op, unsigned short regnum, unsigned long ** pc, unsigned long * registers, unsigned long * immed) | |
2323 { | |
2324 unsigned long * add = NULL; | |
2325 unsigned long work; | |
2326 if(op != NO_OPERAND) | |
2327 { | |
2328 if(op & REGISTER_BIT) | |
2329 add = (unsigned long *)(registers[regnum] + registers[op & OP_REG_MASK]); | |
2330 else | |
2331 { | |
2332 switch(op) | |
2333 { | |
2334 case REG_DIRECT: | |
2335 add = registers + regnum; | |
2336 break; | |
2337 case REG_INDIRECT: | |
2338 add = (unsigned long *) registers[regnum]; | |
2339 break; | |
2340 case IMMED_8: | |
2341 *immed = (char)regnum; | |
2342 add = (unsigned long *)immed; | |
2343 break; | |
2344 case IMMED_32: | |
2345 *immed = *((*pc)++); | |
2346 add = (unsigned long *)immed; | |
2347 break; | |
2348 case STACK_8: | |
2349 work = (char)regnum; | |
2350 add = (unsigned long *)(registers[STACK_REG] + work); | |
2351 break; | |
2352 case REG_REL_32: | |
2353 work = *((*pc)++); | |
2354 add = (unsigned long *)(registers[regnum] + work); | |
2355 break; | |
2356 case PC_REL_8: | |
2357 work = (char)regnum; | |
2358 add = (unsigned long *)(registers[PC_REG] + work); | |
2359 break; | |
2360 default: | |
2361 break; | |
2362 } | |
2363 } | |
2364 } | |
2365 return add; | |
2366 } | |
2367 | |
2368 DWORD WINAPI virtual_processor(unsigned long * program, BOOL main) | |
2369 { | |
2370 int i; | |
2371 unsigned long **pc; | |
2372 unsigned long **stack; | |
2373 unsigned long registers[32]; | |
2374 unsigned long opcode; | |
2375 unsigned long extra, extra2; | |
2376 queue_entry entry; | |
2377 stack_segment initial_stack; | |
2378 stack_segment * current = &initial_stack; | |
2379 char slot_usage[7]; | |
2380 char op1, op2; | |
2381 char inst; | |
2382 unsigned long *add1, *add2; | |
2383 long immed1, immed2; | |
2384 initial_stack.size = MIN_STACK_SIZE; | |
2385 initial_stack.parent = initial_stack.child = NULL; | |
2386 initial_stack.data[0] = main ? RETURN_CODE_EXIT : RETURN_CODE_IDLE; | |
2387 pc = (unsigned long **)(&(registers[PC_REG])); | |
2388 stack = (unsigned long **)(&(registers[STACK_REG])); | |
2389 *pc = program; | |
2390 *stack = (unsigned long *)(initial_stack.data + 1); | |
2391 entry.instance = NULL; | |
2392 entry.worker_num = 0; | |
2393 DEBUGPRINTF("Virtual processor, Program start: %X\n", program); | |
2394 #ifdef ENABLE_PROFILING | |
2395 for(i = 0; i < NUM_PROFS; ++i) | |
2396 { | |
2397 vis_profile_running_total[i] = 0; | |
2398 vis_profile_counts[i] = 0; | |
2399 } | |
2400 VIS_PROFILE_START(PROF_EMPTYFUNC); | |
2401 empty_test(NULL,NULL); | |
2402 VIS_PROFILE_END(PROF_EMPTYFUNC); | |
2403 VIS_PROFILE_START(PROF_NOCODE); | |
2404 VIS_PROFILE_END(PROF_NOCODE); | |
2405 #endif | |
2406 while(execute_active) | |
2407 { | |
2408 VIS_PROFILE_START(PROF_VIRTUAL_DECODE); | |
2409 DEBUGPRINTF("PC: %X\n", *pc); | |
2410 opcode = *((*pc)++); | |
2411 op1 = GET_OP1(opcode); | |
2412 op2 = GET_OP2(opcode); | |
2413 add1 = get_effective_address(op1, GET_REGNUM1(opcode), pc, registers, &immed1); | |
2414 add2 = get_effective_address(op2, GET_REGNUM2(opcode), pc, registers, &immed2); | |
2415 DEBUGPRINTF("Opcode: %X, Instruction: %X, op1 %X, op2 %X\n", opcode, GET_INST(opcode), op1, op2); | |
2416 inst = GET_INST(opcode); | |
2417 VIS_PROFILE_END(PROF_VIRTUAL_DECODE); | |
2418 VIS_PROFILE_START(PROF_VIRTUAL_EXECUTE); | |
2419 switch(inst) | |
2420 { | |
2421 case MOVE_INST: | |
2422 *add2 = *add1; | |
2423 break; | |
2424 case ADDREF_INST: | |
2425 add_ref((datum *)add1); | |
2426 break; | |
2427 case RELEASE_INST: | |
2428 release_ref((datum *)add1); | |
2429 break; | |
2430 /* | |
2431 Temporarily commented out until multiple program support is finished | |
2432 case LOAD_INST: | |
2433 *add2 = (long)get_constant((char *)add1, -1); | |
2434 break; | |
2435 */ | |
2436 case CALL_INST: | |
2437 *((*stack)++) = (unsigned long)*pc; | |
2438 *((*stack)++) = RETURN_CODE_NORMAL; | |
2439 *pc = add1; | |
2440 break; | |
2441 /* | |
2442 Temporarily commented out until multiple program support is finished | |
2443 case CALLB_INST: | |
2444 //TODO: Needs to be made 100% correct | |
2445 DEBUGPRINTF("Calling builtin: %s\n", deflist[*add1].name); | |
2446 execute_def(deflist + *add1, entry, (datum **)registers, NULL); | |
2447 break;*/ | |
2448 case CALLP_INST: | |
2449 //TODO Implement me | |
2450 break; | |
2451 case CALLBP_INST: | |
2452 //TODO Implement me | |
2453 break; | |
2454 case RETURN_INST: | |
2455 switch(*(--(*stack))) | |
2456 { | |
2457 case RETURN_CODE_EXIT: | |
2458 execute_active = FALSE; | |
2459 break; | |
2460 case RETURN_CODE_IDLE: | |
2461 //TODO: Implement me | |
2462 break; | |
2463 case RETURN_CODE_NORMAL: | |
2464 *pc = (unsigned long *)*(--(*stack)); | |
2465 break; | |
2466 default: | |
2467 break; | |
2468 } | |
2469 break; | |
2470 case BRANCH_INST: | |
2471 *pc = add1; | |
2472 break; | |
2473 case BRANCHT_INST: | |
2474 if(*add2) | |
2475 *pc = add1; | |
2476 break; | |
2477 case BRANCHF_INST: | |
2478 if(!*add2) | |
2479 *pc = add1; | |
2480 break; | |
2481 case WAIT_INST: | |
2482 //TODO: Implement Me | |
2483 break; | |
2484 case ADD_INST: | |
2485 *add2 = *add1 + *add2; | |
2486 break; | |
2487 case SUB_INST: | |
2488 *add2 = *add1 - *add2; | |
2489 break; | |
2490 case SUBR_INST: | |
2491 *add2 = *add2 - *add1; | |
2492 break; | |
2493 case GREATER_INST: | |
2494 *add2 = *add1 > *add2; | |
2495 break; | |
2496 case LESSER_INST: | |
2497 *add2 = *add1 < *add2; | |
2498 break; | |
2499 default: | |
2500 break; | |
2501 } | |
2502 VIS_PROFILE_END(PROF_VIRTUAL_EXECUTE); | |
2503 } | |
2504 #ifdef ENABLE_PROFILING | |
2505 for(i = 0; i < NUM_PROFS; ++i) | |
2506 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])); | |
2507 #endif | |
2508 return 0; | |
2509 } | |
2510 | |
2511 void test_virtual() | |
2512 { | |
2513 // int i,j,k; | |
2514 program * prog = new_program(START_DEF_STORAGE, START_COMP_STORAGE); | |
2515 initpredefworkers(prog); | |
2516 init_sync_primitives(); | |
2517 init_datum_storage(); | |
2518 //TODO Uncomment me | |
2519 // init_global_storage(); | |
2520 execute_active = TRUE; | |
2521 /* for(i = MOVE_INST; i <= LESSER_INST; ++i) | |
2522 { | |
2523 for(j = 0; j < 0x10; ++j) | |
2524 { | |
2525 for(k = 0; k < 0x10; ++k) | |
2526 { | |
2527 DEBUGPRINTF("i: %X, j: %X, k: %X, OPC: %X\n", i, j, k, OPC(i, j, j, k, k)); | |
2528 } | |
2529 } | |
2530 }*/ | |
2531 virtual_processor(test_program, TRUE); | |
2532 } | |
2533 | |
2534 DWORD WINAPI worker_thread(LPVOID param) | |
2535 { | |
2536 queue_entry aworker; | |
2537 int temp_queue_len; | |
2538 while(execute_active) | |
2539 { | |
2540 VIS_PROFILE_START(PROF_WORKER_THREAD); | |
2541 #ifdef NINTENDO_DS | |
2542 if(irq_queue_count > 0) | |
2543 run_queued_irqs(); | |
2544 #endif | |
2545 //DEBUGPUTS("Before WaitForSingleObect\n"); | |
2546 /*VIS_EnterCriticalSection(worker_queue_lock); | |
2547 temp_queue_len = queue_len; | |
2548 VIS_LeaveCriticalSection(worker_queue_lock);*/ | |
2549 //DEBUGPUTS("After WaitForSingleObject\n"); | |
2550 aworker = get_queue(); | |
2551 //DEBUGPUTS("After get_queue()\n"); | |
2552 //while(execute_active && aworker.worker_num < 0)//temp_queue_len == 0 && execute_active) | |
2553 //{ | |
2554 // VIS_WaitEvent(queue_add_event); | |
2555 // aworker = get_queue(); | |
2556 /*#if COMPILE_THREADS > 0 | |
2557 #ifdef WIN32 | |
2558 Sleep(0); | |
2559 #else | |
2560 sleep(0); | |
2561 #endif | |
2562 #endif | |
2563 VIS_EnterCriticalSection(worker_queue_lock); | |
2564 temp_queue_len = queue_len; | |
2565 VIS_LeaveCriticalSection(worker_queue_lock);*/ | |
2566 //} | |
2567 | |
2568 if(aworker.worker_num >= 0) | |
2569 { | |
2570 //DEBUGPUTS("Before EnterCriticalSection\n"); | |
2571 | |
2572 /* VIS_EnterCriticalSection(worker_queue_lock); | |
2573 if(queue_len > 0) | |
2574 { | |
2575 DEBUGPUTS("SetEvent\n"); | |
2576 VIS_SetEvent(queue_add_event); | |
2577 } | |
2578 VIS_LeaveCriticalSection(worker_queue_lock);*/ | |
2579 DEBUGPRINTF( "\nExecuting: %s<%d>, Instance: %X\n", aworker.instance->def->implement_func->workerlist[aworker.worker_num].name,aworker.worker_num,aworker.instance); | |
2580 | |
2581 if(process_worker(aworker) == 0) | |
2582 { | |
2583 //worker_complete(aworker); | |
2584 cleanup_check(aworker); | |
2585 //DEBUGPUTS("After cleanup_check\n"); | |
2586 | |
2587 } | |
2588 | |
2589 } | |
2590 VIS_PROFILE_END(PROF_WORKER_THREAD); | |
2591 } | |
2592 VIS_SetEvent(queue_add_event); | |
2593 return 0; | |
2594 } | |
2595 | |
2596 int set_comp_room(datum ** params, int room_index, queue_entry * entry, program * prog) | |
2597 { | |
2598 int i; | |
2599 char * data; | |
2600 //DEBUGPRINTF("params[0]->ref_count: %d\n", params[0]->ref_count); | |
2601 params[0] = copy_datum(params[0], 0); | |
2602 data = ((char *)(params[0]->c.generic.data) + (int)params[0]->company->room_list[room_index].set_func); | |
2603 DEBUGPRINTF("Set comp room: c.generic.data = %X, +get_func = %X\n", params[0]->c.generic.data, data); | |
2604 //TODO: input conversion | |
2605 switch(params[0]->company->room_list[room_index].get_func_type) | |
2606 { | |
2607 case ROOM_BYTE: | |
2608 *data = params[1]->c.integers.num_a; | |
2609 release_ref(params[1]); | |
2610 break; | |
2611 case ROOM_SHORT: | |
2612 *((short *)data) = params[1]->c.integers.num_a; | |
2613 release_ref(params[1]); | |
2614 break; | |
2615 case ROOM_LONG: | |
2616 *((long *)data) = params[1]->c.integers.num_a; | |
2617 release_ref(params[1]); | |
2618 break; | |
2619 case ROOM_SINGLE: | |
2620 *((float *)data) = params[1]->c.real; | |
2621 release_ref(params[1]); | |
2622 break; | |
2623 case ROOM_DOUBLE: | |
2624 *((double *)data) = params[1]->c.real; | |
2625 release_ref(params[1]); | |
2626 break; | |
2627 case ROOM_VIS_REF: | |
2628 release_ref(*((datum **)data)); | |
2629 *((datum **)data) = params[1]; | |
2630 break; | |
2631 case ROOM_CSTRING: //not implemented | |
2632 case ROOM_CSTRING_STRUCT: | |
2633 case ROOM_PSTRING: | |
2634 case ROOM_PSTRING_STRUCT: | |
2635 case ROOM_WORKER://not implemented | |
2636 case ROOM_VIS_OBJECT://not implemented | |
2637 default: | |
2638 release_ref(params[0]); | |
2639 release_ref(params[1]); | |
2640 params[0] = params[1] = NULL; | |
2641 puts("unimplemented company room type\n"); | |
2642 break; | |
2643 } | |
2644 return 0; | |
2645 } | |
2646 | |
2647 int set_comp_room_by_name(datum ** company, char * name, int * room_index_ret, queue_entry * entry, program * prog) | |
2648 { | |
2649 int i; | |
2650 for (i = 0; i < company[0]->company->num_rooms; ++i) | |
2651 if(!strcmp(name,company[0]->company->room_list[i].name)) | |
2652 { | |
2653 if(room_index_ret) | |
2654 *room_index_ret = i; | |
2655 return set_comp_room(company, i, entry, prog); | |
2656 } | |
2657 if(room_index_ret) | |
2658 *room_index_ret = -1; | |
2659 return -1; | |
2660 } | |
2661 | |
2662 int get_comp_room(datum ** company, int room_index, queue_entry * entry, program * prog) | |
2663 { | |
2664 int i; | |
2665 datum * out; | |
2666 queue_entry empty; | |
2667 char * data = ((char *)(company[0]->c.generic.data) + (int)company[0]->company->room_list[room_index].get_func); | |
2668 company[1] = NULL; | |
2669 DEBUGPRINTF("Get comp room: c.generic.data = %X, +get_func = %X\n", company[0]->c.generic.data, data); | |
2670 switch(company[0]->company->room_list[room_index].get_func_type) | |
2671 { | |
2672 case ROOM_BYTE: | |
2673 out = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, prog); | |
2674 out->c.integers.num_a = *data; | |
2675 break; | |
2676 case ROOM_SHORT: | |
2677 out = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, prog); | |
2678 out->c.integers.num_a = *((short *)data); | |
2679 break; | |
2680 case ROOM_LONG: | |
2681 out = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, prog); | |
2682 out->c.integers.num_a = *((long *)data); | |
2683 break; | |
2684 case ROOM_SINGLE: | |
2685 out = new_datum(BUILTIN_TYPE_REAL, 3, 0, prog); | |
2686 out->c.real = *((float *)data); | |
2687 break; | |
2688 case ROOM_DOUBLE: | |
2689 out = new_datum(BUILTIN_TYPE_REAL, 3, 0, prog); | |
2690 out->c.real = *((double *)data); | |
2691 break; | |
2692 case ROOM_CSTRING: | |
2693 data = *((char **)data); | |
2694 case ROOM_CSTRING_STRUCT: | |
2695 out = new_datum(BUILTIN_TYPE_STRING, 1, strlen(data)+1, prog); | |
2696 strcpy(out->c.generic.data, data); | |
2697 break; | |
2698 case ROOM_PSTRING: | |
2699 data = *((char **)data); | |
2700 case ROOM_PSTRING_STRUCT: | |
2701 out = new_datum(BUILTIN_TYPE_STRING, 1, *((unsigned char *)data), prog); | |
2702 memcpy(out->c.generic.data, data, *((unsigned char *)data)); | |
2703 ((char *)out->c.generic.data)[*((unsigned char *)data)] = '\0'; | |
2704 break; | |
2705 case ROOM_VIS_REF: | |
2706 out = add_ref(*((datum **)data)); | |
2707 if(!out) { | |
2708 company[1] = company[0]; | |
2709 company[0] = NULL; | |
2710 } | |
2711 break; | |
2712 case ROOM_WORKER: | |
2713 if(entry) | |
2714 return execute_def((worker_def *)(company[0]->company->room_list[room_index].get_func), *entry, company, sub_callback); | |
2715 else | |
2716 { | |
2717 empty.instance = NULL; | |
2718 empty.worker_num = -1; | |
2719 return execute_def((worker_def *)(company[0]->company->room_list[room_index].get_func), empty, company, sub_callback); | |
2720 } | |
2721 case ROOM_VIS_OBJECT://not implemented | |
2722 default: | |
2723 out = NULL; | |
2724 puts("unimplemented company room type\n"); | |
2725 break; | |
2726 } | |
2727 release_ref(company[0]); | |
2728 company[0] = out; | |
2729 return 0; | |
2730 } | |
2731 | |
2732 int get_comp_room_by_name(datum ** company, char * name, int * room_index_ret, queue_entry * entry, program * prog) | |
2733 { | |
2734 int i; | |
2735 for (i = 0; i < company[0]->company->num_rooms; ++i) | |
2736 if(!strcmp(name,company[0]->company->room_list[i].name)) | |
2737 { | |
2738 if(room_index_ret) | |
2739 *room_index_ret = i; | |
2740 return get_comp_room(company, i, entry, prog); | |
2741 } | |
2742 if(room_index_ret) | |
2743 *room_index_ret = -1; | |
2744 return -1; | |
2745 } | |
2746 | |
2747 datum * literal_string(char * value, int len, program * prog) | |
2748 { | |
2749 char literalchar; | |
2750 BOOL literal; | |
2751 int i, bufpos, lenstr; | |
2752 datum * returnval; | |
2753 | |
2754 if(len < 0) { | |
2755 len = strlen(value); | |
2756 } | |
2757 | |
2758 literal = FALSE; | |
2759 lenstr = 0; | |
2760 for(i = 0; i < len; ++i) | |
2761 if(literal) | |
2762 literal = FALSE; | |
2763 else | |
2764 { | |
2765 ++lenstr; | |
2766 if(value[i] == '\\') | |
2767 literal = TRUE; | |
2768 } | |
2769 //DEBUGPRINTF("Allocating %d bytes for string constant\n", lenstr+1); | |
2770 returnval = new_datum(BUILTIN_TYPE_STRING, 1, lenstr+1, prog); | |
2771 bufpos = 0; | |
2772 for(i = 0; i < len; ++i) | |
2773 { | |
2774 if(literal) | |
2775 { | |
2776 literal = FALSE; | |
2777 switch(value[i]) | |
2778 { | |
2779 case 'n': //newline | |
2780 literalchar = '\n'; | |
2781 break; | |
2782 case 'r': //carriage return | |
2783 literalchar = '\r'; | |
2784 break; | |
2785 case 't': // tab | |
2786 literalchar = '\t'; | |
2787 break; | |
2788 case '0': //NULL | |
2789 literalchar = '\0'; | |
2790 break; | |
2791 default: | |
2792 literalchar = value[i]; | |
2793 break; | |
2794 } | |
2795 ((char *)returnval->c.generic.data)[bufpos++] = literalchar; | |
2796 } | |
2797 else | |
2798 { | |
2799 if(value[i] == '\\') | |
2800 literal = TRUE; | |
2801 else | |
2802 { | |
2803 ((char *)returnval->c.generic.data)[bufpos++] = value[i]; | |
2804 } | |
2805 } | |
2806 } | |
2807 //DEBUGPRINTF("bufpos: %d\n", bufpos); | |
2808 ((char *)returnval->c.generic.data)[bufpos] = '\0'; | |
2809 DEBUGPUTS("Constant Type: String\n"); | |
2810 return returnval; | |
2811 } | |
2812 | |
2813 datum * get_constant(char * value, int len, program * prog) | |
2814 { | |
2815 datum * params[2]; | |
2816 datum * returnval; | |
2817 int i = 0,bufpos; | |
2818 int start; | |
2819 int lenstr; | |
2820 int leftcurly; | |
2821 int dotcount = 0; | |
2822 char literalchar; | |
2823 unsigned short const_type = ANY_TYPE; | |
2824 BOOL literal; | |
2825 if((len == 3 && memcmp(value, "Yes", len) == 0) || (len < 0 && strcmp(value, "Yes") == 0)) | |
2826 { | |
2827 DEBUGPUTS("Constnat: Yes\n"); | |
2828 returnval = new_datum(BUILTIN_TYPE_YESNO, 2, 0, prog); | |
2829 returnval->c.integers.num_a = 1; | |
2830 DEBUGPRINTF("Company: %s, integers.num_a: %d\n", returnval->company->name, returnval->c.integers.num_a); | |
2831 return returnval; | |
2832 } | |
2833 else if((len == 2 && memcmp(value, "No", len) == 0) || (len < 0 && strcmp(value, "No") == 0)) | |
2834 { | |
2835 DEBUGPUTS("Constant: No\n"); | |
2836 returnval = new_datum(BUILTIN_TYPE_YESNO, 2, 0, prog); | |
2837 returnval->c.integers.num_a = 0; | |
2838 DEBUGPRINTF("Company: %s, integers.num_a: %d\n", returnval->company->name, returnval->c.integers.num_a); | |
2839 return returnval; | |
2840 } | |
2841 if(value[0] == '{') | |
2842 { | |
2843 DEBUGPUTS("Constant type: List"); | |
2844 params[0] = create_list(prog); | |
2845 i = start = 1; | |
2846 literal = FALSE; | |
2847 leftcurly = 0; | |
2848 for(;value[i] != 0 && (len < 0 || i < len); ++i) | |
2849 { | |
2850 if(literal) | |
2851 literal = FALSE; | |
2852 else | |
2853 { | |
2854 if(value[i] == '\\') | |
2855 literal = TRUE; | |
2856 else if(value[i] == '}') | |
2857 if(leftcurly) | |
2858 --leftcurly; | |
2859 else | |
2860 break; | |
2861 else if(value[i] == '{') | |
2862 ++leftcurly; | |
2863 else if(value[i] == ',' && !leftcurly) | |
2864 { | |
2865 params[1] = get_constant(value+start, i-start, prog); | |
2866 vis_list_append(params, NULL); | |
2867 start = i+1; | |
2868 } | |
2869 } | |
2870 } | |
2871 params[1]= get_constant(value+start, i-start, prog); | |
2872 vis_list_append(params, NULL); | |
2873 returnval = params[0]; | |
2874 } | |
2875 else if(value[0] == '"') | |
2876 { | |
2877 if(len < 0) { | |
2878 len = strlen(value); | |
2879 } | |
2880 len -= 2; | |
2881 returnval = literal_string(value+1, len, prog); | |
2882 | |
2883 } | |
2884 else | |
2885 { | |
2886 while(value[i] != 0 && (len < 0 || i < len)) | |
2887 { | |
2888 if(value[i] >= '0' && value[i] <= '9') | |
2889 { | |
2890 if(const_type == ANY_TYPE) | |
2891 const_type = BUILTIN_TYPE_WHOLE; | |
2892 } | |
2893 else if(value[i] == '.') | |
2894 { | |
2895 if(dotcount) | |
2896 { | |
2897 const_type = BUILTIN_TYPE_STRING; | |
2898 } | |
2899 else | |
2900 { | |
2901 ++dotcount; | |
2902 if(const_type == BUILTIN_TYPE_WHOLE) | |
2903 const_type = BUILTIN_TYPE_REAL; | |
2904 } | |
2905 } | |
2906 else | |
2907 { | |
2908 //DEBUGPRINTF("Current character: %c resulted in String\n", value[i]); | |
2909 const_type = BUILTIN_TYPE_STRING; | |
2910 break; | |
2911 } | |
2912 ++i; | |
2913 } | |
2914 | |
2915 if(const_type == BUILTIN_TYPE_WHOLE) | |
2916 { | |
2917 returnval = new_datum(const_type, 2, 0, prog); | |
2918 returnval->c.integers.num_a = atol(value); | |
2919 DEBUGPUTS("Constant Type: Whole Number\n"); | |
2920 } | |
2921 else if(const_type == BUILTIN_TYPE_REAL) | |
2922 { | |
2923 returnval = new_datum(const_type, 3, 0, prog); | |
2924 returnval->c.real = atof(value); | |
2925 DEBUGPUTS("Constant Type: Real Number\n"); | |
2926 } | |
2927 else | |
2928 { | |
2929 /* literal = FALSE; | |
2930 lenstr = 0; | |
2931 for(i = 0; (i < len || len < 0) && value[i] != 0; ++i) | |
2932 if(literal) | |
2933 literal = FALSE; | |
2934 else | |
2935 { | |
2936 ++lenstr; | |
2937 if(value[i] == '\\') | |
2938 literal = TRUE; | |
2939 } | |
2940 DEBUGPRINTF("Allocating %d bytes for string constant\n", lenstr+1); | |
2941 returnval = new_datum(BUILTIN_TYPE_STRING, 1, lenstr+1, prog); | |
2942 bufpos = 0; | |
2943 for(i = 0; (i < len || len < 0) && value[i] != 0; ++i) | |
2944 { | |
2945 DEBUGPRINTF("bufpos: %d\n", bufpos); | |
2946 if(literal) | |
2947 { | |
2948 literal = FALSE; | |
2949 switch(value[i]) | |
2950 { | |
2951 case 'n': //newline | |
2952 literalchar = '\n'; | |
2953 break; | |
2954 case 'r': //carriage return | |
2955 literalchar = '\r'; | |
2956 break; | |
2957 case 't': // tab | |
2958 literalchar = '\t'; | |
2959 break; | |
2960 case '0': //NULL | |
2961 literalchar = '\0'; | |
2962 break; | |
2963 default: | |
2964 literalchar = value[i]; | |
2965 break; | |
2966 } | |
2967 ((char *)returnval->c.generic.data)[bufpos++] = literalchar; | |
2968 } | |
2969 else | |
2970 { | |
2971 if(value[i] == '\\') | |
2972 literal = TRUE; | |
2973 else | |
2974 { | |
2975 ((char *)returnval->c.generic.data)[bufpos++] = value[i]; | |
2976 } | |
2977 } | |
2978 } | |
2979 DEBUGPRINTF("bufpos: %d\n", bufpos); | |
2980 ((char *)returnval->c.generic.data)[bufpos] = '\0'; | |
2981 DEBUGPUTS("Constant Type: String\n"); */ | |
2982 returnval = literal_string(value, len, prog); | |
2983 } | |
2984 } | |
2985 return returnval; | |
2986 } | |
2987 | |
2988 int execute_def(worker_def * process_def, queue_entry worker_entry, datum ** params, instance_callback callback) | |
2989 { | |
2990 return execute_def_type(process_def, worker_entry, params, callback, NULL, WORKER); | |
2991 } | |
2992 int execute_def_data(worker_def * process_def, queue_entry worker_entry, datum ** params, instance_callback callback, void * data) | |
2993 { | |
2994 return execute_def_type(process_def, worker_entry, params, callback, data, WORKER); | |
2995 } | |
2996 | |
2997 int execute_def_type(worker_def * process_def, queue_entry worker_entry, datum ** params, instance_callback callback, void * data, int type) | |
2998 { | |
2999 int returnval, i; | |
3000 worker_instance * stack_instance; | |
3001 worker_def *temp_def, *converter; | |
3002 worker_def *parent_def = worker_entry.instance->def; | |
3003 unsigned short magic_cache_type; | |
3004 #ifdef USER_PROFILE | |
3005 LARGE_INTEGER start, end, duration; | |
3006 #endif | |
3007 VIS_PROFILE_START(PROF_PREP_MAGIC); | |
3008 if((process_def->type & TYPE_MASK) == MAGIC_TYPE) | |
3009 { | |
3010 DEBUGPRINTF( "Magic method: %s\n", process_def->name); | |
3011 if(!params || !params[0]) | |
3012 { | |
3013 ERRORPRINTF("Error: null first parmeter or null parameter array for worker %s\n", process_def->name); | |
3014 print_stack_trace(worker_entry.instance); | |
3015 execute_active = FALSE; | |
3016 return -1; | |
3017 } | |
3018 VIS_EnterCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock); | |
3019 temp_def = parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_implement; | |
3020 magic_cache_type = parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_type; | |
3021 VIS_LeaveCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock); | |
3022 if(!temp_def || magic_cache_type != params[0]->company->type_id) | |
3023 { | |
3024 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); | |
3025 temp_def = find_method(params[0]->company->type_id,process_def->name, process_def->num_inputs, process_def->program); | |
3026 if(!temp_def) | |
3027 { | |
3028 for(i = 1; i < process_def->program->num_companies; ++i) | |
3029 { | |
3030 temp_def = find_method(i,process_def->name, process_def->num_inputs, process_def->program); | |
3031 if(temp_def) | |
3032 { | |
3033 converter = find_converter_method(temp_def->input_types[0], params[0]->company->type_id, process_def->program); | |
3034 if(converter) | |
3035 { | |
3036 ((worker_impl)converter->implement_func)(params, &worker_entry); | |
3037 break; | |
3038 } | |
3039 else | |
3040 { | |
3041 //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); | |
3042 //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); | |
3043 temp_def = NULL; | |
3044 } | |
3045 } | |
3046 } | |
3047 } | |
3048 if(temp_def) | |
3049 { | |
3050 VIS_EnterCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock); | |
3051 parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_implement = temp_def; | |
3052 parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_type = temp_def->input_types[0]; | |
3053 VIS_LeaveCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock); | |
3054 } | |
3055 else | |
3056 { | |
3057 ERRORPRINTF("Error: Company %s doesn't implement worker %s. It implements the following:\n", params[0]->company->name, process_def->name); | |
3058 for(i = 0; i < params[0]->company->num_methods; ++i) | |
3059 { | |
3060 ERRORPRINTF("%s\n", params[0]->company->methodlist[i]->name); | |
3061 } | |
3062 print_stack_trace(worker_entry.instance); | |
3063 } | |
3064 } | |
3065 process_def = temp_def; | |
3066 } | |
3067 VIS_PROFILE_END(PROF_PREP_MAGIC); | |
3068 if(!process_def) | |
3069 { | |
3070 //DEBUGPUTS("Invalid def\n"); | |
3071 VIS_PROFILE_END(PROF_EXECUTE_WORKER); | |
3072 execute_active = FALSE; | |
3073 return -2; | |
3074 } | |
3075 | |
3076 VIS_PROFILE_START(PROF_CONVERT_INPUTS); | |
3077 for(i = 0; i < process_def->num_inputs; ++i) | |
3078 { | |
3079 DEBUGPRINTF("params[%d] = %X\n", i, params[i]); | |
3080 if(process_def->input_types[i] != ANY_TYPE && process_def->input_types[i] != params[i]->company->type_id) | |
3081 { | |
3082 DEBUGPRINTF("Input %d needs conversion from %d to %d\n", i, params[i]->company->type_id, process_def->input_types[i]); | |
3083 converter = find_converter_method(process_def->input_types[i], params[i]->company->type_id, process_def->program); | |
3084 if(!converter) | |
3085 { | |
3086 if(worker_entry.instance) { | |
3087 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); | |
3088 } else { | |
3089 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); | |
3090 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); | |
3091 } | |
3092 execute_active = FALSE; | |
3093 VIS_PROFILE_END(PROF_PROCESS_WORKER); | |
3094 return -3; | |
3095 } | |
3096 ((worker_impl)(converter->implement_func))(params+i, &worker_entry); | |
3097 } | |
3098 } | |
3099 VIS_PROFILE_END(PROF_CONVERT_INPUTS); | |
3100 | |
3101 if(process_def->type & USER_FLAG) | |
3102 { | |
3103 VIS_PROFILE_START(PROF_EXECUTE_CUSTOM); | |
3104 // | |
3105 init_custom_worker_type(worker_entry.worker_num, worker_entry.instance, process_def, callback, data, params, type); | |
3106 VIS_PROFILE_END(PROF_EXECUTE_CUSTOM); | |
3107 VIS_PROFILE_END(PROF_PROCESS_WORKER); | |
3108 VIS_PROFILE_END(PROF_EXECUTE_WORKER); | |
3109 return 1; | |
3110 } | |
3111 else | |
3112 { | |
3113 VIS_PROFILE_START(PROF_EXECUTE_BUILTIN); | |
3114 //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); | |
3115 #ifdef USER_PROFILE | |
3116 QueryPerformanceCounter(&start); | |
3117 #endif | |
3118 returnval = ((worker_impl)(process_def->implement_func))(params, &worker_entry); | |
3119 #ifdef USER_PROFILE | |
3120 if(!returnval) | |
3121 { | |
3122 QueryPerformanceCounter(&end); | |
3123 duration.QuadPart = end.QuadPart - start.QuadPart; | |
3124 VIS_EnterCriticalSection(process_def->lock); | |
3125 process_def->total.QuadPart += duration.QuadPart; | |
3126 ++process_def->count; | |
3127 if(duration.QuadPart > process_def->worst.QuadPart) | |
3128 process_def->worst.QuadPart = duration.QuadPart; | |
3129 VIS_LeaveCriticalSection(process_def->lock); | |
3130 } | |
3131 #endif | |
3132 //DEBUGPUTS("Builtin worker returned\n"); | |
3133 VIS_PROFILE_END(PROF_EXECUTE_BUILTIN); | |
3134 return returnval; | |
3135 } | |
3136 } | |
3137 | |
3138 void wait_callback(worker_instance * caller_instance, int caller_workerenum, worker_instance * done_instance, void * data) | |
3139 { | |
3140 int i; | |
3141 def_done * done = (def_done *)data; | |
3142 //DEBUGPUTS("begin wait_callback\n"); | |
3143 for(i = 0; i < done_instance->def->num_outputs; ++i) | |
3144 done->params[i] = NULL; | |
3145 for(i = 0; i < done_instance->def->implement_func->num_workers; ++i) | |
3146 { | |
3147 if(done_instance->def->implement_func->workerlist[i].type == 4) | |
3148 { | |
3149 if(!(done->params[done_instance->def->implement_func->workerlist[i].io_num])) | |
3150 { | |
3151 done->params[done_instance->def->implement_func->workerlist[i].io_num] = done_instance->workerlist[i].value; | |
3152 done_instance->workerlist[i].value = NULL; | |
3153 } | |
3154 } | |
3155 } | |
3156 //DEBUGPUTS("Before EnterCritical\n"); | |
3157 VIS_EnterCriticalSection(done->lock); | |
3158 done->done_flag = TRUE; | |
3159 VIS_LeaveCriticalSection(done->lock); | |
3160 //DEBUGPUTS("After EnterCritical\n"); | |
3161 } | |
3162 | |
3163 | |
3164 BOOL execute_def_wait(worker_def * def, datum ** params) | |
3165 { | |
3166 int val; | |
3167 def_done done; | |
3168 queue_entry entry; | |
3169 entry.worker_num = 0; | |
3170 entry.instance = NULL; | |
3171 VIS_InitializeCriticalSection(done.lock); | |
3172 done.done_flag = FALSE; | |
3173 done.params = params; | |
3174 val = execute_def_data(def, entry, params, wait_callback, &done); | |
3175 if(val == 0) | |
3176 return TRUE; | |
3177 else if (val < 0) | |
3178 return FALSE; | |
3179 while(1) | |
3180 { | |
3181 VIS_EnterCriticalSection(done.lock); | |
3182 if(done.done_flag) | |
3183 { | |
3184 VIS_DeleteCriticalSection(done.lock); | |
3185 break; | |
3186 } | |
3187 VIS_LeaveCriticalSection(done.lock); | |
3188 #if COMPILE_THREADS > 1 | |
3189 #ifdef WIN32 | |
3190 Sleep(0); | |
3191 #else | |
3192 sleep(0); | |
3193 #endif | |
3194 #endif | |
3195 } | |
3196 return TRUE; | |
3197 } | |
3198 | |
3199 int process_worker(queue_entry worker_entry) | |
3200 { | |
3201 //datum * paramstore[32]; | |
3202 datum ** params;// = paramstore; | |
3203 int i, j, start=0; | |
3204 global_store * store; | |
3205 char * varname; | |
3206 datum * varname_dat; | |
3207 datum * tempvalindex, *todelete; | |
3208 int got_params=0; | |
3209 int aworker = worker_entry.worker_num; | |
3210 worker_instance * instance = worker_entry.instance; | |
3211 worker_def * def = instance->def; | |
3212 worker_def * process_def; | |
3213 worker_def * temp_def; | |
3214 worker_def * converter; | |
3215 int returnval = 0; | |
3216 short const_type; | |
3217 char * last; | |
3218 | |
3219 VIS_PROFILE_START(PROF_PROCESS_WORKER); | |
3220 | |
3221 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); | |
3222 /*VIS_EnterCriticalSection(instance->workerlist[aworker].worker_lock); | |
3223 for(i = 0; i < def->implement_func->workerlist[aworker].num_inputs; ++i) | |
3224 { | |
3225 params[i] = instance->workerlist[aworker].params[i+1]; | |
3226 DEBUGPRINTF("params[%d] = %X\n", i, params[i]); | |
3227 instance->workerlist[aworker].params[i+1] = NULL; | |
3228 }*/ | |
3229 if(def->implement_func->workerlist[aworker].null_input) | |
3230 { | |
3231 //DEBUGPUTS("About to call release_ref\n"); | |
3232 release_ref(instance->workerlist[aworker].params[0]); | |
3233 instance->workerlist[aworker].params[0] = NULL; | |
3234 } | |
3235 //VIS_LeaveCriticalSection(instance->workerlist[aworker].worker_lock); | |
3236 //DEBUGPRINTF("Param check complete. returnval: %d, start: %d\n", returnval, start); | |
3237 params = instance->workerlist[aworker].params+1; | |
3238 | |
3239 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 | |
3240 { | |
3241 VIS_PROFILE_START(PROF_EXECUTE_WORKER); | |
3242 //DEBUGPUTS("Worker\n"); | |
3243 process_def = (worker_def *)(def->implement_func->workerlist[aworker].value_index); | |
3244 //DEBUGPUTS("Got process_def\n"); | |
3245 DEBUGPRINTF("process_def->type: %X, type & TYPE_MASK: %X\n", process_def->type, (process_def->type & TYPE_MASK)); | |
3246 | |
3247 returnval = execute_def_type(process_def, worker_entry, params, sub_callback, NULL, def->implement_func->workerlist[aworker].type); | |
3248 DEBUGPRINTF("execute_def returned %d\n", returnval); | |
3249 if(returnval != 0) | |
3250 { | |
3251 VIS_PROFILE_END(PROF_PROCESS_WORKER); | |
3252 VIS_PROFILE_END(PROF_EXECUTE_WORKER); | |
3253 return returnval; | |
3254 } | |
3255 //DEBUGPRINTF("params[0] after execute_def: %X\n", params[0]); | |
3256 | |
3257 //DEBUGPUTS("Before process_outputs\n"); | |
3258 | |
3259 process_outputs(params, aworker, instance); | |
3260 //DEBUGPUTS("After process_outputs\n"); | |
3261 | |
3262 VIS_PROFILE_END(PROF_EXECUTE_WORKER); | |
3263 | |
3264 } | |
3265 else if(def->implement_func->workerlist[aworker].type == GET_GLOBAL) | |
3266 { | |
3267 varname = def->implement_func->workerlist[aworker].name + def->implement_func->workerlist[aworker].io_num; | |
3268 varname_dat = make_string(varname, -1, def->program); | |
3269 if(def->implement_func->workerlist[aworker].value_index < 0) | |
3270 { | |
3271 for(i = 0; i < instance->trans->num_stores; ++i) | |
3272 { | |
3273 VIS_EnterCriticalSection(instance->trans->stores[i].lock); | |
3274 params[0] = add_ref(instance->trans->stores[i].instance_data); | |
3275 VIS_LeaveCriticalSection(instance->trans->stores[i].lock); | |
3276 params[1] = add_ref(varname_dat); | |
3277 vis_dict_index(params, NULL); | |
3278 | |
3279 if(params[0]) | |
3280 { | |
3281 def->implement_func->workerlist[aworker].value_index = i; | |
3282 break; | |
3283 } | |
3284 } | |
3285 if(def->implement_func->workerlist[aworker].value_index < 0) | |
3286 { | |
3287 printf("Error: Variable %s not found in any global stores used by worker %s\n", varname, def->name); | |
3288 DEBUGPRINTF("Error: Variable %s not found in any global stores used by worker %s\n", varname, def->name); | |
3289 execute_active = FALSE; | |
3290 return -1; | |
3291 } | |
3292 } | |
3293 else | |
3294 { | |
3295 VIS_EnterCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock); | |
3296 params[0] = add_ref(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].instance_data); | |
3297 VIS_LeaveCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock); | |
3298 params[1] = varname_dat; | |
3299 vis_dict_index(params, NULL); | |
3300 if(!params[0]) | |
3301 { | |
3302 printf("Error: Global variable %s not found in worker %s\n", def->implement_func->workerlist[aworker].name, def->name); | |
3303 DEBUGPRINTF("Error: Global variable %s not found in worker %s\n", def->implement_func->workerlist[aworker].name, def->name); | |
3304 execute_active = FALSE; | |
3305 return -1; | |
3306 } | |
3307 } | |
3308 process_outputs(params, aworker, instance); | |
3309 | |
3310 | |
3311 } | |
3312 else if(def->implement_func->workerlist[aworker].type == SET_GLOBAL) | |
3313 { | |
3314 varname = def->implement_func->workerlist[aworker].name + def->implement_func->workerlist[aworker].io_num; | |
3315 varname_dat = make_string(varname, -1, def->program); | |
3316 params[2] = params[0]; | |
3317 params[1] = varname_dat; | |
3318 VIS_EnterCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock); | |
3319 //no add_ref here because we'll be replacing instance_data with the result of vis_dict set | |
3320 params[0] = instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].instance_data; | |
3321 vis_dict_set(params, NULL); | |
3322 instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].instance_data = params[0]; | |
3323 VIS_LeaveCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock); | |
3324 //no outputs to process | |
3325 } | |
3326 else if(def->implement_func->workerlist[aworker].type == GET_COMP) | |
3327 { | |
3328 returnval = get_comp_room_by_name(params, def->implement_func->workerlist[aworker].name, NULL, &worker_entry, def->program); | |
3329 if(returnval) | |
3330 return returnval; | |
3331 process_outputs(params, aworker, instance); | |
3332 } | |
3333 else if(def->implement_func->workerlist[aworker].type == SET_COMP) | |
3334 { | |
3335 returnval = set_comp_room_by_name(params, def->implement_func->workerlist[aworker].name, NULL, &worker_entry, def->program); | |
3336 if(returnval) | |
3337 return returnval; | |
3338 process_outputs(params, aworker, instance); | |
3339 } | |
3340 else//Variable | |
3341 { | |
3342 VIS_PROFILE_START(PROF_EXECUTE_OTHER); | |
3343 if(def->implement_func->workerlist[aworker].num_inputs > 0 || def->implement_func->workerlist[aworker].type == INPUT) //Is this a Room or a constant? | |
3344 { | |
3345 todelete = NULL; | |
3346 VIS_EnterCriticalSection(instance->workerlist[aworker].worker_lock); | |
3347 if(def->implement_func->workerlist[aworker].type == OUTPUT) | |
3348 { | |
3349 todelete = instance->workerlist[aworker].value; | |
3350 instance->workerlist[aworker].value = params[0]; | |
3351 DEBUGPRINTF("Setting room/output at pos %d to %X in instance %X\n", aworker, params[0], instance); | |
3352 } | |
3353 //tempvalindex = instance->workerlist[aworker].value; | |
3354 VIS_LeaveCriticalSection(instance->workerlist[aworker].worker_lock); | |
3355 if(def->implement_func->workerlist[aworker].type == INPUT) | |
3356 { | |
3357 params[0] = instance->workerlist[aworker].value; | |
3358 instance->workerlist[aworker].value = NULL; | |
3359 } | |
3360 if(todelete) | |
3361 release_ref(todelete); | |
3362 if(def->implement_func->workerlist[aworker].num_outputs) | |
3363 { | |
3364 //add_ref(tempvalindex); | |
3365 process_outputs(params/*&tempvalindex*/, aworker, instance); | |
3366 } | |
3367 | |
3368 } | |
3369 else | |
3370 { | |
3371 //Hmm, do I potentially need another lock here? | |
3372 /*if(!(instance->def->implement_func->workerlist[aworker].value_index)) | |
3373 { | |
3374 instance->def->implement_func->workerlist[aworker].value_index = (int)(tempvalindex=get_constant(def->implement_func->workerlist[aworker].name,-1));//(int)tempvalindex; | |
3375 } | |
3376 else*/ | |
3377 tempvalindex = (datum *)instance->def->implement_func->workerlist[aworker].value_index; | |
3378 add_ref(tempvalindex); | |
3379 process_outputs(&tempvalindex, aworker, instance); | |
3380 } | |
3381 VIS_PROFILE_END(PROF_EXECUTE_OTHER); | |
3382 } | |
3383 VIS_PROFILE_END(PROF_PROCESS_WORKER); | |
3384 return returnval; | |
3385 } | |
3386 | |
3387 #define OPT_RESULT 0 | |
3388 #define OPT_CUST_RESULT 0x10000000 | |
3389 #define OPT_CONST 0x20000000 | |
3390 #define OPT_INPUT 0x30000000 | |
3391 | |
3392 int find_input_worker(custom_worker * cust, int aworker, int input, int *ret_output) | |
3393 { | |
3394 int o, p, wire_count; | |
3395 int out_worker; | |
3396 o = cust->workerlist[aworker].wire_up_lookup; | |
3397 wire_count = 0; | |
3398 while(cust->wirelist[p=cust->workers_to_wires_up[o]].end_worker == aworker && p >= 0) | |
3399 { | |
3400 if(cust->wirelist[p].input_num == input) | |
3401 { | |
3402 ++wire_count; | |
3403 out_worker = cust->wirelist[p].start_worker; | |
3404 DEBUGPRINTF("Input %d attached to %s(%d)\n", input, cust->workerlist[out_worker].name, out_worker); | |
3405 if(ret_output) | |
3406 *ret_output = cust->wirelist[p].output_num; | |
3407 } | |
3408 ++o; | |
3409 } | |
3410 DEBUGPRINTF("wire_count: %d\n", wire_count); | |
3411 if(wire_count == 1) | |
3412 return out_worker; | |
3413 return -1; | |
3414 } | |
3415 | |
3416 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) | |
3417 { | |
3418 /*if(in_opt[source_worker]) | |
3419 { | |
3420 if(prog->deflist[cust->workerlist[source_worker].value_index].type & USER_FLAG) | |
3421 { | |
3422 return OPT_CUST_RESULT | ((pos_in_opt[source_worker] & 0xFFFF) << 8) | (output_num & 0xFF); | |
3423 } | |
3424 else | |
3425 { | |
3426 if(strcmp(prog->deflist[cust->workerlist[source_worker].value_index].name, "If") == 0) | |
3427 { | |
3428 if(output_num == 0) | |
3429 { | |
3430 branch_flags[index] = 1; | |
3431 if(opts[pos_in_opt[source_worker]].branch1 <= index) | |
3432 opts[pos_in_opt[source_worker]].branch1 = index+1; | |
3433 } | |
3434 else | |
3435 { | |
3436 branch_flags[index] = 2; | |
3437 if(opts[pos_in_opt[source_worker]].branch2 <= index) | |
3438 opts[pos_in_opt[source_worker]].branch2 = index+1; | |
3439 } | |
3440 branch_refs[index] = opts + pos_in_opt[source_worker]; | |
3441 } | |
3442 else if(branch_flags[pos_in_opt[source_worker]]) | |
3443 { | |
3444 if(branch_flags[pos_in_opt[source_worker]] == 1) | |
3445 { | |
3446 branch_refs[pos_in_opt[source_worker]]->branch1 = index + 1; | |
3447 branch_flags[index] = 1; | |
3448 } | |
3449 else | |
3450 { | |
3451 branch_refs[pos_in_opt[source_worker]]->branch1 = index + 2; | |
3452 branch_flags[index] = 2; | |
3453 } | |
3454 branch_refs[index] = branch_refs[pos_in_opt[source_worker]]; | |
3455 } | |
3456 else | |
3457 branch_flags[index] = 0; | |
3458 if(input_num >= 0) | |
3459 ++opts[pos_in_opt[source_worker]].output_refs[output_num]; | |
3460 DEBUGPRINTF("OPT_RESULT: opt_num: %d, output_num: %d\n", pos_in_opt[source_worker], output_num); | |
3461 return OPT_RESULT | ((pos_in_opt[source_worker] & 0xFFFF) << 8) | (output_num & 0xFF); | |
3462 } | |
3463 } | |
3464 else if(cust->workerlist[source_worker].type == CONSTANT) | |
3465 { | |
3466 branch_flags[index] = 0; | |
3467 DEBUGPRINTF("OPT_CONST: %d\n", source_worker); | |
3468 return OPT_CONST | source_worker; | |
3469 } | |
3470 else if(cust->workerlist[source_worker].type == INPUT) | |
3471 { | |
3472 branch_flags[index] = 0; | |
3473 DEBUGPRINTF("OPT_INPUT: %d\n", cust->workerlist[source_worker].io_num); | |
3474 return OPT_INPUT | cust->workerlist[source_worker].io_num; | |
3475 }*/ | |
3476 return -1; | |
3477 } | |
3478 | |
3479 void optimize(worker_def * def) | |
3480 { | |
3481 /* | |
3482 int i,j,k,m,o,p; | |
3483 int * const_in; | |
3484 int num_entries = 0; | |
3485 int aworker; | |
3486 int adjust; | |
3487 int source_worker; | |
3488 int source_output; | |
3489 int source_null; | |
3490 int null_output; | |
3491 int wire_count; | |
3492 int * input_data; | |
3493 int current_null; | |
3494 int cust_result_count; | |
3495 int new_start; | |
3496 custom_worker * cust = def->implement_func; | |
3497 int start_current, end_current, new_current; | |
3498 worker_def * deflist = def->program->deflist; | |
3499 opt_entry * output = malloc(sizeof(opt_entry) * def->implement_func->num_workers); | |
3500 BOOL * in_opt = malloc(sizeof(BOOL) * cust->num_workers); | |
3501 int * branch_flags = malloc(sizeof(int) * cust->num_workers); | |
3502 opt_entry ** branch_refs = malloc(sizeof(int) * cust->num_workers); | |
3503 //BOOL * real_in_opt = malloc(sizeof(BOOL) * cust->num_workers); | |
3504 int * pos_in_opt = malloc(sizeof(int) * cust->num_workers); | |
3505 DEBUGPRINTF("deflist: %X\n", deflist); | |
3506 for(i = 0; i < cust->num_workers; ++i) | |
3507 { | |
3508 branch_flags[i] = 0; | |
3509 DEBUGPRINTF("%d: No input pass\n", i); | |
3510 DEBUGPRINTF("Examining: %s\n", cust->workerlist[i].name); | |
3511 if(cust->workerlist[i].num_inputs == 0 && !cust->workerlist[i].null_input && cust->workerlist[i].type == WORKER) | |
3512 { | |
3513 output[num_entries].def = deflist + cust->workerlist[i].value_index; | |
3514 DEBUGPRINTF("Set output[%d].def = %X\n", num_entries, output[num_entries].def); | |
3515 DEBUGPRINTF("opt: %d is %s\n\n", num_entries, cust->workerlist[i].name); | |
3516 output[num_entries].original_pos = i; | |
3517 output[num_entries].input_data = NULL; | |
3518 if(cust->workerlist[i].num_outputs) | |
3519 { | |
3520 output[num_entries].output_refs = malloc(sizeof(int)*cust->workerlist[i].num_outputs); | |
3521 for(j = 0; j < cust->workerlist[i].num_outputs; ++j) | |
3522 output[num_entries].output_refs[j] = 0; | |
3523 } | |
3524 else | |
3525 output[num_entries].output_refs = NULL; | |
3526 output[num_entries].branch1 = output[num_entries].branch2 = -1; | |
3527 //if(!(deflist[cust->workerlist[i].value_index].type & USER_FLAG)) | |
3528 //{ | |
3529 in_opt[i] = TRUE; | |
3530 pos_in_opt[i] = num_entries; | |
3531 //} | |
3532 //real_in_opt[i] = TRUE; | |
3533 ++num_entries; | |
3534 } | |
3535 else | |
3536 { | |
3537 //real_in_opt[i] = FALSE; | |
3538 in_opt[i] = FALSE; | |
3539 } | |
3540 } | |
3541 start_current = num_entries; | |
3542 for(i = 0; i < cust->num_workers; ++i) | |
3543 { | |
3544 DEBUGPRINTF("%d: Second pass\n", i); | |
3545 if(cust->workerlist[i].num_inputs == 0 && !cust->workerlist[i].null_input) | |
3546 { | |
3547 j = cust->workerlist[i].wire_down_lookup; | |
3548 while(cust->wirelist[k=cust->workers_to_wires_down[j]].start_worker == i && k >= 0) | |
3549 { | |
3550 aworker = cust->wirelist[k].end_worker; | |
3551 if(!in_opt[aworker]) | |
3552 { | |
3553 DEBUGPRINTF("Examining: %s(%d)\n", cust->workerlist[aworker].name, aworker); | |
3554 if(cust->workerlist[i].null_input) | |
3555 adjust = 1; | |
3556 else | |
3557 adjust = 0; | |
3558 input_data = malloc(sizeof(int)* (cust->workerlist[aworker].num_inputs+adjust)); | |
3559 for(m = (0-adjust); m < cust->workerlist[aworker].num_inputs; ++m) | |
3560 { | |
3561 DEBUGPRINTF("Input: %d\n", m); | |
3562 source_worker = find_input_worker(cust, aworker, m, &source_output); | |
3563 DEBUGPRINTF("source_worker: %d\n", source_worker); | |
3564 if(source_worker == -1) | |
3565 break; | |
3566 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); | |
3567 DEBUGPRINTF("input code: %X\n", source_worker); | |
3568 if(source_worker == -1) | |
3569 break; | |
3570 input_data[m+adjust] = source_worker; | |
3571 if(source_worker == -1) | |
3572 break; | |
3573 } | |
3574 if(source_worker == -1) | |
3575 free(input_data); | |
3576 else | |
3577 { | |
3578 if(cust->workerlist[aworker].type == OUTPUT) | |
3579 output[num_entries].def = NULL; | |
3580 else | |
3581 output[num_entries].def = deflist + cust->workerlist[aworker].value_index; | |
3582 DEBUGPRINTF("Set output[%d].def = %X\n", num_entries, output[num_entries].def); | |
3583 DEBUGPRINTF("opt: %d is %s\n\n", num_entries, cust->workerlist[aworker].name); | |
3584 output[num_entries].original_pos = aworker; | |
3585 output[num_entries].input_data = input_data; | |
3586 output[num_entries].null_inputs = adjust; | |
3587 output[num_entries].branch1 = output[num_entries].branch2 = -1; | |
3588 if(cust->workerlist[aworker].num_outputs) | |
3589 { | |
3590 output[num_entries].output_refs = malloc(sizeof(int)*cust->workerlist[aworker].num_outputs); | |
3591 for(m = 0; m < cust->workerlist[aworker].num_outputs; ++m) | |
3592 output[num_entries].output_refs[m] = 0; | |
3593 } | |
3594 else | |
3595 output[num_entries].output_refs = NULL; | |
3596 //if(cust->workerlist[aworker].type != OUTPUT && !(deflist[cust->workerlist[aworker].value_index].type & USER_FLAG)) | |
3597 //{ | |
3598 in_opt[aworker] = TRUE; | |
3599 pos_in_opt[aworker] = num_entries; | |
3600 //} | |
3601 //real_in_opt[aworker] = TRUE; | |
3602 ++num_entries; | |
3603 | |
3604 } | |
3605 } | |
3606 ++j; | |
3607 } | |
3608 } | |
3609 } | |
3610 DEBUGPUTS("Before While\n"); | |
3611 end_current = num_entries; | |
3612 while(start_current != end_current) | |
3613 { | |
3614 DEBUGPRINTF("start_current: %d, end_current: %d\n", start_current, end_current); | |
3615 new_start = num_entries; | |
3616 for(i = start_current; i < end_current; ++i) | |
3617 { | |
3618 DEBUGPRINTF("opt: %d, def: %X, name: %s\n", i, output[i].def, cust->workerlist[output[i].original_pos].name); | |
3619 j = cust->workerlist[output[i].original_pos].wire_down_lookup; | |
3620 DEBUGPRINTF("wire_down_lookup: %d\n", j); | |
3621 while(cust->wirelist[k=cust->workers_to_wires_down[j]].start_worker == output[i].original_pos && k >= 0) | |
3622 { | |
3623 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); | |
3624 aworker = cust->wirelist[k].end_worker; | |
3625 //FIXME: Only works if constant/input attached to only one destination | |
3626 if(cust->workerlist[aworker].type == CONSTANT || cust->workerlist[aworker].type == INPUT) | |
3627 { | |
3628 DEBUGPRINTF("Worker is of type %d, ", cust->workerlist[aworker].type); | |
3629 aworker = cust->wirelist[cust->workers_to_wires_down[cust->workerlist[aworker].wire_down_lookup]].end_worker; | |
3630 DEBUGPRINTF("reruting to worker %d\n", aworker); | |
3631 } | |
3632 if(!in_opt[aworker]) | |
3633 { | |
3634 DEBUGPRINTF("Examining: %s(%d)\n", cust->workerlist[aworker].name, aworker); | |
3635 if(cust->workerlist[i].null_input) | |
3636 adjust = 1; | |
3637 else | |
3638 adjust = 0; | |
3639 for(m = (0-adjust); m < cust->workerlist[aworker].num_inputs; ++m) | |
3640 { | |
3641 source_worker = find_input_worker(cust, aworker, m, &source_output); | |
3642 if(source_worker == -1) | |
3643 break; | |
3644 if(cust->workerlist[source_worker].null_input && cust->workerlist[source_worker].type != WORKER) | |
3645 ++adjust; | |
3646 } | |
3647 if(source_worker != -1) | |
3648 { | |
3649 current_null = 0; | |
3650 input_data = malloc(sizeof(int)* (cust->workerlist[aworker].num_inputs+adjust)); | |
3651 cust_result_count = 0; | |
3652 for(m = (cust->workerlist[i].null_input ? -1 : 0); m < cust->workerlist[aworker].num_inputs; ++m) | |
3653 { | |
3654 DEBUGPRINTF("Input: %d\n", m); | |
3655 source_worker = find_input_worker(cust, aworker, m, &source_output); | |
3656 if(cust->workerlist[source_worker].null_input && cust->workerlist[source_worker].type != WORKER) | |
3657 { | |
3658 source_null = find_input_worker(cust, source_worker, -1, &null_output); | |
3659 if(source_null == -1) | |
3660 { | |
3661 source_worker = -1; | |
3662 break; | |
3663 } | |
3664 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); | |
3665 if((source_null & 0xF0000000) == OPT_CUST_RESULT) | |
3666 ++cust_result_count; | |
3667 if(source_null == -1) | |
3668 { | |
3669 source_worker = -1; | |
3670 break; | |
3671 } | |
3672 input_data[current_null++] = source_null; | |
3673 } | |
3674 DEBUGPRINTF("source_worker: %d\n", source_worker); | |
3675 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); | |
3676 if((source_worker & 0xF0000000) == OPT_CUST_RESULT) | |
3677 ++cust_result_count; | |
3678 DEBUGPRINTF("input code: %d\n", source_worker); | |
3679 if(cust_result_count >= (cust->workerlist[aworker].num_inputs + adjust)) | |
3680 source_worker = -1; | |
3681 if(source_worker == -1) | |
3682 break; | |
3683 input_data[m+adjust] = source_worker; | |
3684 } | |
3685 if(source_worker == -1) | |
3686 free(input_data); | |
3687 else | |
3688 { | |
3689 if(cust->workerlist[aworker].type == OUTPUT) | |
3690 output[num_entries].def = NULL; | |
3691 else | |
3692 output[num_entries].def = deflist + cust->workerlist[aworker].value_index; | |
3693 DEBUGPRINTF("Set output[%d].def = %X\n", num_entries, output[num_entries].def); | |
3694 DEBUGPRINTF("opt: %d is %s\n\n", num_entries, cust->workerlist[aworker].name); | |
3695 output[num_entries].original_pos = aworker; | |
3696 output[num_entries].input_data = input_data; | |
3697 output[num_entries].null_inputs = adjust; | |
3698 output[num_entries].branch1 = output[num_entries].branch2 = -1; | |
3699 if(cust->workerlist[aworker].num_outputs) | |
3700 { | |
3701 output[num_entries].output_refs = malloc(sizeof(int)*cust->workerlist[aworker].num_outputs); | |
3702 for(m = 0; m < cust->workerlist[aworker].num_outputs; ++m) | |
3703 output[num_entries].output_refs[m] = 0; | |
3704 } | |
3705 else | |
3706 output[num_entries].output_refs = NULL; | |
3707 //if(cust->workerlist[aworker].type != OUTPUT && !(deflist[cust->workerlist[aworker].value_index].type & USER_FLAG)) | |
3708 //{ | |
3709 in_opt[aworker] = TRUE; | |
3710 pos_in_opt[aworker] = num_entries; | |
3711 //} | |
3712 //real_in_opt[aworker] = TRUE; | |
3713 ++num_entries; | |
3714 | |
3715 } | |
3716 } | |
3717 } | |
3718 ++j; | |
3719 } | |
3720 } | |
3721 start_current = new_start; | |
3722 end_current = num_entries; | |
3723 } | |
3724 def->optimized = output; | |
3725 def->opt_count = num_entries; | |
3726 DEBUGPUTS("optimize done\n\n\n"); | |
3727 */ | |
3728 } | |
3729 | |
3730 | |
3731 void run_optimized(worker_instance * instance, datum ** params) | |
3732 { | |
3733 int i = 0,j,k; | |
3734 unsigned short output, opt_num; | |
3735 datum * this_params[32]; | |
3736 queue_entry entry; | |
3737 datum * val; | |
3738 BOOL skip; | |
3739 BOOL partial_flag; | |
3740 BOOL continue_flag; | |
3741 int count; | |
3742 int ready; | |
3743 int jump_from = -1; | |
3744 int jump_to = -1; | |
3745 int tmp, addnum; | |
3746 opt_entry * exec_list = instance->def->optimized; | |
3747 datum ** results = instance->opt_results;//malloc(sizeof(datum *) * instance->def->opt_count * 32); | |
3748 VIS_PROFILE_START(PROF_RUN_OPT); | |
3749 entry.instance = instance; | |
3750 for(i = 0; i < instance->def->opt_count; ++i) | |
3751 { | |
3752 VIS_PROFILE_START(PROF_OPT_LOOP); | |
3753 skip = FALSE; | |
3754 partial_flag = FALSE; | |
3755 continue_flag = FALSE; | |
3756 DEBUGPRINTF("\nPeparing exec_list[%d]\n", i); | |
3757 if(exec_list[i].def) | |
3758 { | |
3759 DEBUGPRINTF("Name: %s\n", exec_list[i].def->name); | |
3760 count = exec_list[i].def->num_inputs; | |
3761 } | |
3762 else | |
3763 count = 1; | |
3764 count += exec_list[i].null_inputs; | |
3765 //DEBUGPRINTF("Input count: %d\n", count); | |
3766 if(count && !exec_list[i].input_data) | |
3767 puts("Runtime Error: input data is NULL\n"); | |
3768 //DEBUGPRINTF("input_data: %X\n", exec_list[i].input_data); | |
3769 VIS_PROFILE_START(PROF_OPT_PREP_INPUT); | |
3770 for(j = 0; j < count; ++j) | |
3771 { | |
3772 val = NULL; | |
3773 continue_flag = FALSE; | |
3774 switch(exec_list[i].input_data[j] & 0xF0000000) | |
3775 { | |
3776 case OPT_RESULT: | |
3777 output = exec_list[i].input_data[j] & 0xFF; | |
3778 opt_num = (exec_list[i].input_data[j] >> 8)& 0xFFFF; | |
3779 DEBUGPRINTF("OPT_RESULT for input %d, opt_num: %d, output: %d\n", j, opt_num, output); | |
3780 val = results[(opt_num * 32) | output]; | |
3781 break; | |
3782 case OPT_CUST_RESULT: | |
3783 val = NULL; | |
3784 partial_flag = TRUE; | |
3785 continue_flag = TRUE; | |
3786 break; | |
3787 case OPT_INPUT: | |
3788 DEBUGPRINTF("OPT_INPUT for input %d\n", j); | |
3789 val = add_ref(params[exec_list[i].input_data[j] & 0xFF]); | |
3790 break; | |
3791 case OPT_CONST: | |
3792 DEBUGPRINTF("OPT_CONST for input %d\n", j); | |
3793 val = add_ref((datum *)(instance->def->implement_func->workerlist[exec_list[i].input_data[j] & 0xFFFFFF].value_index)); | |
3794 break; | |
3795 default: | |
3796 puts("Runtime Error: Invalid bytecode\n"); | |
3797 val = NULL; | |
3798 break; | |
3799 } | |
3800 if(!val && !continue_flag) | |
3801 { | |
3802 for(k = exec_list[i].null_inputs; k < j; ++k) | |
3803 release_ref(this_params[k]); | |
3804 skip = TRUE; | |
3805 break; | |
3806 } | |
3807 DEBUGPRINTF("this_params[%d] = %X\n", j, val); | |
3808 if(j >= exec_list[i].null_inputs) | |
3809 if(val) | |
3810 this_params[j] = /*add_ref(*/val/*)*/; | |
3811 else | |
3812 this_params[j] = NULL; | |
3813 | |
3814 } | |
3815 VIS_PROFILE_END(PROF_OPT_PREP_INPUT); | |
3816 if(!skip) | |
3817 { | |
3818 if(partial_flag) | |
3819 { | |
3820 VIS_PROFILE_START(PROF_PARTIAL_EXEC); | |
3821 ready = 0; | |
3822 for(j = exec_list[i].null_inputs; j < count; ++j) | |
3823 if(this_params[j]) | |
3824 { | |
3825 instance->workerlist[exec_list[i].original_pos].params[j-exec_list[i].null_inputs+1] = this_params[j]; | |
3826 ++ready; | |
3827 } | |
3828 if(instance->def->implement_func->workerlist[exec_list[i].original_pos].null_input && this_params[exec_list[i].null_inputs-1]) | |
3829 ++ready; | |
3830 DEBUGPRINTF("ready: %d\n", ready); | |
3831 skip = TRUE; | |
3832 VIS_EnterCriticalSection(instance->workerlist[exec_list[i].original_pos].worker_lock); | |
3833 instance->workerlist[exec_list[i].original_pos].ready_count += ready; | |
3834 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))) | |
3835 { | |
3836 skip = FALSE; | |
3837 instance->workerlist[exec_list[i].original_pos].ready_count = 0; | |
3838 | |
3839 } | |
3840 DEBUGPRINTF("ready_count: %d\n", instance->workerlist[exec_list[i].original_pos].ready_count); | |
3841 VIS_LeaveCriticalSection(instance->workerlist[exec_list[i].original_pos].worker_lock); | |
3842 if(!skip) | |
3843 add_queue(exec_list[i].original_pos, instance); | |
3844 VIS_PROFILE_END(PROF_PARTIAL_EXEC); | |
3845 } | |
3846 else if(exec_list[i].def) | |
3847 { | |
3848 VIS_PROFILE_START(PROF_FULL_EXEC); | |
3849 DEBUGPRINTF("opt_exec: %s(%d)\n", exec_list[i].def->name, exec_list[i].original_pos); | |
3850 entry.worker_num = exec_list[i].original_pos; | |
3851 if(exec_list[i].def->type & USER_FLAG) | |
3852 { | |
3853 VIS_PROFILE_START(PROF_OPT_EXEC_USER); | |
3854 instance->workerlist[exec_list[i].original_pos].params[0] = NULL; | |
3855 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); | |
3856 add_queue(exec_list[i].original_pos, instance); | |
3857 VIS_PROFILE_END(PROF_OPT_EXEC_USER); | |
3858 } | |
3859 else | |
3860 { | |
3861 VIS_PROFILE_START(PROF_OPT_EXEC_BUILT); | |
3862 if(execute_def(exec_list[i].def, entry, this_params + exec_list[i].null_inputs, sub_callback) == 0) | |
3863 { | |
3864 DEBUGPUTS("Exectuted with reslts\n"); | |
3865 if(exec_list[i].output_refs) | |
3866 { | |
3867 for(j = exec_list[i].null_inputs; j < (exec_list[i].def->num_outputs+exec_list[i].null_inputs); ++j) | |
3868 { | |
3869 DEBUGPRINTF("output_refs[%d] = %d\n", j-exec_list[i].null_inputs, exec_list[i].output_refs[j-exec_list[i].null_inputs]); | |
3870 if(!exec_list[i].output_refs[j-exec_list[i].null_inputs]) | |
3871 release_ref(this_params[j]); | |
3872 else if(exec_list[i].output_refs[j-exec_list[i].null_inputs] > 1) | |
3873 { | |
3874 /*DEBUGPRINTF("multi_add_ref(%X): %d\n", this_params[j], exec_list[i].output_refs[j-exec_list[i].null_inputs]-1); | |
3875 tmp = (int)(&(this_params[j]->ref_count)); | |
3876 addnum = exec_list[i].output_refs[j-exec_list[i].null_inputs]-1; | |
3877 __asm | |
3878 { | |
3879 mov ebx, tmp | |
3880 mov eax, addnum | |
3881 lock xadd dword ptr [ebx], eax | |
3882 }*/ | |
3883 VIS_EnterCriticalSection(this_params[j]->lock); | |
3884 this_params[j]->ref_count += exec_list[i].output_refs[j-exec_list[i].null_inputs]-1; | |
3885 | |
3886 VIS_LeaveCriticalSection(this_params[j]->lock); | |
3887 } | |
3888 } | |
3889 memcpy(results + i*32, this_params + exec_list[i].null_inputs, sizeof(datum *) * exec_list[i].def->num_outputs); | |
3890 if(exec_list[i].branch1 >= 0) | |
3891 { | |
3892 if(this_params[exec_list[i].null_inputs]) | |
3893 { | |
3894 jump_from = exec_list[i].branch1; | |
3895 jump_to = exec_list[i].branch2; | |
3896 } | |
3897 else | |
3898 { | |
3899 i = exec_list[i].branch1-1; | |
3900 } | |
3901 } | |
3902 } | |
3903 } | |
3904 /*else | |
3905 { | |
3906 for(j = exec_list[i].null_inputs; j < (exec_list[i].def->num_outputs + exec_list[i].null_inputs); ++j) | |
3907 results[(i*32)|j] = NULL; | |
3908 }*/ | |
3909 VIS_PROFILE_END(PROF_OPT_EXEC_BUILT); | |
3910 } | |
3911 VIS_PROFILE_END(PROF_FULL_EXEC); | |
3912 DEBUGPUTS("Executed\n"); | |
3913 } | |
3914 else | |
3915 instance->workerlist[exec_list[i].original_pos].value = this_params[exec_list[i].null_inputs]; | |
3916 } | |
3917 else | |
3918 { | |
3919 DEBUGPUTS("Skipped\n"); | |
3920 if(exec_list[i].def) | |
3921 { | |
3922 for(j = 0; j < exec_list[i].def->num_outputs; ++j) | |
3923 results[(i*32)|j] = NULL; | |
3924 } | |
3925 } | |
3926 if(jump_from >= 0 && (i+1) == jump_from) | |
3927 { | |
3928 i = jump_to-1; | |
3929 jump_from = -1; | |
3930 } | |
3931 VIS_PROFILE_END(PROF_OPT_LOOP); | |
3932 } | |
3933 DEBUGPUTS("run_optimized calling cleanup_check\n"); | |
3934 for(i = 0; i < instance->def->num_inputs; ++i) | |
3935 release_ref(params[i]); | |
3936 cleanup_check(entry); | |
3937 VIS_PROFILE_END(PROF_RUN_OPT); | |
3938 } | |
3939 | |
3940 int vis_print(datum ** inputlist, queue_entry * worker_entry) | |
3941 { | |
3942 int result; | |
3943 #ifdef CONSOLE | |
3944 puts((char *)inputlist[0]->c.generic.data); | |
3945 #else | |
3946 MessageBox(NULL, (char *)inputlist[0]->c.generic.data, "Visuality Output", MB_OK); | |
3947 #endif | |
3948 result = 1; | |
3949 | |
3950 release_ref(inputlist[0]); | |
3951 inputlist[0] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program); | |
3952 //No one else knows about this new datum yet so we can skip getting a lock | |
3953 datum_set_yesno(inputlist[0], result); | |
3954 return 0; | |
3955 } | |
3956 | |
3957 int vis_end(datum ** inputlist, queue_entry * worker_entry) | |
3958 { | |
3959 // fprintf(outfile, "End worker reached.\n"); | |
3960 execute_active=FALSE; | |
3961 release_ref(inputlist[0]); | |
3962 //interp_stop(); | |
3963 return 0; | |
3964 } | |
3965 | |
3966 #ifdef NINTENDO_DS | |
3967 const char keyLetters[15] = "ABESRLUD><XYMC"; | |
3968 #define MAX_KEY_BITS 14 | |
3969 #endif | |
3970 | |
3971 int vis_getinput(datum ** inputlist, queue_entry * worker_entry) | |
3972 { | |
3973 #ifdef NINTENDO_DS | |
3974 int held,i,pos; | |
3975 char tempstring[14]; | |
3976 scanKeys(); | |
3977 held = keysHeld(); | |
3978 if(held) | |
3979 { | |
3980 pos = 0; | |
3981 for(i = 0; i < MAX_KEY_BITS; ++i) | |
3982 if(held & (1 << i)) | |
3983 tempstring[pos++] = keyLetters[i]; | |
3984 inputlist[0] = new_datum(BUILTIN_TYPE_STRING, 1, pos+1, worker_entry->instance->def->program); | |
3985 memcpy(inputlist[0]->c.generic.data, tempstring, pos); | |
3986 ((char *)inputlist[0]->c.generic.data)[pos]='\0'; | |
3987 return 0; | |
3988 } | |
3989 else | |
3990 { | |
3991 requeue(worker_entry->worker_num, worker_entry->instance); | |
3992 return 1; | |
3993 } | |
3994 #else | |
3995 #ifdef CONSOLE | |
3996 gets(text_buf); | |
3997 text_buf_size = strlen(text_buf); | |
3998 //Nasty hack for testing until I get around to supporting command line args propery | |
3999 //text_buf_size = strlen(global_argv[1]); | |
4000 #else | |
4001 | |
4002 while(text_buf_size <= 0) | |
4003 { | |
4004 Sleep(30); //TODO: replace with I/O queue mechanism | |
4005 } | |
4006 #endif | |
4007 // VIS_EnterCriticalSection(text_buf_lock); | |
4008 DEBUGPRINTF("Allocating %d bytes\n", text_buf_size+1); | |
4009 inputlist[0] = new_datum(BUILTIN_TYPE_STRING, 1, text_buf_size+1, worker_entry->instance->def->program); | |
4010 DEBUGPUTS("Allocated datum.\n"); | |
4011 memcpy(inputlist[0]->c.generic.data, text_buf, text_buf_size); | |
4012 DEBUGPUTS("Copied string.\n"); | |
4013 ((char *)inputlist[0]->c.generic.data)[text_buf_size]='\0'; | |
4014 DEBUGPRINTF("Input is %s\n", inputlist[0]->c.generic.data); | |
4015 text_buf_size = 0; | |
4016 // VIS_LeaveCriticalSection(text_buf_lock); | |
4017 return 0; | |
4018 #endif | |
4019 } | |
4020 | |
4021 int vis_if(datum ** inputlist, queue_entry * worker_entry) | |
4022 { | |
4023 if(!(inputlist[0]->c.integers.num_a)) | |
4024 { | |
4025 inputlist[1] = inputlist[0]; | |
4026 inputlist[0] = NULL; | |
4027 } | |
4028 else | |
4029 inputlist[1] = NULL; | |
4030 return 0; | |
4031 } | |
4032 | |
4033 int vis_build(datum ** inputlist, queue_entry * worker_entry) | |
4034 { | |
4035 int i,j; | |
4036 company * companylist = worker_entry->instance->def->program->companylist; | |
4037 int num_companies = worker_entry->instance->def->program->num_companies; | |
4038 DEBUGPRINTF("Looking for company named %s\n", inputlist[0]->c.generic.data); | |
4039 for(i = 0; i < num_companies; ++i) | |
4040 { | |
4041 DEBUGPRINTF("Checking company %d:%s\n", i, companylist[i].name); | |
4042 if(!strcmp(inputlist[0]->c.generic.data, companylist[i].name)) | |
4043 break; | |
4044 } | |
4045 release_ref(inputlist[0]); | |
4046 if(i < num_companies && companylist[i].build_size > 0) | |
4047 { | |
4048 DEBUGPRINTF("Building company with size %d\n", companylist[i].build_size); | |
4049 inputlist[0] = new_datum(i, 1, companylist[i].build_size, worker_entry->instance->def->program); | |
4050 for(j = 0; j < companylist[i].build_size; ++j) | |
4051 ((char*)(inputlist[0]->c.generic.data))[j] = 0; | |
4052 } | |
4053 else | |
4054 { | |
4055 DEBUGPUTS("Could not find company\n"); | |
4056 inputlist[0] = NULL; | |
4057 } | |
4058 return 0; | |
4059 } | |
4060 | |
4061 int vis_wait_forever(datum ** inputlist, queue_entry * worker_entry) | |
4062 { | |
4063 return 1; | |
4064 } | |
4065 | |
4066 int init_global_store(datum ** inputlist, queue_entry * worker_entry) | |
4067 { | |
4068 datum * params[3]; | |
4069 global_store * store; | |
4070 datum * store_dat = new_datum(BUILTIN_TYPE_GLOBAL_STORE, 1, sizeof(global_store), worker_entry->instance->def->program); | |
4071 store = store_dat->c.generic.data; | |
4072 store->name = add_ref(inputlist[0]); | |
4073 store->data = create_dict(worker_entry->instance->def->program); | |
4074 VIS_EnterCriticalSection(global_store_lock); | |
4075 params[0] = global_store_dict; | |
4076 params[1] = inputlist[0]; | |
4077 params[2] = store_dat; | |
4078 vis_dict_set(params, NULL); | |
4079 global_store_dict = params[0]; | |
4080 DEBUGPUTS("Global store init complete\n"); | |
4081 VIS_LeaveCriticalSection(global_store_lock); | |
4082 DEBUGPUTS("Released global_store_lock\n"); | |
4083 inputlist[0] = NULL; | |
4084 return 0; | |
4085 } | |
4086 | |
4087 int vis_type_of(datum ** inputlist, queue_entry * worker_entry) | |
4088 { | |
4089 datum * output = make_string(inputlist[0]->company->name, -1, worker_entry->instance->def->program); | |
4090 release_ref(inputlist[0]); | |
4091 inputlist[0] = output; | |
4092 return 0; | |
4093 } | |
4094 | |
4095 int vis_random(datum ** inputlist, queue_entry * worker_entry) | |
4096 { | |
4097 inputlist[0] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program); | |
4098 VIS_EnterCriticalSection(randlock); | |
4099 inputlist[0]->c.integers.num_a = genrand_int32(); | |
4100 VIS_LeaveCriticalSection(randlock); | |
4101 return 0; | |
4102 } |