Exemplo n.º 1
0
Ink_HashExpression::ProtoSearchRet Ink_HashExpression::searchPrototype(Ink_InterpreteEngine *engine, Ink_Object *obj, const char *id)
{
    if (engine->prototypeHasTraced(obj)) {
        InkWarn_Circular_Prototype_Reference(engine);
        return Ink_HashExpression::ProtoSearchRet(NULL, obj);
    }
    engine->addPrototypeTrace(obj);

    Ink_HashTable *hash = obj->getSlotMapping(engine, id);
    Ink_HashTable *proto;
    Ink_Object *proto_obj = NULL;
    Ink_HashExpression::ProtoSearchRet search_res;

    if (!hash) { /* cannot find slot in object itself */
        /* get prototype */
        proto = obj->getSlotMapping(engine, "prototype");

        /* prototype exists and it's not undefined */
        if (proto && proto->getValue()->type != INK_UNDEFINED) {
            /* search the slot in prototype, and get the result */
            hash = (search_res = searchPrototype(engine, proto->getValue(), id)).hash;
            proto_obj = search_res.base;
        }
    }

    /* return result with base pointed to the prototype(if has)
     * in which found the slot
     */
    return Ink_HashExpression::ProtoSearchRet(hash, proto_obj ? proto_obj : obj);
}
Exemplo n.º 2
0
Ink_Object *InkNative_Array_Index(Ink_InterpreteEngine *engine, Ink_ContextChain *context, Ink_ArgcType argc, Ink_Object **argv, Ink_Object *this_p)
{
	Ink_Object *base = context->searchSlot(engine, "base");
	Ink_Array *obj = as<Ink_Array>(base);
	Ink_Object *ret;
	Ink_HashTable *hash;
	Ink_ArrayValue::size_type index;

	ASSUME_BASE_TYPE(engine, INK_ARRAY);

	if (!checkArgument(false, argc, argv, 1, INK_NUMERIC)) {
		InkNote_Method_Fallthrough(engine, "[]", INK_ARRAY, INK_OBJECT);
		return InkNative_Object_Index(engine, context, argc, argv, this_p);
	}

	index = getRealIndex(as<Ink_Numeric>(argv[0])->value, obj->value.size());
	if (index < obj->value.size()) {
		if (!obj->value[index]) obj->value[index] = new Ink_HashTable(UNDEFINED);
		for (hash = obj->value[index]; hash->bonding; hash = hash->bonding) ;
		hash->bondee = obj->value[index];
		ret = hash->getValue();
		ret->address = hash;
		ret->setSlot("base", base);
	} else {
		InkWarn_Index_Exceed(engine);
		return UNDEFINED;
	}

	return ret;
}
Exemplo n.º 3
0
Ink_Object *InkNative_Object_Debond(Ink_InterpreteEngine *engine, Ink_ContextChain *context, Ink_Object *base, Ink_ArgcType argc, Ink_Object **argv, Ink_Object *this_p)
{
	Ink_HashTable *tmp;

	if (base->address && (tmp = base->address->getBondee())) {
		tmp->setBonding(engine, NULL);
		return tmp->getValue();
	}

	return NULL_OBJ;
}
Exemplo n.º 4
0
Ink_Object *InkNative_Object_Each(Ink_InterpreteEngine *engine, Ink_ContextChain *context, Ink_Object *base, Ink_ArgcType argc, Ink_Object **argv, Ink_Object *this_p)
{
	Ink_Object **args;
	Ink_Object *ret_tmp;
	Ink_HashTable *hash;
	Ink_Array *ret = NULL;
	IGC_CollectEngine *gc_engine = engine->getCurrentGC();

	if (!checkArgument(engine, argc, argv, 1, INK_FUNCTION)) {
		return NULL_OBJ;
	}

	ret = new Ink_Array(engine);
	engine->addPardonObject(ret);

	args = (Ink_Object **)malloc(2 * sizeof(Ink_Object *));
	for (hash = base->hash_table; hash; hash = hash->next) {
		if (!hash->getValue())
			continue;
		gc_engine->checkGC();

		args[0] = new Ink_String(engine, string(hash->key));
		args[1] = hash->getValue() ? hash->getValue() : UNDEFINED;
		ret->value.push_back(new Ink_HashTable(ret_tmp = argv[0]->call(engine, context, base, 2, args), ret));
		if (engine->getSignal() != INTER_NONE) {
			switch (engine->getSignal()) {
				case INTER_RETURN:
					free(args);
					engine->removePardonObject(ret);
					return engine->getInterruptValue(); // signal penetrated
				case INTER_DROP:
				case INTER_BREAK:
					free(args);
					engine->removePardonObject(ret);
					return engine->trapSignal(); // trap the signal
				case INTER_CONTINUE:
					engine->trapSignal(); // trap the signal, but do not return
					continue;
				default:
					free(args);
					engine->removePardonObject(ret);
					return NULL_OBJ;
			}
		}
	}
	free(args);
	engine->removePardonObject(ret);

	return ret;
}
Exemplo n.º 5
0
Ink_Object *InkNative_Object_SetSetter(Ink_InterpreteEngine *engine, Ink_ContextChain *context, Ink_Object *base, Ink_ArgcType argc, Ink_Object **argv, Ink_Object *this_p)
{
	Ink_HashTable *hash;
	string tmp;

	if (!checkArgument(engine, argc, argv, 1, INK_STRING)) {
		return NULL_OBJ;
	}

	tmp = as<Ink_String>(argv[0])->getValue();
	if (!(hash = base->getSlotMapping(engine, tmp.c_str()))) {
		hash = base->setSlot(tmp.c_str(), NULL);
	}

	hash->setSetter(argc > 1 ? argv[1] : NULL);

	return NULL_OBJ;
}
Exemplo n.º 6
0
Ink_Object *InkNative_Object_Each(Ink_InterpreteEngine *engine, Ink_ContextChain *context, Ink_ArgcType argc, Ink_Object **argv, Ink_Object *this_p)
{
	Ink_Object *base = context->searchSlot(engine, "base");
	Ink_Object **args;
	Ink_Object *ret_tmp;
	Ink_HashTable *hash;
	Ink_ArrayValue ret_val;

	if (!checkArgument(engine, argc, argv, 1, INK_FUNCTION)) {
		return NULL_OBJ;
	}

	args = (Ink_Object **)malloc(2 * sizeof(Ink_Object *));
	for (hash = base->hash_table; hash && hash->getValue(); hash = hash->next) {
		args[0] = new Ink_String(engine, string(hash->key));
		args[1] = hash->getValue() ? hash->getValue() : UNDEFINED;
		ret_val.push_back(new Ink_HashTable(ret_tmp = argv[0]->call(engine, context, 2, args)));
		if (engine->getSignal() != INTER_NONE) {
			switch (engine->getSignal()) {
				case INTER_RETURN:
					free(args);
					cleanArrayHashTable(ret_val);
					return engine->getInterruptValue(); // signal penetrated
				case INTER_DROP:
				case INTER_BREAK:
					free(args);
					cleanArrayHashTable(ret_val);
					return engine->trapSignal(); // trap the signal
				case INTER_CONTINUE:
					engine->trapSignal(); // trap the signal, but do not return
					continue;
				default:
					free(args);
					cleanArrayHashTable(ret_val);
					return NULL_OBJ;
			}
		}
	}
	free(args);

	return new Ink_Array(engine, ret_val);
}