RPA Toolkit
85d48eed683032af570349b7770089125f3842dc
[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)
28 {
29         /*
30          * Not used for now. I should probably get rid of this altogether.
31          */
32 }
33
34
35 static const rchar *rjs_compiler_record2str(rjs_compiler_t *co, rarray_t *records, rlong rec)
36 {
37         rparecord_t *prec = (rparecord_t *)r_array_slot(records, rpa_recordtree_get(records, rec, RPA_RECORD_END));
38         rsize_t size = 16; /* Min size */
39
40         if (prec && prec->inputsiz) {
41                 size = prec->inputsiz + 1;
42         }
43         co->temp = r_realloc(co->temp, size);
44         r_memset(co->temp, 0, size);
45         if (prec->input && prec->inputsiz)
46                 r_memcpy(co->temp, prec->input, prec->inputsiz);
47         return co->temp;
48 }
49
50
51 static rlong rjs_compiler_record_parentuid(rjs_compiler_t *co, rarray_t *records, rlong rec)
52 {
53         rlong parent = rpa_recordtree_parent(records, rec, RPA_RECORD_START);
54
55         if (parent < 0)
56                 return -1;
57         return rpa_record_getruleuid(records, parent);
58 }
59
60
61 static rlong rjs_compiler_record_lastofkind(rjs_compiler_t *co, rarray_t *records, rlong rec)
62 {
63         rlong uid = rpa_record_getruleuid(records, rec);
64         rlong i;
65
66         for (i = rpa_recordtree_next(records, rec, RPA_RECORD_START) ; i >= 0; i = rpa_recordtree_next(records, i, RPA_RECORD_START)) {
67                 if (rpa_record_getruleuid(records, i) == uid)
68                         return 0;
69         }
70         return 1;
71 }
72
73
74 static rlong rjs_compiler_record2identifer(rjs_compiler_t *co, rarray_t *records, rlong rec)
75 {
76         rvm_varmap_t *v = NULL;
77         rjs_coctx_t *ctx = NULL;
78         rparecord_t *prec = (rparecord_t *)r_array_slot(records, rec);
79
80         /*
81          * First lets find out if we are within a function definition or
82          * this is a global variable.
83          */
84         ctx = rjs_compiler_getctx(co, RJS_COCTX_FUNCTION | RJS_COCTX_GLOBAL);
85         R_ASSERT(ctx);
86
87         v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
88
89         /*
90          * TBD: Temporary here
91          */
92         if (v) {
93                 r_printf("ERROR: Identifier already defined: %s\n", rjs_compiler_record2str(co, records, rec));
94                 return -1;
95         }
96
97         if (ctx->type == RJS_COCTX_FUNCTION) {
98                 rjs_coctx_function_t *functx = (rjs_coctx_function_t *)ctx;
99                 functx->allocs += 1;
100                 rvm_scope_addoffset(co->scope, prec->input, prec->inputsiz, functx->allocs);
101         } else {
102 //              rjs_coctx_global_t *globalctx = (rjs_coctx_global_t *)ctx;
103 //              r_carray_setlength(co->cpu->data, globalctx->allocs + 1);
104 //              rvm_scope_addpointer(co->scope, prec->input, prec->inputsiz, r_carray_slot(co->cpu->data, globalctx->allocs));
105
106 //              rvm_scope_addpointer(co->scope, prec->input, prec->inputsiz, r_carray_slot_expand(co->cpu->data, r_carray_length(co->cpu->data)));
107 //              r_carray_setlength(co->cpu->data, r_carray_length(co->cpu->data) + 1);
108                 rvm_scope_addpointer(co->scope, prec->input, prec->inputsiz, rvm_cpu_alloc_global(co->cpu));
109         }
110         v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
111         if (v->datatype == VARMAP_DATATYPE_OFFSET) {
112                 rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDRS, R0, FP, DA, v->data.offset));
113         } else {
114                 rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R0, DA, XX, v->data.ptr));
115         }
116
117         return 0;
118 }
119
120
121 rjs_coctx_t *rjs_compiler_getctx(rjs_compiler_t *co, rulong type)
122 {
123         rlong i;
124         rjs_coctx_t *ctx;
125
126         for (i = r_array_length(co->coctx) - 1; i >= 0; i--) {
127                 ctx = r_array_index(co->coctx, i, rjs_coctx_t*);
128                 if (ctx->type & type)
129                         return ctx;
130         }
131         return NULL;
132 }
133
134
135 rjs_coctx_t *rjs_compiler_gettopctx(rjs_compiler_t *co)
136 {
137         rlong len = r_array_length(co->coctx);
138
139         if (len)
140                 return r_array_index(co->coctx, len - 1, rjs_coctx_t*);
141         return NULL;
142 }
143
144
145 rlong rjs_compiler_record2opcode(rparecord_t *prec)
146 {
147         const rchar *input = prec->input;
148         rsize_t size = prec->inputsiz;
149
150         if (r_stringncmp("++", input,  size))
151                 return RVM_EADD;
152         else 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_ESUB;
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_EMUL;
164         else if (r_stringncmp("*=", input,  size))
165                 return RVM_EMUL;
166         else if (r_stringncmp("/", input,  size))
167                 return RVM_EDIV;
168         else if (r_stringncmp("/=", input,  size))
169                 return RVM_EDIV;
170         else if (r_stringncmp("%", input,  size))
171                 return RVM_EMOD;
172         else if (r_stringncmp("%=", input,  size))
173                 return RVM_EMOD;
174         else if (r_stringncmp("&&", input,  size))
175                 return RVM_ELAND;
176         else if (r_stringncmp("||", input,  size))
177                 return RVM_ELOR;
178         else if (r_stringncmp("&", input,  size))
179                 return RVM_EAND;
180         else if (r_stringncmp("&=", input,  size))
181                 return RVM_EAND;
182         else if (r_stringncmp("|", input,  size))
183                 return RVM_EORR;
184         else if (r_stringncmp("|=", input,  size))
185                 return RVM_EORR;
186         else if (r_stringncmp("^", input,  size))
187                 return RVM_EXOR;
188         else if (r_stringncmp("^=", input,  size))
189                 return RVM_EXOR;
190         else if (r_stringncmp(">>", input,  size))
191                 return RVM_ELSR;
192         else if (r_stringncmp(">>=", input,  size))
193                 return RVM_ELSR;
194         else if (r_stringncmp("<<", input,  size))
195                 return RVM_ELSL;
196         else if (r_stringncmp("<<=", input,  size))
197                 return RVM_ELSL;
198         else if (r_stringncmp(">>>", input,  size))
199                 return RVM_ELSRU;
200         else if (r_stringncmp(">>>=", input,  size))
201                 return RVM_ELSRU;
202         else if (r_stringncmp("<=", input,  size))
203                 return RVM_ELESSEQ;
204         else if (r_stringncmp(">=", input,  size))
205                 return RVM_EGREATEQ;
206         else if (r_stringncmp("<", input,  size))
207                 return RVM_ELESS;
208         else if (r_stringncmp(">", input,  size))
209                 return RVM_EGREAT;
210         else if (r_stringncmp("===", input,  size))
211                 return RVM_EEQ;
212         else if (r_stringncmp("==", input,  size))
213                 return RVM_EEQ;
214         else if (r_stringncmp("!==", input,  size))
215                 return RVM_ENOTEQ;
216         else if (r_stringncmp("!=", input,  size))
217                 return RVM_ENOTEQ;
218         else if (r_stringncmp("!", input,  size))
219                 return RVM_ELNOT;
220         else if (r_stringncmp("~", input,  size))
221                 return RVM_ENOT;
222         else if (r_stringncmp("=", input,  size))
223                 return RVM_NOP;
224
225         return -1;
226 }
227
228
229 rlong rjs_compiler_record2unaryopcode(rparecord_t *prec)
230 {
231         const rchar *input = prec->input;
232         rsize_t size = prec->inputsiz;
233
234         if (r_stringncmp("+", input,  size))
235                 return RVM_NOP;
236         else if (r_stringncmp("-", input,  size))
237                 return RVM_ENEG;
238         else if (r_stringncmp("~", input,  size))
239                 return RVM_ENOT;
240         else if (r_stringncmp("!", input,  size))
241                 return RVM_ELNOT;
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_default(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);
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_default(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_default(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         co->cg->userdata = RJS_COMPILER_CODEGENKEEP;
728         rvm_scope_pop(co->scope);
729         r_array_removelast(co->coctx);
730         return 0;
731
732 error:
733         r_array_removelast(co->coctx);
734         return -1;
735 }
736
737
738 rint rjs_compiler_rh_functionparameter(rjs_compiler_t *co, rarray_t *records, rlong rec)
739 {
740         rjs_coctx_t *ctx = NULL;
741         rjs_coctx_function_t *functx = NULL;
742         rparecord_t *prec;
743         rvm_varmap_t *v;
744
745         prec = (rparecord_t *)r_array_slot(records, rec);
746         rjs_compiler_debughead(co, records, rec);
747         /*
748          * First lets find out if we are within a function definition or
749          * this is a global variable.
750          */
751         ctx = rjs_compiler_getctx(co, RJS_COCTX_FUNCTION);
752         if (!ctx) {
753                 rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTION, prec->input);
754                 return 0;
755         }
756         R_ASSERT(ctx);
757         functx = (rjs_coctx_function_t *)ctx;
758         rjs_compiler_debugtail(co, records, rec);
759
760         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
761                 return -1;
762
763         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
764         prec = (rparecord_t *)r_array_slot(records, rec);
765         rjs_compiler_debughead(co, records, rec);
766         v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
767
768         /*
769          * TBD: Temporary here
770          */
771         if (v) {
772                 r_printf("ERROR: Identifier already defined: %s\n", rjs_compiler_record2str(co, records, rec));
773                 return -1;
774         }
775
776         functx->allocs += 1;
777         rvm_scope_addoffset(co->scope, prec->input, prec->inputsiz, functx->allocs);
778
779         rjs_compiler_debugtail(co, records, rec);
780         return 0;
781 }
782
783
784 rint rjs_compiler_rh_functioncall(rjs_compiler_t *co, rarray_t *records, rlong rec)
785 {
786         rparecord_t *prec;
787         rjs_coctx_functioncall_t ctx;
788
789         r_memset(&ctx, 0, sizeof(ctx));
790         ctx.base.type = RJS_COCTX_FUNCTIONCALL;
791         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
792
793         prec = (rparecord_t *)r_array_slot(records, rec);
794         rjs_compiler_debughead(co, records, rec);
795         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(TP)|BIT(FP)|BIT(SP)|BIT(LR)));
796         rjs_compiler_debugtail(co, records, rec);
797
798         /*
799          * Important: Function call has two children FunctionCallName, Arguments
800          * We evaluate them in reverse order, first we evaluate the Arguments and push them on the
801          * stack, than we evaluate the FunctionCallName -> R0. When we make the call we assume the
802          * result of the FunctionCallName will be in R0.
803          */
804         if (rjs_compiler_playreversechildrecords(co, records, rec) < 0)
805                 goto error;
806
807         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
808         prec = (rparecord_t *)r_array_slot(records, rec);
809         rjs_compiler_debughead(co, records, rec);
810         if (ctx.setthis)
811                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, TP, R1, XX, 0));
812         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUB, FP, SP, DA, ctx.arguments));
813         rvm_codegen_addins(co->cg, rvm_asm(RVM_CALL, R0, XX, XX, 0));
814         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
815         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(TP,LR)));
816         rjs_compiler_debugtail(co, records, rec);
817         r_array_removelast(co->coctx);
818         return 0;
819
820 error:
821         r_array_removelast(co->coctx);
822         return -1;
823 }
824
825
826 rint rjs_compiler_rh_argument(rjs_compiler_t *co, rarray_t *records, rlong rec)
827 {
828         rparecord_t *prec;
829         rjs_coctx_functioncall_t *ctx = (rjs_coctx_functioncall_t *)rjs_compiler_getctx(co, RJS_COCTX_FUNCTIONCALL);
830
831         prec = (rparecord_t *)r_array_slot(records, rec);
832         rjs_compiler_debughead(co, records, rec);
833         if (!ctx) {
834                 rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTIONCALL, prec->input);
835                 return 0;
836         }
837         R_ASSERT(ctx);
838         rjs_compiler_debugtail(co, records, rec);
839
840         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
841                 return -1;
842
843         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
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_PUSH, R0, XX, XX, 0));
847         ctx->arguments += 1;
848         rjs_compiler_debugtail(co, records, rec);
849         return 0;
850 }
851
852
853 rint rjs_compiler_rh_arguments(rjs_compiler_t *co, rarray_t *records, rlong rec)
854 {
855         rparecord_t *prec;
856         rjs_coctx_functioncall_t *ctx = (rjs_coctx_functioncall_t *)rjs_compiler_getctx(co, RJS_COCTX_FUNCTIONCALL);
857
858         prec = (rparecord_t *)r_array_slot(records, rec);
859         rjs_compiler_debughead(co, records, rec);
860         if (!ctx) {
861                 rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTIONCALL, prec->input);
862                 return 0;
863         }
864         R_ASSERT(ctx);
865         rjs_compiler_debugtail(co, records, rec);
866
867         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
868                 return -1;
869
870         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
871         prec = (rparecord_t *)r_array_slot(records, rec);
872         rjs_compiler_debughead(co, records, rec);
873         rjs_compiler_debugtail(co, records, rec);
874         return 0;
875 }
876
877
878 rint rjs_compiler_rh_returnstatement(rjs_compiler_t *co, rarray_t *records, rlong rec)
879 {
880         rparecord_t *prec;
881         prec = (rparecord_t *)r_array_slot(records, rec);
882         rjs_compiler_debughead(co, records, rec);
883         rjs_compiler_debugtail(co, records, rec);
884
885         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
886                 return -1;
887
888         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
889         prec = (rparecord_t *)r_array_slot(records, rec);
890         rjs_compiler_debughead(co, records, rec);
891         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
892         rjs_compiler_debugtail(co, records, rec);
893         return 0;
894 }
895
896
897 rint rjs_compiler_rh_ifstatement(rjs_compiler_t *co, rarray_t *records, rlong rec)
898 {
899         rparecord_t *prec;
900         rjs_coctx_ifstatement_t ctx;
901
902         r_memset(&ctx, 0, sizeof(ctx));
903         ctx.base.type = RJS_COCTX_IFSTATEMENT;
904         ctx.start = rvm_codegen_getcodesize(co->cg);
905         ctx.trueidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__iftrue", ctx.start);
906         ctx.falseidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__iffalse", ctx.start);
907         ctx.endidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__ifend", ctx.start);
908         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
909         prec = (rparecord_t *)r_array_slot(records, rec);
910         rjs_compiler_debughead(co, records, rec);
911         rjs_compiler_debugtail(co, records, rec);
912
913         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
914                 goto error;
915
916         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
917         prec = (rparecord_t *)r_array_slot(records, rec);
918         rjs_compiler_debughead(co, records, rec);
919         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
920         if (!rvm_codegen_validlabel(co->cg, ctx.falseidx))
921                 rvm_codegen_redefinelabel_default(co->cg, ctx.falseidx);
922         rjs_compiler_debugtail(co, records, rec);
923
924         r_array_removelast(co->coctx);
925         return 0;
926
927 error:
928         r_array_removelast(co->coctx);
929         return -1;
930 }
931
932
933 rint rjs_compiler_rh_ifconditionop(rjs_compiler_t *co, rarray_t *records, rlong rec)
934 {
935         rparecord_t *prec;
936         rjs_coctx_ifstatement_t *ctx = (rjs_coctx_ifstatement_t *)rjs_compiler_getctx(co, RJS_COCTX_IFSTATEMENT);
937
938         prec = (rparecord_t *)r_array_slot(records, rec);
939         rjs_compiler_debughead(co, records, rec);
940         if (!ctx) {
941                 rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec->input);
942                 return 0;
943         }
944         R_ASSERT(ctx);
945         rjs_compiler_debugtail(co, records, rec);
946         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
947                 return -1;
948         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
949         prec = (rparecord_t *)r_array_slot(records, rec);
950         rjs_compiler_debughead(co, records, rec);
951         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->falseidx, rvm_asm(RVM_BEQ, DA, XX, XX, 0));
952         rjs_compiler_debugtail(co, records, rec);
953         return 0;
954 }
955
956
957 rint rjs_compiler_rh_iftruestatement(rjs_compiler_t *co, rarray_t *records, rlong rec)
958 {
959         rparecord_t *prec;
960         rjs_coctx_ifstatement_t *ctx = (rjs_coctx_ifstatement_t *)rjs_compiler_getctx(co, RJS_COCTX_IFSTATEMENT);
961
962         prec = (rparecord_t *)r_array_slot(records, rec);
963         rjs_compiler_debughead(co, records, rec);
964         if (!ctx) {
965                 rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec->input);
966                 return 0;
967         }
968         R_ASSERT(ctx);
969         rjs_compiler_debugtail(co, records, rec);
970
971         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
972                 return -1;
973
974         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
975         prec = (rparecord_t *)r_array_slot(records, rec);
976         rjs_compiler_debughead(co, records, rec);
977         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_B, DA, XX, XX, 0));
978         rjs_compiler_debugtail(co, records, rec);
979         return 0;
980 }
981
982
983 rint rjs_compiler_rh_iffalsestatement(rjs_compiler_t *co, rarray_t *records, rlong rec)
984 {
985         rparecord_t *prec;
986         rjs_coctx_ifstatement_t *ctx = (rjs_coctx_ifstatement_t *)rjs_compiler_getctx(co, RJS_COCTX_IFSTATEMENT);
987
988         prec = (rparecord_t *)r_array_slot(records, rec);
989         rjs_compiler_debughead(co, records, rec);
990         if (!ctx) {
991                 rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec->input);
992                 return 0;
993         }
994         R_ASSERT(ctx);
995         rvm_codegen_redefinelabel_default(co->cg, ctx->falseidx);
996         rjs_compiler_debugtail(co, records, rec);
997
998         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
999                 return -1;
1000
1001         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1002         prec = (rparecord_t *)r_array_slot(records, rec);
1003         rjs_compiler_debughead(co, records, rec);
1004         rjs_compiler_debugtail(co, records, rec);
1005         return 0;
1006 }
1007
1008
1009 rint rjs_compiler_rh_iterationfor(rjs_compiler_t *co, rarray_t *records, rlong rec)
1010 {
1011         rlong childrec;
1012         rparecord_t *prec;
1013         rjs_coctx_iteration_t ctx;
1014
1015         r_memset(&ctx, 0, sizeof(ctx));
1016         ctx.base.type = RJS_COCTX_ITERATION;
1017         ctx.start = rvm_codegen_getcodesize(co->cg);
1018         ctx.iterationidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__iteration", ctx.start);
1019         ctx.continueidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__continue", ctx.start);
1020         ctx.endidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__end", ctx.start);
1021         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1022         rvm_scope_push(co->scope);
1023
1024         prec = (rparecord_t *)r_array_slot(records, rec);
1025         rjs_compiler_debughead(co, records, rec);
1026         rjs_compiler_debugtail(co, records, rec);
1027
1028         for (childrec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); childrec >= 0; childrec = rpa_recordtree_next(records, childrec, RPA_RECORD_START)) {
1029                 if (rpa_record_getruleuid(records, childrec) == UID_FOREXPRESSIONINIT) {
1030                         if (rjs_compiler_playrecord(co, records, childrec) < 0)
1031                                 goto error;
1032                         break;
1033                 }
1034         }
1035
1036         rvm_codegen_redefinelabel_default(co->cg, ctx.iterationidx);
1037         for (childrec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); childrec >= 0; childrec = rpa_recordtree_next(records, childrec, RPA_RECORD_START)) {
1038                 if (rpa_record_getruleuid(records, childrec) == UID_FOREXPRESSIONCOMPARE) {
1039                         if (rjs_compiler_playrecord(co, records, childrec) < 0)
1040                                 goto error;
1041                         break;
1042                 }
1043         }
1044
1045         for (childrec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); childrec >= 0; childrec = rpa_recordtree_next(records, childrec, RPA_RECORD_START)) {
1046                 if (rpa_record_getruleuid(records, childrec) == UID_FORITERATIONSTATEMENT) {
1047                         if (rjs_compiler_playrecord(co, records, childrec) < 0)
1048                                 goto error;
1049                         break;
1050                 }
1051         }
1052
1053         rvm_codegen_redefinelabel_default(co->cg, ctx.continueidx);
1054         for (childrec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); childrec >= 0; childrec = rpa_recordtree_next(records, childrec, RPA_RECORD_START)) {
1055                 if (rpa_record_getruleuid(records, childrec) == UID_FOREXPRESSIONINCREMENT) {
1056                         if (rjs_compiler_playrecord(co, records, childrec) < 0)
1057                                 goto error;
1058                         break;
1059                 }
1060         }
1061
1062         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1063         prec = (rparecord_t *)r_array_slot(records, rec);
1064         rjs_compiler_debughead(co, records, rec);
1065         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1066         rjs_compiler_debugtail(co, records, rec);
1067
1068         rvm_scope_pop(co->scope);
1069         r_array_removelast(co->coctx);
1070         return 0;
1071
1072 error:
1073         rvm_scope_pop(co->scope);
1074         r_array_removelast(co->coctx);
1075         return -1;
1076 }
1077
1078
1079 rint rjs_compiler_rh_iterationwhile(rjs_compiler_t *co, rarray_t *records, rlong rec)
1080 {
1081         rparecord_t *prec;
1082         rjs_coctx_iteration_t ctx;
1083
1084         r_memset(&ctx, 0, sizeof(ctx));
1085         ctx.base.type = RJS_COCTX_ITERATION;
1086         ctx.start = rvm_codegen_getcodesize(co->cg);
1087         ctx.iterationidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__iteration", ctx.start);
1088         ctx.continueidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__continue", ctx.start);
1089         ctx.endidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__end", ctx.start);
1090         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1091         rvm_scope_push(co->scope);
1092
1093         prec = (rparecord_t *)r_array_slot(records, rec);
1094         rjs_compiler_debughead(co, records, rec);
1095         rjs_compiler_debugtail(co, records, rec);
1096
1097
1098         rvm_codegen_redefinelabel_default(co->cg, ctx.iterationidx);
1099         rvm_codegen_redefinelabel_default(co->cg, ctx.continueidx);
1100
1101         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1102                 goto error;
1103
1104         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1105         prec = (rparecord_t *)r_array_slot(records, rec);
1106         rjs_compiler_debughead(co, records, rec);
1107         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx.iterationidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1108         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1109         rjs_compiler_debugtail(co, records, rec);
1110
1111         rvm_scope_pop(co->scope);
1112         r_array_removelast(co->coctx);
1113         return 0;
1114
1115 error:
1116         rvm_scope_pop(co->scope);
1117         r_array_removelast(co->coctx);
1118         return -1;
1119 }
1120
1121
1122 rint rjs_compiler_rh_iterationdo(rjs_compiler_t *co, rarray_t *records, rlong rec)
1123 {
1124         rparecord_t *prec;
1125         rjs_coctx_iteration_t ctx;
1126
1127         r_memset(&ctx, 0, sizeof(ctx));
1128         ctx.base.type = RJS_COCTX_ITERATION;
1129         ctx.start = rvm_codegen_getcodesize(co->cg);
1130         ctx.iterationidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__iteration", ctx.start);
1131         ctx.continueidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__continue", ctx.start);
1132         ctx.endidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__end", ctx.start);
1133         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1134         rvm_scope_push(co->scope);
1135
1136         prec = (rparecord_t *)r_array_slot(records, rec);
1137         rjs_compiler_debughead(co, records, rec);
1138         rjs_compiler_debugtail(co, records, rec);
1139
1140
1141         rvm_codegen_redefinelabel_default(co->cg, ctx.iterationidx);
1142
1143         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1144                 goto error;
1145
1146         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1147         prec = (rparecord_t *)r_array_slot(records, rec);
1148         rjs_compiler_debughead(co, records, rec);
1149         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx.iterationidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1150         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1151         rjs_compiler_debugtail(co, records, rec);
1152
1153         rvm_scope_pop(co->scope);
1154         r_array_removelast(co->coctx);
1155         return 0;
1156
1157 error:
1158         rvm_scope_pop(co->scope);
1159         r_array_removelast(co->coctx);
1160         return -1;
1161 }
1162
1163
1164 rint rjs_compiler_rh_dowhileexpressioncompare(rjs_compiler_t *co, rarray_t *records, rlong rec)
1165 {
1166         rparecord_t *prec;
1167         rjs_coctx_iteration_t *ctx = (rjs_coctx_iteration_t *)rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1168
1169         prec = (rparecord_t *)r_array_slot(records, rec);
1170         rjs_compiler_debughead(co, records, rec);
1171         if (!ctx) {
1172                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input);
1173                 return 0;
1174         }
1175         R_ASSERT(ctx);
1176         rvm_codegen_redefinelabel_default(co->cg, ctx->continueidx);
1177         rjs_compiler_debugtail(co, records, rec);
1178
1179         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1180                 return -1;
1181
1182         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1183         prec = (rparecord_t *)r_array_slot(records, rec);
1184         rjs_compiler_debughead(co, records, rec);
1185         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_BEQ, DA, XX, XX, 0));
1186         rjs_compiler_debugtail(co, records, rec);
1187         return 0;
1188 }
1189
1190
1191 rint rjs_compiler_rh_forexpressioncompare(rjs_compiler_t *co, rarray_t *records, rlong rec)
1192 {
1193         rparecord_t *prec;
1194         rjs_coctx_iteration_t *ctx = (rjs_coctx_iteration_t *)rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1195
1196         prec = (rparecord_t *)r_array_slot(records, rec);
1197         rjs_compiler_debughead(co, records, rec);
1198         if (!ctx) {
1199                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input);
1200                 return 0;
1201         }
1202         R_ASSERT(ctx);
1203         rjs_compiler_debugtail(co, records, rec);
1204
1205         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1206                 return -1;
1207
1208         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1209         prec = (rparecord_t *)r_array_slot(records, rec);
1210         rjs_compiler_debughead(co, records, rec);
1211         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_BEQ, DA, XX, XX, 0));
1212         rjs_compiler_debugtail(co, records, rec);
1213         return 0;
1214 }
1215
1216
1217 rint rjs_compiler_rh_forexpressionincrement(rjs_compiler_t *co, rarray_t *records, rlong rec)
1218 {
1219         rparecord_t *prec;
1220         rjs_coctx_iteration_t *ctx = (rjs_coctx_iteration_t *)rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1221
1222         prec = (rparecord_t *)r_array_slot(records, rec);
1223         rjs_compiler_debughead(co, records, rec);
1224         if (!ctx) {
1225                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input);
1226                 return 0;
1227         }
1228         R_ASSERT(ctx);
1229         rjs_compiler_debugtail(co, records, rec);
1230
1231         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1232                 return -1;
1233
1234         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1235         prec = (rparecord_t *)r_array_slot(records, rec);
1236         rjs_compiler_debughead(co, records, rec);
1237         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->iterationidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1238         rjs_compiler_debugtail(co, records, rec);
1239         return 0;
1240 }
1241
1242
1243 rint rjs_compiler_rh_postfixexpressionop(rjs_compiler_t *co, rarray_t *records, rlong rec)
1244 {
1245         rparecord_t *prec;
1246         rlong opcode;
1247         rlong opcoderec;
1248
1249         if ((opcoderec = rpa_recordtree_lastchild(records, rec, RPA_RECORD_END)) < 0)
1250                 return -1;
1251         opcode = rjs_compiler_record2opcode((rparecord_t *)r_array_slot(records, opcoderec));
1252         prec = (rparecord_t *)r_array_slot(records, rec);
1253         rjs_compiler_debughead(co, records, rec);
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_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
1263         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R1, XX, 0));
1264         rvm_codegen_addins(co->cg, rvm_asm(opcode, R2, R0, DA, 1));
1265         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R2, R1, XX, 0));
1266
1267         rjs_compiler_debugtail(co, records, rec);
1268         return 0;
1269 }
1270
1271
1272 rint rjs_compiler_rh_prefixexpressionop(rjs_compiler_t *co, rarray_t *records, rlong rec)
1273 {
1274         rparecord_t *prec;
1275         rlong opcode;
1276         rlong opcoderec;
1277
1278         if ((opcoderec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_END)) < 0)
1279                 return -1;
1280         opcode = rjs_compiler_record2opcode((rparecord_t *)r_array_slot(records, opcoderec));
1281
1282         prec = (rparecord_t *)r_array_slot(records, rec);
1283         rjs_compiler_debughead(co, records, rec);
1284         rjs_compiler_debugtail(co, records, rec);
1285
1286         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1287                 return -1;
1288
1289         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1290         prec = (rparecord_t *)r_array_slot(records, rec);
1291         rjs_compiler_debughead(co, records, rec);
1292         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R0, XX, 0));
1293         rvm_codegen_addins(co->cg, rvm_asm(opcode, R0, R0, DA, 1));
1294         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
1295         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
1296
1297         rjs_compiler_debugtail(co, records, rec);
1298         return 0;
1299 }
1300
1301
1302 rint rjs_compiler_rh_newexpressioncall(rjs_compiler_t *co, rarray_t *records, rlong rec)
1303 {
1304         rparecord_t *prec;
1305         rjs_coctx_functioncall_t ctx;
1306
1307         r_memset(&ctx, 0, sizeof(ctx));
1308         ctx.base.type = RJS_COCTX_FUNCTIONCALL;
1309         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1310
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_PUSHM, DA, XX, XX, BIT(TP)|BIT(FP)|BIT(SP)|BIT(LR)));
1314         rjs_compiler_debugtail(co, records, rec);
1315
1316         /*
1317          * Important: Function call has two children FunctionCallName, Arguments
1318          * We evaluate them in reverse order, first we evaluate the Arguments and push them on the
1319          * stack, than we evaluate the FunctionCallName -> R0. When we make the call we assume the
1320          * result of the FunctionCallName will be in R0.
1321          */
1322         if (rjs_compiler_playreversechildrecords(co, records, rec) < 0)
1323                 goto error;
1324
1325         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1326         prec = (rparecord_t *)r_array_slot(records, rec);
1327         rjs_compiler_debughead(co, records, rec);
1328         rvm_codegen_addins(co->cg, rvm_asm(RVM_ALLOCOBJ, TP, DA, XX, 0));
1329         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUB, FP, SP, DA, ctx.arguments));
1330         rvm_codegen_addins(co->cg, rvm_asm(RVM_CALL, R0, XX, XX, 0));
1331         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
1332         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, TP, XX, 0));
1333         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(TP,LR)));
1334         rjs_compiler_debugtail(co, records, rec);
1335         r_array_removelast(co->coctx);
1336         return 0;
1337
1338 error:
1339         r_array_removelast(co->coctx);
1340         return -1;
1341 }
1342
1343
1344 rint rjs_compiler_rh_this(rjs_compiler_t *co, rarray_t *records, rlong rec)
1345 {
1346         rparecord_t *prec;
1347         prec = (rparecord_t *)r_array_slot(records, rec);
1348         rjs_compiler_debughead(co, records, rec);
1349         rjs_compiler_debugtail(co, records, rec);
1350
1351         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1352                 return -1;
1353
1354         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1355         prec = (rparecord_t *)r_array_slot(records, rec);
1356         rjs_compiler_debughead(co, records, rec);
1357         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, TP, XX, 0));
1358         rjs_compiler_debugtail(co, records, rec);
1359         return 0;
1360 }
1361
1362
1363 rint rjs_compiler_rh_binaryoperator(rjs_compiler_t *co, rarray_t *records, rlong rec)
1364 {
1365         rparecord_t *prec;
1366         rjs_coctx_t *ctx = rjs_compiler_gettopctx(co);
1367
1368         prec = (rparecord_t *)r_array_slot(records, rec);
1369         rjs_compiler_debughead(co, records, rec);
1370         rjs_compiler_debugtail(co, records, rec);
1371
1372         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1373                 return -1;
1374
1375         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1376         prec = (rparecord_t *)r_array_slot(records, rec);
1377         rjs_compiler_debughead(co, records, rec);
1378         if (ctx && ctx->type == RJS_COCTX_OPERATION)
1379                 ((rjs_coctx_operation_t *)ctx)->opcode = rjs_compiler_record2opcode(prec);
1380         rjs_compiler_debugtail(co, records, rec);
1381         return 0;
1382 }
1383
1384
1385 rint rjs_compiler_rh_unaryoperator(rjs_compiler_t *co, rarray_t *records, rlong rec)
1386 {
1387         rparecord_t *prec;
1388         rjs_coctx_t *ctx = rjs_compiler_gettopctx(co);
1389
1390         prec = (rparecord_t *)r_array_slot(records, rec);
1391         rjs_compiler_debughead(co, records, rec);
1392         rjs_compiler_debugtail(co, records, rec);
1393
1394         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1395                 return -1;
1396
1397         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1398         prec = (rparecord_t *)r_array_slot(records, rec);
1399         rjs_compiler_debughead(co, records, rec);
1400         if (ctx && ctx->type == RJS_COCTX_OPERATION)
1401                 ((rjs_coctx_operation_t *)ctx)->opcode = rjs_compiler_record2unaryopcode(prec);
1402         rjs_compiler_debugtail(co, records, rec);
1403         return 0;
1404 }
1405
1406
1407 rint rjs_compiler_rh_identifiername(rjs_compiler_t *co, rarray_t *records, rlong rec)
1408 {
1409         rparecord_t *prec;
1410         prec = (rparecord_t *)r_array_slot(records, rec);
1411         rjs_compiler_debughead(co, records, rec);
1412         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, prec->inputsiz));
1413         rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R2, DA, XX, (void*)prec->input));
1414         rjs_compiler_debugtail(co, records, rec);
1415
1416         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1417                 return -1;
1418
1419         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1420         prec = (rparecord_t *)r_array_slot(records, rec);
1421         rjs_compiler_debughead(co, records, rec);
1422         rjs_compiler_debugtail(co, records, rec);
1423         return 0;
1424 }
1425
1426
1427 rint rjs_compiler_rh_continue(rjs_compiler_t *co, rarray_t *records, rlong rec)
1428 {
1429         rparecord_t *prec;
1430         rjs_coctx_t *ctx;
1431         rjs_coctx_iteration_t *iterctx;
1432
1433         ctx = rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1434         prec = (rparecord_t *)r_array_slot(records, rec);
1435         rjs_compiler_debughead(co, records, rec);
1436         if (!ctx) {
1437                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input);
1438                 return 0;
1439         }
1440         R_ASSERT(ctx);
1441         iterctx = (rjs_coctx_iteration_t *)ctx;
1442         rjs_compiler_debugtail(co, records, rec);
1443
1444         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1445                 return -1;
1446
1447         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1448         prec = (rparecord_t *)r_array_slot(records, rec);
1449         rjs_compiler_debughead(co, records, rec);
1450         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, iterctx->continueidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1451         rjs_compiler_debugtail(co, records, rec);
1452         return 0;
1453 }
1454
1455
1456 rint rjs_compiler_rh_break(rjs_compiler_t *co, rarray_t *records, rlong rec)
1457 {
1458         rparecord_t *prec;
1459         rjs_coctx_t *ctx;
1460         rjs_coctx_iteration_t *iterctx;
1461
1462
1463         ctx = rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1464         prec = (rparecord_t *)r_array_slot(records, rec);
1465         rjs_compiler_debughead(co, records, rec);
1466         if (!ctx) {
1467                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input);
1468                 return 0;
1469         }
1470         R_ASSERT(ctx);
1471         iterctx = (rjs_coctx_iteration_t *)ctx;
1472         rjs_compiler_debugtail(co, records, rec);
1473
1474         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1475                 return -1;
1476
1477         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1478         prec = (rparecord_t *)r_array_slot(records, rec);
1479         rjs_compiler_debughead(co, records, rec);
1480         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, iterctx->endidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1481         rjs_compiler_debugtail(co, records, rec);
1482         return 0;
1483 }
1484
1485
1486 rint rjs_compiler_rh_syntaxerror(rjs_compiler_t *co, rarray_t *records, rlong rec)
1487 {
1488         rparecord_t *prec;
1489         prec = (rparecord_t *)r_array_slot(records, rec);
1490         rjs_compiler_debughead(co, records, rec);
1491         rjs_compiler_debugtail(co, records, rec);
1492
1493         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1494                 return -1;
1495
1496         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1497         prec = (rparecord_t *)r_array_slot(records, rec);
1498         rjs_compiler_debughead(co, records, rec);
1499         rjs_compiler_adderror(co, RJS_ERROR_SYNTAX, prec->input);
1500         rjs_compiler_debugtail(co, records, rec);
1501         return 0;
1502 }
1503
1504
1505 rint rjs_compiler_rh_(rjs_compiler_t *co, rarray_t *records, rlong rec)
1506 {
1507         rparecord_t *prec;
1508         prec = (rparecord_t *)r_array_slot(records, rec);
1509         rjs_compiler_debughead(co, records, rec);
1510         rjs_compiler_debugtail(co, records, rec);
1511
1512         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1513                 return -1;
1514
1515         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1516         prec = (rparecord_t *)r_array_slot(records, rec);
1517         rjs_compiler_debughead(co, records, rec);
1518         rjs_compiler_debugtail(co, records, rec);
1519         return 0;
1520 }
1521
1522
1523 rjs_compiler_t *rjs_compiler_create(rvmcpu_t *cpu)
1524 {
1525         rjs_compiler_t *co = (rjs_compiler_t *) r_zmalloc(sizeof(*co));
1526
1527         co->scope = rvm_scope_create();
1528         co->coctx = r_array_create(sizeof(rjs_coctx_t *));
1529         co->cpu = cpu;
1530         r_memset(co->handlers, 0, sizeof(co->handlers));
1531
1532         co->handlers[UID_PROGRAM] = rjs_compiler_rh_program;
1533         co->handlers[UID_EXPRESSION] = rjs_compiler_rh_expression;
1534         co->handlers[UID_LEFTHANDSIDEEXPRESSION] = rjs_compiler_rh_lefthandsideexpression;
1535         co->handlers[UID_LEFTHANDSIDEEXPRESSIONADDR] = rjs_compiler_rh_lefthandsideexpressionaddr;
1536         co->handlers[UID_DECIMALINTEGERLITERAL] = rjs_compiler_rh_decimalintegerliteral;
1537         co->handlers[UID_DECIMALNONINTEGERLITERAL] = rjs_compiler_rh_decimalnonintegerliteral;
1538         co->handlers[UID_STRINGCHARACTERS] = rjs_compiler_rh_stringcharacters;
1539         co->handlers[UID_ADDITIVEEXPRESSIONOP] = rjs_compiler_rh_binaryexpressionop;
1540         co->handlers[UID_MULTIPLICATIVEEXPRESSIONOP] = rjs_compiler_rh_binaryexpressionop;
1541         co->handlers[UID_BITWISEANDOP] = rjs_compiler_rh_binaryexpressionop;
1542         co->handlers[UID_BITWISEXOROP] = rjs_compiler_rh_binaryexpressionop;
1543         co->handlers[UID_BITWISEOROP] = rjs_compiler_rh_binaryexpressionop;
1544         co->handlers[UID_SHIFTEXPRESSIONOP] = rjs_compiler_rh_binaryexpressionop;
1545         co->handlers[UID_EQUALITYEXPRESSIONOP] = rjs_compiler_rh_binaryexpressionop;
1546         co->handlers[UID_RELATIONALEXPRESSIONOP] = rjs_compiler_rh_binaryexpressionop;
1547         co->handlers[UID_LOGICALOROP] = rjs_compiler_rh_binaryexpressionop;
1548         co->handlers[UID_LOGICALANDOP] = rjs_compiler_rh_binaryexpressionop;
1549         co->handlers[UID_VARIABLEALLOCATEANDINIT] = rjs_compiler_rh_varallocinit;
1550         co->handlers[UID_VARIABLEALLOCATE] = rjs_compiler_rh_varalloc;
1551         co->handlers[UID_IDENTIFIER] = rjs_compiler_rh_identifier;
1552         co->handlers[UID_IDENTIFIERNAME] = rjs_compiler_rh_identifiername;
1553         co->handlers[UID_INITIALISER] = rjs_compiler_rh_initializer;
1554         co->handlers[UID_ASSIGNMENTEXPRESSIONOP] = rjs_compiler_rh_assignmentexpressionop;
1555         co->handlers[UID_NEWARRAYEXPRESSION] = rjs_compiler_rh_newarrayexpression;
1556         co->handlers[UID_MEMBEREXPRESSIONDOTOP] = rjs_compiler_rh_memberexpressiondotop;
1557         co->handlers[UID_MEMBEREXPRESSIONINDEXOP] = rjs_compiler_rh_memberexpressionindexop;
1558         co->handlers[UID_FUNCTIONDECLARATION] = rjs_compiler_rh_functiondeclaration;
1559         co->handlers[UID_FUNCTIONEXPRESSION] = rjs_compiler_rh_functiondeclaration;
1560         co->handlers[UID_FUNCTIONPARAMETER] = rjs_compiler_rh_functionparameter;
1561         co->handlers[UID_FUNCTIONCALL] = rjs_compiler_rh_functioncall;
1562         co->handlers[UID_ARGUMENT] = rjs_compiler_rh_argument;
1563         co->handlers[UID_ARGUMENTS] = rjs_compiler_rh_arguments;
1564         co->handlers[UID_RETURNSTATEMENT] = rjs_compiler_rh_returnstatement;
1565         co->handlers[UID_STRINGCHARACTERS] = rjs_compiler_rh_stringcharacters;
1566         co->handlers[UID_IFSTATEMENT] = rjs_compiler_rh_ifstatement;
1567         co->handlers[UID_IFCONDITIONOP] = rjs_compiler_rh_ifconditionop;
1568         co->handlers[UID_IFTRUESTATEMENT] = rjs_compiler_rh_iftruestatement;
1569         co->handlers[UID_IFFALSESTATEMENT] = rjs_compiler_rh_iffalsestatement;
1570         co->handlers[UID_ITERATIONDO] = rjs_compiler_rh_iterationdo;
1571         co->handlers[UID_ITERATIONWHILE] = rjs_compiler_rh_iterationwhile;
1572         co->handlers[UID_ITERATIONFOR] = rjs_compiler_rh_iterationfor;
1573         co->handlers[UID_DOWHILEEXPRESSIONCOMPARE] = rjs_compiler_rh_dowhileexpressioncompare;
1574         co->handlers[UID_WHILEEXPRESSIONCOMPARE] = rjs_compiler_rh_forexpressioncompare;
1575         co->handlers[UID_FOREXPRESSIONCOMPARE] = rjs_compiler_rh_forexpressioncompare;
1576         co->handlers[UID_FOREXPRESSIONINCREMENT] = rjs_compiler_rh_forexpressionincrement;
1577         co->handlers[UID_POSTFIXEXPRESSIONOP] = rjs_compiler_rh_postfixexpressionop;
1578         co->handlers[UID_PREFIXEXPRESSIONOP] = rjs_compiler_rh_prefixexpressionop;
1579         co->handlers[UID_THIS] = rjs_compiler_rh_this;
1580         co->handlers[UID_NEWEXPRESSIONCALL] = rjs_compiler_rh_newexpressioncall;
1581         co->handlers[UID_UNARYEXPRESSIONOP] = rjs_compiler_rh_unaryexpressionop;
1582         co->handlers[UID_BINARYOPERATOR] = rjs_compiler_rh_binaryoperator;
1583         co->handlers[UID_UNARYOPERATOR] = rjs_compiler_rh_unaryoperator;
1584         co->handlers[UID_BREAKSTATEMENT] = rjs_compiler_rh_break;
1585         co->handlers[UID_CONTINUESTATEMENT] = rjs_compiler_rh_continue;
1586         co->handlers[UID_SYNTAXERROR] = rjs_compiler_rh_syntaxerror;
1587
1588         return co;
1589 }
1590
1591
1592 void rjs_compiler_destroy(rjs_compiler_t *co)
1593 {
1594         if (co) {
1595                 rvm_scope_destroy(co->scope);
1596                 r_array_destroy(co->coctx);
1597                 r_free(co->temp);
1598                 co->cpu = NULL;
1599                 r_free(co);
1600         }
1601 }
1602
1603
1604 static rint rjs_compiler_rh_default(rjs_compiler_t *co, rarray_t *records, rlong rec)
1605 {
1606         rparecord_t *prec;
1607
1608         prec = (rparecord_t *)r_array_slot(records, rec);
1609         rjs_compiler_debughead(co, records, rec);
1610         rjs_compiler_debugtail(co, records, rec);
1611
1612         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1613                 return -1;
1614
1615         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1616         prec = (rparecord_t *)r_array_slot(records, rec);
1617         rjs_compiler_debughead(co, records, rec);
1618         rjs_compiler_debugtail(co, records, rec);
1619
1620         return 0;
1621 }
1622
1623
1624 static rint rjs_compiler_playchildrecords(rjs_compiler_t *co, rarray_t *records, rlong rec)
1625 {
1626         rlong child;
1627
1628         for (child = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); child >= 0; child = rpa_recordtree_next(records, child, RPA_RECORD_START)) {
1629                 if (rjs_compiler_playrecord(co, records, child) < 0)
1630                         return -1;
1631         }
1632
1633         return 0;
1634 }
1635
1636
1637 rint rjs_compiler_playreversechildrecords(rjs_compiler_t *co, rarray_t *records, rlong rec)
1638 {
1639         rlong child;
1640
1641         for (child = rpa_recordtree_lastchild(records, rec, RPA_RECORD_START); child >= 0; child = rpa_recordtree_prev(records, child, RPA_RECORD_START)) {
1642                 if (rjs_compiler_playrecord(co, records, child) < 0)
1643                         return -1;
1644         }
1645
1646         return 0;
1647 }
1648
1649
1650 static rint rjs_compiler_playrecord(rjs_compiler_t *co, rarray_t *records, rlong rec)
1651 {
1652         rparecord_t *prec;
1653         prec = (rparecord_t *)r_array_slot(records, rec);
1654         if (prec->ruleuid >= 0 && prec->ruleuid < RJS_COMPILER_NHANDLERS && co->handlers[prec->ruleuid]) {
1655                 return co->handlers[prec->ruleuid](co, records, rec);
1656         }
1657         return rjs_compiler_rh_default(co, records, rec);
1658 }
1659
1660
1661 rint rjs_compiler_compile(rjs_compiler_t *co, rarray_t *records, rvm_codegen_t *cg)
1662 {
1663         rlong i;
1664         rvm_codelabel_t *labelerr;
1665
1666         if (!co || !records || !cg || r_array_empty(records)) {
1667                 /*
1668                  * TBD
1669                  */
1670                 return -1;
1671         }
1672         co->cg = cg;
1673
1674         for (i = 0; i >= 0; i = rpa_recordtree_next(records, i, RPA_RECORD_START)) {
1675                 if (rjs_compiler_playrecord(co, records, i) < 0)
1676                         /*
1677                          * TBD
1678                          */
1679                         return -1;
1680         }
1681
1682         if (rvm_codegen_relocate(co->cg, &labelerr) < 0) {
1683                 /*
1684                  * TBD
1685                  */
1686                 return -1;
1687         }
1688
1689         return 0;
1690 }