4 #include "dynstrings.h"
10 #define SUPRESS_WARNING(x) (void)x
19 void (*nodefunc
[NODE_MAXFUNC
]) (TreeNode
*node
);
22 TreeNode
*node_new() {
23 TreeNode
*result
= malloc(sizeof(TreeNode
));
24 result
->id
= NODE_EMPTY
;
25 result
->code
= strdup("");
26 result
->next
= result
;
27 result
->previous
= result
;
28 result
->bottom
= NULL
;
32 void node_free(TreeNode
*node
) {
37 void node_set(TreeNode
*node
, char *code
) {
42 void node_next(TreeNode
*parent
, TreeNode
*child
) {
43 child
->previous
->next
= parent
->next
;
44 parent
->next
->previous
= child
->previous
;
46 child
->previous
= parent
;
49 void node_bottom(TreeNode
*parent
, TreeNode
*child
) {
50 if (parent
->bottom
== NULL
) {
51 parent
->bottom
= child
;
54 TreeNode
*childprev
= child
->previous
;
55 TreeNode
*parentprev
= parent
->bottom
->previous
;
56 child
->previous
= parentprev
;
57 parent
->bottom
->previous
= childprev
;
58 childprev
->next
= parent
->bottom
;
59 parentprev
->next
= child
;
60 parent
->bottom
= child
;
64 void node_traverse(TreeNode
*node
) {
65 nodefunc
[node
->id
](node
);
68 void core_error(char *msg
) {
69 c_error
= str_cat2(c_error
, msg
);
72 void core_pad_add(int amount
) {
73 int start
= strlen(c_pad
);
75 for (i
= 0; i
< amount
; i
++)
76 c_pad
[start
+ i
] = ' ';
77 c_pad
[start
+ amount
] = '\0';
80 void core_pad_sub(int amount
) {
81 int position
= strlen(c_pad
) - amount
;
82 if (position
< 0) position
= 0;
83 c_pad
[position
] = '\0';
86 void core_pad_reset() {
90 char *core_translate_name(char *name
) {
91 int length
= strlen(name
);
94 for (i
= 0; i
< length
; i
++) {
95 if ((name
[i
] == '8') || (name
[i
] == '9') || (name
[i
] == '_'))
98 char *result
= malloc(length
+ translate
+ 1);
99 char *output
= result
;
100 for (i
= 0; i
< length
; i
++) {
103 output
[1] = output
[0] = '8';
107 output
[1] = output
[0] = '9';
124 char *core_translate_var(char *name
) {
125 name
= core_translate_name(name
);
127 int local
= varLocal(name
);
129 result
= varGlobal(name
);
130 if (result
== NULL
) {
132 result
= varGlobal(name
);
134 return strdup(result
);
137 return str_printf("^%d", local
+ c_stack
);
140 void core_empty(TreeNode
*node
) {
141 SUPRESS_WARNING(node
);
144 void core_function(TreeNode
*node
) {
148 TreeNode
*iterator
= node
->next
->next
;
149 while (iterator
!= node
) {
150 node_traverse(iterator
);
151 iterator
= iterator
->next
;
152 node_free(iterator
->previous
);
155 c_fnname
= node
->next
->code
;
156 if (varFunction(c_fnname
) != -1) {
157 core_error(str_printf("Error: Function %s already exists!\n", c_fnname
));
160 addFunction(c_fnname
, c_params
);
161 c_fnname
= core_translate_name(c_fnname
);
162 node_free(node
->next
);
164 fprintf(c_output
, "fn%sStart:\n", c_fnname
);
166 fprintf(c_output
, "%sebx = 0 - 1\n", c_pad
);
167 node_traverse(node
->bottom
);
168 fputs(node
->bottom
->code
, c_output
);
169 node_free(node
->bottom
);
170 fprintf(c_output
, "jump fn%sEnd\n", c_fnname
);
171 fprintf(c_output
, "fn%sEnd:\n", c_fnname
);
173 for (i
= 0; i
< c_params
; i
++)
174 fprintf(c_output
, " call BDestroy\n");
175 fprintf(c_output
, " call BFinalizeResult\n");
176 fprintf(c_output
, "return\n\n");
179 core_error(str_printf("Error: Stack inconsistent! (%d)\n", c_stack
));
182 void core_func_args(TreeNode
*node
) {
183 char *name
= core_translate_name(node
->bottom
->code
);
186 node_free(node
->bottom
);
189 void core_return(TreeNode
*node
) {
190 node_traverse(node
->bottom
);
191 char *result
= strdup(node
->bottom
->code
);
192 result
= str_cat2(result
, str_printf("%stop ebx\n", c_pad
));
193 result
= str_cat2(result
, str_printf("%spop\n", c_pad
));
194 result
= str_cat2(result
, str_printf("jump fn%sEnd\n", c_fnname
));
195 node_set(node
, result
);
196 node_free(node
->bottom
);
200 void core_if(TreeNode
*node
) {
201 node_traverse(node
->next
);
204 node_traverse(node
->bottom
);
206 char *label
= str_printf("fn%s%d", c_fnname
, c_label
);
207 char *result
= strdup(node
->next
->code
);
208 result
= str_cat2(result
, str_printf("%scall BBIsZero\n", c_pad
));
209 result
= str_cat2(result
, str_printf("%sifeq eax %s\n", c_pad
, label
));
210 result
= str_cat(result
, node
->bottom
->code
);
211 result
= str_cat2(result
, str_printf("%s%s: eax = eax + 0\n", c_pad
, label
));
212 node_set(node
, result
);
214 node_free(node
->next
);
215 node_free(node
->bottom
);
219 void core_while(TreeNode
*node
) {
221 node_traverse(node
->next
);
223 node_traverse(node
->bottom
);
225 char *check
= str_printf("%sfn%dCheck", c_fnname
, c_label
);
226 char *loop
= str_printf("%sfn%dLoop", c_fnname
, c_label
);
227 char *result
= str_printf("%sjump %s\n", c_pad
, check
);
228 result
= str_cat2(result
, str_printf("%s%s:\n", c_pad
, loop
));
229 result
= str_cat(result
, node
->bottom
->code
);
230 result
= str_cat2(result
, str_printf("%s%s:\n", c_pad
, check
));
231 result
= str_cat(result
, node
->next
->code
);
232 result
= str_cat2(result
, str_printf("%s call BBIsZero\n", c_pad
));
233 result
= str_cat2(result
, str_printf("%sifneq eax %s\n", c_pad
, loop
));
234 node_set(node
, result
);
237 node_free(node
->next
);
238 node_free(node
->bottom
);
242 void core_push_var(TreeNode
*node
) {
243 char *name
= core_translate_var(node
->code
);
244 char *result
= str_printf("%spush %s\n", c_pad
, name
);
246 result
= str_cat2(result
, str_printf("%scall BBCopy\n", c_pad
));
247 node_set(node
, result
);
251 void core_push_bool(TreeNode
*node
) {
252 node_set(node
, str_printf("%scall BB%s\n", c_pad
, node
->code
));
256 void core_push_dec(TreeNode
*node
) {
259 decToBlob(node
->code
, &str
, &length
);
260 char *result
= str_printf("%spush %d\n", c_pad
, length
);
261 result
= str_cat2(result
, str_printf("%scall BBCreate\n", c_pad
));
263 for (i
= 0; i
< length
; i
++) {
264 result
= str_cat2(result
, str_printf("%s@eax = %d + 0\n", c_pad
, str
[i
]));
265 if ((i
+ 1) < length
)
266 result
= str_cat2(result
, str_printf("%seax = eax + 1\n", c_pad
));
268 node_set(node
, result
);
273 void core_push_hex(TreeNode
*node
) {
276 hexToBlob(node
->code
, &str
, &length
);
277 char *result
= str_printf("%spush %d\n", c_pad
, length
);
278 result
= str_cat2(result
, str_printf("%scall BBCreate\n", c_pad
));
280 for (i
= 0; i
< length
; i
++) {
281 result
= str_cat2(result
, str_printf("%s@eax = %d + 0\n", c_pad
, str
[i
]));
282 if ((i
+ 1) < length
)
283 result
= str_cat2(result
, str_printf("%seax = eax + 1\n", c_pad
));
285 node_set(node
, result
);
290 void core_push_str(TreeNode
*node
) {
291 char *str
= node
->code
;
292 char *input
= str
+ 1;
295 while (input
[0] != '"') {
311 core_error(str_printf("Error: Invalid escape character! (\"%c\")\n", input
[0]));
317 if (input
[0] != '\\') {
318 output
[0] = input
[0];
327 core_error(strdup("Error: Dangling escape character!\n"));
329 int length
= (output
- str
);
330 char *result
= str_printf("%spush %d\n", c_pad
, length
);
331 result
= str_cat2(result
, str_printf("%scall BBCreate\n", c_pad
));
333 for (i
= 0; i
< length
; i
++) {
334 result
= str_cat2(result
, str_printf("%s@eax = %d + 0\n", c_pad
, str
[i
]));
335 if ((i
+ 1) < length
)
336 result
= str_cat2(result
, str_printf("%seax = eax + 1\n", c_pad
));
338 node_set(node
, result
);
342 void core_callfn(TreeNode
*node
) {
343 char *params
= strdup("");
345 TreeNode
*iterator
= node
->bottom
->previous
;
346 while (iterator
!= node
->bottom
) {
347 node_traverse(iterator
);
348 params
= str_cat(params
, iterator
->code
);
350 iterator
= iterator
->previous
;
351 node_free(iterator
->next
);
353 char *name
= node
->bottom
->code
;
354 char *result
= params
;
355 if (strcmp(name
, "get_chr") == 0) {
357 core_error(str_printf("Error: get_chr should have 0 parameters! (has %d)\n", c_callargs
));
358 result
= str_cat2(result
, str_printf("%scall BBgetchr\n", c_pad
));
360 else if (strcmp(name
, "get_int") == 0) {
362 core_error(str_printf("Error: get_int should have 0 parameters! (has %d)\n", c_callargs
));
363 result
= str_cat2(result
, str_printf("%scall BBgetint\n", c_pad
));
365 else if (strcmp(name
, "out_str") == 0) {
367 core_error(strdup("Error: out_str should have at least 1 parameter!\n"));
368 result
= str_cat2(result
, str_printf("%scall BBoutstr\n", c_pad
));
369 result
= str_cat2(result
, str_printf("%scall BBFalse\n", c_pad
));
372 addFunctionCall(name
, c_callargs
);
373 char *tname
= core_translate_name(name
);
374 result
= str_cat2(result
, str_printf("%scall fn%sStart\n", c_pad
, tname
));
377 node_set(node
, result
);
378 node_free(node
->bottom
);
379 c_stack
-= c_callargs
- 1;
382 void core_call_args(TreeNode
*node
) {
383 node_traverse(node
->bottom
);
384 node_set(node
, strdup(node
->bottom
->code
));
385 node_free(node
->bottom
);
388 void core_void_return(TreeNode
*node
) {
389 node_traverse(node
->bottom
);
390 char *result
= strdup(node
->bottom
->code
);
391 result
= str_cat2(result
, str_printf("%scall BDestroy\n", c_pad
));
392 node_set(node
, result
);
393 node_free(node
->bottom
);
397 void core_arit_binary(TreeNode
*node
) {
398 node_traverse(node
->bottom
);
399 node_traverse(node
->bottom
->next
);
400 char *result
= strdup(node
->bottom
->code
);
401 result
= str_cat(result
, node
->bottom
->next
->code
);
402 result
= str_cat2(result
, str_printf("%scall BB%s\n", c_pad
, node
->code
));
403 node_set(node
, result
);
404 node_free(node
->bottom
->next
);
405 node_free(node
->bottom
);
409 void core_arit_unary(TreeNode
*node
) {
410 node_traverse(node
->bottom
);
411 char *result
= strdup(node
->bottom
->code
);
412 result
= str_cat2(result
, str_printf("%scall BB%s\n", c_pad
, node
->code
));
413 node_set(node
, result
);
414 node_free(node
->bottom
);
417 void core_set_variable(TreeNode
*node
) {
418 node_traverse(node
->bottom
);
419 char *blob
= core_translate_var(node
->bottom
->next
->code
);
420 char *result
= strdup(node
->bottom
->code
);
421 result
= str_cat2(result
, str_printf("%seax = %s + 0\n", c_pad
, blob
));
422 result
= str_cat2(result
, str_printf("%scall BDestroyR\n", c_pad
));
423 result
= str_cat2(result
, str_printf("%stop %s\n", c_pad
, blob
));
424 result
= str_cat2(result
, str_printf("%spop\n", c_pad
));
425 node_set(node
, result
);
427 node_free(node
->bottom
->next
);
428 node_free(node
->bottom
);
432 void core_get_length(TreeNode
*node
) {
433 node_traverse(node
->bottom
);
434 char *result
= strdup(node
->bottom
->code
);
435 result
= str_cat2(result
, str_printf("%scall BBGetLength\n", c_pad
));
436 node_set(node
, result
);
437 node_free(node
->bottom
);
440 void core_set_length(TreeNode
*node
) {
441 node_traverse(node
->bottom
);
442 char *blob
= core_translate_var(node
->bottom
->next
->code
);
443 char *result
= strdup(node
->bottom
->code
);
444 result
= str_cat2(result
, str_printf("%spush %s\n", c_pad
, blob
));
445 result
= str_cat2(result
, str_printf("%scall BBSetLength\n", c_pad
));
446 result
= str_cat2(result
, str_printf("%stop %s\n", c_pad
, blob
));
447 result
= str_cat2(result
, str_printf("%spop\n", c_pad
));
448 node_set(node
, result
);
450 node_free(node
->bottom
->next
);
451 node_free(node
->bottom
);
455 void core_get_element(TreeNode
*node
) {
456 node_traverse(node
->bottom
);
457 node_traverse(node
->bottom
->next
);
458 char *result
= strdup(node
->bottom
->code
);
459 result
= str_cat(result
, node
->bottom
->next
->code
);
460 result
= str_cat2(result
, str_printf("%scall BBGetElement\n", c_pad
));
461 node_set(node
, result
);
462 node_free(node
->bottom
->next
);
463 node_free(node
->bottom
);
467 void core_set_element(TreeNode
*node
) {
468 node_traverse(node
->bottom
);
469 node_traverse(node
->bottom
->next
);
470 char *blob
= core_translate_var(node
->bottom
->next
->next
->code
);
471 char *result
= strdup(node
->bottom
->code
);
472 result
= str_cat(result
, node
->bottom
->next
->code
);
473 result
= str_cat2(result
, str_printf("%spush %s\n", c_pad
, blob
));
474 result
= str_cat2(result
, str_printf("%scall BBSetElement\n", c_pad
));
475 result
= str_cat2(result
, str_printf("%stop %s\n", c_pad
, blob
));
476 result
= str_cat2(result
, str_printf("%spop\n", c_pad
));
477 node_set(node
, result
);
479 node_free(node
->bottom
->next
->next
);
480 node_free(node
->bottom
->next
);
481 node_free(node
->bottom
);
485 void core_line(TreeNode
*node
) {
486 node_traverse(node
->bottom
);
487 node_set(node
, strdup(node
->bottom
->code
));
488 node_free(node
->bottom
);
491 void core_codeblock(TreeNode
*node
) {
492 TreeNode
*iterator
= node
->bottom
;
493 TreeNode
*last
= iterator
->previous
;
494 node_traverse(iterator
);
495 char *result
= strdup(iterator
->code
);
496 while (iterator
!= last
) {
497 iterator
= iterator
->next
;
498 node_free(iterator
->previous
);
499 node_traverse(iterator
);
500 result
= str_cat(result
, iterator
->code
);
502 node_set(node
, result
);
506 void core_initialize() {
507 c_error
= strdup("");
510 node_bottom(root
, node_new());
511 nodefunc
[NODE_EMPTY
] = core_empty
;
512 nodefunc
[NODE_ROOT
] = NULL
;
513 nodefunc
[NODE_FUNCTION
] = core_function
;
514 nodefunc
[NODE_FUNC_ARGS
] = core_func_args
;
515 nodefunc
[NODE_RETURN
] = core_return
;
516 nodefunc
[NODE_IF
] = core_if
;
517 nodefunc
[NODE_WHILE
] = core_while
;
518 nodefunc
[NODE_PUSH_VAR
] = core_push_var
;
519 nodefunc
[NODE_PUSH_BOOL
] = core_push_bool
;
520 nodefunc
[NODE_PUSH_DEC
] = core_push_dec
;
521 nodefunc
[NODE_PUSH_HEX
] = core_push_hex
;
522 nodefunc
[NODE_PUSH_STR
] = core_push_str
;
523 nodefunc
[NODE_CALLFN
] = core_callfn
;
524 nodefunc
[NODE_CALL_ARGS
] = core_call_args
;
525 nodefunc
[NODE_VOID_RETURN
] = core_void_return
;
526 nodefunc
[NODE_ARIT_BINARY
] = core_arit_binary
;
527 nodefunc
[NODE_ARIT_UNARY
] = core_arit_unary
;
528 nodefunc
[NODE_SET_VARIABLE
] = core_set_variable
;
529 nodefunc
[NODE_GET_LENGTH
] = core_get_length
;
530 nodefunc
[NODE_SET_LENGTH
] = core_set_length
;
531 nodefunc
[NODE_GET_ELEMENT
] = core_get_element
;
532 nodefunc
[NODE_SET_ELEMENT
] = core_set_element
;
533 nodefunc
[NODE_LINE
] = core_line
;
534 nodefunc
[NODE_CODEBLOCK
] = core_codeblock
;
535 addFunction("get_chr", 0);
536 addFunction("get_int", 0);
537 addFunction("out_str", 0);
540 void core_finalize() {
548 TreeNode
*iterator
= root
;
549 TreeNode
*last
= root
->previous
;
550 node_traverse(iterator
->bottom
);
551 node_free(iterator
->bottom
);
552 while (iterator
!= last
) {
553 iterator
= iterator
->next
;
554 node_free(iterator
->previous
);
555 node_traverse(iterator
->bottom
);
556 node_free(iterator
->bottom
);
559 int bob
= varFunction("BoB");
561 core_error(strdup("Error: Function BoB() not defined!\n"));
563 char *msg
= strdup("Error: BoB() should have 0 parameters!");
564 msg
= str_cat2(msg
, str_printf(" (has %d)\n", bob
));
569 varInvalidFunctionCalls(&names
, &count
);
570 for (i
= 0; i
< count
; i
++) {
571 core_error(str_printf("Error: Incorrect call to function \"%s\"!\n", names
[i
]));
574 char *global
= varGlobalNo(i
);
575 fputs("BoBInit:\n", c_output
);
576 while (global
!= NULL
) {
577 fputs(" call BBFalse\n", c_output
);
578 fprintf(c_output
, " top %s\n", global
);
579 fputs(" pop\n", c_output
);
581 global
= varGlobalNo(i
);
583 fputs(" call fnBoBStart\n", c_output
);
584 fputs(c_error
, stderr
);