From b83ff8ccd8294de76bf8dbdea27ace70a667688a Mon Sep 17 00:00:00 2001 From: ksss Date: Mon, 18 Dec 2017 10:54:37 +0900 Subject: [PATCH] Add mrbgems/mruby-method from https://github.com/ksss/mruby-method/commit/0837a0b507a5b4cdf8a1f1039ee371cee4e3b7fb --- mrbgems/mruby-method/.travis.yml | 17 + mrbgems/mruby-method/.travis_build_config.rb | 6 + mrbgems/mruby-method/README.md | 77 ++++ mrbgems/mruby-method/find_all.png | Bin 0 -> 59921 bytes mrbgems/mruby-method/mrbgem.rake | 7 + mrbgems/mruby-method/mrblib/kernel.rb | 9 + mrbgems/mruby-method/mrblib/method.rb | 20 + mrbgems/mruby-method/mrblib/unbound_method.rb | 9 + mrbgems/mruby-method/src/method.c | 423 +++++++++++++++++ mrbgems/mruby-method/test/method.rb | 425 ++++++++++++++++++ 10 files changed, 993 insertions(+) create mode 100644 mrbgems/mruby-method/.travis.yml create mode 100644 mrbgems/mruby-method/.travis_build_config.rb create mode 100644 mrbgems/mruby-method/README.md create mode 100644 mrbgems/mruby-method/find_all.png create mode 100644 mrbgems/mruby-method/mrbgem.rake create mode 100644 mrbgems/mruby-method/mrblib/kernel.rb create mode 100644 mrbgems/mruby-method/mrblib/method.rb create mode 100644 mrbgems/mruby-method/mrblib/unbound_method.rb create mode 100644 mrbgems/mruby-method/src/method.c create mode 100644 mrbgems/mruby-method/test/method.rb diff --git a/mrbgems/mruby-method/.travis.yml b/mrbgems/mruby-method/.travis.yml new file mode 100644 index 000000000..d7422d568 --- /dev/null +++ b/mrbgems/mruby-method/.travis.yml @@ -0,0 +1,17 @@ +language: c +compiler: + - gcc + - clang +before_install: + - sudo apt-get -qq update +install: + - sudo apt-get -qq install rake bison git gperf +before_script: + - cd ../ + - git clone https://github.com/mruby/mruby.git + - cd mruby + - cp -fp ../mruby-method/.travis_build_config.rb build_config.rb +script: + - ruby minirake all test +notifications: + email: false diff --git a/mrbgems/mruby-method/.travis_build_config.rb b/mrbgems/mruby-method/.travis_build_config.rb new file mode 100644 index 000000000..769b98a1b --- /dev/null +++ b/mrbgems/mruby-method/.travis_build_config.rb @@ -0,0 +1,6 @@ +MRuby::Build.new do |conf| + toolchain :gcc + enable_debug + conf.gembox 'default' + conf.gem '../mruby-method' +end diff --git a/mrbgems/mruby-method/README.md b/mrbgems/mruby-method/README.md new file mode 100644 index 000000000..dae6c0108 --- /dev/null +++ b/mrbgems/mruby-method/README.md @@ -0,0 +1,77 @@ +mruby-method +=== + +[![Build Status](https://travis-ci.org/ksss/mruby-method.svg)](https://travis-ci.org/ksss/mruby-method) + +A implementetion of class **Method** and **UnboundMethod** for mruby + +```ruby +p Enumerable.instance_method(:find_all).source_location +#=> ["mruby/mruby/mrblib/enum.rb", 148] +``` + +![https://raw.githubusercontent.com/ksss/mruby-method/master/find_all.png](https://raw.githubusercontent.com/ksss/mruby-method/master/find_all.png) + +# Installation + +in build_config.rb + +```ruby +MRuby::Build.new do |conf| + enable_debug + + conf.gem :mgem => "mruby-method" + # or + conf.gem :github => "ksss/mruby-method" +end +``` + +# Note + +`source_location` method need this configuration in build_config.rb + +```ruby +MRuby::Build.new do |conf| + enable_debug +end +``` + +# Supported Methods + +## Kernel + +- `Kernel#method` +- `Kernel#singleton_method` + +## Module + +- `Module#instance_method` + +## Method class + +- `Method#name` +- `Method#call` +- `Method#super_method` +- `Method#arity` +- `Method#unbind` +- `Method#[]` +- `Method#owner` +- `Method#receiver` +- `Method#parameters` +- `Method#source_location` +- `Method#to_proc` + +## UnboundMethod class + +- `UnboundMethod#name` +- `UnboundMethod#bind` +- `UnboundMethod#super_method` +- `UnboundMethod#arity` +- `UnboundMethod#owner` +- `UnboundMethod#parameters` +- `UnboundMethod#source_location` + +# See also + +- https://ruby-doc.org/core-2.3.3/Method.html +- https://ruby-doc.org/core-2.3.3/UnboundMethod.html diff --git a/mrbgems/mruby-method/find_all.png b/mrbgems/mruby-method/find_all.png new file mode 100644 index 0000000000000000000000000000000000000000..b09b91ee862281e0deffd095b70e6cb008cbc113 GIT binary patch literal 59921 zcmbTdby$>d-|mZwf`E#EbTf1cNVjx%NQsnmcS%bN2uPRI&>&p`(%sz*9nuWBFMiK@ z*LvRAYahqHIr!(EVVL`hZ+y=43Q?4oc!7eCf`EYVLP}Cp83Ex@5BT*&eg^LR$0g1zuw+@&9cm6s^=L)7w3&98!7PPzEqFH8`I{* z!+wN}k6qX(Y)WDX6^M0N-3T`7o+9L7r$|Cy2s54#)|PQ|iMV}g~ zREf{|b*WfLU*8JC7f~VkjSbrhQj(_#Q_IL=bqMJ78M;2!C5mk}WQAWdgb=BS56ncA; zo@n`^%s}7`dWWLi5 zem%lBCa9LgN4*_k@wQexrJ)Yn5RKfBIC16nRx(WKL`5MQs8jxi$I%%_>v>PwZJU!R zaWa;*X2dg6&F5{2Ys9l&k`kW(P3ay9ZYE%0C_rxaQ?&BYdJQf4y=3C6-1s;)4yOK? z_IPte|GmUyY$BSlj#W4AqfEouT0VWj#Ao4sn18~}JC}EkBMBoIF-*k6uMFcF`@cxe z@EHc%A7^!b@~~fd96RvjoFwcRN8BTsQ(&%Zbj;%>aCllbamA>v;?cs0Fg*rZ~!Nz@VD z2nuATEBLj%2cf}jdDKN5wU`Hd*j>uFyK!3*rIJ&=H~Ipt6r^-bX$RTciGu8K_j<@0=2JI zt)e{EtQ7^vBiZa;eDs}bjdoojwzWJTzG@OVstvVqfE)T?cr8WQjmvXp&qYBciKh

cH6C^*}vWvx2AX%?Y;i)_<4sS9n{Y} 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 LlT{V@VEn%Th%2yW literal 0 HcmV?d00001 diff --git a/mrbgems/mruby-method/mrbgem.rake b/mrbgems/mruby-method/mrbgem.rake new file mode 100644 index 000000000..dca0c3af8 --- /dev/null +++ b/mrbgems/mruby-method/mrbgem.rake @@ -0,0 +1,7 @@ +MRuby::Gem::Specification.new('mruby-method') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + spec.summary = 'Method and UnboundMethod class' + + spec.add_dependency('mruby-proc-ext', :core => 'mruby-proc-ext') +end diff --git a/mrbgems/mruby-method/mrblib/kernel.rb b/mrbgems/mruby-method/mrblib/kernel.rb new file mode 100644 index 000000000..b2ebd45ea --- /dev/null +++ b/mrbgems/mruby-method/mrblib/kernel.rb @@ -0,0 +1,9 @@ +module Kernel + def singleton_method(name) + m = method(name) + if m.owner != singleton_class + raise NameError, "undefined method `#{name}' for class `#{singleton_class}'" + end + m + end +end diff --git a/mrbgems/mruby-method/mrblib/method.rb b/mrbgems/mruby-method/mrblib/method.rb new file mode 100644 index 000000000..5de0afdf7 --- /dev/null +++ b/mrbgems/mruby-method/mrblib/method.rb @@ -0,0 +1,20 @@ +class Method + def to_proc + m = self + lambda { |*args, &b| + m.call(*args, &b) + } + end + + def owner + @owner + end + + def receiver + @recv + end + + def name + @name + end +end diff --git a/mrbgems/mruby-method/mrblib/unbound_method.rb b/mrbgems/mruby-method/mrblib/unbound_method.rb new file mode 100644 index 000000000..1d3acf3fa --- /dev/null +++ b/mrbgems/mruby-method/mrblib/unbound_method.rb @@ -0,0 +1,9 @@ +class UnboundMethod + def owner + @owner + end + + def name + @name + end +end diff --git a/mrbgems/mruby-method/src/method.c b/mrbgems/mruby-method/src/method.c new file mode 100644 index 000000000..a40faa5ef --- /dev/null +++ b/mrbgems/mruby-method/src/method.c @@ -0,0 +1,423 @@ +#include "mruby.h" +#include "mruby/array.h" +#include "mruby/data.h" +#include "mruby/class.h" +#include "mruby/variable.h" +#include "mruby/proc.h" +#include "mruby/string.h" +#include + +static struct RObject * +method_object_alloc(mrb_state *mrb, struct RClass *mclass) +{ + return (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mclass); +} + +static mrb_value +unbound_method_bind(mrb_state *mrb, mrb_value self) +{ + struct RObject *me; + mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@owner")); + mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@name")); + mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "proc")); + mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@klass")); + mrb_value recv; + + mrb_get_args(mrb, "o", &recv); + + if (mrb_type(owner) != MRB_TT_MODULE && + mrb_class_ptr(owner) != mrb_obj_class(mrb, recv) && + !mrb_obj_is_kind_of(mrb, recv, mrb_class_ptr(owner))) { + if (mrb_type(owner) == MRB_TT_SCLASS) { + mrb_raise(mrb, E_TYPE_ERROR, "singleton method called for a different object"); + } else { + const char *s = mrb_class_name(mrb, mrb_class_ptr(owner)); + mrb_raisef(mrb, E_TYPE_ERROR, "bind argument must be an instance of %S", mrb_str_new_static(mrb, s, strlen(s))); + } + } + me = method_object_alloc(mrb, mrb_class_get(mrb, "Method")); + mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@owner"), owner); + mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@recv"), recv); + mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@name"), name); + mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "proc"), proc); + mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@klass"), klass); + + return mrb_obj_value(me); +} + +#define IV_GET(value, name) mrb_iv_get(mrb, value, mrb_intern_lit(mrb, name)) +static mrb_value +method_eql(mrb_state *mrb, mrb_value self) +{ + mrb_value other, receiver, orig_proc, other_proc; + struct RClass *owner, *klass; + struct RProc *orig_rproc, *other_rproc; + + mrb_get_args(mrb, "o", &other); + if (!mrb_obj_is_instance_of(mrb, other, mrb_class(mrb, self))) + return mrb_false_value(); + + if (mrb_class(mrb, self) != mrb_class(mrb, other)) + return mrb_false_value(); + + klass = mrb_class_ptr(IV_GET(self, "@klass")); + if (klass != mrb_class_ptr(IV_GET(other, "@klass"))) + return mrb_false_value(); + + owner = mrb_class_ptr(IV_GET(self, "@owner")); + if (owner != mrb_class_ptr(IV_GET(other, "@owner"))) + return mrb_false_value(); + + receiver = IV_GET(self, "@recv"); + if (!mrb_obj_equal(mrb, receiver, IV_GET(other, "@recv"))) + return mrb_false_value(); + + orig_proc = IV_GET(self, "proc"); + other_proc = IV_GET(other, "proc"); + if (mrb_nil_p(orig_proc) && mrb_nil_p(other_proc)) { + if (mrb_symbol(IV_GET(self, "@name")) == mrb_symbol(IV_GET(other, "@name"))) + return mrb_true_value(); + else + return mrb_false_value(); + } + + if (mrb_nil_p(orig_proc)) + return mrb_false_value(); + if (mrb_nil_p(other_proc)) + return mrb_false_value(); + + orig_rproc = mrb_proc_ptr(orig_proc); + other_rproc = mrb_proc_ptr(other_proc); + if (MRB_PROC_CFUNC_P(orig_rproc)) { + if (!MRB_PROC_CFUNC_P(other_rproc)) + return mrb_false_value(); + if (orig_rproc->body.func != other_rproc->body.func) + return mrb_false_value(); + } + else { + if (MRB_PROC_CFUNC_P(other_rproc)) + return mrb_false_value(); + if (orig_rproc->body.irep != other_rproc->body.irep) + return mrb_false_value(); + } + + return mrb_true_value(); +} + +#undef IV_GET + +static mrb_value +method_call(mrb_state *mrb, mrb_value self) +{ + mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "proc")); + mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@name")); + mrb_value recv = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@recv")); + struct RClass *owner = mrb_class_ptr(mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@owner"))); + mrb_int argc, i; + mrb_value *argv, ret, block; + mrb_sym orig_mid; + + mrb_get_args(mrb, "*&", &argv, &argc, &block); + orig_mid = mrb->c->ci->mid; + mrb->c->ci->mid = mrb_symbol(name); + if (mrb_nil_p(proc)) { + mrb_value *missing_argv = (mrb_value*)alloca(sizeof(mrb_value) * (argc + 1)); + missing_argv[0] = name; + for(i = 0; i < argc; i++) { + missing_argv[i + 1] = argv[i]; + } + ret = mrb_funcall_argv(mrb, recv, mrb_intern_lit(mrb, "method_missing"), argc + 1, missing_argv); + } + else if (!mrb_nil_p(block)) { + /* + workaround since `mrb_yield_with_class` does not support passing block as parameter + need new API that initializes `mrb->c->stack[argc+1]` with block passed by argument + */ + ret = mrb_funcall_with_block(mrb, recv, mrb_symbol(name), argc, argv, block); + } + else { + ret = mrb_yield_with_class(mrb, proc, argc, argv, recv, owner); + } + mrb->c->ci->mid = orig_mid; + return ret; +} + +static mrb_value +method_unbind(mrb_state *mrb, mrb_value self) +{ + struct RObject *ume; + mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@owner")); + mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@name")); + mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "proc")); + mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@klass")); + + ume = method_object_alloc(mrb, mrb_class_get(mrb, "UnboundMethod")); + mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "@owner"), owner); + mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "@recv"), mrb_nil_value()); + mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "@name"), name); + mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "proc"), proc); + mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "@klass"), klass); + + return mrb_obj_value(ume); +} + +static struct RProc * +method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid) +{ + mrb_method_t m = mrb_method_search_vm(mrb, cp, mid); + if (MRB_METHOD_UNDEF_P(m)) + return NULL; + if (MRB_METHOD_PROC_P(m)) + return MRB_METHOD_PROC(m); + return mrb_proc_new_cfunc(mrb, MRB_METHOD_FUNC(m)); +} + +static mrb_value +method_super_method(mrb_state *mrb, mrb_value self) +{ + mrb_value recv = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@recv")); + mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@klass")); + mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@owner")); + mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@name")); + struct RClass *super, *rklass; + struct RProc *proc; + struct RObject *me; + + switch (mrb_type(klass)) { + case MRB_TT_SCLASS: + super = mrb_class_ptr(klass)->super->super; + break; + case MRB_TT_ICLASS: + super = mrb_class_ptr(klass)->super; + break; + default: + super = mrb_class_ptr(owner)->super; + break; + } + + proc = method_search_vm(mrb, &super, mrb_symbol(name)); + if (!proc) + return mrb_nil_value(); + + rklass = super; + while (super->tt == MRB_TT_ICLASS) + super = super->c; + + me = method_object_alloc(mrb, mrb_obj_class(mrb, self)); + mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@owner"), mrb_obj_value(super)); + mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@recv"), recv); + mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@name"), name); + mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "proc"), mrb_obj_value(proc)); + mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@klass"), mrb_obj_value(rklass)); + + return mrb_obj_value(me); +} + +static mrb_value +method_arity(mrb_state *mrb, mrb_value self) +{ + mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "proc")); + struct RProc *rproc; + struct RClass *orig; + mrb_value ret; + + if (mrb_nil_p(proc)) + return mrb_fixnum_value(-1); + + rproc = mrb_proc_ptr(proc); + orig = rproc->c; + rproc->c = mrb->proc_class; + ret = mrb_funcall(mrb, proc, "arity", 0); + rproc->c = orig; + return ret; +} + +static mrb_value +method_source_location(mrb_state *mrb, mrb_value self) +{ + mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "proc")); + struct RProc *rproc; + struct RClass *orig; + mrb_value ret; + + if (mrb_nil_p(proc)) + return mrb_nil_value(); + + rproc = mrb_proc_ptr(proc); + orig = rproc->c; + rproc->c = mrb->proc_class; + ret = mrb_funcall(mrb, proc, "source_location", 0); + rproc->c = orig; + return ret; +} + +static mrb_value +method_parameters(mrb_state *mrb, mrb_value self) +{ + mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "proc")); + struct RProc *rproc; + struct RClass *orig; + mrb_value ret; + + if (mrb_nil_p(proc)) { + mrb_value rest = mrb_symbol_value(mrb_intern_lit(mrb, "rest")); + mrb_value arest = mrb_ary_new_from_values(mrb, 1, &rest); + return mrb_ary_new_from_values(mrb, 1, &arest); + } + + rproc = mrb_proc_ptr(proc); + orig = rproc->c; + rproc->c = mrb->proc_class; + ret = mrb_funcall(mrb, proc, "parameters", 0); + rproc->c = orig; + return ret; +} + +static mrb_value +method_to_s(mrb_state *mrb, mrb_value self) +{ + mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@owner")); + mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@klass")); + mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@name")); + mrb_value str = mrb_str_new_lit(mrb, "#<"); + struct RClass *rklass; + + mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, self)); + mrb_str_cat_lit(mrb, str, ": "); + rklass = mrb_class_ptr(klass); + if (mrb_class_ptr(owner) == rklass) { + mrb_str_cat_str(mrb, str, mrb_funcall(mrb, owner, "to_s", 0)); + mrb_str_cat_lit(mrb, str, "#"); + mrb_str_cat_str(mrb, str, mrb_funcall(mrb, name, "to_s", 0)); + } + else { + mrb_str_cat_cstr(mrb, str, mrb_class_name(mrb, rklass)); + mrb_str_cat_lit(mrb, str, "("); + mrb_str_cat_str(mrb, str, mrb_funcall(mrb, owner, "to_s", 0)); + mrb_str_cat_lit(mrb, str, ")#"); + mrb_str_cat_str(mrb, str, mrb_funcall(mrb, name, "to_s", 0)); + } + mrb_str_cat_lit(mrb, str, ">"); + return str; +} + +static void +mrb_search_method_owner(mrb_state *mrb, struct RClass *c, mrb_value obj, mrb_sym name, struct RClass **owner, struct RProc **proc, mrb_bool unbound) +{ + mrb_value ret; + const char *s; + + *owner = c; + *proc = method_search_vm(mrb, owner, name); + if (!*proc) { + if (unbound) { + goto name_error; + } + if (!mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "respond_to_missing?"))) { + goto name_error; + } + ret = mrb_funcall(mrb, obj, "respond_to_missing?", 2, mrb_symbol_value(name), mrb_true_value()); + if (!mrb_test(ret)) { + goto name_error; + } + *owner = c; + } + + while ((*owner)->tt == MRB_TT_ICLASS) + *owner = (*owner)->c; + + return; + +name_error: + s = mrb_class_name(mrb, c); + mrb_raisef( + mrb, E_NAME_ERROR, + "undefined method `%S' for class `%S'", + mrb_sym2str(mrb, name), + mrb_str_new_static(mrb, s, strlen(s)) + ); +} + +static mrb_value +mrb_kernel_method(mrb_state *mrb, mrb_value self) +{ + struct RClass *owner; + struct RProc *proc; + struct RObject *me; + mrb_sym name; + + mrb_get_args(mrb, "n", &name); + + mrb_search_method_owner(mrb, mrb_class(mrb, self), self, name, &owner, &proc, FALSE); + + me = method_object_alloc(mrb, mrb_class_get(mrb, "Method")); + mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@owner"), mrb_obj_value(owner)); + mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@recv"), self); + mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@name"), mrb_symbol_value(name)); + mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "proc"), proc ? mrb_obj_value(proc) : mrb_nil_value()); + mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@klass"), mrb_obj_value(mrb_class(mrb, self))); + + return mrb_obj_value(me); +} + +static mrb_value +mrb_module_instance_method(mrb_state *mrb, mrb_value self) +{ + struct RClass *owner; + struct RProc *proc; + struct RObject *ume; + mrb_sym name; + + mrb_get_args(mrb, "n", &name); + + mrb_search_method_owner(mrb, mrb_class_ptr(self), self, name, &owner, &proc, TRUE); + + ume = method_object_alloc(mrb, mrb_class_get(mrb, "UnboundMethod")); + mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "@owner"), mrb_obj_value(owner)); + mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "@recv"), mrb_nil_value()); + mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "@name"), mrb_symbol_value(name)); + mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "proc"), proc ? mrb_obj_value(proc) : mrb_nil_value()); + mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "@klass"), self); + + return mrb_obj_value(ume); +} + +void +mrb_mruby_method_gem_init(mrb_state* mrb) +{ + struct RClass *unbound_method = mrb_define_class(mrb, "UnboundMethod", mrb->object_class); + struct RClass *method = mrb_define_class(mrb, "Method", mrb->object_class); + + mrb_undef_class_method(mrb, unbound_method, "new"); + mrb_define_method(mrb, unbound_method, "bind", unbound_method_bind, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, unbound_method, "super_method", method_super_method, MRB_ARGS_NONE()); + mrb_define_method(mrb, unbound_method, "==", method_eql, MRB_ARGS_REQ(1)); + mrb_alias_method(mrb, unbound_method, mrb_intern_lit(mrb, "eql?"), mrb_intern_lit(mrb, "==")); + mrb_define_method(mrb, unbound_method, "to_s", method_to_s, MRB_ARGS_NONE()); + mrb_define_method(mrb, unbound_method, "inspect", method_to_s, MRB_ARGS_NONE()); + mrb_define_method(mrb, unbound_method, "arity", method_arity, MRB_ARGS_NONE()); + mrb_define_method(mrb, unbound_method, "source_location", method_source_location, MRB_ARGS_NONE()); + mrb_define_method(mrb, unbound_method, "parameters", method_parameters, MRB_ARGS_NONE()); + + mrb_undef_class_method(mrb, method, "new"); + mrb_define_method(mrb, method, "==", method_eql, MRB_ARGS_REQ(1)); + mrb_alias_method(mrb, method, mrb_intern_lit(mrb, "eql?"), mrb_intern_lit(mrb, "==")); + mrb_define_method(mrb, method, "to_s", method_to_s, MRB_ARGS_NONE()); + mrb_define_method(mrb, method, "inspect", method_to_s, MRB_ARGS_NONE()); + mrb_define_method(mrb, method, "call", method_call, MRB_ARGS_ANY()); + mrb_alias_method(mrb, method, mrb_intern_lit(mrb, "[]"), mrb_intern_lit(mrb, "call")); + mrb_define_method(mrb, method, "unbind", method_unbind, MRB_ARGS_NONE()); + mrb_define_method(mrb, method, "super_method", method_super_method, MRB_ARGS_NONE()); + mrb_define_method(mrb, method, "arity", method_arity, MRB_ARGS_NONE()); + mrb_define_method(mrb, method, "source_location", method_source_location, MRB_ARGS_NONE()); + mrb_define_method(mrb, method, "parameters", method_parameters, MRB_ARGS_NONE()); + + mrb_define_method(mrb, mrb->kernel_module, "method", mrb_kernel_method, MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, mrb->module_class, "instance_method", mrb_module_instance_method, MRB_ARGS_REQ(1)); +} + +void +mrb_mruby_method_gem_final(mrb_state* mrb) +{ +} diff --git a/mrbgems/mruby-method/test/method.rb b/mrbgems/mruby-method/test/method.rb new file mode 100644 index 000000000..b229a4560 --- /dev/null +++ b/mrbgems/mruby-method/test/method.rb @@ -0,0 +1,425 @@ +class Base + def foo() :base end +end + +class Derived < Base + def foo() :derived end +end + +class Interpreter + attr_accessor :ret + + def do_a() @ret += "there, "; end + def do_d() @ret += "Hello "; end + def do_e() @ret += "!\n"; end + def do_v() @ret += "Dave"; end + Dispatcher = { + "a" => instance_method(:do_a), + "d" => instance_method(:do_d), + "e" => instance_method(:do_e), + "v" => instance_method(:do_v) + } + def interpret(string) + @ret = "" + string.each_char {|b| Dispatcher[b].bind(self).call } + end +end + +assert 'demo' do + interpreter = Interpreter.new + interpreter.interpret('dave') + assert_equal "Hello there, Dave!\n", interpreter.ret +end + +assert 'Method#arity' do + Class.new { + attr_accessor :done + def initialize; @done = false; end + def m0() end + def m1(a) end + def m2(a, b) end + def mo1(a = nil, &b) end + def mo2(a, b = nil) end + def mo3(*a) end + def mo4(a, *b, &c) end + def mo5(a, *b, c) end + def mo6(a, *b, c, &d) end + def mo7(a, b = nil, *c, d, &e) end + def ma1((a), &b) nil && a end + + def run + assert_equal(0, method(:m0).arity) + assert_equal(1, method(:m1).arity) + assert_equal(2, method(:m2).arity) + assert_equal(-1, method(:mo1).arity) + assert_equal(-2, method(:mo2).arity) + assert_equal(-1, method(:mo3).arity) + assert_equal(-2, method(:mo4).arity) + assert_equal(-3, method(:mo5).arity) + assert_equal(-3, method(:mo6).arity) + assert_equal(-3, method(:mo7).arity) + assert_equal(1, method(:ma1).arity) + + assert_equal(-1, method(:__send__).arity) + assert_equal(-1, method(:nothing).arity) + end + + def respond_to_missing?(m, b) + m == :nothing + end + }.new.run +end + +assert 'Method and UnboundMethod should not be have a `new` method' do + assert_raise(NoMethodError){ Method.new } + assert_raise(NoMethodError){ UnboundMethod.new } +end + +assert 'instance' do + assert_kind_of Method, 1.method(:+) + assert_kind_of UnboundMethod, Fixnum.instance_method(:+) +end + +assert 'Method#call' do + assert_equal 3, 1.method(:+).call(2) + assert_equal "ab", "a".method(:+)["b"] + klass = Class.new { + def foo; 42; end + } + klass2 = Class.new(klass) { + def foo; super; end + } + assert_equal 42, klass2.new.method(:foo).call + + i = Class.new { + def bar + yield 3 + end + }.new + assert_raise(LocalJumpError) { i.method(:bar).call } + assert_equal 3, i.method(:bar).call { |i| i } +end + +assert 'Method#call for regression' do + obj = BasicObject.new + def obj.foo + :ok + end + assert_equal :ok, Kernel.instance_method(:send).bind(obj).call(:foo), "https://github.com/ksss/mruby-method/issues/4" +end + +assert 'Method#call with undefined method' do + c = Class.new { + attr_accessor :m, :argv + def respond_to_missing?(m, b) + m == :foo + end + + def method_missing(m, *argv) + @m = m + @argv = argv + super + end + } + cc = c.new + assert_raise(NameError) { cc.method(:nothing) } + assert_kind_of Method, cc.method(:foo) + assert_raise(NoMethodError) { cc.method(:foo).call(:arg1, :arg2) } + assert_equal :foo, cc.m + assert_equal [:arg1, :arg2], cc.argv + + cc = c.new + m = cc.method(:foo) + c.class_eval do + def foo + :ng + end + end + assert_raise(NoMethodError) { m.call(:arg1, :arg2) } +end + +assert 'Method#source_location' do + skip if proc{}.source_location.nil? + + filename = __FILE__ + klass = Class.new + + lineno = __LINE__ + 1 + klass.define_method(:find_me_if_you_can) {} + assert_equal [filename, lineno], klass.new.method(:find_me_if_you_can).source_location + + lineno = __LINE__ + 1 + klass.define_singleton_method(:s_find_me_if_you_can) {} + assert_equal [filename, lineno], klass.method(:s_find_me_if_you_can).source_location + + klass = Class.new { def respond_to_missing?(m, b); m == :nothing; end } + assert_nil klass.new.method(:nothing).source_location +end + +assert 'UnboundMethod#source_location' do + skip if proc{}.source_location.nil? + + filename = __FILE__ + klass = Class.new { + def respond_to_missing?(m, b) + m == :nothing + end + } + + lineno = __LINE__ + 1 + klass.define_method(:find_me_if_you_can) {} + assert_equal [filename, lineno], klass.instance_method(:find_me_if_you_can).source_location + assert_nil klass.new.method(:nothing).unbind.source_location +end + +assert 'Method#parameters' do + klass = Class.new { + def foo(a, b=nil, *c) end + def respond_to_missing?(m, b) + m == :missing + end + } + assert_equal [[:req, :a], [:opt, :b], [:rest, :c]], klass.new.method(:foo).parameters + assert_equal [[:rest]], klass.new.method(:missing).parameters +end + +assert 'UnboundMethod#parameters' do + klass = Class.new { + def foo(a, b=nil, *c) end + def respond_to_missing?(m, b) + m == :nothing + end + } + assert_equal [[:req, :a], [:opt, :b], [:rest, :c]], klass.instance_method(:foo).parameters + assert_equal [[:rest]], klass.new.method(:nothing).unbind.parameters +end + +assert 'Method#to_proc' do + m = 3.method(:+) + assert_kind_of Proc, m.to_proc + assert_equal 7, m.call(4) + + o = Object.new + def o.foo(a, b=nil, *c) + [a, b, c] + end + assert_equal [:bar, nil, []], o.method(:foo).to_proc.call(:bar) +# We can fix this issue but leave until the problem +# assert_equal o.method(:foo).arity, o.method(:foo).to_proc.arity + + def o.bar + yield 39 + end + assert_equal 42, o.bar(&3.method(:+)) +end + +assert 'to_s' do + o = Object.new + def o.foo; end + m = o.method(:foo) + assert_equal("#", m.unbind.inspect) + + c = Class.new + c.class_eval { def foo; end; } + m = c.new.method(:foo) + assert_equal("#", m.inspect) + m = c.instance_method(:foo) + assert_equal("#", m.inspect) +end + +assert 'owner' do + c = Class.new do + def foo; end + def self.bar; end + end + m = Module.new do + def baz; end + end + c.include(m) + c2 = Class.new(c) + + assert_equal(c, c.instance_method(:foo).owner) + assert_equal(c, c2.instance_method(:foo).owner) + + assert_equal(c, c.new.method(:foo).owner) + assert_equal(c, c2.new.method(:foo).owner) + assert_equal(c.singleton_class, c2.method(:bar).owner) +end + +assert 'owner missing' do + c = Class.new do + def respond_to_missing?(name, bool) + name == :foo + end + end + c2 = Class.new(c) + assert_equal(c, c.new.method(:foo).owner) + assert_equal(c2, c2.new.method(:foo).owner) +end + +assert 'receiver name owner' do + o = Object.new + def o.foo; end + m = o.method(:foo) + assert_equal(o, m.receiver) + assert_equal(:foo, m.name) + assert_equal(class << o; self; end, m.owner) + assert_equal(:foo, m.unbind.name) + assert_equal(class << o; self; end, m.unbind.owner) +end + +assert 'Method#unbind' do + assert_equal(:derived, Derived.new.foo) + um = Derived.new.method(:foo).unbind + assert_kind_of(UnboundMethod, um) + Derived.class_eval do + def foo() :changed end + end + assert_equal(:changed, Derived.new.foo) + assert_equal(:changed, Derived.new.foo{}) + assert_equal(:derived, um.bind(Derived.new).call) + assert_raise(TypeError) do + um.bind(Base.new) + end + + # TODO: + # Block passed method not handled correctly with workaround. + # See comment near `mrb_funcall_with_block` for detail. + # assert_equal(:derived, um.bind(Derived.new).call{}) +end + +assert 'Kernel#method' do + c1 = Class.new { + def foo; :foo; end + } + o = c1.new + assert_kind_of Method, o.method(:foo) + assert_kind_of Method, o.method('foo') + assert_raise(TypeError) { o.method(nil) } + assert_raise(NameError) { o.method('bar') } + assert_raise(NameError) { o.method(:bar) } +end + +assert "Module#instance_method" do + assert_kind_of UnboundMethod, Object.instance_method(:object_id) + assert_raise(NameError) { Object.instance_method(:nothing) } + c = Class.new { + def respond_to_missing?(m, b) + false + end + } + assert_raise(NameError) { c.instance_method(:nothing) } +end + +assert 'Kernel#singleton_method' do + c1 = Class.new { + def foo; :foo; end + } + o = c1.new + def o.bar; :bar; end + assert_kind_of Method, o.method(:foo) + assert_raise(NameError) { o.singleton_method(:foo) } + assert_kind_of Method, o.singleton_method(:bar) + assert_raise(TypeError) { o.singleton_method(nil) } + m = assert_nothing_raised(NameError) { break o.singleton_method(:bar) } + assert_equal(:bar, m.call) +end + +assert 'Method#super_method' do + o = Derived.new + m = o.method(:foo).super_method + assert_equal(Base, m.owner) + assert_true(o.equal? m.receiver) + assert_equal(:foo, m.name) + assert_nil(m.super_method) + + c = Class.new { + def foo; end + } + o = c.new + o.extend Module.new { + def foo; end + } + assert_equal c, o.method(:foo).super_method.owner + assert_equal :foo, o.method(:foo).super_method.name + assert_equal o, o.method(:foo).super_method.receiver +end + +assert 'Method#==' do + o = Object.new + class << o + def foo; end + end + assert_not_equal(o.method(:foo), nil) + m = o.method(:foo) + def m.foo; end + # TODO: assert_not_equal(o.method(:foo), m) + assert_equal(o.method(:foo), o.method(:foo)) + # TODO: assert_false(o.method(:foo).eql? m) + assert_true(o.method(:foo).eql? o.method(:foo)) + + assert_false(0.method(:+) == 1.method(:+)) + assert_false(0.method(:+) == 0.method(:-)) + a = 0.method(:+) + assert_true(a.method(:==) == a.method(:eql?)) +end + +assert "Method#initialize_copy" do + c = Class.new { + def foo + end + }.new + m1 = c.method(:foo) + m2 = m1.clone + assert_equal(m1, m2) +end + +assert 'UnboundMethod#arity' do + c = Class.new { + def foo(a, b) + end + + def respond_to_missing?(m, b) + m == :nothing + end + } + assert_equal 2, c.instance_method(:foo).arity + assert_equal(-1, c.new.method(:nothing).unbind.arity) +end + +assert 'UnboundMethod#==' do + assert_false(Fixnum.instance_method(:+) == Fixnum.instance_method(:-)) + assert_true(Fixnum.instance_method(:+) == Fixnum.instance_method(:+)) + assert_false(Fixnum.instance_method(:+) == Float.instance_method(:+)) + assert_true(UnboundMethod.instance_method(:==) == UnboundMethod.instance_method(:eql?)) +end + +assert 'UnboundMethod#super_method' do + m = Derived.instance_method(:foo) + m = m.super_method + assert_equal(Base.instance_method(:foo), m) + assert_nil(m.super_method) + + m = Object.instance_method(:object_id) + assert_nil(m.super_method) +end + +assert 'UnboundMethod#bind' do + m = Module.new{ def meth() :meth end }.instance_method(:meth) + assert_raise(ArgumentError) { m.bind } + assert_kind_of Method, m.bind(1) + assert_kind_of Method, m.bind(:sym) + assert_kind_of Method, m.bind(Object.new) + assert_equal(:meth, m.bind(1).call) + assert_equal(:meth, m.bind(:sym).call) + assert_equal(:meth, m.bind(Object.new).call) + sc = Class.new { + class << self + def foo + end + end + }.singleton_class + assert_raise(TypeError) { sc.instance_method(:foo).bind([]) } + assert_raise(TypeError) { Array.instance_method(:each).bind(1) } + assert_kind_of Method, Object.instance_method(:object_id).bind(Object.new) +end