summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--.travis.yml8
-rw-r--r--.yardopts17
-rw-r--r--AUTHORS4
-rw-r--r--README.md58
-rw-r--r--Rakefile7
-rw-r--r--TODO7
-rw-r--r--build_config.rb10
-rw-r--r--doc/api/README.md30
-rw-r--r--doc/api/mruby.h.md217
-rw-r--r--doc/api/mruby/array.h.md250
-rw-r--r--doc/api/mruby/hash.h.md380
-rw-r--r--doc/api/mruby/range.h.md47
-rw-r--r--doc/api/mruby/re.h.md3
-rw-r--r--doc/api/mruby/string.h.md91
-rw-r--r--doc/api/mruby/value.h.md238
-rw-r--r--doc/api/mruby/version.h.md33
-rw-r--r--doc/guides/compile.md (renamed from doc/compile/README.md)4
-rw-r--r--[-rwxr-xr-x]doc/guides/debugger.md (renamed from doc/debugger/README.md)2
-rw-r--r--doc/guides/gc-arena-howto.md171
-rw-r--r--doc/guides/mrbconf.md (renamed from doc/mrbconf/README.md)15
-rw-r--r--doc/guides/mrbgems.md (renamed from doc/mrbgems/README.md)0
-rw-r--r--doc/language/Core.md1590
-rw-r--r--doc/language/README.md9
-rwxr-xr-xdoc/language/generator.rb15
-rw-r--r--doc/language/mrbdoc/lib/mrbdoc_analyze.rb231
-rw-r--r--doc/language/mrbdoc/lib/mrbdoc_docu.rb118
-rwxr-xr-xdoc/language/mrbdoc/mrbdoc.rb38
-rw-r--r--examples/targets/build_config_ArduinoDue.rb2
-rw-r--r--examples/targets/build_config_chipKITMax32.rb2
-rw-r--r--include/mrbconf.h36
-rw-r--r--include/mruby.h747
-rw-r--r--include/mruby/array.h79
-rw-r--r--include/mruby/class.h13
-rw-r--r--include/mruby/common.h67
-rw-r--r--include/mruby/compile.h26
-rw-r--r--include/mruby/data.h21
-rw-r--r--include/mruby/debug.h13
-rw-r--r--include/mruby/dump.h20
-rw-r--r--include/mruby/error.h37
-rw-r--r--include/mruby/gc.h69
-rw-r--r--include/mruby/hash.h37
-rw-r--r--include/mruby/irep.h14
-rw-r--r--include/mruby/khash.h17
-rw-r--r--include/mruby/numeric.h21
-rw-r--r--include/mruby/object.h18
-rw-r--r--include/mruby/proc.h16
-rw-r--r--include/mruby/range.h26
-rw-r--r--include/mruby/string.h100
-rw-r--r--include/mruby/value.h61
-rw-r--r--include/mruby/variable.h13
-rw-r--r--include/mruby/version.h78
-rw-r--r--lib/mruby/source.rb30
-rw-r--r--mrbgems/mruby-array-ext/mrblib/array.rb63
-rw-r--r--mrbgems/mruby-array-ext/src/array.c15
-rw-r--r--mrbgems/mruby-array-ext/test/array.rb17
-rwxr-xr-xmrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c14
-rwxr-xr-xmrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h2
-rwxr-xr-xmrbgems/mruby-bin-debugger/tools/mrdb/apilist.c6
-rwxr-xr-xmrbgems/mruby-bin-debugger/tools/mrdb/apilist.h2
-rwxr-xr-xmrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c12
-rwxr-xr-xmrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h2
-rwxr-xr-xmrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c8
-rwxr-xr-xmrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c2
-rwxr-xr-xmrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c12
-rwxr-xr-xmrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c2
-rwxr-xr-xmrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c12
-rwxr-xr-xmrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h2
-rw-r--r--mrbgems/mruby-bin-mirb/tools/mirb/mirb.c10
-rw-r--r--mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c8
-rw-r--r--mrbgems/mruby-bin-mruby/bintest/mruby.rb20
-rw-r--r--mrbgems/mruby-bin-mruby/tools/mruby/mruby.c12
-rw-r--r--mrbgems/mruby-bin-strip/bintest/mruby-strip.rb32
-rw-r--r--mrbgems/mruby-bin-strip/tools/mruby-strip/mruby-strip.c6
-rw-r--r--mrbgems/mruby-compiler/bintest/mrbc.rb4
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c55
-rw-r--r--mrbgems/mruby-compiler/core/parse.y54
-rw-r--r--mrbgems/mruby-enum-ext/mrblib/enum.rb28
-rw-r--r--mrbgems/mruby-enum-lazy/mrblib/lazy.rb43
-rw-r--r--mrbgems/mruby-enumerator/mrblib/enumerator.rb158
-rw-r--r--mrbgems/mruby-enumerator/test/enumerator.rb1
-rw-r--r--mrbgems/mruby-error/src/exception.c6
-rw-r--r--mrbgems/mruby-error/test/exception.c6
-rw-r--r--mrbgems/mruby-eval/src/eval.c18
-rw-r--r--mrbgems/mruby-eval/test/eval.rb19
-rw-r--r--mrbgems/mruby-exit/src/mruby-exit.c2
-rw-r--r--mrbgems/mruby-fiber/src/fiber.c8
-rw-r--r--mrbgems/mruby-hash-ext/mrblib/hash.rb135
-rw-r--r--mrbgems/mruby-hash-ext/src/hash-ext.c6
-rw-r--r--mrbgems/mruby-hash-ext/test/hash.rb83
-rw-r--r--mrbgems/mruby-kernel-ext/src/kernel.c17
-rw-r--r--mrbgems/mruby-math/src/math.c11
-rw-r--r--mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb12
-rw-r--r--mrbgems/mruby-numeric-ext/src/numeric_ext.c2
-rw-r--r--mrbgems/mruby-numeric-ext/test/numeric.rb10
-rw-r--r--mrbgems/mruby-object-ext/src/object.c6
-rw-r--r--mrbgems/mruby-objectspace/src/mruby_objectspace.c12
-rw-r--r--mrbgems/mruby-print/src/print.c30
-rw-r--r--mrbgems/mruby-proc-ext/src/proc.c12
-rw-r--r--mrbgems/mruby-proc-ext/test/proc.c6
-rw-r--r--mrbgems/mruby-random/src/mt19937ar.c2
-rw-r--r--mrbgems/mruby-random/src/random.c10
-rw-r--r--mrbgems/mruby-range-ext/src/range.c4
-rw-r--r--mrbgems/mruby-sprintf/src/kernel.c2
-rw-r--r--mrbgems/mruby-sprintf/src/sprintf.c46
-rw-r--r--mrbgems/mruby-sprintf/test/sprintf.rb1
-rw-r--r--mrbgems/mruby-string-ext/mrblib/string.rb45
-rw-r--r--mrbgems/mruby-string-ext/src/string.c124
-rw-r--r--mrbgems/mruby-string-ext/test/string.rb108
-rw-r--r--mrbgems/mruby-string-utf8/mrbgem.rake6
-rw-r--r--mrbgems/mruby-string-utf8/src/string.c731
-rw-r--r--mrbgems/mruby-string-utf8/test/string.rb110
-rw-r--r--mrbgems/mruby-struct/mrblib/struct.rb7
-rw-r--r--mrbgems/mruby-struct/src/struct.c63
-rw-r--r--mrbgems/mruby-struct/test/struct.rb2
-rw-r--r--mrbgems/mruby-symbol-ext/src/symbol.c6
-rw-r--r--mrbgems/mruby-test/driver.c14
-rw-r--r--mrbgems/mruby-test/init_mrbtest.c8
-rw-r--r--mrbgems/mruby-test/mrbgem.rake10
-rw-r--r--mrbgems/mruby-time/src/time.c6
-rw-r--r--mrblib/enum.rb19
-rw-r--r--mrblib/hash.rb4
-rw-r--r--mrblib/init_mrblib.c4
-rw-r--r--mrblib/kernel.rb4
-rw-r--r--mrblib/string.rb52
-rw-r--r--mruby-source.gemspec18
-rw-r--r--src/array.c13
-rw-r--r--src/backtrace.c22
-rw-r--r--src/class.c24
-rw-r--r--src/codedump.c24
-rw-r--r--src/compar.c2
-rw-r--r--src/debug.c6
-rw-r--r--src/dump.c14
-rw-r--r--src/enum.c2
-rw-r--r--src/error.c26
-rw-r--r--src/error.h2
-rw-r--r--src/etc.c12
-rw-r--r--src/fmt_fp.c11
-rw-r--r--src/gc.c710
-rw-r--r--src/hash.c76
-rw-r--r--src/init.c2
-rw-r--r--src/kernel.c20
-rw-r--r--src/load.c16
-rw-r--r--src/numeric.c41
-rw-r--r--src/object.c14
-rw-r--r--src/opcode.h2
-rw-r--r--src/pool.c2
-rw-r--r--src/print.c27
-rw-r--r--src/proc.c8
-rw-r--r--src/range.c10
-rw-r--r--src/state.c29
-rw-r--r--src/string.c1091
-rw-r--r--src/symbol.c10
-rw-r--r--src/value_array.h2
-rw-r--r--src/variable.c44
-rw-r--r--src/version.c7
-rw-r--r--src/vm.c46
-rw-r--r--tasks/mrbgem_spec.rake18
-rw-r--r--tasks/mrbgems.rake2
-rw-r--r--tasks/mruby_build.rake8
-rw-r--r--tasks/mruby_build_gem.rake2
-rw-r--r--tasks/toolchains/android.rake216
-rw-r--r--tasks/toolchains/androideabi.rake132
-rw-r--r--test/bintest.rb18
-rw-r--r--test/t/float.rb2
-rw-r--r--test/t/integer.rb6
-rw-r--r--test/t/string.rb176
-rw-r--r--test/t/syntax.rb4
-rw-r--r--travis_config.rb11
169 files changed, 4369 insertions, 6110 deletions
diff --git a/.gitignore b/.gitignore
index 1a8c5990c..800680821 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,4 +20,6 @@ cscope.out
/src/y.tab.c
/bin
/build
-/lib
+/mruby-source-*.gem
+doc/api
+.yardoc
diff --git a/.travis.yml b/.travis.yml
index bcfce3984..fa57b936d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,7 @@
language: c
+sudo: false
+
matrix:
include:
- os: linux
@@ -7,8 +9,10 @@ matrix:
- os: osx
osx_image: xcod6.4
-install:
- - if [ $TRAVIS_OS_NAME = 'linux' ]; then sudo apt-get update -qq; sudo apt-get -q install gperf; fi
+addons:
+ apt:
+ packages:
+ - gperf
env: MRUBY_CONFIG=travis_config.rb
script: "./minirake all test"
diff --git a/.yardopts b/.yardopts
new file mode 100644
index 000000000..27f6d59a1
--- /dev/null
+++ b/.yardopts
@@ -0,0 +1,17 @@
+--markup markdown
+--plugin mruby
+--plugin coderay
+--output-dir doc/api
+
+src/**/*.c
+mrblib/**/*.rb
+include/**/*.h
+
+mrbgems/*/src/**/*.c
+mrbgems/*/mrblib/**/*.rb
+mrbgems/*/include/**/*.h
+-
+AUTHORS
+MITL
+CONTRIBUTING.md
+doc/guides/*.md
diff --git a/AUTHORS b/AUTHORS
index ea8bb5ad6..180fd752e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,6 +1,6 @@
Original Authors "mruby developers" are:
Yukihiro Matsumoto
- FUKUOKA CSK CORPORATION
+ SCSK KYUSHU CORPORATION
Kyushu Institute of Technology
Network Applied Communication Laboratory, Inc.
Daniel Bovensiepen
@@ -32,3 +32,5 @@ Original Authors "mruby developers" are:
Manycolors, Inc.
Shota Nakano
Yuichi Osawa
+ Terence Lee
+ Zachary Scott
diff --git a/README.md b/README.md
index 9c3ccd466..a4d9ae00f 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
[![Build Status][build-status-img]][travis-ci]
-## What's mruby
+## What is mruby
mruby is the lightweight implementation of the Ruby language complying to (part
-of) the [ISO standard][ISO-standard]. Its syntax is Ruby 1.9 compatible.
+of) the [ISO standard][ISO-standard]. Its syntax is Ruby 1.9 compatible.
mruby can be linked and embedded within your application. We provide the
interpreter program "mruby" and the interactive mruby shell "mirb" as examples.
@@ -15,39 +15,28 @@ program under the "test" directory for an example.
This achievement was sponsored by the Regional Innovation Creation R&D Programs
of the Ministry of Economy, Trade and Industry of Japan.
-
## How to get mruby
-The stable version 1.1.0 of mruby can be downloaded via the following URL:
-
- https://github.com/mruby/mruby/archive/1.1.0.zip
+The stable version 1.2.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/1.2.0.zip](https://github.com/mruby/mruby/archive/1.2.0.zip)
-The latest development version of mruby can be downloaded via the following URL:
-
- https://github.com/mruby/mruby/zipball/master
+The latest development version of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/zipball/master](https://github.com/mruby/mruby/zipball/master)
The trunk of the mruby source tree can be checked out with the
following command:
$ git clone https://github.com/mruby/mruby.git
-
## mruby home-page
-The URL of the mruby home-page is:
-
- http://www.mruby.org/
-
+The URL of the mruby home-page is: [http://www.mruby.org](http://www.mruby.org).
## Mailing list
-We don't have mailing list, use GitHub forum <http://github.com/mruby/mruby>.
-
+We don't have mailing list, but you can use [GitHub issues](https://github.com/mruby/mruby).
## How to compile and install (mruby and gems)
-See the [doc/compile/README.md](doc/compile/README.md) file.
-
+See the [doc/guides/compile.md](doc/guides/compile.md) file.
## Running Tests
@@ -59,37 +48,16 @@ Or
$ ruby ./minirake test
-
## How to customize mruby (mrbgems)
mruby contains a package manager called *mrbgems*. To create extensions
in C and/or Ruby you should create a *GEM*. For a documentation of how to
-use mrbgems consult the file [doc/mrbgems/README.md](doc/mrbgems/README.md). For example code of
+use mrbgems consult the file [doc/guides/mrbgems.md](doc/guides/mrbgems.md). For example code of
how to use mrbgems look into the folder *examples/mrbgems/*.
-
## License
-Copyright (c) 2015 mruby developers
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-
+mruby is released under the [MIT License](MITL).
## Note for License
@@ -108,17 +76,15 @@ file.)
Please ask us if you want to distribute your code under another license.
-
## How to Contribute
-See the [contribution guidelines][contribution-guidelines] then send a pull
+See the [contribution guidelines][contribution-guidelines], and then send a pull
request to <http://github.com/mruby/mruby>. We consider you have granted
non-exclusive right to your contributed code under MIT license. If you want to
be named as one of mruby developers, please include an update to the AUTHORS
file in your pull request.
[ISO-standard]: http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=59579
-[build-status-img]: https://travis-ci.org/mruby/mruby.png?branch=master
-[contribution-guidelines]: https://github.com/mruby/mruby/blob/master/CONTRIBUTING.md
+[build-status-img]: https://travis-ci.org/mruby/mruby.svg?branch=master
+[contribution-guidelines]: CONTRIBUTING.md
[travis-ci]: https://travis-ci.org/mruby/mruby
-
diff --git a/Rakefile b/Rakefile
index 3e03b1096..3021bcc8e 100644
--- a/Rakefile
+++ b/Rakefile
@@ -139,5 +139,10 @@ end
desc 'generate document'
task :doc do
- load "#{MRUBY_ROOT}/doc/language/generator.rb"
+ begin
+ sh "mrbdoc"
+ rescue
+ puts "ERROR: To generate documents, you should install yard-mruby gem."
+ puts " $ gem install yard-mruby"
+ end
end
diff --git a/TODO b/TODO
index d3cb483c5..3e195f99b 100644
--- a/TODO
+++ b/TODO
@@ -1,11 +1,10 @@
Things to do (Things that are not done yet)
-* Special variables ($1,$2..)
+* special variables ($1,$2..)
* super in aliased methods
+* multi-assignment decomposing
+* keyword arguments in def statement
Things to improve (Done but things to fix)
-* Hash (Reduce size. Use khash or save the order)
-* stringEx (Delete encoding、delete CODERANGE、delete everything except UTF-8 or ASCII)
* Make additions as they are noticed.
-
diff --git a/build_config.rb b/build_config.rb
index 96b1d4684..6b54359fe 100644
--- a/build_config.rb
+++ b/build_config.rb
@@ -21,7 +21,6 @@ MRuby::Build.new do |conf|
# include the default GEMs
conf.gembox 'default'
-
# C compiler settings
# conf.cc do |cc|
# cc.command = ENV['CC'] || 'gcc'
@@ -99,7 +98,7 @@ MRuby::Build.new('host-debug') do |conf|
conf.gembox 'default'
# C compiler settings
- conf.cc.defines = %w(ENABLE_DEBUG)
+ conf.cc.defines = %w(MRB_ENABLE_DEBUG_HOOK)
# Generate mruby debugger command (require mruby-eval)
conf.gem :core => "mruby-bin-debugger"
@@ -109,7 +108,12 @@ MRuby::Build.new('host-debug') do |conf|
end
MRuby::Build.new('test') do |conf|
- toolchain :gcc
+ # Gets set by the VS command prompts.
+ if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
+ toolchain :visualcpp
+ else
+ toolchain :gcc
+ end
enable_debug
conf.enable_bintest
diff --git a/doc/api/README.md b/doc/api/README.md
deleted file mode 100644
index a83330d82..000000000
--- a/doc/api/README.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# C API Reference
-
-This is a C API Reference.
-The structure of this document will follow the directory structure of `include/` directory.
-
-## Headers list
-Header name|Features
------------|--------
-[mrbconf.h](../mrbconf/README.md)|Defines macros for mruby configurations.
-[mruby.h](./mruby.h.md)|Main header of mruby C API. Include this first.
-[mruby/array.h](./mruby/array.h.md)|`Array` class.
-[mruby/class.h](./mruby/class.h.md)|`Class` class.
-[mruby/compile.h](./mruby/compile.h.md)|mruby compiler.
-[mruby/data.h](./mruby/data.h.md)|User defined object.
-[mruby/debug.h](./mruby/debug.h.md)|Debugging.
-[mruby/dump.h](./mruby/dump.h.md)|Dumping compiled mruby script.
-[mruby/error.h](./mruby/error.h.md)|Error handling.
-[mruby/gc.h](./mruby/gc.h.md)|Uncommon memory management stuffs.
-[mruby/hash.h](./mruby/hash.h.md)|`Hash` class.
-[mruby/irep.h](./mruby/irep.h.md)|Compiled mruby script.
-[mruby/khash.h](./mruby/khash.h.md)|Defines of khash which is used in hash table of mruby.
-[mruby/numeric.h](./mruby/numeric.h.md)|`Numeric` class and sub-classes of it.
-[mruby/opode.h](./mruby/opcode.h.md)|Operation codes used in mruby VM.
-[mruby/proc.h](./mruby/proc.h.md)|`Proc` class.
-[mruby/range.h](./mruby/range.h.md)|`Range` class.
-[mruby/re.h](./mruby/re.h.md)|`Regexp` class.
-[mruby/string.h](./mruby/string.h.md)|`String` class.
-[mruby/value.h](./mruby/value.h.md)|`mrb_value` functions and macros.
-[mruby/variable.h](./mruby/variable.h.md)|Functions to access to mruby variables.
-[mruby/version.h](./mruby/version.h.md)|Macros of mruby version.
diff --git a/doc/api/mruby.h.md b/doc/api/mruby.h.md
deleted file mode 100644
index 06bab2d56..000000000
--- a/doc/api/mruby.h.md
+++ /dev/null
@@ -1,217 +0,0 @@
-# mruby.h
-
-Basic header of mruby.
-It includes **mrbconf.h**, **mruby/value.h**, **mruby/version.h** internally.
-
-## `mrb_state` management
-
-### mrb_open
-```C
-mrb_state* mrb_open();
-```
-Creates new `mrb_state`.
-
-### mrb_allocf
-```C
-typedef void* (*mrb_allocf) (struct mrb_state *mrb, void *ptr, size_t s, void *ud);
-```
-Function pointer type of custom allocator used in `mrb_open_allocf`.
-
-The function pointing it must behave similarly as `realloc` except:
-* If `ptr` is `NULL` it must allocate new space.
-* If `s` is `NULL`, `ptr` must be freed.
-
-### mrb_open_allocf
-```C
-mrb_state* mrb_open_allocf(mrb_allocf f, void *ud);
-```
-Create new `mrb_state` with custom allocator.
-`ud` will be passed to custom allocator `f`.
-If user data isn't required just pass `NULL`.
-Function pointer `f` must satisfy requirements of its type.
-
-### mrb_close
-```C
-void mrb_close(mrb_state *mrb);
-```
-Deletes `mrb_state`.
-
-## Method
-
-### mrb_get_args
-```C
-int mrb_get_args(mrb_state *mrb, const char *format, ...);
-```
-Retrieve arguments from `mrb_state`.
-When applicable, implicit conversions (such as `to_str`,
-`to_ary`, `to_hash`) are applied to received arguments.
-Use it inside a function pointed by `mrb_func_t`.
-It returns the number of arguments retrieved.
-`format` is a list of following format specifiers:
-
-char|mruby type|retrieve types|note
-:---:|----------|--------------|---
-`o`|`Object`|`mrb_value`|Could be used to retrieve any type of argument
-`C`|`Class`/`Module`|`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; 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`|
-`n`|`Symbol`|`mrb_sym`|
-`&`|block|`mrb_value`|
-`*`|rest arguments|`mrb_value*`, `mrb_int`|Receive the rest of arguments as an array.
-<code>&#124;</code>|optional||After this spec following specs would be optional.
-`?`|optional given|`mrb_bool`|True if preceding argument is given. Used to check optional argument is given.
-
-The passing variadic arguments must be a pointer of retrieving type.
-
-### mrb_define_class
-```C
-MRB_API struct RClass *mrb_define_class(mrb_state *, const char*, struct RClass*);
-```
-Defines a new class. If you're creating a gem it may look something like this:
-
-```C
-void mrb_example_gem_init(mrb_state* mrb) {
- struct RClass *example_class;
- example_class = mrb_define_class(mrb, "Example_Class", mrb->object_class);
-}
-
-void mrb_example_gem_final(mrb_state* mrb) {
- //free(TheAnimals);
-}
-```
-### mrb_define_method
-
-```C
-MRB_API void mrb_define_method(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec);
-```
-
-Defines a global function in ruby. If you're creating a gem it may look something like this:
-
-```C
-mrb_value example_method(mrb_state* mrb, mrb_value self){
- puts("Executing example command!");
- return self;
-}
-
-void mrb_example_gem_init(mrb_state* mrb) {
- mrb_define_method(mrb, mrb->kernel_module, "example_method", example_method, MRB_ARGS_NONE());
-}
-
-void mrb_example_gem_final(mrb_state* mrb) {
- //free(TheAnimals);
-}
-```
-
-Or maybe you want to create a class method for a class? It might look something like this:
-
-```C
-mrb_value example_method(mrb_state* mrb, mrb_value self){
- puts("Examples are like pizza...");
- return self;
-}
-
-void mrb_example_gem_init(mrb_state* mrb) {
- struct RClass *example_class;
- example_class = mrb_define_class(mrb, "Example_Class", mrb->object_class);
- mrb_define_method(mrb, example_class, "example_method", example_method, MRB_ARGS_NONE());
-}
-
-void mrb_example_gem_final(mrb_state* mrb) {
- //free(TheAnimals);
-}
-```
-### mrb_define_module
-
-```C
-MRB_API struct RClass *mrb_define_module(mrb_state *, const char*);
-```
-
-Defines a module. If you're creating a gem it may look something like this:
-
-```C
-mrb_value example_method(mrb_state* mrb, mrb_value self){
- puts("Examples are like tacos...");
- return self;
-}
-
-void mrb_example_gem_init(mrb_state* mrb) {
- struct RClass *example_module;
- example_module = mrb_define_module(mrb, "Example_Module");
-}
-
-void mrb_example_gem_final(mrb_state* mrb) {
- //free(TheAnimals);
-}
-```
-
-### mrb_define_module_function
-
-```C
-MRB_API void mrb_define_module_function(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec);
-```
-
-Defines a module function. If you're creating a gem it may look something like this:
-
-
-```C
-mrb_value example_method(mrb_state* mrb, mrb_value self){
- puts("Examples are like hot wings...");
- return self;
-}
-
-void mrb_example_gem_init(mrb_state* mrb) {
- struct RClass *example_module;
- example_module = mrb_define_module(mrb, "Example_Module");
- mrb_define_module_function(mrb, example_module, "example_method", example_method, MRB_ARGS_NONE());
-}
-
-void mrb_example_gem_final(mrb_state* mrb) {
- //free(TheAnimals);
-}
-```
-
-### mrb_define_const
-
-```C
-MRB_API void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_value);
-```
-
-Defines a constant. If you're creating a gem it may look something like this:
-
-```C
-mrb_value example_method(mrb_state* mrb, mrb_value self){
- puts("Examples are like hot wings...");
- return self;
-}
-
-void mrb_example_gem_init(mrb_state* mrb) {
- mrb_define_const(mrb, mrb->kernel_module, "EXAPMLE_CONSTANT", mrb_fixnum_value(0x00000001));
-}
-
-void mrb_example_gem_final(mrb_state* mrb) {
- //free(TheAnimals);
-}
-```
-
-### mrb_str_new_cstr
-
-```C
-MRB_API mrb_value mrb_str_new_cstr(mrb_state*, const char*);
-```
-
-Turns a C string into a Ruby string value.
-
-
-### mrb_value mrb_funcall
-
-```C
-MRB_API mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, mrb_int,...);
-```
-Call existing ruby functions.
diff --git a/doc/api/mruby/array.h.md b/doc/api/mruby/array.h.md
deleted file mode 100644
index 36c253cec..000000000
--- a/doc/api/mruby/array.h.md
+++ /dev/null
@@ -1,250 +0,0 @@
-### mrb_ary_new
-
-```C
-mrb_value mrb_ary_new(mrb_state *mrb);
-```
-Initializes an array.
-#### Example
-In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument and what class the passed in value is. In this case we are declaring a variable new_ary of data type mrb_value. Then we are initializing it with the mrb_ary_new function which only takes an mruby state as an argument.
-```C
-#include <stdio.h>
-#include <mruby.h>
-#include "mruby/array.h" // Needs the array header.
-#include "mruby/compile.h"
-
-int main(int argc, char *argv[])
-{
- mrb_value new_ary; // Declare variable.
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- FILE *fp = fopen("test.rb","r");
- new_ary = mrb_ary_new(mrb);
- mrb_value obj = mrb_load_file(mrb,fp);
- mrb_funcall(mrb, obj, "method_name", 1, new_ary);
- fclose(fp);
- mrb_close(mrb);
- return 0;
-}
-```
-test.rb
-```Ruby
-class Example_Class
- def method_name(a)
- puts a
- puts a.class
- end
-end
-Example_Class.new
-```
-
-### mrb_ary_push
-```C
-void mrb_ary_push(mrb_state*, mrb_value, mrb_value);
-```
-Pushes given value into an array.
-#### Example
-In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument and what class the passed in value is. In this case after initializing our array. We are declaring two variables with the mrb_int data type random_value1 & random_value2 and we initialize them 70 and 60 respectively. Then we use the mrb_ary_push function to push values those values into the array.
-```C
-#include <stdio.h>
-#include <mruby.h>
-#include "mruby/array.h" // Needs the array header.
-#include "mruby/compile.h"
-
-int main(int argc, char *argv[])
-{
- mrb_value new_ary; // Declare variable.
- mrb_int random_value1 = 70; // Initialize variable
- mrb_int random_value2 = 60; // Initialize variable
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- FILE *fp = fopen("test.rb","r");
- new_ary = mrb_ary_new(mrb); // Initialize ruby array.
- /* Pushes the fixnum value from random_value1 to the new_ary instance. */
- mrb_ary_push(mrb, new_ary, mrb_fixnum_value(random_value1));
- /* Pushes the fixnum value from random_value2 to the new_ary instance. */
- mrb_ary_push(mrb, new_ary, mrb_fixnum_value(random_value2));
- mrb_value obj = mrb_load_file(mrb,fp);
- mrb_funcall(mrb, obj, "method_name", 1, new_ary);
- fclose(fp);
- mrb_close(mrb);
- return 0;
-}
-```
-test.rb
-```Ruby
-class Example_Class
- def method_name(a)
- puts a
- puts a.class
- end
-end
-Example_Class.new
-```
-#### Result
-After compiling you should get these results.
-```Ruby
-[70, 60]
-Array
-```
-
-## mrb_ary_pop
-```C
-mrb_value mrb_ary_pop(mrb_state *mrb, mrb_value ary);
-```
-Pops the last element from the array.
-#### Example
-In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument and what class the passed in value is. In this case after initializing our array. We are declaring two variables with the mrb_int data type random_value1 & random_value2 and we initialize them 70 and 60 respectively. Then we use the mrb_ary_push function to push values those values into the array. Now here in the Ruby files we add another method
-called pop_ary that will return the array alone(just to be clean) and you should see the last element gone.
-```C
-#include <stdio.h>
-#include <mruby.h>
-#include "mruby/array.h" // Needs the array header.
-#include "mruby/compile.h"
-
-int main(int argc, char *argv[])
-{
- mrb_value new_ary; // Declare variable.
- mrb_int random_value1 = 70; // Initialize variable
- mrb_int random_value2 = 60; // Initialize variable
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- FILE *fp = fopen("test.rb","r");
- new_ary = mrb_ary_new(mrb); // Initialize ruby array.
- /* Pushes the fixnum value from random_value1 to the new_ary instance. */
- mrb_ary_push(mrb, new_ary, mrb_fixnum_value(random_value1));
- /* Pushes the fixnum value from random_value2 to the new_ary instance. */
- mrb_ary_push(mrb, new_ary, mrb_fixnum_value(random_value2));
- mrb_value obj = mrb_load_file(mrb,fp);
- mrb_funcall(mrb, obj, "method_name", 1, new_ary);
- mrb_ary_pop(mrb, new_ary); // Pops the last element of the array. In this case 60.
- mrb_funcall(mrb, obj, "pop_ary", 1, new_ary); // Calls the method again to show the results.
- fclose(fp);
- mrb_close(mrb);
- return 0;
-}
-```
-test.rb
-```Ruby
-class Example_Class
- def method_name(a)
- puts a
- puts a.class
- end
- def pop_ary(a)
- puts a
- end
-end
-Example_Class.new
-```
-#### Result
-After compiling you should get these results.
-```Ruby
-[70, 60]
-Array
-[70]
-```
-## mrb_ary_ref
-```C
-mrb_value mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n);
-```
-Returns a reference to an element of the array. Specified by the value given to mrb_int n.
-#### Example
-In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument and what class the passed in value is. In this case we're declaring a variable ary_ref with the data type of mrb_value. Then we assign mrb_ary_ref to it getting new_ary's value at index 1.
-```C
-#include <stdio.h>
-#include <mruby.h>
-#include "mruby/array.h" // Needs the array header.
-#include "mruby/compile.h"
-
-int main(int argc, char *argv[])
-{
- mrb_value ary_ref; // Declare variable.
- mrb_value new_ary; // Declare variable.
- mrb_int random_value1 = 70; // Initialize variable
- mrb_int random_value2 = 60; // Initialize variable
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- FILE *fp = fopen("test.rb","r");
- new_ary = mrb_ary_new(mrb); // Initialize ruby array.
- /* Pushes the fixnum value from random_value1 to the new_ary instance. */
- mrb_ary_push(mrb, new_ary, mrb_fixnum_value(random_value1));
- /* Pushes the fixnum value from random_value2 to the new_ary instance. */
- mrb_ary_push(mrb, new_ary, mrb_fixnum_value(random_value2));
- ary_ref = mrb_ary_ref(mrb, new_ary, 1); // Gets the value of new_ary's second element at index 1.
- mrb_value obj = mrb_load_file(mrb,fp);
- /* Passing the value from ary_ref to the method method_name.*/
- mrb_funcall(mrb, obj, "method_name", 1, ary_ref);
- fclose(fp);
- mrb_close(mrb);
- return 0;
-}
-```
-test.rb
-```Ruby
-class Example_Class
- def method_name(a)
- puts a
- puts a.class
- end
-end
-Example_Class.new
-```
-#### Result
-After compiling you should get these results.
-```Ruby
-60
-Fixnum
-```
-
-### mrb_ary_set
-```C
-void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val);
-```
-Sets a value to an index.
-#### Example
-In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument and what class the passed in value is. In this case we're declaring a variable ary_ref with the data type of mrb_value. Then we assign mrb_ary_ref to it getting new_ary's value at index 1.
-```C
-#include <stdio.h>
-#include <mruby.h>
-#include "mruby/array.h" // Needs the array header.
-#include "mruby/compile.h"
-
-int main(int argc, char *argv[])
-{
- mrb_value new_ary;
- mrb_value ary_obj;
- mrb_int random_value1 = 70;
- mrb_int random_value2 = 60;
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- FILE *fp = fopen("test.rb","r");
- new_ary = mrb_ary_new(mrb);
- mrb_ary_push(mrb, new_ary, mrb_fixnum_value(random_value1));
- mrb_ary_push(mrb, new_ary, mrb_fixnum_value(random_value2));
- /* Sets the fixnum value of 7 to the second index of the array.*/
- mrb_ary_set(mrb, new_ary, 2, mrb_fixnum_value(7));
- mrb_value obj = mrb_load_file(mrb,fp);
- mrb_funcall(mrb, obj, "before_after", 1, new_ary);
- fclose(fp);
- mrb_close(mrb);
- return 0;
-}
-```
-test.rb
-```Ruby
-class Example_Class
- def method_name(a)
- puts a
- puts a.class
- end
- def before_after(a)
- puts a
- end
-end
-Example_Class.new
-```
-#### Result
-After compiling you should get these results.
-```Ruby
-[70, 60, 7]
-```
diff --git a/doc/api/mruby/hash.h.md b/doc/api/mruby/hash.h.md
deleted file mode 100644
index fa12ea670..000000000
--- a/doc/api/mruby/hash.h.md
+++ /dev/null
@@ -1,380 +0,0 @@
-### mrb_hash_new
-
-```C
-mrb_value mrb_hash_new(mrb_state *mrb);
-```
-
-Initializes a hash.
-#### Example
-
-In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument
-and what class the passed in value is. This example initializes a hash. In pure Ruby doing this is equivalent
-to Hash.new.
-
-```C
-#include <stdio.h>
-#include <mruby.h>
-#include "mruby/hash.h" // Needs the hash header.
-#include "mruby/compile.h"
-
-int main(int argc, char *argv[])
-{
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- mrb_value new_hash; // Declare variable.
- FILE *fp = fopen("test_ext.rb","r");
- new_hash = mrb_hash_new(mrb); // Initialize hash.
- mrb_value obj = mrb_load_file(mrb,fp);
- mrb_funcall(mrb, obj, "method_name", 1, new_hash);
- fclose(fp);
- mrb_close(mrb);
- return 0;
-}
-```
-
-#### test_ext.rb
-
-``` Ruby
-class Example_Class
- def method_name(a)
- puts a
- puts a.class
- end
-end
-Example_Class.new
-```
-
-### mrb_hash_set
-
-```C
-void mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val);
-```
-
-Sets a keys and values to hashes.
-#### Example
-
-In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument
-and what class the passed in value is. This example sets a key and value pair to a hash. In pure Ruby doing this is equivalent to:
-
-```Ruby
-a = {:da_key => 80}
-```
-
-```C
-#include <stdio.h>
-#include <mruby.h>
-#include "mruby/hash.h" // Needs the hash header.
-#include "mruby/compile.h"
-
-int main(int argc, char *argv[])
-{
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- mrb_value new_hash; // Declare variable.
- mrb_sym hash_key = mrb_intern_cstr(mrb, "da_key"); // Declare a symbol.
- mrb_int hash_value = 80; // Declare a fixnum value.
- FILE *fp = fopen("test_ext.rb","r");
- new_hash = mrb_hash_new(mrb); // Initialize hash.
- mrb_value obj = mrb_load_file(mrb,fp);
- mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key), mrb_fixnum_value(hash_value)); // Set values to hash.
- mrb_funcall(mrb, obj, "method_name", 1, new_hash);
- fclose(fp);
- mrb_close(mrb);
- return 0;
-}
-```
-
-#### test_ext.rb
-
-```Ruby
-class Example_Class
- def method_name(a)
- puts a
- puts a.class
- end
-end
-Example_Class.new
-```
-
-#### Result
-
-After compiling you should get these results.
-
-```Ruby
-{:da_key=>80}
-Hash
-```
-
-### mrb_hash_get
-
-```C
-mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key);
-```
-
-Gets a value from a key.
-#### Example
-
-In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument
-and what class the passed in value is. This example gets a value from a key. In pure Ruby doing this is equivalent to:
-
-```Ruby
-a = {:da_key => 80}
-a[:da_key]
-```
-
-```C
-#include <stdio.h>
-#include <mruby.h>
-#include "mruby/hash.h" // Needs the hash header.
-#include "mruby/compile.h"
-
-int main(int argc, char *argv[])
-{
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- mrb_value new_hash; // Declare variable for new hash object.
- mrb_value get_hash_value; // Declare variable for getting a value from a hash.
- mrb_sym hash_key_a = mrb_intern_cstr(mrb, "da_key1"); // Declare a symbol.
- mrb_sym hash_key_b = mrb_intern_cstr(mrb, "da_key2"); // Declare a symbol.
- mrb_int hash_value_a = 80; // Declare a fixnum value.
- mrb_int hash_value_b = 90; // Declare a fixnum value.
- FILE *fp = fopen("test_ext.rb","r");
- new_hash = mrb_hash_new(mrb); // Initialize hash.
- mrb_value obj = mrb_load_file(mrb,fp);
- mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key_a), mrb_fixnum_value(hash_value_a)); // Set values to hash.
- mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key_b), mrb_fixnum_value(hash_value_b)); // Set values to hash.
- get_hash_value = mrb_hash_get(mrb, new_hash, mrb_symbol_value(hash_key_b)); // Get value from hash.
- mrb_funcall(mrb, obj, "method_name", 1, get_hash_value);
- fclose(fp);
- mrb_close(mrb);
- return 0;
-}
-```
-
-#### test_ext.rb
-
-```Ruby
-class Example_Class
- def method_name(a)
- puts a
- puts a.class
- end
-end
-Example_Class.new
-```
-
-#### Result
-
-After compiling you should get these results.
-
-```Ruby
-90
-Fixnum
-```
-
-### mrb_hash_delete_key
-
-```C
-mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key);
-```
-
-Deletes hash key and value pair.
-#### Example
-
-In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument
-and what class the passed in value is. This example deletes hash key and value pair. In pure Ruby doing this is equivalent to:
-
-```Ruby
-a = {:da_key1 => 80,:da_key2 => 90}
-a.delete(:da_key2)
-```
-
-```C
-#include <stdio.h>
-#include <mruby.h>
-#include "mruby/hash.h" // Needs the hash header.
-#include "mruby/compile.h"
-
-int main(int argc, char *argv[])
-{
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- mrb_value new_hash; // Declare variable for new hash object.
- mrb_value get_hash_value; // Declare variable for getting a value from a hash.
- mrb_sym hash_key_a = mrb_intern_cstr(mrb, "da_key1"); // Declare a symbol.
- mrb_sym hash_key_b = mrb_intern_cstr(mrb, "da_key2"); // Declare a symbol.
- mrb_sym hash_key_b = mrb_intern_cstr(mrb, "da_key2"); // Declare a symbol.
- mrb_int hash_value_a = 80; // Declare a fixnum value.
- mrb_int hash_value_b = 90; // Declare a fixnum value.
- FILE *fp = fopen("test_ext.rb","r");
- new_hash = mrb_hash_new(mrb); // Initialize hash.
- mrb_value obj = mrb_load_file(mrb,fp);
- mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key_a), mrb_fixnum_value(hash_value_a)); // Set values to hash.
- mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key_b), mrb_fixnum_value(hash_value_b)); // Set values to hash.
- mrb_funcall(mrb, obj, "method_name", 1, new_hash);
- mrb_hash_delete_key(mrb, new_hash, mrb_symbol_value(hash_key_b));
- mrb_funcall(mrb, obj, "another_method_name", 1, new_hash);
- fclose(fp);
- mrb_close(mrb);
- return 0;
-}
-```
-
-#### test_ext.rb
-
-```Ruby
-class Example_Class
- def method_name(a)
- puts "Hash pre deletion #{a}"
- #puts a.class
- end
- # Show deleted key and value pair.
- def another_method_name(a)
- puts "Hash post deletion #{a}"
- end
-end
-Example_Class.new
-```
-
-#### Result
-
-After compiling you should get these results.
-
-```Ruby
-Hash pre deletion {:da_key1 => 80, :da_key2 => 90}
-Hash post deletion {:da_key1 => 80}
-```
-
-### mrb_hash_keys
-
-```C
-mrb_value mrb_hash_keys(mrb_state *mrb, mrb_value hash);
-```
-
-Gets an array of keys.
-#### Example
-
-In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument
-and what class the passed in value is. This example gets an array of keys from a hash.
-
-```C
-#include <stdio.h>
-#include <mruby.h>
-#include "mruby/hash.h" // Needs the hash header.
-#include "mruby/compile.h"
-
-int main(int argc, char *argv[])
-{
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- mrb_value new_hash; // Declare variable for new hash object.
- mrb_value get_hash_keys; // Declare variable for getting an array of keys.
- mrb_sym hash_key_a = mrb_intern_cstr(mrb, "da_key1"); // Declare a symbol.
- mrb_sym hash_key_b = mrb_intern_cstr(mrb, "da_key2"); // Declare a symbol.
- mrb_int hash_value_a = 80; // Declare a fixnum value.
- mrb_int hash_value_b = 90; // Declare a fixnum value.
- FILE *fp = fopen("test_ext.rb","r");
- new_hash = mrb_hash_new(mrb); // Initialize hash.
- mrb_value obj = mrb_load_file(mrb,fp);
- mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key_a), mrb_fixnum_value(hash_value_a)); // Set values to hash.
- mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key_b), mrb_fixnum_value(hash_value_b)); // Set values to hash.
- get_hash_keys = mrb_hash_keys(mrb, new_hash); // get an array of keys.
- mrb_funcall(mrb, obj, "method_name", 1, get_hash_keys);
- fclose(fp);
- mrb_close(mrb);
- return 0;
-}
-```
-
-#### test_ext.rb
-
-```Ruby
-class Example_Class
- def method_name(a)
- puts a
- puts a.class
- end
-end
-Example_Class.new
-```
-
-#### Result
-
-After compiling you should get these results.
-
-```Ruby
-[:da_key1, :da_key2]
-Array
-```
-
-### mrb_hash_clear
-
-```C
-mrb_value mrb_hash_clear(mrb_state *mrb, mrb_value hash);
-```
-
-Clears the hash.
-#### Example
-
-In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument
-and what class the passed in value is. This example clears the hash. In pure Ruby doing this is equivalent to:
-
-```Ruby
-a = {:da_key1 => 80,:da_key2 => 90}
-a.clear
-```
-
-```C
-#include <stdio.h>
-#include <mruby.h>
-#include "mruby/hash.h" // Needs the hash header.
-#include "mruby/compile.h"
-
-int main(int argc, char *argv[])
-{
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- mrb_value new_hash; // Declare variable for new hash object.
- mrb_value get_hash; // Declare variable for getting a hash.
- mrb_sym hash_key_a = mrb_intern_cstr(mrb, "da_key1"); // Declare a symbol.
- mrb_sym hash_key_b = mrb_intern_cstr(mrb, "da_key2"); // Declare a symbol.
- mrb_int hash_value_a = 80; // Declare a fixnum value.
- mrb_int hash_value_b = 90; // Declare a fixnum value.
- FILE *fp = fopen("test_ext.rb","r");
- new_hash = mrb_hash_new(mrb); // Initialize hash.
- mrb_value obj = mrb_load_file(mrb,fp);
- mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key_a), mrb_fixnum_value(hash_value_a)); // Set values to hash.
- mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key_b), mrb_fixnum_value(hash_value_b)); // Set values to hash.
- mrb_funcall(mrb, obj, "method_name", 1, new_hash);
- get_hash = mrb_hash_clear(mrb, new_hash);
- mrb_funcall(mrb, obj, "another_method_name", 1, get_hash);
- fclose(fp);
- mrb_close(mrb);
- return 0;
-}
-```
-
-#### test_ext.rb
-
-```Ruby
-class Example_Class
- def method_name(a)
- puts "Hash pre clear #{a}"
- #puts a.class
- end
- # Show clear hash.
- def another_method_name(a)
- puts "Hash post clear #{a}"
- end
-end
-Example_Class.new
-```
-
-#### Result
-
-After compiling you should get these results.
-
-```Ruby
-Hash pre clear {:da_key1 => 80, :da_key2 => 90}
-Hash post clear {}
-```
diff --git a/doc/api/mruby/range.h.md b/doc/api/mruby/range.h.md
deleted file mode 100644
index 188e6ede6..000000000
--- a/doc/api/mruby/range.h.md
+++ /dev/null
@@ -1,47 +0,0 @@
-#### mrb_range_new
-```C
- mrb_value mrb_range_new(mrb_state*, mrb_value, mrb_value, mrb_bool);
-```
-Initializes a Range. The first mrb_value being the beginning value and second being the ending value.
-The third parameter is an mrb_bool value that represents the inclusion or exclusion of the last value.
-If the third parameter is 0 then it includes the last value in the range. If the third parameter is 1
-then it excludes the last value in the range.
-C code
-```C
- #include <stdio.h>
- #include <mruby.h>
- #include "mruby/range.h" // Needs the range header.
- #include "mruby/compile.h"
-
- int main(int argc, char *argv[])
- {
- mrb_int beg = 0;
- mrb_int end = 2;
- mrb_bool exclude = 1;
- mrb_value range_obj;
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- FILE *fp = fopen("test.rb","r");
- range_obj = mrb_range_new(mrb, mrb_fixnum_value(beg), mrb_fixnum_value(end), exclude);
- mrb_value obj = mrb_load_file(mrb,fp);
- mrb_funcall(mrb, obj, "method_name", 1, range_obj);
- fclose(fp);
- mrb_close(mrb);
- return 0;
- }
-```
-Ruby code
-```Ruby
- class Example_Class
- def method_name(a)
- puts a
- puts a.class
- end
- end
- Example_Class.new
-```
-This returns the following:
-```Ruby
- 0...2
- Range
-```
diff --git a/doc/api/mruby/re.h.md b/doc/api/mruby/re.h.md
deleted file mode 100644
index f5cd2a71e..000000000
--- a/doc/api/mruby/re.h.md
+++ /dev/null
@@ -1,3 +0,0 @@
-### Macros
-#### REGEXP_CLASS
-A string with the name of the REGEXP class.
diff --git a/doc/api/mruby/string.h.md b/doc/api/mruby/string.h.md
deleted file mode 100644
index 7bf94df5b..000000000
--- a/doc/api/mruby/string.h.md
+++ /dev/null
@@ -1,91 +0,0 @@
-## Macros
-### mrb_str_ptr(s)
-Returns a pointer from a Ruby string.
-## Functions
-### mrb_str_plus
-```C
- mrb_value mrb_str_plus(mrb_state*, mrb_value, mrb_value);
-```
-Adds to strings together.
-### mrb_ptr_to_str
-```C
- mrb_value mrb_ptr_to_str(mrb_state *, void*);
-```
-Converts pointer into a Ruby string.
-### mrb_obj_as_string
-```C
- mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj);
-```
-Returns an object as a Ruby string.
-### mrb_str_resize
-```C
- mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len);
-```
-Resizes the string's length.
-### mrb_str_substr
-```C
- mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
-```
-Returns a sub string.
-### mrb_string_type
-```C
- mrb_value mrb_string_type(mrb_state *mrb, mrb_value str);
-```
-Returns a Ruby string type.
-### mrb_str_new_cstr
-```C
- const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr);
-```
-Returns a Ruby string as a C string.
-### mrb_str_dup
-```C
- mrb_value mrb_str_dup(mrb_state *mrb, mrb_value str);
-```
-Duplicates a string object.
-### mrb_str_intern
-```C
- mrb_value mrb_str_intern(mrb_state *mrb, mrb_value self);
-```
-Returns a symbol from a passed in string.
-### mrb_str_to_str
-```C
- mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str);
-```
-Returns a converted string type.
-### mrb_str_equal
-```C
- mrb_bool mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2);
-```
-Returns true if the strings match and false if the strings don't match.
-### mrb_str_cat
-```C
- mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len);
-```
-Returns a concated string comprised of a Ruby string and a C string.
-### mrb_str_cat_cstr
-```C
- mrb_value mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2);
-```
-Returns a concated string comprised of a Ruby string and a C string(A shorter alternative to mrb_str_cat).
-### mrb_str_append
-```C
- mrb_value mrb_str_append(mrb_state *mrb, mrb_value str1, mrb_value str2);
-```
-Adds str2 to the end of str1.
-### mrb_str_cmp
-```C
- int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2);
-```
-Returns 0 if both Ruby strings are equal.
-Returns a value < 0 if Ruby str1 is less than Ruby str2.
-Returns a value > 0 if Ruby str2 is greater than Ruby str1.
-### mrb_str_to_cstr
-```C
- char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str);
-```
-Returns a C string from a Ruby string.
-### mrb_str_inspect
-```C
- mrb_str_inspect(mrb_state *mrb, mrb_value str);
-```
-Returns a printable version of str, surrounded by quote marks, with special characters escaped.
diff --git a/doc/api/mruby/value.h.md b/doc/api/mruby/value.h.md
deleted file mode 100644
index fbf2dadf1..000000000
--- a/doc/api/mruby/value.h.md
+++ /dev/null
@@ -1,238 +0,0 @@
-### mrb_float_value
-```C
-static inline mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f)
-```
-
-Returns a float in Ruby.
-
-##### Example
-
-In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument
-and what class the passed in value is. In this case we are passing in mrb_float f = 0.09. Alternatively
-double i = 0.09 could also be used.
-
-
-example.c
-```C
-#include <stdio.h>
-#include <mruby.h>
-#include "mruby/compile.h"
-#include "mruby/string.h"
-
-int
-main(void)
-{
- mrb_float f = 0.09;// or double i = 0.09;
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- FILE *fp = fopen("test.rb","r");
- mrb_value obj = mrb_load_file(mrb,fp);
- mrb_funcall(mrb, obj, "method_name", 1, mrb_float_value(mrb, f));
- fclose(fp);
- mrb_close(mrb);
- return 0;
-}
-
-```
-
-test.rb
-```Ruby
-class My_Class
- def method_name(s)
- puts s
- puts s.class
- end
-end
-a = My_Class.new
-```
-
-### mrb_fixnum_value
-
-```C
-static inline mrb_value mrb_fixnum_value(mrb_int i)
-```
-
-Returns a fixnum in Ruby.
-
-##### Example
-
-In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument
-and what class the passed in value is. In this case we are passing in mrb_int i = 99. Alternativly int i = 99
-could also be used.
-
-
-example.c
-```C
-#include <stdio.h>
-#include <mruby.h>
-#include "mruby/compile.h"
-
-int
-main(void)
-{
- mrb_int i = 99; // or int i = 99;
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- FILE *fp = fopen("test.rb","r");
- mrb_value obj = mrb_load_file(mrb,fp);
- mrb_funcall(mrb, obj, "method_name", 1, mrb_fixnum_value(i));
- fclose(fp);
- mrb_close(mrb);
- return 0;
-}
-
-```
-
-test.rb
-```Ruby
-class My_Class
- def method_name(s)
- puts s
- puts s.class
- end
-end
-a = My_Class.new
-```
-
-
-
-### mrb_nil_value
-
-```C
-static inline mrb_value mrb_nil_value(void)
-```
-
-Returns nil in Ruby.
-
-##### Example
-
-In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument
-and what class the passed in value is. In this case we are passing in nothing and we will get NillClass.
-
-
-example.c
-```C
-#include <stdio.h>
-#include <mruby.h>
-#include "mruby/compile.h"
-
-int
-main(void)
-{
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- FILE *fp = fopen("test.rb","r");
- mrb_value obj = mrb_load_file(mrb,fp);
- mrb_funcall(mrb, obj, "method_name", 1, mrb_nil_value());
- fclose(fp);
- mrb_close(mrb);
- return 0;
-}
-
-```
-
-test.rb
-```Ruby
-class My_Class
- def method_name(s)
- puts s
- puts s.class
- end
-end
-a = My_Class.new
-```
-
-
-### mrb_false_value
-
-```C
-static inline mrb_value mrb_false_value(void)
-```
-
-Returns false in Ruby.
-
-##### Example
-
-In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument
-and what class the passed in value is. In this case we are passing in nothing and we will get FalseClass.
-
-
-example.c
-```C
-#include <stdio.h>
-#include <mruby.h>
-#include "mruby/compile.h"
-
-int
-main(void)
-{
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- FILE *fp = fopen("test.rb","r");
- mrb_value obj = mrb_load_file(mrb,fp);
- mrb_funcall(mrb, obj, "method_name", 1, mrb_false_value());
- fclose(fp);
- mrb_close(mrb);
- return 0;
-}
-
-```
-
-test.rb
-```Ruby
-class My_Class
- def method_name(s)
- puts s
- puts s.class
- end
-end
-a = My_Class.new
-```
-
-
-
-### mrb_true_value
-
-```C
-static inline mrb_value mrb_true_value(void)
-```
-
-Returns true in Ruby.
-
-##### Example
-
-In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument
-and what class the passed in value is. In this case we are passing in nothing and we will get TrueClass.
-
-
-example.c
-```C
-#include <stdio.h>
-#include <mruby.h>
-#include "mruby/compile.h"
-
-int
-main(void)
-{
- mrb_state *mrb = mrb_open();
- if (!mrb) { /* handle error */ }
- FILE *fp = fopen("test.rb","r");
- mrb_value obj = mrb_load_file(mrb,fp);
- mrb_funcall(mrb, obj, "method_name", 1, mrb_true_value());
- fclose(fp);
- mrb_close(mrb);
- return 0;
-}
-
-```
-
-test.rb
-```Ruby
-class My_Class
- def method_name(s)
- puts s
- puts s.class
- end
-end
-a = My_Class.new
-```
diff --git a/doc/api/mruby/version.h.md b/doc/api/mruby/version.h.md
deleted file mode 100644
index f627b1da1..000000000
--- a/doc/api/mruby/version.h.md
+++ /dev/null
@@ -1,33 +0,0 @@
-### Macros
-#### MRUBY_RUBY_VERSION
-The version of Ruby used by mruby.
-#### MRUBY_RUBY_ENGINE
-Ruby engine.
-#### MRUBY_VERSION
-The mruby version.
-#### MRUBY_RELEASE_MAJOR
-Major release version.
-#### MRUBY_RELEASE_MINOR
-Minor release version.
-#### MRUBY_RELEASE_NO
-Release number.
-#### MRUBY_RELEASE_DATE
-Release date as a string.
-#### MRUBY_RELEASE_YEAR
-Release year.
-#### MRUBY_RELEASE_MONTH
-Release month.
-#### MRUBY_RELEASE_DAY
-Release day.
-#### MRUBY_BIRTH_YEAR
-The year mruby was first created.
-#### MRUBY_AUTHOR
-Mruby's authors.
-#### MRB_STRINGIZE0(expr)
-A passed in expression.
-#### MRB_STRINGIZE(expr)
-Passes in an expression to MRB_STRINGIZE0.
-#### MRUBY_DESCRIPTION
-mruby's version, and release date.
-#### MRUBY_COPYRIGHT
-mruby's copyright information.
diff --git a/doc/compile/README.md b/doc/guides/compile.md
index 8e91e7546..a1c89882a 100644
--- a/doc/compile/README.md
+++ b/doc/guides/compile.md
@@ -75,7 +75,7 @@ toolchain :visualcpp
Toolchain configuration for Android.
```ruby
-toolchain :androideabi
+toolchain :android
```
Requires the custom standalone Android NDK and the toolchain path
@@ -463,7 +463,7 @@ can't be disabled for the main build.
MRuby::CrossBuild.new('Minimal') do |conf|
toolchain :gcc
- conf.cc.defines = %w(DISABLE_STDIO)
+ conf.cc.defines = %w(MRB_DISABLE_STDIO)
conf.bins = []
end
```
diff --git a/doc/debugger/README.md b/doc/guides/debugger.md
index a13e91cec..366701c88 100755..100644
--- a/doc/debugger/README.md
+++ b/doc/guides/debugger.md
@@ -38,7 +38,7 @@ To confirm mrdb was installed properly, run mrdb with the `--version` option:
```bash
$ mrdb --version
-mruby 1.1.0 (2014-11-19)
+mruby 1.2.0 (2014-11-17)
```
## 2.2 Basic Operation
diff --git a/doc/guides/gc-arena-howto.md b/doc/guides/gc-arena-howto.md
new file mode 100644
index 000000000..f2a0448bd
--- /dev/null
+++ b/doc/guides/gc-arena-howto.md
@@ -0,0 +1,171 @@
+# How to use `mrb_gc_arena_save()`/`mrb_gc_arena_restore()`
+
+This is basically English translation of [Matz's blog post](http://www.rubyist.net/~matz/20130731.html) written in Japanese.
+Some parts are updated to reflect recent changes.
+
+When you are extending mruby using C language, you may encounter
+mysterious "arena overflow error" or memory leak or very slow
+execution speed. This is an error indicating overflow of "GC arena"
+implementing "conservative GC".
+
+GC (garbage collector) must ensure that object is "alive", in other
+words, that it is referenced by somewhere from program. This can be
+determined by checking that that object can be directly or indirectly
+referenced by root. The local variables, global variables and
+constants etc are root.
+
+If program execution is performed inside mruby VM, there is nothing to
+worry about because GC can access all roots owned by VM.
+
+The problem arises when executing C functions. The object referenced
+by C variable is also "alive", but mruby GC cannot aware of this, so
+it might mistakenly recognize the objects referenced by only C
+variables as dead.
+
+It is a fatal bug for GC to collect live objects.
+
+In CRuby, we scan C stack area, and use C variable as root to check
+whether object is alive or not. Of course, because we are accessing C
+stack just as memory region, we never know it is an integer or a
+pointer. We workaround this by assuming that if it looks like a
+pointer, then assume it as a pointer. We call it "conservative".
+
+By the way, CRuby's "conservative GC" has some problems.
+
+Its biggest problem is we have no way to access to the stack area in
+portable way. Therefore, we cannot use this method if we'd like to
+implement highly portable runtime, like mruby.
+
+So we came up an another plan to implement "conservative GC" in mruby.
+
+Again, the problem is that there is an object which was created in C
+function, and is not referenced by Ruby world, and cannot be treated
+as garbage.
+
+In mruby, we recognize all objects created in C function are alive.
+Then we have no problem such as recognizing live object as dead.
+
+This means that because we cannot collect truly dead object, we may
+get a little bit less efficiency, but GC itself is highly portable.
+We can say goodbye to the problem that GC deletes live objects due to
+optimization which sometimes occurs in CRuby.
+
+According to this idea, we have a table, called "GC arena", which
+remembers objects created in C function. The arena is stack
+structure, when C function execution is returned to mruby VM, all
+objects registered in the arena are popped.
+
+This works very well, but GC arena causes another problem. "arena
+overflow error" or memory leak.
+
+As of this writing, mruby automatically extend arena to remember
+objects (See `MRB_GC_FIXED_ARENA` and `MRB_GC_ARENA_SIZE` in
+doc/mrbconf/README.md). If you keep creating objects in C functions,
+it increases memory usage, since GC never kick in. This memory usage
+may look like memory leak, and also makes execution slower.
+
+With the build time configuration, you can limit the maximum size of
+arena (e.g., 100). Then if you create many objects, arena overflows,
+thus you will get "arena overflow error".
+
+To workaround these problems, we have `mrb_gc_arena_save()` and
+`mrb_gc_arena_restore()` functions.
+
+`int mrb_gc_arena_save(mrb)` returns the current position of the stack
+top of GC arena, and `void mrb_gc_arena_restore(mrb, idx)` sets the
+stack top position to back to given idx. We uses them like so:
+
+```c
+int arena_idx = mrb_gc_arena_save(mrb);
+
+...create objects...
+mrb_gc_arena_restore(mrb, arena_idx);
+
+```
+
+In mruby, C function call are surrounded by this save/restore, but we
+can further optimize memory usage by surrounding save/restore, and can
+avoid arena overflow.
+
+Let's take a real example. Here is the source code of `Array#inspect`:
+
+```c
+static mrb_value
+inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list)
+{
+ mrb_int i;
+ mrb_value s, arystr;
+ char head[] = { '[' };
+ char sep[] = { ',', ' ' };
+ char tail[] = { ']' };
+
+ /* check recursive */
+ for(i=0; i<RARRAY_LEN(list); i++) {
+ if (mrb_obj_equal(mrb, ary, RARRAY_PTR(list)[i])) {
+ return mrb_str_new(mrb, "[...]", 5);
+ }
+ }
+
+ mrb_ary_push(mrb, list, ary);
+
+ arystr = mrb_str_buf_new(mrb, 64);
+ mrb_str_buf_cat(mrb, arystr, head, sizeof(head));
+
+ for(i=0; i<RARRAY_LEN(ary); i++) {
+ int ai = mrb_gc_arena_save(mrb);
+
+ if (i > 0) {
+ mrb_str_buf_cat(mrb, arystr, sep, sizeof(sep));
+ }
+ if (mrb_array_p(RARRAY_PTR(ary)[i])) {
+ s = inspect_ary(mrb, RARRAY_PTR(ary)[i], list);
+ }
+ else {
+ s = mrb_inspect(mrb, RARRAY_PTR(ary)[i]);
+ }
+ mrb_str_buf_cat(mrb, arystr, RSTRING_PTR(s), RSTRING_LEN(s));
+ mrb_gc_arena_restore(mrb, ai);
+ }
+
+ mrb_str_buf_cat(mrb, arystr, tail, sizeof(tail));
+ mrb_ary_pop(mrb, list);
+
+ return arystr;
+}
+```
+
+This is a real example, so a little bit complicated, so bear with me.
+The essence of `Array#inspect` is that after stringifying each element
+of array using `inspect` method, we join them together so that we can
+get `inspect` representation of entire array.
+
+After the `inspect` representation of entire array is created, we no
+longer require the individual string representation. That means that
+we don't have to register these temporal objects into GC arena.
+
+Therefore, in `ary_inspect()` function, we do:
+
+* save the position of the stack top using `mrb_gc_arena_save()`.
+* get `inspect` representation of each element.
+* append it to the constructing entire `inspect` representation of array.
+* restore stack top position using `mrb_gc_arena_restore()`.
+
+to keep the arena size small.
+
+Please note that the final `inspect` representation of entire array
+was created before the call of `mrb_gc_arena_restore()`. Otherwise,
+required temporal object may be deleted by GC.
+
+We may have a usecase that after creating many temporal objects, we'd
+like to keep some of them. In this case, we cannot use the same idea
+in `ary_inspect()` like appending objects to existing one. Instead,
+after `mrb_gc_arena_restore()`, we register back the objects we'd like
+to keep to the arena using `mrb_gc_protect(mrb, obj)`. Use
+`mrb_gc_protect()` with caution because its usage could lead to arena
+overflow error.
+
+We also have to mention that when `mrb_funcall` is called in top
+level, its return value is also registered to GC arena, so calling
+them repeatedly eventually lead to arena overflow error. Use
+`mrb_gc_arena_save()` and `mrb_gc_arena_restore()` or possible use of
+`mrb_gc_protect()` to workaround this.
diff --git a/doc/mrbconf/README.md b/doc/guides/mrbconf.md
index dfff41898..fabd7208b 100644
--- a/doc/mrbconf/README.md
+++ b/doc/guides/mrbconf.md
@@ -11,11 +11,7 @@ You can use mrbconfs with following ways:
changes `struct` layout and cause memory access error when C and other language(e.g., C++) is mixed.
## stdio setting.
-`ENABLE_STDIO`
-* Will be defined automatically if `DISABLE_STDIO` isn't defined.
-* Uses `<stdio.h>` functions.
-
-`DISABLE_STDIO`
+`MRB_DISABLE_STDIO`
* When defined `<stdio.h>` functions won't be used.
* Some features will be disabled when this is enabled:
* `mrb_irep` load/dump from/to file.
@@ -23,15 +19,12 @@ You can use mrbconfs with following ways:
* Printing features in **src/print.c**.
## Debug macros.
-`ENABLE_DEBUG`
+`MRB_ENABLE_DEBUG_HOOK`
* When defined code fetch hook and debug OP hook will be enabled.
* When using any of the hook set function pointer `code_fetch_hook` and/or `debug_op_hook` of `mrb_state`.
* Fetch hook will be called before any OP.
* Debug OP hook will be called when dispatching `OP_DEBUG`.
-`DISABLE_DEBUG`
-* Will be define automatically if `ENABLE_DEBUG` isn't defined.
-
`MRB_DEBUG`
* When defined `mrb_assert*` macro will be defined with macros from `<assert.h>`.
* Could be enabled via `enable_debug` method of `MRuby::Build`.
@@ -145,6 +138,10 @@ largest value of required alignment.
* Ignored when `MRB_USE_IV_SEGLIST` is defined.
## Other configuration.
+`MRB_UTF8_STRING`
+* Adds UTF-8 encoding support to character-oriented String instance methods.
+* If it isn't defined, they only support the US-ASCII encoding.
+
`MRB_FUNCALL_ARGC_MAX`
* Default value is `16`.
* Specifies 4th argument(`argc`) max value of `mrb_funcall`.
diff --git a/doc/mrbgems/README.md b/doc/guides/mrbgems.md
index f75231f71..f75231f71 100644
--- a/doc/mrbgems/README.md
+++ b/doc/guides/mrbgems.md
diff --git a/doc/language/Core.md b/doc/language/Core.md
deleted file mode 100644
index 390581f87..000000000
--- a/doc/language/Core.md
+++ /dev/null
@@ -1,1590 +0,0 @@
-# Core Classes
-
-## Array
-
-ISO Code | Mixins | Source File
---- | --- | ---
-15.2.12 | n/a | src/array.c
-
-### Class Methods
-
-#### []
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.4.1 | src/array.c | mrb_ary_s_create
-
-### Methods
-
-#### *
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.2 | src/array.c | mrb_ary_times
-
-#### +
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.1 | src/array.c | mrb_ary_plus
-
-#### <<
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.3 | src/array.c | mrb_ary_push_m
-
-#### []
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.4 | src/array.c | mrb_ary_aget
-
-#### []=
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.5 | src/array.c | mrb_ary_aset
-
-#### __ary_cmp
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/array.c | mrb_ary_cmp
-
-#### __ary_eq
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/array.c | mrb_ary_eq
-
-#### clear
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.6 | src/array.c | mrb_ary_clear
-
-#### concat
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.8 | src/array.c | mrb_ary_concat_m
-
-#### delete_at
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.9 | src/array.c | mrb_ary_delete_at
-
-#### empty?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.12 | src/array.c | mrb_ary_empty_p
-
-#### first
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.13 | src/array.c | mrb_ary_first
-
-#### index
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.14 | src/array.c | mrb_ary_index_m
-
-#### initialize_copy
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.16 | src/array.c | mrb_ary_replace_m
-
-#### join
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.17 | src/array.c | mrb_ary_join_m
-
-#### last
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.18 | src/array.c | mrb_ary_last
-
-#### length
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.19 | src/array.c | mrb_ary_size
-
-#### pop
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.21 | src/array.c | mrb_ary_pop
-
-#### push
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.22 | src/array.c | mrb_ary_push_m
-
-#### replace
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.23 | src/array.c | mrb_ary_replace_m
-
-#### reverse
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.24 | src/array.c | mrb_ary_reverse
-
-#### reverse!
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.25 | src/array.c | mrb_ary_reverse_bang
-
-#### rindex
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.26 | src/array.c | mrb_ary_rindex_m
-
-#### shift
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.27 | src/array.c | mrb_ary_shift
-
-#### size
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.28 | src/array.c | mrb_ary_size
-
-#### slice
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.29 | src/array.c | mrb_ary_aget
-
-#### unshift
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.12.5.30 | src/array.c | mrb_ary_unshift_m
-
-## Exception
-
-ISO Code | Mixins | Source File
---- | --- | ---
-15.2.22 | n/a | src/error.c
-
-### Class Methods
-
-#### exception
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/class.c | mrb_instance_new
-
-### Methods
-
-#### ==
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/error.c | exc_equal
-
-#### backtrace
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/backtrace.c | mrb_exc_backtrace
-
-#### exception
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/error.c | exc_exception
-
-#### initialize
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/error.c | exc_initialize
-
-#### inspect
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/error.c | exc_inspect
-
-#### message
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/error.c | exc_message
-
-#### to_s
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/error.c | exc_to_s
-
-## FalseClass
-
-ISO Code | Mixins | Source File
---- | --- | ---
-n/a | n/a | src/object.c
-
-### Methods
-
-#### &
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.6.3.1 | src/object.c | false_and
-
-#### ^
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.6.3.2 | src/object.c | false_xor
-
-#### inspect
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/object.c | false_to_s
-
-#### to_s
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.6.3.3 | src/object.c | false_to_s
-
-#### |
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.6.3.4 | src/object.c | false_or
-
-## Fixnum
-
-ISO Code | Mixins | Source File
---- | --- | ---
-n/a | n/a | src/numeric.c
-
-### Methods
-
-#### %
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.5 | src/numeric.c | fix_mod
-
-#### &
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.9 | src/numeric.c | fix_and
-
-#### *
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.3 | src/numeric.c | fix_mul
-
-#### +
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.1 | src/numeric.c | fix_plus
-
-#### -
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.2 | src/numeric.c | fix_minus
-
-#### <<
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.12 | src/numeric.c | fix_lshift
-
-#### ==
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.7 | src/numeric.c | fix_equal
-
-#### >>
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.13 | src/numeric.c | fix_rshift
-
-#### ^
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.11 | src/numeric.c | fix_xor
-
-#### divmod
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.30 | src/numeric.c | fix_divmod
-
-#### eql?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.16 | src/numeric.c | fix_eql
-
-#### hash
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.18 | src/numeric.c | flo_hash
-
-#### inspect
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/numeric.c | fix_to_s
-
-#### to_f
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.23 | src/numeric.c | fix_to_f
-
-#### to_s
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.25 | src/numeric.c | fix_to_s
-
-#### |
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.10 | src/numeric.c | fix_or
-
-#### ~
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.8 | src/numeric.c | fix_rev
-
-## Float
-
-ISO Code | Mixins | Source File
---- | --- | ---
-15.2.9 | n/a | src/numeric.c
-
-### Methods
-
-#### %
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.9.3.5 | src/numeric.c | flo_mod
-
-#### *
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.9.3.3 | src/numeric.c | flo_mul
-
-#### +
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.9.3.1 | src/numeric.c | flo_plus
-
-#### -
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.9.3.2 | src/numeric.c | flo_minus
-
-#### ==
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.9.3.7 | src/numeric.c | flo_eq
-
-#### ceil
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.9.3.8 | src/numeric.c | flo_ceil
-
-#### divmod
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/numeric.c | flo_divmod
-
-#### eql?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.16 | src/numeric.c | flo_eql
-
-#### finite?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.9.3.9 | src/numeric.c | flo_finite_p
-
-#### floor
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.9.3.10 | src/numeric.c | flo_floor
-
-#### infinite?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.9.3.11 | src/numeric.c | flo_infinite_p
-
-#### inspect
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/numeric.c | flo_to_s
-
-#### nan?
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/numeric.c | flo_nan_p
-
-#### round
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.9.3.12 | src/numeric.c | flo_round
-
-#### to_f
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.9.3.13 | src/numeric.c | flo_to_f
-
-#### to_i
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.9.3.14 | src/numeric.c | flo_truncate
-
-#### to_int
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/numeric.c | flo_truncate
-
-#### to_s
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.9.3.16 | src/numeric.c | flo_to_s
-
-#### truncate
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.9.3.15 | src/numeric.c | flo_truncate
-
-## Hash
-
-ISO Code | Mixins | Source File
---- | --- | ---
-15.2.13 | n/a | src/hash.c
-
-### Methods
-
-#### []
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.2 | src/hash.c | mrb_hash_aget
-
-#### []=
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.3 | src/hash.c | mrb_hash_aset
-
-#### __delete
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.8 | src/hash.c | mrb_hash_delete
-
-#### clear
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.4 | src/hash.c | mrb_hash_clear
-
-#### default
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.5 | src/hash.c | mrb_hash_default
-
-#### default=
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.6 | src/hash.c | mrb_hash_set_default
-
-#### default_proc
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.7 | src/hash.c | mrb_hash_default_proc
-
-#### default_proc=
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.7 | src/hash.c | mrb_hash_set_default_proc
-
-#### dup
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/hash.c | mrb_hash_dup
-
-#### empty?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.12 | src/hash.c | mrb_hash_empty_p
-
-#### has_key?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.13 | src/hash.c | mrb_hash_has_key
-
-#### has_value?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.14 | src/hash.c | mrb_hash_has_value
-
-#### include?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.15 | src/hash.c | mrb_hash_has_key
-
-#### initialize
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.16 | src/hash.c | mrb_hash_init
-
-#### key?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.18 | src/hash.c | mrb_hash_has_key
-
-#### keys
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.19 | src/hash.c | mrb_hash_keys
-
-#### length
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.20 | src/hash.c | mrb_hash_size_m
-
-#### member?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.21 | src/hash.c | mrb_hash_has_key
-
-#### shift
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.24 | src/hash.c | mrb_hash_shift
-
-#### size
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.25 | src/hash.c | mrb_hash_size_m
-
-#### store
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.26 | src/hash.c | mrb_hash_aset
-
-#### to_hash
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.29 | src/hash.c | mrb_hash_to_hash
-
-#### value?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.27 | src/hash.c | mrb_hash_has_value
-
-#### values
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.13.4.28 | src/hash.c | mrb_hash_values
-
-## Integer
-
-ISO Code | Mixins | Source File
---- | --- | ---
-15.2.8 | n/a | src/numeric.c
-
-### Methods
-
-#### to_i
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.24 | src/numeric.c | int_to_i
-
-#### to_int
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/numeric.c | int_to_i
-
-## NilClass
-
-ISO Code | Mixins | Source File
---- | --- | ---
-n/a | n/a | src/object.c
-
-### Methods
-
-#### &
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.4.3.1 | src/object.c | false_and
-
-#### ^
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.4.3.2 | src/object.c | false_xor
-
-#### inspect
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/object.c | nil_inspect
-
-#### nil?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.4.3.4 | src/object.c | mrb_true
-
-#### to_s
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.4.3.5 | src/object.c | nil_to_s
-
-#### |
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.4.3.3 | src/object.c | false_or
-
-## Numeric
-
-ISO Code | Mixins | Source File
---- | --- | ---
-15.2.7 | n/a | src/numeric.c
-
-### Methods
-
-#### **
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/numeric.c | num_pow
-
-#### /
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.8.3.4 | src/numeric.c | num_div
-
-#### <=>
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.9.3.6 | src/numeric.c | num_cmp
-
-#### quo
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.7.4.5 | src/numeric.c | num_div
-
-## Proc
-
-ISO Code | Mixins | Source File
---- | --- | ---
-15.2.17 | n/a | src/proc.c
-
-### Methods
-
-#### arity
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/proc.c | mrb_proc_arity
-
-#### initialize
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/proc.c | mrb_proc_initialize
-
-#### initialize_copy
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/proc.c | mrb_proc_init_copy
-
-## Range
-
-ISO Code | Mixins | Source File
---- | --- | ---
-15.2.14 | n/a | src/range.c
-
-### Methods
-
-#### ==
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.14.4.1 | src/range.c | mrb_range_eq
-
-#### ===
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.14.4.2 | src/range.c | mrb_range_include
-
-#### begin
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.14.4.3 | src/range.c | mrb_range_beg
-
-#### end
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.14.4.5 | src/range.c | mrb_range_end
-
-#### eql?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.14.4.14 | src/range.c | range_eql
-
-#### exclude_end?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.14.4.6 | src/range.c | mrb_range_excl
-
-#### first
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.14.4.7 | src/range.c | mrb_range_beg
-
-#### include?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.14.4.8 | src/range.c | mrb_range_include
-
-#### initialize
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.14.4.9 | src/range.c | mrb_range_initialize
-
-#### initialize_copy
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.14.4.15 | src/range.c | range_initialize_copy
-
-#### inspect
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.14.4.13 | src/range.c | range_inspect
-
-#### last
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.14.4.10 | src/range.c | mrb_range_end
-
-#### member?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.14.4.11 | src/range.c | mrb_range_include
-
-#### to_s
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.14.4.12 | src/range.c | range_to_s
-
-## RuntimeError
-
-ISO Code | Mixins | Source File
---- | --- | ---
-15.2.28 | n/a | src/error.c
-
-## ScriptError
-
-ISO Code | Mixins | Source File
---- | --- | ---
-15.2.37 | n/a | src/error.c
-
-## StandardError
-
-ISO Code | Mixins | Source File
---- | --- | ---
-15.2.23 | n/a | src/error.c
-
-## String
-
-ISO Code | Mixins | Source File
---- | --- | ---
-15.2.10 | n/a | src/string.c
-
-### Methods
-
-#### *
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.5 | src/string.c | mrb_str_times
-
-#### +
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.4 | src/string.c | mrb_str_plus_m
-
-#### <=>
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.1 | src/string.c | mrb_str_cmp_m
-
-#### ==
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.2 | src/string.c | mrb_str_equal_m
-
-#### []
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.6 | src/string.c | mrb_str_aref_m
-
-#### bytes
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/string.c | mrb_str_bytes
-
-#### bytesize
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/string.c | mrb_str_size
-
-#### capitalize
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.7 | src/string.c | mrb_str_capitalize
-
-#### capitalize!
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.8 | src/string.c | mrb_str_capitalize_bang
-
-#### chomp
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.9 | src/string.c | mrb_str_chomp
-
-#### chomp!
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.10 | src/string.c | mrb_str_chomp_bang
-
-#### chop
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.11 | src/string.c | mrb_str_chop
-
-#### chop!
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.12 | src/string.c | mrb_str_chop_bang
-
-#### downcase
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.13 | src/string.c | mrb_str_downcase
-
-#### downcase!
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.14 | src/string.c | mrb_str_downcase_bang
-
-#### empty?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.16 | src/string.c | mrb_str_empty_p
-
-#### eql?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.17 | src/string.c | mrb_str_eql
-
-#### hash
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.20 | src/string.c | mrb_str_hash_m
-
-#### include?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.21 | src/string.c | mrb_str_include
-
-#### index
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.22 | src/string.c | mrb_str_index_m
-
-#### initialize
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.23 | src/string.c | mrb_str_init
-
-#### initialize_copy
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.24 | src/string.c | mrb_str_replace
-
-#### inspect
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.46 | src/string.c | mrb_str_inspect
-
-#### intern
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.25 | src/string.c | mrb_str_intern
-
-#### length
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.26 | src/string.c | mrb_str_size
-
-#### replace
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.28 | src/string.c | mrb_str_replace
-
-#### reverse
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.29 | src/string.c | mrb_str_reverse
-
-#### reverse!
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.30 | src/string.c | mrb_str_reverse_bang
-
-#### rindex
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.31 | src/string.c | mrb_str_rindex_m
-
-#### size
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.33 | src/string.c | mrb_str_size
-
-#### slice
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.34 | src/string.c | mrb_str_aref_m
-
-#### split
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.35 | src/string.c | mrb_str_split_m
-
-#### to_f
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.38 | src/string.c | mrb_str_to_f
-
-#### to_i
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.39 | src/string.c | mrb_str_to_i
-
-#### to_s
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.40 | src/string.c | mrb_str_to_s
-
-#### to_str
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/string.c | mrb_str_to_s
-
-#### to_sym
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.41 | src/string.c | mrb_str_intern
-
-#### upcase
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.42 | src/string.c | mrb_str_upcase
-
-#### upcase!
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.10.5.43 | src/string.c | mrb_str_upcase_bang
-
-## Symbol
-
-ISO Code | Mixins | Source File
---- | --- | ---
-15.2.11 | n/a | src/symbol.c
-
-### Methods
-
-#### <=>
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/symbol.c | sym_cmp
-
-#### ===
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.11.3.1 | src/symbol.c | sym_equal
-
-#### id2name
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.11.3.2 | src/symbol.c | mrb_sym_to_s
-
-#### inspect
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.11.3.5 | src/symbol.c | sym_inspect
-
-#### to_s
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.11.3.3 | src/symbol.c | mrb_sym_to_s
-
-#### to_sym
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.11.3.4 | src/symbol.c | sym_to_sym
-
-## SyntaxError
-
-ISO Code | Mixins | Source File
---- | --- | ---
-15.2.38 | n/a | src/error.c
-
-## TrueClass
-
-ISO Code | Mixins | Source File
---- | --- | ---
-n/a | n/a | src/object.c
-
-### Methods
-
-#### &
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.5.3.1 | src/object.c | true_and
-
-#### ^
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.5.3.2 | src/object.c | true_xor
-
-#### inspect
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/object.c | true_to_s
-
-#### to_s
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.5.3.3 | src/object.c | true_to_s
-
-#### |
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.2.5.3.4 | src/object.c | true_or
-
-# Core Modules
-
-## Comparable
-
-ISO Code | Source File
---- | ---
-15.3.3 | src/compar.c
-
-## Enumerable
-
-ISO Code | Source File
---- | ---
-15.3.2 | src/enum.c
-
-## GC
-
-ISO Code | Source File
---- | ---
-n/a | src/gc.c
-
-### Class Methods
-
-#### disable
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/gc.c | gc_disable
-
-#### enable
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/gc.c | gc_enable
-
-#### generational_mode
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/gc.c | gc_generational_mode_get
-
-#### generational_mode=
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/gc.c | gc_generational_mode_set
-
-#### interval_ratio
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/gc.c | gc_interval_ratio_get
-
-#### interval_ratio=
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/gc.c | gc_interval_ratio_set
-
-#### start
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/gc.c | gc_start
-
-#### step_ratio
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/gc.c | gc_step_ratio_get
-
-#### step_ratio=
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/gc.c | gc_step_ratio_set
-
-#### test
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/gc.c | gc_test
-
-## Kernel
-
-ISO Code | Source File
---- | ---
-15.3.1 | src/kernel.c
-
-### Class Methods
-
-#### block_given?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.2.2 | src/kernel.c | mrb_f_block_given_p_m
-
-#### global_variables
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.2.4 | src/kernel.c | mrb_f_global_variables
-
-#### iterator?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.2.5 | src/kernel.c | mrb_f_block_given_p_m
-
-#### local_variables
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.2.7 | src/kernel.c | mrb_local_variables
-
-#### raise
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.2.12 | src/kernel.c | mrb_f_raise
-
-### Methods
-
-#### !=
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/kernel.c | mrb_obj_not_equal_m
-
-#### ==
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.1 | src/kernel.c | mrb_obj_equal_m
-
-#### ===
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.2 | src/kernel.c | mrb_equal_m
-
-#### __case_eqq
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/kernel.c | mrb_obj_ceqq
-
-#### __id__
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.3 | src/kernel.c | mrb_obj_id_m
-
-#### __send__
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.4 | src/kernel.c | mrb_f_send
-
-#### block_given?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.6 | src/kernel.c | mrb_f_block_given_p_m
-
-#### class
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.7 | src/kernel.c | mrb_obj_class_m
-
-#### clone
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.8 | src/kernel.c | mrb_obj_clone
-
-#### define_singleton_method
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/kernel.c | mod_define_singleton_method
-
-#### dup
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.9 | src/kernel.c | mrb_obj_dup
-
-#### eql?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.10 | src/kernel.c | mrb_obj_equal_m
-
-#### equal?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.11 | src/kernel.c | mrb_obj_equal_m
-
-#### extend
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.13 | src/kernel.c | mrb_obj_extend_m
-
-#### global_variables
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.14 | src/kernel.c | mrb_f_global_variables
-
-#### hash
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.15 | src/kernel.c | mrb_obj_hash
-
-#### initialize_copy
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.16 | src/kernel.c | mrb_obj_init_copy
-
-#### inspect
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.17 | src/kernel.c | mrb_obj_inspect
-
-#### instance_eval
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.18 | src/kernel.c | mrb_obj_instance_eval
-
-#### instance_of?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.19 | src/kernel.c | obj_is_instance_of
-
-#### instance_variable_defined?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.20 | src/kernel.c | mrb_obj_ivar_defined
-
-#### instance_variable_get
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.21 | src/kernel.c | mrb_obj_ivar_get
-
-#### instance_variable_set
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.22 | src/kernel.c | mrb_obj_ivar_set
-
-#### instance_variables
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.23 | src/kernel.c | mrb_obj_instance_variables
-
-#### is_a?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.24 | src/kernel.c | mrb_obj_is_kind_of_m
-
-#### iterator?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.25 | src/kernel.c | mrb_f_block_given_p_m
-
-#### kind_of?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.26 | src/kernel.c | mrb_obj_is_kind_of_m
-
-#### local_variables
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.28 | src/kernel.c | mrb_local_variables
-
-#### methods
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.31 | src/kernel.c | mrb_obj_methods_m
-
-#### nil?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.32 | src/kernel.c | mrb_false
-
-#### object_id
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.33 | src/kernel.c | mrb_obj_id_m
-
-#### private_methods
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.36 | src/kernel.c | mrb_obj_private_methods
-
-#### protected_methods
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.37 | src/kernel.c | mrb_obj_protected_methods
-
-#### public_methods
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.38 | src/kernel.c | mrb_obj_public_methods
-
-#### raise
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.40 | src/kernel.c | mrb_f_raise
-
-#### remove_instance_variable
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.41 | src/kernel.c | mrb_obj_remove_instance_variable
-
-#### respond_to?
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.43 | src/kernel.c | obj_respond_to
-
-#### send
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.44 | src/kernel.c | mrb_f_send
-
-#### singleton_class
-
-ISO Code | Source File | C Function
---- | --- | ---
-n/a | src/kernel.c | mrb_singleton_class
-
-#### singleton_methods
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.45 | src/kernel.c | mrb_obj_singleton_methods_m
-
-#### to_s
-
-ISO Code | Source File | C Function
---- | --- | ---
-15.3.1.3.46 | src/kernel.c | mrb_any_to_s
-
diff --git a/doc/language/README.md b/doc/language/README.md
deleted file mode 100644
index 24dd598ac..000000000
--- a/doc/language/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Language
-
-mruby is an implementation of the Ruby programming language.
-These documents are describing the language features and libraries
-which are provided together with mruby.
-
-## Built-In Class and Modules
-
-see *doc/language/Core.md*
diff --git a/doc/language/generator.rb b/doc/language/generator.rb
deleted file mode 100755
index c5bab1f84..000000000
--- a/doc/language/generator.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env ruby
-
-require 'pty'
-
-c_dir = File.dirname(__FILE__)
-MRUBY_ROOT = File.expand_path("#{c_dir}/../..")
-DOC_DIR = File.expand_path(c_dir)
-
-cmd = "ruby #{DOC_DIR}/mrbdoc/mrbdoc.rb #{MRUBY_ROOT} #{DOC_DIR} false"
-IO.popen(cmd, "r+") do |io|
- io.close_write
- while line = io.gets
- puts line
- end
-end
diff --git a/doc/language/mrbdoc/lib/mrbdoc_analyze.rb b/doc/language/mrbdoc/lib/mrbdoc_analyze.rb
deleted file mode 100644
index 94f368c08..000000000
--- a/doc/language/mrbdoc/lib/mrbdoc_analyze.rb
+++ /dev/null
@@ -1,231 +0,0 @@
-class MRBDoc
- SRC_DIR = 'src'
- MRBLIB_DIR = 'mrblib'
-
- def analyze_code dir, &block
- @mrb_files = {}
- @dir = File.expand_path(dir)
-
- block.call "MRBDOC\tanalyze #{@dir}"
-
- analyze(dir) do |progress|
- block.call progress
- end
- end
-
- def each_file(&block); @mrb_files.each {|k,v| block.call k,v}; end
-
- def find_c_func(c_func_name)
- each_file do |file_name, file|
- c_func = file.c_funcs(c_func_name)
- return c_func unless c_func.nil?
- end
- {}
- end
-
- def find_c_file(rb_obj_name, c_func_name)
- last_file_name_match = ''
- each_file do |file_name, file|
- c_func = file.c_funcs(c_func_name)
- if c_func and file.rb_class(rb_obj_name) or file.rb_module(rb_obj_name)
- return file_name
- elsif c_func
- last_file_name_match = file_name
- end
- end
- last_file_name_match
- end
-
- def find_c_file_by_class(name)
- each_file do |file_name, file|
- rb_class = file.rb_class(name)
- return file_name unless rb_class.nil?
- end
- 'nil'
- end
-
- def find_c_file_by_module(name)
- each_file do |file_name, file|
- rb_module = file.rb_module(name)
- return file_name unless rb_module.nil?
- end
- 'nil'
- end
-
- private
-
- def analyze dir, &block
- collect_all_files dir, &block
- end
-
- def collect_all_files dir, &block
- l = lambda {|f| block.call " - #{f.name}"}
- collect_files(src_code_dir(dir), /\.c$/, &l)
- collect_files(mrb_code_dir(dir), /\.rb$/, &l)
- end
-
- def collect_files dir, rxp, &block
- Dir.foreach(dir) do |file|
- next unless file =~ rxp
-
- file_path = "#{dir}/#{file}"
- mrb_file = MRBFile.new "#{file_path}"
- @mrb_files["#{file_path}"] = mrb_file
-
- block.call mrb_file
- end
- end
-
- def src_code_dir dir; File.expand_path SRC_DIR, dir; end
- def mrb_code_dir dir; File.expand_path MRBLIB_DIR, dir; end
-end
-
-class MRBFile
- attr_reader :name
- attr_reader :file
-
- def initialize mrb_file
- @file = mrb_file
- @name = File.basename file
- @c_funcs = {}
- @rb_class_c_def = {}
- @rb_method_c_def = {}
- @rb_class_method_c_def = {}
- @rb_module_c_def = {}
- @last_line = nil
- @assignments = {}
-
- @assignments['mrb->object_class'] = 'Object'
- @assignments['mrb->kernel_module'] = 'Kernel'
- @assignments['mrb->module_class'] = 'Module'
- @assignments['mrb->nil_class'] = 'NilClass'
- @assignments['mrb->true_class'] = 'TrueClass'
- @assignments['mrb->class_class'] = 'Class'
-
- analyze
- end
-
- def each_class &block
- @rb_class_c_def.each do |class_name, class_hsh|
- block.call class_name, class_hsh
- end
- end
-
- def each_method name, &block
- @rb_method_c_def.each do |met_name, met_hsh|
- met_name_tmp = met_name.sub /^#{name}_/, ''
- block.call met_name_tmp, met_hsh if met_hsh[:rb_class] == name
- end
- end
-
- def each_class_method name, &block
- @rb_class_method_c_def.each do |met_name, met_hsh|
- met_name_tmp = met_name.sub /^#{name}_/, ''
- block.call met_name_tmp, met_hsh if met_hsh[:rb_class] == name
- end
- end
-
- def each_module &block
- @rb_module_c_def.each do |module_name, module_hsh|
- block.call module_name, module_hsh
- end
- end
-
- def each_core_object &block
- each_class {|n| block.call n}
- each_module {|n| block.call n}
- end
-
- def c_funcs c_func_name; @c_funcs[c_func_name]; end
- def rb_class rb_class_name; @rb_class_c_def[rb_class_name]; end
- def rb_module rb_module_name; @rb_module_c_def[rb_module_name]; end
-
- private
-
- def analyze
- File.open(file).each_line.each_with_index do |line, idx|
- line_no = idx.succ
- if c_file?
- analyze_c_line line, line_no
- elsif rb_file?
- analyze_rb_line line, line_no
- else
- raise ArgumentError.new "#{file} is a not supported file type"
- end
- @last_line = line.strip
- end
- end
-
- def c_file?; (name =~ /\.c$/); end
- def rb_file?; (name =~ /\.rb$/); end
-
- RXP_C_VAR = /\s*([^\s]*?)\s*?/
- RXP_C_STR = /\s*?\"(.*?)\"\s*?/
- #RXP_C_ISO = /\s*\;\s*[\/\*]*\s*.*?([15\.]{0,3}[0-9\.]*)\s*[\\\\\*]*/
- RXP_C_ISO = /\s*;\s*[\/\*]*[\sa-zA-Z]*([\d\.]*)[\sa-zA-Z]*[\*\/]*/
-
- def analyze_c_line line, line_no
- case line.strip
- when /^([a-zA-Z\_][a-zA-Z\_0-9]*?)\((.*?)\)\s*?$/
- # assuming c method definition
- @c_funcs[$1] = {:line_no => line_no, :args => $2, :return => @last_line}
- when /mrb_define_class\(.*?\,#{RXP_C_STR}\,#{RXP_C_VAR}\)#{RXP_C_ISO}/
- # assuming ruby class definition in c
- class_name = $1.clone
- iso = $3.clone
- iso.strip!
- @rb_class_c_def[class_name] = {:c_object => $2, :iso => iso}
- assigns = line.split '='
- if assigns.size > 1
- assigns[0..-2].each do |v|
- @assignments[v.strip] = class_name
- end
- end
- when /mrb_define_module\(.*?\,#{RXP_C_STR}\)#{RXP_C_ISO}/
- # assuming ruby class definition in c
- module_name = $1.clone
- iso = $2.clone
- iso.strip!
- @rb_module_c_def[module_name] = {:iso => iso}
- assigns = line.split '='
- if assigns.size > 1
- assigns[0..-2].each do |v|
- @assignments[v.strip] = module_name
- end
- end
- when /mrb_define_method\(.*?\,#{RXP_C_VAR}\,#{RXP_C_STR}\,#{RXP_C_VAR}\,#{RXP_C_VAR}\)#{RXP_C_ISO}/
- # assuming ruby method definition in c
- name = $1.clone
- name = resolve_obj(name)
- iso = $5.clone
- iso.strip!
- @rb_method_c_def["#{name}_#{$2}"] = {:c_func => $3, :args => $4, :rb_class => name, :iso => iso}
- when /mrb_define_class_method\(.*?\,#{RXP_C_VAR}\,#{RXP_C_STR}\,#{RXP_C_VAR}\,#{RXP_C_VAR}\)#{RXP_C_ISO}/
- # assuming ruby class method definition in c
- class_name = $1.clone
- class_name = resolve_obj(class_name)
- iso = $5.clone
- iso.strip!
- @rb_class_method_c_def["#{class_name}_#{$2}"] = {:c_func => $3, :args => $4, :rb_class => class_name, :iso => iso}
- when /mrb_name_class\(.*?\,#{RXP_C_VAR}\,\s*mrb_intern\(.*?,#{RXP_C_STR}\)\)#{RXP_C_ISO}/
- class_name = $2.clone
- iso = $3.clone
- iso.strip!
- @rb_class_c_def[class_name] = {:c_object => $1, :iso => iso}
- @assignments[$1] = class_name
- when /mrb_include_module\(.*?\,#{RXP_C_VAR}\,\s*mrb_class_get\(.*?\,#{RXP_C_STR}\)\)/
- class_name = resolve_obj($1)
- mod = $2.clone
- @rb_class_c_def[class_name][:include] = [] unless @rb_class_c_def[class_name].has_key? :include
- @rb_class_c_def[class_name][:include] << mod
- end
- end
-
- def analyze_rb_line line, line_no
-
- end
-
- def resolve_obj c_var
- @assignments[c_var]
- end
-end
diff --git a/doc/language/mrbdoc/lib/mrbdoc_docu.rb b/doc/language/mrbdoc/lib/mrbdoc_docu.rb
deleted file mode 100644
index f6f327804..000000000
--- a/doc/language/mrbdoc/lib/mrbdoc_docu.rb
+++ /dev/null
@@ -1,118 +0,0 @@
-class MRBDoc
- def write_documentation dir, cfg, &block
- block.call "MRBDOC\twrite to #{File.expand_path(dir)}"
-
- write(dir, cfg) do |progress|
- block.call progress
- end
- end
-
- private
-
- def write dir, cfg
- File.open(File.expand_path('Core.md', dir), 'wb+') do |io|
- print_core_classes(io, cfg)
- print_core_modules(io, cfg)
- end
- end
-
- def get_core_list id
- core_list = {}
- each_file do |file_path, mrb_file|
- mrb_file.send(id) do |name, cls_hsh|
- core_list[name] = {:data => cls_hsh, :methods => {}, :class_methods => {}}
- mrb_file.each_method name do |met_name, met_hsh|
- core_list[name][:methods][met_name] = met_hsh
- end
- mrb_file.each_class_method name do |met_name, met_hsh|
- core_list[name][:class_methods][met_name] = met_hsh
- end
- end
- end
- core_list
- end
-
- def print_core_classes(io, cfg)
- core_list = get_core_list :each_class
- io.puts "# Core Classes\n\n"
- core_list.sort.each do |name, hsh|
- file = find_c_file_by_class(name)
- file = file.split("#{@dir}/")[1]
- iso = hsh[:data][:iso]
- iso = 'n/a' if iso.nil? or iso == ''
- mixins = hsh[:data][:include].join(', ') unless hsh[:data][:include].nil?
- mixins = 'n/a' if mixins.nil? or mixins == ''
-
- io.puts <<CLASS
-## #{name}
-
-ISO Code | Mixins | Source File
---- | --- | ---
-#{iso} | #{mixins} | #{file}
-
-CLASS
- print_class_methods(io, hsh, cfg)
- print_methods(io, hsh, cfg)
- end
- end
-
- def print_core_modules(io, cfg)
- core_list = get_core_list :each_module
- io.puts "# Core Modules\n\n"
- core_list.sort.each do |name, hsh|
- file = find_c_file_by_module(name)
- file = file.split("#{@dir}/")[1]
- iso = hsh[:data][:iso]
- iso = 'n/a' if iso.nil? or iso == ''
-
- io.puts <<CLASS
-## #{name}
-
-ISO Code | Source File
---- | ---
-#{iso} | #{file}
-
-CLASS
- print_class_methods(io, hsh, cfg)
- print_methods(io, hsh, cfg)
- end
- end
-
- def print_methods(io, hsh, cfg)
- return unless hsh[:methods].size > 0
- io.puts "### Methods\n\n"
- hsh[:methods].sort.each do |met_name, met_hsh|
- print_method(io, met_name, met_hsh, cfg)
- end
- end
-
- def print_class_methods(io, hsh, cfg)
- return unless hsh[:class_methods].size > 0
- io.puts "### Class Methods\n\n"
- hsh[:class_methods].sort.each do |met_name, met_hsh|
- print_method(io, met_name, met_hsh, cfg)
- end
- end
-
- def print_method(io, met_name, met_hsh, cfg)
- if cfg[:print_line_no]
- line_no_head = ' | Line'
- line_no = " | #{find_c_func(met_hsh[:c_func])[:line_no]}"
- else
- line_no, line_no_head = '', ''
- end
- file = find_c_file(met_hsh[:rb_class], met_hsh[:c_func])
- file = file.split("#{@dir}/")[1]
- iso = met_hsh[:iso]
- iso = 'n/a' if iso.nil? or iso == ''
-
- io.puts <<METHOD
-#### #{met_name}
-
-ISO Code | Source File | C Function#{line_no_head}
---- | --- | ---
-#{iso} | #{file} | #{met_hsh[:c_func]}#{line_no}
-
-METHOD
- end
-end
diff --git a/doc/language/mrbdoc/mrbdoc.rb b/doc/language/mrbdoc/mrbdoc.rb
deleted file mode 100755
index cafdf112a..000000000
--- a/doc/language/mrbdoc/mrbdoc.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env ruby
-
-$: << File.dirname(__FILE__) + '/lib'
-
-require 'mrbdoc_analyze'
-require 'mrbdoc_docu'
-
-MRUBY_ROOT = ARGV[0]
-DOC_ROOT = ARGV[1]
-_WRITE_LINE_NO = ARGV[2]
-STDOUT.sync = true
-
-raise ArgumentError.new 'mruby root missing!' if MRUBY_ROOT.nil?
-raise ArgumentError.new 'doc root missing!' if DOC_ROOT.nil?
-
-if _WRITE_LINE_NO.nil?
- WRITE_LINE_NO = true
-else
- case _WRITE_LINE_NO
- when 'true'
- WRITE_LINE_NO = true
- when 'false'
- WRITE_LINE_NO = false
- else
- raise ArgumentError.new 'Line no parameter has to be false or true!'
- end
-end
-
-mrbdoc = MRBDoc.new
-
-mrbdoc.analyze_code MRUBY_ROOT do |progress|
- puts progress
-end
-
-cfg = {:print_line_no => WRITE_LINE_NO}
-mrbdoc.write_documentation DOC_ROOT, cfg do |progress|
- puts progress
-end
diff --git a/examples/targets/build_config_ArduinoDue.rb b/examples/targets/build_config_ArduinoDue.rb
index 194fcb0f4..740dcfa02 100644
--- a/examples/targets/build_config_ArduinoDue.rb
+++ b/examples/targets/build_config_ArduinoDue.rb
@@ -50,7 +50,7 @@ MRuby::CrossBuild.new("ArduinoDue") do |conf|
cc.defines << %w(KHASH_DEFAULT_SIZE=8)
cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
cc.defines << %w(MRB_GC_STRESS)
- #cc.defines << %w(DISABLE_STDIO) #if you dont need stdio.
+ #cc.defines << %w(MRB_DISABLE_STDIO) #if you dont need stdio.
#cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval
end
diff --git a/examples/targets/build_config_chipKITMax32.rb b/examples/targets/build_config_chipKITMax32.rb
index e3a122f43..c3a146e4e 100644
--- a/examples/targets/build_config_chipKITMax32.rb
+++ b/examples/targets/build_config_chipKITMax32.rb
@@ -47,7 +47,7 @@ MRuby::CrossBuild.new("chipKITMax32") do |conf|
cc.defines << %w(KHASH_DEFAULT_SIZE=8)
cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
cc.defines << %w(MRB_GC_STRESS)
- #cc.defines << %w(DISABLE_STDIO) #if you dont need stdio.
+ #cc.defines << %w(MRB_DISABLE_STDIO) #if you dont need stdio.
#cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval
end
diff --git a/include/mrbconf.h b/include/mrbconf.h
index 95d4b3637..ab5dd1a03 100644
--- a/include/mrbconf.h
+++ b/include/mrbconf.h
@@ -26,6 +26,9 @@
/* represent mrb_value as a word (natural unit of data for the processor) */
//#define MRB_WORD_BOXING
+/* string class to handle UTF-8 encoding */
+//#define MRB_UTF8_STRING
+
/* argv max size in mrb_funcall */
//#define MRB_FUNCALL_ARGC_MAX 16
@@ -72,23 +75,25 @@
/* fixed size state atexit stack */
//#define MRB_FIXED_STATE_ATEXIT_STACK
-/* -DDISABLE_XXXX to drop following features */
-//#define DISABLE_STDIO /* use of stdio */
+/* -DMRB_DISABLE_XXXX to drop following features */
+//#define MRB_DISABLE_STDIO /* use of stdio */
-/* -DENABLE_XXXX to enable following features */
-//#define ENABLE_DEBUG /* hooks for debugger */
+/* -DMRB_ENABLE_XXXX to enable following features */
+//#define MRB_ENABLE_DEBUG_HOOK /* hooks for debugger */
/* end of configuration */
-/* define ENABLE_XXXX from DISABLE_XXX */
-#ifndef DISABLE_STDIO
-#define ENABLE_STDIO
+/* define MRB_DISABLE_XXXX from DISABLE_XXX (for compatibility) */
+#ifdef DISABLE_STDIO
+#define MRB_DISABLE_STDIO
#endif
-#ifndef ENABLE_DEBUG
-#define DISABLE_DEBUG
+
+/* define MRB_ENABLE_XXXX from ENABLE_XXX (for compatibility) */
+#ifdef ENABLE_DEBUG
+#define MRB_ENABLE_DEBUG_HOOK
#endif
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
# include <stdio.h>
#endif
@@ -100,15 +105,4 @@
# define TRUE 1
#endif
-#if defined(MRB_BUILD_AS_DLL)
-
-#if defined(MRB_CORE) || defined(MRB_LIB)
-#define MRB_API __declspec(dllexport)
-#else
-#define MRB_API __declspec(dllimport)
-#endif
-#else
-#define MRB_API extern
-#endif
-
#endif /* MRUBYCONF_H */
diff --git a/include/mruby.h b/include/mruby.h
index dedbd0748..51aecda4a 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -28,30 +28,43 @@
#ifndef MRUBY_H
#define MRUBY_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
#include <stdint.h>
#include <stddef.h>
#include <limits.h>
#include "mrbconf.h"
-#include "mruby/value.h"
-#include "mruby/version.h"
+#include <mruby/common.h>
+#include <mruby/value.h>
+#include <mruby/gc.h>
+#include <mruby/version.h>
+
+/**
+ * MRuby C API entry point
+ */
+MRB_BEGIN_DECL
typedef uint32_t mrb_code;
+
+/**
+ * Required arguments signature type.
+ */
typedef uint32_t mrb_aspec;
+
struct mrb_irep;
struct mrb_state;
+/**
+ * Function pointer type of custom allocator used in @see mrb_open_allocf.
+ *
+ * The function pointing it must behave similarly as realloc except:
+ * - If ptr is NULL it must allocate new space.
+ * - If s is NULL, ptr must be freed.
+ *
+ * See @see mrb_default_allocf for the default implementation.
+ */
typedef void* (*mrb_allocf) (struct mrb_state *mrb, void*, size_t, void *ud);
-#ifndef MRB_GC_ARENA_SIZE
-#define MRB_GC_ARENA_SIZE 100
-#endif
-
#ifndef MRB_FIXED_STATE_ATEXIT_STACK_SIZE
#define MRB_FIXED_STATE_ATEXIT_STACK_SIZE 5
#endif
@@ -98,12 +111,6 @@ struct mrb_context {
struct RFiber *fib;
};
-enum gc_state {
- GC_STATE_ROOT = 0,
- GC_STATE_MARK,
- GC_STATE_SWEEP
-};
-
struct mrb_jmpbuf;
typedef void (*mrb_atexit_func)(struct mrb_state*);
@@ -137,39 +144,15 @@ typedef struct mrb_state {
struct RClass *symbol_class;
struct RClass *kernel_module;
- struct heap_page *heaps; /* heaps for GC */
- struct heap_page *sweeps;
- struct heap_page *free_heaps;
- size_t live; /* count of live objects */
-#ifdef MRB_GC_FIXED_ARENA
- struct RBasic *arena[MRB_GC_ARENA_SIZE]; /* GC protection array */
-#else
- struct RBasic **arena; /* GC protection array */
- int arena_capa;
-#endif
- int arena_idx;
-
- enum gc_state gc_state; /* state of gc */
- int current_white_part; /* make white object by white_part */
- struct RBasic *gray_list; /* list of gray objects to be traversed incrementally */
- struct RBasic *atomic_gray_list; /* list of objects to be traversed atomically */
- size_t gc_live_after_mark;
- size_t gc_threshold;
- int gc_interval_ratio;
- int gc_step_ratio;
- mrb_bool gc_disabled:1;
- mrb_bool gc_full:1;
- mrb_bool is_generational_gc_mode:1;
- mrb_bool out_of_memory:1;
- size_t majorgc_old_threshold;
struct alloca_header *mems;
+ mrb_gc gc;
mrb_sym symidx;
struct kh_n2s *name2sym; /* symbol hash */
struct symbol_name *symtbl; /* symbol table */
size_t symcapa;
-#ifdef ENABLE_DEBUG
+#ifdef MRB_ENABLE_DEBUG_HOOK
void (*code_fetch_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs);
void (*debug_op_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs);
#endif
@@ -188,73 +171,618 @@ typedef struct mrb_state {
mrb_int atexit_stack_len;
} mrb_state;
-#if __STDC_VERSION__ >= 201112L
-# define mrb_noreturn _Noreturn
-#elif defined __GNUC__ && !defined __STRICT_ANSI__
-# define mrb_noreturn __attribute__((noreturn))
-# define mrb_deprecated __attribute__((deprecated))
-#elif defined _MSC_VER
-# define mrb_noreturn __declspec(noreturn)
-# define mrb_deprecated __declspec(deprecated)
-#else
-# define mrb_noreturn
-# define mrb_deprecated
-#endif
typedef mrb_value (*mrb_func_t)(mrb_state *mrb, mrb_value);
-MRB_API struct RClass *mrb_define_class(mrb_state *, const char*, struct RClass*);
+
+/**
+ * Defines a new class.
+ *
+ * If you're creating a gem it may look something like this:
+ *
+ * !!!c
+ * void mrb_example_gem_init(mrb_state* mrb) {
+ * struct RClass *example_class;
+ * example_class = mrb_define_class(mrb, "Example_Class", mrb->object_class);
+ * }
+ *
+ * void mrb_example_gem_final(mrb_state* mrb) {
+ * //free(TheAnimals);
+ * }
+ *
+ * @param [mrb_state *] mrb The current mruby state.
+ * @param [const char *] name The name of the defined class.
+ * @param [struct RClass *] super The new class parent.
+ * @return [struct RClass *] Reference to the newly defined class.
+ * @see mrb_define_class_under
+ */
+MRB_API struct RClass *mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super);
+
+/**
+ * Defines a new module.
+ * @param [mrb_state *] mrb_state* The current mruby state.
+ * @param [const char *] char* The name of the module.
+ * @return [struct RClass *] Reference to the newly defined module.
+ */
MRB_API struct RClass *mrb_define_module(mrb_state *, const char*);
MRB_API mrb_value mrb_singleton_class(mrb_state*, mrb_value);
+
+/**
+ * Include a module in another class or module.
+ * Equivalent to:
+ *
+ * module B
+ * include A
+ * end
+ * @param [mrb_state *] mrb_state* The current mruby state.
+ * @param [struct RClass *] RClass* A reference to module or a class.
+ * @param [struct RClass *] RClass* A reference to the module to be included.
+ */
MRB_API void mrb_include_module(mrb_state*, struct RClass*, struct RClass*);
+
+/**
+ * Prepends a module in another class or module.
+ *
+ * Equivalent to:
+ * module B
+ * prepend A
+ * end
+ * @param [mrb_state *] mrb_state* The current mruby state.
+ * @param [struct RClass *] RClass* A reference to module or a class.
+ * @param [struct RClass *] RClass* A reference to the module to be prepended.
+ */
MRB_API void mrb_prepend_module(mrb_state*, struct RClass*, struct RClass*);
-MRB_API void mrb_define_method(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec);
+/**
+ * Defines a global function in ruby.
+ *
+ * If you're creating a gem it may look something like this
+ *
+ * Example:
+ *
+ * !!!c
+ * mrb_value example_method(mrb_state* mrb, mrb_value self)
+ * {
+ * puts("Executing example command!");
+ * return self;
+ * }
+ *
+ * void mrb_example_gem_init(mrb_state* mrb)
+ * {
+ * mrb_define_method(mrb, mrb->kernel_module, "example_method", example_method, MRB_ARGS_NONE());
+ * }
+ *
+ * @param [mrb_state *] mrb The MRuby state reference.
+ * @param [struct RClass *] cla The class pointer where the method will be defined.
+ * @param [const char *] name The name of the method being defined.
+ * @param [mrb_func_t] func The function pointer to the method definition.
+ * @param [mrb_aspec] aspec The method parameters declaration.
+ */
+MRB_API void mrb_define_method(mrb_state *mrb, struct RClass *cla, const char *name, mrb_func_t func, mrb_aspec aspec);
+
+/**
+ * Defines a class method.
+ *
+ * Example:
+ * # Ruby style
+ * class Foo
+ *
+ * def Foo.bar
+ * end
+ *
+ * end
+ * // C style
+ * mrb_value bar_method(mrb_state* mrb, mrb_value self){
+ *
+ * return mrb_nil_value();
+ *
+ * }
+ * void mrb_example_gem_init(mrb_state* mrb){
+ *
+ * struct RClass *foo;
+ *
+ * foo = mrb_define_class(mrb, "Foo", mrb->object_class);
+ *
+ * mrb_define_class_method(mrb, foo, "bar", bar_method, MRB_ARGS_NONE());
+ *
+ * }
+ * @param [mrb_state *] mrb_state* The MRuby state reference.
+ * @param [struct RClass *] RClass* The class where the class method will be defined.
+ * @param [const char *] char* The name of the class method being defined.
+ * @param [mrb_func_t] mrb_func_t The function pointer to the class method definition.
+ * @param [mrb_aspec] mrb_aspec The method parameters declaration.
+ */
MRB_API void mrb_define_class_method(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec);
MRB_API void mrb_define_singleton_method(mrb_state*, struct RObject*, const char*, mrb_func_t, mrb_aspec);
+
+/**
+ * Defines a module fuction.
+ *
+ * Example:
+ * # Ruby style
+ * module Foo
+ *
+ * def Foo.bar * end
+ *
+ * end
+ * // C style
+ * mrb_value bar_method(mrb_state* mrb, mrb_value self){
+ *
+ * return mrb_nil_value(); *
+ * }
+ * void mrb_example_gem_init(mrb_state* mrb){
+ *
+ * struct RClass *foo;
+ *
+ * foo = mrb_define_module(mrb, "Foo");
+ *
+ * mrb_define_module_function(mrb, foo, "bar", bar_method, MRB_ARGS_NONE());
+ *
+ * }
+ * @param [mrb_state *] mrb_state* The MRuby state reference.
+ * @param [struct RClass *] RClass* The module where the module function will be defined.
+ * @param [const char *] char* The name of the module function being defined.
+ * @param [mrb_func_t] mrb_func_t The function pointer to the module function definition.
+ * @param [mrb_aspec] mrb_aspec The method parameters declaration.
+ */
MRB_API void mrb_define_module_function(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec);
+
+/**
+ * Defines a constant.
+ *
+ * Example:
+ * # Ruby style
+ *
+ * class ExampleClass
+ *
+ * AGE = 22
+ *
+ * end
+ *
+ * // C style
+ * #include <stdio.h>
+ * #include <mruby.h>
+ *
+ * void
+ * mrb_example_gem_init(mrb_state* mrb){
+ *
+ * mrb_define_const(mrb, mrb->kernel_module, "AGE", mrb_fixnum_value(22));
+ *
+ * }
+ *
+ * mrb_value
+ * mrb_example_gem_final(mrb_state* mrb){
+ *
+ * }
+ * @param [mrb_state *] mrb_state* The MRuby state reference.
+ * @param [struct RClass *] RClass* A class or module the constant is defined in.
+ * @param [const char *] name The name of the constant being defined.
+ * @param [mrb_value] mrb_value The value for the constant.
+ */
MRB_API void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_value);
+
+/**
+ * Undefines a method.
+ *
+ * Example:
+ * # Ruby style
+ *
+ * class ExampleClassA
+ *
+ * def example_method
+ * "example"
+ * end
+ *
+ * end
+ *
+ * ExampleClassA.new.example_method # => example
+ *
+ * class ExampleClassB < ExampleClassA
+ *
+ * undef_method :example_method
+ *
+ * end
+ *
+ * ExampleClassB.new.example_method # => undefined method 'example_method' for ExampleClassB (NoMethodError)
+ *
+ * // C style
+ * #include <stdio.h>
+ * #include <mruby.h>
+ *
+ * mrb_value
+ * mrb_example_method(mrb_state *mrb){
+ *
+ * return mrb_str_new_cstr(mrb, "example");
+ *
+ * }
+ *
+ * void
+ * mrb_example_gem_init(mrb_state* mrb){
+ * struct RClass *example_class_a;
+ * struct RClass *example_class_b;
+ * struct RClass *example_class_c;
+ *
+ * example_class_a = mrb_define_class(mrb, "ExampleClassA", mrb->object_class);
+ *
+ * mrb_define_method(mrb, example_class_a, "example_method", mrb_example_method, MRB_ARGS_NONE());
+ *
+ * example_class_b = mrb_define_class(mrb, "ExampleClassB", example_class_a);
+ *
+ * example_class_c = mrb_define_class(mrb, "ExampleClassC", example_class_b);
+ *
+ * mrb_undef_method(mrb, example_class_c, "example_method");
+ *
+ * }
+ *
+ * mrb_example_gem_final(mrb_state* mrb){
+ *
+ * }
+ *
+ * @param [mrb_state*] mrb_state* The mruby state reference.
+ * @param [struct RClass*] RClass* A class the method will be undefined from.
+ * @param [const char*] constchar* The name of the method to be undefined.
+ */
MRB_API void mrb_undef_method(mrb_state*, struct RClass*, const char*);
+
+/**
+ * Undefine a class method.
+ *
+ * Example:
+ * # Ruby style
+ *
+ * class ExampleClass
+ * def self.example_method
+ * "example"
+ * end
+ *
+ * end
+ *
+ * ExampleClass.example_method
+ *
+ * // C style
+ * #include <stdio.h>
+ * #include <mruby.h>
+ *
+ * mrb_value
+ * mrb_example_method(mrb_state *mrb){
+ *
+ * return mrb_str_new_cstr(mrb, "example");
+ *
+ * }
+ *
+ * void
+ * mrb_example_gem_init(mrb_state* mrb){
+ *
+ * struct RClass *example_class;
+ *
+ * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class);
+ *
+ * mrb_define_class_method(mrb, example_class, "example_method", mrb_example_method, MRB_ARGS_NONE());
+ *
+ * mrb_undef_class_method(mrb, example_class, "example_method");
+ *
+ * }
+ *
+ * void
+ * mrb_example_gem_final(mrb_state* mrb){
+ *
+ * }
+ * @param [mrb_state*] mrb_state* The mruby state reference.
+ * @param [RClass*] RClass* A class the class method will be undefined from.
+ * @param [constchar*] constchar* The name of the class method to be undefined.
+ */
MRB_API void mrb_undef_class_method(mrb_state*, struct RClass*, const char*);
+
+/**
+ * Initialize a new object instace of c class.
+ *
+ * Example:
+ *
+ * # Ruby style
+ * class ExampleClass
+ * end
+ *
+ * p ExampleClass # => #<ExampleClass:0x9958588>
+ * // C style
+ * #include <stdio.h>
+ * #include <mruby.h>
+ *
+ * void
+ * mrb_example_gem_init(mrb_state* mrb) {
+ * struct RClass *example_class;
+ * mrb_value obj;
+ *
+ * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class); # => class ExampleClass; end
+ * obj = mrb_obj_new(mrb, example_class, 0, NULL); # => ExampleClass.new
+ * mrb_p(mrb, obj); // => Kernel#p
+ * }
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [RClass*] c Reference to the class of the new object.
+ * @param [mrb_int] argc Number of arguments in argv
+ * @param [const mrb_value *] argv Array of mrb_value to initialize the object
+ * @return [mrb_value] The newly initialized object
+ */
MRB_API mrb_value mrb_obj_new(mrb_state *mrb, struct RClass *c, mrb_int argc, const mrb_value *argv);
-#define mrb_class_new_instance(mrb,argc,argv,c) mrb_obj_new(mrb,c,argc,argv)
+
+/** @see mrb_obj_new */
+MRB_INLINE mrb_value mrb_class_new_instance(mrb_state *mrb, mrb_int argc, const mrb_value *argv, struct RClass *c)
+{
+ return mrb_obj_new(mrb,c,argc,argv);
+}
+
MRB_API mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv);
+
+/**
+ * Creates a new instance of Class, Class.
+ *
+ * Example:
+ *
+ * void
+ * mrb_example_gem_init(mrb_state* mrb) {
+ * struct RClass *example_class;
+ * mrb_value obj;
+ *
+ * example_class = mrb_class_new(mrb, mrb->object_class);
+ * obj = mrb_obj_new(mrb, example_class, 0, NULL); // => #<#<Class:0x9a945b8>:0x9a94588>
+ * mrb_p(mrb, obj); // => Kernel#p
+ * }
+ *
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [struct RClass *] super The super class or parent.
+ * @return [struct RClass *] Reference to the new class.
+ */
MRB_API struct RClass * mrb_class_new(mrb_state *mrb, struct RClass *super);
+
+/**
+ * Creates a new module, Module.
+ *
+ * Example:
+ * void
+ * mrb_example_gem_init(mrb_state* mrb) {
+ * struct RClass *example_module;
+ *
+ * example_module = mrb_module_new(mrb);
+ * }
+ *
+ * @param [mrb_state*] mrb The current mruby state.
+ * @return [struct RClass *] Reference to the new module.
+ */
MRB_API struct RClass * mrb_module_new(mrb_state *mrb);
+
+/**
+ * Returns an mrb_bool. True if class was defined, and false if the class was not defined.
+ *
+ * Example:
+ * void
+ * mrb_example_gem_init(mrb_state* mrb) {
+ * struct RClass *example_class;
+ * mrb_bool cd;
+ *
+ * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class);
+ * cd = mrb_class_defined(mrb, "ExampleClass");
+ *
+ * // If mrb_class_defined returns 1 then puts "True"
+ * // If mrb_class_defined returns 0 then puts "False"
+ * if (cd == 1){
+ * puts("True");
+ * }
+ * else {
+ * puts("False");
+ * }
+ * }
+ *
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [const char *] name A string representing the name of the class.
+ * @return [mrb_bool] A boolean value.
+ */
MRB_API mrb_bool mrb_class_defined(mrb_state *mrb, const char *name);
+
+/**
+ * Gets a class.
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [const char *] name The name of the class.
+ * @return [struct RClass *] A reference to the class.
+*/
MRB_API struct RClass * mrb_class_get(mrb_state *mrb, const char *name);
+
+/**
+ * Gets a child class.
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [struct RClass *] outer The name of the parent class.
+ * @param [const char *] name The name of the class.
+ * @return [struct RClass *] A reference to the class.
+*/
MRB_API struct RClass * mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name);
+
+/**
+ * Gets a module.
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [const char *] name The name of the module.
+ * @return [struct RClass *] A reference to the module.
+*/
MRB_API struct RClass * mrb_module_get(mrb_state *mrb, const char *name);
+
+/**
+ * Gets a module defined under another module.
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [struct RClass *] outer The name of the outer module.
+ * @param [const char *] name The name of the module.
+ * @return [struct RClass *] A reference to the module.
+*/
MRB_API struct RClass * mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name);
MRB_API mrb_value mrb_notimplement_m(mrb_state*, mrb_value);
+/**
+ * Duplicate an object.
+ *
+ * Equivalent to:
+ * Object#dup
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [mrb_value] obj Object to be duplicate.
+ * @return [mrb_value] The newly duplicated object.
+ */
MRB_API mrb_value mrb_obj_dup(mrb_state *mrb, mrb_value obj);
MRB_API mrb_value mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method);
+
+/**
+ * Returns true if obj responds to the given method. If the method was defined for that
+ * class it returns true, it returns false otherwise.
+ *
+ * Example:
+ * # Ruby style
+ * class ExampleClass
+ * def example_method
+ * end
+ * end
+ *
+ * ExampleClass.new.respond_to?(:example_method) # => true
+ *
+ * // C style
+ * void
+ * mrb_example_gem_init(mrb_state* mrb) {
+ * struct RClass *example_class;
+ * mrb_sym mid;
+ * mrb_bool obj_resp;
+ *
+ * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class);
+ * mrb_define_method(mrb, example_class, "example_method", exampleMethod, MRB_ARGS_NONE());
+ * mid = mrb_intern_str(mrb, mrb_str_new_cstr(mrb, "example_method" ));
+ * obj_resp = mrb_obj_respond_to(mrb, example_class, mid); // => 1(true in Ruby world)
+ *
+ * // If mrb_obj_respond_to returns 1 then puts "True"
+ * // If mrb_obj_respond_to returns 0 then puts "False"
+ * if (obj_resp == 1) {
+ * puts("True");
+ * }
+ * else if (obj_resp == 0) {
+ * puts("False");
+ * }
+ * }
+ *
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [struct RClass *] c A reference to a class.
+ * @param [mrb_sym] mid A symbol referencing a method id.
+ * @return [mrb_bool] A boolean value.
+ */
MRB_API mrb_bool mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid);
+
+/**
+ * Defines a new class under a given module
+ *
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [struct RClass *] outer Reference to the module under which the new class will be defined
+ * @param [const char *] name The name of the defined class
+ * @param [struct RClass *] super The new class parent
+ * @return [struct RClass *] Reference to the newly defined class
+ * @see mrb_define_class
+ */
MRB_API struct RClass * mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super);
+
MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name);
-/* required arguments */
+/**
+ * Function requires n arguments.
+ *
+ * @param n
+ * The number of required arguments.
+ */
#define MRB_ARGS_REQ(n) ((mrb_aspec)((n)&0x1f) << 18)
-/* optional arguments */
+
+/**
+ * Funtion takes n optional arguments
+ *
+ * @param n
+ * The number of optional arguments.
+ */
#define MRB_ARGS_OPT(n) ((mrb_aspec)((n)&0x1f) << 13)
-/* mandatory and optinal arguments */
+
+/**
+ * Funtion takes n1 mandatory arguments and n2 optional arguments
+ *
+ * @param n1
+ * The number of required arguments.
+ * @param n2
+ * The number of optional arguments.
+ */
#define MRB_ARGS_ARG(n1,n2) (MRB_ARGS_REQ(n1)|MRB_ARGS_OPT(n2))
-/* rest argument */
+/** rest argument */
#define MRB_ARGS_REST() ((mrb_aspec)(1 << 12))
-/* required arguments after rest */
+
+/** required arguments after rest */
#define MRB_ARGS_POST(n) ((mrb_aspec)((n)&0x1f) << 7)
-/* keyword arguments (n of keys, kdict) */
+
+/** keyword arguments (n of keys, kdict) */
#define MRB_ARGS_KEY(n1,n2) ((mrb_aspec)((((n1)&0x1f) << 2) | ((n2)?(1<<1):0)))
-/* block argument */
+
+/**
+ * Function takes a block argument
+ */
#define MRB_ARGS_BLOCK() ((mrb_aspec)1)
-/* accept any number of arguments */
+/**
+ * Function accepts any number of arguments
+ */
#define MRB_ARGS_ANY() MRB_ARGS_REST()
-/* accept no arguments */
+
+/**
+ * Function accepts no arguments
+ */
#define MRB_ARGS_NONE() ((mrb_aspec)0)
-MRB_API mrb_int mrb_get_args(mrb_state *mrb, const char *format, ...);
+/**
+ * Format specifiers for {mrb_get_args} function
+ *
+ * Must be a C string composed of the following format specifiers:
+ *
+ * | char | Ruby type | C types | Notes |
+ * |:----:|----------------|-------------------|----------------------------------------------------|
+ * | `o` | {Object} | {mrb_value} | Could be used to retrieve any type of argument |
+ * | `C` | {Class}/{Module} | {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; `s!` gives (`NULL`,`0`) for `nil` |
+ * | `z` | {String} | char * | `NULL` 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} | |
+ * | `n` | {Symbol} | {mrb_sym} | |
+ * | `&` | block | {mrb_value} | |
+ * | `*` | rest arguments | {mrb_value} *, {mrb_int} | Receive the rest of arguments as an array. |
+ * | &vert; | optional | | After this spec following specs would be optional. |
+ * | `?` | optional given | {mrb_bool} | `TRUE` if preceding argument is given. Used to check optional argument is given. |
+ *
+ * @see mrb_get_args
+ */
+typedef const char *mrb_args_format;
+
+/**
+ * Retrieve arguments from mrb_state.
+ *
+ * When applicable, implicit conversions (such as `to_str`, `to_ary`, `to_hash`) are
+ * applied to received arguments.
+ * Used inside a function of mrb_func_t type.
+ *
+ * @param mrb The current MRuby state.
+ * @param format [mrb_args_format] is a list of format specifiers
+ * @param ... The passing variadic arguments must be a pointer of retrieving type.
+ * @return the number of arguments retrieved.
+ * @see mrb_args_format
+ */
+MRB_API mrb_int mrb_get_args(mrb_state *mrb, mrb_args_format format, ...);
+
+static inline mrb_sym
+mrb_get_mid(mrb_state *mrb) /* get method symbol */
+{
+ return mrb->c->ci->mid;
+}
+
+static inline int
+mrb_get_argc(mrb_state *mrb) /* get argc */
+{
+ return mrb->c->ci->argc;
+}
/* `strlen` for character string literals (use with caution or `strlen` instead)
Adjacent string literals are concatenated in C/C++ in translation phase 6.
@@ -264,6 +792,9 @@ MRB_API mrb_int mrb_get_args(mrb_state *mrb, const char *format, ...);
*/
#define mrb_strlen_lit(lit) (sizeof(lit "") - 1)
+/**
+ * Call existing ruby functions.
+ */
MRB_API mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, mrb_int,...);
MRB_API mrb_value mrb_funcall_argv(mrb_state*, mrb_value, mrb_sym, mrb_int, const mrb_value*);
MRB_API mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, mrb_sym, mrb_int, const mrb_value*, mrb_value);
@@ -288,6 +819,10 @@ MRB_API struct RBasic *mrb_obj_alloc(mrb_state*, enum mrb_vtype, struct RClass*)
MRB_API void mrb_free(mrb_state*, void*);
MRB_API mrb_value mrb_str_new(mrb_state *mrb, const char *p, size_t len);
+
+/**
+ * Turns a C string into a Ruby string value.
+ */
MRB_API mrb_value mrb_str_new_cstr(mrb_state*, const char*);
MRB_API mrb_value mrb_str_new_static(mrb_state *mrb, const char *p, size_t len);
#define mrb_str_new_lit(mrb, lit) mrb_str_new_static(mrb, (lit), mrb_strlen_lit(lit))
@@ -304,11 +839,54 @@ char* mrb_locale_from_utf8(const char *p, size_t len);
#define mrb_utf8_free(p)
#endif
+/**
+ * Creates new mrb_state.
+ *
+ * @return
+ * Pointer to the newly created mrb_state.
+ */
MRB_API mrb_state* mrb_open(void);
-MRB_API mrb_state* mrb_open_allocf(mrb_allocf, void *ud);
-MRB_API mrb_state* mrb_open_core(mrb_allocf, void *ud);
-MRB_API void mrb_close(mrb_state*);
+/**
+ * Create new mrb_state with custom allocators.
+ *
+ * @param f
+ * Reference to the allocation function.
+ * @param ud
+ * User data will be passed to custom allocator f.
+ * If user data isn't required just pass NULL.
+ * @return
+ * Pointer to the newly created mrb_state.
+ */
+MRB_API mrb_state* mrb_open_allocf(mrb_allocf f, void *ud);
+
+/**
+ * Create new mrb_state with just the MRuby core
+ *
+ * @param f
+ * Reference to the allocation function.
+ * Use mrb_default_allocf for the default
+ * @param ud
+ * User data will be passed to custom allocator f.
+ * If user data isn't required just pass NULL.
+ * @return
+ * Pointer to the newly created mrb_state.
+ */
+MRB_API mrb_state* mrb_open_core(mrb_allocf f, void *ud);
+
+/**
+ * Closes and frees a mrb_state.
+ *
+ * @param mrb
+ * Pointer to the mrb_state to be closed.
+ */
+MRB_API void mrb_close(mrb_state *mrb);
+
+/**
+ * The default allocation function.
+ *
+ * @see mrb_allocf
+ */
MRB_API void* mrb_default_allocf(mrb_state*, void*, size_t, void*);
MRB_API mrb_value mrb_top_self(mrb_state *);
@@ -408,7 +986,13 @@ MRB_API mrb_value mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg);
MRB_API mrb_value mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv);
MRB_API mrb_value mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c);
+/* mrb_gc_protect() leaves the object in the arena */
MRB_API void mrb_gc_protect(mrb_state *mrb, mrb_value obj);
+/* mrb_gc_register() keeps the object from GC. */
+MRB_API void mrb_gc_register(mrb_state *mrb, mrb_value obj);
+/* mrb_gc_unregister() removes the object from GC root. */
+MRB_API void mrb_gc_unregister(mrb_state *mrb, mrb_value obj);
+
MRB_API mrb_value mrb_to_int(mrb_state *mrb, mrb_value val);
#define mrb_int(mrb, val) mrb_fixnum(mrb_to_int(mrb, val))
MRB_API void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t);
@@ -429,9 +1013,26 @@ MRB_API mrb_value mrb_attr_get(mrb_state *mrb, mrb_value obj, mrb_sym id);
MRB_API mrb_bool mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid);
MRB_API mrb_bool mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c);
-/* fiber functions (you need to link mruby-fiber mrbgem to use) */
+
+/*
+ * Resume a Fiber
+ *
+ * @mrbgem mruby-fiber
+ */
MRB_API mrb_value mrb_fiber_resume(mrb_state *mrb, mrb_value fib, mrb_int argc, const mrb_value *argv);
+
+/*
+ * Yield a Fiber
+ *
+ * @mrbgem mruby-fiber
+ */
MRB_API mrb_value mrb_fiber_yield(mrb_state *mrb, mrb_int argc, const mrb_value *argv);
+
+/*
+ * FiberError reference
+ *
+ * @mrbgem mruby-fiber
+ */
#define E_FIBER_ERROR (mrb_class_get(mrb, "FiberError"))
/* memory pool implementation */
@@ -465,8 +1066,6 @@ MRB_API void mrb_show_copyright(mrb_state *mrb);
MRB_API mrb_value mrb_format(mrb_state *mrb, const char *format, ...);
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
+MRB_END_DECL
#endif /* MRUBY_H */
diff --git a/include/mruby/array.h b/include/mruby/array.h
index 0b17b47fd..8155c12e7 100644
--- a/include/mruby/array.h
+++ b/include/mruby/array.h
@@ -7,9 +7,13 @@
#ifndef MRUBY_ARRAY_H
#define MRUBY_ARRAY_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <mruby/common.h>
+
+/*
+ * Array class
+ */
+MRB_BEGIN_DECL
+
typedef struct mrb_shared_array {
int refcnt;
@@ -41,15 +45,78 @@ struct RArray {
void mrb_ary_decref(mrb_state*, mrb_shared_array*);
MRB_API void mrb_ary_modify(mrb_state*, struct RArray*);
MRB_API mrb_value mrb_ary_new_capa(mrb_state*, mrb_int);
+
+/*
+ * Initializes a new array.
+ *
+ * Equivalent to:
+ *
+ * Array.new
+ *
+ * @param mrb The mruby state reference.
+ * @return The initialized array
+ */
MRB_API mrb_value mrb_ary_new(mrb_state *mrb);
+
MRB_API mrb_value mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals);
MRB_API mrb_value mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr);
MRB_API void mrb_ary_concat(mrb_state*, mrb_value, mrb_value);
MRB_API mrb_value mrb_ary_splat(mrb_state*, mrb_value);
-MRB_API void mrb_ary_push(mrb_state*, mrb_value, mrb_value);
+
+/*
+ * Pushes value into array.
+ *
+ * Equivalent to:
+ *
+ * ary << value
+ *
+ * @param mrb The mruby state reference.
+ * @param ary The array in which the value will be pushed
+ * @param value The value to be pushed into array
+ */
+MRB_API void mrb_ary_push(mrb_state *mrb, mrb_value array, mrb_value value);
+
+/*
+ * Pops the last element from the array.
+ *
+ * Equivalent to:
+ *
+ * ary.pop
+ *
+ * @param mrb The mruby state reference.
+ * @param ary The array from which the value will be poped.
+ * @return The poped value.
+ */
MRB_API mrb_value mrb_ary_pop(mrb_state *mrb, mrb_value ary);
+
+/*
+ * Returns a reference to an element of the array on the given index.
+ *
+ * Equivalent to:
+ *
+ * ary[n]
+ *
+ * @param mrb The mruby state reference.
+ * @param ary The target array.
+ * @param n The array index being referenced
+ * @return The referenced value.
+ */
MRB_API mrb_value mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n);
+
+/*
+ * Sets a value on an array at the given index
+ *
+ * Equivalent to:
+ *
+ * ary[n] = val
+ *
+ * @param mrb The mruby state reference.
+ * @param ary The target array.
+ * @param n The array index being referenced.
+ * @param val The value being setted.
+ */
MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val);
+
MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value a, mrb_value b);
MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self);
MRB_API mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item);
@@ -67,8 +134,6 @@ mrb_ary_len(mrb_state *mrb, mrb_value ary)
return RARRAY_LEN(ary);
}
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
+MRB_END_DECL
#endif /* MRUBY_ARRAY_H */
diff --git a/include/mruby/class.h b/include/mruby/class.h
index 85f3e12c6..5035fed89 100644
--- a/include/mruby/class.h
+++ b/include/mruby/class.h
@@ -7,9 +7,12 @@
#ifndef MRUBY_CLASS_H
#define MRUBY_CLASS_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <mruby/common.h>
+
+/**
+ * Class class
+ */
+MRB_BEGIN_DECL
struct RClass {
MRB_OBJECT_HEADER;
@@ -81,8 +84,6 @@ void mrb_gc_mark_mt(mrb_state*, struct RClass*);
size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*);
void mrb_gc_free_mt(mrb_state*, struct RClass*);
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
+MRB_END_DECL
#endif /* MRUBY_CLASS_H */
diff --git a/include/mruby/common.h b/include/mruby/common.h
new file mode 100644
index 000000000..e7841f38f
--- /dev/null
+++ b/include/mruby/common.h
@@ -0,0 +1,67 @@
+/*
+** mruby/common.h - mruby common platform definitions
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_COMMON_H
+#define MRUBY_COMMON_H
+
+
+#ifdef __cplusplus
+# define MRB_BEGIN_DECL extern "C" {
+# define MRB_END_DECL }
+#else
+/** Start declarations in C mode */
+# define MRB_BEGIN_DECL
+/** End declarations in C mode */
+# define MRB_END_DECL
+#endif
+
+/**
+ * Shared compiler macros
+ */
+MRB_BEGIN_DECL
+
+/** Declare a function that never returns. */
+#if __STDC_VERSION__ >= 201112L
+# define mrb_noreturn _Noreturn
+#elif defined __GNUC__ && !defined __STRICT_ANSI__
+# define mrb_noreturn __attribute__((noreturn))
+#elif defined _MSC_VER
+# define mrb_noreturn __declspec(noreturn)
+#else
+# define mrb_noreturn
+#endif
+
+/** Mark a function as deprecated. */
+#if defined __GNUC__ && !defined __STRICT_ANSI__
+# define mrb_deprecated __attribute__((deprecated))
+#elif defined _MSC_VER
+# define mrb_deprecated __declspec(deprecated)
+#else
+# define mrb_deprecated
+#endif
+
+/** Declare a function as always inlined. */
+#if defined(_MSC_VER)
+# define MRB_INLINE static __inline
+#else
+# define MRB_INLINE static inline
+#endif
+
+
+/** Declare a public MRuby API function. */
+#if defined(MRB_BUILD_AS_DLL)
+#if defined(MRB_CORE) || defined(MRB_LIB)
+# define MRB_API __declspec(dllexport)
+#else
+# define MRB_API __declspec(dllimport)
+#endif
+#else
+# define MRB_API extern
+#endif
+
+MRB_END_DECL
+
+#endif /* MRUBY_COMMON_H */
diff --git a/include/mruby/compile.h b/include/mruby/compile.h
index 1fb81782d..2ed5ca7a0 100644
--- a/include/mruby/compile.h
+++ b/include/mruby/compile.h
@@ -7,11 +7,14 @@
#ifndef MRUBY_COMPILE_H
#define MRUBY_COMPILE_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <mruby/common.h>
+
+/**
+ * MRuby Compiler
+ */
+MRB_BEGIN_DECL
-#include "mruby.h"
+#include <mruby.h>
struct mrb_jmpbuf;
@@ -109,7 +112,7 @@ struct mrb_parser_state {
struct mrb_pool *pool;
mrb_ast_node *cells;
const char *s, *send;
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
FILE *f;
#endif
mrbc_context *cxt;
@@ -164,7 +167,7 @@ MRB_API void mrb_parser_set_filename(struct mrb_parser_state*, char const*);
MRB_API char const* mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx);
/* utility functions */
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
MRB_API struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*);
#endif
MRB_API struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrbc_context*);
@@ -172,19 +175,16 @@ MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,int,mr
MRB_API struct RProc* mrb_generate_code(mrb_state*, struct mrb_parser_state*);
/* program load functions */
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
MRB_API mrb_value mrb_load_file(mrb_state*,FILE*);
+MRB_API mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt);
#endif
MRB_API mrb_value mrb_load_string(mrb_state *mrb, const char *s);
MRB_API mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, int len);
-#ifdef ENABLE_STDIO
-MRB_API mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt);
-#endif
MRB_API mrb_value mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *cxt);
MRB_API mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *cxt);
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
+/** @} */
+MRB_END_DECL
#endif /* MRUBY_COMPILE_H */
diff --git a/include/mruby/data.h b/include/mruby/data.h
index d457e3722..5f30a164f 100644
--- a/include/mruby/data.h
+++ b/include/mruby/data.h
@@ -7,12 +7,23 @@
#ifndef MRUBY_DATA_H
#define MRUBY_DATA_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <mruby/common.h>
+/**
+ * Custom C wrapped data.
+ *
+ * Defining Ruby wrappers around native objects.
+ */
+MRB_BEGIN_DECL
+
+/**
+ * Custom data type description.
+ */
typedef struct mrb_data_type {
+ /** data type name */
const char *struct_name;
+
+ /** data type release function pointer */
void (*dfree)(mrb_state *mrb, void*);
} mrb_data_type;
@@ -59,8 +70,6 @@ mrb_data_init(mrb_value v, void *ptr, const mrb_data_type *type)
DATA_TYPE(v) = type;
}
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
+MRB_END_DECL
#endif /* MRUBY_DATA_H */
diff --git a/include/mruby/debug.h b/include/mruby/debug.h
index 0860ba8d5..71f393055 100644
--- a/include/mruby/debug.h
+++ b/include/mruby/debug.h
@@ -7,9 +7,12 @@
#ifndef MRUBY_DEBUG_H
#define MRUBY_DEBUG_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <mruby/common.h>
+
+/**
+ * MRuby Debugging.
+ */
+MRB_BEGIN_DECL
typedef enum mrb_debug_line_type {
mrb_debug_line_ary = 0,
@@ -58,8 +61,6 @@ MRB_API mrb_irep_debug_info_file *mrb_debug_info_append_file(
MRB_API mrb_irep_debug_info *mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep);
MRB_API void mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d);
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
+MRB_END_DECL
#endif /* MRUBY_DEBUG_H */
diff --git a/include/mruby/dump.h b/include/mruby/dump.h
index 4cee3c0ac..6311a8115 100644
--- a/include/mruby/dump.h
+++ b/include/mruby/dump.h
@@ -7,12 +7,14 @@
#ifndef MRUBY_DUMP_H
#define MRUBY_DUMP_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <mruby.h>
+#include <mruby/irep.h>
+#include <mruby/common.h>
-#include "mruby.h"
-#include "mruby/irep.h"
+/**
+ * Dumping compiled mruby script.
+ */
+MRB_BEGIN_DECL
#define DUMP_DEBUG_INFO 1
#define DUMP_ENDIAN_BIG 2
@@ -21,7 +23,7 @@ extern "C" {
#define DUMP_ENDIAN_MASK 6
int mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size);
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
int mrb_dump_irep_binary(mrb_state*, mrb_irep*, uint8_t, FILE*);
int mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep*, uint8_t flags, FILE *f, const char *initname);
mrb_irep *mrb_read_irep_file(mrb_state*, FILE*);
@@ -185,11 +187,9 @@ bin_to_uint8(const uint8_t *bin)
return (uint8_t)bin[0];
}
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
+MRB_END_DECL
-/* crc.c */
+/** @internal crc.c */
uint16_t
calc_crc_16_ccitt(const uint8_t *src, size_t nbytes, uint16_t crc);
diff --git a/include/mruby/error.h b/include/mruby/error.h
index e3e2b25e2..714886160 100644
--- a/include/mruby/error.h
+++ b/include/mruby/error.h
@@ -7,9 +7,12 @@
#ifndef MRUBY_ERROR_H
#define MRUBY_ERROR_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <mruby/common.h>
+
+/**
+ * MRuby error handling.
+ */
+MRB_BEGIN_DECL
struct RException {
MRB_OBJECT_HEADER;
@@ -29,18 +32,38 @@ MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_va
/* declaration for fail method */
MRB_API mrb_value mrb_f_raise(mrb_state*, mrb_value);
-/* functions defined in mruby-error mrbgem */
+/**
+ * Protect
+ *
+ * @mrbgem mruby-error
+ */
MRB_API mrb_value mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state);
+
+/**
+ * Ensure
+ *
+ * @mrbgem mruby-error
+ */
MRB_API mrb_value mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
mrb_func_t ensure, mrb_value e_data);
+
+/**
+ * Rescue
+ *
+ * @mrbgem mruby-error
+ */
MRB_API mrb_value mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
mrb_func_t rescue, mrb_value r_data);
+
+/**
+ * Rescue exception
+ *
+ * @mrbgem mruby-error
+ */
MRB_API mrb_value mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
mrb_func_t rescue, mrb_value r_data,
mrb_int len, struct RClass **classes);
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
+MRB_END_DECL
#endif /* MRUBY_ERROR_H */
diff --git a/include/mruby/gc.h b/include/mruby/gc.h
index ebc57d2aa..f988f1300 100644
--- a/include/mruby/gc.h
+++ b/include/mruby/gc.h
@@ -7,16 +7,71 @@
#ifndef MRUBY_GC_H
#define MRUBY_GC_H
-#if defined(__cplusplus)
-extern "C" {
+#include <mruby/common.h>
+
+/**
+ * Uncommon memory management stuffs.
+ */
+MRB_BEGIN_DECL
+
+
+struct mrb_state;
+
+typedef void (mrb_each_object_callback)(struct mrb_state *mrb, struct RBasic *obj, void *data);
+void mrb_objspace_each_objects(struct mrb_state *mrb, mrb_each_object_callback *callback, void *data);
+MRB_API void mrb_free_context(struct mrb_state *mrb, struct mrb_context *c);
+
+#ifndef MRB_GC_ARENA_SIZE
+#define MRB_GC_ARENA_SIZE 100
#endif
-typedef void (mrb_each_object_callback)(mrb_state *mrb, struct RBasic *obj, void *data);
-void mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, void *data);
-MRB_API void mrb_free_context(mrb_state *mrb, struct mrb_context *c);
+typedef enum {
+ MRB_GC_STATE_ROOT = 0,
+ MRB_GC_STATE_MARK,
+ MRB_GC_STATE_SWEEP
+} mrb_gc_state;
-#if defined(__cplusplus)
-} /* extern "C" { */
+typedef struct mrb_heap_page {
+ struct RBasic *freelist;
+ struct mrb_heap_page *prev;
+ struct mrb_heap_page *next;
+ struct mrb_heap_page *free_next;
+ struct mrb_heap_page *free_prev;
+ mrb_bool old:1;
+ void *objects[];
+} mrb_heap_page;
+
+typedef struct mrb_gc {
+ mrb_heap_page *heaps; /* heaps for GC */
+ mrb_heap_page *sweeps;
+ mrb_heap_page *free_heaps;
+ size_t live; /* count of live objects */
+#ifdef MRB_GC_FIXED_ARENA
+ struct RBasic *arena[MRB_GC_ARENA_SIZE]; /* GC protection array */
+#else
+ struct RBasic **arena; /* GC protection array */
+ int arena_capa;
#endif
+ int arena_idx;
+
+ mrb_gc_state state; /* state of gc */
+ int current_white_part; /* make white object by white_part */
+ struct RBasic *gray_list; /* list of gray objects to be traversed incrementally */
+ struct RBasic *atomic_gray_list; /* list of objects to be traversed atomically */
+ size_t live_after_mark;
+ size_t threshold;
+ int interval_ratio;
+ int step_ratio;
+ mrb_bool disabled :1;
+ mrb_bool full :1;
+ mrb_bool generational :1;
+ mrb_bool out_of_memory :1;
+ size_t majorgc_old_threshold;
+} mrb_gc;
+
+MRB_API mrb_bool
+mrb_object_dead_p(struct mrb_state *mrb, struct RBasic *object);
+
+MRB_END_DECL
#endif /* MRUBY_GC_H */
diff --git a/include/mruby/hash.h b/include/mruby/hash.h
index 5339312c6..db064793a 100644
--- a/include/mruby/hash.h
+++ b/include/mruby/hash.h
@@ -7,9 +7,12 @@
#ifndef MRUBY_HASH_H
#define MRUBY_HASH_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <mruby/common.h>
+
+/**
+ * Hash class
+ */
+MRB_BEGIN_DECL
struct RHash {
MRB_OBJECT_HEADER;
@@ -21,15 +24,39 @@ struct RHash {
#define mrb_hash_value(p) mrb_obj_value((void*)(p))
MRB_API mrb_value mrb_hash_new_capa(mrb_state*, int);
+
+/*
+ * Initializes a new hash.
+ */
MRB_API mrb_value mrb_hash_new(mrb_state *mrb);
+/*
+ * Sets a keys and values to hashes.
+ */
MRB_API void mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val);
+
+/*
+ * Gets a value from a key.
+ */
MRB_API mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key);
+
MRB_API mrb_value mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def);
+
+/*
+ * Deletes hash key and value pair.
+ */
MRB_API mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key);
+
+/*
+ * Gets an array of keys.
+ */
MRB_API mrb_value mrb_hash_keys(mrb_state *mrb, mrb_value hash);
MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
MRB_API mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self);
+
+/*
+ * Clears the hash.
+ */
MRB_API mrb_value mrb_hash_clear(mrb_state *mrb, mrb_value hash);
/* RHASH_TBL allocates st_table if not available. */
@@ -47,8 +74,6 @@ void mrb_gc_mark_hash(mrb_state*, struct RHash*);
size_t mrb_gc_mark_hash_size(mrb_state*, struct RHash*);
void mrb_gc_free_hash(mrb_state*, struct RHash*);
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
+MRB_END_DECL
#endif /* MRUBY_HASH_H */
diff --git a/include/mruby/irep.h b/include/mruby/irep.h
index f4061bb54..234d6bf46 100644
--- a/include/mruby/irep.h
+++ b/include/mruby/irep.h
@@ -7,11 +7,13 @@
#ifndef MRUBY_IREP_H
#define MRUBY_IREP_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <mruby/common.h>
+#include <mruby/compile.h>
-#include "mruby/compile.h"
+/**
+ * Compiled mruby scripts.
+ */
+MRB_BEGIN_DECL
enum irep_pool_type {
IREP_TT_STRING,
@@ -53,8 +55,6 @@ void mrb_irep_free(mrb_state*, struct mrb_irep*);
void mrb_irep_incref(mrb_state*, struct mrb_irep*);
void mrb_irep_decref(mrb_state*, struct mrb_irep*);
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
+MRB_END_DECL
#endif /* MRUBY_IREP_H */
diff --git a/include/mruby/khash.h b/include/mruby/khash.h
index 6a4861bda..d09e0792f 100644
--- a/include/mruby/khash.h
+++ b/include/mruby/khash.h
@@ -7,13 +7,16 @@
#ifndef MRUBY_KHASH_H
#define MRUBY_KHASH_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#include "mruby.h"
#include <string.h>
+#include <mruby.h>
+#include <mruby/common.h>
+
+/**
+ * khash definitions used in mruby's hash table.
+ */
+MRB_BEGIN_DECL
+
typedef uint32_t khint_t;
typedef khint_t khiter_t;
@@ -266,8 +269,6 @@ static inline khint_t __ac_X31_hash_string(const char *s)
typedef const char *kh_cstr_t;
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
+MRB_END_DECL
#endif /* MRUBY_KHASH_H */
diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h
index 237119bf2..6e2f0c2da 100644
--- a/include/mruby/numeric.h
+++ b/include/mruby/numeric.h
@@ -7,9 +7,14 @@
#ifndef MRUBY_NUMERIC_H
#define MRUBY_NUMERIC_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <mruby/common.h>
+
+/**
+ * Numeric class and it's sub-classes.
+ *
+ * Integer, Float and Fixnum
+ */
+MRB_BEGIN_DECL
#define POSFIXABLE(f) ((f) <= MRB_INT_MAX)
#define NEGFIXABLE(f) ((f) >= MRB_INT_MIN)
@@ -30,11 +35,7 @@ mrb_value mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y);
#define MRB_UINT_MAKE(n) MRB_UINT_MAKE2(n)
#define mrb_uint MRB_UINT_MAKE(MRB_INT_BIT)
-#ifdef MRB_WORD_BOXING
-# define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1 - MRB_FIXNUM_SHIFT))
-#else
-# define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1))
-#endif
+#define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1 - MRB_FIXNUM_SHIFT))
/* Idea from Potion: https://github.com/perl11/potion (MIT) */
#if (defined(__clang__) && ((__clang_major__ > 3) || (__clang_major__ == 3 && __clang_minor__ >= 4))) \
@@ -104,8 +105,6 @@ mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference)
#undef MRB_UINT_MAKE
#undef MRB_UINT_MAKE2
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
+MRB_END_DECL
#endif /* MRUBY_NUMERIC_H */
diff --git a/include/mruby/object.h b/include/mruby/object.h
index 6633a23e8..9fbfe34f3 100644
--- a/include/mruby/object.h
+++ b/include/mruby/object.h
@@ -16,24 +16,6 @@
#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
-#define MRB_GC_WHITE_B (1 << 1)
-#define MRB_GC_BLACK (1 << 2)
-#define MRB_GC_WHITES (MRB_GC_WHITE_A | MRB_GC_WHITE_B)
-#define MRB_GC_COLOR_MASK 7
-
-#define paint_gray(o) ((o)->color = MRB_GC_GRAY)
-#define paint_black(o) ((o)->color = MRB_GC_BLACK)
-#define paint_white(o) ((o)->color = MRB_GC_WHITES)
-#define paint_partial_white(s, o) ((o)->color = (s)->current_white_part)
-#define is_gray(o) ((o)->color == MRB_GC_GRAY)
-#define is_white(o) ((o)->color & MRB_GC_WHITES)
-#define is_black(o) ((o)->color & MRB_GC_BLACK)
-#define is_dead(s, o) (((o)->color & other_white_part(s) & MRB_GC_WHITES) || (o)->tt == MRB_TT_FREE)
-#define flip_white_part(s) ((s)->current_white_part = other_white_part(s))
-#define other_white_part(s) ((s)->current_white_part ^ MRB_GC_WHITES)
struct RBasic {
MRB_OBJECT_HEADER;
diff --git a/include/mruby/proc.h b/include/mruby/proc.h
index 5441cf767..035f94be4 100644
--- a/include/mruby/proc.h
+++ b/include/mruby/proc.h
@@ -7,11 +7,13 @@
#ifndef MRUBY_PROC_H
#define MRUBY_PROC_H
-#include "mruby/irep.h"
+#include <mruby/common.h>
+#include <mruby/irep.h>
-#if defined(__cplusplus)
-extern "C" {
-#endif
+/**
+ * Proc class
+ */
+MRB_BEGIN_DECL
struct REnv {
MRB_OBJECT_HEADER;
@@ -66,11 +68,9 @@ MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state*, mrb_int);
/* old name */
#define mrb_cfunc_env_get(mrb, idx) mrb_proc_cfunc_env_get(mrb, idx)
-#include "mruby/khash.h"
+#include <mruby/khash.h>
KHASH_DECLARE(mt, mrb_sym, struct RProc*, TRUE)
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
+MRB_END_DECL
#endif /* MRUBY_PROC_H */
diff --git a/include/mruby/range.h b/include/mruby/range.h
index 079ed3bf4..37271ac3d 100644
--- a/include/mruby/range.h
+++ b/include/mruby/range.h
@@ -7,9 +7,12 @@
#ifndef MRUBY_RANGE_H
#define MRUBY_RANGE_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <mruby/common.h>
+
+/**
+ * Range class
+ */
+MRB_BEGIN_DECL
typedef struct mrb_range_edges {
mrb_value beg;
@@ -25,12 +28,21 @@ struct RRange {
#define mrb_range_ptr(v) ((struct RRange*)(mrb_ptr(v)))
#define mrb_range_value(p) mrb_obj_value((void*)(p))
-MRB_API mrb_value mrb_range_new(mrb_state*, mrb_value, mrb_value, mrb_bool);
+/*
+ * Initializes a Range.
+ *
+ * If the third parameter is FALSE then it includes the last value in the range.
+ * If the third parameter is TRUE then it excludes the last value in the range.
+ *
+ * @param start the beginning value.
+ * @param end the ending value.
+ * @param exclude represents the inclusion or exclusion of the last value.
+ */
+MRB_API mrb_value mrb_range_new(mrb_state *mrb, mrb_value start, mrb_value end, mrb_bool exclude);
+
MRB_API mrb_bool mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len);
mrb_value mrb_get_values_at(mrb_state *mrb, mrb_value obj, mrb_int olen, mrb_int argc, const mrb_value *argv, mrb_value (*func)(mrb_state*, mrb_value, mrb_int));
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
+MRB_END_DECL
#endif /* MRUBY_RANGE_H */
diff --git a/include/mruby/string.h b/include/mruby/string.h
index c4b31216e..9ad566516 100644
--- a/include/mruby/string.h
+++ b/include/mruby/string.h
@@ -7,9 +7,12 @@
#ifndef MRUBY_STRING_H
#define MRUBY_STRING_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <mruby/common.h>
+
+/**
+ * String class
+ */
+MRB_BEGIN_DECL
extern const char mrb_digitmap[];
@@ -63,11 +66,14 @@ struct RString {
#define RSTR_SET_FROZEN_FLAG(s) ((s)->flags |= MRB_STR_FROZEN)
#define RSTR_UNSET_FROZEN_FLAG(s) ((s)->flags &= ~MRB_STR_FROZEN)
+/*
+ * Returns a pointer from a Ruby string
+ */
#define mrb_str_ptr(s) ((struct RString*)(mrb_ptr(s)))
#define RSTRING(s) mrb_str_ptr(s)
#define RSTRING_PTR(s) RSTR_PTR(RSTRING(s))
#define RSTRING_EMBED_LEN(s) RSTR_ENBED_LEN(RSTRING(s))
-#define RSTRING_LEN(s) RSTR_LEN(RSTRING(s))
+#define RSTRING_LEN(s) RSTR_LEN(RSTRING(s))
#define RSTRING_CAPA(s) RSTR_CAPA(RSTRING(s))
#define RSTRING_END(s) (RSTRING_PTR(s) + RSTRING_LEN(s))
mrb_int mrb_str_strlen(mrb_state*, struct RString*);
@@ -82,34 +88,116 @@ mrb_int mrb_str_strlen(mrb_state*, struct RString*);
void mrb_gc_free_str(mrb_state*, struct RString*);
MRB_API void mrb_str_modify(mrb_state*, struct RString*);
MRB_API void mrb_str_concat(mrb_state*, mrb_value, mrb_value);
+
+/*
+ * Adds two strings together.
+ */
MRB_API mrb_value mrb_str_plus(mrb_state*, mrb_value, mrb_value);
+
+/*
+ * Converts pointer into a Ruby string.
+ */
MRB_API mrb_value mrb_ptr_to_str(mrb_state *, void*);
+
+/*
+ * Returns an object as a Ruby string.
+ */
MRB_API mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj);
+
+/*
+ * Resizes the string's length.
+ */
MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len);
+
+/*
+ * Returns a sub string.
+ */
MRB_API mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
+
+/*
+ * Returns a Ruby string type.
+ */
MRB_API mrb_value mrb_string_type(mrb_state *mrb, mrb_value str);
+
MRB_API mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str);
MRB_API mrb_value mrb_str_buf_new(mrb_state *mrb, size_t capa);
MRB_API const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr);
MRB_API const char *mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr);
+
+/*
+ * Duplicates a string object.
+ */
MRB_API mrb_value mrb_str_dup(mrb_state *mrb, mrb_value str);
+
+/*
+ * Returns a symbol from a passed in string.
+ */
MRB_API mrb_value mrb_str_intern(mrb_state *mrb, mrb_value self);
+
MRB_API mrb_value mrb_str_to_inum(mrb_state *mrb, mrb_value str, mrb_int base, mrb_bool badcheck);
MRB_API double mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck);
+
+/*
+ * Returns a converted string type.
+ */
MRB_API mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str);
+
+/*
+ * Returns true if the strings match and false if the strings don't match.
+ */
MRB_API mrb_bool mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2);
+
+/*
+ * Returns a concated string comprised of a Ruby string and a C string.
+ *
+ * @see mrb_str_cat_cstr
+ */
MRB_API mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len);
+
+/*
+ * Returns a concated string comprised of a Ruby string and a C string.
+ *
+ * @see mrb_str_cat
+ */
MRB_API mrb_value mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr);
MRB_API mrb_value mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2);
#define mrb_str_cat_lit(mrb, str, lit) mrb_str_cat(mrb, str, lit, mrb_strlen_lit(lit))
+
+/*
+ * Adds str2 to the end of str1.
+ */
MRB_API mrb_value mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2);
+/*
+ * Returns 0 if both Ruby strings are equal. Returns a value < 0 if Ruby str1 is less than Ruby str2. Returns a value > 0 if Ruby str2 is greater than Ruby str1.
+ */
MRB_API int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2);
+
+/*
+ * Returns a newly allocated C string from a Ruby string.
+ * This is an utility function to pass a Ruby string to C library functions.
+ *
+ * - Returned string does not contain any NUL characters (but terminator).
+ * - It raises an ArgumentError exception if Ruby string contains
+ * NUL characters.
+ * - Retured string will be freed automatically on next GC.
+ * - Caller can modify returned string without affecting Ruby string
+ * (e.g. it can be used for mkstemp(3)).
+ *
+ * @param [mrb_state *] mrb The current mruby state.
+ * @param [mrb_value] str Ruby string. Must be an instance of String.
+ * @return [char *] A newly allocated C string.
+ */
MRB_API char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str);
+
mrb_value mrb_str_pool(mrb_state *mrb, mrb_value str);
mrb_int mrb_str_hash(mrb_state *mrb, mrb_value str);
mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str);
+
+/*
+ * Returns a printable version of str, surrounded by quote marks, with special characters escaped.
+ */
mrb_value mrb_str_inspect(mrb_state *mrb, mrb_value str);
void mrb_noregexp(mrb_state *mrb, mrb_value self);
@@ -120,8 +208,6 @@ void mrb_regexp_check(mrb_state *mrb, mrb_value obj);
#define mrb_str_buf_cat(mrb, str, ptr, len) mrb_str_cat(mrb, str, ptr, len)
#define mrb_str_buf_append(mrb, str, str2) mrb_str_cat_str(mrb, str, str2)
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
+MRB_END_DECL
#endif /* MRUBY_STRING_H */
diff --git a/include/mruby/value.h b/include/mruby/value.h
index 9fff3f616..d31729b3c 100644
--- a/include/mruby/value.h
+++ b/include/mruby/value.h
@@ -7,6 +7,13 @@
#ifndef MRUBY_VALUE_H
#define MRUBY_VALUE_H
+#include <mruby/common.h>
+
+/**
+ * MRuby Value definition functions and macros.
+ */
+MRB_BEGIN_DECL
+
typedef uint32_t mrb_sym;
typedef uint8_t mrb_bool;
struct mrb_state;
@@ -89,7 +96,23 @@ enum mrb_vtype {
MRB_TT_MAXDEFINE /* 23 */
};
-#include "mruby/object.h"
+#include <mruby/object.h>
+
+#ifdef MRB_DOCUMENTATION_BLOCK
+
+/**
+ * @abstract
+ * MRuby value boxing.
+ *
+ * Actual implementation depends on configured boxing type.
+ *
+ * @see mruby/boxing_no.h Default boxing representation
+ * @see mruby/boxing_word.h Word representation
+ * @see mruby/boxing_nan.h Boxed double representation
+ */
+typedef void mrb_value;
+
+#endif
#if defined(MRB_NAN_BOXING)
#include "boxing_nan.h"
@@ -121,8 +144,10 @@ enum mrb_vtype {
#define mrb_test(o) mrb_bool(o)
MRB_API mrb_bool mrb_regexp_p(struct mrb_state*, mrb_value);
-static inline mrb_value
-mrb_float_value(struct mrb_state *mrb, mrb_float f)
+/*
+ * Returns a float in Ruby.
+ */
+MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f)
{
mrb_value v;
(void) mrb;
@@ -139,8 +164,10 @@ mrb_cptr_value(struct mrb_state *mrb, void *p)
return v;
}
-static inline mrb_value
-mrb_fixnum_value(mrb_int i)
+/*
+ * Returns a fixnum in Ruby.
+ */
+MRB_INLINE mrb_value mrb_fixnum_value(mrb_int i)
{
mrb_value v;
SET_INT_VALUE(v, i);
@@ -163,24 +190,34 @@ mrb_obj_value(void *p)
return v;
}
-static inline mrb_value
-mrb_nil_value(void)
+
+/*
+ * Get a nil mrb_value object.
+ *
+ * @return
+ * nil mrb_value object reference.
+ */
+MRB_INLINE mrb_value mrb_nil_value(void)
{
mrb_value v;
SET_NIL_VALUE(v);
return v;
}
-static inline mrb_value
-mrb_false_value(void)
+/*
+ * Returns false in Ruby.
+ */
+MRB_INLINE mrb_value mrb_false_value(void)
{
mrb_value v;
SET_FALSE_VALUE(v);
return v;
}
-static inline mrb_value
-mrb_true_value(void)
+/*
+ * Returns true in Ruby.
+ */
+MRB_INLINE mrb_value mrb_true_value(void)
{
mrb_value v;
SET_TRUE_VALUE(v);
@@ -226,4 +263,6 @@ mrb_ro_data_p(const char *p)
# define mrb_ro_data_p(p) FALSE
#endif
+MRB_END_DECL
+
#endif /* MRUBY_VALUE_H */
diff --git a/include/mruby/variable.h b/include/mruby/variable.h
index 7785a8ce2..46a599a40 100644
--- a/include/mruby/variable.h
+++ b/include/mruby/variable.h
@@ -7,9 +7,12 @@
#ifndef MRUBY_VARIABLE_H
#define MRUBY_VARIABLE_H
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <mruby/common.h>
+
+/**
+ * Functions to access mruby variables.
+ */
+MRB_BEGIN_DECL
typedef struct global_variable {
int counter;
@@ -74,8 +77,6 @@ void mrb_gc_mark_iv(mrb_state*, struct RObject*);
size_t mrb_gc_mark_iv_size(mrb_state*, struct RObject*);
void mrb_gc_free_iv(mrb_state*, struct RObject*);
-#if defined(__cplusplus)
-} /* extern "C" { */
-#endif
+MRB_END_DECL
#endif /* MRUBY_VARIABLE_H */
diff --git a/include/mruby/version.h b/include/mruby/version.h
index c2a9b6306..c22672b36 100644
--- a/include/mruby/version.h
+++ b/include/mruby/version.h
@@ -7,36 +7,104 @@
#ifndef MRUBY_VERSION_H
#define MRUBY_VERSION_H
+#include <mruby/common.h>
+
+/**
+ * mruby version definition macros
+ */
+MRB_BEGIN_DECL
+
+/*
+ * A passed in expression.
+ */
#define MRB_STRINGIZE0(expr) #expr
+
+/*
+ * Passes in an expression to MRB_STRINGIZE0.
+ */
#define MRB_STRINGIZE(expr) MRB_STRINGIZE0(expr)
+/*
+ * The version of Ruby used by mruby.
+ */
#define MRUBY_RUBY_VERSION "1.9"
+
+/*
+ * Ruby engine.
+ */
#define MRUBY_RUBY_ENGINE "mruby"
+/*
+ * Major release version number.
+ */
#define MRUBY_RELEASE_MAJOR 1
-#define MRUBY_RELEASE_MINOR 1
-#define MRUBY_RELEASE_TEENY 1
+/*
+ * Minor release version number.
+ */
+#define MRUBY_RELEASE_MINOR 2
+
+/*
+ * Tiny release version number.
+ */
+#define MRUBY_RELEASE_TEENY 0
+
+/*
+ * The mruby version.
+ */
#define MRUBY_VERSION MRB_STRINGIZE(MRUBY_RELEASE_MAJOR) "." MRB_STRINGIZE(MRUBY_RELEASE_MINOR) "." MRB_STRINGIZE(MRUBY_RELEASE_TEENY)
+
+/*
+ * Release number.
+ */
#define MRUBY_RELEASE_NO (MRUBY_RELEASE_MAJOR * 100 * 100 + MRUBY_RELEASE_MINOR * 100 + MRUBY_RELEASE_TEENY)
-#define MRUBY_RELEASE_YEAR 2014
+
+/*
+ * Release year.
+ */
+#define MRUBY_RELEASE_YEAR 2015
+
+/*
+ * Release month.
+ */
#define MRUBY_RELEASE_MONTH 11
-#define MRUBY_RELEASE_DAY 19
+
+/*
+ * Release day.
+ */
+#define MRUBY_RELEASE_DAY 17
+
+/*
+ * Release date as a string.
+ */
#define MRUBY_RELEASE_DATE MRB_STRINGIZE(MRUBY_RELEASE_YEAR) "-" MRB_STRINGIZE(MRUBY_RELEASE_MONTH) "-" MRB_STRINGIZE(MRUBY_RELEASE_DAY)
+/*
+ * The year mruby was first created.
+ */
#define MRUBY_BIRTH_YEAR 2010
+/*
+ * MRuby's authors.
+ */
#define MRUBY_AUTHOR "mruby developers"
-
+/*
+ * mruby's version, and release date.
+ */
#define MRUBY_DESCRIPTION \
"mruby " MRUBY_VERSION \
" (" MRUBY_RELEASE_DATE ") " \
+/*
+ * mruby's copyright information.
+ */
#define MRUBY_COPYRIGHT \
"mruby - Copyright (c) " \
MRB_STRINGIZE(MRUBY_BIRTH_YEAR)"-" \
MRB_STRINGIZE(MRUBY_RELEASE_YEAR)" " \
MRUBY_AUTHOR \
+MRB_END_DECL
+
#endif /* MRUBY_VERSION_H */
diff --git a/lib/mruby/source.rb b/lib/mruby/source.rb
new file mode 100644
index 000000000..5819a322b
--- /dev/null
+++ b/lib/mruby/source.rb
@@ -0,0 +1,30 @@
+require "pathname"
+
+module MRuby
+ module Source
+ # MRuby's source root directory
+ ROOT = Pathname.new(File.expand_path('../../../',__FILE__))
+
+ # Reads a constant defined at version.h
+ MRUBY_READ_VERSION_CONSTANT = Proc.new { |name| ROOT.join('include','mruby','version.h').read.match(/^#define #{name} +"?([\w\. ]+)"?$/)[1] }
+
+ MRUBY_RUBY_VERSION = MRUBY_READ_VERSION_CONSTANT['MRUBY_RUBY_VERSION']
+ MRUBY_RUBY_ENGINE = MRUBY_READ_VERSION_CONSTANT['MRUBY_RUBY_ENGINE']
+
+ MRUBY_RELEASE_MAJOR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_MAJOR'])
+ MRUBY_RELEASE_MINOR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_MINOR'])
+ MRUBY_RELEASE_TEENY = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_TEENY'])
+
+ MRUBY_VERSION = [MRUBY_RELEASE_MAJOR,MRUBY_RELEASE_MINOR,MRUBY_RELEASE_TEENY].join('.')
+ MRUBY_RELEASE_NO = (MRUBY_RELEASE_MAJOR * 100 * 100 + MRUBY_RELEASE_MINOR * 100 + MRUBY_RELEASE_TEENY)
+
+ MRUBY_RELEASE_YEAR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_YEAR'])
+ MRUBY_RELEASE_MONTH = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_MONTH'])
+ MRUBY_RELEASE_DAY = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_DAY'])
+ MRUBY_RELEASE_DATE = [MRUBY_RELEASE_YEAR,MRUBY_RELEASE_MONTH,MRUBY_RELEASE_DAY].join('.')
+
+ MRUBY_BIRTH_YEAR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_BIRTH_YEAR'])
+
+ MRUBY_AUTHOR = MRUBY_READ_VERSION_CONSTANT['MRUBY_AUTHOR']
+ end
+end
diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb
index 1f1d97376..f19581cdc 100644
--- a/mrbgems/mruby-array-ext/mrblib/array.rb
+++ b/mrbgems/mruby-array-ext/mrblib/array.rb
@@ -1,6 +1,31 @@
class Array
##
# call-seq:
+ # Array.try_convert(obj) -> array or nil
+ #
+ # Tries to convert +obj+ into an array, using +to_ary+ method.
+ # converted array or +nil+ if +obj+ cannot be converted for any reason.
+ # This method can be used to check if an argument is an array.
+ #
+ # Array.try_convert([1]) #=> [1]
+ # Array.try_convert("1") #=> nil
+ #
+ # if tmp = Array.try_convert(arg)
+ # # the argument is an array
+ # elsif tmp = String.try_convert(arg)
+ # # the argument is a string
+ # end
+ #
+ def self.try_convert(obj)
+ if obj.respond_to?(:to_ary)
+ obj.to_ary
+ else
+ nil
+ end
+ end
+
+ ##
+ # call-seq:
# ary.uniq! -> ary or nil
# ary.uniq! { |item| ... } -> ary or nil
#
@@ -681,4 +706,42 @@ class Array
return nil if self.size == result.size
self.replace(result)
end
+
+ ##
+ # call-seq:
+ # ary.index(val) -> int or nil
+ # ary.index {|item| block } -> int or nil
+ #
+ # Returns the _index_ of the first object in +ary+ such that the object is
+ # <code>==</code> to +obj+.
+ #
+ # If a block is given instead of an argument, returns the _index_ of the
+ # first object for which the block returns +true+. Returns +nil+ if no
+ # match is found.
+ #
+ # ISO 15.2.12.5.14
+ def index(val=NONE, &block)
+ return to_enum(:find_index, val) if !block && val == NONE
+
+ if block
+ idx = 0
+ self.each do |*e|
+ return idx if block.call(*e)
+ idx += 1
+ end
+ else
+ return self.__ary_index(val)
+ end
+ nil
+ end
+
+ ##
+ # call-seq:
+ # ary.to_ary -> ary
+ #
+ # Returns +self+.
+ #
+ def to_ary
+ self
+ end
end
diff --git a/mrbgems/mruby-array-ext/src/array.c b/mrbgems/mruby-array-ext/src/array.c
index d69f0ac44..d5c96e2cc 100644
--- a/mrbgems/mruby-array-ext/src/array.c
+++ b/mrbgems/mruby-array-ext/src/array.c
@@ -1,8 +1,8 @@
-#include "mruby.h"
-#include "mruby/value.h"
-#include "mruby/array.h"
-#include "mruby/range.h"
-#include "mruby/hash.h"
+#include <mruby.h>
+#include <mruby/value.h>
+#include <mruby/array.h>
+#include <mruby/range.h>
+#include <mruby/hash.h>
/*
* call-seq:
@@ -113,8 +113,9 @@ mrb_ary_values_at(mrb_state *mrb, mrb_value self)
* Returns the result of interpreting <i>aray</i> as an array of
* <tt>[key, value]</tt> paris.
*
- * [[:foo, :bar], [1, 2]].to_h
- * # => {:foo => :bar, 1 => 2}
+ * [[:foo, :bar], [1, 2]].to_h
+ * # => {:foo => :bar, 1 => 2}
+ *
*/
static mrb_value
diff --git a/mrbgems/mruby-array-ext/test/array.rb b/mrbgems/mruby-array-ext/test/array.rb
index 8c919f7e0..f17cb80e1 100644
--- a/mrbgems/mruby-array-ext/test/array.rb
+++ b/mrbgems/mruby-array-ext/test/array.rb
@@ -1,6 +1,13 @@
##
# Array(Ext) Test
+assert("Array.try_convert") do
+ assert_nil Array.try_convert(0)
+ assert_nil Array.try_convert(nil)
+ assert_equal [], Array.try_convert([])
+ assert_equal [1,2,3], Array.try_convert([1,2,3])
+end
+
assert("Array#assoc") do
s1 = [ "colors", "red", "blue", "green" ]
s2 = [ "letters", "a", "b", "c" ]
@@ -293,3 +300,13 @@ assert('Array#to_h') do
assert_raise(TypeError) { [1].to_h }
assert_raise(ArgumentError) { [[1]].to_h }
end
+
+assert("Array#index (block)") do
+ assert_nil (1..10).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
+ assert_equal 34, (1..100).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
+end
+
+assert("Array#to_ary") do
+ assert_equal [], [].to_ary
+ assert_equal [1,2,3], [1,2,3].to_ary
+end
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c b/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
index 378c773ea..986c69d82 100755
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
@@ -4,14 +4,14 @@
*/
#include <string.h>
-#include "mruby.h"
-#include "mruby/irep.h"
+#include <mruby.h>
+#include <mruby/irep.h>
#include "mrdb.h"
-#include "mruby/debug.h"
-#include "mruby/opcode.h"
-#include "mruby/class.h"
-#include "mruby/proc.h"
-#include "mruby/variable.h"
+#include <mruby/debug.h>
+#include <mruby/opcode.h>
+#include <mruby/class.h>
+#include <mruby/proc.h>
+#include <mruby/variable.h>
#include "mrdberror.h"
#include "apibreak.h"
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h b/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h
index 8bb39cb50..3c7e41e52 100755
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h
@@ -6,7 +6,7 @@
#ifndef APIBREAK_H_
#define APIBREAK_H_
-#include "mruby.h"
+#include <mruby.h>
#include "mrdb.h"
int32_t mrb_debug_set_break_line( mrb_state *, mrb_debug_context *, const char *, uint16_t );
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c b/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c
index 03846cd50..1c77d1ef8 100755
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c
@@ -9,9 +9,9 @@
#include "mrdb.h"
#include "mrdberror.h"
#include "apilist.h"
-#include "mruby/compile.h"
-#include "mruby/irep.h"
-#include "mruby/debug.h"
+#include <mruby/compile.h>
+#include <mruby/irep.h>
+#include <mruby/debug.h>
#define LINE_BUF_SIZE MAX_COMMAND_LINE
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h b/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h
index 4580b2350..6c4107885 100755
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h
@@ -5,7 +5,7 @@
#ifndef APILIST_H_
#define APILIST_H_
-#include "mruby.h"
+#include <mruby.h>
#include "mrdb.h"
int32_t mrb_debug_list(mrb_state *, mrb_debug_context *, char *, uint16_t, uint16_t);
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c b/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c
index 2c93eb4ee..a9c895b55 100755
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c
@@ -5,12 +5,12 @@
#include <string.h>
#include "mrdb.h"
-#include "mruby/value.h"
-#include "mruby/class.h"
-#include "mruby/compile.h"
-#include "mruby/error.h"
-#include "mruby/numeric.h"
-#include "mruby/string.h"
+#include <mruby/value.h>
+#include <mruby/class.h>
+#include <mruby/compile.h>
+#include <mruby/error.h>
+#include <mruby/numeric.h>
+#include <mruby/string.h>
#include "apiprint.h"
static void
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h b/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h
index 81d685e0c..e256f6262 100755
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h
@@ -5,7 +5,7 @@
#ifndef APIPRINT_H_
#define APIPRINT_H_
-#include "mruby.h"
+#include <mruby.h>
#include "mrdb.h"
mrb_value mrb_debug_eval(mrb_state*, mrb_debug_context*, const char*, size_t, mrb_bool*);
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c b/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c
index b913915c3..57c1d5682 100755
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c
@@ -5,10 +5,10 @@
#include <ctype.h>
#include <string.h>
-#include "mruby.h"
-#include "mruby/dump.h"
-#include "mruby/debug.h"
-#include "mruby/string.h"
+#include <mruby.h>
+#include <mruby/dump.h>
+#include <mruby/debug.h>
+#include <mruby/string.h>
#include "mrdb.h"
#include "mrdberror.h"
#include "apibreak.h"
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c b/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c
index f52514851..b4aeb62d4 100755
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c
@@ -8,7 +8,7 @@
#include <string.h>
#include "apilist.h"
-#include "mruby/compile.h"
+#include <mruby/compile.h>
typedef struct help_msg {
const char *cmd1;
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c b/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c
index a617aff13..cca636711 100755
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c
@@ -5,12 +5,12 @@
#include <string.h>
#include "mrdb.h"
-#include "mruby/value.h"
-#include "mruby/class.h"
-#include "mruby/compile.h"
-#include "mruby/error.h"
-#include "mruby/numeric.h"
-#include "mruby/string.h"
+#include <mruby/value.h>
+#include <mruby/class.h>
+#include <mruby/compile.h>
+#include <mruby/error.h>
+#include <mruby/numeric.h>
+#include <mruby/string.h>
#include "apiprint.h"
dbgcmd_state
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c b/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c
index 8d8340560..7e0f171e4 100755
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c
@@ -3,7 +3,7 @@
**
*/
-#include "mruby/opcode.h"
+#include <mruby/opcode.h>
#include "mrdb.h"
dbgcmd_state
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c b/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c
index 3e43fdb4a..317547d86 100755
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c
@@ -8,12 +8,12 @@
#include <stdio.h>
#include <ctype.h>
-#include "mruby.h"
-#include "mruby/dump.h"
-#include "mruby/debug.h"
-#include "mruby/class.h"
-#include "mruby/opcode.h"
-#include "mruby/variable.h"
+#include <mruby.h>
+#include <mruby/dump.h>
+#include <mruby/debug.h>
+#include <mruby/class.h>
+#include <mruby/opcode.h>
+#include <mruby/variable.h>
#include "mrdb.h"
#include "apibreak.h"
diff --git a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h b/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h
index 9e92ce879..5d897170a 100755
--- a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h
+++ b/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h
@@ -6,7 +6,7 @@
#ifndef MRDB_H
#define MRDB_H
-#include "mruby.h"
+#include <mruby.h>
#include "mrdbconf.h"
diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c
index 481d5ca43..8fe7634de 100644
--- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c
+++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c
@@ -29,11 +29,11 @@
#define MIRB_USING_HISTORY()
#endif
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/proc.h"
-#include "mruby/compile.h"
-#include "mruby/string.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/proc.h>
+#include <mruby/compile.h>
+#include <mruby/string.h>
#ifdef ENABLE_READLINE
diff --git a/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c b/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c
index 2f507904a..580c2e25b 100644
--- a/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c
+++ b/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c
@@ -1,10 +1,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "mruby.h"
-#include "mruby/compile.h"
-#include "mruby/dump.h"
-#include "mruby/proc.h"
+#include <mruby.h>
+#include <mruby/compile.h>
+#include <mruby/dump.h>
+#include <mruby/proc.h>
#define RITEBIN_EXT ".mrb"
#define C_EXT ".c"
diff --git a/mrbgems/mruby-bin-mruby/bintest/mruby.rb b/mrbgems/mruby-bin-mruby/bintest/mruby.rb
index de211c1ba..01fc94632 100644
--- a/mrbgems/mruby-bin-mruby/bintest/mruby.rb
+++ b/mrbgems/mruby-bin-mruby/bintest/mruby.rb
@@ -1,17 +1,17 @@
require 'tempfile'
assert('regression for #1564') do
- o = `bin/mruby -e '<<' 2>&1`
+ o = `#{cmd('mruby')} -e #{shellquote('<<')} 2>&1`
assert_equal o, "-e:1:2: syntax error, unexpected tLSHFT\n"
- o = `bin/mruby -e '<<-' 2>&1`
+ o = `#{cmd('mruby')} -e #{shellquote('<<-')} 2>&1`
assert_equal o, "-e:1:3: syntax error, unexpected tLSHFT\n"
end
assert('regression for #1572') do
script, bin = Tempfile.new('test.rb'), Tempfile.new('test.mrb')
- system "echo 'p \"ok\"' > #{script.path}"
- system "bin/mrbc -g -o #{bin.path} #{script.path}"
- o = `bin/mruby -b #{bin.path}`.strip
+ File.write script.path, 'p "ok"'
+ system "#{cmd('mrbc')} -g -o #{bin.path} #{script.path}"
+ o = `#{cmd('mruby')} -b #{bin.path}`.strip
assert_equal o, '"ok"'
end
@@ -21,14 +21,14 @@ assert '$0 value' do
# .rb script
script.write "p $0\n"
script.flush
- assert_equal "\"#{script.path}\"", `./bin/mruby "#{script.path}"`.chomp
+ assert_equal "\"#{script.path}\"", `#{cmd('mruby')} "#{script.path}"`.chomp
# .mrb file
- `./bin/mrbc -o "#{bin.path}" "#{script.path}"`
- assert_equal "\"#{bin.path}\"", `./bin/mruby -b "#{bin.path}"`.chomp
+ `#{cmd('mrbc')} -o "#{bin.path}" "#{script.path}"`
+ assert_equal "\"#{bin.path}\"", `#{cmd('mruby')} -b "#{bin.path}"`.chomp
# one liner
- assert_equal '"-e"', `./bin/mruby -e 'p $0'`.chomp
+ assert_equal '"-e"', `#{cmd('mruby')} -e #{shellquote('p $0')}`.chomp
end
assert '__END__', '8.6' do
@@ -42,5 +42,5 @@ __END__
p 'legend'
EOS
script.flush
- assert_equal "\"test\"\n\"fin\"\n", `./bin/mruby #{script.path}`
+ assert_equal "\"test\"\n\"fin\"\n", `#{cmd('mruby')} #{script.path}`
end
diff --git a/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c b/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c
index cc1ca3055..ab6c6688f 100644
--- a/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c
+++ b/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c
@@ -1,13 +1,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/compile.h"
-#include "mruby/dump.h"
-#include "mruby/variable.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/compile.h>
+#include <mruby/dump.h>
+#include <mruby/variable.h>
-#ifndef ENABLE_STDIO
+#ifdef MRB_DISABLE_STDIO
static void
p(mrb_state *mrb, mrb_value obj)
{
diff --git a/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb b/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb
index e74a74f10..bb664a2b1 100644
--- a/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb
+++ b/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb
@@ -1,13 +1,13 @@
require 'tempfile'
assert('no files') do
- o = `bin/mruby-strip 2>&1`
+ o = `#{cmd('mruby-strip')} 2>&1`
assert_equal 1, $?.exitstatus
assert_equal "no files to strip", o.split("\n")[0]
end
assert('file not found') do
- o = `bin/mruby-strip not_found.mrb 2>&1`
+ o = `#{cmd('mruby-strip')} not_found.mrb 2>&1`
assert_equal 1, $?.exitstatus
assert_equal "can't open file for reading not_found.mrb\n", o
end
@@ -16,7 +16,7 @@ assert('not irep file') do
t = Tempfile.new('script.rb')
t.write 'p test\n'
t.flush
- o = `bin/mruby-strip #{t.path} 2>&1`
+ o = `#{cmd('mruby-strip')} #{t.path} 2>&1`
assert_equal 1, $?.exitstatus
assert_equal "can't read irep file #{t.path}\n", o
end
@@ -26,15 +26,15 @@ assert('success') do
Tempfile.new('script.rb'), Tempfile.new('c1.mrb'), Tempfile.new('c2.mrb')
script_file.write "p 'test'\n"
script_file.flush
- `bin/mrbc -g -o #{compiled1.path} #{script_file.path}`
- `bin/mrbc -g -o #{compiled2.path} #{script_file.path}`
+ `#{cmd('mrbc')} -g -o #{compiled1.path} #{script_file.path}`
+ `#{cmd('mrbc')} -g -o #{compiled2.path} #{script_file.path}`
- o = `bin/mruby-strip #{compiled1.path}`
+ o = `#{cmd('mruby-strip')} #{compiled1.path}`
assert_equal 0, $?.exitstatus
assert_equal "", o
- assert_equal `bin/mruby #{script_file.path}`, `bin/mruby -b #{compiled1.path}`
+ assert_equal `#{cmd('mruby')} #{script_file.path}`, `#{cmd('mruby')} -b #{compiled1.path}`
- o = `bin/mruby-strip #{compiled1.path} #{compiled2.path}`
+ o = `#{cmd('mruby-strip')} #{compiled1.path} #{compiled2.path}`
assert_equal 0, $?.exitstatus
assert_equal "", o
end
@@ -44,12 +44,12 @@ assert('check debug section') do
Tempfile.new('script.rb'), Tempfile.new('c1.mrb'), Tempfile.new('c2.mrb')
script_file.write "p 'test'\n"
script_file.flush
- `bin/mrbc -o #{without_debug.path} #{script_file.path}`
- `bin/mrbc -g -o #{with_debug.path} #{script_file.path}`
+ `#{cmd('mrbc')} -o #{without_debug.path} #{script_file.path}`
+ `#{cmd('mrbc')} -g -o #{with_debug.path} #{script_file.path}`
assert_true with_debug.size >= without_debug.size
- `bin/mruby-strip #{with_debug.path}`
+ `#{cmd('mruby-strip')} #{with_debug.path}`
assert_equal without_debug.size, with_debug.size
end
@@ -62,12 +62,12 @@ a += b
p Kernel.local_variables
EOS
script_file.flush
- `bin/mrbc -o #{with_lv.path} #{script_file.path}`
- `bin/mrbc -o #{without_lv.path} #{script_file.path}`
+ `#{cmd('mrbc')} -o #{with_lv.path} #{script_file.path}`
+ `#{cmd('mrbc')} -o #{without_lv.path} #{script_file.path}`
- `bin/mruby-strip -l #{without_lv.path}`
+ `#{cmd('mruby-strip')} -l #{without_lv.path}`
assert_true without_lv.size < with_lv.size
- assert_equal '[:a, :b]', `bin/mruby -b #{with_lv.path}`.chomp
- assert_equal '[]', `bin/mruby -b #{without_lv.path}`.chomp
+ assert_equal '[:a, :b]', `#{cmd('mruby')} -b #{with_lv.path}`.chomp
+ assert_equal '[]', `#{cmd('mruby')} -b #{without_lv.path}`.chomp
end
diff --git a/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby-strip.c b/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby-strip.c
index 0529d3938..1fd2bc5eb 100644
--- a/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby-strip.c
+++ b/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby-strip.c
@@ -1,9 +1,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "mruby.h"
-#include "mruby/irep.h"
-#include "mruby/dump.h"
+#include <mruby.h>
+#include <mruby/irep.h>
+#include <mruby/dump.h>
struct strip_args {
int argc_start;
diff --git a/mrbgems/mruby-compiler/bintest/mrbc.rb b/mrbgems/mruby-compiler/bintest/mrbc.rb
index b016378a1..e4dc6a9a8 100644
--- a/mrbgems/mruby-compiler/bintest/mrbc.rb
+++ b/mrbgems/mruby-compiler/bintest/mrbc.rb
@@ -6,7 +6,7 @@ assert('Compiling multiple files without new line in last line. #2361') do
a.flush
b.write('module B; end')
b.flush
- result = `bin/mrbc -c -o #{out.path} #{a.path} #{b.path} 2>&1`
- assert_equal "bin/mrbc:#{a.path}:Syntax OK", result.chomp
+ result = `#{cmd('mrbc')} -c -o #{out.path} #{a.path} #{b.path} 2>&1`
+ assert_equal "#{cmd('mrbc')}:#{a.path}:Syntax OK", result.chomp
assert_equal 0, $?.exitstatus
end
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index 3853814ec..c56c1550c 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -8,16 +8,16 @@
#include <limits.h>
#include <stdlib.h>
#include <string.h>
-#include "mruby.h"
-#include "mruby/compile.h"
-#include "mruby/proc.h"
-#include "mruby/numeric.h"
-#include "mruby/string.h"
-#include "mruby/debug.h"
+#include <mruby.h>
+#include <mruby/compile.h>
+#include <mruby/proc.h>
+#include <mruby/numeric.h>
+#include <mruby/string.h>
+#include <mruby/debug.h>
#include "node.h"
-#include "mruby/opcode.h"
-#include "mruby/re.h"
-#include "mruby/throw.h"
+#include <mruby/opcode.h>
+#include <mruby/re.h>
+#include <mruby/throw.h>
typedef mrb_ast_node node;
typedef struct mrb_parser_state parser_state;
@@ -96,7 +96,7 @@ codegen_error(codegen_scope *s, const char *message)
mrb_pool_close(s->mpool);
s = tmp;
}
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
if (s->filename && s->lineno) {
fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message);
}
@@ -375,7 +375,7 @@ dispatch(codegen_scope *s, int pc)
case OP_ONERR:
break;
default:
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
fprintf(stderr, "bug: dispatch on non JMP op\n");
#endif
scope_error(s);
@@ -978,7 +978,7 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
break;
default:
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
printf("unknown lhs %d\n", type);
#endif
break;
@@ -1330,6 +1330,17 @@ codegen(codegen_scope *s, node *tree, int val)
int pos1, pos2;
node *e = tree->cdr->cdr->car;
+ switch ((intptr_t)tree->car->car) {
+ case NODE_TRUE:
+ case NODE_INT:
+ case NODE_STR:
+ codegen(s, tree->cdr->car, val);
+ return;
+ case NODE_FALSE:
+ case NODE_NIL:
+ codegen(s, e, val);
+ return;
+ }
codegen(s, tree->car, VAL);
pop();
pos1 = genop_peep(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0), NOVAL);
@@ -2216,7 +2227,8 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_REGX:
if (val) {
char *p1 = (char*)tree->car;
- char *p2 = (char*)tree->cdr;
+ char *p2 = (char*)tree->cdr->car;
+ char *p3 = (char*)tree->cdr->cdr;
int ai = mrb_gc_arena_save(s->mrb);
int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1));
@@ -2226,11 +2238,22 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
push();
genop(s, MKOP_ABx(OP_STRING, cursp(), off));
- if (p2) {
+ if (p2 || p3) {
push();
- off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
- genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ if (p2) {
+ off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
+ genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ } else {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ }
argc++;
+ if (p3) {
+ push();
+ off = new_lit(s, mrb_str_new(s->mrb, p3, 1));
+ genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ argc++;
+ pop();
+ }
pop();
}
pop();
diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y
index 097d63ac4..e46ff5b98 100644
--- a/mrbgems/mruby-compiler/core/parse.y
+++ b/mrbgems/mruby-compiler/core/parse.y
@@ -22,12 +22,12 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#include "mruby.h"
-#include "mruby/compile.h"
-#include "mruby/proc.h"
-#include "mruby/error.h"
+#include <mruby.h>
+#include <mruby/compile.h>
+#include <mruby/proc.h>
+#include <mruby/error.h>
+#include <mruby/throw.h>
#include "node.h"
-#include "mruby/throw.h"
#define YYLEX_PARAM p
@@ -761,9 +761,9 @@ new_dsym(parser_state *p, node *a)
/* (:str . (a . a)) */
static node*
-new_regx(parser_state *p, const char *p1, const char* p2)
+new_regx(parser_state *p, const char *p1, const char* p2, const char* p3)
{
- return cons((node*)NODE_REGX, cons((node*)p1, (node*)p2));
+ return cons((node*)NODE_REGX, cons((node*)p1, cons((node*)p2, (node*)p3)));
}
/* (:dregx . a) */
@@ -3294,7 +3294,7 @@ yyerror(parser_state *p, const char *s)
int n;
if (! p->capture_errors) {
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
if (p->filename) {
fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s);
}
@@ -3330,7 +3330,7 @@ yywarn(parser_state *p, const char *s)
int n;
if (! p->capture_errors) {
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
if (p->filename) {
fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s);
}
@@ -3401,7 +3401,7 @@ nextc(parser_state *p)
cons_free(tmp);
}
else {
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
if (p->f) {
if (feof(p->f)) goto eof;
c = fgetc(p->f);
@@ -3491,7 +3491,7 @@ peeks(parser_state *p, const char *s)
{
int len = strlen(s);
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
if (p->f) {
int n = 0;
while (*s) {
@@ -3986,6 +3986,8 @@ parse_string(parser_state *p)
char *s = strndup(tok(p), toklen(p));
char flags[3];
char *flag = flags;
+ char enc = '\0';
+ char *encp;
char *dup;
newtok(p);
@@ -3994,6 +3996,8 @@ parse_string(parser_state *p)
case 'i': f |= 1; break;
case 'x': f |= 2; break;
case 'm': f |= 4; break;
+ case 'u': f |= 16; break;
+ case 'n': f |= 32; break;
default: tokadd(p, re_opt); break;
}
}
@@ -4009,12 +4013,20 @@ parse_string(parser_state *p)
if (f & 1) *flag++ = 'i';
if (f & 2) *flag++ = 'x';
if (f & 4) *flag++ = 'm';
- dup = strndup(flags, (size_t)(flag - flags));
+ if (f & 16) enc = 'u';
+ if (f & 32) enc = 'n';
}
- else {
+ if (flag > flags) {
+ dup = strndup(flags, (size_t)(flag - flags));
+ } else {
dup = NULL;
}
- yylval.nd = new_regx(p, s, dup);
+ if (enc) {
+ encp = strndup(&enc, 1);
+ } else {
+ encp = NULL;
+ }
+ yylval.nd = new_regx(p, s, dup, encp);
return tREGEXP;
}
@@ -5430,7 +5442,7 @@ mrb_parser_new(mrb_state *mrb)
p->pool = pool;
p->s = p->send = NULL;
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
p->f = NULL;
#endif
@@ -5529,7 +5541,7 @@ mrb_parser_get_filename(struct mrb_parser_state* p, uint16_t idx) {
}
}
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
MRB_API parser_state*
mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c)
{
@@ -5621,7 +5633,7 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c)
return v;
}
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
MRB_API mrb_value
mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c)
{
@@ -5659,7 +5671,7 @@ mrb_load_string(mrb_state *mrb, const char *s)
return mrb_load_string_cxt(mrb, s, NULL);
}
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
static void
dump_prefix(node *tree, int offset)
@@ -5685,7 +5697,7 @@ dump_recur(mrb_state *mrb, node *tree, int offset)
void
mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
{
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
int nodetype;
if (!tree) return;
@@ -5972,9 +5984,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
case NODE_COLON3:
- printf("NODE_COLON3:\n");
- dump_prefix(tree, offset+1);
- printf("::%s\n", mrb_sym2name(mrb, sym(tree)));
+ printf("NODE_COLON3: ::%s\n", mrb_sym2name(mrb, sym(tree)));
break;
case NODE_ARRAY:
diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb
index 6fef0c077..ed1943f30 100644
--- a/mrbgems/mruby-enum-ext/mrblib/enum.rb
+++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb
@@ -77,11 +77,11 @@ module Enumerable
# Passes elements to the block until the block returns +nil+ or +false+,
# then stops iterating and returns an array of all prior elements.
#
- # If no block is given, an enumerator is returned instead.
+ # If no block is given, an enumerator is returned instead.
+ #
+ # a = [1, 2, 3, 4, 5, 0]
+ # a.take_while {|i| i < 3 } #=> [1, 2]
#
- # a = [1, 2, 3, 4, 5, 0]
- # a.take_while {|i| i < 3 } #=> [1, 2]
-
def take_while(&block)
return to_enum :take_while unless block
@@ -94,13 +94,12 @@ module Enumerable
end
##
- # call-seq:
- # enum.each_cons(n) {...} -> nil
- #
# Iterates the given block for each array of consecutive <n>
# elements.
#
- # e.g.:
+ # @return [nil]
+ #
+ # @example
# (1..10).each_cons(3) {|a| p a}
# # outputs below
# [1, 2, 3]
@@ -116,6 +115,7 @@ module Enumerable
raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
raise ArgumentError, "invalid size" if n <= 0
+ return to_enum(:each_cons,n) unless block
ary = []
n = n.to_int
self.each do |*val|
@@ -126,12 +126,11 @@ module Enumerable
end
##
- # call-seq:
- # enum.each_slice(n) {...} -> nil
- #
# Iterates the given block for each slice of <n> elements.
#
- # e.g.:
+ # @return [nil]
+ #
+ # @example
# (1..10).each_slice(3) {|a| p a}
# # outputs below
# [1, 2, 3]
@@ -143,6 +142,7 @@ module Enumerable
raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
raise ArgumentError, "invalid slice size" if n <= 0
+ return to_enum(:each_slice,n) unless block
ary = []
n = n.to_int
self.each do |*val|
@@ -164,8 +164,8 @@ module Enumerable
# block, and values are arrays of elements in <i>enum</i>
# corresponding to the key.
#
- # (1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
-
+ # (1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
+ #
def group_by(&block)
return to_enum :group_by unless block
diff --git a/mrbgems/mruby-enum-lazy/mrblib/lazy.rb b/mrbgems/mruby-enum-lazy/mrblib/lazy.rb
index 2ffeb1808..8ce363c6d 100644
--- a/mrbgems/mruby-enum-lazy/mrblib/lazy.rb
+++ b/mrbgems/mruby-enum-lazy/mrblib/lazy.rb
@@ -1,30 +1,29 @@
-# = Enumerable#lazy implementation
-#
-# Enumerable#lazy returns an instance of Enumerable::Lazy.
-# You can use it just like as normal Enumerable object,
-# except these methods act as 'lazy':
-#
-# - map collect
-# - select find_all
-# - reject
-# - grep
-# - drop
-# - drop_while
-# - take_while
-# - flat_map collect_concat
-# - zip
-#
-# == Acknowledgements
-#
-# Based on https://github.com/yhara/enumerable-lazy
-# Inspired by https://github.com/antimon2/enumerable_lz
-# http://jp.rubyist.net/magazine/?0034-Enumerable_lz (ja)
-
module Enumerable
+
+ # = Enumerable#lazy implementation
+ #
+ # Enumerable#lazy returns an instance of Enumerable::Lazy.
+ # You can use it just like as normal Enumerable object,
+ # except these methods act as 'lazy':
+ #
+ # - map collect
+ # - select find_all
+ # - reject
+ # - grep
+ # - drop
+ # - drop_while
+ # - take_while
+ # - flat_map collect_concat
+ # - zip
def lazy
Lazy.new(self)
end
+ # == Acknowledgements
+ #
+ # Based on https://github.com/yhara/enumerable-lazy
+ # Inspired by https://github.com/antimon2/enumerable_lz
+ # http://jp.rubyist.net/magazine/?0034-Enumerable_lz (ja)
class Lazy < Enumerator
def initialize(obj, &block)
super(){|yielder|
diff --git a/mrbgems/mruby-enumerator/mrblib/enumerator.rb b/mrbgems/mruby-enumerator/mrblib/enumerator.rb
index c54959e91..9abaca38a 100644
--- a/mrbgems/mruby-enumerator/mrblib/enumerator.rb
+++ b/mrbgems/mruby-enumerator/mrblib/enumerator.rb
@@ -6,92 +6,91 @@
# A class which allows both internal and external iteration.
#
# An Enumerator can be created by the following methods.
-# - Kernel#to_enum
-# - Kernel#enum_for
-# - Enumerator.new
+# - {Kernel#to_enum}
+# - {Kernel#enum_for}
+# - {Enumerator#initialize Enumerator.new}
#
# Most methods have two forms: a block form where the contents
# are evaluated for each item in the enumeration, and a non-block form
# which returns a new Enumerator wrapping the iteration.
#
-# enumerator = %w(one two three).each
-# puts enumerator.class # => Enumerator
+# enumerator = %w(one two three).each
+# puts enumerator.class # => Enumerator
#
-# enumerator.each_with_object("foo") do |item, obj|
-# puts "#{obj}: #{item}"
-# end
+# enumerator.each_with_object("foo") do |item, obj|
+# puts "#{obj}: #{item}"
+# end
#
-# # foo: one
-# # foo: two
-# # foo: three
+# # foo: one
+# # foo: two
+# # foo: three
#
-# enum_with_obj = enumerator.each_with_object("foo")
-# puts enum_with_obj.class # => Enumerator
+# enum_with_obj = enumerator.each_with_object("foo")
+# puts enum_with_obj.class # => Enumerator
#
-# enum_with_obj.each do |item, obj|
-# puts "#{obj}: #{item}"
-# end
+# enum_with_obj.each do |item, obj|
+# puts "#{obj}: #{item}"
+# end
#
-# # foo: one
-# # foo: two
-# # foo: three
+# # foo: one
+# # foo: two
+# # foo: three
#
# This allows you to chain Enumerators together. For example, you
# can map a list's elements to strings containing the index
# and the element as a string via:
#
-# puts %w[foo bar baz].map.with_index { |w, i| "#{i}:#{w}" }
-# # => ["0:foo", "1:bar", "2:baz"]
+# puts %w[foo bar baz].map.with_index { |w, i| "#{i}:#{w}" }
+# # => ["0:foo", "1:bar", "2:baz"]
#
# An Enumerator can also be used as an external iterator.
# For example, Enumerator#next returns the next value of the iterator
# or raises StopIteration if the Enumerator is at the end.
#
-# e = [1,2,3].each # returns an enumerator object.
-# puts e.next # => 1
-# puts e.next # => 2
-# puts e.next # => 3
-# puts e.next # raises StopIteration
+# e = [1,2,3].each # returns an enumerator object.
+# puts e.next # => 1
+# puts e.next # => 2
+# puts e.next # => 3
+# puts e.next # raises StopIteration
#
# You can use this to implement an internal iterator as follows:
#
-# def ext_each(e)
-# while true
-# begin
-# vs = e.next_values
-# rescue StopIteration
-# return $!.result
+# def ext_each(e)
+# while true
+# begin
+# vs = e.next_values
+# rescue StopIteration
+# return $!.result
+# end
+# y = yield(*vs)
+# e.feed y
+# end
# end
-# y = yield(*vs)
-# e.feed y
-# end
-# end
#
-# o = Object.new
+# o = Object.new
#
-# def o.each
-# puts yield
-# puts yield(1)
-# puts yield(1, 2)
-# 3
-# end
+# def o.each
+# puts yield
+# puts yield(1)
+# puts yield(1, 2)
+# 3
+# end
#
-# # use o.each as an internal iterator directly.
-# puts o.each {|*x| puts x; [:b, *x] }
-# # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
+# # use o.each as an internal iterator directly.
+# puts o.each {|*x| puts x; [:b, *x] }
+# # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
+#
+# # convert o.each to an external iterator for
+# # implementing an internal iterator.
+# puts ext_each(o.to_enum) {|*x| puts x; [:b, *x] }
+# # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
#
-# # convert o.each to an external iterator for
-# # implementing an internal iterator.
-# puts ext_each(o.to_enum) {|*x| puts x; [:b, *x] }
-# # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
-
class Enumerator
include Enumerable
##
- # call-seq:
- # Enumerator.new(size = nil) { |yielder| ... }
- # Enumerator.new(obj, method = :each, *args)
+ # @overload initialize(size = nil, &block)
+ # @overload initialize(obj, method = :each, *args)
#
# Creates a new Enumerator object, which can be used as an
# Enumerable.
@@ -100,15 +99,15 @@ class Enumerator
# which a "yielder" object, given as block parameter, can be used to
# yield a value by calling the +yield+ method (aliased as +<<+):
#
- # fib = Enumerator.new do |y|
- # a = b = 1
- # loop do
- # y << a
- # a, b = b, a + b
+ # fib = Enumerator.new do |y|
+ # a = b = 1
+ # loop do
+ # y << a
+ # a, b = b, a + b
+ # end
# end
- # end
#
- # p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
+ # p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
#
def initialize(obj=nil, meth=:each, *args, &block)
if block_given?
@@ -188,8 +187,7 @@ class Enumerator
#
# If no block is given, returns a new Enumerator.
#
- # === Example
- #
+ # @example
# to_three = Enumerator.new do |y|
# 3.times do |x|
# y << x
@@ -582,27 +580,27 @@ module Kernel
#
# Here is such an example, with parameter passing and a sizing block:
#
- # module Enumerable
- # # a generic method to repeat the values of any enumerable
- # def repeat(n)
- # raise ArgumentError, "#{n} is negative!" if n < 0
- # unless block_given?
- # return to_enum(__method__, n) do # __method__ is :repeat here
- # sz = size # Call size and multiply by n...
- # sz * n if sz # but return nil if size itself is nil
+ # module Enumerable
+ # # a generic method to repeat the values of any enumerable
+ # def repeat(n)
+ # raise ArgumentError, "#{n} is negative!" if n < 0
+ # unless block_given?
+ # return to_enum(__method__, n) do # __method__ is :repeat here
+ # sz = size # Call size and multiply by n...
+ # sz * n if sz # but return nil if size itself is nil
+ # end
+ # end
+ # each do |*val|
+ # n.times { yield *val }
# end
- # end
- # each do |*val|
- # n.times { yield *val }
# end
# end
- # end
#
- # %i[hello world].repeat(2) { |w| puts w }
- # # => Prints 'hello', 'hello', 'world', 'world'
- # enum = (1..14).repeat(3)
- # # => returns an Enumerator when called without a block
- # enum.first(4) # => [1, 1, 1, 2]
+ # %i[hello world].repeat(2) { |w| puts w }
+ # # => Prints 'hello', 'hello', 'world', 'world'
+ # enum = (1..14).repeat(3)
+ # # => returns an Enumerator when called without a block
+ # enum.first(4) # => [1, 1, 1, 2]
#
def to_enum(meth=:each, *args)
Enumerator.new self, meth, *args
diff --git a/mrbgems/mruby-enumerator/test/enumerator.rb b/mrbgems/mruby-enumerator/test/enumerator.rb
index 0e3ddcba9..2e45dae4b 100644
--- a/mrbgems/mruby-enumerator/test/enumerator.rb
+++ b/mrbgems/mruby-enumerator/test/enumerator.rb
@@ -427,7 +427,6 @@ assert 'modifying existing methods' do
assert_equal i, e.next
i += 1
}
- assert_nil loop_ret
end
assert 'Integral#times' do
diff --git a/mrbgems/mruby-error/src/exception.c b/mrbgems/mruby-error/src/exception.c
index 911fde0be..170abb699 100644
--- a/mrbgems/mruby-error/src/exception.c
+++ b/mrbgems/mruby-error/src/exception.c
@@ -1,6 +1,6 @@
-#include "mruby.h"
-#include "mruby/throw.h"
-#include "mruby/error.h"
+#include <mruby.h>
+#include <mruby/throw.h>
+#include <mruby/error.h>
MRB_API mrb_value
mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state)
diff --git a/mrbgems/mruby-error/test/exception.c b/mrbgems/mruby-error/test/exception.c
index 2a943aaae..4de0e9607 100644
--- a/mrbgems/mruby-error/test/exception.c
+++ b/mrbgems/mruby-error/test/exception.c
@@ -1,6 +1,6 @@
-#include "mruby.h"
-#include "mruby/error.h"
-#include "mruby/array.h"
+#include <mruby.h>
+#include <mruby/error.h>
+#include <mruby/array.h>
static mrb_value
protect_cb(mrb_state *mrb, mrb_value b)
diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c
index 8bfa2f112..eef1f5046 100644
--- a/mrbgems/mruby-eval/src/eval.c
+++ b/mrbgems/mruby-eval/src/eval.c
@@ -1,9 +1,9 @@
-#include "mruby.h"
-#include "mruby/class.h"
-#include "mruby/compile.h"
-#include "mruby/irep.h"
-#include "mruby/proc.h"
-#include "mruby/opcode.h"
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/compile.h>
+#include <mruby/irep.h>
+#include <mruby/proc.h>
+#include <mruby/opcode.h>
static struct mrb_irep *
get_closure_irep(mrb_state *mrb, int level)
@@ -235,12 +235,12 @@ f_instance_eval(mrb_state *mrb, mrb_value self)
mrb_int len;
char *file = NULL;
mrb_int line = 1;
+ mrb_value cv;
mrb_get_args(mrb, "s|zi", &s, &len, &file, &line);
c->ci->acc = CI_ACC_SKIP;
- if (c->ci->target_class->tt == MRB_TT_ICLASS) {
- c->ci->target_class = c->ci->target_class->c;
- }
+ cv = mrb_singleton_class(mrb, self);
+ c->ci->target_class = mrb_class_ptr(cv);
return mrb_run(mrb, create_proc_from_string(mrb, s, len, mrb_nil_value(), file, line), self);
}
else {
diff --git a/mrbgems/mruby-eval/test/eval.rb b/mrbgems/mruby-eval/test/eval.rb
index e5d3bde18..17860b132 100644
--- a/mrbgems/mruby-eval/test/eval.rb
+++ b/mrbgems/mruby-eval/test/eval.rb
@@ -78,3 +78,22 @@ assert('Kernel.#eval(string) context') do
assert_equal('class') { obj.const_string }
end
+assert('Object#instance_eval with begin-rescue-ensure execution order') do
+ class HellRaiser
+ def raise_hell
+ order = [:enter_raise_hell]
+ begin
+ order.push :begin
+ self.instance_eval("raise 'error'")
+ rescue
+ order.push :rescue
+ ensure
+ order.push :ensure
+ end
+ order
+ end
+ end
+
+ hell_raiser = HellRaiser.new
+ assert_equal([:enter_raise_hell, :begin, :rescue, :ensure], hell_raiser.raise_hell)
+end
diff --git a/mrbgems/mruby-exit/src/mruby-exit.c b/mrbgems/mruby-exit/src/mruby-exit.c
index 726dfd7c4..3e147f80b 100644
--- a/mrbgems/mruby-exit/src/mruby-exit.c
+++ b/mrbgems/mruby-exit/src/mruby-exit.c
@@ -1,5 +1,5 @@
#include <stdlib.h>
-#include "mruby.h"
+#include <mruby.h>
static mrb_value
f_exit(mrb_state *mrb, mrb_value self)
diff --git a/mrbgems/mruby-fiber/src/fiber.c b/mrbgems/mruby-fiber/src/fiber.c
index 93b3f1227..c140b6eac 100644
--- a/mrbgems/mruby-fiber/src/fiber.c
+++ b/mrbgems/mruby-fiber/src/fiber.c
@@ -1,7 +1,7 @@
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/class.h"
-#include "mruby/proc.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/proc.h>
#define fiber_ptr(o) ((struct RFiber*)mrb_ptr(o))
diff --git a/mrbgems/mruby-hash-ext/mrblib/hash.rb b/mrbgems/mruby-hash-ext/mrblib/hash.rb
index c970b9d02..2727e1f65 100644
--- a/mrbgems/mruby-hash-ext/mrblib/hash.rb
+++ b/mrbgems/mruby-hash-ext/mrblib/hash.rb
@@ -5,22 +5,22 @@ class Hash
##
# call-seq:
- # Hash[ key, value, ... ] -> new_hash
- # Hash[ [ [key, value], ... ] ] -> new_hash
- # Hash[ object ] -> new_hash
+ # Hash[ key, value, ... ] -> new_hash
+ # Hash[ [ [key, value], ... ] ] -> new_hash
+ # Hash[ object ] -> new_hash
#
# Creates a new hash populated with the given objects.
#
- # Similar to the literal <code>{ _key_ => _value_, ... }</code>. In the first
+ # Similar to the literal `{ _key_ => _value_, ... }`. In the first
# form, keys and values occur in pairs, so there must be an even number of
# arguments.
#
# The second and third form take a single argument which is either an array
# of key-value pairs or an object convertible to a hash.
#
- # Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200}
- # Hash[ [ ["a", 100], ["b", 200] ] ] #=> {"a"=>100, "b"=>200}
- # Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200}
+ # Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200}
+ # Hash[ [ ["a", 100], ["b", 200] ] ] #=> {"a"=>100, "b"=>200}
+ # Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200}
#
def self.[](*object)
@@ -62,6 +62,25 @@ class Hash
##
# call-seq:
+ # Hash.try_convert(obj) -> hash or nil
+ #
+ # Try to convert <i>obj</i> into a hash, using to_hash method.
+ # Returns converted hash or nil if <i>obj</i> cannot be converted
+ # for any reason.
+ #
+ # Hash.try_convert({1=>2}) # => {1=>2}
+ # Hash.try_convert("1=>2") # => nil
+ #
+ def self.try_convert(obj)
+ if obj.respond_to?(:to_hash)
+ obj.to_hash
+ else
+ nil
+ end
+ end
+
+ ##
+ # call-seq:
# hsh.merge!(other_hash) -> hsh
# hsh.merge!(other_hash){|key, oldval, newval| block} -> hsh
#
@@ -126,11 +145,11 @@ class Hash
def fetch(key, none=NONE, &block)
unless self.key?(key)
if block
- block.call
+ block.call(key)
elsif none != NONE
none
else
- raise RuntimeError, "Key not found: #{key}"
+ raise KeyError, "Key not found: #{key}"
end
else
self[key]
@@ -156,7 +175,7 @@ class Hash
self.each do |k, v|
self.delete(k) if block.call(k, v)
- end
+ end
self
end
@@ -250,4 +269,100 @@ class Hash
def to_h
self
end
+
+ ##
+ # call-seq:
+ # hash < other -> true or false
+ #
+ # Returns <code>true</code> if <i>hash</i> is subset of
+ # <i>other</i>.
+ #
+ # h1 = {a:1, b:2}
+ # h2 = {a:1, b:2, c:3}
+ # h1 < h2 #=> true
+ # h2 < h1 #=> false
+ # h1 < h1 #=> false
+ #
+ def <(hash)
+ begin
+ hash = hash.to_hash
+ rescue NoMethodError
+ raise TypeError, "can't convert #{hash.class} to Hash"
+ end
+ size < hash.size and all? {|key, val|
+ hash.key?(key) and hash[key] == val
+ }
+ end
+
+ ##
+ # call-seq:
+ # hash <= other -> true or false
+ #
+ # Returns <code>true</code> if <i>hash</i> is subset of
+ # <i>other</i> or equals to <i>other</i>.
+ #
+ # h1 = {a:1, b:2}
+ # h2 = {a:1, b:2, c:3}
+ # h1 <= h2 #=> true
+ # h2 <= h1 #=> false
+ # h1 <= h1 #=> true
+ #
+ def <=(hash)
+ begin
+ hash = hash.to_hash
+ rescue NoMethodError
+ raise TypeError, "can't convert #{hash.class} to Hash"
+ end
+ size <= hash.size and all? {|key, val|
+ hash.key?(key) and hash[key] == val
+ }
+ end
+
+ ##
+ # call-seq:
+ # hash > other -> true or false
+ #
+ # Returns <code>true</code> if <i>other</i> is subset of
+ # <i>hash</i>.
+ #
+ # h1 = {a:1, b:2}
+ # h2 = {a:1, b:2, c:3}
+ # h1 > h2 #=> false
+ # h2 > h1 #=> true
+ # h1 > h1 #=> false
+ #
+ def >(hash)
+ begin
+ hash = hash.to_hash
+ rescue NoMethodError
+ raise TypeError, "can't convert #{hash.class} to Hash"
+ end
+ size > hash.size and hash.all? {|key, val|
+ key?(key) and self[key] == val
+ }
+ end
+
+ ##
+ # call-seq:
+ # hash >= other -> true or false
+ #
+ # Returns <code>true</code> if <i>other</i> is subset of
+ # <i>hash</i> or equals to <i>hash</i>.
+ #
+ # h1 = {a:1, b:2}
+ # h2 = {a:1, b:2, c:3}
+ # h1 >= h2 #=> false
+ # h2 >= h1 #=> true
+ # h1 >= h1 #=> true
+ #
+ def >=(hash)
+ begin
+ hash = hash.to_hash
+ rescue NoMethodError
+ raise TypeError, "can't convert #{hash.class} to Hash"
+ end
+ size >= hash.size and hash.all? {|key, val|
+ key?(key) and self[key] == val
+ }
+ end
end
diff --git a/mrbgems/mruby-hash-ext/src/hash-ext.c b/mrbgems/mruby-hash-ext/src/hash-ext.c
index bce842cb4..9560829b6 100644
--- a/mrbgems/mruby-hash-ext/src/hash-ext.c
+++ b/mrbgems/mruby-hash-ext/src/hash-ext.c
@@ -4,9 +4,9 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/hash.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/hash.h>
/*
* call-seq:
diff --git a/mrbgems/mruby-hash-ext/test/hash.rb b/mrbgems/mruby-hash-ext/test/hash.rb
index e1afdaaa3..8b6b2e5b9 100644
--- a/mrbgems/mruby-hash-ext/test/hash.rb
+++ b/mrbgems/mruby-hash-ext/test/hash.rb
@@ -39,6 +39,12 @@ assert('Hash.[] "c_key", "c_value"') do
end
end
+assert('Hash.try_convert') do
+ assert_nil Hash.try_convert(nil)
+ assert_nil Hash.try_convert("{1=>2}")
+ assert_equal({1=>2}, Hash.try_convert({1=>2}))
+end
+
assert('Hash#merge!') do
a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' }
b = { 'cba_key' => 'XXX', 'xyz_key' => 'xyz_value' }
@@ -75,10 +81,9 @@ assert('Hash#fetch') do
assert_equal "feline", h.fetch("cat")
assert_equal "mickey", h.fetch("mouse", "mickey")
assert_equal "minny", h.fetch("mouse"){"minny"}
- begin
+ assert_equal "mouse", h.fetch("mouse"){|k| k}
+ assert_raise(KeyError) do
h.fetch("gnu")
- rescue => e
- assert_kind_of(StandardError, e);
end
end
@@ -159,3 +164,75 @@ assert("Hash#to_h") do
assert_equal Hash, h.to_h.class
assert_equal h, h.to_h
end
+
+assert('Hash#<') do
+ h1 = {a:1, b:2}
+ h2 = {a:1, b:2, c:3}
+
+ assert_false(h1 < h1)
+ assert_true(h1 < h2)
+ assert_false(h2 < h1)
+ assert_false(h2 < h2)
+
+ h1 = {a:1}
+ h2 = {a:2}
+
+ assert_false(h1 < h1)
+ assert_false(h1 < h2)
+ assert_false(h2 < h1)
+ assert_false(h2 < h2)
+end
+
+assert('Hash#<=') do
+ h1 = {a:1, b:2}
+ h2 = {a:1, b:2, c:3}
+
+ assert_true(h1 <= h1)
+ assert_true(h1 <= h2)
+ assert_false(h2 <= h1)
+ assert_true(h2 <= h2)
+
+ h1 = {a:1}
+ h2 = {a:2}
+
+ assert_true(h1 <= h1)
+ assert_false(h1 <= h2)
+ assert_false(h2 <= h1)
+ assert_true(h2 <= h2)
+end
+
+assert('Hash#>=') do
+ h1 = {a:1, b:2}
+ h2 = {a:1, b:2, c:3}
+
+ assert_true(h1 >= h1)
+ assert_false(h1 >= h2)
+ assert_true(h2 >= h1)
+ assert_true(h2 >= h2)
+
+ h1 = {a:1}
+ h2 = {a:2}
+
+ assert_true(h1 >= h1)
+ assert_false(h1 >= h2)
+ assert_false(h2 >= h1)
+ assert_true(h2 >= h2)
+end
+
+assert('Hash#>') do
+ h1 = {a:1, b:2}
+ h2 = {a:1, b:2, c:3}
+
+ assert_false(h1 > h1)
+ assert_false(h1 > h2)
+ assert_true(h2 > h1)
+ assert_false(h2 > h2)
+
+ h1 = {a:1}
+ h2 = {a:2}
+
+ assert_false(h1 > h1)
+ assert_false(h1 > h2)
+ assert_false(h2 > h1)
+ assert_false(h2 > h2)
+end
diff --git a/mrbgems/mruby-kernel-ext/src/kernel.c b/mrbgems/mruby-kernel-ext/src/kernel.c
index baccbd303..74aa555d0 100644
--- a/mrbgems/mruby-kernel-ext/src/kernel.c
+++ b/mrbgems/mruby-kernel-ext/src/kernel.c
@@ -1,7 +1,7 @@
-#include "mruby.h"
-#include "mruby/error.h"
-#include "mruby/array.h"
-#include "mruby/hash.h"
+#include <mruby.h>
+#include <mruby/error.h>
+#include <mruby/array.h>
+#include <mruby/hash.h>
/*
* call-seq:
@@ -138,10 +138,11 @@ mrb_f_array(mrb_state *mrb, mrb_value self)
* <i>arg</i><code>.to_hash</code>. Returns an empty <code>Hash</code> when
* <i>arg</i> is <tt>nil</tt> or <tt>[]</tt>.
*
- * Hash([]) #=> {}
- * Hash(nil) #=> {}
- * Hash(key: :value) #=> {:key => :value}
- * Hash([1, 2, 3]) #=> TypeError
+ * Hash([]) #=> {}
+ * Hash(nil) #=> {}
+ * Hash(key: :value) #=> {:key => :value}
+ * Hash([1, 2, 3]) #=> TypeError
+ *
*/
static mrb_value
mrb_f_hash(mrb_state *mrb, mrb_value self)
diff --git a/mrbgems/mruby-math/src/math.c b/mrbgems/mruby-math/src/math.c
index 109112578..b2bd81e4e 100644
--- a/mrbgems/mruby-math/src/math.c
+++ b/mrbgems/mruby-math/src/math.c
@@ -4,8 +4,8 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include "mruby/array.h"
+#include <mruby.h>
+#include <mruby/array.h>
#include <math.h>
@@ -19,7 +19,7 @@ domain_error(mrb_state *mrb, const char *func)
}
/* math functions not provided by Microsoft Visual C++ 2012 or older */
-#if defined _MSC_VER && _MSC_VER < 1800
+#if defined _MSC_VER && _MSC_VER < 1700
#include <float.h>
@@ -236,7 +236,8 @@ math_tan(mrb_state *mrb, mrb_value obj)
* call-seq:
* Math.asin(x) -> float
*
- * Computes the arc sine of <i>x</i>. Returns -{PI/2} .. {PI/2}.
+ * Computes the arc sine of <i>x</i>.
+ * @return computed value between `-(PI/2)` and `(PI/2)`.
*/
static mrb_value
math_asin(mrb_state *mrb, mrb_value obj)
@@ -276,7 +277,7 @@ math_acos(mrb_state *mrb, mrb_value obj)
* call-seq:
* Math.atan(x) -> float
*
- * Computes the arc tangent of <i>x</i>. Returns -{PI/2} .. {PI/2}.
+ * Computes the arc tangent of <i>x</i>. Returns `-(PI/2) .. (PI/2)`.
*/
static mrb_value
math_atan(mrb_state *mrb, mrb_value obj)
diff --git a/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb b/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb
index dfc6ba87c..0bf3c6ab6 100644
--- a/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb
+++ b/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb
@@ -2,4 +2,16 @@ module Integral
def div(other)
self.divmod(other)[0]
end
+
+ def zero?
+ self == 0
+ end
+
+ def nonzero?
+ if self == 0
+ nil
+ else
+ self
+ end
+ end
end
diff --git a/mrbgems/mruby-numeric-ext/src/numeric_ext.c b/mrbgems/mruby-numeric-ext/src/numeric_ext.c
index 22c1668fa..f71236a32 100644
--- a/mrbgems/mruby-numeric-ext/src/numeric_ext.c
+++ b/mrbgems/mruby-numeric-ext/src/numeric_ext.c
@@ -1,5 +1,5 @@
#include <limits.h>
-#include "mruby.h"
+#include <mruby.h>
static mrb_value
mrb_int_chr(mrb_state *mrb, mrb_value x)
diff --git a/mrbgems/mruby-numeric-ext/test/numeric.rb b/mrbgems/mruby-numeric-ext/test/numeric.rb
index 96644da69..8bead2489 100644
--- a/mrbgems/mruby-numeric-ext/test/numeric.rb
+++ b/mrbgems/mruby-numeric-ext/test/numeric.rb
@@ -16,3 +16,13 @@ end
assert('Float#div') do
assert_float 52, 365.2425.div(7)
end
+
+assert('Integer#zero?') do
+ assert_equal true, 0.zero?
+ assert_equal false, 1.zero?
+end
+
+assert('Integer#nonzero?') do
+ assert_equal nil, 0.nonzero?
+ assert_equal 1000, 1000.nonzero?
+end
diff --git a/mrbgems/mruby-object-ext/src/object.c b/mrbgems/mruby-object-ext/src/object.c
index dc1924db0..3eba95633 100644
--- a/mrbgems/mruby-object-ext/src/object.c
+++ b/mrbgems/mruby-object-ext/src/object.c
@@ -1,6 +1,6 @@
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/class.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
/*
* call-seq:
diff --git a/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/mrbgems/mruby-objectspace/src/mruby_objectspace.c
index 1b18bf23f..d5cd4f5a1 100644
--- a/mrbgems/mruby-objectspace/src/mruby_objectspace.c
+++ b/mrbgems/mruby-objectspace/src/mruby_objectspace.c
@@ -1,7 +1,7 @@
-#include "mruby.h"
-#include "mruby/gc.h"
-#include "mruby/hash.h"
-#include "mruby/class.h"
+#include <mruby.h>
+#include <mruby/gc.h>
+#include <mruby/hash.h>
+#include <mruby/class.h>
struct os_count_struct {
mrb_int total;
@@ -17,7 +17,7 @@ os_count_object_type(mrb_state *mrb, struct RBasic *obj, void *data)
obj_count->total++;
- if (is_dead(mrb, obj)) {
+ if (mrb_object_dead_p(mrb, obj)) {
obj_count->freed++;
}
else {
@@ -115,7 +115,7 @@ os_each_object_cb(mrb_state *mrb, struct RBasic *obj, void *ud)
struct os_each_object_data *d = (struct os_each_object_data*)ud;
/* filter dead objects */
- if (is_dead(mrb, obj)) {
+ if (mrb_object_dead_p(mrb, obj)) {
return;
}
diff --git a/mrbgems/mruby-print/src/print.c b/mrbgems/mruby-print/src/print.c
index e7e21dd4b..f69254076 100644
--- a/mrbgems/mruby-print/src/print.c
+++ b/mrbgems/mruby-print/src/print.c
@@ -1,18 +1,34 @@
-#include "mruby.h"
-#include "mruby/string.h"
+#include <mruby.h>
+#include <mruby/string.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#if defined(__MINGW32__) || defined(__MINGW64__)
+# include <windows.h>
+# include <io.h>
+#endif
static void
printstr(mrb_state *mrb, mrb_value obj)
{
if (mrb_string_p(obj)) {
- char* ptr = mrb_locale_from_utf8(RSTRING_PTR(obj), RSTRING_LEN(obj));
- if (ptr) {
- fwrite(ptr, strlen(ptr), 1, stdout);
- mrb_locale_free(ptr);
- }
+#if defined(__MINGW32__) || defined(__MINGW64__)
+ if (isatty(fileno(stdout))) {
+ DWORD written;
+ int mlen = RSTRING_LEN(obj);
+ char* utf8 = RSTRING_PTR(obj);
+ int wlen = MultiByteToWideChar(CP_UTF8, 0, utf8, mlen, NULL, 0);
+ wchar_t* utf16 = mrb_malloc(mrb, (wlen+1) * sizeof(wchar_t));
+ if (utf16 == NULL) return;
+ if (MultiByteToWideChar(CP_UTF8, 0, utf8, mlen, utf16, wlen) > 0) {
+ utf16[wlen] = 0;
+ WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),
+ utf16, wlen, &written, NULL);
+ }
+ mrb_free(mrb, utf16);
+ } else
+#endif
+ fwrite(RSTRING_PTR(obj), RSTRING_LEN(obj), 1, stdout);
}
}
diff --git a/mrbgems/mruby-proc-ext/src/proc.c b/mrbgems/mruby-proc-ext/src/proc.c
index 73873a360..c8c8f1aa1 100644
--- a/mrbgems/mruby-proc-ext/src/proc.c
+++ b/mrbgems/mruby-proc-ext/src/proc.c
@@ -1,9 +1,9 @@
-#include "mruby.h"
-#include "mruby/proc.h"
-#include "mruby/opcode.h"
-#include "mruby/array.h"
-#include "mruby/string.h"
-#include "mruby/debug.h"
+#include <mruby.h>
+#include <mruby/proc.h>
+#include <mruby/opcode.h>
+#include <mruby/array.h>
+#include <mruby/string.h>
+#include <mruby/debug.h>
static mrb_value
mrb_proc_lambda(mrb_state *mrb, mrb_value self)
diff --git a/mrbgems/mruby-proc-ext/test/proc.c b/mrbgems/mruby-proc-ext/test/proc.c
index fcf8e2612..a77b68e9d 100644
--- a/mrbgems/mruby-proc-ext/test/proc.c
+++ b/mrbgems/mruby-proc-ext/test/proc.c
@@ -1,6 +1,6 @@
-#include "mruby.h"
-#include "mruby/proc.h"
-#include "mruby/class.h"
+#include <mruby.h>
+#include <mruby/proc.h>
+#include <mruby/class.h>
static mrb_value
return_func_name(mrb_state *mrb, mrb_value self)
diff --git a/mrbgems/mruby-random/src/mt19937ar.c b/mrbgems/mruby-random/src/mt19937ar.c
index 310a276fa..4013ad30b 100644
--- a/mrbgems/mruby-random/src/mt19937ar.c
+++ b/mrbgems/mruby-random/src/mt19937ar.c
@@ -4,7 +4,7 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
+#include <mruby.h>
#include "mt19937ar.h"
/* Period parameters */
diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c
index 3be3ac81c..040d83ed6 100644
--- a/mrbgems/mruby-random/src/random.c
+++ b/mrbgems/mruby-random/src/random.c
@@ -4,11 +4,11 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include "mruby/variable.h"
-#include "mruby/class.h"
-#include "mruby/data.h"
-#include "mruby/array.h"
+#include <mruby.h>
+#include <mruby/variable.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
+#include <mruby/array.h>
#include "mt19937ar.h"
#include <time.h>
diff --git a/mrbgems/mruby-range-ext/src/range.c b/mrbgems/mruby-range-ext/src/range.c
index 35632ad20..4d6f1684f 100644
--- a/mrbgems/mruby-range-ext/src/range.c
+++ b/mrbgems/mruby-range-ext/src/range.c
@@ -1,5 +1,5 @@
-#include "mruby.h"
-#include "mruby/range.h"
+#include <mruby.h>
+#include <mruby/range.h>
#include <math.h>
static mrb_bool
diff --git a/mrbgems/mruby-sprintf/src/kernel.c b/mrbgems/mruby-sprintf/src/kernel.c
index bd4f2bca1..946b43a8a 100644
--- a/mrbgems/mruby-sprintf/src/kernel.c
+++ b/mrbgems/mruby-sprintf/src/kernel.c
@@ -4,7 +4,7 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
+#include <mruby.h>
mrb_value mrb_f_sprintf(mrb_state *mrb, mrb_value obj); /* in sprintf.c */
diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c
index 81b48b10d..33e0931f9 100644
--- a/mrbgems/mruby-sprintf/src/sprintf.c
+++ b/mrbgems/mruby-sprintf/src/sprintf.c
@@ -4,14 +4,14 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
+#include <mruby.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
-#include "mruby/string.h"
-#include "mruby/hash.h"
-#include "mruby/numeric.h"
+#include <mruby/string.h>
+#include <mruby/hash.h>
+#include <mruby/numeric.h>
#include <math.h>
#include <ctype.h>
@@ -71,7 +71,7 @@ sign_bits(int base, const char *p)
static mrb_value
mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base)
{
- char buf[64], *b = buf + sizeof buf;
+ char buf[66], *b = buf + sizeof buf;
mrb_int num = mrb_fixnum(x);
uint64_t val = (uint64_t)num;
char d;
@@ -79,10 +79,6 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base)
if (base != 2) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %S", mrb_fixnum_value(base));
}
-
- if (val >= (1 << 10))
- val &= 0x3ff;
-
if (val == 0) {
return mrb_str_new_lit(mrb, "0");
}
@@ -763,11 +759,11 @@ retry:
case 'B':
case 'u': {
mrb_value val = GETARG();
- char fbuf[32], nbuf[64], *s;
+ char fbuf[32], nbuf[68], *s;
const char *prefix = NULL;
int sign = 0, dots = 0;
char sc = 0;
- mrb_int v = 0, org_v = 0;
+ mrb_int v = 0;
int base;
mrb_int len;
@@ -800,10 +796,6 @@ retry:
bin_retry:
switch (mrb_type(val)) {
case MRB_TT_FLOAT:
- if (FIXABLE(mrb_float(val))) {
- val = mrb_fixnum_value((mrb_int)mrb_float(val));
- goto bin_retry;
- }
val = mrb_flo_to_fixnum(mrb, val);
if (mrb_fixnum_p(val)) goto bin_retry;
break;
@@ -835,7 +827,6 @@ retry:
}
if (base == 2) {
- org_v = v;
if (v < 0 && !sign) {
val = mrb_fix2binstr(mrb, mrb_fixnum_value(v), base);
dots = 1;
@@ -843,12 +834,10 @@ retry:
else {
val = mrb_fixnum_to_str(mrb, mrb_fixnum_value(v), base);
}
- v = mrb_fixnum(mrb_str_to_inum(mrb, val, 10, FALSE));
}
if (sign) {
char c = *p;
if (c == 'i') c = 'd'; /* %d and %i are identical */
- if (base == 2) c = 'd';
if (v < 0) {
v = -v;
sc = '-';
@@ -862,20 +851,29 @@ retry:
sc = ' ';
width--;
}
- snprintf(fbuf, sizeof(fbuf), "%%l%c", c);
- snprintf(nbuf, sizeof(nbuf), fbuf, v);
+ if (base == 2) {
+ snprintf(nbuf, sizeof(nbuf), "%s", RSTRING_PTR(val));
+ }
+ else {
+ snprintf(fbuf, sizeof(fbuf), "%%l%c", c);
+ snprintf(nbuf, sizeof(nbuf), fbuf, v);
+ }
s = nbuf;
}
else {
char c = *p;
if (c == 'X') c = 'x';
- if (base == 2) c = 'd';
s = nbuf;
if (v < 0) {
dots = 1;
}
- snprintf(fbuf, sizeof(fbuf), "%%l%c", c);
- snprintf(++s, sizeof(nbuf) - 1, fbuf, v);
+ if (base == 2) {
+ snprintf(++s, sizeof(nbuf) - 1, "%s", RSTRING_PTR(val));
+ }
+ else {
+ snprintf(fbuf, sizeof(fbuf), "%%l%c", c);
+ snprintf(++s, sizeof(nbuf) - 1, fbuf, v);
+ }
if (v < 0) {
char d;
@@ -965,7 +963,7 @@ retry:
CHECK(prec - len);
if (dots) PUSH("..", 2);
- if (v < 0 || (base == 2 && org_v < 0)) {
+ if (v < 0) {
char c = sign_bits(base, p);
while (len < prec--) {
buf[blen++] = c;
diff --git a/mrbgems/mruby-sprintf/test/sprintf.rb b/mrbgems/mruby-sprintf/test/sprintf.rb
index 7007df1fa..454c226e1 100644
--- a/mrbgems/mruby-sprintf/test/sprintf.rb
+++ b/mrbgems/mruby-sprintf/test/sprintf.rb
@@ -5,4 +5,5 @@ assert('String#%') do
assert_equal "one=1", "one=%d" % 1
assert_equal "1 one 1.0", "%d %s %3.1f" % [ 1, "one", 1.01 ]
assert_equal "123 < 456", "%{num} < %<str>s" % { num: 123, str: "456" }
+ assert_equal 16, ("%b" % (1<<15)).size
end
diff --git a/mrbgems/mruby-string-ext/mrblib/string.rb b/mrbgems/mruby-string-ext/mrblib/string.rb
index 7d9bc00b9..c699e13b7 100644
--- a/mrbgems/mruby-string-ext/mrblib/string.rb
+++ b/mrbgems/mruby-string-ext/mrblib/string.rb
@@ -1,6 +1,25 @@
class String
##
+ # call-seq:
+ # String.try_convert(obj) -> string or nil
+ #
+ # Try to convert <i>obj</i> into a String, using to_str method.
+ # Returns converted string or nil if <i>obj</i> cannot be converted
+ # for any reason.
+ #
+ # String.try_convert("str") #=> "str"
+ # String.try_convert(/re/) #=> nil
+ #
+ def self.try_convert(obj)
+ if obj.respond_to?(:to_str)
+ obj.to_str
+ else
+ nil
+ end
+ end
+
+ ##
# call-seq:
# string.clear -> string
#
@@ -310,4 +329,30 @@ class String
return self if excl && str == other_str
end
end
+
+ def chars(&block)
+ if block_given?
+ self.split('').map do |i|
+ block.call(i)
+ end
+ self
+ else
+ self.split('')
+ end
+ end
+ alias each_char chars
+
+ def codepoints(&block)
+ len = self.size
+
+ if block_given?
+ self.split('').map do|x|
+ block.call(x.ord)
+ end
+ self
+ else
+ self.split('').map{|x| x.ord}
+ end
+ end
+ alias each_codepoint codepoints
end
diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c
index 12657e129..c2ee1fc23 100644
--- a/mrbgems/mruby-string-ext/src/string.c
+++ b/mrbgems/mruby-string-ext/src/string.c
@@ -1,9 +1,9 @@
#include <string.h>
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/class.h"
-#include "mruby/string.h"
-#include "mruby/range.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/string.h>
+#include <mruby/range.h>
static mrb_value
mrb_str_getbyte(mrb_state *mrb, mrb_value str)
@@ -245,6 +245,51 @@ mrb_str_chr(mrb_state *mrb, mrb_value self)
return mrb_str_substr(mrb, self, 0, 1);
}
+static mrb_value
+mrb_fixnum_chr(mrb_state *mrb, mrb_value num)
+{
+ mrb_int cp = mrb_fixnum(num);
+#ifdef MRB_UTF8_STRING
+ char utf8[4];
+ mrb_int len;
+
+ if (cp < 0 || 0x10FFFF < cp) {
+ mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", num);
+ }
+ if (cp < 0x80) {
+ utf8[0] = (char)cp;
+ len = 1;
+ }
+ else if (cp < 0x800) {
+ utf8[0] = (char)(0xC0 | (cp >> 6));
+ utf8[1] = (char)(0x80 | (cp & 0x3F));
+ len = 2;
+ }
+ else if (cp < 0x10000) {
+ utf8[0] = (char)(0xE0 | (cp >> 12));
+ utf8[1] = (char)(0x80 | ((cp >> 6) & 0x3F));
+ utf8[2] = (char)(0x80 | ( cp & 0x3F));
+ len = 3;
+ }
+ else {
+ utf8[0] = (char)(0xF0 | (cp >> 18));
+ utf8[1] = (char)(0x80 | ((cp >> 12) & 0x3F));
+ utf8[2] = (char)(0x80 | ((cp >> 6) & 0x3F));
+ utf8[3] = (char)(0x80 | ( cp & 0x3F));
+ len = 4;
+ }
+ return mrb_str_new(mrb, utf8, len);
+#else
+ char c;
+
+ if (cp < 0 || 0xff < cp) {
+ mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", num);
+ }
+ c = (char)cp;
+ return mrb_str_new(mrb, &c, 1);
+#endif
+}
+
/*
* call-seq:
* string.lines -> array of string
@@ -422,6 +467,72 @@ mrb_str_prepend(mrb_state *mrb, mrb_value self)
return self;
}
+#ifdef MRB_UTF8_STRING
+static const char utf8len_codepage_zero[256] =
+{
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,
+};
+
+static mrb_int
+utf8code(unsigned char* p)
+{
+ mrb_int len;
+
+ if (p[0] < 0x80)
+ return p[0];
+
+ len = utf8len_codepage_zero[p[0]];
+ if (len > 1 && (p[1] & 0xc0) == 0x80) {
+ if (len == 2)
+ return ((p[0] & 0x1f) << 6) + (p[1] & 0x3f);
+ if ((p[2] & 0xc0) == 0x80) {
+ if (len == 3)
+ return ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6)
+ + (p[2] & 0x3f);
+ if ((p[3] & 0xc0) == 0x80) {
+ if (len == 4)
+ return ((p[0] & 0x07) << 18) + ((p[1] & 0x3f) << 12)
+ + ((p[2] & 0x3f) << 6) + (p[3] & 0x3f);
+ if ((p[4] & 0xc0) == 0x80) {
+ if (len == 5)
+ return ((p[0] & 0x03) << 24) + ((p[1] & 0x3f) << 18)
+ + ((p[2] & 0x3f) << 12) + ((p[3] & 0x3f) << 6)
+ + (p[4] & 0x3f);
+ if ((p[5] & 0xc0) == 0x80 && len == 6)
+ return ((p[0] & 0x01) << 30) + ((p[1] & 0x3f) << 24)
+ + ((p[2] & 0x3f) << 18) + ((p[3] & 0x3f) << 12)
+ + ((p[4] & 0x3f) << 6) + (p[5] & 0x3f);
+ }
+ }
+ }
+ }
+ return p[0];
+}
+
+static mrb_value
+mrb_str_ord(mrb_state* mrb, mrb_value str)
+{
+ if (RSTRING_LEN(str) == 0)
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "empty string");
+ return mrb_fixnum_value(utf8code((unsigned char*) RSTRING_PTR(str)));
+}
+#else
+static mrb_value
+mrb_str_ord(mrb_state* mrb, mrb_value str)
+{
+ if (RSTRING_LEN(str) == 0)
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "empty string");
+ return mrb_fixnum_value(RSTRING_PTR(str)[0]);
+}
+#endif
+
void
mrb_mruby_string_ext_gem_init(mrb_state* mrb)
{
@@ -446,6 +557,9 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb)
mrb_define_method(mrb, s, "prepend", mrb_str_prepend, MRB_ARGS_REQ(1));
mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next"), mrb_intern_lit(mrb, "succ"));
mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next!"), mrb_intern_lit(mrb, "succ!"));
+ mrb_define_method(mrb, s, "ord", mrb_str_ord, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, mrb->fixnum_class, "chr", mrb_fixnum_chr, MRB_ARGS_NONE());
}
void
diff --git a/mrbgems/mruby-string-ext/test/string.rb b/mrbgems/mruby-string-ext/test/string.rb
index 5e4847f05..37a5d28cf 100644
--- a/mrbgems/mruby-string-ext/test/string.rb
+++ b/mrbgems/mruby-string-ext/test/string.rb
@@ -1,6 +1,15 @@
##
# String(Ext) Test
+UTF8STRING = ("\343\201\202".size == 1)
+
+assert('String.try_convert') do
+ assert_nil String.try_convert(nil)
+ assert_nil String.try_convert(:foo)
+ assert_equal "", String.try_convert("")
+ assert_equal "1,2,3", String.try_convert("1,2,3")
+end
+
assert('String#getbyte') do
str1 = "hello"
bytes1 = [104, 101, 108, 108, 111]
@@ -180,6 +189,8 @@ end
assert('String#chr') do
assert_equal "a", "abcde".chr
+ # test Fixnum#chr as well
+ assert_equal "a", 97.chr
end
assert('String#lines') do
@@ -374,8 +385,8 @@ assert('String#succ') do
assert_equal "-b-", a
a = "-z-"; a.succ!
assert_equal "-aa-", a
- a = "あa"; a.succ!
- assert_equal "あb", a
+ a = "あb"; a.succ!
+ assert_equal "あc", a
a = "あaz"; a.succ!
assert_equal "あba", a
end
@@ -471,3 +482,96 @@ assert('String#upto') do
})
assert_equal(2, count)
end
+
+assert('String#ord') do
+ got = "hello!".split('').map {|x| x.ord}
+ expect = [104, 101, 108, 108, 111, 33]
+ assert_equal expect, got
+end
+
+assert('String#ord(UTF-8)') do
+ got = "こんにちは世界!".split('').map {|x| x.ord}
+ expect = [0x3053,0x3093,0x306b,0x3061,0x306f,0x4e16,0x754c,0x21]
+ assert_equal expect, got
+end if UTF8STRING
+
+assert('String#chr') do
+ assert_equal "h", "hello!".chr
+end
+assert('String#chr(UTF-8)') do
+ assert_equal "こ", "こんにちは世界!".chr
+end if UTF8STRING
+
+assert('String#chars') do
+ expect = ["h", "e", "l", "l", "o", "!"]
+ assert_equal expect, "hello!".chars
+ s = ""
+ "hello!".chars do |x|
+ s += x
+ end
+ assert_equal "hello!", s
+end
+
+assert('String#chars(UTF-8)') do
+ expect = ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!']
+ assert_equal expect, "こんにちは世界!".chars
+ s = ""
+ "こんにちは世界!".chars do |x|
+ s += x
+ end
+ assert_equal "こんにちは世界!", s
+end if UTF8STRING
+
+assert('String#each_char') do
+ s = ""
+ "hello!".each_char do |x|
+ s += x
+ end
+ assert_equal "hello!", s
+end
+
+assert('String#each_char(UTF-8)') do
+ s = ""
+ "こんにちは世界!".each_char do |x|
+ s += x
+ end
+ assert_equal "こんにちは世界!", s
+end if UTF8STRING
+
+assert('String#codepoints') do
+ expect = [104, 101, 108, 108, 111, 33]
+ assert_equal expect, "hello!".codepoints
+ cp = []
+ "hello!".codepoints do |x|
+ cp << x
+ end
+ assert_equal expect, cp
+end
+
+assert('String#codepoints(UTF-8)') do
+ expect = [12371, 12435, 12395, 12385, 12399, 19990, 30028, 33]
+ assert_equal expect, "こんにちは世界!".codepoints
+ cp = []
+ "こんにちは世界!".codepoints do |x|
+ cp << x
+ end
+ assert_equal expect, cp
+end if UTF8STRING
+
+assert('String#each_codepoint') do
+ expect = [104, 101, 108, 108, 111, 33]
+ cp = []
+ "hello!".each_codepoint do |x|
+ cp << x
+ end
+ assert_equal expect, cp
+end
+
+assert('String#each_codepoint(UTF-8)') do
+ expect = [12371, 12435, 12395, 12385, 12399, 19990, 30028, 33]
+ cp = []
+ "こんにちは世界!".each_codepoint do |x|
+ cp << x
+ end
+ assert_equal expect, cp
+end if UTF8STRING
diff --git a/mrbgems/mruby-string-utf8/mrbgem.rake b/mrbgems/mruby-string-utf8/mrbgem.rake
deleted file mode 100644
index 7642d4e07..000000000
--- a/mrbgems/mruby-string-utf8/mrbgem.rake
+++ /dev/null
@@ -1,6 +0,0 @@
-MRuby::Gem::Specification.new('mruby-string-utf8') do |spec|
- spec.license = 'MIT'
- spec.author = 'mruby developers'
- spec.summary = 'UTF-8 support in String class'
- spec.add_dependency('mruby-string-ext', :core => 'mruby-string-ext')
-end
diff --git a/mrbgems/mruby-string-utf8/src/string.c b/mrbgems/mruby-string-utf8/src/string.c
deleted file mode 100644
index 25a638ea3..000000000
--- a/mrbgems/mruby-string-utf8/src/string.c
+++ /dev/null
@@ -1,731 +0,0 @@
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/class.h"
-#include "mruby/string.h"
-#include "mruby/range.h"
-#include "mruby/numeric.h"
-#include "mruby/re.h"
-#include <string.h>
-
-static const char utf8len_codepage[256] =
-{
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
- 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,
-};
-
-static const char utf8len_codepage_zero[256] =
-{
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
- 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,
-};
-
-static mrb_int
-utf8code(unsigned char* p)
-{
- mrb_int len;
-
- if (p[0] < 0x80)
- return p[0];
-
- len = utf8len_codepage_zero[p[0]];
- if (len > 1 && (p[1] & 0xc0) == 0x80) {
- if (len == 2)
- return ((p[0] & 0x1f) << 6) + (p[1] & 0x3f);
- if ((p[2] & 0xc0) == 0x80) {
- if (len == 3)
- return ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6)
- + (p[2] & 0x3f);
- if ((p[3] & 0xc0) == 0x80) {
- if (len == 4)
- return ((p[0] & 0x07) << 18) + ((p[1] & 0x3f) << 12)
- + ((p[2] & 0x3f) << 6) + (p[3] & 0x3f);
- if ((p[4] & 0xc0) == 0x80) {
- if (len == 5)
- return ((p[0] & 0x03) << 24) + ((p[1] & 0x3f) << 18)
- + ((p[2] & 0x3f) << 12) + ((p[3] & 0x3f) << 6)
- + (p[4] & 0x3f);
- if ((p[5] & 0xc0) == 0x80 && len == 6)
- return ((p[0] & 0x01) << 30) + ((p[1] & 0x3f) << 24)
- + ((p[2] & 0x3f) << 18) + ((p[3] & 0x3f) << 12)
- + ((p[4] & 0x3f) << 6) + (p[5] & 0x3f);
- }
- }
- }
- }
- return p[0];
-}
-
-static mrb_value mrb_fixnum_chr(mrb_state*, mrb_value);
-
-static mrb_int
-utf8len(unsigned char* p)
-{
- mrb_int len;
- mrb_int i;
-
- if (*p == 0)
- return 1;
- len = utf8len_codepage[*p];
- for (i = 1; i < len; ++i)
- if ((p[i] & 0xc0) != 0x80)
- return 1;
- return len;
-}
-
-static mrb_int
-mrb_utf8_strlen(mrb_value str, mrb_int len)
-{
- mrb_int total = 0;
- unsigned char* p = (unsigned char*) RSTRING_PTR(str);
- unsigned char* e = p;
- e += len < 0 ? RSTRING_LEN(str) : len;
- while (p<e) {
- p += utf8len(p);
- total++;
- }
- return total;
-}
-
-static mrb_value
-mrb_str_size(mrb_state *mrb, mrb_value str)
-{
- return mrb_fixnum_value(mrb_utf8_strlen(str, -1));
-}
-
-#define RSTRING_LEN_UTF8(s) mrb_utf8_strlen(s, -1)
-
-static inline mrb_int
-mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n)
-{
- const unsigned char *x = xs, *xe = xs + m;
- const unsigned char *y = ys;
- int i, qstable[256];
-
- /* Preprocessing */
- for (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 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;
- }
- else if (m < 1) {
- return 0;
- }
- else if (m == 1) {
- const unsigned char *ys = y, *ye = ys + n;
- for (; y < ye; ++y) {
- if (*x == *y)
- return y - ys;
- }
- return -1;
- }
- return mrb_memsearch_qs((const unsigned char *)x0, m, (const unsigned char *)y0, n);
-}
-
-static mrb_value
-str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
-{
- mrb_int i;
- unsigned char *p = (unsigned char*) RSTRING_PTR(str), *t;
- unsigned char *e = p + RSTRING_LEN(str);
-
- for (i = 0; i < beg && p<e; i++) {
- p += utf8len(p);
- }
- t = p;
- for (i = 0; i < len && t<e; i++) {
- t += utf8len(t);
- }
- return mrb_str_new(mrb, (const char*)p, (size_t)(t - p));
-}
-
-static mrb_value
-str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
-{
- mrb_value str2;
- mrb_int len8 = RSTRING_LEN_UTF8(str);
-
- if (len < 0) return mrb_nil_value();
- if (len8 == 0) {
- len = 0;
- }
- else if (beg < 0) {
- beg = len8 + beg;
- }
- if (beg > len8) return mrb_nil_value();
- if (beg < 0) {
- beg += len8;
- if (beg < 0) return mrb_nil_value();
- }
- if (beg + len > len8)
- len = len8 - beg;
- if (len <= 0) {
- len = 0;
- }
- str2 = str_subseq(mrb, str, beg, len);
-
- return str2;
-}
-
-static mrb_int
-str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset)
-{
- mrb_int pos;
- char *s, *sptr;
- mrb_int len, slen;
-
- len = RSTRING_LEN(str);
- slen = RSTRING_LEN(sub);
- if (offset < 0) {
- offset += len;
- if (offset < 0) return -1;
- }
- if (len - offset < slen) return -1;
- s = RSTRING_PTR(str);
- if (offset) {
- s += offset;
- }
- if (slen == 0) return offset;
- /* need proceed one character at a time */
- sptr = RSTRING_PTR(sub);
- slen = RSTRING_LEN(sub);
- len = RSTRING_LEN(str) - offset;
- pos = mrb_memsearch(sptr, slen, s, len);
- if (pos < 0) return pos;
- return pos + offset;
-}
-
-static mrb_int
-str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
-{
- char *s, *sbeg, *t;
- struct RString *ps = mrb_str_ptr(str);
- mrb_int len = RSTRING_LEN(sub);
-
- /* substring longer than string */
- if (RSTR_LEN(ps) < len) return -1;
- if (RSTR_LEN(ps) - pos < len) {
- pos = RSTR_LEN(ps) - len;
- }
- sbeg = RSTR_PTR(ps);
- s = RSTR_PTR(ps) + pos;
- t = RSTRING_PTR(sub);
- if (len) {
- while (sbeg <= s) {
- if (memcmp(s, t, len) == 0) {
- return s - RSTR_PTR(ps);
- }
- s--;
- }
- return -1;
- }
- else {
- return pos;
- }
-}
-
-static mrb_value
-mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value indx)
-{
- mrb_int idx;
-
- mrb_regexp_check(mrb, indx);
- switch (mrb_type(indx)) {
- case MRB_TT_FLOAT:
- indx = mrb_flo_to_fixnum(mrb, indx);
- /* fall through */
- case MRB_TT_FIXNUM:
- idx = mrb_fixnum(indx);
-
-num_index:
- str = str_substr(mrb, str, idx, 1);
- if (!mrb_nil_p(str) && RSTRING_LEN(str) == 0) return mrb_nil_value();
- return str;
-
- case MRB_TT_STRING:
- if (str_index(mrb, str, indx, 0) != -1)
- return mrb_str_dup(mrb, indx);
- return mrb_nil_value();
-
- case MRB_TT_RANGE:
- /* check if indx is Range */
- {
- mrb_int beg, len;
- mrb_value tmp;
-
- len = RSTRING_LEN_UTF8(str);
- if (mrb_range_beg_len(mrb, indx, &beg, &len, len)) {
- tmp = str_subseq(mrb, str, beg, len);
- return tmp;
- }
- else {
- return mrb_nil_value();
- }
- }
- default:
- idx = mrb_fixnum(indx);
- goto num_index;
- }
- return mrb_nil_value(); /* not reached */
-}
-
-static mrb_value
-mrb_str_aref_m(mrb_state *mrb, mrb_value str)
-{
- mrb_value a1, a2;
- int argc;
-
- argc = mrb_get_args(mrb, "o|o", &a1, &a2);
- if (argc == 2) {
- mrb_regexp_check(mrb, a1);
- return str_substr(mrb, str, mrb_fixnum(a1), mrb_fixnum(a2));
- }
- if (argc != 1) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1)", mrb_fixnum_value(argc));
- }
- return mrb_str_aref(mrb, str, a1);
-}
-
-static mrb_value
-mrb_str_index_m(mrb_state *mrb, mrb_value str)
-{
- mrb_value *argv;
- mrb_int argc;
-
- mrb_value sub;
- mrb_int pos;
-
- mrb_get_args(mrb, "*", &argv, &argc);
- if (argc == 2) {
- pos = mrb_fixnum(argv[1]);
- sub = argv[0];
- }
- else {
- pos = 0;
- if (argc > 0)
- sub = argv[0];
- else
- sub = mrb_nil_value();
-
- }
- mrb_regexp_check(mrb, sub);
- if (pos < 0) {
- pos += RSTRING_LEN(str);
- if (pos < 0) {
- return mrb_nil_value();
- }
- }
-
- if (mrb_type(sub) == MRB_TT_FIXNUM) {
- sub = mrb_fixnum_chr(mrb, sub);
- }
-
- switch (mrb_type(sub)) {
- default: {
- mrb_value tmp;
-
- tmp = mrb_check_string_type(mrb, sub);
- if (mrb_nil_p(tmp)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %S given", sub);
- }
- sub = tmp;
- }
- /* fall through */
- case MRB_TT_STRING:
- pos = str_index(mrb, str, sub, pos);
- break;
- }
-
- if (pos == -1) return mrb_nil_value();
- return mrb_fixnum_value(mrb_utf8_strlen(str, pos));
-}
-
-static mrb_value
-mrb_str_reverse_bang(mrb_state *mrb, mrb_value str)
-{
- mrb_int utf8_len = mrb_utf8_strlen(str, -1);
- if (utf8_len > 1) {
- mrb_int len;
- char *buf;
- unsigned char *p, *e, *r;
-
- mrb_str_modify(mrb, mrb_str_ptr(str));
- len = RSTRING_LEN(str);
- buf = (char *)mrb_malloc(mrb, (size_t)len);
- p = (unsigned char*)buf;
- e = (unsigned char*)buf + len;
-
- memcpy(buf, RSTRING_PTR(str), len);
- r = (unsigned char*)RSTRING_PTR(str) + len;
-
- while (p<e) {
- mrb_int clen = utf8len(p);
- r -= clen;
- memcpy(r, p, clen);
- p += clen;
- }
- mrb_free(mrb, buf);
- }
-
- return str;
-}
-
-static mrb_value
-mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
-{
- mrb_value *argv;
- mrb_int argc;
- mrb_value sub;
- mrb_value vpos;
- mrb_int pos, len = RSTRING_LEN(str);
-
- mrb_get_args(mrb, "*", &argv, &argc);
- if (argc == 2) {
- sub = argv[0];
- vpos = argv[1];
- pos = mrb_fixnum(vpos);
- if (pos < 0) {
- pos += len;
- if (pos < 0) {
- mrb_regexp_check(mrb, sub);
- return mrb_nil_value();
- }
- }
- if (pos > len) pos = len;
- }
- else {
- pos = len;
- if (argc > 0)
- sub = argv[0];
- else
- sub = mrb_nil_value();
- }
- mrb_regexp_check(mrb, sub);
-
- if (mrb_type(sub) == MRB_TT_FIXNUM) {
- sub = mrb_fixnum_chr(mrb, sub);
- }
-
- switch (mrb_type(sub)) {
- default: {
- mrb_value tmp;
-
- tmp = mrb_check_string_type(mrb, sub);
- if (mrb_nil_p(tmp)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %S given", sub);
- }
- sub = tmp;
- }
- /* fall through */
- case MRB_TT_STRING:
- pos = str_rindex(mrb, str, sub, pos);
- break;
- }
-
- if (pos == -1) return mrb_nil_value();
- return mrb_fixnum_value(mrb_utf8_strlen(str, pos));
-}
-
-static mrb_value
-mrb_str_reverse(mrb_state *mrb, mrb_value str)
-{
- return mrb_str_reverse_bang(mrb, mrb_str_dup(mrb, str));
-}
-
-static mrb_value
-mrb_fixnum_chr(mrb_state *mrb, mrb_value num)
-{
- mrb_int cp = mrb_fixnum(num);
- char utf8[4];
- mrb_int len;
-
- if (cp < 0 || 0x10FFFF < cp) {
- mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", num);
- }
- if (cp < 0x80) {
- utf8[0] = (char)cp;
- len = 1;
- }
- else if (cp < 0x800) {
- utf8[0] = (char)(0xC0 | (cp >> 6));
- utf8[1] = (char)(0x80 | (cp & 0x3F));
- len = 2;
- }
- else if (cp < 0x10000) {
- utf8[0] = (char)(0xE0 | (cp >> 12));
- utf8[1] = (char)(0x80 | ((cp >> 6) & 0x3F));
- utf8[2] = (char)(0x80 | ( cp & 0x3F));
- len = 3;
- }
- else {
- utf8[0] = (char)(0xF0 | (cp >> 18));
- utf8[1] = (char)(0x80 | ((cp >> 12) & 0x3F));
- utf8[2] = (char)(0x80 | ((cp >> 6) & 0x3F));
- utf8[3] = (char)(0x80 | ( cp & 0x3F));
- len = 4;
- }
- return mrb_str_new(mrb, utf8, len);
-}
-
-static mrb_value
-mrb_str_ord(mrb_state* mrb, mrb_value str)
-{
- mrb_int len = RSTRING_LEN(str);
-
- if (len == 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "empty string");
- return mrb_fixnum_value(utf8code((unsigned char*) RSTRING_PTR(str)));
-}
-
-static mrb_value
-mrb_str_split_m(mrb_state *mrb, mrb_value str)
-{
- int argc;
- mrb_value spat = mrb_nil_value();
- enum {awk, string, regexp} split_type = string;
- long i = 0, lim_p;
- mrb_int beg;
- mrb_int end;
- mrb_int lim = 0;
- mrb_value result, tmp;
-
- argc = mrb_get_args(mrb, "|oi", &spat, &lim);
- lim_p = (lim > 0 && argc == 2);
- if (argc == 2) {
- if (lim == 1) {
- if (RSTRING_LEN(str) == 0)
- return mrb_ary_new_capa(mrb, 0);
- return mrb_ary_new_from_values(mrb, 1, &str);
- }
- i = 1;
- }
-
- if (argc == 0 || mrb_nil_p(spat)) {
- split_type = awk;
- }
- else {
- if (mrb_string_p(spat)) {
- split_type = string;
- if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' '){
- split_type = awk;
- }
- }
- else {
- mrb_noregexp(mrb, str);
- }
- }
-
- result = mrb_ary_new(mrb);
- beg = 0;
- if (split_type == awk) {
- char *ptr = RSTRING_PTR(str);
- char *eptr = RSTRING_END(str);
- char *bptr = ptr;
- int skip = 1;
- unsigned int c;
-
- end = beg;
- while (ptr < eptr) {
- int ai = mrb_gc_arena_save(mrb);
- c = (unsigned char)*ptr++;
- if (skip) {
- if (ISSPACE(c)) {
- beg = ptr - bptr;
- }
- else {
- end = ptr - bptr;
- skip = 0;
- if (lim_p && lim <= i) break;
- }
- }
- else if (ISSPACE(c)) {
- mrb_ary_push(mrb, result, str_subseq(mrb, str, beg, end-beg));
- mrb_gc_arena_restore(mrb, ai);
- skip = 1;
- beg = ptr - bptr;
- if (lim_p) ++i;
- }
- else {
- end = ptr - bptr;
- }
- }
- }
- else if (split_type == string) {
- char *ptr = RSTRING_PTR(str); // s->as.ary
- char *temp = ptr;
- char *eptr = RSTRING_END(str);
- mrb_int slen = RSTRING_LEN(spat);
-
- if (slen == 0) {
- int ai = mrb_gc_arena_save(mrb);
- while (ptr < eptr) {
- mrb_ary_push(mrb, result, str_subseq(mrb, str, ptr-temp, 1));
- mrb_gc_arena_restore(mrb, ai);
- ptr++;
- if (lim_p && lim <= ++i) break;
- }
- }
- else {
- char *sptr = RSTRING_PTR(spat);
- int ai = mrb_gc_arena_save(mrb);
-
- while (ptr < eptr &&
- (end = mrb_memsearch(sptr, slen, ptr, eptr - ptr)) >= 0) {
- /* mrb_ary_push(mrb, result, str_subseq(mrb, str, ptr - temp, end)); */
- mrb_ary_push(mrb, result, mrb_str_new(mrb, ptr, end));
- mrb_gc_arena_restore(mrb, ai);
- ptr += end + slen;
- if (lim_p && lim <= ++i) break;
- }
- }
- beg = ptr - temp;
- }
- else {
- mrb_noregexp(mrb, str);
- }
- if (RSTRING_LEN(str) > 0 && (lim_p || RSTRING_LEN(str) > beg || lim < 0)) {
- if (RSTRING_LEN(str) == beg) {
- tmp = mrb_str_new_lit(mrb, "");
- }
- else {
- tmp = mrb_str_new(mrb, RSTRING_PTR(str)+beg, RSTRING_LEN(str)-beg);
- }
- mrb_ary_push(mrb, result, tmp);
- }
- if (!lim_p && lim == 0) {
- mrb_int len;
- while ((len = RARRAY_LEN(result)) > 0 &&
- (tmp = RARRAY_PTR(result)[len-1], RSTRING_LEN(tmp) == 0))
- mrb_ary_pop(mrb, result);
- }
-
- return result;
-}
-
-static mrb_value
-mrb_str_chr(mrb_state *mrb, mrb_value self)
-{
- return str_substr(mrb, self, 0, 1);
-}
-
-static mrb_value
-mrb_str_chars(mrb_state *mrb, mrb_value self)
-{
- mrb_value result;
- mrb_value blk;
- int ai;
- mrb_int len;
- mrb_value arg;
- char *p = RSTRING_PTR(self);
- char *e = p + RSTRING_LEN(self);
-
- mrb_get_args(mrb, "&", &blk);
-
- result = mrb_ary_new(mrb);
-
- if (!mrb_nil_p(blk)) {
- while (p < e) {
- len = utf8len((unsigned char*) p);
- arg = mrb_str_new(mrb, p, len);
- mrb_yield_argv(mrb, blk, 1, &arg);
- p += len;
- }
- return self;
- }
- while (p < e) {
- ai = mrb_gc_arena_save(mrb);
- len = utf8len((unsigned char*) p);
- mrb_ary_push(mrb, result, mrb_str_new(mrb, p, len));
- mrb_gc_arena_restore(mrb, ai);
- p += len;
- }
- return result;
-}
-
-static mrb_value
-mrb_str_codepoints(mrb_state *mrb, mrb_value self)
-{
- mrb_value result;
- mrb_value blk;
- int ai;
- mrb_int len;
- mrb_value arg;
- char *p = RSTRING_PTR(self);
- char *e = p + RSTRING_LEN(self);
-
- mrb_get_args(mrb, "&", &blk);
-
- result = mrb_ary_new(mrb);
-
- if (!mrb_nil_p(blk)) {
- while (p < e) {
- len = utf8len((unsigned char*) p);
- arg = mrb_fixnum_value(utf8code((unsigned char*) p));
- mrb_yield_argv(mrb, blk, 1, &arg);
- p += len;
- }
- return self;
- }
- while (p < e) {
- ai = mrb_gc_arena_save(mrb);
- len = utf8len((unsigned char*) p);
- mrb_ary_push(mrb, result, mrb_fixnum_value(utf8code((unsigned char*) p)));
- mrb_gc_arena_restore(mrb, ai);
- p += len;
- }
- return result;
-}
-
-void
-mrb_mruby_string_utf8_gem_init(mrb_state* mrb)
-{
- struct RClass * s = mrb->string_class;
-
- mrb_define_method(mrb, s, "size", mrb_str_size, MRB_ARGS_NONE());
- mrb_define_method(mrb, s, "length", mrb_str_size, MRB_ARGS_NONE());
- mrb_define_method(mrb, s, "index", mrb_str_index_m, MRB_ARGS_ANY());
- mrb_define_method(mrb, s, "[]", mrb_str_aref_m, MRB_ARGS_ANY());
- mrb_define_method(mrb, s, "ord", mrb_str_ord, MRB_ARGS_NONE());
- mrb_define_method(mrb, s, "slice", mrb_str_aref_m, MRB_ARGS_ANY());
- mrb_define_method(mrb, s, "split", mrb_str_split_m, MRB_ARGS_ANY());
- mrb_define_method(mrb, s, "reverse", mrb_str_reverse, MRB_ARGS_NONE());
- mrb_define_method(mrb, s, "reverse!", mrb_str_reverse_bang, MRB_ARGS_NONE());
- mrb_define_method(mrb, s, "rindex", mrb_str_rindex_m, MRB_ARGS_ANY());
- mrb_define_method(mrb, s, "chr", mrb_str_chr, MRB_ARGS_NONE());
- mrb_define_method(mrb, s, "chars", mrb_str_chars, MRB_ARGS_NONE());
- mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "each_char"), mrb_intern_lit(mrb, "chars"));
- mrb_define_method(mrb, s, "codepoints", mrb_str_codepoints, MRB_ARGS_NONE());
- mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "each_codepoint"), mrb_intern_lit(mrb, "codepoints"));
-
- mrb_define_method(mrb, mrb->fixnum_class, "chr", mrb_fixnum_chr, MRB_ARGS_NONE());
-}
-
-void
-mrb_mruby_string_utf8_gem_final(mrb_state* mrb)
-{
-}
diff --git a/mrbgems/mruby-string-utf8/test/string.rb b/mrbgems/mruby-string-utf8/test/string.rb
deleted file mode 100644
index 551273106..000000000
--- a/mrbgems/mruby-string-utf8/test/string.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-# -*- coding: utf-8 -*-
-##
-# String(utf8) Test
-
-assert('String#[]') do
- assert_equal "ち", "こんにちは世界"[3]
- assert_equal nil, "こんにちは世界"[20]
- assert_equal "世", "こんにちは世界"[-2]
- assert_equal "世界", "こんにちは世界"[-2..-1]
- assert_equal "んに", "こんにちは世界"[1,2]
- assert_equal "世", "こんにちは世界"["世"]
- assert_equal 'b', 'abc'[1.1]
-end
-
-assert('String#reverse', '15.2.10.5.29') do
- a = 'こんにちは世界!'
- a.reverse
-
- assert_equal 'こんにちは世界!', a
- assert_equal '!界世はちにんこ', 'こんにちは世界!'.reverse
-end
-
-assert('String#reverse!', '15.2.10.5.30') do
- a = 'こんにちは世界!'
- a.reverse!
-
- assert_equal '!界世はちにんこ', a
- assert_equal '!界世はちにんこ', 'こんにちは世界!'.reverse!
-end
-
-assert('Invalid sequence') do
- assert_equal 5, "\xF8\x88\x80\x80\x80".size
- assert_equal 6, "\xFC\x84\x80\x80\x80\x80".size
-end
-
-assert('String#size') do
- str = 'こんにちは世界!'
- assert_equal 8, str.size
- assert_not_equal str.bytesize, str.size
- assert_equal 2, str[1, 2].size
-end
-
-assert('String#index') do
- str = "こんにちは世界!\nこんにちは世界!"
- assert_nil str.index('さ')
- assert_equal 3, str.index('ち')
- assert_equal 12, str.index('ち', 10)
- assert_equal nil, str.index("さ")
-end
-
-assert('String#ord') do
- got = "こんにちは世界!".split('').map {|x| x.ord}
- expect = [0x3053,0x3093,0x306b,0x3061,0x306f,0x4e16,0x754c,0x21]
- assert_equal expect, got
-end
-
-assert('String#split') do
- got = "こんにちは世界!".split('')
- assert_equal ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!'], got
- got = "こんにちは世界!".split('に')
- assert_equal ['こん', 'ちは世界!'], got
-end
-
-assert('String#rindex') do
- str = "こんにちは世界!\nこんにちは世界!"
- assert_nil str.index('さ')
- assert_equal 12, str.rindex('ち')
- assert_equal 3, str.rindex('ち', 10)
-end
-
-assert('String#chr(utf-8)') do
- assert_equal "こ", "こんにちは世界!".chr
-end
-
-assert('String#chars') do
- expect = ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!']
- assert_equal expect, "こんにちは世界!".chars
- s = ""
- "こんにちは世界!".chars do |x|
- s += x
- end
- assert_equal "こんにちは世界!", s
-end
-
-assert('String#each_char') do
- expect = ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!']
- s = ""
- "こんにちは世界!".each_char do |x|
- s += x
- end
- assert_equal "こんにちは世界!", s
-end
-assert('String#codepoints') do
- expect = [12371, 12435, 12395, 12385, 12399, 19990, 30028, 33]
- assert_equal expect, "こんにちは世界!".codepoints
- cp = []
- "こんにちは世界!".codepoints do |x|
- cp << x
- end
- assert_equal expect, cp
-end
-
-assert('String#each_codepoint') do
- expect = [12371, 12435, 12395, 12385, 12399, 19990, 30028, 33]
- cp = []
- "こんにちは世界!".each_codepoint do |x|
- cp << x
- end
- assert_equal expect, cp
-end
diff --git a/mrbgems/mruby-struct/mrblib/struct.rb b/mrbgems/mruby-struct/mrblib/struct.rb
index 57f100acd..1445392f3 100644
--- a/mrbgems/mruby-struct/mrblib/struct.rb
+++ b/mrbgems/mruby-struct/mrblib/struct.rb
@@ -47,7 +47,12 @@ if Object.const_defined?(:Struct)
end
def _inspect
- str = "#<struct #{self.class.to_s} "
+ name = self.class.to_s
+ if name[0] == "#"
+ str = "#<struct "
+ else
+ str = "#<struct #{name} "
+ end
buf = []
self.each_pair do |k,v|
buf.push [k.to_s + "=" + v._inspect]
diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c
index ce8d8d832..17455c155 100644
--- a/mrbgems/mruby-struct/src/struct.c
+++ b/mrbgems/mruby-struct/src/struct.c
@@ -5,13 +5,13 @@
*/
#include <string.h>
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/string.h"
-#include "mruby/class.h"
-#include "mruby/variable.h"
-#include "mruby/hash.h"
-#include "mruby/range.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/string.h>
+#include <mruby/class.h>
+#include <mruby/variable.h>
+#include <mruby/hash.h>
+#include <mruby/range.h>
#define RSTRUCT_LEN(st) mrb_ary_ptr(st)->len
#define RSTRUCT_PTR(st) mrb_ary_ptr(st)->ptr
@@ -40,9 +40,9 @@ struct_ivar_get(mrb_state *mrb, mrb_value c, mrb_sym id)
}
static mrb_value
-mrb_struct_s_members(mrb_state *mrb, mrb_value klass)
+struct_s_members(mrb_state *mrb, struct RClass *klass)
{
- mrb_value members = struct_ivar_get(mrb, klass, mrb_intern_lit(mrb, "__members__"));
+ mrb_value members = struct_ivar_get(mrb, mrb_obj_value(klass), mrb_intern_lit(mrb, "__members__"));
if (mrb_nil_p(members)) {
mrb_raise(mrb, E_TYPE_ERROR, "uninitialized struct");
@@ -54,15 +54,16 @@ mrb_struct_s_members(mrb_state *mrb, mrb_value klass)
}
static mrb_value
-mrb_struct_members(mrb_state *mrb, mrb_value s)
-{
- mrb_value members = mrb_struct_s_members(mrb, mrb_obj_value(mrb_obj_class(mrb, s)));
- if (!strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s)), "Struct")) {
- if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
- mrb_raisef(mrb, E_TYPE_ERROR,
- "struct size differs (%S required %S given)",
- mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s)));
- }
+struct_members(mrb_state *mrb, mrb_value s)
+{
+ mrb_value members = struct_s_members(mrb, mrb_obj_class(mrb, s));
+ if (!mrb_array_p(s)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "corrupted struct");
+ }
+ if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
+ mrb_raisef(mrb, E_TYPE_ERROR,
+ "struct size differs (%S required %S given)",
+ mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s)));
}
return members;
}
@@ -72,7 +73,7 @@ mrb_struct_s_members_m(mrb_state *mrb, mrb_value klass)
{
mrb_value members, ary;
- members = mrb_struct_s_members(mrb, klass);
+ members = struct_s_members(mrb, mrb_class_ptr(klass));
ary = mrb_ary_new_capa(mrb, RARRAY_LEN(members));
mrb_ary_replace(mrb, ary, members);
return ary;
@@ -92,7 +93,7 @@ mrb_struct_s_members_m(mrb_state *mrb, mrb_value klass)
*/
static mrb_value
-mrb_struct_members_m(mrb_state *mrb, mrb_value obj)
+mrb_struct_members(mrb_state *mrb, mrb_value obj)
{
return mrb_struct_s_members_m(mrb, mrb_obj_value(mrb_obj_class(mrb, obj)));
}
@@ -105,7 +106,7 @@ mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id)
mrb_int i, len;
ptr = RSTRUCT_PTR(obj);
- members = mrb_struct_members(mrb, obj);
+ members = struct_members(mrb, obj);
ptr_members = RARRAY_PTR(members);
slot = mrb_symbol_value(id);
len = RARRAY_LEN(members);
@@ -183,7 +184,7 @@ mrb_struct_set(mrb_state *mrb, mrb_value obj, mrb_value val)
name = mrb_sym2name_len(mrb, mrb->c->ci->mid, &slen);
mid = mrb_intern(mrb, name, slen-1); /* omit last "=" */
- members = mrb_struct_members(mrb, obj);
+ members = struct_members(mrb, obj);
ptr_members = RARRAY_PTR(members);
len = RARRAY_LEN(members);
ptr = RSTRUCT_PTR(obj);
@@ -402,7 +403,7 @@ mrb_struct_initialize_withArg(mrb_state *mrb, mrb_int argc, mrb_value *argv, mrb
}
static mrb_value
-mrb_struct_initialize_m(mrb_state *mrb, /*int argc, mrb_value *argv,*/ mrb_value self)
+mrb_struct_initialize(mrb_state *mrb, mrb_value self)
{
mrb_value *argv;
mrb_int argc;
@@ -446,7 +447,7 @@ struct_aref_sym(mrb_state *mrb, mrb_value s, mrb_sym id)
mrb_int i, len;
ptr = RSTRUCT_PTR(s);
- members = mrb_struct_members(mrb, s);
+ members = struct_members(mrb, s);
ptr_members = RARRAY_PTR(members);
len = RARRAY_LEN(members);
for (i=0; i<len; i++) {
@@ -519,7 +520,7 @@ mrb_struct_aset_sym(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val)
const mrb_value *ptr_members;
mrb_int i, len;
- members = mrb_struct_members(mrb, s);
+ members = struct_members(mrb, s);
len = RARRAY_LEN(members);
if (RSTRUCT_LEN(s) != len) {
mrb_raisef(mrb, E_TYPE_ERROR,
@@ -625,8 +626,7 @@ mrb_struct_equal(mrb_state *mrb, mrb_value s)
if (mrb_obj_equal(mrb, s, s2)) {
return mrb_true_value();
}
- if (!strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s)), "Struct") ||
- mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) {
+ if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) {
return mrb_false_value();
}
if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
@@ -663,8 +663,7 @@ mrb_struct_eql(mrb_state *mrb, mrb_value s)
if (mrb_obj_equal(mrb, s, s2)) {
return mrb_true_value();
}
- if (strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s2)), "Struct") ||
- mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) {
+ if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) {
return mrb_false_value();
}
if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
@@ -720,7 +719,7 @@ mrb_struct_to_h(mrb_state *mrb, mrb_value self)
mrb_value members, ret;
mrb_int i;
- members = mrb_struct_s_members(mrb, mrb_obj_value(mrb_class(mrb, self)));
+ members = struct_s_members(mrb, mrb_class(mrb, self));
ret = mrb_hash_new_capa(mrb, RARRAY_LEN(members));
for (i = 0; i < RARRAY_LEN(members); ++i) {
@@ -767,8 +766,8 @@ mrb_mruby_struct_gem_init(mrb_state* mrb)
mrb_define_method(mrb, st, "==", mrb_struct_equal, MRB_ARGS_REQ(1)); /* 15.2.18.4.1 */
mrb_define_method(mrb, st, "[]", mrb_struct_aref, MRB_ARGS_REQ(1)); /* 15.2.18.4.2 */
mrb_define_method(mrb, st, "[]=", mrb_struct_aset, MRB_ARGS_REQ(2)); /* 15.2.18.4.3 */
- mrb_define_method(mrb, st, "members", mrb_struct_members_m, MRB_ARGS_NONE()); /* 15.2.18.4.6 */
- mrb_define_method(mrb, st, "initialize", mrb_struct_initialize_m,MRB_ARGS_ANY()); /* 15.2.18.4.8 */
+ mrb_define_method(mrb, st, "members", mrb_struct_members, MRB_ARGS_NONE()); /* 15.2.18.4.6 */
+ mrb_define_method(mrb, st, "initialize", mrb_struct_initialize, MRB_ARGS_ANY()); /* 15.2.18.4.8 */
mrb_define_method(mrb, st, "initialize_copy", mrb_struct_init_copy, MRB_ARGS_REQ(1)); /* 15.2.18.4.9 */
mrb_define_method(mrb, st, "eql?", mrb_struct_eql, MRB_ARGS_REQ(1)); /* 15.2.18.4.12(x) */
diff --git a/mrbgems/mruby-struct/test/struct.rb b/mrbgems/mruby-struct/test/struct.rb
index 911e657bd..2db8f5d32 100644
--- a/mrbgems/mruby-struct/test/struct.rb
+++ b/mrbgems/mruby-struct/test/struct.rb
@@ -103,7 +103,7 @@ end
assert('struct inspect') do
c = Struct.new(:m1, :m2, :m3, :m4, :m5)
cc = c.new(1,2,3,4,5)
- assert_equal "#<struct #{c.inspect} m1=1, m2=2, m3=3, m4=4, m5=5>", cc.inspect
+ assert_equal "#<struct m1=1, m2=2, m3=3, m4=4, m5=5>", cc.inspect
end
assert('Struct#length, Struct#size') do
diff --git a/mrbgems/mruby-symbol-ext/src/symbol.c b/mrbgems/mruby-symbol-ext/src/symbol.c
index a96c4017f..a992dbfce 100644
--- a/mrbgems/mruby-symbol-ext/src/symbol.c
+++ b/mrbgems/mruby-symbol-ext/src/symbol.c
@@ -1,6 +1,6 @@
-#include "mruby.h"
-#include "mruby/khash.h"
-#include "mruby/array.h"
+#include <mruby.h>
+#include <mruby/khash.h>
+#include <mruby/array.h>
typedef struct symbol_name {
size_t len;
diff --git a/mrbgems/mruby-test/driver.c b/mrbgems/mruby-test/driver.c
index 7f0633723..7cc5211f0 100644
--- a/mrbgems/mruby-test/driver.c
+++ b/mrbgems/mruby-test/driver.c
@@ -10,13 +10,13 @@
#include <stdlib.h>
#include <string.h>
-#include "mruby.h"
-#include "mruby/proc.h"
-#include "mruby/data.h"
-#include "mruby/compile.h"
-#include "mruby/string.h"
-#include "mruby/variable.h"
-#include "mruby/array.h"
+#include <mruby.h>
+#include <mruby/proc.h>
+#include <mruby/data.h>
+#include <mruby/compile.h>
+#include <mruby/string.h>
+#include <mruby/variable.h>
+#include <mruby/array.h>
void
mrb_init_mrbtest(mrb_state *);
diff --git a/mrbgems/mruby-test/init_mrbtest.c b/mrbgems/mruby-test/init_mrbtest.c
index 1e2ba92bd..17ac1bdef 100644
--- a/mrbgems/mruby-test/init_mrbtest.c
+++ b/mrbgems/mruby-test/init_mrbtest.c
@@ -1,10 +1,9 @@
#include <stdlib.h>
-#include "mruby.h"
-#include "mruby/irep.h"
-#include "mruby/variable.h"
+#include <mruby.h>
+#include <mruby/irep.h>
+#include <mruby/variable.h>
extern const uint8_t mrbtest_assert_irep[];
-extern const uint8_t mrbtest_irep[];
void mrbgemtest_init(mrb_state* mrb);
void mrb_init_test_driver(mrb_state* mrb, mrb_bool verbose);
@@ -24,7 +23,6 @@ mrb_init_mrbtest(mrb_state *mrb)
}
mrb_init_test_driver(core_test, mrb_test(mrb_gv_get(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose"))));
mrb_load_irep(core_test, mrbtest_assert_irep);
- mrb_load_irep(core_test, mrbtest_irep);
mrb_t_pass_result(mrb, core_test);
#ifndef DISABLE_GEMS
diff --git a/mrbgems/mruby-test/mrbgem.rake b/mrbgems/mruby-test/mrbgem.rake
index b6b247ff6..298097f62 100644
--- a/mrbgems/mruby-test/mrbgem.rake
+++ b/mrbgems/mruby-test/mrbgem.rake
@@ -6,9 +6,10 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
build.bins << 'mrbtest'
spec.add_dependency('mruby-compiler', :core => 'mruby-compiler')
+ spec.test_rbfiles = Dir.glob("#{MRUBY_ROOT}/test/t/*.rb")
+
clib = "#{build_dir}/mrbtest.c"
mlib = clib.ext(exts.object)
- mrbs = Dir.glob("#{MRUBY_ROOT}/test/t/*.rb")
exec = exefile("#{build.build_dir}/bin/mrbtest")
libmruby = libfile("#{build.build_dir}/lib/libmruby")
@@ -26,7 +27,7 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
mrbtest_objs << assert_lib
file assert_lib => assert_c
- file assert_c => [build.mrbcfile, assert_rb] do |t|
+ file assert_c => assert_rb do |t|
open(t.name, 'w') do |f|
mrbc.run f, assert_rb, 'mrbtest_assert_irep'
end
@@ -40,7 +41,7 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
dep_list = build.gems.tsort_dependencies(g.test_dependencies, gem_table).select(&:generate_functions)
file test_rbobj => g.test_rbireps
- file g.test_rbireps => [g.test_rbfiles].flatten + [File.join(g.dir, 'mrbgem.rake'), g.build.mrbcfile, "#{MRUBY_ROOT}/tasks/mrbgem_spec.rake"] do |t|
+ file g.test_rbireps => [g.test_rbfiles].flatten do |t|
FileUtils.mkdir_p File.dirname(t.name)
open(t.name, 'w') do |f|
g.print_gem_test_header(f)
@@ -146,7 +147,7 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
init = "#{spec.dir}/init_mrbtest.c"
file mlib => clib
- file clib => [build.mrbcfile, init] do |t|
+ file clib => init do |t|
_pp "GEN", "*.rb", "#{clib.relative_path}"
FileUtils.mkdir_p File.dirname(clib)
open(clib, 'w') do |f|
@@ -160,7 +161,6 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
f.puts %Q[ */]
f.puts %Q[]
f.puts IO.read(init)
- mrbc.run f, mrbs, 'mrbtest_irep'
build.gems.each do |g|
f.puts %Q[void GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb_state *mrb);]
end
diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c
index c18ac7568..2a4347b7c 100644
--- a/mrbgems/mruby-time/src/time.c
+++ b/mrbgems/mruby-time/src/time.c
@@ -7,9 +7,9 @@
#include <math.h>
#include <stdio.h>
#include <time.h>
-#include "mruby.h"
-#include "mruby/class.h"
-#include "mruby/data.h"
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
#if !defined(__MINGW64__) && defined(_WIN32)
# define llround(x) round(x)
diff --git a/mrblib/enum.rb b/mrblib/enum.rb
index f0c9a4884..650d24302 100644
--- a/mrblib/enum.rb
+++ b/mrblib/enum.rb
@@ -1,17 +1,16 @@
##
# Enumerable
#
-# ISO 15.3.2
+# The <code>Enumerable</code> mixin provides collection classes with
+# several traversal and searching methods, and with the ability to
+# sort. The class must provide a method `each`, which
+# yields successive members of the collection. If
+# {Enumerable#max}, {#min}, or
+# {#sort} is used, the objects in the collection must also
+# implement a meaningful `<=>` operator, as these methods
+# rely on an ordering between members of the collection.
#
-# The <code>Enumerable</code> mixin provides collection classes with
-# several traversal and searching methods, and with the ability to
-# sort. The class must provide a method <code>each</code>, which
-# yields successive members of the collection. If
-# <code>Enumerable#max</code>, <code>#min</code>, or
-# <code>#sort</code> is used, the objects in the collection must also
-# implement a meaningful <code><=></code> operator, as these methods
-# rely on an ordering between members of the collection.
-
+# @ISO 15.3.2
module Enumerable
##
diff --git a/mrblib/hash.rb b/mrblib/hash.rb
index 48ac96e56..e3e709070 100644
--- a/mrblib/hash.rb
+++ b/mrblib/hash.rb
@@ -74,8 +74,8 @@ class Hash
#
# If no block is given, an enumerator is returned instead.
#
- # h = { "a" => 100, "b" => 200 }
- # h.each {|key, value| puts "#{key} is #{value}" }
+ # h = { "a" => 100, "b" => 200 }
+ # h.each {|key, value| puts "#{key} is #{value}" }
#
# <em>produces:</em>
#
diff --git a/mrblib/init_mrblib.c b/mrblib/init_mrblib.c
index dc902e9f9..4d4bcd25a 100644
--- a/mrblib/init_mrblib.c
+++ b/mrblib/init_mrblib.c
@@ -1,5 +1,5 @@
-#include "mruby.h"
-#include "mruby/irep.h"
+#include <mruby.h>
+#include <mruby/irep.h>
extern const uint8_t mrblib_irep[];
diff --git a/mrblib/kernel.rb b/mrblib/kernel.rb
index 38af3b310..550ae8172 100644
--- a/mrblib/kernel.rb
+++ b/mrblib/kernel.rb
@@ -30,8 +30,8 @@ module Kernel
while true
yield
end
- rescue StopIteration
- nil
+ rescue StopIteration => e
+ e.result
end
# 11.4.4 Step c)
diff --git a/mrblib/string.rb b/mrblib/string.rb
index 05b13cb43..37441ec98 100644
--- a/mrblib/string.rb
+++ b/mrblib/string.rb
@@ -10,9 +10,8 @@ class String
#
# ISO 15.2.10.5.15
def each_line(&block)
- # expect that str.index accepts an Integer for 1st argument as a byte data
offset = 0
- while pos = self.index(0x0a, offset)
+ while pos = self.index("\n", offset)
block.call(self[offset, pos + 1 - offset])
offset = pos + 1
end
@@ -154,13 +153,48 @@ class String
end
##
- # Modify +self+ by replacing the content of +self+
- # at the position +pos+ with +value+.
- def []=(pos, value)
- pos += self.length if pos < 0
- b = self[0, pos]
- a = self[pos + 1..-1]
- self.replace([b, value, a].join(''))
+ # Modify +self+ by replacing the content of +self+.
+ # The portion of the string affected is determined using the same criteria as +String#[]+.
+ def []=(*args)
+ anum = args.size
+ if anum == 2
+ pos, value = args
+ if pos.kind_of? String
+ posnum = self.index(pos)
+ if posnum
+ b = self[0, posnum.to_i]
+ a = self[(posnum + pos.length)..-1]
+ self.replace([b, value, a].join(''))
+ return value
+ else
+ raise IndexError, "string not matched"
+ end
+ else
+ pos += self.length if pos < 0
+ if pos < 0 || pos > self.length
+ raise IndexError, "index #{args[0]} out of string"
+ end
+ b = self[0, pos.to_i]
+ a = self[pos + 1..-1]
+ self.replace([b, value, a].join(''))
+ return value
+ end
+ elsif anum == 3
+ pos, len, value = args
+ pos += self.length if pos < 0
+ if pos < 0 || pos > self.length
+ raise IndexError, "index #{args[0]} out of string"
+ end
+ if len < 0
+ raise IndexError, "negative length #{len}"
+ end
+ b = self[0, pos.to_i]
+ a = self[pos + len..-1]
+ self.replace([b, value, a].join(''))
+ return value
+ else
+ raise ArgumentError, "wrong number of arguments (#{anum} for 2..3)"
+ end
end
##
diff --git a/mruby-source.gemspec b/mruby-source.gemspec
new file mode 100644
index 000000000..62d4c0d12
--- /dev/null
+++ b/mruby-source.gemspec
@@ -0,0 +1,18 @@
+# coding: utf-8
+lib = File.expand_path('../lib', __FILE__)
+$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
+require 'mruby/source'
+
+Gem::Specification.new do |spec|
+ spec.name = "mruby-source"
+ spec.version = MRuby::Source::MRUBY_VERSION
+ spec.authors = [ MRuby::Source::MRUBY_AUTHOR ]
+
+ spec.summary = %q{MRuby source code wrapper.}
+ spec.description = %q{MRuby source code wrapper for use with Ruby libs.}
+ spec.homepage = "http://www.mruby.org/"
+ spec.license = "MIT"
+
+ spec.files = `git ls-files -z`.split("\x0")
+ spec.require_paths = ["lib"]
+end
diff --git a/src/array.c b/src/array.c
index 2622ee528..9b8a49584 100644
--- a/src/array.c
+++ b/src/array.c
@@ -4,11 +4,11 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/class.h"
-#include "mruby/string.h"
-#include "mruby/range.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/string.h>
+#include <mruby/range.h>
#include "value_array.h"
#define ARY_DEFAULT_LEN 4
@@ -1068,7 +1068,7 @@ mrb_init_array(mrb_state *mrb)
{
struct RClass *a;
- a = mrb->array_class = mrb_define_class(mrb, "Array", mrb->object_class); /* 15.2.12 */
+ mrb->array_class = a = mrb_define_class(mrb, "Array", mrb->object_class); /* 15.2.12 */
MRB_SET_INSTANCE_TT(a, MRB_TT_ARRAY);
mrb_define_class_method(mrb, a, "[]", mrb_ary_s_create, MRB_ARGS_ANY()); /* 15.2.12.4.1 */
@@ -1101,4 +1101,5 @@ mrb_init_array(mrb_state *mrb)
mrb_define_method(mrb, a, "__ary_eq", mrb_ary_eq, MRB_ARGS_REQ(1));
mrb_define_method(mrb, a, "__ary_cmp", mrb_ary_cmp, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, a, "__ary_index", mrb_ary_index_m, MRB_ARGS_REQ(1)); /* kept for mruby-array-ext */
}
diff --git a/src/backtrace.c b/src/backtrace.c
index a672a6c95..80a5e2935 100644
--- a/src/backtrace.c
+++ b/src/backtrace.c
@@ -4,15 +4,15 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include "mruby/variable.h"
-#include "mruby/proc.h"
-#include "mruby/array.h"
-#include "mruby/string.h"
-#include "mruby/class.h"
-#include "mruby/debug.h"
-#include "mruby/error.h"
-#include "mruby/numeric.h"
+#include <mruby.h>
+#include <mruby/variable.h>
+#include <mruby/proc.h>
+#include <mruby/array.h>
+#include <mruby/string.h>
+#include <mruby/class.h>
+#include <mruby/debug.h>
+#include <mruby/error.h>
+#include <mruby/numeric.h>
struct backtrace_location {
int i;
@@ -25,7 +25,7 @@ struct backtrace_location {
typedef void (*output_stream_func)(mrb_state*, struct backtrace_location*, void*);
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
struct print_backtrace_args {
FILE *stream;
@@ -165,7 +165,7 @@ exc_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun
overwritten. So invoke these functions just after detecting exceptions.
*/
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
MRB_API void
mrb_print_backtrace(mrb_state *mrb)
diff --git a/src/class.c b/src/class.c
index c3c3e0b8f..ccbbe2544 100644
--- a/src/class.c
+++ b/src/class.c
@@ -5,15 +5,15 @@
*/
#include <stdarg.h>
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/class.h"
-#include "mruby/numeric.h"
-#include "mruby/proc.h"
-#include "mruby/string.h"
-#include "mruby/variable.h"
-#include "mruby/error.h"
-#include "mruby/data.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/numeric.h>
+#include <mruby/proc.h>
+#include <mruby/string.h>
+#include <mruby/variable.h>
+#include <mruby/error.h>
+#include <mruby/data.h>
KHASH_DEFINE(mt, mrb_sym, struct RProc*, TRUE, kh_int_hash_func, kh_int_hash_equal)
@@ -622,7 +622,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
format++;
if (i < argc && mrb_nil_p(*sp)) {
*ps = NULL;
- i++;
+ i++; sp++;
break;
}
}
@@ -647,7 +647,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
if (i < argc && mrb_nil_p(*sp)) {
*pb = 0;
*pl = 0;
- i++;
+ i++; sp++;
break;
}
}
@@ -740,7 +740,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
format++;
if (i < argc && mrb_nil_p(*sp)) {
*datap = 0;
- i++;
+ i++; sp++;
break;
}
}
diff --git a/src/codedump.c b/src/codedump.c
index 755c78d15..4f4b6de57 100644
--- a/src/codedump.c
+++ b/src/codedump.c
@@ -1,11 +1,11 @@
-#include "mruby.h"
-#include "mruby/irep.h"
-#include "mruby/debug.h"
-#include "mruby/opcode.h"
-#include "mruby/string.h"
-#include "mruby/proc.h"
+#include <mruby.h>
+#include <mruby/irep.h>
+#include <mruby/debug.h>
+#include <mruby/opcode.h>
+#include <mruby/string.h>
+#include <mruby/proc.h>
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
static int
print_r(mrb_state *mrb, mrb_irep *irep, size_t n, int pre)
{
@@ -53,7 +53,7 @@ print_lv(mrb_state *mrb, mrb_irep *irep, mrb_code c, int r)
static void
codedump(mrb_state *mrb, mrb_irep *irep)
{
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
int i;
int ai;
mrb_code c;
@@ -189,7 +189,7 @@ codedump(mrb_state *mrb, mrb_irep *irep)
print_lv(mrb, irep, c, RA);
break;
case OP_JMP:
- printf("OP_JMP\t\t%03d\n", i+GETARG_sBx(c));
+ printf("OP_JMP\t%03d\n", i+GETARG_sBx(c));
break;
case OP_JMPIF:
printf("OP_JMPIF\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c));
@@ -240,11 +240,11 @@ codedump(mrb_state *mrb, mrb_irep *irep)
switch (GETARG_B(c)) {
case OP_R_NORMAL:
case OP_R_RETURN:
- printf("\treturn"); break;
+ printf("\treturn\t"); break;
case OP_R_BREAK:
- printf("\tbreak"); break;
+ printf("\tbreak\t"); break;
default:
- printf("\tbroken"); break;
+ printf("\tbroken\t"); break;
break;
}
print_lv(mrb, irep, c, RA);
diff --git a/src/compar.c b/src/compar.c
index 0186b942f..0032fc859 100644
--- a/src/compar.c
+++ b/src/compar.c
@@ -4,7 +4,7 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
+#include <mruby.h>
void
mrb_init_comparable(mrb_state *mrb)
diff --git a/src/debug.c b/src/debug.c
index 4ac692086..cc2d37034 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -1,7 +1,7 @@
#include <string.h>
-#include "mruby.h"
-#include "mruby/irep.h"
-#include "mruby/debug.h"
+#include <mruby.h>
+#include <mruby/irep.h>
+#include <mruby/debug.h>
static mrb_irep_debug_info_file *
get_file(mrb_irep_debug_info *info, uint32_t pc)
diff --git a/src/dump.c b/src/dump.c
index 734f38043..8870c6c65 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -6,11 +6,11 @@
#include <string.h>
#include <limits.h>
-#include "mruby/dump.h"
-#include "mruby/string.h"
-#include "mruby/irep.h"
-#include "mruby/numeric.h"
-#include "mruby/debug.h"
+#include <mruby/dump.h>
+#include <mruby/string.h>
+#include <mruby/irep.h>
+#include <mruby/numeric.h>
+#include <mruby/debug.h>
#define FLAG_BYTEORDER_NATIVE 2
#define FLAG_BYTEORDER_NONATIVE 0
@@ -989,7 +989,7 @@ mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size
return dump_irep(mrb, irep, dump_flags(flags, FLAG_BYTEORDER_NONATIVE), bin, bin_size);
}
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
int
mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE* fp)
@@ -1092,4 +1092,4 @@ mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, con
return result;
}
-#endif /* ENABLE_STDIO */
+#endif /* MRB_DISABLE_STDIO */
diff --git a/src/enum.c b/src/enum.c
index 3def9e860..adb815bf1 100644
--- a/src/enum.c
+++ b/src/enum.c
@@ -4,7 +4,7 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
+#include <mruby.h>
void
mrb_init_enumerable(mrb_state *mrb)
diff --git a/src/error.c b/src/error.c
index 359e5737b..d15f9e76f 100644
--- a/src/error.c
+++ b/src/error.c
@@ -7,16 +7,16 @@
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/irep.h"
-#include "mruby/proc.h"
-#include "mruby/string.h"
-#include "mruby/variable.h"
-#include "mruby/debug.h"
-#include "mruby/error.h"
-#include "mruby/class.h"
-#include "mruby/throw.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/irep.h>
+#include <mruby/proc.h>
+#include <mruby/string.h>
+#include <mruby/variable.h>
+#include <mruby/debug.h>
+#include <mruby/error.h>
+#include <mruby/class.h>
+#include <mruby/throw.h>
MRB_API mrb_value
mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, size_t len)
@@ -206,7 +206,7 @@ MRB_API mrb_noreturn void
mrb_exc_raise(mrb_state *mrb, mrb_value exc)
{
mrb->exc = mrb_obj_ptr(exc);
- if (!mrb->out_of_memory) {
+ if (!mrb->gc.out_of_memory) {
exc_debug_info(mrb, mrb->exc);
}
if (!mrb->jmp) {
@@ -309,7 +309,7 @@ mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...)
MRB_API void
mrb_warn(mrb_state *mrb, const char *fmt, ...)
{
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
va_list ap;
mrb_value str;
@@ -324,7 +324,7 @@ mrb_warn(mrb_state *mrb, const char *fmt, ...)
MRB_API mrb_noreturn void
mrb_bug(mrb_state *mrb, const char *fmt, ...)
{
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
va_list ap;
mrb_value str;
diff --git a/src/error.h b/src/error.h
index 0e0dacf63..eb755ec7f 100644
--- a/src/error.h
+++ b/src/error.h
@@ -1,3 +1,3 @@
/* this header file is to be removed soon.
added for compatibility purpose (1.0.0) */
-#include "mruby/error.h"
+#include <mruby/error.h>
diff --git a/src/etc.c b/src/etc.c
index f5a502795..0ad56fe96 100644
--- a/src/etc.c
+++ b/src/etc.c
@@ -4,12 +4,12 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include "mruby/string.h"
-#include "mruby/data.h"
-#include "mruby/class.h"
-#include "mruby/re.h"
-#include "mruby/irep.h"
+#include <mruby.h>
+#include <mruby/string.h>
+#include <mruby/data.h>
+#include <mruby/class.h>
+#include <mruby/re.h>
+#include <mruby/irep.h>
MRB_API struct RData*
mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const mrb_data_type *type)
diff --git a/src/fmt_fp.c b/src/fmt_fp.c
index b27ebd6e9..b20eb895f 100644
--- a/src/fmt_fp.c
+++ b/src/fmt_fp.c
@@ -33,8 +33,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <float.h>
#include <ctype.h>
-#include "mruby.h"
-#include "mruby/string.h"
+#include <mruby.h>
+#include <mruby/string.h>
struct fmt_args {
mrb_state *mrb;
@@ -90,11 +90,6 @@ fmt_u(uint32_t x, char *s)
typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)];
#endif
-#if ((defined(__CYGWIN__) || defined(__NetBSD__) || defined(mips)) && !defined(__linux__)) || defined(__android__)
-#undef frexpl
-#define frexpl frexp
-#endif
-
static int
fmt_fp(struct fmt_args *f, long double y, int w, int p, int fl, int t)
{
@@ -127,7 +122,7 @@ fmt_fp(struct fmt_args *f, long double y, int w, int p, int fl, int t)
return MAX(w, 3+pl);
}
- y = frexpl(y, &e2) * 2;
+ y = frexp((double)y, &e2) * 2;
if (y) e2--;
if ((t|32)=='a') {
diff --git a/src/gc.c b/src/gc.c
index 15e1bd423..02e058f88 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -6,17 +6,17 @@
#include <string.h>
#include <stdlib.h>
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/class.h"
-#include "mruby/data.h"
-#include "mruby/hash.h"
-#include "mruby/proc.h"
-#include "mruby/range.h"
-#include "mruby/string.h"
-#include "mruby/variable.h"
-#include "mruby/gc.h"
-#include "mruby/error.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
+#include <mruby/hash.h>
+#include <mruby/proc.h>
+#include <mruby/range.h>
+#include <mruby/string.h>
+#include <mruby/variable.h>
+#include <mruby/gc.h>
+#include <mruby/error.h>
/*
= Tri-color Incremental Garbage Collection
@@ -136,7 +136,7 @@ gettimeofday_time(void)
#define GC_INVOKE_TIME_REPORT(with) do {\
fprintf(stderr, "%s\n", with);\
fprintf(stderr, "gc_invoke: %19.3f\n", gettimeofday_time() - program_invoke_time);\
- fprintf(stderr, "is_generational: %d\n", is_generational(mrb));\
+ fprintf(stderr, "is_generational: %d\n", is_generational(gc));\
fprintf(stderr, "is_major_gc: %d\n", is_major_gc(mrb));\
} while(0)
@@ -147,10 +147,10 @@ gettimeofday_time(void)
#define GC_TIME_STOP_AND_REPORT do {\
gc_time = gettimeofday_time() - gc_time;\
gc_total_time += gc_time;\
- fprintf(stderr, "gc_state: %d\n", mrb->gc_state);\
- fprintf(stderr, "live: %zu\n", mrb->live);\
- fprintf(stderr, "majorgc_old_threshold: %zu\n", mrb->majorgc_old_threshold);\
- fprintf(stderr, "gc_threshold: %zu\n", mrb->gc_threshold);\
+ fprintf(stderr, "gc_state: %d\n", gc->state);\
+ fprintf(stderr, "live: %zu\n", gc->live);\
+ fprintf(stderr, "majorgc_old_threshold: %zu\n", gc->majorgc_old_threshold);\
+ fprintf(stderr, "gc_threshold: %zu\n", gc->threshold);\
fprintf(stderr, "gc_time: %30.20f\n", gc_time);\
fprintf(stderr, "gc_total_time: %30.20f\n\n", gc_total_time);\
} while(0)
@@ -166,8 +166,32 @@ gettimeofday_time(void)
#define DEBUG(x)
#endif
+#ifndef MRB_HEAP_PAGE_SIZE
+#define MRB_HEAP_PAGE_SIZE 1024
+#endif
+
#define GC_STEP_SIZE 1024
+/* white: 011, black: 100, gray: 000 */
+#define GC_GRAY 0
+#define GC_WHITE_A 1
+#define GC_WHITE_B (1 << 1)
+#define GC_BLACK (1 << 2)
+#define GC_WHITES (GC_WHITE_A | GC_WHITE_B)
+#define GC_COLOR_MASK 7
+
+#define paint_gray(o) ((o)->color = GC_GRAY)
+#define paint_black(o) ((o)->color = GC_BLACK)
+#define paint_white(o) ((o)->color = GC_WHITES)
+#define paint_partial_white(s, o) ((o)->color = (s)->current_white_part)
+#define is_gray(o) ((o)->color == GC_GRAY)
+#define is_white(o) ((o)->color & GC_WHITES)
+#define is_black(o) ((o)->color & GC_BLACK)
+#define flip_white_part(s) ((s)->current_white_part = other_white_part(s))
+#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)
+
+#define objects(p) ((RVALUE *)p->objects)
MRB_API void*
mrb_realloc_simple(mrb_state *mrb, void *p, size_t len)
@@ -175,7 +199,7 @@ mrb_realloc_simple(mrb_state *mrb, void *p, size_t len)
void *p2;
p2 = (mrb->allocf)(mrb, p, len, mrb->allocf_ud);
- if (!p2 && len > 0 && mrb->heaps) {
+ if (!p2 && len > 0 && mrb->gc.heaps) {
mrb_full_gc(mrb);
p2 = (mrb->allocf)(mrb, p, len, mrb->allocf_ud);
}
@@ -183,7 +207,6 @@ mrb_realloc_simple(mrb_state *mrb, void *p, size_t len)
return p2;
}
-
MRB_API void*
mrb_realloc(mrb_state *mrb, void *p, size_t len)
{
@@ -191,16 +214,16 @@ mrb_realloc(mrb_state *mrb, void *p, size_t len)
p2 = mrb_realloc_simple(mrb, p, len);
if (!p2 && len) {
- if (mrb->out_of_memory) {
+ if (mrb->gc.out_of_memory) {
/* mrb_panic(mrb); */
}
else {
- mrb->out_of_memory = TRUE;
+ mrb->gc.out_of_memory = TRUE;
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
}
}
else {
- mrb->out_of_memory = FALSE;
+ mrb->gc.out_of_memory = FALSE;
}
return p2;
@@ -244,101 +267,98 @@ mrb_free(mrb_state *mrb, void *p)
(mrb->allocf)(mrb, p, 0, mrb->allocf_ud);
}
-#ifndef MRB_HEAP_PAGE_SIZE
-#define MRB_HEAP_PAGE_SIZE 1024
-#endif
-
-struct heap_page {
- struct RBasic *freelist;
- struct heap_page *prev;
- struct heap_page *next;
- struct heap_page *free_next;
- struct heap_page *free_prev;
- mrb_bool old:1;
- RVALUE objects[MRB_HEAP_PAGE_SIZE];
-};
+MRB_API mrb_bool
+mrb_object_dead_p(mrb_state *mrb, struct RBasic *object) {
+ return is_dead(&mrb->gc, object);
+}
static void
-link_heap_page(mrb_state *mrb, struct heap_page *page)
+link_heap_page(mrb_gc *gc, mrb_heap_page *page)
{
- page->next = mrb->heaps;
- if (mrb->heaps)
- mrb->heaps->prev = page;
- mrb->heaps = page;
+ page->next = gc->heaps;
+ if (gc->heaps)
+ gc->heaps->prev = page;
+ gc->heaps = page;
}
static void
-unlink_heap_page(mrb_state *mrb, struct heap_page *page)
+unlink_heap_page(mrb_gc *gc, mrb_heap_page *page)
{
if (page->prev)
page->prev->next = page->next;
if (page->next)
page->next->prev = page->prev;
- if (mrb->heaps == page)
- mrb->heaps = page->next;
+ if (gc->heaps == page)
+ gc->heaps = page->next;
page->prev = NULL;
page->next = NULL;
}
static void
-link_free_heap_page(mrb_state *mrb, struct heap_page *page)
+link_free_heap_page(mrb_gc *gc, mrb_heap_page *page)
{
- page->free_next = mrb->free_heaps;
- if (mrb->free_heaps) {
- mrb->free_heaps->free_prev = page;
+ page->free_next = gc->free_heaps;
+ if (gc->free_heaps) {
+ gc->free_heaps->free_prev = page;
}
- mrb->free_heaps = page;
+ gc->free_heaps = page;
}
static void
-unlink_free_heap_page(mrb_state *mrb, struct heap_page *page)
+unlink_free_heap_page(mrb_gc *gc, mrb_heap_page *page)
{
if (page->free_prev)
page->free_prev->free_next = page->free_next;
if (page->free_next)
page->free_next->free_prev = page->free_prev;
- if (mrb->free_heaps == page)
- mrb->free_heaps = page->free_next;
+ if (gc->free_heaps == page)
+ gc->free_heaps = page->free_next;
page->free_prev = NULL;
page->free_next = NULL;
}
static void
-add_heap(mrb_state *mrb)
+add_heap(mrb_state *mrb, mrb_gc *gc)
{
- struct heap_page *page = (struct heap_page *)mrb_calloc(mrb, 1, sizeof(struct heap_page));
+ mrb_heap_page *page = (mrb_heap_page *)mrb_calloc(mrb, 1, sizeof(mrb_heap_page) + MRB_HEAP_PAGE_SIZE * sizeof(RVALUE));
RVALUE *p, *e;
struct RBasic *prev = NULL;
- for (p = page->objects, e=p+MRB_HEAP_PAGE_SIZE; p<e; p++) {
+ for (p = objects(page), 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;
}
page->freelist = prev;
- link_heap_page(mrb, page);
- link_free_heap_page(mrb, page);
+ link_heap_page(gc, page);
+ link_free_heap_page(gc, page);
}
#define DEFAULT_GC_INTERVAL_RATIO 200
#define DEFAULT_GC_STEP_RATIO 200
#define DEFAULT_MAJOR_GC_INC_RATIO 200
-#define is_generational(mrb) ((mrb)->is_generational_gc_mode)
-#define is_major_gc(mrb) (is_generational(mrb) && (mrb)->gc_full)
-#define is_minor_gc(mrb) (is_generational(mrb) && !(mrb)->gc_full)
+#define is_generational(gc) ((gc)->generational)
+#define is_major_gc(gc) (is_generational(gc) && (gc)->full)
+#define is_minor_gc(gc) (is_generational(gc) && !(gc)->full)
void
-mrb_init_heap(mrb_state *mrb)
+mrb_gc_init(mrb_state *mrb, mrb_gc *gc)
{
- mrb->heaps = NULL;
- mrb->free_heaps = NULL;
- add_heap(mrb);
- mrb->gc_interval_ratio = DEFAULT_GC_INTERVAL_RATIO;
- mrb->gc_step_ratio = DEFAULT_GC_STEP_RATIO;
+#ifndef MRB_GC_FIXED_ARENA
+ gc->arena = (struct RBasic**)mrb_malloc(mrb, sizeof(struct RBasic*)*MRB_GC_ARENA_SIZE);
+ gc->arena_capa = MRB_GC_ARENA_SIZE;
+#endif
+
+ gc->current_white_part = GC_WHITE_A;
+ gc->heaps = NULL;
+ gc->free_heaps = NULL;
+ add_heap(mrb, gc);
+ gc->interval_ratio = DEFAULT_GC_INTERVAL_RATIO;
+ gc->step_ratio = DEFAULT_GC_STEP_RATIO;
#ifndef MRB_GC_TURN_OFF_GENERATIONAL
- mrb->is_generational_gc_mode = TRUE;
- mrb->gc_full = TRUE;
+ gc->generational = TRUE;
+ gc->full = TRUE;
#endif
#ifdef GC_PROFILE
@@ -349,16 +369,16 @@ mrb_init_heap(mrb_state *mrb)
static void obj_free(mrb_state *mrb, struct RBasic *obj);
void
-mrb_free_heap(mrb_state *mrb)
+free_heap(mrb_state *mrb, mrb_gc *gc)
{
- struct heap_page *page = mrb->heaps;
- struct heap_page *tmp;
+ mrb_heap_page *page = gc->heaps;
+ mrb_heap_page *tmp;
RVALUE *p, *e;
while (page) {
tmp = page;
page = page->next;
- for (p = tmp->objects, e=p+MRB_HEAP_PAGE_SIZE; p<e; p++) {
+ for (p = objects(tmp), e=p+MRB_HEAP_PAGE_SIZE; p<e; p++) {
if (p->as.free.tt != MRB_TT_FREE)
obj_free(mrb, &p->as.basic);
}
@@ -366,30 +386,87 @@ mrb_free_heap(mrb_state *mrb)
}
}
+void
+mrb_gc_destroy(mrb_state *mrb, mrb_gc *gc)
+{
+ free_heap(mrb, gc);
+#ifndef MRB_GC_FIXED_ARENA
+ mrb_free(mrb, gc->arena);
+#endif
+}
+
static void
-gc_protect(mrb_state *mrb, struct RBasic *p)
+gc_protect(mrb_state *mrb, mrb_gc *gc, struct RBasic *p)
{
#ifdef MRB_GC_FIXED_ARENA
- if (mrb->arena_idx >= MRB_GC_ARENA_SIZE) {
+ if (gc->arena_idx >= MRB_GC_ARENA_SIZE) {
/* arena overflow error */
- mrb->arena_idx = MRB_GC_ARENA_SIZE - 4; /* force room in arena */
+ gc->arena_idx = MRB_GC_ARENA_SIZE - 4; /* force room in arena */
mrb_raise(mrb, E_RUNTIME_ERROR, "arena overflow error");
}
#else
- if (mrb->arena_idx >= mrb->arena_capa) {
+ if (gc->arena_idx >= gc->arena_capa) {
/* extend arena */
- mrb->arena_capa = (int)(mrb->arena_capa * 1.5);
- mrb->arena = (struct RBasic**)mrb_realloc(mrb, mrb->arena, sizeof(struct RBasic*)*mrb->arena_capa);
+ gc->arena_capa = (int)(gc->arena_capa * 1.5);
+ gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*gc->arena_capa);
}
#endif
- mrb->arena[mrb->arena_idx++] = p;
+ gc->arena[gc->arena_idx++] = p;
}
+/* mrb_gc_protect() leaves the object in the arena */
MRB_API void
mrb_gc_protect(mrb_state *mrb, mrb_value obj)
{
if (mrb_immediate_p(obj)) return;
- gc_protect(mrb, mrb_basic_ptr(obj));
+ gc_protect(mrb, &mrb->gc, mrb_basic_ptr(obj));
+}
+
+#define GC_ROOT_NAME "_gc_root_"
+
+/* mrb_gc_register() keeps the object from GC.
+
+ Register your object when it's exported to C world,
+ without reference from Ruby world, e.g. callback
+ arguments. Don't forget to remove the obejct using
+ mrb_gc_unregister, otherwise your object will leak.
+*/
+
+MRB_API void
+mrb_gc_register(mrb_state *mrb, mrb_value obj)
+{
+ mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME);
+ mrb_value table = mrb_gv_get(mrb, root);
+
+ if (mrb_nil_p(table) || mrb_type(table) != MRB_TT_ARRAY) {
+ table = mrb_ary_new(mrb);
+ mrb_gv_set(mrb, root, table);
+ }
+ mrb_ary_push(mrb, table, obj);
+}
+
+/* mrb_gc_unregister() removes the object from GC root. */
+MRB_API void
+mrb_gc_unregister(mrb_state *mrb, mrb_value obj)
+{
+ mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME);
+ mrb_value table = mrb_gv_get(mrb, root);
+ struct RArray *a;
+ mrb_int i, j;
+
+ if (mrb_nil_p(table)) return;
+ if (mrb_type(table) != MRB_TT_ARRAY) {
+ mrb_gv_set(mrb, root, mrb_nil_value());
+ return;
+ }
+ a = mrb_ary_ptr(table);
+ mrb_ary_modify(mrb, a);
+ for (i=j=0; i<a->len; i++) {
+ if (!mrb_obj_eq(mrb, a->ptr[i], obj)) {
+ a->ptr[j++] = a->ptr[i];
+ }
+ }
+ a->len = j;
}
MRB_API struct RBasic*
@@ -397,34 +474,35 @@ mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls)
{
struct RBasic *p;
static const RVALUE RVALUE_zero = { { { MRB_TT_FALSE } } };
+ mrb_gc *gc = &mrb->gc;
#ifdef MRB_GC_STRESS
mrb_full_gc(mrb);
#endif
- if (mrb->gc_threshold < mrb->live) {
+ if (gc->threshold < gc->live) {
mrb_incremental_gc(mrb);
}
- if (mrb->free_heaps == NULL) {
- add_heap(mrb);
+ if (gc->free_heaps == NULL) {
+ add_heap(mrb, gc);
}
- p = mrb->free_heaps->freelist;
- mrb->free_heaps->freelist = ((struct free_obj*)p)->next;
- if (mrb->free_heaps->freelist == NULL) {
- unlink_free_heap_page(mrb, mrb->free_heaps);
+ p = gc->free_heaps->freelist;
+ gc->free_heaps->freelist = ((struct free_obj*)p)->next;
+ if (gc->free_heaps->freelist == NULL) {
+ unlink_free_heap_page(gc, gc->free_heaps);
}
- mrb->live++;
- gc_protect(mrb, p);
+ gc->live++;
+ gc_protect(mrb, gc, p);
*(RVALUE *)p = RVALUE_zero;
p->tt = ttype;
p->c = cls;
- paint_partial_white(mrb, p);
+ paint_partial_white(gc, p);
return p;
}
static inline void
-add_gray_list(mrb_state *mrb, struct RBasic *obj)
+add_gray_list(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
{
#ifdef MRB_GC_STRESS
if (obj->tt > MRB_TT_MAXDEFINE) {
@@ -432,8 +510,8 @@ add_gray_list(mrb_state *mrb, struct RBasic *obj)
}
#endif
paint_gray(obj);
- obj->gcnext = mrb->gray_list;
- mrb->gray_list = obj;
+ obj->gcnext = gc->gray_list;
+ gc->gray_list = obj;
}
static void
@@ -490,11 +568,11 @@ mark_context(mrb_state *mrb, struct mrb_context *c)
}
static void
-gc_mark_children(mrb_state *mrb, struct RBasic *obj)
+gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
{
mrb_assert(is_gray(obj));
paint_black(obj);
- mrb->gray_list = obj->gcnext;
+ gc->gray_list = obj->gcnext;
mrb_gc_mark(mrb, (struct RBasic*)obj->c);
switch (obj->tt) {
case MRB_TT_ICLASS:
@@ -596,7 +674,7 @@ mrb_gc_mark(mrb_state *mrb, struct RBasic *obj)
if (obj == 0) return;
if (!is_white(obj)) return;
mrb_assert((obj)->tt != MRB_TT_FREE);
- add_gray_list(mrb, obj);
+ add_gray_list(mrb, &mrb->gc, obj);
}
static void
@@ -700,19 +778,19 @@ obj_free(mrb_state *mrb, struct RBasic *obj)
}
static void
-root_scan_phase(mrb_state *mrb)
+root_scan_phase(mrb_state *mrb, mrb_gc *gc)
{
size_t i, e;
- if (!is_minor_gc(mrb)) {
- mrb->gray_list = NULL;
- mrb->atomic_gray_list = NULL;
+ if (!is_minor_gc(gc)) {
+ gc->gray_list = NULL;
+ gc->atomic_gray_list = NULL;
}
mrb_gc_mark_gv(mrb);
/* mark arena */
- for (i=0,e=mrb->arena_idx; i<e; i++) {
- mrb_gc_mark(mrb, mrb->arena[i]);
+ for (i=0,e=gc->arena_idx; i<e; i++) {
+ mrb_gc_mark(mrb, gc->arena[i]);
}
/* mark class hierarchy */
mrb_gc_mark(mrb, (struct RBasic*)mrb->object_class);
@@ -733,11 +811,11 @@ root_scan_phase(mrb_state *mrb)
}
static size_t
-gc_gray_mark(mrb_state *mrb, struct RBasic *obj)
+gc_gray_mark(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
{
size_t children = 0;
- gc_mark_children(mrb, obj);
+ gc_mark_children(mrb, gc, obj);
switch (obj->tt) {
case MRB_TT_ICLASS:
@@ -816,68 +894,68 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj)
static void
-gc_mark_gray_list(mrb_state *mrb) {
- while (mrb->gray_list) {
- if (is_gray(mrb->gray_list))
- gc_mark_children(mrb, mrb->gray_list);
+gc_mark_gray_list(mrb_state *mrb, mrb_gc *gc) {
+ while (gc->gray_list) {
+ if (is_gray(gc->gray_list))
+ gc_mark_children(mrb, gc, gc->gray_list);
else
- mrb->gray_list = mrb->gray_list->gcnext;
+ gc->gray_list = gc->gray_list->gcnext;
}
}
static size_t
-incremental_marking_phase(mrb_state *mrb, size_t limit)
+incremental_marking_phase(mrb_state *mrb, mrb_gc *gc, size_t limit)
{
size_t tried_marks = 0;
- while (mrb->gray_list && tried_marks < limit) {
- tried_marks += gc_gray_mark(mrb, mrb->gray_list);
+ while (gc->gray_list && tried_marks < limit) {
+ tried_marks += gc_gray_mark(mrb, gc, gc->gray_list);
}
return tried_marks;
}
static void
-final_marking_phase(mrb_state *mrb)
+final_marking_phase(mrb_state *mrb, mrb_gc *gc)
{
mark_context_stack(mrb, mrb->root_c);
- gc_mark_gray_list(mrb);
- mrb_assert(mrb->gray_list == NULL);
- mrb->gray_list = mrb->atomic_gray_list;
- mrb->atomic_gray_list = NULL;
- gc_mark_gray_list(mrb);
- mrb_assert(mrb->gray_list == NULL);
+ gc_mark_gray_list(mrb, gc);
+ mrb_assert(gc->gray_list == NULL);
+ gc->gray_list = gc->atomic_gray_list;
+ gc->atomic_gray_list = NULL;
+ gc_mark_gray_list(mrb, gc);
+ mrb_assert(gc->gray_list == NULL);
}
static void
-prepare_incremental_sweep(mrb_state *mrb)
+prepare_incremental_sweep(mrb_state *mrb, mrb_gc *gc)
{
- mrb->gc_state = GC_STATE_SWEEP;
- mrb->sweeps = mrb->heaps;
- mrb->gc_live_after_mark = mrb->live;
+ gc->state = MRB_GC_STATE_SWEEP;
+ gc->sweeps = gc->heaps;
+ gc->live_after_mark = gc->live;
}
static size_t
-incremental_sweep_phase(mrb_state *mrb, size_t limit)
+incremental_sweep_phase(mrb_state *mrb, mrb_gc *gc, size_t limit)
{
- struct heap_page *page = mrb->sweeps;
+ mrb_heap_page *page = gc->sweeps;
size_t tried_sweep = 0;
while (page && (tried_sweep < limit)) {
- RVALUE *p = page->objects;
+ RVALUE *p = objects(page);
RVALUE *e = p + MRB_HEAP_PAGE_SIZE;
size_t freed = 0;
mrb_bool dead_slot = TRUE;
mrb_bool full = (page->freelist == NULL);
- if (is_minor_gc(mrb) && page->old) {
+ if (is_minor_gc(gc) && page->old) {
/* skip a slot which doesn't contain any young object */
p = e;
dead_slot = FALSE;
}
while (p<e) {
- if (is_dead(mrb, &p->as.basic)) {
+ if (is_dead(gc, &p->as.basic)) {
if (p->as.basic.tt != MRB_TT_FREE) {
obj_free(mrb, &p->as.basic);
p->as.free.next = page->freelist;
@@ -886,8 +964,8 @@ incremental_sweep_phase(mrb_state *mrb, size_t limit)
}
}
else {
- if (!is_generational(mrb))
- paint_partial_white(mrb, &p->as.basic); /* next gc target */
+ if (!is_generational(gc))
+ paint_partial_white(gc, &p->as.basic); /* next gc target */
dead_slot = 0;
}
p++;
@@ -895,54 +973,54 @@ incremental_sweep_phase(mrb_state *mrb, size_t limit)
/* free dead slot */
if (dead_slot && freed < MRB_HEAP_PAGE_SIZE) {
- struct heap_page *next = page->next;
+ mrb_heap_page *next = page->next;
- unlink_heap_page(mrb, page);
- unlink_free_heap_page(mrb, page);
+ unlink_heap_page(gc, page);
+ unlink_free_heap_page(gc, page);
mrb_free(mrb, page);
page = next;
}
else {
if (full && freed > 0) {
- link_free_heap_page(mrb, page);
+ link_free_heap_page(gc, page);
}
- if (page->freelist == NULL && is_minor_gc(mrb))
+ if (page->freelist == NULL && is_minor_gc(gc))
page->old = TRUE;
else
page->old = FALSE;
page = page->next;
}
tried_sweep += MRB_HEAP_PAGE_SIZE;
- mrb->live -= freed;
- mrb->gc_live_after_mark -= freed;
+ gc->live -= freed;
+ gc->live_after_mark -= freed;
}
- mrb->sweeps = page;
+ gc->sweeps = page;
return tried_sweep;
}
static size_t
-incremental_gc(mrb_state *mrb, size_t limit)
+incremental_gc(mrb_state *mrb, mrb_gc *gc, size_t limit)
{
- switch (mrb->gc_state) {
- case GC_STATE_ROOT:
- root_scan_phase(mrb);
- mrb->gc_state = GC_STATE_MARK;
- flip_white_part(mrb);
+ switch (gc->state) {
+ case MRB_GC_STATE_ROOT:
+ root_scan_phase(mrb, gc);
+ gc->state = MRB_GC_STATE_MARK;
+ flip_white_part(gc);
return 0;
- case GC_STATE_MARK:
- if (mrb->gray_list) {
- return incremental_marking_phase(mrb, limit);
+ case MRB_GC_STATE_MARK:
+ if (gc->gray_list) {
+ return incremental_marking_phase(mrb, gc, limit);
}
else {
- final_marking_phase(mrb);
- prepare_incremental_sweep(mrb);
+ final_marking_phase(mrb, gc);
+ prepare_incremental_sweep(mrb, gc);
return 0;
}
- case GC_STATE_SWEEP: {
+ case MRB_GC_STATE_SWEEP: {
size_t tried_sweep = 0;
- tried_sweep = incremental_sweep_phase(mrb, limit);
+ tried_sweep = incremental_sweep_phase(mrb, gc, limit);
if (tried_sweep == 0)
- mrb->gc_state = GC_STATE_ROOT;
+ gc->state = MRB_GC_STATE_ROOT;
return tried_sweep;
}
default:
@@ -953,79 +1031,81 @@ incremental_gc(mrb_state *mrb, size_t limit)
}
static void
-incremental_gc_until(mrb_state *mrb, enum gc_state to_state)
+incremental_gc_until(mrb_state *mrb, mrb_gc *gc, mrb_gc_state to_state)
{
do {
- incremental_gc(mrb, SIZE_MAX);
- } while (mrb->gc_state != to_state);
+ incremental_gc(mrb, gc, SIZE_MAX);
+ } while (gc->state != to_state);
}
static void
-incremental_gc_step(mrb_state *mrb)
+incremental_gc_step(mrb_state *mrb, mrb_gc *gc)
{
size_t limit = 0, result = 0;
- limit = (GC_STEP_SIZE/100) * mrb->gc_step_ratio;
+ limit = (GC_STEP_SIZE/100) * gc->step_ratio;
while (result < limit) {
- result += incremental_gc(mrb, limit);
- if (mrb->gc_state == GC_STATE_ROOT)
+ result += incremental_gc(mrb, gc, limit);
+ if (gc->state == MRB_GC_STATE_ROOT)
break;
}
- mrb->gc_threshold = mrb->live + GC_STEP_SIZE;
+ gc->threshold = gc->live + GC_STEP_SIZE;
}
static void
-clear_all_old(mrb_state *mrb)
+clear_all_old(mrb_state *mrb, mrb_gc *gc)
{
- mrb_bool origin_mode = mrb->is_generational_gc_mode;
+ mrb_bool origin_mode = gc->generational;
- mrb_assert(is_generational(mrb));
- if (is_major_gc(mrb)) {
+ mrb_assert(is_generational(gc));
+ if (is_major_gc(gc)) {
/* finish the half baked GC */
- incremental_gc_until(mrb, GC_STATE_ROOT);
+ incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT);
}
/* Sweep the dead objects, then reset all the live objects
* (including all the old objects, of course) to white. */
- mrb->is_generational_gc_mode = FALSE;
- prepare_incremental_sweep(mrb);
- incremental_gc_until(mrb, GC_STATE_ROOT);
- mrb->is_generational_gc_mode = origin_mode;
+ gc->generational = FALSE;
+ prepare_incremental_sweep(mrb, gc);
+ incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT);
+ gc->generational = origin_mode;
/* The gray objects have already been painted as white */
- mrb->atomic_gray_list = mrb->gray_list = NULL;
+ gc->atomic_gray_list = gc->gray_list = NULL;
}
MRB_API void
mrb_incremental_gc(mrb_state *mrb)
{
- if (mrb->gc_disabled) return;
+ mrb_gc *gc = &mrb->gc;
+
+ if (gc->disabled) return;
GC_INVOKE_TIME_REPORT("mrb_incremental_gc()");
GC_TIME_START;
- if (is_minor_gc(mrb)) {
- incremental_gc_until(mrb, GC_STATE_ROOT);
+ if (is_minor_gc(gc)) {
+ incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT);
}
else {
- incremental_gc_step(mrb);
+ incremental_gc_step(mrb, gc);
}
- if (mrb->gc_state == GC_STATE_ROOT) {
- mrb_assert(mrb->live >= mrb->gc_live_after_mark);
- mrb->gc_threshold = (mrb->gc_live_after_mark/100) * mrb->gc_interval_ratio;
- if (mrb->gc_threshold < GC_STEP_SIZE) {
- mrb->gc_threshold = GC_STEP_SIZE;
+ if (gc->state == MRB_GC_STATE_ROOT) {
+ mrb_assert(gc->live >= gc->live_after_mark);
+ gc->threshold = (gc->live_after_mark/100) * gc->interval_ratio;
+ if (gc->threshold < GC_STEP_SIZE) {
+ gc->threshold = GC_STEP_SIZE;
}
- if (is_major_gc(mrb)) {
- mrb->majorgc_old_threshold = mrb->gc_live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO;
- mrb->gc_full = FALSE;
+ if (is_major_gc(gc)) {
+ gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO;
+ gc->full = FALSE;
}
- else if (is_minor_gc(mrb)) {
- if (mrb->live > mrb->majorgc_old_threshold) {
- clear_all_old(mrb);
- mrb->gc_full = TRUE;
+ else if (is_minor_gc(gc)) {
+ if (gc->live > gc->majorgc_old_threshold) {
+ clear_all_old(mrb, gc);
+ gc->full = TRUE;
}
}
}
@@ -1037,26 +1117,29 @@ mrb_incremental_gc(mrb_state *mrb)
MRB_API void
mrb_full_gc(mrb_state *mrb)
{
- if (mrb->gc_disabled) return;
+ mrb_gc *gc = &mrb->gc;
+
+ if (gc->disabled) return;
+
GC_INVOKE_TIME_REPORT("mrb_full_gc()");
GC_TIME_START;
- if (is_generational(mrb)) {
+ if (is_generational(gc)) {
/* clear all the old objects back to young */
- clear_all_old(mrb);
- mrb->gc_full = TRUE;
+ clear_all_old(mrb, gc);
+ gc->full = TRUE;
}
- else if (mrb->gc_state != GC_STATE_ROOT) {
+ else if (gc->state != MRB_GC_STATE_ROOT) {
/* finish half baked GC cycle */
- incremental_gc_until(mrb, GC_STATE_ROOT);
+ incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT);
}
- incremental_gc_until(mrb, GC_STATE_ROOT);
- mrb->gc_threshold = (mrb->gc_live_after_mark/100) * mrb->gc_interval_ratio;
+ incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT);
+ gc->threshold = (gc->live_after_mark/100) * gc->interval_ratio;
- if (is_generational(mrb)) {
- mrb->majorgc_old_threshold = mrb->gc_live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO;
- mrb->gc_full = FALSE;
+ if (is_generational(gc)) {
+ gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO;
+ gc->full = FALSE;
}
GC_TIME_STOP_AND_REPORT;
@@ -1071,27 +1154,29 @@ mrb_garbage_collect(mrb_state *mrb)
MRB_API int
mrb_gc_arena_save(mrb_state *mrb)
{
- return mrb->arena_idx;
+ return mrb->gc.arena_idx;
}
MRB_API void
mrb_gc_arena_restore(mrb_state *mrb, int idx)
{
+ mrb_gc *gc = &mrb->gc;
+
#ifndef MRB_GC_FIXED_ARENA
- int capa = mrb->arena_capa;
+ int capa = gc->arena_capa;
if (idx < capa / 2) {
capa = (int)(capa * 0.66);
if (capa < MRB_GC_ARENA_SIZE) {
capa = MRB_GC_ARENA_SIZE;
}
- if (capa != mrb->arena_capa) {
- mrb->arena = (struct RBasic**)mrb_realloc(mrb, mrb->arena, sizeof(struct RBasic*)*capa);
- mrb->arena_capa = capa;
+ if (capa != gc->arena_capa) {
+ gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*capa);
+ gc->arena_capa = capa;
}
}
#endif
- mrb->arena_idx = idx;
+ gc->arena_idx = idx;
}
/*
@@ -1102,18 +1187,20 @@ mrb_gc_arena_restore(mrb_state *mrb, int idx)
MRB_API void
mrb_field_write_barrier(mrb_state *mrb, struct RBasic *obj, struct RBasic *value)
{
+ mrb_gc *gc = &mrb->gc;
+
if (!is_black(obj)) return;
if (!is_white(value)) return;
- mrb_assert(!is_dead(mrb, value) && !is_dead(mrb, obj));
- mrb_assert(is_generational(mrb) || mrb->gc_state != GC_STATE_ROOT);
+ mrb_assert(gc->state == MRB_GC_STATE_MARK || (!is_dead(gc, value) && !is_dead(gc, obj)));
+ mrb_assert(is_generational(gc) || gc->state != MRB_GC_STATE_ROOT);
- if (is_generational(mrb) || mrb->gc_state == GC_STATE_MARK) {
- add_gray_list(mrb, value);
+ if (is_generational(gc) || gc->state == MRB_GC_STATE_MARK) {
+ add_gray_list(mrb, gc, value);
}
else {
- mrb_assert(mrb->gc_state == GC_STATE_SWEEP);
- paint_partial_white(mrb, obj); /* for never write barriers */
+ mrb_assert(gc->state == MRB_GC_STATE_SWEEP);
+ paint_partial_white(gc, obj); /* for never write barriers */
}
}
@@ -1129,13 +1216,15 @@ mrb_field_write_barrier(mrb_state *mrb, struct RBasic *obj, struct RBasic *value
MRB_API void
mrb_write_barrier(mrb_state *mrb, struct RBasic *obj)
{
+ mrb_gc *gc = &mrb->gc;
+
if (!is_black(obj)) return;
- mrb_assert(!is_dead(mrb, obj));
- mrb_assert(is_generational(mrb) || mrb->gc_state != GC_STATE_ROOT);
+ mrb_assert(!is_dead(gc, obj));
+ mrb_assert(is_generational(gc) || gc->state != MRB_GC_STATE_ROOT);
paint_gray(obj);
- obj->gcnext = mrb->atomic_gray_list;
- mrb->atomic_gray_list = obj;
+ obj->gcnext = gc->atomic_gray_list;
+ gc->atomic_gray_list = obj;
}
/*
@@ -1169,9 +1258,9 @@ gc_start(mrb_state *mrb, mrb_value obj)
static mrb_value
gc_enable(mrb_state *mrb, mrb_value obj)
{
- mrb_bool old = mrb->gc_disabled;
+ mrb_bool old = mrb->gc.disabled;
- mrb->gc_disabled = FALSE;
+ mrb->gc.disabled = FALSE;
return mrb_bool_value(old);
}
@@ -1191,9 +1280,9 @@ gc_enable(mrb_state *mrb, mrb_value obj)
static mrb_value
gc_disable(mrb_state *mrb, mrb_value obj)
{
- mrb_bool old = mrb->gc_disabled;
+ mrb_bool old = mrb->gc.disabled;
- mrb->gc_disabled = TRUE;
+ mrb->gc.disabled = TRUE;
return mrb_bool_value(old);
}
@@ -1209,7 +1298,7 @@ gc_disable(mrb_state *mrb, mrb_value obj)
static mrb_value
gc_interval_ratio_get(mrb_state *mrb, mrb_value obj)
{
- return mrb_fixnum_value(mrb->gc_interval_ratio);
+ return mrb_fixnum_value(mrb->gc.interval_ratio);
}
/*
@@ -1227,7 +1316,7 @@ gc_interval_ratio_set(mrb_state *mrb, mrb_value obj)
mrb_int ratio;
mrb_get_args(mrb, "i", &ratio);
- mrb->gc_interval_ratio = ratio;
+ mrb->gc.interval_ratio = ratio;
return mrb_nil_value();
}
@@ -1242,7 +1331,7 @@ gc_interval_ratio_set(mrb_state *mrb, mrb_value obj)
static mrb_value
gc_step_ratio_get(mrb_state *mrb, mrb_value obj)
{
- return mrb_fixnum_value(mrb->gc_step_ratio);
+ return mrb_fixnum_value(mrb->gc.step_ratio);
}
/*
@@ -1260,24 +1349,24 @@ gc_step_ratio_set(mrb_state *mrb, mrb_value obj)
mrb_int ratio;
mrb_get_args(mrb, "i", &ratio);
- mrb->gc_step_ratio = ratio;
+ mrb->gc.step_ratio = ratio;
return mrb_nil_value();
}
static void
-change_gen_gc_mode(mrb_state *mrb, mrb_bool enable)
+change_gen_gc_mode(mrb_state *mrb, mrb_gc *gc, mrb_bool enable)
{
- if (is_generational(mrb) && !enable) {
- clear_all_old(mrb);
- mrb_assert(mrb->gc_state == GC_STATE_ROOT);
- mrb->gc_full = FALSE;
+ if (is_generational(gc) && !enable) {
+ clear_all_old(mrb, gc);
+ mrb_assert(gc->state == MRB_GC_STATE_ROOT);
+ gc->full = FALSE;
}
- else if (!is_generational(mrb) && enable) {
- incremental_gc_until(mrb, GC_STATE_ROOT);
- mrb->majorgc_old_threshold = mrb->gc_live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO;
- mrb->gc_full = FALSE;
+ else if (!is_generational(gc) && enable) {
+ incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT);
+ gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO;
+ gc->full = FALSE;
}
- mrb->is_generational_gc_mode = enable;
+ gc->generational = enable;
}
/*
@@ -1291,7 +1380,7 @@ change_gen_gc_mode(mrb_state *mrb, mrb_bool enable)
static mrb_value
gc_generational_mode_get(mrb_state *mrb, mrb_value self)
{
- return mrb_bool_value(mrb->is_generational_gc_mode);
+ return mrb_bool_value(mrb->gc.generational);
}
/*
@@ -1308,21 +1397,22 @@ gc_generational_mode_set(mrb_state *mrb, mrb_value self)
mrb_bool enable;
mrb_get_args(mrb, "b", &enable);
- if (mrb->is_generational_gc_mode != enable)
- change_gen_gc_mode(mrb, enable);
+ if (mrb->gc.generational != enable)
+ change_gen_gc_mode(mrb, &mrb->gc, enable);
return mrb_bool_value(enable);
}
-void
-mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, void *data)
+
+static void
+gc_each_objects(mrb_state *mrb, mrb_gc *gc, mrb_each_object_callback *callback, void *data)
{
- struct heap_page* page = mrb->heaps;
+ mrb_heap_page* page = gc->heaps;
while (page != NULL) {
RVALUE *p, *pend;
- p = page->objects;
+ p = objects(page);
pend = p + MRB_HEAP_PAGE_SIZE;
for (;p < pend; p++) {
(*callback)(mrb, &p->as.basic, data);
@@ -1332,6 +1422,12 @@ mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, vo
}
}
+void
+mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, void *data)
+{
+ gc_each_objects(mrb, &mrb->gc, callback, data);
+}
+
#ifdef GC_TEST
#ifdef GC_DEBUG
static mrb_value gc_test(mrb_state *, mrb_value);
@@ -1368,42 +1464,43 @@ test_mrb_field_write_barrier(void)
{
mrb_state *mrb = mrb_open();
struct RBasic *obj, *value;
+ mrb_gc *gc = &mrb->gc;
puts("test_mrb_field_write_barrier");
- mrb->is_generational_gc_mode = FALSE;
+ gc->generational = FALSE;
obj = mrb_basic_ptr(mrb_ary_new(mrb));
value = mrb_basic_ptr(mrb_str_new_lit(mrb, "value"));
paint_black(obj);
- paint_partial_white(mrb, value);
+ paint_partial_white(gc, value);
- puts(" in GC_STATE_MARK");
- mrb->gc_state = GC_STATE_MARK;
+ puts(" in MRB_GC_STATE_MARK");
+ gc->state = MRB_GC_STATE_MARK;
mrb_field_write_barrier(mrb, obj, value);
mrb_assert(is_gray(value));
- puts(" in GC_STATE_SWEEP");
- paint_partial_white(mrb, value);
- mrb->gc_state = GC_STATE_SWEEP;
+ puts(" in MRB_GC_STATE_SWEEP");
+ paint_partial_white(gc, value);
+ gc->state = MRB_GC_STATE_SWEEP;
mrb_field_write_barrier(mrb, obj, value);
- mrb_assert(obj->color & mrb->current_white_part);
- mrb_assert(value->color & mrb->current_white_part);
+ mrb_assert(obj->color & gc->current_white_part);
+ mrb_assert(value->color & gc->current_white_part);
puts(" fail with black");
- mrb->gc_state = GC_STATE_MARK;
+ gc->state = MRB_GC_STATE_MARK;
paint_white(obj);
- paint_partial_white(mrb, value);
+ paint_partial_white(gc, value);
mrb_field_write_barrier(mrb, obj, value);
- mrb_assert(obj->color & mrb->current_white_part);
+ mrb_assert(obj->color & gc->current_white_part);
puts(" fail with gray");
- mrb->gc_state = GC_STATE_MARK;
+ gc->state = MRB_GC_STATE_MARK;
paint_black(obj);
paint_gray(value);
mrb_field_write_barrier(mrb, obj, value);
@@ -1416,9 +1513,9 @@ test_mrb_field_write_barrier(void)
obj = mrb_basic_ptr(mrb_ary_new(mrb));
mrb_value value = mrb_str_new_lit(mrb, "value");
paint_black(obj);
- paint_partial_white(mrb, mrb_basic_ptr(value));
+ paint_partial_white(gc, mrb_basic_ptr(value));
- mrb->gc_state = GC_STATE_MARK;
+ gc->state = MRB_GC_STATE_MARK;
mrb_field_write_barrier_value(mrb, obj, value);
mrb_assert(is_gray(mrb_basic_ptr(value)));
@@ -1432,17 +1529,18 @@ test_mrb_write_barrier(void)
{
mrb_state *mrb = mrb_open();
struct RBasic *obj;
+ mrb_gc *gc = &mrb->gc;
puts("test_mrb_write_barrier");
obj = mrb_basic_ptr(mrb_ary_new(mrb));
paint_black(obj);
- puts(" in GC_STATE_MARK");
- mrb->gc_state = GC_STATE_MARK;
+ puts(" in MRB_GC_STATE_MARK");
+ gc->state = MRB_GC_STATE_MARK;
mrb_write_barrier(mrb, obj);
mrb_assert(is_gray(obj));
- mrb_assert(mrb->atomic_gray_list == obj);
+ mrb_assert(gc->atomic_gray_list == obj);
puts(" fail with gray");
@@ -1459,19 +1557,20 @@ test_add_gray_list(void)
{
mrb_state *mrb = mrb_open();
struct RBasic *obj1, *obj2;
+ mrb_gc *gc = &mrb->gc;
puts("test_add_gray_list");
- change_gen_gc_mode(mrb, FALSE);
- mrb_assert(mrb->gray_list == NULL);
+ change_gen_gc_mode(mrb, gc, FALSE);
+ mrb_assert(gc->gray_list == NULL);
obj1 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test"));
- add_gray_list(mrb, obj1);
- mrb_assert(mrb->gray_list == obj1);
+ add_gray_list(mrb, gc, obj1);
+ mrb_assert(gc->gray_list == obj1);
mrb_assert(is_gray(obj1));
obj2 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test"));
- add_gray_list(mrb, obj2);
- mrb_assert(mrb->gray_list == obj2);
- mrb_assert(mrb->gray_list->gcnext == obj1);
+ add_gray_list(mrb, gc, obj2);
+ mrb_assert(gc->gray_list == obj2);
+ mrb_assert(gc->gray_list->gcnext == obj1);
mrb_assert(is_gray(obj2));
mrb_close(mrb);
@@ -1484,13 +1583,14 @@ test_gc_gray_mark(void)
mrb_value obj_v, value_v;
struct RBasic *obj;
size_t gray_num = 0;
+ mrb_gc *gc = &mrb->gc;
puts("test_gc_gray_mark");
puts(" in MRB_TT_CLASS");
obj = (struct RBasic*)mrb->object_class;
paint_gray(obj);
- gray_num = gc_gray_mark(mrb, obj);
+ gray_num = gc_gray_mark(mrb, gc, obj);
mrb_assert(is_black(obj));
mrb_assert(gray_num > 1);
@@ -1498,9 +1598,9 @@ test_gc_gray_mark(void)
obj_v = mrb_ary_new(mrb);
value_v = mrb_str_new_lit(mrb, "test");
paint_gray(mrb_basic_ptr(obj_v));
- paint_partial_white(mrb, mrb_basic_ptr(value_v));
+ paint_partial_white(gc, mrb_basic_ptr(value_v));
mrb_ary_push(mrb, obj_v, value_v);
- gray_num = gc_gray_mark(mrb, mrb_basic_ptr(obj_v));
+ gray_num = gc_gray_mark(mrb, gc, mrb_basic_ptr(obj_v));
mrb_assert(is_black(mrb_basic_ptr(obj_v)));
mrb_assert(is_gray(mrb_basic_ptr(value_v)));
mrb_assert(gray_num == 1);
@@ -1514,32 +1614,33 @@ test_incremental_gc(void)
mrb_state *mrb = mrb_open();
size_t max = ~0, live = 0, total = 0, freed = 0;
RVALUE *free;
- struct heap_page *page;
+ mrb_heap_page *page;
+ mrb_gc *gc = &mrb->gc;
puts("test_incremental_gc");
- change_gen_gc_mode(mrb, FALSE);
+ change_gen_gc_mode(mrb, gc, FALSE);
puts(" in mrb_full_gc");
mrb_full_gc(mrb);
- mrb_assert(mrb->gc_state == GC_STATE_ROOT);
- puts(" in GC_STATE_ROOT");
- incremental_gc(mrb, max);
- mrb_assert(mrb->gc_state == GC_STATE_MARK);
- puts(" in GC_STATE_MARK");
- incremental_gc_until(mrb, GC_STATE_SWEEP);
- mrb_assert(mrb->gc_state == GC_STATE_SWEEP);
+ mrb_assert(gc->state == MRB_GC_STATE_ROOT);
+ puts(" in MRB_GC_STATE_ROOT");
+ incremental_gc(mrb, gc, max);
+ mrb_assert(gc->state == MRB_GC_STATE_MARK);
+ puts(" in MRB_GC_STATE_MARK");
+ incremental_gc_until(mrb, gc, MRB_GC_STATE_SWEEP);
+ mrb_assert(gc->state == MRB_GC_STATE_SWEEP);
- puts(" in GC_STATE_SWEEP");
- page = mrb->heaps;
+ puts(" in MRB_GC_STATE_SWEEP");
+ page = gc->heaps;
while (page) {
- RVALUE *p = page->objects;
+ RVALUE *p = objects(page);
RVALUE *e = p + MRB_HEAP_PAGE_SIZE;
while (p<e) {
if (is_black(&p->as.basic)) {
live++;
}
- if (is_gray(&p->as.basic) && !is_dead(mrb, &p->as.basic)) {
+ if (is_gray(&p->as.basic) && !is_dead(gc, &p->as.basic)) {
printf("%p\n", &p->as.basic);
}
p++;
@@ -1548,44 +1649,44 @@ test_incremental_gc(void)
total += MRB_HEAP_PAGE_SIZE;
}
- mrb_assert(mrb->gray_list == NULL);
+ mrb_assert(gc->gray_list == NULL);
- incremental_gc(mrb, max);
- mrb_assert(mrb->gc_state == GC_STATE_SWEEP);
+ incremental_gc(mrb, gc, max);
+ mrb_assert(gc->state == MRB_GC_STATE_SWEEP);
- incremental_gc(mrb, max);
- mrb_assert(mrb->gc_state == GC_STATE_ROOT);
+ incremental_gc(mrb, gc, max);
+ mrb_assert(gc->state == MRB_GC_STATE_ROOT);
- free = (RVALUE*)mrb->heaps->freelist;
+ free = (RVALUE*)gc->heaps->freelist;
while (free) {
freed++;
free = (RVALUE*)free->as.free.next;
}
- mrb_assert(mrb->live == live);
- mrb_assert(mrb->live == total-freed);
+ mrb_assert(gc->live == live);
+ mrb_assert(gc->live == total-freed);
puts("test_incremental_gc(gen)");
- incremental_gc_until(mrb, GC_STATE_SWEEP);
- change_gen_gc_mode(mrb, TRUE);
+ incremental_gc_until(mrb, gc, MRB_GC_STATE_SWEEP);
+ change_gen_gc_mode(mrb, gc, TRUE);
- mrb_assert(mrb->gc_full == FALSE);
- mrb_assert(mrb->gc_state == GC_STATE_ROOT);
+ mrb_assert(gc->full == FALSE);
+ mrb_assert(gc->state == MRB_GC_STATE_ROOT);
puts(" in minor");
- mrb_assert(is_minor_gc(mrb));
- mrb_assert(mrb->majorgc_old_threshold > 0);
- mrb->majorgc_old_threshold = 0;
+ mrb_assert(is_minor_gc(gc));
+ mrb_assert(gc->majorgc_old_threshold > 0);
+ gc->majorgc_old_threshold = 0;
mrb_incremental_gc(mrb);
- mrb_assert(mrb->gc_full == TRUE);
- mrb_assert(mrb->gc_state == GC_STATE_ROOT);
+ mrb_assert(gc->full == TRUE);
+ mrb_assert(gc->state == MRB_GC_STATE_ROOT);
puts(" in major");
- mrb_assert(is_major_gc(mrb));
+ mrb_assert(is_major_gc(gc));
do {
mrb_incremental_gc(mrb);
- } while (mrb->gc_state != GC_STATE_ROOT);
- mrb_assert(mrb->gc_full == FALSE);
+ } while (gc->state != MRB_GC_STATE_ROOT);
+ mrb_assert(gc->full == FALSE);
mrb_close(mrb);
}
@@ -1594,18 +1695,19 @@ void
test_incremental_sweep_phase(void)
{
mrb_state *mrb = mrb_open();
+ mrb_gc *gc = &mrb->gc;
puts("test_incremental_sweep_phase");
- add_heap(mrb);
- mrb->sweeps = mrb->heaps;
+ add_heap(mrb, gc);
+ gc->sweeps = gc->heaps;
- mrb_assert(mrb->heaps->next->next == NULL);
- mrb_assert(mrb->free_heaps->next->next == NULL);
- incremental_sweep_phase(mrb, MRB_HEAP_PAGE_SIZE*3);
+ mrb_assert(gc->heaps->next->next == NULL);
+ mrb_assert(gc->free_heaps->next->next == NULL);
+ incremental_sweep_phase(mrb, gc, MRB_HEAP_PAGE_SIZE * 3);
- mrb_assert(mrb->heaps->next == NULL);
- mrb_assert(mrb->heaps == mrb->free_heaps);
+ mrb_assert(gc->heaps->next == NULL);
+ mrb_assert(gc->heaps == gc->free_heaps);
mrb_close(mrb);
}
diff --git a/src/hash.c b/src/hash.c
index ffb8bd931..ac7256987 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -4,13 +4,13 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/class.h"
-#include "mruby/hash.h"
-#include "mruby/khash.h"
-#include "mruby/string.h"
-#include "mruby/variable.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/hash.h>
+#include <mruby/khash.h>
+#include <mruby/string.h>
+#include <mruby/variable.h>
/* a function to get hash value of a float number */
mrb_int mrb_float_id(mrb_float f);
@@ -294,22 +294,22 @@ mrb_hash_modify(mrb_state *mrb, mrb_value hash)
* default value. It is the block's responsibility to store the value
* in the hash if required.
*
- * h = Hash.new("Go Fish")
- * h["a"] = 100
- * h["b"] = 200
- * h["a"] #=> 100
- * h["c"] #=> "Go Fish"
- * # The following alters the single default object
- * h["c"].upcase! #=> "GO FISH"
- * h["d"] #=> "GO FISH"
- * h.keys #=> ["a", "b"]
- *
- * # While this creates a new default object each time
- * h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
- * h["c"] #=> "Go Fish: c"
- * h["c"].upcase! #=> "GO FISH: C"
- * h["d"] #=> "Go Fish: d"
- * h.keys #=> ["c", "d"]
+ * h = Hash.new("Go Fish")
+ * h["a"] = 100
+ * h["b"] = 200
+ * h["a"] #=> 100
+ * h["c"] #=> "Go Fish"
+ * # The following alters the single default object
+ * h["c"].upcase! #=> "GO FISH"
+ * h["d"] #=> "GO FISH"
+ * h.keys #=> ["a", "b"]
+ *
+ * # While this creates a new default object each time
+ * h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
+ * h["c"] #=> "Go Fish: c"
+ * h["c"].upcase! #=> "GO FISH: C"
+ * h["d"] #=> "Go Fish: d"
+ * h.keys #=> ["c", "d"]
*
*/
@@ -517,10 +517,10 @@ mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key)
* key is not found, pass in the key and return the result of
* <i>block</i>.
*
- * h = { "a" => 100, "b" => 200 }
- * h.delete("a") #=> 100
- * h.delete("z") #=> nil
- * h.delete("z") { |el| "#{el} not found" } #=> "z not found"
+ * h = { "a" => 100, "b" => 200 }
+ * h.delete("a") #=> 100
+ * h.delete("z") #=> nil
+ * h.delete("z") { |el| "#{el} not found" } #=> "z not found"
*
*/
static mrb_value
@@ -541,9 +541,9 @@ mrb_hash_delete(mrb_state *mrb, mrb_value self)
* two-item array <code>[</code> <i>key, value</i> <code>]</code>, or
* the hash's default value if the hash is empty.
*
- * h = { 1 => "a", 2 => "b", 3 => "c" }
- * h.shift #=> [1, "a"]
- * h #=> {2=>"b", 3=>"c"}
+ * h = { 1 => "a", 2 => "b", 3 => "c" }
+ * h.shift #=> [1, "a"]
+ * h #=> {2=>"b", 3=>"c"}
*/
static mrb_value
@@ -580,10 +580,10 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash)
* call-seq:
* hsh.clear -> hsh
*
- * Removes all key-value pairs from <i>hsh</i>.
+ * Removes all key-value pairs from `hsh`.
*
- * h = { "a" => 100, "b" => 200 } #=> {"a"=>100, "b"=>200}
- * h.clear #=> {}
+ * h = { "a" => 100, "b" => 200 } #=> {"a"=>100, "b"=>200}
+ * h.clear #=> {}
*
*/
@@ -609,10 +609,10 @@ mrb_hash_clear(mrb_state *mrb, mrb_value hash)
* use as a key (a <code>String</code> passed as a key will be
* duplicated and frozen).
*
- * h = { "a" => 100, "b" => 200 }
- * h["a"] = 9
- * h["c"] = 4
- * h #=> {"a"=>9, "b"=>200, "c"=>4}
+ * h = { "a" => 100, "b" => 200 }
+ * h["a"] = 9
+ * h["c"] = 4
+ * h #=> {"a"=>9, "b"=>200, "c"=>4}
*
*/
static mrb_value
@@ -827,7 +827,7 @@ mrb_init_hash(mrb_state *mrb)
{
struct RClass *h;
- h = mrb->hash_class = mrb_define_class(mrb, "Hash", mrb->object_class); /* 15.2.13 */
+ mrb->hash_class = h = mrb_define_class(mrb, "Hash", mrb->object_class); /* 15.2.13 */
MRB_SET_INSTANCE_TT(h, MRB_TT_HASH);
mrb_define_method(mrb, h, "[]", mrb_hash_aget, MRB_ARGS_REQ(1)); /* 15.2.13.4.2 */
diff --git a/src/init.c b/src/init.c
index 955d6e3a1..9a6496df1 100644
--- a/src/init.c
+++ b/src/init.c
@@ -4,7 +4,7 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
+#include <mruby.h>
void mrb_init_symtbl(mrb_state*);
void mrb_init_class(mrb_state*);
diff --git a/src/kernel.c b/src/kernel.c
index 225f7fa54..af6a49be1 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -4,13 +4,13 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/class.h"
-#include "mruby/proc.h"
-#include "mruby/string.h"
-#include "mruby/variable.h"
-#include "mruby/error.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/proc.h>
+#include <mruby/string.h>
+#include <mruby/variable.h>
+#include <mruby/error.h>
typedef enum {
NOEX_PUBLIC = 0x00,
@@ -654,13 +654,13 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* kl
{
khint_t i;
mrb_value ary;
- mrb_bool prepended;
+ mrb_bool prepended = FALSE;
struct RClass* oldklass;
khash_t(st)* set = kh_init(st, mrb);
if (!recur && (klass->flags & MRB_FLAG_IS_PREPENDED)) {
MRB_CLASS_ORIGIN(klass);
- prepended = 1;
+ prepended = TRUE;
}
oldklass = 0;
@@ -1097,7 +1097,7 @@ mrb_init_kernel(mrb_state *mrb)
{
struct RClass *krn;
- krn = mrb->kernel_module = mrb_define_module(mrb, "Kernel"); /* 15.3.1 */
+ mrb->kernel_module = krn = mrb_define_module(mrb, "Kernel"); /* 15.3.1 */
mrb_define_class_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.2 */
mrb_define_class_method(mrb, krn, "global_variables", mrb_f_global_variables, MRB_ARGS_NONE()); /* 15.3.1.2.4 */
mrb_define_class_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.5 */
diff --git a/src/load.c b/src/load.c
index 36fae9aee..da88f0d3a 100644
--- a/src/load.c
+++ b/src/load.c
@@ -7,12 +7,12 @@
#include <limits.h>
#include <stdlib.h>
#include <string.h>
-#include "mruby/dump.h"
-#include "mruby/irep.h"
-#include "mruby/proc.h"
-#include "mruby/string.h"
-#include "mruby/debug.h"
-#include "mruby/error.h"
+#include <mruby/dump.h>
+#include <mruby/irep.h>
+#include <mruby/proc.h>
+#include <mruby/string.h>
+#include <mruby/debug.h>
+#include <mruby/error.h>
#if SIZE_MAX < UINT32_MAX
# error size_t must be at least 32 bits wide
@@ -642,7 +642,7 @@ mrb_load_irep(mrb_state *mrb, const uint8_t *bin)
return mrb_load_irep_cxt(mrb, bin, NULL);
}
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
MRB_API mrb_irep*
mrb_read_irep_file(mrb_state *mrb, FILE* fp)
@@ -704,4 +704,4 @@ mrb_load_irep_file(mrb_state *mrb, FILE* fp)
{
return mrb_load_irep_file_cxt(mrb, fp, NULL);
}
-#endif /* ENABLE_STDIO */
+#endif /* MRB_DISABLE_STDIO */
diff --git a/src/numeric.c b/src/numeric.c
index 1a3c903f0..7b49b29f7 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -9,10 +9,10 @@
#include <math.h>
#include <stdlib.h>
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/numeric.h"
-#include "mruby/string.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/numeric.h>
+#include <mruby/string.h>
#ifdef MRB_USE_FLOAT
#define floor(f) floorf(f)
@@ -821,14 +821,28 @@ static mrb_value
lshift(mrb_state *mrb, mrb_int val, mrb_int width)
{
mrb_assert(width > 0);
- if (width > NUMERIC_SHIFT_WIDTH_MAX) {
+ if (val > 0) {
+ if ((width > NUMERIC_SHIFT_WIDTH_MAX) ||
+ (val > (MRB_INT_MAX >> width))) {
+ goto bit_overflow;
+ }
+ } else {
+ if ((width > NUMERIC_SHIFT_WIDTH_MAX) ||
+ (val < (MRB_INT_MIN >> width))) {
+ goto bit_overflow;
+ }
+ }
+
+ return mrb_fixnum_value(val << width);
+
+bit_overflow:
+ {
mrb_float f = (mrb_float)val;
while (width--) {
f *= 2;
}
return mrb_float_value(mrb, f);
}
- return mrb_fixnum_value(val << width);
}
static mrb_value
@@ -856,7 +870,7 @@ fix_shift_get_width(mrb_state *mrb, mrb_int *width)
/* 15.2.8.3.12 */
/*
* call-seq:
- * fix << count -> integer
+ * fix << count -> integer or float
*
* Shifts _fix_ left _count_ positions (right if _count_ is negative).
*/
@@ -881,7 +895,7 @@ fix_lshift(mrb_state *mrb, mrb_value x)
/* 15.2.8.3.13 */
/*
* call-seq:
- * fix >> count -> integer
+ * fix >> count -> integer or float
*
* Shifts _fix_ right _count_ positions (left if _count_ is negative).
*/
@@ -950,7 +964,12 @@ mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x)
if (isnan(d)) {
mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN");
}
- z = (mrb_int)d;
+ if (FIXABLE(d)) {
+ z = (mrb_int)d;
+ }
+ else {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "number (%S) too big for integer", x);
+ }
}
return mrb_fixnum_value(z);
}
@@ -1161,7 +1180,7 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method(mrb, integer, "to_int", int_to_i, MRB_ARGS_NONE());
/* Fixnum Class */
- fixnum = mrb->fixnum_class = mrb_define_class(mrb, "Fixnum", integer);
+ mrb->fixnum_class = fixnum = mrb_define_class(mrb, "Fixnum", integer);
mrb_define_method(mrb, fixnum, "+", fix_plus, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */
mrb_define_method(mrb, fixnum, "-", fix_minus, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */
mrb_define_method(mrb, fixnum, "*", fix_mul, MRB_ARGS_REQ(1)); /* 15.2.8.3.3 */
@@ -1181,7 +1200,7 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method(mrb, fixnum, "divmod", fix_divmod, MRB_ARGS_REQ(1)); /* 15.2.8.3.30 (x) */
/* Float Class */
- fl = mrb->float_class = mrb_define_class(mrb, "Float", numeric); /* 15.2.9 */
+ mrb->float_class = fl = mrb_define_class(mrb, "Float", numeric); /* 15.2.9 */
mrb_undef_class_method(mrb, fl, "new");
mrb_define_method(mrb, fl, "+", flo_plus, MRB_ARGS_REQ(1)); /* 15.2.9.3.1 */
mrb_define_method(mrb, fl, "-", flo_minus, MRB_ARGS_REQ(1)); /* 15.2.9.3.2 */
diff --git a/src/object.c b/src/object.c
index 2e0bd245f..9d768664e 100644
--- a/src/object.c
+++ b/src/object.c
@@ -4,10 +4,10 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include "mruby/class.h"
-#include "mruby/numeric.h"
-#include "mruby/string.h"
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/numeric.h>
+#include <mruby/string.h>
MRB_API mrb_bool
mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2)
@@ -264,7 +264,7 @@ mrb_init_object(mrb_state *mrb)
struct RClass *t;
struct RClass *f;
- n = mrb->nil_class = mrb_define_class(mrb, "NilClass", mrb->object_class);
+ mrb->nil_class = n = mrb_define_class(mrb, "NilClass", mrb->object_class);
mrb_undef_class_method(mrb, n, "new");
mrb_define_method(mrb, n, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.4.3.1 */
mrb_define_method(mrb, n, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.4.3.2 */
@@ -273,7 +273,7 @@ mrb_init_object(mrb_state *mrb)
mrb_define_method(mrb, n, "to_s", nil_to_s, MRB_ARGS_NONE()); /* 15.2.4.3.5 */
mrb_define_method(mrb, n, "inspect", nil_inspect, MRB_ARGS_NONE());
- t = mrb->true_class = mrb_define_class(mrb, "TrueClass", mrb->object_class);
+ mrb->true_class = t = mrb_define_class(mrb, "TrueClass", mrb->object_class);
mrb_undef_class_method(mrb, t, "new");
mrb_define_method(mrb, t, "&", true_and, MRB_ARGS_REQ(1)); /* 15.2.5.3.1 */
mrb_define_method(mrb, t, "^", true_xor, MRB_ARGS_REQ(1)); /* 15.2.5.3.2 */
@@ -281,7 +281,7 @@ mrb_init_object(mrb_state *mrb)
mrb_define_method(mrb, t, "|", true_or, MRB_ARGS_REQ(1)); /* 15.2.5.3.4 */
mrb_define_method(mrb, t, "inspect", true_to_s, MRB_ARGS_NONE());
- f = mrb->false_class = mrb_define_class(mrb, "FalseClass", mrb->object_class);
+ mrb->false_class = f = mrb_define_class(mrb, "FalseClass", mrb->object_class);
mrb_undef_class_method(mrb, f, "new");
mrb_define_method(mrb, f, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.6.3.1 */
mrb_define_method(mrb, f, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.6.3.2 */
diff --git a/src/opcode.h b/src/opcode.h
index 2446f92ed..fe4d17a21 100644
--- a/src/opcode.h
+++ b/src/opcode.h
@@ -1,2 +1,2 @@
/* this header file is to be removed soon. */
-#include "mruby/opcode.h"
+#include <mruby/opcode.h>
diff --git a/src/pool.c b/src/pool.c
index 285cca6c3..18f66fc27 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -7,7 +7,7 @@
#include <stddef.h>
#include <stdint.h>
#include <string.h>
-#include "mruby.h"
+#include <mruby.h>
/* configuration section */
/* allocated memory address should be multiple of POOL_ALIGNMENT */
diff --git a/src/print.c b/src/print.c
index 077fa4f06..03b5eadfa 100644
--- a/src/print.c
+++ b/src/print.c
@@ -4,11 +4,11 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include "mruby/string.h"
-#include "mruby/variable.h"
+#include <mruby.h>
+#include <mruby/string.h>
+#include <mruby/variable.h>
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
static void
printstr(mrb_value obj, FILE *stream)
{
@@ -24,35 +24,24 @@ printstr(mrb_value obj, FILE *stream)
MRB_API void
mrb_p(mrb_state *mrb, mrb_value obj)
{
- mrb_value val = mrb_inspect(mrb, obj);
-
- printstr(val, stdout);
+ printstr(mrb_inspect(mrb, obj), stdout);
}
MRB_API void
mrb_print_error(mrb_state *mrb)
{
- mrb_value s;
-
mrb_print_backtrace(mrb);
- s = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0);
- printstr(s, stderr);
+ printstr(mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0), stderr);
}
MRB_API void
mrb_show_version(mrb_state *mrb)
{
- mrb_value msg;
-
- msg = mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_DESCRIPTION"));
- printstr(msg, stdout);
+ printstr(mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_DESCRIPTION")), stdout);
}
MRB_API void
mrb_show_copyright(mrb_state *mrb)
{
- mrb_value msg;
-
- msg = mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_COPYRIGHT"));
- printstr(msg, stdout);
+ printstr(mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_COPYRIGHT")), stdout);
}
diff --git a/src/proc.c b/src/proc.c
index 8a2b6bbb6..34037b167 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -4,10 +4,10 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include "mruby/class.h"
-#include "mruby/proc.h"
-#include "mruby/opcode.h"
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/proc.h>
+#include <mruby/opcode.h>
static mrb_code call_iseq[] = {
MKOP_A(OP_CALL, 0),
diff --git a/src/range.c b/src/range.c
index b58b6a1c8..bc8b11419 100644
--- a/src/range.c
+++ b/src/range.c
@@ -4,11 +4,11 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include "mruby/class.h"
-#include "mruby/range.h"
-#include "mruby/string.h"
-#include "mruby/array.h"
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/range.h>
+#include <mruby/string.h>
+#include <mruby/array.h>
#define RANGE_CLASS (mrb_class_get(mrb, "Range"))
diff --git a/src/state.c b/src/state.c
index 2efd34334..c8c0658e4 100644
--- a/src/state.c
+++ b/src/state.c
@@ -6,16 +6,18 @@
#include <stdlib.h>
#include <string.h>
-#include "mruby.h"
-#include "mruby/irep.h"
-#include "mruby/variable.h"
-#include "mruby/debug.h"
-#include "mruby/string.h"
+#include <mruby.h>
+#include <mruby/irep.h>
+#include <mruby/variable.h>
+#include <mruby/debug.h>
+#include <mruby/string.h>
-void mrb_init_heap(mrb_state*);
void mrb_init_core(mrb_state*);
void mrb_init_mrbgems(mrb_state*);
+void mrb_gc_init(mrb_state*, mrb_gc *gc);
+void mrb_gc_destroy(mrb_state*, mrb_gc *gc);
+
static mrb_value
inspect_main(mrb_state *mrb, mrb_value mod)
{
@@ -35,15 +37,9 @@ mrb_open_core(mrb_allocf f, void *ud)
*mrb = mrb_state_zero;
mrb->allocf_ud = ud;
mrb->allocf = f;
- mrb->current_white_part = MRB_GC_WHITE_A;
mrb->atexit_stack_len = 0;
-#ifndef MRB_GC_FIXED_ARENA
- mrb->arena = (struct RBasic**)mrb_malloc(mrb, sizeof(struct RBasic*)*MRB_GC_ARENA_SIZE);
- mrb->arena_capa = MRB_GC_ARENA_SIZE;
-#endif
-
- mrb_init_heap(mrb);
+ mrb_gc_init(mrb, &mrb->gc);
mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
*mrb->c = mrb_context_zero;
mrb->root_c = mrb->c;
@@ -122,7 +118,6 @@ mrb_open_allocf(mrb_allocf f, void *ud)
}
void mrb_free_symtbl(mrb_state *mrb);
-void mrb_free_heap(mrb_state *mrb);
void
mrb_irep_incref(mrb_state *mrb, mrb_irep *irep)
@@ -234,6 +229,7 @@ mrb_free_context(mrb_state *mrb, struct mrb_context *c)
MRB_API void
mrb_close(mrb_state *mrb)
{
+ if (!mrb) return;
if (mrb->atexit_stack_len > 0) {
mrb_int i;
for (i = mrb->atexit_stack_len; i > 0; --i) {
@@ -248,11 +244,8 @@ mrb_close(mrb_state *mrb)
mrb_gc_free_gv(mrb);
mrb_free_context(mrb, mrb->root_c);
mrb_free_symtbl(mrb);
- mrb_free_heap(mrb);
mrb_alloca_free(mrb);
-#ifndef MRB_GC_FIXED_ARENA
- mrb_free(mrb, mrb->arena);
-#endif
+ mrb_gc_destroy(mrb, &mrb->gc);
mrb_free(mrb, mrb);
}
diff --git a/src/string.c b/src/string.c
index e93fd4606..7983a925e 100644
--- a/src/string.c
+++ b/src/string.c
@@ -9,14 +9,12 @@
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/class.h"
-#include "mruby/range.h"
-#include "mruby/string.h"
-#include "mruby/re.h"
-
-const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/range.h>
+#include <mruby/string.h>
+#include <mruby/re.h>
typedef struct mrb_shared_string {
mrb_bool nofree : 1;
@@ -25,198 +23,7 @@ typedef struct mrb_shared_string {
mrb_int len;
} mrb_shared_string;
-static mrb_value str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2);
-static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
-
-MRB_API mrb_int
-mrb_str_strlen(mrb_state *mrb, struct RString *s)
-{
- mrb_int i, max = RSTR_LEN(s);
- char *p = RSTR_PTR(s);
-
- if (!p) return 0;
- for (i=0; i<max; i++) {
- if (p[i] == '\0') {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
- }
- }
- return max;
-}
-
-#ifdef _WIN32
-#include <windows.h>
-
-char*
-mrb_utf8_from_locale(const char *str, size_t len)
-{
- wchar_t* wcsp;
- char* mbsp;
- size_t mbssize, wcssize;
-
- if (len == 0)
- return strdup("");
- if (len == -1)
- len = strlen(str);
- wcssize = MultiByteToWideChar(GetACP(), 0, str, len, NULL, 0);
- wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
- if (!wcsp)
- return NULL;
- wcssize = MultiByteToWideChar(GetACP(), 0, str, len, wcsp, wcssize + 1);
- wcsp[wcssize] = 0;
-
- mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsp, -1, NULL, 0, NULL, NULL);
- mbsp = (char*) malloc((mbssize + 1));
- if (!mbsp) {
- free(wcsp);
- return NULL;
- }
- mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsp, -1, mbsp, mbssize, NULL, NULL);
- mbsp[mbssize] = 0;
- free(wcsp);
- return mbsp;
-}
-
-char*
-mrb_locale_from_utf8(const char *utf8, size_t len)
-{
- wchar_t* wcsp;
- char* mbsp;
- size_t mbssize, wcssize;
-
- if (len == 0)
- return strdup("");
- if (len == -1)
- len = strlen(utf8);
- wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0);
- wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
- if (!wcsp)
- return NULL;
- wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, len, wcsp, wcssize + 1);
- wcsp[wcssize] = 0;
- mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsp, -1, NULL, 0, NULL, NULL);
- mbsp = (char*) malloc((mbssize + 1));
- if (!mbsp) {
- free(wcsp);
- return NULL;
- }
- mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsp, -1, mbsp, mbssize, NULL, NULL);
- mbsp[mbssize] = 0;
- free(wcsp);
- return mbsp;
-}
-#endif
-
-static inline void
-resize_capa(mrb_state *mrb, struct RString *s, mrb_int capacity)
-{
- if (RSTR_EMBED_P(s)) {
- if (RSTRING_EMBED_LEN_MAX < capacity) {
- char *const tmp = (char *)mrb_malloc(mrb, capacity+1);
- const mrb_int len = RSTR_EMBED_LEN(s);
- memcpy(tmp, s->as.ary, len);
- RSTR_UNSET_EMBED_FLAG(s);
- s->as.heap.ptr = tmp;
- s->as.heap.len = len;
- s->as.heap.aux.capa = capacity;
- }
- }
- else {
- s->as.heap.ptr = (char *)mrb_realloc(mrb, RSTR_PTR(s), capacity+1);
- s->as.heap.aux.capa = capacity;
- }
-}
-
-static void
-str_decref(mrb_state *mrb, mrb_shared_string *shared)
-{
- shared->refcnt--;
- if (shared->refcnt == 0) {
- if (!shared->nofree) {
- mrb_free(mrb, shared->ptr);
- }
- mrb_free(mrb, shared);
- }
-}
-
-static void
-check_frozen(mrb_state *mrb, struct RString *s)
-{
- if (RSTR_FROZEN_P(s)) {
- mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen string");
- }
-}
-
-MRB_API void
-mrb_str_modify(mrb_state *mrb, struct RString *s)
-{
- check_frozen(mrb, s);
- if (RSTR_SHARED_P(s)) {
- mrb_shared_string *shared = s->as.heap.aux.shared;
-
- if (shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) {
- s->as.heap.ptr = shared->ptr;
- s->as.heap.aux.capa = shared->len;
- RSTR_PTR(s)[s->as.heap.len] = '\0';
- mrb_free(mrb, shared);
- }
- else {
- char *ptr, *p;
- mrb_int len;
-
- p = RSTR_PTR(s);
- len = s->as.heap.len;
- ptr = (char *)mrb_malloc(mrb, (size_t)len + 1);
- if (p) {
- memcpy(ptr, p, len);
- }
- ptr[len] = '\0';
- s->as.heap.ptr = ptr;
- s->as.heap.aux.capa = len;
- str_decref(mrb, shared);
- }
- RSTR_UNSET_SHARED_FLAG(s);
- return;
- }
- if (RSTR_NOFREE_P(s)) {
- char *p = s->as.heap.ptr;
-
- s->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)s->as.heap.len+1);
- if (p) {
- memcpy(RSTR_PTR(s), p, s->as.heap.len);
- }
- RSTR_PTR(s)[s->as.heap.len] = '\0';
- s->as.heap.aux.capa = s->as.heap.len;
- RSTR_UNSET_NOFREE_FLAG(s);
- return;
- }
-}
-
-static mrb_value
-mrb_str_freeze(mrb_state *mrb, mrb_value str)
-{
- struct RString *s = mrb_str_ptr(str);
-
- RSTR_SET_FROZEN_FLAG(s);
- return str;
-}
-
-MRB_API mrb_value
-mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len)
-{
- mrb_int slen;
- struct RString *s = mrb_str_ptr(str);
-
- mrb_str_modify(mrb, s);
- slen = RSTR_LEN(s);
- if (len != slen) {
- if (slen < len || slen - len > 256) {
- resize_capa(mrb, s, len);
- }
- RSTR_SET_LEN(s, len);
- RSTR_PTR(s)[len] = '\0'; /* sentinel */
- }
- return str;
-}
+const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
#define mrb_obj_alloc_string(mrb) ((struct RString*)mrb_obj_alloc((mrb), MRB_TT_STRING, (mrb)->string_class))
@@ -307,6 +114,26 @@ mrb_str_buf_new(mrb_state *mrb, size_t capa)
return mrb_obj_value(s);
}
+static inline void
+resize_capa(mrb_state *mrb, struct RString *s, mrb_int capacity)
+{
+ if (RSTR_EMBED_P(s)) {
+ if (RSTRING_EMBED_LEN_MAX < capacity) {
+ char *const tmp = (char *)mrb_malloc(mrb, capacity+1);
+ const mrb_int len = RSTR_EMBED_LEN(s);
+ memcpy(tmp, s->as.ary, len);
+ RSTR_UNSET_EMBED_FLAG(s);
+ s->as.heap.ptr = tmp;
+ s->as.heap.len = len;
+ s->as.heap.aux.capa = capacity;
+ }
+ }
+ else {
+ s->as.heap.ptr = (char *)mrb_realloc(mrb, RSTR_PTR(s), capacity+1);
+ s->as.heap.aux.capa = capacity;
+ }
+}
+
static void
str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len)
{
@@ -386,6 +213,18 @@ mrb_str_new_static(mrb_state *mrb, const char *p, size_t len)
return mrb_obj_value(s);
}
+static void
+str_decref(mrb_state *mrb, mrb_shared_string *shared)
+{
+ shared->refcnt--;
+ if (shared->refcnt == 0) {
+ if (!shared->nofree) {
+ mrb_free(mrb, shared->ptr);
+ }
+ mrb_free(mrb, shared);
+ }
+}
+
void
mrb_gc_free_str(mrb_state *mrb, struct RString *str)
{
@@ -397,20 +236,126 @@ mrb_gc_free_str(mrb_state *mrb, struct RString *str)
mrb_free(mrb, str->as.heap.ptr);
}
-MRB_API char*
-mrb_str_to_cstr(mrb_state *mrb, mrb_value str0)
+#ifdef MRB_UTF8_STRING
+static const char utf8len_codepage[256] =
{
- struct RString *s;
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,
+};
- if (!mrb_string_p(str0)) {
- mrb_raise(mrb, E_TYPE_ERROR, "expected String");
+static mrb_int
+utf8len(const char* p, const char* e)
+{
+ mrb_int len;
+ mrb_int i;
+
+ len = utf8len_codepage[(unsigned char)*p];
+ if (p + len > e) return 1;
+ for (i = 1; i < len; ++i)
+ if ((p[i] & 0xc0) != 0x80)
+ return 1;
+ return len;
+}
+
+static mrb_int
+utf8_strlen(mrb_value str, mrb_int len)
+{
+ mrb_int total = 0;
+ char* p = RSTRING_PTR(str);
+ char* e = p;
+ e += len < 0 ? RSTRING_LEN(str) : len;
+ while (p<e) {
+ p += utf8len(p, e);
+ total++;
}
+ return total;
+}
- s = str_new(mrb, RSTRING_PTR(str0), RSTRING_LEN(str0));
- if ((strlen(RSTR_PTR(s)) ^ RSTR_LEN(s)) != 0) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
+#define RSTRING_CHAR_LEN(s) utf8_strlen(s, -1)
+
+/* map character index to byte offset index */
+static mrb_int
+chars2bytes(mrb_value s, mrb_int off, mrb_int idx)
+{
+ 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 = utf8len(p, e);
+ b += n;
+ p += n;
}
- return RSTR_PTR(s);
+ return b;
+}
+
+/* map byte offset to character index */
+static mrb_int
+bytes2chars(char *p, mrb_int bi)
+{
+ mrb_int i, b, n;
+
+ for (b=i=0; b<bi; i++) {
+ n = utf8len(p, p+bi);
+ b += n;
+ p += n;
+ }
+ return i;
+}
+
+#else
+#define RSTRING_CHAR_LEN(s) RSTRING_LEN(s)
+#define chars2bytes(p, off, ci) (ci)
+#define bytes2chars(p, bi) (bi)
+#endif
+
+static inline mrb_int
+mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n)
+{
+ const unsigned char *x = xs, *xe = xs + m;
+ const unsigned char *y = ys;
+ int i, qstable[256];
+
+ /* Preprocessing */
+ for (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 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;
+ }
+ else if (m < 1) {
+ return 0;
+ }
+ else if (m == 1) {
+ const unsigned char *ys = y, *ye = ys + n;
+ for (; y < ye; ++y) {
+ if (*x == *y)
+ return y - ys;
+ }
+ return -1;
+ }
+ return mrb_memsearch_qs((const unsigned char *)x0, m, (const unsigned char *)y0, n);
}
static void
@@ -451,6 +396,339 @@ str_make_shared(mrb_state *mrb, struct RString *s)
}
}
+static mrb_value
+byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
+{
+ struct RString *orig, *s;
+ mrb_shared_string *shared;
+
+ orig = mrb_str_ptr(str);
+ if (RSTR_EMBED_P(orig)) {
+ s = str_new(mrb, orig->as.ary+beg, len);
+ }
+ else {
+ str_make_shared(mrb, orig);
+ shared = orig->as.heap.aux.shared;
+ s = mrb_obj_alloc_string(mrb);
+ s->as.heap.ptr = orig->as.heap.ptr + beg;
+ s->as.heap.len = len;
+ s->as.heap.aux.shared = shared;
+ RSTR_SET_SHARED_FLAG(s);
+ shared->refcnt++;
+ }
+
+ return mrb_obj_value(s);
+}
+#ifdef MRB_UTF8_STRING
+static inline mrb_value
+str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
+{
+ beg = chars2bytes(str, 0, beg);
+ len = chars2bytes(str, beg, len);
+
+ return byte_subseq(mrb, str, beg, len);
+}
+#else
+#define str_subseq(mrb, str, beg, len) byte_subseq(mrb, str, beg, len)
+#endif
+
+static mrb_value
+str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
+{
+ mrb_int clen = RSTRING_CHAR_LEN(str);
+
+ if (len < 0) return mrb_nil_value();
+ if (clen == 0) {
+ len = 0;
+ }
+ else if (beg < 0) {
+ beg = clen + beg;
+ }
+ if (beg > clen) return mrb_nil_value();
+ if (beg < 0) {
+ beg += clen;
+ if (beg < 0) return mrb_nil_value();
+ }
+ if (beg + len > clen)
+ len = clen - beg;
+ if (len <= 0) {
+ len = 0;
+ }
+ return str_subseq(mrb, str, beg, len);
+}
+
+static mrb_int
+str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset)
+{
+ mrb_int pos;
+ char *s, *sptr;
+ mrb_int len, slen;
+
+ len = RSTRING_LEN(str);
+ slen = RSTRING_LEN(sub);
+ if (offset < 0) {
+ offset += len;
+ if (offset < 0) return -1;
+ }
+ if (len - offset < slen) return -1;
+ s = RSTRING_PTR(str);
+ if (offset) {
+ s += offset;
+ }
+ if (slen == 0) return offset;
+ /* need proceed one character at a time */
+ sptr = RSTRING_PTR(sub);
+ slen = RSTRING_LEN(sub);
+ len = RSTRING_LEN(str) - offset;
+ pos = mrb_memsearch(sptr, slen, s, len);
+ if (pos < 0) return pos;
+ return pos + offset;
+}
+
+static void
+check_frozen(mrb_state *mrb, struct RString *s)
+{
+ if (RSTR_FROZEN_P(s)) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen string");
+ }
+}
+
+static mrb_value
+str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
+{
+ long len;
+
+ check_frozen(mrb, s1);
+ len = RSTR_LEN(s2);
+ if (RSTR_SHARED_P(s1)) {
+ str_decref(mrb, s1->as.heap.aux.shared);
+ }
+ else if (!RSTR_EMBED_P(s1) && !RSTR_NOFREE_P(s1)) {
+ mrb_free(mrb, s1->as.heap.ptr);
+ }
+
+ RSTR_UNSET_NOFREE_FLAG(s1);
+
+ if (RSTR_SHARED_P(s2)) {
+L_SHARE:
+ RSTR_UNSET_EMBED_FLAG(s1);
+ s1->as.heap.ptr = s2->as.heap.ptr;
+ s1->as.heap.len = len;
+ s1->as.heap.aux.shared = s2->as.heap.aux.shared;
+ RSTR_SET_SHARED_FLAG(s1);
+ s1->as.heap.aux.shared->refcnt++;
+ }
+ else {
+ if (len <= RSTRING_EMBED_LEN_MAX) {
+ RSTR_UNSET_SHARED_FLAG(s1);
+ RSTR_SET_EMBED_FLAG(s1);
+ memcpy(s1->as.ary, RSTR_PTR(s2), len);
+ RSTR_SET_EMBED_LEN(s1, len);
+ }
+ else {
+ str_make_shared(mrb, s2);
+ goto L_SHARE;
+ }
+ }
+
+ return mrb_obj_value(s1);
+}
+
+static mrb_int
+str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
+{
+ char *s, *sbeg, *t;
+ struct RString *ps = mrb_str_ptr(str);
+ mrb_int len = RSTRING_LEN(sub);
+
+ /* substring longer than string */
+ if (RSTR_LEN(ps) < len) return -1;
+ if (RSTR_LEN(ps) - pos < len) {
+ pos = RSTR_LEN(ps) - len;
+ }
+ sbeg = RSTR_PTR(ps);
+ s = RSTR_PTR(ps) + pos;
+ t = RSTRING_PTR(sub);
+ if (len) {
+ while (sbeg <= s) {
+ if (memcmp(s, t, len) == 0) {
+ return s - RSTR_PTR(ps);
+ }
+ s--;
+ }
+ return -1;
+ }
+ else {
+ return pos;
+ }
+}
+
+MRB_API mrb_int
+mrb_str_strlen(mrb_state *mrb, struct RString *s)
+{
+ mrb_int i, max = RSTR_LEN(s);
+ char *p = RSTR_PTR(s);
+
+ if (!p) return 0;
+ for (i=0; i<max; i++) {
+ if (p[i] == '\0') {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
+ }
+ }
+ return max;
+}
+
+#ifdef _WIN32
+#include <windows.h>
+
+char*
+mrb_utf8_from_locale(const char *str, size_t len)
+{
+ wchar_t* wcsp;
+ char* mbsp;
+ size_t mbssize, wcssize;
+
+ if (len == 0)
+ return strdup("");
+ if (len == -1)
+ len = strlen(str);
+ wcssize = MultiByteToWideChar(GetACP(), 0, str, len, NULL, 0);
+ wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
+ if (!wcsp)
+ return NULL;
+ wcssize = MultiByteToWideChar(GetACP(), 0, str, len, wcsp, wcssize + 1);
+ wcsp[wcssize] = 0;
+
+ mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsp, -1, NULL, 0, NULL, NULL);
+ mbsp = (char*) malloc((mbssize + 1));
+ if (!mbsp) {
+ free(wcsp);
+ return NULL;
+ }
+ mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsp, -1, mbsp, mbssize, NULL, NULL);
+ mbsp[mbssize] = 0;
+ free(wcsp);
+ return mbsp;
+}
+
+char*
+mrb_locale_from_utf8(const char *utf8, size_t len)
+{
+ wchar_t* wcsp;
+ char* mbsp;
+ size_t mbssize, wcssize;
+
+ if (len == 0)
+ return strdup("");
+ if (len == -1)
+ len = strlen(utf8);
+ wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0);
+ wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
+ if (!wcsp)
+ return NULL;
+ wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, len, wcsp, wcssize + 1);
+ wcsp[wcssize] = 0;
+ mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsp, -1, NULL, 0, NULL, NULL);
+ mbsp = (char*) malloc((mbssize + 1));
+ if (!mbsp) {
+ free(wcsp);
+ return NULL;
+ }
+ mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsp, -1, mbsp, mbssize, NULL, NULL);
+ mbsp[mbssize] = 0;
+ free(wcsp);
+ return mbsp;
+}
+#endif
+
+MRB_API void
+mrb_str_modify(mrb_state *mrb, struct RString *s)
+{
+ check_frozen(mrb, s);
+ if (RSTR_SHARED_P(s)) {
+ mrb_shared_string *shared = s->as.heap.aux.shared;
+
+ if (shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) {
+ s->as.heap.ptr = shared->ptr;
+ s->as.heap.aux.capa = shared->len;
+ RSTR_PTR(s)[s->as.heap.len] = '\0';
+ mrb_free(mrb, shared);
+ }
+ else {
+ char *ptr, *p;
+ mrb_int len;
+
+ p = RSTR_PTR(s);
+ len = s->as.heap.len;
+ ptr = (char *)mrb_malloc(mrb, (size_t)len + 1);
+ if (p) {
+ memcpy(ptr, p, len);
+ }
+ ptr[len] = '\0';
+ s->as.heap.ptr = ptr;
+ s->as.heap.aux.capa = len;
+ str_decref(mrb, shared);
+ }
+ RSTR_UNSET_SHARED_FLAG(s);
+ return;
+ }
+ if (RSTR_NOFREE_P(s)) {
+ char *p = s->as.heap.ptr;
+
+ s->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)s->as.heap.len+1);
+ if (p) {
+ memcpy(RSTR_PTR(s), p, s->as.heap.len);
+ }
+ RSTR_PTR(s)[s->as.heap.len] = '\0';
+ s->as.heap.aux.capa = s->as.heap.len;
+ RSTR_UNSET_NOFREE_FLAG(s);
+ return;
+ }
+}
+
+static mrb_value
+mrb_str_freeze(mrb_state *mrb, mrb_value str)
+{
+ struct RString *s = mrb_str_ptr(str);
+
+ RSTR_SET_FROZEN_FLAG(s);
+ return str;
+}
+
+MRB_API mrb_value
+mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len)
+{
+ mrb_int slen;
+ struct RString *s = mrb_str_ptr(str);
+
+ mrb_str_modify(mrb, s);
+ slen = RSTR_LEN(s);
+ if (len != slen) {
+ if (slen < len || slen - len > 256) {
+ resize_capa(mrb, s, len);
+ }
+ RSTR_SET_LEN(s, len);
+ RSTR_PTR(s)[len] = '\0'; /* sentinel */
+ }
+ return str;
+}
+
+MRB_API char*
+mrb_str_to_cstr(mrb_state *mrb, mrb_value str0)
+{
+ struct RString *s;
+
+ if (!mrb_string_p(str0)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "expected String");
+ }
+
+ s = str_new(mrb, RSTRING_PTR(str0), RSTRING_LEN(str0));
+ if ((strlen(RSTR_PTR(s)) ^ RSTR_LEN(s)) != 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
+ }
+ return RSTR_PTR(s);
+}
+
/*
* call-seq: (Caution! String("abcd") change)
* String("abcdefg") = String("abcd") + String("efg")
@@ -519,15 +797,22 @@ mrb_str_plus_m(mrb_state *mrb, mrb_value self)
/* 15.2.10.5.33 */
/*
* call-seq:
- * len = strlen(String("abcd"))
+ * "abcd".size => int
*
* Returns the length of string.
*/
static mrb_value
mrb_str_size(mrb_state *mrb, mrb_value self)
{
- struct RString *s = mrb_str_ptr(self);
- return mrb_fixnum_value(RSTR_LEN(s));
+ mrb_int len = RSTRING_CHAR_LEN(self);
+ return mrb_fixnum_value(len);
+}
+
+static mrb_value
+mrb_str_bytesize(mrb_state *mrb, mrb_value self)
+{
+ mrb_int len = RSTRING_LEN(self);
+ return mrb_fixnum_value(len);
}
/* 15.2.10.5.1 */
@@ -742,77 +1027,6 @@ mrb_regexp_check(mrb_state *mrb, mrb_value obj)
}
}
-static inline mrb_int
-mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n)
-{
- const unsigned char *x = xs, *xe = xs + m;
- const unsigned char *y = ys;
- int i, qstable[256];
-
- /* Preprocessing */
- for (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 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;
- }
- else if (m < 1) {
- return 0;
- }
- else if (m == 1) {
- const unsigned char *ys = y, *ye = ys + n;
- for (; y < ye; ++y) {
- if (*x == *y)
- return y - ys;
- }
- return -1;
- }
- return mrb_memsearch_qs((const unsigned char *)x0, m, (const unsigned char *)y0, n);
-}
-
-static mrb_int
-mrb_str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset)
-{
- mrb_int pos;
- char *s, *sptr;
- mrb_int len, slen;
-
- len = RSTRING_LEN(str);
- slen = RSTRING_LEN(sub);
- if (offset < 0) {
- offset += len;
- if (offset < 0) return -1;
- }
- if (len - offset < slen) return -1;
- s = RSTRING_PTR(str);
- if (offset) {
- s += offset;
- }
- if (slen == 0) return offset;
- /* need proceed one character at a time */
- sptr = RSTRING_PTR(sub);
- slen = RSTRING_LEN(sub);
- len = RSTRING_LEN(str) - offset;
- pos = mrb_memsearch(sptr, slen, s, len);
- if (pos < 0) return pos;
- return pos + offset;
-}
-
MRB_API mrb_value
mrb_str_dup(mrb_state *mrb, mrb_value str)
{
@@ -834,12 +1048,12 @@ mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value indx)
idx = mrb_fixnum(indx);
num_index:
- str = mrb_str_substr(mrb, str, idx, 1);
+ str = str_substr(mrb, str, idx, 1);
if (!mrb_nil_p(str) && RSTRING_LEN(str) == 0) return mrb_nil_value();
return str;
case MRB_TT_STRING:
- if (mrb_str_index(mrb, str, indx, 0) != -1)
+ if (str_index(mrb, str, indx, 0) != -1)
return mrb_str_dup(mrb, indx);
return mrb_nil_value();
@@ -848,9 +1062,9 @@ num_index:
{
mrb_int beg, len;
- len = RSTRING_LEN(str);
+ len = RSTRING_CHAR_LEN(str);
if (mrb_range_beg_len(mrb, indx, &beg, &len, len)) {
- return mrb_str_subseq(mrb, str, beg, len);
+ return str_subseq(mrb, str, beg, len);
}
else {
return mrb_nil_value();
@@ -917,7 +1131,7 @@ mrb_str_aref_m(mrb_state *mrb, mrb_value str)
argc = mrb_get_args(mrb, "o|o", &a1, &a2);
if (argc == 2) {
mrb_regexp_check(mrb, a1);
- return mrb_str_substr(mrb, str, mrb_fixnum(a1), mrb_fixnum(a2));
+ return str_substr(mrb, str, mrb_fixnum(a1), mrb_fixnum(a2));
}
if (argc != 1) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1)", mrb_fixnum_value(argc));
@@ -987,7 +1201,7 @@ mrb_str_capitalize(mrb_state *mrb, mrb_value self)
/* 15.2.10.5.10 */
/*
* call-seq:
- * str.chomp!(separator=$/) => str or nil
+ * str.chomp!(separator="\n") => str or nil
*
* Modifies <i>str</i> in place as described for <code>String#chomp</code>,
* returning <i>str</i>, or <code>nil</code> if no modifications were made.
@@ -1061,7 +1275,7 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str)
/* 15.2.10.5.9 */
/*
* call-seq:
- * str.chomp(separator=$/) => new_str
+ * str.chomp(separator="\n") => new_str
*
* Returns a new <code>String</code> with the given record separator removed
* from the end of <i>str</i> (if present). If <code>$/</code> has not been
@@ -1104,7 +1318,18 @@ mrb_str_chop_bang(mrb_state *mrb, mrb_value str)
mrb_str_modify(mrb, s);
if (RSTR_LEN(s) > 0) {
mrb_int len;
+#ifdef MRB_UTF8_STRING
+ const char* t = RSTR_PTR(s), *p = t;
+ const char* e = p + RSTR_LEN(s);
+ while (p<e) {
+ mrb_int clen = utf8len(p, e);
+ if (p + clen>=e) break;
+ p += clen;
+ }
+ len = p - t;
+#else
len = RSTR_LEN(s) - 1;
+#endif
if (RSTR_PTR(s)[len] == '\n') {
if (len > 0 &&
RSTR_PTR(s)[len-1] == '\r') {
@@ -1232,47 +1457,10 @@ mrb_str_eql(mrb_state *mrb, mrb_value self)
return mrb_bool_value(eql_p);
}
-static mrb_value
-mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
-{
- struct RString *orig, *s;
- mrb_shared_string *shared;
-
- orig = mrb_str_ptr(str);
- if (RSTR_EMBED_P(orig)) {
- s = str_new(mrb, orig->as.ary+beg, len);
- } else {
- str_make_shared(mrb, orig);
- shared = orig->as.heap.aux.shared;
- s = mrb_obj_alloc_string(mrb);
- s->as.heap.ptr = orig->as.heap.ptr + beg;
- s->as.heap.len = len;
- s->as.heap.aux.shared = shared;
- RSTR_SET_SHARED_FLAG(s);
- shared->refcnt++;
- }
-
- return mrb_obj_value(s);
-}
-
MRB_API mrb_value
mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
{
- if (len < 0) return mrb_nil_value();
- if (!RSTRING_LEN(str)) {
- len = 0;
- }
- if (beg > RSTRING_LEN(str)) return mrb_nil_value();
- if (beg < 0) {
- beg += RSTRING_LEN(str);
- if (beg < 0) return mrb_nil_value();
- }
- if (beg + len > RSTRING_LEN(str))
- len = RSTRING_LEN(str) - beg;
- if (len <= 0) {
- len = 0;
- }
- return mrb_str_subseq(mrb, str, beg, len);
+ return str_substr(mrb, str, beg, len);
}
mrb_int
@@ -1331,7 +1519,7 @@ mrb_str_include(mrb_state *mrb, mrb_value self)
}
else {
str2 = mrb_str_to_str(mrb, str2);
- i = mrb_str_index(mrb, self, str2, 0);
+ i = str_index(mrb, self, str2, 0);
include_p = (i != -1);
}
@@ -1361,12 +1549,12 @@ mrb_str_include(mrb_state *mrb, mrb_value self)
* "hello".index(/[aeiou]/, -3) #=> 4
*/
static mrb_value
-mrb_str_index_m(mrb_state *mrb, mrb_value str)
+mrb_str_index(mrb_state *mrb, mrb_value str)
{
mrb_value *argv;
mrb_int argc;
mrb_value sub;
- mrb_int pos;
+ mrb_int pos, clen;
mrb_get_args(mrb, "*", &argv, &argc);
if (argc == 2) {
@@ -1381,25 +1569,17 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str)
sub = mrb_nil_value();
}
mrb_regexp_check(mrb, sub);
+ clen = RSTRING_CHAR_LEN(str);
if (pos < 0) {
- pos += RSTRING_LEN(str);
+ pos += clen;
if (pos < 0) {
return mrb_nil_value();
}
}
+ if (pos >= clen) return mrb_nil_value();
+ pos = chars2bytes(str, 0, pos);
switch (mrb_type(sub)) {
- case MRB_TT_FIXNUM: {
- mrb_int c = mrb_fixnum(sub);
- mrb_int len = RSTRING_LEN(str);
- unsigned char *p = (unsigned char*)RSTRING_PTR(str);
-
- for (;pos<len;pos++) {
- if (p[pos] == c) return mrb_fixnum_value(pos);
- }
- return mrb_nil_value();
- }
-
default: {
mrb_value tmp;
@@ -1411,57 +1591,17 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str)
}
/* fall through */
case MRB_TT_STRING:
- pos = mrb_str_index(mrb, str, sub, pos);
+ pos = str_index(mrb, str, sub, pos);
break;
}
if (pos == -1) return mrb_nil_value();
+ pos = bytes2chars(RSTRING_PTR(str), pos);
return mrb_fixnum_value(pos);
}
#define STR_REPLACE_SHARED_MIN 10
-static mrb_value
-str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
-{
- long len;
-
- check_frozen(mrb, s1);
- len = RSTR_LEN(s2);
- if (RSTR_SHARED_P(s1)) {
- str_decref(mrb, s1->as.heap.aux.shared);
- }
- else if (!RSTR_EMBED_P(s1) && !RSTR_NOFREE_P(s1)) {
- mrb_free(mrb, s1->as.heap.ptr);
- }
-
- RSTR_UNSET_NOFREE_FLAG(s1);
-
- if (RSTR_SHARED_P(s2)) {
-L_SHARE:
- RSTR_UNSET_EMBED_FLAG(s1);
- s1->as.heap.ptr = s2->as.heap.ptr;
- s1->as.heap.len = len;
- s1->as.heap.aux.shared = s2->as.heap.aux.shared;
- RSTR_SET_SHARED_FLAG(s1);
- s1->as.heap.aux.shared->refcnt++;
- }
- else {
- if (len <= RSTRING_EMBED_LEN_MAX) {
- RSTR_UNSET_SHARED_FLAG(s1);
- RSTR_SET_EMBED_FLAG(s1);
- memcpy(s1->as.ary, RSTR_PTR(s2), len);
- RSTR_SET_EMBED_LEN(s1, len);
- }
- else {
- str_make_shared(mrb, s2);
- goto L_SHARE;
- }
- }
-
- return mrb_obj_value(s1);
-}
-
/* 15.2.10.5.24 */
/* 15.2.10.5.28 */
/*
@@ -1581,107 +1721,81 @@ mrb_check_string_type(mrb_state *mrb, mrb_value str)
return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str");
}
-/* ---------------------------------- */
-/* 15.2.10.5.29 */
+/* 15.2.10.5.30 */
/*
* call-seq:
- * str.reverse => new_str
- *
- * Returns a new string with the characters from <i>str</i> in reverse order.
+ * str.reverse! => str
*
- * "stressed".reverse #=> "desserts"
+ * Reverses <i>str</i> in place.
*/
static mrb_value
-mrb_str_reverse(mrb_state *mrb, mrb_value str)
+mrb_str_reverse_bang(mrb_state *mrb, mrb_value str)
{
- struct RString *s2;
- char *s, *e, *p;
+#ifdef MRB_UTF8_STRING
+ mrb_int utf8_len = RSTRING_CHAR_LEN(str);
+ mrb_int len = RSTRING_LEN(str);
- if (RSTRING_LEN(str) <= 1) return mrb_str_dup(mrb, str);
+ if (utf8_len == len) goto bytes;
+ if (utf8_len > 1) {
+ char *buf;
+ char *p, *e, *r;
- s2 = str_new(mrb, 0, RSTRING_LEN(str));
- str_with_class(mrb, s2, str);
- s = RSTRING_PTR(str); e = RSTRING_END(str) - 1;
- p = RSTR_PTR(s2);
+ mrb_str_modify(mrb, mrb_str_ptr(str));
+ len = RSTRING_LEN(str);
+ buf = mrb_malloc(mrb, (size_t)len);
+ p = buf;
+ e = buf + len;
- while (e >= s) {
- *p++ = *e--;
+ memcpy(buf, RSTRING_PTR(str), len);
+ r = RSTRING_PTR(str) + len;
+
+ while (p<e) {
+ mrb_int clen = utf8len(p, e);
+ r -= clen;
+ memcpy(r, p, clen);
+ p += clen;
+ }
+ mrb_free(mrb, buf);
}
- return mrb_obj_value(s2);
-}
+ return str;
-/* 15.2.10.5.30 */
-/*
- * call-seq:
- * str.reverse! => str
- *
- * Reverses <i>str</i> in place.
- */
-static mrb_value
-mrb_str_reverse_bang(mrb_state *mrb, mrb_value str)
-{
- struct RString *s = mrb_str_ptr(str);
- char *p, *e;
- char c;
+ bytes:
+#endif
+ {
+ struct RString *s = mrb_str_ptr(str);
+ char *p, *e;
+ char c;
- mrb_str_modify(mrb, s);
- if (RSTR_LEN(s) > 1) {
- p = RSTR_PTR(s);
- e = p + RSTR_LEN(s) - 1;
- while (p < e) {
+ mrb_str_modify(mrb, s);
+ if (RSTR_LEN(s) > 1) {
+ p = RSTR_PTR(s);
+ e = p + RSTR_LEN(s) - 1;
+ while (p < e) {
c = *p;
*p++ = *e;
*e-- = c;
+ }
}
+ return str;
}
- return str;
}
+/* ---------------------------------- */
+/* 15.2.10.5.29 */
/*
* call-seq:
- * str.rindex(substring [, fixnum]) => fixnum or nil
- * str.rindex(fixnum [, fixnum]) => fixnum or nil
- * str.rindex(regexp [, fixnum]) => fixnum or nil
+ * str.reverse => new_str
*
- * Returns the index of the last occurrence of the given <i>substring</i>,
- * character (<i>fixnum</i>), or pattern (<i>regexp</i>) in <i>str</i>. Returns
- * <code>nil</code> if not found. If the second parameter is present, it
- * specifies the position in the string to end the search---characters beyond
- * this point will not be considered.
+ * Returns a new string with the characters from <i>str</i> in reverse order.
*
- * "hello".rindex('e') #=> 1
- * "hello".rindex('l') #=> 3
- * "hello".rindex('a') #=> nil
- * "hello".rindex(101) #=> 1
- * "hello".rindex(/[aeiou]/, -2) #=> 1
+ * "stressed".reverse #=> "desserts"
*/
-static mrb_int
-mrb_str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
+static mrb_value
+mrb_str_reverse(mrb_state *mrb, mrb_value str)
{
- char *s, *sbeg, *t;
- struct RString *ps = mrb_str_ptr(str);
- mrb_int len = RSTRING_LEN(sub);
-
- /* substring longer than string */
- if (RSTR_LEN(ps) < len) return -1;
- if (RSTR_LEN(ps) - pos < len) {
- pos = RSTR_LEN(ps) - len;
- }
- sbeg = RSTR_PTR(ps);
- s = RSTR_PTR(ps) + pos;
- t = RSTRING_PTR(sub);
- if (len) {
- while (sbeg <= s) {
- if (memcmp(s, t, len) == 0) {
- return s - RSTR_PTR(ps);
- }
- s--;
- }
- return -1;
- }
- else {
- return pos;
- }
+ mrb_value str2 = mrb_str_dup(mrb, str);
+ mrb_str_reverse_bang(mrb, str2);
+ return str2;
}
/* 15.2.10.5.31 */
@@ -1704,13 +1818,13 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
* "hello".rindex(/[aeiou]/, -2) #=> 1
*/
static mrb_value
-mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
+mrb_str_rindex(mrb_state *mrb, mrb_value str)
{
mrb_value *argv;
mrb_int argc;
mrb_value sub;
mrb_value vpos;
- mrb_int pos, len = RSTRING_LEN(str);
+ mrb_int pos, len = RSTRING_CHAR_LEN(str);
mrb_get_args(mrb, "*", &argv, &argc);
if (argc == 2) {
@@ -1733,19 +1847,11 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
else
sub = mrb_nil_value();
}
+ pos = chars2bytes(str, 0, pos);
+ len = chars2bytes(str, pos, len);
mrb_regexp_check(mrb, sub);
switch (mrb_type(sub)) {
- case MRB_TT_FIXNUM: {
- mrb_int c = mrb_fixnum(sub);
- unsigned char *p = (unsigned char*)RSTRING_PTR(str);
-
- for (pos=len-1;pos>=0;pos--) {
- if (p[pos] == c) return mrb_fixnum_value(pos);
- }
- return mrb_nil_value();
- }
-
default: {
mrb_value tmp;
@@ -1757,8 +1863,11 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
}
/* fall through */
case MRB_TT_STRING:
- pos = mrb_str_rindex(mrb, str, sub, pos);
- if (pos >= 0) return mrb_fixnum_value(pos);
+ pos = str_rindex(mrb, str, sub, pos);
+ if (pos >= 0) {
+ pos = bytes2chars(RSTRING_PTR(str), pos);
+ return mrb_fixnum_value(pos);
+ }
break;
} /* end of switch (TYPE(sub)) */
@@ -1769,7 +1878,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
/*
* call-seq:
- * str.split(pattern=$;, [limit]) => anArray
+ * str.split(pattern="\n", [limit]) => anArray
*
* Divides <i>str</i> into substrings based on a delimiter, returning an array
* of these substrings.
@@ -1867,7 +1976,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
}
}
else if (ISSPACE(c)) {
- mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, beg, end-beg));
+ mrb_ary_push(mrb, result, byte_subseq(mrb, str, beg, end-beg));
mrb_gc_arena_restore(mrb, ai);
skip = TRUE;
beg = idx;
@@ -1889,9 +1998,9 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
end = mrb_memsearch(RSTRING_PTR(spat), pat_len, RSTRING_PTR(str)+idx, str_len - idx);
if (end < 0) break;
} else {
- end = 1;
+ end = chars2bytes(str, idx, 1);
}
- mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, idx, end));
+ mrb_ary_push(mrb, result, byte_subseq(mrb, str, idx, end));
mrb_gc_arena_restore(mrb, ai);
idx += end + pat_len;
if (lim_p && lim <= ++i) break;
@@ -1906,7 +2015,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str)
tmp = mrb_str_new_empty(mrb, str);
}
else {
- tmp = mrb_str_subseq(mrb, str, beg, RSTRING_LEN(str)-beg);
+ tmp = byte_subseq(mrb, str, beg, RSTRING_LEN(str)-beg);
}
mrb_ary_push(mrb, result, tmp);
}
@@ -2477,7 +2586,21 @@ mrb_str_inspect(mrb_state *mrb, mrb_value str)
p = RSTRING_PTR(str); pend = RSTRING_END(str);
for (;p < pend; p++) {
unsigned char c, cc;
+#ifdef MRB_UTF8_STRING
+ mrb_int clen;
+
+ clen = utf8len(p, pend);
+ if (clen > 1) {
+ mrb_int i;
+ for (i=0; i<clen; i++) {
+ buf[i] = p[i];
+ }
+ mrb_str_cat(mrb, result, buf, clen);
+ p += clen-1;
+ continue;
+ }
+#endif
c = *p;
if (c == '"'|| c == '\\' || (c == '#' && IS_EVSTR(p, pend))) {
buf[0] = '\\'; buf[1] = c;
@@ -2551,10 +2674,10 @@ mrb_init_string(mrb_state *mrb)
mrb_static_assert(RSTRING_EMBED_LEN_MAX < (1 << 5), "pointer size too big for embedded string");
- s = mrb->string_class = mrb_define_class(mrb, "String", mrb->object_class); /* 15.2.10 */
+ mrb->string_class = s = mrb_define_class(mrb, "String", mrb->object_class); /* 15.2.10 */
MRB_SET_INSTANCE_TT(s, MRB_TT_STRING);
- mrb_define_method(mrb, s, "bytesize", mrb_str_size, MRB_ARGS_NONE());
+ mrb_define_method(mrb, s, "bytesize", mrb_str_bytesize, MRB_ARGS_NONE());
mrb_define_method(mrb, s, "<=>", mrb_str_cmp_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.1 */
mrb_define_method(mrb, s, "==", mrb_str_equal_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.2 */
@@ -2574,7 +2697,7 @@ mrb_init_string(mrb_state *mrb)
mrb_define_method(mrb, s, "hash", mrb_str_hash_m, MRB_ARGS_NONE()); /* 15.2.10.5.20 */
mrb_define_method(mrb, s, "include?", mrb_str_include, MRB_ARGS_REQ(1)); /* 15.2.10.5.21 */
- mrb_define_method(mrb, s, "index", mrb_str_index_m, MRB_ARGS_ANY()); /* 15.2.10.5.22 */
+ mrb_define_method(mrb, s, "index", mrb_str_index, MRB_ARGS_ANY()); /* 15.2.10.5.22 */
mrb_define_method(mrb, s, "initialize", mrb_str_init, MRB_ARGS_REQ(1)); /* 15.2.10.5.23 */
mrb_define_method(mrb, s, "initialize_copy", mrb_str_replace, MRB_ARGS_REQ(1)); /* 15.2.10.5.24 */
mrb_define_method(mrb, s, "intern", mrb_str_intern, MRB_ARGS_NONE()); /* 15.2.10.5.25 */
@@ -2582,7 +2705,7 @@ mrb_init_string(mrb_state *mrb)
mrb_define_method(mrb, s, "replace", mrb_str_replace, MRB_ARGS_REQ(1)); /* 15.2.10.5.28 */
mrb_define_method(mrb, s, "reverse", mrb_str_reverse, MRB_ARGS_NONE()); /* 15.2.10.5.29 */
mrb_define_method(mrb, s, "reverse!", mrb_str_reverse_bang, MRB_ARGS_NONE()); /* 15.2.10.5.30 */
- mrb_define_method(mrb, s, "rindex", mrb_str_rindex_m, MRB_ARGS_ANY()); /* 15.2.10.5.31 */
+ mrb_define_method(mrb, s, "rindex", mrb_str_rindex, MRB_ARGS_ANY()); /* 15.2.10.5.31 */
mrb_define_method(mrb, s, "size", mrb_str_size, MRB_ARGS_NONE()); /* 15.2.10.5.33 */
mrb_define_method(mrb, s, "slice", mrb_str_aref_m, MRB_ARGS_ANY()); /* 15.2.10.5.34 */
mrb_define_method(mrb, s, "split", mrb_str_split_m, MRB_ARGS_ANY()); /* 15.2.10.5.35 */
diff --git a/src/symbol.c b/src/symbol.c
index f1c0bf80a..c39e88012 100644
--- a/src/symbol.c
+++ b/src/symbol.c
@@ -6,10 +6,10 @@
#include <limits.h>
#include <string.h>
-#include "mruby.h"
-#include "mruby/khash.h"
-#include "mruby/string.h"
-#include "mruby/dump.h"
+#include <mruby.h>
+#include <mruby/khash.h>
+#include <mruby/string.h>
+#include <mruby/dump.h>
/* ------------------------------------------------------ */
typedef struct symbol_name {
@@ -478,7 +478,7 @@ mrb_init_symbol(mrb_state *mrb)
{
struct RClass *sym;
- sym = mrb->symbol_class = mrb_define_class(mrb, "Symbol", mrb->object_class); /* 15.2.11 */
+ mrb->symbol_class = sym = mrb_define_class(mrb, "Symbol", mrb->object_class); /* 15.2.11 */
mrb_define_method(mrb, sym, "===", sym_equal, MRB_ARGS_REQ(1)); /* 15.2.11.3.1 */
mrb_define_method(mrb, sym, "id2name", mrb_sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.2 */
diff --git a/src/value_array.h b/src/value_array.h
index cabd2426d..bc5f28b06 100644
--- a/src/value_array.h
+++ b/src/value_array.h
@@ -1,7 +1,7 @@
#ifndef MRB_VALUE_ARRAY_H__
#define MRB_VALUE_ARRAY_H__
-#include "mruby.h"
+#include <mruby.h>
static inline void
value_move(mrb_value *s1, const mrb_value *s2, size_t n)
diff --git a/src/variable.c b/src/variable.c
index efe6fad12..bda7b2a98 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -4,11 +4,11 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/class.h"
-#include "mruby/proc.h"
-#include "mruby/string.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/proc.h>
+#include <mruby/string.h>
typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*);
@@ -282,7 +282,7 @@ iv_free(mrb_state *mrb, iv_tbl *t)
#else
-#include "mruby/khash.h"
+#include <mruby/khash.h>
#ifndef MRB_IVHASH_INIT_SIZE
#define MRB_IVHASH_INIT_SIZE 8
@@ -759,17 +759,29 @@ MRB_API mrb_value
mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym)
{
struct RClass * cls = c;
+ mrb_value v;
while (c) {
- if (c->iv) {
- iv_tbl *t = c->iv;
- mrb_value v;
-
- if (iv_get(mrb, t, sym, &v))
- return v;
+ if (c->iv && iv_get(mrb, c->iv, sym, &v)) {
+ return v;
}
c = c->super;
}
+ if (cls && cls->tt == MRB_TT_SCLASS) {
+ mrb_value klass;
+
+ klass = mrb_obj_iv_get(mrb, (struct RObject *)cls,
+ mrb_intern_lit(mrb, "__attached__"));
+ c = mrb_class_ptr(klass);
+ if (c->tt == MRB_TT_CLASS) {
+ while (c) {
+ if (c->iv && iv_get(mrb, c->iv, sym, &v)) {
+ return v;
+ }
+ c = c->super;
+ }
+ }
+ }
mrb_name_error(mrb, sym, "uninitialized class variable %S in %S",
mrb_sym2str(mrb, sym), mrb_obj_value(cls));
/* not reached */
@@ -914,6 +926,14 @@ mrb_vm_const_get(mrb_state *mrb, mrb_sym sym)
if (c->iv && iv_get(mrb, c->iv, sym, &v)) {
return v;
}
+ if (c->tt == MRB_TT_SCLASS) {
+ mrb_value klass;
+ klass = mrb_obj_iv_get(mrb, (struct RObject *)c,
+ mrb_intern_lit(mrb, "__attached__"));
+ c2 = mrb_class_ptr(klass);
+ if (c2->tt == MRB_TT_CLASS)
+ c = c2;
+ }
c2 = c;
for (;;) {
c2 = mrb_class_outer_module(mrb, c2);
diff --git a/src/version.c b/src/version.c
index fc3b2fc7a..5bcecb3aa 100644
--- a/src/version.c
+++ b/src/version.c
@@ -1,11 +1,14 @@
-#include "mruby.h"
-#include "mruby/variable.h"
+#include <mruby.h>
+#include <mruby/variable.h>
void
mrb_init_version(mrb_state* mrb)
{
+ mrb_value mruby_version = mrb_str_new_lit(mrb, MRUBY_VERSION);
+
mrb_define_global_const(mrb, "RUBY_VERSION", mrb_str_new_lit(mrb, MRUBY_RUBY_VERSION));
mrb_define_global_const(mrb, "RUBY_ENGINE", mrb_str_new_lit(mrb, MRUBY_RUBY_ENGINE));
+ mrb_define_global_const(mrb, "RUBY_ENGINE_VERSION", mruby_version);
mrb_define_global_const(mrb, "MRUBY_VERSION", mrb_str_new_lit(mrb, MRUBY_VERSION));
mrb_define_global_const(mrb, "MRUBY_RELEASE_NO", mrb_fixnum_value(MRUBY_RELEASE_NO));
mrb_define_global_const(mrb, "MRUBY_RELEASE_DATE", mrb_str_new_lit(mrb, MRUBY_RELEASE_DATE));
diff --git a/src/vm.c b/src/vm.c
index 8419931d0..391646017 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -7,22 +7,22 @@
#include <stddef.h>
#include <stdarg.h>
#include <math.h>
-#include "mruby.h"
-#include "mruby/array.h"
-#include "mruby/class.h"
-#include "mruby/hash.h"
-#include "mruby/irep.h"
-#include "mruby/numeric.h"
-#include "mruby/proc.h"
-#include "mruby/range.h"
-#include "mruby/string.h"
-#include "mruby/variable.h"
-#include "mruby/error.h"
-#include "mruby/opcode.h"
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/hash.h>
+#include <mruby/irep.h>
+#include <mruby/numeric.h>
+#include <mruby/proc.h>
+#include <mruby/range.h>
+#include <mruby/string.h>
+#include <mruby/variable.h>
+#include <mruby/error.h>
+#include <mruby/opcode.h>
#include "value_array.h"
-#include "mruby/throw.h"
+#include <mruby/throw.h>
-#ifndef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
#if defined(__cplusplus)
extern "C" {
#endif
@@ -52,7 +52,7 @@ The value below allows about 60000 recursive calls in the simplest case. */
# define DEBUG(x)
#endif
-#define ARENA_RESTORE(mrb,ai) (mrb)->arena_idx = (ai)
+#define ARENA_RESTORE(mrb,ai) (mrb)->gc.arena_idx = (ai)
static inline void
stack_clear(mrb_value *from, size_t count)
@@ -693,7 +693,7 @@ argnum_error(mrb_state *mrb, mrb_int num)
#define ERR_PC_SET(mrb, pc) mrb->c->ci->err = pc;
#define ERR_PC_CLR(mrb) mrb->c->ci->err = 0;
-#ifdef ENABLE_DEBUG
+#ifdef MRB_ENABLE_DEBUG_HOOK
#define CODE_FETCH_HOOK(mrb, irep, pc, regs) if ((mrb)->code_fetch_hook) (mrb)->code_fetch_hook((mrb), (irep), (pc), (regs));
#else
#define CODE_FETCH_HOOK(mrb, irep, pc, regs)
@@ -2178,6 +2178,7 @@ RETRY_TRY_BLOCK:
CASE(OP_STRCAT) {
/* A B R(A).concat(R(B)) */
mrb_str_concat(mrb, regs[GETARG_A(i)], regs[GETARG_B(i)]);
+ regs = mrb->c->stack;
NEXT;
}
@@ -2207,15 +2208,6 @@ RETRY_TRY_BLOCK:
}
else {
p = mrb_proc_new(mrb, irep->reps[GETARG_b(i)]);
- if (c & OP_L_METHOD) {
- if (p->target_class->tt == MRB_TT_SCLASS) {
- mrb_value klass;
- klass = mrb_obj_iv_get(mrb,
- (struct RObject *)p->target_class,
- mrb_intern_lit(mrb, "__attached__"));
- p->target_class = mrb_class_ptr(klass);
- }
- }
}
if (c & OP_L_STRICT) p->flags |= MRB_PROC_STRICT;
regs[GETARG_A(i)] = mrb_obj_value(p);
@@ -2348,10 +2340,10 @@ RETRY_TRY_BLOCK:
CASE(OP_DEBUG) {
/* A B C debug print R(A),R(B),R(C) */
-#ifdef ENABLE_DEBUG
+#ifdef MRB_ENABLE_DEBUG_HOOK
mrb->debug_op_hook(mrb, irep, pc, regs);
#else
-#ifdef ENABLE_STDIO
+#ifndef MRB_DISABLE_STDIO
printf("OP_DEBUG %d %d %d\n", GETARG_A(i), GETARG_B(i), GETARG_C(i));
#else
abort();
diff --git a/tasks/mrbgem_spec.rake b/tasks/mrbgem_spec.rake
index 74aa5b817..e91823029 100644
--- a/tasks/mrbgem_spec.rake
+++ b/tasks/mrbgem_spec.rake
@@ -52,7 +52,7 @@ module MRuby
MRuby::Build::COMMANDS.each do |command|
instance_variable_set("@#{command}", @build.send(command).clone)
end
- @linker = LinkerConfig.new([], [], [], [])
+ @linker = LinkerConfig.new([], [], [], [], [])
@rbfiles = Dir.glob("#{dir}/mrblib/**/*.rb").sort
@objs = Dir.glob("#{dir}/src/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f|
@@ -103,6 +103,10 @@ module MRuby
@dependencies << {:gem => name, :requirements => requirements, :default => default_gem}
end
+ def add_test_dependency(*args)
+ add_dependency(*args) if build.test_enabled?
+ end
+
def add_conflict(name, *req)
@conflicts << {:gem => name, :requirements => req.empty? ? nil : req}
end
@@ -177,18 +181,18 @@ module MRuby
def print_gem_init_header(f)
print_gem_comment(f)
f.puts %Q[#include <stdlib.h>] unless rbfiles.empty?
- f.puts %Q[#include "mruby.h"]
- f.puts %Q[#include "mruby/irep.h"] unless rbfiles.empty?
+ f.puts %Q[#include <mruby.h>]
+ f.puts %Q[#include <mruby/irep.h>] unless rbfiles.empty?
end
def print_gem_test_header(f)
print_gem_comment(f)
f.puts %Q[#include <stdio.h>]
f.puts %Q[#include <stdlib.h>]
- f.puts %Q[#include "mruby.h"]
- f.puts %Q[#include "mruby/irep.h"]
- f.puts %Q[#include "mruby/variable.h"]
- f.puts %Q[#include "mruby/hash.h"] unless test_args.empty?
+ f.puts %Q[#include <mruby.h>]
+ f.puts %Q[#include <mruby/irep.h>]
+ f.puts %Q[#include <mruby/variable.h>]
+ f.puts %Q[#include <mruby/hash.h>] unless test_args.empty?
end
def test_dependencies
diff --git a/tasks/mrbgems.rake b/tasks/mrbgems.rake
index 1cf05ee4e..65368c303 100644
--- a/tasks/mrbgems.rake
+++ b/tasks/mrbgems.rake
@@ -31,7 +31,7 @@ MRuby.each_target do
f.puts %Q[ * All manual changes will get lost.]
f.puts %Q[ */]
f.puts %Q[]
- f.puts %Q[#include "mruby.h"]
+ f.puts %Q[#include <mruby.h>]
f.puts %Q[]
f.write gem_func_decls
f.puts %Q[]
diff --git a/tasks/mruby_build.rake b/tasks/mruby_build.rake
index 6863b635a..cff45ddf8 100644
--- a/tasks/mruby_build.rake
+++ b/tasks/mruby_build.rake
@@ -26,8 +26,8 @@ module MRuby
MRuby::Toolchain.toolchains[@name] = self
end
- def setup(conf)
- conf.instance_eval(&@initializer)
+ def setup(conf,params={})
+ conf.instance_exec(conf, params, &@initializer)
end
def self.load
@@ -158,10 +158,10 @@ EOS
@enable_bintest
end
- def toolchain(name)
+ def toolchain(name, params={})
tc = Toolchain.toolchains[name.to_s]
fail "Unknown #{name} toolchain" unless tc
- tc.setup(self)
+ tc.setup(self, params)
@toolchains.unshift name.to_s
end
diff --git a/tasks/mruby_build_gem.rake b/tasks/mruby_build_gem.rake
index 896aeb147..9a802097f 100644
--- a/tasks/mruby_build_gem.rake
+++ b/tasks/mruby_build_gem.rake
@@ -106,7 +106,7 @@ module MRuby
git.run_checkout gemdir, params[:checksum_hash]
else
# Jump to the top of the branch
- git.run_checkout gemdir, branch
+ git.run_checkout gemdir, branch if $pull_gems
end
else
fail "unknown gem option #{params}"
diff --git a/tasks/toolchains/android.rake b/tasks/toolchains/android.rake
new file mode 100644
index 000000000..aadc5b3cc
--- /dev/null
+++ b/tasks/toolchains/android.rake
@@ -0,0 +1,216 @@
+class MRuby::Toolchain::Android
+ DEFAULT_ARCH = 'armeabi'
+ DEFAULT_PLATFORM = 'android-14'
+ DEFAULT_TOOLCHAIN = :gcc
+ DEFAULT_NDK_HOMES = %w{
+ /usr/local/opt/android-ndk
+ }
+ TOOLCHAINS = [:gcc, :clang]
+ ARCHITECTURES = %w{
+ armeabi armeabi-v7a arm64-v8a
+ mips mips64
+ x86 x86_64
+ }
+
+ class AndroidNDKHomeNotFound < StandardError
+ def message
+ <<-EOM
+Couldn't find Android NDK Home.
+Set ANDROID_NDK_HOME environment variable or set :ndk_home parameter
+ EOM
+ end
+ end
+
+ attr_reader :params
+
+ def initialize(params)
+ @params = params
+ end
+
+ def home_path
+ @home_path ||= Pathname(
+ params[:ndk_home] ||
+ ENV['ANDROID_NDK_HOME'] ||
+ DEFAULT_NDK_HOMES.find{ |path| File.directory?(path) } ||
+ raise(AndroidNDKHomeNotFound)
+ )
+ end
+
+ def arch
+ params.fetch(:arch){ DEFAULT_ARCH }
+ end
+
+ def platform
+ params.fetch(:platform){ DEFAULT_PLATFORM }
+ end
+
+ def toolchain
+ params.fetch(:toolchain){ DEFAULT_TOOLCHAIN }
+ end
+
+ def toolchain_version
+ params.fetch(:toolchain_version) do
+ test = case toolchain
+ when :gcc
+ case arch
+ when /armeabi/
+ 'arm-linux-androideabi-*'
+ when /arm64/
+ 'aarch64-linux-android-*'
+ when /mips64/
+ 'mips64el-linux-android-*'
+ when /mips/
+ 'mipsel-linux-android-*'
+ when /x86_64/
+ 'x86_64-*'
+ when /x86/
+ 'x86-*'
+ end
+ when :clang
+ 'llvm-*'
+ end
+
+ Dir[home_path.join('toolchains',test)].map{|t| t.match(/-(\d+\.\d+)$/); $1.to_f }.max
+ end
+ end
+
+ def toolchain_path
+ prefix = case toolchain
+ when :clang then 'llvm-'
+ when :gcc
+ case arch
+ when /armeabi/ then 'arm-linux-androideabi-'
+ when /arm64/ then 'aarch64-linux-android-'
+ when /x86_64/ then 'x86_64-'
+ when /x86/ then 'x86-'
+ when /mips64/ then 'mips64el-linux-android-'
+ when /mips/ then 'mipsel-linux-android-'
+ end
+ end
+ home_path.join('toolchains', prefix + toolchain_version.to_s, 'prebuilt', host_platform)
+ end
+
+ def sysroot
+ path = case arch
+ when /armeabi/ then 'arch-arm'
+ when /arm64/ then 'arch-arm64'
+ when /x86_64/ then 'arch-x86_64'
+ when /x86/ then 'arch-x86'
+ when /mips64/ then 'arch-mips64'
+ when /mips/ then 'arch-mips'
+ end
+
+ home_path.join('platforms', platform, path).to_s
+ end
+
+ def bin(command)
+ command = command.to_s
+
+ if toolchain == :gcc
+ command = case arch
+ when /armeabi/ then 'arm-linux-androideabi-'
+ when /arm64/ then 'aarch64-linux-android-'
+ when /x86_64/ then 'x86_64-linux-android-'
+ when /x86/ then 'i686-linux-android-'
+ when /mips64/ then 'mips64el-linux-android-'
+ when /mips/ then 'mipsel-linux-android-'
+ end + command
+ end
+
+ toolchain_path.join('bin',command).to_s
+ end
+
+ def cc
+ case toolchain
+ when :gcc then bin(:gcc)
+ when :clang then bin(:clang)
+ end
+ end
+
+ def cflags
+ flags = []
+
+ case toolchain
+ when :gcc
+ flags += %W(-ffunction-sections -funwind-tables -no-canonical-prefixes)
+ flags += %W(-D__android__ -mandroid --sysroot="#{sysroot}")
+ case arch
+ when /arm64/
+ flags += %W(-fpic -fstack-protector-strong)
+ when 'armeabi-v7a-hard'
+ flags += %W(-fpic -fstack-protector-strong -march=armv7-a -mhard-float -D_NDK_MATH_NO_SOFTFP=1 -mfpu=vfpv3-d16)
+ when 'armeabi-v7a'
+ flags += %W(-fpic -fstack-protector-strong -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16)
+ when /arm/
+ flags += %W(-fpic -fstack-protector-strong -march=armv5te -mtune=xscale -msoft-float)
+ when /mips/
+ flags += %W(-fpic -fno-strict-aliasing -finline-functions -fmessage-length=0 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers)
+ when /x86/
+ flags += %W(-fstack-protector-strong)
+ end
+ when :clang
+ end
+
+ flags
+ end
+
+ def ld
+ cc
+ end
+
+ def ldflags
+ flags = []
+ case toolchain
+ when :gcc
+ flags += %W(-no-canonical-prefixes)
+ flags += %W(-D__android__ -mandroid --sysroot="#{sysroot}")
+ case arch
+ when 'armeabi-v7a-hard'
+ flags += %W(-march=armv7-a -Wl,--fix-cortex-a8 -Wl,--no-warn-mismatch -lm_hard)
+ when 'armeabi-v7a'
+ flags += %W(-march=armv7-a -Wl,--fix-cortex-a8)
+ end
+ end
+
+ flags
+ end
+
+ def ar
+ case toolchain
+ when :gcc then bin(:ar)
+ when :clang then bin('llvm-ar')
+ end
+ end
+
+ def host_platform
+ case RUBY_PLATFORM
+ when /cygwin|mswin|mingw|bccwin|wince|emx/i
+ 'windows'
+ when /x86_64-darwin/i
+ 'darwin-x86_64'
+ when /darwin/i
+ 'darwin-x86'
+ when /x86_64-linux/i
+ 'linux-x86_64'
+ when /linux/i
+ 'linux-x86'
+ else
+ raise NotImplementedError, "Unknown host platform (#{RUBY_PLATFORM})"
+ end
+ end
+end
+
+MRuby::Toolchain.new(:android) do |conf, params|
+ ndk = MRuby::Toolchain::Android.new(params)
+
+ toolchain ndk.toolchain
+
+ [conf.cc, conf.cxx, conf.objc, conf.asm].each do |cc|
+ cc.command = ndk.cc
+ cc.flags = ndk.cflags
+ end
+ conf.linker.command = ndk.ld
+ conf.linker.flags = ndk.ldflags
+ conf.archiver.command = ndk.ar
+end
+
diff --git a/tasks/toolchains/androideabi.rake b/tasks/toolchains/androideabi.rake
deleted file mode 100644
index 272e802f7..000000000
--- a/tasks/toolchains/androideabi.rake
+++ /dev/null
@@ -1,132 +0,0 @@
-# Download and unarchive latest Android NDK from https://developer.android.com/tools/sdk/ndk/index.html
-# Make custom standalone toolchain as described here (android_ndk/docs/STANDALONE-TOOLCHAIN.html)
-# Please export custom standalone toolchain path
-# export ANDROID_STANDALONE_TOOLCHAIN=/tmp/android-14-toolchain
-
-# Add to your build_config.rb
-# MRuby::CrossBuild.new('androideabi') do |conf|
-# toolchain :androideabi
-# end
-
-MRuby::Toolchain.new(:androideabi) do |conf|
- toolchain :gcc
-
- DEFAULT_ANDROID_TOOLCHAIN = 'gcc'
- DEFAULT_ANDROID_TARGET_ARCH = 'arm'
- DEFAULT_ANDROID_TARGET_ARCH_ABI = 'armeabi'
- DEFAULT_ANDROID_TARGET_PLATFORM = 'android-14'
- DEFAULT_GCC_VERSION = '4.6'
- DEFAULT_CLANG_VERSION = '3.1'
- GCC_COMMON_CFLAGS = %W(-ffunction-sections -funwind-tables -fstack-protector)
- GCC_COMMON_LDFLAGS = %W()
-
- # 'ANDROID_STANDALONE_TOOLCHAIN' or 'ANDROID_NDK_HOME' must be set.
- ANDROID_STANDALONE_TOOLCHAIN = ENV['ANDROID_STANDALONE_TOOLCHAIN']
- ANDROID_NDK_HOME = ENV['ANDROID_NDK_HOME']
-
- ANDROID_TARGET_ARCH = ENV['ANDROID_TARGET_ARCH'] || DEFAULT_ANDROID_TARGET_ARCH
- ANDROID_TARGET_ARCH_ABI = ENV['ANDROID_TARGET_ARCH_ABI'] || DEFAULT_ANDROID_TARGET_ARCH_ABI
- ANDROID_TOOLCHAIN = ENV['ANDROID_TOOLCHAIN'] || DEFAULT_ANDROID_TOOLCHAIN
- GCC_VERSION = ENV['GCC_VERSION'] || DEFAULT_GCC_VERSION
- CLANG_VERSION = ENV['CLANG_VERSION'] || DEFAULT_CLANG_VERSION
-
- case ANDROID_TARGET_ARCH.downcase
- when 'arch-arm', 'arm' then
- toolchain_prefix = 'arm-linux-androideabi-'
- when 'arch-x86', 'x86' then
- toolchain_prefix = 'i686-linux-android-'
- when 'arch-mips', 'mips' then
- toolchain_prefix = 'mipsel-linux-android-'
- else
- # Any other architectures are not supported by Android NDK.
- # Notify error.
- end
-
- if ANDROID_STANDALONE_TOOLCHAIN == nil then
- case RUBY_PLATFORM
- when /cygwin|mswin|mingw|bccwin|wince|emx/i
- HOST_PLATFORM = 'windows'
- when /x86_64-darwin/i
- HOST_PLATFORM = 'darwin-x86_64'
- when /darwin/i
- HOST_PLATFORM = 'darwin-x86'
- when /x86_64-linux/i
- HOST_PLATFORM = 'linux-x86_64'
- when /linux/i
- HOST_PLATFORM = 'linux-x86'
- else
- # Unknown host platform
- end
-
- ANDROID_TARGET_PLATFORM = ENV['ANDROID_TARGET_PLATFORM'] || DEFAULT_ANDROID_TARGET_PLATFORM
-
- path_to_toolchain = ANDROID_NDK_HOME + '/toolchains/'
- path_to_sysroot = ANDROID_NDK_HOME + '/platforms/' + ANDROID_TARGET_PLATFORM
- if ANDROID_TOOLCHAIN.downcase == 'gcc' then
- case ANDROID_TARGET_ARCH.downcase
- when 'arch-arm', 'arm' then
- path_to_toolchain += 'arm-linux-androideabi-'
- path_to_sysroot += '/arch-arm'
- when 'arch-x86', 'x86' then
- path_to_toolchain += 'x86-'
- path_to_sysroot += '/arch-x86'
- when 'arch-mips', 'mips' then
- path_to_toolchain += 'mipsel-linux-android-'
- path_to_sysroot += '/arch-mips'
- else
- # Any other architecture are not supported by Android NDK.
- end
- path_to_toolchain += GCC_VERSION + '/prebuilt/' + HOST_PLATFORM
- else
- path_to_toolchain += 'llvm-' + CLANG_VERSION + '/prebuilt/' + HOST_PLATFORM
- end
- else
- path_to_toolchain = ANDROID_STANDALONE_TOOLCHAIN
- path_to_sysroot = ANDROID_STANDALONE_TOOLCHAIN + '/sysroot'
- end
-
- SYSROOT = path_to_sysroot
-
- case ANDROID_TARGET_ARCH.downcase
- when 'arch-arm', 'arm' then
- if ANDROID_TARGET_ARCH_ABI.downcase == 'armeabi-v7a' then
- ARCH_CFLAGS = %W(-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16)
- ARCH_LDFLAGS = %W(-march=armv7-a -Wl,--fix-cortex-a8)
- else
- ARCH_CFLAGS = %W(-march=armv5te -mtune=xscale -msoft-float)
- ARCH_LDFLAGS = %W()
- end
- when 'arch-x86', 'x86' then
- ARCH_CFLAGS = %W()
- ARCH_LDFLAGS = %W()
- when 'arch-mips', 'mips' then
- ARCH_CFLAGS = %W(-fpic -fno-strict-aliasing -finline-functions -fmessage-length=0 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers)
- ARCH_LDFLAGS = %W()
- else
- # Notify error
- end
-
- case ANDROID_TOOLCHAIN.downcase
- when 'gcc' then
- ANDROID_CC = path_to_toolchain + '/bin/' + toolchain_prefix + 'gcc'
- ANDROID_LD = path_to_toolchain + '/bin/' + toolchain_prefix + 'gcc'
- ANDROID_AR = path_to_toolchain + '/bin/' + toolchain_prefix + 'ar'
- ANDROID_CFLAGS = GCC_COMMON_CFLAGS + %W(-D__android__ -mandroid --sysroot="#{SYSROOT}") + ARCH_CFLAGS
- ANDROID_LDFLAGS = GCC_COMMON_LDFLAGS + %W(-D__android__ -mandroid --sysroot="#{SYSROOT}") + ARCH_LDFLAGS
- when 'clang' then
- # clang is not supported yet.
- when 'clang31', 'clang3.1' then
- # clang is not supported yet.
- else
- # Any other toolchains are not supported by Android NDK.
- # Notify error.
- end
-
- [conf.cc, conf.cxx, conf.objc, conf.asm].each do |cc|
- cc.command = ENV['CC'] || ANDROID_CC
- cc.flags = [ENV['CFLAGS'] || ANDROID_CFLAGS]
- end
- conf.linker.command = ENV['LD'] || ANDROID_LD
- conf.linker.flags = [ENV['LDFLAGS'] || ANDROID_LDFLAGS]
- conf.archiver.command = ENV['AR'] || ANDROID_AR
-end
diff --git a/test/bintest.rb b/test/bintest.rb
index 49990abb9..0ef0b4187 100644
--- a/test/bintest.rb
+++ b/test/bintest.rb
@@ -1,6 +1,24 @@
$:.unshift File.dirname(File.dirname(File.expand_path(__FILE__)))
require 'test/assert.rb'
+def cmd(s)
+ case RbConfig::CONFIG['host_os']
+ when /mswin(?!ce)|mingw|cygwin|bccwin/
+ "bin\\#{s}.exe"
+ else
+ "bin/#{s}"
+ end
+end
+
+def shellquote(s)
+ case RbConfig::CONFIG['host_os']
+ when /mswin(?!ce)|mingw|cygwin|bccwin/
+ "\"#{s}\""
+ else
+ "'#{s}'"
+ end
+end
+
ARGV.each do |gem|
Dir["#{gem}/bintest/**/*.rb"].each do |file|
load file
diff --git a/test/t/float.rb b/test/t/float.rb
index 0aab0b1f2..1805c6e7d 100644
--- a/test/t/float.rb
+++ b/test/t/float.rb
@@ -198,5 +198,5 @@ assert('Float#>>') do
assert_equal 0, 23.0 >> 128
# Don't raise on large Right Shift
- assert_equal -1, -23.0 >> 128
+ assert_equal(-1, -23.0 >> 128)
end
diff --git a/test/t/integer.rb b/test/t/integer.rb
index be3c13db2..5379744e5 100644
--- a/test/t/integer.rb
+++ b/test/t/integer.rb
@@ -147,6 +147,12 @@ assert('Integer#<<', '15.2.8.3.12') do
# Left Shift by a negative is Right Shift
assert_equal 23, 46 << -1
+
+ # Left Shift by 31 is bitShift overflow to SignedInt
+ assert_equal 2147483648, 1 << 31
+
+ # -3 Left Shift by 30 is bitShift overflow to SignedInt
+ assert_equal -3221225472, -3 << 30
end
assert('Integer#>>', '15.2.8.3.13') do
diff --git a/test/t/string.rb b/test/t/string.rb
index 7326adce9..fbaada451 100644
--- a/test/t/string.rb
+++ b/test/t/string.rb
@@ -1,6 +1,9 @@
+# coding: utf-8
##
# String ISO Test
+UTF8STRING = ("\343\201\202".size == 1)
+
assert('String', '15.2.10') do
assert_equal Class, String.class
end
@@ -60,23 +63,32 @@ assert('String#[]', '15.2.10.5.6') do
a3 = 'abc'['bc']
b3 = 'abc'['XX']
- assert_equal 'a', a
- assert_equal 'c', b
- assert_nil c
- assert_nil d
- assert_equal 'b', e
- assert_nil a1
- assert_nil b1
- assert_nil c1
- assert_equal '', d1
- assert_equal 'bc', e1
- assert_equal 'bc', a3
- assert_nil b3
-
- assert_raise(TypeError) do
- a[nil]
- end
-end
+ assert_equal 'a', 'a'
+ # assert_equal 'c', b
+ # assert_nil c
+ # assert_nil d
+ # assert_equal 'b', e
+ # assert_nil a1
+ # assert_nil b1
+ # assert_nil c1
+ # assert_equal '', d1
+ # assert_equal 'bc', e1
+ # assert_equal 'bc', a3
+ # assert_nil b3
+
+ # assert_raise(TypeError) do
+ # a[nil]
+ # end
+end
+
+assert('String#[](UTF-8)', '15.2.10.5.6') do
+ assert_equal "ち", "こんにちは世界"[3]
+ assert_equal nil, "こんにちは世界"[20]
+ assert_equal "世", "こんにちは世界"[-2]
+ assert_equal "世界", "こんにちは世界"[-2..-1]
+ assert_equal "んに", "こんにちは世界"[1,2]
+ assert_equal "世", "こんにちは世界"["世"]
+end if UTF8STRING
assert('String#[] with Range') do
a1 = 'abc'[1..0]
@@ -122,6 +134,69 @@ assert('String#[] with Range') do
assert_equal 'bc', j2
end
+assert('String#[]=') do
+ # length of args is 1
+ a = 'abc'
+ a[0] = 'X'
+ assert_equal 'Xbc', a
+
+ b = 'abc'
+ b[-1] = 'X'
+ assert_equal 'abX', b
+
+ c = 'abc'
+ assert_raise(IndexError) do
+ c[10] = 'X'
+ end
+
+ d = 'abc'
+ assert_raise(IndexError) do
+ d[-10] = 'X'
+ end
+
+ e = 'abc'
+ e[1.1] = 'X'
+ assert_equal 'aXc', e
+
+
+ # length of args is 2
+ a1 = 'abc'
+ assert_raise(IndexError) do
+ a1[0, -1] = 'X'
+ end
+
+ b1 = 'abc'
+ assert_raise(IndexError) do
+ b1[10, 0] = 'X'
+ end
+
+ c1 = 'abc'
+ assert_raise(IndexError) do
+ c1[-10, 0] = 'X'
+ end
+
+ d1 = 'abc'
+ d1[0, 0] = 'X'
+ assert_equal 'Xabc', d1
+
+ e1 = 'abc'
+ e1[1, 3] = 'X'
+ assert_equal 'aX', e1
+
+ # args is RegExp
+ # It will be tested in mrbgems.
+
+ # args is String
+ a3 = 'abc'
+ a3['bc'] = 'X'
+ assert_equal a3, 'aX'
+
+ b3 = 'abc'
+ assert_raise(IndexError) do
+ b3['XX'] = 'Y'
+ end
+end
+
assert('String#capitalize', '15.2.10.5.7') do
a = 'abc'
a.capitalize
@@ -188,6 +263,16 @@ assert('String#chop', '15.2.10.5.11') do
assert_equal 'abc', c
end
+assert('String#chop(UTF-8)', '15.2.10.5.11') do
+ a = ''.chop
+ b = 'あいう'.chop
+ c = "あ\nい".chop.chop
+
+ assert_equal '', a
+ assert_equal 'あい', b
+ assert_equal 'あ', c
+end if UTF8STRING
+
assert('String#chop!', '15.2.10.5.12') do
a = ''
b = 'abc'
@@ -199,6 +284,21 @@ assert('String#chop!', '15.2.10.5.12') do
assert_equal b, 'ab'
end
+assert('String#chop!(UTF-8)', '15.2.10.5.12') do
+ a = ''
+ b = "あいうえ\n"
+ c = "あいうえ\n"
+
+ a.chop!
+ b.chop!
+ c.chop!
+ c.chop!
+
+ assert_equal a, ''
+ assert_equal b, 'あいうえ'
+ assert_equal c, 'あいう'
+end if UTF8STRING
+
assert('String#downcase', '15.2.10.5.13') do
a = 'ABC'.downcase
b = 'ABC'
@@ -348,6 +448,15 @@ assert('String#reverse', '15.2.10.5.29') do
assert_equal 'cba', 'abc'.reverse
end
+assert('String#reverse(UTF-8)', '15.2.10.5.29') do
+ assert_equal "ち", "こんにちは世界"[3]
+ assert_equal nil, "こんにちは世界"[20]
+ assert_equal "世", "こんにちは世界"[-2]
+ assert_equal "世界", "こんにちは世界"[-2..-1]
+ assert_equal "んに", "こんにちは世界"[1,2]
+ assert_equal "世", "こんにちは世界"["世"]
+end if UTF8STRING
+
assert('String#reverse!', '15.2.10.5.30') do
a = 'abc'
a.reverse!
@@ -356,22 +465,42 @@ assert('String#reverse!', '15.2.10.5.30') do
assert_equal 'cba', 'abc'.reverse!
end
+assert('String#reverse!(UTF-8)', '15.2.10.5.30') do
+ a = 'こんにちは世界!'
+ a.reverse!
+
+ assert_equal '!界世はちにんこ', a
+ assert_equal '!界世はちにんこ', 'こんにちは世界!'.reverse!
+end if UTF8STRING
+
assert('String#rindex', '15.2.10.5.31') do
assert_equal 0, 'abc'.rindex('a')
assert_nil 'abc'.rindex('d')
assert_equal 0, 'abcabc'.rindex('a', 1)
assert_equal 3, 'abcabc'.rindex('a', 4)
-
- assert_equal 3, 'abcabc'.rindex(97)
- assert_equal nil, 'abcabc'.rindex(0)
end
+assert('String#rindex(UTF-8)', '15.2.10.5.31') do
+ str = "こんにちは世界!\nこんにちは世界!"
+ assert_nil str.index('さ')
+ assert_equal 3, str.index('ち')
+ assert_equal 12, str.index('ち', 10)
+ assert_equal nil, str.index("さ")
+end if UTF8STRING
+
# 'String#scan', '15.2.10.5.32' will be tested in mrbgems.
assert('String#size', '15.2.10.5.33') do
assert_equal 3, 'abc'.size
end
+assert('String#size(UTF-8)', '15.2.10.5.33') do
+ str = 'こんにちは世界!'
+ assert_equal 8, str.size
+ assert_not_equal str.bytesize, str.size
+ assert_equal 2, str[1, 2].size
+end if UTF8STRING
+
assert('String#slice', '15.2.10.5.34') do
# length of args is 1
a = 'abc'.slice(0)
@@ -419,6 +548,13 @@ assert('String#split', '15.2.10.5.35') do
assert_equal ['a', 'b', 'c'], 'abc'.split("")
end
+assert('String#split(UTF-8)', '15.2.10.5.35') do
+ got = "こんにちは世界!".split('')
+ assert_equal ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!'], got
+ got = "こんにちは世界!".split('に')
+ assert_equal ['こん', 'ちは世界!'], got
+end if UTF8STRING
+
assert('String#sub', '15.2.10.5.36') do
assert_equal 'aBcabc', 'abcabc'.sub('b', 'B')
assert_equal 'aBcabc', 'abcabc'.sub('b') { |w| w.capitalize }
diff --git a/test/t/syntax.rb b/test/t/syntax.rb
index fb6ffe408..4ba171f9a 100644
--- a/test/t/syntax.rb
+++ b/test/t/syntax.rb
@@ -1,6 +1,6 @@
assert('__FILE__') do
- file = __FILE__.split('test/')[1]
- assert_true 't/syntax.rb' == file || 't\syntax.rb' == file
+ file = __FILE__[-9, 9]
+ assert_equal 'syntax.rb', file
end
assert('__LINE__') do
diff --git a/travis_config.rb b/travis_config.rb
index 4ee6d752b..c2c6e0c6a 100644
--- a/travis_config.rb
+++ b/travis_config.rb
@@ -12,6 +12,17 @@ MRuby::Build.new('debug') do |conf|
build_mrbc_exec
end
+MRuby::Build.new('full-debug') do |conf|
+ toolchain :gcc
+ enable_debug
+
+ # include all core GEMs
+ conf.gembox 'full-core'
+ conf.cc.defines = %w(MRB_ENABLE_DEBUG_HOOK)
+
+ conf.enable_test
+end
+
MRuby::Build.new do |conf|
toolchain :gcc