bool Install(lua_State *L, std::vector<fs::path> const& include_path) { // set the module load path to include_path lua_getglobal(L, "package"); push_value(L, "path"); push_value(L, ""); for (auto const& path : include_path) { lua_pushfstring(L, "%s/?.lua;%s/?/init.lua;", path.string().c_str(), path.string().c_str()); lua_concat(L, 2); } #ifndef _WIN32 // No point in checking any of the default locations on Windows since // there won't be anything there push_value(L, "path"); lua_gettable(L, -4); lua_concat(L, 2); #endif lua_settable(L, -3); // Replace the default lua module loader with our unicode compatible one lua_getfield(L, -1, "loaders"); push_value(L, exception_wrapper<module_loader>); lua_rawseti(L, -2, 2); lua_pop(L, 2); // loaders, package luaL_loadstring(L, "return require('moonscript').loadstring"); if (lua_pcall(L, 0, 1, 0)) { return false; // leave error message } lua_setfield(L, LUA_REGISTRYINDEX, "moonscript"); return true; }
static int moon_line(lua_State *L, int lua_line, std::string const& file) { if (luaL_dostring(L, "return require 'moonscript.line_tables'")) { lua_pop(L, 1); // pop error message return lua_line; } push_value(L, file); lua_rawget(L, -2); if (!lua_istable(L, -1)) { lua_pop(L, 2); return lua_line; } lua_rawgeti(L, -1, lua_line); if (!lua_isnumber(L, -1)) { lua_pop(L, 3); return lua_line; } auto char_pos = static_cast<size_t>(lua_tonumber(L, -1)); lua_pop(L, 3); // The moonscript line tables give us a character offset into the file, // so now we need to map that to a line number lua_getfield(L, LUA_REGISTRYINDEX, ("raw moonscript: " + file).c_str()); if (!lua_isstring(L, -1)) { lua_pop(L, 1); return lua_line; } size_t moon_len; auto moon = lua_tolstring(L, -1, &moon_len); return std::count(moon, moon + std::min(moon_len, char_pos), '\n') + 1; }
void lambda(su_state *s, prototype_t *prot, int narg) { unsigned i, tmp; value_t v; function_t *func = su_allocate(s, NULL, sizeof(function_t)); func->narg = narg; func->prot = prot; func->num_const = prot->num_const; func->num_ups = prot->num_ups; func->constants = su_allocate(s, NULL, sizeof(value_t) * prot->num_const); func->upvalues = su_allocate(s, NULL, sizeof(value_t) * prot->num_ups); for (i = 0; i < func->num_const; i++) func->constants[i] = create_value(s, &prot->constants[i]); for (i = 0; i < func->num_ups; i++) { tmp = s->frame_top - prot->upvalues[i].lv; tmp = s->frames[tmp].stack_top + prot->upvalues[i].idx + 1; func->upvalues[i] = s->stack[tmp]; } gc_insert_object(s, (gc_t*)func, SU_FUNCTION); v.type = SU_FUNCTION; v.obj.func = func; push_value(s, &v); }
call_ret_t call(state_t &state, const function_ref_t &func, const Args &... args) { if( !func.is_valid() ) throw fatal_error_t(state, "lua function invalid()"); int top_beg = ::lua_gettop(state); func.get(); if( state != func.state() ) throw std::runtime_error("state not equal to function state"); std::int32_t arg_cnt = sizeof...( args ); push_value(state, args...); int error_index = 0; int base = ::lua_gettop(state) - arg_cnt; std::string error_msg; error_handler(state, error_msg); lua_insert(state, base); error_index = base; int error = lua_pcall(state, arg_cnt, LUA_MULTRET, error_index); if(error_index != 0) lua_remove(state, error_index); if( error != 0 ) throw fatal_error_t(state, error_msg, error); int top_last = ::lua_gettop(state); return call_ret_t(state, top_last - top_beg); }
call_ret_t call(state_t &state, const char *function_name, Args&&... args ) { assert(function_name && "function_name not be empty"); int top_beg = ::lua_gettop(state); ::lua_getglobal(state, function_name); std::int32_t arg_cnt = sizeof...(args); push_value(state, std::forward<Args>(args)...); int base = ::lua_gettop(state) - arg_cnt; std::string error_msg; error_handler(state, error_msg); lua_insert(state, base); int error_index = base; int error = lua_pcall(state, arg_cnt, LUA_MULTRET, error_index); if( error_index != 0 ) lua_remove(state, error_index); if( error != 0 ) throw fatal_error_t(state, error_msg, error); int top_last = ::lua_gettop(state); return call_ret_t(state, top_last - top_beg); }
static void eval_inc_dec_expression(SIMCAR_Interpreter *inter, SIMCAR_LocalEnvironment *env, Expression *expr) { SIMCAR_Value *operand; SIMCAR_Value result; int old_value; operand = get_lvalue(inter, env, expr->u.inc_dec.operand); if (operand->type != SIMCAR_INT_VALUE) { crb_runtime_error(expr->line_number, INC_DEC_OPERAND_TYPE_ERR, MESSAGE_ARGUMENT_END); } old_value = operand->u.int_value; if (expr->type == INCREMENT_EXPRESSION) { operand->u.int_value++; } else { DBG_assert(expr->type == DECREMENT_EXPRESSION, ("expr->type..%d\n", expr->type)); operand->u.int_value--; } result.type = SIMCAR_INT_VALUE; result.u.int_value = old_value; push_value(inter, &result); }
static value_t* call_function_lua(language_t*li, const char*name, value_t*args) { lua_internal_t*lua = (lua_internal_t*)li->internal; lua_State*l = lua->state; lua_getfield(l, LUA_GLOBALSINDEX, name); if(!lua_isfunction(l, -1)) { language_error(li, "%s is not a function", name); return NULL; } int i; for(i=0;i<args->length;i++) { push_value(l, args->data[i]); } int error = lua_pcall(l, /*nargs*/args->length, /*nresults*/1, 0); if(error) { show_error(li, l); language_error(li, "Error calling function %s: %d\n", name, error); return NULL; } value_t*ret = lua_to_value(li, -1); lua_pop(l, 1); return ret; }
static void push_value(lua_State*l, value_t*value) { int i; switch(value->type) { case TYPE_VOID: lua_pushnil(l); break; case TYPE_FLOAT32: lua_pushnumber(l, value->f32); break; case TYPE_INT32: lua_pushinteger(l, value->i32); break; case TYPE_BOOLEAN: lua_pushboolean(l, value->b); break; case TYPE_STRING: { lua_pushstring(l, value->str); } break; case TYPE_ARRAY: { lua_newtable(l); for(i=0;i<value->length;i++) { lua_pushinteger(l, i); push_value(l, value->data[i]); lua_settable(l, -3); } } break; default: { lua_pushnil(l); } } }
void pushFromPacket(const hexabus::ValuePacket<T>& packet) { std::ostringstream oss; oss << std::fixed << std::setprecision(1) << float(packet.value()); push_value(packet.eid(), oss.str()); }
void su_vector(su_state *s, int num) { int i; value_t vec = vector_create_empty(s); for (i = 0; i < num; i++) vec = vector_push(s, vec.obj.vec, STK(-(num - i))); s->stack_top -= num; push_value(s, &vec); }
void su_vector_push(su_state *s, int idx, int num) { int i; value_t vec = *STK(TOP(idx)); for (i = 0; i < num; i++) vec = vector_push(s, vec.obj.vec, STK(-(num - i))); s->stack_top -= num; push_value(s, &vec); }
void su_vector_pop(su_state *s, int idx, int num) { int i; int n = (int)STK(TOP(num))->obj.num; value_t vec = *STK(TOP(idx)); for (i = 0; i < n; i++) vec = vector_pop(s, vec.obj.vec); push_value(s, &vec); }
int su_getglobal(su_state *s, const char *name) { int size = strlen(name); value_t v = get_global(s, name, murmur(name, size, 0), size); if (v.type == SU_INV) return 0; push_value(s, &v); return 1; }
static void eval_int_expression(SIMCAR_Interpreter *inter, int int_value) { SIMCAR_Value v; v.type = SIMCAR_INT_VALUE; v.u.int_value = int_value; push_value(inter, &v); }
static void define_constant_lua(struct _language*li, const char*name, value_t*value) { lua_internal_t*lua = (lua_internal_t*)li->internal; lua_State*l = lua->state; push_value(l, value); lua_setglobal(l, name); }
static void eval_null_expression(SIMCAR_Interpreter *inter) { SIMCAR_Value v; v.type = SIMCAR_NULL_VALUE; push_value(inter, &v); }
static void eval_string_expression(SIMCAR_Interpreter *inter, char *string_value) { SIMCAR_Value v; v.type = SIMCAR_STRING_VALUE; v.u.object = crb_literal_to_crb_string(inter, string_value); push_value(inter, &v); }
static void eval_double_expression(SIMCAR_Interpreter *inter, double double_value) { SIMCAR_Value v; v.type = SIMCAR_DOUBLE_VALUE; v.u.double_value = double_value; push_value(inter, &v); }
static void eval_boolean_expression(SIMCAR_Interpreter *inter, SIMCAR_Boolean boolean_value) { SIMCAR_Value v; v.type = SIMCAR_BOOLEAN_VALUE; v.u.boolean_value = boolean_value; push_value(inter, &v); }
void su_string_push(su_state *s) { value_t v; assert(s->string_builder); v.type = SU_STRING; s->string_builder->hash = murmur(s->string_builder->str, s->string_builder->size, 0); v.obj.gc_object = string_build_from_cache(s); push_value(s, &v); s->string_builder = NULL; }
void *su_newdata(su_state *s, unsigned size, const su_data_class_t *vt) { value_t v; v.type = SU_NATIVEDATA; v.obj.data = (native_data_t*)su_allocate(s, NULL, sizeof(native_data_t) + size - 1); v.obj.data->vt = (su_data_class_t*)vt; gc_insert_object(s, v.obj.gc_object, SU_NATIVEDATA); push_value(s, &v); return (void*)v.obj.data->data; }
static void eval_index_expression(SIMCAR_Interpreter *inter, SIMCAR_LocalEnvironment *env, Expression *expr) { SIMCAR_Value *left; left = get_array_element_lvalue(inter, env, expr); push_value(inter, left); }
/* -3: function decode -2: table key -1: table id */ static void decode_cb(void *ud, int type, const char * type_name, union pbc_value *v, int id, const char *key) { lua_State *L = (lua_State *)ud; if (key == NULL) { // undefined field return; } if (type & PBC_REPEATED) { push_value(L, type & ~PBC_REPEATED, type_name, v); new_array(L, id , key); // func.decode table.key table.id value array int n = (int)lua_rawlen(L,-1); lua_insert(L, -2); // func.decode table.key table.id array value lua_rawseti(L, -2 , n+1); // func.decode table.key table.id array lua_pop(L,1); } else { push_value(L, type, type_name, v); lua_setfield(L, -3 , key); } }
int su_unpack_seq(su_state *s, int idx) { int num = 0; value_t tmp; value_t v = *STK(TOP(idx)); while (isseq(s, &v)) { tmp = v.obj.q->vt->first(s, v.obj.q); push_value(s, &tmp); v = v.obj.q->vt->rest(s, v.obj.q); num++; } return num; }
void su_map(su_state *s, int num) { int i; value_t k, v; value_t m = map_create_empty(s); for (i = num * 2; i > 0; i -= 2) { k = *STK(-i); v = *STK(-i + 1); m = map_insert(s, m.obj.m, &k, hash_value(&k), &v); } s->stack_top -= num * 2; push_value(s, &m); }
node_t hash_push_value(char* key,node_t value){ node_t head,target,nvalue; head=HASH+key2hash(key,NUM); target=get_node(head->cdr,key); if(!target){ target=alloc_node(key); target->cdr=head->cdr; head->cdr=target; } nvalue=alloc_node(key); nvalue->child=value; node->child=push_value(node->child,nvalue); return value; }
void su_fork(su_state *s, int narg) { value_t v; su_state *ns; narg++; v.type = SU_BOOLEAN; su_thread_indisposable(s); spin_lock(&s->msi->thread_pool_lock); su_thread_disposable(s); ns = new_state(s); if (!ns) { s->stack_top -= narg; v.obj.b = 0; push_value(s, &v); spin_unlock(&s->msi->thread_pool_lock); return; } ns->interrupt = 0x0; ns->narg = narg - 1; ns->pc = 0xffff; ns->string_builder = NULL; ns->errtop = ns->ferrtop = -1; ns->stack[SU_GLOBAL_INDEX] = s->stack[SU_GLOBAL_INDEX]; su_assert(s, !thread_init(&thread_boot, (void*)ns), "Could not create thread!"); s->stack_top -= narg; v.obj.b = 1; push_value(s, &v); spin_unlock(&s->msi->thread_pool_lock); }
bool LoadFile(lua_State *L, agi::fs::path const& raw_filename) { auto filename = raw_filename; try { filename = agi::fs::Canonicalize(raw_filename); } catch (agi::fs::FileSystemUnknownError const& e) { LOG_E("auto4/lua") << "Error canonicalizing path: " << e.GetMessage(); } agi::read_file_mapping file(filename); auto buff = file.read(); size_t size = static_cast<size_t>(file.size()); // Discard the BOM if present if (size >= 3 && buff[0] == -17 && buff[1] == -69 && buff[2] == -65) { buff += 3; size -= 3; } if (!agi::fs::HasExtension(filename, "moon")) return luaL_loadbuffer(L, buff, size, filename.string().c_str()) == 0; // We have a MoonScript file, so we need to load it with that // It might be nice to have a dedicated lua state for compiling // MoonScript to Lua lua_getfield(L, LUA_REGISTRYINDEX, "moonscript"); // Save the text we'll be loading for the line number rewriting in the // error handling lua_pushlstring(L, buff, size); lua_pushvalue(L, -1); lua_setfield(L, LUA_REGISTRYINDEX, ("raw moonscript: " + filename.string()).c_str()); push_value(L, filename); if (lua_pcall(L, 2, 2, 0)) return false; // Leaves error message on stack // loadstring returns nil, error on error or a function on success if (lua_isnil(L, 1)) { lua_remove(L, 1); return false; } lua_pop(L, 1); // Remove the extra nil for the stackchecker return true; }
su_state *su_init(su_alloc alloc) { int i; value_t v; su_state *s; su_alloc mf; main_state_internal_t *msi; assert(sizeof(value_t) <= SU_VALUE_SIZE); assert(sizeof(value_t) > SU_VALUE_DATA_SIZE); mf = alloc ? alloc : default_alloc; msi = (main_state_internal_t*)mf(NULL, sizeof(main_state_internal_t)); s = &msi->threads[0]; memset(msi, 0, sizeof(main_state_internal_t)); for (i = 0; i < SU_OPT_MAX_THREADS; i++) msi->threads[i].thread_finished.value = 1; s->alloc = mf; s->msi = msi; s->main_state = s; msi->gc_state = GC_STATE_SWEEP; s->fstdin = stdin; s->fstdout = stdout; s->fstderr = stderr; s->errtop = s->ferrtop = -1; s->pc = 0xffff; s->msi->ref_counter = 0x1; s->msi->tid_count.value = 1; s->msi->thread_count.value = 1; v = init_globals(s); su_pushnil(s); /* SU_NIL_INDEX */ push_value(s, &v); /* SU_GLOBAL_INDEX */ su_map(s, 0); /* SU_REGISTRY_INDEX */ rw_barrier(); return s; }
static void call_crowbar_function(SIMCAR_Interpreter *inter, SIMCAR_LocalEnvironment *env, SIMCAR_LocalEnvironment *caller_env, Expression *expr, FunctionDefinition *func) { SIMCAR_Value value; StatementResult result; ArgumentList *arg_p; ParameterList *param_p; for (arg_p = expr->u.function_call_expression.argument, param_p = func->u.crowbar_f.parameter; arg_p; arg_p = arg_p->next, param_p = param_p->next) { Variable *new_var; SIMCAR_Value arg_val; if (param_p == NULL) { crb_runtime_error(expr->line_number, ARGUMENT_TOO_MANY_ERR, MESSAGE_ARGUMENT_END); } eval_expression(inter, caller_env, arg_p->expression); arg_val = pop_value(inter); new_var = crb_add_local_variable(env, param_p->name); new_var->value = arg_val; } if (param_p) { crb_runtime_error(expr->line_number, ARGUMENT_TOO_FEW_ERR, MESSAGE_ARGUMENT_END); } result = crb_execute_statement_list(inter, env, func->u.crowbar_f.block ->statement_list); if (result.type == RETURN_STATEMENT_RESULT) { value = result.u.return_value; } else { value.type = SIMCAR_NULL_VALUE; } push_value(inter, &value); }