Merge master branch.

This commit is contained in:
mimaki
2022-05-12 19:59:10 +09:00
123 changed files with 6843 additions and 2801 deletions
-3
View File
@@ -4,9 +4,6 @@
# MD001 heading-increment/header-increment - Heading levels should only increment by one level at a time
MD001: false
# MD010 no-hard-tabs - Hard tabs
MD010: false
# MD013 line-length - Line length
MD013: false
+9 -55
View File
@@ -10,7 +10,7 @@ jobs:
MRUBY_CONFIG: ci/gcc-clang
CC: gcc
steps:
- uses: actions/checkout@v2.4.0
- uses: actions/checkout@v3
- name: Ruby version
run: ruby -v
- name: Compiler version
@@ -25,7 +25,7 @@ jobs:
MRUBY_CONFIG: ci/gcc-clang
CC: clang
steps:
- uses: actions/checkout@v2.4.0
- uses: actions/checkout@v3
- name: Ruby version
run: ruby -v
- name: Compiler version
@@ -40,7 +40,7 @@ jobs:
MRUBY_CONFIG: ci/gcc-clang
CC: gcc
steps:
- uses: actions/checkout@v2.4.0
- uses: actions/checkout@v3
- name: Ruby version
run: ruby -v
- name: Compiler version
@@ -55,7 +55,7 @@ jobs:
MRUBY_CONFIG: ci/gcc-clang
CC: clang
steps:
- uses: actions/checkout@v2.4.0
- uses: actions/checkout@v3
- name: Ruby version
run: ruby -v
- name: Compiler version
@@ -70,7 +70,7 @@ jobs:
MRUBY_CONFIG: ci/gcc-clang
CC: clang
steps:
- uses: actions/checkout@v2.4.0
- uses: actions/checkout@v3
- name: Ruby version
run: ruby -v
- name: Compiler version
@@ -85,7 +85,7 @@ jobs:
MRUBY_CONFIG: ci/gcc-clang
CC: gcc
steps:
- uses: actions/checkout@v2.4.0
- uses: actions/checkout@v3
- name: Ruby version
run: ruby -v
- name: Compiler version
@@ -93,63 +93,17 @@ jobs:
- name: Build and test
run: rake -m test:build && rake test:run
Windows-Cygwin:
runs-on: windows-latest
timeout-minutes: 15
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
MRUBY_CONFIG: ci/gcc-clang
CC: gcc
installer-path: '%TMP%\cygwin-setup.exe'
cygwin-root: C:\cygwin
package-dir: C:\cygwin-package
cache-version: v1
steps:
- uses: actions/checkout@v2.4.0
- uses: actions/cache@v2.1.7
with:
path: ${{ env.package-dir }}
key: ${{ runner.os }}-cygwin-${{ env.cache-version }}
- name: Download Cygwin installer
shell: cmd
run: >
bitsadmin /transfer download /priority foreground
https://cygwin.com/setup-x86_64.exe ${{ env.installer-path }}
- name: Install Cygwin
shell: cmd
run: >
${{ env.installer-path }}
--quiet-mode --no-shortcuts --no-startmenu --no-desktop --no-admin
--only-site --site http://mirrors.kernel.org/sourceware/cygwin/
--root ${{ env.cygwin-root }}
--local-package-dir ${{ env.package-dir }}
--packages gcc-core,gcc-g++,ruby
- name: Set PATH for Cygwin
run: |
echo '::set-env name=PATH::${{ env.cygwin-root }}\bin;${{ env.cygwin-root }}\usr\bin'
- name: Ruby version
shell: cmd
run: ruby -v
- name: Compiler version
run: ${{ env.CC }} --version
- name: Build and test
shell: cmd
run: ruby /usr/bin/rake -m test:build && ruby /usr/bin/rake test:run
- name: Set PATH for cache archiving (tar)
# set Windows path so that Cygwin tar is not used for cache archiving
run: echo '::set-env name=PATH::C:\windows\System32'
Windows-VC:
runs-on: windows-latest
runs-on: windows-2022
timeout-minutes: 10
env:
MRUBY_CONFIG: ci/msvc
steps:
- uses: actions/checkout@v2.4.0
- uses: actions/checkout@v3
- name: Ruby version
run: ruby -v
- name: Build and test
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
rake -m test:build && rake test:run
+5 -4
View File
@@ -2,6 +2,7 @@ name: "Code scanning - action"
on:
push:
branches-ignore: "dependabot/**"
pull_request:
schedule:
- cron: '0 19 * * 4'
@@ -13,7 +14,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2.4.0
uses: actions/checkout@v3
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
@@ -21,7 +22,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, java
@@ -29,7 +30,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v2
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -43,4 +44,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2
+6 -5
View File
@@ -8,23 +8,24 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check Out
uses: actions/checkout@v2.4.0
uses: actions/checkout@v3
- name: Install
run: wget -O - -q https://git.io/misspell | sh -s -- -b .
- name: Misspell
- name: Run misspell
run: git ls-files --empty-directory | xargs ./misspell -error
pre-commit:
name: Run pre-commit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.4.0
- name: Check merge conflict
- name: Check Out
uses: actions/checkout@v3
- name: Install
run: |
python -m pip install --upgrade pip
pip install pre-commit
- name: Set PY
run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV
- uses: actions/cache@v2.1.7
- uses: actions/cache@v3
with:
path: ~/.cache/pre-commit
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
fuzz-seconds: 600
dry-run: false
- name: Upload Crash
uses: actions/upload-artifact@v2.3.1
uses: actions/upload-artifact@v3
if: failure()
with:
name: artifacts
+3 -8
View File
@@ -1,19 +1,14 @@
name: Super Linter
on:
push:
branches-ignore: [master]
# Remove the line above to run when pushing to master
pull_request:
branches: [master]
on: [pull_request]
jobs:
build:
name: Lint Code Base
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.4.0
- uses: github/super-linter@v4.8.5
- uses: actions/checkout@v3
- uses: github/super-linter@v4.9.2
env:
ERROR_ON_MISSING_EXEC_BIT: true
VALIDATE_BASH: true
+3 -3
View File
@@ -3,14 +3,14 @@ default_stages: [commit, push]
default_language_version:
# force all unspecified Python hooks to run python3
python: python3
minimum_pre_commit_version: "1.20.0"
minimum_pre_commit_version: '2.18.1'
repos:
- repo: meta
hooks:
- id: identity
- id: check-hooks-apply
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0
rev: v4.2.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
@@ -39,7 +39,7 @@ repos:
description: Check spelling with codespell
entry: codespell --ignore-words=codespell.txt
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.30.0
rev: v0.31.1
hooks:
- id: markdownlint
name: Run markdownlint
+11 -10
View File
@@ -1,16 +1,16 @@
# Authors of mruby (mruby developers)
## The List of Contributors sorted by number of commits (as of 2022-01-10 69b1667)
## The List of Contributors sorted by number of commits (as of 2022-04-28 32fb8b1)
7956 Yukihiro "Matz" Matsumoto (@matz)*
8214 Yukihiro "Matz" Matsumoto (@matz)*
586 KOBAYASHI Shuji (@shuujii)
376 Daniel Bovensiepen (@bovi)
372 dearblue (@dearblue)*
346 Takeshi Watanabe (@take-cheeze)*
342 dearblue (@dearblue)*
334 Masaki Muranaka (@monaka)
298 Tomoyuki Sahara (@tsahara)*
308 Tomoyuki Sahara (@tsahara)*
234 Jun Hiroe (@suzukaze)
219 Cremno (@cremno)*
220 Cremno (@cremno)*
208 Yuki Kurihara (@ksss)+
148 Yasuhiro Matsumoto (@mattn)*
113 Carson McDonald (@carsonmcdonald)
@@ -20,12 +20,12 @@
74 Yuichiro MASUI (@masuidrive)
71 Tatsuhiko Kubo (@cubicdaiya)*
68 Hiroshi Mimaki (@mimaki)*
63 Akira Yumiyama (@akiray03)*
67 Akira Yumiyama (@akiray03)*
62 Paolo Bosetti (@pbosetti)*
60 John Bampton (@jbampton)
59 Kurebayashi, Takahiro (@crimsonwoods)*
56 h2so5 (@h2so5)
52 Ralph Desir (@Mav7)*
49 John Bampton (@jbampton)
45 Rory O'Connell (@RoryO)*
43 Yuichiro Kaneko (@yui-knk)+
42 fleuria (@flaneur2020)
@@ -66,10 +66,10 @@
12 Ukrainskiy Sergey (@ukrainskiysergey)
12 Xuejie "Rafael" Xiao (@xxuejie)*
11 Julien Ammous (@schmurfy)
11 Kazuho Oku (@kazuho)
11 Seeker (@SeekingMeaning)
11 YAMAMOTO Masaya (pandax381)
11 takkaw (@takkaw)
10 Kazuho Oku (@kazuho)
10 Miura Hideki (@miura1729)
10 Narihiro Nakamura (@authorNari)
10 Ray Chason (@chasonr)*
@@ -107,6 +107,7 @@
5 Yurie Yamane (@yurie)+
5 dreamedge (@dreamedge)
5 nkshigeru (@nkshigeru)
4 Chris Reuter (@suetanvil)
4 Dante Catalfamo (@dantecatalfamo)
4 Goro Kikuchi (@gorogit)
4 Herwin Weststrate (@herwinw)
@@ -128,6 +129,7 @@
3 Carlo Prelz (@asfluido)*
3 David Turnbull (@AE9RB)
3 Franck Verrot (@franckverrot)
3 HASUMI Hitoshi (@hasumikin)
3 Horimoto Yasuhiro (@komainu8)
3 J. Mutua (@katmutua)+
3 Jan Berdajs (@mrbrdo)
@@ -158,7 +160,6 @@
2 Francois Chagnon (@EiNSTeiN-)*
2 Gilad Zohari (@gzohari)
2 Go Saito (@govm)
2 HASUMI Hitoshi (@hasumikin)
2 Hirohito Higashi (@HirohitoHigashi)
2 Hiroyuki Iwatsuki (@iwadon)
2 Huei-Horng Yo (@hiroshiyui)
@@ -196,7 +197,6 @@
1 Atsushi Morimoto (@mynz)
1 Ben A Morgan (@BenMorganIO)
1 Benoit Daloze (@eregon)
1 Chris Reuter (@suetanvil)
1 Daehyub Kim (@lateau)
1 Daniel Varga (@vargad)
1 Edgar Boda-Majer (@eboda)
@@ -225,6 +225,7 @@
1 Kazuhiro NISHIYAMA (@znz)
1 Kei Sawada (@remore)
1 Kim H Madsen (@kimhmadsen)
1 Koichi ITO (@koic)
1 Konstantin Haase (@rkh)
1 Leo Neat (@Leo-Neat)
1 Lian Cheng (@liancheng)
+3 -1
View File
@@ -15,4 +15,6 @@ We *don't* consider following issues as vulnerabilities:
* Runtime C undefined behavior (including integer overflow)
* Crash caused by misused API
* Crash caused by tweaked compiled binary
* Crash caused by modified compiled binary
* ASAN/Valgrind warning for too big memory allocation
mruby assumes `malloc(3)` returns `NULL` for too big allocations
+1 -1
View File
@@ -5,7 +5,7 @@ ints = [64, 32]
boxings.product(bits, ints) do |boxing, bit, int|
MRuby::Build.new("boxing-#{boxing}-m#{bit}-i#{int}") do |conf|
conf.toolchain :gcc
conf.gembox 'default'
conf.gembox 'full-core'
conf.compilers.each do |c|
c.defines << "MRB_#{boxing.upcase}_BOXING"
c.defines << "MRB_INT#{int}"
+1 -1
View File
@@ -3,7 +3,7 @@ MRuby::Build.new do |conf|
toolchain :gcc
# include the GEM box
conf.gembox 'default'
conf.gembox 'full-core'
conf.cc.defines << 'MRB_USE_FLOAT32'
+1 -1
View File
@@ -3,7 +3,7 @@ MRuby::Build.new do |conf|
toolchain :gcc
# include the GEM box
conf.gembox 'default'
conf.gembox 'full-core'
conf.cc.flags << '-pg'
conf.linker.flags << '-pg'
+1 -1
View File
@@ -3,7 +3,7 @@ MRuby::Build.new do |conf|
toolchain :gcc
# include the GEM box
conf.gembox 'default'
conf.gembox 'full-core'
conf.cc.flags << '-m32'
conf.linker.flags << '-m32'
+4 -4
View File
@@ -14,7 +14,7 @@ GC (garbage collector) must ensure that object is "alive", in other
words, that it is referenced by somewhere from the program. This can be
determined by checking if the object can be directly or indirectly
referenced by root. The local variables, global variables and
constants etc are root.
constants etc. are root.
If program execution is performed inside mruby VM, there is nothing to
worry about because GC can access all roots owned by the VM.
@@ -29,7 +29,7 @@ This can be a fatal bug if the GC tries to collect a live object.
In CRuby, we scan C stack area, and use C variable as root to check
whether object is alive or not. Of course, because we are accessing C
stack just as memory region, we never know it is an integer or a
pointer. We workaround this by assuming that if it looks like a
pointer. We work around this by assuming that if it looks like a
pointer, then assume it as a pointer. We call it "conservative".
By the way, CRuby's "conservative GC" has some problems.
@@ -65,14 +65,14 @@ objects (See `MRB_GC_FIXED_ARENA` and `MRB_GC_ARENA_SIZE` in
doc/guides/mrbconf.md).
If you create many objects in C functions, memory usage will increase, since
GC never kick in. This memory usage may look like memory leak, but will also
GC never kicks in. This memory usage may look like memory leaks, but will also
make execution slower as more memory will need to be allocated.
With the build time configuration, you can limit the maximum size of
arena (e.g., 100). Then if you create many objects, arena overflows,
thus you will get an "arena overflow error".
To workaround these problems, we have `mrb_gc_arena_save()` and
To work around these problems, we have `mrb_gc_arena_save()` and
`mrb_gc_arena_restore()` functions.
`int mrb_gc_arena_save(mrb)` returns the current position of the stack
+30 -13
View File
@@ -33,6 +33,9 @@ conf.gem :github => 'masuidrive/mrbgems-example', :branch => 'master'
conf.gem :bitbucket => 'mruby/mrbgems-example', :branch => 'master'
```
NOTE: `:bitbucket` option supports only git. Hg is unsupported in this
version.
You can specify the subdirectory of the repository with `:path` option:
```ruby
@@ -55,10 +58,24 @@ conf.gem mgem: 'mruby-redis', checksum_hash: '3446d19fc4a3f9697b5ddbf2a904f301c4
If there are missing dependencies, mrbgem dependencies solver will reference
mrbgem from the core or mgem-list.
To pull all gems from remote GIT repository on build, call `rake -p`,
or `rake --pull-gems`.
Note that if more than one git-based gem has the same base name
(i.e. the default checkout directory name), it is (now) an error
**UNLESS** they have the same repository URL, branch name and
commit-id (i.e. checksum hash). You can bypass this by explicitly
importing your preferred version **first** and setting the
`canonical:` option to `true`:
NOTE: `:bitbucket` option supports only git. Hg is unsupported in this version.
```ruby
conf.gem github: 'me/mruby-yaml', branch: 'my-hacked-branch', canonical: true
```
If you do this, the system will (mostly) silently ignore other
attempts to clone a gem with this name.
Note that this only affects cloning the gem from git. It does not
resolve version conflicts. If the version as specified in the gem's
rakefile is incompatible with a dependency, your build will still
fail.
## GemBox
@@ -94,7 +111,7 @@ conf.gembox 'custom'
This will cause the `custom` GemBox to be read in during the build process,
adding `mruby-time` and `mrbgems-example` to the build.
If you want, you can put GemBox outside of mruby directory. In that case you must
If you want, you can put GemBox outside the mruby directory. In that case you must
specify an absolute path like below.
```ruby
@@ -143,7 +160,7 @@ GEM directory. A typical GEM specification could look like this for example:
MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'Example mrbgem using C and ruby'
spec.summary = 'Example mrbgem using C and Ruby'
end
```
@@ -397,21 +414,21 @@ binary gems, to separate normal gems and binary gems.
```
+- mruby-bin-example/
|
+- README.md (Optional)
+- README.md (Optional)
|
+- bintest/
| |
| +- example.rb <- Test code for binary gem
| +- example.rb <- Test code for binary gem
|
+- mrbgem.rake <- Gem specification
+- mrbgem.rake <- Gem specification
|
+- mrblib/ <- Source for Ruby extension (Optional)
+- mrblib/ <- Source for Ruby extension (Optional)
|
+- src/ <- Source for C extension (Optional)
+- src/ <- Source for C extension (Optional)
|
+- tools/
|
+- example/ <- Executable name directory
|
+- example.c <- Source for Executable (includes main)
+- example/ <- Executable name directory
|
+- example.c <- Source for Executable (includes main)
```
+104 -104
View File
@@ -22,107 +22,107 @@ sign) of operands.
## table.1 Instruction Table
| Instruction Name | Operand type | Semantics |
|------------------|--------------|----------------------------------------------------------|
| `OP_NOP` | `-` | `no operation` |
| `OP_MOVE` | `BB` | `R(a) = R(b)` |
| `OP_LOADL` | `BB` | `R(a) = Pool(b)` |
| `OP_LOADI` | `BB` | `R(a) = mrb_int(b)` |
| `OP_LOADINEG` | `BB` | `R(a) = mrb_int(-b)` |
| `OP_LOADI__1` | `B` | `R(a) = mrb_int(-1)` |
| `OP_LOADI_0` | `B` | `R(a) = mrb_int(0)` |
| `OP_LOADI_1` | `B` | `R(a) = mrb_int(1)` |
| `OP_LOADI_2` | `B` | `R(a) = mrb_int(2)` |
| `OP_LOADI_3` | `B` | `R(a) = mrb_int(3)` |
| `OP_LOADI_4` | `B` | `R(a) = mrb_int(4)` |
| `OP_LOADI_5` | `B` | `R(a) = mrb_int(5)` |
| `OP_LOADI_6` | `B` | `R(a) = mrb_int(6)` |
| `OP_LOADI_7` | `B` | `R(a) = mrb_int(7)` |
| `OP_LOADI16` | `BS` | `R(a) = mrb_int(b)` |
| `OP_LOADI32` | `BSS` | `R(a) = mrb_int((b<<16)+c)` |
| `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[Syms(b)]` |
| `OP_SETSV` | `BB` | `Special[Syms(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` | `BS` | `if R(a) pc+=b` |
| `OP_JMPNOT` | `BS` | `if !R(a) pc+=b` |
| `OP_JMPNIL` | `BS` | `if R(a)==nil pc+=b` |
| `OP_JMPUW` | `S` | `unwind_and_jump_to(a)` |
| `OP_EXCEPT` | `B` | `R(a) = exc` |
| `OP_RESCUE` | `BB` | `R(b) = R(a).isa?(R(b))` |
| `OP_RAISEIF` | `B` | `raise(R(a)) if R(a)` |
| `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(b),R(a+1),...,R(a+c),&R(a+c+1))` |
| `OP_CALL` | `-` | `R(0) = 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=m5:r1:m5:d1:lv4)` |
| `OP_ENTER` | `W` | `arg setup according to flags (23=m5:o5:r1:m5:k5:d1:b1)` |
| `OP_KEY_P` | `BB` | `R(a) = kdict.key?(Syms(b))` |
| `OP_KEYEND` | `-` | `raise unless kdict.empty?` |
| `OP_KARG` | `BB` | `R(a) = kdict[Syms(b)]; kdict.delete(Syms(b))` |
| `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=m5:r1:m5:d1:lv4)` |
| `OP_ADD` | `B` | `R(a) = R(a)+R(a+1)` |
| `OP_ADDI` | `BB` | `R(a) = R(a)+mrb_int(b)` |
| `OP_SUB` | `B` | `R(a) = R(a)-R(a+1)` |
| `OP_SUBI` | `BB` | `R(a) = R(a)-mrb_int(b)` |
| `OP_MUL` | `B` | `R(a) = R(a)*R(a+1)` |
| `OP_DIV` | `B` | `R(a) = R(a)/R(a+1)` |
| `OP_EQ` | `B` | `R(a) = R(a)==R(a+1)` |
| `OP_LT` | `B` | `R(a) = R(a)<R(a+1)` |
| `OP_LE` | `B` | `R(a) = R(a)<=R(a+1)` |
| `OP_GT` | `B` | `R(a) = R(a)>R(a+1)` |
| `OP_GE` | `B` | `R(a) = R(a)>=R(a+1)` |
| `OP_ARRAY` | `BB` | `R(a) = ary_new(R(a),R(a+1)..R(a+b))` |
| `OP_ARRAY2` | `BBB` | `R(a) = ary_new(R(b),R(b+1)..R(b+c))` |
| `OP_ARYCAT` | `B` | `ary_cat(R(a),R(a+1))` |
| `OP_ARYPUSH` | `BB` | `ary_push(R(a),R(a+1)..R(a+b))` |
| `OP_ARYDUP` | `B` | `R(a) = ary_dup(R(a))` |
| `OP_AREF` | `BBB` | `R(a) = R(b)[c]` |
| `OP_ASET` | `BBB` | `R(b)[c] = R(a)` |
| `OP_APOST` | `BBB` | `*R(a),R(a+1)..R(a+c) = R(a)[b..]` |
| `OP_INTERN` | `B` | `R(a) = intern(R(a))` |
| `OP_STRING` | `BB` | `R(a) = str_dup(Pool(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*2-1))` |
| `OP_HASHADD` | `BB` | `hash_push(R(a),R(a+1)..R(a+b*2))` |
| `OP_HASHCAT` | `B` | `R(a) = hash_cat(R(a),R(a+1))` |
| `OP_LAMBDA` | `BB` | `R(a) = lambda(Irep(b),OP_L_LAMBDA)` |
| `OP_BLOCK` | `BB` | `R(a) = lambda(Irep(b),OP_L_BLOCK)` |
| `OP_METHOD` | `BB` | `R(a) = lambda(Irep(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),Irep[b])` |
| `OP_DEF` | `BB` | `R(a).newmethod(Syms(b),R(a+1)); R(a) = Syms(b)` |
| `OP_ALIAS` | `BB` | `alias_method(target_class,Syms(a),Syms(b))` |
| `OP_UNDEF` | `B` | `undef_method(target_class,Syms(a))` |
| `OP_SCLASS` | `B` | `R(a) = R(a).singleton_class` |
| `OP_TCLASS` | `B` | `R(a) = target_class` |
| `OP_DEBUG` | `BBB` | `print a,b,c` |
| `OP_ERR` | `B` | `raise(LocalJumpError, Pool(a))` |
| `OP_EXT1` | `-` | `make 1st operand 16bit` |
| `OP_EXT2` | `-` | `make 2nd operand 16bit` |
| `OP_EXT3` | `-` | `make 1st and 2nd operands 16bit` |
| `OP_STOP` | `-` | `stop VM` |
|------------------|--------------|----------------------------------------------------------|
| Instruction Name | Operand type | Semantics |
|--------------------|----------------|------------------------------------------------------------|
| `OP_NOP` | `-` | `no operation` |
| `OP_MOVE` | `BB` | `R(a) = R(b)` |
| `OP_LOADL` | `BB` | `R(a) = Pool(b)` |
| `OP_LOADI` | `BB` | `R(a) = mrb_int(b)` |
| `OP_LOADINEG` | `BB` | `R(a) = mrb_int(-b)` |
| `OP_LOADI__1` | `B` | `R(a) = mrb_int(-1)` |
| `OP_LOADI_0` | `B` | `R(a) = mrb_int(0)` |
| `OP_LOADI_1` | `B` | `R(a) = mrb_int(1)` |
| `OP_LOADI_2` | `B` | `R(a) = mrb_int(2)` |
| `OP_LOADI_3` | `B` | `R(a) = mrb_int(3)` |
| `OP_LOADI_4` | `B` | `R(a) = mrb_int(4)` |
| `OP_LOADI_5` | `B` | `R(a) = mrb_int(5)` |
| `OP_LOADI_6` | `B` | `R(a) = mrb_int(6)` |
| `OP_LOADI_7` | `B` | `R(a) = mrb_int(7)` |
| `OP_LOADI16` | `BS` | `R(a) = mrb_int(b)` |
| `OP_LOADI32` | `BSS` | `R(a) = mrb_int((b<<16)+c)` |
| `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[Syms(b)]` |
| `OP_SETSV` | `BB` | `Special[Syms(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` | `BS` | `if R(a) pc+=b` |
| `OP_JMPNOT` | `BS` | `if !R(a) pc+=b` |
| `OP_JMPNIL` | `BS` | `if R(a)==nil pc+=b` |
| `OP_JMPUW` | `S` | `unwind_and_jump_to(a)` |
| `OP_EXCEPT` | `B` | `R(a) = exc` |
| `OP_RESCUE` | `BB` | `R(b) = R(a).isa?(R(b))` |
| `OP_RAISEIF` | `B` | `raise(R(a)) if R(a)` |
| `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(b),R(a+1),...,R(a+c),&R(a+c+1))` |
| `OP_CALL` | `-` | `R(0) = 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=m5:r1:m5:d1:lv4)` |
| `OP_ENTER` | `W` | `arg setup according to flags (23=m5:o5:r1:m5:k5:d1:b1)` |
| `OP_KEY_P` | `BB` | `R(a) = kdict.key?(Syms(b))` |
| `OP_KEYEND` | `-` | `raise unless kdict.empty?` |
| `OP_KARG` | `BB` | `R(a) = kdict[Syms(b)]; kdict.delete(Syms(b))` |
| `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=m5:r1:m5:d1:lv4)` |
| `OP_ADD` | `B` | `R(a) = R(a)+R(a+1)` |
| `OP_ADDI` | `BB` | `R(a) = R(a)+mrb_int(b)` |
| `OP_SUB` | `B` | `R(a) = R(a)-R(a+1)` |
| `OP_SUBI` | `BB` | `R(a) = R(a)-mrb_int(b)` |
| `OP_MUL` | `B` | `R(a) = R(a)*R(a+1)` |
| `OP_DIV` | `B` | `R(a) = R(a)/R(a+1)` |
| `OP_EQ` | `B` | `R(a) = R(a)==R(a+1)` |
| `OP_LT` | `B` | `R(a) = R(a)<R(a+1)` |
| `OP_LE` | `B` | `R(a) = R(a)<=R(a+1)` |
| `OP_GT` | `B` | `R(a) = R(a)>R(a+1)` |
| `OP_GE` | `B` | `R(a) = R(a)>=R(a+1)` |
| `OP_ARRAY` | `BB` | `R(a) = ary_new(R(a),R(a+1)..R(a+b))` |
| `OP_ARRAY2` | `BBB` | `R(a) = ary_new(R(b),R(b+1)..R(b+c))` |
| `OP_ARYCAT` | `B` | `ary_cat(R(a),R(a+1))` |
| `OP_ARYPUSH` | `BB` | `ary_push(R(a),R(a+1)..R(a+b))` |
| `OP_ARYDUP` | `B` | `R(a) = ary_dup(R(a))` |
| `OP_AREF` | `BBB` | `R(a) = R(b)[c]` |
| `OP_ASET` | `BBB` | `R(b)[c] = R(a)` |
| `OP_APOST` | `BBB` | `*R(a),R(a+1)..R(a+c) = R(a)[b..]` |
| `OP_INTERN` | `B` | `R(a) = intern(R(a))` |
| `OP_STRING` | `BB` | `R(a) = str_dup(Pool(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*2-1))` |
| `OP_HASHADD` | `BB` | `hash_push(R(a),R(a+1)..R(a+b*2))` |
| `OP_HASHCAT` | `B` | `R(a) = hash_cat(R(a),R(a+1))` |
| `OP_LAMBDA` | `BB` | `R(a) = lambda(Irep(b),OP_L_LAMBDA)` |
| `OP_BLOCK` | `BB` | `R(a) = lambda(Irep(b),OP_L_BLOCK)` |
| `OP_METHOD` | `BB` | `R(a) = lambda(Irep(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),Irep[b])` |
| `OP_DEF` | `BB` | `R(a).newmethod(Syms(b),R(a+1)); R(a) = Syms(b)` |
| `OP_ALIAS` | `BB` | `alias_method(target_class,Syms(a),Syms(b))` |
| `OP_UNDEF` | `B` | `undef_method(target_class,Syms(a))` |
| `OP_SCLASS` | `B` | `R(a) = R(a).singleton_class` |
| `OP_TCLASS` | `B` | `R(a) = target_class` |
| `OP_DEBUG` | `BBB` | `print a,b,c` |
| `OP_ERR` | `B` | `raise(LocalJumpError, Pool(a))` |
| `OP_EXT1` | `-` | `make 1st operand 16bit` |
| `OP_EXT2` | `-` | `make 2nd operand 16bit` |
| `OP_EXT3` | `-` | `make 1st and 2nd operands 16bit` |
| `OP_STOP` | `-` | `stop VM` |
| ------------------ | -------------- | ---------------------------------------------------------- |
+2 -2
View File
@@ -75,7 +75,7 @@ to be default `mrb_value` representation. Now the default is
## `MRB_WORD_BOXING`
Pack `mrb_value` in an `intptr_t` integer. Consumes less
memory compared to `MRB_NO_BOXING` especially on 32 bit
memory compared to `MRB_NO_BOXING` especially on 32-bit
platforms. `Fixnum` size is 31 bits so some integer values
does not fit in `Fixnum` integers.
@@ -116,7 +116,7 @@ Instructions that access pool[i]/syms[i] where i>255.
* `OP_STRING16`
* `OP_LOADSYM16`
Instructions that load a 32 bit integer.
Instructions that load a 32-bit integer.
* `OP_LOADI32`
+44
View File
@@ -0,0 +1,44 @@
# User visible changes in `mruby3.2` from `mruby3.1`
# The language
- Now `a::B = c` should evaluate `a` then `c`.
- Anonymous arguments `*`, `**`, `&` can be passed for forwarding.
- Multi-precision integer is available now via `mruby-bigint` gem.
# Tools
## `mruby`
- `-b` only specifies the script is the binary. The files loaded by `-r` are not affected by the option.
- `mruby` now loads complied binary if the suffix is `.mrb`.
## `mrbc`
- Add `--no-optimize` option to disable optimization.
# mrbgems
## mruby-errno
- `mruby-errno` gem is now bundled.
## mruby-class-ext
- Add `Class#subclasses` method.
- Add `Module#undefined_instance_methods` method.
# CVEs
Following CVEs are fixed.
- [CVE-2022-0481](https://nvd.nist.gov/vuln/detail/CVE-2022-0481)
- [CVE-2022-0525](https://nvd.nist.gov/vuln/detail/CVE-2022-0525)
- [CVE-2022-0570](https://nvd.nist.gov/vuln/detail/CVE-2022-0570)
- [CVE-2022-0614](https://nvd.nist.gov/vuln/detail/CVE-2022-0614)
- [CVE-2022-0623](https://nvd.nist.gov/vuln/detail/CVE-2022-0623)
- [CVE-2022-0630](https://nvd.nist.gov/vuln/detail/CVE-2022-0630)
- [CVE-2022-0717](https://nvd.nist.gov/vuln/detail/CVE-2022-0817)
- [CVE-2022-1212](https://nvd.nist.gov/vuln/detail/CVE-2022-1212)
- [CVE-2022-1276](https://nvd.nist.gov/vuln/detail/CVE-2022-1276)
- [CVE-2022-1286](https://nvd.nist.gov/vuln/detail/CVE-2022-1286)
+18 -13
View File
@@ -312,7 +312,7 @@ typedef struct mrb_state {
struct RClass *eException_class;
struct RClass *eStandardError_class;
struct RObject *nomem_err; /* pre-allocated NoMemoryError */
struct RObject *stack_err; /* pre-allocated SysStackError */
struct RObject *stack_err; /* pre-allocated SystemStackError */
#ifdef MRB_GC_FIXED_ARENA
struct RObject *arena_err; /* pre-allocated arena overflow error */
#endif
@@ -948,14 +948,14 @@ typedef const char *mrb_args_format;
/**
* Get keyword arguments by `mrb_get_args()` with `:` specifier.
*
* `mrb_kwargs::num` indicates that the number of keyword values.
* `mrb_kwargs::num` indicates that the total number of keyword values.
*
* `mrb_kwargs::values` is an object array, and the keyword argument corresponding to the string array is assigned.
* Note that `undef` is assigned if there is no keyword argument corresponding to `mrb_kwargs::optional`.
* `mrb_kwargs::required` indicates that the specified number of keywords starting from the beginning of the `mrb_sym` array are required.
*
* `mrb_kwargs::table` accepts a string array.
* `mrb_kwargs::table` accepts a `mrb_sym` array of C.
*
* `mrb_kwargs::required` indicates that the specified number of keywords starting from the beginning of the string array are required.
* `mrb_kwargs::values` is an object array of C, and the keyword argument corresponding to the `mrb_sym` array is assigned.
* Note that `undef` is assigned if there is no keyword argument corresponding over `mrb_kwargs::required` to `mrb_kwargs::num`.
*
* `mrb_kwargs::rest` is the remaining keyword argument that can be accepted as `**rest` in Ruby.
* If `NULL` is specified, `ArgumentError` is raised when there is an undefined keyword.
@@ -965,10 +965,10 @@ typedef const char *mrb_args_format;
* // def method(a: 1, b: 2)
*
* uint32_t kw_num = 2;
* const char *kw_names[kw_num] = { "a", "b" };
* uint32_t kw_required = 0;
* mrb_sym kw_names[] = { mrb_intern_lit(mrb, "a"), mrb_intern_lit(mrb, "b") };
* mrb_value kw_values[kw_num];
* const mrb_kwargs kwargs = { kw_num, kw_required, kw_names, kw_values, NULL };
* mrb_kwargs kwargs = { kw_num, kw_required, kw_names, kw_values, NULL };
*
* mrb_get_args(mrb, ":", &kwargs);
* if (mrb_undef_p(kw_values[0])) { kw_values[0] = mrb_fixnum_value(1); }
@@ -979,10 +979,12 @@ typedef const char *mrb_args_format;
*
* mrb_value str, kw_rest;
* uint32_t kw_num = 3;
* const mrb_sym kw_names[kw_num] = { MRB_SYM(x), MRB_SYM(y), MRB_SYM(z) };
* uint32_t kw_required = 1;
* // Note that `#include <mruby/presym.h>` is required beforehand because `MRB_SYM()` is used.
* // If the usage of `MRB_SYM()` is not desired, replace it with `mrb_intern_lit()`.
* mrb_sym kw_names[] = { MRB_SYM(x), MRB_SYM(y), MRB_SYM(z) };
* mrb_value kw_values[kw_num];
* const mrb_kwargs kwargs = { kw_num, kw_required, kw_names, kw_values, &kw_rest };
* mrb_kwargs kwargs = { kw_num, kw_required, kw_names, kw_values, &kw_rest };
*
* mrb_get_args(mrb, "S:", &str, &kwargs);
* // or: mrb_get_args(mrb, ":S", &kwargs, &str);
@@ -1178,13 +1180,13 @@ MRB_API void mrb_free(mrb_state*, void*);
*/
#define MRB_OBJ_ALLOC(mrb, tt, klass) ((MRB_VTYPE_TYPEOF(tt)*)mrb_obj_alloc(mrb, tt, klass))
MRB_API mrb_value mrb_str_new(mrb_state *mrb, const char *p, size_t len);
MRB_API mrb_value mrb_str_new(mrb_state *mrb, const char *p, mrb_int len);
/**
* Turns a C string into a Ruby string value.
*/
MRB_API mrb_value mrb_str_new_cstr(mrb_state*, const char*);
MRB_API mrb_value mrb_str_new_static(mrb_state *mrb, const char *p, size_t len);
MRB_API mrb_value mrb_str_new_static(mrb_state *mrb, const char *p, mrb_int len);
#define mrb_str_new_lit(mrb, lit) mrb_str_new_static(mrb, (lit), mrb_strlen_lit(lit))
MRB_API mrb_value mrb_obj_freeze(mrb_state*, mrb_value);
@@ -1336,7 +1338,7 @@ MRB_API mrb_value mrb_obj_clone(mrb_state *mrb, mrb_value self);
#define TOLOWER(c) (ISUPPER(c) ? ((c) | 0x20) : (c))
#endif
MRB_API mrb_value mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, size_t len);
MRB_API mrb_value mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, mrb_int len);
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);
@@ -1404,6 +1406,9 @@ MRB_API mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str);
#define mrb_to_str(mrb, str) mrb_ensure_string_type(mrb,str)
/* obsolete: use mrb_obj_as_string() instead */
#define mrb_str_to_str(mrb, str) mrb_obj_as_string(mrb, str)
/* check if val is an integer (including Bigint) */
MRB_API mrb_value mrb_ensure_integer_type(mrb_state *mrb, mrb_value val);
/* check if val fit in mrb_int */
MRB_API mrb_value mrb_ensure_int_type(mrb_state *mrb, mrb_value val);
#define mrb_as_int(mrb, val) mrb_integer(mrb_ensure_int_type(mrb, val))
/* obsolete: use mrb_ensure_int_type() instead */
-3
View File
@@ -85,7 +85,6 @@ struct RArray {
#define ARY_SET_SHARED_FLAG(a) ((a)->flags |= MRB_ARY_SHARED)
#define ARY_UNSET_SHARED_FLAG(a) ((a)->flags &= ~MRB_ARY_SHARED)
void mrb_ary_decref(mrb_state*, mrb_shared_array*);
MRB_API void mrb_ary_modify(mrb_state*, struct RArray*);
MRB_API mrb_value mrb_ary_new_capa(mrb_state*, mrb_int);
@@ -296,8 +295,6 @@ MRB_API mrb_value mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep);
*/
MRB_API mrb_value mrb_ary_resize(mrb_state *mrb, mrb_value ary, mrb_int new_len);
/* helper functions */
mrb_value mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len);
MRB_END_DECL
-11
View File
@@ -73,8 +73,6 @@ mrb_class(mrb_state *mrb, mrb_value v)
#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)
struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym);
struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym);
MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, mrb_method_t);
MRB_API void mrb_alias_method(mrb_state*, struct RClass *c, mrb_sym a, mrb_sym b);
MRB_API void mrb_remove_method(mrb_state *mrb, struct RClass *c, mrb_sym sym);
@@ -83,15 +81,6 @@ 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*);
mrb_value mrb_mod_to_s(mrb_state*, mrb_value);
void mrb_gc_mark_mt(mrb_state*, struct RClass*);
size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*);
void mrb_gc_free_mt(mrb_state*, struct RClass*);
#ifndef MRB_NO_METHOD_CACHE
void mrb_mc_clear_by_class(mrb_state *mrb, struct RClass* c);
+4 -3
View File
@@ -31,10 +31,11 @@ typedef struct mrb_irep_debug_info_file {
uint32_t line_entry_count;
mrb_debug_line_type line_type;
union {
const char *s;
void *ptr;
uint16_t *ary;
mrb_irep_debug_info_line *flat_map;
uint8_t *packed_map;
const uint16_t *ary;
const mrb_irep_debug_info_line *flat_map;
const uint8_t *packed_map;
} lines;
} mrb_irep_debug_info_file;
+1 -5
View File
@@ -21,15 +21,11 @@ MRB_BEGIN_DECL
#define MRB_DUMP_STATIC 2
#define DUMP_DEBUG_INFO MRB_DUMP_DEBUG_INFO /* deprecated */
int mrb_dump_irep(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size);
#ifndef MRB_NO_STDIO
int mrb_dump_irep_binary(mrb_state*, const mrb_irep*, uint8_t, FILE*);
int mrb_dump_irep_cfunc(mrb_state *mrb, const mrb_irep*, uint8_t flags, FILE *f, const char *initname);
int mrb_dump_irep_cstruct(mrb_state *mrb, const mrb_irep*, uint8_t flags, FILE *f, const char *initname);
mrb_irep *mrb_read_irep_file(mrb_state*, FILE*);
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
/* avoid mrb_read_irep(); use mrb_read_irep_buf() instead (may cause buffer overflow) */
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);
+3 -7
View File
@@ -17,20 +17,16 @@ MRB_BEGIN_DECL
struct RException {
MRB_OBJECT_HEADER;
struct iv_tbl *iv;
struct RString *mesg;
struct RObject *mesg; // NULL or probably RString
struct RObject *backtrace; // NULL, RArray or RData
};
#define mrb_exc_ptr(v) ((struct RException*)mrb_ptr(v))
#define MRB_EXC_MESG_STRING_FLAG 0x100
MRB_API void mrb_sys_fail(mrb_state *mrb, const char *mesg);
MRB_API mrb_noreturn void mrb_sys_fail(mrb_state *mrb, const char *mesg);
MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str);
#define mrb_exc_new_lit(mrb, c, lit) mrb_exc_new_str(mrb, c, mrb_str_new_lit(mrb, lit))
#define mrb_exc_new_str_lit(mrb, c, lit) mrb_exc_new_lit(mrb, c, lit)
MRB_API mrb_value mrb_make_exception(mrb_state *mrb, mrb_int argc, const mrb_value *argv);
mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc);
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 */
+1 -2
View File
@@ -84,8 +84,7 @@ typedef struct mrb_gc {
size_t majorgc_old_threshold;
} mrb_gc;
MRB_API mrb_bool
mrb_object_dead_p(struct mrb_state *mrb, struct RBasic *object);
MRB_API mrb_bool mrb_object_dead_p(struct mrb_state *mrb, struct RBasic *object);
#define MRB_GC_RED 7
-6
View File
@@ -35,7 +35,6 @@ struct RHash {
#define mrb_hash_ptr(v) ((struct RHash*)(mrb_ptr(v)))
#define mrb_hash_value(p) mrb_obj_value((void*)(p))
size_t mrb_hash_memsize(mrb_value obj);
MRB_API mrb_value mrb_hash_new_capa(mrb_state *mrb, mrb_int capa);
/*
@@ -226,11 +225,6 @@ MRB_API void mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2);
#define MRB_RHASH_DEFAULT_P(hash) (RHASH(hash)->flags & MRB_HASH_DEFAULT)
#define MRB_RHASH_PROCDEFAULT_P(hash) (RHASH(hash)->flags & MRB_HASH_PROC_DEFAULT)
/* GC functions */
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);
+192
View File
@@ -0,0 +1,192 @@
/**
** @file mruby/internal.h - Functions only called from within the library
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_INTERNAL_H
#define MRUBY_INTERNAL_H
#ifdef MRUBY_ARRAY_H
void mrb_ary_decref(mrb_state*, mrb_shared_array*);
mrb_value mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len);
#endif
#ifdef MRUBY_CLASS_H
struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym);
struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym);
mrb_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*);
mrb_value mrb_mod_to_s(mrb_state *, mrb_value);
void mrb_method_added(mrb_state *mrb, struct RClass *c, mrb_sym mid);
#endif
/* debug */
size_t mrb_packed_int_len(uint32_t num);
size_t mrb_packed_int_encode(uint32_t num, uint8_t *p, uint8_t *pend);
uint32_t mrb_packed_int_decode(const uint8_t *p, const uint8_t **newpos);
/* dump */
#ifdef MRUBY_IREP_H
int mrb_dump_irep(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size);
#ifndef MRB_NO_STDIO
int mrb_dump_irep_binary(mrb_state*, const mrb_irep*, uint8_t, FILE*);
int mrb_dump_irep_cfunc(mrb_state *mrb, const mrb_irep*, uint8_t flags, FILE *f, const char *initname);
int mrb_dump_irep_cstruct(mrb_state *mrb, const mrb_irep*, uint8_t flags, FILE *f, const char *initname);
mrb_irep *mrb_read_irep_file(mrb_state*, FILE*);
#endif
#endif
/* error */
mrb_value mrb_exc_inspect(mrb_state *mrb, mrb_value exc);
mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc);
mrb_value mrb_get_backtrace(mrb_state *mrb);
void mrb_exc_mesg_set(mrb_state *mrb, struct RException *exc, mrb_value mesg);
mrb_value mrb_exc_mesg_get(mrb_state *mrb, struct RException *exc);
/* gc */
void mrb_gc_mark_mt(mrb_state*, struct RClass*);
size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*);
void mrb_gc_free_mt(mrb_state*, struct RClass*);
/* hash */
size_t mrb_hash_memsize(mrb_value obj);
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*);
/* irep */
struct mrb_insn_data mrb_decode_insn(const mrb_code *pc);
#ifdef MRUBY_IREP_H
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);
static inline const struct mrb_irep_catch_handler *
mrb_irep_catch_handler_table(const struct mrb_irep *irep)
{
if (irep->clen > 0) {
return (const struct mrb_irep_catch_handler*)(irep->iseq + irep->ilen);
}
else {
return (const struct mrb_irep_catch_handler*)NULL;
}
}
#endif
/* numeric */
mrb_int mrb_div_int(mrb_state *mrb, mrb_int x, mrb_int y);
mrb_value mrb_int_add(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_int_sub(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_int_mul(mrb_state *mrb, mrb_value x, mrb_value y);
void mrb_int_zerodiv(mrb_state *mrb);
void mrb_int_overflow(mrb_state *mrb, const char *reason);
#ifdef MRB_USE_COMPLEX
mrb_value mrb_complex_new(mrb_state *mrb, mrb_float x, mrb_float y);
mrb_value mrb_complex_add(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_complex_sub(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_complex_mul(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_complex_div(mrb_state *mrb, mrb_value x, mrb_value y);
#endif
#ifdef MRB_USE_RATIONAL
mrb_value mrb_rational_new(mrb_state *mrb, mrb_int x, mrb_int y);
mrb_value mrb_rational_add(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_rational_sub(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_rational_mul(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_rational_div(mrb_state *mrb, mrb_value x, mrb_value y);
#endif
#ifdef MRUBY_PROC_H
struct RProc *mrb_proc_new(mrb_state*, const mrb_irep*);
struct RProc *mrb_closure_new(mrb_state*, const mrb_irep*);
void mrb_proc_copy(mrb_state *mrb, struct RProc *a, struct RProc *b);
mrb_int mrb_proc_arity(const struct RProc *p);
#endif
/* range */
#ifdef MRUBY_RANGE_H
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);
#endif
/* string */
void mrb_gc_free_str(mrb_state*, struct RString*);
uint32_t mrb_str_hash(mrb_state *mrb, mrb_value str);
mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str);
mrb_value mrb_str_inspect(mrb_state *mrb, mrb_value str);
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_value mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value idx, mrb_value len);
#ifdef MRB_UTF8_STRING
mrb_int mrb_utf8len(const char *str, const char *end);
mrb_int mrb_utf8_strlen(const char *str, mrb_int byte_len);
#endif
/* variable */
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_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);
void mrb_vm_const_set(mrb_state*, mrb_sym, mrb_value);
size_t mrb_obj_iv_tbl_memsize(mrb_value);
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*);
void mrb_gc_free_gv(mrb_state*);
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*);
/* VM */
mrb_int mrb_ci_bidx(mrb_callinfo *ci);
#ifdef MRB_USE_BIGINT
mrb_value mrb_bint_new_int(mrb_state *mrb, mrb_int x);
mrb_value mrb_bint_new_str(mrb_state *mrb, const char *x, mrb_int len, mrb_int base);
mrb_value mrb_as_bint(mrb_state *mrb, mrb_value x);
mrb_value mrb_bint_add(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_bint_sub(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_bint_mul(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_bint_div(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_bint_divmod(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_bint_add_ii(mrb_state *mrb, mrb_int x, mrb_int y);
mrb_value mrb_bint_sub_ii(mrb_state *mrb, mrb_int x, mrb_int y);
mrb_value mrb_bint_mul_ii(mrb_state *mrb, mrb_int x, mrb_int y);
mrb_value mrb_bint_div_ii(mrb_state *mrb, mrb_int x, mrb_int y);
mrb_value mrb_bint_mod(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_bint_rem(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_bint_pow(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_bint_powm(mrb_state *mrb, mrb_value x, mrb_int y, mrb_value z);
mrb_value mrb_bint_and(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_bint_or(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_bint_xor(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_bint_rev(mrb_state *mrb, mrb_value x);
mrb_value mrb_bint_lshift(mrb_state *mrb, mrb_value x, mrb_int width);
mrb_value mrb_bint_rshift(mrb_state *mrb, mrb_value x, mrb_int width);
mrb_value mrb_bint_to_s(mrb_state *mrb, mrb_value x, mrb_int base);
#ifndef MRB_NO_FLOAT
mrb_value mrb_bint_new_float(mrb_state *mrb, mrb_float x);
mrb_float mrb_bint_as_float(mrb_state *mrb, mrb_value x);
#endif
mrb_int mrb_bint_as_int(mrb_state *mrb, mrb_value x);
mrb_int mrb_bint_cmp(mrb_state *mrb, mrb_value x, mrb_value y);
void mrb_gc_free_bint(mrb_state *mrb, struct RBasic *x);
#endif
#endif /* MRUBY_INTERNAL_H */
+2 -21
View File
@@ -99,7 +99,7 @@ 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.
* @param [size_t] size of irep buffer.
*/
MRB_API mrb_value mrb_load_irep_buf(mrb_state*, const void*, size_t);
@@ -108,16 +108,10 @@ 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.
* @param [size_t] size of irep buffer.
*/
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;
@@ -126,19 +120,6 @@ struct mrb_insn_data {
const mrb_code *addr;
};
struct mrb_insn_data mrb_decode_insn(const mrb_code *pc);
static inline const struct mrb_irep_catch_handler *
mrb_irep_catch_handler_table(const struct mrb_irep *irep)
{
if (irep->clen > 0) {
return (const struct mrb_irep_catch_handler*)(irep->iseq + irep->ilen);
}
else {
return (const struct mrb_irep_catch_handler*)NULL;
}
}
#define mrb_irep_catch_handler_pack(n, v) uint32_to_bin(n, v)
#define mrb_irep_catch_handler_unpack(v) bin_to_uint32(v)
+6 -9
View File
@@ -30,16 +30,17 @@ MRB_BEGIN_DECL
#endif
#endif
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);
/* utility functions */
MRB_API mrb_value mrb_num_add(mrb_state *mrb, mrb_value x, mrb_value y);
MRB_API mrb_value mrb_num_sub(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);
/* obsolete old names */
#define mrb_num_plus(mrb, x, y) mrb_num_add(mrb, x, y)
#define mrb_num_minus(mrb, x, y) mrb_num_sub(mrb, x, y)
MRB_API mrb_value mrb_integer_to_str(mrb_state *mrb, mrb_value x, mrb_int base);
MRB_API char *mrb_int_to_cstr(char *buf, size_t len, mrb_int n, mrb_int base);
/* internal function(s) */
mrb_int mrb_div_int(mrb_state *mrb, mrb_int x, mrb_int y);
/* obsolete function(s); will be removed */
#define mrb_fixnum_to_str(mrb, x, base) mrb_integer_to_str(mrb, x, base)
@@ -166,10 +167,6 @@ mrb_float mrb_div_float(mrb_float x, mrb_float y);
mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt);
int mrb_format_float(mrb_float f, char *buf, size_t buf_size, char fmt, int prec, char sign);
/* obsolete functions; will be removed */
#define mrb_flo_to_fixnum(mrb, val) mrb_float_to_integer(mrb, val)
#define mrb_to_flo(mrb, x) mrb_as_float(mrb, x)
#endif /* MRB_NO_FLOAT */
MRB_END_DECL
-4
View File
@@ -88,12 +88,8 @@ struct RProc {
#define mrb_proc_ptr(v) ((struct RProc*)(mrb_ptr(v)))
struct RProc *mrb_proc_new(mrb_state*, const mrb_irep*);
struct RProc *mrb_closure_new(mrb_state*, const 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(mrb_state *mrb, struct RProc *a, struct RProc *b);
mrb_int mrb_proc_arity(const struct RProc *p);
/* 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, mrb_func_t func, mrb_int argc, const mrb_value *argv);
-2
View File
@@ -71,8 +71,6 @@ enum mrb_range_beg_len {
};
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
+5 -22
View File
@@ -102,7 +102,6 @@ struct RStringEmbed {
#define RSTRING_LEN(s) RSTR_LEN(RSTRING(s))
#define RSTRING_CAPA(s) RSTR_CAPA(RSTRING(s))
#define RSTRING_END(s) (RSTRING_PTR(s) + RSTRING_LEN(s))
MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*);
#define RSTRING_CSTR(mrb,s) mrb_string_cstr(mrb, s)
#define MRB_STR_SHARED 1
@@ -115,8 +114,6 @@ MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*);
#define MRB_STR_EMBED_LEN_MASK (((1 << MRB_STR_EMBED_LEN_BIT) - 1) << MRB_STR_EMBED_LEN_SHIFT)
#define MRB_STR_TYPE_MASK 15
void mrb_gc_free_str(mrb_state*, struct RString*);
MRB_API void mrb_str_modify(mrb_state *mrb, struct RString *s);
/* mrb_str_modify() with keeping ASCII flag if set */
MRB_API void mrb_str_modify_keep_ascii(mrb_state *mrb, struct RString *s);
@@ -324,7 +321,7 @@ MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len);
*/
MRB_API mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
MRB_API mrb_value mrb_str_new_capa(mrb_state *mrb, size_t capa);
MRB_API mrb_value mrb_str_new_capa(mrb_state *mrb, mrb_int capa);
#define mrb_str_buf_new(mrb, capa) mrb_str_new_capa(mrb, (capa))
/* NULL terminated C string from mrb_value */
@@ -332,9 +329,11 @@ MRB_API const char *mrb_string_cstr(mrb_state *mrb, mrb_value str);
/* NULL terminated C string from mrb_value; `str` will be updated */
MRB_API const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *str);
/* obsolete: use RSTRING_PTR() */
MRB_API const char *mrb_string_value_ptr(mrb_state *mrb, mrb_value str);
#define mrb_string_value_ptr(mrb, str) RSTRING_PTR(str)
/* obsolete: use RSTRING_LEN() */
MRB_API mrb_int mrb_string_value_len(mrb_state *mrb, mrb_value str);
#define mrb_string_value_len(mrb, str) RSTRING_LEN(str)
/* obsolete: substituted by a macro; shall be removed */
#define mrb_str_strlen(mrb, s) strlen(RSTR_PTR(s))
/**
* Duplicates a string object.
@@ -422,27 +421,11 @@ MRB_API int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2);
*/
MRB_API char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str);
uint32_t mrb_str_hash(mrb_state *mrb, mrb_value str);
mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str);
/**
* Returns a printable version of str, surrounded by quote marks, with special characters escaped.
*/
mrb_value mrb_str_inspect(mrb_state *mrb, mrb_value str);
/* For backward compatibility */
#define mrb_str_cat2(mrb, str, ptr) mrb_str_cat_cstr(mrb, str, ptr)
#define mrb_str_buf_cat(mrb, str, ptr, len) mrb_str_cat(mrb, str, ptr, len)
#define mrb_str_buf_append(mrb, str, str2) mrb_str_cat_str(mrb, str, str2)
mrb_bool mrb_str_beg_len(mrb_int str_len, mrb_int *begp, mrb_int *lenp);
mrb_value mrb_str_byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
#ifdef MRB_UTF8_STRING
mrb_int mrb_utf8len(const char *str, const char *end);
mrb_int mrb_utf8_strlen(const char *str, mrb_int byte_len);
#endif
MRB_END_DECL
#endif /* MRUBY_STRING_H */
+5 -1
View File
@@ -154,7 +154,8 @@ static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000;
f(MRB_TT_ISTRUCT, struct RIStruct, "istruct") \
f(MRB_TT_BREAK, struct RBreak, "break") \
f(MRB_TT_COMPLEX, struct RComplex, "Complex") \
f(MRB_TT_RATIONAL, struct RRational, "Rational")
f(MRB_TT_RATIONAL, struct RRational, "Rational") \
f(MRB_TT_BIGINT, struct RBigint, "Integer")
enum mrb_vtype {
#define MRB_VTYPE_DEFINE(tt, type, name) tt,
@@ -300,6 +301,9 @@ struct RCptr {
#define mrb_bool(o) (mrb_type(o) != MRB_TT_FALSE)
#endif
#define mrb_test(o) mrb_bool(o)
#ifndef mrb_bigint_p
#define mrb_bigint_p(o) (mrb_type(o) == MRB_TT_BIGINT)
#endif
/**
* Returns a float in Ruby.
-23
View File
@@ -14,13 +14,6 @@
*/
MRB_BEGIN_DECL
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_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);
void mrb_vm_const_set(mrb_state*, mrb_sym, mrb_value);
size_t mrb_obj_iv_tbl_memsize(mrb_value);
MRB_API mrb_value mrb_const_get(mrb_state*, mrb_value, mrb_sym);
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);
@@ -99,22 +92,6 @@ MRB_API mrb_value mrb_cv_get(mrb_state *mrb, mrb_value mod, mrb_sym sym);
MRB_API void mrb_mod_cv_set(mrb_state *mrb, struct RClass * c, mrb_sym sym, mrb_value v);
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*);
void mrb_gc_free_gv(mrb_state*);
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*);
+11 -1
View File
@@ -123,6 +123,7 @@ module MRuby
@enable_test = false
@enable_lock = true
@enable_presym = true
@enable_benchmark = true
@mrbcfile_external = false
@internal = internal
@toolchains = []
@@ -232,6 +233,14 @@ module MRuby
@cxx_abi_enabled = true
end
def benchmark_enabled?
@enable_benchmark
end
def disable_benchmark
@enable_benchmark = false
end
def compile_as_cxx(src, cxx_src = nil, obj = nil, includes = [])
#
# If `cxx_src` is specified, this method behaves the same as before as
@@ -491,7 +500,8 @@ EOS
v = instance_variable_get(n)
v = case v
when nil, true, false, Numeric; v
when String, Command; v.clone
when String; v.clone
when Command; v.clone.tap { |u| u.build = build }
else Marshal.load(Marshal.dump(v)) # deep clone
end
build.instance_variable_set(n, v)
+324 -82
View File
@@ -1,5 +1,8 @@
require 'yaml'
module MRuby
module LoadGems
def gembox(gemboxfile)
gembox = File.expand_path("#{gemboxfile}.gembox", "#{MRUBY_ROOT}/mrbgems")
fail "Can't find gembox '#{gembox}'" unless File.exist?(gembox)
@@ -12,28 +15,30 @@ module MRuby
GemBox.path = nil
end
def gem(gemdir, &block)
if gemdir.is_a?(Hash)
gemdir = load_special_path_gem(gemdir)
elsif GemBox.path
gemdir = File.expand_path(gemdir, File.dirname(GemBox.path))
else
caller_dir = File.expand_path(File.dirname(caller(1,1)[0][/^(.*?):\d/,1]))
if caller_dir == "#{MRUBY_ROOT}/build_config"
caller_dir = MRUBY_ROOT
end
gemdir = File.expand_path(gemdir, caller_dir)
end
def gem(gem_src, &block)
gemrake = File.join(gemdir, "mrbgem.rake")
caller_dir = File.expand_path(File.dirname(caller(1,1)[0][/^(.*?):\d/,1]))
gem_src = {gemdir: gem_src} if gem_src.is_a? String
@gem_checkouts ||= {}
checkout = GemLoader
.new(self, caller_dir, @gem_checkouts, **gem_src)
.fetch!
return nil unless checkout
@gem_checkouts[checkout.gemdir] = checkout
# Load the gem's rakefile
gemrake = File.join(checkout.gemdir, "mrbgem.rake")
fail "Can't find #{gemrake}" unless File.exist?(gemrake)
Gem.current = nil
load gemrake
return nil unless Gem.current
current = Gem.current
current.dir = gemdir
# Add it to gems
current.dir = checkout.gemdir
current.build = self.is_a?(MRuby::Build) ? self : MRuby::Build.current
current.build_config_initializer = block
gems << current
@@ -44,92 +49,329 @@ module MRuby
current
end
def load_special_path_gem(params)
if params[:github]
params[:git] = "https://github.com/#{params[:github]}.git"
elsif params[:bitbucket]
if params[:method] == "ssh"
params[:git] = "git@bitbucket.org:#{params[:bitbucket]}.git"
else
params[:git] = "https://bitbucket.org/#{params[:bitbucket]}.git"
end
elsif params[:mgem]
mgem_list_dir = "#{gem_clone_dir}/mgem-list"
mgem_list_url = 'https://github.com/mruby/mgem-list.git'
if File.exist? mgem_list_dir
git.run_pull mgem_list_dir, mgem_list_url if $pull_gems
else
mkdir_p mgem_list_dir
git.run_clone mgem_list_dir, mgem_list_url, "--depth 1"
end
require 'yaml'
# Class to represent the relationship between a gem dependency and
# its remote repository (if any).
class GemCheckout
attr_reader :gemdir, :repo, :branch, :commit
conf_path = "#{mgem_list_dir}/#{params[:mgem]}.gem"
conf_path = "#{mgem_list_dir}/mruby-#{params[:mgem]}.gem" unless File.exist? conf_path
fail "mgem not found: #{params[:mgem]}" unless File.exist? conf_path
conf = YAML.load File.read conf_path
def initialize(gemdir, repo, branch, commit, canonical)
@gemdir = gemdir # Working copy of the gem
fail "unknown mgem protocol: #{conf['protocol']}" if conf['protocol'] != 'git'
params[:git] = conf['repository']
params[:branch] = conf['branch'] if conf['branch']
@repo = repo # Remote gem repo
@branch = branch # Branch to check out
@commit = commit # Commit-id to use
@canonical = canonical # This is the One True checkout
end
if params[:core]
gemdir = "#{root}/mrbgems/#{params[:core]}"
elsif params[:git]
url = params[:git]
gemdir = "#{gem_clone_dir}/#{url.match(/([-\w]+)(\.[-\w]+|)$/).to_a[1]}"
def canonical?() return @canonical; end
def git?() return !!@repo; end
def gemname() return File.basename(@gemdir); end
# by default the 'master' branch is used
branch = params[:branch] ? params[:branch] : 'master'
def hash()
return [@gemdir, @repo, @branch, @commit, @canonical].hash
end
lock = locks[url] if lock_enabled?
def ==(other)
return @gemdir == other.gemdir && @repo == other.repo &&
@branch == other.branch && @commit == other.commit &&
@canonical == other.canonical?
end
alias_method :eql?, :==
if File.exist?(gemdir)
if $pull_gems
# Jump to the top of the branch
git.run_checkout gemdir, branch
git.run_pull gemdir, url
elsif params[:checksum_hash]
git.run_checkout_detach gemdir, params[:checksum_hash]
elsif lock
git.run_checkout_detach gemdir, lock['commit']
end
def to_s
desc = @gemdir
desc += " -> #{@repo}/#{@branch}" if git?
desc += "/#{commit}" if commit
return desc
end
end
# Class to decode the argument set given to 'MRuby::Build::gem',
# and git-clone+git-checkout the sources if needed.
class GemLoader
def initialize(build,
build_config_dir, # Parent dir. of build_config
gem_checkouts, # Hash of existing checkouts
# Git repo:
git: nil,
branch: "master",
checksum_hash: nil,
options: [],
# Git repo on GitHub
github: nil,
# Git repo on BitBucket
bitbucket: nil,
method: nil,
# mgem entry
mgem: nil,
# Core package
core: nil,
# Path relative to the mruby checkout; probably wrong!
path: nil,
# Local file(s)
gemdir: nil,
# Related flags:
canonical: false # Ignore subsequent checkout of this gem
)
@build = build
@build_config_dir = build_config_dir
@gem_checkouts = gem_checkouts
@canonical = canonical
@git = git
@branch = branch
@checksum_hash = checksum_hash
@options = options
@canonical = canonical
@github = github
@bitbucket = bitbucket
@method = method
@mgem = mgem
@core = core
@path = path
@gemdir = gemdir
actions = [git, github, bitbucket, mgem, core, path, gemdir]
fail("Need to set exactly ONE of git, github, bitbucket, mgem, core, " +
"path, or gemdir") unless actions.compact.size == 1
end
# Retrieve the repo and return the details in a GemCheckout
# object or nil if nothing needed to be done.
def fetch!
return fromGemdir! if @gemdir
return fromCore! if @core
return fromPath! if @path
return fromGitHub! if @github
return fromBitBucket! if @bitbucket
return fromMGem! if @mgem
return fromGit!(@git, @branch) if @git
# Shouldn't be reachable, but...
fail "Invalid gem configuration!"
end
private
#
# Local Paths
#
def fromGemdir!
gem_src = @gemdir
# If @gemdir is a relative path, we first convert it to an
# absolute path; this depends on circumstances.
if MRuby::GemBox.path
# If GemBox.path is set, it means that this fetch operation is
# happening as part of a gembox evaluation and we use the
# gembox's path as the starting point.
gem_src = File.expand_path(gem_src, File.dirname(MRuby::GemBox.path))
else
options = [params[:options]] || []
options << "--recursive"
options << "--branch \"#{branch}\""
options << "--depth 1" unless params[:checksum_hash] || lock
mkdir_p "#{gem_clone_dir}"
git.run_clone gemdir, url, options
# Otherwise, we use the path to the build_config.rb file that
# requested this gem. This path was extracted earlier and
# stored in @build_config_dir via the second argument of
# 'initialize'.
root_dir = @build_config_dir
# Jump to the specified commit
if params[:checksum_hash]
git.run_checkout_detach gemdir, params[:checksum_hash]
elsif lock
git.run_checkout_detach gemdir, lock['commit']
end
# And we default to the repo root if the file is one of the
# stock configs in build_config/.
root_dir = MRUBY_ROOT if root_dir == "#{MRUBY_ROOT}/build_config"
gem_src = File.expand_path(gem_src, root_dir)
end
if lock_enabled?
@gem_dir_to_repo_url[gemdir] = url unless params[:path]
locks[url] = {
return GemCheckout.new(gem_src, nil, nil, nil, @canonical)
end
def fromCore!
return GemCheckout.new("#{@build.root}/mrbgems/#{@core}", nil, nil,
nil, @canonical)
end
# This is probably incorrect.
#
# According to doc/guides/mrbgems.md, this should specify a
# subdirectory of a git checkout (i.e. for the case where the gem
# itself is not in the repository's root.)
#
# However, the code treats this as simple path to a local
# directory (just like :gemdir) with relative paths resolved
# relative to the project root.
#
# I'm pretty sure that the correct thing is what guide says but
# I'm going to keep the initial semantics for now.
def fromPath!
p = Pathname.new(@path).absolute? ? @path : "#{@build.root}/#{@path}"
return GemCheckout.new(p, nil, nil, nil, @canonical)
end
#
# Git forges
#
def fromGitHub!
url = "https://github.com/#{@github}.git"
return fromGit!(url, @branch)
end
def fromBitBucket!
if @method == "ssh"
url = "git@bitbucket.org:#{@bitbucket}.git"
else
url = "https://bitbucket.org/#{@bitbucket}.git"
end
return fromGit!(url, @branch)
end
#
# mgem file
#
def fromMGem!
mgem = fetchMGem(@mgem)
url = mgem['repository']
branch = mgem['branch'] || @branch
return fromGit!(url, branch)
end
# Fetch the contents of the named mgem item. Will clone the
# mgem-list repo if not present
def fetchMGem(mgem)
list_dir = "#{@build.gem_clone_dir}/mgem-list"
url = 'https://github.com/mruby/mgem-list.git'
git_clone_dependency(url, list_dir, nil, 'master')
conf_path = "#{list_dir}/#{mgem}.gem"
conf_path = "#{list_dir}/mruby-#{mgem}.gem" unless
File.exist? conf_path
fail "mgem not found: #{mgem}" unless File.exist? conf_path
conf = YAML.load File.read conf_path
fail "unknown mgem protocol: #{conf['protocol']}" if
conf['protocol'] != 'git'
return conf
end
#
# Git checkouts
#
def fromGit!(url, branch)
repo_dir = "#{@build.gem_clone_dir}/" +
"#{url.match(/([-\w]+)(\.[-\w]+|)$/).to_a[1]}"
commit = @checksum_hash
return nil if skip_this?(url, repo_dir, branch, commit)
# If there's a lockfile entry for this repo AND the user hasn't
# specified a specific commit ID, we use the locked branch and
# commit.
lock = @build.locks[url] if @build.lock_enabled?
if !commit && lock
branch = lock['branch']
commit = lock['commit']
end
# Clone the dependency (if needed) and checkout the expected
# revision.
git_clone_dependency(url, repo_dir, commit, branch)
git_checkout_dependency(repo_dir, commit, branch)
# Set the lockfile entry if enabled
if @build.lock_enabled?
@build.gem_dir_to_repo_url[repo_dir] = url
@build.locks[url] = {
'url' => url,
'branch' => git.current_branch(gemdir),
'commit' => git.commit_hash(gemdir),
'branch' => @build.git.current_branch(repo_dir),
'commit' => @build.git.commit_hash(repo_dir),
}
end
gemdir << "/#{params[:path]}" if params[:path]
elsif params[:path]
require 'pathname'
gemdir = Pathname.new(params[:path]).absolute? ? params[:path] : "#{root}/#{params[:path]}"
else
fail "unknown gem option #{params}"
return GemCheckout.new(repo_dir, url, branch, commit, @canonical)
end
gemdir
# Test if this repo can be skipped. This will happen if it's
# already in @gem_checkouts and EITHER it is identical (same
# url, branch and commit-ID) as the current checkout OR it's
# "canonical" flag is true. If it's in @gem_checkouts and
# neither of these conditions is true, that's a fatal error; it
# means there are multiple incompatible versions of this gem to
# be checked out into this directory.
#
# Otherwise, returns false.
def skip_this?(url, repo_dir, branch, commit)
prev = @gem_checkouts[repo_dir]
return false unless prev
# Canonical declarations must precede all others.
fail("Attempted to re-declare #{prev.gemname} as canonical!\n" +
"('canonical' can only be used on its first declaration.)") if
prev && @canonical
# If prev is canonical, we can ignore this
if prev.canonical?
puts "Found canonical #{prev.gemname}; skipping this one."
return true
end
# If this checkout is identical to the current one, we can skip it.
candidate = GemCheckout.new(repo_dir, url, branch, commit, @canonical)
if prev == candidate
puts "Found duplicate checkout for #{repo_dir}; ignoring."
return true
end
# Otherwise, we have a checkout conflict. This is an error.
fail "Conflicting gem definitions for '#{repo_dir}':\n" +
" #{candidate}\n" +
" #{prev}\n"
end
# Retrieve a git repo if it's not present. Return
# [path_to_checkout, did_clone]
def git_clone_dependency(url, repo_dir, commit, branch)
return if File.exist?(repo_dir)
FileUtils.mkdir_p repo_dir
options = @options.dup
options << "--recursive"
options << "--branch \"#{branch}\""
options << "--depth 1" unless commit
@build.git.run_clone repo_dir, url, options
end
def git_checkout_dependency(repo_dir, commit, branch)
@build.git.run_checkout_detach(repo_dir, commit)
end
end
def enable_gems?
+6 -12
View File
@@ -3,6 +3,7 @@
#include <mruby/array.h>
#include <mruby/range.h>
#include <mruby/hash.h>
#include <mruby/internal.h>
#include <mruby/presym.h>
/*
@@ -111,6 +112,8 @@ mrb_ary_values_at(mrb_state *mrb, mrb_value self)
return mrb_get_values_at(mrb, self, RARRAY_LEN(self), argc, argv, ary_ref);
}
mrb_value mrb_ary_delete_at(mrb_state *mrb, mrb_value self);
/*
* call-seq:
* ary.slice!(index) -> obj or nil
@@ -137,7 +140,6 @@ mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self);
mrb_int i, j, k, len, alen;
mrb_value val;
mrb_value *ptr;
mrb_value ary;
@@ -146,21 +148,13 @@ mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
if (mrb_get_argc(mrb) == 1) {
mrb_value index = mrb_get_arg1(mrb);
switch (mrb_type(index)) {
case MRB_TT_RANGE:
if (mrb_type(index) == MRB_TT_RANGE) {
if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == MRB_RANGE_OK) {
goto delete_pos_len;
}
else {
return mrb_nil_value();
}
case MRB_TT_INTEGER:
val = mrb_funcall_id(mrb, self, MRB_SYM(delete_at), 1, index);
return val;
default:
val = mrb_funcall_id(mrb, self, MRB_SYM(delete_at), 1, index);
return val;
return mrb_nil_value();
}
return mrb_ary_delete_at(mrb, self);
}
mrb_get_args(mrb, "ii", &i, &len);
+154
View File
@@ -0,0 +1,154 @@
# fgmp
FGMP is a public domain implementation of a subset of the GNU gmp library with the same API.
WELCOME TO FGMP.
FGMP is a public domain implementation of a subset of the GNU gmp library
with the same API.
For instance, you can link the following trivial program with either
this code, or libgmp.a and get the same results.
``` C
#include <stdio.h>
#include "gmp.h"
main()
{
MP_INT a; MP_INT b; MP_INT c;
mpz_init_set_ui(&a,1); mpz_init_set_ui(&b,2); mpz_init(&c);
mpz_add(&c,&a,&b);
printf("\n%s\n", mpz_get_str(NULL,10,&c));
}
```
FGMP is really in the public domain. You can do whatever you want with
it.
I wrote FGMP so that we would all have access to a (truly free)
implementation of this subset of the API of GNU libgmp. I encourage
everyone to distribute this as widely as possible.
If you need more documentation, I suggest you look at the file
gmp.texi which is included with the GNU gmp library.
You can send me bug reports, implementations of missing functions, flames
and rants by Email.
Any submissions of new code to be integrated into fgmp must also be
placed in the public domain (For the particularly dense, you can
release a new fgmp yourself under different licensing terms. This
is a condition for including a submission in a release of FGMP that
I personally prepare).
Mark Henderson <markh@wimsey.bc.ca>
# This is the fifth BETA release. 1.0b5
I hearby place this file and all of FGMP in the public domain.
Thanks to Paul Rouse <par@r-cube.demon.co.uk> for changes to get fgmp
to work on a 286 MS-DOS compiler, the functions mpz_sqrt and
mpz_sqrtrem, plus other general bug fixes.
Thanks also to Erick Gallesio <eg@kaolin.unice.fr> for a fix
to mpz_init_set_str
Define B64 if your "long" type is 64 bits. Otherwise we assume 32
bit longs. (The 64 bit version hasn't been tested enough)
```
Platforms:
Linux 0.99 (gcc)
IBM RS6000/AIX 3.2 (IBM xlc compiler and gcc 2.3)
Sun OS 4.1, Sun 3/4
DEC Alpha OSF/1 (only lightly tested, 64 bit longs do make a difference,
thanks to DEC for providing access via axposf.pa.dec.com). Define B64
for this platform
MS-DOS 286 C compiler (see credits above)
```
# Some differences between gmp and fgmp
1. fgmp is considerably slower than gmp
2. fgmp does not implement the following:
all mpq_*
internal mpn_* functions
mpz_perfect_square_p
mpz_inp_raw, mpz_out_raw
mp_set_memory_functions, mpz_out_str, mpz_inp_str
3. fgmp implements the following in addition to the routines in GNU gmp.
`int mpz_jacobi(MP_INT *a, MP_INT *b)`
- finds the jacobi symbol (a/b)
4. mpz_sizeinbase often overestimates the exact value
5. To convert your gmp based program to fgmp (subject to the
above)
- recompile your source. Make sure to include the gmp.h file included
with fgmp rather than that included with gmp. (The point is to recompile
all files which include gmp.h)
- link with gmp.o instead of libgmp.a
Here's a complete sorted list of function implemented in fgmp:
```
_mpz_realloc
mpz_abs
mpz_add
mpz_add_ui
mpz_and
mpz_clear
mpz_cmp
mpz_cmp_si
mpz_cmp_ui
mpz_div
mpz_div_2exp
mpz_div_ui
mpz_divmod
mpz_divmod_ui
mpz_fac_ui
mpz_gcd
mpz_gcdext
mpz_get_si
mpz_get_str
mpz_get_ui
mpz_init
mpz_init_set
mpz_init_set_si
mpz_init_set_str
mpz_init_set_ui
mpz_jacobi
mpz_mdiv
mpz_mdiv_ui
mpz_mdivmod
mpz_mdivmod_ui
mpz_mmod
mpz_mmod_ui
mpz_mod
mpz_mod_2exp
mpz_mod_ui
mpz_mul
mpz_mul_2exp
mpz_mul_ui
mpz_neg
mpz_or
mpz_pow_ui
mpz_powm
mpz_powm_ui
mpz_probab_prime_p
mpz_random
mpz_random2
mpz_set
mpz_set_si
mpz_set_str
mpz_set_ui
mpz_size
mpz_sizeinbase
mpz_sqrt
mpz_sqrtrem
mpz_sub
mpz_sub_ui
mpz_xor
```
+5
View File
@@ -0,0 +1,5 @@
# Multi-precision Integer extension for mruby
This extension uses fgmp, which is a public domain implementation of a subset of the GNU gmp library by Mark Henderson <markh@wimsey.bc.ca>
But it's heavily modified to fit with mruby. You can get the original source code from <https://github.com/deischi/fgmp.git>
You can read the original README for fgmp in <README-fgmp.md>
File diff suppressed because it is too large Load Diff
+87
View File
@@ -0,0 +1,87 @@
/**
** @file mruby/bigint.h - Multi-precision, Integer
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_BIGINT_H
#define MRUBY_BIGINT_H
/*
* FREE GMP - a public domain implementation of a subset of the
* gmp library
*
* I hearby place the file in the public domain.
*
* Do whatever you want with this code. Change it. Sell it. Claim you
* wrote it.
* Bugs, complaints, flames, rants: please send email to
* Mark Henderson <markh@wimsey.bc.ca>
* I'm already aware that fgmp is considerably slower than gmp
*
* CREDITS:
* Paul Rouse <par@r-cube.demon.co.uk> - generic bug fixes, mpz_sqrt and
* mpz_sqrtrem, and modifications to get fgmp to compile on a system
* with int and long of different sizes (specifically MS-DOS,286 compiler)
* Also see the file "notes" included with the fgmp distribution, for
* more credits.
*
* VERSION 1.0 - beta 5
*/
#include <sys/types.h>
#if defined(MRB_32BIT) && defined(MRB_INT32)
/*
* The values below are for 32 bit machines (i.e. machines with a
* 32 bit long type)
* You'll need to change them, if you're using something else
* If DIGITBITS is odd, see the comment at the top of mpz_sqrtrem
*/
typedef int32_t mp_limb;
typedef uint32_t mp_ulimb;
#define LMAX 0x3fffffffL
#define LC 0xc0000000L
#define CMASK (LMAX+1)
#define HLMAX 0x7fffL
#define HCMASK (HLMAX + 1)
#define HIGH(x) (((x) & 0x3fff8000L) >> 15)
#define LOW(x) ((x) & 0x7fffL)
#else
/* 64 bit long type */
typedef int64_t mp_limb;
typedef uint64_t mp_ulimb;
#define LMAX 0x3fffffffffffffffLL
#define LC 0xc000000000000000LL
#define CMASK (LMAX+1)
#define HLMAX 0x7fffffffLL
#define HCMASK (HLMAX + 1)
#define HIGH(x) (((x) & 0x3fffffff80000000LL) >> 31)
#define LOW(x) ((x) & 0x7fffffffLL)
#endif
typedef struct _mpz_t {
mp_limb *p;
short sn;
size_t sz;
} mpz_t;
struct RBigint {
MRB_OBJECT_HEADER;
mpz_t mp;
};
#define RBIGINT(v) ((struct RBigint*)mrb_ptr(v))
#define iabs(x) ((x>0) ? (x) : (-x))
#define imax(x,y) ((x>y)?x:y)
#define LONGBITS (sizeof(mp_limb)*8)
#define DIGITBITS (LONGBITS-2)
#define HALFDIGITBITS ((LONGBITS-2)/2)
#define hd(x,i) (((size_t)(i)>=2*((x)->sz))? 0:(((i)%2) ? HIGH((x)->p[(i)/2]) \
: LOW((x)->p[(i)/2])))
#define dg(x,i) (((size_t)(i) < (x)->sz) ? ((x)->p)[i] : 0)
#define RBIGINT(v) ((struct RBigint*)mrb_ptr(v))
#endif /* MRUBY_BIGINT_H */
+10
View File
@@ -0,0 +1,10 @@
MRuby::Gem::Specification.new('mruby-bigint') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'Integer class extension to multiple-precision'
spec.build.defines << "MRB_USE_BIGINT"
spec.build.libmruby_core_objs << Dir.glob(File.join(__dir__, "core/**/*.c")).map { |fn|
objfile(fn.relative_path_from(__dir__).pathmap("#{spec.build_dir}/%X"))
}
end
+23
View File
@@ -0,0 +1,23 @@
assert 'Bigint basic' do
n = 1<<65
assert_equal 36893488147419103232, n
assert_equal 36893488147419104229, n+997
assert_equal 36893488147419102235, n-997
assert_equal 36782807682976845922304, n*997
assert_equal 37004501652376231, n.div(997)
end
assert 'Bigint to_s' do
n = 1197857166996989179607278372168909873645893814254642585755536286462800958278984531968
assert_equal n, "11978_571669_96989179607278372168909873645893814254642585755536286462800958278984531968".to_i
assert_equal(-n, "-11978_571669_96989179607278372168909873645893814254642585755536286462800958278984531968".to_i)
n = 0x1197857166996989179607278372168909873645893814254642585755536286462800958278984531968
assert_equal n, "1197857166996989179607278372168909873645893814254642585755536286462800958278984531968".to_i(16)
end
assert 'Bigint pow' do
n = 18446744073709551616
assert_equal n, 2 ** 64
assert_equal n, 1 << 64
assert_equal 2, n >> 63
end
@@ -12,6 +12,7 @@
#include <mruby/class.h>
#include <mruby/proc.h>
#include <mruby/variable.h>
#include <mruby/internal.h>
#include "mrdberror.h"
#include "apibreak.h"
#include "apistring.h"
@@ -20,8 +21,6 @@
#define MRB_DEBUG_BP_FILE_OK (0x0001)
#define MRB_DEBUG_BP_LINENO_OK (0x0002)
uint32_t mrb_packed_int_decode(uint8_t *p, uint8_t **newpos);
static uint16_t
check_lineno(mrb_irep_debug_info_file *info_file, uint16_t lineno)
{
@@ -47,8 +46,8 @@ check_lineno(mrb_irep_debug_info_file *info_file, uint16_t lineno)
case mrb_debug_line_packed_map:
{
uint8_t *p = info_file->lines.packed_map;
uint8_t *pend = p + count;
const uint8_t *p = info_file->lines.packed_map;
const uint8_t *pend = p + count;
uint32_t line = 0;
while (p < pend) {
mrb_packed_int_decode(p, &p);
@@ -14,6 +14,7 @@
#include <mruby/opcode.h>
#include <mruby/variable.h>
#include <mruby/proc.h>
#include <mruby/internal.h>
#include "mrdb.h"
#include "apibreak.h"
+9 -29
View File
@@ -9,6 +9,7 @@
#include <mruby/compile.h>
#include <mruby/dump.h>
#include <mruby/proc.h>
#include <mruby/internal.h>
#define RITEBIN_EXT ".mrb"
#define C_EXT ".c"
@@ -25,7 +26,8 @@ struct mrbc_args {
mrb_bool verbose : 1;
mrb_bool remove_lv : 1;
mrb_bool no_ext_ops : 1;
uint8_t flags : 4;
mrb_bool no_optimize : 1;
uint8_t flags : 2;
};
static void
@@ -42,6 +44,7 @@ usage(const char *name)
"-s define <symbol> as static variable",
"--remove-lv remove local variables",
"--no-ext-ops prohibit using OP_EXTs",
"--no-optimize disable peephole optimization",
"--verbose run at verbose mode",
"--version print the version",
"--copyright print the copyright",
@@ -169,6 +172,10 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
args->no_ext_ops = TRUE;
break;
}
else if (strcmp(argv[i] + 2, "no-optimize") == 0) {
args->no_optimize = TRUE;
break;
}
return -1;
default:
return i;
@@ -224,6 +231,7 @@ load_file(mrb_state *mrb, struct mrbc_args *args)
c->dump_result = TRUE;
c->no_exec = TRUE;
c->no_ext_ops = args->no_ext_ops;
c->no_optimize = args->no_optimize;
if (input[0] == '-' && input[1] == '\0') {
infile = stdin;
}
@@ -366,31 +374,3 @@ mrb_final_mrbgems(mrb_state *mrb)
{
}
#endif
#ifdef MRB_USE_COMPLEX
mrb_value mrb_complex_to_i(mrb_state *mrb, mrb_value comp)
{
/* dummy method */
return mrb_nil_value();
}
mrb_value mrb_complex_to_f(mrb_state *mrb, mrb_value comp)
{
/* dummy method */
return mrb_nil_value();
}
#endif
#ifdef MRB_USE_RATIONAL
mrb_value
mrb_rational_to_i(mrb_state *mrb, mrb_value rat)
{
/* dummy method */
return mrb_nil_value();
}
mrb_value
mrb_rational_to_f(mrb_state *mrb, mrb_value rat)
{
/* dummy method */
return mrb_nil_value();
}
#endif
+68
View File
@@ -0,0 +1,68 @@
#include <mruby.h>
/*
functions defined in mrbgems referenced from the core should be listed here
to avoid link errors, since mrbc does not link any mrbgem ignoring configuration.
*/
#ifdef MRB_USE_COMPLEX
mrb_value mrb_complex_new(mrb_state *mrb, mrb_float x, mrb_float y)
{
return mrb_nil_value();
}
mrb_value mrb_complex_add(mrb_state *mrb, mrb_value x, mrb_value y)
{
return mrb_nil_value();
}
mrb_value mrb_complex_sub(mrb_state *mrb, mrb_value x, mrb_value y)
{
return mrb_nil_value();
}
mrb_value mrb_complex_mul(mrb_state *mrb, mrb_value x, mrb_value y)
{
return mrb_nil_value();
}
mrb_value mrb_complex_div(mrb_state *mrb, mrb_value x, mrb_value y)
{
return mrb_nil_value();
}
mrb_value mrb_complex_to_i(mrb_state *mrb, mrb_value x)
{
return mrb_nil_value();
}
mrb_value mrb_complex_to_f(mrb_state *mrb, mrb_value x)
{
return mrb_nil_value();
}
#endif
#ifdef MRB_USE_RATIONAL
mrb_value mrb_rational_new(mrb_state *mrb, mrb_int x, mrb_int y)
{
return mrb_nil_value();
}
mrb_value mrb_rational_add(mrb_state *mrb, mrb_value x, mrb_value y)
{
return mrb_nil_value();
}
mrb_value mrb_rational_sub(mrb_state *mrb, mrb_value x, mrb_value y)
{
return mrb_nil_value();
}
mrb_value mrb_rational_mul(mrb_state *mrb, mrb_value x, mrb_value y)
{
return mrb_nil_value();
}
mrb_value mrb_rational_div(mrb_state *mrb, mrb_value x, mrb_value y)
{
return mrb_nil_value();
}
mrb_value mrb_rational_to_i(mrb_state *mrb, mrb_value x)
{
return mrb_nil_value();
}
mrb_value mrb_rational_to_f(mrb_state *mrb, mrb_value x)
{
return mrb_nil_value();
}
#endif
+12 -2
View File
@@ -63,6 +63,16 @@ usage(const char *name)
printf(" %s\n", *p++);
}
static mrb_bool
mrb_extension_p(const char *path)
{
const char *e = strrchr(path, '.');
if (e && e[1] == 'm' && e[2] == 'r' && e[3] == 'b' && e[4] == '\0') {
return TRUE;
}
return FALSE;
}
static void
options_init(struct options *opts, int argc, char **argv)
{
@@ -323,7 +333,7 @@ main(int argc, char **argv)
return EXIT_FAILURE;
}
mrbc_filename(mrb, c, args.libv[i]);
if (args.mrbfile) {
if (mrb_extension_p(args.libv[i])) {
v = mrb_load_irep_file_cxt(mrb, lfp, c);
}
else {
@@ -340,7 +350,7 @@ main(int argc, char **argv)
mrbc_filename(mrb, c, cmdline);
/* Load program */
if (args.mrbfile) {
if (args.mrbfile || mrb_extension_p(cmdline)) {
v = mrb_load_irep_file_cxt(mrb, args.rfp, c);
}
else if (args.rfp) {
@@ -8,6 +8,7 @@
#include <string.h>
#include <mruby/irep.h>
#include <mruby/dump.h>
#include <mruby/internal.h>
struct strip_args {
int argc_start;
+1 -1
View File
@@ -45,7 +45,7 @@ binding_eval_error_check(mrb_state *mrb, struct mrb_parser_state *p, const char
struct expand_lvspace {
mrb_irep *irep;
struct REnv *env;
size_t numvar;
int numvar;
mrb_sym syms[LV_BUFFERS];
};
+2 -1
View File
@@ -1,9 +1,10 @@
#include <mruby.h>
#include <mruby/presym.h>
static mrb_value
binding_in_c(mrb_state *mrb, mrb_value self)
{
return mrb_funcall_argv(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "binding"), 0, NULL);
return mrb_funcall_argv(mrb, mrb_obj_value(mrb->object_class), MRB_SYM(binding), 0, NULL);
}
void
+55
View File
@@ -1,6 +1,7 @@
#include "mruby.h"
#include "mruby/class.h"
#include "mruby/string.h"
#include "mruby/array.h"
#include "mruby/proc.h"
static mrb_value
@@ -56,6 +57,57 @@ mrb_mod_module_exec(mrb_state *mrb, mrb_value self)
return mrb_yield_cont(mrb, blk, self, argc, argv);
}
struct subclass_args {
struct RClass *c;
mrb_value ary;
};
static int
add_subclasses(mrb_state *mrb, struct RBasic *obj, void *data)
{
struct subclass_args *args = (struct subclass_args*)data;
if (obj->tt == MRB_TT_CLASS) {
struct RClass *c = (struct RClass*)obj;
if (mrb_class_real(c->super) == args->c) {
mrb_ary_push(mrb, args->ary, mrb_obj_value(obj));
}
}
return MRB_EACH_OBJ_OK;
}
/*
* call-seq:
* subclasses -> array
*
* Returns an array of classes where the receiver is the
* direct superclass of the class, excluding singleton classes.
* The order of the returned array is not defined.
*
* class A; end
* class B < A; end
* class C < B; end
* class D < A; end
*
* A.subclasses #=> [D, B]
* B.subclasses #=> [C]
* C.subclasses #=> []
*/
static mrb_value
mrb_class_subclasses(mrb_state *mrb, mrb_value self)
{
struct RClass *c;
mrb_value ary;
c = mrb_class_ptr(self);
ary = mrb_ary_new(mrb);
if (c->flags & MRB_FL_CLASS_IS_INHERITED) {
struct subclass_args arg = {c, ary};
mrb_objspace_each_objects(mrb, add_subclasses, &arg);
}
return ary;
}
void
mrb_mruby_class_ext_gem_init(mrb_state *mrb)
{
@@ -65,6 +117,9 @@ mrb_mruby_class_ext_gem_init(mrb_state *mrb)
mrb_define_method(mrb, mod, "singleton_class?", mrb_mod_singleton_class_p, MRB_ARGS_NONE());
mrb_define_method(mrb, mod, "module_exec", mrb_mod_module_exec, MRB_ARGS_ANY()|MRB_ARGS_BLOCK());
mrb_define_method(mrb, mod, "class_exec", mrb_mod_module_exec, MRB_ARGS_ANY()|MRB_ARGS_BLOCK());
struct RClass *cls = mrb->module_class;
mrb_define_method(mrb, cls, "subclasses", mrb_class_subclasses, MRB_ARGS_NONE());
}
void
+13
View File
@@ -0,0 +1,13 @@
assert 'Class#subclasses' do
a = Class.new
b = Class.new(a)
c = Class.new(b)
d = Class.new(a)
a_sub = a.subclasses
assert_equal(2, a_sub.size)
assert_true(a_sub.include?(b))
assert_true(a_sub.include?(d))
assert_equal([c], b.subclasses)
assert_equal([], c.subclasses)
end
+329 -200
View File
@@ -18,6 +18,7 @@
#include <mruby/throw.h>
#include <ctype.h>
#include <string.h>
#include <mruby/internal.h>
#ifndef MRB_CODEGEN_LEVEL_MAX
#define MRB_CODEGEN_LEVEL_MAX 256
@@ -57,7 +58,7 @@ typedef struct scope {
uint32_t pc;
uint32_t lastpc;
uint32_t lastlabel;
size_t ainfo:15;
uint16_t ainfo:15;
mrb_bool mscope:1;
struct loopinfo *loop;
@@ -101,8 +102,8 @@ static void loop_pop(codegen_scope *s, int val);
static int catch_handler_new(codegen_scope *s);
static void catch_handler_set(codegen_scope *s, int ent, enum mrb_catch_type type, uint32_t begin, uint32_t end, uint32_t target);
static void gen_assignment(codegen_scope *s, node *tree, int sp, int val);
static void gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val);
static void gen_assignment(codegen_scope *s, node *tree, node *rhs, int sp, int val);
static void gen_massignment(codegen_scope *s, node *tree, int sp, int val);
static void codegen(codegen_scope *s, node *tree, int val);
static void raise_error(codegen_scope *s, const char *msg);
@@ -286,10 +287,10 @@ genop_2(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
}
static void
genop_3(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b, uint8_t c)
genop_3(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b, uint16_t c)
{
genop_2(s, i, a, b);
gen_B(s, c);
gen_B(s, (uint8_t)c);
}
static void
@@ -594,9 +595,22 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
switch (data.insn) {
case OP_MOVE:
if (dst == src) return; /* remove useless MOVE */
if (data.b == dst && data.a == src) /* skip swapping MOVE */
if (dst == src) return; /* remove useless MOVE */
if (data.a == src) {
if (data.b == dst) /* skip swapping MOVE */
return;
if (data.a < s->nlocals) goto normal;
rewind_pc(s);
s->lastpc = addr_pc(s, mrb_prev_pc(s, data.addr));
gen_move(s, dst, data.b, FALSE);
return;
}
if (dst == data.a) { /* skip overwritten move */
rewind_pc(s);
s->lastpc = addr_pc(s, mrb_prev_pc(s, data.addr));
gen_move(s, dst, src, FALSE);
return;
}
goto normal;
case OP_LOADNIL: case OP_LOADSELF: case OP_LOADT: case OP_LOADF:
case OP_LOADI__1:
@@ -606,7 +620,7 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
rewind_pc(s);
genop_1(s, data.insn, dst);
return;
case OP_HASH: case OP_ARRAY:
case OP_HASH:
if (data.b != 0) goto normal;
/* fall through */
case OP_LOADI: case OP_LOADINEG:
@@ -631,6 +645,19 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
genop_2SS(s, data.insn, dst, i);
}
return;
case OP_ARRAY:
if (data.a != src || data.a < s->nlocals || data.a < dst) goto normal;
rewind_pc(s);
if (data.b == 0 || dst == data.a)
genop_2(s, OP_ARRAY, dst, 0);
else
genop_3(s, OP_ARRAY2, dst, data.a, data.b);
return;
case OP_ARRAY2:
if (data.a != src || data.a < s->nlocals || data.a < dst) goto normal;
rewind_pc(s);
genop_3(s, OP_ARRAY2, dst, data.b, data.c);
return;
case OP_AREF:
case OP_GETUPVAR:
if (data.a != src || data.a < s->nlocals) goto normal;
@@ -831,13 +858,14 @@ gen_muldiv(codegen_scope *s, uint8_t op, uint16_t dst)
goto normal;
}
struct mrb_insn_data data0 = mrb_decode_insn(mrb_prev_pc(s, data.addr));
if (!get_int_operand(s, &data0, &n0) || n == 0) {
if (!get_int_operand(s, &data0, &n0)) {
goto normal;
}
if (op == OP_MUL) {
if (mrb_int_mul_overflow(n0, n, &n)) goto normal;
}
else { /* OP_DIV */
if (n == 0) goto normal;
if (n0 == MRB_INT_MIN && n == -1) goto normal;
n = mrb_div_int(s->mrb, n0, n);
}
@@ -961,6 +989,17 @@ pop_n_(codegen_scope *s, int n)
#define pop_n(n) pop_n_(s,n)
#define cursp() (s->sp)
static mrb_pool_value*
lit_pool_extend(codegen_scope *s)
{
if (s->irep->plen == s->pcapa) {
s->pcapa *= 2;
s->pool = (mrb_pool_value*)codegen_realloc(s, s->pool, sizeof(mrb_pool_value)*s->pcapa);
}
return &s->pool[s->irep->plen++];
}
static int
new_litbn(codegen_scope *s, const char *p, int base, mrb_bool neg)
{
@@ -981,13 +1020,8 @@ new_litbn(codegen_scope *s, const char *p, int base, mrb_bool neg)
return i;
}
if (s->irep->plen == s->pcapa) {
s->pcapa *= 2;
s->pool = (mrb_pool_value*)codegen_realloc(s, s->pool, sizeof(mrb_pool_value)*s->pcapa);
}
pv = lit_pool_extend(s);
pv = &s->pool[s->irep->plen];
i = s->irep->plen++;
{
char *buf;
pv->tt = IREP_TT_BIGINT;
@@ -1003,104 +1037,100 @@ new_litbn(codegen_scope *s, const char *p, int base, mrb_bool neg)
}
static int
new_lit(codegen_scope *s, mrb_value val)
new_lit_str(codegen_scope *s, const char *str, mrb_int len)
{
int i;
mrb_pool_value *pv;
switch (mrb_type(val)) {
case MRB_TT_STRING:
for (i=0; i<s->irep->plen; i++) {
mrb_int len;
pv = &s->pool[i];
if (pv->tt & IREP_TT_NFLAG) continue;
len = pv->tt>>2;
if (RSTRING_LEN(val) != len) continue;
if (memcmp(pv->u.str, RSTRING_PTR(val), len) == 0)
return i;
}
break;
#ifndef MRB_NO_FLOAT
case MRB_TT_FLOAT:
for (i=0; i<s->irep->plen; i++) {
mrb_float f1, f2;
pv = &s->pool[i];
if (pv->tt != IREP_TT_FLOAT) continue;
pv = &s->pool[i];
f1 = pv->u.f;
f2 = mrb_float(val);
if (f1 == f2 && !signbit(f1) == !signbit(f2)) return i;
}
break;
#endif
case MRB_TT_INTEGER:
for (i=0; i<s->irep->plen; i++) {
mrb_int v = mrb_integer(val);
pv = &s->pool[i];
if (pv->tt == IREP_TT_INT32) {
if (v == pv->u.i32) return i;
}
#ifdef MRB_64BIT
else if (pv->tt == IREP_TT_INT64) {
if (v == pv->u.i64) return i;
}
continue;
#endif
}
break;
default:
/* should not happen */
return 0;
for (i=0; i<s->irep->plen; i++) {
pv = &s->pool[i];
if (pv->tt & IREP_TT_NFLAG) continue;
mrb_int plen = pv->tt>>2;
if (len != plen) continue;
if (memcmp(pv->u.str, str, plen) == 0)
return i;
}
if (s->irep->plen == s->pcapa) {
s->pcapa *= 2;
s->pool = (mrb_pool_value*)codegen_realloc(s, s->pool, sizeof(mrb_pool_value)*s->pcapa);
pv = lit_pool_extend(s);
if (mrb_ro_data_p(str)) {
pv->tt = (uint32_t)(len<<2) | IREP_TT_SSTR;
pv->u.str = str;
}
else {
char *p;
pv->tt = (uint32_t)(len<<2) | IREP_TT_STR;
p = (char*)codegen_realloc(s, NULL, len+1);
memcpy(p, str, len);
p[len] = '\0';
pv->u.str = p;
}
pv = &s->pool[s->irep->plen];
i = s->irep->plen++;
switch (mrb_type(val)) {
case MRB_TT_STRING:
if (RSTR_NOFREE_P(RSTRING(val))) {
pv->tt = (uint32_t)(RSTRING_LEN(val)<<2) | IREP_TT_SSTR;
pv->u.str = RSTRING_PTR(val);
}
else {
char *p;
mrb_int len = RSTRING_LEN(val);
pv->tt = (uint32_t)(len<<2) | IREP_TT_STR;
p = (char*)codegen_realloc(s, NULL, len+1);
memcpy(p, RSTRING_PTR(val), len);
p[len] = '\0';
pv->u.str = p;
}
break;
#ifndef MRB_NO_FLOAT
case MRB_TT_FLOAT:
pv->tt = IREP_TT_FLOAT;
pv->u.f = mrb_float(val);
break;
#endif
case MRB_TT_INTEGER:
#ifdef MRB_INT64
pv->tt = IREP_TT_INT64;
pv->u.i64 = mrb_integer(val);
#else
pv->tt = IREP_TT_INT32;
pv->u.i32 = mrb_integer(val);
#endif
break;
default:
/* should not happen */
break;
}
return i;
}
static int
new_lit_cstr(codegen_scope *s, const char *str)
{
return new_lit_str(s, str, (mrb_int)strlen(str));
}
static int
new_lit_int(codegen_scope *s, mrb_int num)
{
int i;
mrb_pool_value *pv;
for (i=0; i<s->irep->plen; i++) {
pv = &s->pool[i];
if (pv->tt == IREP_TT_INT32) {
if (num == pv->u.i32) return i;
}
#ifdef MRB_64BIT
else if (pv->tt == IREP_TT_INT64) {
if (num == pv->u.i64) return i;
}
continue;
#endif
}
pv = lit_pool_extend(s);
#ifdef MRB_INT64
pv->tt = IREP_TT_INT64;
pv->u.i64 = num;
#else
pv->tt = IREP_TT_INT32;
pv->u.i32 = num;
#endif
return i;
}
#ifndef MRB_NO_FLOAT
static int
new_lit_float(codegen_scope *s, mrb_float num)
{
int i;
mrb_pool_value *pv;
for (i=0; i<s->irep->plen; i++) {
mrb_float f;
pv = &s->pool[i];
if (pv->tt != IREP_TT_FLOAT) continue;
f = pv->u.f;
if (f == num && !signbit(f) == !signbit(num)) return i;
}
pv = lit_pool_extend(s);
pv->tt = IREP_TT_FLOAT;
pv->u.f = num;
return i;
}
#endif
static int
new_sym(codegen_scope *s, mrb_sym sym)
{
@@ -1153,7 +1183,7 @@ gen_int(codegen_scope *s, uint16_t dst, mrb_int i)
else if (i <= INT32_MAX) genop_2SS(s, OP_LOADI32, dst, (uint32_t)i);
else {
int_lit:
genop_2(s, OP_LOADL, dst, new_lit(s, mrb_int_value(s->mrb, i)));
genop_2(s, OP_LOADL, dst, new_lit_int(s, i));
}
}
@@ -1275,10 +1305,10 @@ for_body(codegen_scope *s, node *tree)
n2 = tree->car;
genop_W(s, OP_ENTER, 0x40000);
if (n2->car && !n2->car->cdr && !n2->cdr) {
gen_assignment(s, n2->car->car, 1, NOVAL);
gen_assignment(s, n2->car->car, NULL, 1, NOVAL);
}
else {
gen_vmassignment(s, n2, 1, VAL);
gen_massignment(s, n2, 1, VAL);
}
/* construct loop */
lp = loop_push(s, LOOP_FOR);
@@ -1444,7 +1474,7 @@ lambda_body(codegen_scope *s, node *tree, int blk)
pos = 1;
while (n) {
if (nint(n->car->car) == NODE_MASGN) {
gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
gen_massignment(s, n->car->cdr->car, pos, NOVAL);
}
pos++;
n = n->cdr;
@@ -1456,7 +1486,7 @@ lambda_body(codegen_scope *s, node *tree, int blk)
pos = ma+oa+ra+1;
while (n) {
if (nint(n->car->car) == NODE_MASGN) {
gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
gen_massignment(s, n->car->cdr->car, pos, NOVAL);
}
pos++;
n = n->cdr;
@@ -1530,7 +1560,7 @@ attrsym(codegen_scope *s, mrb_sym a)
#define GEN_VAL_STACK_MAX 99
static int
gen_values(codegen_scope *s, node *t, int val, int extra, int limit)
gen_values(codegen_scope *s, node *t, int val, int limit)
{
int n = 0;
int first = 1;
@@ -1551,7 +1581,7 @@ gen_values(codegen_scope *s, node *t, int val, int extra, int limit)
while (t) {
int is_splat = nint(t->car->car) == NODE_SPLAT;
if (is_splat || n+extra >= limit-1 || cursp() >= slimit) { /* flush stack */
if (is_splat || cursp() >= slimit) { /* flush stack */
pop_n(n);
if (first) {
if (n == 0) {
@@ -1590,6 +1620,11 @@ gen_values(codegen_scope *s, node *t, int val, int extra, int limit)
}
return -1; /* variable length */
}
else if (n > limit) {
pop_n(n);
genop_2(s, OP_ARRAY, cursp(), n);
return -1;
}
return n;
}
@@ -1600,10 +1635,16 @@ gen_hash(codegen_scope *s, node *tree, int val, int limit)
if (cursp() >= GEN_LIT_ARY_MAX) slimit = INT16_MAX;
int len = 0;
mrb_bool update = FALSE;
mrb_bool first = TRUE;
while (tree) {
if (nint(tree->car->car->car) == NODE_KW_REST_ARGS) {
if (val && len > 0) {
if (val && first) {
genop_2(s, OP_HASH, cursp(), 0);
push();
update = TRUE;
}
else if (val && len > 0) {
pop_n(len*2);
if (!update) {
genop_2(s, OP_HASH, cursp(), len);
@@ -1642,6 +1683,13 @@ gen_hash(codegen_scope *s, node *tree, int val, int limit)
update = TRUE;
len = 0;
}
first = FALSE;
}
if (val && len > limit) {
pop_n(len*2);
genop_2(s, OP_HASH, cursp(), len);
push();
return -1;
}
if (update) {
if (val && len > 0) {
@@ -1655,10 +1703,10 @@ gen_hash(codegen_scope *s, node *tree, int val, int limit)
}
static void
gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
gen_call(codegen_scope *s, node *tree, int val, int safe)
{
mrb_sym sym = name ? name : nsym(tree->cdr->car);
int skip = 0, n = 0, nk = 0, noop = 0, noself = 0, blk = 0, sp_save = cursp();
mrb_sym sym = nsym(tree->cdr->car);
int skip = 0, n = 0, nk = 0, noop = no_optimize(s), noself = 0, blk = 0, sp_save = cursp();
if (!tree->car) {
noself = noop = 1;
@@ -1675,7 +1723,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
tree = tree->cdr->cdr->car;
if (tree) {
if (tree->car) { /* positional arguments */
n = gen_values(s, tree->car, VAL, sp?1:0, 14);
n = gen_values(s, tree->car, VAL, 14);
if (n < 0) { /* variable length */
noop = 1; /* not operator */
n = 15;
@@ -1688,32 +1736,6 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
if (nk < 0) nk = 15;
}
}
if (sp) { /* last argument pushed (attr=, []=) */
/* pack keyword arguments */
if (nk > 0 && nk < 15) {
pop_n(nk*2);
genop_2(s, OP_HASH, cursp(), nk);
push();
}
if (n == CALL_MAXARGS) {
if (nk > 0) {
pop(); pop();
genop_2(s, OP_ARYPUSH, cursp(), 1);
push();
}
gen_move(s, cursp(), sp, 0);
pop();
genop_2(s, OP_ARYPUSH, cursp(), 1);
push();
}
else {
gen_move(s, cursp(), sp, 0);
push();
if (nk > 0) n++;
n++;
}
nk = 0;
}
if (tree && tree->cdr && tree->cdr->cdr) {
codegen(s, tree->cdr->cdr, VAL);
pop();
@@ -1773,11 +1795,42 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
}
static void
gen_assignment(codegen_scope *s, node *tree, int sp, int val)
gen_assignment(codegen_scope *s, node *tree, node *rhs, int sp, int val)
{
int idx;
int type = nint(tree->car);
switch (type) {
case NODE_GVAR:
case NODE_ARG:
case NODE_LVAR:
case NODE_IVAR:
case NODE_CVAR:
case NODE_CONST:
case NODE_NIL:
case NODE_MASGN:
if (rhs) {
codegen(s, rhs, VAL);
pop();
sp = cursp();
}
break;
case NODE_COLON2:
case NODE_CALL:
case NODE_SCALL:
/* keep evaluation order */
break;
case NODE_NVAR:
codegen_error(s, "Can't assign to numbered parameter");
break;
default:
codegen_error(s, "unknown lhs");
break;
}
tree = tree->cdr;
switch (type) {
case NODE_GVAR:
@@ -1796,10 +1849,6 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
gen_setupvar(s, sp, nsym(tree));
}
break;
case NODE_NVAR:
idx = nint(tree);
codegen_error(s, "Can't assign to numbered parameter");
break;
case NODE_IVAR:
gen_setxv(s, OP_SETIV, sp, nsym(tree), val);
break;
@@ -1810,9 +1859,16 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
gen_setxv(s, OP_SETCONST, sp, nsym(tree), val);
break;
case NODE_COLON2:
gen_move(s, cursp(), sp, 0);
if (sp) {
gen_move(s, cursp(), sp, 0);
}
sp = cursp();
push();
codegen(s, tree->car, VAL);
if (rhs) {
codegen(s, rhs, VAL); pop();
gen_move(s, sp, cursp(), 0);
}
pop_n(2);
idx = new_sym(s, nsym(tree->cdr));
genop_2(s, OP_SETMCNST, sp, idx);
@@ -1820,17 +1876,91 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
case NODE_CALL:
case NODE_SCALL:
push();
gen_call(s, tree, attrsym(s, nsym(tree->cdr->car)), sp, NOVAL,
type == NODE_SCALL);
pop();
if (val && cursp() != sp) {
gen_move(s, cursp(), sp, 0);
{
int noself = 0, safe = (type == NODE_SCALL), skip = 0, top, call, n = 0;
mrb_sym mid = nsym(tree->cdr->car);
top = cursp();
if (val || sp == cursp()) {
push(); /* room for retval */
}
call = cursp();
if (!tree->car) {
noself = 1;
push();
}
else {
codegen(s, tree->car, VAL); /* receiver */
}
if (safe) {
int recv = cursp()-1;
gen_move(s, cursp(), recv, 1);
skip = genjmp2_0(s, OP_JMPNIL, cursp(), val);
}
tree = tree->cdr->cdr->car;
if (tree) {
if (tree->car) { /* positional arguments */
n = gen_values(s, tree->car, VAL, (tree->cdr->car)?13:14);
if (n < 0) { /* variable length */
n = 15;
push();
}
}
if (tree->cdr->car) { /* keyword arguments */
if (n == 13 || n == 14) {
pop_n(n);
genop_2(s, OP_ARRAY, cursp(), n);
push();
n = 15;
}
gen_hash(s, tree->cdr->car->cdr, VAL, 0);
if (n < 14) {
n++;
}
else {
pop_n(2);
genop_2(s, OP_ARYPUSH, cursp(), 1);
}
push();
}
}
if (rhs) {
codegen(s, rhs, VAL);
pop();
}
else {
gen_move(s, cursp(), sp, 0);
}
if (val) {
gen_move(s, top, cursp(), 1);
}
if (n < 15) {
n++;
if (n == 15) {
pop_n(14);
genop_2(s, OP_ARRAY, cursp(), 15);
}
}
else {
pop();
genop_2(s, OP_ARYPUSH, cursp(), 1);
}
s->sp = call;
if (mid == MRB_OPSYM_2(s->mrb, aref) && n == 2) {
genop_1(s, OP_SETIDX, cursp());
}
else {
genop_3(s, noself ? OP_SSEND : OP_SEND, cursp(), new_sym(s, attrsym(s, mid)), n);
}
if (safe) {
dispatch(s, skip);
}
s->sp = top;
}
break;
case NODE_MASGN:
gen_vmassignment(s, tree->car, sp, val);
gen_massignment(s, tree->car, sp, val);
break;
/* splat without assignment */
@@ -1845,7 +1975,7 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
}
static void
gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
gen_massignment(codegen_scope *s, node *tree, int rhs, int val)
{
int n = 0, post = 0;
node *t, *p;
@@ -1858,7 +1988,7 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
genop_3(s, OP_AREF, sp, rhs, n);
push();
gen_assignment(s, t->car, sp, NOVAL);
gen_assignment(s, t->car, NULL, sp, NOVAL);
pop();
n++;
t = t->cdr;
@@ -1879,12 +2009,12 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
genop_3(s, OP_APOST, cursp(), n, post);
n = 1;
if (t->car && t->car != (node*)-1) { /* rest */
gen_assignment(s, t->car, cursp(), NOVAL);
gen_assignment(s, t->car, NULL, cursp(), NOVAL);
}
if (t->cdr && t->cdr->car) {
t = t->cdr->car;
while (t) {
gen_assignment(s, t->car, cursp()+n, NOVAL);
gen_assignment(s, t->car, NULL, cursp()+n, NOVAL);
t = t->cdr;
n++;
}
@@ -1989,7 +2119,7 @@ gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
static void
raise_error(codegen_scope *s, const char *msg)
{
int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg));
int idx = new_lit_cstr(s, msg);
genop_1(s, OP_ERR, idx);
}
@@ -2204,7 +2334,7 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
if (n3->cdr->car) {
gen_assignment(s, n3->cdr->car, exc, NOVAL);
gen_assignment(s, n3->cdr->car, NULL, exc, NOVAL);
}
if (n3->cdr->cdr->car) {
codegen(s, n3->cdr->cdr->car, val);
@@ -2509,10 +2639,10 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_FCALL:
case NODE_CALL:
gen_call(s, tree, 0, 0, val, 0);
gen_call(s, tree, val, 0);
break;
case NODE_SCALL:
gen_call(s, tree, 0, 0, val, 1);
gen_call(s, tree, val, 1);
break;
case NODE_DOT2:
@@ -2560,7 +2690,7 @@ codegen(codegen_scope *s, node *tree, int val)
{
int n;
n = gen_values(s, tree, val, 0, 0);
n = gen_values(s, tree, val, 0);
if (val) {
if (n >= 0) {
pop_n(n);
@@ -2588,9 +2718,7 @@ codegen(codegen_scope *s, node *tree, int val)
break;
case NODE_ASGN:
codegen(s, tree->cdr, VAL);
pop();
gen_assignment(s, tree->car, cursp(), val);
gen_assignment(s, tree->car, tree->cdr, 0, val);
break;
case NODE_MASGN:
@@ -2613,12 +2741,12 @@ codegen(codegen_scope *s, node *tree, int val)
n = 0;
while (t) {
if (n < len) {
gen_assignment(s, t->car, rhs+n, NOVAL);
gen_assignment(s, t->car, NULL, rhs+n, NOVAL);
n++;
}
else {
genop_1(s, OP_LOADNIL, rhs+n);
gen_assignment(s, t->car, rhs+n, NOVAL);
gen_assignment(s, t->car, NULL, rhs+n, NOVAL);
}
t = t->cdr;
}
@@ -2641,14 +2769,25 @@ codegen(codegen_scope *s, node *tree, int val)
else {
rn = len - post - n;
}
genop_3(s, OP_ARRAY2, cursp(), rhs+n, rn);
gen_assignment(s, t->car, cursp(), NOVAL);
if (cursp() == rhs+n) {
genop_2(s, OP_ARRAY, cursp(), rn);
}
else {
genop_3(s, OP_ARRAY2, cursp(), rhs+n, rn);
}
gen_assignment(s, t->car, NULL, cursp(), NOVAL);
n += rn;
}
if (t->cdr && t->cdr->car) {
t = t->cdr->car;
while (n<len) {
gen_assignment(s, t->car, rhs+n, NOVAL);
while (t) {
if (n<len) {
gen_assignment(s, t->car, NULL, rhs+n, NOVAL);
}
else {
genop_1(s, OP_LOADNIL, cursp());
gen_assignment(s, t->car, NULL, cursp(), NOVAL);
}
t = t->cdr;
n++;
}
@@ -2663,7 +2802,7 @@ codegen(codegen_scope *s, node *tree, int val)
else {
/* variable rhs */
codegen(s, t, VAL);
gen_vmassignment(s, tree->car, rhs, val);
gen_massignment(s, tree->car, rhs, val);
if (!val) {
pop();
}
@@ -2713,7 +2852,7 @@ codegen(codegen_scope *s, node *tree, int val)
idx = new_sym(s, nsym(n->cdr->car));
base = cursp()-1;
if (n->cdr->cdr->car) {
nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 1, 14);
nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 13);
if (nargs >= 0) {
callargs = nargs;
}
@@ -2769,7 +2908,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop_3(s, OP_SEND, cursp(), idx, callargs);
}
else {
gen_assignment(s, tree->car, cursp(), val);
gen_assignment(s, tree->car, NULL, cursp(), val);
}
dispatch(s, pos);
goto exit;
@@ -2807,7 +2946,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop_3(s, OP_SEND, cursp(), idx, 1);
}
if (callargs < 0) {
gen_assignment(s, tree->car, cursp(), val);
gen_assignment(s, tree->car, NULL, cursp(), val);
}
else {
if (val && vsp >= 0) {
@@ -2843,7 +2982,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (tree) {
node *args = tree->car;
if (args) {
st = n = gen_values(s, args, VAL, 0, 14);
st = n = gen_values(s, args, VAL, 14);
if (n < 0) {
st = 1; n = 15;
push();
@@ -2884,7 +3023,7 @@ codegen(codegen_scope *s, node *tree, int val)
{
codegen_scope *s2 = s;
int lv = 0;
size_t ainfo = 0;
uint16_t ainfo = 0;
int n = CALL_MAXARGS;
int sp = cursp();
@@ -2961,7 +3100,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (ainfo < 0) codegen_error(s, "invalid yield (SyntaxError)");
push();
if (tree) {
n = gen_values(s, tree, VAL, 0, 14);
n = gen_values(s, tree, VAL, 14);
if (n < 0) {
n = sendv = 1;
push();
@@ -3156,7 +3295,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (val) {
char *p = (char*)tree;
mrb_float f = mrb_float_read(p, NULL);
int off = new_lit(s, mrb_float_value(s->mrb, f));
int off = new_lit_float(s, f);
genop_2(s, OP_LOADL, cursp(), off);
push();
@@ -3173,7 +3312,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (val) {
char *p = (char*)tree->cdr;
mrb_float f = mrb_float_read(p, NULL);
int off = new_lit(s, mrb_float_value(s->mrb, -f));
int off = new_lit_float(s, -f);
genop_2(s, OP_LOADL, cursp(), off);
push();
@@ -3222,11 +3361,9 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_STR:
if (val) {
char *p = (char*)tree->car;
size_t len = (intptr_t)tree->cdr;
int ai = mrb_gc_arena_save(s->mrb);
int off = new_lit(s, mrb_str_new(s->mrb, p, len));
mrb_int len = nint(tree->cdr);
int off = new_lit_str(s, p, len);
mrb_gc_arena_restore(s->mrb, ai);
genop_2(s, OP_STRING, cursp(), off);
push();
}
@@ -3277,7 +3414,6 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_DXSTR:
{
node *n;
int ai = mrb_gc_arena_save(s->mrb);
int sym = new_sym(s, MRB_SYM_2(s->mrb, Kernel));
genop_1(s, OP_LOADSELF, cursp());
@@ -3300,16 +3436,14 @@ codegen(codegen_scope *s, node *tree, int val)
sym = new_sym(s, MRB_OPSYM_2(s->mrb, tick)); /* ` */
genop_3(s, OP_SEND, cursp(), sym, 1);
if (val) push();
mrb_gc_arena_restore(s->mrb, ai);
}
break;
case NODE_XSTR:
{
char *p = (char*)tree->car;
size_t len = (intptr_t)tree->cdr;
int ai = mrb_gc_arena_save(s->mrb);
int off = new_lit(s, mrb_str_new(s->mrb, p, len));
mrb_int len = nint(tree->cdr);
int off = new_lit_str(s, p, len);
int sym;
genop_1(s, OP_LOADSELF, cursp());
@@ -3320,7 +3454,6 @@ codegen(codegen_scope *s, node *tree, int val)
sym = new_sym(s, MRB_OPSYM_2(s->mrb, tick)); /* ` */
genop_3(s, OP_SEND, cursp(), sym, 1);
if (val) push();
mrb_gc_arena_restore(s->mrb, ai);
}
break;
@@ -3329,9 +3462,8 @@ codegen(codegen_scope *s, node *tree, int val)
char *p1 = (char*)tree->car;
char *p2 = (char*)tree->cdr->car;
char *p3 = (char*)tree->cdr->cdr;
int ai = mrb_gc_arena_save(s->mrb);
int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1));
int off = new_lit_cstr(s, p1);
int argc = 1;
genop_1(s, OP_OCLASS, cursp());
@@ -3341,7 +3473,7 @@ codegen(codegen_scope *s, node *tree, int val)
push();
if (p2 || p3) {
if (p2) { /* opt */
off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
off = new_lit_cstr(s, p2);
genop_2(s, OP_STRING, cursp(), off);
}
else {
@@ -3350,7 +3482,7 @@ codegen(codegen_scope *s, node *tree, int val)
push();
argc++;
if (p3) { /* enc */
off = new_lit(s, mrb_str_new(s->mrb, p3, 1));
off = new_lit_str(s, p3, 1);
genop_2(s, OP_STRING, cursp(), off);
push();
argc++;
@@ -3360,7 +3492,6 @@ codegen(codegen_scope *s, node *tree, int val)
pop_n(argc+2);
sym = new_sym(s, MRB_SYM_2(s->mrb, compile));
genop_3(s, OP_SEND, cursp(), sym, argc);
mrb_gc_arena_restore(s->mrb, ai);
push();
}
break;
@@ -3368,7 +3499,6 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_DREGX:
if (val) {
node *n = tree->car;
int ai = mrb_gc_arena_save(s->mrb);
int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
int argc = 1;
int off;
@@ -3389,7 +3519,7 @@ codegen(codegen_scope *s, node *tree, int val)
n = tree->cdr->cdr;
if (n->car) { /* tail */
p = (char*)n->car;
off = new_lit(s, mrb_str_new_cstr(s->mrb, p));
off = new_lit_cstr(s, p);
codegen(s, tree->car, VAL);
genop_2(s, OP_STRING, cursp(), off);
pop();
@@ -3398,14 +3528,14 @@ codegen(codegen_scope *s, node *tree, int val)
}
if (n->cdr->car) { /* opt */
char *p2 = (char*)n->cdr->car;
off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
off = new_lit_cstr(s, p2);
genop_2(s, OP_STRING, cursp(), off);
push();
argc++;
}
if (n->cdr->cdr) { /* enc */
char *p2 = (char*)n->cdr->cdr;
off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
off = new_lit_cstr(s, p2);
genop_2(s, OP_STRING, cursp(), off);
push();
argc++;
@@ -3414,7 +3544,6 @@ codegen(codegen_scope *s, node *tree, int val)
pop_n(argc+2);
sym = new_sym(s, MRB_SYM_2(s->mrb, compile));
genop_3(s, OP_SEND, cursp(), sym, argc);
mrb_gc_arena_restore(s->mrb, ai);
push();
}
else {
+16 -16
View File
@@ -21,6 +21,7 @@
#include <mruby/throw.h>
#include <mruby/string.h>
#include <mruby/dump.h>
#include <mruby/internal.h>
#include <mruby/presym.h>
#include "node.h"
@@ -994,13 +995,13 @@ static node*
new_imaginary(parser_state *p, node *imaginary)
{
return new_call(p, new_const(p, MRB_SYM_2(p->mrb, Kernel)), MRB_SYM_2(p->mrb, Complex),
new_callargs(p, list2(list3((node*)NODE_INT, (node*)strdup("0"), nint(10)), imaginary), 0, 0), 1);
new_callargs(p, list2(list3((node*)NODE_INT, (node*)strdup("0"), nint(10)), imaginary), 0, 0), '.');
}
static node*
new_rational(parser_state *p, node *rational)
{
return new_call(p, new_const(p, MRB_SYM_2(p->mrb, Kernel)), MRB_SYM_2(p->mrb, Rational), new_callargs(p, list1(rational), 0, 0), 1);
return new_call(p, new_const(p, MRB_SYM_2(p->mrb, Kernel)), MRB_SYM_2(p->mrb, Rational), new_callargs(p, list1(rational), 0, 0), '.');
}
/* (:int . i) */
@@ -1216,14 +1217,14 @@ static node*
call_uni_op(parser_state *p, node *recv, const char *m)
{
void_expr_error(p, recv);
return new_call(p, recv, intern_cstr(m), 0, 1);
return new_call(p, recv, intern_cstr(m), 0, '.');
}
/* (:call a op b) */
static node*
call_bin_op(parser_state *p, node *recv, const char *m, node *arg1)
{
return new_call(p, recv, intern_cstr(m), new_callargs(p, list1(arg1), 0, 0), 1);
return new_call(p, recv, intern_cstr(m), new_callargs(p, list1(arg1), 0, 0), '.');
}
static void
@@ -6933,7 +6934,7 @@ mrb_load_detect_file_cxt(mrb_state *mrb, FILE *fp, mrbc_context *c)
return mrb_load_exec(mrb, mrb_parse_file_continue(mrb, fp, leading.b, bufsize, c), c);
}
else {
size_t binsize;
mrb_int binsize;
uint8_t *bin;
mrb_value bin_obj = mrb_nil_value(); /* temporary string object */
mrb_value result;
@@ -6941,11 +6942,12 @@ mrb_load_detect_file_cxt(mrb_state *mrb, FILE *fp, mrbc_context *c)
binsize = bin_to_uint32(leading.h.binary_size);
bin_obj = mrb_str_new(mrb, NULL, binsize);
bin = (uint8_t *)RSTRING_PTR(bin_obj);
memcpy(bin, leading.b, bufsize);
if (binsize > bufsize &&
fread(bin + bufsize, binsize - bufsize, 1, fp) == 0) {
binsize = bufsize;
/* The error is reported by mrb_load_irep_buf_cxt() */
if ((size_t)binsize > bufsize) {
memcpy(bin, leading.b, bufsize);
if (fread(bin + bufsize, binsize - bufsize, 1, fp) == 0) {
binsize = bufsize;
/* The error is reported by mrb_load_irep_buf_cxt() */
}
}
result = mrb_load_irep_buf_cxt(mrb, bin, binsize, c);
@@ -7417,12 +7419,10 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
}
}
n2 = n2->cdr;
if (n2) {
if (n2->car) {
dump_prefix(n2, offset+2);
printf("post:\n");
dump_recur(mrb, n2->car, offset+3);
}
if (n2 && n2->car) {
dump_prefix(n2, offset+2);
printf("post:\n");
dump_recur(mrb, n2->car, offset+3);
}
}
}
File diff suppressed because it is too large Load Diff
+27 -81
View File
@@ -168,10 +168,9 @@ complex_eq(mrb_state *mrb, mrb_value x)
return mrb_bool_value(mrb_complex_eq(mrb, x, y));
}
static mrb_value
complex_add(mrb_state *mrb, mrb_value x)
mrb_value
mrb_complex_add(mrb_state *mrb, mrb_value x, mrb_value y)
{
mrb_value y = mrb_get_arg1(mrb);
struct mrb_complex *p1 = complex_ptr(mrb, x);
switch (mrb_type(y)) {
@@ -190,9 +189,15 @@ complex_add(mrb_state *mrb, mrb_value x)
}
static mrb_value
complex_sub(mrb_state *mrb, mrb_value x)
complex_add(mrb_state *mrb, mrb_value x)
{
mrb_value y = mrb_get_arg1(mrb);
return mrb_complex_add(mrb, x, y);
}
mrb_value
mrb_complex_sub(mrb_state *mrb, mrb_value x, mrb_value y)
{
struct mrb_complex *p1 = complex_ptr(mrb, x);
switch (mrb_type(y)) {
@@ -211,9 +216,15 @@ complex_sub(mrb_state *mrb, mrb_value x)
}
static mrb_value
complex_mul(mrb_state *mrb, mrb_value x)
complex_sub(mrb_state *mrb, mrb_value x)
{
mrb_value y = mrb_get_arg1(mrb);
return mrb_complex_sub(mrb, x, y);
}
mrb_value
mrb_complex_mul(mrb_state *mrb, mrb_value x, mrb_value y)
{
struct mrb_complex *p1 = complex_ptr(mrb, x);
switch (mrb_type(y)) {
@@ -232,6 +243,13 @@ complex_mul(mrb_state *mrb, mrb_value x)
}
}
static mrb_value
complex_mul(mrb_state *mrb, mrb_value x)
{
mrb_value y = mrb_get_arg1(mrb);
return mrb_complex_mul(mrb, x, y);
}
/* Arithmetic on (significand, exponent) pairs avoids premature overflow in
complex division */
struct float_pair {
@@ -272,11 +290,10 @@ div_pair(struct float_pair *q, struct float_pair const *a,
q->x = a->x - b->x;
}
static mrb_value
complex_div(mrb_state *mrb, mrb_value self)
mrb_value
mrb_complex_div(mrb_state *mrb, mrb_value self, mrb_value rhs)
{
struct mrb_complex *a, *b;
mrb_value rhs = mrb_get_arg1(mrb);
a = complex_ptr(mrb, self);
if (mrb_type(rhs) != MRB_TT_COMPLEX) {
@@ -324,78 +341,11 @@ complex_div(mrb_state *mrb, mrb_value self)
return complex_new(mrb, F(ldexp)(zr.s, zr.x), F(ldexp)(zi.s, zi.x));
}
mrb_int mrb_div_int(mrb_state *mrb, mrb_int x, mrb_int y);
mrb_value mrb_rational_new(mrb_state *mrb, mrb_int n, mrb_int d);
mrb_value mrb_rational_div(mrb_state *mrb, mrb_value x);
/* 15.2.8.3.4 */
/*
* redefine Integer#/
*/
static mrb_value
cpx_int_div(mrb_state *mrb, mrb_value x)
complex_div(mrb_state *mrb, mrb_value x)
{
mrb_value y = mrb_get_arg1(mrb);
mrb_int a = mrb_integer(x);
if (mrb_integer_p(y)) {
mrb_int div = mrb_div_int(mrb, a, mrb_integer(y));
return mrb_int_value(mrb, div);
}
switch (mrb_type(y)) {
#ifdef MRB_USE_RATIONAL
case MRB_TT_RATIONAL:
return mrb_rational_div(mrb, mrb_rational_new(mrb, a, 1));
#endif
case MRB_TT_COMPLEX:
x = complex_new(mrb, (mrb_float)a, 0);
return complex_div(mrb, x);
default:
return mrb_float_value(mrb, mrb_div_float((mrb_float)a, mrb_as_float(mrb, y)));
}
}
/* 15.2.9.3.19(x) */
/*
* redefine Integer#quo
*/
static mrb_value
cpx_int_quo(mrb_state *mrb, mrb_value x)
{
mrb_value y = mrb_get_arg1(mrb);
mrb_int a = mrb_integer(x);
switch (mrb_type(y)) {
#ifdef MRB_USE_RATIONAL
case MRB_TT_RATIONAL:
x = mrb_rational_new(mrb, a, 1);
return mrb_funcall_id(mrb, x, MRB_OPSYM(div), 1, y);
#endif
case MRB_TT_COMPLEX:
x = complex_new(mrb, (mrb_float)a, 0);
return complex_div(mrb, x);
default:
return mrb_float_value(mrb, mrb_div_float((mrb_float)a, mrb_as_float(mrb, y)));
}
}
static mrb_value
cpx_flo_div(mrb_state *mrb, mrb_value x)
{
mrb_float a = mrb_float(x);
mrb_value y = mrb_get_arg1(mrb);
switch(mrb_type(y)) {
case MRB_TT_COMPLEX:
return complex_div(mrb, complex_new(mrb, a, 0));
case MRB_TT_FLOAT:
a = mrb_div_float(a, mrb_float(y));
return mrb_float_value(mrb, a);
default:
a = mrb_div_float(a, mrb_as_float(mrb, y));
return mrb_float_value(mrb, a);
}
return mrb_complex_div(mrb, x, y);
}
void mrb_mruby_complex_gem_init(mrb_state *mrb)
@@ -424,10 +374,6 @@ void mrb_mruby_complex_gem_init(mrb_state *mrb)
mrb_define_method(mrb, comp, "/", complex_div, MRB_ARGS_REQ(1));
mrb_define_method(mrb, comp, "quo", complex_div, MRB_ARGS_REQ(1));
mrb_define_method(mrb, comp, "==", complex_eq, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mrb->integer_class, "/", cpx_int_div, MRB_ARGS_REQ(1)); /* override */
mrb_define_method(mrb, mrb->integer_class, "quo", cpx_int_quo, MRB_ARGS_REQ(1)); /* override */
mrb_define_method(mrb, mrb->float_class, "/", cpx_flo_div, MRB_ARGS_REQ(1)); /* override */
mrb_define_method(mrb, mrb->float_class, "quo", cpx_flo_div, MRB_ARGS_REQ(1)); /* override */
}
void
+1
View File
@@ -0,0 +1 @@
/tmp
+2
View File
@@ -0,0 +1,2 @@
script:
- "ruby run_test.rb all test"
+25
View File
@@ -0,0 +1,25 @@
# mruby-errno
Errno module for mruby
## License
Copyright (c) 2013 Internet Initiative Japan Inc.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
+6
View File
@@ -0,0 +1,6 @@
MRuby::Gem::Specification.new('mruby-errno') do |spec|
spec.license = 'MIT'
spec.authors = 'Internet Initiative Japan Inc.'
spec.cc.include_paths << "#{build.root}/src"
end
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env ruby
#
# mrbgems test runner
#
gemname = File.basename(File.dirname(File.expand_path __FILE__))
if __FILE__ == $0
repository, dir = 'https://github.com/mruby/mruby.git', 'tmp/mruby'
build_args = ARGV
build_args = ['all', 'test'] if build_args.nil? or build_args.empty?
Dir.mkdir 'tmp' unless File.exist?('tmp')
unless File.exist?(dir)
system "git clone #{repository} #{dir}"
end
exit system(%Q[cd #{dir}; MRUBY_CONFIG=#{File.expand_path __FILE__} ruby minirake #{build_args.join(' ')}])
end
MRuby::Build.new do |conf|
toolchain :gcc
conf.gembox 'default'
conf.gem File.expand_path(File.dirname(__FILE__))
end
+191
View File
@@ -0,0 +1,191 @@
#include "mruby.h"
#include "mruby/array.h"
#include "mruby/class.h"
#include "mruby/error.h"
#include "mruby/hash.h"
#include "mruby/numeric.h"
#include "mruby/string.h"
#include "mruby/variable.h"
#include "mruby/internal.h"
#include <mruby/presym.h>
#include <errno.h>
#include <string.h>
static const struct {
#ifdef MRB_NO_PRESYM
#define itsdefined(name, sym) { #name, name },
const char *name;
#else
#define itsdefined(name, sym) { sym, name },
mrb_sym sym;
#endif
int eno;
} e2c[] = {
#define itsnotdefined(name, sym)
#include "known_errors_def.cstub"
#undef itsdefined
#undef itsnotdefined
};
#ifdef MRB_NO_PRESYM
#define ENTRY_SYM(e) mrb_intern_static(mrb, (e).name, strlen((e).name))
#else
#define ENTRY_SYM(e) (e).sym
#endif
#define E2C_LEN (sizeof(e2c) / sizeof(e2c[0]))
static void
mrb_sce_init(mrb_state *mrb, mrb_value self, mrb_value m, int n)
{
mrb_value str;
struct RClass *m_errno;
int no_errno = (n < 0);
char buf[20];
m_errno = mrb_module_get_id(mrb, MRB_SYM(Errno));
if (!no_errno) {
size_t i;
for (i=0; i < E2C_LEN; i++) {
if (e2c[i].eno == n) {
mrb_basic_ptr(self)->c = mrb_class_get_under_id(mrb, m_errno, ENTRY_SYM(e2c[i]));
str = mrb_str_new_cstr(mrb, strerror(n));
break;
}
}
if (i == E2C_LEN) {
mrb_iv_set(mrb, self, MRB_SYM(errno), mrb_fixnum_value(n));
str = mrb_str_new_cstr(mrb, "Unknown error: ");
char *bp = mrb_int_to_cstr(buf, sizeof(buf), n, 10);
mrb_str_cat2(mrb, str, bp);
}
}
else {
str = mrb_str_new_cstr(mrb, "unknown error");
}
if (!mrb_nil_p(m)) {
mrb_str_cat2(mrb, str, " - ");
mrb_str_append(mrb, str, m);
}
mrb_exc_mesg_set(mrb, mrb_exc_ptr(self), str);
}
static mrb_value
mrb_sce_init_m(mrb_state *mrb, mrb_value self)
{
mrb_value m;
mrb_int n;
if (mrb_get_args(mrb, "o|i", &m, &n) == 1) {
if (mrb_fixnum_p(m)) {
n = mrb_fixnum(m);
m = mrb_nil_value();
}
else {
n = -1;
}
}
mrb_sce_init(mrb, self, m, (int)n);
return self;
}
static mrb_value
mrb_sce_errno(mrb_state *mrb, mrb_value self)
{
struct RClass *c;
mrb_sym sym;
c = mrb_class(mrb, self);
sym = MRB_SYM(Errno);
if (mrb_const_defined_at(mrb, mrb_obj_value(c), sym)) {
return mrb_const_get(mrb, mrb_obj_value(c), sym);
} else {
sym = MRB_SYM(errno);
return mrb_attr_get(mrb, self, sym);
}
}
static mrb_value
mrb_sce_sys_fail(mrb_state *mrb, mrb_value cls)
{
struct RClass *sce;
mrb_value msg;
mrb_int no = -1;
mrb_int argc;
mrb->c->ci->mid = 0;
sce = mrb_class_get_id(mrb, MRB_SYM(SystemCallError));
argc = mrb_get_args(mrb, "i|S", &no, &msg);
struct RBasic* e = mrb_obj_alloc(mrb, MRB_TT_EXCEPTION, sce);
mrb_value exc = mrb_obj_value(e);
if (argc == 1) {
msg = mrb_nil_value();
}
exc = mrb_obj_value(e);
mrb_sce_init(mrb, exc, msg, (int)no);
mrb_exc_raise(mrb, exc);
return mrb_nil_value(); /* NOTREACHED */
}
static mrb_value
mrb_exxx_init(mrb_state *mrb, mrb_value self)
{
mrb_value m, no, str;
no = mrb_const_get(mrb, mrb_obj_value(mrb_class(mrb, self)), MRB_SYM(Errno));
str = mrb_str_new_cstr(mrb, strerror((int)mrb_fixnum(no)));
m = mrb_nil_value();
mrb_get_args(mrb, "|S", &m);
if (!mrb_nil_p(m)) {
mrb_str_cat2(mrb, str, " - ");
mrb_str_append(mrb, str, m);
}
mrb_exc_mesg_set(mrb, mrb_exc_ptr(self), str);
return self;
}
void
mrb_mruby_errno_gem_init(mrb_state *mrb)
{
struct RClass *e, *eno, *sce, *ste;
mrb_value noerror;
ste = mrb_class_get_id(mrb, MRB_SYM(StandardError));
sce = mrb_define_class(mrb, "SystemCallError", ste);
mrb_define_class_method(mrb, sce, "_sys_fail", mrb_sce_sys_fail, MRB_ARGS_REQ(1));
mrb_define_method(mrb, sce, "errno", mrb_sce_errno, MRB_ARGS_NONE());
mrb_define_method(mrb, sce, "initialize", mrb_sce_init_m, MRB_ARGS_ARG(1, 1));
eno = mrb_define_module_id(mrb, MRB_SYM(Errno));
e = mrb_define_class_under_id(mrb, eno, MRB_SYM(NOERROR), sce);
mrb_define_const_id(mrb, e, MRB_SYM(Errno), mrb_fixnum_value(0));
mrb_define_method(mrb, e, "initialize", mrb_exxx_init, MRB_ARGS_OPT(1));
//mrb_define_method(mrb, e, "===", mrb_exxx_cmp, MRB_ARGS_REQ(1));
noerror = mrb_obj_value(e);
#define itsdefined(name, sym) \
do { \
int ai = mrb_gc_arena_save(mrb); \
e = mrb_define_class_under_id(mrb, eno, sym, sce); \
mrb_define_const_id(mrb, e, MRB_SYM(Errno), mrb_fixnum_value(name)); \
mrb_define_method(mrb, e, "initialize", mrb_exxx_init, MRB_ARGS_OPT(1)); \
mrb_gc_arena_restore(mrb, ai); \
} while (0);
#define itsnotdefined(name, sym) \
do { \
mrb_define_const_id(mrb, eno, sym, noerror); \
} while (0);
#include "known_errors_def.cstub"
}
void
mrb_mruby_errno_gem_final(mrb_state *mrb)
{
}
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env ruby
Dir.chdir(File.dirname($0))
d = File.open("known_errors_def.cstub", "w")
IO.readlines("known_errors.def").each { |name|
next if name =~ /^#/
name.strip!
d.write <<CODE
#ifdef #{name}
itsdefined(#{name}, MRB_SYM(#{name}))
#else
itsnotdefined(#{name}, MRB_SYM(#{name}))
#endif
CODE
}
+156
View File
@@ -0,0 +1,156 @@
EPERM
ENOENT
ESRCH
EINTR
EIO
ENXIO
E2BIG
ENOEXEC
EBADF
ECHILD
EAGAIN
ENOMEM
EACCES
EFAULT
ENOTBLK
EBUSY
EEXIST
EXDEV
ENODEV
ENOTDIR
EISDIR
EINVAL
ENFILE
EMFILE
ENOTTY
ETXTBSY
EFBIG
ENOSPC
ESPIPE
EROFS
EMLINK
EPIPE
EDOM
ERANGE
EDEADLK
ENAMETOOLONG
ENOLCK
ENOSYS
ENOTEMPTY
ELOOP
EWOULDBLOCK
ENOMSG
EIDRM
ECHRNG
EL2NSYNC
EL3HLT
EL3RST
ELNRNG
EUNATCH
ENOCSI
EL2HLT
EBADE
EBADR
EXFULL
ENOANO
EBADRQC
EBADSLT
EDEADLOCK
EBFONT
ENOSTR
ENODATA
ETIME
ENOSR
ENONET
ENOPKG
EREMOTE
ENOLINK
EADV
ESRMNT
ECOMM
EPROTO
ENOTCAPABLE
ECAPMODE
EMULTIHOP
EDOTDOT
EBADMSG
EPWROFF
EDEVERR
EOVERFLOW
EBADEXEC
EBADARCH
EBADMACHO
ESHLIBVERS
ENOTUNIQ
EBADFD
EREMCHG
ELIBACC
ELIBBAD
ELIBSCN
ELIBMAX
ELIBEXEC
EILSEQ
ERESTART
ESTRPIPE
EUSERS
ENOTSOCK
EDESTADDRREQ
EMSGSIZE
EPROTOTYPE
ENOPROTOOPT
EPROTONOSUPPORT
ESOCKTNOSUPPORT
EOPNOTSUPP
EPFNOSUPPORT
EAFNOSUPPORT
EADDRINUSE
EADDRNOTAVAIL
ENETDOWN
ENETUNREACH
ENETRESET
ECONNABORTED
ECONNRESET
ENOBUFS
EISCONN
ENOTCONN
ESHUTDOWN
ETOOMANYREFS
ETIMEDOUT
ECONNREFUSED
EHOSTDOWN
EHOSTUNREACH
EALREADY
EINPROGRESS
ESTALE
EUCLEAN
ENOTNAM
ENAVAIL
EISNAM
EREMOTEIO
EDQUOT
ECANCELED
EKEYEXPIRED
EKEYREJECTED
EKEYREVOKED
EMEDIUMTYPE
ENOKEY
ENOMEDIUM
ENOTRECOVERABLE
EOWNERDEAD
EINTEGRITY
ERFKILL
EAUTH
EBADRPC
EDOOFUS
EFTYPE
ENEEDAUTH
ENOATTR
ENOTSUP
EPROCLIM
EPROCUNAVAIL
EPROGMISMATCH
EPROGUNAVAIL
ERPCMISMATCH
EIPSEC
ENOPOLICY
EQFULL
@@ -0,0 +1,780 @@
#ifdef EPERM
itsdefined(EPERM, MRB_SYM(EPERM))
#else
itsnotdefined(EPERM, MRB_SYM(EPERM))
#endif
#ifdef ENOENT
itsdefined(ENOENT, MRB_SYM(ENOENT))
#else
itsnotdefined(ENOENT, MRB_SYM(ENOENT))
#endif
#ifdef ESRCH
itsdefined(ESRCH, MRB_SYM(ESRCH))
#else
itsnotdefined(ESRCH, MRB_SYM(ESRCH))
#endif
#ifdef EINTR
itsdefined(EINTR, MRB_SYM(EINTR))
#else
itsnotdefined(EINTR, MRB_SYM(EINTR))
#endif
#ifdef EIO
itsdefined(EIO, MRB_SYM(EIO))
#else
itsnotdefined(EIO, MRB_SYM(EIO))
#endif
#ifdef ENXIO
itsdefined(ENXIO, MRB_SYM(ENXIO))
#else
itsnotdefined(ENXIO, MRB_SYM(ENXIO))
#endif
#ifdef E2BIG
itsdefined(E2BIG, MRB_SYM(E2BIG))
#else
itsnotdefined(E2BIG, MRB_SYM(E2BIG))
#endif
#ifdef ENOEXEC
itsdefined(ENOEXEC, MRB_SYM(ENOEXEC))
#else
itsnotdefined(ENOEXEC, MRB_SYM(ENOEXEC))
#endif
#ifdef EBADF
itsdefined(EBADF, MRB_SYM(EBADF))
#else
itsnotdefined(EBADF, MRB_SYM(EBADF))
#endif
#ifdef ECHILD
itsdefined(ECHILD, MRB_SYM(ECHILD))
#else
itsnotdefined(ECHILD, MRB_SYM(ECHILD))
#endif
#ifdef EAGAIN
itsdefined(EAGAIN, MRB_SYM(EAGAIN))
#else
itsnotdefined(EAGAIN, MRB_SYM(EAGAIN))
#endif
#ifdef ENOMEM
itsdefined(ENOMEM, MRB_SYM(ENOMEM))
#else
itsnotdefined(ENOMEM, MRB_SYM(ENOMEM))
#endif
#ifdef EACCES
itsdefined(EACCES, MRB_SYM(EACCES))
#else
itsnotdefined(EACCES, MRB_SYM(EACCES))
#endif
#ifdef EFAULT
itsdefined(EFAULT, MRB_SYM(EFAULT))
#else
itsnotdefined(EFAULT, MRB_SYM(EFAULT))
#endif
#ifdef ENOTBLK
itsdefined(ENOTBLK, MRB_SYM(ENOTBLK))
#else
itsnotdefined(ENOTBLK, MRB_SYM(ENOTBLK))
#endif
#ifdef EBUSY
itsdefined(EBUSY, MRB_SYM(EBUSY))
#else
itsnotdefined(EBUSY, MRB_SYM(EBUSY))
#endif
#ifdef EEXIST
itsdefined(EEXIST, MRB_SYM(EEXIST))
#else
itsnotdefined(EEXIST, MRB_SYM(EEXIST))
#endif
#ifdef EXDEV
itsdefined(EXDEV, MRB_SYM(EXDEV))
#else
itsnotdefined(EXDEV, MRB_SYM(EXDEV))
#endif
#ifdef ENODEV
itsdefined(ENODEV, MRB_SYM(ENODEV))
#else
itsnotdefined(ENODEV, MRB_SYM(ENODEV))
#endif
#ifdef ENOTDIR
itsdefined(ENOTDIR, MRB_SYM(ENOTDIR))
#else
itsnotdefined(ENOTDIR, MRB_SYM(ENOTDIR))
#endif
#ifdef EISDIR
itsdefined(EISDIR, MRB_SYM(EISDIR))
#else
itsnotdefined(EISDIR, MRB_SYM(EISDIR))
#endif
#ifdef EINVAL
itsdefined(EINVAL, MRB_SYM(EINVAL))
#else
itsnotdefined(EINVAL, MRB_SYM(EINVAL))
#endif
#ifdef ENFILE
itsdefined(ENFILE, MRB_SYM(ENFILE))
#else
itsnotdefined(ENFILE, MRB_SYM(ENFILE))
#endif
#ifdef EMFILE
itsdefined(EMFILE, MRB_SYM(EMFILE))
#else
itsnotdefined(EMFILE, MRB_SYM(EMFILE))
#endif
#ifdef ENOTTY
itsdefined(ENOTTY, MRB_SYM(ENOTTY))
#else
itsnotdefined(ENOTTY, MRB_SYM(ENOTTY))
#endif
#ifdef ETXTBSY
itsdefined(ETXTBSY, MRB_SYM(ETXTBSY))
#else
itsnotdefined(ETXTBSY, MRB_SYM(ETXTBSY))
#endif
#ifdef EFBIG
itsdefined(EFBIG, MRB_SYM(EFBIG))
#else
itsnotdefined(EFBIG, MRB_SYM(EFBIG))
#endif
#ifdef ENOSPC
itsdefined(ENOSPC, MRB_SYM(ENOSPC))
#else
itsnotdefined(ENOSPC, MRB_SYM(ENOSPC))
#endif
#ifdef ESPIPE
itsdefined(ESPIPE, MRB_SYM(ESPIPE))
#else
itsnotdefined(ESPIPE, MRB_SYM(ESPIPE))
#endif
#ifdef EROFS
itsdefined(EROFS, MRB_SYM(EROFS))
#else
itsnotdefined(EROFS, MRB_SYM(EROFS))
#endif
#ifdef EMLINK
itsdefined(EMLINK, MRB_SYM(EMLINK))
#else
itsnotdefined(EMLINK, MRB_SYM(EMLINK))
#endif
#ifdef EPIPE
itsdefined(EPIPE, MRB_SYM(EPIPE))
#else
itsnotdefined(EPIPE, MRB_SYM(EPIPE))
#endif
#ifdef EDOM
itsdefined(EDOM, MRB_SYM(EDOM))
#else
itsnotdefined(EDOM, MRB_SYM(EDOM))
#endif
#ifdef ERANGE
itsdefined(ERANGE, MRB_SYM(ERANGE))
#else
itsnotdefined(ERANGE, MRB_SYM(ERANGE))
#endif
#ifdef EDEADLK
itsdefined(EDEADLK, MRB_SYM(EDEADLK))
#else
itsnotdefined(EDEADLK, MRB_SYM(EDEADLK))
#endif
#ifdef ENAMETOOLONG
itsdefined(ENAMETOOLONG, MRB_SYM(ENAMETOOLONG))
#else
itsnotdefined(ENAMETOOLONG, MRB_SYM(ENAMETOOLONG))
#endif
#ifdef ENOLCK
itsdefined(ENOLCK, MRB_SYM(ENOLCK))
#else
itsnotdefined(ENOLCK, MRB_SYM(ENOLCK))
#endif
#ifdef ENOSYS
itsdefined(ENOSYS, MRB_SYM(ENOSYS))
#else
itsnotdefined(ENOSYS, MRB_SYM(ENOSYS))
#endif
#ifdef ENOTEMPTY
itsdefined(ENOTEMPTY, MRB_SYM(ENOTEMPTY))
#else
itsnotdefined(ENOTEMPTY, MRB_SYM(ENOTEMPTY))
#endif
#ifdef ELOOP
itsdefined(ELOOP, MRB_SYM(ELOOP))
#else
itsnotdefined(ELOOP, MRB_SYM(ELOOP))
#endif
#ifdef EWOULDBLOCK
itsdefined(EWOULDBLOCK, MRB_SYM(EWOULDBLOCK))
#else
itsnotdefined(EWOULDBLOCK, MRB_SYM(EWOULDBLOCK))
#endif
#ifdef ENOMSG
itsdefined(ENOMSG, MRB_SYM(ENOMSG))
#else
itsnotdefined(ENOMSG, MRB_SYM(ENOMSG))
#endif
#ifdef EIDRM
itsdefined(EIDRM, MRB_SYM(EIDRM))
#else
itsnotdefined(EIDRM, MRB_SYM(EIDRM))
#endif
#ifdef ECHRNG
itsdefined(ECHRNG, MRB_SYM(ECHRNG))
#else
itsnotdefined(ECHRNG, MRB_SYM(ECHRNG))
#endif
#ifdef EL2NSYNC
itsdefined(EL2NSYNC, MRB_SYM(EL2NSYNC))
#else
itsnotdefined(EL2NSYNC, MRB_SYM(EL2NSYNC))
#endif
#ifdef EL3HLT
itsdefined(EL3HLT, MRB_SYM(EL3HLT))
#else
itsnotdefined(EL3HLT, MRB_SYM(EL3HLT))
#endif
#ifdef EL3RST
itsdefined(EL3RST, MRB_SYM(EL3RST))
#else
itsnotdefined(EL3RST, MRB_SYM(EL3RST))
#endif
#ifdef ELNRNG
itsdefined(ELNRNG, MRB_SYM(ELNRNG))
#else
itsnotdefined(ELNRNG, MRB_SYM(ELNRNG))
#endif
#ifdef EUNATCH
itsdefined(EUNATCH, MRB_SYM(EUNATCH))
#else
itsnotdefined(EUNATCH, MRB_SYM(EUNATCH))
#endif
#ifdef ENOCSI
itsdefined(ENOCSI, MRB_SYM(ENOCSI))
#else
itsnotdefined(ENOCSI, MRB_SYM(ENOCSI))
#endif
#ifdef EL2HLT
itsdefined(EL2HLT, MRB_SYM(EL2HLT))
#else
itsnotdefined(EL2HLT, MRB_SYM(EL2HLT))
#endif
#ifdef EBADE
itsdefined(EBADE, MRB_SYM(EBADE))
#else
itsnotdefined(EBADE, MRB_SYM(EBADE))
#endif
#ifdef EBADR
itsdefined(EBADR, MRB_SYM(EBADR))
#else
itsnotdefined(EBADR, MRB_SYM(EBADR))
#endif
#ifdef EXFULL
itsdefined(EXFULL, MRB_SYM(EXFULL))
#else
itsnotdefined(EXFULL, MRB_SYM(EXFULL))
#endif
#ifdef ENOANO
itsdefined(ENOANO, MRB_SYM(ENOANO))
#else
itsnotdefined(ENOANO, MRB_SYM(ENOANO))
#endif
#ifdef EBADRQC
itsdefined(EBADRQC, MRB_SYM(EBADRQC))
#else
itsnotdefined(EBADRQC, MRB_SYM(EBADRQC))
#endif
#ifdef EBADSLT
itsdefined(EBADSLT, MRB_SYM(EBADSLT))
#else
itsnotdefined(EBADSLT, MRB_SYM(EBADSLT))
#endif
#ifdef EDEADLOCK
itsdefined(EDEADLOCK, MRB_SYM(EDEADLOCK))
#else
itsnotdefined(EDEADLOCK, MRB_SYM(EDEADLOCK))
#endif
#ifdef EBFONT
itsdefined(EBFONT, MRB_SYM(EBFONT))
#else
itsnotdefined(EBFONT, MRB_SYM(EBFONT))
#endif
#ifdef ENOSTR
itsdefined(ENOSTR, MRB_SYM(ENOSTR))
#else
itsnotdefined(ENOSTR, MRB_SYM(ENOSTR))
#endif
#ifdef ENODATA
itsdefined(ENODATA, MRB_SYM(ENODATA))
#else
itsnotdefined(ENODATA, MRB_SYM(ENODATA))
#endif
#ifdef ETIME
itsdefined(ETIME, MRB_SYM(ETIME))
#else
itsnotdefined(ETIME, MRB_SYM(ETIME))
#endif
#ifdef ENOSR
itsdefined(ENOSR, MRB_SYM(ENOSR))
#else
itsnotdefined(ENOSR, MRB_SYM(ENOSR))
#endif
#ifdef ENONET
itsdefined(ENONET, MRB_SYM(ENONET))
#else
itsnotdefined(ENONET, MRB_SYM(ENONET))
#endif
#ifdef ENOPKG
itsdefined(ENOPKG, MRB_SYM(ENOPKG))
#else
itsnotdefined(ENOPKG, MRB_SYM(ENOPKG))
#endif
#ifdef EREMOTE
itsdefined(EREMOTE, MRB_SYM(EREMOTE))
#else
itsnotdefined(EREMOTE, MRB_SYM(EREMOTE))
#endif
#ifdef ENOLINK
itsdefined(ENOLINK, MRB_SYM(ENOLINK))
#else
itsnotdefined(ENOLINK, MRB_SYM(ENOLINK))
#endif
#ifdef EADV
itsdefined(EADV, MRB_SYM(EADV))
#else
itsnotdefined(EADV, MRB_SYM(EADV))
#endif
#ifdef ESRMNT
itsdefined(ESRMNT, MRB_SYM(ESRMNT))
#else
itsnotdefined(ESRMNT, MRB_SYM(ESRMNT))
#endif
#ifdef ECOMM
itsdefined(ECOMM, MRB_SYM(ECOMM))
#else
itsnotdefined(ECOMM, MRB_SYM(ECOMM))
#endif
#ifdef EPROTO
itsdefined(EPROTO, MRB_SYM(EPROTO))
#else
itsnotdefined(EPROTO, MRB_SYM(EPROTO))
#endif
#ifdef ENOTCAPABLE
itsdefined(ENOTCAPABLE, MRB_SYM(ENOTCAPABLE))
#else
itsnotdefined(ENOTCAPABLE, MRB_SYM(ENOTCAPABLE))
#endif
#ifdef ECAPMODE
itsdefined(ECAPMODE, MRB_SYM(ECAPMODE))
#else
itsnotdefined(ECAPMODE, MRB_SYM(ECAPMODE))
#endif
#ifdef EMULTIHOP
itsdefined(EMULTIHOP, MRB_SYM(EMULTIHOP))
#else
itsnotdefined(EMULTIHOP, MRB_SYM(EMULTIHOP))
#endif
#ifdef EDOTDOT
itsdefined(EDOTDOT, MRB_SYM(EDOTDOT))
#else
itsnotdefined(EDOTDOT, MRB_SYM(EDOTDOT))
#endif
#ifdef EBADMSG
itsdefined(EBADMSG, MRB_SYM(EBADMSG))
#else
itsnotdefined(EBADMSG, MRB_SYM(EBADMSG))
#endif
#ifdef EPWROFF
itsdefined(EPWROFF, MRB_SYM(EPWROFF))
#else
itsnotdefined(EPWROFF, MRB_SYM(EPWROFF))
#endif
#ifdef EDEVERR
itsdefined(EDEVERR, MRB_SYM(EDEVERR))
#else
itsnotdefined(EDEVERR, MRB_SYM(EDEVERR))
#endif
#ifdef EOVERFLOW
itsdefined(EOVERFLOW, MRB_SYM(EOVERFLOW))
#else
itsnotdefined(EOVERFLOW, MRB_SYM(EOVERFLOW))
#endif
#ifdef EBADEXEC
itsdefined(EBADEXEC, MRB_SYM(EBADEXEC))
#else
itsnotdefined(EBADEXEC, MRB_SYM(EBADEXEC))
#endif
#ifdef EBADARCH
itsdefined(EBADARCH, MRB_SYM(EBADARCH))
#else
itsnotdefined(EBADARCH, MRB_SYM(EBADARCH))
#endif
#ifdef EBADMACHO
itsdefined(EBADMACHO, MRB_SYM(EBADMACHO))
#else
itsnotdefined(EBADMACHO, MRB_SYM(EBADMACHO))
#endif
#ifdef ESHLIBVERS
itsdefined(ESHLIBVERS, MRB_SYM(ESHLIBVERS))
#else
itsnotdefined(ESHLIBVERS, MRB_SYM(ESHLIBVERS))
#endif
#ifdef ENOTUNIQ
itsdefined(ENOTUNIQ, MRB_SYM(ENOTUNIQ))
#else
itsnotdefined(ENOTUNIQ, MRB_SYM(ENOTUNIQ))
#endif
#ifdef EBADFD
itsdefined(EBADFD, MRB_SYM(EBADFD))
#else
itsnotdefined(EBADFD, MRB_SYM(EBADFD))
#endif
#ifdef EREMCHG
itsdefined(EREMCHG, MRB_SYM(EREMCHG))
#else
itsnotdefined(EREMCHG, MRB_SYM(EREMCHG))
#endif
#ifdef ELIBACC
itsdefined(ELIBACC, MRB_SYM(ELIBACC))
#else
itsnotdefined(ELIBACC, MRB_SYM(ELIBACC))
#endif
#ifdef ELIBBAD
itsdefined(ELIBBAD, MRB_SYM(ELIBBAD))
#else
itsnotdefined(ELIBBAD, MRB_SYM(ELIBBAD))
#endif
#ifdef ELIBSCN
itsdefined(ELIBSCN, MRB_SYM(ELIBSCN))
#else
itsnotdefined(ELIBSCN, MRB_SYM(ELIBSCN))
#endif
#ifdef ELIBMAX
itsdefined(ELIBMAX, MRB_SYM(ELIBMAX))
#else
itsnotdefined(ELIBMAX, MRB_SYM(ELIBMAX))
#endif
#ifdef ELIBEXEC
itsdefined(ELIBEXEC, MRB_SYM(ELIBEXEC))
#else
itsnotdefined(ELIBEXEC, MRB_SYM(ELIBEXEC))
#endif
#ifdef EILSEQ
itsdefined(EILSEQ, MRB_SYM(EILSEQ))
#else
itsnotdefined(EILSEQ, MRB_SYM(EILSEQ))
#endif
#ifdef ERESTART
itsdefined(ERESTART, MRB_SYM(ERESTART))
#else
itsnotdefined(ERESTART, MRB_SYM(ERESTART))
#endif
#ifdef ESTRPIPE
itsdefined(ESTRPIPE, MRB_SYM(ESTRPIPE))
#else
itsnotdefined(ESTRPIPE, MRB_SYM(ESTRPIPE))
#endif
#ifdef EUSERS
itsdefined(EUSERS, MRB_SYM(EUSERS))
#else
itsnotdefined(EUSERS, MRB_SYM(EUSERS))
#endif
#ifdef ENOTSOCK
itsdefined(ENOTSOCK, MRB_SYM(ENOTSOCK))
#else
itsnotdefined(ENOTSOCK, MRB_SYM(ENOTSOCK))
#endif
#ifdef EDESTADDRREQ
itsdefined(EDESTADDRREQ, MRB_SYM(EDESTADDRREQ))
#else
itsnotdefined(EDESTADDRREQ, MRB_SYM(EDESTADDRREQ))
#endif
#ifdef EMSGSIZE
itsdefined(EMSGSIZE, MRB_SYM(EMSGSIZE))
#else
itsnotdefined(EMSGSIZE, MRB_SYM(EMSGSIZE))
#endif
#ifdef EPROTOTYPE
itsdefined(EPROTOTYPE, MRB_SYM(EPROTOTYPE))
#else
itsnotdefined(EPROTOTYPE, MRB_SYM(EPROTOTYPE))
#endif
#ifdef ENOPROTOOPT
itsdefined(ENOPROTOOPT, MRB_SYM(ENOPROTOOPT))
#else
itsnotdefined(ENOPROTOOPT, MRB_SYM(ENOPROTOOPT))
#endif
#ifdef EPROTONOSUPPORT
itsdefined(EPROTONOSUPPORT, MRB_SYM(EPROTONOSUPPORT))
#else
itsnotdefined(EPROTONOSUPPORT, MRB_SYM(EPROTONOSUPPORT))
#endif
#ifdef ESOCKTNOSUPPORT
itsdefined(ESOCKTNOSUPPORT, MRB_SYM(ESOCKTNOSUPPORT))
#else
itsnotdefined(ESOCKTNOSUPPORT, MRB_SYM(ESOCKTNOSUPPORT))
#endif
#ifdef EOPNOTSUPP
itsdefined(EOPNOTSUPP, MRB_SYM(EOPNOTSUPP))
#else
itsnotdefined(EOPNOTSUPP, MRB_SYM(EOPNOTSUPP))
#endif
#ifdef EPFNOSUPPORT
itsdefined(EPFNOSUPPORT, MRB_SYM(EPFNOSUPPORT))
#else
itsnotdefined(EPFNOSUPPORT, MRB_SYM(EPFNOSUPPORT))
#endif
#ifdef EAFNOSUPPORT
itsdefined(EAFNOSUPPORT, MRB_SYM(EAFNOSUPPORT))
#else
itsnotdefined(EAFNOSUPPORT, MRB_SYM(EAFNOSUPPORT))
#endif
#ifdef EADDRINUSE
itsdefined(EADDRINUSE, MRB_SYM(EADDRINUSE))
#else
itsnotdefined(EADDRINUSE, MRB_SYM(EADDRINUSE))
#endif
#ifdef EADDRNOTAVAIL
itsdefined(EADDRNOTAVAIL, MRB_SYM(EADDRNOTAVAIL))
#else
itsnotdefined(EADDRNOTAVAIL, MRB_SYM(EADDRNOTAVAIL))
#endif
#ifdef ENETDOWN
itsdefined(ENETDOWN, MRB_SYM(ENETDOWN))
#else
itsnotdefined(ENETDOWN, MRB_SYM(ENETDOWN))
#endif
#ifdef ENETUNREACH
itsdefined(ENETUNREACH, MRB_SYM(ENETUNREACH))
#else
itsnotdefined(ENETUNREACH, MRB_SYM(ENETUNREACH))
#endif
#ifdef ENETRESET
itsdefined(ENETRESET, MRB_SYM(ENETRESET))
#else
itsnotdefined(ENETRESET, MRB_SYM(ENETRESET))
#endif
#ifdef ECONNABORTED
itsdefined(ECONNABORTED, MRB_SYM(ECONNABORTED))
#else
itsnotdefined(ECONNABORTED, MRB_SYM(ECONNABORTED))
#endif
#ifdef ECONNRESET
itsdefined(ECONNRESET, MRB_SYM(ECONNRESET))
#else
itsnotdefined(ECONNRESET, MRB_SYM(ECONNRESET))
#endif
#ifdef ENOBUFS
itsdefined(ENOBUFS, MRB_SYM(ENOBUFS))
#else
itsnotdefined(ENOBUFS, MRB_SYM(ENOBUFS))
#endif
#ifdef EISCONN
itsdefined(EISCONN, MRB_SYM(EISCONN))
#else
itsnotdefined(EISCONN, MRB_SYM(EISCONN))
#endif
#ifdef ENOTCONN
itsdefined(ENOTCONN, MRB_SYM(ENOTCONN))
#else
itsnotdefined(ENOTCONN, MRB_SYM(ENOTCONN))
#endif
#ifdef ESHUTDOWN
itsdefined(ESHUTDOWN, MRB_SYM(ESHUTDOWN))
#else
itsnotdefined(ESHUTDOWN, MRB_SYM(ESHUTDOWN))
#endif
#ifdef ETOOMANYREFS
itsdefined(ETOOMANYREFS, MRB_SYM(ETOOMANYREFS))
#else
itsnotdefined(ETOOMANYREFS, MRB_SYM(ETOOMANYREFS))
#endif
#ifdef ETIMEDOUT
itsdefined(ETIMEDOUT, MRB_SYM(ETIMEDOUT))
#else
itsnotdefined(ETIMEDOUT, MRB_SYM(ETIMEDOUT))
#endif
#ifdef ECONNREFUSED
itsdefined(ECONNREFUSED, MRB_SYM(ECONNREFUSED))
#else
itsnotdefined(ECONNREFUSED, MRB_SYM(ECONNREFUSED))
#endif
#ifdef EHOSTDOWN
itsdefined(EHOSTDOWN, MRB_SYM(EHOSTDOWN))
#else
itsnotdefined(EHOSTDOWN, MRB_SYM(EHOSTDOWN))
#endif
#ifdef EHOSTUNREACH
itsdefined(EHOSTUNREACH, MRB_SYM(EHOSTUNREACH))
#else
itsnotdefined(EHOSTUNREACH, MRB_SYM(EHOSTUNREACH))
#endif
#ifdef EALREADY
itsdefined(EALREADY, MRB_SYM(EALREADY))
#else
itsnotdefined(EALREADY, MRB_SYM(EALREADY))
#endif
#ifdef EINPROGRESS
itsdefined(EINPROGRESS, MRB_SYM(EINPROGRESS))
#else
itsnotdefined(EINPROGRESS, MRB_SYM(EINPROGRESS))
#endif
#ifdef ESTALE
itsdefined(ESTALE, MRB_SYM(ESTALE))
#else
itsnotdefined(ESTALE, MRB_SYM(ESTALE))
#endif
#ifdef EUCLEAN
itsdefined(EUCLEAN, MRB_SYM(EUCLEAN))
#else
itsnotdefined(EUCLEAN, MRB_SYM(EUCLEAN))
#endif
#ifdef ENOTNAM
itsdefined(ENOTNAM, MRB_SYM(ENOTNAM))
#else
itsnotdefined(ENOTNAM, MRB_SYM(ENOTNAM))
#endif
#ifdef ENAVAIL
itsdefined(ENAVAIL, MRB_SYM(ENAVAIL))
#else
itsnotdefined(ENAVAIL, MRB_SYM(ENAVAIL))
#endif
#ifdef EISNAM
itsdefined(EISNAM, MRB_SYM(EISNAM))
#else
itsnotdefined(EISNAM, MRB_SYM(EISNAM))
#endif
#ifdef EREMOTEIO
itsdefined(EREMOTEIO, MRB_SYM(EREMOTEIO))
#else
itsnotdefined(EREMOTEIO, MRB_SYM(EREMOTEIO))
#endif
#ifdef EDQUOT
itsdefined(EDQUOT, MRB_SYM(EDQUOT))
#else
itsnotdefined(EDQUOT, MRB_SYM(EDQUOT))
#endif
#ifdef ECANCELED
itsdefined(ECANCELED, MRB_SYM(ECANCELED))
#else
itsnotdefined(ECANCELED, MRB_SYM(ECANCELED))
#endif
#ifdef EKEYEXPIRED
itsdefined(EKEYEXPIRED, MRB_SYM(EKEYEXPIRED))
#else
itsnotdefined(EKEYEXPIRED, MRB_SYM(EKEYEXPIRED))
#endif
#ifdef EKEYREJECTED
itsdefined(EKEYREJECTED, MRB_SYM(EKEYREJECTED))
#else
itsnotdefined(EKEYREJECTED, MRB_SYM(EKEYREJECTED))
#endif
#ifdef EKEYREVOKED
itsdefined(EKEYREVOKED, MRB_SYM(EKEYREVOKED))
#else
itsnotdefined(EKEYREVOKED, MRB_SYM(EKEYREVOKED))
#endif
#ifdef EMEDIUMTYPE
itsdefined(EMEDIUMTYPE, MRB_SYM(EMEDIUMTYPE))
#else
itsnotdefined(EMEDIUMTYPE, MRB_SYM(EMEDIUMTYPE))
#endif
#ifdef ENOKEY
itsdefined(ENOKEY, MRB_SYM(ENOKEY))
#else
itsnotdefined(ENOKEY, MRB_SYM(ENOKEY))
#endif
#ifdef ENOMEDIUM
itsdefined(ENOMEDIUM, MRB_SYM(ENOMEDIUM))
#else
itsnotdefined(ENOMEDIUM, MRB_SYM(ENOMEDIUM))
#endif
#ifdef ENOTRECOVERABLE
itsdefined(ENOTRECOVERABLE, MRB_SYM(ENOTRECOVERABLE))
#else
itsnotdefined(ENOTRECOVERABLE, MRB_SYM(ENOTRECOVERABLE))
#endif
#ifdef EOWNERDEAD
itsdefined(EOWNERDEAD, MRB_SYM(EOWNERDEAD))
#else
itsnotdefined(EOWNERDEAD, MRB_SYM(EOWNERDEAD))
#endif
#ifdef EINTEGRITY
itsdefined(EINTEGRITY, MRB_SYM(EINTEGRITY))
#else
itsnotdefined(EINTEGRITY, MRB_SYM(EINTEGRITY))
#endif
#ifdef ERFKILL
itsdefined(ERFKILL, MRB_SYM(ERFKILL))
#else
itsnotdefined(ERFKILL, MRB_SYM(ERFKILL))
#endif
#ifdef EAUTH
itsdefined(EAUTH, MRB_SYM(EAUTH))
#else
itsnotdefined(EAUTH, MRB_SYM(EAUTH))
#endif
#ifdef EBADRPC
itsdefined(EBADRPC, MRB_SYM(EBADRPC))
#else
itsnotdefined(EBADRPC, MRB_SYM(EBADRPC))
#endif
#ifdef EDOOFUS
itsdefined(EDOOFUS, MRB_SYM(EDOOFUS))
#else
itsnotdefined(EDOOFUS, MRB_SYM(EDOOFUS))
#endif
#ifdef EFTYPE
itsdefined(EFTYPE, MRB_SYM(EFTYPE))
#else
itsnotdefined(EFTYPE, MRB_SYM(EFTYPE))
#endif
#ifdef ENEEDAUTH
itsdefined(ENEEDAUTH, MRB_SYM(ENEEDAUTH))
#else
itsnotdefined(ENEEDAUTH, MRB_SYM(ENEEDAUTH))
#endif
#ifdef ENOATTR
itsdefined(ENOATTR, MRB_SYM(ENOATTR))
#else
itsnotdefined(ENOATTR, MRB_SYM(ENOATTR))
#endif
#ifdef ENOTSUP
itsdefined(ENOTSUP, MRB_SYM(ENOTSUP))
#else
itsnotdefined(ENOTSUP, MRB_SYM(ENOTSUP))
#endif
#ifdef EPROCLIM
itsdefined(EPROCLIM, MRB_SYM(EPROCLIM))
#else
itsnotdefined(EPROCLIM, MRB_SYM(EPROCLIM))
#endif
#ifdef EPROCUNAVAIL
itsdefined(EPROCUNAVAIL, MRB_SYM(EPROCUNAVAIL))
#else
itsnotdefined(EPROCUNAVAIL, MRB_SYM(EPROCUNAVAIL))
#endif
#ifdef EPROGMISMATCH
itsdefined(EPROGMISMATCH, MRB_SYM(EPROGMISMATCH))
#else
itsnotdefined(EPROGMISMATCH, MRB_SYM(EPROGMISMATCH))
#endif
#ifdef EPROGUNAVAIL
itsdefined(EPROGUNAVAIL, MRB_SYM(EPROGUNAVAIL))
#else
itsnotdefined(EPROGUNAVAIL, MRB_SYM(EPROGUNAVAIL))
#endif
#ifdef ERPCMISMATCH
itsdefined(ERPCMISMATCH, MRB_SYM(ERPCMISMATCH))
#else
itsnotdefined(ERPCMISMATCH, MRB_SYM(ERPCMISMATCH))
#endif
#ifdef EIPSEC
itsdefined(EIPSEC, MRB_SYM(EIPSEC))
#else
itsnotdefined(EIPSEC, MRB_SYM(EIPSEC))
#endif
#ifdef ENOPOLICY
itsdefined(ENOPOLICY, MRB_SYM(ENOPOLICY))
#else
itsnotdefined(ENOPOLICY, MRB_SYM(ENOPOLICY))
#endif
#ifdef EQFULL
itsdefined(EQFULL, MRB_SYM(EQFULL))
#else
itsnotdefined(EQFULL, MRB_SYM(EQFULL))
#endif
+58
View File
@@ -0,0 +1,58 @@
assert('Errno') do
assert_equal(Module, Errno.class)
end
assert('SystemCallError') do
assert_equal(Class, SystemCallError.class)
end
assert('SystemCallError superclass') do
assert_equal(StandardError, SystemCallError.superclass)
end
assert('SystemCallError#initialize') do
assert_equal("unknown error - a", SystemCallError.new("a").message)
assert_equal("Unknown error: 12345 - a", SystemCallError.new("a", 12345).message)
assert_equal("Unknown error: 12345", SystemCallError.new(12345).message)
end
assert('SystemCallError#errno') do
assert_equal 1, SystemCallError.new("a", 1).errno
assert_equal 1, SystemCallError.new(1).errno
assert_equal 12345, SystemCallError.new("a", 12345).errno
assert_equal 23456, SystemCallError.new(23456).errno
end
assert('SystemCallError#inspect') do
assert_equal("unknown error - a (SystemCallError)", SystemCallError.new("a").inspect)
end
assert('Errno::NOERROR') do
assert_equal(Class, Errno::NOERROR.class)
end
# Is there any platform does not have EPERM?
assert('Errno::EPERM') do
assert_equal(Class, Errno::EPERM.class)
end
assert('Errno::EPERM superclass') do
assert_equal(SystemCallError, Errno::EPERM.superclass)
end
assert('Errno::EPERM::Errno') do
assert_true(Errno::EPERM::Errno.is_a?(Fixnum))
end
assert('Errno::EPERM#message') do
msg = Errno::EPERM.new.message
assert_equal("#{msg} - a", Errno::EPERM.new("a").message)
end
assert('Errno::EPERM#inspect') do
msg = Errno::EPERM.new.message
assert_equal("#{msg} (Errno::EPERM)", Errno::EPERM.new.inspect)
msg = Errno::EPERM.new.message
assert_equal("#{msg} - a (Errno::EPERM)", Errno::EPERM.new("a").inspect)
end
+1 -1
View File
@@ -224,7 +224,7 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
*b++ = *a++;
}
}
c->cibase->n = len;
c->cibase->n = (uint8_t)len;
value = c->stbase[0] = MRB_PROC_ENV(c->cibase->proc)->stack[0];
}
else {
+129 -129
View File
@@ -16,158 +16,158 @@ Add the line below to your build configuration.
* <https://doc.ruby-lang.org/ja/1.9.3/class/IO.html>
| method | mruby-io | memo |
| ------------------------- | -------- | ---- |
| IO.binread | | |
| IO.binwrite | | |
| IO.copy_stream | | |
| IO.new, IO.for_fd, IO.open | o | |
| IO.foreach | | |
| IO.pipe | o | |
| IO.popen | o | |
| IO.read | o | |
| IO.readlines | | |
| IO.select | o | |
| IO.sysopen | o | |
| IO.try_convert | | |
| IO.write | | |
| IO#<< | | |
| IO#advise | | |
| IO#autoclose= | | |
| IO#autoclose? | | |
| IO#binmode | | |
| IO#binmode? | | |
| method | mruby-io | memo |
|----------------------------|----------|----------|
| IO.binread | | |
| IO.binwrite | | |
| IO.copy_stream | | |
| IO.new, IO.for_fd, IO.open | o | |
| IO.foreach | | |
| IO.pipe | o | |
| IO.popen | o | |
| IO.read | o | |
| IO.readlines | | |
| IO.select | o | |
| IO.sysopen | o | |
| IO.try_convert | | |
| IO.write | | |
| IO#<< | | |
| IO#advise | | |
| IO#autoclose= | | |
| IO#autoclose? | | |
| IO#binmode | | |
| IO#binmode? | | |
| IO#bytes | | obsolete |
| IO#chars | | obsolete |
| IO#clone, IO#dup | o | |
| IO#close | o | |
| IO#close_on_exec= | o | |
| IO#close_on_exec? | o | |
| IO#close_read | | |
| IO#close_write | | |
| IO#closed? | o | |
| IO#clone, IO#dup | o | |
| IO#close | o | |
| IO#close_on_exec= | o | |
| IO#close_on_exec? | o | |
| IO#close_read | | |
| IO#close_write | | |
| IO#closed? | o | |
| IO#codepoints | | obsolete |
| IO#each_byte | o | |
| IO#each_char | o | |
| IO#each_codepoint | | |
| IO#each_line | o | |
| IO#eof, IO#eof? | o | |
| IO#external_encoding | | |
| IO#fcntl | | |
| IO#fdatasync | | |
| IO#fileno, IO#to_i | o | |
| IO#flush | o | |
| IO#fsync | | |
| IO#getbyte | o | |
| IO#getc | o | |
| IO#gets | o | |
| IO#internal_encoding | | |
| IO#ioctl | | |
| IO#isatty, IO#tty? | o | |
| IO#lineno | | |
| IO#lineno= | | |
| IO#each_byte | o | |
| IO#each_char | o | |
| IO#each_codepoint | | |
| IO#each_line | o | |
| IO#eof, IO#eof? | o | |
| IO#external_encoding | | |
| IO#fcntl | | |
| IO#fdatasync | | |
| IO#fileno, IO#to_i | o | |
| IO#flush | o | |
| IO#fsync | | |
| IO#getbyte | o | |
| IO#getc | o | |
| IO#gets | o | |
| IO#internal_encoding | | |
| IO#ioctl | | |
| IO#isatty, IO#tty? | o | |
| IO#lineno | | |
| IO#lineno= | | |
| IO#lines | | obsolete |
| IO#pid | o | |
| IO#pos, IO#tell | o | |
| IO#pos= | o | |
| IO#print | o | |
| IO#printf | o | |
| IO#putc | | |
| IO#puts | o | |
| IO#read | o | |
| IO#read_nonblock | | |
| IO#readbyte | o | |
| IO#readchar | o | |
| IO#readline | o | |
| IO#readlines | o | |
| IO#readpartial | | |
| IO#reopen | | |
| IO#rewind | | |
| IO#seek | o | |
| IO#set_encoding | | |
| IO#stat | | |
| IO#sync | o | |
| IO#sync= | o | |
| IO#sysread | o | |
| IO#sysseek | o | |
| IO#syswrite | o | |
| IO#to_io | | |
| IO#ungetbyte | o | |
| IO#ungetc | o | |
| IO#write | o | |
| IO#write_nonblock | | |
| IO#pid | o | |
| IO#pos, IO#tell | o | |
| IO#pos= | o | |
| IO#print | o | |
| IO#printf | o | |
| IO#putc | | |
| IO#puts | o | |
| IO#read | o | |
| IO#read_nonblock | | |
| IO#readbyte | o | |
| IO#readchar | o | |
| IO#readline | o | |
| IO#readlines | o | |
| IO#readpartial | | |
| IO#reopen | | |
| IO#rewind | | |
| IO#seek | o | |
| IO#set_encoding | | |
| IO#stat | | |
| IO#sync | o | |
| IO#sync= | o | |
| IO#sysread | o | |
| IO#sysseek | o | |
| IO#syswrite | o | |
| IO#to_io | | |
| IO#ungetbyte | o | |
| IO#ungetc | o | |
| IO#write | o | |
| IO#write_nonblock | | |
### File
* <https://doc.ruby-lang.org/ja/1.9.3/class/File.html>
| method | mruby-io | memo |
| --------------------------- | -------- | ---- |
| File.absolute_path | | |
| File.atime | | |
| File.basename | o | |
| method | mruby-io | memo |
|-----------------------------|----------|----------|
| File.absolute_path | | |
| File.atime | | |
| File.basename | o | |
| File.blockdev? | | FileTest |
| File.chardev? | | FileTest |
| File.chmod | o | |
| File.chown | | |
| File.ctime | | |
| File.delete, File.unlink | o | |
| File.directory? | o | FileTest |
| File.dirname | o | |
| File.chmod | o | |
| File.chown | | |
| File.ctime | | |
| File.delete, File.unlink | o | |
| File.directory? | o | FileTest |
| File.dirname | o | |
| File.executable? | | FileTest |
| File.executable_real? | | FileTest |
| File.exist?, exists? | o | FileTest |
| File.expand_path | o | |
| File.extname | o | |
| File.file? | o | FileTest |
| File.fnmatch, File.fnmatch? | | |
| File.ftype | | |
| File.exist?, exists? | o | FileTest |
| File.expand_path | o | |
| File.extname | o | |
| File.file? | o | FileTest |
| File.fnmatch, File.fnmatch? | | |
| File.ftype | | |
| File.grpowned? | | FileTest |
| File.identical? | | FileTest |
| File.join | o | |
| File.lchmod | | |
| File.lchown | | |
| File.link | | |
| File.lstat | | |
| File.mtime | | |
| File.new, File.open | o | |
| File.join | o | |
| File.lchmod | | |
| File.lchown | | |
| File.link | | |
| File.lstat | | |
| File.mtime | | |
| File.new, File.open | o | |
| File.owned? | | FileTest |
| File.path | | |
| File.pipe? | o | FileTest |
| File.path | | |
| File.pipe? | o | FileTest |
| File.readable? | | FileTest |
| File.readable_real? | | FileTest |
| File.readlink | o | |
| File.realdirpath | | |
| File.realpath | o | |
| File.rename | o | |
| File.readlink | o | |
| File.realdirpath | | |
| File.realpath | o | |
| File.rename | o | |
| File.setgid? | | FileTest |
| File.setuid? | | FileTest |
| File.size | o | |
| File.size? | o | FileTest |
| File.socket? | o | FileTest |
| File.split | | |
| File.stat | | |
| File.size | o | |
| File.size? | o | FileTest |
| File.socket? | o | FileTest |
| File.split | | |
| File.stat | | |
| File.sticky? | | FileTest |
| File.symlink | | |
| File.symlink? | o | FileTest |
| File.truncate | | |
| File.umask | o | |
| File.utime | | |
| File.world_readable? | | |
| File.world_writable? | | |
| File.symlink | | |
| File.symlink? | o | FileTest |
| File.truncate | | |
| File.umask | o | |
| File.utime | | |
| File.world_readable? | | |
| File.world_writable? | | |
| File.writable? | | FileTest |
| File.writable_real? | | FileTest |
| File.zero? | o | FileTest |
| File#atime | | |
| File#chmod | | |
| File#chown | | |
| File#ctime | | |
| File#flock | o | |
| File#lstat | | |
| File#mtime | | |
| File#path, File#to_path | o | |
| File#size | | |
| File#truncate | | |
| File.zero? | o | FileTest |
| File#atime | | |
| File#chmod | | |
| File#chown | | |
| File#ctime | | |
| File#flock | o | |
| File#lstat | | |
| File#mtime | | |
| File#path, File#to_path | o | |
| File#size | | |
| File#truncate | | |
## License
+1
View File
@@ -11,6 +11,7 @@
#include "mruby/variable.h"
#include "mruby/ext/io.h"
#include "mruby/error.h"
#include "mruby/internal.h"
#include "mruby/presym.h"
#include <sys/types.h>
+3 -2
View File
@@ -6,6 +6,7 @@
#include <mruby/string.h>
#include <mruby/numeric.h>
#include <mruby/proc.h>
#include <mruby/internal.h>
#include <mruby/presym.h>
static mrb_value
@@ -166,7 +167,7 @@ arg_error:
mrb_raise(mrb, E_ARGUMENT_ERROR, "base specified for non string value");
}
/* to raise TypeError */
return mrb_to_integer(mrb, val);
return mrb_ensure_integer_type(mrb, val);
}
#ifndef MRB_NO_FLOAT
@@ -190,7 +191,7 @@ mrb_f_float(mrb_state *mrb, mrb_value self)
if (mrb_string_p(arg)) {
return mrb_float_value(mrb, mrb_str_to_dbl(mrb, arg, TRUE));
}
return mrb_to_float(mrb, arg);
return mrb_ensure_float_type(mrb, arg);
}
#endif
+35
View File
@@ -5,6 +5,7 @@
#include "mruby/proc.h"
#include "mruby/class.h"
#include "mruby/string.h"
#include <mruby/internal.h>
#include "mruby/presym.h"
typedef enum {
@@ -575,6 +576,39 @@ mrb_mod_instance_methods(mrb_state *mrb, mrb_value mod)
return mrb_class_instance_method_list(mrb, recur, c);
}
static int
undefined_method_i(mrb_state *mrb, mrb_sym mid, mrb_method_t m, void *p)
{
mrb_value ary = *(mrb_value*)p;
if (MRB_METHOD_UNDEF_P(m)) {
mrb_ary_push(mrb, ary, mrb_symbol_value(mid));
}
return 0;
}
/*
* call-seq:
* mod.undefined_methods() -> array
*
* Returns an array containing the names of the undefined methods of the module/class.
*/
static mrb_value
mrb_mod_undefined_methods(mrb_state *mrb, mrb_value mod)
{
struct RClass *m = mrb_class_ptr(mod);
mrb_get_args(mrb, ""); /* no argument */
mrb_value ary = mrb_ary_new(mrb);
if (m->flags & MRB_FL_CLASS_IS_PREPENDED) {
MRB_CLASS_ORIGIN(m);
}
mrb_mt_foreach(mrb, m, undefined_method_i, (void*)&ary);
return ary;
}
/* 15.2.2.4.41 */
/*
* call-seq:
@@ -663,6 +697,7 @@ mrb_mruby_metaprog_gem_init(mrb_state* mrb)
mrb_define_method(mrb, mod, "class_variable_set", mrb_mod_cvar_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.18 */
mrb_define_method(mrb, mod, "included_modules", mrb_mod_included_modules, MRB_ARGS_NONE()); /* 15.2.2.4.30 */
mrb_define_method(mrb, mod, "instance_methods", mrb_mod_instance_methods, MRB_ARGS_ANY()); /* 15.2.2.4.33 */
mrb_define_method(mrb, mod, "undefined_instance_methods", mrb_mod_undefined_methods, MRB_ARGS_NONE());
mrb_define_method(mrb, mod, "remove_method", mrb_mod_remove_method, MRB_ARGS_ANY()); /* 15.2.2.4.41 */
mrb_define_method(mrb, mod, "method_removed", mrb_f_nil, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mod, "constants", mrb_mod_constants, MRB_ARGS_OPT(1)); /* 15.2.2.4.24 */
+1
View File
@@ -4,6 +4,7 @@
#include "mruby/variable.h"
#include "mruby/proc.h"
#include "mruby/string.h"
#include "mruby/internal.h"
#include "mruby/presym.h"
mrb_noreturn void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args);
+111 -12
View File
@@ -1,7 +1,39 @@
#include <mruby.h>
#include <mruby/numeric.h>
#include <mruby/internal.h>
#include <mruby/presym.h>
#ifdef MRB_USE_BIGINT
static mrb_value
bint_allbits(mrb_state *mrb, mrb_value x, mrb_value y)
{
y = mrb_as_bint(mrb, y);
x = mrb_bint_and(mrb, x, y);
if (mrb_bint_cmp(mrb, x, y) == 0) return mrb_true_value();
return mrb_false_value();
}
static mrb_value
bint_anybits(mrb_state *mrb, mrb_value x, mrb_value y)
{
y = mrb_as_bint(mrb, y);
x = mrb_bint_and(mrb, x, y);
if (mrb_bint_cmp(mrb, x, mrb_fixnum_value(0)) != 0)
return mrb_true_value();
return mrb_false_value();
}
static mrb_value
bint_nobits(mrb_state *mrb, mrb_value x, mrb_value y)
{
y = mrb_as_bint(mrb, y);
x = mrb_bint_and(mrb, x, y);
if (mrb_bint_cmp(mrb, x, mrb_fixnum_value(0)) == 0)
return mrb_true_value();
return mrb_false_value();
}
#endif
/*
* call-seq:
* int.allbits?(mask) -> true or false
@@ -11,6 +43,9 @@
static mrb_value
int_allbits(mrb_state *mrb, mrb_value self)
{
#ifdef MRB_USE_BIGINT
return bint_allbits(mrb, self, mrb_get_arg1(mrb));
#endif
mrb_int n, m;
mrb_get_args(mrb, "i", &m);
@@ -27,6 +62,9 @@ int_allbits(mrb_state *mrb, mrb_value self)
static mrb_value
int_anybits(mrb_state *mrb, mrb_value self)
{
#ifdef MRB_USE_BIGINT
return bint_anybits(mrb, self, mrb_get_arg1(mrb));
#endif
mrb_int n, m;
mrb_get_args(mrb, "i", &m);
@@ -43,6 +81,9 @@ int_anybits(mrb_state *mrb, mrb_value self)
static mrb_value
int_nobits(mrb_state *mrb, mrb_value self)
{
#ifdef MRB_USE_BIGINT
return bint_nobits(mrb, self, mrb_get_arg1(mrb));
#endif
mrb_int n, m;
mrb_get_args(mrb, "i", &m);
@@ -50,11 +91,9 @@ int_nobits(mrb_state *mrb, mrb_value self)
return mrb_bool_value((n & m) == 0);
}
static void
zerodiv(mrb_state *mrb)
{
mrb_raise(mrb, E_ZERODIV_ERROR, "divided by 0");
}
#ifndef MRB_NO_FLOAT
static mrb_value flo_remainder(mrb_state *mrb, mrb_value self);
#endif
/*
* call-seq:
@@ -70,24 +109,82 @@ int_remainder(mrb_state *mrb, mrb_value x)
mrb_value y = mrb_get_arg1(mrb);
mrb_int a, b;
#ifdef MRB_USE_BIGINT
if (mrb_bigint_p(x)) {
if (mrb_integer_p(y) || mrb_bigint_p(y)) {
return mrb_bint_rem(mrb, x, y);
}
return flo_remainder(mrb, mrb_float_value(mrb, mrb_as_float(mrb, x)));
}
#endif
a = mrb_integer(x);
if (mrb_integer_p(y)) {
b = mrb_integer(y);
if (b == 0) zerodiv(mrb);
if (b == 0) mrb_int_zerodiv(mrb);
if (a == MRB_INT_MIN && b == -1) return mrb_fixnum_value(0);
return mrb_int_value(mrb, a % b);
}
#ifdef MRB_NO_FLOAT
mrb_raise(mrb, E_TYPE_ERROR, "non integer remainder");
#else
mrb_float n = (mrb_float)a;
mrb_float m = mrb_as_float(mrb, y);
if (isinf(m)) return mrb_float_value(mrb, n);
return mrb_float_value(mrb, n-m*trunc(n/m));
return flo_remainder(mrb, mrb_float_value(mrb, mrb_as_float(mrb, x)));
#endif
}
mrb_value mrb_int_pow(mrb_state *mrb, mrb_value x);
/*
* call-seq:
* integer.pow(numeric) -> numeric
* integer.pow(integer, integer) -> integer
*
* Returns (modular) exponentiation as:
*
* a.pow(b) #=> same as a**b
* a.pow(b, m) #=> same as (a**b) % m, but avoids huge temporary values
*/
static mrb_value
int_powm(mrb_state *mrb, mrb_value x)
{
mrb_value m;
mrb_int base, exp, mod, result = 1;
if (mrb_get_argc(mrb) == 1) {
return mrb_int_pow(mrb, x);
}
mrb_get_args(mrb, "io", &exp, &m);
if (exp < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "int.pow(n,m): n must be positive");
#ifdef MRB_USE_BIGINT
if (mrb_bigint_p(x)) {
return mrb_bint_powm(mrb, x, exp, m);
}
if (mrb_bigint_p(m)) {
return mrb_bint_powm(mrb, mrb_bint_new_int(mrb, mrb_integer(x)), exp, m);
}
#endif
if (!mrb_integer_p(m)) mrb_raise(mrb, E_TYPE_ERROR, "int.pow(n,m): m must be integer");
mod = mrb_integer(m);
if (mod < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "int.pow(n,m): m must be positive");
if (mod == 0) mrb_int_zerodiv(mrb);
if (mod == 1) return mrb_fixnum_value(0);
base = mrb_integer(x);
for (;;) {
if (exp & 1) {
if (mrb_int_mul_overflow(result, base, &result)) {
mrb_int_overflow(mrb, "pow");
}
result %= mod;
}
exp >>= 1;
if (exp == 0) break;
if (mrb_int_mul_overflow(base, base, &base)) {
mrb_int_overflow(mrb, "pow");
}
base %= mod;
}
return mrb_int_value(mrb, result);
}
#ifndef MRB_NO_FLOAT
static mrb_value
flo_remainder(mrb_state *mrb, mrb_value self)
@@ -96,7 +193,7 @@ flo_remainder(mrb_state *mrb, mrb_value self)
a = mrb_float(self);
mrb_get_args(mrb, "f", &b);
if (b == 0) zerodiv(mrb);
if (b == 0) mrb_int_zerodiv(mrb);
if (isinf(b)) return mrb_float_value(mrb, a);
return mrb_float_value(mrb, a-b*trunc(a/b));
}
@@ -114,6 +211,8 @@ mrb_mruby_numeric_ext_gem_init(mrb_state* mrb)
mrb_define_alias(mrb, i, "modulo", "%");
mrb_define_method(mrb, i, "remainder", int_remainder, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, i, MRB_SYM(pow), int_powm, MRB_ARGS_ARG(1,1));
#ifndef MRB_NO_FLOAT
struct RClass *f = mrb_class_get(mrb, "Float");
@@ -19,3 +19,9 @@ assert('Integer#nonzero?') do
assert_equal nil, 0.nonzero?
assert_equal 1000, 1000.nonzero?
end
assert('Integer#pow') do
assert_equal(8, 2.pow(3))
assert_equal(-8, (-2).pow(3))
assert_equal(361, 9.pow(1024,1000))
end
+10 -8
View File
@@ -10,6 +10,7 @@
#include <mruby/proc.h>
#include <mruby/value.h>
#include <mruby/range.h>
#include <mruby/internal.h>
static size_t
os_memsize_of_irep(mrb_state* state, const struct mrb_irep *irep)
@@ -127,23 +128,24 @@ os_memsize_of_object(mrb_state* mrb, mrb_value obj)
case MRB_TT_INTEGER:
if (mrb_immediate_p(obj))
break;
case MRB_TT_RATIONAL:
case MRB_TT_RATIONAL:
#if defined(MRB_USE_RATIONAL)
#if defined(MRB_INT64) && defined(MRB_32BIT)
size += sizeof(mrb_int)*2;
size += sizeof(mrb_int)*2;
#endif
size += mrb_objspace_page_slot_size();
size += mrb_objspace_page_slot_size();
#endif
break;
break;
case MRB_TT_COMPLEX:
case MRB_TT_COMPLEX:
#if defined(MRB_USE_COMPLEX)
#if defined(MRB_32BIT) && !defined(MRB_USE_FLOAT32)
size += sizeof(mrb_float)*2;
size += sizeof(mrb_float)*2;
#endif
size += mrb_objspace_page_slot_size();
size += mrb_objspace_page_slot_size();
#endif
break;
break;
case MRB_TT_BIGINT:
case MRB_TT_DATA:
case MRB_TT_ISTRUCT:
size += mrb_objspace_page_slot_size();
+12 -10
View File
@@ -387,13 +387,13 @@ static int
pack_BER(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags)
{
mrb_int n = mrb_integer(o);
size_t i;
int i;
char *p;
if (n < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "can't compress negative numbers");
}
for (i=1; i<sizeof(mrb_int)+1; i++) {
for (i=1; i<(int)sizeof(mrb_int)+1; i++) {
mrb_int mask = ~((1L<<(7*i))-1);
if ((n & mask) == 0) break;
}
@@ -410,10 +410,12 @@ pack_BER(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int
static int
unpack_BER(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, unsigned int flags)
{
mrb_int i, n = 0;
int i;
mrb_int n = 0;
const unsigned char *p = src;
const unsigned char *e = p + srclen;
if (srclen == 0) return 0;
for (i=1; p<e; p++,i++) {
if (n > (MRB_INT_MAX>>7)) {
mrb_raise(mrb, E_RANGE_ERROR, "BER unpacking 'w' overflow");
@@ -620,6 +622,7 @@ utf8_to_uv(mrb_state *mrb, const char *p, long *lenp)
}
if (!(uv & 0x40)) {
*lenp = 1;
malformed:
mrb_raise(mrb, E_ARGUMENT_ERROR, "malformed UTF-8 character");
}
@@ -630,7 +633,7 @@ utf8_to_uv(mrb_state *mrb, const char *p, long *lenp)
else if (!(uv & 0x02)) { n = 6; uv &= 0x01; }
else {
*lenp = 1;
mrb_raise(mrb, E_ARGUMENT_ERROR, "malformed UTF-8 character");
goto malformed;
}
if (n > *lenp) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "malformed UTF-8 character (expected %d bytes, given %d bytes)",
@@ -642,7 +645,7 @@ utf8_to_uv(mrb_state *mrb, const char *p, long *lenp)
c = *p++ & 0xff;
if ((c & 0xc0) != 0x80) {
*lenp -= n + 1;
mrb_raise(mrb, E_ARGUMENT_ERROR, "malformed UTF-8 character");
goto malformed;
}
else {
c &= 0x3f;
@@ -1300,7 +1303,7 @@ alias:
mrb_raise(mrb, E_RUNTIME_ERROR, "too big template length");
}
count = (int)n;
tmpl->idx = e - tptr;
tmpl->idx = (int)(e - tptr);
continue;
} else if (ch == '*') {
if (type == PACK_TYPE_NONE)
@@ -1387,13 +1390,12 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary)
o = mrb_ary_ref(mrb, ary, aidx);
if (type == PACK_TYPE_INTEGER) {
o = mrb_to_integer(mrb, o);
o = mrb_ensure_int_type(mrb, o);
}
#ifndef MRB_NO_FLOAT
else if (type == PACK_TYPE_FLOAT) {
if (!mrb_float_p(o)) {
mrb_float f = mrb_as_float(mrb, o);
o = mrb_float_value(mrb, f);
o = mrb_ensure_float_type(mrb, o);
}
}
#endif
@@ -1524,7 +1526,7 @@ pack_unpack(mrb_state *mrb, mrb_value str, int single)
break;
}
while (count != 0) {
while (count != 0 && srcidx < srclen) {
if (srclen - srcidx < size) {
while (count-- > 0) {
mrb_ary_push(mrb, result, mrb_nil_value());
+28 -11
View File
@@ -137,7 +137,7 @@ random_rand(mrb_state *mrb, rand_state *t, mrb_int max)
}
static mrb_int
random_rand_i(mrb_state *mrb, rand_state *t, mrb_int max)
rand_i(rand_state *t, mrb_int max)
{
return rand_uint32(t) % max;
}
@@ -167,6 +167,7 @@ random_default(mrb_state *mrb) {
#define random_ptr(v) (rand_state*)mrb_istruct_ptr(v)
#define random_default_state(mrb) random_ptr(random_default(mrb))
#define ID_RANDOM_STRICT MRB_SYM(mruby_Random)
static mrb_value
random_m_init(mrb_state *mrb, mrb_value self)
@@ -241,14 +242,22 @@ random_m_bytes(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary)
{
mrb_int i, max;
rand_state *random;
if (RARRAY_LEN(ary) > 1) {
struct RClass *c = mrb_class_get_id(mrb, MRB_SYM(Random));
if (mrb_get_args(mrb, "|I", &random, c) == 0) {
mrb_int i, max;
mrb_value r;
rand_state *random;
struct RClass *c = mrb_class_get_id(mrb, ID_RANDOM_STRICT);
if (mrb_get_args(mrb, "|o", &r) == 0) {
random = random_default_state(mrb);
}
else if (mrb_obj_is_kind_of(mrb, r, c)){
random = (rand_state*)mrb_istruct_ptr(r);
}
else {
mrb_raise(mrb, E_TYPE_ERROR, "Random object required");
}
mrb_ary_modify(mrb, mrb_ary_ptr(ary));
max = RARRAY_LEN(ary);
for (i = RARRAY_LEN(ary) - 1; i > 0; i--) {
@@ -256,7 +265,7 @@ mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary)
mrb_value *ptr = RARRAY_PTR(ary);
mrb_value tmp;
j = random_rand_i(mrb, random, max);
j = rand_i(random, max);
tmp = ptr[i];
ptr[i] = ptr[j];
@@ -303,13 +312,20 @@ mrb_ary_sample(mrb_state *mrb, mrb_value ary)
{
mrb_int n = 0;
mrb_bool given;
mrb_value r;
rand_state *random;
mrb_int len;
struct RClass *c = mrb_class_get_id(mrb, MRB_SYM(Random));
struct RClass *c = mrb_class_get_id(mrb, ID_RANDOM_STRICT);
if (mrb_get_args(mrb, "|i?I", &n, &given, &random, c) < 2) {
if (mrb_get_args(mrb, "|i?o", &n, &given, &r) < 2) {
random = random_default_state(mrb);
}
else if (mrb_obj_is_kind_of(mrb, r, c)){
random = (rand_state*)mrb_istruct_ptr(r);
}
else {
mrb_raise(mrb, E_TYPE_ERROR, "Random object required");
}
len = RARRAY_LEN(ary);
if (!given) { /* pick one element */
switch (len) {
@@ -318,7 +334,7 @@ mrb_ary_sample(mrb_state *mrb, mrb_value ary)
case 1:
return RARRAY_PTR(ary)[0];
default:
return RARRAY_PTR(ary)[rand_uint32(random) % len];
return RARRAY_PTR(ary)[rand_i(random, len)];
}
}
else {
@@ -333,7 +349,7 @@ mrb_ary_sample(mrb_state *mrb, mrb_value ary)
for (;;) {
retry:
r = (mrb_int)(rand_uint32(random) % len);
r = rand_i(random, len);
for (j=0; j<i; j++) {
if (mrb_integer(RARRAY_PTR(result)[j]) == r) {
@@ -386,6 +402,7 @@ void mrb_mruby_random_gem_init(mrb_state *mrb)
mrb_define_method(mrb, mrb->kernel_module, "srand", random_f_srand, MRB_ARGS_OPT(1));
random = mrb_define_class(mrb, "Random", mrb->object_class);
mrb_const_set(mrb, mrb_obj_value(mrb->object_class), ID_RANDOM_STRICT, mrb_obj_value(random)); // for class check
MRB_SET_INSTANCE_TT(random, MRB_TT_ISTRUCT);
mrb_define_class_method(mrb, random, "rand", random_f_rand, MRB_ARGS_OPT(1));
mrb_define_class_method(mrb, random, "srand", random_f_srand, MRB_ARGS_OPT(1));
@@ -401,7 +418,7 @@ void mrb_mruby_random_gem_init(mrb_state *mrb)
mrb_define_method(mrb, array, "sample", mrb_ary_sample, MRB_ARGS_OPT(2));
mrb_const_set(mrb, mrb_obj_value(random), MRB_SYM(DEFAULT),
mrb_obj_new(mrb, random, 0, NULL));
mrb_obj_new(mrb, random, 0, NULL));
}
void mrb_mruby_random_gem_final(mrb_state *mrb)
+60 -23
View File
@@ -2,29 +2,33 @@
#include <mruby/range.h>
static mrb_bool
r_le(mrb_state *mrb, mrb_value a, mrb_value b)
r_less(mrb_state *mrb, mrb_value a, mrb_value b, mrb_bool excl)
{
mrb_int n = mrb_cmp(mrb, a, b);
if (n == 0 || n == -1) return TRUE;
return FALSE;
}
static mrb_bool
r_lt(mrb_state *mrb, mrb_value a, mrb_value b)
{
return mrb_cmp(mrb, a, b) == -1;
switch (mrb_cmp(mrb, a, b)) {
case -2: /* failure */
case 1:
return FALSE;
case 0:
return !excl;
case -1:
default: /* just in case */
return TRUE;
}
}
/*
* call-seq:
* rng.cover?(obj) -> true or false
* rng.cover?(range) -> true or false
*
* Returns <code>true</code> if +obj+ is between the begin and end of
* the range.
* Returns +true+ if the given argument is within +self+, +false+ otherwise.
*
* This tests <code>begin <= obj <= end</code> when #exclude_end? is +false+
* and <code>begin <= obj < end</code> when #exclude_end? is +true+.
* With non-range argument +object+, evaluates with <tt><=</tt> and <tt><</tt>.
*
* For range +self+ with included end value (<tt>#exclude_end? == false</tt>),
* evaluates thus:
*
* self.begin <= object <= self.end
*
* ("a".."z").cover?("c") #=> true
* ("a".."z").cover?("5") #=> false
@@ -40,20 +44,53 @@ range_cover(mrb_state *mrb, mrb_value range)
beg = RANGE_BEG(r);
end = RANGE_END(r);
if (r_le(mrb, beg, val)) {
if (mrb_nil_p(end)) {
if (mrb_nil_p(beg) && mrb_nil_p(end)) return mrb_true_value();
if (mrb_range_p(val)) {
struct RRange *r2 = mrb_range_ptr(mrb, val);
mrb_value beg2 = RANGE_BEG(r2);
mrb_value end2 = RANGE_END(r2);
/* range.cover?(nil..nil) => true */
if (mrb_nil_p(beg2) && mrb_nil_p(end2)) return mrb_true_value();
/* (a..b).cover?(c..d) */
if (mrb_nil_p(end)) { /* a.. */
/* (a..).cover?(c..) => true */
if (mrb_nil_p(end2)) return mrb_bool_value(mrb_cmp(mrb, beg, beg2) != -2);
/* (a..).cover?(c..d) where d<a => false */
if (r_less(mrb, end2, beg, RANGE_EXCL(r2))) return mrb_false_value();
return mrb_true_value();
}
if (RANGE_EXCL(r)) {
if (r_lt(mrb, val, end))
return mrb_true_value();
else if (mrb_nil_p(beg)) { /* ..b */
/* (..b).cover?(..d) => true */
if (mrb_nil_p(beg2)) return mrb_bool_value(mrb_cmp(mrb, end, end2) != -2);
/* (..b).cover?(c..d) where b<c => false */
if (r_less(mrb, end, beg2, RANGE_EXCL(r))) return mrb_false_value();
return mrb_true_value();
}
else {
if (r_le(mrb, val, end))
return mrb_true_value();
else { /* a..b */
/* (a..b).cover?(c..) => (c<b) */
if (mrb_nil_p(end2))
return mrb_bool_value(r_less(mrb, beg2, end, RANGE_EXCL(r)));
/* (a..b).cover?(..d) => (a<d) */
if (mrb_nil_p(beg2))
return mrb_bool_value(r_less(mrb, beg, end2, RANGE_EXCL(r2)));
/* (a..b).cover?(c..d) where (b<c) => false */
if (r_less(mrb, end, beg2, RANGE_EXCL(r))) return mrb_false_value();
/* (a..b).cover?(c..d) where (d<a) => false */
if (r_less(mrb, end2, beg, RANGE_EXCL(r2))) return mrb_false_value();
return mrb_true_value();
}
}
if (mrb_nil_p(beg) || r_less(mrb, beg, val, FALSE)) {
if (mrb_nil_p(end)) {
return mrb_true_value();
}
if (r_less(mrb, val, end, RANGE_EXCL(r)))
return mrb_true_value();
}
return mrb_false_value();
}
+15 -1
View File
@@ -3,11 +3,25 @@
assert('Range#cover?') do
assert_true ("a".."z").cover?("c")
assert_true !("a".."z").cover?("5")
assert_false ("a".."z").cover?("5")
assert_true ("a".."z").cover?("cc")
assert_false ("a".."z").cover?(nil)
assert_true ("a"..).cover?("c")
assert_false ("a"..).cover?("5")
assert_true ("a"..).cover?("cc")
assert_true (.."z").cover?("a")
assert_false (..."z").cover?("z")
assert_true (.."z").cover?("z")
assert_true (nil..nil).cover?(nil)
assert_true ("a".."c").cover?("b".."d")
assert_true ("a"..).cover?("b"..)
assert_false ("a"..).cover?(1..)
assert_false ("d"..).cover?(.."b")
assert_true (.."c").cover?("b".."d")
assert_true (.."c").cover?(.."d")
assert_false (.."c").cover?(..2)
assert_false (.."c").cover?("d"..)
end
assert('Range#first') do
+52 -84
View File
@@ -3,6 +3,13 @@
#include <mruby/numeric.h>
#include <mruby/presym.h>
mrb_value mrb_complex_new(mrb_state *, mrb_float, mrb_float);
mrb_bool mrb_complex_eq(mrb_state *mrb, mrb_value, mrb_value);
mrb_value mrb_complex_add(mrb_state *mrb, mrb_value, mrb_value);
mrb_value mrb_complex_sub(mrb_state *mrb, mrb_value, mrb_value);
mrb_value mrb_complex_mul(mrb_state *mrb, mrb_value, mrb_value);
mrb_value mrb_complex_div(mrb_state *mrb, mrb_value, mrb_value);
struct mrb_rational {
mrb_int numerator;
mrb_int denominator;
@@ -393,7 +400,6 @@ rational_eq(mrb_state *mrb, mrb_value x)
#ifdef MRB_USE_COMPLEX
case MRB_TT_COMPLEX:
{
mrb_bool mrb_complex_eq(mrb_state *mrb, mrb_value, mrb_value);
result = mrb_complex_eq(mrb, y, mrb_rational_to_f(mrb, x));
break;
}
@@ -405,10 +411,6 @@ rational_eq(mrb_state *mrb, mrb_value x)
return mrb_bool_value(result);
}
#ifndef MRB_NO_FLOAT
mrb_value mrb_complex_new(mrb_state *, mrb_float, mrb_float);
#endif
static mrb_value
rational_cmp(mrb_state *mrb, mrb_value x)
{
@@ -454,11 +456,6 @@ rational_cmp(mrb_state *mrb, mrb_value x)
return mrb_fixnum_value(-1);
return mrb_fixnum_value(0);
}
#endif
#ifdef MRB_USE_COMPLEX
case MRB_TT_COMPLEX:
x = mrb_complex_new(mrb, rat_float(p1), 0);
return mrb_funcall_id(mrb, x, MRB_OPSYM(cmp), 1, y);
#endif
default:
x = mrb_funcall_id(mrb, y, MRB_OPSYM(cmp), 1, x);
@@ -479,11 +476,10 @@ rational_minus(mrb_state *mrb, mrb_value x)
return rational_new(mrb, -n, p->denominator);
}
static mrb_value
rational_add(mrb_state *mrb, mrb_value x)
mrb_value
mrb_rational_add(mrb_state *mrb, mrb_value x, mrb_value y)
{
struct mrb_rational *p1 = rational_ptr(mrb, x);
mrb_value y = mrb_get_arg1(mrb);
switch (mrb_type(y)) {
case MRB_TT_INTEGER:
@@ -513,16 +509,27 @@ rational_add(mrb_state *mrb, mrb_value x)
}
#endif
#if defined(MRB_USE_COMPLEX)
case MRB_TT_COMPLEX:
return mrb_complex_add(mrb, mrb_complex_new(mrb, rat_float(p1), 0), y);
#endif
default:
return mrb_funcall_id(mrb, y, MRB_OPSYM(add), 1, x);
}
}
static mrb_value
rational_sub(mrb_state *mrb, mrb_value x)
rational_add(mrb_state *mrb, mrb_value x)
{
mrb_value y = mrb_get_arg1(mrb);
return mrb_rational_add(mrb, x, y);
}
mrb_value
mrb_rational_sub(mrb_state *mrb, mrb_value x, mrb_value y)
{
struct mrb_rational *p1 = rational_ptr(mrb, x);
mrb_value y = mrb_get_arg1(mrb);
switch (mrb_type(y)) {
case MRB_TT_INTEGER:
@@ -546,8 +553,7 @@ rational_sub(mrb_state *mrb, mrb_value x)
#if defined(MRB_USE_COMPLEX)
case MRB_TT_COMPLEX:
x = mrb_complex_new(mrb, rat_float(p1), 0);
return mrb_funcall_id(mrb, x, MRB_OPSYM(sub), 1, y);
return mrb_complex_sub(mrb, mrb_complex_new(mrb, rat_float(p1), 0), y);
#endif
#ifndef MRB_NO_FLOAT
@@ -565,10 +571,16 @@ rational_sub(mrb_state *mrb, mrb_value x)
}
static mrb_value
rational_mul(mrb_state *mrb, mrb_value x)
rational_sub(mrb_state *mrb, mrb_value x)
{
mrb_value y = mrb_get_arg1(mrb);
return mrb_rational_sub(mrb, x, y);
}
mrb_value
mrb_rational_mul(mrb_state *mrb, mrb_value x, mrb_value y)
{
struct mrb_rational *p1 = rational_ptr(mrb, x);
mrb_value y = mrb_get_arg1(mrb);
switch (mrb_type(y)) {
case MRB_TT_INTEGER:
@@ -595,16 +607,27 @@ rational_mul(mrb_state *mrb, mrb_value x)
}
#endif
#if defined(MRB_USE_COMPLEX)
case MRB_TT_COMPLEX:
return mrb_complex_mul(mrb, mrb_complex_new(mrb, rat_float(p1), 0), y);
#endif
default:
return mrb_funcall_id(mrb, y, MRB_OPSYM(mul), 1, x);
}
}
static mrb_value
rational_mul(mrb_state *mrb, mrb_value x)
{
mrb_value y = mrb_get_arg1(mrb);
return mrb_rational_mul(mrb, x, y);
}
mrb_value
mrb_rational_div(mrb_state *mrb, mrb_value x)
mrb_rational_div(mrb_state *mrb, mrb_value x, mrb_value y)
{
struct mrb_rational *p1 = rational_ptr(mrb, x);
mrb_value y = mrb_get_arg1(mrb);
switch (mrb_type(y)) {
case MRB_TT_INTEGER:
@@ -625,8 +648,7 @@ mrb_rational_div(mrb_state *mrb, mrb_value x)
#if defined(MRB_USE_COMPLEX)
case MRB_TT_COMPLEX:
x = mrb_complex_new(mrb, rat_float(p1), 0);
return mrb_funcall_id(mrb, x, MRB_OPSYM(div), 1, y);
return mrb_complex_div(mrb, mrb_complex_new(mrb, rat_float(p1), 0), y);
#endif
default:
@@ -642,65 +664,15 @@ mrb_rational_div(mrb_state *mrb, mrb_value x)
}
}
#define rational_div mrb_rational_div
static mrb_value
rational_div(mrb_state *mrb, mrb_value x)
{
mrb_value y = mrb_get_arg1(mrb);
return mrb_rational_div(mrb, x, y);
}
mrb_int mrb_div_int(mrb_state *, mrb_int, mrb_int);
#ifndef MRB_USE_COMPLEX
/* 15.2.8.3.4 */
/*
* redefine Integer#/
*/
static mrb_value
rational_int_div(mrb_state *mrb, mrb_value x)
{
mrb_value y = mrb_get_arg1(mrb);
mrb_int a = mrb_integer(x);
if (mrb_integer_p(y)) {
mrb_int div = mrb_div_int(mrb, a, mrb_integer(y));
return mrb_int_value(mrb, div);
}
switch (mrb_type(y)) {
case MRB_TT_RATIONAL:
return rational_div(mrb, rational_new(mrb, a, 1));
default:
#ifdef MRB_NO_FLOAT
case MRB_TT_FLOAT:
mrb_raise(mrb, E_TYPE_ERROR, "non integer multiplication");
#else
return mrb_float_value(mrb, mrb_div_float((mrb_float)a, mrb_as_float(mrb, y)));
#endif
}
}
/* 15.2.9.3.19(x) */
/*
* redefine Integer#quo
*/
static mrb_value
rational_int_quo(mrb_state *mrb, mrb_value x)
{
mrb_value y = mrb_get_arg1(mrb);
mrb_int a = mrb_integer(x);
if (mrb_integer_p(y)) {
return rational_new(mrb, a, mrb_integer(y));
}
switch (mrb_type(y)) {
case MRB_TT_RATIONAL:
x = rational_new(mrb, a, 1);
return mrb_funcall_id(mrb, x, MRB_OPSYM(div), 1, y);
default:
#ifdef MRB_NO_FLOAT
mrb_raise(mrb, E_TYPE_ERROR, "non integer multiplication");
#else
return mrb_float_value(mrb, mrb_div_float((mrb_float)a, mrb_as_float(mrb, y)));
#endif
}
}
#endif /* !MRB_USE_COMPLEX */
void mrb_mruby_rational_gem_init(mrb_state *mrb)
{
struct RClass *rat;
@@ -726,10 +698,6 @@ void mrb_mruby_rational_gem_init(mrb_state *mrb)
mrb_define_method(mrb, rat, "/", rational_div, MRB_ARGS_REQ(1));
mrb_define_method(mrb, rat, "quo", rational_div, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mrb->integer_class, "to_r", fix_to_r, MRB_ARGS_NONE());
#ifndef MRB_USE_COMPLEX
mrb_define_method(mrb, mrb->integer_class, "/", rational_int_div, MRB_ARGS_REQ(1)); /* override */
mrb_define_method(mrb, mrb->integer_class, "quo", rational_int_quo, MRB_ARGS_REQ(1)); /* override */
#endif
mrb_define_method(mrb, mrb->kernel_module, "Rational", rational_m, MRB_ARGS_ARG(1,1));
}
+1 -1
View File
@@ -95,7 +95,7 @@ mrb_f_usleep(mrb_state *mrb, mrb_value self)
if (usec >= 0) {
usleep(usec);
} else {
mrb_raise(mrb, E_ARGUMENT_ERROR, "time interval must not be negative integer");
mrb_raise(mrb, E_ARGUMENT_ERROR, "time interval must not be negative");
}
#ifdef _WIN32
+11 -15
View File
@@ -38,6 +38,7 @@
#include "mruby/string.h"
#include "mruby/variable.h"
#include "mruby/error.h"
#include "mruby/internal.h"
#include "mruby/presym.h"
#include "mruby/ext/io.h"
@@ -52,12 +53,6 @@
#define E_SOCKET_ERROR mrb_class_get_id(mrb, MRB_SYM(SocketError))
#if !defined(mrb_cptr)
#define mrb_cptr_value(m,p) mrb_voidp_value((m),(p))
#define mrb_cptr(o) mrb_voidp(o)
#define mrb_cptr_p(o) mrb_voidp_p(o)
#endif
#ifdef _WIN32
static const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
{
@@ -262,10 +257,12 @@ sa2addrlist(mrb_state *mrb, const struct sockaddr *sa, socklen_t salen)
return ary;
}
int mrb_io_fileno(mrb_state *mrb, mrb_value io);
static int
socket_fd(mrb_state *mrb, mrb_value sock)
{
return (int)mrb_integer(mrb_funcall_id(mrb, sock, MRB_SYM(fileno), 0));
return mrb_io_fileno(mrb, sock);
}
static int
@@ -468,9 +465,10 @@ mrb_basicsocket_setsockopt(mrb_state *mrb, mrb_value self)
} else if (argc == 1) {
if (strcmp(mrb_obj_classname(mrb, so), "Socket::Option") != 0)
mrb_raise(mrb, E_ARGUMENT_ERROR, "not an instance of Socket::Option");
level = mrb_integer(mrb_funcall_id(mrb, so, MRB_SYM(level), 0));
optname = mrb_integer(mrb_funcall_id(mrb, so, MRB_SYM(optname), 0));
level = mrb_as_int(mrb, mrb_funcall_id(mrb, so, MRB_SYM(level), 0));
optname = mrb_as_int(mrb, mrb_funcall_id(mrb, so, MRB_SYM(optname), 0));
optval = mrb_funcall_id(mrb, so, MRB_SYM(data), 0);
mrb_ensure_string_type(mrb, optval);
} else {
mrb_argnum_error(mrb, argc, 3, 3);
}
@@ -515,9 +513,8 @@ mrb_ipsocket_ntop(mrb_state *mrb, mrb_value klass)
char buf[50];
mrb_get_args(mrb, "is", &af, &addr, &n);
if ((af == AF_INET && n != 4) || (af == AF_INET6 && n != 16))
mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid address");
if (inet_ntop((int)af, addr, buf, sizeof(buf)) == NULL)
if ((af == AF_INET && n != 4) || (af == AF_INET6 && n != 16) ||
inet_ntop((int)af, addr, buf, sizeof(buf)) == NULL)
mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid address");
return mrb_str_new_cstr(mrb, buf);
}
@@ -530,8 +527,7 @@ mrb_ipsocket_pton(mrb_state *mrb, mrb_value klass)
char buf[50];
mrb_get_args(mrb, "is", &af, &bp, &n);
if ((size_t)n > sizeof(buf) - 1)
mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid address");
if ((size_t)n > sizeof(buf) - 1) goto invalid;
memcpy(buf, bp, n);
buf[n] = '\0';
@@ -623,7 +619,7 @@ mrb_socket_accept2(mrb_state *mrb, mrb_value klass)
mrb_get_args(mrb, "i", &s0);
socklen = sizeof(struct sockaddr_storage);
sastr = mrb_str_new_capa(mrb, socklen);
sastr = mrb_str_new_capa(mrb, (mrb_int)socklen);
s1 = (int)accept(s0, (struct sockaddr *)RSTRING_PTR(sastr), &socklen);
if (s1 == -1) {
mrb_sys_fail(mrb, "accept");
+4 -2
View File
@@ -1002,12 +1002,14 @@ retry:
}
break;
#ifndef MRB_NO_FLOAT
case 'f':
case 'g':
case 'G':
case 'e':
case 'E': {
#ifdef MRB_NO_FLOAT
mrb_raisef(mrb, E_ARGUMENT_ERROR, "%%%c not supported with MRB_NO_FLOAT defined", *p);
#else
mrb_value val = GETARG();
double fval;
mrb_int need = 6;
@@ -1077,9 +1079,9 @@ retry:
mrb_raise(mrb, E_RUNTIME_ERROR, "formatting error");
}
blen += n;
#endif
}
break;
#endif
}
flags = FNONE;
}
+1
View File
@@ -4,6 +4,7 @@
#include <mruby/class.h>
#include <mruby/string.h>
#include <mruby/range.h>
#include <mruby/internal.h>
#define ENC_ASCII_8BIT "ASCII-8BIT"
#define ENC_BINARY "BINARY"
+1
View File
@@ -13,6 +13,7 @@
#include <mruby/hash.h>
#include <mruby/range.h>
#include <mruby/proc.h>
#include <mruby/internal.h>
#include <mruby/presym.h>
#define RSTRUCT_LEN(st) RARRAY_LEN(st)
+1
View File
@@ -1,6 +1,7 @@
#include <mruby.h>
#include <mruby/array.h>
#include <mruby/string.h>
#include <mruby/internal.h>
#ifdef MRB_USE_ALL_SYMBOLS
# include <mruby/presym.h>
#endif
+11 -3
View File
@@ -56,10 +56,18 @@ istruct_test_test_receive(mrb_state *mrb, mrb_value self)
static mrb_value
istruct_test_test_receive_direct(mrb_state *mrb, mrb_value self)
{
char *ptr;
mrb_value is;
struct RClass *klass = mrb_class_get(mrb, "InlineStructTest");
mrb_get_args(mrb, "I", &ptr, klass);
return mrb_bool_value(ptr[0] == 's');
mrb_get_args(mrb, "o", &is);
/* if you need to protect istruct retrieval from untrusted code,
you need to care about class replacing.
See mrbgem/mruby-random/src/random.c for detail */
if (mrb_istruct_p(is) && mrb_obj_is_kind_of(mrb, is, klass)) {
char *ptr = (char*)mrb_istruct_ptr(is);;
return mrb_bool_value(ptr[0] == 's');
}
mrb_raise(mrb, E_TYPE_ERROR, "InlineStructTest");
return mrb_false_value();
}
static mrb_value
+11 -4
View File
@@ -459,7 +459,7 @@ time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday,
#define OUTINT(x) 0
#endif
if (OUTINT(ayear-1900) ||
if (ayear < 1900 || OUTINT(ayear-1900) ||
amonth < 1 || amonth > 12 ||
aday < 1 || aday > 31 ||
ahour < 0 || ahour > 24 ||
@@ -476,14 +476,21 @@ time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday,
nowtime.tm_sec = (int)asec;
nowtime.tm_isdst = -1;
time_t (*mk)(struct tm*);
if (timezone == MRB_TIMEZONE_UTC) {
nowsecs = timegm(&nowtime);
mk = timegm;
}
else {
nowsecs = mktime(&nowtime);
mk = mktime;
}
nowsecs = (*mk)(&nowtime);
if (nowsecs == (time_t)-1) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "Not a valid time");
nowtime.tm_sec += 1; /* maybe Epoch-1 sec */
nowsecs = (*mk)(&nowtime);
if (nowsecs != 0) { /* check if Epoch */
mrb_raise(mrb, E_ARGUMENT_ERROR, "Not a valid time");
}
nowsecs = (time_t)-1; /* valid Epoch-1 */
}
return time_alloc_time(mrb, nowsecs, ausec, timezone);
-4
View File
@@ -267,7 +267,3 @@ assert('2000 times 500us make a second') do
end
assert_equal(0, t.usec)
end
assert('Time.gm with Dec 31 23:59:59 1969 raise ArgumentError') do
assert_raise(ArgumentError) {Time.gm(1969, 12, 31, 23, 59, 59)}
end
+3
View File
@@ -51,4 +51,7 @@ MRuby::GemBox.new do |conf|
# Use class/module extension
conf.gem :core => "mruby-class-ext"
# Use errno extension
conf.gem :core => "mruby-errno"
end
+4 -2
View File
@@ -22,7 +22,8 @@ class Module
# 15.2.2.4.27
def include(*args)
args.reverse.each do |m|
args.reverse!
args.each do |m|
m.append_features(self)
m.included(self)
end
@@ -30,7 +31,8 @@ class Module
end
def prepend(*args)
args.reverse.each do |m|
args.reverse!
args.each do |m|
m.prepend_features(self)
m.prepended(self)
end
+35
View File
@@ -0,0 +1,35 @@
module Kernel
##
# call-seq:
# obj.extend(module, ...) -> obj
#
# Adds to _obj_ the instance methods from each module given as a
# parameter.
#
# module Mod
# def hello
# "Hello from Mod.\n"
# end
# end
#
# class Klass
# def hello
# "Hello from Klass.\n"
# end
# end
#
# k = Klass.new
# k.hello #=> "Hello from Klass.\n"
# k.extend(Mod) #=> #<Klass:0x401b3bc8>
# k.hello #=> "Hello from Mod.\n"
#
# ISO 15.3.1.3.13
def extend(*args)
args.reverse!
args.each do |m|
m.extend_object(self)
m.extended(self)
end
self
end
end
+13
View File
@@ -1,3 +1,16 @@
class Exception
##
# call-seq:
# exception.message -> string
#
# Returns the result of invoking <code>exception.to_s</code>.
# Normally this returns the exception's message or name.
#
def message
to_s
end
end
# ISO 15.2.24
class ArgumentError < StandardError
end
+8 -4
View File
@@ -167,10 +167,14 @@ class Array
n = other.size
len = n if len > n
i = 0
while i < len
n = (self[i] <=> other[i])
return n if n.nil? || n != 0
i += 1
begin
while i < len
n = (self[i] <=> other[i])
return n if n.nil? || n != 0
i += 1
end
rescue NoMethodError
return nil
end
len = self.size - other.size
if len == 0
+2 -3
View File
@@ -150,10 +150,9 @@ class String
# Call the given block for each byte of +self+.
def each_byte(&block)
return to_enum(:each_byte, &block) unless block
bytes = self.bytes
pos = 0
while pos < bytes.size
block.call(bytes[pos])
while pos < bytesize
block.call(getbyte(pos))
pos += 1
end
self
+32 -19
View File
@@ -10,6 +10,7 @@
#include <mruby/string.h>
#include <mruby/range.h>
#include <mruby/proc.h>
#include <mruby/internal.h>
#include <mruby/presym.h>
#include "value_array.h"
@@ -18,15 +19,26 @@
#define ARY_C_MAX_SIZE (SIZE_MAX / sizeof(mrb_value))
#define ARY_MAX_SIZE ((mrb_int)((ARY_C_MAX_SIZE < (size_t)MRB_INT_MAX) ? ARY_C_MAX_SIZE : MRB_INT_MAX-1))
static void
ary_too_big(mrb_state *mrb)
{
mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
}
static void
ary_check_too_big(mrb_state *mrb, mrb_int a, mrb_int b)
{
if (a > ARY_MAX_SIZE - b || a < 0)
ary_too_big(mrb);
}
static struct RArray*
ary_new_capa(mrb_state *mrb, mrb_int capa)
{
struct RArray *a;
size_t blen;
if (capa > ARY_MAX_SIZE) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
}
ary_check_too_big(mrb, capa, 0);
blen = capa * sizeof(mrb_value);
a = MRB_OBJ_ALLOC(mrb, MRB_TT_ARRAY, mrb->array_class);
@@ -188,11 +200,7 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, mrb_int len)
{
mrb_int capa = ARY_CAPA(a);
if (len > ARY_MAX_SIZE || len < 0) {
size_error:
mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
}
ary_check_too_big(mrb, len, 0);
if (capa < ARY_DEFAULT_LEN) {
capa = ARY_DEFAULT_LEN;
}
@@ -205,7 +213,7 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, mrb_int len)
}
}
if (capa < len || capa > ARY_MAX_SIZE) {
goto size_error;
ary_too_big(mrb);
}
if (ARY_EMBED_P(a)) {
@@ -302,9 +310,7 @@ ary_concat(mrb_state *mrb, struct RArray *a, struct RArray *a2)
ary_replace(mrb, a, a2);
return;
}
if (ARY_LEN(a2) > ARY_MAX_SIZE - ARY_LEN(a)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
}
ary_check_too_big(mrb, ARY_LEN(a2), ARY_LEN(a));
len = ARY_LEN(a) + ARY_LEN(a2);
ary_modify(mrb, a);
@@ -343,9 +349,7 @@ mrb_ary_plus(mrb_state *mrb, mrb_value self)
mrb_int blen, len1;
mrb_get_args(mrb, "a", &ptr, &blen);
if (ARY_MAX_SIZE - blen < ARY_LEN(a1)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
}
ary_check_too_big(mrb, ARY_LEN(a1), blen);
len1 = ARY_LEN(a1);
a2 = ary_new_capa(mrb, len1 + blen);
array_copy(ARY_PTR(a2), ARY_PTR(a1), len1);
@@ -425,16 +429,22 @@ mrb_ary_times(mrb_state *mrb, mrb_value self)
{
struct RArray *a1 = mrb_ary_ptr(self);
struct RArray *a2;
mrb_value *ptr;
mrb_value *ptr, sep, tmp;
mrb_int times, len1;
mrb_get_args(mrb, "o", &sep);
tmp = mrb_check_string_type(mrb, sep);
if (!mrb_nil_p(tmp)) {
return mrb_ary_join(mrb, self, tmp);
}
mrb_get_args(mrb, "i", &times);
if (times < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument");
}
if (times == 0) return mrb_ary_new(mrb);
if (ARY_MAX_SIZE / times < ARY_LEN(a1)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
ary_too_big(mrb);
}
len1 = ARY_LEN(a1);
a2 = ary_new_capa(mrb, len1 * times);
@@ -710,6 +720,9 @@ mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val)
mrb_raisef(mrb, E_INDEX_ERROR, "index %i out of array", n - len);
}
}
if (n >= ARY_MAX_SIZE) {
mrb_raise(mrb, E_INDEX_ERROR, "index too big");
}
if (len <= n) {
if (ARY_CAPA(a) <= n)
ary_expand_capa(mrb, a, n + 1);
@@ -834,7 +847,7 @@ ary_subseq(mrb_state *mrb, struct RArray *a, mrb_int beg, mrb_int len)
return mrb_ary_new_from_values(mrb, len, ARY_PTR(a)+beg);
}
ary_make_shared(mrb, a);
b = MRB_OBJ_ALLOC(mrb, MRB_TT_ARRAY, mrb->array_class);
b = MRB_OBJ_ALLOC(mrb, MRB_TT_ARRAY, mrb->array_class);
b->as.heap.ptr = a->as.heap.ptr + beg;
b->as.heap.len = len;
b->as.heap.aux.shared = a->as.heap.aux.shared;
@@ -1003,7 +1016,7 @@ mrb_ary_aset(mrb_state *mrb, mrb_value self)
return v3;
}
static mrb_value
mrb_value
mrb_ary_delete_at(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self);
+42 -36
View File
@@ -14,6 +14,7 @@
#include <mruby/error.h>
#include <mruby/numeric.h>
#include <mruby/data.h>
#include <mruby/internal.h>
#include <mruby/presym.h>
struct backtrace_location {
@@ -26,8 +27,7 @@ typedef void (*each_backtrace_func)(mrb_state*, const struct backtrace_location*
static const mrb_data_type bt_type = { "Backtrace", mrb_free };
mrb_value mrb_exc_inspect(mrb_state *mrb, mrb_value exc);
mrb_value mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace);
struct RObject *mrb_unpack_backtrace(mrb_state *mrb, struct RObject *backtrace);
static void
each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, each_backtrace_func func, void *data)
@@ -97,17 +97,17 @@ each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, each_backtrace_func func, void *
#ifndef MRB_NO_STDIO
static void
print_backtrace(mrb_state *mrb, struct RObject *exc, mrb_value backtrace)
print_backtrace(mrb_state *mrb, struct RObject *exc, struct RArray *backtrace)
{
mrb_int i;
mrb_int n = RARRAY_LEN(backtrace);
mrb_int n = ARY_LEN(backtrace);
mrb_value *loc, mesg;
if (n != 0) {
if (n > 1) {
fprintf(stderr, "trace (most recent call last):\n");
}
for (i=n-1,loc=&RARRAY_PTR(backtrace)[i]; i>0; i--,loc--) {
for (i=n-1,loc=&ARY_PTR(backtrace)[i]; i>0; i--,loc--) {
if (mrb_string_p(*loc)) {
fprintf(stderr, "\t[%d] %.*s\n",
(int)i, (int)RSTRING_LEN(*loc), RSTRING_PTR(*loc));
@@ -130,16 +130,14 @@ print_backtrace(mrb_state *mrb, struct RObject *exc, mrb_value backtrace)
MRB_API void
mrb_print_backtrace(mrb_state *mrb)
{
mrb_value backtrace;
if (!mrb->exc) {
return;
}
backtrace = mrb_obj_iv_get(mrb, mrb->exc, MRB_SYM(backtrace));
if (mrb_nil_p(backtrace)) return;
if (!mrb_array_p(backtrace)) backtrace = mrb_unpack_backtrace(mrb, backtrace);
print_backtrace(mrb, mrb->exc, backtrace);
struct RObject *backtrace = ((struct RException*)mrb->exc)->backtrace;
if (!backtrace) return;
if (backtrace->tt != MRB_TT_ARRAY) backtrace = mrb_unpack_backtrace(mrb, backtrace);
print_backtrace(mrb, mrb->exc, (struct RArray*)backtrace);
}
#else
@@ -172,7 +170,7 @@ pack_backtrace_i(mrb_state *mrb,
*pptr = ptr+1;
}
static mrb_value
static struct RObject*
packed_backtrace(mrb_state *mrb)
{
struct RData *backtrace;
@@ -183,44 +181,51 @@ packed_backtrace(mrb_state *mrb)
each_backtrace(mrb, ciidx, count_backtrace_i, &len);
size = len * sizeof(struct backtrace_location);
backtrace = mrb_data_object_alloc(mrb, NULL, NULL, &bt_type);
ptr = mrb_malloc(mrb, size);
backtrace = mrb_data_object_alloc(mrb, NULL, ptr, &bt_type);
backtrace->data = ptr;
backtrace->flags = (uint32_t)len;
each_backtrace(mrb, ciidx, pack_backtrace_i, &ptr);
return mrb_obj_value(backtrace);
return (struct RObject*)backtrace;
}
static void
store_backtrace(mrb_state *mrb, mrb_value exc, struct RObject *backtrace)
{
struct RException *e = mrb_exc_ptr(exc);
e->backtrace = backtrace;
mrb_field_write_barrier(mrb, (struct RBasic*)e, (struct RBasic*)backtrace);
}
void
mrb_keep_backtrace(mrb_state *mrb, mrb_value exc)
{
mrb_sym sym = MRB_SYM(backtrace);
mrb_value backtrace;
int ai;
if (mrb_iv_defined(mrb, exc, sym)) return;
if (mrb_exc_ptr(exc)->backtrace) return;
ai = mrb_gc_arena_save(mrb);
backtrace = packed_backtrace(mrb);
mrb_iv_set(mrb, exc, sym, backtrace);
struct RObject *backtrace = packed_backtrace(mrb);
store_backtrace(mrb, exc, backtrace);
mrb_gc_arena_restore(mrb, ai);
}
mrb_value
mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace)
struct RObject*
mrb_unpack_backtrace(mrb_state *mrb, struct RObject *backtrace)
{
const struct backtrace_location *bt;
mrb_int n, i;
int ai;
if (mrb_nil_p(backtrace)) {
if (backtrace == NULL) {
empty_backtrace:
return mrb_ary_new_capa(mrb, 0);
return mrb_obj_ptr(mrb_ary_new_capa(mrb, 0));
}
if (mrb_array_p(backtrace)) return backtrace;
bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, backtrace, &bt_type);
if (backtrace->tt == MRB_TT_ARRAY) return backtrace;
bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, mrb_obj_value(backtrace), &bt_type);
if (bt == NULL) goto empty_backtrace;
n = (mrb_int)RDATA(backtrace)->flags;
n = (mrb_int)backtrace->flags;
if (n == 0) goto empty_backtrace;
backtrace = mrb_ary_new_capa(mrb, n);
backtrace = mrb_obj_ptr(mrb_ary_new_capa(mrb, n));
ai = mrb_gc_arena_save(mrb);
for (i = 0; i < n; i++) {
const struct backtrace_location *entry = &bt[i];
@@ -236,7 +241,7 @@ mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace)
mrb_str_cat_lit(mrb, btline, ":in ");
mrb_str_cat_cstr(mrb, btline, mrb_sym_name(mrb, entry->method_id));
}
mrb_ary_push(mrb, backtrace, btline);
mrb_ary_push(mrb, mrb_obj_value(backtrace), btline);
mrb_gc_arena_restore(mrb, ai);
}
@@ -246,20 +251,21 @@ mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace)
mrb_value
mrb_exc_backtrace(mrb_state *mrb, mrb_value exc)
{
mrb_value backtrace;
backtrace = mrb_iv_get(mrb, exc, MRB_SYM(backtrace));
if (mrb_nil_p(backtrace) || mrb_array_p(backtrace)) {
return backtrace;
struct RObject *backtrace = mrb_exc_ptr(exc)->backtrace;
if (backtrace == NULL) {
return mrb_nil_value();
}
if (backtrace->tt == MRB_TT_ARRAY) {
return mrb_obj_value(backtrace);
}
/* unpack packed-backtrace */
backtrace = mrb_unpack_backtrace(mrb, backtrace);
mrb_iv_set(mrb, exc, MRB_SYM(backtrace), backtrace);
return backtrace;
store_backtrace(mrb, exc, backtrace);
return mrb_obj_value(backtrace);
}
mrb_value
mrb_get_backtrace(mrb_state *mrb)
{
return mrb_unpack_backtrace(mrb, packed_backtrace(mrb));
return mrb_obj_value(mrb_unpack_backtrace(mrb, packed_backtrace(mrb)));
}
+4 -3
View File
@@ -9,6 +9,7 @@
#include <mruby/dump.h>
#include <mruby/irep.h>
#include <mruby/debug.h>
#include <mruby/internal.h>
#include <string.h>
@@ -302,7 +303,7 @@ cdump_debug(mrb_state *mrb, const char *name, int n, mrb_irep_debug_info *info,
line_type = "mrb_debug_line_flat_map";
fprintf(fp, "static struct mrb_irep_debug_info_line %s_debug_lines_%d[%d] = {", name, n, len);
for (i=0; i<len; i++) {
mrb_irep_debug_info_line *fmap = &info->files[0]->lines.flat_map[i];
const mrb_irep_debug_info_line *fmap = &info->files[0]->lines.flat_map[i];
fprintf(fp, "\t{.start_pos=0x%04x,.line=%d},\n", fmap->start_pos, fmap->line);
}
fputs("};\n", fp);
@@ -310,8 +311,8 @@ cdump_debug(mrb_state *mrb, const char *name, int n, mrb_irep_debug_info *info,
case mrb_debug_line_packed_map:
line_type = "mrb_debug_line_packed_map";
fprintf(fp, "static char %s_debug_lines_%d[] = \"", name, n);
uint8_t *pmap = info->files[0]->lines.packed_map;
fprintf(fp, "static const char %s_debug_lines_%d[] = \"", name, n);
const uint8_t *pmap = info->files[0]->lines.packed_map;
for (i=0; i<len; i++) {
fprintf(fp, "\\x%02x", pmap[i]&0xff);
}
+25 -46
View File
@@ -16,6 +16,7 @@
#include <mruby/data.h>
#include <mruby/istruct.h>
#include <mruby/opcode.h>
#include <mruby/internal.h>
#include <mruby/presym.h>
union mt_ptr {
@@ -150,9 +151,11 @@ mt_get(mrb_state *mrb, mt_tbl *t, mrb_sym sym, union mt_ptr *pp)
hash = kh_int_hash_func(mrb, sym);
#ifdef MRB_USE_INLINE_METHOD_CACHE
int cpos = (hash^(uintptr_t)t) % MT_CACHE_SIZE;
mrb_sym key;
pos = mt_cache[cpos];
if (cpos < t->alloc && t->table[cpos].key == sym) {
return &t->table[cpos];
if (cpos < t->alloc && key = keys[pos] && MT_KEY_SYM(key) == sym) {
*pp = vals[pos];
return key;
}
#endif
start = pos = hash & (t->alloc-1);
@@ -161,7 +164,7 @@ mt_get(mrb_state *mrb, mt_tbl *t, mrb_sym sym, union mt_ptr *pp)
if (MT_KEY_SYM(key) == sym) {
*pp = vals[pos];
#ifdef MRB_USE_INLINE_METHOD_CACHE
if (pos < 0xff) {
if (pos < 0x100) {
mt_cache[cpos] = pos;
}
#endif
@@ -545,7 +548,7 @@ mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super)
return mrb_define_class_id(mrb, mrb_intern_cstr(mrb, name), super);
}
static mrb_value mrb_bob_init(mrb_state *mrb, mrb_value);
static mrb_value mrb_do_nothing(mrb_state *mrb, mrb_value);
#ifndef MRB_NO_METHOD_CACHE
static void mc_clear(mrb_state *mrb);
#else
@@ -564,7 +567,7 @@ mrb_class_inherited(mrb_state *mrb, struct RClass *super, struct RClass *klass)
s = mrb_obj_value(super);
mrb_mc_clear_by_class(mrb, klass);
mid = MRB_SYM(inherited);
if (!mrb_func_basic_p(mrb, s, mid, mrb_bob_init)) {
if (!mrb_func_basic_p(mrb, s, mid, mrb_do_nothing)) {
mrb_value c = mrb_obj_value(klass);
mrb_funcall_argv(mrb, s, mid, 1, &c);
}
@@ -877,8 +880,6 @@ mrb_get_arg1(mrb_state *mrb)
return array_argv[0];
}
mrb_int mrb_ci_bidx(mrb_callinfo *ci);
MRB_API mrb_bool
mrb_block_given_p(mrb_state *mrb)
{
@@ -913,7 +914,6 @@ mrb_block_given_p(mrb_state *mrb)
b: boolean [mrb_bool]
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*,struct RClass] I! gives NULL for nil
&: block [mrb_value] &! raises exception if no block given
*: rest argument [const mrb_value*,mrb_int] The rest of the arguments as an array; *! avoid copy of the stack
|: optional Following arguments are optional
@@ -932,10 +932,10 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
{
const char *fmt = format;
char c;
int i = 0;
mrb_int i = 0;
va_list ap;
mrb_callinfo *ci = mrb->c->ci;
int argc = ci->n;
mrb_int argc = ci->n;
const mrb_value *argv = ci->stack+1;
mrb_bool argv_on_stack;
mrb_bool opt = FALSE;
@@ -1161,29 +1161,6 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
}
break;
case 'I':
{
void* *p;
struct RClass *klass;
p = va_arg(ap, void**);
klass = va_arg(ap, struct RClass*);
if (pickarg) {
if (altmode && mrb_nil_p(*pickarg)) {
*p = NULL;
}
else {
if (!mrb_obj_is_kind_of(mrb, *pickarg, klass)) {
mrb_raisef(mrb, E_TYPE_ERROR, "%v is not a %C", *pickarg, klass);
}
if (!mrb_istruct_p(*pickarg)) {
mrb_raisef(mrb, E_TYPE_ERROR, "%v is not inline struct", *pickarg);
}
*p = mrb_istruct_ptr(*pickarg);
}
}
}
break;
#ifndef MRB_NO_FLOAT
case 'f':
{
@@ -1376,6 +1353,7 @@ boot_defclass(mrb_state *mrb, struct RClass *super)
if (super) {
c->super = super;
mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)super);
c->flags |= MRB_FL_CLASS_IS_INHERITED;
}
else {
c->super = mrb->object_class;
@@ -1970,7 +1948,7 @@ mrb_instance_new(mrb_state *mrb, mrb_value cv)
mrb_get_args(mrb, "*!&", &argv, &argc, &blk);
obj = mrb_instance_alloc(mrb, cv);
init = MRB_SYM(initialize);
if (!mrb_func_basic_p(mrb, obj, init, mrb_bob_init)) {
if (!mrb_func_basic_p(mrb, obj, init, mrb_do_nothing)) {
mrb_funcall_with_block(mrb, obj, init, argc, argv, blk);
}
return obj;
@@ -1984,7 +1962,7 @@ mrb_obj_new(mrb_state *mrb, struct RClass *c, mrb_int argc, const mrb_value *arg
obj = mrb_instance_alloc(mrb, mrb_obj_value(c));
mid = MRB_SYM(initialize);
if (!mrb_func_basic_p(mrb, obj, mid, mrb_bob_init)) {
if (!mrb_func_basic_p(mrb, obj, mid, mrb_do_nothing)) {
mrb_funcall_argv(mrb, obj, mid, argc, argv);
}
return obj;
@@ -2041,7 +2019,7 @@ mrb_class_superclass(mrb_state *mrb, mrb_value klass)
}
static mrb_value
mrb_bob_init(mrb_state *mrb, mrb_value cv)
mrb_do_nothing(mrb_state *mrb, mrb_value cv)
{
return mrb_nil_value();
}
@@ -2305,8 +2283,6 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
}
}
void mrb_method_added(mrb_state *mrb, struct RClass *c, mrb_sym mid);
static mrb_value
mrb_mod_alias(mrb_state *mrb, mrb_value mod)
{
@@ -2363,7 +2339,10 @@ mrb_remove_method(mrb_state *mrb, struct RClass *c, mrb_sym mid)
MRB_CLASS_ORIGIN(c);
h = c->mt;
if (h && mt_del(mrb, h, mid)) return;
if (h && mt_del(mrb, h, mid)) {
mrb_mc_clear_by_class(mrb, c);
return;
}
mrb_name_error(mrb, mid, "method '%n' not defined in %C", mid, c);
}
@@ -2930,32 +2909,32 @@ mrb_init_class(mrb_state *mrb)
MRB_SET_INSTANCE_TT(mrb->proc_class, MRB_TT_PROC);
MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS);
mrb_define_method(mrb, bob, "initialize", mrb_bob_init, MRB_ARGS_NONE());
mrb_define_method(mrb, bob, "initialize", mrb_do_nothing, MRB_ARGS_NONE());
mrb_define_method(mrb, bob, "!", mrb_bob_not, MRB_ARGS_NONE());
mrb_define_method(mrb, bob, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */
mrb_define_method(mrb, bob, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.4 */
mrb_define_method(mrb, bob, "__send__", mrb_f_send, MRB_ARGS_REQ(1)|MRB_ARGS_REST()|MRB_ARGS_BLOCK()); /* 15.3.1.3.5 */
mrb_define_method(mrb, bob, "equal?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.11 */
mrb_define_method(mrb, bob, "instance_eval", mrb_obj_instance_eval, MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK()); /* 15.3.1.3.18 */
mrb_define_method(mrb, bob, "singleton_method_added", mrb_bob_init, MRB_ARGS_REQ(1));
mrb_define_method(mrb, bob, "singleton_method_added", mrb_do_nothing, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK());
mrb_define_method(mrb, cls, "allocate", mrb_instance_alloc, MRB_ARGS_NONE());
mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, MRB_ARGS_NONE()); /* 15.2.3.3.4 */
mrb_define_method(mrb, cls, "initialize", mrb_class_initialize, MRB_ARGS_OPT(1)); /* 15.2.3.3.1 */
mrb_define_method(mrb, cls, "inherited", mrb_bob_init, MRB_ARGS_REQ(1));
mrb_define_method(mrb, cls, "inherited", mrb_do_nothing, MRB_ARGS_REQ(1));
init_class_new(mrb, cls);
MRB_SET_INSTANCE_TT(mod, MRB_TT_MODULE);
mrb_define_method(mrb, mod, "extend_object", mrb_mod_extend_object, MRB_ARGS_REQ(1)); /* 15.2.2.4.25 */
mrb_define_method(mrb, mod, "extended", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */
mrb_define_method(mrb, mod, "prepended", mrb_bob_init, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mod, "extended", mrb_do_nothing, MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */
mrb_define_method(mrb, mod, "prepended", mrb_do_nothing, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mod, "prepend_features", mrb_mod_prepend_features, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mod, "include?", mrb_mod_include_p, MRB_ARGS_REQ(1)); /* 15.2.2.4.28 */
mrb_define_method(mrb, mod, "append_features", mrb_mod_append_features, MRB_ARGS_REQ(1)); /* 15.2.2.4.10 */
mrb_define_method(mrb, mod, "class_eval", mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.15 */
mrb_define_method(mrb, mod, "included", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.29 */
mrb_define_method(mrb, mod, "included", mrb_do_nothing, MRB_ARGS_REQ(1)); /* 15.2.2.4.29 */
mrb_define_method(mrb, mod, "initialize", mrb_mod_initialize, MRB_ARGS_NONE()); /* 15.2.2.4.31 */
mrb_define_method(mrb, mod, "module_eval", mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.35 */
mrb_define_method(mrb, mod, "module_function", mrb_mod_module_function, MRB_ARGS_ANY());
@@ -2978,7 +2957,7 @@ mrb_init_class(mrb_state *mrb)
mrb_define_method(mrb, mod, "define_method", mod_define_method, MRB_ARGS_ARG(1,1));
mrb_define_method(mrb, mod, "===", mrb_mod_eqq, MRB_ARGS_REQ(1)); /* 15.2.2.4.7 */
mrb_define_method(mrb, mod, "dup", mrb_mod_dup, MRB_ARGS_NONE());
mrb_define_method(mrb, bob, "method_added", mrb_bob_init, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mod, "method_added", mrb_do_nothing, MRB_ARGS_REQ(1));
mrb_undef_method(mrb, cls, "append_features");
mrb_undef_method(mrb, cls, "prepend_features");

Some files were not shown because too many files have changed in this diff Show More