RPA Toolkit
reverted back to the original function declaration implementation
[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         rvm_scope_pop(co->scope);
730         r_array_removelast(co->coctx);
731         return 0;
732
733 error:
734         r_array_removelast(co->coctx);
735         return -1;
736 }
737
738
739 rint rjs_compiler_rh_functionparameter(rjs_compiler_t *co, rarray_t *records, rlong rec)
740 {
741         rjs_coctx_t *ctx = NULL;
742         rjs_coctx_function_t *functx = NULL;
743         rparecord_t *prec;
744         rvm_varmap_t *v;
745
746         prec = (rparecord_t *)r_array_slot(records, rec);
747         rjs_compiler_debughead(co, records, rec);
748         /*
749          * First lets find out if we are within a function definition or
750          * this is a global variable.
751          */
752         ctx = rjs_compiler_getctx(co, RJS_COCTX_FUNCTION);
753         if (!ctx) {
754                 rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTION, prec->input, prec->inputsiz);
755                 return 0;
756         }
757         R_ASSERT(ctx);
758         functx = (rjs_coctx_function_t *)ctx;
759         rjs_compiler_debugtail(co, records, rec);
760
761         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
762                 return -1;
763
764         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
765         prec = (rparecord_t *)r_array_slot(records, rec);
766         rjs_compiler_debughead(co, records, rec);
767         v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
768
769         /*
770          * TBD: Temporary here
771          */
772         if (v) {
773                 r_printf("ERROR: Identifier already defined: %s\n", rjs_compiler_record2str(co, records, rec));
774                 return -1;
775         }
776
777         functx->allocs += 1;
778         rvm_scope_addoffset(co->scope, prec->input, prec->inputsiz, functx->allocs);
779
780         rjs_compiler_debugtail(co, records, rec);
781         return 0;
782 }
783
784
785 rint rjs_compiler_rh_functioncall(rjs_compiler_t *co, rarray_t *records, rlong rec)
786 {
787         rparecord_t *prec;
788         rjs_coctx_functioncall_t ctx;
789
790         r_memset(&ctx, 0, sizeof(ctx));
791         ctx.base.type = RJS_COCTX_FUNCTIONCALL;
792         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
793
794         prec = (rparecord_t *)r_array_slot(records, rec);
795         rjs_compiler_debughead(co, records, rec);
796         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(TP)|BIT(FP)|BIT(SP)|BIT(LR)));
797         rjs_compiler_debugtail(co, records, rec);
798
799         /*
800          * Important: Function call has two children FunctionCallName, Arguments
801          * We evaluate them in reverse order, first we evaluate the Arguments and push them on the
802          * stack, than we evaluate the FunctionCallName -> R0. When we make the call we assume the
803          * result of the FunctionCallName will be in R0.
804          */
805         if (rjs_compiler_playreversechildrecords(co, records, rec) < 0)
806                 goto error;
807
808         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
809         prec = (rparecord_t *)r_array_slot(records, rec);
810         rjs_compiler_debughead(co, records, rec);
811         if (ctx.setthis)
812                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, TP, R1, XX, 0));
813         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUB, FP, SP, DA, ctx.arguments));
814         rvm_codegen_addins(co->cg, rvm_asm(RVM_CALL, R0, XX, XX, 0));
815         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
816         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(TP,LR)));
817         rjs_compiler_debugtail(co, records, rec);
818         r_array_removelast(co->coctx);
819         return 0;
820
821 error:
822         r_array_removelast(co->coctx);
823         return -1;
824 }
825
826
827 rint rjs_compiler_rh_argument(rjs_compiler_t *co, rarray_t *records, rlong rec)
828 {
829         rparecord_t *prec;
830         rjs_coctx_functioncall_t *ctx = (rjs_coctx_functioncall_t *)rjs_compiler_getctx(co, RJS_COCTX_FUNCTIONCALL);
831
832         prec = (rparecord_t *)r_array_slot(records, rec);
833         rjs_compiler_debughead(co, records, rec);
834         if (!ctx) {
835                 rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTIONCALL, prec->input, prec->inputsiz);
836                 return 0;
837         }
838         R_ASSERT(ctx);
839         rjs_compiler_debugtail(co, records, rec);
840
841         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
842                 return -1;
843
844         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
845         prec = (rparecord_t *)r_array_slot(records, rec);
846         rjs_compiler_debughead(co, records, rec);
847         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
848         ctx->arguments += 1;
849         rjs_compiler_debugtail(co, records, rec);
850         return 0;
851 }
852
853
854 rint rjs_compiler_rh_arguments(rjs_compiler_t *co, rarray_t *records, rlong rec)
855 {
856         rparecord_t *prec;
857         rjs_coctx_functioncall_t *ctx = (rjs_coctx_functioncall_t *)rjs_compiler_getctx(co, RJS_COCTX_FUNCTIONCALL);
858
859         prec = (rparecord_t *)r_array_slot(records, rec);
860         rjs_compiler_debughead(co, records, rec);
861         if (!ctx) {
862                 rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTIONCALL, prec->input, prec->inputsiz);
863                 return 0;
864         }
865         R_ASSERT(ctx);
866         rjs_compiler_debugtail(co, records, rec);
867
868         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
869                 return -1;
870
871         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
872         prec = (rparecord_t *)r_array_slot(records, rec);
873         rjs_compiler_debughead(co, records, rec);
874         rjs_compiler_debugtail(co, records, rec);
875         return 0;
876 }
877
878
879 rint rjs_compiler_rh_returnstatement(rjs_compiler_t *co, rarray_t *records, rlong rec)
880 {
881         rparecord_t *prec;
882         prec = (rparecord_t *)r_array_slot(records, rec);
883         rjs_compiler_debughead(co, records, rec);
884         rjs_compiler_debugtail(co, records, rec);
885
886         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
887                 return -1;
888
889         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
890         prec = (rparecord_t *)r_array_slot(records, rec);
891         rjs_compiler_debughead(co, records, rec);
892         rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
893         rjs_compiler_debugtail(co, records, rec);
894         return 0;
895 }
896
897
898 rint rjs_compiler_rh_ifstatement(rjs_compiler_t *co, rarray_t *records, rlong rec)
899 {
900         rparecord_t *prec;
901         rjs_coctx_ifstatement_t ctx;
902
903         r_memset(&ctx, 0, sizeof(ctx));
904         ctx.base.type = RJS_COCTX_IFSTATEMENT;
905         ctx.start = rvm_codegen_getcodesize(co->cg);
906         ctx.trueidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__iftrue", ctx.start);
907         ctx.falseidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__iffalse", ctx.start);
908         ctx.endidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__ifend", ctx.start);
909         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
910         prec = (rparecord_t *)r_array_slot(records, rec);
911         rjs_compiler_debughead(co, records, rec);
912         rjs_compiler_debugtail(co, records, rec);
913
914         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
915                 goto error;
916
917         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
918         prec = (rparecord_t *)r_array_slot(records, rec);
919         rjs_compiler_debughead(co, records, rec);
920         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
921         if (!rvm_codegen_validlabel(co->cg, ctx.falseidx))
922                 rvm_codegen_redefinelabel_default(co->cg, ctx.falseidx);
923         rjs_compiler_debugtail(co, records, rec);
924
925         r_array_removelast(co->coctx);
926         return 0;
927
928 error:
929         r_array_removelast(co->coctx);
930         return -1;
931 }
932
933
934 rint rjs_compiler_rh_ifconditionop(rjs_compiler_t *co, rarray_t *records, rlong rec)
935 {
936         rparecord_t *prec;
937         rjs_coctx_ifstatement_t *ctx = (rjs_coctx_ifstatement_t *)rjs_compiler_getctx(co, RJS_COCTX_IFSTATEMENT);
938
939         prec = (rparecord_t *)r_array_slot(records, rec);
940         rjs_compiler_debughead(co, records, rec);
941         if (!ctx) {
942                 rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec->input, prec->inputsiz);
943                 return 0;
944         }
945         R_ASSERT(ctx);
946         rjs_compiler_debugtail(co, records, rec);
947         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
948                 return -1;
949         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
950         prec = (rparecord_t *)r_array_slot(records, rec);
951         rjs_compiler_debughead(co, records, rec);
952         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->falseidx, rvm_asm(RVM_BEQ, DA, XX, XX, 0));
953         rjs_compiler_debugtail(co, records, rec);
954         return 0;
955 }
956
957
958 rint rjs_compiler_rh_iftruestatement(rjs_compiler_t *co, rarray_t *records, rlong rec)
959 {
960         rparecord_t *prec;
961         rjs_coctx_ifstatement_t *ctx = (rjs_coctx_ifstatement_t *)rjs_compiler_getctx(co, RJS_COCTX_IFSTATEMENT);
962
963         prec = (rparecord_t *)r_array_slot(records, rec);
964         rjs_compiler_debughead(co, records, rec);
965         if (!ctx) {
966                 rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec->input, prec->inputsiz);
967                 return 0;
968         }
969         R_ASSERT(ctx);
970         rjs_compiler_debugtail(co, records, rec);
971
972         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
973                 return -1;
974
975         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
976         prec = (rparecord_t *)r_array_slot(records, rec);
977         rjs_compiler_debughead(co, records, rec);
978         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_B, DA, XX, XX, 0));
979         rjs_compiler_debugtail(co, records, rec);
980         return 0;
981 }
982
983
984 rint rjs_compiler_rh_iffalsestatement(rjs_compiler_t *co, rarray_t *records, rlong rec)
985 {
986         rparecord_t *prec;
987         rjs_coctx_ifstatement_t *ctx = (rjs_coctx_ifstatement_t *)rjs_compiler_getctx(co, RJS_COCTX_IFSTATEMENT);
988
989         prec = (rparecord_t *)r_array_slot(records, rec);
990         rjs_compiler_debughead(co, records, rec);
991         if (!ctx) {
992                 rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec->input, prec->inputsiz);
993                 return 0;
994         }
995         R_ASSERT(ctx);
996         rvm_codegen_redefinelabel_default(co->cg, ctx->falseidx);
997         rjs_compiler_debugtail(co, records, rec);
998
999         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1000                 return -1;
1001
1002         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1003         prec = (rparecord_t *)r_array_slot(records, rec);
1004         rjs_compiler_debughead(co, records, rec);
1005         rjs_compiler_debugtail(co, records, rec);
1006         return 0;
1007 }
1008
1009
1010 rint rjs_compiler_rh_iterationfor(rjs_compiler_t *co, rarray_t *records, rlong rec)
1011 {
1012         rlong childrec;
1013         rparecord_t *prec;
1014         rjs_coctx_iteration_t ctx;
1015
1016         r_memset(&ctx, 0, sizeof(ctx));
1017         ctx.base.type = RJS_COCTX_ITERATION;
1018         ctx.start = rvm_codegen_getcodesize(co->cg);
1019         ctx.iterationidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__iteration", ctx.start);
1020         ctx.continueidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__continue", ctx.start);
1021         ctx.endidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__end", ctx.start);
1022         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1023         rvm_scope_push(co->scope);
1024
1025         prec = (rparecord_t *)r_array_slot(records, rec);
1026         rjs_compiler_debughead(co, records, rec);
1027         rjs_compiler_debugtail(co, records, rec);
1028
1029         for (childrec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); childrec >= 0; childrec = rpa_recordtree_next(records, childrec, RPA_RECORD_START)) {
1030                 if (rpa_record_getruleuid(records, childrec) == UID_FOREXPRESSIONINIT) {
1031                         if (rjs_compiler_playrecord(co, records, childrec) < 0)
1032                                 goto error;
1033                         break;
1034                 }
1035         }
1036
1037         rvm_codegen_redefinelabel_default(co->cg, ctx.iterationidx);
1038         for (childrec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); childrec >= 0; childrec = rpa_recordtree_next(records, childrec, RPA_RECORD_START)) {
1039                 if (rpa_record_getruleuid(records, childrec) == UID_FOREXPRESSIONCOMPARE) {
1040                         if (rjs_compiler_playrecord(co, records, childrec) < 0)
1041                                 goto error;
1042                         break;
1043                 }
1044         }
1045
1046         for (childrec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); childrec >= 0; childrec = rpa_recordtree_next(records, childrec, RPA_RECORD_START)) {
1047                 if (rpa_record_getruleuid(records, childrec) == UID_FORITERATIONSTATEMENT) {
1048                         if (rjs_compiler_playrecord(co, records, childrec) < 0)
1049                                 goto error;
1050                         break;
1051                 }
1052         }
1053
1054         rvm_codegen_redefinelabel_default(co->cg, ctx.continueidx);
1055         for (childrec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); childrec >= 0; childrec = rpa_recordtree_next(records, childrec, RPA_RECORD_START)) {
1056                 if (rpa_record_getruleuid(records, childrec) == UID_FOREXPRESSIONINCREMENT) {
1057                         if (rjs_compiler_playrecord(co, records, childrec) < 0)
1058                                 goto error;
1059                         break;
1060                 }
1061         }
1062
1063         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1064         prec = (rparecord_t *)r_array_slot(records, rec);
1065         rjs_compiler_debughead(co, records, rec);
1066         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1067         rjs_compiler_debugtail(co, records, rec);
1068
1069         rvm_scope_pop(co->scope);
1070         r_array_removelast(co->coctx);
1071         return 0;
1072
1073 error:
1074         rvm_scope_pop(co->scope);
1075         r_array_removelast(co->coctx);
1076         return -1;
1077 }
1078
1079
1080 rint rjs_compiler_rh_iterationwhile(rjs_compiler_t *co, rarray_t *records, rlong rec)
1081 {
1082         rparecord_t *prec;
1083         rjs_coctx_iteration_t ctx;
1084
1085         r_memset(&ctx, 0, sizeof(ctx));
1086         ctx.base.type = RJS_COCTX_ITERATION;
1087         ctx.start = rvm_codegen_getcodesize(co->cg);
1088         ctx.iterationidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__iteration", ctx.start);
1089         ctx.continueidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__continue", ctx.start);
1090         ctx.endidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__end", ctx.start);
1091         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1092         rvm_scope_push(co->scope);
1093
1094         prec = (rparecord_t *)r_array_slot(records, rec);
1095         rjs_compiler_debughead(co, records, rec);
1096         rjs_compiler_debugtail(co, records, rec);
1097
1098
1099         rvm_codegen_redefinelabel_default(co->cg, ctx.iterationidx);
1100         rvm_codegen_redefinelabel_default(co->cg, ctx.continueidx);
1101
1102         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1103                 goto error;
1104
1105         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1106         prec = (rparecord_t *)r_array_slot(records, rec);
1107         rjs_compiler_debughead(co, records, rec);
1108         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx.iterationidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1109         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1110         rjs_compiler_debugtail(co, records, rec);
1111
1112         rvm_scope_pop(co->scope);
1113         r_array_removelast(co->coctx);
1114         return 0;
1115
1116 error:
1117         rvm_scope_pop(co->scope);
1118         r_array_removelast(co->coctx);
1119         return -1;
1120 }
1121
1122
1123 rint rjs_compiler_rh_iterationdo(rjs_compiler_t *co, rarray_t *records, rlong rec)
1124 {
1125         rparecord_t *prec;
1126         rjs_coctx_iteration_t ctx;
1127
1128         r_memset(&ctx, 0, sizeof(ctx));
1129         ctx.base.type = RJS_COCTX_ITERATION;
1130         ctx.start = rvm_codegen_getcodesize(co->cg);
1131         ctx.iterationidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__iteration", ctx.start);
1132         ctx.continueidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__continue", ctx.start);
1133         ctx.endidx = rvm_codegen_invalid_add_numlabel_s(co->cg, "__end", ctx.start);
1134         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1135         rvm_scope_push(co->scope);
1136
1137         prec = (rparecord_t *)r_array_slot(records, rec);
1138         rjs_compiler_debughead(co, records, rec);
1139         rjs_compiler_debugtail(co, records, rec);
1140
1141
1142         rvm_codegen_redefinelabel_default(co->cg, ctx.iterationidx);
1143
1144         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1145                 goto error;
1146
1147         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1148         prec = (rparecord_t *)r_array_slot(records, rec);
1149         rjs_compiler_debughead(co, records, rec);
1150         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx.iterationidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1151         rvm_codegen_redefinelabel_default(co->cg, ctx.endidx);
1152         rjs_compiler_debugtail(co, records, rec);
1153
1154         rvm_scope_pop(co->scope);
1155         r_array_removelast(co->coctx);
1156         return 0;
1157
1158 error:
1159         rvm_scope_pop(co->scope);
1160         r_array_removelast(co->coctx);
1161         return -1;
1162 }
1163
1164
1165 rint rjs_compiler_rh_dowhileexpressioncompare(rjs_compiler_t *co, rarray_t *records, rlong rec)
1166 {
1167         rparecord_t *prec;
1168         rjs_coctx_iteration_t *ctx = (rjs_coctx_iteration_t *)rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1169
1170         prec = (rparecord_t *)r_array_slot(records, rec);
1171         rjs_compiler_debughead(co, records, rec);
1172         if (!ctx) {
1173                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input, prec->inputsiz);
1174                 return 0;
1175         }
1176         R_ASSERT(ctx);
1177         rvm_codegen_redefinelabel_default(co->cg, ctx->continueidx);
1178         rjs_compiler_debugtail(co, records, rec);
1179
1180         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1181                 return -1;
1182
1183         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1184         prec = (rparecord_t *)r_array_slot(records, rec);
1185         rjs_compiler_debughead(co, records, rec);
1186         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_BEQ, DA, XX, XX, 0));
1187         rjs_compiler_debugtail(co, records, rec);
1188         return 0;
1189 }
1190
1191
1192 rint rjs_compiler_rh_forexpressioncompare(rjs_compiler_t *co, rarray_t *records, rlong rec)
1193 {
1194         rparecord_t *prec;
1195         rjs_coctx_iteration_t *ctx = (rjs_coctx_iteration_t *)rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1196
1197         prec = (rparecord_t *)r_array_slot(records, rec);
1198         rjs_compiler_debughead(co, records, rec);
1199         if (!ctx) {
1200                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input, prec->inputsiz);
1201                 return 0;
1202         }
1203         R_ASSERT(ctx);
1204         rjs_compiler_debugtail(co, records, rec);
1205
1206         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1207                 return -1;
1208
1209         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1210         prec = (rparecord_t *)r_array_slot(records, rec);
1211         rjs_compiler_debughead(co, records, rec);
1212         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->endidx, rvm_asm(RVM_BEQ, DA, XX, XX, 0));
1213         rjs_compiler_debugtail(co, records, rec);
1214         return 0;
1215 }
1216
1217
1218 rint rjs_compiler_rh_forexpressionincrement(rjs_compiler_t *co, rarray_t *records, rlong rec)
1219 {
1220         rparecord_t *prec;
1221         rjs_coctx_iteration_t *ctx = (rjs_coctx_iteration_t *)rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1222
1223         prec = (rparecord_t *)r_array_slot(records, rec);
1224         rjs_compiler_debughead(co, records, rec);
1225         if (!ctx) {
1226                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input, prec->inputsiz);
1227                 return 0;
1228         }
1229         R_ASSERT(ctx);
1230         rjs_compiler_debugtail(co, records, rec);
1231
1232         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1233                 return -1;
1234
1235         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1236         prec = (rparecord_t *)r_array_slot(records, rec);
1237         rjs_compiler_debughead(co, records, rec);
1238         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, ctx->iterationidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1239         rjs_compiler_debugtail(co, records, rec);
1240         return 0;
1241 }
1242
1243
1244 rint rjs_compiler_rh_postfixexpressionop(rjs_compiler_t *co, rarray_t *records, rlong rec)
1245 {
1246         rparecord_t *prec;
1247         rlong opcode;
1248         rlong opcoderec;
1249
1250         if ((opcoderec = rpa_recordtree_lastchild(records, rec, RPA_RECORD_END)) < 0)
1251                 return -1;
1252         opcode = rjs_compiler_record2opcode((rparecord_t *)r_array_slot(records, opcoderec));
1253         prec = (rparecord_t *)r_array_slot(records, rec);
1254         rjs_compiler_debughead(co, records, rec);
1255         rjs_compiler_debugtail(co, records, rec);
1256
1257         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1258                 return -1;
1259
1260         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1261         prec = (rparecord_t *)r_array_slot(records, rec);
1262         rjs_compiler_debughead(co, records, rec);
1263         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
1264         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R1, XX, 0));
1265         rvm_codegen_addins(co->cg, rvm_asm(opcode, R2, R0, DA, 1));
1266         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R2, R1, XX, 0));
1267
1268         rjs_compiler_debugtail(co, records, rec);
1269         return 0;
1270 }
1271
1272
1273 rint rjs_compiler_rh_prefixexpressionop(rjs_compiler_t *co, rarray_t *records, rlong rec)
1274 {
1275         rparecord_t *prec;
1276         rlong opcode;
1277         rlong opcoderec;
1278
1279         if ((opcoderec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_END)) < 0)
1280                 return -1;
1281         opcode = rjs_compiler_record2opcode((rparecord_t *)r_array_slot(records, opcoderec));
1282
1283         prec = (rparecord_t *)r_array_slot(records, rec);
1284         rjs_compiler_debughead(co, records, rec);
1285         rjs_compiler_debugtail(co, records, rec);
1286
1287         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1288                 return -1;
1289
1290         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1291         prec = (rparecord_t *)r_array_slot(records, rec);
1292         rjs_compiler_debughead(co, records, rec);
1293         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R0, R0, XX, 0));
1294         rvm_codegen_addins(co->cg, rvm_asm(opcode, R0, R0, DA, 1));
1295         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
1296         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
1297
1298         rjs_compiler_debugtail(co, records, rec);
1299         return 0;
1300 }
1301
1302
1303 rint rjs_compiler_rh_newexpressioncall(rjs_compiler_t *co, rarray_t *records, rlong rec)
1304 {
1305         rparecord_t *prec;
1306         rjs_coctx_functioncall_t ctx;
1307
1308         r_memset(&ctx, 0, sizeof(ctx));
1309         ctx.base.type = RJS_COCTX_FUNCTIONCALL;
1310         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
1311
1312         prec = (rparecord_t *)r_array_slot(records, rec);
1313         rjs_compiler_debughead(co, records, rec);
1314         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSHM, DA, XX, XX, BIT(TP)|BIT(FP)|BIT(SP)|BIT(LR)));
1315         rjs_compiler_debugtail(co, records, rec);
1316
1317         /*
1318          * Important: Function call has two children FunctionCallName, Arguments
1319          * We evaluate them in reverse order, first we evaluate the Arguments and push them on the
1320          * stack, than we evaluate the FunctionCallName -> R0. When we make the call we assume the
1321          * result of the FunctionCallName will be in R0.
1322          */
1323         if (rjs_compiler_playreversechildrecords(co, records, rec) < 0)
1324                 goto error;
1325
1326         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1327         prec = (rparecord_t *)r_array_slot(records, rec);
1328         rjs_compiler_debughead(co, records, rec);
1329         rvm_codegen_addins(co->cg, rvm_asm(RVM_ALLOCOBJ, TP, DA, XX, 0));
1330         rvm_codegen_addins(co->cg, rvm_asm(RVM_SUB, FP, SP, DA, ctx.arguments));
1331         rvm_codegen_addins(co->cg, rvm_asm(RVM_CALL, R0, XX, XX, 0));
1332         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, SP, FP, XX, 0));
1333         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, TP, XX, 0));
1334         rvm_codegen_addins(co->cg, rvm_asm(RVM_POPM, DA, XX, XX, BITS(TP,LR)));
1335         rjs_compiler_debugtail(co, records, rec);
1336         r_array_removelast(co->coctx);
1337         return 0;
1338
1339 error:
1340         r_array_removelast(co->coctx);
1341         return -1;
1342 }
1343
1344
1345 rint rjs_compiler_rh_this(rjs_compiler_t *co, rarray_t *records, rlong rec)
1346 {
1347         rparecord_t *prec;
1348         prec = (rparecord_t *)r_array_slot(records, rec);
1349         rjs_compiler_debughead(co, records, rec);
1350         rjs_compiler_debugtail(co, records, rec);
1351
1352         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1353                 return -1;
1354
1355         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1356         prec = (rparecord_t *)r_array_slot(records, rec);
1357         rjs_compiler_debughead(co, records, rec);
1358         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, TP, XX, 0));
1359         rjs_compiler_debugtail(co, records, rec);
1360         return 0;
1361 }
1362
1363
1364 rint rjs_compiler_rh_binaryoperator(rjs_compiler_t *co, rarray_t *records, rlong rec)
1365 {
1366         rparecord_t *prec;
1367         rjs_coctx_t *ctx = rjs_compiler_gettopctx(co);
1368
1369         prec = (rparecord_t *)r_array_slot(records, rec);
1370         rjs_compiler_debughead(co, records, rec);
1371         rjs_compiler_debugtail(co, records, rec);
1372
1373         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1374                 return -1;
1375
1376         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1377         prec = (rparecord_t *)r_array_slot(records, rec);
1378         rjs_compiler_debughead(co, records, rec);
1379         if (ctx && ctx->type == RJS_COCTX_OPERATION)
1380                 ((rjs_coctx_operation_t *)ctx)->opcode = rjs_compiler_record2opcode(prec);
1381         rjs_compiler_debugtail(co, records, rec);
1382         return 0;
1383 }
1384
1385
1386 rint rjs_compiler_rh_unaryoperator(rjs_compiler_t *co, rarray_t *records, rlong rec)
1387 {
1388         rparecord_t *prec;
1389         rjs_coctx_t *ctx = rjs_compiler_gettopctx(co);
1390
1391         prec = (rparecord_t *)r_array_slot(records, rec);
1392         rjs_compiler_debughead(co, records, rec);
1393         rjs_compiler_debugtail(co, records, rec);
1394
1395         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1396                 return -1;
1397
1398         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1399         prec = (rparecord_t *)r_array_slot(records, rec);
1400         rjs_compiler_debughead(co, records, rec);
1401         if (ctx && ctx->type == RJS_COCTX_OPERATION)
1402                 ((rjs_coctx_operation_t *)ctx)->opcode = rjs_compiler_record2unaryopcode(prec);
1403         rjs_compiler_debugtail(co, records, rec);
1404         return 0;
1405 }
1406
1407
1408 rint rjs_compiler_rh_identifiername(rjs_compiler_t *co, rarray_t *records, rlong rec)
1409 {
1410         rparecord_t *prec;
1411         prec = (rparecord_t *)r_array_slot(records, rec);
1412         rjs_compiler_debughead(co, records, rec);
1413         rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, prec->inputsiz));
1414         rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R2, DA, XX, (void*)prec->input));
1415         rjs_compiler_debugtail(co, records, rec);
1416
1417         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1418                 return -1;
1419
1420         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1421         prec = (rparecord_t *)r_array_slot(records, rec);
1422         rjs_compiler_debughead(co, records, rec);
1423         rjs_compiler_debugtail(co, records, rec);
1424         return 0;
1425 }
1426
1427
1428 rint rjs_compiler_rh_continue(rjs_compiler_t *co, rarray_t *records, rlong rec)
1429 {
1430         rparecord_t *prec;
1431         rjs_coctx_t *ctx;
1432         rjs_coctx_iteration_t *iterctx;
1433
1434         ctx = rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1435         prec = (rparecord_t *)r_array_slot(records, rec);
1436         rjs_compiler_debughead(co, records, rec);
1437         if (!ctx) {
1438                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input, prec->inputsiz);
1439                 return 0;
1440         }
1441         R_ASSERT(ctx);
1442         iterctx = (rjs_coctx_iteration_t *)ctx;
1443         rjs_compiler_debugtail(co, records, rec);
1444
1445         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1446                 return -1;
1447
1448         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1449         prec = (rparecord_t *)r_array_slot(records, rec);
1450         rjs_compiler_debughead(co, records, rec);
1451         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, iterctx->continueidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1452         rjs_compiler_debugtail(co, records, rec);
1453         return 0;
1454 }
1455
1456
1457 rint rjs_compiler_rh_break(rjs_compiler_t *co, rarray_t *records, rlong rec)
1458 {
1459         rparecord_t *prec;
1460         rjs_coctx_t *ctx;
1461         rjs_coctx_iteration_t *iterctx;
1462
1463
1464         ctx = rjs_compiler_getctx(co, RJS_COCTX_ITERATION);
1465         prec = (rparecord_t *)r_array_slot(records, rec);
1466         rjs_compiler_debughead(co, records, rec);
1467         if (!ctx) {
1468                 rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input, prec->inputsiz);
1469                 return 0;
1470         }
1471         R_ASSERT(ctx);
1472         iterctx = (rjs_coctx_iteration_t *)ctx;
1473         rjs_compiler_debugtail(co, records, rec);
1474
1475         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1476                 return -1;
1477
1478         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1479         prec = (rparecord_t *)r_array_slot(records, rec);
1480         rjs_compiler_debughead(co, records, rec);
1481         rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, iterctx->endidx, rvm_asm(RVM_B, DA, XX, XX, 0));
1482         rjs_compiler_debugtail(co, records, rec);
1483         return 0;
1484 }
1485
1486
1487 rint rjs_compiler_rh_syntaxerror(rjs_compiler_t *co, rarray_t *records, rlong rec)
1488 {
1489         rparecord_t *prec;
1490         prec = (rparecord_t *)r_array_slot(records, rec);
1491         rjs_compiler_debughead(co, records, rec);
1492         rjs_compiler_debugtail(co, records, rec);
1493
1494         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1495                 return -1;
1496
1497         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1498         prec = (rparecord_t *)r_array_slot(records, rec);
1499         rjs_compiler_debughead(co, records, rec);
1500         rjs_compiler_adderror(co, RJS_ERROR_SYNTAX, prec->input, prec->inputsiz);
1501         rjs_compiler_debugtail(co, records, rec);
1502         return 0;
1503 }
1504
1505
1506 rint rjs_compiler_rh_(rjs_compiler_t *co, rarray_t *records, rlong rec)
1507 {
1508         rparecord_t *prec;
1509         prec = (rparecord_t *)r_array_slot(records, rec);
1510         rjs_compiler_debughead(co, records, rec);
1511         rjs_compiler_debugtail(co, records, rec);
1512
1513         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1514                 return -1;
1515
1516         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1517         prec = (rparecord_t *)r_array_slot(records, rec);
1518         rjs_compiler_debughead(co, records, rec);
1519         rjs_compiler_debugtail(co, records, rec);
1520         return 0;
1521 }
1522
1523
1524 rjs_compiler_t *rjs_compiler_create(rvmcpu_t *cpu)
1525 {
1526         rjs_compiler_t *co = (rjs_compiler_t *) r_zmalloc(sizeof(*co));
1527
1528         co->cg = rvm_codegen_create();
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_codegen_destroy(co->cg);
1599                 rvm_scope_destroy(co->scope);
1600                 r_array_destroy(co->coctx);
1601                 r_array_destroy(co->errors);
1602                 r_free(co->temp);
1603                 co->cpu = NULL;
1604                 r_free(co);
1605         }
1606 }
1607
1608
1609 static rint rjs_compiler_rh_default(rjs_compiler_t *co, rarray_t *records, rlong rec)
1610 {
1611         rparecord_t *prec;
1612
1613         prec = (rparecord_t *)r_array_slot(records, rec);
1614         rjs_compiler_debughead(co, records, rec);
1615         rjs_compiler_debugtail(co, records, rec);
1616
1617         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
1618                 return -1;
1619
1620         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
1621         prec = (rparecord_t *)r_array_slot(records, rec);
1622         rjs_compiler_debughead(co, records, rec);
1623         rjs_compiler_debugtail(co, records, rec);
1624
1625         return 0;
1626 }
1627
1628
1629 static rint rjs_compiler_playchildrecords(rjs_compiler_t *co, rarray_t *records, rlong rec)
1630 {
1631         rlong child;
1632
1633         for (child = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); child >= 0; child = rpa_recordtree_next(records, child, RPA_RECORD_START)) {
1634                 if (rjs_compiler_playrecord(co, records, child) < 0)
1635                         return -1;
1636         }
1637
1638         return 0;
1639 }
1640
1641
1642 rint rjs_compiler_playreversechildrecords(rjs_compiler_t *co, rarray_t *records, rlong rec)
1643 {
1644         rlong child;
1645
1646         for (child = rpa_recordtree_lastchild(records, rec, RPA_RECORD_START); child >= 0; child = rpa_recordtree_prev(records, child, RPA_RECORD_START)) {
1647                 if (rjs_compiler_playrecord(co, records, child) < 0)
1648                         return -1;
1649         }
1650
1651         return 0;
1652 }
1653
1654
1655 static rint rjs_compiler_playrecord(rjs_compiler_t *co, rarray_t *records, rlong rec)
1656 {
1657         rparecord_t *prec;
1658         prec = (rparecord_t *)r_array_slot(records, rec);
1659         if (prec->ruleuid >= 0 && prec->ruleuid < RJS_COMPILER_NHANDLERS && co->handlers[prec->ruleuid]) {
1660                 return co->handlers[prec->ruleuid](co, records, rec);
1661         }
1662         return rjs_compiler_rh_default(co, records, rec);
1663 }
1664
1665
1666 rint rjs_compiler_compile(rjs_compiler_t *co, rarray_t *records)
1667 {
1668         rlong i;
1669         rvm_codelabel_t *labelerr;
1670
1671         if (!co || !records || r_array_empty(records)) {
1672                 /*
1673                  * TBD
1674                  */
1675                 return -1;
1676         }
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 }