int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp) { VALUE b, e; int excl; if (rb_obj_is_kind_of(range, rb_cRange)) { b = RANGE_BEG(range); e = RANGE_END(range); excl = EXCL(range); } else { if (!rb_vm_respond_to(range, selBeg, false)) { return 0; } if (!rb_vm_respond_to(range, selEnd, false)) { return 0; } b = rb_vm_call(range, selBeg, 0, NULL); e = rb_vm_call(range, selEnd, 0, NULL); excl = RTEST(rb_vm_call(range, selExcludeEnd, 0, NULL)); } *begp = b; *endp = e; *exclp = excl; return 1; }
static VALUE format_message(VALUE exc) { CFMutableStringRef result = CFStringCreateMutable(NULL, 0); VALUE message = rb_vm_call(exc, sel_registerName("message"), 0, NULL); VALUE bt = rb_vm_call(exc, sel_registerName("backtrace"), 0, NULL); message = rb_check_string_type(message); const char *msg = message == Qnil ? "" : RSTRING_PTR(message); const long count = (bt != Qnil ? RARRAY_LEN(bt) : 0); if (count > 0) { for (long i = 0; i < count; i++) { const char *bte = RSTRING_PTR(RARRAY_AT(bt, i)); if (i == 0) { CFStringAppendFormat(result, NULL, CFSTR("%s: %s (%s)\n"), bte, msg, rb_class2name(*(VALUE *)exc)); } else { CFStringAppendFormat(result, NULL, CFSTR("\tfrom %s\n"), bte); } } } else { CFStringAppendFormat(result, NULL, CFSTR("%s (%s)\n"), msg, rb_class2name(*(VALUE *)exc)); } CFMakeCollectable(result); return (VALUE)result; }
static VALUE exc_equal(VALUE exc, SEL sel, VALUE obj) { VALUE mesg, backtrace; if (exc == obj) { return Qtrue; } ID id_mesg = rb_intern("mesg"); if (rb_obj_class(exc) != rb_obj_class(obj)) { SEL sel_message = sel_registerName("message"); SEL sel_backtrace = sel_registerName("backtrace"); if (!rb_vm_respond_to(obj, sel_message, false) || !rb_vm_respond_to(obj, sel_backtrace, false)) { return Qfalse; } mesg = rb_vm_call(obj, sel_message, 0, NULL); backtrace = rb_vm_call(obj, sel_backtrace, 0, NULL); } else { mesg = rb_attr_get(obj, id_mesg); backtrace = exc_backtrace(obj, 0); } if (!rb_equal(rb_attr_get(exc, id_mesg), mesg)) { return Qfalse; } if (!rb_equal(exc_backtrace(exc, 0), backtrace)) { return Qfalse; } return Qtrue; }
static VALUE range_each_func(VALUE range, VALUE (*func) (VALUE, void *), void *arg) { int c; VALUE b = RANGE_BEG(range); VALUE e = RANGE_END(range); VALUE v = b; if (EXCL(range)) { while (r_lt(v, e)) { (*func) (v, arg); RETURN_IF_BROKEN(); v = rb_vm_call(v, selSucc, 0, NULL); } } else { while (RTEST(c = r_le(v, e))) { (*func) (v, arg); RETURN_IF_BROKEN(); if (c == INT2FIX(0)) break; v = rb_vm_call(v, selSucc, 0, NULL); } } return range; }
static VALUE rb_yaml_emitter_add(VALUE self, SEL sel, int argc, VALUE *argv) { VALUE first = Qnil, second = Qnil; rb_scan_args(argc, argv, "11", &first, &second); rb_vm_call(first, sel_to_yaml, 1, &self); if (argc == 2) { rb_vm_call(second, sel_to_yaml, 1, &self); } return self; }
static VALUE interpret_value(rb_yaml_parser_t *parser, VALUE result, VALUE handler) { if (NIL_P(handler)) { return result; } if (rb_vm_respond_to(handler, sel_call, 0)) { return rb_vm_call(handler, sel_call, 1, &result); } else if (rb_vm_respond_to(handler, sel_yaml_new, 0)) { return rb_vm_call(handler, sel_yaml_new, 1, &result); } return result; }
VALUE rb_method_call(int argc, VALUE *argv, VALUE method) { VALUE result = Qnil; /* OK */ struct METHOD *data; int state; volatile int safe = -1; Data_Get_Struct(method, struct METHOD, data); if (data->recv == Qundef) { rb_raise(rb_eTypeError, "can't call unbound method; bind first"); } PUSH_TAG(); if (OBJ_TAINTED(method)) { safe = rb_safe_level(); if (rb_safe_level() < 4) { rb_set_safe_level_force(4); } } if ((state = EXEC_TAG()) == 0) { rb_thread_t *th = GET_THREAD(); VALUE rb_vm_call(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid, int argc, const VALUE *argv, const NODE *body, int nosuper); PASS_PASSED_BLOCK_TH(th); result = rb_vm_call(th, data->oclass, data->recv, data->id, data->oid, argc, argv, data->body, 0); } POP_TAG(); if (safe >= 0) rb_set_safe_level_force(safe); if (state) JUMP_TAG(state); return result; }
unsigned long rb_hash_code(VALUE obj) { switch (TYPE(obj)) { case T_FIXNUM: case T_FLOAT: case T_SYMBOL: case T_NIL: case T_FALSE: case T_TRUE: return (unsigned long)obj; case T_STRING: return rb_str_hash(obj); case T_ARRAY: return rb_ary_hash(obj); } VALUE v = rb_vm_call(obj, selHash, 0, NULL); retry: switch (TYPE(v)) { case T_FIXNUM: return FIX2LONG(v); case T_BIGNUM: return ((unsigned long *)(RBIGNUM_DIGITS(v)))[0]; default: v = rb_to_int(v); goto retry; } }
static VALUE range_max(VALUE range, SEL sel) { VALUE e = RANGE_END(range); int nm = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cNumeric); if (rb_block_given_p() || (EXCL(range) && !nm)) { if (sel == NULL) { sel = sel_registerName("max"); } return rb_vm_call_super(range, sel, 0, NULL); } else { VALUE b = RANGE_BEG(range); int c = rb_cmpint(rb_objs_cmp(b, e), b, e); if (c > 0) return Qnil; if (EXCL(range)) { if (!FIXNUM_P(e) && !rb_obj_is_kind_of(e, rb_cInteger)) { rb_raise(rb_eTypeError, "cannot exclude non Integer end value"); } if (c == 0) { return Qnil; } if (FIXNUM_P(e)) { return LONG2NUM(FIX2LONG(e) - 1); } VALUE one = INT2FIX(1); return rb_vm_call(e, selMINUS, 1, &one); } return e; } }
static BOOL rb_obj_imp_isEqual(void *rcv, SEL sel, void *obj) { if (obj == NULL) { return false; } VALUE arg = OC2RB(obj); return rb_vm_call((VALUE)rcv, selEq, 1, &arg) == Qtrue; }
static VALUE cmp_gt(VALUE x, SEL sel, VALUE y) { VALUE c = rb_vm_call(x, cmp, 1, &y); if (rb_cmpint(c, x, y) > 0) { return Qtrue; } return Qfalse; }
VALUE rb_class_inherited(VALUE super, VALUE klass) { if (rb_vm_running()) { if (super == 0) { super = rb_cObject; } return rb_vm_call(super, selInherited, 1, &klass); } return Qnil; }
static void * rb_obj_imp_description(void *rcv, SEL sel) { // If #description and #to_s are the same method (ex. when aliased) Class rcv_class = (Class)CLASS_OF(rcv); IMP desc_imp = class_getMethodImplementation(rcv_class, selDescription); IMP to_s_imp = class_getMethodImplementation(rcv_class, selToS); if (desc_imp == to_s_imp) { return (void *)rb_any_to_string((VALUE)rcv, sel); } return (void *)rb_vm_call(OC2RB(rcv), selToS, 0, NULL); }
static VALUE cmp_eq(VALUE *a) { VALUE c = rb_vm_call(a[0], cmp, 1, &a[1]); if (NIL_P(c)) { return Qfalse; } if (rb_cmpint(c, a[0], a[1]) == 0) { return Qtrue; } return Qfalse; }
static VALUE rhash_flatten(VALUE hash, SEL sel, int argc, VALUE *argv) { VALUE tmp, ary = rhash_to_a(hash, 0); if (argc == 0) { argc = 1; tmp = INT2FIX(1); argv = &tmp; } rb_vm_call(ary, selFlattenBang, argc, argv); return ary; }
static VALUE sym_step_i(VALUE i, void *arg) { VALUE *iter = arg; if (FIXNUM_P(iter[0])) { iter[0] -= INT2FIX(1) & ~FIXNUM_FLAG; } else { VALUE one = INT2FIX(1); iter[0] = rb_vm_call(iter[0], selMINUS,1, &one); } if (iter[0] == INT2FIX(0)) { rb_yield(ID2SYM(rb_intern_str(i))); iter[0] = iter[1]; } return Qnil; }
static bool rb_obj_respond_to2(VALUE obj, VALUE klass, ID id, int priv, int check_override) { const char *id_name = rb_id2name(id); SEL sel = sel_registerName(id_name); if (!rb_vm_respond_to2(obj, klass, sel, priv, check_override)) { char buf[100]; snprintf(buf, sizeof buf, "%s:", id_name); sel = sel_registerName(buf); if (!rb_vm_respond_to2(obj, klass, sel, priv, check_override)) { VALUE args[2]; args[0] = ID2SYM(id); args[1] = priv ? Qtrue : Qfalse; return RTEST(rb_vm_call(obj, selRespondToDefault, 2, args)); } } return true; }
VALUE rb_objs_cmp(VALUE x, VALUE y) { return rb_vm_call(x, cmp, 1, &y); }
static VALUE range_eqq(VALUE range, SEL sel, VALUE val) { return rb_vm_call(range, selInclude, 1, &val); }
static VALUE range_step(VALUE range, SEL sel, int argc, VALUE *argv) { VALUE b, e, step, tmp; RETURN_ENUMERATOR(range, argc, argv); b = RANGE_BEG(range); e = RANGE_END(range); if (argc == 0) { step = INT2FIX(1); } else { rb_scan_args(argc, argv, "01", &step); if (!rb_obj_is_kind_of(step, rb_cNumeric)) { step = rb_to_int(step); } VALUE zero = INT2FIX(0); if (rb_vm_call(step, selLT, 1, &zero)) { rb_raise(rb_eArgError, "step can't be negative"); } else if (!rb_vm_call(step, selGT, 1, &zero)) { rb_raise(rb_eArgError, "step can't be 0"); } } if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */ long end = FIX2LONG(e); long i, unit = FIX2LONG(step); if (!EXCL(range)) end += 1; i = FIX2LONG(b); while (i < end) { rb_yield(LONG2NUM(i)); RETURN_IF_BROKEN(); if (i + unit < i) break; i += unit; } } else if (SYMBOL_P(b) && SYMBOL_P(e)) { /* symbols are special */ VALUE args[2]; VALUE iter[2]; args[0] = rb_sym_to_s(e); args[1] = EXCL(range) ? Qtrue : Qfalse; iter[0] = INT2FIX(1); iter[1] = step; rb_objc_block_call(rb_sym_to_s(b), selUpto, 2, args, sym_step_i, (VALUE)iter); } else if (ruby_float_step(b, e, step, EXCL(range))) { /* done */ } else if (rb_obj_is_kind_of(b, rb_cNumeric) || !NIL_P(rb_check_to_integer(b, "to_int")) || !NIL_P(rb_check_to_integer(e, "to_int"))) { SEL op = EXCL(range) ? selLT : selLE; VALUE v = b; int i = 0; while (RTEST(rb_vm_call(v, op, 1, &e))) { rb_yield(v); RETURN_IF_BROKEN(); i++; VALUE tmp = rb_vm_call(INT2NUM(i), selMULT, 1, &step); v = rb_vm_call(b, selPLUS, 1, &tmp); } } else { tmp = rb_check_string_type(b); if (!NIL_P(tmp)) { VALUE args[2], iter[2]; b = tmp; args[0] = e; args[1] = EXCL(range) ? Qtrue : Qfalse; iter[0] = INT2FIX(1); iter[1] = step; rb_objc_block_call(b, selUpto, 2, args, step_i, (VALUE)iter); } else { VALUE args[2]; if (!discrete_object_p(b)) { rb_raise(rb_eTypeError, "can't iterate from %s", rb_obj_classname(b)); } args[0] = INT2FIX(1); args[1] = step; return range_each_func(range, step_i, args); } } return range; }
static void * rb_obj_imp_init(void *rcv, SEL sel) { rb_vm_call((VALUE)rcv, selInitialize, 0, NULL); return rcv; }
static inline VALUE rhash_call_default(VALUE hash, VALUE key) { return rb_vm_call(hash, selDefault, 1, &key); }
bool RoxorCore::respond_to(VALUE obj, VALUE klass, SEL sel, bool priv, bool check_override) { if (klass == Qnil) { klass = CLASS_OF(obj); } else { assert(!check_override); } IMP imp = NULL; const bool overriden = check_override ? ((imp = class_getMethodImplementation((Class)klass, selRespondTo)) != basic_respond_to_imp) : false; if (!overriden) { lock(); const long key = respond_to_key((Class)klass, sel); std::map<long, int>::iterator iter = respond_to_cache.find(key); int iter_cached = (iter != respond_to_cache.end()); unlock(); int status; if (iter_cached) { status = iter->second; } else { Method m = class_getInstanceMethod((Class)klass, sel); if (m == NULL) { const char *selname = sel_getName(sel); sel = helper_sel(selname, strlen(selname)); if (sel != NULL) { m = class_getInstanceMethod((Class)klass, sel); } } IMP imp = method_getImplementation(m); if (UNAVAILABLE_IMP(imp) || imp == (IMP)rb_f_notimplement) { status = RESPOND_TO_NOT_EXIST; } else { rb_vm_method_node_t *node = method_node_get(m); if (node != NULL && (node->flags & VM_METHOD_PRIVATE)) { status = RESPOND_TO_PRIVATE; } else { status = RESPOND_TO_PUBLIC; } } lock(); respond_to_cache[key] = status; unlock(); } return status == RESPOND_TO_PUBLIC || (priv && status == RESPOND_TO_PRIVATE); } else { if (imp == NULL || imp == _objc_msgForward) { // The class does not respond to respond_to?:, it's probably // NSProxy-based. return false; } VALUE args[2]; int n = 0; args[n++] = ID2SYM(rb_intern(sel_getName(sel))); if (priv) { rb_vm_method_node_t *node = method_node_get(imp); if (node != NULL && (2 < node->arity.min || (node->arity.max != -1 && 2 > node->arity.max))) { // Do nothing, custom respond_to? method incompatible arity. } else { args[n++] = Qtrue; } } return rb_vm_call(obj, selRespondTo, n, args) == Qtrue; } }
void Init_libyaml() { id_plain = rb_intern("plain"); id_quote1 = rb_intern("quote1"); id_quote2 = rb_intern("quote2"); id_inline = rb_intern("inline"); id_fold = rb_intern("fold"); id_literal = rb_intern("literal"); sel_to_yaml = sel_registerName("to_yaml:"); sel_call = sel_registerName("call:"); sel_yaml_new = sel_registerName("yaml_new:"); rb_mYAML = rb_define_module("YAML"); rb_mLibYAML = rb_define_module_under(rb_mYAML, "LibYAML"); rb_define_const(rb_mLibYAML, "VERSION", rb_str_new2(yaml_get_version_string())); rb_cParser = rb_define_class_under(rb_mLibYAML, "Parser", rb_cObject); rb_objc_define_method(*(VALUE *)rb_cParser, "alloc", rb_yaml_parser_alloc, 0); rb_objc_define_method(rb_cParser, "initialize", rb_yaml_parser_initialize, -1); rb_objc_define_method(rb_cParser, "input", rb_yaml_parser_input, 0); rb_objc_define_method(rb_cParser, "input=", rb_yaml_parser_set_input, 1); // commented methods here are just unimplemented; i plan to put them in soon. //rb_objc_define_method(rb_cParser, "encoding", rb_yaml_parser_encoding, 0); //rb_objc_define_method(rb_cParser, "encoding=", rb_yaml_parser_set_encoding, 1); rb_objc_define_method(rb_cParser, "error", rb_yaml_parser_error, 0); rb_objc_define_method(rb_cParser, "load", rb_yaml_parser_load, 0); rb_objc_define_method(rb_cParser, "parse", rb_yaml_parser_parse, 0); rb_yaml_parser_finalize_super = rb_objc_install_method2((Class)rb_cParser, "finalize", (IMP)rb_yaml_parser_finalize); rb_cResolver = rb_define_class_under(rb_mLibYAML, "Resolver", rb_cObject); rb_objc_define_method(*(VALUE *)rb_cResolver, "alloc", rb_yaml_resolver_alloc, 0); rb_objc_define_method(rb_cResolver, "initialize", rb_yaml_resolver_initialize, 0); //rb_objc_define_method(rb_cResolver, "transfer", rb_yaml_resolver_transfer, 1); rb_objc_define_method(rb_cResolver, "add_type", rb_yaml_resolver_add_type, 2); //rb_objc_define_method(rb_cResolver, "add_domain_type", rb_yaml_resolver_add_domain_type, 2); //rb_objc_define_method(rb_cResolver, "add_ruby_type", rb_yaml_resolver_add_ruby_type, 1); //rb_objc_define_method(rb_cResolver, "add_builtin_type", rb_yaml_resolver_add_builtin_type, 1); //rb_objc_define_method(rb_cResolver, "add_private_type", rb_yaml_resolver_add_private_type, 1); rb_oDefaultResolver = rb_vm_call(rb_cResolver, sel_registerName("new"), 0, NULL); rb_define_const(rb_mLibYAML, "DEFAULT_RESOLVER", rb_oDefaultResolver); rb_cEmitter = rb_define_class_under(rb_mLibYAML, "Emitter", rb_cObject); rb_objc_define_method(*(VALUE *)rb_cEmitter, "alloc", rb_yaml_emitter_alloc, 0); rb_define_attr(rb_cEmitter, "output", 1, 1); rb_objc_define_method(rb_cEmitter, "initialize", rb_yaml_emitter_initialize, -1); rb_objc_define_method(rb_cEmitter, "output=", rb_yaml_emitter_set_output, 1); //rb_objc_define_method(rb_cEmitter, "dump", rb_yaml_emitter_dump, -1); rb_objc_define_method(rb_cEmitter, "stream", rb_yaml_emitter_stream, 0); rb_objc_define_method(rb_cEmitter, "document", rb_yaml_emitter_document, -1); rb_objc_define_method(rb_cEmitter, "seq", rb_yaml_emitter_sequence, 2); rb_objc_define_method(rb_cEmitter, "map", rb_yaml_emitter_mapping, 2); rb_objc_define_method(rb_cEmitter, "scalar", rb_yaml_emitter_scalar, 3); rb_objc_define_method(rb_cEmitter, "add", rb_yaml_emitter_add, -1); //rb_objc_define_method(rb_cEmitter, "error", rb_yaml_emitter_error, 0); //rb_objc_define_method(rb_cEmitter, "encoding", rb_yaml_emitter_encoding, 0); //rb_objc_define_method(rb_cEmitter, "encoding=", rb_yaml_emitter_set_encoding, 1); //rb_objc_define_method(rb_cEmitter, "indentation", rb_yaml_emitter_indent, 0); // TODO: fill in the rest of the accessors rb_yaml_emitter_finalize_super = rb_objc_install_method2((Class)rb_cEmitter, "finalize", (IMP)rb_yaml_emitter_finalize); rb_cYamlNode = rb_define_class_under(rb_mYAML, "YamlNode", rb_cObject); }