summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/mruby/khash.h16
-rw-r--r--src/class.c2
-rw-r--r--src/gc.c14
-rw-r--r--src/kernel.c13
-rw-r--r--src/struct.c4
-rw-r--r--test/t/kernel.rb83
-rw-r--r--test/t/struct.rb7
7 files changed, 117 insertions, 22 deletions
diff --git a/include/mruby/khash.h b/include/mruby/khash.h
index e236f0bea..0803521b7 100644
--- a/include/mruby/khash.h
+++ b/include/mruby/khash.h
@@ -61,6 +61,7 @@ static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
khint_t kh_put_##name(kh_##name##_t *h, khkey_t key); \
void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \
void kh_del_##name(kh_##name##_t *h, khint_t x); \
+ kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h);
/* define kh_xxx_funcs
@@ -179,6 +180,20 @@ static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
{ \
h->d_flags[x/8] |= __m[x%8]; \
h->size--; \
+ } \
+ kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h) \
+ { \
+ kh_##name##_t *h2; \
+ khiter_t k, k2; \
+ \
+ h2 = kh_init_##name(mrb); \
+ for (k = kh_begin(h); k != kh_end(h); k++) { \
+ if (kh_exist(h, k)) { \
+ k2 = kh_put_##name(h2, kh_key(h, k)); \
+ kh_value(h2, k2) = kh_value(h, k); \
+ } \
+ } \
+ return h2; \
}
@@ -191,6 +206,7 @@ static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
#define kh_put(name, h, k) kh_put_##name(h, k)
#define kh_get(name, h, k) kh_get_##name(h, k)
#define kh_del(name, h, k) kh_del_##name(h, k)
+#define kh_copy(name, mrb, h) kh_copy_##name(mrb, h)
#define kh_exist(h, x) (!__ac_iseither((h)->e_flags, (h)->d_flags, (x)))
#define kh_key(h, x) ((h)->keys[x])
diff --git a/src/class.c b/src/class.c
index 881a0072e..16fb36617 100644
--- a/src/class.c
+++ b/src/class.c
@@ -37,7 +37,7 @@ mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c)
if (kh_exist(h, k)){
struct RProc *m = kh_value(h, k);
if (m) {
- paint_black(m);
+ mrb_gc_mark(mrb, (struct RBasic*)m);
}
}
}
diff --git a/src/gc.c b/src/gc.c
index 1010a6749..93085db61 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -345,8 +345,8 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj)
break;
case MRB_TT_CLASS:
- case MRB_TT_SCLASS:
case MRB_TT_MODULE:
+ case MRB_TT_SCLASS:
{
struct RClass *c = (struct RClass*)obj;
@@ -430,6 +430,18 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj)
break;
#endif
+#ifdef ENABLE_STRUCT
+ case MRB_TT_STRUCT:
+ {
+ struct RStruct *s = (struct RStruct*)obj;
+ long i;
+ for (i=0; i<s->len; i++){
+ mrb_gc_mark_value(mrb, s->ptr[i]);
+ }
+ }
+ break;
+#endif
+
default:
break;
}
diff --git a/src/kernel.c b/src/kernel.c
index 8da112ee5..5e17d4b5a 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -338,7 +338,12 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj)
if (klass->iv) {
clone->iv = klass->iv;
}
- clone->mt = kh_init(mt, mrb);
+ if (klass->mt) {
+ clone->mt = kh_copy(mt, mrb, klass->mt);
+ }
+ else {
+ clone->mt = kh_init(mt, mrb);
+ }
clone->tt = MRB_TT_SCLASS;
return clone;
}
@@ -361,10 +366,11 @@ init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj)
case MRB_TT_CLASS:
case MRB_TT_MODULE:
if (ROBJECT(dest)->iv) {
+ kh_destroy(iv, ROBJECT(dest)->iv);
ROBJECT(dest)->iv = 0;
}
if (ROBJECT(obj)->iv) {
- ROBJECT(dest)->iv = ROBJECT(obj)->iv;
+ ROBJECT(dest)->iv = kh_copy(iv, mrb, ROBJECT(obj)->iv);
}
break;
@@ -446,9 +452,8 @@ mrb_obj_dup(mrb_state *mrb, mrb_value obj)
mrb_raise(mrb, E_TYPE_ERROR, "can't dup %s", mrb_obj_classname(mrb, obj));
}
p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj));
- //init_copy(dup, obj);
dup = mrb_obj_value(p);
- mrb_funcall(mrb, dup, "initialize_copy", 1, obj);
+ init_copy(mrb, dup, obj);
return dup;
}
diff --git a/src/struct.c b/src/struct.c
index 855974182..25cd02d3d 100644
--- a/src/struct.c
+++ b/src/struct.c
@@ -286,8 +286,8 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k
nstr = mrb_obj_value(c);
mrb_iv_set(mrb, nstr, mrb_intern(mrb, "__members__"), members);
- mrb_define_class_method(mrb, c, "new", mrb_class_new_instance_m, ARGS_ANY());
- mrb_define_class_method(mrb, c, "[]", mrb_class_new_instance_m, ARGS_ANY());
+ mrb_define_class_method(mrb, c, "new", mrb_instance_new, ARGS_ANY());
+ mrb_define_class_method(mrb, c, "[]", mrb_instance_new, ARGS_ANY());
mrb_define_class_method(mrb, c, "members", mrb_struct_s_members_m, ARGS_NONE());
//RSTRUCT(nstr)->basic.c->super = c->c;
ptr_members = RARRAY_PTR(members);
diff --git a/test/t/kernel.rb b/test/t/kernel.rb
index ba708dbb7..c1f42e420 100644
--- a/test/t/kernel.rb
+++ b/test/t/kernel.rb
@@ -71,11 +71,67 @@ assert('Kernel.raise', '15.3.1.2.12') do
e_list[0].class == RuntimeError
end
-assert('Kernel#hash', '15.3.1.2.15') do
+assert('Kernel#clone', '15.3.1.3.8') do
+ class KernelCloneTest
+ def initialize
+ @v = 0
+ end
+
+ def get
+ @v
+ end
+
+ def set(v)
+ @v = v
+ end
+ end
+
+ a = KernelCloneTest.new
+ a.set(1)
+ b = a.clone
+
+ def a.test
+ end
+ a.set(2)
+ c = a.clone
+
+ a.get == 2 && b.get == 1 && c.get == 2 &&
+ a.respond_to?(:test) == true && b.respond_to?(:test) == false && c.respond_to?(:test) == true
+end
+
+assert('Kernel#dup', '15.3.1.3.9') do
+ class KernelDupTest
+ def initialize
+ @v = 0
+ end
+
+ def get
+ @v
+ end
+
+ def set(v)
+ @v = v
+ end
+ end
+
+ a = KernelDupTest.new
+ a.set(1)
+ b = a.dup
+
+ def a.test
+ end
+ a.set(2)
+ c = a.dup
+
+ a.get == 2 && b.get == 1 && c.get == 2 &&
+ a.respond_to?(:test) == true && b.respond_to?(:test) == false && c.respond_to?(:test) == false
+end
+
+assert('Kernel#hash', '15.3.1.3.15') do
hash == hash
end
-assert('Kernel#loop', '15.3.1.2.29') do
+assert('Kernel#loop', '15.3.1.3.29') do
i = 0
loop do
@@ -86,32 +142,31 @@ assert('Kernel#loop', '15.3.1.2.29') do
i == 100
end
-assert('Kernel#methods', '15.3.1.2.31') do
+assert('Kernel#methods', '15.3.1.3.31') do
methods.class == Array
end
-assert('Kernel#nil?', '15.3.1.2.32') do
- # TODO why is Kernel nil ????
- nil? == true
+assert('Kernel#nil?', '15.3.1.3.32') do
+ nil.nil? == true
end
-assert('Kernel#private_methods', '15.3.1.2.36') do
- private_methods.class == Array
+assert('Kernel#private_methods', '15.3.1.3.36') do
+ private_methods.class == Array
end
-assert('Kernel#protected_methods', '15.3.1.2.37') do
+assert('Kernel#protected_methods', '15.3.1.3.37') do
protected_methods.class == Array
end
-assert('Kernel#public_methods', '15.3.1.2.38') do
+assert('Kernel#public_methods', '15.3.1.3.38') do
public_methods.class == Array
end
-assert('Kernel#respond_to?', '15.3.1.2.43') do
+assert('Kernel#respond_to?', '15.3.1.3.43') do
respond_to? :nil?
end
-assert('Kernel#send', '15.3.1.2.44') do
+assert('Kernel#send', '15.3.1.3.44') do
# test with block
l = send(:lambda) do
true
@@ -123,11 +178,11 @@ assert('Kernel#send', '15.3.1.2.44') do
send(:public_methods).class == Array
end
-assert('Kernel#singleton_methods', '15.3.1.2.45') do
+assert('Kernel#singleton_methods', '15.3.1.3.45') do
singleton_methods.class == Array
end
-assert('Kernel#to_s', '15.3.1.2.46') do
+assert('Kernel#to_s', '15.3.1.3.46') do
# TODO looks strange..
to_s == ''
end
diff --git a/test/t/struct.rb b/test/t/struct.rb
index fff02ee56..5cf6929b8 100644
--- a/test/t/struct.rb
+++ b/test/t/struct.rb
@@ -16,6 +16,13 @@ if Object.const_defined?(:Struct)
c.members == [:m1,:m2]
end
+ assert('Struct#==', '15.2.18.4.1') do
+ c = Struct.new(:m1, :m2)
+ cc1 = c.new(1,2)
+ cc2 = c.new(1,2)
+ cc1 == cc2
+ end
+
assert('Struct#[]', '15.2.18.4.2') do
c = Struct.new(:m1, :m2)
cc = c.new(1,2)