RPA Toolkit
Fixed SYNTAX_ERROR reporting. Added a few string operations (SWI).
[rpatk.git] / rjs / rjs.c
1 #include "rmem.h"
2 #include "rjsobject.h"
3 #include "rjs.h"
4 #include "rvmcodegen.h"
5
6
7 static void rjs_engine_print(rvmcpu_t *cpu, rvm_asmins_t *ins);
8 static void rjs_engine_dbgprint(rvmcpu_t *cpu, rvm_asmins_t *ins);
9 static void rjs_engine_object(rvmcpu_t *cpu, rvm_asmins_t *ins);
10 static rvm_switable_t rjsswitable[] = {
11                 {"print", rjs_engine_print},
12                 {"dbgprint", rjs_engine_dbgprint},
13                 {"Object", rjs_engine_object},
14                 {"Array", rjs_engine_object},
15                 {NULL, NULL},
16 };
17
18
19 const rchar *rjs_version()
20 {
21         return RJS_VERSION_STRING;
22 }
23
24
25 rjs_engine_t *rjs_engine_create()
26 {
27         rvmreg_t *tp;
28         rjs_engine_t *jse = (rjs_engine_t *) r_zmalloc(sizeof(*jse));
29
30         jse->pa = rjs_parser_create();
31         jse->cpu = rvm_cpu_create_default();
32         jse->co = rjs_compiler_create(jse->cpu);
33         jse->cgs = r_array_create(sizeof(rvm_codegen_t*));
34         jse->errors = r_array_create(sizeof(rjs_error_t));
35         jse->cpu->userdata1 = jse;
36         rvm_cpu_addswitable(jse->cpu, "rjsswitable", rjsswitable);
37         if (!jse->pa || !jse->cpu || !jse->co || !jse->cgs)
38                 goto error;
39         tp = rvm_cpu_alloc_global(jse->cpu);
40         rvm_reg_setjsobject(tp, (robject_t *)rjs_object_create(sizeof(rvmreg_t)));
41         rvm_gc_add(jse->cpu->gc, (robject_t*)RVM_REG_GETP(tp));
42         rvm_cpu_setreg(jse->cpu, TP, tp);
43         return jse;
44 error:
45         rjs_engine_destroy(jse);
46         return NULL;
47 }
48
49
50 void rjs_engine_destroy(rjs_engine_t *jse)
51 {
52         rlong i;
53         if (jse) {
54                 if (jse->cgs) {
55                         for (i = 0; i < r_array_length(jse->cgs); i++) {
56                                 rvm_codegen_destroy(r_array_index(jse->cgs, i, rvm_codegen_t*));
57                         }
58                 }
59                 r_array_destroy(jse->cgs);
60                 r_array_destroy(jse->errors);
61                 rjs_parser_destroy(jse->pa);
62                 rvm_cpu_destroy(jse->cpu);
63                 rjs_compiler_destroy(jse->co);
64                 r_free(jse);
65         }
66 }
67
68
69 rint rjs_engine_open(rjs_engine_t *jse)
70 {
71         return 0;
72 }
73
74
75 rint rjs_engine_addswitable(rjs_engine_t *jse, const rchar *tabname, rvm_switable_t *switalbe)
76 {
77         return rvm_cpu_addswitable(jse->cpu, tabname, switalbe);
78 }
79
80
81 static rint rjs_engine_parse(rjs_engine_t *jse, const rchar *script, rsize_t size, rarray_t *records, rjs_error_t *error)
82 {
83         rlong res = 0;
84
85         res = rjs_parser_exec(jse->pa, script, size, records, error);
86         return res;
87 }
88
89
90 rint rjs_engine_compile(rjs_engine_t *jse, const rchar *script, rsize_t size)
91 {
92         rvm_codegen_t *topcg = NULL;
93         rarray_t *records = rpa_records_create();
94         rjs_error_t error;
95         jse->co->debug = jse->debugcompile;
96
97         r_memset(&error, 0, sizeof(error));
98         if (rjs_engine_parse(jse, script, size, records, &error) < 0) {
99
100                 goto err;
101         }
102
103         topcg =  r_array_empty(jse->cgs) ? NULL : r_array_last(jse->cgs, rvm_codegen_t*);
104         if (!topcg || (topcg->userdata & RJS_COMPILER_CODEGENKEEP) == 1) {
105                 topcg = rvm_codegen_create();
106                 r_array_add(jse->cgs, &topcg);
107         } else {
108                 rvm_codegen_clear(topcg);
109         }
110         topcg->userdata = 0;
111         if (rjs_compiler_compile(jse->co, script, size, records, topcg, &error) < 0) {
112                 topcg->userdata = 0;
113                 goto err;
114         }
115
116         rpa_records_destroy(records);
117         return 0;
118
119 err:
120         r_array_add(jse->errors, &error);
121         rpa_records_destroy(records);
122         return -1;
123 }
124
125
126 rint rjs_engine_dumpast(rjs_engine_t *jse, const rchar *script, rsize_t size)
127 {
128         rjs_error_t error;
129         rarray_t *records = rpa_records_create();
130
131         if (rjs_engine_parse(jse, script, size, records, &error) < 0) {
132
133
134                 return -1;
135         }
136
137         if (records) {
138                 rlong i;
139                 for (i = 0; i < rpa_records_length(records); i++)
140                         rpa_record_dump(records, i);
141         }
142
143         rpa_records_destroy(records);
144         return 0;
145 }
146
147
148 rint rjs_engine_compile_s(rjs_engine_t *jse, const rchar *script)
149 {
150         return rjs_engine_compile(jse, script, r_strlen(script));
151 }
152
153
154 rint rjs_engine_close(rjs_engine_t *jse)
155 {
156
157         return 0;
158 }
159
160
161 rint rjs_engine_run(rjs_engine_t *jse)
162 {
163         rint res = 0;
164         rvm_codegen_t *cg = r_array_empty(jse->cgs) ? NULL : r_array_last(jse->cgs, rvm_codegen_t*);
165
166         if (!cg) {
167
168                 return -1;
169         }
170         if (jse->debugexec) {
171                 res = rvm_cpu_exec_debug(jse->cpu, rvm_codegen_getcode(cg, 0), 0);
172         } else {
173                 res = rvm_cpu_exec(jse->cpu, rvm_codegen_getcode(cg, 0), 0);
174         }
175         return res;
176 }
177
178
179 rvmreg_t * rjs_engine_exec(rjs_engine_t *jse, const rchar *script, rsize_t size)
180 {
181         if (rjs_engine_compile(jse, script, size) < 0)
182                 return NULL;
183         if (rjs_engine_run(jse) < 0)
184                 return NULL;
185         return RVM_CPUREG_PTR(jse->cpu, R0);
186 }
187
188
189 rvmreg_t *rjs_engine_exec_s(rjs_engine_t *jse, const rchar *script)
190 {
191         return rjs_engine_exec(jse, script, r_strlen(script));
192 }
193
194
195 static void rjs_engine_print(rvmcpu_t *cpu, rvm_asmins_t *ins)
196 {
197         rvmreg_t *r = (rvmreg_t *)RVM_STACK_ADDR(cpu->stack, RVM_CPUREG_GETU(cpu, FP) + 1);
198
199         if (rvm_reg_gettype(r) == RVM_DTYPE_UNSIGNED)
200                 r_printf("%lu\n", RVM_REG_GETU(r));
201         else if (rvm_reg_gettype(r) == RVM_DTYPE_NAN)
202                 r_printf("NaN\n");
203         else if (rvm_reg_gettype(r) == RVM_DTYPE_UNDEF)
204                 r_printf("undefined\n");
205         else if (rvm_reg_gettype(r) == RVM_DTYPE_BOOLEAN)
206                 r_printf("%s\n", RVM_REG_GETU(r) ? "true" : "false");
207         else if (rvm_reg_gettype(r) == RVM_DTYPE_POINTER)
208                 r_printf("%p\n", RVM_REG_GETP(r));
209         else if (rvm_reg_gettype(r) == RVM_DTYPE_LONG)
210                 r_printf("%ld\n", RVM_REG_GETL(r));
211         else if (rvm_reg_gettype(r) == RVM_DTYPE_DOUBLE)
212                 r_printf("%f\n", RVM_REG_GETD(r));
213         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRING)
214                 r_printf("%s\n", ((rstring_t*) RVM_REG_GETP(r))->s.str);
215         else if (rvm_reg_gettype(r) == RVM_DTYPE_JSOBJECT)
216                 r_printf("(object) %p\n",RVM_REG_GETP(r));
217         else if (rvm_reg_gettype(r) == RVM_DTYPE_HARRAY)
218                 r_printf("(hashed array) %p\n",RVM_REG_GETP(r));
219         else if (rvm_reg_gettype(r) == RVM_DTYPE_SWIID)
220                 r_printf("(function) %p\n",RVM_REG_GETP(r));
221         else
222                 r_printf("%p\n", RVM_REG_GETP(r));
223 }
224
225
226 static void rjs_engine_dbgprint(rvmcpu_t *cpu, rvm_asmins_t *ins)
227 {
228         rvmreg_t *r = (rvmreg_t *)RVM_STACK_ADDR(cpu->stack, RVM_CPUREG_GETU(cpu, FP) + 1);
229
230         if (rvm_reg_gettype(r) == RVM_DTYPE_UNSIGNED)
231                 r_printf("(UNSIGNED) %lu\n", RVM_REG_GETU(r));
232         else if (rvm_reg_gettype(r) == RVM_DTYPE_NAN)
233                 r_printf("(NAN) NaN\n");
234         else if (rvm_reg_gettype(r) == RVM_DTYPE_UNDEF)
235                 r_printf("(UNDEF) undefined\n");
236         else if (rvm_reg_gettype(r) == RVM_DTYPE_BOOLEAN)
237                 r_printf("(BOOLEAN) %s\n", RVM_REG_GETU(r) ? "true" : "false");
238         else if (rvm_reg_gettype(r) == RVM_DTYPE_POINTER)
239                 r_printf("(POINTER) %p\n", RVM_REG_GETP(r));
240         else if (rvm_reg_gettype(r) == RVM_DTYPE_LONG)
241                 r_printf("(LONG) %ld\n", RVM_REG_GETL(r));
242         else if (rvm_reg_gettype(r) == RVM_DTYPE_DOUBLE)
243                 r_printf("(DOUBLE) %f\n", RVM_REG_GETD(r));
244         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRING)
245                 r_printf("(STRING) %s\n", ((rstring_t*) RVM_REG_GETP(r))->s.str);
246         else if (rvm_reg_gettype(r) == RVM_DTYPE_JSOBJECT)
247                 r_printf("(object) %p\n",RVM_REG_GETP(r));
248         else if (rvm_reg_gettype(r) == RVM_DTYPE_HARRAY)
249                 r_printf("(hashed array) %p\n",RVM_REG_GETP(r));
250         else if (rvm_reg_gettype(r) == RVM_DTYPE_SWIID)
251                 r_printf("(swi function) %p\n",RVM_REG_GETP(r));
252         else if (rvm_reg_gettype(r) == RVM_DTYPE_FUNCTION)
253                 r_printf("(function) %p\n",RVM_REG_GETP(r));
254         else
255                 r_printf("%p\n", RVM_REG_GETP(r));
256 }
257
258
259 static void rjs_engine_object(rvmcpu_t *cpu, rvm_asmins_t *ins)
260 {
261
262 }
263
264
265 void rjs_engine_abort(rjs_engine_t *jse, rjs_error_t *error)
266 {
267         if (error) {
268                 r_array_add(jse->errors, error);
269         }
270         rvm_cpu_abort(jse->cpu);
271 }
272
273
274 rjs_engine_t *rjs_engine_get(rvmcpu_t *cpu)
275 {
276         return (rjs_engine_t *)cpu->userdata1;
277 }