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