static void mark_context_stack(mrb_state *mrb, struct mrb_context *c) { size_t i; size_t e; mrb_value nil; int nregs; if (c->stack == NULL) return; e = c->stack - c->stbase; if (c->ci) { nregs = c->ci->argc + 2; if (c->ci->nregs > nregs) nregs = c->ci->nregs; e += nregs; } if (c->stbase + e > c->stend) e = c->stend - c->stbase; for (i=0; i<e; i++) { mrb_value v = c->stbase[i]; if (!mrb_immediate_p(v)) { mrb_gc_mark(mrb, mrb_basic_ptr(v)); } } e = c->stend - c->stbase; nil = mrb_nil_value(); for (; i<e; i++) { c->stbase[i] = nil; } }
static mrb_value join_ary(mrb_state *mrb, mrb_value ary, mrb_value sep, mrb_value list) { mrb_int i; mrb_value result, val, tmp; /* check recursive */ for (i=0; i<RARRAY_LEN(list); i++) { if (mrb_obj_equal(mrb, ary, RARRAY_PTR(list)[i])) { mrb_raise(mrb, E_ARGUMENT_ERROR, "recursive array join"); } } mrb_ary_push(mrb, list, ary); result = mrb_str_buf_new(mrb, 64); for (i=0; i<RARRAY_LEN(ary); i++) { if (i > 0 && !mrb_nil_p(sep)) { mrb_str_cat_str(mrb, result, sep); } val = RARRAY_PTR(ary)[i]; switch (mrb_type(val)) { case MRB_TT_ARRAY: ary_join: val = join_ary(mrb, val, sep, list); /* fall through */ case MRB_TT_STRING: str_join: mrb_str_cat_str(mrb, result, val); break; default: if (!mrb_immediate_p(val)) { tmp = mrb_check_string_type(mrb, val); if (!mrb_nil_p(tmp)) { val = tmp; goto str_join; } tmp = mrb_check_convert_type(mrb, val, MRB_TT_ARRAY, "Array", "to_ary"); if (!mrb_nil_p(tmp)) { val = tmp; goto ary_join; } } val = mrb_obj_as_string(mrb, val); goto str_join; } } mrb_ary_pop(mrb, list); return result; }
static mrb_value mrb_ary_cmp(mrb_state *mrb, mrb_value ary1) { mrb_value ary2; mrb_get_args(mrb, "o", &ary2); if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_fixnum_value(0); if (mrb_immediate_p(ary2)) return mrb_nil_value(); if (!mrb_array_p(ary2)) { return mrb_nil_value(); } return ary2; }
static mrb_value mrb_ary_eq(mrb_state *mrb, mrb_value ary1) { mrb_value ary2; mrb_get_args(mrb, "o", &ary2); if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value(); if (mrb_immediate_p(ary2)) return mrb_false_value(); if (!mrb_array_p(ary2)) { return mrb_false_value(); } if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value(); return ary2; }
MRB_API mrb_value mrb_obj_dup(mrb_state *mrb, mrb_value obj) { struct RBasic *p; mrb_value dup; if (mrb_immediate_p(obj)) { mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %S", obj); } p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj)); dup = mrb_obj_value(p); init_copy(mrb, dup, obj); return dup; }
/* * call-seq: * obj.clone -> an_object * * Produces a shallow copy of <i>obj</i>---the instance variables of * <i>obj</i> are copied, but not the objects they reference. Copies * the frozen state of <i>obj</i>. See also the discussion * under <code>Object#dup</code>. * * class Klass * attr_accessor :str * end * s1 = Klass.new #=> #<Klass:0x401b3a38> * s1.str = "Hello" #=> "Hello" * s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello"> * s2.str[1,4] = "i" #=> "i" * s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">" * s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">" * * This method may have class-specific behavior. If so, that * behavior will be documented under the #+initialize_copy+ method of * the class. * * Some Class(True False Nil Symbol Fixnum Float) Object cannot clone. */ MRB_API mrb_value mrb_obj_clone(mrb_state *mrb, mrb_value self) { struct RObject *p; mrb_value clone; if (mrb_immediate_p(self)) { mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %S", self); } p = (struct RObject*)mrb_obj_alloc(mrb, mrb_type(self), mrb_obj_class(mrb, self)); p->c = mrb_singleton_class_clone(mrb, self); clone = mrb_obj_value(p); init_copy(mrb, clone, self); return clone; }
/* * call-seq: * obj.clone -> an_object * * Produces a shallow copy of <i>obj</i>---the instance variables of * <i>obj</i> are copied, but not the objects they reference. Copies * the frozen state of <i>obj</i>. See also the discussion * under <code>Object#dup</code>. * * class Klass * attr_accessor :str * end * s1 = Klass.new #=> #<Klass:0x401b3a38> * s1.str = "Hello" #=> "Hello" * s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello"> * s2.str[1,4] = "i" #=> "i" * s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">" * s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">" * * This method may have class-specific behavior. If so, that * behavior will be documented under the #+initialize_copy+ method of * the class. * * Some Class(True False Nil Symbol Fixnum Float) Object cannot clone. */ MRB_API mrb_value mrb_obj_clone(mrb_state *mrb, mrb_value self) { struct RObject *p; mrb_value clone; if (mrb_immediate_p(self)) { mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %S", self); } if (mrb_type(self) == MRB_TT_SCLASS) { mrb_raise(mrb, E_TYPE_ERROR, "can't clone singleton class"); } p = (struct RObject*)mrb_obj_alloc(mrb, mrb_type(self), mrb_obj_class(mrb, self)); p->c = mrb_singleton_class_clone(mrb, self); mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)p->c); clone = mrb_obj_value(p); init_copy(mrb, clone, self); return clone; }
static void mark_context_stack(mrb_state *mrb, struct mrb_context *c) { size_t i; size_t e; e = c->stack - c->stbase; if (c->ci) e += c->ci->nregs; if (c->stbase + e > c->stend) e = c->stend - c->stbase; for (i=0; i<e; i++) { mrb_value v = c->stbase[i]; if (!mrb_immediate_p(v)) { if (mrb_basic_ptr(v)->tt == MRB_TT_FREE) { c->stbase[i] = mrb_nil_value(); } else { mrb_gc_mark(mrb, mrb_basic_ptr(v)); } } } }
MRB_API void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t) { const struct types *type = builtin_types; enum mrb_vtype xt; xt = mrb_type(x); if ((xt != t) || (xt == MRB_TT_DATA)) { while (type->type < MRB_TT_MAXDEFINE) { if (type->type == t) { const char *etype; if (mrb_nil_p(x)) { etype = "nil"; } else if (mrb_fixnum_p(x)) { etype = "Fixnum"; } else if (mrb_type(x) == MRB_TT_SYMBOL) { etype = "Symbol"; } else if (mrb_immediate_p(x)) { etype = RSTRING_PTR(mrb_obj_as_string(mrb, x)); } else { etype = mrb_obj_classname(mrb, x); } mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)", mrb_str_new_cstr(mrb, etype), mrb_str_new_cstr(mrb, type->name)); } type++; } mrb_raisef(mrb, E_TYPE_ERROR, "unknown type %S (%S given)", mrb_fixnum_value(t), mrb_fixnum_value(mrb_type(x))); } }
/* mrb_gc_protect() leaves the object in the arena */ MRB_API void mrb_gc_protect(mrb_state *mrb, mrb_value obj) { if (mrb_immediate_p(obj)) return; gc_protect(mrb, mrb_basic_ptr(obj)); }