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