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