summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-object-ext
diff options
context:
space:
mode:
Diffstat (limited to 'mrbgems/mruby-object-ext')
-rw-r--r--mrbgems/mruby-object-ext/mrbgem.rake2
-rw-r--r--mrbgems/mruby-object-ext/mrblib/object.rb16
-rw-r--r--mrbgems/mruby-object-ext/src/object.c72
-rw-r--r--mrbgems/mruby-object-ext/test/nil.rb5
-rw-r--r--mrbgems/mruby-object-ext/test/object.rb28
5 files changed, 99 insertions, 24 deletions
diff --git a/mrbgems/mruby-object-ext/mrbgem.rake b/mrbgems/mruby-object-ext/mrbgem.rake
index 91a6e7ff1..1aea2c8cd 100644
--- a/mrbgems/mruby-object-ext/mrbgem.rake
+++ b/mrbgems/mruby-object-ext/mrbgem.rake
@@ -1,5 +1,5 @@
MRuby::Gem::Specification.new('mruby-object-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
- spec.summary = 'extensional Object class'
+ spec.summary = 'extensional methods shared by all objects'
end
diff --git a/mrbgems/mruby-object-ext/mrblib/object.rb b/mrbgems/mruby-object-ext/mrblib/object.rb
index 581156cb0..f014df469 100644
--- a/mrbgems/mruby-object-ext/mrblib/object.rb
+++ b/mrbgems/mruby-object-ext/mrblib/object.rb
@@ -1,4 +1,18 @@
-class Object
+module Kernel
+ # call-seq:
+ # obj.yield_self {|_obj|...} -> an_object
+ # obj.then {|_obj|...} -> an_object
+ #
+ # Yields <i>obj</i> and returns the result.
+ #
+ # 'my string'.yield_self {|s|s.upcase} #=> "MY STRING"
+ #
+ def yield_self(&block)
+ return to_enum :yield_self unless block
+ block.call(self)
+ end
+ alias then yield_self
+
##
# call-seq:
# obj.tap{|x|...} -> obj
diff --git a/mrbgems/mruby-object-ext/src/object.c b/mrbgems/mruby-object-ext/src/object.c
index dc1924db0..a65feea6d 100644
--- a/mrbgems/mruby-object-ext/src/object.c
+++ b/mrbgems/mruby-object-ext/src/object.c
@@ -1,6 +1,9 @@
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/class.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/hash.h>
+#include <mruby/proc.h>
+#include <mruby/presym.h>
/*
* call-seq:
@@ -15,6 +18,7 @@ nil_to_a(mrb_state *mrb, mrb_value obj)
return mrb_ary_new(mrb);
}
+#ifndef MRB_NO_FLOAT
/*
* call-seq:
* nil.to_f -> 0.0
@@ -27,6 +31,20 @@ nil_to_f(mrb_state *mrb, mrb_value obj)
{
return mrb_float_value(mrb, 0.0);
}
+#endif
+
+/*
+ * call-seq:
+ * nil.to_h -> {}
+ *
+ * Always returns an empty hash.
+ */
+
+static mrb_value
+nil_to_h(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_hash_new(mrb);
+}
/*
* call-seq:
@@ -43,6 +61,22 @@ nil_to_i(mrb_state *mrb, mrb_value obj)
/*
* call-seq:
+ * obj.itself -> an_object
+ *
+ * Returns <i>obj</i>.
+ *
+ * string = 'my string' #=> "my string"
+ * string.itself.object_id == string.object_id #=> true
+ *
+ */
+static mrb_value
+mrb_f_itself(mrb_state *mrb, mrb_value self)
+{
+ return self;
+}
+
+/*
+ * call-seq:
* obj.instance_exec(arg...) {|var...| block } -> obj
*
* Executes the given block within the context of the receiver
@@ -62,29 +96,18 @@ nil_to_i(mrb_state *mrb, mrb_value obj)
static mrb_value
mrb_obj_instance_exec(mrb_state *mrb, mrb_value self)
{
- mrb_value *argv;
+ const mrb_value *argv;
mrb_int argc;
mrb_value blk;
struct RClass *c;
- mrb_get_args(mrb, "*&", &argv, &argc, &blk);
-
- if (mrb_nil_p(blk)) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
- }
-
- switch (mrb_type(self)) {
- case MRB_TT_SYMBOL:
- case MRB_TT_FIXNUM:
- case MRB_TT_FLOAT:
- c = NULL;
- break;
- default:
- c = mrb_class_ptr(mrb_singleton_class(mrb, self));
- break;
+ mrb_get_args(mrb, "*&!", &argv, &argc, &blk);
+ c = mrb_singleton_class_ptr(mrb, self);
+ if (mrb->c->ci->acc < 0) {
+ return mrb_yield_with_class(mrb, blk, argc, argv, self, c);
}
-
- return mrb_yield_with_class(mrb, blk, argc, argv, self, c);
+ mrb_vm_ci_target_class_set(mrb->c->ci, c);
+ return mrb_yield_cont(mrb, blk, self, argc, argv);
}
void
@@ -93,10 +116,15 @@ mrb_mruby_object_ext_gem_init(mrb_state* mrb)
struct RClass * n = mrb->nil_class;
mrb_define_method(mrb, n, "to_a", nil_to_a, MRB_ARGS_NONE());
+#ifndef MRB_NO_FLOAT
mrb_define_method(mrb, n, "to_f", nil_to_f, MRB_ARGS_NONE());
+#endif
+ mrb_define_method(mrb, n, "to_h", nil_to_h, MRB_ARGS_NONE());
mrb_define_method(mrb, n, "to_i", nil_to_i, MRB_ARGS_NONE());
- mrb_define_method(mrb, mrb->object_class, "instance_exec", mrb_obj_instance_exec, MRB_ARGS_ANY() | MRB_ARGS_BLOCK());
+ mrb_define_method(mrb, mrb->kernel_module, "itself", mrb_f_itself, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, mrb_class_get_id(mrb, MRB_SYM(BasicObject)), "instance_exec", mrb_obj_instance_exec, MRB_ARGS_ANY() | MRB_ARGS_BLOCK());
}
void
diff --git a/mrbgems/mruby-object-ext/test/nil.rb b/mrbgems/mruby-object-ext/test/nil.rb
index 5cd1cf4ed..9975e785a 100644
--- a/mrbgems/mruby-object-ext/test/nil.rb
+++ b/mrbgems/mruby-object-ext/test/nil.rb
@@ -3,9 +3,14 @@ assert('NilClass#to_a') do
end
assert('NilClass#to_f') do
+ skip unless Object.const_defined?(:Float)
assert_equal 0.0, nil.to_f
end
+assert('NilClass#to_h') do
+ assert_equal Hash.new, nil.to_h
+end
+
assert('NilClass#to_i') do
assert_equal 0, nil.to_i
end
diff --git a/mrbgems/mruby-object-ext/test/object.rb b/mrbgems/mruby-object-ext/test/object.rb
index fe56f1ec5..f0742f8ce 100644
--- a/mrbgems/mruby-object-ext/test/object.rb
+++ b/mrbgems/mruby-object-ext/test/object.rb
@@ -23,3 +23,31 @@ assert('Object#tap') do
], ret
assert_equal(:tap_ok, Class.new {def m; tap{return :tap_ok}; end}.new.m)
end
+
+assert('instance_exec on primitives with class and module definition') do
+ begin
+ class A
+ 1.instance_exec do
+ class B
+ end
+ end
+ end
+
+ assert_kind_of Class, A::B
+ ensure
+ Object.remove_const :A
+ end
+
+ begin
+ class A
+ 1.instance_exec do
+ module B
+ end
+ end
+ end
+
+ assert_kind_of Module, A::B
+ ensure
+ Object.remove_const :A
+ end
+end