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