mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge branch 'master' into i110/inspect-recursion
This commit is contained in:
+15
-8
@@ -1,13 +1,12 @@
|
||||
# /
|
||||
*.bak
|
||||
*.bc
|
||||
*.d
|
||||
*.i
|
||||
*.o
|
||||
/benchmark/**/*.dat
|
||||
/benchmark/*.pdf
|
||||
/benchmark/*.png
|
||||
*.orig
|
||||
*.pdb
|
||||
*.rej
|
||||
*.s
|
||||
*.sav
|
||||
*.swp
|
||||
*.tmp
|
||||
@@ -15,13 +14,21 @@
|
||||
.DS_Store
|
||||
.ccmalloc
|
||||
.svn
|
||||
/.git
|
||||
.vscode
|
||||
.yardoc
|
||||
cscope.files
|
||||
cscope.out
|
||||
tags
|
||||
/src/y.tab.c
|
||||
|
||||
/.git
|
||||
/bin
|
||||
/build
|
||||
/mruby-source-*.gem
|
||||
doc/api
|
||||
.yardoc
|
||||
|
||||
/benchmark/**/*.dat
|
||||
/benchmark/*.pdf
|
||||
/benchmark/*.png
|
||||
|
||||
/doc/api
|
||||
|
||||
/src/y.tab.c
|
||||
|
||||
+3
-4
@@ -5,7 +5,7 @@ sudo: false
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
sudo: 9000
|
||||
sudo: false
|
||||
- os: osx
|
||||
osx_image: xcode7.1
|
||||
|
||||
@@ -15,6 +15,5 @@ addons:
|
||||
- gperf
|
||||
|
||||
env:
|
||||
MRUBY_CONFIG=travis_config.rb
|
||||
env: MRUBY_CONFIG=travis_config.rb
|
||||
script: "./minirake all test"
|
||||
- MRUBY_CONFIG=travis_config.rb
|
||||
script: "./minirake -j4 all test"
|
||||
|
||||
@@ -12,6 +12,6 @@ mrbgems/*/mrblib/**/*.rb
|
||||
mrbgems/*/include/**/*.h
|
||||
-
|
||||
AUTHORS
|
||||
MITL
|
||||
LICENSE
|
||||
CONTRIBUTING.md
|
||||
doc/guides/*.md
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
Original Authors "mruby developers" are:
|
||||
Yukihiro Matsumoto
|
||||
This is the (likely incomplete) list of "mruby developers".
|
||||
If you submit a patch to mruby, please add your name to the end
|
||||
of this list.
|
||||
|
||||
Yukihiro Matsumoto (Matz)
|
||||
SCSK KYUSHU CORPORATION
|
||||
Kyushu Institute of Technology
|
||||
Network Applied Communication Laboratory, Inc.
|
||||
@@ -38,3 +41,4 @@ Original Authors "mruby developers" are:
|
||||
Christopher Aue
|
||||
Masahiro Wakame
|
||||
YAMAMOTO Masaya
|
||||
KOBAYASHI Shuji
|
||||
|
||||
@@ -2,5 +2,5 @@ LEGAL NOTICE INFORMATION
|
||||
------------------------
|
||||
|
||||
All the files in this distribution are covered under the MIT license
|
||||
(see the file MITL) except some files mentioned below:
|
||||
(see the file LICENSE) except some files mentioned below:
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2018 mruby developers
|
||||
Copyright (c) 2019 mruby developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -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.
|
||||
@@ -17,7 +17,7 @@ of the Ministry of Economy, Trade and Industry of Japan.
|
||||
|
||||
## How to get mruby
|
||||
|
||||
The stable version 1.4.1 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/1.4.1.zip](https://github.com/mruby/mruby/archive/1.4.1.zip)
|
||||
The stable version 2.0.1 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/2.0.1.zip](https://github.com/mruby/mruby/archive/2.0.1.zip)
|
||||
|
||||
The latest development version of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/zipball/master](https://github.com/mruby/mruby/zipball/master)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -54,12 +54,12 @@ Or
|
||||
|
||||
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](MITL).
|
||||
mruby is released under the [MIT License](https://github.com/mruby/mruby/blob/master/LICENSE).
|
||||
|
||||
## Note for License
|
||||
|
||||
@@ -88,5 +88,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
|
||||
|
||||
@@ -32,20 +32,25 @@ load "#{MRUBY_ROOT}/tasks/benchmark.rake"
|
||||
|
||||
load "#{MRUBY_ROOT}/tasks/gitlab.rake"
|
||||
|
||||
def install_D(src, dst)
|
||||
opts = { :verbose => $verbose }
|
||||
FileUtils.rm_f dst, opts
|
||||
FileUtils.mkdir_p File.dirname(dst), opts
|
||||
FileUtils.cp src, dst, opts
|
||||
end
|
||||
|
||||
##############################
|
||||
# generic build targets, rules
|
||||
task :default => :all
|
||||
|
||||
bin_path = ENV['INSTALL_DIR'] || "#{MRUBY_ROOT}/bin"
|
||||
FileUtils.mkdir_p bin_path, { :verbose => $verbose }
|
||||
|
||||
depfiles = MRuby.targets['host'].bins.map do |bin|
|
||||
install_path = MRuby.targets['host'].exefile("#{bin_path}/#{bin}")
|
||||
source_path = MRuby.targets['host'].exefile("#{MRuby.targets['host'].build_dir}/bin/#{bin}")
|
||||
|
||||
file install_path => source_path do |t|
|
||||
FileUtils.rm_f t.name, { :verbose => $verbose }
|
||||
FileUtils.cp t.prerequisites.first, t.name, { :verbose => $verbose }
|
||||
install_D t.prerequisites.first, t.name
|
||||
end
|
||||
|
||||
install_path
|
||||
@@ -65,7 +70,7 @@ MRuby.each_target do |target|
|
||||
exec = exefile("#{build_dir}/bin/#{bin}")
|
||||
objs = Dir.glob("#{current_dir}/tools/#{bin}/*.{c,cpp,cxx,cc}").map { |f| objfile(f.pathmap("#{current_build_dir}/tools/#{bin}/%n")) }
|
||||
|
||||
file exec => objs + [libfile("#{build_dir}/lib/libmruby")] do |t|
|
||||
file exec => objs + target.libraries do |t|
|
||||
gem_flags = gems.map { |g| g.linker.flags }
|
||||
gem_flags_before_libraries = gems.map { |g| g.linker.flags_before_libraries }
|
||||
gem_flags_after_libraries = gems.map { |g| g.linker.flags_after_libraries }
|
||||
@@ -78,8 +83,7 @@ MRuby.each_target do |target|
|
||||
install_path = MRuby.targets['host'].exefile("#{bin_path}/#{bin}")
|
||||
|
||||
file install_path => exec do |t|
|
||||
FileUtils.rm_f t.name, { :verbose => $verbose }
|
||||
FileUtils.cp t.prerequisites.first, t.name, { :verbose => $verbose }
|
||||
install_D t.prerequisites.first, t.name
|
||||
end
|
||||
depfiles += [ install_path ]
|
||||
elsif target == MRuby.targets['host-debug']
|
||||
@@ -87,8 +91,7 @@ MRuby.each_target do |target|
|
||||
install_path = MRuby.targets['host-debug'].exefile("#{bin_path}/#{bin}")
|
||||
|
||||
file install_path => exec do |t|
|
||||
FileUtils.rm_f t.name, { :verbose => $verbose }
|
||||
FileUtils.cp t.prerequisites.first, t.name, { :verbose => $verbose }
|
||||
install_D t.prerequisites.first, t.name
|
||||
end
|
||||
depfiles += [ install_path ]
|
||||
end
|
||||
@@ -100,7 +103,7 @@ MRuby.each_target do |target|
|
||||
end
|
||||
|
||||
depfiles += MRuby.targets.map { |n, t|
|
||||
[t.libfile("#{t.build_dir}/lib/libmruby")]
|
||||
t.libraries
|
||||
}.flatten
|
||||
|
||||
depfiles += MRuby.targets.reject { |n, t| n == 'host' }.map { |n, t|
|
||||
@@ -118,9 +121,22 @@ task :all => depfiles do
|
||||
end
|
||||
|
||||
desc "run all mruby tests"
|
||||
task :test => ["all"] do
|
||||
MRuby.each_target do
|
||||
run_test if test_enabled?
|
||||
task :test
|
||||
MRuby.each_target do
|
||||
if test_enabled?
|
||||
t = :"test_#{self.name}"
|
||||
task t => ["all"] do
|
||||
run_test
|
||||
end
|
||||
task :test => t
|
||||
end
|
||||
|
||||
if bintest_enabled?
|
||||
t = :"bintest_#{self.name}"
|
||||
task t => ["all"] do
|
||||
run_bintest
|
||||
end
|
||||
task :test => t
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@ Things to do (Things that are not done yet)
|
||||
|
||||
* special variables ($1,$2..)
|
||||
* super in aliased methods
|
||||
* multi-assignment decomposing
|
||||
* keyword arguments in def statement
|
||||
|
||||
Things to improve (Done but things to fix)
|
||||
|
||||
|
||||
+11
-7
@@ -1,16 +1,19 @@
|
||||
version: "{build}"
|
||||
|
||||
os: Visual Studio 2015
|
||||
os: Visual Studio 2017
|
||||
|
||||
clone_depth: 50
|
||||
shallow_clone: true
|
||||
|
||||
|
||||
cache:
|
||||
- win_flex_bison-2.5.10.zip
|
||||
- win_flex_bison
|
||||
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
# Visual Studio 2017 64bit
|
||||
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat
|
||||
|
||||
# Visual Studio 2015 64bit
|
||||
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
|
||||
machine: amd64
|
||||
@@ -28,11 +31,12 @@ init:
|
||||
|
||||
|
||||
install:
|
||||
- if not exist win_flex_bison-2.5.10.zip appveyor DownloadFile "https://github.com/lexxmark/winflexbison/releases/download/v.2.5.10/win_flex_bison-2.5.10.zip"
|
||||
- 7z x -y -owin_flex_bison win_flex_bison-2.5.10.zip > nul
|
||||
|
||||
- if not exist win_flex_bison (
|
||||
appveyor DownloadFile "https://github.com/lexxmark/winflexbison/releases/download/v.2.5.10/win_flex_bison-2.5.10.zip" &
|
||||
7z x -y -owin_flex_bison win_flex_bison-2.5.10.zip
|
||||
)
|
||||
|
||||
build_script:
|
||||
- set YACC=.\win_flex_bison\win_bison.exe
|
||||
- set MRUBY_CONFIG=appveyor_config.rb
|
||||
- ruby .\minirake test all
|
||||
- rake -E $stdout.sync=true test
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ MRuby::Build.new('full-debug') do |conf|
|
||||
|
||||
# include all core GEMs
|
||||
conf.gembox 'full-core'
|
||||
conf.cc.defines = %w(MRB_ENABLE_DEBUG_HOOK)
|
||||
conf.cc.defines += %w(MRB_ENABLE_DEBUG_HOOK)
|
||||
|
||||
conf.enable_test
|
||||
end
|
||||
|
||||
@@ -48,5 +48,4 @@ answer = to_array(solution).map do |p|
|
||||
to_string(p)
|
||||
end
|
||||
|
||||
answer_str = answer.to_a
|
||||
# puts answer_str
|
||||
# puts answer
|
||||
|
||||
+3
-2
@@ -8,7 +8,8 @@ MRuby::Build.new do |conf|
|
||||
toolchain :gcc
|
||||
end
|
||||
|
||||
enable_debug
|
||||
# Turn on `enable_debug` for better debugging
|
||||
# enable_debug
|
||||
|
||||
# Use mrbgems
|
||||
# conf.gem 'examples/mrbgems/ruby_extension_example'
|
||||
@@ -28,7 +29,7 @@ MRuby::Build.new do |conf|
|
||||
# cc.command = ENV['CC'] || 'gcc'
|
||||
# cc.flags = [ENV['CFLAGS'] || %w()]
|
||||
# cc.include_paths = ["#{root}/include"]
|
||||
# cc.defines = %w(DISABLE_GEMS)
|
||||
# cc.defines = %w()
|
||||
# cc.option_include_path = '-I%s'
|
||||
# cc.option_define = '-D%s'
|
||||
# cc.compile_options = "%{flags} -MMD -o %{outfile} -c %{infile}"
|
||||
|
||||
@@ -38,7 +38,7 @@ To confirm mrdb was installed properly, run mrdb with the `--version` option:
|
||||
|
||||
```bash
|
||||
$ mrdb --version
|
||||
mruby 1.4.1 (2018-4-27)
|
||||
mruby 2.0.1 (2019-4-4)
|
||||
```
|
||||
|
||||
## 2.2 Basic Operation
|
||||
|
||||
+50
-6
@@ -50,15 +50,21 @@ You can use mrbconfs with following ways:
|
||||
* When defined single precision floating point type(C type `float`) is used as `mrb_float`.
|
||||
* Else double precision floating point type(C type `double`) is used as `mrb_float`.
|
||||
|
||||
`MRB_WITHOUT_FLOAT`
|
||||
* When defined removes floating point numbers from mruby.
|
||||
* It makes mruby easier to handle in "Microcontroller without FPU" and "Kernel Space".
|
||||
|
||||
`MRB_INT16`
|
||||
* When defined `int16_t` will be defined as `mrb_int`.
|
||||
* Conflicts with `MRB_INT64`.
|
||||
* Conflicts with `MRB_INT32` and `MRB_INT64`.
|
||||
|
||||
`MRB_INT32`
|
||||
* When defined, or both `MRB_INT16` and `MRB_INT64` are not defined on 32-bit CPU mode, `int32_t` will be defined as `mrb_int`.
|
||||
* Conflicts with `MRB_INT16` and `MRB_INT64`.
|
||||
|
||||
`MRB_INT64`
|
||||
* When defined `int64_t` will be defined as `mrb_int`.
|
||||
* Conflicts with `MRB_INT16`.
|
||||
* When `MRB_INT16` or `MRB_INT64` isn't defined `int`(most of the times 32-bit integer)
|
||||
will be defined as `mrb_int`.
|
||||
* When defined, or both `MRB_INT16` and `MRB_INT32` are not defined on 64-bit CPU mode, `int64_t` will be defined as `mrb_int`.
|
||||
* Conflicts with `MRB_INT16` and `MRB_INT32`.
|
||||
|
||||
## Garbage collector configuration.
|
||||
|
||||
@@ -115,7 +121,7 @@ largest value of required alignment.
|
||||
|
||||
`MRB_NAN_BOXING`
|
||||
* If defined represent `mrb_value` in boxed `double`.
|
||||
* Conflicts with `MRB_USE_FLOAT`.
|
||||
* Conflicts with `MRB_USE_FLOAT` and `MRB_WITHOUT_FLOAT`.
|
||||
|
||||
`MRB_WORD_BOXING`
|
||||
* If defined represent `mrb_value` as a word.
|
||||
@@ -126,6 +132,27 @@ largest value of required alignment.
|
||||
* Default value is `4`.
|
||||
* Specifies size of each segment in segment list.
|
||||
|
||||
## Reduce heap memory configuration.
|
||||
|
||||
`MRB_USE_ETEXT_EDATA`
|
||||
* 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 `_etext` and `__init_array_start`.
|
||||
* It must be `_etext < data_addr < &__init_array_start`.
|
||||
|
||||
`MRB_NO_INIT_ARRAY_START`
|
||||
* Ignored if `MRB_USE_ETEXT_EDATA` is not defined.
|
||||
* Please try if `__init_array_start` is not available.
|
||||
* Uses `_etext` and `_edata`.
|
||||
* It must be `_etext < data_addr < _edata`.
|
||||
|
||||
`MRB_USE_CUSTOM_RO_DATA_P`
|
||||
* Takes precedence over `MRB_USE_ETEXT_EDATA`.
|
||||
* Please try if both `MRB_USE_ETEXT_EDATA` and `MRB_NO_INIT_ARRAY_START` are 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 +171,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_TABLE_INLINE`
|
||||
* Reduce the size of method table.
|
||||
* Requires LSB of function pointers to be zero.
|
||||
* For example, you might need to specify `--falign-functions=n` (where `n > 1`) for GCC.
|
||||
|
||||
`MRB_ENABLE_ALL_SYMBOLS`
|
||||
* Make it available `Symbols.all_symbols` in `mrbgems/mruby-symbol-ext`
|
||||
* Increase heap memory usage.
|
||||
|
||||
@@ -179,11 +179,11 @@ Version requirement supports following operators:
|
||||
|
||||
When more than one version requirements is passed, the dependency must satisfy all of it.
|
||||
|
||||
You can have default gem to use as depedency when it's not defined in *build_config.rb*.
|
||||
You can have default gem to use as dependency when it's not defined in *build_config.rb*.
|
||||
When the last argument of `add_dependency` call is `Hash`, it will be treated as default gem information.
|
||||
Its format is same as argument of method `MRuby::Build#gem`, expect that it can't be treated as path gem location.
|
||||
|
||||
When a special version of depedency is required,
|
||||
When a special version of dependency is required,
|
||||
use `MRuby::Build#gem` in *build_config.rb* to override default gem.
|
||||
|
||||
If you have conflicting GEMs use the following method:
|
||||
|
||||
+69
-7
@@ -38,7 +38,7 @@ puts [1,2,3]
|
||||
3
|
||||
```
|
||||
|
||||
#### mruby [1.4.1 (2018-4-27)]
|
||||
#### mruby [2.0.1 (2019-4-4)]
|
||||
|
||||
```
|
||||
[1, 2, 3]
|
||||
@@ -61,7 +61,7 @@ end
|
||||
|
||||
```ZeroDivisionError``` is raised.
|
||||
|
||||
#### mruby [1.4.1 (2018-4-27)]
|
||||
#### mruby [2.0.1 (2019-4-4)]
|
||||
|
||||
No exception is raised.
|
||||
|
||||
@@ -89,7 +89,7 @@ p Liste.new "foobar"
|
||||
|
||||
``` [] ```
|
||||
|
||||
#### mruby [1.4.1 (2018-4-27)]
|
||||
#### mruby [2.0.1 (2019-4-4)]
|
||||
|
||||
```ArgumentError``` is raised.
|
||||
|
||||
@@ -119,7 +119,7 @@ false
|
||||
true
|
||||
```
|
||||
|
||||
#### mruby [1.4.1 (2018-4-27)]
|
||||
#### mruby [2.0.1 (2019-4-4)]
|
||||
|
||||
```
|
||||
true
|
||||
@@ -142,7 +142,7 @@ defined?(Foo)
|
||||
nil
|
||||
```
|
||||
|
||||
#### mruby [1.4.1 (2018-4-27)]
|
||||
#### mruby [2.0.1 (2019-4-4)]
|
||||
|
||||
```NameError``` is raised.
|
||||
|
||||
@@ -159,7 +159,7 @@ alias $a $__a__
|
||||
|
||||
``` nil ```
|
||||
|
||||
#### mruby [1.4.1 (2018-4-27)]
|
||||
#### mruby [2.0.1 (2019-4-4)]
|
||||
|
||||
Syntax error
|
||||
|
||||
@@ -181,7 +181,69 @@ end
|
||||
```ArgumentError``` is raised.
|
||||
The re-defined ```+``` operator does not accept any arguments.
|
||||
|
||||
#### mruby [1.4.1 (2018-4-27)]
|
||||
#### mruby [2.0.1 (2019-4-4)]
|
||||
|
||||
``` 'ab' ```
|
||||
Behavior of the operator wasn't changed.
|
||||
|
||||
## Kernel#binding is not supported
|
||||
|
||||
`Kernel#binding` method is not supported.
|
||||
|
||||
#### Ruby [ruby 2.5.1p57 (2018-03-29 revision 63029)]
|
||||
|
||||
```
|
||||
$ ruby -e 'puts Proc.new {}.binding'
|
||||
#<Binding:0x00000e9deabb9950>
|
||||
```
|
||||
|
||||
#### mruby [2.0.1 (2019-4-4)]
|
||||
|
||||
```
|
||||
$ ./bin/mruby -e 'puts Proc.new {}.binding'
|
||||
trace (most recent call last):
|
||||
[0] -e:1
|
||||
-e:1: undefined method 'binding' (NoMethodError)
|
||||
```
|
||||
|
||||
## Keyword arguments
|
||||
|
||||
mruby keyword arguments behave slightly different from CRuby 2.5
|
||||
to make the behavior simpler and less confusing. Maybe in the
|
||||
future, the simpler behavior will be adopted to CRuby as well.
|
||||
|
||||
#### Ruby [ruby 2.5.1p57 (2018-03-29 revision 63029)]
|
||||
|
||||
```
|
||||
$ ruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
|
||||
[[{"a"=>1}], {:b=>2}]
|
||||
```
|
||||
|
||||
#### mruby [mruby 2.0.1]
|
||||
|
||||
```
|
||||
$ ./bin/mruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
|
||||
trace (most recent call last):
|
||||
[0] -e:1
|
||||
-e:1: keyword argument hash with non symbol keys (ArgumentError)
|
||||
```
|
||||
|
||||
## Argument Destructuring
|
||||
|
||||
```ruby
|
||||
def m(a,(b,c),d); p [a,b,c,d]; end
|
||||
m(1,[2,3],4) # => [1,2,3,4]
|
||||
```
|
||||
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]
|
||||
end
|
||||
f(1,[2,3])
|
||||
```
|
||||
|
||||
CRuby gives `[1,2,3,nil]`. mruby raises `NoMethodError` for `b`.
|
||||
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
# The new bytecode
|
||||
|
||||
We will reimplement VM to use 8bit instruction code. By
|
||||
bytecode, we mean real byte code. The whole purpose is
|
||||
reducing the memory consumption of mruby VM.
|
||||
|
||||
# Instructions
|
||||
|
||||
Instructions are bytes. There can be 256 instructions. Currently we
|
||||
have 94 instructions. Instructions can take 0 to 3 operands.
|
||||
|
||||
## operands
|
||||
|
||||
The size of operands can be either 8bits, 16bits or 24bits.
|
||||
In the table.1 below, the second field describes the size (and
|
||||
sign) of operands.
|
||||
|
||||
* B: 8bit
|
||||
* sB: signed 8bit
|
||||
* S: 16bit
|
||||
* sS: signed 16bit
|
||||
* W: 24bit
|
||||
|
||||
First two byte operands may be extended to 16bit. When those byte
|
||||
operands are bigger than 256, the instruction will be prefixed by
|
||||
`OP_EXT1` (means 1st operand is 16bit) or `OP_EXT2` (means 2nd operand
|
||||
is 16bit) or `OP_EXT3` (means 1st and 2nd operands are 16bit).
|
||||
|
||||
For instructions marked by `'`, `OP_EXT1` can be prefixed. For those
|
||||
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
|
||||
@@ -15,8 +15,8 @@ end
|
||||
|
||||
# Requires Android NDK r13 or later.
|
||||
MRuby::CrossBuild.new('android-arm64-v8a') do |conf|
|
||||
params = {
|
||||
:arch => 'arm64-v8a',
|
||||
params = {
|
||||
:arch => 'arm64-v8a',
|
||||
:platform => 'android-24',
|
||||
:toolchain => :clang,
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@ end
|
||||
|
||||
# Requires Android NDK r13 or later.
|
||||
MRuby::CrossBuild.new('android-armeabi') do |conf|
|
||||
params = {
|
||||
:arch => 'armeabi',
|
||||
params = {
|
||||
:arch => 'armeabi',
|
||||
:platform => 'android-24',
|
||||
:toolchain => :clang,
|
||||
}
|
||||
|
||||
+90
-5
@@ -41,10 +41,15 @@
|
||||
/* you might need to specify --falign-functions=n (where n>1) */
|
||||
//#define MRB_METHOD_TABLE_INLINE
|
||||
|
||||
/* 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,12 +63,20 @@
|
||||
# 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) || \
|
||||
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
# define MRB_ENDIAN_BIG
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* represent mrb_value in boxed double; conflict with MRB_USE_FLOAT and MRB_WITHOUT_FLOAT */
|
||||
//#define MRB_NAN_BOXING
|
||||
|
||||
/* define on big endian machines; used by MRB_NAN_BOXING */
|
||||
//#define MRB_ENDIAN_BIG
|
||||
|
||||
/* represent mrb_value as a word (natural unit of data for the processor) */
|
||||
//#define MRB_WORD_BOXING
|
||||
|
||||
@@ -83,6 +96,11 @@
|
||||
effective only when MRB_USE_ETEXT_EDATA is defined */
|
||||
//#define MRB_NO_INIT_ARRAY_START
|
||||
|
||||
/* if do not works both MRB_USE_ETEXT_EDATA and MRB_NO_INIT_ARRAY_START,
|
||||
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
|
||||
|
||||
@@ -115,6 +133,7 @@
|
||||
|
||||
/* -DMRB_ENABLE_XXXX to enable following features */
|
||||
//#define MRB_ENABLE_DEBUG_HOOK /* hooks for debugger */
|
||||
//#define MRB_ENABLE_ALL_SYMBOLS /* Symbols.all_symbols */
|
||||
|
||||
/* end of configuration */
|
||||
|
||||
@@ -140,4 +159,70 @@
|
||||
# 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_METHOD_TABLE_INLINE
|
||||
# define MRB_METHOD_TABLE_INLINE
|
||||
# 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_METHOD_TABLE_INLINE
|
||||
# define MRB_METHOD_TABLE_INLINE
|
||||
# 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 */
|
||||
|
||||
+52
-46
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
** mruby - An embeddable Ruby implementation
|
||||
**
|
||||
** Copyright (c) mruby developers 2010-2018
|
||||
** Copyright (c) mruby developers 2010-2019
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
@@ -34,6 +34,7 @@
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
@@ -57,7 +58,7 @@
|
||||
#define mrb_assert_int_fit(t1,n,t2,max) ((void)0)
|
||||
#endif
|
||||
|
||||
#if __STDC_VERSION__ >= 201112L
|
||||
#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L
|
||||
#define mrb_static_assert(exp, str) _Static_assert(exp, str)
|
||||
#else
|
||||
#define mrb_static_assert(exp, str) mrb_assert(exp)
|
||||
@@ -83,7 +84,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "mruby/common.h"
|
||||
#include <mruby/common.h>
|
||||
#include <mruby/value.h>
|
||||
#include <mruby/gc.h>
|
||||
#include <mruby/version.h>
|
||||
@@ -93,7 +94,7 @@
|
||||
*/
|
||||
MRB_BEGIN_DECL
|
||||
|
||||
typedef uint32_t mrb_code;
|
||||
typedef uint8_t mrb_code;
|
||||
|
||||
/**
|
||||
* Required arguments signature type.
|
||||
@@ -123,9 +124,8 @@ typedef struct {
|
||||
mrb_sym mid;
|
||||
struct RProc *proc;
|
||||
mrb_value *stackent;
|
||||
int nregs;
|
||||
int ridx;
|
||||
int epos;
|
||||
uint16_t ridx;
|
||||
uint16_t epos;
|
||||
struct REnv *env;
|
||||
mrb_code *pc; /* return address */
|
||||
mrb_code *err; /* error position */
|
||||
@@ -152,10 +152,10 @@ struct mrb_context {
|
||||
mrb_callinfo *ci;
|
||||
mrb_callinfo *cibase, *ciend;
|
||||
|
||||
mrb_code **rescue; /* exception handler stack */
|
||||
int rsize;
|
||||
uint16_t *rescue; /* exception handler stack */
|
||||
uint16_t rsize;
|
||||
struct RProc **ensure; /* ensure handler stack */
|
||||
int esize, eidx;
|
||||
uint16_t esize, eidx;
|
||||
|
||||
enum mrb_fiber_state status;
|
||||
mrb_bool vmexec;
|
||||
@@ -196,13 +196,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 +228,6 @@ typedef struct mrb_state {
|
||||
struct RClass *symbol_class;
|
||||
struct RClass *kernel_module;
|
||||
|
||||
struct alloca_header *mems;
|
||||
mrb_gc gc;
|
||||
|
||||
#ifdef MRB_METHOD_CACHE
|
||||
@@ -240,9 +235,12 @@ typedef struct mrb_state {
|
||||
#endif
|
||||
|
||||
mrb_sym symidx;
|
||||
struct kh_n2s *name2sym; /* symbol hash */
|
||||
struct symbol_name *symtbl; /* symbol table */
|
||||
mrb_sym symhash[256];
|
||||
size_t symcapa;
|
||||
#ifndef MRB_ENABLE_SYMBOLL_ALL
|
||||
char symbuf[8]; /* buffer for small symbol names */
|
||||
#endif
|
||||
|
||||
#ifdef MRB_ENABLE_DEBUG_HOOK
|
||||
void (*code_fetch_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs);
|
||||
@@ -268,7 +266,8 @@ typedef struct mrb_state {
|
||||
#else
|
||||
mrb_atexit_func *atexit_stack;
|
||||
#endif
|
||||
mrb_int atexit_stack_len;
|
||||
uint16_t atexit_stack_len;
|
||||
uint16_t ecall_nest; /* prevent infinite recursive ecall() */
|
||||
} mrb_state;
|
||||
|
||||
/**
|
||||
@@ -386,7 +385,7 @@ MRB_API void mrb_define_class_method(mrb_state *, struct RClass *, const char *,
|
||||
MRB_API void mrb_define_singleton_method(mrb_state*, struct RObject*, const char*, mrb_func_t, mrb_aspec);
|
||||
|
||||
/**
|
||||
* Defines a module fuction.
|
||||
* Defines a module function.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
@@ -486,9 +485,10 @@ MRB_API void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_
|
||||
* }
|
||||
* @param [mrb_state*] mrb_state* The mruby state reference.
|
||||
* @param [struct RClass*] RClass* A class the method will be undefined from.
|
||||
* @param [const char*] constchar* The name of the method to be undefined.
|
||||
* @param [const char*] const char* 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_id(mrb_state*, struct RClass*, mrb_sym);
|
||||
|
||||
/**
|
||||
* Undefine a class method.
|
||||
@@ -525,12 +525,12 @@ MRB_API void mrb_undef_method(mrb_state*, struct RClass*, const char*);
|
||||
* }
|
||||
* @param [mrb_state*] mrb_state* The mruby state reference.
|
||||
* @param [RClass*] RClass* A class the class method will be undefined from.
|
||||
* @param [constchar*] constchar* The name of the class method to be undefined.
|
||||
* @param [const char*] const char* The name of the class method to be undefined.
|
||||
*/
|
||||
MRB_API void mrb_undef_class_method(mrb_state*, struct RClass*, const char*);
|
||||
|
||||
/**
|
||||
* Initialize a new object instace of c class.
|
||||
* Initialize a new object instance of c class.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
@@ -565,8 +565,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.
|
||||
*
|
||||
@@ -704,6 +702,9 @@ MRB_API struct RClass * mrb_module_get(mrb_state *mrb, const char *name);
|
||||
* @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);
|
||||
/* a function to raise NotImplementedError with current method name */
|
||||
MRB_API void mrb_notimplement(mrb_state*);
|
||||
/* a function to be replacement of unimplemented method */
|
||||
MRB_API mrb_value mrb_notimplement_m(mrb_state*, mrb_value);
|
||||
|
||||
/**
|
||||
@@ -716,7 +717,6 @@ MRB_API mrb_value mrb_notimplement_m(mrb_state*, mrb_value);
|
||||
* @return [mrb_value] The newly duplicated object.
|
||||
*/
|
||||
MRB_API mrb_value mrb_obj_dup(mrb_state *mrb, mrb_value obj);
|
||||
MRB_API mrb_value mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method);
|
||||
|
||||
/**
|
||||
* Returns true if obj responds to the given method. If the method was defined for that
|
||||
@@ -783,7 +783,7 @@ MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *o
|
||||
#define MRB_ARGS_REQ(n) ((mrb_aspec)((n)&0x1f) << 18)
|
||||
|
||||
/**
|
||||
* Funtion takes n optional arguments
|
||||
* Function takes n optional arguments
|
||||
*
|
||||
* @param n
|
||||
* The number of optional arguments.
|
||||
@@ -791,7 +791,7 @@ MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *o
|
||||
#define MRB_ARGS_OPT(n) ((mrb_aspec)((n)&0x1f) << 13)
|
||||
|
||||
/**
|
||||
* Funtion takes n1 mandatory arguments and n2 optional arguments
|
||||
* Function takes n1 mandatory arguments and n2 optional arguments
|
||||
*
|
||||
* @param n1
|
||||
* The number of required arguments.
|
||||
@@ -836,15 +836,17 @@ 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. |
|
||||
* | `*` | rest arguments | {mrb_value} *, {mrb_int} | Receive the rest of arguments as an array; `*!` avoid copy of the stack. |
|
||||
* | | | optional | | After this spec following specs would be optional. |
|
||||
* | `?` | optional given | {mrb_bool} | `TRUE` if preceding argument is given. Used to check optional argument is given. |
|
||||
*
|
||||
@@ -855,10 +857,6 @@ typedef const char *mrb_args_format;
|
||||
/**
|
||||
* Retrieve arguments from mrb_state.
|
||||
*
|
||||
* When applicable, implicit conversions (such as `to_str`, `to_ary`, `to_hash`) are
|
||||
* applied to received arguments.
|
||||
* Used inside a function of mrb_func_t type.
|
||||
*
|
||||
* @param mrb The current MRuby state.
|
||||
* @param format [mrb_args_format] is a list of format specifiers
|
||||
* @param ... The passing variadic arguments must be a pointer of retrieving type.
|
||||
@@ -867,7 +865,7 @@ typedef const char *mrb_args_format;
|
||||
*/
|
||||
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;
|
||||
@@ -994,13 +992,13 @@ 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))
|
||||
|
||||
#ifdef _WIN32
|
||||
char* mrb_utf8_from_locale(const char *p, int len);
|
||||
char* mrb_locale_from_utf8(const char *p, int len);
|
||||
MRB_API char* mrb_utf8_from_locale(const char *p, int len);
|
||||
MRB_API char* mrb_locale_from_utf8(const char *p, int len);
|
||||
#define mrb_locale_free(p) free(p)
|
||||
#define mrb_utf8_free(p) free(p)
|
||||
#else
|
||||
#define mrb_utf8_from_locale(p, l) ((char*)p)
|
||||
#define mrb_locale_from_utf8(p, l) ((char*)p)
|
||||
#define mrb_utf8_from_locale(p, l) ((char*)(p))
|
||||
#define mrb_locale_from_utf8(p, l) ((char*)(p))
|
||||
#define mrb_locale_free(p)
|
||||
#define mrb_utf8_free(p)
|
||||
#endif
|
||||
@@ -1080,16 +1078,13 @@ MRB_API mrb_value mrb_Float(mrb_state *mrb, mrb_value val);
|
||||
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);
|
||||
|
||||
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;
|
||||
@@ -1140,10 +1135,13 @@ 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);
|
||||
MRB_API void mrb_print_error(mrb_state *mrb);
|
||||
/* function for `raisef` formatting */
|
||||
MRB_API mrb_value mrb_vformat(mrb_state *mrb, const char *format, va_list ap);
|
||||
|
||||
/* macros to get typical exception objects
|
||||
note:
|
||||
@@ -1188,8 +1186,14 @@ MRB_API void mrb_gc_unregister(mrb_state *mrb, mrb_value obj);
|
||||
|
||||
MRB_API mrb_value mrb_to_int(mrb_state *mrb, mrb_value val);
|
||||
#define mrb_int(mrb, val) mrb_fixnum(mrb_to_int(mrb, val))
|
||||
MRB_API 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,
|
||||
@@ -1197,7 +1201,7 @@ typedef enum call_type {
|
||||
CALL_TYPE_MAX
|
||||
} call_type;
|
||||
|
||||
MRB_API void mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const char *name2);
|
||||
MRB_API void mrb_define_alias(mrb_state *mrb, struct RClass *c, const char *a, const char *b);
|
||||
MRB_API const char *mrb_class_name(mrb_state *mrb, struct RClass* klass);
|
||||
MRB_API void mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val);
|
||||
|
||||
@@ -1235,6 +1239,7 @@ MRB_API mrb_value mrb_fiber_alive_p(mrb_state *mrb, mrb_value fib);
|
||||
* @mrbgem mruby-fiber
|
||||
*/
|
||||
#define E_FIBER_ERROR (mrb_exc_get(mrb, "FiberError"))
|
||||
MRB_API void mrb_stack_extend(mrb_state*, mrb_int);
|
||||
|
||||
/* memory pool implementation */
|
||||
typedef struct mrb_pool mrb_pool;
|
||||
@@ -1243,6 +1248,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);
|
||||
|
||||
+18
-2
@@ -33,7 +33,6 @@ struct RArray {
|
||||
} aux;
|
||||
mrb_value *ptr;
|
||||
} heap;
|
||||
mrb_value embed[MRB_ARY_EMBED_LEN_MAX];
|
||||
} as;
|
||||
};
|
||||
|
||||
@@ -46,7 +45,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)
|
||||
|
||||
#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)
|
||||
@@ -199,6 +198,7 @@ MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val
|
||||
* @param other The array to replace it with.
|
||||
*/
|
||||
MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other);
|
||||
MRB_API mrb_value mrb_ensure_array_type(mrb_state *mrb, mrb_value self);
|
||||
MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self);
|
||||
|
||||
/*
|
||||
@@ -226,6 +226,22 @@ MRB_API mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item
|
||||
*/
|
||||
MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset);
|
||||
|
||||
/*
|
||||
* Replace subsequence of an array.
|
||||
*
|
||||
* Equivalent to:
|
||||
*
|
||||
* ary.shift
|
||||
*
|
||||
* @param mrb The mruby state reference.
|
||||
* @param self The array from which the value will be shifted.
|
||||
* @param head Beginning position of a replacement subsequence.
|
||||
* @param len Length of a replacement subsequence.
|
||||
* @param rpl The array of replacement elements.
|
||||
* @return The receiver array.
|
||||
*/
|
||||
MRB_API mrb_value mrb_ary_splice(mrb_state *mrb, mrb_value self, mrb_int head, mrb_int len, mrb_value rpl);
|
||||
|
||||
/*
|
||||
* Shifts the first element from the array.
|
||||
*
|
||||
|
||||
@@ -81,7 +81,7 @@ typedef struct mrb_value {
|
||||
} while (0)
|
||||
|
||||
#define SET_FLOAT_VALUE(mrb,r,v) do { \
|
||||
if (v != v) { \
|
||||
if ((v) != (v)) { \
|
||||
(r).value.ttt = 0x7ff80000; \
|
||||
(r).value.i = 0; \
|
||||
} \
|
||||
|
||||
+33
-23
@@ -45,6 +45,14 @@ enum mrb_special_consts {
|
||||
#define MRB_SYMBOL_FLAG 0x0e
|
||||
#define MRB_SPECIAL_SHIFT 8
|
||||
|
||||
#if defined(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)
|
||||
#endif
|
||||
|
||||
typedef union mrb_value {
|
||||
union {
|
||||
void *p;
|
||||
@@ -54,7 +62,7 @@ typedef union mrb_value {
|
||||
};
|
||||
struct {
|
||||
unsigned int sym_flag : MRB_SPECIAL_SHIFT;
|
||||
mrb_sym sym : (sizeof(mrb_sym) * CHAR_BIT);
|
||||
mrb_sym sym : MRB_SYMBOL_BITSIZE;
|
||||
};
|
||||
struct RBasic *bp;
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
@@ -83,7 +91,7 @@ MRB_API mrb_value mrb_word_boxing_float_pool(struct mrb_state*, mrb_float);
|
||||
#define mrb_fixnum(o) ((mrb_int)(o).value.i)
|
||||
#define mrb_symbol(o) (o).value.sym
|
||||
|
||||
static inline enum mrb_vtype
|
||||
MRB_INLINE enum mrb_vtype
|
||||
mrb_type(mrb_value o)
|
||||
{
|
||||
switch (o.w) {
|
||||
@@ -108,29 +116,31 @@ mrb_type(mrb_value o)
|
||||
#define mrb_fixnum_p(o) ((o).value.i_flag == MRB_FIXNUM_FLAG)
|
||||
#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 SET_FLOAT_VALUE(mrb,r,v) r = mrb_word_boxing_float_value(mrb, v)
|
||||
#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_CPTR_VALUE(mrb,r,v) ((r) = mrb_word_boxing_cptr_value(mrb, v))
|
||||
#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) do { \
|
||||
(r).w = 0; \
|
||||
(r).value.i_flag = MRB_FIXNUM_FLAG; \
|
||||
(r).value.i = (n); \
|
||||
} while (0)
|
||||
#define SET_SYM_VALUE(r,v) do { \
|
||||
(r).w = 0; \
|
||||
(r).value.sym_flag = MRB_SYMBOL_FLAG; \
|
||||
(r).value.sym = (v); \
|
||||
} while (0)
|
||||
#define SET_OBJ_VALUE(r,v) do { \
|
||||
(r).w = 0; \
|
||||
(r).value.p = (v); \
|
||||
} while (0)
|
||||
|
||||
#endif /* MRUBY_BOXING_WORD_H */
|
||||
|
||||
+21
-16
@@ -22,11 +22,8 @@ struct RClass {
|
||||
};
|
||||
|
||||
#define mrb_class_ptr(v) ((struct RClass*)(mrb_ptr(v)))
|
||||
#define RCLASS_SUPER(v) (((struct RClass*)(mrb_ptr(v)))->super)
|
||||
#define RCLASS_IV_TBL(v) (((struct RClass*)(mrb_ptr(v)))->iv)
|
||||
#define RCLASS_M_TBL(v) (((struct RClass*)(mrb_ptr(v)))->mt)
|
||||
|
||||
static inline struct RClass*
|
||||
MRB_INLINE struct RClass*
|
||||
mrb_class(mrb_state *mrb, mrb_value v)
|
||||
{
|
||||
switch (mrb_type(v)) {
|
||||
@@ -53,22 +50,28 @@ mrb_class(mrb_state *mrb, mrb_value v)
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: figure out where to put user flags */
|
||||
/* flags bits >= 18 is reserved */
|
||||
#define MRB_FLAG_IS_PREPENDED (1 << 19)
|
||||
#define MRB_FLAG_IS_ORIGIN (1 << 20)
|
||||
/* flags:
|
||||
20: frozen
|
||||
19: is_prepended
|
||||
18: is_origin
|
||||
17: is_inherited (used by method cache)
|
||||
16: unused
|
||||
0-15: instance type
|
||||
*/
|
||||
#define MRB_FL_CLASS_IS_PREPENDED (1 << 19)
|
||||
#define MRB_FL_CLASS_IS_ORIGIN (1 << 18)
|
||||
#define MRB_CLASS_ORIGIN(c) do {\
|
||||
if (c->flags & MRB_FLAG_IS_PREPENDED) {\
|
||||
c = c->super;\
|
||||
while (!(c->flags & MRB_FLAG_IS_ORIGIN)) {\
|
||||
c = c->super;\
|
||||
if ((c)->flags & MRB_FL_CLASS_IS_PREPENDED) {\
|
||||
(c) = (c)->super;\
|
||||
while (!((c)->flags & MRB_FL_CLASS_IS_ORIGIN)) {\
|
||||
(c) = (c)->super;\
|
||||
}\
|
||||
}\
|
||||
} while (0)
|
||||
#define MRB_FLAG_IS_INHERITED (1 << 21)
|
||||
#define MRB_FL_CLASS_IS_INHERITED (1 << 17)
|
||||
#define MRB_INSTANCE_TT_MASK (0xFF)
|
||||
#define MRB_SET_INSTANCE_TT(c, tt) c->flags = ((c->flags & ~MRB_INSTANCE_TT_MASK) | (char)tt)
|
||||
#define MRB_INSTANCE_TT(c) (enum mrb_vtype)(c->flags & MRB_INSTANCE_TT_MASK)
|
||||
#define MRB_SET_INSTANCE_TT(c, tt) ((c)->flags = (((c)->flags & ~MRB_INSTANCE_TT_MASK) | (char)(tt)))
|
||||
#define MRB_INSTANCE_TT(c) (enum mrb_vtype)((c)->flags & MRB_INSTANCE_TT_MASK)
|
||||
|
||||
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);
|
||||
@@ -76,14 +79,16 @@ MRB_API struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb
|
||||
MRB_API 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 *mrb, struct RClass *c, mrb_sym a, mrb_sym b);
|
||||
MRB_API void mrb_alias_method(mrb_state*, struct RClass *c, mrb_sym a, mrb_sym b);
|
||||
|
||||
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*);
|
||||
|
||||
+11
-6
@@ -7,6 +7,11 @@
|
||||
#ifndef MRUBY_COMMON_H
|
||||
#define MRUBY_COMMON_H
|
||||
|
||||
#ifdef __APPLE__
|
||||
#ifndef __TARGETCONDITIONALS__
|
||||
#include "TargetConditionals.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#ifdef MRB_ENABLE_CXX_ABI
|
||||
@@ -29,7 +34,7 @@
|
||||
MRB_BEGIN_DECL
|
||||
|
||||
/** Declare a function that never returns. */
|
||||
#if __STDC_VERSION__ >= 201112L
|
||||
#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L
|
||||
# define mrb_noreturn _Noreturn
|
||||
#elif defined __GNUC__ && !defined __STRICT_ANSI__
|
||||
# define mrb_noreturn __attribute__((noreturn))
|
||||
@@ -49,12 +54,12 @@ 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. */
|
||||
#if defined(MRB_BUILD_AS_DLL)
|
||||
|
||||
+10
-9
@@ -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;
|
||||
@@ -33,6 +33,7 @@ typedef struct mrbc_context {
|
||||
mrb_bool no_exec:1;
|
||||
mrb_bool keep_lv:1;
|
||||
mrb_bool no_optimize:1;
|
||||
mrb_bool on_eval:1;
|
||||
|
||||
size_t parser_nerr;
|
||||
} mrbc_context;
|
||||
@@ -66,7 +67,7 @@ enum mrb_lex_state_enum {
|
||||
|
||||
/* saved error message */
|
||||
struct mrb_parser_message {
|
||||
int lineno;
|
||||
uint16_t lineno;
|
||||
int column;
|
||||
char* message;
|
||||
};
|
||||
@@ -104,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 */
|
||||
@@ -117,8 +118,8 @@ struct mrb_parser_state {
|
||||
FILE *f;
|
||||
#endif
|
||||
mrbc_context *cxt;
|
||||
char const *filename;
|
||||
int lineno;
|
||||
mrb_sym filename_sym;
|
||||
uint16_t lineno;
|
||||
int column;
|
||||
|
||||
enum mrb_lex_state_enum lstate;
|
||||
@@ -142,7 +143,6 @@ struct mrb_parser_state {
|
||||
mrb_ast_node *heredocs_from_nextline;
|
||||
mrb_ast_node *parsing_heredoc;
|
||||
mrb_ast_node *lex_strterm_before_heredoc;
|
||||
mrb_bool heredoc_end_now:1; /* for mirb */
|
||||
|
||||
void *ylval;
|
||||
|
||||
@@ -151,13 +151,14 @@ struct mrb_parser_state {
|
||||
mrb_ast_node *tree;
|
||||
|
||||
mrb_bool no_optimize:1;
|
||||
mrb_bool on_eval:1;
|
||||
mrb_bool capture_errors:1;
|
||||
struct mrb_parser_message error_buffer[10];
|
||||
struct mrb_parser_message warn_buffer[10];
|
||||
|
||||
mrb_sym* filename_table;
|
||||
size_t filename_table_length;
|
||||
int current_filename_index;
|
||||
uint16_t filename_table_length;
|
||||
uint16_t current_filename_index;
|
||||
|
||||
struct mrb_jmpbuf* jmp;
|
||||
};
|
||||
@@ -167,7 +168,7 @@ MRB_API void mrb_parser_free(struct mrb_parser_state*);
|
||||
MRB_API void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*);
|
||||
|
||||
MRB_API void mrb_parser_set_filename(struct mrb_parser_state*, char const*);
|
||||
MRB_API char const* mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx);
|
||||
MRB_API mrb_sym mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx);
|
||||
|
||||
/* utility functions */
|
||||
#ifndef MRB_DISABLE_STDIO
|
||||
|
||||
@@ -39,10 +39,11 @@ MRB_API struct RData *mrb_data_object_alloc(mrb_state *mrb, struct RClass* klass
|
||||
#define Data_Wrap_Struct(mrb,klass,type,ptr)\
|
||||
mrb_data_object_alloc(mrb,klass,ptr,type)
|
||||
|
||||
#define Data_Make_Struct(mrb,klass,strct,type,sval,data) do { \
|
||||
sval = mrb_malloc(mrb, sizeof(strct)); \
|
||||
{ static const strct zero = { 0 }; *sval = zero; };\
|
||||
data = Data_Wrap_Struct(mrb,klass,type,sval);\
|
||||
#define Data_Make_Struct(mrb,klass,strct,type,sval,data_obj) do { \
|
||||
(data_obj) = Data_Wrap_Struct(mrb,klass,type,NULL);\
|
||||
(sval) = (strct *)mrb_malloc(mrb, sizeof(strct)); \
|
||||
{ static const strct zero = { 0 }; *(sval) = zero; };\
|
||||
(data_obj)->data = (sval);\
|
||||
} while (0)
|
||||
|
||||
#define RDATA(obj) ((struct RData *)(mrb_ptr(obj)))
|
||||
@@ -62,7 +63,7 @@ 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);
|
||||
|
||||
@@ -26,7 +26,6 @@ typedef struct mrb_irep_debug_info_line {
|
||||
|
||||
typedef struct mrb_irep_debug_info_file {
|
||||
uint32_t start_pos;
|
||||
const char *filename;
|
||||
mrb_sym filename_sym;
|
||||
uint32_t line_entry_count;
|
||||
mrb_debug_line_type line_type;
|
||||
@@ -47,18 +46,19 @@ typedef struct mrb_irep_debug_info {
|
||||
* get line from irep's debug info and program counter
|
||||
* @return returns NULL if not found
|
||||
*/
|
||||
MRB_API const char *mrb_debug_get_filename(mrb_irep *irep, ptrdiff_t pc);
|
||||
MRB_API const char *mrb_debug_get_filename(mrb_state *mrb, mrb_irep *irep, ptrdiff_t pc);
|
||||
|
||||
/*
|
||||
* get line from irep's debug info and program counter
|
||||
* @return returns -1 if not found
|
||||
*/
|
||||
MRB_API int32_t mrb_debug_get_line(mrb_irep *irep, ptrdiff_t pc);
|
||||
MRB_API int32_t mrb_debug_get_line(mrb_state *mrb, mrb_irep *irep, ptrdiff_t pc);
|
||||
|
||||
MRB_API mrb_irep_debug_info_file *mrb_debug_info_append_file(
|
||||
mrb_state *mrb, mrb_irep *irep,
|
||||
uint32_t start_pos, uint32_t end_pos);
|
||||
MRB_API mrb_irep_debug_info *mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep);
|
||||
MRB_API mrb_irep_debug_info_file *mrb_debug_info_append_file(
|
||||
mrb_state *mrb, mrb_irep_debug_info *info,
|
||||
const char *filename, uint16_t *lines,
|
||||
uint32_t start_pos, uint32_t end_pos);
|
||||
MRB_API void mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d);
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
@@ -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
|
||||
*
|
||||
@@ -52,15 +53,14 @@ MRB_API mrb_irep *mrb_read_irep(mrb_state*, const uint8_t*);
|
||||
/* Rite Binary File header */
|
||||
#define RITE_BINARY_IDENT "RITE"
|
||||
#define RITE_BINARY_IDENT_LIL "ETIR"
|
||||
#define RITE_BINARY_FORMAT_VER "0004"
|
||||
#define RITE_BINARY_FORMAT_VER "0006"
|
||||
#define RITE_COMPILER_NAME "MATZ"
|
||||
#define RITE_COMPILER_VERSION "0000"
|
||||
|
||||
#define RITE_VM_VER "0000"
|
||||
#define RITE_VM_VER "0002"
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
@@ -29,7 +29,7 @@ MRB_API mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc);
|
||||
MRB_API mrb_value mrb_get_backtrace(mrb_state *mrb);
|
||||
MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, const char *fmt, ...);
|
||||
|
||||
/* declaration for fail method */
|
||||
/* declaration for `fail` method */
|
||||
MRB_API mrb_value mrb_f_raise(mrb_state*, mrb_value);
|
||||
|
||||
struct RBreak {
|
||||
|
||||
+56
-9
@@ -8,7 +8,6 @@
|
||||
#define MRUBY_HASH_H
|
||||
|
||||
#include "common.h"
|
||||
#include <mruby/khash.h>
|
||||
|
||||
/**
|
||||
* Hash class
|
||||
@@ -18,13 +17,15 @@ MRB_BEGIN_DECL
|
||||
struct RHash {
|
||||
MRB_OBJECT_HEADER;
|
||||
struct iv_tbl *iv;
|
||||
struct kh_ht *ht;
|
||||
struct htable *ht;
|
||||
};
|
||||
|
||||
#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_ensure_hash_type(mrb_state *mrb, mrb_value hash);
|
||||
MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
|
||||
|
||||
/*
|
||||
* Initializes a new hash.
|
||||
@@ -74,7 +75,7 @@ MRB_API mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key);
|
||||
*
|
||||
* Equivalent to:
|
||||
*
|
||||
* hash.hash_key?(key) ? hash[key] : def
|
||||
* hash.key?(key) ? hash[key] : def
|
||||
*
|
||||
* @param mrb The mruby state reference.
|
||||
* @param hash The target hash.
|
||||
@@ -110,7 +111,19 @@ MRB_API mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value
|
||||
* @return An array with the keys of the hash.
|
||||
*/
|
||||
MRB_API mrb_value mrb_hash_keys(mrb_state *mrb, mrb_value hash);
|
||||
MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
|
||||
/*
|
||||
* Check if the hash has the key.
|
||||
*
|
||||
* Equivalent to:
|
||||
*
|
||||
* hash.key?(key)
|
||||
*
|
||||
* @param mrb The mruby state reference.
|
||||
* @param hash The target hash.
|
||||
* @param key The key to check existence.
|
||||
* @return True if the hash has the key
|
||||
*/
|
||||
MRB_API mrb_bool mrb_hash_key_p(mrb_state *mrb, mrb_value hash, mrb_value key);
|
||||
|
||||
/*
|
||||
* Check if the hash is empty
|
||||
@@ -123,7 +136,7 @@ MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
|
||||
* @param self The target hash.
|
||||
* @return True if the hash is empty, false otherwise.
|
||||
*/
|
||||
MRB_API mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self);
|
||||
MRB_API mrb_bool mrb_hash_empty_p(mrb_state *mrb, mrb_value self);
|
||||
|
||||
/*
|
||||
* Gets an array of values.
|
||||
@@ -151,21 +164,51 @@ MRB_API mrb_value mrb_hash_values(mrb_state *mrb, mrb_value hash);
|
||||
*/
|
||||
MRB_API mrb_value mrb_hash_clear(mrb_state *mrb, mrb_value hash);
|
||||
|
||||
/* declaration of struct kh_ht */
|
||||
/*
|
||||
* Get hash size.
|
||||
*
|
||||
* Equivalent to:
|
||||
*
|
||||
* hash.size
|
||||
*
|
||||
* @param mrb The mruby state reference.
|
||||
* @param hash The target hash.
|
||||
* @return The hash size.
|
||||
*/
|
||||
MRB_API mrb_int mrb_hash_size(mrb_state *mrb, mrb_value hash);
|
||||
|
||||
/*
|
||||
* Copies the hash.
|
||||
*
|
||||
*
|
||||
* @param mrb The mruby state reference.
|
||||
* @param hash The target hash.
|
||||
* @return The copy of the hash
|
||||
*/
|
||||
MRB_API mrb_value mrb_hash_dup(mrb_state *mrb, mrb_value hash);
|
||||
|
||||
/*
|
||||
* Merges two hashes. The first hash will be modified by the
|
||||
* second hash.
|
||||
*
|
||||
* @param mrb The mruby state reference.
|
||||
* @param hash1 The target hash.
|
||||
* @param hash2 Updating 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;
|
||||
|
||||
KHASH_DECLARE(ht, mrb_value, mrb_hash_value, TRUE)
|
||||
|
||||
/* RHASH_TBL allocates st_table if not available. */
|
||||
#define RHASH(obj) ((struct RHash*)(mrb_ptr(obj)))
|
||||
#define RHASH_TBL(h) (RHASH(h)->ht)
|
||||
#define RHASH_IFNONE(h) mrb_iv_get(mrb, (h), mrb_intern_lit(mrb, "ifnone"))
|
||||
#define RHASH_PROCDEFAULT(h) RHASH_IFNONE(h)
|
||||
MRB_API struct kh_ht * mrb_hash_tbl(mrb_state *mrb, mrb_value hash);
|
||||
|
||||
#define MRB_HASH_DEFAULT 1
|
||||
#define MRB_HASH_PROC_DEFAULT 2
|
||||
@@ -177,6 +220,10 @@ void mrb_gc_mark_hash(mrb_state*, struct RHash*);
|
||||
size_t mrb_gc_mark_hash_size(mrb_state*, struct RHash*);
|
||||
void mrb_gc_free_hash(mrb_state*, struct RHash*);
|
||||
|
||||
/* return non zero to break the loop */
|
||||
typedef int (mrb_hash_foreach_func)(mrb_state *mrb, mrb_value key, mrb_value val, void *data);
|
||||
MRB_API void mrb_hash_foreach(mrb_state *mrb, struct RHash *hash, mrb_hash_foreach_func *func, void *p);
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
#endif /* MRUBY_HASH_H */
|
||||
|
||||
+29
-4
@@ -39,23 +39,48 @@ typedef struct mrb_irep {
|
||||
|
||||
struct mrb_locals *lv;
|
||||
/* debug info */
|
||||
mrb_bool own_filename;
|
||||
const char *filename;
|
||||
uint16_t *lines;
|
||||
struct mrb_irep_debug_info* debug_info;
|
||||
|
||||
int ilen, plen, slen, rlen, refcnt;
|
||||
uint16_t ilen, plen, slen, rlen;
|
||||
uint32_t refcnt;
|
||||
} mrb_irep;
|
||||
|
||||
#define MRB_ISEQ_NO_FREE 1
|
||||
|
||||
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*);
|
||||
void mrb_irep_cutref(mrb_state*, struct mrb_irep*);
|
||||
void mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep);
|
||||
|
||||
struct mrb_insn_data {
|
||||
uint8_t insn;
|
||||
uint16_t a;
|
||||
uint16_t b;
|
||||
uint8_t c;
|
||||
};
|
||||
|
||||
struct mrb_insn_data mrb_decode_insn(mrb_code *pc);
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -23,7 +23,7 @@ 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)
|
||||
#define FIXABLE_FLOAT(f) TYPED_FIXABLE(f,mrb_float)
|
||||
#endif
|
||||
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
@@ -34,12 +34,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
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
struct RClass *c;\
|
||||
struct RBasic *gcnext
|
||||
|
||||
#define MRB_FLAG_TEST(obj, flag) ((obj)->flags & flag)
|
||||
#define MRB_FLAG_TEST(obj, flag) ((obj)->flags & (flag))
|
||||
|
||||
|
||||
struct RBasic {
|
||||
@@ -22,11 +22,10 @@ struct RBasic {
|
||||
};
|
||||
#define mrb_basic_ptr(v) ((struct RBasic*)(mrb_ptr(v)))
|
||||
|
||||
/* flags bits >= 18 is reserved */
|
||||
#define MRB_FLAG_IS_FROZEN (1 << 18)
|
||||
#define MRB_FROZEN_P(o) ((o)->flags & MRB_FLAG_IS_FROZEN)
|
||||
#define MRB_SET_FROZEN_FLAG(o) ((o)->flags |= MRB_FLAG_IS_FROZEN)
|
||||
#define MRB_UNSET_FROZEN_FLAG(o) ((o)->flags &= ~MRB_FLAG_IS_FROZEN)
|
||||
#define MRB_FL_OBJ_IS_FROZEN (1 << 20)
|
||||
#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)
|
||||
|
||||
struct RObject {
|
||||
MRB_OBJECT_HEADER;
|
||||
|
||||
+47
-139
@@ -7,145 +7,10 @@
|
||||
#ifndef MRUBY_OPCODE_H
|
||||
#define MRUBY_OPCODE_H
|
||||
|
||||
#define MAXARG_Bx (0xffff)
|
||||
#define MAXARG_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */
|
||||
|
||||
/* instructions: packed 32 bit */
|
||||
/* ------------------------------- */
|
||||
/* A:B:C:OP = 9: 9: 7: 7 */
|
||||
/* A:Bx:OP = 9:16: 7 */
|
||||
/* Ax:OP = 25: 7 */
|
||||
/* A:Bz:Cz:OP = 9:14: 2: 7 */
|
||||
|
||||
#define GET_OPCODE(i) ((int)(((mrb_code)(i)) & 0x7f))
|
||||
#define GETARG_A(i) ((int)((((mrb_code)(i)) >> 23) & 0x1ff))
|
||||
#define GETARG_B(i) ((int)((((mrb_code)(i)) >> 14) & 0x1ff))
|
||||
#define GETARG_C(i) ((int)((((mrb_code)(i)) >> 7) & 0x7f))
|
||||
#define GETARG_Bx(i) ((int)((((mrb_code)(i)) >> 7) & 0xffff))
|
||||
#define GETARG_sBx(i) ((int)(GETARG_Bx(i)-MAXARG_sBx))
|
||||
#define GETARG_Ax(i) ((int32_t)((((mrb_code)(i)) >> 7) & 0x1ffffff))
|
||||
#define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+(n2))) & (((1<<(n1))-1))))
|
||||
#define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<(n2))-1))))
|
||||
#define GETARG_b(i) GETARG_UNPACK_b(i,14,2)
|
||||
#define GETARG_c(i) GETARG_UNPACK_c(i,14,2)
|
||||
|
||||
#define MKOPCODE(op) ((op) & 0x7f)
|
||||
#define MKARG_A(c) ((mrb_code)((c) & 0x1ff) << 23)
|
||||
#define MKARG_B(c) ((mrb_code)((c) & 0x1ff) << 14)
|
||||
#define MKARG_C(c) (((c) & 0x7f) << 7)
|
||||
#define MKARG_Bx(v) ((mrb_code)((v) & 0xffff) << 7)
|
||||
#define MKARG_sBx(v) MKARG_Bx((v)+MAXARG_sBx)
|
||||
#define MKARG_Ax(v) ((mrb_code)((v) & 0x1ffffff) << 7)
|
||||
#define MKARG_PACK(b,n1,c,n2) ((((b) & ((1<<n1)-1)) << (7+n2))|(((c) & ((1<<n2)-1)) << 7))
|
||||
#define MKARG_bc(b,c) MKARG_PACK(b,14,c,2)
|
||||
|
||||
#define MKOP_A(op,a) (MKOPCODE(op)|MKARG_A(a))
|
||||
#define MKOP_AB(op,a,b) (MKOP_A(op,a)|MKARG_B(b))
|
||||
#define MKOP_ABC(op,a,b,c) (MKOP_AB(op,a,b)|MKARG_C(c))
|
||||
#define MKOP_ABx(op,a,bx) (MKOP_A(op,a)|MKARG_Bx(bx))
|
||||
#define MKOP_Bx(op,bx) (MKOPCODE(op)|MKARG_Bx(bx))
|
||||
#define MKOP_sBx(op,sbx) (MKOPCODE(op)|MKARG_sBx(sbx))
|
||||
#define MKOP_AsBx(op,a,sbx) (MKOP_A(op,a)|MKARG_sBx(sbx))
|
||||
#define MKOP_Ax(op,ax) (MKOPCODE(op)|MKARG_Ax(ax))
|
||||
#define MKOP_Abc(op,a,b,c) (MKOP_A(op,a)|MKARG_bc(b,c))
|
||||
|
||||
enum {
|
||||
/*-----------------------------------------------------------------------
|
||||
operation code operand description
|
||||
------------------------------------------------------------------------*/
|
||||
OP_NOP=0,/* */
|
||||
OP_MOVE,/* A B R(A) := R(B) */
|
||||
OP_LOADL,/* A Bx R(A) := Pool(Bx) */
|
||||
OP_LOADI,/* A sBx R(A) := sBx */
|
||||
OP_LOADSYM,/* A Bx R(A) := Syms(Bx) */
|
||||
OP_LOADNIL,/* A R(A) := nil */
|
||||
OP_LOADSELF,/* A R(A) := self */
|
||||
OP_LOADT,/* A R(A) := true */
|
||||
OP_LOADF,/* A R(A) := false */
|
||||
|
||||
OP_GETGLOBAL,/* A Bx R(A) := getglobal(Syms(Bx)) */
|
||||
OP_SETGLOBAL,/* A Bx setglobal(Syms(Bx), R(A)) */
|
||||
OP_GETSPECIAL,/*A Bx R(A) := Special[Bx] */
|
||||
OP_SETSPECIAL,/*A Bx Special[Bx] := R(A) */
|
||||
OP_GETIV,/* A Bx R(A) := ivget(Syms(Bx)) */
|
||||
OP_SETIV,/* A Bx ivset(Syms(Bx),R(A)) */
|
||||
OP_GETCV,/* A Bx R(A) := cvget(Syms(Bx)) */
|
||||
OP_SETCV,/* A Bx cvset(Syms(Bx),R(A)) */
|
||||
OP_GETCONST,/* A Bx R(A) := constget(Syms(Bx)) */
|
||||
OP_SETCONST,/* A Bx constset(Syms(Bx),R(A)) */
|
||||
OP_GETMCNST,/* A Bx R(A) := R(A)::Syms(Bx) */
|
||||
OP_SETMCNST,/* A Bx R(A+1)::Syms(Bx) := R(A) */
|
||||
OP_GETUPVAR,/* A B C R(A) := uvget(B,C) */
|
||||
OP_SETUPVAR,/* A B C uvset(B,C,R(A)) */
|
||||
|
||||
OP_JMP,/* sBx pc+=sBx */
|
||||
OP_JMPIF,/* A sBx if R(A) pc+=sBx */
|
||||
OP_JMPNOT,/* A sBx if !R(A) pc+=sBx */
|
||||
OP_ONERR,/* sBx rescue_push(pc+sBx) */
|
||||
OP_RESCUE,/* A B C if A (if C exc=R(A) else R(A) := exc);
|
||||
if B R(B) := exc.isa?(R(B)); clear(exc) */
|
||||
OP_POPERR,/* A A.times{rescue_pop()} */
|
||||
OP_RAISE,/* A raise(R(A)) */
|
||||
OP_EPUSH,/* Bx ensure_push(SEQ[Bx]) */
|
||||
OP_EPOP,/* A A.times{ensure_pop().call} */
|
||||
|
||||
OP_SEND,/* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C)) */
|
||||
OP_SENDB,/* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C),&R(A+C+1))*/
|
||||
OP_FSEND,/* A B C R(A) := fcall(R(A),Syms(B),R(A+1),...,R(A+C-1)) */
|
||||
OP_CALL,/* A R(A) := self.call(frame.argc, frame.argv) */
|
||||
OP_SUPER,/* A C R(A) := super(R(A+1),... ,R(A+C+1)) */
|
||||
OP_ARGARY,/* A Bx R(A) := argument array (16=6:1:5:4) */
|
||||
OP_ENTER,/* Ax arg setup according to flags (23=5:5:1:5:5:1:1) */
|
||||
OP_KARG,/* A B C R(A) := kdict[Syms(B)]; if C kdict.rm(Syms(B)) */
|
||||
OP_KDICT,/* A C R(A) := kdict */
|
||||
|
||||
OP_RETURN,/* A B return R(A) (B=normal,in-block return/break) */
|
||||
OP_TAILCALL,/* A B C return call(R(A),Syms(B),*R(C)) */
|
||||
OP_BLKPUSH,/* A Bx R(A) := block (16=6:1:5:4) */
|
||||
|
||||
OP_ADD,/* A B C R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1) */
|
||||
OP_ADDI,/* A B C R(A) := R(A)+C (Syms[B]=:+) */
|
||||
OP_SUB,/* A B C R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1) */
|
||||
OP_SUBI,/* A B C R(A) := R(A)-C (Syms[B]=:-) */
|
||||
OP_MUL,/* A B C R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1) */
|
||||
OP_DIV,/* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1) */
|
||||
OP_EQ,/* A B C R(A) := R(A)==R(A+1) (Syms[B]=:==,C=1) */
|
||||
OP_LT,/* A B C R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1) */
|
||||
OP_LE,/* A B C R(A) := R(A)<=R(A+1) (Syms[B]=:<=,C=1) */
|
||||
OP_GT,/* A B C R(A) := R(A)>R(A+1) (Syms[B]=:>,C=1) */
|
||||
OP_GE,/* A B C R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1) */
|
||||
|
||||
OP_ARRAY,/* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */
|
||||
OP_ARYCAT,/* A B ary_cat(R(A),R(B)) */
|
||||
OP_ARYPUSH,/* A B ary_push(R(A),R(B)) */
|
||||
OP_AREF,/* A B C R(A) := R(B)[C] */
|
||||
OP_ASET,/* A B C R(B)[C] := R(A) */
|
||||
OP_APOST,/* A B C *R(A),R(A+1)..R(A+C) := R(A)[B..] */
|
||||
|
||||
OP_STRING,/* A Bx R(A) := str_dup(Lit(Bx)) */
|
||||
OP_STRCAT,/* A B str_cat(R(A),R(B)) */
|
||||
|
||||
OP_HASH,/* A B C R(A) := hash_new(R(B),R(B+1)..R(B+C)) */
|
||||
OP_LAMBDA,/* A Bz Cz R(A) := lambda(SEQ[Bz],Cz) */
|
||||
OP_RANGE,/* A B C R(A) := range_new(R(B),R(B+1),C) */
|
||||
|
||||
OP_OCLASS,/* A R(A) := ::Object */
|
||||
OP_CLASS,/* A B R(A) := newclass(R(A),Syms(B),R(A+1)) */
|
||||
OP_MODULE,/* A B R(A) := newmodule(R(A),Syms(B)) */
|
||||
OP_EXEC,/* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */
|
||||
OP_METHOD,/* A B R(A).newmethod(Syms(B),R(A+1)) */
|
||||
OP_SCLASS,/* A B R(A) := R(B).singleton_class */
|
||||
OP_TCLASS,/* A R(A) := target_class */
|
||||
|
||||
OP_DEBUG,/* A B C print R(A),R(B),R(C) */
|
||||
OP_STOP,/* stop VM */
|
||||
OP_ERR,/* Bx raise RuntimeError with message Lit(Bx) */
|
||||
|
||||
OP_RSVD1,/* reserved instruction #1 */
|
||||
OP_RSVD2,/* reserved instruction #2 */
|
||||
OP_RSVD3,/* reserved instruction #3 */
|
||||
OP_RSVD4,/* reserved instruction #4 */
|
||||
OP_RSVD5,/* reserved instruction #5 */
|
||||
enum mrb_insn {
|
||||
#define OPCODE(x,_) OP_ ## x,
|
||||
#include "mruby/ops.h"
|
||||
#undef OPCODE
|
||||
};
|
||||
|
||||
#define OP_L_STRICT 1
|
||||
@@ -158,4 +23,47 @@ enum {
|
||||
#define OP_R_BREAK 1
|
||||
#define OP_R_RETURN 2
|
||||
|
||||
#define PEEK_B(pc) (*(pc))
|
||||
#define PEEK_S(pc) ((pc)[0]<<8|(pc)[1])
|
||||
#define PEEK_W(pc) ((pc)[0]<<16|(pc)[1]<<8|(pc)[2])
|
||||
|
||||
#define READ_B() PEEK_B(pc++)
|
||||
#define READ_S() (pc+=2, PEEK_S(pc-2))
|
||||
#define READ_W() (pc+=3, PEEK_W(pc-3))
|
||||
|
||||
#define FETCH_Z() /* nothing */
|
||||
#define FETCH_B() do {a=READ_B();} while (0)
|
||||
#define FETCH_BB() do {a=READ_B(); b=READ_B();} while (0)
|
||||
#define FETCH_BBB() do {a=READ_B(); b=READ_B(); c=READ_B();} while (0)
|
||||
#define FETCH_BS() do {a=READ_B(); b=READ_S();} while (0)
|
||||
#define FETCH_S() do {a=READ_S();} while (0)
|
||||
#define FETCH_W() do {a=READ_W();} while (0)
|
||||
|
||||
/* with OP_EXT1 (1st 16bit) */
|
||||
#define FETCH_Z_1() FETCH_Z()
|
||||
#define FETCH_B_1() FETCH_S()
|
||||
#define FETCH_BB_1() do {a=READ_S(); b=READ_B();} while (0)
|
||||
#define FETCH_BBB_1() do {a=READ_S(); b=READ_B(); c=READ_B();} while (0)
|
||||
#define FETCH_BS_1() do {a=READ_S(); b=READ_S();} while (0)
|
||||
#define FETCH_S_1() FETCH_S()
|
||||
#define FETCH_W_1() FETCH_W()
|
||||
|
||||
/* with OP_EXT2 (2nd 16bit) */
|
||||
#define FETCH_Z_2() FETCH_Z()
|
||||
#define FETCH_B_2() FETCH_B()
|
||||
#define FETCH_BB_2() do {a=READ_B(); b=READ_S();} while (0)
|
||||
#define FETCH_BBB_2() do {a=READ_B(); b=READ_S(); c=READ_B();} while (0)
|
||||
#define FETCH_BS_2() FETCH_BS()
|
||||
#define FETCH_S_2() FETCH_S()
|
||||
#define FETCH_W_2() FETCH_W()
|
||||
|
||||
/* with OP_EXT3 (1st & 2nd 16bit) */
|
||||
#define FETCH_Z_3() FETCH_Z()
|
||||
#define FETCH_B_3() FETCH_B()
|
||||
#define FETCH_BB_3() do {a=READ_S(); b=READ_S();} while (0)
|
||||
#define FETCH_BBB_3() do {a=READ_S(); b=READ_S(); c=READ_B();} while (0)
|
||||
#define FETCH_BS_3() do {a=READ_S(); b=READ_S();} while (0)
|
||||
#define FETCH_S_3() FETCH_S()
|
||||
#define FETCH_W_3() FETCH_W()
|
||||
|
||||
#endif /* MRUBY_OPCODE_H */
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/* operand types:
|
||||
+ Z: no operand (Z,Z,Z,Z)
|
||||
+ B: 8bit (B,S,B,B)
|
||||
+ BB: 8+8bit (BB,SB,BS,SS)
|
||||
+ BBB: 8+8+8bit (BBB,SBB,BSB,SSB)
|
||||
+ BS: 8+16bit (BS,SS,BS,BS)
|
||||
+ S: 16bit (S,S,S,S)
|
||||
+ W: 24bit (W,W,W,W)
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
operation code operands semantics
|
||||
------------------------------------------------------------------------*/
|
||||
OPCODE(NOP, Z) /* no operation */
|
||||
OPCODE(MOVE, BB) /* R(a) = R(b) */
|
||||
OPCODE(LOADL, BB) /* R(a) = Pool(b) */
|
||||
OPCODE(LOADI, BB) /* R(a) = mrb_int(b) */
|
||||
OPCODE(LOADINEG, BB) /* R(a) = mrb_int(-b) */
|
||||
OPCODE(LOADI__1, B) /* R(a) = mrb_int(-1) */
|
||||
OPCODE(LOADI_0, B) /* R(a) = mrb_int(0) */
|
||||
OPCODE(LOADI_1, B) /* R(a) = mrb_int(1) */
|
||||
OPCODE(LOADI_2, B) /* R(a) = mrb_int(2) */
|
||||
OPCODE(LOADI_3, B) /* R(a) = mrb_int(3) */
|
||||
OPCODE(LOADI_4, B) /* R(a) = mrb_int(4) */
|
||||
OPCODE(LOADI_5, B) /* R(a) = mrb_int(5) */
|
||||
OPCODE(LOADI_6, B) /* R(a) = mrb_int(6) */
|
||||
OPCODE(LOADI_7, B) /* R(a) = mrb_int(7) */
|
||||
OPCODE(LOADSYM, BB) /* R(a) = Syms(b) */
|
||||
OPCODE(LOADNIL, B) /* R(a) = nil */
|
||||
OPCODE(LOADSELF, B) /* R(a) = self */
|
||||
OPCODE(LOADT, B) /* R(a) = true */
|
||||
OPCODE(LOADF, B) /* R(a) = false */
|
||||
OPCODE(GETGV, BB) /* R(a) = getglobal(Syms(b)) */
|
||||
OPCODE(SETGV, BB) /* setglobal(Syms(b), R(a)) */
|
||||
OPCODE(GETSV, BB) /* R(a) = Special[Syms(b)] */
|
||||
OPCODE(SETSV, BB) /* Special[Syms(b)] = R(a) */
|
||||
OPCODE(GETIV, BB) /* R(a) = ivget(Syms(b)) */
|
||||
OPCODE(SETIV, BB) /* ivset(Syms(b),R(a)) */
|
||||
OPCODE(GETCV, BB) /* R(a) = cvget(Syms(b)) */
|
||||
OPCODE(SETCV, BB) /* cvset(Syms(b),R(a)) */
|
||||
OPCODE(GETCONST, BB) /* R(a) = constget(Syms(b)) */
|
||||
OPCODE(SETCONST, BB) /* constset(Syms(b),R(a)) */
|
||||
OPCODE(GETMCNST, BB) /* R(a) = R(a)::Syms(b) */
|
||||
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(ONERR, S) /* rescue_push(a) */
|
||||
OPCODE(EXCEPT, B) /* R(a) = exc */
|
||||
OPCODE(RESCUE, BB) /* R(b) = R(a).isa?(R(b)) */
|
||||
OPCODE(POPERR, B) /* a.times{rescue_pop()} */
|
||||
OPCODE(RAISE, B) /* raise(R(a)) */
|
||||
OPCODE(EPUSH, B) /* ensure_push(SEQ[a]) */
|
||||
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(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) */
|
||||
OPCODE(ENTER, W) /* arg setup according to flags (23=m5:o5:r1:m5:k5:d1:b1) */
|
||||
OPCODE(KEY_P, BB) /* R(a) = kdict.key?(Syms(b)) # todo */
|
||||
OPCODE(KEYEND, Z) /* raise unless kdict.empty? # todo */
|
||||
OPCODE(KARG, BB) /* R(a) = kdict[Syms(b)]; kdict.delete(Syms(b)) # todo */
|
||||
OPCODE(RETURN, B) /* return R(a) (normal) */
|
||||
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(SUB, B) /* R(a) = R(a)-R(a+1) */
|
||||
OPCODE(SUBI, BB) /* R(a) = R(a)-C */
|
||||
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) */
|
||||
OPCODE(LT, B) /* R(a) = R(a)<R(a+1) */
|
||||
OPCODE(LE, B) /* R(a) = R(a)<=R(a+1) */
|
||||
OPCODE(GT, B) /* R(a) = R(a)>R(a+1) */
|
||||
OPCODE(GE, B) /* R(a) = R(a)>=R(a+1) */
|
||||
OPCODE(ARRAY, BB) /* R(a) = ary_new(R(a),R(a+1)..R(a+b)) */
|
||||
OPCODE(ARRAY2, BBB) /* R(a) = ary_new(R(b),R(b+1)..R(b+c)) */
|
||||
OPCODE(ARYCAT, B) /* ary_cat(R(a),R(a+1)) */
|
||||
OPCODE(ARYPUSH, B) /* ary_push(R(a),R(a+1)) */
|
||||
OPCODE(ARYDUP, B) /* R(a) = ary_dup(R(a)) */
|
||||
OPCODE(AREF, BBB) /* R(a) = R(b)[c] */
|
||||
OPCODE(ASET, BBB) /* R(a)[c] = R(b) */
|
||||
OPCODE(APOST, BBB) /* *R(a),R(a+1)..R(a+c) = R(a)[b..] */
|
||||
OPCODE(INTERN, B) /* R(a) = intern(R(a)) */
|
||||
OPCODE(STRING, BB) /* R(a) = str_dup(Lit(b)) */
|
||||
OPCODE(STRCAT, B) /* str_cat(R(a),R(a+1)) */
|
||||
OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b)) */
|
||||
OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b)) */
|
||||
OPCODE(HASHCAT, B) /* R(a) = hash_cat(R(a),R(a+1)) */
|
||||
OPCODE(LAMBDA, BB) /* R(a) = lambda(SEQ[b],L_LAMBDA) */
|
||||
OPCODE(BLOCK, BB) /* R(a) = lambda(SEQ[b],L_BLOCK) */
|
||||
OPCODE(METHOD, BB) /* R(a) = lambda(SEQ[b],L_METHOD) */
|
||||
OPCODE(RANGE_INC, B) /* R(a) = range_new(R(a),R(a+1),FALSE) */
|
||||
OPCODE(RANGE_EXC, B) /* R(a) = range_new(R(a),R(a+1),TRUE) */
|
||||
OPCODE(OCLASS, B) /* R(a) = ::Object */
|
||||
OPCODE(CLASS, BB) /* R(a) = newclass(R(a),Syms(b),R(a+1)) */
|
||||
OPCODE(MODULE, BB) /* R(a) = newmodule(R(a),Syms(b)) */
|
||||
OPCODE(EXEC, BB) /* R(a) = blockexec(R(a),SEQ[b]) */
|
||||
OPCODE(DEF, BB) /* R(a).newmethod(Syms(b),R(a+1)) */
|
||||
OPCODE(ALIAS, BB) /* alias_method(target_class,Syms(a),Syms(b)) */
|
||||
OPCODE(UNDEF, B) /* undef_method(target_class,Syms(a)) */
|
||||
OPCODE(SCLASS, B) /* R(a) = R(a).singleton_class */
|
||||
OPCODE(TCLASS, B) /* R(a) = target_class */
|
||||
OPCODE(DEBUG, BBB) /* print a,b,c */
|
||||
OPCODE(ERR, B) /* raise(LocalJumpError, Lit(a)) */
|
||||
OPCODE(EXT1, Z) /* make 1st operand 16bit */
|
||||
OPCODE(EXT2, Z) /* make 2nd operand 16bit */
|
||||
OPCODE(EXT3, Z) /* make 1st and 2nd operands 16bit */
|
||||
OPCODE(STOP, Z) /* stop VM */
|
||||
@@ -23,13 +23,13 @@ struct REnv {
|
||||
};
|
||||
|
||||
/* flags (21bits): 1(shared flag):10(cioff/bidx):10(stack_len) */
|
||||
#define MRB_ENV_SET_STACK_LEN(e,len) (e)->flags = (((e)->flags & ~0x3ff)|((unsigned int)(len) & 0x3ff))
|
||||
#define MRB_ENV_SET_STACK_LEN(e,len) ((e)->flags = (((e)->flags & ~0x3ff)|((unsigned int)(len) & 0x3ff)))
|
||||
#define MRB_ENV_STACK_LEN(e) ((mrb_int)((e)->flags & 0x3ff))
|
||||
#define MRB_ENV_STACK_UNSHARED (1<<20)
|
||||
#define MRB_ENV_UNSHARE_STACK(e) (e)->flags |= MRB_ENV_STACK_UNSHARED
|
||||
#define MRB_ENV_UNSHARE_STACK(e) ((e)->flags |= MRB_ENV_STACK_UNSHARED)
|
||||
#define MRB_ENV_STACK_SHARED_P(e) (((e)->flags & MRB_ENV_STACK_UNSHARED) == 0)
|
||||
#define MRB_ENV_BIDX(e) (((e)->flags >> 10) & 0x3ff)
|
||||
#define MRB_ENV_SET_BIDX(e,idx) (e)->flags = (((e)->flags & ~(0x3ff<<10))|((unsigned int)(idx) & 0x3ff)<<10)
|
||||
#define MRB_ENV_SET_BIDX(e,idx) ((e)->flags = (((e)->flags & ~(0x3ff<<10))|((unsigned int)(idx) & 0x3ff)<<10))
|
||||
|
||||
void mrb_env_unshare(mrb_state*, struct REnv*);
|
||||
|
||||
@@ -69,11 +69,11 @@ struct RProc {
|
||||
#define MRB_PROC_SET_TARGET_CLASS(p,tc) do {\
|
||||
if (MRB_PROC_ENV_P(p)) {\
|
||||
(p)->e.env->c = (tc);\
|
||||
mrb_field_write_barrier(mrb, (struct RBasic*)(p)->e.env, (struct RBasic*)tc);\
|
||||
mrb_field_write_barrier(mrb, (struct RBasic*)(p)->e.env, (struct RBasic*)(tc));\
|
||||
}\
|
||||
else {\
|
||||
(p)->e.target_class = (tc);\
|
||||
mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)tc);\
|
||||
mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)(tc));\
|
||||
}\
|
||||
} while (0)
|
||||
#define MRB_PROC_SCOPE 2048
|
||||
@@ -86,9 +86,10 @@ 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_API mrb_value mrb_f_send(mrb_state *mrb, mrb_value self);
|
||||
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*);
|
||||
@@ -101,8 +102,8 @@ MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state*, mrb_int);
|
||||
#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_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_PROC_P(m) (!MRB_METHOD_FUNC_P(m))
|
||||
#define MRB_METHOD_PROC(m) ((struct RProc*)(m))
|
||||
#define MRB_METHOD_UNDEF_P(m) ((m)==0)
|
||||
|
||||
+36
-6
@@ -14,20 +14,43 @@
|
||||
*/
|
||||
MRB_BEGIN_DECL
|
||||
|
||||
#if defined(MRB_NAN_BOXING) && defined(MRB_64BIT) || defined(MRB_WORD_BOXING)
|
||||
# define MRB_RANGE_EMBED
|
||||
#endif
|
||||
|
||||
#ifdef MRB_RANGE_EMBED
|
||||
struct RRange {
|
||||
MRB_OBJECT_HEADER;
|
||||
mrb_value beg;
|
||||
mrb_value end;
|
||||
mrb_bool excl;
|
||||
};
|
||||
# define mrb_gc_free_range(mrb, p) ((void)0)
|
||||
# define RANGE_BEG(p) ((p)->beg)
|
||||
# define RANGE_END(p) ((p)->end)
|
||||
#else
|
||||
typedef struct mrb_range_edges {
|
||||
mrb_value beg;
|
||||
mrb_value end;
|
||||
} mrb_range_edges;
|
||||
|
||||
struct RRange {
|
||||
MRB_OBJECT_HEADER;
|
||||
mrb_range_edges *edges;
|
||||
mrb_bool excl : 1;
|
||||
mrb_bool excl;
|
||||
};
|
||||
# define mrb_gc_free_range(mrb, p) mrb_free(mrb, (p)->edges)
|
||||
# define RANGE_BEG(p) ((p)->edges->beg)
|
||||
# define RANGE_END(p) ((p)->edges->end)
|
||||
#endif
|
||||
|
||||
MRB_API struct RRange* mrb_range_ptr(mrb_state *mrb, mrb_value v);
|
||||
#define mrb_range_raw_ptr(v) ((struct RRange*)mrb_ptr(v))
|
||||
#define mrb_range_value(p) mrb_obj_value((void*)(p))
|
||||
#define mrb_range_beg(mrb, r) RANGE_BEG(mrb_range_ptr(mrb, r))
|
||||
#define mrb_range_end(mrb, r) RANGE_END(mrb_range_ptr(mrb, r))
|
||||
#define mrb_range_excl_p(mrb, r) RANGE_EXCL(mrb_range_ptr(mrb, r))
|
||||
#define mrb_range_raw_ptr(r) ((struct RRange*)mrb_ptr(r))
|
||||
#define mrb_range_value(p) mrb_obj_value((void*)(p))
|
||||
#define RANGE_EXCL(p) ((p)->excl)
|
||||
|
||||
MRB_API struct RRange* mrb_range_ptr(mrb_state *mrb, mrb_value range);
|
||||
|
||||
/*
|
||||
* Initializes a Range.
|
||||
@@ -41,8 +64,15 @@ MRB_API struct RRange* mrb_range_ptr(mrb_state *mrb, mrb_value v);
|
||||
*/
|
||||
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);
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
|
||||
+47
-15
@@ -39,15 +39,15 @@ struct RString {
|
||||
#define RSTR_UNSET_EMBED_FLAG(s) ((s)->flags &= ~(MRB_STR_EMBED|MRB_STR_EMBED_LEN_MASK))
|
||||
#define RSTR_SET_EMBED_LEN(s, n) do {\
|
||||
size_t tmp_n = (n);\
|
||||
s->flags &= ~MRB_STR_EMBED_LEN_MASK;\
|
||||
s->flags |= (tmp_n) << MRB_STR_EMBED_LEN_SHIFT;\
|
||||
(s)->flags &= ~MRB_STR_EMBED_LEN_MASK;\
|
||||
(s)->flags |= (tmp_n) << MRB_STR_EMBED_LEN_SHIFT;\
|
||||
} while (0)
|
||||
#define RSTR_SET_LEN(s, n) do {\
|
||||
if (RSTR_EMBED_P(s)) {\
|
||||
RSTR_SET_EMBED_LEN((s),(n));\
|
||||
}\
|
||||
else {\
|
||||
s->as.heap.len = (mrb_int)(n);\
|
||||
(s)->as.heap.len = (mrb_int)(n);\
|
||||
}\
|
||||
} while (0)
|
||||
#define RSTR_EMBED_LEN(s)\
|
||||
@@ -68,6 +68,20 @@ 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)
|
||||
|
||||
@@ -87,13 +101,14 @@ MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*);
|
||||
#define MRB_STR_FSHARED 2
|
||||
#define MRB_STR_NOFREE 4
|
||||
#define MRB_STR_POOL 8
|
||||
#define MRB_STR_NO_UTF 16
|
||||
#define MRB_STR_ASCII 16
|
||||
#define MRB_STR_EMBED 32
|
||||
#define MRB_STR_EMBED_LEN_MASK 0x7c0
|
||||
#define MRB_STR_EMBED_LEN_SHIFT 6
|
||||
|
||||
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_keep_ascii(mrb_state *mrb, struct RString *s);
|
||||
|
||||
/*
|
||||
* Finds the index of a substring in a string
|
||||
@@ -102,7 +117,7 @@ MRB_API mrb_int mrb_str_index(mrb_state*, mrb_value, const char*, mrb_int, mrb_i
|
||||
#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 concatnated string.
|
||||
* Appends self to other. Returns self as a concatenated string.
|
||||
*
|
||||
*
|
||||
* Example:
|
||||
@@ -126,10 +141,10 @@ MRB_API mrb_int mrb_str_index(mrb_state*, mrb_value, const char*, mrb_int, mrb_i
|
||||
* str1 = mrb_str_new_lit(mrb, "abc");
|
||||
* str2 = mrb_str_new_lit(mrb, "def");
|
||||
*
|
||||
* // Concatnates str2 to str1.
|
||||
* // Concatenates str2 to str1.
|
||||
* mrb_str_concat(mrb, str1, str2);
|
||||
*
|
||||
* // Prints new Concatnated Ruby string.
|
||||
* // Prints new Concatenated Ruby string.
|
||||
* mrb_p(mrb, str1);
|
||||
*
|
||||
* mrb_close(mrb);
|
||||
@@ -178,10 +193,10 @@ MRB_API void mrb_str_concat(mrb_state*, mrb_value, mrb_value);
|
||||
* mrb_p(mrb, a);
|
||||
* mrb_p(mrb, b);
|
||||
*
|
||||
* // Concatnates both Ruby strings.
|
||||
* // Concatenates both Ruby strings.
|
||||
* c = mrb_str_plus(mrb, a, b);
|
||||
*
|
||||
* // Prints new Concatnated Ruby string.
|
||||
* // Prints new Concatenated Ruby string.
|
||||
* mrb_p(mrb, c);
|
||||
*
|
||||
* mrb_close(mrb);
|
||||
@@ -193,7 +208,7 @@ MRB_API void mrb_str_concat(mrb_state*, mrb_value, mrb_value);
|
||||
*
|
||||
* => "abc" # First string
|
||||
* => "def" # Second string
|
||||
* => "abcdef" # First & Second concatnated.
|
||||
* => "abcdef" # First & Second concatenated.
|
||||
*
|
||||
* @param [mrb_state] mrb The current mruby state.
|
||||
* @param [mrb_value] a First string to concatenate.
|
||||
@@ -311,9 +326,12 @@ MRB_API mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb
|
||||
* @param [mrb_value] str Ruby string.
|
||||
* @return [mrb_value] A Ruby string.
|
||||
*/
|
||||
MRB_API mrb_value mrb_ensure_string_type(mrb_state *mrb, mrb_value str);
|
||||
MRB_API mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str);
|
||||
/* obsolete: use mrb_ensure_string_type() instead */
|
||||
MRB_API mrb_value mrb_string_type(mrb_state *mrb, mrb_value str);
|
||||
|
||||
MRB_API mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str);
|
||||
|
||||
MRB_API mrb_value mrb_str_new_capa(mrb_state *mrb, size_t capa);
|
||||
MRB_API mrb_value mrb_str_buf_new(mrb_state *mrb, size_t capa);
|
||||
|
||||
@@ -349,10 +367,13 @@ MRB_API mrb_value mrb_str_dup(mrb_state *mrb, mrb_value str);
|
||||
MRB_API mrb_value mrb_str_intern(mrb_state *mrb, mrb_value self);
|
||||
|
||||
MRB_API mrb_value mrb_str_to_inum(mrb_state *mrb, mrb_value str, mrb_int base, mrb_bool badcheck);
|
||||
MRB_API mrb_value mrb_cstr_to_inum(mrb_state *mrb, const char *s, mrb_int base, mrb_bool badcheck);
|
||||
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);
|
||||
|
||||
@@ -427,14 +448,25 @@ mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str);
|
||||
*/
|
||||
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);
|
||||
|
||||
MRB_INLINE void
|
||||
mrb_str_modify(mrb_state *mrb, struct RString *s)
|
||||
{
|
||||
mrb_str_modify_keep_ascii(mrb, s);
|
||||
RSTR_UNSET_ASCII_FLAG(s);
|
||||
}
|
||||
|
||||
#ifdef MRB_UTF8_STRING
|
||||
mrb_int mrb_utf8_len(const char *str, mrb_int byte_len);
|
||||
#endif
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
#endif /* MRUBY_STRING_H */
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
|
||||
#if defined(MRB_ENABLE_CXX_EXCEPTION) && defined(__cplusplus)
|
||||
|
||||
#define MRB_TRY(buf) do { try {
|
||||
#define MRB_TRY(buf) try {
|
||||
#define MRB_CATCH(buf) } catch(mrb_jmpbuf_impl e) { if (e != (buf)->impl) { throw e; }
|
||||
#define MRB_END_EXC(buf) } } while(0)
|
||||
#define MRB_END_EXC(buf) }
|
||||
|
||||
#define MRB_THROW(buf) throw((buf)->impl)
|
||||
typedef mrb_int mrb_jmpbuf_impl;
|
||||
@@ -34,9 +34,9 @@ typedef mrb_int mrb_jmpbuf_impl;
|
||||
#define MRB_LONGJMP longjmp
|
||||
#endif
|
||||
|
||||
#define MRB_TRY(buf) do { if (MRB_SETJMP((buf)->impl) == 0) {
|
||||
#define MRB_TRY(buf) if (MRB_SETJMP((buf)->impl) == 0) {
|
||||
#define MRB_CATCH(buf) } else {
|
||||
#define MRB_END_EXC(buf) } } while(0)
|
||||
#define MRB_END_EXC(buf) }
|
||||
|
||||
#define MRB_THROW(buf) MRB_LONGJMP((buf)->impl, 1);
|
||||
#define mrb_jmpbuf_impl jmp_buf
|
||||
|
||||
+19
-10
@@ -73,9 +73,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, ...);
|
||||
@@ -157,9 +154,19 @@ typedef void mrb_value;
|
||||
#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_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
|
||||
@@ -170,7 +177,6 @@ typedef void mrb_value;
|
||||
#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.
|
||||
@@ -185,7 +191,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;
|
||||
@@ -204,7 +210,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;
|
||||
@@ -212,7 +218,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;
|
||||
@@ -256,7 +262,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;
|
||||
@@ -264,7 +270,7 @@ mrb_bool_value(mrb_bool boolean)
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline mrb_value
|
||||
MRB_INLINE mrb_value
|
||||
mrb_undef_value(void)
|
||||
{
|
||||
mrb_value v;
|
||||
@@ -272,7 +278,10 @@ mrb_undef_value(void)
|
||||
return v;
|
||||
}
|
||||
|
||||
#ifdef MRB_USE_ETEXT_EDATA
|
||||
#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_ETEXT_EDATA)
|
||||
#if (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <mach-o/getsect.h>
|
||||
static inline mrb_bool
|
||||
|
||||
@@ -31,8 +31,6 @@ struct global_entry {
|
||||
|
||||
mrb_value mrb_vm_special_get(mrb_state*, mrb_sym);
|
||||
void mrb_vm_special_set(mrb_state*, mrb_sym, mrb_value);
|
||||
mrb_value mrb_vm_iv_get(mrb_state*, mrb_sym);
|
||||
void mrb_vm_iv_set(mrb_state*, mrb_sym, mrb_value);
|
||||
mrb_value mrb_vm_cv_get(mrb_state*, mrb_sym);
|
||||
void mrb_vm_cv_set(mrb_state*, mrb_sym, mrb_value);
|
||||
mrb_value mrb_vm_const_get(mrb_state*, mrb_sym);
|
||||
@@ -42,8 +40,8 @@ MRB_API void mrb_const_set(mrb_state*, mrb_value, mrb_sym, mrb_value);
|
||||
MRB_API mrb_bool mrb_const_defined(mrb_state*, mrb_value, mrb_sym);
|
||||
MRB_API void mrb_const_remove(mrb_state*, mrb_value, mrb_sym);
|
||||
|
||||
MRB_API mrb_bool mrb_iv_p(mrb_state *mrb, mrb_sym sym);
|
||||
MRB_API void mrb_iv_check(mrb_state *mrb, mrb_sym sym);
|
||||
MRB_API mrb_bool mrb_iv_name_sym_p(mrb_state *mrb, mrb_sym sym);
|
||||
MRB_API void mrb_iv_name_sym_check(mrb_state *mrb, mrb_sym sym);
|
||||
MRB_API mrb_value mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
|
||||
MRB_API void mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
|
||||
MRB_API mrb_bool mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
|
||||
@@ -119,12 +117,14 @@ 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);
|
||||
mrb_value mrb_mod_class_variables(mrb_state*, mrb_value);
|
||||
mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym);
|
||||
mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym);
|
||||
mrb_bool mrb_ident_p(const char *s, mrb_int len);
|
||||
|
||||
/* GC functions */
|
||||
void mrb_gc_mark_gv(mrb_state*);
|
||||
@@ -133,6 +133,10 @@ void mrb_gc_mark_iv(mrb_state*, struct RObject*);
|
||||
size_t mrb_gc_mark_iv_size(mrb_state*, struct RObject*);
|
||||
void mrb_gc_free_iv(mrb_state*, struct RObject*);
|
||||
|
||||
/* return non zero to break the loop */
|
||||
typedef int (mrb_iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*);
|
||||
MRB_API void mrb_iv_foreach(mrb_state *mrb, mrb_value obj, mrb_iv_foreach_func *func, void *p);
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
#endif /* MRUBY_VARIABLE_H */
|
||||
|
||||
+20
-6
@@ -27,7 +27,7 @@ MRB_BEGIN_DECL
|
||||
/*
|
||||
* The version of Ruby used by mruby.
|
||||
*/
|
||||
#define MRUBY_RUBY_VERSION "1.9"
|
||||
#define MRUBY_RUBY_VERSION "2.0"
|
||||
|
||||
/*
|
||||
* Ruby engine.
|
||||
@@ -37,12 +37,12 @@ MRB_BEGIN_DECL
|
||||
/*
|
||||
* Major release version number.
|
||||
*/
|
||||
#define MRUBY_RELEASE_MAJOR 1
|
||||
#define MRUBY_RELEASE_MAJOR 2
|
||||
|
||||
/*
|
||||
* Minor release version number.
|
||||
*/
|
||||
#define MRUBY_RELEASE_MINOR 4
|
||||
#define MRUBY_RELEASE_MINOR 0
|
||||
|
||||
/*
|
||||
* Tiny release version number.
|
||||
@@ -62,7 +62,7 @@ MRB_BEGIN_DECL
|
||||
/*
|
||||
* Release year.
|
||||
*/
|
||||
#define MRUBY_RELEASE_YEAR 2018
|
||||
#define MRUBY_RELEASE_YEAR 2019
|
||||
|
||||
/*
|
||||
* Release month.
|
||||
@@ -72,12 +72,26 @@ MRB_BEGIN_DECL
|
||||
/*
|
||||
* Release day.
|
||||
*/
|
||||
#define MRUBY_RELEASE_DAY 27
|
||||
#define MRUBY_RELEASE_DAY 4
|
||||
|
||||
/*
|
||||
* 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.
|
||||
|
||||
+23
-17
@@ -18,18 +18,20 @@ class String
|
||||
end
|
||||
|
||||
# Compatible with 1.9 on 1.8
|
||||
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)
|
||||
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
|
||||
sprintf(self, params)
|
||||
if params.is_a?(Array)
|
||||
sprintf(self, *params)
|
||||
else
|
||||
sprintf(self, params)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -37,17 +39,21 @@ end
|
||||
|
||||
class Symbol
|
||||
# Compatible with 1.9 on 1.8
|
||||
def to_proc
|
||||
proc { |obj, *args| obj.send(self, *args) }
|
||||
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
|
||||
def each_with_object(memo)
|
||||
return to_enum :each_with_object, memo unless block_given?
|
||||
each { |obj| yield obj, memo }
|
||||
memo
|
||||
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
|
||||
|
||||
|
||||
+45
-21
@@ -22,7 +22,6 @@ module MRuby
|
||||
|
||||
def initialize(name, &block)
|
||||
@name, @initializer = name.to_s, block
|
||||
MRuby::Toolchain.toolchains ||= {}
|
||||
MRuby::Toolchain.toolchains[@name] = self
|
||||
end
|
||||
|
||||
@@ -30,13 +29,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,9 +39,11 @@ module MRuby
|
||||
include Rake::DSL
|
||||
include LoadGems
|
||||
attr_accessor :name, :bins, :exts, :file_separator, :build_dir, :gem_clone_dir
|
||||
attr_reader :libmruby, :gems, :toolchains
|
||||
attr_reader :libmruby_objs, :gems, :toolchains
|
||||
attr_writer :enable_bintest, :enable_test
|
||||
|
||||
alias libmruby libmruby_objs
|
||||
|
||||
COMPILERS = %w(cc cxx objc asm)
|
||||
COMMANDS = COMPILERS + %w(linker archiver yacc gperf git exts mrbc)
|
||||
attr_block MRuby::Build::COMMANDS
|
||||
@@ -81,7 +77,7 @@ module MRuby
|
||||
@mrbc = Command::Mrbc.new(self)
|
||||
|
||||
@bins = []
|
||||
@gems, @libmruby = MRuby::Gem::List.new, []
|
||||
@gems, @libmruby_objs = MRuby::Gem::List.new, []
|
||||
@build_mrbtest_lib_only = false
|
||||
@cxx_exception_enabled = false
|
||||
@cxx_exception_disabled = false
|
||||
@@ -100,6 +96,10 @@ module MRuby
|
||||
build_mrbtest if test_enabled?
|
||||
end
|
||||
|
||||
def debug_enabled?
|
||||
@enable_debug
|
||||
end
|
||||
|
||||
def enable_debug
|
||||
compilers.each do |c|
|
||||
c.defines += %w(MRB_DEBUG)
|
||||
@@ -108,6 +108,8 @@ module MRuby
|
||||
end
|
||||
end
|
||||
@mrbc.compile_options += ' -g'
|
||||
|
||||
@enable_debug = true
|
||||
end
|
||||
|
||||
def disable_cxx_exception
|
||||
@@ -154,8 +156,6 @@ module MRuby
|
||||
end
|
||||
|
||||
def compile_as_cxx src, cxx_src, obj = nil, includes = []
|
||||
src = File.absolute_path src
|
||||
cxx_src = File.absolute_path cxx_src
|
||||
obj = objfile(cxx_src) if obj.nil?
|
||||
|
||||
file cxx_src => [src, __FILE__] do |t|
|
||||
@@ -167,7 +167,7 @@ module MRuby
|
||||
#ifndef MRB_ENABLE_CXX_ABI
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "#{src}"
|
||||
#include "#{File.absolute_path src}"
|
||||
#ifndef MRB_ENABLE_CXX_ABI
|
||||
}
|
||||
#endif
|
||||
@@ -190,10 +190,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
|
||||
@@ -249,7 +254,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
|
||||
|
||||
@@ -257,15 +262,18 @@ 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
|
||||
|
||||
def exefile(name)
|
||||
if name.is_a?(Array)
|
||||
name.flatten.map { |n| exefile(n) }
|
||||
else
|
||||
elsif File.extname(name).empty?
|
||||
"#{name}#{exts.executable}"
|
||||
else
|
||||
# `name` sometimes have (non-standard) extension (e.g. `.bat`).
|
||||
name
|
||||
end
|
||||
end
|
||||
|
||||
@@ -293,18 +301,22 @@ EOS
|
||||
@build_mrbtest_lib_only
|
||||
end
|
||||
|
||||
def verbose_flag
|
||||
$verbose ? ' -v' : ''
|
||||
end
|
||||
|
||||
def run_test
|
||||
puts ">>> Test #{name} <<<"
|
||||
mrbtest = exefile("#{build_dir}/bin/mrbtest")
|
||||
sh "#{filename mrbtest.relative_path}#{$verbose ? ' -v' : ''}"
|
||||
sh "#{filename mrbtest.relative_path}#{verbose_flag}"
|
||||
puts
|
||||
run_bintest if bintest_enabled?
|
||||
end
|
||||
|
||||
def run_bintest
|
||||
puts ">>> Bintest #{name} <<<"
|
||||
targets = @gems.select { |v| File.directory? "#{v.dir}/bintest" }.map { |v| filename v.dir }
|
||||
targets << filename(".") if File.directory? "./bintest"
|
||||
sh "ruby test/bintest.rb #{targets.join ' '}"
|
||||
sh "ruby test/bintest.rb#{verbose_flag} #{targets.join ' '}"
|
||||
end
|
||||
|
||||
def print_build_summary
|
||||
@@ -324,6 +336,18 @@ EOS
|
||||
puts "================================================"
|
||||
puts
|
||||
end
|
||||
|
||||
def libmruby_static
|
||||
libfile("#{build_dir}/lib/libmruby")
|
||||
end
|
||||
|
||||
def libmruby_core_static
|
||||
libfile("#{build_dir}/lib/libmruby_core")
|
||||
end
|
||||
|
||||
def libraries
|
||||
[libmruby_static]
|
||||
end
|
||||
end # Build
|
||||
|
||||
class CrossBuild < Build
|
||||
|
||||
@@ -67,8 +67,8 @@ module MRuby
|
||||
path && build.filename("#{path}/#{name}").sub(/^"(.*)"$/, '\1')
|
||||
end
|
||||
|
||||
def all_flags(_defineds=[], _include_paths=[], _flags=[])
|
||||
define_flags = [defines, _defineds].flatten.map{ |d| option_define % d }
|
||||
def all_flags(_defines=[], _include_paths=[], _flags=[])
|
||||
define_flags = [defines, _defines].flatten.map{ |d| option_define % d }
|
||||
include_path_flags = [include_paths, _include_paths].flatten.map do |f|
|
||||
if MRUBY_BUILD_HOST_IS_CYGWIN
|
||||
option_include_path % cygwin_filename(f)
|
||||
@@ -79,14 +79,14 @@ module MRuby
|
||||
[flags, define_flags, include_path_flags, _flags].flatten.join(' ')
|
||||
end
|
||||
|
||||
def run(outfile, infile, _defineds=[], _include_paths=[], _flags=[])
|
||||
def run(outfile, infile, _defines=[], _include_paths=[], _flags=[])
|
||||
FileUtils.mkdir_p File.dirname(outfile)
|
||||
_pp "CC", infile.relative_path, outfile.relative_path
|
||||
if MRUBY_BUILD_HOST_IS_CYGWIN
|
||||
_run compile_options, { :flags => all_flags(_defineds, _include_paths, _flags),
|
||||
_run compile_options, { :flags => all_flags(_defines, _include_paths, _flags),
|
||||
:infile => cygwin_filename(infile), :outfile => cygwin_filename(outfile) }
|
||||
else
|
||||
_run compile_options, { :flags => all_flags(_defineds, _include_paths, _flags),
|
||||
_run compile_options, { :flags => all_flags(_defines, _include_paths, _flags),
|
||||
:infile => filename(infile), :outfile => filename(outfile) }
|
||||
end
|
||||
end
|
||||
@@ -127,13 +127,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
|
||||
|
||||
|
||||
+22
-20
@@ -52,6 +52,8 @@ module MRuby
|
||||
end
|
||||
|
||||
def setup
|
||||
return if defined?(@linker) # return if already set up
|
||||
|
||||
MRuby::Gem.current = self
|
||||
MRuby::Build::COMMANDS.each do |command|
|
||||
instance_variable_set("@#{command}", @build.send(command).clone)
|
||||
@@ -63,7 +65,7 @@ module MRuby
|
||||
objfile(f.relative_path_from(@dir).to_s.pathmap("#{build_dir}/%X"))
|
||||
end
|
||||
|
||||
@test_rbfiles = Dir.glob("#{dir}/test/**/*.rb")
|
||||
@test_rbfiles = Dir.glob("#{dir}/test/**/*.rb").sort
|
||||
@test_objs = Dir.glob("#{dir}/test/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f|
|
||||
objfile(f.relative_path_from(dir).to_s.pathmap("#{build_dir}/%X"))
|
||||
end
|
||||
@@ -87,7 +89,7 @@ module MRuby
|
||||
fail "#{name || dir} required to set name, license(s) and author(s)"
|
||||
end
|
||||
|
||||
build.libmruby << @objs
|
||||
build.libmruby_objs << @objs
|
||||
|
||||
instance_eval(&@build_config_initializer) if @build_config_initializer
|
||||
end
|
||||
@@ -110,17 +112,13 @@ module MRuby
|
||||
end
|
||||
|
||||
def add_test_dependency(*args)
|
||||
add_dependency(*args) if build.test_enabled?
|
||||
add_dependency(*args) if build.test_enabled? || build.bintest_enabled?
|
||||
end
|
||||
|
||||
def add_conflict(name, *req)
|
||||
@conflicts << {:gem => name, :requirements => req.empty? ? nil : req}
|
||||
end
|
||||
|
||||
def self.bin=(bin)
|
||||
@bins = [bin].flatten
|
||||
end
|
||||
|
||||
def build_dir
|
||||
"#{build.build_dir}/mrbgems/#{name}"
|
||||
end
|
||||
@@ -269,16 +267,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
|
||||
@@ -334,26 +334,26 @@ module MRuby
|
||||
end
|
||||
|
||||
def generate_gem_table build
|
||||
gem_table = @ary.reduce({}) { |res,v| res[v.name] = v; res }
|
||||
gem_table = each_with_object({}) { |spec, h| h[spec.name] = spec }
|
||||
|
||||
default_gems = []
|
||||
default_gems = {}
|
||||
each do |g|
|
||||
g.dependencies.each do |dep|
|
||||
default_gems << default_gem_params(dep) unless gem_table.key? dep[:gem]
|
||||
default_gems[dep[:gem]] ||= default_gem_params(dep)
|
||||
end
|
||||
end
|
||||
|
||||
until default_gems.empty?
|
||||
def_gem = default_gems.pop
|
||||
def_name, def_gem = default_gems.shift
|
||||
next if gem_table[def_name]
|
||||
|
||||
spec = build.gem def_gem[:default]
|
||||
fail "Invalid gem name: #{spec.name} (Expected: #{def_gem[:gem]})" if spec.name != def_gem[:gem]
|
||||
spec = gem_table[def_name] = build.gem(def_gem[:default])
|
||||
fail "Invalid gem name: #{spec.name} (Expected: #{def_name})" if spec.name != def_name
|
||||
spec.setup
|
||||
|
||||
spec.dependencies.each do |dep|
|
||||
default_gems << default_gem_params(dep) unless gem_table.key? dep[:gem]
|
||||
default_gems[dep[:gem]] ||= default_gem_params(dep)
|
||||
end
|
||||
gem_table[spec.name] = spec
|
||||
end
|
||||
|
||||
each do |g|
|
||||
@@ -428,7 +428,8 @@ module MRuby
|
||||
end
|
||||
|
||||
def import_include_paths(g)
|
||||
gem_table = @ary.reduce({}) { |res,v| res[v.name] = v; res }
|
||||
gem_table = each_with_object({}) { |spec, h| h[spec.name] = spec }
|
||||
|
||||
g.dependencies.each do |dep|
|
||||
dep_g = gem_table[dep[:gem]]
|
||||
# We can do recursive call safely
|
||||
@@ -454,5 +455,6 @@ module MRuby
|
||||
def new(&block); block.call(self); end
|
||||
def config=(obj); @config = obj; end
|
||||
def gem(gemdir, &block); @config.gem(gemdir, &block); end
|
||||
def gembox(gemfile); @config.gembox(gemfile); end
|
||||
end # GemBox
|
||||
end # MRuby
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
require 'getoptlong'
|
||||
require 'fileutils'
|
||||
|
||||
$rake_fiber_table = {}
|
||||
$rake_jobs = 1
|
||||
$rake_failed = []
|
||||
|
||||
class String
|
||||
def ext(newext='')
|
||||
return self.dup if ['.', '..'].include? self
|
||||
@@ -86,14 +90,36 @@ module MiniRake
|
||||
@name.to_s
|
||||
end
|
||||
|
||||
# Invoke the task if it is needed. Prerequites are invoked first.
|
||||
def done?; @done end
|
||||
def running?; @running end
|
||||
|
||||
# Invoke the task if it is needed. Prerequisites are invoked first.
|
||||
def invoke
|
||||
puts "Invoke #{name} (already=[#{@already_invoked}], needed=[#{needed?}])" if $trace
|
||||
return if @already_invoked
|
||||
@already_invoked = true
|
||||
prerequisites = @prerequisites.collect{ |n| n.is_a?(Proc) ? n.call(name) : n }.flatten
|
||||
prerequisites.each { |n| Task[n].invoke }
|
||||
execute if needed?
|
||||
prerequisites.each do |n|
|
||||
t = Task[n]
|
||||
unless t.done?
|
||||
return prerequisites.select{|v| v = Task[v]; v && (!v.done? || !v.running?) }
|
||||
end
|
||||
end
|
||||
|
||||
@already_invoked = true
|
||||
|
||||
if needed?
|
||||
@running = true
|
||||
if $rake_root_fiber
|
||||
return Fiber.new do
|
||||
self.execute
|
||||
$rake_root_fiber.transfer
|
||||
end
|
||||
else
|
||||
self.execute
|
||||
end
|
||||
end
|
||||
|
||||
@done = true
|
||||
end
|
||||
|
||||
# Execute the actions associated with this task.
|
||||
@@ -103,6 +129,8 @@ module MiniRake
|
||||
unless $dryrun
|
||||
@actions.each { |act| act.call(self) }
|
||||
end
|
||||
@done = true
|
||||
@running = false
|
||||
end
|
||||
|
||||
# Is this task needed?
|
||||
@@ -281,7 +309,19 @@ module MiniRake
|
||||
# Run the system command +cmd+.
|
||||
def sh(cmd)
|
||||
puts cmd if $verbose
|
||||
system(cmd) or fail "Command Failed: [#{cmd}]"
|
||||
|
||||
if !$rake_root_fiber || Fiber.current == $rake_root_fiber
|
||||
system(cmd) or fail "Command Failed: [#{cmd}]"
|
||||
return
|
||||
end
|
||||
|
||||
pid = Process.spawn(cmd)
|
||||
$rake_fiber_table[pid] = {
|
||||
fiber: Fiber.current,
|
||||
command: cmd,
|
||||
process_waiter: Process.detach(pid)
|
||||
}
|
||||
$rake_root_fiber.transfer
|
||||
end
|
||||
|
||||
def desc(text)
|
||||
@@ -329,7 +369,9 @@ class RakeApp
|
||||
['--verbose', '-v', GetoptLong::NO_ARGUMENT,
|
||||
"Log message to standard output."],
|
||||
['--directory', '-C', GetoptLong::REQUIRED_ARGUMENT,
|
||||
"Change executing directory of rakefiles."]
|
||||
"Change executing directory of rakefiles."],
|
||||
['--jobs', '-j', GetoptLong::REQUIRED_ARGUMENT,
|
||||
'Execute rake with parallel jobs.']
|
||||
]
|
||||
|
||||
# Create a RakeApp object.
|
||||
@@ -422,6 +464,8 @@ class RakeApp
|
||||
exit
|
||||
when '--directory'
|
||||
Dir.chdir value
|
||||
when '--jobs'
|
||||
$rake_jobs = [value.to_i, 1].max
|
||||
else
|
||||
fail "Unknown option: #{opt}"
|
||||
end
|
||||
@@ -438,6 +482,12 @@ class RakeApp
|
||||
# Run the +rake+ application.
|
||||
def run
|
||||
handle_options
|
||||
|
||||
unless $rake_root_fiber
|
||||
require 'fiber'
|
||||
$rake_root_fiber = Fiber.current
|
||||
end
|
||||
|
||||
begin
|
||||
here = Dir.pwd
|
||||
while ! have_rakefile
|
||||
@@ -447,12 +497,12 @@ class RakeApp
|
||||
end
|
||||
here = Dir.pwd
|
||||
end
|
||||
tasks = []
|
||||
root_tasks = []
|
||||
ARGV.each do |task_name|
|
||||
if /^(\w+)=(.*)/.match(task_name)
|
||||
ENV[$1] = $2
|
||||
else
|
||||
tasks << task_name
|
||||
root_tasks << task_name
|
||||
end
|
||||
end
|
||||
puts "(in #{Dir.pwd})"
|
||||
@@ -461,22 +511,93 @@ class RakeApp
|
||||
if $show_tasks
|
||||
display_tasks
|
||||
else
|
||||
tasks.push("default") if tasks.size == 0
|
||||
tasks.each do |task_name|
|
||||
MiniRake::Task[task_name].invoke
|
||||
root_tasks.push("default") if root_tasks.empty?
|
||||
# revese tasks for popping
|
||||
root_tasks.reverse!
|
||||
|
||||
tasks = []
|
||||
until root_tasks.empty?
|
||||
root_name = root_tasks.pop
|
||||
tasks << root_name
|
||||
until tasks.empty?
|
||||
task_name = tasks.pop
|
||||
t = MiniRake::Task[task_name]
|
||||
f = t.invoke
|
||||
|
||||
# append additional tasks to task queue
|
||||
if f.kind_of?(Array)
|
||||
tasks.push(*f)
|
||||
tasks.uniq!
|
||||
end
|
||||
|
||||
unless f.kind_of? Fiber
|
||||
tasks.insert 0, task_name unless t.done?
|
||||
if root_name == task_name
|
||||
wait_process
|
||||
end
|
||||
next
|
||||
end
|
||||
|
||||
wait_process while $rake_fiber_table.size >= $rake_jobs
|
||||
|
||||
f.transfer
|
||||
end
|
||||
end
|
||||
|
||||
wait_process until $rake_fiber_table.empty?
|
||||
end
|
||||
rescue Exception => ex
|
||||
puts "rake aborted!"
|
||||
rescue Exception => e
|
||||
begin
|
||||
$rake_failed << e
|
||||
wait_process until $rake_fiber_table.empty?
|
||||
rescue Exception => next_e
|
||||
e = next_e
|
||||
retry
|
||||
end
|
||||
end
|
||||
|
||||
return if $rake_failed.empty?
|
||||
|
||||
puts "rake aborted!"
|
||||
$rake_failed.each do |ex|
|
||||
puts ex.message
|
||||
if $trace
|
||||
if $trace || $verbose
|
||||
puts ex.backtrace.join("\n")
|
||||
else
|
||||
puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
|
||||
end
|
||||
exit 1
|
||||
end
|
||||
exit 1
|
||||
end
|
||||
|
||||
def wait_process(count = 0)
|
||||
dur = [0.0001 * (10 ** count), 1].min
|
||||
sleep dur
|
||||
|
||||
exited = []
|
||||
$rake_fiber_table.each do |pid, v|
|
||||
exited << pid unless v[:process_waiter].alive?
|
||||
end
|
||||
|
||||
exited.each do |pid|
|
||||
ent = $rake_fiber_table.delete pid
|
||||
st = ent[:process_waiter].value
|
||||
|
||||
# ignore process that isn't created by `sh` method
|
||||
return if ent.nil?
|
||||
|
||||
if st.exitstatus != 0
|
||||
raise "Command Failed: [#{ent[:command]}]"
|
||||
end
|
||||
|
||||
fail 'task scheduling bug!' if $rake_fiber_table.size >= $rake_jobs
|
||||
|
||||
ent[:fiber].transfer
|
||||
end
|
||||
|
||||
wait_process(count + 1) if !$rake_fiber_table.empty? && exited.empty?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if __FILE__ == $0 then
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
MRuby::GemBox.new do |conf|
|
||||
# Meta-programming features
|
||||
conf.gem :core => "mruby-metaprog"
|
||||
|
||||
# Use standard IO/File class
|
||||
conf.gem :core => "mruby-io"
|
||||
|
||||
@@ -83,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,29 +1,4 @@
|
||||
class Array
|
||||
##
|
||||
# call-seq:
|
||||
# Array.try_convert(obj) -> array or nil
|
||||
#
|
||||
# Tries to convert +obj+ into an array, using +to_ary+ method.
|
||||
# converted array or +nil+ if +obj+ cannot be converted for any reason.
|
||||
# This method can be used to check if an argument is an array.
|
||||
#
|
||||
# Array.try_convert([1]) #=> [1]
|
||||
# Array.try_convert("1") #=> nil
|
||||
#
|
||||
# if tmp = Array.try_convert(arg)
|
||||
# # the argument is an array
|
||||
# elsif tmp = String.try_convert(arg)
|
||||
# # the argument is a string
|
||||
# end
|
||||
#
|
||||
def self.try_convert(obj)
|
||||
if obj.respond_to?(:to_ary)
|
||||
obj.to_ary
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# ary.uniq! -> ary or nil
|
||||
@@ -41,23 +16,19 @@ class Array
|
||||
# c.uniq! { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
|
||||
#
|
||||
def uniq!(&block)
|
||||
ary = self.dup
|
||||
result = []
|
||||
hash = {}
|
||||
if block
|
||||
hash = {}
|
||||
while ary.size > 0
|
||||
val = ary.shift
|
||||
self.each do |val|
|
||||
key = block.call(val)
|
||||
hash[key] = val unless hash.has_key?(key)
|
||||
end
|
||||
hash.each_value do |value|
|
||||
result << value
|
||||
hash[key] = val unless hash.key?(key)
|
||||
end
|
||||
result = hash.values
|
||||
else
|
||||
while ary.size > 0
|
||||
result << ary.shift
|
||||
ary.delete(result.last)
|
||||
hash = {}
|
||||
self.each do |val|
|
||||
hash[val] = val
|
||||
end
|
||||
result = hash.keys
|
||||
end
|
||||
if result.size == self.size
|
||||
nil
|
||||
@@ -134,6 +105,25 @@ class Array
|
||||
ary.uniq! or ary
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# ary.union(other_ary,...) -> new_ary
|
||||
#
|
||||
# Set Union---Returns a new array by joining this array with
|
||||
# <i>other_ary</i>, removing duplicates.
|
||||
#
|
||||
# ["a", "b", "c"].union(["c", "d", "a"], ["a", "c", "e"])
|
||||
# #=> ["a", "b", "c", "d", "e"]
|
||||
#
|
||||
def union(*args)
|
||||
ary = self.dup
|
||||
args.each do |x|
|
||||
ary.concat(x)
|
||||
ary.uniq!
|
||||
end
|
||||
ary
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# ary & other_ary -> new_ary
|
||||
@@ -276,7 +266,6 @@ class Array
|
||||
self
|
||||
end
|
||||
|
||||
NONE=Object.new
|
||||
##
|
||||
# call-seq:
|
||||
# ary.fetch(index) -> obj
|
||||
@@ -301,7 +290,7 @@ class Array
|
||||
# #=> "100 is out of bounds"
|
||||
#
|
||||
|
||||
def fetch(n=nil, ifnone=NONE, &block)
|
||||
def fetch(n, ifnone=NONE, &block)
|
||||
warn "block supersedes default value argument" if !n.nil? && ifnone != NONE && block
|
||||
|
||||
idx = n
|
||||
@@ -782,16 +771,6 @@ class Array
|
||||
nil
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# ary.to_ary -> ary
|
||||
#
|
||||
# Returns +self+.
|
||||
#
|
||||
def to_ary
|
||||
self
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# ary.dig(idx, ...) -> object
|
||||
@@ -911,7 +890,7 @@ class Array
|
||||
#
|
||||
# Assumes that self is an array of arrays and transposes the rows and columns.
|
||||
#
|
||||
# If the length of the subarrays don’t match, an IndexError is raised.
|
||||
# If the length of the subarrays don't match, an IndexError is raised.
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
@@ -932,4 +911,32 @@ class Array
|
||||
self.map { |row| row[column_index] }
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# ary.to_h -> Hash
|
||||
# ary.to_h{|item| ... } -> Hash
|
||||
#
|
||||
# Returns the result of interpreting <i>aray</i> as an array of
|
||||
# <tt>[key, value]</tt> pairs. If a block is given, it should
|
||||
# return <tt>[key, value]</tt> pairs to construct a hash.
|
||||
#
|
||||
# [[:foo, :bar], [1, 2]].to_h
|
||||
# # => {:foo => :bar, 1 => 2}
|
||||
# [1, 2].to_h{|x| [x, x*2]}
|
||||
# # => {1 => 2, 2 => 4}
|
||||
#
|
||||
def to_h(&blk)
|
||||
h = {}
|
||||
self.each do |v|
|
||||
v = blk.call(v) if blk
|
||||
raise TypeError, "wrong element type #{v.class}" unless Array === v
|
||||
raise ArgumentError, "wrong array length (expected 2, was #{v.length})" unless v.length == 2
|
||||
h[v[0]] = v[1]
|
||||
end
|
||||
h
|
||||
end
|
||||
|
||||
alias append push
|
||||
alias prepend unshift
|
||||
end
|
||||
|
||||
@@ -106,49 +106,6 @@ mrb_ary_values_at(mrb_state *mrb, mrb_value self)
|
||||
return mrb_get_values_at(mrb, self, RARRAY_LEN(self), argc, argv, mrb_ary_ref);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ary.to_h -> Hash
|
||||
*
|
||||
* Returns the result of interpreting <i>aray</i> as an array of
|
||||
* <tt>[key, value]</tt> paris.
|
||||
*
|
||||
* [[:foo, :bar], [1, 2]].to_h
|
||||
* # => {:foo => :bar, 1 => 2}
|
||||
*
|
||||
*/
|
||||
|
||||
static mrb_value
|
||||
mrb_ary_to_h(mrb_state *mrb, mrb_value ary)
|
||||
{
|
||||
mrb_int i;
|
||||
mrb_value v, hash;
|
||||
|
||||
hash = mrb_hash_new_capa(mrb, 0);
|
||||
|
||||
for (i = 0; i < RARRAY_LEN(ary); ++i) {
|
||||
mrb_value elt = RARRAY_PTR(ary)[i];
|
||||
v = mrb_check_array_type(mrb, elt);
|
||||
|
||||
if (mrb_nil_p(v)) {
|
||||
mrb_raisef(mrb, E_TYPE_ERROR, "wrong element type %S at %S (expected array)",
|
||||
mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, elt)),
|
||||
mrb_fixnum_value(i)
|
||||
);
|
||||
}
|
||||
|
||||
if (RARRAY_LEN(v) != 2) {
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong array length at %S (expected 2, was %S)",
|
||||
mrb_fixnum_value(i),
|
||||
mrb_fixnum_value(RARRAY_LEN(v))
|
||||
);
|
||||
}
|
||||
|
||||
mrb_hash_set(mrb, hash, RARRAY_PTR(v)[0], RARRAY_PTR(v)[1]);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
@@ -175,7 +132,7 @@ static mrb_value
|
||||
mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct RArray *a = mrb_ary_ptr(self);
|
||||
mrb_int i, j, k, len, alen = ARY_LEN(a);
|
||||
mrb_int i, j, k, len, alen;
|
||||
mrb_value val;
|
||||
mrb_value *ptr;
|
||||
mrb_value ary;
|
||||
@@ -188,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, alen, TRUE) == 1) {
|
||||
if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == MRB_RANGE_OK) {
|
||||
goto delete_pos_len;
|
||||
}
|
||||
else {
|
||||
@@ -205,6 +162,7 @@ mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
|
||||
|
||||
mrb_get_args(mrb, "ii", &i, &len);
|
||||
delete_pos_len:
|
||||
alen = ARY_LEN(a);
|
||||
if (i < 0) i += alen;
|
||||
if (i < 0 || alen < i) return mrb_nil_value();
|
||||
if (len < 0) return mrb_nil_value();
|
||||
@@ -236,8 +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, "to_h", mrb_ary_to_h, MRB_ARGS_REQ(0));
|
||||
mrb_define_method(mrb, a, "slice!", mrb_ary_slice_bang, MRB_ARGS_ANY());
|
||||
mrb_define_method(mrb, a, "slice!", mrb_ary_slice_bang, MRB_ARGS_ARG(1,1));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
##
|
||||
# Array(Ext) Test
|
||||
|
||||
assert("Array.try_convert") do
|
||||
assert_nil Array.try_convert(0)
|
||||
assert_nil Array.try_convert(nil)
|
||||
assert_equal [], Array.try_convert([])
|
||||
assert_equal [1,2,3], Array.try_convert([1,2,3])
|
||||
end
|
||||
|
||||
assert("Array#assoc") do
|
||||
s1 = [ "colors", "red", "blue", "green" ]
|
||||
s2 = [ "letters", "a", "b", "c" ]
|
||||
@@ -75,6 +68,14 @@ assert("Array#|") do
|
||||
assert_equal [1, 2, 3, 1], a
|
||||
end
|
||||
|
||||
assert("Array#union") do
|
||||
a = [1, 2, 3, 1]
|
||||
b = [1, 4]
|
||||
c = [1, 5]
|
||||
|
||||
assert_equal [1, 2, 3, 4, 5], a.union(b,c)
|
||||
end
|
||||
|
||||
assert("Array#&") do
|
||||
a = [1, 2, 3, 1]
|
||||
b = [1, 4]
|
||||
@@ -267,9 +268,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]
|
||||
@@ -330,27 +331,11 @@ assert('Array#to_h') do
|
||||
assert_raise(ArgumentError) { [[1]].to_h }
|
||||
end
|
||||
|
||||
assert('Array#to_h (Modified)') do
|
||||
class A
|
||||
def to_ary
|
||||
$a.clear
|
||||
nil
|
||||
end
|
||||
end
|
||||
$a = [A.new]
|
||||
assert_raise(TypeError) { $a.to_h }
|
||||
end
|
||||
|
||||
assert("Array#index (block)") do
|
||||
assert_nil (1..10).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
|
||||
assert_equal 34, (1..100).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
|
||||
end
|
||||
|
||||
assert("Array#to_ary") do
|
||||
assert_equal [], [].to_ary
|
||||
assert_equal [1,2,3], [1,2,3].to_ary
|
||||
end
|
||||
|
||||
assert("Array#dig") do
|
||||
h = [[[1]], 0]
|
||||
assert_equal(1, h.dig(0, 0, 0))
|
||||
@@ -418,5 +403,5 @@ assert('Array#transpose') do
|
||||
assert_equal([[1], [2], [3]].transpose, [[1,2,3]])
|
||||
assert_equal([[1,2], [3,4], [5,6]].transpose, [[1,3,5], [2,4,6]])
|
||||
assert_raise(TypeError) { [1].transpose }
|
||||
assert_raise(IndexError) { [[1], [2,3,4]].transpose }
|
||||
assert_raise(IndexError) { [[1], [2,3,4]].transpose }
|
||||
end
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
unless MRuby::Build.current.kind_of?(MRuby::CrossBuild)
|
||||
MRuby::Gem::Specification.new('mruby-bin-config') do |spec|
|
||||
name = 'mruby-config'
|
||||
spec.license = 'MIT'
|
||||
spec.author = 'mruby developers'
|
||||
spec.summary = "#{name} command"
|
||||
|
||||
mruby_config = name + (ENV['OS'] == 'Windows_NT' ? '.bat' : '')
|
||||
mruby_config_path = "#{build.build_dir}/bin/#{mruby_config}"
|
||||
make_cfg = "#{build.build_dir}/lib/libmruby.flags.mak"
|
||||
tmplt_path = "#{__dir__}/#{mruby_config}"
|
||||
build.bins << mruby_config
|
||||
|
||||
file mruby_config_path => [make_cfg, tmplt_path] do |t|
|
||||
config = Hash[File.readlines(make_cfg).map!(&:chomp).map! {|l|
|
||||
l.gsub('\\"', '"').split(' = ', 2).map! {|s| s.sub(/^(?=.)/, 'echo ')}
|
||||
}]
|
||||
tmplt = File.read(tmplt_path)
|
||||
File.write(t.name, tmplt.gsub(/(#{Regexp.union(*config.keys)})\b/, config))
|
||||
FileUtils.chmod(0755, t.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -317,7 +317,7 @@ TestConstNameSubClass.new.m()
|
||||
bp = nil
|
||||
SRC
|
||||
|
||||
# todo: wait for 'break' to be implimented
|
||||
# todo: wait for 'break' to be implemented
|
||||
tc = []
|
||||
9.times { tc << {:cmd=>"s"} }
|
||||
tc << {:cmd=>"p CONST", :exp=>"super class"}
|
||||
|
||||
@@ -84,7 +84,7 @@ free_breakpoint(mrb_state *mrb, mrb_debug_breakpoint *bp)
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
check_file_lineno(struct mrb_irep *irep, const char *file, uint16_t lineno)
|
||||
check_file_lineno(mrb_state *mrb, struct mrb_irep *irep, const char *file, uint16_t lineno)
|
||||
{
|
||||
mrb_irep_debug_info_file *info_file;
|
||||
uint16_t result = 0;
|
||||
@@ -93,8 +93,10 @@ check_file_lineno(struct mrb_irep *irep, const char *file, uint16_t lineno)
|
||||
uint16_t i;
|
||||
|
||||
for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
|
||||
const char *filename;
|
||||
info_file = irep->debug_info->files[f_idx];
|
||||
if (!strcmp(info_file->filename, file)) {
|
||||
filename = mrb_sym2name_len(mrb, info_file->filename_sym, NULL);
|
||||
if (!strcmp(filename, file)) {
|
||||
result = MRB_DEBUG_BP_FILE_OK;
|
||||
|
||||
fix_lineno = check_lineno(info_file, lineno);
|
||||
@@ -103,7 +105,7 @@ check_file_lineno(struct mrb_irep *irep, const char *file, uint16_t lineno)
|
||||
}
|
||||
}
|
||||
for (i=0; i < irep->rlen; ++i) {
|
||||
result |= check_file_lineno(irep->reps[i], file, lineno);
|
||||
result |= check_file_lineno(mrb, irep->reps[i], file, lineno);
|
||||
if (result == (MRB_DEBUG_BP_FILE_OK | MRB_DEBUG_BP_LINENO_OK)) {
|
||||
return result;
|
||||
}
|
||||
@@ -185,7 +187,7 @@ mrb_debug_set_break_line(mrb_state *mrb, mrb_debug_context *dbg, const char *fil
|
||||
}
|
||||
|
||||
/* file and lineno check (line type mrb_debug_line_ary only.) */
|
||||
result = check_file_lineno(dbg->root_irep, file, lineno);
|
||||
result = check_file_lineno(mrb, dbg->root_irep, file, lineno);
|
||||
if (result == 0) {
|
||||
return MRB_DEBUG_BREAK_INVALID_FILE;
|
||||
}
|
||||
@@ -426,10 +428,10 @@ mrb_debug_disable_break_all(mrb_state *mrb, mrb_debug_context *dbg)
|
||||
}
|
||||
|
||||
static mrb_bool
|
||||
check_start_pc_for_line(mrb_irep *irep, mrb_code *pc, uint16_t line)
|
||||
check_start_pc_for_line(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, uint16_t line)
|
||||
{
|
||||
if (pc > irep->iseq) {
|
||||
if (line == mrb_debug_get_line(irep, pc - irep->iseq - 1)) {
|
||||
if (line == mrb_debug_get_line(mrb, irep, pc - irep->iseq - 1)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@@ -447,7 +449,7 @@ mrb_debug_check_breakpoint_line(mrb_state *mrb, mrb_debug_context *dbg, const ch
|
||||
return MRB_DEBUG_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (!check_start_pc_for_line(dbg->irep, dbg->pc, line)) {
|
||||
if (!check_start_pc_for_line(mrb, dbg->irep, dbg->pc, line)) {
|
||||
return MRB_DEBUG_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ mrb_debug_get_source(mrb_state *mrb, mrdb_state *mrdb, const char *srcpath, cons
|
||||
else srcname = filename;
|
||||
|
||||
search_path[0] = srcpath;
|
||||
search_path[1] = dirname(mrb, mrb_debug_get_filename(mrdb->dbg->irep, 0));
|
||||
search_path[1] = dirname(mrb, mrb_debug_get_filename(mrb, mrdb->dbg->irep, 0));
|
||||
search_path[2] = ".";
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
|
||||
@@ -31,7 +31,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)
|
||||
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 *);
|
||||
mrb_value ruby_code;
|
||||
@@ -48,6 +48,11 @@ mrb_debug_eval(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t
|
||||
v = mrb_obj_value(mrb->exc);
|
||||
mrb->exc = 0;
|
||||
}
|
||||
else if (direct_eval) {
|
||||
recv = dbg->regs[0];
|
||||
|
||||
v = mrb_funcall(mrb, recv, expr, 0);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* begin
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
#include <mruby.h>
|
||||
#include "mrdb.h"
|
||||
|
||||
mrb_value mrb_debug_eval(mrb_state*, mrb_debug_context*, const char*, size_t, mrb_bool*);
|
||||
mrb_value mrb_debug_eval(mrb_state*, mrb_debug_context*, const char*, size_t, mrb_bool*, int);
|
||||
|
||||
#endif /* APIPRINT_H_ */
|
||||
|
||||
@@ -242,7 +242,7 @@ info_break_select(mrb_state *mrb, mrdb_state *mrdb)
|
||||
}
|
||||
|
||||
mrb_debug_bptype
|
||||
parse_breakcommand(mrdb_state *mrdb, const char **file, uint32_t *line, char **cname, char **method)
|
||||
parse_breakcommand(mrb_state *mrb, mrdb_state *mrdb, const char **file, uint32_t *line, char **cname, char **method)
|
||||
{
|
||||
mrb_debug_context *dbg = mrdb->dbg;
|
||||
char *args;
|
||||
@@ -274,7 +274,7 @@ parse_breakcommand(mrdb_state *mrdb, const char **file, uint32_t *line, char **c
|
||||
STRTOUL(l, body);
|
||||
if (l <= 65535) {
|
||||
*line = l;
|
||||
*file = (body == args)? mrb_debug_get_filename(dbg->irep, dbg->pc - dbg->irep->iseq): args;
|
||||
*file = (body == args)? mrb_debug_get_filename(mrb, dbg->irep, dbg->pc - dbg->irep->iseq): args;
|
||||
}
|
||||
else {
|
||||
puts(BREAK_ERR_MSG_RANGEOVER);
|
||||
@@ -332,7 +332,7 @@ dbgcmd_break(mrb_state *mrb, mrdb_state *mrdb)
|
||||
char *method = NULL;
|
||||
int32_t ret;
|
||||
|
||||
type = parse_breakcommand(mrdb, &file, &line, &cname, &method);
|
||||
type = parse_breakcommand(mrb, mrdb, &file, &line, &cname, &method);
|
||||
switch (type) {
|
||||
case MRB_DEBUG_BPTYPE_LINE:
|
||||
ret = mrb_debug_set_break_line(mrb, dbg, file, line);
|
||||
|
||||
@@ -81,6 +81,12 @@ static help_msg help_msg_list[] = {
|
||||
"Status of specified breakpoints (all user-settable breakpoints if no argument).\n"
|
||||
"Arguments are breakpoint numbers with spaces in between.\n"
|
||||
},
|
||||
{
|
||||
"i[nfo]", "l[ocals]", "Print name of local variables",
|
||||
"Usage: info locals\n"
|
||||
"\n"
|
||||
"Print name of local variables.\n"
|
||||
},
|
||||
{
|
||||
"l[ist]", NULL, "List specified line",
|
||||
"Usage: list\n"
|
||||
@@ -495,7 +501,7 @@ dbgcmd_quit(mrb_state *mrb, mrdb_state *mrdb)
|
||||
|
||||
if (mrdb->dbg->xm == DBG_QUIT) {
|
||||
struct RClass *exc;
|
||||
exc = mrb_define_class(mrb, "DebuggerExit", mrb_class_get(mrb, "Exception"));
|
||||
exc = mrb_define_class(mrb, "DebuggerExit", mrb->eException_class);
|
||||
mrb_raise(mrb, exc, "Exit mrdb.");
|
||||
}
|
||||
return DBGST_PROMPT;
|
||||
|
||||
@@ -36,7 +36,7 @@ dbgcmd_print(mrb_state *mrb, mrdb_state *mrdb)
|
||||
expr = mrb_str_cat_cstr(mrb, expr, mrdb->words[wcnt]);
|
||||
}
|
||||
|
||||
result = mrb_debug_eval(mrb, mrdb->dbg, RSTRING_PTR(expr), RSTRING_LEN(expr), NULL);
|
||||
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");
|
||||
@@ -56,3 +56,26 @@ dbgcmd_eval(mrb_state *mrb, mrdb_state *mrdb)
|
||||
{
|
||||
return dbgcmd_print(mrb, mrdb);
|
||||
}
|
||||
|
||||
dbgcmd_state
|
||||
dbgcmd_info_local(mrb_state *mrb, mrdb_state *mrdb)
|
||||
{
|
||||
mrb_value result;
|
||||
mrb_value s;
|
||||
int ai;
|
||||
|
||||
ai = mrb_gc_arena_save(mrb);
|
||||
|
||||
result = mrb_debug_eval(mrb, mrdb->dbg, "local_variables", 0, NULL, 1);
|
||||
|
||||
s = mrb_str_cat_lit(mrb, result, "\0");
|
||||
printf("$%lu = %s\n", (unsigned long)mrdb->print_no++, RSTRING_PTR(s));
|
||||
|
||||
if (mrdb->print_no == 0) {
|
||||
mrdb->print_no = 1;
|
||||
}
|
||||
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
|
||||
return DBGST_PROMPT;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ dbgcmd_run(mrb_state *mrb, mrdb_state *mrdb)
|
||||
if (dbg->xphase == DBG_PHASE_RUNNING){
|
||||
struct RClass *exc;
|
||||
puts("Start it from the beginning.");
|
||||
exc = mrb_define_class(mrb, "DebuggerRestart", mrb_class_get(mrb, "Exception"));
|
||||
exc = mrb_define_class(mrb, "DebuggerRestart", mrb->eException_class);
|
||||
mrb_raise(mrb, exc, "Restart mrdb.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ static const debug_command debug_command_list[] = {
|
||||
{"eval", NULL, 2, 0, 0, DBGCMD_EVAL, dbgcmd_eval}, /* ev[al] */
|
||||
{"help", NULL, 1, 0, 1, DBGCMD_HELP, dbgcmd_help}, /* h[elp] */
|
||||
{"info", "breakpoints", 1, 1, 1, DBGCMD_INFO_BREAK, dbgcmd_info_break}, /* i[nfo] b[reakpoints] */
|
||||
{"info", "locals", 1, 1, 0, DBGCMD_INFO_LOCAL, dbgcmd_info_local}, /* i[nfo] l[ocals] */
|
||||
{"list", NULL, 1, 0, 1, DBGCMD_LIST, dbgcmd_list}, /* l[ist] */
|
||||
{"print", NULL, 1, 0, 0, DBGCMD_PRINT, dbgcmd_print}, /* p[rint] */
|
||||
{"quit", NULL, 1, 0, 0, DBGCMD_QUIT, dbgcmd_quit}, /* q[uit] */
|
||||
@@ -510,6 +511,7 @@ check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value
|
||||
mrb_sym sym;
|
||||
int32_t bpno;
|
||||
mrb_bool isCfunc;
|
||||
struct mrb_insn_data insn;
|
||||
|
||||
mrb_debug_context *dbg = mrb_debug_context_get(mrb);
|
||||
|
||||
@@ -517,11 +519,12 @@ check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value
|
||||
bpno = dbg->method_bpno;
|
||||
dbg->method_bpno = 0;
|
||||
|
||||
switch(GET_OPCODE(*pc)) {
|
||||
insn = mrb_decode_insn(pc);
|
||||
switch(insn.insn) {
|
||||
case OP_SEND:
|
||||
case OP_SENDB:
|
||||
c = mrb_class(mrb, regs[GETARG_A(*pc)]);
|
||||
sym = irep->syms[GETARG_B(*pc)];
|
||||
c = mrb_class(mrb, regs[insn.a]);
|
||||
sym = irep->syms[insn.b];
|
||||
break;
|
||||
case OP_SUPER:
|
||||
c = mrb->c->ci->target_class->super;
|
||||
@@ -566,8 +569,8 @@ mrb_code_fetch_hook(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *reg
|
||||
dbg->xphase = DBG_PHASE_RUNNING;
|
||||
}
|
||||
|
||||
file = mrb_debug_get_filename(irep, pc - irep->iseq);
|
||||
line = mrb_debug_get_line(irep, pc - irep->iseq);
|
||||
file = mrb_debug_get_filename(mrb, irep, pc - irep->iseq);
|
||||
line = mrb_debug_get_line(mrb, irep, pc - irep->iseq);
|
||||
|
||||
switch (dbg->xm) {
|
||||
case DBG_STEP:
|
||||
|
||||
@@ -23,6 +23,7 @@ typedef enum debug_command_id {
|
||||
DBGCMD_STEP,
|
||||
DBGCMD_BREAK,
|
||||
DBGCMD_INFO_BREAK,
|
||||
DBGCMD_INFO_LOCAL,
|
||||
DBGCMD_WATCH,
|
||||
DBGCMD_INFO_WATCH,
|
||||
DBGCMD_ENABLE,
|
||||
@@ -151,6 +152,7 @@ dbgcmd_state dbgcmd_next(mrb_state*, mrdb_state*);
|
||||
/* cmdbreak.c */
|
||||
dbgcmd_state dbgcmd_break(mrb_state*, mrdb_state*);
|
||||
dbgcmd_state dbgcmd_info_break(mrb_state*, mrdb_state*);
|
||||
dbgcmd_state dbgcmd_info_local(mrb_state*, mrdb_state*);
|
||||
dbgcmd_state dbgcmd_delete(mrb_state*, mrdb_state*);
|
||||
dbgcmd_state dbgcmd_enable(mrb_state*, mrdb_state*);
|
||||
dbgcmd_state dbgcmd_disable(mrb_state*, mrdb_state*);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -12,9 +12,9 @@ assert('regression for #1563') do
|
||||
end
|
||||
|
||||
assert('mirb -d option') do
|
||||
o, _ = Open3.capture2('bin/mirb', :stdin_data => "p $DEBUG\n")
|
||||
o, _ = Open3.capture2('bin/mirb', :stdin_data => "$DEBUG\n")
|
||||
assert_true o.include?('=> false')
|
||||
o, _ = Open3.capture2('bin/mirb -d', :stdin_data => "p $DEBUG\n")
|
||||
o, _ = Open3.capture2('bin/mirb -d', :stdin_data => "$DEBUG\n")
|
||||
assert_true o.include?('=> true')
|
||||
end
|
||||
|
||||
|
||||
@@ -6,6 +6,15 @@
|
||||
** immediately. It's a REPL...
|
||||
*/
|
||||
|
||||
#include <mruby.h>
|
||||
#include <mruby/array.h>
|
||||
#include <mruby/proc.h>
|
||||
#include <mruby/compile.h>
|
||||
#include <mruby/dump.h>
|
||||
#include <mruby/string.h>
|
||||
#include <mruby/variable.h>
|
||||
#include <mruby/throw.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
@@ -49,14 +58,6 @@
|
||||
#define SIGJMP_BUF jmp_buf
|
||||
#endif
|
||||
|
||||
#include <mruby.h>
|
||||
#include <mruby/array.h>
|
||||
#include <mruby/proc.h>
|
||||
#include <mruby/compile.h>
|
||||
#include <mruby/dump.h>
|
||||
#include <mruby/string.h>
|
||||
#include <mruby/variable.h>
|
||||
|
||||
#ifdef ENABLE_READLINE
|
||||
|
||||
static const char history_file_name[] = ".mirb_history";
|
||||
@@ -111,7 +112,7 @@ p(mrb_state *mrb, mrb_value obj, int prompt)
|
||||
if (!mrb_string_p(val)) {
|
||||
val = mrb_obj_as_string(mrb, obj);
|
||||
}
|
||||
msg = mrb_locale_from_utf8(RSTRING_PTR(val), RSTRING_LEN(val));
|
||||
msg = mrb_locale_from_utf8(RSTRING_PTR(val), (int)RSTRING_LEN(val));
|
||||
fwrite(msg, strlen(msg), 1, stdout);
|
||||
mrb_locale_free(msg);
|
||||
putc('\n', stdout);
|
||||
@@ -126,10 +127,6 @@ is_code_block_open(struct mrb_parser_state *parser)
|
||||
|
||||
/* check for heredoc */
|
||||
if (parser->parsing_heredoc != NULL) return TRUE;
|
||||
if (parser->heredoc_end_now) {
|
||||
parser->heredoc_end_now = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* check for unterminated string */
|
||||
if (parser->lex_strterm) return TRUE;
|
||||
@@ -233,7 +230,7 @@ usage(const char *name)
|
||||
{
|
||||
static const char *const usage_msg[] = {
|
||||
"switches:",
|
||||
"-d set $DEBUG to true (same as `mruby -d`)"
|
||||
"-d set $DEBUG to true (same as `mruby -d`)",
|
||||
"-r library same as `mruby -r`",
|
||||
"-v print version number, then run in verbose mode",
|
||||
"--verbose run in verbose mode",
|
||||
@@ -376,7 +373,7 @@ check_keyword(const char *buf, const char *word)
|
||||
size_t len = strlen(word);
|
||||
|
||||
/* skip preceding spaces */
|
||||
while (*p && isspace((unsigned char)*p)) {
|
||||
while (*p && ISSPACE(*p)) {
|
||||
p++;
|
||||
}
|
||||
/* check keyword */
|
||||
@@ -386,7 +383,7 @@ check_keyword(const char *buf, const char *word)
|
||||
p += len;
|
||||
/* skip trailing spaces */
|
||||
while (*p) {
|
||||
if (!isspace((unsigned char)*p)) return 0;
|
||||
if (!ISSPACE(*p)) return 0;
|
||||
p++;
|
||||
}
|
||||
return 1;
|
||||
@@ -495,7 +492,10 @@ main(int argc, char **argv)
|
||||
|
||||
while (TRUE) {
|
||||
char *utf8;
|
||||
struct mrb_jmpbuf c_jmp;
|
||||
|
||||
MRB_TRY(&c_jmp);
|
||||
mrb->jmp = &c_jmp;
|
||||
if (args.rfp) {
|
||||
if (fgets(last_code_line, sizeof(last_code_line)-1, args.rfp) != NULL)
|
||||
goto done;
|
||||
@@ -559,8 +559,7 @@ main(int argc, char **argv)
|
||||
MIRB_LINE_FREE(line);
|
||||
#endif
|
||||
|
||||
done:
|
||||
|
||||
done:
|
||||
if (code_block_open) {
|
||||
if (strlen(ruby_code)+strlen(last_code_line) > sizeof(ruby_code)-1) {
|
||||
fputs("concatenated input string too long\n", stderr);
|
||||
@@ -599,13 +598,13 @@ done:
|
||||
/* warning */
|
||||
char* msg = mrb_locale_from_utf8(parser->warn_buffer[0].message, -1);
|
||||
printf("line %d: %s\n", parser->warn_buffer[0].lineno, msg);
|
||||
mrb_utf8_free(msg);
|
||||
mrb_locale_free(msg);
|
||||
}
|
||||
if (0 < parser->nerr) {
|
||||
/* syntax error */
|
||||
char* msg = mrb_locale_from_utf8(parser->error_buffer[0].message, -1);
|
||||
printf("line %d: %s\n", parser->error_buffer[0].lineno, msg);
|
||||
mrb_utf8_free(msg);
|
||||
mrb_locale_free(msg);
|
||||
}
|
||||
else {
|
||||
/* generate bytecode */
|
||||
@@ -652,6 +651,11 @@ done:
|
||||
}
|
||||
mrb_parser_free(parser);
|
||||
cxt->lineno++;
|
||||
MRB_CATCH(&c_jmp) {
|
||||
p(mrb, mrb_obj_value(mrb->exc), 0);
|
||||
mrb->exc = 0;
|
||||
}
|
||||
MRB_END_EXC(&c_jmp);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_READLINE
|
||||
@@ -661,6 +665,12 @@ done:
|
||||
|
||||
if (args.rfp) fclose(args.rfp);
|
||||
mrb_free(mrb, args.argv);
|
||||
if (args.libv) {
|
||||
for (i = 0; i < args.libc; ++i) {
|
||||
mrb_free(mrb, args.libv[i]);
|
||||
}
|
||||
mrb_free(mrb, args.libv);
|
||||
}
|
||||
mrbc_context_free(mrb, cxt);
|
||||
mrb_close(mrb);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ MRuby::Gem::Specification.new 'mruby-bin-mrbc' do |spec|
|
||||
exec = exefile("#{build.build_dir}/bin/mrbc")
|
||||
mrbc_objs = Dir.glob("#{spec.dir}/tools/mrbc/*.c").map { |f| objfile(f.pathmap("#{spec.build_dir}/tools/mrbc/%n")) }.flatten
|
||||
|
||||
file exec => mrbc_objs + [libfile("#{build.build_dir}/lib/libmruby_core")] do |t|
|
||||
file exec => mrbc_objs + [build.libmruby_core_static] do |t|
|
||||
build.linker.run t.name, t.prerequisites
|
||||
end
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ struct mrbc_args {
|
||||
const char *initname;
|
||||
mrb_bool check_syntax : 1;
|
||||
mrb_bool verbose : 1;
|
||||
mrb_bool remove_lv : 1;
|
||||
unsigned int flags : 4;
|
||||
};
|
||||
|
||||
@@ -33,6 +34,7 @@ usage(const char *name)
|
||||
"-B<symbol> binary <symbol> output in C language format",
|
||||
"-e generate little endian iseq data",
|
||||
"-E generate big endian iseq data",
|
||||
"--remove-lv remove local variables",
|
||||
"--verbose run at verbose mode",
|
||||
"--version print the version",
|
||||
"--copyright print the copyright",
|
||||
@@ -142,6 +144,10 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
|
||||
mrb_show_copyright(mrb);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
else if (strcmp(argv[i] + 2, "remove-lv") == 0) {
|
||||
args->remove_lv = TRUE;
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
default:
|
||||
return i;
|
||||
@@ -232,6 +238,9 @@ dump_file(mrb_state *mrb, FILE *wfp, const char *outfile, struct RProc *proc, st
|
||||
int n = MRB_DUMP_OK;
|
||||
mrb_irep *irep = proc->body.irep;
|
||||
|
||||
if (args->remove_lv) {
|
||||
mrb_irep_remove_lv(mrb, irep);
|
||||
}
|
||||
if (args->initname) {
|
||||
n = mrb_dump_irep_cfunc(mrb, irep, args->flags, wfp, args->initname);
|
||||
if (n == MRB_DUMP_INVALID_ARGUMENT) {
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
module MRuby
|
||||
class Build
|
||||
def exefile(name)
|
||||
if name.is_a?(Array)
|
||||
name.flatten.map { |n| exefile(n) }
|
||||
elsif name !~ /\./
|
||||
"#{name}#{exts.executable}"
|
||||
else
|
||||
name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
MRuby.each_target do
|
||||
next if kind_of? MRuby::CrossBuild
|
||||
|
||||
mruby_config = 'mruby-config' + (ENV['OS'] == 'Windows_NT' ? '.bat' : '')
|
||||
mruby_config_path = "#{build_dir}/bin/#{mruby_config}"
|
||||
@bins << mruby_config
|
||||
|
||||
file mruby_config_path => libfile("#{build_dir}/lib/libmruby") do |t|
|
||||
FileUtils.copy "#{File.dirname(__FILE__)}/#{mruby_config}", t.name
|
||||
config = Hash[open("#{build_dir}/lib/libmruby.flags.mak").read.split("\n").map {|x| a = x.split(/\s*=\s*/, 2); [a[0], a[1].gsub('\\"', '"') ]}]
|
||||
IO.write(t.name, File.open(t.name) {|f|
|
||||
f.read.gsub (/echo (MRUBY_CFLAGS|MRUBY_LIBS|MRUBY_LDFLAGS_BEFORE_LIBS|MRUBY_LDFLAGS|MRUBY_LIBMRUBY_PATH)/) {|x| config[$1].empty? ? '' : "echo #{config[$1]}"}
|
||||
})
|
||||
FileUtils.chmod(0755, t.name)
|
||||
end
|
||||
end
|
||||
@@ -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 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
|
||||
@@ -12,7 +20,7 @@ assert('regression for #1572') do
|
||||
File.write script.path, 'p "ok"'
|
||||
system "#{cmd('mrbc')} -g -o #{bin.path} #{script.path}"
|
||||
o = `#{cmd('mruby')} -b #{bin.path}`.strip
|
||||
assert_equal o, '"ok"'
|
||||
assert_equal '"ok"', o
|
||||
end
|
||||
|
||||
assert '$0 value' do
|
||||
@@ -31,6 +39,13 @@ assert '$0 value' do
|
||||
assert_equal '"-e"', `#{cmd('mruby')} -e #{shellquote('p $0')}`.chomp
|
||||
end
|
||||
|
||||
assert('float literal') do
|
||||
script, bin = Tempfile.new('test.rb'), Tempfile.new('test.mrb')
|
||||
File.write script.path, 'p [3.21, 2e308.infinite?, -2e308.infinite?]'
|
||||
system "#{cmd('mrbc')} -g -o #{bin.path} #{script.path}"
|
||||
assert_equal "[3.21, 1, -1]", `#{cmd('mruby')} -b #{bin.path}`.chomp!
|
||||
end
|
||||
|
||||
assert '__END__', '8.6' do
|
||||
script = Tempfile.new('test.rb')
|
||||
|
||||
@@ -59,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
|
||||
@@ -66,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
|
||||
@@ -88,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
|
||||
|
||||
@@ -5,6 +5,7 @@ MRuby::Gem::Specification.new('mruby-bin-mruby') do |spec|
|
||||
spec.bins = %w(mruby)
|
||||
spec.add_dependency('mruby-compiler', :core => 'mruby-compiler')
|
||||
spec.add_dependency('mruby-error', :core => 'mruby-error')
|
||||
spec.add_test_dependency('mruby-print', :core => 'mruby-print')
|
||||
|
||||
if build.cxx_exception_enabled?
|
||||
build.compile_as_cxx("#{spec.dir}/tools/mruby/mruby.c", "#{spec.build_dir}/tools/mruby/mruby.cxx")
|
||||
|
||||
@@ -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;
|
||||
@@ -41,7 +28,7 @@ usage(const char *name)
|
||||
"switches:",
|
||||
"-b load and execute RiteBinary (mrb) file",
|
||||
"-c check syntax only",
|
||||
"-d set debugging flags (set $DEBUG to true)"
|
||||
"-d set debugging flags (set $DEBUG to true)",
|
||||
"-e 'command' one line of script",
|
||||
"-r library load the library before executing your script",
|
||||
"-v print version number, then run in verbose mode",
|
||||
@@ -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,8 @@ 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;
|
||||
}
|
||||
@@ -288,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;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ EOS
|
||||
|
||||
`#{cmd('mruby-strip')} -l #{without_lv.path}`
|
||||
assert_true without_lv.size < with_lv.size
|
||||
|
||||
assert_equal '[:a, :b]', `#{cmd('mruby')} -b #{with_lv.path}`.chomp
|
||||
assert_equal '[]', `#{cmd('mruby')} -b #{without_lv.path}`.chomp
|
||||
#
|
||||
# assert_equal '[:a, :b]', `#{cmd('mruby')} -b #{with_lv.path}`.chomp
|
||||
# assert_equal '[]', `#{cmd('mruby')} -b #{without_lv.path}`.chomp
|
||||
end
|
||||
|
||||
@@ -12,22 +12,6 @@ struct strip_args {
|
||||
mrb_bool lvar;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
irep_remove_lv(mrb_state *mrb, mrb_irep *irep)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (irep->lv) {
|
||||
mrb_free(mrb, irep->lv);
|
||||
irep->lv = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < irep->rlen; ++i) {
|
||||
irep_remove_lv(mrb, irep->reps[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_usage(const char *f)
|
||||
{
|
||||
@@ -99,7 +83,7 @@ strip(mrb_state *mrb, struct strip_args *args)
|
||||
|
||||
/* clear lv if --lvar is enabled */
|
||||
if (args->lvar) {
|
||||
irep_remove_lv(mrb, irep);
|
||||
mrb_irep_remove_lv(mrb, irep);
|
||||
}
|
||||
|
||||
wfile = fopen(filename, "wb");
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
class Module
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# mod < other -> true, false, or nil
|
||||
#
|
||||
# Returns true if `mod` is a subclass of `other`. Returns
|
||||
# <code>nil</code> if there's no relationship between the two.
|
||||
# (Think of the relationship in terms of the class definition:
|
||||
# "class A < B" implies "A < B".)
|
||||
#
|
||||
def <(other)
|
||||
if self.equal?(other)
|
||||
false
|
||||
else
|
||||
self <= other
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# mod <= other -> true, false, or nil
|
||||
#
|
||||
# Returns true if `mod` is a subclass of `other` or
|
||||
# is the same as `other`. Returns
|
||||
# <code>nil</code> if there's no relationship between the two.
|
||||
# (Think of the relationship in terms of the class definition:
|
||||
# "class A < B" implies "A < B".)
|
||||
def <=(other)
|
||||
raise TypeError, 'compared with non class/module' unless other.is_a?(Module)
|
||||
if self.ancestors.include?(other)
|
||||
return true
|
||||
elsif other.ancestors.include?(self)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# mod > other -> true, false, or nil
|
||||
#
|
||||
# Returns true if `mod` is an ancestor of `other`. Returns
|
||||
# <code>nil</code> if there's no relationship between the two.
|
||||
# (Think of the relationship in terms of the class definition:
|
||||
# "class A < B" implies "B > A".)
|
||||
#
|
||||
def >(other)
|
||||
if self.equal?(other)
|
||||
false
|
||||
else
|
||||
self >= other
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# mod >= other -> true, false, or nil
|
||||
#
|
||||
# Returns true if `mod` is an ancestor of `other`, or the
|
||||
# two modules are the same. Returns
|
||||
# <code>nil</code> if there's no relationship between the two.
|
||||
# (Think of the relationship in terms of the class definition:
|
||||
# "class A < B" implies "B > A".)
|
||||
#
|
||||
def >=(other)
|
||||
raise TypeError, 'compared with non class/module' unless other.is_a?(Module)
|
||||
return other < self
|
||||
end
|
||||
|
||||
##
|
||||
# call-seq:
|
||||
# module <=> other_module -> -1, 0, +1, or nil
|
||||
#
|
||||
# Comparison---Returns -1, 0, +1 or nil depending on whether `module`
|
||||
# includes `other_module`, they are the same, or if `module` is included by
|
||||
# `other_module`.
|
||||
#
|
||||
# Returns `nil` if `module` has no relationship with `other_module`, if
|
||||
# `other_module` is not a module, or if the two values are incomparable.
|
||||
#
|
||||
def <=>(other)
|
||||
return 0 if self.equal?(other)
|
||||
return nil unless other.is_a?(Module)
|
||||
cmp = self < other
|
||||
return -1 if cmp
|
||||
return 1 unless cmp.nil?
|
||||
return nil
|
||||
end
|
||||
end
|
||||
@@ -5,8 +5,7 @@
|
||||
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
|
||||
|
||||
@@ -1,3 +1,57 @@
|
||||
assert 'Module#<' do
|
||||
a = Class.new
|
||||
b = Class.new(a)
|
||||
c = Class.new(a)
|
||||
d = Module.new
|
||||
e = Class.new { include d }
|
||||
f = Module.new { include d }
|
||||
|
||||
# compare class to class
|
||||
assert_true b < a
|
||||
assert_false b < b
|
||||
assert_false a < b
|
||||
assert_nil c < b
|
||||
|
||||
# compare class to module
|
||||
assert_true e < d
|
||||
assert_false d < e
|
||||
assert_nil a < d
|
||||
|
||||
# compare module to module
|
||||
assert_true f < d
|
||||
assert_false f < f
|
||||
assert_false d < f
|
||||
|
||||
assert_raise(TypeError) { a < Object.new }
|
||||
end
|
||||
|
||||
assert 'Module#<=' do
|
||||
a = Class.new
|
||||
b = Class.new(a)
|
||||
c = Class.new(a)
|
||||
d = Module.new
|
||||
e = Class.new { include d }
|
||||
f = Module.new { include d }
|
||||
|
||||
# compare class to class
|
||||
assert_true b <= a
|
||||
assert_true b <= b
|
||||
assert_false a <= b
|
||||
assert_nil c <= b
|
||||
|
||||
# compare class to module
|
||||
assert_true e <= d
|
||||
assert_false d <= e
|
||||
assert_nil a <= d
|
||||
|
||||
# compare module to module
|
||||
assert_true f <= d
|
||||
assert_true f <= f
|
||||
assert_false d <= f
|
||||
|
||||
assert_raise(TypeError) { a <= Object.new }
|
||||
end
|
||||
|
||||
assert 'Module#name' do
|
||||
module Outer
|
||||
class Inner; end
|
||||
@@ -26,7 +80,7 @@ end
|
||||
assert 'Module#singleton_class?' do
|
||||
mod = Module.new
|
||||
cls = Class.new
|
||||
scl = cls.singleton_class
|
||||
scl = (class <<cls; self; end)
|
||||
|
||||
assert_false mod.singleton_class?
|
||||
assert_false cls.singleton_class?
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,14 +9,11 @@
|
||||
|
||||
enum node_type {
|
||||
NODE_METHOD,
|
||||
NODE_FBODY,
|
||||
NODE_CFUNC,
|
||||
NODE_SCOPE,
|
||||
NODE_BLOCK,
|
||||
NODE_IF,
|
||||
NODE_CASE,
|
||||
NODE_WHEN,
|
||||
NODE_OPT_N,
|
||||
NODE_WHILE,
|
||||
NODE_UNTIL,
|
||||
NODE_ITER,
|
||||
@@ -40,12 +37,12 @@ enum node_type {
|
||||
NODE_CALL,
|
||||
NODE_SCALL,
|
||||
NODE_FCALL,
|
||||
NODE_VCALL,
|
||||
NODE_SUPER,
|
||||
NODE_ZSUPER,
|
||||
NODE_ARRAY,
|
||||
NODE_ZARRAY,
|
||||
NODE_HASH,
|
||||
NODE_KW_HASH,
|
||||
NODE_RETURN,
|
||||
NODE_YIELD,
|
||||
NODE_LVAR,
|
||||
@@ -57,8 +54,6 @@ enum node_type {
|
||||
NODE_NTH_REF,
|
||||
NODE_BACK_REF,
|
||||
NODE_MATCH,
|
||||
NODE_MATCH2,
|
||||
NODE_MATCH3,
|
||||
NODE_INT,
|
||||
NODE_FLOAT,
|
||||
NODE_NEGATE,
|
||||
@@ -71,10 +66,10 @@ enum node_type {
|
||||
NODE_REGX,
|
||||
NODE_DREGX,
|
||||
NODE_DREGX_ONCE,
|
||||
NODE_LIST,
|
||||
NODE_ARG,
|
||||
NODE_ARGSCAT,
|
||||
NODE_ARGSPUSH,
|
||||
NODE_ARGS_TAIL,
|
||||
NODE_KW_ARG,
|
||||
NODE_KW_REST_ARGS,
|
||||
NODE_SPLAT,
|
||||
NODE_TO_ARY,
|
||||
NODE_SVALUE,
|
||||
@@ -88,26 +83,15 @@ enum node_type {
|
||||
NODE_SCLASS,
|
||||
NODE_COLON2,
|
||||
NODE_COLON3,
|
||||
NODE_CREF,
|
||||
NODE_DOT2,
|
||||
NODE_DOT3,
|
||||
NODE_FLIP2,
|
||||
NODE_FLIP3,
|
||||
NODE_ATTRSET,
|
||||
NODE_SELF,
|
||||
NODE_NIL,
|
||||
NODE_TRUE,
|
||||
NODE_FALSE,
|
||||
NODE_DEFINED,
|
||||
NODE_NEWLINE,
|
||||
NODE_POSTEXE,
|
||||
NODE_ALLOCA,
|
||||
NODE_DMETHOD,
|
||||
NODE_BMETHOD,
|
||||
NODE_MEMO,
|
||||
NODE_IFUNC,
|
||||
NODE_DSYM,
|
||||
NODE_ATTRASGN,
|
||||
NODE_HEREDOC,
|
||||
NODE_LITERAL_DELIM,
|
||||
NODE_WORDS,
|
||||
|
||||
+784
-323
File diff suppressed because it is too large
Load Diff
@@ -23,10 +23,10 @@ MRuby::Gem::Specification.new 'mruby-compiler' do |spec|
|
||||
cc.run t.name, t.prerequisites.first, [], ["#{current_dir}/core"]
|
||||
end
|
||||
end
|
||||
file objfile("#{current_build_dir}/core/y.tab") => lex_def
|
||||
|
||||
# Parser
|
||||
file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y"] do |t|
|
||||
file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y", lex_def] do |t|
|
||||
FileUtils.mkdir_p File.dirname t.name
|
||||
yacc.run t.name, t.prerequisites.first
|
||||
end
|
||||
|
||||
@@ -35,6 +35,6 @@ MRuby::Gem::Specification.new 'mruby-compiler' do |spec|
|
||||
gperf.run t.name, t.prerequisites.first
|
||||
end
|
||||
|
||||
file libfile("#{build.build_dir}/lib/libmruby_core") => core_objs
|
||||
file build.libmruby_core_static => core_objs
|
||||
build.libmruby << core_objs
|
||||
end
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
MRuby::Gem::Specification.new('mruby-complex') do |spec|
|
||||
spec.license = 'MIT'
|
||||
spec.author = 'mruby developers'
|
||||
spec.summary = 'Complex class'
|
||||
|
||||
spec.add_dependency 'mruby-metaprog', core: 'mruby-metaprog'
|
||||
spec.add_dependency 'mruby-object-ext', core: 'mruby-object-ext'
|
||||
spec.add_dependency 'mruby-numeric-ext', core: 'mruby-numeric-ext'
|
||||
spec.add_dependency 'mruby-math', core: 'mruby-math'
|
||||
end
|
||||
@@ -0,0 +1,123 @@
|
||||
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.real * rhs.real + rhs.imaginary * rhs.imaginary
|
||||
Complex((real * rhs.real + imaginary * rhs.imaginary) / div, (rhs.real * imaginary - real * rhs.imaginary) / div)
|
||||
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.sqrt(abs2)
|
||||
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
|
||||
end
|
||||
|
||||
[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
|
||||
@@ -0,0 +1,150 @@
|
||||
#include <mruby.h>
|
||||
#include <mruby/class.h>
|
||||
#include <mruby/numeric.h>
|
||||
|
||||
struct mrb_complex {
|
||||
mrb_float real;
|
||||
mrb_float imaginary;
|
||||
};
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
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 %S into Float", self);
|
||||
}
|
||||
|
||||
return mrb_float_value(mrb, p->real);
|
||||
}
|
||||
#endif
|
||||
|
||||
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 %S into Float", self);
|
||||
}
|
||||
return mrb_int_value(mrb, p->real);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
complex_to_c(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
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"));
|
||||
//MRB_SET_INSTANCE_TT(comp, MRB_TT_ISTRUCT);
|
||||
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());
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
mrb_define_method(mrb, comp, "to_f", complex_to_f, MRB_ARGS_NONE());
|
||||
#endif
|
||||
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());
|
||||
}
|
||||
|
||||
void
|
||||
mrb_mruby_complex_gem_final(mrb_state* mrb)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
def assert_complex(real, exp)
|
||||
assert 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)
|
||||
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
|
||||
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
|
||||
@@ -0,0 +1,6 @@
|
||||
MRuby::Gem::Specification.new('mruby-enum-chain') do |spec|
|
||||
spec.license = 'MIT'
|
||||
spec.author = 'mruby developers'
|
||||
spec.summary = 'Enumerator::Chain class'
|
||||
spec.add_dependency('mruby-enumerator', :core => 'mruby-enumerator')
|
||||
end
|
||||
@@ -0,0 +1,60 @@
|
||||
##
|
||||
# chain.rb Enumerator::Chain class
|
||||
# See Copyright Notice in mruby.h
|
||||
|
||||
module Enumerable
|
||||
def chain(*args)
|
||||
Enumerator::Chain.new(self, *args)
|
||||
end
|
||||
|
||||
def +(other)
|
||||
Enumerator::Chain.new(self, other)
|
||||
end
|
||||
end
|
||||
|
||||
class Enumerator
|
||||
class Chain
|
||||
include Enumerable
|
||||
|
||||
def initialize(*args)
|
||||
@enums = args
|
||||
end
|
||||
|
||||
def initialize_copy(orig)
|
||||
@enums = orig.__copy_enums
|
||||
end
|
||||
|
||||
def each(&block)
|
||||
return to_enum unless block_given?
|
||||
|
||||
@enums.each { |e| e.each(&block) }
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
def size
|
||||
@enums.reduce(0) do |a, e|
|
||||
return nil unless e.respond_to?(:size)
|
||||
a + e.size
|
||||
end
|
||||
end
|
||||
|
||||
def rewind
|
||||
@enums.reverse_each do |e|
|
||||
e.rewind if e.respond_to?(:rewind)
|
||||
end
|
||||
|
||||
self
|
||||
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
|
||||
@@ -0,0 +1,76 @@
|
||||
##
|
||||
# Enumerator::Chain test
|
||||
|
||||
assert("Enumerable#chain") do
|
||||
a = []
|
||||
b = {}
|
||||
c = Object.new # not has #each method
|
||||
|
||||
assert_kind_of Enumerator::Chain, a.chain
|
||||
assert_kind_of Enumerator::Chain, a.chain(b)
|
||||
assert_kind_of Enumerator::Chain, a.chain(b, c)
|
||||
assert_raise(NoMethodError) { c.chain }
|
||||
end
|
||||
|
||||
assert("Enumerable#+") do
|
||||
a = [].each
|
||||
b = {}.reverse_each
|
||||
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
|
||||
assert_raise(NoMethodError) { c + a }
|
||||
end
|
||||
|
||||
assert("Enumerator.new") do
|
||||
a = []
|
||||
b = {}
|
||||
c = Object.new # not has #each method
|
||||
|
||||
assert_kind_of Enumerator::Chain, Enumerator::Chain.new
|
||||
assert_kind_of Enumerator::Chain, Enumerator::Chain.new(a, a)
|
||||
assert_kind_of Enumerator::Chain, Enumerator::Chain.new(a, b)
|
||||
assert_kind_of Enumerator::Chain, Enumerator::Chain.new(a, c)
|
||||
assert_kind_of Enumerator::Chain, Enumerator::Chain.new(b, a)
|
||||
assert_kind_of Enumerator::Chain, Enumerator::Chain.new(b, b)
|
||||
assert_kind_of Enumerator::Chain, Enumerator::Chain.new(b, c)
|
||||
assert_kind_of Enumerator::Chain, Enumerator::Chain.new(c, a)
|
||||
end
|
||||
|
||||
assert("Enumerator::Chain#each") do
|
||||
a = [1, 2, 3]
|
||||
|
||||
aa = a.chain(a)
|
||||
assert_kind_of Enumerator, aa.each
|
||||
assert_equal [1, 2, 3, 1, 2, 3], aa.each.to_a
|
||||
|
||||
aa = a.chain(a.reverse_each)
|
||||
assert_kind_of Enumerator, aa.each
|
||||
assert_equal [1, 2, 3, 3, 2, 1], aa.each.to_a
|
||||
|
||||
aa = a.chain(a.reverse_each, a)
|
||||
assert_kind_of Enumerator, aa.each
|
||||
assert_equal [1, 2, 3, 3, 2, 1, 1, 2, 3], aa.each.to_a
|
||||
|
||||
aa = a.chain(Object.new)
|
||||
assert_kind_of Enumerator, aa.each
|
||||
assert_raise(NoMethodError) { aa.each.to_a }
|
||||
end
|
||||
|
||||
assert("Enumerator::Chain#size") do
|
||||
a = [1, 2, 3]
|
||||
|
||||
aa = a.chain(a)
|
||||
assert_equal 6, aa.size
|
||||
|
||||
aa = a.chain(a.reverse_each)
|
||||
assert_nil aa.size
|
||||
|
||||
aa = a.chain(a.reverse_each, a)
|
||||
assert_nil aa.size
|
||||
|
||||
aa = a.chain(Object.new)
|
||||
assert_nil aa.size
|
||||
end
|
||||
@@ -13,10 +13,9 @@ module Enumerable
|
||||
# a.drop(3) #=> [4, 5, 0]
|
||||
|
||||
def drop(n)
|
||||
raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
|
||||
n = n.__to_int
|
||||
raise ArgumentError, "attempt to drop negative size" if n < 0
|
||||
|
||||
n = n.to_int
|
||||
ary = []
|
||||
self.each {|*val| n == 0 ? ary << val.__svalue : n -= 1 }
|
||||
ary
|
||||
@@ -57,8 +56,8 @@ module Enumerable
|
||||
# a.take(3) #=> [1, 2, 3]
|
||||
|
||||
def take(n)
|
||||
raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
|
||||
i = n.to_int
|
||||
n = n.__to_int
|
||||
i = n.to_i
|
||||
raise ArgumentError, "attempt to take negative size" if i < 0
|
||||
ary = []
|
||||
return ary if i == 0
|
||||
@@ -113,12 +112,12 @@ module Enumerable
|
||||
# [8, 9, 10]
|
||||
|
||||
def each_cons(n, &block)
|
||||
raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
|
||||
n = n.__to_int
|
||||
raise ArgumentError, "invalid size" if n <= 0
|
||||
|
||||
return to_enum(:each_cons,n) unless block
|
||||
ary = []
|
||||
n = n.to_int
|
||||
n = n.to_i
|
||||
self.each do |*val|
|
||||
ary.shift if ary.size == n
|
||||
ary << val.__svalue
|
||||
@@ -141,12 +140,12 @@ module Enumerable
|
||||
# [10]
|
||||
|
||||
def each_slice(n, &block)
|
||||
raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
|
||||
n = n.__to_int
|
||||
raise ArgumentError, "invalid slice size" if n <= 0
|
||||
|
||||
return to_enum(:each_slice,n) unless block
|
||||
ary = []
|
||||
n = n.to_int
|
||||
n = n.to_i
|
||||
self.each do |*val|
|
||||
ary << val.__svalue
|
||||
if ary.size == n
|
||||
@@ -201,14 +200,11 @@ module Enumerable
|
||||
ary.push([block.call(e), i])
|
||||
}
|
||||
if ary.size > 1
|
||||
ary.__sort_sub__(0, ary.size - 1) do |a,b|
|
||||
a <=> b
|
||||
end
|
||||
ary.sort!
|
||||
end
|
||||
ary.collect{|e,i| orig[i]}
|
||||
end
|
||||
|
||||
NONE = Object.new
|
||||
##
|
||||
# call-seq:
|
||||
# enum.first -> obj or nil
|
||||
@@ -225,9 +221,7 @@ module Enumerable
|
||||
end
|
||||
return nil
|
||||
when 1
|
||||
n = args[0]
|
||||
raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
|
||||
i = n.to_int
|
||||
i = args[0].__to_int
|
||||
raise ArgumentError, "attempt to take negative size" if i < 0
|
||||
ary = []
|
||||
return ary if i == 0
|
||||
@@ -675,13 +669,7 @@ module Enumerable
|
||||
if nv.nil?
|
||||
n = -1
|
||||
else
|
||||
unless nv.respond_to?(:to_int)
|
||||
raise TypeError, "no implicit conversion of #{nv.class} into Integer"
|
||||
end
|
||||
n = nv.to_int
|
||||
unless n.kind_of?(Integer)
|
||||
raise TypeError, "no implicit conversion of #{nv.class} into Integer"
|
||||
end
|
||||
n = nv.__to_int
|
||||
return nil if n <= 0
|
||||
end
|
||||
|
||||
@@ -803,13 +791,22 @@ module Enumerable
|
||||
# # => {:hello => 0, :world => 1}
|
||||
#
|
||||
|
||||
def to_h
|
||||
def to_h(&blk)
|
||||
h = {}
|
||||
self.each do |*v|
|
||||
v = v.__svalue
|
||||
raise TypeError, "wrong element type #{v.class} (expected Array)" unless v.is_a? Array
|
||||
raise ArgumentError, "element has wrong array length (expected 2, was #{v.size})" if v.size != 2
|
||||
h[v[0]] = v[1]
|
||||
if blk
|
||||
self.each do |v|
|
||||
v = blk.call(v)
|
||||
raise TypeError, "wrong element type #{v.class} (expected Array)" unless v.is_a? Array
|
||||
raise ArgumentError, "element has wrong array length (expected 2, was #{v.size})" if v.size != 2
|
||||
h[v[0]] = v[1]
|
||||
end
|
||||
else
|
||||
self.each do |*v|
|
||||
v = v.__svalue
|
||||
raise TypeError, "wrong element type #{v.class} (expected Array)" unless v.is_a? Array
|
||||
raise ArgumentError, "element has wrong array length (expected 2, was #{v.size})" if v.size != 2
|
||||
h[v[0]] = v[1]
|
||||
end
|
||||
end
|
||||
h
|
||||
end
|
||||
|
||||
@@ -128,14 +128,14 @@ assert("Enumerable#any? (enhancement)") do
|
||||
end
|
||||
|
||||
assert("Enumerable#each_with_object") do
|
||||
assert_true [2, 4, 6, 8, 10, 12, 14, 16, 18, 20], (1..10).each_with_object([]) { |i, a| a << i*2 }
|
||||
assert_equal [2, 4, 6, 8, 10, 12, 14, 16, 18, 20], (1..10).each_with_object([]) { |i, a| a << i*2 }
|
||||
assert_raise(ArgumentError) { (1..10).each_with_object() { |i, a| a << i*2 } }
|
||||
end
|
||||
|
||||
assert("Enumerable#reverse_each") do
|
||||
r = (1..3)
|
||||
a = []
|
||||
assert_equal (1..3), r.reverse_each { |v| a << v }
|
||||
assert_same r, r.reverse_each { |v| a << v }
|
||||
assert_equal [3, 2, 1], a
|
||||
end
|
||||
|
||||
@@ -188,4 +188,6 @@ assert("Enumerable#to_h") do
|
||||
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
|
||||
|
||||
@@ -44,7 +44,7 @@ class Enumerator
|
||||
|
||||
def to_enum(meth=:each, *args, &block)
|
||||
unless self.respond_to?(meth)
|
||||
raise NoMethodError, "undefined method #{meth}"
|
||||
raise ArgumentError, "undefined method #{meth}"
|
||||
end
|
||||
lz = Lazy.new(self, &block)
|
||||
lz.obj = self
|
||||
|
||||
@@ -109,27 +109,30 @@ class Enumerator
|
||||
#
|
||||
# p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
|
||||
#
|
||||
def initialize(obj=nil, meth=:each, *args, &block)
|
||||
# In the second, deprecated, form, a generated Enumerator iterates over the
|
||||
# given object using the given method with the given arguments passed. This
|
||||
# form is left only for internal use.
|
||||
#
|
||||
# Use of this form is discouraged. Use Kernel#enum_for or Kernel#to_enum
|
||||
# instead.
|
||||
def initialize(obj=NONE, meth=:each, *args, &block)
|
||||
if block
|
||||
obj = Generator.new(&block)
|
||||
else
|
||||
raise ArgumentError unless obj
|
||||
end
|
||||
if @obj and !self.respond_to?(meth)
|
||||
raise NoMethodError, "undefined method #{meth}"
|
||||
elsif obj == NONE
|
||||
raise ArgumentError, "wrong number of arguments (given 0, expected 1+)"
|
||||
end
|
||||
|
||||
@obj = obj
|
||||
@meth = meth
|
||||
@args = args.dup
|
||||
@args = args
|
||||
@fib = nil
|
||||
@dst = nil
|
||||
@lookahead = nil
|
||||
@feedvalue = nil
|
||||
@stop_exc = false
|
||||
end
|
||||
attr_accessor :obj, :meth, :args, :fib
|
||||
private :obj, :meth, :args, :fib
|
||||
attr_accessor :obj, :meth, :args
|
||||
attr_reader :fib
|
||||
|
||||
def initialize_copy(obj)
|
||||
raise TypeError, "can't copy type #{obj.class}" unless obj.kind_of? Enumerator
|
||||
@@ -157,12 +160,10 @@ class Enumerator
|
||||
def with_index(offset=0, &block)
|
||||
return to_enum :with_index, offset unless block
|
||||
|
||||
offset = if offset.nil?
|
||||
0
|
||||
elsif offset.respond_to?(:to_int)
|
||||
offset.to_int
|
||||
if offset.nil?
|
||||
offset = 0
|
||||
else
|
||||
raise TypeError, "no implicit conversion of #{offset.class} into Integer"
|
||||
offset = offset.__to_int
|
||||
end
|
||||
|
||||
n = offset - 1
|
||||
@@ -223,13 +224,11 @@ class Enumerator
|
||||
end
|
||||
|
||||
def inspect
|
||||
return "#<#{self.class}: uninitialized>" unless @obj
|
||||
|
||||
if @args && @args.size > 0
|
||||
args = @args.join(", ")
|
||||
"#<#{self.class}: #{@obj}:#{@meth}(#{args})>"
|
||||
"#<#{self.class}: #{@obj.inspect}:#{@meth}(#{args})>"
|
||||
else
|
||||
"#<#{self.class}: #{@obj}:#{@meth}>"
|
||||
"#<#{self.class}: #{@obj.inspect}:#{@meth}>"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -245,9 +244,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
|
||||
#
|
||||
@@ -623,9 +623,7 @@ module Enumerable
|
||||
# use Enumerator to use infinite sequence
|
||||
def zip(*args, &block)
|
||||
args = args.map do |a|
|
||||
if a.respond_to?(:to_ary)
|
||||
a.to_ary.to_enum(:each)
|
||||
elsif a.respond_to?(:each)
|
||||
if a.respond_to?(:each)
|
||||
a.to_enum(:each)
|
||||
else
|
||||
raise TypeError, "wrong argument type #{a.class} (must respond to :each)"
|
||||
|
||||
@@ -6,11 +6,11 @@ class << @obj
|
||||
end
|
||||
end
|
||||
|
||||
assert 'Enumerator' do
|
||||
assert 'Enumerator.class' do
|
||||
assert_equal Class, Enumerator.class
|
||||
end
|
||||
|
||||
assert 'Enumerator' do
|
||||
assert 'Enumerator.superclass' do
|
||||
assert_equal Object, Enumerator.superclass
|
||||
end
|
||||
|
||||
@@ -19,11 +19,8 @@ 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(@obj, :foo, 1,2,3).to_a
|
||||
assert_equal [1,2,3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.take(3)
|
||||
assert_raise(ArgumentError) { Enumerator.new }
|
||||
enum = @obj.to_enum
|
||||
assert_raise(NoMethodError) { enum.each {} }
|
||||
|
||||
# examples
|
||||
fib = Enumerator.new do |y|
|
||||
@@ -55,12 +52,6 @@ assert 'Enumerator#with_index' do
|
||||
assert_equal [[[1, 10], 20], [[2, 11], 21], [[3, 12], 22]], a
|
||||
end
|
||||
|
||||
assert 'Enumerator#with_index nonnum offset' do
|
||||
s = Object.new
|
||||
def s.to_int; 1 end
|
||||
assert_equal([[1,1],[2,2],[3,3]], @obj.to_enum(:foo, 1, 2, 3).with_index(s).to_a)
|
||||
end
|
||||
|
||||
assert 'Enumerator#with_index string offset' do
|
||||
assert_raise(TypeError){ @obj.to_enum(:foo, 1, 2, 3).with_index('1').to_a }
|
||||
end
|
||||
@@ -99,11 +90,13 @@ end
|
||||
|
||||
assert 'Enumerator#inspect' do
|
||||
e = (0..10).each
|
||||
assert_equal("#<Enumerator: 0..10:each>", e.inspect)
|
||||
e = Enumerator.new("FooObject", :foo, 1)
|
||||
assert_equal("#<Enumerator: FooObject:foo(1)>", e.inspect)
|
||||
e = Enumerator.new("FooObject", :foo, 1, 2, 3)
|
||||
assert_equal("#<Enumerator: FooObject:foo(1, 2, 3)>", e.inspect)
|
||||
assert_equal('#<Enumerator: 0..10:each>', e.inspect)
|
||||
e = 'FooObject'.enum_for(:foo, 1)
|
||||
assert_equal('#<Enumerator: "FooObject":foo(1)>', e.inspect)
|
||||
e = 'FooObject'.enum_for(:foo, 1, 2, 3)
|
||||
assert_equal('#<Enumerator: "FooObject":foo(1, 2, 3)>', e.inspect)
|
||||
e = nil.enum_for(:to_s)
|
||||
assert_equal('#<Enumerator: nil:to_s>', e.inspect)
|
||||
end
|
||||
|
||||
assert 'Enumerator#each' do
|
||||
@@ -425,8 +418,10 @@ assert 'nested iteration' do
|
||||
end
|
||||
|
||||
assert 'Kernel#to_enum' do
|
||||
e = nil
|
||||
assert_equal Enumerator, [].to_enum.class
|
||||
assert_raise(ArgumentError){ nil.to_enum }
|
||||
assert_nothing_raised { e = [].to_enum(:_not_implemented_) }
|
||||
assert_raise(NoMethodError) { e.first }
|
||||
end
|
||||
|
||||
assert 'modifying existing methods' do
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user