RPA Toolkit
RJS prop access changes... continued.
[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_PROPSET, R0, R1, R2, 0));        // R1 Array
804
805 #if 0
806                 rvm_codegen_addins(co->cg, rvm_asm(RJS_PROPLKUPADD, R0, R1, R2, 0));    // Get the offset of the element at offset R0
807                 rvm_codegen_addins(co->cg, rvm_asm(RJS_PROPADDR, R0, R1, R0, 0));       // Get the address of the element at offset R0
808 #endif
809
810         } else {
811                 rvm_codegen_addins(co->cg, rvm_asm(RJS_PROPGET, R0, R1, R2, 0));        // Get the property
812
813 #if 0
814                 rvm_codegen_addins(co->cg, rvm_asm(RJS_PROPLKUP, R0, R1, R2, 0));       // Get the offset of the element at offset R0
815                 if (ctx && ctx->type == RJS_COCTX_DELETE)
816                         rvm_codegen_addins(co->cg, rvm_asm(RJS_PROPDEL, R0, R1, R0, 0));                // Get the result of deletion in R0
817                 else
818                         rvm_codegen_addins(co->cg, rvm_asm(RJS_PROPLDR, R0, R1, R0, 0));                // Get the value of the element at offset R0
819 #endif
820         }
821         rjs_compiler_debugtail(co, records, rec);
822         return 0;
823 }
824
825
826 int rjs_compiler_rh_memberexpressionindexop(rjs_compiler_t *co, rarray_t *records, long rec)
827 {
828         rjs_coctx_t *ctx = rjs_compiler_gettopctx(co);
829         rparecord_t *prec;
830         prec = (rparecord_t *)r_array_slot(records, rec);
831         rjs_compiler_debughead(co, records, rec);
832         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));   // Supposedly an Array
833         rjs_compiler_debugtail(co, records, rec);
834
835         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
836                 return -1;
837         if (ctx && ctx->type == RJS_COCTX_FUNCTIONCALL)
838                 ((rjs_coctx_functioncall_t *)ctx)->setthis = 1;
839         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
840         prec = (rparecord_t *)r_array_slot(records, rec);
841         rjs_compiler_debughead(co, records, rec);
842         if (rjs_compiler_record_parentuid(co, records, rec) == UID_LEFTHANDSIDEEXPRESSIONADDR && rjs_compiler_record_lastofkind(co, records, rec)) {
843                 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));    // Supposedly an Array
844 #if 0
845                 rvm_codegen_addins(co->cg, rvm_asm(RJS_PROPLKUPADD, R0, R1, R0, 0));    // R1 Array
846                 rvm_codegen_addins(co->cg, rvm_asm(RJS_PROPADDR, R0, R1, R0, 0));       // Get the address of the element at offset R0
847 #endif
848                 rvm_codegen_addins(co->cg, rvm_asm(RJS_PROPSET, R0, R1, R0, 0));        // R1 Array
849
850         } else {
851                 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));    // Supposedly an Array
852                 rvm_codegen_addins(co->cg, rvm_asm(RJS_PROPGET, R0, R1, R0, 0));        // R1 Array
853 #if 0
854                 rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));    // Supposedly an Array
855                 rvm_codegen_addins(co->cg, rvm_asm(RJS_PROPLKUP, R0, R1, R0, 0));       // R1 Array
856                 if (ctx && ctx->type == RJS_COCTX_DELETE)
857                         rvm_codegen_addins(co->cg, rvm_asm(RJS_PROPDEL, R0, R1, R0, 0));                // Get the result of deletion in R0
858                 else
859                         rvm_codegen_addins(co->cg, rvm_asm(RJS_PROPLDR, R0, R1, R0, 0));                // Get the value of the element at offset R0
860 #endif
861         }
862         rjs_compiler_debugtail(co, records, rec);
863         return 0;
864 }
865
866
867 int rjs_compiler_rh_functiondeclaration(rjs_compiler_t *co, rarray_t *records, long rec)
868 {
869         rjs_coctx_function_t ctx;
870         rparecord_t *prec;
871         long start, execidx, endidx, allocsidx;
872
873         r_memset(&ctx, 0, sizeof(ctx));
874         ctx.base.type = RJS_COCTX_FUNCTION;
875
876         prec = (rparecord_t *)r_array_slot(records, rec);
877         rjs_compiler_debughead(co, records, rec);
878         start = rvm_codegen_getcodesize(co->cg);
879         endidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
880         execidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
881         allocsidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
882         if (rpa_record_getruleuid(records, rpa_recordtree_firstchild(records, rec, RPA_RECORD_START)) == UID_FUNCTIONNAME) {
883                 if (rjs_compiler_record2identifer(co, records, rpa_recordtree_firstchild(records, rec, RPA_RECORD_START)) < 0)
884                         goto error;
885                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R0, XX, 0));
886         }
887         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_JUMP, execidx, rvm_asm(RVM_MOV, R0, DA, XX, 0));
888         rvm_codegen_addins(co->cg, rvm_asm(RVM_SETTYPE, R0, DA, XX, RVM_DTYPE_FUNCTION));
889         if (rpa_record_getruleuid(records, rpa_recordtree_firstchild(records, rec, RPA_RECORD_START)) == UID_FUNCTIONNAME) {
890                 rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
891         }
892         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, endidx, rvm_asm(RVM_B, DA, XX, XX, 0));
893         rvm_codegen_redefinelabel_default(co->cg, execidx);
894         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_DEFAULT, allocsidx, rvm_asm(RVM_ADD, SP, FP, DA, 0));
895
896         rjs_compiler_debugtail(co, records, rec);
897
898         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
899         rvm_scope_push(co->scope);
900         if (rjs_compiler_playchildrecords(co, records, rec) < 0) {
901                 rvm_scope_pop(co->scope);
902                 goto error;
903         }
904         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
905         prec = (rparecord_t *)r_array_slot(records, rec);
906         rjs_compiler_debughead(co, records, rec);
907         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
908         rvm_codegen_redefinelabel_default(co->cg, endidx);
909         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0xffffffff));
910         rvm_codegen_redefinepointer(co->cg, allocsidx, (rpointer)ctx.stackallocs);
911         rjs_compiler_debugtail(co, records, rec);
912
913         co->cg->userdata = RJS_COMPILER_CODEGENKEEP;
914         rvm_scope_pop(co->scope);
915         r_array_removelast(co->coctx);
916         return 0;
917
918 error:
919         r_array_removelast(co->coctx);
920         return -1;
921 }
922
923
924 int rjs_compiler_rh_functionparameter(rjs_compiler_t *co, rarray_t *records, long rec)
925 {
926         rjs_coctx_t *ctx = NULL;
927         rjs_coctx_function_t *functx = NULL;
928         rparecord_t *prec;
929         rvm_varmap_t *v;
930
931         prec = (rparecord_t *)r_array_slot(records, rec);
932         rjs_compiler_debughead(co, records, rec);
933         /*
934          * First lets find out if we are within a function definition or
935          * this is a global variable.
936          */
937         ctx = rjs_compiler_getctx(co, RJS_COCTX_FUNCTION);
938         if (!ctx) {
939                 rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTION, prec);
940                 return -1;
941         }
942         R_ASSERT(ctx);
943         functx = (rjs_coctx_function_t *)ctx;
944         rjs_compiler_debugtail(co, records, rec);
945
946         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
947                 return -1;
948
949         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
950         prec = (rparecord_t *)r_array_slot(records, rec);
951         rjs_compiler_debughead(co, records, rec);
952         v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
953
954         /*
955          * TBD: Temporary here
956          */
957         if (v) {
958                 r_printf("ERROR: Identifier already defined: %s\n", rjs_compiler_record2str(co, records, rec));
959                 return -1;
960         }
961
962         functx->stackallocs += 1;
963         rvm_scope_addoffset(co->scope, prec->input, prec->inputsiz, functx->stackallocs);
964
965         rjs_compiler_debugtail(co, records, rec);
966         return 0;
967 }
968
969
970 int rjs_compiler_rh_functioncall(rjs_compiler_t *co, rarray_t *records, long rec)
971 {
972         rparecord_t *prec;
973         rjs_coctx_functioncall_t ctx;
974
975         r_memset(&ctx, 0, sizeof(ctx));
976         ctx.base.type = RJS_COCTX_FUNCTIONCALL;
977         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
978
979         prec = (rparecord_t *)r_array_slot(records, rec);
980         rjs_compiler_debughead(co, records, rec);
981         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(TP)|BIT(FP)|BIT(SP)|BIT(LR)));
982         rjs_compiler_debugtail(co, records, rec);
983
984         /*
985          * Important: Function call has two children FunctionCallName, Arguments
986          * We evaluate them in reverse order, first we evaluate the Arguments and push them on the
987          * stack, than we evaluate the FunctionCallName -> R0. When we make the call we assume the
988          * result of the FunctionCallName will be in R0.
989          */
990         if (rjs_compiler_playreversechildrecords(co, records, rec) < 0)
991                 goto error;
992
993         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
994         prec = (rparecord_t *)r_array_slot(records, rec);
995         rjs_compiler_debughead(co, records, rec);
996         if (ctx.setthis)
997                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, TP, R1, XX, 0));
998         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUB, FP, SP, DA, ctx.arguments));
999         rvm_codegen_addins(co->cg, rvm_asm(RVM_CALL, R0, XX, XX, 0));
1000         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
1001         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(TP,LR)));
1002         rjs_compiler_debugtail(co, records, rec);
1003         r_array_removelast(co->coctx);
1004         return 0;
1005
1006 error:
1007         r_array_removelast(co->coctx);
1008         return -1;
1009 }
1010
1011
1012 int rjs_compiler_rh_argument(rjs_compiler_t *co, rarray_t *records, long rec)
1013 {
1014         rparecord_t *prec;
1015         rjs_coctx_functioncall_t *ctx = (rjs_coctx_functioncall_t *)rjs_compiler_getctx(co, RJS_COCTX_FUNCTIONCALL);
1016
1017         prec = (rparecord_t *)r_array_slot(records, rec);
1018         rjs_compiler_debughead(co, records, rec);
1019         if (!ctx) {
1020                 rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTIONCALL, prec);
1021                 return -1;
1022         }
1023         R_ASSERT(ctx);
1024         rjs_compiler_debugtail(co, records, rec);
1025
1026         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1027                 return -1;
1028
1029         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1030         prec = (rparecord_t *)r_array_slot(records, rec);
1031         rjs_compiler_debughead(co, records, rec);
1032         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
1033         ctx->arguments += 1;
1034         rjs_compiler_debugtail(co, records, rec);
1035         return 0;
1036 }
1037
1038
1039 int rjs_compiler_rh_arguments(rjs_compiler_t *co, rarray_t *records, long rec)
1040 {
1041         rparecord_t *prec;
1042         rjs_coctx_functioncall_t *ctx = (rjs_coctx_functioncall_t *)rjs_compiler_getctx(co, RJS_COCTX_FUNCTIONCALL);
1043
1044         prec = (rparecord_t *)r_array_slot(records, rec);
1045         rjs_compiler_debughead(co, records, rec);
1046         if (!ctx) {
1047                 rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTIONCALL, prec);
1048                 return -1;
1049         }
1050         R_ASSERT(ctx);
1051         rjs_compiler_debugtail(co, records, rec);
1052
1053         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1054                 return -1;
1055
1056         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1057         prec = (rparecord_t *)r_array_slot(records, rec);
1058         rjs_compiler_debughead(co, records, rec);
1059         rjs_compiler_debugtail(co, records, rec);
1060         return 0;
1061 }
1062
1063
1064 int rjs_compiler_rh_returnstatement(rjs_compiler_t *co, rarray_t *records, long rec)
1065 {
1066         rparecord_t *prec;
1067         prec = (rparecord_t *)r_array_slot(records, rec);
1068         rjs_compiler_debughead(co, records, rec);
1069         rjs_compiler_debugtail(co, records, rec);
1070
1071         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1072                 return -1;
1073
1074         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1075         prec = (rparecord_t *)r_array_slot(records, rec);
1076         rjs_compiler_debughead(co, records, rec);
1077         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
1078         rjs_compiler_debugtail(co, records, rec);
1079         return 0;
1080 }
1081
1082
1083 int rjs_compiler_rh_ifstatement(rjs_compiler_t *co, rarray_t *records, long rec)
1084 {
1085         rparecord_t *prec;
1086         rjs_coctx_ifstatement_t ctx;
1087
1088         r_memset(&ctx, 0, sizeof(ctx));
1089         ctx.base.type = RJS_COCTX_IFSTATEMENT;
1090         ctx.start = rvm_codegen_getcodesize(co->cg);
1091         ctx.trueidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1092         ctx.falseidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1093         ctx.endidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1094         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1095         prec = (rparecord_t *)r_array_slot(records, rec);
1096         rjs_compiler_debughead(co, records, rec);
1097         rjs_compiler_debugtail(co, records, rec);
1098         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1099                 goto error;
1100         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1101         prec = (rparecord_t *)r_array_slot(records, rec);
1102         rjs_compiler_debughead(co, records, rec);
1103         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1104         if (!rvm_codegen_validlabel(co->cg, ctx.falseidx))
1105                 rvm_codegen_redefinelabel_default(co->cg, ctx.falseidx);
1106         rjs_compiler_debugtail(co, records, rec);
1107         r_array_removelast(co->coctx);
1108         return 0;
1109
1110 error:
1111         r_array_removelast(co->coctx);
1112         return -1;
1113 }
1114
1115
1116 int rjs_compiler_rh_ifconditionop(rjs_compiler_t *co, rarray_t *records, long rec)
1117 {
1118         rparecord_t *prec;
1119         rjs_coctx_ifstatement_t *ctx = (rjs_coctx_ifstatement_t *)rjs_compiler_getctx(co, RJS_COCTX_IFSTATEMENT);
1120
1121         prec = (rparecord_t *)r_array_slot(records, rec);
1122         rjs_compiler_debughead(co, records, rec);
1123         if (!ctx) {
1124                 rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec);
1125                 return -1;
1126         }
1127         R_ASSERT(ctx);
1128         rjs_compiler_debugtail(co, records, rec);
1129         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1130                 return -1;
1131         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1132         prec = (rparecord_t *)r_array_slot(records, rec);
1133         rjs_compiler_debughead(co, records, rec);
1134         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->falseidx, rvm_asm(RVM_BEQ, DA, XX, XX, 0));
1135         rjs_compiler_debugtail(co, records, rec);
1136         return 0;
1137 }
1138
1139
1140 int rjs_compiler_rh_iftruestatement(rjs_compiler_t *co, rarray_t *records, long rec)
1141 {
1142         rparecord_t *prec;
1143         rjs_coctx_ifstatement_t *ctx = (rjs_coctx_ifstatement_t *)rjs_compiler_getctx(co, RJS_COCTX_IFSTATEMENT);
1144
1145         prec = (rparecord_t *)r_array_slot(records, rec);
1146         rjs_compiler_debughead(co, records, rec);
1147         if (!ctx) {
1148                 rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec);
1149                 return -1;
1150         }
1151         R_ASSERT(ctx);
1152         rjs_compiler_debugtail(co, records, rec);
1153
1154         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1155                 return -1;
1156
1157         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1158         prec = (rparecord_t *)r_array_slot(records, rec);
1159         rjs_compiler_debughead(co, records, rec);
1160         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1161         rjs_compiler_debugtail(co, records, rec);
1162         return 0;
1163 }
1164
1165
1166 int rjs_compiler_rh_iffalsestatement(rjs_compiler_t *co, rarray_t *records, long rec)
1167 {
1168         rparecord_t *prec;
1169         rjs_coctx_ifstatement_t *ctx = (rjs_coctx_ifstatement_t *)rjs_compiler_getctx(co, RJS_COCTX_IFSTATEMENT);
1170
1171         prec = (rparecord_t *)r_array_slot(records, rec);
1172         rjs_compiler_debughead(co, records, rec);
1173         if (!ctx) {
1174                 rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec);
1175                 return -1;
1176         }
1177         R_ASSERT(ctx);
1178         rvm_codegen_redefinelabel_default(co->cg, ctx->falseidx);
1179         rjs_compiler_debugtail(co, records, rec);
1180
1181         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1182                 return -1;
1183
1184         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1185         prec = (rparecord_t *)r_array_slot(records, rec);
1186         rjs_compiler_debughead(co, records, rec);
1187         rjs_compiler_debugtail(co, records, rec);
1188         return 0;
1189 }
1190
1191
1192 int rjs_compiler_rh_iterationfor(rjs_compiler_t *co, rarray_t *records, long rec)
1193 {
1194         long childrec;
1195         rparecord_t *prec;
1196         rjs_coctx_iteration_t ctx;
1197
1198         r_memset(&ctx, 0, sizeof(ctx));
1199         ctx.base.type = RJS_COCTX_ITERATION;
1200         ctx.start = rvm_codegen_getcodesize(co->cg);
1201         ctx.iterationidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1202         ctx.continueidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1203         ctx.endidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1204         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1205         rvm_scope_push(co->scope);
1206         prec = (rparecord_t *)r_array_slot(records, rec);
1207         rjs_compiler_debughead(co, records, rec);
1208         rjs_compiler_debugtail(co, records, rec);
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_FOREXPRESSIONINIT) {
1211                         if (rjs_compiler_playrecord(co, records, childrec) < 0)
1212                                 goto error;
1213                         break;
1214                 }
1215         }
1216         rvm_codegen_redefinelabel_default(co->cg, ctx.iterationidx);
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_FOREXPRESSIONCOMPARE) {
1219                         if (rjs_compiler_playrecord(co, records, childrec) < 0)
1220                                 goto error;
1221                         break;
1222                 }
1223         }
1224         for (childrec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); childrec >= 0; childrec = rpa_recordtree_next(records, childrec, RPA_RECORD_START)) {
1225                 if (rpa_record_getruleuid(records, childrec) == UID_FORITERATIONSTATEMENT) {
1226                         if (rjs_compiler_playrecord(co, records, childrec) < 0)
1227                                 goto error;
1228                         break;
1229                 }
1230         }
1231         rvm_codegen_redefinelabel_default(co->cg, ctx.continueidx);
1232         for (childrec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); childrec >= 0; childrec = rpa_recordtree_next(records, childrec, RPA_RECORD_START)) {
1233                 if (rpa_record_getruleuid(records, childrec) == UID_FOREXPRESSIONINCREMENT) {
1234                         if (rjs_compiler_playrecord(co, records, childrec) < 0)
1235                                 goto error;
1236                         break;
1237                 }
1238         }
1239         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1240         prec = (rparecord_t *)r_array_slot(records, rec);
1241         rjs_compiler_debughead(co, records, rec);
1242         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1243         rjs_compiler_debugtail(co, records, rec);
1244         rvm_scope_pop(co->scope);
1245         r_array_removelast(co->coctx);
1246         return 0;
1247
1248 error:
1249         rvm_scope_pop(co->scope);
1250         r_array_removelast(co->coctx);
1251         return -1;
1252 }
1253
1254
1255 int rjs_compiler_rh_iterationforin(rjs_compiler_t *co, rarray_t *records, long rec)
1256 {
1257         rparecord_t *prec;
1258         rjs_coctx_iteration_t ctx;
1259
1260         r_memset(&ctx, 0, sizeof(ctx));
1261         ctx.base.type = RJS_COCTX_ITERATION;
1262         ctx.start = rvm_codegen_getcodesize(co->cg);
1263         ctx.iterationidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1264         ctx.continueidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1265         ctx.endidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1266         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1267         rvm_scope_push(co->scope);
1268         prec = (rparecord_t *)r_array_slot(records, rec);
1269         rjs_compiler_debughead(co, records, rec);
1270         rjs_compiler_debugtail(co, records, rec);
1271
1272         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1273                 goto error;
1274
1275         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1276         prec = (rparecord_t *)r_array_slot(records, rec);
1277         rjs_compiler_debughead(co, records, rec);
1278         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx.iterationidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1279         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1280         rvm_codegen_addins(co->cg, rvm_asml(RVM_SUB, SP, SP, DA, 3));
1281         rjs_compiler_debugtail(co, records, rec);
1282         rvm_scope_pop(co->scope);       rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1283         prec = (rparecord_t *)r_array_slot(records, rec);
1284         rjs_compiler_debughead(co, records, rec);
1285         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1286         rjs_compiler_debugtail(co, records, rec);
1287
1288         r_array_removelast(co->coctx);
1289         return 0;
1290
1291 error:
1292         rvm_scope_pop(co->scope);
1293         r_array_removelast(co->coctx);
1294         return -1;
1295 }
1296
1297
1298 int rjs_compiler_rh_forininit(rjs_compiler_t *co, rarray_t *records, long rec)
1299 {
1300         rjs_coctx_iteration_t *ctx = (rjs_coctx_iteration_t *)rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1301         rparecord_t *prec;
1302         prec = (rparecord_t *)r_array_slot(records, rec);
1303         rjs_compiler_debughead(co, records, rec);
1304         rvm_codegen_addins(co->cg, rvm_asml(RVM_PUSH, DA, XX, XX, -1));
1305         rjs_compiler_debugtail(co, records, rec);
1306
1307         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1308                 goto error;
1309
1310         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1311         prec = (rparecord_t *)r_array_slot(records, rec);
1312         rjs_compiler_debughead(co, records, rec);
1313         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
1314         rvm_codegen_addins(co->cg, rvm_asm(RVM_TYPE, R0, R0, XX, 0));
1315         rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, RVM_DTYPE_MAP));
1316         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_BNEQ, DA, XX, XX, 0));
1317         rvm_codegen_redefinelabel_default(co->cg, ctx->iterationidx);
1318         rvm_codegen_redefinelabel_default(co->cg, ctx->continueidx);
1319         rvm_codegen_addins(co->cg, rvm_asml(RVM_LDS, R0, SP, DA, -2));
1320         rvm_codegen_addins(co->cg, rvm_asml(RVM_LDS, R1, SP, DA, 0));
1321         rvm_codegen_addins(co->cg, rvm_asml(RVM_LDS, R2, SP, DA, -1));
1322         rvm_codegen_addins(co->cg, rvm_asml(RJS_PROPNEXT, R0, R1, R0, 0));
1323         rvm_codegen_addins(co->cg, rvm_asml(RVM_CMP, R0, DA, XX, 0));
1324         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
1325         rvm_codegen_addins(co->cg, rvm_asml(RVM_STS, R0, SP, DA, -2));
1326         rvm_codegen_addins(co->cg, rvm_asml(RJS_PROPKEYLDR, R0, R1, R0, 0));
1327         rvm_codegen_addins(co->cg, rvm_asml(RVM_STRR, R0, R2, XX, 0));
1328         rjs_compiler_debugtail(co, records, rec);
1329         return 0;
1330
1331 error:
1332         return -1;
1333 }
1334
1335
1336 int rjs_compiler_rh_iterationwhile(rjs_compiler_t *co, rarray_t *records, long rec)
1337 {
1338         rparecord_t *prec;
1339         rjs_coctx_iteration_t ctx;
1340
1341         r_memset(&ctx, 0, sizeof(ctx));
1342         ctx.base.type = RJS_COCTX_ITERATION;
1343         ctx.start = rvm_codegen_getcodesize(co->cg);
1344         ctx.iterationidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1345         ctx.continueidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1346         ctx.endidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1347         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1348         rvm_scope_push(co->scope);
1349         prec = (rparecord_t *)r_array_slot(records, rec);
1350         rjs_compiler_debughead(co, records, rec);
1351         rjs_compiler_debugtail(co, records, rec);
1352         rvm_codegen_redefinelabel_default(co->cg, ctx.iterationidx);
1353         rvm_codegen_redefinelabel_default(co->cg, ctx.continueidx);
1354         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1355                 goto error;
1356         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1357         prec = (rparecord_t *)r_array_slot(records, rec);
1358         rjs_compiler_debughead(co, records, rec);
1359         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx.iterationidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1360         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1361         rjs_compiler_debugtail(co, records, rec);
1362         rvm_scope_pop(co->scope);
1363         r_array_removelast(co->coctx);
1364         return 0;
1365
1366 error:
1367         rvm_scope_pop(co->scope);
1368         r_array_removelast(co->coctx);
1369         return -1;
1370 }
1371
1372
1373 int rjs_compiler_rh_iterationdo(rjs_compiler_t *co, rarray_t *records, long rec)
1374 {
1375         rparecord_t *prec;
1376         rjs_coctx_iteration_t ctx;
1377
1378         r_memset(&ctx, 0, sizeof(ctx));
1379         ctx.base.type = RJS_COCTX_ITERATION;
1380         ctx.start = rvm_codegen_getcodesize(co->cg);
1381         ctx.iterationidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1382         ctx.continueidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1383         ctx.endidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1384         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1385         rvm_scope_push(co->scope);
1386         prec = (rparecord_t *)r_array_slot(records, rec);
1387         rjs_compiler_debughead(co, records, rec);
1388         rjs_compiler_debugtail(co, records, rec);
1389         rvm_codegen_redefinelabel_default(co->cg, ctx.iterationidx);
1390         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1391                 goto error;
1392         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1393         prec = (rparecord_t *)r_array_slot(records, rec);
1394         rjs_compiler_debughead(co, records, rec);
1395         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx.iterationidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1396         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1397         rjs_compiler_debugtail(co, records, rec);
1398         rvm_scope_pop(co->scope);
1399         r_array_removelast(co->coctx);
1400         return 0;
1401
1402 error:
1403         rvm_scope_pop(co->scope);
1404         r_array_removelast(co->coctx);
1405         return -1;
1406 }
1407
1408
1409 int rjs_compiler_rh_caseblock(rjs_compiler_t *co, rarray_t *records, long rec)
1410 {
1411         rparecord_t *prec;
1412         rjs_coctx_switch_t ctx;
1413
1414         r_memset(&ctx, 0, sizeof(ctx));
1415         ctx.base.type = RJS_COCTX_SWITCH;
1416         ctx.start = rvm_codegen_getcodesize(co->cg);
1417         ctx.endidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1418         ctx.defaultidx = ctx.endidx;
1419         ctx.caseidx = r_array_create(sizeof(long));
1420
1421         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1422         rvm_scope_push(co->scope);
1423         prec = (rparecord_t *)r_array_slot(records, rec);
1424         rjs_compiler_debughead(co, records, rec);
1425         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
1426         rjs_compiler_debugtail(co, records, rec);
1427         ctx.pass = RJS_COMPILER_PASS_1;
1428         ctx.casenum = 0;
1429         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1430                 goto error;
1431         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx.defaultidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1432         ctx.pass = RJS_COMPILER_PASS_2;
1433         ctx.casenum = 0;
1434         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1435                 goto error;
1436         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1437         prec = (rparecord_t *)r_array_slot(records, rec);
1438         rjs_compiler_debughead(co, records, rec);
1439         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1440         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUB, SP, SP, DA, 1));
1441         rjs_compiler_debugtail(co, records, rec);
1442         rvm_scope_pop(co->scope);
1443         r_array_removelast(co->coctx);
1444         r_array_destroy(ctx.caseidx);
1445         return 0;
1446
1447 error:
1448         rvm_scope_pop(co->scope);
1449         r_array_removelast(co->coctx);
1450         r_array_destroy(ctx.caseidx);
1451         return -1;
1452 }
1453
1454
1455 int rjs_compiler_rh_caseclause(rjs_compiler_t *co, rarray_t *records, long rec)
1456 {
1457         rparecord_t *prec;
1458         rjs_coctx_switch_t *ctx = (rjs_coctx_switch_t *)rjs_compiler_gettopctx(co);
1459
1460         prec = (rparecord_t *)r_array_slot(records, rec);
1461         rjs_compiler_debughead(co, records, rec);
1462         if (!ctx || ctx->base.type != RJS_COCTX_SWITCH) {
1463                 rjs_compiler_adderror(co, RJS_ERROR_NOTASWITCH, prec);
1464                 return -1;
1465         }
1466         R_ASSERT(ctx);
1467         rjs_compiler_debugtail(co, records, rec);
1468
1469         if (ctx->pass == RJS_COMPILER_PASS_1) {
1470                 long child = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START);
1471                 long caseidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1472                 r_array_add(ctx->caseidx, &caseidx);
1473                 ctx->casenum += 1;
1474                 R_ASSERT(child >= 0);
1475                 if (rjs_compiler_playrecord(co, records, child) < 0)
1476                         return -1;
1477                 rjs_compiler_debughead(co, records, rpa_recordtree_get(records, rec, RPA_RECORD_END));
1478                 rvm_codegen_addins(co->cg, rvm_asml(RVM_LDS, R1, SP, DA, 0));
1479                 rvm_codegen_addins(co->cg, rvm_asml(RJS_EEQ, R0, R0, R1, 0));
1480                 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, caseidx, rvm_asm(RVM_BNEQ, DA, XX, XX, 0));
1481                 rjs_compiler_debugtail(co, records, rpa_recordtree_get(records, rec, RPA_RECORD_END));
1482
1483         }
1484
1485         if (ctx->pass == RJS_COMPILER_PASS_2) {
1486                 long child = rpa_recordtree_lastchild(records, rec, RPA_RECORD_START);
1487                 long caseidx = r_array_index(ctx->caseidx, ctx->casenum, long);
1488                 ctx->casenum += 1;
1489                 R_ASSERT(child >= 0);
1490                 rvm_codegen_redefinelabel_default(co->cg, caseidx);
1491                 if (rjs_compiler_playrecord(co, records, child) < 0)
1492                         return -1;
1493         }
1494
1495         return 0;
1496 }
1497
1498
1499 int rjs_compiler_rh_defaultclause(rjs_compiler_t *co, rarray_t *records, long rec)
1500 {
1501         rparecord_t *prec;
1502         rjs_coctx_switch_t *ctx = (rjs_coctx_switch_t *)rjs_compiler_gettopctx(co);
1503
1504         prec = (rparecord_t *)r_array_slot(records, rec);
1505         rjs_compiler_debughead(co, records, rec);
1506         if (!ctx || ctx->base.type != RJS_COCTX_SWITCH) {
1507                 rjs_compiler_adderror(co, RJS_ERROR_NOTASWITCH, prec);
1508                 return -1;
1509         }
1510         R_ASSERT(ctx);
1511         rjs_compiler_debugtail(co, records, rec);
1512
1513         if (ctx->pass == RJS_COMPILER_PASS_1) {
1514                 ctx->defaultidx = rvm_codegen_invalid_addlabel_s(co->cg, NULL);
1515         }
1516
1517         if (ctx->pass == RJS_COMPILER_PASS_2) {
1518                 rvm_codegen_redefinelabel_default(co->cg, ctx->defaultidx);
1519                 if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1520                         return -1;
1521         }
1522
1523         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1524         prec = (rparecord_t *)r_array_slot(records, rec);
1525         rjs_compiler_debughead(co, records, rec);
1526         rjs_compiler_debugtail(co, records, rec);
1527         return 0;
1528 }
1529
1530
1531 int rjs_compiler_rh_dowhileexpressioncompare(rjs_compiler_t *co, rarray_t *records, long rec)
1532 {
1533         rparecord_t *prec;
1534         rjs_coctx_iteration_t *ctx = (rjs_coctx_iteration_t *)rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1535
1536         prec = (rparecord_t *)r_array_slot(records, rec);
1537         rjs_compiler_debughead(co, records, rec);
1538         if (!ctx) {
1539                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec);
1540                 return -1;
1541         }
1542         R_ASSERT(ctx);
1543         rvm_codegen_redefinelabel_default(co->cg, ctx->continueidx);
1544         rjs_compiler_debugtail(co, records, rec);
1545
1546         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1547                 return -1;
1548
1549         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1550         prec = (rparecord_t *)r_array_slot(records, rec);
1551         rjs_compiler_debughead(co, records, rec);
1552         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_BEQ, DA, XX, XX, 0));
1553         rjs_compiler_debugtail(co, records, rec);
1554         return 0;
1555 }
1556
1557
1558 int rjs_compiler_rh_forexpressioncompare(rjs_compiler_t *co, rarray_t *records, long rec)
1559 {
1560         rparecord_t *prec;
1561         rjs_coctx_iteration_t *ctx = (rjs_coctx_iteration_t *)rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1562
1563         prec = (rparecord_t *)r_array_slot(records, rec);
1564         rjs_compiler_debughead(co, records, rec);
1565         if (!ctx) {
1566                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec);
1567                 return -1;
1568         }
1569         R_ASSERT(ctx);
1570         rjs_compiler_debugtail(co, records, rec);
1571
1572         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1573                 return -1;
1574
1575         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1576         prec = (rparecord_t *)r_array_slot(records, rec);
1577         rjs_compiler_debughead(co, records, rec);
1578         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_BEQ, DA, XX, XX, 0));
1579         rjs_compiler_debugtail(co, records, rec);
1580         return 0;
1581 }
1582
1583
1584 int rjs_compiler_rh_forexpressionincrement(rjs_compiler_t *co, rarray_t *records, long rec)
1585 {
1586         rparecord_t *prec;
1587         rjs_coctx_iteration_t *ctx = (rjs_coctx_iteration_t *)rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1588
1589         prec = (rparecord_t *)r_array_slot(records, rec);
1590         rjs_compiler_debughead(co, records, rec);
1591         if (!ctx) {
1592                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec);
1593                 return -1;
1594         }
1595         R_ASSERT(ctx);
1596         rjs_compiler_debugtail(co, records, rec);
1597
1598         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1599                 return -1;
1600
1601         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1602         prec = (rparecord_t *)r_array_slot(records, rec);
1603         rjs_compiler_debughead(co, records, rec);
1604         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->iterationidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1605         rjs_compiler_debugtail(co, records, rec);
1606         return 0;
1607 }
1608
1609
1610 int rjs_compiler_rh_postfixexpressionop(rjs_compiler_t *co, rarray_t *records, long rec)
1611 {
1612         rparecord_t *prec;
1613         long opcode;
1614         long opcoderec;
1615
1616         if ((opcoderec = rpa_recordtree_lastchild(records, rec, RPA_RECORD_END)) < 0)
1617                 return -1;
1618         opcode = rjs_compiler_record2opcode((rparecord_t *)r_array_slot(records, opcoderec));
1619         prec = (rparecord_t *)r_array_slot(records, rec);
1620         rjs_compiler_debughead(co, records, rec);
1621         rjs_compiler_debugtail(co, records, rec);
1622
1623         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1624                 return -1;
1625
1626         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1627         prec = (rparecord_t *)r_array_slot(records, rec);
1628         rjs_compiler_debughead(co, records, rec);
1629         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
1630         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R1, XX, 0));
1631         rvm_codegen_addins(co->cg, rvm_asm(opcode, R2, R0, DA, 1));
1632         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R2, R1, XX, 0));
1633
1634         rjs_compiler_debugtail(co, records, rec);
1635         return 0;
1636 }
1637
1638
1639 int rjs_compiler_rh_prefixexpressionop(rjs_compiler_t *co, rarray_t *records, long rec)
1640 {
1641         rparecord_t *prec;
1642         long opcode;
1643         long opcoderec;
1644
1645         if ((opcoderec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_END)) < 0)
1646                 return -1;
1647         opcode = rjs_compiler_record2opcode((rparecord_t *)r_array_slot(records, opcoderec));
1648
1649         prec = (rparecord_t *)r_array_slot(records, rec);
1650         rjs_compiler_debughead(co, records, rec);
1651         rjs_compiler_debugtail(co, records, rec);
1652
1653         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1654                 return -1;
1655
1656         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1657         prec = (rparecord_t *)r_array_slot(records, rec);
1658         rjs_compiler_debughead(co, records, rec);
1659         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R0, XX, 0));
1660         rvm_codegen_addins(co->cg, rvm_asm(opcode, R0, R0, DA, 1));
1661         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
1662         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
1663
1664         rjs_compiler_debugtail(co, records, rec);
1665         return 0;
1666 }
1667
1668
1669 int rjs_compiler_rh_newexpressioncall(rjs_compiler_t *co, rarray_t *records, long rec)
1670 {
1671         rparecord_t *prec;
1672         rjs_coctx_functioncall_t ctx;
1673
1674         r_memset(&ctx, 0, sizeof(ctx));
1675         ctx.base.type = RJS_COCTX_FUNCTIONCALL;
1676         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1677
1678         prec = (rparecord_t *)r_array_slot(records, rec);
1679         rjs_compiler_debughead(co, records, rec);
1680         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(TP)|BIT(FP)|BIT(SP)|BIT(LR)));
1681         rjs_compiler_debugtail(co, records, rec);
1682
1683         /*
1684          * Important: Function call has two children FunctionCallName, Arguments
1685          * We evaluate them in reverse order, first we evaluate the Arguments and push them on the
1686          * stack, than we evaluate the FunctionCallName -> R0. When we make the call we assume the
1687          * result of the FunctionCallName will be in R0.
1688          */
1689         if (rjs_compiler_playreversechildrecords(co, records, rec) < 0)
1690                 goto error;
1691
1692         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1693         prec = (rparecord_t *)r_array_slot(records, rec);
1694         rjs_compiler_debughead(co, records, rec);
1695         rvm_codegen_addins(co->cg, rvm_asm(RJS_MAPALLOC, TP, DA, XX, 0));
1696         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUB, FP, SP, DA, ctx.arguments));
1697         rvm_codegen_addins(co->cg, rvm_asm(RVM_CALL, R0, XX, XX, 0));
1698         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
1699         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, TP, XX, 0));
1700         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(TP,LR)));
1701         rjs_compiler_debugtail(co, records, rec);
1702         r_array_removelast(co->coctx);
1703         return 0;
1704
1705 error:
1706         r_array_removelast(co->coctx);
1707         return -1;
1708 }
1709
1710
1711 int rjs_compiler_rh_this(rjs_compiler_t *co, rarray_t *records, long rec)
1712 {
1713         rparecord_t *prec;
1714         prec = (rparecord_t *)r_array_slot(records, rec);
1715         rjs_compiler_debughead(co, records, rec);
1716         rjs_compiler_debugtail(co, records, rec);
1717
1718         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1719                 return -1;
1720
1721         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1722         prec = (rparecord_t *)r_array_slot(records, rec);
1723         rjs_compiler_debughead(co, records, rec);
1724         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, TP, XX, 0));
1725         rjs_compiler_debugtail(co, records, rec);
1726         return 0;
1727 }
1728
1729
1730 int rjs_compiler_rh_binaryoperator(rjs_compiler_t *co, rarray_t *records, long rec)
1731 {
1732         rparecord_t *prec;
1733         rjs_coctx_t *ctx = rjs_compiler_gettopctx(co);
1734
1735         prec = (rparecord_t *)r_array_slot(records, rec);
1736         rjs_compiler_debughead(co, records, rec);
1737         rjs_compiler_debugtail(co, records, rec);
1738
1739         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1740                 return -1;
1741
1742         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1743         prec = (rparecord_t *)r_array_slot(records, rec);
1744         rjs_compiler_debughead(co, records, rec);
1745         if (ctx && ctx->type == RJS_COCTX_OPERATION)
1746                 ((rjs_coctx_operation_t *)ctx)->opcode = rjs_compiler_record2opcode(prec);
1747         rjs_compiler_debugtail(co, records, rec);
1748         return 0;
1749 }
1750
1751
1752 int rjs_compiler_rh_unaryoperator(rjs_compiler_t *co, rarray_t *records, long rec)
1753 {
1754         rparecord_t *prec;
1755         rjs_coctx_t *ctx = rjs_compiler_gettopctx(co);
1756
1757         prec = (rparecord_t *)r_array_slot(records, rec);
1758         rjs_compiler_debughead(co, records, rec);
1759         rjs_compiler_debugtail(co, records, rec);
1760
1761         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1762                 return -1;
1763
1764         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1765         prec = (rparecord_t *)r_array_slot(records, rec);
1766         rjs_compiler_debughead(co, records, rec);
1767         if (ctx && ctx->type == RJS_COCTX_OPERATION)
1768                 ((rjs_coctx_operation_t *)ctx)->opcode = rjs_compiler_record2unaryopcode(prec);
1769         rjs_compiler_debugtail(co, records, rec);
1770         return 0;
1771 }
1772
1773
1774 int rjs_compiler_rh_identifiername(rjs_compiler_t *co, rarray_t *records, long rec)
1775 {
1776         rparecord_t *prec;
1777         prec = (rparecord_t *)r_array_slot(records, rec);
1778         rjs_compiler_debughead(co, records, rec);
1779         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, prec->inputsiz));
1780         rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R2, DA, XX, (void*)prec->input));
1781         rjs_compiler_debugtail(co, records, rec);
1782
1783         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1784                 return -1;
1785
1786         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1787         prec = (rparecord_t *)r_array_slot(records, rec);
1788         rjs_compiler_debughead(co, records, rec);
1789         rjs_compiler_debugtail(co, records, rec);
1790         return 0;
1791 }
1792
1793
1794 int rjs_compiler_rh_continue(rjs_compiler_t *co, rarray_t *records, long rec)
1795 {
1796         rparecord_t *prec;
1797         rjs_coctx_t *ctx;
1798         rjs_coctx_iteration_t *iterctx;
1799
1800         ctx = rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1801         prec = (rparecord_t *)r_array_slot(records, rec);
1802         rjs_compiler_debughead(co, records, rec);
1803         if (!ctx) {
1804                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec);
1805                 return -1;
1806         }
1807         R_ASSERT(ctx);
1808         iterctx = (rjs_coctx_iteration_t *)ctx;
1809         rjs_compiler_debugtail(co, records, rec);
1810
1811         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1812                 return -1;
1813
1814         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1815         prec = (rparecord_t *)r_array_slot(records, rec);
1816         rjs_compiler_debughead(co, records, rec);
1817         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, iterctx->continueidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1818         rjs_compiler_debugtail(co, records, rec);
1819         return 0;
1820 }
1821
1822
1823 int rjs_compiler_rh_break(rjs_compiler_t *co, rarray_t *records, long rec)
1824 {
1825         rparecord_t *prec;
1826         rjs_coctx_t *ctx;
1827
1828         ctx = rjs_compiler_getctx(co, RJS_COCTX_ITERATION|RJS_COCTX_SWITCH);
1829         prec = (rparecord_t *)r_array_slot(records, rec);
1830         rjs_compiler_debughead(co, records, rec);
1831         if (!ctx) {
1832                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec);
1833                 return -1;
1834         }
1835         R_ASSERT(ctx);
1836         rjs_compiler_debugtail(co, records, rec);
1837
1838         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1839                 return -1;
1840
1841         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1842         prec = (rparecord_t *)r_array_slot(records, rec);
1843         rjs_compiler_debughead(co, records, rec);
1844         if (ctx->type == RJS_COCTX_ITERATION) {
1845                 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ((rjs_coctx_iteration_t *)ctx)->endidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1846         } else  if (ctx->type == RJS_COCTX_SWITCH) {
1847                 rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ((rjs_coctx_switch_t *)ctx)->endidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1848         } else {
1849                 /*
1850                  * Error
1851                  */
1852                 return -1;
1853         }
1854
1855         rjs_compiler_debugtail(co, records, rec);
1856         return 0;
1857 }
1858
1859
1860 int rjs_compiler_rh_syntaxerror(rjs_compiler_t *co, rarray_t *records, long rec)
1861 {
1862         rparecord_t *prec;
1863         prec = (rparecord_t *)r_array_slot(records, rec);
1864         rjs_compiler_debughead(co, records, rec);
1865         rjs_compiler_debugtail(co, records, rec);
1866
1867         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1868                 return -1;
1869
1870         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1871         prec = (rparecord_t *)r_array_slot(records, rec);
1872         rjs_compiler_debughead(co, records, rec);
1873         rjs_compiler_adderror(co, RJS_ERROR_SYNTAX, prec);
1874         rjs_compiler_debugtail(co, records, rec);
1875         return 0;
1876 }
1877
1878
1879 int rjs_compiler_rh_block(rjs_compiler_t *co, rarray_t *records, long rec)
1880 {
1881         rparecord_t *prec;
1882         prec = (rparecord_t *)r_array_slot(records, rec);
1883         rjs_compiler_debughead(co, records, rec);
1884         rvm_scope_push(co->scope);
1885         rjs_compiler_debugtail(co, records, rec);
1886
1887         if (rjs_compiler_playchildrecords(co, records, rec) < 0) {
1888                 rvm_scope_pop(co->scope);
1889                 return -1;
1890         }
1891
1892         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1893         prec = (rparecord_t *)r_array_slot(records, rec);
1894         rjs_compiler_debughead(co, records, rec);
1895         rvm_scope_pop(co->scope);
1896         rjs_compiler_debugtail(co, records, rec);
1897         return 0;
1898 }
1899
1900
1901 int rjs_compiler_rh_(rjs_compiler_t *co, rarray_t *records, long rec)
1902 {
1903         rparecord_t *prec;
1904         prec = (rparecord_t *)r_array_slot(records, rec);
1905         rjs_compiler_debughead(co, records, rec);
1906         rjs_compiler_debugtail(co, records, rec);
1907
1908         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1909                 return -1;
1910
1911         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1912         prec = (rparecord_t *)r_array_slot(records, rec);
1913         rjs_compiler_debughead(co, records, rec);
1914         rjs_compiler_debugtail(co, records, rec);
1915         return 0;
1916 }
1917
1918
1919 rjs_compiler_t *rjs_compiler_create(rvmcpu_t *cpu)
1920 {
1921         rjs_compiler_t *co = (rjs_compiler_t *) r_zmalloc(sizeof(*co));
1922
1923         co->scope = rvm_scope_create();
1924         co->coctx = r_array_create(sizeof(rjs_coctx_t *));
1925         co->cpu = cpu;
1926         r_memset(co->handlers, 0, sizeof(co->handlers));
1927
1928         co->handlers[UID_PROGRAM] = rjs_compiler_rh_program;
1929         co->handlers[UID_EXPRESSION] = rjs_compiler_rh_expression;
1930         co->handlers[UID_LEFTHANDSIDEEXPRESSION] = rjs_compiler_rh_lefthandsideexpression;
1931         co->handlers[UID_LEFTHANDSIDEEXPRESSIONADDR] = rjs_compiler_rh_lefthandsideexpressionaddr;
1932         co->handlers[UID_DECIMALINTEGERLITERAL] = rjs_compiler_rh_decimalintegerliteral;
1933         co->handlers[UID_HEXINTEGERLITERAL] = rjs_compiler_rh_hexintegerliteral;
1934         co->handlers[UID_DECIMALNONINTEGERLITERAL] = rjs_compiler_rh_decimalnonintegerliteral;
1935         co->handlers[UID_STRINGCHARACTERS] = rjs_compiler_rh_stringcharacters;
1936         co->handlers[UID_STRINGLITERAL] = rjs_compiler_rh_stringliteral;
1937
1938         co->handlers[UID_ADDITIVEEXPRESSIONOP] = rjs_compiler_rh_binaryexpressionop;
1939         co->handlers[UID_MULTIPLICATIVEEXPRESSIONOP] = rjs_compiler_rh_binaryexpressionop;
1940         co->handlers[UID_BITWISEANDOP] = rjs_compiler_rh_binaryexpressionop;
1941         co->handlers[UID_BITWISEXOROP] = rjs_compiler_rh_binaryexpressionop;
1942         co->handlers[UID_BITWISEOROP] = rjs_compiler_rh_binaryexpressionop;
1943         co->handlers[UID_SHIFTEXPRESSIONOP] = rjs_compiler_rh_binaryexpressionop;
1944         co->handlers[UID_EQUALITYEXPRESSIONOP] = rjs_compiler_rh_binaryexpressionop;
1945         co->handlers[UID_RELATIONALEXPRESSIONOP] = rjs_compiler_rh_binaryexpressionop;
1946         co->handlers[UID_LOGICALOROP] = rjs_compiler_rh_binaryexpressionop;
1947         co->handlers[UID_LOGICALANDOP] = rjs_compiler_rh_binaryexpressionop;
1948         co->handlers[UID_VARIABLEALLOCATEANDINIT] = rjs_compiler_rh_varallocinit;
1949         co->handlers[UID_VARIABLEALLOCATE] = rjs_compiler_rh_varalloc;
1950         co->handlers[UID_IDENTIFIER] = rjs_compiler_rh_identifier;
1951         co->handlers[UID_IDENTIFIERNAME] = rjs_compiler_rh_identifiername;
1952         co->handlers[UID_INITIALISER] = rjs_compiler_rh_initializer;
1953         co->handlers[UID_ASSIGNMENTEXPRESSIONOP] = rjs_compiler_rh_assignmentexpressionop;
1954         co->handlers[UID_NEWARRAYEXPRESSION] = rjs_compiler_rh_newarrayexpression;
1955         co->handlers[UID_MEMBEREXPRESSIONDOTOP] = rjs_compiler_rh_memberexpressiondotop;
1956         co->handlers[UID_MEMBEREXPRESSIONINDEXOP] = rjs_compiler_rh_memberexpressionindexop;
1957         co->handlers[UID_FUNCTIONDECLARATION] = rjs_compiler_rh_functiondeclaration;
1958         co->handlers[UID_FUNCTIONEXPRESSION] = rjs_compiler_rh_functiondeclaration;
1959         co->handlers[UID_FUNCTIONPARAMETER] = rjs_compiler_rh_functionparameter;
1960         co->handlers[UID_FUNCTIONCALL] = rjs_compiler_rh_functioncall;
1961         co->handlers[UID_ARGUMENT] = rjs_compiler_rh_argument;
1962         co->handlers[UID_ARGUMENTS] = rjs_compiler_rh_arguments;
1963         co->handlers[UID_RETURNSTATEMENT] = rjs_compiler_rh_returnstatement;
1964         co->handlers[UID_IFSTATEMENT] = rjs_compiler_rh_ifstatement;
1965         co->handlers[UID_IFCONDITIONOP] = rjs_compiler_rh_ifconditionop;
1966         co->handlers[UID_IFTRUESTATEMENT] = rjs_compiler_rh_iftruestatement;
1967         co->handlers[UID_IFFALSESTATEMENT] = rjs_compiler_rh_iffalsestatement;
1968         co->handlers[UID_ITERATIONDO] = rjs_compiler_rh_iterationdo;
1969         co->handlers[UID_ITERATIONWHILE] = rjs_compiler_rh_iterationwhile;
1970         co->handlers[UID_ITERATIONFOR] = rjs_compiler_rh_iterationfor;
1971         co->handlers[UID_ITERATIONFORIN] = rjs_compiler_rh_iterationforin;
1972         co->handlers[UID_FORININIT] = rjs_compiler_rh_forininit;
1973         co->handlers[UID_DOWHILEEXPRESSIONCOMPARE] = rjs_compiler_rh_dowhileexpressioncompare;
1974         co->handlers[UID_WHILEEXPRESSIONCOMPARE] = rjs_compiler_rh_forexpressioncompare;
1975         co->handlers[UID_FOREXPRESSIONCOMPARE] = rjs_compiler_rh_forexpressioncompare;
1976         co->handlers[UID_FOREXPRESSIONINCREMENT] = rjs_compiler_rh_forexpressionincrement;
1977         co->handlers[UID_POSTFIXEXPRESSIONOP] = rjs_compiler_rh_postfixexpressionop;
1978         co->handlers[UID_PREFIXEXPRESSIONOP] = rjs_compiler_rh_prefixexpressionop;
1979         co->handlers[UID_THIS] = rjs_compiler_rh_this;
1980         co->handlers[UID_NEWEXPRESSIONCALL] = rjs_compiler_rh_newexpressioncall;
1981         co->handlers[UID_UNARYEXPRESSIONOP] = rjs_compiler_rh_unaryexpressionop;
1982         co->handlers[UID_UNARYEXPRESSIONDELETE] = rjs_compiler_rh_unaryexpressiondelete;
1983         co->handlers[UID_UNARYEXPRESSIONTYPEOF] = rjs_compiler_rh_unaryexpressiontypeof;
1984         co->handlers[UID_BINARYOPERATOR] = rjs_compiler_rh_binaryoperator;
1985         co->handlers[UID_UNARYOPERATOR] = rjs_compiler_rh_unaryoperator;
1986         co->handlers[UID_BREAKSTATEMENT] = rjs_compiler_rh_break;
1987         co->handlers[UID_CONTINUESTATEMENT] = rjs_compiler_rh_continue;
1988         co->handlers[UID_SYNTAXERROR] = rjs_compiler_rh_syntaxerror;
1989         co->handlers[UID_BLOCK] = rjs_compiler_rh_block;
1990         co->handlers[UID_CASECLAUSE] = rjs_compiler_rh_caseclause;
1991         co->handlers[UID_DEFAULTCLAUSE] = rjs_compiler_rh_defaultclause;
1992         co->handlers[UID_CASEBLOCK] = rjs_compiler_rh_caseblock;
1993
1994         return co;
1995 }
1996
1997
1998 void rjs_compiler_destroy(rjs_compiler_t *co)
1999 {
2000         if (co) {
2001                 rvm_scope_destroy(co->scope);
2002                 r_array_destroy(co->coctx);
2003                 r_free(co->temp);
2004                 co->cpu = NULL;
2005                 r_free(co);
2006         }
2007 }
2008
2009
2010 static int rjs_compiler_rh_default(rjs_compiler_t *co, rarray_t *records, long rec)
2011 {
2012         rparecord_t *prec;
2013
2014         prec = (rparecord_t *)r_array_slot(records, rec);
2015         rjs_compiler_debughead(co, records, rec);
2016         rjs_compiler_debugtail(co, records, rec);
2017
2018         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
2019                 return -1;
2020
2021         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
2022         prec = (rparecord_t *)r_array_slot(records, rec);
2023         rjs_compiler_debughead(co, records, rec);
2024         rjs_compiler_debugtail(co, records, rec);
2025
2026         return 0;
2027 }
2028
2029
2030 static int rjs_compiler_playchildrecords(rjs_compiler_t *co, rarray_t *records, long rec)
2031 {
2032         long child;
2033
2034         for (child = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); child >= 0; child = rpa_recordtree_next(records, child, RPA_RECORD_START)) {
2035                 if (rjs_compiler_playrecord(co, records, child) < 0)
2036                         return -1;
2037         }
2038
2039         return 0;
2040 }
2041
2042
2043 int rjs_compiler_playreversechildrecords(rjs_compiler_t *co, rarray_t *records, long rec)
2044 {
2045         long child;
2046
2047         for (child = rpa_recordtree_lastchild(records, rec, RPA_RECORD_START); child >= 0; child = rpa_recordtree_prev(records, child, RPA_RECORD_START)) {
2048                 if (rjs_compiler_playrecord(co, records, child) < 0)
2049                         return -1;
2050         }
2051
2052         return 0;
2053 }
2054
2055
2056 static int rjs_compiler_playrecord(rjs_compiler_t *co, rarray_t *records, long rec)
2057 {
2058         rparecord_t *prec;
2059         prec = (rparecord_t *)r_array_slot(records, rec);
2060         if (prec->ruleuid >= 0 && prec->ruleuid < RJS_COMPILER_NHANDLERS && co->handlers[prec->ruleuid]) {
2061                 return co->handlers[prec->ruleuid](co, records, rec);
2062         }
2063         return rjs_compiler_rh_default(co, records, rec);
2064 }
2065
2066
2067 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)
2068 {
2069         long i;
2070         rvm_codelabel_t *labelerr;
2071
2072         if (!co || !records || !cg || r_array_empty(records)) {
2073                 /*
2074                  * TBD
2075                  */
2076                 return -1;
2077         }
2078         co->cg = cg;
2079         co->error = error;
2080         co->script = script;
2081         co->scriptsize = scriptsize;
2082
2083         for (i = 0; i >= 0; i = rpa_recordtree_next(records, i, RPA_RECORD_START)) {
2084                 if (rjs_compiler_playrecord(co, records, i) < 0)
2085                         /*
2086                          * TBD
2087                          */
2088                         return -1;
2089         }
2090
2091         if (rvm_codegen_relocate(co->cg, &labelerr) < 0) {
2092                 /*
2093                  * TBD
2094                  */
2095                 return -1;
2096         }
2097
2098         return 0;
2099 }