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