예제 #1
0
파일: array.cpp 프로젝트: jango2015/ink
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;
}
예제 #2
0
파일: io.cpp 프로젝트: jango2015/ink
	void InkMod_Loader(Ink_InterpreteEngine *engine, Ink_ContextChain *context)
	{
		Ink_Object *tmp;
		Ink_TypeTag *type_p = NULL;

		if (!engine->getEngineComAs<Ink_TypeTag>(ink_native_file_mod_id)) {
			type_p = (Ink_TypeTag *)malloc(sizeof(Ink_TypeTag) * 2);

			type_p[0] = (Ink_TypeTag)engine->registerType("io.file.File");
			type_p[1] = (Ink_TypeTag)engine->registerType("io.direct.Directory");

			engine->addEngineCom(ink_native_file_mod_id, type_p);
			engine->addDestructor(Ink_EngineDestructor(InkNative_IO_EngineComCleaner, new com_cleaner_arg(ink_native_file_mod_id)));

			context->getGlobal()->context->setSlot("$io.file.File", tmp = new Ink_FilePointer(engine));
			tmp->derivedMethodInit(engine);
			context->getGlobal()->context->setSlot("$io.direct.Directory", tmp = new Ink_DirectPointer(engine));
			tmp->derivedMethodInit(engine);
		}

		Ink_Object *io_pkg = addPackage(engine, context, "io", new Ink_FunctionObject(engine, InkMod_IO_Loader));
		Ink_Object *io_file_pkg = addPackage(engine, io_pkg, "file", new Ink_FunctionObject(engine, InkMod_File_Loader));
		Ink_Object *io_direct_pkg = addPackage(engine, io_pkg, "direct", new Ink_FunctionObject(engine, InkMod_Direct_Loader));

		InkMod_IO_bondTo(engine, io_pkg);
		InkMod_File_bondTo(engine, io_file_pkg);
		InkMod_Direct_bondTo(engine, io_direct_pkg);
	}
예제 #3
0
파일: actor.cpp 프로젝트: rod-lin/ink
Ink_Object *InkNative_Actor_Send(Ink_InterpreteEngine *engine, Ink_ContextChain *context, Ink_Object *base, Ink_ArgcType argc, Ink_Object **argv, Ink_Object *this_p)
{
	if (!checkArgument(engine, argc, argv, 1, INK_STRING)) {
		return NULL_OBJ;
	}
	
	Ink_Object *sender = new Ink_Object(engine);
	sender->setSlot_c("->", new Ink_FunctionObject(engine, InkNative_Actor_Send_Sub));
	sender->setSlot_c("msg", argv[0]);

	return sender;
}
예제 #4
0
파일: object.cpp 프로젝트: jinrenlab/ink
Ink_Object *InkNative_Object_Index(Ink_InterpreteEngine *engine, Ink_ContextChain *context, Ink_ArgcType argc, Ink_Object **argv, Ink_Object *this_p)
{
	Ink_Object *base = context->searchSlot(engine, "base");

	if (!checkArgument(engine, argc, argv, 1, INK_STRING)) {
		return NULL_OBJ;
	}
	
	if (!base->getSlotMapping(engine, as<Ink_String>(argv[0])->getValue().c_str())) {
		string *tmp = new string(as<Ink_String>(argv[0])->getValue());
		return getSlotWithProto(engine, context, base, tmp->c_str(), tmp);
	}

	return getSlotWithProto(engine, context, base, as<Ink_String>(argv[0])->getValue().c_str());
}
예제 #5
0
파일: object.cpp 프로젝트: jinrenlab/ink
Ink_Object *InkNative_Object_New(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 *new_obj = new Ink_Object(engine);
	Ink_HashTable *prototype_hash = base->getSlotMapping(engine, "prototype");

	if (prototype_hash) {
		new_obj->setSlot("prototype", prototype_hash->getValue());
	}

	if (base->type == INK_FUNCTION) {
		return base->call(engine, context, argc, argv, new_obj);
	}

	return new_obj;
}
예제 #6
0
파일: object.cpp 프로젝트: jinrenlab/ink
Ink_Object *InkNative_Object_SetSetter(Ink_InterpreteEngine *engine, Ink_ContextChain *context, Ink_ArgcType argc, Ink_Object **argv, Ink_Object *this_p)
{
	Ink_Object *base = context->searchSlot(engine, "base");
	Ink_HashTable *hash;
	const char *tmp;

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

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

	hash->setter = argc > 1 ? argv[1] : NULL;

	return NULL_OBJ;
}
예제 #7
0
파일: io.cpp 프로젝트: rod-lin/ink
Ink_Object *InkMod_IO_Loader(Ink_InterpreteEngine *engine, Ink_ContextChain *context, Ink_Object *base, Ink_ArgcType argc, Ink_Object **argv, Ink_Object *this_p)
{
	if (!checkArgument(engine, argc, 2)) {
		return NULL_OBJ;
	}

	Ink_Object *self = argv[0];
	Ink_Object *apply_to = argv[1];
	Ink_Object **tmp_argv = (Ink_Object **)malloc(sizeof(Ink_Object *) * 2);

	Ink_Object *file_pkg = self->getSlot(engine, "file");
	Ink_Object *direct_pkg = self->getSlot(engine, "direct");

	Ink_Object *file_loader = file_pkg->getSlot(engine, "load");
	Ink_Object *direct_loader = direct_pkg->getSlot(engine, "load");

	tmp_argv[0] = file_pkg;
	tmp_argv[1] = apply_to;

	if (file_loader->type == INK_FUNCTION) {
		file_loader->call(engine, context, file_pkg, 2, tmp_argv);
	} else {
		InkWarn_Package_Broken(engine, "io.file");
		return NULL_OBJ;
	}

	tmp_argv[0] = direct_pkg;

	if (direct_loader->type == INK_FUNCTION) {
		direct_loader->call(engine, context, direct_pkg, 2, tmp_argv);
	} else {
		InkWarn_Package_Broken(engine, "io.direct");
		return NULL_OBJ;
	}

	free(tmp_argv);

	InkMod_IO_bondTo(engine, apply_to);

	return NULL_OBJ;
}
예제 #8
0
Ink_Object *Ink_HashTableExpression::eval(Ink_InterpreteEngine *engine, Ink_ContextChain *context_chain, Ink_EvalFlag flags)
{
    const char *file_name_back;
    Ink_LineNoType line_num_back;
    SET_LINE_NUM;

    Ink_Object *ret = new Ink_Object(engine), *key;
    Ink_HashTableMapping::size_type i;

    for (i = 0; i < mapping.size(); i++) {
        /* two possibility: 1. identifier key; 2. expression key with brackets */
        if (mapping[i]->name) {
            ret->setSlot(mapping[i]->name->c_str(), mapping[i]->value->eval(engine, context_chain));
            if (INTER_SIGNAL_RECEIVED) {
                RESTORE_LINE_NUM;
                return engine->getInterruptValue();
            }
        } else {
            key = mapping[i]->key->eval(engine, context_chain);
            if (INTER_SIGNAL_RECEIVED) {
                RESTORE_LINE_NUM;
                return engine->getInterruptValue();
            }
            if (key->type != INK_STRING) {
                InkWarn_Hash_Table_Mapping_Expect_String(engine);
                return NULL_OBJ;
            }
            string *tmp = new string(as<Ink_String>(key)->getValue().c_str());
            ret->setSlot(tmp->c_str(),
                         mapping[i]->value->eval(engine, context_chain), true, tmp);
            if (INTER_SIGNAL_RECEIVED) {
                RESTORE_LINE_NUM;
                return engine->getInterruptValue();
            }
        }
    }

    RESTORE_LINE_NUM;
    return ret;
}
예제 #9
0
파일: interface.cpp 프로젝트: rod-lin/ink
void InkMod_Bignum_bondType(Ink_InterpreteEngine *engine, Ink_ContextChain *context)
{
	Ink_Object *tmp;
	com_struct *com = NULL;
	Ink_Object *obj_proto = engine->getTypePrototype(INK_OBJECT);

	if (!(com = engine->getEngineComAs<com_struct>(ink_native_bignum_mod_id))) {
		com = new com_struct();

		engine->addEngineCom(ink_native_bignum_mod_id, com);
		engine->addDestructor(Ink_EngineDestructor(InkMod_Bignum_EngineComCleaner,
												   new com_cleaner_arg(ink_native_bignum_mod_id)));
	} else if (com->bignum_type != (Ink_TypeTag)-1) /* has registered */ return;

	com->bignum_type = engine->registerType("bignum");
	context->getGlobal()->setSlot_c("$bignum", tmp = new Ink_BigNumeric(engine, "0"));
	engine->setTypePrototype(com->bignum_type, tmp);
	tmp->setProto(obj_proto);
	tmp->derivedMethodInit(engine);

	return;
}
예제 #10
0
파일: actor.cpp 프로젝트: jango2015/ink
Ink_Object *InkNative_Actor_Send_Sub(Ink_InterpreteEngine *engine, Ink_ContextChain *context, Ink_ArgcType argc, Ink_Object **argv, Ink_Object *this_p)
{
    Ink_Object *base = context->searchSlot(engine, "base");

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

    Ink_Object *msg = base->getSlot(engine, "msg");
    if (msg->type != INK_STRING) {
        InkWarn_Multink_Message_is_not_a_String(engine);
        return NULL_OBJ;
    }

    Ink_InterpreteEngine *dest = InkActor_getActor(as<Ink_String>(argv[0])->getValue());
    if (!dest) {
        InkWarn_Multink_Actor_Not_Found(engine, as<Ink_String>(argv[0])->getValue().c_str());
        return NULL_OBJ;
    }

    dest->sendInMessage(engine, as<Ink_String>(msg)->getValue());

    return TRUE_OBJ;
}
예제 #11
0
Ink_Object *Ink_CallExpression::eval(Ink_InterpreteEngine *engine, Ink_ContextChain *context_chain, Ink_EvalFlag flags)
{
    const char *file_name_back;
    Ink_LineNoType line_num_back;
    SET_LINE_NUM;

    Ink_ArgumentList::size_type i;
    Ink_Object **argv = NULL, **argv_back = NULL;
    Ink_Object *ret_val, *expandee;
    /* eval callee to get parameter declaration */
    Ink_Object *func = callee->eval(engine, context_chain);
    Ink_FunctionObject *tmp_func = NULL;
    if (INTER_SIGNAL_RECEIVED)
        return engine->getInterruptValue();
    Ink_ParamList param_list = Ink_ParamList();
    Ink_ArgumentList dispose_list, tmp_arg_list, another_tmp_arg_list;

    /* this part was moved from Ink_FunctionObject::call */
    bool is_arg_completed = true,
         if_delete_argv = false;
    Ink_ArgcType tmp_argc, j, argi, argc;
    Ink_Object **tmp_argv;

    if (func->type == INK_FUNCTION) {
        param_list = as<Ink_FunctionObject>(func)->param;
        tmp_func = as<Ink_FunctionObject>(func);
    }
    if (is_new) {
        func = Ink_HashExpression::getSlot(engine, context_chain, func, "new");
    }


    tmp_arg_list = Ink_ArgumentList();
    for (Ink_ArgumentList::iterator arg_list_iter = arg_list.begin();
            arg_list_iter != arg_list.end(); arg_list_iter++) {
        if ((*arg_list_iter)->is_expand) {
            /* if the argument is 'with' argument attachment */

            /* eval expandee */
            expandee = (*arg_list_iter)->expandee->eval(engine, context_chain);
            if (INTER_SIGNAL_RECEIVED) {
                ret_val = engine->getInterruptValue();
                goto DISPOSE_LIST;
            }

            /* expand argument */
            another_tmp_arg_list = expandArgument(engine, expandee);

            /* insert expanded argument to dispose list and temporary argument list */
            dispose_list.insert(dispose_list.end(), another_tmp_arg_list.begin(), another_tmp_arg_list.end());
            tmp_arg_list.insert(tmp_arg_list.end(), another_tmp_arg_list.begin(), another_tmp_arg_list.end());
        } else {
            /* normal argument, directly push to argument list */
            tmp_arg_list.push_back(*arg_list_iter);
        }
    }

    if (tmp_arg_list.size()) {
        /* allocate argument list */
        argv = (Ink_Object **)malloc(tmp_arg_list.size() * sizeof(Ink_Object *));
        argv_back = argv;

        /* set argument list, according to the parameter declaration */
        for (i = 0; i < tmp_arg_list.size(); i++) {
            if (i < param_list.size() && param_list[i].is_ref) {
                /* if the paramete is declared as reference, seal the expression to a anonymous function */
                if (param_list[i].is_variant) {
                    for (; i < tmp_arg_list.size(); i++) {
                        if (tmp_arg_list[i]->arg->is_unknown) {
                            argv[i] = new Ink_Unknown(engine);
                        } else {
                            Ink_ExpressionList exp_list = Ink_ExpressionList();
                            exp_list.push_back(tmp_arg_list[i]->arg);
                            argv[i] = new Ink_FunctionObject(engine, Ink_ParamList(), exp_list,
                                                             context_chain->copyContextChain(),
                                                             true);
                        }
                    }
                } else {
                    if (tmp_arg_list[i]->arg->is_unknown) {
                        argv[i] = new Ink_Unknown(engine);
                    } else {
                        Ink_ExpressionList exp_list = Ink_ExpressionList();
                        exp_list.push_back(tmp_arg_list[i]->arg);
                        argv[i] = new Ink_FunctionObject(engine, Ink_ParamList(), exp_list,
                                                         context_chain->copyContextChain(),
                                                         true);
                    }
                }
            } else {
                /* normal argument */
                argv[i] = tmp_arg_list[i]->arg->eval(engine, context_chain);
                if (INTER_SIGNAL_RECEIVED) {
                    ret_val = engine->getInterruptValue();
                    /* goto dispose and interrupt */
                    goto DISPOSE_ARGV;
                }
            }
        }
    }

    argc = tmp_arg_list.size();
    /* if some arguments have been applied already */
    if (tmp_func && tmp_func->partial_applied_argv) {
        tmp_argc = tmp_func->partial_applied_argc;
        tmp_argv = copyArgv(tmp_func->partial_applied_argc,
                            tmp_func->partial_applied_argv);
        for (j = 0, argi = 0; j < tmp_argc; j++) {
            /* find unknown place to put in arguments */
            if (isUnknown(tmp_argv[j])) {
                if (argi < argc /* not excess */
                        && !isUnknown(argv[argi]) /* not another unknown argument */)
                    tmp_argv[j] = argv[argi];
                else
                    is_arg_completed = false;
                argi++;
            }
        }

        if (!is_arg_completed) {
            /* still missing arguments -- return another PAF */
            if (argi < argc) {
                Ink_ArgcType remainc = argc - argi; /* remaining arguments */
                argc = remainc + tmp_argc;
                /* link the PA arguments and remaining arguments */
                argv = linkArgv(tmp_argc, tmp_argv,
                                remainc, &argv[argi]);

                free(tmp_argv);
                tmp_argc = argc;
                tmp_argv = argv;
            }
            ret_val = tmp_func->cloneWithPA(engine, tmp_argc, tmp_argv, true);
            goto DISPOSE_ARGV;
        }

        Ink_ArgcType remainc = argc - argi; /* remaining arguments */
        argc = remainc + tmp_argc;
        /* link the PA arguments and remaining arguments */
        argv = linkArgv(tmp_argc, tmp_argv,
                        remainc, &argv[argi]);
        free(tmp_argv);
        if_delete_argv = true;
    }

    for (argi = 0; tmp_func && argi < argc; argi++) {
        if (isUnknown(argv[argi])) { /* find unknown argument */
            ret_val = tmp_func->cloneWithPA(engine, argc, copyArgv(argc, argv), true);
            goto DISPOSE_ARGV;
        }
    }

    ret_val = func->call(engine, context_chain, argc, argv);

DISPOSE_ARGV:
    if (if_delete_argv)
        free(argv);
    if (argv_back)
        free(argv_back);

DISPOSE_LIST:
    for (i = 0; i < dispose_list.size(); i++) {
        delete dispose_list[i];
    }

    RESTORE_LINE_NUM;

    return ret_val;
}
예제 #12
0
Ink_Object *Ink_HashExpression::getSlot(Ink_InterpreteEngine *engine, Ink_ContextChain *context_chain,
                                        Ink_Object *obj, const char *id, Ink_EvalFlag flags, string *id_p)
{
    const char *debug_name_back;
    Ink_HashTable *hash, *address;
    Ink_Object *base = obj, *ret, *tmp;
    Ink_Object **argv;
    ProtoSearchRet search_res;

    if (!(hash = obj->getSlotMapping(engine, id)) /* cannot find slot in the origin object */) {
        if (obj->type == INK_UNDEFINED) {
            InkWarn_Get_Slot_Of_Undefined(engine, id);
        }
        /* search prototype */
        engine->initPrototypeSearch();
        hash = (search_res = searchPrototype(engine, obj, id)).hash;

        /* create barrier to prevent changes on prototype */
        address = obj->setSlot(id, NULL, id_p);
        if (hash) { /* if found the slot in prototype */
            base = search_res.base; /* set base as the prototype(to make some native method run correctly) */
            ret = hash->getValue();
        } else {
            if ((tmp = obj->getSlot(engine, "missing"))->type == INK_FUNCTION) {
                /* has missing method, call it */
                tmp->setSlot("base", obj);
                argv = (Ink_Object **)malloc(sizeof(Ink_Object *));
                argv[0] = new Ink_String(engine, string(id));
                ret = tmp->call(engine, context_chain, 1, argv);
                free(argv);
                goto END;
            } else {
                /* return undefined */
                ret = UNDEFINED;
            }
        }
    } else {
        /* found slot correctly */
        ret = hash->getValue();
        address = hash;
        delete id_p;
    }

    /* set address for possible assignment */
    ret->address = address;
    /* set base */
    debug_name_back = base->getDebugName();
    ret->setSlot("base", base);
    base->setDebugName(debug_name_back);

    /* call getter if has one */
    if (!flags.is_left_value && address->getter) {
        address->getter->setSlot("base", address->getValue());
        ret = address->getter->call(engine, context_chain, 0, NULL);
        // /* trap all interrupt signal */
        // engine->setSignal(INTER_NONE);
        if (INTER_SIGNAL_RECEIVED) {
            return engine->getInterruptValue();
        }
    }

END:
    return ret;
}
예제 #13
0
파일: direct.cpp 프로젝트: jinrenlab/ink
Ink_Object *InkNative_Direct_Each(Ink_InterpreteEngine *engine, Ink_ContextChain *context, Ink_ArgcType argc, Ink_Object **argv, Ink_Object *this_p)
{
	Ink_Object *base = context->searchSlot(engine, "base");
	string *tmp_path;
	Ink_Object **args = NULL;
	Ink_Object *ret_tmp;
	Ink_ArrayValue ret_val;
	Ink_ArrayValue::size_type i;
	Ink_Object *block = NULL;

	ASSUME_BASE_TYPE(engine, DIRECT_TYPE);

	if (!(tmp_path = as<Ink_DirectPointer>(base)->path)) {
		InkWarn_IO_Uninitialized_Direct_Pointer(engine);
		return NULL_OBJ;
	}

	if (argc && argv[0]->type == INK_FUNCTION)
		block = argv[0];

	args = (Ink_Object **)malloc(sizeof(Ink_Object *));

#if defined(INK_PLATFORM_LINUX)
	DIR *dir_handle = opendir(tmp_path->c_str());
	struct dirent *child;

	if (!dir_handle) {
		InkWarn_Direct_Not_Exist(engine, tmp_path->c_str());
		free(args);
		return NULL_OBJ;
	}

	while ((child = readdir(dir_handle)) != NULL) {

	#define CLOSE_HANDLER closedir(dir_handle)
	#define CHILD_NAME (child->d_name)
#elif defined(INK_PLATFORM_WIN32)
	WIN32_FIND_DATA data;
	HANDLE dir_handle = NULL;

	dir_handle = FindFirstFile((string(INK_MODULE_DIR) + "/*").c_str(), &data);

	if (dir_handle == INVALID_HANDLE_VALUE) {
		do {

	#define CLOSE_HANDLER FindClose(dir_handle)
	#define CHILD_NAME (data.cFileName)
#endif

	if (block) {
		args[0] = new Ink_String(engine, string(CHILD_NAME));
		ret_val.push_back(new Ink_HashTable(ret_tmp = block->call(engine, context, 1, args)));
		if (engine->getSignal() != INTER_NONE) {
			switch (engine->getSignal()) {
				case INTER_RETURN:
					free(args);
					cleanArrayHashTable(ret_val);
					CLOSE_HANDLER;
					return engine->getInterruptValue(); // signal penetrated
				case INTER_DROP:
				case INTER_BREAK:
					free(args);
					cleanArrayHashTable(ret_val);
					CLOSE_HANDLER;
					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);
					CLOSE_HANDLER;
					return NULL_OBJ;
			}
		}
	} else {
		ret_val.push_back(new Ink_HashTable(new Ink_String(engine, string(CHILD_NAME))));
	}


#if defined(INK_PLATFORM_LINUX)
	}

	closedir(dir_handle);
#elif defined(INK_PLATFORM_WIN32)
		} while (FindNextFile(dir_handle, &data));
	} else {
예제 #14
0
파일: object.cpp 프로젝트: jinrenlab/ink
Ink_Object *InkNative_Object_Clone(Ink_InterpreteEngine *engine, Ink_ContextChain *context, Ink_ArgcType argc, Ink_Object **argv, Ink_Object *this_p)
{
	Ink_Object *base = context->searchSlot(engine, "base");

	return base->clone(engine);
}