Merge branch 'master' into stable

This commit is contained in:
mimaki
2024-02-14 19:01:59 +09:00
47 changed files with 824 additions and 502 deletions
+6
View File
@@ -7,11 +7,17 @@ build:
- any:
- changed-files:
- any-glob-to-any-file:
- Dockerfile
- Makefile
- Rakefile
- appveyor.yml
- build_config.rb
- build_config/**/*
- docker-compose.yml
- lib/**/*
- minirake
- tasks/**/*
- .travis.yml
core:
- any:
- changed-files:
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
pip install pre-commit
- name: Set PY
run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV
- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
+1 -2
View File
@@ -20,9 +20,8 @@ jobs:
# Full git history is needed to get a proper list of changed files within `super-linter`
fetch-depth: 0
- name: Lint Code Base
uses: super-linter/super-linter/slim@v5.7.2
uses: super-linter/super-linter/slim@v6.0.0
env:
ERROR_ON_MISSING_EXEC_BIT: true
VALIDATE_BASH: true
# VALIDATE_BASH_EXEC: true
# VALIDATE_EDITORCONFIG: true
+2
View File
@@ -20,6 +20,8 @@ repos:
- id: check-shebang-scripts-are-executable
- id: check-vcs-permalinks
- id: check-yaml
- id: detect-aws-credentials
args: [--allow-missing-credentials]
- id: detect-private-key
- id: end-of-file-fixer
- id: file-contents-sorter
+6 -4
View File
@@ -1,10 +1,10 @@
# Authors of mruby (mruby developers)
## The List of Contributors sorted by number of commits (as of 2023-12-28 67cb987)
## The List of Contributors sorted by number of commits (as of 2024-02-10 d2af9da)
9477 Yukihiro "Matz" Matsumoto (@matz)*
9592 Yukihiro "Matz" Matsumoto (@matz)*
586 KOBAYASHI Shuji (@shuujii)
533 dearblue (@dearblue)*
547 dearblue (@dearblue)*
378 Daniel Bovensiepen (@bovi)*
346 Takeshi Watanabe (@take-cheeze)*
334 Masaki Muranaka (@monaka)
@@ -12,7 +12,7 @@
234 Jun Hiroe (@suzukaze)
220 Cremno (@cremno)*
209 Yuki Kurihara (@ksss)+
166 John Bampton (@jbampton)
170 John Bampton (@jbampton)
151 Yasuhiro Matsumoto (@mattn)*
113 Carson McDonald (@carsonmcdonald)
103 Tomasz Dąbrowski (@dabroz)*
@@ -156,6 +156,7 @@
3 bamchoh (@bamchoh)
3 sasaki takeru (@takeru)
3 windwiny (@windwiny)
3 星湖新 (@hoshiumiarata)
2 Akira Moroo (@retrage)
2 Artur K (@nemerle)
2 Christian Mauceri (@mauceri)
@@ -290,6 +291,7 @@
1 Yusuke Tanaka (@csouls)
1 alpha.netzilla (@alpha-netzilla)
1 arton (@arton)
1 buty4649 (@buty4649)
1 duangsuse (@duangsuse)
1 fl0l0u (@fl0l0u)
1 hhc0null (@hhc0null)
+31
View File
@@ -4,10 +4,41 @@ LEGAL NOTICE INFORMATION
All the files in this distribution are covered under the MIT license
(see the file LICENSE) except some files mentioned below:
- src/string.c: mrb_memsearch_ss() is based on 2 clause BSD license code by Wojciech Muła (@WojciechMula)
- src/readfloat.c: public domain by Yasuhiro Matsumoto (@mattn)
- src/fmt_fp.c: public domain by Dave Hylands (@dhylands)
- mrbgems/mruby-dir/src/Win/dirent.c: MIT-like license by Kevlin Henney
[src/string.c]
The implementation of mrb_memsearch_ss() is taken from
https://github.com/WojciechMula/sse4-strstr.git
Copyright (c) 2008-2016, Wojciech Muła
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[src/readfloat.c]
strtod implementation.
+2
View File
@@ -798,6 +798,8 @@ MRB_API struct RClass * mrb_module_get_under_id(mrb_state *mrb, struct RClass *o
MRB_API void mrb_notimplement(mrb_state*);
/* a function to be replacement of unimplemented method */
MRB_API mrb_value mrb_notimplement_m(mrb_state*, mrb_value);
/* just return it self */
MRB_API mrb_value mrb_obj_itself(mrb_state*, mrb_value);
/**
* Duplicate an object.
+2 -2
View File
@@ -17,8 +17,8 @@ MRB_BEGIN_DECL
struct RException {
MRB_OBJECT_HEADER;
struct iv_tbl *iv;
struct RObject *mesg; // NULL or probably RString
struct RObject *backtrace; // NULL, RArray or RData
struct RBasic *mesg; // NULL or probably RString
struct RBasic *backtrace; // NULL, RArray or RData
};
/* error that should terminate execution */
+12
View File
@@ -61,6 +61,18 @@ mrb_value mrb_exc_mesg_get(mrb_state *mrb, struct RException *exc);
mrb_value mrb_f_raise(mrb_state*, mrb_value);
mrb_value mrb_make_exception(mrb_state *mrb, mrb_value exc, mrb_value mesg);
struct RBacktrace {
MRB_OBJECT_HEADER;
size_t len;
struct mrb_backtrace_location *locations;
};
struct mrb_backtrace_location {
mrb_sym method_id;
int32_t idx;
const mrb_irep *irep;
};
/* gc */
void mrb_gc_mark_mt(mrb_state*, struct RClass*);
size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*);
+12 -11
View File
@@ -79,18 +79,19 @@ struct RStringEmbed {
#define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE)
#ifdef MRB_UTF8_STRING
# define RSTR_ASCII_P(s) ((s)->flags & MRB_STR_ASCII)
# define RSTR_SET_ASCII_FLAG(s) ((s)->flags |= MRB_STR_ASCII)
# define RSTR_UNSET_ASCII_FLAG(s) ((s)->flags &= ~MRB_STR_ASCII)
# define RSTR_WRITE_ASCII_FLAG(s, v) (RSTR_UNSET_ASCII_FLAG(s), (s)->flags |= v)
# define RSTR_COPY_ASCII_FLAG(dst, src) RSTR_WRITE_ASCII_FLAG(dst, RSTR_ASCII_P(src))
# define RSTR_SINGLE_BYTE_P(s) ((s)->flags & MRB_STR_SINGLE_BYTE)
# define RSTR_SET_SINGLE_BYTE_FLAG(s) ((s)->flags |= MRB_STR_SINGLE_BYTE)
# define RSTR_UNSET_SINGLE_BYTE_FLAG(s) ((s)->flags &= ~MRB_STR_SINGLE_BYTE)
# define RSTR_WRITE_SINGLE_BYTE_FLAG(s, v) (RSTR_UNSET_SINGLE_BYTE_FLAG(s), (s)->flags |= v)
# define RSTR_COPY_SINGLE_BYTE_FLAG(dst, src) RSTR_WRITE_SINGLE_BYTE_FLAG(dst, RSTR_SINGLE_BYTE_P(src))
#else
# define RSTR_ASCII_P(s) (void)0
# define RSTR_SET_ASCII_FLAG(s) (void)0
# define RSTR_UNSET_ASCII_FLAG(s) (void)0
# define RSTR_WRITE_ASCII_FLAG(s, v) (void)0
# define RSTR_COPY_ASCII_FLAG(dst, src) (void)0
# define RSTR_SINGLE_BYTE_P(s) (void)1
# define RSTR_SET_SINGLE_BYTE_FLAG(s) (void)0
# define RSTR_UNSET_SINGLE_BYTE_FLAG(s) (void)0
# define RSTR_WRITE_SINGLE_BYTE_FLAG(s, v) (void)0
# define RSTR_COPY_SINGLE_BYTE_FLAG(dst, src) (void)0
#endif
#define RSTR_SET_ASCII_FLAG(s) RSTR_SET_SINGLE_BYTE_FLAG(s)
/**
* Returns a pointer from a Ruby string
@@ -108,7 +109,7 @@ struct RStringEmbed {
#define MRB_STR_FSHARED 2
#define MRB_STR_NOFREE 4
#define MRB_STR_EMBED 8 /* type flags up to here */
#define MRB_STR_ASCII 16
#define MRB_STR_SINGLE_BYTE 16
#define MRB_STR_EMBED_LEN_SHIFT 6
#define MRB_STR_EMBED_LEN_BIT 5
#define MRB_STR_EMBED_LEN_MASK (((1 << MRB_STR_EMBED_LEN_BIT) - 1) << MRB_STR_EMBED_LEN_SHIFT)
+2 -1
View File
@@ -159,7 +159,8 @@ static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000;
f(MRB_TT_BREAK, struct RBreak, "break") \
f(MRB_TT_COMPLEX, struct RComplex, "Complex") \
f(MRB_TT_RATIONAL, struct RRational, "Rational") \
f(MRB_TT_BIGINT, struct RBigint, "Integer")
f(MRB_TT_BIGINT, struct RBigint, "Integer") \
f(MRB_TT_BACKTRACE, struct RBacktrace, "backtrace")
enum mrb_vtype {
#define MRB_VTYPE_DEFINE(tt, type, name) tt,
+2
View File
@@ -372,6 +372,7 @@ module MRuby
def each(&b)
@ary.each(&b)
self
end
def [](name)
@@ -384,6 +385,7 @@ module MRuby
else
# GEM was already added to this list
end
self
end
def empty?
+4 -4
View File
@@ -478,7 +478,6 @@ udiv(mrb_state *mrb, mpz_t *qq, mpz_t *rr, mpz_t *xx, mpz_t *yy)
}
mpz_t q, x, y;
size_t i;
mrb_assert(!uzero(yy)); /* divided by zero */
mpz_init(mrb, &q);
@@ -502,6 +501,8 @@ udiv(mrb_state *mrb, mpz_t *qq, mpz_t *rr, mpz_t *xx, mpz_t *yy)
else
qhat = (((mp_dbl_limb)x.p[j+yd] << DIG_SIZE) + x.p[j+yd-1]) / z;
if (qhat) {
size_t i;
for (i=0; i<yd; i++) {
mp_dbl_limb zz = qhat * y.p[i];
mp_dbl_limb_signed u = LOW(b)+x.p[i+j]-LOW(zz);
@@ -512,7 +513,7 @@ udiv(mrb_state *mrb, mpz_t *qq, mpz_t *rr, mpz_t *xx, mpz_t *yy)
}
for (; b!=0; qhat--) {
mp_dbl_limb c = 0;
for (i=0; i<yd; i++) {
for (size_t i=0; i<yd; i++) {
c += (mp_dbl_limb)x.p[i+j] + (mp_dbl_limb)y.p[i];
x.p[i+j] = LOW(c);
c = HIGH(c);
@@ -1111,7 +1112,6 @@ mrb_bint_new_float(mrb_state *mrb, mrb_float x)
mrb_float bi = 1.0 / b;
size_t rn;
mp_limb *rp;
mp_limb f;
for (rn = 1; x >= b; rn++)
x *= bi;
@@ -1119,7 +1119,7 @@ mrb_bint_new_float(mrb_state *mrb, mrb_float x)
mpz_realloc(mrb, r, rn);
rp = r->p;
for (size_t i=rn-1;;i--) {
f = LOW((mp_limb)x);
mp_limb f = LOW((mp_limb)x);
x -= f;
mrb_assert(x < 1.0);
rp[i] = f;
+7 -9
View File
@@ -98,8 +98,8 @@ options_opt(struct options *opts)
while (++opts->argv, --opts->argc) {
opts->opt = *opts->argv;
/* empty || not start with `-` || `-` */
if (!opts->opt[0] || opts->opt[0] != '-' || !opts->opt[1]) return NULL;
/* not start with `-` || `-` */
if (opts->opt[0] != '-' || !opts->opt[1]) return NULL;
if (opts->opt[1] == '-') {
/* `--` */
@@ -278,10 +278,8 @@ main(int argc, char **argv)
{
mrb_state *mrb = mrb_open();
int n = -1;
int i;
struct _args args;
mrb_value ARGV;
mrb_ccontext *c;
mrb_value v;
if (mrb == NULL) {
@@ -297,7 +295,7 @@ main(int argc, char **argv)
else {
int ai = mrb_gc_arena_save(mrb);
ARGV = mrb_ary_new_capa(mrb, args.argc);
for (i = 0; i < args.argc; i++) {
for (int i = 0; i < args.argc; i++) {
char* utf8 = mrb_utf8_from_locale(args.argv[i], -1);
if (utf8) {
mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8));
@@ -307,7 +305,7 @@ main(int argc, char **argv)
mrb_define_global_const(mrb, "ARGV", ARGV);
mrb_gv_set(mrb, mrb_intern_lit(mrb, "$DEBUG"), mrb_bool_value(args.debug));
c = mrb_ccontext_new(mrb);
mrb_ccontext *c = mrb_ccontext_new(mrb);
if (args.verbose)
c->dump_result = TRUE;
if (args.check_syntax)
@@ -324,7 +322,7 @@ main(int argc, char **argv)
mrb_gv_set(mrb, mrb_intern_lit(mrb, "$0"), mrb_str_new_cstr(mrb, cmdline));
/* Load libraries */
for (i = 0; i < args.libc; i++) {
for (int i = 0; i < args.libc; i++) {
FILE *lfp = fopen(args.libv[i], "rb");
if (lfp == NULL) {
fprintf(stderr, "%s: Cannot open library file: %s\n", *argv, args.libv[i]);
@@ -334,10 +332,10 @@ main(int argc, char **argv)
}
mrb_ccontext_filename(mrb, c, args.libv[i]);
if (mrb_extension_p(args.libv[i])) {
v = mrb_load_irep_file_cxt(mrb, lfp, c);
mrb_load_irep_file_cxt(mrb, lfp, c);
}
else {
v = mrb_load_detect_file_cxt(mrb, lfp, c);
mrb_load_detect_file_cxt(mrb, lfp, c);
}
fclose(lfp);
mrb_vm_ci_env_clear(mrb, mrb->c->cibase);
+1 -7
View File
@@ -149,12 +149,6 @@ mrb_complex_to_i(mrb_state *mrb, mrb_value self)
return mrb_int_value(mrb, (mrb_int)p->real);
}
static mrb_value
complex_to_c(mrb_state *mrb, mrb_value self)
{
return self;
}
mrb_bool
mrb_complex_eq(mrb_state *mrb, mrb_value x, mrb_value y)
{
@@ -406,7 +400,7 @@ void mrb_mruby_complex_gem_init(mrb_state *mrb)
mrb_define_method(mrb, comp, "imaginary", complex_imaginary, MRB_ARGS_NONE());
mrb_define_method(mrb, comp, "to_f", mrb_complex_to_f, MRB_ARGS_NONE());
mrb_define_method(mrb, comp, "to_i", mrb_complex_to_i, MRB_ARGS_NONE());
mrb_define_method(mrb, comp, "to_c", complex_to_c, MRB_ARGS_NONE());
mrb_define_method(mrb, comp, "to_c", mrb_obj_itself, MRB_ARGS_NONE());
mrb_define_method(mrb, comp, "+", complex_add, MRB_ARGS_REQ(1));
mrb_define_method(mrb, comp, "-", complex_sub, MRB_ARGS_REQ(1));
mrb_define_method(mrb, comp, "*", complex_mul, MRB_ARGS_REQ(1));
+11
View File
@@ -840,6 +840,17 @@ module Enumerable
alias filter select
def grep_v(pattern, &block)
ary = []
self.each{|*val|
sv = val.__svalue
unless pattern === sv
ary.push((block)? block.call(*val): sv)
end
}
ary
end
##
# call-seq:
# enum.tally -> a_hash
+7
View File
@@ -195,3 +195,10 @@ end
assert("Enumerable#tally") do
assert_equal({"a"=>1, "b"=>2, "c"=>1}, ["a", "b", "c", "b"].tally)
end
assert("Enumerable#grep_v") do
a = [1, 2, 3, 4, 5, 0]
assert_equal [1, 5, 0], a.grep_v(2..4)
assert_equal [1, 2, 3, 4, 5, 0], a.grep_v(6..8)
assert_equal [2, 4, 6, 8, 10], a.grep_v(0) {|v| v * 2}
end
@@ -701,4 +701,72 @@ module Enumerable
result
end
##
# call-seq:
# enum.chunk -> enumerator
# enum.chunk { |arr| block } -> enumerator
#
# Each element in the returned enumerator is a 2-element array consisting of:
#
# - A value returned by the block.
# - An array ("chunk") containing the element for which that value was returned,
# and all following elements for which the block returned the same value:
#
# So that:
#
# - Each block return value that is different from its predecessor
# begins a new chunk.
# - Each block return value that is the same as its predecessor
# continues the same chunk.
#
# Example:
#
# e = (0..10).chunk {|i| (i / 3).floor } # => #<Enumerator: ...>
# # The enumerator elements.
# e.next # => [0, [0, 1, 2]]
# e.next # => [1, [3, 4, 5]]
# e.next # => [2, [6, 7, 8]]
# e.next # => [3, [9, 10]]
#
# You can use the special symbol <tt>:_alone</tt> to force an element
# into its own separate chuck:
#
# a = [0, 0, 1, 1]
# e = a.chunk{|i| i.even? ? :_alone : true }
# e.to_a # => [[:_alone, [0]], [:_alone, [0]], [true, [1, 1]]]
#
# You can use the special symbol <tt>:_separator</tt> or +nil+
# to force an element to be ignored (not included in any chunk):
#
# a = [0, 0, -1, 1, 1]
# e = a.chunk{|i| i < 0 ? :_separator : true }
# e.to_a # => [[true, [0, 0]], [true, [1, 1]]]
def chunk(&block)
return to_enum :chunk unless block
enum = self
Enumerator.new do |y|
last_value, arr = nil, []
enum.each do |element|
value = block.call(element)
case value
when :_alone
y.yield [last_value, arr] if arr.size > 0
y.yield [value, [element]]
last_value, arr = nil, []
when :_separator, nil
y.yield [last_value, arr] if arr.size > 0
last_value, arr = nil, []
when last_value
arr << element
else
raise 'symbols beginning with an underscore are reserved' if value.is_a?(Symbol) && value.to_s[0] == '_'
y.yield [last_value, arr] if arr.size > 0
last_value, arr = value, [element]
end
end
y.yield [last_value, arr] if arr.size > 0
end
end
end
@@ -598,3 +598,52 @@ assert 'Enumerator.produce' do
], enum.to_a
}
end
assert("Enumerable#chunk") do
chunk = [1, 2, 3, 1, 2].chunk
assert_equal Enumerator, chunk.class
result = chunk.with_index { |elt, i| elt - i }.to_a
assert_equal [[1, [1, 2, 3]], [-2, [1, 2]]], result
assert_equal Enumerator, [].chunk {}.class
e = [1, 2, 3]
recorded = []
e.chunk { |x| recorded << x }.to_a
assert_equal [1, 2, 3], recorded
e = [1, 2, 3, 2, 3, 2, 1]
result = e.chunk { |x| x < 3 && 1 || 0 }.to_a
assert_equal [[1, [1, 2]], [0, [3]], [1, [2]], [0, [3]], [1, [2, 1]]], result
e = [1, 2, 3]
assert_equal [[1, 2], [3]], e.chunk { |x| x > 2 }.map(&:last)
e = [1, 2, 3, 2, 1]
result = e.chunk { |x| x < 2 && :_alone }.to_a
assert_equal [[:_alone, [1]], [false, [2, 3, 2]], [:_alone, [1]]], result
e = [[1, 2]]
inner_value = []
e.chunk { |*x| inner_value << x }.to_a
assert_equal [[[1, 2]]], inner_value
e = [1, 2, 3, 3, 2, 1]
result = e.chunk { |x| x == 2 ? :_separator : 1 }.to_a
assert_equal [[1, [1]], [1, [3, 3]], [1, [1]]], result
e = [1, 2, 3, 2, 1]
result = e.chunk { |x| x == 2 ? nil : 1 }.to_a
assert_equal [[1, [1]], [1, [3]], [1, [1]]], result
e = [1, 2, 3, 2, 1]
assert_raise(RuntimeError) { e.chunk { |x| :_arbitrary }.to_a }
e = [1, 2, 3]
assert_raise(ArgumentError) { e.chunk(1) {} }
e = [1, 2, 3, 2, 1]
enum = e.chunk { |x| true }
assert_nil enum.size
end
-1
View File
@@ -288,7 +288,6 @@ mrb_sce_sys_fail(mrb_state *mrb, mrb_value cls)
if (argc == 1) {
msg = mrb_nil_value();
}
exc = mrb_obj_value(e);
mrb_sce_init(mrb, exc, msg, no);
mrb_exc_raise(mrb, exc);
return mrb_nil_value(); /* NOTREACHED */
+2 -2
View File
@@ -344,8 +344,8 @@ mrb_mruby_eval_gem_init(mrb_state* mrb)
{
mrb_define_module_function(mrb, mrb->kernel_module, "eval", f_eval, MRB_ARGS_ARG(1, 3));
mrb_define_method_id(mrb, mrb_class_get_id(mrb, MRB_SYM(BasicObject)), MRB_SYM(instance_eval), f_instance_eval, MRB_ARGS_OPT(3)|MRB_ARGS_BLOCK());
mrb_define_method_id(mrb, mrb_class_get_id(mrb, MRB_SYM(Module)), MRB_SYM(module_eval), f_class_eval, MRB_ARGS_OPT(3)|MRB_ARGS_BLOCK());
mrb_define_method_id(mrb, mrb_class_get_id(mrb, MRB_SYM(Module)), MRB_SYM(class_eval), f_class_eval, MRB_ARGS_OPT(3)|MRB_ARGS_BLOCK());
mrb_define_method_id(mrb, mrb->module_class, MRB_SYM(module_eval), f_class_eval, MRB_ARGS_OPT(3)|MRB_ARGS_BLOCK());
mrb_define_method_id(mrb, mrb->module_class, MRB_SYM(class_eval), f_class_eval, MRB_ARGS_OPT(3)|MRB_ARGS_BLOCK());
struct RClass *binding = mrb_class_get_id(mrb, MRB_SYM(Binding));
mrb_define_method(mrb, binding, "eval", mrb_binding_eval, MRB_ARGS_ANY());
+9 -9
View File
@@ -43,12 +43,12 @@ fiber_init_fiber(mrb_state *mrb, struct RFiber *f, const struct RProc *p)
c->stend = c->stbase + slen;
{
mrb_value *p = c->stbase;
mrb_value *pend = c->stend;
mrb_value *s = c->stbase;
mrb_value *send = c->stend;
while (p < pend) {
SET_NIL_VALUE(*p);
p++;
while (s < send) {
SET_NIL_VALUE(*s);
s++;
}
}
@@ -252,8 +252,6 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
}
fiber_switch_context(mrb, c);
if (status == MRB_FIBER_CREATED) {
mrb_value *b, *e;
if (!c->ci->proc) {
return fiber_error(mrb, "double resume (current)");
}
@@ -267,8 +265,10 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
}
else {
mrb_stack_extend(mrb, len+2); /* for receiver and (optional) block */
b = c->stbase+1;
e = b + len;
mrb_value *b = c->stbase+1;
mrb_value *e = b + len;
while (b<e) {
*b++ = *a++;
}
+6 -6
View File
@@ -24,14 +24,14 @@ hash_values_at(mrb_state *mrb, mrb_value hash)
{
const mrb_value *argv;
mrb_value result;
mrb_int argc, i;
mrb_int argc;
int ai;
mrb_get_args(mrb, "*", &argv, &argc);
result = mrb_ary_new_capa(mrb, argc);
if (argc == 0) return result;
ai = mrb_gc_arena_save(mrb);
for (i = 0; i < argc; i++) {
for (mrb_int i = 0; i < argc; i++) {
mrb_ary_push(mrb, result, mrb_hash_get(mrb, hash, argv[i]));
mrb_gc_arena_restore(mrb, ai);
}
@@ -53,12 +53,12 @@ hash_slice(mrb_state *mrb, mrb_value hash)
{
const mrb_value *argv;
mrb_value result;
mrb_int argc, i;
mrb_int argc;
mrb_get_args(mrb, "*", &argv, &argc);
result = mrb_hash_new_capa(mrb, argc);
if (argc == 0) return result; /* empty hash */
for (i = 0; i < argc; i++) {
for (mrb_int i = 0; i < argc; i++) {
mrb_value key = argv[i];
mrb_value val;
@@ -85,11 +85,11 @@ hash_except(mrb_state *mrb, mrb_value hash)
{
const mrb_value *argv;
mrb_value result;
mrb_int argc, i;
mrb_int argc;
mrb_get_args(mrb, "*", &argv, &argc);
result = mrb_hash_dup(mrb, hash);
for (i = 0; i < argc; i++) {
for (mrb_int i = 0; i < argc; i++) {
mrb_hash_delete_key(mrb, result, argv[i]);
}
return result;
+3 -2
View File
@@ -6,6 +6,7 @@
#define MRUBY_IO_H
#include <mruby.h>
#include <mruby/presym.h>
#ifdef MRB_NO_STDIO
# error IO and File conflicts 'MRB_NO_STDIO' in your build configuration
@@ -63,8 +64,8 @@ struct mrb_io {
#define MRB_O_DSYNC 0x00008000
#define MRB_O_RSYNC 0x00010000
#define E_IO_ERROR (mrb_exc_get(mrb, "IOError"))
#define E_EOF_ERROR (mrb_exc_get(mrb, "EOFError"))
#define E_IO_ERROR mrb_exc_get_id(mrb, MRB_SYM(IOError))
#define E_EOF_ERROR mrb_exc_get_id(mrb, MRB_SYM(EOFError))
int mrb_io_fileno(mrb_state *mrb, mrb_value io);
+2 -4
View File
@@ -120,15 +120,13 @@ mrb_file_s_unlink(mrb_state *mrb, mrb_value obj)
{
const mrb_value *argv;
mrb_int argc, i;
char *path;
mrb_get_args(mrb, "*", &argv, &argc);
for (i = 0; i < argc; i++) {
const char *utf8_path;
mrb_value pathv = argv[i];
mrb_ensure_string_type(mrb, pathv);
utf8_path = RSTRING_CSTR(mrb, pathv);
path = mrb_locale_from_utf8(utf8_path, -1);
const char *utf8_path = RSTRING_CSTR(mrb, pathv);
char *path = mrb_locale_from_utf8(utf8_path, -1);
if (UNLINK(path) < 0) {
mrb_locale_free(path);
mrb_sys_fail(mrb, utf8_path);
+6 -13
View File
@@ -102,12 +102,11 @@ io_get_open_fptr(mrb_state *mrb, mrb_value io)
static void
io_set_process_status(mrb_state *mrb, pid_t pid, int status)
{
struct RClass *c_process, *c_status;
struct RClass *c_status = NULL;
mrb_value v;
c_status = NULL;
if (mrb_class_defined_id(mrb, MRB_SYM(Process))) {
c_process = mrb_module_get_id(mrb, MRB_SYM(Process));
struct RClass *c_process = mrb_module_get_id(mrb, MRB_SYM(Process));
if (mrb_const_defined(mrb, mrb_obj_value(c_process), MRB_SYM(Status))) {
c_status = mrb_class_get_under_id(mrb, c_process, MRB_SYM(Status));
}
@@ -522,8 +521,6 @@ io_s_popen(mrb_state *mrb, mrb_value klass)
}
if (!doexec) {
// XXX
fflush(stdin);
fflush(stdout);
fflush(stderr);
}
@@ -1223,26 +1220,22 @@ time2timeval(mrb_state *mrb, mrb_value time)
static mrb_value
io_s_pipe(mrb_state *mrb, mrb_value klass)
{
mrb_value r = mrb_nil_value();
mrb_value w = mrb_nil_value();
struct mrb_io *fptr_r;
struct mrb_io *fptr_w;
int pipes[2];
if (io_pipe(mrb, pipes) == -1) {
mrb_sys_fail(mrb, "pipe");
}
r = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
fptr_r = io_alloc(mrb);
mrb_value r = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
struct mrb_io *fptr_r = io_alloc(mrb);
fptr_r->fd = pipes[0];
fptr_r->readable = 1;
DATA_TYPE(r) = &mrb_io_type;
DATA_PTR(r) = fptr_r;
io_init_buf(mrb, fptr_r);
w = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
fptr_w = io_alloc(mrb);
mrb_value w = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
struct mrb_io *fptr_w = io_alloc(mrb);
fptr_w->fd = pipes[1];
fptr_w->writable = 1;
fptr_w->sync = 1;
+1 -1
View File
@@ -59,7 +59,7 @@ mrb_f_caller(mrb_state *mrb, mrb_value self)
if (n < 0) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative size (%d)", n);
}
if (n == 0 || bt_len <= lev) {
if (n == 0) {
return mrb_ary_new(mrb);
}
if (bt_len <= n + lev) n = bt_len - lev - 1;
+6 -6
View File
@@ -74,7 +74,7 @@ atanh(double x)
}
else {
/* Basic formula for atanh */
y = 0.5 * (log(1.0+x) - log(1.0-x));
y = 0.5 * (log1p(x) - log1p(-x));
}
return y;
@@ -105,7 +105,7 @@ double erfc(double x);
double
erf(double x)
{
static const double two_sqrtpi = 1.128379167095512574;
static const double two_sqrtpi = 1.128379167095512574;
double sum = x;
double term = x;
double xsqr = x*x;
@@ -129,7 +129,7 @@ erf(double x)
double
erfc(double x)
{
static const double one_sqrtpi= 0.564189583547756287;
static const double one_sqrtpi = 0.564189583547756287;
double a = 1;
double b = x;
double c = x;
@@ -137,15 +137,15 @@ erfc(double x)
double q1;
double q2 = b/d;
double n = 1.0;
double t;
if (fabs(x) < 2.2) {
return 1.0 - erf(x);
return erfc(x);
}
if (x < 0.0) { /*signbit(x)*/
return 2.0 - erfc(-x);
}
do {
t = a*n+b*x;
double t = a*n+b*x;
a = b;
b = t;
t = c*n+d*x;
+1 -2
View File
@@ -176,7 +176,6 @@ static mrb_value
mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass *klass)
{
mrb_value ary;
struct RClass *oldklass;
khash_t(st) *set = kh_init(st, mrb);
if (!recur) {
@@ -187,8 +186,8 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass *kl
}
else {
khash_t(st) *undef = kh_init(st, mrb);
struct RClass *oldklass = NULL;
oldklass = NULL;
while (klass && (klass != oldklass)) {
method_entry_loop(mrb, klass, set, undef);
oldklass = klass;
+1 -2
View File
@@ -165,8 +165,7 @@ int_digits(mrb_state *mrb, mrb_value self)
}
while (mrb_bint_cmp(mrb, x, zero) > 0) {
mrb_value q = mrb_bint_mod(mrb, x, bv);
mrb_ary_push(mrb, digits, q);
mrb_ary_push(mrb, digits, mrb_bint_mod(mrb, x, bv));
x = mrb_bint_div(mrb, x, bv);
if (!mrb_bigint_p(x)) {
mrb_int n = mrb_integer(x);
+3 -6
View File
@@ -60,6 +60,8 @@ nil_to_i(mrb_state *mrb, mrb_value obj)
}
/*
* Document-method: Kernel#itself
*
* call-seq:
* obj.itself -> an_object
*
@@ -69,11 +71,6 @@ nil_to_i(mrb_state *mrb, mrb_value obj)
* string.itself.object_id == string.object_id #=> true
*
*/
static mrb_value
f_itself(mrb_state *mrb, mrb_value self)
{
return self;
}
/*
* call-seq:
@@ -122,7 +119,7 @@ mrb_mruby_object_ext_gem_init(mrb_state* mrb)
mrb_define_method(mrb, n, "to_h", nil_to_h, MRB_ARGS_NONE());
mrb_define_method(mrb, n, "to_i", nil_to_i, MRB_ARGS_NONE());
mrb_define_method(mrb, mrb->kernel_module, "itself", f_itself, MRB_ARGS_NONE());
mrb_define_method(mrb, mrb->kernel_module, "itself", mrb_obj_itself, MRB_ARGS_NONE());
mrb_define_method(mrb, mrb_class_get_id(mrb, MRB_SYM(BasicObject)), "instance_exec", obj_instance_exec, MRB_ARGS_ANY() | MRB_ARGS_BLOCK());
}
+4
View File
@@ -1,4 +1,5 @@
#include <mruby.h>
#include <mruby/error.h>
#include <mruby/gc.h>
#include <mruby/hash.h>
#include <mruby/class.h>
@@ -167,6 +168,9 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj)
case MRB_TT_ISTRUCT:
size += mrb_objspace_page_slot_size();
break;
case MRB_TT_BACKTRACE:
size += ((struct RBacktrace*)mrb_obj_ptr(obj))->len * sizeof(struct mrb_backtrace_location);
break;
/* zero heap size types.
* immediate VM stack values, contained within mrb_state, or on C stack */
case MRB_TT_TRUE:
+2
View File
@@ -45,7 +45,9 @@ There is no dependency on other mrbgems.
- V : 32-bit unsigned, VAX (little-endian) byte order
- v : 16-bit unsigned, VAX (little-endian) byte order
- x : null byte
- X : back up bytes
- Z : same as "a", except that null is added with \*
- @ : absolute position
## License
+26 -25
View File
@@ -291,27 +291,24 @@ static void
u64tostr(char *buf, size_t len, uint64_t n)
{
#ifdef MRB_NO_STDIO
char *bufend = buf + len;
char *p = bufend - 1;
mrb_assert(len > 0);
if (len < 1) {
if (n < 10) {
buf[0] = '0' + n;
buf[1] = '\0';
return;
}
char *bufend = buf + len;
char *p = bufend - 1;
*p-- = '\0';
len--;
if (n > 0) {
for (; len > 0 && n > 0; len--, n /= 10) {
*p-- = '0' + (n % 10);
}
p++;
for (; len > 0 && n > 0; len--, n /= 10) {
*p-- = '0' + (n % 10);
}
else if (len > 0) {
*p = '0';
len--;
}
p++;
memmove(buf, p, bufend - p);
#else
snprintf(buf, len, "%" PRIu64, n);
@@ -323,9 +320,7 @@ static void
i64tostr(char *buf, size_t len, int64_t n)
{
#ifdef MRB_NO_STDIO
if (len < 1) {
return;
}
mrb_assert(len > 0);
if (n < 0) {
*buf++ = '-';
@@ -731,7 +726,7 @@ unpack_str(mrb_state *mrb, const void *src, int slen, mrb_value ary, int count,
CHECK_UNPACK_LEN(mrb, slen, ary);
mrb_value dst;
const char *cp, *sptr;
const char *sptr;
int copylen;
sptr = (const char*)src;
@@ -741,6 +736,8 @@ unpack_str(mrb_state *mrb, const void *src, int slen, mrb_value ary, int count,
copylen = slen;
if (slen >= 0 && flags & PACK_FLAG_Z) { /* "Z" */
const char *cp;
if ((cp = (const char*)memchr(sptr, '\0', slen)) != NULL) {
copylen = (int)(cp - sptr);
if (count == -1) {
@@ -764,7 +761,6 @@ unpack_str(mrb_state *mrb, const void *src, int slen, mrb_value ary, int count,
static int
pack_hex(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, int count, unsigned int flags)
{
int a, b;
unsigned int ashift, bshift;
long slen;
char *dptr, *dptr0, *sptr;
@@ -793,7 +789,8 @@ pack_hex(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, int count,
dptr0 = dptr;
for (; count > 0; count -= 2) {
a = b = 0;
int a = 0, b = 0;
if (slen > 0) {
a = hex2int(*sptr++);
if (a < 0) break;
@@ -1498,19 +1495,17 @@ static mrb_value
mrb_pack_pack(mrb_state *mrb, mrb_value ary)
{
mrb_value o, result;
mrb_int aidx;
struct tmpl tmpl;
int count;
enum pack_type type;
int count, size;
unsigned int flags;
enum pack_dir dir;
enum pack_type type;
int ridx, size;
prepare_tmpl(mrb, &tmpl);
result = mrb_str_new(mrb, NULL, 128); /* allocate initial buffer */
aidx = 0;
ridx = 0;
mrb_int aidx = 0;
mrb_int ridx = 0;
while (has_tmpl(&tmpl)) {
dir = read_tmpl(mrb, &tmpl, &type, &size, &count, &flags);
@@ -1667,18 +1662,23 @@ pack_unpack(mrb_state *mrb, mrb_value str, int single)
switch (dir) {
case PACK_DIR_HEX:
srcidx += unpack_hex(mrb, sptr, srclen - srcidx, result, count, flags);
if (single) goto single_return;
continue;
case PACK_DIR_BSTR:
srcidx += unpack_bstr(mrb, sptr, srclen - srcidx, result, count, flags);
if (single) goto single_return;
continue;
case PACK_DIR_STR:
srcidx += unpack_str(mrb, sptr, srclen - srcidx, result, count, flags);
if (single) goto single_return;
continue;
case PACK_DIR_BASE64:
srcidx += unpack_base64(mrb, sptr, srclen - srcidx, result);
if (single) goto single_return;
continue;
case PACK_DIR_QENC:
srcidx += unpack_qenc(mrb, sptr, srclen - srcidx, result);
if (single) goto single_return;
continue;
default:
break;
@@ -1729,6 +1729,7 @@ pack_unpack(mrb_state *mrb, mrb_value str, int single)
}
}
if (single) {
single_return:
if (RARRAY_LEN(result) > 0) {
return RARRAY_PTR(result)[0];
}
+15
View File
@@ -156,3 +156,18 @@ assert 'pack/unpack "U"' do
assert_raise(RangeError) { [-1].pack("U") }
assert_raise(RangeError) { [0x40000000].pack("U") }
end
assert 'unpack1' do
d = 1234
assert_equal(d, [d].pack("i").unpack1("i"))
d = "foobar"
assert_equal(d, [d].pack("a*").unpack1("a*"))
assert_equal(d, [d].pack("A*").unpack1("A*"))
assert_equal(d, [d].pack("Z*").unpack1("Z*"))
assert_equal(d, [d].pack("m").unpack1("m"))
assert_equal(d, [d].pack("M").unpack1("M"))
d = "10010101"
assert_equal(d, [d].pack("b*").unpack1("b*"))
d = "f00b00"
assert_equal(d, [d].pack("h*").unpack1("h*"))
end
+7 -8
View File
@@ -344,28 +344,27 @@ mrb_ary_sample(mrb_state *mrb, mrb_value ary)
}
else {
mrb_value result;
mrb_int i, j;
if (n < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "negative sample number");
if (n > len) n = len;
result = mrb_ary_new_capa(mrb, n);
for (i=0; i<n; i++) {
mrb_int r;
for (mrb_int i=0; i<n; i++) {
mrb_int idx;
for (;;) {
retry:
r = rand_i(random, len);
idx = rand_i(random, len);
for (j=0; j<i; j++) {
if (mrb_integer(RARRAY_PTR(result)[j]) == r) {
for (mrb_int j=0; j<i; j++) {
if (mrb_integer(RARRAY_PTR(result)[j]) == idx) {
goto retry; /* retry if duplicate */
}
}
break;
}
mrb_ary_push(mrb, result, mrb_int_value(mrb, r));
mrb_ary_push(mrb, result, mrb_int_value(mrb, idx));
}
for (i=0; i<n; i++) {
for (mrb_int i=0; i<n; i++) {
mrb_int idx = mrb_integer(RARRAY_PTR(result)[i]);
mrb_value elem = RARRAY_PTR(ary)[idx];
mrb_ary_set(mrb, result, i, elem);
+3 -50
View File
@@ -254,47 +254,6 @@ rational_new_f(mrb_state *mrb, mrb_float f0)
}
#endif
static mrb_value
rational_s_new(mrb_state *mrb, mrb_value self)
{
mrb_int numerator, denominator;
#ifdef MRB_NO_FLOAT
mrb_get_args(mrb, "ii", &numerator, &denominator);
#else
mrb_value numv, denomv;
mrb_get_args(mrb, "oo", &numv, &denomv);
if (mrb_integer_p(numv)) {
numerator = mrb_integer(numv);
if (mrb_integer_p(denomv)) {
denominator = mrb_integer(denomv);
}
else {
mrb_float numf = (mrb_float)numerator;
mrb_float denomf = mrb_as_float(mrb, denomv);
return rational_new_f(mrb, numf/denomf);
}
}
else {
mrb_float numf = mrb_as_float(mrb, numv);
mrb_float denomf;
if (mrb_integer_p(denomv)) {
denomf = (mrb_float)mrb_integer(denomv);
}
else {
denomf = mrb_as_float(mrb, denomv);
}
return rational_new_f(mrb, numf/denomf);
}
#endif
return rational_new(mrb, numerator, denominator);
}
#ifndef MRB_NO_FLOAT
static mrb_float
rat_float(struct mrb_rational *p)
@@ -329,12 +288,6 @@ mrb_rational_to_i(mrb_state *mrb, mrb_value self)
return mrb_int_value(mrb, p->numerator / p->denominator);
}
static mrb_value
rational_to_r(mrb_state *mrb, mrb_value self)
{
return self;
}
static mrb_value
rational_negative_p(mrb_state *mrb, mrb_value self)
{
@@ -702,9 +655,10 @@ rational_div(mrb_state *mrb, mrb_value x)
static mrb_value
rational_pow(mrb_state *mrb, mrb_value x)
{
#ifndef MRB_NO_FLOAT
mrb_value y = mrb_get_arg1(mrb);
struct mrb_rational *p1 = rational_ptr(mrb, x);
#ifndef MRB_NO_FLOAT
double d1, d2;
switch (mrb_type(y)) {
@@ -770,14 +724,13 @@ void mrb_mruby_rational_gem_init(mrb_state *mrb)
MRB_SET_INSTANCE_TT(rat, MRB_TT_RATIONAL);
MRB_UNDEF_ALLOCATOR(rat);
mrb_undef_class_method(mrb, rat, "new");
mrb_define_class_method(mrb, rat, "_new", rational_s_new, MRB_ARGS_REQ(2));
mrb_define_method(mrb, rat, "numerator", rational_numerator, MRB_ARGS_NONE());
mrb_define_method(mrb, rat, "denominator", rational_denominator, MRB_ARGS_NONE());
#ifndef MRB_NO_FLOAT
mrb_define_method(mrb, rat, "to_f", mrb_rational_to_f, MRB_ARGS_NONE());
#endif
mrb_define_method(mrb, rat, "to_i", mrb_rational_to_i, MRB_ARGS_NONE());
mrb_define_method(mrb, rat, "to_r", rational_to_r, MRB_ARGS_NONE());
mrb_define_method(mrb, rat, "to_r", mrb_obj_itself, MRB_ARGS_NONE());
mrb_define_method(mrb, rat, "negative?", rational_negative_p, MRB_ARGS_NONE());
mrb_define_method(mrb, rat, "==", rational_eq, MRB_ARGS_REQ(1));
mrb_define_method(mrb, rat, "<=>", rational_cmp, MRB_ARGS_REQ(1));
+24 -22
View File
@@ -53,7 +53,7 @@ int_chr_utf8(mrb_state *mrb, mrb_value num)
char utf8[4];
mrb_int len;
mrb_value str;
uint32_t ascii_flag = 0;
uint32_t sb_flag = 0;
if (cp < 0 || 0x10FFFF < cp) {
mrb_raisef(mrb, E_RANGE_ERROR, "%v out of char range", num);
@@ -61,7 +61,7 @@ int_chr_utf8(mrb_state *mrb, mrb_value num)
if (cp < 0x80) {
utf8[0] = (char)cp;
len = 1;
ascii_flag = MRB_STR_ASCII;
sb_flag = MRB_STR_SINGLE_BYTE;
}
else if (cp < 0x800) {
utf8[0] = (char)(0xC0 | (cp >> 6));
@@ -82,7 +82,7 @@ int_chr_utf8(mrb_state *mrb, mrb_value num)
len = 4;
}
str = mrb_str_new(mrb, utf8, len);
mrb_str_ptr(str)->flags |= ascii_flag;
mrb_str_ptr(str)->flags |= sb_flag;
return str;
}
#endif
@@ -1304,10 +1304,6 @@ str_uplus(mrb_state *mrb, mrb_value str)
*
* Returns a frozen, possibly pre-existing copy of the string.
*
* The returned \String will be deduplicated as long as it does not have
* any instance variables set on it and is not a String subclass.
*
* String#dedup is an alias for String#-@.
*/
static mrb_value
str_uminus(mrb_state *mrb, mrb_value str)
@@ -1332,34 +1328,39 @@ str_valid_enc_p(mrb_state *mrb, mrb_value str)
#define utf8_islead(c) ((unsigned char)((c)&0xc0) != 0x80)
struct RString *s = mrb_str_ptr(str);
if (RSTR_ASCII_P(s)) return mrb_true_value();
if (RSTR_SINGLE_BYTE_P(s)) return mrb_true_value();
mrb_int byte_len = RSTR_LEN(s);
mrb_int utf8_len = 0;
const char *p = RSTR_PTR(s);
const char *e = p + byte_len;
while (p < e) {
mrb_int len = mrb_utf8len_table[(unsigned char)p[0] >> 3];
if (len == 0 || len > e - p)
return mrb_false_value();
switch (len) {
case 4:
if (utf8_islead(p[3])) return mrb_false_value();
case 3:
if (utf8_islead(p[2])) return mrb_false_value();
case 2:
if (utf8_islead(p[1])) return mrb_false_value();
default:
break;
}
mrb_int len = mrb_utf8len(p, e);
if (len == 1 && (*p & 0x80)) return mrb_false_value();
p += len;
utf8_len++;
}
if (byte_len == utf8_len) RSTR_SET_ASCII_FLAG(s);
if (byte_len == utf8_len) RSTR_SET_SINGLE_BYTE_FLAG(s);
#endif
return mrb_true_value();
}
static mrb_value
str_ascii_only_p(mrb_state *mrb, mrb_value str)
{
struct RString *s = mrb_str_ptr(str);
const char *p = RSTR_PTR(s);
const char *e = p + RSTR_LEN(s);
while (p < e) {
if (*p & 0x80) return mrb_false_value();
p++;
}
RSTR_SET_SINGLE_BYTE_FLAG(mrb_str_ptr(str));
return mrb_true_value();
}
void
mrb_mruby_string_ext_gem_init(mrb_state* mrb)
{
@@ -1398,6 +1399,7 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb)
mrb_define_method(mrb, s, "+@", str_uplus, MRB_ARGS_REQ(1));
mrb_define_method(mrb, s, "-@", str_uminus, MRB_ARGS_REQ(1));
mrb_define_method(mrb, s, "valid_encoding?", str_valid_enc_p, MRB_ARGS_NONE());
mrb_define_method(mrb, s, "ascii_only?", str_ascii_only_p, MRB_ARGS_NONE());
mrb_define_method(mrb, s, "__lines", str_lines, MRB_ARGS_NONE());
mrb_define_method(mrb, s, "__codepoints", str_codepoints, MRB_ARGS_NONE());
+4 -4
View File
@@ -215,18 +215,18 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, mrb_int len)
capa = len;
}
}
if (capa < len || capa > ARY_MAX_SIZE) {
if (capa > ARY_MAX_SIZE) {
ary_too_big(mrb);
}
if (ARY_EMBED_P(a)) {
mrb_value *ptr = ARY_EMBED_PTR(a);
mrb_int len = ARY_EMBED_LEN(a);
mrb_int slen = ARY_EMBED_LEN(a);
mrb_value *expanded_ptr = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*capa);
ARY_UNSET_EMBED_FLAG(a);
array_copy(expanded_ptr, ptr, len);
a->as.heap.len = len;
array_copy(expanded_ptr, ptr, slen);
a->as.heap.len = slen;
a->as.heap.aux.capa = capa;
a->as.heap.ptr = expanded_ptr;
}
+103 -95
View File
@@ -17,23 +17,30 @@
#include <mruby/internal.h>
#include <mruby/presym.h>
struct backtrace_location {
mrb_sym method_id;
int32_t idx;
const mrb_irep *irep;
};
typedef void (*each_backtrace_func)(mrb_state*, const struct backtrace_location*, void*);
static const mrb_data_type bt_type = { "Backtrace", mrb_free };
static uint32_t
each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, each_backtrace_func func, void *data)
static void
copy_backtrace(mrb_state *mrb,
const struct mrb_backtrace_location *loc,
struct mrb_backtrace_location *ptr,
size_t n)
{
uint32_t n = 0;
ptr[n] = *loc;
if (loc->irep) {
if (loc->irep->refcnt == UINT16_MAX) {
ptr[n].irep = NULL;
}
else {
mrb_irep_incref(mrb, (mrb_irep*)loc->irep);
}
}
}
static size_t
pack_backtrace(mrb_state *mrb, ptrdiff_t ciidx, struct mrb_backtrace_location *ptr)
{
size_t n = 0;
for (ptrdiff_t i=ciidx; i >= 0; i--) {
struct backtrace_location loc;
struct mrb_backtrace_location loc;
mrb_callinfo *ci;
const mrb_code *pc;
@@ -75,59 +82,42 @@ each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, each_backtrace_func func, void *
}
loc.irep = irep;
loc.idx = (uint32_t)(pc - loc.irep->iseq);
loc.idx = (uint32_t)(pc - irep->iseq);
break;
}
}
if (func) func(mrb, &loc, data);
copy_backtrace(mrb, &loc, ptr, n);
n++;
}
return n;
}
static void
pack_backtrace_i(mrb_state *mrb,
const struct backtrace_location *loc,
void *data)
{
struct backtrace_location **pptr = (struct backtrace_location**)data;
struct backtrace_location *ptr = *pptr;
*ptr = *loc;
*pptr = ptr+1;
}
static struct RObject*
static struct RBasic*
packed_backtrace(mrb_state *mrb)
{
struct RData *backtrace;
struct RBacktrace *backtrace;
ptrdiff_t ciidx = mrb->c->ci - mrb->c->cibase;
if (ciidx >= mrb->c->ciend - mrb->c->cibase)
ciidx = mrb->c->ciend - mrb->c->cibase; /* ciidx is broken... */
/* count the number of backtraces */
int len = each_backtrace(mrb, ciidx, NULL, NULL);
backtrace = mrb_data_object_alloc(mrb, NULL, NULL, &bt_type);
if (len > 0) {
void *ptr = mrb_malloc(mrb, len * sizeof(struct backtrace_location));
backtrace->data = ptr;
backtrace->flags = len;
each_backtrace(mrb, ciidx, pack_backtrace_i, &ptr);
}
else {
backtrace->data = NULL;
backtrace->flags = 0;
}
return (struct RObject*)backtrace;
ptrdiff_t len = ciidx + 1;
backtrace = MRB_OBJ_ALLOC(mrb, MRB_TT_BACKTRACE, NULL);
void *ptr = mrb_malloc(mrb, len * sizeof(struct mrb_backtrace_location));
backtrace->locations = (struct mrb_backtrace_location*)ptr;
backtrace->len = pack_backtrace(mrb, ciidx, backtrace->locations);
return (struct RBasic*)backtrace;
}
static void
store_backtrace(mrb_state *mrb, mrb_value exc, struct RObject *backtrace)
store_backtrace(mrb_state *mrb, mrb_value exc, struct RBasic *backtrace)
{
struct RException *e = mrb_exc_ptr(exc);
e->backtrace = backtrace;
mrb_field_write_barrier(mrb, (struct RBasic*)e, (struct RBasic*)backtrace);
mrb_field_write_barrier(mrb, (struct RBasic*)e, backtrace);
}
void
@@ -138,48 +128,52 @@ mrb_keep_backtrace(mrb_state *mrb, mrb_value exc)
if (mrb->c->ci == NULL) return;
if (mrb_exc_ptr(exc)->backtrace) return;
ai = mrb_gc_arena_save(mrb);
struct RObject *backtrace = packed_backtrace(mrb);
struct RBasic *backtrace = packed_backtrace(mrb);
store_backtrace(mrb, exc, backtrace);
mrb_gc_arena_restore(mrb, ai);
}
static struct RObject*
mrb_unpack_backtrace(mrb_state *mrb, struct RObject *backtrace)
static mrb_value
decode_location(mrb_state *mrb, const struct mrb_backtrace_location *entry)
{
const struct backtrace_location *bt;
mrb_int n, i;
int ai;
mrb_value btline;
int32_t lineno;
const char *filename;
if (!entry->irep || !mrb_debug_get_position(mrb, entry->irep, entry->idx, &lineno, &filename)) {
btline = mrb_str_new_lit(mrb, "(unknown):0");
}
else if (lineno != -1) {//debug info was available
btline = mrb_format(mrb, "%s:%d", filename, (int)lineno);
}
else { //all that was left was the stack frame
btline = mrb_format(mrb, "%s:0", filename);
}
if (entry->method_id != 0) {
mrb_str_cat_lit(mrb, btline, ":in ");
mrb_str_cat_cstr(mrb, btline, mrb_sym_name(mrb, entry->method_id));
}
return btline;
}
static struct RBasic*
mrb_unpack_backtrace(mrb_state *mrb, struct RBasic *backtrace)
{
if (backtrace == NULL) {
empty_backtrace:
return mrb_obj_ptr(mrb_ary_new_capa(mrb, 0));
return mrb_basic_ptr(mrb_ary_new_capa(mrb, 0));
}
if (backtrace->tt == MRB_TT_ARRAY) return backtrace;
bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, mrb_obj_value(backtrace), &bt_type);
if (bt == NULL) goto empty_backtrace;
n = (mrb_int)backtrace->flags;
if (n == 0) goto empty_backtrace;
backtrace = mrb_obj_ptr(mrb_ary_new_capa(mrb, n));
ai = mrb_gc_arena_save(mrb);
for (i = 0; i < n; i++) {
const struct backtrace_location *entry = &bt[i];
mrb_value btline;
int32_t lineno;
const char *filename;
if (!mrb_debug_get_position(mrb, entry->irep, entry->idx, &lineno, &filename)) {
btline = mrb_str_new_lit(mrb, "(unknown):0");
}
else if (lineno != -1) {//debug info was available
btline = mrb_format(mrb, "%s:%d", filename, (int)lineno);
}
else { //all that was left was the stack frame
btline = mrb_format(mrb, "%s:0", filename);
}
if (entry->method_id != 0) {
mrb_str_cat_lit(mrb, btline, ":in ");
mrb_str_cat_cstr(mrb, btline, mrb_sym_name(mrb, entry->method_id));
}
mrb_assert(backtrace->tt == MRB_TT_BACKTRACE);
struct RBacktrace *bt = (struct RBacktrace*)backtrace;
mrb_int n = bt ? (mrb_int)bt->len : 0;
const struct mrb_backtrace_location *loc = bt->locations;
backtrace = mrb_basic_ptr(mrb_ary_new_capa(mrb, n));
int ai = mrb_gc_arena_save(mrb);
for (mrb_int i = 0; i < n; i++) {
mrb_value btline = decode_location(mrb, &loc[i]);
mrb_ary_push(mrb, mrb_obj_value(backtrace), btline);
mrb_gc_arena_restore(mrb, ai);
}
@@ -190,7 +184,7 @@ mrb_unpack_backtrace(mrb_state *mrb, struct RObject *backtrace)
mrb_value
mrb_exc_backtrace(mrb_state *mrb, mrb_value exc)
{
struct RObject *backtrace = mrb_exc_ptr(exc)->backtrace;
struct RBasic *backtrace = mrb_exc_ptr(exc)->backtrace;
if (backtrace == NULL) {
return mrb_nil_value();
}
@@ -212,25 +206,40 @@ mrb_get_backtrace(mrb_state *mrb)
#ifndef MRB_NO_STDIO
static void
print_backtrace(mrb_state *mrb, struct RObject *exc, struct RArray *backtrace)
print_backtrace(mrb_state *mrb, struct RObject *exc, struct RBasic *ptr)
{
mrb_int i;
mrb_int n = (backtrace ? ARY_LEN(backtrace) : 0);
mrb_value *loc, mesg;
struct RArray *ary = NULL;
struct RBacktrace *bt = NULL;
mrb_int n = 0;
if (ptr) {
if (ptr->tt == MRB_TT_ARRAY) {
ary = (struct RArray*)ptr;
n = ARY_LEN(ary);
}
else {
bt = (struct RBacktrace*)ptr;
n = (mrb_int)bt->len;
}
}
if (n != 0) {
if (n > 1) {
fputs("trace (most recent call last):\n", stderr);
}
for (i=n-1,loc=&ARY_PTR(backtrace)[i]; i>0; i--,loc--) {
if (mrb_string_p(*loc)) {
mrb_value btline;
fputs("trace (most recent call last):\n", stderr);
for (mrb_int i=n-1; i>0; i--) {
if (ary) btline = ARY_PTR(ary)[i];
else btline = decode_location(mrb, &bt->locations[i]);
if (mrb_string_p(btline)) {
fprintf(stderr, "\t[%d] ", (int)i);
fwrite(RSTRING_PTR(*loc), (int)RSTRING_LEN(*loc), 1, stderr);
fwrite(RSTRING_PTR(btline), (int)RSTRING_LEN(btline), 1, stderr);
fputc('\n', stderr);
}
}
if (mrb_string_p(*loc)) {
fwrite(RSTRING_PTR(*loc), (int)RSTRING_LEN(*loc), 1, stderr);
if (ary) btline = ARY_PTR(ary)[0];
else btline = decode_location(mrb, &bt->locations[0]);
if (mrb_string_p(btline)) {
fwrite(RSTRING_PTR(btline), (int)RSTRING_LEN(btline), 1, stderr);
fputs(": ", stderr);
}
}
@@ -243,7 +252,7 @@ print_backtrace(mrb_state *mrb, struct RObject *exc, struct RArray *backtrace)
fwrite(nomem, sizeof(nomem)-1, 1, stderr);
}
else {
mesg = mrb_exc_inspect(mrb, mrb_obj_value(exc));
mrb_value mesg = mrb_exc_inspect(mrb, mrb_obj_value(exc));
fwrite(RSTRING_PTR(mesg), RSTRING_LEN(mesg), 1, stderr);
fputc('\n', stderr);
}
@@ -261,9 +270,8 @@ mrb_print_backtrace(mrb_state *mrb)
return;
}
struct RObject *backtrace = ((struct RException*)mrb->exc)->backtrace;
if (backtrace && backtrace->tt != MRB_TT_ARRAY) backtrace = mrb_unpack_backtrace(mrb, backtrace);
print_backtrace(mrb, mrb->exc, (struct RArray*)backtrace);
struct RBasic *backtrace = ((struct RException*)mrb->exc)->backtrace;
print_backtrace(mrb, mrb->exc, backtrace);
}
#else
MRB_API void
+2 -2
View File
@@ -24,7 +24,7 @@ mrb_exc_mesg_set(mrb_state *mrb, struct RException *exc, mrb_value mesg)
if (!mrb_string_p(mesg)) {
mesg = mrb_obj_as_string(mrb, mesg);
}
exc->mesg = mrb_obj_ptr(mesg);
exc->mesg = mrb_basic_ptr(mesg);
mrb_field_write_barrier_value(mrb, (struct RBasic*)exc, mesg);
}
@@ -160,7 +160,7 @@ set_backtrace(mrb_state *mrb, mrb_value exc, mrb_value backtrace)
p++;
}
}
mrb_exc_ptr(exc)->backtrace = mrb_obj_ptr(backtrace);
mrb_exc_ptr(exc)->backtrace = mrb_basic_ptr(backtrace);
mrb_field_write_barrier_value(mrb, mrb_basic_ptr(exc), backtrace);
}
+41 -31
View File
@@ -107,9 +107,11 @@
*/
typedef struct RVALUE RVALUE;
struct free_obj {
MRB_OBJECT_HEADER;
struct RBasic *next;
RVALUE *next;
};
struct RVALUE_initializer {
@@ -117,7 +119,7 @@ struct RVALUE_initializer {
char padding[sizeof(void*) * 4 - sizeof(uint32_t)];
};
typedef struct {
struct RVALUE {
union {
struct RVALUE_initializer init; /* must be first member to ensure initialization */
struct free_obj free;
@@ -136,7 +138,7 @@ typedef struct {
struct RException exc;
struct RBreak brk;
} as;
} RVALUE;
};
#ifdef GC_DEBUG
#define DEBUG(x) (x)
@@ -149,12 +151,11 @@ typedef struct {
#endif
typedef struct mrb_heap_page {
struct RBasic *freelist;
RVALUE *freelist;
struct mrb_heap_page *next;
struct mrb_heap_page *free_next;
mrb_bool old:1;
/* Flexible array members are not C++ compatible */
/* void* objects[]; */
RVALUE objects[MRB_HEAP_PAGE_SIZE];
} mrb_heap_page;
#define GC_STEP_SIZE 1024
@@ -181,12 +182,6 @@ mrb_static_assert(MRB_GC_RED <= GC_COLOR_MASK);
#define other_white_part(s) ((s)->current_white_part ^ GC_WHITES)
#define is_dead(s, o) (((o)->color & other_white_part(s) & GC_WHITES) || (o)->tt == MRB_TT_FREE)
/* We have removed `objects[]` from `mrb_heap_page` since it was not C++
* compatible. Using array index to get pointer after structure instead. */
/* #define objects(p) ((RVALUE*)p->objects) */
#define objects(p) ((RVALUE*)&p[1])
mrb_noreturn void mrb_raise_nomemory(mrb_state *mrb);
MRB_API void*
@@ -279,7 +274,7 @@ heap_p(mrb_gc *gc, struct RBasic *object)
while (page) {
RVALUE *p;
p = objects(page);
p = page->objects;
if (&p[0].as.basic <= object && object <= &p[MRB_HEAP_PAGE_SIZE - 1].as.basic) {
return TRUE;
}
@@ -299,14 +294,14 @@ mrb_object_dead_p(mrb_state *mrb, struct RBasic *object)
static void
add_heap(mrb_state *mrb, mrb_gc *gc)
{
mrb_heap_page *page = (mrb_heap_page*)mrb_calloc(mrb, 1, sizeof(mrb_heap_page) + MRB_HEAP_PAGE_SIZE * sizeof(RVALUE));
mrb_heap_page *page = (mrb_heap_page*)mrb_calloc(mrb, 1, sizeof(mrb_heap_page));
RVALUE *p, *e;
struct RBasic *prev = NULL;
RVALUE *prev = NULL;
for (p = objects(page), e=p+MRB_HEAP_PAGE_SIZE; p<e; p++) {
for (p = page->objects, e=p+MRB_HEAP_PAGE_SIZE; p<e; p++) {
p->as.free.tt = MRB_TT_FREE;
p->as.free.next = prev;
prev = &p->as.basic;
prev = p;
}
page->freelist = prev;
@@ -345,7 +340,7 @@ mrb_gc_init(mrb_state *mrb, mrb_gc *gc)
#endif
}
static void obj_free(mrb_state *mrb, struct RBasic *obj, int end);
static void obj_free(mrb_state *mrb, struct RBasic *obj, mrb_bool end);
static void
free_heap(mrb_state *mrb, mrb_gc *gc)
@@ -357,7 +352,7 @@ free_heap(mrb_state *mrb, mrb_gc *gc)
while (page) {
tmp = page;
page = page->next;
for (p = objects(tmp), e=p+MRB_HEAP_PAGE_SIZE; p<e; p++) {
for (p = tmp->objects, e=p+MRB_HEAP_PAGE_SIZE; p<e; p++) {
if (p->as.free.tt != MRB_TT_FREE)
obj_free(mrb, &p->as.basic, TRUE);
}
@@ -498,19 +493,19 @@ mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls)
add_heap(mrb, gc);
}
struct RBasic *p = gc->free_heaps->freelist;
gc->free_heaps->freelist = ((struct free_obj*)p)->next;
RVALUE *p = gc->free_heaps->freelist;
gc->free_heaps->freelist = p->as.free.next;
if (gc->free_heaps->freelist == NULL) {
gc->free_heaps = gc->free_heaps->free_next;
}
gc->live++;
gc_protect(mrb, gc, p);
*(RVALUE*)p = RVALUE_zero;
p->tt = ttype;
p->c = cls;
paint_partial_white(gc, p);
return p;
gc_protect(mrb, gc, &p->as.basic);
*p = RVALUE_zero;
p->as.basic.tt = ttype;
p->as.basic.c = cls;
paint_partial_white(gc, &p->as.basic);
return &p->as.basic;
}
static inline void
@@ -704,7 +699,7 @@ mrb_gc_mark(mrb_state *mrb, struct RBasic *obj)
}
static void
obj_free(mrb_state *mrb, struct RBasic *obj, int end)
obj_free(mrb_state *mrb, struct RBasic *obj, mrb_bool end)
{
DEBUG(fprintf(stderr, "obj_free(%p,tt=%d)\n",obj,obj->tt));
switch (obj->tt) {
@@ -823,6 +818,17 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end)
break;
#endif
case MRB_TT_BACKTRACE:
{
struct RBacktrace *bt = (struct RBacktrace*)obj;
for (size_t i = 0; i < bt->len; i++) {
const mrb_irep *irep = bt->locations[i].irep;
if (irep == NULL) continue;
mrb_irep_decref(mrb, (mrb_irep*)irep);
}
mrb_free(mrb, bt->locations);
}
default:
break;
}
@@ -969,6 +975,10 @@ gc_gray_counts(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
}
break;
case MRB_TT_BACKTRACE:
children += ((struct RBacktrace*)obj)->len;
break;
default:
break;
}
@@ -1064,7 +1074,7 @@ incremental_sweep_phase(mrb_state *mrb, mrb_gc *gc, size_t limit)
size_t tried_sweep = 0;
while (page && (tried_sweep < limit)) {
RVALUE *p = objects(page);
RVALUE *p = page->objects;
RVALUE *e = p + MRB_HEAP_PAGE_SIZE;
size_t freed = 0;
mrb_bool dead_slot = TRUE;
@@ -1080,7 +1090,7 @@ incremental_sweep_phase(mrb_state *mrb, mrb_gc *gc, size_t limit)
obj_free(mrb, &p->as.basic, FALSE);
if (p->as.basic.tt == MRB_TT_FREE) {
p->as.free.next = page->freelist;
page->freelist = (struct RBasic*)p;
page->freelist = p;
freed++;
}
else {
@@ -1524,7 +1534,7 @@ gc_each_objects(mrb_state *mrb, mrb_gc *gc, mrb_each_object_callback *callback,
while (page != NULL) {
RVALUE *p;
p = objects(page);
p = page->objects;
for (int i=0; i < MRB_HEAP_PAGE_SIZE; i++) {
if ((*callback)(mrb, &p[i].as.basic, data) == MRB_EACH_OBJ_BREAK)
return;
+13 -16
View File
@@ -744,18 +744,14 @@ flo_lshift(mrb_state *mrb, mrb_value x)
/* 15.2.9.3.13 */
/*
* Document-method: Float#to_f
*
* call-seq:
* flt.to_f -> self
*
* As <code>flt</code> is already a float, returns +self+.
*/
static mrb_value
flo_to_f(mrb_state *mrb, mrb_value num)
{
return num;
}
/* 15.2.9.3.11 */
/*
* call-seq:
@@ -1105,19 +1101,17 @@ flo_abs(mrb_state *mrb, mrb_value num)
/* 15.2.9.3.24 */
/*
* Document-method: Integer#to_i
* Document-method: Integer#to_int
*
* call-seq:
* int.to_i -> integer
* int.to_int -> integer
*
* As <i>int</i> is already an <code>Integer</code>, all these
* methods simply return the receiver.
*/
static mrb_value
int_to_i(mrb_state *mrb, mrb_value num)
{
return num;
}
mrb_value
mrb_int_mul(mrb_state *mrb, mrb_value x, mrb_value y)
{
@@ -1976,7 +1970,6 @@ MRB_API mrb_value
mrb_integer_to_str(mrb_state *mrb, mrb_value x, mrb_int base)
{
char buf[MRB_INT_BIT+1];
mrb_int val = mrb_integer(x);
if (base < 2 || 36 < base) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %i", base);
@@ -1986,6 +1979,7 @@ mrb_integer_to_str(mrb_state *mrb, mrb_value x, mrb_int base)
return mrb_bint_to_s(mrb, x, base);
}
#endif
mrb_int val = mrb_integer(x);
const char *p = mrb_int_to_cstr(buf, sizeof(buf), val, base);
mrb_assert(p != NULL);
mrb_value str = mrb_str_new_cstr(mrb, p);
@@ -2031,6 +2025,9 @@ cmpnum(mrb_state *mrb, mrb_value v1, mrb_value v2)
if (mrb_bigint_p(v1)) {
return mrb_bint_cmp(mrb, v1, v2);
}
if (mrb_bigint_p(v2)) {
return mrb_bint_cmp(mrb, mrb_bint_new_int(mrb, mrb_integer(v1)), v2);
}
#endif
#ifdef MRB_NO_FLOAT
@@ -2237,8 +2234,8 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method_id(mrb, integer, MRB_OPSYM(gt), num_gt, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, integer, MRB_OPSYM(ge), num_ge, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, integer, MRB_SYM(to_i), int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.24 */
mrb_define_method_id(mrb, integer, MRB_SYM(to_int), int_to_i, MRB_ARGS_NONE());
mrb_define_method_id(mrb, integer, MRB_SYM(to_i), mrb_obj_itself, MRB_ARGS_NONE()); /* 15.2.8.3.24 */
mrb_define_method_id(mrb, integer, MRB_SYM(to_int), mrb_obj_itself, MRB_ARGS_NONE());
mrb_define_method_id(mrb, integer, MRB_OPSYM(add), int_add, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */
mrb_define_method_id(mrb, integer, MRB_OPSYM(sub), int_sub, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */
@@ -2301,7 +2298,7 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method_id(mrb, fl, MRB_SYM(floor), flo_floor, MRB_ARGS_OPT(1)); /* 15.2.9.3.10 */
mrb_define_method_id(mrb, fl, MRB_SYM_Q(infinite),flo_infinite_p, MRB_ARGS_NONE()); /* 15.2.9.3.11 */
mrb_define_method_id(mrb, fl, MRB_SYM(round), flo_round, MRB_ARGS_OPT(1)); /* 15.2.9.3.12 */
mrb_define_method_id(mrb, fl, MRB_SYM(to_f), flo_to_f, MRB_ARGS_NONE()); /* 15.2.9.3.13 */
mrb_define_method_id(mrb, fl, MRB_SYM(to_f), mrb_obj_itself, MRB_ARGS_NONE()); /* 15.2.9.3.13 */
mrb_define_method_id(mrb, fl, MRB_SYM(to_i), flo_to_i, MRB_ARGS_NONE()); /* 15.2.9.3.14 */
mrb_define_method_id(mrb, fl, MRB_SYM(truncate), flo_truncate, MRB_ARGS_OPT(1)); /* 15.2.9.3.15 */
mrb_define_method_id(mrb, fl, MRB_SYM(divmod), flo_divmod, MRB_ARGS_REQ(1));
+6
View File
@@ -649,3 +649,9 @@ mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2)
if (mrb_class(mrb, obj1) != mrb_class(mrb, obj2)) return FALSE;
return mrb_test(mrb_funcall_argv(mrb, obj1, MRB_SYM_Q(eql), 1, &obj2));
}
MRB_API mrb_value
mrb_obj_itself(mrb_state *mrb, mrb_value self)
{
return self;
}
+3
View File
@@ -161,6 +161,9 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep)
}
mrb_free(mrb, (void*)irep->lv);
mrb_debug_info_free(mrb, irep->debug_info);
#ifdef MRB_DEBUG
memset(irep, -1, sizeof(*irep));
#endif
mrb_free(mrb, irep);
}
+302 -147
View File
@@ -263,7 +263,138 @@ mrb_gc_free_str(mrb_state *mrb, struct RString *str)
mrb_free(mrb, str->as.heap.ptr);
}
#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \
defined(__powerpc64__) || defined(__POWERPC__) || defined(__aarch64__) || \
defined(__mc68020__)
# define ALIGNED_WORD_ACCESS 0
#else
# define ALIGNED_WORD_ACCESS 1
#endif
#ifdef MRB_UTF8_STRING
#define NOASCII(c) ((c) & 0x80)
#ifdef SIMPLE_SEARCH_NONASCII
/* the naive implementation. define SIMPLE_SEARCH_NONASCII, */
/* if you need it for any constraint (e.g. code size). */
static const char*
search_nonascii(const char* p, const char *e)
{
for (; p < e; ++p) {
if (NOASCII(*p)) return p;
}
return e;
}
#elif defined(__SSE2__)
# include <emmintrin.h>
static inline const char *
search_nonascii(const char *p, const char *e)
{
if (sizeof(__m128i) < (size_t)(e - p)) {
if (!_mm_movemask_epi8(_mm_loadu_si128((__m128i const*)p))) {
const intptr_t lowbits = sizeof(__m128i) - 1;
const __m128i *s, *t;
s = (const __m128i*)(~lowbits & ((intptr_t)p + lowbits));
t = (const __m128i*)(~lowbits & (intptr_t)e);
for (; s < t; ++s) {
if (_mm_movemask_epi8(_mm_load_si128(s))) break;
}
p = (const char *)s;
}
}
switch (e - p) {
default:
case 15: if (NOASCII(*p)) return p; ++p;
case 14: if (NOASCII(*p)) return p; ++p;
case 13: if (NOASCII(*p)) return p; ++p;
case 12: if (NOASCII(*p)) return p; ++p;
case 11: if (NOASCII(*p)) return p; ++p;
case 10: if (NOASCII(*p)) return p; ++p;
case 9: if (NOASCII(*p)) return p; ++p;
case 8: if (NOASCII(*p)) return p; ++p;
case 7: if (NOASCII(*p)) return p; ++p;
case 6: if (NOASCII(*p)) return p; ++p;
case 5: if (NOASCII(*p)) return p; ++p;
case 4: if (NOASCII(*p)) return p; ++p;
case 3: if (NOASCII(*p)) return p; ++p;
case 2: if (NOASCII(*p)) return p; ++p;
case 1: if (NOASCII(*p)) return p; ++p;
if (NOASCII(*p)) return p;
}
return e;
}
#else
#ifdef MRB_64BIT
# define NONASCII_MASK 0x8080808080808080ULL
#else /* MRB_32BIT */
# define NONASCII_MASK 0x80808080UL
#endif
static const char*
search_nonascii(const char *p, const char *e)
{
if (e - p >= sizeof(void*)) {
#if ALIGNED_WORD_ACCESS
if ((uintptr_t)p % sizeof(void*)) {
int l = sizeof(void*) - (uintptr_t)p % sizeof(void*);
p += l;
switch (l) {
#ifdef MRB_64BIT
case 7: if (p[-7]&0x80) return p-7;
case 6: if (p[-6]&0x80) return p-6;
case 5: if (p[-5]&0x80) return p-5;
case 4: if (p[-4]&0x80) return p-4;
#endif
case 3: if (p[-3]&0x80) return p-3;
case 2: if (p[-2]&0x80) return p-2;
case 1: if (p[-1]&0x80) return p-1;
case 0: break;
}
}
#endif
const uintptr_t *s = (uintptr_t*)p;
const uintptr_t *t = (uintptr_t*)(e - (sizeof(void*)-1));
for (;s < t; s++) {
if (*s & NONASCII_MASK) {
p = (const char*)s;
if (NOASCII(p[0])) return p+0;
if (NOASCII(p[1])) return p+1;
if (NOASCII(p[2])) return p+2;
if (NOASCII(p[3])) return p+3;
#ifdef MRB_64BIT
if (NOASCII(p[4])) return p+4;
if (NOASCII(p[5])) return p+5;
if (NOASCII(p[6])) return p+6;
if (NOASCII(p[7])) return p+7;
#endif
}
}
}
switch (e - p) {
default:
#ifdef MRB_64BIT
case 7: if (e[-7]&0x80) return e-7;
case 6: if (e[-6]&0x80) return e-6;
case 5: if (e[-5]&0x80) return e-5;
case 4: if (e[-4]&0x80) return e-4;
#endif
case 3: if (e[-3]&0x80) return e-3;
case 2: if (e[-2]&0x80) return e-2;
case 1: if (e[-1]&0x80) return e-1;
}
return e;
}
#endif /* SIMPLE_SEARCH_NONASCII */
#define utf8_islead(c) ((unsigned char)((c)&0xc0) != 0x80)
extern const char mrb_utf8len_table[];
@@ -278,7 +409,7 @@ mrb_utf8len(const char* p, const char* e)
mrb_int len = mrb_utf8len_table[(unsigned char)p[0] >> 3];
if (len > e - p) return 1;
switch (len) {
case 1:
case 0:
return 1;
case 4:
if (utf8_islead(p[3])) return 1;
@@ -309,12 +440,12 @@ utf8_strlen(mrb_value str)
struct RString *s = mrb_str_ptr(str);
mrb_int byte_len = RSTR_LEN(s);
if (RSTR_ASCII_P(s)) {
if (RSTR_SINGLE_BYTE_P(s)) {
return byte_len;
}
else {
mrb_int utf8_len = mrb_utf8_strlen(RSTR_PTR(s), byte_len);
if (byte_len == utf8_len) RSTR_SET_ASCII_FLAG(s);
if (byte_len == utf8_len) RSTR_SET_SINGLE_BYTE_FLAG(s);
return utf8_len;
}
}
@@ -325,33 +456,62 @@ utf8_strlen(mrb_value str)
static mrb_int
chars2bytes(mrb_value s, mrb_int off, mrb_int idx)
{
if (RSTR_ASCII_P(mrb_str_ptr(s))) {
if (RSTR_SINGLE_BYTE_P(mrb_str_ptr(s))) {
return idx;
}
else {
mrb_int i, b, n;
const char *p = RSTRING_PTR(s) + off;
const char *e = RSTRING_END(s);
for (b=i=0; p<e && i<idx; i++) {
n = mrb_utf8len(p, e);
b += n;
p += n;
const char *p0 = RSTRING_PTR(s) + off;
const char *p = p0;
const char *e = RSTRING_END(s);
mrb_int i = 0;
while (p<e && i<idx) {
if ((*p & 0x80) == 0) {
const char *np = search_nonascii(p, e);
ptrdiff_t alen = np - p;
if (idx < i+alen) {
p += idx-i;
i=idx;
}
else {
p = np;
i += alen;
}
}
else {
p += mrb_utf8len(p, e);
i++;
}
return b;
}
mrb_int len = (mrb_int)(p-p0);
if (i<idx) len++;
return len;
}
/* map byte offset to character index */
static mrb_int
bytes2chars(char *p, mrb_int len, mrb_int bi)
bytes2chars(mrb_value s, mrb_int bi)
{
const char *e = p + (size_t)len;
const char *pivot = p + bi;
mrb_int i;
if (RSTR_SINGLE_BYTE_P(mrb_str_ptr(s))) {
return bi;
}
for (i = 0; p < pivot; i++) {
p += mrb_utf8len(p, e);
const char *p = RSTRING_PTR(s);
const char *pivot = p + bi;
mrb_int i = 0;
if (RSTRING_END(s) < pivot) return -1;
while (p < pivot) {
if ((*p & 0x80) == 0) {
const char *np = search_nonascii(p, pivot);
i += np - p;
p = np;
}
else {
p += mrb_utf8len(p, pivot);
i++;
}
}
if (p != pivot) return -1;
return i;
@@ -380,135 +540,135 @@ char_backtrack(const char *ptr, const char *end)
}
static mrb_int
str_index_str_by_char_search(mrb_state *mrb, const char *p, const char *pend, const char *s, const mrb_int slen, mrb_int off)
str_index_str_by_char(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
{
/* Based on Quick Search algorithm (Boyer-Moore-Horspool algorithm) */
const char *ptr = RSTRING_PTR(sub);
mrb_int len = RSTRING_LEN(sub);
ptrdiff_t qstable[1 << CHAR_BIT];
if (pos > 0) {
pos = chars2bytes(str, 0, pos);
}
/* Preprocessing */
{
mrb_int i;
pos = mrb_str_index(mrb, str, ptr, len, pos);
for (i = 0; i < 1 << CHAR_BIT; i++) {
qstable[i] = slen;
}
for (i = 0; i < slen; i++) {
qstable[(unsigned char)s[i]] = slen - (i + 1);
if (pos > 0) {
pos = bytes2chars(str, pos);
}
return pos;
}
#else
#define RSTRING_CHAR_LEN(s) RSTRING_LEN(s)
#define chars2bytes(s, off, ci) (ci)
#define bytes2chars(s, bi) (bi)
#define char_adjust(beg, end, ptr) (ptr)
#define char_backtrack(ptr, end) ((end) - 1)
#define str_index_str_by_char(mrb, str, sub, pos) str_index_str((mrb), (str), (sub), (pos))
#endif
/* memsearch_swar (SWAR stands for SIMD within a register) */
/* See https://en.wikipedia.org/wiki/SWAR */
/* The function is taken from http://0x80.pl/articles/simd-strfind.html */
/* The original source code is under 2-clause BSD license; see LEGAL file. */
/* The modifications:
* port from C++ to C
* returns mrb_int
* remove alignment issue
* support bigendian CPU
* fixed potential buffer overflow
*/
static inline mrb_int
memsearch_swar(const char *xs, mrb_int m, const char *ys, mrb_int n)
{
#ifdef MRB_64BIT
#define bitint uint64_t
#define MASK1 0x0101010101010101ull
#define MASK2 0x7f7f7f7f7f7f7f7full
#define MASK3 0x8080808080808080ull
#else
#define bitint uint32_t
#define MASK1 0x01010101ul
#define MASK2 0x7f7f7f7ful
#define MASK3 0x80808080ul
#endif
#if defined(MRB_ENDIAN_BIG)
#ifdef MRB_64BIT
#define MASK4 0x8000000000000000ull
#else
#define MASK4 0x80000000ul
#endif
#else
#define MASK4 0x80
#endif
const bitint first = MASK1 * (uint8_t)xs[0];
const bitint last = MASK1 * (uint8_t)xs[m-1];
const char *s0 = ys;
const char *s1 = ys+m-1;
const mrb_int lim = n - m - (mrb_int)sizeof(bitint);
mrb_int i;
for (i=0; i < lim; i+=sizeof(bitint)) {
bitint t0, t1;
memcpy(&t0, s0+i, sizeof(bitint));
memcpy(&t1, s1+i, sizeof(bitint));
const bitint eq = (t0 ^ first) | (t1 ^ last);
bitint zeros = ((~eq & MASK2) + MASK1) & (~eq & MASK3);
for (size_t j = 0; zeros; j++) {
if (zeros & MASK4) {
const mrb_int idx = i + j;
const char* p = s0 + idx + 1;
if (memcmp(p, xs + 1, m - 2) == 0) {
return idx;
}
}
#if defined(MRB_ENDIAN_BIG)
zeros <<= 8;
#else
zeros >>= 8;
#endif
}
}
/* Searching */
while (p < pend && pend - p >= slen) {
const char *pivot;
if (memcmp(p, s, slen) == 0) {
return off;
if (i+m < n) {
const char *p = s0;
const char *e = ys + n;
for (;p<e;) {
size_t len = e - p;
p = (const char*)memchr(p, *xs, len);
if (p == NULL || (e - p) < m) break;
if (memcmp(p+1, xs+1, m-1) == 0) return (mrb_int)(p - ys);
p++;
}
pivot = p + qstable[(unsigned char)p[slen - 1]];
if (pivot >= pend || pivot < p /* overflowed */) { return -1; }
do {
p += mrb_utf8len(p, pend);
off++;
} while (p < pivot);
}
return -1;
}
static mrb_int
str_index_str_by_char(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
mrb_memsearch(const char *x, mrb_int m, const char *y, mrb_int n)
{
const char *p = RSTRING_PTR(str);
const char *pend = p + RSTRING_LEN(str);
const char *s = RSTRING_PTR(sub);
const mrb_int slen = RSTRING_LEN(sub);
mrb_int off = pos;
for (; pos > 0; pos --) {
if (pend - p < 1) { return -1; }
p += mrb_utf8len(p, pend);
}
if (slen < 1) { return off; }
return str_index_str_by_char_search(mrb, p, pend, s, slen, off);
}
#define BYTES_ALIGN_CHECK(pos) if (pos < 0) return mrb_nil_value();
#else
#define RSTRING_CHAR_LEN(s) RSTRING_LEN(s)
#define chars2bytes(p, off, ci) (ci)
#define bytes2chars(p, end, bi) (bi)
#define char_adjust(beg, end, ptr) (ptr)
#define char_backtrack(ptr, end) ((end) - 1)
#define BYTES_ALIGN_CHECK(pos)
#define str_index_str_by_char(mrb, str, sub, pos) str_index_str(mrb, str, sub, pos)
#endif
#ifndef MRB_QS_SHORT_STRING_LENGTH
#define MRB_QS_SHORT_STRING_LENGTH 2048
#endif
static inline mrb_int
mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n)
{
if (n + m < MRB_QS_SHORT_STRING_LENGTH) {
const unsigned char *y = ys;
const unsigned char *ye = ys+n-m+1;
for (;;) {
y = (const unsigned char*)memchr(y, xs[0], (size_t)(ye-y));
if (y == NULL) return -1;
if (memcmp(xs, y, m) == 0) {
return (mrb_int)(y - ys);
}
y++;
}
return -1;
}
else {
const unsigned char *x = xs, *xe = xs + m;
const unsigned char *y = ys;
ptrdiff_t qstable[256];
/* Preprocessing */
for (int i = 0; i < 256; i++)
qstable[i] = m + 1;
for (; x < xe; x++)
qstable[*x] = xe - x;
/* Searching */
for (; y + m <= ys + n; y += *(qstable + y[m])) {
if (*xs == *y && memcmp(xs, y, m) == 0)
return (mrb_int)(y - ys);
}
return -1;
}
}
static mrb_int
mrb_memsearch(const void *x0, mrb_int m, const void *y0, mrb_int n)
{
const unsigned char *x = (const unsigned char*)x0, *y = (const unsigned char*)y0;
if (m > n) return -1;
else if (m == n) {
return memcmp(x0, y0, m) == 0 ? 0 : -1;
return memcmp(x, y, m) == 0 ? 0 : -1;
}
else if (m < 1) {
return 0;
}
else if (m == 1) {
const unsigned char *ys = (const unsigned char*)memchr(y, *x, n);
const char *p = (const char*)memchr(y, *x, n);
if (ys)
return (mrb_int)(ys - y);
else
return -1;
if (p) return (mrb_int)(p - y);
return -1;
}
return mrb_memsearch_qs((const unsigned char*)x0, m, (const unsigned char*)y0, n);
return memsearch_swar(x, m, y, n);
}
static void
@@ -551,21 +711,16 @@ mrb_str_byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
s->as.heap.ptr += (mrb_ssize)beg;
s->as.heap.len = (mrb_ssize)len;
}
RSTR_COPY_ASCII_FLAG(s, orig);
RSTR_COPY_SINGLE_BYTE_FLAG(s, orig);
return mrb_obj_value(s);
}
static void
str_range_to_bytes(mrb_value str, mrb_int *pos, mrb_int *len)
{
*pos = chars2bytes(str, 0, *pos);
*len = chars2bytes(str, *pos, *len);
}
#ifdef MRB_UTF8_STRING
static inline mrb_value
str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
{
str_range_to_bytes(str, &beg, &len);
beg = chars2bytes(str, 0, beg);
len = chars2bytes(str, beg, len);
return mrb_str_byte_subseq(mrb, str, beg, len);
}
#else
@@ -639,7 +794,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
mrb_check_frozen(mrb, s1);
if (s1 == s2) return mrb_obj_value(s1);
RSTR_COPY_ASCII_FLAG(s1, s2);
RSTR_COPY_SINGLE_BYTE_FLAG(s1, s2);
if (RSTR_SHARED_P(s1)) {
str_decref(mrb, s1->as.heap.aux.shared);
}
@@ -765,7 +920,7 @@ MRB_API void
mrb_str_modify(mrb_state *mrb, struct RString *s)
{
mrb_str_modify_keep_ascii(mrb, s);
RSTR_UNSET_ASCII_FLAG(s);
RSTR_UNSET_SINGLE_BYTE_FLAG(s);
}
MRB_API mrb_value
@@ -903,7 +1058,7 @@ mrb_str_times(mrb_state *mrb, mrb_value self)
memcpy(p + n, p, len-n);
}
p[RSTR_LEN(str2)] = '\0';
RSTR_COPY_ASCII_FLAG(str2, mrb_str_ptr(self));
RSTR_COPY_SINGLE_BYTE_FLAG(str2, mrb_str_ptr(self));
return mrb_obj_value(str2);
}
@@ -1213,7 +1368,7 @@ str_escape(mrb_state *mrb, mrb_value str, mrb_bool inspect)
char buf[4]; /* `\x??` or UTF-8 character */
mrb_value result = mrb_str_new_lit(mrb, "\"");
#ifdef MRB_UTF8_STRING
uint32_t ascii_flag = MRB_STR_ASCII;
uint32_t sb_flag = MRB_STR_SINGLE_BYTE;
#endif
p = RSTRING_PTR(str); pend = RSTRING_END(str);
@@ -1225,7 +1380,7 @@ str_escape(mrb_state *mrb, mrb_value str, mrb_bool inspect)
if (clen > 1) {
mrb_str_cat(mrb, result, p, clen);
p += clen-1;
ascii_flag = 0;
sb_flag = 0;
continue;
}
}
@@ -1267,11 +1422,11 @@ str_escape(mrb_state *mrb, mrb_value str, mrb_bool inspect)
mrb_str_cat_lit(mrb, result, "\"");
#ifdef MRB_UTF8_STRING
if (inspect) {
mrb_str_ptr(str)->flags |= ascii_flag;
mrb_str_ptr(result)->flags |= ascii_flag;
mrb_str_ptr(str)->flags |= sb_flag;
mrb_str_ptr(result)->flags |= sb_flag;
}
else {
RSTR_SET_ASCII_FLAG(mrb_str_ptr(result));
RSTR_SET_SINGLE_BYTE_FLAG(mrb_str_ptr(result));
}
#endif
@@ -1297,7 +1452,8 @@ mrb_str_aset(mrb_state *mrb, mrb_value str, mrb_value indx, mrb_value alen, mrb_
if (beg < 0 || beg > charlen) { str_out_of_index(mrb, indx); }
/* fall through */
case STR_CHAR_RANGE_CORRECTED:
str_range_to_bytes(str, &beg, &len);
beg = chars2bytes(str, 0, beg);
len = chars2bytes(str, beg, len);
/* fall through */
case STR_BYTE_RANGE_CORRECTED:
if (mrb_int_add_overflow(beg, len, &len)) {
@@ -1791,7 +1947,7 @@ mrb_str_byteindex_m(mrb_state *mrb, mrb_value str)
static mrb_value
mrb_str_index_m(mrb_state *mrb, mrb_value str)
{
if (RSTR_ASCII_P(mrb_str_ptr(str))) {
if (RSTR_SINGLE_BYTE_P(mrb_str_ptr(str))) {
return mrb_str_byteindex_m(mrb, str);
}
@@ -2062,7 +2218,7 @@ mrb_str_byterindex_m(mrb_state *mrb, mrb_value str)
static mrb_value
mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
{
if (RSTR_ASCII_P(mrb_str_ptr(str))) {
if (RSTR_SINGLE_BYTE_P(mrb_str_ptr(str))) {
return mrb_str_byterindex_m(mrb, str);
}
@@ -2070,8 +2226,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
mrb_int pos;
if (mrb_get_args(mrb, "S|i", &sub, &pos) == 1) {
pos = RSTRING_CHAR_LEN(str);
pos = chars2bytes(str, 0, pos);
pos = RSTRING_LEN(str);
}
else if (pos >= 0) {
pos = chars2bytes(str, 0, pos);
@@ -2087,8 +2242,8 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
}
pos = str_rindex(mrb, str, sub, pos);
if (pos >= 0) {
pos = bytes2chars(RSTRING_PTR(str), RSTRING_LEN(str), pos);
BYTES_ALIGN_CHECK(pos);
pos = bytes2chars(str, pos);
if (pos < 0) return mrb_nil_value();
return mrb_int_value(mrb, pos);
}
return mrb_nil_value();
+3 -7
View File
@@ -441,6 +441,8 @@ sym_name(mrb_state *mrb, mrb_value vsym)
/* 15.2.11.3.4 */
/*
* Document-method: Symbol#to_sym
*
* call-seq:
* sym.to_sym -> sym
* sym.intern -> sym
@@ -450,12 +452,6 @@ sym_name(mrb_state *mrb, mrb_value vsym)
* in this case.
*/
static mrb_value
sym_to_sym(mrb_state *mrb, mrb_value sym)
{
return sym;
}
/* 15.2.11.3.5(x) */
/*
* call-seq:
@@ -696,7 +692,7 @@ mrb_init_symbol(mrb_state *mrb)
mrb_define_method_id(mrb, sym, MRB_SYM(to_s), sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.3 */
mrb_define_method_id(mrb, sym, MRB_SYM(name), sym_name, MRB_ARGS_NONE());
mrb_define_method_id(mrb, sym, MRB_SYM(to_sym), sym_to_sym, MRB_ARGS_NONE()); /* 15.2.11.3.4 */
mrb_define_method_id(mrb, sym, MRB_SYM(to_sym), mrb_obj_itself, MRB_ARGS_NONE()); /* 15.2.11.3.4 */
mrb_define_method_id(mrb, sym, MRB_SYM(inspect), sym_inspect, MRB_ARGS_NONE()); /* 15.2.11.3.5(x) */
mrb_define_method_id(mrb, sym, MRB_OPSYM(cmp), sym_cmp, MRB_ARGS_REQ(1));
}