From efe4f30b3982e8ff85a9142933955d6fa0bdebc7 Mon Sep 17 00:00:00 2001 From: ksss Date: Wed, 12 Oct 2016 22:05:14 +0900 Subject: Module#define_method supports proc argument --- src/class.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 47a6c846b..00fc9c12e 100644 --- a/src/class.c +++ b/src/class.c @@ -1773,9 +1773,21 @@ mod_define_method(mrb_state *mrb, mrb_value self) struct RClass *c = mrb_class_ptr(self); struct RProc *p; mrb_sym mid; + mrb_value proc = mrb_undef_value(); mrb_value blk; - mrb_get_args(mrb, "n&", &mid, &blk); + mrb_get_args(mrb, "n|o&", &mid, &proc, &blk); + switch (mrb_type(proc)) { + case MRB_TT_PROC: + blk = proc; + break; + case MRB_TT_UNDEF: + /* ignored */ + break; + default: + mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected Proc)", mrb_obj_value(mrb_obj_class(mrb, proc))); + break; + } if (mrb_nil_p(blk)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); } -- cgit v1.2.3 From e3c8092ccdd3a9991ccd31634e28e9a5a0e29d91 Mon Sep 17 00:00:00 2001 From: Felix Jones Date: Thu, 10 Nov 2016 19:51:56 +0000 Subject: Renamed class_under_defined to class_defined_under --- include/mruby.h | 8 ++++---- src/class.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/class.c') diff --git a/include/mruby.h b/include/mruby.h index 886b15e50..1b227d41a 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -578,10 +578,10 @@ MRB_API struct RClass * mrb_class_get(mrb_state *mrb, const char *name); * example_outer = mrb_define_module(mrb, "ExampleOuter"); * * example_inner = mrb_define_class_under(mrb, example_outer, "ExampleInner", mrb->object_class); - * cd = mrb_class_under_defined(mrb, example_outer, "ExampleInner"); + * cd = mrb_class_defined_under(mrb, example_outer, "ExampleInner"); * - * // If mrb_class_under_defined returns 1 then puts "True" - * // If mrb_class_under_defined returns 0 then puts "False" + * // If mrb_class_defined_under returns 1 then puts "True" + * // If mrb_class_defined_under returns 0 then puts "False" * if (cd == 1){ * puts("True"); * } @@ -595,7 +595,7 @@ MRB_API struct RClass * mrb_class_get(mrb_state *mrb, const char *name); * @param [const char *] name A string representing the name of the inner class. * @return [mrb_bool] A boolean value. */ -MRB_API mrb_bool mrb_class_under_defined(mrb_state *mrb, struct RClass *outer, const char *name); +MRB_API mrb_bool mrb_class_defined_under(mrb_state *mrb, struct RClass *outer, const char *name); /** * Gets a child class. diff --git a/src/class.c b/src/class.c index ed2e5d5ba..b81859ab8 100644 --- a/src/class.c +++ b/src/class.c @@ -272,7 +272,7 @@ mrb_class_defined(mrb_state *mrb, const char *name) } MRB_API mrb_bool -mrb_class_under_defined(mrb_state *mrb, struct RClass *outer, const char *name) +mrb_class_defined_under(mrb_state *mrb, struct RClass *outer, const char *name) { mrb_value sym = mrb_check_intern_cstr(mrb, name); if (mrb_nil_p(sym)) { -- cgit v1.2.3 From 1422e5763005e50ce5f7874910e1a130a12091c9 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 13 Nov 2016 16:12:13 +0900 Subject: move mrb_str_dup() to mrb_class_path; ref #2470 Class#to_s used to return same string repeatedly, that mean you can modify "class name" by modifying the return value from Class#to_s. --- src/class.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 7097a593a..d044cb68a 100644 --- a/src/class.c +++ b/src/class.c @@ -1539,7 +1539,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) } mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path); } - return path; + return mrb_str_dup(mrb, path); } MRB_API struct RClass * -- cgit v1.2.3 From 4f6cce059b317f7e6c1da801fe0edd487985df6e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 15 Nov 2016 04:15:24 +0900 Subject: class/module statement should re-open; fix #3225 --- src/class.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index d044cb68a..e5d60a693 100644 --- a/src/class.c +++ b/src/class.c @@ -174,6 +174,14 @@ MRB_API struct RClass* mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id) { check_if_class_or_module(mrb, outer); + if (mrb_const_defined_at(mrb, outer, id)) { + mrb_value old = mrb_const_get(mrb, outer, id); + + if (mrb_type(old) != MRB_TT_MODULE) { + mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a module", mrb_inspect(mrb, old)); + } + return mrb_class_ptr(old); + } return define_module(mrb, id, mrb_class_ptr(outer)); } @@ -255,6 +263,21 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id s = 0; } check_if_class_or_module(mrb, outer); + if (mrb_const_defined_at(mrb, outer, id)) { + mrb_value old = mrb_const_get(mrb, outer, id); + + if (mrb_type(old) != MRB_TT_CLASS) { + mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class", mrb_inspect(mrb, old)); + } + c = mrb_class_ptr(old); + if (s) { + /* check super class */ + if (mrb_class_real(c->super) != s) { + mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %S", old); + } + } + return c; + } c = define_class(mrb, id, s, mrb_class_ptr(outer)); mrb_class_inherited(mrb, mrb_class_real(c->super), c); -- cgit v1.2.3 From 8e0dc6fa8db54d43d6d0dc4b81751cc3db06ebf0 Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Wed, 16 Nov 2016 15:45:47 +0100 Subject: Correct argument specifications for few methods: - Struct#values_at - Module#define_method - String#chop - String#chop! --- mrbgems/mruby-struct/src/struct.c | 2 +- src/class.c | 2 +- src/string.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/class.c') diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index 1a06e0c12..0ccb7f4cb 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -703,7 +703,7 @@ mrb_mruby_struct_gem_init(mrb_state* mrb) mrb_define_method(mrb, st, "to_a", mrb_struct_to_a, MRB_ARGS_NONE()); mrb_define_method(mrb, st, "values", mrb_struct_to_a, MRB_ARGS_NONE()); mrb_define_method(mrb, st, "to_h", mrb_struct_to_h, MRB_ARGS_NONE()); - mrb_define_method(mrb, st, "values_at", mrb_struct_values_at, MRB_ARGS_NONE()); + mrb_define_method(mrb, st, "values_at", mrb_struct_values_at, MRB_ARGS_ANY()); } void diff --git a/src/class.c b/src/class.c index e5d60a693..4fc81689b 100644 --- a/src/class.c +++ b/src/class.c @@ -2287,7 +2287,7 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, mod, "constants", mrb_mod_constants, MRB_ARGS_OPT(1)); /* 15.2.2.4.24 */ mrb_define_method(mrb, mod, "remove_const", mrb_mod_remove_const, MRB_ARGS_REQ(1)); /* 15.2.2.4.40 */ mrb_define_method(mrb, mod, "const_missing", mrb_mod_const_missing, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, mod, "define_method", mod_define_method, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, mod, "define_method", mod_define_method, MRB_ARGS_ARG(1,1)); mrb_define_method(mrb, mod, "class_variables", mrb_mod_class_variables, MRB_ARGS_NONE()); /* 15.2.2.4.19 */ mrb_define_method(mrb, mod, "===", mrb_mod_eqq, MRB_ARGS_REQ(1)); mrb_define_class_method(mrb, mod, "constants", mrb_mod_s_constants, MRB_ARGS_ANY()); /* 15.2.2.3.1 */ diff --git a/src/string.c b/src/string.c index 15fcc502a..8c46da2bf 100644 --- a/src/string.c +++ b/src/string.c @@ -2723,8 +2723,8 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "capitalize!", mrb_str_capitalize_bang, MRB_ARGS_NONE()); /* 15.2.10.5.8 */ mrb_define_method(mrb, s, "chomp", mrb_str_chomp, MRB_ARGS_ANY()); /* 15.2.10.5.9 */ mrb_define_method(mrb, s, "chomp!", mrb_str_chomp_bang, MRB_ARGS_ANY()); /* 15.2.10.5.10 */ - mrb_define_method(mrb, s, "chop", mrb_str_chop, MRB_ARGS_REQ(1)); /* 15.2.10.5.11 */ - mrb_define_method(mrb, s, "chop!", mrb_str_chop_bang, MRB_ARGS_REQ(1)); /* 15.2.10.5.12 */ + mrb_define_method(mrb, s, "chop", mrb_str_chop, MRB_ARGS_NONE()); /* 15.2.10.5.11 */ + mrb_define_method(mrb, s, "chop!", mrb_str_chop_bang, MRB_ARGS_NONE()); /* 15.2.10.5.12 */ mrb_define_method(mrb, s, "downcase", mrb_str_downcase, MRB_ARGS_NONE()); /* 15.2.10.5.13 */ mrb_define_method(mrb, s, "downcase!", mrb_str_downcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.14 */ mrb_define_method(mrb, s, "empty?", mrb_str_empty_p, MRB_ARGS_NONE()); /* 15.2.10.5.16 */ -- cgit v1.2.3 From 4cca8bac6bbdab02eba11e6527f793f2e9a5e75d Mon Sep 17 00:00:00 2001 From: Tomasz Dąbrowski Date: Wed, 16 Nov 2016 17:43:55 +0100 Subject: inline structures data type for mruby (MRB_TT_INLINE) (fix #3237) Inline structures have no instance variables, no finalizer, and offer as much space as possible in RBASIC object. This means 24 bytes on 64-bit platforms and 12 bytes on 32-bit platforms. mruby-inline-struct gem is only provided for testing. --- include/mruby/inline.h | 47 +++++++++ include/mruby/value.h | 3 +- mrbgems/default.gembox | 3 + mrbgems/mruby-inline-struct/mrbgem.rake | 5 + mrbgems/mruby-inline-struct/test/inline.c | 83 ++++++++++++++++ mrbgems/mruby-inline-struct/test/inline.rb | 151 +++++++++++++++++++++++++++++ src/class.c | 20 ++++ src/etc.c | 1 + src/kernel.c | 4 + src/object.c | 4 +- 10 files changed, 318 insertions(+), 3 deletions(-) create mode 100644 include/mruby/inline.h create mode 100644 mrbgems/mruby-inline-struct/mrbgem.rake create mode 100644 mrbgems/mruby-inline-struct/test/inline.c create mode 100644 mrbgems/mruby-inline-struct/test/inline.rb (limited to 'src/class.c') diff --git a/include/mruby/inline.h b/include/mruby/inline.h new file mode 100644 index 000000000..e773aa118 --- /dev/null +++ b/include/mruby/inline.h @@ -0,0 +1,47 @@ +/* +** mruby/inline.h - Inline structures +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRUBY_INLINE_H +#define MRUBY_INLINE_H + +#include "common.h" +#include + +/** + * Inline structures that fit in RVALUE + * + * They cannot have finalizer, and cannot have instance variables. + */ +MRB_BEGIN_DECL + +#define INLINE_DATA_SIZE (sizeof(void*) * 3) + +struct RInline { + MRB_OBJECT_HEADER; + char inline_data[INLINE_DATA_SIZE]; +}; + +#define RINLINE(obj) ((struct RInline*)(mrb_ptr(obj))) +#define INLINE_PTR(obj) (RINLINE(obj)->inline_data) + +MRB_INLINE mrb_int mrb_inline_size() +{ + return INLINE_DATA_SIZE; +} + +MRB_INLINE void* mrb_inline_ptr(mrb_value object) +{ + return INLINE_PTR(object); +} + +MRB_INLINE void mrb_inline_copy(mrb_value dest, mrb_value src) +{ + memcpy(INLINE_PTR(dest), INLINE_PTR(src), INLINE_DATA_SIZE); +} + +MRB_END_DECL + +#endif /* MRUBY_INLINE_H */ diff --git a/include/mruby/value.h b/include/mruby/value.h index 4330b9441..eb3f931e1 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -116,7 +116,8 @@ enum mrb_vtype { MRB_TT_ENV, /* 20 */ MRB_TT_DATA, /* 21 */ MRB_TT_FIBER, /* 22 */ - MRB_TT_MAXDEFINE /* 23 */ + MRB_TT_INLINE, /* 23 */ + MRB_TT_MAXDEFINE /* 24 */ }; #include diff --git a/mrbgems/default.gembox b/mrbgems/default.gembox index dab7230aa..e3bd114f3 100644 --- a/mrbgems/default.gembox +++ b/mrbgems/default.gembox @@ -74,6 +74,9 @@ MRuby::GemBox.new do |conf| # Use class/module extension conf.gem :core => "mruby-class-ext" + # Use inline struct + conf.gem :core => "mruby-inline-struct" + # Use mruby-compiler to build other mrbgems conf.gem :core => "mruby-compiler" end diff --git a/mrbgems/mruby-inline-struct/mrbgem.rake b/mrbgems/mruby-inline-struct/mrbgem.rake new file mode 100644 index 000000000..91ad9f44b --- /dev/null +++ b/mrbgems/mruby-inline-struct/mrbgem.rake @@ -0,0 +1,5 @@ +MRuby::Gem::Specification.new('mruby-inline-struct') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + spec.summary = 'inline structure' +end diff --git a/mrbgems/mruby-inline-struct/test/inline.c b/mrbgems/mruby-inline-struct/test/inline.c new file mode 100644 index 000000000..903c08aca --- /dev/null +++ b/mrbgems/mruby-inline-struct/test/inline.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include + +static mrb_value +inline_test_initialize(mrb_state *mrb, mrb_value self) +{ + char *string = mrb_inline_ptr(self); + mrb_int size = mrb_inline_size(); + mrb_value object; + mrb_get_args(mrb, "o", &object); + + if (mrb_float_p(object)) + { + snprintf(string, size, "float(%.3f)", mrb_float(object)); + } + else if (mrb_fixnum_p(object)) + { + snprintf(string, size, "fixnum(%d)", mrb_fixnum(object)); + } + else if (mrb_string_p(object)) + { + snprintf(string, size, "string(%s)", mrb_string_value_cstr(mrb, &object)); + } + + string[size - 1] = 0; // force NULL at the end + return self; +} + +static mrb_value +inline_test_to_s(mrb_state *mrb, mrb_value self) +{ + return mrb_str_new_cstr(mrb, mrb_inline_ptr(self)); +} + +static mrb_value +inline_test_length(mrb_state *mrb, mrb_value self) +{ + return mrb_fixnum_value(mrb_inline_size()); +} + +static mrb_value +inline_test_test_receive(mrb_state *mrb, mrb_value self) +{ + mrb_value object; + mrb_get_args(mrb, "o", &object); + if (mrb_obj_class(mrb, object) != mrb_class_get(mrb, "InlineStructTest")) + { + mrb_raisef(mrb, E_TYPE_ERROR, "Expected InlineStructTest"); + } + return mrb_bool_value(((char*)mrb_inline_ptr(object))[0] == 's'); +} + +static mrb_value +inline_test_test_receive_direct(mrb_state *mrb, mrb_value self) +{ + char *ptr; + mrb_get_args(mrb, "I", &ptr); + return mrb_bool_value(ptr[0] == 's'); +} + +static mrb_value +inline_test_mutate(mrb_state *mrb, mrb_value self) +{ + char *ptr = mrb_inline_ptr(self); + memcpy(ptr, "mutate", 6); + return mrb_nil_value(); +} + +void mrb_mruby_inline_struct_gem_test(mrb_state *mrb) +{ + struct RClass *cls; + + cls = mrb_define_class(mrb, "InlineStructTest", mrb->object_class); + MRB_SET_INSTANCE_TT(cls, MRB_TT_INLINE); + mrb_define_method(mrb, cls, "initialize", inline_test_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, cls, "to_s", inline_test_to_s, MRB_ARGS_NONE()); + mrb_define_method(mrb, cls, "mutate", inline_test_mutate, MRB_ARGS_NONE()); + mrb_define_class_method(mrb, cls, "length", inline_test_length, MRB_ARGS_NONE()); + mrb_define_class_method(mrb, cls, "test_receive", inline_test_test_receive, MRB_ARGS_REQ(1)); + mrb_define_class_method(mrb, cls, "test_receive_direct", inline_test_test_receive_direct, MRB_ARGS_REQ(1)); +} diff --git a/mrbgems/mruby-inline-struct/test/inline.rb b/mrbgems/mruby-inline-struct/test/inline.rb new file mode 100644 index 000000000..495859232 --- /dev/null +++ b/mrbgems/mruby-inline-struct/test/inline.rb @@ -0,0 +1,151 @@ +## +# InlineStruct Test + +class InlineStructTest + def extra_method + :ok + end + + def test_ivar_set + @var = :ivar + end + + def test_ivar_get + @vat + end +end + +assert('InlineStructTest#dup') do + obj = InlineStructTest.new(1) + assert_equal obj.to_s, 'fixnum(1)' + assert_equal obj.dup.to_s, 'fixnum(1)' +end + +assert('InlineStructTest#clone') do + obj = InlineStructTest.new(1) + assert_equal obj.to_s, 'fixnum(1)' + assert_equal obj.clone.to_s, 'fixnum(1)' +end + +assert('InlineStruct#object_id') do + obj1 = InlineStructTest.new(1) + obj2 = InlineStructTest.new(1) + assert_not_equal obj1, obj2 + assert_not_equal obj1.object_id, obj2.object_id + assert_not_equal obj1.object_id, obj1.dup.object_id + assert_not_equal obj1.object_id, obj1.clone.object_id +end + +assert('InlineStructTest#mutate (dup)') do + obj1 = InlineStructTest.new("foo") + assert_equal obj1.to_s, "string(foo)" + obj2 = obj1.dup + assert_equal obj2.to_s, "string(foo)" + obj1.mutate + assert_equal obj1.to_s, "mutate(foo)" + assert_equal obj2.to_s, "string(foo)" +end + +assert('InlineStructTest#mutate (clone)') do + obj1 = InlineStructTest.new("foo") + assert_equal obj1.to_s, "string(foo)" + obj2 = obj1.clone + assert_equal obj2.to_s, "string(foo)" + obj1.mutate + assert_equal obj1.to_s, "mutate(foo)" + assert_equal obj2.to_s, "string(foo)" +end + +assert('InlineStructTest#test_receive(string)') do + assert_equal InlineStructTest.test_receive(InlineStructTest.new('a')), true +end + +assert('InlineStructTest#test_receive(float)') do + assert_equal InlineStructTest.test_receive(InlineStructTest.new(1.25)), false +end + +assert('InlineStructTest#test_receive(invalid object)') do + assert_raise(TypeError) do + InlineStructTest.test_receive([]) + end +end + +assert('InlineStructTest#test_receive(string)') do + assert_equal InlineStructTest.test_receive_direct(InlineStructTest.new('a')), true +end + +assert('InlineStructTest#test_receive(float)') do + assert_equal InlineStructTest.test_receive_direct(InlineStructTest.new(1.25)), false +end + +assert('InlineStructTest#test_receive(invalid object)') do + assert_raise(TypeError) do + InlineStructTest.test_receive_direct([]) + end +end + +assert('InlineStructTest#extra_method') do + assert_equal InlineStructTest.new(1).extra_method, :ok +end + +assert('InlineStructTest instance variable') do + obj = InlineStructTest.new(1) + assert_raise(ArgumentError) do + obj.test_ivar_set + end + assert_equal obj.test_ivar_get, nil +end + +# 64-bit mode +if InlineStructTest.length == 24 + assert('InlineStructTest length [64 bit]') do + assert_equal InlineStructTest.length, 3 * 8 + end + + assert('InlineStructTest w/float [64 bit]') do + obj = InlineStructTest.new(1.25) + assert_equal obj.to_s, "float(1.250)" + end + + assert('InlineStructTest w/fixnum [64 bit]') do + obj = InlineStructTest.new(42) + assert_equal obj.to_s, "fixnum(42)" + end + + assert('InlineStructTest w/string [64 bit]') do + obj = InlineStructTest.new("hello") + assert_equal obj.to_s, "string(hello)" + end + + assert('InlineStructTest w/long string [64 bit]') do + obj = InlineStructTest.new("this won't fit in 3 * 8 bytes available for the structure") + assert_equal obj.to_s, "string(this won't fit i" + end +end + +# 32-bit mode +if InlineStructTest.length == 12 + assert('InlineStructTest length [32 bit]') do + assert_equal InlineStructTest.length, 3 * 4 + end + + assert('InlineStructTest w/float [32 bit]') do + obj = InlineStructTest.new(1.25) + assert_equal obj.to_s, "float(1.250" + end + + assert('InlineStructTest w/fixnum [32 bit]') do + obj = InlineStructTest.new(42) + assert_equal obj.to_s, "fixnum(42)" + end + + assert('InlineStructTest w/string [32 bit]') do + obj = InlineStructTest.new("hello") + assert_equal obj.to_s, "string(hell" + end + + assert('InlineStructTest w/long string [32 bit]') do + obj = InlineStructTest.new("this won't fit in 3 * 4 bytes available for the structure") + assert_equal obj.to_s, "string(this" + end +end diff --git a/src/class.c b/src/class.c index 4fc81689b..53354d02a 100644 --- a/src/class.c +++ b/src/class.c @@ -14,6 +14,7 @@ #include #include #include +#include KHASH_DEFINE(mt, mrb_sym, struct RProc*, TRUE, kh_int_hash_func, kh_int_hash_equal) @@ -491,6 +492,7 @@ to_sym(mrb_state *mrb, mrb_value ss) b: Boolean [mrb_bool] n: Symbol [mrb_sym] d: Data [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified + I: Inline struct [void*] &: Block [mrb_value] *: rest argument [mrb_value*,mrb_int] Receive the rest of the arguments as an array. |: optional Next argument of '|' and later are optional. @@ -702,6 +704,24 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) } } break; + case 'I': + { + void* *p; + mrb_value ss; + + p = va_arg(ap, void**); + if (i < argc) { + ss = ARGV[arg_i]; + if (mrb_type(ss) != MRB_TT_INLINE) + { + mrb_raisef(mrb, E_TYPE_ERROR, "%S is not inline struct", ss); + } + *p = mrb_inline_ptr(ss); + arg_i++; + i++; + } + } + break; case 'f': { mrb_float *p; diff --git a/src/etc.c b/src/etc.c index 183e2f070..c89549da6 100644 --- a/src/etc.c +++ b/src/etc.c @@ -139,6 +139,7 @@ mrb_obj_id(mrb_value obj) case MRB_TT_EXCEPTION: case MRB_TT_FILE: case MRB_TT_DATA: + case MRB_TT_INLINE: default: return MakeID(mrb_ptr(obj)); } diff --git a/src/kernel.c b/src/kernel.c index df237cd46..4a4b6b414 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -11,6 +11,7 @@ #include #include #include +#include typedef enum { NOEX_PUBLIC = 0x00, @@ -301,6 +302,9 @@ init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj) case MRB_TT_EXCEPTION: mrb_iv_copy(mrb, dest, obj); break; + case MRB_TT_INLINE: + mrb_inline_copy(dest, obj); + break; default: break; diff --git a/src/object.c b/src/object.c index bb1a4ebc4..af66d93d0 100644 --- a/src/object.c +++ b/src/object.c @@ -348,7 +348,7 @@ mrb_check_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const { mrb_value v; - if (mrb_type(val) == type && type != MRB_TT_DATA) return val; + if (mrb_type(val) == type && type != MRB_TT_DATA && type != MRB_TT_INLINE) return val; v = convert_type(mrb, val, tname, method, FALSE); if (mrb_nil_p(v) || mrb_type(v) != type) return mrb_nil_value(); return v; @@ -390,7 +390,7 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t) enum mrb_vtype xt; xt = mrb_type(x); - if ((xt != t) || (xt == MRB_TT_DATA)) { + if ((xt != t) || (xt == MRB_TT_DATA) || (xt == MRB_TT_INLINE)) { while (type->type < MRB_TT_MAXDEFINE) { if (type->type == t) { const char *etype; -- cgit v1.2.3 From 8438792d27bac2a236d5eef9824d36f815c0472f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 17 Nov 2016 17:12:11 +0900 Subject: renamed "inline" to "istruct" to represent inline struct; ref #3251 --- include/mruby/inline.h | 47 ------------------------------- include/mruby/istruct.h | 47 +++++++++++++++++++++++++++++++ include/mruby/value.h | 2 +- mrbgems/mruby-inline-struct/test/inline.c | 40 +++++++++++++------------- src/class.c | 6 ++-- src/etc.c | 2 +- src/kernel.c | 6 ++-- src/object.c | 4 +-- 8 files changed, 77 insertions(+), 77 deletions(-) delete mode 100644 include/mruby/inline.h create mode 100644 include/mruby/istruct.h (limited to 'src/class.c') diff --git a/include/mruby/inline.h b/include/mruby/inline.h deleted file mode 100644 index e773aa118..000000000 --- a/include/mruby/inline.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -** mruby/inline.h - Inline structures -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_INLINE_H -#define MRUBY_INLINE_H - -#include "common.h" -#include - -/** - * Inline structures that fit in RVALUE - * - * They cannot have finalizer, and cannot have instance variables. - */ -MRB_BEGIN_DECL - -#define INLINE_DATA_SIZE (sizeof(void*) * 3) - -struct RInline { - MRB_OBJECT_HEADER; - char inline_data[INLINE_DATA_SIZE]; -}; - -#define RINLINE(obj) ((struct RInline*)(mrb_ptr(obj))) -#define INLINE_PTR(obj) (RINLINE(obj)->inline_data) - -MRB_INLINE mrb_int mrb_inline_size() -{ - return INLINE_DATA_SIZE; -} - -MRB_INLINE void* mrb_inline_ptr(mrb_value object) -{ - return INLINE_PTR(object); -} - -MRB_INLINE void mrb_inline_copy(mrb_value dest, mrb_value src) -{ - memcpy(INLINE_PTR(dest), INLINE_PTR(src), INLINE_DATA_SIZE); -} - -MRB_END_DECL - -#endif /* MRUBY_INLINE_H */ diff --git a/include/mruby/istruct.h b/include/mruby/istruct.h new file mode 100644 index 000000000..293a13788 --- /dev/null +++ b/include/mruby/istruct.h @@ -0,0 +1,47 @@ +/* +** mruby/instruct.h - Inline structures +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRUBY_ISTRUCT_H +#define MRUBY_ISTRUCT_H + +#include "common.h" +#include + +/** + * Inline structures that fit in RVALUE + * + * They cannot have finalizer, and cannot have instance variables. + */ +MRB_BEGIN_DECL + +#define ISTRUCT_DATA_SIZE (sizeof(void*) * 3) + +struct RIstruct { + MRB_OBJECT_HEADER; + char inline_data[ISTRUCT_DATA_SIZE]; +}; + +#define RISTRUCT(obj) ((struct RIstruct*)(mrb_ptr(obj))) +#define ISTRUCT_PTR(obj) (RISTRUCT(obj)->inline_data) + +MRB_INLINE mrb_int mrb_istruct_size() +{ + return ISTRUCT_DATA_SIZE; +} + +MRB_INLINE void* mrb_istruct_ptr(mrb_value object) +{ + return ISTRUCT_PTR(object); +} + +MRB_INLINE void mrb_istruct_copy(mrb_value dest, mrb_value src) +{ + memcpy(ISTRUCT_PTR(dest), ISTRUCT_PTR(src), ISTRUCT_DATA_SIZE); +} + +MRB_END_DECL + +#endif /* MRUBY_ISTRUCT_H */ diff --git a/include/mruby/value.h b/include/mruby/value.h index eb3f931e1..6b29ab273 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -116,7 +116,7 @@ enum mrb_vtype { MRB_TT_ENV, /* 20 */ MRB_TT_DATA, /* 21 */ MRB_TT_FIBER, /* 22 */ - MRB_TT_INLINE, /* 23 */ + MRB_TT_ISTRUCT, /* 23 */ MRB_TT_MAXDEFINE /* 24 */ }; diff --git a/mrbgems/mruby-inline-struct/test/inline.c b/mrbgems/mruby-inline-struct/test/inline.c index 903c08aca..49ef31d00 100644 --- a/mrbgems/mruby-inline-struct/test/inline.c +++ b/mrbgems/mruby-inline-struct/test/inline.c @@ -1,13 +1,13 @@ #include #include #include -#include +#include static mrb_value -inline_test_initialize(mrb_state *mrb, mrb_value self) +istruct_test_initialize(mrb_state *mrb, mrb_value self) { - char *string = mrb_inline_ptr(self); - mrb_int size = mrb_inline_size(); + char *string = mrb_istruct_ptr(self); + mrb_int size = mrb_istruct_size(); mrb_value object; mrb_get_args(mrb, "o", &object); @@ -29,19 +29,19 @@ inline_test_initialize(mrb_state *mrb, mrb_value self) } static mrb_value -inline_test_to_s(mrb_state *mrb, mrb_value self) +istruct_test_to_s(mrb_state *mrb, mrb_value self) { - return mrb_str_new_cstr(mrb, mrb_inline_ptr(self)); + return mrb_str_new_cstr(mrb, mrb_istruct_ptr(self)); } static mrb_value -inline_test_length(mrb_state *mrb, mrb_value self) +istruct_test_length(mrb_state *mrb, mrb_value self) { - return mrb_fixnum_value(mrb_inline_size()); + return mrb_fixnum_value(mrb_istruct_size()); } static mrb_value -inline_test_test_receive(mrb_state *mrb, mrb_value self) +istruct_test_test_receive(mrb_state *mrb, mrb_value self) { mrb_value object; mrb_get_args(mrb, "o", &object); @@ -49,11 +49,11 @@ inline_test_test_receive(mrb_state *mrb, mrb_value self) { mrb_raisef(mrb, E_TYPE_ERROR, "Expected InlineStructTest"); } - return mrb_bool_value(((char*)mrb_inline_ptr(object))[0] == 's'); + return mrb_bool_value(((char*)mrb_istruct_ptr(object))[0] == 's'); } static mrb_value -inline_test_test_receive_direct(mrb_state *mrb, mrb_value self) +istruct_test_test_receive_direct(mrb_state *mrb, mrb_value self) { char *ptr; mrb_get_args(mrb, "I", &ptr); @@ -61,9 +61,9 @@ inline_test_test_receive_direct(mrb_state *mrb, mrb_value self) } static mrb_value -inline_test_mutate(mrb_state *mrb, mrb_value self) +istruct_test_mutate(mrb_state *mrb, mrb_value self) { - char *ptr = mrb_inline_ptr(self); + char *ptr = mrb_istruct_ptr(self); memcpy(ptr, "mutate", 6); return mrb_nil_value(); } @@ -73,11 +73,11 @@ void mrb_mruby_inline_struct_gem_test(mrb_state *mrb) struct RClass *cls; cls = mrb_define_class(mrb, "InlineStructTest", mrb->object_class); - MRB_SET_INSTANCE_TT(cls, MRB_TT_INLINE); - mrb_define_method(mrb, cls, "initialize", inline_test_initialize, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, cls, "to_s", inline_test_to_s, MRB_ARGS_NONE()); - mrb_define_method(mrb, cls, "mutate", inline_test_mutate, MRB_ARGS_NONE()); - mrb_define_class_method(mrb, cls, "length", inline_test_length, MRB_ARGS_NONE()); - mrb_define_class_method(mrb, cls, "test_receive", inline_test_test_receive, MRB_ARGS_REQ(1)); - mrb_define_class_method(mrb, cls, "test_receive_direct", inline_test_test_receive_direct, MRB_ARGS_REQ(1)); + MRB_SET_INSTANCE_TT(cls, MRB_TT_ISTRUCT); + mrb_define_method(mrb, cls, "initialize", istruct_test_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, cls, "to_s", istruct_test_to_s, MRB_ARGS_NONE()); + mrb_define_method(mrb, cls, "mutate", istruct_test_mutate, MRB_ARGS_NONE()); + mrb_define_class_method(mrb, cls, "length", istruct_test_length, MRB_ARGS_NONE()); + mrb_define_class_method(mrb, cls, "test_receive", istruct_test_test_receive, MRB_ARGS_REQ(1)); + mrb_define_class_method(mrb, cls, "test_receive_direct", istruct_test_test_receive_direct, MRB_ARGS_REQ(1)); } diff --git a/src/class.c b/src/class.c index 53354d02a..d02253c57 100644 --- a/src/class.c +++ b/src/class.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include KHASH_DEFINE(mt, mrb_sym, struct RProc*, TRUE, kh_int_hash_func, kh_int_hash_equal) @@ -712,11 +712,11 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) p = va_arg(ap, void**); if (i < argc) { ss = ARGV[arg_i]; - if (mrb_type(ss) != MRB_TT_INLINE) + if (mrb_type(ss) != MRB_TT_ISTRUCT) { mrb_raisef(mrb, E_TYPE_ERROR, "%S is not inline struct", ss); } - *p = mrb_inline_ptr(ss); + *p = mrb_istruct_ptr(ss); arg_i++; i++; } diff --git a/src/etc.c b/src/etc.c index c89549da6..e0810d589 100644 --- a/src/etc.c +++ b/src/etc.c @@ -139,7 +139,7 @@ mrb_obj_id(mrb_value obj) case MRB_TT_EXCEPTION: case MRB_TT_FILE: case MRB_TT_DATA: - case MRB_TT_INLINE: + case MRB_TT_ISTRUCT: default: return MakeID(mrb_ptr(obj)); } diff --git a/src/kernel.c b/src/kernel.c index 4a4b6b414..8b1ef80a0 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include typedef enum { NOEX_PUBLIC = 0x00, @@ -302,8 +302,8 @@ init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj) case MRB_TT_EXCEPTION: mrb_iv_copy(mrb, dest, obj); break; - case MRB_TT_INLINE: - mrb_inline_copy(dest, obj); + case MRB_TT_ISTRUCT: + mrb_istruct_copy(dest, obj); break; default: diff --git a/src/object.c b/src/object.c index af66d93d0..392432b0f 100644 --- a/src/object.c +++ b/src/object.c @@ -348,7 +348,7 @@ mrb_check_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const { mrb_value v; - if (mrb_type(val) == type && type != MRB_TT_DATA && type != MRB_TT_INLINE) return val; + if (mrb_type(val) == type && type != MRB_TT_DATA && type != MRB_TT_ISTRUCT) return val; v = convert_type(mrb, val, tname, method, FALSE); if (mrb_nil_p(v) || mrb_type(v) != type) return mrb_nil_value(); return v; @@ -390,7 +390,7 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t) enum mrb_vtype xt; xt = mrb_type(x); - if ((xt != t) || (xt == MRB_TT_DATA) || (xt == MRB_TT_INLINE)) { + if ((xt != t) || (xt == MRB_TT_DATA) || (xt == MRB_TT_ISTRUCT)) { while (type->type < MRB_TT_MAXDEFINE) { if (type->type == t) { const char *etype; -- cgit v1.2.3 From 22f550405449faf5bb424f04a52835376add2ae2 Mon Sep 17 00:00:00 2001 From: Bouke van der Bijl Date: Mon, 14 Nov 2016 17:57:43 -0500 Subject: Fix segfault on remove_method with invalid argument Reported by https://hackerone.com/jpenalbae --- src/class.c | 2 +- test/t/class.rb | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index d02253c57..d120f1fec 100644 --- a/src/class.c +++ b/src/class.c @@ -2068,7 +2068,7 @@ mrb_mod_remove_method(mrb_state *mrb, mrb_value mod) mrb_get_args(mrb, "*", &argv, &argc); while (argc--) { - remove_method(mrb, mod, mrb_symbol(*argv)); + remove_method(mrb, mod, to_sym(mrb, *argv)); argv++; } return mod; diff --git a/test/t/class.rb b/test/t/class.rb index 7bcaaf90d..597999d3e 100644 --- a/test/t/class.rb +++ b/test/t/class.rb @@ -401,3 +401,12 @@ assert('class with non-class/module outer raises TypeError') do assert_raise(TypeError) { class 0::C1; end } assert_raise(TypeError) { class []::C2; end } end + +assert("remove_method doesn't segfault if the passed in argument isn't a symbol") do + klass = Class.new + assert_raise(TypeError) { klass.remove_method nil } + assert_raise(TypeError) { klass.remove_method 123 } + assert_raise(TypeError) { klass.remove_method 1.23 } + assert_raise(NameError) { klass.remove_method "hello" } + assert_raise(TypeError) { klass.remove_method Class.new } +end -- cgit v1.2.3 From 2bb47addadb3eda796520837c21d694c8d6e3320 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 30 Nov 2016 10:36:17 +0900 Subject: Prohibit instantiation of immediate objects --- src/class.c | 3 +++ src/numeric.c | 3 +++ src/object.c | 4 ++++ src/symbol.c | 3 +++ 4 files changed, 13 insertions(+) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index d120f1fec..bac1d2984 100644 --- a/src/class.c +++ b/src/class.c @@ -1348,6 +1348,9 @@ mrb_instance_alloc(mrb_state *mrb, mrb_value cv) mrb_raise(mrb, E_TYPE_ERROR, "can't create instance of singleton class"); if (ttype == 0) ttype = MRB_TT_OBJECT; + if (ttype <= MRB_TT_CPTR) { + mrb_raisef(mrb, E_TYPE_ERROR, "can't create instance of %S", cv); + } o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c); return mrb_obj_value(o); } diff --git a/src/numeric.c b/src/numeric.c index c86373318..25a411de8 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef MRB_USE_FLOAT #define trunc(f) truncf(f) @@ -1265,6 +1266,7 @@ mrb_init_numeric(mrb_state *mrb) /* Integer Class */ integer = mrb_define_class(mrb, "Integer", numeric); /* 15.2.8 */ + MRB_SET_INSTANCE_TT(integer, MRB_TT_FIXNUM); mrb_undef_class_method(mrb, integer, "new"); mrb_define_method(mrb, integer, "to_i", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.24 */ mrb_define_method(mrb, integer, "to_int", int_to_i, MRB_ARGS_NONE()); @@ -1291,6 +1293,7 @@ mrb_init_numeric(mrb_state *mrb) /* Float Class */ mrb->float_class = fl = mrb_define_class(mrb, "Float", numeric); /* 15.2.9 */ + MRB_SET_INSTANCE_TT(fl, MRB_TT_FLOAT); mrb_undef_class_method(mrb, fl, "new"); mrb_define_method(mrb, fl, "+", flo_plus, MRB_ARGS_REQ(1)); /* 15.2.9.3.1 */ mrb_define_method(mrb, fl, "-", flo_minus, MRB_ARGS_REQ(1)); /* 15.2.9.3.2 */ diff --git a/src/object.c b/src/object.c index c61feb342..f76ee68a2 100644 --- a/src/object.c +++ b/src/object.c @@ -8,6 +8,7 @@ #include #include #include +#include MRB_API mrb_bool mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2) @@ -265,6 +266,7 @@ mrb_init_object(mrb_state *mrb) struct RClass *f; mrb->nil_class = n = mrb_define_class(mrb, "NilClass", mrb->object_class); + MRB_SET_INSTANCE_TT(n, MRB_TT_TRUE); mrb_undef_class_method(mrb, n, "new"); mrb_define_method(mrb, n, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.4.3.1 */ mrb_define_method(mrb, n, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.4.3.2 */ @@ -274,6 +276,7 @@ mrb_init_object(mrb_state *mrb) mrb_define_method(mrb, n, "inspect", nil_inspect, MRB_ARGS_NONE()); mrb->true_class = t = mrb_define_class(mrb, "TrueClass", mrb->object_class); + MRB_SET_INSTANCE_TT(t, MRB_TT_TRUE); mrb_undef_class_method(mrb, t, "new"); mrb_define_method(mrb, t, "&", true_and, MRB_ARGS_REQ(1)); /* 15.2.5.3.1 */ mrb_define_method(mrb, t, "^", true_xor, MRB_ARGS_REQ(1)); /* 15.2.5.3.2 */ @@ -282,6 +285,7 @@ mrb_init_object(mrb_state *mrb) mrb_define_method(mrb, t, "inspect", true_to_s, MRB_ARGS_NONE()); mrb->false_class = f = mrb_define_class(mrb, "FalseClass", mrb->object_class); + MRB_SET_INSTANCE_TT(f, MRB_TT_TRUE); mrb_undef_class_method(mrb, f, "new"); mrb_define_method(mrb, f, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.6.3.1 */ mrb_define_method(mrb, f, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.6.3.2 */ diff --git a/src/symbol.c b/src/symbol.c index 25ae132e1..a3ab05c85 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -10,6 +10,7 @@ #include #include #include +#include /* ------------------------------------------------------ */ typedef struct symbol_name { @@ -481,6 +482,8 @@ mrb_init_symbol(mrb_state *mrb) struct RClass *sym; mrb->symbol_class = sym = mrb_define_class(mrb, "Symbol", mrb->object_class); /* 15.2.11 */ + MRB_SET_INSTANCE_TT(sym, MRB_TT_SYMBOL); + mrb_undef_class_method(mrb, sym, "new"); mrb_define_method(mrb, sym, "===", sym_equal, MRB_ARGS_REQ(1)); /* 15.2.11.3.1 */ mrb_define_method(mrb, sym, "id2name", mrb_sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.2 */ -- cgit v1.2.3 From ac561a52f583ce154a27622642a37a7a386cbcd9 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sun, 4 Dec 2016 10:41:01 +0900 Subject: Add symbol type check for Module#undef_method --- src/class.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index bac1d2984..e724dbb91 100644 --- a/src/class.c +++ b/src/class.c @@ -1817,7 +1817,7 @@ mrb_mod_undef(mrb_state *mrb, mrb_value mod) mrb_get_args(mrb, "*", &argv, &argc); while (argc--) { - undef_method(mrb, c, mrb_symbol(*argv)); + undef_method(mrb, c, to_sym(mrb, *argv)); argv++; } return mrb_nil_value(); -- cgit v1.2.3 From 1164463a7c21699cfee2e0fb610ae9931b830cc0 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 12 Dec 2016 01:05:07 +0900 Subject: freeze classes/modules; ref #3340 --- src/class.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index e724dbb91..de68087cb 100644 --- a/src/class.c +++ b/src/class.c @@ -370,6 +370,12 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RPro MRB_CLASS_ORIGIN(c); h = c->mt; + if (MRB_FROZEN_P(c)) { + if (c->tt == MRB_TT_MODULE) + mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen module"); + else + mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen class"); + } if (!h) h = c->mt = kh_init(mt, mrb); k = kh_put(mt, mrb, h, mid); kh_value(h, k) = p; -- cgit v1.2.3 From 9cef2654025e6646b1d0ff259086fc9eb02fff84 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 12 Dec 2016 10:34:21 +0900 Subject: should not try to set classpath for frozen classes; ref #3340 --- src/class.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index de68087cb..fed259b5b 100644 --- a/src/class.c +++ b/src/class.c @@ -1589,7 +1589,9 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) name = mrb_sym2name_len(mrb, sym, &len); path = mrb_str_new(mrb, name, len); } - mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path); + if (!MRB_FROZEN_P(c)) { + mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path); + } } return mrb_str_dup(mrb, path); } -- cgit v1.2.3 From 44edc51612536a9e23dabf7c87afc3996efde027 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 11 Jan 2017 09:53:31 +0900 Subject: Raises Exception if raising exception class is redefined close #3384 This issue was reported by https://hackerone.com/brakhane --- include/mruby.h | 44 ++++++++++++++++++++++++++------------------ src/class.c | 14 ++++++++++++++ 2 files changed, 40 insertions(+), 18 deletions(-) (limited to 'src/class.c') diff --git a/include/mruby.h b/include/mruby.h index 76a028ad4..99d06146f 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -607,6 +607,14 @@ MRB_API mrb_bool mrb_class_defined(mrb_state *mrb, const char *name); */ MRB_API struct RClass * mrb_class_get(mrb_state *mrb, const char *name); +/** + * Gets a exception class. + * @param [mrb_state*] mrb The current mruby state. + * @param [const char *] name The name of the class. + * @return [struct RClass *] A reference to the class. +*/ +MRB_API struct RClass * mrb_exc_get(mrb_state *mrb, const char *name); + /** * Returns an mrb_bool. True if inner class was defined, and false if the inner class was not defined. * @@ -1091,23 +1099,23 @@ MRB_API void mrb_print_error(mrb_state *mrb); + those E_* macros requires mrb_state* variable named mrb. + exception objects obtained from those macros are local to mrb */ -#define E_RUNTIME_ERROR (mrb_class_get(mrb, "RuntimeError")) -#define E_TYPE_ERROR (mrb_class_get(mrb, "TypeError")) -#define E_ARGUMENT_ERROR (mrb_class_get(mrb, "ArgumentError")) -#define E_INDEX_ERROR (mrb_class_get(mrb, "IndexError")) -#define E_RANGE_ERROR (mrb_class_get(mrb, "RangeError")) -#define E_NAME_ERROR (mrb_class_get(mrb, "NameError")) -#define E_NOMETHOD_ERROR (mrb_class_get(mrb, "NoMethodError")) -#define E_SCRIPT_ERROR (mrb_class_get(mrb, "ScriptError")) -#define E_SYNTAX_ERROR (mrb_class_get(mrb, "SyntaxError")) -#define E_LOCALJUMP_ERROR (mrb_class_get(mrb, "LocalJumpError")) -#define E_REGEXP_ERROR (mrb_class_get(mrb, "RegexpError")) -#define E_SYSSTACK_ERROR (mrb_class_get(mrb, "SystemStackError")) - -#define E_NOTIMP_ERROR (mrb_class_get(mrb, "NotImplementedError")) -#define E_FLOATDOMAIN_ERROR (mrb_class_get(mrb, "FloatDomainError")) - -#define E_KEY_ERROR (mrb_class_get(mrb, "KeyError")) +#define E_RUNTIME_ERROR (mrb_exc_get(mrb, "RuntimeError")) +#define E_TYPE_ERROR (mrb_exc_get(mrb, "TypeError")) +#define E_ARGUMENT_ERROR (mrb_exc_get(mrb, "ArgumentError")) +#define E_INDEX_ERROR (mrb_exc_get(mrb, "IndexError")) +#define E_RANGE_ERROR (mrb_exc_get(mrb, "RangeError")) +#define E_NAME_ERROR (mrb_exc_get(mrb, "NameError")) +#define E_NOMETHOD_ERROR (mrb_exc_get(mrb, "NoMethodError")) +#define E_SCRIPT_ERROR (mrb_exc_get(mrb, "ScriptError")) +#define E_SYNTAX_ERROR (mrb_exc_get(mrb, "SyntaxError")) +#define E_LOCALJUMP_ERROR (mrb_exc_get(mrb, "LocalJumpError")) +#define E_REGEXP_ERROR (mrb_exc_get(mrb, "RegexpError")) +#define E_SYSSTACK_ERROR (mrb_exc_get(mrb, "SystemStackError")) + +#define E_NOTIMP_ERROR (mrb_exc_get(mrb, "NotImplementedError")) +#define E_FLOATDOMAIN_ERROR (mrb_exc_get(mrb, "FloatDomainError")) + +#define E_KEY_ERROR (mrb_exc_get(mrb, "KeyError")) MRB_API mrb_value mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg); MRB_API mrb_value mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv); @@ -1160,7 +1168,7 @@ MRB_API mrb_value mrb_fiber_yield(mrb_state *mrb, mrb_int argc, const mrb_value * * @mrbgem mruby-fiber */ -#define E_FIBER_ERROR (mrb_class_get(mrb, "FiberError")) +#define E_FIBER_ERROR (mrb_exc_get(mrb, "FiberError")) /* memory pool implementation */ typedef struct mrb_pool mrb_pool; diff --git a/src/class.c b/src/class.c index fed259b5b..cb7bdfddd 100644 --- a/src/class.c +++ b/src/class.c @@ -317,6 +317,20 @@ mrb_class_get(mrb_state *mrb, const char *name) return mrb_class_get_under(mrb, mrb->object_class, name); } +MRB_API struct RClass * +mrb_exc_get(mrb_state *mrb, const char *name) +{ + struct RClass *exc = mrb_class_get_under(mrb, mrb->object_class, name); + struct RClass *e = exc; + + while (e) { + if (e == mrb->eException_class) + return exc; + e = e->super; + } + return mrb->eException_class; +} + MRB_API struct RClass * mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name) { -- cgit v1.2.3 From 38acb9ec36bdd56123e6680885499fbf7f729f21 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 12 Jan 2017 21:43:23 +0900 Subject: Kernel#initialize should not break existing mt; fix #3397 This issue was reported by https://hackerone.com/icanthack The solution is suggested by @clayton-shopify. --- src/class.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index cb7bdfddd..45827f5ba 100644 --- a/src/class.c +++ b/src/class.c @@ -915,7 +915,9 @@ boot_defclass(mrb_state *mrb, struct RClass *super) static void boot_initmod(mrb_state *mrb, struct RClass *mod) { - mod->mt = kh_init(mt, mrb); + if (!mod->mt) { + mod->mt = kh_init(mt, mrb); + } } static struct RClass* -- cgit v1.2.3 From b3ce364537cf1f745112d6e5acd71f009dcd872f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 24 Jan 2017 17:54:05 +0900 Subject: Outer class may be same as the class; fix #3382 --- src/class.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 45827f5ba..81b312fd0 100644 --- a/src/class.c +++ b/src/class.c @@ -1586,7 +1586,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) if (sym == 0) { return mrb_nil_value(); } - else if (outer && outer != mrb->object_class) { + else if (outer && outer != c && outer != mrb->object_class) { mrb_value base = mrb_class_path(mrb, outer); path = mrb_str_buf_new(mrb, 0); if (mrb_nil_p(base)) { -- cgit v1.2.3 From dd24f9f5cc6cc878ae00cf96ce08ae1486d8c0cb Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 09:25:09 +0900 Subject: Avoid calling hook methods if they are not overridden. --- src/class.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 81b312fd0..84cc08a10 100644 --- a/src/class.c +++ b/src/class.c @@ -240,12 +240,22 @@ mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super) return mrb_define_class_id(mrb, mrb_intern_cstr(mrb, name), super); } +static mrb_value mrb_bob_init(mrb_state *mrb, mrb_value cv); + static void mrb_class_inherited(mrb_state *mrb, struct RClass *super, struct RClass *klass) { + mrb_value s; + mrb_sym mid; + if (!super) super = mrb->object_class; - mrb_funcall(mrb, mrb_obj_value(super), "inherited", 1, mrb_obj_value(klass)); + s = mrb_obj_value(super); + mid = mrb_intern_lit(mrb, "inherited"); + if (!mrb_func_basic_p(mrb, s, mid, mrb_bob_init)) { + mrb_value c = mrb_obj_value(klass); + mrb_funcall_argv(mrb, mrb_obj_value(super), mid, 1, &c); + } } MRB_API struct RClass* @@ -1407,10 +1417,13 @@ MRB_API mrb_value mrb_obj_new(mrb_state *mrb, struct RClass *c, mrb_int argc, const mrb_value *argv) { mrb_value obj; + mrb_sym mid; obj = mrb_instance_alloc(mrb, mrb_obj_value(c)); - mrb_funcall_argv(mrb, obj, mrb_intern_lit(mrb, "initialize"), argc, argv); - + mid = mrb_intern_lit(mrb, "initialize"); + if (!mrb_func_basic_p(mrb, obj, mid, mrb_bob_init)) { + mrb_funcall_argv(mrb, obj, mid, argc, argv); + } return obj; } @@ -1432,13 +1445,17 @@ mrb_class_new_class(mrb_state *mrb, mrb_value cv) mrb_int n; mrb_value super, blk; mrb_value new_class; + mrb_sym mid; n = mrb_get_args(mrb, "|C&", &super, &blk); if (n == 0) { super = mrb_obj_value(mrb->object_class); } new_class = mrb_obj_value(mrb_class_new(mrb, mrb_class_ptr(super))); - mrb_funcall_with_block(mrb, new_class, mrb_intern_lit(mrb, "initialize"), n, &super, blk); + mid = mrb_intern_lit(mrb, "initialize"); + if (!mrb_func_basic_p(mrb, new_class, mid, mrb_bob_init)) { + mrb_funcall_with_block(mrb, new_class, mid, n, &super, blk); + } mrb_class_inherited(mrb, mrb_class_ptr(super), mrb_class_ptr(new_class)); return new_class; } -- cgit v1.2.3 From 3f9450e7b07bea475dc0ceccda55c216a4a8a2c2 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 12:56:27 +0900 Subject: Move BasicObject#method_missing to Kernel#method_missing; ref #3417 More compatibility to CRuby. Updated tests that assume old mruby behavior. --- src/class.c | 72 ------------------------------------------------- src/kernel.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ test/t/nomethoderror.rb | 20 +++++++------- 3 files changed, 82 insertions(+), 82 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 84cc08a10..0b7521e61 100644 --- a/src/class.c +++ b/src/class.c @@ -1486,77 +1486,6 @@ mrb_bob_not(mrb_state *mrb, mrb_value cv) return mrb_bool_value(!mrb_test(cv)); } -void -mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args) -{ - mrb_sym inspect; - mrb_value repr; - - inspect = mrb_intern_lit(mrb, "inspect"); - if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) { - /* method missing in inspect; avoid recursion */ - repr = mrb_any_to_s(mrb, self); - } - else if (mrb_respond_to(mrb, self, inspect) && mrb->c->ci - mrb->c->cibase < 64) { - repr = mrb_funcall_argv(mrb, self, inspect, 0, 0); - if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) { - repr = mrb_any_to_s(mrb, self); - } - } - else { - repr = mrb_any_to_s(mrb, self); - } - - mrb_no_method_error(mrb, name, args, "undefined method '%S' for %S", - mrb_sym2str(mrb, name), repr); -} - -/* 15.3.1.3.30 */ -/* - * call-seq: - * obj.method_missing(symbol [, *args] ) -> result - * - * Invoked by Ruby when obj is sent a message it cannot handle. - * symbol is the symbol for the method called, and args - * are any arguments that were passed to it. By default, the interpreter - * raises an error when this method is called. However, it is possible - * to override the method to provide more dynamic behavior. - * If it is decided that a particular method should not be handled, then - * super should be called, so that ancestors can pick up the - * missing method. - * The example below creates - * a class Roman, which responds to methods with names - * consisting of roman numerals, returning the corresponding integer - * values. - * - * class Roman - * def romanToInt(str) - * # ... - * end - * def method_missing(methId) - * str = methId.id2name - * romanToInt(str) - * end - * end - * - * r = Roman.new - * r.iv #=> 4 - * r.xxiii #=> 23 - * r.mm #=> 2000 - */ -static mrb_value -mrb_bob_missing(mrb_state *mrb, mrb_value mod) -{ - mrb_sym name; - mrb_value *a; - mrb_int alen; - - mrb_get_args(mrb, "n*", &name, &a, &alen); - mrb_method_missing(mrb, name, mod, mrb_ary_new_from_values(mrb, alen, a)); - /* not reached */ - return mrb_nil_value(); -} - MRB_API mrb_bool mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid) { @@ -2306,7 +2235,6 @@ mrb_init_class(mrb_state *mrb) MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS); mrb_define_method(mrb, bob, "initialize", mrb_bob_init, MRB_ARGS_NONE()); mrb_define_method(mrb, bob, "!", mrb_bob_not, MRB_ARGS_NONE()); - mrb_define_method(mrb, bob, "method_missing", mrb_bob_missing, MRB_ARGS_ANY()); /* 15.3.1.3.30 */ mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, MRB_ARGS_OPT(1)); mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, MRB_ARGS_NONE()); /* 15.2.3.3.4 */ diff --git a/src/kernel.c b/src/kernel.c index 02bb3c99b..fd00d0484 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -963,6 +963,77 @@ mrb_obj_remove_instance_variable(mrb_state *mrb, mrb_value self) return val; } +void +mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args) +{ + mrb_sym inspect; + mrb_value repr; + + inspect = mrb_intern_lit(mrb, "inspect"); + if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) { + /* method missing in inspect; avoid recursion */ + repr = mrb_any_to_s(mrb, self); + } + else if (mrb_respond_to(mrb, self, inspect) && mrb->c->ci - mrb->c->cibase < 64) { + repr = mrb_funcall_argv(mrb, self, inspect, 0, 0); + if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) { + repr = mrb_any_to_s(mrb, self); + } + } + else { + repr = mrb_any_to_s(mrb, self); + } + + mrb_no_method_error(mrb, name, args, "undefined method '%S' for %S", + mrb_sym2str(mrb, name), repr); +} + +/* 15.3.1.3.30 */ +/* + * call-seq: + * obj.method_missing(symbol [, *args] ) -> result + * + * Invoked by Ruby when obj is sent a message it cannot handle. + * symbol is the symbol for the method called, and args + * are any arguments that were passed to it. By default, the interpreter + * raises an error when this method is called. However, it is possible + * to override the method to provide more dynamic behavior. + * If it is decided that a particular method should not be handled, then + * super should be called, so that ancestors can pick up the + * missing method. + * The example below creates + * a class Roman, which responds to methods with names + * consisting of roman numerals, returning the corresponding integer + * values. + * + * class Roman + * def romanToInt(str) + * # ... + * end + * def method_missing(methId) + * str = methId.id2name + * romanToInt(str) + * end + * end + * + * r = Roman.new + * r.iv #=> 4 + * r.xxiii #=> 23 + * r.mm #=> 2000 + */ +static mrb_value +mrb_obj_missing(mrb_state *mrb, mrb_value mod) +{ + mrb_sym name; + mrb_value *a; + mrb_int alen; + + mrb_get_args(mrb, "n*", &name, &a, &alen); + mrb_method_missing(mrb, name, mod, mrb_ary_new_from_values(mrb, alen, a)); + /* not reached */ + return mrb_nil_value(); +} + static inline mrb_bool basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub) { @@ -1199,6 +1270,7 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.25 */ mrb_define_method(mrb, krn, "kind_of?", mrb_obj_is_kind_of_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.26 */ mrb_define_method(mrb, krn, "local_variables", mrb_local_variables, MRB_ARGS_NONE()); /* 15.3.1.3.28 */ + mrb_define_method(mrb, krn, "method_missing", mrb_obj_missing, MRB_ARGS_ANY()); /* 15.3.1.3.30 */ mrb_define_method(mrb, krn, "methods", mrb_obj_methods_m, MRB_ARGS_OPT(1)); /* 15.3.1.3.31 */ mrb_define_method(mrb, krn, "nil?", mrb_false, MRB_ARGS_NONE()); /* 15.3.1.3.32 */ mrb_define_method(mrb, krn, "object_id", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.33 */ diff --git a/test/t/nomethoderror.rb b/test/t/nomethoderror.rb index 41a3ba14f..35cbdaee9 100644 --- a/test/t/nomethoderror.rb +++ b/test/t/nomethoderror.rb @@ -21,20 +21,20 @@ assert('NoMethodError#args', '15.2.32.2.1') do end end -assert('Can still raise when BasicObject#method_missing is removed') do +assert('Can still raise when Kernel#method_missing is removed') do assert_raise(NoMethodError) do begin - BasicObject.alias_method(:old_method_missing, :method_missing) - BasicObject.remove_method(:method_missing) + Kernel.alias_method(:old_method_missing, :method_missing) + Kernel.remove_method(:method_missing) 1.__send__(:foo) ensure - BasicObject.alias_method(:method_missing, :old_method_missing) - BasicObject.remove_method(:old_method_missing) + Kernel.alias_method(:method_missing, :old_method_missing) + Kernel.remove_method(:old_method_missing) end end end -assert('Can still call super when BasicObject#method_missing is removed') do +assert('Can still call super when Kernel#method_missing is removed') do assert_raise(NoMethodError) do class A def foo @@ -42,12 +42,12 @@ assert('Can still call super when BasicObject#method_missing is removed') do end end begin - BasicObject.alias_method(:old_method_missing, :method_missing) - BasicObject.remove_method(:method_missing) + Kernel.alias_method(:old_method_missing, :method_missing) + Kernel.remove_method(:method_missing) A.new.foo ensure - BasicObject.alias_method(:method_missing, :old_method_missing) - BasicObject.remove_method(:old_method_missing) + Kernel.alias_method(:method_missing, :old_method_missing) + Kernel.remove_method(:old_method_missing) end end end -- cgit v1.2.3 From 8b4bd3158b365cd1baddc4e9f9e5f770717022cf Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 13:07:53 +0900 Subject: Move #== and #!= to BasicObject; ref #3417 --- src/class.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/kernel.c | 52 +--------------------------------------------------- 2 files changed, 52 insertions(+), 51 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 0b7521e61..21a4d3f20 100644 --- a/src/class.c +++ b/src/class.c @@ -1486,6 +1486,55 @@ mrb_bob_not(mrb_state *mrb, mrb_value cv) return mrb_bool_value(!mrb_test(cv)); } +/* 15.3.1.3.1 */ +/* 15.3.1.3.10 */ +/* 15.3.1.3.11 */ +/* + * call-seq: + * obj == other -> true or false + * obj.equal?(other) -> true or false + * obj.eql?(other) -> true or false + * + * Equality---At the Object level, == returns + * true only if obj and other are the + * same object. Typically, this method is overridden in descendant + * classes to provide class-specific meaning. + * + * Unlike ==, the equal? method should never be + * overridden by subclasses: it is used to determine object identity + * (that is, a.equal?(b) iff a is the same + * object as b). + * + * The eql? method returns true if + * obj and anObject have the same value. Used by + * Hash to test members for equality. For objects of + * class Object, eql? is synonymous with + * ==. Subclasses normally continue this tradition, but + * there are exceptions. Numeric types, for example, + * perform type conversion across ==, but not across + * eql?, so: + * + * 1 == 1.0 #=> true + * 1.eql? 1.0 #=> false + */ +mrb_value +mrb_obj_equal_m(mrb_state *mrb, mrb_value self) +{ + mrb_value arg; + + mrb_get_args(mrb, "o", &arg); + return mrb_bool_value(mrb_obj_equal(mrb, self, arg)); +} + +static mrb_value +mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self) +{ + mrb_value arg; + + mrb_get_args(mrb, "o", &arg); + return mrb_bool_value(!mrb_equal(mrb, self, arg)); +} + MRB_API mrb_bool mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid) { @@ -2235,6 +2284,8 @@ mrb_init_class(mrb_state *mrb) MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS); mrb_define_method(mrb, bob, "initialize", mrb_bob_init, MRB_ARGS_NONE()); mrb_define_method(mrb, bob, "!", mrb_bob_not, MRB_ARGS_NONE()); + mrb_define_method(mrb, bob, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */ + mrb_define_method(mrb, bob, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(1)); mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, MRB_ARGS_OPT(1)); mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, MRB_ARGS_NONE()); /* 15.2.3.3.4 */ diff --git a/src/kernel.c b/src/kernel.c index fd00d0484..e21a99352 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -66,55 +66,6 @@ mrb_obj_inspect(mrb_state *mrb, mrb_value obj) return mrb_any_to_s(mrb, obj); } -/* 15.3.1.3.1 */ -/* 15.3.1.3.10 */ -/* 15.3.1.3.11 */ -/* - * call-seq: - * obj == other -> true or false - * obj.equal?(other) -> true or false - * obj.eql?(other) -> true or false - * - * Equality---At the Object level, == returns - * true only if obj and other are the - * same object. Typically, this method is overridden in descendant - * classes to provide class-specific meaning. - * - * Unlike ==, the equal? method should never be - * overridden by subclasses: it is used to determine object identity - * (that is, a.equal?(b) iff a is the same - * object as b). - * - * The eql? method returns true if - * obj and anObject have the same value. Used by - * Hash to test members for equality. For objects of - * class Object, eql? is synonymous with - * ==. Subclasses normally continue this tradition, but - * there are exceptions. Numeric types, for example, - * perform type conversion across ==, but not across - * eql?, so: - * - * 1 == 1.0 #=> true - * 1.eql? 1.0 #=> false - */ -static mrb_value -mrb_obj_equal_m(mrb_state *mrb, mrb_value self) -{ - mrb_value arg; - - mrb_get_args(mrb, "o", &arg); - return mrb_bool_value(mrb_obj_equal(mrb, self, arg)); -} - -static mrb_value -mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self) -{ - mrb_value arg; - - mrb_get_args(mrb, "o", &arg); - return mrb_bool_value(!mrb_equal(mrb, self, arg)); -} - /* 15.3.1.3.2 */ /* * call-seq: @@ -1227,6 +1178,7 @@ mrb_local_variables(mrb_state *mrb, mrb_value self) return mrb_hash_keys(mrb, vars); } +mrb_value mrb_obj_equal_m(mrb_state *mrb, mrb_value); void mrb_init_kernel(mrb_state *mrb) { @@ -1242,8 +1194,6 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "singleton_class", mrb_singleton_class, MRB_ARGS_NONE()); - mrb_define_method(mrb, krn, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */ - mrb_define_method(mrb, krn, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(1)); mrb_define_method(mrb, krn, "===", mrb_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.2 */ mrb_define_method(mrb, krn, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.3 */ mrb_define_method(mrb, krn, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.4 */ -- cgit v1.2.3 From 3dbda9178834a4e55d884c97677ed2ecf46c2289 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 13:12:05 +0900 Subject: Move #__send__ to BasicObject; ref #3417 --- src/class.c | 1 + src/kernel.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 21a4d3f20..086833eaf 100644 --- a/src/class.c +++ b/src/class.c @@ -2286,6 +2286,7 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, bob, "!", mrb_bob_not, MRB_ARGS_NONE()); mrb_define_method(mrb, bob, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */ mrb_define_method(mrb, bob, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, bob, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.4 */ mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, MRB_ARGS_OPT(1)); mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, MRB_ARGS_NONE()); /* 15.2.3.3.4 */ diff --git a/src/kernel.c b/src/kernel.c index e21a99352..95ebcfbd8 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -1196,7 +1196,6 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "===", mrb_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.2 */ mrb_define_method(mrb, krn, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.3 */ - mrb_define_method(mrb, krn, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.4 */ mrb_define_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.6 */ mrb_define_method(mrb, krn, "class", mrb_obj_class_m, MRB_ARGS_NONE()); /* 15.3.1.3.7 */ mrb_define_method(mrb, krn, "clone", mrb_obj_clone, MRB_ARGS_NONE()); /* 15.3.1.3.8 */ -- cgit v1.2.3 From 612d636b77edd7c0969e8850583aefd895638284 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 13:15:58 +0900 Subject: Move #instance_eval to BasicObject; ref #3417 --- src/class.c | 4 ++++ src/kernel.c | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 086833eaf..f3146ca15 100644 --- a/src/class.c +++ b/src/class.c @@ -2245,6 +2245,9 @@ mrb_mod_module_function(mrb_state *mrb, mrb_value mod) return mod; } +/* implementation of instance_eval */ +mrb_value mrb_obj_instance_eval(mrb_state*, mrb_value); + void mrb_init_class(mrb_state *mrb) { @@ -2287,6 +2290,7 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, bob, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */ mrb_define_method(mrb, bob, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(1)); mrb_define_method(mrb, bob, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.4 */ + mrb_define_method(mrb, bob, "instance_eval", mrb_obj_instance_eval, MRB_ARGS_ANY()); /* 15.3.1.3.18 */ mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, MRB_ARGS_OPT(1)); mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, MRB_ARGS_NONE()); /* 15.2.3.3.4 */ diff --git a/src/kernel.c b/src/kernel.c index 95ebcfbd8..04bcbe6c2 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -489,9 +489,6 @@ mrb_obj_init_copy(mrb_state *mrb, mrb_value self) } -/* implementation of instance_eval */ -mrb_value mrb_obj_instance_eval(mrb_state*, mrb_value); - MRB_API mrb_bool mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c) { @@ -1209,7 +1206,6 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "hash", mrb_obj_hash, MRB_ARGS_NONE()); /* 15.3.1.3.15 */ mrb_define_method(mrb, krn, "initialize_copy", mrb_obj_init_copy, MRB_ARGS_REQ(1)); /* 15.3.1.3.16 */ mrb_define_method(mrb, krn, "inspect", mrb_obj_inspect, MRB_ARGS_NONE()); /* 15.3.1.3.17 */ - mrb_define_method(mrb, krn, "instance_eval", mrb_obj_instance_eval, MRB_ARGS_ANY()); /* 15.3.1.3.18 */ mrb_define_method(mrb, krn, "instance_of?", obj_is_instance_of, MRB_ARGS_REQ(1)); /* 15.3.1.3.19 */ mrb_define_method(mrb, krn, "instance_variable_defined?", mrb_obj_ivar_defined, MRB_ARGS_REQ(1)); /* 15.3.1.3.20 */ mrb_define_method(mrb, krn, "instance_variable_get", mrb_obj_ivar_get, MRB_ARGS_REQ(1)); /* 15.3.1.3.21 */ -- cgit v1.2.3 From 517e9313bf6e6d4697095a9257598915ac857ff3 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 13:19:21 +0900 Subject: Move #__id__ to BasicObject; ref #3417 --- src/class.c | 3 +++ src/kernel.c | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index f3146ca15..0922b3cff 100644 --- a/src/class.c +++ b/src/class.c @@ -2245,6 +2245,8 @@ mrb_mod_module_function(mrb_state *mrb, mrb_value mod) return mod; } +/* implementation of __id__ */ +mrb_value mrb_obj_id_m(mrb_state *mrb, mrb_value self); /* implementation of instance_eval */ mrb_value mrb_obj_instance_eval(mrb_state*, mrb_value); @@ -2289,6 +2291,7 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, bob, "!", mrb_bob_not, MRB_ARGS_NONE()); mrb_define_method(mrb, bob, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */ mrb_define_method(mrb, bob, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, bob, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.3 */ mrb_define_method(mrb, bob, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.4 */ mrb_define_method(mrb, bob, "instance_eval", mrb_obj_instance_eval, MRB_ARGS_ANY()); /* 15.3.1.3.18 */ diff --git a/src/kernel.c b/src/kernel.c index 04bcbe6c2..6cb2e3ad5 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -101,7 +101,7 @@ mrb_equal_m(mrb_state *mrb, mrb_value self) * :name notation, which returns the symbol id of * name. Replaces the deprecated Object#id. */ -static mrb_value +mrb_value mrb_obj_id_m(mrb_state *mrb, mrb_value self) { return mrb_fixnum_value(mrb_obj_id(self)); @@ -1192,7 +1192,6 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "singleton_class", mrb_singleton_class, MRB_ARGS_NONE()); mrb_define_method(mrb, krn, "===", mrb_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.2 */ - mrb_define_method(mrb, krn, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.3 */ mrb_define_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.6 */ mrb_define_method(mrb, krn, "class", mrb_obj_class_m, MRB_ARGS_NONE()); /* 15.3.1.3.7 */ mrb_define_method(mrb, krn, "clone", mrb_obj_clone, MRB_ARGS_NONE()); /* 15.3.1.3.8 */ -- cgit v1.2.3