void dump_state(mrb_state *mrb) { mrb_full_gc(mrb); printf("\nVM: %s\n", (const char *)mrb->ud); mrb_funcall(mrb, mrb_obj_value(mrb->top_self), "print_memory_state", 0); }
void init_cfunc_type(mrb_state *mrb, struct RClass* module) { struct cfunc_state *state = cfunc_state(mrb, module); struct RClass *type_class = mrb_define_class_under(mrb, module, "Type", mrb->object_class); MRB_SET_INSTANCE_TT(type_class, MRB_TT_DATA); state->type_class = type_class; set_cfunc_state(mrb, type_class, state); int ai = mrb_gc_arena_save(mrb); mrb_define_class_method(mrb, type_class, "refer", cfunc_type_class_refer, ARGS_REQ(1)); mrb_define_class_method(mrb, type_class, "size", cfunc_type_size, ARGS_NONE()); mrb_define_class_method(mrb, type_class, "align", cfunc_type_align, ARGS_NONE()); mrb_define_class_method(mrb, type_class, "get", cfunc_type_class_get, ARGS_REQ(1)); mrb_define_class_method(mrb, type_class, "set", cfunc_type_class_set, ARGS_REQ(2)); mrb_define_method(mrb, type_class, "initialize", cfunc_type_initialize, ARGS_ANY()); mrb_define_method(mrb, type_class, "value", cfunc_type_get_value, ARGS_NONE()); mrb_define_method(mrb, type_class, "value=", cfunc_type_set_value, ARGS_REQ(1)); mrb_define_method(mrb, type_class, "addr", cfunc_type_addr, ARGS_NONE()); mrb_define_method(mrb, type_class, "to_ffi_value", cfunc_type_addr, ARGS_NONE()); DONE; int map_size = sizeof(types) / sizeof(struct mrb_ffi_type); int i; for(i = 0; i < map_size; ++i) { struct RClass *new_class = mrb_define_class_under(mrb, module, types[i].name, type_class); mrb_value ffi_type = mrb_obj_value(Data_Wrap_Struct(mrb, mrb->object_class, &cfunc_class_ffi_data_type, &types[i])); mrb_obj_iv_set(mrb, (struct RObject*)new_class, mrb_intern(mrb, "@ffi_type"), ffi_type); } DONE; mrb_value mod = mrb_obj_value(module); state->void_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern(mrb, "Void"))); state->uint8_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern(mrb, "UInt8"))); state->sint8_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern(mrb, "SInt8"))); state->uint16_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern(mrb, "UInt16"))); state->sint16_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern(mrb, "SInt16"))); state->uint32_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern(mrb, "UInt32"))); state->sint32_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern(mrb, "SInt32"))); state->uint64_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern(mrb, "UInt64"))); state->sint64_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern(mrb, "SInt64"))); state->float_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern(mrb, "Float"))); state->double_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern(mrb, "Double"))); DONE; mrb_define_class_method(mrb, mrb->nil_class, "size", cfunc_nil_size, ARGS_NONE()); mrb_define_class_method(mrb, mrb->nil_class, "align", cfunc_nil_align, ARGS_NONE()); DONE; // uint64 specific struct RClass *uint64_class = state->uint64_class; mrb_define_class_method(mrb, uint64_class, "get", cfunc_uint64_class_get, ARGS_REQ(1)); mrb_define_method(mrb, uint64_class, "value", cfunc_uint64_get_value, ARGS_NONE()); mrb_define_method(mrb, uint64_class, "low", cfunc_uint64_get_low, ARGS_NONE()); mrb_define_method(mrb, uint64_class, "low=", cfunc_uint64_set_low, ARGS_REQ(1)); mrb_define_method(mrb, uint64_class, "high", cfunc_uint64_get_high, ARGS_NONE()); mrb_define_method(mrb, uint64_class, "high=", cfunc_uint64_set_high, ARGS_REQ(1)); mrb_define_method(mrb, uint64_class, "to_s", cfunc_uint64_to_s, ARGS_REQ(1)); mrb_define_method(mrb, uint64_class, "divide", cfunc_uint64_divide, ARGS_REQ(1)); DONE; // sint64 specific struct RClass *sint64_class = state->sint64_class; mrb_define_class_method(mrb, sint64_class, "get", cfunc_sint64_class_get, ARGS_REQ(1)); mrb_define_method(mrb, sint64_class, "value", cfunc_sint64_get_value, ARGS_NONE()); mrb_define_method(mrb, sint64_class, "low", cfunc_uint64_get_low, ARGS_NONE()); mrb_define_method(mrb, sint64_class, "low=", cfunc_uint64_set_low, ARGS_REQ(1)); mrb_define_method(mrb, sint64_class, "high", cfunc_uint64_get_high, ARGS_NONE()); mrb_define_method(mrb, sint64_class, "high=", cfunc_uint64_set_high, ARGS_REQ(1)); mrb_define_method(mrb, sint64_class, "to_s", cfunc_int64_to_s, ARGS_REQ(1)); DONE; }
MRB_API mrb_value mrb_ary_new_capa(mrb_state *mrb, mrb_int capa) { struct RArray *a = ary_new_capa(mrb, capa); return mrb_obj_value(a); }
mrb_value mrb_sdl2_input_event(mrb_state *mrb, SDL_Event const *event) { if (NULL == event) { return mrb_nil_value(); } mrb_sdl2_input_event_data_t *data = (mrb_sdl2_input_event_data_t*)mrb_malloc(mrb, sizeof(mrb_sdl2_input_event_data_t)); if (NULL == data) { mrb_raise(mrb, E_RUNTIME_ERROR, "insufficient memory."); } data->event = *event; switch (event->type) { case SDL_QUIT: return mrb_obj_value(Data_Wrap_Struct(mrb, class_QuitEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_APP_TERMINATING: case SDL_APP_LOWMEMORY: case SDL_APP_WILLENTERBACKGROUND: case SDL_APP_DIDENTERBACKGROUND: case SDL_APP_WILLENTERFOREGROUND: case SDL_APP_DIDENTERFOREGROUND: return mrb_obj_value(Data_Wrap_Struct(mrb, class_OsEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_WINDOWEVENT: return mrb_obj_value(Data_Wrap_Struct(mrb, class_WindowEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_SYSWMEVENT: return mrb_obj_value(Data_Wrap_Struct(mrb, class_SysWMEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_KEYDOWN: case SDL_KEYUP: return mrb_obj_value(Data_Wrap_Struct(mrb, class_KeyboardEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_TEXTEDITING: return mrb_obj_value(Data_Wrap_Struct(mrb, class_TextEditingEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_TEXTINPUT: return mrb_obj_value(Data_Wrap_Struct(mrb, class_TextInputEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_MOUSEMOTION: return mrb_obj_value(Data_Wrap_Struct(mrb, class_MouseMotionEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: return mrb_obj_value(Data_Wrap_Struct(mrb, class_MouseButtonEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_MOUSEWHEEL: return mrb_obj_value(Data_Wrap_Struct(mrb, class_MouseWheelEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_JOYAXISMOTION: return mrb_obj_value(Data_Wrap_Struct(mrb, class_JoyAxisEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_JOYBALLMOTION: return mrb_obj_value(Data_Wrap_Struct(mrb, class_JoyBallEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_JOYHATMOTION: return mrb_obj_value(Data_Wrap_Struct(mrb, class_JoyHatEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: return mrb_obj_value(Data_Wrap_Struct(mrb, class_JoyButtonEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_JOYDEVICEADDED: case SDL_JOYDEVICEREMOVED: return mrb_obj_value(Data_Wrap_Struct(mrb, class_JoyDeviceEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_CONTROLLERAXISMOTION: return mrb_obj_value(Data_Wrap_Struct(mrb, class_ControllerAxisEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_CONTROLLERBUTTONDOWN: case SDL_CONTROLLERBUTTONUP: return mrb_obj_value(Data_Wrap_Struct(mrb, class_ControllerButtonEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_CONTROLLERDEVICEADDED: case SDL_CONTROLLERDEVICEREMOVED: case SDL_CONTROLLERDEVICEREMAPPED: return mrb_obj_value(Data_Wrap_Struct(mrb, class_ControllerDeviceEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_FINGERDOWN: case SDL_FINGERUP: case SDL_FINGERMOTION: return mrb_obj_value(Data_Wrap_Struct(mrb, class_TouchFingerEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_DOLLARGESTURE: case SDL_DOLLARRECORD: return mrb_obj_value(Data_Wrap_Struct(mrb, class_DollarGestureEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_MULTIGESTURE: return mrb_obj_value(Data_Wrap_Struct(mrb, class_MultiGestureEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_CLIPBOARDUPDATE: break; /* missing event */ case SDL_DROPFILE: return mrb_obj_value(Data_Wrap_Struct(mrb, class_DropEvent, &mrb_sdl2_input_event_data_type, data)); case SDL_USEREVENT: return mrb_obj_value(Data_Wrap_Struct(mrb, class_UserEvent, &mrb_sdl2_input_event_data_type, data)); default: if (event->type > SDL_USEREVENT) { return mrb_obj_value(Data_Wrap_Struct(mrb, class_UserEvent, &mrb_sdl2_input_event_data_type, data)); } else { mrb_free(mrb, data); mrb_raise(mrb, E_RUNTIME_ERROR, "undefined event type."); } break; } mrb_free(mrb, data); return mrb_nil_value(); }
mrb_value mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, long len) { return mrb_funcall(mrb, mrb_obj_value(c), "new", 1, mrb_str_new(mrb, ptr, len)); }
void mrb_init_class(mrb_state *mrb) { struct RClass *bob; /* BasicObject */ struct RClass *obj; /* Object */ struct RClass *mod; /* Module */ struct RClass *cls; /* Class */ //struct RClass *krn; /* Kernel */ /* boot class hierarchy */ bob = boot_defclass(mrb, 0); obj = boot_defclass(mrb, bob); mrb->object_class = obj; mod = boot_defclass(mrb, obj); mrb->module_class = mod;/* obj -> mod */ cls = boot_defclass(mrb, mod); mrb->class_class = cls; /* obj -> cls */ /* fix-up loose ends */ bob->c = obj->c = mod->c = cls->c = cls; make_metaclass(mrb, bob); make_metaclass(mrb, obj); make_metaclass(mrb, mod); make_metaclass(mrb, cls); /* name basic classes */ mrb_define_const(mrb, bob, "BasicObject", mrb_obj_value(bob)); mrb_define_const(mrb, obj, "BasicObject", mrb_obj_value(bob)); mrb_define_const(mrb, obj, "Object", mrb_obj_value(obj)); mrb_define_const(mrb, obj, "Module", mrb_obj_value(mod)); mrb_define_const(mrb, obj, "Class", mrb_obj_value(cls)); /* name each classes */ mrb_name_class(mrb, bob, mrb_intern(mrb, "BasicObject")); mrb_name_class(mrb, obj, mrb_intern(mrb, "Object")); mrb_name_class(mrb, mod, mrb_intern(mrb, "Module")); mrb_name_class(mrb, cls, mrb_intern(mrb, "Class")); mrb_undef_method(mrb, mod, "new"); MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS); mrb_define_method(mrb, bob, "initialize", mrb_bob_init, MRB_ARGS_NONE()); mrb_define_method(mrb, bob, "!", mrb_bob_not, MRB_ARGS_NONE()); mrb_define_method(mrb, bob, "method_missing", mrb_bob_missing, MRB_ARGS_ANY()); /* 15.3.1.3.30 */ mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, MRB_ARGS_ANY()); mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, MRB_ARGS_NONE()); /* 15.2.3.3.4 */ mrb_define_method(mrb, cls, "new", mrb_instance_new, MRB_ARGS_ANY()); /* 15.2.3.3.3 */ mrb_define_method(mrb, cls, "inherited", mrb_bob_init, MRB_ARGS_REQ(1)); MRB_SET_INSTANCE_TT(mod, MRB_TT_MODULE); mrb_define_method(mrb, mod, "class_variable_defined?", mrb_mod_cvar_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.16 */ mrb_define_method(mrb, mod, "class_variable_get", mrb_mod_cvar_get, MRB_ARGS_REQ(1)); /* 15.2.2.4.17 */ mrb_define_method(mrb, mod, "class_variable_set", mrb_mod_cvar_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.18 */ mrb_define_method(mrb, mod, "extend_object", mrb_mod_extend_object, MRB_ARGS_REQ(1)); /* 15.2.2.4.25 */ mrb_define_method(mrb, mod, "extended", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */ mrb_define_method(mrb, mod, "include", mrb_mod_include, MRB_ARGS_ANY()); /* 15.2.2.4.27 */ mrb_define_method(mrb, mod, "include?", mrb_mod_include_p, MRB_ARGS_REQ(1)); /* 15.2.2.4.28 */ mrb_define_method(mrb, mod, "append_features", mrb_mod_append_features, MRB_ARGS_REQ(1)); /* 15.2.2.4.10 */ mrb_define_method(mrb, mod, "class_eval", mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.15 */ mrb_define_method(mrb, mod, "included", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.29 */ mrb_define_method(mrb, mod, "included_modules", mrb_mod_included_modules, MRB_ARGS_NONE()); /* 15.2.2.4.30 */ mrb_define_method(mrb, mod, "instance_methods", mrb_mod_instance_methods, MRB_ARGS_ANY()); /* 15.2.2.4.33 */ mrb_define_method(mrb, mod, "method_defined?", mrb_mod_method_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.34 */ mrb_define_method(mrb, mod, "module_eval", mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.35 */ mrb_define_method(mrb, mod, "remove_class_variable", mrb_mod_remove_cvar, MRB_ARGS_REQ(1)); /* 15.2.2.4.39 */ mrb_define_method(mrb, mod, "remove_method", mrb_mod_remove_method, MRB_ARGS_ANY()); /* 15.2.2.4.41 */ mrb_define_method(mrb, mod, "to_s", mrb_mod_to_s, MRB_ARGS_NONE()); mrb_define_method(mrb, mod, "inspect", mrb_mod_to_s, MRB_ARGS_NONE()); mrb_define_method(mrb, mod, "alias_method", mrb_mod_alias, MRB_ARGS_ANY()); /* 15.2.2.4.8 */ mrb_define_method(mrb, mod, "ancestors", mrb_mod_ancestors, MRB_ARGS_NONE()); /* 15.2.2.4.9 */ mrb_define_method(mrb, mod, "undef_method", mrb_mod_undef, MRB_ARGS_ANY()); /* 15.2.2.4.41 */ mrb_define_method(mrb, mod, "const_defined?", mrb_mod_const_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.20 */ mrb_define_method(mrb, mod, "const_get", mrb_mod_const_get, MRB_ARGS_REQ(1)); /* 15.2.2.4.21 */ mrb_define_method(mrb, mod, "const_set", mrb_mod_const_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.23 */ mrb_define_method(mrb, mod, "constants", mrb_mod_constants, MRB_ARGS_NONE()); /* 15.2.2.4.24 */ mrb_define_method(mrb, mod, "remove_const", mrb_mod_remove_const, MRB_ARGS_REQ(1)); /* 15.2.2.4.40 */ mrb_define_method(mrb, mod, "define_method", mod_define_method, MRB_ARGS_REQ(1)); mrb_define_method(mrb, mod, "class_variables", mrb_mod_class_variables, MRB_ARGS_NONE()); /* 15.2.2.4.19 */ mrb_define_method(mrb, mod, "===", mrb_mod_eqq, MRB_ARGS_REQ(1)); mrb_define_class_method(mrb, mod, "constants", mrb_mod_s_constants, MRB_ARGS_ANY()); /* 15.2.2.3.1 */ mrb_undef_method(mrb, cls, "append_features"); mrb_undef_method(mrb, cls, "extend_object"); }
static mrb_value mrb_js_func_class_new(mrb_state *mrb, NPObject *func) { NPN_RetainObject(func); return mrb_obj_value(Data_Wrap_Struct(mrb, MRB_UD_JS_FUNC_CLASS(mrb), &mrb_js_func_type, func)); }
static mrb_value enc_new(mrb_state *mrb, mrb_encoding *encoding) { return mrb_obj_value(Data_Wrap_Struct(mrb, ENCODE_CLASS, &encoding_data_type, encoding)); }
static mrb_value mrb_curl_get(mrb_state *mrb, mrb_value self) { char error[CURL_ERROR_SIZE] = {0}; CURL* curl; CURLcode res = CURLE_OK; MEMFILE* mf; struct RClass* _class_curl; int ssl_verifypeer; struct curl_slist* headerlist = NULL; mrb_value str; struct RClass* _class_http; struct RClass* _class_http_parser; mrb_value parser; mrb_value args[1]; mrb_value url = mrb_nil_value(); mrb_value headers = mrb_nil_value(); mrb_value b = mrb_nil_value(); mrb_get_args(mrb, "S|H&", &url, &headers, &b); if (!mrb_nil_p(headers) && mrb_type(headers) != MRB_TT_HASH) { mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument"); } mf = memfopen(); curl = curl_easy_init(); _class_curl = mrb_class_get(mrb, "Curl"); ssl_verifypeer = mrb_fixnum(mrb_const_get(mrb, mrb_obj_value(_class_curl), mrb_intern_cstr(mrb, "SSL_VERIFYPEER"))); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, ssl_verifypeer); curl_easy_setopt(curl, CURLOPT_URL, RSTRING_PTR(url)); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error); curl_easy_setopt(curl, CURLOPT_WRITEDATA, mf); if (mrb_nil_p(b)) { curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memfwrite); } else { mf->mrb = mrb; mf->proc = b; mf->header = mrb_nil_value(); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memfwrite_callback); } curl_easy_setopt(curl, CURLOPT_HEADERDATA, mf); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, memfwrite); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 0); if (!mrb_nil_p(headers)) { mrb_value keys = mrb_hash_keys(mrb, headers); int i, l = RARRAY_LEN(keys); for (i = 0; i < l; i++) { mrb_value key = mrb_ary_entry(keys, i); mrb_value header = mrb_str_dup(mrb, key); mrb_str_cat2(mrb, header, ": "); mrb_str_concat(mrb, header, mrb_hash_get(mrb, headers, key)); headerlist = curl_slist_append(headerlist, RSTRING_PTR(header)); } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); } res = curl_easy_perform(curl); if (headerlist) curl_slist_free_all(headerlist); curl_easy_cleanup(curl); if (res != CURLE_OK) { mrb_raise(mrb, E_RUNTIME_ERROR, error); } if (!mrb_nil_p(b)) { return mrb_nil_value(); } str = mrb_str_new(mrb, mf->data, mf->size); memfclose(mf); _class_http = mrb_class_get(mrb, "HTTP"); _class_http_parser = mrb_class_ptr(mrb_const_get(mrb, mrb_obj_value(_class_http), mrb_intern_cstr(mrb, "Parser"))); parser = mrb_obj_new(mrb, _class_http_parser, 0, NULL); args[0] = str; return mrb_funcall_argv(mrb, parser, mrb_intern_cstr(mrb, "parse_response"), 1, args); }
static mrb_value sysctl_net_list(mrb_state *mrb, mrb_value self) { const char *ifname = NULL; struct ifaddrs *addrs, *curr; mrb_value r_ret; struct RClass *if_class = mrb_class_get(mrb, "NetworkAddress"); mrb_get_args(mrb, "|z", &ifname); if( getifaddrs(&addrs) == -1 ){ mrb_raisef(mrb, E_RUNTIME_ERROR, "getifaddrs: %S", mrb_str_new_cstr(mrb, strerror(errno))); goto ret; } if( ifname ){ r_ret = mrb_ary_new(mrb); } else { r_ret = mrb_hash_new(mrb); } curr = addrs; while( curr != NULL ){ char addr[INET6_ADDRSTRLEN]; char netmask[INET6_ADDRSTRLEN]; if( curr->ifa_netmask != NULL ){ mrb_value r_key, r_addr, r_list; // only return wanted infos if( !ifname || !strcmp(ifname, curr->ifa_name) ){ if( sockaddr_to_string(curr->ifa_addr, addr, sizeof(addr)) == -1) continue; if( sockaddr_to_string(curr->ifa_netmask, netmask, sizeof(netmask)) == -1) continue; r_key = mrb_str_new_cstr(mrb, curr->ifa_name); r_addr = mrb_funcall(mrb, mrb_obj_value(if_class), "new", 2, mrb_str_new_cstr(mrb, addr), mrb_str_new_cstr(mrb, netmask) ); if( ifname ){ mrb_ary_push(mrb, r_ret, r_addr); } else { // check if key exists r_list = mrb_hash_get(mrb, r_ret, r_key); if( mrb_nil_p(r_list) ){ r_list = mrb_ary_new(mrb); } mrb_ary_push(mrb, r_list, r_addr); mrb_hash_set(mrb, r_ret, r_key, r_list); } } } curr = curr->ifa_next; } ret: return r_ret; }
static mrb_value mrb_struct_members(mrb_state *mrb, mrb_value obj) { return mrb_struct_s_members_m(mrb, mrb_obj_value(mrb_obj_class(mrb, obj))); }
// Create the MRuby object for this virtual mrb_value Create_MRuby_Object(mrb_state* p_state) { // Someone needs to hold the event table, hence I decided // pKeyboard should do this. return mrb_obj_value(Data_Wrap_Struct(p_state, mrb_class_get(p_state, "InputClass"), &Scripting::rtTSC_Scriptable, this)); }
mrb_value regexp_pcre_match(mrb_state *mrb, mrb_value self) { struct mrb_matchdata *mrb_md; int rc; int ccount, matchlen; int *match; struct RClass *c; mrb_value md, str; mrb_int i, pos; pcre_extra extra; struct mrb_regexp_pcre *reg; reg = (struct mrb_regexp_pcre *)mrb_get_datatype(mrb, self, &mrb_regexp_type); if (!reg) return mrb_nil_value(); pos = 0; mrb_get_args(mrb, "S|i", &str, &pos); // XXX: RSTRING_LEN(str) >= pos ... rc = pcre_fullinfo(reg->re, NULL, PCRE_INFO_CAPTURECOUNT, &ccount); if (rc < 0) { /* fullinfo error */ return mrb_nil_value(); } matchlen = ccount + 1; match = mrb_malloc(mrb, sizeof(int) * matchlen * 3); extra.flags = PCRE_EXTRA_MATCH_LIMIT_RECURSION; extra.match_limit_recursion = 1000; rc = pcre_exec(reg->re, &extra, RSTRING_PTR(str), RSTRING_LEN(str), pos, 0, match, matchlen * 3); if (rc < 0) { mrb_free(mrb, match); return mrb_nil_value(); } /* XXX: need current scope */ mrb_obj_iv_set(mrb, (struct RObject *)mrb_class_real(RDATA(self)->c), mrb_intern_lit(mrb, "@last_match"), mrb_nil_value()); c = mrb_class_get(mrb, "MatchData"); md = mrb_funcall(mrb, mrb_obj_value(c), "new", 0); mrb_md = (struct mrb_matchdata *)mrb_get_datatype(mrb, md, &mrb_matchdata_type); mrb_md->ovector = match; mrb_md->length = matchlen; mrb_iv_set(mrb, md, mrb_intern_lit(mrb, "@regexp"), self); mrb_iv_set(mrb, md, mrb_intern_lit(mrb, "@string"), mrb_str_dup(mrb, str)); /* XXX: need current scope */ mrb_obj_iv_set(mrb, (struct RObject *)mrb_class_real(RDATA(self)->c), mrb_intern_lit(mrb, "@last_match"), md); mrb_gv_set(mrb, mrb_intern_lit(mrb, "$~"), md); mrb_gv_set(mrb, mrb_intern_lit(mrb, "$&"), mrb_funcall(mrb, md, "to_s", 0)); mrb_gv_set(mrb, mrb_intern_lit(mrb, "$`"), mrb_funcall(mrb, md, "pre_match", 0)); mrb_gv_set(mrb, mrb_intern_lit(mrb, "$'"), mrb_funcall(mrb, md, "post_match", 0)); for (i = 1; i < 10; i++) { char sym[8]; snprintf(sym, sizeof(sym), "$%d", i); mrb_gv_set(mrb, mrb_intern_cstr(mrb, sym), mrb_funcall(mrb, md, "[]", 1, mrb_fixnum_value(i))); } return md; }
int main(int argc, char **argv) { mrb_state *mrb = mrb_open(); int n = -1; int i; struct _args args; mrb_value ARGV; if (mrb == NULL) { fputs("Invalid mrb_state, exiting mruby\n", stderr); return EXIT_FAILURE; } n = parse_args(mrb, argc, argv, &args); if (n == EXIT_FAILURE || (args.cmdline == NULL && args.rfp == NULL)) { cleanup(mrb, &args); usage(argv[0]); return n; } ARGV = mrb_ary_new_capa(mrb, args.argc); for (i = 0; i < args.argc; i++) { mrb_ary_push(mrb, ARGV, mrb_str_new(mrb, args.argv[i], strlen(args.argv[i]))); } mrb_define_global_const(mrb, "ARGV", ARGV); if (args.mrbfile) { n = mrb_read_irep_file(mrb, args.rfp); if (n < 0) { fprintf(stderr, "failed to load mrb file: %s\n", args.cmdline); } else if (!args.check_syntax) { mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb)); n = 0; if (mrb->exc) { showcallinfo(mrb); p(mrb, mrb_obj_value(mrb->exc)); n = -1; } } } else { mrbc_context *c = mrbc_context_new(mrb); mrb_sym zero_sym = mrb_intern2(mrb, "$0", 2); mrb_value v; if (args.verbose) c->dump_result = 1; if (args.check_syntax) c->no_exec = 1; if (args.rfp) { char *cmdline; cmdline = args.cmdline ? args.cmdline : "-"; mrbc_filename(mrb, c, cmdline); mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline)); v = mrb_load_file_cxt(mrb, args.rfp, c); } else { mrbc_filename(mrb, c, "-e"); mrb_gv_set(mrb, zero_sym, mrb_str_new(mrb, "-e", 2)); v = mrb_load_string_cxt(mrb, args.cmdline, c); } mrbc_context_free(mrb, c); if (mrb->exc) { if (!mrb_undef_p(v)) { showcallinfo(mrb); p(mrb, mrb_obj_value(mrb->exc)); } n = -1; } else if (args.check_syntax) { printf("Syntax OK\n"); } } cleanup(mrb, &args); return n == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }
static mrb_value mrb_time_wrap(mrb_state *mrb, struct RClass *tc, struct mrb_time *tm) { return mrb_obj_value(Data_Wrap_Struct(mrb, tc, &mrb_time_type, tm)); }
void mrb_define_const(mrb_state *mrb, struct RClass *mod, const char *name, mrb_value v) { mrb_iv_set(mrb, mrb_obj_value(mod), mrb_intern(mrb, name), v); }
static void undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a) { mrb_value m; if (!mrb_obj_respond_to(c, a)) { mrb_name_error(mrb, a, "undefined method '%S' for class '%S'", mrb_sym2str(mrb, a), mrb_obj_value(c)); } else { MRB_SET_VALUE(m, MRB_TT_PROC, value.p, 0); mrb_define_method_vm(mrb, c, a, m); } }
int main(int argc, char **argv) { char ruby_code[1024] = { 0 }; char last_code_line[1024] = { 0 }; #ifndef ENABLE_READLINE int last_char; int char_index; #else char *home = NULL; #endif mrbc_context *cxt; struct mrb_parser_state *parser; mrb_state *mrb; mrb_value result; struct _args args; int n; mrb_bool code_block_open = FALSE; int ai; mrb_bool first_command = TRUE; unsigned int nregs; /* new interpreter instance */ mrb = mrb_open(); if (mrb == NULL) { fputs("Invalid mrb interpreter, exiting mirb\n", stderr); return EXIT_FAILURE; } mrb_define_global_const(mrb, "ARGV", mrb_ary_new_capa(mrb, 0)); n = parse_args(mrb, argc, argv, &args); if (n == EXIT_FAILURE) { cleanup(mrb, &args); usage(argv[0]); return n; } print_hint(); cxt = mrbc_context_new(mrb); cxt->capture_errors = 1; cxt->lineno = 1; mrbc_filename(mrb, cxt, "(mirb)"); if (args.verbose) cxt->dump_result = 1; ai = mrb_gc_arena_save(mrb); #ifdef ENABLE_READLINE using_history(); home = getenv("HOME"); #ifdef _WIN32 if (!home) home = getenv("USERPROFILE"); #endif if (home) { strcpy(history_path, home); strcat(history_path, "/"); strcat(history_path, history_file_name); read_history(history_path); } #endif while (TRUE) { #ifndef ENABLE_READLINE print_cmdline(code_block_open); char_index = 0; while ((last_char = getchar()) != '\n') { if (last_char == EOF) break; last_code_line[char_index++] = last_char; } if (last_char == EOF) { fputs("\n", stdout); break; } last_code_line[char_index] = '\0'; #else char* line = readline(code_block_open ? "* " : "> "); if (line == NULL) { printf("\n"); break; } strncpy(last_code_line, line, sizeof(last_code_line)-1); add_history(line); free(line); #endif if ((strcmp(last_code_line, "quit") == 0) || (strcmp(last_code_line, "exit") == 0)) { if (!code_block_open) { break; } else{ /* count the quit/exit commands as strings if in a quote block */ strcat(ruby_code, "\n"); strcat(ruby_code, last_code_line); } } else { if (code_block_open) { strcat(ruby_code, "\n"); strcat(ruby_code, last_code_line); } else { strcpy(ruby_code, last_code_line); } } /* parse code */ parser = mrb_parser_new(mrb); parser->s = ruby_code; parser->send = ruby_code + strlen(ruby_code); parser->lineno = cxt->lineno; mrb_parser_parse(parser, cxt); code_block_open = is_code_block_open(parser); if (code_block_open) { /* no evaluation of code */ } else { if (0 < parser->nerr) { /* syntax error */ printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message); } else { /* generate bytecode */ struct RProc *proc = mrb_generate_code(mrb, parser); if (args.verbose) { mrb_codedump_all(mrb, proc); } /* pass a proc for evaulation */ nregs = first_command ? 0: proc->body.irep->nregs; /* evaluate the bytecode */ result = mrb_context_run(mrb, proc, mrb_top_self(mrb), nregs); /* did an exception occur? */ if (mrb->exc) { p(mrb, mrb_obj_value(mrb->exc), 0); mrb->exc = 0; } else { /* no */ if (!mrb_respond_to(mrb, result, mrb_intern_lit(mrb, "inspect"))){ result = mrb_any_to_s(mrb,result); } p(mrb, result, 1); } } ruby_code[0] = '\0'; last_code_line[0] = '\0'; mrb_gc_arena_restore(mrb, ai); } mrb_parser_free(parser); cxt->lineno++; first_command = FALSE; } mrbc_context_free(mrb, cxt); mrb_close(mrb); #ifdef ENABLE_READLINE write_history(history_path); #endif return 0; }
static mrb_value mrb_js_obj_class_new(mrb_state *mrb, NPObject *obj) { NPN_RetainObject(obj); return mrb_obj_value(Data_Wrap_Struct(mrb, MRB_UD_JS_OBJ_CLASS(mrb), &mrb_js_obj_type, obj)); }
static mrb_value _http_parser_parse(mrb_state *mrb, mrb_value self, int type) { mrb_value arg_data = mrb_nil_value(); mrb_value value_context; mrb_http_parser_context* context; mrb_value b = mrb_nil_value(); struct RClass* _class_http; struct RClass* clazz; char* data; size_t len; char* eol; size_t done; value_context = mrb_iv_get(mrb, self, mrb_intern(mrb, "context")); Data_Get_Struct(mrb, value_context, &http_parser_context_type, context); if (!context) { mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument"); } mrb_get_args(mrb, "|&o", &b, &arg_data); if (mrb_nil_p(arg_data)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument"); } context->parser.data = context; _class_http = mrb_class_get(mrb, "HTTP"); if (type == HTTP_REQUEST) { clazz = mrb_class_ptr(mrb_const_get(mrb, mrb_obj_value(_class_http), mrb_intern(mrb, "Request"))); context->instance = mrb_class_new_instance(mrb, 0, NULL, clazz); } else { clazz = mrb_class_ptr(mrb_const_get(mrb, mrb_obj_value(_class_http), mrb_intern(mrb, "Response"))); context->instance = mrb_class_new_instance(mrb, 0, NULL, clazz); } context->was_header_value = TRUE; http_parser_init(&context->parser, type); context->type = type; context->settings.on_url = parser_settings_on_url; context->settings.on_header_field = parser_settings_on_header_field; context->settings.on_header_value = parser_settings_on_header_value; context->settings.on_headers_complete = parser_settings_on_headers_complete; context->settings.on_body = parser_settings_on_body; context->settings.on_message_complete = parser_settings_on_message_complete; data = RSTRING_PTR(arg_data); len = RSTRING_LEN(arg_data); eol = strpbrk(data, "\r\n"); if (eol) { } RETRY: if (len > 10 && (!strncmp(data+9, "200 Connection established\r\n", 28) || !strncmp(data+9, "100 Continue\r\n", 14) || *(data+9) == '3')) { char* next = strstr(data, "\r\n\r\n"); if (next) { len -= (next + 4 - data); data = next + 4; goto RETRY; } } done = http_parser_execute(&context->parser, &context->settings, data, len); if (done < len) { OBJECT_SET(mrb, context->instance, "body", mrb_str_new(mrb, data + done, len - done)); } if (!mrb_nil_p(b)) { mrb_value args[1]; args[0] = context->instance; mrb_yield_argv(mrb, b, 1, args); return mrb_nil_value(); } return context->instance; }
int main(int argc, char **argv) { mrb_state *mrb = mrb_open(); int n = -1; struct _args args; mrb_value v; mrdb_state *mrdb; mrdb_state *mrdb_backup; mrb_debug_context* dbg_backup; debug_command *cmd; l_restart: if (mrb == NULL) { fputs("Invalid mrb_state, exiting mruby\n", stderr); return EXIT_FAILURE; } /* parse command parameters */ n = parse_args(mrb, argc, argv, &args); if (n == EXIT_FAILURE || args.rfp == NULL) { cleanup(mrb, &args); usage(argv[0]); return n; } /* initialize debugger information */ mrdb = mrdb_state_get(mrb); mrb_assert(mrdb && mrdb->dbg); mrdb->srcpath = args.srcpath; if(mrdb->dbg->xm == DBG_QUIT) { mrdb->dbg->xphase = DBG_PHASE_RESTART; } else { mrdb->dbg->xphase = DBG_PHASE_BEFORE_RUN; } mrdb->dbg->xm = DBG_INIT; mrdb->dbg->ccnt = 1; /* setup hook functions */ mrb->code_fetch_hook = mrb_code_fetch_hook; mrdb->dbg->break_hook = mrb_debug_break_hook; if (args.mrbfile) { /* .mrb */ v = mrb_load_irep_file(mrb, args.rfp); } else { /* .rb */ mrbc_context *cc = mrbc_context_new(mrb); mrbc_filename(mrb, cc, args.fname); v = mrb_load_file_cxt(mrb, args.rfp, cc); mrbc_context_free(mrb, cc); } if (mrdb->dbg->xm == DBG_QUIT && !mrb_undef_p(v) && mrb->exc) { const char *classname = mrb_obj_classname(mrb, mrb_obj_value(mrb->exc)); if (!strcmp(classname, "DebuggerExit")) { cleanup(mrb, &args); return 0; } if (!strcmp(classname, "DebuggerRestart")) { mrdb_backup = mrdb_state_get(mrb); dbg_backup = mrb_debug_context_get(mrb); mrdb_state_set(NULL); mrb_debug_context_set(NULL); cleanup(mrb, &args); mrb = mrb_open(); mrdb_state_set(mrdb_backup); mrb_debug_context_set(dbg_backup); goto l_restart; } } puts("mruby application exited."); mrdb->dbg->xphase = DBG_PHASE_AFTER_RUN; if (!mrb_undef_p(v)) { if (mrb->exc) { mrb_print_error(mrb); } else { printf(" => "); mrb_p(mrb, v); } } mrdb->dbg->prvfile = "-"; mrdb->dbg->prvline = 0; while (1) { cmd = get_and_parse_command(mrb, mrdb); mrb_assert(cmd); if (cmd->id == DBGCMD_QUIT) { break; } if( cmd->func(mrb, mrdb) == DBGST_RESTART ) goto l_restart; } cleanup(mrb, &args); return 0; }
int main(void) { char last_char, ruby_code[1024], last_code_line[1024]; int char_index; struct mrb_parser_state *parser; mrb_state *mrb_interpreter; mrb_value mrb_return_value; int byte_code; int code_block_open = FALSE; print_hint(); /* new interpreter instance */ mrb_interpreter = mrb_open(); /* new parser instance */ parser = mrb_parser_new(mrb_interpreter); memset(ruby_code, 0, sizeof(*ruby_code)); memset(last_code_line, 0, sizeof(*last_code_line)); while (TRUE) { print_cmdline(code_block_open); char_index = 0; while ((last_char = getchar()) != '\n') { if (last_char == EOF) break; last_code_line[char_index++] = last_char; } if (last_char == EOF) { printf("\n"); break; } last_code_line[char_index] = '\0'; if ((strcmp(last_code_line, "quit") == 0) || (strcmp(last_code_line, "exit") == 0)) { if (code_block_open) { /* cancel the current block and reset */ code_block_open = FALSE; memset(ruby_code, 0, sizeof(*ruby_code)); memset(last_code_line, 0, sizeof(*last_code_line)); continue; } else { /* quit the program */ break; } } else { if (code_block_open) { strcat(ruby_code, "\n"); strcat(ruby_code, last_code_line); } else { memset(ruby_code, 0, sizeof(*ruby_code)); strcat(ruby_code, last_code_line); } /* parse code */ parser->s = ruby_code; parser->send = ruby_code + strlen(ruby_code); parser->capture_errors = 1; parser->lineno = 1; mrb_parser_parse(parser); code_block_open = is_code_block_open(parser); if (code_block_open) { /* no evaluation of code */ } else { if (0 < parser->nerr) { /* syntax error */ printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message); } else { /* generate bytecode */ byte_code = mrb_generate_code(mrb_interpreter, parser->tree); /* evaluate the bytecode */ mrb_return_value = mrb_run(mrb_interpreter, /* pass a proc for evaulation */ mrb_proc_new(mrb_interpreter, mrb_interpreter->irep[byte_code]), mrb_top_self(mrb_interpreter)); /* did an exception occur? */ if (mrb_interpreter->exc) { mrb_p(mrb_interpreter, mrb_obj_value(mrb_interpreter->exc)); mrb_interpreter->exc = 0; } else { /* no */ printf(" => "); mrb_p(mrb_interpreter, mrb_return_value); } } memset(ruby_code, 0, sizeof(*ruby_code)); memset(ruby_code, 0, sizeof(*last_code_line)); } } } mrb_close(mrb_interpreter); return 0; }
int main(int argc, char **argv) { mrb_state *mrb = mrb_open(); int n = -1; int i; struct _args args; mrb_value ARGV; if (mrb == NULL) { fprintf(stderr, "Invalid mrb_state, exiting mruby"); return EXIT_FAILURE; } n = parse_args(mrb, argc, argv, &args); if (n < 0 || (args.cmdline == NULL && args.rfp == NULL)) { cleanup(mrb, &args); usage(argv[0]); return n; } ARGV = mrb_ary_new(mrb); for (i = 0; i < args.argc; i++) { mrb_ary_push(mrb, ARGV, mrb_str_new(mrb, args.argv[i], strlen(args.argv[i]))); } mrb_define_global_const(mrb, "ARGV", ARGV); if (args.mrbfile) { n = mrb_load_irep(mrb, args.rfp); if (n >= 0) { if (!args.check_syntax) { mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb)); if (mrb->exc) { p(mrb, mrb_obj_value(mrb->exc)); } } } } else { mrbc_context *c = mrbc_context_new(mrb); mrb_value v; if (args.verbose) c->dump_result = 1; if (args.check_syntax) c->no_exec = 1; if (args.cmdline) { mrbc_filename(mrb, c, "-e"); v = mrb_load_string_cxt(mrb, (char*)args.cmdline, c); } else { mrbc_filename(mrb, c, args.argv[0]); v = mrb_load_file_cxt(mrb, args.rfp, c); } mrbc_context_free(mrb, c); if (mrb->exc) { if (!mrb_undef_p(v)) { p(mrb, mrb_obj_value(mrb->exc)); } } else if (args.check_syntax) { printf("Syntax OK\n"); } } cleanup(mrb, &args); return n > 0 ? 0 : 1; }
mrb_value mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) { /* assert(mrb_proc_cfunc_p(proc)) */ mrb_irep *irep = proc->body.irep; mrb_code *pc = irep->iseq; mrb_value *pool = irep->pool; mrb_sym *syms = irep->syms; mrb_value *regs = NULL; mrb_code i; int ai = mrb->arena_idx; jmp_buf *prev_jmp = (jmp_buf *)mrb->jmp; jmp_buf c_jmp; #ifdef DIRECT_THREADED static void *optable[] = { &&L_OP_NOP, &&L_OP_MOVE, &&L_OP_LOADL, &&L_OP_LOADI, &&L_OP_LOADSYM, &&L_OP_LOADNIL, &&L_OP_LOADSELF, &&L_OP_LOADT, &&L_OP_LOADF, &&L_OP_GETGLOBAL, &&L_OP_SETGLOBAL, &&L_OP_GETSPECIAL, &&L_OP_SETSPECIAL, &&L_OP_GETIV, &&L_OP_SETIV, &&L_OP_GETCV, &&L_OP_SETCV, &&L_OP_GETCONST, &&L_OP_SETCONST, &&L_OP_GETMCNST, &&L_OP_SETMCNST, &&L_OP_GETUPVAR, &&L_OP_SETUPVAR, &&L_OP_JMP, &&L_OP_JMPIF, &&L_OP_JMPNOT, &&L_OP_ONERR, &&L_OP_RESCUE, &&L_OP_POPERR, &&L_OP_RAISE, &&L_OP_EPUSH, &&L_OP_EPOP, &&L_OP_SEND, &&L_OP_SENDB, &&L_OP_FSEND, &&L_OP_CALL, &&L_OP_SUPER, &&L_OP_ARGARY, &&L_OP_ENTER, &&L_OP_KARG, &&L_OP_KDICT, &&L_OP_RETURN, &&L_OP_TAILCALL, &&L_OP_BLKPUSH, &&L_OP_ADD, &&L_OP_ADDI, &&L_OP_SUB, &&L_OP_SUBI, &&L_OP_MUL, &&L_OP_DIV, &&L_OP_EQ, &&L_OP_LT, &&L_OP_LE, &&L_OP_GT, &&L_OP_GE, &&L_OP_ARRAY, &&L_OP_ARYCAT, &&L_OP_ARYPUSH, &&L_OP_AREF, &&L_OP_ASET, &&L_OP_APOST, &&L_OP_STRING, &&L_OP_STRCAT, &&L_OP_HASH, &&L_OP_LAMBDA, &&L_OP_RANGE, &&L_OP_OCLASS, &&L_OP_CLASS, &&L_OP_MODULE, &&L_OP_EXEC, &&L_OP_METHOD, &&L_OP_SCLASS, &&L_OP_TCLASS, &&L_OP_DEBUG, &&L_OP_STOP, &&L_OP_ERR, }; #endif if (setjmp(c_jmp) == 0) { mrb->jmp = &c_jmp; } else { goto L_RAISE; } if (!mrb->stack) { stack_init(mrb); } mrb->ci->proc = proc; mrb->ci->nregs = irep->nregs + 2; regs = mrb->stack; regs[0] = self; INIT_DISPATCH { CASE(OP_NOP) { /* do nothing */ NEXT; } CASE(OP_MOVE) { /* A B R(A) := R(B) */ regs[GETARG_A(i)] = regs[GETARG_B(i)]; NEXT; } CASE(OP_LOADL) { /* A Bx R(A) := Pool(Bx) */ regs[GETARG_A(i)] = pool[GETARG_Bx(i)]; NEXT; } CASE(OP_LOADI) { /* A Bx R(A) := sBx */ SET_INT_VALUE(regs[GETARG_A(i)], GETARG_sBx(i)); NEXT; } CASE(OP_LOADSYM) { /* A B R(A) := Sym(B) */ SET_SYM_VALUE(regs[GETARG_A(i)], syms[GETARG_Bx(i)]); NEXT; } CASE(OP_LOADSELF) { /* A R(A) := self */ regs[GETARG_A(i)] = regs[0]; NEXT; } CASE(OP_LOADT) { /* A R(A) := true */ SET_TRUE_VALUE(regs[GETARG_A(i)]); NEXT; } CASE(OP_LOADF) { /* A R(A) := false */ SET_FALSE_VALUE(regs[GETARG_A(i)]); NEXT; } CASE(OP_GETGLOBAL) { /* A B R(A) := getglobal(Sym(B)) */ regs[GETARG_A(i)] = mrb_gv_get(mrb, syms[GETARG_Bx(i)]); NEXT; } CASE(OP_SETGLOBAL) { /* setglobal(Sym(b), R(A)) */ mrb_gv_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]); NEXT; } CASE(OP_GETSPECIAL) { /* A Bx R(A) := Special[Bx] */ regs[GETARG_A(i)] = mrb_vm_special_get(mrb, GETARG_Bx(i)); NEXT; } CASE(OP_SETSPECIAL) { /* A Bx Special[Bx] := R(A) */ mrb_vm_special_set(mrb, GETARG_Bx(i), regs[GETARG_A(i)]); NEXT; } CASE(OP_GETIV) { /* A Bx R(A) := ivget(Bx) */ regs[GETARG_A(i)] = mrb_vm_iv_get(mrb, syms[GETARG_Bx(i)]); NEXT; } CASE(OP_SETIV) { /* ivset(Sym(B),R(A)) */ mrb_vm_iv_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]); NEXT; } CASE(OP_GETCV) { /* A B R(A) := ivget(Sym(B)) */ regs[GETARG_A(i)] = mrb_vm_cv_get(mrb, syms[GETARG_Bx(i)]); NEXT; } CASE(OP_SETCV) { /* ivset(Sym(B),R(A)) */ mrb_vm_cv_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]); NEXT; } CASE(OP_GETCONST) { /* A B R(A) := constget(Sym(B)) */ regs[GETARG_A(i)] = mrb_vm_const_get(mrb, syms[GETARG_Bx(i)]); NEXT; } CASE(OP_SETCONST) { /* A B constset(Sym(B),R(A)) */ mrb_vm_const_set(mrb, syms[GETARG_Bx(i)], regs[GETARG_A(i)]); NEXT; } CASE(OP_GETMCNST) { /* A B C R(A) := R(C)::Sym(B) */ int a = GETARG_A(i); regs[a] = mrb_const_get(mrb, regs[a], syms[GETARG_Bx(i)]); NEXT; } CASE(OP_SETMCNST) { /* A B C R(A+1)::Sym(B) := R(A) */ int a = GETARG_A(i); mrb_const_set(mrb, regs[a+1], syms[GETARG_Bx(i)], regs[a]); NEXT; } CASE(OP_GETUPVAR) { /* A B C R(A) := uvget(B,C) */ regs[GETARG_A(i)] = uvget(mrb, GETARG_C(i), GETARG_B(i)); NEXT; } CASE(OP_SETUPVAR) { /* A B C uvset(B,C,R(A)) */ uvset(mrb, GETARG_C(i), GETARG_B(i), regs[GETARG_A(i)]); NEXT; } CASE(OP_JMP) { /* sBx pc+=sBx */ pc += GETARG_sBx(i); JUMP; } CASE(OP_JMPIF) { /* A sBx if R(A) pc+=sBx */ if (mrb_test(regs[GETARG_A(i)])) { pc += GETARG_sBx(i); JUMP; } NEXT; } CASE(OP_JMPNOT) { /* A sBx if R(A) pc+=sBx */ if (!mrb_test(regs[GETARG_A(i)])) { pc += GETARG_sBx(i); JUMP; } NEXT; } CASE(OP_ONERR) { /* sBx pc+=sBx on exception */ if (mrb->rsize <= mrb->ci->ridx) { if (mrb->rsize == 0) mrb->rsize = 16; else mrb->rsize *= 2; mrb->rescue = (mrb_code **)mrb_realloc(mrb, mrb->rescue, sizeof(mrb_code*) * mrb->rsize); } mrb->rescue[mrb->ci->ridx++] = pc + GETARG_sBx(i); NEXT; } CASE(OP_RESCUE) { /* A R(A) := exc; clear(exc) */ SET_OBJ_VALUE(regs[GETARG_A(i)], mrb->exc); mrb->exc = 0; NEXT; } CASE(OP_POPERR) { int a = GETARG_A(i); while (a--) { mrb->ci->ridx--; } NEXT; } CASE(OP_RAISE) { /* A raise(R(A)) */ mrb->exc = (struct RObject*)mrb_object(regs[GETARG_A(i)]); goto L_RAISE; } CASE(OP_EPUSH) { /* Bx ensure_push(SEQ[Bx]) */ struct RProc *p; p = mrb_closure_new(mrb, mrb->irep[irep->idx+GETARG_Bx(i)]); /* push ensure_stack */ if (mrb->esize <= mrb->ci->eidx) { if (mrb->esize == 0) mrb->esize = 16; else mrb->esize *= 2; mrb->ensure = (struct RProc **)mrb_realloc(mrb, mrb->ensure, sizeof(struct RProc*) * mrb->esize); } mrb->ensure[mrb->ci->eidx++] = p; mrb->arena_idx = ai; NEXT; } CASE(OP_EPOP) { /* A A.times{ensure_pop().call} */ int n; int a = GETARG_A(i); for (n=0; n<a; n++) { ecall(mrb, --mrb->ci->eidx); } mrb->arena_idx = ai; NEXT; } CASE(OP_LOADNIL) { /* A B R(A) := nil */ int a = GETARG_A(i); SET_NIL_VALUE(regs[a]); NEXT; } CASE(OP_SENDB) { /* fall through */ }; L_SEND: CASE(OP_SEND) { /* A B C R(A) := call(R(A),Sym(B),R(A+1),... ,R(A+C-1)) */ int a = GETARG_A(i); int n = GETARG_C(i); struct RProc *m; struct RClass *c; mrb_callinfo *ci; mrb_value recv, result; mrb_sym mid = syms[GETARG_B(i)]; recv = regs[a]; if (GET_OPCODE(i) != OP_SENDB) { if (n == CALL_MAXARGS) { SET_NIL_VALUE(regs[a+2]); } else { SET_NIL_VALUE(regs[a+n+1]); } } c = mrb_class(mrb, recv); m = mrb_method_search_vm(mrb, &c, mid); if (!m) { mrb_value sym = mrb_symbol_value(mid); mid = mrb_intern(mrb, "method_missing"); m = mrb_method_search_vm(mrb, &c, mid); if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], sym); } else { memmove(regs+a+2, regs+a+1, sizeof(mrb_value)*(n+1)); regs[a+1] = sym; n++; } } /* push callinfo */ ci = cipush(mrb); ci->mid = mid; ci->proc = m; ci->stackidx = mrb->stack - mrb->stbase; ci->argc = n; if (ci->argc == CALL_MAXARGS) ci->argc = -1; ci->target_class = c; ci->pc = pc + 1; ci->acc = a; /* prepare stack */ mrb->stack += a; if (MRB_PROC_CFUNC_P(m)) { if (n == CALL_MAXARGS) { ci->nregs = 3; } else { ci->nregs = n + 2; } result = m->body.func(mrb, recv); mrb->stack[0] = result; mrb->arena_idx = ai; if (mrb->exc) goto L_RAISE; /* pop stackpos */ regs = mrb->stack = mrb->stbase + mrb->ci->stackidx; cipop(mrb); NEXT; } else { /* setup environment for calling method */ proc = mrb->ci->proc = m; irep = m->body.irep; pool = irep->pool; syms = irep->syms; ci->nregs = irep->nregs; if (ci->argc < 0) { stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3); } else { stack_extend(mrb, irep->nregs, ci->argc+2); } regs = mrb->stack; pc = irep->iseq; JUMP; } } CASE(OP_FSEND) { /* A B C R(A) := fcall(R(A),Sym(B),R(A+1),... ,R(A+C)) */ NEXT; } CASE(OP_CALL) { /* A R(A) := self.call(frame.argc, frame.argv) */ mrb_callinfo *ci; mrb_value recv = mrb->stack[0]; struct RProc *m = mrb_proc_ptr(recv); /* replace callinfo */ ci = mrb->ci; ci->target_class = m->target_class; ci->proc = m; if (m->env) { if (m->env->mid) { ci->mid = m->env->mid; } if (!m->env->stack) { m->env->stack = mrb->stack; } } /* prepare stack */ if (MRB_PROC_CFUNC_P(m)) { recv = m->body.func(mrb, recv); mrb->arena_idx = ai; if (mrb->exc) goto L_RAISE; /* pop stackpos */ ci = mrb->ci; regs = mrb->stack = mrb->stbase + ci->stackidx; regs[ci->acc] = recv; pc = ci->pc; cipop(mrb); irep = mrb->ci->proc->body.irep; pool = irep->pool; syms = irep->syms; JUMP; } else { /* setup environment for calling method */ proc = m; irep = m->body.irep; if (!irep) { mrb->stack[0] = mrb_nil_value(); goto L_RETURN; } pool = irep->pool; syms = irep->syms; ci->nregs = irep->nregs; if (ci->argc < 0) { stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3); } else { stack_extend(mrb, irep->nregs, ci->argc+2); } regs = mrb->stack; regs[0] = m->env->stack[0]; pc = m->body.irep->iseq; JUMP; } } CASE(OP_SUPER) { /* A B C R(A) := super(R(A+1),... ,R(A+C-1)) */ mrb_value recv; mrb_callinfo *ci = mrb->ci; struct RProc *m; struct RClass *c; mrb_sym mid = ci->mid; int a = GETARG_A(i); int n = GETARG_C(i); recv = regs[0]; c = mrb->ci->target_class->super; m = mrb_method_search_vm(mrb, &c, mid); if (!m) { mid = mrb_intern(mrb, "method_missing"); m = mrb_method_search_vm(mrb, &c, mid); if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid)); } else { memmove(regs+a+2, regs+a+1, sizeof(mrb_value)*(n+1)); SET_SYM_VALUE(regs[a+1], ci->mid); n++; } } /* push callinfo */ ci = cipush(mrb); ci->mid = mid; ci->proc = m; ci->stackidx = mrb->stack - mrb->stbase; ci->argc = n; if (ci->argc == CALL_MAXARGS) ci->argc = -1; ci->target_class = m->target_class; ci->pc = pc + 1; /* prepare stack */ mrb->stack += a; mrb->stack[0] = recv; if (MRB_PROC_CFUNC_P(m)) { mrb->stack[0] = m->body.func(mrb, recv); mrb->arena_idx = ai; if (mrb->exc) goto L_RAISE; /* pop stackpos */ regs = mrb->stack = mrb->stbase + mrb->ci->stackidx; cipop(mrb); NEXT; } else { /* fill callinfo */ ci->acc = a; /* setup environment for calling method */ ci->proc = m; irep = m->body.irep; pool = irep->pool; syms = irep->syms; ci->nregs = irep->nregs; if (ci->argc < 0) { stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3); } else { stack_extend(mrb, irep->nregs, ci->argc+2); } regs = mrb->stack; pc = irep->iseq; JUMP; } } CASE(OP_ARGARY) { /* A Bx R(A) := argument array (16=6:1:5:4) */ int a = GETARG_A(i); int bx = GETARG_Bx(i); int m1 = (bx>>10)&0x3f; int r = (bx>>9)&0x1; int m2 = (bx>>4)&0x1f; int lv = (bx>>0)&0xf; mrb_value *stack; if (lv == 0) stack = regs + 1; else { struct REnv *e = uvenv(mrb, lv-1); if (!e) { mrb_value exc; static const char m[] = "super called outside of method"; exc = mrb_exc_new(mrb, E_NOMETHOD_ERROR, m, sizeof(m) - 1); mrb->exc = (struct RObject*)mrb_object(exc); goto L_RAISE; } stack = e->stack + 1; } if (r == 0) { regs[a] = mrb_ary_new_elts(mrb, m1+m2, stack); } else { mrb_value *pp = NULL; struct RArray *rest; int len = 0; if (mrb_type(stack[m1]) == MRB_TT_ARRAY) { struct RArray *ary = mrb_ary_ptr(stack[m1]); pp = ary->ptr; len = ary->len; } regs[a] = mrb_ary_new_capa(mrb, m1+len+m2); rest = mrb_ary_ptr(regs[a]); stack_copy(rest->ptr, stack, m1); if (len > 0) { stack_copy(rest->ptr+m1, pp, len); } if (m2 > 0) { stack_copy(rest->ptr+m1+len, stack+m1+1, m2); } rest->len = m1+len+m2; } regs[a+1] = stack[m1+r+m2]; mrb->arena_idx = ai; NEXT; } CASE(OP_ENTER) { /* Ax arg setup according to flags (24=5:5:1:5:5:1:1) */ /* number of optional arguments times OP_JMP should follow */ int ax = GETARG_Ax(i); int m1 = (ax>>18)&0x1f; int o = (ax>>13)&0x1f; int r = (ax>>12)&0x1; int m2 = (ax>>7)&0x1f; /* unused int k = (ax>>2)&0x1f; int kd = (ax>>1)&0x1; int b = (ax>>0)& 0x1; */ int argc = mrb->ci->argc; mrb_value *argv = regs+1; mrb_value *argv0 = argv; int len = m1 + o + r + m2; mrb_value *blk = &argv[argc < 0 ? 1 : argc]; if (argc < 0) { struct RArray *ary = mrb_ary_ptr(regs[1]); argv = ary->ptr; argc = ary->len; mrb_gc_protect(mrb, regs[1]); } if (mrb->ci->proc && MRB_PROC_STRICT_P(mrb->ci->proc)) { if (argc >= 0) { if (argc < m1 + m2 || (r == 0 && argc > len)) { argnum_error(mrb, m1+m2); goto L_RAISE; } } } else if (len > 1 && argc == 1 && mrb_type(argv[0]) == MRB_TT_ARRAY) { argc = mrb_ary_ptr(argv[0])->len; argv = mrb_ary_ptr(argv[0])->ptr; } mrb->ci->argc = len; if (argc < len) { regs[len+1] = *blk; /* move block */ if (argv0 != argv) { memmove(®s[1], argv, sizeof(mrb_value)*(argc-m2)); /* m1 + o */ } if (m2) { memmove(®s[len-m2+1], &argv[argc-m2], sizeof(mrb_value)*m2); /* m2 */ } if (r) { /* r */ regs[m1+o+1] = mrb_ary_new_capa(mrb, 0); } if (o == 0) pc++; else pc += argc - m1 - m2 + 1; } else { if (argv0 != argv) { memmove(®s[1], argv, sizeof(mrb_value)*(m1+o)); /* m1 + o */ } if (r) { /* r */ regs[m1+o+1] = mrb_ary_new_elts(mrb, argc-m1-o-m2, argv+m1+o); } if (m2) { memmove(®s[m1+o+r+1], &argv[argc-m2], sizeof(mrb_value)*m2); } regs[len+1] = *blk; /* move block */ pc += o + 1; } JUMP; } CASE(OP_KARG) { /* A B C R(A) := kdict[Sym(B)]; if C kdict.rm(Sym(B)) */ /* if C == 2; raise unless kdict.empty? */ /* OP_JMP should follow to skip init code */ NEXT; } CASE(OP_KDICT) { /* A C R(A) := kdict */ NEXT; } CASE(OP_RETURN) { /* A return R(A) */ L_RETURN: if (mrb->exc) { mrb_callinfo *ci; int eidx; L_RAISE: ci = mrb->ci; eidx = mrb->ci->eidx; if (ci == mrb->cibase) goto L_STOP; while (ci[0].ridx == ci[-1].ridx) { cipop(mrb); ci = mrb->ci; if (ci[1].acc < 0 && prev_jmp) { mrb->jmp = prev_jmp; longjmp(*(jmp_buf*)mrb->jmp, 1); } while (eidx > mrb->ci->eidx) { ecall(mrb, --eidx); } if (ci == mrb->cibase) { if (ci->ridx == 0) { regs = mrb->stack = mrb->stbase; goto L_STOP; } break; } } irep = ci->proc->body.irep; pool = irep->pool; syms = irep->syms; regs = mrb->stack = mrb->stbase + ci[1].stackidx; pc = mrb->rescue[--ci->ridx]; } else { mrb_callinfo *ci = mrb->ci; int acc, eidx = mrb->ci->eidx; mrb_value v = regs[GETARG_A(i)]; switch (GETARG_B(i)) { case OP_R_NORMAL: NORMAL_RETURN: if (ci == mrb->cibase) { localjump_error(mrb, "return"); goto L_RAISE; } ci = mrb->ci; break; case OP_R_BREAK: if (proc->env->cioff < 0) { localjump_error(mrb, "break"); goto L_RAISE; } ci = mrb->ci = mrb->cibase + proc->env->cioff + 1; break; case OP_R_RETURN: if (!proc->env) goto NORMAL_RETURN; if (proc->env->cioff < 0) { localjump_error(mrb, "return"); goto L_RAISE; } ci = mrb->ci = mrb->cibase + proc->env->cioff; break; default: /* cannot happen */ break; } cipop(mrb); acc = ci->acc; pc = ci->pc; regs = mrb->stack = mrb->stbase + ci->stackidx; while (eidx > mrb->ci->eidx) { ecall(mrb, --eidx); } if (acc < 0) { mrb->jmp = prev_jmp; return v; } DEBUG(printf("from :%s\n", mrb_sym2name(mrb, ci->mid))); proc = mrb->ci->proc; irep = proc->body.irep; pool = irep->pool; syms = irep->syms; regs[acc] = v; } JUMP; } CASE(OP_TAILCALL) { /* A B C return call(R(A),Sym(B),R(A+1),... ,R(A+C-1)) */ int a = GETARG_A(i); int n = GETARG_C(i); struct RProc *m; struct RClass *c; mrb_callinfo *ci; mrb_value recv; mrb_sym mid = syms[GETARG_B(i)]; recv = regs[a]; c = mrb_class(mrb, recv); m = mrb_method_search_vm(mrb, &c, mid); if (!m) { mrb_value sym = mrb_symbol_value(mid); mid = mrb_intern(mrb, "method_missing"); m = mrb_method_search_vm(mrb, &c, mid); if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], sym); } else { memmove(regs+a+2, regs+a+1, sizeof(mrb_value)*(n+1)); regs[a+1] = sym; n++; } } /* replace callinfo */ ci = mrb->ci; ci->mid = mid; ci->target_class = m->target_class; ci->argc = n; if (ci->argc == CALL_MAXARGS) ci->argc = -1; /* move stack */ memmove(mrb->stack, ®s[a], (ci->argc+1)*sizeof(mrb_value)); if (MRB_PROC_CFUNC_P(m)) { mrb->stack[0] = m->body.func(mrb, recv); mrb->arena_idx = ai; goto L_RETURN; } else { /* setup environment for calling method */ irep = m->body.irep; pool = irep->pool; syms = irep->syms; if (ci->argc < 0) { stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3); } else { stack_extend(mrb, irep->nregs, ci->argc+2); } regs = mrb->stack; pc = irep->iseq; } JUMP; } CASE(OP_BLKPUSH) { /* A Bx R(A) := block (16=6:1:5:4) */ int a = GETARG_A(i); int bx = GETARG_Bx(i); int m1 = (bx>>10)&0x3f; int r = (bx>>9)&0x1; int m2 = (bx>>4)&0x1f; int lv = (bx>>0)&0xf; mrb_value *stack; if (lv == 0) stack = regs + 1; else { struct REnv *e = uvenv(mrb, lv-1); if (!e) { localjump_error(mrb, "yield"); goto L_RAISE; } stack = e->stack + 1; } regs[a] = stack[m1+r+m2]; NEXT; } #define attr_i value.i #ifdef MRB_NAN_BOXING #define attr_f f #else #define attr_f value.f #endif #define TYPES2(a,b) (((((int)(a))<<8)|((int)(b)))&0xffff) #define OP_MATH_BODY(op,v1,v2) do {\ regs[a].v1 = regs[a].v1 op regs[a+1].v2;\ } while(0) CASE(OP_ADD) { /* A B C R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1)*/ int a = GETARG_A(i); /* need to check if op is overridden */ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): { mrb_int x, y, z; x = mrb_fixnum(regs[a]); y = mrb_fixnum(regs[a+1]); z = x + y; if (((x < 0) ^ (y < 0)) == 0 && (x < 0) != (z < 0)) { /* integer overflow */ SET_FLT_VALUE(regs[a], (mrb_float)x + (mrb_float)y); break; } SET_INT_VALUE(regs[a], z); } break; case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): { mrb_int x = mrb_fixnum(regs[a]); mrb_float y = mrb_float(regs[a+1]); SET_FLT_VALUE(regs[a], (mrb_float)x + y); } break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): OP_MATH_BODY(+,attr_f,attr_i); break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): OP_MATH_BODY(+,attr_f,attr_f); break; case TYPES2(MRB_TT_STRING,MRB_TT_STRING): regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]); break; default: goto L_SEND; } mrb->arena_idx = ai; NEXT; } CASE(OP_SUB) { /* A B C R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1)*/ int a = GETARG_A(i); /* need to check if op is overridden */ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): { mrb_int x, y, z; x = mrb_fixnum(regs[a]); y = mrb_fixnum(regs[a+1]); z = x - y; if (((x < 0) ^ (y < 0)) == 0 && (x < 0) != (z < 0)) { /* integer overflow */ SET_FLT_VALUE(regs[a], (mrb_float)x - (mrb_float)y); break; } SET_INT_VALUE(regs[a], z); } break; case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): { mrb_int x = mrb_fixnum(regs[a]); mrb_float y = mrb_float(regs[a+1]); SET_FLT_VALUE(regs[a], (mrb_float)x - y); } break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): OP_MATH_BODY(-,attr_f,attr_i); break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): OP_MATH_BODY(-,attr_f,attr_f); break; default: goto L_SEND; } NEXT; } CASE(OP_MUL) { /* A B C R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1)*/ int a = GETARG_A(i); /* need to check if op is overridden */ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): { mrb_int x, y, z; x = mrb_fixnum(regs[a]); y = mrb_fixnum(regs[a+1]); z = x * y; if (x != 0 && z/x != y) { SET_FLT_VALUE(regs[a], (mrb_float)x * (mrb_float)y); } else { SET_INT_VALUE(regs[a], z); } } break; case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): { mrb_int x = mrb_fixnum(regs[a]); mrb_float y = mrb_float(regs[a+1]); SET_FLT_VALUE(regs[a], (mrb_float)x * y); } break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): OP_MATH_BODY(*,attr_f,attr_i); break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): OP_MATH_BODY(*,attr_f,attr_f); break; default: goto L_SEND; } NEXT; } CASE(OP_DIV) { /* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1)*/ int a = GETARG_A(i); /* need to check if op is overridden */ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): { mrb_int x = mrb_fixnum(regs[a]); mrb_int y = mrb_fixnum(regs[a+1]); SET_FLT_VALUE(regs[a], (mrb_float)x / (mrb_float)y); } break; case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): { mrb_int x = mrb_fixnum(regs[a]); mrb_float y = mrb_float(regs[a+1]); SET_FLT_VALUE(regs[a], (mrb_float)x / y); } break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): OP_MATH_BODY(/,attr_f,attr_i); break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): OP_MATH_BODY(/,attr_f,attr_f); break; default: goto L_SEND; } NEXT; } CASE(OP_ADDI) { /* A B C R(A) := R(A)+C (Syms[B]=:+)*/ int a = GETARG_A(i); /* need to check if + is overridden */ switch (mrb_type(regs[a])) { case MRB_TT_FIXNUM: { mrb_int x = regs[a].attr_i; mrb_int y = GETARG_C(i); mrb_int z = x + y; if (((x < 0) ^ (y < 0)) == 0 && (x < 0) != (z < 0)) { /* integer overflow */ SET_FLT_VALUE(regs[a], (mrb_float)x + (mrb_float)y); break; } regs[a].attr_i = z; } break; case MRB_TT_FLOAT: regs[a].attr_f += GETARG_C(i); break; default: SET_INT_VALUE(regs[a+1], GETARG_C(i)); i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1); goto L_SEND; } NEXT; } CASE(OP_SUBI) { /* A B C R(A) := R(A)-C (Syms[B]=:+)*/ int a = GETARG_A(i); /* need to check if + is overridden */ switch (mrb_type(regs[a])) { case MRB_TT_FIXNUM: { mrb_int x = regs[a].attr_i; mrb_int y = GETARG_C(i); mrb_int z = x - y; if (((x < 0) ^ (y < 0)) == 0 && (x < 0) != (z < 0)) { /* integer overflow */ SET_FLT_VALUE(regs[a], (mrb_float)x - (mrb_float)y); break; } regs[a].attr_i = z; } break; case MRB_TT_FLOAT: regs[a].attr_f -= GETARG_C(i); break; default: SET_INT_VALUE(regs[a+1], GETARG_C(i)); i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1); goto L_SEND; } NEXT; } #define OP_CMP_BODY(op,v1,v2) do {\ if (regs[a].v1 op regs[a+1].v2) {\ SET_TRUE_VALUE(regs[a]);\ }\ else {\ SET_FALSE_VALUE(regs[a]);\ }\ } while(0) #define OP_CMP(op) do {\ int a = GETARG_A(i);\ /* need to check if - is overridden */\ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\ OP_CMP_BODY(op,attr_i,attr_i);\ break;\ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):\ OP_CMP_BODY(op,attr_i,attr_f);\ break;\ case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):\ OP_CMP_BODY(op,attr_f,attr_i);\ break;\ case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):\ OP_CMP_BODY(op,attr_f,attr_f);\ break;\ default:\ goto L_SEND;\ }\ } while (0) CASE(OP_EQ) { /* A B C R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1)*/ int a = GETARG_A(i); if (mrb_obj_eq(mrb, regs[a], regs[a+1])) { SET_TRUE_VALUE(regs[a]); } else { OP_CMP(==); } NEXT; } CASE(OP_LT) { /* A B C R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1)*/ OP_CMP(<); NEXT; } CASE(OP_LE) { /* A B C R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1)*/ OP_CMP(<=); NEXT; } CASE(OP_GT) { /* A B C R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1)*/ OP_CMP(>); NEXT; } CASE(OP_GE) { /* A B C R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1)*/ OP_CMP(>=); NEXT; } CASE(OP_ARRAY) { /* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */ regs[GETARG_A(i)] = mrb_ary_new_from_values(mrb, GETARG_C(i), ®s[GETARG_B(i)]); mrb->arena_idx = ai; NEXT; } CASE(OP_ARYCAT) { /* A B mrb_ary_concat(R(A),R(B)) */ mrb_ary_concat(mrb, regs[GETARG_A(i)], mrb_ary_splat(mrb, regs[GETARG_B(i)])); mrb->arena_idx = ai; NEXT; } CASE(OP_ARYPUSH) { /* A B R(A).push(R(B)) */ mrb_ary_push(mrb, regs[GETARG_A(i)], regs[GETARG_B(i)]); NEXT; } CASE(OP_AREF) { /* A B C R(A) := R(B)[C] */ int a = GETARG_A(i); int c = GETARG_C(i); mrb_value v = regs[GETARG_B(i)]; if (mrb_type(v) != MRB_TT_ARRAY) { if (c == 0) { regs[GETARG_A(i)] = v; } else { SET_NIL_VALUE(regs[a]); } } else { regs[GETARG_A(i)] = mrb_ary_ref(mrb, v, c); } NEXT; } CASE(OP_ASET) { /* A B C R(B)[C] := R(A) */ mrb_ary_set(mrb, regs[GETARG_B(i)], GETARG_C(i), regs[GETARG_A(i)]); NEXT; } CASE(OP_APOST) { /* A B C *R(A),R(A+1)..R(A+C) := R(A) */ int a = GETARG_A(i); mrb_value v = regs[a]; int pre = GETARG_B(i); int post = GETARG_C(i); if (mrb_type(v) != MRB_TT_ARRAY) { regs[a++] = mrb_ary_new_capa(mrb, 0); while (post--) { SET_NIL_VALUE(regs[a]); a++; } } else { struct RArray *ary = mrb_ary_ptr(v); int len = ary->len; int i; if (len > pre + post) { regs[a++] = mrb_ary_new_elts(mrb, len - pre - post, ary->ptr+pre); while (post--) { regs[a++] = ary->ptr[len-post-1]; } } else { regs[a++] = mrb_ary_new_capa(mrb, 0); for (i=0; i+pre<len; i++) { regs[a+i] = ary->ptr[pre+i]; } while (i < post) { SET_NIL_VALUE(regs[a+i]); i++; } } } mrb->arena_idx = ai; NEXT; } CASE(OP_STRING) { /* A Bx R(A) := str_new(Lit(Bx)) */ regs[GETARG_A(i)] = mrb_str_literal(mrb, pool[GETARG_Bx(i)]); mrb->arena_idx = ai; NEXT; } CASE(OP_STRCAT) { /* A B R(A).concat(R(B)) */ mrb_str_concat(mrb, regs[GETARG_A(i)], regs[GETARG_B(i)]); NEXT; } CASE(OP_HASH) { /* A B C R(A) := hash_new(R(B),R(B+1)..R(B+C)) */ int b = GETARG_B(i); int c = GETARG_C(i); int lim = b+c*2; mrb_value hash = mrb_hash_new_capa(mrb, c); while (b < lim) { mrb_hash_set(mrb, hash, regs[b], regs[b+1]); b+=2; } regs[GETARG_A(i)] = hash; mrb->arena_idx = ai; NEXT; } CASE(OP_LAMBDA) { /* A b c R(A) := lambda(SEQ[b],c) (b:c = 14:2) */ struct RProc *p; int c = GETARG_c(i); if (c & OP_L_CAPTURE) { p = mrb_closure_new(mrb, mrb->irep[irep->idx+GETARG_b(i)]); } else { p = mrb_proc_new(mrb, mrb->irep[irep->idx+GETARG_b(i)]); } if (c & OP_L_STRICT) p->flags |= MRB_PROC_STRICT; regs[GETARG_A(i)] = mrb_obj_value(p); mrb->arena_idx = ai; NEXT; } CASE(OP_OCLASS) { /* A R(A) := ::Object */ regs[GETARG_A(i)] = mrb_obj_value(mrb->object_class); NEXT; } CASE(OP_CLASS) { /* A B R(A) := newclass(R(A),Sym(B),R(A+1)) */ struct RClass *c = 0; int a = GETARG_A(i); mrb_value base, super; mrb_sym id = syms[GETARG_B(i)]; base = regs[a]; super = regs[a+1]; if (mrb_nil_p(base)) { base = mrb_obj_value(mrb->ci->target_class); } c = mrb_vm_define_class(mrb, base, super, id); regs[a] = mrb_obj_value(c); mrb->arena_idx = ai; NEXT; } CASE(OP_MODULE) { /* A B R(A) := newmodule(R(A),Sym(B)) */ struct RClass *c = 0; int a = GETARG_A(i); mrb_value base; mrb_sym id = syms[GETARG_B(i)]; base = regs[a]; if (mrb_nil_p(base)) { base = mrb_obj_value(mrb->ci->target_class); } c = mrb_vm_define_module(mrb, base, id); regs[a] = mrb_obj_value(c); mrb->arena_idx = ai; NEXT; } CASE(OP_EXEC) { /* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */ int a = GETARG_A(i); mrb_callinfo *ci; mrb_value recv = regs[a]; struct RProc *p; /* prepare stack */ ci = cipush(mrb); ci->pc = pc + 1; ci->acc = a; ci->mid = 0; ci->stackidx = mrb->stack - mrb->stbase; ci->argc = 0; ci->target_class = mrb_class_ptr(recv); /* prepare stack */ mrb->stack += a; p = mrb_proc_new(mrb, mrb->irep[irep->idx+GETARG_Bx(i)]); p->target_class = ci->target_class; ci->proc = p; if (MRB_PROC_CFUNC_P(p)) { mrb->stack[0] = p->body.func(mrb, recv); mrb->arena_idx = ai; if (mrb->exc) goto L_RAISE; /* pop stackpos */ regs = mrb->stack = mrb->stbase + mrb->ci->stackidx; cipop(mrb); NEXT; } else { irep = p->body.irep; pool = irep->pool; syms = irep->syms; stack_extend(mrb, irep->nregs, 1); ci->nregs = irep->nregs; regs = mrb->stack; pc = irep->iseq; JUMP; } } CASE(OP_METHOD) { /* A B R(A).newmethod(Sym(B),R(A+1)) */ int a = GETARG_A(i); struct RClass *c = mrb_class_ptr(regs[a]); mrb_define_method_vm(mrb, c, syms[GETARG_B(i)], regs[a+1]); mrb->arena_idx = ai; NEXT; } CASE(OP_SCLASS) { /* A B R(A) := R(B).singleton_class */ regs[GETARG_A(i)] = mrb_singleton_class(mrb, regs[GETARG_B(i)]); mrb->arena_idx = ai; NEXT; } CASE(OP_TCLASS) { /* A B R(A) := target_class */ if (!mrb->ci->target_class) { static const char msg[] = "no target class or module"; mrb_value exc = mrb_exc_new(mrb, E_TYPE_ERROR, msg, sizeof(msg) - 1); mrb->exc = (struct RObject*)mrb_object(exc); goto L_RAISE; } regs[GETARG_A(i)] = mrb_obj_value(mrb->ci->target_class); NEXT; } CASE(OP_RANGE) { /* A B C R(A) := range_new(R(B),R(B+1),C) */ int b = GETARG_B(i); regs[GETARG_A(i)] = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i)); mrb->arena_idx = ai; NEXT; } CASE(OP_DEBUG) { /* A debug print R(A),R(B),R(C) */ #ifdef ENABLE_STDIO printf("OP_DEBUG %d %d %d\n", GETARG_A(i), GETARG_B(i), GETARG_C(i)); #else abort(); #endif NEXT; } CASE(OP_STOP) { /* stop VM */ L_STOP: { int n = mrb->ci->eidx; while (n--) { ecall(mrb, n); } } mrb->jmp = prev_jmp; if (mrb->exc) { return mrb_obj_value(mrb->exc); } return regs[irep->nlocals]; } CASE(OP_ERR) { /* Bx raise RuntimeError with message Lit(Bx) */ mrb_value msg = pool[GETARG_Bx(i)]; mrb_value exc; if (GETARG_A(i) == 0) { exc = mrb_exc_new3(mrb, E_RUNTIME_ERROR, msg); } else { exc = mrb_exc_new3(mrb, E_LOCALJUMP_ERROR, msg); } mrb->exc = (struct RObject*)mrb_object(exc); goto L_RAISE; } } END_DISPATCH; }
// Create the MRuby object for this virtual mrb_value Create_MRuby_Object(mrb_state* p_state) { return mrb_obj_value(Data_Wrap_Struct(p_state, mrb_class_get(p_state, "Spika"), &Scripting::rtTSC_Scriptable, this)); }
mrb_value winapi_hook_class_value(mrb_state* mrb) { return mrb_obj_value(winapi_hook_class(mrb)); }
/* * call-seq: * obj.class -> class * * Returns the class of <i>obj</i>. This method must always be * called with an explicit receiver, as <code>class</code> is also a * reserved word in Ruby. * * 1.class #=> Fixnum * self.class #=> Object */ static mrb_value mrb_obj_class_m(mrb_state *mrb, mrb_value self) { return mrb_obj_value(mrb_obj_class(mrb, self)); }
mrb_value mrb_exc_new3(mrb_state *mrb, struct RClass* c, mrb_value str) { mrb_string_value(mrb, &str); return mrb_funcall(mrb, mrb_obj_value(c), "new", 1, str); }
void mrb_undef_class_method(mrb_state *mrb, struct RClass *c, const char *name) { mrb_undef_method(mrb, mrb_class_ptr(mrb_singleton_class(mrb, mrb_obj_value(c))), name); }
//---------------------------------------------------------- mrb_value BindImage::ToMrb(mrb_state* mrb, struct RClass* aClass, ofImage* aPtr) { struct RData *data = mrb_data_object_alloc(mrb, aClass, aPtr, &data_type); return mrb_obj_value(data); }