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