2 * Regular Pattern Analyzer (RPA)
3 * Copyright (c) 2009-2010 Martin Stoilov
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.
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.
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/>.
18 * Martin Stoilov <martin@rpasearch.com>
22 #include "rlib/rmem.h"
23 #include "rlib/rmap.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"
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);
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},
51 static void rjs_op_cast(rvmcpu_t *cpu, rvm_asmins_t *ins)
53 rvmreg_type_t type = (rvmreg_type_t)RVM_CPUREG_GETU(cpu, ins->op3);
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);
62 static void rjs_op_eadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
64 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
65 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
67 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_ADD, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
71 static void rjs_op_esub(rvmcpu_t *cpu, rvm_asmins_t *ins)
73 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
74 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
76 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_SUB, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
80 static void rjs_op_eneg(rvmcpu_t *cpu, rvm_asmins_t *ins)
82 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
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);
91 static void rjs_op_emul(rvmcpu_t *cpu, rvm_asmins_t *ins)
93 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
94 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
96 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_MUL, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
100 static void rjs_op_ediv(rvmcpu_t *cpu, rvm_asmins_t *ins)
102 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
103 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
105 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_DIV, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
109 static void rjs_op_emod(rvmcpu_t *cpu, rvm_asmins_t *ins)
111 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
112 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
114 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_MOD, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
118 static void rjs_op_elsl(rvmcpu_t *cpu, rvm_asmins_t *ins)
120 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
121 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
123 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LSL, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
127 static void rjs_op_elsr(rvmcpu_t *cpu, rvm_asmins_t *ins)
129 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
130 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
132 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LSR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
136 static void rjs_op_elsru(rvmcpu_t *cpu, rvm_asmins_t *ins)
138 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
139 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
141 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LSRU, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
145 static void rjs_op_eand(rvmcpu_t *cpu, rvm_asmins_t *ins)
147 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
148 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
150 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_AND, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
154 static void rjs_op_eorr(rvmcpu_t *cpu, rvm_asmins_t *ins)
156 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
157 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
159 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_OR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
163 static void rjs_op_exor(rvmcpu_t *cpu, rvm_asmins_t *ins)
165 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
166 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
168 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_XOR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
172 static void rjs_op_enot(rvmcpu_t *cpu, rvm_asmins_t *ins)
174 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
176 rjs_opmap_invoke_unary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_NOT, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2);
180 static void rjs_op_eland(rvmcpu_t *cpu, rvm_asmins_t *ins)
182 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
183 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
185 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LOGICAND, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
189 static void rjs_op_elor(rvmcpu_t *cpu, rvm_asmins_t *ins)
191 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
192 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
194 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LOGICOR, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
198 static void rjs_op_elnot(rvmcpu_t *cpu, rvm_asmins_t *ins)
200 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
202 rjs_opmap_invoke_unary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LOGICNOT, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2);
206 static void rjs_op_eeq(rvmcpu_t *cpu, rvm_asmins_t *ins)
208 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
209 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
211 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_EQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
215 static void rjs_op_enoteq(rvmcpu_t *cpu, rvm_asmins_t *ins)
217 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
218 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
220 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_NOTEQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
224 static void rjs_op_egreat(rvmcpu_t *cpu, rvm_asmins_t *ins)
226 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
227 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
229 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_GREATER, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
233 static void rjs_op_egreateq(rvmcpu_t *cpu, rvm_asmins_t *ins)
235 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
236 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
238 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_GREATEREQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
242 static void rjs_op_elesseq(rvmcpu_t *cpu, rvm_asmins_t *ins)
244 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
245 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
247 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LESSEQ, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
251 static void rjs_op_eless(rvmcpu_t *cpu, rvm_asmins_t *ins)
253 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
254 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
256 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_LESS, cpu, RVM_CPUREG_PTR(cpu, ins->op1), arg2, arg3);
260 static void rjs_op_ecmp(rvmcpu_t *cpu, rvm_asmins_t *ins)
262 rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
263 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
265 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CMP, cpu, NULL, arg1, arg2);
269 static void rjs_op_ecmn(rvmcpu_t *cpu, rvm_asmins_t *ins)
271 rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
272 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
274 rjs_opmap_invoke_binary_handler(RJS_USERDATA2MAP(cpu->userdata2), RJS_OPID_CMN, cpu, NULL, arg1, arg2);
278 static void rjs_op_stralloc(rvmcpu_t *cpu, rvm_asmins_t *ins)
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));
283 RVM_ABORT(cpu, RVM_E_ILLEGAL);
285 r_gc_add(cpu->gc, (robject_t*)s);
286 rvm_reg_setstring(arg1, s);
290 static void rjs_op_mapalloc(rvmcpu_t *cpu, rvm_asmins_t *ins)
292 rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
293 rmap_t *a = r_map_create(sizeof(rvmreg_t), 7);
295 RVM_ABORT(cpu, RVM_E_ILLEGAL);
297 r_gc_add(cpu->gc, (robject_t*)a);
298 rvm_reg_setjsobject(arg1, (robject_t*)a);
302 static long rjs_op_mapproplookupadd(rmap_t *map, rvmcpu_t *cpu, rvm_asmins_t *ins)
305 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
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));
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));
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);
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));
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);
331 static void rjs_op_proplookupadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
338 if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
339 index = rjs_op_mapproplookupadd(map, cpu, ins);
344 RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
345 RVM_REG_SETL(arg1, index);
349 static long rjs_op_mapproplookup(rmap_t *map, rvmcpu_t *cpu, rvm_asmins_t *ins)
352 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
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));
369 static long rjs_op_stringproplookup(rstring_t *str, rvmcpu_t *cpu, rvm_asmins_t *ins)
372 rvmreg_t *arg3 = RVM_CPUREG_PTR(cpu, ins->op3);
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);
380 if (index >= str->s.size)
386 static void rjs_op_propget(rvmcpu_t *cpu, rvm_asmins_t *ins)
390 rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
391 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
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);
397 *arg1 = *((rvmreg_t*)r_map_value(map, index));
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);
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);
411 map = rjs_engine_get(cpu)->props[rvm_reg_gettype(arg2)];
412 index = rjs_op_mapproplookup(map, cpu, ins);
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);
422 rvm_reg_setundef(arg1);
426 static void rjs_op_propset(rvmcpu_t *cpu, rvm_asmins_t *ins)
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;
434 if (rvm_reg_gettype(arg2) == RVM_DTYPE_MAP) {
435 index = rjs_op_mapproplookupadd(map, cpu, ins);
436 value = r_map_value(map, index);
439 value = &rjs_engine_get(cpu)->scratch;
442 RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
443 RVM_REG_SETP(arg1, value);
447 static void rjs_op_proplookup(rvmcpu_t *cpu, rvm_asmins_t *ins)
450 rboolean globalprop = 0;
451 rvmreg_t *arg1 = RVM_CPUREG_PTR(cpu, ins->op1);
452 rvmreg_t *arg2 = RVM_CPUREG_PTR(cpu, ins->op2);
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);
462 index = rjs_op_mapproplookup(rjs_engine_get(cpu)->props[RVM_DTYPE_STRING], cpu, ins);
466 rvm_reg_setsigned(arg1, index);
468 RVM_REG_SETFLAG(arg1, RVM_INFOBIT_GLOBAL);
473 static void rjs_op_propstr(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
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) {
488 a = (rmap_t*)RVM_REG_GETP(arg2);
489 value = r_map_value(a, index);
491 RVM_ABORT(cpu, RVM_E_ILLEGAL);
492 r_map_setvalue(a, index, arg1);
496 static void rjs_op_propldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
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);
509 *arg1 = *((rvmreg_t*)value);
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);
517 *arg1 = *((rvmreg_t*)value);
521 if (index >= s->s.size) {
522 rvm_reg_setundef(arg1);
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);
530 rvm_reg_setundef(arg1);
535 static void rjs_op_propkeyldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
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);
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);
552 rvm_reg_setstring(arg1, key);
554 } else if (rvm_reg_gettype(arg2) == RVM_DTYPE_STRING) {
560 static void rjs_op_propdel(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
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);
580 static void rjs_op_propaddr(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
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);
596 RVM_ABORT(cpu, RVM_E_ILLEGAL);
598 RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
599 RVM_REG_SETP(arg1, value);
603 static void rjs_op_propnext(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
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);
616 index = r_map_first(map);
618 index = r_map_next(map, index);
621 RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
622 RVM_REG_SETL(arg1, index);
626 static void rjs_op_propprev(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
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);
639 index = r_map_last(map);
641 index = r_map_prev(map, index);
644 RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
645 RVM_REG_SETL(arg1, index);
649 static void rjs_op_mapdel(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
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);
668 static void rjs_op_maplookup(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
676 if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP) {
677 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
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));
688 RVM_ABORT(cpu, RVM_E_ILLEGAL);
692 RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
693 RVM_REG_SETL(arg1, index);
697 static void rjs_op_mapadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
705 if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP) {
706 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
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);
717 RVM_ABORT(cpu, RVM_E_ILLEGAL);
721 RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
722 RVM_REG_SETL(arg1, index);
726 static void rjs_op_maplookupadd(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
734 if (rvm_reg_gettype(arg2) != RVM_DTYPE_MAP) {
735 RVM_ABORT(cpu, RVM_E_NOTOBJECT);
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));
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));
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);
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));
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);
754 RVM_ABORT(cpu, RVM_E_ILLEGAL);
757 RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
758 RVM_REG_SETL(arg1, index);
762 static void rjs_op_mapaddr(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
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);
778 RVM_ABORT(cpu, RVM_E_ILLEGAL);
780 RVM_REG_SETTYPE(arg1, RVM_DTYPE_POINTER);
781 RVM_REG_SETP(arg1, value);
785 static void rjs_op_mapldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
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);
802 RVM_REG_SETTYPE(arg1, RVM_DTYPE_UNDEF);
804 *arg1 = *((rvmreg_t*)value);
809 static void rjs_op_mapkeyldr(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
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);
826 RVM_REG_SETTYPE(arg1, RVM_DTYPE_UNDEF);
828 rvm_reg_setstring(arg1, key);
833 static void rjs_op_mapnext(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
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);
847 index = r_map_first(a);
849 index = r_map_next(a, index);
851 RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
852 RVM_REG_SETL(arg1, index);
856 static void rjs_op_mapprev(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
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);
870 index = r_map_last(a);
872 index = r_map_prev(a, index);
874 RVM_REG_SETTYPE(arg1, RVM_DTYPE_SIGNED);
875 RVM_REG_SETL(arg1, index);
879 static void rjs_op_mapstr(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
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);
895 RVM_ABORT(cpu, RVM_E_ILLEGAL);
896 r_map_setvalue(a, index, arg1);
900 const char *rjs_version()
902 return RJS_VERSION_STRING;
906 static void rjs_string_ltrim(rvmcpu_t *cpu, rvm_asmins_t *ins)
908 const char *ptr, *list;
910 rvmreg_t *r = NULL, *l = NULL;
911 rstring_t *src, *dest;
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);
919 if (rvm_reg_gettype(r) != RVM_DTYPE_STRING)
920 RJS_SWI_ABORT(rjs_engine_get(cpu), NULL);
922 list = ((rstring_t *)RVM_REG_GETP(l))->s.str;
925 src = (rstring_t *)RVM_REG_GETP(r);
929 if (!r_strchr(list, *ptr))
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);
940 static void rjs_string_length(rvmcpu_t *cpu, rvm_asmins_t *ins)
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);
951 rvm_reg_setsigned(RVM_CPUREG_PTR(cpu, R0), size);
955 rjs_engine_t *rjs_engine_create()
959 rjs_engine_t *jse = (rjs_engine_t *) r_zmalloc(sizeof(*jse));
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)
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);
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);
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));
1021 rjs_set_ophandler(jse, RVM_DTYPE_STRING, "ltrim", rjs_string_ltrim);
1022 rjs_set_prophandler(jse, RVM_DTYPE_STRING, "length", rjs_string_length);
1025 rjs_engine_destroy(jse);
1030 void rjs_engine_destroy(rjs_engine_t *jse)
1036 for (i = 0; i < r_array_length(jse->cgs); i++) {
1037 rvm_codegen_destroy(r_array_index(jse->cgs, i, rvm_codegen_t*));
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);
1051 static void rjs_engine_addtypename(rjs_engine_t *jse, rmap_t *types, unsigned long type, const char *typename)
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);
1063 static void rjs_engine_inittypes(rjs_engine_t *jse)
1065 rmap_t *gmap = (rmap_t *)RVM_CPUREG_GETP(jse->cpu, GP);
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");
1086 static void rjs_engine_initgp(rjs_engine_t *jse)
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);
1099 int rjs_engine_open(rjs_engine_t *jse)
1105 int rjs_engine_addswitable(rjs_engine_t *jse, const char *tabname, rvm_switable_t *switalbe)
1107 return rvm_cpu_addswitable(jse->cpu, tabname, switalbe);
1111 static int rjs_engine_parse(rjs_engine_t *jse, const char *script, unsigned long size, rarray_t *records, rjs_error_t *error)
1115 res = rjs_parser_exec(jse->pa, script, size, records, error);
1120 int rjs_engine_compile(rjs_engine_t *jse, const char *script, unsigned long size)
1122 rvm_codegen_t *topcg = NULL;
1123 rarray_t *records = rpa_records_create();
1125 jse->co->debug = jse->debugcompile;
1127 r_memset(&error, 0, sizeof(error));
1128 if (rjs_engine_parse(jse, script, size, records, &error) < 0) {
1133 topcg = r_array_empty(jse->cgs) ? NULL : r_array_last(jse->cgs, rvm_codegen_t*);
1134 if (!topcg || (topcg->userdata & RJS_COMPILER_CODEGENKEEP)) {
1136 * Keep this script codegen object. Allocate a new one for the
1139 topcg = rvm_codegen_create();
1140 r_array_add(jse->cgs, &topcg);
1142 rvm_codegen_clear(topcg);
1144 topcg->userdata = 0;
1145 if (rjs_compiler_compile(jse->co, script, size, records, topcg, &error) < 0) {
1146 topcg->userdata = 0;
1150 rpa_records_destroy(records);
1154 r_array_add(jse->errors, &error);
1155 rpa_records_destroy(records);
1160 int rjs_engine_dumpast(rjs_engine_t *jse, const char *script, unsigned long size)
1163 rarray_t *records = rpa_records_create();
1165 if (rjs_engine_parse(jse, script, size, records, &error) < 0) {
1173 for (i = 0; i < rpa_records_length(records); i++)
1174 rpa_record_dump(records, i);
1177 rpa_records_destroy(records);
1182 int rjs_engine_compile_s(rjs_engine_t *jse, const char *script)
1184 return rjs_engine_compile(jse, script, r_strlen(script));
1188 int rjs_engine_close(rjs_engine_t *jse)
1195 int rjs_engine_run(rjs_engine_t *jse)
1198 rvm_codegen_t *cg = r_array_empty(jse->cgs) ? NULL : r_array_last(jse->cgs, rvm_codegen_t*);
1204 if (jse->debugexec) {
1205 res = rvm_cpu_exec_debug(jse->cpu, rvm_codegen_getcode(cg, 0), 0);
1207 res = rvm_cpu_exec(jse->cpu, rvm_codegen_getcode(cg, 0), 0);
1210 if (jse->cpu->error == RVM_E_USERABORT) {
1211 rword idx = RVM_CPUREG_GETIP(jse->cpu, PC) - rvm_codegen_getcode(cg, 0);
1213 r_printf("Aborted at source index: %ld\n", rvm_codegen_getsource(cg, (unsigned long)idx));
1220 rvmreg_t * rjs_engine_exec(rjs_engine_t *jse, const char *script, unsigned long size)
1222 if (rjs_engine_compile(jse, script, size) < 0)
1224 RVM_CPUREG_SETU(jse->cpu, FP, 0);
1225 RVM_CPUREG_SETU(jse->cpu, SP, 0);
1226 if (rjs_engine_run(jse) < 0)
1228 return RVM_CPUREG_PTR(jse->cpu, R0);
1232 rvmreg_t *rjs_engine_exec_s(rjs_engine_t *jse, const char *script)
1234 return rjs_engine_exec(jse, script, r_strlen(script));
1238 static int rjs_compiler_argarray_setup(rjs_compiler_t *co)
1241 rvmreg_t count = rvm_reg_create_signed(0);
1244 v = rvm_scope_tiplookup_s(co->scope, "ARGS");
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);
1256 static int rjs_compiler_addarg(rjs_compiler_t *co, rvmreg_t *arg)
1263 v = rvm_scope_tiplookup_s(co->scope, "ARGS");
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);
1278 rvmreg_t *rjs_engine_vexec(rjs_engine_t *jse, const char *script, unsigned long size, unsigned long nargs, va_list args)
1281 unsigned long i = 0;
1283 if (rjs_engine_compile(jse, script, size) < 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);
1292 RVM_CPUREG_SETU(jse->cpu, FP, 0);
1293 RVM_CPUREG_SETU(jse->cpu, SP, 0);
1294 if (rjs_engine_run(jse) < 0)
1296 return RVM_CPUREG_PTR(jse->cpu, R0);
1300 rvmreg_t *rjs_engine_args_exec(rjs_engine_t *jse, const char *script, unsigned long size, unsigned long nargs, ...)
1304 va_start(args, nargs);
1305 ret = rjs_engine_vexec(jse, script, size, nargs, args);
1311 rvmreg_t *rjs_engine_args_exec_s(rjs_engine_t *jse, const char *script, unsigned long nargs, ...)
1315 va_start(args, nargs);
1316 ret = rjs_engine_vexec(jse, script, r_strlen(script), nargs, args);
1322 static void rjs_engine_print(rvmcpu_t *cpu, rvm_asmins_t *ins)
1324 rvmreg_t *r = (rvmreg_t *)RVM_STACK_ADDR(cpu->stack, RVM_CPUREG_GETU(cpu, FP) + 1);
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)
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));
1351 r_printf("%p\n", RVM_REG_GETP(r));
1355 static void rjs_engine_dbgprint(rvmcpu_t *cpu, rvm_asmins_t *ins)
1357 rvmreg_t *r = (rvmreg_t *)RVM_STACK_ADDR(cpu->stack, RVM_CPUREG_GETU(cpu, FP) + 1);
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));
1386 r_printf("%p\n", RVM_REG_GETP(r));
1390 static void rjs_engine_object(rvmcpu_t *cpu, rvm_asmins_t *ins)
1396 void rjs_engine_abort(rjs_engine_t *jse, rjs_error_t *error)
1399 r_array_add(jse->errors, error);
1401 rvm_cpu_abort(jse->cpu);
1405 rjs_engine_t *rjs_engine_get(rvmcpu_t *cpu)
1407 return RJS_CPU2JSE(cpu);
1411 static void rjs_set_handler(rjs_engine_t *jse, unsigned long type, const char *name, rconstpointer handler, unsigned long handlertype)
1416 if (type >= RVM_DTYPE_SIZE)
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);
1428 void rjs_set_prophandler(rjs_engine_t *jse, unsigned long type, const char *name, rconstpointer handler)
1430 rjs_set_handler(jse, type, name, handler, RVM_DTYPE_PROPHANDLER);
1434 void rjs_set_ophandler(rjs_engine_t *jse, unsigned long type, const char *name, rconstpointer handler)
1436 rjs_set_handler(jse, type, name, handler, RVM_DTYPE_OPHANDLER);