mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge master.
This commit is contained in:
+2
-2
@@ -1,3 +1,4 @@
|
||||
*.lock
|
||||
*.bak
|
||||
*.bc
|
||||
*.d
|
||||
@@ -30,5 +31,4 @@ tags
|
||||
/benchmark/*.png
|
||||
|
||||
/doc/api
|
||||
|
||||
/src/y.tab.c
|
||||
/doc/capi
|
||||
|
||||
+10
-3
@@ -33,9 +33,16 @@ mruby should be highly portable to other systems and compilers. For this it is
|
||||
recommended to keep your code as close as possible to the C99 standard
|
||||
(http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf).
|
||||
|
||||
Although we target C99, Visual C++ is also an important target for mruby. For
|
||||
this reason a declaration of a local variable has to be at the beginning of a
|
||||
scope block.
|
||||
Although we target C99, we've heard some compilers in the embedded environment
|
||||
still requires declarations of local variables to be at the beginning of a
|
||||
scope. Until we confirm the situation has changed, we use the old-style
|
||||
variable declaration.
|
||||
|
||||
Visual C++ is also an important target for mruby (supported version is 2013 or
|
||||
later). For this reason features that are not supported by Visual C++ may not
|
||||
be used (e.g. `%z` of `strftime()`).
|
||||
|
||||
NOTE: Old GCC requires `-std=gnu99` option to enable C99 support.
|
||||
|
||||
#### Reduce library dependencies to a minimum
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## 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 2.x compatible.
|
||||
|
||||
mruby can be linked and embedded within your application. We provide the
|
||||
interpreter program "mruby" and the interactive mruby shell "mirb" as examples.
|
||||
@@ -38,7 +38,7 @@ We don't have a mailing list, but you can use [GitHub issues](https://github.com
|
||||
|
||||
## How to compile and install (mruby and gems)
|
||||
|
||||
See the [doc/guides/compile.md](doc/guides/compile.md) file.
|
||||
See the [compile.md](https://github.com/mruby/mruby/blob/master/doc/guides/compile.md) file.
|
||||
|
||||
## Running Tests
|
||||
|
||||
@@ -50,16 +50,29 @@ Or
|
||||
|
||||
$ ruby ./minirake test
|
||||
|
||||
## Building documentation
|
||||
|
||||
There are two sets of documentation in mruby: the mruby API (generated by yard) and C API (Doxygen)
|
||||
|
||||
To build both of them, simply go
|
||||
|
||||
rake doc
|
||||
|
||||
You can also view them in your browser
|
||||
|
||||
rake view_api
|
||||
rake view_capi
|
||||
|
||||
## 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/guides/mrbgems.md](doc/guides/mrbgems.md). For example code of
|
||||
how to use mrbgems look into the folder *examples/mrbgems/*.
|
||||
use mrbgems consult the file [mrbgems.md](https://github.com/mruby/mruby/blob/master/doc/guides/mrbgems.md).
|
||||
For example code of how to use mrbgems look into the folder *examples/mrbgems/*.
|
||||
|
||||
## License
|
||||
|
||||
mruby is released under the [MIT License](LICENSE).
|
||||
mruby is released under the [MIT License](https://github.com/mruby/mruby/blob/master/LICENSE).
|
||||
|
||||
## Note for License
|
||||
|
||||
@@ -88,5 +101,5 @@ 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.svg?branch=master
|
||||
[contribution-guidelines]: CONTRIBUTING.md
|
||||
[contribution-guidelines]: https://github.com/mruby/mruby/blob/master/CONTRIBUTING.md
|
||||
[travis-ci]: https://travis-ci.org/mruby/mruby
|
||||
|
||||
@@ -10,7 +10,6 @@ $LOAD_PATH << File.join(MRUBY_ROOT, "lib")
|
||||
# load build systems
|
||||
require "mruby-core-ext"
|
||||
require "mruby/build"
|
||||
require "mruby/gem"
|
||||
|
||||
# load configuration file
|
||||
MRUBY_CONFIG = (ENV['MRUBY_CONFIG'] && ENV['MRUBY_CONFIG'] != '') ? ENV['MRUBY_CONFIG'] : "#{MRUBY_ROOT}/build_config.rb"
|
||||
@@ -31,6 +30,7 @@ load "#{MRUBY_ROOT}/tasks/libmruby.rake"
|
||||
load "#{MRUBY_ROOT}/tasks/benchmark.rake"
|
||||
|
||||
load "#{MRUBY_ROOT}/tasks/gitlab.rake"
|
||||
load "#{MRUBY_ROOT}/tasks/doc.rake"
|
||||
|
||||
def install_D(src, dst)
|
||||
opts = { :verbose => $verbose }
|
||||
@@ -118,6 +118,7 @@ task :all => depfiles do
|
||||
MRuby.each_target do
|
||||
print_build_summary
|
||||
end
|
||||
MRuby::Lockfile.write
|
||||
end
|
||||
|
||||
desc "run all mruby tests"
|
||||
@@ -150,19 +151,9 @@ task :clean do
|
||||
end
|
||||
|
||||
desc "clean everything!"
|
||||
task :deep_clean => ["clean"] do
|
||||
task :deep_clean => ["clean", "clean_doc"] do
|
||||
MRuby.each_target do |t|
|
||||
FileUtils.rm_rf t.gem_clone_dir, { :verbose => $verbose }
|
||||
end
|
||||
puts "Cleaned up mrbgems build folder"
|
||||
end
|
||||
|
||||
desc 'generate document'
|
||||
task :doc do
|
||||
begin
|
||||
sh "mrbdoc"
|
||||
rescue
|
||||
puts "ERROR: To generate documents, you should install yard-mruby gem."
|
||||
puts " $ gem install yard-mruby"
|
||||
end
|
||||
end
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ MRuby::Build.new('full-debug') do |conf|
|
||||
|
||||
# include all core GEMs
|
||||
conf.gembox 'full-core'
|
||||
conf.cc.defines = %w(MRB_ENABLE_DEBUG_HOOK)
|
||||
conf.cc.defines += %w(MRB_ENABLE_DEBUG_HOOK)
|
||||
|
||||
conf.enable_test
|
||||
end
|
||||
|
||||
+3
-3
@@ -18,9 +18,9 @@ MRuby::Build.new do |conf|
|
||||
# end
|
||||
# conf.gem 'examples/mrbgems/c_and_ruby_extension_example'
|
||||
# conf.gem :core => 'mruby-eval'
|
||||
# conf.gem :mgem => 'mruby-io'
|
||||
# conf.gem :github => 'iij/mruby-io'
|
||||
# conf.gem :git => 'git@github.com:iij/mruby-io.git', :branch => 'master', :options => '-v'
|
||||
# conf.gem :mgem => 'mruby-onig-regexp'
|
||||
# conf.gem :github => 'mattn/mruby-onig-regexp'
|
||||
# conf.gem :git => 'git@github.com:mattn/mruby-onig-regexp.git', :branch => 'master', :options => '-v'
|
||||
|
||||
# include the default GEMs
|
||||
conf.gembox 'default'
|
||||
|
||||
+42
-42
@@ -6,11 +6,11 @@ binaries.
|
||||
## Prerequisites
|
||||
|
||||
To compile mruby out of the source code you need the following tools:
|
||||
* C Compiler (i.e. ```gcc```)
|
||||
* Linker (i.e. ```gcc```)
|
||||
* Archive utility (i.e. ```ar```)
|
||||
* Parser generator (i.e. ```bison```)
|
||||
* Ruby 1.8 or 1.9 (i.e. ```ruby``` or ```jruby```)
|
||||
* C Compiler (e.g. `gcc`)
|
||||
* Linker (e.g. `gcc`)
|
||||
* Archive utility (e.g. `ar`)
|
||||
* Parser generator (e.g. `bison`)
|
||||
* Ruby 2.0 or later (e.g. `ruby` or `jruby`)
|
||||
|
||||
Optional:
|
||||
* GIT (to update mruby source and integrate mrbgems easier)
|
||||
@@ -32,10 +32,10 @@ All tools necessary to compile mruby can be set or modified here. In case
|
||||
you want to maintain an additional *build_config.rb* you can define a
|
||||
customized path using the *$MRUBY_CONFIG* environment variable.
|
||||
|
||||
To compile just call ```./minirake``` inside of the mruby source root. To
|
||||
generate and execute the test tools call ```./minirake test```. To clean
|
||||
all build files call ```./minirake clean```. To see full command line on
|
||||
build, call ```./minirake -v```.
|
||||
To compile just call `./minirake` inside of the mruby source root. To
|
||||
generate and execute the test tools call `./minirake test`. To clean
|
||||
all build files call `./minirake clean`. To see full command line on
|
||||
build, call `./minirake -v`.
|
||||
|
||||
## Build Configuration
|
||||
|
||||
@@ -79,7 +79,7 @@ toolchain :android
|
||||
```
|
||||
|
||||
Requires the custom standalone Android NDK and the toolchain path
|
||||
in ```ANDROID_STANDALONE_TOOLCHAIN```.
|
||||
in `ANDROID_STANDALONE_TOOLCHAIN`.
|
||||
|
||||
### Binaries
|
||||
|
||||
@@ -97,7 +97,7 @@ conf.gem "#{root}/mrbgems/mruby-bin-mirb"
|
||||
### File Separator
|
||||
|
||||
Some environments require a different file separator character. It is possible to
|
||||
set the character via ```conf.file_separator```.
|
||||
set the character via `conf.file_separator`.
|
||||
```ruby
|
||||
conf.file_separator = '/'
|
||||
```
|
||||
@@ -119,7 +119,7 @@ end
|
||||
|
||||
C Compiler has header searcher to detect installed library.
|
||||
|
||||
If you need a include path of header file use ```search_header_path```:
|
||||
If you need a include path of header file use `search_header_path`:
|
||||
```ruby
|
||||
# Searches ```iconv.h```.
|
||||
# If found it will return include path of the header file.
|
||||
@@ -127,7 +127,7 @@ If you need a include path of header file use ```search_header_path```:
|
||||
fail 'iconv.h not found' unless conf.cc.search_header_path 'iconv.h'
|
||||
```
|
||||
|
||||
If you need a full file name of header file use ```search_header```:
|
||||
If you need a full file name of header file use `search_header`:
|
||||
```ruby
|
||||
# Searches ```iconv.h```.
|
||||
# If found it will return full path of the header file.
|
||||
@@ -136,11 +136,11 @@ iconv_h = conf.cc.search_header 'iconv.h'
|
||||
print "iconv.h found: #{iconv_h}\n"
|
||||
```
|
||||
|
||||
Header searcher uses compiler's ```include_paths``` by default.
|
||||
Header searcher uses compiler's `include_paths` by default.
|
||||
When you are using GCC toolchain (including clang toolchain since its base is gcc toolchain)
|
||||
it will use compiler specific include paths too. (For example ```/usr/local/include```, ```/usr/include```)
|
||||
it will use compiler specific include paths too. (For example `/usr/local/include`, `/usr/include`)
|
||||
|
||||
If you need a special header search paths define a singleton method ```header_search_paths``` to C compiler:
|
||||
If you need a special header search paths define a singleton method `header_search_paths` to C compiler:
|
||||
```ruby
|
||||
def conf.cc.header_search_paths
|
||||
['/opt/local/include'] + include_paths
|
||||
@@ -222,7 +222,7 @@ See doc/mrbgems/README.md for more option about mrbgems.
|
||||
|
||||
Configuration Mrbtest build process.
|
||||
|
||||
If you want mrbtest.a only, You should set ```conf.build_mrbtest_lib_only```
|
||||
If you want mrbtest.a only, You should set `conf.build_mrbtest_lib_only`
|
||||
```ruby
|
||||
conf.build_mrbtest_lib_only
|
||||
```
|
||||
@@ -230,9 +230,9 @@ conf.build_mrbtest_lib_only
|
||||
### Bintest
|
||||
|
||||
Tests for mrbgem tools using CRuby.
|
||||
To have bintests place \*.rb scripts to ```bintest/``` directory of mrbgems.
|
||||
See ```mruby-bin-*/bintest/*.rb``` if you need examples.
|
||||
If you want a temporary files use `tempfile` module of CRuby instead of ```/tmp/```.
|
||||
To have bintests place \*.rb scripts to `bintest/` directory of mrbgems.
|
||||
See `mruby-bin-*/bintest/*.rb` if you need examples.
|
||||
If you want a temporary files use `tempfile` module of CRuby instead of `/tmp/`.
|
||||
|
||||
You can enable it with following:
|
||||
```ruby
|
||||
@@ -247,8 +247,8 @@ correctly. To support mrbgems written in C++, mruby can be
|
||||
configured to use C++ exception.
|
||||
|
||||
There are two levels of C++ exception handling. The one is
|
||||
```enable_cxx_exception``` that enables C++ exception, but
|
||||
uses C ABI. The other is ```enable_cxx_abi``` where all
|
||||
`enable_cxx_exception` that enables C++ exception, but
|
||||
uses C ABI. The other is `enable_cxx_abi` where all
|
||||
files are compiled by C++ compiler.
|
||||
|
||||
When you mix C++ code, C++ exception would be enabled automatically.
|
||||
@@ -266,7 +266,7 @@ C++ exception, add following:
|
||||
conf.disable_cxx_exception
|
||||
```
|
||||
and you will get an error when you try to use C++ gem.
|
||||
Note that it must be called before ```enable_cxx_exception``` or ```gem``` method.
|
||||
Note that it must be called before `enable_cxx_exception` or `gem` method.
|
||||
|
||||
### Debugging mode
|
||||
|
||||
@@ -276,17 +276,17 @@ conf.enable_debug
|
||||
```
|
||||
|
||||
When debugging mode is enabled
|
||||
* Macro ```MRB_DEBUG``` would be defined.
|
||||
* Which means ```mrb_assert()``` macro is enabled.
|
||||
* Debug information of irep would be generated by ```mrbc```.
|
||||
* Because ```-g``` flag would be added to ```mrbc``` runner.
|
||||
* Macro `MRB_DEBUG` would be defined.
|
||||
* Which means `mrb_assert()` macro is enabled.
|
||||
* Debug information of irep would be generated by `mrbc`.
|
||||
* Because `-g` flag would be added to `mrbc` runner.
|
||||
* You can have better backtrace of mruby scripts with this.
|
||||
|
||||
## Cross-Compilation
|
||||
|
||||
mruby can also be cross-compiled from one platform to another. To
|
||||
achieve this the *build_config.rb* needs to contain an instance of
|
||||
```MRuby::CrossBuild```. This instance defines the compilation
|
||||
`MRuby::CrossBuild`. This instance defines the compilation
|
||||
tools and flags for the target platform. An example could look
|
||||
like this:
|
||||
```ruby
|
||||
@@ -298,12 +298,12 @@ MRuby::CrossBuild.new('32bit') do |conf|
|
||||
end
|
||||
```
|
||||
|
||||
All configuration options of ```MRuby::Build``` can also be used
|
||||
in ```MRuby::CrossBuild```.
|
||||
All configuration options of `MRuby::Build` can also be used
|
||||
in `MRuby::CrossBuild`.
|
||||
|
||||
### Mrbtest in Cross-Compilation
|
||||
|
||||
In cross compilation, you can run ```mrbtest``` on emulator if
|
||||
In cross compilation, you can run `mrbtest` on emulator if
|
||||
you have it by changing configuration of test runner.
|
||||
```ruby
|
||||
conf.test_runner do |t|
|
||||
@@ -350,15 +350,15 @@ in *build/host/src*)
|
||||
result will be stored in *build/host/src/y.tab.c*)
|
||||
* compile *build/host/src/y.tab.c* to *build/host/src/y.tab.o*
|
||||
* create *build/host/lib/libmruby_core.a* out of all object files (C only)
|
||||
* create ```build/host/bin/mrbc``` by compiling *tools/mrbc/mrbc.c* and
|
||||
* create `build/host/bin/mrbc` by compiling *tools/mrbc/mrbc.c* and
|
||||
linking with *build/host/lib/libmruby_core.a*
|
||||
* create *build/host/mrblib/mrblib.c* by compiling all \*.rb files
|
||||
under *mrblib* with ```build/host/bin/mrbc```
|
||||
under *mrblib* with `build/host/bin/mrbc`
|
||||
* compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o*
|
||||
* create *build/host/lib/libmruby.a* out of all object files (C and Ruby)
|
||||
* create ```build/host/bin/mruby``` by compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and
|
||||
* create `build/host/bin/mruby` by compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and
|
||||
linking with *build/host/lib/libmruby.a*
|
||||
* create ```build/host/bin/mirb``` by compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and
|
||||
* create `build/host/bin/mirb` by compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and
|
||||
linking with *build/host/lib/libmruby.a*
|
||||
|
||||
```
|
||||
@@ -427,15 +427,15 @@ in *build/i386/src*)
|
||||
result will be stored in *build/i386/src/y.tab.c*)
|
||||
* cross-compile *build/i386/src/y.tab.c* to *build/i386/src/y.tab.o*
|
||||
* create *build/i386/mrblib/mrblib.c* by compiling all \*.rb files
|
||||
under *mrblib* with the native ```build/host/bin/mrbc```
|
||||
under *mrblib* with the native `build/host/bin/mrbc`
|
||||
* cross-compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o*
|
||||
* create *build/i386/lib/libmruby.a* out of all object files (C and Ruby)
|
||||
* create ```build/i386/bin/mruby``` by cross-compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and
|
||||
* create `build/i386/bin/mruby` by cross-compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and
|
||||
linking with *build/i386/lib/libmruby.a*
|
||||
* create ```build/i386/bin/mirb``` by cross-compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and
|
||||
* create `build/i386/bin/mirb` by cross-compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and
|
||||
linking with *build/i386/lib/libmruby.a*
|
||||
* create *build/i386/lib/libmruby_core.a* out of all object files (C only)
|
||||
* create ```build/i386/bin/mrbc``` by cross-compiling *tools/mrbc/mrbc.c* and
|
||||
* create `build/i386/bin/mrbc` by cross-compiling *tools/mrbc/mrbc.c* and
|
||||
linking with *build/i386/lib/libmruby_core.a*
|
||||
|
||||
```
|
||||
@@ -463,7 +463,7 @@ linking with *build/i386/lib/libmruby_core.a*
|
||||
### Minimal Library
|
||||
|
||||
To build a minimal mruby library you need to use the Cross Compiling
|
||||
feature due to the reason that there are functions (i.e. stdio) which
|
||||
feature due to the reason that there are functions (e.g. stdio) which
|
||||
can't be disabled for the main build.
|
||||
|
||||
```ruby
|
||||
@@ -477,12 +477,12 @@ end
|
||||
|
||||
This configuration defines a cross compile build called 'Minimal' which
|
||||
is using the GCC and compiles for the host machine. It also disables
|
||||
all usages of stdio and doesn't compile any binaries (i.e. mrbc).
|
||||
all usages of stdio and doesn't compile any binaries (e.g. mrbc).
|
||||
|
||||
## Test Environment
|
||||
|
||||
mruby's build process includes a test environment. In case you start the testing
|
||||
of mruby, a native binary called ```mrbtest``` will be generated and executed.
|
||||
of mruby, a native binary called `mrbtest` will be generated and executed.
|
||||
This binary contains all test cases which are defined under *test/t*. In case
|
||||
of a cross-compilation an additional cross-compiled *mrbtest* binary is
|
||||
generated. You can copy this binary and run on your target system.
|
||||
|
||||
+45
-6
@@ -50,15 +50,21 @@ You can use mrbconfs with following ways:
|
||||
* When defined single precision floating point type(C type `float`) is used as `mrb_float`.
|
||||
* Else double precision floating point type(C type `double`) is used as `mrb_float`.
|
||||
|
||||
`MRB_WITHOUT_FLOAT`
|
||||
* When defined removes floating point numbers from mruby.
|
||||
* It makes mruby easier to handle in "Microcontroller without FPU" and "Kernel Space".
|
||||
|
||||
`MRB_INT16`
|
||||
* When defined `int16_t` will be defined as `mrb_int`.
|
||||
* Conflicts with `MRB_INT64`.
|
||||
* Conflicts with `MRB_INT32` and `MRB_INT64`.
|
||||
|
||||
`MRB_INT32`
|
||||
* When defined, or both `MRB_INT16` and `MRB_INT64` are not defined on 32-bit CPU mode, `int32_t` will be defined as `mrb_int`.
|
||||
* Conflicts with `MRB_INT16` and `MRB_INT64`.
|
||||
|
||||
`MRB_INT64`
|
||||
* When defined `int64_t` will be defined as `mrb_int`.
|
||||
* Conflicts with `MRB_INT16`.
|
||||
* When `MRB_INT16` or `MRB_INT64` isn't defined `int`(most of the times 32-bit integer)
|
||||
will be defined as `mrb_int`.
|
||||
* When defined, or both `MRB_INT16` and `MRB_INT32` are not defined on 64-bit CPU mode, `int64_t` will be defined as `mrb_int`.
|
||||
* Conflicts with `MRB_INT16` and `MRB_INT32`.
|
||||
|
||||
## Garbage collector configuration.
|
||||
|
||||
@@ -115,7 +121,7 @@ largest value of required alignment.
|
||||
|
||||
`MRB_NAN_BOXING`
|
||||
* If defined represent `mrb_value` in boxed `double`.
|
||||
* Conflicts with `MRB_USE_FLOAT`.
|
||||
* Conflicts with `MRB_USE_FLOAT` and `MRB_WITHOUT_FLOAT`.
|
||||
|
||||
`MRB_WORD_BOXING`
|
||||
* If defined represent `mrb_value` as a word.
|
||||
@@ -126,6 +132,22 @@ largest value of required alignment.
|
||||
* Default value is `4`.
|
||||
* Specifies size of each segment in segment list.
|
||||
|
||||
## Reduce heap memory configuration.
|
||||
|
||||
`MRB_USE_LINK_TIME_RO_DATA_P`
|
||||
* Only available on ELF platforms.
|
||||
* If you specify the address of a read-only section when creating a symbol or string, that string will be used as it is.
|
||||
* Heap memory can be saved.
|
||||
* Uses `__ehdr_start` and `__init_array_start`.
|
||||
* It must be `__ehdr_start < data_addr < __init_array_start`.
|
||||
|
||||
`MRB_USE_CUSTOM_RO_DATA_P`
|
||||
* Takes precedence over `MRB_USE_LINK_TIME_RO_DATA_P`.
|
||||
* Please try if `MRB_USE_LINK_TIME_RO_DATA_P` is not available.
|
||||
* The `mrb_ro_data_p()` function is implemented by the user in an arbitrary file.
|
||||
* The prototype declaration is `mrb_bool mrb_ro_data_p(const char *ptr)`.
|
||||
* Return `TRUE` if `ptr` is in read-only section, otherwise return `FALSE`.
|
||||
|
||||
## Other configuration.
|
||||
`MRB_UTF8_STRING`
|
||||
* Adds UTF-8 encoding support to character-oriented String instance methods.
|
||||
@@ -144,3 +166,20 @@ largest value of required alignment.
|
||||
`MRB_STR_BUF_MIN_SIZE`
|
||||
* Default value is `128`.
|
||||
* Specifies initial capacity of `RString` created by `mrb_str_buf_new` function..
|
||||
|
||||
`MRB_METHOD_CACHE`
|
||||
* Improve performance for method dispatch.
|
||||
|
||||
`MRB_METHOD_CACHE_SIZE`
|
||||
* Default value is `128`.
|
||||
* Ignored if `MRB_METHOD_CACHE` is not defined.
|
||||
* Need to be the power of 2.
|
||||
|
||||
`MRB_METHOD_T_STRUCT`
|
||||
* Use C struct to represent `mrb_method_t`
|
||||
* No `MRB_METHOD_T_STRUCT` requires highest 2 bits of function pointers to be zero
|
||||
* Define this macro on machines that use higher bits of pointers
|
||||
|
||||
`MRB_ENABLE_ALL_SYMBOLS`
|
||||
* Make it available `Symbols.all_symbols` in `mrbgems/mruby-symbol-ext`
|
||||
* Increase heap memory usage.
|
||||
|
||||
@@ -37,6 +37,11 @@ conf.gem :mgem => 'mruby-yaml'
|
||||
conf.gem :mgem => 'yaml' # 'mruby-' prefix could be omitted
|
||||
```
|
||||
|
||||
For specifying commit hash to checkout use `:checksum_hash` option:
|
||||
```ruby
|
||||
conf.gem mgem: 'mruby-redis', checksum_hash: '3446d19fc4a3f9697b5ddbf2a904f301c42f2f4e'
|
||||
```
|
||||
|
||||
If there is missing dependencies, mrbgem dependencies solver will reference
|
||||
mrbgem from core or mgem-list.
|
||||
|
||||
|
||||
+79
-29
@@ -14,17 +14,17 @@ This document does not contain a complete list of limitations.
|
||||
Please help to improve it by submitting your findings.
|
||||
|
||||
|
||||
## ```1/2``` gives ```0.5```
|
||||
## `1/2` gives `0.5`
|
||||
|
||||
Since mruby does not have ```Bignum```, bigger integers are represented
|
||||
by ```Float``` numbers. To enhance interoperability between ```Fixnum```
|
||||
and ```Float```, mruby provides ```Float#upto``` and other iterating
|
||||
methods for the ```Float``` class. As a side effect, ```1/2``` gives ```0.5```
|
||||
not ```0```.
|
||||
Since mruby does not have `Bignum`, bigger integers are represented
|
||||
by `Float` numbers. To enhance interoperability between `Fixnum`
|
||||
and `Float`, mruby provides `Float#upto` and other iterating
|
||||
methods for the `Float` class. As a side effect, `1/2` gives `0.5`
|
||||
not `0`.
|
||||
|
||||
## ```Array``` passed to ```puts```
|
||||
## `Array` passed to `puts`
|
||||
|
||||
Passing an Array to ```puts``` results in different output.
|
||||
Passing an Array to `puts` results in different output.
|
||||
|
||||
```ruby
|
||||
puts [1,2,3]
|
||||
@@ -44,9 +44,9 @@ puts [1,2,3]
|
||||
[1, 2, 3]
|
||||
```
|
||||
|
||||
## ```Kernel.raise``` in rescue clause
|
||||
## `Kernel.raise` in rescue clause
|
||||
|
||||
```Kernel.raise``` without arguments does not raise the current exception within
|
||||
`Kernel.raise` without arguments does not raise the current exception within
|
||||
a rescue clause.
|
||||
|
||||
```ruby
|
||||
@@ -59,7 +59,7 @@ end
|
||||
|
||||
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
|
||||
|
||||
```ZeroDivisionError``` is raised.
|
||||
`ZeroDivisionError` is raised.
|
||||
|
||||
#### mruby [2.0.1 (2019-4-4)]
|
||||
|
||||
@@ -67,13 +67,13 @@ No exception is raised.
|
||||
|
||||
## Fiber execution can't cross C function boundary
|
||||
|
||||
mruby's ```Fiber``` is implemented in a similar way to Lua's co-routine. This
|
||||
mruby's `Fiber` is implemented in a similar way to Lua's co-routine. This
|
||||
results in the consequence that you can't switch context within C functions.
|
||||
Only exception is ```mrb_fiber_yield``` at return.
|
||||
Only exception is `mrb_fiber_yield` at return.
|
||||
|
||||
## ```Array``` does not support instance variables
|
||||
## `Array` does not support instance variables
|
||||
|
||||
To reduce memory consumption ```Array``` does not support instance variables.
|
||||
To reduce memory consumption `Array` does not support instance variables.
|
||||
|
||||
```ruby
|
||||
class Liste < Array
|
||||
@@ -87,16 +87,16 @@ p Liste.new "foobar"
|
||||
|
||||
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
|
||||
|
||||
``` [] ```
|
||||
` [] `
|
||||
|
||||
#### mruby [2.0.1 (2019-4-4)]
|
||||
|
||||
```ArgumentError``` is raised.
|
||||
`ArgumentError` is raised.
|
||||
|
||||
## Method visibility
|
||||
|
||||
For simplicity reasons no method visibility (public/private/protected) is
|
||||
supported.
|
||||
supported. Those methods are defined but they are dummy methods.
|
||||
|
||||
```ruby
|
||||
class VisibleTest
|
||||
@@ -126,10 +126,46 @@ true
|
||||
true
|
||||
```
|
||||
|
||||
## defined?
|
||||
### Visibility Declaration
|
||||
|
||||
The ```defined?``` keyword is considered too complex to be fully
|
||||
implemented. It is recommended to use ```const_defined?``` and
|
||||
The declaration form of following visibility methods are not implemented.
|
||||
|
||||
* `public`
|
||||
* `private`
|
||||
* `protected`
|
||||
* `module_function`
|
||||
|
||||
Especially, `module_function` method is not dummy, but no declaration form.
|
||||
|
||||
```
|
||||
module TestModule
|
||||
module_function
|
||||
def test_func
|
||||
p 'test_func called'
|
||||
end
|
||||
|
||||
test_func
|
||||
end
|
||||
|
||||
p 'ok'
|
||||
```
|
||||
|
||||
#### Ruby [ruby 2.5.5p157 (2019-03-15 revision 67260)]
|
||||
|
||||
```
|
||||
ok
|
||||
```
|
||||
|
||||
#### mruby [2.0.1 (2019-4-4)]
|
||||
|
||||
```
|
||||
test.rb:8: undefined method 'test_func' (NoMethodError)
|
||||
```
|
||||
|
||||
## `defined?`
|
||||
|
||||
The `defined?` keyword is considered too complex to be fully
|
||||
implemented. It is recommended to use `const_defined?` and
|
||||
other reflection methods instead.
|
||||
|
||||
```ruby
|
||||
@@ -144,9 +180,9 @@ nil
|
||||
|
||||
#### mruby [2.0.1 (2019-4-4)]
|
||||
|
||||
```NameError``` is raised.
|
||||
`NameError` is raised.
|
||||
|
||||
## ```alias``` on global variables
|
||||
## `alias` on global variables
|
||||
|
||||
Aliasing a global variable works in CRuby but is not part
|
||||
of the ISO standard.
|
||||
@@ -157,7 +193,7 @@ alias $a $__a__
|
||||
|
||||
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
|
||||
|
||||
``` nil ```
|
||||
` nil `
|
||||
|
||||
#### mruby [2.0.1 (2019-4-4)]
|
||||
|
||||
@@ -178,15 +214,15 @@ end
|
||||
|
||||
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
|
||||
|
||||
```ArgumentError``` is raised.
|
||||
The re-defined ```+``` operator does not accept any arguments.
|
||||
`ArgumentError` is raised.
|
||||
The re-defined `+` operator does not accept any arguments.
|
||||
|
||||
#### mruby [2.0.1 (2019-4-4)]
|
||||
|
||||
``` 'ab' ```
|
||||
` 'ab' `
|
||||
Behavior of the operator wasn't changed.
|
||||
|
||||
## Kernel#binding is not supported
|
||||
## `Kernel#binding` is not supported
|
||||
|
||||
`Kernel#binding` method is not supported.
|
||||
|
||||
@@ -238,7 +274,7 @@ Destructured arguments (`b` and `c` in above example) cannot be accessed
|
||||
from the default expression of optional arguments and keyword arguments,
|
||||
since actual assignment is done after the evaluation of those default
|
||||
expressions. Thus:
|
||||
|
||||
|
||||
```ruby
|
||||
def f(a,(b,c),d=b)
|
||||
p [a,b,c,d]
|
||||
@@ -247,3 +283,17 @@ f(1,[2,3])
|
||||
```
|
||||
|
||||
CRuby gives `[1,2,3,nil]`. mruby raises `NoMethodError` for `b`.
|
||||
|
||||
## `nil?` redefinition in conditional expressions
|
||||
|
||||
Redefinition of `nil?` is ignored in conditional expressions.
|
||||
|
||||
```ruby
|
||||
a = "a"
|
||||
def a.nil?
|
||||
true
|
||||
end
|
||||
puts(a.nil? ? "truthy" : "falsy")
|
||||
```
|
||||
|
||||
Ruby outputs `falsy`. mruby outputs `truthy`.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.4 KiB |
+94
-94
@@ -31,97 +31,97 @@ with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
|
||||
|
||||
## table.1 Instruction Table
|
||||
|
||||
|Instruction Name |Operand type |Semantics
|
||||
|-----------------|-------------|-----------------
|
||||
|OP_NOP | - |
|
||||
|OP_MOVE" |BB |R(a) = R(b)
|
||||
|OP_LOADL" |BB |R(a) = Pool(b)
|
||||
|OP_LOADI" |BsB |R(a) = mrb_int(b)
|
||||
|OP_LOADI_0' |B |R(a) = 0
|
||||
|OP_LOADI_1' |B |R(a) = 1
|
||||
|OP_LOADI_2' |B |R(a) = 2
|
||||
|OP_LOADI_3' |B |R(a) = 3
|
||||
|OP_LOADSYM" |BB |R(a) = Syms(b)
|
||||
|OP_LOADNIL' |B |R(a) = nil
|
||||
|OP_LOADSELF' |B |R(a) = self
|
||||
|OP_LOADT' |B |R(a) = true
|
||||
|OP_LOADF' |B |R(a) = false
|
||||
|OP_GETGV" |BB |R(a) = getglobal(Syms(b))
|
||||
|OP_SETGV" |BB |setglobal(Syms(b), R(a))
|
||||
|OP_GETSV" |BB |R(a) = Special[b]
|
||||
|OP_SETSV" |BB |Special[b] = R(a)
|
||||
|OP_GETIV" |BB |R(a) = ivget(Syms(b))
|
||||
|OP_SETIV" |BB |ivset(Syms(b),R(a))
|
||||
|OP_GETCV" |BB |R(a) = cvget(Syms(b))
|
||||
|OP_SETCV" |BB |cvset(Syms(b),R(a))
|
||||
|OP_GETCONST" |BB |R(a) = constget(Syms(b))
|
||||
|OP_SETCONST" |BB |constset(Syms(b),R(a))
|
||||
|OP_GETMCNST" |BB |R(a) = R(a)::Syms(b)
|
||||
|OP_SETMCNST" |BB |R(a+1)::Syms(b) = R(a)
|
||||
|OP_GETUPVAR' |BBB |R(a) = uvget(b,c)
|
||||
|OP_SETUPVAR' |BBB |uvset(b,c,R(a))
|
||||
|OP_JMP |S |pc+=a
|
||||
|OP_JMPIF' |SB |if R(b) pc+=a
|
||||
|OP_JMPNOT' |SB |if !R(b) pc+=a
|
||||
|OP_ONERR |sS |rescue_push(pc+a)
|
||||
|OP_EXCEPT' |B |R(a) = exc
|
||||
|OP_RESCUE" |BB |R(b) = R(a).isa?(R(b))
|
||||
|OP_POPERR |B |a.times{rescue_pop()}
|
||||
|OP_RAISE' |B |raise(R(a))
|
||||
|OP_EPUSH' |B |ensure_push(SEQ[a])
|
||||
|OP_EPOP |B |A.times{ensure_pop().call}
|
||||
|OP_SENDV" |BB |R(a) = call(R(a),Syms(b),*R(a+1))
|
||||
|OP_SENDVB" |BB |R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2))
|
||||
|OP_SEND" |BBB |R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c))
|
||||
|OP_SENDB" |BBB |R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1))
|
||||
|OP_CALL' |B |R(a) = self.call(frame.argc, frame.argv)
|
||||
|OP_SUPER' |BB |R(a) = super(R(a+1),... ,R(a+b+1))
|
||||
|OP_ARGARY' |BS |R(a) = argument array (16=5:1:5:1:4)
|
||||
|OP_ENTER |W |arg setup according to flags (23=5:5:1:5:5:1:1)
|
||||
|OP_KARG" |BB |R(a) = kdict[Syms(Bx)] # todo
|
||||
|OP_KARG2" |BB |R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo
|
||||
|OP_RETURN' |B |return R(a) (normal)
|
||||
|OP_RETURN_BLK' |B |return R(a) (in-block return)
|
||||
|OP_BREAK' |B |break R(a)
|
||||
|OP_BLKPUSH' |BS |R(a) = block (16=5:1:5:1:4)
|
||||
|OP_ADD" |BB |R(a) = R(a)+R(a+1)
|
||||
|OP_ADDI" |BBB |R(a) = R(a)+mrb_int(c)
|
||||
|OP_SUB" |BB |R(a) = R(a)-R(a+1)
|
||||
|OP_SUBI" |BB |R(a) = R(a)-C
|
||||
|OP_MUL" |BB |R(a) = R(a)*R(a+1)
|
||||
|OP_DIV" |BB |R(a) = R(a)/R(a+1)
|
||||
|OP_EQ" |BB |R(a) = R(a)==R(a+1)
|
||||
|OP_LT" |BB |R(a) = R(a)<R(a+1)
|
||||
|OP_LE" |BB |R(a) = R(a)<=R(a+1)
|
||||
|OP_GT" |BB |R(a) = R(a)>R(a+1)
|
||||
|OP_GE" |BB |R(a) = R(a)>=R(a+1)
|
||||
|OP_ARRAY' |BB |R(a) = ary_new(R(a),R(a+1)..R(a+b))
|
||||
|OP_ARRAY2" |BB |R(a) = ary_new(R(b),R(b+1)..R(b+c))
|
||||
|OP_ARYCAT' |B |ary_cat(R(a),R(a+1))
|
||||
|OP_ARYPUSH' |B |ary_push(R(a),R(a+1))
|
||||
|OP_AREF' |BB |R(a) = R(a)[b]
|
||||
|OP_ASET' |BB |R(a)[b] = R(a+1)
|
||||
|OP_APOST' |BB |*R(a),R(A+1)..R(A+C) = R(a)[B..]
|
||||
|OP_STRING" |BB |R(a) = str_dup(Lit(b))
|
||||
|OP_STRCAT' |B |str_cat(R(a),R(a+1))
|
||||
|OP_HASH' |BB |R(a) = hash_new(R(a),R(a+1)..R(a+b))
|
||||
|OP_HASHADD' |BB |R(a) = hash_push(R(a),R(a+1)..R(a+b))
|
||||
|OP_LAMBDA" |BB |R(a) = lambda(SEQ[b],OP_L_LAMBDA)
|
||||
|OP_BLOCK" |BB |R(a) = lambda(SEQ[b],OP_L_BLOCK)
|
||||
|OP_METHOD" |BB |R(a) = lambda(SEQ[b],OP_L_METHOD)
|
||||
|OP_RANGE_INC' |B |R(a) = range_new(R(a),R(a+1),FALSE)
|
||||
|OP_RANGE_EXC' |B |R(a) = range_new(R(a),R(a+1),TRUE)
|
||||
|OP_OCLASS' |B |R(a) = ::Object
|
||||
|OP_CLASS" |BB |R(a) = newclass(R(a),Syms(b),R(a+1))
|
||||
|OP_MODULE" |BB |R(a) = newmodule(R(a),Syms(b))
|
||||
|OP_EXEC" |BB |R(a) = blockexec(R(a),SEQ[b])
|
||||
|OP_DEF" |BB |R(a).newmethod(Syms(b),R(a+1))
|
||||
|OP_ALIAS' |B |alias_method(R(a),R(a+1),R(a+2))
|
||||
|OP_UNDEF" |BB |undef_method(R(a),Syms(b))
|
||||
|OP_SCLASS' |B |R(a) = R(a).singleton_class
|
||||
|OP_TCLASS' |B |R(a) = target_class
|
||||
|OP_ERR' |B |raise(RuntimeError, Lit(Bx))
|
||||
|OP_EXT1 |- |make 1st operand 16bit
|
||||
|OP_EXT2 |- |make 2nd operand 16bit
|
||||
|OP_EXT3 |- |make 1st and 2nd operands 16bit
|
||||
|OP_STOP |- |stop VM
|
||||
| Instruction Name | Operand type | Semantics |
|
||||
|:-----------------|--------------|---------------------|
|
||||
| OP_NOP | - | |
|
||||
| OP_MOVE" | BB | R(a) = R(b)
|
||||
| OP_LOADL" | BB | R(a) = Pool(b)
|
||||
| OP_LOADI" | BsB | R(a) = mrb_int(b)
|
||||
| OP_LOADI_0' | B | R(a) = 0
|
||||
| OP_LOADI_1' | B | R(a) = 1
|
||||
| OP_LOADI_2' | B | R(a) = 2
|
||||
| OP_LOADI_3' | B | R(a) = 3
|
||||
| OP_LOADSYM" | BB | R(a) = Syms(b)
|
||||
| OP_LOADNIL' | B | R(a) = nil
|
||||
| OP_LOADSELF' | B | R(a) = self
|
||||
| OP_LOADT' | B | R(a) = true
|
||||
| OP_LOADF' | B | R(a) = false
|
||||
| OP_GETGV" | BB | R(a) = getglobal(Syms(b))
|
||||
| OP_SETGV" | BB | setglobal(Syms(b), R(a))
|
||||
| OP_GETSV" | BB | R(a) = Special[b]
|
||||
| OP_SETSV" | BB | Special[b] = R(a)
|
||||
| OP_GETIV" | BB | R(a) = ivget(Syms(b))
|
||||
| OP_SETIV" | BB | ivset(Syms(b),R(a))
|
||||
| OP_GETCV" | BB | R(a) = cvget(Syms(b))
|
||||
| OP_SETCV" | BB | cvset(Syms(b),R(a))
|
||||
| OP_GETCONST" | BB | R(a) = constget(Syms(b))
|
||||
| OP_SETCONST" | BB | constset(Syms(b),R(a))
|
||||
| OP_GETMCNST" | BB | R(a) = R(a)::Syms(b)
|
||||
| OP_SETMCNST" | BB | R(a+1)::Syms(b) = R(a)
|
||||
| OP_GETUPVAR' | BBB | R(a) = uvget(b,c)
|
||||
| OP_SETUPVAR' | BBB | uvset(b,c,R(a))
|
||||
| OP_JMP | S | pc+=a
|
||||
| OP_JMPIF' | SB | if R(b) pc+=a
|
||||
| OP_JMPNOT' | SB | if !R(b) pc+=a
|
||||
| OP_ONERR | sS | rescue_push(pc+a)
|
||||
| OP_EXCEPT' | B | R(a) = exc
|
||||
| OP_RESCUE" | BB | R(b) = R(a).isa?(R(b))
|
||||
| OP_POPERR | B | a.times{rescue_pop()}
|
||||
| OP_RAISE' | B | raise(R(a))
|
||||
| OP_EPUSH' | B | ensure_push(SEQ[a])
|
||||
| OP_EPOP | B | A.times{ensure_pop().call}
|
||||
| OP_SENDV" | BB | R(a) = call(R(a),Syms(b),*R(a+1))
|
||||
| OP_SENDVB" | BB | R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2))
|
||||
| OP_SEND" | BBB | R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c))
|
||||
| OP_SENDB" | BBB | R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1))
|
||||
| OP_CALL' | B | R(a) = self.call(frame.argc, frame.argv)
|
||||
| OP_SUPER' | BB | R(a) = super(R(a+1),... ,R(a+b+1))
|
||||
| OP_ARGARY' | BS | R(a) = argument array (16=5:1:5:1:4)
|
||||
| OP_ENTER | W | arg setup according to flags (23=5:5:1:5:5:1:1)
|
||||
| OP_KARG" | BB | R(a) = kdict[Syms(Bx)] # todo
|
||||
| OP_KARG2" | BB | R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo
|
||||
| OP_RETURN' | B | return R(a) (normal)
|
||||
| OP_RETURN_BLK' | B | return R(a) (in-block return)
|
||||
| OP_BREAK' | B | break R(a)
|
||||
| OP_BLKPUSH' | BS | R(a) = block (16=5:1:5:1:4)
|
||||
| OP_ADD" | BB | R(a) = R(a)+R(a+1)
|
||||
| OP_ADDI" | BBB | R(a) = R(a)+mrb_int(c)
|
||||
| OP_SUB" | BB | R(a) = R(a)-R(a+1)
|
||||
| OP_SUBI" | BB | R(a) = R(a)-C
|
||||
| OP_MUL" | BB | R(a) = R(a)*R(a+1)
|
||||
| OP_DIV" | BB | R(a) = R(a)/R(a+1)
|
||||
| OP_EQ" | BB | R(a) = R(a)==R(a+1)
|
||||
| OP_LT" | BB | R(a) = R(a)<R(a+1)
|
||||
| OP_LE" | BB | R(a) = R(a)<=R(a+1)
|
||||
| OP_GT" | BB | R(a) = R(a)>R(a+1)
|
||||
| OP_GE" | BB | R(a) = R(a)>=R(a+1)
|
||||
| OP_ARRAY' | BB | R(a) = ary_new(R(a),R(a+1)..R(a+b))
|
||||
| OP_ARRAY2" | BB | R(a) = ary_new(R(b),R(b+1)..R(b+c))
|
||||
| OP_ARYCAT' | B | ary_cat(R(a),R(a+1))
|
||||
| OP_ARYPUSH' | B | ary_push(R(a),R(a+1))
|
||||
| OP_AREF' | BB | R(a) = R(a)[b]
|
||||
| OP_ASET' | BB | R(a)[b] = R(a+1)
|
||||
| OP_APOST' | BB | *R(a),R(A+1)..R(A+C) = R(a)[B..]
|
||||
| OP_STRING" | BB | R(a) = str_dup(Lit(b))
|
||||
| OP_STRCAT' | B | str_cat(R(a),R(a+1))
|
||||
| OP_HASH' | BB | R(a) = hash_new(R(a),R(a+1)..R(a+b))
|
||||
| OP_HASHADD' | BB | R(a) = hash_push(R(a),R(a+1)..R(a+b))
|
||||
| OP_LAMBDA" | BB | R(a) = lambda(SEQ[b],OP_L_LAMBDA)
|
||||
| OP_BLOCK" | BB | R(a) = lambda(SEQ[b],OP_L_BLOCK)
|
||||
| OP_METHOD" | BB | R(a) = lambda(SEQ[b],OP_L_METHOD)
|
||||
| OP_RANGE_INC' | B | R(a) = range_new(R(a),R(a+1),FALSE)
|
||||
| OP_RANGE_EXC' | B | R(a) = range_new(R(a),R(a+1),TRUE)
|
||||
| OP_OCLASS' | B | R(a) = ::Object
|
||||
| OP_CLASS" | BB | R(a) = newclass(R(a),Syms(b),R(a+1))
|
||||
| OP_MODULE" | BB | R(a) = newmodule(R(a),Syms(b))
|
||||
| OP_EXEC" | BB | R(a) = blockexec(R(a),SEQ[b])
|
||||
| OP_DEF" | BB | R(a).newmethod(Syms(b),R(a+1))
|
||||
| OP_ALIAS' | B | alias_method(R(a),R(a+1),R(a+2))
|
||||
| OP_UNDEF" | BB | undef_method(R(a),Syms(b))
|
||||
| OP_SCLASS' | B | R(a) = R(a).singleton_class
|
||||
| OP_TCLASS' | B | R(a) = target_class
|
||||
| OP_ERR' | B | raise(RuntimeError, Lit(Bx))
|
||||
| OP_EXT1 | - | make 1st operand 16bit
|
||||
| OP_EXT2 | - | make 2nd operand 16bit
|
||||
| OP_EXT3 | - | make 1st and 2nd operands 16bit
|
||||
| OP_STOP | - | stop VM
|
||||
|
||||
+77
-11
@@ -36,15 +36,19 @@
|
||||
/* size of the method cache (need to be the power of 2) */
|
||||
//#define MRB_METHOD_CACHE_SIZE (1<<7)
|
||||
|
||||
/* add -DMRB_METHOD_TABLE_INLINE to reduce the size of method table */
|
||||
/* MRB_METHOD_TABLE_INLINE requires LSB of function pointers to be zero */
|
||||
/* you might need to specify --falign-functions=n (where n>1) */
|
||||
//#define MRB_METHOD_TABLE_INLINE
|
||||
/* add -DMRB_METHOD_T_STRUCT on machines that use higher bits of pointers */
|
||||
/* no MRB_METHOD_T_STRUCT requires highest 2 bits of function pointers to be zero */
|
||||
//#define MRB_METHOD_T_STRUCT
|
||||
|
||||
/* add -DMRB_INT16 to use 16bit integer for mrb_int; conflict with MRB_INT64 */
|
||||
/* add -DMRB_INT16 to use 16bit integer for mrb_int; conflict with MRB_INT32 and MRB_INT64 */
|
||||
//#define MRB_INT16
|
||||
|
||||
/* add -DMRB_INT64 to use 64bit integer for mrb_int; conflict with MRB_INT16 */
|
||||
/* add -DMRB_INT32 to use 32bit integer for mrb_int; conflict with MRB_INT16 and MRB_INT64;
|
||||
Default for 32-bit CPU mode. */
|
||||
//#define MRB_INT32
|
||||
|
||||
/* add -DMRB_INT64 to use 64bit integer for mrb_int; conflict with MRB_INT16 and MRB_INT32;
|
||||
Default for 64-bit CPU mode. */
|
||||
//#define MRB_INT64
|
||||
|
||||
/* if no specific integer type is chosen */
|
||||
@@ -58,6 +62,9 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define MRB_COMPLEX_NUMBERS
|
||||
#define MRB_RATIONAL_NUMBERS
|
||||
|
||||
/* define on big endian machines; used by MRB_NAN_BOXING, etc. */
|
||||
#ifndef MRB_ENDIAN_BIG
|
||||
# if (defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN) || \
|
||||
@@ -81,12 +88,13 @@
|
||||
/* number of object per heap page */
|
||||
//#define MRB_HEAP_PAGE_SIZE 1024
|
||||
|
||||
/* if _etext and _edata available, mruby can reduce memory used by symbols */
|
||||
//#define MRB_USE_ETEXT_EDATA
|
||||
/* if __ehdr_start is available, mruby can reduce memory used by symbols */
|
||||
//#define MRB_USE_LINK_TIME_RO_DATA_P
|
||||
|
||||
/* do not use __init_array_start to determine readonly data section;
|
||||
effective only when MRB_USE_ETEXT_EDATA is defined */
|
||||
//#define MRB_NO_INIT_ARRAY_START
|
||||
/* if MRB_USE_LINK_TIME_RO_DATA_P does not work,
|
||||
you can try mrb_ro_data_p() that you have implemented yourself in any file;
|
||||
prototype is `mrb_bool mrb_ro_data_p(const char *ptr)` */
|
||||
//#define MRB_USE_CUSTOM_RO_DATA_P
|
||||
|
||||
/* turn off generational GC by default */
|
||||
//#define MRB_GC_TURN_OFF_GENERATIONAL
|
||||
@@ -146,4 +154,62 @@
|
||||
# define TRUE 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** mruby tuning profiles
|
||||
**/
|
||||
|
||||
/* A profile for micro controllers */
|
||||
#if defined(MRB_CONSTRAINED_BASELINE_PROFILE)
|
||||
# ifndef KHASH_DEFAULT_SIZE
|
||||
# define KHASH_DEFAULT_SIZE 16
|
||||
# endif
|
||||
|
||||
# ifndef MRB_STR_BUF_MIN_SIZE
|
||||
# define MRB_STR_BUF_MIN_SIZE 32
|
||||
# endif
|
||||
|
||||
# ifndef MRB_HEAP_PAGE_SIZE
|
||||
# define MRB_HEAP_PAGE_SIZE 256
|
||||
# endif
|
||||
|
||||
/* A profile for default mruby */
|
||||
#elif defined(MRB_BASELINE_PROFILE)
|
||||
|
||||
/* A profile for desktop computers or workstations; rich memory! */
|
||||
#elif defined(MRB_MAIN_PROFILE)
|
||||
# ifndef MRB_METHOD_CACHE
|
||||
# define MRB_METHOD_CACHE
|
||||
# endif
|
||||
|
||||
# ifndef MRB_METHOD_CACHE_SIZE
|
||||
# define MRB_METHOD_CACHE_SIZE (1<<10)
|
||||
# endif
|
||||
|
||||
# ifndef MRB_IV_SEGMENT_SIZE
|
||||
# define MRB_IV_SEGMENT_SIZE 32
|
||||
# endif
|
||||
|
||||
# ifndef MRB_HEAP_PAGE_SIZE
|
||||
# define MRB_HEAP_PAGE_SIZE 4096
|
||||
# endif
|
||||
|
||||
/* A profile for server; mruby vm is long life */
|
||||
#elif defined(MRB_HIGH_PROFILE)
|
||||
# ifndef MRB_METHOD_CACHE
|
||||
# define MRB_METHOD_CACHE
|
||||
# endif
|
||||
|
||||
# ifndef MRB_METHOD_CACHE_SIZE
|
||||
# define MRB_METHOD_CACHE_SIZE (1<<12)
|
||||
# endif
|
||||
|
||||
# ifndef MRB_IV_SEGMENT_SIZE
|
||||
# define MRB_IV_SEGMENT_SIZE 64
|
||||
# endif
|
||||
|
||||
# ifndef MRB_HEAP_PAGE_SIZE
|
||||
# define MRB_HEAP_PAGE_SIZE 4096
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* MRUBYCONF_H */
|
||||
|
||||
+242
-146
@@ -25,6 +25,10 @@
|
||||
** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file mruby.h
|
||||
*/
|
||||
|
||||
#ifndef MRUBY_H
|
||||
#define MRUBY_H
|
||||
|
||||
@@ -84,7 +88,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "mruby/common.h"
|
||||
#include <mruby/common.h>
|
||||
#include <mruby/value.h>
|
||||
#include <mruby/gc.h>
|
||||
#include <mruby/version.h>
|
||||
@@ -97,11 +101,14 @@ MRB_BEGIN_DECL
|
||||
typedef uint8_t mrb_code;
|
||||
|
||||
/**
|
||||
* Required arguments signature type.
|
||||
* \class mrb_aspec
|
||||
*
|
||||
* Specifies the number of arguments a function takes
|
||||
*
|
||||
* Example: `MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1)` for a method that expects 2..3 arguments
|
||||
*/
|
||||
typedef uint32_t mrb_aspec;
|
||||
|
||||
|
||||
struct mrb_irep;
|
||||
struct mrb_state;
|
||||
|
||||
@@ -127,8 +134,8 @@ typedef struct {
|
||||
uint16_t ridx;
|
||||
uint16_t epos;
|
||||
struct REnv *env;
|
||||
mrb_code *pc; /* return address */
|
||||
mrb_code *err; /* error position */
|
||||
const mrb_code *pc; /* return address */
|
||||
const mrb_code *err; /* error position */
|
||||
int argc;
|
||||
int acc;
|
||||
struct RClass *target_class;
|
||||
@@ -170,13 +177,22 @@ struct mrb_context {
|
||||
# define MRB_METHOD_CACHE_SIZE (1<<7)
|
||||
#endif
|
||||
|
||||
typedef mrb_value (*mrb_func_t)(struct mrb_state *mrb, mrb_value);
|
||||
/**
|
||||
* Function pointer type for a function callable by mruby.
|
||||
*
|
||||
* The arguments to the function are stored on the mrb_state. To get them see mrb_get_args
|
||||
*
|
||||
* @param mrb The mruby state
|
||||
* @param self The self object
|
||||
* @return [mrb_value] The function's return value
|
||||
*/
|
||||
typedef mrb_value (*mrb_func_t)(struct mrb_state *mrb, mrb_value self);
|
||||
|
||||
#ifdef MRB_METHOD_TABLE_INLINE
|
||||
#ifndef MRB_METHOD_T_STRUCT
|
||||
typedef uintptr_t mrb_method_t;
|
||||
#else
|
||||
typedef struct {
|
||||
mrb_bool func_p;
|
||||
uint8_t flags;
|
||||
union {
|
||||
struct RProc *proc;
|
||||
mrb_func_t func;
|
||||
@@ -196,13 +212,9 @@ struct mrb_jmpbuf;
|
||||
|
||||
typedef void (*mrb_atexit_func)(struct mrb_state*);
|
||||
|
||||
#define MRB_STATE_NO_REGEXP 1
|
||||
#define MRB_STATE_REGEXP 2
|
||||
|
||||
typedef struct mrb_state {
|
||||
struct mrb_jmpbuf *jmp;
|
||||
|
||||
uint32_t flags;
|
||||
mrb_allocf allocf; /* memory allocation function */
|
||||
void *allocf_ud; /* auxiliary data of allocf */
|
||||
|
||||
@@ -232,7 +244,6 @@ typedef struct mrb_state {
|
||||
struct RClass *symbol_class;
|
||||
struct RClass *kernel_module;
|
||||
|
||||
struct alloca_header *mems;
|
||||
mrb_gc gc;
|
||||
|
||||
#ifdef MRB_METHOD_CACHE
|
||||
@@ -248,8 +259,8 @@ typedef struct mrb_state {
|
||||
#endif
|
||||
|
||||
#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);
|
||||
void (*code_fetch_hook)(struct mrb_state* mrb, struct mrb_irep *irep, const mrb_code *pc, mrb_value *regs);
|
||||
void (*debug_op_hook)(struct mrb_state* mrb, struct mrb_irep *irep, const mrb_code *pc, mrb_value *regs);
|
||||
#endif
|
||||
|
||||
#ifdef MRB_BYTECODE_DECODE_OPTION
|
||||
@@ -290,9 +301,9 @@ typedef struct mrb_state {
|
||||
* //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.
|
||||
* @param mrb The current mruby state.
|
||||
* @param name The name of the defined class.
|
||||
* @param super The new class parent.
|
||||
* @return [struct RClass *] Reference to the newly defined class.
|
||||
* @see mrb_define_class_under
|
||||
*/
|
||||
@@ -301,12 +312,12 @@ MRB_API struct RClass *mrb_define_class(mrb_state *mrb, const char *name, struct
|
||||
/**
|
||||
* Defines a new module.
|
||||
*
|
||||
* @param [mrb_state *] mrb_state* The current mruby state.
|
||||
* @param [const char *] char* The name of the module.
|
||||
* @param mrb The current mruby state.
|
||||
* @param name 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);
|
||||
MRB_API struct RClass *mrb_define_module(mrb_state *mrb, const char *name);
|
||||
MRB_API mrb_value mrb_singleton_class(mrb_state *mrb, mrb_value val);
|
||||
|
||||
/**
|
||||
* Include a module in another class or module.
|
||||
@@ -315,11 +326,11 @@ MRB_API mrb_value mrb_singleton_class(mrb_state*, mrb_value);
|
||||
* 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.
|
||||
* @param mrb The current mruby state.
|
||||
* @param cla A reference to module or a class.
|
||||
* @param included A reference to the module to be included.
|
||||
*/
|
||||
MRB_API void mrb_include_module(mrb_state*, struct RClass*, struct RClass*);
|
||||
MRB_API void mrb_include_module(mrb_state *mrb, struct RClass *cla, struct RClass *included);
|
||||
|
||||
/**
|
||||
* Prepends a module in another class or module.
|
||||
@@ -328,11 +339,11 @@ MRB_API void mrb_include_module(mrb_state*, struct RClass*, struct RClass*);
|
||||
* 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.
|
||||
* @param mrb The current mruby state.
|
||||
* @param cla A reference to module or a class.
|
||||
* @param prepended A reference to the module to be prepended.
|
||||
*/
|
||||
MRB_API void mrb_prepend_module(mrb_state*, struct RClass*, struct RClass*);
|
||||
MRB_API void mrb_prepend_module(mrb_state *mrb, struct RClass *cla, struct RClass *prepended);
|
||||
|
||||
/**
|
||||
* Defines a global function in ruby.
|
||||
@@ -341,7 +352,6 @@ MRB_API void mrb_prepend_module(mrb_state*, struct RClass*, struct RClass*);
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* !!!c
|
||||
* mrb_value example_method(mrb_state* mrb, mrb_value self)
|
||||
* {
|
||||
* puts("Executing example command!");
|
||||
@@ -353,11 +363,11 @@ MRB_API void mrb_prepend_module(mrb_state*, struct RClass*, struct RClass*);
|
||||
* 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.
|
||||
* @param mrb The MRuby state reference.
|
||||
* @param cla The class pointer where the method will be defined.
|
||||
* @param name The name of the method being defined.
|
||||
* @param func The function pointer to the method definition.
|
||||
* @param 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);
|
||||
|
||||
@@ -380,14 +390,20 @@ MRB_API void mrb_define_method(mrb_state *mrb, struct RClass *cla, const char *n
|
||||
* 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.
|
||||
* @param mrb The MRuby state reference.
|
||||
* @param cla The class where the class method will be defined.
|
||||
* @param name The name of the class method being defined.
|
||||
* @param fun The function pointer to the class method definition.
|
||||
* @param 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);
|
||||
MRB_API void mrb_define_class_method(mrb_state *mrb, struct RClass *cla, const char *name, mrb_func_t fun, mrb_aspec aspec);
|
||||
|
||||
/**
|
||||
* Defines a singleton method
|
||||
*
|
||||
* @see mrb_define_class_method
|
||||
*/
|
||||
MRB_API void mrb_define_singleton_method(mrb_state *mrb, struct RObject *cla, const char *name, mrb_func_t fun, mrb_aspec aspec);
|
||||
|
||||
/**
|
||||
* Defines a module function.
|
||||
@@ -408,13 +424,13 @@ MRB_API void mrb_define_singleton_method(mrb_state*, struct RObject*, const char
|
||||
* 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.
|
||||
* @param mrb The MRuby state reference.
|
||||
* @param cla The module where the module function will be defined.
|
||||
* @param name The name of the module function being defined.
|
||||
* @param fun The function pointer to the module function definition.
|
||||
* @param aspec The method parameters declaration.
|
||||
*/
|
||||
MRB_API void mrb_define_module_function(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec);
|
||||
MRB_API void mrb_define_module_function(mrb_state *mrb, struct RClass *cla, const char *name, mrb_func_t fun, mrb_aspec aspec);
|
||||
|
||||
/**
|
||||
* Defines a constant.
|
||||
@@ -437,12 +453,12 @@ MRB_API void mrb_define_module_function(mrb_state*, struct RClass*, const char*,
|
||||
* 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.
|
||||
* @param mrb The MRuby state reference.
|
||||
* @param cla A class or module the constant is defined in.
|
||||
* @param name The name of the constant being defined.
|
||||
* @param val The value for the constant.
|
||||
*/
|
||||
MRB_API void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_value);
|
||||
MRB_API void mrb_define_const(mrb_state* mrb, struct RClass* cla, const char *name, mrb_value val);
|
||||
|
||||
/**
|
||||
* Undefines a method.
|
||||
@@ -488,11 +504,11 @@ MRB_API void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_
|
||||
*
|
||||
* 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*] const char* The name of the method to be undefined.
|
||||
* @param mrb The mruby state reference.
|
||||
* @param cla The class the method will be undefined from.
|
||||
* @param name The name of the method to be undefined.
|
||||
*/
|
||||
MRB_API void mrb_undef_method(mrb_state*, struct RClass*, const char*);
|
||||
MRB_API void mrb_undef_method(mrb_state *mrb, struct RClass *cla, const char *name);
|
||||
MRB_API void mrb_undef_method_id(mrb_state*, struct RClass*, mrb_sym);
|
||||
|
||||
/**
|
||||
@@ -528,11 +544,11 @@ MRB_API void mrb_undef_method_id(mrb_state*, struct RClass*, mrb_sym);
|
||||
* 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 [const char*] const char* The name of the class method to be undefined.
|
||||
* @param mrb The mruby state reference.
|
||||
* @param cls A class the class method will be undefined from.
|
||||
* @param name The name of the class method to be undefined.
|
||||
*/
|
||||
MRB_API void mrb_undef_class_method(mrb_state*, struct RClass*, const char*);
|
||||
MRB_API void mrb_undef_class_method(mrb_state *mrb, struct RClass *cls, const char *name);
|
||||
|
||||
/**
|
||||
* Initialize a new object instance of c class.
|
||||
@@ -556,10 +572,10 @@ MRB_API void mrb_undef_class_method(mrb_state*, struct RClass*, const char*);
|
||||
* 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
|
||||
* @param mrb The current mruby state.
|
||||
* @param c Reference to the class of the new object.
|
||||
* @param argc Number of arguments in argv
|
||||
* @param 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);
|
||||
@@ -570,8 +586,6 @@ MRB_INLINE mrb_value mrb_class_new_instance(mrb_state *mrb, mrb_int argc, const
|
||||
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.
|
||||
*
|
||||
@@ -587,8 +601,8 @@ MRB_API mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv);
|
||||
* mrb_p(mrb, obj); // => Kernel#p
|
||||
* }
|
||||
*
|
||||
* @param [mrb_state*] mrb The current mruby state.
|
||||
* @param [struct RClass *] super The super class or parent.
|
||||
* @param mrb The current mruby state.
|
||||
* @param 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);
|
||||
@@ -604,7 +618,7 @@ MRB_API struct RClass * mrb_class_new(mrb_state *mrb, struct RClass *super);
|
||||
* example_module = mrb_module_new(mrb);
|
||||
* }
|
||||
*
|
||||
* @param [mrb_state*] mrb The current mruby state.
|
||||
* @param mrb The current mruby state.
|
||||
* @return [struct RClass *] Reference to the new module.
|
||||
*/
|
||||
MRB_API struct RClass * mrb_module_new(mrb_state *mrb);
|
||||
@@ -631,24 +645,24 @@ MRB_API struct RClass * mrb_module_new(mrb_state *mrb);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @param [mrb_state*] mrb The current mruby state.
|
||||
* @param [const char *] name A string representing the name of the class.
|
||||
* @param mrb The current mruby state.
|
||||
* @param 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.
|
||||
* @param mrb The current mruby state.
|
||||
* @param 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 exception class.
|
||||
* @param [mrb_state*] mrb The current mruby state.
|
||||
* @param [const char *] name The name of the class.
|
||||
* @param mrb The current mruby state.
|
||||
* @param name The name of the class.
|
||||
* @return [struct RClass *] A reference to the class.
|
||||
*/
|
||||
MRB_API struct RClass * mrb_exc_get(mrb_state *mrb, const char *name);
|
||||
@@ -677,35 +691,35 @@ MRB_API struct RClass * mrb_exc_get(mrb_state *mrb, const char *name);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @param [mrb_state*] mrb The current mruby state.
|
||||
* @param [struct RClass *] outer The name of the outer class.
|
||||
* @param [const char *] name A string representing the name of the inner class.
|
||||
* @param mrb The current mruby state.
|
||||
* @param outer The name of the outer class.
|
||||
* @param name A string representing the name of the inner class.
|
||||
* @return [mrb_bool] A boolean value.
|
||||
*/
|
||||
MRB_API mrb_bool mrb_class_defined_under(mrb_state *mrb, struct RClass *outer, 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.
|
||||
* @param mrb The current mruby state.
|
||||
* @param outer The name of the parent class.
|
||||
* @param 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.
|
||||
* @param mrb The current mruby state.
|
||||
* @param 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.
|
||||
* @param mrb The current mruby state.
|
||||
* @param outer The name of the outer module.
|
||||
* @param 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);
|
||||
@@ -719,8 +733,8 @@ MRB_API mrb_value mrb_notimplement_m(mrb_state*, mrb_value);
|
||||
*
|
||||
* Equivalent to:
|
||||
* Object#dup
|
||||
* @param [mrb_state*] mrb The current mruby state.
|
||||
* @param [mrb_value] obj Object to be duplicate.
|
||||
* @param mrb The current mruby state.
|
||||
* @param 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);
|
||||
@@ -760,9 +774,9 @@ MRB_API mrb_value mrb_obj_dup(mrb_state *mrb, mrb_value obj);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @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.
|
||||
* @param mrb The current mruby state.
|
||||
* @param c A reference to a class.
|
||||
* @param 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);
|
||||
@@ -770,10 +784,10 @@ MRB_API mrb_bool mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mi
|
||||
/**
|
||||
* 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
|
||||
* @param mrb The current mruby state.
|
||||
* @param outer Reference to the module under which the new class will be defined
|
||||
* @param name The name of the defined class
|
||||
* @param super The new class parent
|
||||
* @return [struct RClass *] Reference to the newly defined class
|
||||
* @see mrb_define_class
|
||||
*/
|
||||
@@ -843,34 +857,93 @@ MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *o
|
||||
* | `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` |
|
||||
* | `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} | |
|
||||
* | `f` | {Fixnum}/{Float} | {mrb_float} | |
|
||||
* | `i` | {Fixnum}/{Float} | {mrb_int} | |
|
||||
* | `b` | boolean | {mrb_bool} | |
|
||||
* | `n` | {Symbol} | {mrb_sym} | |
|
||||
* | `n` | {String}/{Symbol} | {mrb_sym} | |
|
||||
* | `d` | data | void *, {mrb_data_type} const | 2nd argument will be used to check data type so it won't be modified; when `!` follows, the value may be `nil` |
|
||||
* | `I` | inline struct | void * | |
|
||||
* | `&` | block | {mrb_value} | &! raises exception if no block given. |
|
||||
* | `*` | rest arguments | {mrb_value} *, {mrb_int} | Receive the rest of arguments as an array; *! avoid copy of the stack. |
|
||||
* | | | optional | | After this spec following specs would be optional. |
|
||||
* | `*` | rest arguments | {mrb_value} *, {mrb_int} | Receive the rest of arguments as an array; `*!` avoid copy of the stack. |
|
||||
* | <code>\|</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. |
|
||||
* | `:` | keyword args | {mrb_kwargs} const | Get keyword arguments. @see mrb_kwargs |
|
||||
*
|
||||
* @see mrb_get_args
|
||||
*/
|
||||
typedef const char *mrb_args_format;
|
||||
|
||||
/**
|
||||
* Get keyword arguments by `mrb_get_args()` with `:` specifier.
|
||||
*
|
||||
* `mrb_kwargs::num` indicates that the number of keyword values.
|
||||
*
|
||||
* `mrb_kwargs::values` is an object array, and the keyword argument corresponding to the string array is assigned.
|
||||
* Note that `undef` is assigned if there is no keyword argument corresponding to `mrb_kwargs::optional`.
|
||||
*
|
||||
* `mrb_kwargs::table` accepts a string array.
|
||||
*
|
||||
* `mrb_kwargs::required` indicates that the specified number of keywords starting from the beginning of the string array are required.
|
||||
*
|
||||
* `mrb_kwargs::rest` is the remaining keyword argument that can be accepted as `**rest` in Ruby.
|
||||
* If `NULL` is specified, `ArgumentError` is raised when there is an undefined keyword.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* // def method(a: 1, b: 2)
|
||||
*
|
||||
* uint32_t kw_num = 2;
|
||||
* const char *kw_names[kw_num] = { "a", "b" };
|
||||
* uint32_t kw_required = 0;
|
||||
* mrb_value kw_values[kw_num];
|
||||
* const mrb_kwargs kwargs = { kw_num, kw_values, kw_names, kw_required, NULL };
|
||||
*
|
||||
* mrb_get_args(mrb, ":", &kwargs);
|
||||
* if (mrb_undef_p(kw_values[0])) { kw_values[0] = mrb_fixnum_value(1); }
|
||||
* if (mrb_undef_p(kw_values[1])) { kw_values[1] = mrb_fixnum_value(2); }
|
||||
*
|
||||
*
|
||||
* // def method(str, x:, y: 2, z: "default string", **opts)
|
||||
*
|
||||
* mrb_value str, kw_rest;
|
||||
* uint32_t kw_num = 3;
|
||||
* const char *kw_names[kw_num] = { "x", "y", "z" };
|
||||
* uint32_t kw_required = 1;
|
||||
* mrb_value kw_values[kw_num];
|
||||
* const mrb_kwargs kwargs = { kw_num, kw_values, kw_names, kw_required, &kw_rest };
|
||||
*
|
||||
* mrb_get_args(mrb, "S:", &str, &kwargs);
|
||||
* // or: mrb_get_args(mrb, ":S", &kwargs, &str);
|
||||
* if (mrb_undef_p(kw_values[1])) { kw_values[1] = mrb_fixnum_value(2); }
|
||||
* if (mrb_undef_p(kw_values[2])) { kw_values[2] = mrb_str_new_cstr(mrb, "default string"); }
|
||||
*/
|
||||
typedef struct mrb_kwargs mrb_kwargs;
|
||||
|
||||
struct mrb_kwargs
|
||||
{
|
||||
uint32_t num;
|
||||
mrb_value *values;
|
||||
const char *const *table;
|
||||
uint32_t required;
|
||||
mrb_value *rest;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve arguments from mrb_state.
|
||||
*
|
||||
* @param mrb The current MRuby state.
|
||||
* @param format [mrb_args_format] is a list of format specifiers
|
||||
* @param 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
|
||||
* @see mrb_kwargs
|
||||
*/
|
||||
MRB_API mrb_int mrb_get_args(mrb_state *mrb, mrb_args_format format, ...);
|
||||
|
||||
static inline mrb_sym
|
||||
MRB_INLINE mrb_sym
|
||||
mrb_get_mid(mrb_state *mrb) /* get method symbol */
|
||||
{
|
||||
return mrb->c->ci->mid;
|
||||
@@ -896,6 +969,8 @@ MRB_API mrb_value* mrb_get_argv(mrb_state *mrb);
|
||||
/**
|
||||
* Call existing ruby functions.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* #include <stdio.h>
|
||||
* #include <mruby.h>
|
||||
* #include "mruby/compile.h"
|
||||
@@ -912,15 +987,16 @@ MRB_API mrb_value* mrb_get_argv(mrb_state *mrb);
|
||||
* mrb_funcall(mrb, obj, "method_name", 1, mrb_fixnum_value(i));
|
||||
* fclose(fp);
|
||||
* mrb_close(mrb);
|
||||
* }
|
||||
* @param [mrb_state*] mrb_state* The current mruby state.
|
||||
* @param [mrb_value] mrb_value A reference to an mruby value.
|
||||
* @param [const char*] const char* The name of the method.
|
||||
* @param [mrb_int] mrb_int The number of arguments the method has.
|
||||
* @param [...] ... Variadic values(not type safe!).
|
||||
* @return [mrb_value] mrb_value mruby function value.
|
||||
* }
|
||||
*
|
||||
* @param mrb The current mruby state.
|
||||
* @param val A reference to an mruby value.
|
||||
* @param name The name of the method.
|
||||
* @param argc The number of arguments the method has.
|
||||
* @param ... Variadic values(not type safe!).
|
||||
* @return [mrb_value] mruby function value.
|
||||
*/
|
||||
MRB_API mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, mrb_int,...);
|
||||
MRB_API mrb_value mrb_funcall(mrb_state *mrb, mrb_value val, const char *name, mrb_int argc, ...);
|
||||
/**
|
||||
* Call existing ruby functions. This is basically the type safe version of mrb_funcall.
|
||||
*
|
||||
@@ -942,32 +1018,35 @@ MRB_API mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, mrb_int,...);
|
||||
* fclose(fp);
|
||||
* mrb_close(mrb);
|
||||
* }
|
||||
* @param [mrb_state*] mrb_state* The current mruby state.
|
||||
* @param [mrb_value] mrb_value A reference to an mruby value.
|
||||
* @param [mrb_sym] mrb_sym The symbol representing the method.
|
||||
* @param [mrb_int] mrb_int The number of arguments the method has.
|
||||
* @param [const mrb_value*] mrb_value* Pointer to the object.
|
||||
* @param mrb The current mruby state.
|
||||
* @param val A reference to an mruby value.
|
||||
* @param name_sym The symbol representing the method.
|
||||
* @param argc The number of arguments the method has.
|
||||
* @param obj Pointer to the object.
|
||||
* @return [mrb_value] mrb_value mruby function value.
|
||||
* @see mrb_funcall
|
||||
*/
|
||||
MRB_API mrb_value mrb_funcall_argv(mrb_state*, mrb_value, mrb_sym, mrb_int, const mrb_value*);
|
||||
MRB_API mrb_value mrb_funcall_argv(mrb_state *mrb, mrb_value val, mrb_sym name, mrb_int argc, const mrb_value *argv);
|
||||
/**
|
||||
* Call existing ruby functions with a block.
|
||||
*/
|
||||
MRB_API mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, mrb_sym, mrb_int, const mrb_value*, mrb_value);
|
||||
MRB_API mrb_value mrb_funcall_with_block(mrb_state *mrb, mrb_value val, mrb_sym name, mrb_int argc, const mrb_value *argv, mrb_value block);
|
||||
/**
|
||||
* Create a symbol
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* # Ruby style:
|
||||
* :pizza # => :pizza
|
||||
*
|
||||
* // C style:
|
||||
* mrb_sym m_sym = mrb_intern_lit(mrb, "pizza"); // => :pizza
|
||||
* @param [mrb_state*] mrb_state* The current mruby state.
|
||||
* @param [const char*] const char* The name of the method.
|
||||
*
|
||||
* @param mrb The current mruby state.
|
||||
* @param str The string to be symbolized
|
||||
* @return [mrb_sym] mrb_sym A symbol.
|
||||
*/
|
||||
MRB_API mrb_sym mrb_intern_cstr(mrb_state*,const char*);
|
||||
MRB_API mrb_sym mrb_intern_cstr(mrb_state *mrb, const char* str);
|
||||
MRB_API mrb_sym mrb_intern(mrb_state*,const char*,size_t);
|
||||
MRB_API mrb_sym mrb_intern_static(mrb_state*,const char*,size_t);
|
||||
#define mrb_intern_lit(mrb, lit) mrb_intern_static(mrb, lit, mrb_strlen_lit(lit))
|
||||
@@ -975,9 +1054,13 @@ MRB_API mrb_sym mrb_intern_str(mrb_state*,mrb_value);
|
||||
MRB_API mrb_value mrb_check_intern_cstr(mrb_state*,const char*);
|
||||
MRB_API mrb_value mrb_check_intern(mrb_state*,const char*,size_t);
|
||||
MRB_API mrb_value mrb_check_intern_str(mrb_state*,mrb_value);
|
||||
MRB_API const char *mrb_sym2name(mrb_state*,mrb_sym);
|
||||
MRB_API const char *mrb_sym2name_len(mrb_state*,mrb_sym,mrb_int*);
|
||||
MRB_API mrb_value mrb_sym2str(mrb_state*,mrb_sym);
|
||||
MRB_API const char *mrb_sym_name(mrb_state*,mrb_sym);
|
||||
MRB_API const char *mrb_sym_name_len(mrb_state*,mrb_sym,mrb_int*);
|
||||
MRB_API const char *mrb_sym_dump(mrb_state*,mrb_sym);
|
||||
MRB_API mrb_value mrb_sym_str(mrb_state*,mrb_sym);
|
||||
#define mrb_sym2name(mrb,sym) mrb_sym_name(mrb,sym)
|
||||
#define mrb_sym2name_len(mrb,sym,len) mrb_sym_name_len(mrb,sym,len)
|
||||
#define mrb_sym2str(mrb,sym) mrb_sym_str(mrb,sym)
|
||||
|
||||
MRB_API void *mrb_malloc(mrb_state*, size_t); /* raise RuntimeError if no mem */
|
||||
MRB_API void *mrb_calloc(mrb_state*, size_t, size_t); /* ditto */
|
||||
@@ -996,6 +1079,12 @@ 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))
|
||||
|
||||
MRB_API mrb_value mrb_obj_freeze(mrb_state*, mrb_value);
|
||||
#define mrb_str_new_frozen(mrb,p,len) mrb_obj_freeze(mrb,mrb_str_new(mrb,p,len))
|
||||
#define mrb_str_new_cstr_frozen(mrb,p) mrb_obj_freeze(mrb,mrb_str_new_cstr(mrb,p))
|
||||
#define mrb_str_new_static_frozen(mrb,p,len) mrb_obj_freeze(mrb,mrb_str_new_static(mrb,p,len))
|
||||
#define mrb_str_new_lit_frozen(mrb,lit) mrb_obj_freeze(mrb,mrb_str_new_lit(mrb,lit))
|
||||
|
||||
#ifdef _WIN32
|
||||
MRB_API char* mrb_utf8_from_locale(const char *p, int len);
|
||||
MRB_API char* mrb_locale_from_utf8(const char *p, int len);
|
||||
@@ -1058,11 +1147,11 @@ MRB_API void mrb_close(mrb_state *mrb);
|
||||
*/
|
||||
MRB_API void* mrb_default_allocf(mrb_state*, void*, size_t, void*);
|
||||
|
||||
MRB_API mrb_value mrb_top_self(mrb_state *);
|
||||
MRB_API mrb_value mrb_run(mrb_state*, struct RProc*, mrb_value);
|
||||
MRB_API mrb_value mrb_top_run(mrb_state*, struct RProc*, mrb_value, unsigned int);
|
||||
MRB_API mrb_value mrb_vm_run(mrb_state*, struct RProc*, mrb_value, unsigned int);
|
||||
MRB_API mrb_value mrb_vm_exec(mrb_state*, struct RProc*, mrb_code*);
|
||||
MRB_API mrb_value mrb_top_self(mrb_state *mrb);
|
||||
MRB_API mrb_value mrb_run(mrb_state *mrb, struct RProc* proc, mrb_value self);
|
||||
MRB_API mrb_value mrb_top_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep);
|
||||
MRB_API mrb_value mrb_vm_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep);
|
||||
MRB_API mrb_value mrb_vm_exec(mrb_state *mrb, struct RProc *proc, const mrb_code *iseq);
|
||||
/* compatibility macros */
|
||||
#define mrb_toplevel_run_keep(m,p,k) mrb_top_run((m),(p),mrb_top_self(m),(k))
|
||||
#define mrb_toplevel_run(m,p) mrb_toplevel_run_keep((m),(p),0)
|
||||
@@ -1072,8 +1161,8 @@ MRB_API void mrb_p(mrb_state*, mrb_value);
|
||||
MRB_API mrb_int mrb_obj_id(mrb_value obj);
|
||||
MRB_API mrb_sym mrb_obj_to_sym(mrb_state *mrb, mrb_value name);
|
||||
|
||||
MRB_API mrb_bool mrb_obj_eq(mrb_state*, mrb_value, mrb_value);
|
||||
MRB_API mrb_bool mrb_obj_equal(mrb_state*, mrb_value, mrb_value);
|
||||
MRB_API mrb_bool mrb_obj_eq(mrb_state *mrb, mrb_value a, mrb_value b);
|
||||
MRB_API mrb_bool mrb_obj_equal(mrb_state *mrb, mrb_value a, mrb_value b);
|
||||
MRB_API mrb_bool mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2);
|
||||
MRB_API mrb_value mrb_convert_to_integer(mrb_state *mrb, mrb_value val, mrb_int base);
|
||||
MRB_API mrb_value mrb_Integer(mrb_state *mrb, mrb_value val);
|
||||
@@ -1082,17 +1171,16 @@ MRB_API mrb_value mrb_Float(mrb_state *mrb, mrb_value val);
|
||||
#endif
|
||||
MRB_API mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj);
|
||||
MRB_API mrb_bool mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2);
|
||||
/* mrb_cmp(mrb, obj1, obj2): 1:0:-1; -2 for error */
|
||||
MRB_API mrb_int mrb_cmp(mrb_state *mrb, mrb_value obj1, mrb_value obj2);
|
||||
|
||||
static inline int mrb_gc_arena_save(mrb_state*);
|
||||
static inline void mrb_gc_arena_restore(mrb_state*,int);
|
||||
|
||||
static inline int
|
||||
MRB_INLINE int
|
||||
mrb_gc_arena_save(mrb_state *mrb)
|
||||
{
|
||||
return mrb->gc.arena_idx;
|
||||
}
|
||||
|
||||
static inline void
|
||||
MRB_INLINE void
|
||||
mrb_gc_arena_restore(mrb_state *mrb, int idx)
|
||||
{
|
||||
mrb->gc.arena_idx = idx;
|
||||
@@ -1143,6 +1231,7 @@ MRB_API mrb_noreturn void mrb_exc_raise(mrb_state *mrb, mrb_value exc);
|
||||
MRB_API mrb_noreturn void mrb_raise(mrb_state *mrb, struct RClass *c, const char *msg);
|
||||
MRB_API mrb_noreturn void mrb_raisef(mrb_state *mrb, struct RClass *c, const char *fmt, ...);
|
||||
MRB_API mrb_noreturn void mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...);
|
||||
MRB_API mrb_noreturn void mrb_frozen_error(mrb_state *mrb, void *frozen_obj);
|
||||
MRB_API void mrb_warn(mrb_state *mrb, const char *fmt, ...);
|
||||
MRB_API mrb_noreturn void mrb_bug(mrb_state *mrb, const char *fmt, ...);
|
||||
MRB_API void mrb_print_backtrace(mrb_state *mrb);
|
||||
@@ -1193,9 +1282,15 @@ 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))
|
||||
/* string type checking (contrary to the name, it doesn't convert) */
|
||||
MRB_API mrb_value mrb_to_str(mrb_state *mrb, mrb_value val);
|
||||
MRB_API void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t);
|
||||
|
||||
MRB_INLINE void mrb_check_frozen(mrb_state *mrb, void *o)
|
||||
{
|
||||
if (mrb_frozen_p((struct RBasic*)o)) mrb_frozen_error(mrb, o);
|
||||
}
|
||||
|
||||
typedef enum call_type {
|
||||
CALL_PUBLIC,
|
||||
CALL_FCALL,
|
||||
@@ -1214,31 +1309,31 @@ MRB_API mrb_bool mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RC
|
||||
MRB_API mrb_bool mrb_func_basic_p(mrb_state *mrb, mrb_value obj, mrb_sym mid, mrb_func_t func);
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
* Resume a Fiber
|
||||
*
|
||||
* @mrbgem mruby-fiber
|
||||
* Implemented in 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
|
||||
* Implemented in mruby-fiber
|
||||
*/
|
||||
MRB_API mrb_value mrb_fiber_yield(mrb_state *mrb, mrb_int argc, const mrb_value *argv);
|
||||
|
||||
/*
|
||||
/**
|
||||
* Check if a Fiber is alive
|
||||
*
|
||||
* @mrbgem mruby-fiber
|
||||
* Implemented in mruby-fiber
|
||||
*/
|
||||
MRB_API mrb_value mrb_fiber_alive_p(mrb_state *mrb, mrb_value fib);
|
||||
|
||||
/*
|
||||
/**
|
||||
* FiberError reference
|
||||
*
|
||||
* @mrbgem mruby-fiber
|
||||
* Implemented in mruby-fiber
|
||||
*/
|
||||
#define E_FIBER_ERROR (mrb_exc_get(mrb, "FiberError"))
|
||||
MRB_API void mrb_stack_extend(mrb_state*, mrb_int);
|
||||
@@ -1250,6 +1345,7 @@ MRB_API void mrb_pool_close(struct mrb_pool*);
|
||||
MRB_API void* mrb_pool_alloc(struct mrb_pool*, size_t);
|
||||
MRB_API void* mrb_pool_realloc(struct mrb_pool*, void*, size_t oldlen, size_t newlen);
|
||||
MRB_API mrb_bool mrb_pool_can_realloc(struct mrb_pool*, void*, size_t);
|
||||
/* temporary memory allocation, only effective while GC arena is kept */
|
||||
MRB_API void* mrb_alloca(mrb_state *mrb, size_t);
|
||||
|
||||
MRB_API void mrb_state_atexit(mrb_state *mrb, mrb_atexit_func func);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/array.h - Array class
|
||||
/**
|
||||
** @file mruby/array.h - Array class
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -33,7 +33,7 @@ struct RArray {
|
||||
} aux;
|
||||
mrb_value *ptr;
|
||||
} heap;
|
||||
mrb_value embed[MRB_ARY_EMBED_LEN_MAX];
|
||||
void *ary[3];
|
||||
} as;
|
||||
};
|
||||
|
||||
@@ -46,7 +46,7 @@ struct RArray {
|
||||
#define ARY_UNSET_EMBED_FLAG(a) ((a)->flags &= ~(MRB_ARY_EMBED_MASK))
|
||||
#define ARY_EMBED_LEN(a) ((mrb_int)(((a)->flags & MRB_ARY_EMBED_MASK) - 1))
|
||||
#define ARY_SET_EMBED_LEN(a,len) ((a)->flags = ((a)->flags&~MRB_ARY_EMBED_MASK) | ((uint32_t)(len) + 1))
|
||||
#define ARY_EMBED_PTR(a) (&((a)->as.embed[0]))
|
||||
#define ARY_EMBED_PTR(a) ((mrb_value*)(&(a)->as.ary))
|
||||
|
||||
#define ARY_LEN(a) (ARY_EMBED_P(a)?ARY_EMBED_LEN(a):(a)->as.heap.len)
|
||||
#define ARY_PTR(a) (ARY_EMBED_P(a)?ARY_EMBED_PTR(a):(a)->as.heap.ptr)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/boxing_nan.h - nan boxing mrb_value definition
|
||||
/**
|
||||
** @file mruby/boxing_nan.h - nan boxing mrb_value definition
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -20,13 +20,6 @@
|
||||
#endif
|
||||
|
||||
#define MRB_FIXNUM_SHIFT 0
|
||||
#define MRB_TT_HAS_BASIC MRB_TT_OBJECT
|
||||
|
||||
#ifdef MRB_ENDIAN_BIG
|
||||
#define MRB_ENDIAN_LOHI(a,b) a b
|
||||
#else
|
||||
#define MRB_ENDIAN_LOHI(a,b) b a
|
||||
#endif
|
||||
|
||||
/* value representation by nan-boxing:
|
||||
* float : FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
|
||||
|
||||
+12
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/boxing_no.h - unboxed mrb_value definition
|
||||
/**
|
||||
** @file mruby/boxing_no.h - unboxed mrb_value definition
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -8,17 +8,18 @@
|
||||
#define MRUBY_BOXING_NO_H
|
||||
|
||||
#define MRB_FIXNUM_SHIFT 0
|
||||
#define MRB_TT_HAS_BASIC MRB_TT_OBJECT
|
||||
|
||||
union mrb_value_union {
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
mrb_float f;
|
||||
#endif
|
||||
void *p;
|
||||
mrb_int i;
|
||||
mrb_sym sym;
|
||||
};
|
||||
|
||||
typedef struct mrb_value {
|
||||
union {
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
mrb_float f;
|
||||
#endif
|
||||
void *p;
|
||||
mrb_int i;
|
||||
mrb_sym sym;
|
||||
} value;
|
||||
union mrb_value_union value;
|
||||
enum mrb_vtype tt;
|
||||
} mrb_value;
|
||||
|
||||
|
||||
+103
-68
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/boxing_word.h - word boxing mrb_value definition
|
||||
/**
|
||||
** @file mruby/boxing_word.h - word boxing mrb_value definition
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -27,43 +27,61 @@ struct RCptr {
|
||||
void *p;
|
||||
};
|
||||
|
||||
#define MRB_FIXNUM_SHIFT 1
|
||||
#ifdef MRB_WITHOUT_FLOAT
|
||||
#define MRB_TT_HAS_BASIC MRB_TT_CPTR
|
||||
#else
|
||||
#define MRB_TT_HAS_BASIC MRB_TT_FLOAT
|
||||
#endif
|
||||
|
||||
enum mrb_special_consts {
|
||||
MRB_Qnil = 0,
|
||||
MRB_Qfalse = 2,
|
||||
MRB_Qtrue = 4,
|
||||
MRB_Qundef = 6,
|
||||
MRB_Qnil = 0,
|
||||
MRB_Qfalse = 4,
|
||||
MRB_Qtrue = 12,
|
||||
MRB_Qundef = 20,
|
||||
};
|
||||
|
||||
#define MRB_FIXNUM_FLAG 0x01
|
||||
#define MRB_SYMBOL_FLAG 0x0e
|
||||
#define MRB_SPECIAL_SHIFT 8
|
||||
#define MRB_FIXNUM_SHIFT 1
|
||||
#define MRB_SYMBOL_SHIFT 2
|
||||
#define MRB_FIXNUM_FLAG (1 << (MRB_FIXNUM_SHIFT - 1))
|
||||
#define MRB_SYMBOL_FLAG (1 << (MRB_SYMBOL_SHIFT - 1))
|
||||
#define MRB_FIXNUM_MASK ((1 << MRB_FIXNUM_SHIFT) - 1)
|
||||
#define MRB_SYMBOL_MASK ((1 << MRB_SYMBOL_SHIFT) - 1)
|
||||
#define MRB_IMMEDIATE_MASK 0x07
|
||||
|
||||
#if defined(MRB_64BIT)
|
||||
#ifdef MRB_64BIT
|
||||
#define MRB_SYMBOL_BITSIZE (sizeof(mrb_sym) * CHAR_BIT)
|
||||
#define MRB_SYMBOL_MAX UINT32_MAX
|
||||
#else
|
||||
#define MRB_SYMBOL_BITSIZE (sizeof(mrb_sym) * CHAR_BIT - MRB_SPECIAL_SHIFT)
|
||||
#define MRB_SYMBOL_MAX (UINT32_MAX >> MRB_SPECIAL_SHIFT)
|
||||
#define MRB_SYMBOL_BITSIZE (sizeof(mrb_sym) * CHAR_BIT - MRB_SYMBOL_SHIFT)
|
||||
#define MRB_SYMBOL_MAX (UINT32_MAX >> MRB_SYMBOL_SHIFT)
|
||||
#endif
|
||||
|
||||
#define BOXWORD_SHIFT_VALUE(o,n,t) \
|
||||
((((t)(o).w)) >> MRB_##n##_SHIFT)
|
||||
#define BOXWORD_SET_SHIFT_VALUE(o,n,v) \
|
||||
((o).w = (((unsigned long)(v)) << MRB_##n##_SHIFT) | MRB_##n##_FLAG)
|
||||
#define BOXWORD_SHIFT_VALUE_P(o,n) \
|
||||
(((o).w & MRB_##n##_MASK) == MRB_##n##_FLAG)
|
||||
#define BOXWORD_OBJ_TYPE_P(o,n) \
|
||||
(!mrb_immediate_p(o) && (o).value.bp->tt == MRB_TT_##n)
|
||||
|
||||
/*
|
||||
* mrb_value representation:
|
||||
*
|
||||
* nil : ...0000 0000 (all bits are zero)
|
||||
* false : ...0000 0100
|
||||
* true : ...0000 1100
|
||||
* undef : ...0001 0100
|
||||
* fixnum: ...IIII III1
|
||||
* symbol: ...SSSS SS10 (high-order 32-bit are symbol value in 64-bit mode)
|
||||
* object: ...PPPP P000
|
||||
*/
|
||||
typedef union mrb_value {
|
||||
union {
|
||||
void *p;
|
||||
#ifdef MRB_64BIT
|
||||
/* use struct to avoid bit shift. */
|
||||
struct {
|
||||
unsigned int i_flag : MRB_FIXNUM_SHIFT;
|
||||
mrb_int i : (MRB_INT_BIT - MRB_FIXNUM_SHIFT);
|
||||
};
|
||||
struct {
|
||||
unsigned int sym_flag : MRB_SPECIAL_SHIFT;
|
||||
mrb_sym sym : MRB_SYMBOL_BITSIZE;
|
||||
MRB_ENDIAN_LOHI(
|
||||
mrb_sym sym;
|
||||
,uint32_t sym_flag;
|
||||
)
|
||||
};
|
||||
#endif
|
||||
struct RBasic *bp;
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
struct RFloat *fp;
|
||||
@@ -88,57 +106,74 @@ MRB_API mrb_value mrb_word_boxing_float_pool(struct mrb_state*, mrb_float);
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
#define mrb_float(o) (o).value.fp->f
|
||||
#endif
|
||||
#define mrb_fixnum(o) ((mrb_int)(o).value.i)
|
||||
#define mrb_fixnum(o) BOXWORD_SHIFT_VALUE(o, FIXNUM, mrb_int)
|
||||
#ifdef MRB_64BIT
|
||||
#define mrb_symbol(o) (o).value.sym
|
||||
#else
|
||||
#define mrb_symbol(o) BOXWORD_SHIFT_VALUE(o, SYMBOL, mrb_sym)
|
||||
#endif
|
||||
#define mrb_bool(o) (((o).w & ~(unsigned long)MRB_Qfalse) != 0)
|
||||
|
||||
static inline enum mrb_vtype
|
||||
mrb_type(mrb_value o)
|
||||
{
|
||||
switch (o.w) {
|
||||
case MRB_Qfalse:
|
||||
case MRB_Qnil:
|
||||
return MRB_TT_FALSE;
|
||||
case MRB_Qtrue:
|
||||
return MRB_TT_TRUE;
|
||||
case MRB_Qundef:
|
||||
return MRB_TT_UNDEF;
|
||||
}
|
||||
if (o.value.i_flag == MRB_FIXNUM_FLAG) {
|
||||
return MRB_TT_FIXNUM;
|
||||
}
|
||||
if (o.value.sym_flag == MRB_SYMBOL_FLAG) {
|
||||
return MRB_TT_SYMBOL;
|
||||
}
|
||||
return o.value.bp->tt;
|
||||
}
|
||||
|
||||
#define mrb_bool(o) ((o).w != MRB_Qnil && (o).w != MRB_Qfalse)
|
||||
#define mrb_fixnum_p(o) ((o).value.i_flag == MRB_FIXNUM_FLAG)
|
||||
#define mrb_immediate_p(o) ((o).w & MRB_IMMEDIATE_MASK || (o).w == MRB_Qnil)
|
||||
#define mrb_fixnum_p(o) BOXWORD_SHIFT_VALUE_P(o, FIXNUM)
|
||||
#ifdef MRB_64BIT
|
||||
#define mrb_symbol_p(o) ((o).value.sym_flag == MRB_SYMBOL_FLAG)
|
||||
#else
|
||||
#define mrb_symbol_p(o) BOXWORD_SHIFT_VALUE_P(o, SYMBOL)
|
||||
#endif
|
||||
#define mrb_undef_p(o) ((o).w == MRB_Qundef)
|
||||
#define mrb_nil_p(o) ((o).w == MRB_Qnil)
|
||||
|
||||
#define BOXWORD_SET_VALUE(o, ttt, attr, v) do { \
|
||||
switch (ttt) {\
|
||||
case MRB_TT_FALSE: (o).w = (v) ? MRB_Qfalse : MRB_Qnil; break;\
|
||||
case MRB_TT_TRUE: (o).w = MRB_Qtrue; break;\
|
||||
case MRB_TT_UNDEF: (o).w = MRB_Qundef; break;\
|
||||
case MRB_TT_FIXNUM: (o).w = 0;(o).value.i_flag = MRB_FIXNUM_FLAG; (o).attr = (v); break;\
|
||||
case MRB_TT_SYMBOL: (o).w = 0;(o).value.sym_flag = MRB_SYMBOL_FLAG; (o).attr = (v); break;\
|
||||
default: (o).w = 0; (o).attr = (v); if ((o).value.bp) (o).value.bp->tt = ttt; break;\
|
||||
}\
|
||||
} while (0)
|
||||
#define mrb_false_p(o) ((o).w == MRB_Qfalse)
|
||||
#define mrb_true_p(o) ((o).w == MRB_Qtrue)
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
#define mrb_float_p(o) BOXWORD_OBJ_TYPE_P(o, FLOAT)
|
||||
#endif
|
||||
#define mrb_array_p(o) BOXWORD_OBJ_TYPE_P(o, ARRAY)
|
||||
#define mrb_string_p(o) BOXWORD_OBJ_TYPE_P(o, STRING)
|
||||
#define mrb_hash_p(o) BOXWORD_OBJ_TYPE_P(o, HASH)
|
||||
#define mrb_cptr_p(o) BOXWORD_OBJ_TYPE_P(o, CPTR)
|
||||
#define mrb_exception_p(o) BOXWORD_OBJ_TYPE_P(o, EXCEPTION)
|
||||
#define mrb_free_p(o) BOXWORD_OBJ_TYPE_P(o, FREE)
|
||||
#define mrb_object_p(o) BOXWORD_OBJ_TYPE_P(o, OBJECT)
|
||||
#define mrb_class_p(o) BOXWORD_OBJ_TYPE_P(o, CLASS)
|
||||
#define mrb_module_p(o) BOXWORD_OBJ_TYPE_P(o, MODULE)
|
||||
#define mrb_iclass_p(o) BOXWORD_OBJ_TYPE_P(o, ICLASS)
|
||||
#define mrb_sclass_p(o) BOXWORD_OBJ_TYPE_P(o, SCLASS)
|
||||
#define mrb_proc_p(o) BOXWORD_OBJ_TYPE_P(o, PROC)
|
||||
#define mrb_range_p(o) BOXWORD_OBJ_TYPE_P(o, RANGE)
|
||||
#define mrb_file_p(o) BOXWORD_OBJ_TYPE_P(o, FILE)
|
||||
#define mrb_env_p(o) BOXWORD_OBJ_TYPE_P(o, ENV)
|
||||
#define mrb_data_p(o) BOXWORD_OBJ_TYPE_P(o, DATA)
|
||||
#define mrb_fiber_p(o) BOXWORD_OBJ_TYPE_P(o, FIBER)
|
||||
#define mrb_istruct_p(o) BOXWORD_OBJ_TYPE_P(o, ISTRUCT)
|
||||
#define mrb_break_p(o) BOXWORD_OBJ_TYPE_P(o, BREAK)
|
||||
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
#define SET_FLOAT_VALUE(mrb,r,v) ((r) = mrb_word_boxing_float_value(mrb, v))
|
||||
#endif
|
||||
#define SET_CPTR_VALUE(mrb,r,v) ((r) = mrb_word_boxing_cptr_value(mrb, v))
|
||||
#define SET_NIL_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_FALSE, value.i, 0)
|
||||
#define SET_FALSE_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_FALSE, value.i, 1)
|
||||
#define SET_TRUE_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_TRUE, value.i, 1)
|
||||
#define SET_BOOL_VALUE(r,b) BOXWORD_SET_VALUE(r, (b) ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1)
|
||||
#define SET_INT_VALUE(r,n) BOXWORD_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n))
|
||||
#define SET_SYM_VALUE(r,v) BOXWORD_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v))
|
||||
#define SET_OBJ_VALUE(r,v) BOXWORD_SET_VALUE(r, (((struct RObject*)(v))->tt), value.p, (v))
|
||||
#define SET_UNDEF_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0)
|
||||
#define SET_UNDEF_VALUE(r) ((r).w = MRB_Qundef)
|
||||
#define SET_NIL_VALUE(r) ((r).w = MRB_Qnil)
|
||||
#define SET_FALSE_VALUE(r) ((r).w = MRB_Qfalse)
|
||||
#define SET_TRUE_VALUE(r) ((r).w = MRB_Qtrue)
|
||||
#define SET_BOOL_VALUE(r,b) ((b) ? SET_TRUE_VALUE(r) : SET_FALSE_VALUE(r))
|
||||
#define SET_INT_VALUE(r,n) BOXWORD_SET_SHIFT_VALUE(r, FIXNUM, n)
|
||||
#ifdef MRB_64BIT
|
||||
#define SET_SYM_VALUE(r,v) ((r).value.sym = v, (r).value.sym_flag = MRB_SYMBOL_FLAG)
|
||||
#else
|
||||
#define SET_SYM_VALUE(r,n) BOXWORD_SET_SHIFT_VALUE(r, SYMBOL, n)
|
||||
#endif
|
||||
#define SET_OBJ_VALUE(r,v) ((r).value.p = v)
|
||||
|
||||
MRB_INLINE enum mrb_vtype
|
||||
mrb_type(mrb_value o)
|
||||
{
|
||||
return !mrb_bool(o) ? MRB_TT_FALSE :
|
||||
mrb_true_p(o) ? MRB_TT_TRUE :
|
||||
mrb_fixnum_p(o) ? MRB_TT_FIXNUM :
|
||||
mrb_symbol_p(o) ? MRB_TT_SYMBOL :
|
||||
mrb_undef_p(o) ? MRB_TT_UNDEF :
|
||||
o.value.bp->tt;
|
||||
}
|
||||
|
||||
#endif /* MRUBY_BOXING_WORD_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/class.h - Class class
|
||||
/**
|
||||
** @file mruby/class.h - Class class
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -23,7 +23,7 @@ struct RClass {
|
||||
|
||||
#define mrb_class_ptr(v) ((struct RClass*)(mrb_ptr(v)))
|
||||
|
||||
static inline struct RClass*
|
||||
MRB_INLINE struct RClass*
|
||||
mrb_class(mrb_state *mrb, mrb_value v)
|
||||
{
|
||||
switch (mrb_type(v)) {
|
||||
@@ -75,8 +75,8 @@ mrb_class(mrb_state *mrb, mrb_value v)
|
||||
|
||||
MRB_API struct RClass* mrb_define_class_id(mrb_state*, mrb_sym, struct RClass*);
|
||||
MRB_API struct RClass* mrb_define_module_id(mrb_state*, mrb_sym);
|
||||
MRB_API struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym);
|
||||
MRB_API struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym);
|
||||
struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym);
|
||||
struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym);
|
||||
MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, mrb_method_t);
|
||||
MRB_API void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec);
|
||||
MRB_API void mrb_alias_method(mrb_state*, struct RClass *c, mrb_sym a, mrb_sym b);
|
||||
@@ -85,8 +85,10 @@ MRB_API mrb_method_t mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym);
|
||||
MRB_API mrb_method_t mrb_method_search(mrb_state*, struct RClass*, mrb_sym);
|
||||
|
||||
MRB_API struct RClass* mrb_class_real(struct RClass* cl);
|
||||
mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv);
|
||||
|
||||
void mrb_class_name_class(mrb_state*, struct RClass*, struct RClass*, mrb_sym);
|
||||
mrb_bool mrb_const_name_p(mrb_state*, const char*, mrb_int);
|
||||
mrb_value mrb_class_find_path(mrb_state*, struct RClass*);
|
||||
void mrb_gc_mark_mt(mrb_state*, struct RClass*);
|
||||
size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
**"common.h - mruby common platform definition"
|
||||
/**
|
||||
** @file common.h - mruby common platform definition"
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -54,14 +54,15 @@ MRB_BEGIN_DECL
|
||||
#endif
|
||||
|
||||
/** Declare a function as always inlined. */
|
||||
#if defined(_MSC_VER)
|
||||
# define MRB_INLINE static __inline
|
||||
#else
|
||||
# define MRB_INLINE static inline
|
||||
#if defined _MSC_VER && _MSC_VER < 1900
|
||||
# ifndef __cplusplus
|
||||
# define inline __inline
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define MRB_INLINE static inline
|
||||
|
||||
/** Declare a public MRuby API function. */
|
||||
#ifndef MRB_API
|
||||
#if defined(MRB_BUILD_AS_DLL)
|
||||
#if defined(MRB_CORE) || defined(MRB_LIB)
|
||||
# define MRB_API __declspec(dllexport)
|
||||
@@ -71,6 +72,7 @@ MRB_BEGIN_DECL
|
||||
#else
|
||||
# define MRB_API extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/compile.h - mruby parser
|
||||
/**
|
||||
** @file mruby/compile.h - mruby parser
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -24,7 +24,7 @@ typedef struct mrbc_context {
|
||||
mrb_sym *syms;
|
||||
int slen;
|
||||
char *filename;
|
||||
short lineno;
|
||||
uint16_t lineno;
|
||||
int (*partial_hook)(struct mrb_parser_state*);
|
||||
void *partial_data;
|
||||
struct RClass *target_class;
|
||||
@@ -67,7 +67,7 @@ enum mrb_lex_state_enum {
|
||||
|
||||
/* saved error message */
|
||||
struct mrb_parser_message {
|
||||
int lineno;
|
||||
uint16_t lineno;
|
||||
int column;
|
||||
char* message;
|
||||
};
|
||||
@@ -105,7 +105,7 @@ struct mrb_parser_heredoc_info {
|
||||
mrb_ast_node *doc;
|
||||
};
|
||||
|
||||
#define MRB_PARSER_TOKBUF_MAX 65536
|
||||
#define MRB_PARSER_TOKBUF_MAX (UINT16_MAX-1)
|
||||
#define MRB_PARSER_TOKBUF_SIZE 256
|
||||
|
||||
/* parser structure */
|
||||
@@ -119,7 +119,7 @@ struct mrb_parser_state {
|
||||
#endif
|
||||
mrbc_context *cxt;
|
||||
mrb_sym filename_sym;
|
||||
int lineno;
|
||||
uint16_t lineno;
|
||||
int column;
|
||||
|
||||
enum mrb_lex_state_enum lstate;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/data.h - Data class
|
||||
/**
|
||||
** @file mruby/data.h - Data class
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -41,7 +41,7 @@ MRB_API struct RData *mrb_data_object_alloc(mrb_state *mrb, struct RClass* klass
|
||||
|
||||
#define Data_Make_Struct(mrb,klass,strct,type,sval,data_obj) do { \
|
||||
(data_obj) = Data_Wrap_Struct(mrb,klass,type,NULL);\
|
||||
(sval) = mrb_malloc(mrb, sizeof(strct)); \
|
||||
(sval) = (strct *)mrb_malloc(mrb, sizeof(strct)); \
|
||||
{ static const strct zero = { 0 }; *(sval) = zero; };\
|
||||
(data_obj)->data = (sval);\
|
||||
} while (0)
|
||||
@@ -63,10 +63,10 @@ MRB_API void *mrb_data_check_get_ptr(mrb_state *mrb, mrb_value, const mrb_data_t
|
||||
*(void**)&sval = mrb_data_get_ptr(mrb, obj, type); \
|
||||
} while (0)
|
||||
|
||||
static inline void
|
||||
MRB_INLINE void
|
||||
mrb_data_init(mrb_value v, void *ptr, const mrb_data_type *type)
|
||||
{
|
||||
mrb_assert(mrb_type(v) == MRB_TT_DATA);
|
||||
mrb_assert(mrb_data_p(v));
|
||||
DATA_PTR(v) = ptr;
|
||||
DATA_TYPE(v) = type;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/debug.h - mruby debug info
|
||||
/**
|
||||
** @file mruby/debug.h - mruby debug info
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/dump.h - mruby binary dumper (mrbc binary format)
|
||||
/**
|
||||
** @file mruby/dump.h - mruby binary dumper (mrbc binary format)
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -31,6 +31,7 @@ MRB_API mrb_value mrb_load_irep_file(mrb_state*,FILE*);
|
||||
MRB_API mrb_value mrb_load_irep_file_cxt(mrb_state*, FILE*, mrbc_context*);
|
||||
#endif
|
||||
MRB_API mrb_irep *mrb_read_irep(mrb_state*, const uint8_t*);
|
||||
MRB_API mrb_irep *mrb_read_irep_buf(mrb_state*, const void*, size_t);
|
||||
|
||||
/* dump/load error code
|
||||
*
|
||||
@@ -60,7 +61,6 @@ MRB_API mrb_irep *mrb_read_irep(mrb_state*, const uint8_t*);
|
||||
|
||||
#define RITE_BINARY_EOF "END\0"
|
||||
#define RITE_SECTION_IREP_IDENT "IREP"
|
||||
#define RITE_SECTION_LINENO_IDENT "LINE"
|
||||
#define RITE_SECTION_DEBUG_IDENT "DBG\0"
|
||||
#define RITE_SECTION_LV_IDENT "LVAR"
|
||||
|
||||
@@ -92,10 +92,6 @@ struct rite_section_irep_header {
|
||||
uint8_t rite_version[4]; /* Rite Instruction Specification Version */
|
||||
};
|
||||
|
||||
struct rite_section_lineno_header {
|
||||
RITE_SECTION_HEADER;
|
||||
};
|
||||
|
||||
struct rite_section_debug_header {
|
||||
RITE_SECTION_HEADER;
|
||||
};
|
||||
|
||||
+34
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/error.h - Exception class
|
||||
/**
|
||||
** @file mruby/error.h - Exception class
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -32,23 +32,51 @@ 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);
|
||||
|
||||
#if defined(MRB_64BIT) || defined(MRB_USE_FLOAT) || defined(MRB_NAN_BOXING) || defined(MRB_WORD_BOXING)
|
||||
struct RBreak {
|
||||
MRB_OBJECT_HEADER;
|
||||
struct RProc *proc;
|
||||
mrb_value val;
|
||||
};
|
||||
#define mrb_break_value_get(brk) ((brk)->val)
|
||||
#define mrb_break_value_set(brk, v) ((brk)->val = v)
|
||||
#else
|
||||
struct RBreak {
|
||||
MRB_OBJECT_HEADER;
|
||||
struct RProc *proc;
|
||||
union mrb_value_union value;
|
||||
};
|
||||
#define RBREAK_VALUE_TT_MASK ((1 << 8) - 1)
|
||||
static inline mrb_value
|
||||
mrb_break_value_get(struct RBreak *brk)
|
||||
{
|
||||
mrb_value val;
|
||||
val.value = brk->value;
|
||||
val.tt = brk->flags & RBREAK_VALUE_TT_MASK;
|
||||
return val;
|
||||
}
|
||||
static inline void
|
||||
mrb_break_value_set(struct RBreak *brk, mrb_value val)
|
||||
{
|
||||
brk->value = val.value;
|
||||
brk->flags &= ~RBREAK_VALUE_TT_MASK;
|
||||
brk->flags |= val.tt;
|
||||
}
|
||||
#endif /* MRB_64BIT || MRB_USE_FLOAT || MRB_NAN_BOXING || MRB_WORD_BOXING */
|
||||
#define mrb_break_proc_get(brk) ((brk)->proc)
|
||||
#define mrb_break_proc_set(brk, p) ((brk)->proc = p)
|
||||
|
||||
/**
|
||||
* Protect
|
||||
*
|
||||
* @mrbgem mruby-error
|
||||
* Implemented in the mruby-error mrbgem
|
||||
*/
|
||||
MRB_API mrb_value mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state);
|
||||
|
||||
/**
|
||||
* Ensure
|
||||
*
|
||||
* @mrbgem mruby-error
|
||||
* Implemented in the mruby-error mrbgem
|
||||
*/
|
||||
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);
|
||||
@@ -56,7 +84,7 @@ MRB_API mrb_value mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
|
||||
/**
|
||||
* Rescue
|
||||
*
|
||||
* @mrbgem mruby-error
|
||||
* Implemented in the mruby-error mrbgem
|
||||
*/
|
||||
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);
|
||||
@@ -64,7 +92,7 @@ MRB_API mrb_value mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
|
||||
/**
|
||||
* Rescue exception
|
||||
*
|
||||
* @mrbgem mruby-error
|
||||
* Implemented in the mruby-error mrbgem
|
||||
*/
|
||||
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,
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/gc.h - garbage collector for mruby
|
||||
/**
|
||||
** @file mruby/gc.h - garbage collector for mruby
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
|
||||
+4
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/hash.h - Hash class
|
||||
/**
|
||||
** @file mruby/hash.h - Hash class
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -23,7 +23,7 @@ struct RHash {
|
||||
#define mrb_hash_ptr(v) ((struct RHash*)(mrb_ptr(v)))
|
||||
#define mrb_hash_value(p) mrb_obj_value((void*)(p))
|
||||
|
||||
MRB_API mrb_value mrb_hash_new_capa(mrb_state*, mrb_int);
|
||||
MRB_API mrb_value mrb_hash_new_capa(mrb_state *mrb, mrb_int capa);
|
||||
MRB_API mrb_value mrb_ensure_hash_type(mrb_state *mrb, mrb_value hash);
|
||||
MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
|
||||
|
||||
@@ -95,7 +95,7 @@ MRB_API mrb_value mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key,
|
||||
* @param mrb The mruby state reference.
|
||||
* @param hash The target hash.
|
||||
* @param key The key to delete.
|
||||
* @return The deleted value.
|
||||
* @return The deleted value. This value is not protected from GC. Use `mrb_gc_protect()` if necessary.
|
||||
*/
|
||||
MRB_API mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key);
|
||||
|
||||
@@ -197,13 +197,6 @@ MRB_API mrb_value mrb_hash_dup(mrb_state *mrb, mrb_value hash);
|
||||
*/
|
||||
MRB_API void mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2);
|
||||
|
||||
/* declaration of struct mrb_hash_value */
|
||||
/* be careful when you touch the internal */
|
||||
typedef struct {
|
||||
mrb_value v;
|
||||
mrb_int n;
|
||||
} mrb_hash_value;
|
||||
|
||||
/* RHASH_TBL allocates st_table if not available. */
|
||||
#define RHASH(obj) ((struct RHash*)(mrb_ptr(obj)))
|
||||
#define RHASH_TBL(h) (RHASH(h)->ht)
|
||||
|
||||
+16
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/irep.h - mrb_irep structure
|
||||
/**
|
||||
** @file mruby/irep.h - mrb_irep structure
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -32,7 +32,7 @@ typedef struct mrb_irep {
|
||||
uint16_t nregs; /* Number of register variables */
|
||||
uint8_t flags;
|
||||
|
||||
mrb_code *iseq;
|
||||
const mrb_code *iseq;
|
||||
mrb_value *pool;
|
||||
mrb_sym *syms;
|
||||
struct mrb_irep **reps;
|
||||
@@ -52,9 +52,21 @@ MRB_API mrb_irep *mrb_add_irep(mrb_state *mrb);
|
||||
/* @param [const uint8_t*] irep code, expected as a literal */
|
||||
MRB_API mrb_value mrb_load_irep(mrb_state*, const uint8_t*);
|
||||
|
||||
/*
|
||||
* @param [const void*] irep code
|
||||
* @param [size_t] size of irep buffer. If -1 is given, it is considered unrestricted.
|
||||
*/
|
||||
MRB_API mrb_value mrb_load_irep_buf(mrb_state*, const void*, size_t);
|
||||
|
||||
/* @param [const uint8_t*] irep code, expected as a literal */
|
||||
MRB_API mrb_value mrb_load_irep_cxt(mrb_state*, const uint8_t*, mrbc_context*);
|
||||
|
||||
/*
|
||||
* @param [const void*] irep code
|
||||
* @param [size_t] size of irep buffer. If -1 is given, it is considered unrestricted.
|
||||
*/
|
||||
MRB_API mrb_value mrb_load_irep_buf_cxt(mrb_state*, const void*, size_t, mrbc_context*);
|
||||
|
||||
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*);
|
||||
@@ -68,7 +80,7 @@ struct mrb_insn_data {
|
||||
uint8_t c;
|
||||
};
|
||||
|
||||
struct mrb_insn_data mrb_decode_insn(mrb_code *pc);
|
||||
struct mrb_insn_data mrb_decode_insn(const mrb_code *pc);
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/istruct.h - Inline structures
|
||||
/**
|
||||
** @file mruby/istruct.h - Inline structures
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -19,12 +19,12 @@ MRB_BEGIN_DECL
|
||||
|
||||
#define ISTRUCT_DATA_SIZE (sizeof(void*) * 3)
|
||||
|
||||
struct RIstruct {
|
||||
struct RIStruct {
|
||||
MRB_OBJECT_HEADER;
|
||||
char inline_data[ISTRUCT_DATA_SIZE];
|
||||
};
|
||||
|
||||
#define RISTRUCT(obj) ((struct RIstruct*)(mrb_ptr(obj)))
|
||||
#define RISTRUCT(obj) ((struct RIStruct*)(mrb_ptr(obj)))
|
||||
#define ISTRUCT_PTR(obj) (RISTRUCT(obj)->inline_data)
|
||||
|
||||
MRB_INLINE mrb_int mrb_istruct_size()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/khash.c - Hash for mruby
|
||||
/**
|
||||
** @file mruby/khash.h - Hash for mruby
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
|
||||
+41
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/numeric.h - Numeric, Integer, Float, Fixnum class
|
||||
/**
|
||||
** @file mruby/numeric.h - Numeric, Integer, Float, Fixnum class
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -23,7 +23,11 @@ MRB_BEGIN_DECL
|
||||
#define NEGFIXABLE(f) TYPED_NEGFIXABLE(f,mrb_int)
|
||||
#define FIXABLE(f) TYPED_FIXABLE(f,mrb_int)
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
#define FIXABLE_FLOAT(f) TYPED_FIXABLE(f,double)
|
||||
#ifdef MRB_INT64
|
||||
#define FIXABLE_FLOAT(f) ((f)>=-9223372036854775808.0 && (f)<9223372036854775808.0)
|
||||
#else
|
||||
#define FIXABLE_FLOAT(f) TYPED_FIXABLE(f,mrb_float)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
@@ -34,12 +38,12 @@ MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base);
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt);
|
||||
MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x);
|
||||
MRB_API mrb_value mrb_int_value(mrb_state *mrb, mrb_float f);
|
||||
#endif
|
||||
|
||||
mrb_value mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
mrb_value mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
MRB_API mrb_value mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
MRB_API mrb_value mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
MRB_API mrb_value mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
@@ -156,6 +160,36 @@ mrb_int_mul_overflow(mrb_int multiplier, mrb_int multiplicand, mrb_int *product)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
# include <stdint.h>
|
||||
# include <float.h>
|
||||
|
||||
# define MRB_FLT_RADIX FLT_RADIX
|
||||
|
||||
# ifdef MRB_USE_FLOAT
|
||||
# define MRB_FLT_MANT_DIG FLT_MANT_DIG
|
||||
# define MRB_FLT_EPSILON FLT_EPSILON
|
||||
# define MRB_FLT_DIG FLT_DIG
|
||||
# define MRB_FLT_MIN_EXP FLT_MIN_EXP
|
||||
# define MRB_FLT_MIN FLT_MIN
|
||||
# define MRB_FLT_MIN_10_EXP FLT_MIN_10_EXP
|
||||
# define MRB_FLT_MAX_EXP FLT_MAX_EXP
|
||||
# define MRB_FLT_MAX FLT_MAX
|
||||
# define MRB_FLT_MAX_10_EXP FLT_MAX_10_EXP
|
||||
|
||||
# else /* not MRB_USE_FLOAT */
|
||||
# define MRB_FLT_MANT_DIG DBL_MANT_DIG
|
||||
# define MRB_FLT_EPSILON DBL_EPSILON
|
||||
# define MRB_FLT_DIG DBL_DIG
|
||||
# define MRB_FLT_MIN_EXP DBL_MIN_EXP
|
||||
# define MRB_FLT_MIN DBL_MIN
|
||||
# define MRB_FLT_MIN_10_EXP DBL_MIN_10_EXP
|
||||
# define MRB_FLT_MAX_EXP DBL_MAX_EXP
|
||||
# define MRB_FLT_MAX DBL_MAX
|
||||
# define MRB_FLT_MAX_10_EXP DBL_MAX_10_EXP
|
||||
# endif /* MRB_USE_FLOAT */
|
||||
#endif /* MRB_WITHOUT_FLOAT */
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
#endif /* MRUBY_NUMERIC_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/object.h - mruby object definition
|
||||
/**
|
||||
** @file mruby/object.h - mruby object definition
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -8,15 +8,14 @@
|
||||
#define MRUBY_OBJECT_H
|
||||
|
||||
#define MRB_OBJECT_HEADER \
|
||||
enum mrb_vtype tt:8;\
|
||||
uint32_t color:3;\
|
||||
uint32_t flags:21;\
|
||||
struct RClass *c;\
|
||||
struct RBasic *gcnext
|
||||
struct RClass *c; \
|
||||
struct RBasic *gcnext; \
|
||||
enum mrb_vtype tt:8; \
|
||||
uint32_t color:3; \
|
||||
uint32_t flags:21
|
||||
|
||||
#define MRB_FLAG_TEST(obj, flag) ((obj)->flags & (flag))
|
||||
|
||||
|
||||
struct RBasic {
|
||||
MRB_OBJECT_HEADER;
|
||||
};
|
||||
@@ -26,6 +25,7 @@ struct RBasic {
|
||||
#define MRB_FROZEN_P(o) ((o)->flags & MRB_FL_OBJ_IS_FROZEN)
|
||||
#define MRB_SET_FROZEN_FLAG(o) ((o)->flags |= MRB_FL_OBJ_IS_FROZEN)
|
||||
#define MRB_UNSET_FROZEN_FLAG(o) ((o)->flags &= ~MRB_FL_OBJ_IS_FROZEN)
|
||||
#define mrb_frozen_p(o) MRB_FROZEN_P(o)
|
||||
|
||||
struct RObject {
|
||||
MRB_OBJECT_HEADER;
|
||||
@@ -33,7 +33,6 @@ struct RObject {
|
||||
};
|
||||
#define mrb_obj_ptr(v) ((struct RObject*)(mrb_ptr(v)))
|
||||
|
||||
#define mrb_immediate_p(x) (mrb_type(x) < MRB_TT_HAS_BASIC)
|
||||
#define mrb_special_const_p(x) mrb_immediate_p(x)
|
||||
|
||||
struct RFiber {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/opcode.h - RiteVM operation codes
|
||||
/**
|
||||
** @file mruby/opcode.h - RiteVM operation codes
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
|
||||
+6
-6
@@ -45,9 +45,9 @@ OPCODE(SETMCNST, BB) /* R(a+1)::Syms(b) = R(a) */
|
||||
OPCODE(GETUPVAR, BBB) /* R(a) = uvget(b,c) */
|
||||
OPCODE(SETUPVAR, BBB) /* uvset(b,c,R(a)) */
|
||||
OPCODE(JMP, S) /* pc=a */
|
||||
OPCODE(JMPIF, BS) /* if R(b) pc=a */
|
||||
OPCODE(JMPNOT, BS) /* if !R(b) pc=a */
|
||||
OPCODE(JMPNIL, BS) /* if R(b)==nil pc=a */
|
||||
OPCODE(JMPIF, BS) /* if R(a) pc=b */
|
||||
OPCODE(JMPNOT, BS) /* if !R(a) pc=b */
|
||||
OPCODE(JMPNIL, BS) /* if R(a)==nil pc=b */
|
||||
OPCODE(ONERR, S) /* rescue_push(a) */
|
||||
OPCODE(EXCEPT, B) /* R(a) = exc */
|
||||
OPCODE(RESCUE, BB) /* R(b) = R(a).isa?(R(b)) */
|
||||
@@ -58,7 +58,7 @@ OPCODE(EPOP, B) /* A.times{ensure_pop().call} */
|
||||
OPCODE(SENDV, BB) /* R(a) = call(R(a),Syms(b),*R(a+1)) */
|
||||
OPCODE(SENDVB, BB) /* R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2)) */
|
||||
OPCODE(SEND, BBB) /* R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c)) */
|
||||
OPCODE(SENDB, BBB) /* R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1)) */
|
||||
OPCODE(SENDB, BBB) /* R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c),&R(a+c+1)) */
|
||||
OPCODE(CALL, Z) /* R(0) = self.call(frame.argc, frame.argv) */
|
||||
OPCODE(SUPER, BB) /* R(a) = super(R(a+1),... ,R(a+b+1)) */
|
||||
OPCODE(ARGARY, BS) /* R(a) = argument array (16=m5:r1:m5:d1:lv4) */
|
||||
@@ -71,9 +71,9 @@ OPCODE(RETURN_BLK, B) /* return R(a) (in-block return) */
|
||||
OPCODE(BREAK, B) /* break R(a) */
|
||||
OPCODE(BLKPUSH, BS) /* R(a) = block (16=m5:r1:m5:d1:lv4) */
|
||||
OPCODE(ADD, B) /* R(a) = R(a)+R(a+1) */
|
||||
OPCODE(ADDI, BB) /* R(a) = R(a)+mrb_int(c) */
|
||||
OPCODE(ADDI, BB) /* R(a) = R(a)+mrb_int(b) */
|
||||
OPCODE(SUB, B) /* R(a) = R(a)-R(a+1) */
|
||||
OPCODE(SUBI, BB) /* R(a) = R(a)-C */
|
||||
OPCODE(SUBI, BB) /* R(a) = R(a)-mrb_int(b) */
|
||||
OPCODE(MUL, B) /* R(a) = R(a)*R(a+1) */
|
||||
OPCODE(DIV, B) /* R(a) = R(a)/R(a+1) */
|
||||
OPCODE(EQ, B) /* R(a) = R(a)==R(a+1) */
|
||||
|
||||
+19
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/proc.h - Proc class
|
||||
/**
|
||||
** @file mruby/proc.h - Proc class
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -86,38 +86,44 @@ struct RProc *mrb_closure_new(mrb_state*, mrb_irep*);
|
||||
MRB_API struct RProc *mrb_proc_new_cfunc(mrb_state*, mrb_func_t);
|
||||
MRB_API struct RProc *mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals);
|
||||
void mrb_proc_copy(struct RProc *a, struct RProc *b);
|
||||
mrb_int mrb_proc_arity(const struct RProc *p);
|
||||
|
||||
/* implementation of #send method */
|
||||
mrb_value mrb_f_send(mrb_state *mrb, mrb_value self);
|
||||
|
||||
/* following functions are defined in mruby-proc-ext so please include it when using */
|
||||
MRB_API struct RProc *mrb_proc_new_cfunc_with_env(mrb_state*, mrb_func_t, mrb_int, const mrb_value*);
|
||||
MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state*, mrb_int);
|
||||
MRB_API struct RProc *mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const mrb_value *argv);
|
||||
MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx);
|
||||
/* old name */
|
||||
#define mrb_cfunc_env_get(mrb, idx) mrb_proc_cfunc_env_get(mrb, idx)
|
||||
|
||||
#ifdef MRB_METHOD_TABLE_INLINE
|
||||
#define MRB_METHOD_FUNC_FL 1
|
||||
#define MRB_METHOD_NOARG_FL 2
|
||||
#ifndef MRB_METHOD_T_STRUCT
|
||||
|
||||
#define MRB_METHOD_FUNC_FL ((uintptr_t)1)
|
||||
#define MRB_METHOD_FUNC_P(m) (((uintptr_t)(m))&MRB_METHOD_FUNC_FL)
|
||||
#define MRB_METHOD_FUNC(m) ((mrb_func_t)((uintptr_t)(m)&(~MRB_METHOD_FUNC_FL)))
|
||||
#define MRB_METHOD_FROM_FUNC(m,fn) ((m)=(mrb_method_t)((struct RProc*)((uintptr_t)(fn)|MRB_METHOD_FUNC_FL)))
|
||||
#define MRB_METHOD_FROM_PROC(m,pr) ((m)=(mrb_method_t)(struct RProc*)(pr))
|
||||
#define MRB_METHOD_NOARG_P(m) (((uintptr_t)(m))&MRB_METHOD_NOARG_FL)
|
||||
#define MRB_METHOD_NOARG_SET(m) ((m)=(mrb_method_t)(((uintptr_t)(m))|MRB_METHOD_NOARG_FL))
|
||||
#define MRB_METHOD_FUNC(m) ((mrb_func_t)((uintptr_t)(m)>>2))
|
||||
#define MRB_METHOD_FROM_FUNC(m,fn) ((m)=(mrb_method_t)((((uintptr_t)(fn))<<2)|MRB_METHOD_FUNC_FL))
|
||||
#define MRB_METHOD_FROM_PROC(m,pr) ((m)=(mrb_method_t)(pr))
|
||||
#define MRB_METHOD_PROC_P(m) (!MRB_METHOD_FUNC_P(m))
|
||||
#define MRB_METHOD_PROC(m) ((struct RProc*)(m))
|
||||
#define MRB_METHOD_UNDEF_P(m) ((m)==0)
|
||||
|
||||
#else
|
||||
|
||||
#define MRB_METHOD_FUNC_P(m) ((m).func_p)
|
||||
#define MRB_METHOD_FUNC_P(m) ((m).flags&MRB_METHOD_FUNC_FL)
|
||||
#define MRB_METHOD_NOARG_P(m) ((m).flags&MRB_METHOD_NOARG_FL)
|
||||
#define MRB_METHOD_FUNC(m) ((m).func)
|
||||
#define MRB_METHOD_FROM_FUNC(m,fn) do{(m).func_p=TRUE;(m).func=(fn);}while(0)
|
||||
#define MRB_METHOD_FROM_PROC(m,pr) do{(m).func_p=FALSE;(m).proc=(pr);}while(0)
|
||||
#define MRB_METHOD_NOARG_SET(m) do{(m).flags|=MRB_METHOD_NOARG_FL;}while(0)
|
||||
#define MRB_METHOD_FROM_FUNC(m,fn) do{(m).flags=MRB_METHOD_FUNC_FL;(m).func=(fn);}while(0)
|
||||
#define MRB_METHOD_FROM_PROC(m,pr) do{(m).flags=0;(m).proc=(pr);}while(0)
|
||||
#define MRB_METHOD_PROC_P(m) (!MRB_METHOD_FUNC_P(m))
|
||||
#define MRB_METHOD_PROC(m) ((m).proc)
|
||||
#define MRB_METHOD_UNDEF_P(m) ((m).proc==NULL)
|
||||
|
||||
#endif /* MRB_METHOD_TABLE_INLINE */
|
||||
#endif /* MRB_METHOD_T_STRUCT */
|
||||
|
||||
#define MRB_METHOD_CFUNC_P(m) (MRB_METHOD_FUNC_P(m)?TRUE:(MRB_METHOD_PROC(m)?(MRB_PROC_CFUNC_P(MRB_METHOD_PROC(m))):FALSE))
|
||||
#define MRB_METHOD_CFUNC(m) (MRB_METHOD_FUNC_P(m)?MRB_METHOD_FUNC(m):((MRB_METHOD_PROC(m)&&MRB_PROC_CFUNC_P(MRB_METHOD_PROC(m)))?MRB_PROC_CFUNC(MRB_METHOD_PROC(m)):NULL))
|
||||
|
||||
+10
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/range.h - Range class
|
||||
/**
|
||||
** @file mruby/range.h - Range class
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -14,7 +14,7 @@
|
||||
*/
|
||||
MRB_BEGIN_DECL
|
||||
|
||||
#if defined(MRB_NAN_BOXING) || defined(MRB_WORD_BOXING)
|
||||
#if defined(MRB_NAN_BOXING) && defined(MRB_64BIT) || defined(MRB_WORD_BOXING)
|
||||
# define MRB_RANGE_EMBED
|
||||
#endif
|
||||
|
||||
@@ -64,7 +64,13 @@ MRB_API struct RRange* mrb_range_ptr(mrb_state *mrb, mrb_value range);
|
||||
*/
|
||||
MRB_API mrb_value mrb_range_new(mrb_state *mrb, mrb_value start, mrb_value end, mrb_bool exclude);
|
||||
|
||||
MRB_API mrb_int mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc);
|
||||
enum mrb_range_beg_len {
|
||||
MRB_RANGE_TYPE_MISMATCH = 0, /* (failure) not range */
|
||||
MRB_RANGE_OK = 1, /* (success) range */
|
||||
MRB_RANGE_OUT = 2 /* (failure) out of range */
|
||||
};
|
||||
|
||||
MRB_API enum mrb_range_beg_len mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc);
|
||||
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));
|
||||
void mrb_gc_mark_range(mrb_state *mrb, struct RRange *r);
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/re.h - Regexp class
|
||||
/**
|
||||
** @file mruby/re.h - Regexp class
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
|
||||
+127
-104
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/string.h - String class
|
||||
/**
|
||||
** @file mruby/string.h - String class
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -16,7 +16,8 @@ MRB_BEGIN_DECL
|
||||
|
||||
extern const char mrb_digitmap[];
|
||||
|
||||
#define RSTRING_EMBED_LEN_MAX ((mrb_int)(sizeof(void*) * 3 - 1))
|
||||
#define RSTRING_EMBED_LEN_MAX \
|
||||
((mrb_int)(sizeof(void*) * 3 + sizeof(void*) - 32 / CHAR_BIT - 1))
|
||||
|
||||
struct RString {
|
||||
MRB_OBJECT_HEADER;
|
||||
@@ -30,9 +31,15 @@ struct RString {
|
||||
} aux;
|
||||
char *ptr;
|
||||
} heap;
|
||||
char ary[RSTRING_EMBED_LEN_MAX + 1];
|
||||
} as;
|
||||
};
|
||||
struct RStringEmbed {
|
||||
MRB_OBJECT_HEADER;
|
||||
char ary[];
|
||||
};
|
||||
|
||||
#define RSTR_SET_TYPE_FLAG(s, type) (RSTR_UNSET_TYPE_FLAG(s), (s)->flags |= MRB_STR_##type)
|
||||
#define RSTR_UNSET_TYPE_FLAG(s) ((s)->flags &= ~(MRB_STR_TYPE_MASK|MRB_STR_EMBED_LEN_MASK))
|
||||
|
||||
#define RSTR_EMBED_P(s) ((s)->flags & MRB_STR_EMBED)
|
||||
#define RSTR_SET_EMBED_FLAG(s) ((s)->flags |= MRB_STR_EMBED)
|
||||
@@ -50,9 +57,12 @@ struct RString {
|
||||
(s)->as.heap.len = (mrb_int)(n);\
|
||||
}\
|
||||
} while (0)
|
||||
#define RSTR_EMBED_PTR(s) (((struct RStringEmbed*)(s))->ary)
|
||||
#define RSTR_EMBED_LEN(s)\
|
||||
(mrb_int)(((s)->flags & MRB_STR_EMBED_LEN_MASK) >> MRB_STR_EMBED_LEN_SHIFT)
|
||||
#define RSTR_PTR(s) ((RSTR_EMBED_P(s)) ? (s)->as.ary : (s)->as.heap.ptr)
|
||||
#define RSTR_EMBEDDABLE_P(len) ((len) <= RSTRING_EMBED_LEN_MAX)
|
||||
|
||||
#define RSTR_PTR(s) ((RSTR_EMBED_P(s)) ? RSTR_EMBED_PTR(s) : (s)->as.heap.ptr)
|
||||
#define RSTR_LEN(s) ((RSTR_EMBED_P(s)) ? RSTR_EMBED_LEN(s) : (s)->as.heap.len)
|
||||
#define RSTR_CAPA(s) (RSTR_EMBED_P(s) ? RSTRING_EMBED_LEN_MAX : (s)->as.heap.aux.capa)
|
||||
|
||||
@@ -68,10 +78,24 @@ struct RString {
|
||||
#define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE)
|
||||
#define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE)
|
||||
|
||||
#ifdef MRB_UTF8_STRING
|
||||
# define RSTR_ASCII_P(s) ((s)->flags & MRB_STR_ASCII)
|
||||
# define RSTR_SET_ASCII_FLAG(s) ((s)->flags |= MRB_STR_ASCII)
|
||||
# define RSTR_UNSET_ASCII_FLAG(s) ((s)->flags &= ~MRB_STR_ASCII)
|
||||
# define RSTR_WRITE_ASCII_FLAG(s, v) (RSTR_UNSET_ASCII_FLAG(s), (s)->flags |= v)
|
||||
# define RSTR_COPY_ASCII_FLAG(dst, src) RSTR_WRITE_ASCII_FLAG(dst, RSTR_ASCII_P(src))
|
||||
#else
|
||||
# define RSTR_ASCII_P(s) (void)0
|
||||
# define RSTR_SET_ASCII_FLAG(s) (void)0
|
||||
# define RSTR_UNSET_ASCII_FLAG(s) (void)0
|
||||
# define RSTR_WRITE_ASCII_FLAG(s, v) (void)0
|
||||
# define RSTR_COPY_ASCII_FLAG(dst, src) (void)0
|
||||
#endif
|
||||
|
||||
#define RSTR_POOL_P(s) ((s)->flags & MRB_STR_POOL)
|
||||
#define RSTR_SET_POOL_FLAG(s) ((s)->flags |= MRB_STR_POOL)
|
||||
|
||||
/*
|
||||
/**
|
||||
* Returns a pointer from a Ruby string
|
||||
*/
|
||||
#define mrb_str_ptr(s) ((struct RString*)(mrb_ptr(s)))
|
||||
@@ -82,32 +106,38 @@ struct RString {
|
||||
#define RSTRING_CAPA(s) RSTR_CAPA(RSTRING(s))
|
||||
#define RSTRING_END(s) (RSTRING_PTR(s) + RSTRING_LEN(s))
|
||||
MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*);
|
||||
#define RSTRING_CSTR(mrb,s) mrb_string_cstr(mrb, s)
|
||||
|
||||
#define MRB_STR_SHARED 1
|
||||
#define MRB_STR_FSHARED 2
|
||||
#define MRB_STR_NOFREE 4
|
||||
#define MRB_STR_POOL 8
|
||||
#define MRB_STR_NO_UTF 16
|
||||
#define MRB_STR_EMBED 32
|
||||
#define MRB_STR_EMBED_LEN_MASK 0x7c0
|
||||
#define MRB_STR_EMBED 8 /* type flags up to here */
|
||||
#define MRB_STR_POOL 16 /* status flags from here */
|
||||
#define MRB_STR_ASCII 32
|
||||
#define MRB_STR_EMBED_LEN_SHIFT 6
|
||||
#define MRB_STR_EMBED_LEN_BITSIZE 5
|
||||
#define MRB_STR_EMBED_LEN_MASK (((1 << MRB_STR_EMBED_LEN_BITSIZE) - 1) << MRB_STR_EMBED_LEN_SHIFT)
|
||||
#define MRB_STR_TYPE_MASK (MRB_STR_POOL - 1)
|
||||
|
||||
|
||||
void mrb_gc_free_str(mrb_state*, struct RString*);
|
||||
MRB_API void mrb_str_modify(mrb_state*, struct RString*);
|
||||
|
||||
/*
|
||||
MRB_API void mrb_str_modify(mrb_state *mrb, struct RString *s);
|
||||
/* mrb_str_modify() with keeping ASCII flag if set */
|
||||
MRB_API void mrb_str_modify_keep_ascii(mrb_state *mrb, struct RString *s);
|
||||
|
||||
/**
|
||||
* Finds the index of a substring in a string
|
||||
*/
|
||||
MRB_API mrb_int mrb_str_index(mrb_state*, mrb_value, const char*, mrb_int, mrb_int);
|
||||
MRB_API mrb_int mrb_str_index(mrb_state *mrb, mrb_value str, const char *p, mrb_int len, mrb_int offset);
|
||||
#define mrb_str_index_lit(mrb, str, lit, off) mrb_str_index(mrb, str, lit, mrb_strlen_lit(lit), off);
|
||||
|
||||
/*
|
||||
/**
|
||||
* Appends self to other. Returns self as a concatenated string.
|
||||
*
|
||||
*
|
||||
* Example:
|
||||
* Example:
|
||||
*
|
||||
* !!!c
|
||||
* int
|
||||
* main(int argc,
|
||||
* char **argv)
|
||||
@@ -129,32 +159,30 @@ MRB_API mrb_int mrb_str_index(mrb_state*, mrb_value, const char*, mrb_int, mrb_i
|
||||
* // Concatenates str2 to str1.
|
||||
* mrb_str_concat(mrb, str1, str2);
|
||||
*
|
||||
* // Prints new Concatenated Ruby string.
|
||||
* mrb_p(mrb, str1);
|
||||
* // Prints new Concatenated Ruby string.
|
||||
* mrb_p(mrb, str1);
|
||||
*
|
||||
* mrb_close(mrb);
|
||||
* return 0;
|
||||
* }
|
||||
* mrb_close(mrb);
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
*
|
||||
* Result:
|
||||
* Result:
|
||||
*
|
||||
* => "abcdef"
|
||||
*
|
||||
* @param [mrb_state] mrb The current mruby state.
|
||||
* @param [mrb_value] self String to concatenate.
|
||||
* @param [mrb_value] other String to append to self.
|
||||
* @param mrb The current mruby state.
|
||||
* @param self String to concatenate.
|
||||
* @param other String to append to self.
|
||||
* @return [mrb_value] Returns a new String appending other to self.
|
||||
*/
|
||||
MRB_API void mrb_str_concat(mrb_state*, mrb_value, mrb_value);
|
||||
MRB_API void mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other);
|
||||
|
||||
/*
|
||||
/**
|
||||
* Adds two strings together.
|
||||
*
|
||||
*
|
||||
* Example:
|
||||
* Example:
|
||||
*
|
||||
* !!!c
|
||||
* int
|
||||
* main(int argc,
|
||||
* char **argv)
|
||||
@@ -181,52 +209,51 @@ MRB_API void mrb_str_concat(mrb_state*, mrb_value, mrb_value);
|
||||
* // Concatenates both Ruby strings.
|
||||
* c = mrb_str_plus(mrb, a, b);
|
||||
*
|
||||
* // Prints new Concatenated Ruby string.
|
||||
* mrb_p(mrb, c);
|
||||
* // Prints new Concatenated Ruby string.
|
||||
* mrb_p(mrb, c);
|
||||
*
|
||||
* mrb_close(mrb);
|
||||
* return 0;
|
||||
* }
|
||||
* mrb_close(mrb);
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
*
|
||||
* Result:
|
||||
* Result:
|
||||
*
|
||||
* => "abc" # First string
|
||||
* => "def" # Second string
|
||||
* => "abcdef" # First & Second concatenated.
|
||||
*
|
||||
* @param [mrb_state] mrb The current mruby state.
|
||||
* @param [mrb_value] a First string to concatenate.
|
||||
* @param [mrb_value] b Second string to concatenate.
|
||||
* @param mrb The current mruby state.
|
||||
* @param a First string to concatenate.
|
||||
* @param b Second string to concatenate.
|
||||
* @return [mrb_value] Returns a new String containing a concatenated to b.
|
||||
*/
|
||||
MRB_API mrb_value mrb_str_plus(mrb_state*, mrb_value, mrb_value);
|
||||
MRB_API mrb_value mrb_str_plus(mrb_state *mrb, mrb_value a, mrb_value b);
|
||||
|
||||
/*
|
||||
/**
|
||||
* Converts pointer into a Ruby string.
|
||||
*
|
||||
* @param [mrb_state] mrb The current mruby state.
|
||||
* @param [void*] p The pointer to convert to Ruby string.
|
||||
* @param mrb The current mruby state.
|
||||
* @param p The pointer to convert to Ruby string.
|
||||
* @return [mrb_value] Returns a new Ruby String.
|
||||
*/
|
||||
MRB_API mrb_value mrb_ptr_to_str(mrb_state *, void*);
|
||||
MRB_API mrb_value mrb_ptr_to_str(mrb_state *mrb, void *p);
|
||||
|
||||
/*
|
||||
/**
|
||||
* Returns an object as a Ruby string.
|
||||
*
|
||||
* @param [mrb_state] mrb The current mruby state.
|
||||
* @param [mrb_value] obj An object to return as a Ruby string.
|
||||
* @param mrb The current mruby state.
|
||||
* @param obj An object to return as a Ruby string.
|
||||
* @return [mrb_value] 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. Returns the amount of characters
|
||||
* in the specified by len.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* !!!c
|
||||
* int
|
||||
* main(int argc,
|
||||
* char **argv)
|
||||
@@ -251,21 +278,20 @@ MRB_API mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj);
|
||||
*
|
||||
* Result:
|
||||
*
|
||||
* => "Hello"
|
||||
* => "Hello"
|
||||
*
|
||||
* @param [mrb_state] mrb The current mruby state.
|
||||
* @param [mrb_value] str The Ruby string to resize.
|
||||
* @param [mrb_value] len The length.
|
||||
* @param mrb The current mruby state.
|
||||
* @param str The Ruby string to resize.
|
||||
* @param len The length.
|
||||
* @return [mrb_value] An object as a Ruby string.
|
||||
*/
|
||||
MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len);
|
||||
|
||||
/*
|
||||
/**
|
||||
* Returns a sub string.
|
||||
*
|
||||
* Example:
|
||||
* Example:
|
||||
*
|
||||
* !!!c
|
||||
* int
|
||||
* main(int argc,
|
||||
* char const **argv)
|
||||
@@ -291,24 +317,24 @@ MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len);
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* Result:
|
||||
* Result:
|
||||
*
|
||||
* => "He"
|
||||
*
|
||||
* @param [mrb_state] mrb The current mruby state.
|
||||
* @param [mrb_value] str Ruby string.
|
||||
* @param [mrb_int] beg The beginning point of the sub-string.
|
||||
* @param [mrb_int] len The end point of the sub-string.
|
||||
* @param mrb The current mruby state.
|
||||
* @param str Ruby string.
|
||||
* @param beg The beginning point of the sub-string.
|
||||
* @param len The end point of the sub-string.
|
||||
* @return [mrb_value] An object as a Ruby 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.
|
||||
*
|
||||
*
|
||||
* @param [mrb_state] mrb The current mruby state.
|
||||
* @param [mrb_value] str Ruby string.
|
||||
* @param mrb The current mruby state.
|
||||
* @param str Ruby string.
|
||||
* @return [mrb_value] A Ruby string.
|
||||
*/
|
||||
MRB_API mrb_value mrb_ensure_string_type(mrb_state *mrb, mrb_value str);
|
||||
@@ -320,33 +346,30 @@ MRB_API mrb_value mrb_string_type(mrb_state *mrb, mrb_value str);
|
||||
MRB_API mrb_value mrb_str_new_capa(mrb_state *mrb, size_t capa);
|
||||
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);
|
||||
/* NULL terminated C string from mrb_value */
|
||||
MRB_API const char *mrb_string_cstr(mrb_state *mrb, mrb_value str);
|
||||
/* NULL terminated C string from mrb_value; `str` will be updated */
|
||||
MRB_API const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *str);
|
||||
/* obslete: use RSTRING_PTR() */
|
||||
MRB_API const char *mrb_string_value_ptr(mrb_state *mrb, mrb_value str);
|
||||
/*
|
||||
* Returns the length of the Ruby string.
|
||||
*
|
||||
*
|
||||
* @param [mrb_state] mrb The current mruby state.
|
||||
* @param [mrb_value] str Ruby string.
|
||||
* @return [mrb_int] The length of the passed in Ruby string.
|
||||
*/
|
||||
/* obslete: use RSTRING_LEN() */
|
||||
MRB_API mrb_int mrb_string_value_len(mrb_state *mrb, mrb_value str);
|
||||
|
||||
/*
|
||||
/**
|
||||
* Duplicates a string object.
|
||||
*
|
||||
*
|
||||
* @param [mrb_state] mrb The current mruby state.
|
||||
* @param [mrb_value] str Ruby string.
|
||||
* @param mrb The current mruby state.
|
||||
* @param str Ruby string.
|
||||
* @return [mrb_value] Duplicated Ruby string.
|
||||
*/
|
||||
MRB_API mrb_value mrb_str_dup(mrb_state *mrb, mrb_value str);
|
||||
|
||||
/*
|
||||
/**
|
||||
* Returns a symbol from a passed in Ruby string.
|
||||
*
|
||||
* @param [mrb_state] mrb The current mruby state.
|
||||
* @param [mrb_value] self Ruby string.
|
||||
* @param mrb The current mruby state.
|
||||
* @param self Ruby string.
|
||||
* @return [mrb_value] A symbol.
|
||||
*/
|
||||
MRB_API mrb_value mrb_str_intern(mrb_state *mrb, mrb_value self);
|
||||
@@ -356,40 +379,40 @@ MRB_API mrb_value mrb_cstr_to_inum(mrb_state *mrb, const char *s, mrb_int base,
|
||||
MRB_API double mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck);
|
||||
MRB_API double mrb_cstr_to_dbl(mrb_state *mrb, const char *s, mrb_bool badcheck);
|
||||
|
||||
/*
|
||||
/**
|
||||
* Returns a converted string type.
|
||||
* For type checking, non converting `mrb_to_str` is recommended.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param [mrb_state] mrb The current mruby state.
|
||||
* @param [mrb_value] str1 Ruby string to compare.
|
||||
* @param [mrb_value] str2 Ruby string to compare.
|
||||
* @param mrb The current mruby state.
|
||||
* @param str1 Ruby string to compare.
|
||||
* @param str2 Ruby string to compare.
|
||||
* @return [mrb_value] boolean value.
|
||||
*/
|
||||
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.
|
||||
/**
|
||||
* Returns a concatenated string comprised of a Ruby string and a C string.
|
||||
*
|
||||
* @param [mrb_state] mrb The current mruby state.
|
||||
* @param [mrb_value] str Ruby string.
|
||||
* @param [const char *] ptr A C string.
|
||||
* @param [size_t] len length of C string.
|
||||
* @param mrb The current mruby state.
|
||||
* @param str Ruby string.
|
||||
* @param ptr A C string.
|
||||
* @param len length of C string.
|
||||
* @return [mrb_value] A Ruby 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.
|
||||
/**
|
||||
* Returns a concatenated string comprised of a Ruby string and a C string.
|
||||
*
|
||||
* @param [mrb_state] mrb The current mruby state.
|
||||
* @param [mrb_value] str Ruby string.
|
||||
* @param [const char *] ptr A C string.
|
||||
* @param mrb The current mruby state.
|
||||
* @param str Ruby string.
|
||||
* @param ptr A C string.
|
||||
* @return [mrb_value] A Ruby string.
|
||||
* @see mrb_str_cat
|
||||
*/
|
||||
@@ -397,17 +420,17 @@ MRB_API mrb_value mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *pt
|
||||
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.
|
||||
*
|
||||
@@ -418,8 +441,8 @@ MRB_API int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2);
|
||||
* - 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.
|
||||
* @param mrb The current mruby state.
|
||||
* @param 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);
|
||||
@@ -428,19 +451,19 @@ mrb_value mrb_str_pool(mrb_state *mrb, mrb_value str);
|
||||
uint32_t 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);
|
||||
void mrb_regexp_check(mrb_state *mrb, mrb_value obj);
|
||||
|
||||
/* For backward compatibility */
|
||||
#define mrb_str_cat2(mrb, str, ptr) mrb_str_cat_cstr(mrb, str, ptr)
|
||||
#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)
|
||||
|
||||
mrb_bool mrb_str_beg_len(mrb_int str_len, mrb_int *begp, mrb_int *lenp);
|
||||
mrb_value mrb_str_byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
|
||||
|
||||
#ifdef MRB_UTF8_STRING
|
||||
mrb_int mrb_utf8_len(const char *str, mrb_int byte_len);
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/throw.h - mruby exception throwing handler
|
||||
/**
|
||||
** @file mruby/throw.h - mruby exception throwing handler
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
|
||||
+136
-56
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/value.h - mruby value definitions
|
||||
/**
|
||||
** @file mruby/value.h - mruby value definitions
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -9,12 +9,28 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/**
|
||||
/*
|
||||
* MRuby Value definition functions and macros.
|
||||
*/
|
||||
MRB_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* mruby Symbol.
|
||||
* @class mrb_sym
|
||||
*
|
||||
* You can create an mrb_sym by simply using mrb_str_intern() or mrb_intern_cstr()
|
||||
*/
|
||||
typedef uint32_t mrb_sym;
|
||||
|
||||
/**
|
||||
* mruby Boolean.
|
||||
* @class mrb_bool
|
||||
*
|
||||
*
|
||||
* Used internally to represent boolean. Can be TRUE or FALSE.
|
||||
* Not to be confused with Ruby's boolean classes, which can be
|
||||
* obtained using mrb_false_value() and mrb_true_value()
|
||||
*/
|
||||
typedef uint8_t mrb_bool;
|
||||
struct mrb_state;
|
||||
|
||||
@@ -25,12 +41,15 @@ struct mrb_state;
|
||||
#if defined _MSC_VER && _MSC_VER < 1800
|
||||
# define PRIo64 "llo"
|
||||
# define PRId64 "lld"
|
||||
# define PRIu64 "llu"
|
||||
# define PRIx64 "llx"
|
||||
# define PRIo16 "ho"
|
||||
# define PRId16 "hd"
|
||||
# define PRIu16 "hu"
|
||||
# define PRIx16 "hx"
|
||||
# define PRIo32 "o"
|
||||
# define PRId32 "d"
|
||||
# define PRIu32 "u"
|
||||
# define PRIx32 "x"
|
||||
#else
|
||||
# include <inttypes.h>
|
||||
@@ -62,6 +81,11 @@ struct mrb_state;
|
||||
# define MRB_PRIx PRIx32
|
||||
#endif
|
||||
|
||||
#ifdef MRB_ENDIAN_BIG
|
||||
# define MRB_ENDIAN_LOHI(a,b) a b
|
||||
#else
|
||||
# define MRB_ENDIAN_LOHI(a,b) b a
|
||||
#endif
|
||||
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
MRB_API double mrb_float_read(const char*, char**);
|
||||
@@ -73,9 +97,6 @@ MRB_API double mrb_float_read(const char*, char**);
|
||||
#endif
|
||||
|
||||
#if defined _MSC_VER && _MSC_VER < 1900
|
||||
# ifndef __cplusplus
|
||||
# define inline __inline
|
||||
# endif
|
||||
# include <stdarg.h>
|
||||
MRB_API int mrb_msvc_vsnprintf(char *s, size_t n, const char *format, va_list arg);
|
||||
MRB_API int mrb_msvc_snprintf(char *s, size_t n, const char *format, ...);
|
||||
@@ -95,13 +116,13 @@ static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000;
|
||||
|
||||
enum mrb_vtype {
|
||||
MRB_TT_FALSE = 0, /* 0 */
|
||||
MRB_TT_FREE, /* 1 */
|
||||
MRB_TT_TRUE, /* 2 */
|
||||
MRB_TT_TRUE, /* 1 */
|
||||
MRB_TT_FLOAT, /* 2 */
|
||||
MRB_TT_FIXNUM, /* 3 */
|
||||
MRB_TT_SYMBOL, /* 4 */
|
||||
MRB_TT_UNDEF, /* 5 */
|
||||
MRB_TT_FLOAT, /* 6 */
|
||||
MRB_TT_CPTR, /* 7 */
|
||||
MRB_TT_CPTR, /* 6 */
|
||||
MRB_TT_FREE, /* 7 */
|
||||
MRB_TT_OBJECT, /* 8 */
|
||||
MRB_TT_CLASS, /* 9 */
|
||||
MRB_TT_MODULE, /* 10 */
|
||||
@@ -148,36 +169,103 @@ typedef void mrb_value;
|
||||
#include "boxing_no.h"
|
||||
#endif
|
||||
|
||||
#if !defined(MRB_SYMBOL_BITSIZE)
|
||||
#define MRB_SYMBOL_BITSIZE (sizeof(mrb_sym) * CHAR_BIT)
|
||||
#define MRB_SYMBOL_MAX UINT32_MAX
|
||||
#endif
|
||||
|
||||
#ifndef mrb_immediate_p
|
||||
#define mrb_immediate_p(o) (mrb_type(o) < MRB_TT_FREE)
|
||||
#endif
|
||||
#ifndef mrb_fixnum_p
|
||||
#define mrb_fixnum_p(o) (mrb_type(o) == MRB_TT_FIXNUM)
|
||||
#endif
|
||||
#ifndef mrb_symbol_p
|
||||
#define mrb_symbol_p(o) (mrb_type(o) == MRB_TT_SYMBOL)
|
||||
#endif
|
||||
#ifndef mrb_undef_p
|
||||
#define mrb_undef_p(o) (mrb_type(o) == MRB_TT_UNDEF)
|
||||
#endif
|
||||
#ifndef mrb_nil_p
|
||||
#define mrb_nil_p(o) (mrb_type(o) == MRB_TT_FALSE && !mrb_fixnum(o))
|
||||
#endif
|
||||
#ifndef mrb_false_p
|
||||
#define mrb_false_p(o) (mrb_type(o) == MRB_TT_FALSE && !!mrb_fixnum(o))
|
||||
#endif
|
||||
#ifndef mrb_true_p
|
||||
#define mrb_true_p(o) (mrb_type(o) == MRB_TT_TRUE)
|
||||
#endif
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
#ifndef mrb_float_p
|
||||
#define mrb_float_p(o) (mrb_type(o) == MRB_TT_FLOAT)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef mrb_array_p
|
||||
#define mrb_array_p(o) (mrb_type(o) == MRB_TT_ARRAY)
|
||||
#endif
|
||||
#ifndef mrb_string_p
|
||||
#define mrb_string_p(o) (mrb_type(o) == MRB_TT_STRING)
|
||||
#endif
|
||||
#ifndef mrb_hash_p
|
||||
#define mrb_hash_p(o) (mrb_type(o) == MRB_TT_HASH)
|
||||
#endif
|
||||
#ifndef mrb_cptr_p
|
||||
#define mrb_cptr_p(o) (mrb_type(o) == MRB_TT_CPTR)
|
||||
#endif
|
||||
#ifndef mrb_exception_p
|
||||
#define mrb_exception_p(o) (mrb_type(o) == MRB_TT_EXCEPTION)
|
||||
#endif
|
||||
#ifndef mrb_free_p
|
||||
#define mrb_free_p(o) (mrb_type(o) == MRB_TT_FREE)
|
||||
#endif
|
||||
#ifndef mrb_object_p
|
||||
#define mrb_object_p(o) (mrb_type(o) == MRB_TT_OBJECT)
|
||||
#endif
|
||||
#ifndef mrb_class_p
|
||||
#define mrb_class_p(o) (mrb_type(o) == MRB_TT_CLASS)
|
||||
#endif
|
||||
#ifndef mrb_module_p
|
||||
#define mrb_module_p(o) (mrb_type(o) == MRB_TT_MODULE)
|
||||
#endif
|
||||
#ifndef mrb_iclass_p
|
||||
#define mrb_iclass_p(o) (mrb_type(o) == MRB_TT_ICLASS)
|
||||
#endif
|
||||
#ifndef mrb_sclass_p
|
||||
#define mrb_sclass_p(o) (mrb_type(o) == MRB_TT_SCLASS)
|
||||
#endif
|
||||
#ifndef mrb_proc_p
|
||||
#define mrb_proc_p(o) (mrb_type(o) == MRB_TT_PROC)
|
||||
#endif
|
||||
#ifndef mrb_range_p
|
||||
#define mrb_range_p(o) (mrb_type(o) == MRB_TT_RANGE)
|
||||
#endif
|
||||
#ifndef mrb_file_p
|
||||
#define mrb_file_p(o) (mrb_type(o) == MRB_TT_FILE)
|
||||
#endif
|
||||
#ifndef mrb_env_p
|
||||
#define mrb_env_p(o) (mrb_type(o) == MRB_TT_ENV)
|
||||
#endif
|
||||
#ifndef mrb_data_p
|
||||
#define mrb_data_p(o) (mrb_type(o) == MRB_TT_DATA)
|
||||
#endif
|
||||
#ifndef mrb_fiber_p
|
||||
#define mrb_fiber_p(o) (mrb_type(o) == MRB_TT_FIBER)
|
||||
#endif
|
||||
#ifndef mrb_istruct_p
|
||||
#define mrb_istruct_p(o) (mrb_type(o) == MRB_TT_ISTRUCT)
|
||||
#endif
|
||||
#ifndef mrb_break_p
|
||||
#define mrb_break_p(o) (mrb_type(o) == MRB_TT_BREAK)
|
||||
#endif
|
||||
#ifndef mrb_bool
|
||||
#define mrb_bool(o) (mrb_type(o) != MRB_TT_FALSE)
|
||||
#endif
|
||||
#if !defined(MRB_SYMBOL_BITSIZE)
|
||||
#define MRB_SYMBOL_BITSIZE (sizeof(mrb_sym) * CHAR_BIT)
|
||||
#define MRB_SYMBOL_MAX UINT32_MAX
|
||||
#endif
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
#define mrb_float_p(o) (mrb_type(o) == MRB_TT_FLOAT)
|
||||
#endif
|
||||
#define mrb_symbol_p(o) (mrb_type(o) == MRB_TT_SYMBOL)
|
||||
#define mrb_array_p(o) (mrb_type(o) == MRB_TT_ARRAY)
|
||||
#define mrb_string_p(o) (mrb_type(o) == MRB_TT_STRING)
|
||||
#define mrb_hash_p(o) (mrb_type(o) == MRB_TT_HASH)
|
||||
#define mrb_cptr_p(o) (mrb_type(o) == MRB_TT_CPTR)
|
||||
#define mrb_exception_p(o) (mrb_type(o) == MRB_TT_EXCEPTION)
|
||||
#define mrb_test(o) mrb_bool(o)
|
||||
MRB_API mrb_bool mrb_regexp_p(struct mrb_state*, mrb_value);
|
||||
|
||||
/*
|
||||
/**
|
||||
* Returns a float in Ruby.
|
||||
*
|
||||
* Takes a float and boxes it into an mrb_value
|
||||
*/
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f)
|
||||
@@ -189,7 +277,7 @@ MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f)
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline mrb_value
|
||||
MRB_INLINE mrb_value
|
||||
mrb_cptr_value(struct mrb_state *mrb, void *p)
|
||||
{
|
||||
mrb_value v;
|
||||
@@ -198,8 +286,10 @@ mrb_cptr_value(struct mrb_state *mrb, void *p)
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Returns a fixnum in Ruby.
|
||||
*
|
||||
* Takes an integer and boxes it into an mrb_value
|
||||
*/
|
||||
MRB_INLINE mrb_value mrb_fixnum_value(mrb_int i)
|
||||
{
|
||||
@@ -208,7 +298,7 @@ MRB_INLINE mrb_value mrb_fixnum_value(mrb_int i)
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline mrb_value
|
||||
MRB_INLINE mrb_value
|
||||
mrb_symbol_value(mrb_sym i)
|
||||
{
|
||||
mrb_value v;
|
||||
@@ -216,7 +306,7 @@ mrb_symbol_value(mrb_sym i)
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline mrb_value
|
||||
MRB_INLINE mrb_value
|
||||
mrb_obj_value(void *p)
|
||||
{
|
||||
mrb_value v;
|
||||
@@ -226,8 +316,7 @@ mrb_obj_value(void *p)
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
* Get a nil mrb_value object.
|
||||
*
|
||||
* @return
|
||||
@@ -240,7 +329,7 @@ MRB_INLINE mrb_value mrb_nil_value(void)
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Returns false in Ruby.
|
||||
*/
|
||||
MRB_INLINE mrb_value mrb_false_value(void)
|
||||
@@ -250,7 +339,7 @@ MRB_INLINE mrb_value mrb_false_value(void)
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Returns true in Ruby.
|
||||
*/
|
||||
MRB_INLINE mrb_value mrb_true_value(void)
|
||||
@@ -260,7 +349,7 @@ MRB_INLINE mrb_value mrb_true_value(void)
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline mrb_value
|
||||
MRB_INLINE mrb_value
|
||||
mrb_bool_value(mrb_bool boolean)
|
||||
{
|
||||
mrb_value v;
|
||||
@@ -268,7 +357,7 @@ mrb_bool_value(mrb_bool boolean)
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline mrb_value
|
||||
MRB_INLINE mrb_value
|
||||
mrb_undef_value(void)
|
||||
{
|
||||
mrb_value v;
|
||||
@@ -276,34 +365,25 @@ mrb_undef_value(void)
|
||||
return v;
|
||||
}
|
||||
|
||||
#ifdef MRB_USE_ETEXT_EDATA
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <mach-o/getsect.h>
|
||||
static inline mrb_bool
|
||||
mrb_ro_data_p(const char *p)
|
||||
{
|
||||
return (const char*)get_etext() < p && p < (const char*)get_edata();
|
||||
}
|
||||
#else
|
||||
extern char _etext[];
|
||||
#ifdef MRB_NO_INIT_ARRAY_START
|
||||
extern char _edata[];
|
||||
#if defined(MRB_USE_ETEXT_EDATA) && !defined(MRB_USE_LINK_TIME_RO_DATA_P)
|
||||
# ifdef __GNUC__
|
||||
# warning MRB_USE_ETEXT_EDATA is deprecated. Define MRB_USE_LINK_TIME_RO_DATA_P instead.
|
||||
# endif
|
||||
# define MRB_USE_LINK_TIME_RO_DATA_P
|
||||
#endif
|
||||
|
||||
static inline mrb_bool
|
||||
mrb_ro_data_p(const char *p)
|
||||
{
|
||||
return _etext < p && p < _edata;
|
||||
}
|
||||
#else
|
||||
#if defined(MRB_USE_CUSTOM_RO_DATA_P)
|
||||
/* If you define `MRB_USE_CUSTOM_RO_DATA_P`, you must implement `mrb_ro_data_p()`. */
|
||||
mrb_bool mrb_ro_data_p(const char *p);
|
||||
#elif defined(MRB_USE_LINK_TIME_RO_DATA_P)
|
||||
extern char __ehdr_start[];
|
||||
extern char __init_array_start[];
|
||||
|
||||
static inline mrb_bool
|
||||
mrb_ro_data_p(const char *p)
|
||||
{
|
||||
return _etext < p && p < (char*)&__init_array_start;
|
||||
return __ehdr_start < p && p < __init_array_start;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
# define mrb_ro_data_p(p) FALSE
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/variable.h - mruby variables
|
||||
/**
|
||||
** @file mruby/variable.h - mruby variables
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -97,18 +97,15 @@ MRB_API void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value val);
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* !!!ruby
|
||||
* # Ruby style
|
||||
* $value = nil
|
||||
*
|
||||
* !!!c
|
||||
* // C style
|
||||
* mrb_sym sym = mrb_intern_lit(mrb, "$value");
|
||||
* mrb_gv_remove(mrb, sym);
|
||||
*
|
||||
* @param mrb The mruby state reference
|
||||
* @param sym The name of the global variable
|
||||
* @param val The value of the global variable
|
||||
*/
|
||||
MRB_API void mrb_gv_remove(mrb_state *mrb, mrb_sym sym);
|
||||
|
||||
@@ -117,6 +114,7 @@ MRB_API void mrb_mod_cv_set(mrb_state *mrb, struct RClass * c, mrb_sym sym, mrb_
|
||||
MRB_API void mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v);
|
||||
MRB_API mrb_bool mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym);
|
||||
mrb_value mrb_obj_iv_inspect(mrb_state*, struct RObject*);
|
||||
void mrb_obj_iv_set_force(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
|
||||
mrb_value mrb_mod_constants(mrb_state *mrb, mrb_value mod);
|
||||
mrb_value mrb_f_global_variables(mrb_state *mrb, mrb_value self);
|
||||
mrb_value mrb_obj_instance_variables(mrb_state*, mrb_value);
|
||||
|
||||
+20
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** mruby/version.h - mruby version definition
|
||||
/**
|
||||
** @file mruby/version.h - mruby version definition
|
||||
**
|
||||
** See Copyright Notice in mruby.h
|
||||
*/
|
||||
@@ -77,7 +77,21 @@ MRB_BEGIN_DECL
|
||||
/*
|
||||
* Release date as a string.
|
||||
*/
|
||||
#define MRUBY_RELEASE_DATE MRB_STRINGIZE(MRUBY_RELEASE_YEAR) "-" MRB_STRINGIZE(MRUBY_RELEASE_MONTH) "-" MRB_STRINGIZE(MRUBY_RELEASE_DAY)
|
||||
#define MRUBY_RELEASE_DATE \
|
||||
MRUBY_RELEASE_YEAR_STR "-" \
|
||||
MRUBY_RELEASE_MONTH_STR "-" \
|
||||
MRUBY_RELEASE_DAY_STR
|
||||
#define MRUBY_RELEASE_YEAR_STR MRB_STRINGIZE(MRUBY_RELEASE_YEAR)
|
||||
#if MRUBY_RELEASE_MONTH < 10
|
||||
#define MRUBY_RELEASE_MONTH_STR "0" MRB_STRINGIZE(MRUBY_RELEASE_MONTH)
|
||||
#else
|
||||
#define MRUBY_RELEASE_MONTH_STR MRB_STRINGIZE(MRUBY_RELEASE_MONTH)
|
||||
#endif
|
||||
#if MRUBY_RELEASE_DAY < 10
|
||||
#define MRUBY_RELEASE_DAY_STR "0" MRB_STRINGIZE(MRUBY_RELEASE_DAY)
|
||||
#else
|
||||
#define MRUBY_RELEASE_DAY_STR MRB_STRINGIZE(MRUBY_RELEASE_DAY)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The year mruby was first created.
|
||||
@@ -92,9 +106,9 @@ MRB_BEGIN_DECL
|
||||
/*
|
||||
* mruby's version, and release date.
|
||||
*/
|
||||
#define MRUBY_DESCRIPTION \
|
||||
"mruby " MRUBY_VERSION \
|
||||
" (" MRUBY_RELEASE_DATE ") " \
|
||||
#define MRUBY_DESCRIPTION \
|
||||
"mruby " MRUBY_VERSION \
|
||||
" (" MRUBY_RELEASE_DATE ")" \
|
||||
|
||||
/*
|
||||
* mruby's copyright information.
|
||||
|
||||
+2
-39
@@ -1,3 +1,5 @@
|
||||
autoload :Pathname, 'pathname'
|
||||
|
||||
class Object
|
||||
class << self
|
||||
def attr_block(*syms)
|
||||
@@ -16,45 +18,6 @@ class String
|
||||
def relative_path
|
||||
relative_path_from(Dir.pwd)
|
||||
end
|
||||
|
||||
# Compatible with 1.9 on 1.8
|
||||
unless (sprintf("%{a}", :a => 1) rescue false)
|
||||
def %(params)
|
||||
if params.is_a?(Hash)
|
||||
str = self.clone
|
||||
params.each do |k, v|
|
||||
str.gsub!("%{#{k}}") { v }
|
||||
end
|
||||
str
|
||||
else
|
||||
if params.is_a?(Array)
|
||||
sprintf(self, *params)
|
||||
else
|
||||
sprintf(self, params)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Symbol
|
||||
# Compatible with 1.9 on 1.8
|
||||
unless method_defined?(:to_proc)
|
||||
def to_proc
|
||||
proc { |obj, *args| obj.send(self, *args) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module Enumerable
|
||||
# Compatible with 1.9 on 1.8
|
||||
unless method_defined?(:each_with_object)
|
||||
def each_with_object(memo)
|
||||
return to_enum :each_with_object, memo unless block_given?
|
||||
each { |obj| yield obj, memo }
|
||||
memo
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
$pp_show = true
|
||||
|
||||
+32
-15
@@ -1,7 +1,11 @@
|
||||
require "mruby-core-ext"
|
||||
require "mruby/build/load_gems"
|
||||
require "mruby/build/command"
|
||||
|
||||
module MRuby
|
||||
autoload :Gem, "mruby/gem"
|
||||
autoload :Lockfile, "mruby/lockfile"
|
||||
|
||||
class << self
|
||||
def targets
|
||||
@targets ||= {}
|
||||
@@ -22,7 +26,6 @@ module MRuby
|
||||
|
||||
def initialize(name, &block)
|
||||
@name, @initializer = name.to_s, block
|
||||
MRuby::Toolchain.toolchains ||= {}
|
||||
MRuby::Toolchain.toolchains[@name] = self
|
||||
end
|
||||
|
||||
@@ -30,13 +33,8 @@ module MRuby
|
||||
conf.instance_exec(conf, params, &@initializer)
|
||||
end
|
||||
|
||||
def self.load
|
||||
Dir.glob("#{MRUBY_ROOT}/tasks/toolchains/*.rake").each do |file|
|
||||
Kernel.load file
|
||||
end
|
||||
end
|
||||
self.toolchains = {}
|
||||
end
|
||||
Toolchain.load
|
||||
|
||||
class Build
|
||||
class << self
|
||||
@@ -45,7 +43,7 @@ module MRuby
|
||||
include Rake::DSL
|
||||
include LoadGems
|
||||
attr_accessor :name, :bins, :exts, :file_separator, :build_dir, :gem_clone_dir
|
||||
attr_reader :libmruby_objs, :gems, :toolchains
|
||||
attr_reader :libmruby_objs, :gems, :toolchains, :gem_dir_to_repo_url
|
||||
attr_writer :enable_bintest, :enable_test
|
||||
|
||||
alias libmruby libmruby_objs
|
||||
@@ -70,7 +68,7 @@ module MRuby
|
||||
|
||||
@file_separator = '/'
|
||||
@build_dir = "#{build_dir}/#{@name}"
|
||||
@gem_clone_dir = "#{build_dir}/mrbgems"
|
||||
@gem_clone_dir = "#{build_dir}/repos/#{@name}"
|
||||
@cc = Command::Compiler.new(self, %w(.c))
|
||||
@cxx = Command::Compiler.new(self, %w(.cc .cxx .cpp))
|
||||
@objc = Command::Compiler.new(self, %w(.m))
|
||||
@@ -90,7 +88,9 @@ module MRuby
|
||||
@cxx_abi_enabled = false
|
||||
@enable_bintest = false
|
||||
@enable_test = false
|
||||
@enable_lock = true
|
||||
@toolchains = []
|
||||
@gem_dir_to_repo_url = {}
|
||||
|
||||
MRuby.targets[@name] = self
|
||||
end
|
||||
@@ -118,6 +118,14 @@ module MRuby
|
||||
@enable_debug = true
|
||||
end
|
||||
|
||||
def disable_lock
|
||||
@enable_lock = false
|
||||
end
|
||||
|
||||
def lock_enabled?
|
||||
Lockfile.enabled? && @enable_lock
|
||||
end
|
||||
|
||||
def disable_cxx_exception
|
||||
if @cxx_exception_enabled or @cxx_abi_enabled
|
||||
raise "cxx_exception already enabled"
|
||||
@@ -155,8 +163,8 @@ module MRuby
|
||||
compilers.each { |c|
|
||||
c.defines += %w(MRB_ENABLE_CXX_EXCEPTION MRB_ENABLE_CXX_ABI)
|
||||
c.flags << c.cxx_compile_flag
|
||||
c.flags = c.flags.flatten - c.cxx_invalid_flags.flatten
|
||||
}
|
||||
compilers.each { |c| c.flags << c.cxx_compile_flag }
|
||||
linker.command = cxx.command if toolchains.find { |v| v == 'gcc' }
|
||||
@cxx_abi_enabled = true
|
||||
end
|
||||
@@ -196,10 +204,15 @@ EOS
|
||||
end
|
||||
|
||||
def toolchain(name, params={})
|
||||
tc = Toolchain.toolchains[name.to_s]
|
||||
fail "Unknown #{name} toolchain" unless tc
|
||||
name = name.to_s
|
||||
tc = Toolchain.toolchains[name] || begin
|
||||
path = "#{MRUBY_ROOT}/tasks/toolchains/#{name}.rake"
|
||||
fail "Unknown #{name} toolchain" unless File.exist?(path)
|
||||
load path
|
||||
Toolchain.toolchains[name]
|
||||
end
|
||||
tc.setup(self, params)
|
||||
@toolchains.unshift name.to_s
|
||||
@toolchains.unshift name
|
||||
end
|
||||
|
||||
def primary_toolchain
|
||||
@@ -226,6 +239,10 @@ EOS
|
||||
gem :core => 'mruby-bin-mrbc'
|
||||
end
|
||||
|
||||
def locks
|
||||
Lockfile.build(@name)
|
||||
end
|
||||
|
||||
def mrbcfile
|
||||
return @mrbcfile if @mrbcfile
|
||||
|
||||
@@ -255,7 +272,7 @@ EOS
|
||||
if name.is_a?(Array)
|
||||
name.flatten.map { |n| filename(n) }
|
||||
else
|
||||
'"%s"' % name.gsub('/', file_separator)
|
||||
name.gsub('/', file_separator)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -263,7 +280,7 @@ EOS
|
||||
if name.is_a?(Array)
|
||||
name.flatten.map { |n| cygwin_filename(n) }
|
||||
else
|
||||
'"%s"' % `cygpath -w "#{filename(name)}"`.strip
|
||||
`cygpath -w "#{filename(name)}"`.strip
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
+52
-16
@@ -41,7 +41,7 @@ module MRuby
|
||||
class Command::Compiler < Command
|
||||
attr_accessor :flags, :include_paths, :defines, :source_exts
|
||||
attr_accessor :compile_options, :option_define, :option_include_path, :out_ext
|
||||
attr_accessor :cxx_compile_flag, :cxx_exception_flag
|
||||
attr_accessor :cxx_compile_flag, :cxx_exception_flag, :cxx_invalid_flags
|
||||
|
||||
def initialize(build, source_exts=[])
|
||||
super(build)
|
||||
@@ -53,6 +53,7 @@ module MRuby
|
||||
@option_include_path = '-I%s'
|
||||
@option_define = '-D%s'
|
||||
@compile_options = '%{flags} -o %{outfile} -c %{infile}'
|
||||
@cxx_invalid_flags = []
|
||||
end
|
||||
|
||||
alias header_search_paths include_paths
|
||||
@@ -127,13 +128,40 @@ module MRuby
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
#
|
||||
# === Example of +.d+ file
|
||||
#
|
||||
# ==== Without <tt>-MP</tt> compiler flag
|
||||
#
|
||||
# /build/host/src/array.o: \
|
||||
# /src/array.c \
|
||||
# /include/mruby/common.h \
|
||||
# /include/mruby/value.h \
|
||||
# /src/value_array.h
|
||||
#
|
||||
# ==== With <tt>-MP</tt> compiler flag
|
||||
#
|
||||
# /build/host/src/array.o: \
|
||||
# /src/array.c \
|
||||
# /include/mruby/common.h \
|
||||
# /include/mruby/value.h \
|
||||
# /src/value_array.h
|
||||
#
|
||||
# /include/mruby/common.h:
|
||||
#
|
||||
# /include/mruby/value.h:
|
||||
#
|
||||
# /src/value_array.h:
|
||||
#
|
||||
def get_dependencies(file)
|
||||
file = file.ext('d') unless File.extname(file) == '.d'
|
||||
deps = []
|
||||
if File.exist?(file)
|
||||
File.read(file).gsub("\\\n ", "").scan(/^\S+:\s+(.+)$/).flatten.map {|s| s.split(' ') }.flatten
|
||||
else
|
||||
[]
|
||||
end + [ MRUBY_CONFIG ]
|
||||
File.foreach(file){|line| deps << $1 if /^ +(.*?)(?: *\\)?$/ =~ line}
|
||||
deps.uniq!
|
||||
end
|
||||
deps << MRUBY_CONFIG
|
||||
end
|
||||
end
|
||||
|
||||
@@ -243,15 +271,16 @@ module MRuby
|
||||
|
||||
class Command::Git < Command
|
||||
attr_accessor :flags
|
||||
attr_accessor :clone_options, :pull_options, :checkout_options
|
||||
attr_accessor :clone_options, :pull_options, :checkout_options, :reset_options
|
||||
|
||||
def initialize(build)
|
||||
super
|
||||
@command = 'git'
|
||||
@flags = %w[]
|
||||
@clone_options = "clone %{flags} %{url} %{dir}"
|
||||
@pull_options = "pull"
|
||||
@checkout_options = "checkout %{checksum_hash}"
|
||||
@pull_options = "--git-dir '%{repo_dir}/.git' --work-tree '%{repo_dir}' pull"
|
||||
@checkout_options = "--git-dir '%{repo_dir}/.git' --work-tree '%{repo_dir}' checkout %{checksum_hash}"
|
||||
@reset_options = "--git-dir '%{repo_dir}/.git' --work-tree '%{repo_dir}' reset %{checksum_hash}"
|
||||
end
|
||||
|
||||
def run_clone(dir, url, _flags = [])
|
||||
@@ -260,19 +289,26 @@ module MRuby
|
||||
end
|
||||
|
||||
def run_pull(dir, url)
|
||||
root = Dir.pwd
|
||||
Dir.chdir dir
|
||||
_pp "GIT PULL", url, dir.relative_path
|
||||
_run pull_options
|
||||
Dir.chdir root
|
||||
_run pull_options, { :repo_dir => dir }
|
||||
end
|
||||
|
||||
def run_checkout(dir, checksum_hash)
|
||||
root = Dir.pwd
|
||||
Dir.chdir dir
|
||||
_pp "GIT CHECKOUT", checksum_hash
|
||||
_run checkout_options, { :checksum_hash => checksum_hash }
|
||||
Dir.chdir root
|
||||
_run checkout_options, { :checksum_hash => checksum_hash, :repo_dir => dir }
|
||||
end
|
||||
|
||||
def run_reset_hard(dir, checksum_hash)
|
||||
_pp "GIT RESET", checksum_hash
|
||||
_run reset_options, { :checksum_hash => checksum_hash, :repo_dir => dir }
|
||||
end
|
||||
|
||||
def commit_hash(dir)
|
||||
`#{@command} --git-dir '#{dir}/.git' --work-tree '#{dir}' rev-parse --verify HEAD`.strip
|
||||
end
|
||||
|
||||
def current_branch(dir)
|
||||
`#{@command} --git-dir '#{dir}/.git' --work-tree '#{dir}' rev-parse --abbrev-ref HEAD`.strip
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -83,11 +83,18 @@ module MRuby
|
||||
# by default the 'master' branch is used
|
||||
branch = params[:branch] ? params[:branch] : 'master'
|
||||
|
||||
lock = locks[url] if lock_enabled?
|
||||
|
||||
if File.exist?(gemdir)
|
||||
if $pull_gems
|
||||
git.run_pull gemdir, url
|
||||
else
|
||||
gemdir
|
||||
# Jump to the top of the branch
|
||||
git.run_checkout(gemdir, branch)
|
||||
git.run_reset_hard gemdir, "origin/#{branch}"
|
||||
elsif params[:checksum_hash]
|
||||
git.run_reset_hard(gemdir, params[:checksum_hash])
|
||||
elsif lock
|
||||
git.run_reset_hard(gemdir, lock['commit'])
|
||||
end
|
||||
else
|
||||
options = [params[:options]] || []
|
||||
@@ -96,14 +103,22 @@ module MRuby
|
||||
options << "--depth 1" unless params[:checksum_hash]
|
||||
FileUtils.mkdir_p "#{gem_clone_dir}"
|
||||
git.run_clone gemdir, url, options
|
||||
|
||||
# Jump to the specified commit
|
||||
if params[:checksum_hash]
|
||||
git.run_reset_hard gemdir, params[:checksum_hash]
|
||||
elsif lock
|
||||
git.run_reset_hard gemdir, lock['commit']
|
||||
end
|
||||
end
|
||||
|
||||
if params[:checksum_hash]
|
||||
# Jump to the specified commit
|
||||
git.run_checkout gemdir, params[:checksum_hash]
|
||||
else
|
||||
# Jump to the top of the branch
|
||||
git.run_checkout gemdir, branch if $pull_gems
|
||||
if lock_enabled?
|
||||
@gem_dir_to_repo_url[gemdir] = url unless params[:path]
|
||||
locks[url] = {
|
||||
'url' => url,
|
||||
'branch' => git.current_branch(gemdir),
|
||||
'commit' => git.commit_hash(gemdir),
|
||||
}
|
||||
end
|
||||
|
||||
gemdir << "/#{params[:path]}" if params[:path]
|
||||
|
||||
+11
-7
@@ -1,7 +1,6 @@
|
||||
require 'pathname'
|
||||
require 'forwardable'
|
||||
require 'tsort'
|
||||
require 'shellwords'
|
||||
autoload :TSort, 'tsort'
|
||||
autoload :Shellwords, 'shellwords'
|
||||
|
||||
module MRuby
|
||||
module Gem
|
||||
@@ -92,6 +91,9 @@ module MRuby
|
||||
build.libmruby_objs << @objs
|
||||
|
||||
instance_eval(&@build_config_initializer) if @build_config_initializer
|
||||
|
||||
repo_url = build.gem_dir_to_repo_url[dir]
|
||||
build.locks[repo_url]['version'] = version if repo_url
|
||||
end
|
||||
|
||||
def setup_compilers
|
||||
@@ -267,16 +269,18 @@ module MRuby
|
||||
# ~> compare algorithm
|
||||
#
|
||||
# Example:
|
||||
# ~> 2 means >= 2.0.0 and < 3.0.0
|
||||
# ~> 2.2 means >= 2.2.0 and < 3.0.0
|
||||
# ~> 2.2.0 means >= 2.2.0 and < 2.3.0
|
||||
# ~> 2.2.2 means >= 2.2.2 and < 2.3.0
|
||||
def twiddle_wakka_ok?(other)
|
||||
gr_or_eql = (self <=> other) >= 0
|
||||
still_minor = (self <=> other.skip_minor) < 0
|
||||
gr_or_eql and still_minor
|
||||
still_major_or_minor = (self <=> other.skip_major_or_minor) < 0
|
||||
gr_or_eql and still_major_or_minor
|
||||
end
|
||||
|
||||
def skip_minor
|
||||
def skip_major_or_minor
|
||||
a = @ary.dup
|
||||
a << 0 if a.size == 1 # ~> 2 can also be represented as ~> 2.0
|
||||
a.slice!(-1)
|
||||
a[-1] = a[-1].succ
|
||||
a
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
autoload :YAML, 'yaml'
|
||||
|
||||
module MRuby
|
||||
autoload :Source, 'mruby/source'
|
||||
|
||||
class Lockfile
|
||||
class << self
|
||||
def enable
|
||||
@enabled = true
|
||||
end
|
||||
|
||||
def disable
|
||||
@enabled = false
|
||||
end
|
||||
|
||||
def enabled?
|
||||
@enabled
|
||||
end
|
||||
|
||||
def build(target_name)
|
||||
instance.build(target_name)
|
||||
end
|
||||
|
||||
def write
|
||||
instance.write if enabled?
|
||||
end
|
||||
|
||||
def instance
|
||||
@instance ||= new("#{MRUBY_CONFIG}.lock")
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(filename)
|
||||
@filename = filename
|
||||
end
|
||||
|
||||
def build(target_name)
|
||||
read[target_name] ||= {}
|
||||
end
|
||||
|
||||
def write
|
||||
locks = {"mruby_version" => mruby}
|
||||
locks["builds"] = @builds if @builds
|
||||
File.write(@filename, YAML.dump(locks))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def read
|
||||
@builds ||= if File.exist?(@filename)
|
||||
YAML.load_file(@filename)["builds"] || {}
|
||||
else
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
def mruby
|
||||
mruby = {
|
||||
'version' => MRuby::Source::MRUBY_VERSION,
|
||||
'release_no' => MRuby::Source::MRUBY_RELEASE_NO,
|
||||
}
|
||||
|
||||
git_dir = "#{MRUBY_ROOT}/.git"
|
||||
if File.directory?(git_dir)
|
||||
mruby['git_commit'] = `git --git-dir '#{git_dir}' --work-tree '#{MRUBY_ROOT}' rev-parse --verify HEAD`.strip
|
||||
end
|
||||
|
||||
mruby
|
||||
end
|
||||
|
||||
enable
|
||||
end
|
||||
end
|
||||
@@ -206,25 +206,41 @@ module MiniRake
|
||||
# task with the prerequisites and actions from the rule. Set the
|
||||
# source attribute of the task appropriately for the rule. Return
|
||||
# the enhanced task or nil of no rule was found.
|
||||
def enhance_with_matching_rule(task_name)
|
||||
def enhance_with_matching_rule(task_name, level=0)
|
||||
fail "Rule Recursion Too Deep: #{task_name}" if level >= 16
|
||||
RULES.each do |pattern, extensions, block|
|
||||
if pattern.match(task_name)
|
||||
ext = extensions.first
|
||||
deps = extensions[1..-1]
|
||||
next unless pattern && pattern.match(task_name)
|
||||
sources = extensions.flat_map do |ext|
|
||||
case ext
|
||||
when /%/
|
||||
task_name.pathmap(ext)
|
||||
when %r{/}
|
||||
ext
|
||||
when /^\./
|
||||
source = task_name.sub(pattern, ext)
|
||||
source == ext ? task_name.ext(ext) : source
|
||||
when String
|
||||
source = task_name.sub(/\.[^.]*$/, ext)
|
||||
when Proc
|
||||
source = ext.call(task_name)
|
||||
ext
|
||||
when Proc, Method
|
||||
ext.arity == 1 ? ext.call(task_name) : ext.call
|
||||
else
|
||||
fail "Don't know how to handle rule dependent: #{ext.inspect}"
|
||||
end
|
||||
if File.exist?(source)
|
||||
task = FileTask.define_task({task_name => [source]+deps}, &block)
|
||||
task.source = source
|
||||
return task
|
||||
end
|
||||
prereqs = sources.map do |source|
|
||||
if File.exist?(source) || TASKS[source]
|
||||
source
|
||||
elsif parent = enhance_with_matching_rule(source, level + 1)
|
||||
parent.name
|
||||
else
|
||||
break nil
|
||||
end
|
||||
end
|
||||
if prereqs
|
||||
task = FileTask.define_task(task_name => prereqs, &block)
|
||||
task.source = prereqs.first
|
||||
return task
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
@@ -86,6 +86,9 @@ MRuby::GemBox.new do |conf|
|
||||
# Use class/module extension
|
||||
conf.gem :core => "mruby-class-ext"
|
||||
|
||||
# Use Method/UnboundMethod class
|
||||
conf.gem :core => "mruby-method"
|
||||
|
||||
# Use mruby-compiler to build other mrbgems
|
||||
conf.gem :core => "mruby-compiler"
|
||||
end
|
||||
|
||||
@@ -2,5 +2,4 @@ MRuby::Gem::Specification.new('mruby-array-ext') do |spec|
|
||||
spec.license = 'MIT'
|
||||
spec.author = 'mruby developers'
|
||||
spec.summary = 'Array class extension'
|
||||
spec.add_test_dependency 'mruby-enumerator', core: 'mruby-enumerator'
|
||||
end
|
||||
|
||||
@@ -88,6 +88,22 @@ class Array
|
||||
array
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# ary.difference(other_ary1, other_ary2, ...) -> new_ary
|
||||
#
|
||||
# Returns a new array that is a copy of the original array, removing all
|
||||
# occurrences of any item that also appear in +other_ary+. The order is
|
||||
# preserved from the original array.
|
||||
#
|
||||
def difference(*args)
|
||||
ary = self
|
||||
args.each do |x|
|
||||
ary = ary - x
|
||||
end
|
||||
ary
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# ary | other_ary -> new_ary
|
||||
@@ -157,6 +173,24 @@ class Array
|
||||
array
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# ary.intersection(other_ary,...) -> new_ary
|
||||
#
|
||||
# Set Intersection---Returns a new array containing elements common to
|
||||
# this array and <i>other_ary</i>s, removing duplicates. The order is
|
||||
# preserved from the original array.
|
||||
#
|
||||
# [1, 2, 3].intersection([3, 4, 1], [1, 3, 5]) #=> [1, 3]
|
||||
#
|
||||
def intersection(*args)
|
||||
ary = self
|
||||
args.each do |x|
|
||||
ary = ary & x
|
||||
end
|
||||
ary
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# ary.flatten -> new_ary
|
||||
@@ -815,12 +849,11 @@ class Array
|
||||
# a.permutation(0).to_a #=> [[]] # one permutation of length 0
|
||||
# a.permutation(4).to_a #=> [] # no permutations of length 4
|
||||
def permutation(n=self.size, &block)
|
||||
size = self.size
|
||||
return to_enum(:permutation, n) unless block
|
||||
return if n > size
|
||||
size = self.size
|
||||
if n == 0
|
||||
yield []
|
||||
else
|
||||
yield []
|
||||
elsif 0 < n && n <= size
|
||||
i = 0
|
||||
while i<size
|
||||
result = [self[i]]
|
||||
@@ -835,6 +868,7 @@ class Array
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
@@ -861,9 +895,8 @@ class Array
|
||||
# a.combination(5).to_a #=> [] # no combinations of length 5
|
||||
|
||||
def combination(n, &block)
|
||||
size = self.size
|
||||
return to_enum(:combination, n) unless block
|
||||
return if n > size
|
||||
size = self.size
|
||||
if n == 0
|
||||
yield []
|
||||
elsif n == 1
|
||||
@@ -872,7 +905,7 @@ class Array
|
||||
yield [self[i]]
|
||||
i += 1
|
||||
end
|
||||
else
|
||||
elsif n <= size
|
||||
i = 0
|
||||
while i<size
|
||||
result = [self[i]]
|
||||
@@ -882,6 +915,7 @@ class Array
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
@@ -903,8 +937,8 @@ class Array
|
||||
column_count = nil
|
||||
self.each do |row|
|
||||
raise TypeError unless row.is_a?(Array)
|
||||
column_count ||= row.count
|
||||
raise IndexError, 'element size differs' unless column_count == row.count
|
||||
column_count ||= row.size
|
||||
raise IndexError, 'element size differs' unless column_count == row.size
|
||||
end
|
||||
|
||||
Array.new(column_count) do |column_index|
|
||||
@@ -936,4 +970,8 @@ class Array
|
||||
end
|
||||
h
|
||||
end
|
||||
|
||||
alias append push
|
||||
alias prepend unshift
|
||||
alias filter! select!
|
||||
end
|
||||
|
||||
@@ -65,7 +65,7 @@ mrb_ary_rassoc(mrb_state *mrb, mrb_value ary)
|
||||
|
||||
for (i = 0; i < RARRAY_LEN(ary); ++i) {
|
||||
v = RARRAY_PTR(ary)[i];
|
||||
if (mrb_type(v) == MRB_TT_ARRAY &&
|
||||
if (mrb_array_p(v) &&
|
||||
RARRAY_LEN(v) > 1 &&
|
||||
mrb_equal(mrb, RARRAY_PTR(v)[1], value))
|
||||
return v;
|
||||
@@ -145,7 +145,7 @@ mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
|
||||
mrb_get_args(mrb, "o|i", &index, &len);
|
||||
switch (mrb_type(index)) {
|
||||
case MRB_TT_RANGE:
|
||||
if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == 1) {
|
||||
if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == MRB_RANGE_OK) {
|
||||
goto delete_pos_len;
|
||||
}
|
||||
else {
|
||||
@@ -194,7 +194,7 @@ mrb_mruby_array_ext_gem_init(mrb_state* mrb)
|
||||
mrb_define_method(mrb, a, "at", mrb_ary_at, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, a, "rassoc", mrb_ary_rassoc, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, a, "values_at", mrb_ary_values_at, MRB_ARGS_ANY());
|
||||
mrb_define_method(mrb, a, "slice!", mrb_ary_slice_bang, MRB_ARGS_ANY());
|
||||
mrb_define_method(mrb, a, "slice!", mrb_ary_slice_bang, MRB_ARGS_ARG(1,1));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
##
|
||||
# Array(Ext) Test
|
||||
|
||||
def assert_permutation_combination(exp, receiver, meth, *args)
|
||||
act = []
|
||||
ret = receiver.__send__(meth, *args) { |v| act << v }
|
||||
assert "assert_#{meth}" do
|
||||
assert_equal(exp, act.sort)
|
||||
assert_same(receiver, ret)
|
||||
end
|
||||
end
|
||||
|
||||
def assert_permutation(exp, receiver, *args)
|
||||
assert_permutation_combination(exp, receiver, :permutation, *args)
|
||||
end
|
||||
|
||||
def assert_combination(exp, receiver, *args)
|
||||
assert_permutation_combination(exp, receiver, :combination, *args)
|
||||
end
|
||||
|
||||
assert("Array#assoc") do
|
||||
s1 = [ "colors", "red", "blue", "green" ]
|
||||
s2 = [ "letters", "a", "b", "c" ]
|
||||
@@ -76,6 +93,14 @@ assert("Array#union") do
|
||||
assert_equal [1, 2, 3, 4, 5], a.union(b,c)
|
||||
end
|
||||
|
||||
assert("Array#difference") do
|
||||
a = [1, 2, 3, 1, 6, 7]
|
||||
b = [1, 4, 6]
|
||||
c = [1, 5, 7]
|
||||
|
||||
assert_equal [2, 3], a.difference(b,c)
|
||||
end
|
||||
|
||||
assert("Array#&") do
|
||||
a = [1, 2, 3, 1]
|
||||
b = [1, 4]
|
||||
@@ -86,6 +111,14 @@ assert("Array#&") do
|
||||
assert_equal [1, 2, 3, 1], a
|
||||
end
|
||||
|
||||
assert("Array#intersection") do
|
||||
a = [1, 2, 3, 1, 8, 6, 7, 8]
|
||||
b = [1, 4, 6, 8]
|
||||
c = [1, 5, 7, 8]
|
||||
|
||||
assert_equal [1, 8], a.intersection(b,c)
|
||||
end
|
||||
|
||||
assert("Array#flatten") do
|
||||
assert_equal [1, 2, "3", {4=>5}, :'6'], [1, 2, "3", {4=>5}, :'6'].flatten
|
||||
assert_equal [1, 2, 3, 4, 5, 6], [1, 2, [3, 4, 5], 6].flatten
|
||||
@@ -268,9 +301,9 @@ assert("Array#bsearch") do
|
||||
end
|
||||
end
|
||||
|
||||
assert("Array#bsearch_index") do
|
||||
# tested through Array#bsearch
|
||||
end
|
||||
# tested through Array#bsearch
|
||||
#assert("Array#bsearch_index") do
|
||||
#end
|
||||
|
||||
assert("Array#delete_if") do
|
||||
a = [1, 2, 3, 4, 5]
|
||||
@@ -369,30 +402,24 @@ end
|
||||
|
||||
assert("Array#permutation") do
|
||||
a = [1, 2, 3]
|
||||
assert_equal([[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]],
|
||||
a.permutation.to_a)
|
||||
assert_equal([[1],[2],[3]],
|
||||
a.permutation(1).to_a)
|
||||
assert_equal([[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]],
|
||||
a.permutation(2).to_a)
|
||||
assert_equal([[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]],
|
||||
a.permutation(3).to_a)
|
||||
assert_equal([[]], a.permutation(0).to_a)
|
||||
assert_equal([], a.permutation(4).to_a)
|
||||
assert_permutation([[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]], a)
|
||||
assert_permutation([[1],[2],[3]], a, 1)
|
||||
assert_permutation([[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]], a, 2)
|
||||
assert_permutation([[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]], a, 3)
|
||||
assert_permutation([[]], a, 0)
|
||||
assert_permutation([], a, 4)
|
||||
assert_permutation([], a, -1)
|
||||
end
|
||||
|
||||
assert("Array#combination") do
|
||||
a = [1, 2, 3, 4]
|
||||
assert_equal([[1],[2],[3],[4]],
|
||||
a.combination(1).to_a)
|
||||
assert_equal([[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]],
|
||||
a.combination(2).to_a)
|
||||
assert_equal([[1,2,3],[1,2,4],[1,3,4],[2,3,4]],
|
||||
a.combination(3).to_a)
|
||||
assert_equal([[1,2,3,4]],
|
||||
a.combination(4).to_a)
|
||||
assert_equal([[]], a.combination(0).to_a)
|
||||
assert_equal([], a.combination(5).to_a)
|
||||
assert_combination([[1],[2],[3],[4]], a, 1)
|
||||
assert_combination([[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]], a, 2)
|
||||
assert_combination([[1,2,3],[1,2,4],[1,3,4],[2,3,4]], a, 3)
|
||||
assert_combination([[1,2,3,4]], a, 4)
|
||||
assert_combination([[]], a, 0)
|
||||
assert_combination([], a, 5)
|
||||
assert_combination([], a, -1)
|
||||
end
|
||||
|
||||
assert('Array#transpose') do
|
||||
|
||||
@@ -95,7 +95,7 @@ check_file_lineno(mrb_state *mrb, struct mrb_irep *irep, const char *file, uint1
|
||||
for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
|
||||
const char *filename;
|
||||
info_file = irep->debug_info->files[f_idx];
|
||||
filename = mrb_sym2name_len(mrb, info_file->filename_sym, NULL);
|
||||
filename = mrb_sym_name_len(mrb, info_file->filename_sym, NULL);
|
||||
if (!strcmp(filename, file)) {
|
||||
result = MRB_DEBUG_BP_FILE_OK;
|
||||
|
||||
@@ -126,7 +126,7 @@ compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *cl
|
||||
mrb_debug_methodpoint *method_p;
|
||||
mrb_bool is_defined;
|
||||
|
||||
method_name = mrb_sym2name(mrb, method_sym);
|
||||
method_name = mrb_sym_name(mrb, method_sym);
|
||||
|
||||
method_p = &bp->point.methodpoint;
|
||||
if (strcmp(method_p->method_name, method_name) == 0) {
|
||||
@@ -428,7 +428,7 @@ mrb_debug_disable_break_all(mrb_state *mrb, mrb_debug_context *dbg)
|
||||
}
|
||||
|
||||
static mrb_bool
|
||||
check_start_pc_for_line(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, uint16_t line)
|
||||
check_start_pc_for_line(mrb_state *mrb, mrb_irep *irep, const mrb_code *pc, uint16_t line)
|
||||
{
|
||||
if (pc > irep->iseq) {
|
||||
if (line == mrb_debug_get_line(mrb, irep, pc - irep->iseq - 1)) {
|
||||
|
||||
@@ -33,7 +33,7 @@ mrdb_check_syntax(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size
|
||||
mrb_value
|
||||
mrb_debug_eval(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t len, mrb_bool *exc, int direct_eval)
|
||||
{
|
||||
void (*tmp)(struct mrb_state *, struct mrb_irep *, mrb_code *, mrb_value *);
|
||||
void (*tmp)(struct mrb_state *, struct mrb_irep *, const mrb_code *, mrb_value *);
|
||||
mrb_value ruby_code;
|
||||
mrb_value s;
|
||||
mrb_value v;
|
||||
@@ -74,7 +74,7 @@ mrb_debug_eval(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t
|
||||
*exc = mrb_obj_is_kind_of(mrb, v, mrb->eException_class);
|
||||
}
|
||||
|
||||
s = mrb_funcall(mrb, v, "inspect", 0);
|
||||
s = mrb_inspect(mrb, v);
|
||||
|
||||
/* enable code_fetch_hook */
|
||||
mrb->code_fetch_hook = tmp;
|
||||
|
||||
@@ -18,7 +18,6 @@ dbgcmd_print(mrb_state *mrb, mrdb_state *mrdb)
|
||||
{
|
||||
mrb_value expr;
|
||||
mrb_value result;
|
||||
mrb_value s;
|
||||
uint8_t wcnt;
|
||||
int ai;
|
||||
|
||||
@@ -39,8 +38,9 @@ dbgcmd_print(mrb_state *mrb, mrdb_state *mrdb)
|
||||
result = mrb_debug_eval(mrb, mrdb->dbg, RSTRING_PTR(expr), RSTRING_LEN(expr), NULL, 0);
|
||||
|
||||
/* $print_no = result */
|
||||
s = mrb_str_cat_lit(mrb, result, "\0");
|
||||
printf("$%lu = %s\n", (unsigned long)mrdb->print_no++, RSTRING_PTR(s));
|
||||
printf("$%lu = ", (unsigned long)mrdb->print_no++);
|
||||
fwrite(RSTRING_PTR(result), RSTRING_LEN(result), 1, stdout);
|
||||
putc('\n', stdout);
|
||||
|
||||
if (mrdb->print_no == 0) {
|
||||
mrdb->print_no = 1;
|
||||
|
||||
@@ -505,7 +505,7 @@ get_and_parse_command(mrb_state *mrb, mrdb_state *mrdb)
|
||||
}
|
||||
|
||||
static int32_t
|
||||
check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *regs)
|
||||
check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, const mrb_code *pc, mrb_value *regs)
|
||||
{
|
||||
struct RClass* c;
|
||||
mrb_sym sym;
|
||||
@@ -546,7 +546,7 @@ check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value
|
||||
}
|
||||
|
||||
static void
|
||||
mrb_code_fetch_hook(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *regs)
|
||||
mrb_code_fetch_hook(mrb_state *mrb, mrb_irep *irep, const mrb_code *pc, mrb_value *regs)
|
||||
{
|
||||
const char *file;
|
||||
int32_t line;
|
||||
|
||||
@@ -105,7 +105,7 @@ typedef struct mrb_debug_breakpoint {
|
||||
typedef struct mrb_debug_context {
|
||||
struct mrb_irep *root_irep;
|
||||
struct mrb_irep *irep;
|
||||
mrb_code *pc;
|
||||
const mrb_code *pc;
|
||||
mrb_value *regs;
|
||||
|
||||
const char *prvfile;
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
#ifndef MRDBCONF_H
|
||||
#define MRDBCONF_H
|
||||
|
||||
#ifndef MRB_ENABLE_DEBUG_HOOK
|
||||
# error Need 'MRB_ENABLE_DEBUG_HOOK' configuration in your 'build_config.rb'
|
||||
#endif
|
||||
|
||||
/* configuration options: */
|
||||
/* maximum size for command buffer */
|
||||
#define MAX_COMMAND_LINE 1024
|
||||
|
||||
@@ -240,7 +240,7 @@ usage(const char *name)
|
||||
};
|
||||
const char *const *p = usage_msg;
|
||||
|
||||
printf("Usage: %s [switches]\n", name);
|
||||
printf("Usage: %s [switches] [programfile] [arguments]\n", name);
|
||||
while (*p)
|
||||
printf(" %s\n", *p++);
|
||||
}
|
||||
@@ -406,6 +406,26 @@ ctrl_c_handler(int signo)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_MIRB_UNDERSCORE
|
||||
void decl_lv_underscore(mrb_state *mrb, mrbc_context *cxt)
|
||||
{
|
||||
struct RProc *proc;
|
||||
struct mrb_parser_state *parser;
|
||||
|
||||
parser = mrb_parse_string(mrb, "_=nil", cxt);
|
||||
if (parser == NULL) {
|
||||
fputs("create parser state error\n", stderr);
|
||||
mrb_close(mrb);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
proc = mrb_generate_code(mrb, parser);
|
||||
mrb_vm_run(mrb, proc, mrb_top_self(mrb), 0);
|
||||
|
||||
mrb_parser_free(parser);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@@ -471,6 +491,10 @@ main(int argc, char **argv)
|
||||
|
||||
cxt = mrbc_context_new(mrb);
|
||||
|
||||
#ifndef DISABLE_MIRB_UNDERSCORE
|
||||
decl_lv_underscore(mrb, cxt);
|
||||
#endif
|
||||
|
||||
/* Load libraries */
|
||||
for (i = 0; i < args.libc; i++) {
|
||||
FILE *lfp = fopen(args.libv[i], "r");
|
||||
@@ -643,6 +667,9 @@ main(int argc, char **argv)
|
||||
result = mrb_any_to_s(mrb, result);
|
||||
}
|
||||
p(mrb, result, 1);
|
||||
#ifndef DISABLE_MIRB_UNDERSCORE
|
||||
*(mrb->c->stack + 1) = result;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
ruby_code[0] = '\0';
|
||||
|
||||
@@ -71,7 +71,6 @@ get_outfilename(mrb_state *mrb, char *infile, const char *ext)
|
||||
static int
|
||||
parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
|
||||
{
|
||||
char *outfile = NULL;
|
||||
static const struct mrbc_args args_zero = { 0 };
|
||||
int i;
|
||||
|
||||
@@ -86,7 +85,7 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
|
||||
case 'o':
|
||||
if (args->outfile) {
|
||||
fprintf(stderr, "%s: an output file is already specified. (%s)\n",
|
||||
args->prog, outfile);
|
||||
args->prog, args->outfile);
|
||||
return -1;
|
||||
}
|
||||
if (argv[i][2] == '\0' && argv[i+1]) {
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
require 'tempfile'
|
||||
require 'open3'
|
||||
|
||||
def assert_mruby(exp_out, exp_err, exp_success, args)
|
||||
out, err, stat = Open3.capture3(cmd("mruby"), *args)
|
||||
assert "assert_mruby" do
|
||||
assert_operator(exp_out, :===, out, "standard output")
|
||||
assert_operator(exp_err, :===, err, "standard error")
|
||||
assert_equal(exp_success, stat.success?, "exit success?")
|
||||
end
|
||||
end
|
||||
|
||||
assert('regression for #1564') do
|
||||
o = `#{cmd('mruby')} -e #{shellquote('<<')} 2>&1`
|
||||
assert_include o, "-e:1:2: syntax error"
|
||||
o = `#{cmd('mruby')} -e #{shellquote('<<-')} 2>&1`
|
||||
assert_include o, "-e:1:3: syntax error"
|
||||
assert_mruby("", /\A-e:1:2: syntax error, .*\n\z/, false, %w[-e <<])
|
||||
assert_mruby("", /\A-e:1:3: syntax error, .*\n\z/, false, %w[-e <<-])
|
||||
end
|
||||
|
||||
assert('regression for #1572') do
|
||||
@@ -66,6 +74,11 @@ RUBY
|
||||
assert_equal 0, $?.exitstatus
|
||||
end
|
||||
|
||||
assert('mruby -c option') do
|
||||
assert_mruby("Syntax OK\n", "", true, ["-c", "-e", "p 1"])
|
||||
assert_mruby("", /\A-e:1:7: syntax error, .*\n\z/, false, ["-c", "-e", "p 1; 1."])
|
||||
end
|
||||
|
||||
assert('mruby -d option') do
|
||||
o = `#{cmd('mruby')} -e #{shellquote('p $DEBUG')}`
|
||||
assert_equal "false\n", o
|
||||
@@ -73,6 +86,14 @@ assert('mruby -d option') do
|
||||
assert_equal "true\n", o
|
||||
end
|
||||
|
||||
assert('mruby -e option (no code specified)') do
|
||||
assert_mruby("", /\A.*: No code specified for -e\n\z/, false, %w[-e])
|
||||
end
|
||||
|
||||
assert('mruby -h option') do
|
||||
assert_mruby(/\AUsage: #{Regexp.escape cmd("mruby")} .*/m, "", true, %w[-h])
|
||||
end
|
||||
|
||||
assert('mruby -r option') do
|
||||
lib = Tempfile.new('lib.rb')
|
||||
lib.write <<EOS
|
||||
@@ -95,3 +116,32 @@ EOS
|
||||
assert_equal 'hogeClass', `#{cmd('mruby')} -r #{lib.path} -r #{script.path} -e #{shellquote('print Hoge.class')}`
|
||||
assert_equal 0, $?.exitstatus
|
||||
end
|
||||
|
||||
assert('mruby -r option (no library specified)') do
|
||||
assert_mruby("", /\A.*: No library specified for -r\n\z/, false, %w[-r])
|
||||
end
|
||||
|
||||
assert('mruby -r option (file not found)') do
|
||||
assert_mruby("", /\A.*: Cannot open library file: .*\n\z/, false, %w[-r _no_exists_])
|
||||
end
|
||||
|
||||
assert('mruby invalid short option') do
|
||||
assert_mruby("", /\A.*: invalid option -1 .*\n\z/, false, %w[-1])
|
||||
end
|
||||
|
||||
assert('mruby invalid long option') do
|
||||
assert_mruby("", /\A.*: invalid option --longopt .*\n\z/, false, %w[--longopt])
|
||||
end
|
||||
|
||||
assert('unhandled exception') do
|
||||
assert_mruby("", /\bEXCEPTION\b.*\n\z/, false, %w[-e raise("EXCEPTION")])
|
||||
end
|
||||
|
||||
assert('program file not found') do
|
||||
assert_mruby("", /\A.*: Cannot open program file: .*\n\z/, false, %w[_no_exists_])
|
||||
end
|
||||
|
||||
assert('codegen error') do
|
||||
code = "def f(#{(1..100).map{|n| "a#{n}"} * ","}); end"
|
||||
assert_mruby("", /\Acodegen error:.*\n\z/, false, ["-e", code])
|
||||
end
|
||||
|
||||
@@ -7,19 +7,6 @@
|
||||
#include <mruby/dump.h>
|
||||
#include <mruby/variable.h>
|
||||
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
static void
|
||||
p(mrb_state *mrb, mrb_value obj)
|
||||
{
|
||||
mrb_value val = mrb_inspect(mrb, obj);
|
||||
|
||||
fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout);
|
||||
putc('\n', stdout);
|
||||
}
|
||||
#else
|
||||
#define p(mrb,obj) mrb_p(mrb,obj)
|
||||
#endif
|
||||
|
||||
struct _args {
|
||||
FILE *rfp;
|
||||
char* cmdline;
|
||||
@@ -52,7 +39,7 @@ usage(const char *name)
|
||||
};
|
||||
const char *const *p = usage_msg;
|
||||
|
||||
printf("Usage: %s [switches] programfile\n", name);
|
||||
printf("Usage: %s [switches] [programfile] [arguments]\n", name);
|
||||
while (*p)
|
||||
printf(" %s\n", *p++);
|
||||
}
|
||||
@@ -119,14 +106,17 @@ append_cmdline:
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("%s: No code specified for -e\n", *origargv);
|
||||
return EXIT_SUCCESS;
|
||||
fprintf(stderr, "%s: No code specified for -e\n", *origargv);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
usage(*origargv);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'r':
|
||||
if (!item[0]) {
|
||||
if (argc <= 1) {
|
||||
printf("%s: No library specified for -r\n", *origargv);
|
||||
fprintf(stderr, "%s: No library specified for -r\n", *origargv);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
argc--; argv++;
|
||||
@@ -158,6 +148,7 @@ append_cmdline:
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "%s: invalid option %s (-h will show valid options)\n", *origargv, *argv);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
@@ -167,7 +158,7 @@ append_cmdline:
|
||||
else {
|
||||
args->rfp = fopen(argv[0], args->mrbfile ? "rb" : "r");
|
||||
if (args->rfp == NULL) {
|
||||
printf("%s: Cannot open program file. (%s)\n", *origargv, *argv);
|
||||
fprintf(stderr, "%s: Cannot open program file: %s\n", *origargv, *argv);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
args->fname = TRUE;
|
||||
@@ -212,14 +203,13 @@ main(int argc, char **argv)
|
||||
mrb_sym zero_sym;
|
||||
|
||||
if (mrb == NULL) {
|
||||
fputs("Invalid mrb_state, exiting mruby\n", stderr);
|
||||
fprintf(stderr, "%s: Invalid mrb_state, exiting mruby\n", *argv);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
n = parse_args(mrb, argc, argv, &args);
|
||||
if (n == EXIT_FAILURE || (args.cmdline == NULL && args.rfp == NULL)) {
|
||||
cleanup(mrb, &args);
|
||||
usage(argv[0]);
|
||||
return n;
|
||||
}
|
||||
else {
|
||||
@@ -258,7 +248,7 @@ main(int argc, char **argv)
|
||||
for (i = 0; i < args.libc; i++) {
|
||||
FILE *lfp = fopen(args.libv[i], args.mrbfile ? "rb" : "r");
|
||||
if (lfp == NULL) {
|
||||
printf("Cannot open library file: %s\n", args.libv[i]);
|
||||
fprintf(stderr, "%s: Cannot open library file: %s\n", *argv, args.libv[i]);
|
||||
mrbc_context_free(mrb, c);
|
||||
cleanup(mrb, &args);
|
||||
return EXIT_FAILURE;
|
||||
@@ -289,19 +279,16 @@ main(int argc, char **argv)
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
mrbc_context_free(mrb, c);
|
||||
if (mrb->exc) {
|
||||
if (mrb_undef_p(v)) {
|
||||
mrb_p(mrb, mrb_obj_value(mrb->exc));
|
||||
}
|
||||
else {
|
||||
if (!mrb_undef_p(v)) {
|
||||
mrb_print_error(mrb);
|
||||
}
|
||||
n = -1;
|
||||
n = EXIT_FAILURE;
|
||||
}
|
||||
else if (args.check_syntax) {
|
||||
printf("Syntax OK\n");
|
||||
puts("Syntax OK");
|
||||
}
|
||||
}
|
||||
cleanup(mrb, &args);
|
||||
|
||||
return n == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -5,14 +5,13 @@
|
||||
static mrb_value
|
||||
mrb_mod_name(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value name = mrb_class_path(mrb, mrb_class_ptr(self));
|
||||
return mrb_nil_p(name)? name : mrb_str_dup(mrb, name);
|
||||
return mrb_class_path(mrb, mrb_class_ptr(self));
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_mod_singleton_class_p(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
return mrb_bool_value(mrb_type(self) == MRB_TT_SCLASS);
|
||||
return mrb_bool_value(mrb_sclass_p(self));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -41,11 +40,7 @@ mrb_mod_module_exec(mrb_state *mrb, mrb_value self)
|
||||
mrb_int argc;
|
||||
mrb_value blk;
|
||||
|
||||
mrb_get_args(mrb, "*&", &argv, &argc, &blk);
|
||||
|
||||
if (mrb_nil_p(blk)) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
|
||||
}
|
||||
mrb_get_args(mrb, "*&!", &argv, &argc, &blk);
|
||||
|
||||
mrb->c->ci->target_class = mrb_class_ptr(self);
|
||||
return mrb_yield_cont(mrb, blk, self, argc, argv);
|
||||
|
||||
@@ -102,12 +102,13 @@ codegen_error(codegen_scope *s, const char *message)
|
||||
while (s->prev) {
|
||||
codegen_scope *tmp = s->prev;
|
||||
mrb_free(s->mrb, s->iseq);
|
||||
mrb_free(s->mrb, s->lines);
|
||||
mrb_pool_close(s->mpool);
|
||||
s = tmp;
|
||||
}
|
||||
#ifndef MRB_DISABLE_STDIO
|
||||
if (s->filename_sym && s->lineno) {
|
||||
const char *filename = mrb_sym2name_len(s->mrb, s->filename_sym, NULL);
|
||||
const char *filename = mrb_sym_name_len(s->mrb, s->filename_sym, NULL);
|
||||
fprintf(stderr, "codegen error:%s:%d: %s\n", filename, s->lineno, message);
|
||||
}
|
||||
else {
|
||||
@@ -272,8 +273,7 @@ genop_W(codegen_scope *s, mrb_code i, uint32_t a)
|
||||
#define NOVAL 0
|
||||
#define VAL 1
|
||||
|
||||
//static
|
||||
mrb_bool
|
||||
static mrb_bool
|
||||
no_optimize(codegen_scope *s)
|
||||
{
|
||||
if (s && s->parser && s->parser->no_optimize)
|
||||
@@ -291,7 +291,7 @@ on_eval(codegen_scope *s)
|
||||
}
|
||||
|
||||
struct mrb_insn_data
|
||||
mrb_decode_insn(mrb_code *pc)
|
||||
mrb_decode_insn(const mrb_code *pc)
|
||||
{
|
||||
struct mrb_insn_data data = { 0 };
|
||||
mrb_code insn = READ_B();
|
||||
@@ -559,7 +559,7 @@ new_lit(codegen_scope *s, mrb_value val)
|
||||
mrb_int len;
|
||||
pv = &s->irep->pool[i];
|
||||
|
||||
if (mrb_type(*pv) != MRB_TT_STRING) continue;
|
||||
if (!mrb_string_p(*pv)) continue;
|
||||
if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue;
|
||||
if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0)
|
||||
return i;
|
||||
@@ -570,7 +570,7 @@ new_lit(codegen_scope *s, mrb_value val)
|
||||
for (i=0; i<s->irep->plen; i++) {
|
||||
mrb_float f1, f2;
|
||||
pv = &s->irep->pool[i];
|
||||
if (mrb_type(*pv) != MRB_TT_FLOAT) continue;
|
||||
if (!mrb_float_p(*pv)) continue;
|
||||
f1 = mrb_float(*pv);
|
||||
f2 = mrb_float(val);
|
||||
if (f1 == f2 && !signbit(f1) == !signbit(f2)) return i;
|
||||
@@ -686,9 +686,6 @@ for_body(codegen_scope *s, node *tree)
|
||||
codegen(s, tree->cdr->car, VAL);
|
||||
/* generate loop-block */
|
||||
s = scope_new(s->mrb, s, NULL);
|
||||
if (s == NULL) {
|
||||
raise_error(prev, "unexpected scope");
|
||||
}
|
||||
|
||||
push(); /* push for a block parameter */
|
||||
|
||||
@@ -724,9 +721,6 @@ lambda_body(codegen_scope *s, node *tree, int blk)
|
||||
{
|
||||
codegen_scope *parent = s;
|
||||
s = scope_new(s->mrb, s, tree->car);
|
||||
if (s == NULL) {
|
||||
raise_error(parent, "unexpected scope");
|
||||
}
|
||||
|
||||
s->mscope = !blk;
|
||||
|
||||
@@ -888,9 +882,6 @@ static int
|
||||
scope_body(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
codegen_scope *scope = scope_new(s->mrb, s, tree->car);
|
||||
if (scope == NULL) {
|
||||
codegen_error(s, "unexpected scope");
|
||||
}
|
||||
|
||||
codegen(scope, tree->cdr, VAL);
|
||||
gen_return(scope, OP_RETURN, scope->sp-1);
|
||||
@@ -922,7 +913,7 @@ attrsym(codegen_scope *s, mrb_sym a)
|
||||
mrb_int len;
|
||||
char *name2;
|
||||
|
||||
name = mrb_sym2name_len(s->mrb, a, &len);
|
||||
name = mrb_sym_name_len(s->mrb, a, &len);
|
||||
name2 = (char *)codegen_palloc(s,
|
||||
(size_t)len
|
||||
+ 1 /* '=' */
|
||||
@@ -956,7 +947,12 @@ gen_values(codegen_scope *s, node *t, int val, int extra)
|
||||
}
|
||||
else {
|
||||
pop_n(n);
|
||||
genop_2(s, OP_ARRAY, cursp(), n);
|
||||
if (n == 0 && is_splat) {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
}
|
||||
else {
|
||||
genop_2(s, OP_ARRAY, cursp(), n);
|
||||
}
|
||||
push();
|
||||
codegen(s, t->car, VAL);
|
||||
pop(); pop();
|
||||
@@ -1041,7 +1037,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
|
||||
pop_n(n+1);
|
||||
{
|
||||
mrb_int symlen;
|
||||
const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen);
|
||||
const char *symname = mrb_sym_name_len(s->mrb, sym, &symlen);
|
||||
|
||||
if (!noop && symlen == 1 && symname[0] == '+' && n == 1) {
|
||||
gen_addsub(s, OP_ADD, cursp());
|
||||
@@ -1401,7 +1397,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
}
|
||||
if (s->irep && s->filename_index != tree->filename_index) {
|
||||
mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
|
||||
const char *filename = mrb_sym2name_len(s->mrb, fname, NULL);
|
||||
const char *filename = mrb_sym_name_len(s->mrb, fname, NULL);
|
||||
|
||||
mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
|
||||
filename, s->lines, s->debug_start_pos, s->pc);
|
||||
@@ -1553,7 +1549,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
|
||||
case NODE_IF:
|
||||
{
|
||||
int pos1, pos2;
|
||||
int pos1, pos2, nil_p = FALSE;
|
||||
node *elsepart = tree->cdr->cdr->car;
|
||||
|
||||
if (!tree->car) {
|
||||
@@ -1570,32 +1566,59 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
case NODE_NIL:
|
||||
codegen(s, elsepart, val);
|
||||
goto exit;
|
||||
case NODE_CALL:
|
||||
{
|
||||
node *n = tree->car->cdr;
|
||||
mrb_sym mid = nsym(n->cdr->car);
|
||||
mrb_sym mnil = mrb_intern_lit(s->mrb, "nil?");
|
||||
if (mid == mnil && n->cdr->cdr->car == NULL) {
|
||||
nil_p = TRUE;
|
||||
codegen(s, n->car, VAL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!nil_p) {
|
||||
codegen(s, tree->car, VAL);
|
||||
}
|
||||
codegen(s, tree->car, VAL);
|
||||
pop();
|
||||
pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
|
||||
|
||||
codegen(s, tree->cdr->car, val);
|
||||
if (elsepart) {
|
||||
if (val || tree->cdr->car) {
|
||||
if (nil_p) {
|
||||
pos2 = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
|
||||
pos1 = genjmp(s, OP_JMP, 0);
|
||||
dispatch(s, pos2);
|
||||
}
|
||||
else {
|
||||
pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
|
||||
}
|
||||
codegen(s, tree->cdr->car, val);
|
||||
if (val) pop();
|
||||
pos2 = genjmp(s, OP_JMP, 0);
|
||||
dispatch(s, pos1);
|
||||
codegen(s, elsepart, val);
|
||||
dispatch(s, pos2);
|
||||
}
|
||||
else {
|
||||
if (val) {
|
||||
pop();
|
||||
if (elsepart || val) {
|
||||
pos2 = genjmp(s, OP_JMP, 0);
|
||||
dispatch(s, pos1);
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
codegen(s, elsepart, val);
|
||||
dispatch(s, pos2);
|
||||
push();
|
||||
}
|
||||
else {
|
||||
dispatch(s, pos1);
|
||||
}
|
||||
}
|
||||
else { /* empty then-part */
|
||||
if (elsepart) {
|
||||
if (nil_p) {
|
||||
pos1 = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
|
||||
}
|
||||
else {
|
||||
pos1 = genjmp2(s, OP_JMPIF, cursp(), 0, val);
|
||||
}
|
||||
codegen(s, elsepart, val);
|
||||
dispatch(s, pos1);
|
||||
}
|
||||
else if (val && !nil_p) {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
push();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1955,7 +1978,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
mrb_sym sym = nsym(tree->cdr->car);
|
||||
mrb_int len;
|
||||
const char *name = mrb_sym2name_len(s->mrb, sym, &len);
|
||||
const char *name = mrb_sym_name_len(s->mrb, sym, &len);
|
||||
int idx, callargs = -1, vsp = -1;
|
||||
|
||||
if ((len == 2 && name[0] == '|' && name[1] == '|') &&
|
||||
@@ -2353,10 +2376,6 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_DEFINED:
|
||||
codegen(s, tree, val);
|
||||
break;
|
||||
|
||||
case NODE_BACK_REF:
|
||||
if (val) {
|
||||
char buf[] = {'$', nchar(tree)};
|
||||
@@ -2373,7 +2392,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
mrb_value str;
|
||||
int sym;
|
||||
|
||||
str = mrb_format(mrb, "$%S", mrb_fixnum_value(nint(tree)));
|
||||
str = mrb_format(mrb, "$%d", nint(tree));
|
||||
sym = new_sym(s, mrb_intern_str(mrb, str));
|
||||
genop_2(s, OP_GETGV, cursp(), sym);
|
||||
push();
|
||||
@@ -2944,7 +2963,11 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
|
||||
mrb_pool *pool = mrb_pool_open(mrb);
|
||||
codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope));
|
||||
|
||||
if (!p) return NULL;
|
||||
if (!p) {
|
||||
if (prev)
|
||||
codegen_error(prev, "unexpected scope");
|
||||
return NULL;
|
||||
}
|
||||
*p = codegen_scope_zero;
|
||||
p->mrb = mrb;
|
||||
p->mpool = pool;
|
||||
@@ -3020,6 +3043,9 @@ scope_finish(codegen_scope *s)
|
||||
mrb_state *mrb = s->mrb;
|
||||
mrb_irep *irep = s->irep;
|
||||
|
||||
if (s->nlocals >= 0x3ff) {
|
||||
codegen_error(s, "too many local variables");
|
||||
}
|
||||
irep->flags = 0;
|
||||
if (s->iseq) {
|
||||
irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
|
||||
@@ -3030,7 +3056,7 @@ scope_finish(codegen_scope *s)
|
||||
irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
|
||||
if (s->filename_sym) {
|
||||
mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
|
||||
const char *filename = mrb_sym2name_len(s->mrb, fname, NULL);
|
||||
const char *filename = mrb_sym_name_len(s->mrb, fname, NULL);
|
||||
|
||||
mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
|
||||
filename, s->lines, s->debug_start_pos, s->pc);
|
||||
@@ -3134,9 +3160,6 @@ generate_code(mrb_state *mrb, parser_state *p, int val)
|
||||
struct RProc *proc;
|
||||
struct mrb_jmpbuf *prev_jmp = mrb->jmp;
|
||||
|
||||
if (!scope) {
|
||||
return NULL;
|
||||
}
|
||||
scope->mrb = mrb;
|
||||
scope->parser = p;
|
||||
scope->filename_sym = p->filename_sym;
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
%{
|
||||
struct kwtable {const char *name; int id[2]; enum mrb_lex_state_enum state;};
|
||||
const struct kwtable *mrb_reserved_word(const char *, unsigned int);
|
||||
static const struct kwtable *reserved_word(const char *, unsigned int);
|
||||
#define mrb_reserved_word(str, len) reserved_word(str, len)
|
||||
%}
|
||||
|
||||
struct kwtable;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* ANSI-C code produced by gperf version 3.0.4 */
|
||||
/* ANSI-C code produced by gperf version 3.1 */
|
||||
/* Command-line: gperf -L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k'1,3,$' /home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords */
|
||||
|
||||
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
|
||||
@@ -25,16 +25,13 @@
|
||||
&& ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
|
||||
&& ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
|
||||
/* The character set is not based on ISO-646. */
|
||||
#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
|
||||
#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>."
|
||||
#endif
|
||||
|
||||
#line 1 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
|
||||
struct kwtable {const char *name; int id[2]; enum mrb_lex_state_enum state;};
|
||||
const struct kwtable *mrb_reserved_word(const char *, unsigned int);
|
||||
static const struct kwtable *reserved_word(const char *, unsigned int);
|
||||
#define mrb_reserved_word(str, len) reserved_word(str, len)
|
||||
#line 8 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
#line 5 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
struct kwtable;
|
||||
|
||||
#define TOTAL_KEYWORDS 40
|
||||
@@ -52,7 +49,7 @@ inline
|
||||
#endif
|
||||
#endif
|
||||
static unsigned int
|
||||
hash (const char *str, unsigned int len)
|
||||
hash (register const char *str, register size_t len)
|
||||
{
|
||||
static const unsigned char asso_values[] =
|
||||
{
|
||||
@@ -83,7 +80,7 @@ hash (const char *str, unsigned int len)
|
||||
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
|
||||
51, 51, 51, 51, 51, 51
|
||||
};
|
||||
int hval = len;
|
||||
register unsigned int hval = len;
|
||||
|
||||
switch (hval)
|
||||
{
|
||||
@@ -98,109 +95,103 @@ hash (const char *str, unsigned int len)
|
||||
return hval + asso_values[(unsigned char)str[len - 1]];
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
|
||||
__attribute__ ((__gnu_inline__))
|
||||
#endif
|
||||
#endif
|
||||
const struct kwtable *
|
||||
mrb_reserved_word (const char *str, unsigned int len)
|
||||
mrb_reserved_word (register const char *str, register size_t len)
|
||||
{
|
||||
static const struct kwtable wordlist[] =
|
||||
{
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
#line 18 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"break", {keyword_break, keyword_break}, EXPR_MID},
|
||||
#line 23 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"else", {keyword_else, keyword_else}, EXPR_BEG},
|
||||
#line 33 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"nil", {keyword_nil, keyword_nil}, EXPR_END},
|
||||
#line 26 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"ensure", {keyword_ensure, keyword_ensure}, EXPR_BEG},
|
||||
#line 25 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"end", {keyword_end, keyword_end}, EXPR_END},
|
||||
#line 42 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"then", {keyword_then, keyword_then}, EXPR_BEG},
|
||||
#line 34 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"not", {keyword_not, keyword_not}, EXPR_ARG},
|
||||
#line 27 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"false", {keyword_false, keyword_false}, EXPR_END},
|
||||
#line 40 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"self", {keyword_self, keyword_self}, EXPR_END},
|
||||
#line 24 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"elsif", {keyword_elsif, keyword_elsif}, EXPR_VALUE},
|
||||
#line 37 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"rescue", {keyword_rescue, modifier_rescue}, EXPR_MID},
|
||||
#line 43 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"true", {keyword_true, keyword_true}, EXPR_END},
|
||||
#line 46 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"until", {keyword_until, modifier_until}, EXPR_VALUE},
|
||||
#line 45 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"unless", {keyword_unless, modifier_unless}, EXPR_VALUE},
|
||||
#line 39 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"return", {keyword_return, keyword_return}, EXPR_MID},
|
||||
#line 21 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"def", {keyword_def, keyword_def}, EXPR_FNAME},
|
||||
#line 16 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"and", {keyword_and, keyword_and}, EXPR_VALUE},
|
||||
#line 22 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"do", {keyword_do, keyword_do}, EXPR_BEG},
|
||||
#line 49 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"yield", {keyword_yield, keyword_yield}, EXPR_ARG},
|
||||
#line 28 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"for", {keyword_for, keyword_for}, EXPR_VALUE},
|
||||
#line 44 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"undef", {keyword_undef, keyword_undef}, EXPR_FNAME},
|
||||
#line 35 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"or", {keyword_or, keyword_or}, EXPR_VALUE},
|
||||
#line 30 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"in", {keyword_in, keyword_in}, EXPR_VALUE},
|
||||
#line 47 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"when", {keyword_when, keyword_when}, EXPR_VALUE},
|
||||
#line 38 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"retry", {keyword_retry, keyword_retry}, EXPR_END},
|
||||
#line 29 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"if", {keyword_if, modifier_if}, EXPR_VALUE},
|
||||
#line 19 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"case", {keyword_case, keyword_case}, EXPR_VALUE},
|
||||
#line 36 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"redo", {keyword_redo, keyword_redo}, EXPR_END},
|
||||
#line 32 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"next", {keyword_next, keyword_next}, EXPR_MID},
|
||||
#line 41 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"super", {keyword_super, keyword_super}, EXPR_ARG},
|
||||
#line 31 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"module", {keyword_module, keyword_module}, EXPR_VALUE},
|
||||
#line 17 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"begin", {keyword_begin, keyword_begin}, EXPR_BEG},
|
||||
#line 12 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"__LINE__", {keyword__LINE__, keyword__LINE__}, EXPR_END},
|
||||
#line 11 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"__FILE__", {keyword__FILE__, keyword__FILE__}, EXPR_END},
|
||||
#line 10 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"__ENCODING__", {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END},
|
||||
#line 14 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"END", {keyword_END, keyword_END}, EXPR_END},
|
||||
#line 15 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"alias", {keyword_alias, keyword_alias}, EXPR_FNAME},
|
||||
{"break", {keyword_break, keyword_break}, EXPR_MID},
|
||||
#line 20 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"else", {keyword_else, keyword_else}, EXPR_BEG},
|
||||
#line 30 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"nil", {keyword_nil, keyword_nil}, EXPR_END},
|
||||
#line 23 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"ensure", {keyword_ensure, keyword_ensure}, EXPR_BEG},
|
||||
#line 22 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"end", {keyword_end, keyword_end}, EXPR_END},
|
||||
#line 39 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"then", {keyword_then, keyword_then}, EXPR_BEG},
|
||||
#line 31 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"not", {keyword_not, keyword_not}, EXPR_ARG},
|
||||
#line 24 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"false", {keyword_false, keyword_false}, EXPR_END},
|
||||
#line 37 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"self", {keyword_self, keyword_self}, EXPR_END},
|
||||
#line 21 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"elsif", {keyword_elsif, keyword_elsif}, EXPR_VALUE},
|
||||
#line 34 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"rescue", {keyword_rescue, modifier_rescue}, EXPR_MID},
|
||||
#line 40 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"true", {keyword_true, keyword_true}, EXPR_END},
|
||||
#line 43 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"until", {keyword_until, modifier_until}, EXPR_VALUE},
|
||||
#line 42 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"unless", {keyword_unless, modifier_unless}, EXPR_VALUE},
|
||||
#line 36 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"return", {keyword_return, keyword_return}, EXPR_MID},
|
||||
#line 18 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"def", {keyword_def, keyword_def}, EXPR_FNAME},
|
||||
#line 13 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"and", {keyword_and, keyword_and}, EXPR_VALUE},
|
||||
#line 19 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"do", {keyword_do, keyword_do}, EXPR_BEG},
|
||||
#line 46 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"yield", {keyword_yield, keyword_yield}, EXPR_ARG},
|
||||
#line 25 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"for", {keyword_for, keyword_for}, EXPR_VALUE},
|
||||
#line 41 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"undef", {keyword_undef, keyword_undef}, EXPR_FNAME},
|
||||
#line 32 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"or", {keyword_or, keyword_or}, EXPR_VALUE},
|
||||
#line 27 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"in", {keyword_in, keyword_in}, EXPR_VALUE},
|
||||
#line 44 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"when", {keyword_when, keyword_when}, EXPR_VALUE},
|
||||
#line 35 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"retry", {keyword_retry, keyword_retry}, EXPR_END},
|
||||
#line 26 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"if", {keyword_if, modifier_if}, EXPR_VALUE},
|
||||
#line 16 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"case", {keyword_case, keyword_case}, EXPR_VALUE},
|
||||
#line 33 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"redo", {keyword_redo, keyword_redo}, EXPR_END},
|
||||
#line 29 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"next", {keyword_next, keyword_next}, EXPR_MID},
|
||||
#line 38 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"super", {keyword_super, keyword_super}, EXPR_ARG},
|
||||
#line 28 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"module", {keyword_module, keyword_module}, EXPR_VALUE},
|
||||
#line 14 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"begin", {keyword_begin, keyword_begin}, EXPR_BEG},
|
||||
#line 9 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"__LINE__", {keyword__LINE__, keyword__LINE__}, EXPR_END},
|
||||
#line 8 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"__FILE__", {keyword__FILE__, keyword__FILE__}, EXPR_END},
|
||||
#line 7 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"__ENCODING__", {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END},
|
||||
#line 11 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"END", {keyword_END, keyword_END}, EXPR_END},
|
||||
#line 12 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"alias", {keyword_alias, keyword_alias}, EXPR_FNAME},
|
||||
#line 10 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"BEGIN", {keyword_BEGIN, keyword_BEGIN}, EXPR_END},
|
||||
{""},
|
||||
#line 20 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
#line 17 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"class", {keyword_class, keyword_class}, EXPR_CLASS},
|
||||
{""}, {""},
|
||||
#line 48 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
#line 45 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
{"while", {keyword_while, modifier_while}, EXPR_VALUE}
|
||||
};
|
||||
|
||||
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
||||
{
|
||||
int key = hash (str, len);
|
||||
register unsigned int key = hash (str, len);
|
||||
|
||||
if (key <= MAX_HASH_VALUE && key >= 0)
|
||||
if (key <= MAX_HASH_VALUE)
|
||||
{
|
||||
const char *s = wordlist[key].name;
|
||||
register const char *s = wordlist[key].name;
|
||||
|
||||
if (*str == *s && !strcmp (str + 1, s + 1))
|
||||
return &wordlist[key];
|
||||
@@ -208,4 +199,5 @@ mrb_reserved_word (const char *str, unsigned int len)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#line 50 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
#line 47 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||
|
||||
|
||||
+400
-158
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
MRuby::Gem::Specification.new('mruby-complex') do |spec|
|
||||
spec.license = 'MIT'
|
||||
spec.author = 'mruby developers'
|
||||
spec.summary = 'Complex class'
|
||||
|
||||
spec.add_dependency 'mruby-metaprog', core: 'mruby-metaprog'
|
||||
spec.add_dependency 'mruby-object-ext', core: 'mruby-object-ext'
|
||||
spec.add_dependency 'mruby-numeric-ext', core: 'mruby-numeric-ext'
|
||||
spec.add_dependency 'mruby-math', core: 'mruby-math'
|
||||
end
|
||||
@@ -0,0 +1,122 @@
|
||||
class Complex < Numeric
|
||||
def self.polar(abs, arg = 0)
|
||||
Complex(abs * Math.cos(arg), abs * Math.sin(arg))
|
||||
end
|
||||
|
||||
def inspect
|
||||
"(#{to_s})"
|
||||
end
|
||||
|
||||
def to_s
|
||||
"#{real}#{'+' unless imaginary.negative?}#{imaginary}i"
|
||||
end
|
||||
|
||||
def +@
|
||||
Complex(real, imaginary)
|
||||
end
|
||||
|
||||
def -@
|
||||
Complex(-real, -imaginary)
|
||||
end
|
||||
|
||||
def +(rhs)
|
||||
if rhs.is_a? Complex
|
||||
Complex(real + rhs.real, imaginary + rhs.imaginary)
|
||||
elsif rhs.is_a? Numeric
|
||||
Complex(real + rhs, imaginary)
|
||||
end
|
||||
end
|
||||
|
||||
def -(rhs)
|
||||
if rhs.is_a? Complex
|
||||
Complex(real - rhs.real, imaginary - rhs.imaginary)
|
||||
elsif rhs.is_a? Numeric
|
||||
Complex(real - rhs, imaginary)
|
||||
end
|
||||
end
|
||||
|
||||
def *(rhs)
|
||||
if rhs.is_a? Complex
|
||||
Complex(real * rhs.real - imaginary * rhs.imaginary, real * rhs.imaginary + rhs.real * imaginary)
|
||||
elsif rhs.is_a? Numeric
|
||||
Complex(real * rhs, imaginary * rhs)
|
||||
end
|
||||
end
|
||||
|
||||
def /(rhs)
|
||||
if rhs.is_a? Complex
|
||||
__div__(rhs)
|
||||
elsif rhs.is_a? Numeric
|
||||
Complex(real / rhs, imaginary / rhs)
|
||||
end
|
||||
end
|
||||
alias_method :quo, :/
|
||||
|
||||
def ==(rhs)
|
||||
if rhs.is_a? Complex
|
||||
real == rhs.real && imaginary == rhs.imaginary
|
||||
elsif rhs.is_a? Numeric
|
||||
imaginary.zero? && real == rhs
|
||||
end
|
||||
end
|
||||
|
||||
def abs
|
||||
Math.hypot imaginary, real
|
||||
end
|
||||
alias_method :magnitude, :abs
|
||||
|
||||
def abs2
|
||||
real * real + imaginary * imaginary
|
||||
end
|
||||
|
||||
def arg
|
||||
Math.atan2 imaginary, real
|
||||
end
|
||||
alias_method :angle, :arg
|
||||
alias_method :phase, :arg
|
||||
|
||||
def conjugate
|
||||
Complex(real, -imaginary)
|
||||
end
|
||||
alias_method :conj, :conjugate
|
||||
|
||||
def fdiv(numeric)
|
||||
Complex(real.to_f / numeric, imaginary.to_f / numeric)
|
||||
end
|
||||
|
||||
def polar
|
||||
[abs, arg]
|
||||
end
|
||||
|
||||
def real?
|
||||
false
|
||||
end
|
||||
|
||||
def rectangular
|
||||
[real, imaginary]
|
||||
end
|
||||
alias_method :rect, :rectangular
|
||||
|
||||
def to_r
|
||||
raise RangeError.new "can't convert #{to_s} into Rational" unless imaginary.zero?
|
||||
Rational(real, 1)
|
||||
end
|
||||
|
||||
alias_method :imag, :imaginary
|
||||
|
||||
[Fixnum, Float].each do |cls|
|
||||
[:+, :-, :*, :/, :==].each do |op|
|
||||
cls.instance_exec do
|
||||
original_operator_name = "__original_operator_#{op}_complex"
|
||||
alias_method original_operator_name, op
|
||||
define_method op do |rhs|
|
||||
if rhs.is_a? Complex
|
||||
Complex(self).send(op, rhs)
|
||||
else
|
||||
send(original_operator_name, rhs)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,249 @@
|
||||
#include <mruby.h>
|
||||
#include <mruby/class.h>
|
||||
#include <mruby/numeric.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef MRB_WITHOUT_FLOAT
|
||||
# error Complex conflicts 'MRB_WITHOUT_FLOAT' configuration in your 'build_config.rb'
|
||||
#endif
|
||||
|
||||
struct mrb_complex {
|
||||
mrb_float real;
|
||||
mrb_float imaginary;
|
||||
};
|
||||
|
||||
#ifdef MRB_USE_FLOAT
|
||||
#define F(x) x##f
|
||||
#else
|
||||
#define F(x) x
|
||||
#endif
|
||||
|
||||
#if defined(MRB_64BIT) || defined(MRB_USE_FLOAT)
|
||||
|
||||
#define COMPLEX_USE_ISTRUCT
|
||||
/* use TT_ISTRUCT */
|
||||
#include <mruby/istruct.h>
|
||||
|
||||
#define complex_ptr(mrb, v) (struct mrb_complex*)mrb_istruct_ptr(v)
|
||||
|
||||
static struct RBasic*
|
||||
complex_alloc(mrb_state *mrb, struct RClass *c, struct mrb_complex **p)
|
||||
{
|
||||
struct RIStruct *s;
|
||||
|
||||
s = (struct RIStruct*)mrb_obj_alloc(mrb, MRB_TT_ISTRUCT, c);
|
||||
*p = (struct mrb_complex*)s->inline_data;
|
||||
|
||||
return (struct RBasic*)s;
|
||||
}
|
||||
|
||||
#else
|
||||
/* use TT_DATA */
|
||||
#include <mruby/data.h>
|
||||
|
||||
static const struct mrb_data_type mrb_complex_type = {"Complex", mrb_free};
|
||||
|
||||
static struct RBasic*
|
||||
complex_alloc(mrb_state *mrb, struct RClass *c, struct mrb_complex **p)
|
||||
{
|
||||
struct RData *d;
|
||||
|
||||
Data_Make_Struct(mrb, c, struct mrb_complex, &mrb_complex_type, *p, d);
|
||||
|
||||
return (struct RBasic*)d;
|
||||
}
|
||||
|
||||
static struct mrb_complex*
|
||||
complex_ptr(mrb_state *mrb, mrb_value v)
|
||||
{
|
||||
struct mrb_complex *p;
|
||||
|
||||
p = DATA_GET_PTR(mrb, v, &mrb_complex_type, struct mrb_complex);
|
||||
if (!p) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized complex");
|
||||
}
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
|
||||
static mrb_value
|
||||
complex_new(mrb_state *mrb, mrb_float real, mrb_float imaginary)
|
||||
{
|
||||
struct RClass *c = mrb_class_get(mrb, "Complex");
|
||||
struct mrb_complex *p;
|
||||
struct RBasic *comp = complex_alloc(mrb, c, &p);
|
||||
p->real = real;
|
||||
p->imaginary = imaginary;
|
||||
MRB_SET_FROZEN_FLAG(comp);
|
||||
|
||||
return mrb_obj_value(comp);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
complex_real(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_complex *p = complex_ptr(mrb, self);
|
||||
return mrb_float_value(mrb, p->real);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
complex_imaginary(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_complex *p = complex_ptr(mrb, self);
|
||||
return mrb_float_value(mrb, p->imaginary);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
complex_s_rect(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_float real, imaginary = 0.0;
|
||||
|
||||
mrb_get_args(mrb, "f|f", &real, &imaginary);
|
||||
return complex_new(mrb, real, imaginary);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
complex_to_f(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_complex *p = complex_ptr(mrb, self);
|
||||
|
||||
if (p->imaginary != 0) {
|
||||
mrb_raisef(mrb, E_RANGE_ERROR, "can't convert %v into Float", self);
|
||||
}
|
||||
|
||||
return mrb_float_value(mrb, p->real);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
complex_to_i(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_complex *p = complex_ptr(mrb, self);
|
||||
|
||||
if (p->imaginary != 0) {
|
||||
mrb_raisef(mrb, E_RANGE_ERROR, "can't convert %v into Float", self);
|
||||
}
|
||||
return mrb_int_value(mrb, p->real);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
complex_to_c(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Arithmetic on (significand, exponent) pairs avoids premature overflow in
|
||||
complex division */
|
||||
struct float_pair {
|
||||
mrb_float s;
|
||||
int x;
|
||||
};
|
||||
|
||||
static void
|
||||
add_pair(struct float_pair *s, struct float_pair const *a,
|
||||
struct float_pair const *b)
|
||||
{
|
||||
if (b->s == 0.0F) {
|
||||
*s = *a;
|
||||
} else if (a->s == 0.0F) {
|
||||
*s = *b;
|
||||
} else if (a->x >= b->x) {
|
||||
s->s = a->s + F(ldexp)(b->s, b->x - a->x);
|
||||
s->x = a->x;
|
||||
} else {
|
||||
s->s = F(ldexp)(a->s, a->x - b->x) + b->s;
|
||||
s->x = b->x;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mul_pair(struct float_pair *p, struct float_pair const *a,
|
||||
struct float_pair const *b)
|
||||
{
|
||||
p->s = a->s * b->s;
|
||||
p->x = a->x + b->x;
|
||||
}
|
||||
|
||||
static void
|
||||
div_pair(struct float_pair *q, struct float_pair const *a,
|
||||
struct float_pair const *b)
|
||||
{
|
||||
q->s = a->s / b->s;
|
||||
q->x = a->x - b->x;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
complex_div(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value rhs;
|
||||
struct mrb_complex *a, *b;
|
||||
struct float_pair ar, ai, br, bi;
|
||||
struct float_pair br2, bi2;
|
||||
struct float_pair div;
|
||||
struct float_pair ar_br, ai_bi;
|
||||
struct float_pair ai_br, ar_bi;
|
||||
struct float_pair zr, zi;
|
||||
|
||||
mrb_get_args(mrb, "o", &rhs);
|
||||
a = complex_ptr(mrb, self);
|
||||
b = complex_ptr(mrb, rhs);
|
||||
|
||||
/* Split floating point components into significand and exponent */
|
||||
ar.s = F(frexp)(a->real, &ar.x);
|
||||
ai.s = F(frexp)(a->imaginary, &ai.x);
|
||||
br.s = F(frexp)(b->real, &br.x);
|
||||
bi.s = F(frexp)(b->imaginary, &bi.x);
|
||||
|
||||
/* Perform arithmetic on (significand, exponent) pairs to produce
|
||||
the result: */
|
||||
|
||||
/* the divisor */
|
||||
mul_pair(&br2, &br, &br);
|
||||
mul_pair(&bi2, &bi, &bi);
|
||||
add_pair(&div, &br2, &bi2);
|
||||
|
||||
/* real component */
|
||||
mul_pair(&ar_br, &ar, &br);
|
||||
mul_pair(&ai_bi, &ai, &bi);
|
||||
add_pair(&zr, &ar_br, &ai_bi);
|
||||
div_pair(&zr, &zr, &div);
|
||||
|
||||
/* imaginary component */
|
||||
mul_pair(&ai_br, &ai, &br);
|
||||
mul_pair(&ar_bi, &ar, &bi);
|
||||
ar_bi.s = -ar_bi.s;
|
||||
add_pair(&zi, &ai_br, &ar_bi);
|
||||
div_pair(&zi, &zi, &div);
|
||||
|
||||
/* assemble the result */
|
||||
return complex_new(mrb, F(ldexp)(zr.s, zr.x), F(ldexp)(zi.s, zi.x));
|
||||
}
|
||||
|
||||
void mrb_mruby_complex_gem_init(mrb_state *mrb)
|
||||
{
|
||||
struct RClass *comp;
|
||||
|
||||
#ifdef COMPLEX_USE_ISTRUCT
|
||||
mrb_assert(sizeof(struct mrb_complex) < ISTRUCT_DATA_SIZE);
|
||||
#endif
|
||||
comp = mrb_define_class(mrb, "Complex", mrb_class_get(mrb, "Numeric"));
|
||||
#ifdef COMPLEX_USE_ISTRUCT
|
||||
MRB_SET_INSTANCE_TT(comp, MRB_TT_ISTRUCT);
|
||||
#else
|
||||
MRB_SET_INSTANCE_TT(comp, MRB_TT_DATA);
|
||||
#endif
|
||||
mrb_undef_class_method(mrb, comp, "new");
|
||||
mrb_define_class_method(mrb, comp, "rectangular", complex_s_rect, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
|
||||
mrb_define_class_method(mrb, comp, "rect", complex_s_rect, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
|
||||
mrb_define_method(mrb, mrb->kernel_module, "Complex", complex_s_rect, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
|
||||
mrb_define_method(mrb, comp, "real", complex_real, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, comp, "imaginary", complex_imaginary, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, comp, "to_f", complex_to_f, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, comp, "to_i", complex_to_i, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, comp, "to_c", complex_to_c, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, comp, "__div__", complex_div, MRB_ARGS_REQ(1));
|
||||
}
|
||||
|
||||
void
|
||||
mrb_mruby_complex_gem_final(mrb_state* mrb)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
def assert_complex(real, exp)
|
||||
assert "assert_complex" do
|
||||
assert_float real.real, exp.real
|
||||
assert_float real.imaginary, exp.imaginary
|
||||
end
|
||||
end
|
||||
|
||||
assert 'Complex' do
|
||||
c = 123i
|
||||
assert_equal Complex, c.class
|
||||
assert_equal [c.real, c.imaginary], [0, 123]
|
||||
c = 123 + -1.23i
|
||||
assert_equal Complex, c.class
|
||||
assert_equal [c.real, c.imaginary], [123, -1.23]
|
||||
end
|
||||
|
||||
assert 'Complex::polar' do
|
||||
assert_complex Complex.polar(3, 0), (3 + 0i)
|
||||
assert_complex Complex.polar(3, Math::PI/2), (0 + 3i)
|
||||
assert_complex Complex.polar(3, Math::PI), (-3 + 0i)
|
||||
assert_complex Complex.polar(3, -Math::PI/2), (0 + -3i)
|
||||
end
|
||||
|
||||
assert 'Complex::rectangular' do
|
||||
assert_complex Complex.rectangular(1, 2), (1 + 2i)
|
||||
end
|
||||
|
||||
assert 'Complex#*' do
|
||||
assert_complex Complex(2, 3) * Complex(2, 3), (-5 + 12i)
|
||||
assert_complex Complex(900) * Complex(1), (900 + 0i)
|
||||
assert_complex Complex(-2, 9) * Complex(-9, 2), (0 - 85i)
|
||||
assert_complex Complex(9, 8) * 4, (36 + 32i)
|
||||
assert_complex Complex(20, 9) * 9.8, (196.0 + 88.2i)
|
||||
end
|
||||
|
||||
assert 'Complex#+' do
|
||||
assert_complex Complex(2, 3) + Complex(2, 3) , (4 + 6i)
|
||||
assert_complex Complex(900) + Complex(1) , (901 + 0i)
|
||||
assert_complex Complex(-2, 9) + Complex(-9, 2), (-11 + 11i)
|
||||
assert_complex Complex(9, 8) + 4 , (13 + 8i)
|
||||
assert_complex Complex(20, 9) + 9.8 , (29.8 + 9i)
|
||||
end
|
||||
|
||||
assert 'Complex#-' do
|
||||
assert_complex Complex(2, 3) - Complex(2, 3) , (0 + 0i)
|
||||
assert_complex Complex(900) - Complex(1) , (899 + 0i)
|
||||
assert_complex Complex(-2, 9) - Complex(-9, 2), (7 + 7i)
|
||||
assert_complex Complex(9, 8) - 4 , (5 + 8i)
|
||||
assert_complex Complex(20, 9) - 9.8 , (10.2 + 9i)
|
||||
end
|
||||
|
||||
assert 'Complex#-@' do
|
||||
assert_complex(-Complex(1, 2), (-1 - 2i))
|
||||
end
|
||||
|
||||
assert 'Complex#/' do
|
||||
assert_complex Complex(2, 3) / Complex(2, 3) , (1 + 0i)
|
||||
assert_complex Complex(900) / Complex(1) , (900 + 0i)
|
||||
assert_complex Complex(-2, 9) / Complex(-9, 2), ((36 / 85) - (77i / 85))
|
||||
assert_complex Complex(9, 8) / 4 , ((9 / 4) + 2i)
|
||||
assert_complex Complex(20, 9) / 9.8 , (2.0408163265306123 + 0.9183673469387754i)
|
||||
if 1e39.infinite? then
|
||||
# MRB_USE_FLOAT in effect
|
||||
ten = 1e21
|
||||
one = 1e20
|
||||
else
|
||||
ten = 1e201
|
||||
one = 1e200
|
||||
end
|
||||
assert_complex Complex(ten, ten) / Complex(one, one), Complex(10.0, 0.0)
|
||||
end
|
||||
|
||||
assert 'Complex#==' do
|
||||
assert_true Complex(2, 3) == Complex(2, 3)
|
||||
assert_true Complex(5) == 5
|
||||
assert_true Complex(0) == 0.0
|
||||
end
|
||||
|
||||
assert 'Complex#abs' do
|
||||
assert_float Complex(-1).abs, 1
|
||||
assert_float Complex(3.0, -4.0).abs, 5.0
|
||||
if 1e39.infinite? then
|
||||
# MRB_USE_FLOAT in effect
|
||||
exp = 125
|
||||
else
|
||||
exp = 1021
|
||||
end
|
||||
assert_true Complex(3.0*2.0**exp, 4.0*2.0**exp).abs.finite?
|
||||
assert_float Complex(3.0*2.0**exp, 4.0*2.0**exp).abs, 5.0*2.0**exp
|
||||
end
|
||||
|
||||
assert 'Complex#abs2' do
|
||||
assert_float Complex(-1).abs2, 1
|
||||
assert_float Complex(3.0, -4.0).abs2, 25.0
|
||||
end
|
||||
|
||||
assert 'Complex#arg' do
|
||||
assert_float Complex.polar(3, Math::PI/2).arg, 1.5707963267948966
|
||||
end
|
||||
|
||||
assert 'Complex#conjugate' do
|
||||
assert_complex Complex(1, 2).conjugate, (1 - 2i)
|
||||
end
|
||||
|
||||
assert 'Complex#fdiv' do
|
||||
assert_complex Complex(11, 22).fdiv(3), (3.6666666666666665 + 7.333333333333333i)
|
||||
end
|
||||
|
||||
assert 'Complex#imaginary' do
|
||||
assert_float Complex(7).imaginary , 0
|
||||
assert_float Complex(9, -4).imaginary, -4
|
||||
end
|
||||
|
||||
assert 'Complex#polar' do
|
||||
assert_equal Complex(1, 2).polar, [2.23606797749979, 1.1071487177940904]
|
||||
end
|
||||
|
||||
assert 'Complex#real' do
|
||||
assert_float Complex(7).real, 7
|
||||
assert_float Complex(9, -4).real, 9
|
||||
end
|
||||
|
||||
assert 'Complex#real?' do
|
||||
assert_false Complex(1).real?
|
||||
end
|
||||
|
||||
assert 'Complex::rectangular' do
|
||||
assert_equal Complex(1, 2).rectangular, [1, 2]
|
||||
end
|
||||
|
||||
assert 'Complex::to_c' do
|
||||
assert_equal Complex(1, 2).to_c, Complex(1, 2)
|
||||
end
|
||||
|
||||
assert 'Complex::to_f' do
|
||||
assert_float Complex(1, 0).to_f, 1.0
|
||||
assert_raise(RangeError) do
|
||||
Complex(1, 2).to_f
|
||||
end
|
||||
end
|
||||
|
||||
assert 'Complex::to_i' do
|
||||
assert_equal Complex(1, 0).to_i, 1
|
||||
assert_raise(RangeError) do
|
||||
Complex(1, 2).to_i
|
||||
end
|
||||
end
|
||||
|
||||
assert 'Complex#frozen?' do
|
||||
assert_predicate(1i, :frozen?)
|
||||
assert_predicate(Complex(2,3), :frozen?)
|
||||
assert_predicate(4+5i, :frozen?)
|
||||
end
|
||||
@@ -6,28 +6,30 @@ module Enumerable
|
||||
def chain(*args)
|
||||
Enumerator::Chain.new(self, *args)
|
||||
end
|
||||
|
||||
def +(other)
|
||||
Enumerator::Chain.new(self, other)
|
||||
end
|
||||
end
|
||||
|
||||
class Enumerator
|
||||
def +(other)
|
||||
Chain.new(self, other)
|
||||
end
|
||||
|
||||
class Chain
|
||||
include Enumerable
|
||||
|
||||
def initialize(*args)
|
||||
@enums = args
|
||||
end
|
||||
|
||||
def initialize_copy(orig)
|
||||
@enums = orig.__copy_enums
|
||||
@enums = args.freeze
|
||||
@pos = -1
|
||||
end
|
||||
|
||||
def each(&block)
|
||||
return to_enum unless block_given?
|
||||
return to_enum unless block
|
||||
|
||||
@enums.each { |e| e.each(&block) }
|
||||
i = 0
|
||||
while i < @enums.size
|
||||
@pos = i
|
||||
@enums[i].each(&block)
|
||||
i += 1
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
@@ -40,21 +42,21 @@ class Enumerator
|
||||
end
|
||||
|
||||
def rewind
|
||||
@enums.reverse_each do |e|
|
||||
while 0 <= @pos && @pos < @enums.size
|
||||
e = @enums[@pos]
|
||||
e.rewind if e.respond_to?(:rewind)
|
||||
@pos -= 1
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
def +(other)
|
||||
self.class.new(self, other)
|
||||
end
|
||||
|
||||
def inspect
|
||||
"#<#{self.class}: #{@enums.inspect}>"
|
||||
end
|
||||
|
||||
def __copy_enums
|
||||
@enums.each_with_object([]) do |e, a|
|
||||
a << e.clone
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,9 +12,9 @@ assert("Enumerable#chain") do
|
||||
assert_raise(NoMethodError) { c.chain }
|
||||
end
|
||||
|
||||
assert("Enumerable#+") do
|
||||
assert("Enumerator#+") do
|
||||
a = [].each
|
||||
b = {}.reverse_each
|
||||
b = {}.each
|
||||
c = Object.new # not has #each method
|
||||
|
||||
assert_kind_of Enumerator::Chain, a + b
|
||||
@@ -24,7 +24,7 @@ assert("Enumerable#+") do
|
||||
assert_raise(NoMethodError) { c + a }
|
||||
end
|
||||
|
||||
assert("Enumerator.new") do
|
||||
assert("Enumerator::Chain.new") do
|
||||
a = []
|
||||
b = {}
|
||||
c = Object.new # not has #each method
|
||||
@@ -46,13 +46,13 @@ assert("Enumerator::Chain#each") do
|
||||
assert_kind_of Enumerator, aa.each
|
||||
assert_equal [1, 2, 3, 1, 2, 3], aa.each.to_a
|
||||
|
||||
aa = a.chain(a.reverse_each)
|
||||
aa = a.chain(6..9)
|
||||
assert_kind_of Enumerator, aa.each
|
||||
assert_equal [1, 2, 3, 3, 2, 1], aa.each.to_a
|
||||
assert_equal [1, 2, 3, 6, 7, 8, 9], aa.each.to_a
|
||||
|
||||
aa = a.chain(a.reverse_each, a)
|
||||
aa = a.chain((-3..-2).each_with_index, a)
|
||||
assert_kind_of Enumerator, aa.each
|
||||
assert_equal [1, 2, 3, 3, 2, 1, 1, 2, 3], aa.each.to_a
|
||||
assert_equal [1, 2, 3, [-3, 0], [-2, 1], 1, 2, 3], aa.each.to_a
|
||||
|
||||
aa = a.chain(Object.new)
|
||||
assert_kind_of Enumerator, aa.each
|
||||
@@ -65,12 +65,44 @@ assert("Enumerator::Chain#size") do
|
||||
aa = a.chain(a)
|
||||
assert_equal 6, aa.size
|
||||
|
||||
aa = a.chain(a.reverse_each)
|
||||
aa = a.chain(3..4)
|
||||
assert_nil aa.size
|
||||
|
||||
aa = a.chain(a.reverse_each, a)
|
||||
aa = a.chain(3..4, a)
|
||||
assert_nil aa.size
|
||||
|
||||
aa = a.chain(Object.new)
|
||||
assert_nil aa.size
|
||||
end
|
||||
|
||||
assert("Enumerator::Chain#rewind") do
|
||||
rewound = nil
|
||||
e1 = [1, 2]
|
||||
e2 = (4..6)
|
||||
(class << e1; self end).define_method(:rewind) { rewound << self }
|
||||
(class << e2; self end).define_method(:rewind) { rewound << self }
|
||||
c = e1.chain(e2)
|
||||
|
||||
rewound = []
|
||||
c.rewind
|
||||
assert_equal [], rewound
|
||||
|
||||
rewound = []
|
||||
c.each{break c}.rewind
|
||||
assert_equal [e1], rewound
|
||||
|
||||
rewound = []
|
||||
c.each{}.rewind
|
||||
assert_equal [e2, e1], rewound
|
||||
end
|
||||
|
||||
assert("Enumerator::Chain#+") do
|
||||
a = [].chain
|
||||
b = {}.chain
|
||||
c = Object.new # not has #each method
|
||||
|
||||
assert_kind_of Enumerator::Chain, a + b
|
||||
assert_kind_of Enumerator::Chain, a + c
|
||||
assert_kind_of Enumerator::Chain, b + a
|
||||
assert_kind_of Enumerator::Chain, b + c
|
||||
end
|
||||
|
||||
@@ -811,10 +811,6 @@ module Enumerable
|
||||
h
|
||||
end
|
||||
|
||||
def nil.to_h
|
||||
{}
|
||||
end
|
||||
|
||||
def uniq(&block)
|
||||
hash = {}
|
||||
if block
|
||||
@@ -830,4 +826,34 @@ module Enumerable
|
||||
end
|
||||
hash.values
|
||||
end
|
||||
|
||||
def filter_map(&blk)
|
||||
return to_enum(:filter_map) unless blk
|
||||
|
||||
ary = []
|
||||
self.each do |x|
|
||||
x = blk.call(x)
|
||||
ary.push x if x
|
||||
end
|
||||
ary
|
||||
end
|
||||
|
||||
alias filter select
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# enum.tally -> a_hash
|
||||
#
|
||||
# Tallys the collection. Returns a hash where the keys are the
|
||||
# elements and the values are numbers of elements in the collection
|
||||
# that correspond to the key.
|
||||
#
|
||||
# ["a", "b", "c", "b"].tally #=> {"a"=>1, "b"=>2, "c"=>1}
|
||||
def tally
|
||||
hash = {}
|
||||
self.each do |x|
|
||||
hash[x] = (hash[x]||0)+1
|
||||
end
|
||||
hash
|
||||
end
|
||||
end
|
||||
|
||||
@@ -186,8 +186,13 @@ assert("Enumerable#to_h") do
|
||||
h = c.new.to_h
|
||||
assert_equal Hash, h.class
|
||||
assert_equal h0, h
|
||||
# mruby-enum-ext also provides nil.to_h
|
||||
assert_equal Hash.new, nil.to_h
|
||||
|
||||
assert_equal({1=>4,3=>8}, c.new.to_h{|k,v|[k,v*2]})
|
||||
end
|
||||
|
||||
assert("Enumerable#filter_map") do
|
||||
assert_equal [4, 8, 12, 16, 20], (1..10).filter_map{|i| i * 2 if i%2==0}
|
||||
end
|
||||
|
||||
assert("Enumerable#tally") do
|
||||
assert_equal({"a"=>1, "b"=>2, "c"=>1}, ["a", "b", "c", "b"].tally)
|
||||
end
|
||||
|
||||
@@ -2,6 +2,5 @@ MRuby::Gem::Specification.new('mruby-enumerator') do |spec|
|
||||
spec.license = 'MIT'
|
||||
spec.author = 'mruby developers'
|
||||
spec.add_dependency('mruby-fiber', :core => 'mruby-fiber')
|
||||
spec.add_dependency 'mruby-enum-ext', :core => 'mruby-enum-ext'
|
||||
spec.summary = 'Enumerator class'
|
||||
end
|
||||
|
||||
@@ -89,7 +89,6 @@ class Enumerator
|
||||
include Enumerable
|
||||
|
||||
##
|
||||
# @overload initialize(size = nil, &block)
|
||||
# @overload initialize(obj, method = :each, *args)
|
||||
#
|
||||
# Creates a new Enumerator object, which can be used as an
|
||||
@@ -244,9 +243,10 @@ class Enumerator
|
||||
#
|
||||
# === Examples
|
||||
#
|
||||
# "Hello, world!".scan(/\w+/) #=> ["Hello", "world"]
|
||||
# "Hello, world!".to_enum(:scan, /\w+/).to_a #=> ["Hello", "world"]
|
||||
# "Hello, world!".to_enum(:scan).each(/\w+/).to_a #=> ["Hello", "world"]
|
||||
# Array.new(3) #=> [nil, nil, nil]
|
||||
# Array.new(3) { |i| i } #=> [0, 1, 2]
|
||||
# Array.to_enum(:new, 3).to_a #=> [0, 1, 2]
|
||||
# Array.to_enum(:new).each(3).to_a #=> [0, 1, 2]
|
||||
#
|
||||
# obj = Object.new
|
||||
#
|
||||
@@ -555,6 +555,46 @@ class Enumerator
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# Enumerator.produce(initial = nil) { |val| } -> enumerator
|
||||
#
|
||||
# Creates an infinite enumerator from any block, just called over and
|
||||
# over. Result of the previous iteration is passed to the next one.
|
||||
# If +initial+ is provided, it is passed to the first iteration, and
|
||||
# becomes the first element of the enumerator; if it is not provided,
|
||||
# first iteration receives +nil+, and its result becomes first
|
||||
# element of the iterator.
|
||||
#
|
||||
# Raising StopIteration from the block stops an iteration.
|
||||
#
|
||||
# Examples of usage:
|
||||
#
|
||||
# Enumerator.produce(1, &:succ) # => enumerator of 1, 2, 3, 4, ....
|
||||
#
|
||||
# Enumerator.produce { rand(10) } # => infinite random number sequence
|
||||
#
|
||||
# ancestors = Enumerator.produce(node) { |prev| node = prev.parent or raise StopIteration }
|
||||
# enclosing_section = ancestors.find { |n| n.type == :section }
|
||||
def Enumerator.produce(init=NONE, &block)
|
||||
raise ArgumentError, "no block given" if block.nil?
|
||||
Enumerator.new do |y|
|
||||
if init == NONE
|
||||
val = nil
|
||||
else
|
||||
val = init
|
||||
y.yield(val)
|
||||
end
|
||||
begin
|
||||
while true
|
||||
y.yield(val = block.call(val))
|
||||
end
|
||||
rescue StopIteration
|
||||
# do nothing
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module Kernel
|
||||
@@ -562,15 +602,10 @@ module Kernel
|
||||
# call-seq:
|
||||
# obj.to_enum(method = :each, *args) -> enum
|
||||
# obj.enum_for(method = :each, *args) -> enum
|
||||
# obj.to_enum(method = :each, *args) {|*args| block} -> enum
|
||||
# obj.enum_for(method = :each, *args){|*args| block} -> enum
|
||||
#
|
||||
# Creates a new Enumerator which will enumerate by calling +method+ on
|
||||
# +obj+, passing +args+ if any.
|
||||
#
|
||||
# If a block is given, it will be used to calculate the size of
|
||||
# the enumerator without the need to iterate it (see Enumerator#size).
|
||||
#
|
||||
# === Examples
|
||||
#
|
||||
# str = "xyz"
|
||||
@@ -588,17 +623,14 @@ module Kernel
|
||||
# It is typical to call to_enum when defining methods for
|
||||
# a generic Enumerable, in case no block is passed.
|
||||
#
|
||||
# Here is such an example, with parameter passing and a sizing block:
|
||||
# Here is such an example with parameter passing:
|
||||
#
|
||||
# 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
|
||||
# return to_enum(__method__, n) # __method__ is :repeat here
|
||||
# end
|
||||
# each do |*val|
|
||||
# n.times { yield *val }
|
||||
|
||||
@@ -6,6 +6,17 @@ class << @obj
|
||||
end
|
||||
end
|
||||
|
||||
def assert_take(exp, enumerator)
|
||||
result = []
|
||||
n = exp.size
|
||||
enumerator.each do |v|
|
||||
result << v
|
||||
n -= 1
|
||||
break if n == 0
|
||||
end if n > 0
|
||||
assert_equal exp, result
|
||||
end
|
||||
|
||||
assert 'Enumerator.class' do
|
||||
assert_equal Class, Enumerator.class
|
||||
end
|
||||
@@ -19,7 +30,7 @@ assert 'Enumerator.new' do
|
||||
assert_equal [:x,:y,:z], [:x,:y,:z].each.map{|i| i}.sort
|
||||
assert_equal [[:x,1],[:y,2]], {x:1, y:2}.each.map{|i| i}.sort
|
||||
assert_equal [1,2,3], @obj.to_enum(:foo, 1,2,3).to_a
|
||||
assert_equal [1,2,3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.take(3)
|
||||
assert_take [1,2,3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }
|
||||
assert_raise(ArgumentError) { Enumerator.new }
|
||||
|
||||
# examples
|
||||
@@ -30,7 +41,7 @@ assert 'Enumerator.new' do
|
||||
a, b = b, a + b
|
||||
end
|
||||
end
|
||||
assert_equal [1,1,2,3,5,8,13,21,34,55], fib.take(10)
|
||||
assert_take [1,1,2,3,5,8,13,21,34,55], fib
|
||||
end
|
||||
|
||||
assert 'Enumerator#initialize_copy' do
|
||||
@@ -549,3 +560,41 @@ assert 'Enumerable#zip' do
|
||||
|
||||
assert_raise(TypeError) { [1].zip(1) }
|
||||
end
|
||||
|
||||
assert 'Enumerator.produce' do
|
||||
assert_raise(ArgumentError) { Enumerator.produce }
|
||||
|
||||
# Without initial object
|
||||
passed_args = []
|
||||
enum = Enumerator.produce {|obj| passed_args << obj; (obj || 0).succ }
|
||||
assert_equal Enumerator, enum.class
|
||||
assert_take [1, 2, 3], enum
|
||||
assert_equal [nil, 1, 2], passed_args
|
||||
|
||||
# With initial object
|
||||
passed_args = []
|
||||
enum = Enumerator.produce(1) {|obj| passed_args << obj; obj.succ }
|
||||
assert_take [1, 2, 3], enum
|
||||
assert_equal [1, 2], passed_args
|
||||
|
||||
# Raising StopIteration
|
||||
words = %w[The quick brown fox jumps over the lazy dog]
|
||||
enum = Enumerator.produce { words.shift or raise StopIteration }
|
||||
assert_equal %w[The quick brown fox jumps over the lazy dog], enum.to_a
|
||||
|
||||
# Raising StopIteration
|
||||
object = [[[["abc", "def"], "ghi", "jkl"], "mno", "pqr"], "stuv", "wxyz"]
|
||||
enum = Enumerator.produce(object) {|obj|
|
||||
obj.respond_to?(:first) or raise StopIteration
|
||||
obj.first
|
||||
}
|
||||
assert_nothing_raised {
|
||||
assert_equal [
|
||||
[[[["abc", "def"], "ghi", "jkl"], "mno", "pqr"], "stuv", "wxyz"],
|
||||
[[["abc", "def"], "ghi", "jkl"], "mno", "pqr"],
|
||||
[["abc", "def"], "ghi", "jkl"],
|
||||
["abc", "def"],
|
||||
"abc",
|
||||
], enum.to_a
|
||||
}
|
||||
end
|
||||
|
||||
@@ -8,6 +8,7 @@ mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state)
|
||||
struct mrb_jmpbuf *prev_jmp = mrb->jmp;
|
||||
struct mrb_jmpbuf c_jmp;
|
||||
mrb_value result = mrb_nil_value();
|
||||
mrb_int ai = mrb_gc_arena_save(mrb);
|
||||
|
||||
if (state) { *state = FALSE; }
|
||||
|
||||
@@ -22,6 +23,7 @@ mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state)
|
||||
if (state) { *state = TRUE; }
|
||||
} MRB_END_EXC(&c_jmp);
|
||||
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
mrb_gc_protect(mrb, result);
|
||||
return result;
|
||||
}
|
||||
@@ -32,6 +34,7 @@ mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t ensure,
|
||||
struct mrb_jmpbuf *prev_jmp = mrb->jmp;
|
||||
struct mrb_jmpbuf c_jmp;
|
||||
mrb_value result;
|
||||
mrb_int ai = mrb_gc_arena_save(mrb);
|
||||
|
||||
MRB_TRY(&c_jmp) {
|
||||
mrb->jmp = &c_jmp;
|
||||
@@ -39,11 +42,15 @@ mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t ensure,
|
||||
mrb->jmp = prev_jmp;
|
||||
} MRB_CATCH(&c_jmp) {
|
||||
mrb->jmp = prev_jmp;
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
ensure(mrb, e_data);
|
||||
MRB_THROW(mrb->jmp); /* rethrow catched exceptions */
|
||||
} MRB_END_EXC(&c_jmp);
|
||||
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
mrb_gc_protect(mrb, result);
|
||||
ensure(mrb, e_data);
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
mrb_gc_protect(mrb, result);
|
||||
return result;
|
||||
}
|
||||
@@ -64,6 +71,7 @@ mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_fun
|
||||
mrb_value result;
|
||||
mrb_bool error_matched = FALSE;
|
||||
mrb_int i;
|
||||
mrb_int ai = mrb_gc_arena_save(mrb);
|
||||
|
||||
MRB_TRY(&c_jmp) {
|
||||
mrb->jmp = &c_jmp;
|
||||
@@ -82,9 +90,11 @@ mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_fun
|
||||
if (!error_matched) { MRB_THROW(mrb->jmp); }
|
||||
|
||||
mrb->exc = NULL;
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
result = rescue(mrb, r_data);
|
||||
} MRB_END_EXC(&c_jmp);
|
||||
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
mrb_gc_protect(mrb, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -102,25 +102,28 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
|
||||
uint8_t c;
|
||||
mrb_code insn;
|
||||
int argc = irep_argc(irep);
|
||||
mrb_code *iseq = (mrb_code *)irep->iseq;
|
||||
|
||||
mrb_assert((irep->flags & MRB_ISEQ_NO_FREE) == 0);
|
||||
|
||||
for (i = 0; i < irep->ilen; ) {
|
||||
insn = irep->iseq[i];
|
||||
insn = iseq[i];
|
||||
switch(insn){
|
||||
case OP_EPUSH:
|
||||
b = PEEK_S(irep->iseq+i+1);
|
||||
b = PEEK_S(iseq+i+1);
|
||||
patch_irep(mrb, irep->reps[b], bnest + 1, top);
|
||||
break;
|
||||
|
||||
case OP_LAMBDA:
|
||||
case OP_BLOCK:
|
||||
a = PEEK_B(irep->iseq+i+1);
|
||||
b = PEEK_B(irep->iseq+i+2);
|
||||
a = PEEK_B(iseq+i+1);
|
||||
b = PEEK_B(iseq+i+2);
|
||||
patch_irep(mrb, irep->reps[b], bnest + 1, top);
|
||||
break;
|
||||
|
||||
case OP_SEND:
|
||||
b = PEEK_B(irep->iseq+i+2);
|
||||
c = PEEK_B(irep->iseq+i+3);
|
||||
b = PEEK_B(iseq+i+2);
|
||||
c = PEEK_B(iseq+i+3);
|
||||
if (c != 0) {
|
||||
break;
|
||||
}
|
||||
@@ -128,24 +131,24 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
|
||||
uint16_t arg = search_variable(mrb, irep->syms[b], bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
irep->iseq[i] = OP_GETUPVAR;
|
||||
irep->iseq[i+2] = arg >> 8;
|
||||
irep->iseq[i+3] = arg & 0xff;
|
||||
iseq[i] = OP_GETUPVAR;
|
||||
iseq[i+2] = arg >> 8;
|
||||
iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_MOVE:
|
||||
a = PEEK_B(irep->iseq+i+1);
|
||||
b = PEEK_B(irep->iseq+i+2);
|
||||
a = PEEK_B(iseq+i+1);
|
||||
b = PEEK_B(iseq+i+2);
|
||||
/* src part */
|
||||
if (potential_upvar_p(irep->lv, b, argc, irep->nlocals)) {
|
||||
uint16_t arg = search_variable(mrb, irep->lv[b - 1].name, bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
irep->iseq[i] = insn = OP_GETUPVAR;
|
||||
irep->iseq[i+2] = arg >> 8;
|
||||
irep->iseq[i+3] = arg & 0xff;
|
||||
iseq[i] = insn = OP_GETUPVAR;
|
||||
iseq[i+2] = arg >> 8;
|
||||
iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
/* dst part */
|
||||
@@ -153,18 +156,18 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
|
||||
uint16_t arg = search_variable(mrb, irep->lv[a - 1].name, bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
irep->iseq[i] = insn = OP_SETUPVAR;
|
||||
irep->iseq[i+1] = (mrb_code)b;
|
||||
irep->iseq[i+2] = arg >> 8;
|
||||
irep->iseq[i+3] = arg & 0xff;
|
||||
iseq[i] = insn = OP_SETUPVAR;
|
||||
iseq[i+1] = (mrb_code)b;
|
||||
iseq[i+2] = arg >> 8;
|
||||
iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_GETUPVAR:
|
||||
a = PEEK_B(irep->iseq+i+1);
|
||||
b = PEEK_B(irep->iseq+i+2);
|
||||
c = PEEK_B(irep->iseq+i+3);
|
||||
a = PEEK_B(iseq+i+1);
|
||||
b = PEEK_B(iseq+i+2);
|
||||
c = PEEK_B(iseq+i+3);
|
||||
{
|
||||
int lev = c+1;
|
||||
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
|
||||
@@ -172,18 +175,18 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
|
||||
uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
irep->iseq[i] = OP_GETUPVAR;
|
||||
irep->iseq[i+2] = arg >> 8;
|
||||
irep->iseq[i+3] = arg & 0xff;
|
||||
iseq[i] = OP_GETUPVAR;
|
||||
iseq[i+2] = arg >> 8;
|
||||
iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_SETUPVAR:
|
||||
a = PEEK_B(irep->iseq+i+1);
|
||||
b = PEEK_B(irep->iseq+i+2);
|
||||
c = PEEK_B(irep->iseq+i+3);
|
||||
a = PEEK_B(iseq+i+1);
|
||||
b = PEEK_B(iseq+i+2);
|
||||
c = PEEK_B(iseq+i+3);
|
||||
{
|
||||
int lev = c+1;
|
||||
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
|
||||
@@ -191,25 +194,25 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
|
||||
uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
irep->iseq[i] = OP_SETUPVAR;
|
||||
irep->iseq[i+1] = a;
|
||||
irep->iseq[i+2] = arg >> 8;
|
||||
irep->iseq[i+3] = arg & 0xff;
|
||||
iseq[i] = OP_SETUPVAR;
|
||||
iseq[i+1] = a;
|
||||
iseq[i+2] = arg >> 8;
|
||||
iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_EXT1:
|
||||
insn = PEEK_B(irep->iseq+i+1);
|
||||
insn = PEEK_B(iseq+i+1);
|
||||
i += mrb_insn_size1[insn]+1;
|
||||
continue;
|
||||
case OP_EXT2:
|
||||
insn = PEEK_B(irep->iseq+i+1);
|
||||
insn = PEEK_B(iseq+i+1);
|
||||
i += mrb_insn_size2[insn]+1;
|
||||
continue;
|
||||
case OP_EXT3:
|
||||
insn = PEEK_B(irep->iseq+i+1);
|
||||
insn = PEEK_B(iseq+i+1);
|
||||
i += mrb_insn_size3[insn]+1;
|
||||
continue;
|
||||
}
|
||||
@@ -235,7 +238,7 @@ create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding,
|
||||
}
|
||||
|
||||
cxt = mrbc_context_new(mrb);
|
||||
cxt->lineno = (short)line;
|
||||
cxt->lineno = (uint16_t)line;
|
||||
|
||||
mrbc_filename(mrb, cxt, file ? file : "(eval)");
|
||||
cxt->capture_errors = TRUE;
|
||||
@@ -254,15 +257,15 @@ create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding,
|
||||
mrb_value str;
|
||||
|
||||
if (file) {
|
||||
str = mrb_format(mrb, " file %S line %S: %S",
|
||||
mrb_str_new_cstr(mrb, file),
|
||||
mrb_fixnum_value(p->error_buffer[0].lineno),
|
||||
mrb_str_new_cstr(mrb, p->error_buffer[0].message));
|
||||
str = mrb_format(mrb, "file %s line %d: %s",
|
||||
file,
|
||||
p->error_buffer[0].lineno,
|
||||
p->error_buffer[0].message);
|
||||
}
|
||||
else {
|
||||
str = mrb_format(mrb, " line %S: %S",
|
||||
mrb_fixnum_value(p->error_buffer[0].lineno),
|
||||
mrb_str_new_cstr(mrb, p->error_buffer[0].message));
|
||||
str = mrb_format(mrb, "line %d: %s",
|
||||
p->error_buffer[0].lineno,
|
||||
p->error_buffer[0].message);
|
||||
}
|
||||
mrb_parser_free(p);
|
||||
mrbc_context_free(mrb, cxt);
|
||||
@@ -387,7 +390,7 @@ void
|
||||
mrb_mruby_eval_gem_init(mrb_state* mrb)
|
||||
{
|
||||
mrb_define_module_function(mrb, mrb->kernel_module, "eval", f_eval, MRB_ARGS_ARG(1, 3));
|
||||
mrb_define_method(mrb, mrb->kernel_module, "instance_eval", f_instance_eval, MRB_ARGS_ARG(1, 2));
|
||||
mrb_define_method(mrb, mrb_class_get(mrb, "BasicObject"), "instance_eval", f_instance_eval, MRB_ARGS_ARG(1, 2));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -80,7 +80,7 @@ assert('Kernel.#eval(string) context') do
|
||||
assert_equal('class') { obj.const_string }
|
||||
end
|
||||
|
||||
assert('Object#instance_eval with begin-rescue-ensure execution order') do
|
||||
assert('BasicObject#instance_eval with begin-rescue-ensure execution order') do
|
||||
class HellRaiser
|
||||
def raise_hell
|
||||
order = [:enter_raise_hell]
|
||||
@@ -100,7 +100,7 @@ assert('Object#instance_eval with begin-rescue-ensure execution order') do
|
||||
assert_equal([:enter_raise_hell, :begin, :rescue, :ensure], hell_raiser.raise_hell)
|
||||
end
|
||||
|
||||
assert('Kernel#instance_eval() to define singleton methods Issue #3141') do
|
||||
assert('BasicObject#instance_eval to define singleton methods Issue #3141') do
|
||||
foo_class = Class.new do
|
||||
def bar(x)
|
||||
instance_eval "def baz; #{x}; end"
|
||||
|
||||
@@ -72,14 +72,11 @@ fiber_init(mrb_state *mrb, mrb_value self)
|
||||
mrb_value blk;
|
||||
size_t slen;
|
||||
|
||||
mrb_get_args(mrb, "&", &blk);
|
||||
mrb_get_args(mrb, "&!", &blk);
|
||||
|
||||
if (f->cxt) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "cannot initialize twice");
|
||||
}
|
||||
if (mrb_nil_p(blk)) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Fiber object without a block");
|
||||
}
|
||||
p = mrb_proc_ptr(blk);
|
||||
if (MRB_PROC_CFUNC_P(p)) {
|
||||
mrb_raise(mrb, E_FIBER_ERROR, "tried to create Fiber from C defined method");
|
||||
@@ -191,14 +188,21 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
|
||||
|
||||
fiber_check_cfunc(mrb, c);
|
||||
status = c->status;
|
||||
if (resume && status == MRB_FIBER_TRANSFERRED) {
|
||||
mrb_raise(mrb, E_FIBER_ERROR, "resuming transferred fiber");
|
||||
}
|
||||
if (status == MRB_FIBER_RUNNING || status == MRB_FIBER_RESUMED) {
|
||||
switch (status) {
|
||||
case MRB_FIBER_TRANSFERRED:
|
||||
if (resume) {
|
||||
mrb_raise(mrb, E_FIBER_ERROR, "resuming transferred fiber");
|
||||
}
|
||||
break;
|
||||
case MRB_FIBER_RUNNING:
|
||||
case MRB_FIBER_RESUMED:
|
||||
mrb_raise(mrb, E_FIBER_ERROR, "double resume");
|
||||
}
|
||||
if (status == MRB_FIBER_TERMINATED) {
|
||||
break;
|
||||
case MRB_FIBER_TERMINATED:
|
||||
mrb_raise(mrb, E_FIBER_ERROR, "resuming dead fiber");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
old_c->status = resume ? MRB_FIBER_RESUMED : MRB_FIBER_TRANSFERRED;
|
||||
c->prev = resume ? mrb->c : (c->prev ? c->prev : mrb->root_c);
|
||||
@@ -290,7 +294,7 @@ fiber_eq(mrb_state *mrb, mrb_value self)
|
||||
mrb_value other;
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
|
||||
if (mrb_type(other) != MRB_TT_FIBER) {
|
||||
if (!mrb_fiber_p(other)) {
|
||||
return mrb_false_value();
|
||||
}
|
||||
return mrb_bool_value(fiber_ptr(self) == fiber_ptr(other));
|
||||
|
||||
@@ -76,7 +76,7 @@ assert('Fiber iteration') do
|
||||
end
|
||||
|
||||
assert('Fiber with splat in the block argument list') {
|
||||
Fiber.new{|*x|x}.resume(1) == [1]
|
||||
assert_equal([1], Fiber.new{|*x|x}.resume(1))
|
||||
}
|
||||
|
||||
assert('Fiber raises on resume when dead') do
|
||||
|
||||
@@ -494,4 +494,7 @@ class Hash
|
||||
self.fetch(k, &block)
|
||||
end
|
||||
end
|
||||
|
||||
alias filter select
|
||||
alias filter! select!
|
||||
end
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
/tmp
|
||||
@@ -1,2 +0,0 @@
|
||||
script:
|
||||
- "ruby run_test.rb all test"
|
||||
@@ -1,7 +1,5 @@
|
||||
mruby-io
|
||||
========
|
||||
[](https://travis-ci.org/iij/mruby-io)
|
||||
|
||||
|
||||
`IO` and `File` classes for mruby
|
||||
|
||||
@@ -9,7 +7,7 @@ mruby-io
|
||||
Add the line below to your `build_config.rb`:
|
||||
|
||||
```
|
||||
conf.gem :github => 'iij/mruby-io'
|
||||
conf.gem core: 'mruby-io'
|
||||
```
|
||||
|
||||
## Implemented methods
|
||||
|
||||
@@ -6,7 +6,7 @@ MRuby::Gem::Specification.new('mruby-io') do |spec|
|
||||
spec.cc.include_paths << "#{build.root}/src"
|
||||
|
||||
case RUBY_PLATFORM
|
||||
when /mingw|mswin/
|
||||
when /mingw|mswin|msys/
|
||||
spec.linker.libraries += ['Ws2_32']
|
||||
#spec.cc.include_paths += ["C:/Windows/system/include"]
|
||||
spec.linker.library_paths += ["C:/Windows/system"]
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
class File < IO
|
||||
class FileError < Exception; end
|
||||
class NoFileError < FileError; end
|
||||
class UnableToStat < FileError; end
|
||||
class PermissionError < FileError; end
|
||||
|
||||
attr_accessor :path
|
||||
|
||||
def initialize(fd_or_path, mode = "r", perm = 0666)
|
||||
|
||||
@@ -123,8 +123,8 @@ class IO
|
||||
|
||||
def write(string)
|
||||
str = string.is_a?(String) ? string : string.to_s
|
||||
return str.size unless str.size > 0
|
||||
if 0 < @buf.length
|
||||
return 0 if str.empty?
|
||||
unless @buf.empty?
|
||||
# reset real pos ignore buf
|
||||
seek(pos, SEEK_SET)
|
||||
end
|
||||
@@ -140,8 +140,8 @@ class IO
|
||||
def eof?
|
||||
_check_readable
|
||||
begin
|
||||
buf = _read_buf
|
||||
return buf.size == 0
|
||||
_read_buf
|
||||
return @buf.empty?
|
||||
rescue EOFError
|
||||
return true
|
||||
end
|
||||
@@ -150,7 +150,7 @@ class IO
|
||||
|
||||
def pos
|
||||
raise IOError if closed?
|
||||
sysseek(0, SEEK_CUR) - @buf.length
|
||||
sysseek(0, SEEK_CUR) - @buf.bytesize
|
||||
end
|
||||
alias_method :tell, :pos
|
||||
|
||||
@@ -170,8 +170,13 @@ class IO
|
||||
end
|
||||
|
||||
def _read_buf
|
||||
return @buf if @buf && @buf.size > 0
|
||||
@buf = sysread(BUF_SIZE)
|
||||
return @buf if @buf && @buf.bytesize >= 4 # maximum UTF-8 character is 4 bytes
|
||||
@buf ||= ""
|
||||
begin
|
||||
@buf += sysread(BUF_SIZE)
|
||||
rescue EOFError => e
|
||||
raise e if @buf.empty?
|
||||
end
|
||||
end
|
||||
|
||||
def ungetc(substr)
|
||||
@@ -207,9 +212,8 @@ class IO
|
||||
end
|
||||
|
||||
if length
|
||||
consume = (length <= @buf.size) ? length : @buf.size
|
||||
array.push @buf[0, consume]
|
||||
@buf = @buf[consume, @buf.size - consume]
|
||||
consume = (length <= @buf.bytesize) ? length : @buf.bytesize
|
||||
array.push IO._bufread(@buf, consume)
|
||||
length -= consume
|
||||
break if length == 0
|
||||
else
|
||||
@@ -226,12 +230,12 @@ class IO
|
||||
end
|
||||
end
|
||||
|
||||
def readline(arg = $/, limit = nil)
|
||||
def readline(arg = "\n", limit = nil)
|
||||
case arg
|
||||
when String
|
||||
rs = arg
|
||||
when Fixnum
|
||||
rs = $/
|
||||
rs = "\n"
|
||||
limit = arg
|
||||
else
|
||||
raise ArgumentError
|
||||
@@ -242,7 +246,7 @@ class IO
|
||||
end
|
||||
|
||||
if rs == ""
|
||||
rs = $/ + $/
|
||||
rs = "\n\n"
|
||||
end
|
||||
|
||||
array = []
|
||||
@@ -256,12 +260,12 @@ class IO
|
||||
|
||||
if limit && limit <= @buf.size
|
||||
array.push @buf[0, limit]
|
||||
@buf = @buf[limit, @buf.size - limit]
|
||||
@buf[0, limit] = ""
|
||||
break
|
||||
elsif idx = @buf.index(rs)
|
||||
len = idx + rs.size
|
||||
array.push @buf[0, len]
|
||||
@buf = @buf[len, @buf.size - len]
|
||||
@buf[0, len] = ""
|
||||
break
|
||||
else
|
||||
array.push @buf
|
||||
@@ -285,7 +289,7 @@ class IO
|
||||
def readchar
|
||||
_read_buf
|
||||
c = @buf[0]
|
||||
@buf = @buf[1, @buf.size]
|
||||
@buf[0] = ""
|
||||
c
|
||||
end
|
||||
|
||||
@@ -299,6 +303,8 @@ class IO
|
||||
|
||||
# 15.2.20.5.3
|
||||
def each(&block)
|
||||
return to_enum unless block
|
||||
|
||||
while line = self.gets
|
||||
block.call(line)
|
||||
end
|
||||
@@ -307,6 +313,8 @@ class IO
|
||||
|
||||
# 15.2.20.5.4
|
||||
def each_byte(&block)
|
||||
return to_enum(:each_byte) unless block
|
||||
|
||||
while char = self.getc
|
||||
block.call(char)
|
||||
end
|
||||
@@ -364,25 +372,3 @@ STDERR = IO.open(2, "w")
|
||||
$stdin = STDIN
|
||||
$stdout = STDOUT
|
||||
$stderr = STDERR
|
||||
|
||||
module Kernel
|
||||
def print(*args)
|
||||
$stdout.print(*args)
|
||||
end
|
||||
|
||||
def puts(*args)
|
||||
$stdout.puts(*args)
|
||||
end
|
||||
|
||||
def printf(*args)
|
||||
$stdout.printf(*args)
|
||||
end
|
||||
|
||||
def gets(*args)
|
||||
$stdin.gets(*args)
|
||||
end
|
||||
|
||||
def getc(*args)
|
||||
$stdin.getc(*args)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,4 +12,24 @@ module Kernel
|
||||
File.open(file, *rest, &block)
|
||||
end
|
||||
end
|
||||
|
||||
def print(*args)
|
||||
$stdout.print(*args)
|
||||
end
|
||||
|
||||
def puts(*args)
|
||||
$stdout.puts(*args)
|
||||
end
|
||||
|
||||
def printf(*args)
|
||||
$stdout.printf(*args)
|
||||
end
|
||||
|
||||
def gets(*args)
|
||||
$stdin.gets(*args)
|
||||
end
|
||||
|
||||
def getc(*args)
|
||||
$stdin.getc(*args)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
#
|
||||
# mrbgems test runner
|
||||
#
|
||||
|
||||
if __FILE__ == $0
|
||||
repository, dir = 'https://github.com/mruby/mruby.git', 'tmp/mruby'
|
||||
build_args = ARGV
|
||||
|
||||
Dir.mkdir 'tmp' unless File.exist?('tmp')
|
||||
unless File.exist?(dir)
|
||||
system "git clone #{repository} #{dir}"
|
||||
end
|
||||
|
||||
exit system(%Q[cd #{dir}; MRUBY_CONFIG=#{File.expand_path __FILE__} ruby minirake #{build_args.join(' ')}])
|
||||
end
|
||||
|
||||
MRuby::Build.new do |conf|
|
||||
toolchain :gcc
|
||||
conf.gembox 'default'
|
||||
|
||||
conf.gem :git => 'https://github.com/iij/mruby-env.git'
|
||||
conf.enable_test
|
||||
|
||||
conf.gem File.expand_path(File.dirname(__FILE__))
|
||||
end
|
||||
+18
-17
@@ -116,7 +116,7 @@ mrb_file_s_unlink(mrb_state *mrb, mrb_value obj)
|
||||
for (i = 0; i < argc; i++) {
|
||||
const char *utf8_path;
|
||||
pathv = mrb_ensure_string_type(mrb, argv[i]);
|
||||
utf8_path = mrb_string_value_cstr(mrb, &pathv);
|
||||
utf8_path = RSTRING_CSTR(mrb, pathv);
|
||||
path = mrb_locale_from_utf8(utf8_path, -1);
|
||||
if (UNLINK(path) < 0) {
|
||||
mrb_locale_free(path);
|
||||
@@ -134,8 +134,8 @@ mrb_file_s_rename(mrb_state *mrb, mrb_value obj)
|
||||
char *src, *dst;
|
||||
|
||||
mrb_get_args(mrb, "SS", &from, &to);
|
||||
src = mrb_locale_from_utf8(mrb_string_value_cstr(mrb, &from), -1);
|
||||
dst = mrb_locale_from_utf8(mrb_string_value_cstr(mrb, &to), -1);
|
||||
src = mrb_locale_from_utf8(RSTRING_CSTR(mrb, from), -1);
|
||||
dst = mrb_locale_from_utf8(RSTRING_CSTR(mrb, to), -1);
|
||||
if (rename(src, dst) < 0) {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (CHMOD(dst, 0666) == 0 && UNLINK(dst) == 0 && rename(src, dst) == 0) {
|
||||
@@ -146,7 +146,8 @@ mrb_file_s_rename(mrb_state *mrb, mrb_value obj)
|
||||
#endif
|
||||
mrb_locale_free(src);
|
||||
mrb_locale_free(dst);
|
||||
mrb_sys_fail(mrb, mrb_str_to_cstr(mrb, mrb_format(mrb, "(%S, %S)", from, to)));
|
||||
mrb_sys_fail(mrb, RSTRING_CSTR(mrb, mrb_format(mrb, "(%v, %v)", from, to)));
|
||||
return mrb_fixnum_value(-1); /* not reached */
|
||||
}
|
||||
mrb_locale_free(src);
|
||||
mrb_locale_free(dst);
|
||||
@@ -159,12 +160,12 @@ mrb_file_dirname(mrb_state *mrb, mrb_value klass)
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
char dname[_MAX_DIR], vname[_MAX_DRIVE];
|
||||
char buffer[_MAX_DRIVE + _MAX_DIR];
|
||||
const char *utf8_path;
|
||||
char *path;
|
||||
size_t ridx;
|
||||
mrb_value s;
|
||||
mrb_get_args(mrb, "S", &s);
|
||||
path = mrb_locale_from_utf8(mrb_str_to_cstr(mrb, s), -1);
|
||||
_splitpath((const char*)path, vname, dname, NULL, NULL);
|
||||
mrb_get_args(mrb, "z", &utf8_path);
|
||||
path = mrb_locale_from_utf8(utf8_path, -1);
|
||||
_splitpath(path, vname, dname, NULL, NULL);
|
||||
snprintf(buffer, _MAX_DRIVE + _MAX_DIR, "%s%s", vname, dname);
|
||||
mrb_locale_free(path);
|
||||
ridx = strlen(buffer);
|
||||
@@ -248,11 +249,12 @@ mrb_file_realpath(mrb_state *mrb, mrb_value klass)
|
||||
s = mrb_str_append(mrb, s, pathname);
|
||||
pathname = s;
|
||||
}
|
||||
cpath = mrb_locale_from_utf8(mrb_str_to_cstr(mrb, pathname), -1);
|
||||
cpath = mrb_locale_from_utf8(RSTRING_CSTR(mrb, pathname), -1);
|
||||
result = mrb_str_buf_new(mrb, PATH_MAX);
|
||||
if (realpath(cpath, RSTRING_PTR(result)) == NULL) {
|
||||
mrb_locale_free(cpath);
|
||||
mrb_sys_fail(mrb, cpath);
|
||||
return result; /* not reached */
|
||||
}
|
||||
mrb_locale_free(cpath);
|
||||
mrb_str_resize(mrb, result, strlen(RSTRING_PTR(result)));
|
||||
@@ -300,14 +302,14 @@ mrb_file__gethome(mrb_state *mrb, mrb_value klass)
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "non-absolute home");
|
||||
}
|
||||
} else {
|
||||
const char *cuser = mrb_str_to_cstr(mrb, username);
|
||||
const char *cuser = RSTRING_CSTR(mrb, username);
|
||||
struct passwd *pwd = getpwnam(cuser);
|
||||
if (pwd == NULL) {
|
||||
return mrb_nil_value();
|
||||
}
|
||||
home = pwd->pw_dir;
|
||||
if (!mrb_file_is_absolute_path(home)) {
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "non-absolute home of ~%S", username);
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "non-absolute home of ~%v", username);
|
||||
}
|
||||
}
|
||||
home = mrb_locale_from_utf8(home, -1);
|
||||
@@ -393,13 +395,12 @@ mrb_file_s_symlink(mrb_state *mrb, mrb_value klass)
|
||||
int ai = mrb_gc_arena_save(mrb);
|
||||
|
||||
mrb_get_args(mrb, "SS", &from, &to);
|
||||
src = mrb_locale_from_utf8(mrb_str_to_cstr(mrb, from), -1);
|
||||
dst = mrb_locale_from_utf8(mrb_str_to_cstr(mrb, to), -1);
|
||||
|
||||
src = mrb_locale_from_utf8(RSTRING_CSTR(mrb, from), -1);
|
||||
dst = mrb_locale_from_utf8(RSTRING_CSTR(mrb, to), -1);
|
||||
if (symlink(src, dst) == -1) {
|
||||
mrb_locale_free(src);
|
||||
mrb_locale_free(dst);
|
||||
mrb_sys_fail(mrb, mrb_str_to_cstr(mrb, mrb_format(mrb, "(%S, %S)", from, to)));
|
||||
mrb_sys_fail(mrb, RSTRING_CSTR(mrb, mrb_format(mrb, "(%v, %v)", from, to)));
|
||||
}
|
||||
mrb_locale_free(src);
|
||||
mrb_locale_free(dst);
|
||||
@@ -417,16 +418,16 @@ mrb_file_s_chmod(mrb_state *mrb, mrb_value klass) {
|
||||
|
||||
mrb_get_args(mrb, "i*", &mode, &filenames, &argc);
|
||||
for (i = 0; i < argc; i++) {
|
||||
const char *utf8_path = mrb_str_to_cstr(mrb, filenames[i]);
|
||||
const char *utf8_path = RSTRING_CSTR(mrb, filenames[i]);
|
||||
char *path = mrb_locale_from_utf8(utf8_path, -1);
|
||||
if (CHMOD(path, mode) == -1) {
|
||||
mrb_locale_free(path);
|
||||
mrb_sys_fail(mrb, utf8_path);
|
||||
}
|
||||
mrb_locale_free(path);
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
}
|
||||
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
return mrb_fixnum_value(argc);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** file.c - File class
|
||||
** file_test.c - FileTest class
|
||||
*/
|
||||
|
||||
#include "mruby.h"
|
||||
@@ -42,16 +42,9 @@ extern struct mrb_data_type mrb_io_type;
|
||||
static int
|
||||
mrb_stat0(mrb_state *mrb, mrb_value obj, struct stat *st, int do_lstat)
|
||||
{
|
||||
mrb_value tmp;
|
||||
mrb_value io_klass, str_klass;
|
||||
|
||||
io_klass = mrb_obj_value(mrb_class_get(mrb, "IO"));
|
||||
str_klass = mrb_obj_value(mrb_class_get(mrb, "String"));
|
||||
|
||||
tmp = mrb_funcall(mrb, obj, "is_a?", 1, io_klass);
|
||||
if (mrb_test(tmp)) {
|
||||
if (mrb_obj_is_kind_of(mrb, obj, mrb_class_get(mrb, "IO"))) {
|
||||
struct mrb_io *fptr;
|
||||
fptr = (struct mrb_io *)mrb_get_datatype(mrb, obj, &mrb_io_type);
|
||||
fptr = (struct mrb_io *)mrb_data_get_ptr(mrb, obj, &mrb_io_type);
|
||||
|
||||
if (fptr && fptr->fd >= 0) {
|
||||
return fstat(fptr->fd, st);
|
||||
@@ -60,10 +53,8 @@ mrb_stat0(mrb_state *mrb, mrb_value obj, struct stat *st, int do_lstat)
|
||||
mrb_raise(mrb, E_IO_ERROR, "closed stream");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp = mrb_funcall(mrb, obj, "is_a?", 1, str_klass);
|
||||
if (mrb_test(tmp)) {
|
||||
char *path = mrb_locale_from_utf8(mrb_str_to_cstr(mrb, obj), -1);
|
||||
else {
|
||||
char *path = mrb_locale_from_utf8(RSTRING_CSTR(mrb, obj), -1);
|
||||
int ret;
|
||||
if (do_lstat) {
|
||||
ret = LSTAT(path, st);
|
||||
@@ -73,8 +64,6 @@ mrb_stat0(mrb_state *mrb, mrb_value obj, struct stat *st, int do_lstat)
|
||||
mrb_locale_free(path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
+41
-26
@@ -79,7 +79,7 @@ io_get_open_fptr(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
|
||||
fptr = (struct mrb_io *)mrb_get_datatype(mrb, self, &mrb_io_type);
|
||||
fptr = (struct mrb_io *)mrb_data_get_ptr(mrb, self, &mrb_io_type);
|
||||
if (fptr == NULL) {
|
||||
mrb_raise(mrb, E_IO_ERROR, "uninitialized stream.");
|
||||
}
|
||||
@@ -127,7 +127,7 @@ mrb_io_modestr_to_flags(mrb_state *mrb, const char *mode)
|
||||
flags |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
|
||||
break;
|
||||
default:
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %S", mrb_str_new_cstr(mrb, mode));
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %s", mode);
|
||||
}
|
||||
|
||||
while (*m) {
|
||||
@@ -141,7 +141,7 @@ mrb_io_modestr_to_flags(mrb_state *mrb, const char *mode)
|
||||
case ':':
|
||||
/* XXX: PASSTHROUGH*/
|
||||
default:
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %S", mrb_str_new_cstr(mrb, mode));
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %s", mode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,8 +191,7 @@ mrb_fd_cloexec(mrb_state *mrb, int fd)
|
||||
|
||||
flags = fcntl(fd, F_GETFD);
|
||||
if (flags == -1) {
|
||||
mrb_bug(mrb, "mrb_fd_cloexec: fcntl(%S, F_GETFD) failed: %S",
|
||||
mrb_fixnum_value(fd), mrb_fixnum_value(errno));
|
||||
mrb_bug(mrb, "mrb_fd_cloexec: fcntl(%d, F_GETFD) failed: %d", fd, errno);
|
||||
}
|
||||
if (fd <= 2) {
|
||||
flags2 = flags & ~FD_CLOEXEC; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
|
||||
@@ -202,8 +201,7 @@ mrb_fd_cloexec(mrb_state *mrb, int fd)
|
||||
}
|
||||
if (flags != flags2) {
|
||||
if (fcntl(fd, F_SETFD, flags2) == -1) {
|
||||
mrb_bug(mrb, "mrb_fd_cloexec: fcntl(%S, F_SETFD, %S) failed: %S",
|
||||
mrb_fixnum_value(fd), mrb_fixnum_value(flags2), mrb_fixnum_value(errno));
|
||||
mrb_bug(mrb, "mrb_fd_cloexec: fcntl(%d, F_SETFD, %d) failed: %d", fd, flags2, errno);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -334,8 +332,8 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
mrb_get_args(mrb, "S|SH", &cmd, &mode, &opt);
|
||||
io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
|
||||
|
||||
pname = mrb_string_value_cstr(mrb, &cmd);
|
||||
flags = mrb_io_modestr_to_flags(mrb, mrb_string_value_cstr(mrb, &mode));
|
||||
pname = RSTRING_CSTR(mrb, cmd);
|
||||
flags = mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
|
||||
|
||||
doexec = (strcmp("-", pname) != 0);
|
||||
opt_in = option_to_fd(mrb, opt, "in");
|
||||
@@ -381,7 +379,7 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
CloseHandle(ifd[1]);
|
||||
CloseHandle(ofd[0]);
|
||||
CloseHandle(ofd[1]);
|
||||
mrb_raisef(mrb, E_IO_ERROR, "command not found: %S", cmd);
|
||||
mrb_raisef(mrb, E_IO_ERROR, "command not found: %v", cmd);
|
||||
}
|
||||
CloseHandle(pi.hThread);
|
||||
CloseHandle(ifd[0]);
|
||||
@@ -430,8 +428,8 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
mrb_get_args(mrb, "S|SH", &cmd, &mode, &opt);
|
||||
io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
|
||||
|
||||
pname = mrb_string_value_cstr(mrb, &cmd);
|
||||
flags = mrb_io_modestr_to_flags(mrb, mrb_string_value_cstr(mrb, &mode));
|
||||
pname = RSTRING_CSTR(mrb, cmd);
|
||||
flags = mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
|
||||
|
||||
doexec = (strcmp("-", pname) != 0);
|
||||
opt_in = option_to_fd(mrb, opt, "in");
|
||||
@@ -494,7 +492,7 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
close(fd);
|
||||
}
|
||||
mrb_proc_exec(pname);
|
||||
mrb_raisef(mrb, E_IO_ERROR, "command not found: %S", cmd);
|
||||
mrb_raisef(mrb, E_IO_ERROR, "command not found: %v", cmd);
|
||||
_exit(127);
|
||||
}
|
||||
result = mrb_nil_value();
|
||||
@@ -628,7 +626,7 @@ mrb_io_initialize(mrb_state *mrb, mrb_value io)
|
||||
opt = mrb_hash_new(mrb);
|
||||
}
|
||||
|
||||
flags = mrb_io_modestr_to_flags(mrb, mrb_string_value_cstr(mrb, &mode));
|
||||
flags = mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
|
||||
|
||||
mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@buf"), mrb_str_new_cstr(mrb, ""));
|
||||
|
||||
@@ -760,7 +758,6 @@ mrb_io_s_sysclose(mrb_state *mrb, mrb_value klass)
|
||||
int
|
||||
mrb_cloexec_open(mrb_state *mrb, const char *pathname, mrb_int flags, mrb_int mode)
|
||||
{
|
||||
mrb_value emsg;
|
||||
int fd, retry = FALSE;
|
||||
char* fname = mrb_locale_from_utf8(pathname, -1);
|
||||
|
||||
@@ -783,9 +780,7 @@ reopen:
|
||||
}
|
||||
}
|
||||
|
||||
emsg = mrb_format(mrb, "open %S", mrb_str_new_cstr(mrb, pathname));
|
||||
mrb_str_modify(mrb, mrb_str_ptr(emsg));
|
||||
mrb_sys_fail(mrb, RSTRING_PTR(emsg));
|
||||
mrb_sys_fail(mrb, RSTRING_CSTR(mrb, mrb_format(mrb, "open %s", pathname)));
|
||||
}
|
||||
mrb_locale_free(fname);
|
||||
|
||||
@@ -812,8 +807,8 @@ mrb_io_s_sysopen(mrb_state *mrb, mrb_value klass)
|
||||
perm = 0666;
|
||||
}
|
||||
|
||||
pat = mrb_string_value_cstr(mrb, &path);
|
||||
flags = mrb_io_modestr_to_flags(mrb, mrb_string_value_cstr(mrb, &mode));
|
||||
pat = RSTRING_CSTR(mrb, path);
|
||||
flags = mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
|
||||
modenum = mrb_io_flags_to_modenum(mrb, flags);
|
||||
fd = mrb_cloexec_open(mrb, pat, modenum, perm);
|
||||
return mrb_fixnum_value(fd);
|
||||
@@ -912,7 +907,7 @@ mrb_io_syswrite(mrb_state *mrb, mrb_value io)
|
||||
}
|
||||
|
||||
mrb_get_args(mrb, "S", &str);
|
||||
if (mrb_type(str) != MRB_TT_STRING) {
|
||||
if (!mrb_string_p(str)) {
|
||||
buf = mrb_funcall(mrb, str, "to_s", 0);
|
||||
} else {
|
||||
buf = str;
|
||||
@@ -955,7 +950,7 @@ mrb_value
|
||||
mrb_io_closed(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
fptr = (struct mrb_io *)mrb_get_datatype(mrb, io, &mrb_io_type);
|
||||
fptr = (struct mrb_io *)mrb_data_get_ptr(mrb, io, &mrb_io_type);
|
||||
if (fptr == NULL || fptr->fd >= 0) {
|
||||
return mrb_false_value();
|
||||
}
|
||||
@@ -1005,7 +1000,7 @@ static int
|
||||
mrb_io_read_data_pending(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
mrb_value buf = mrb_iv_get(mrb, io, mrb_intern_cstr(mrb, "@buf"));
|
||||
if (mrb_type(buf) == MRB_TT_STRING && RSTRING_LEN(buf) > 0) {
|
||||
if (mrb_string_p(buf) && RSTRING_LEN(buf) > 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -1068,7 +1063,7 @@ mrb_io_s_select(mrb_state *mrb, mrb_value klass)
|
||||
mrb_get_args(mrb, "*", &argv, &argc);
|
||||
|
||||
if (argc < 1 || argc > 4) {
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1..4)", mrb_fixnum_value(argc));
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%i for 1..4)", argc);
|
||||
}
|
||||
|
||||
timeout = mrb_nil_value();
|
||||
@@ -1299,6 +1294,27 @@ mrb_io_sync(mrb_state *mrb, mrb_value self)
|
||||
return mrb_bool_value(fptr->sync);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
io_bufread(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value str, str2;
|
||||
mrb_int len, newlen;
|
||||
struct RString *s;
|
||||
char *p;
|
||||
|
||||
mrb_get_args(mrb, "Si", &str, &len);
|
||||
s = RSTRING(str);
|
||||
mrb_str_modify(mrb, s);
|
||||
p = RSTR_PTR(s);
|
||||
str2 = mrb_str_new(mrb, p, len);
|
||||
newlen = RSTR_LEN(s)-len;
|
||||
memmove(p, p+len, newlen);
|
||||
p[newlen] = '\0';
|
||||
RSTR_SET_LEN(s, newlen);
|
||||
|
||||
return str2;
|
||||
}
|
||||
|
||||
void
|
||||
mrb_init_io(mrb_state *mrb)
|
||||
{
|
||||
@@ -1334,6 +1350,5 @@ mrb_init_io(mrb_state *mrb)
|
||||
mrb_define_method(mrb, io, "pid", mrb_io_pid, MRB_ARGS_NONE()); /* 15.2.20.5.2 */
|
||||
mrb_define_method(mrb, io, "fileno", mrb_io_fileno, MRB_ARGS_NONE());
|
||||
|
||||
|
||||
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$/"), mrb_str_new_cstr(mrb, "\n"));
|
||||
mrb_define_class_method(mrb, io, "_bufread", io_bufread, MRB_ARGS_REQ(2));
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
##
|
||||
# File Test
|
||||
|
||||
assert('File TEST SETUP') do
|
||||
MRubyIOTestUtil.io_test_setup
|
||||
end
|
||||
MRubyIOTestUtil.io_test_setup
|
||||
|
||||
assert('File', '15.2.21') do
|
||||
assert('File.class', '15.2.21') do
|
||||
assert_equal Class, File.class
|
||||
end
|
||||
|
||||
assert('File', '15.2.21.2') do
|
||||
assert('File.superclass', '15.2.21.2') do
|
||||
assert_equal IO, File.superclass
|
||||
end
|
||||
|
||||
@@ -35,6 +33,7 @@ assert('File.basename') do
|
||||
assert_equal 'a', File.basename('/a/')
|
||||
assert_equal 'b', File.basename('/a/b')
|
||||
assert_equal 'b', File.basename('../a/b')
|
||||
assert_raise(ArgumentError) { File.basename("/a/b\0") }
|
||||
end
|
||||
|
||||
assert('File.dirname') do
|
||||
@@ -108,6 +107,8 @@ assert('File.realpath') do
|
||||
MRubyIOTestUtil.rmdir dir
|
||||
end
|
||||
end
|
||||
|
||||
assert_raise(ArgumentError) { File.realpath("TO\0DO") }
|
||||
end
|
||||
|
||||
assert("File.readlink") do
|
||||
@@ -178,20 +179,25 @@ end
|
||||
|
||||
assert('File.symlink') do
|
||||
target_name = "/usr/bin"
|
||||
symlink_name = "test-bin-dummy"
|
||||
if !File.exist?(target_name)
|
||||
skip("target directory of File.symlink is not found")
|
||||
else
|
||||
begin
|
||||
assert_equal 0, File.symlink(target_name, symlink_name)
|
||||
begin
|
||||
assert_equal true, File.symlink?(symlink_name)
|
||||
ensure
|
||||
File.delete symlink_name
|
||||
end
|
||||
rescue NotImplementedError => e
|
||||
skip e.message
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
tmpdir = MRubyIOTestUtil.mkdtemp("mruby-io-test.XXXXXX")
|
||||
rescue => e
|
||||
skip e.message
|
||||
end
|
||||
|
||||
symlink_name = "#{tmpdir}/test-bin-dummy"
|
||||
begin
|
||||
assert_equal 0, File.symlink(target_name, symlink_name)
|
||||
assert_equal true, File.symlink?(symlink_name)
|
||||
rescue NotImplementedError => e
|
||||
skip e.message
|
||||
ensure
|
||||
File.delete symlink_name rescue nil
|
||||
MRubyIOTestUtil.rmdir tmpdir rescue nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -204,6 +210,4 @@ assert('File.chmod') do
|
||||
end
|
||||
end
|
||||
|
||||
assert('File TEST CLEANUP') do
|
||||
assert_nil MRubyIOTestUtil.io_test_cleanup
|
||||
end
|
||||
MRubyIOTestUtil.io_test_cleanup
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
##
|
||||
# FileTest
|
||||
|
||||
assert('FileTest TEST SETUP') do
|
||||
MRubyIOTestUtil.io_test_setup
|
||||
end
|
||||
MRubyIOTestUtil.io_test_setup
|
||||
|
||||
assert("FileTest.directory?") do
|
||||
dir = MRubyIOTestUtil.mkdtemp("mruby-io-test.XXXXXX")
|
||||
@@ -22,9 +20,8 @@ assert("FileTest.exist?") do
|
||||
assert_equal true, FileTest.exist?(io), "io obj - exist"
|
||||
io.close
|
||||
assert_equal true, io.closed?
|
||||
assert_raise IOError do
|
||||
FileTest.exist?(io)
|
||||
end
|
||||
assert_raise(IOError) { FileTest.exist?(io) }
|
||||
assert_raise(TypeError) { File.exist?($mrbtest_io_rfname.to_sym) }
|
||||
end
|
||||
|
||||
assert("FileTest.file?") do
|
||||
@@ -112,6 +109,4 @@ assert("FileTest.zero?") do
|
||||
assert_true fp2.closed?
|
||||
end
|
||||
|
||||
assert('FileTest TEST CLEANUP') do
|
||||
assert_nil MRubyIOTestUtil.io_test_cleanup
|
||||
end
|
||||
MRubyIOTestUtil.io_test_cleanup
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user