RPA Toolkit
bbab69ed6bdb3b1b63df61f0af580023f41b61a9
[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_funcallname_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         rvm_funcall_t funcall = {input, size, 0};
1030
1031         r_array_add(co->funcall, &funcall);
1032
1033
1034         /*
1035          * R0 holds the label of the called function, we save on the stack
1036          * and FP will point there. After the call we save the LR at that spot
1037          * as we don't need the RO anymore.
1038          */
1039 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_TYPE, R1, R0, XX, 0));
1040 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R1, DA, XX, RVM_DTYPE_POINTER));
1041 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_BNEQ, DA, XX, XX, 2));
1042 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R0, XX, 0));
1043
1044         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(TP)|BIT(FP)|BIT(SP)));
1045         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
1046
1047         codegen_print_callback(stat, name, userdata, input, size, reason);
1048         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1049
1050         return size;
1051 }
1052
1053
1054 int codegen_funcallexpression_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1055 {
1056         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1057         rulong off = rvm_codegen_getcodesize(co->cg);
1058         rvm_funcall_t *funcall = r_array_empty(co->funcall) ? NULL : (rvm_funcall_t *) r_array_slot(co->funcall, r_array_length(co->funcall) - 1);
1059
1060         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUB, FP, SP, DA, funcall->params));
1061         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDS, R1, FP, XX, 0));
1062         rvm_codegen_addins(co->cg, rvm_asm(RVM_STS, LR, FP, XX, 0));
1063         rvm_codegen_addins(co->cg, rvm_asm(RVM_CALL, R1, DA, XX, -rvm_codegen_getcodesize(co->cg)));
1064         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
1065         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(TP,LR)));
1066
1067         r_array_removelast(co->funcall);
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_fundeclparameter_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_fundecl_t *fundecl = (rvm_fundecl_t *)r_array_lastslot(co->fundecl);
1080         rvm_varmap_t *v = rvm_scope_tiplookup(co->scope, input, size);
1081         if (v) {
1082                 fprintf(stdout, "ERROR: variable already defined: ");
1083                 fwrite(input, sizeof(char), size, stdout);
1084                 fprintf(stdout, "\n");
1085                 rpa_dbex_abort(co->dbex);
1086                 return 0;
1087         }
1088
1089         fundecl->params += 1;
1090         r_array_inclast(co->fp, rword);
1091         rvm_scope_addoffset(co->scope, input, size, r_array_last(co->fp, rword));
1092         codegen_print_callback(stat, name, userdata, input, size, reason);
1093         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1094
1095         return size;
1096 }
1097
1098
1099 int codegen_fundeclname_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1100 {
1101         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1102         rulong off;
1103         rvm_fundecl_t fundecl = {input, size, 0, 0};
1104         rint ret;
1105
1106         ret = codegen_varalloc_callback(stat, name, userdata, input, size, reason);
1107         if (ret == 0)
1108                 return ret;
1109
1110         off = rvm_codegen_getcodesize(co->cg);
1111         fundecl.codestart = off;
1112
1113         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, 0));    /* Will be re-written later */
1114         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, DA, R0, XX, 0));   /* Will be re-written later */
1115         rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0));              /* Will be re-written later */
1116         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADD, SP, FP, DA, 0));    /* Will be re-written later */
1117         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0xffffffff));
1118 //      rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0xffffffff));
1119
1120         r_array_push(co->fp, 0, rword);
1121         r_array_add(co->fundecl, &fundecl);
1122         rvm_scope_push(co->scope);
1123         rvm_costat_pushroot(co);
1124
1125         codegen_print_callback(stat, name, userdata, input, size, reason);
1126         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1127         return size;
1128 }
1129
1130
1131
1132 int codegen_fundeclsignature_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1133 {
1134         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1135         rulong off = rvm_codegen_getcodesize(co->cg);
1136
1137 //      rvm_codemap_add(cg->codemap, fundecl->funname, fundecl->funnamesiz, rvm_codegen_getcodesize(co->cg));
1138
1139         codegen_print_callback(stat, name, userdata, input, size, reason);
1140         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1141
1142         return size;
1143 }
1144
1145
1146 int codegen_fundecl_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1147 {
1148         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1149         rulong off = rvm_codegen_getcodesize(co->cg);
1150         rvm_fundecl_t *fundecl = (rvm_fundecl_t *)r_array_lastslot(co->fundecl);
1151         rvm_varmap_t *fname;
1152         rword fp = r_array_pop(co->fp, rword);
1153         rvm_scope_pop(co->scope);
1154         fname = rvm_scope_tiplookup(co->scope, fundecl->funname, fundecl->funnamesiz);
1155
1156         /*
1157          * Function end, we first define the function end
1158          */
1159         if (rvm_costat_getdirty(co))
1160                 rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(RVM_SAVEDREGS_FIRST, RVM_SAVEDREGS_FIRST+ rvm_costat_getdirty(co) - 1)));
1161         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
1162
1163         /*
1164          * the number of arguments passed is = SP - FP
1165          */
1166         fundecl->codesize = rvm_codegen_getcodesize(co->cg) - fundecl->codestart;
1167         if (fname->datatype == VARMAP_DATATYPE_OFFSET) {
1168                 rvm_codegen_replaceins(co->cg, fundecl->codestart + 0, rvm_asm(RVM_ADDRS, R0, FP, DA, fname->data.offset));
1169         } else {
1170                 rvm_codegen_replaceins(co->cg, fundecl->codestart + 0, rvm_asmp(RVM_MOV, R0, DA, XX, fname->data.ptr));
1171         }
1172         rvm_codegen_replaceins(co->cg, fundecl->codestart + 1, rvm_asm(RVM_STRR, DA, R0, XX, fundecl->codestart + 3));
1173         rvm_codegen_replaceins(co->cg, fundecl->codestart + 2, rvm_asm(RVM_B, DA, XX, XX, fundecl->codesize - 2));
1174         rvm_codegen_replaceins(co->cg, fundecl->codestart + 3, rvm_asm(RVM_ADD, SP, FP, DA, fp));
1175         if (rvm_costat_getdirty(co))
1176                 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)));
1177
1178         fundecl->codesize = rvm_codegen_getcodesize(co->cg) - fundecl->codestart;
1179         fundecl->params = r_array_last(co->fp, rword);
1180
1181         r_array_removelast(co->fundecl);
1182         rvm_costat_pop(co);
1183         codegen_print_callback(stat, name, userdata, input, size, reason);
1184         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1185
1186         return size;
1187 }
1188
1189
1190 int codegen_opreturn_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1191 {
1192         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1193         rulong off = rvm_codegen_getcodesize(co->cg);
1194
1195         if (rvm_costat_getdirty(co))
1196                 rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(RVM_SAVEDREGS_FIRST, RVM_SAVEDREGS_FIRST + rvm_costat_getdirty(co) - 1)));
1197         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
1198
1199         codegen_print_callback(stat, name, userdata, input, size, reason);
1200         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1201
1202         return size;
1203 }
1204
1205
1206 int codegen_ifconditionop_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1207 {
1208         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1209         rulong off = rvm_codegen_getcodesize(co->cg);
1210         rvm_codespan_t cs = {RVM_CODESPAN_NONE, 0, 0, 0, 0, 0, 0};
1211
1212         cs.codestart = rvm_codegen_getcodesize(co->cg);
1213         r_array_add(co->codespan, &cs);
1214
1215         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
1216         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
1217
1218         codegen_print_callback(stat, name, userdata, input, size, reason);
1219         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1220
1221         return size;
1222 }
1223
1224
1225 int codegen_ifop_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1226 {
1227         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1228         rulong off = rvm_codegen_getcodesize(co->cg);
1229         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1230
1231         cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1232         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
1233
1234         codegen_print_callback(stat, name, userdata, input, size, reason);
1235         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1236
1237         return size;
1238 }
1239
1240
1241 int codegen_elseop_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1242 {
1243         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1244         rulong off = rvm_codegen_getcodesize(co->cg);
1245         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1246
1247         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
1248         cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1249         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
1250
1251         /* Reuse the cs to define the *else* codespan */
1252         cs.codestart = rvm_codegen_getcodesize(co->cg);
1253         cs.codesize = 0;
1254         r_array_add(co->codespan, &cs);
1255
1256         codegen_print_callback(stat, name, userdata, input, size, reason);
1257         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1258
1259         return size;
1260 }
1261
1262
1263 int codegen_ifelseop_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1264 {
1265         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1266         rulong off = rvm_codegen_getcodesize(co->cg);
1267         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1268
1269         cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1270         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
1271
1272         codegen_print_callback(stat, name, userdata, input, size, reason);
1273         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1274
1275         return size;
1276 }
1277
1278
1279 int codegen_dokeyword_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1280 {
1281         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1282         rulong off = rvm_codegen_getcodesize(co->cg);
1283         rvm_codespan_t cs = {RVM_CODESPAN_NONE, 0, 0, 0, 0, 0, 0};
1284
1285         cs.codestart = rvm_codegen_getcodesize(co->cg);
1286         r_array_add(co->codespan, &cs);
1287
1288         codegen_print_callback(stat, name, userdata, input, size, reason);
1289         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1290         return size;
1291 }
1292
1293
1294 int codegen_iterationdo_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1295 {
1296         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1297         rulong off = rvm_codegen_getcodesize(co->cg);
1298         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1299         rvm_asmins_t *last = rvm_codegen_getcode(co->cg, off - 1);
1300
1301         if (last->op1 == R0 && last->opcode >= RVM_EADD && last->opcode <= RVM_ELESSEQ) {
1302                 /*
1303                  * Nothing to do, the status register will be updated.
1304                  */
1305         } else {
1306                 rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
1307         }
1308
1309         cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1310         rvm_codegen_addins(co->cg, rvm_asm(RVM_BNEQ, DA, XX, XX, -cs.codesize));
1311         rvm_codemap_poploopblock(co->cg->codemap);
1312
1313         codegen_print_callback(stat, name, userdata, input, size, reason);
1314         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1315         return size;
1316 }
1317
1318
1319 int codegen_whileconditionop_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1320 {
1321         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1322         rulong off = rvm_codegen_getcodesize(co->cg);
1323         rvm_codespan_t *cs = (rvm_codespan_t*)r_array_lastslot(co->codespan);
1324
1325         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
1326         cs->l1 = rvm_codegen_getcodesize(co->cg);
1327         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
1328
1329         codegen_print_callback(stat, name, userdata, input, size, reason);
1330         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1331
1332         return size;
1333 }
1334
1335
1336 int codegen_iterationwhileop_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1337 {
1338         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1339         rulong off = rvm_codegen_getcodesize(co->cg);
1340
1341         if (reason & RPA_REASON_START) {
1342                 rvm_codespan_t cs = {RVM_CODESPAN_NONE, 0, 0, 0, 0, 0, 0};
1343
1344                 cs.codestart = rvm_codegen_getcodesize(co->cg);
1345                 r_array_add(co->codespan, &cs);
1346         } else if (reason & RPA_REASON_MATCHED) {
1347                 rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1348
1349                 cs.codesize = rvm_codegen_getcodesize(co->cg) + 1 - cs.codestart;
1350                 rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, -(cs.codesize - 1)));
1351 //              rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, DA, XX, XX, 0xaaaaa));
1352
1353                 rvm_codegen_replaceins(co->cg, cs.l1, rvm_asm(RVM_BEQ, DA, XX, XX, cs.codesize - (cs.l1 - cs.codestart)));      // Re-writing the instruction
1354         } else if (reason & RPA_REASON_END) {
1355                 rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1356                 cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1357         }
1358
1359         codegen_print_callback(stat, name, userdata, input, size, reason);
1360         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1361
1362         return size;
1363 }
1364
1365
1366 int codegen_questionmarkop_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1367 {
1368         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1369         rulong off = rvm_codegen_getcodesize(co->cg);
1370         rvm_codespan_t cs = {RVM_CODESPAN_NONE, 0, 0, 0, 0, 0, 0};
1371
1372         cs.codestart = rvm_codegen_getcodesize(co->cg);
1373         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
1374         cs.l1 = rvm_codegen_getcodesize(co->cg);
1375         rvm_codegen_addins(co->cg, rvm_asm(RVM_BEQ, DA, XX, XX, 0)); // This will be re-written
1376         r_array_add(co->codespan, &cs);
1377
1378         codegen_print_callback(stat, name, userdata, input, size, reason);
1379         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1380
1381         return size;
1382 }
1383
1384
1385 int codegen_iftrueop_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1386 {
1387         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1388         rulong off = rvm_codegen_getcodesize(co->cg);
1389         rvm_codespan_t *cs = (rvm_codespan_t*) r_array_lastslot(co->codespan);
1390
1391         cs->l2 = rvm_codegen_getcodesize(co->cg);
1392         rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 0)); // This will be re-written
1393         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
1394
1395         codegen_print_callback(stat, name, userdata, input, size, reason);
1396         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1397
1398         return size;
1399 }
1400
1401
1402 int codegen_iffalseop_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1403 {
1404         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1405         rulong off = rvm_codegen_getcodesize(co->cg);
1406         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1407
1408         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
1409
1410         codegen_print_callback(stat, name, userdata, input, size, reason);
1411         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1412
1413         return size;
1414 }
1415
1416
1417 int codegen_breakkeyword_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1418 {
1419         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1420         rulong off = rvm_codegen_getcodesize(co->cg);
1421         rvm_codespan_t *cs = (rvm_codespan_t *)r_array_last(co->loops, rvm_codespan_t*);
1422
1423         if (cs->type != RVM_CODESPAN_LOOP) {
1424                 return 0;
1425         }
1426
1427         rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, -(rvm_codegen_getcodesize(co->cg) - cs->l2)));
1428
1429
1430         codegen_print_callback(stat, name, userdata, input, size, reason);
1431         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1432         return size;
1433 }
1434
1435
1436 int codegen_continuekeyword_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1437 {
1438         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1439         rulong off = rvm_codegen_getcodesize(co->cg);
1440         rvm_codespan_t *cs = (rvm_codespan_t *)r_array_last(co->loops, rvm_codespan_t*);
1441
1442         if (cs->type != RVM_CODESPAN_LOOP) {
1443                 return 0;
1444         }
1445
1446         rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, -(rvm_codegen_getcodesize(co->cg) - cs->l3)));
1447
1448
1449         codegen_print_callback(stat, name, userdata, input, size, reason);
1450         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1451         return size;
1452 }
1453
1454
1455 int codegen_forkeyword_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1456 {
1457         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1458         rulong off = rvm_codegen_getcodesize(co->cg);
1459         rvm_codespan_t cs = {RVM_CODESPAN_LOOP, 0, 0, 0, 0, 0, 0};
1460
1461         cs.codestart = rvm_codegen_getcodesize(co->cg);
1462         r_array_add(co->codespan, &cs);
1463         rvm_scope_push(co->scope);
1464         r_array_push(co->loops, r_array_lastslot(co->codespan), rvm_codespan_t*);
1465
1466         codegen_print_callback(stat, name, userdata, input, size, reason);
1467         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1468         return size;
1469 }
1470
1471
1472 int codegen_forinitop_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1473 {
1474         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1475         rulong off = rvm_codegen_getcodesize(co->cg);
1476         rvm_codespan_t *cs = (rvm_codespan_t *)r_array_lastslot(co->codespan);
1477
1478
1479         cs->l1 = rvm_codegen_getcodesize(co->cg);
1480         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
1481         cs->l2 = rvm_codegen_getcodesize(co->cg);
1482         rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, 1)); // Break point, This will be re-written.
1483         cs->l3 = rvm_codegen_getcodesize(co->cg);
1484
1485         codegen_print_callback(stat, name, userdata, input, size, reason);
1486         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1487         return size;
1488 }
1489
1490 /*
1491  * The code generated for the increment expression will appear before the comparison expression
1492  * due to the trick we did in the BNF schema. That will make the implementation of the for ( ; ; ) loops
1493  * a lot more easier and the generated code having less branch instructions
1494  */
1495 int codegen_forincrementop_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1496 {
1497         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1498         rulong off = rvm_codegen_getcodesize(co->cg);
1499         rvm_codespan_t *cs = (rvm_codespan_t *)r_array_lastslot(co->codespan);
1500
1501         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
1502
1503         codegen_print_callback(stat, name, userdata, input, size, reason);
1504         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1505         return size;
1506 }
1507
1508
1509 int codegen_forcompareop_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1510 {
1511         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1512         rulong off = rvm_codegen_getcodesize(co->cg);
1513         rvm_codespan_t *cs = (rvm_codespan_t *)r_array_lastslot(co->codespan);
1514
1515         rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
1516         cs->l4 = rvm_codegen_getcodesize(co->cg);
1517         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.
1518         /*
1519          * The beginning loop starts here, right after the RVM_BEQ instruction.
1520          */
1521
1522         codegen_print_callback(stat, name, userdata, input, size, reason);
1523         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1524         return size;
1525 }
1526
1527
1528 int codegen_iterationforop_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1529 {
1530         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1531         rulong off = rvm_codegen_getcodesize(co->cg);
1532         rvm_codespan_t cs = r_array_pop(co->codespan, rvm_codespan_t);
1533
1534         rvm_codegen_addins(co->cg, rvm_asm(RVM_B, DA, XX, XX, -(rvm_codegen_getcodesize(co->cg) - (cs.l3))));
1535         cs.codesize = rvm_codegen_getcodesize(co->cg) - cs.codestart;
1536         rvm_codegen_replaceins(co->cg, cs.l4, rvm_asm(RVM_BEQ, DA, XX, XX, cs.codesize - (cs.l4 - cs.codestart)));
1537         rvm_codegen_replaceins(co->cg, cs.l2, rvm_asm(RVM_B, DA, XX, XX, cs.codesize - (cs.l2 - cs.codestart)));        // Re-writing the instruction
1538
1539         rvm_scope_pop(co->scope);
1540         r_array_removelast(co->loops);
1541
1542         codegen_print_callback(stat, name, userdata, input, size, reason);
1543         codegen_dump_code(rvm_codegen_getcode(co->cg, off), rvm_codegen_getcodesize(co->cg) - off);
1544         return size;
1545 }
1546
1547
1548 int codegen_newexpressionop_callback(rpa_stat_handle stat, const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason)
1549 {
1550         rvm_compiler_t *co = (rvm_compiler_t *)userdata;
1551         rulong off = rvm_codegen_getcodesize(co->cg);
1552
1553         if (reason & RPA_REASON_START) {
1554
1555         } else  if (reason & RPA_REASON_MATCHED) {
1556
1557         }
1558
1559
1560         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
1561
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 void codegen_unmap_file(rstr_t *buf)
1570 {
1571         if (buf) {
1572                 munmap(buf->str, buf->size);
1573                 r_free(buf);
1574         }
1575 }
1576
1577
1578 rstr_t *codegen_map_file(const char *filename)
1579 {
1580         struct stat st;
1581         rstr_t *str;
1582         char *buffer;
1583
1584
1585         int fd = open(filename, O_RDONLY);
1586         if (fd < 0) {
1587                 return (void*)0;
1588         }
1589         if (fstat(fd, &st) < 0) {
1590                 close(fd);
1591                 return (void*)0;
1592         }
1593         buffer = (char*)mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
1594         if (buffer == (void*)-1) {
1595                 close(fd);
1596                 return (void*)0;
1597         }
1598         str = (rstr_t *)r_malloc(sizeof(*str));
1599         if (!str)
1600                 goto error;
1601         r_memset(str, 0, sizeof(*str));
1602         str->str = buffer;
1603         str->size = st.st_size;
1604         close(fd);
1605         return str;
1606
1607 error:
1608         munmap(buffer, st.st_size);
1609         close(fd);
1610         return str;
1611 }
1612
1613
1614 int main(int argc, char *argv[])
1615 {
1616         int res, i;
1617         rstr_t *script = NULL, *unmapscript = NULL;
1618         rvmcpu_t *cpu;
1619         ruint ntable;
1620         rpa_dbex_handle dbex = rpa_dbex_create();
1621         rvm_compiler_t *co = rvm_compiler_create(dbex);
1622
1623         cpu = rvm_cpu_create_default();
1624         ntable = rvm_cpu_addswitable(cpu, switable);
1625         rvm_cpu_addswitable(cpu, switable_js);
1626         co->cpu = cpu;
1627
1628         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
1629         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
1630         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
1631         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
1632
1633         for (i = 1; i < argc; i++) {
1634                 if (r_strcmp(argv[i], "-L") == 0) {
1635                 } else if (r_strcmp(argv[i], "-d") == 0) {
1636                         debuginfo = 1;
1637                 } else if (r_strcmp(argv[i], "-p") == 0) {
1638                         parseinfo = 1;
1639                 } else if (r_strcmp(argv[i], "-P") == 0) {
1640                         parseinfo = 1;
1641                         verboseinfo = 1;
1642                 } else if (r_strcmp(argv[i], "-c") == 0) {
1643                         compileonly = 1;
1644                 } else if (r_strcmp(argv[i], "-o") == 0) {
1645                         co->optimized = 1;
1646                 } else if (r_strcmp(argv[i], "-m") == 0) {
1647
1648                 }
1649         }
1650
1651         rpagen_load_rules(dbex, co);
1652
1653         for (i = 1; i < argc; i++) {
1654                 if (r_strcmp(argv[i], "-e") == 0) {
1655                         if (++i < argc) {
1656                                 rstr_t script = { argv[i], r_strlen(argv[i]) };
1657                                 res = rpa_dbex_parse(dbex, rpa_dbex_default_pattern(dbex), script.str, script.str, script.str + script.size);
1658                                 if (res <= 0)
1659                                         rvm_codegen_clear(co->cg);
1660                         }
1661                         goto exec;
1662                 }
1663         }
1664
1665         for (i = 1; i < argc; i++) {
1666                 if (r_strcmp(argv[i], "-f") == 0) {
1667
1668                         if (++i < argc) {
1669                                 script = codegen_map_file(argv[i]);
1670                                 if (script) {
1671                                         res = rpa_dbex_parse(dbex, rpa_dbex_default_pattern(dbex), script->str, script->str, script->str + script->size);
1672                                         unmapscript = script;
1673                                 }
1674
1675                         }
1676                         goto exec;
1677                 }
1678         }
1679
1680
1681 exec:
1682         rvm_relocate(rvm_codegen_getcode(co->cg, 0), rvm_codegen_getcodesize(co->cg));
1683
1684         if (debuginfo) {
1685                 fprintf(stdout, "\nGenerated Code:\n");
1686                 rvm_asm_dump(rvm_codegen_getcode(co->cg, 0), rvm_codegen_getcodesize(co->cg));
1687                 if (rvm_codegen_getcodesize(co->cg)) {
1688                         if (!compileonly) {
1689                                 fprintf(stdout, "\nExecution:\n");
1690                                 rvm_cpu_exec_debug(cpu, rvm_codegen_getcode(co->cg, 0), 0);
1691                         }
1692                 }
1693         } else {
1694                 if (!compileonly)
1695                         rvm_cpu_exec(cpu, rvm_codegen_getcode(co->cg, 0), 0);
1696         }
1697
1698         if (unmapscript)
1699                 codegen_unmap_file(unmapscript);
1700         rpa_dbex_destroy(dbex);
1701         rvm_cpu_destroy(cpu);
1702         rvm_compiler_destroy(co);
1703
1704         if (debuginfo) {
1705                 r_printf("Max alloc mem: %ld\n", r_debug_get_maxmem());
1706                 r_printf("Leaked mem: %ld\n", r_debug_get_allocmem());
1707         }
1708         return 0;
1709 }
1710
1711
1712 #define EOL "\n"
1713
1714
1715 extern char _binary_____________tests_ecma262_rpa_start[];
1716 extern char _binary_____________tests_ecma262_rpa_end[];
1717 extern unsigned long *_binary_____________tests_ecma262_rpa_size;
1718
1719 void rpagen_load_rules(rpa_dbex_handle dbex, rvm_compiler_t *co)
1720 {
1721         int ret, line;
1722         int inputsize = _binary_____________tests_ecma262_rpa_end - _binary_____________tests_ecma262_rpa_start;
1723         const char *buffer = _binary_____________tests_ecma262_rpa_start;
1724         const char *pattern = buffer;
1725
1726         rpa_dbex_open(dbex);
1727
1728         rpa_dbex_add_callback_exact(dbex, "BitwiseANDOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1729         rpa_dbex_add_callback_exact(dbex, "BitwiseXOROp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1730         rpa_dbex_add_callback_exact(dbex, "BitwiseOROp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1731         rpa_dbex_add_callback_exact(dbex, "AdditiveExpressionOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1732
1733         rpa_dbex_add_callback_exact(dbex, "MultiplicativeExpressionOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1734         rpa_dbex_add_callback_exact(dbex, "ShiftExpressionOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1735         rpa_dbex_add_callback_exact(dbex, "EqualityExpressionOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1736         rpa_dbex_add_callback_exact(dbex, "RelationalExpressionOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1737         rpa_dbex_add_callback_exact(dbex, "LogicalOROp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1738         rpa_dbex_add_callback_exact(dbex, "LogicalANDOp", RPA_REASON_ALL, codegen_binary_asmop_callback, co);
1739
1740         rpa_dbex_add_callback_exact(dbex, "AssignmentOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1741         rpa_dbex_add_callback_exact(dbex, "EqualityOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1742         rpa_dbex_add_callback_exact(dbex, "RelationalOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1743         rpa_dbex_add_callback_exact(dbex, "AdditiveOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1744         rpa_dbex_add_callback_exact(dbex, "MultiplicativeOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1745         rpa_dbex_add_callback_exact(dbex, "ShiftOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1746         rpa_dbex_add_callback_exact(dbex, "BitwiseANDOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1747         rpa_dbex_add_callback_exact(dbex, "BitwiseXOROperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1748         rpa_dbex_add_callback_exact(dbex, "BitwiseOROperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1749         rpa_dbex_add_callback_exact(dbex, "LogicalANDOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1750         rpa_dbex_add_callback_exact(dbex, "LogicalOROperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1751         rpa_dbex_add_callback_exact(dbex, "LogicalNotOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1752         rpa_dbex_add_callback_exact(dbex, "BitwiseNotOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1753         rpa_dbex_add_callback_exact(dbex, "UnaryOperatorOpcode", RPA_REASON_MATCHED, codegen_opcode_unary_callback, co);
1754         rpa_dbex_add_callback_exact(dbex, "PrintOp", RPA_REASON_MATCHED, codegen_printop_callback, co);
1755
1756
1757         rpa_dbex_add_callback_exact(dbex, "PostfixOperator", RPA_REASON_MATCHED, codegen_opcode_callback, co);
1758         rpa_dbex_add_callback_exact(dbex, "PostfixExpressionOp", RPA_REASON_MATCHED, codegen_oppostfix_callback, co);
1759         rpa_dbex_add_callback_exact(dbex, "PrefixExpressionOp", RPA_REASON_MATCHED, codegen_opprefix_callback, co);
1760
1761
1762         rpa_dbex_add_callback_exact(dbex, "UnaryExpressionOp", RPA_REASON_ALL, codegen_unary_asmop_callback, co);
1763         rpa_dbex_add_callback_exact(dbex, "LogicalNotExpressionOp", RPA_REASON_ALL, codegen_unary_asmop_callback, co);
1764         rpa_dbex_add_callback_exact(dbex, "BitwiseNotExpressionOp", RPA_REASON_ALL, codegen_unary_asmop_callback, co);
1765
1766         rpa_dbex_add_callback_exact(dbex, "DecimalIntegerLiteral", RPA_REASON_MATCHED, codegen_integer_callback, co);
1767         rpa_dbex_add_callback_exact(dbex, "DecimalNonIntegerLiteral", RPA_REASON_MATCHED, codegen_double_callback, co);
1768         rpa_dbex_add_callback_exact(dbex, "BlockBegin", RPA_REASON_MATCHED, codegen_scopepush_callback, co);
1769         rpa_dbex_add_callback_exact(dbex, "BlockEnd", RPA_REASON_MATCHED, codegen_scopepop_callback, co);
1770
1771         rpa_dbex_add_callback_exact(dbex, "DoKeyword", RPA_REASON_MATCHED, codegen_dokeyword_callback, co);
1772         rpa_dbex_add_callback_exact(dbex, "IterationDo", RPA_REASON_MATCHED, codegen_iterationdo_callback, co);
1773
1774         rpa_dbex_add_callback_exact(dbex, "sqstring", RPA_REASON_MATCHED, codegen_string_callback, co);
1775         rpa_dbex_add_callback_exact(dbex, "dqstring", RPA_REASON_MATCHED, codegen_string_callback, co);
1776         rpa_dbex_add_callback_exact(dbex, "DoubleStringCharacters", RPA_REASON_MATCHED, codegen_string_callback, co);
1777         rpa_dbex_add_callback_exact(dbex, "SingleStringCharacters", RPA_REASON_MATCHED, codegen_string_callback, co);
1778         rpa_dbex_add_callback_exact(dbex, "Program", RPA_REASON_START|RPA_REASON_MATCHED, codegen_program_callback, co);
1779         rpa_dbex_add_callback_exact(dbex, "Initialiser", RPA_REASON_MATCHED, codegen_opinit_callback, co);
1780         rpa_dbex_add_callback_exact(dbex, "AssignmentExpressionOp", RPA_REASON_MATCHED, codegen_opassign_callback, co);
1781
1782         rpa_dbex_add_callback_exact(dbex, "VariableAllocate", RPA_REASON_MATCHED, codegen_varalloc_callback, co);
1783         rpa_dbex_add_callback_exact(dbex, "VariableAllocateAndInit", RPA_REASON_MATCHED, codegen_varalloc_to_ptr_callback, co);
1784
1785         rpa_dbex_add_callback_exact(dbex, "ReturnOp", RPA_REASON_MATCHED, codegen_opreturn_callback, co);
1786
1787         rpa_dbex_add_callback_exact(dbex, "SwiId", RPA_REASON_MATCHED, codegen_swiid_callback, co);
1788         rpa_dbex_add_callback_exact(dbex, "SwiIdExist", RPA_REASON_MATCHED, codegen_swiidexist_callback, co);
1789
1790         rpa_dbex_add_callback_exact(dbex, "PostfixExpressionValOp", RPA_REASON_ALL, codegen_valop_callback, co);
1791         rpa_dbex_add_callback_exact(dbex, "LeftHandSideExpressionPush", RPA_REASON_MATCHED, codegen_push_r0_callback, co);
1792
1793         ////////////////
1794
1795         rpa_dbex_add_callback_exact(dbex, "IdentifierOp", RPA_REASON_MATCHED, codegen_opidentifier_callback, co);
1796         rpa_dbex_add_callback_exact(dbex, "MemberIdentifierNameOp", RPA_REASON_MATCHED, codegen_h_arraynamelookup_callback, co);
1797         rpa_dbex_add_callback_exact(dbex, "MemberExpressionBaseOp", RPA_REASON_MATCHED, codegen_push_r0_callback, co);
1798         rpa_dbex_add_callback_exact(dbex, "MemberExpressionIndexOp", RPA_REASON_MATCHED, codegen_n_arrayelementvalue_callback, co);
1799         rpa_dbex_add_callback_exact(dbex, "MemberExpressionNameOp", RPA_REASON_MATCHED, codegen_h_arrayelementvalue_callback, co);
1800         rpa_dbex_add_callback_exact(dbex, "CallExpressionNameOp", RPA_REASON_MATCHED, codegen_h_arrayelementvalue_callback, co);
1801         rpa_dbex_add_callback_exact(dbex, "CallExpressionBaseOp", RPA_REASON_MATCHED, codegen_push_r0_callback, co);
1802         rpa_dbex_add_callback_exact(dbex, "CallExpressionIndexOp", RPA_REASON_MATCHED, codegen_n_arrayelementvalue_callback, co);
1803         rpa_dbex_add_callback_exact(dbex, "AddressLeftHandSideExpression", RPA_REASON_MATCHED, codegen_addressoflefthandside_callback, co);
1804
1805         ////////////////
1806
1807
1808         rpa_dbex_add_callback_exact(dbex, "ConditionalExpression", RPA_REASON_MATCHED, codegen_conditionalexp_callback, co);
1809         rpa_dbex_add_callback_exact(dbex, "NewArraySize", RPA_REASON_MATCHED, codegen_newarraysize_callback, co);
1810         rpa_dbex_add_callback_exact(dbex, "NewArrayNoSize", RPA_REASON_MATCHED, codegen_newarraynosize_callback, co);
1811         rpa_dbex_add_callback_exact(dbex, "compile_error", RPA_REASON_MATCHED, codegen_compile_error_callback, co);
1812
1813         rpa_dbex_add_callback_exact(dbex, "ArgumentsOp", RPA_REASON_ALL, codegen_costate_callback, co);
1814         rpa_dbex_add_callback_exact(dbex, "BracketExpressionOp", RPA_REASON_ALL, codegen_costate_callback, co);
1815         rpa_dbex_add_callback_exact(dbex, "ValLeftHandSideExpression", RPA_REASON_ALL, codegen_costate_callback, co);
1816
1817
1818         rpa_dbex_add_callback_exact(dbex, "FunctionName", RPA_REASON_MATCHED, codegen_fundeclname_callback, co);
1819         rpa_dbex_add_callback_exact(dbex, "FunctionDefinition", RPA_REASON_MATCHED, codegen_fundeclsignature_callback, co);
1820         rpa_dbex_add_callback_exact(dbex, "FunctionDeclaration", RPA_REASON_MATCHED, codegen_fundecl_callback, co);
1821         rpa_dbex_add_callback_exact(dbex, "FunctionParameter", RPA_REASON_MATCHED, codegen_fundeclparameter_callback, co);
1822         rpa_dbex_add_callback_exact(dbex, "FunctionCallParameter", RPA_REASON_MATCHED, codegen_funcallparameter_callback, co);
1823         rpa_dbex_add_callback_exact(dbex, "FunctionCallName", RPA_REASON_MATCHED, codegen_funcallname_callback, co);
1824         rpa_dbex_add_callback_exact(dbex, "CallExpressionOp", RPA_REASON_MATCHED, codegen_funcallexpression_callback, co);
1825
1826
1827         rpa_dbex_add_callback_exact(dbex, "IfConditionOp", RPA_REASON_MATCHED, codegen_ifconditionop_callback, co);
1828         rpa_dbex_add_callback_exact(dbex, "IfOp", RPA_REASON_MATCHED, codegen_ifop_callback, co);
1829         rpa_dbex_add_callback_exact(dbex, "ElseOp", RPA_REASON_MATCHED, codegen_elseop_callback, co);
1830         rpa_dbex_add_callback_exact(dbex, "IfElseOp", RPA_REASON_MATCHED, codegen_ifelseop_callback, co);
1831
1832         rpa_dbex_add_callback_exact(dbex, "WhileConditionOp", RPA_REASON_MATCHED, codegen_whileconditionop_callback, co);
1833         rpa_dbex_add_callback_exact(dbex, "IterationWhileOp", RPA_REASON_ALL, codegen_iterationwhileop_callback, co);
1834
1835         rpa_dbex_add_callback_exact(dbex, "QuestionMarkOp", RPA_REASON_MATCHED, codegen_questionmarkop_callback, co);
1836         rpa_dbex_add_callback_exact(dbex, "AssignmentExpressionIfTrueOp", RPA_REASON_MATCHED, codegen_iftrueop_callback, co);
1837         rpa_dbex_add_callback_exact(dbex, "AssignmentExpressionIfFalseOp", RPA_REASON_MATCHED, codegen_iffalseop_callback, co);
1838
1839         rpa_dbex_add_callback_exact(dbex, "ForKeyword", RPA_REASON_MATCHED, codegen_forkeyword_callback, co);
1840         rpa_dbex_add_callback_exact(dbex, "ForExpressionInitOp", RPA_REASON_END, codegen_forinitop_callback, co);
1841         rpa_dbex_add_callback_exact(dbex, "ForExpressionCompareOp", RPA_REASON_END, codegen_forcompareop_callback, co);
1842         rpa_dbex_add_callback_exact(dbex, "ForExpressionIncrementOp", RPA_REASON_END, codegen_forincrementop_callback, co);
1843         rpa_dbex_add_callback_exact(dbex, "IterationForOp", RPA_REASON_MATCHED, codegen_iterationforop_callback, co);
1844         rpa_dbex_add_callback_exact(dbex, "BreakOp", RPA_REASON_MATCHED, codegen_breakkeyword_callback, co);
1845         rpa_dbex_add_callback_exact(dbex, "ContinueOp", RPA_REASON_MATCHED, codegen_continuekeyword_callback, co);
1846
1847         rpa_dbex_add_callback_exact(dbex, "NewExpressionOp", RPA_REASON_ALL, codegen_newexpressionop_callback, co);
1848
1849         if (verboseinfo)
1850                 rpa_dbex_add_callback(dbex, ".*", RPA_REASON_MATCHED, codegen_print_callback, co);
1851
1852         while ((ret = rpa_dbex_load(dbex, pattern, inputsize)) > 0) {
1853                 inputsize -= ret;
1854                 pattern += ret;
1855         }
1856         if (ret < 0) {
1857                 for (line = 1; pattern >= buffer; --pattern) {
1858                         if (*pattern == '\n')
1859                                 line += 1;
1860                 }
1861                 fprintf(stdout, "Line: %d, RPA LOAD ERROR: %s\n", line, (rpa_dbex_get_error(dbex) == RPA_E_SYNTAX_ERROR) ? "Syntax Error." : "Pattern Loading failed.");
1862                 goto error;
1863         }
1864
1865 error:
1866         rpa_dbex_close(dbex);
1867 }