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