/* todo regex */ static int strpto_indexOf(PSTATE *ps, Value *args, Value *_this, Value *ret, int asc) { if (asc) die("Execute String.prototype.indexOf as constructor\n"); if (_this->vt != VT_OBJECT || _this->d.obj->ot != OT_STRING) { die("apply String.prototype.indexOf to a non-string object\n"); } unichar *v = _this->d.obj->d.str; Value *seq = value_object_lookup_array(args, 0, NULL); Value *start = value_object_lookup_array(args, 1, NULL); if (!seq) { value_make_number(*ret, -1); return 0; } value_tostring(seq); unichar *vseq = seq->d.str; int istart = 0; if (start && is_number(start)) { istart = (int) start->d.num; if (istart < 0) istart = 0; } int r = unistrpos(v, istart, vseq); value_make_number(*ret, r); return 0; }
int main(int argc, const char **argv) { ArgState *state = arg_command_line(args,argv); if (! interactive) { if (array_len(incdirs) > 0) { printf("the include paths\n"); FOR_ARR (str_t,P,incdirs) printf("'%s'\n",*P); } if (array_len(string_args) > 0) { printf("the string args\n"); FOR_ARR (str_t,P,string_args) printf("'%s'\n",*P); } printf("flag a is %d\n",a); } else { char *line; printf("> "); while ((line = file_getline(stdin)) != NULL) { char **parts = str_split(line," "); // args_process assumes args start at second element, hence -1 here PValue v = arg_process(state,(const char**)parts-1); if (v != NULL) { printf("%s\n",value_tostring(v)); unref(v); } dispose(parts,line); printf("> "); arg_reset_used(state); } } return 0; }
/* charCodeAt */ static int strpto_charCodeAt(PSTATE *ps, Value *args, Value *_this, Value *ret, int asc) { if (asc) die("Execute String.prototype.charCodeAt as constructor\n"); Value target = { 0 }; value_copy(target, *_this); value_tostring(&target); int slen = unistrlen(target.d.str); int pos = 0; Value *vpos; if ((vpos = value_object_lookup_array(args, 0, NULL))) { value_toint32(vpos); pos = (int)vpos->d.num; } if (pos < 0 || pos >= slen) { value_make_number(*ret, ieee_makenan()); } else { value_make_number(*ret, target.d.str[pos]); } value_erase(target); return 0; }
int eval(PSTATE *ps, OpCodes *opcodes, ScopeChain *scope, Value *currentScope, /* scope chain */ Value *_this, Value *vret) { int context_id = ps->_context_id++; OpCode *ip = &opcodes->codes[0]; OpCode *end = &opcodes->codes[opcodes->code_len]; TryList *trylist = NULL; if (currentScope->vt != VT_OBJECT) { bug("Eval: current scope is not a object\n"); } while(ip < end) { #ifdef DEBUG int i; printf("STACK%d: ", sp); for (i = 0; i < sp; ++i) { printf("%s ", vprint(&stack[i])); } printf("\tthis: %s ", vprint(_this)); TryList *tlt = trylist; for (i = 0; tlt; tlt = tlt->next) i++; printf("TL: %d, excpt: %s\n", i, vprint(&ps->last_exception)); code_decode(ip, ip - opcodes->codes); #endif switch(ip->op) { case OP_NOP: case OP_LASTOP: break; case OP_PUSHNUM: value_make_number(stack[sp], (*((double *)ip->data))); sp++; break; case OP_PUSHSTR: value_make_string(stack[sp], unistrdup(ip->data)); sp++; break; case OP_PUSHVAR: { FastVar *n = ip->data; Value *v = NULL; if (n->context_id == context_id) { v = n->var.lval; } else { unichar *varname = n->var.varname; v = value_object_lookup(currentScope, (ObjKey *)varname, NULL); if (!v) v = scope_chain_object_lookup(scope, (ObjKey *)varname); if (!v) { /* add to global scope */ Value *global_scope = scope->chains_cnt > 0 ? scope->chains[0]:currentScope; Value key; value_make_string(key, varname); /* varname is not dupped, do not erase*/ Value val; value_make_undef(val); v = value_object_key_assign(global_scope, &key, &val, OM_DONTEMU); /* key assign dup key and insert into object, so release ourself */ } n->context_id = context_id; n->var.lval = v; } stack[sp].vt = VT_VARIABLE; stack[sp].d.lval = v; sp++; break; } case OP_PUSHUND: value_make_undef(stack[sp]); sp++; break; case OP_PUSHBOO: value_make_bool(stack[sp], (int)ip->data); sp++; break; case OP_PUSHFUN: { FuncObj *fo = funcobj_new((Func *)ip->data); fo->scope = scope_chain_dup_next(scope, currentScope); Object *obj = object_new(); obj->ot = OT_FUNCTION; obj->d.fobj = fo; obj->__proto__ = Function_prototype; Value *fun_prototype = value_object_utils_new_object(); fun_prototype->d.obj->__proto__ = Object_prototype; value_make_object(stack[sp], obj); value_object_utils_insert(&stack[sp], PROTOTYPE.unistr, fun_prototype, 0, 1, 0); /* todo: make own prototype and prototype.constructor */ sp++; break; } case OP_PUSHREG: { Object *obj = object_new(); obj->ot = OT_REGEXP; obj->d.robj = (regex_t *)ip->data; obj->__proto__ = RegExp_prototype; value_make_object(stack[sp], obj); sp++; break; } case OP_PUSHARG: value_copy(stack[sp], *currentScope); sp++; break; case OP_PUSHTHS: value_copy(stack[sp], *_this); sp++; break; case OP_PUSHTOP: value_copy(stack[sp], TOP); sp++; break; case OP_UNREF: topeval1(); break; case OP_PUSHTOP2: value_copy(stack[sp], TOQ); value_copy(stack[sp+1], TOP); sp += 2; break; case OP_CHTHIS: { int t = sp - 2; if (ip->data) { value_erase(obj_this[t]); value_copy(obj_this[t], TOQ); if (obj_this[t].vt == VT_VARIABLE) { Value *v = obj_this[t].d.lval; value_copy(obj_this[t], *v); } value_toobject(&obj_this[t]); } break; } case OP_LOCAL: { ObjKey *strkey = objkey_new((const unichar *)ip->data, OM_DONTEMU); value_object_insert(currentScope, strkey, value_new()); /* make all FastVar to be relocated */ context_id = ps->_context_id++; break; } case OP_POP: pop_n(ip->data); break; case OP_NEG: topeval1(); value_tonumber(&TOP); TOP.d.num = -(TOP.d.num); break; case OP_POS: topeval1(); value_tonumber(&TOP); break; case OP_NOT: { int val = 0; topeval1(); val = value_istrue(&TOP); value_erase(TOP); value_make_bool(TOP, !val); break; } case OP_BNOT: { topeval1(); value_toint32(&TOP); TOP.d.num = (double)(~((int)TOP.d.num)); break; } case OP_ADD: { topeval2(); value_toprimitive(&TOP); value_toprimitive(&TOQ); if (TOP.vt == VT_STRING || TOQ.vt == VT_STRING) { value_tostring(&TOP); value_tostring(&TOQ); unichar *v = unistrcat(TOQ.d.str, TOP.d.str); value_erase(TOQ); value_make_string(TOQ, v); } else { value_tonumber(&TOP); value_tonumber(&TOQ); double n = TOP.d.num + TOQ.d.num; value_erase(TOQ); value_make_number(TOQ, n); } pop(); break; } case OP_SUB: /* god, the notes in ecma is so long, pray to run correctly */ common_math_opr(-); break; case OP_MUL: common_math_opr(*); break; case OP_DIV: common_math_opr(/); break; case OP_MOD: { topeval2(); if (!is_number(&TOP)) value_tonumber(&TOP); if (!is_number(&TOQ)) value_tonumber(&TOQ); TOQ.d.num = fmod(TOQ.d.num, TOP.d.num); pop(); break; } case OP_LESS: topeval2(); logic_less(TOQ, TOP, TOQ); pop(); break; case OP_GREATER: topeval2(); logic_less(TOP, TOQ, TOQ); pop(); break; case OP_LESSEQU: topeval2(); logic_less(TOP, TOQ, TOQ); TOQ.d.val = !TOQ.d.val; pop(); break; case OP_GREATEREQU: topeval2(); logic_less(TOQ, TOP, TOQ); TOQ.d.val = !TOQ.d.val; pop(); break; case OP_EQUAL: case OP_NOTEQUAL: { /* awful, equal opration */ int r = 0; topeval2(); if (TOP.vt != TOQ.vt) { value_toprimitive(&TOP); value_toprimitive(&TOQ); } if (TOP.vt != TOQ.vt) { if ((is_undef(&TOP) || is_null(&TOP)) && (is_undef(&TOQ) || is_null(&TOQ))) { r = 1; } else { value_tonumber(&TOP); value_tonumber(&TOQ); r = (TOP.d.num == TOQ.d.num); } } else { switch (TOP.vt) { case VT_NUMBER: r = (TOP.d.num == TOQ.d.num); break; case VT_BOOL: r = (TOP.d.val == TOQ.d.val); break; case VT_STRING: r = (unistrcmp(TOQ.d.str, TOP.d.str) == 0); break; case VT_OBJECT: /* todo: refer to objects joined to each other */ r = (TOP.d.obj == TOQ.d.obj); break; case VT_UNDEF: case VT_NULL: r = 1; break; default: bug("Unexpected value type\n"); } } r = (ip->op == OP_EQUAL ? r : !r); value_erase(TOQ); value_make_bool(TOQ, r); pop(); break; } case OP_STRICTEQU: case OP_STRICTNEQ: { int r = 0; topeval2(); if (TOP.vt == TOQ.vt) { switch (TOP.vt) { case VT_NUMBER: r = (TOP.d.num == TOQ.d.num); break; case VT_BOOL: r = (TOP.d.val == TOQ.d.val); break; case VT_STRING: r = (unistrcmp(TOQ.d.str, TOP.d.str) == 0); break; case VT_OBJECT: /* todo: refer to objects joined to each other */ r = (TOP.d.obj == TOQ.d.obj); break; case VT_UNDEF: case VT_NULL: r = 1; break; default: bug("Unexpected value type\n"); } } r = (ip->op == OP_STRICTEQU ? r : !r); value_erase(TOQ); value_make_bool(TOQ, r); pop(); break; } case OP_BAND: common_bitwise_opr(&); break; case OP_BOR: common_bitwise_opr(|); break; case OP_BXOR: common_bitwise_opr(^); break; case OP_SHF: { topeval2(); value_toint32(&TOQ); value_toint32(&TOP); int t1 = (int)TOQ.d.num; int t2 = ((unsigned int)TOP.d.num) & 0x1f; if (ip->data) { /* thift right */ if ((int)ip->data == 2) { /* unsigned shift */ unsigned int t3 = (unsigned int)t1; t3 >>= t2; value_make_number(TOQ, t3); } else { t1 >>= t2; value_make_number(TOQ, t1); } } else { t1 <<= t2; value_make_number(TOQ, t1); } pop(); break; }