mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Compare commits
184 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 112120969d | |||
| 63956036e1 | |||
| cdf45438f0 | |||
| b6b9c57f24 | |||
| aa578c346d | |||
| ac8360003e | |||
| 233cb49903 | |||
| 9cdf439db5 | |||
| 95360a17f2 | |||
| 9dfe50f1d9 | |||
| c07f24cd18 | |||
| 03c2b8656b | |||
| ea6e1b003c | |||
| c2b37e76b3 | |||
| d40b922c98 | |||
| 28e793496a | |||
| 33c8d6af1e | |||
| 49ae2a69f2 | |||
| 2ffb77586a | |||
| dad99afae8 | |||
| f93dffb5ee | |||
| 742117e7a3 | |||
| 15ceb35e05 | |||
| f0bad600e0 | |||
| a8aeba89ef | |||
| 7f593893e8 | |||
| 5d5b1d1f3c | |||
| bb6846468a | |||
| 960c82e396 | |||
| 5be33b82c7 | |||
| 4cd858f93d | |||
| 2098acee7d | |||
| 3157efa57c | |||
| 613e0bee5e | |||
| 78c9c71bdf | |||
| aa30b13b36 | |||
| 6ba542cd53 | |||
| 106f4c4e9d | |||
| f1523d2404 | |||
| 00f6271e3b | |||
| b0e49ef79e | |||
| 81d340e042 | |||
| 4e40169ed6 | |||
| 49f1c0e94d | |||
| dcfebc6eed | |||
| 3d2d9f8a9b | |||
| 07129c76d9 | |||
| 6fe03f3b39 | |||
| 41f3456a28 | |||
| 7a420d4bba | |||
| d2b9c90f28 | |||
| ce12ef7e5c | |||
| 8bca11a64e | |||
| 14e325e45d | |||
| f85906b679 | |||
| 1fc9345b45 | |||
| 0a5983dd5e | |||
| aec40d10b8 | |||
| 89ceb3e7ba | |||
| fc80e4b651 | |||
| 52ab095ccf | |||
| d5cca2bdb2 | |||
| ebbb4fd7fb | |||
| b717cc7830 | |||
| a476c83caf | |||
| 15c63688e3 | |||
| 69c62415c0 | |||
| 690b2aa761 | |||
| 69311fa4c9 | |||
| ab9be1b48a | |||
| 5a682bfc7b | |||
| 53ea8abea6 | |||
| 6445e4683f | |||
| 6d49ec25a9 | |||
| a3ec6ede76 | |||
| 6803ddb8e2 | |||
| 4ce3997ca4 | |||
| 93e78fcde1 | |||
| 6f4c585bd7 | |||
| 47ea60814b | |||
| 86223b6eca | |||
| d79147fe5d | |||
| ac68c90800 | |||
| 82194c01ca | |||
| 69bc477b43 | |||
| 3655d4e0f4 | |||
| bc929656fb | |||
| 4aba93c969 | |||
| 49d97d6051 | |||
| 484577670f | |||
| d64c4d64e6 | |||
| 846af371c0 | |||
| 38b4483f9d | |||
| bb2512641f | |||
| bd60ad98eb | |||
| 7826af38ac | |||
| 84d842ea5c | |||
| f6c2662632 | |||
| e2aecacaeb | |||
| 8cdf6a87ed | |||
| 181f7b97d6 | |||
| 3491372a1d | |||
| 03b0741994 | |||
| a87f0b158d | |||
| e82b8b7bf8 | |||
| 91368c117c | |||
| 87576b819e | |||
| 48c473a0c4 | |||
| 87d77c13f5 | |||
| 4188219620 | |||
| fa8668c77d | |||
| 47f5f887e8 | |||
| c143d87e7c | |||
| 2fcdd3f8eb | |||
| 8c0dc55af8 | |||
| 8c04379a4c | |||
| a5bfe548d7 | |||
| 84aad39940 | |||
| c89ca5ebb8 | |||
| 1a4b86233f | |||
| 69a487c407 | |||
| f32c73ad1f | |||
| a343439973 | |||
| aeb86d953e | |||
| 49bba6c997 | |||
| 49b2e8c3a9 | |||
| 9c1220e14d | |||
| e2ac2a82a5 | |||
| bb6290a5d5 | |||
| 312411dea0 | |||
| 7277682cfb | |||
| 0f229bfbbf | |||
| 28b23b44ec | |||
| 8627157298 | |||
| b87268f130 | |||
| a395f8e2c8 | |||
| 3ce459f23a | |||
| e51923778f | |||
| 468578113a | |||
| 2c32154115 | |||
| 47d99457d9 | |||
| 88b756b39f | |||
| 462ff4cc84 | |||
| 18274e717a | |||
| 7870f74c21 | |||
| 8dee2e3984 | |||
| 8e86e64d78 | |||
| e79e972255 | |||
| 682a31f92b | |||
| 17974aa285 | |||
| 0a7fd86d59 | |||
| d95d46dee6 | |||
| 81c8352179 | |||
| 6d80c9505d | |||
| 1b0cf6a91b | |||
| 954ce5379c | |||
| 8b5c19218d | |||
| f6408c7b11 | |||
| 095aae5e2c | |||
| 26eb29547b | |||
| d3a02a297f | |||
| ab508e1e7f | |||
| 87d1bbe947 | |||
| 2e661e82d1 | |||
| 61c6832b48 | |||
| ed0038fdf2 | |||
| c181d89c9d | |||
| c91c9e2429 | |||
| 7add524041 | |||
| 72928f201c | |||
| 81a9210091 | |||
| e9877bc72a | |||
| ea632ab8a4 | |||
| d0501c69b0 | |||
| 3c03385e2e | |||
| 191ccbf660 | |||
| d983269908 | |||
| 2ceab2d270 | |||
| 8ce3664305 | |||
| ccd8485111 | |||
| 70caf4ed6d | |||
| b7c8bf7781 | |||
| 6af555b394 | |||
| ad6c58972c |
@@ -0,0 +1,106 @@
|
||||
name: Build & Test
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
Ubuntu-1604:
|
||||
runs-on: ubuntu-16.04
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: apt
|
||||
run: sudo apt install ruby gperf
|
||||
- name: build and test
|
||||
run: rake -m -j4 all test
|
||||
env:
|
||||
MRUBY_CONFIG: travis_config.rb
|
||||
|
||||
Ubuntu-1804-gcc:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: apt
|
||||
run: sudo apt install ruby gperf gcc g++
|
||||
- name: build and test
|
||||
run: rake -m -j4 all test
|
||||
env:
|
||||
MRUBY_CONFIG: travis_config.rb
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
|
||||
Ubuntu-1804-clang:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: apt
|
||||
run: sudo apt install ruby gperf
|
||||
- name: build and test
|
||||
run: rake -m -j4 all test
|
||||
env:
|
||||
MRUBY_CONFIG: travis_config.rb
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
|
||||
macOS:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: brew
|
||||
run: brew install ruby gperf
|
||||
- name: build and test
|
||||
run: rake -m -j4 all test
|
||||
env:
|
||||
MRUBY_CONFIG: travis_config.rb
|
||||
|
||||
Windows-MinGW:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: chocolatey
|
||||
run: choco install -y ruby gperf
|
||||
- name: build and test
|
||||
run: rake -E '$stdout.sync=true' -j4 test
|
||||
env:
|
||||
MRUBY_CONFIG: travis_config.rb
|
||||
CFLAGS: -g -O1 -Wall -Wundef
|
||||
|
||||
Windows-Cygwin:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: C:\Users\runneradmin\AppData\Local\Temp\chocolatey
|
||||
key: ${{ runner.os }}-cygwin-chocolatey-${{ matrix.os }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cygwin-chocolatey-${{ matrix.os }}-
|
||||
${{ runner.os }}-cygwin-chocolatey-
|
||||
- name: chocolatey
|
||||
run: choco install -y cygwin
|
||||
- name: Install cygwin packages
|
||||
shell: cmd
|
||||
run: C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -l C:/tools/cygwin/package -s http://mirrors.kernel.org/sourceware/cygwin/ -P gcc-core,gcc-g++,make,gperf,ruby
|
||||
- name: Set ENV
|
||||
run: |
|
||||
echo '::set-env name=PATH::C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin'
|
||||
- name: build and test
|
||||
shell: cmd
|
||||
run: C:\tools\cygwin\bin\ruby.exe /usr/bin/rake -m -j4 -E 'STDOUT.sync=true' test
|
||||
env:
|
||||
MRUBY_CONFIG: travis_config.rb
|
||||
|
||||
Windows-VC:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: chocolatey
|
||||
run: choco install -y ruby gperf
|
||||
- name: build and test
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||
rake -E "STDOUT.sync=true" -m -j4 test
|
||||
env:
|
||||
MRUBY_CONFIG: appveyor_config.rb
|
||||
# TODO(take-cheeze): Re-enable /O2
|
||||
CFLAGS: "/c /nologo /W3 /we4013 /Zi /MD /D_CRT_SECURE_NO_WARNINGS"
|
||||
CXXFLAGS: "/c /nologo /W3 /Zi /MD /EHs /D_CRT_SECURE_NO_WARNINGS"
|
||||
@@ -0,0 +1,51 @@
|
||||
name: "Code scanning - action"
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: '0 19 * * 4'
|
||||
|
||||
jobs:
|
||||
CodeQL-Build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
fetch-depth: 2
|
||||
|
||||
# If this run was triggered by a pull request event, then checkout
|
||||
# the head of the pull request instead of the merge commit.
|
||||
- run: git checkout HEAD^2
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
# Override language selection by uncommenting this and choosing your languages
|
||||
# with:
|
||||
# languages: go, javascript, csharp, python, cpp, java
|
||||
|
||||
# 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
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
@@ -17,6 +17,9 @@
|
||||
.svn
|
||||
.vscode
|
||||
.yardoc
|
||||
.ccls*
|
||||
compile_flags.txt
|
||||
compile_commands.json
|
||||
cscope.files
|
||||
cscope.out
|
||||
tags
|
||||
|
||||
+6
-9
@@ -1,14 +1,11 @@
|
||||
language: c
|
||||
|
||||
sudo: false
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
sudo: false
|
||||
- os: osx
|
||||
osx_image: xcode7.1
|
||||
jobs:
|
||||
- os: linux
|
||||
- os: osx
|
||||
|
||||
env:
|
||||
- MRUBY_CONFIG=travis_config.rb
|
||||
script: "rake -m && rake test"
|
||||
|
||||
script:
|
||||
- rake -m && rake test
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "mruby"
|
||||
PROJECT_NUMBER = 2.1.1
|
||||
PROJECT_NUMBER = 2.1.2
|
||||
|
||||
PROJECT_BRIEF = "mruby is the lightweight implementation of the Ruby language"
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ of the Ministry of Economy, Trade and Industry of Japan.
|
||||
|
||||
## How to get mruby
|
||||
|
||||
The stable version 2.1.1 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/2.1.1.zip](https://github.com/mruby/mruby/archive/2.1.1.zip)
|
||||
The stable version 2.1.2 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/2.1.2.zip](https://github.com/mruby/mruby/archive/2.1.2.zip)
|
||||
|
||||
The latest development version of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/zipball/master](https://github.com/mruby/mruby/zipball/master)
|
||||
|
||||
@@ -46,6 +46,10 @@ To run the tests, execute the following from the project's root directory.
|
||||
|
||||
$ rake test
|
||||
|
||||
Note: `bison` bundled with MacOS is too old to compile `mruby`.
|
||||
Try `brew install bison` and follow the instuction shown to update
|
||||
the `$PATH` to compile `mruby`.
|
||||
|
||||
## Building documentation
|
||||
|
||||
There are two sets of documentation in mruby: the mruby API (generated by yard) and C API (Doxygen)
|
||||
|
||||
+1
-12
@@ -4,11 +4,6 @@ os: Visual Studio 2017
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
|
||||
cache:
|
||||
- win_flex_bison
|
||||
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
# Visual Studio 2017 64bit
|
||||
@@ -38,13 +33,7 @@ init:
|
||||
- ruby --version
|
||||
|
||||
|
||||
install:
|
||||
- if not exist win_flex_bison (
|
||||
appveyor DownloadFile "https://github.com/lexxmark/winflexbison/releases/download/v.2.5.10/win_flex_bison-2.5.10.zip" &
|
||||
7z x -y -owin_flex_bison win_flex_bison-2.5.10.zip
|
||||
)
|
||||
|
||||
build_script:
|
||||
- set YACC=.\win_flex_bison\win_bison.exe
|
||||
- set MRUBY_CONFIG=appveyor_config.rb
|
||||
- rake -m
|
||||
- rake -E $stdout.sync=true test
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
def setup_option(conf)
|
||||
conf.cc.flags[0].delete("/Zi") unless ENV['CFLAGS']
|
||||
conf.cxx.flags[0].delete("/Zi") unless ENV['CFLAGS'] || ENV['CXXFLAGS']
|
||||
conf.linker.flags << "/DEBUG:NONE" unless ENV['LDFLAGS']
|
||||
end
|
||||
|
||||
MRuby::Build.new('full-debug') do |conf|
|
||||
toolchain :visualcpp
|
||||
enable_debug
|
||||
@@ -5,6 +11,7 @@ MRuby::Build.new('full-debug') do |conf|
|
||||
# include all core GEMs
|
||||
conf.gembox 'full-core'
|
||||
conf.cc.defines += %w(MRB_GC_STRESS MRB_METHOD_CACHE MRB_ENABLE_DEBUG_HOOK)
|
||||
setup_option(conf)
|
||||
|
||||
conf.enable_test
|
||||
end
|
||||
@@ -17,6 +24,7 @@ MRuby::Build.new do |conf|
|
||||
conf.compilers.each do |c|
|
||||
c.defines += %w(MRB_GC_FIXED_ARENA)
|
||||
end
|
||||
setup_option(conf)
|
||||
conf.enable_bintest
|
||||
conf.enable_test
|
||||
end
|
||||
@@ -28,6 +36,7 @@ MRuby::Build.new('cxx_abi') do |conf|
|
||||
conf.compilers.each do |c|
|
||||
c.defines += %w(MRB_GC_FIXED_ARENA)
|
||||
end
|
||||
setup_option(conf)
|
||||
conf.enable_bintest
|
||||
conf.enable_test
|
||||
|
||||
|
||||
@@ -6,12 +6,16 @@ binaries.
|
||||
## Prerequisites
|
||||
|
||||
To compile mruby out of the source code you need the following tools:
|
||||
* C Compiler (e.g. `gcc`)
|
||||
* Linker (e.g. `gcc`)
|
||||
* C Compiler (e.g. `gcc` or `clang`)
|
||||
* Linker (e.g. `gcc` or `clang`)
|
||||
* Archive utility (e.g. `ar`)
|
||||
* Parser generator (e.g. `bison`)
|
||||
* Ruby 2.0 or later (e.g. `ruby` or `jruby`)
|
||||
|
||||
Note that `bison` bundled with MacOS is too old to compile `mruby`.
|
||||
Try `brew install bison` and follow the instuction shown to update
|
||||
the `$PATH` to compile `mruby`.
|
||||
|
||||
Optional:
|
||||
* GIT (to update mruby source and integrate mrbgems easier)
|
||||
* C++ compiler (to use GEMs which include \*.cpp, \*.cxx, \*.cc)
|
||||
|
||||
@@ -38,7 +38,7 @@ To confirm mrdb was installed properly, run mrdb with the `--version` option:
|
||||
|
||||
```bash
|
||||
$ mrdb --version
|
||||
mruby 2.1.1 (2020-06-04)
|
||||
mruby 2.1.2 (2020-07-10)
|
||||
```
|
||||
|
||||
## 2.2 Basic Operation
|
||||
|
||||
+10
-10
@@ -38,7 +38,7 @@ puts [1,2,3]
|
||||
3
|
||||
```
|
||||
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
#### mruby [2.1.2 (2020-07-10)]
|
||||
|
||||
```
|
||||
[1, 2, 3]
|
||||
@@ -61,7 +61,7 @@ end
|
||||
|
||||
`ZeroDivisionError` is raised.
|
||||
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
#### mruby [2.1.2 (2020-07-10)]
|
||||
|
||||
No exception is raised.
|
||||
|
||||
@@ -89,7 +89,7 @@ p Liste.new "foobar"
|
||||
|
||||
` [] `
|
||||
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
#### mruby [2.1.2 (2020-07-10)]
|
||||
|
||||
`ArgumentError` is raised.
|
||||
|
||||
@@ -119,7 +119,7 @@ false
|
||||
true
|
||||
```
|
||||
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
#### mruby [2.1.2 (2020-07-10)]
|
||||
|
||||
```
|
||||
true
|
||||
@@ -156,7 +156,7 @@ p 'ok'
|
||||
ok
|
||||
```
|
||||
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
#### mruby [2.1.2 (2020-07-10)]
|
||||
|
||||
```
|
||||
test.rb:8: undefined method 'test_func' (NoMethodError)
|
||||
@@ -178,7 +178,7 @@ defined?(Foo)
|
||||
nil
|
||||
```
|
||||
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
#### mruby [2.1.2 (2020-07-10)]
|
||||
|
||||
`NameError` is raised.
|
||||
|
||||
@@ -195,7 +195,7 @@ alias $a $__a__
|
||||
|
||||
` nil `
|
||||
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
#### mruby [2.1.2 (2020-07-10)]
|
||||
|
||||
Syntax error
|
||||
|
||||
@@ -217,7 +217,7 @@ end
|
||||
`ArgumentError` is raised.
|
||||
The re-defined `+` operator does not accept any arguments.
|
||||
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
#### mruby [2.1.2 (2020-07-10)]
|
||||
|
||||
` 'ab' `
|
||||
Behavior of the operator wasn't changed.
|
||||
@@ -233,7 +233,7 @@ $ ruby -e 'puts Proc.new {}.binding'
|
||||
#<Binding:0x00000e9deabb9950>
|
||||
```
|
||||
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
#### mruby [2.1.2 (2020-07-10)]
|
||||
|
||||
```
|
||||
$ ./bin/mruby -e 'puts Proc.new {}.binding'
|
||||
@@ -255,7 +255,7 @@ $ ruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
|
||||
[[{"a"=>1}], {:b=>2}]
|
||||
```
|
||||
|
||||
#### mruby [mruby 2.1.1]
|
||||
#### mruby [mruby 2.1.2]
|
||||
|
||||
```
|
||||
$ ./bin/mruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
|
||||
|
||||
+108
-95
@@ -16,7 +16,6 @@ In the table.1 below, the second field describes the size (and
|
||||
sign) of operands.
|
||||
|
||||
* B: 8bit
|
||||
* sB: signed 8bit
|
||||
* S: 16bit
|
||||
* sS: signed 16bit
|
||||
* W: 24bit
|
||||
@@ -31,97 +30,111 @@ with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
|
||||
|
||||
## table.1 Instruction Table
|
||||
|
||||
| Instruction Name | Operand type | Semantics |
|
||||
|:-----------------|--------------|---------------------|
|
||||
| OP_NOP | - | |
|
||||
| OP_MOVE" | BB | R(a) = R(b)
|
||||
| OP_LOADL" | BB | R(a) = Pool(b)
|
||||
| OP_LOADI" | BsB | R(a) = mrb_int(b)
|
||||
| OP_LOADI_0' | B | R(a) = 0
|
||||
| OP_LOADI_1' | B | R(a) = 1
|
||||
| OP_LOADI_2' | B | R(a) = 2
|
||||
| OP_LOADI_3' | B | R(a) = 3
|
||||
| OP_LOADSYM" | BB | R(a) = Syms(b)
|
||||
| OP_LOADNIL' | B | R(a) = nil
|
||||
| OP_LOADSELF' | B | R(a) = self
|
||||
| OP_LOADT' | B | R(a) = true
|
||||
| OP_LOADF' | B | R(a) = false
|
||||
| OP_GETGV" | BB | R(a) = getglobal(Syms(b))
|
||||
| OP_SETGV" | BB | setglobal(Syms(b), R(a))
|
||||
| OP_GETSV" | BB | R(a) = Special[b]
|
||||
| OP_SETSV" | BB | Special[b] = R(a)
|
||||
| OP_GETIV" | BB | R(a) = ivget(Syms(b))
|
||||
| OP_SETIV" | BB | ivset(Syms(b),R(a))
|
||||
| OP_GETCV" | BB | R(a) = cvget(Syms(b))
|
||||
| OP_SETCV" | BB | cvset(Syms(b),R(a))
|
||||
| OP_GETCONST" | BB | R(a) = constget(Syms(b))
|
||||
| OP_SETCONST" | BB | constset(Syms(b),R(a))
|
||||
| OP_GETMCNST" | BB | R(a) = R(a)::Syms(b)
|
||||
| OP_SETMCNST" | BB | R(a+1)::Syms(b) = R(a)
|
||||
| OP_GETUPVAR' | BBB | R(a) = uvget(b,c)
|
||||
| OP_SETUPVAR' | BBB | uvset(b,c,R(a))
|
||||
| OP_JMP | S | pc+=a
|
||||
| OP_JMPIF' | SB | if R(b) pc+=a
|
||||
| OP_JMPNOT' | SB | if !R(b) pc+=a
|
||||
| OP_ONERR | sS | rescue_push(pc+a)
|
||||
| OP_EXCEPT' | B | R(a) = exc
|
||||
| OP_RESCUE" | BB | R(b) = R(a).isa?(R(b))
|
||||
| OP_POPERR | B | a.times{rescue_pop()}
|
||||
| OP_RAISE' | B | raise(R(a))
|
||||
| OP_EPUSH' | B | ensure_push(SEQ[a])
|
||||
| OP_EPOP | B | A.times{ensure_pop().call}
|
||||
| OP_SENDV" | BB | R(a) = call(R(a),Syms(b),*R(a+1))
|
||||
| OP_SENDVB" | BB | R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2))
|
||||
| OP_SEND" | BBB | R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c))
|
||||
| OP_SENDB" | BBB | R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1))
|
||||
| OP_CALL' | B | R(a) = self.call(frame.argc, frame.argv)
|
||||
| OP_SUPER' | BB | R(a) = super(R(a+1),... ,R(a+b+1))
|
||||
| OP_ARGARY' | BS | R(a) = argument array (16=5:1:5:1:4)
|
||||
| OP_ENTER | W | arg setup according to flags (23=5:5:1:5:5:1:1)
|
||||
| OP_KARG" | BB | R(a) = kdict[Syms(Bx)] # todo
|
||||
| OP_KARG2" | BB | R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo
|
||||
| OP_RETURN' | B | return R(a) (normal)
|
||||
| OP_RETURN_BLK' | B | return R(a) (in-block return)
|
||||
| OP_BREAK' | B | break R(a)
|
||||
| OP_BLKPUSH' | BS | R(a) = block (16=5:1:5:1:4)
|
||||
| OP_ADD" | BB | R(a) = R(a)+R(a+1)
|
||||
| OP_ADDI" | BBB | R(a) = R(a)+mrb_int(c)
|
||||
| OP_SUB" | BB | R(a) = R(a)-R(a+1)
|
||||
| OP_SUBI" | BB | R(a) = R(a)-C
|
||||
| OP_MUL" | BB | R(a) = R(a)*R(a+1)
|
||||
| OP_DIV" | BB | R(a) = R(a)/R(a+1)
|
||||
| OP_EQ" | BB | R(a) = R(a)==R(a+1)
|
||||
| OP_LT" | BB | R(a) = R(a)<R(a+1)
|
||||
| OP_LE" | BB | R(a) = R(a)<=R(a+1)
|
||||
| OP_GT" | BB | R(a) = R(a)>R(a+1)
|
||||
| OP_GE" | BB | R(a) = R(a)>=R(a+1)
|
||||
| OP_ARRAY' | BB | R(a) = ary_new(R(a),R(a+1)..R(a+b))
|
||||
| OP_ARRAY2" | BB | R(a) = ary_new(R(b),R(b+1)..R(b+c))
|
||||
| OP_ARYCAT' | B | ary_cat(R(a),R(a+1))
|
||||
| OP_ARYPUSH' | B | ary_push(R(a),R(a+1))
|
||||
| OP_AREF' | BB | R(a) = R(a)[b]
|
||||
| OP_ASET' | BB | R(a)[b] = R(a+1)
|
||||
| OP_APOST' | BB | *R(a),R(A+1)..R(A+C) = R(a)[B..]
|
||||
| OP_STRING" | BB | R(a) = str_dup(Lit(b))
|
||||
| OP_STRCAT' | B | str_cat(R(a),R(a+1))
|
||||
| OP_HASH' | BB | R(a) = hash_new(R(a),R(a+1)..R(a+b))
|
||||
| OP_HASHADD' | BB | R(a) = hash_push(R(a),R(a+1)..R(a+b))
|
||||
| OP_LAMBDA" | BB | R(a) = lambda(SEQ[b],OP_L_LAMBDA)
|
||||
| OP_BLOCK" | BB | R(a) = lambda(SEQ[b],OP_L_BLOCK)
|
||||
| OP_METHOD" | BB | R(a) = lambda(SEQ[b],OP_L_METHOD)
|
||||
| OP_RANGE_INC' | B | R(a) = range_new(R(a),R(a+1),FALSE)
|
||||
| OP_RANGE_EXC' | B | R(a) = range_new(R(a),R(a+1),TRUE)
|
||||
| OP_OCLASS' | B | R(a) = ::Object
|
||||
| OP_CLASS" | BB | R(a) = newclass(R(a),Syms(b),R(a+1))
|
||||
| OP_MODULE" | BB | R(a) = newmodule(R(a),Syms(b))
|
||||
| OP_EXEC" | BB | R(a) = blockexec(R(a),SEQ[b])
|
||||
| OP_DEF" | BB | R(a).newmethod(Syms(b),R(a+1))
|
||||
| OP_ALIAS' | B | alias_method(R(a),R(a+1),R(a+2))
|
||||
| OP_UNDEF" | BB | undef_method(R(a),Syms(b))
|
||||
| OP_SCLASS' | B | R(a) = R(a).singleton_class
|
||||
| OP_TCLASS' | B | R(a) = target_class
|
||||
| OP_ERR' | B | raise(RuntimeError, Lit(Bx))
|
||||
| OP_EXT1 | - | make 1st operand 16bit
|
||||
| OP_EXT2 | - | make 2nd operand 16bit
|
||||
| OP_EXT3 | - | make 1st and 2nd operands 16bit
|
||||
| OP_STOP | - | stop VM
|
||||
| Instruction Name | Operand type | Semantics |
|
||||
|------------------|--------------|--------------------------------------------------------|
|
||||
| OP_NOP | - | 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' | BsS | R(a) = mrb_int(b) |
|
||||
| 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_ONERR | S | rescue_push(a) |
|
||||
| OP_EXCEPT' | B | R(a) = exc |
|
||||
| OP_RESCUE" | BB | R(b) = R(a).isa?(R(b)) |
|
||||
| OP_POPERR' | B | a.times{rescue_pop()} |
|
||||
| OP_RAISE' | B | raise(R(a)) |
|
||||
| OP_EPUSH' | B | ensure_push(SEQ[a]) |
|
||||
| OP_EPOP' | B | A.times{ensure_pop().call} |
|
||||
| OP_SENDV" | BB | R(a) = call(R(a),Syms(b),*R(a+1)) |
|
||||
| OP_SENDVB" | BB | R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2)) |
|
||||
| OP_SEND" | BBB | R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c)) |
|
||||
| OP_SENDB" | BBB | R(a) = call(R(a),Syms(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=5:1:5:1:4) |
|
||||
| OP_ENTER | W | arg setup according to flags (23=5:5:1:5:5:1:1) |
|
||||
| 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=5:1:5:1:4) |
|
||||
| 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' | B | ary_push(R(a),R(a+1)) |
|
||||
| OP_ARYDUP' | B | R(a) = ary_dup(R(a)) |
|
||||
| OP_AREF" | BBB | R(a) = R(b)[c] |
|
||||
| OP_ASET" | BBB | R(a)[c] = R(b) |
|
||||
| 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(Lit(b)) |
|
||||
| OP_STRCAT' | B | str_cat(R(a),R(a+1)) |
|
||||
| OP_HASH" | BB | R(a) = hash_new(R(a),R(a+1)..R(a+b)) |
|
||||
| OP_HASHADD" | BB | R(a) = hash_push(R(a),R(a+1)..R(a+b)) |
|
||||
| OP_HASHCAT' | B | R(a) = hash_cat(R(a),R(a+1)) |
|
||||
| OP_LAMBDA" | BB | R(a) = lambda(SEQ[b],OP_L_LAMBDA) |
|
||||
| OP_BLOCK" | BB | R(a) = lambda(SEQ[b],OP_L_BLOCK) |
|
||||
| OP_METHOD" | BB | R(a) = lambda(SEQ[b],OP_L_METHOD) |
|
||||
| OP_RANGE_INC' | B | R(a) = range_new(R(a),R(a+1),FALSE) |
|
||||
| OP_RANGE_EXC' | B | R(a) = range_new(R(a),R(a+1),TRUE) |
|
||||
| OP_OCLASS' | B | R(a) = ::Object |
|
||||
| OP_CLASS" | BB | R(a) = newclass(R(a),Syms(b),R(a+1)) |
|
||||
| OP_MODULE" | BB | R(a) = newmodule(R(a),Syms(b)) |
|
||||
| OP_EXEC" | BB | R(a) = blockexec(R(a),SEQ[b]) |
|
||||
| OP_DEF" | BB | R(a).newmethod(Syms(b),R(a+1)) |
|
||||
| OP_ALIAS" | 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, Lit(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 |
|
||||
|------------------|--------------|--------------------------------------------------------|
|
||||
|
||||
+3
-2
@@ -39,8 +39,9 @@
|
||||
/* add -DMRB_METHOD_T_STRUCT on machines that use higher bits of pointers */
|
||||
/* no MRB_METHOD_T_STRUCT requires highest 2 bits of function pointers to be zero */
|
||||
#ifndef MRB_METHOD_T_STRUCT
|
||||
// can't use highest 2 bits of function pointers on 32bit Windows.
|
||||
# if defined(_WIN32) && !defined(_WIN64)
|
||||
// can't use highest 2 bits of function pointers at least on 32bit
|
||||
// Windows and 32bit Linux.
|
||||
# ifdef MRB_32BIT
|
||||
# define MRB_METHOD_T_STRUCT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
+18
-3
@@ -76,6 +76,7 @@
|
||||
#include <mruby/version.h>
|
||||
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
#include <float.h>
|
||||
#ifndef FLT_EPSILON
|
||||
#define FLT_EPSILON (1.19209290e-07f)
|
||||
#endif
|
||||
@@ -164,8 +165,8 @@ struct mrb_context {
|
||||
struct RProc **ensure; /* ensure handler stack */
|
||||
uint16_t esize, eidx;
|
||||
|
||||
enum mrb_fiber_state status;
|
||||
mrb_bool vmexec;
|
||||
enum mrb_fiber_state status : 4;
|
||||
mrb_bool vmexec : 1;
|
||||
struct RFiber *fib;
|
||||
};
|
||||
|
||||
@@ -317,7 +318,9 @@ MRB_API struct RClass *mrb_define_class(mrb_state *mrb, const char *name, struct
|
||||
* @return [struct RClass *] Reference to the newly defined module.
|
||||
*/
|
||||
MRB_API struct RClass *mrb_define_module(mrb_state *mrb, const char *name);
|
||||
|
||||
MRB_API mrb_value mrb_singleton_class(mrb_state *mrb, mrb_value val);
|
||||
MRB_API struct RClass *mrb_singleton_class_ptr(mrb_state *mrb, mrb_value val);
|
||||
|
||||
/**
|
||||
* Include a module in another class or module.
|
||||
@@ -956,8 +959,21 @@ mrb_get_mid(mrb_state *mrb) /* get method symbol */
|
||||
*/
|
||||
MRB_API mrb_int mrb_get_argc(mrb_state *mrb);
|
||||
|
||||
/**
|
||||
* Retrieve an array of arguments from mrb_state.
|
||||
*
|
||||
* Correctly handles *splat arguments.
|
||||
*/
|
||||
MRB_API mrb_value* mrb_get_argv(mrb_state *mrb);
|
||||
|
||||
/**
|
||||
* Retrieve the first and only argument from mrb_state.
|
||||
* Raises ArgumentError unless the number of arguments is exactly one.
|
||||
*
|
||||
* Correctly handles *splat arguments.
|
||||
*/
|
||||
MRB_API mrb_value mrb_get_arg1(mrb_state *mrb);
|
||||
|
||||
/* `strlen` for character string literals (use with caution or `strlen` instead)
|
||||
Adjacent string literals are concatenated in C/C++ in translation phase 6.
|
||||
If `lit` is not one, the compiler will report a syntax error:
|
||||
@@ -1148,7 +1164,6 @@ MRB_API void mrb_close(mrb_state *mrb);
|
||||
MRB_API void* mrb_default_allocf(mrb_state*, void*, size_t, void*);
|
||||
|
||||
MRB_API mrb_value mrb_top_self(mrb_state *mrb);
|
||||
MRB_API mrb_value mrb_run(mrb_state *mrb, struct RProc* proc, mrb_value self);
|
||||
MRB_API mrb_value mrb_top_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep);
|
||||
MRB_API mrb_value mrb_vm_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep);
|
||||
MRB_API mrb_value mrb_vm_exec(mrb_state *mrb, struct RProc *proc, const mrb_code *iseq);
|
||||
|
||||
@@ -239,6 +239,7 @@ MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset);
|
||||
* @param head Beginning position of a replacement subsequence.
|
||||
* @param len Length of a replacement subsequence.
|
||||
* @param rpl The array of replacement elements.
|
||||
* It is possible to pass `mrb_undef_value()` instead of an empty array.
|
||||
* @return The receiver array.
|
||||
*/
|
||||
MRB_API mrb_value mrb_ary_splice(mrb_state *mrb, mrb_value self, mrb_int head, mrb_int len, mrb_value rpl);
|
||||
@@ -291,6 +292,9 @@ 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
|
||||
|
||||
#endif /* MRUBY_ARRAY_H */
|
||||
|
||||
@@ -44,6 +44,9 @@ typedef struct mrb_value {
|
||||
};
|
||||
)
|
||||
};
|
||||
#ifdef MRB_64BIT
|
||||
struct RCptr *vp;
|
||||
#endif
|
||||
} value;
|
||||
};
|
||||
} mrb_value;
|
||||
@@ -54,13 +57,15 @@ typedef struct mrb_value {
|
||||
#define mrb_type(o) (enum mrb_vtype)((uint32_t)0xfff00000 < (o).value.ttt ? mrb_tt(o) : MRB_TT_FLOAT)
|
||||
#define mrb_ptr(o) ((void*)((((uintptr_t)0x3fffffffffff)&((uintptr_t)((o).value.p)))<<2))
|
||||
#define mrb_float(o) (o).f
|
||||
#define mrb_cptr(o) mrb_ptr(o)
|
||||
#define mrb_fixnum(o) (o).value.i
|
||||
#define mrb_symbol(o) (o).value.sym
|
||||
|
||||
#ifdef MRB_64BIT
|
||||
MRB_API mrb_value mrb_nan_boxing_cptr_value(struct mrb_state*, void*);
|
||||
#define mrb_cptr(o) (((struct RCptr*)mrb_ptr(o))->p)
|
||||
#define BOXNAN_SHIFT_LONG_POINTER(v) (((uintptr_t)(v)>>34)&0x3fff)
|
||||
#else
|
||||
#define mrb_cptr(o) ((o).value.p)
|
||||
#define BOXNAN_SHIFT_LONG_POINTER(v) 0
|
||||
#endif
|
||||
|
||||
@@ -90,7 +95,11 @@ typedef struct mrb_value {
|
||||
#define SET_INT_VALUE(r,n) BOXNAN_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n))
|
||||
#define SET_SYM_VALUE(r,v) BOXNAN_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v))
|
||||
#define SET_OBJ_VALUE(r,v) BOXNAN_SET_OBJ_VALUE(r, (((struct RObject*)(v))->tt), (v))
|
||||
#define SET_CPTR_VALUE(mrb,r,v) BOXNAN_SET_OBJ_VALUE(r, MRB_TT_CPTR, v)
|
||||
#ifdef MRB_64BIT
|
||||
#define SET_CPTR_VALUE(mrb,r,v) ((r) = mrb_nan_boxing_cptr_value(mrb, v))
|
||||
#else
|
||||
#define SET_CPTR_VALUE(mrb,r,v) BOXNAN_SET_VALUE(r, MRB_TT_CPTR, value.p, v)
|
||||
#endif
|
||||
#define SET_UNDEF_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0)
|
||||
|
||||
#endif /* MRUBY_BOXING_NAN_H */
|
||||
|
||||
@@ -18,11 +18,6 @@ struct RFloat {
|
||||
};
|
||||
#endif
|
||||
|
||||
struct RCptr {
|
||||
MRB_OBJECT_HEADER;
|
||||
void *p;
|
||||
};
|
||||
|
||||
enum mrb_special_consts {
|
||||
MRB_Qnil = 0,
|
||||
MRB_Qfalse = 4,
|
||||
@@ -142,7 +137,6 @@ MRB_API mrb_value mrb_word_boxing_float_pool(struct mrb_state*, mrb_float);
|
||||
#define mrb_sclass_p(o) BOXWORD_OBJ_TYPE_P(o, SCLASS)
|
||||
#define mrb_proc_p(o) BOXWORD_OBJ_TYPE_P(o, PROC)
|
||||
#define mrb_range_p(o) BOXWORD_OBJ_TYPE_P(o, RANGE)
|
||||
#define mrb_file_p(o) BOXWORD_OBJ_TYPE_P(o, FILE)
|
||||
#define mrb_env_p(o) BOXWORD_OBJ_TYPE_P(o, ENV)
|
||||
#define mrb_data_p(o) BOXWORD_OBJ_TYPE_P(o, DATA)
|
||||
#define mrb_fiber_p(o) BOXWORD_OBJ_TYPE_P(o, FIBER)
|
||||
|
||||
+11
-3
@@ -33,7 +33,7 @@ typedef struct mrbc_context {
|
||||
mrb_bool no_exec:1;
|
||||
mrb_bool keep_lv:1;
|
||||
mrb_bool no_optimize:1;
|
||||
mrb_bool on_eval:1;
|
||||
struct RProc *upper;
|
||||
|
||||
size_t parser_nerr;
|
||||
} mrbc_context;
|
||||
@@ -151,8 +151,8 @@ struct mrb_parser_state {
|
||||
mrb_ast_node *tree;
|
||||
|
||||
mrb_bool no_optimize:1;
|
||||
mrb_bool on_eval:1;
|
||||
mrb_bool capture_errors:1;
|
||||
struct RProc *upper;
|
||||
struct mrb_parser_message error_buffer[10];
|
||||
struct mrb_parser_message warn_buffer[10];
|
||||
|
||||
@@ -180,7 +180,15 @@ MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,size_t
|
||||
MRB_API struct RProc* mrb_generate_code(mrb_state*, struct mrb_parser_state*);
|
||||
MRB_API mrb_value mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c);
|
||||
|
||||
/* program load functions */
|
||||
/** program load functions
|
||||
* Please note! Currently due to interactions with the GC calling these functions will
|
||||
* leak one RProc object per function call.
|
||||
* To prevent this save the current memory arena before calling and restore the arena
|
||||
* right after, like so
|
||||
* int ai = mrb_gc_arena_save(mrb);
|
||||
* mrb_value status = mrb_load_string(mrb, buffer);
|
||||
* mrb_gc_arena_restore(mrb, ai);
|
||||
*/
|
||||
#ifndef MRB_DISABLE_STDIO
|
||||
MRB_API mrb_value mrb_load_file(mrb_state*,FILE*);
|
||||
MRB_API mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt);
|
||||
|
||||
+1
-17
@@ -17,10 +17,6 @@
|
||||
MRB_BEGIN_DECL
|
||||
|
||||
#define DUMP_DEBUG_INFO 1
|
||||
#define DUMP_ENDIAN_BIG 2
|
||||
#define DUMP_ENDIAN_LIL 4
|
||||
#define DUMP_ENDIAN_NAT 6
|
||||
#define DUMP_ENDIAN_MASK 6
|
||||
|
||||
int mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size);
|
||||
#ifndef MRB_DISABLE_STDIO
|
||||
@@ -52,8 +48,7 @@ MRB_API mrb_irep *mrb_read_irep_buf(mrb_state*, const void*, size_t);
|
||||
|
||||
/* Rite Binary File header */
|
||||
#define RITE_BINARY_IDENT "RITE"
|
||||
#define RITE_BINARY_IDENT_LIL "ETIR"
|
||||
#define RITE_BINARY_FORMAT_VER "0006"
|
||||
#define RITE_BINARY_FORMAT_VER "0007"
|
||||
#define RITE_COMPILER_NAME "MATZ"
|
||||
#define RITE_COMPILER_VERSION "0000"
|
||||
|
||||
@@ -106,17 +101,6 @@ struct rite_binary_footer {
|
||||
RITE_SECTION_HEADER;
|
||||
};
|
||||
|
||||
static inline int
|
||||
bigendian_p()
|
||||
{
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
i = 1;
|
||||
p = (char*)&i;
|
||||
return p[0]?0:1;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
uint8_to_bin(uint8_t s, uint8_t *bin)
|
||||
{
|
||||
|
||||
@@ -49,6 +49,16 @@ typedef struct mrb_irep {
|
||||
|
||||
MRB_API mrb_irep *mrb_add_irep(mrb_state *mrb);
|
||||
|
||||
/** load mruby bytecode functions
|
||||
* Please note! Currently due to interactions with the GC calling these functions will
|
||||
* leak one RProc object per function call.
|
||||
* To prevent this save the current memory arena before calling and restore the arena
|
||||
* right after, like so
|
||||
* int ai = mrb_gc_arena_save(mrb);
|
||||
* mrb_value status = mrb_load_irep(mrb, buffer);
|
||||
* mrb_gc_arena_restore(mrb, ai);
|
||||
*/
|
||||
|
||||
/* @param [const uint8_t*] irep code, expected as a literal */
|
||||
MRB_API mrb_value mrb_load_irep(mrb_state*, const uint8_t*);
|
||||
|
||||
|
||||
@@ -21,7 +21,10 @@ MRB_BEGIN_DECL
|
||||
|
||||
struct RIStruct {
|
||||
MRB_OBJECT_HEADER;
|
||||
char inline_data[ISTRUCT_DATA_SIZE];
|
||||
union {
|
||||
intptr_t inline_alignment[3];
|
||||
char inline_data[ISTRUCT_DATA_SIZE];
|
||||
};
|
||||
};
|
||||
|
||||
#define RISTRUCT(obj) ((struct RIStruct*)(mrb_ptr(obj)))
|
||||
|
||||
+23
-5
@@ -73,6 +73,7 @@ static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0};
|
||||
void kh_clear_##name(mrb_state *mrb, kh_##name##_t *h); \
|
||||
khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key); \
|
||||
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret); \
|
||||
void kh_put_prepare_##name(mrb_state *mrb, kh_##name##_t *h); \
|
||||
void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets); \
|
||||
void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x); \
|
||||
kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h);
|
||||
@@ -95,16 +96,25 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
|
||||
__hash_equal: hash comparation function
|
||||
*/
|
||||
#define KHASH_DEFINE(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
|
||||
void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h) \
|
||||
mrb_noreturn void mrb_raise_nomemory(mrb_state *mrb); \
|
||||
int kh_alloc_simple_##name(mrb_state *mrb, kh_##name##_t *h) \
|
||||
{ \
|
||||
khint_t sz = h->n_buckets; \
|
||||
size_t len = sizeof(khkey_t) + (kh_is_map ? sizeof(khval_t) : 0); \
|
||||
uint8_t *p = (uint8_t*)mrb_malloc(mrb, sizeof(uint8_t)*sz/4+len*sz); \
|
||||
uint8_t *p = (uint8_t*)mrb_malloc_simple(mrb, sizeof(uint8_t)*sz/4+len*sz); \
|
||||
if (!p) { return 1; } \
|
||||
h->size = h->n_occupied = 0; \
|
||||
h->keys = (khkey_t *)p; \
|
||||
h->vals = kh_is_map ? (khval_t *)(p+sizeof(khkey_t)*sz) : NULL; \
|
||||
h->ed_flags = p+len*sz; \
|
||||
kh_fill_flags(h->ed_flags, 0xaa, sz/4); \
|
||||
return 0; \
|
||||
} \
|
||||
void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h) \
|
||||
{ \
|
||||
if (kh_alloc_simple_##name(mrb, h)) { \
|
||||
mrb_raise_nomemory(mrb); \
|
||||
} \
|
||||
} \
|
||||
kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size) { \
|
||||
kh_##name##_t *h = (kh_##name##_t*)mrb_calloc(mrb, 1, sizeof(kh_##name##_t)); \
|
||||
@@ -112,7 +122,10 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
|
||||
size = KHASH_MIN_SIZE; \
|
||||
khash_power2(size); \
|
||||
h->n_buckets = size; \
|
||||
kh_alloc_##name(mrb, h); \
|
||||
if (kh_alloc_simple_##name(mrb, h)) { \
|
||||
mrb_free(mrb, h); \
|
||||
mrb_raise_nomemory(mrb); \
|
||||
} \
|
||||
return h; \
|
||||
} \
|
||||
kh_##name##_t *kh_init_##name(mrb_state *mrb) { \
|
||||
@@ -171,12 +184,16 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
|
||||
mrb_free(mrb, old_keys); \
|
||||
} \
|
||||
} \
|
||||
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) \
|
||||
void kh_put_prepare_##name(mrb_state *mrb, kh_##name##_t *h) \
|
||||
{ \
|
||||
khint_t k, del_k, step = 0; \
|
||||
if (h->n_occupied >= khash_upper_bound(h)) { \
|
||||
kh_resize_##name(mrb, h, h->n_buckets*2); \
|
||||
} \
|
||||
} \
|
||||
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) \
|
||||
{ \
|
||||
khint_t k, del_k, step = 0; \
|
||||
kh_put_prepare_##name(mrb, h); \
|
||||
k = __hash_func(mrb,key) & khash_mask(h); \
|
||||
del_k = kh_end(h); \
|
||||
while (!__ac_isempty(h->ed_flags, k)) { \
|
||||
@@ -239,6 +256,7 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
|
||||
#define kh_destroy(name, mrb, h) kh_destroy_##name(mrb, h)
|
||||
#define kh_clear(name, mrb, h) kh_clear_##name(mrb, h)
|
||||
#define kh_resize(name, mrb, h, s) kh_resize_##name(mrb, h, s)
|
||||
#define kh_put_prepare(name, mrb, h) kh_put_prepare_##name(mrb, h)
|
||||
#define kh_put(name, mrb, h, k) kh_put_##name(mrb, h, k, NULL)
|
||||
#define kh_put2(name, mrb, h, k, r) kh_put_##name(mrb, h, k, r)
|
||||
#define kh_get(name, mrb, h, k) kh_get_##name(mrb, h, k)
|
||||
|
||||
@@ -37,6 +37,7 @@ MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base);
|
||||
/* ArgumentError if format string doesn't match /%(\.[0-9]+)?[aAeEfFgG]/ */
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt);
|
||||
MRB_API int mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float f);
|
||||
MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x);
|
||||
MRB_API mrb_value mrb_int_value(mrb_state *mrb, mrb_float f);
|
||||
#endif
|
||||
|
||||
+3
-2
@@ -92,8 +92,8 @@ OPCODE(APOST, BBB) /* *R(a),R(a+1)..R(a+c) = R(a)[b..] */
|
||||
OPCODE(INTERN, B) /* R(a) = intern(R(a)) */
|
||||
OPCODE(STRING, BB) /* R(a) = str_dup(Lit(b)) */
|
||||
OPCODE(STRCAT, B) /* str_cat(R(a),R(a+1)) */
|
||||
OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b)) */
|
||||
OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b)) */
|
||||
OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b*2-1)) */
|
||||
OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b*2)) */
|
||||
OPCODE(HASHCAT, B) /* R(a) = hash_cat(R(a),R(a+1)) */
|
||||
OPCODE(LAMBDA, BB) /* R(a) = lambda(SEQ[b],L_LAMBDA) */
|
||||
OPCODE(BLOCK, BB) /* R(a) = lambda(SEQ[b],L_BLOCK) */
|
||||
@@ -115,3 +115,4 @@ OPCODE(EXT1, Z) /* make 1st operand 16bit */
|
||||
OPCODE(EXT2, Z) /* make 2nd operand 16bit */
|
||||
OPCODE(EXT3, Z) /* make 1st and 2nd operands 16bit */
|
||||
OPCODE(STOP, Z) /* stop VM */
|
||||
OPCODE(LOADI16, BS) /* R(a) = mrb_int(b) */
|
||||
|
||||
+13
-8
@@ -22,14 +22,19 @@ struct REnv {
|
||||
mrb_sym mid;
|
||||
};
|
||||
|
||||
/* flags (21bits): 1(shared flag):10(cioff/bidx):10(stack_len) */
|
||||
#define MRB_ENV_SET_STACK_LEN(e,len) ((e)->flags = (((e)->flags & ~0x3ff)|((unsigned int)(len) & 0x3ff)))
|
||||
#define MRB_ENV_STACK_LEN(e) ((mrb_int)((e)->flags & 0x3ff))
|
||||
#define MRB_ENV_STACK_UNSHARED (1<<20)
|
||||
#define MRB_ENV_UNSHARE_STACK(e) ((e)->flags |= MRB_ENV_STACK_UNSHARED)
|
||||
#define MRB_ENV_STACK_SHARED_P(e) (((e)->flags & MRB_ENV_STACK_UNSHARED) == 0)
|
||||
#define MRB_ENV_BIDX(e) (((e)->flags >> 10) & 0x3ff)
|
||||
#define MRB_ENV_SET_BIDX(e,idx) ((e)->flags = (((e)->flags & ~(0x3ff<<10))|((unsigned int)(idx) & 0x3ff)<<10))
|
||||
/* flags (21bits): 1(close):1(touched):1(heap):8(cioff/bidx):8(stack_len) */
|
||||
#define MRB_ENV_SET_LEN(e,len) ((e)->flags = (((e)->flags & ~0xff)|((unsigned int)(len) & 0xff)))
|
||||
#define MRB_ENV_LEN(e) ((mrb_int)((e)->flags & 0xff))
|
||||
#define MRB_ENV_CLOSED (1<<20)
|
||||
#define MRB_ENV_TOUCHED (1<<19)
|
||||
#define MRB_ENV_HEAPED (1<<18)
|
||||
#define MRB_ENV_CLOSE(e) ((e)->flags |= MRB_ENV_CLOSED)
|
||||
#define MRB_ENV_TOUCH(e) ((e)->flags |= MRB_ENV_TOUCHED)
|
||||
#define MRB_ENV_HEAP(e) ((e)->flags |= MRB_ENV_HEAPED)
|
||||
#define MRB_ENV_HEAP_P(e) ((e)->flags & MRB_ENV_HEAPED)
|
||||
#define MRB_ENV_ONSTACK_P(e) (((e)->flags & MRB_ENV_CLOSED) == 0)
|
||||
#define MRB_ENV_BIDX(e) (((e)->flags >> 8) & 0xff)
|
||||
#define MRB_ENV_SET_BIDX(e,idx) ((e)->flags = (((e)->flags & ~(0xff<<8))|((unsigned int)(idx) & 0xff)<<8))
|
||||
|
||||
void mrb_env_unshare(mrb_state*, struct REnv*);
|
||||
|
||||
|
||||
+32
-29
@@ -103,32 +103,31 @@ static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000;
|
||||
#endif
|
||||
|
||||
enum mrb_vtype {
|
||||
MRB_TT_FALSE = 0, /* 0 */
|
||||
MRB_TT_TRUE, /* 1 */
|
||||
MRB_TT_FLOAT, /* 2 */
|
||||
MRB_TT_FIXNUM, /* 3 */
|
||||
MRB_TT_SYMBOL, /* 4 */
|
||||
MRB_TT_UNDEF, /* 5 */
|
||||
MRB_TT_CPTR, /* 6 */
|
||||
MRB_TT_FREE, /* 7 */
|
||||
MRB_TT_OBJECT, /* 8 */
|
||||
MRB_TT_CLASS, /* 9 */
|
||||
MRB_TT_MODULE, /* 10 */
|
||||
MRB_TT_ICLASS, /* 11 */
|
||||
MRB_TT_SCLASS, /* 12 */
|
||||
MRB_TT_PROC, /* 13 */
|
||||
MRB_TT_ARRAY, /* 14 */
|
||||
MRB_TT_HASH, /* 15 */
|
||||
MRB_TT_STRING, /* 16 */
|
||||
MRB_TT_RANGE, /* 17 */
|
||||
MRB_TT_EXCEPTION, /* 18 */
|
||||
MRB_TT_FILE, /* 19 */
|
||||
MRB_TT_ENV, /* 20 */
|
||||
MRB_TT_DATA, /* 21 */
|
||||
MRB_TT_FIBER, /* 22 */
|
||||
MRB_TT_ISTRUCT, /* 23 */
|
||||
MRB_TT_BREAK, /* 24 */
|
||||
MRB_TT_MAXDEFINE /* 25 */
|
||||
MRB_TT_FALSE = 0,
|
||||
MRB_TT_TRUE,
|
||||
MRB_TT_FLOAT,
|
||||
MRB_TT_FIXNUM,
|
||||
MRB_TT_SYMBOL,
|
||||
MRB_TT_UNDEF,
|
||||
MRB_TT_CPTR,
|
||||
MRB_TT_FREE,
|
||||
MRB_TT_OBJECT,
|
||||
MRB_TT_CLASS,
|
||||
MRB_TT_MODULE,
|
||||
MRB_TT_ICLASS,
|
||||
MRB_TT_SCLASS,
|
||||
MRB_TT_PROC,
|
||||
MRB_TT_ARRAY,
|
||||
MRB_TT_HASH,
|
||||
MRB_TT_STRING,
|
||||
MRB_TT_RANGE,
|
||||
MRB_TT_EXCEPTION,
|
||||
MRB_TT_ENV,
|
||||
MRB_TT_DATA,
|
||||
MRB_TT_FIBER,
|
||||
MRB_TT_ISTRUCT,
|
||||
MRB_TT_BREAK,
|
||||
MRB_TT_MAXDEFINE
|
||||
};
|
||||
|
||||
#include <mruby/object.h>
|
||||
@@ -149,6 +148,13 @@ typedef void mrb_value;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(MRB_WORD_BOXING) || (defined(MRB_NAN_BOXING) && defined(MRB_64BIT))
|
||||
struct RCptr {
|
||||
MRB_OBJECT_HEADER;
|
||||
void *p;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(MRB_NAN_BOXING)
|
||||
#include "boxing_nan.h"
|
||||
#elif defined(MRB_WORD_BOXING)
|
||||
@@ -233,9 +239,6 @@ typedef void mrb_value;
|
||||
#ifndef mrb_range_p
|
||||
#define mrb_range_p(o) (mrb_type(o) == MRB_TT_RANGE)
|
||||
#endif
|
||||
#ifndef mrb_file_p
|
||||
#define mrb_file_p(o) (mrb_type(o) == MRB_TT_FILE)
|
||||
#endif
|
||||
#ifndef mrb_env_p
|
||||
#define mrb_env_p(o) (mrb_type(o) == MRB_TT_ENV)
|
||||
#endif
|
||||
|
||||
@@ -47,7 +47,7 @@ MRB_BEGIN_DECL
|
||||
/*
|
||||
* Tiny release version number.
|
||||
*/
|
||||
#define MRUBY_RELEASE_TEENY 1
|
||||
#define MRUBY_RELEASE_TEENY 2
|
||||
|
||||
/*
|
||||
* The mruby version.
|
||||
@@ -67,12 +67,12 @@ MRB_BEGIN_DECL
|
||||
/*
|
||||
* Release month.
|
||||
*/
|
||||
#define MRUBY_RELEASE_MONTH 6
|
||||
#define MRUBY_RELEASE_MONTH 7
|
||||
|
||||
/*
|
||||
* Release day.
|
||||
*/
|
||||
#define MRUBY_RELEASE_DAY 4
|
||||
#define MRUBY_RELEASE_DAY 10
|
||||
|
||||
/*
|
||||
* Release date as a string.
|
||||
|
||||
+2
-22
@@ -336,7 +336,8 @@ EOS
|
||||
puts " Binaries: #{@bins.join(', ')}" unless @bins.empty?
|
||||
unless @gems.empty?
|
||||
puts " Included Gems:"
|
||||
@gems.map do |gem|
|
||||
gems = @gems.sort_by { |gem| gem.name }
|
||||
gems.each do |gem|
|
||||
gem_version = " - #{gem.version}" if gem.version != '0.0.0'
|
||||
gem_summary = " - #{gem.summary}" if gem.summary
|
||||
puts " #{gem.name}#{gem_version}#{gem_summary}"
|
||||
@@ -387,26 +388,5 @@ EOS
|
||||
@test_runner.run(mrbtest)
|
||||
end
|
||||
end
|
||||
|
||||
def big_endian
|
||||
if @endian
|
||||
puts "Endian has already specified as #{@endian}."
|
||||
return
|
||||
end
|
||||
@endian = :big
|
||||
@mrbc.compile_options += ' -E'
|
||||
compilers.each do |c|
|
||||
c.defines += %w(MRB_ENDIAN_BIG)
|
||||
end
|
||||
end
|
||||
|
||||
def little_endian
|
||||
if @endian
|
||||
puts "Endian has already specified as #{@endian}."
|
||||
return
|
||||
end
|
||||
@endian = :little
|
||||
@mrbc.compile_options += ' -e'
|
||||
end
|
||||
end # CrossBuild
|
||||
end # MRuby
|
||||
|
||||
+3
-1
@@ -6,7 +6,9 @@ module MRuby
|
||||
ROOT = Pathname.new(File.expand_path('../../../',__FILE__))
|
||||
|
||||
# Reads a constant defined at version.h
|
||||
MRUBY_READ_VERSION_CONSTANT = Proc.new { |name| ROOT.join('include','mruby','version.h').read.match(/^#define #{name} +"?([\w\. ]+)"?$/)[1] }
|
||||
MRUBY_READ_VERSION_CONSTANT = Proc.new do |name|
|
||||
ROOT.join('include','mruby','version.h').read.match(/^#define #{name} +"?([\w\. ]+)"?\r?$/)[1]
|
||||
end
|
||||
|
||||
MRUBY_RUBY_VERSION = MRUBY_READ_VERSION_CONSTANT['MRUBY_RUBY_VERSION']
|
||||
MRUBY_RUBY_ENGINE = MRUBY_READ_VERSION_CONSTANT['MRUBY_RUBY_ENGINE']
|
||||
|
||||
@@ -71,6 +71,10 @@ MRuby::GemBox.new do |conf|
|
||||
# Use toplevel object (main) methods extension
|
||||
conf.gem :core => "mruby-toplevel-ext"
|
||||
|
||||
# Use Rational/Complex numbers
|
||||
conf.gem :core => "mruby-rational"
|
||||
conf.gem :core => "mruby-complex"
|
||||
|
||||
# Generate mirb command
|
||||
conf.gem :core => "mruby-bin-mirb"
|
||||
|
||||
@@ -89,6 +93,9 @@ MRuby::GemBox.new do |conf|
|
||||
# Use Method/UnboundMethod class
|
||||
conf.gem :core => "mruby-method"
|
||||
|
||||
# Use eval()
|
||||
conf.gem :core => "mruby-eval"
|
||||
|
||||
# Use mruby-compiler to build other mrbgems
|
||||
conf.gem :core => "mruby-compiler"
|
||||
end
|
||||
|
||||
@@ -28,9 +28,8 @@ static mrb_value
|
||||
mrb_ary_assoc(mrb_state *mrb, mrb_value ary)
|
||||
{
|
||||
mrb_int i;
|
||||
mrb_value v, k;
|
||||
|
||||
mrb_get_args(mrb, "o", &k);
|
||||
mrb_value v;
|
||||
mrb_value k = mrb_get_arg1(mrb);
|
||||
|
||||
for (i = 0; i < RARRAY_LEN(ary); ++i) {
|
||||
v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]);
|
||||
@@ -59,9 +58,8 @@ static mrb_value
|
||||
mrb_ary_rassoc(mrb_state *mrb, mrb_value ary)
|
||||
{
|
||||
mrb_int i;
|
||||
mrb_value v, value;
|
||||
|
||||
mrb_get_args(mrb, "o", &value);
|
||||
mrb_value v;
|
||||
mrb_value value = mrb_get_arg1(mrb);
|
||||
|
||||
for (i = 0; i < RARRAY_LEN(ary); ++i) {
|
||||
v = RARRAY_PTR(ary)[i];
|
||||
@@ -140,9 +138,8 @@ mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
|
||||
mrb_ary_modify(mrb, a);
|
||||
|
||||
if (mrb_get_argc(mrb) == 1) {
|
||||
mrb_value index;
|
||||
mrb_value index = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o|i", &index, &len);
|
||||
switch (mrb_type(index)) {
|
||||
case MRB_TT_RANGE:
|
||||
if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == MRB_RANGE_OK) {
|
||||
|
||||
@@ -5,13 +5,16 @@ unless MRuby::Build.current.kind_of?(MRuby::CrossBuild)
|
||||
spec.author = 'mruby developers'
|
||||
spec.summary = "#{name} command"
|
||||
|
||||
mruby_config_dir = "#{build.build_dir}/bin"
|
||||
mruby_config = name + (ENV['OS'] == 'Windows_NT' ? '.bat' : '')
|
||||
mruby_config_path = "#{build.build_dir}/bin/#{mruby_config}"
|
||||
mruby_config_path = "#{mruby_config_dir}/#{mruby_config}"
|
||||
make_cfg = "#{build.build_dir}/lib/libmruby.flags.mak"
|
||||
tmplt_path = "#{__dir__}/#{mruby_config}"
|
||||
build.bins << mruby_config
|
||||
|
||||
file mruby_config_path => [make_cfg, tmplt_path] do |t|
|
||||
directory mruby_config_dir
|
||||
|
||||
file mruby_config_path => [mruby_config_dir, make_cfg, tmplt_path] do |t|
|
||||
config = Hash[File.readlines(make_cfg).map!(&:chomp).map! {|l|
|
||||
l.gsub('\\"', '"').split(' = ', 2).map! {|s| s.sub(/^(?=.)/, 'echo ')}
|
||||
}]
|
||||
|
||||
@@ -649,8 +649,8 @@ main(int argc, char **argv)
|
||||
/* adjust stack length of toplevel environment */
|
||||
if (mrb->c->cibase->env) {
|
||||
struct REnv *e = mrb->c->cibase->env;
|
||||
if (e && MRB_ENV_STACK_LEN(e) < proc->body.irep->nlocals) {
|
||||
MRB_ENV_SET_STACK_LEN(e, proc->body.irep->nlocals);
|
||||
if (e && MRB_ENV_LEN(e) < proc->body.irep->nlocals) {
|
||||
MRB_ENV_SET_LEN(e, proc->body.irep->nlocals);
|
||||
}
|
||||
}
|
||||
/* pass a proc for evaluation */
|
||||
|
||||
@@ -36,8 +36,6 @@ usage(const char *name)
|
||||
"-v print version number, then turn on verbose mode",
|
||||
"-g produce debugging information",
|
||||
"-B<symbol> binary <symbol> output in C language format",
|
||||
"-e generate little endian iseq data",
|
||||
"-E generate big endian iseq data",
|
||||
"--remove-lv remove local variables",
|
||||
"--verbose run at verbose mode",
|
||||
"--version print the version",
|
||||
@@ -54,19 +52,26 @@ usage(const char *name)
|
||||
static char *
|
||||
get_outfilename(mrb_state *mrb, char *infile, const char *ext)
|
||||
{
|
||||
size_t infilelen;
|
||||
size_t extlen;
|
||||
size_t ilen, flen, elen;
|
||||
char *outfile;
|
||||
char *p;
|
||||
char *p = NULL;
|
||||
|
||||
infilelen = strlen(infile);
|
||||
extlen = strlen(ext);
|
||||
outfile = (char*)mrb_malloc(mrb, infilelen + extlen + 1);
|
||||
memcpy(outfile, infile, infilelen + 1);
|
||||
ilen = strlen(infile);
|
||||
flen = ilen;
|
||||
if (*ext) {
|
||||
if ((p = strrchr(outfile, '.')) == NULL)
|
||||
p = outfile + infilelen;
|
||||
memcpy(p, ext, extlen + 1);
|
||||
elen = strlen(ext);
|
||||
if ((p = strrchr(infile, '.'))) {
|
||||
ilen = p - infile;
|
||||
}
|
||||
flen += elen;
|
||||
}
|
||||
else {
|
||||
flen = ilen;
|
||||
}
|
||||
outfile = (char*)mrb_malloc(mrb, flen+1);
|
||||
strncpy(outfile, infile, ilen+1);
|
||||
if (p) {
|
||||
strncpy(outfile+ilen, ext, elen+1);
|
||||
}
|
||||
|
||||
return outfile;
|
||||
@@ -124,10 +129,8 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
|
||||
args->flags |= DUMP_DEBUG_INFO;
|
||||
break;
|
||||
case 'E':
|
||||
args->flags = DUMP_ENDIAN_BIG | (args->flags & ~DUMP_ENDIAN_MASK);
|
||||
break;
|
||||
case 'e':
|
||||
args->flags = DUMP_ENDIAN_LIL | (args->flags & ~DUMP_ENDIAN_MASK);
|
||||
fprintf(stderr, "%s: -e/-E option no longer needed.\n", args->prog);
|
||||
break;
|
||||
case 'h':
|
||||
return -1;
|
||||
@@ -160,10 +163,6 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (args->verbose && args->initname && (args->flags & DUMP_ENDIAN_MASK) == 0) {
|
||||
fprintf(stderr, "%s: generating %s endian C file. specify -e/-E for cross compiling.\n",
|
||||
args->prog, bigendian_p() ? "big" : "little");
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ MRuby::Gem::Specification.new('mruby-bin-mruby') do |spec|
|
||||
spec.summary = 'mruby command'
|
||||
spec.bins = %w(mruby)
|
||||
spec.add_dependency('mruby-compiler', :core => 'mruby-compiler')
|
||||
spec.add_dependency('mruby-error', :core => 'mruby-error')
|
||||
spec.add_test_dependency('mruby-print', :core => 'mruby-print')
|
||||
|
||||
if build.cxx_exception_enabled?
|
||||
|
||||
@@ -43,10 +43,15 @@ mrb_mod_module_exec(mrb_state *mrb, mrb_value self)
|
||||
const mrb_value *argv;
|
||||
mrb_int argc;
|
||||
mrb_value blk;
|
||||
struct RClass *c;
|
||||
|
||||
mrb_get_args(mrb, "*&!", &argv, &argc, &blk);
|
||||
|
||||
mrb->c->ci->target_class = mrb_class_ptr(self);
|
||||
c = mrb_class_ptr(self);
|
||||
if (mrb->c->ci->acc < 0) {
|
||||
return mrb_yield_with_class(mrb, blk, argc, argv, self, c);
|
||||
}
|
||||
mrb->c->ci->target_class = c;
|
||||
return mrb_yield_cont(mrb, blk, self, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
@@ -281,15 +281,6 @@ no_optimize(codegen_scope *s)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
mrb_bool
|
||||
on_eval(codegen_scope *s)
|
||||
{
|
||||
if (s && s->parser && s->parser->on_eval)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
struct mrb_insn_data
|
||||
mrb_decode_insn(const mrb_code *pc)
|
||||
{
|
||||
@@ -407,9 +398,6 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
|
||||
if (no_peephole(s)) {
|
||||
normal:
|
||||
genop_2(s, OP_MOVE, dst, src);
|
||||
if (on_eval(s)) {
|
||||
genop_0(s, OP_NOP);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
@@ -674,6 +662,43 @@ lv_idx(codegen_scope *s, mrb_sym id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
search_upvar(codegen_scope *s, mrb_sym id, int *idx)
|
||||
{
|
||||
struct RProc *u;
|
||||
int lv = 0;
|
||||
codegen_scope *up = s->prev;
|
||||
|
||||
while (up) {
|
||||
*idx = lv_idx(up, id);
|
||||
if (*idx > 0) {
|
||||
return lv;
|
||||
}
|
||||
lv ++;
|
||||
up = up->prev;
|
||||
}
|
||||
|
||||
if (lv < 1) lv = 1;
|
||||
u = s->parser->upper;
|
||||
while (u && !MRB_PROC_CFUNC_P(u)) {
|
||||
struct mrb_irep *ir = u->body.irep;
|
||||
uint_fast16_t n = ir->nlocals;
|
||||
const struct mrb_locals *v = ir->lv;
|
||||
for (; n > 1; n --, v ++) {
|
||||
if (v->name == id) {
|
||||
*idx = v->r;
|
||||
return lv - 1;
|
||||
}
|
||||
}
|
||||
if (MRB_PROC_SCOPE_P(u)) break;
|
||||
u = u->upper;
|
||||
lv ++;
|
||||
}
|
||||
|
||||
codegen_error(s, "Can't found local variables");
|
||||
return -1; /* not reached */
|
||||
}
|
||||
|
||||
static void
|
||||
for_body(codegen_scope *s, node *tree)
|
||||
{
|
||||
@@ -786,12 +811,19 @@ lambda_body(codegen_scope *s, node *tree, int blk)
|
||||
i = 0;
|
||||
while (opt) {
|
||||
int idx;
|
||||
mrb_sym id = nsym(opt->car->car);
|
||||
|
||||
dispatch(s, pos+i*3+1);
|
||||
codegen(s, opt->car->cdr, VAL);
|
||||
pop();
|
||||
idx = lv_idx(s, nsym(opt->car->car));
|
||||
gen_move(s, idx, cursp(), 0);
|
||||
idx = lv_idx(s, id);
|
||||
if (idx > 0) {
|
||||
gen_move(s, idx, cursp(), 0);
|
||||
}
|
||||
else {
|
||||
int lv = search_upvar(s, id, &idx);
|
||||
genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
|
||||
}
|
||||
i++;
|
||||
opt = opt->cdr;
|
||||
}
|
||||
@@ -818,11 +850,19 @@ lambda_body(codegen_scope *s, node *tree, int blk)
|
||||
mrb_assert(nint(kwd->car) == NODE_KW_ARG);
|
||||
|
||||
if (def_arg) {
|
||||
int idx;
|
||||
genop_2(s, OP_KEY_P, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
|
||||
jmpif_key_p = genjmp2(s, OP_JMPIF, lv_idx(s, kwd_sym), 0, 0);
|
||||
codegen(s, def_arg, VAL);
|
||||
pop();
|
||||
gen_move(s, lv_idx(s, kwd_sym), cursp(), 0);
|
||||
idx = lv_idx(s, kwd_sym);
|
||||
if (idx > 0) {
|
||||
gen_move(s, idx, cursp(), 0);
|
||||
}
|
||||
else {
|
||||
int lv = search_upvar(s, kwd_sym, &idx);
|
||||
genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
|
||||
}
|
||||
jmp_def_set = genjmp(s, OP_JMP, 0);
|
||||
dispatch(s, jmpif_key_p);
|
||||
}
|
||||
@@ -1103,23 +1143,12 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
|
||||
if (idx > 0) {
|
||||
if (idx != sp) {
|
||||
gen_move(s, idx, sp, val);
|
||||
if (val && on_eval(s)) genop_0(s, OP_NOP);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else { /* upvar */
|
||||
int lv = 0;
|
||||
codegen_scope *up = s->prev;
|
||||
|
||||
while (up) {
|
||||
idx = lv_idx(up, nsym(tree));
|
||||
if (idx > 0) {
|
||||
genop_3(s, OP_SETUPVAR, sp, idx, lv);
|
||||
break;
|
||||
}
|
||||
lv++;
|
||||
up = up->prev;
|
||||
}
|
||||
int lv = search_upvar(s, nsym(tree), &idx);
|
||||
genop_3(s, OP_SETUPVAR, sp, idx, lv);
|
||||
}
|
||||
break;
|
||||
case NODE_NVAR:
|
||||
@@ -1860,7 +1889,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
len++;
|
||||
}
|
||||
tree = tree->cdr;
|
||||
if (val && len == 255) {
|
||||
if (val && cursp() > 127) {
|
||||
pop_n(len*2);
|
||||
if (!update) {
|
||||
genop_2(s, OP_HASH, cursp(), len);
|
||||
@@ -2324,21 +2353,10 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
|
||||
if (idx > 0) {
|
||||
gen_move(s, cursp(), idx, val);
|
||||
if (val && on_eval(s)) genop_0(s, OP_NOP);
|
||||
}
|
||||
else {
|
||||
int lv = 0;
|
||||
codegen_scope *up = s->prev;
|
||||
|
||||
while (up) {
|
||||
idx = lv_idx(up, nsym(tree));
|
||||
if (idx > 0) {
|
||||
genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
|
||||
break;
|
||||
}
|
||||
lv++;
|
||||
up = up->prev;
|
||||
}
|
||||
int lv = search_upvar(s, nsym(tree), &idx);
|
||||
genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
|
||||
}
|
||||
push();
|
||||
}
|
||||
@@ -2349,7 +2367,6 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
int idx = nint(tree);
|
||||
|
||||
gen_move(s, cursp(), idx, val);
|
||||
if (val && on_eval(s)) genop_0(s, OP_NOP);
|
||||
|
||||
push();
|
||||
}
|
||||
@@ -2440,12 +2457,20 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (i == -1) genop_1(s, OP_LOADI__1, cursp());
|
||||
else if (i < 0) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
|
||||
if (i < 0) {
|
||||
if (i == -1) genop_1(s, OP_LOADI__1, cursp());
|
||||
else if (i >= -0xff) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
|
||||
else if (i >= -0x8000) genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i);
|
||||
else goto lit_int;
|
||||
}
|
||||
else if (i < 8) genop_1(s, OP_LOADI_0 + (uint8_t)i, cursp());
|
||||
else if (i <= 0xffff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i);
|
||||
else if (i <= 0xff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i);
|
||||
else if (i <= 0x7fff) genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i);
|
||||
else {
|
||||
int off = new_lit(s, mrb_fixnum_value(i));
|
||||
int off;
|
||||
|
||||
lit_int:
|
||||
off = new_lit(s, mrb_fixnum_value(i));
|
||||
genop_2(s, OP_LOADL, cursp(), off);
|
||||
}
|
||||
}
|
||||
@@ -2501,9 +2526,12 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
else {
|
||||
#endif
|
||||
if (i == -1) genop_1(s, OP_LOADI__1, cursp());
|
||||
else if (i >= -0xffff) {
|
||||
else if (i >= -0xff) {
|
||||
genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
|
||||
}
|
||||
else if (i >= -0x8000) {
|
||||
genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i);
|
||||
}
|
||||
else {
|
||||
int off = new_lit(s, mrb_fixnum_value(i));
|
||||
genop_2(s, OP_LOADL, cursp(), off);
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#ifdef PARSER_DEBUG
|
||||
# define YYDEBUG 1
|
||||
#endif
|
||||
#define YYERROR_VERBOSE 1
|
||||
#define YYSTACK_USE_ALLOCA 1
|
||||
|
||||
#include <ctype.h>
|
||||
@@ -266,6 +265,7 @@ local_unnest(parser_state *p)
|
||||
static mrb_bool
|
||||
local_var_p(parser_state *p, mrb_sym sym)
|
||||
{
|
||||
struct RProc *u;
|
||||
node *l = p->locals;
|
||||
|
||||
while (l) {
|
||||
@@ -276,6 +276,18 @@ local_var_p(parser_state *p, mrb_sym sym)
|
||||
}
|
||||
l = l->cdr;
|
||||
}
|
||||
|
||||
u = p->upper;
|
||||
while (u && !MRB_PROC_CFUNC_P(u)) {
|
||||
struct mrb_irep *ir = u->body.irep;
|
||||
uint_fast16_t n = ir->nlocals;
|
||||
const struct mrb_locals *v = ir->lv;
|
||||
for (; n > 1; n --, v ++) {
|
||||
if (v->name == sym) return TRUE;
|
||||
}
|
||||
if (MRB_PROC_SCOPE_P(u)) break;
|
||||
u = u->upper;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -827,6 +839,13 @@ new_kw_arg(parser_state *p, mrb_sym kw, node *def_arg)
|
||||
return list3((node*)NODE_KW_ARG, nsym(kw), def_arg);
|
||||
}
|
||||
|
||||
/* (:kw_rest_args . a) */
|
||||
static node*
|
||||
new_kw_rest_args(parser_state *p, node *a)
|
||||
{
|
||||
return cons((node*)NODE_KW_REST_ARGS, a);
|
||||
}
|
||||
|
||||
/* (:block_arg . a) */
|
||||
static node*
|
||||
new_block_arg(parser_state *p, node *a)
|
||||
@@ -1323,7 +1342,8 @@ heredoc_end(parser_state *p)
|
||||
|
||||
%}
|
||||
|
||||
%pure-parser
|
||||
%define parse.error verbose
|
||||
%define api.pure
|
||||
%parse-param {parser_state *p}
|
||||
%lex-param {parser_state *p}
|
||||
|
||||
@@ -2265,6 +2285,30 @@ paren_args : '(' opt_call_args ')'
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| '(' tDOT3 rparen
|
||||
{
|
||||
#if 1
|
||||
mrb_sym r = mrb_intern_lit(p->mrb, "*");
|
||||
mrb_sym b = mrb_intern_lit(p->mrb, "&");
|
||||
if (local_var_p(p, r) && local_var_p(p, b)) {
|
||||
$$ = cons(list1(new_splat(p, new_lvar(p, r))),
|
||||
new_block_arg(p, new_lvar(p, b)));
|
||||
}
|
||||
#else
|
||||
mrb_sym r = mrb_intern_lit(p->mrb, "*");
|
||||
mrb_sym k = mrb_intern_lit(p->mrb, "**");
|
||||
mrb_sym b = mrb_intern_lit(p->mrb, "&");
|
||||
if (local_var_p(p, r) && local_var_p(p, k) && local_var_p(p, b)) {
|
||||
$$ = cons(list2(new_splat(p, new_lvar(p, r)),
|
||||
new_kw_hash(p, list1(cons(new_kw_rest_args(p, 0), new_lvar(p, k))))),
|
||||
new_block_arg(p, new_lvar(p, b)));
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
yyerror(p, "unexpected argument forwarding ...");
|
||||
$$ = 0;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
opt_paren_args : none
|
||||
@@ -3361,6 +3405,24 @@ f_arglist : '(' f_args rparen
|
||||
p->lstate = EXPR_BEG;
|
||||
p->cmd_start = TRUE;
|
||||
}
|
||||
| '(' tDOT3 rparen
|
||||
{
|
||||
#if 1
|
||||
/* til real keyword args implemented */
|
||||
mrb_sym r = mrb_intern_lit(p->mrb, "*");
|
||||
mrb_sym b = mrb_intern_lit(p->mrb, "&");
|
||||
local_add_f(p, r);
|
||||
$$ = new_args(p, 0, 0, r, 0,
|
||||
new_args_tail(p, 0, 0, b));
|
||||
#else
|
||||
mrb_sym r = mrb_intern_lit(p->mrb, "*");
|
||||
mrb_sym k = mrb_intern_lit(p->mrb, "**");
|
||||
mrb_sym b = mrb_intern_lit(p->mrb, "&");
|
||||
local_add_f(p, r); local_add_f(p, k);
|
||||
$$ = new_args(p, 0, 0, r, 0,
|
||||
new_args_tail(p, 0, new_kw_rest_args(p, nsym(k)), b));
|
||||
#endif
|
||||
}
|
||||
| f_args term
|
||||
{
|
||||
$$ = $1;
|
||||
@@ -3424,11 +3486,11 @@ kwrest_mark : tPOW
|
||||
|
||||
f_kwrest : kwrest_mark tIDENTIFIER
|
||||
{
|
||||
$$ = cons((node*)NODE_KW_REST_ARGS, nsym($2));
|
||||
$$ = new_kw_rest_args(p, nsym($2));
|
||||
}
|
||||
| kwrest_mark
|
||||
{
|
||||
$$ = cons((node*)NODE_KW_REST_ARGS, 0);
|
||||
$$ = new_kw_rest_args(p, 0);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -3743,7 +3805,7 @@ assoc : arg tASSOC arg
|
||||
| tDSTAR arg
|
||||
{
|
||||
void_expr_error(p, $2);
|
||||
$$ = cons(cons((node*)NODE_KW_REST_ARGS, 0), $2);
|
||||
$$ = cons(new_kw_rest_args(p, 0), $2);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -3807,7 +3869,7 @@ term : ';' {yyerrok;}
|
||||
|
||||
nl : '\n'
|
||||
{
|
||||
p->lineno++;
|
||||
p->lineno += $<num>1;
|
||||
p->column = 0;
|
||||
}
|
||||
;
|
||||
@@ -4795,6 +4857,7 @@ static int
|
||||
parser_yylex(parser_state *p)
|
||||
{
|
||||
int32_t c;
|
||||
int nlines = 1;
|
||||
int space_seen = 0;
|
||||
int cmd_state;
|
||||
enum mrb_lex_state_enum last_state;
|
||||
@@ -4852,6 +4915,7 @@ parser_yylex(parser_state *p)
|
||||
break;
|
||||
}
|
||||
if (p->parsing_heredoc != NULL) {
|
||||
pylval.num = nlines;
|
||||
return '\n';
|
||||
}
|
||||
while ((c = nextc(p))) {
|
||||
@@ -4861,13 +4925,13 @@ parser_yylex(parser_state *p)
|
||||
space_seen = 1;
|
||||
break;
|
||||
case '#': /* comment as a whitespace */
|
||||
pushback(p, '#');
|
||||
p->lineno++;
|
||||
goto retry;
|
||||
skip(p, '\n');
|
||||
nlines++;
|
||||
break;
|
||||
case '.':
|
||||
if (!peek(p, '.')) {
|
||||
pushback(p, '.');
|
||||
p->lineno++;
|
||||
p->lineno+=nlines; nlines=1;
|
||||
goto retry;
|
||||
}
|
||||
pushback(p, c);
|
||||
@@ -4875,7 +4939,7 @@ parser_yylex(parser_state *p)
|
||||
case '&':
|
||||
if (peek(p, '.')) {
|
||||
pushback(p, '&');
|
||||
p->lineno++;
|
||||
p->lineno+=nlines; nlines=1;
|
||||
goto retry;
|
||||
}
|
||||
pushback(p, c);
|
||||
@@ -4891,6 +4955,7 @@ parser_yylex(parser_state *p)
|
||||
normal_newline:
|
||||
p->cmd_start = TRUE;
|
||||
p->lstate = EXPR_BEG;
|
||||
pylval.num = nlines;
|
||||
return '\n';
|
||||
|
||||
case '*':
|
||||
@@ -4973,7 +5038,7 @@ parser_yylex(parser_state *p)
|
||||
c = nextc(p);
|
||||
} while (!(c < 0 || ISSPACE(c)));
|
||||
if (c != '\n') skip(p, '\n');
|
||||
p->lineno++;
|
||||
p->lineno+=nlines; nlines=1;
|
||||
p->column = 0;
|
||||
goto retry;
|
||||
}
|
||||
@@ -5695,7 +5760,7 @@ parser_yylex(parser_state *p)
|
||||
case '\\':
|
||||
c = nextc(p);
|
||||
if (c == '\n') {
|
||||
p->lineno++;
|
||||
p->lineno+=nlines; nlines=1;
|
||||
p->column = 0;
|
||||
space_seen = 1;
|
||||
goto retry; /* skip \\n */
|
||||
@@ -6140,7 +6205,7 @@ parser_init_cxt(parser_state *p, mrbc_context *cxt)
|
||||
}
|
||||
p->capture_errors = cxt->capture_errors;
|
||||
p->no_optimize = cxt->no_optimize;
|
||||
p->on_eval = cxt->on_eval;
|
||||
p->upper = cxt->upper;
|
||||
if (cxt->partial_hook) {
|
||||
p->cxt = cxt;
|
||||
}
|
||||
@@ -6559,7 +6624,7 @@ dump_args(mrb_state *mrb, node *n, int offset)
|
||||
static const char*
|
||||
str_dump(mrb_state *mrb, const char *str, int len)
|
||||
{
|
||||
mrb_int ai = mrb_gc_arena_save(mrb);
|
||||
int ai = mrb_gc_arena_save(mrb);
|
||||
mrb_value s;
|
||||
# if INT_MAX > MRB_INT_MAX / 4
|
||||
/* check maximum length with "\xNN" charactor */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,35 +3,33 @@ MRuby::Gem::Specification.new 'mruby-compiler' do |spec|
|
||||
spec.author = 'mruby developers'
|
||||
spec.summary = 'mruby compiler library'
|
||||
|
||||
current_dir = spec.dir
|
||||
current_build_dir = spec.build_dir
|
||||
|
||||
lex_def = "#{current_dir}/core/lex.def"
|
||||
core_objs = Dir.glob("#{current_dir}/core/*.c").map { |f|
|
||||
lex_def = "#{dir}/core/lex.def"
|
||||
core_objs = Dir.glob("#{dir}/core/*.c").map { |f|
|
||||
next nil if build.cxx_exception_enabled? and f =~ /(codegen).c$/
|
||||
objfile(f.pathmap("#{current_build_dir}/core/%n"))
|
||||
objfile(f.pathmap("#{build_dir}/core/%n"))
|
||||
}.compact
|
||||
|
||||
if build.cxx_exception_enabled?
|
||||
core_objs <<
|
||||
build.compile_as_cxx("#{current_build_dir}/core/y.tab.c", "#{current_build_dir}/core/y.tab.cxx",
|
||||
objfile("#{current_build_dir}/y.tab"), ["#{current_dir}/core"]) <<
|
||||
build.compile_as_cxx("#{current_dir}/core/codegen.c", "#{current_build_dir}/core/codegen.cxx")
|
||||
build.compile_as_cxx("#{dir}/core/y.tab.c", "#{build_dir}/core/y.tab.cxx",
|
||||
objfile("#{build_dir}/y.tab"), ["#{dir}/core"]) <<
|
||||
build.compile_as_cxx("#{dir}/core/codegen.c", "#{build_dir}/core/codegen.cxx")
|
||||
else
|
||||
core_objs << objfile("#{current_build_dir}/core/y.tab")
|
||||
file objfile("#{current_build_dir}/core/y.tab") => "#{current_build_dir}/core/y.tab.c" do |t|
|
||||
cc.run t.name, t.prerequisites.first, [], ["#{current_dir}/core"]
|
||||
core_objs << objfile("#{build_dir}/core/y.tab")
|
||||
file objfile("#{build_dir}/core/y.tab") => "#{dir}/core/y.tab.c" do |t|
|
||||
cc.run t.name, t.prerequisites.first, [], ["#{dir}/core"]
|
||||
end
|
||||
end
|
||||
|
||||
# Parser
|
||||
file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y", lex_def] do |t|
|
||||
mkdir_p File.dirname t.name
|
||||
file "#{dir}/core/y.tab.c" => ["#{dir}/core/parse.y", lex_def] do |t|
|
||||
yacc.run t.name, t.prerequisites.first
|
||||
content = File.read(t.name).gsub(/^#line +\d+ +"\K.*$/){$&.relative_path}
|
||||
File.write(t.name, content)
|
||||
end
|
||||
|
||||
# Lexical analyzer
|
||||
file lex_def => "#{current_dir}/core/keywords" do |t|
|
||||
file lex_def => "#{dir}/core/keywords" do |t|
|
||||
gperf.run t.name, t.prerequisites.first
|
||||
end
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ class Complex < Numeric
|
||||
[Fixnum, Float].each do |cls|
|
||||
[:+, :-, :*, :/, :==].each do |op|
|
||||
cls.instance_eval do
|
||||
original_operator_name = "__original_operator_#{op}_complex"
|
||||
original_operator_name = :"__original_operator_#{op}_complex"
|
||||
alias_method original_operator_name, op
|
||||
define_method op do |rhs|
|
||||
if rhs.is_a? Complex
|
||||
|
||||
@@ -174,7 +174,7 @@ div_pair(struct float_pair *q, struct float_pair const *a,
|
||||
static mrb_value
|
||||
complex_div(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value rhs;
|
||||
mrb_value rhs = mrb_get_arg1(mrb);
|
||||
struct mrb_complex *a, *b;
|
||||
struct float_pair ar, ai, br, bi;
|
||||
struct float_pair br2, bi2;
|
||||
@@ -183,7 +183,6 @@ complex_div(mrb_state *mrb, mrb_value self)
|
||||
struct float_pair ai_br, ar_bi;
|
||||
struct float_pair zr, zi;
|
||||
|
||||
mrb_get_args(mrb, "o", &rhs);
|
||||
a = complex_ptr(mrb, self);
|
||||
b = complex_ptr(mrb, rhs);
|
||||
|
||||
|
||||
@@ -9,217 +9,6 @@
|
||||
mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p);
|
||||
mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self);
|
||||
|
||||
static struct mrb_irep *
|
||||
get_closure_irep(mrb_state *mrb, int level)
|
||||
{
|
||||
struct RProc *proc = mrb->c->ci[-1].proc;
|
||||
|
||||
while (level--) {
|
||||
if (!proc) return NULL;
|
||||
proc = proc->upper;
|
||||
}
|
||||
if (!proc) return NULL;
|
||||
if (MRB_PROC_CFUNC_P(proc)) {
|
||||
return NULL;
|
||||
}
|
||||
return proc->body.irep;
|
||||
}
|
||||
|
||||
/* search for irep lev above the bottom */
|
||||
static mrb_irep*
|
||||
search_irep(mrb_irep *top, int bnest, int lev, mrb_irep *bottom)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<top->rlen; i++) {
|
||||
mrb_irep* tmp = top->reps[i];
|
||||
|
||||
if (tmp == bottom) return top;
|
||||
tmp = search_irep(tmp, bnest-1, lev, bottom);
|
||||
if (tmp) {
|
||||
if (bnest == lev) return top;
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
|
||||
{
|
||||
mrb_irep *virep;
|
||||
int level;
|
||||
int pos;
|
||||
|
||||
for (level = 0; (virep = get_closure_irep(mrb, level)); level++) {
|
||||
if (virep->lv == NULL) {
|
||||
continue;
|
||||
}
|
||||
for (pos = 0; pos < virep->nlocals - 1; pos++) {
|
||||
if (vsym == virep->lv[pos].name) {
|
||||
return (pos+1)<<8 | (level+bnest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
irep_argc(mrb_irep *irep)
|
||||
{
|
||||
mrb_code c;
|
||||
|
||||
c = irep->iseq[0];
|
||||
if (c == OP_ENTER) {
|
||||
mrb_aspec ax = PEEK_W(irep->iseq+1);
|
||||
/* extra 1 means a slot for block */
|
||||
return MRB_ASPEC_REQ(ax)+MRB_ASPEC_OPT(ax)+MRB_ASPEC_REST(ax)+MRB_ASPEC_POST(ax)+1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static mrb_bool
|
||||
potential_upvar_p(struct mrb_locals *lv, uint16_t v, int argc, uint16_t nlocals)
|
||||
{
|
||||
if (v >= nlocals) return FALSE;
|
||||
/* skip arguments */
|
||||
if (v < argc+1) return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
extern uint8_t mrb_insn_size[];
|
||||
extern uint8_t mrb_insn_size1[];
|
||||
extern uint8_t mrb_insn_size2[];
|
||||
extern uint8_t mrb_insn_size3[];
|
||||
|
||||
static void
|
||||
patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
|
||||
{
|
||||
int i;
|
||||
uint32_t a;
|
||||
uint16_t b;
|
||||
uint8_t c;
|
||||
mrb_code insn;
|
||||
int argc = irep_argc(irep);
|
||||
mrb_code *iseq = (mrb_code *)irep->iseq;
|
||||
|
||||
mrb_assert((irep->flags & MRB_ISEQ_NO_FREE) == 0);
|
||||
|
||||
for (i = 0; i < irep->ilen; ) {
|
||||
insn = iseq[i];
|
||||
switch(insn){
|
||||
case OP_EPUSH:
|
||||
a = PEEK_B(iseq+i+1);
|
||||
patch_irep(mrb, irep->reps[a], bnest + 1, top);
|
||||
break;
|
||||
|
||||
case OP_LAMBDA:
|
||||
case OP_BLOCK:
|
||||
a = PEEK_B(iseq+i+1);
|
||||
b = PEEK_B(iseq+i+2);
|
||||
patch_irep(mrb, irep->reps[b], bnest + 1, top);
|
||||
break;
|
||||
|
||||
case OP_SEND:
|
||||
b = PEEK_B(iseq+i+2);
|
||||
c = PEEK_B(iseq+i+3);
|
||||
if (c != 0) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
uint16_t arg = search_variable(mrb, irep->syms[b], bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
iseq[i] = OP_GETUPVAR;
|
||||
iseq[i+2] = arg >> 8;
|
||||
iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_MOVE:
|
||||
a = PEEK_B(iseq+i+1);
|
||||
b = PEEK_B(iseq+i+2);
|
||||
/* src part */
|
||||
if (potential_upvar_p(irep->lv, b, argc, irep->nlocals)) {
|
||||
uint16_t arg = search_variable(mrb, irep->lv[b - 1].name, bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
iseq[i] = insn = OP_GETUPVAR;
|
||||
iseq[i+2] = arg >> 8;
|
||||
iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
/* dst part */
|
||||
if (potential_upvar_p(irep->lv, a, argc, irep->nlocals)) {
|
||||
uint16_t arg = search_variable(mrb, irep->lv[a - 1].name, bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
iseq[i] = insn = OP_SETUPVAR;
|
||||
iseq[i+1] = (mrb_code)b;
|
||||
iseq[i+2] = arg >> 8;
|
||||
iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_GETUPVAR:
|
||||
a = PEEK_B(iseq+i+1);
|
||||
b = PEEK_B(iseq+i+2);
|
||||
c = PEEK_B(iseq+i+3);
|
||||
{
|
||||
int lev = c+1;
|
||||
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
|
||||
if (potential_upvar_p(tmp->lv, b, irep_argc(tmp), tmp->nlocals)) {
|
||||
uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
iseq[i] = OP_GETUPVAR;
|
||||
iseq[i+2] = arg >> 8;
|
||||
iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_SETUPVAR:
|
||||
a = PEEK_B(iseq+i+1);
|
||||
b = PEEK_B(iseq+i+2);
|
||||
c = PEEK_B(iseq+i+3);
|
||||
{
|
||||
int lev = c+1;
|
||||
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
|
||||
if (potential_upvar_p(tmp->lv, b, irep_argc(tmp), tmp->nlocals)) {
|
||||
uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
|
||||
if (arg != 0) {
|
||||
/* must replace */
|
||||
iseq[i] = OP_SETUPVAR;
|
||||
iseq[i+1] = a;
|
||||
iseq[i+2] = arg >> 8;
|
||||
iseq[i+3] = arg & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_EXT1:
|
||||
insn = PEEK_B(iseq+i+1);
|
||||
i += mrb_insn_size1[insn]+1;
|
||||
continue;
|
||||
case OP_EXT2:
|
||||
insn = PEEK_B(iseq+i+1);
|
||||
i += mrb_insn_size2[insn]+1;
|
||||
continue;
|
||||
case OP_EXT3:
|
||||
insn = PEEK_B(iseq+i+1);
|
||||
i += mrb_insn_size3[insn]+1;
|
||||
continue;
|
||||
}
|
||||
i+=mrb_insn_size[insn];
|
||||
}
|
||||
}
|
||||
|
||||
void mrb_codedump_all(mrb_state*, struct RProc*);
|
||||
|
||||
static struct RProc*
|
||||
@@ -243,7 +32,8 @@ create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding,
|
||||
mrbc_filename(mrb, cxt, file ? file : "(eval)");
|
||||
cxt->capture_errors = TRUE;
|
||||
cxt->no_optimize = TRUE;
|
||||
cxt->on_eval = TRUE;
|
||||
ci = (mrb->c->ci > mrb->c->cibase) ? mrb->c->ci - 1 : mrb->c->cibase;
|
||||
cxt->upper = ci->proc && MRB_PROC_CFUNC_P(ci->proc) ? NULL : ci->proc;
|
||||
|
||||
p = mrb_parse_nstring(mrb, s, len, cxt);
|
||||
|
||||
@@ -298,7 +88,7 @@ create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding,
|
||||
e->mid = ci->mid;
|
||||
e->stack = ci[1].stackent;
|
||||
e->cxt = mrb->c;
|
||||
MRB_ENV_SET_STACK_LEN(e, ci->proc->body.irep->nlocals);
|
||||
MRB_ENV_SET_LEN(e, ci->proc->body.irep->nlocals);
|
||||
bidx = ci->argc;
|
||||
if (ci->argc < 0) bidx = 2;
|
||||
else bidx += 1;
|
||||
@@ -311,7 +101,6 @@ create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding,
|
||||
}
|
||||
proc->upper = ci->proc;
|
||||
mrb->c->ci->target_class = target_class;
|
||||
patch_irep(mrb, proc->body.irep, 0, proc->body.irep);
|
||||
/* mrb_codedump_all(mrb, proc); */
|
||||
|
||||
mrb_parser_free(p);
|
||||
|
||||
@@ -130,3 +130,24 @@ Proc.new { foo }
|
||||
EOS
|
||||
}
|
||||
end
|
||||
|
||||
assert('Calling the same method as the variable name') do
|
||||
hoge = Object.new
|
||||
def hoge.fuga
|
||||
"Hit!"
|
||||
end
|
||||
assert_equal("Hit!") { fuga = "Miss!"; eval "hoge.fuga" }
|
||||
assert_equal("Hit!") { fuga = "Miss!"; -> { eval "hoge.fuga" }.call }
|
||||
assert_equal("Hit!") { -> { fuga = "Miss!"; eval "hoge.fuga" }.call }
|
||||
assert_equal("Hit!") { fuga = "Miss!"; eval("-> { hoge.fuga }").call }
|
||||
end
|
||||
|
||||
assert('Access numbered parameter from eval') do
|
||||
hoge = Object.new
|
||||
def hoge.fuga(a, &b)
|
||||
b.call(a)
|
||||
end
|
||||
assert_equal(6) {
|
||||
hoge.fuga(3) { _1 + eval("_1") }
|
||||
}
|
||||
end
|
||||
|
||||
@@ -291,8 +291,7 @@ mrb_fiber_alive_p(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
fiber_eq(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
mrb_value other = mrb_get_arg1(mrb);
|
||||
|
||||
if (!mrb_fiber_p(other)) {
|
||||
return mrb_false_value();
|
||||
|
||||
@@ -8,8 +8,7 @@ istruct_test_initialize(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
char *string = (char*)mrb_istruct_ptr(self);
|
||||
mrb_int size = mrb_istruct_size();
|
||||
mrb_value object;
|
||||
mrb_get_args(mrb, "o", &object);
|
||||
mrb_value object = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_fixnum_p(object)) {
|
||||
strncpy(string, "fixnum", size-1);
|
||||
@@ -45,8 +44,8 @@ istruct_test_length(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
istruct_test_test_receive(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value object;
|
||||
mrb_get_args(mrb, "o", &object);
|
||||
mrb_value object = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_obj_class(mrb, object) != mrb_class_get(mrb, "InlineStructTest"))
|
||||
{
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "Expected InlineStructTest");
|
||||
|
||||
@@ -18,7 +18,7 @@ extern "C" {
|
||||
#if defined(MRB_WITHOUT_IO_PREAD_PWRITE)
|
||||
# undef MRB_WITH_IO_PREAD_PWRITE
|
||||
#elif !defined(MRB_WITH_IO_PREAD_PWRITE)
|
||||
# if defined(__unix__)
|
||||
# if defined(__unix__) || defined(__MACH__)
|
||||
# define MRB_WITH_IO_PREAD_PWRITE
|
||||
# endif
|
||||
#endif
|
||||
@@ -50,8 +50,8 @@ struct mrb_io {
|
||||
#define MRB_O_SHARE_DELETE 0x1000
|
||||
#define MRB_O_TMPFILE 0x2000
|
||||
#define MRB_O_NOATIME 0x4000
|
||||
#define MRB_O_DSYNC 0x00008000 /* Ignored with MRB_INT16 and MRB_WITHOUT_FLOAT */
|
||||
#define MRB_O_RSYNC 0x00010000 /* Ignored with MRB_INT16 and MRB_WITHOUT_FLOAT */
|
||||
#define MRB_O_DSYNC 0x00008000
|
||||
#define MRB_O_RSYNC 0x00010000
|
||||
|
||||
#define MRB_O_RDONLY_P(f) ((mrb_bool)(((f) & MRB_O_ACCMODE) == MRB_O_RDONLY))
|
||||
#define MRB_O_WRONLY_P(f) ((mrb_bool)(((f) & MRB_O_ACCMODE) == MRB_O_WRONLY))
|
||||
|
||||
@@ -89,7 +89,7 @@ flock(int fd, int operation) {
|
||||
}
|
||||
#endif
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_file_s_umask(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
@@ -265,7 +265,7 @@ mrb_file_realpath(mrb_state *mrb, mrb_value klass)
|
||||
return result;
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_file__getwd(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
mrb_value path;
|
||||
@@ -401,7 +401,7 @@ mrb_file_mtime(mrb_state *mrb, mrb_value self)
|
||||
return mrb_funcall(mrb, obj, "at", 1, mrb_fixnum_value(st.st_mtime));
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_file_flock(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
#if defined(sun)
|
||||
@@ -458,7 +458,7 @@ mrb_file_size(mrb_state *mrb, mrb_value self)
|
||||
}
|
||||
|
||||
static int
|
||||
mrb_ftruncate(int fd, int64_t length)
|
||||
mrb_ftruncate(int fd, mrb_int length)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
return ftruncate(fd, (off_t)length);
|
||||
@@ -491,32 +491,11 @@ static mrb_value
|
||||
mrb_file_truncate(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
int fd;
|
||||
int64_t length;
|
||||
mrb_value lenv;
|
||||
mrb_int length;
|
||||
mrb_value lenv = mrb_get_arg1(mrb);
|
||||
|
||||
fd = mrb_io_fileno(mrb, self);
|
||||
mrb_get_args(mrb, "o", &lenv);
|
||||
switch (mrb_type(lenv)) {
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
case MRB_TT_FLOAT:
|
||||
{
|
||||
mrb_float lenf = mrb_float(lenv);
|
||||
if (lenf > INT64_MAX) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "length too large");
|
||||
}
|
||||
length = (int64_t)lenf;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case MRB_TT_FIXNUM:
|
||||
default:
|
||||
{
|
||||
mrb_int leni = mrb_int(mrb, lenv);
|
||||
length = (int64_t)leni;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
length = mrb_int(mrb, lenv);
|
||||
if (mrb_ftruncate(fd, length) != 0) {
|
||||
mrb_raise(mrb, E_IO_ERROR, "ftruncate failed");
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ mrb_lstat(mrb_state *mrb, mrb_value obj, struct stat *st)
|
||||
* File.directory?(".")
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#ifndef S_ISDIR
|
||||
@@ -93,9 +93,7 @@ mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass)
|
||||
#endif
|
||||
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_stat(mrb, obj, &st) < 0)
|
||||
return mrb_false_value();
|
||||
@@ -112,7 +110,7 @@ mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass)
|
||||
* Returns <code>true</code> if the named file is a pipe.
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
@@ -124,9 +122,7 @@ mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
|
||||
# endif
|
||||
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_stat(mrb, obj, &st) < 0)
|
||||
return mrb_false_value();
|
||||
@@ -145,7 +141,7 @@ mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
|
||||
* Returns <code>true</code> if the named file is a symbolic link.
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
@@ -167,9 +163,7 @@ mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
|
||||
|
||||
#ifdef S_ISLNK
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_lstat(mrb, obj, &st) == -1)
|
||||
return mrb_false_value();
|
||||
@@ -188,7 +182,7 @@ mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
|
||||
* Returns <code>true</code> if the named file is a socket.
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
@@ -210,9 +204,7 @@ mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
|
||||
|
||||
#ifdef S_ISSOCK
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_stat(mrb, obj, &st) < 0)
|
||||
return mrb_false_value();
|
||||
@@ -232,13 +224,12 @@ mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
|
||||
* Return <code>true</code> if the named file exists.
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_exist_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
if (mrb_stat(mrb, obj, &st) < 0)
|
||||
return mrb_false_value();
|
||||
|
||||
@@ -253,7 +244,7 @@ mrb_filetest_s_exist_p(mrb_state *mrb, mrb_value klass)
|
||||
* regular file.
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_file_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#ifndef S_ISREG
|
||||
@@ -261,9 +252,7 @@ mrb_filetest_s_file_p(mrb_state *mrb, mrb_value klass)
|
||||
#endif
|
||||
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_stat(mrb, obj, &st) < 0)
|
||||
return mrb_false_value();
|
||||
@@ -281,13 +270,11 @@ mrb_filetest_s_file_p(mrb_state *mrb, mrb_value klass)
|
||||
* a zero size.
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_zero_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_stat(mrb, obj, &st) < 0)
|
||||
return mrb_false_value();
|
||||
@@ -306,13 +293,11 @@ mrb_filetest_s_zero_p(mrb_state *mrb, mrb_value klass)
|
||||
* _file_name_ can be an IO object.
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_size(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_stat(mrb, obj, &st) < 0)
|
||||
mrb_sys_fail(mrb, "mrb_stat");
|
||||
@@ -328,13 +313,11 @@ mrb_filetest_s_size(mrb_state *mrb, mrb_value klass)
|
||||
* file otherwise.
|
||||
*/
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_filetest_s_size_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
struct stat st;
|
||||
mrb_value obj;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_stat(mrb, obj, &st) < 0)
|
||||
return mrb_nil_value();
|
||||
|
||||
+67
-41
@@ -341,7 +341,7 @@ option_to_fd(mrb_state *mrb, mrb_value hash, const char *key)
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
mrb_value cmd, io;
|
||||
@@ -439,14 +439,14 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
return io;
|
||||
}
|
||||
#elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
mrb_raise(mrb, E_NOTIMP_ERROR, "IO#popen is not supported on the platform");
|
||||
return mrb_false_value();
|
||||
}
|
||||
#else
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
mrb_value cmd, io, result;
|
||||
@@ -596,16 +596,15 @@ mrb_dup(mrb_state *mrb, int fd, mrb_bool *failed)
|
||||
return new_fd;
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_initialize_copy(mrb_state *mrb, mrb_value copy)
|
||||
{
|
||||
mrb_value orig;
|
||||
mrb_value orig = mrb_get_arg1(mrb);
|
||||
mrb_value buf;
|
||||
struct mrb_io *fptr_copy;
|
||||
struct mrb_io *fptr_orig;
|
||||
mrb_bool failed = TRUE;
|
||||
|
||||
mrb_get_args(mrb, "o", &orig);
|
||||
fptr_orig = io_get_open_fptr(mrb, orig);
|
||||
fptr_copy = (struct mrb_io *)DATA_PTR(copy);
|
||||
if (fptr_orig == fptr_copy) return copy;
|
||||
@@ -645,7 +644,44 @@ mrb_io_initialize_copy(mrb_state *mrb, mrb_value copy)
|
||||
return copy;
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static void
|
||||
check_file_descriptor(mrb_state *mrb, mrb_int fd)
|
||||
{
|
||||
struct stat sb;
|
||||
int fdi = (int)fd;
|
||||
|
||||
#if MRB_INT_MIN < INT_MIN || MRB_INT_MAX > INT_MAX
|
||||
if (fdi != fd) {
|
||||
goto badfd;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
DWORD err;
|
||||
int len = sizeof(err);
|
||||
|
||||
if (getsockopt(fdi, SOL_SOCKET, SO_ERROR, (char*)&err, &len) == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (fdi < 0 || fdi > _getmaxstdio()) {
|
||||
goto badfd;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
if (fstat(fdi, &sb) != 0) {
|
||||
goto badfd;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
badfd:
|
||||
mrb_sys_fail(mrb, "bad file descriptor");
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_io_initialize(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -656,6 +692,7 @@ mrb_io_initialize(mrb_state *mrb, mrb_value io)
|
||||
mode = opt = mrb_nil_value();
|
||||
|
||||
mrb_get_args(mrb, "i|oo", &fd, &mode, &opt);
|
||||
check_file_descriptor(mrb, fd);
|
||||
if (mrb_nil_p(mode)) {
|
||||
mode = mrb_str_new_cstr(mrb, "r");
|
||||
}
|
||||
@@ -747,7 +784,7 @@ fptr_finalize(mrb_state *mrb, struct mrb_io *fptr, int quiet)
|
||||
}
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_check_readable(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_io *fptr = io_get_open_fptr(mrb, self);
|
||||
@@ -757,7 +794,7 @@ mrb_io_check_readable(mrb_state *mrb, mrb_value self)
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_isatty(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -768,7 +805,7 @@ mrb_io_isatty(mrb_state *mrb, mrb_value self)
|
||||
return mrb_true_value();
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_s_for_fd(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
struct RClass *c = mrb_class_ptr(klass);
|
||||
@@ -781,7 +818,7 @@ mrb_io_s_for_fd(mrb_state *mrb, mrb_value klass)
|
||||
return mrb_io_initialize(mrb, obj);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_s_sysclose(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
mrb_int fd;
|
||||
@@ -792,7 +829,7 @@ mrb_io_s_sysclose(mrb_state *mrb, mrb_value klass)
|
||||
return mrb_fixnum_value(0);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
mrb_cloexec_open(mrb_state *mrb, const char *pathname, mrb_int flags, mrb_int mode)
|
||||
{
|
||||
int fd, retry = FALSE;
|
||||
@@ -827,7 +864,7 @@ reopen:
|
||||
return fd;
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_s_sysopen(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
mrb_value path = mrb_nil_value();
|
||||
@@ -857,7 +894,7 @@ mrb_sysread_dummy(int fd, void *buf, fsize_t nbytes, off_t offset)
|
||||
return (mrb_io_read_write_size)read(fd, buf, nbytes);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_sysread(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
mrb_value buf = mrb_nil_value();
|
||||
@@ -911,7 +948,7 @@ mrb_io_sysread_common(mrb_state *mrb,
|
||||
return buf;
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_sysseek(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -971,7 +1008,7 @@ mrb_syswrite_dummy(int fd, const void *buf, fsize_t nbytes, off_t offset)
|
||||
return (mrb_io_read_write_size)write(fd, buf, nbytes);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_syswrite(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
mrb_value buf;
|
||||
@@ -981,7 +1018,7 @@ mrb_io_syswrite(mrb_state *mrb, mrb_value io)
|
||||
return mrb_io_syswrite_common(mrb, mrb_syswrite_dummy, io, buf, 0);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_close(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -990,7 +1027,7 @@ mrb_io_close(mrb_state *mrb, mrb_value self)
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_close_write(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -1001,7 +1038,7 @@ mrb_io_close_write(mrb_state *mrb, mrb_value self)
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_closed(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -1013,7 +1050,7 @@ mrb_io_closed(mrb_state *mrb, mrb_value io)
|
||||
return mrb_true_value();
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_pid(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -1147,6 +1184,7 @@ mrb_io_s_select(mrb_state *mrb, mrb_value klass)
|
||||
for (i = 0; i < RARRAY_LEN(read); i++) {
|
||||
read_io = RARRAY_PTR(read)[i];
|
||||
fptr = io_get_open_fptr(mrb, read_io);
|
||||
if (fptr->fd >= FD_SETSIZE) continue;
|
||||
FD_SET(fptr->fd, rp);
|
||||
if (mrb_io_read_data_pending(mrb, read_io)) {
|
||||
pending++;
|
||||
@@ -1169,6 +1207,7 @@ mrb_io_s_select(mrb_state *mrb, mrb_value klass)
|
||||
FD_ZERO(wp);
|
||||
for (i = 0; i < RARRAY_LEN(write); i++) {
|
||||
fptr = io_get_open_fptr(mrb, RARRAY_PTR(write)[i]);
|
||||
if (fptr->fd >= FD_SETSIZE) continue;
|
||||
FD_SET(fptr->fd, wp);
|
||||
if (max < fptr->fd)
|
||||
max = fptr->fd;
|
||||
@@ -1188,6 +1227,7 @@ mrb_io_s_select(mrb_state *mrb, mrb_value klass)
|
||||
FD_ZERO(ep);
|
||||
for (i = 0; i < RARRAY_LEN(except); i++) {
|
||||
fptr = io_get_open_fptr(mrb, RARRAY_PTR(except)[i]);
|
||||
if (fptr->fd >= FD_SETSIZE) continue;
|
||||
FD_SET(fptr->fd, ep);
|
||||
if (max < fptr->fd)
|
||||
max = fptr->fd;
|
||||
@@ -1276,7 +1316,7 @@ mrb_io_fileno_m(mrb_state *mrb, mrb_value io)
|
||||
return mrb_fixnum_value(fd);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_close_on_exec_p(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
#if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
|
||||
@@ -1300,7 +1340,7 @@ mrb_io_close_on_exec_p(mrb_state *mrb, mrb_value self)
|
||||
#endif
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_set_close_on_exec(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
#if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
|
||||
@@ -1336,7 +1376,7 @@ mrb_io_set_close_on_exec(mrb_state *mrb, mrb_value self)
|
||||
#endif
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_set_sync(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -1348,7 +1388,7 @@ mrb_io_set_sync(mrb_state *mrb, mrb_value self)
|
||||
return mrb_bool_value(b);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_sync(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
@@ -1363,22 +1403,7 @@ mrb_io_sync(mrb_state *mrb, mrb_value self)
|
||||
static off_t
|
||||
value2off(mrb_state *mrb, mrb_value offv)
|
||||
{
|
||||
switch (mrb_type(offv)) {
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
case MRB_TT_FLOAT:
|
||||
{
|
||||
mrb_float tmp = mrb_float(offv);
|
||||
if (tmp < INT64_MIN || tmp > INT64_MAX) {
|
||||
/* fall through to use convert by `mrb_int()` (and raise error if out of range) */
|
||||
} else {
|
||||
return (off_t)tmp;
|
||||
}
|
||||
}
|
||||
/* fall through */
|
||||
#endif /* MRB_WITHOUT_FLOAT */
|
||||
default:
|
||||
return (off_t)mrb_int(mrb, offv);
|
||||
}
|
||||
return (off_t)mrb_int(mrb, offv);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1452,7 +1477,8 @@ mrb_io_readchar(mrb_state *mrb, mrb_value self)
|
||||
#endif
|
||||
|
||||
mrb_get_args(mrb, "S", &buf);
|
||||
mrb_assert(RSTRING_PTR(buf) > 0);
|
||||
mrb_assert(RSTRING_LEN(buf) > 0);
|
||||
mrb_assert(RSTRING_PTR(buf) != NULL);
|
||||
mrb_str_modify(mrb, RSTRING(buf));
|
||||
#ifdef MRB_UTF8_STRING
|
||||
c = RSTRING_PTR(buf)[0];
|
||||
|
||||
@@ -110,18 +110,22 @@ assert('File.join') do
|
||||
end
|
||||
|
||||
assert('File.realpath') do
|
||||
if File::ALT_SEPARATOR
|
||||
readme_path = File._getwd + File::ALT_SEPARATOR + "README.md"
|
||||
assert_equal readme_path, File.realpath("README.md")
|
||||
else
|
||||
dir = MRubyIOTestUtil.mkdtemp("mruby-io-test.XXXXXX")
|
||||
begin
|
||||
dir1 = File.realpath($mrbtest_io_rfname)
|
||||
dir2 = File.realpath("./#{dir}//./../#{$mrbtest_io_symlinkname}")
|
||||
assert_equal dir1, dir2
|
||||
ensure
|
||||
MRubyIOTestUtil.rmdir dir
|
||||
dir = MRubyIOTestUtil.mkdtemp("mruby-io-test.XXXXXX")
|
||||
begin
|
||||
sep = File::ALT_SEPARATOR || File::SEPARATOR
|
||||
relative_path = "#{File.basename(dir)}#{sep}realpath_test"
|
||||
path = "#{File._getwd}#{sep}#{relative_path}"
|
||||
File.open(path, "w"){}
|
||||
assert_equal path, File.realpath(relative_path)
|
||||
|
||||
unless MRubyIOTestUtil.win?
|
||||
path1 = File.realpath($mrbtest_io_rfname)
|
||||
path2 = File.realpath($mrbtest_io_symlinkname)
|
||||
assert_equal path1, path2
|
||||
end
|
||||
ensure
|
||||
File.delete path rescue nil
|
||||
MRubyIOTestUtil.rmdir dir
|
||||
end
|
||||
|
||||
assert_raise(ArgumentError) { File.realpath("TO\0DO") }
|
||||
@@ -129,7 +133,9 @@ end
|
||||
|
||||
assert("File.readlink") do
|
||||
begin
|
||||
assert_equal $mrbtest_io_rfname, File.readlink($mrbtest_io_symlinkname)
|
||||
exp = File.basename($mrbtest_io_rfname)
|
||||
act = File.readlink($mrbtest_io_symlinkname)
|
||||
assert_equal exp, act
|
||||
rescue NotImplementedError => e
|
||||
skip e.message
|
||||
end
|
||||
|
||||
@@ -24,6 +24,10 @@ def assert_io_open(meth)
|
||||
end
|
||||
end
|
||||
io2.close unless meth == :open
|
||||
|
||||
assert_raise(RuntimeError) { IO.__send__(meth, 1023) } # For Windows
|
||||
assert_raise(RuntimeError) { IO.__send__(meth, 1 << 26) }
|
||||
assert_raise(RuntimeError) { IO.__send__(meth, 1 << 32) } if (1 << 32).kind_of?(Integer)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ mkdtemp(char *temp)
|
||||
#include <unistd.h>
|
||||
#include <sys/un.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
@@ -66,88 +67,53 @@ mkdtemp(char *temp)
|
||||
#include "mruby/variable.h"
|
||||
#include <mruby/ext/io.h>
|
||||
|
||||
int wd_save;
|
||||
int socket_available_p;
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
static int mrb_io_socket_available()
|
||||
{
|
||||
int fd, retval = 0;
|
||||
struct sockaddr_un sun0;
|
||||
char socketname[] = "tmp.mruby-io-socket-ok.XXXXXXXX";
|
||||
if (!(fd = mkstemp(socketname))) {
|
||||
goto sock_test_out;
|
||||
}
|
||||
unlink(socketname);
|
||||
close(fd);
|
||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd == -1) {
|
||||
goto sock_test_out;
|
||||
}
|
||||
sun0.sun_family = AF_UNIX;
|
||||
strncpy(sun0.sun_path, socketname, sizeof(sun0.sun_path));
|
||||
if (bind(fd, (struct sockaddr *)&sun0, sizeof(sun0)) == 0) {
|
||||
retval = 1;
|
||||
}
|
||||
sock_test_out:
|
||||
unlink(socketname);
|
||||
close(fd);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
static mrb_value
|
||||
mrb_io_test_io_setup(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
char rfname[] = "tmp.mruby-io-test-r.XXXXXXXX";
|
||||
char wfname[] = "tmp.mruby-io-test-w.XXXXXXXX";
|
||||
char symlinkname[] = "tmp.mruby-io-test-l.XXXXXXXX";
|
||||
char socketname[] = "tmp.mruby-io-test-s.XXXXXXXX";
|
||||
#define GVNAME(n) "$mrbtest_io_" #n "name"
|
||||
enum {IDX_READ, IDX_WRITE, IDX_LINK, IDX_SOCKET, IDX_COUNT};
|
||||
const char *gvnames[] = {GVNAME(rf), GVNAME(wf), GVNAME(symlink), GVNAME(socket)};
|
||||
char *fnames[IDX_COUNT];
|
||||
int fds[IDX_COUNT];
|
||||
char msg[] = "mruby io test\n";
|
||||
mode_t mask;
|
||||
int fd0, fd1;
|
||||
FILE *fp;
|
||||
|
||||
int i;
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
int fd2, fd3;
|
||||
struct sockaddr_un sun0;
|
||||
|
||||
if(!(socket_available_p = mrb_io_socket_available())) {
|
||||
char *tmpdir;
|
||||
wd_save = open(".", O_DIRECTORY);
|
||||
tmpdir = getenv("TMPDIR");
|
||||
if (tmpdir) chdir(tmpdir);
|
||||
else chdir("/tmp");
|
||||
}
|
||||
#endif
|
||||
|
||||
mask = umask(077);
|
||||
fd0 = mkstemp(rfname);
|
||||
fd1 = mkstemp(wfname);
|
||||
if (fd0 == -1 || fd1 == -1) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "can't create temporary file");
|
||||
return mrb_nil_value();
|
||||
}
|
||||
close(fd0);
|
||||
close(fd1);
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
fd2 = mkstemp(symlinkname);
|
||||
fd3 = mkstemp(socketname);
|
||||
if (fd2 == -1 || fd3 == -1) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "can't create temporary file");
|
||||
return mrb_nil_value();
|
||||
}
|
||||
#endif
|
||||
umask(mask);
|
||||
|
||||
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_rfname"), mrb_str_new_cstr(mrb, rfname));
|
||||
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_wfname"), mrb_str_new_cstr(mrb, wfname));
|
||||
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_symlinkname"), mrb_str_new_cstr(mrb, symlinkname));
|
||||
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_socketname"), mrb_str_new_cstr(mrb, socketname));
|
||||
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_msg"), mrb_str_new_cstr(mrb, msg));
|
||||
|
||||
fp = fopen(rfname, "wb");
|
||||
mask = umask(077);
|
||||
for (i = 0; i < IDX_COUNT; i++) {
|
||||
mrb_value fname = mrb_str_new_capa(mrb, 0);
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
/*
|
||||
* Workaround for not being able to bind a socket to some file systems
|
||||
* (e.g. vboxsf, NFS). [#4981]
|
||||
*/
|
||||
char *tmpdir = getenv("TMPDIR");
|
||||
if (tmpdir && strlen(tmpdir) > 0) {
|
||||
mrb_str_cat_cstr(mrb, fname, tmpdir);
|
||||
if (*(RSTRING_END(fname)-1) != '/') mrb_str_cat_lit(mrb, fname, "/");
|
||||
} else {
|
||||
mrb_str_cat_lit(mrb, fname, "/tmp/");
|
||||
}
|
||||
#endif
|
||||
mrb_str_cat_cstr(mrb, fname, gvnames[i]+1);
|
||||
mrb_str_cat_cstr(mrb, fname, ".XXXXXXXX");
|
||||
fnames[i] = RSTRING_PTR(fname);
|
||||
fds[i] = mkstemp(fnames[i]);
|
||||
if (fds[i] == -1) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "can't create temporary file");
|
||||
}
|
||||
close(fds[i]);
|
||||
mrb_gv_set(mrb, mrb_intern_cstr(mrb, gvnames[i]), fname);
|
||||
}
|
||||
umask(mask);
|
||||
|
||||
fp = fopen(fnames[IDX_READ], "wb");
|
||||
if (fp == NULL) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "can't open temporary file");
|
||||
return mrb_nil_value();
|
||||
@@ -155,7 +121,7 @@ mrb_io_test_io_setup(mrb_state *mrb, mrb_value self)
|
||||
fputs(msg, fp);
|
||||
fclose(fp);
|
||||
|
||||
fp = fopen(wfname, "wb");
|
||||
fp = fopen(fnames[IDX_WRITE], "wb");
|
||||
if (fp == NULL) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "can't open temporary file");
|
||||
return mrb_nil_value();
|
||||
@@ -163,29 +129,29 @@ mrb_io_test_io_setup(mrb_state *mrb, mrb_value self)
|
||||
fclose(fp);
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
unlink(symlinkname);
|
||||
close(fd2);
|
||||
if (symlink(rfname, symlinkname) == -1) {
|
||||
unlink(fnames[IDX_LINK]);
|
||||
if (symlink(basename(fnames[IDX_READ]), fnames[IDX_LINK]) == -1) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "can't make a symbolic link");
|
||||
}
|
||||
|
||||
unlink(socketname);
|
||||
close(fd3);
|
||||
fd3 = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd3 == -1) {
|
||||
unlink(fnames[IDX_SOCKET]);
|
||||
fds[IDX_SOCKET] = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fds[IDX_SOCKET] == -1) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "can't make a socket");
|
||||
}
|
||||
sun0.sun_family = AF_UNIX;
|
||||
strncpy(sun0.sun_path, socketname, sizeof(sun0.sun_path));
|
||||
if (bind(fd3, (struct sockaddr *)&sun0, sizeof(sun0)) == -1) {
|
||||
strncpy(sun0.sun_path, fnames[IDX_SOCKET], sizeof(sun0.sun_path)-1);
|
||||
sun0.sun_path[sizeof(sun0.sun_path)-1] = 0;
|
||||
if (bind(fds[IDX_SOCKET], (struct sockaddr *)&sun0, sizeof(sun0)) == -1) {
|
||||
mrb_raisef(mrb, E_RUNTIME_ERROR, "can't bind AF_UNIX socket to %s: %d",
|
||||
sun0.sun_path,
|
||||
errno);
|
||||
}
|
||||
close(fd3);
|
||||
close(fds[IDX_SOCKET]);
|
||||
#endif
|
||||
|
||||
return mrb_true_value();
|
||||
#undef GVNAME
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
@@ -215,13 +181,6 @@ mrb_io_test_io_cleanup(mrb_state *mrb, mrb_value self)
|
||||
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_socketname"), mrb_nil_value());
|
||||
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_msg"), mrb_nil_value());
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
if(!socket_available_p) {
|
||||
fchdir(wd_save);
|
||||
close(wd_save);
|
||||
}
|
||||
#endif
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
@@ -251,7 +210,7 @@ mrb_io_test_rmdir(mrb_state *mrb, mrb_value klass)
|
||||
return mrb_true_value();
|
||||
}
|
||||
|
||||
mrb_value
|
||||
static mrb_value
|
||||
mrb_io_win_p(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
@@ -128,9 +128,8 @@ mrb_f_integer(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_f_float(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value arg;
|
||||
mrb_value arg = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &arg);
|
||||
return mrb_Float(mrb, arg);
|
||||
}
|
||||
#endif
|
||||
@@ -149,9 +148,9 @@ mrb_f_float(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_f_string(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value arg, tmp;
|
||||
mrb_value arg = mrb_get_arg1(mrb);
|
||||
mrb_value tmp;
|
||||
|
||||
mrb_get_args(mrb, "o", &arg);
|
||||
tmp = mrb_convert_type(mrb, arg, MRB_TT_STRING, "String", "to_s");
|
||||
return tmp;
|
||||
}
|
||||
@@ -168,9 +167,9 @@ mrb_f_string(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_f_array(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value arg, tmp;
|
||||
mrb_value arg = mrb_get_arg1(mrb);
|
||||
mrb_value tmp;
|
||||
|
||||
mrb_get_args(mrb, "o", &arg);
|
||||
tmp = mrb_check_convert_type(mrb, arg, MRB_TT_ARRAY, "Array", "to_a");
|
||||
if (mrb_nil_p(tmp)) {
|
||||
return mrb_ary_new_from_values(mrb, 1, &arg);
|
||||
@@ -196,9 +195,8 @@ mrb_f_array(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_f_hash(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value arg;
|
||||
mrb_value arg = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &arg);
|
||||
if (mrb_nil_p(arg) || (mrb_array_p(arg) && RARRAY_LEN(arg) == 0)) {
|
||||
return mrb_hash_new(mrb);
|
||||
}
|
||||
|
||||
@@ -146,24 +146,23 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
|
||||
while (proc) {
|
||||
if (MRB_PROC_CFUNC_P(proc)) break;
|
||||
irep = proc->body.irep;
|
||||
if (!irep->lv) break;
|
||||
for (i = 0; i + 1 < irep->nlocals; ++i) {
|
||||
if (irep->lv[i].name) {
|
||||
mrb_sym sym = irep->lv[i].name;
|
||||
const char *name = mrb_sym_name(mrb, sym);
|
||||
switch (name[0]) {
|
||||
case '*': case '&':
|
||||
break;
|
||||
default:
|
||||
mrb_hash_set(mrb, vars, mrb_symbol_value(sym), mrb_true_value());
|
||||
break;
|
||||
if (irep->lv) {
|
||||
for (i = 0; i + 1 < irep->nlocals; ++i) {
|
||||
if (irep->lv[i].name) {
|
||||
mrb_sym sym = irep->lv[i].name;
|
||||
const char *name = mrb_sym_name(mrb, sym);
|
||||
switch (name[0]) {
|
||||
case '*': case '&':
|
||||
break;
|
||||
default:
|
||||
mrb_hash_set(mrb, vars, mrb_symbol_value(sym), mrb_true_value());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!MRB_PROC_ENV_P(proc)) break;
|
||||
if (MRB_PROC_SCOPE_P(proc)) break;
|
||||
proc = proc->upper;
|
||||
//if (MRB_PROC_SCOPE_P(proc)) break;
|
||||
if (!proc->c) break;
|
||||
}
|
||||
|
||||
return mrb_hash_keys(mrb, vars);
|
||||
@@ -671,8 +670,7 @@ mrb_mod_s_nesting(mrb_state *mrb, mrb_value mod)
|
||||
|
||||
ary = mrb_ary_new(mrb);
|
||||
proc = mrb->c->ci[-1].proc; /* callee proc */
|
||||
mrb_assert(!MRB_PROC_CFUNC_P(proc));
|
||||
while (proc) {
|
||||
while (proc && !MRB_PROC_CFUNC_P(proc)) {
|
||||
if (MRB_PROC_SCOPE_P(proc)) {
|
||||
struct RClass *c2 = MRB_PROC_TARGET_CLASS(proc);
|
||||
|
||||
|
||||
@@ -114,6 +114,15 @@ assert('Kernel.local_variables', '15.3.1.2.7') do
|
||||
# Kernel#local_variables: 15.3.1.3.28
|
||||
local_variables.sort
|
||||
}.call(-1, -2)
|
||||
|
||||
a = Object.new
|
||||
def a.hoge(vars, *, **)
|
||||
Proc.new {
|
||||
x, y = 1, 2
|
||||
local_variables.sort
|
||||
}
|
||||
end
|
||||
assert_equal([:vars, :x, :y]) { a.hoge(0).call }
|
||||
end
|
||||
|
||||
assert('Kernel#define_singleton_method') do
|
||||
|
||||
@@ -33,9 +33,8 @@ unbound_method_bind(mrb_state *mrb, mrb_value self)
|
||||
mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_name"));
|
||||
mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_proc"));
|
||||
mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_klass"));
|
||||
mrb_value recv;
|
||||
mrb_value recv = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &recv);
|
||||
bind_check(mrb, recv, owner);
|
||||
me = method_object_alloc(mrb, mrb_class_get(mrb, "Method"));
|
||||
mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_owner"), owner);
|
||||
@@ -51,11 +50,11 @@ unbound_method_bind(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
method_eql(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other, receiver, orig_proc, other_proc;
|
||||
mrb_value other = mrb_get_arg1(mrb);
|
||||
mrb_value receiver, orig_proc, other_proc;
|
||||
struct RClass *owner, *klass;
|
||||
struct RProc *orig_rproc, *other_rproc;
|
||||
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
if (!mrb_obj_is_instance_of(mrb, other, mrb_class(mrb, self)))
|
||||
return mrb_false_value();
|
||||
|
||||
@@ -110,7 +109,7 @@ method_eql(mrb_state *mrb, mrb_value self)
|
||||
|
||||
static mrb_value
|
||||
mcall(mrb_state *mrb, mrb_value recv, mrb_value proc, mrb_value name, struct RClass *owner,
|
||||
int argc, mrb_value *argv, mrb_value block)
|
||||
mrb_int argc, mrb_value *argv, mrb_value block)
|
||||
{
|
||||
mrb_value ret;
|
||||
mrb_sym orig_mid = mrb->c->ci->mid;
|
||||
|
||||
@@ -101,18 +101,9 @@ mrb_obj_instance_exec(mrb_state *mrb, mrb_value self)
|
||||
struct RClass *c;
|
||||
|
||||
mrb_get_args(mrb, "*&!", &argv, &argc, &blk);
|
||||
|
||||
switch (mrb_type(self)) {
|
||||
case MRB_TT_SYMBOL:
|
||||
case MRB_TT_FIXNUM:
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
case MRB_TT_FLOAT:
|
||||
#endif
|
||||
c = NULL;
|
||||
break;
|
||||
default:
|
||||
c = mrb_class_ptr(mrb_singleton_class(mrb, self));
|
||||
break;
|
||||
c = mrb_singleton_class_ptr(mrb, self);
|
||||
if (mrb->c->ci->acc < 0) {
|
||||
return mrb_yield_with_class(mrb, blk, argc, argv, self, c);
|
||||
}
|
||||
mrb->c->ci->target_class = c;
|
||||
return mrb_yield_cont(mrb, blk, self, argc, argv);
|
||||
|
||||
@@ -89,7 +89,6 @@ os_count_objects(mrb_state *mrb, mrb_value self)
|
||||
COUNT_TYPE(T_STRING);
|
||||
COUNT_TYPE(T_RANGE);
|
||||
COUNT_TYPE(T_EXCEPTION);
|
||||
COUNT_TYPE(T_FILE);
|
||||
COUNT_TYPE(T_ENV);
|
||||
COUNT_TYPE(T_DATA);
|
||||
COUNT_TYPE(T_FIBER);
|
||||
|
||||
+112
-13
@@ -3,11 +3,6 @@
|
||||
*/
|
||||
|
||||
#include <mruby.h>
|
||||
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
# error pack/unpack conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
|
||||
#endif
|
||||
|
||||
#include "mruby/error.h"
|
||||
#include "mruby/array.h"
|
||||
#include "mruby/class.h"
|
||||
@@ -217,6 +212,59 @@ pack_l(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int fl
|
||||
return 4;
|
||||
}
|
||||
|
||||
#ifndef MRB_INT64
|
||||
static void
|
||||
u32tostr(char *buf, size_t len, uint32_t n)
|
||||
{
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
char *bufend = buf + len;
|
||||
char *p = bufend - 1;
|
||||
|
||||
if (len < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
*p -- = '\0';
|
||||
len --;
|
||||
|
||||
if (n > 0) {
|
||||
for (; len > 0 && n > 0; len --, n /= 10) {
|
||||
*p -- = '0' + (n % 10);
|
||||
}
|
||||
p ++;
|
||||
}
|
||||
else if (len > 0) {
|
||||
*p = '0';
|
||||
len --;
|
||||
}
|
||||
|
||||
memmove(buf, p, bufend - p);
|
||||
#else
|
||||
snprintf(buf, len, "%" PRIu32, n);
|
||||
#endif /* MRB_DISABLE_STDIO */
|
||||
}
|
||||
|
||||
static void
|
||||
i32tostr(char *buf, size_t len, int32_t n)
|
||||
{
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
if (len < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
*buf ++ = '-';
|
||||
len --;
|
||||
n = -n;
|
||||
}
|
||||
|
||||
u32tostr(buf, len, (uint32_t)n);
|
||||
#else
|
||||
snprintf(buf, len, "%" PRId32, n);
|
||||
#endif /* MRB_DISABLE_STDIO */
|
||||
}
|
||||
#endif /* MRB_INT64 */
|
||||
|
||||
static int
|
||||
unpack_l(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, unsigned int flags)
|
||||
{
|
||||
@@ -241,16 +289,16 @@ unpack_l(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, un
|
||||
int32_t sl = ul;
|
||||
#ifndef MRB_INT64
|
||||
if (!FIXABLE(sl)) {
|
||||
snprintf(msg, sizeof(msg), "cannot unpack to Fixnum: %" PRId32, sl);
|
||||
mrb_raise(mrb, E_RANGE_ERROR, msg);
|
||||
i32tostr(msg, sizeof(msg), sl);
|
||||
mrb_raisef(mrb, E_RANGE_ERROR, "cannot unpack to Fixnum: %s", msg);
|
||||
}
|
||||
#endif
|
||||
n = sl;
|
||||
} else {
|
||||
#ifndef MRB_INT64
|
||||
if (!POSFIXABLE(ul)) {
|
||||
snprintf(msg, sizeof(msg), "cannot unpack to Fixnum: %" PRIu32, ul);
|
||||
mrb_raise(mrb, E_RANGE_ERROR, msg);
|
||||
u32tostr(msg, sizeof(msg), ul);
|
||||
mrb_raisef(mrb, E_RANGE_ERROR, "cannot unpack to Fixnum: %s", msg);
|
||||
}
|
||||
#endif
|
||||
n = ul;
|
||||
@@ -288,6 +336,57 @@ pack_q(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int fl
|
||||
return 8;
|
||||
}
|
||||
|
||||
static void
|
||||
u64tostr(char *buf, size_t len, uint64_t n)
|
||||
{
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
char *bufend = buf + len;
|
||||
char *p = bufend - 1;
|
||||
|
||||
if (len < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
*p -- = '\0';
|
||||
len --;
|
||||
|
||||
if (n > 0) {
|
||||
for (; len > 0 && n > 0; len --, n /= 10) {
|
||||
*p -- = '0' + (n % 10);
|
||||
}
|
||||
p ++;
|
||||
}
|
||||
else if (len > 0) {
|
||||
*p = '0';
|
||||
len --;
|
||||
}
|
||||
|
||||
memmove(buf, p, bufend - p);
|
||||
#else
|
||||
snprintf(buf, len, "%" PRIu64, n);
|
||||
#endif /* MRB_DISABLE_STDIO */
|
||||
}
|
||||
|
||||
static void
|
||||
i64tostr(char *buf, size_t len, int64_t n)
|
||||
{
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
if (len < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
*buf ++ = '-';
|
||||
len --;
|
||||
n = -n;
|
||||
}
|
||||
|
||||
u64tostr(buf, len, (uint64_t)n);
|
||||
#else
|
||||
snprintf(buf, len, "%" PRId64, n);
|
||||
#endif /* MRB_DISABLE_STDIO */
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_q(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, unsigned int flags)
|
||||
{
|
||||
@@ -311,14 +410,14 @@ unpack_q(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, un
|
||||
if (flags & PACK_FLAG_SIGNED) {
|
||||
int64_t sll = ull;
|
||||
if (!FIXABLE(sll)) {
|
||||
snprintf(msg, sizeof(msg), "cannot unpack to Fixnum: %" PRId64, sll);
|
||||
mrb_raise(mrb, E_RANGE_ERROR, msg);
|
||||
i64tostr(msg, sizeof(msg), sll);
|
||||
mrb_raisef(mrb, E_RANGE_ERROR, "cannot unpack to Fixnum: %s", msg);
|
||||
}
|
||||
n = sll;
|
||||
} else {
|
||||
if (!POSFIXABLE(ull)) {
|
||||
snprintf(msg, sizeof(msg), "cannot unpack to Fixnum: %" PRIu64, ull);
|
||||
mrb_raise(mrb, E_RANGE_ERROR, msg);
|
||||
u64tostr(msg, sizeof(msg), ull);
|
||||
mrb_raisef(mrb, E_RANGE_ERROR, "cannot unpack to Fixnum: %s", msg);
|
||||
}
|
||||
n = ull;
|
||||
}
|
||||
|
||||
@@ -45,9 +45,8 @@ printstr(mrb_state *mrb, mrb_value obj)
|
||||
mrb_value
|
||||
mrb_printstr(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value argv;
|
||||
mrb_value argv = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &argv);
|
||||
printstr(mrb, argv);
|
||||
|
||||
return argv;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <mruby/debug.h>
|
||||
|
||||
static mrb_value
|
||||
mrb_proc_lambda(mrb_state *mrb, mrb_value self)
|
||||
mrb_proc_lambda_p(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct RProc *p = mrb_proc_ptr(self);
|
||||
return mrb_bool_value(MRB_PROC_STRICT_P(p));
|
||||
@@ -169,7 +169,7 @@ void
|
||||
mrb_mruby_proc_ext_gem_init(mrb_state* mrb)
|
||||
{
|
||||
struct RClass *p = mrb->proc_class;
|
||||
mrb_define_method(mrb, p, "lambda?", mrb_proc_lambda, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, p, "lambda?", mrb_proc_lambda_p, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, p, "source_location", mrb_proc_source_location, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, p, "to_s", mrb_proc_inspect, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, p, "inspect", mrb_proc_inspect, MRB_ARGS_NONE());
|
||||
|
||||
@@ -34,12 +34,10 @@ r_lt(mrb_state *mrb, mrb_value a, mrb_value b)
|
||||
static mrb_value
|
||||
range_cover(mrb_state *mrb, mrb_value range)
|
||||
{
|
||||
mrb_value val;
|
||||
struct RRange *r = mrb_range_ptr(mrb, range);
|
||||
mrb_value val = mrb_get_arg1(mrb);
|
||||
mrb_value beg, end;
|
||||
|
||||
mrb_get_args(mrb, "o", &val);
|
||||
|
||||
beg = RANGE_BEG(r);
|
||||
end = RANGE_END(r);
|
||||
|
||||
|
||||
@@ -91,8 +91,8 @@ module Kernel
|
||||
end
|
||||
|
||||
[:+, :-, :*, :/, :<=>, :==, :<, :<=, :>, :>=].each do |op|
|
||||
original_operator_name = :"__original_operator_#{op}_rational"
|
||||
Fixnum.instance_eval do
|
||||
original_operator_name = "__original_operator_#{op}_rational"
|
||||
alias_method original_operator_name, op
|
||||
define_method op do |rhs|
|
||||
if rhs.is_a? Rational
|
||||
@@ -103,7 +103,6 @@ module Kernel
|
||||
end
|
||||
end
|
||||
Float.instance_eval do
|
||||
original_operator_name = "__original_operator_#{op}_rational"
|
||||
alias_method original_operator_name, op
|
||||
define_method op do |rhs|
|
||||
if rhs.is_a? Rational
|
||||
@@ -114,4 +113,3 @@ module Kernel
|
||||
end if Object.const_defined?(:Float)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -91,9 +91,9 @@ rational_s_new(mrb_state *mrb, mrb_value self)
|
||||
mrb_get_args(mrb, "ii", &numerator, &denominator);
|
||||
#else
|
||||
|
||||
#define DROP_PRECISION(cond, num, denom) \
|
||||
#define DROP_PRECISION(f, num, denom) \
|
||||
do { \
|
||||
while (cond) { \
|
||||
while (f < (mrb_float)MRB_INT_MIN || f > (mrb_float)MRB_INT_MAX) { \
|
||||
num /= 2; \
|
||||
denom /= 2; \
|
||||
} \
|
||||
@@ -111,8 +111,8 @@ rational_s_new(mrb_state *mrb, mrb_value self)
|
||||
else {
|
||||
mrb_float denomf = mrb_to_flo(mrb, denomv);
|
||||
|
||||
DROP_PRECISION(denomf < MRB_INT_MIN || denomf > MRB_INT_MAX, numerator, denomf);
|
||||
denominator = denomf;
|
||||
DROP_PRECISION(denomf, numerator, denomf);
|
||||
denominator = (mrb_int)denomf;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -124,12 +124,12 @@ rational_s_new(mrb_state *mrb, mrb_value self)
|
||||
else {
|
||||
mrb_float denomf = mrb_to_flo(mrb, denomv);
|
||||
|
||||
DROP_PRECISION(denomf < MRB_INT_MIN || denomf > MRB_INT_MAX, numf, denomf);
|
||||
denominator = denomf;
|
||||
DROP_PRECISION(denomf, numf, denomf);
|
||||
denominator = (mrb_int)denomf;
|
||||
}
|
||||
|
||||
DROP_PRECISION(numf < MRB_INT_MIN || numf > MRB_INT_MAX, numf, denominator);
|
||||
numerator = numf;
|
||||
DROP_PRECISION(numf, numf, denominator);
|
||||
numerator = (mrb_int)numf;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -152,7 +152,7 @@ rational_to_i(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct mrb_rational *p = rational_ptr(mrb, self);
|
||||
if (p->denominator == 0) {
|
||||
mrb_raise(mrb, mrb_exc_get(mrb, "StandardError"), "divided by 0");
|
||||
mrb_raise(mrb, mrb->eStandardError_class, "divided by 0");
|
||||
}
|
||||
return mrb_fixnum_value(p->numerator / p->denominator);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#define sleep(x) Sleep(x * 1000)
|
||||
#define usleep(x) Sleep((DWORD)((x)<1000) ? 1 : ((x)/1000))
|
||||
#define usleep(x) Sleep((DWORD)(((x)<1000) ? 1 : ((x)/1000)))
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
@@ -5,11 +5,6 @@
|
||||
*/
|
||||
|
||||
#include <mruby.h>
|
||||
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
# error sprintf conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <mruby/string.h>
|
||||
@@ -521,6 +516,50 @@ mrb_f_sprintf(mrb_state *mrb, mrb_value obj)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mrb_int2str(char *buf, size_t len, mrb_int n)
|
||||
{
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
char *bufend = buf + len;
|
||||
char *p = bufend - 1;
|
||||
|
||||
if (len < 1) return -1;
|
||||
|
||||
*p -- = '\0';
|
||||
len --;
|
||||
|
||||
if (n < 0) {
|
||||
if (len < 1) return -1;
|
||||
|
||||
*p -- = '-';
|
||||
len --;
|
||||
n = -n;
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
for (; n > 0; len --, n /= 10) {
|
||||
if (len < 1) return -1;
|
||||
|
||||
*p -- = '0' + (n % 10);
|
||||
}
|
||||
p ++;
|
||||
}
|
||||
else if (len > 0) {
|
||||
*p = '0';
|
||||
len --;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memmove(buf, p, bufend - p);
|
||||
|
||||
return bufend - p - 1;
|
||||
#else
|
||||
return snprintf(buf, len, "%" MRB_PRId, n);
|
||||
#endif /* MRB_DISABLE_STDIO */
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_str_format(mrb_state *mrb, mrb_int argc, const mrb_value *argv, mrb_value fmt)
|
||||
{
|
||||
@@ -711,7 +750,12 @@ retry:
|
||||
}
|
||||
else if (mrb_fixnum_p(val)) {
|
||||
mrb_int n = mrb_fixnum(val);
|
||||
#ifndef MRB_UTF8_STRING
|
||||
char buf[1];
|
||||
|
||||
buf[0] = (char)n&0xff;
|
||||
tmp = mrb_str_new(mrb, buf, 1);
|
||||
#else
|
||||
if (n < 0x80) {
|
||||
char buf[1];
|
||||
|
||||
@@ -722,6 +766,7 @@ retry:
|
||||
tmp = mrb_funcall(mrb, val, "chr", 0);
|
||||
mrb_check_type(mrb, tmp, MRB_TT_STRING);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid character");
|
||||
@@ -797,7 +842,7 @@ retry:
|
||||
case 'B':
|
||||
case 'u': {
|
||||
mrb_value val = GETARG();
|
||||
char nbuf[68], *s;
|
||||
char nbuf[69], *s;
|
||||
const char *prefix = NULL;
|
||||
int sign = 0, dots = 0;
|
||||
char sc = 0;
|
||||
@@ -869,7 +914,7 @@ retry:
|
||||
width--;
|
||||
}
|
||||
mrb_assert(base == 10);
|
||||
snprintf(nbuf, sizeof(nbuf), "%" MRB_PRId, v);
|
||||
mrb_int2str(nbuf, sizeof(nbuf)-1, v);
|
||||
s = nbuf;
|
||||
if (v < 0) s++; /* skip minus sign */
|
||||
}
|
||||
@@ -877,24 +922,12 @@ retry:
|
||||
s = nbuf;
|
||||
if (v < 0) {
|
||||
dots = 1;
|
||||
val = mrb_fix2binstr(mrb, mrb_fixnum_value(v), base);
|
||||
}
|
||||
switch (base) {
|
||||
case 2:
|
||||
if (v < 0) {
|
||||
val = mrb_fix2binstr(mrb, mrb_fixnum_value(v), base);
|
||||
}
|
||||
else {
|
||||
val = mrb_fixnum_to_str(mrb, mrb_fixnum_value(v), base);
|
||||
}
|
||||
strncpy(++s, RSTRING_PTR(val), sizeof(nbuf)-1);
|
||||
break;
|
||||
case 8:
|
||||
snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRIo, v);
|
||||
break;
|
||||
case 16:
|
||||
snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRIx, v);
|
||||
break;
|
||||
else {
|
||||
val = mrb_fixnum_to_str(mrb, mrb_fixnum_value(v), base);
|
||||
}
|
||||
strncpy(++s, RSTRING_PTR(val), sizeof(nbuf)-2);
|
||||
if (v < 0) {
|
||||
char d;
|
||||
|
||||
@@ -1008,7 +1041,7 @@ retry:
|
||||
mrb_value val = GETARG();
|
||||
double fval;
|
||||
mrb_int need = 6;
|
||||
char fbuf[32];
|
||||
char fbuf[64];
|
||||
|
||||
fval = mrb_float(mrb_Float(mrb, val));
|
||||
if (!isfinite(fval)) {
|
||||
@@ -1049,7 +1082,6 @@ retry:
|
||||
break;
|
||||
}
|
||||
|
||||
fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec);
|
||||
need = 0;
|
||||
if (*p != 'e' && *p != 'E') {
|
||||
int i;
|
||||
@@ -1071,7 +1103,8 @@ retry:
|
||||
need += 20;
|
||||
|
||||
CHECK(need);
|
||||
n = snprintf(&buf[blen], need, fbuf, fval);
|
||||
fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec);
|
||||
n = mrb_float_to_cstr(mrb, &buf[blen], need, fbuf, fval);
|
||||
if (n < 0 || n >= need) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "formatting error");
|
||||
}
|
||||
@@ -1113,12 +1146,13 @@ fmt_setup(char *buf, size_t size, int c, int flags, mrb_int width, mrb_int prec)
|
||||
if (flags & FSPACE) *buf++ = ' ';
|
||||
|
||||
if (flags & FWIDTH) {
|
||||
n = snprintf(buf, end - buf, "%d", (int)width);
|
||||
n = mrb_int2str(buf, end - buf, width);
|
||||
buf += n;
|
||||
}
|
||||
|
||||
if (flags & FPREC) {
|
||||
n = snprintf(buf, end - buf, ".%d", (int)prec);
|
||||
*buf ++ = '.';
|
||||
n = mrb_int2str(buf, end - buf, prec);
|
||||
buf += n;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,11 @@ assert('String#%') do
|
||||
assert_equal 15, ("%b" % (1<<14)).size
|
||||
skip unless Object.const_defined?(:Float)
|
||||
assert_equal "1.0", "%3.1f" % 1.01
|
||||
assert_equal " 123456789.12", "% 4.2f" % 123456789.123456789
|
||||
assert_equal "123456789.12", "%-4.2f" % 123456789.123456789
|
||||
assert_equal "+123456789.12", "%+4.2f" % 123456789.123456789
|
||||
assert_equal "123456789.12", "%04.2f" % 123456789.123456789
|
||||
assert_equal "00000000123456789.12", "%020.2f" % 123456789.123456789
|
||||
end
|
||||
|
||||
assert('String#% with inf') do
|
||||
@@ -68,29 +73,6 @@ assert('String#% with nan') do
|
||||
assert_equal " NaN", "% 5f" % nan
|
||||
end
|
||||
|
||||
assert("String#% with invalid chr") do
|
||||
begin
|
||||
class Fixnum
|
||||
alias_method :chr_, :chr if method_defined?(:chr)
|
||||
|
||||
def chr
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
assert_raise TypeError do
|
||||
"%c" % 0x80
|
||||
end
|
||||
ensure
|
||||
class Fixnum
|
||||
if method_defined?(:chr_)
|
||||
alias_method :chr, :chr_
|
||||
remove_method :chr_
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assert("String#% %b") do
|
||||
assert_equal("..10115", "%0b5" % -5)
|
||||
end
|
||||
|
||||
@@ -164,9 +164,8 @@ mrb_str_swapcase(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_str_concat_m(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value str;
|
||||
mrb_value str = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &str);
|
||||
if (mrb_fixnum_p(str) || mrb_float_p(str))
|
||||
#ifdef MRB_UTF8_STRING
|
||||
str = int_chr_utf8(mrb, str);
|
||||
@@ -335,7 +334,7 @@ tr_parse_pattern(mrb_state *mrb, struct tr_pattern *ret, const mrb_value v_patte
|
||||
|
||||
len = i - start_pos;
|
||||
if (len > UINT16_MAX) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "tr pattern too long (max 65536)");
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "tr pattern too long (max 65535)");
|
||||
}
|
||||
if (pat1 == NULL && ret) {
|
||||
goto nomem;
|
||||
@@ -343,9 +342,9 @@ tr_parse_pattern(mrb_state *mrb, struct tr_pattern *ret, const mrb_value v_patte
|
||||
pat1->type = TR_IN_ORDER;
|
||||
pat1->flag_reverse = flag_reverse;
|
||||
pat1->flag_on_heap = !ret_uninit;
|
||||
pat1->n = len;
|
||||
pat1->n = (uint16_t)len;
|
||||
pat1->next = NULL;
|
||||
pat1->val.start_pos = start_pos;
|
||||
pat1->val.start_pos = (uint16_t)start_pos;
|
||||
}
|
||||
|
||||
if (ret == NULL || ret_uninit) {
|
||||
|
||||
@@ -154,9 +154,8 @@ mrb_struct_set_m(mrb_state *mrb, mrb_value obj)
|
||||
{
|
||||
mrb_int i = mrb_fixnum(mrb_proc_cfunc_env_get(mrb, 0));
|
||||
mrb_value *ptr;
|
||||
mrb_value val;
|
||||
mrb_value val = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &val);
|
||||
mrb_struct_modify(mrb, obj);
|
||||
ptr = RSTRUCT_PTR(obj);
|
||||
if (ptr == NULL || i >= RSTRUCT_LEN(obj)) {
|
||||
@@ -356,9 +355,7 @@ mrb_struct_initialize(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_struct_init_copy(mrb_state *mrb, mrb_value copy)
|
||||
{
|
||||
mrb_value s;
|
||||
|
||||
mrb_get_args(mrb, "o", &s);
|
||||
mrb_value s = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_obj_equal(mrb, copy, s)) return copy;
|
||||
if (!mrb_obj_is_instance_of(mrb, s, mrb_obj_class(mrb, copy))) {
|
||||
@@ -428,9 +425,8 @@ struct_aref_int(mrb_state *mrb, mrb_value s, mrb_int i)
|
||||
static mrb_value
|
||||
mrb_struct_aref(mrb_state *mrb, mrb_value s)
|
||||
{
|
||||
mrb_value idx;
|
||||
mrb_value idx = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &idx);
|
||||
if (mrb_string_p(idx)) {
|
||||
mrb_value sym = mrb_check_intern_str(mrb, idx);
|
||||
|
||||
@@ -545,11 +541,10 @@ mrb_struct_aset(mrb_state *mrb, mrb_value s)
|
||||
static mrb_value
|
||||
mrb_struct_equal(mrb_state *mrb, mrb_value s)
|
||||
{
|
||||
mrb_value s2;
|
||||
mrb_value s2 = mrb_get_arg1(mrb);
|
||||
mrb_value *ptr, *ptr2;
|
||||
mrb_int i, len;
|
||||
|
||||
mrb_get_args(mrb, "o", &s2);
|
||||
if (mrb_obj_equal(mrb, s, s2)) {
|
||||
return mrb_true_value();
|
||||
}
|
||||
@@ -582,11 +577,10 @@ mrb_struct_equal(mrb_state *mrb, mrb_value s)
|
||||
static mrb_value
|
||||
mrb_struct_eql(mrb_state *mrb, mrb_value s)
|
||||
{
|
||||
mrb_value s2;
|
||||
mrb_value s2 = mrb_get_arg1(mrb);
|
||||
mrb_value *ptr, *ptr2;
|
||||
mrb_int i, len;
|
||||
|
||||
mrb_get_args(mrb, "o", &s2);
|
||||
if (mrb_obj_equal(mrb, s, s2)) {
|
||||
return mrb_true_value();
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
|
||||
|
||||
file assert_lib => assert_c
|
||||
file assert_c => [assert_rb, build.mrbcfile] do |t|
|
||||
mkdir_p File.dirname(t.name)
|
||||
open(t.name, 'w') do |f|
|
||||
mrbc.run f, assert_rb, 'mrbtest_assert_irep'
|
||||
end
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <mruby/data.h>
|
||||
#include <mruby/numeric.h>
|
||||
#include <mruby/time.h>
|
||||
#include <mruby/string.h>
|
||||
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
#include <string.h>
|
||||
@@ -514,11 +515,10 @@ time_get_ptr(mrb_state *mrb, mrb_value time)
|
||||
static mrb_value
|
||||
mrb_time_eq(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_value other = mrb_get_arg1(mrb);
|
||||
struct mrb_time *tm1, *tm2;
|
||||
mrb_bool eq_p;
|
||||
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
tm1 = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
|
||||
tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time);
|
||||
eq_p = tm1 && tm2 && tm1->sec == tm2->sec && tm1->usec == tm2->usec;
|
||||
@@ -529,10 +529,9 @@ mrb_time_eq(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_time_cmp(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_value other = mrb_get_arg1(mrb);
|
||||
struct mrb_time *tm1, *tm2;
|
||||
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
tm1 = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
|
||||
tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time);
|
||||
if (!tm1 || !tm2) return mrb_nil_value();
|
||||
@@ -555,11 +554,10 @@ mrb_time_cmp(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_time_plus(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value o;
|
||||
mrb_value o = mrb_get_arg1(mrb);
|
||||
struct mrb_time *tm;
|
||||
time_t sec, usec;
|
||||
|
||||
mrb_get_args(mrb, "o", &o);
|
||||
tm = time_get_ptr(mrb, self);
|
||||
sec = mrb_to_time_t(mrb, o, &usec);
|
||||
return mrb_time_make_time(mrb, mrb_obj_class(mrb, self), tm->sec+sec, tm->usec+usec, tm->timezone);
|
||||
@@ -568,10 +566,9 @@ mrb_time_plus(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_time_minus(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_value other = mrb_get_arg1(mrb);
|
||||
struct mrb_time *tm, *tm2;
|
||||
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
tm = time_get_ptr(mrb, self);
|
||||
tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time);
|
||||
if (tm2) {
|
||||
@@ -769,10 +766,9 @@ mrb_time_initialize(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_time_initialize_copy(mrb_state *mrb, mrb_value copy)
|
||||
{
|
||||
mrb_value src;
|
||||
mrb_value src = mrb_get_arg1(mrb);
|
||||
struct mrb_time *t1, *t2;
|
||||
|
||||
mrb_get_args(mrb, "o", &src);
|
||||
if (mrb_obj_equal(mrb, copy, src)) return copy;
|
||||
if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) {
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
|
||||
@@ -954,7 +950,9 @@ mrb_time_to_s(mrb_state *mrb, mrb_value self)
|
||||
struct mrb_time *tm = time_get_ptr(mrb, self);
|
||||
mrb_bool utc = tm->timezone == MRB_TIMEZONE_UTC;
|
||||
size_t len = (utc ? time_to_s_utc : time_to_s_local)(mrb, tm, buf, sizeof(buf));
|
||||
return mrb_str_new(mrb, buf, len);
|
||||
mrb_value str = mrb_str_new(mrb, buf, len);
|
||||
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
|
||||
return str;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
class BasicObject
|
||||
def !=(other)
|
||||
if self == other
|
||||
false
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Module
|
||||
# 15.2.2.4.12
|
||||
def attr_accessor(*names)
|
||||
|
||||
+3
-3
@@ -140,7 +140,7 @@ class Hash
|
||||
def each_value(&block)
|
||||
return to_enum :each_value unless block
|
||||
|
||||
self.keys.each{|k| block.call(self[k])}
|
||||
self.values.each{|v| block.call(v)}
|
||||
self
|
||||
end
|
||||
|
||||
@@ -192,11 +192,11 @@ class Hash
|
||||
recur_list[self.object_id] = true
|
||||
ary=[]
|
||||
keys=self.keys
|
||||
vals=self.values
|
||||
size=keys.size
|
||||
i=0
|
||||
while i<size
|
||||
k=keys[i]
|
||||
ary<<(k._inspect(recur_list) + "=>" + self[k]._inspect(recur_list))
|
||||
ary<<(keys[i]._inspect(recur_list) + "=>" + vals[i]._inspect(recur_list))
|
||||
i+=1
|
||||
end
|
||||
"{"+ary.join(", ")+"}"
|
||||
|
||||
+25
-11
@@ -732,6 +732,10 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val
|
||||
argv = ARY_PTR(r);
|
||||
}
|
||||
}
|
||||
else if (mrb_undef_p(rpl)) {
|
||||
argc = 0;
|
||||
argv = NULL;
|
||||
}
|
||||
else {
|
||||
argc = 1;
|
||||
argv = &rpl;
|
||||
@@ -804,6 +808,13 @@ ary_subseq(mrb_state *mrb, struct RArray *a, mrb_int beg, mrb_int len)
|
||||
return mrb_obj_value(b);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len)
|
||||
{
|
||||
struct RArray *a = mrb_ary_ptr(ary);
|
||||
return ary_subseq(mrb, a, beg, len);
|
||||
}
|
||||
|
||||
static mrb_int
|
||||
aget_index(mrb_state *mrb, mrb_value index)
|
||||
{
|
||||
@@ -855,10 +866,12 @@ static mrb_value
|
||||
mrb_ary_aget(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
struct RArray *a = mrb_ary_ptr(self);
|
||||
mrb_int i, len, alen;
|
||||
mrb_int i;
|
||||
mrb_int len, alen;
|
||||
mrb_value index;
|
||||
|
||||
if (mrb_get_args(mrb, "o|i", &index, &len) == 1) {
|
||||
if (mrb_get_argc(mrb) == 1) {
|
||||
index = mrb_get_arg1(mrb);
|
||||
switch (mrb_type(index)) {
|
||||
/* a[n..m] */
|
||||
case MRB_TT_RANGE:
|
||||
@@ -875,6 +888,7 @@ mrb_ary_aget(mrb_state *mrb, mrb_value self)
|
||||
}
|
||||
}
|
||||
|
||||
mrb_get_args(mrb, "oi", &index, &len);
|
||||
i = aget_index(mrb, index);
|
||||
alen = ARY_LEN(a);
|
||||
if (i < 0) i += alen;
|
||||
@@ -928,7 +942,10 @@ mrb_ary_aset(mrb_state *mrb, mrb_value self)
|
||||
mrb_int i, len;
|
||||
|
||||
mrb_ary_modify(mrb, mrb_ary_ptr(self));
|
||||
if (mrb_get_args(mrb, "oo|o", &v1, &v2, &v3) == 2) {
|
||||
if (mrb_get_argc(mrb) == 2) {
|
||||
mrb_value *vs = mrb_get_argv(mrb);
|
||||
v1 = vs[0]; v2 = vs[1];
|
||||
|
||||
/* a[n..m] = v */
|
||||
switch (mrb_range_beg_len(mrb, v1, &i, &len, RARRAY_LEN(self), FALSE)) {
|
||||
case MRB_RANGE_TYPE_MISMATCH:
|
||||
@@ -944,6 +961,7 @@ mrb_ary_aset(mrb_state *mrb, mrb_value self)
|
||||
return v2;
|
||||
}
|
||||
|
||||
mrb_get_args(mrb, "ooo", &v1, &v2, &v3);
|
||||
/* a[n,m] = v */
|
||||
mrb_ary_splice(mrb, self, aget_index(mrb, v1), aget_index(mrb, v2), v3);
|
||||
return v3;
|
||||
@@ -1027,10 +1045,9 @@ mrb_ary_last(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_ary_index_m(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value obj;
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
mrb_int i;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
for (i = 0; i < RARRAY_LEN(self); i++) {
|
||||
if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
|
||||
return mrb_fixnum_value(i);
|
||||
@@ -1042,10 +1059,9 @@ mrb_ary_index_m(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_ary_rindex_m(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value obj;
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
mrb_int i, len;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
for (i = RARRAY_LEN(self) - 1; i >= 0; i--) {
|
||||
if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
|
||||
return mrb_fixnum_value(i);
|
||||
@@ -1219,9 +1235,8 @@ mrb_ary_join_m(mrb_state *mrb, mrb_value ary)
|
||||
static mrb_value
|
||||
mrb_ary_eq(mrb_state *mrb, mrb_value ary1)
|
||||
{
|
||||
mrb_value ary2;
|
||||
mrb_value ary2 = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &ary2);
|
||||
if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value();
|
||||
if (!mrb_array_p(ary2)) {
|
||||
return mrb_false_value();
|
||||
@@ -1234,9 +1249,8 @@ mrb_ary_eq(mrb_state *mrb, mrb_value ary1)
|
||||
static mrb_value
|
||||
mrb_ary_cmp(mrb_state *mrb, mrb_value ary1)
|
||||
{
|
||||
mrb_value ary2;
|
||||
mrb_value ary2 = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &ary2);
|
||||
if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_fixnum_value(0);
|
||||
if (!mrb_array_p(ary2)) {
|
||||
return mrb_nil_value();
|
||||
|
||||
+47
-31
@@ -549,6 +549,23 @@ mrb_get_argv(mrb_state *mrb)
|
||||
return array_argv;
|
||||
}
|
||||
|
||||
MRB_API mrb_value
|
||||
mrb_get_arg1(mrb_state *mrb)
|
||||
{
|
||||
mrb_int argc = mrb->c->ci->argc;
|
||||
mrb_value *array_argv = mrb->c->stack + 1;
|
||||
if (argc < 0) {
|
||||
struct RArray *a = mrb_ary_ptr(*array_argv);
|
||||
|
||||
argc = ARY_LEN(a);
|
||||
array_argv = ARY_PTR(a);
|
||||
}
|
||||
if (argc != 1) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
|
||||
}
|
||||
return array_argv[0];
|
||||
}
|
||||
|
||||
void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self);
|
||||
|
||||
/*
|
||||
@@ -1212,10 +1229,9 @@ mrb_mod_ancestors(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_mod_extend_object(mrb_state *mrb, mrb_value mod)
|
||||
{
|
||||
mrb_value obj;
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_check_type(mrb, mod, MRB_TT_MODULE);
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
mrb_include_module(mrb, mrb_class_ptr(mrb_singleton_class(mrb, obj)), mrb_class_ptr(mod));
|
||||
return mod;
|
||||
}
|
||||
@@ -1242,33 +1258,45 @@ mrb_mod_dummy_visibility(mrb_state *mrb, mrb_value mod)
|
||||
return mod;
|
||||
}
|
||||
|
||||
MRB_API mrb_value
|
||||
mrb_singleton_class(mrb_state *mrb, mrb_value v)
|
||||
/* returns mrb_class_ptr(mrb_singleton_class()) */
|
||||
/* except that it return NULL for immediate values */
|
||||
MRB_API struct RClass*
|
||||
mrb_singleton_class_ptr(mrb_state *mrb, mrb_value v)
|
||||
{
|
||||
struct RBasic *obj;
|
||||
|
||||
switch (mrb_type(v)) {
|
||||
case MRB_TT_FALSE:
|
||||
if (mrb_nil_p(v))
|
||||
return mrb_obj_value(mrb->nil_class);
|
||||
return mrb_obj_value(mrb->false_class);
|
||||
return mrb->nil_class;
|
||||
return mrb->false_class;
|
||||
case MRB_TT_TRUE:
|
||||
return mrb_obj_value(mrb->true_class);
|
||||
return mrb->true_class;
|
||||
case MRB_TT_CPTR:
|
||||
return mrb_obj_value(mrb->object_class);
|
||||
return mrb->object_class;
|
||||
case MRB_TT_SYMBOL:
|
||||
case MRB_TT_FIXNUM:
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
case MRB_TT_FLOAT:
|
||||
#endif
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton");
|
||||
return mrb_nil_value(); /* not reached */
|
||||
return NULL;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
obj = mrb_basic_ptr(v);
|
||||
prepare_singleton_class(mrb, obj);
|
||||
return mrb_obj_value(obj->c);
|
||||
return obj->c;
|
||||
}
|
||||
|
||||
MRB_API mrb_value
|
||||
mrb_singleton_class(mrb_state *mrb, mrb_value v)
|
||||
{
|
||||
struct RClass *c = mrb_singleton_class_ptr(mrb, v);
|
||||
|
||||
if (c == NULL) {
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton");
|
||||
}
|
||||
return mrb_obj_value(c);
|
||||
}
|
||||
|
||||
MRB_API void
|
||||
@@ -1481,9 +1509,8 @@ static mrb_value
|
||||
attr_writer(mrb_state *mrb, mrb_value obj)
|
||||
{
|
||||
mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
|
||||
mrb_value val;
|
||||
mrb_value val = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &val);
|
||||
mrb_iv_set(mrb, obj, to_sym(mrb, name), val);
|
||||
return val;
|
||||
}
|
||||
@@ -1651,21 +1678,11 @@ mrb_bob_not(mrb_state *mrb, mrb_value cv)
|
||||
mrb_value
|
||||
mrb_obj_equal_m(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value arg;
|
||||
mrb_value arg = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &arg);
|
||||
return mrb_bool_value(mrb_obj_equal(mrb, self, arg));
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value arg;
|
||||
|
||||
mrb_get_args(mrb, "o", &arg);
|
||||
return mrb_bool_value(!mrb_equal(mrb, self, arg));
|
||||
}
|
||||
|
||||
MRB_API mrb_bool
|
||||
mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid)
|
||||
{
|
||||
@@ -1716,7 +1733,10 @@ mrb_class_real(struct RClass* cl)
|
||||
MRB_API const char*
|
||||
mrb_class_name(mrb_state *mrb, struct RClass* c)
|
||||
{
|
||||
mrb_value name = class_name_str(mrb, c);
|
||||
mrb_value name;
|
||||
|
||||
if (c == NULL) return NULL;
|
||||
name = class_name_str(mrb, c);
|
||||
return RSTRING_PTR(name);
|
||||
}
|
||||
|
||||
@@ -1960,13 +1980,11 @@ mrb_const_get_sym(mrb_state *mrb, mrb_value mod, mrb_sym id)
|
||||
static mrb_value
|
||||
mrb_mod_const_get(mrb_state *mrb, mrb_value mod)
|
||||
{
|
||||
mrb_value path;
|
||||
mrb_value path = mrb_get_arg1(mrb);
|
||||
mrb_sym id;
|
||||
char *ptr;
|
||||
mrb_int off, end, len;
|
||||
|
||||
mrb_get_args(mrb, "o", &path);
|
||||
|
||||
if (mrb_symbol_p(path)) {
|
||||
/* const get with symbol */
|
||||
id = mrb_symbol(path);
|
||||
@@ -2119,10 +2137,9 @@ top_define_method(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_mod_eqq(mrb_state *mrb, mrb_value mod)
|
||||
{
|
||||
mrb_value obj;
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
mrb_bool eqq;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
eqq = mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod));
|
||||
|
||||
return mrb_bool_value(eqq);
|
||||
@@ -2257,7 +2274,6 @@ mrb_init_class(mrb_state *mrb)
|
||||
mrb_define_method(mrb, bob, "initialize", mrb_bob_init, 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, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(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 */
|
||||
|
||||
@@ -130,6 +130,10 @@ codedump(mrb_state *mrb, mrb_irep *irep)
|
||||
printf("OP_LOADI\tR%d\t-%d\t", a, b);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
CASE(OP_LOADI16, BS):
|
||||
printf("OP_LOADI16\tR%d\t%d\t", a, (int)(int16_t)b);
|
||||
print_lv_a(mrb, irep, a);
|
||||
break;
|
||||
CASE(OP_LOADI__1, B):
|
||||
printf("OP_LOADI__1\tR%d\t\t", a);
|
||||
print_lv_a(mrb, irep, a);
|
||||
|
||||
+8
-5
@@ -204,11 +204,14 @@ mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d)
|
||||
|
||||
if (!d) { return; }
|
||||
|
||||
for (i = 0; i < d->flen; ++i) {
|
||||
mrb_assert(d->files[i]);
|
||||
mrb_free(mrb, d->files[i]->lines.ptr);
|
||||
mrb_free(mrb, d->files[i]);
|
||||
if (d->files) {
|
||||
for (i = 0; i < d->flen; ++i) {
|
||||
if (d->files[i]) {
|
||||
mrb_free(mrb, d->files[i]->lines.ptr);
|
||||
mrb_free(mrb, d->files[i]);
|
||||
}
|
||||
}
|
||||
mrb_free(mrb, d->files);
|
||||
}
|
||||
mrb_free(mrb, d->files);
|
||||
mrb_free(mrb, d);
|
||||
}
|
||||
|
||||
+3
-65
@@ -13,9 +13,6 @@
|
||||
#include <mruby/numeric.h>
|
||||
#include <mruby/debug.h>
|
||||
|
||||
#define FLAG_BYTEORDER_NATIVE 2
|
||||
#define FLAG_BYTEORDER_NONATIVE 0
|
||||
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
#ifdef MRB_USE_FLOAT
|
||||
#define MRB_FLOAT_FMT "%.9g"
|
||||
@@ -709,22 +706,7 @@ write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t *bin, uint8
|
||||
uint16_t crc;
|
||||
uint32_t offset;
|
||||
|
||||
switch (flags & DUMP_ENDIAN_NAT) {
|
||||
endian_big:
|
||||
case DUMP_ENDIAN_BIG:
|
||||
memcpy(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident));
|
||||
break;
|
||||
endian_little:
|
||||
case DUMP_ENDIAN_LIL:
|
||||
memcpy(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident));
|
||||
break;
|
||||
|
||||
case DUMP_ENDIAN_NAT:
|
||||
if (bigendian_p()) goto endian_big;
|
||||
goto endian_little;
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident));
|
||||
memcpy(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version));
|
||||
memcpy(header->compiler_name, RITE_COMPILER_NAME, sizeof(header->compiler_name));
|
||||
memcpy(header->compiler_version, RITE_COMPILER_VERSION, sizeof(header->compiler_version));
|
||||
@@ -764,21 +746,6 @@ lv_defined_p(mrb_irep *irep)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
dump_flags(uint8_t flags, uint8_t native)
|
||||
{
|
||||
if (native == FLAG_BYTEORDER_NATIVE) {
|
||||
if ((flags & DUMP_ENDIAN_NAT) == 0) {
|
||||
return (flags & DUMP_DEBUG_INFO) | DUMP_ENDIAN_NAT;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
if ((flags & DUMP_ENDIAN_NAT) == 0) {
|
||||
return (flags & DUMP_DEBUG_INFO) | DUMP_ENDIAN_BIG;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
static int
|
||||
dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size)
|
||||
{
|
||||
@@ -870,7 +837,7 @@ error_exit:
|
||||
int
|
||||
mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size)
|
||||
{
|
||||
return dump_irep(mrb, irep, dump_flags(flags, FLAG_BYTEORDER_NONATIVE), bin, bin_size);
|
||||
return dump_irep(mrb, irep, flags, bin, bin_size);
|
||||
}
|
||||
|
||||
#ifndef MRB_DISABLE_STDIO
|
||||
@@ -886,7 +853,7 @@ mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE* fp)
|
||||
return MRB_DUMP_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
result = dump_irep(mrb, irep, dump_flags(flags, FLAG_BYTEORDER_NONATIVE), &bin, &bin_size);
|
||||
result = dump_irep(mrb, irep, flags, &bin, &bin_size);
|
||||
if (result == MRB_DUMP_OK) {
|
||||
if (fwrite(bin, sizeof(bin[0]), bin_size, fp) != bin_size) {
|
||||
result = MRB_DUMP_WRITE_FAULT;
|
||||
@@ -897,20 +864,6 @@ mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE* fp)
|
||||
return result;
|
||||
}
|
||||
|
||||
static mrb_bool
|
||||
dump_bigendian_p(uint8_t flags)
|
||||
{
|
||||
switch (flags & DUMP_ENDIAN_NAT) {
|
||||
case DUMP_ENDIAN_BIG:
|
||||
return TRUE;
|
||||
case DUMP_ENDIAN_LIL:
|
||||
return FALSE;
|
||||
default:
|
||||
case DUMP_ENDIAN_NAT:
|
||||
return bigendian_p();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, const char *initname)
|
||||
{
|
||||
@@ -921,23 +874,8 @@ mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, con
|
||||
if (fp == NULL || initname == NULL || initname[0] == '\0') {
|
||||
return MRB_DUMP_INVALID_ARGUMENT;
|
||||
}
|
||||
flags = dump_flags(flags, FLAG_BYTEORDER_NATIVE);
|
||||
result = dump_irep(mrb, irep, flags, &bin, &bin_size);
|
||||
if (result == MRB_DUMP_OK) {
|
||||
if (!dump_bigendian_p(flags)) {
|
||||
if (fprintf(fp, "/* dumped in little endian order.\n"
|
||||
" use `mrbc -E` option for big endian CPU. */\n") < 0) {
|
||||
mrb_free(mrb, bin);
|
||||
return MRB_DUMP_WRITE_FAULT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (fprintf(fp, "/* dumped in big endian order.\n"
|
||||
" use `mrbc -e` option for better performance on little endian CPU. */\n") < 0) {
|
||||
mrb_free(mrb, bin);
|
||||
return MRB_DUMP_WRITE_FAULT;
|
||||
}
|
||||
}
|
||||
if (fprintf(fp, "#include <stdint.h>\n") < 0) { /* for uint8_t under at least Darwin */
|
||||
mrb_free(mrb, bin);
|
||||
return MRB_DUMP_WRITE_FAULT;
|
||||
|
||||
+58
-7
@@ -160,9 +160,8 @@ set_backtrace(mrb_state *mrb, mrb_value exc, mrb_value backtrace)
|
||||
static mrb_value
|
||||
exc_set_backtrace(mrb_state *mrb, mrb_value exc)
|
||||
{
|
||||
mrb_value backtrace;
|
||||
mrb_value backtrace = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &backtrace);
|
||||
set_backtrace(mrb, exc, backtrace);
|
||||
return backtrace;
|
||||
}
|
||||
@@ -185,6 +184,16 @@ mrb_exc_set(mrb_state *mrb, mrb_value exc)
|
||||
}
|
||||
}
|
||||
|
||||
static mrb_noreturn void
|
||||
exc_throw(mrb_state *mrb, mrb_value exc)
|
||||
{
|
||||
if (!mrb->jmp) {
|
||||
mrb_p(mrb, exc);
|
||||
abort();
|
||||
}
|
||||
MRB_THROW(mrb->jmp);
|
||||
}
|
||||
|
||||
MRB_API mrb_noreturn void
|
||||
mrb_exc_raise(mrb_state *mrb, mrb_value exc)
|
||||
{
|
||||
@@ -197,11 +206,7 @@ mrb_exc_raise(mrb_state *mrb, mrb_value exc)
|
||||
}
|
||||
mrb_exc_set(mrb, exc);
|
||||
}
|
||||
if (!mrb->jmp) {
|
||||
mrb_p(mrb, exc);
|
||||
abort();
|
||||
}
|
||||
MRB_THROW(mrb->jmp);
|
||||
exc_throw(mrb, exc);
|
||||
}
|
||||
|
||||
MRB_API mrb_noreturn void
|
||||
@@ -550,6 +555,52 @@ mrb_argnum_error(mrb_state *mrb, mrb_int argc, int min, int max)
|
||||
#undef FMT
|
||||
}
|
||||
|
||||
void mrb_core_init_printabort(void);
|
||||
|
||||
int
|
||||
mrb_core_init_protect(mrb_state *mrb, void (*body)(mrb_state *, void *), void *opaque)
|
||||
{
|
||||
struct mrb_jmpbuf *prev_jmp = mrb->jmp;
|
||||
struct mrb_jmpbuf c_jmp;
|
||||
int err = 1;
|
||||
|
||||
MRB_TRY(&c_jmp) {
|
||||
mrb->jmp = &c_jmp;
|
||||
body(mrb, opaque);
|
||||
err = 0;
|
||||
} MRB_CATCH(&c_jmp) {
|
||||
if (mrb->exc) {
|
||||
mrb_p(mrb, mrb_obj_value(mrb->exc));
|
||||
mrb->exc = NULL;
|
||||
}
|
||||
else {
|
||||
mrb_core_init_printabort();
|
||||
}
|
||||
} MRB_END_EXC(&c_jmp);
|
||||
|
||||
mrb->jmp = prev_jmp;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
mrb_noreturn void
|
||||
mrb_core_init_abort(mrb_state *mrb)
|
||||
{
|
||||
mrb->exc = NULL;
|
||||
exc_throw(mrb, mrb_nil_value());
|
||||
}
|
||||
|
||||
mrb_noreturn void
|
||||
mrb_raise_nomemory(mrb_state *mrb)
|
||||
{
|
||||
if (mrb->nomem_err) {
|
||||
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
|
||||
}
|
||||
else {
|
||||
mrb_core_init_abort(mrb);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mrb_init_exception(mrb_state *mrb)
|
||||
{
|
||||
|
||||
@@ -132,7 +132,6 @@ mrb_obj_id(mrb_value obj)
|
||||
case MRB_TT_HASH:
|
||||
case MRB_TT_RANGE:
|
||||
case MRB_TT_EXCEPTION:
|
||||
case MRB_TT_FILE:
|
||||
case MRB_TT_DATA:
|
||||
case MRB_TT_ISTRUCT:
|
||||
default:
|
||||
@@ -140,7 +139,13 @@ mrb_obj_id(mrb_value obj)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(MRB_NAN_BOXING) && defined(MRB_64BIT)
|
||||
#define mrb_xxx_boxing_cptr_value mrb_nan_boxing_cptr_value
|
||||
#endif
|
||||
|
||||
#ifdef MRB_WORD_BOXING
|
||||
#define mrb_xxx_boxing_cptr_value mrb_word_boxing_cptr_value
|
||||
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
MRB_API mrb_value
|
||||
mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f)
|
||||
@@ -164,17 +169,20 @@ mrb_word_boxing_float_pool(mrb_state *mrb, mrb_float f)
|
||||
return mrb_obj_value(nf);
|
||||
}
|
||||
#endif /* MRB_WITHOUT_FLOAT */
|
||||
#endif /* MRB_WORD_BOXING */
|
||||
|
||||
#if defined(MRB_WORD_BOXING) || (defined(MRB_NAN_BOXING) && defined(MRB_64BIT))
|
||||
MRB_API mrb_value
|
||||
mrb_word_boxing_cptr_value(mrb_state *mrb, void *p)
|
||||
mrb_xxx_boxing_cptr_value(mrb_state *mrb, void *p)
|
||||
{
|
||||
mrb_value v;
|
||||
struct RCptr *cptr = (struct RCptr*)mrb_obj_alloc(mrb, MRB_TT_CPTR, mrb->object_class);
|
||||
|
||||
v.value.p = mrb_obj_alloc(mrb, MRB_TT_CPTR, mrb->object_class);
|
||||
v.value.vp->p = p;
|
||||
SET_OBJ_VALUE(v, cptr);
|
||||
cptr->p = p;
|
||||
return v;
|
||||
}
|
||||
#endif /* MRB_WORD_BOXING */
|
||||
#endif
|
||||
|
||||
#if defined _MSC_VER && _MSC_VER < 1900
|
||||
|
||||
|
||||
+98
-21
@@ -37,9 +37,19 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#include <mruby.h>
|
||||
#include <mruby/string.h>
|
||||
|
||||
struct fmt_args;
|
||||
|
||||
typedef void output_func(struct fmt_args *f, const char *s, size_t l);
|
||||
|
||||
struct fmt_args {
|
||||
mrb_state *mrb;
|
||||
mrb_value str;
|
||||
output_func *output;
|
||||
void *opaque;
|
||||
};
|
||||
|
||||
struct mrb_cstr {
|
||||
char *buf;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
#define MAX(a,b) ((a)>(b) ? (a) : (b))
|
||||
@@ -54,15 +64,44 @@ struct fmt_args {
|
||||
#define PAD_POS (1U<<(' '-' '))
|
||||
#define MARK_POS (1U<<('+'-' '))
|
||||
|
||||
#define FLAGMASK (ALT_FORM|ZERO_PAD|LEFT_ADJ|PAD_POS|MARK_POS)
|
||||
|
||||
static output_func strcat_value;
|
||||
static output_func strcat_cstr;
|
||||
|
||||
static void
|
||||
strcat_value(struct fmt_args *f, const char *s, size_t l)
|
||||
{
|
||||
mrb_value str = *(mrb_value*)f->opaque;
|
||||
mrb_str_cat(f->mrb, str, s, l);
|
||||
}
|
||||
|
||||
static void
|
||||
strcat_cstr(struct fmt_args *f, const char *s, size_t l)
|
||||
{
|
||||
struct mrb_cstr *cstr = (struct mrb_cstr*)f->opaque;
|
||||
|
||||
if (l > cstr->len) {
|
||||
mrb_state *mrb = f->mrb;
|
||||
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "string buffer too small");
|
||||
}
|
||||
|
||||
memcpy(cstr->buf, s, l);
|
||||
|
||||
cstr->buf += l;
|
||||
cstr->len -= l;
|
||||
}
|
||||
|
||||
static void
|
||||
out(struct fmt_args *f, const char *s, size_t l)
|
||||
{
|
||||
mrb_str_cat(f->mrb, f->str, s, l);
|
||||
f->output(f, s, l);
|
||||
}
|
||||
|
||||
#define PAD_SIZE 256
|
||||
static void
|
||||
pad(struct fmt_args *f, char c, ptrdiff_t w, ptrdiff_t l, uint8_t fl)
|
||||
pad(struct fmt_args *f, char c, ptrdiff_t w, ptrdiff_t l, uint32_t fl)
|
||||
{
|
||||
char pad[PAD_SIZE];
|
||||
if (fl & (LEFT_ADJ | ZERO_PAD) || l >= w) return;
|
||||
@@ -92,7 +131,7 @@ typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)
|
||||
#endif
|
||||
|
||||
static int
|
||||
fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
|
||||
fmt_fp(struct fmt_args *f, long double y, ptrdiff_t w, ptrdiff_t p, uint32_t fl, int t)
|
||||
{
|
||||
uint32_t big[(LDBL_MANT_DIG+28)/29 + 1 // mantissa expansion
|
||||
+ (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion
|
||||
@@ -117,11 +156,11 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
|
||||
if (!isfinite(y)) {
|
||||
const char *ss = (t&32)?"inf":"INF";
|
||||
if (y!=y) ss=(t&32)?"nan":"NAN";
|
||||
pad(f, ' ', 0, 3+pl, fl&~ZERO_PAD);
|
||||
pad(f, ' ', w, 3+pl, fl&~ZERO_PAD);
|
||||
out(f, prefix, pl);
|
||||
out(f, ss, 3);
|
||||
pad(f, ' ', 0, 3+pl, fl^LEFT_ADJ);
|
||||
return 3+(int)pl;
|
||||
pad(f, ' ', w, 3+pl, fl^LEFT_ADJ);
|
||||
return (int)MAX(w, 3+pl);
|
||||
}
|
||||
|
||||
y = frexp((double)y, &e2) * 2;
|
||||
@@ -169,14 +208,14 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
|
||||
else
|
||||
l = (s-buf) + (ebuf-estr);
|
||||
|
||||
pad(f, ' ', 0, pl+l, fl);
|
||||
pad(f, ' ', w, pl+l, fl);
|
||||
out(f, prefix, pl);
|
||||
pad(f, '0', 0, pl+l, fl^ZERO_PAD);
|
||||
pad(f, '0', w, pl+l, fl^ZERO_PAD);
|
||||
out(f, buf, s-buf);
|
||||
pad(f, '0', l-(ebuf-estr)-(s-buf), 0, 0);
|
||||
out(f, estr, ebuf-estr);
|
||||
pad(f, ' ', 0, pl+l, fl^LEFT_ADJ);
|
||||
return (int)pl+(int)l;
|
||||
pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
|
||||
return (int)MAX(w, pl+l);
|
||||
}
|
||||
if (p<0) p=6;
|
||||
|
||||
@@ -288,9 +327,9 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
|
||||
l += ebuf-estr;
|
||||
}
|
||||
|
||||
pad(f, ' ', 0, pl+l, fl);
|
||||
pad(f, ' ', w, pl+l, fl);
|
||||
out(f, prefix, pl);
|
||||
pad(f, '0', 0, pl+l, fl^ZERO_PAD);
|
||||
pad(f, '0', w, pl+l, fl^ZERO_PAD);
|
||||
|
||||
if ((t|32)=='f') {
|
||||
if (a>r) a=r;
|
||||
@@ -325,21 +364,33 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
|
||||
out(f, estr, ebuf-estr);
|
||||
}
|
||||
|
||||
pad(f, ' ', 0, pl+l, fl^LEFT_ADJ);
|
||||
pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
|
||||
|
||||
return (int)pl+(int)l;
|
||||
return (int)MAX(w, pl+l);
|
||||
}
|
||||
|
||||
static int
|
||||
fmt_core(struct fmt_args *f, const char *fmt, mrb_float flo)
|
||||
{
|
||||
ptrdiff_t p;
|
||||
ptrdiff_t w, p;
|
||||
uint32_t fl;
|
||||
|
||||
if (*fmt != '%') {
|
||||
return -1;
|
||||
}
|
||||
++fmt;
|
||||
|
||||
/* Read modifier flags */
|
||||
for (fl=0; (unsigned)*fmt-' '<32 && (FLAGMASK&(1U<<(*fmt-' '))); fmt++)
|
||||
fl |= 1U<<(*fmt-' ');
|
||||
|
||||
/* - and 0 flags are mutually exclusive */
|
||||
if (fl & LEFT_ADJ) fl &= ~ZERO_PAD;
|
||||
|
||||
for (w = 0; ISDIGIT(*fmt); ++fmt) {
|
||||
w = 10 * w + (*fmt - '0');
|
||||
}
|
||||
|
||||
if (*fmt == '.') {
|
||||
++fmt;
|
||||
for (p = 0; ISDIGIT(*fmt); ++fmt) {
|
||||
@@ -353,29 +404,49 @@ fmt_core(struct fmt_args *f, const char *fmt, mrb_float flo)
|
||||
switch (*fmt) {
|
||||
case 'e': case 'f': case 'g': case 'a':
|
||||
case 'E': case 'F': case 'G': case 'A':
|
||||
return fmt_fp(f, flo, p, 0, *fmt);
|
||||
return fmt_fp(f, flo, w, p, fl, *fmt);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
mrb_value
|
||||
MRB_API mrb_value
|
||||
mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt)
|
||||
{
|
||||
struct fmt_args f;
|
||||
mrb_value str = mrb_str_new_capa(mrb, 24);
|
||||
|
||||
f.mrb = mrb;
|
||||
f.str = mrb_str_new_capa(mrb, 24);
|
||||
f.output = strcat_value;
|
||||
f.opaque = (void*)&str;
|
||||
if (fmt_core(&f, fmt, mrb_float(flo)) < 0) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format string");
|
||||
}
|
||||
return f.str;
|
||||
return str;
|
||||
}
|
||||
|
||||
MRB_API int
|
||||
mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float fval)
|
||||
{
|
||||
struct fmt_args f;
|
||||
struct mrb_cstr cstr;
|
||||
|
||||
cstr.buf = buf;
|
||||
cstr.len = len - 1; /* reserve NUL terminator */
|
||||
f.mrb = mrb;
|
||||
f.output = strcat_cstr;
|
||||
f.opaque = (void*)&cstr;
|
||||
if (fmt_core(&f, fmt, fval) < 0) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format string");
|
||||
}
|
||||
*cstr.buf = '\0';
|
||||
return (int)(cstr.buf - buf);
|
||||
}
|
||||
#else /* MRB_DISABLE_STDIO || _WIN32 || _WIN64 */
|
||||
#include <mruby.h>
|
||||
#include <stdio.h>
|
||||
|
||||
mrb_value
|
||||
MRB_API mrb_value
|
||||
mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt)
|
||||
{
|
||||
char buf[25];
|
||||
@@ -383,5 +454,11 @@ mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt)
|
||||
snprintf(buf, sizeof(buf), fmt, mrb_float(flo));
|
||||
return mrb_str_new_cstr(mrb, buf);
|
||||
}
|
||||
|
||||
MRB_API int
|
||||
mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float fval)
|
||||
{
|
||||
return snprintf(buf, len, fmt, fval);
|
||||
}
|
||||
#endif /* MRB_DISABLE_STDIO || _WIN32 || _WIN64 */
|
||||
#endif
|
||||
|
||||
@@ -201,6 +201,8 @@ gettimeofday_time(void)
|
||||
|
||||
#define objects(p) ((RVALUE *)p->objects)
|
||||
|
||||
mrb_noreturn void mrb_raise_nomemory(mrb_state *mrb);
|
||||
|
||||
MRB_API void*
|
||||
mrb_realloc_simple(mrb_state *mrb, void *p, size_t len)
|
||||
{
|
||||
@@ -224,12 +226,12 @@ mrb_realloc(mrb_state *mrb, void *p, size_t len)
|
||||
if (len == 0) return p2;
|
||||
if (p2 == NULL) {
|
||||
if (mrb->gc.out_of_memory) {
|
||||
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
|
||||
mrb_raise_nomemory(mrb);
|
||||
/* mrb_panic(mrb); */
|
||||
}
|
||||
else {
|
||||
mrb->gc.out_of_memory = TRUE;
|
||||
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
|
||||
mrb_raise_nomemory(mrb);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -714,10 +716,10 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
|
||||
struct REnv *e = (struct REnv*)obj;
|
||||
mrb_int i, len;
|
||||
|
||||
if (MRB_ENV_STACK_SHARED_P(e) && e->cxt && e->cxt->fib) {
|
||||
if (MRB_ENV_ONSTACK_P(e) && e->cxt && e->cxt->fib) {
|
||||
mrb_gc_mark(mrb, (struct RBasic*)e->cxt->fib);
|
||||
}
|
||||
len = MRB_ENV_STACK_LEN(e);
|
||||
len = MRB_ENV_LEN(e);
|
||||
for (i=0; i<len; i++) {
|
||||
mrb_gc_mark_value(mrb, e->stack[i]);
|
||||
}
|
||||
@@ -818,7 +820,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end)
|
||||
{
|
||||
struct REnv *e = (struct REnv*)obj;
|
||||
|
||||
if (MRB_ENV_STACK_SHARED_P(e)) {
|
||||
if (MRB_ENV_ONSTACK_P(e)) {
|
||||
/* cannot be freed */
|
||||
e->stack = NULL;
|
||||
break;
|
||||
@@ -840,7 +842,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end)
|
||||
while (ce <= ci) {
|
||||
struct REnv *e = ci->env;
|
||||
if (e && !mrb_object_dead_p(mrb, (struct RBasic*)e) &&
|
||||
e->tt == MRB_TT_ENV && MRB_ENV_STACK_SHARED_P(e)) {
|
||||
e->tt == MRB_TT_ENV && MRB_ENV_ONSTACK_P(e)) {
|
||||
mrb_env_unshare(mrb, e);
|
||||
}
|
||||
ci--;
|
||||
@@ -958,13 +960,12 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc)
|
||||
}
|
||||
}
|
||||
|
||||
/* rough estimation of number of GC marks (non recursive) */
|
||||
static size_t
|
||||
gc_gray_mark(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
|
||||
gc_gray_counts(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
|
||||
{
|
||||
size_t children = 0;
|
||||
|
||||
gc_mark_children(mrb, gc, obj);
|
||||
|
||||
switch (obj->tt) {
|
||||
case MRB_TT_ICLASS:
|
||||
children++;
|
||||
@@ -989,7 +990,7 @@ gc_gray_mark(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
|
||||
break;
|
||||
|
||||
case MRB_TT_ENV:
|
||||
children += MRB_ENV_STACK_LEN(obj);
|
||||
children += MRB_ENV_LEN(obj);
|
||||
break;
|
||||
|
||||
case MRB_TT_FIBER:
|
||||
@@ -1062,7 +1063,9 @@ incremental_marking_phase(mrb_state *mrb, mrb_gc *gc, size_t limit)
|
||||
size_t tried_marks = 0;
|
||||
|
||||
while (gc->gray_list && tried_marks < limit) {
|
||||
tried_marks += gc_gray_mark(mrb, gc, gc->gray_list);
|
||||
struct RBasic *obj = gc->gray_list;
|
||||
gc_mark_children(mrb, gc, obj);
|
||||
tried_marks += gc_gray_counts(mrb, gc, obj);
|
||||
}
|
||||
|
||||
return tried_marks;
|
||||
@@ -1294,6 +1297,7 @@ mrb_full_gc(mrb_state *mrb)
|
||||
{
|
||||
mrb_gc *gc = &mrb->gc;
|
||||
|
||||
if (!mrb->c) return;
|
||||
if (gc->disabled || gc->iterating) return;
|
||||
|
||||
GC_INVOKE_TIME_REPORT("mrb_full_gc()");
|
||||
@@ -1632,272 +1636,3 @@ mrb_init_gc(mrb_state *mrb)
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef GC_TEST
|
||||
#ifdef GC_DEBUG
|
||||
void
|
||||
test_mrb_field_write_barrier(void)
|
||||
{
|
||||
mrb_state *mrb = mrb_open();
|
||||
struct RBasic *obj, *value;
|
||||
mrb_gc *gc = &mrb->gc;
|
||||
|
||||
puts("test_mrb_field_write_barrier");
|
||||
gc->generational = FALSE;
|
||||
obj = mrb_basic_ptr(mrb_ary_new(mrb));
|
||||
value = mrb_basic_ptr(mrb_str_new_lit(mrb, "value"));
|
||||
paint_black(obj);
|
||||
paint_partial_white(gc, value);
|
||||
|
||||
|
||||
puts(" in MRB_GC_STATE_MARK");
|
||||
gc->state = MRB_GC_STATE_MARK;
|
||||
mrb_field_write_barrier(mrb, obj, value);
|
||||
|
||||
mrb_assert(is_gray(value));
|
||||
|
||||
|
||||
puts(" in MRB_GC_STATE_SWEEP");
|
||||
paint_partial_white(gc, value);
|
||||
gc->state = MRB_GC_STATE_SWEEP;
|
||||
mrb_field_write_barrier(mrb, obj, value);
|
||||
|
||||
mrb_assert(obj->color & gc->current_white_part);
|
||||
mrb_assert(value->color & gc->current_white_part);
|
||||
|
||||
|
||||
puts(" fail with black");
|
||||
gc->state = MRB_GC_STATE_MARK;
|
||||
paint_white(obj);
|
||||
paint_partial_white(gc, value);
|
||||
mrb_field_write_barrier(mrb, obj, value);
|
||||
|
||||
mrb_assert(obj->color & gc->current_white_part);
|
||||
|
||||
|
||||
puts(" fail with gray");
|
||||
gc->state = MRB_GC_STATE_MARK;
|
||||
paint_black(obj);
|
||||
paint_gray(value);
|
||||
mrb_field_write_barrier(mrb, obj, value);
|
||||
|
||||
mrb_assert(is_gray(value));
|
||||
|
||||
|
||||
{
|
||||
puts("test_mrb_field_write_barrier_value");
|
||||
obj = mrb_basic_ptr(mrb_ary_new(mrb));
|
||||
mrb_value value = mrb_str_new_lit(mrb, "value");
|
||||
paint_black(obj);
|
||||
paint_partial_white(gc, mrb_basic_ptr(value));
|
||||
|
||||
gc->state = MRB_GC_STATE_MARK;
|
||||
mrb_field_write_barrier_value(mrb, obj, value);
|
||||
|
||||
mrb_assert(is_gray(mrb_basic_ptr(value)));
|
||||
}
|
||||
|
||||
mrb_close(mrb);
|
||||
}
|
||||
|
||||
void
|
||||
test_mrb_write_barrier(void)
|
||||
{
|
||||
mrb_state *mrb = mrb_open();
|
||||
struct RBasic *obj;
|
||||
mrb_gc *gc = &mrb->gc;
|
||||
|
||||
puts("test_mrb_write_barrier");
|
||||
obj = mrb_basic_ptr(mrb_ary_new(mrb));
|
||||
paint_black(obj);
|
||||
|
||||
puts(" in MRB_GC_STATE_MARK");
|
||||
gc->state = MRB_GC_STATE_MARK;
|
||||
mrb_write_barrier(mrb, obj);
|
||||
|
||||
mrb_assert(is_gray(obj));
|
||||
mrb_assert(gc->atomic_gray_list == obj);
|
||||
|
||||
|
||||
puts(" fail with gray");
|
||||
paint_gray(obj);
|
||||
mrb_write_barrier(mrb, obj);
|
||||
|
||||
mrb_assert(is_gray(obj));
|
||||
|
||||
mrb_close(mrb);
|
||||
}
|
||||
|
||||
void
|
||||
test_add_gray_list(void)
|
||||
{
|
||||
mrb_state *mrb = mrb_open();
|
||||
struct RBasic *obj1, *obj2;
|
||||
mrb_gc *gc = &mrb->gc;
|
||||
|
||||
puts("test_add_gray_list");
|
||||
change_gen_gc_mode(mrb, gc, FALSE);
|
||||
mrb_assert(gc->gray_list == NULL);
|
||||
obj1 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test"));
|
||||
add_gray_list(mrb, gc, obj1);
|
||||
mrb_assert(gc->gray_list == obj1);
|
||||
mrb_assert(is_gray(obj1));
|
||||
|
||||
obj2 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test"));
|
||||
add_gray_list(mrb, gc, obj2);
|
||||
mrb_assert(gc->gray_list == obj2);
|
||||
mrb_assert(gc->gray_list->gcnext == obj1);
|
||||
mrb_assert(is_gray(obj2));
|
||||
|
||||
mrb_close(mrb);
|
||||
}
|
||||
|
||||
void
|
||||
test_gc_gray_mark(void)
|
||||
{
|
||||
mrb_state *mrb = mrb_open();
|
||||
mrb_value obj_v, value_v;
|
||||
struct RBasic *obj;
|
||||
size_t gray_num = 0;
|
||||
mrb_gc *gc = &mrb->gc;
|
||||
|
||||
puts("test_gc_gray_mark");
|
||||
|
||||
puts(" in MRB_TT_CLASS");
|
||||
obj = (struct RBasic*)mrb->object_class;
|
||||
paint_gray(obj);
|
||||
gray_num = gc_gray_mark(mrb, gc, obj);
|
||||
mrb_assert(is_black(obj));
|
||||
mrb_assert(gray_num > 1);
|
||||
|
||||
puts(" in MRB_TT_ARRAY");
|
||||
obj_v = mrb_ary_new(mrb);
|
||||
value_v = mrb_str_new_lit(mrb, "test");
|
||||
paint_gray(mrb_basic_ptr(obj_v));
|
||||
paint_partial_white(gc, mrb_basic_ptr(value_v));
|
||||
mrb_ary_push(mrb, obj_v, value_v);
|
||||
gray_num = gc_gray_mark(mrb, gc, mrb_basic_ptr(obj_v));
|
||||
mrb_assert(is_black(mrb_basic_ptr(obj_v)));
|
||||
mrb_assert(is_gray(mrb_basic_ptr(value_v)));
|
||||
mrb_assert(gray_num == 1);
|
||||
|
||||
mrb_close(mrb);
|
||||
}
|
||||
|
||||
void
|
||||
test_incremental_gc(void)
|
||||
{
|
||||
mrb_state *mrb = mrb_open();
|
||||
size_t max = ~0, live = 0, total = 0, freed = 0;
|
||||
RVALUE *free;
|
||||
mrb_heap_page *page;
|
||||
mrb_gc *gc = &mrb->gc;
|
||||
|
||||
puts("test_incremental_gc");
|
||||
change_gen_gc_mode(mrb, gc, FALSE);
|
||||
|
||||
puts(" in mrb_full_gc");
|
||||
mrb_full_gc(mrb);
|
||||
|
||||
mrb_assert(gc->state == MRB_GC_STATE_ROOT);
|
||||
puts(" in MRB_GC_STATE_ROOT");
|
||||
incremental_gc(mrb, gc, max);
|
||||
mrb_assert(gc->state == MRB_GC_STATE_MARK);
|
||||
puts(" in MRB_GC_STATE_MARK");
|
||||
incremental_gc_until(mrb, gc, MRB_GC_STATE_SWEEP);
|
||||
mrb_assert(gc->state == MRB_GC_STATE_SWEEP);
|
||||
|
||||
puts(" in MRB_GC_STATE_SWEEP");
|
||||
page = gc->heaps;
|
||||
while (page) {
|
||||
RVALUE *p = objects(page);
|
||||
RVALUE *e = p + MRB_HEAP_PAGE_SIZE;
|
||||
while (p<e) {
|
||||
if (is_black(&p->as.basic)) {
|
||||
live++;
|
||||
}
|
||||
if (is_gray(&p->as.basic) && !is_dead(gc, &p->as.basic)) {
|
||||
printf("%p\n", &p->as.basic);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
page = page->next;
|
||||
total += MRB_HEAP_PAGE_SIZE;
|
||||
}
|
||||
|
||||
mrb_assert(gc->gray_list == NULL);
|
||||
|
||||
incremental_gc(mrb, gc, max);
|
||||
mrb_assert(gc->state == MRB_GC_STATE_SWEEP);
|
||||
|
||||
incremental_gc(mrb, gc, max);
|
||||
mrb_assert(gc->state == MRB_GC_STATE_ROOT);
|
||||
|
||||
free = (RVALUE*)gc->heaps->freelist;
|
||||
while (free) {
|
||||
freed++;
|
||||
free = (RVALUE*)free->as.free.next;
|
||||
}
|
||||
|
||||
mrb_assert(gc->live == live);
|
||||
mrb_assert(gc->live == total-freed);
|
||||
|
||||
puts("test_incremental_gc(gen)");
|
||||
incremental_gc_until(mrb, gc, MRB_GC_STATE_SWEEP);
|
||||
change_gen_gc_mode(mrb, gc, TRUE);
|
||||
|
||||
mrb_assert(gc->full == FALSE);
|
||||
mrb_assert(gc->state == MRB_GC_STATE_ROOT);
|
||||
|
||||
puts(" in minor");
|
||||
mrb_assert(is_minor_gc(gc));
|
||||
mrb_assert(gc->majorgc_old_threshold > 0);
|
||||
gc->majorgc_old_threshold = 0;
|
||||
mrb_incremental_gc(mrb);
|
||||
mrb_assert(gc->full == TRUE);
|
||||
mrb_assert(gc->state == MRB_GC_STATE_ROOT);
|
||||
|
||||
puts(" in major");
|
||||
mrb_assert(is_major_gc(gc));
|
||||
do {
|
||||
mrb_incremental_gc(mrb);
|
||||
} while (gc->state != MRB_GC_STATE_ROOT);
|
||||
mrb_assert(gc->full == FALSE);
|
||||
|
||||
mrb_close(mrb);
|
||||
}
|
||||
|
||||
void
|
||||
test_incremental_sweep_phase(void)
|
||||
{
|
||||
mrb_state *mrb = mrb_open();
|
||||
mrb_gc *gc = &mrb->gc;
|
||||
|
||||
puts("test_incremental_sweep_phase");
|
||||
|
||||
add_heap(mrb, gc);
|
||||
gc->sweeps = gc->heaps;
|
||||
|
||||
mrb_assert(gc->heaps->next->next == NULL);
|
||||
mrb_assert(gc->free_heaps->next->next == NULL);
|
||||
incremental_sweep_phase(mrb, gc, MRB_HEAP_PAGE_SIZE * 3);
|
||||
|
||||
mrb_assert(gc->heaps->next == NULL);
|
||||
mrb_assert(gc->heaps == gc->free_heaps);
|
||||
|
||||
mrb_close(mrb);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
gc_test(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
test_mrb_field_write_barrier();
|
||||
test_mrb_write_barrier();
|
||||
test_add_gray_list();
|
||||
test_gc_gray_mark();
|
||||
test_incremental_gc();
|
||||
test_incremental_sweep_phase();
|
||||
return mrb_nil_value();
|
||||
}
|
||||
#endif /* GC_DEBUG */
|
||||
#endif /* GC_TEST */
|
||||
|
||||
+12
-19
@@ -73,7 +73,7 @@ ht_hash_func(mrb_state *mrb, htable *t, mrb_value key)
|
||||
|
||||
default:
|
||||
hv = mrb_funcall(mrb, key, "hash", 0);
|
||||
h = (size_t)t ^ (size_t)mrb_fixnum(hv);
|
||||
h = (size_t)tt ^ (size_t)mrb_fixnum(hv);
|
||||
break;
|
||||
}
|
||||
if (index && (index != t->index || capa != index->capa)) {
|
||||
@@ -365,7 +365,7 @@ ht_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val)
|
||||
if (!seg->next && i >= t->last_len) {
|
||||
seg->e[i].key = key;
|
||||
seg->e[i].val = val;
|
||||
t->last_len = i+1;
|
||||
t->last_len = (uint16_t)i+1;
|
||||
t->size++;
|
||||
return;
|
||||
}
|
||||
@@ -373,7 +373,7 @@ ht_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val)
|
||||
deleted++;
|
||||
continue;
|
||||
}
|
||||
if (ht_hash_equal(mrb, t, k, key)) {
|
||||
if (ht_hash_equal(mrb, t, key, k)) {
|
||||
seg->e[i].val = val;
|
||||
return;
|
||||
}
|
||||
@@ -407,7 +407,7 @@ ht_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val)
|
||||
}
|
||||
seg->e[i].key = key;
|
||||
seg->e[i].val = val;
|
||||
t->last_len = i+1;
|
||||
t->last_len = (uint16_t)i+1;
|
||||
if (t->index == NULL && t->size > MRB_HT_INIT_SIZE*4) {
|
||||
ht_index(mrb, t);
|
||||
}
|
||||
@@ -454,7 +454,7 @@ ht_get(mrb_state *mrb, htable *t, mrb_value key, mrb_value *vp)
|
||||
return FALSE;
|
||||
}
|
||||
if (mrb_undef_p(k)) continue;
|
||||
if (ht_hash_equal(mrb, t, k, key)) {
|
||||
if (ht_hash_equal(mrb, t, key, k)) {
|
||||
if (vp) *vp = seg->e[i].val;
|
||||
return TRUE;
|
||||
}
|
||||
@@ -641,12 +641,11 @@ static mrb_value hash_default(mrb_state *mrb, mrb_value hash, mrb_value key);
|
||||
static mrb_value
|
||||
mrb_hash_init_copy(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value orig;
|
||||
mrb_value orig = mrb_get_arg1(mrb);
|
||||
struct RHash* copy;
|
||||
htable *orig_h;
|
||||
mrb_value ifnone, vret;
|
||||
|
||||
mrb_get_args(mrb, "o", &orig);
|
||||
if (mrb_obj_equal(mrb, self, orig)) return self;
|
||||
if ((mrb_type(self) != mrb_type(orig)) || (mrb_obj_class(mrb, self) != mrb_obj_class(mrb, orig))) {
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "initialize_copy should take same class object");
|
||||
@@ -828,9 +827,8 @@ mrb_hash_init(mrb_state *mrb, mrb_value hash)
|
||||
static mrb_value
|
||||
mrb_hash_aget(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value key;
|
||||
mrb_value key = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &key);
|
||||
return mrb_hash_get(mrb, self, key);
|
||||
}
|
||||
|
||||
@@ -913,9 +911,8 @@ mrb_hash_default(mrb_state *mrb, mrb_value hash)
|
||||
static mrb_value
|
||||
mrb_hash_set_default(mrb_state *mrb, mrb_value hash)
|
||||
{
|
||||
mrb_value ifnone;
|
||||
mrb_value ifnone = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &ifnone);
|
||||
mrb_hash_modify(mrb, hash);
|
||||
mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone);
|
||||
RHASH(hash)->flags &= ~MRB_HASH_PROC_DEFAULT;
|
||||
@@ -969,9 +966,8 @@ mrb_hash_default_proc(mrb_state *mrb, mrb_value hash)
|
||||
static mrb_value
|
||||
mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash)
|
||||
{
|
||||
mrb_value ifnone;
|
||||
mrb_value ifnone = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &ifnone);
|
||||
mrb_hash_modify(mrb, hash);
|
||||
mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone);
|
||||
if (!mrb_nil_p(ifnone)) {
|
||||
@@ -1003,9 +999,8 @@ mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key)
|
||||
static mrb_value
|
||||
mrb_hash_delete(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value key;
|
||||
mrb_value key = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &key);
|
||||
mrb_hash_modify(mrb, self);
|
||||
return mrb_hash_delete_key(mrb, self, key);
|
||||
}
|
||||
@@ -1288,10 +1283,9 @@ mrb_hash_key_p(mrb_state *mrb, mrb_value hash, mrb_value key)
|
||||
static mrb_value
|
||||
mrb_hash_has_key(mrb_state *mrb, mrb_value hash)
|
||||
{
|
||||
mrb_value key;
|
||||
mrb_value key = mrb_get_arg1(mrb);
|
||||
mrb_bool key_p;
|
||||
|
||||
mrb_get_args(mrb, "o", &key);
|
||||
key_p = mrb_hash_key_p(mrb, hash, key);
|
||||
return mrb_bool_value(key_p);
|
||||
}
|
||||
@@ -1331,10 +1325,9 @@ hash_has_value_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p)
|
||||
static mrb_value
|
||||
mrb_hash_has_value(mrb_state *mrb, mrb_value hash)
|
||||
{
|
||||
mrb_value val;
|
||||
mrb_value val = mrb_get_arg1(mrb);
|
||||
struct has_v_arg arg;
|
||||
|
||||
mrb_get_args(mrb, "o", &val);
|
||||
arg.found = FALSE;
|
||||
arg.val = val;
|
||||
ht_foreach(mrb, RHASH_TBL(hash), hash_has_value_i, &arg);
|
||||
|
||||
+6
-9
@@ -71,9 +71,8 @@ mrb_obj_inspect(mrb_state *mrb, mrb_value obj)
|
||||
static mrb_value
|
||||
mrb_equal_m(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value arg;
|
||||
mrb_value arg = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &arg);
|
||||
return mrb_bool_value(mrb_equal(mrb, self, arg));
|
||||
}
|
||||
|
||||
@@ -161,7 +160,7 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
|
||||
/* use saved block arg position */
|
||||
bidx = MRB_ENV_BIDX(e);
|
||||
/* bidx may be useless (e.g. define_method) */
|
||||
if (bidx >= MRB_ENV_STACK_LEN(e))
|
||||
if (bidx >= MRB_ENV_LEN(e))
|
||||
return mrb_false_value();
|
||||
bp = &e->stack[bidx];
|
||||
}
|
||||
@@ -325,7 +324,7 @@ mrb_obj_clone(mrb_state *mrb, mrb_value self)
|
||||
mrb_value clone;
|
||||
|
||||
if (mrb_immediate_p(self)) {
|
||||
mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %v", self);
|
||||
return self;
|
||||
}
|
||||
if (mrb_sclass_p(self)) {
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "can't clone singleton class");
|
||||
@@ -366,7 +365,7 @@ mrb_obj_dup(mrb_state *mrb, mrb_value obj)
|
||||
mrb_value dup;
|
||||
|
||||
if (mrb_immediate_p(obj)) {
|
||||
mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %v", obj);
|
||||
return obj;
|
||||
}
|
||||
if (mrb_sclass_p(obj)) {
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "can't dup singleton class");
|
||||
@@ -471,9 +470,8 @@ mrb_obj_hash(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_obj_init_copy(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value orig;
|
||||
mrb_value orig = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &orig);
|
||||
if (mrb_obj_equal(mrb, self, orig)) return self;
|
||||
if ((mrb_type(self) != mrb_type(orig)) || (mrb_obj_class(mrb, self) != mrb_obj_class(mrb, orig))) {
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "initialize_copy should take same class object");
|
||||
@@ -744,12 +742,11 @@ obj_respond_to(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_obj_ceqq(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value v;
|
||||
mrb_value v = mrb_get_arg1(mrb);
|
||||
mrb_int i, len;
|
||||
mrb_sym eqq = mrb_intern_lit(mrb, "===");
|
||||
mrb_value ary = mrb_ary_splat(mrb, self);
|
||||
|
||||
mrb_get_args(mrb, "o", &v);
|
||||
len = RARRAY_LEN(ary);
|
||||
for (i=0; i<len; i++) {
|
||||
mrb_value c = mrb_funcall_argv(mrb, mrb_ary_entry(ary, i), eqq, 1, &v);
|
||||
|
||||
+56
-30
@@ -14,14 +14,12 @@
|
||||
#include <mruby/string.h>
|
||||
#include <mruby/debug.h>
|
||||
#include <mruby/error.h>
|
||||
#include <mruby/data.h>
|
||||
|
||||
#if SIZE_MAX < UINT32_MAX
|
||||
# error size_t must be at least 32 bits wide
|
||||
#endif
|
||||
|
||||
#define FLAG_BYTEORDER_BIG 2
|
||||
#define FLAG_BYTEORDER_LIL 4
|
||||
#define FLAG_BYTEORDER_NATIVE 8
|
||||
#define FLAG_SRC_MALLOC 1
|
||||
#define FLAG_SRC_STATIC 0
|
||||
|
||||
@@ -58,6 +56,14 @@ str_to_double(mrb_state *mrb, const char *p, size_t len)
|
||||
|
||||
mrb_value mrb_str_len_to_inum(mrb_state *mrb, const char *str, mrb_int len, mrb_int base, int badcheck);
|
||||
|
||||
static void
|
||||
tempirep_free(mrb_state *mrb, void *p)
|
||||
{
|
||||
if (p) mrb_irep_decref(mrb, (mrb_irep *)p);
|
||||
}
|
||||
|
||||
static const mrb_data_type tempirep_type = { "temporary irep", tempirep_free };
|
||||
|
||||
static mrb_irep*
|
||||
read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags)
|
||||
{
|
||||
@@ -66,8 +72,11 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
|
||||
ptrdiff_t diff;
|
||||
uint16_t tt, pool_data_len, snl;
|
||||
int plen;
|
||||
int ai = mrb_gc_arena_save(mrb);
|
||||
struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type);
|
||||
mrb_irep *irep = mrb_add_irep(mrb);
|
||||
int ai = mrb_gc_arena_save(mrb);
|
||||
|
||||
irep_obj->data = irep;
|
||||
|
||||
/* skip record size */
|
||||
src += sizeof(uint32_t);
|
||||
@@ -94,8 +103,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
|
||||
if (SIZE_ERROR_MUL(irep->ilen, sizeof(mrb_code))) {
|
||||
return NULL;
|
||||
}
|
||||
if ((flags & FLAG_SRC_MALLOC) == 0 &&
|
||||
(flags & FLAG_BYTEORDER_NATIVE)) {
|
||||
if ((flags & FLAG_SRC_MALLOC) == 0) {
|
||||
irep->iseq = (mrb_code*)src;
|
||||
src += sizeof(mrb_code) * irep->ilen;
|
||||
irep->flags |= MRB_ISEQ_NO_FREE;
|
||||
@@ -188,36 +196,47 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
|
||||
}
|
||||
}
|
||||
|
||||
irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*irep->rlen);
|
||||
irep->reps = (mrb_irep**)mrb_calloc(mrb, irep->rlen, sizeof(mrb_irep*));
|
||||
|
||||
diff = src - bin;
|
||||
mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
|
||||
*len = (size_t)diff;
|
||||
|
||||
irep_obj->data = NULL;
|
||||
|
||||
return irep;
|
||||
}
|
||||
|
||||
static mrb_irep*
|
||||
read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags)
|
||||
{
|
||||
struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type);
|
||||
int ai = mrb_gc_arena_save(mrb);
|
||||
mrb_irep *irep = read_irep_record_1(mrb, bin, len, flags);
|
||||
int i;
|
||||
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
if (irep == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
irep_obj->data = irep;
|
||||
|
||||
bin += *len;
|
||||
for (i=0; i<irep->rlen; i++) {
|
||||
size_t rlen;
|
||||
|
||||
irep->reps[i] = read_irep_record(mrb, bin, &rlen, flags);
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
if (irep->reps[i] == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
bin += rlen;
|
||||
*len += rlen;
|
||||
}
|
||||
|
||||
irep_obj->data = NULL;
|
||||
|
||||
return irep;
|
||||
}
|
||||
|
||||
@@ -241,21 +260,21 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *
|
||||
|
||||
if (irep->debug_info) { return MRB_DUMP_INVALID_IREP; }
|
||||
|
||||
irep->debug_info = (mrb_irep_debug_info*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info));
|
||||
irep->debug_info = (mrb_irep_debug_info*)mrb_calloc(mrb, 1, sizeof(mrb_irep_debug_info));
|
||||
irep->debug_info->pc_count = (uint32_t)irep->ilen;
|
||||
|
||||
record_size = (size_t)bin_to_uint32(bin);
|
||||
bin += sizeof(uint32_t);
|
||||
|
||||
irep->debug_info->flen = bin_to_uint16(bin);
|
||||
irep->debug_info->files = (mrb_irep_debug_info_file**)mrb_malloc(mrb, sizeof(mrb_irep_debug_info*) * irep->debug_info->flen);
|
||||
irep->debug_info->files = (mrb_irep_debug_info_file**)mrb_calloc(mrb, irep->debug_info->flen, sizeof(mrb_irep_debug_info*));
|
||||
bin += sizeof(uint16_t);
|
||||
|
||||
for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
|
||||
mrb_irep_debug_info_file *file;
|
||||
uint16_t filename_idx;
|
||||
|
||||
file = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*file));
|
||||
file = (mrb_irep_debug_info_file *)mrb_calloc(mrb, 1, sizeof(*file));
|
||||
irep->debug_info->files[f_idx] = file;
|
||||
|
||||
file->start_pos = bin_to_uint32(bin);
|
||||
@@ -285,8 +304,8 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *
|
||||
case mrb_debug_line_flat_map: {
|
||||
uint32_t l;
|
||||
|
||||
file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc(
|
||||
mrb, sizeof(mrb_irep_debug_info_line) * (size_t)(file->line_entry_count));
|
||||
file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_calloc(
|
||||
mrb, (size_t)(file->line_entry_count), sizeof(mrb_irep_debug_info_line));
|
||||
for (l = 0; l < file->line_entry_count; ++l) {
|
||||
file->lines.flat_map[l].start_pos = bin_to_uint32(bin);
|
||||
bin += sizeof(uint32_t);
|
||||
@@ -333,6 +352,7 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t
|
||||
int result;
|
||||
uint16_t filenames_len;
|
||||
mrb_sym *filenames;
|
||||
mrb_value filenames_obj;
|
||||
|
||||
bin = start;
|
||||
header = (struct rite_section_debug_header *)bin;
|
||||
@@ -340,7 +360,8 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t
|
||||
|
||||
filenames_len = bin_to_uint16(bin);
|
||||
bin += sizeof(uint16_t);
|
||||
filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)filenames_len);
|
||||
filenames_obj = mrb_str_new(mrb, NULL, sizeof(mrb_sym) * (size_t)filenames_len);
|
||||
filenames = (mrb_sym*)RSTRING_PTR(filenames_obj);
|
||||
for (i = 0; i < filenames_len; ++i) {
|
||||
uint16_t f_len = bin_to_uint16(bin);
|
||||
bin += sizeof(uint16_t);
|
||||
@@ -364,7 +385,7 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t
|
||||
}
|
||||
|
||||
debug_exit:
|
||||
mrb_free(mrb, filenames);
|
||||
mrb_str_resize(mrb, filenames_obj, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -422,6 +443,7 @@ read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t fl
|
||||
int result;
|
||||
uint32_t syms_len;
|
||||
mrb_sym *syms;
|
||||
mrb_value syms_obj;
|
||||
mrb_sym (*intern_func)(mrb_state*, const char*, size_t) =
|
||||
(flags & FLAG_SRC_MALLOC)? mrb_intern : mrb_intern_static;
|
||||
|
||||
@@ -431,7 +453,8 @@ read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t fl
|
||||
|
||||
syms_len = bin_to_uint32(bin);
|
||||
bin += sizeof(uint32_t);
|
||||
syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)syms_len);
|
||||
syms_obj = mrb_str_new(mrb, NULL, sizeof(mrb_sym) * (size_t)syms_len);
|
||||
syms = (mrb_sym*)RSTRING_PTR(syms_obj);
|
||||
for (i = 0; i < syms_len; ++i) {
|
||||
uint16_t const str_len = bin_to_uint16(bin);
|
||||
bin += sizeof(uint16_t);
|
||||
@@ -451,7 +474,7 @@ read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t fl
|
||||
}
|
||||
|
||||
lv_exit:
|
||||
mrb_free(mrb, syms);
|
||||
mrb_str_resize(mrb, syms_obj, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -464,19 +487,7 @@ read_binary_header(const uint8_t *bin, size_t bufsize, size_t *bin_size, uint16_
|
||||
return MRB_DUMP_READ_FAULT;
|
||||
}
|
||||
|
||||
if (memcmp(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)) == 0) {
|
||||
if (bigendian_p())
|
||||
*flags |= FLAG_BYTEORDER_NATIVE;
|
||||
else
|
||||
*flags |= FLAG_BYTEORDER_BIG;
|
||||
}
|
||||
else if (memcmp(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident)) == 0) {
|
||||
if (bigendian_p())
|
||||
*flags |= FLAG_BYTEORDER_LIL;
|
||||
else
|
||||
*flags |= FLAG_BYTEORDER_NATIVE;
|
||||
}
|
||||
else {
|
||||
if (memcmp(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)) != 0) {
|
||||
return MRB_DUMP_INVALID_FILE_HEADER;
|
||||
}
|
||||
|
||||
@@ -500,6 +511,7 @@ static mrb_irep*
|
||||
read_irep(mrb_state *mrb, const uint8_t *bin, size_t bufsize, uint8_t flags)
|
||||
{
|
||||
int result;
|
||||
struct RData *irep_obj = NULL;
|
||||
mrb_irep *irep = NULL;
|
||||
const struct rite_section_header *section_header;
|
||||
uint16_t crc;
|
||||
@@ -520,12 +532,15 @@ read_irep(mrb_state *mrb, const uint8_t *bin, size_t bufsize, uint8_t flags)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type);
|
||||
|
||||
bin += sizeof(struct rite_binary_header);
|
||||
do {
|
||||
section_header = (const struct rite_section_header *)bin;
|
||||
if (memcmp(section_header->section_ident, RITE_SECTION_IREP_IDENT, sizeof(section_header->section_ident)) == 0) {
|
||||
irep = read_section_irep(mrb, bin, flags);
|
||||
if (!irep) return NULL;
|
||||
irep_obj->data = irep;
|
||||
}
|
||||
else if (memcmp(section_header->section_ident, RITE_SECTION_DEBUG_IDENT, sizeof(section_header->section_ident)) == 0) {
|
||||
if (!irep) return NULL; /* corrupted data */
|
||||
@@ -544,6 +559,8 @@ read_irep(mrb_state *mrb, const uint8_t *bin, size_t bufsize, uint8_t flags)
|
||||
bin += bin_to_uint32(section_header->section_size);
|
||||
} while (memcmp(section_header->section_ident, RITE_BINARY_EOF, sizeof(section_header->section_ident)) != 0);
|
||||
|
||||
irep_obj->data = NULL;
|
||||
|
||||
return irep;
|
||||
}
|
||||
|
||||
@@ -595,7 +612,16 @@ load_irep(mrb_state *mrb, mrb_irep *irep, mrbc_context *c)
|
||||
MRB_API mrb_value
|
||||
mrb_load_irep_cxt(mrb_state *mrb, const uint8_t *bin, mrbc_context *c)
|
||||
{
|
||||
return load_irep(mrb, mrb_read_irep(mrb, bin), c);
|
||||
struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type);
|
||||
mrb_irep *irep = mrb_read_irep(mrb, bin);
|
||||
mrb_value ret;
|
||||
|
||||
irep_obj->data = irep;
|
||||
mrb_irep_incref(mrb, irep);
|
||||
ret = load_irep(mrb, irep, c);
|
||||
irep_obj->data = NULL;
|
||||
mrb_irep_decref(mrb, irep);
|
||||
return ret;
|
||||
}
|
||||
|
||||
MRB_API mrb_value
|
||||
|
||||
+50
-70
@@ -67,12 +67,11 @@ mrb_int_value(mrb_state *mrb, mrb_float f)
|
||||
static mrb_value
|
||||
integral_pow(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
mrb_float d;
|
||||
#endif
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
if (mrb_fixnum_p(x) && mrb_fixnum_p(y)) {
|
||||
/* try ipow() */
|
||||
mrb_int base = mrb_fixnum(x);
|
||||
@@ -116,9 +115,8 @@ static mrb_value
|
||||
integral_idiv(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
#ifdef MRB_WITHOUT_FLOAT
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
if (!mrb_fixnum_p(y)) {
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
|
||||
}
|
||||
@@ -154,9 +152,8 @@ static mrb_value
|
||||
integral_div(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
#ifdef MRB_WITHOUT_FLOAT
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
if (!mrb_fixnum_p(y)) {
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
|
||||
}
|
||||
@@ -210,26 +207,30 @@ static mrb_value
|
||||
flo_to_s(mrb_state *mrb, mrb_value flt)
|
||||
{
|
||||
mrb_float f = mrb_float(flt);
|
||||
mrb_value str;
|
||||
|
||||
if (isinf(f)) {
|
||||
return f < 0 ? mrb_str_new_lit(mrb, "-Infinity")
|
||||
: mrb_str_new_lit(mrb, "Infinity");
|
||||
str = f < 0 ? mrb_str_new_lit(mrb, "-Infinity")
|
||||
: mrb_str_new_lit(mrb, "Infinity");
|
||||
goto exit;
|
||||
}
|
||||
else if (isnan(f)) {
|
||||
return mrb_str_new_lit(mrb, "NaN");
|
||||
str = mrb_str_new_lit(mrb, "NaN");
|
||||
goto exit;
|
||||
}
|
||||
else {
|
||||
char fmt[] = "%." MRB_STRINGIZE(FLO_TO_STR_PREC) "g";
|
||||
mrb_value str = mrb_float_to_str(mrb, flt, fmt);
|
||||
mrb_int len;
|
||||
char *begp, *p, *endp;
|
||||
|
||||
str = mrb_float_to_str(mrb, flt, fmt);
|
||||
|
||||
insert_dot_zero:
|
||||
begp = RSTRING_PTR(str);
|
||||
len = RSTRING_LEN(str);
|
||||
for (p = begp, endp = p + len; p < endp; ++p) {
|
||||
if (*p == '.') {
|
||||
return str;
|
||||
goto exit;
|
||||
}
|
||||
else if (*p == 'e') {
|
||||
ptrdiff_t e_pos = p - begp;
|
||||
@@ -237,7 +238,7 @@ flo_to_s(mrb_state *mrb, mrb_value flt)
|
||||
p = RSTRING_PTR(str) + e_pos;
|
||||
memmove(p + 2, p, len - e_pos);
|
||||
memcpy(p, ".0", 2);
|
||||
return str;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,8 +248,12 @@ flo_to_s(mrb_state *mrb, mrb_value flt)
|
||||
goto insert_dot_zero;
|
||||
}
|
||||
|
||||
return str;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
|
||||
return str;
|
||||
}
|
||||
|
||||
/* 15.2.9.3.2 */
|
||||
@@ -263,9 +268,8 @@ flo_to_s(mrb_state *mrb, mrb_value flt)
|
||||
static mrb_value
|
||||
flo_minus(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y));
|
||||
}
|
||||
|
||||
@@ -281,9 +285,8 @@ flo_minus(mrb_state *mrb, mrb_value x)
|
||||
static mrb_value
|
||||
flo_mul(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
return mrb_float_value(mrb, mrb_float(x) * mrb_to_flo(mrb, y));
|
||||
}
|
||||
|
||||
@@ -343,11 +346,9 @@ flodivmod(mrb_state *mrb, double x, double y, mrb_float *divp, mrb_float *modp)
|
||||
static mrb_value
|
||||
flo_mod(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
mrb_float mod;
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
|
||||
flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), 0, &mod);
|
||||
return mrb_float_value(mrb, mod);
|
||||
}
|
||||
@@ -368,9 +369,8 @@ flo_mod(mrb_state *mrb, mrb_value x)
|
||||
static mrb_value
|
||||
fix_eql(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
if (!mrb_fixnum_p(y)) return mrb_false_value();
|
||||
return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y));
|
||||
}
|
||||
@@ -379,9 +379,8 @@ fix_eql(mrb_state *mrb, mrb_value x)
|
||||
static mrb_value
|
||||
flo_eql(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
if (!mrb_float_p(y)) return mrb_false_value();
|
||||
return mrb_bool_value(mrb_float(x) == mrb_float(y));
|
||||
}
|
||||
@@ -402,8 +401,7 @@ flo_eql(mrb_state *mrb, mrb_value x)
|
||||
static mrb_value
|
||||
flo_eq(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
switch (mrb_type(y)) {
|
||||
case MRB_TT_FIXNUM:
|
||||
@@ -421,7 +419,6 @@ value_int64(mrb_state *mrb, mrb_value x)
|
||||
switch (mrb_type(x)) {
|
||||
case MRB_TT_FIXNUM:
|
||||
return (int64_t)mrb_fixnum(x);
|
||||
break;
|
||||
case MRB_TT_FLOAT:
|
||||
return (int64_t)mrb_float(x);
|
||||
default:
|
||||
@@ -452,9 +449,8 @@ flo_rev(mrb_state *mrb, mrb_value x)
|
||||
static mrb_value
|
||||
flo_and(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
int64_t v1, v2;
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
|
||||
v1 = (int64_t)mrb_float(x);
|
||||
v2 = value_int64(mrb, y);
|
||||
@@ -464,9 +460,8 @@ flo_and(mrb_state *mrb, mrb_value x)
|
||||
static mrb_value
|
||||
flo_or(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
int64_t v1, v2;
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
|
||||
v1 = (int64_t)mrb_float(x);
|
||||
v2 = value_int64(mrb, y);
|
||||
@@ -476,9 +471,8 @@ flo_or(mrb_state *mrb, mrb_value x)
|
||||
static mrb_value
|
||||
flo_xor(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
int64_t v1, v2;
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
|
||||
v1 = (int64_t)mrb_float(x);
|
||||
v2 = value_int64(mrb, y);
|
||||
@@ -839,9 +833,8 @@ mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
static mrb_value
|
||||
fix_mul(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
return fixnum_mul(mrb, x, y);
|
||||
}
|
||||
|
||||
@@ -886,10 +879,9 @@ fixdivmod(mrb_state *mrb, mrb_int x, mrb_int y, mrb_int *divp, mrb_int *modp)
|
||||
static mrb_value
|
||||
fix_mod(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
mrb_int a, b;
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
a = mrb_fixnum(x);
|
||||
if (mrb_fixnum_p(y) && a != MRB_INT_MIN && (b=mrb_fixnum(y)) != MRB_INT_MIN) {
|
||||
mrb_int mod;
|
||||
@@ -928,9 +920,7 @@ fix_mod(mrb_state *mrb, mrb_value x)
|
||||
static mrb_value
|
||||
fix_divmod(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_fixnum_p(y)) {
|
||||
mrb_int div, mod;
|
||||
@@ -967,12 +957,10 @@ fix_divmod(mrb_state *mrb, mrb_value x)
|
||||
static mrb_value
|
||||
flo_divmod(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
mrb_float div, mod;
|
||||
mrb_value a, b;
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
|
||||
flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), &div, &mod);
|
||||
a = mrb_int_value(mrb, div);
|
||||
b = mrb_float_value(mrb, mod);
|
||||
@@ -995,9 +983,8 @@ flo_divmod(mrb_state *mrb, mrb_value x)
|
||||
static mrb_value
|
||||
fix_equal(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
switch (mrb_type(y)) {
|
||||
case MRB_TT_FIXNUM:
|
||||
return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y));
|
||||
@@ -1054,9 +1041,8 @@ static mrb_value flo_xor(mrb_state *mrb, mrb_value x);
|
||||
static mrb_value
|
||||
fix_and(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
bit_op(x, y, and, &);
|
||||
}
|
||||
|
||||
@@ -1071,9 +1057,8 @@ fix_and(mrb_state *mrb, mrb_value x)
|
||||
static mrb_value
|
||||
fix_or(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
bit_op(x, y, or, |);
|
||||
}
|
||||
|
||||
@@ -1088,9 +1073,8 @@ fix_or(mrb_state *mrb, mrb_value x)
|
||||
static mrb_value
|
||||
fix_xor(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
bit_op(x, y, or, ^);
|
||||
}
|
||||
|
||||
@@ -1312,9 +1296,8 @@ mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
static mrb_value
|
||||
fix_plus(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_value other = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
return fixnum_plus(mrb, self, other);
|
||||
}
|
||||
|
||||
@@ -1370,9 +1353,8 @@ mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
static mrb_value
|
||||
fix_minus(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_value other = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
return fixnum_minus(mrb, self, other);
|
||||
}
|
||||
|
||||
@@ -1383,6 +1365,7 @@ mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base)
|
||||
char buf[MRB_INT_BIT+1];
|
||||
char *b = buf + sizeof buf;
|
||||
mrb_int val = mrb_fixnum(x);
|
||||
mrb_value str;
|
||||
|
||||
if (base < 2 || 36 < base) {
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %i", base);
|
||||
@@ -1403,7 +1386,9 @@ mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base)
|
||||
} while (val /= base);
|
||||
}
|
||||
|
||||
return mrb_str_new(mrb, b, buf + sizeof(buf) - b);
|
||||
str = mrb_str_new(mrb, b, buf + sizeof(buf) - b);
|
||||
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
|
||||
return str;
|
||||
}
|
||||
|
||||
/* 15.2.8.3.25 */
|
||||
@@ -1474,21 +1459,21 @@ cmpnum(mrb_state *mrb, mrb_value v1, mrb_value v2)
|
||||
/* 15.2.9.3.6 */
|
||||
/*
|
||||
* call-seq:
|
||||
* self.f <=> other.f => -1, 0, +1
|
||||
* self.f <=> other.f => -1, 0, +1, or nil
|
||||
* < => -1
|
||||
* = => 0
|
||||
* > => +1
|
||||
* Comparison---Returns -1, 0, or +1 depending on whether <i>fix</i> is
|
||||
* less than, equal to, or greater than <i>numeric</i>. This is the
|
||||
* basis for the tests in <code>Comparable</code>.
|
||||
* basis for the tests in <code>Comparable</code>. When the operands are
|
||||
* not comparable, it returns nil instead of raising an exception.
|
||||
*/
|
||||
static mrb_value
|
||||
integral_cmp(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_value other = mrb_get_arg1(mrb);
|
||||
mrb_int n;
|
||||
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
n = cmpnum(mrb, self, other);
|
||||
if (n == -2) return mrb_nil_value();
|
||||
return mrb_fixnum_value(n);
|
||||
@@ -1503,10 +1488,9 @@ cmperr(mrb_state *mrb, mrb_value v1, mrb_value v2)
|
||||
static mrb_value
|
||||
integral_lt(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_value other = mrb_get_arg1(mrb);
|
||||
mrb_int n;
|
||||
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
n = cmpnum(mrb, self, other);
|
||||
if (n == -2) cmperr(mrb, self, other);
|
||||
if (n < 0) return mrb_true_value();
|
||||
@@ -1516,10 +1500,9 @@ integral_lt(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
integral_le(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_value other = mrb_get_arg1(mrb);
|
||||
mrb_int n;
|
||||
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
n = cmpnum(mrb, self, other);
|
||||
if (n == -2) cmperr(mrb, self, other);
|
||||
if (n <= 0) return mrb_true_value();
|
||||
@@ -1529,10 +1512,9 @@ integral_le(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
integral_gt(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_value other = mrb_get_arg1(mrb);
|
||||
mrb_int n;
|
||||
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
n = cmpnum(mrb, self, other);
|
||||
if (n == -2) cmperr(mrb, self, other);
|
||||
if (n > 0) return mrb_true_value();
|
||||
@@ -1542,10 +1524,9 @@ integral_gt(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
integral_ge(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value other;
|
||||
mrb_value other = mrb_get_arg1(mrb);
|
||||
mrb_int n;
|
||||
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
n = cmpnum(mrb, self, other);
|
||||
if (n == -2) cmperr(mrb, self, other);
|
||||
if (n >= 0) return mrb_true_value();
|
||||
@@ -1597,9 +1578,8 @@ num_infinite_p(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
flo_plus(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &y);
|
||||
return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y));
|
||||
}
|
||||
#endif
|
||||
|
||||
+23
-5
@@ -47,6 +47,17 @@ mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2)
|
||||
mrb_value result;
|
||||
|
||||
if (mrb_obj_eq(mrb, obj1, obj2)) return TRUE;
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
/* value mixing with integer and float */
|
||||
if (mrb_fixnum_p(obj1)) {
|
||||
if (mrb_float_p(obj2) && (mrb_float)mrb_fixnum(obj1) == mrb_float(obj2))
|
||||
return TRUE;
|
||||
}
|
||||
else if (mrb_float_p(obj1)) {
|
||||
if (mrb_fixnum_p(obj2) && mrb_float(obj1) == (mrb_float)mrb_fixnum(obj2))
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
result = mrb_funcall(mrb, obj1, "==", 1, obj2);
|
||||
if (mrb_test(result)) return TRUE;
|
||||
return FALSE;
|
||||
@@ -83,13 +94,17 @@ mrb_true(mrb_state *mrb, mrb_value obj)
|
||||
static mrb_value
|
||||
nil_to_s(mrb_state *mrb, mrb_value obj)
|
||||
{
|
||||
return mrb_str_new_frozen(mrb, 0, 0);
|
||||
mrb_value str = mrb_str_new_frozen(mrb, 0, 0);
|
||||
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
|
||||
return str;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
nil_inspect(mrb_state *mrb, mrb_value obj)
|
||||
{
|
||||
return mrb_str_new_lit_frozen(mrb, "nil");
|
||||
mrb_value str = mrb_str_new_lit_frozen(mrb, "nil");
|
||||
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
|
||||
return str;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -150,7 +165,9 @@ true_xor(mrb_state *mrb, mrb_value obj)
|
||||
static mrb_value
|
||||
true_to_s(mrb_state *mrb, mrb_value obj)
|
||||
{
|
||||
return mrb_str_new_lit_frozen(mrb, "true");
|
||||
mrb_value str = mrb_str_new_lit_frozen(mrb, "true");
|
||||
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
|
||||
return str;
|
||||
}
|
||||
|
||||
/* 15.2.5.3.4 */
|
||||
@@ -257,7 +274,9 @@ false_or(mrb_state *mrb, mrb_value obj)
|
||||
static mrb_value
|
||||
false_to_s(mrb_state *mrb, mrb_value obj)
|
||||
{
|
||||
return mrb_str_new_lit_frozen(mrb, "false");
|
||||
mrb_value str = mrb_str_new_lit_frozen(mrb, "false");
|
||||
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
|
||||
return str;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -358,7 +377,6 @@ static const struct types {
|
||||
{MRB_TT_STRING, "String"},
|
||||
{MRB_TT_RANGE, "Range"},
|
||||
/* {MRB_TT_BIGNUM, "Bignum"}, */
|
||||
{MRB_TT_FILE, "File"},
|
||||
{MRB_TT_DATA, "Data"}, /* internal use: wrapped C pointers */
|
||||
/* {MRB_TT_VARMAP, "Varmap"}, */ /* internal use: dynamic variables */
|
||||
/* {MRB_TT_NODE, "Node"}, */ /* internal use: syntax tree node */
|
||||
|
||||
+27
-3
@@ -7,24 +7,48 @@
|
||||
#include <mruby.h>
|
||||
#include <mruby/string.h>
|
||||
#include <mruby/variable.h>
|
||||
#include <mruby/error.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef MRB_DISABLE_STDIO
|
||||
static void
|
||||
printcstr(const char *str, size_t len, FILE *stream)
|
||||
{
|
||||
if (str) {
|
||||
fwrite(str, len, 1, stream);
|
||||
putc('\n', stream);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
printstr(mrb_value obj, FILE *stream)
|
||||
{
|
||||
if (mrb_string_p(obj)) {
|
||||
fwrite(RSTRING_PTR(obj), RSTRING_LEN(obj), 1, stream);
|
||||
putc('\n', stream);
|
||||
printcstr(RSTRING_PTR(obj), RSTRING_LEN(obj), stream);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define printcstr(str, len, stream) (void)0
|
||||
# define printstr(obj, stream) (void)0
|
||||
#endif
|
||||
|
||||
void
|
||||
mrb_core_init_printabort(void)
|
||||
{
|
||||
static const char *str = "Failed mruby core initialization";
|
||||
printcstr(str, strlen(str), stdout);
|
||||
}
|
||||
|
||||
MRB_API void
|
||||
mrb_p(mrb_state *mrb, mrb_value obj)
|
||||
{
|
||||
printstr(mrb_inspect(mrb, obj), stdout);
|
||||
if (mrb_type(obj) == MRB_TT_EXCEPTION && mrb_obj_ptr(obj) == mrb->nomem_err) {
|
||||
static const char *str = "Out of memory";
|
||||
printcstr(str, strlen(str), stdout);
|
||||
}
|
||||
else {
|
||||
printstr(mrb_inspect(mrb, obj), stdout);
|
||||
}
|
||||
}
|
||||
|
||||
MRB_API void
|
||||
|
||||
+26
-7
@@ -8,6 +8,7 @@
|
||||
#include <mruby/class.h>
|
||||
#include <mruby/proc.h>
|
||||
#include <mruby/opcode.h>
|
||||
#include <mruby/data.h>
|
||||
|
||||
static const mrb_code call_iseq[] = {
|
||||
OP_CALL,
|
||||
@@ -46,7 +47,7 @@ env_new(mrb_state *mrb, mrb_int nlocals)
|
||||
int bidx;
|
||||
|
||||
e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, NULL);
|
||||
MRB_ENV_SET_STACK_LEN(e, nlocals);
|
||||
MRB_ENV_SET_LEN(e, nlocals);
|
||||
bidx = ci->argc;
|
||||
if (ci->argc < 0) bidx = 2;
|
||||
else bidx += 1;
|
||||
@@ -121,8 +122,15 @@ mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const
|
||||
p->e.env = e = env_new(mrb, argc);
|
||||
p->flags |= MRB_PROC_ENVSET;
|
||||
mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)e);
|
||||
MRB_ENV_UNSHARE_STACK(e);
|
||||
MRB_ENV_CLOSE(e);
|
||||
|
||||
/* NOTE: Prevents keeping invalid addresses when NoMemoryError is raised from `mrb_malloc()`. */
|
||||
e->stack = NULL;
|
||||
MRB_ENV_SET_LEN(e, 0);
|
||||
|
||||
e->stack = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * argc);
|
||||
MRB_ENV_SET_LEN(e, argc);
|
||||
|
||||
if (argv) {
|
||||
for (i = 0; i < argc; ++i) {
|
||||
e->stack[i] = argv[i];
|
||||
@@ -155,9 +163,9 @@ mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx)
|
||||
if (!e) {
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from cfunc Proc without REnv.");
|
||||
}
|
||||
if (idx < 0 || MRB_ENV_STACK_LEN(e) <= idx) {
|
||||
if (idx < 0 || MRB_ENV_LEN(e) <= idx) {
|
||||
mrb_raisef(mrb, E_INDEX_ERROR, "Env index out of range: %i (expected: 0 <= index < %i)",
|
||||
idx, MRB_ENV_STACK_LEN(e));
|
||||
idx, MRB_ENV_LEN(e));
|
||||
}
|
||||
|
||||
return e->stack[idx];
|
||||
@@ -203,9 +211,8 @@ mrb_proc_s_new(mrb_state *mrb, mrb_value proc_class)
|
||||
static mrb_value
|
||||
mrb_proc_init_copy(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value proc;
|
||||
mrb_value proc = mrb_get_arg1(mrb);
|
||||
|
||||
mrb_get_args(mrb, "o", &proc);
|
||||
if (!mrb_proc_p(proc)) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc");
|
||||
}
|
||||
@@ -286,14 +293,25 @@ mrb_proc_arity(const struct RProc *p)
|
||||
return arity;
|
||||
}
|
||||
|
||||
static void
|
||||
tempirep_free(mrb_state *mrb, void *p)
|
||||
{
|
||||
if (p) mrb_irep_free(mrb, (mrb_irep *)p);
|
||||
}
|
||||
|
||||
static const mrb_data_type tempirep_type = { "temporary irep", tempirep_free };
|
||||
|
||||
void
|
||||
mrb_init_proc(mrb_state *mrb)
|
||||
{
|
||||
struct RProc *p;
|
||||
mrb_method_t m;
|
||||
mrb_irep *call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
|
||||
struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type);
|
||||
mrb_irep *call_irep;
|
||||
static const mrb_irep mrb_irep_zero = { 0 };
|
||||
|
||||
call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
|
||||
irep_obj->data = call_irep;
|
||||
*call_irep = mrb_irep_zero;
|
||||
call_irep->flags = MRB_ISEQ_NO_FREE;
|
||||
call_irep->iseq = call_iseq;
|
||||
@@ -305,6 +323,7 @@ mrb_init_proc(mrb_state *mrb)
|
||||
mrb_define_method(mrb, mrb->proc_class, "arity", proc_arity, MRB_ARGS_NONE());
|
||||
|
||||
p = mrb_proc_new(mrb, call_irep);
|
||||
irep_obj->data = NULL;
|
||||
MRB_METHOD_FROM_PROC(m, p);
|
||||
mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "call"), m);
|
||||
mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "[]"), m);
|
||||
|
||||
+4
-12
@@ -182,11 +182,9 @@ range_eq(mrb_state *mrb, mrb_value range)
|
||||
{
|
||||
struct RRange *rr;
|
||||
struct RRange *ro;
|
||||
mrb_value obj;
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
mrb_bool v1, v2;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
|
||||
if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
|
||||
if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) { /* same class? */
|
||||
return mrb_false_value();
|
||||
@@ -211,13 +209,11 @@ range_eq(mrb_state *mrb, mrb_value range)
|
||||
static mrb_value
|
||||
range_include(mrb_state *mrb, mrb_value range)
|
||||
{
|
||||
mrb_value val;
|
||||
mrb_value val = mrb_get_arg1(mrb);
|
||||
struct RRange *r = mrb_range_ptr(mrb, range);
|
||||
mrb_value beg, end;
|
||||
mrb_bool include_p;
|
||||
|
||||
mrb_get_args(mrb, "o", &val);
|
||||
|
||||
beg = RANGE_BEG(r);
|
||||
end = RANGE_END(r);
|
||||
include_p = r_le(mrb, beg, val) && /* beg <= val */
|
||||
@@ -289,11 +285,9 @@ range_inspect(mrb_state *mrb, mrb_value range)
|
||||
static mrb_value
|
||||
range_eql(mrb_state *mrb, mrb_value range)
|
||||
{
|
||||
mrb_value obj;
|
||||
mrb_value obj = mrb_get_arg1(mrb);
|
||||
struct RRange *r, *o;
|
||||
|
||||
mrb_get_args(mrb, "o", &obj);
|
||||
|
||||
if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
|
||||
if (!mrb_obj_is_kind_of(mrb, obj, mrb->range_class)) return mrb_false_value();
|
||||
if (!mrb_range_p(obj)) return mrb_false_value();
|
||||
@@ -312,11 +306,9 @@ range_eql(mrb_state *mrb, mrb_value range)
|
||||
static mrb_value
|
||||
range_initialize_copy(mrb_state *mrb, mrb_value copy)
|
||||
{
|
||||
mrb_value src;
|
||||
mrb_value src = mrb_get_arg1(mrb);
|
||||
struct RRange *r;
|
||||
|
||||
mrb_get_args(mrb, "o", &src);
|
||||
|
||||
if (mrb_obj_equal(mrb, copy, src)) return copy;
|
||||
if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) {
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
|
||||
|
||||
+34
-11
@@ -19,11 +19,25 @@ void mrb_init_mrbgems(mrb_state*);
|
||||
void mrb_gc_init(mrb_state*, mrb_gc *gc);
|
||||
void mrb_gc_destroy(mrb_state*, mrb_gc *gc);
|
||||
|
||||
int mrb_core_init_protect(mrb_state *mrb, void (*body)(mrb_state *, void *), void *opaque);
|
||||
|
||||
static void
|
||||
init_gc_and_core(mrb_state *mrb, void *opaque)
|
||||
{
|
||||
static const struct mrb_context mrb_context_zero = { 0 };
|
||||
|
||||
mrb_gc_init(mrb, &mrb->gc);
|
||||
mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
|
||||
*mrb->c = mrb_context_zero;
|
||||
mrb->root_c = mrb->c;
|
||||
|
||||
mrb_init_core(mrb);
|
||||
}
|
||||
|
||||
MRB_API mrb_state*
|
||||
mrb_open_core(mrb_allocf f, void *ud)
|
||||
{
|
||||
static const mrb_state mrb_state_zero = { 0 };
|
||||
static const struct mrb_context mrb_context_zero = { 0 };
|
||||
mrb_state *mrb;
|
||||
|
||||
if (f == NULL) f = mrb_default_allocf;
|
||||
@@ -35,12 +49,10 @@ mrb_open_core(mrb_allocf f, void *ud)
|
||||
mrb->allocf = f;
|
||||
mrb->atexit_stack_len = 0;
|
||||
|
||||
mrb_gc_init(mrb, &mrb->gc);
|
||||
mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
|
||||
*mrb->c = mrb_context_zero;
|
||||
mrb->root_c = mrb->c;
|
||||
|
||||
mrb_init_core(mrb);
|
||||
if (mrb_core_init_protect(mrb, init_gc_and_core, NULL)) {
|
||||
mrb_close(mrb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mrb;
|
||||
}
|
||||
@@ -65,6 +77,12 @@ mrb_open(void)
|
||||
return mrb;
|
||||
}
|
||||
|
||||
static void
|
||||
init_mrbgems(mrb_state *mrb, void *opaque)
|
||||
{
|
||||
mrb_init_mrbgems(mrb);
|
||||
}
|
||||
|
||||
MRB_API mrb_state*
|
||||
mrb_open_allocf(mrb_allocf f, void *ud)
|
||||
{
|
||||
@@ -75,7 +93,10 @@ mrb_open_allocf(mrb_allocf f, void *ud)
|
||||
}
|
||||
|
||||
#ifndef DISABLE_GEMS
|
||||
mrb_init_mrbgems(mrb);
|
||||
if (mrb_core_init_protect(mrb, init_mrbgems, NULL)) {
|
||||
mrb_close(mrb);
|
||||
return NULL;
|
||||
}
|
||||
mrb_gc_arena_restore(mrb, 0);
|
||||
#endif
|
||||
return mrb;
|
||||
@@ -131,9 +152,11 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep)
|
||||
}
|
||||
mrb_free(mrb, irep->pool);
|
||||
mrb_free(mrb, irep->syms);
|
||||
for (i=0; i<irep->rlen; i++) {
|
||||
if (irep->reps[i])
|
||||
mrb_irep_decref(mrb, irep->reps[i]);
|
||||
if (irep->reps) {
|
||||
for (i=0; i<irep->rlen; i++) {
|
||||
if (irep->reps[i])
|
||||
mrb_irep_decref(mrb, irep->reps[i]);
|
||||
}
|
||||
}
|
||||
mrb_free(mrb, irep->reps);
|
||||
mrb_free(mrb, irep->lv);
|
||||
|
||||
+25
-22
@@ -1061,10 +1061,9 @@ mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2)
|
||||
static mrb_value
|
||||
mrb_str_cmp_m(mrb_state *mrb, mrb_value str1)
|
||||
{
|
||||
mrb_value str2;
|
||||
mrb_value str2 = mrb_get_arg1(mrb);
|
||||
mrb_int result;
|
||||
|
||||
mrb_get_args(mrb, "o", &str2);
|
||||
if (!mrb_string_p(str2)) {
|
||||
return mrb_nil_value();
|
||||
}
|
||||
@@ -1106,9 +1105,7 @@ mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2)
|
||||
static mrb_value
|
||||
mrb_str_equal_m(mrb_state *mrb, mrb_value str1)
|
||||
{
|
||||
mrb_value str2;
|
||||
|
||||
mrb_get_args(mrb, "o", &str2);
|
||||
mrb_value str2 = mrb_get_arg1(mrb);
|
||||
|
||||
return mrb_bool_value(mrb_str_equal(mrb, str1, str2));
|
||||
}
|
||||
@@ -1791,10 +1788,9 @@ mrb_str_empty_p(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
mrb_str_eql(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value str2;
|
||||
mrb_value str2 = mrb_get_arg1(mrb);
|
||||
mrb_bool eql_p;
|
||||
|
||||
mrb_get_args(mrb, "o", &str2);
|
||||
eql_p = (mrb_string_p(str2)) && str_eql(mrb, self, str2);
|
||||
|
||||
return mrb_bool_value(eql_p);
|
||||
@@ -2759,7 +2755,7 @@ mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len)
|
||||
MRB_API mrb_value
|
||||
mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr)
|
||||
{
|
||||
return mrb_str_cat(mrb, str, ptr, strlen(ptr));
|
||||
return mrb_str_cat(mrb, str, ptr, ptr ? strlen(ptr) : 0);
|
||||
}
|
||||
|
||||
MRB_API mrb_value
|
||||
@@ -2889,25 +2885,32 @@ mrb_str_setbyte(mrb_state *mrb, mrb_value str)
|
||||
static mrb_value
|
||||
mrb_str_byteslice(mrb_state *mrb, mrb_value str)
|
||||
{
|
||||
mrb_value a1, a2;
|
||||
mrb_value a1;
|
||||
mrb_int str_len = RSTRING_LEN(str), beg, len;
|
||||
mrb_bool empty = TRUE;
|
||||
|
||||
if (mrb_get_args(mrb, "o|o", &a1, &a2) == 2) {
|
||||
beg = mrb_fixnum(mrb_to_int(mrb, a1));
|
||||
len = mrb_fixnum(mrb_to_int(mrb, a2));
|
||||
}
|
||||
else if (mrb_range_p(a1)) {
|
||||
if (mrb_range_beg_len(mrb, a1, &beg, &len, str_len, TRUE) != MRB_RANGE_OK) {
|
||||
return mrb_nil_value();
|
||||
len = mrb_get_argc(mrb);
|
||||
switch (len) {
|
||||
case 2:
|
||||
mrb_get_args(mrb, "ii", &beg, &len);
|
||||
break;
|
||||
case 1:
|
||||
a1 = mrb_get_arg1(mrb);
|
||||
if (mrb_range_p(a1)) {
|
||||
if (mrb_range_beg_len(mrb, a1, &beg, &len, str_len, TRUE) != MRB_RANGE_OK) {
|
||||
return mrb_nil_value();
|
||||
}
|
||||
}
|
||||
else {
|
||||
beg = mrb_fixnum(mrb_to_int(mrb, a1));
|
||||
len = 1;
|
||||
empty = FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
mrb_argnum_error(mrb, len, 1, 2);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
beg = mrb_fixnum(mrb_to_int(mrb, a1));
|
||||
len = 1;
|
||||
empty = FALSE;
|
||||
}
|
||||
|
||||
if (mrb_str_beg_len(str_len, &beg, &len) && (empty || len != 0)) {
|
||||
return mrb_str_byte_subseq(mrb, str, beg, len);
|
||||
}
|
||||
|
||||
+8
-7
@@ -172,11 +172,13 @@ sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit)
|
||||
if (sym > 0) return sym;
|
||||
|
||||
/* registering a new symbol */
|
||||
sym = ++mrb->symidx;
|
||||
sym = mrb->symidx + 1;
|
||||
if (mrb->symcapa < sym) {
|
||||
if (mrb->symcapa == 0) mrb->symcapa = 100;
|
||||
else mrb->symcapa = (size_t)(mrb->symcapa * 6 / 5);
|
||||
mrb->symtbl = (symbol_name*)mrb_realloc(mrb, mrb->symtbl, sizeof(symbol_name)*(mrb->symcapa+1));
|
||||
size_t symcapa = mrb->symcapa;
|
||||
if (symcapa == 0) symcapa = 100;
|
||||
else symcapa = (size_t)(symcapa * 6 / 5);
|
||||
mrb->symtbl = (symbol_name*)mrb_realloc(mrb, mrb->symtbl, sizeof(symbol_name)*(symcapa+1));
|
||||
mrb->symcapa = symcapa;
|
||||
}
|
||||
sname = &mrb->symtbl[sym];
|
||||
sname->len = (uint16_t)len;
|
||||
@@ -201,7 +203,7 @@ sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit)
|
||||
else {
|
||||
sname->prev = 0;
|
||||
}
|
||||
mrb->symhash[hash] = sym;
|
||||
mrb->symhash[hash] = mrb->symidx = sym;
|
||||
|
||||
return sym<<SYMBOL_NORMAL_SHIFT;
|
||||
}
|
||||
@@ -562,10 +564,9 @@ mrb_sym_dump(mrb_state *mrb, mrb_sym sym)
|
||||
static mrb_value
|
||||
sym_cmp(mrb_state *mrb, mrb_value s1)
|
||||
{
|
||||
mrb_value s2;
|
||||
mrb_value s2 = mrb_get_arg1(mrb);
|
||||
mrb_sym sym1, sym2;
|
||||
|
||||
mrb_get_args(mrb, "o", &s2);
|
||||
if (!mrb_symbol_p(s2)) return mrb_nil_value();
|
||||
sym1 = mrb_symbol(s1);
|
||||
sym2 = mrb_symbol(s2);
|
||||
|
||||
@@ -152,7 +152,7 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase, size_t oldsize
|
||||
struct REnv *e = ci->env;
|
||||
mrb_value *st;
|
||||
|
||||
if (e && MRB_ENV_STACK_SHARED_P(e) &&
|
||||
if (e && MRB_ENV_ONSTACK_P(e) &&
|
||||
(st = e->stack) && oldbase <= st && st < oldbase+oldsize) {
|
||||
ptrdiff_t off = e->stack - oldbase;
|
||||
|
||||
@@ -162,7 +162,7 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase, size_t oldsize
|
||||
if (ci->proc && MRB_PROC_ENV_P(ci->proc) && ci->env != MRB_PROC_ENV(ci->proc)) {
|
||||
e = MRB_PROC_ENV(ci->proc);
|
||||
|
||||
if (e && MRB_ENV_STACK_SHARED_P(e) &&
|
||||
if (e && MRB_ENV_ONSTACK_P(e) &&
|
||||
(st = e->stack) && oldbase <= st && st < oldbase+oldsize) {
|
||||
ptrdiff_t off = e->stack - oldbase;
|
||||
|
||||
@@ -297,10 +297,10 @@ mrb_env_unshare(mrb_state *mrb, struct REnv *e)
|
||||
{
|
||||
if (e == NULL) return;
|
||||
else {
|
||||
size_t len = (size_t)MRB_ENV_STACK_LEN(e);
|
||||
size_t len = (size_t)MRB_ENV_LEN(e);
|
||||
mrb_value *p;
|
||||
|
||||
if (!MRB_ENV_STACK_SHARED_P(e)) return;
|
||||
if (!MRB_ENV_ONSTACK_P(e)) return;
|
||||
if (e->cxt != mrb->c) return;
|
||||
if (e == mrb->c->cibase->env) return; /* for mirb */
|
||||
p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
|
||||
@@ -308,7 +308,7 @@ mrb_env_unshare(mrb_state *mrb, struct REnv *e)
|
||||
stack_copy(p, e->stack, len);
|
||||
}
|
||||
e->stack = p;
|
||||
MRB_ENV_UNSHARE_STACK(e);
|
||||
MRB_ENV_CLOSE(e);
|
||||
mrb_write_barrier(mrb, (struct RBasic *)e);
|
||||
}
|
||||
}
|
||||
@@ -324,6 +324,7 @@ cipop(mrb_state *mrb)
|
||||
}
|
||||
|
||||
void mrb_exc_set(mrb_state *mrb, mrb_value exc);
|
||||
static mrb_value mrb_run(mrb_state *mrb, struct RProc* proc, mrb_value self);
|
||||
|
||||
static void
|
||||
ecall(mrb_state *mrb)
|
||||
@@ -335,10 +336,12 @@ ecall(mrb_state *mrb)
|
||||
struct REnv *env;
|
||||
ptrdiff_t cioff;
|
||||
int ai = mrb_gc_arena_save(mrb);
|
||||
uint16_t i = --c->eidx;
|
||||
uint16_t i;
|
||||
int nregs;
|
||||
|
||||
if (i<0) return;
|
||||
if (c->eidx == 0) return;
|
||||
i = --c->eidx;
|
||||
|
||||
/* restrict total call depth of ecall() */
|
||||
if (++mrb->ecall_nest > MRB_ECALL_DEPTH_MAX) {
|
||||
mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
|
||||
@@ -624,7 +627,7 @@ mrb_f_send(mrb_state *mrb, mrb_value self)
|
||||
ci->argc--;
|
||||
}
|
||||
else { /* variable length arguments */
|
||||
mrb_ary_shift(mrb, regs[0]);
|
||||
regs[0] = mrb_ary_subseq(mrb, regs[0], 1, RARRAY_LEN(regs[0]) - 1);
|
||||
}
|
||||
|
||||
if (MRB_METHOD_CFUNC_P(m)) {
|
||||
@@ -648,8 +651,7 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c)
|
||||
}
|
||||
ci = mrb->c->ci;
|
||||
if (ci->acc == CI_ACC_DIRECT) {
|
||||
ci->target_class = c;
|
||||
return mrb_yield_cont(mrb, blk, self, 1, &self);
|
||||
return mrb_yield_with_class(mrb, blk, 1, &self, self, c);
|
||||
}
|
||||
ci->target_class = c;
|
||||
p = mrb_proc_ptr(blk);
|
||||
@@ -724,26 +726,11 @@ mrb_value
|
||||
mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value a, b;
|
||||
mrb_value cv;
|
||||
struct RClass *c;
|
||||
|
||||
if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
|
||||
mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented");
|
||||
}
|
||||
switch (mrb_type(self)) {
|
||||
case MRB_TT_SYMBOL:
|
||||
case MRB_TT_FIXNUM:
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
case MRB_TT_FLOAT:
|
||||
#endif
|
||||
c = 0;
|
||||
break;
|
||||
default:
|
||||
cv = mrb_singleton_class(mrb, self);
|
||||
c = mrb_class_ptr(cv);
|
||||
break;
|
||||
}
|
||||
return eval_under(mrb, self, b, c);
|
||||
return eval_under(mrb, self, b, mrb_singleton_class_ptr(mrb, self));
|
||||
}
|
||||
|
||||
MRB_API mrb_value
|
||||
@@ -767,16 +754,25 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value
|
||||
ci = cipush(mrb);
|
||||
ci->mid = mid;
|
||||
ci->proc = p;
|
||||
ci->stackent = mrb->c->stack;
|
||||
ci->argc = (int)argc;
|
||||
ci->target_class = c;
|
||||
ci->acc = CI_ACC_SKIP;
|
||||
n = MRB_PROC_CFUNC_P(p) ? (int)(argc+2) : p->body.irep->nregs;
|
||||
mrb->c->stack = mrb->c->stack + n;
|
||||
ci->stackent = mrb->c->stack;
|
||||
mrb->c->stack += n;
|
||||
if (argc >= CALL_MAXARGS) {
|
||||
ci->argc = -1;
|
||||
n = 3;
|
||||
}
|
||||
else {
|
||||
ci->argc = (int)argc;
|
||||
n = argc + 2;
|
||||
}
|
||||
mrb_stack_extend(mrb, n);
|
||||
|
||||
mrb->c->stack[0] = self;
|
||||
if (argc > 0) {
|
||||
if (ci->argc < 0) {
|
||||
mrb->c->stack[1] = mrb_ary_new_from_values(mrb, argc, argv);
|
||||
argc = 1;
|
||||
}
|
||||
else if (argc > 0) {
|
||||
stack_copy(mrb->c->stack+1, argv, argc);
|
||||
}
|
||||
mrb->c->stack[argc+1] = mrb_nil_value();
|
||||
@@ -1062,6 +1058,11 @@ RETRY_TRY_BLOCK:
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_LOADI16, BS) {
|
||||
SET_INT_VALUE(regs[a], (mrb_int)(int16_t)b);
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_LOADSYM, BB) {
|
||||
SET_SYM_VALUE(regs[a], syms[b]);
|
||||
NEXT;
|
||||
@@ -1099,13 +1100,13 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
|
||||
CASE(OP_GETSV, BB) {
|
||||
mrb_value val = mrb_vm_special_get(mrb, b);
|
||||
mrb_value val = mrb_vm_special_get(mrb, syms[b]);
|
||||
regs[a] = val;
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_SETSV, BB) {
|
||||
mrb_vm_special_set(mrb, b, regs[a]);
|
||||
mrb_vm_special_set(mrb, syms[b], regs[a]);
|
||||
NEXT;
|
||||
}
|
||||
|
||||
@@ -1168,7 +1169,7 @@ RETRY_TRY_BLOCK:
|
||||
mrb_value *regs_a = regs + a;
|
||||
struct REnv *e = uvenv(mrb, c);
|
||||
|
||||
if (e && b < MRB_ENV_STACK_LEN(e)) {
|
||||
if (e && b < MRB_ENV_LEN(e)) {
|
||||
*regs_a = e->stack[b];
|
||||
}
|
||||
else {
|
||||
@@ -1183,7 +1184,7 @@ RETRY_TRY_BLOCK:
|
||||
if (e) {
|
||||
mrb_value *regs_a = regs + a;
|
||||
|
||||
if (b < MRB_ENV_STACK_LEN(e)) {
|
||||
if (b < MRB_ENV_LEN(e)) {
|
||||
e->stack[b] = *regs_a;
|
||||
mrb_write_barrier(mrb, (struct RBasic*)e);
|
||||
}
|
||||
@@ -1496,12 +1497,7 @@ RETRY_TRY_BLOCK:
|
||||
ci->target_class = MRB_PROC_TARGET_CLASS(m);
|
||||
ci->proc = m;
|
||||
if (MRB_PROC_ENV_P(m)) {
|
||||
struct REnv *e = MRB_PROC_ENV(m);
|
||||
|
||||
ci->mid = e->mid;
|
||||
if (!e->stack) {
|
||||
e->stack = mrb->c->stack;
|
||||
}
|
||||
ci->mid = MRB_PROC_ENV(m)->mid;
|
||||
}
|
||||
|
||||
/* prepare stack */
|
||||
@@ -1697,7 +1693,7 @@ RETRY_TRY_BLOCK:
|
||||
else {
|
||||
struct REnv *e = uvenv(mrb, lv-1);
|
||||
if (!e) goto L_NOSUPER;
|
||||
if (MRB_ENV_STACK_LEN(e) <= m1+r+m2+kd+1)
|
||||
if (MRB_ENV_LEN(e) <= m1+r+m2+kd+1)
|
||||
goto L_NOSUPER;
|
||||
stack = e->stack + 1;
|
||||
}
|
||||
@@ -2023,7 +2019,7 @@ RETRY_TRY_BLOCK:
|
||||
if (MRB_PROC_ENV_P(dst)) {
|
||||
struct REnv *e = MRB_PROC_ENV(dst);
|
||||
|
||||
if (!MRB_ENV_STACK_SHARED_P(e) || (e->cxt && e->cxt != mrb->c)) {
|
||||
if (!MRB_ENV_ONSTACK_P(e) || (e->cxt && e->cxt != mrb->c)) {
|
||||
localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
|
||||
goto L_RAISE;
|
||||
}
|
||||
@@ -2078,7 +2074,7 @@ RETRY_TRY_BLOCK:
|
||||
mrb_exc_set(mrb, exc);
|
||||
goto L_RAISE;
|
||||
}
|
||||
if (!MRB_PROC_ENV_P(proc) || !MRB_ENV_STACK_SHARED_P(MRB_PROC_ENV(proc))) {
|
||||
if (!MRB_PROC_ENV_P(proc) || !MRB_ENV_ONSTACK_P(MRB_PROC_ENV(proc))) {
|
||||
goto L_BREAK_ERROR;
|
||||
}
|
||||
else {
|
||||
@@ -2178,8 +2174,8 @@ RETRY_TRY_BLOCK:
|
||||
if (lv == 0) stack = regs + 1;
|
||||
else {
|
||||
struct REnv *e = uvenv(mrb, lv-1);
|
||||
if (!e || (!MRB_ENV_STACK_SHARED_P(e) && e->mid == 0) ||
|
||||
MRB_ENV_STACK_LEN(e) <= m1+r+m2+1) {
|
||||
if (!e || (!MRB_ENV_ONSTACK_P(e) && e->mid == 0) ||
|
||||
MRB_ENV_LEN(e) <= m1+r+m2+1) {
|
||||
localjump_error(mrb, LOCALJUMP_ERROR_YIELD);
|
||||
goto L_RAISE;
|
||||
}
|
||||
@@ -2824,7 +2820,7 @@ RETRY_TRY_BLOCK:
|
||||
MRB_END_EXC(&c_jmp);
|
||||
}
|
||||
|
||||
MRB_API mrb_value
|
||||
static mrb_value
|
||||
mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
|
||||
{
|
||||
if (mrb->c->ci->argc < 0) {
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ MRuby.each_target do
|
||||
# loader all gems
|
||||
self.libmruby_objs << objfile("#{build_dir}/mrbgems/gem_init")
|
||||
file objfile("#{build_dir}/mrbgems/gem_init") => ["#{build_dir}/mrbgems/gem_init.c", "#{build_dir}/LEGAL"]
|
||||
file "#{build_dir}/mrbgems/gem_init.c" => [MRUBY_CONFIG, __FILE__] do |t|
|
||||
file "#{build_dir}/mrbgems/gem_init.c" => [MRUBY_CONFIG, __FILE__, *Dir.glob("#{build_dir}/mrbgems/mruby-*/*.c")] do |t|
|
||||
mkdir_p "#{build_dir}/mrbgems"
|
||||
open(t.name, 'w') do |f|
|
||||
gem_func_gems = gems.select { |g| g.generate_functions }
|
||||
|
||||
+5
-4
@@ -56,7 +56,9 @@ def assertion_string(err, str, iso=nil, e=nil, bt=nil)
|
||||
msg = "#{err}#{str}"
|
||||
msg += " [#{iso}]" if iso && !iso.empty?
|
||||
msg += " => #{e}" if e && !e.to_s.empty?
|
||||
msg += " (#{GEMNAME == 'mruby-test' ? 'core' : "mrbgems: #{GEMNAME}"})"
|
||||
if Object.const_defined?(:GEMNAME)
|
||||
msg += " (#{GEMNAME == 'mruby-test' ? 'core' : "mrbgems: #{GEMNAME}"})"
|
||||
end
|
||||
if $mrbtest_assert
|
||||
$mrbtest_assert.each do |idx, assert_msg, diff|
|
||||
msg += "\n - Assertion[#{idx}]"
|
||||
@@ -64,7 +66,7 @@ def assertion_string(err, str, iso=nil, e=nil, bt=nil)
|
||||
msg += "\n#{diff}" if diff && !diff.empty?
|
||||
end
|
||||
end
|
||||
msg += "\nbacktrace:\n #{bt.join("\n ")}" if bt
|
||||
msg += "\nbacktrace:\n #{bt.join("\n ")}" if bt && !bt.empty?
|
||||
msg
|
||||
end
|
||||
|
||||
@@ -122,8 +124,7 @@ def assert(str = 'assert', iso = '')
|
||||
$mrbtest_child_noassert[-2] += 1
|
||||
t_print('?')
|
||||
rescue Exception => e
|
||||
bt = e.backtrace if $mrbtest_verbose
|
||||
$asserts.push(assertion_string("#{e.class}: ", str, iso, e, bt))
|
||||
$asserts.push(assertion_string("#{e.class}: ", str, iso, e, e.backtrace))
|
||||
$kill_test += 1
|
||||
t_print('X')
|
||||
ensure
|
||||
|
||||
+8
-26
@@ -1,16 +1,16 @@
|
||||
##
|
||||
# ensure Test
|
||||
|
||||
assert('ensure - context - yield') do
|
||||
class EnsureYieldBreak
|
||||
attr_reader :ensure_context
|
||||
def try
|
||||
yield
|
||||
ensure
|
||||
@ensure_context = self
|
||||
end
|
||||
class EnsureYieldBreak
|
||||
attr_reader :ensure_context
|
||||
def try
|
||||
yield
|
||||
ensure
|
||||
@ensure_context = self
|
||||
end
|
||||
end
|
||||
|
||||
assert('ensure - context - yield') do
|
||||
yielder = EnsureYieldBreak.new
|
||||
yielder.try do
|
||||
end
|
||||
@@ -18,15 +18,6 @@ assert('ensure - context - yield') do
|
||||
end
|
||||
|
||||
assert('ensure - context - yield and break') do
|
||||
class EnsureYieldBreak
|
||||
attr_reader :ensure_context
|
||||
def try
|
||||
yield
|
||||
ensure
|
||||
@ensure_context = self
|
||||
end
|
||||
end
|
||||
|
||||
yielder = EnsureYieldBreak.new
|
||||
yielder.try do
|
||||
break
|
||||
@@ -35,15 +26,6 @@ assert('ensure - context - yield and break') do
|
||||
end
|
||||
|
||||
assert('ensure - context - yield and return') do
|
||||
class EnsureYieldBreak
|
||||
attr_reader :ensure_context
|
||||
def try
|
||||
yield
|
||||
ensure
|
||||
@ensure_context = self
|
||||
end
|
||||
end
|
||||
|
||||
yielder = EnsureYieldBreak.new
|
||||
lambda do
|
||||
yielder.try do
|
||||
|
||||
+15
-24
@@ -29,7 +29,7 @@ assert('Kernel.block_given?', '15.3.1.2.2') do
|
||||
end
|
||||
end
|
||||
|
||||
# Kernel.eval is provided by the mruby-gem mrbgem. '15.3.1.2.3'
|
||||
# Kernel.eval is provided by the mruby-eval mrbgem. '15.3.1.2.3'
|
||||
|
||||
assert('Kernel.iterator?', '15.3.1.2.5') do
|
||||
assert_false Kernel.iterator?
|
||||
@@ -59,20 +59,11 @@ assert('Kernel.loop', '15.3.1.2.8') do
|
||||
assert_equal 100, i
|
||||
end
|
||||
|
||||
assert('Kernel.p', '15.3.1.2.9') do
|
||||
# TODO search for a way to test p to stdio
|
||||
assert_true true
|
||||
end
|
||||
# Kernel.p is provided by the mruby-print mrbgem. '15.3.1.2.9'
|
||||
|
||||
assert('Kernel.print', '15.3.1.2.10') do
|
||||
# TODO search for a way to test print to stdio
|
||||
assert_true true
|
||||
end
|
||||
# Kernel.print is provided by the mruby-print mrbgem. '15.3.1.2.10'
|
||||
|
||||
assert('Kernel.puts', '15.3.1.2.11') do
|
||||
# TODO search for a way to test puts to stdio
|
||||
assert_true true
|
||||
end
|
||||
# Kernel.puts is provided by the mruby-print mrbgem. '15.3.1.2.11'
|
||||
|
||||
assert('Kernel.raise', '15.3.1.2.12') do
|
||||
assert_raise RuntimeError do
|
||||
@@ -100,6 +91,10 @@ assert('Kernel#__send__', '15.3.1.3.4') do
|
||||
assert_true __send__(:respond_to?, :nil?)
|
||||
# test without argument and without block
|
||||
assert_equal String, __send__(:to_s).class
|
||||
|
||||
args = [:respond_to?, :nil?]
|
||||
assert_true __send__(*args)
|
||||
assert_equal [:respond_to?, :nil?], args
|
||||
end
|
||||
|
||||
assert('Kernel#block_given?', '15.3.1.3.6') do
|
||||
@@ -121,6 +116,13 @@ assert('Kernel#block_given?', '15.3.1.3.6') do
|
||||
"block"
|
||||
end
|
||||
end
|
||||
|
||||
def bg_try_in_block
|
||||
-> { block_given? }[]
|
||||
end
|
||||
|
||||
assert_false bg_try_in_block
|
||||
assert_true bg_try_in_block{}
|
||||
end
|
||||
|
||||
assert('Kernel#class', '15.3.1.3.7') do
|
||||
@@ -197,17 +199,6 @@ assert('Kernel#dup', '15.3.1.3.9') do
|
||||
a.set(2)
|
||||
c = a.dup
|
||||
|
||||
immutables = [ 1, :foo, true, false, nil ]
|
||||
error_count = 0
|
||||
immutables.each do |i|
|
||||
begin
|
||||
i.dup
|
||||
rescue TypeError
|
||||
error_count += 1
|
||||
end
|
||||
end
|
||||
|
||||
assert_equal immutables.size, error_count
|
||||
assert_equal 2, a.get
|
||||
assert_equal 1, b.get
|
||||
assert_equal 2, c.get
|
||||
|
||||
Reference in New Issue
Block a user