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