RPA Toolkit
b7efb52a52b86fe71e6e15595dbcb54579d06b49
[rpatk.git] / rjs / rjs.c
1 /*
2  *  Regular Pattern Analyzer (RPA)
3  *  Copyright (c) 2009-2010 Martin Stoilov
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  *  Martin Stoilov <martin@rpasearch.com>
19  */
20
21 #include <stdarg.h>
22 #include "rlib/rmem.h"
23 #include "rlib/rmap.h"
24 #include "rjs/rjs.h"
25 #include "rvm/rvmcodegen.h"
26 #include "rvmoperator.h"
27 #include "rvmoperatorbin.h"
28 #include "rvmoperatorcast.h"
29 #include "rvmoperatornot.h"
30 #include "rvmoperatorlogicnot.h"
31
32
33 static void rjs_engine_initgp(rjs_engine_t *jse);
34 static void rjs_engine_print(rvmcpu_t *cpu, rvm_asmins_t *ins);
35 static void rjs_engine_dbgprint(rvmcpu_t *cpu, rvm_asmins_t *ins);
36 static void rjs_engine_object(rvmcpu_t *cpu, rvm_asmins_t *ins);
37 static void rjs_string_ltrim(rvmcpu_t *cpu, rvm_asmins_t *ins);
38 static void rjs_string_length(rvmcpu_t *cpu, rvm_asmins_t *ins);
39
40 static rvm_switable_t rjsswitable[] = {
41                 {"print", rjs_engine_print},
42                 {"dbgprint", rjs_engine_dbgprint},
43                 {"Object", rjs_engine_object},
44                 {"Array", rjs_engine_object},
45                 {"string.ltrim", rjs_string_ltrim},
46                 {"string.length", rjs_string_length},
47                 {NULL, NULL},
48 };
49
50
51 static void rjs_op_cast(rvmcpu_t *cpu, rvm_asmins_t *ins)
52 {
53         rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETU(cpu, ins->op3);
54         rvmreg_t tmp;
55
56         RVM_REG_CLEAR(&tmp);
57         RVM_REG_SETTYPE(&tmp, type);
58         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, RVM_CPUREG_PTR(cpu, ins->op1), RVM_CPUREG_PTR(cpu, ins->op2), &tmp);
59 }
60
61
62 static void rjs_op_eadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
63 {
64         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
65         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
66
67         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_ADD, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
68 }
69
70
71 static void rjs_op_esub(rvmcpu_t *cpu, rvm_asmins_t *ins)
72 {
73         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
74         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
75
76         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_SUB, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
77 }
78
79
80 static void rjs_op_eneg(rvmcpu_t *cpu, rvm_asmins_t *ins)
81 {
82         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
83         rvmreg_t zero;
84
85         rvm_reg_setunsigned(&zero, 0);
86         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_SUB, cpu, RVM_CPUREG_PTR(cpu, ins->op1), &zero, arg2);
87 }
88
89
90
91 static void rjs_op_emul(rvmcpu_t *cpu, rvm_asmins_t *ins)
92 {
93         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
94         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
95
96         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_MUL, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
97 }
98
99
100 static void rjs_op_ediv(rvmcpu_t *cpu, rvm_asmins_t *ins)
101 {
102         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
103         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
104
105         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_DIV, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
106 }
107
108
109 static void rjs_op_emod(rvmcpu_t *cpu, rvm_asmins_t *ins)
110 {
111         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
112         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
113
114         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_MOD, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
115 }
116
117
118 static void rjs_op_elsl(rvmcpu_t *cpu, rvm_asmins_t *ins)
119 {
120         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
121         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
122
123         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LSL, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
124 }
125
126
127 static void rjs_op_elsr(rvmcpu_t *cpu, rvm_asmins_t *ins)
128 {
129         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
130         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
131
132         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LSR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
133 }
134
135
136 static void rjs_op_elsru(rvmcpu_t *cpu, rvm_asmins_t *ins)
137 {
138         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
139         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
140
141         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LSRU, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
142 }
143
144
145 static void rjs_op_eand(rvmcpu_t *cpu, rvm_asmins_t *ins)
146 {
147         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
148         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
149
150         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_AND, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
151 }
152
153
154 static void rjs_op_eorr(rvmcpu_t *cpu, rvm_asmins_t *ins)
155 {
156         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
157         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
158
159         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_OR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
160 }
161
162
163 static void rjs_op_exor(rvmcpu_t *cpu, rvm_asmins_t *ins)
164 {
165         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
166         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
167
168         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_XOR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
169 }
170
171
172 static void rjs_op_enot(rvmcpu_t *cpu, rvm_asmins_t *ins)
173 {
174         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
175
176         rjs_opmap_invoke_unary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_NOT, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2);
177 }
178
179
180 static void rjs_op_eland(rvmcpu_t *cpu, rvm_asmins_t *ins)
181 {
182         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
183         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
184
185         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LOGICAND, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
186 }
187
188
189 static void rjs_op_elor(rvmcpu_t *cpu, rvm_asmins_t *ins)
190 {
191         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
192         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
193
194         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LOGICOR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
195 }
196
197
198 static void rjs_op_elnot(rvmcpu_t *cpu, rvm_asmins_t *ins)
199 {
200         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
201
202         rjs_opmap_invoke_unary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LOGICNOT, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2);
203 }
204
205
206 static void rjs_op_eeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
207 {
208         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
209         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
210
211         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_EQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
212 }
213
214
215 static void rjs_op_enoteq(rvmcpu_t *cpu, rvm_asmins_t *ins)
216 {
217         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
218         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
219
220         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_NOTEQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
221 }
222
223
224 static void rjs_op_egreat(rvmcpu_t *cpu, rvm_asmins_t *ins)
225 {
226         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
227         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
228
229         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_GREATER, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
230 }
231
232
233 static void rjs_op_egreateq(rvmcpu_t *cpu, rvm_asmins_t *ins)
234 {
235         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
236         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
237
238         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_GREATEREQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
239 }
240
241
242 static void rjs_op_elesseq(rvmcpu_t *cpu, rvm_asmins_t *ins)
243 {
244         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
245         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
246
247         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LESSEQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
248 }
249
250
251 static void rjs_op_eless(rvmcpu_t *cpu, rvm_asmins_t *ins)
252 {
253         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
254         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
255
256         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LESS, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
257 }
258
259
260 static void rjs_op_ecmp(rvmcpu_t *cpu, rvm_asmins_t *ins)
261 {
262         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
263         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
264
265         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CMP, cpu, NULL, arg1, arg2);
266 }
267
268
269 static void rjs_op_ecmn(rvmcpu_t *cpu, rvm_asmins_t *ins)
270 {
271         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
272         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
273
274         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CMN, cpu, NULL, arg1, arg2);
275 }
276
277
278 static void rjs_op_stralloc(rvmcpu_t *cpu, rvm_asmins_t *ins)
279 {
280         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
281         rstring_t *s = r_string_create_strsize((const char*)RVM_CPUREG_GETP(cpu, ins->op2), (unsigned long)RVM_CPUREG_GETU(cpu, ins->op3));
282         if (!s) {
283                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
284         }
285         r_gc_add(cpu->gc, (robject_t*)s);
286         rvm_reg_setstring(arg1, s);
287 }
288
289
290 static void rjs_op_mapalloc(rvmcpu_t *cpu, rvm_asmins_t *ins)
291 {
292         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
293         rmap_t *a = r_map_create(sizeof(rvmreg_t), 7);
294         if (!a) {
295                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
296         }
297         r_gc_add(cpu->gc, (robject_t*)a);
298         rvm_reg_setjsobject(arg1, (robject_t*)a);
299 }
300
301
302 static long rjs_op_mapproplookupadd(rmap_t *map, rvmcpu_t *cpu, rvm_asmins_t *ins)
303 {
304         long index;
305         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
306
307         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SIGNED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
308                 index = r_map_lookup_l(map, -1, (long)RVM_REG_GETL(arg3));
309                 if (index < 0)
310                         index = r_map_gckey_add_l(map, cpu->gc, (long)RVM_REG_GETL(arg3), NULL);
311         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
312                 index = r_map_lookup_d(map, -1, RVM_REG_GETD(arg3));
313                 if (index < 0)
314                         index = r_map_gckey_add_d(map, cpu->gc, RVM_REG_GETD(arg3), NULL);
315         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
316                 index = r_map_lookup(map, -1, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size);
317                 if (index < 0)
318                         index = r_map_gckey_add(map, cpu->gc, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size, NULL);
319         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
320                 index = r_map_lookup(map, -1, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1));
321                 if (index < 0)
322                         index = r_map_gckey_add(map, cpu->gc, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1), NULL);
323         } else {
324                 index = -1;
325         }
326
327         return index;
328 }
329
330
331 static void rjs_op_proplookupadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
332 {
333         long index = -1;
334         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
335         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
336         rmap_t *map = (rmap_t*)RVM_REG_GETP(arg2);
337
338         if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
339                 index = rjs_op_mapproplookupadd(map, cpu, ins);
340         } else {
341
342         }
343         RVM_REG_CLEAR(arg1);
344         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
345         RVM_REG_SETL(arg1, index);
346 }
347
348
349 static long rjs_op_mapproplookup(rmap_t *map, rvmcpu_t *cpu, rvm_asmins_t *ins)
350 {
351         long index = -1;
352         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
353
354         if (!map)
355                 return -1;
356         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SIGNED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
357                 index = r_map_lookup_l(map, -1, (long)RVM_REG_GETL(arg3));
358         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
359                 index = r_map_lookup_d(map, -1, RVM_REG_GETD(arg3));
360         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
361                 index = r_map_lookup(map, -1, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size);
362         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
363                 index = r_map_lookup(map, -1, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1));
364         }
365         return index;
366 }
367
368
369 static long rjs_op_stringproplookup(rstring_t *str, rvmcpu_t *cpu, rvm_asmins_t *ins)
370 {
371         long index = -1;
372         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
373
374         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SIGNED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
375                 index = RVM_REG_GETL(arg3);
376         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
377                 index = (long)RVM_REG_GETD(arg3);
378         }
379
380         if (index >= str->s.size)
381                 index = -1;
382         return index;
383 }
384
385
386 static void rjs_op_propget(rvmcpu_t *cpu, rvm_asmins_t *ins)
387 {
388         long index = -1;
389         rmap_t *map;
390         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
391         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
392
393         if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
394                 rmap_t *map = (rmap_t*)RVM_REG_GETP(arg2);
395                 index = rjs_op_mapproplookup(map, cpu, ins);
396                 if (index >= 0) {
397                         *arg1 = *((rvmreg_t*)r_map_value(map, index));
398                         return;
399                 }
400         } else if (rvm_reg_gettype(arg2) == RVM_DTYPE_STRING) {
401                 rstring_t *str = (rstring_t*)RVM_REG_GETP(arg2);
402                 index = rjs_op_stringproplookup(str, cpu, ins);
403                 if (index >= 0) {
404                         rstring_t * allocstr = r_string_create_strsize(&str->s.str[index], 1);
405                         r_gc_add(cpu->gc, (robject_t*)allocstr);
406                         rvm_reg_setstring(arg1, allocstr);
407                         return;
408                 }
409         }
410
411         map = rjs_engine_get(cpu)->props[rvm_reg_gettype(arg2)];
412         index = rjs_op_mapproplookup(map, cpu, ins);
413         if (index >= 0) {
414                 rvmreg_t *val = (rvmreg_t*)r_map_value(map, index);
415                 if (RVM_REG_GETTYPE(val) == RVM_DTYPE_PROPHANDLER) {
416                         ((rvmcpu_op)RVM_REG_GETP(val))(cpu, ins);
417                 } else {
418                         *arg1 = *val;
419                 }
420                 return;
421         }
422         rvm_reg_setundef(arg1);
423 }
424
425
426 static void rjs_op_propset(rvmcpu_t *cpu, rvm_asmins_t *ins)
427 {
428         long index = -1;
429         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
430         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
431         rmap_t *map = (rmap_t*)RVM_REG_GETP(arg2);
432         rpointer value = NULL;
433
434         if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
435                 index = rjs_op_mapproplookupadd(map, cpu, ins);
436                 value = r_map_value(map, index);
437         }
438         if (!value) {
439                 value = &rjs_engine_get(cpu)->scratch;
440         }
441         RVM_REG_CLEAR(arg1);
442         RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
443         RVM_REG_SETP(arg1, value);
444 }
445
446
447 static void rjs_op_proplookup(rvmcpu_t *cpu, rvm_asmins_t *ins)
448 {
449         long index = -1;
450         rboolean globalprop = 0;
451         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
452         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
453
454         if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
455                 rmap_t *map = (rmap_t*)RVM_REG_GETP(arg2);
456                 index = rjs_op_mapproplookup(map, cpu, ins);
457                 rvm_reg_setsigned(arg1, index);
458         } else if (rvm_reg_gettype(arg2) == RVM_DTYPE_STRING) {
459                 rstring_t *str = (rstring_t*)RVM_REG_GETP(arg2);
460                 index = rjs_op_stringproplookup(str, cpu, ins);
461                 if (index < 0) {
462                         index = rjs_op_mapproplookup(rjs_engine_get(cpu)->props[RVM_DTYPE_STRING], cpu, ins);
463                         if (index >= 0)
464                                 globalprop = TRUE;
465                 }
466                 rvm_reg_setsigned(arg1, index);
467                 if (globalprop)
468                         RVM_REG_SETFLAG(arg1, RVM_INFOBIT_GLOBAL);
469         }
470 }
471
472
473 static void rjs_op_propstr(rvmcpu_t *cpu, rvm_asmins_t *ins)
474 {
475         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
476         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
477         rvmreg_t tmp = rvm_reg_create_signed(0);
478         rmap_t *a = NULL;
479         rpointer value;
480         long index;
481
482         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
483         index = (long)RVM_REG_GETL(&tmp);
484         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP) {
485
486                 return;
487         }
488         a = (rmap_t*)RVM_REG_GETP(arg2);
489         value = r_map_value(a, index);
490         if (!value)
491                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
492         r_map_setvalue(a, index, arg1);
493 }
494
495
496 static void rjs_op_propldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
497 {
498         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
499         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
500         rvmreg_t tmp = rvm_reg_create_signed(0);
501         rpointer value;
502         long index;
503
504         index = (long)RVM_REG_GETL(arg1);
505         if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
506                 rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
507                 value = r_map_value(a, index);
508                 if (value) {
509                         *arg1 = *((rvmreg_t*)value);
510                 }
511         } else if (rvm_reg_gettype(arg2) == RVM_DTYPE_STRING) {
512                 rstring_t *s = (rstring_t*)RVM_REG_GETP(arg2);
513                 if (RVM_REG_TSTFLAG(arg1, RVM_INFOBIT_GLOBAL)) {
514                         rmap_t *a = rjs_engine_get(cpu)->props[RVM_DTYPE_STRING];
515                         value = r_map_value(a, index);
516                         if (value) {
517                                 *arg1 = *((rvmreg_t*)value);
518                         }
519                 } else {
520                         rstring_t *allocstr;
521                         if (index >= s->s.size) {
522                                 rvm_reg_setundef(arg1);
523                                 return;
524                         }
525                         allocstr = r_string_create_strsize(&s->s.str[index], 1);
526                         r_gc_add(cpu->gc, (robject_t*)allocstr);
527                         rvm_reg_setstring(arg1, allocstr);
528                 }
529         } else {
530                 rvm_reg_setundef(arg1);
531         }
532 }
533
534
535 static void rjs_op_propkeyldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
536 {
537         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
538         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
539         rvmreg_t tmp = rvm_reg_create_signed(0);
540         rmap_t *map = NULL;
541         rstring_t *key;
542         long index;
543
544         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
545         index = (long)RVM_REG_GETL(&tmp);
546         RVM_REG_CLEAR(arg1);
547         RVM_REG_SETTYPE(arg1, RVM_DTYPE_UNDEF);
548         if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
549                 map = (rmap_t*)RVM_REG_GETP(arg2);
550                 key = r_map_key(map, index);
551                 if (key) {
552                         rvm_reg_setstring(arg1, key);
553                 }
554         } else if (rvm_reg_gettype(arg2) == RVM_DTYPE_STRING) {
555
556         }
557 }
558
559
560 static void rjs_op_propdel(rvmcpu_t *cpu, rvm_asmins_t *ins)
561 {
562         int ret;
563         long index;
564         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
565         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
566         rvmreg_t tmp = rvm_reg_create_signed(0);
567         rmap_t *a = NULL;
568
569         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
570         index = (long)RVM_REG_GETL(&tmp);
571         rvm_reg_setboolean(arg1, 0);
572         if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
573                 a = (rmap_t*)RVM_REG_GETP(arg2);
574                 ret = r_map_delete(a, index);
575                 rvm_reg_setboolean(arg1, ret == 0 ? 1 : 0);
576         }
577 }
578
579
580 static void rjs_op_propaddr(rvmcpu_t *cpu, rvm_asmins_t *ins)
581 {
582         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
583         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
584         rvmreg_t tmp = rvm_reg_create_signed(0);
585         rmap_t *a;
586         rpointer value;
587         long index;
588
589         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
590         index = (long)RVM_REG_GETL(&tmp);
591         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP)
592                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
593         a = (rmap_t*)RVM_REG_GETP(arg2);
594         value = r_map_value(a, index);
595         if (!value)
596                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
597         RVM_REG_CLEAR(arg1);
598         RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
599         RVM_REG_SETP(arg1, value);
600 }
601
602
603 static void rjs_op_propnext(rvmcpu_t *cpu, rvm_asmins_t *ins)
604 {
605         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
606         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
607         rvmreg_t tmp = rvm_reg_create_signed(0);
608         rmap_t *map = NULL;
609         long index = -1;
610
611         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
612         index = (long)RVM_REG_GETL(&tmp);
613         if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
614                 map = (rmap_t*)RVM_REG_GETP(arg2);
615                 if (index < 0)
616                         index = r_map_first(map);
617                 else
618                         index = r_map_next(map, index);
619         }
620         RVM_REG_CLEAR(arg1);
621         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
622         RVM_REG_SETL(arg1, index);
623 }
624
625
626 static void rjs_op_propprev(rvmcpu_t *cpu, rvm_asmins_t *ins)
627 {
628         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
629         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
630         rvmreg_t tmp = rvm_reg_create_signed(0);
631         rmap_t *map = NULL;
632         long index = -1;
633
634         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
635         index = (long)RVM_REG_GETL(&tmp);
636         if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
637                 map = (rmap_t*)RVM_REG_GETP(arg2);
638                 if (index < 0)
639                         index = r_map_last(map);
640                 else
641                         index = r_map_prev(map, index);
642         }
643         RVM_REG_CLEAR(arg1);
644         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
645         RVM_REG_SETL(arg1, index);
646 }
647
648
649 static void rjs_op_mapdel(rvmcpu_t *cpu, rvm_asmins_t *ins)
650 {
651         int ret;
652         long index;
653         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
654         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
655         rvmreg_t tmp = rvm_reg_create_signed(0);
656         rmap_t *a = NULL;
657
658         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
659         index = (long)RVM_REG_GETL(&tmp);
660         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP)
661                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
662         a = (rmap_t*)RVM_REG_GETP(arg2);
663         ret = r_map_delete(a, index);
664         rvm_reg_setboolean(arg1, ret == 0 ? 1 : 0);
665 }
666
667
668 static void rjs_op_maplookup(rvmcpu_t *cpu, rvm_asmins_t *ins)
669 {
670         long index;
671         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
672         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
673         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
674         rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
675
676         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP) {
677                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
678         }
679         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SIGNED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
680                 index = r_map_lookup_l(a, -1, (long)RVM_REG_GETL(arg3));
681         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
682                 index = r_map_lookup_d(a, -1, RVM_REG_GETD(arg3));
683         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
684                 index = r_map_lookup(a, -1, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size);
685         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
686                 index = r_map_lookup(a, -1, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1));
687         } else {
688                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
689         }
690
691         RVM_REG_CLEAR(arg1);
692         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
693         RVM_REG_SETL(arg1, index);
694 }
695
696
697 static void rjs_op_mapadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
698 {
699         long index;
700         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
701         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
702         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
703         rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
704
705         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP) {
706                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
707         }
708         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SIGNED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
709                 index = r_map_gckey_add_l(a, cpu->gc, (long)RVM_REG_GETL(arg3), NULL);
710         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
711                 index = r_map_gckey_add_d(a, cpu->gc, RVM_REG_GETD(arg3), NULL);
712         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
713                 index = r_map_gckey_add(a, cpu->gc, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size, NULL);
714         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
715                 index = r_map_gckey_add(a, cpu->gc, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1), NULL);
716         } else {
717                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
718         }
719
720         RVM_REG_CLEAR(arg1);
721         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
722         RVM_REG_SETL(arg1, index);
723 }
724
725
726 static void rjs_op_maplookupadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
727 {
728         long index;
729         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
730         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
731         rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
732         rmap_t *a = (rmap_t*)RVM_REG_GETP(arg2);
733
734         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP) {
735                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
736         }
737         if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_SIGNED || RVM_REG_GETTYPE(arg3) == RVM_DTYPE_UNSIGNED) {
738                 index = r_map_lookup_l(a, -1, (long)RVM_REG_GETL(arg3));
739                 if (index < 0)
740                         index = r_map_gckey_add_l(a, cpu->gc, (long)RVM_REG_GETL(arg3), NULL);
741         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_DOUBLE) {
742                 index = r_map_lookup_d(a, -1, RVM_REG_GETD(arg3));
743                 if (index < 0)
744                         index = r_map_gckey_add_d(a, cpu->gc, RVM_REG_GETD(arg3), NULL);
745         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_STRING) {
746                 index = r_map_lookup(a, -1, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size);
747                 if (index < 0)
748                         index = r_map_gckey_add(a, cpu->gc, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.str, ((rstring_t *)RVM_CPUREG_GETP(cpu, ins->op3))->s.size, NULL);
749         } else if (RVM_REG_GETTYPE(arg3) == RVM_DTYPE_POINTER) {
750                 index = r_map_lookup(a, -1, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1));
751                 if (index < 0)
752                         index = r_map_gckey_add(a, cpu->gc, (char*)RVM_CPUREG_GETP(cpu, ins->op3), (unsigned int)RVM_CPUREG_GETL(cpu, ins->op1), NULL);
753         } else {
754                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
755         }
756         RVM_REG_CLEAR(arg1);
757         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
758         RVM_REG_SETL(arg1, index);
759 }
760
761
762 static void rjs_op_mapaddr(rvmcpu_t *cpu, rvm_asmins_t *ins)
763 {
764         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
765         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
766         rvmreg_t tmp = rvm_reg_create_signed(0);
767         rmap_t *a;
768         rpointer value;
769         long index;
770
771         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
772         index = (long)RVM_REG_GETL(&tmp);
773         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP)
774                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
775         a = (rmap_t*)RVM_REG_GETP(arg2);
776         value = r_map_value(a, index);
777         if (!value)
778                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
779         RVM_REG_CLEAR(arg1);
780         RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
781         RVM_REG_SETP(arg1, value);
782 }
783
784
785 static void rjs_op_mapldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
786 {
787         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
788         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
789         rvmreg_t tmp = rvm_reg_create_signed(0);
790         rmap_t *a = NULL;
791         rpointer value;
792         long index;
793
794         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
795         index = (long)RVM_REG_GETL(&tmp);
796         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP)
797                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
798         a = (rmap_t*)RVM_REG_GETP(arg2);
799         value = r_map_value(a, index);
800         if (!value) {
801                 RVM_REG_CLEAR(arg1);
802                 RVM_REG_SETTYPE(arg1, RVM_DTYPE_UNDEF);
803         } else {
804                 *arg1 = *((rvmreg_t*)value);
805         }
806 }
807
808
809 static void rjs_op_mapkeyldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
810 {
811         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
812         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
813         rvmreg_t tmp = rvm_reg_create_signed(0);
814         rmap_t *a = NULL;
815         rstring_t *key;
816         long index;
817
818         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
819         index = (long)RVM_REG_GETL(&tmp);
820         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP)
821                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
822         a = (rmap_t*)RVM_REG_GETP(arg2);
823         key = r_map_key(a, index);
824         if (!key) {
825                 RVM_REG_CLEAR(arg1);
826                 RVM_REG_SETTYPE(arg1, RVM_DTYPE_UNDEF);
827         } else {
828                 rvm_reg_setstring(arg1, key);
829         }
830 }
831
832
833 static void rjs_op_mapnext(rvmcpu_t *cpu, rvm_asmins_t *ins)
834 {
835         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
836         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
837         rvmreg_t tmp = rvm_reg_create_signed(0);
838         rmap_t *a = NULL;
839         long index;
840
841         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
842         index = (long)RVM_REG_GETL(&tmp);
843         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP)
844                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
845         a = (rmap_t*)RVM_REG_GETP(arg2);
846         if (index < 0)
847                 index = r_map_first(a);
848         else
849                 index = r_map_next(a, index);
850         RVM_REG_CLEAR(arg1);
851         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
852         RVM_REG_SETL(arg1, index);
853 }
854
855
856 static void rjs_op_mapprev(rvmcpu_t *cpu, rvm_asmins_t *ins)
857 {
858         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
859         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
860         rvmreg_t tmp = rvm_reg_create_signed(0);
861         rmap_t *a = NULL;
862         long index;
863
864         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
865         index = (long)RVM_REG_GETL(&tmp);
866         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP)
867                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
868         a = (rmap_t*)RVM_REG_GETP(arg2);
869         if (index < 0)
870                 index = r_map_last(a);
871         else
872                 index = r_map_prev(a, index);
873         RVM_REG_CLEAR(arg1);
874         RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
875         RVM_REG_SETL(arg1, index);
876 }
877
878
879 static void rjs_op_mapstr(rvmcpu_t *cpu, rvm_asmins_t *ins)
880 {
881         rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
882         rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
883         rvmreg_t tmp = rvm_reg_create_signed(0);
884         rmap_t *a = NULL;
885         rpointer value;
886         long index;
887
888         rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CAST, cpu, &tmp, RVM_CPUREG_PTR(cpu, ins->op3), &tmp);
889         index = (long)RVM_REG_GETL(&tmp);
890         if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP)
891                 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
892         a = (rmap_t*)RVM_REG_GETP(arg2);
893         value = r_map_value(a, index);
894         if (!value)
895                 RVM_ABORT(cpu, RVM_E_ILLEGAL);
896         r_map_setvalue(a, index, arg1);
897 }
898
899
900 const char *rjs_version()
901 {
902         return RJS_VERSION_STRING;
903 }
904
905
906 static void rjs_string_ltrim(rvmcpu_t *cpu, rvm_asmins_t *ins)
907 {
908         const char *ptr, *list;
909         unsigned long size;
910         rvmreg_t *r = NULL, *l = NULL;
911         rstring_t *src, *dest;
912
913         r = (rvmreg_t *) RVM_CPUREG_PTR(cpu, TP);
914         if (RJS_SWI_PARAMS(cpu) > 0) {
915                 l = (rvmreg_t *) RJS_SWI_PARAM(cpu, 1);
916                 if (rvm_reg_gettype(l) != RVM_DTYPE_STRING)
917                         RJS_SWI_ABORT(rjs_engine_get(cpu), NULL);
918         }
919         if (rvm_reg_gettype(r) != RVM_DTYPE_STRING)
920                 RJS_SWI_ABORT(rjs_engine_get(cpu), NULL);
921         if (l)
922                 list = ((rstring_t *)RVM_REG_GETP(l))->s.str;
923         else
924                 list = " \t\n\r\0";
925         src = (rstring_t *)RVM_REG_GETP(r);
926         ptr = src->s.str;
927         size = src->s.size;
928         while (size > 0) {
929                 if (!r_strchr(list, *ptr))
930                         break;
931                 size--;
932                 ptr++;
933         }
934         dest = r_string_create_strsize(ptr, size);
935         r_gc_add(cpu->gc, (robject_t*)dest);
936         rvm_reg_setstring(RVM_CPUREG_PTR(cpu, R0), dest);
937 }
938
939
940 static void rjs_string_length(rvmcpu_t *cpu, rvm_asmins_t *ins)
941 {
942         unsigned long size;
943         rvmreg_t *r = NULL;
944         rstring_t *src;
945
946         r = (rvmreg_t *) RVM_CPUREG_PTR(cpu, ins->op2);
947         if (rvm_reg_gettype(r) != RVM_DTYPE_STRING)
948                 RJS_SWI_ABORT(rjs_engine_get(cpu), NULL);
949         src = (rstring_t *)RVM_REG_GETP(r);
950         size = src->s.size;
951         rvm_reg_setsigned(RVM_CPUREG_PTR(cpu, R0), size);
952 }
953
954
955 rjs_engine_t *rjs_engine_create()
956 {
957         rvmcpu_t *cpu;
958         rvmreg_t *tp;
959         rjs_engine_t *jse = (rjs_engine_t *) r_zmalloc(sizeof(*jse));
960
961         jse->pa = rjs_parser_create();
962         jse->cpu = cpu = rvm_cpu_create_default();
963         jse->co = rjs_compiler_create(jse->cpu);
964         jse->cgs = r_array_create(sizeof(rvm_codegen_t*));
965         jse->errors = r_array_create(sizeof(rjs_error_t));
966         jse->cpu->userdata1 = jse;
967         rvm_cpu_addswitable(jse->cpu, "rjsswitable", rjsswitable);
968         if (!jse->pa || !jse->cpu || !jse->co || !jse->cgs)
969                 goto error;
970         rjs_engine_initgp(jse);
971         tp = rvm_cpu_alloc_global(jse->cpu);
972         rvm_reg_setjsobject(tp, (robject_t *)r_map_create(sizeof(rvmreg_t), 7));
973         r_gc_add(jse->cpu->gc, (robject_t*)RVM_REG_GETP(tp));
974         rvm_cpu_setreg(jse->cpu, TP, tp);
975
976         rvm_cpu_setophandler(cpu, RJS_CAST, "RJS_CAST", rjs_op_cast);
977         rvm_cpu_setophandler(cpu, RJS_ENEG, "RJS_ENEG", rjs_op_eneg);
978         rvm_cpu_setophandler(cpu, RJS_EADD, "RJS_EADD", rjs_op_eadd);
979         rvm_cpu_setophandler(cpu, RJS_ESUB, "RJS_ESUB", rjs_op_esub);
980         rvm_cpu_setophandler(cpu, RJS_EMUL, "RJS_EMUL", rjs_op_emul);
981         rvm_cpu_setophandler(cpu, RJS_EDIV, "RJS_EDIV", rjs_op_ediv);
982         rvm_cpu_setophandler(cpu, RJS_EMOD, "RJS_EMOD", rjs_op_emod);
983         rvm_cpu_setophandler(cpu, RJS_ELSL, "RJS_ELSL", rjs_op_elsl);
984         rvm_cpu_setophandler(cpu, RJS_ELSR, "RJS_ELSR", rjs_op_elsr);
985         rvm_cpu_setophandler(cpu, RJS_ELSRU, "RJS_ELSRU", rjs_op_elsru);
986         rvm_cpu_setophandler(cpu, RJS_EAND, "RJS_EAND", rjs_op_eand);
987         rvm_cpu_setophandler(cpu, RJS_EORR, "RJS_EORR", rjs_op_eorr);
988         rvm_cpu_setophandler(cpu, RJS_EXOR, "RJS_EXOR", rjs_op_exor);
989         rvm_cpu_setophandler(cpu, RJS_ENOT, "RJS_ENOT", rjs_op_enot);
990         rvm_cpu_setophandler(cpu, RJS_ELAND, "RJS_ELAND", rjs_op_eland);
991         rvm_cpu_setophandler(cpu, RJS_ELOR, "RJS_ELOR", rjs_op_elor);
992         rvm_cpu_setophandler(cpu, RJS_ELNOT, "RJS_ELNOT", rjs_op_elnot);
993         rvm_cpu_setophandler(cpu, RJS_EEQ, "RJS_EEQ", rjs_op_eeq);
994         rvm_cpu_setophandler(cpu, RJS_ENOTEQ, "RJS_ENOTEQ", rjs_op_enoteq);
995         rvm_cpu_setophandler(cpu, RJS_EGREAT, "RJS_EGREAT", rjs_op_egreat);
996         rvm_cpu_setophandler(cpu, RJS_EGREATEQ, "RJS_EGREATEQ", rjs_op_egreateq);
997         rvm_cpu_setophandler(cpu, RJS_ELESS, "RJS_ELESS", rjs_op_eless);
998         rvm_cpu_setophandler(cpu, RJS_ELESSEQ, "RJS_ELESSEQ", rjs_op_elesseq);
999         rvm_cpu_setophandler(cpu, RJS_ECMP, "RJS_ECMP", rjs_op_ecmp);
1000         rvm_cpu_setophandler(cpu, RJS_ECMN, "RJS_ECMN", rjs_op_ecmn);
1001         rvm_cpu_setophandler(cpu, RJS_PROPLKUP, "RJS_PROPLKUP", rjs_op_proplookup);
1002         rvm_cpu_setophandler(cpu, RJS_PROPLKUPADD, "RJS_PROPLKUPADD", rjs_op_proplookupadd);
1003         rvm_cpu_setophandler(cpu, RJS_PROPLDR, "RJS_PROPLDR", rjs_op_propldr);
1004         rvm_cpu_setophandler(cpu, RJS_PROPSTR, "RJS_PROPSTR", rjs_op_propstr);
1005         rvm_cpu_setophandler(cpu, RJS_PROPADDR, "RJS_PROPADDR", rjs_op_propaddr);
1006         rvm_cpu_setophandler(cpu, RJS_PROPKEYLDR, "RJS_PROPKEYLDR", rjs_op_propkeyldr);
1007         rvm_cpu_setophandler(cpu, RJS_PROPDEL, "RJS_PROPDEL", rjs_op_propdel);
1008         rvm_cpu_setophandler(cpu, RJS_PROPNEXT, "RJS_PROPNEXT", rjs_op_propnext);
1009         rvm_cpu_setophandler(cpu, RJS_PROPPREV, "RJS_PROPPREV", rjs_op_propprev);
1010         rvm_cpu_setophandler(cpu, RJS_STRALLOC, "RJS_STRALLOC", rjs_op_stralloc);
1011         rvm_cpu_setophandler(cpu, RJS_MAPALLOC, "RJS_MAPALLOC", rjs_op_mapalloc);
1012         rvm_cpu_setophandler(cpu, RJS_PROPGET, "RJS_PROPGET", rjs_op_propget);
1013         rvm_cpu_setophandler(cpu, RJS_PROPSET, "RJS_PROPSET", rjs_op_propset);
1014
1015         cpu->userdata2 = rjs_opmap_create();
1016         rjs_op_binary_init(RJS_USERDATA2MAP(cpu->userdata2));
1017         rjs_op_cast_init(RJS_USERDATA2MAP(cpu->userdata2));
1018         rjs_op_not_init(RJS_USERDATA2MAP(cpu->userdata2));
1019         rjs_op_logicnot_init(RJS_USERDATA2MAP(cpu->userdata2));
1020
1021         rjs_set_ophandler(jse, RVM_DTYPE_STRING, "ltrim", rjs_string_ltrim);
1022         rjs_set_prophandler(jse, RVM_DTYPE_STRING, "length", rjs_string_length);
1023         return jse;
1024 error:
1025         rjs_engine_destroy(jse);
1026         return NULL;
1027 }
1028
1029
1030 void rjs_engine_destroy(rjs_engine_t *jse)
1031 {
1032         unsigned long i;
1033
1034         if (jse) {
1035                 if (jse->cgs) {
1036                         for (i = 0; i < r_array_length(jse->cgs); i++) {
1037                                 rvm_codegen_destroy(r_array_index(jse->cgs, i, rvm_codegen_t*));
1038                         }
1039                 }
1040                 r_array_destroy(jse->cgs);
1041                 r_array_destroy(jse->errors);
1042                 rjs_parser_destroy(jse->pa);
1043                 rjs_opmap_destroy(RJS_USERDATA2MAP(jse->cpu->userdata2));
1044                 rvm_cpu_destroy(jse->cpu);
1045                 rjs_compiler_destroy(jse->co);
1046                 r_free(jse);
1047         }
1048 }
1049
1050
1051 static void rjs_engine_addtypename(rjs_engine_t *jse, rmap_t *types, unsigned long type, const char *typename)
1052 {
1053         rvmreg_t rs;
1054         rstring_t *s;
1055
1056         s = r_string_create_from_ansistr(typename);
1057         r_gc_add(jse->cpu->gc, (robject_t*)s);
1058         rvm_reg_setstring(&rs, s);
1059         r_map_add_l(types, type, &rs);
1060 }
1061
1062
1063 static void rjs_engine_inittypes(rjs_engine_t *jse)
1064 {
1065         rmap_t *gmap = (rmap_t *)RVM_CPUREG_GETP(jse->cpu, GP);
1066         rmap_t *types;
1067         rvmreg_t rt;
1068
1069         types = r_map_create(sizeof(rvmreg_t), 3);
1070         r_gc_add(jse->cpu->gc, (robject_t*)types);
1071         rvm_reg_setjsobject(&rt, (robject_t *)types);
1072         r_map_add_l(gmap, RJS_GPKEY_TYPES, &rt);
1073         rjs_engine_addtypename(jse, types, RVM_DTYPE_UNDEF, "undefined");
1074         rjs_engine_addtypename(jse, types, RVM_DTYPE_BOOLEAN, "boolean");
1075         rjs_engine_addtypename(jse, types, RVM_DTYPE_DOUBLE, "number");
1076         rjs_engine_addtypename(jse, types, RVM_DTYPE_UNSIGNED, "number");
1077         rjs_engine_addtypename(jse, types, RVM_DTYPE_SIGNED, "number");
1078         rjs_engine_addtypename(jse, types, RVM_DTYPE_STRING, "string");
1079         rjs_engine_addtypename(jse, types, RVM_DTYPE_FUNCTION, "object");
1080         rjs_engine_addtypename(jse, types, RVM_DTYPE_NAN, "object");
1081         rjs_engine_addtypename(jse, types, RVM_DTYPE_MAP, "object");
1082         rjs_engine_addtypename(jse, types, RVM_DTYPE_POINTER, "object");
1083 }
1084
1085
1086 static void rjs_engine_initgp(rjs_engine_t *jse)
1087 {
1088         rvmreg_t gp;
1089         rmap_t *gmap;
1090
1091         rvm_reg_init(&gp);
1092         gmap = r_map_create(sizeof(rvmreg_t), 7);
1093         r_gc_add(jse->cpu->gc, (robject_t*)gmap);
1094         rvm_reg_setjsobject(RVM_CPUREG_PTR(jse->cpu, GP), (robject_t *)gmap);
1095         rjs_engine_inittypes(jse);
1096 }
1097
1098
1099 int rjs_engine_open(rjs_engine_t *jse)
1100 {
1101         return 0;
1102 }
1103
1104
1105 int rjs_engine_addswitable(rjs_engine_t *jse, const char *tabname, rvm_switable_t *switalbe)
1106 {
1107         return rvm_cpu_addswitable(jse->cpu, tabname, switalbe);
1108 }
1109
1110
1111 static int rjs_engine_parse(rjs_engine_t *jse, const char *script, unsigned long size, rarray_t *records, rjs_error_t *error)
1112 {
1113         long res = 0;
1114
1115         res = rjs_parser_exec(jse->pa, script, size, records, error);
1116         return res;
1117 }
1118
1119
1120 int rjs_engine_compile(rjs_engine_t *jse, const char *script, unsigned long size)
1121 {
1122         rvm_codegen_t *topcg = NULL;
1123         rarray_t *records = rpa_records_create();
1124         rjs_error_t error;
1125         jse->co->debug = jse->debugcompile;
1126
1127         r_memset(&error, 0, sizeof(error));
1128         if (rjs_engine_parse(jse, script, size, records, &error) < 0) {
1129
1130                 goto err;
1131         }
1132
1133         topcg =  r_array_empty(jse->cgs) ? NULL : r_array_last(jse->cgs, rvm_codegen_t*);
1134         if (!topcg || (topcg->userdata & RJS_COMPILER_CODEGENKEEP)) {
1135                 /*
1136                  * Keep this script codegen object. Allocate a new one for the
1137                  * next script.
1138                  */
1139                 topcg = rvm_codegen_create();
1140                 r_array_add(jse->cgs, &topcg);
1141         } else {
1142                 rvm_codegen_clear(topcg);
1143         }
1144         topcg->userdata = 0;
1145         if (rjs_compiler_compile(jse->co, script, size, records, topcg, &error) < 0) {
1146                 topcg->userdata = 0;
1147                 goto err;
1148         }
1149
1150         rpa_records_destroy(records);
1151         return 0;
1152
1153 err:
1154         r_array_add(jse->errors, &error);
1155         rpa_records_destroy(records);
1156         return -1;
1157 }
1158
1159
1160 int rjs_engine_dumpast(rjs_engine_t *jse, const char *script, unsigned long size)
1161 {
1162         rjs_error_t error;
1163         rarray_t *records = rpa_records_create();
1164
1165         if (rjs_engine_parse(jse, script, size, records, &error) < 0) {
1166
1167
1168                 return -1;
1169         }
1170
1171         if (records) {
1172                 long i;
1173                 for (i = 0; i < rpa_records_length(records); i++)
1174                         rpa_record_dump(records, i);
1175         }
1176
1177         rpa_records_destroy(records);
1178         return 0;
1179 }
1180
1181
1182 int rjs_engine_compile_s(rjs_engine_t *jse, const char *script)
1183 {
1184         return rjs_engine_compile(jse, script, r_strlen(script));
1185 }
1186
1187
1188 int rjs_engine_close(rjs_engine_t *jse)
1189 {
1190
1191         return 0;
1192 }
1193
1194
1195 int rjs_engine_run(rjs_engine_t *jse)
1196 {
1197         int res = 0;
1198         rvm_codegen_t *cg = r_array_empty(jse->cgs) ? NULL : r_array_last(jse->cgs, rvm_codegen_t*);
1199
1200         if (!cg) {
1201
1202                 return -1;
1203         }
1204         if (jse->debugexec) {
1205                 res = rvm_cpu_exec_debug(jse->cpu, rvm_codegen_getcode(cg, 0), 0);
1206         } else {
1207                 res = rvm_cpu_exec(jse->cpu, rvm_codegen_getcode(cg, 0), 0);
1208         }
1209
1210         if (jse->cpu->error == RVM_E_USERABORT) {
1211                 rword idx = RVM_CPUREG_GETIP(jse->cpu, PC) - rvm_codegen_getcode(cg, 0);
1212                 if (idx >= 0) {
1213                         r_printf("Aborted at source index: %ld\n", rvm_codegen_getsource(cg, (unsigned long)idx));
1214                 }
1215         }
1216         return res;
1217 }
1218
1219
1220 rvmreg_t * rjs_engine_exec(rjs_engine_t *jse, const char *script, unsigned long size)
1221 {
1222         if (rjs_engine_compile(jse, script, size) < 0)
1223                 return NULL;
1224         RVM_CPUREG_SETU(jse->cpu, FP, 0);
1225         RVM_CPUREG_SETU(jse->cpu, SP, 0);
1226         if (rjs_engine_run(jse) < 0)
1227                 return NULL;
1228         return RVM_CPUREG_PTR(jse->cpu, R0);
1229 }
1230
1231
1232 rvmreg_t *rjs_engine_exec_s(rjs_engine_t *jse, const char *script)
1233 {
1234         return rjs_engine_exec(jse, script, r_strlen(script));
1235 }
1236
1237
1238 static int rjs_compiler_argarray_setup(rjs_compiler_t *co)
1239 {
1240         rvm_varmap_t *v;
1241         rvmreg_t count = rvm_reg_create_signed(0);
1242         rmap_t *a;
1243
1244         v = rvm_scope_tiplookup_s(co->scope, "ARGS");
1245         if (!v) {
1246                 return -1;
1247         }
1248         a = r_map_create(sizeof(rvmreg_t), 7);
1249         r_gc_add(co->cpu->gc, (robject_t*)a);
1250         r_map_add_s(a, "count", &count);
1251         rvm_reg_setjsobject((rvmreg_t*)v->data.ptr, (robject_t*)a);
1252         return 0;
1253 }
1254
1255
1256 static int rjs_compiler_addarg(rjs_compiler_t *co, rvmreg_t *arg)
1257 {
1258         rvm_varmap_t *v;
1259         rmap_t *a;
1260         rvmreg_t *count;
1261         long index;
1262
1263         v = rvm_scope_tiplookup_s(co->scope, "ARGS");
1264         if (!v) {
1265                 return -1;
1266         }
1267         a = (rmap_t*)RVM_REG_GETP((rvmreg_t*)v->data.ptr);
1268         index = r_map_lookup_s(a, -1, "count");
1269         R_ASSERT(index >= 0);
1270         count = (rvmreg_t *)r_map_value(a, index);
1271         r_map_add_l(a, (long)RVM_REG_GETL(count), arg);
1272         rvm_reg_setsigned(count, RVM_REG_GETL(count) + 1);
1273
1274         return 0;
1275 }
1276
1277
1278 rvmreg_t *rjs_engine_vexec(rjs_engine_t *jse, const char *script, unsigned long size, unsigned long nargs, va_list args)
1279 {
1280         rvmreg_t arg;
1281         unsigned long i = 0;
1282
1283         if (rjs_engine_compile(jse, script, size) < 0)
1284                 return NULL;
1285         if (nargs > 0) {
1286                 rjs_compiler_argarray_setup(jse->co);
1287                 for (i = 0; i < nargs; i++) {
1288                         arg = va_arg(args, rvmreg_t);
1289                         rjs_compiler_addarg(jse->co, &arg);
1290                 }
1291         }
1292         RVM_CPUREG_SETU(jse->cpu, FP, 0);
1293         RVM_CPUREG_SETU(jse->cpu, SP, 0);
1294         if (rjs_engine_run(jse) < 0)
1295                 return NULL;
1296         return RVM_CPUREG_PTR(jse->cpu, R0);
1297 }
1298
1299
1300 rvmreg_t *rjs_engine_args_exec(rjs_engine_t *jse, const char *script, unsigned long size, unsigned long nargs, ...)
1301 {
1302         rvmreg_t *ret;
1303         va_list args;
1304         va_start(args, nargs);
1305         ret = rjs_engine_vexec(jse, script, size, nargs, args);
1306         va_end(args);
1307         return ret;
1308 }
1309
1310
1311 rvmreg_t *rjs_engine_args_exec_s(rjs_engine_t *jse, const char *script, unsigned long nargs, ...)
1312 {
1313         rvmreg_t *ret;
1314         va_list args;
1315         va_start(args, nargs);
1316         ret = rjs_engine_vexec(jse, script, r_strlen(script), nargs, args);
1317         va_end(args);
1318         return ret;
1319 }
1320
1321
1322 static void rjs_engine_print(rvmcpu_t *cpu, rvm_asmins_t *ins)
1323 {
1324         rvmreg_t *r = (rvmreg_t *)RVM_STACK_ADDR(cpu->stack, RVM_CPUREG_GETU(cpu, FP) + 1);
1325
1326         if (rvm_reg_gettype(r) == RVM_DTYPE_UNSIGNED)
1327                 r_printf("%lu\n", RVM_REG_GETU(r));
1328         else if (rvm_reg_gettype(r) == RVM_DTYPE_NAN)
1329                 r_printf("NaN\n");
1330         else if (rvm_reg_gettype(r) == RVM_DTYPE_UNDEF)
1331                 r_printf("undefined\n");
1332         else if (rvm_reg_gettype(r) == RVM_DTYPE_BOOLEAN)
1333                 r_printf("%s\n", RVM_REG_GETU(r) ? "true" : "false");
1334         else if (rvm_reg_gettype(r) == RVM_DTYPE_POINTER)
1335                 r_printf("%p\n", RVM_REG_GETP(r));
1336         else if (rvm_reg_gettype(r) == RVM_DTYPE_SIGNED)
1337                 r_printf("%ld\n", RVM_REG_GETL(r));
1338         else if (rvm_reg_gettype(r) == RVM_DTYPE_DOUBLE)
1339                 r_printf("%f\n", RVM_REG_GETD(r));
1340         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRING)
1341                 r_printf("%s\n", ((rstring_t*) RVM_REG_GETP(r))->s.str);
1342         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRPTR)
1343                 r_printf("(STRPTR) %s\n", (RVM_REG_GETSTR(r)));
1344         else if (rvm_reg_gettype(r) == RVM_DTYPE_MAP)
1345                 r_printf("(object) %p\n",RVM_REG_GETP(r));
1346         else if (rvm_reg_gettype(r) == RVM_DTYPE_HARRAY)
1347                 r_printf("(hashed array) %p\n",RVM_REG_GETP(r));
1348         else if (rvm_reg_gettype(r) == RVM_DTYPE_SWIID)
1349                 r_printf("(function) %p\n",RVM_REG_GETP(r));
1350         else
1351                 r_printf("%p\n", RVM_REG_GETP(r));
1352 }
1353
1354
1355 static void rjs_engine_dbgprint(rvmcpu_t *cpu, rvm_asmins_t *ins)
1356 {
1357         rvmreg_t *r = (rvmreg_t *)RVM_STACK_ADDR(cpu->stack, RVM_CPUREG_GETU(cpu, FP) + 1);
1358
1359         if (rvm_reg_gettype(r) == RVM_DTYPE_UNSIGNED)
1360                 r_printf("(UNSIGNED) %lu\n", RVM_REG_GETU(r));
1361         else if (rvm_reg_gettype(r) == RVM_DTYPE_NAN)
1362                 r_printf("(NAN) NaN\n");
1363         else if (rvm_reg_gettype(r) == RVM_DTYPE_UNDEF)
1364                 r_printf("(UNDEF) undefined\n");
1365         else if (rvm_reg_gettype(r) == RVM_DTYPE_BOOLEAN)
1366                 r_printf("(BOOLEAN) %s\n", RVM_REG_GETU(r) ? "true" : "false");
1367         else if (rvm_reg_gettype(r) == RVM_DTYPE_POINTER)
1368                 r_printf("(POINTER) %p\n", RVM_REG_GETP(r));
1369         else if (rvm_reg_gettype(r) == RVM_DTYPE_SIGNED)
1370                 r_printf("(LONG) %ld\n", RVM_REG_GETL(r));
1371         else if (rvm_reg_gettype(r) == RVM_DTYPE_DOUBLE)
1372                 r_printf("(DOUBLE) %f\n", RVM_REG_GETD(r));
1373         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRING)
1374                 r_printf("(STRING) %s\n", ((rstring_t*) RVM_REG_GETP(r))->s.str);
1375         else if (rvm_reg_gettype(r) == RVM_DTYPE_STRPTR)
1376                 r_printf("(STRPTR) %s\n", (RVM_REG_GETSTR(r)));
1377         else if (rvm_reg_gettype(r) == RVM_DTYPE_MAP)
1378                 r_printf("(object) %p\n",RVM_REG_GETP(r));
1379         else if (rvm_reg_gettype(r) == RVM_DTYPE_HARRAY)
1380                 r_printf("(hashed array) %p\n",RVM_REG_GETP(r));
1381         else if (rvm_reg_gettype(r) == RVM_DTYPE_SWIID)
1382                 r_printf("(swi function) %p\n",RVM_REG_GETP(r));
1383         else if (rvm_reg_gettype(r) == RVM_DTYPE_FUNCTION)
1384                 r_printf("(function) %p\n",RVM_REG_GETP(r));
1385         else
1386                 r_printf("%p\n", RVM_REG_GETP(r));
1387 }
1388
1389
1390 static void rjs_engine_object(rvmcpu_t *cpu, rvm_asmins_t *ins)
1391 {
1392
1393 }
1394
1395
1396 void rjs_engine_abort(rjs_engine_t *jse, rjs_error_t *error)
1397 {
1398         if (error) {
1399                 r_array_add(jse->errors, error);
1400         }
1401         rvm_cpu_abort(jse->cpu);
1402 }
1403
1404
1405 rjs_engine_t *rjs_engine_get(rvmcpu_t *cpu)
1406 {
1407         return RJS_CPU2JSE(cpu);
1408 }
1409
1410
1411 static void rjs_set_handler(rjs_engine_t *jse, unsigned long type, const char *name, rconstpointer handler, unsigned long handlertype)
1412 {
1413         rmap_t *map;
1414         rvmreg_t r;
1415
1416         if (type >= RVM_DTYPE_SIZE)
1417                 return;
1418         if (!jse->props[type])
1419                 jse->props[type] = r_map_create(sizeof(rvmreg_t), 3);
1420         map = jse->props[type];
1421         r_memset(&r, 0, sizeof(r));
1422         RVM_REG_SETP(&r, handler);
1423         RVM_REG_SETTYPE(&r, handlertype);
1424         r_map_add_s(map, name, &r);
1425 }
1426
1427
1428 void rjs_set_prophandler(rjs_engine_t *jse, unsigned long type, const char *name, rconstpointer handler)
1429 {
1430         rjs_set_handler(jse, type, name, handler, RVM_DTYPE_PROPHANDLER);
1431 }
1432
1433
1434 void rjs_set_ophandler(rjs_engine_t *jse, unsigned long type, const char *name, rconstpointer handler)
1435 {
1436         rjs_set_handler(jse, type, name, handler, RVM_DTYPE_OPHANDLER);
1437 }