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