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