diff options
Diffstat (limited to 'mrbgems/mruby-object-ext')
| -rw-r--r-- | mrbgems/mruby-object-ext/mrbgem.rake | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-object-ext/mrblib/object.rb | 16 | ||||
| -rw-r--r-- | mrbgems/mruby-object-ext/src/object.c | 72 | ||||
| -rw-r--r-- | mrbgems/mruby-object-ext/test/nil.rb | 5 | ||||
| -rw-r--r-- | mrbgems/mruby-object-ext/test/object.rb | 28 |
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 |
