From 59ea323976557408ba1c5f694213c7a31bbb6e39 Mon Sep 17 00:00:00 2001 From: cremno Date: Fri, 29 May 2015 14:51:48 +0200 Subject: check if outer is a class or module For modules this check didn't exist yet. Also call #inspect. --- src/class.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 3246564ec..35c3aa040 100644 --- a/src/class.c +++ b/src/class.c @@ -131,6 +131,19 @@ mrb_class_outer_module(mrb_state *mrb, struct RClass *c) return mrb_class_ptr(outer); } +static void +check_if_class_or_module(mrb_state *mrb, mrb_value obj) +{ + switch (mrb_type(obj)) { + case MRB_TT_CLASS: + case MRB_TT_SCLASS: + case MRB_TT_MODULE: + return; + default: + mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", mrb_inspect(mrb, obj)); + } +} + static struct RClass* define_module(mrb_state *mrb, mrb_sym name, struct RClass *outer) { @@ -160,6 +173,7 @@ mrb_define_module(mrb_state *mrb, const char *name) MRB_API struct RClass* mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id) { + check_if_class_or_module(mrb, outer); return define_module(mrb, id, mrb_class_ptr(outer)); } @@ -232,15 +246,7 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id else { s = 0; } - switch (mrb_type(outer)) { - case MRB_TT_CLASS: - case MRB_TT_SCLASS: - case MRB_TT_MODULE: - break; - default: - mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", outer); - break; - } + check_if_class_or_module(mrb, outer); 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 9781580c7134fcee7bf5a6d4356bc47593549da8 Mon Sep 17 00:00:00 2001 From: Jared Breeden Date: Mon, 22 Jun 2015 23:19:58 -0700 Subject: Fixes #912 --- src/class.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 35c3aa040..05b549b3e 100644 --- a/src/class.c +++ b/src/class.c @@ -1174,11 +1174,11 @@ mrb_instance_alloc(mrb_state *mrb, mrb_value cv) * call-seq: * class.new(args, ...) -> obj * - * Calls allocate to create a new object of - * class's class, then invokes that object's - * initialize method, passing it args. - * This is the method that ends up getting called whenever - * an object is constructed using .new. + * Creates a new object of class's class, then + * invokes that object's initialize method, + * passing it args. This is the method that ends + * up getting called whenever an object is constructed using + * `.new`. * */ -- cgit v1.2.3 From 25885072858582d3d2f985b405a8e84d58f716e8 Mon Sep 17 00:00:00 2001 From: Franck Verrot Date: Wed, 24 Jun 2015 13:07:07 +0200 Subject: Remove unnecessary backticks. Dr Markus Kuhn published in 1999 an article [1] explaining in details why we shouldn't use the ASCII grave accent (0x60) as a left quotation. Backticks have been used most notably to produce nice-looking LaTeX documents but it doesn't seem to be an issue on modern platforms and for the oldest ones, there are workarounds as mentioned by Dr Kuhn. [1]: https://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html --- include/mruby/compile.h | 4 +- include/mruby/opcode.h | 2 +- mrbgems/mruby-compiler/core/parse.y | 14 +++--- mrbgems/mruby-hash-ext/mrblib/hash.rb | 2 +- mrbgems/mruby-sprintf/src/sprintf.c | 80 +++++++++++++++++------------------ mrbgems/mruby-struct/src/struct.c | 8 ++-- mrblib/array.rb | 2 +- src/class.c | 8 ++-- src/numeric.c | 4 +- src/object.c | 2 +- src/string.c | 6 +-- src/variable.c | 2 +- 12 files changed, 67 insertions(+), 67 deletions(-) (limited to 'src/class.c') diff --git a/include/mruby/compile.h b/include/mruby/compile.h index e20473298..1fb81782d 100644 --- a/include/mruby/compile.h +++ b/include/mruby/compile.h @@ -55,8 +55,8 @@ enum mrb_lex_state_enum { EXPR_CMDARG, /* newline significant, +/- is an operator. */ EXPR_MID, /* newline significant, +/- is an operator. */ EXPR_FNAME, /* ignore newline, no reserved words. */ - EXPR_DOT, /* right after `.' or `::', no reserved words. */ - EXPR_CLASS, /* immediate after `class', no here document. */ + EXPR_DOT, /* right after '.' or '::', no reserved words. */ + EXPR_CLASS, /* immediate after 'class', no here document. */ EXPR_VALUE, /* alike EXPR_BEG but label is disallowed. */ EXPR_MAX_STATE }; diff --git a/include/mruby/opcode.h b/include/mruby/opcode.h index 4774e78c6..9dfa7f75d 100644 --- a/include/mruby/opcode.h +++ b/include/mruby/opcode.h @@ -8,7 +8,7 @@ #define MRUBY_OPCODE_H #define MAXARG_Bx (0xffff) -#define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */ +#define MAXARG_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */ /* instructions: packed 32 bit */ /* ------------------------------- */ diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 5b17649a9..f6a43d32b 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -4204,7 +4204,7 @@ parser_yylex(parser_state *p) } pushback(p, c); if (IS_SPCARG(c)) { - yywarning(p, "`*' interpreted as argument prefix"); + yywarning(p, "'*' interpreted as argument prefix"); c = tSTAR; } else if (IS_BEG()) { @@ -4455,7 +4455,7 @@ parser_yylex(parser_state *p) } pushback(p, c); if (IS_SPCARG(c)) { - yywarning(p, "`&' interpreted as argument prefix"); + yywarning(p, "'&' interpreted as argument prefix"); c = tAMPER; } else if (IS_BEG()) { @@ -4761,7 +4761,7 @@ parser_yylex(parser_state *p) nondigit = c; break; - case '_': /* `_' in number just ignored */ + case '_': /* '_' in number just ignored */ if (nondigit) goto decode_num; nondigit = c; break; @@ -4776,7 +4776,7 @@ parser_yylex(parser_state *p) pushback(p, c); if (nondigit) { trailing_uc: - yyerror_i(p, "trailing `%c' in number", nondigit); + yyerror_i(p, "trailing '%c' in number", nondigit); } tokfix(p); if (is_float) { @@ -5157,10 +5157,10 @@ parser_yylex(parser_state *p) } else if (isdigit(c)) { if (p->bidx == 1) { - yyerror_i(p, "`@%c' is not allowed as an instance variable name", c); + yyerror_i(p, "'@%c' is not allowed as an instance variable name", c); } else { - yyerror_i(p, "`@@%c' is not allowed as a class variable name", c); + yyerror_i(p, "'@@%c' is not allowed as a class variable name", c); } return 0; } @@ -5176,7 +5176,7 @@ parser_yylex(parser_state *p) default: if (!identchar(c)) { - yyerror_i(p, "Invalid char `\\x%02X' in expression", c); + yyerror_i(p, "Invalid char '\\x%02X' in expression", c); goto retry; } diff --git a/mrbgems/mruby-hash-ext/mrblib/hash.rb b/mrbgems/mruby-hash-ext/mrblib/hash.rb index ea5e6bc1b..c970b9d02 100644 --- a/mrbgems/mruby-hash-ext/mrblib/hash.rb +++ b/mrbgems/mruby-hash-ext/mrblib/hash.rb @@ -119,7 +119,7 @@ class Hash # # produces: # - # prog.rb:2:in `fetch': key not found (KeyError) + # prog.rb:2:in 'fetch': key not found (KeyError) # from prog.rb:2 # diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index d88e242c6..de216f69f 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -234,20 +234,20 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv) * ------+-------------------------------------------------------------- * b | Convert argument as a binary number. * | Negative numbers will be displayed as a two's complement - * | prefixed with `..1'. - * B | Equivalent to `b', but uses an uppercase 0B for prefix + * | prefixed with '..1'. + * B | Equivalent to 'b', but uses an uppercase 0B for prefix * | in the alternative format by #. * d | Convert argument as a decimal number. - * i | Identical to `d'. + * i | Identical to 'd'. * o | Convert argument as an octal number. * | Negative numbers will be displayed as a two's complement - * | prefixed with `..7'. - * u | Identical to `d'. + * | prefixed with '..7'. + * u | Identical to 'd'. * x | Convert argument as a hexadecimal number. * | Negative numbers will be displayed as a two's complement - * | prefixed with `..f' (representing an infinite string of + * | prefixed with '..f' (representing an infinite string of * | leading 'ff's). - * X | Equivalent to `x', but uses uppercase letters. + * X | Equivalent to 'x', but uses uppercase letters. * * Field | Float Format * ------+-------------------------------------------------------------- @@ -255,7 +255,7 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv) * | with one digit before the decimal point as [-]d.dddddde[+-]dd. * | The precision specifies the number of digits after the decimal * | point (defaulting to six). - * E | Equivalent to `e', but uses an uppercase E to indicate + * E | Equivalent to 'e', but uses an uppercase E to indicate * | the exponent. * f | Convert floating point argument as [-]ddd.dddddd, * | where the precision specifies the number of digits after @@ -264,11 +264,11 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv) * | if the exponent is less than -4 or greater than or * | equal to the precision, or in dd.dddd form otherwise. * | The precision specifies the number of significant digits. - * G | Equivalent to `g', but use an uppercase `E' in exponent form. + * G | Equivalent to 'g', but use an uppercase 'E' in exponent form. * a | Convert floating point argument as [-]0xh.hhhhp[+-]dd, * | which is consisted from optional sign, "0x", fraction part * | as hexadecimal, "p", and exponential part as decimal. - * A | Equivalent to `a', but use uppercase `X' and `P'. + * A | Equivalent to 'a', but use uppercase 'X' and 'P'. * * Field | Other Format * ------+-------------------------------------------------------------- @@ -287,7 +287,7 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv) * ---------+---------------+----------------------------------------- * space | bBdiouxX | Leave a space at the start of * | aAeEfgG | non-negative numbers. - * | (numeric fmt) | For `o', `x', `X', `b' and `B', use + * | (numeric fmt) | For 'o', 'x', 'X', 'b' and 'B', use * | | a minus sign with absolute value for * | | negative values. * ---------+---------------+----------------------------------------- @@ -297,27 +297,27 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv) * | | sprintf string. * ---------+---------------+----------------------------------------- * # | bBoxX | Use an alternative format. - * | aAeEfgG | For the conversions `o', increase the precision - * | | until the first digit will be `0' if + * | aAeEfgG | For the conversions 'o', increase the precision + * | | until the first digit will be '0' if * | | it is not formatted as complements. - * | | For the conversions `x', `X', `b' and `B' - * | | on non-zero, prefix the result with ``0x'', - * | | ``0X'', ``0b'' and ``0B'', respectively. - * | | For `a', `A', `e', `E', `f', `g', and 'G', + * | | For the conversions 'x', 'X', 'b' and 'B' + * | | on non-zero, prefix the result with "0x", + * | | "0X", "0b" and "0B", respectively. + * | | For 'a', 'A', 'e', 'E', 'f', 'g', and 'G', * | | force a decimal point to be added, * | | even if no digits follow. - * | | For `g' and 'G', do not remove trailing zeros. + * | | For 'g' and 'G', do not remove trailing zeros. * ---------+---------------+----------------------------------------- * + | bBdiouxX | Add a leading plus sign to non-negative * | aAeEfgG | numbers. - * | (numeric fmt) | For `o', `x', `X', `b' and `B', use + * | (numeric fmt) | For 'o', 'x', 'X', 'b' and 'B', use * | | a minus sign with absolute value for * | | negative values. * ---------+---------------+----------------------------------------- * - | all | Left-justify the result of this conversion. * ---------+---------------+----------------------------------------- * 0 (zero) | bBdiouxX | Pad with zeros, not spaces. - * | aAeEfgG | For `o', `x', `X', `b' and `B', radix-1 + * | aAeEfgG | For 'o', 'x', 'X', 'b' and 'B', radix-1 * | (numeric fmt) | is used for negative numbers formatted as * | | complements. * ---------+---------------+----------------------------------------- @@ -328,21 +328,21 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv) * * Examples of flags: * - * # `+' and space flag specifies the sign of non-negative numbers. + * # '+' and space flag specifies the sign of non-negative numbers. * sprintf("%d", 123) #=> "123" * sprintf("%+d", 123) #=> "+123" * sprintf("% d", 123) #=> " 123" * - * # `#' flag for `o' increases number of digits to show `0'. - * # `+' and space flag changes format of negative numbers. + * # '#' flag for 'o' increases number of digits to show '0'. + * # '+' and space flag changes format of negative numbers. * sprintf("%o", 123) #=> "173" * sprintf("%#o", 123) #=> "0173" * sprintf("%+o", -123) #=> "-173" * sprintf("%o", -123) #=> "..7605" * sprintf("%#o", -123) #=> "..7605" * - * # `#' flag for `x' add a prefix `0x' for non-zero numbers. - * # `+' and space flag disables complements for negative numbers. + * # '#' flag for 'x' add a prefix '0x' for non-zero numbers. + * # '+' and space flag disables complements for negative numbers. * sprintf("%x", 123) #=> "7b" * sprintf("%#x", 123) #=> "0x7b" * sprintf("%+x", -123) #=> "-7b" @@ -350,12 +350,12 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv) * sprintf("%#x", -123) #=> "0x..f85" * sprintf("%#x", 0) #=> "0" * - * # `#' for `X' uses the prefix `0X'. + * # '#' for 'X' uses the prefix '0X'. * sprintf("%X", 123) #=> "7B" * sprintf("%#X", 123) #=> "0X7B" * - * # `#' flag for `b' add a prefix `0b' for non-zero numbers. - * # `+' and space flag disables complements for negative numbers. + * # '#' flag for 'b' add a prefix '0b' for non-zero numbers. + * # '+' and space flag disables complements for negative numbers. * sprintf("%b", 123) #=> "1111011" * sprintf("%#b", 123) #=> "0b1111011" * sprintf("%+b", -123) #=> "-1111011" @@ -363,19 +363,19 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv) * sprintf("%#b", -123) #=> "0b..10000101" * sprintf("%#b", 0) #=> "0" * - * # `#' for `B' uses the prefix `0B'. + * # '#' for 'B' uses the prefix '0B'. * sprintf("%B", 123) #=> "1111011" * sprintf("%#B", 123) #=> "0B1111011" * - * # `#' for `e' forces to show the decimal point. + * # '#' for 'e' forces to show the decimal point. * sprintf("%.0e", 1) #=> "1e+00" * sprintf("%#.0e", 1) #=> "1.e+00" * - * # `#' for `f' forces to show the decimal point. + * # '#' for 'f' forces to show the decimal point. * sprintf("%.0f", 1234) #=> "1234" * sprintf("%#.0f", 1234) #=> "1234." * - * # `#' for `g' forces to show the decimal point. + * # '#' for 'g' forces to show the decimal point. * # It also disables stripping lowest zeros. * sprintf("%g", 123.4) #=> "123.4" * sprintf("%#g", 123.4) #=> "123.400" @@ -409,7 +409,7 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv) * * Examples of precisions: * - * # precision for `d', 'o', 'x' and 'b' is + * # precision for 'd', 'o', 'x' and 'b' is * # minimum number of digits <------> * sprintf("%20.8d", 123) #=> " 00000123" * sprintf("%20.8o", 123) #=> " 00000173" @@ -420,8 +420,8 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv) * sprintf("%20.8x", -123) #=> " ..ffff85" * sprintf("%20.8b", -11) #=> " ..110101" * - * # "0x" and "0b" for `#x' and `#b' is not counted for - * # precision but "0" for `#o' is counted. <------> + * # "0x" and "0b" for '#x' and '#b' is not counted for + * # precision but "0" for '#o' is counted. <------> * sprintf("%#20.8d", 123) #=> " 00000123" * sprintf("%#20.8o", 123) #=> " 00000173" * sprintf("%#20.8x", 123) #=> " 0x0000007b" @@ -431,22 +431,22 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv) * sprintf("%#20.8x", -123) #=> " 0x..ffff85" * sprintf("%#20.8b", -11) #=> " 0b..110101" * - * # precision for `e' is number of + * # precision for 'e' is number of * # digits after the decimal point <------> * sprintf("%20.8e", 1234.56789) #=> " 1.23456789e+03" * - * # precision for `f' is number of + * # precision for 'f' is number of * # digits after the decimal point <------> * sprintf("%20.8f", 1234.56789) #=> " 1234.56789000" * - * # precision for `g' is number of + * # precision for 'g' is number of * # significant digits <-------> * sprintf("%20.8g", 1234.56789) #=> " 1234.5679" * * # <-------> * sprintf("%20.8g", 123456789) #=> " 1.2345679e+08" * - * # precision for `s' is + * # precision for 's' is * # maximum number of characters <------> * sprintf("%20.8s", "string test") #=> " string t" * @@ -539,7 +539,7 @@ mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt) if (t >= end) goto sprint_exit; /* end of fmt string */ - p = t + 1; /* skip `%' */ + p = t + 1; /* skip '%' */ width = prec = -1; nextvalue = mrb_undef_value(); diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index d2187a2d1..ce8d8d832 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -114,7 +114,7 @@ mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id) return ptr[i]; } } - mrb_raisef(mrb, E_INDEX_ERROR, "`%S' is not a struct member", mrb_sym2str(mrb, id)); + mrb_raisef(mrb, E_INDEX_ERROR, "'%S' is not a struct member", mrb_sym2str(mrb, id)); return mrb_nil_value(); /* not reached */ } @@ -193,7 +193,7 @@ mrb_struct_set(mrb_state *mrb, mrb_value obj, mrb_value val) return ptr[i] = val; } } - mrb_raisef(mrb, E_INDEX_ERROR, "`%S' is not a struct member", mrb_sym2str(mrb, mid)); + mrb_raisef(mrb, E_INDEX_ERROR, "'%S' is not a struct member", mrb_sym2str(mrb, mid)); return mrb_nil_value(); /* not reached */ } @@ -749,8 +749,8 @@ mrb_struct_values_at(mrb_state *mrb, mrb_value self) * The Struct class is a generator of specific classes, * each one of which is defined to hold a set of variables and their * accessors. In these examples, we'll call the generated class - * ``CustomerClass,'' and we'll show an example instance of that - * class as ``CustomerInst.'' + * "CustomerClass," and we'll show an example instance of that + * class as "CustomerInst." * * In the descriptions that follow, the parameter symbol refers * to a symbol, which is either a quoted string or a diff --git a/mrblib/array.rb b/mrblib/array.rb index 83a42c62d..933f822db 100644 --- a/mrblib/array.rb +++ b/mrblib/array.rb @@ -146,7 +146,7 @@ class Array # equal, then that inequality is the return value. If all the # values found are equal, then the return is based on a # comparison of the array lengths. Thus, two arrays are - # ``equal'' according to Array#<=> if and only if they have + # "equal" according to Array#<=> if and only if they have # the same length and the value of each element is equal to the # value of the corresponding element in the other array. # diff --git a/src/class.c b/src/class.c index 05b549b3e..e9cbc592d 100644 --- a/src/class.c +++ b/src/class.c @@ -212,7 +212,7 @@ MRB_API struct RClass* mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super) { if (!super) { - mrb_warn(mrb, "no super class for `%S', Object assumed", mrb_sym2str(mrb, name)); + mrb_warn(mrb, "no super class for '%S', Object assumed", mrb_sym2str(mrb, name)); } return define_class(mrb, name, super, mrb->object_class); } @@ -311,7 +311,7 @@ mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, s #if 0 if (!super) { - mrb_warn(mrb, "no super class for `%S::%S', Object assumed", + mrb_warn(mrb, "no super class for '%S::%S', Object assumed", mrb_obj_value(outer), mrb_sym2str(mrb, id)); } #endif @@ -1658,7 +1658,7 @@ check_cv_name_str(mrb_state *mrb, mrb_value str) mrb_int len = RSTRING_LEN(str); if (len < 3 || !(s[0] == '@' && s[1] == '@')) { - mrb_name_error(mrb, mrb_intern_str(mrb, str), "`%S' is not allowed as a class variable name", str); + mrb_name_error(mrb, mrb_intern_str(mrb, str), "'%S' is not allowed as a class variable name", str); } } @@ -1846,7 +1846,7 @@ remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid) } } - mrb_name_error(mrb, mid, "method `%S' not defined in %S", + mrb_name_error(mrb, mid, "method '%S' not defined in %S", mrb_sym2str(mrb, mid), mod); } diff --git a/src/numeric.c b/src/numeric.c index 8b6ec4c88..013273232 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -110,8 +110,8 @@ num_div(mrb_state *mrb, mrb_value x) * * Returns a string containing a representation of self. As well as a * fixed or exponential form of the number, the call may return - * ``NaN'', ``Infinity'', and - * ``-Infinity''. + * "NaN", "Infinity", and + * "-Infinity". */ static mrb_value diff --git a/src/object.c b/src/object.c index c5fb74575..f8f41bfe8 100644 --- a/src/object.c +++ b/src/object.c @@ -428,7 +428,7 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t) * Returns a string representing obj. The default * to_s prints the object's class and an encoding of the * object id. As a special case, the top-level object that is the - * initial execution context of Ruby programs returns ``main.'' + * initial execution context of Ruby programs returns "main." */ MRB_API mrb_value diff --git a/src/string.c b/src/string.c index 22a289ade..8df79d4c0 100644 --- a/src/string.c +++ b/src/string.c @@ -1100,7 +1100,7 @@ mrb_str_downcase_bang(mrb_state *mrb, mrb_value str) * * Returns a copy of str with all uppercase letters replaced with their * lowercase counterparts. The operation is locale insensitive---only - * characters ``A'' to ``Z'' are affected. + * characters 'A' to 'Z' are affected. * * "hEllO".downcase #=> "hello" */ @@ -1703,7 +1703,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str) * * If pattern is omitted, the value of $; is used. If * $; is nil (which is the default), str is - * split on whitespace as if ` ' were specified. + * split on whitespace as if ' ' were specified. * * If the limit parameter is omitted, trailing null fields are * suppressed. If limit is a positive number, at most that number of @@ -2211,7 +2211,7 @@ mrb_str_upcase_bang(mrb_state *mrb, mrb_value str) * * Returns a copy of str with all lowercase letters replaced with their * uppercase counterparts. The operation is locale insensitive---only - * characters ``a'' to ``z'' are affected. + * characters 'a' to 'z' are affected. * * "hEllO".upcase #=> "HELLO" */ diff --git a/src/variable.c b/src/variable.c index 3e451df05..1b2ad56a7 100644 --- a/src/variable.c +++ b/src/variable.c @@ -563,7 +563,7 @@ MRB_API void mrb_iv_check(mrb_state *mrb, mrb_sym iv_name) { if (!mrb_iv_p(mrb, iv_name)) { - mrb_name_error(mrb, iv_name, "`%S' is not allowed as an instance variable name", mrb_sym2str(mrb, iv_name)); + mrb_name_error(mrb, iv_name, "'%S' is not allowed as an instance variable name", mrb_sym2str(mrb, iv_name)); } } -- cgit v1.2.3 From 9c311ddc938ad2cc88e4119374e47cd496e15a94 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 13 Jul 2015 07:08:01 +0900 Subject: refactor mrb_bob_missing to share raising NoMethodError code; fix #2878 Note: arguments of mrb_no_method_error() has changed. You need to replace 3rd and 4th argument (say n, argv) to mrb_ary_new_from_values(mrb, n, argv). --- include/mruby/error.h | 2 +- src/class.c | 45 ++++++++++++++++++++++++++------------------- src/error.c | 5 ++--- src/vm.c | 13 +++++++++++-- 4 files changed, 40 insertions(+), 25 deletions(-) (limited to 'src/class.c') diff --git a/include/mruby/error.h b/include/mruby/error.h index 52f6772bd..282be0a24 100644 --- a/include/mruby/error.h +++ b/include/mruby/error.h @@ -24,7 +24,7 @@ MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value st MRB_API mrb_value mrb_make_exception(mrb_state *mrb, int argc, const mrb_value *argv); MRB_API mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc); MRB_API mrb_value mrb_get_backtrace(mrb_state *mrb); -MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_int argc, const mrb_value *argv, const char *fmt, ...); +MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, const char *fmt, ...); /* declaration for fail method */ MRB_API mrb_value mrb_f_raise(mrb_state*, mrb_value); diff --git a/src/class.c b/src/class.c index e9cbc592d..0f9a77b2a 100644 --- a/src/class.c +++ b/src/class.c @@ -1262,6 +1262,31 @@ 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: @@ -1301,27 +1326,9 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod) mrb_sym name; mrb_value *a; mrb_int alen; - mrb_sym inspect; - mrb_value repr; mrb_get_args(mrb, "n*", &name, &a, &alen); - - 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, mod); - } - else if (mrb_respond_to(mrb, mod, inspect) && mrb->c->ci - mrb->c->cibase < 64) { - repr = mrb_funcall_argv(mrb, mod, inspect, 0, 0); - if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) { - repr = mrb_any_to_s(mrb, mod); - } - } - else { - repr = mrb_any_to_s(mrb, mod); - } - - mrb_no_method_error(mrb, name, alen, a, "undefined method '%S' for %S", mrb_sym2str(mrb, name), repr); + mrb_method_missing(mrb, name, mod, mrb_ary_new_from_values(mrb, alen, a)); /* not reached */ return mrb_nil_value(); } diff --git a/src/error.c b/src/error.c index a800f77f9..20c63bd43 100644 --- a/src/error.c +++ b/src/error.c @@ -424,15 +424,14 @@ mrb_sys_fail(mrb_state *mrb, const char *mesg) } MRB_API mrb_noreturn void -mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_int argc, const mrb_value *argv, char const* fmt, ...) +mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, char const* fmt, ...) { mrb_value exc; va_list ap; va_start(ap, fmt); exc = mrb_funcall(mrb, mrb_obj_value(E_NOMETHOD_ERROR), "new", 3, - mrb_vformat(mrb, fmt, ap), mrb_symbol_value(id), - mrb_ary_new_from_values(mrb, argc, argv)); + mrb_vformat(mrb, fmt, ap), mrb_symbol_value(id), args); va_end(ap); mrb_exc_raise(mrb, exc); } diff --git a/src/vm.c b/src/vm.c index 15a3926e3..22ea177e0 100644 --- a/src/vm.c +++ b/src/vm.c @@ -723,6 +723,8 @@ argnum_error(mrb_state *mrb, mrb_int num) #define CALL_MAXARGS 127 +void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args); + MRB_API mrb_value mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep) { @@ -1078,8 +1080,15 @@ RETRY_TRY_BLOCK: m = mrb_method_search_vm(mrb, &c, missing); if (!m) { - mrb_no_method_error(mrb, mid, n, regs+a+1, - "undefined method '%S' for %S", mrb_sym2str(mrb, mid), recv); + mrb_value args; + + if (n == CALL_MAXARGS) { + args = regs[a+1]; + } + else { + args = mrb_ary_new_from_values(mrb, n, regs+a+1); + } + mrb_method_missing(mrb, mid, recv, args); } mid = missing; if (n == CALL_MAXARGS) { -- cgit v1.2.3 From 02474daa14623f3ee24a5235e9b7b88c33d43455 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 13 Jul 2015 11:14:50 +0900 Subject: allow '!' after 'S' specifier of mrb_get_args() that allow nil. thus "S!" means String|nil type. you have to check nil before dereferencing the value. this is added to address #2882 while keeping code simplicity. besides that current #2882 fix lose polymorphism provided by mrb_get_args(). --- src/class.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 0f9a77b2a..8a9fdaca6 100644 --- a/src/class.c +++ b/src/class.c @@ -435,7 +435,7 @@ to_sym(mrb_state *mrb, mrb_value ss) ---------------------------------------------------------------------------------------------- o: Object [mrb_value] C: class/module [mrb_value] - S: String [mrb_value] + S: String [mrb_value] when ! follows the value may be nil A: Array [mrb_value] H: Hash [mrb_value] s: String [char*,mrb_int] Receive two arguments. @@ -525,6 +525,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value *p; p = va_arg(ap, mrb_value*); + if (*format == '!') { + format++; + if (mrb_nil_p(*sp)) { + *p = *sp++; + i++; + break; + } + } if (i < argc) { *p = to_str(mrb, *sp++); i++; -- cgit v1.2.3 From f962890a928b566c0f5ca7fdff5ef4ce19207e65 Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Thu, 9 Jul 2015 23:46:54 +0200 Subject: Implement Module#prepend. --- include/mruby/class.h | 1 + src/class.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++-- test/t/module.rb | 33 +++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 2 deletions(-) (limited to 'src/class.c') diff --git a/include/mruby/class.h b/include/mruby/class.h index 9d5260a24..60310ae9d 100644 --- a/include/mruby/class.h +++ b/include/mruby/class.h @@ -16,6 +16,7 @@ struct RClass { struct iv_tbl *iv; struct kh_mt *mt; struct RClass *super; + struct RClass *origin; }; #define mrb_class_ptr(v) ((struct RClass*)(mrb_ptr(v))) diff --git a/src/class.c b/src/class.c index 8a9fdaca6..3b1ea2321 100644 --- a/src/class.c +++ b/src/class.c @@ -194,6 +194,7 @@ define_class(mrb_state *mrb, mrb_sym name, struct RClass *super, struct RClass * if (mrb_const_defined_at(mrb, mrb_obj_value(outer), name)) { c = class_from_sym(mrb, outer, name); + c = c->origin; if (super && mrb_class_real(c->super) != super) { mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for Class %S (%S not %S)", mrb_sym2str(mrb, name), @@ -763,12 +764,13 @@ boot_defclass(mrb_state *mrb, struct RClass *super) else { c->super = mrb->object_class; } + c->origin = c; c->mt = kh_init(mt, mrb); return c; } -MRB_API void -mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) +MRB_API inline void +include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *m, int search_super) { struct RClass *ins_pos; @@ -782,6 +784,7 @@ mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) } while (p) { if (c != p && p->tt == MRB_TT_CLASS) { + if (!search_super) break; superclass_seen = 1; } else if (p->mt == m->mt) { @@ -810,6 +813,63 @@ mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) } } +MRB_API void +mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) +{ + include_module_at(mrb, c, m, FALSE); +} + +MRB_API void +mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m) +{ + struct RClass *origin; + int changed = 0; + + origin = c->origin; + if (origin == c) { + origin = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, c); + //OBJ_WB_UNPROTECT(origin); /* TODO: conservative shading. Need more survey. */ + origin->super = c->super; + c->super = origin; + c->origin = origin; + origin->mt = c->mt; + c->mt = kh_init(mt, mrb); + } + include_module_at(mrb, c, m, FALSE); // changed = + if (changed) { + //rb_vm_check_redefinition_by_prepend(klass); + } +} + +static mrb_value +mrb_mod_prepend_features(mrb_state *mrb, mrb_value mod) +{ + mrb_value klass; + + mrb_check_type(mrb, mod, MRB_TT_MODULE); + mrb_get_args(mrb, "C", &klass); + mrb_prepend_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod)); + return mod; +} + +static mrb_value +mrb_mod_prepend(mrb_state *mrb, mrb_value klass) +{ + mrb_value *argv; + mrb_int argc, i; + + mrb_get_args(mrb, "*", &argv, &argc); + for (i=0; i Date: Fri, 10 Jul 2015 21:00:14 +0200 Subject: Expose insert position, which should be at origin for include and klass for prepend. --- src/class.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 3b1ea2321..c1d377e86 100644 --- a/src/class.c +++ b/src/class.c @@ -770,11 +770,8 @@ boot_defclass(mrb_state *mrb, struct RClass *super) } MRB_API inline void -include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *m, int search_super) +include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, struct RClass *m, int search_super) { - struct RClass *ins_pos; - - ins_pos = c; while (m) { struct RClass *p = c, *ic; int superclass_seen = 0; @@ -816,7 +813,7 @@ include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *m, int search MRB_API void mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) { - include_module_at(mrb, c, m, FALSE); + include_module_at(mrb, c, c->origin, m, FALSE); } MRB_API void @@ -835,7 +832,7 @@ mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m) origin->mt = c->mt; c->mt = kh_init(mt, mrb); } - include_module_at(mrb, c, m, FALSE); // changed = + include_module_at(mrb, c, c, m, FALSE); // changed = if (changed) { //rb_vm_check_redefinition_by_prepend(klass); } -- cgit v1.2.3 From 2e617e37e134b428ce7a979446cc2d768d1cf2fe Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Fri, 10 Jul 2015 21:14:28 +0200 Subject: origin must be initialized --- src/class.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index c1d377e86..9f21ae395 100644 --- a/src/class.c +++ b/src/class.c @@ -76,6 +76,7 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o) if (o->c->tt == MRB_TT_SCLASS) return; sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class); + sc->origin = sc; sc->mt = 0; sc->iv = 0; if (o->tt == MRB_TT_CLASS) { @@ -799,6 +800,7 @@ include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, stru else { ic->c = m; } + ic->origin = ic; ic->mt = m->mt; ic->iv = m->iv; ic->super = ins_pos->super; @@ -825,6 +827,7 @@ mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m) origin = c->origin; if (origin == c) { origin = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, c); + origin->origin = origin; //OBJ_WB_UNPROTECT(origin); /* TODO: conservative shading. Need more survey. */ origin->super = c->super; c->super = origin; @@ -1547,6 +1550,7 @@ MRB_API struct RClass* mrb_module_new(mrb_state *mrb) { struct RClass *m = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_MODULE, mrb->module_class); + m->origin = m; m->mt = kh_init(mt, mrb); return m; -- cgit v1.2.3 From 97529c2a9a7b75a838234a420bbe2c6dc59c56ba Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Fri, 10 Jul 2015 22:01:07 +0200 Subject: Comment in a refactor to match MRI, but that fails 320 tests. --- src/class.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 9f21ae395..ca4582041 100644 --- a/src/class.c +++ b/src/class.c @@ -776,11 +776,25 @@ include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, stru while (m) { struct RClass *p = c, *ic; int superclass_seen = 0; - + + //if (m->origin != m) + // goto skip; if (c->mt && c->mt == m->mt) { mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected"); } while (p) { + /*if (p->tt == MRB_TT_ICLASS) { + if (!superclass_seen) { + ins_pos = p; // move insert point + } + goto skip; + } else if (p->tt == MRB_TT_CLASS) { + if (p->mt == m->mt) { + if (!search_super) break; + superclass_seen = 1; + } + }*/ + // if (c != p && p->tt == MRB_TT_CLASS) { if (!search_super) break; superclass_seen = 1; -- cgit v1.2.3 From 005cacf18b8ce2cf854872aa8cb803819478a47d Mon Sep 17 00:00:00 2001 From: Corey Powell Date: Sat, 11 Jul 2015 11:15:18 +0200 Subject: Additional patches to make this work --- src/class.c | 129 ++++++++++++++++++++++++++++++++--------------------------- src/kernel.c | 12 ++++++ 2 files changed, 83 insertions(+), 58 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index ca4582041..73e6687c0 100644 --- a/src/class.c +++ b/src/class.c @@ -325,9 +325,16 @@ mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, s MRB_API void mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RProc *p) { - khash_t(mt) *h = c->mt; + khash_t(mt) *h; khiter_t k; + if (!c->origin) { + printf("Warning, class %s does not have valid origin\n", mrb_class_name(mrb, c)); + mrb_raisef(mrb, E_RUNTIME_ERROR, "Invalid origin"); + c->origin = c; + } + h = c->origin->mt; + if (!h) h = c->mt = kh_init(mt, mrb); k = kh_put(mt, mrb, h, mid); kh_value(h, k) = p; @@ -758,6 +765,7 @@ boot_defclass(mrb_state *mrb, struct RClass *super) struct RClass *c; c = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_CLASS, mrb->class_class); + c->origin = c; if (super) { c->super = super; mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)super); @@ -765,71 +773,74 @@ boot_defclass(mrb_state *mrb, struct RClass *super) else { c->super = mrb->object_class; } - c->origin = c; c->mt = kh_init(mt, mrb); return c; } -MRB_API inline void -include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, struct RClass *m, int search_super) +static struct RClass* +include_class_new(mrb_state *mrb, struct RClass *m, struct RClass *super) +{ + struct RClass *ic = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, mrb->class_class); + if (m->tt == MRB_TT_ICLASS) { + m = m->c; + } + ic->origin = ic; + ic->iv = m->iv; + ic->mt = m->origin->mt; + ic->super = super; + if (m->tt == MRB_TT_ICLASS) { + ic->c = m->c; + } else { + ic->c = m; + } + return ic; +} + +MRB_API int +include_module_at(mrb_state *mrb, struct RClass *klass, struct RClass *c, struct RClass *module, int search_super) { - while (m) { - struct RClass *p = c, *ic; + struct RClass *p, *iclass; + void *klass_mt = klass->origin->mt; + + while (module) { int superclass_seen = 0; - - //if (m->origin != m) - // goto skip; - if (c->mt && c->mt == m->mt) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected"); - } - while (p) { - /*if (p->tt == MRB_TT_ICLASS) { - if (!superclass_seen) { - ins_pos = p; // move insert point + + if (module->origin != module) + goto skip; + + if (klass_mt && klass_mt == module->mt) + return -1; + + p = klass->super; + while(p) { + if (p->tt == MRB_TT_ICLASS) { + if (p->mt == module->mt) { + if (!superclass_seen) { + c = p; // move insert point + } + goto skip; } - goto skip; } else if (p->tt == MRB_TT_CLASS) { - if (p->mt == m->mt) { - if (!search_super) break; - superclass_seen = 1; - } - }*/ - // - if (c != p && p->tt == MRB_TT_CLASS) { if (!search_super) break; superclass_seen = 1; } - else if (p->mt == m->mt) { - if (p->tt == MRB_TT_ICLASS && !superclass_seen) { - ins_pos = p; - } - goto skip; - } p = p->super; } - ic = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, mrb->class_class); - if (m->tt == MRB_TT_ICLASS) { - ic->c = m->c; - } - else { - ic->c = m; - } - ic->origin = ic; - ic->mt = m->mt; - ic->iv = m->iv; - ic->super = ins_pos->super; - ins_pos->super = ic; - mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ic); - ins_pos = ic; + + iclass = include_class_new(mrb, module, c->super); + c->super = iclass; + mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)c->super); + c = iclass; skip: - m = m->super; + module = module->super; } + return 0; } MRB_API void mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) { - include_module_at(mrb, c, c->origin, m, FALSE); + include_module_at(mrb, c, c->origin, m, 1); } MRB_API void @@ -842,16 +853,16 @@ mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m) if (origin == c) { origin = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, c); origin->origin = origin; - //OBJ_WB_UNPROTECT(origin); /* TODO: conservative shading. Need more survey. */ origin->super = c->super; c->super = origin; c->origin = origin; origin->mt = c->mt; c->mt = kh_init(mt, mrb); + mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)c->origin); } - include_module_at(mrb, c, c, m, FALSE); // changed = - if (changed) { - //rb_vm_check_redefinition_by_prepend(klass); + changed = include_module_at(mrb, c, c, m, 0); + if (changed < 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic prepend detected"); } } @@ -955,15 +966,12 @@ mrb_mod_ancestors(mrb_state *mrb, mrb_value self) { mrb_value result; struct RClass *c = mrb_class_ptr(self); - result = mrb_ary_new(mrb); - mrb_ary_push(mrb, result, mrb_obj_value(c)); - c = c->super; while (c) { if (c->tt == MRB_TT_ICLASS) { mrb_ary_push(mrb, result, mrb_obj_value(c->c)); } - else if (c->tt != MRB_TT_SCLASS) { + else if (c->origin == c) { mrb_ary_push(mrb, result, mrb_obj_value(c)); } c = c->super; @@ -1005,9 +1013,14 @@ mrb_mod_initialize(mrb_state *mrb, mrb_value mod) { mrb_value b; + /* hack, fix missing module->origin */ + struct RClass *m = mrb_class_ptr(mod); + if (!m->origin) + m->origin = m; + mrb_get_args(mrb, "&", &b); if (!mrb_nil_p(b)) { - mrb_yield_with_class(mrb, b, 1, &mod, mod, mrb_class_ptr(mod)); + mrb_yield_with_class(mrb, b, 1, &mod, mod, m); } return mod; } @@ -1324,9 +1337,9 @@ mrb_class_superclass(mrb_state *mrb, mrb_value klass) struct RClass *c; c = mrb_class_ptr(klass); - c = c->super; + c = c->origin->super; while (c && c->tt == MRB_TT_ICLASS) { - c = c->super; + c = c->origin->super; } if (!c) return mrb_nil_value(); return mrb_obj_value(c); @@ -1925,7 +1938,7 @@ static void remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid) { struct RClass *c = mrb_class_ptr(mod); - khash_t(mt) *h = c->mt; + khash_t(mt) *h = c->origin->mt; khiter_t k; if (h) { diff --git a/src/kernel.c b/src/kernel.c index b5b13f874..bafab6e76 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -248,6 +248,11 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj) clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass)); } + if (klass->origin != klass) + clone->origin = klass->origin; + else + clone->origin = clone; + clone->super = klass->super; if (klass->iv) { mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass)); @@ -269,6 +274,13 @@ copy_class(mrb_state *mrb, mrb_value dst, mrb_value src) { struct RClass *dc = mrb_class_ptr(dst); struct RClass *sc = mrb_class_ptr(src); + /* if the origin is not the same as the class, then the origin and + the current class need to be copied */ + if (sc->origin != sc) { + dc->origin = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(sc->origin))); + } else { + dc->origin = dc; + } dc->mt = kh_copy(mt, mrb, sc->mt); dc->super = sc->super; } -- cgit v1.2.3 From ce6672717706365929b1c2c3c2c278e75a3c4be4 Mon Sep 17 00:00:00 2001 From: Corey Powell Date: Sat, 11 Jul 2015 08:16:04 -0500 Subject: Remove some remnant debug code --- src/class.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 73e6687c0..e9df1dae4 100644 --- a/src/class.c +++ b/src/class.c @@ -327,12 +327,6 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RPro { khash_t(mt) *h; khiter_t k; - - if (!c->origin) { - printf("Warning, class %s does not have valid origin\n", mrb_class_name(mrb, c)); - mrb_raisef(mrb, E_RUNTIME_ERROR, "Invalid origin"); - c->origin = c; - } h = c->origin->mt; if (!h) h = c->mt = kh_init(mt, mrb); -- cgit v1.2.3 From 40f48034d512a8e4f24f8d67373f18093e96513c Mon Sep 17 00:00:00 2001 From: Corey Powell Date: Sat, 11 Jul 2015 08:25:43 -0500 Subject: Added changed check to the mrb_include_module --- src/class.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index e9df1dae4..4a64e5b23 100644 --- a/src/class.c +++ b/src/class.c @@ -834,7 +834,10 @@ include_module_at(mrb_state *mrb, struct RClass *klass, struct RClass *c, struct MRB_API void mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) { - include_module_at(mrb, c, c->origin, m, 1); + int changed = include_module_at(mrb, c, c->origin, m, 1); + if (changed < 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected"); + } } MRB_API void -- cgit v1.2.3 From d4b009b394d3933ee1b828d0e91d3c6aaa522339 Mon Sep 17 00:00:00 2001 From: Corey Powell Date: Sat, 11 Jul 2015 11:09:13 -0500 Subject: Fixed Modules not being fully initialized before #initialize was called --- src/class.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 4a64e5b23..d83216cb4 100644 --- a/src/class.c +++ b/src/class.c @@ -77,7 +77,7 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o) if (o->c->tt == MRB_TT_SCLASS) return; sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class); sc->origin = sc; - sc->mt = 0; + sc->mt = kh_init(mt, mrb); sc->iv = 0; if (o->tt == MRB_TT_CLASS) { c = (struct RClass*)o; @@ -771,6 +771,13 @@ boot_defclass(mrb_state *mrb, struct RClass *super) return c; } +static void +boot_initmod(mrb_state *mrb, struct RClass *mod) +{ + mod->origin = mod; + mod->mt = kh_init(mt, mrb); +} + static struct RClass* include_class_new(mrb_state *mrb, struct RClass *m, struct RClass *super) { @@ -1012,10 +1019,8 @@ mrb_mod_initialize(mrb_state *mrb, mrb_value mod) /* hack, fix missing module->origin */ struct RClass *m = mrb_class_ptr(mod); - if (!m->origin) - m->origin = m; - - mrb_get_args(mrb, "&", &b); + boot_initmod(mrb, m); // bootstrap a newly initialized module + mrb_get_args(mrb, "|&", &b); if (!mrb_nil_p(b)) { mrb_yield_with_class(mrb, b, 1, &mod, mod, m); } @@ -1574,9 +1579,7 @@ MRB_API struct RClass* mrb_module_new(mrb_state *mrb) { struct RClass *m = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_MODULE, mrb->module_class); - m->origin = m; - m->mt = kh_init(mt, mrb); - + boot_initmod(mrb, m); return m; } -- cgit v1.2.3 From 668153092f48275279f85d2618fff6eb9730332c Mon Sep 17 00:00:00 2001 From: Corey Powell Date: Mon, 13 Jul 2015 09:38:24 -0500 Subject: Added Module#method_removed hook --- src/class.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index d83216cb4..0b00a6484 100644 --- a/src/class.c +++ b/src/class.c @@ -1945,6 +1945,7 @@ remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid) k = kh_get(mt, mrb, h, mid); if (k != kh_end(h)) { kh_del(mt, mrb, h, k); + mrb_funcall(mrb, mod, "method_removed", 1, mrb_symbol_value(mid)); return; } } @@ -2197,6 +2198,7 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, mod, "public", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.38 */ mrb_define_method(mrb, mod, "remove_class_variable", mrb_mod_remove_cvar, MRB_ARGS_REQ(1)); /* 15.2.2.4.39 */ mrb_define_method(mrb, mod, "remove_method", mrb_mod_remove_method, MRB_ARGS_ANY()); /* 15.2.2.4.41 */ + mrb_define_method(mrb, mod, "method_removed", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.41 */ mrb_define_method(mrb, mod, "attr_reader", mrb_mod_attr_reader, MRB_ARGS_ANY()); /* 15.2.2.4.13 */ mrb_define_method(mrb, mod, "attr_writer", mrb_mod_attr_writer, MRB_ARGS_ANY()); /* 15.2.2.4.14 */ mrb_define_method(mrb, mod, "to_s", mrb_mod_to_s, MRB_ARGS_NONE()); -- cgit v1.2.3 From 1f678a4acefc14531a2ed25c33f62a0d628b1474 Mon Sep 17 00:00:00 2001 From: Corey Powell Date: Mon, 13 Jul 2015 09:40:40 -0500 Subject: Removed comment beside method_removed Not sure if this apart of the ISO standard, so make sure its not misrepresented --- 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 0b00a6484..a13da63ac 100644 --- a/src/class.c +++ b/src/class.c @@ -2198,7 +2198,7 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, mod, "public", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.38 */ mrb_define_method(mrb, mod, "remove_class_variable", mrb_mod_remove_cvar, MRB_ARGS_REQ(1)); /* 15.2.2.4.39 */ mrb_define_method(mrb, mod, "remove_method", mrb_mod_remove_method, MRB_ARGS_ANY()); /* 15.2.2.4.41 */ - mrb_define_method(mrb, mod, "method_removed", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.41 */ + mrb_define_method(mrb, mod, "method_removed", mrb_bob_init, MRB_ARGS_REQ(1)); mrb_define_method(mrb, mod, "attr_reader", mrb_mod_attr_reader, MRB_ARGS_ANY()); /* 15.2.2.4.13 */ mrb_define_method(mrb, mod, "attr_writer", mrb_mod_attr_writer, MRB_ARGS_ANY()); /* 15.2.2.4.14 */ mrb_define_method(mrb, mod, "to_s", mrb_mod_to_s, MRB_ARGS_NONE()); -- cgit v1.2.3 From 199a808e36197bd6f893112bbd43f18f2c25345f Mon Sep 17 00:00:00 2001 From: Corey Powell Date: Mon, 13 Jul 2015 09:49:18 -0500 Subject: Bugfix, included_modules would include classes --- 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 a13da63ac..5450f3a20 100644 --- a/src/class.c +++ b/src/class.c @@ -1004,7 +1004,9 @@ mrb_mod_included_modules(mrb_state *mrb, mrb_value self) result = mrb_ary_new(mrb); while (c) { if (c->tt == MRB_TT_ICLASS) { - mrb_ary_push(mrb, result, mrb_obj_value(c->c)); + if (c->c->tt == MRB_TT_MODULE) { + mrb_ary_push(mrb, result, mrb_obj_value(c->c)); + } } c = c->super; } -- cgit v1.2.3 From 81a2b3431c63c969f73e6c0eeaa968acbace0e44 Mon Sep 17 00:00:00 2001 From: Corey Powell Date: Mon, 13 Jul 2015 09:49:51 -0500 Subject: included_modules, origin fix Prepended modules would include their origin ICLASS --- src/class.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 5450f3a20..cde5736e0 100644 --- a/src/class.c +++ b/src/class.c @@ -1000,10 +1000,11 @@ mrb_mod_included_modules(mrb_state *mrb, mrb_value self) { mrb_value result; struct RClass *c = mrb_class_ptr(self); + struct RClass *origin = c->origin; result = mrb_ary_new(mrb); while (c) { - if (c->tt == MRB_TT_ICLASS) { + if (c != origin && c->tt == MRB_TT_ICLASS) { if (c->c->tt == MRB_TT_MODULE) { mrb_ary_push(mrb, result, mrb_obj_value(c->c)); } -- cgit v1.2.3 From a0754986134fbe6b65992b19338c97d596f4ef60 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 14 Jul 2015 13:22:42 +0900 Subject: mrb_get_args: allow A,H,s,z,a,d specifiers to take ! to accept nil. S,A,H gives nil, s,z,a,d gives NULL for nil argument. ref 02474da --- src/class.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 8a9fdaca6..b5f5f5287 100644 --- a/src/class.c +++ b/src/class.c @@ -435,9 +435,9 @@ to_sym(mrb_state *mrb, mrb_value ss) ---------------------------------------------------------------------------------------------- o: Object [mrb_value] C: class/module [mrb_value] - S: String [mrb_value] when ! follows the value may be nil - A: Array [mrb_value] - H: Hash [mrb_value] + S: String [mrb_value] when ! follows, the value may be nil + A: Array [mrb_value] when ! follows, the value may be nil + H: Hash [mrb_value] when ! follows, the value may be nil s: String [char*,mrb_int] Receive two arguments. z: String [char*] NUL terminated string. a: Array [mrb_value*,mrb_int] Receive two arguments. @@ -527,7 +527,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) p = va_arg(ap, mrb_value*); if (*format == '!') { format++; - if (mrb_nil_p(*sp)) { + if (i < argc && mrb_nil_p(*sp)) { *p = *sp++; i++; break; @@ -544,6 +544,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value *p; p = va_arg(ap, mrb_value*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *p = *sp++; + i++; + break; + } + } if (i < argc) { *p = to_ary(mrb, *sp++); i++; @@ -555,6 +563,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value *p; p = va_arg(ap, mrb_value*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *p = *sp++; + i++; + break; + } + } if (i < argc) { *p = to_hash(mrb, *sp++); i++; @@ -569,6 +585,15 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) ps = va_arg(ap, char**); pl = va_arg(ap, mrb_int*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *ps = NULL; + *pl = 0; + i++; + break; + } + } if (i < argc) { ss = to_str(mrb, *sp++); *ps = RSTRING_PTR(ss); @@ -583,6 +608,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) const char **ps; ps = va_arg(ap, const char**); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *ps = NULL; + i++; + break; + } + } if (i < argc) { ss = to_str(mrb, *sp++); *ps = mrb_string_value_cstr(mrb, &ss); @@ -599,6 +632,15 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) pb = va_arg(ap, mrb_value**); pl = va_arg(ap, mrb_int*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *pb = 0; + *pl = 0; + i++; + break; + } + } if (i < argc) { aa = to_ary(mrb, *sp++); a = mrb_ary_ptr(aa); -- cgit v1.2.3 From 4e7050fe0c56a9403f182d3f79a22a4196d377f0 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 14 Jul 2015 13:34:21 +0900 Subject: mrb_get_args: allow d! --- src/class.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index b5f5f5287..b306cb489 100644 --- a/src/class.c +++ b/src/class.c @@ -726,6 +726,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) datap = va_arg(ap, void**); type = va_arg(ap, struct mrb_data_type const*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *datap = 0; + i++; + break; + } + } if (i < argc) { *datap = mrb_data_get_ptr(mrb, *sp++, type); ++i; -- cgit v1.2.3 From 53a81da0fafc2adbc791d9f161207faa29bccb4e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 14 Jul 2015 13:35:06 +0900 Subject: mrb_get_args: improve function description about ! --- src/class.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index b306cb489..1d54c91f4 100644 --- a/src/class.c +++ b/src/class.c @@ -438,9 +438,9 @@ to_sym(mrb_state *mrb, mrb_value ss) S: String [mrb_value] when ! follows, the value may be nil A: Array [mrb_value] when ! follows, the value may be nil H: Hash [mrb_value] when ! follows, the value may be nil - s: String [char*,mrb_int] Receive two arguments. - z: String [char*] NUL terminated string. - a: Array [mrb_value*,mrb_int] Receive two arguments. + s: String [char*,mrb_int] Receive two arguments; s! gives (NULL,0) for nil + z: String [char*] NUL terminated string; z! gives NULL for nil + a: Array [mrb_value*,mrb_int] Receive two arguments; a! gives (NULL,0) for nil f: Float [mrb_float] i: Integer [mrb_int] b: Boolean [mrb_bool] -- cgit v1.2.3 From f0e920baf07e17fd1073566d7e9605f9192d766d Mon Sep 17 00:00:00 2001 From: Corey Powell Date: Tue, 14 Jul 2015 08:55:53 -0500 Subject: Renamed parameters in include_module_at --- src/class.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index cde5736e0..14d81495e 100644 --- a/src/class.c +++ b/src/class.c @@ -798,26 +798,26 @@ include_class_new(mrb_state *mrb, struct RClass *m, struct RClass *super) } MRB_API int -include_module_at(mrb_state *mrb, struct RClass *klass, struct RClass *c, struct RClass *module, int search_super) +include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, struct RClass *m, int search_super) { - struct RClass *p, *iclass; - void *klass_mt = klass->origin->mt; + struct RClass *p, *ic; + void *klass_mt = c->origin->mt; - while (module) { + while (m) { int superclass_seen = 0; - if (module->origin != module) + if (m->origin != m) goto skip; - if (klass_mt && klass_mt == module->mt) + if (klass_mt && klass_mt == m->mt) return -1; - p = klass->super; + p = c->super; while(p) { if (p->tt == MRB_TT_ICLASS) { - if (p->mt == module->mt) { + if (p->mt == m->mt) { if (!superclass_seen) { - c = p; // move insert point + ins_pos = p; // move insert point } goto skip; } @@ -828,12 +828,12 @@ include_module_at(mrb_state *mrb, struct RClass *klass, struct RClass *c, struct p = p->super; } - iclass = include_class_new(mrb, module, c->super); - c->super = iclass; - mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)c->super); - c = iclass; + ic = include_class_new(mrb, m, ins_pos->super); + ins_pos->super = ic; + mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ins_pos->super); + ins_pos = ic; skip: - module = module->super; + m = m->super; } return 0; } -- cgit v1.2.3 From eb172c28d79b4fdf978e78fc7e929caa855dd29b Mon Sep 17 00:00:00 2001 From: Corey Powell Date: Tue, 14 Jul 2015 09:44:04 -0500 Subject: Applied gc patch to fix ORIGIN ICLASS method table leak Based on the gc patch by ko1 https://github.com/ruby/ruby/commit/5922c954614e5947a548780bb3b894626affe6dd --- include/mruby/class.h | 7 +++++-- include/mruby/object.h | 2 ++ src/class.c | 1 + src/gc.c | 12 ++++++++++-- 4 files changed, 18 insertions(+), 4 deletions(-) (limited to 'src/class.c') diff --git a/include/mruby/class.h b/include/mruby/class.h index 60310ae9d..9f2c32bb0 100644 --- a/include/mruby/class.h +++ b/include/mruby/class.h @@ -49,8 +49,11 @@ mrb_class(mrb_state *mrb, mrb_value v) } } -#define MRB_SET_INSTANCE_TT(c, tt) c->flags = ((c->flags & ~0xff) | (char)tt) -#define MRB_INSTANCE_TT(c) (enum mrb_vtype)(c->flags & 0xff) +// TODO: figure out where to put user flags +#define MRB_FLAG_IS_ORIGIN (1 << 20) +#define MRB_FLAG_IS_INSTANCE (0xFF) +#define MRB_SET_INSTANCE_TT(c, tt) c->flags = ((c->flags & ~MRB_FLAG_IS_INSTANCE) | (char)tt) +#define MRB_INSTANCE_TT(c) (enum mrb_vtype)(c->flags & MRB_FLAG_IS_INSTANCE) MRB_API struct RClass* mrb_define_class_id(mrb_state*, mrb_sym, struct RClass*); MRB_API struct RClass* mrb_define_module_id(mrb_state*, mrb_sym); diff --git a/include/mruby/object.h b/include/mruby/object.h index fe55620fe..6633a23e8 100644 --- a/include/mruby/object.h +++ b/include/mruby/object.h @@ -14,6 +14,8 @@ struct RClass *c;\ struct RBasic *gcnext +#define MRB_FLAG_TEST(obj, flag) ((obj)->flags & flag) + /* white: 011, black: 100, gray: 000 */ #define MRB_GC_GRAY 0 #define MRB_GC_WHITE_A 1 diff --git a/src/class.c b/src/class.c index 14d81495e..58742299b 100644 --- a/src/class.c +++ b/src/class.c @@ -856,6 +856,7 @@ mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m) origin = c->origin; if (origin == c) { origin = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, c); + origin->flags |= MRB_FLAG_IS_ORIGIN; origin->origin = origin; origin->super = c->super; c->super = origin; diff --git a/src/gc.c b/src/gc.c index 8bd8243f1..15e1bd423 100644 --- a/src/gc.c +++ b/src/gc.c @@ -498,7 +498,12 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj) mrb_gc_mark(mrb, (struct RBasic*)obj->c); switch (obj->tt) { case MRB_TT_ICLASS: - mrb_gc_mark(mrb, (struct RBasic*)((struct RClass*)obj)->super); + { + struct RClass *c = (struct RClass*)obj; + if (MRB_FLAG_TEST(c, MRB_FLAG_IS_ORIGIN)) + mrb_gc_mark_mt(mrb, c); + mrb_gc_mark(mrb, (struct RBasic*)((struct RClass*)obj)->super); + } break; case MRB_TT_CLASS: @@ -624,7 +629,10 @@ obj_free(mrb_state *mrb, struct RBasic *obj) mrb_gc_free_mt(mrb, (struct RClass*)obj); mrb_gc_free_iv(mrb, (struct RObject*)obj); break; - + case MRB_TT_ICLASS: + if (MRB_FLAG_TEST(obj, MRB_FLAG_IS_ORIGIN)) + mrb_gc_free_mt(mrb, (struct RClass*)obj); + break; case MRB_TT_ENV: { struct REnv *e = (struct REnv*)obj; -- cgit v1.2.3 From dbbf2e26231c04d76badb1889627869d1f9361bb Mon Sep 17 00:00:00 2001 From: Corey Powell Date: Tue, 14 Jul 2015 14:12:23 -0500 Subject: Remove non-applicable "hack" comment --- src/class.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 58742299b..f342ded20 100644 --- a/src/class.c +++ b/src/class.c @@ -1020,8 +1020,6 @@ static mrb_value mrb_mod_initialize(mrb_state *mrb, mrb_value mod) { mrb_value b; - - /* hack, fix missing module->origin */ struct RClass *m = mrb_class_ptr(mod); boot_initmod(mrb, m); // bootstrap a newly initialized module mrb_get_args(mrb, "|&", &b); -- cgit v1.2.3 From 938ed044f4e053c1832be3868230d80ccba190e8 Mon Sep 17 00:00:00 2001 From: cremno Date: Thu, 16 Jul 2015 03:56:31 +0200 Subject: use mrb_str_cat_str() instead of mrb_str_append() If the argument is always a string, then mrb_str_cat_str() can be directly called instead of indirectly by mrb_str_append(). mrb_any_to_s(), mrb_obj_as_string(), mrb_inspect() always return a string. --- src/class.c | 4 ++-- src/error.c | 4 ++-- src/range.c | 4 ++-- src/variable.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/class.c') diff --git a/src/class.c b/src/class.c index 1d54c91f4..33fb61211 100644 --- a/src/class.c +++ b/src/class.c @@ -1608,10 +1608,10 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass) case MRB_TT_CLASS: case MRB_TT_MODULE: case MRB_TT_SCLASS: - mrb_str_append(mrb, str, mrb_inspect(mrb, v)); + mrb_str_cat_str(mrb, str, mrb_inspect(mrb, v)); break; default: - mrb_str_append(mrb, str, mrb_any_to_s(mrb, v)); + mrb_str_cat_str(mrb, str, mrb_any_to_s(mrb, v)); break; } return mrb_str_cat_lit(mrb, str, ">"); diff --git a/src/error.c b/src/error.c index 20c63bd43..359e5737b 100644 --- a/src/error.c +++ b/src/error.c @@ -152,7 +152,7 @@ exc_inspect(mrb_state *mrb, mrb_value exc) mrb_str_append(mrb, str, line); mrb_str_cat_lit(mrb, str, ": "); if (append_mesg) { - mrb_str_append(mrb, str, mesg); + mrb_str_cat_str(mrb, str, mesg); mrb_str_cat_lit(mrb, str, " ("); } mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc)); @@ -165,7 +165,7 @@ exc_inspect(mrb_state *mrb, mrb_value exc) str = mrb_str_new_cstr(mrb, cname); mrb_str_cat_lit(mrb, str, ": "); if (append_mesg) { - mrb_str_append(mrb, str, mesg); + mrb_str_cat_str(mrb, str, mesg); } else { mrb_str_cat_cstr(mrb, str, cname); diff --git a/src/range.c b/src/range.c index b427dc1b7..b58b6a1c8 100644 --- a/src/range.c +++ b/src/range.c @@ -290,7 +290,7 @@ range_to_s(mrb_state *mrb, mrb_value range) str2 = mrb_obj_as_string(mrb, r->edges->end); str = mrb_str_dup(mrb, str); mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2); - mrb_str_append(mrb, str, str2); + mrb_str_cat_str(mrb, str, str2); return str; } @@ -315,7 +315,7 @@ range_inspect(mrb_state *mrb, mrb_value range) str2 = mrb_inspect(mrb, r->edges->end); str = mrb_str_dup(mrb, str); mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2); - mrb_str_append(mrb, str, str2); + mrb_str_cat_str(mrb, str, str2); return str; } diff --git a/src/variable.c b/src/variable.c index 1b2ad56a7..efe6fad12 100644 --- a/src/variable.c +++ b/src/variable.c @@ -609,7 +609,7 @@ inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) else { ins = mrb_inspect(mrb, v); } - mrb_str_append(mrb, str, ins); + mrb_str_cat_str(mrb, str, ins); return 0; } -- cgit v1.2.3 From ae1ece72282fdfa558810e8422bb690bbc6d2193 Mon Sep 17 00:00:00 2001 From: Corey Powell Date: Thu, 16 Jul 2015 15:25:14 -0500 Subject: Make include_module_at static Since I can't forsee any reason to use it directly inplace of using prepend/include --- 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 f342ded20..90c463579 100644 --- a/src/class.c +++ b/src/class.c @@ -797,7 +797,7 @@ include_class_new(mrb_state *mrb, struct RClass *m, struct RClass *super) return ic; } -MRB_API int +static int include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, struct RClass *m, int search_super) { struct RClass *p, *ic; -- cgit v1.2.3 From 2550edd570f1d7485e862ce11ceb50ea59dee3c5 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 5 Sep 2015 02:01:02 +0900 Subject: remove `origin` member to implement prepend from struct RClass; ref #2885 instead origin is saved in ICLASS with MRB_FLAG_IS_ORIGIN set. --- include/mruby/class.h | 10 +++++++++- src/class.c | 44 ++++++++++++++++++++++++-------------------- src/kernel.c | 29 +++++++++++++++-------------- src/object.c | 2 +- 4 files changed, 49 insertions(+), 36 deletions(-) (limited to 'src/class.c') diff --git a/include/mruby/class.h b/include/mruby/class.h index 80a0cbe35..85f3e12c6 100644 --- a/include/mruby/class.h +++ b/include/mruby/class.h @@ -16,7 +16,6 @@ struct RClass { struct iv_tbl *iv; struct kh_mt *mt; struct RClass *super; - struct RClass *origin; }; #define mrb_class_ptr(v) ((struct RClass*)(mrb_ptr(v))) @@ -50,7 +49,16 @@ mrb_class(mrb_state *mrb, mrb_value v) } // TODO: figure out where to put user flags +#define MRB_FLAG_IS_PREPENDED (1 << 19) #define MRB_FLAG_IS_ORIGIN (1 << 20) +#define MRB_CLASS_ORIGIN(c) do {\ + if (c->flags & MRB_FLAG_IS_PREPENDED) {\ + c = c->super;\ + while (!(c->flags & MRB_FLAG_IS_ORIGIN)) {\ + c = c->super;\ + }\ + }\ +} while (0) #define MRB_INSTANCE_TT_MASK (0xFF) #define MRB_SET_INSTANCE_TT(c, tt) c->flags = ((c->flags & ~MRB_INSTANCE_TT_MASK) | (char)tt) #define MRB_INSTANCE_TT(c) (enum mrb_vtype)(c->flags & MRB_INSTANCE_TT_MASK) diff --git a/src/class.c b/src/class.c index 462ab40b5..c3c3e0b8f 100644 --- a/src/class.c +++ b/src/class.c @@ -76,7 +76,6 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o) if (o->c->tt == MRB_TT_SCLASS) return; sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class); - sc->origin = sc; sc->mt = kh_init(mt, mrb); sc->iv = 0; if (o->tt == MRB_TT_CLASS) { @@ -188,6 +187,13 @@ mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name) return c; } +static struct RClass* +find_origin(struct RClass *c) +{ + MRB_CLASS_ORIGIN(c); + return c; +} + static struct RClass* define_class(mrb_state *mrb, mrb_sym name, struct RClass *super, struct RClass *outer) { @@ -195,7 +201,7 @@ define_class(mrb_state *mrb, mrb_sym name, struct RClass *super, struct RClass * if (mrb_const_defined_at(mrb, mrb_obj_value(outer), name)) { c = class_from_sym(mrb, outer, name); - c = c->origin; + MRB_CLASS_ORIGIN(c); if (super && mrb_class_real(c->super) != super) { mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for Class %S (%S not %S)", mrb_sym2str(mrb, name), @@ -327,7 +333,8 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RPro { khash_t(mt) *h; khiter_t k; - h = c->origin->mt; + MRB_CLASS_ORIGIN(c); + h = c->mt; if (!h) h = c->mt = kh_init(mt, mrb); k = kh_put(mt, mrb, h, mid); @@ -809,7 +816,6 @@ boot_defclass(mrb_state *mrb, struct RClass *super) struct RClass *c; c = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_CLASS, mrb->class_class); - c->origin = c; if (super) { c->super = super; mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)super); @@ -824,7 +830,6 @@ boot_defclass(mrb_state *mrb, struct RClass *super) static void boot_initmod(mrb_state *mrb, struct RClass *mod) { - mod->origin = mod; mod->mt = kh_init(mt, mrb); } @@ -835,9 +840,9 @@ include_class_new(mrb_state *mrb, struct RClass *m, struct RClass *super) if (m->tt == MRB_TT_ICLASS) { m = m->c; } - ic->origin = ic; + MRB_CLASS_ORIGIN(m); ic->iv = m->iv; - ic->mt = m->origin->mt; + ic->mt = m->mt; ic->super = super; if (m->tt == MRB_TT_ICLASS) { ic->c = m->c; @@ -851,12 +856,12 @@ static int include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, struct RClass *m, int search_super) { struct RClass *p, *ic; - void *klass_mt = c->origin->mt; + void *klass_mt = find_origin(c)->mt; while (m) { int superclass_seen = 0; - if (m->origin != m) + if (m->flags & MRB_FLAG_IS_PREPENDED) goto skip; if (klass_mt && klass_mt == m->mt) @@ -891,7 +896,7 @@ include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, stru MRB_API void mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m) { - int changed = include_module_at(mrb, c, c->origin, m, 1); + int changed = include_module_at(mrb, c, find_origin(c), m, 1); if (changed < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected"); } @@ -903,17 +908,15 @@ mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m) struct RClass *origin; int changed = 0; - origin = c->origin; - if (origin == c) { + if (!(c->flags & MRB_FLAG_IS_PREPENDED)) { origin = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, c); origin->flags |= MRB_FLAG_IS_ORIGIN; - origin->origin = origin; origin->super = c->super; c->super = origin; - c->origin = origin; origin->mt = c->mt; c->mt = kh_init(mt, mrb); - mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)c->origin); + mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)origin); + c->flags |= MRB_FLAG_IS_PREPENDED; } changed = include_module_at(mrb, c, c, m, 0); if (changed < 0) { @@ -1026,7 +1029,7 @@ mrb_mod_ancestors(mrb_state *mrb, mrb_value self) if (c->tt == MRB_TT_ICLASS) { mrb_ary_push(mrb, result, mrb_obj_value(c->c)); } - else if (c->origin == c) { + else if (!(c->flags & MRB_FLAG_IS_PREPENDED)) { mrb_ary_push(mrb, result, mrb_obj_value(c)); } c = c->super; @@ -1051,8 +1054,9 @@ mrb_mod_included_modules(mrb_state *mrb, mrb_value self) { mrb_value result; struct RClass *c = mrb_class_ptr(self); - struct RClass *origin = c->origin; + struct RClass *origin = c; + MRB_CLASS_ORIGIN(origin); result = mrb_ary_new(mrb); while (c) { if (c != origin && c->tt == MRB_TT_ICLASS) { @@ -1391,9 +1395,9 @@ mrb_class_superclass(mrb_state *mrb, mrb_value klass) struct RClass *c; c = mrb_class_ptr(klass); - c = c->origin->super; + c = find_origin(c)->super; while (c && c->tt == MRB_TT_ICLASS) { - c = c->origin->super; + c = find_origin(c)->super; } if (!c) return mrb_nil_value(); return mrb_obj_value(c); @@ -1990,7 +1994,7 @@ static void remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid) { struct RClass *c = mrb_class_ptr(mod); - khash_t(mt) *h = c->origin->mt; + khash_t(mt) *h = find_origin(c)->mt; khiter_t k; if (h) { diff --git a/src/kernel.c b/src/kernel.c index 36ad683ee..225f7fa54 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -240,19 +240,12 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj) /* copy singleton(unnamed) class */ struct RClass *clone = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, mrb->class_class); - if ((mrb_type(obj) == MRB_TT_CLASS) || - (mrb_type(obj) == MRB_TT_SCLASS)) { /* BUILTIN_TYPE(obj) == T_CLASS */ + if ((mrb_type(obj) == MRB_TT_CLASS) || (mrb_type(obj) == MRB_TT_SCLASS)) { clone->c = clone; } else { clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass)); } - - if (klass->origin != klass) - clone->origin = klass->origin; - else - clone->origin = clone; - clone->super = klass->super; if (klass->iv) { mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass)); @@ -276,10 +269,18 @@ copy_class(mrb_state *mrb, mrb_value dst, mrb_value src) struct RClass *sc = mrb_class_ptr(src); /* if the origin is not the same as the class, then the origin and the current class need to be copied */ - if (sc->origin != sc) { - dc->origin = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(sc->origin))); - } else { - dc->origin = dc; + if (sc->flags & MRB_FLAG_IS_PREPENDED) { + struct RClass *c0 = sc->super; + struct RClass *c1 = dc; + + /* copy prepended iclasses */ + while (!(c0->flags & MRB_FLAG_IS_ORIGIN)) { + c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0))); + c1 = c1->super; + c0 = c0->super; + } + c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0))); + c1->super->flags |= MRB_FLAG_IS_ORIGIN; } dc->mt = kh_copy(mt, mrb, sc->mt); dc->super = sc->super; @@ -657,8 +658,8 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* kl struct RClass* oldklass; khash_t(st)* set = kh_init(st, mrb); - if (!recur && klass->origin != klass) { - klass = klass->origin; + if (!recur && (klass->flags & MRB_FLAG_IS_PREPENDED)) { + MRB_CLASS_ORIGIN(klass); prepended = 1; } diff --git a/src/object.c b/src/object.c index c834ee04f..2e0bd245f 100644 --- a/src/object.c +++ b/src/object.c @@ -487,7 +487,7 @@ mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c) mrb_raise(mrb, E_TYPE_ERROR, "class or module required"); } - c = c->origin; + MRB_CLASS_ORIGIN(c); while (cl) { if (cl == c || cl->mt == c->mt) return TRUE; -- cgit v1.2.3