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; }
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; }
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 {