Merge master.

This commit is contained in:
Hiroshi Mimaki
2019-10-18 14:46:03 +09:00
228 changed files with 12034 additions and 5430 deletions
+2 -2
View File
@@ -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
View File
@@ -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
+2408
View File
File diff suppressed because it is too large Load Diff
+19 -6
View File
@@ -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
+3 -12
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+5
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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. |
* | &vert; | 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);
+4 -4
View File
@@ -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)
+2 -9
View File
@@ -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
View File
@@ -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
View File
@@ -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 */
+7 -5
View File
@@ -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*);
+9 -7
View File
@@ -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
+6 -6
View File
@@ -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;
+5 -5
View File
@@ -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;
}
+2 -2
View File
@@ -1,5 +1,5 @@
/*
** mruby/debug.h - mruby debug info
/**
** @file mruby/debug.h - mruby debug info
**
** See Copyright Notice in mruby.h
*/
+3 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+4 -4
View File
@@ -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()
+2 -2
View File
@@ -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
View File
@@ -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 */
+8 -9
View File
@@ -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 {
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -1,5 +1,5 @@
/*
** mruby/re.h - Regexp class
/**
** @file mruby/re.h - Regexp class
**
** See Copyright Notice in mruby.h
*/
+127 -104
View File
@@ -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
+2 -2
View File
@@ -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
View File
@@ -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
+3 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+23 -8
View File
@@ -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
View File
@@ -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
+73
View File
@@ -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
+27 -11
View File
@@ -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
+3
View File
@@ -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
-1
View File
@@ -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
+47 -9
View File
@@ -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
+3 -3
View File
@@ -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
+50 -23
View File
@@ -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;
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -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
+28 -1
View File
@@ -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';
+1 -2
View File
@@ -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]) {
+54 -4
View File
@@ -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
+15 -28
View File
@@ -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;
}
+3 -8
View File
@@ -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);
+69 -46
View File
@@ -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;
-3
View File
@@ -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;
+86 -94
View File
@@ -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"
File diff suppressed because it is too large Load Diff
+10
View File
@@ -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
+122
View File
@@ -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
+249
View File
@@ -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)
{
}
+153
View File
@@ -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
+20 -18
View File
@@ -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
+41 -9
View File
@@ -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
+30 -4
View File
@@ -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
+8 -3
View File
@@ -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
-1
View File
@@ -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
+46 -14
View File
@@ -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 }
+51 -2
View File
@@ -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
+10
View File
@@ -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;
}
+46 -43
View File
@@ -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
+2 -2
View File
@@ -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"
+15 -11
View File
@@ -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));
+1 -1
View File
@@ -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
+3
View File
@@ -494,4 +494,7 @@ class Hash
self.fetch(k, &block)
end
end
alias filter select
alias filter! select!
end
-1
View File
@@ -1 +0,0 @@
/tmp
-2
View File
@@ -1,2 +0,0 @@
script:
- "ruby run_test.rb all test"
+1 -3
View File
@@ -1,7 +1,5 @@
mruby-io
========
[![Build Status](https://travis-ci.org/iij/mruby-io.svg?branch=master)](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
+1 -1
View File
@@ -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"]
-5
View File
@@ -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)
+24 -38
View File
@@ -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
+20
View File
@@ -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
-26
View File
@@ -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
View File
@@ -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);
}
+5 -16
View File
@@ -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
View File
@@ -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));
}
+24 -20
View File
@@ -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
+4 -9
View File
@@ -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