RPA Toolkit
327f12dde7e13fe9c743d08a1ee7283df262706d
[rpatk.git] / rjs / rjscompiler.c
1 #include "rmem.h"
2 #include "rjscompiler.h"
3
4 rint rjs_compiler_playreversechildrecords(rjs_compiler_t *co, rarray_t *records, rlong rec);
5 static rint rjs_compiler_playrecord(rjs_compiler_t *co, rarray_t *records, rlong rec);
6 static rint rjs_compiler_playchildrecords(rjs_compiler_t *co, rarray_t *records, rlong rec);
7
8
9 void rjs_compiler_debughead(rjs_compiler_t *co, rarray_t *records, rlong rec)
10 {
11         if (co->debug) {
12                 rpa_record_dump(records, rec);
13                 co->headoff = rvm_codegen_getcodesize(co->cg);
14         }
15 }
16
17
18 void rjs_compiler_debugtail(rjs_compiler_t *co, rarray_t *records, rlong rec)
19 {
20         if (co->debug) {
21                 rvm_asm_dump(rvm_codegen_getcode(co->cg, co->headoff), rvm_codegen_getcodesize(co->cg) - co->headoff);
22         }
23
24 }
25
26
27 static const rchar *rjs_compiler_record2str(rjs_compiler_t *co, rarray_t *records, rlong rec)
28 {
29         rparecord_t *prec = (rparecord_t *)r_array_slot(records, rpa_recordtree_get(records, rec, RPA_RECORD_END));
30         rsize_t size = 16; /* Min size */
31
32         if (prec && prec->inputsiz) {
33                 size = prec->inputsiz + 1;
34         }
35         co->temp = r_realloc(co->temp, size);
36         r_memset(co->temp, 0, size);
37         if (prec->input && prec->inputsiz)
38                 r_memcpy(co->temp, prec->input, prec->inputsiz);
39         return co->temp;
40 }
41
42
43 rlong rjs_compiler_record2opcode(rparecord_t *prec)
44 {
45         const rchar *input = prec->input;
46         rsize_t size = prec->inputsiz;
47
48         if (r_stringncmp("++", input,  size))
49                 return RVM_EADD;
50         else if (r_stringncmp("+", input,  size))
51                 return RVM_EADD;
52         else if (r_stringncmp("+=", input,  size))
53                 return RVM_EADD;
54         else if (r_stringncmp("--", input,  size))
55                 return RVM_ESUB;
56         else if (r_stringncmp("-", input,  size))
57                 return RVM_ESUB;
58         else if (r_stringncmp("-=", input,  size))
59                 return RVM_ESUB;
60         else if (r_stringncmp("*", input,  size))
61                 return RVM_EMUL;
62         else if (r_stringncmp("*=", input,  size))
63                 return RVM_EMUL;
64         else if (r_stringncmp("/", input,  size))
65                 return RVM_EDIV;
66         else if (r_stringncmp("/=", input,  size))
67                 return RVM_EDIV;
68         else if (r_stringncmp("%", input,  size))
69                 return RVM_EMOD;
70         else if (r_stringncmp("%=", input,  size))
71                 return RVM_EMOD;
72         else if (r_stringncmp("&&", input,  size))
73                 return RVM_ELAND;
74         else if (r_stringncmp("||", input,  size))
75                 return RVM_ELOR;
76         else if (r_stringncmp("&", input,  size))
77                 return RVM_EAND;
78         else if (r_stringncmp("&=", input,  size))
79                 return RVM_EAND;
80         else if (r_stringncmp("|", input,  size))
81                 return RVM_EORR;
82         else if (r_stringncmp("|=", input,  size))
83                 return RVM_EORR;
84         else if (r_stringncmp("^", input,  size))
85                 return RVM_EXOR;
86         else if (r_stringncmp("^=", input,  size))
87                 return RVM_EXOR;
88         else if (r_stringncmp(">>", input,  size))
89                 return RVM_ELSR;
90         else if (r_stringncmp(">>=", input,  size))
91                 return RVM_ELSR;
92         else if (r_stringncmp("<<", input,  size))
93                 return RVM_ELSL;
94         else if (r_stringncmp("<<=", input,  size))
95                 return RVM_ELSL;
96         else if (r_stringncmp(">>>", input,  size))
97                 return RVM_ELSRU;
98         else if (r_stringncmp(">>>=", input,  size))
99                 return RVM_ELSRU;
100         else if (r_stringncmp("<=", input,  size))
101                 return RVM_ELESSEQ;
102         else if (r_stringncmp(">=", input,  size))
103                 return RVM_EGREATEQ;
104         else if (r_stringncmp("<", input,  size))
105                 return RVM_ELESS;
106         else if (r_stringncmp(">", input,  size))
107                 return RVM_EGREAT;
108         else if (r_stringncmp("===", input,  size))
109                 return RVM_EEQ;
110         else if (r_stringncmp("==", input,  size))
111                 return RVM_EEQ;
112         else if (r_stringncmp("!==", input,  size))
113                 return RVM_ENOTEQ;
114         else if (r_stringncmp("!=", input,  size))
115                 return RVM_ENOTEQ;
116         else if (r_stringncmp("!", input,  size))
117                 return RVM_ELNOT;
118         else if (r_stringncmp("~", input,  size))
119                 return RVM_ENOT;
120         else if (r_stringncmp("=", input,  size))
121                 return RVM_NOP;
122
123         return -1;
124 }
125
126
127 rint rjs_compiler_rh_program(rjs_compiler_t *co, rarray_t *records, rlong rec)
128 {
129         rjs_coctx_global_t ctx;
130         rparecord_t *prec;
131
132         r_memset(&ctx, 0, sizeof(ctx));
133         ctx.base.type = RJS_COCTX_GLOBAL;
134         r_array_push(co->coctx, &ctx, rjs_coctx_t*);
135
136         prec = (rparecord_t *)r_array_slot(records, rec);
137         rjs_compiler_debughead(co, records, rec);
138         rvm_codegen_addins(co->cg, rvm_asm(RVM_NOP, XX, XX, XX, 0));
139         rjs_compiler_debugtail(co, records, rec);
140
141         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
142                 goto error;
143
144         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
145         prec = (rparecord_t *)r_array_slot(records, rec);
146         rjs_compiler_debughead(co, records, rec);
147         rvm_codegen_addins(co->cg, rvm_asm(RVM_PRN, R0, XX, XX, 0));
148         rvm_codegen_addins(co->cg, rvm_asm(RVM_EXT, XX, XX, XX, 0));
149         rjs_compiler_debugtail(co, records, rec);
150         r_array_removelast(co->coctx);
151         return 0;
152
153 error:
154         r_array_removelast(co->coctx);
155         return -1;
156 }
157
158
159 rint rjs_compiler_rh_varalloc(rjs_compiler_t *co, rarray_t *records, rlong rec)
160 {
161         rparecord_t *prec;
162         rjs_coctx_t *ctx = NULL;
163         rvm_varmap_t *v = NULL;
164         rlong i;
165
166         R_ASSERT(r_array_length(co->coctx));
167
168         /*
169          * First lets find out if we are within a function definition or
170          * this is a global variable.
171          */
172         for (i = r_array_length(co->coctx) - 1; i >= 0; i--) {
173                 ctx = r_array_index(co->coctx, i, rjs_coctx_t*);
174                 if (ctx->type == RJS_COCTX_FUNCTION || ctx->type == RJS_COCTX_GLOBAL)
175                         break;
176         }
177         R_ASSERT(ctx);
178
179         prec = (rparecord_t *)r_array_slot(records, rec);
180         rjs_compiler_debughead(co, records, rec);
181         rjs_compiler_debugtail(co, records, rec);
182
183         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
184                 goto error;
185
186         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
187         prec = (rparecord_t *)r_array_slot(records, rec);
188         rjs_compiler_debughead(co, records, rec);
189         v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
190
191         /*
192          * TBD: Temporary here
193          */
194         if (v) {
195                 r_printf("ERROR: variable already defined: %s\n", rjs_compiler_record2str(co, records, rec));
196                 goto error;
197         }
198
199         if (ctx->type == RJS_COCTX_FUNCTION) {
200                 rjs_coctx_function_t *functx = (rjs_coctx_function_t *)ctx;
201                 functx->allocs += 1;
202                 rvm_scope_addoffset(co->scope, prec->input, prec->inputsiz, functx->allocs);
203         } else {
204                 rjs_coctx_global_t *functx = (rjs_coctx_global_t *)ctx;
205                 functx->allocs += 1;
206                 r_carray_setlength(co->cpu->data, functx->allocs + 1);
207                 rvm_scope_addpointer(co->scope, prec->input, prec->inputsiz, r_carray_slot(co->cpu->data, functx->allocs));
208         }
209         v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
210         if (v->datatype == VARMAP_DATATYPE_OFFSET) {
211                 rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDRS, R1, FP, DA, v->data.offset));
212         } else {
213                 rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R1, DA, XX, v->data.ptr));
214         }
215         rvm_codegen_addins(co->cg, rvm_asm(RVM_CLRR, R1, XX, XX, 0));
216
217         rjs_compiler_debugtail(co, records, rec);
218         return 0;
219
220 error:
221         return -1;
222 }
223
224
225 rint rjs_compiler_rh_varallocinit(rjs_compiler_t *co, rarray_t *records, rlong rec)
226 {
227         rparecord_t *prec;
228         rjs_coctx_t *ctx = NULL;
229         rvm_varmap_t *v = NULL;
230         rlong i;
231
232         R_ASSERT(r_array_length(co->coctx));
233
234         /*
235          * First lets find out if we are within a function definition or
236          * this is a global variable.
237          */
238         for (i = r_array_length(co->coctx) - 1; i >= 0; i--) {
239                 ctx = r_array_index(co->coctx, i, rjs_coctx_t*);
240                 if (ctx->type == RJS_COCTX_FUNCTION || ctx->type == RJS_COCTX_GLOBAL)
241                         break;
242         }
243         R_ASSERT(ctx);
244
245         prec = (rparecord_t *)r_array_slot(records, rec);
246         rjs_compiler_debughead(co, records, rec);
247         rjs_compiler_debugtail(co, records, rec);
248
249         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
250                 goto error;
251
252         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
253         prec = (rparecord_t *)r_array_slot(records, rec);
254         rjs_compiler_debughead(co, records, rec);
255         v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
256
257         /*
258          * TBD: Temporary here
259          */
260         if (v) {
261                 r_printf("ERROR: variable already defined: %s\n", rjs_compiler_record2str(co, records, rec));
262                 goto error;
263         }
264
265         if (ctx->type == RJS_COCTX_FUNCTION) {
266                 rjs_coctx_function_t *functx = (rjs_coctx_function_t *)ctx;
267                 functx->allocs += 1;
268                 rvm_scope_addoffset(co->scope, prec->input, prec->inputsiz, functx->allocs);
269         } else {
270                 rjs_coctx_global_t *functx = (rjs_coctx_global_t *)ctx;
271                 functx->allocs += 1;
272                 r_carray_setlength(co->cpu->data, functx->allocs + 1);
273                 rvm_scope_addpointer(co->scope, prec->input, prec->inputsiz, r_carray_slot(co->cpu->data, functx->allocs));
274         }
275         v = rvm_scope_tiplookup(co->scope, prec->input, prec->inputsiz);
276         if (v->datatype == VARMAP_DATATYPE_OFFSET) {
277                 rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDRS, R0, FP, DA, v->data.offset));
278         } else {
279                 rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R0, DA, XX, v->data.ptr));
280         }
281         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
282         rjs_compiler_debugtail(co, records, rec);
283         return 0;
284
285 error:
286         return -1;
287 }
288
289
290 rint rjs_compiler_rh_initializer(rjs_compiler_t *co, rarray_t *records, rlong rec)
291 {
292         rparecord_t *prec;
293         prec = (rparecord_t *)r_array_slot(records, rec);
294         rjs_compiler_debughead(co, records, rec);
295         rjs_compiler_debugtail(co, records, rec);
296
297         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
298                 return -1;
299
300         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
301         prec = (rparecord_t *)r_array_slot(records, rec);
302         rjs_compiler_debughead(co, records, rec);
303         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
304         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
305         rjs_compiler_debugtail(co, records, rec);
306         return 0;
307 }
308
309
310 rint rjs_compiler_rh_identifier(rjs_compiler_t *co, rarray_t *records, rlong rec)
311 {
312         rvm_varmap_t *v;
313         rlong parrec;
314         rparecord_t *prec, *pparrec;
315         prec = (rparecord_t *)r_array_slot(records, rec);
316         rjs_compiler_debughead(co, records, rec);
317         rjs_compiler_debugtail(co, records, rec);
318
319         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
320                 return -1;
321
322         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
323         prec = (rparecord_t *)r_array_slot(records, rec);
324         rjs_compiler_debughead(co, records, rec);
325         v = rvm_scope_lookup(co->scope, prec->input, prec->inputsiz);
326         if (!v) {
327                 r_printf("ERROR: Undefined identifier: %s\n", rjs_compiler_record2str(co, records, rec));
328                 return -1;
329         }
330
331         if ((parrec = rpa_recordtree_parent(records, rec, RPA_RECORD_END)) < 0) {
332
333                 return -1;
334         }
335         pparrec = (rparecord_t *)r_array_slot(records, parrec);
336         if (rpa_recordtree_next(records, rec, RPA_RECORD_START) < 0 && pparrec->ruleuid == UID_LEFTHANDSIDEEXPRESSIONADDR) {
337                 /*
338                  * If this is the last child of UID_LEFTHANDSIDEEXPRESSIONADDR
339                  */
340                 if (v->datatype == VARMAP_DATATYPE_OFFSET) {
341                         rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDRS, R0, FP, DA, v->data.offset));
342                 } else {
343                         rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R0, DA, XX, v->data.ptr));
344                 }
345         } else {
346                 if (v->datatype == VARMAP_DATATYPE_OFFSET) {
347                         rvm_codegen_addins(co->cg, rvm_asm(RVM_LDS, R0, FP, DA, v->data.offset));
348                 } else {
349                         rvm_codegen_addins(co->cg, rvm_asmp(RVM_LDRR, R0, DA, XX, v->data.ptr));
350                 }
351         }
352
353         rjs_compiler_debugtail(co, records, rec);
354         return 0;
355 }
356
357
358 rint rjs_compiler_rh_expression(rjs_compiler_t *co, rarray_t *records, rlong rec)
359 {
360         rparecord_t *prec;
361         prec = (rparecord_t *)r_array_slot(records, rec);
362         rjs_compiler_debughead(co, records, rec);
363         rjs_compiler_debugtail(co, records, rec);
364
365         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
366                 return -1;
367
368         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
369         prec = (rparecord_t *)r_array_slot(records, rec);
370         rjs_compiler_debughead(co, records, rec);
371         rjs_compiler_debugtail(co, records, rec);
372         return 0;
373 }
374
375
376 rint rjs_compiler_rh_lefthandsideexpression(rjs_compiler_t *co, rarray_t *records, rlong rec)
377 {
378         rparecord_t *prec;
379         prec = (rparecord_t *)r_array_slot(records, rec);
380         rjs_compiler_debughead(co, records, rec);
381         rjs_compiler_debugtail(co, records, rec);
382
383         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
384                 return -1;
385
386         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
387         prec = (rparecord_t *)r_array_slot(records, rec);
388         rjs_compiler_debughead(co, records, rec);
389         rjs_compiler_debugtail(co, records, rec);
390         return 0;
391 }
392
393
394 rint rjs_compiler_rh_lefthandsideexpressionaddr(rjs_compiler_t *co, rarray_t *records, rlong rec)
395 {
396         rparecord_t *prec;
397         prec = (rparecord_t *)r_array_slot(records, rec);
398         rjs_compiler_debughead(co, records, rec);
399         rjs_compiler_debugtail(co, records, rec);
400
401         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
402                 return -1;
403
404         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
405         prec = (rparecord_t *)r_array_slot(records, rec);
406         rjs_compiler_debughead(co, records, rec);
407         rvm_codegen_addins(co->cg, rvm_asmp(RVM_PUSH, R0, XX, XX, 0));
408         rjs_compiler_debugtail(co, records, rec);
409         return 0;
410 }
411
412
413 rint rjs_compiler_rh_decimalintegerliteral(rjs_compiler_t *co, rarray_t *records, rlong rec)
414 {
415         rparecord_t *prec;
416         prec = (rparecord_t *)r_array_slot(records, rec);
417         rjs_compiler_debughead(co, records, rec);
418         rjs_compiler_debugtail(co, records, rec);
419
420         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
421                 return -1;
422
423         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
424         prec = (rparecord_t *)r_array_slot(records, rec);
425         rjs_compiler_debughead(co, records, rec);
426         rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R0, DA, XX, r_strtol(prec->input, NULL, 10)));
427         rjs_compiler_debugtail(co, records, rec);
428         return 0;
429 }
430
431
432 rint rjs_compiler_rh_decimalnonintegerliteral(rjs_compiler_t *co, rarray_t *records, rlong rec)
433 {
434         rparecord_t *prec;
435         prec = (rparecord_t *)r_array_slot(records, rec);
436         rjs_compiler_debughead(co, records, rec);
437         rjs_compiler_debugtail(co, records, rec);
438
439         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
440                 return -1;
441
442         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
443         prec = (rparecord_t *)r_array_slot(records, rec);
444         rjs_compiler_debughead(co, records, rec);
445         rvm_codegen_addins(co->cg, rvm_asmd(RVM_MOV, R0, DA, XX, r_strtod(prec->input, NULL)));
446
447         rjs_compiler_debugtail(co, records, rec);
448         return 0;
449 }
450
451
452 rint rjs_compiler_rh_expressionop(rjs_compiler_t *co, rarray_t *records, rlong rec)
453 {
454         rparecord_t *prec;
455         rlong opcode = 0;
456         rlong opcoderec = -1;
457
458         prec = (rparecord_t *)r_array_slot(records, rec);
459         rjs_compiler_debughead(co, records, rec);
460         rvm_codegen_addins(co->cg, rvm_asm(RVM_PUSH, R0, XX, XX, 0));
461         rjs_compiler_debugtail(co, records, rec);
462
463         if ((opcoderec = rpa_recordtree_firstchild(records, rec, RPA_RECORD_END)) < 0)
464                 return -1;
465         opcode = rjs_compiler_record2opcode((rparecord_t *)r_array_slot(records, opcoderec));
466
467         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
468                 return -1;
469
470         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
471         prec = (rparecord_t *)r_array_slot(records, rec);
472         rjs_compiler_debughead(co, records, rec);
473         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
474         rvm_codegen_addins(co->cg, rvm_asm(opcode, R0, R1, R0, 0));
475         rjs_compiler_debugtail(co, records, rec);
476         return 0;
477 }
478
479
480 rint rjs_compiler_rh_assignmentexpressionop(rjs_compiler_t *co, rarray_t *records, rlong rec)
481 {
482         rparecord_t *prec;
483         rlong opcode = 0;
484         rlong opcoderec = -1;
485
486         prec = (rparecord_t *)r_array_slot(records, rec);
487         rjs_compiler_debughead(co, records, rec);
488         rjs_compiler_debugtail(co, records, rec);
489
490         if ((opcoderec = rpa_recordtree_next(records, rpa_recordtree_firstchild(records, rec, RPA_RECORD_END), RPA_RECORD_END)) < 0)
491                 return -1;
492         opcode = rjs_compiler_record2opcode((rparecord_t *)r_array_slot(records, opcoderec));
493
494         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
495                 return -1;
496
497         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
498         prec = (rparecord_t *)r_array_slot(records, rec);
499         rjs_compiler_debughead(co, records, rec);
500         rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, R1, XX, XX, 0));
501         if (opcode != RVM_NOP) {
502                 rvm_codegen_addins(co->cg, rvm_asm(RVM_LDRR, R2, R1, XX, 0));
503                 rvm_codegen_addins(co->cg, rvm_asm(opcode, R0, R2, R0, 0));
504         }
505         rvm_codegen_addins(co->cg, rvm_asm(RVM_STRR, R0, R1, XX, 0));
506         rjs_compiler_debugtail(co, records, rec);
507         return 0;
508 }
509
510
511 rint rjs_compiler_rh_newarrayexpression(rjs_compiler_t *co, rarray_t *records, rlong rec)
512 {
513         rparecord_t *prec;
514         prec = (rparecord_t *)r_array_slot(records, rec);
515         rjs_compiler_debughead(co, records, rec);
516         rjs_compiler_debugtail(co, records, rec);
517
518         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
519                 return -1;
520
521         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
522         prec = (rparecord_t *)r_array_slot(records, rec);
523         rjs_compiler_debughead(co, records, rec);
524         rvm_codegen_addins(co->cg, rvm_asm(RVM_ALLOCOBJ, R0, DA, XX, 0));
525         rjs_compiler_debugtail(co, records, rec);
526         return 0;
527 }
528
529
530 rint rjs_compiler_rh_memberexpressiondotop(rjs_compiler_t *co, rarray_t *records, rlong rec)
531 {
532         rparecord_t *prec;
533         prec = (rparecord_t *)r_array_slot(records, rec);
534         rjs_compiler_debughead(co, records, rec);
535         rjs_compiler_debugtail(co, records, rec);
536
537         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
538                 return -1;
539
540         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
541         prec = (rparecord_t *)r_array_slot(records, rec);
542         rjs_compiler_debughead(co, records, rec);
543         if (rpa_record_getruleuid(records, rpa_recordtree_parent(records, rec, RPA_RECORD_START)) == UID_LEFTHANDSIDEEXPRESSIONADDR &&
544                 rpa_recordtree_next(records, rec, RPA_RECORD_START) == -1) {
545                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R0, XX, 0));    // Supposedly Array Address
546                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, prec->inputsiz));
547                 rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R2, DA, XX, (void*)prec->input));
548                 rvm_codegen_addins(co->cg, rvm_asm(RVM_OBJLKUPADD, R0, R1, R2, 0));     // Get the offset of the element at offset R0
549                 rvm_codegen_addins(co->cg, rvm_asm(RVM_ADDROBJH, R0, R1, R0, 0));       // Get the address of the element at offset R0
550
551         } else {
552                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R1, R0, XX, 0));    // Supposedly Array Address
553                 rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R0, DA, XX, prec->inputsiz));
554                 rvm_codegen_addins(co->cg, rvm_asmp(RVM_MOV, R2, DA, XX, (void*)prec->input));
555                 rvm_codegen_addins(co->cg, rvm_asm(RVM_OBJLKUP, R0, R1, R2, 0));        // Get the offset of the element at offset R0
556                 rvm_codegen_addins(co->cg, rvm_asm(RVM_LDOBJH, R0, R1, R0, 0)); // Get the value of the element at offset R0
557         }
558         rjs_compiler_debugtail(co, records, rec);
559         return 0;
560 }
561
562
563 rint rjs_compiler_rh_(rjs_compiler_t *co, rarray_t *records, rlong rec)
564 {
565         rparecord_t *prec;
566         prec = (rparecord_t *)r_array_slot(records, rec);
567         rjs_compiler_debughead(co, records, rec);
568         rjs_compiler_debugtail(co, records, rec);
569
570         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
571                 return -1;
572
573         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
574         prec = (rparecord_t *)r_array_slot(records, rec);
575         rjs_compiler_debughead(co, records, rec);
576         rjs_compiler_debugtail(co, records, rec);
577         return 0;
578 }
579
580
581 rjs_compiler_t *rjs_compiler_create(rvmcpu_t *cpu)
582 {
583         rjs_compiler_t *co = (rjs_compiler_t *) r_zmalloc(sizeof(*co));
584
585         co->cg = rvm_codegen_create();
586         co->scope = rvm_scope_create();
587         co->coctx = r_array_create(sizeof(rjs_coctx_t *));
588         co->cpu = cpu;
589         r_memset(co->handlers, 0, sizeof(co->handlers));
590
591         co->handlers[UID_PROGRAM] = rjs_compiler_rh_program;
592         co->handlers[UID_EXPRESSION] = rjs_compiler_rh_expression;
593         co->handlers[UID_LEFTHANDSIDEEXPRESSION] = rjs_compiler_rh_lefthandsideexpression;
594         co->handlers[UID_LEFTHANDSIDEEXPRESSIONADDR] = rjs_compiler_rh_lefthandsideexpressionaddr;
595         co->handlers[UID_DECIMALINTEGERLITERAL] = rjs_compiler_rh_decimalintegerliteral;
596         co->handlers[UID_DECIMALNONINTEGERLITERAL] = rjs_compiler_rh_decimalnonintegerliteral;
597         co->handlers[UID_ADDITIVEEXPRESSIONOP] = rjs_compiler_rh_expressionop;
598         co->handlers[UID_MULTIPLICATIVEEXPRESSIONOP] = rjs_compiler_rh_expressionop;
599         co->handlers[UID_BITWISEANDOP] = rjs_compiler_rh_expressionop;
600         co->handlers[UID_BITWISEXOROP] = rjs_compiler_rh_expressionop;
601         co->handlers[UID_BITWISEOROP] = rjs_compiler_rh_expressionop;
602         co->handlers[UID_SHIFTEXPRESSIONOP] = rjs_compiler_rh_expressionop;
603         co->handlers[UID_EQUALITYEXPRESSIONOP] = rjs_compiler_rh_expressionop;
604         co->handlers[UID_RELATIONALEXPRESSIONOP] = rjs_compiler_rh_expressionop;
605         co->handlers[UID_LOGICALOROP] = rjs_compiler_rh_expressionop;
606         co->handlers[UID_LOGICALANDOP] = rjs_compiler_rh_expressionop;
607         co->handlers[UID_VARIABLEALLOCATEANDINIT] = rjs_compiler_rh_varallocinit;
608         co->handlers[UID_VARIABLEALLOCATE] = rjs_compiler_rh_varalloc;
609         co->handlers[UID_IDENTIFIER] = rjs_compiler_rh_identifier;
610         co->handlers[UID_INITIALISER] = rjs_compiler_rh_initializer;
611         co->handlers[UID_ASSIGNMENTEXPRESSIONOP] = rjs_compiler_rh_assignmentexpressionop;
612         co->handlers[UID_NEWARRAYEXPRESSION] = rjs_compiler_rh_newarrayexpression;
613         co->handlers[UID_MEMBEREXPRESSIONDOTOP] = rjs_compiler_rh_memberexpressiondotop;
614
615         return co;
616 }
617
618
619 void rjs_compiler_destroy(rjs_compiler_t *co)
620 {
621         if (co) {
622                 rvm_codegen_destroy(co->cg);
623                 rvm_scope_destroy(co->scope);
624                 r_array_destroy(co->coctx);
625                 r_free(co->temp);
626                 co->cpu = NULL;
627                 r_free(co);
628         }
629 }
630
631
632 static rint rjs_compiler_rh_default(rjs_compiler_t *co, rarray_t *records, rlong rec)
633 {
634         rparecord_t *prec;
635
636         prec = (rparecord_t *)r_array_slot(records, rec);
637         rjs_compiler_debughead(co, records, rec);
638         rjs_compiler_debugtail(co, records, rec);
639
640         if (rjs_compiler_playchildrecords(co, records, rec) < 0)
641                 return -1;
642
643         rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
644         prec = (rparecord_t *)r_array_slot(records, rec);
645         rjs_compiler_debughead(co, records, rec);
646         rjs_compiler_debugtail(co, records, rec);
647
648         return 0;
649 }
650
651
652 static rint rjs_compiler_playchildrecords(rjs_compiler_t *co, rarray_t *records, rlong rec)
653 {
654         rlong child;
655
656         for (child = rpa_recordtree_firstchild(records, rec, RPA_RECORD_START); child >= 0; child = rpa_recordtree_next(records, child, RPA_RECORD_START)) {
657                 if (rjs_compiler_playrecord(co, records, child) < 0)
658                         return -1;
659         }
660
661         return 0;
662 }
663
664
665 rint rjs_compiler_playreversechildrecords(rjs_compiler_t *co, rarray_t *records, rlong rec)
666 {
667         rlong child;
668
669         for (child = rpa_recordtree_lastchild(records, rec, RPA_RECORD_START); child >= 0; child = rpa_recordtree_prev(records, child, RPA_RECORD_START)) {
670                 if (rjs_compiler_playrecord(co, records, child) < 0)
671                         return -1;
672         }
673
674         return 0;
675 }
676
677
678 static rint rjs_compiler_playrecord(rjs_compiler_t *co, rarray_t *records, rlong rec)
679 {
680         rparecord_t *prec;
681         prec = (rparecord_t *)r_array_slot(records, rec);
682         if (prec->ruleuid >= 0 && prec->ruleuid < RJS_COMPILER_NHANDLERS && co->handlers[prec->ruleuid]) {
683                 return co->handlers[prec->ruleuid](co, records, rec);
684         }
685         return rjs_compiler_rh_default(co, records, rec);
686 }
687
688
689 rint rjs_compiler_compile(rjs_compiler_t *co, rarray_t *records)
690 {
691         rlong i;
692
693         if (!co || !records || r_array_empty(records)) {
694
695                 return -1;
696         }
697
698         for (i = 0; i >= 0; i = rpa_recordtree_next(records, i, RPA_RECORD_START)) {
699                 if (rjs_compiler_playrecord(co, records, i) < 0)
700                         return -1;
701         }
702         return 0;
703 }