RPA Toolkit
work on RJS object introspection.
[rpatk.git] / rjs / rjscompiler.c
1 /*
2  *  Regular Pattern Analyzer (RPA)
3  *  Copyright (c) 2009-2010 Martin Stoilov
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  *  Martin Stoilov <martin@rpasearch.com>
19  */
20
21 #include "rlib/rmem.h"
22 #include "rjs/rjscompiler.h"
23 #include "rjs/rjsparser.h"
24
25
26 int rjs_compiler_playreversechildrecords(rjs_compiler_t *co, rarray_t *records, long rec);
27 static int rjs_compiler_playrecord(rjs_compiler_t *co, rarray_t *records, long rec);
28 static int rjs_compiler_playchildrecords(rjs_compiler_t *co, rarray_t *records, long rec);
29
30
31 void rjs_compiler_debughead(rjs_compiler_t *co, rarray_t *records, long rec)
32 {
33         rvm_codegen_setsource(co->cg, rec);
34         if (co->debug) {
35                 rparecord_t *prec = (rparecord_t *) r_array_slot(records, rec);
36                 co->headoff = rvm_codegen_getcodesize(co->cg);
37                 if (prec->type & RPA_RECORD_START) {
38                         rpa_record_dump(records, rec);
39                 }
40
41         }
42 }
43
44
45 void rjs_compiler_debugtail(rjs_compiler_t *co, rarray_t *records, long rec)
46 {
47         rvm_codegen_setsource(co->cg, rec);
48         if (co->debug) {
49                 rparecord_t *prec = (rparecord_t *) r_array_slot(records, rec);
50                 rvm_asm_dump(rvm_codegen_getcode(co->cg, co->headoff), rvm_codegen_getcodesize(co->cg) - co->headoff);
51                 if (prec->type & RPA_RECORD_END) {
52                         rpa_record_dump(records, rec);
53                 }
54         }
55
56 }
57
58
59 void rjs_compiler_adderror(rjs_compiler_t *co, long code, rparecord_t *prec)
60 {
61         co->error->type = RJS_ERRORTYPE_SYNTAX;
62         co->error->error = code;
63         co->error->script = co->script;
64         co->error->offset = (long)(prec->input - co->script);
65         co->error->size = prec->inputsiz;
66         co->error->line = rjs_parser_offset2line(co->script, co->error->offset);
67         co->error->lineoffset = rjs_parser_offset2lineoffset(co->script, co->error->offset);
68
69 }
70
71
72 static const char *rjs_compiler_record2str(rjs_compiler_t *co, rarray_t *records, long rec)
73 {
74         rparecord_t *prec = (rparecord_t *)r_array_slot(records, rpa_recordtree_get(records, rec, RPA_RECORD_END));
75         unsigned long size = 16; /* Min size */
76
77         if (prec && prec->inputsiz) {
78                 size = prec->inputsiz + 1;
79         }
80         co->temp = r_realloc(co->temp, size);
81         r_memset(co->temp, 0, size);
82         if (prec->input && prec->inputsiz)
83                 r_memcpy(co->temp, prec->input, prec->inputsiz);
84         return co->temp;
85 }
86
87
88 static long rjs_compiler_record_parentuid(rjs_compiler_t *co, rarray_t *records, long rec)
89 {
90         long parent = rpa_recordtree_parent(records, rec, RPA_RECORD_START);
91
92         if (parent < 0)
93                 return -1;
94         return rpa_record_getruleuid(records, parent);
95 }
96
97
98 static long rjs_compiler_record_lastofkind(rjs_compiler_t *co, rarray_t *records, long rec)
99 {
100         long uid = rpa_record_getruleuid(records, rec);
101         long i;
102
103         for (i = rpa_recordtree_next(records, rec, RPA_RECORD_START) ; i >= 0; i = rpa_recordtree_next(records, i, RPA_RECORD_START)) {
104                 if (rpa_record_getruleuid(records, i) == uid)
105                         return 0;
106         }
107         return 1;
108 }
109
110
111 static long rjs_compiler_record2identifer(rjs_compiler_t *co, rarray_t *records, long rec)
112 {
113         rvm_varmap_t *v = NULL;
114         rjs_coctx_t *ctx = NULL;
115         rparecord_t *prec = (rparecord_t *)r_array_slot(records, rec);
116
117         /*
118          * First lets find out if we are within a function definition or
119          * this is a global variable.
120          */
121         ctx = rjs_compiler_getctx(co, RJS_COCTX_FUNCTION | RJS_COCTX_GLOBAL);
122         R_ASSERT(ctx);
123
124         v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
125
126         /*
127          * TBD: Temporary here
128          */
129         if (v) {
130                 r_printf("ERROR: Identifier already defined: %s\n", rjs_compiler_record2str(co, records, rec));
131                 return -1;
132         }
133
134         if ( ctx->type == RJS_COCTX_FUNCTION ) {
135                 rjs_coctx_function_t *functx = (rjs_coctx_function_t *)ctx;
136                 functx->stackallocs += 1;
137                 rvm_scope_addoffset(co->scope, prec->input, prec->inputsiz, functx->stackallocs);
138         } else {
139                 if (rvm_scope_count(co->scope)) {
140                         rjs_coctx_global_t *globalctx = (rjs_coctx_global_t *)ctx;
141                         globalctx->stackallocs += 1;
142                         rvm_scope_addoffset(co->scope, prec->input, prec->inputsiz, globalctx->stackallocs);
143                 } else {
144                         /*
145                          * Global Data
146                          */
147                         rvm_scope_addpointer(co->scope, prec->input, prec->inputsiz, rvm_cpu_alloc_global(co->cpu));
148                 }
149         }
150         v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
151         if (v->datatype == VARMAP_DATATYPE_OFFSET) {
152                 rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDRS, R0, FP, DA, v->data.offset));
153         } else {
154                 rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R0, DA, XX, v->data.ptr));
155         }
156
157         return 0;
158 }
159
160
161 rjs_coctx_t *rjs_compiler_getctx(rjs_compiler_t *co, unsigned long type)
162 {
163         long i;
164         rjs_coctx_t *ctx;
165
166         for (i = r_array_length(co->coctx) - 1; i >= 0; i--) {
167                 ctx = r_array_index(co->coctx, i, rjs_coctx_t*);
168                 if (ctx->type & type)
169                         return ctx;
170         }
171         return NULL;
172 }
173
174
175 rjs_coctx_t *rjs_compiler_gettopctx(rjs_compiler_t *co)
176 {
177         long len = r_array_length(co->coctx);
178
179         if (len)
180                 return r_array_index(co->coctx, len - 1, rjs_coctx_t*);
181         return NULL;
182 }
183
184
185 long rjs_compiler_record2opcode(rparecord_t *prec)
186 {
187         const char *input = prec->input;
188         unsigned long size = prec->inputsiz;
189
190         if (r_stringncmp("++", input,  size))
191                 return RVM_EADD;
192         else if (r_stringncmp("+", input,  size))
193                 return RVM_EADD;
194         else if (r_stringncmp("+=", input,  size))
195                 return RVM_EADD;
196         else if (r_stringncmp("--", input,  size))
197                 return RVM_ESUB;
198         else if (r_stringncmp("-", input,  size))
199                 return RVM_ESUB;
200         else if (r_stringncmp("-=", input,  size))
201                 return RVM_ESUB;
202         else if (r_stringncmp("*", input,  size))
203                 return RVM_EMUL;
204         else if (r_stringncmp("*=", input,  size))
205                 return RVM_EMUL;
206         else if (r_stringncmp("/", input,  size))
207                 return RVM_EDIV;
208         else if (r_stringncmp("/=", input,  size))
209                 return RVM_EDIV;
210         else if (r_stringncmp("%", input,  size))
211                 return RVM_EMOD;
212         else if (r_stringncmp("%=", input,  size))
213                 return RVM_EMOD;
214         else if (r_stringncmp("&&", input,  size))
215                 return RVM_ELAND;
216         else if (r_stringncmp("||", input,  size))
217                 return RVM_ELOR;
218         else if (r_stringncmp("&", input,  size))
219                 return RVM_EAND;
220         else if (r_stringncmp("&=", input,  size))
221                 return RVM_EAND;
222         else if (r_stringncmp("|", input,  size))
223                 return RVM_EORR;
224         else if (r_stringncmp("|=", input,  size))
225                 return RVM_EORR;
226         else if (r_stringncmp("^", input,  size))
227                 return RVM_EXOR;
228         else if (r_stringncmp("^=", input,  size))
229                 return RVM_EXOR;
230         else if (r_stringncmp(">>", input,  size))
231                 return RVM_ELSR;
232         else if (r_stringncmp(">>=", input,  size))
233                 return RVM_ELSR;
234         else if (r_stringncmp("<<", input,  size))
235                 return RVM_ELSL;
236         else if (r_stringncmp("<<=", input,  size))
237                 return RVM_ELSL;
238         else if (r_stringncmp(">>>", input,  size))
239                 return RVM_ELSRU;
240         else if (r_stringncmp(">>>=", input,  size))
241                 return RVM_ELSRU;
242         else if (r_stringncmp("<=", input,  size))
243                 return RVM_ELESSEQ;
244         else if (r_stringncmp(">=", input,  size))
245                 return RVM_EGREATEQ;
246         else if (r_stringncmp("<", input,  size))
247                 return RVM_ELESS;
248         else if (r_stringncmp(">", input,  size))
249                 return RVM_EGREAT;
250         else if (r_stringncmp("===", input,  size))
251                 return RVM_EEQ;
252         else if (r_stringncmp("==", input,  size))
253                 return RVM_EEQ;
254         else if (r_stringncmp("!==", input,  size))
255                 return RVM_ENOTEQ;
256         else if (r_stringncmp("!=", input,  size))
257                 return RVM_ENOTEQ;
258         else if (r_stringncmp("!", input,  size))
259                 return RVM_ELNOT;
260         else if (r_stringncmp("~", input,  size))
261                 return RVM_ENOT;
262         else if (r_stringncmp("=", input,  size))
263                 return RVM_NOP;
264
265         return -1;
266 }
267
268
269 long rjs_compiler_record2unaryopcode(rparecord_t *prec)
270 {
271         const char *input = prec->input;
272         unsigned long size = prec->inputsiz;
273
274         if (r_stringncmp("+", input,  size))
275                 return RVM_NOP;
276         else if (r_stringncmp("-", input,  size))
277                 return RVM_ENEG;
278         else if (r_stringncmp("~", input,  size))
279                 return RVM_ENOT;
280         else if (r_stringncmp("!", input,  size))
281                 return RVM_ELNOT;
282         else
283                 return RVM_NOP;
284
285         return -1;
286 }
287
288
289 static int rjs_compiler_internalvars_setup(rjs_compiler_t *co)
290 {
291         rvm_varmap_t *v;
292
293         v = rvm_scope_tiplookup_s(co->scope, "ARGS");
294         if (!v) {
295                 rvm_scope_addpointer_s(co->scope, "ARGS", rvm_cpu_alloc_global(co->cpu));
296                 v = rvm_scope_tiplookup_s(co->scope, "ARGS");
297                 R_ASSERT(v);
298                 return -1;
299         }
300         rvm_reg_setundef((rvmreg_t*)v->data.ptr);
301
302         return 0;
303 }
304
305
306 int rjs_compiler_rh_program(rjs_compiler_t *co, rarray_t *records, long rec)
307 {
308         rjs_coctx_global_t ctx;
309         rparecord_t *prec;
310         long mainidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
311         long allocsidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
312         long start;
313
314         r_memset(&ctx, 0, sizeof(ctx));
315         ctx.base.type = RJS_COCTX_GLOBAL;
316         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
317
318         prec = (rparecord_t *)r_array_slot(records, rec);
319         rjs_compiler_debughead(co, records, rec);
320         rjs_compiler_internalvars_setup(co);
321         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, mainidx, rvm_asm(RVM_B, DA, XX, XX, 0));
322         start = rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
323         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_DEFAULT, allocsidx, rvm_asm(RVM_ADD, SP, FP, DA, 0));
324         rjs_compiler_debugtail(co, records, rec);
325
326         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
327                 goto error;
328
329         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
330         prec = (rparecord_t *)r_array_slot(records, rec);
331         rvm_codegen_redefinepointer(co->cg, allocsidx, (rpointer)ctx.stackallocs);
332         rjs_compiler_debughead(co, records, rec);
333         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
334         rvm_codegen_redefinelabel_default(co->cg, mainidx);
335         rvm_codegen_addins(co->cg, rvm_asm(RVM_BL, DA, XX, XX, start - (long)rvm_codegen_getcodesize(co->cg)));
336         rvm_codegen_addins(co->cg, rvm_asm(RVM_EXT, XX, XX, XX, 0));
337         rjs_compiler_debugtail(co, records, rec);
338         r_array_removelast(co->coctx);
339         return 0;
340
341 error:
342         r_array_removelast(co->coctx);
343         return -1;
344 }
345
346
347 int rjs_compiler_rh_varalloc(rjs_compiler_t *co, rarray_t *records, long rec)
348 {
349         rparecord_t *prec;
350         prec = (rparecord_t *)r_array_slot(records, rec);
351         rjs_compiler_debughead(co, records, rec);
352         rjs_compiler_debugtail(co, records, rec);
353
354         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
355                 return -1;
356
357         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
358         prec = (rparecord_t *)r_array_slot(records, rec);
359         rjs_compiler_debughead(co, records, rec);
360         if (rjs_compiler_record2identifer(co, records, rec) < 0)
361                 return -1;
362         rjs_compiler_debugtail(co, records, rec);
363         return 0;
364 }
365
366
367 int rjs_compiler_rh_varallocinit(rjs_compiler_t *co, rarray_t *records, long rec)
368 {
369         rparecord_t *prec;
370         prec = (rparecord_t *)r_array_slot(records, rec);
371         rjs_compiler_debughead(co, records, rec);
372         rjs_compiler_debugtail(co, records, rec);
373
374         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
375                 return -1;
376
377         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
378         prec = (rparecord_t *)r_array_slot(records, rec);
379         rjs_compiler_debughead(co, records, rec);
380         if (rjs_compiler_record2identifer(co, records, rec) < 0)
381                 return -1;
382         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
383         rjs_compiler_debugtail(co, records, rec);
384         return 0;
385 }
386
387
388 int rjs_compiler_rh_initializer(rjs_compiler_t *co, rarray_t *records, long rec)
389 {
390         rparecord_t *prec;
391         prec = (rparecord_t *)r_array_slot(records, rec);
392         rjs_compiler_debughead(co, records, rec);
393         rjs_compiler_debugtail(co, records, rec);
394
395         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
396                 return -1;
397
398         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
399         prec = (rparecord_t *)r_array_slot(records, rec);
400         rjs_compiler_debughead(co, records, rec);
401         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
402         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
403         rjs_compiler_debugtail(co, records, rec);
404         return 0;
405 }
406
407
408 int rjs_compiler_rh_identifier(rjs_compiler_t *co, rarray_t *records, long rec)
409 {
410         rvm_varmap_t *v;
411         rparecord_t *prec;
412         long swiid = -1;
413         prec = (rparecord_t *)r_array_slot(records, rec);
414         rjs_compiler_debughead(co, records, rec);
415         rjs_compiler_debugtail(co, records, rec);
416
417         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
418                 return -1;
419
420         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
421         prec = (rparecord_t *)r_array_slot(records, rec);
422         rjs_compiler_debughead(co, records, rec);
423         v = rvm_scope_lookup(co->scope, prec->input, prec->inputsiz);
424         if (!v) {
425                 /*
426                  * Let see if this is a swiid
427                  */
428                 if ((swiid = rvm_cpu_swilookup(co->cpu, NULL, prec->input, prec->inputsiz)) >= 0) {
429                         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, swiid));
430                         rvm_codegen_addins(co->cg, rvm_asm(RVM_SETTYPE, R0, DA, XX, RVM_DTYPE_SWIID));
431                         goto end;
432                 }
433
434                 rjs_compiler_adderror(co, RJS_ERROR_UNDEFINED, prec);
435                 return -1;
436         }
437
438         if (rjs_compiler_record_parentuid(co, records, rec) == UID_LEFTHANDSIDEEXPRESSIONADDR && rpa_recordtree_next(records, rec, RPA_RECORD_START) == -1) {
439                 /*
440                  * If this is the last child of UID_LEFTHANDSIDEEXPRESSIONADDR
441                  */
442                 if (v->datatype == VARMAP_DATATYPE_OFFSET) {
443                         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDRS, R0, FP, DA, v->data.offset));
444                 } else {
445                         rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R0, DA, XX, v->data.ptr));
446                 }
447         } else {
448                 if (v->datatype == VARMAP_DATATYPE_OFFSET) {
449                         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDS, R0, FP, DA, v->data.offset));
450                 } else {
451                         rvm_codegen_addins(co->cg, rvm_asmp(RVM_LDRR, R0, DA, XX, v->data.ptr));
452                 }
453         }
454 end:
455         rjs_compiler_debugtail(co, records, rec);
456         return 0;
457 }
458
459
460 int rjs_compiler_rh_expression(rjs_compiler_t *co, rarray_t *records, long rec)
461 {
462         rparecord_t *prec;
463         prec = (rparecord_t *)r_array_slot(records, rec);
464         rjs_compiler_debughead(co, records, rec);
465         rjs_compiler_debugtail(co, records, rec);
466
467         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
468                 return -1;
469
470         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
471         prec = (rparecord_t *)r_array_slot(records, rec);
472         rjs_compiler_debughead(co, records, rec);
473         rjs_compiler_debugtail(co, records, rec);
474         return 0;
475 }
476
477
478 int rjs_compiler_rh_lefthandsideexpression(rjs_compiler_t *co, rarray_t *records, long rec)
479 {
480         rparecord_t *prec;
481         prec = (rparecord_t *)r_array_slot(records, rec);
482         rjs_compiler_debughead(co, records, rec);
483         rjs_compiler_debugtail(co, records, rec);
484
485         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
486                 return -1;
487
488         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
489         prec = (rparecord_t *)r_array_slot(records, rec);
490         rjs_compiler_debughead(co, records, rec);
491         rjs_compiler_debugtail(co, records, rec);
492         return 0;
493 }
494
495
496 int rjs_compiler_rh_lefthandsideexpressionaddr(rjs_compiler_t *co, rarray_t *records, long rec)
497 {
498         rparecord_t *prec;
499         prec = (rparecord_t *)r_array_slot(records, rec);
500         rjs_compiler_debughead(co, records, rec);
501         rjs_compiler_debugtail(co, records, rec);
502
503         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
504                 return -1;
505
506         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
507         prec = (rparecord_t *)r_array_slot(records, rec);
508         rjs_compiler_debughead(co, records, rec);
509         rvm_codegen_addins(co->cg, rvm_asmp(RVM_PUSH, R0, XX, XX, 0));
510         rjs_compiler_debugtail(co, records, rec);
511         return 0;
512 }
513
514
515 int rjs_compiler_rh_decimalintegerliteral(rjs_compiler_t *co, rarray_t *records, long rec)
516 {
517         rparecord_t *prec;
518         prec = (rparecord_t *)r_array_slot(records, rec);
519         rjs_compiler_debughead(co, records, rec);
520         rjs_compiler_debugtail(co, records, rec);
521
522         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
523                 return -1;
524
525         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
526         prec = (rparecord_t *)r_array_slot(records, rec);
527         rjs_compiler_debughead(co, records, rec);
528         rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R0, DA, XX, r_strtol(prec->input, NULL, 10)));
529         rjs_compiler_debugtail(co, records, rec);
530         return 0;
531 }
532
533
534 int rjs_compiler_rh_decimalnonintegerliteral(rjs_compiler_t *co, rarray_t *records, long rec)
535 {
536         rparecord_t *prec;
537         prec = (rparecord_t *)r_array_slot(records, rec);
538         rjs_compiler_debughead(co, records, rec);
539         rjs_compiler_debugtail(co, records, rec);
540
541         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
542                 return -1;
543
544         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
545         prec = (rparecord_t *)r_array_slot(records, rec);
546         rjs_compiler_debughead(co, records, rec);
547         rvm_codegen_addins(co->cg, rvm_asmd(RVM_MOV, R0, DA, XX, r_strtod(prec->input, NULL)));
548
549         rjs_compiler_debugtail(co, records, rec);
550         return 0;
551 }
552
553
554 int rjs_compiler_rh_stringcharacters(rjs_compiler_t *co, rarray_t *records, long rec)
555 {
556         rparecord_t *prec;
557         prec = (rparecord_t *)r_array_slot(records, rec);
558
559         rjs_compiler_debughead(co, records, rec);
560         rjs_compiler_debugtail(co, records, rec);
561
562         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
563                 return -1;
564
565         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
566         prec = (rparecord_t *)r_array_slot(records, rec);
567         rjs_compiler_debughead(co, records, rec);
568         co->stringcharacters.str = (char*)prec->input;
569         co->stringcharacters.size = prec->inputsiz;
570         rjs_compiler_debugtail(co, records, rec);
571         return 0;
572 }
573
574
575 int rjs_compiler_rh_stringliteral(rjs_compiler_t *co, rarray_t *records, long rec)
576 {
577         rparecord_t *prec;
578         prec = (rparecord_t *)r_array_slot(records, rec);
579
580         rjs_compiler_debughead(co, records, rec);
581         co->stringcharacters.str = NULL;
582         co->stringcharacters.size = 0;
583         rjs_compiler_debugtail(co, records, rec);
584
585         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
586                 return -1;
587
588         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
589         prec = (rparecord_t *)r_array_slot(records, rec);
590         rjs_compiler_debughead(co, records, rec);
591         rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R1, DA, XX, co->stringcharacters.str));
592         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R2, DA, XX, co->stringcharacters.size));
593         rvm_codegen_addins(co->cg, rvm_asm(RVM_ALLOCSTR, R0, R1, R2, 0));
594         rjs_compiler_debugtail(co, records, rec);
595         return 0;
596 }
597
598
599 int rjs_compiler_rh_binaryexpressionop(rjs_compiler_t *co, rarray_t *records, long rec)
600 {
601         rparecord_t *prec;
602         rjs_coctx_operation_t ctx;
603
604         r_memset(&ctx, 0, sizeof(ctx));
605         ctx.base.type = RJS_COCTX_OPERATION;
606         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
607
608         prec = (rparecord_t *)r_array_slot(records, rec);
609         rjs_compiler_debughead(co, records, rec);
610         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
611         rjs_compiler_debugtail(co, records, rec);
612         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
613                 goto error;
614         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
615         prec = (rparecord_t *)r_array_slot(records, rec);
616         rjs_compiler_debughead(co, records, rec);
617         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
618         rvm_codegen_addins(co->cg, rvm_asm(ctx.opcode, R0, R1, R0, 0));
619         rjs_compiler_debugtail(co, records, rec);
620         r_array_removelast(co->coctx);
621         return 0;
622
623 error:
624         r_array_removelast(co->coctx);
625         return -1;
626 }
627
628
629 int rjs_compiler_rh_unaryexpressionop(rjs_compiler_t *co, rarray_t *records, long rec)
630 {
631         rparecord_t *prec;
632         rjs_coctx_operation_t ctx;
633
634         r_memset(&ctx, 0, sizeof(ctx));
635         ctx.base.type = RJS_COCTX_OPERATION;
636         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
637
638         prec = (rparecord_t *)r_array_slot(records, rec);
639         rjs_compiler_debughead(co, records, rec);
640         rjs_compiler_debugtail(co, records, rec);
641         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
642                 goto error;
643         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
644         prec = (rparecord_t *)r_array_slot(records, rec);
645         rjs_compiler_debughead(co, records, rec);
646         rvm_codegen_addins(co->cg, rvm_asm(ctx.opcode, R0, R0, XX, 0));
647         rjs_compiler_debugtail(co, records, rec);
648         r_array_removelast(co->coctx);
649         return 0;
650
651 error:
652         r_array_removelast(co->coctx);
653         return -1;
654 }
655
656
657 int rjs_compiler_rh_unaryexpressiondelete(rjs_compiler_t *co, rarray_t *records, long rec)
658 {
659         rparecord_t *prec;
660         rjs_coctx_operation_t ctx;
661
662         r_memset(&ctx, 0, sizeof(ctx));
663         ctx.base.type = RJS_COCTX_DELETE;
664         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
665
666         prec = (rparecord_t *)r_array_slot(records, rec);
667         rjs_compiler_debughead(co, records, rec);
668         rjs_compiler_debugtail(co, records, rec);
669         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
670                 goto error;
671         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
672         prec = (rparecord_t *)r_array_slot(records, rec);
673         rjs_compiler_debughead(co, records, rec);
674         rjs_compiler_debugtail(co, records, rec);
675         r_array_removelast(co->coctx);
676         return 0;
677
678 error:
679         r_array_removelast(co->coctx);
680         return -1;
681 }
682
683
684 int rjs_compiler_rh_assignmentexpressionop(rjs_compiler_t *co, rarray_t *records, long rec)
685 {
686         rparecord_t *prec;
687         rjs_coctx_operation_t ctx;
688
689         r_memset(&ctx, 0, sizeof(ctx));
690         ctx.base.type = RJS_COCTX_OPERATION;
691         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
692
693         prec = (rparecord_t *)r_array_slot(records, rec);
694         rjs_compiler_debughead(co, records, rec);
695         rjs_compiler_debugtail(co, records, rec);
696         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
697                 goto error;
698         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
699         prec = (rparecord_t *)r_array_slot(records, rec);
700         rjs_compiler_debughead(co, records, rec);
701         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
702         if (ctx.opcode != RVM_NOP) {
703                 rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R2, R1, XX, 0));
704                 rvm_codegen_addins(co->cg, rvm_asm(ctx.opcode, R0, R2, R0, 0));
705         }
706         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
707         rjs_compiler_debugtail(co, records, rec);
708         r_array_removelast(co->coctx);
709         return 0;
710 error:
711         r_array_removelast(co->coctx);
712         return -1;
713 }
714
715
716 int rjs_compiler_rh_newarrayexpression(rjs_compiler_t *co, rarray_t *records, long rec)
717 {
718         rparecord_t *prec;
719         prec = (rparecord_t *)r_array_slot(records, rec);
720         rjs_compiler_debughead(co, records, rec);
721         rjs_compiler_debugtail(co, records, rec);
722         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
723                 return -1;
724         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
725         prec = (rparecord_t *)r_array_slot(records, rec);
726         rjs_compiler_debughead(co, records, rec);
727         rvm_codegen_addins(co->cg, rvm_asm(RVM_MAPALLOC, R0, DA, XX, 0));
728         rjs_compiler_debugtail(co, records, rec);
729         return 0;
730 }
731
732
733 int rjs_compiler_rh_memberexpressiondotop(rjs_compiler_t *co, rarray_t *records, long rec)
734 {
735         rjs_coctx_t *ctx = rjs_compiler_gettopctx(co);
736         rparecord_t *prec;
737
738         prec = (rparecord_t *)r_array_slot(records, rec);
739         rjs_compiler_debughead(co, records, rec);
740         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R0, XX, 0));    // Supposedly an Array
741         rjs_compiler_debugtail(co, records, rec);
742         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
743                 return -1;
744         if (ctx && ctx->type == RJS_COCTX_FUNCTIONCALL)
745                 ((rjs_coctx_functioncall_t *)ctx)->setthis = 1;
746         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
747         prec = (rparecord_t *)r_array_slot(records, rec);
748         rjs_compiler_debughead(co, records, rec);
749         if (rjs_compiler_record_parentuid(co, records, rec) == UID_LEFTHANDSIDEEXPRESSIONADDR && rjs_compiler_record_lastofkind(co, records, rec)) {
750                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MAPLKUPADD, R0, R1, R2, 0));     // Get the offset of the element at offset R0
751                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MAPADDR, R0, R1, R0, 0));        // Get the address of the element at offset R0
752
753         } else {
754                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MAPLKUP, R0, R1, R2, 0));        // Get the offset of the element at offset R0
755                 if (ctx && ctx->type == RJS_COCTX_DELETE)
756                         rvm_codegen_addins(co->cg, rvm_asm(RVM_MAPDEL, R0, R1, R0, 0));         // Get the result of deletion in R0
757                 else
758                         rvm_codegen_addins(co->cg, rvm_asm(RVM_MAPLDR, R0, R1, R0, 0));         // Get the value of the element at offset R0
759         }
760         rjs_compiler_debugtail(co, records, rec);
761         return 0;
762 }
763
764
765 int rjs_compiler_rh_memberexpressionindexop(rjs_compiler_t *co, rarray_t *records, long rec)
766 {
767         rjs_coctx_t *ctx = rjs_compiler_gettopctx(co);
768         rparecord_t *prec;
769         prec = (rparecord_t *)r_array_slot(records, rec);
770         rjs_compiler_debughead(co, records, rec);
771         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));   // Supposedly an Array
772         rjs_compiler_debugtail(co, records, rec);
773
774         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
775                 return -1;
776         if (ctx && ctx->type == RJS_COCTX_FUNCTIONCALL)
777                 ((rjs_coctx_functioncall_t *)ctx)->setthis = 1;
778         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
779         prec = (rparecord_t *)r_array_slot(records, rec);
780         rjs_compiler_debughead(co, records, rec);
781         if (rjs_compiler_record_parentuid(co, records, rec) == UID_LEFTHANDSIDEEXPRESSIONADDR && rjs_compiler_record_lastofkind(co, records, rec)) {
782                 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));    // Supposedly an Array
783                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MAPLKUPADD, R0, R1, R0, 0));     // R1 Array
784                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MAPADDR, R0, R1, R0, 0));        // Get the address of the element at offset R0
785
786         } else {
787                 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));    // Supposedly an Array
788                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MAPLKUP, R0, R1, R0, 0));        // R1 Array
789                 if (ctx && ctx->type == RJS_COCTX_DELETE)
790                         rvm_codegen_addins(co->cg, rvm_asm(RVM_MAPDEL, R0, R1, R0, 0));         // Get the result of deletion in R0
791                 else
792                         rvm_codegen_addins(co->cg, rvm_asm(RVM_MAPLDR, R0, R1, R0, 0));         // Get the value of the element at offset R0
793         }
794         rjs_compiler_debugtail(co, records, rec);
795         return 0;
796 }
797
798
799 int rjs_compiler_rh_functiondeclaration(rjs_compiler_t *co, rarray_t *records, long rec)
800 {
801         rjs_coctx_function_t ctx;
802         rparecord_t *prec;
803         long start, execidx, endidx, allocsidx;
804
805         r_memset(&ctx, 0, sizeof(ctx));
806         ctx.base.type = RJS_COCTX_FUNCTION;
807
808         prec = (rparecord_t *)r_array_slot(records, rec);
809         rjs_compiler_debughead(co, records, rec);
810         start = rvm_codegen_getcodesize(co->cg);
811         endidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
812         execidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
813         allocsidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
814         if (rpa_record_getruleuid(records, rpa_recordtree_firstchild(records, rec, RPA_RECORD_START)) == UID_FUNCTIONNAME) {
815                 if (rjs_compiler_record2identifer(co, records, rpa_recordtree_firstchild(records, rec, RPA_RECORD_START)) < 0)
816                         goto error;
817                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R0, XX, 0));
818         }
819         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_JUMP, execidx, rvm_asm(RVM_MOV, R0, DA, XX, 0));
820         rvm_codegen_addins(co->cg, rvm_asm(RVM_SETTYPE, R0, DA, XX, RVM_DTYPE_FUNCTION));
821         if (rpa_record_getruleuid(records, rpa_recordtree_firstchild(records, rec, RPA_RECORD_START)) == UID_FUNCTIONNAME) {
822                 rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
823         }
824         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, endidx, rvm_asm(RVM_B, DA, XX, XX, 0));
825         rvm_codegen_redefinelabel_default(co->cg, execidx);
826         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_DEFAULT, allocsidx, rvm_asm(RVM_ADD, SP, FP, DA, 0));
827
828         rjs_compiler_debugtail(co, records, rec);
829
830         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
831         rvm_scope_push(co->scope);
832         if (rjs_compiler_playchildrecords(co, records, rec) < 0) {
833                 rvm_scope_pop(co->scope);
834                 goto error;
835         }
836         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
837         prec = (rparecord_t *)r_array_slot(records, rec);
838         rjs_compiler_debughead(co, records, rec);
839         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
840         rvm_codegen_redefinelabel_default(co->cg, endidx);
841         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0xffffffff));
842         rvm_codegen_redefinepointer(co->cg, allocsidx, (rpointer)ctx.stackallocs);
843         rjs_compiler_debugtail(co, records, rec);
844
845         co->cg->userdata = RJS_COMPILER_CODEGENKEEP;
846         rvm_scope_pop(co->scope);
847         r_array_removelast(co->coctx);
848         return 0;
849
850 error:
851         r_array_removelast(co->coctx);
852         return -1;
853 }
854
855
856 int rjs_compiler_rh_functionparameter(rjs_compiler_t *co, rarray_t *records, long rec)
857 {
858         rjs_coctx_t *ctx = NULL;
859         rjs_coctx_function_t *functx = NULL;
860         rparecord_t *prec;
861         rvm_varmap_t *v;
862
863         prec = (rparecord_t *)r_array_slot(records, rec);
864         rjs_compiler_debughead(co, records, rec);
865         /*
866          * First lets find out if we are within a function definition or
867          * this is a global variable.
868          */
869         ctx = rjs_compiler_getctx(co, RJS_COCTX_FUNCTION);
870         if (!ctx) {
871                 rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTION, prec);
872                 return -1;
873         }
874         R_ASSERT(ctx);
875         functx = (rjs_coctx_function_t *)ctx;
876         rjs_compiler_debugtail(co, records, rec);
877
878         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
879                 return -1;
880
881         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
882         prec = (rparecord_t *)r_array_slot(records, rec);
883         rjs_compiler_debughead(co, records, rec);
884         v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
885
886         /*
887          * TBD: Temporary here
888          */
889         if (v) {
890                 r_printf("ERROR: Identifier already defined: %s\n", rjs_compiler_record2str(co, records, rec));
891                 return -1;
892         }
893
894         functx->stackallocs += 1;
895         rvm_scope_addoffset(co->scope, prec->input, prec->inputsiz, functx->stackallocs);
896
897         rjs_compiler_debugtail(co, records, rec);
898         return 0;
899 }
900
901
902 int rjs_compiler_rh_functioncall(rjs_compiler_t *co, rarray_t *records, long rec)
903 {
904         rparecord_t *prec;
905         rjs_coctx_functioncall_t ctx;
906
907         r_memset(&ctx, 0, sizeof(ctx));
908         ctx.base.type = RJS_COCTX_FUNCTIONCALL;
909         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
910
911         prec = (rparecord_t *)r_array_slot(records, rec);
912         rjs_compiler_debughead(co, records, rec);
913         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(TP)|BIT(FP)|BIT(SP)|BIT(LR)));
914         rjs_compiler_debugtail(co, records, rec);
915
916         /*
917          * Important: Function call has two children FunctionCallName, Arguments
918          * We evaluate them in reverse order, first we evaluate the Arguments and push them on the
919          * stack, than we evaluate the FunctionCallName -> R0. When we make the call we assume the
920          * result of the FunctionCallName will be in R0.
921          */
922         if (rjs_compiler_playreversechildrecords(co, records, rec) < 0)
923                 goto error;
924
925         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
926         prec = (rparecord_t *)r_array_slot(records, rec);
927         rjs_compiler_debughead(co, records, rec);
928         if (ctx.setthis)
929                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, TP, R1, XX, 0));
930         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUB, FP, SP, DA, ctx.arguments));
931         rvm_codegen_addins(co->cg, rvm_asm(RVM_CALL, R0, XX, XX, 0));
932         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
933         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(TP,LR)));
934         rjs_compiler_debugtail(co, records, rec);
935         r_array_removelast(co->coctx);
936         return 0;
937
938 error:
939         r_array_removelast(co->coctx);
940         return -1;
941 }
942
943
944 int rjs_compiler_rh_argument(rjs_compiler_t *co, rarray_t *records, long rec)
945 {
946         rparecord_t *prec;
947         rjs_coctx_functioncall_t *ctx = (rjs_coctx_functioncall_t *)rjs_compiler_getctx(co, RJS_COCTX_FUNCTIONCALL);
948
949         prec = (rparecord_t *)r_array_slot(records, rec);
950         rjs_compiler_debughead(co, records, rec);
951         if (!ctx) {
952                 rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTIONCALL, prec);
953                 return -1;
954         }
955         R_ASSERT(ctx);
956         rjs_compiler_debugtail(co, records, rec);
957
958         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
959                 return -1;
960
961         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
962         prec = (rparecord_t *)r_array_slot(records, rec);
963         rjs_compiler_debughead(co, records, rec);
964         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
965         ctx->arguments += 1;
966         rjs_compiler_debugtail(co, records, rec);
967         return 0;
968 }
969
970
971 int rjs_compiler_rh_arguments(rjs_compiler_t *co, rarray_t *records, long rec)
972 {
973         rparecord_t *prec;
974         rjs_coctx_functioncall_t *ctx = (rjs_coctx_functioncall_t *)rjs_compiler_getctx(co, RJS_COCTX_FUNCTIONCALL);
975
976         prec = (rparecord_t *)r_array_slot(records, rec);
977         rjs_compiler_debughead(co, records, rec);
978         if (!ctx) {
979                 rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTIONCALL, prec);
980                 return -1;
981         }
982         R_ASSERT(ctx);
983         rjs_compiler_debugtail(co, records, rec);
984
985         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
986                 return -1;
987
988         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
989         prec = (rparecord_t *)r_array_slot(records, rec);
990         rjs_compiler_debughead(co, records, rec);
991         rjs_compiler_debugtail(co, records, rec);
992         return 0;
993 }
994
995
996 int rjs_compiler_rh_returnstatement(rjs_compiler_t *co, rarray_t *records, long rec)
997 {
998         rparecord_t *prec;
999         prec = (rparecord_t *)r_array_slot(records, rec);
1000         rjs_compiler_debughead(co, records, rec);
1001         rjs_compiler_debugtail(co, records, rec);
1002
1003         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1004                 return -1;
1005
1006         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1007         prec = (rparecord_t *)r_array_slot(records, rec);
1008         rjs_compiler_debughead(co, records, rec);
1009         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
1010         rjs_compiler_debugtail(co, records, rec);
1011         return 0;
1012 }
1013
1014
1015 int rjs_compiler_rh_ifstatement(rjs_compiler_t *co, rarray_t *records, long rec)
1016 {
1017         rparecord_t *prec;
1018         rjs_coctx_ifstatement_t ctx;
1019
1020         r_memset(&ctx, 0, sizeof(ctx));
1021         ctx.base.type = RJS_COCTX_IFSTATEMENT;
1022         ctx.start = rvm_codegen_getcodesize(co->cg);
1023         ctx.trueidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1024         ctx.falseidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1025         ctx.endidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1026         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1027         prec = (rparecord_t *)r_array_slot(records, rec);
1028         rjs_compiler_debughead(co, records, rec);
1029         rjs_compiler_debugtail(co, records, rec);
1030         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1031                 goto error;
1032         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1033         prec = (rparecord_t *)r_array_slot(records, rec);
1034         rjs_compiler_debughead(co, records, rec);
1035         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1036         if (!rvm_codegen_validlabel(co->cg, ctx.falseidx))
1037                 rvm_codegen_redefinelabel_default(co->cg, ctx.falseidx);
1038         rjs_compiler_debugtail(co, records, rec);
1039         r_array_removelast(co->coctx);
1040         return 0;
1041
1042 error:
1043         r_array_removelast(co->coctx);
1044         return -1;
1045 }
1046
1047
1048 int rjs_compiler_rh_ifconditionop(rjs_compiler_t *co, rarray_t *records, long rec)
1049 {
1050         rparecord_t *prec;
1051         rjs_coctx_ifstatement_t *ctx = (rjs_coctx_ifstatement_t *)rjs_compiler_getctx(co, RJS_COCTX_IFSTATEMENT);
1052
1053         prec = (rparecord_t *)r_array_slot(records, rec);
1054         rjs_compiler_debughead(co, records, rec);
1055         if (!ctx) {
1056                 rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec);
1057                 return -1;
1058         }
1059         R_ASSERT(ctx);
1060         rjs_compiler_debugtail(co, records, rec);
1061         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1062                 return -1;
1063         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1064         prec = (rparecord_t *)r_array_slot(records, rec);
1065         rjs_compiler_debughead(co, records, rec);
1066         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->falseidx, rvm_asm(RVM_BEQ, DA, XX, XX, 0));
1067         rjs_compiler_debugtail(co, records, rec);
1068         return 0;
1069 }
1070
1071
1072 int rjs_compiler_rh_iftruestatement(rjs_compiler_t *co, rarray_t *records, long rec)
1073 {
1074         rparecord_t *prec;
1075         rjs_coctx_ifstatement_t *ctx = (rjs_coctx_ifstatement_t *)rjs_compiler_getctx(co, RJS_COCTX_IFSTATEMENT);
1076
1077         prec = (rparecord_t *)r_array_slot(records, rec);
1078         rjs_compiler_debughead(co, records, rec);
1079         if (!ctx) {
1080                 rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec);
1081                 return -1;
1082         }
1083         R_ASSERT(ctx);
1084         rjs_compiler_debugtail(co, records, rec);
1085
1086         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1087                 return -1;
1088
1089         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1090         prec = (rparecord_t *)r_array_slot(records, rec);
1091         rjs_compiler_debughead(co, records, rec);
1092         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1093         rjs_compiler_debugtail(co, records, rec);
1094         return 0;
1095 }
1096
1097
1098 int rjs_compiler_rh_iffalsestatement(rjs_compiler_t *co, rarray_t *records, long rec)
1099 {
1100         rparecord_t *prec;
1101         rjs_coctx_ifstatement_t *ctx = (rjs_coctx_ifstatement_t *)rjs_compiler_getctx(co, RJS_COCTX_IFSTATEMENT);
1102
1103         prec = (rparecord_t *)r_array_slot(records, rec);
1104         rjs_compiler_debughead(co, records, rec);
1105         if (!ctx) {
1106                 rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec);
1107                 return -1;
1108         }
1109         R_ASSERT(ctx);
1110         rvm_codegen_redefinelabel_default(co->cg, ctx->falseidx);
1111         rjs_compiler_debugtail(co, records, rec);
1112
1113         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1114                 return -1;
1115
1116         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1117         prec = (rparecord_t *)r_array_slot(records, rec);
1118         rjs_compiler_debughead(co, records, rec);
1119         rjs_compiler_debugtail(co, records, rec);
1120         return 0;
1121 }
1122
1123
1124 int rjs_compiler_rh_iterationfor(rjs_compiler_t *co, rarray_t *records, long rec)
1125 {
1126         long childrec;
1127         rparecord_t *prec;
1128         rjs_coctx_iteration_t ctx;
1129
1130         r_memset(&ctx, 0, sizeof(ctx));
1131         ctx.base.type = RJS_COCTX_ITERATION;
1132         ctx.start = rvm_codegen_getcodesize(co->cg);
1133         ctx.iterationidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1134         ctx.continueidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1135         ctx.endidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1136         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1137         rvm_scope_push(co->scope);
1138         prec = (rparecord_t *)r_array_slot(records, rec);
1139         rjs_compiler_debughead(co, records, rec);
1140         rjs_compiler_debugtail(co, records, rec);
1141         for (childrec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); childrec >= 0; childrec = rpa_recordtree_next(records, childrec, RPA_RECORD_START)) {
1142                 if (rpa_record_getruleuid(records, childrec) == UID_FOREXPRESSIONINIT) {
1143                         if (rjs_compiler_playrecord(co, records, childrec) < 0)
1144                                 goto error;
1145                         break;
1146                 }
1147         }
1148         rvm_codegen_redefinelabel_default(co->cg, ctx.iterationidx);
1149         for (childrec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); childrec >= 0; childrec = rpa_recordtree_next(records, childrec, RPA_RECORD_START)) {
1150                 if (rpa_record_getruleuid(records, childrec) == UID_FOREXPRESSIONCOMPARE) {
1151                         if (rjs_compiler_playrecord(co, records, childrec) < 0)
1152                                 goto error;
1153                         break;
1154                 }
1155         }
1156         for (childrec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); childrec >= 0; childrec = rpa_recordtree_next(records, childrec, RPA_RECORD_START)) {
1157                 if (rpa_record_getruleuid(records, childrec) == UID_FORITERATIONSTATEMENT) {
1158                         if (rjs_compiler_playrecord(co, records, childrec) < 0)
1159                                 goto error;
1160                         break;
1161                 }
1162         }
1163         rvm_codegen_redefinelabel_default(co->cg, ctx.continueidx);
1164         for (childrec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); childrec >= 0; childrec = rpa_recordtree_next(records, childrec, RPA_RECORD_START)) {
1165                 if (rpa_record_getruleuid(records, childrec) == UID_FOREXPRESSIONINCREMENT) {
1166                         if (rjs_compiler_playrecord(co, records, childrec) < 0)
1167                                 goto error;
1168                         break;
1169                 }
1170         }
1171         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1172         prec = (rparecord_t *)r_array_slot(records, rec);
1173         rjs_compiler_debughead(co, records, rec);
1174         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1175         rjs_compiler_debugtail(co, records, rec);
1176         rvm_scope_pop(co->scope);
1177         r_array_removelast(co->coctx);
1178         return 0;
1179
1180 error:
1181         rvm_scope_pop(co->scope);
1182         r_array_removelast(co->coctx);
1183         return -1;
1184 }
1185
1186
1187 int rjs_compiler_rh_iterationforin(rjs_compiler_t *co, rarray_t *records, long rec)
1188 {
1189         rparecord_t *prec;
1190         rjs_coctx_iteration_t ctx;
1191
1192         r_memset(&ctx, 0, sizeof(ctx));
1193         ctx.base.type = RJS_COCTX_ITERATION;
1194         ctx.start = rvm_codegen_getcodesize(co->cg);
1195         ctx.iterationidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1196         ctx.continueidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1197         ctx.endidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1198         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1199         rvm_scope_push(co->scope);
1200         prec = (rparecord_t *)r_array_slot(records, rec);
1201         rjs_compiler_debughead(co, records, rec);
1202         rjs_compiler_debugtail(co, records, rec);
1203
1204         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1205                 goto error;
1206
1207         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1208         prec = (rparecord_t *)r_array_slot(records, rec);
1209         rjs_compiler_debughead(co, records, rec);
1210         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx.iterationidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1211         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1212         rvm_codegen_addins(co->cg, rvm_asml(RVM_SUB, SP, SP, DA, 3));
1213         rjs_compiler_debugtail(co, records, rec);
1214         rvm_scope_pop(co->scope);
1215         r_array_removelast(co->coctx);
1216         return 0;
1217
1218 error:
1219         rvm_scope_pop(co->scope);
1220         r_array_removelast(co->coctx);
1221         return -1;
1222 }
1223
1224
1225 int rjs_compiler_rh_forininit(rjs_compiler_t *co, rarray_t *records, long rec)
1226 {
1227         rjs_coctx_iteration_t *ctx = (rjs_coctx_iteration_t *)rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1228         rparecord_t *prec;
1229         prec = (rparecord_t *)r_array_slot(records, rec);
1230         rjs_compiler_debughead(co, records, rec);
1231         rvm_codegen_addins(co->cg, rvm_asml(RVM_PUSH, DA, XX, XX, -1));
1232         rjs_compiler_debugtail(co, records, rec);
1233
1234         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1235                 goto error;
1236
1237         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1238         prec = (rparecord_t *)r_array_slot(records, rec);
1239         rjs_compiler_debughead(co, records, rec);
1240         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
1241         rvm_codegen_addins(co->cg, rvm_asm(RVM_TYPE, R0, R0, XX, 0));
1242         rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, RVM_DTYPE_JSOBJECT));
1243         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_BNEQ, DA, XX, XX, 0));
1244         rvm_codegen_redefinelabel_default(co->cg, ctx->iterationidx);
1245         rvm_codegen_redefinelabel_default(co->cg, ctx->continueidx);
1246         rvm_codegen_addins(co->cg, rvm_asml(RVM_LDS, R0, SP, DA, -2));
1247         rvm_codegen_addins(co->cg, rvm_asml(RVM_LDS, R1, SP, DA, 0));
1248         rvm_codegen_addins(co->cg, rvm_asml(RVM_LDS, R2, SP, DA, -1));
1249         rvm_codegen_addins(co->cg, rvm_asml(RVM_MAPNEXT, R0, R1, R0, 0));
1250         rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
1251         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
1252         rvm_codegen_addins(co->cg, rvm_asml(RVM_STS, R0, SP, DA, -2));
1253         rvm_codegen_addins(co->cg, rvm_asml(RVM_MAPKEYLDR, R0, R1, R0, 0));
1254         rvm_codegen_addins(co->cg, rvm_asml(RVM_STRR, R0, R2, XX, 0));
1255         rjs_compiler_debugtail(co, records, rec);
1256         return 0;
1257
1258 error:
1259         return -1;
1260 }
1261
1262
1263 int rjs_compiler_rh_iterationwhile(rjs_compiler_t *co, rarray_t *records, long rec)
1264 {
1265         rparecord_t *prec;
1266         rjs_coctx_iteration_t ctx;
1267
1268         r_memset(&ctx, 0, sizeof(ctx));
1269         ctx.base.type = RJS_COCTX_ITERATION;
1270         ctx.start = rvm_codegen_getcodesize(co->cg);
1271         ctx.iterationidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1272         ctx.continueidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1273         ctx.endidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1274         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1275         rvm_scope_push(co->scope);
1276         prec = (rparecord_t *)r_array_slot(records, rec);
1277         rjs_compiler_debughead(co, records, rec);
1278         rjs_compiler_debugtail(co, records, rec);
1279         rvm_codegen_redefinelabel_default(co->cg, ctx.iterationidx);
1280         rvm_codegen_redefinelabel_default(co->cg, ctx.continueidx);
1281         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1282                 goto error;
1283         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1284         prec = (rparecord_t *)r_array_slot(records, rec);
1285         rjs_compiler_debughead(co, records, rec);
1286         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx.iterationidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1287         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1288         rjs_compiler_debugtail(co, records, rec);
1289         rvm_scope_pop(co->scope);
1290         r_array_removelast(co->coctx);
1291         return 0;
1292
1293 error:
1294         rvm_scope_pop(co->scope);
1295         r_array_removelast(co->coctx);
1296         return -1;
1297 }
1298
1299
1300 int rjs_compiler_rh_iterationdo(rjs_compiler_t *co, rarray_t *records, long rec)
1301 {
1302         rparecord_t *prec;
1303         rjs_coctx_iteration_t ctx;
1304
1305         r_memset(&ctx, 0, sizeof(ctx));
1306         ctx.base.type = RJS_COCTX_ITERATION;
1307         ctx.start = rvm_codegen_getcodesize(co->cg);
1308         ctx.iterationidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1309         ctx.continueidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1310         ctx.endidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1311         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1312         rvm_scope_push(co->scope);
1313         prec = (rparecord_t *)r_array_slot(records, rec);
1314         rjs_compiler_debughead(co, records, rec);
1315         rjs_compiler_debugtail(co, records, rec);
1316         rvm_codegen_redefinelabel_default(co->cg, ctx.iterationidx);
1317         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1318                 goto error;
1319         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1320         prec = (rparecord_t *)r_array_slot(records, rec);
1321         rjs_compiler_debughead(co, records, rec);
1322         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx.iterationidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1323         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1324         rjs_compiler_debugtail(co, records, rec);
1325         rvm_scope_pop(co->scope);
1326         r_array_removelast(co->coctx);
1327         return 0;
1328
1329 error:
1330         rvm_scope_pop(co->scope);
1331         r_array_removelast(co->coctx);
1332         return -1;
1333 }
1334
1335
1336 int rjs_compiler_rh_dowhileexpressioncompare(rjs_compiler_t *co, rarray_t *records, long rec)
1337 {
1338         rparecord_t *prec;
1339         rjs_coctx_iteration_t *ctx = (rjs_coctx_iteration_t *)rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1340
1341         prec = (rparecord_t *)r_array_slot(records, rec);
1342         rjs_compiler_debughead(co, records, rec);
1343         if (!ctx) {
1344                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec);
1345                 return -1;
1346         }
1347         R_ASSERT(ctx);
1348         rvm_codegen_redefinelabel_default(co->cg, ctx->continueidx);
1349         rjs_compiler_debugtail(co, records, rec);
1350
1351         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1352                 return -1;
1353
1354         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1355         prec = (rparecord_t *)r_array_slot(records, rec);
1356         rjs_compiler_debughead(co, records, rec);
1357         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_BEQ, DA, XX, XX, 0));
1358         rjs_compiler_debugtail(co, records, rec);
1359         return 0;
1360 }
1361
1362
1363 int rjs_compiler_rh_forexpressioncompare(rjs_compiler_t *co, rarray_t *records, long rec)
1364 {
1365         rparecord_t *prec;
1366         rjs_coctx_iteration_t *ctx = (rjs_coctx_iteration_t *)rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1367
1368         prec = (rparecord_t *)r_array_slot(records, rec);
1369         rjs_compiler_debughead(co, records, rec);
1370         if (!ctx) {
1371                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec);
1372                 return -1;
1373         }
1374         R_ASSERT(ctx);
1375         rjs_compiler_debugtail(co, records, rec);
1376
1377         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1378                 return -1;
1379
1380         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1381         prec = (rparecord_t *)r_array_slot(records, rec);
1382         rjs_compiler_debughead(co, records, rec);
1383         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_BEQ, DA, XX, XX, 0));
1384         rjs_compiler_debugtail(co, records, rec);
1385         return 0;
1386 }
1387
1388
1389 int rjs_compiler_rh_forexpressionincrement(rjs_compiler_t *co, rarray_t *records, long rec)
1390 {
1391         rparecord_t *prec;
1392         rjs_coctx_iteration_t *ctx = (rjs_coctx_iteration_t *)rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1393
1394         prec = (rparecord_t *)r_array_slot(records, rec);
1395         rjs_compiler_debughead(co, records, rec);
1396         if (!ctx) {
1397                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec);
1398                 return -1;
1399         }
1400         R_ASSERT(ctx);
1401         rjs_compiler_debugtail(co, records, rec);
1402
1403         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1404                 return -1;
1405
1406         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1407         prec = (rparecord_t *)r_array_slot(records, rec);
1408         rjs_compiler_debughead(co, records, rec);
1409         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->iterationidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1410         rjs_compiler_debugtail(co, records, rec);
1411         return 0;
1412 }
1413
1414
1415 int rjs_compiler_rh_postfixexpressionop(rjs_compiler_t *co, rarray_t *records, long rec)
1416 {
1417         rparecord_t *prec;
1418         long opcode;
1419         long opcoderec;
1420
1421         if ((opcoderec = rpa_recordtree_lastchild(records, rec, RPA_RECORD_END)) < 0)
1422                 return -1;
1423         opcode = rjs_compiler_record2opcode((rparecord_t *)r_array_slot(records, opcoderec));
1424         prec = (rparecord_t *)r_array_slot(records, rec);
1425         rjs_compiler_debughead(co, records, rec);
1426         rjs_compiler_debugtail(co, records, rec);
1427
1428         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1429                 return -1;
1430
1431         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1432         prec = (rparecord_t *)r_array_slot(records, rec);
1433         rjs_compiler_debughead(co, records, rec);
1434         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
1435         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R1, XX, 0));
1436         rvm_codegen_addins(co->cg, rvm_asm(opcode, R2, R0, DA, 1));
1437         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R2, R1, XX, 0));
1438
1439         rjs_compiler_debugtail(co, records, rec);
1440         return 0;
1441 }
1442
1443
1444 int rjs_compiler_rh_prefixexpressionop(rjs_compiler_t *co, rarray_t *records, long rec)
1445 {
1446         rparecord_t *prec;
1447         long opcode;
1448         long opcoderec;
1449
1450         if ((opcoderec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_END)) < 0)
1451                 return -1;
1452         opcode = rjs_compiler_record2opcode((rparecord_t *)r_array_slot(records, opcoderec));
1453
1454         prec = (rparecord_t *)r_array_slot(records, rec);
1455         rjs_compiler_debughead(co, records, rec);
1456         rjs_compiler_debugtail(co, records, rec);
1457
1458         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1459                 return -1;
1460
1461         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1462         prec = (rparecord_t *)r_array_slot(records, rec);
1463         rjs_compiler_debughead(co, records, rec);
1464         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R0, XX, 0));
1465         rvm_codegen_addins(co->cg, rvm_asm(opcode, R0, R0, DA, 1));
1466         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
1467         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
1468
1469         rjs_compiler_debugtail(co, records, rec);
1470         return 0;
1471 }
1472
1473
1474 int rjs_compiler_rh_newexpressioncall(rjs_compiler_t *co, rarray_t *records, long rec)
1475 {
1476         rparecord_t *prec;
1477         rjs_coctx_functioncall_t ctx;
1478
1479         r_memset(&ctx, 0, sizeof(ctx));
1480         ctx.base.type = RJS_COCTX_FUNCTIONCALL;
1481         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1482
1483         prec = (rparecord_t *)r_array_slot(records, rec);
1484         rjs_compiler_debughead(co, records, rec);
1485         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(TP)|BIT(FP)|BIT(SP)|BIT(LR)));
1486         rjs_compiler_debugtail(co, records, rec);
1487
1488         /*
1489          * Important: Function call has two children FunctionCallName, Arguments
1490          * We evaluate them in reverse order, first we evaluate the Arguments and push them on the
1491          * stack, than we evaluate the FunctionCallName -> R0. When we make the call we assume the
1492          * result of the FunctionCallName will be in R0.
1493          */
1494         if (rjs_compiler_playreversechildrecords(co, records, rec) < 0)
1495                 goto error;
1496
1497         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1498         prec = (rparecord_t *)r_array_slot(records, rec);
1499         rjs_compiler_debughead(co, records, rec);
1500         rvm_codegen_addins(co->cg, rvm_asm(RVM_MAPALLOC, TP, DA, XX, 0));
1501         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUB, FP, SP, DA, ctx.arguments));
1502         rvm_codegen_addins(co->cg, rvm_asm(RVM_CALL, R0, XX, XX, 0));
1503         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
1504         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, TP, XX, 0));
1505         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(TP,LR)));
1506         rjs_compiler_debugtail(co, records, rec);
1507         r_array_removelast(co->coctx);
1508         return 0;
1509
1510 error:
1511         r_array_removelast(co->coctx);
1512         return -1;
1513 }
1514
1515
1516 int rjs_compiler_rh_this(rjs_compiler_t *co, rarray_t *records, long rec)
1517 {
1518         rparecord_t *prec;
1519         prec = (rparecord_t *)r_array_slot(records, rec);
1520         rjs_compiler_debughead(co, records, rec);
1521         rjs_compiler_debugtail(co, records, rec);
1522
1523         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1524                 return -1;
1525
1526         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1527         prec = (rparecord_t *)r_array_slot(records, rec);
1528         rjs_compiler_debughead(co, records, rec);
1529         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, TP, XX, 0));
1530         rjs_compiler_debugtail(co, records, rec);
1531         return 0;
1532 }
1533
1534
1535 int rjs_compiler_rh_binaryoperator(rjs_compiler_t *co, rarray_t *records, long rec)
1536 {
1537         rparecord_t *prec;
1538         rjs_coctx_t *ctx = rjs_compiler_gettopctx(co);
1539
1540         prec = (rparecord_t *)r_array_slot(records, rec);
1541         rjs_compiler_debughead(co, records, rec);
1542         rjs_compiler_debugtail(co, records, rec);
1543
1544         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1545                 return -1;
1546
1547         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1548         prec = (rparecord_t *)r_array_slot(records, rec);
1549         rjs_compiler_debughead(co, records, rec);
1550         if (ctx && ctx->type == RJS_COCTX_OPERATION)
1551                 ((rjs_coctx_operation_t *)ctx)->opcode = rjs_compiler_record2opcode(prec);
1552         rjs_compiler_debugtail(co, records, rec);
1553         return 0;
1554 }
1555
1556
1557 int rjs_compiler_rh_unaryoperator(rjs_compiler_t *co, rarray_t *records, long rec)
1558 {
1559         rparecord_t *prec;
1560         rjs_coctx_t *ctx = rjs_compiler_gettopctx(co);
1561
1562         prec = (rparecord_t *)r_array_slot(records, rec);
1563         rjs_compiler_debughead(co, records, rec);
1564         rjs_compiler_debugtail(co, records, rec);
1565
1566         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1567                 return -1;
1568
1569         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1570         prec = (rparecord_t *)r_array_slot(records, rec);
1571         rjs_compiler_debughead(co, records, rec);
1572         if (ctx && ctx->type == RJS_COCTX_OPERATION)
1573                 ((rjs_coctx_operation_t *)ctx)->opcode = rjs_compiler_record2unaryopcode(prec);
1574         rjs_compiler_debugtail(co, records, rec);
1575         return 0;
1576 }
1577
1578
1579 int rjs_compiler_rh_identifiername(rjs_compiler_t *co, rarray_t *records, long rec)
1580 {
1581         rparecord_t *prec;
1582         prec = (rparecord_t *)r_array_slot(records, rec);
1583         rjs_compiler_debughead(co, records, rec);
1584         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, prec->inputsiz));
1585         rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R2, DA, XX, (void*)prec->input));
1586         rjs_compiler_debugtail(co, records, rec);
1587
1588         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1589                 return -1;
1590
1591         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1592         prec = (rparecord_t *)r_array_slot(records, rec);
1593         rjs_compiler_debughead(co, records, rec);
1594         rjs_compiler_debugtail(co, records, rec);
1595         return 0;
1596 }
1597
1598
1599 int rjs_compiler_rh_continue(rjs_compiler_t *co, rarray_t *records, long rec)
1600 {
1601         rparecord_t *prec;
1602         rjs_coctx_t *ctx;
1603         rjs_coctx_iteration_t *iterctx;
1604
1605         ctx = rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1606         prec = (rparecord_t *)r_array_slot(records, rec);
1607         rjs_compiler_debughead(co, records, rec);
1608         if (!ctx) {
1609                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec);
1610                 return -1;
1611         }
1612         R_ASSERT(ctx);
1613         iterctx = (rjs_coctx_iteration_t *)ctx;
1614         rjs_compiler_debugtail(co, records, rec);
1615
1616         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1617                 return -1;
1618
1619         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1620         prec = (rparecord_t *)r_array_slot(records, rec);
1621         rjs_compiler_debughead(co, records, rec);
1622         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, iterctx->continueidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1623         rjs_compiler_debugtail(co, records, rec);
1624         return 0;
1625 }
1626
1627
1628 int rjs_compiler_rh_break(rjs_compiler_t *co, rarray_t *records, long rec)
1629 {
1630         rparecord_t *prec;
1631         rjs_coctx_t *ctx;
1632         rjs_coctx_iteration_t *iterctx;
1633
1634
1635         ctx = rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1636         prec = (rparecord_t *)r_array_slot(records, rec);
1637         rjs_compiler_debughead(co, records, rec);
1638         if (!ctx) {
1639                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec);
1640                 return -1;
1641         }
1642         R_ASSERT(ctx);
1643         iterctx = (rjs_coctx_iteration_t *)ctx;
1644         rjs_compiler_debugtail(co, records, rec);
1645
1646         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1647                 return -1;
1648
1649         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1650         prec = (rparecord_t *)r_array_slot(records, rec);
1651         rjs_compiler_debughead(co, records, rec);
1652         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, iterctx->endidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1653         rjs_compiler_debugtail(co, records, rec);
1654         return 0;
1655 }
1656
1657
1658 int rjs_compiler_rh_syntaxerror(rjs_compiler_t *co, rarray_t *records, long rec)
1659 {
1660         rparecord_t *prec;
1661         prec = (rparecord_t *)r_array_slot(records, rec);
1662         rjs_compiler_debughead(co, records, rec);
1663         rjs_compiler_debugtail(co, records, rec);
1664
1665         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1666                 return -1;
1667
1668         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1669         prec = (rparecord_t *)r_array_slot(records, rec);
1670         rjs_compiler_debughead(co, records, rec);
1671         rjs_compiler_adderror(co, RJS_ERROR_SYNTAX, prec);
1672         rjs_compiler_debugtail(co, records, rec);
1673         return 0;
1674 }
1675
1676
1677 int rjs_compiler_rh_block(rjs_compiler_t *co, rarray_t *records, long rec)
1678 {
1679         rparecord_t *prec;
1680         prec = (rparecord_t *)r_array_slot(records, rec);
1681         rjs_compiler_debughead(co, records, rec);
1682         rvm_scope_push(co->scope);
1683         rjs_compiler_debugtail(co, records, rec);
1684
1685         if (rjs_compiler_playchildrecords(co, records, rec) < 0) {
1686                 rvm_scope_pop(co->scope);
1687                 return -1;
1688         }
1689
1690         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1691         prec = (rparecord_t *)r_array_slot(records, rec);
1692         rjs_compiler_debughead(co, records, rec);
1693         rvm_scope_pop(co->scope);
1694         rjs_compiler_debugtail(co, records, rec);
1695         return 0;
1696 }
1697
1698
1699 int rjs_compiler_rh_(rjs_compiler_t *co, rarray_t *records, long rec)
1700 {
1701         rparecord_t *prec;
1702         prec = (rparecord_t *)r_array_slot(records, rec);
1703         rjs_compiler_debughead(co, records, rec);
1704         rjs_compiler_debugtail(co, records, rec);
1705
1706         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1707                 return -1;
1708
1709         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1710         prec = (rparecord_t *)r_array_slot(records, rec);
1711         rjs_compiler_debughead(co, records, rec);
1712         rjs_compiler_debugtail(co, records, rec);
1713         return 0;
1714 }
1715
1716
1717 rjs_compiler_t *rjs_compiler_create(rvmcpu_t *cpu)
1718 {
1719         rjs_compiler_t *co = (rjs_compiler_t *) r_zmalloc(sizeof(*co));
1720
1721         co->scope = rvm_scope_create();
1722         co->coctx = r_array_create(sizeof(rjs_coctx_t *));
1723         co->cpu = cpu;
1724         r_memset(co->handlers, 0, sizeof(co->handlers));
1725
1726         co->handlers[UID_PROGRAM] = rjs_compiler_rh_program;
1727         co->handlers[UID_EXPRESSION] = rjs_compiler_rh_expression;
1728         co->handlers[UID_LEFTHANDSIDEEXPRESSION] = rjs_compiler_rh_lefthandsideexpression;
1729         co->handlers[UID_LEFTHANDSIDEEXPRESSIONADDR] = rjs_compiler_rh_lefthandsideexpressionaddr;
1730         co->handlers[UID_DECIMALINTEGERLITERAL] = rjs_compiler_rh_decimalintegerliteral;
1731         co->handlers[UID_DECIMALNONINTEGERLITERAL] = rjs_compiler_rh_decimalnonintegerliteral;
1732         co->handlers[UID_STRINGCHARACTERS] = rjs_compiler_rh_stringcharacters;
1733         co->handlers[UID_STRINGLITERAL] = rjs_compiler_rh_stringliteral;
1734
1735         co->handlers[UID_ADDITIVEEXPRESSIONOP] = rjs_compiler_rh_binaryexpressionop;
1736         co->handlers[UID_MULTIPLICATIVEEXPRESSIONOP] = rjs_compiler_rh_binaryexpressionop;
1737         co->handlers[UID_BITWISEANDOP] = rjs_compiler_rh_binaryexpressionop;
1738         co->handlers[UID_BITWISEXOROP] = rjs_compiler_rh_binaryexpressionop;
1739         co->handlers[UID_BITWISEOROP] = rjs_compiler_rh_binaryexpressionop;
1740         co->handlers[UID_SHIFTEXPRESSIONOP] = rjs_compiler_rh_binaryexpressionop;
1741         co->handlers[UID_EQUALITYEXPRESSIONOP] = rjs_compiler_rh_binaryexpressionop;
1742         co->handlers[UID_RELATIONALEXPRESSIONOP] = rjs_compiler_rh_binaryexpressionop;
1743         co->handlers[UID_LOGICALOROP] = rjs_compiler_rh_binaryexpressionop;
1744         co->handlers[UID_LOGICALANDOP] = rjs_compiler_rh_binaryexpressionop;
1745         co->handlers[UID_VARIABLEALLOCATEANDINIT] = rjs_compiler_rh_varallocinit;
1746         co->handlers[UID_VARIABLEALLOCATE] = rjs_compiler_rh_varalloc;
1747         co->handlers[UID_IDENTIFIER] = rjs_compiler_rh_identifier;
1748         co->handlers[UID_IDENTIFIERNAME] = rjs_compiler_rh_identifiername;
1749         co->handlers[UID_INITIALISER] = rjs_compiler_rh_initializer;
1750         co->handlers[UID_ASSIGNMENTEXPRESSIONOP] = rjs_compiler_rh_assignmentexpressionop;
1751         co->handlers[UID_NEWARRAYEXPRESSION] = rjs_compiler_rh_newarrayexpression;
1752         co->handlers[UID_MEMBEREXPRESSIONDOTOP] = rjs_compiler_rh_memberexpressiondotop;
1753         co->handlers[UID_MEMBEREXPRESSIONINDEXOP] = rjs_compiler_rh_memberexpressionindexop;
1754         co->handlers[UID_FUNCTIONDECLARATION] = rjs_compiler_rh_functiondeclaration;
1755         co->handlers[UID_FUNCTIONEXPRESSION] = rjs_compiler_rh_functiondeclaration;
1756         co->handlers[UID_FUNCTIONPARAMETER] = rjs_compiler_rh_functionparameter;
1757         co->handlers[UID_FUNCTIONCALL] = rjs_compiler_rh_functioncall;
1758         co->handlers[UID_ARGUMENT] = rjs_compiler_rh_argument;
1759         co->handlers[UID_ARGUMENTS] = rjs_compiler_rh_arguments;
1760         co->handlers[UID_RETURNSTATEMENT] = rjs_compiler_rh_returnstatement;
1761         co->handlers[UID_IFSTATEMENT] = rjs_compiler_rh_ifstatement;
1762         co->handlers[UID_IFCONDITIONOP] = rjs_compiler_rh_ifconditionop;
1763         co->handlers[UID_IFTRUESTATEMENT] = rjs_compiler_rh_iftruestatement;
1764         co->handlers[UID_IFFALSESTATEMENT] = rjs_compiler_rh_iffalsestatement;
1765         co->handlers[UID_ITERATIONDO] = rjs_compiler_rh_iterationdo;
1766         co->handlers[UID_ITERATIONWHILE] = rjs_compiler_rh_iterationwhile;
1767         co->handlers[UID_ITERATIONFOR] = rjs_compiler_rh_iterationfor;
1768         co->handlers[UID_ITERATIONFORIN] = rjs_compiler_rh_iterationforin;
1769         co->handlers[UID_FORININIT] = rjs_compiler_rh_forininit;
1770         co->handlers[UID_DOWHILEEXPRESSIONCOMPARE] = rjs_compiler_rh_dowhileexpressioncompare;
1771         co->handlers[UID_WHILEEXPRESSIONCOMPARE] = rjs_compiler_rh_forexpressioncompare;
1772         co->handlers[UID_FOREXPRESSIONCOMPARE] = rjs_compiler_rh_forexpressioncompare;
1773         co->handlers[UID_FOREXPRESSIONINCREMENT] = rjs_compiler_rh_forexpressionincrement;
1774         co->handlers[UID_POSTFIXEXPRESSIONOP] = rjs_compiler_rh_postfixexpressionop;
1775         co->handlers[UID_PREFIXEXPRESSIONOP] = rjs_compiler_rh_prefixexpressionop;
1776         co->handlers[UID_THIS] = rjs_compiler_rh_this;
1777         co->handlers[UID_NEWEXPRESSIONCALL] = rjs_compiler_rh_newexpressioncall;
1778         co->handlers[UID_UNARYEXPRESSIONOP] = rjs_compiler_rh_unaryexpressionop;
1779         co->handlers[UID_UNARYEXPRESSIONDELETE] = rjs_compiler_rh_unaryexpressiondelete;
1780         co->handlers[UID_BINARYOPERATOR] = rjs_compiler_rh_binaryoperator;
1781         co->handlers[UID_UNARYOPERATOR] = rjs_compiler_rh_unaryoperator;
1782         co->handlers[UID_BREAKSTATEMENT] = rjs_compiler_rh_break;
1783         co->handlers[UID_CONTINUESTATEMENT] = rjs_compiler_rh_continue;
1784         co->handlers[UID_SYNTAXERROR] = rjs_compiler_rh_syntaxerror;
1785         co->handlers[UID_BLOCK] = rjs_compiler_rh_block;
1786
1787         return co;
1788 }
1789
1790
1791 void rjs_compiler_destroy(rjs_compiler_t *co)
1792 {
1793         if (co) {
1794                 rvm_scope_destroy(co->scope);
1795                 r_array_destroy(co->coctx);
1796                 r_free(co->temp);
1797                 co->cpu = NULL;
1798                 r_free(co);
1799         }
1800 }
1801
1802
1803 static int rjs_compiler_rh_default(rjs_compiler_t *co, rarray_t *records, long rec)
1804 {
1805         rparecord_t *prec;
1806
1807         prec = (rparecord_t *)r_array_slot(records, rec);
1808         rjs_compiler_debughead(co, records, rec);
1809         rjs_compiler_debugtail(co, records, rec);
1810
1811         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1812                 return -1;
1813
1814         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1815         prec = (rparecord_t *)r_array_slot(records, rec);
1816         rjs_compiler_debughead(co, records, rec);
1817         rjs_compiler_debugtail(co, records, rec);
1818
1819         return 0;
1820 }
1821
1822
1823 static int rjs_compiler_playchildrecords(rjs_compiler_t *co, rarray_t *records, long rec)
1824 {
1825         long child;
1826
1827         for (child = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); child >= 0; child = rpa_recordtree_next(records, child, RPA_RECORD_START)) {
1828                 if (rjs_compiler_playrecord(co, records, child) < 0)
1829                         return -1;
1830         }
1831
1832         return 0;
1833 }
1834
1835
1836 int rjs_compiler_playreversechildrecords(rjs_compiler_t *co, rarray_t *records, long rec)
1837 {
1838         long child;
1839
1840         for (child = rpa_recordtree_lastchild(records, rec, RPA_RECORD_START); child >= 0; child = rpa_recordtree_prev(records, child, RPA_RECORD_START)) {
1841                 if (rjs_compiler_playrecord(co, records, child) < 0)
1842                         return -1;
1843         }
1844
1845         return 0;
1846 }
1847
1848
1849 static int rjs_compiler_playrecord(rjs_compiler_t *co, rarray_t *records, long rec)
1850 {
1851         rparecord_t *prec;
1852         prec = (rparecord_t *)r_array_slot(records, rec);
1853         if (prec->ruleuid >= 0 && prec->ruleuid < RJS_COMPILER_NHANDLERS && co->handlers[prec->ruleuid]) {
1854                 return co->handlers[prec->ruleuid](co, records, rec);
1855         }
1856         return rjs_compiler_rh_default(co, records, rec);
1857 }
1858
1859
1860 int rjs_compiler_compile(rjs_compiler_t *co, const char *script, unsigned long scriptsize, rarray_t *records, rvm_codegen_t *cg, rjs_error_t *error)
1861 {
1862         long i;
1863         rvm_codelabel_t *labelerr;
1864
1865         if (!co || !records || !cg || r_array_empty(records)) {
1866                 /*
1867                  * TBD
1868                  */
1869                 return -1;
1870         }
1871         co->cg = cg;
1872         co->error = error;
1873         co->script = script;
1874         co->scriptsize = scriptsize;
1875
1876         for (i = 0; i >= 0; i = rpa_recordtree_next(records, i, RPA_RECORD_START)) {
1877                 if (rjs_compiler_playrecord(co, records, i) < 0)
1878                         /*
1879                          * TBD
1880                          */
1881                         return -1;
1882         }
1883
1884         if (rvm_codegen_relocate(co->cg, &labelerr) < 0) {
1885                 /*
1886                  * TBD
1887                  */
1888                 return -1;
1889         }
1890
1891         return 0;
1892 }