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