RPA Toolkit
73643c612055a9b866db634a0d9b7d4ea9f72d7f
[rpatk.git] / tests / rpagen-test.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <sys/types.h>
6 #include <fcntl.h>
7 #include <unistd.h>
8 #include <sys/mman.h>
9 #include "rmem.h"
10 #include "rvmcpu.h"
11 #include "rpadbex.h"
12 #include "rpaerror.h"
13 #include "rvmcodegen.h"
14 #include "rvmcodemap.h"
15 #include "rvmscope.h"
16 #include "rvmoperator.h"
17
18 #define DEBUGPRINT 1
19 static int debuginfo = 0;
20 static int parseinfo = 0;
21 static int verboseinfo = 0;
22 static int compileonly = 0;
23
24 typedef struct rvm_vardeclaration_s {
25         const rchar *varname;
26         ruint varnamesiz;
27         const rchar *val;
28         ruint valsiz;
29 } rvm_vardeclaration_t;
30
31
32 typedef struct rvm_fundecl_s {
33         const rchar *funname;
34         rword funnamesiz;
35         rword params;
36         rword codestart;
37         rword codesize;
38 } rvm_fundecl_t;
39
40
41 typedef struct rvm_funcall_s {
42         const rchar *funname;
43         rword funnamesiz;
44         rword params;
45 } rvm_funcall_t;
46
47
48 typedef enum {
49         RVM_CODESPAN_NONE = 0,
50         RVM_CODESPAN_LOOP,
51 } rvm_codespantype_t;
52
53 typedef struct rvm_codespan_s {
54         rvm_codespantype_t type;
55         rword codestart;
56         rword codesize;
57         rword l1;
58         rword l2;
59         rword l3;
60         rword l4;
61 } rvm_codespan_t;
62
63
64 typedef struct rvm_costat_s rvm_costat_t;
65
66 struct rvm_costat_s {
67         ruint binaryop;
68         ruint level;
69         ruint dirty;
70         ruint funcalls;
71         rvm_costat_t *root;
72 };
73
74 typedef struct rvm_compiler_s {
75         rpa_dbex_handle dbex;
76         rvm_codegen_t *cg;
77         rvm_scope_t *scope;
78         rarray_t *fp;
79         rarray_t *funcall;
80         rarray_t *fundecl;
81         rarray_t *opcodes;
82         rarray_t *codespan;
83         rarray_t *varmap;
84         rarray_t *stat;
85         rvmcpu_t *cpu;
86         rboolean optimized;
87 } rvm_compiler_t;
88
89
90
91 #define RVM_SAVEDREGS_FIRST 4
92 #define RVM_SAVEDREGS_MAX (RLST - (RLST - FP) - RVM_SAVEDREGS_FIRST - 1)
93
94
95 void rpagen_load_rules(rpa_dbex_handle dbex, rvm_compiler_t *co);
96
97 rvm_costat_t *rvm_costat_current(rvm_compiler_t *co)
98 {
99         return (rvm_costat_t *)r_array_lastslot(co->stat);
100 }
101
102
103 ruint rvm_costat_getdebth(rvm_compiler_t *co)
104 {
105         return r_array_length(co->stat);
106 }
107
108 ruint rvm_costat_getlevel(rvm_compiler_t *co)
109 {
110         if (!rvm_costat_current(co))
111                 return 0;
112         return rvm_costat_current(co)->level;
113 }
114
115
116 void rvm_costat_inclevel(rvm_compiler_t *co)
117 {
118         rvm_costat_current(co)->level += 1;
119         if (rvm_costat_current(co)->level > rvm_costat_current(co)->root->dirty)
120                 rvm_costat_current(co)->root->dirty = rvm_costat_current(co)->level;
121 }
122
123 void rvm_costat_declevel(rvm_compiler_t *co)
124 {
125         rvm_costat_current(co)->level -= 1;
126 }
127
128
129 ruint rvm_costat_getbinaryop(rvm_compiler_t *co)
130 {
131         if (!rvm_costat_current(co))
132                 return 0;
133         return rvm_costat_current(co)->binaryop;
134 }
135
136
137 void rvm_costat_incbinaryop(rvm_compiler_t *co)
138 {
139         rvm_costat_current(co)->binaryop += 1;
140 }
141
142
143 void rvm_costat_decbinaryop(rvm_compiler_t *co)
144 {
145         rvm_costat_current(co)->binaryop -= 1;
146 }
147
148 ruint rvm_costat_getdirty(rvm_compiler_t *co)
149 {
150         if (!rvm_costat_current(co))
151                 return 0;
152         return rvm_costat_current(co)->root->dirty;
153 }
154
155
156 void rvm_costat_push(rvm_compiler_t *co)
157 {
158         rvm_costat_t stat = *rvm_costat_current(co);
159         stat.binaryop = 0;
160         r_array_add(co->stat, &stat);
161 }
162
163
164 void rvm_costat_pushroot(rvm_compiler_t *co)
165 {
166         rvm_costat_t stat;
167         r_memset(&stat, 0, sizeof(stat));
168         r_array_add(co->stat, &stat);
169         rvm_costat_current(co)->root = rvm_costat_current(co);
170 }
171
172 void rvm_costat_pop(rvm_compiler_t *co)
173 {
174         r_array_removelast(co->stat);
175 }
176
177
178
179 rvm_compiler_t *rvm_compiler_create(rpa_dbex_handle dbex)
180 {
181         rvm_compiler_t *co;
182
183         co = r_malloc(sizeof(*co));
184         r_memset(co, 0, sizeof(*co));
185         co->cg = rvm_codegen_create();
186         co->scope = rvm_scope_create();
187         co->opcodes = r_array_create(sizeof(ruint));
188         co->fp = r_array_create(sizeof(rword));
189         co->funcall = r_array_create(sizeof(rvm_funcall_t));
190         co->stat = r_array_create(sizeof(rvm_costat_t));
191         co->fundecl = r_array_create(sizeof(rvm_fundecl_t));
192         co->codespan = r_array_create(sizeof(rvm_codespan_t));
193         co->varmap = r_array_create(sizeof(rvm_varmap_t*));
194         r_array_push(co->fp, 0, rword);
195         co->dbex = dbex;
196         return co;
197 }
198
199
200 void rvm_compiler_destroy(rvm_compiler_t *co)
201 {
202         if (co) {
203                 rvm_codegen_destroy(co->cg);
204                 rvm_scope_destroy(co->scope);
205                 r_object_destroy((robject_t*) co->opcodes);
206                 r_object_destroy((robject_t*) co->stat);
207                 r_object_destroy((robject_t*) co->fp);
208                 r_object_destroy((robject_t*) co->funcall);
209                 r_object_destroy((robject_t*) co->fundecl);
210                 r_object_destroy((robject_t*) co->codespan);
211                 r_object_destroy((robject_t*) co->varmap);
212                 r_free(co);
213         }
214 }
215
216
217 static void test_swi_none(rvmcpu_t *cpu, rvm_asmins_t *ins)
218 {
219 }
220
221
222 static void rvm_swi_negative(rvmcpu_t *cpu, rvm_asmins_t *ins)
223 {
224         rvmreg_t *res = RVM_CPUREG_PTR(cpu, ins->op1);
225         rvmreg_t *arg = RVM_CPUREG_PTR(cpu, ins->op2);
226         rvmreg_t zero;
227
228         RVM_REG_CLEAR(&zero);
229         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_SUB, cpu, res, &zero, arg);
230 }
231
232
233 static void rvm_swi_eadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
234 {
235         rvmreg_t *res = RVM_CPUREG_PTR(cpu, R0);
236         rvmreg_t *arg1 = (rvmreg_t *)RVM_STACK_ADDR(cpu->stack, RVM_CPUREG_GETU(cpu, FP) + 1);
237         rvmreg_t *arg2 = (rvmreg_t *)RVM_STACK_ADDR(cpu->stack, RVM_CPUREG_GETU(cpu, FP) + 2);
238
239         rvm_opmap_invoke_binary_handler(cpu->opmap, RVM_OPID_ADD, cpu, res, arg1, arg2);
240 }
241
242
243 static rvm_switable_t switable[] = {
244                 {"none", test_swi_none},
245                 {"RVM_SWI_NEG", rvm_swi_negative},
246                 {"rvm_swi_eadd", rvm_swi_eadd},
247                 {NULL, NULL},
248 };
249
250
251 static void rvm_js_print(rvmcpu_t *cpu, rvm_asmins_t *ins)
252 {
253         rvmreg_t *r = (rvmreg_t *)RVM_STACK_ADDR(cpu->stack, RVM_CPUREG_GETU(cpu, FP) + 1);
254
255         if (rvm_reg_gettype(r) == RVM_DTYPE_UNSIGNED)
256                 r_printf("%lu\n", RVM_REG_GETU(r));
257         else if (rvm_reg_gettype(r) == RVM_DTYPE_BOOLEAN)
258                 r_printf("%s\n", RVM_REG_GETU(r) ? "true" : "false");
259         else if (rvm_reg_gettype(r) == RVM_DTYPE_POINTER)
260                 r_printf("%p\n", RVM_REG_GETP(r));
261         else if (rvm_reg_gettype(r) == RVM_DTYPE_LONG)
262                 r_printf("%ld\n", RVM_REG_GETL(r));
263         else if (rvm_reg_gettype(r) == RVM_DTYPE_DOUBLE)
264                 r_printf("%f\n", RVM_REG_GETD(r));
265         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRING)
266                 r_printf("%s\n", ((rstring_t*) RVM_REG_GETP(r))->s.str);
267         else if (rvm_reg_gettype(r) == RVM_DTYPE_ARRAY)
268                 r_printf("(array) %p\n",RVM_REG_GETP(r));
269         else if (rvm_reg_gettype(r) == RVM_DTYPE_SWIID)
270                 r_printf("(function) %p\n",RVM_REG_GETP(r));
271         else
272                 r_printf("%p\n", RVM_REG_GETP(r));
273 }
274
275 static rvm_switable_t switable_js[] = {
276                 {"print", rvm_js_print},
277                 {NULL, NULL},
278 };
279
280 inline int codegen_print_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
281 {
282         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
283
284         if (parseinfo) {
285                 if (reason & RPA_REASON_START)
286                         fprintf(stdout, "START ");
287                 if (reason & RPA_REASON_MATCHED)
288                         fprintf(stdout, "MATCHED ");
289                 if (reason & RPA_REASON_END)
290                         fprintf(stdout, "END ");
291                 fprintf(stdout, "%s: ", name);
292                 if (!(reason & RPA_REASON_START))
293                                 fwrite(input, sizeof(char), size, stdout);
294                 fprintf(stdout, " (debth: %d, level: %d, binaryop: %d, dirty: %d)", rvm_costat_getdebth(co), rvm_costat_getlevel(co), rvm_costat_getbinaryop(co), rvm_costat_getdirty(co));
295                 fprintf(stdout, "\n");
296                 fflush(stdout);
297         }
298
299         return size;
300 }
301
302
303 void codegen_dump_code(rvm_asmins_t *code, rulong size)
304 {
305         if (parseinfo)
306                 rvm_asm_dump(code, size);
307 }
308
309
310 int codegen_opcode_unary_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
311 {
312         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
313
314         if (r_stringncmp("-", input, size))
315                 r_array_push(co->opcodes, RVM_OPSWI(rvm_cpu_getswi_s(co->cpu, "RVM_SWI_NEG")), ruint);
316         else if (r_stringncmp("+", input, size))
317                 r_array_push(co->opcodes, RVM_NOP, ruint);
318         else if (r_stringncmp("delete", input, size))
319                 r_array_push(co->opcodes, RVM_NOP, ruint);
320         else if (r_stringncmp("void", input, size))
321                 r_array_push(co->opcodes, RVM_NOP, ruint);
322         else if (r_stringncmp("typeof", input, size))
323                 r_array_push(co->opcodes, RVM_NOP, ruint);
324
325         else
326                 r_array_push(co->opcodes, RVM_ABORT, ruint);
327
328         codegen_print_callback(name, userdata, input, size, reason, start, end);
329         return size;
330 }
331
332
333 int codegen_opcode_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
334 {
335         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
336
337         if (r_stringncmp("++", input,  size))
338                 r_array_push(co->opcodes, RVM_EADD, ruint);
339         else if (r_stringncmp("+", input,  size))
340                 r_array_push(co->opcodes, RVM_EADD, ruint);
341         else if (r_stringncmp("+=", input,  size))
342                 r_array_push(co->opcodes, RVM_EADD, ruint);
343         else if (r_stringncmp("--", input,  size))
344                 r_array_push(co->opcodes, RVM_ESUB, ruint);
345         else if (r_stringncmp("-", input,  size))
346                 r_array_push(co->opcodes, RVM_ESUB, ruint);
347         else if (r_stringncmp("-=", input,  size))
348                 r_array_push(co->opcodes, RVM_ESUB, ruint);
349         else if (r_stringncmp("*", input,  size))
350                 r_array_push(co->opcodes, RVM_EMUL, ruint);
351         else if (r_stringncmp("*=", input,  size))
352                 r_array_push(co->opcodes, RVM_EMUL, ruint);
353         else if (r_stringncmp("/", input,  size))
354                 r_array_push(co->opcodes, RVM_EDIV, ruint);
355         else if (r_stringncmp("/=", input,  size))
356                 r_array_push(co->opcodes, RVM_EDIV, ruint);
357         else if (r_stringncmp("%", input,  size))
358                 r_array_push(co->opcodes, RVM_EMOD, ruint);
359         else if (r_stringncmp("%=", input,  size))
360                 r_array_push(co->opcodes, RVM_EMOD, ruint);
361         else if (r_stringncmp("&&", input,  size))
362                 r_array_push(co->opcodes, RVM_ELAND, ruint);
363         else if (r_stringncmp("||", input,  size))
364                 r_array_push(co->opcodes, RVM_ELOR, ruint);
365         else if (r_stringncmp("&", input,  size))
366                 r_array_push(co->opcodes, RVM_EAND, ruint);
367         else if (r_stringncmp("&=", input,  size))
368                 r_array_push(co->opcodes, RVM_EAND, ruint);
369         else if (r_stringncmp("|", input,  size))
370                 r_array_push(co->opcodes, RVM_EORR, ruint);
371         else if (r_stringncmp("|=", input,  size))
372                 r_array_push(co->opcodes, RVM_EORR, ruint);
373         else if (r_stringncmp("^", input,  size))
374                 r_array_push(co->opcodes, RVM_EXOR, ruint);
375         else if (r_stringncmp("^=", input,  size))
376                 r_array_push(co->opcodes, RVM_EXOR, ruint);
377         else if (r_stringncmp(">>", input,  size))
378                 r_array_push(co->opcodes, RVM_ELSR, ruint);
379         else if (r_stringncmp(">>=", input,  size))
380                 r_array_push(co->opcodes, RVM_ELSR, ruint);
381         else if (r_stringncmp("<<", input,  size))
382                 r_array_push(co->opcodes, RVM_ELSL, ruint);
383         else if (r_stringncmp("<<=", input,  size))
384                 r_array_push(co->opcodes, RVM_ELSL, ruint);
385         else if (r_stringncmp(">>>", input,  size))
386                 r_array_push(co->opcodes, RVM_ELSRU, ruint);
387         else if (r_stringncmp(">>>=", input,  size))
388                 r_array_push(co->opcodes, RVM_ELSRU, ruint);
389         else if (r_stringncmp("<=", input,  size))
390                 r_array_push(co->opcodes, RVM_ELESSEQ, ruint);
391         else if (r_stringncmp(">=", input,  size))
392                 r_array_push(co->opcodes, RVM_EGREATEQ, ruint);
393         else if (r_stringncmp("<", input,  size))
394                 r_array_push(co->opcodes, RVM_ELESS, ruint);
395         else if (r_stringncmp(">", input,  size))
396                 r_array_push(co->opcodes, RVM_EGREAT, ruint);
397         else if (r_stringncmp("===", input,  size))
398                 r_array_push(co->opcodes, RVM_EEQ, ruint);
399         else if (r_stringncmp("==", input,  size))
400                 r_array_push(co->opcodes, RVM_EEQ, ruint);
401         else if (r_stringncmp("!==", input,  size))
402                 r_array_push(co->opcodes, RVM_ENOTEQ, ruint);
403         else if (r_stringncmp("!=", input,  size))
404                 r_array_push(co->opcodes, RVM_ENOTEQ, ruint);
405         else if (r_stringncmp("!", input,  size))
406                 r_array_push(co->opcodes, RVM_ELNOT, ruint);
407         else if (r_stringncmp("~", input,  size))
408                 r_array_push(co->opcodes, RVM_ENOT, ruint);
409         else if (r_stringncmp("=", input,  size))
410                 r_array_push(co->opcodes, RVM_NOP, ruint);
411         else
412                 r_array_push(co->opcodes, RVM_ABORT, ruint);
413
414         codegen_print_callback(name, userdata, input, size, reason, start, end);
415         return size;
416 }
417
418
419 int codegen_binary_asmop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
420 {
421         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
422         rulong off = rvm_codegen_getcodesize(co->cg);
423
424         if (reason & RPA_REASON_START) {
425                 rvm_costat_inclevel(co);
426                 rvm_costat_incbinaryop(co);
427         } else if (reason & RPA_REASON_MATCHED) {
428                 ruint op1;
429                 ruint opcode = r_array_pop(co->opcodes, ruint);
430
431                 if (rvm_costat_getlevel(co) < RVM_SAVEDREGS_MAX) {
432                         op1 = rvm_costat_getlevel(co) + RVM_SAVEDREGS_FIRST - 1;
433                 } else {
434                         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
435                         op1 = R1;
436                 }
437                 rvm_codegen_addins(co->cg, rvm_asm(opcode, R0, op1, R0, 0));
438                 rvm_costat_declevel(co);
439                 rvm_costat_decbinaryop(co);
440         } else if (reason & RPA_REASON_END) {
441                 rvm_costat_declevel(co);
442                 rvm_costat_decbinaryop(co);
443         }
444
445         codegen_print_callback(name, userdata, input, size, reason, start, end);
446         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
447
448         return size;
449 }
450
451
452 int codegen_valop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
453 {
454         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
455         rulong off = rvm_codegen_getcodesize(co->cg);
456         rvm_asmins_t *last = rvm_codegen_getcode(co->cg, off - 1);
457
458         if ((reason & RPA_REASON_START) && rvm_costat_getbinaryop(co)) {
459                 if (rvm_costat_getlevel(co) < RVM_SAVEDREGS_MAX) {
460                         if (co->optimized && last->op1 == R0 && (last->opcode == RVM_MOV || last->opcode == RVM_LDRR ||
461                                         last->opcode == RVM_LDS || (last->opcode >= RVM_EADD && last->opcode <= RVM_ELESSEQ))) {
462                                 last->op1 = rvm_costat_getlevel(co) + RVM_SAVEDREGS_FIRST - 1;
463                                 off -= 1;
464                         } else {
465                                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, rvm_costat_getlevel(co) + RVM_SAVEDREGS_FIRST - 1, R0, XX, 0));
466                         }
467                 } else {
468                         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
469                 }
470         }
471
472
473         if (reason & RPA_REASON_MATCHED) {
474
475         }
476
477         codegen_print_callback(name, userdata, input, size, reason, start, end);
478         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
479
480         return size;
481 }
482
483
484 int codegen_conditionalexp_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
485 {
486         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
487         rulong off = rvm_codegen_getcodesize(co->cg);
488
489         codegen_print_callback(name, userdata, input, size, reason, start, end);
490         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
491
492         return size;
493 }
494
495
496 int codegen_unary_asmop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
497 {
498         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
499         rulong off = rvm_codegen_getcodesize(co->cg);
500         ruint op1 = rvm_costat_getlevel(co) ? RVM_SAVEDREGS_FIRST - 1 + rvm_costat_getlevel(co) : R0;
501
502         if (reason & RPA_REASON_START) {
503         }
504
505         if (reason & RPA_REASON_MATCHED) {
506                 ruint opcode = r_array_pop(co->opcodes, ruint);
507                 rvm_codegen_addins(co->cg, rvm_asm(opcode, op1, op1, XX, 0));
508         }
509
510         if (reason & RPA_REASON_END) {
511         }
512
513         codegen_print_callback(name, userdata, input, size, reason, start, end);
514         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
515         return size;
516 }
517
518
519 int codegen_costate_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
520 {
521         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
522         rulong off = rvm_codegen_getcodesize(co->cg);
523
524         if (reason & RPA_REASON_START) {
525                 rvm_costat_push(co);
526         }
527
528         if (reason & RPA_REASON_END) {
529                 rvm_costat_pop(co);
530         }
531
532         codegen_print_callback(name, userdata, input, size, reason, start, end);
533         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
534         return size;
535 }
536
537
538 int codegen_push_r0_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
539 {
540         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
541         rulong off = rvm_codegen_getcodesize(co->cg);
542
543         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
544
545         codegen_print_callback(name, userdata, input, size, reason, start, end);
546         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
547
548         return size;
549 }
550
551
552 int codegen_integer_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
553 {
554         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
555         rulong off = rvm_codegen_getcodesize(co->cg);
556
557         rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R0, DA, XX, r_strtol(input, NULL, 10)));
558
559         codegen_print_callback(name, userdata, input, size, reason, start, end);
560         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
561
562         return size;
563 }
564
565
566 int codegen_printop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
567 {
568         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
569         rulong off = rvm_codegen_getcodesize(co->cg);
570
571         rvm_codegen_addins(co->cg, rvm_asmd(RVM_PRN, R0, DA, XX, 0));
572
573         codegen_print_callback(name, userdata, input, size, reason, start, end);
574         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
575
576         return size;
577 }
578
579
580 int codegen_double_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
581 {
582         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
583         rulong off = rvm_codegen_getcodesize(co->cg);
584
585         rvm_codegen_addins(co->cg, rvm_asmd(RVM_MOV, R0, DA, XX, r_strtod(input, NULL)));
586
587         codegen_print_callback(name, userdata, input, size, reason, start, end);
588         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
589
590         return size;
591 }
592
593
594 int codegen_string_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
595 {
596         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
597         rulong off = rvm_codegen_getcodesize(co->cg);
598
599         rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R1, DA, XX, (void*)input));
600         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R2, DA, XX, size));
601         rvm_codegen_addins(co->cg, rvm_asm(RVM_ALLOCSTR, R0, R1, R2, 0));
602
603         codegen_print_callback(name, userdata, input, size, reason, start, end);
604         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
605
606         return size;
607 }
608
609
610 int codegen_program_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
611 {
612         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
613         ruint off;
614
615         if (reason & RPA_REASON_START) {
616                 off = rvm_codegen_getcodesize(co->cg);
617                 rvm_costat_pushroot(co);
618                 rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
619                 rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
620         } else {
621                 rvm_codegen_replaceins(co->cg, 0, rvm_asm(RVM_MOV, FP, SP, XX, 0));
622                 rvm_codegen_replaceins(co->cg, 1, rvm_asm(RVM_ADD, SP, SP, DA, r_array_pop(co->fp, rword)));
623                 off = rvm_codegen_getcodesize(co->cg);
624                 if (debuginfo)
625                         rvm_codegen_addins(co->cg, rvm_asm(RVM_PRN, R0, XX, XX, 0));
626                 rvm_codegen_addins(co->cg, rvm_asm(RVM_EXT, XX, XX, XX, 0));
627         }
628
629
630         codegen_print_callback(name, userdata, input, size, reason, start, end);
631         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
632
633         if (reason & RPA_REASON_END) {
634                 rvm_costat_pop(co);
635         }
636         return size;
637 }
638
639
640 int codegen_opinit_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
641 {
642         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
643         rulong off = rvm_codegen_getcodesize(co->cg);
644
645         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
646         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
647
648         codegen_print_callback(name, userdata, input, size, reason, start, end);
649         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
650
651         return size;
652 }
653
654
655 int codegen_opassign_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
656 {
657         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
658         rulong off = rvm_codegen_getcodesize(co->cg);
659         ruint opcode = r_array_pop(co->opcodes, ruint);
660
661         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
662         if (opcode != RVM_NOP) {
663                 rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R2, R1, XX, 0));
664                 rvm_codegen_addins(co->cg, rvm_asm(opcode, R0, R2, R0, 0));
665         }
666         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
667
668         codegen_print_callback(name, userdata, input, size, reason, start, end);
669         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
670
671         return size;
672 }
673
674
675 int codegen_oppostfix_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
676 {
677         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
678         rulong off = rvm_codegen_getcodesize(co->cg);
679         ruint opcode = r_array_pop(co->opcodes, ruint);
680
681         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R0, XX, 0));
682         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R1, XX, 0));
683         rvm_codegen_addins(co->cg, rvm_asm(opcode, R2, R0, DA, 1));
684         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R2, R1, XX, 0));
685
686
687         codegen_print_callback(name, userdata, input, size, reason, start, end);
688         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
689
690         return size;
691 }
692
693
694 int codegen_opprefix_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
695 {
696         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
697         rulong off = rvm_codegen_getcodesize(co->cg);
698         ruint opcode = r_array_pop(co->opcodes, ruint);
699
700         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R0, XX, 0));
701         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R1, XX, 0));
702         rvm_codegen_addins(co->cg, rvm_asm(opcode, R0, R0, DA, 1));
703         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
704
705         codegen_print_callback(name, userdata, input, size, reason, start, end);
706         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
707
708         return size;
709 }
710
711
712 int codegen_ptr_deref_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
713 {
714         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
715         rulong off = rvm_codegen_getcodesize(co->cg);
716
717         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));    // Address
718         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R1, XX, 0));   // Load the value from offset
719         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));   // Push it on the stack
720
721         codegen_print_callback(name, userdata, input, size, reason, start, end);
722         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
723
724         return size;
725 }
726
727
728 int codegen_arrayelementvalue_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
729 {
730         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
731         rulong off = rvm_codegen_getcodesize(co->cg);
732
733         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));    // Array
734         rvm_codegen_addins(co->cg, rvm_asm(RVM_ELDA, R0, R1, R0, 0));   // Load the value from array offset
735
736         codegen_print_callback(name, userdata, input, size, reason, start, end);
737         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
738
739         return size;
740 }
741
742
743 int codegen_memberexpressionbase_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
744 {
745         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
746         rulong off = rvm_codegen_getcodesize(co->cg);
747
748         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R0, XX, 0));   // Array Address
749         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));   // Array -> On Stack
750
751         codegen_print_callback(name, userdata, input, size, reason, start, end);
752         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
753
754         return size;
755 }
756
757
758 int codegen_arrayelementaddress_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
759 {
760         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
761         rulong off = rvm_codegen_getcodesize(co->cg);
762
763         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));    // Supposedly Array Address
764         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDRA, R0, R1, R0, 0));  // Get the address of the element at offset R0
765
766         codegen_print_callback(name, userdata, input, size, reason, start, end);
767         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
768
769         return size;
770 }
771
772
773 int codegen_offset_to_ptr_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
774 {
775         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
776         rulong off = rvm_codegen_getcodesize(co->cg);
777
778         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R2, XX, XX, 0));    // Offset
779         rvm_codegen_addins(co->cg, rvm_asm(RVM_CAST, R2, R2, DA, RVM_DTYPE_UNSIGNED));  // cast to unsigned
780         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));    // Array
781         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDRA, R0, R1, R2, 0));  // Pointer to element at offset
782         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));   // Push it on the stack
783
784         codegen_print_callback(name, userdata, input, size, reason, start, end);
785         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
786
787         return size;
788 }
789
790
791 int codegen_swiidexist_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
792 {
793         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
794         rint swi = rvm_cpu_getswi(co->cpu, input, size);
795
796         if (swi < 0)
797                 return 0;
798
799
800         return size;
801 }
802
803
804 int codegen_swiid_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
805 {
806         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
807         rulong off = rvm_codegen_getcodesize(co->cg);
808         rint swi = rvm_cpu_getswi(co->cpu, input, size);
809
810         if (swi < 0)
811                 return 0;
812
813         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, swi));
814         rvm_codegen_addins(co->cg, rvm_asm(RVM_SETTYPE, R0, DA, XX, RVM_DTYPE_SWIID));
815
816         codegen_print_callback(name, userdata, input, size, reason, start, end);
817         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
818
819         return size;
820 }
821
822
823 int codegen_opidentifier_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
824 {
825         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
826         rulong off = rvm_codegen_getcodesize(co->cg);
827         rvm_varmap_t *v = rvm_scope_lookup(co->scope, input, size);
828
829         if (v) {
830                 if (v->datatype == VARMAP_DATATYPE_OFFSET) {
831                         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDRS, R0, FP, DA, v->data.offset));
832                 } else {
833                         rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R0, DA, XX, v->data.ptr));
834                 }
835                 codegen_print_callback(name, userdata, input, size, reason, start, end);
836                 codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
837
838                 return size;
839         }
840
841         fprintf(stdout, "ERROR: undefined variable: ");
842         fwrite(input, sizeof(char), size, stdout);
843         fprintf(stdout, "\n");
844         rpa_dbex_abort(co->dbex);
845         return 0;
846 }
847
848
849 int codegen_validentifierop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
850 {
851         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
852         rulong off = rvm_codegen_getcodesize(co->cg);
853         rvm_varmap_t *v = rvm_scope_lookup(co->scope, input, size);
854
855         if (v) {
856                 if (v->datatype == VARMAP_DATATYPE_OFFSET) {
857                         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDS, R0, FP, DA, v->data.offset));
858                 } else {
859                         rvm_codegen_addins(co->cg, rvm_asmp(RVM_LDRR, R0, DA, XX, v->data.ptr));
860                 }
861                 codegen_print_callback(name, userdata, input, size, reason, start, end);
862                 codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
863
864                 return size;
865         }
866
867         fprintf(stdout, "ERROR: undefined variable: ");
868         fwrite(input, sizeof(char), size, stdout);
869         fprintf(stdout, "\n");
870         rpa_dbex_abort(co->dbex);
871         return 0;
872 }
873
874
875 int codegen_varalloc_to_ptr_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
876 {
877         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
878         rulong off = rvm_codegen_getcodesize(co->cg);
879         rvm_varmap_t *v = rvm_scope_tiplookup(co->scope, input, size);
880         if (v) {
881                 fprintf(stdout, "ERROR: variable already defined: ");
882                 fwrite(input, sizeof(char), size, stdout);
883                 fprintf(stdout, "\n");
884                 rpa_dbex_abort(co->dbex);
885                 return 0;
886         }
887
888         if (rvm_scope_count(co->scope)) {
889                 r_array_inclast(co->fp, rword);
890                 rvm_scope_addoffset(co->scope, input, size, r_array_last(co->fp, rword));
891         } else {
892                 rvm_scope_addpointer(co->scope, input, size, r_carray_slot_expand(co->cpu->data, r_carray_length(co->cpu->data)));
893                 r_carray_inclength(co->cpu->data);
894         }
895         v = rvm_scope_tiplookup(co->scope, input, size);
896
897         if (v->datatype == VARMAP_DATATYPE_OFFSET) {
898                 rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDRS, R0, FP, DA, v->data.offset));
899         } else {
900                 rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R0, DA, XX, v->data.ptr));
901         }
902         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
903
904         codegen_print_callback(name, userdata, input, size, reason, start, end);
905         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
906
907         return size;
908 }
909
910
911 int codegen_varalloc_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
912 {
913         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
914         rulong off = rvm_codegen_getcodesize(co->cg);
915         rvm_varmap_t *v = rvm_scope_tiplookup(co->scope, input, size);
916         if (v) {
917                 fprintf(stdout, "ERROR: variable already defined: ");
918                 fwrite(input, sizeof(char), size, stdout);
919                 fprintf(stdout, "\n");
920                 rpa_dbex_abort(co->dbex);
921                 return 0;
922         }
923
924         if (rvm_scope_count(co->scope)) {
925                 r_array_inclast(co->fp, rword);
926                 rvm_scope_addoffset(co->scope, input, size, r_array_last(co->fp, rword));
927         } else {
928                 rvm_scope_addpointer(co->scope, input, size, r_carray_slot_expand(co->cpu->data, r_carray_length(co->cpu->data)));
929                 r_carray_inclength(co->cpu->data);
930         }
931
932         codegen_print_callback(name, userdata, input, size, reason, start, end);
933         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
934
935         return size;
936 }
937
938
939 int codegen_newarraysize_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
940 {
941         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
942         rulong off = rvm_codegen_getcodesize(co->cg);
943
944         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R0, XX, 0));
945         rvm_codegen_addins(co->cg, rvm_asm(RVM_ALLOCARR, R0, R1, XX, 0));
946
947         codegen_print_callback(name, userdata, input, size, reason, start, end);
948         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
949
950         return size;
951 }
952
953
954 int codegen_newarraynosize_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
955 {
956         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
957         rulong off = rvm_codegen_getcodesize(co->cg);
958
959         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, DA, XX, 0));
960         rvm_codegen_addins(co->cg, rvm_asm(RVM_ALLOCARR, R0, R1, XX, 0));
961 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
962
963         codegen_print_callback(name, userdata, input, size, reason, start, end);
964         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
965
966         return size;
967 }
968
969
970 int codegen_scopepush_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
971 {
972         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
973         rulong off = rvm_codegen_getcodesize(co->cg);
974
975         rvm_scope_push(co->scope);
976         codegen_print_callback(name, userdata, input, size, reason, start, end);
977         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
978
979         return size;
980 }
981
982
983 int codegen_scopepop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
984 {
985         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
986         rulong off = rvm_codegen_getcodesize(co->cg);
987
988         rvm_scope_pop(co->scope);
989         codegen_print_callback(name, userdata, input, size, reason, start, end);
990         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
991
992         return size;
993 }
994
995
996 int codegen_compile_error_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
997 {
998         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
999         fprintf(stdout, "COMPILE ERROR pos: %ld\n", (long) (input - start));
1000         rpa_dbex_abort(co->dbex);
1001         return 0;
1002 }
1003
1004
1005 int codegen_funcallparameter_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1006 {
1007         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1008         rulong off = rvm_codegen_getcodesize(co->cg);
1009         rvm_funcall_t *funcall = (rvm_funcall_t *)r_array_slot(co->funcall, r_array_length(co->funcall) - 1);
1010
1011         funcall->params += 1;
1012         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
1013         codegen_print_callback(name, userdata, input, size, reason, start, end);
1014         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1015
1016         return size;
1017 }
1018
1019
1020 int codegen_funcallname_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1021 {
1022         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1023         rulong off = rvm_codegen_getcodesize(co->cg);
1024         rvm_funcall_t funcall = {input, size, 0};
1025
1026         r_array_add(co->funcall, &funcall);
1027
1028
1029         /*
1030          * R0 holds the label of the called function, we save on the stack
1031          * and FP will point there. After the call we save the LR at that spot
1032          * as we don't need the RO anymore.
1033          */
1034 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_TYPE, R1, R0, XX, 0));
1035 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R1, DA, XX, RVM_DTYPE_POINTER));
1036 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_BNEQ, DA, XX, XX, 2));
1037 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R0, XX, 0));
1038
1039         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(FP)|BIT(SP)));
1040         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
1041
1042         codegen_print_callback(name, userdata, input, size, reason, start, end);
1043         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1044
1045         return size;
1046 }
1047
1048
1049 int codegen_funcallexpression_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1050 {
1051         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1052         rulong off = rvm_codegen_getcodesize(co->cg);
1053         rvm_funcall_t *funcall = r_array_empty(co->funcall) ? NULL : (rvm_funcall_t *) r_array_slot(co->funcall, r_array_length(co->funcall) - 1);
1054
1055         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUB, FP, SP, DA, funcall->params));
1056         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDS, R1, FP, XX, 0));
1057         rvm_codegen_addins(co->cg, rvm_asm(RVM_STS, LR, FP, XX, 0));
1058         rvm_codegen_addins(co->cg, rvm_asm(RVM_CALL, R1, DA, XX, -rvm_codegen_getcodesize(co->cg)));
1059         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
1060         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(FP,LR)));
1061
1062         r_array_removelast(co->funcall);
1063         codegen_print_callback(name, userdata, input, size, reason, start, end);
1064         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1065
1066         return size;
1067 }
1068
1069
1070 int codegen_fundeclparameter_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1071 {
1072         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1073         rulong off = rvm_codegen_getcodesize(co->cg);
1074         rvm_fundecl_t *fundecl = (rvm_fundecl_t *)r_array_lastslot(co->fundecl);
1075         rvm_varmap_t *v = rvm_scope_tiplookup(co->scope, input, size);
1076         if (v) {
1077                 fprintf(stdout, "ERROR: variable already defined: ");
1078                 fwrite(input, sizeof(char), size, stdout);
1079                 fprintf(stdout, "\n");
1080                 rpa_dbex_abort(co->dbex);
1081                 return 0;
1082         }
1083
1084         fundecl->params += 1;
1085         r_array_inclast(co->fp, rword);
1086         rvm_scope_addoffset(co->scope, input, size, r_array_last(co->fp, rword));
1087         codegen_print_callback(name, userdata, input, size, reason, start, end);
1088         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1089
1090         return size;
1091 }
1092
1093
1094 int codegen_fundeclname_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1095 {
1096         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1097         rulong off = rvm_codegen_getcodesize(co->cg);
1098         rvm_fundecl_t fundecl = {input, size, 0, off};
1099         rint ret;
1100
1101         ret = codegen_varalloc_callback(name, userdata, input, size, reason, start, end);
1102         if (ret == 0)
1103                 return ret;
1104
1105         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, 0));    /* Will be re-written later */
1106         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, DA, R0, XX, 0));   /* Will be re-written later */
1107         rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));              /* Will be re-written later */
1108         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADD, SP, FP, DA, 0));    /* Will be re-written later */
1109         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0xffffffff));
1110 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0xffffffff));
1111
1112         r_array_push(co->fp, 0, rword);
1113         r_array_add(co->fundecl, &fundecl);
1114         rvm_scope_push(co->scope);
1115         rvm_costat_pushroot(co);
1116
1117         codegen_print_callback(name, userdata, input, size, reason, start, end);
1118         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1119         return size;
1120 }
1121
1122
1123
1124 int codegen_fundeclsignature_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1125 {
1126         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1127         rulong off = rvm_codegen_getcodesize(co->cg);
1128
1129 //      rvm_codemap_add(cg->codemap, fundecl->funname, fundecl->funnamesiz, rvm_codegen_getcodesize(co->cg));
1130
1131         codegen_print_callback(name, userdata, input, size, reason, start, end);
1132         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1133
1134         return size;
1135 }
1136
1137
1138 int codegen_fundecl_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1139 {
1140         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1141         rulong off = rvm_codegen_getcodesize(co->cg);
1142         rvm_fundecl_t *fundecl = (rvm_fundecl_t *)r_array_lastslot(co->fundecl);
1143         rvm_varmap_t *fname;
1144         rword fp = r_array_pop(co->fp, rword);
1145         rvm_scope_pop(co->scope);
1146         fname = rvm_scope_tiplookup(co->scope, fundecl->funname, fundecl->funnamesiz);
1147
1148         /*
1149          * Function end, we first define the function end
1150          */
1151         if (rvm_costat_getdirty(co))
1152                 rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(RVM_SAVEDREGS_FIRST, RVM_SAVEDREGS_FIRST+ rvm_costat_getdirty(co) - 1)));
1153         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
1154
1155         /*
1156          * the number of arguments passed is = SP - FP
1157          */
1158         fundecl->codesize = rvm_codegen_getcodesize(co->cg) - fundecl->codestart;
1159         if (fname->datatype == VARMAP_DATATYPE_OFFSET) {
1160                 rvm_codegen_replaceins(co->cg, fundecl->codestart + 0, rvm_asm(RVM_ADDRS, R0, FP, DA, fname->data.offset));
1161         } else {
1162                 rvm_codegen_replaceins(co->cg, fundecl->codestart + 0, rvm_asmp(RVM_MOV, R0, DA, XX, fname->data.ptr));
1163         }
1164         rvm_codegen_replaceins(co->cg, fundecl->codestart + 1, rvm_asm(RVM_STRR, DA, R0, XX, fundecl->codestart + 3));
1165         rvm_codegen_replaceins(co->cg, fundecl->codestart + 2, rvm_asm(RVM_B, DA, XX, XX, fundecl->codesize - 2));
1166         rvm_codegen_replaceins(co->cg, fundecl->codestart + 3, rvm_asm(RVM_ADD, SP, FP, DA, fp));
1167         if (rvm_costat_getdirty(co))
1168                 rvm_codegen_replaceins(co->cg, fundecl->codestart + 4, rvm_asm(RVM_PUSHM, DA, XX, XX, BITS(RVM_SAVEDREGS_FIRST, RVM_SAVEDREGS_FIRST + rvm_costat_getdirty(co) - 1)));
1169
1170         fundecl->codesize = rvm_codegen_getcodesize(co->cg) - fundecl->codestart;
1171         fundecl->params = r_array_last(co->fp, rword);
1172
1173         r_array_removelast(co->fundecl);
1174         rvm_costat_pop(co);
1175         codegen_print_callback(name, userdata, input, size, reason, start, end);
1176         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1177
1178         return size;
1179 }
1180
1181
1182 int codegen_opreturn_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1183 {
1184         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1185         rulong off = rvm_codegen_getcodesize(co->cg);
1186
1187         if (rvm_costat_getdirty(co))
1188                 rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(RVM_SAVEDREGS_FIRST, RVM_SAVEDREGS_FIRST + rvm_costat_getdirty(co) - 1)));
1189         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
1190
1191         codegen_print_callback(name, userdata, input, size, reason, start, end);
1192         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1193
1194         return size;
1195 }
1196
1197
1198 int codegen_ifconditionop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1199 {
1200         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1201         rulong off = rvm_codegen_getcodesize(co->cg);
1202         rvm_codespan_t cs = {RVM_CODESPAN_NONE, 0, 0, 0, 0, 0, 0};
1203
1204         cs.codestart = rvm_codegen_getcodesize(co->cg);
1205         r_array_add(co->codespan, &cs);
1206
1207         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
1208         rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, -1));   //This has to be redefined when we know the size of the code block
1209
1210         codegen_print_callback(name, userdata, input, size, reason, start, end);
1211         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1212
1213         return size;
1214 }
1215
1216
1217 int codegen_ifop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1218 {
1219         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1220         rulong off = rvm_codegen_getcodesize(co->cg);
1221         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1222
1223         cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1224         rvm_codegen_replaceins(co->cg, cs.codestart + 1, rvm_asm(RVM_BEQ, DA, XX, XX, cs.codesize - 1));        //This has to be redefined when we know the size of the code block
1225
1226         codegen_print_callback(name, userdata, input, size, reason, start, end);
1227         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1228
1229         return size;
1230 }
1231
1232
1233 int codegen_elseop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1234 {
1235         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1236         rulong off = rvm_codegen_getcodesize(co->cg);
1237         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1238
1239         rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, - 1));            // Branch to the end of the else block, has to be redefined
1240         cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1241         rvm_codegen_replaceins(co->cg, cs.codestart + 1, rvm_asm(RVM_BEQ, DA, XX, XX, cs.codesize - 1));        // Branch to the begining of the else block
1242
1243         /* Reuse the cs to define the *else* codespan */
1244         cs.codestart = rvm_codegen_getcodesize(co->cg);
1245         cs.codesize = 0;
1246         r_array_add(co->codespan, &cs);
1247
1248         codegen_print_callback(name, userdata, input, size, reason, start, end);
1249         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1250
1251         return size;
1252 }
1253
1254
1255 int codegen_ifelseop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1256 {
1257         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1258         rulong off = rvm_codegen_getcodesize(co->cg);
1259         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1260
1261         cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1262         rvm_codegen_replaceins(co->cg, cs.codestart - 1, rvm_asm(RVM_B, DA, XX, XX, cs.codesize));      //Branch to the end of the else block, now we know the size
1263
1264         codegen_print_callback(name, userdata, input, size, reason, start, end);
1265         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1266
1267         return size;
1268 }
1269
1270
1271 int codegen_dokeyword_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1272 {
1273         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1274         rulong off = rvm_codegen_getcodesize(co->cg);
1275         rvm_codespan_t cs = {RVM_CODESPAN_NONE, 0, 0, 0, 0, 0, 0};
1276
1277         cs.codestart = rvm_codegen_getcodesize(co->cg);
1278         r_array_add(co->codespan, &cs);
1279
1280         codegen_print_callback(name, userdata, input, size, reason, start, end);
1281         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1282         return size;
1283 }
1284
1285
1286 int codegen_iterationdo_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1287 {
1288         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1289         rulong off = rvm_codegen_getcodesize(co->cg);
1290         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1291         rvm_asmins_t *last = rvm_codegen_getcode(co->cg, off - 1);
1292
1293         if (last->op1 == R0 && last->opcode >= RVM_EADD && last->opcode <= RVM_ELESSEQ) {
1294                 /*
1295                  * Nothing to do, the status register will be updated.
1296                  */
1297         } else {
1298                 rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
1299         }
1300
1301         cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1302         rvm_codegen_addins(co->cg, rvm_asm(RVM_BNEQ, DA, XX, XX, -cs.codesize));
1303         rvm_codemap_poploopblock(co->cg->codemap);
1304
1305         codegen_print_callback(name, userdata, input, size, reason, start, end);
1306         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1307         return size;
1308 }
1309
1310
1311 int codegen_whileconditionop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1312 {
1313         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1314         rulong off = rvm_codegen_getcodesize(co->cg);
1315         rvm_codespan_t *cs = (rvm_codespan_t*)r_array_lastslot(co->codespan);
1316
1317         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
1318         cs->l1 = rvm_codegen_getcodesize(co->cg);
1319         rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, -1));   //This has to be redefined when we know the size of the code block
1320
1321         codegen_print_callback(name, userdata, input, size, reason, start, end);
1322         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1323
1324         return size;
1325 }
1326
1327
1328 int codegen_iterationwhileop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1329 {
1330         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1331         rulong off = rvm_codegen_getcodesize(co->cg);
1332
1333         if (reason & RPA_REASON_START) {
1334                 rvm_codespan_t cs = {RVM_CODESPAN_NONE, 0, 0, 0, 0, 0, 0};
1335
1336                 cs.codestart = rvm_codegen_getcodesize(co->cg);
1337                 r_array_add(co->codespan, &cs);
1338         } else if (reason & RPA_REASON_MATCHED) {
1339                 rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1340
1341                 cs.codesize = rvm_codegen_getcodesize(co->cg) + 1 - cs.codestart;
1342                 rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, -(cs.codesize - 1)));
1343 //              rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, DA, XX, XX, 0xaaaaa));
1344
1345                 rvm_codegen_replaceins(co->cg, cs.l1, rvm_asm(RVM_BEQ, DA, XX, XX, cs.codesize - (cs.l1 - cs.codestart)));      // Re-writing the instruction
1346         } else if (reason & RPA_REASON_END) {
1347                 rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1348                 cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1349         }
1350
1351         codegen_print_callback(name, userdata, input, size, reason, start, end);
1352         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1353
1354         return size;
1355 }
1356
1357
1358 int codegen_questionmarkop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1359 {
1360         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1361         rulong off = rvm_codegen_getcodesize(co->cg);
1362         rvm_codespan_t cs = {RVM_CODESPAN_NONE, 0, 0, 0, 0, 0, 0};
1363
1364         cs.codestart = rvm_codegen_getcodesize(co->cg);
1365         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
1366         cs.l1 = rvm_codegen_getcodesize(co->cg);
1367         rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 0)); // This will be re-written
1368         r_array_add(co->codespan, &cs);
1369
1370         codegen_print_callback(name, userdata, input, size, reason, start, end);
1371         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1372
1373         return size;
1374 }
1375
1376
1377 int codegen_iftrueop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1378 {
1379         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1380         rulong off = rvm_codegen_getcodesize(co->cg);
1381         rvm_codespan_t *cs = (rvm_codespan_t*) r_array_lastslot(co->codespan);
1382
1383         cs->l2 = rvm_codegen_getcodesize(co->cg);
1384         rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0)); // This will be re-written
1385         rvm_codegen_replaceins(co->cg, cs->l1, rvm_asm(RVM_BEQ, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - cs->l1)); // Re-writing the instruction
1386
1387         codegen_print_callback(name, userdata, input, size, reason, start, end);
1388         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1389
1390         return size;
1391 }
1392
1393
1394 int codegen_iffalseop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1395 {
1396         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1397         rulong off = rvm_codegen_getcodesize(co->cg);
1398         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1399
1400         rvm_codegen_replaceins(co->cg, cs.l2, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - cs.l2));     // Re-writing the instruction
1401
1402         codegen_print_callback(name, userdata, input, size, reason, start, end);
1403         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1404
1405         return size;
1406 }
1407
1408
1409 int codegen_breakkeyword_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1410 {
1411         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1412         rulong off = rvm_codegen_getcodesize(co->cg);
1413         rvm_codespan_t *cs = (rvm_codespan_t *)r_array_lastslot(co->codespan);
1414
1415         if (cs->type != RVM_CODESPAN_LOOP) {
1416                 return 0;
1417         }
1418
1419         rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, -(rvm_codegen_getcodesize(co->cg) - cs->l2)));
1420
1421
1422         codegen_print_callback(name, userdata, input, size, reason, start, end);
1423         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1424         return size;
1425 }
1426
1427
1428 int codegen_forkeyword_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1429 {
1430         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1431         rulong off = rvm_codegen_getcodesize(co->cg);
1432         rvm_codespan_t cs = {RVM_CODESPAN_LOOP, 0, 0, 0, 0, 0, 0};
1433
1434         cs.codestart = rvm_codegen_getcodesize(co->cg);
1435         r_array_add(co->codespan, &cs);
1436         rvm_scope_push(co->scope);
1437
1438         codegen_print_callback(name, userdata, input, size, reason, start, end);
1439         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1440         return size;
1441 }
1442
1443
1444 int codegen_forinitop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1445 {
1446         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1447         rulong off = rvm_codegen_getcodesize(co->cg);
1448         rvm_codespan_t *cs = (rvm_codespan_t *)r_array_lastslot(co->codespan);
1449
1450
1451         cs->l1 = rvm_codegen_getcodesize(co->cg);
1452         rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 1)); // This will be re-written, when we know the start point of the comparison expression
1453         cs->l2 = rvm_codegen_getcodesize(co->cg);
1454         rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 1)); // Break point, This will be re-written.
1455         cs->l3 = rvm_codegen_getcodesize(co->cg);
1456
1457         codegen_print_callback(name, userdata, input, size, reason, start, end);
1458         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1459         return size;
1460 }
1461
1462 /*
1463  * The code generated for the increment expression will appear before the comparison expression
1464  * due to the trick we did in the BNF schema. That will make the implementation of the for ( ; ; ) loops
1465  * a lot more easier and the generated code having less branch instructions
1466  */
1467 int codegen_forincrementop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1468 {
1469         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1470         rulong off = rvm_codegen_getcodesize(co->cg);
1471         rvm_codespan_t *cs = (rvm_codespan_t *)r_array_lastslot(co->codespan);
1472
1473         rvm_codegen_replaceins(co->cg, cs->l1, rvm_asm(RVM_B, DA, XX, XX, rvm_codegen_getcodesize(co->cg) - cs->l1));   // Re-writing the instruction
1474
1475         codegen_print_callback(name, userdata, input, size, reason, start, end);
1476         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1477         return size;
1478 }
1479
1480
1481 int codegen_forcompareop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1482 {
1483         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1484         rulong off = rvm_codegen_getcodesize(co->cg);
1485         rvm_codespan_t *cs = (rvm_codespan_t *)r_array_lastslot(co->codespan);
1486
1487         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
1488         cs->l4 = rvm_codegen_getcodesize(co->cg);
1489         rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 0)); // This will be re-written when we know the size of the code inside the loop.
1490         /*
1491          * The beginning loop starts here, right after the RVM_BEQ instruction.
1492          */
1493
1494         codegen_print_callback(name, userdata, input, size, reason, start, end);
1495         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1496         return size;
1497 }
1498
1499
1500
1501
1502 int codegen_iterationforop_callback(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
1503 {
1504         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1505         rulong off = rvm_codegen_getcodesize(co->cg);
1506         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1507
1508         rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, -(rvm_codegen_getcodesize(co->cg) - (cs.l3))));
1509         cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1510         rvm_codegen_replaceins(co->cg, cs.l4, rvm_asm(RVM_BEQ, DA, XX, XX, cs.codesize - (cs.l4 - cs.codestart)));
1511         rvm_codegen_replaceins(co->cg, cs.l2, rvm_asm(RVM_B, DA, XX, XX, cs.codesize - (cs.l2 - cs.codestart)));        // Re-writing the instruction
1512
1513         rvm_scope_pop(co->scope);
1514
1515         codegen_print_callback(name, userdata, input, size, reason, start, end);
1516         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1517         return size;
1518 }
1519
1520
1521 void codegen_unmap_file(rstr_t *buf)
1522 {
1523         if (buf) {
1524                 munmap(buf->str, buf->size);
1525                 r_free(buf);
1526         }
1527 }
1528
1529
1530 rstr_t *codegen_map_file(const char *filename)
1531 {
1532         struct stat st;
1533         rstr_t *str;
1534         char *buffer;
1535
1536
1537         int fd = open(filename, O_RDONLY);
1538         if (fd < 0) {
1539                 return (void*)0;
1540         }
1541         if (fstat(fd, &st) < 0) {
1542                 close(fd);
1543                 return (void*)0;
1544         }
1545         buffer = (char*)mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
1546         if (buffer == (void*)-1) {
1547                 close(fd);
1548                 return (void*)0;
1549         }
1550         str = (rstr_t *)r_malloc(sizeof(*str));
1551         if (!str)
1552                 goto error;
1553         r_memset(str, 0, sizeof(*str));
1554         str->str = buffer;
1555         str->size = st.st_size;
1556         close(fd);
1557         return str;
1558
1559 error:
1560         munmap(buffer, st.st_size);
1561         close(fd);
1562         return str;
1563 }
1564
1565
1566 int main(int argc, char *argv[])
1567 {
1568         int res, i;
1569         rvmcpu_t *cpu;
1570         ruint ntable;
1571         rpa_dbex_handle dbex = rpa_dbex_create();
1572         rvm_compiler_t *co = rvm_compiler_create(dbex);
1573
1574         cpu = rvm_cpu_create_default();
1575         ntable = rvm_cpu_addswitable(cpu, switable);
1576         rvm_cpu_addswitable(cpu, switable_js);
1577         co->cpu = cpu;
1578
1579         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
1580         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
1581         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
1582         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
1583
1584         for (i = 1; i < argc; i++) {
1585                 if (r_strcmp(argv[i], "-L") == 0) {
1586                 } else if (r_strcmp(argv[i], "-d") == 0) {
1587                         debuginfo = 1;
1588                 } else if (r_strcmp(argv[i], "-p") == 0) {
1589                         parseinfo = 1;
1590                 } else if (r_strcmp(argv[i], "-P") == 0) {
1591                         parseinfo = 1;
1592                         verboseinfo = 1;
1593                 } else if (r_strcmp(argv[i], "-c") == 0) {
1594                         compileonly = 1;
1595                 } else if (r_strcmp(argv[i], "-o") == 0) {
1596                         co->optimized = 1;
1597                 } else if (r_strcmp(argv[i], "-m") == 0) {
1598
1599                 }
1600         }
1601
1602         rpagen_load_rules(dbex, co);
1603
1604         for (i = 1; i < argc; i++) {
1605                 if (r_strcmp(argv[i], "-e") == 0) {
1606                         if (++i < argc) {
1607                                 rstr_t script = { argv[i], r_strlen(argv[i]) };
1608                                 res = rpa_dbex_parse(dbex, rpa_dbex_default_pattern(dbex), script.str, script.str, script.str + script.size);
1609                                 if (res <= 0)
1610                                         rvm_codegen_clear(co->cg);
1611                         }
1612                         goto exec;
1613                 }
1614         }
1615
1616         for (i = 1; i < argc; i++) {
1617                 if (r_strcmp(argv[i], "-f") == 0) {
1618                         rstr_t *script = NULL;
1619                         if (++i < argc) {
1620                                 script = codegen_map_file(argv[i]);
1621                                 if (script) {
1622                                         res = rpa_dbex_parse(dbex, rpa_dbex_default_pattern(dbex), script->str, script->str, script->str + script->size);
1623                                         codegen_unmap_file(script);
1624                                 }
1625
1626                         }
1627                         goto exec;
1628                 }
1629         }
1630
1631
1632 exec:
1633         rvm_relocate(rvm_codegen_getcode(co->cg, 0), rvm_codegen_getcodesize(co->cg));
1634
1635         if (debuginfo) {
1636                 fprintf(stdout, "\nGenerated Code:\n");
1637                 rvm_asm_dump(rvm_codegen_getcode(co->cg, 0), rvm_codegen_getcodesize(co->cg));
1638                 if (rvm_codegen_getcodesize(co->cg)) {
1639                         if (!compileonly) {
1640                                 fprintf(stdout, "\nExecution:\n");
1641                                 rvm_cpu_exec_debug(cpu, rvm_codegen_getcode(co->cg, 0), 0);
1642                         }
1643                 }
1644         } else {
1645                 if (!compileonly)
1646                         rvm_cpu_exec(cpu, rvm_codegen_getcode(co->cg, 0), 0);
1647         }
1648
1649
1650         rpa_dbex_destroy(dbex);
1651         rvm_cpu_destroy(cpu);
1652         rvm_compiler_destroy(co);
1653
1654         if (debuginfo) {
1655                 r_printf("Max alloc mem: %ld\n", r_debug_get_maxmem());
1656                 r_printf("Leaked mem: %ld\n", r_debug_get_allocmem());
1657         }
1658         return 0;
1659 }
1660
1661
1662 #define EOL "\n"
1663
1664
1665 extern char _binary_____________tests_ecma262_rpa_start[];
1666 extern char _binary_____________tests_ecma262_rpa_end[];
1667 extern unsigned long *_binary_____________tests_ecma262_rpa_size;
1668
1669 void rpagen_load_rules(rpa_dbex_handle dbex, rvm_compiler_t *co)
1670 {
1671         int ret, line;
1672         int inputsize = _binary_____________tests_ecma262_rpa_end - _binary_____________tests_ecma262_rpa_start;
1673         const char *buffer = _binary_____________tests_ecma262_rpa_start;
1674         const char *pattern = buffer;
1675
1676         rpa_dbex_open(dbex);
1677
1678         rpa_dbex_add_callback_exact(dbex, "BitwiseANDOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1679         rpa_dbex_add_callback_exact(dbex, "BitwiseXOROp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1680         rpa_dbex_add_callback_exact(dbex, "BitwiseOROp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1681         rpa_dbex_add_callback_exact(dbex, "AdditiveExpressionOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1682
1683         rpa_dbex_add_callback_exact(dbex, "MultiplicativeExpressionOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1684         rpa_dbex_add_callback_exact(dbex, "ShiftExpressionOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1685         rpa_dbex_add_callback_exact(dbex, "EqualityExpressionOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1686         rpa_dbex_add_callback_exact(dbex, "RelationalExpressionOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1687         rpa_dbex_add_callback_exact(dbex, "LogicalOROp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1688         rpa_dbex_add_callback_exact(dbex, "LogicalANDOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1689
1690         rpa_dbex_add_callback_exact(dbex, "AssignmentOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1691         rpa_dbex_add_callback_exact(dbex, "EqualityOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1692         rpa_dbex_add_callback_exact(dbex, "RelationalOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1693         rpa_dbex_add_callback_exact(dbex, "AdditiveOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1694         rpa_dbex_add_callback_exact(dbex, "MultiplicativeOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1695         rpa_dbex_add_callback_exact(dbex, "ShiftOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1696         rpa_dbex_add_callback_exact(dbex, "BitwiseANDOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1697         rpa_dbex_add_callback_exact(dbex, "BitwiseXOROperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1698         rpa_dbex_add_callback_exact(dbex, "BitwiseOROperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1699         rpa_dbex_add_callback_exact(dbex, "LogicalANDOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1700         rpa_dbex_add_callback_exact(dbex, "LogicalOROperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1701         rpa_dbex_add_callback_exact(dbex, "LogicalNotOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1702         rpa_dbex_add_callback_exact(dbex, "BitwiseNotOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1703         rpa_dbex_add_callback_exact(dbex, "UnaryOperatorOpcode", RPA_REASON_MATCHED, codegen_opcode_unary_callback, co);
1704         rpa_dbex_add_callback_exact(dbex, "PrintOp", RPA_REASON_MATCHED, codegen_printop_callback, co);
1705
1706
1707         rpa_dbex_add_callback_exact(dbex, "PostfixOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1708         rpa_dbex_add_callback_exact(dbex, "PostfixExpressionOp", RPA_REASON_MATCHED, codegen_oppostfix_callback, co);
1709         rpa_dbex_add_callback_exact(dbex, "PrefixExpressionOp", RPA_REASON_MATCHED, codegen_opprefix_callback, co);
1710
1711
1712         rpa_dbex_add_callback_exact(dbex, "UnaryExpressionOp", RPA_REASON_ALL, codegen_unary_asmop_callback, co);
1713         rpa_dbex_add_callback_exact(dbex, "LogicalNotExpressionOp", RPA_REASON_ALL, codegen_unary_asmop_callback, co);
1714         rpa_dbex_add_callback_exact(dbex, "BitwiseNotExpressionOp", RPA_REASON_ALL, codegen_unary_asmop_callback, co);
1715
1716         rpa_dbex_add_callback_exact(dbex, "DecimalIntegerLiteral", RPA_REASON_MATCHED, codegen_integer_callback, co);
1717         rpa_dbex_add_callback_exact(dbex, "DecimalNonIntegerLiteral", RPA_REASON_MATCHED, codegen_double_callback, co);
1718         rpa_dbex_add_callback_exact(dbex, "BlockBegin", RPA_REASON_MATCHED, codegen_scopepush_callback, co);
1719         rpa_dbex_add_callback_exact(dbex, "BlockEnd", RPA_REASON_MATCHED, codegen_scopepop_callback, co);
1720
1721         rpa_dbex_add_callback_exact(dbex, "DoKeyword", RPA_REASON_MATCHED, codegen_dokeyword_callback, co);
1722         rpa_dbex_add_callback_exact(dbex, "IterationDo", RPA_REASON_MATCHED, codegen_iterationdo_callback, co);
1723
1724         rpa_dbex_add_callback_exact(dbex, "sqstring", RPA_REASON_MATCHED, codegen_string_callback, co);
1725         rpa_dbex_add_callback_exact(dbex, "dqstring", RPA_REASON_MATCHED, codegen_string_callback, co);
1726         rpa_dbex_add_callback_exact(dbex, "DoubleStringCharacters", RPA_REASON_MATCHED, codegen_string_callback, co);
1727         rpa_dbex_add_callback_exact(dbex, "SingleStringCharacters", RPA_REASON_MATCHED, codegen_string_callback, co);
1728         rpa_dbex_add_callback_exact(dbex, "Program", RPA_REASON_START|RPA_REASON_MATCHED, codegen_program_callback, co);
1729         rpa_dbex_add_callback_exact(dbex, "Initialiser", RPA_REASON_MATCHED, codegen_opinit_callback, co);
1730         rpa_dbex_add_callback_exact(dbex, "AssignmentExpressionOp", RPA_REASON_MATCHED, codegen_opassign_callback, co);
1731
1732         rpa_dbex_add_callback_exact(dbex, "VariableAllocate", RPA_REASON_MATCHED, codegen_varalloc_callback, co);
1733         rpa_dbex_add_callback_exact(dbex, "VariableAllocateAndInit", RPA_REASON_MATCHED, codegen_varalloc_to_ptr_callback, co);
1734
1735         rpa_dbex_add_callback_exact(dbex, "ReturnOp", RPA_REASON_MATCHED, codegen_opreturn_callback, co);
1736
1737         rpa_dbex_add_callback_exact(dbex, "SwiId", RPA_REASON_MATCHED, codegen_swiid_callback, co);
1738         rpa_dbex_add_callback_exact(dbex, "SwiIdExist", RPA_REASON_MATCHED, codegen_swiidexist_callback, co);
1739
1740         rpa_dbex_add_callback_exact(dbex, "IdentifierOp", RPA_REASON_MATCHED, codegen_opidentifier_callback, co);
1741         rpa_dbex_add_callback_exact(dbex, "ValIdentifierOp", RPA_REASON_MATCHED, codegen_validentifierop_callback, co);
1742         rpa_dbex_add_callback_exact(dbex, "PostfixExpressionValOp", RPA_REASON_ALL, codegen_valop_callback, co);
1743
1744         rpa_dbex_add_callback_exact(dbex, "LeftHandSideExpressionPush", RPA_REASON_MATCHED, codegen_push_r0_callback, co);
1745
1746         rpa_dbex_add_callback_exact(dbex, "MemberExpressionIndexBaseOp", RPA_REASON_MATCHED, codegen_memberexpressionbase_callback, co);
1747         rpa_dbex_add_callback_exact(dbex, "MemberExpressionIndexOp", RPA_REASON_MATCHED, codegen_arrayelementaddress_callback, co);
1748
1749         rpa_dbex_add_callback_exact(dbex, "ValMemberExpressionIndexBaseOp", RPA_REASON_MATCHED, codegen_push_r0_callback, co);
1750         rpa_dbex_add_callback_exact(dbex, "ValMemberExpressionIndexOp", RPA_REASON_MATCHED, codegen_arrayelementvalue_callback, co);
1751
1752         rpa_dbex_add_callback_exact(dbex, "CallExpressionIndexBaseOp", RPA_REASON_MATCHED, codegen_memberexpressionbase_callback, co);
1753         rpa_dbex_add_callback_exact(dbex, "CallExpressionIndexOp", RPA_REASON_MATCHED, codegen_arrayelementaddress_callback, co);
1754
1755
1756         rpa_dbex_add_callback_exact(dbex, "ValCallExpressionIndexBaseOp", RPA_REASON_MATCHED, codegen_push_r0_callback, co);
1757         rpa_dbex_add_callback_exact(dbex, "ValCallExpressionIndexOp", RPA_REASON_MATCHED, codegen_arrayelementvalue_callback, co);
1758
1759         rpa_dbex_add_callback_exact(dbex, "ConditionalExpression", RPA_REASON_MATCHED, codegen_conditionalexp_callback, co);
1760
1761         rpa_dbex_add_callback_exact(dbex, "NewArraySize", RPA_REASON_MATCHED, codegen_newarraysize_callback, co);
1762         rpa_dbex_add_callback_exact(dbex, "NewArrayNoSize", RPA_REASON_MATCHED, codegen_newarraynosize_callback, co);
1763         rpa_dbex_add_callback_exact(dbex, "compile_error", RPA_REASON_MATCHED, codegen_compile_error_callback, co);
1764
1765         rpa_dbex_add_callback_exact(dbex, "ArgumentsOp", RPA_REASON_ALL, codegen_costate_callback, co);
1766         rpa_dbex_add_callback_exact(dbex, "BracketExpressionOp", RPA_REASON_ALL, codegen_costate_callback, co);
1767
1768         rpa_dbex_add_callback_exact(dbex, "FunctionName", RPA_REASON_MATCHED, codegen_fundeclname_callback, co);
1769         rpa_dbex_add_callback_exact(dbex, "FunctionDefinition", RPA_REASON_MATCHED, codegen_fundeclsignature_callback, co);
1770         rpa_dbex_add_callback_exact(dbex, "FunctionDeclaration", RPA_REASON_MATCHED, codegen_fundecl_callback, co);
1771         rpa_dbex_add_callback_exact(dbex, "FunctionParameter", RPA_REASON_MATCHED, codegen_fundeclparameter_callback, co);
1772         rpa_dbex_add_callback_exact(dbex, "FunctionCallParameter", RPA_REASON_MATCHED, codegen_funcallparameter_callback, co);
1773         rpa_dbex_add_callback_exact(dbex, "FunctionCallName", RPA_REASON_MATCHED, codegen_funcallname_callback, co);
1774         rpa_dbex_add_callback_exact(dbex, "CallExpressionOp", RPA_REASON_MATCHED, codegen_funcallexpression_callback, co);
1775
1776         rpa_dbex_add_callback_exact(dbex, "ValFunctionCallName", RPA_REASON_MATCHED, codegen_funcallname_callback, co);
1777         rpa_dbex_add_callback_exact(dbex, "ValCallExpressionOp", RPA_REASON_MATCHED, codegen_funcallexpression_callback, co);
1778
1779
1780         rpa_dbex_add_callback_exact(dbex, "IfConditionOp", RPA_REASON_MATCHED, codegen_ifconditionop_callback, co);
1781         rpa_dbex_add_callback_exact(dbex, "IfOp", RPA_REASON_MATCHED, codegen_ifop_callback, co);
1782         rpa_dbex_add_callback_exact(dbex, "ElseOp", RPA_REASON_MATCHED, codegen_elseop_callback, co);
1783         rpa_dbex_add_callback_exact(dbex, "IfElseOp", RPA_REASON_MATCHED, codegen_ifelseop_callback, co);
1784
1785         rpa_dbex_add_callback_exact(dbex, "WhileConditionOp", RPA_REASON_MATCHED, codegen_whileconditionop_callback, co);
1786         rpa_dbex_add_callback_exact(dbex, "IterationWhileOp", RPA_REASON_ALL, codegen_iterationwhileop_callback, co);
1787
1788         rpa_dbex_add_callback_exact(dbex, "QuestionMarkOp", RPA_REASON_MATCHED, codegen_questionmarkop_callback, co);
1789         rpa_dbex_add_callback_exact(dbex, "AssignmentExpressionIfTrueOp", RPA_REASON_MATCHED, codegen_iftrueop_callback, co);
1790         rpa_dbex_add_callback_exact(dbex, "AssignmentExpressionIfFalseOp", RPA_REASON_MATCHED, codegen_iffalseop_callback, co);
1791
1792         rpa_dbex_add_callback_exact(dbex, "ForKeyword", RPA_REASON_MATCHED, codegen_forkeyword_callback, co);
1793         rpa_dbex_add_callback_exact(dbex, "ForExpressionInitOp", RPA_REASON_END, codegen_forinitop_callback, co);
1794         rpa_dbex_add_callback_exact(dbex, "ForExpressionCompareOp", RPA_REASON_END, codegen_forcompareop_callback, co);
1795         rpa_dbex_add_callback_exact(dbex, "ForExpressionIncrementOp", RPA_REASON_END, codegen_forincrementop_callback, co);
1796         rpa_dbex_add_callback_exact(dbex, "IterationForOp", RPA_REASON_MATCHED, codegen_iterationforop_callback, co);
1797         rpa_dbex_add_callback_exact(dbex, "BreakOp", RPA_REASON_MATCHED, codegen_breakkeyword_callback, co);
1798
1799
1800         if (verboseinfo)
1801                 rpa_dbex_add_callback(dbex, ".*", RPA_REASON_MATCHED, codegen_print_callback, co);
1802
1803         while ((ret = rpa_dbex_load(dbex, pattern, inputsize)) > 0) {
1804                 inputsize -= ret;
1805                 pattern += ret;
1806         }
1807         if (ret < 0) {
1808                 for (line = 1; pattern >= buffer; --pattern) {
1809                         if (*pattern == '\n')
1810                                 line += 1;
1811                 }
1812                 fprintf(stdout, "Line: %d, RPA LOAD ERROR: %s\n", line, (rpa_dbex_get_error(dbex) == RPA_E_SYNTAX_ERROR) ? "Syntax Error." : "Pattern Loading failed.");
1813                 goto error;
1814         }
1815
1816 error:
1817         rpa_dbex_close(dbex);
1818 }