예제 #1
0
/* match */
static int strpto_match(PSTATE *ps, Value *args, Value *_this, Value *ret, int asc)
{
	if (asc) die("Execute String.prototype.match as constructor\n");
	if (_this->vt != VT_OBJECT || _this->d.obj->ot != OT_STRING) {
		die("apply String.prototype.match to a non-string object\n");
	}

	unichar *v = _this->d.obj->d.str;
	Value *seq = value_object_lookup_array(args, 0, NULL);

	if (!seq || seq->vt != VT_OBJECT || seq->d.obj->ot != OT_REGEXP) {
		value_make_null(*ret);
		return 0;
	}

	regex_t *reg = seq->d.obj->d.robj;
	
	regmatch_t pos[MAX_SUBREGEX];
	memset(&pos, 0, MAX_SUBREGEX * sizeof(regmatch_t));
	int r;
	if ((r = regexec(reg, tochars(v), MAX_SUBREGEX, pos, 0)) != 0) {
		if (r == REG_NOMATCH) {
			value_make_null(*ret);
			return 0;
		} else die("Out of memory\n");
	}

	Object *obj = object_new();
	obj->__proto__ = Array_prototype;
	value_make_object(*ret, obj);
	object_set_length(ret->d.obj, 0);
	
	int i;
	for (i = 0; i < MAX_SUBREGEX; ++i) {
		if (pos[i].rm_so <= 0 && pos[i].rm_eo <= 0) break;

		Value *val = value_new();
		value_make_string(*val, 
			unisubstrdup(v, pos[i].rm_so, pos[i].rm_eo - pos[i].rm_so));
		value_object_utils_insert_array(ret, i, val, 1, 1, 1);
	}

	Value *vind = value_new();
	value_make_number(*vind, pos[0].rm_so);
	value_object_utils_insert(ret, INDEX.unistr, vind, 1, 1, 1);
	Value *vinput = value_new();
	value_make_string(*vinput, unistrdup(v));
	value_object_utils_insert(ret, INPUT.unistr, vinput, 1, 1, 1);
	
	return 0;
}
예제 #2
0
void proto_string_init(Value *global)
{
	if (!String_prototype) bug("proto init failed?");
	int i;
	for (i = 0; i < sizeof(strpro_funcs) / sizeof(struct st_strpro_tab); ++i) {
		Value *n = func_utils_make_func_value(strpro_funcs[i].func);
		n->d.obj->__proto__ = Function_prototype;
		value_object_utils_insert(String_prototype, tounichars(strpro_funcs[i].name), n, 0, 0, 0);
	}
}
예제 #3
0
void proto_number_init(Value *global)
    {
    if (!Number_prototype) bug("proto init failed?");
    int i;
    for (i = 0; i < sizeof(numpro_funcs) / sizeof(struct st_numpro_tab); ++i)
        {
        Value *n = func_utils_make_func_value(numpro_funcs[i].func);
        n->d.obj->__proto__ = Function_prototype;
        value_object_utils_insert(Number_prototype, tounichars(numpro_funcs[i].name), n, 0, 0, 0);
        }


    Value *NaN = value_new();
    value_make_number(*NaN, ieee_makenan());

    Value *Inf = value_new();
    value_make_number(*Inf, ieee_makeinf(1));

    value_object_utils_insert(global, tounichars("NaN"), NaN, 0, 0, 0);
    value_object_utils_insert(global, tounichars("Infinity"), Inf, 0, 0, 0);
    }
예제 #4
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;
			}