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