mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Compare commits
374 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 71e8dbcd97 | |||
| 791b374155 | |||
| c152f3a79a | |||
| 18b45c7ab5 | |||
| 561a3eac82 | |||
| 20b32531ea | |||
| 9d739cdad8 | |||
| f47609574a | |||
| ea0ceff7fb | |||
| 73c61e4a60 | |||
| e2982bdb57 | |||
| 0430f1e9b8 | |||
| d7a0d5687e | |||
| 83fc43e71d | |||
| 3a5d0a1840 | |||
| eb1820d75e | |||
| e30ec3da42 | |||
| bce8cee8f9 | |||
| d41d477e22 | |||
| deb5c47fc6 | |||
| 60f06e7a0f | |||
| 091e48159a | |||
| 04b38c2c47 | |||
| e096eeed1a | |||
| 5e2a7568e2 | |||
| 100ba913f2 | |||
| f210772465 | |||
| c117674cfe | |||
| 8538c79f3f | |||
| 169654ad9b | |||
| c188b9a1aa | |||
| 10ea05d3aa | |||
| d9f0c5a3a4 | |||
| 56a41b844e | |||
| 4ae3068b2a | |||
| 73a1eb03e8 | |||
| abae5a5ff5 | |||
| a2339a7fde | |||
| 72b51c4e92 | |||
| 655981c6ed | |||
| e4ed04ba8b | |||
| 52285161e7 | |||
| 1238fb2808 | |||
| f44a7bc5db | |||
| 7a1732d438 | |||
| 11106525c4 | |||
| 7ffe6a3a9a | |||
| e87bd7fcc1 | |||
| 695207be68 | |||
| d73e337442 | |||
| 4cd7f523fb | |||
| e2e2b5d35b | |||
| 5931aeb825 | |||
| afd5805224 | |||
| 2edfd96cbe | |||
| ef1cdbc0c7 | |||
| 67dbaf856f | |||
| 0fc6288ae2 | |||
| 085adaf408 | |||
| 783bc526e4 | |||
| 35fafe57fb | |||
| 10c40c4e87 | |||
| 0a306b81ed | |||
| d015d91c12 | |||
| 262d3715f5 | |||
| 8cb427b75c | |||
| a25a896caf | |||
| 65369ca1e6 | |||
| ff2464e879 | |||
| f7813268d6 | |||
| ebd9f29b38 | |||
| bf0f37833d | |||
| 12c124e1d4 | |||
| ac8d5c6ae6 | |||
| 1b189bc1a2 | |||
| 8ef1d1e104 | |||
| 74f46a05fd | |||
| 6b64447f0e | |||
| 04b769b5ca | |||
| 91ec6ea9cc | |||
| 0b52b33597 | |||
| 18f65c6652 | |||
| 84c308aedc | |||
| 0a45941337 | |||
| b5197c22f6 | |||
| 2f00046758 | |||
| 3a27a868a1 | |||
| 4e711fe0ef | |||
| 396a85de9a | |||
| 59902a94ab | |||
| 3814cbc539 | |||
| 5e5b4445ff | |||
| 97ad019707 | |||
| 8fbe5523cf | |||
| 470c1dc184 | |||
| 813dc8eae5 | |||
| 5cdd394c6d | |||
| 6509f52642 | |||
| acf3656e49 | |||
| 1beecb9670 | |||
| d7f7ea0d82 | |||
| 6bcee69c9c | |||
| 5731fbf17c | |||
| f835b86d10 | |||
| 50945bec68 | |||
| 5cc5a8a9c3 | |||
| c7ffb0cc55 | |||
| 35d073a986 | |||
| 2b75da7335 | |||
| da9365f98e | |||
| e55b3f0c55 | |||
| b4826fdbcf | |||
| 2f19fe1e36 | |||
| 19ddbdcf4b | |||
| bdd379bc8c | |||
| ddbbf3bd82 | |||
| 64d390b9e0 | |||
| d3f339062b | |||
| 1e3295d93e | |||
| 24a84a5a37 | |||
| 52d56fe443 | |||
| 576a104a77 | |||
| ad015f14a8 | |||
| 1ff94c5e00 | |||
| a3e72804cd | |||
| 99d9568aeb | |||
| 851f9f61a9 | |||
| e68eafd511 | |||
| 59f08ff148 | |||
| 8e0081923f | |||
| c837d386de | |||
| c3d2b903c6 | |||
| 83b21e8fd6 | |||
| e8458f9c22 | |||
| d2728fb0ae | |||
| 70956e9683 | |||
| 91c59ced99 | |||
| 46b8e80d9e | |||
| 7f3329e393 | |||
| 9c5d1cdaa9 | |||
| 493cc64902 | |||
| 273e7325c9 | |||
| ec68497a39 | |||
| 05c7aa2fe2 | |||
| f4b56a5e56 | |||
| 5924a23b8d | |||
| bbb5d28530 | |||
| df62559ddb | |||
| b925d6fee4 | |||
| bee56a8634 | |||
| 0011ee2267 | |||
| 70614ba82a | |||
| a668834b2d | |||
| e0d1f99744 | |||
| 224d0c8933 | |||
| e5905fe1dc | |||
| eb5fbfbb40 | |||
| e8ebeb151d | |||
| bdcd496bc2 | |||
| bec5dbc4e9 | |||
| 63a09ee336 | |||
| 9cee6ead4c | |||
| ca6dc4ec2d | |||
| 7c02e17e25 | |||
| 11bf789730 | |||
| 9537d9b75a | |||
| e82f49adf7 | |||
| ed8ec097a2 | |||
| 8a91c91a69 | |||
| 0c51a72bfe | |||
| ca526044d3 | |||
| 86ef7a912d | |||
| f4b01ed19e | |||
| 1fa9eaa2b5 | |||
| 77d08772a5 | |||
| 1726b61481 | |||
| d329d9af79 | |||
| d08276a052 | |||
| 82d03b32f2 | |||
| f9414456a5 | |||
| 1d426c50bf | |||
| 94d9f6cfc7 | |||
| ff4109735f | |||
| 18c43c2a5a | |||
| 65247613b9 | |||
| 31ebcb349e | |||
| c356e8f2ff | |||
| 96cbde7988 | |||
| bb712f9467 | |||
| 9fc58852e3 | |||
| fa19d7d3b5 | |||
| 36df859333 | |||
| 4417321d1c | |||
| b952ca30cd | |||
| ef840eced0 | |||
| 923b1c9e37 | |||
| 9e6ddbb2ad | |||
| d414e3f912 | |||
| 34bd571a65 | |||
| 1fcaa3995e | |||
| 781edbd446 | |||
| 4f2f2cfd20 | |||
| 93a7e5ec26 | |||
| 75466f9aab | |||
| 9ef2f551b7 | |||
| dbc9d12254 | |||
| ebca0cbf6a | |||
| c2d5a402ba | |||
| 6700c327ac | |||
| f98a05c738 | |||
| 6566099dbb | |||
| 6766fcb905 | |||
| 4704a7700a | |||
| 6df8096af2 | |||
| c6e3ae7e74 | |||
| 7e4810658e | |||
| 5522c94bb3 | |||
| 5c71681d82 | |||
| c3cc559dfc | |||
| f515669ce3 | |||
| 0bdd529430 | |||
| 3d2f848e64 | |||
| 88e86ee62e | |||
| 21d6bfb6dd | |||
| 37b84f40e0 | |||
| 5b10fdf684 | |||
| 147af9d669 | |||
| 3879b95a62 | |||
| 2b0d866da1 | |||
| 50c8e180d8 | |||
| dbc4768758 | |||
| c9a36e5d39 | |||
| 41e91a2ca8 | |||
| ef0cbc2981 | |||
| 567617ceb5 | |||
| aec8d0c58b | |||
| 81f5f5b8d4 | |||
| c36d9b7732 | |||
| 6eb969ff04 | |||
| 33d9ad6c44 | |||
| 85d048c1fb | |||
| a87b4b6bc3 | |||
| 333c364d5f | |||
| b5ad35d8ef | |||
| 0da5e0e190 | |||
| abfef2c38d | |||
| 7be940942c | |||
| 98906d5ac9 | |||
| fdfd67ff40 | |||
| 202c213fe1 | |||
| 4390aeb78d | |||
| 0723e10dcd | |||
| 757c0472d0 | |||
| ddae958405 | |||
| 7a3eebc1d5 | |||
| 30d1db4528 | |||
| 0fb280adbf | |||
| 1bc16676a1 | |||
| 683ecc09b5 | |||
| 789d350da9 | |||
| 08f74dd2be | |||
| 1b39c7d7da | |||
| e9d20a1590 | |||
| 6c72f8b378 | |||
| 6c25b5896a | |||
| 9387cd382e | |||
| 5fe406d59c | |||
| a6ef3a45d1 | |||
| dd96afd5a8 | |||
| e5478c2b40 | |||
| 8f120971b5 | |||
| 03719490eb | |||
| 6e1538ce3a | |||
| 279855985f | |||
| 586ff7a694 | |||
| fe201dc72f | |||
| 9c6349c769 | |||
| d4097716b3 | |||
| 99f5668243 | |||
| a309524d0b | |||
| baea6e284e | |||
| 061521ead5 | |||
| 16198dc985 | |||
| e42523fcf4 | |||
| ddfe65763e | |||
| dee661913f | |||
| 9a0f96e617 | |||
| 8b213c4fbf | |||
| 9cc6d39956 | |||
| 1969100fb4 | |||
| 953ebdf334 | |||
| 95f9de4877 | |||
| e08452585e | |||
| 90d77e71f5 | |||
| 118e13d85c | |||
| cda551ce25 | |||
| 82522a2e71 | |||
| 29964b3ba7 | |||
| 0d5fecf833 | |||
| 3fd5e1c250 | |||
| 52de3b7e10 | |||
| 40095bf755 | |||
| 46aa35a117 | |||
| 84e1b0045c | |||
| 1fdd961041 | |||
| 8c2ea232ea | |||
| 6c4b799b42 | |||
| 96855d31b5 | |||
| dd68681002 | |||
| cb8cd9388c | |||
| 9750513c25 | |||
| bf36ba9d10 | |||
| b1d910f6f4 | |||
| 76f7678db2 | |||
| 07d7aa6fdb | |||
| b88680ee9e | |||
| 3684a27209 | |||
| 5c2c77c71c | |||
| 4af6fe87c4 | |||
| 9405702e02 | |||
| 206eccb828 | |||
| b56f984c25 | |||
| 39fbc96eaf | |||
| 14f2e6db5a | |||
| a317b744f4 | |||
| 14de644234 | |||
| 6a3e5b87f8 | |||
| a9353c4f73 | |||
| 2ce0606f14 | |||
| c1a0a6193b | |||
| 1ae4f94844 | |||
| 7538ee8f5d | |||
| 68a0ecc782 | |||
| 0090e2cd01 | |||
| 7351f1127b | |||
| d908daa8b9 | |||
| b446b0d547 | |||
| a574034cb2 | |||
| 4ca61298ac | |||
| 7e18b1dadb | |||
| b8351d6191 | |||
| dd2950211c | |||
| 4aae7be949 | |||
| a33426da15 | |||
| 11f6251d23 | |||
| cde0b7edeb | |||
| aa06aff50d | |||
| 4e7399d4f4 | |||
| f3b79fcc23 | |||
| ca693dec30 | |||
| 9e315af2a5 | |||
| 90d4805f5b | |||
| 5bc391e170 | |||
| ed00879923 | |||
| dbafada7be | |||
| 1ec84a2874 | |||
| 226acdc540 | |||
| a55e3685a9 | |||
| c0024e1077 | |||
| 6396aac434 | |||
| 2a435caf79 | |||
| 8b65a296db | |||
| 468c6f1901 | |||
| d1909320d9 | |||
| a6848ca2cb | |||
| eb455c19fe | |||
| 8472fe0f13 | |||
| 9c37098c15 | |||
| 609a5c23b2 | |||
| 17d5aaa048 | |||
| 5bc00bf199 | |||
| 1e6442f54e | |||
| 1e36d7662c | |||
| 92b18d6a44 |
@@ -0,0 +1,3 @@
|
||||
[codespell]
|
||||
ignore-words = .github/linters/codespell.txt
|
||||
skip = ./build,./doc/api,./doc/capi
|
||||
@@ -19,8 +19,11 @@ build:
|
||||
- lib/**/*
|
||||
- minirake
|
||||
- tasks/**/*
|
||||
- .codespellrc
|
||||
- .dockerignore
|
||||
- .pre-commit-config.yaml
|
||||
- .prettierignore
|
||||
- .prettierrc
|
||||
- .travis.yml
|
||||
- .yardopts
|
||||
core:
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
ls:
|
||||
.c: snake_case
|
||||
.cpp: snake_case
|
||||
.h: snake_case
|
||||
.json: snake_case
|
||||
.rb: snake_case
|
||||
.yaml: regex:\.?[a-z]+(-[a-z]+)*
|
||||
.yml: regex:\.?[a-z]+(-[a-z]+)*
|
||||
|
||||
ignore:
|
||||
- build_config
|
||||
- mrbgems/mruby-compiler/core/y.tab.c
|
||||
@@ -22,7 +22,8 @@ jobs:
|
||||
- {os: ubuntu-22.04, cc: clang, cxx: clang++}
|
||||
- {os: macos-15, cc: clang, cxx: clang++}
|
||||
- {os: macos-14, cc: clang, cxx: clang++}
|
||||
- {os: windows-latest, cc: gcc, cxx: g++, altname: "mingw-gcc"}
|
||||
- {os: windows-2025, cc: gcc, cxx: g++, altname: "mingw-gcc"}
|
||||
- {os: windows-2022, cc: gcc, cxx: g++, altname: "mingw-gcc"}
|
||||
env:
|
||||
MRUBY_CONFIG: ci/gcc-clang
|
||||
CC: ${{ matrix.cc }}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: Coverage
|
||||
|
||||
on: [push, pull_request]
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
coverage:
|
||||
|
||||
@@ -25,3 +25,11 @@ jobs:
|
||||
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
- name: Run pre-commit
|
||||
run: pre-commit run --all-files
|
||||
ls-lint:
|
||||
name: Run ls-lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ls-lint/action@v2.3.1
|
||||
with:
|
||||
config: .github/linters/.ls-lint.yml
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
# Full git history is needed to get a proper list of changed files within `super-linter`
|
||||
fetch-depth: 0
|
||||
- name: Lint Code Base
|
||||
uses: super-linter/super-linter/slim@v7.3.0
|
||||
uses: super-linter/super-linter/slim@v7.4.0
|
||||
env:
|
||||
# VALIDATE_BASH_EXEC: true
|
||||
VALIDATE_DOCKERFILE_HADOLINT: true
|
||||
|
||||
@@ -37,4 +37,3 @@ node_modules
|
||||
perf.data*
|
||||
tags
|
||||
!Gemfile.lock
|
||||
y.tab.c
|
||||
|
||||
+24
-16
@@ -4,15 +4,19 @@ default_stages: [pre-commit, pre-push]
|
||||
default_language_version:
|
||||
# force all unspecified Python hooks to run python3
|
||||
python: python3
|
||||
node: 22.2.0
|
||||
# force all unspecified Node hooks to run Node.js v22.15.0 LTS
|
||||
node: 22.15.0
|
||||
minimum_pre_commit_version: "3.2.0"
|
||||
exclude: "^tools/lrama/"
|
||||
repos:
|
||||
- repo: meta
|
||||
hooks:
|
||||
- id: identity
|
||||
name: run identity check
|
||||
name: run identity
|
||||
description: check your identity
|
||||
- id: check-hooks-apply
|
||||
name: check hooks apply to the repository
|
||||
name: run check-hooks-apply
|
||||
description: check hooks apply to the repository
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: prettier
|
||||
@@ -21,17 +25,19 @@ repos:
|
||||
entry: prettier --write .
|
||||
files: \.(json|md|ya?ml)$
|
||||
language: node
|
||||
additional_dependencies: ["prettier@3.3.3"]
|
||||
additional_dependencies: ["prettier@3.5.3"]
|
||||
- repo: https://github.com/gitleaks/gitleaks
|
||||
rev: v8.24.0
|
||||
rev: v8.25.1
|
||||
hooks:
|
||||
- id: gitleaks
|
||||
name: detect hardcoded secrets
|
||||
name: run gitleaks
|
||||
description: detect hardcoded secrets with gitleaks
|
||||
- repo: https://github.com/shssoichiro/oxipng
|
||||
rev: v9.1.4
|
||||
rev: v9.1.5
|
||||
hooks:
|
||||
- id: oxipng
|
||||
name: run oxipng
|
||||
description: use lossless compression to optimize PNG files
|
||||
args: ["-o", "4", "--strip", "safe", "--alpha"]
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v5.0.0
|
||||
@@ -64,10 +70,12 @@ repos:
|
||||
rev: v1.5.5
|
||||
hooks:
|
||||
- id: forbid-tabs
|
||||
name: no-tabs checker
|
||||
name: run no-tabs checker
|
||||
description: check the codebase for tabs
|
||||
exclude: Makefile$
|
||||
- id: remove-tabs
|
||||
name: tabs remover
|
||||
name: run tabs remover
|
||||
description: find and convert tabs to spaces
|
||||
args: [--whitespaces-count, "2"]
|
||||
exclude: Makefile$
|
||||
- repo: https://github.com/rhysd/actionlint
|
||||
@@ -81,8 +89,7 @@ repos:
|
||||
hooks:
|
||||
- id: codespell
|
||||
name: run codespell
|
||||
description: Check spelling with codespell
|
||||
args: [--ignore-words=.github/linters/codespell.txt]
|
||||
description: check spelling with codespell
|
||||
- repo: https://github.com/jumanjihouse/pre-commit-hooks
|
||||
rev: 3.0.0
|
||||
hooks:
|
||||
@@ -95,16 +102,16 @@ repos:
|
||||
hooks:
|
||||
- id: markdownlint
|
||||
name: run markdownlint
|
||||
description: Checks the style of Markdown files
|
||||
description: checks the style of Markdown files
|
||||
args: [--config=.github/linters/.markdown-lint.yml]
|
||||
types: [markdown]
|
||||
files: \.md$
|
||||
- repo: https://github.com/tcort/markdown-link-check
|
||||
rev: v3.13.6
|
||||
rev: v3.13.7
|
||||
hooks:
|
||||
- id: markdown-link-check
|
||||
name: run markdown-link-check
|
||||
description: Checks hyperlinks in Markdown files
|
||||
description: checks hyperlinks in Markdown files
|
||||
args: [--config=.github/linters/mlc_config.json, -q]
|
||||
types: [markdown]
|
||||
files: \.md$
|
||||
@@ -113,12 +120,13 @@ repos:
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
name: run shellcheck
|
||||
description: check shell scripts with a static analysis tool
|
||||
- repo: https://github.com/adrienverge/yamllint
|
||||
rev: v1.35.1
|
||||
rev: v1.37.0
|
||||
hooks:
|
||||
- id: yamllint
|
||||
name: run yamllint
|
||||
description: Check YAML files with yamllint
|
||||
description: check YAML files with yamllint
|
||||
args: [--strict, -c=.github/linters/.yaml-lint.yml]
|
||||
types: [yaml]
|
||||
files: \.ya?ml$
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
build
|
||||
coverage
|
||||
doc/internal/opcode.md
|
||||
tools/lrama
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
# Authors of mruby (mruby developers)
|
||||
|
||||
## The List of Contributors sorted by number of commits (as of 2025-03-01 8ba2ed6)
|
||||
## The List of Contributors sorted by number of commits (as of 2025-06-03 a3e7280)
|
||||
|
||||
6083 Yukihiro "Matz" Matsumoto (@matz)*
|
||||
673 dearblue (@dearblue)*
|
||||
6258 Yukihiro "Matz" Matsumoto (@matz)*
|
||||
681 dearblue (@dearblue)*
|
||||
587 KOBAYASHI Shuji (@shuujii)
|
||||
353 Daniel Bovensiepen (@bovi)*
|
||||
345 Takeshi Watanabe (@take-cheeze)*
|
||||
333 Masaki Muranaka (@monaka)
|
||||
234 Jun Hiroe (@suzukaze)
|
||||
233 John Bampton (@jbampton)
|
||||
228 Tomoyuki Sahara (@tsahara)*
|
||||
220 Cremno (@cremno)*
|
||||
219 John Bampton (@jbampton)
|
||||
209 Yuki Kurihara (@ksss)+
|
||||
144 Yasuhiro Matsumoto (@mattn)*
|
||||
113 Carson McDonald (@carsonmcdonald)
|
||||
@@ -19,9 +19,9 @@
|
||||
83 Akira Yumiyama (@akiray03)*
|
||||
83 skandhas (@skandhas)
|
||||
80 Masamitsu MURASE (@masamitsu-murase)
|
||||
73 Hiroshi Mimaki (@mimaki)*
|
||||
71 Tatsuhiko Kubo (@cubicdaiya)*
|
||||
71 Yuichiro MASUI (@masuidrive)
|
||||
69 Hiroshi Mimaki (@mimaki)*
|
||||
62 Yuichiro Kaneko (@yui-knk)+
|
||||
59 Kurebayashi, Takahiro (@crimsonwoods)*
|
||||
56 h2so5 (@h2so5)
|
||||
@@ -49,6 +49,7 @@
|
||||
18 Corey Powell (@IceDragon200)
|
||||
18 Hidetaka Takano (@TJ-Hidetaka-Takano)
|
||||
18 Jon Maken (@jonforums)+
|
||||
18 leviongit (@leviongit)
|
||||
18 mirichi (@mirichi)
|
||||
17 Mitchell Blank Jr (@mitchblank)*
|
||||
16 bggd (@bggd)
|
||||
@@ -58,9 +59,9 @@
|
||||
14 Kazuki Tsujimoto (@k-tsj)
|
||||
14 Tadashi FUKUZAWA (@FUKUZAWA-Tadashi)+
|
||||
14 fn ⌃ ⌥ (@FnControlOption)
|
||||
14 leviongit (@leviongit)
|
||||
13 Jose Narvaez (@goyox86)
|
||||
13 Patrick Hogan (@pbhogan)
|
||||
13 google-labs-jules[bot] (@google-jules)
|
||||
12 Akira Kuroda (@akuroda)
|
||||
12 Kouki Ooyatsu (kaishuu0123)*
|
||||
12 NAKAMURA Usaku (@unak)*
|
||||
@@ -89,10 +90,12 @@
|
||||
7 Simon Génier (@simon-shopify)
|
||||
7 Terence Lee (@hone)
|
||||
7 roco (@rystyle)*
|
||||
7 vickash (@vickash)
|
||||
6 Akito Mochizuki (@ak-mochi)
|
||||
6 Beoran (@beoran)
|
||||
6 David Siaw (@davidsiaw)*
|
||||
6 Frederick John Milens III (@fjmilens3)
|
||||
6 HASUMI Hitoshi (@hasumikin)
|
||||
6 Hiro Asari (@BanzaiMan)
|
||||
6 INOUE Yasuyuki (@yasuyuki)
|
||||
6 Junji Sawada (@junjis0203)
|
||||
@@ -113,11 +116,9 @@
|
||||
5 Yurie Yamane (@yurie)+
|
||||
5 dreamedge (@dreamedge)
|
||||
5 nkshigeru (@nkshigeru)
|
||||
5 vickash (@vickash)
|
||||
5 xuejianqing (@joans321)
|
||||
4 Dante Catalfamo (@dantecatalfamo)
|
||||
4 Goro Kikuchi (@gorogit)
|
||||
4 HASUMI Hitoshi (@hasumikin)
|
||||
4 Herwin Weststrate (@herwinw)
|
||||
4 Horimoto Yasuhiro (@komainu8)
|
||||
4 Jon Moss (@maclover7)
|
||||
@@ -126,6 +127,7 @@
|
||||
4 Lanza (@LanzaSchneider)
|
||||
4 Li Yazhou (@flaneur2020)
|
||||
4 Marcus Stollsteimer (@stomar)
|
||||
4 Mark Delk (@jethrodaniel)
|
||||
4 NARUSE, Yui (@nurse)
|
||||
4 Ravil Bayramgalin (@brainopia)*+
|
||||
4 Satoshi Odawara (@SatoshiOdawara)
|
||||
@@ -139,11 +141,11 @@
|
||||
3 Daniel K. Sierpiński (@513ry)+
|
||||
3 David Turnbull (@AE9RB)
|
||||
3 Franck Verrot (@franckverrot)
|
||||
3 Hirohito Higashi (@HirohitoHigashi)
|
||||
3 J. Mutua (@katmutua)+
|
||||
3 Jan Berdajs (@mrbrdo)
|
||||
3 Jonas Minnberg (@sasq64)
|
||||
3 Joseph McCullough (@joequery)
|
||||
3 Mark Delk (@jethrodaniel)
|
||||
3 Mark McCurry (@fundamental)
|
||||
3 Nobuhiro Iwamatsu (@iwamatsu)
|
||||
3 Per Lundberg (@perlun)*
|
||||
@@ -171,7 +173,6 @@
|
||||
2 Francois Chagnon (@EiNSTeiN-)*
|
||||
2 Gilad Zohari (@gzohari)
|
||||
2 Go Saito (@govm)
|
||||
2 Hirohito Higashi (@HirohitoHigashi)
|
||||
2 Hiroyuki Iwatsuki (@iwadon)
|
||||
2 Huei-Horng Yo (@hiroshiyui)
|
||||
2 Jonas Kulla (@Ancurio)
|
||||
@@ -209,6 +210,7 @@
|
||||
1 Atsushi Morimoto (@mynz)
|
||||
1 Ben A Morgan (@BenMorganIO)
|
||||
1 Benoit Daloze (@eregon)
|
||||
1 Bradley Whited (@esotericpig)
|
||||
1 Colin MacKenzie IV (@sinisterchipmunk)
|
||||
1 Daehyub Kim (@lateau)
|
||||
1 Daniel Varga (@vargad)
|
||||
@@ -265,10 +267,12 @@
|
||||
1 Patrick Ellis (@pje)
|
||||
1 Patrick Pokatilo (@SHyx0rmZ)
|
||||
1 Pavel Evstigneev (@Paxa)+
|
||||
1 Paweł Świątkowski (@katafrakt)
|
||||
1 Pete Kinnecom (@petekinnecom)
|
||||
1 Prayag Verma (@pra85)
|
||||
1 Ranmocy (@ranmocy)
|
||||
1 Robert McNally (@wolfmcnally)
|
||||
1 Ryan Davis (@zenspider)
|
||||
1 Ryan Scott Lewis (@RyanScottLewis)
|
||||
1 Ryo Okubo (@syucream)
|
||||
1 SAkira a.k.a. Akira Suzuki (@sakisakira)
|
||||
@@ -303,6 +307,7 @@
|
||||
1 arton (@arton)
|
||||
1 duangsuse (@duangsuse)
|
||||
1 fl0l0u (@fl0l0u)
|
||||
1 hasse (@hasse09052)
|
||||
1 hhc0null (@hhc0null)
|
||||
1 iTitou (@titouanc)
|
||||
1 javier ramírez (@javier)
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ things in mind before submitting your pull request:
|
||||
- Create a branch which is dedicated to your change
|
||||
- Test your changes before creating a pull request (`rake test`)
|
||||
- If possible write a test case which confirms your change
|
||||
- Don't mix several features or bug-fixes in one pull request
|
||||
- Don't mix several features or bugfixes in one pull request
|
||||
- Create a meaningful commit message
|
||||
- Explain your change (i.e. with a link to the issue you are fixing)
|
||||
- Use mrbgem to provide non ISO features (classes, modules and methods) unless
|
||||
|
||||
@@ -48,7 +48,7 @@ PROJECT_NAME = mruby
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 3.3.0
|
||||
PROJECT_NUMBER = 3.4.0
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
coderay (1.1.3)
|
||||
rake (13.2.1)
|
||||
rake (13.3.0)
|
||||
yard (0.9.37)
|
||||
yard-coderay (0.1.0)
|
||||
coderay
|
||||
|
||||
@@ -1,189 +1,254 @@
|
||||
NEWS
|
||||
----
|
||||
|
||||
# User visible changes in `mruby3.3` from `mruby3.2`
|
||||
# User visible changes in `mruby3.4` from `mruby3.3`
|
||||
|
||||
"**_NOTE_**:" are changes to be aware of.
|
||||
|
||||
# The language
|
||||
|
||||
- aliases work properly with `super` ([2ad3f0e](https://github.com/mruby/mruby/commit/2ad3f0e))
|
||||
- `callee` method work differently with aliases in mruby ([f2dc76e](https://github.com/mruby/mruby/commit/f2dc76e))
|
||||
- define `Kernel#respond_to_missing?` method ([347586e](https://github.com/mruby/mruby/commit/347586e))
|
||||
- `_inspect` method (`inspect` with recursive check) is removed
|
||||
([e2bbf75](https://github.com/mruby/mruby/commit/e2bbf75), [5cb0c74](https://github.com/mruby/mruby/commit/5cb0c74), [113565a](https://github.com/mruby/mruby/commit/113565a),
|
||||
[0713f2a](https://github.com/mruby/mruby/commit/0713f2a), [6ae6b63](https://github.com/mruby/mruby/commit/6ae6b63), [fc9fffc](https://github.com/mruby/mruby/commit/fc9fffc))
|
||||
- `__printstr__` method is removed; use `print` instead
|
||||
([acecee0](https://github.com/mruby/mruby/commit/acecee0), [192e6e3](https://github.com/mruby/mruby/commit/192e6e3))
|
||||
- New method `String#bytesplice` ([5274647](https://github.com/mruby/mruby/commit/5274647), [a2e2e83](https://github.com/mruby/mruby/commit/a2e2e83))
|
||||
- Allow `return` in blocks to cross C boundaries ([#6125](https://github.com/mruby/mruby/pull/6125))
|
||||
|
||||
# Configuration
|
||||
|
||||
- mruby can be built using Docker now. Try `docker-compose build` for example. ([#5961](https://github.com/mruby/mruby/pull/5961))
|
||||
- New Platform: DJGPP (MS-DOS) ([#6022](https://github.com/mruby/mruby/pull/6022))
|
||||
- New Platform: Nintendo Wii ([#6086](https://github.com/mruby/mruby/pull/6086))
|
||||
- Improved Platform: Android ([#6013](https://github.com/mruby/mruby/pull/6013))
|
||||
- Improved Platform: Dreamcast ([#6130](https://github.com/mruby/mruby/pull/6130))
|
||||
- Allow tests to be disabled for specific gems; warn about disabled tests ([#6012](https://github.com/mruby/mruby/pull/6012))
|
||||
- Replace `MRB_NO_DIRECT_THREADING` with `MRB_USE_VM_SWITCH_DISPATCH` ([#5902](https://github.com/mruby/mruby/pull/5902))
|
||||
|
||||
# mruby memory API
|
||||
|
||||
- `mrb_default_allocf` can be overridden by the application ([34c5d96](https://github.com/mruby/mruby/commit/34c5d96))
|
||||
- `mrb_open_allocf` will be deprecated ([cfee5c2](https://github.com/mruby/mruby/commit/cfee5c2))
|
||||
- mruby now supports `private` and `protected` visibility ([b0db0bd](https://github.com/mruby/mruby/commit/b0db0bd))
|
||||
- Maximum length of inlined symbols reduced from 5 to 4 characters to provide space for visibility flags ([6442a01](https://github.com/mruby/mruby/commit/6442a01))
|
||||
- Many methods are made private according to CRuby visibility ([4a0e806](https://github.com/mruby/mruby/commit/4a0e806))
|
||||
- Generate OP_SSEND for `self.method` type calls ([111fe4b](https://github.com/mruby/mruby/commit/111fe4b))
|
||||
- `initialize` method will be always private ([eb8b412](https://github.com/mruby/mruby/commit/eb8b412))
|
||||
- Add new hooks `method_removed`, `method_undefined` ([9c74f6e](https://github.com/mruby/mruby/commit/9c74f6e))
|
||||
- Add new hooks `singleton_method_removed`, `singleton_method_undefined` ([0863c08](https://github.com/mruby/mruby/commit/0863c08))
|
||||
- Updated `OP_DEF` output from codedump ([3a3e877](https://github.com/mruby/mruby/commit/3a3e877))
|
||||
- Better handling of binary strings, e.g. String#b ([b0127f0](https://github.com/mruby/mruby/commit/b0127f0))
|
||||
- Hash `to_s` format has changed ([baeeb5e](https://github.com/mruby/mruby/commit/baeeb5e))
|
||||
- Some encoding related method such as `#force_encoding` ([e47b4ca](https://github.com/mruby/mruby/commit/e47b4ca)), `#b` ([b0127f0](https://github.com/mruby/mruby/commit/b0127f0))
|
||||
- Constant folding for `String#+` ([6687bdd](https://github.com/mruby/mruby/commit/6687bdd))
|
||||
- Remove Float bit-operation ([db8368f](https://github.com/mruby/mruby/commit/db8368f))
|
||||
- use SWAR technique for strlen performance ([cbb31e6](https://github.com/mruby/mruby/commit/cbb31e6))
|
||||
- use merge sort for `Array#sort` ([5bd63d6](https://github.com/mruby/mruby/commit/5bd63d6))
|
||||
|
||||
# Changes in C API
|
||||
|
||||
- add new error handling API functions ([8c8bbd9](https://github.com/mruby/mruby/commit/8c8bbd9))
|
||||
- Add `mrb_vm_ci_env_clear()` function with `MRB_API` ([#5945](https://github.com/mruby/mruby/pull/5945))
|
||||
- a new function `mrb_check_frozen_value()` ([ccdf75c](https://github.com/mruby/mruby/commit/ccdf75c))
|
||||
- avoid formatting in `mrb_bug()` ([82a48bd](https://github.com/mruby/mruby/commit/82a48bd)) <br>
|
||||
**_NOTE_**: If you are using it, you must give a simple string or replace it with a call to `mrb_raise()` series.
|
||||
- stop using `mrbc_` prefix for compiler context ([c5e3cbe](https://github.com/mruby/mruby/commit/c5e3cbe)) <br>
|
||||
The same names are provided as before, but we recommend replacing them.
|
||||
- Allow `Class#allocate` to be prohibited
|
||||
([#5979](https://github.com/mruby/mruby/pull/5979), [#6122](https://github.com/mruby/mruby/pull/6122), [#6123](https://github.com/mruby/mruby/pull/6123)) <br>
|
||||
To disable `#allocate`, use `MRB_UNDEF_ALLOCATOR()`.
|
||||
This is also automatically applied when the subclass is created, but to explicitly allow it, use `MRB_DEFINE_ALLOCATOR()`.
|
||||
- pool.c renamed to mempool.c (and mrb_pool to mrb_mempool) ([49525fa](https://github.com/mruby/mruby/commit/49525fa))
|
||||
- mrb_pool_value renamed to mrb_irep_pool to reduce confusion ([62ef5db](https://github.com/mruby/mruby/commit/62ef5db))
|
||||
- rename BOXNIX_SET_VALUE to BOXNO_SET_VALUE ([#6397](https://github.com/mruby/mruby/pull/6397))
|
||||
- `MRB_FROZEN_P()` is replaced by `mrb_frozen_p()` ([c11d18e](https://github.com/mruby/mruby/commit/c11d18e))
|
||||
- rename `color` to `gc_color` ([0e79f6b](https://github.com/mruby/mruby/commit/0e79f6b), [1e36d76](https://github.com/mruby/mruby/commit/1e36d76))
|
||||
- add `obj->frozen` instead of flags `MRB_SET_FROZEN_FLAG`/`MRB_UNSET_FROZEN_FLAG` ([8276143](https://github.com/mruby/mruby/commit/8276143))
|
||||
|
||||
# Build & Configuration
|
||||
|
||||
- New Build Target: `test:run:serial`, `test:run:serial:lib`, `test:run:serial:bin` ([#6423](https://github.com/mruby/mruby/pull/6423))
|
||||
- New Platform: PlayStation Portable ([#6022](https://github.com/mruby/mruby/pull/6465))
|
||||
- New Platform: emscripten ([#6487](https://github.com/mruby/mruby/pull/6487))
|
||||
- New Config: no-float (with MRB_NO_FLOAT) ([32200f1](https://github.com/mruby/mruby/commit/32200f1))
|
||||
|
||||
# Changes in mrbgems
|
||||
|
||||
- **default.gembox**: Add mruby debugger mrdb (`mruby-bin-debugger`) ([#5966](https://github.com/mruby/mruby/pull/5966))
|
||||
- **mruby-bin-config**: new options `--cxx`, `--cxxflags`, `--as`, `--asflags`, `--objc`, `--objcflags` ([#6054](https://github.com/mruby/mruby/pull/6054))
|
||||
- **mruby-binding**: renamed from `mruby-binding-core` of mruby3.2 ([11af5db](https://github.com/mruby/mruby/commit/11af5db)) <br>
|
||||
**_NOTE_**: If using `mruby-binding-core` of mruby 3.2, replace it with `mruby-binding`.
|
||||
- **mruby-binding**: implemented `Binding#initialize_copy` method ([#5517](https://github.com/mruby/mruby/pull/5517))
|
||||
- **mruby-binding**: `Kernel#binding` responds only to calls from Ruby ([#5981](https://github.com/mruby/mruby/pull/5981))
|
||||
- **mruby-compar-ext**: Comparable#clamp to accept nil as arguments ([836bebc](https://github.com/mruby/mruby/commit/836bebc))
|
||||
- **mruby-compiler**: add print name for identifier tokens ([d7b2e3a](https://github.com/mruby/mruby/commit/d7b2e3a))
|
||||
- **mruby-data**: allow empty Data ([927a9df](https://github.com/mruby/mruby/commit/927a9df))
|
||||
- **mruby-enumerator**: remove internal attribute methods `obj`, `args`, `kwd`, `meth`, `fib`. ([735fa24](https://github.com/mruby/mruby/commit/735fa24))
|
||||
- **mruby-enumerator**: add Enumerator#size ([861f8bd](https://github.com/mruby/mruby/commit/861f8bd))
|
||||
- **mruby-eval**: merged `mruby-binding` of mruby3.2 ([501b22a](https://github.com/mruby/mruby/commit/501b22a), [#5989](https://github.com/mruby/mruby/pull/5989)) <br>
|
||||
**_NOTE_**: If using `mruby-binding` of mruby 3.2, replace it with `mruby-eval`.
|
||||
- **mruby-fiber**: Add a new `mrb_fiber_new()` with `MRB_API` ([#6097](https://github.com/mruby/mruby/pull/6097))
|
||||
- **mruby-fiber**: Allows calling `Fiber#resume` from C ([#6106](https://github.com/mruby/mruby/pull/6106))
|
||||
- **mruby-fiber**: `Fiber#to_s` format changed ([#6105](https://github.com/mruby/mruby/pull/6105))
|
||||
- **mruby-io**: add File#atime and File#ctime ([321cfe9](https://github.com/mruby/mruby/commit/321cfe9))
|
||||
- **mruby-io**: Add "x" mode option for `IO.open` ([#6081](https://github.com/mruby/mruby/pull/6081))
|
||||
- **mruby-io**: File.new should not take blocks ([53de964](https://github.com/mruby/mruby/commit/53de964))
|
||||
- **mruby-method**: `Method#to_s` format changed ([f5bc82f](https://github.com/mruby/mruby/commit/f5bc82f), [02f189c](https://github.com/mruby/mruby/commit/02f189c))
|
||||
- **mruby-numeric-ext**: `int.pow(n,m)` to take bigint as exponential ([d482eab](https://github.com/mruby/mruby/commit/d482eab))
|
||||
- **mruby-pack**: support new directives `j`, `J`, `b`, `B`, `#`
|
||||
([2a1e3a5](https://github.com/mruby/mruby/commit/2a1e3a5), [e7021f1](https://github.com/mruby/mruby/commit/e7021f1), [e17f325](https://github.com/mruby/mruby/commit/e17f325))
|
||||
- **mruby-range-ext**: new method `Range#overlap?` ([384d0e2](https://github.com/mruby/mruby/commit/384d0e2))
|
||||
- **mruby-string-ext**: Add `String#valid_encoding?` method ([eabe2d9](https://github.com/mruby/mruby/commit/eabe2d9))
|
||||
- **mruby-struct**: allow empty Struct when a name is not given ([c212ede](https://github.com/mruby/mruby/commit/c212ede))
|
||||
- **mruby-time**: should allow year before 1900 ([e5de08b](https://github.com/mruby/mruby/commit/e5de08b))
|
||||
- **mruby-time**: support bigint to time_t if necessary ([7096d27](https://github.com/mruby/mruby/commit/7096d27))
|
||||
- **mruby-time**: need to handle negative time_t ([b064d7e](https://github.com/mruby/mruby/commit/b064d7e))
|
||||
- **mruby-print**: removed; if you do not use `mruby-io`, mruby use `#print` etc. in the core ([8c8bbd9](https://github.com/mruby/mruby/commit/8c8bbd9))
|
||||
- **mruby-enum-lazy**: Add Enumerable::Lazy#grep_v to mruby-enum-lazy ([#6171](https://github.com/mruby/mruby/pull/6171))
|
||||
- **mruby-io**: Add `level` argument to `File.dirname` ([#6463](https://github.com/mruby/mruby/pull/6463))
|
||||
- **mruby-io**: File.absolute_path? ([#6482](https://github.com/mruby/mruby/pull/6482))
|
||||
- **mruby-io**: File.absolute_path ([96113a2](https://github.com/mruby/mruby/commit/96113a2))
|
||||
- **mruby-toplevel-ext**: top-level public/private/protected moved to the core ([2a876d2](https://github.com/mruby/mruby/commit/2a876d2))
|
||||
- **mruby-metaprog**: method list methods now works according to the visibility ([9229da1](https://github.com/mruby/mruby/commit/9229da1))
|
||||
- **mruby-metaprog**: `public_instance_methods`, `private_instance_methods`, `protected_instance_methods` ([9e3e7b2](https://github.com/mruby/mruby/commit/9e3e7b2))
|
||||
- **mruby-encoding**: MRB_UTF8_STRING turned on automatically with this gem ([74bdae9](https://github.com/mruby/mruby/commit/74bdae9))
|
||||
|
||||
# Changes in build system
|
||||
# Fixed GitHub Issues
|
||||
|
||||
- Extended `rake install` task ([#5928](https://github.com/mruby/mruby/pull/5928)) <br>
|
||||
**_NOTE_**: Due to this impact, executable files in the `mruby/bin/` directory by default are now symbolic links (batch files on Windows).
|
||||
If previously relied on those executables, should be replaced with direct references to the entity created under the build directory (e.g. `mruby/build/host/bin/`).
|
||||
- Encode and decode escape characters for presym ([#6011](https://github.com/mruby/mruby/pull/6011))
|
||||
- Rakefile: remove default build target directories in `deep_clean` ([#6032](https://github.com/mruby/mruby/pull/6032), [1e38569](https://github.com/mruby/mruby/commit/1e38569))
|
||||
- [#6173](https://github.com/mruby/mruby/issues/6173) Fails to build with tcc(Tiny C Compiler)
|
||||
- [#6156](https://github.com/mruby/mruby/issues/6156) '/LIBPATH' issue
|
||||
- [#6183](https://github.com/mruby/mruby/issues/6183) ".e".to_f returns NAN
|
||||
- [#6182](https://github.com/mruby/mruby/issues/6182) mrb_read_float() converts "0.3" with a small error compared to strtod()
|
||||
- [#6210](https://github.com/mruby/mruby/issues/6210) Unary minus seems broken
|
||||
- [#6255](https://github.com/mruby/mruby/issues/6255) Wrong number of characters in broken UTF-8 string
|
||||
- [#4038](https://github.com/mruby/mruby/issues/4038) Heap buffer overflow in OP_ENTER
|
||||
- [#6262](https://github.com/mruby/mruby/issues/6262) Unable to define == for objects when using Array#delete
|
||||
- [#6267](https://github.com/mruby/mruby/issues/6267) When MRB_UTF8_STRING is enabled, giving byte characters for String#index and String#split gives wrong results
|
||||
- [#6277](https://github.com/mruby/mruby/issues/6277) MSVC: can't use malloc() in string.c with WIN32_LEAN_AND_MEAN
|
||||
- [#6240](https://github.com/mruby/mruby/issues/6240) Differentiate between lib and lib64 in the build settings.
|
||||
- [#6304](https://github.com/mruby/mruby/issues/6304) Calling method_missing with only Kwargs passes arguments incorrectly
|
||||
- [#6317](https://github.com/mruby/mruby/issues/6317) mrb_gc_register() may cause GC and collect the object being protected
|
||||
- [#6307](https://github.com/mruby/mruby/issues/6307) Planned change patch for mrb_vm_exec()
|
||||
- [#6298](https://github.com/mruby/mruby/issues/6298) foo :bar {} is legal in mruby?
|
||||
- [#6326](https://github.com/mruby/mruby/issues/6326) Detect “Use-after-free” with address sanitizer
|
||||
- [#5358](https://github.com/mruby/mruby/issues/5358) static warning from getpwnam
|
||||
- [#6339](https://github.com/mruby/mruby/issues/6339) mrb_ary_delete() may refer to an invalid address (use-after-free)
|
||||
- [#6346](https://github.com/mruby/mruby/issues/6346) Block kwargs are passed as last positional arg when using yield
|
||||
- [#6365](https://github.com/mruby/mruby/issues/6365) powl() not available when compiling for Dreamcast
|
||||
- [#6369](https://github.com/mruby/mruby/issues/6369) 100x Performance Regression from 3.1
|
||||
- [#6270](https://github.com/mruby/mruby/issues/6270) NODE_ZSUPER from deeply nested blocks will result in a truncated digits for block index in OP_ARGARY
|
||||
- [#6297](https://github.com/mruby/mruby/issues/6297) Assigning to a block variable changes the actual block (thus affecting block_given? and yield)
|
||||
- [#6389](https://github.com/mruby/mruby/issues/6389) instance_exec named block args don't work properly
|
||||
- [#6388](https://github.com/mruby/mruby/issues/6388) Recent commit broke my windows build
|
||||
- [#6411](https://github.com/mruby/mruby/issues/6411) Wrong function unwinding when using return in a block
|
||||
- [#6439](https://github.com/mruby/mruby/issues/6439) OP_JMPUW does not call the ensure block when it jumps to the beginning of the begin block
|
||||
- [#6441](https://github.com/mruby/mruby/issues/6441) break inside while loop will execute the ensure block outside of the while loop
|
||||
- [#6453](https://github.com/mruby/mruby/issues/6453) Bigint: incorrect behavior of ^ operator
|
||||
- [#6452](https://github.com/mruby/mruby/issues/6452) Bigint: weird mod behavior
|
||||
- [#6451](https://github.com/mruby/mruby/issues/6451) Bigint: incorrect division behavior
|
||||
- [#6456](https://github.com/mruby/mruby/issues/6456) bigint: bug with division of a small number by a bigint
|
||||
- [#6466](https://github.com/mruby/mruby/issues/6466) mruby-bin-mruby using Kernel#p and Kernel#print in bintest fails test
|
||||
- [#6467](https://github.com/mruby/mruby/issues/6467) Heap-Use-After-Free due to Recursive group_by Calls
|
||||
- [#6471](https://github.com/mruby/mruby/issues/6471) Discrepancy in codegen for binary operations between master branch and 3.3.0
|
||||
- [#6477](https://github.com/mruby/mruby/issues/6477) heap-buffer-overflow in mrb_vm_exec
|
||||
- [#6485](https://github.com/mruby/mruby/issues/6485) Hash#rehash does not check if the hash is frozen
|
||||
- [#6483](https://github.com/mruby/mruby/issues/6483) Hash#default_proc= accepts arbitrary objects that are not callable
|
||||
- [#6491](https://github.com/mruby/mruby/issues/6491) Destroy existing string literals when composing string literals
|
||||
|
||||
# Other breaking changes
|
||||
# Merged Pull Requests (User Visible Ones)
|
||||
|
||||
- `mrb_f_raise()` is now an internal function
|
||||
([#5923](https://github.com/mruby/mruby/pull/5923), [#6070](https://github.com/mruby/mruby/pull/6070))
|
||||
- `mrb_make_exception()` is now an internal function with different parameters
|
||||
([431f83e](https://github.com/mruby/mruby/commit/431f83e), [78137f3](https://github.com/mruby/mruby/commit/78137f3))
|
||||
- The `File#path` method no longer uses the `#to_path` method for implicit conversion
|
||||
([d86c4a7](https://github.com/mruby/mruby/commit/d86c4a7))
|
||||
- stop mrb isolation for each test file ([a20fbe5](https://github.com/mruby/mruby/commit/a20fbe5))
|
||||
- RBreak remembers the CI location ([#6103](https://github.com/mruby/mruby/pull/6103))
|
||||
|
||||
# Bugs Fixed
|
||||
|
||||
- [#5724](https://github.com/mruby/mruby/issues/5724) Rational#\*\* is missing
|
||||
- [#5725](https://github.com/mruby/mruby/issues/5725) weird const_missing exceptions in mrblib code
|
||||
- [#5789](https://github.com/mruby/mruby/issues/5789) No memory release of backtrace information due to stack error
|
||||
- [#5932](https://github.com/mruby/mruby/issues/5932) How to create a block using the C API? mrb_yield keeps crashing!
|
||||
- [#5943](https://github.com/mruby/mruby/issues/5943) TCPSocket#write is failed
|
||||
- [#5944](https://github.com/mruby/mruby/issues/5944) Behavior of calling method with a hash variable
|
||||
- [#5946](https://github.com/mruby/mruby/pull/5946) Don't switch constant search path from modules to Object
|
||||
- [#5949](https://github.com/mruby/mruby/issues/5949) Caller appears to report wrong line when block passed and brackets omitted
|
||||
- [0906cd7](https://github.com/mruby/mruby/commit/0906cd7) numeric.c: fix rounding function issues with big numbers
|
||||
- [#5974](https://github.com/mruby/mruby/issues/5974) Invalid escape sequences in gem_init.c on windows
|
||||
- [#5975](https://github.com/mruby/mruby/issues/5975) Equals comparison fails on extreme ends of 64-bit integers
|
||||
- [#5985](https://github.com/mruby/mruby/issues/5985) Sign extension with OP_LOADI32 in get_int_operand()
|
||||
- [#5986](https://github.com/mruby/mruby/issues/5986) Fix bugs in String#bytesplice
|
||||
- [#5987](https://github.com/mruby/mruby/issues/5987) ~(-1 << 64) is incorrect
|
||||
- [#5991](https://github.com/mruby/mruby/issues/5991) 'gets' method not working in mruby-3.2.0
|
||||
- [#5994](https://github.com/mruby/mruby/pull/5994) fix typo in mrbgems/mruby-io/src/io.c
|
||||
- [#5995](https://github.com/mruby/mruby/issues/5995) One seemingly unnecessary parameter is passed in the block parameters
|
||||
- [#6008](https://github.com/mruby/mruby/pull/6008) Make "bintest" independent of directory
|
||||
- [b47c8b7](https://github.com/mruby/mruby/commit/b47c8b7) gc.c (clear_all_old): fix a generational GC bug
|
||||
- [#6029](https://github.com/mruby/mruby/issues/6029) mruby build fails under mrbgems directory
|
||||
- [a264965](https://github.com/mruby/mruby/commit/a264965) mruby-os-memsize/memsize.c: fix irep size calculation
|
||||
- [3310e10](https://github.com/mruby/mruby/commit/3310e10) mruby-test/mrbgem.rake: fix mrb_state handling bug
|
||||
- [#6041](https://github.com/mruby/mruby/issues/6041) GC Performance may have degraded
|
||||
- [#6044](https://github.com/mruby/mruby/issues/6044) Generated presym/table.h contains invalid characters
|
||||
- [#6051](https://github.com/mruby/mruby/issues/6051) Null pointer dereference in mrb_addrinfo_unix_path
|
||||
- [#6052](https://github.com/mruby/mruby/issues/6052) Null pointer dereference while handling the Proc class
|
||||
- [#6055](https://github.com/mruby/mruby/pull/6055) Fix libmruby name for VisualC++
|
||||
- [#6060](https://github.com/mruby/mruby/issues/6060) SEGFAULT Issue Related to Fiber Usage in ngx_mruby Development
|
||||
- [#6061](https://github.com/mruby/mruby/issues/6061) Performance issue in String#codepoints
|
||||
- [#6064](https://github.com/mruby/mruby/issues/6064) MRUBY_PACKAGE_DIR does not always have a value.
|
||||
- [#6065](https://github.com/mruby/mruby/issues/6065) Null pointer dereference while handling the Proc class
|
||||
- [#6066](https://github.com/mruby/mruby/issues/6066) Null pointer dereference involving Struct.new()
|
||||
- [#6067](https://github.com/mruby/mruby/issues/6067) Null pointer dereference in mrb_string_value_cstr
|
||||
- [#6068](https://github.com/mruby/mruby/issues/6068) Stack overflow in mrb_vm_exec
|
||||
- [#6076](https://github.com/mruby/mruby/pull/6076) Fixed unwinding block that could point to invalid PC
|
||||
- [#6084](https://github.com/mruby/mruby/issues/6084) Incorrect symbolic sinks in binary built on Linux
|
||||
- [#6087](https://github.com/mruby/mruby/issues/6087) 'Remote branch HEAD not found in upstream origin' error on build
|
||||
- [#6089](https://github.com/mruby/mruby/issues/6089) binding.eval() handles def expressions differently from CRuby
|
||||
- [#6098](https://github.com/mruby/mruby/issues/6098) Fails to call superclass of wrapped method
|
||||
- [#6099](https://github.com/mruby/mruby/issues/6099) `ensure` section is not executed if the function exits via a return in a proc
|
||||
- [#6108](https://github.com/mruby/mruby/issues/6108) VM crashes with break
|
||||
- [#6118](https://github.com/mruby/mruby/pull/6118) Fixed IO#read with buf
|
||||
- [#6120](https://github.com/mruby/mruby/pull/6120) Set EBADF if check_file_descriptor() fails
|
||||
- [#6126](https://github.com/mruby/mruby/pull/6126) Fixed return value of `OP_RETURN_BLK` called directly under C function
|
||||
- [#6134](https://github.com/mruby/mruby/issues/6134) String#unpack1 returns an array instead of a single string
|
||||
- [#6136](https://github.com/mruby/mruby/pull/6136) Fixed when combined `mrb_fiber_resume()` and `Fiber#transfer`
|
||||
|
||||
# Pull Requests (User Visible Ones)
|
||||
|
||||
- [#5517](https://github.com/mruby/mruby/pull/5517) Fixed local variables not separated between copied binding objects
|
||||
- [#5902](https://github.com/mruby/mruby/pull/5902) Replace `MRB_NO_DIRECT_THREADING` with `MRB_USE_VM_SWITCH_DISPATCH`
|
||||
- [#5923](https://github.com/mruby/mruby/pull/5923) Demotion `mrb_f_raise()` from `MRB_API`
|
||||
- [#5928](https://github.com/mruby/mruby/pull/5928) Improved `rake install`
|
||||
- [#5945](https://github.com/mruby/mruby/pull/5945) Avoid exposure for `REnv` objects
|
||||
- [#5946](https://github.com/mruby/mruby/pull/5946) Don't switch constant search path from modules to Object
|
||||
- [#5966](https://github.com/mruby/mruby/pull/5966) Update default.gembox add mruby debugger mrdb
|
||||
- [#5979](https://github.com/mruby/mruby/pull/5979) Allow Class#allocate to be prohibited
|
||||
- [#5981](https://github.com/mruby/mruby/pull/5981) `Kernel#binding` responds only to calls from Ruby
|
||||
- [#5989](https://github.com/mruby/mruby/pull/5989) Integrate mruby-binding-eval into mruby-eval
|
||||
- [#5961](https://github.com/mruby/mruby/pull/5961) Add Docker to build and run all mruby tests. Run pre-commit and generate YARD docs with Docker
|
||||
- [#5994](https://github.com/mruby/mruby/pull/5994) fix typo in mrbgems/mruby-io/src/io.c
|
||||
- [#6008](https://github.com/mruby/mruby/pull/6008) Make "bintest" independent of directory
|
||||
- [#6009](https://github.com/mruby/mruby/pull/6009) Avoid adding <MRUBY_ROOT>/bintest which does not exist
|
||||
- [#6011](https://github.com/mruby/mruby/pull/6011) Encode and decode escape characters for presym
|
||||
- [#6012](https://github.com/mruby/mruby/pull/6012) Allow tests to be disabled for specific gems; warn about disabled tests
|
||||
- [#6013](https://github.com/mruby/mruby/pull/6013) Fix Android toolchain
|
||||
- [#6022](https://github.com/mruby/mruby/pull/6022) Build configuration for MS-DOS and DJGPP
|
||||
- [#6032](https://github.com/mruby/mruby/pull/6032) Rake: update task clean to remove bin and build folders
|
||||
- [#6045](https://github.com/mruby/mruby/pull/6045) Fixes escape sequence bug and enhancements in Presym scanning
|
||||
- [#6054](https://github.com/mruby/mruby/pull/6054) Extends `bin/mruby-config`
|
||||
- [#6055](https://github.com/mruby/mruby/pull/6055) Fix libmruby name for VisualC++
|
||||
- [#6070](https://github.com/mruby/mruby/pull/6070) Demotion mrb_f_raise() in kernel.c from MRB_API too
|
||||
- [#6076](https://github.com/mruby/mruby/pull/6076) Fixed unwinding block that could point to invalid PC
|
||||
- [#6081](https://github.com/mruby/mruby/pull/6081) Add "x" mode option for IO.open
|
||||
- [#6086](https://github.com/mruby/mruby/pull/6086) Add build config for Nintendo Wii
|
||||
- [#6097](https://github.com/mruby/mruby/pull/6097) Add a new mrb_fiber_new() with MRB_API
|
||||
- [#6103](https://github.com/mruby/mruby/pull/6103) RBreak remembers the CI location
|
||||
- [#6105](https://github.com/mruby/mruby/pull/6105) Implement `Fiber#to_s` method
|
||||
- [#6106](https://github.com/mruby/mruby/pull/6106) Ease fiber limitations
|
||||
- [#6118](https://github.com/mruby/mruby/pull/6118) Fixed IO#read with buf
|
||||
- [#6120](https://github.com/mruby/mruby/pull/6120) Set EBADF if check_file_descriptor() fails
|
||||
- [#6122](https://github.com/mruby/mruby/pull/6122) Prohibit `Class#allocate` in a different way
|
||||
- [#6123](https://github.com/mruby/mruby/pull/6123) Inherit `MRB_FL_UNDEF_ALLOCATE` in subclasses
|
||||
- [#6125](https://github.com/mruby/mruby/pull/6125) Allow `OP_RETURN_BLK` to cross C boundaries
|
||||
- [#6126](https://github.com/mruby/mruby/pull/6126) Fixed return value of `OP_RETURN_BLK` called directly under C function
|
||||
- [#6130](https://github.com/mruby/mruby/pull/6130) `dreamcast_shelf build config`: complete overhaul
|
||||
- [#6136](https://github.com/mruby/mruby/pull/6136) Fixed when combined `mrb_fiber_resume()` and `Fiber#transfer`
|
||||
- [#6171](https://github.com/mruby/mruby/pull/6171) Add Enumerable::Lazy#grep_v to mruby-enum-lazy
|
||||
- [#6174](https://github.com/mruby/mruby/pull/6174) Fix MRUBY_PACKAGE_DIR in mruby-config.bat
|
||||
- [#6175](https://github.com/mruby/mruby/pull/6175) Corrected strange conditional in mrb_vm_run()
|
||||
- [#6176](https://github.com/mruby/mruby/pull/6176) Stop assuming alias proc in CI_PROC_SET()
|
||||
- [#6177](https://github.com/mruby/mruby/pull/6177) gha: add macOS 14 to the build
|
||||
- [#6184](https://github.com/mruby/mruby/pull/6184) Remove the L_STOP label
|
||||
- [#6185](https://github.com/mruby/mruby/pull/6185) Added mrb_callinfo::u.keep_context for clarity
|
||||
- [#6186](https://github.com/mruby/mruby/pull/6186) Omit NULL check of e->cxt in OP_RETURN_BLK
|
||||
- [#6191](https://github.com/mruby/mruby/pull/6191) Speed up symbol equality comparison
|
||||
- [#6192](https://github.com/mruby/mruby/pull/6192) Fix `OP_STOP` with exception
|
||||
- [#6193](https://github.com/mruby/mruby/pull/6193) Fix wrong assertion in `OP_SENDB`.
|
||||
- [#6194](https://github.com/mruby/mruby/pull/6194) Simplify the calculation of the number of closures in `MRB_TT_FIBER`
|
||||
- [#6197](https://github.com/mruby/mruby/pull/6197) Fix int_xor to call flo_xor.
|
||||
- [#6201](https://github.com/mruby/mruby/pull/6201) tasks/doc.rake: standardize the `rake doc` error messages
|
||||
- [#6202](https://github.com/mruby/mruby/pull/6202) Remove the `.yardoc` folder with `rake doc:clean:api`
|
||||
- [#6204](https://github.com/mruby/mruby/pull/6204) Clean up the `.editorconfig` file
|
||||
- [#6209](https://github.com/mruby/mruby/pull/6209) Minor `.gitignore` clean up
|
||||
- [#6211](https://github.com/mruby/mruby/pull/6211) Minor `.gitignore` clean up; order entries
|
||||
- [#6216](https://github.com/mruby/mruby/pull/6216) Shared empty `iv_tbl` of module
|
||||
- [#6217](https://github.com/mruby/mruby/pull/6217) Strict declaration for `mrb_istruct_size()`
|
||||
- [#6219](https://github.com/mruby/mruby/pull/6219) Avoid assigning a fixed value in the loop
|
||||
- [#6220](https://github.com/mruby/mruby/pull/6220) Reorganize `mrb_cache_entry` and `mrb_method_t` types
|
||||
- [#6221](https://github.com/mruby/mruby/pull/6221) Arranging `each_backtrace()`
|
||||
- [#6222](https://github.com/mruby/mruby/pull/6222) Need to synchronize `dbg->regs` after VM call in `mrdb`
|
||||
- [#6224](https://github.com/mruby/mruby/pull/6224) `mrb_env_unshare()` to break the link to fiber
|
||||
- [#6225](https://github.com/mruby/mruby/pull/6225) Revert "Adjust environment when `mrb_exec_irep` happened."
|
||||
- [#6227](https://github.com/mruby/mruby/pull/6227) fix: `Array#shuffle(!)` result distribution
|
||||
- [#6228](https://github.com/mruby/mruby/pull/6228) Revert "`env` referred from top-level callinfo should not be unshared; fix #4019"
|
||||
- [#6230](https://github.com/mruby/mruby/pull/6230) Fix status of fiber after switched by exception raised
|
||||
- [#6231](https://github.com/mruby/mruby/pull/6231) Add a way to let other gems handle closing of fds in mruby-io
|
||||
- [#6232](https://github.com/mruby/mruby/pull/6232) Fold the code for freeing `env`
|
||||
- [#6233](https://github.com/mruby/mruby/pull/6233) Free stack memory at end of fiber
|
||||
- [#6235](https://github.com/mruby/mruby/pull/6235) fix `Array#delete` always firing the block when deleting `nil`
|
||||
- [#6236](https://github.com/mruby/mruby/pull/6236) unify the code for filter methods (and speed up `#reject!`)
|
||||
- [#6237](https://github.com/mruby/mruby/pull/6237) Stricter env objects to attach to ci
|
||||
- [#6238](https://github.com/mruby/mruby/pull/6238) Minimize zero initialization of the stack
|
||||
- [#6243](https://github.com/mruby/mruby/pull/6243) Fixed base64 decoding in `mruby-pack`
|
||||
- [#6244](https://github.com/mruby/mruby/pull/6244) Revise scope of role of `mrb_vm_run()`
|
||||
- [#6246](https://github.com/mruby/mruby/pull/6246) Fix typo in `test/t/hash.rb`
|
||||
- [#6249](https://github.com/mruby/mruby/pull/6249) Fix spelling in `src/vm.c`
|
||||
- [#6250](https://github.com/mruby/mruby/pull/6250) Fix spelling
|
||||
- [#6251](https://github.com/mruby/mruby/pull/6251) Clean up root move `CODEOWNERS` to `.github` directory
|
||||
- [#6253](https://github.com/mruby/mruby/pull/6253) Allow recycling fibers by GC if not referenced directly
|
||||
- [#6256](https://github.com/mruby/mruby/pull/6256) Update documentation for `mrb_top_run()`
|
||||
- [#6257](https://github.com/mruby/mruby/pull/6257) fix some mrbconf.md typos
|
||||
- [#6260](https://github.com/mruby/mruby/pull/6260) Remove `exc_caught` from `mrb_vm_exec()`
|
||||
- [#6261](https://github.com/mruby/mruby/pull/6261) fix: `to_a` integer ranges with `begin > end` failing
|
||||
- [#6263](https://github.com/mruby/mruby/pull/6263) fix: `Array#delete` mistakenly calling block even if not passed
|
||||
- [#6264](https://github.com/mruby/mruby/pull/6264) Must pass keyword arguments for `Kernel#to_enum`
|
||||
- [#6265](https://github.com/mruby/mruby/pull/6265) Fixes `Dir.children` and `Dir.each_child`
|
||||
- [#6266](https://github.com/mruby/mruby/pull/6266) Passes the nonexistent key as a block argument in `Array#delete`
|
||||
- [#6273](https://github.com/mruby/mruby/pull/6273) Improvements to `mrb_protect_atexit()`
|
||||
- [#6275](https://github.com/mruby/mruby/pull/6275) Fixed `Binding#eval` that failed to assign to the same variable
|
||||
- [#6276](https://github.com/mruby/mruby/pull/6276) Always run `atexit` on the top-level call frame
|
||||
- [#6279](https://github.com/mruby/mruby/pull/6279) Include headers for malloc() explicitly; fix #6277
|
||||
- [#6280](https://github.com/mruby/mruby/pull/6280) Remove `MRB_ENV_CLOSED` flag
|
||||
- [#6281](https://github.com/mruby/mruby/pull/6281) Fixes local variables in `mruby-binding`.
|
||||
- [#6283](https://github.com/mruby/mruby/pull/6283) Simplify `uvenv()`
|
||||
- [#6288](https://github.com/mruby/mruby/pull/6288) Detach `env` of ci explicitly on atexit
|
||||
- [#6289](https://github.com/mruby/mruby/pull/6289) Simplify `OP_RETURN_BLK` and `OP_BREAK`
|
||||
- [#6290](https://github.com/mruby/mruby/pull/6290) Allow to change the output directory name of the `libmruby` file
|
||||
- [#6293](https://github.com/mruby/mruby/pull/6293) Changed the instruction table in `opcode.md`
|
||||
- [#6294](https://github.com/mruby/mruby/pull/6294) Optimise `mrb_iv_get`
|
||||
- [#6302](https://github.com/mruby/mruby/pull/6302) Minor cleanup in mrb_str_init
|
||||
- [#6303](https://github.com/mruby/mruby/pull/6303) mrb_str_aset_m() should return replace instead of str
|
||||
- [#6305](https://github.com/mruby/mruby/pull/6305) Protect keyword arguments in `prepare_missing()`
|
||||
- [#6308](https://github.com/mruby/mruby/pull/6308) Assume that `MRB_CATCH()` has `mrb->exc` set
|
||||
- [#6310](https://github.com/mruby/mruby/pull/6310) Doubling the call stack when extending it
|
||||
- [#6311](https://github.com/mruby/mruby/pull/6311) Added fast-path for positional arguments less than 15 in `OP_SEND`
|
||||
- [#6312](https://github.com/mruby/mruby/pull/6312) Omit error checking at `OP_RETURN`, `OP_RETURN_BLK` and `OP_BREAK`
|
||||
- [#6313](https://github.com/mruby/mruby/pull/6313) Fix wrong column number in opcode.md
|
||||
- [#6314](https://github.com/mruby/mruby/pull/6314) Optimize even?/odd? for big integers
|
||||
- [#6318](https://github.com/mruby/mruby/pull/6318) Shrink variables in `mrb_vm_exec()`
|
||||
- [#6320](https://github.com/mruby/mruby/pull/6320) Shrinking the code in `OP_BREAK` and `OP_RETURN_BLK`
|
||||
- [#6321](https://github.com/mruby/mruby/pull/6321) Avoid warnings in `lib/**/*.rb`
|
||||
- [#6322](https://github.com/mruby/mruby/pull/6322) Fix mrb_ro_data_p on Intel Mac
|
||||
- [#6324](https://github.com/mruby/mruby/pull/6324) Remove `localjump_error()`
|
||||
- [#6327](https://github.com/mruby/mruby/pull/6327) fix ncurses linking issues
|
||||
- [#6328](https://github.com/mruby/mruby/pull/6328) Fix use-after-free in `obj_free()` for env objects
|
||||
- [#6329](https://github.com/mruby/mruby/pull/6329) Fix use-after-free in `mrb_obj_alloc()`
|
||||
- [#6330](https://github.com/mruby/mruby/pull/6330) Add a precondition to call `mrb_env_unshare()`.
|
||||
- [#6331](https://github.com/mruby/mruby/pull/6331) Restore the GC arena with tests
|
||||
- [#6332](https://github.com/mruby/mruby/pull/6332) Must not depend on the “host” build to generate `mruby-compiler/core/y.tab.c`
|
||||
- [#6333](https://github.com/mruby/mruby/pull/6333) Reduce the number of branch instructions in the `heap_p()`
|
||||
- [#6335](https://github.com/mruby/mruby/pull/6335) Add `return_ci` in `CHECKPOINT_MAIN()` of `OP_RETURN`
|
||||
- [#6338](https://github.com/mruby/mruby/pull/6338) Need to place static proc objects into 8-byte alignments
|
||||
- [#6340](https://github.com/mruby/mruby/pull/6340) Fix use-after-free for `Array#<=>`
|
||||
- [#6341](https://github.com/mruby/mruby/pull/6341) Need to restore the GC arena after some function calls
|
||||
- [#6344](https://github.com/mruby/mruby/pull/6344) prefer using `mrb_yield` to call block arguments
|
||||
- [#6347](https://github.com/mruby/mruby/pull/6347) codegen.c,parse.y: remove flattening of `yield` arguments; fix #6346
|
||||
- [#6348](https://github.com/mruby/mruby/pull/6348) Cancel the warning disablement
|
||||
- [#6349](https://github.com/mruby/mruby/pull/6349) Perform GC before deleting directories
|
||||
- [#6350](https://github.com/mruby/mruby/pull/6350) Fixed character encoding conversion function mismatch
|
||||
- [#6351](https://github.com/mruby/mruby/pull/6351) Remove unnecessary `mrb_gc_arena_restore()`
|
||||
- [#6353](https://github.com/mruby/mruby/pull/6353) Fix use-after-free in `mrb_ary_delete()`
|
||||
- [#6356](https://github.com/mruby/mruby/pull/6356) Making splat argument objects invisible from Ruby side
|
||||
- [#6373](https://github.com/mruby/mruby/pull/6373) Add build config for Milk-V Duo (RISC-V Linux) board
|
||||
- [#6382](https://github.com/mruby/mruby/pull/6382) Make array objects invisible in `mrb_gc_register()`
|
||||
- [#6385](https://github.com/mruby/mruby/pull/6385) Small improvements for `mrb_gc_register()`
|
||||
- [#6386](https://github.com/mruby/mruby/pull/6386) Avoid calling `mrb_gv_set()` from `mrb_gc_unregister()`
|
||||
- [#6387](https://github.com/mruby/mruby/pull/6387) Small improvements for `mrb_gc_unregister()`
|
||||
- [#6390](https://github.com/mruby/mruby/pull/6390) Fix use-after-free by `mrb_gc_unregistor()`
|
||||
- [#6391](https://github.com/mruby/mruby/pull/6391) Fixed argument forwarding in `instance_exec`
|
||||
- [#6392](https://github.com/mruby/mruby/pull/6392) Fix argument forwarding in `mrb_exec_irep()`
|
||||
- [#6393](https://github.com/mruby/mruby/pull/6393) Follow-up to #6391
|
||||
- [#6395](https://github.com/mruby/mruby/pull/6395) Storing method-id inside Symbol#to_proc
|
||||
- [#6396](https://github.com/mruby/mruby/pull/6396) Milk-V Build Config: update GPIO gem URL
|
||||
- [#6397](https://github.com/mruby/mruby/pull/6397) boxing_no.h: rename BOXNIX_SET_VALUE -> BOXNO_SET_VALUE
|
||||
- [#6399](https://github.com/mruby/mruby/pull/6399) Add macOS 15 to the build
|
||||
- [#6405](https://github.com/mruby/mruby/pull/6405) `io_read`: use `%i` instead of `%d` in call to `mrb_raisef`
|
||||
- [#6407](https://github.com/mruby/mruby/pull/6407) Allow to exclude specific files in `rake install`
|
||||
- [#6408](https://github.com/mruby/mruby/pull/6408) Improve compliance with C++ standards
|
||||
- [#6410](https://github.com/mruby/mruby/pull/6410) Put `#include <stdlib.h>` in `parse.y`
|
||||
- [#6412](https://github.com/mruby/mruby/pull/6412) Distinguish the call frame of the generator with `OP_RETURN_BLK`
|
||||
- [#6413](https://github.com/mruby/mruby/pull/6413) Add links to documentation in `README.md`
|
||||
- [#6415](https://github.com/mruby/mruby/pull/6415) Fix numbered parameters when used as a singleton
|
||||
- [#6416](https://github.com/mruby/mruby/pull/6416) Optimize the "new" method's iseq
|
||||
- [#6419](https://github.com/mruby/mruby/pull/6419) Follow Ruby's behavior for numbered parameters in -> {}
|
||||
- [#6420](https://github.com/mruby/mruby/pull/6420) Update `labeler.yml`: add label for the `tools` directory
|
||||
- [#6422](https://github.com/mruby/mruby/pull/6422) Add annotations for function names defined in the preprocessor
|
||||
- [#6423](https://github.com/mruby/mruby/pull/6423) Adding a serialized test task
|
||||
- [#6427](https://github.com/mruby/mruby/pull/6427) Need to update `ci` variable after re-entry to VM
|
||||
- [#6428](https://github.com/mruby/mruby/pull/6428) Change the limits of OP_ADDI and OP_SUBI from 0-127 to 0-255.
|
||||
- [#6429](https://github.com/mruby/mruby/pull/6429) Fix numbered parameters when used as hash keys
|
||||
- [#6432](https://github.com/mruby/mruby/pull/6432) Moving code in macro arguments out of macros
|
||||
- [#6434](https://github.com/mruby/mruby/pull/6434) Added document "Layout of the mruby filesystem"
|
||||
- [#6436](https://github.com/mruby/mruby/pull/6436) Make `rake doc:update-index` prettier friendly
|
||||
- [#6437](https://github.com/mruby/mruby/pull/6437) Add more details to the pre-commit config
|
||||
- [#6438](https://github.com/mruby/mruby/pull/6438) Remove unused `MRuby::Build#list_install_excludes` method
|
||||
- [#6440](https://github.com/mruby/mruby/pull/6440) Fix `redo` keyword
|
||||
- [#6442](https://github.com/mruby/mruby/pull/6442) Fixed wrong range condition in `OP_JMPUW`
|
||||
- [#6443](https://github.com/mruby/mruby/pull/6443) Fix NODE_NEGATE for bigints
|
||||
- [#6444](https://github.com/mruby/mruby/pull/6444) Add test cases for bigints
|
||||
- [#6446](https://github.com/mruby/mruby/pull/6446) Omit the `_WIN64` definition check
|
||||
- [#6447](https://github.com/mruby/mruby/pull/6447) Fixed `File.expand_path`
|
||||
- [#6448](https://github.com/mruby/mruby/pull/6448) Suppress presym in `mruby/ext/io.h` file
|
||||
- [#6449](https://github.com/mruby/mruby/pull/6449) Using presym in the `mruby-io/src/file_test.c` file
|
||||
- [#6450](https://github.com/mruby/mruby/pull/6450) Change `MRB_WITH_IO_PREAD_PWRITE` configuration name
|
||||
- [#6454](https://github.com/mruby/mruby/pull/6454) mruby-bigint: handle rhs bigint in int_mod and int_divmod functions
|
||||
- [#6455](https://github.com/mruby/mruby/pull/6455) mruby-bigint: fix rounding behavior in mpz_mdiv and mpz_mdivmod functions
|
||||
- [#6457](https://github.com/mruby/mruby/pull/6457) bigint: fix bug with division of a small number by a bigint
|
||||
- [#6459](https://github.com/mruby/mruby/pull/6459) `FileTest` is a module
|
||||
- [#6461](https://github.com/mruby/mruby/pull/6461) To create a release package file in draft
|
||||
- [#6462](https://github.com/mruby/mruby/pull/6462) Properly cast the return value of `memchr()`
|
||||
- [#6463](https://github.com/mruby/mruby/pull/6463) Add `level` argument to `File.dirname`
|
||||
- [#6465](https://github.com/mruby/mruby/pull/6465) Add initial PlayStation portable crossbuild support
|
||||
- [#6468](https://github.com/mruby/mruby/pull/6468) Fixed missing changes to `IB_FIND_BY_KEY()` parameter names
|
||||
- [#6469](https://github.com/mruby/mruby/pull/6469) Add more `const` qualifier for `RProc`
|
||||
- [#6472](https://github.com/mruby/mruby/pull/6472) Moved tests for `Integer#quo`
|
||||
- [#6473](https://github.com/mruby/mruby/pull/6473) Hide `mpz_and()` symbol
|
||||
- [#6473](https://github.com/mruby/mruby/pull/6473) Hide mpz_and() symbol
|
||||
- [#6474](https://github.com/mruby/mruby/pull/6474) Avoid array object creation with “unknown keyword” error
|
||||
- [#6475](https://github.com/mruby/mruby/pull/6475) Don't include deleted mruby-print
|
||||
- [#6478](https://github.com/mruby/mruby/pull/6478) Fixed buffer overrun in function `chars2bytes()`
|
||||
- [#6479](https://github.com/mruby/mruby/pull/6479) Reimplementation of `File.expand_path` method
|
||||
- [#6482](https://github.com/mruby/mruby/pull/6482) Add `File.absolute_path?` method
|
||||
- [#6487](https://github.com/mruby/mruby/pull/6487) Add Emscripten toolchain & build_config
|
||||
|
||||
@@ -30,12 +30,10 @@ of the Ministry of Economy, Trade and Industry of Japan.
|
||||
|
||||
## How to get mruby
|
||||
|
||||
To get mruby, you can download the stable version 3.3.0 from the official mruby
|
||||
To get mruby, you can download the stable version 3.4.0 from the official mruby
|
||||
GitHub repository or clone the trunk of the mruby source tree with the "git
|
||||
clone" command. You can also install and compile mruby using [ruby-install](https://github.com/postmodern/ruby-install), [ruby-build](https://github.com/rbenv/ruby-build) or [rvm](https://github.com/rvm/rvm).
|
||||
|
||||
The release candidate version 3.4.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/3.4.0-rc.zip](https://github.com/mruby/mruby/archive/3.4.0-rc.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)
|
||||
|
||||
The trunk of the mruby source tree can be checked out with the
|
||||
|
||||
@@ -60,7 +60,7 @@ MRuby::Build.new do |conf|
|
||||
# gperf settings
|
||||
# conf.gperf do |gperf|
|
||||
# gperf.command = 'gperf'
|
||||
# gperf.compile_options = %q[-L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" "%{infile}" > "%{outfile}"]
|
||||
# gperf.compile_options = %q[-L ANSI-C -C -j1 -i 1 -o -t -N mrb_reserved_word -k"1,3,$" "%{infile}" > "%{outfile}"]
|
||||
# end
|
||||
|
||||
# file extensions
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
# Cross Compiling configuration for Luckfox Pico embedded SBC.
|
||||
#
|
||||
# To build on Ubuntu x86_64: rake MRUBY_CONFIG=build_config/luckfox_pico.rb
|
||||
# Uses Buildroot SDK for this board. Binaries run on the corresponding Linux image.
|
||||
# Requires: https://github.com/LuckfoxTECH/luckfox-pico
|
||||
#
|
||||
# NOTE: default config includes all standard mrbgems, EXCEPT: mruby-cmath
|
||||
#
|
||||
MRuby::CrossBuild.new("luckfox_pico") do |conf|
|
||||
# Clone the luckfox-pico repo above next to (same directory level) as mruby.
|
||||
SDK_BASE = File.realpath(File.expand_path("../../../", File.expand_path(__FILE__)) + "/luckfox-pico")
|
||||
TOOLCHAIN_BASE = "#{SDK_BASE}/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf"
|
||||
SYSROOT = "#{TOOLCHAIN_BASE}/arm-rockchip830-linux-uclibcgnueabihf/sysroot"
|
||||
|
||||
toolchain :gcc
|
||||
|
||||
# C compiler settings
|
||||
conf.cc do |cc|
|
||||
cc.command = "#{TOOLCHAIN_BASE}/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc"
|
||||
|
||||
cc.include_paths << "#{TOOLCHAIN_BASE}/lib/gcc/arm-rockchip830-linux-uclibcgnueabihf/8.3.0/include"
|
||||
cc.include_paths << "#{TOOLCHAIN_BASE}/lib/gcc/arm-rockchip830-linux-uclibcgnueabihf/8.3.0/include-fixed"
|
||||
cc.include_paths << "#{TOOLCHAIN_BASE}/arm-rockchip830-linux-uclibcgnueabihf/include/c++/8.3.0/arm-rockchip830-linux-uclibcgnueabihf"
|
||||
cc.include_paths << "#{SYSROOT}/usr/include"
|
||||
|
||||
# Flags taken from the SDK's Makefile
|
||||
cc.flags << ["-march=armv7-a", "-mfpu=neon", "-mfloat-abi=hard"]
|
||||
cc.flags << ["-D_LARGEFILE_SOURCE", "-D_LARGEFILE64_SOURCE", "-D_FILE_OFFSET_BITS=64", "-ffunction-sections", "-fdata-sections"]
|
||||
cc.flags << ["-O2", "-fPIC"]
|
||||
cc.flags << ["-Wl,--copy-dt-needed-entries", "-Wl,-lc,-lgcc_s"]
|
||||
end
|
||||
|
||||
# Linker settings
|
||||
conf.linker do |linker|
|
||||
linker.command = cc.command
|
||||
linker.library_paths << "#{TOOLCHAIN_BASE}/arm-rockchip830-linux-uclibcgnueabihf/lib"
|
||||
linker.flags = cc.flags
|
||||
end
|
||||
|
||||
# Archiver settings
|
||||
conf.archiver do |archiver|
|
||||
archiver.command = "#{TOOLCHAIN_BASE}/bin/arm-rockchip830-linux-uclibcgnueabihf-ar"
|
||||
end
|
||||
|
||||
# Do not build executable test
|
||||
conf.build_mrbtest_lib_only
|
||||
|
||||
# Disable C++ exception
|
||||
conf.disable_cxx_exception
|
||||
|
||||
# All standard gems.
|
||||
conf.gem 'mrbgems/mruby-array-ext/'
|
||||
conf.gem 'mrbgems/mruby-bigint/'
|
||||
conf.gem 'mrbgems/mruby-bin-config/'
|
||||
conf.gem 'mrbgems/mruby-bin-debugger/'
|
||||
conf.gem 'mrbgems/mruby-bin-mirb/'
|
||||
conf.gem 'mrbgems/mruby-bin-mrbc/'
|
||||
conf.gem 'mrbgems/mruby-bin-mruby/'
|
||||
conf.gem 'mrbgems/mruby-bin-strip/'
|
||||
conf.gem 'mrbgems/mruby-binding/'
|
||||
conf.gem 'mrbgems/mruby-catch/'
|
||||
conf.gem 'mrbgems/mruby-class-ext/'
|
||||
# SDK doesn't include complex math for uClibc
|
||||
# conf.gem 'mrbgems/mruby-cmath/'
|
||||
conf.gem 'mrbgems/mruby-compar-ext/'
|
||||
conf.gem 'mrbgems/mruby-compiler/'
|
||||
conf.gem 'mrbgems/mruby-complex/'
|
||||
conf.gem 'mrbgems/mruby-data/'
|
||||
conf.gem 'mrbgems/mruby-dir/'
|
||||
conf.gem 'mrbgems/mruby-enum-chain/'
|
||||
conf.gem 'mrbgems/mruby-enum-ext/'
|
||||
conf.gem 'mrbgems/mruby-enum-lazy/'
|
||||
conf.gem 'mrbgems/mruby-enumerator/'
|
||||
conf.gem 'mrbgems/mruby-errno/'
|
||||
conf.gem 'mrbgems/mruby-error/'
|
||||
conf.gem 'mrbgems/mruby-eval/'
|
||||
conf.gem 'mrbgems/mruby-exit/'
|
||||
conf.gem 'mrbgems/mruby-fiber/'
|
||||
conf.gem 'mrbgems/mruby-hash-ext/'
|
||||
conf.gem 'mrbgems/mruby-io/'
|
||||
conf.gem 'mrbgems/mruby-kernel-ext/'
|
||||
conf.gem 'mrbgems/mruby-math/'
|
||||
conf.gem 'mrbgems/mruby-metaprog/'
|
||||
conf.gem 'mrbgems/mruby-method/'
|
||||
conf.gem 'mrbgems/mruby-numeric-ext/'
|
||||
conf.gem 'mrbgems/mruby-object-ext/'
|
||||
conf.gem 'mrbgems/mruby-objectspace/'
|
||||
conf.gem 'mrbgems/mruby-os-memsize/'
|
||||
conf.gem 'mrbgems/mruby-pack/'
|
||||
conf.gem 'mrbgems/mruby-proc-binding/'
|
||||
conf.gem 'mrbgems/mruby-proc-ext/'
|
||||
conf.gem 'mrbgems/mruby-random/'
|
||||
conf.gem 'mrbgems/mruby-range-ext/'
|
||||
conf.gem 'mrbgems/mruby-rational/'
|
||||
conf.gem 'mrbgems/mruby-set/'
|
||||
conf.gem 'mrbgems/mruby-sleep/'
|
||||
conf.gem 'mrbgems/mruby-socket/'
|
||||
conf.gem 'mrbgems/mruby-sprintf/'
|
||||
conf.gem 'mrbgems/mruby-string-ext/'
|
||||
conf.gem 'mrbgems/mruby-struct/'
|
||||
conf.gem 'mrbgems/mruby-symbol-ext/'
|
||||
# conf.gem 'mrbgems/mruby-test-inline-struct/'
|
||||
# conf.gem 'mrbgems/mruby-test/'
|
||||
conf.gem 'mrbgems/mruby-time/'
|
||||
conf.gem 'mrbgems/mruby-toplevel-ext/'
|
||||
end
|
||||
@@ -176,7 +176,7 @@ If you need an include path of header file use `search_header_path`:
|
||||
fail 'iconv.h not found' unless conf.cc.search_header_path 'iconv.h'
|
||||
```
|
||||
|
||||
If you need a full file name of header file use `search_header`:
|
||||
If you need a full filename of header file use `search_header`:
|
||||
|
||||
```ruby
|
||||
# Searches `iconv.h`.
|
||||
|
||||
@@ -40,7 +40,7 @@ To confirm mrdb was installed properly, run mrdb with the `--version` option:
|
||||
|
||||
```bash
|
||||
$ mrdb --version
|
||||
mruby 3.3.0 (2024-02-14)
|
||||
mruby 3.4.0 (2025-04-20)
|
||||
```
|
||||
|
||||
## 2.2 Basic Operation
|
||||
@@ -52,7 +52,7 @@ To invoke the mruby debugger, just type `mrdb`.
|
||||
To specify the script file:
|
||||
|
||||
```bash
|
||||
$ mrdb [option] file name
|
||||
$ mrdb [option] filename
|
||||
```
|
||||
|
||||
For example: Debugging sample.rb
|
||||
@@ -121,7 +121,7 @@ Be aware that the breakpoint command will not check the validity of the class na
|
||||
|
||||
You can get the current breakpoint information by the following options.
|
||||
|
||||
breakpoint breakpoint number : file name. line number
|
||||
breakpoint breakpoint number : filename. line number
|
||||
|
||||
breakpoint breakpoint number : [class name,] method name
|
||||
|
||||
@@ -267,7 +267,7 @@ Example:
|
||||
```
|
||||
(sample.rb:1) info breakpoints
|
||||
Num Type Enb What
|
||||
1 breakpoint y at sample.rb:3 -> file name,line number
|
||||
1 breakpoint y at sample.rb:3 -> filename,line number
|
||||
2 breakpoint n in Sample_class:sample_class_method -> [class:]method name
|
||||
3 breakpoint y in sample_global_method
|
||||
```
|
||||
@@ -301,11 +301,11 @@ When you do not specify both the `first` and `last` options, you will receive th
|
||||
Example:
|
||||
|
||||
```
|
||||
Specifying file name and first row number
|
||||
Specifying filename and first row number
|
||||
sample.rb:1) list sample2.rb:5
|
||||
```
|
||||
|
||||
Specifying the file name and the first and last row number:
|
||||
Specifying the filename and the first and last row number:
|
||||
|
||||
```
|
||||
(sample.rb:1) list sample2.rb:6,7
|
||||
|
||||
+108
-11
@@ -2,22 +2,119 @@
|
||||
|
||||
# Memory Allocation
|
||||
|
||||
There are three methods to customize memory allocation in mruby.
|
||||
In mruby, you can customize how memory is allocated in two ways:
|
||||
|
||||
1. Provide your own `realloc()`/`free()`
|
||||
2. Redefine `mrb_default_allocf()`
|
||||
3. Specify a function with `mrb_open_allocf()`
|
||||
1. **Provide your own `malloc()`/`realloc()`/`free()`**
|
||||
2. **Override `mrb_basic_alloc_func()`**
|
||||
|
||||
## Provide your own `realloc()`/`free()`
|
||||
---
|
||||
|
||||
On some platforms, especially on microcontrollers, the standard library may not provide `malloc()`, `realloc()`, and `free()`. In such cases, it may be necessary to define memory allocation functions for the specific platform. mruby uses `realloc()` and `free()` from the standard C library for memory management. By defining these two functions of your own, you can make mruby work. However, note the following two points:
|
||||
## 1. Provide your own `malloc()`/`realloc()`/`free()`
|
||||
|
||||
First, `realloc(NULL, size)` behaves the same as malloc(size). Second, `free(NULL)` exits without doing anything.
|
||||
On platforms without a full C standard library —such as many microcontrollers— you may need to supply your own implementations of `malloc()`, `realloc()`, and `free()`. mruby’s allocator calls directly into these functions, so replacing them lets you control **every** allocation and deallocation performed by your entire program, including any third‑party libraries you link against.
|
||||
|
||||
## Redefine `mrb_default_allocf()`
|
||||
Keep in mind:
|
||||
|
||||
The only function in mruby that uses the standard C library's memory allocation functions is `mrb_default_allocf()`, defined in `alloc.c`. By defining this function within your application, you can customize the memory management of your application.
|
||||
- Calling `realloc(NULL, size)` must behave like `malloc(size)`.
|
||||
- Calling `free(NULL)` must be a no‑op.
|
||||
|
||||
## Specify a function with `mrb_open_allocf()`
|
||||
Simply define these three functions in your code (or link against a library that provides them), and mruby — along with all other code in your process — will use your versions automatically.
|
||||
|
||||
If you want to perform different memory management for each `mrb_state` within your application, you can use the `mrb_open_allocf()` function to create the `mrb_state` structure. This allows you to specify a memory allocation function (which is compatible with `mrb_default_allocf`) for each `mrb_state`. Although this scheme is not recommended. It may become obsolete in the future, since I have never seen per mrb_state memory management use-case.
|
||||
## 2. Override `mrb_basic_alloc_func()`
|
||||
|
||||
Inside mruby, all of its own memory allocations go through a single function called mrb_basic_alloc_func() (formerly mrb_default_allocf()). By defining this function in your application before linking, you can intercept and handle **only** the memory operations initiated by mruby itself without affecting other libraries or parts of your program.
|
||||
|
||||
```c
|
||||
// Example signature:
|
||||
// void* mrb_basic_alloc_func(void* ptr, size_t size);
|
||||
```
|
||||
|
||||
Implement mrb_basic_alloc_func() in your code, and mruby will invoke it for every internal allocation, reallocation, and free request.
|
||||
|
||||
### Expected behavior
|
||||
|
||||
- `mrb_basic_alloc_func(NULL, size)` should allocate `size` bytes, just like `malloc(size)`.
|
||||
- `mrb_basic_alloc_func(ptr, size)` should resize the existing block at `ptr` to `size` bytes, just like `realloc(ptr, size)`.
|
||||
- `mrb_basic_alloc_func(ptr, 0)` should free the block at `ptr`, just like `free(ptr)`.
|
||||
|
||||
---
|
||||
|
||||
## Summary of effects:
|
||||
|
||||
- **Custom `malloc`/`realloc`/`free`**: replaces allocation behavior globally (mruby + all other code and third‑party libraries).
|
||||
|
||||
- **Custom `mrb_basic_alloc_func()`**: replaces allocation behavior only for mruby’s internal use, leaving other libraries’ allocations untouched.
|
||||
|
||||
## Migration note
|
||||
|
||||
If you are moving from the old API:
|
||||
|
||||
1. **Removal of `mrb_open_allocf()`**
|
||||
|
||||
- \_Old:
|
||||
|
||||
```c
|
||||
mrb_state *mrb = mrb_open_allocf(my_allocf, ud);
|
||||
```
|
||||
|
||||
- \_New:
|
||||
|
||||
```c
|
||||
// No allocf parameter; set up your hook via mrb_basic_alloc_func definition.
|
||||
mrb_state *mrb = mrb_open_core();
|
||||
```
|
||||
|
||||
2. **`mrb_open_core()` takes no arguments**
|
||||
|
||||
- Simply drop any allocf or user-data arguments, and redefine `mrb_basic_alloc_func` as you need.
|
||||
|
||||
3. **No more `mrb_allocf` type**
|
||||
|
||||
- Definitions using the `mrb_allocf` typedef can be removed; implement `mrb_basic_alloc_func()` with the signature below:
|
||||
|
||||
```c
|
||||
void* mrb_basic_alloc_func(void *ptr, size_t size);
|
||||
```
|
||||
|
||||
4. **`mrb_basic_alloc_func` signature change**
|
||||
|
||||
- _Old:_
|
||||
|
||||
```c
|
||||
void* mrb_default_allocf(mrb_state *mrb, void *ptr, size_t size, void *ud);
|
||||
```
|
||||
|
||||
- _New:_
|
||||
|
||||
```c
|
||||
void* mrb_basic_alloc_func(void *ptr, size_t size);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Code examples
|
||||
|
||||
- **Old style**:
|
||||
|
||||
```c
|
||||
static void*
|
||||
my_allocf(mrb_state *mrb, void *ud, void *ptr, size_t size)
|
||||
{
|
||||
// ...custom logic...
|
||||
}
|
||||
|
||||
mrb_state *mrb = mrb_open_allocf(my_allocf, some_ud);
|
||||
```
|
||||
|
||||
- **New style**:
|
||||
|
||||
```c
|
||||
// Define your hook before creating the state:
|
||||
void*
|
||||
mrb_basic_alloc_func(void *ptr, size_t size)
|
||||
{
|
||||
// ...custom logic...
|
||||
}
|
||||
|
||||
mrb_state *mrb = mrb_open_core();
|
||||
```
|
||||
|
||||
@@ -368,7 +368,7 @@ mruby can be extended with pure Ruby. It is possible to override existing
|
||||
classes or add new ones in this way. Put all Ruby files into the `mrblib`
|
||||
directory.
|
||||
|
||||
### Pre-Conditions
|
||||
### Preconditions
|
||||
|
||||
none
|
||||
|
||||
@@ -400,7 +400,7 @@ mruby codes under `mrblib` directory would be executed after gem init C
|
||||
function is called. Make sure _mruby script_ depends on _C code_ and
|
||||
_C code_ doesn't depend on _mruby script_.
|
||||
|
||||
### Pre-Conditions
|
||||
### Preconditions
|
||||
|
||||
See C and Ruby example.
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ header.
|
||||
For `MRB_OPSYM()`, specify the names corresponding to operators (see
|
||||
`MRuby::Presym::OPERATORS` in `lib/mruby/presym.rb` for the names that
|
||||
can be specified for it). Other than that, describe only word characters
|
||||
excluding leading and ending punctuations.
|
||||
excluding leading and ending punctuation.
|
||||
|
||||
These macros are converted to static symbol IDs at compile time, unless
|
||||
preallocate symbols are disabled by `conf.disable_presym`. In that case,
|
||||
|
||||
+27
-69
@@ -72,75 +72,6 @@ p Liste.new "foobar"
|
||||
|
||||
`ArgumentError` is raised.
|
||||
|
||||
## Method visibility
|
||||
|
||||
For simplicity reasons no method visibility (public/private/protected) is
|
||||
supported. Those methods are defined, but they are dummy methods.
|
||||
|
||||
```ruby
|
||||
class VisibleTest
|
||||
|
||||
def public_method; end
|
||||
|
||||
private
|
||||
def private_method; end
|
||||
|
||||
end
|
||||
|
||||
p VisibleTest.new.respond_to?(:private_method, false)
|
||||
p VisibleTest.new.respond_to?(:private_method, true)
|
||||
```
|
||||
|
||||
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
|
||||
|
||||
```
|
||||
false
|
||||
true
|
||||
```
|
||||
|
||||
#### mruby [3.1.0 (2022-05-12)]
|
||||
|
||||
```
|
||||
true
|
||||
true
|
||||
```
|
||||
|
||||
### Visibility Declaration
|
||||
|
||||
The declaration form of following visibility methods are not implemented.
|
||||
|
||||
- `public`
|
||||
- `private`
|
||||
- `protected`
|
||||
- `module_function`
|
||||
|
||||
Especially, `module_function` method is not dummy, but no declaration form.
|
||||
|
||||
```ruby
|
||||
module TestModule
|
||||
module_function
|
||||
def test_func
|
||||
p 'test_func called'
|
||||
end
|
||||
|
||||
test_func
|
||||
end
|
||||
|
||||
p 'ok'
|
||||
```
|
||||
|
||||
#### Ruby [ruby 2.5.5p157 (2019-03-15 revision 67260)]
|
||||
|
||||
```
|
||||
ok
|
||||
```
|
||||
|
||||
#### mruby [3.1.0 (2022-05-12)]
|
||||
|
||||
```
|
||||
test.rb:8: undefined method 'test_func' (NoMethodError)
|
||||
```
|
||||
|
||||
## `defined?`
|
||||
|
||||
The `defined?` keyword is considered too complex to be fully
|
||||
@@ -255,3 +186,30 @@ def g(a: 1, b: a)
|
||||
end
|
||||
g(a:1)
|
||||
```
|
||||
|
||||
## No Double Dispatch in Module Loading
|
||||
|
||||
To make implementation simpler, mruby does not use double dispatching in module loading (`include`/`prepend`/`extend`).
|
||||
Those method internally called corresponding actual load methods (`append_features`/`prepend_features`/`extend_object`).
|
||||
But they are rarely overloaded, consumes more memory, and make loading little bit slower. As a Ruby implementation for the smaller device,
|
||||
we decided mruby simpler.
|
||||
|
||||
```ruby
|
||||
module M
|
||||
def self.append_features(mod)
|
||||
p :append
|
||||
end
|
||||
end
|
||||
|
||||
class C
|
||||
include M
|
||||
end
|
||||
```
|
||||
|
||||
#### Ruby [ruby 3.5.0dev (2025-04-21 85bab61565))]
|
||||
|
||||
Prints `:append`.
|
||||
|
||||
#### mruby [3.5.0 (2025-04-28)]
|
||||
|
||||
Nothing printed (since `include` does not call `append_features` internally).
|
||||
|
||||
+1
-1
@@ -197,7 +197,7 @@ For better and faster hash values.
|
||||
|
||||
---
|
||||
|
||||
# Major bug fixes
|
||||
# Major bugfixes
|
||||
|
||||
- Fix infinite recursive call bugs in integer division [98799aa6](https://github.com/mruby/mruby/commit/98799aa6)
|
||||
- Fix to raise TypeError with super inside instance_eval / class_eval [#5476](https://github.com/mruby/mruby/pull/5476)
|
||||
|
||||
+251
@@ -0,0 +1,251 @@
|
||||
# User visible changes in `mruby3.4` from `mruby3.3`
|
||||
|
||||
"**_NOTE_**:" are changes to be aware of.
|
||||
|
||||
# The language
|
||||
|
||||
- mruby now supports `private` and `protected` visibility ([b0db0bd](https://github.com/mruby/mruby/commit/b0db0bd))
|
||||
- Maximum length of inlined symbols reduced from 5 to 4 characters to provide space for visibility flags ([6442a01](https://github.com/mruby/mruby/commit/6442a01))
|
||||
- Many methods are made private according to CRuby visibility ([4a0e806](https://github.com/mruby/mruby/commit/4a0e806))
|
||||
- Generate OP_SSEND for `self.method` type calls ([111fe4b](https://github.com/mruby/mruby/commit/111fe4b))
|
||||
- `initialize` method will be always private ([eb8b412](https://github.com/mruby/mruby/commit/eb8b412))
|
||||
- Add new hooks `method_removed`, `method_undefined` ([9c74f6e](https://github.com/mruby/mruby/commit/9c74f6e))
|
||||
- Add new hooks `singleton_method_removed`, `singleton_method_undefined` ([0863c08](https://github.com/mruby/mruby/commit/0863c08))
|
||||
- Updated `OP_DEF` output from codedump ([3a3e877](https://github.com/mruby/mruby/commit/3a3e877))
|
||||
- Better handling of binary strings, e.g. String#b ([b0127f0](https://github.com/mruby/mruby/commit/b0127f0))
|
||||
- Hash `to_s` format has changed ([baeeb5e](https://github.com/mruby/mruby/commit/baeeb5e))
|
||||
- Some encoding related method such as `#force_encoding` ([e47b4ca](https://github.com/mruby/mruby/commit/e47b4ca)), `#b` ([b0127f0](https://github.com/mruby/mruby/commit/b0127f0))
|
||||
- Constant folding for `String#+` ([6687bdd](https://github.com/mruby/mruby/commit/6687bdd))
|
||||
- Remove Float bit-operation ([db8368f](https://github.com/mruby/mruby/commit/db8368f))
|
||||
- use SWAR technique for strlen performance ([cbb31e6](https://github.com/mruby/mruby/commit/cbb31e6))
|
||||
- use merge sort for `Array#sort` ([5bd63d6](https://github.com/mruby/mruby/commit/5bd63d6))
|
||||
|
||||
# Changes in C API
|
||||
|
||||
- pool.c renamed to mempool.c (and mrb_pool to mrb_mempool) ([49525fa](https://github.com/mruby/mruby/commit/49525fa))
|
||||
- mrb_pool_value renamed to mrb_irep_pool to reduce confusion ([62ef5db](https://github.com/mruby/mruby/commit/62ef5db))
|
||||
- rename BOXNIX_SET_VALUE to BOXNO_SET_VALUE ([#6397](https://github.com/mruby/mruby/pull/6397))
|
||||
- `MRB_FROZEN_P()` is replaced by `mrb_frozen_p()` ([c11d18e](https://github.com/mruby/mruby/commit/c11d18e))
|
||||
- rename `color` to `gc_color` ([0e79f6b](https://github.com/mruby/mruby/commit/0e79f6b), [1e36d76](https://github.com/mruby/mruby/commit/1e36d76))
|
||||
- add `obj->frozen` instead of flags `MRB_SET_FROZEN_FLAG`/`MRB_UNSET_FROZEN_FLAG` ([8276143](https://github.com/mruby/mruby/commit/8276143))
|
||||
|
||||
# Build & Configuration
|
||||
|
||||
- New Build Target: `test:run:serial`, `test:run:serial:lib`, `test:run:serial:bin` ([#6423](https://github.com/mruby/mruby/pull/6423))
|
||||
- New Platform: PlayStation Portable ([#6022](https://github.com/mruby/mruby/pull/6465))
|
||||
- New Platform: emscripten ([#6487](https://github.com/mruby/mruby/pull/6487))
|
||||
- New Config: no-float (with MRB_NO_FLOAT) ([32200f1](https://github.com/mruby/mruby/commit/32200f1))
|
||||
|
||||
# Changes in mrbgems
|
||||
|
||||
- **mruby-print**: removed; if you do not use `mruby-io`, mruby use `#print` etc. in the core ([8c8bbd9](https://github.com/mruby/mruby/commit/8c8bbd9))
|
||||
- **mruby-enum-lazy**: Add Enumerable::Lazy#grep_v to mruby-enum-lazy ([#6171](https://github.com/mruby/mruby/pull/6171))
|
||||
- **mruby-io**: Add `level` argument to `File.dirname` ([#6463](https://github.com/mruby/mruby/pull/6463))
|
||||
- **mruby-io**: File.absolute_path? ([#6482](https://github.com/mruby/mruby/pull/6482))
|
||||
- **mruby-io**: File.absolute_path ([96113a2](https://github.com/mruby/mruby/commit/96113a2))
|
||||
- **mruby-toplevel-ext**: top-level public/private/protected moved to the core ([2a876d2](https://github.com/mruby/mruby/commit/2a876d2))
|
||||
- **mruby-metaprog**: method list methods now works according to the visibility ([9229da1](https://github.com/mruby/mruby/commit/9229da1))
|
||||
- **mruby-metaprog**: `public_instance_methods`, `private_instance_methods`, `protected_instance_methods` ([9e3e7b2](https://github.com/mruby/mruby/commit/9e3e7b2))
|
||||
- **mruby-encoding**: MRB_UTF8_STRING turned on automatically with this gem ([74bdae9](https://github.com/mruby/mruby/commit/74bdae9))
|
||||
|
||||
# Fixed GitHub Issues
|
||||
|
||||
- [#6173](https://github.com/mruby/mruby/issues/6173) Fails to build with tcc(Tiny C Compiler)
|
||||
- [#6156](https://github.com/mruby/mruby/issues/6156) '/LIBPATH' issue
|
||||
- [#6183](https://github.com/mruby/mruby/issues/6183) ".e".to_f returns NAN
|
||||
- [#6182](https://github.com/mruby/mruby/issues/6182) mrb_read_float() converts "0.3" with a small error compared to strtod()
|
||||
- [#6210](https://github.com/mruby/mruby/issues/6210) Unary minus seems broken
|
||||
- [#6255](https://github.com/mruby/mruby/issues/6255) Wrong number of characters in broken UTF-8 string
|
||||
- [#4038](https://github.com/mruby/mruby/issues/4038) Heap buffer overflow in OP_ENTER
|
||||
- [#6262](https://github.com/mruby/mruby/issues/6262) Unable to define == for objects when using Array#delete
|
||||
- [#6267](https://github.com/mruby/mruby/issues/6267) When MRB_UTF8_STRING is enabled, giving byte characters for String#index and String#split gives wrong results
|
||||
- [#6277](https://github.com/mruby/mruby/issues/6277) MSVC: can't use malloc() in string.c with WIN32_LEAN_AND_MEAN
|
||||
- [#6240](https://github.com/mruby/mruby/issues/6240) Differentiate between lib and lib64 in the build settings.
|
||||
- [#6304](https://github.com/mruby/mruby/issues/6304) Calling method_missing with only Kwargs passes arguments incorrectly
|
||||
- [#6317](https://github.com/mruby/mruby/issues/6317) mrb_gc_register() may cause GC and collect the object being protected
|
||||
- [#6307](https://github.com/mruby/mruby/issues/6307) Planned change patch for mrb_vm_exec()
|
||||
- [#6298](https://github.com/mruby/mruby/issues/6298) foo :bar {} is legal in mruby?
|
||||
- [#6326](https://github.com/mruby/mruby/issues/6326) Detect “Use-after-free” with address sanitizer
|
||||
- [#5358](https://github.com/mruby/mruby/issues/5358) static warning from getpwnam
|
||||
- [#6339](https://github.com/mruby/mruby/issues/6339) mrb_ary_delete() may refer to an invalid address (use-after-free)
|
||||
- [#6346](https://github.com/mruby/mruby/issues/6346) Block kwargs are passed as last positional arg when using yield
|
||||
- [#6365](https://github.com/mruby/mruby/issues/6365) powl() not available when compiling for Dreamcast
|
||||
- [#6369](https://github.com/mruby/mruby/issues/6369) 100x Performance Regression from 3.1
|
||||
- [#6270](https://github.com/mruby/mruby/issues/6270) NODE_ZSUPER from deeply nested blocks will result in a truncated digits for block index in OP_ARGARY
|
||||
- [#6297](https://github.com/mruby/mruby/issues/6297) Assigning to a block variable changes the actual block (thus affecting block_given? and yield)
|
||||
- [#6389](https://github.com/mruby/mruby/issues/6389) instance_exec named block args don't work properly
|
||||
- [#6388](https://github.com/mruby/mruby/issues/6388) Recent commit broke my windows build
|
||||
- [#6411](https://github.com/mruby/mruby/issues/6411) Wrong function unwinding when using return in a block
|
||||
- [#6439](https://github.com/mruby/mruby/issues/6439) OP_JMPUW does not call the ensure block when it jumps to the beginning of the begin block
|
||||
- [#6441](https://github.com/mruby/mruby/issues/6441) break inside while loop will execute the ensure block outside of the while loop
|
||||
- [#6453](https://github.com/mruby/mruby/issues/6453) Bigint: incorrect behavior of ^ operator
|
||||
- [#6452](https://github.com/mruby/mruby/issues/6452) Bigint: weird mod behavior
|
||||
- [#6451](https://github.com/mruby/mruby/issues/6451) Bigint: incorrect division behavior
|
||||
- [#6456](https://github.com/mruby/mruby/issues/6456) bigint: bug with division of a small number by a bigint
|
||||
- [#6466](https://github.com/mruby/mruby/issues/6466) mruby-bin-mruby using Kernel#p and Kernel#print in bintest fails test
|
||||
- [#6467](https://github.com/mruby/mruby/issues/6467) Heap-Use-After-Free due to Recursive group_by Calls
|
||||
- [#6471](https://github.com/mruby/mruby/issues/6471) Discrepancy in codegen for binary operations between master branch and 3.3.0
|
||||
- [#6477](https://github.com/mruby/mruby/issues/6477) heap-buffer-overflow in mrb_vm_exec
|
||||
- [#6485](https://github.com/mruby/mruby/issues/6485) Hash#rehash does not check if the hash is frozen
|
||||
- [#6483](https://github.com/mruby/mruby/issues/6483) Hash#default_proc= accepts arbitrary objects that are not callable
|
||||
- [#6491](https://github.com/mruby/mruby/issues/6491) Destroy existing string literals when composing string literals
|
||||
|
||||
# Merged Pull Requests (User Visible Ones)
|
||||
|
||||
- [#6171](https://github.com/mruby/mruby/pull/6171) Add Enumerable::Lazy#grep_v to mruby-enum-lazy
|
||||
- [#6174](https://github.com/mruby/mruby/pull/6174) Fix MRUBY_PACKAGE_DIR in mruby-config.bat
|
||||
- [#6175](https://github.com/mruby/mruby/pull/6175) Corrected strange conditional in mrb_vm_run()
|
||||
- [#6176](https://github.com/mruby/mruby/pull/6176) Stop assuming alias proc in CI_PROC_SET()
|
||||
- [#6177](https://github.com/mruby/mruby/pull/6177) gha: add macOS 14 to the build
|
||||
- [#6184](https://github.com/mruby/mruby/pull/6184) Remove the L_STOP label
|
||||
- [#6185](https://github.com/mruby/mruby/pull/6185) Added mrb_callinfo::u.keep_context for clarity
|
||||
- [#6186](https://github.com/mruby/mruby/pull/6186) Omit NULL check of e->cxt in OP_RETURN_BLK
|
||||
- [#6191](https://github.com/mruby/mruby/pull/6191) Speed up symbol equality comparison
|
||||
- [#6192](https://github.com/mruby/mruby/pull/6192) Fix `OP_STOP` with exception
|
||||
- [#6193](https://github.com/mruby/mruby/pull/6193) Fix wrong assertion in `OP_SENDB`.
|
||||
- [#6194](https://github.com/mruby/mruby/pull/6194) Simplify the calculation of the number of closures in `MRB_TT_FIBER`
|
||||
- [#6197](https://github.com/mruby/mruby/pull/6197) Fix int_xor to call flo_xor.
|
||||
- [#6201](https://github.com/mruby/mruby/pull/6201) tasks/doc.rake: standardize the `rake doc` error messages
|
||||
- [#6202](https://github.com/mruby/mruby/pull/6202) Remove the `.yardoc` folder with `rake doc:clean:api`
|
||||
- [#6204](https://github.com/mruby/mruby/pull/6204) Clean up the `.editorconfig` file
|
||||
- [#6209](https://github.com/mruby/mruby/pull/6209) Minor `.gitignore` clean up
|
||||
- [#6211](https://github.com/mruby/mruby/pull/6211) Minor `.gitignore` clean up; order entries
|
||||
- [#6216](https://github.com/mruby/mruby/pull/6216) Shared empty `iv_tbl` of module
|
||||
- [#6217](https://github.com/mruby/mruby/pull/6217) Strict declaration for `mrb_istruct_size()`
|
||||
- [#6219](https://github.com/mruby/mruby/pull/6219) Avoid assigning a fixed value in the loop
|
||||
- [#6220](https://github.com/mruby/mruby/pull/6220) Reorganize `mrb_cache_entry` and `mrb_method_t` types
|
||||
- [#6221](https://github.com/mruby/mruby/pull/6221) Arranging `each_backtrace()`
|
||||
- [#6222](https://github.com/mruby/mruby/pull/6222) Need to synchronize `dbg->regs` after VM call in `mrdb`
|
||||
- [#6224](https://github.com/mruby/mruby/pull/6224) `mrb_env_unshare()` to break the link to fiber
|
||||
- [#6225](https://github.com/mruby/mruby/pull/6225) Revert "Adjust environment when `mrb_exec_irep` happened."
|
||||
- [#6227](https://github.com/mruby/mruby/pull/6227) fix: `Array#shuffle(!)` result distribution
|
||||
- [#6228](https://github.com/mruby/mruby/pull/6228) Revert "`env` referred from top-level callinfo should not be unshared; fix #4019"
|
||||
- [#6230](https://github.com/mruby/mruby/pull/6230) Fix status of fiber after switched by exception raised
|
||||
- [#6231](https://github.com/mruby/mruby/pull/6231) Add a way to let other gems handle closing of fds in mruby-io
|
||||
- [#6232](https://github.com/mruby/mruby/pull/6232) Fold the code for freeing `env`
|
||||
- [#6233](https://github.com/mruby/mruby/pull/6233) Free stack memory at end of fiber
|
||||
- [#6235](https://github.com/mruby/mruby/pull/6235) fix `Array#delete` always firing the block when deleting `nil`
|
||||
- [#6236](https://github.com/mruby/mruby/pull/6236) unify the code for filter methods (and speed up `#reject!`)
|
||||
- [#6237](https://github.com/mruby/mruby/pull/6237) Stricter env objects to attach to ci
|
||||
- [#6238](https://github.com/mruby/mruby/pull/6238) Minimize zero initialization of the stack
|
||||
- [#6243](https://github.com/mruby/mruby/pull/6243) Fixed base64 decoding in `mruby-pack`
|
||||
- [#6244](https://github.com/mruby/mruby/pull/6244) Revise scope of role of `mrb_vm_run()`
|
||||
- [#6246](https://github.com/mruby/mruby/pull/6246) Fix typo in `test/t/hash.rb`
|
||||
- [#6249](https://github.com/mruby/mruby/pull/6249) Fix spelling in `src/vm.c`
|
||||
- [#6250](https://github.com/mruby/mruby/pull/6250) Fix spelling
|
||||
- [#6251](https://github.com/mruby/mruby/pull/6251) Clean up root move `CODEOWNERS` to `.github` directory
|
||||
- [#6253](https://github.com/mruby/mruby/pull/6253) Allow recycling fibers by GC if not referenced directly
|
||||
- [#6256](https://github.com/mruby/mruby/pull/6256) Update documentation for `mrb_top_run()`
|
||||
- [#6257](https://github.com/mruby/mruby/pull/6257) fix some mrbconf.md typos
|
||||
- [#6260](https://github.com/mruby/mruby/pull/6260) Remove `exc_caught` from `mrb_vm_exec()`
|
||||
- [#6261](https://github.com/mruby/mruby/pull/6261) fix: `to_a` integer ranges with `begin > end` failing
|
||||
- [#6263](https://github.com/mruby/mruby/pull/6263) fix: `Array#delete` mistakenly calling block even if not passed
|
||||
- [#6264](https://github.com/mruby/mruby/pull/6264) Must pass keyword arguments for `Kernel#to_enum`
|
||||
- [#6265](https://github.com/mruby/mruby/pull/6265) Fixes `Dir.children` and `Dir.each_child`
|
||||
- [#6266](https://github.com/mruby/mruby/pull/6266) Passes the nonexistent key as a block argument in `Array#delete`
|
||||
- [#6273](https://github.com/mruby/mruby/pull/6273) Improvements to `mrb_protect_atexit()`
|
||||
- [#6275](https://github.com/mruby/mruby/pull/6275) Fixed `Binding#eval` that failed to assign to the same variable
|
||||
- [#6276](https://github.com/mruby/mruby/pull/6276) Always run `atexit` on the top-level call frame
|
||||
- [#6279](https://github.com/mruby/mruby/pull/6279) Include headers for malloc() explicitly; fix #6277
|
||||
- [#6280](https://github.com/mruby/mruby/pull/6280) Remove `MRB_ENV_CLOSED` flag
|
||||
- [#6281](https://github.com/mruby/mruby/pull/6281) Fixes local variables in `mruby-binding`.
|
||||
- [#6283](https://github.com/mruby/mruby/pull/6283) Simplify `uvenv()`
|
||||
- [#6288](https://github.com/mruby/mruby/pull/6288) Detach `env` of ci explicitly on atexit
|
||||
- [#6289](https://github.com/mruby/mruby/pull/6289) Simplify `OP_RETURN_BLK` and `OP_BREAK`
|
||||
- [#6290](https://github.com/mruby/mruby/pull/6290) Allow to change the output directory name of the `libmruby` file
|
||||
- [#6293](https://github.com/mruby/mruby/pull/6293) Changed the instruction table in `opcode.md`
|
||||
- [#6294](https://github.com/mruby/mruby/pull/6294) Optimise `mrb_iv_get`
|
||||
- [#6302](https://github.com/mruby/mruby/pull/6302) Minor cleanup in mrb_str_init
|
||||
- [#6303](https://github.com/mruby/mruby/pull/6303) mrb_str_aset_m() should return replace instead of str
|
||||
- [#6305](https://github.com/mruby/mruby/pull/6305) Protect keyword arguments in `prepare_missing()`
|
||||
- [#6308](https://github.com/mruby/mruby/pull/6308) Assume that `MRB_CATCH()` has `mrb->exc` set
|
||||
- [#6310](https://github.com/mruby/mruby/pull/6310) Doubling the call stack when extending it
|
||||
- [#6311](https://github.com/mruby/mruby/pull/6311) Added fast-path for positional arguments less than 15 in `OP_SEND`
|
||||
- [#6312](https://github.com/mruby/mruby/pull/6312) Omit error checking at `OP_RETURN`, `OP_RETURN_BLK` and `OP_BREAK`
|
||||
- [#6313](https://github.com/mruby/mruby/pull/6313) Fix wrong column number in opcode.md
|
||||
- [#6314](https://github.com/mruby/mruby/pull/6314) Optimize even?/odd? for big integers
|
||||
- [#6318](https://github.com/mruby/mruby/pull/6318) Shrink variables in `mrb_vm_exec()`
|
||||
- [#6320](https://github.com/mruby/mruby/pull/6320) Shrinking the code in `OP_BREAK` and `OP_RETURN_BLK`
|
||||
- [#6321](https://github.com/mruby/mruby/pull/6321) Avoid warnings in `lib/**/*.rb`
|
||||
- [#6322](https://github.com/mruby/mruby/pull/6322) Fix mrb_ro_data_p on Intel Mac
|
||||
- [#6324](https://github.com/mruby/mruby/pull/6324) Remove `localjump_error()`
|
||||
- [#6327](https://github.com/mruby/mruby/pull/6327) fix ncurses linking issues
|
||||
- [#6328](https://github.com/mruby/mruby/pull/6328) Fix use-after-free in `obj_free()` for env objects
|
||||
- [#6329](https://github.com/mruby/mruby/pull/6329) Fix use-after-free in `mrb_obj_alloc()`
|
||||
- [#6330](https://github.com/mruby/mruby/pull/6330) Add a precondition to call `mrb_env_unshare()`.
|
||||
- [#6331](https://github.com/mruby/mruby/pull/6331) Restore the GC arena with tests
|
||||
- [#6332](https://github.com/mruby/mruby/pull/6332) Must not depend on the “host” build to generate `mruby-compiler/core/y.tab.c`
|
||||
- [#6333](https://github.com/mruby/mruby/pull/6333) Reduce the number of branch instructions in the `heap_p()`
|
||||
- [#6335](https://github.com/mruby/mruby/pull/6335) Add `return_ci` in `CHECKPOINT_MAIN()` of `OP_RETURN`
|
||||
- [#6338](https://github.com/mruby/mruby/pull/6338) Need to place static proc objects into 8-byte alignments
|
||||
- [#6340](https://github.com/mruby/mruby/pull/6340) Fix use-after-free for `Array#<=>`
|
||||
- [#6341](https://github.com/mruby/mruby/pull/6341) Need to restore the GC arena after some function calls
|
||||
- [#6344](https://github.com/mruby/mruby/pull/6344) prefer using `mrb_yield` to call block arguments
|
||||
- [#6347](https://github.com/mruby/mruby/pull/6347) codegen.c,parse.y: remove flattening of `yield` arguments; fix #6346
|
||||
- [#6348](https://github.com/mruby/mruby/pull/6348) Cancel the warning disablement
|
||||
- [#6349](https://github.com/mruby/mruby/pull/6349) Perform GC before deleting directories
|
||||
- [#6350](https://github.com/mruby/mruby/pull/6350) Fixed character encoding conversion function mismatch
|
||||
- [#6351](https://github.com/mruby/mruby/pull/6351) Remove unnecessary `mrb_gc_arena_restore()`
|
||||
- [#6353](https://github.com/mruby/mruby/pull/6353) Fix use-after-free in `mrb_ary_delete()`
|
||||
- [#6356](https://github.com/mruby/mruby/pull/6356) Making splat argument objects invisible from Ruby side
|
||||
- [#6373](https://github.com/mruby/mruby/pull/6373) Add build config for Milk-V Duo (RISC-V Linux) board
|
||||
- [#6382](https://github.com/mruby/mruby/pull/6382) Make array objects invisible in `mrb_gc_register()`
|
||||
- [#6385](https://github.com/mruby/mruby/pull/6385) Small improvements for `mrb_gc_register()`
|
||||
- [#6386](https://github.com/mruby/mruby/pull/6386) Avoid calling `mrb_gv_set()` from `mrb_gc_unregister()`
|
||||
- [#6387](https://github.com/mruby/mruby/pull/6387) Small improvements for `mrb_gc_unregister()`
|
||||
- [#6390](https://github.com/mruby/mruby/pull/6390) Fix use-after-free by `mrb_gc_unregistor()`
|
||||
- [#6391](https://github.com/mruby/mruby/pull/6391) Fixed argument forwarding in `instance_exec`
|
||||
- [#6392](https://github.com/mruby/mruby/pull/6392) Fix argument forwarding in `mrb_exec_irep()`
|
||||
- [#6393](https://github.com/mruby/mruby/pull/6393) Follow-up to #6391
|
||||
- [#6395](https://github.com/mruby/mruby/pull/6395) Storing method-id inside Symbol#to_proc
|
||||
- [#6396](https://github.com/mruby/mruby/pull/6396) Milk-V Build Config: update GPIO gem URL
|
||||
- [#6397](https://github.com/mruby/mruby/pull/6397) boxing_no.h: rename BOXNIX_SET_VALUE -> BOXNO_SET_VALUE
|
||||
- [#6399](https://github.com/mruby/mruby/pull/6399) Add macOS 15 to the build
|
||||
- [#6405](https://github.com/mruby/mruby/pull/6405) `io_read`: use `%i` instead of `%d` in call to `mrb_raisef`
|
||||
- [#6407](https://github.com/mruby/mruby/pull/6407) Allow to exclude specific files in `rake install`
|
||||
- [#6408](https://github.com/mruby/mruby/pull/6408) Improve compliance with C++ standards
|
||||
- [#6410](https://github.com/mruby/mruby/pull/6410) Put `#include <stdlib.h>` in `parse.y`
|
||||
- [#6412](https://github.com/mruby/mruby/pull/6412) Distinguish the call frame of the generator with `OP_RETURN_BLK`
|
||||
- [#6413](https://github.com/mruby/mruby/pull/6413) Add links to documentation in `README.md`
|
||||
- [#6415](https://github.com/mruby/mruby/pull/6415) Fix numbered parameters when used as a singleton
|
||||
- [#6416](https://github.com/mruby/mruby/pull/6416) Optimize the "new" method's iseq
|
||||
- [#6419](https://github.com/mruby/mruby/pull/6419) Follow Ruby's behavior for numbered parameters in -> {}
|
||||
- [#6420](https://github.com/mruby/mruby/pull/6420) Update `labeler.yml`: add label for the `tools` directory
|
||||
- [#6422](https://github.com/mruby/mruby/pull/6422) Add annotations for function names defined in the preprocessor
|
||||
- [#6423](https://github.com/mruby/mruby/pull/6423) Adding a serialized test task
|
||||
- [#6427](https://github.com/mruby/mruby/pull/6427) Need to update `ci` variable after re-entry to VM
|
||||
- [#6428](https://github.com/mruby/mruby/pull/6428) Change the limits of OP_ADDI and OP_SUBI from 0-127 to 0-255.
|
||||
- [#6429](https://github.com/mruby/mruby/pull/6429) Fix numbered parameters when used as hash keys
|
||||
- [#6432](https://github.com/mruby/mruby/pull/6432) Moving code in macro arguments out of macros
|
||||
- [#6434](https://github.com/mruby/mruby/pull/6434) Added document "Layout of the mruby filesystem"
|
||||
- [#6436](https://github.com/mruby/mruby/pull/6436) Make `rake doc:update-index` prettier friendly
|
||||
- [#6437](https://github.com/mruby/mruby/pull/6437) Add more details to the pre-commit config
|
||||
- [#6438](https://github.com/mruby/mruby/pull/6438) Remove unused `MRuby::Build#list_install_excludes` method
|
||||
- [#6440](https://github.com/mruby/mruby/pull/6440) Fix `redo` keyword
|
||||
- [#6442](https://github.com/mruby/mruby/pull/6442) Fixed wrong range condition in `OP_JMPUW`
|
||||
- [#6443](https://github.com/mruby/mruby/pull/6443) Fix NODE_NEGATE for bigints
|
||||
- [#6444](https://github.com/mruby/mruby/pull/6444) Add test cases for bigints
|
||||
- [#6446](https://github.com/mruby/mruby/pull/6446) Omit the `_WIN64` definition check
|
||||
- [#6447](https://github.com/mruby/mruby/pull/6447) Fixed `File.expand_path`
|
||||
- [#6448](https://github.com/mruby/mruby/pull/6448) Suppress presym in `mruby/ext/io.h` file
|
||||
- [#6449](https://github.com/mruby/mruby/pull/6449) Using presym in the `mruby-io/src/file_test.c` file
|
||||
- [#6450](https://github.com/mruby/mruby/pull/6450) Change `MRB_WITH_IO_PREAD_PWRITE` configuration name
|
||||
- [#6454](https://github.com/mruby/mruby/pull/6454) mruby-bigint: handle rhs bigint in int_mod and int_divmod functions
|
||||
- [#6455](https://github.com/mruby/mruby/pull/6455) mruby-bigint: fix rounding behavior in mpz_mdiv and mpz_mdivmod functions
|
||||
- [#6457](https://github.com/mruby/mruby/pull/6457) bigint: fix bug with division of a small number by a bigint
|
||||
- [#6459](https://github.com/mruby/mruby/pull/6459) `FileTest` is a module
|
||||
- [#6461](https://github.com/mruby/mruby/pull/6461) To create a release package file in draft
|
||||
- [#6462](https://github.com/mruby/mruby/pull/6462) Properly cast the return value of `memchr()`
|
||||
- [#6463](https://github.com/mruby/mruby/pull/6463) Add `level` argument to `File.dirname`
|
||||
- [#6465](https://github.com/mruby/mruby/pull/6465) Add initial PlayStation portable crossbuild support
|
||||
- [#6468](https://github.com/mruby/mruby/pull/6468) Fixed missing changes to `IB_FIND_BY_KEY()` parameter names
|
||||
- [#6469](https://github.com/mruby/mruby/pull/6469) Add more `const` qualifier for `RProc`
|
||||
- [#6472](https://github.com/mruby/mruby/pull/6472) Moved tests for `Integer#quo`
|
||||
- [#6473](https://github.com/mruby/mruby/pull/6473) Hide `mpz_and()` symbol
|
||||
- [#6473](https://github.com/mruby/mruby/pull/6473) Hide mpz_and() symbol
|
||||
- [#6474](https://github.com/mruby/mruby/pull/6474) Avoid array object creation with “unknown keyword” error
|
||||
- [#6475](https://github.com/mruby/mruby/pull/6475) Don't include deleted mruby-print
|
||||
- [#6478](https://github.com/mruby/mruby/pull/6478) Fixed buffer overrun in function `chars2bytes()`
|
||||
- [#6479](https://github.com/mruby/mruby/pull/6479) Reimplementation of `File.expand_path` method
|
||||
- [#6482](https://github.com/mruby/mruby/pull/6482) Add `File.absolute_path?` method
|
||||
- [#6487](https://github.com/mruby/mruby/pull/6487) Add Emscripten toolchain & build_config
|
||||
@@ -42,12 +42,6 @@
|
||||
#error Cannot define MRB_USE_FLOAT32 and MRB_NO_FLOAT at the same time
|
||||
#endif
|
||||
|
||||
/* add -DMRB_NO_METHOD_CACHE to disable method cache to save memory */
|
||||
//#define MRB_NO_METHOD_CACHE
|
||||
/* size of the method cache (need to be the power of 2) */
|
||||
//#define MRB_METHOD_CACHE_SIZE (1<<8)
|
||||
//#define MRB_USE_INLINE_METHOD_CACHE
|
||||
|
||||
/* define on big endian machines; used by MRB_NAN_BOXING, etc. */
|
||||
#ifndef MRB_ENDIAN_BIG
|
||||
# if (defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN) || \
|
||||
|
||||
+6
-33
@@ -157,17 +157,6 @@ typedef uint32_t mrb_aspec;
|
||||
typedef struct mrb_irep mrb_irep;
|
||||
struct mrb_state;
|
||||
|
||||
/**
|
||||
* Function pointer type of custom allocator used in @see mrb_open_allocf.
|
||||
*
|
||||
* The function pointing it must behave similarly as realloc except:
|
||||
* - If ptr is NULL it must allocate new space.
|
||||
* - If size is zero, ptr must be freed.
|
||||
*
|
||||
* See @see mrb_default_allocf for the default implementation.
|
||||
*/
|
||||
typedef void* (*mrb_allocf) (struct mrb_state *mrb, void *ptr, size_t size, void *ud);
|
||||
|
||||
#ifndef MRB_FIXED_STATE_ATEXIT_STACK_SIZE
|
||||
#define MRB_FIXED_STATE_ATEXIT_STACK_SIZE 5
|
||||
#endif
|
||||
@@ -176,7 +165,8 @@ typedef struct {
|
||||
uint8_t n:4; /* (15=*) c=n|nk<<4 */
|
||||
uint8_t nk:4; /* (15=*) */
|
||||
uint8_t cci; /* called from C function */
|
||||
uint8_t vis; /* visibility in the current scope */
|
||||
uint8_t vis; /* 5(ZERO):1(separate module):2(method visibility) */
|
||||
/* under 3-bit flags are copied to env, and after that, env takes precedence */
|
||||
mrb_sym mid;
|
||||
const struct RProc *proc;
|
||||
struct RProc *blk;
|
||||
@@ -255,9 +245,6 @@ typedef void (*mrb_atexit_func)(struct mrb_state*);
|
||||
typedef struct mrb_state {
|
||||
struct mrb_jmpbuf *jmp;
|
||||
|
||||
mrb_allocf allocf; /* memory allocation function */
|
||||
void *allocf_ud; /* auxiliary data of allocf */
|
||||
|
||||
struct mrb_context *c;
|
||||
struct mrb_context *root_c;
|
||||
struct iv_tbl *globals; /* global variable table */
|
||||
@@ -1239,32 +1226,19 @@ MRB_API char* mrb_locale_from_utf8(const char *p, int len);
|
||||
*/
|
||||
MRB_API mrb_state* mrb_open(void);
|
||||
|
||||
/**
|
||||
* Create new mrb_state with custom allocators.
|
||||
*
|
||||
* @param f
|
||||
* Reference to the allocation function.
|
||||
* @param ud
|
||||
* User data will be passed to custom allocator f.
|
||||
* If user data isn't required just pass NULL.
|
||||
* @return
|
||||
* Pointer to the newly created mrb_state.
|
||||
*/
|
||||
MRB_API mrb_state* mrb_open_allocf(mrb_allocf f, void *ud);
|
||||
|
||||
/**
|
||||
* Create new mrb_state with just the mruby core
|
||||
*
|
||||
* @param f
|
||||
* Reference to the allocation function.
|
||||
* Use mrb_default_allocf for the default
|
||||
* Use mrb_basic_alloc_func for the default
|
||||
* @param ud
|
||||
* User data will be passed to custom allocator f.
|
||||
* If user data isn't required just pass NULL.
|
||||
* @return
|
||||
* Pointer to the newly created mrb_state.
|
||||
*/
|
||||
MRB_API mrb_state* mrb_open_core(mrb_allocf f, void *ud);
|
||||
MRB_API mrb_state* mrb_open_core(void);
|
||||
|
||||
/**
|
||||
* Closes and frees a mrb_state.
|
||||
@@ -1275,11 +1249,10 @@ MRB_API mrb_state* mrb_open_core(mrb_allocf f, void *ud);
|
||||
MRB_API void mrb_close(mrb_state *mrb);
|
||||
|
||||
/**
|
||||
* The default allocation function.
|
||||
* The memory allocation function. You can redefine this function for your own allocator.
|
||||
*
|
||||
* @see mrb_allocf
|
||||
*/
|
||||
MRB_API void* mrb_default_allocf(mrb_state*, void*, size_t, void*);
|
||||
MRB_API void* mrb_basic_alloc_func(void*, size_t);
|
||||
|
||||
MRB_API mrb_value mrb_top_self(mrb_state *mrb);
|
||||
|
||||
|
||||
@@ -50,8 +50,9 @@ enum mrb_special_consts {
|
||||
#define WORDBOX_FIXNUM_FLAG (1 << (WORDBOX_FIXNUM_BIT_POS - 1))
|
||||
#define WORDBOX_FIXNUM_MASK ((1 << WORDBOX_FIXNUM_BIT_POS) - 1)
|
||||
|
||||
#if defined(MRB_WORDBOX_NO_FLOAT_TRUNCATE)
|
||||
#if defined(MRB_WORDBOX_NO_FLOAT_TRUNCATE) || defined(MRB_NO_FLOAT)
|
||||
/* floats are allocated in heaps */
|
||||
#define WORDBOX_IMMEDIATE_MASK 0x03
|
||||
#define WORDBOX_SYMBOL_BIT_POS 2
|
||||
#define WORDBOX_SYMBOL_SHIFT WORDBOX_SYMBOL_BIT_POS
|
||||
#define WORDBOX_SYMBOL_FLAG (1 << (WORDBOX_SYMBOL_BIT_POS - 1))
|
||||
@@ -68,7 +69,9 @@ enum mrb_special_consts {
|
||||
#define WORDBOX_SYMBOL_MASK 0x1f
|
||||
#endif
|
||||
|
||||
#ifndef WORDBOX_IMMEDIATE_MASK
|
||||
#define WORDBOX_IMMEDIATE_MASK 0x07
|
||||
#endif
|
||||
|
||||
#define WORDBOX_SET_SHIFT_VALUE(o,n,v) \
|
||||
((o).w = (((uintptr_t)(v)) << WORDBOX_##n##_SHIFT) | WORDBOX_##n##_FLAG)
|
||||
@@ -107,7 +110,7 @@ enum mrb_special_consts {
|
||||
* undef : ...0001 0100
|
||||
* fixnum: ...IIII III1
|
||||
* symbol: ...SSSS SS10
|
||||
* object: ...PPPP P000 (any bits are 1)
|
||||
* object: ...PPPP PP00 (any bits are 1)
|
||||
*/
|
||||
typedef struct mrb_value {
|
||||
uintptr_t w;
|
||||
@@ -145,7 +148,11 @@ MRB_API mrb_value mrb_word_boxing_float_value(struct mrb_state*, mrb_float);
|
||||
#endif
|
||||
MRB_API mrb_value mrb_boxing_int_value(struct mrb_state*, mrb_int);
|
||||
|
||||
#if WORDBOX_IMMEDIATE_MASK == 0x3
|
||||
#define mrb_immediate_p(o) ((o).w & WORDBOX_IMMEDIATE_MASK || (o).w <= MRB_Qundef)
|
||||
#else
|
||||
#define mrb_immediate_p(o) ((o).w & WORDBOX_IMMEDIATE_MASK || (o).w == MRB_Qnil)
|
||||
#endif
|
||||
|
||||
#define mrb_ptr(o) mrb_val_union(o).p
|
||||
#define mrb_cptr(o) mrb_val_union(o).vp->p
|
||||
|
||||
@@ -41,8 +41,8 @@ typedef struct mrb_ccontext {
|
||||
MRB_API mrb_ccontext* mrb_ccontext_new(mrb_state *mrb);
|
||||
MRB_API void mrb_ccontext_free(mrb_state *mrb, mrb_ccontext *cxt);
|
||||
MRB_API const char *mrb_ccontext_filename(mrb_state *mrb, mrb_ccontext *c, const char *s);
|
||||
MRB_API void mrb_ccontext_partial_hook(mrb_state *mrb, mrb_ccontext *c, int (*partial_hook)(struct mrb_parser_state*), void*data);
|
||||
MRB_API void mrb_ccontext_cleanup_local_variables(mrb_state *mrb, mrb_ccontext *c);
|
||||
MRB_API void mrb_ccontext_partial_hook(mrb_ccontext *c, int (*partial_hook)(struct mrb_parser_state*), void*data);
|
||||
MRB_API void mrb_ccontext_cleanup_local_variables(mrb_ccontext *c);
|
||||
|
||||
/* compatibility macros */
|
||||
#define mrbc_context mrb_ccontext
|
||||
@@ -123,7 +123,7 @@ struct mrb_parser_heredoc_info {
|
||||
/* parser structure */
|
||||
struct mrb_parser_state {
|
||||
mrb_state *mrb;
|
||||
struct mrb_mempool *pool;
|
||||
mempool *pool;
|
||||
mrb_ast_node *cells;
|
||||
const char *s, *send;
|
||||
#ifndef MRB_NO_STDIO
|
||||
|
||||
@@ -28,6 +28,7 @@ mrb_method_t mrb_vm_find_method(mrb_state *mrb, struct RClass *c, struct RClass
|
||||
mrb_value mrb_mod_const_missing(mrb_state *mrb, mrb_value mod);
|
||||
mrb_value mrb_const_missing(mrb_state *mrb, mrb_value mod, mrb_sym sym);
|
||||
size_t mrb_class_mt_memsize(mrb_state*, struct RClass*);
|
||||
mrb_value mrb_obj_extend(mrb_state*, mrb_value obj);
|
||||
#endif
|
||||
|
||||
mrb_value mrb_obj_equal_m(mrb_state *mrb, mrb_value);
|
||||
@@ -60,6 +61,7 @@ void mrb_exc_mesg_set(mrb_state *mrb, struct RException *exc, mrb_value mesg);
|
||||
mrb_value mrb_exc_mesg_get(mrb_state *mrb, struct RException *exc);
|
||||
mrb_value mrb_f_raise(mrb_state*, mrb_value);
|
||||
mrb_value mrb_make_exception(mrb_state *mrb, mrb_value exc, mrb_value mesg);
|
||||
mrb_value mrb_exc_get_output(mrb_state *mrb, struct RObject *exc);
|
||||
|
||||
struct RBacktrace {
|
||||
MRB_OBJECT_HEADER;
|
||||
@@ -82,6 +84,7 @@ size_t mrb_hash_memsize(mrb_value obj);
|
||||
size_t mrb_gc_mark_hash(mrb_state*, struct RHash*);
|
||||
void mrb_gc_free_hash(mrb_state*, struct RHash*);
|
||||
mrb_value mrb_hash_first_key(mrb_state*, mrb_value);
|
||||
uint32_t mrb_obj_hash_code(mrb_state *mrb, mrb_value key);
|
||||
|
||||
/* irep */
|
||||
struct mrb_insn_data mrb_decode_insn(const mrb_code *pc);
|
||||
@@ -171,16 +174,16 @@ void mrb_vm_special_set(mrb_state*, mrb_sym, mrb_value);
|
||||
mrb_value mrb_vm_cv_get(mrb_state*, mrb_sym);
|
||||
void mrb_vm_cv_set(mrb_state*, mrb_sym, mrb_value);
|
||||
mrb_value mrb_vm_const_get(mrb_state*, mrb_sym);
|
||||
void mrb_vm_const_set(mrb_state*, mrb_sym, mrb_value);
|
||||
size_t mrb_obj_iv_tbl_memsize(mrb_value);
|
||||
mrb_value mrb_obj_iv_inspect(mrb_state*, struct RObject*);
|
||||
void mrb_obj_iv_set_force(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
|
||||
mrb_value mrb_mod_constants(mrb_state *mrb, mrb_value mod);
|
||||
mrb_value mrb_mod_const_at(mrb_state *mrb, struct RClass *c, mrb_value ary);
|
||||
mrb_value mrb_f_global_variables(mrb_state *mrb, mrb_value self);
|
||||
mrb_value mrb_obj_instance_variables(mrb_state*, mrb_value);
|
||||
mrb_value mrb_mod_class_variables(mrb_state*, mrb_value);
|
||||
mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym);
|
||||
mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym);
|
||||
mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass *c, mrb_sym sym);
|
||||
mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass *c, mrb_sym sym);
|
||||
mrb_bool mrb_ident_p(const char *s, mrb_int len);
|
||||
mrb_value mrb_exc_const_get(mrb_state *mrb, mrb_sym sym);
|
||||
|
||||
@@ -191,6 +194,10 @@ size_t mrb_gc_mark_iv(mrb_state*, struct RObject*);
|
||||
void mrb_gc_free_iv(mrb_state*, struct RObject*);
|
||||
|
||||
/* VM */
|
||||
#define MRB_CI_VISIBILITY(ci) MRB_FLAGS_GET((ci)->vis, 0, 2)
|
||||
#define MRB_CI_SET_VISIBILITY(ci, visi) MRB_FLAGS_SET((ci)->vis, 0, 2, visi)
|
||||
#define MRB_CI_VISIBILITY_BREAK_P(ci) MRB_FLAG_CHECK((ci)->vis, 2)
|
||||
#define MRB_CI_SET_VISIBILITY_BREAK(ci) MRB_FLAG_ON((ci)->vis, 2)
|
||||
mrb_int mrb_ci_bidx(mrb_callinfo *ci);
|
||||
mrb_int mrb_ci_nregs(mrb_callinfo *ci);
|
||||
mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, const struct RProc *p);
|
||||
@@ -198,6 +205,7 @@ mrb_value mrb_obj_instance_eval(mrb_state*, mrb_value);
|
||||
mrb_value mrb_object_exec(mrb_state *mrb, mrb_value self, struct RClass *target_class);
|
||||
mrb_value mrb_mod_module_eval(mrb_state*, mrb_value);
|
||||
mrb_value mrb_f_send(mrb_state *mrb, mrb_value self);
|
||||
mrb_value mrb_f_public_send(mrb_state *mrb, mrb_value self);
|
||||
|
||||
#ifdef MRB_USE_BIGINT
|
||||
mrb_value mrb_bint_new_int(mrb_state *mrb, mrb_int x);
|
||||
@@ -247,6 +255,7 @@ void mrb_gc_free_bint(mrb_state *mrb, struct RBasic *x);
|
||||
void mrb_bint_copy(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||
size_t mrb_bint_memsize(mrb_value x);
|
||||
mrb_value mrb_bint_hash(mrb_state *mrb, mrb_value x);
|
||||
mrb_value mrb_bint_sqrt(mrb_state *mrb, mrb_value x);
|
||||
#endif
|
||||
|
||||
#endif /* MRUBY_INTERNAL_H */
|
||||
|
||||
+21
-1
@@ -21,7 +21,7 @@ typedef uint32_t khint_t;
|
||||
typedef khint_t khiter_t;
|
||||
|
||||
#ifndef KHASH_DEFAULT_SIZE
|
||||
# define KHASH_DEFAULT_SIZE 32
|
||||
# define KHASH_DEFAULT_SIZE 8
|
||||
#endif
|
||||
#define KHASH_MIN_SIZE 8
|
||||
|
||||
@@ -281,4 +281,24 @@ typedef const char *kh_cstr_t;
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
/**
|
||||
* Macro for iterating over all elements in a khash.
|
||||
*
|
||||
* Usage:
|
||||
* KHASH_FOREACH(mrb, kh, k) {
|
||||
* // k is the khiter_t iterator
|
||||
* // Access the key with kh_key(kh, k)
|
||||
* // Access the value with kh_val(kh, k) if applicable
|
||||
* // Your code here
|
||||
* }
|
||||
*
|
||||
* @param mrb The mrb_state
|
||||
* @param kh The khash to iterate over
|
||||
* @param k The name to use for the khiter_t iterator variable
|
||||
*/
|
||||
#define KHASH_FOREACH(mrb, kh, k) \
|
||||
if (kh) \
|
||||
for (khiter_t k = kh_begin(kh); k != kh_end(kh); k++) \
|
||||
if (kh_exist(kh, k))
|
||||
|
||||
#endif /* MRUBY_KHASH_H */
|
||||
|
||||
+12
-6
@@ -5,9 +5,15 @@
|
||||
*/
|
||||
|
||||
/* memory pool implementation */
|
||||
typedef struct mrb_mempool mrb_mempool;
|
||||
MRB_API struct mrb_mempool* mrb_mempool_open(mrb_state*);
|
||||
MRB_API void mrb_mempool_close(struct mrb_mempool*);
|
||||
MRB_API void* mrb_mempool_alloc(struct mrb_mempool*, size_t);
|
||||
MRB_API void* mrb_mempool_realloc(struct mrb_mempool*, void*, size_t oldlen, size_t newlen);
|
||||
MRB_API mrb_bool mrb_mempool_can_realloc(struct mrb_mempool*, void*, size_t);
|
||||
typedef struct mempool mempool;
|
||||
MRB_API struct mempool* mempool_open(void);
|
||||
MRB_API void mempool_close(struct mempool*);
|
||||
MRB_API void* mempool_alloc(struct mempool*, size_t);
|
||||
MRB_API void* mempool_realloc(struct mempool*, void*, size_t oldlen, size_t newlen);
|
||||
|
||||
/* compatibility layer */
|
||||
typedef struct mempool mrb_mempool;
|
||||
#define mrb_mempool_open(m) mempool_open()
|
||||
#define mrb_mempool_close(m) mempool_close(m)
|
||||
#define mrb_mempool_alloc(m, size) mempool_alloc((m),(size))
|
||||
#define mrb_mempool_realloc(m, ptr, oldlen, newlen) mempool_realloc((m),(ptr),(oldlen),(newlen))
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
struct RClass *c; \
|
||||
struct RBasic *gcnext; \
|
||||
enum mrb_vtype tt:8; \
|
||||
unsigned int gccolor:3; \
|
||||
unsigned int gc_color:3; \
|
||||
unsigned int frozen:1; \
|
||||
uint32_t flags:20
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
* For `MRB_OPSYM`, specify the names corresponding to operators (see
|
||||
* `MRuby::Presym::OPERATORS` in `lib/mruby/presym.rb` for the names that
|
||||
* can be specified for it). Other than that, describe only word characters
|
||||
* excluding leading and ending punctuations.
|
||||
* excluding leading and ending punctuation.
|
||||
*
|
||||
* These macros are expanded to `mrb_intern_lit` if presym is disabled,
|
||||
* therefore the mruby state variable is required. The above macros can be
|
||||
|
||||
@@ -30,13 +30,17 @@ struct REnv {
|
||||
mrb_sym mid;
|
||||
};
|
||||
|
||||
/* flags (21bits): 5(ZERO):8(cioff/bidx):8(stack_len) */
|
||||
/* flags (20bits): 1(ZERO):1(separate module):2(visibility):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_CLOSE(e) ((e)->cxt = NULL)
|
||||
#define MRB_ENV_ONSTACK_P(e) ((e)->cxt != NULL)
|
||||
#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))
|
||||
#define MRB_ENV_SET_VISIBILITY(e, vis) MRB_FLAGS_SET((e)->flags, 16, 2, vis)
|
||||
#define MRB_ENV_VISIBILITY(e) MRB_FLAGS_GET((e)->flags, 16, 2)
|
||||
#define MRB_ENV_VISIBILITY_BREAK_P(e) MRB_FLAG_CHECK((e)->flags, 18)
|
||||
#define MRB_ENV_COPY_FLAGS_FROM_CI(e, ci) MRB_FLAGS_SET((e)->flags, 16, 3, (ci)->vis)
|
||||
|
||||
/*
|
||||
* Returns TRUE on success.
|
||||
@@ -127,8 +131,8 @@ MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx);
|
||||
#define MRB_METHOD_PROC(m) ((m).as.proc)
|
||||
#define MRB_METHOD_UNDEF_P(m) ((m).as.proc==NULL)
|
||||
#define MRB_METHOD_VISIBILITY(m) ((m).flags & MRB_METHOD_VISIBILITY_MASK)
|
||||
#define MRB_SET_VISIBILITY(f,v) ((f)=(((f)&~MRB_METHOD_VISIBILITY_MASK)|(v)))
|
||||
#define MRB_METHOD_SET_VISIBILITY(m,v) MRB_SET_VISIBILITY((m).flags,(v))
|
||||
#define MRB_SET_VISIBILITY_FLAGS(f,v) ((f)=(((f)&~MRB_METHOD_VISIBILITY_MASK)|(v)))
|
||||
#define MRB_METHOD_SET_VISIBILITY(m,v) MRB_SET_VISIBILITY_FLAGS((m).flags,(v))
|
||||
|
||||
#define MRB_METHOD_CFUNC_P(m) (MRB_METHOD_FUNC_P(m) || (MRB_METHOD_PROC(m)?(MRB_PROC_CFUNC_P(MRB_METHOD_PROC(m))):FALSE))
|
||||
/* use MRB_METHOD_CFUNC(m) only when MRB_METHOD_CFUNC_P(m) is true */
|
||||
|
||||
@@ -90,7 +90,7 @@ struct RStringEmbed {
|
||||
# define RSTR_WRITE_SINGLE_BYTE_FLAG(s, v) (RSTR_UNSET_SINGLE_BYTE_FLAG(s), (s)->flags |= v)
|
||||
# define RSTR_COPY_SINGLE_BYTE_FLAG(dst, src) RSTR_WRITE_SINGLE_BYTE_FLAG(dst, RSTR_SINGLE_BYTE_P(src))
|
||||
#else
|
||||
# define RSTR_SINGLE_BYTE_P(s) (void)1
|
||||
# define RSTR_SINGLE_BYTE_P(s) TRUE
|
||||
# define RSTR_SET_SINGLE_BYTE_FLAG(s) (void)0
|
||||
# define RSTR_UNSET_SINGLE_BYTE_FLAG(s) (void)0
|
||||
# define RSTR_WRITE_SINGLE_BYTE_FLAG(s, v) (void)0
|
||||
|
||||
@@ -94,11 +94,14 @@ struct mrb_state;
|
||||
# define MRB_PRIx PRIx32
|
||||
#endif
|
||||
|
||||
#ifdef MRB_ENDIAN_BIG
|
||||
# define MRB_ENDIAN_LOHI(a,b) a b
|
||||
#else
|
||||
# define MRB_ENDIAN_LOHI(a,b) b a
|
||||
#endif
|
||||
#define MRB_FLAGS_MASK(shift, width) (~(~0U << (width)) << (shift))
|
||||
#define MRB_FLAGS_GET(b, s, w) (((b) >> (s)) & MRB_FLAGS_MASK(0, w))
|
||||
#define MRB_FLAGS_SET(b, s, w, n) ((b) = MRB_FLAGS_ZERO(b, s, w) | MRB_FLAGS_MAKE(s, w, n))
|
||||
#define MRB_FLAGS_ZERO(b, s, w) ((b) & ~MRB_FLAGS_MASK(s, w))
|
||||
#define MRB_FLAGS_MAKE(s, w, n) (((n) & MRB_FLAGS_MASK(0, w)) << (s))
|
||||
#define MRB_FLAG_ON(b, s) ((b) |= MRB_FLAGS_MASK(s, 1))
|
||||
#define MRB_FLAG_OFF(b, s) ((b) &= ~MRB_FLAGS_MASK(s, 1))
|
||||
#define MRB_FLAG_CHECK(b, s) (!!((b) & MRB_FLAGS_MASK(s, 1)))
|
||||
|
||||
MRB_API mrb_bool mrb_read_int(const char *p, const char *e, char **endp, mrb_int *np);
|
||||
/* obsolete; do not use mrb_int_read() */
|
||||
|
||||
@@ -57,7 +57,7 @@ MRB_BEGIN_DECL
|
||||
/*
|
||||
* Patch level string. (optional)
|
||||
*/
|
||||
#define MRUBY_PATCHLEVEL_STR "RC"
|
||||
#define MRUBY_PATCHLEVEL_STR ""
|
||||
|
||||
#ifndef MRUBY_PATCHLEVEL_STR
|
||||
# if MRUBY_PATCHLEVEL < 0
|
||||
@@ -85,12 +85,12 @@ MRB_BEGIN_DECL
|
||||
/*
|
||||
* Release month.
|
||||
*/
|
||||
#define MRUBY_RELEASE_MONTH 3
|
||||
#define MRUBY_RELEASE_MONTH 4
|
||||
|
||||
/*
|
||||
* Release day.
|
||||
*/
|
||||
#define MRUBY_RELEASE_DAY 10
|
||||
#define MRUBY_RELEASE_DAY 20
|
||||
|
||||
/*
|
||||
* Release date as a string.
|
||||
|
||||
@@ -266,7 +266,7 @@ module MRuby
|
||||
def initialize(build)
|
||||
super
|
||||
@command = 'gperf'
|
||||
@compile_options = %q[-L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" "%{infile}" > "%{outfile}"]
|
||||
@compile_options = %q[-L ANSI-C -C -j1 -i 1 -o -t -N mrb_reserved_word -k"1,3,$" "%{infile}" > "%{outfile}"]
|
||||
end
|
||||
|
||||
def run(outfile, infile)
|
||||
|
||||
@@ -7,8 +7,6 @@ MRuby::GemBox.new do |conf|
|
||||
# Use Rational/Complex numbers
|
||||
conf.gem :core => "mruby-rational"
|
||||
conf.gem :core => "mruby-complex"
|
||||
# Use Complex math functions in CMath module
|
||||
conf.gem :core => "mruby-cmath"
|
||||
# Use Multi-precision Integer
|
||||
conf.gem :core => "mruby-bigint"
|
||||
end
|
||||
|
||||
@@ -10,6 +10,12 @@ MRuby::GemBox.new do |conf|
|
||||
# Use eval()
|
||||
conf.gem :core => "mruby-eval"
|
||||
|
||||
# Use binding()
|
||||
conf.gem :core => "mruby-binding"
|
||||
|
||||
# Use Proc#binding()
|
||||
conf.gem :core => "mruby-proc-binding"
|
||||
|
||||
# Use mruby-compiler to build other mrbgems
|
||||
conf.gem :core => "mruby-compiler"
|
||||
end
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
# mruby-array-ext
|
||||
|
||||
This mrbgem extends the `Array` class in mruby, providing a rich set of additional methods for array manipulation. These extensions enhance mruby's built-in array capabilities, offering functionalities commonly found in standard Ruby.
|
||||
|
||||
## Functionality
|
||||
|
||||
The `mruby-array-ext` gem adds the following methods to the `Array` class:
|
||||
|
||||
### Set Operations
|
||||
|
||||
- `uniq`: Returns a new array by removing duplicate values.
|
||||
- `uniq!`: Removes duplicate elements from self. Returns `nil` if no changes are made.
|
||||
- `-` (difference): Returns a new array that is a copy of the original array, removing any items that also appear in another array.
|
||||
- `|` (union): Returns a new array by joining this array with another array, removing duplicates.
|
||||
- `&` (intersection): Returns a new array containing elements common to two arrays, with no duplicates.
|
||||
- `difference`: Returns a new array that is a copy of the original array, removing all occurrences of any item that also appear in the specified other arrays.
|
||||
- `union`: Returns a new array by joining this array with other arrays, removing duplicates.
|
||||
- `intersection`: Returns a new array containing elements common to this array and specified other arrays, removing duplicates.
|
||||
- `intersect?`: Returns `true` if the array and another array have at least one element in common.
|
||||
|
||||
### Element Manipulation and Access
|
||||
|
||||
- `flatten`: Returns a new array that is a one-dimensional flattening of self.
|
||||
- `flatten!`: Flattens self in place. Returns `nil` if no modifications were made.
|
||||
- `fetch`: Tries to return the element at a given position. Throws an `IndexError` if the index is out of bounds, unless a default value or block is provided.
|
||||
- `fill`: Sets selected elements of self to a given object or the result of a block.
|
||||
- `compact`: Returns a copy of self with all `nil` elements removed.
|
||||
- `compact!`: Removes `nil` elements from self. Returns `nil` if no changes were made.
|
||||
- `rotate(count=1)`: Returns a new array by rotating self so that the element at `count` is the first element.
|
||||
- `rotate!(count=1)`: Rotates self in place.
|
||||
- `insert(index, obj...)`: Inserts the given values before the element with the given index.
|
||||
- `slice!(index)` / `slice!(start, length)` / `slice!(range)`: Deletes element(s) given by an index or range and returns the deleted object(s).
|
||||
- `at(index)`: Returns the element at `index`. Returns `nil` if the index is out of range.
|
||||
- `dig(idx, ...)`: Extracts a nested value specified by a sequence of indices.
|
||||
- `fetch_values(idx, ...)`: Returns an array containing the values associated with the given indexes. Raises `IndexError` if an index is not found, unless a block is provided.
|
||||
- `values_at(selector, ...)`: Returns an array containing the elements corresponding to the given selector(s).
|
||||
|
||||
### Searching and Comparison
|
||||
|
||||
- `assoc(obj)`: Searches through an array of arrays, comparing `obj` with the first element of each contained array. Returns the first matching contained array or `nil`.
|
||||
- `rassoc(obj)`: Searches through an array of arrays, comparing `obj` with the second element of each contained array. Returns the first matching contained array or `nil`.
|
||||
- `bsearch { |x| block }`: Finds a value from the array which meets the given condition using binary search.
|
||||
- `bsearch_index { |x| block }`: Finds the index of a value from the array which meets the given condition using binary search.
|
||||
|
||||
### Iterators and Combinatorics
|
||||
|
||||
- `reverse_each`: Calls the given block for each element in reverse order.
|
||||
- `permutation(n=self.size)`: Yields all permutations of length `n` of the elements of the array.
|
||||
- `combination(n)`: Yields all combinations of length `n` of elements from the array.
|
||||
- `product(*arys)`: Returns an array of all combinations of elements from self and the given arrays.
|
||||
- `repeated_combination(n)`: Yields all repeated combinations of length `n`.
|
||||
- `repeated_permutation(n)`: Yields all repeated permutations of length `n`.
|
||||
|
||||
### Conversions and Other Utilities
|
||||
|
||||
- `to_h`: Returns the result of interpreting the array as an array of `[key, value]` pairs.
|
||||
- `transpose`: Assumes that self is an array of arrays and transposes the rows and columns.
|
||||
|
||||
### Filtering
|
||||
|
||||
- `delete_if { |item| block }`: Deletes every element of self for which the block evaluates to `true`.
|
||||
- `reject! { |item| block }`: Equivalent to `delete_if`, but returns `nil` if no changes were made.
|
||||
- `keep_if { |item| block }`: Deletes every element of self for which the given block evaluates to `false`.
|
||||
- `select! { |item| block }`: Deletes elements for which the block returns a `false` value. Returns `self` if changes were made, otherwise `nil`.
|
||||
|
||||
### Aliases
|
||||
|
||||
- `append` (alias for `push`)
|
||||
- `prepend` (alias for `unshift`)
|
||||
- `filter!` (alias for `select!`)
|
||||
|
||||
## Usage
|
||||
|
||||
To use this gem, add it to your `build_config.rb` or `mrbgem.rake` file. For detailed examples of each method, please refer to the comments in the source code (`mrblib/array.rb` and `src/array.c`).
|
||||
|
||||
Example:
|
||||
|
||||
```ruby
|
||||
a = [1, 2, 2, 3, nil, 4]
|
||||
p a.compact #=> [1, 2, 2, 3, 4]
|
||||
p a.uniq #=> [1, 2, 3, nil, 4]
|
||||
|
||||
b = ["a", "b", "c"]
|
||||
p b.rotate #=> ["b", "c", "a"]
|
||||
```
|
||||
|
||||
This gem is part of the mruby project.
|
||||
@@ -50,7 +50,7 @@ I hereby place this file and all of FGMP in the public domain.
|
||||
|
||||
Thanks to Paul Rouse <par@r-cube.demon.co.uk> for changes to get fgmp
|
||||
to work on a 286 MS-DOS compiler, the functions mpz_sqrt and
|
||||
mpz_sqrtrem, plus other general bug fixes.
|
||||
mpz_sqrtrem, plus other general bugfixes.
|
||||
|
||||
Thanks also to Erick Gallesio <eg@kaolin.unice.fr> for a fix
|
||||
to mpz_init_set_str
|
||||
|
||||
@@ -1,7 +1,44 @@
|
||||
# Multi-precision Integer extension for mruby
|
||||
# mruby-bigint
|
||||
|
||||
mruby-bigint is an mrbgem that provides multi-precision integer (BigInt) support for mruby. It allows you to work with integers that are larger than the standard Integer type can handle.
|
||||
|
||||
This extension uses fgmp, which is a public domain implementation of a subset of the GNU gmp library by Mark Henderson <markh@wimsey.bc.ca>.
|
||||
But it's heavily modified to fit with mruby. You can get the original source code from <https://github.com/deischi/fgmp.git>.
|
||||
You can read the original README for fgmp in [README-fgmp.md](README-fgmp.md).
|
||||
|
||||
If you want to create your own Multi-precision Integer GEM, see [examples/mrbgems/mruby-YOUR-bigint/TODO-HINT.md](../../examples/mrbgems/mruby-YOUR-bigint/TODO-HINT.md).
|
||||
|
||||
## Features
|
||||
|
||||
- Basic arithmetic operations: `+`, `-`, `*`, `/`, `%`
|
||||
- Power operation: `**`
|
||||
- Modular exponentiation
|
||||
- Bitwise operations: `&`, `|`, `^`, `<<`, `>>`
|
||||
- Comparison: `<=>`
|
||||
- Conversion to and from strings: `to_s`, `String#to_i` (with base)
|
||||
- Square root
|
||||
- Greatest Common Divisor (GCD) (available if `MRB_USE_RATIONAL` is defined)
|
||||
|
||||
## Usage
|
||||
|
||||
Here are some simple examples of how to use mruby-bigint:
|
||||
|
||||
```ruby
|
||||
# Creating BigInts
|
||||
a = BigInt(12345678901234567890)
|
||||
b = "98765432109876543210".to_i(10) # Specify base 10 for string conversion
|
||||
|
||||
# Arithmetic operations
|
||||
c = a + b
|
||||
puts c.to_s # Output: 111111111011111111100
|
||||
|
||||
d = a * 2
|
||||
puts d.to_s # Output: 24691357802469135780
|
||||
|
||||
# Comparison
|
||||
puts a <=> b # Output: -1
|
||||
```
|
||||
|
||||
## fgmp Dependency
|
||||
|
||||
mruby-bigint depends on fgmp. For more information about fgmp, please see [README-fgmp.md](README-fgmp.md).
|
||||
|
||||
@@ -882,7 +882,7 @@ mpz_get_str(mrb_state *mrb, char *s, mrb_int sz, mrb_int base, mpz_t *x)
|
||||
if ((base & (base - 1)) == 0) { // base is a power of 2
|
||||
int shift = 0;
|
||||
while ((1 << shift) < base) shift++;
|
||||
mp_limb mask = base - 1;
|
||||
mp_limb mask = (mp_limb)base - 1;
|
||||
mp_dbl_limb value = 0;
|
||||
int bits = 0;
|
||||
|
||||
@@ -1246,6 +1246,61 @@ mpz_gcd(mrb_state *mrb, mpz_t *gg, mpz_t *aa, mpz_t *bb)
|
||||
}
|
||||
#endif
|
||||
|
||||
static size_t
|
||||
mpz_bits(const mpz_t *x)
|
||||
{
|
||||
if (x->sz == 0 || x->sn == 0) return 0;
|
||||
|
||||
size_t limb_bits = sizeof(mp_limb) * 8;
|
||||
|
||||
// Get the most significant limb
|
||||
size_t i = x->sz - 1;
|
||||
mp_limb high = x->p[i];
|
||||
|
||||
// Number of bits = total full limbs + significant bits in top limb
|
||||
return i * limb_bits + (limb_bits - lzb(high));
|
||||
}
|
||||
|
||||
static void
|
||||
mpz_sqrt(mrb_state *mrb, mpz_t *z, mpz_t *x)
|
||||
{
|
||||
mrb_assert(x->sn >= 0);
|
||||
|
||||
if (x->sz == 0) {
|
||||
// sqrt(0) = 0
|
||||
z->sn = 0;
|
||||
z->sz = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Estimate initial value: 1 << (bit_length(x) / 2)
|
||||
size_t xbits = mpz_bits(x);
|
||||
size_t sbit = (xbits + 1) / 2;
|
||||
mpz_t s, t;
|
||||
mpz_init_set_int(mrb, &s, 1);
|
||||
mpz_mul_2exp(mrb, &s, &s, sbit);
|
||||
|
||||
mpz_init(mrb, &t);
|
||||
|
||||
// Iteratively refine s using Newton-Raphson method:
|
||||
// s = (s + x / s) / 2
|
||||
for (;;) {
|
||||
mpz_mdiv(mrb, &t, x, &s); // t = x / s
|
||||
mpz_add(mrb, &t, &t, &s); // t = s + x/s
|
||||
mpz_div_2exp(mrb, &t, &t, 1); // t = (s + x/s) / 2
|
||||
|
||||
if (mpz_cmp(mrb, &t, &s) >= 0) {
|
||||
// Converged: t >= s
|
||||
break;
|
||||
}
|
||||
|
||||
mpz_set(mrb, &s, &t);
|
||||
}
|
||||
|
||||
mpz_move(mrb, z, &s);
|
||||
mpz_clear(mrb, &t);
|
||||
}
|
||||
|
||||
/* --- mruby functions --- */
|
||||
/* initialize mpz_t from RBigint (not need to clear) */
|
||||
static void
|
||||
@@ -1861,7 +1916,7 @@ mrb_bint_to_s(mrb_state *mrb, mrb_value x, mrb_int base)
|
||||
return mrb_str_new_lit(mrb, "0");
|
||||
}
|
||||
size_t len = mpz_sizeinbase(&a, (int)base);
|
||||
if (MRB_INT_MAX-2 < len) {
|
||||
if (sizeof(size_t) >= sizeof(mrb_int) && MRB_INT_MAX-2 < len) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "too long string from Integer");
|
||||
}
|
||||
mrb_value str = mrb_str_new(mrb, NULL, len+2);
|
||||
@@ -2014,6 +2069,23 @@ mrb_bint_memsize(mrb_value x)
|
||||
return z.sz * sizeof(mp_limb);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_bint_sqrt(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mpz_t a;
|
||||
|
||||
bint_as_mpz(RBIGINT(x), &a);
|
||||
if (a.sn < 0) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "square root of negative number");
|
||||
}
|
||||
|
||||
mpz_t z;
|
||||
mpz_init(mrb, &z);
|
||||
mpz_sqrt(mrb, &z, &a);
|
||||
|
||||
return bint_norm(mrb, bint_new(mrb, &z));
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_bint_hash(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* I'm already aware that fgmp is considerably slower than gmp
|
||||
*
|
||||
* CREDITS:
|
||||
* Paul Rouse <par@r-cube.demon.co.uk> - generic bug fixes, mpz_sqrt and
|
||||
* Paul Rouse <par@r-cube.demon.co.uk> - generic bugfixes, mpz_sqrt and
|
||||
* mpz_sqrtrem, and modifications to get fgmp to compile on a system
|
||||
* with int and long of different sizes (specifically MS-DOS,286 compiler)
|
||||
* Also see the file "notes" included with the fgmp distribution, for
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <mruby/error.h>
|
||||
#include <mruby/numeric.h>
|
||||
#include <mruby/string.h>
|
||||
#include <mruby/internal.h>
|
||||
#include <mruby/presym.h>
|
||||
#include "apiprint.h"
|
||||
|
||||
@@ -70,12 +71,15 @@ mrb_debug_eval(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t
|
||||
|
||||
v = mrb_funcall_argv(mrb, recv, MRB_SYM(instance_eval), 1, &ruby_code);
|
||||
}
|
||||
|
||||
if (exc) {
|
||||
*exc = mrb_obj_is_kind_of(mrb, v, E_EXCEPTION);
|
||||
mrb_bool is_exc = mrb_obj_is_kind_of(mrb, v, E_EXCEPTION);
|
||||
if (is_exc) {
|
||||
s = mrb_exc_get_output(mrb, mrb_obj_ptr(v));
|
||||
}
|
||||
else {
|
||||
s = mrb_inspect(mrb, v);
|
||||
}
|
||||
|
||||
s = mrb_inspect(mrb, v);
|
||||
if (exc) *exc = is_exc;
|
||||
|
||||
/* enable code_fetch_hook */
|
||||
mrb->code_fetch_hook = tmp;
|
||||
|
||||
@@ -112,19 +112,17 @@ get_history_path(mrb_state *mrb)
|
||||
#endif
|
||||
|
||||
static void
|
||||
p(mrb_state *mrb, mrb_value obj, int prompt)
|
||||
p(mrb_state *mrb, mrb_value obj)
|
||||
{
|
||||
mrb_value val;
|
||||
char* msg;
|
||||
|
||||
val = mrb_funcall_argv(mrb, obj, MRB_SYM(inspect), 0, NULL);
|
||||
if (prompt) {
|
||||
if (!mrb->exc) {
|
||||
fputs(" => ", stdout);
|
||||
}
|
||||
else {
|
||||
val = mrb_funcall_id(mrb, mrb_obj_value(mrb->exc), MRB_SYM(inspect), 0);
|
||||
}
|
||||
if (!mrb->exc) {
|
||||
fputs(" => ", stdout);
|
||||
}
|
||||
else {
|
||||
val = mrb_exc_get_output(mrb, mrb->exc);
|
||||
}
|
||||
if (!mrb_string_p(val)) {
|
||||
val = mrb_obj_as_string(mrb, obj);
|
||||
@@ -135,6 +133,22 @@ p(mrb_state *mrb, mrb_value obj, int prompt)
|
||||
putc('\n', stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
p_error(mrb_state *mrb, struct RObject* exc)
|
||||
{
|
||||
mrb_value val;
|
||||
char* msg;
|
||||
|
||||
val = mrb_exc_get_output(mrb, exc);
|
||||
if (!mrb_string_p(val)) {
|
||||
val = mrb_obj_as_string(mrb, val);
|
||||
}
|
||||
msg = mrb_locale_from_utf8(RSTRING_PTR(val), (int)RSTRING_LEN(val));
|
||||
fwrite(msg, strlen(msg), 1, stdout);
|
||||
mrb_locale_free(msg);
|
||||
putc('\n', stdout);
|
||||
}
|
||||
|
||||
/* Guess if the user might want to enter more
|
||||
* or if they wants an evaluation of their code now */
|
||||
static mrb_bool
|
||||
@@ -517,7 +531,7 @@ main(int argc, char **argv)
|
||||
mrb_load_file_cxt(mrb, lfp, cxt);
|
||||
fclose(lfp);
|
||||
mrb_vm_ci_env_clear(mrb, mrb->c->cibase);
|
||||
mrb_ccontext_cleanup_local_variables(mrb, cxt);
|
||||
mrb_ccontext_cleanup_local_variables(cxt);
|
||||
}
|
||||
|
||||
#ifndef MRB_NO_MIRB_UNDERSCORE
|
||||
@@ -593,7 +607,9 @@ main(int argc, char **argv)
|
||||
}
|
||||
strcpy(last_code_line, line);
|
||||
strcat(last_code_line, "\n");
|
||||
MIRB_ADD_HISTORY(line);
|
||||
if (strlen(line) > 0) {
|
||||
MIRB_ADD_HISTORY(line);
|
||||
}
|
||||
MIRB_LINE_FREE(line);
|
||||
#endif
|
||||
|
||||
@@ -672,7 +688,7 @@ main(int argc, char **argv)
|
||||
/* did an exception occur? */
|
||||
if (mrb->exc) {
|
||||
MRB_EXC_CHECK_EXIT(mrb, mrb->exc);
|
||||
p(mrb, mrb_obj_value(mrb->exc), 0);
|
||||
p_error(mrb, mrb->exc);
|
||||
mrb->exc = 0;
|
||||
}
|
||||
else {
|
||||
@@ -680,7 +696,7 @@ main(int argc, char **argv)
|
||||
if (!mrb_respond_to(mrb, result, MRB_SYM(inspect))){
|
||||
result = mrb_any_to_s(mrb, result);
|
||||
}
|
||||
p(mrb, result, 1);
|
||||
p(mrb, result);
|
||||
#ifndef MRB_NO_MIRB_UNDERSCORE
|
||||
*(mrb->c->ci->stack + 1) = result;
|
||||
#endif
|
||||
|
||||
@@ -26,7 +26,7 @@ struct mrbc_args {
|
||||
mrb_bool verbose : 1;
|
||||
mrb_bool no_ext_ops : 1;
|
||||
mrb_bool no_optimize : 1;
|
||||
uint8_t flags : 2;
|
||||
uint8_t flags : 3;
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -245,7 +245,7 @@ load_file(mrb_state *mrb, struct mrbc_args *args)
|
||||
args->idx++;
|
||||
if (args->idx < args->argc) {
|
||||
need_close = FALSE;
|
||||
mrb_ccontext_partial_hook(mrb, c, partial_hook, (void*)args);
|
||||
mrb_ccontext_partial_hook(c, partial_hook, (void*)args);
|
||||
}
|
||||
|
||||
result = mrb_load_file_cxt(mrb, infile, c);
|
||||
@@ -286,7 +286,7 @@ dump_file(mrb_state *mrb, FILE *wfp, const char *outfile, const struct RProc *pr
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
mrb_state *mrb = mrb_open_core(NULL, NULL);
|
||||
mrb_state *mrb = mrb_open_core();
|
||||
int n, result;
|
||||
struct mrbc_args args;
|
||||
FILE *wfp;
|
||||
|
||||
@@ -339,10 +339,10 @@ main(int argc, char **argv)
|
||||
}
|
||||
fclose(lfp);
|
||||
mrb_vm_ci_env_clear(mrb, mrb->c->cibase);
|
||||
mrb_ccontext_cleanup_local_variables(mrb, c);
|
||||
mrb_ccontext_cleanup_local_variables(c);
|
||||
}
|
||||
|
||||
/* set program file name */
|
||||
/* set program filename */
|
||||
mrb_ccontext_filename(mrb, c, cmdline);
|
||||
|
||||
/* Load program */
|
||||
|
||||
+1
-1
@@ -126,7 +126,7 @@ main(int argc, char **argv)
|
||||
print_usage(argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
mrb = mrb_open_core(mrb_default_allocf, NULL);
|
||||
mrb = mrb_open_core();
|
||||
if (mrb == NULL) {
|
||||
fputs("Invalid mrb_state, exiting mruby-strip\n", stderr);
|
||||
return EXIT_FAILURE;
|
||||
@@ -0,0 +1,256 @@
|
||||
# mruby-binding
|
||||
|
||||
The `mruby-binding` mrbgem provides the `Binding` class for mruby. This class allows you to encapsulate the execution context (variables, methods, and `self`) at a particular point in your code, making it available for later use. It is similar in purpose to the `Binding` class in standard Ruby.
|
||||
|
||||
## Obtaining a Binding Object
|
||||
|
||||
You can obtain a `Binding` object using the `Kernel#binding` method:
|
||||
|
||||
### `Kernel#binding` -> Binding
|
||||
|
||||
Returns a `Binding` object that encapsulates the execution context (including local variables, `self`, and any active block) at the point of the call.
|
||||
|
||||
Example:
|
||||
|
||||
```ruby
|
||||
def get_binding(param)
|
||||
local_var = 42
|
||||
binding # This will capture param, local_var, and self
|
||||
end
|
||||
|
||||
b = get_binding("hello")
|
||||
# b now holds the context from inside get_binding
|
||||
```
|
||||
|
||||
**Note:** `Kernel#binding` cannot be called from a C function or a Proc defined in C. Attempting to do so will raise a `RuntimeError`.
|
||||
|
||||
## `Binding` Class Methods
|
||||
|
||||
A `Binding` object has the following methods:
|
||||
|
||||
### `local_variables` -> Array of Symbol
|
||||
|
||||
Returns an array of symbols representing the names of the local variables defined in the binding's context.
|
||||
|
||||
Example:
|
||||
|
||||
```ruby
|
||||
def my_method
|
||||
a = 10
|
||||
b = 20
|
||||
binding.local_variables # => [:a, :b]
|
||||
end
|
||||
```
|
||||
|
||||
### `local_variable_get(symbol)` -> Object
|
||||
|
||||
Retrieves the value of the local variable named by `symbol`. Raises a `NameError` if the variable is not defined in the binding's context.
|
||||
|
||||
Example:
|
||||
|
||||
```ruby
|
||||
def my_method
|
||||
a = 10
|
||||
b = binding
|
||||
b.local_variable_get(:a) # => 10
|
||||
end
|
||||
```
|
||||
|
||||
### `local_variable_set(symbol, value)` -> Object
|
||||
|
||||
Sets the local variable named by `symbol` to `value`. If the variable is not already defined, it will be defined in the binding's scope. Returns the `value` that was set.
|
||||
|
||||
Example:
|
||||
|
||||
```ruby
|
||||
def my_method
|
||||
a = 10
|
||||
b = binding
|
||||
b.local_variable_set(:a, 20) # a is now 20
|
||||
b.local_variable_set(:c, 30) # c is now defined as 30 in this scope
|
||||
a # => 20
|
||||
c # => 30
|
||||
end
|
||||
```
|
||||
|
||||
### `local_variable_defined?(symbol)` -> Boolean
|
||||
|
||||
Returns `true` if the local variable named by `symbol` is defined in the binding's context, `false` otherwise.
|
||||
|
||||
Example:
|
||||
|
||||
```ruby
|
||||
def my_method
|
||||
a = 10
|
||||
b = binding
|
||||
b.local_variable_defined?(:a) # => true
|
||||
b.local_variable_defined?(:c) # => false
|
||||
end
|
||||
```
|
||||
|
||||
### `receiver` -> Object
|
||||
|
||||
Returns the receiver object (`self`) of the binding.
|
||||
|
||||
Example:
|
||||
|
||||
```ruby
|
||||
class MyClass
|
||||
def get_binding
|
||||
@x = "instance var"
|
||||
binding
|
||||
end
|
||||
end
|
||||
|
||||
obj = MyClass.new
|
||||
b = obj.get_binding
|
||||
b.receiver # => obj (the instance of MyClass)
|
||||
b.receiver.instance_variable_get(:@x) # => "instance var" (Not directly using eval)
|
||||
```
|
||||
|
||||
### `source_location` -> [String, Integer] | nil
|
||||
|
||||
Returns a two-element array containing the filename and line number where the binding was created. Returns `nil` if the source location cannot be determined (e.g., for bindings created from C).
|
||||
|
||||
Example:
|
||||
|
||||
```ruby
|
||||
# In a file named 'test.rb'
|
||||
b = binding # Assuming this is line 2
|
||||
b.source_location # => ["test.rb", 2] (approximately)
|
||||
```
|
||||
|
||||
### `dup` / `clone` -> Binding
|
||||
|
||||
Creates a shallow copy of the binding. Modifications to local variables in one binding object can affect the other if the variables themselves are mutable objects, but setting a variable in one binding will not create it in the other after duplication. The internal state concerning local variable storage is also duplicated.
|
||||
|
||||
(The C code refers to `binding_initialize_copy`, which is what `dup` and `clone` would use.)
|
||||
|
||||
```ruby
|
||||
def my_method
|
||||
x = 1
|
||||
original_binding = binding
|
||||
original_binding.local_variable_set(:y, 2)
|
||||
|
||||
copied_binding = original_binding.dup
|
||||
|
||||
original_binding.local_variable_set(:x, 10)
|
||||
original_binding.local_variable_set(:y, 20)
|
||||
original_binding.local_variable_set(:z, 30) # New variable in original
|
||||
|
||||
puts copied_binding.local_variable_get(:x) # => 1 (Original value before duplication for variables existing at duplication time)
|
||||
# Correction: The tests show that changes to existing variables are reflected.
|
||||
# Let's re-verify test behavior for `dup`.
|
||||
|
||||
# Re-checking test `Binding#dup`:
|
||||
# x = 5
|
||||
# bind1 = binding
|
||||
# bind1.local_variable_set(:y, 10)
|
||||
# bind2 = bind1.dup
|
||||
# assert_equal 5, bind2.local_variable_get(:x)
|
||||
# assert_equal 10, bind2.local_variable_get(:y)
|
||||
# x = 50 # x is changed in the original scope AFTER duplication
|
||||
# assert_equal 50, bind1.local_variable_get(:x)
|
||||
# assert_equal 50, bind2.local_variable_get(:x) # bind2 sees the change to x!
|
||||
# bind1.local_variable_set(:y, 20) # y is changed in bind1 AFTER duplication
|
||||
# assert_equal 20, bind1.local_variable_get(:y)
|
||||
# assert_equal 20, bind2.local_variable_get(:y) # bind2 sees the change to y!
|
||||
# bind1.local_variable_set(:z, 30) # z is added to bind1
|
||||
# assert_raise(NameError) { bind2.local_variable_get(:z) } # bind2 does not see new z
|
||||
# bind2.local_variable_set(:z, 40) # z is added to bind2
|
||||
# assert_equal 30, bind1.local_variable_get(:z)
|
||||
# assert_equal 40, bind2.local_variable_get(:z)
|
||||
|
||||
# Corrected explanation for dup/clone:
|
||||
# Creates a copy of the binding. Both the original and copied bindings share the same
|
||||
# underlying environment for local variables that existed at the time of duplication.
|
||||
# This means:
|
||||
# - If a variable that existed when `dup` was called is modified (either in the original
|
||||
# scope or via `local_variable_set` on either binding), the change is visible in both bindings.
|
||||
# - If a *new* local variable is added to one binding using `local_variable_set` *after*
|
||||
# duplication, it is not visible in the other binding.
|
||||
end
|
||||
```
|
||||
|
||||
**Note on `eval`:** While the `Binding` object is often used with `eval` in standard Ruby to execute code within the binding's context, `mruby-binding` itself does not provide an `eval` method directly on the `Binding` object. You would typically use `Binding` with mruby's core `eval` method if you need to evaluate a string of code within a captured context. The `mruby-binding` gem provides the necessary infrastructure (like `mrb_binding_extract_proc` and `mrb_binding_extract_env` in C) that can be utilized by an `eval` implementation.
|
||||
|
||||
```ruby
|
||||
# Conceptual example (actual eval might vary based on mruby core)
|
||||
def my_method
|
||||
a = 10
|
||||
b = binding
|
||||
# eval("puts a", b) # => would print 10
|
||||
# eval("a = 20", b) # a in my_method's scope would become 20
|
||||
end
|
||||
```
|
||||
|
||||
## Usage Example
|
||||
|
||||
Here's a more complete example demonstrating some of the `Binding` object's capabilities:
|
||||
|
||||
```ruby
|
||||
class Greeter
|
||||
def initialize(name)
|
||||
@name = name
|
||||
end
|
||||
|
||||
def get_binding_for_greeting(additional_message)
|
||||
greeting_type = "Hello"
|
||||
# Capture the binding here
|
||||
binding
|
||||
end
|
||||
end
|
||||
|
||||
# Create an instance and get a binding
|
||||
greeter_instance = Greeter.new("World")
|
||||
captured_binding = greeter_instance.get_binding_for_greeting("Have a nice day!")
|
||||
|
||||
# Access the receiver (self)
|
||||
puts "Receiver: #{captured_binding.receiver}"
|
||||
# => Receiver: #<Greeter:0x...> (actual object id will vary)
|
||||
puts "Receiver's name: #{captured_binding.receiver.instance_variable_get(:@name)}"
|
||||
# => Receiver's name: World
|
||||
|
||||
# List local variables in the binding
|
||||
puts "Local variables: #{captured_binding.local_variables.inspect}"
|
||||
# => Local variables: [:additional_message, :greeting_type] (order may vary)
|
||||
|
||||
# Get local variable values
|
||||
puts "Greeting type: #{captured_binding.local_variable_get(:greeting_type)}"
|
||||
# => Greeting type: Hello
|
||||
puts "Additional message: #{captured_binding.local_variable_get(:additional_message)}"
|
||||
# => Additional message: Have a nice day!
|
||||
|
||||
# Set a local variable within the binding's context
|
||||
captured_binding.local_variable_set(:greeting_type, "Hi")
|
||||
puts "New greeting type: #{captured_binding.local_variable_get(:greeting_type)}"
|
||||
# => New greeting type: Hi
|
||||
|
||||
# Check if a variable is defined
|
||||
puts "Is 'greeting_type' defined? #{captured_binding.local_variable_defined?(:greeting_type)}"
|
||||
# => Is 'greeting_type' defined? true
|
||||
puts "Is 'non_existent_var' defined? #{captured_binding.local_variable_defined?(:non_existent_var)}"
|
||||
# => Is 'non_existent_var' defined? false
|
||||
|
||||
# Source location (will vary based on where the code is run)
|
||||
location = captured_binding.source_location
|
||||
if location
|
||||
puts "Binding created at: #{location[0]}:#{location[1]}"
|
||||
else
|
||||
puts "Source location not available for this binding."
|
||||
end
|
||||
```
|
||||
|
||||
This example illustrates how a `Binding` object captures the state of local variables and `self` from the scope where it was created, and how these can be inspected and manipulated.
|
||||
|
||||
## Limitations and mruby-specific Considerations
|
||||
|
||||
- **Nesting Depth for Local Variables:** mruby has an internal limit on how deeply nested Procs (blocks) can be while still allowing the `Binding` object to access and manage their local variables. This limit is defined by the `BINDING_UPPER_MAX` constant (defaulting to 20, with a minimum of 10 and a maximum of 100, configurable at compile time via `MRB_BINDING_UPPER_MAX`). If you exceed this nesting depth, attempting to create or manipulate a binding that needs to access variables across too many Proc scopes might result in a `RuntimeError` ("too many upper procs for local variables").
|
||||
|
||||
- **`eval` Method:** As noted earlier, this gem provides the `Binding` object itself, not a `Binding#eval` method. You would use `Kernel.eval(string, binding)` if you need to evaluate code within the context of a binding, relying on mruby's core `eval` capabilities.
|
||||
|
||||
- **C Function Callers:** `Kernel#binding` cannot create a `Binding` object if the direct caller is a C function. It must be called from Ruby code.
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
@@ -402,7 +402,7 @@ mrb_mruby_binding_gem_init(mrb_state *mrb)
|
||||
|
||||
mrb_define_private_method_id(mrb, mrb->kernel_module, MRB_SYM(binding), mrb_f_binding, MRB_ARGS_NONE());
|
||||
|
||||
mrb_define_method_id(mrb, binding, MRB_SYM(initialize_copy), binding_initialize_copy, MRB_ARGS_REQ(1));
|
||||
mrb_define_private_method_id(mrb, binding, MRB_SYM(initialize_copy), binding_initialize_copy, MRB_ARGS_REQ(1));
|
||||
mrb_define_method_id(mrb, binding, MRB_SYM_Q(local_variable_defined), binding_local_variable_defined_p, MRB_ARGS_REQ(1));
|
||||
mrb_define_method_id(mrb, binding, MRB_SYM(local_variable_get), binding_local_variable_get, MRB_ARGS_REQ(1));
|
||||
mrb_define_method_id(mrb, binding, MRB_SYM(local_variable_set), binding_local_variable_set, MRB_ARGS_REQ(2));
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
# mruby-catch
|
||||
|
||||
This mrbgem provides `catch` and `throw` functionality similar to what is available in standard Ruby. It allows for non-local exits from blocks of code.
|
||||
|
||||
## `catch`
|
||||
|
||||
The `catch` method is used to establish a block that can be exited prematurely using `throw`.
|
||||
|
||||
```ruby
|
||||
catch(tag) do |current_tag|
|
||||
# ... code ...
|
||||
if some_condition
|
||||
throw(tag, return_value)
|
||||
end
|
||||
# ... more code ...
|
||||
end
|
||||
```
|
||||
|
||||
- **With a tag:** When `catch` is called with a `tag` (any Ruby object), it executes the block. If `throw` is called with the same `tag` from within this block (or any method called from within it), the `catch` block immediately exits and returns the value provided to `throw`.
|
||||
- **Block completion:** If the block executes to completion without `throw` being called with a matching tag, the `catch` block returns the result of the last expression evaluated in the block.
|
||||
- **No tag:** If `catch` is called without a tag, a new unique `Object` is created and used as the tag. This tag is passed as an argument to the block.
|
||||
|
||||
```ruby
|
||||
catch do |generated_tag|
|
||||
# generated_tag is a new Object
|
||||
throw(generated_tag, "hello")
|
||||
end # => "hello"
|
||||
```
|
||||
|
||||
## `throw`
|
||||
|
||||
The `throw` method is used to initiate a non-local exit to a corresponding `catch` block.
|
||||
|
||||
```ruby
|
||||
throw(tag)
|
||||
throw(tag, value)
|
||||
```
|
||||
|
||||
- **With a tag and value:** `throw(tag, value)` jumps to the innermost active `catch` block that is waiting for `tag`. The `catch` block then returns `value`.
|
||||
- **With only a tag:** `throw(tag)` is equivalent to `throw(tag, nil)`.
|
||||
- **Uncaught throw:** If `throw` is called with a `tag` for which there is no matching `catch` block in the current call stack, an `UncaughtThrowError` is raised.
|
||||
|
||||
## `UncaughtThrowError`
|
||||
|
||||
This is a custom error class that inherits from `ArgumentError`. It is raised when `throw` is called for a tag that is not currently being caught.
|
||||
It has two attributes:
|
||||
|
||||
- `tag`: The tag that was thrown.
|
||||
- `value`: The value that was thrown with the tag.
|
||||
|
||||
## Example
|
||||
|
||||
```ruby
|
||||
def check_value(val)
|
||||
puts "Checking: #{val}"
|
||||
if val < 0
|
||||
throw(:negative_value, val)
|
||||
elsif val == 0
|
||||
throw(:zero_value) # value will be nil
|
||||
end
|
||||
puts "#{val} is positive"
|
||||
val * 2
|
||||
end
|
||||
|
||||
result = catch(:negative_value) do
|
||||
puts catch(:zero_value) do
|
||||
puts check_value(10)
|
||||
puts check_value(-5) # This will throw to :negative_value
|
||||
puts check_value(0) # This would throw to :zero_value, but it's not reached
|
||||
end
|
||||
puts "This line is skipped if :zero_value is thrown."
|
||||
end
|
||||
|
||||
puts "Result: #{result}"
|
||||
|
||||
# Output:
|
||||
# Checking: 10
|
||||
# 10 is positive
|
||||
# 20
|
||||
# Checking: -5
|
||||
# Result: -5
|
||||
|
||||
puts "--- Next example --- "
|
||||
|
||||
result2 = catch do |tag_a|
|
||||
catch do |tag_b|
|
||||
puts "In tag_b block"
|
||||
throw(tag_a, "Exited from A via B")
|
||||
puts "This is not printed"
|
||||
end
|
||||
puts "This is not printed either"
|
||||
end
|
||||
puts result2 # => Exited from A via B
|
||||
```
|
||||
@@ -0,0 +1,81 @@
|
||||
# mruby-class-ext
|
||||
|
||||
This mrbgem extends the `Module` and `Class` classes in mruby, providing additional methods for reflection and class manipulation.
|
||||
|
||||
## Module Methods
|
||||
|
||||
### `mod < other`
|
||||
|
||||
Returns `true` if `mod` is a subclass of `other`. Returns `nil` if there's no relationship between the two. (Think of the relationship in terms of the class definition: "class A < B" implies "A < B".)
|
||||
|
||||
### `mod <= other`
|
||||
|
||||
Returns `true` if `mod` is a subclass of `other` or is the same as `other`. Returns `nil` if there's no relationship between the two. (Think of the relationship in terms of the class definition: "class A < B" implies "A < B".)
|
||||
|
||||
### `mod > other`
|
||||
|
||||
Returns `true` if `mod` is an ancestor of `other`. Returns `nil` if there's no relationship between the two. (Think of the relationship in terms of the class definition: "class A < B" implies "B > A".)
|
||||
|
||||
### `mod >= other`
|
||||
|
||||
Returns `true` if `mod` is an ancestor of `other`, or the two modules are the same. Returns `nil` if there's no relationship between the two. (Think of the relationship in terms of the class definition: "class A < B" implies "B > A".)
|
||||
|
||||
### `module <=> other_module`
|
||||
|
||||
Comparison---Returns -1, 0, +1 or `nil` depending on whether `module` includes `other_module`, they are the same, or if `module` is included by `other_module`.
|
||||
|
||||
Returns `nil` if `module` has no relationship with `other_module`, if `other_module` is not a module, or if the two values are incomparable.
|
||||
|
||||
### `name`
|
||||
|
||||
Returns the name of the module.
|
||||
|
||||
### `singleton_class?`
|
||||
|
||||
Returns `true` if the module is a singleton class.
|
||||
|
||||
### `module_exec(arg...) {|var...| block } -> obj`
|
||||
|
||||
### `class_exec(arg...) {|var...| block } -> obj`
|
||||
|
||||
Evaluates the given block in the context of the class/module. The method defined in the block will belong to the receiver. Any arguments passed to the method will be passed to the block. This can be used if the block needs to access instance variables.
|
||||
|
||||
```ruby
|
||||
class Thing
|
||||
end
|
||||
Thing.class_exec{
|
||||
def hello() "Hello there!" end
|
||||
}
|
||||
puts Thing.new.hello()
|
||||
```
|
||||
|
||||
## Class Methods
|
||||
|
||||
### `subclasses -> array`
|
||||
|
||||
Returns an array of classes where the receiver is the direct superclass of the class, excluding singleton classes. The order of the returned array is not defined.
|
||||
|
||||
```ruby
|
||||
class A; end
|
||||
class B < A; end
|
||||
class C < B; end
|
||||
class D < A; end
|
||||
|
||||
A.subclasses #=> [D, B]
|
||||
B.subclasses #=> [C]
|
||||
C.subclasses #=> []
|
||||
```
|
||||
|
||||
### `attached_object -> object`
|
||||
|
||||
Returns the object for which the receiver is the singleton class. Raises a `TypeError` if the class is not a singleton class.
|
||||
|
||||
```ruby
|
||||
class Foo; end
|
||||
|
||||
Foo.singleton_class.attached_object #=> Foo
|
||||
Foo.attached_object #=> TypeError: not a singleton class
|
||||
Foo.new.singleton_class.attached_object #=> #<Foo:0x000000010491a370>
|
||||
TrueClass.attached_object #=> TypeError: not a singleton class
|
||||
NilClass.attached_object #=> TypeError: not a singleton class
|
||||
```
|
||||
@@ -0,0 +1,45 @@
|
||||
# mruby-cmath
|
||||
|
||||
This mrbgem provides complex number support for mruby, offering mathematical functions that can handle complex numbers, similar to Ruby's standard `cmath` library.
|
||||
|
||||
## Requirements
|
||||
|
||||
This gem utilizes C99 `_Complex` features. Therefore, you will need a C compiler that supports C99 or a later version to build and use this gem.
|
||||
|
||||
## Provided Functions
|
||||
|
||||
The `CMath` module includes the following mathematical functions:
|
||||
|
||||
- `exp(z)`: Computes the exponential of `z`.
|
||||
- `log(z)`: Computes the natural logarithm of `z`.
|
||||
- `log(z, b)`: Computes the logarithm of `z` with base `b`.
|
||||
- `log2(z)`: Computes the base-2 logarithm of `z`.
|
||||
- `log10(z)`: Computes the base-10 logarithm of `z`.
|
||||
- `sqrt(z)`: Computes the square root of `z`.
|
||||
- `sin(z)`: Computes the sine of `z`.
|
||||
- `cos(z)`: Computes the cosine of `z`.
|
||||
- `tan(z)`: Computes the tangent of `z`.
|
||||
- `asin(z)`: Computes the arc sine of `z`.
|
||||
- `acos(z)`: Computes the arc cosine of `z`.
|
||||
- `atan(z)`: Computes the arc tangent of `z`.
|
||||
- `sinh(z)`: Computes the hyperbolic sine of `z`.
|
||||
- `cosh(z)`: Computes the hyperbolic cosine of `z`.
|
||||
- `tanh(z)`: Computes the hyperbolic tangent of `z`.
|
||||
- `asinh(z)`: Computes the inverse hyperbolic sine of `z`.
|
||||
- `acosh(z)`: Computes the inverse hyperbolic cosine of `z`.
|
||||
- `atanh(z)`: Computes the inverse hyperbolic tangent of `z`.
|
||||
|
||||
## Usage Example
|
||||
|
||||
Here's a simple example of how to use `CMath` to calculate the square root of a negative number:
|
||||
|
||||
```ruby
|
||||
# Assuming mruby is built with mruby-cmath
|
||||
|
||||
# Calculate the square root of -4
|
||||
result = CMath.sqrt(-4)
|
||||
|
||||
# result will be a Complex number (0+2i)
|
||||
puts result.real # Output: 0.0
|
||||
puts result.imaginary # Output: 2.0
|
||||
```
|
||||
@@ -0,0 +1,65 @@
|
||||
# mruby-compar-ext
|
||||
|
||||
Comparable module extension.
|
||||
|
||||
This mrbgem adds the `clamp` method to the `Comparable` module.
|
||||
|
||||
## `Comparable#clamp`
|
||||
|
||||
The `clamp` method restricts a value to a given range.
|
||||
|
||||
**Syntax:**
|
||||
|
||||
```ruby
|
||||
obj.clamp(min, max) -> obj
|
||||
obj.clamp(range) -> obj
|
||||
```
|
||||
|
||||
**Description:**
|
||||
|
||||
- In the `(min, max)` form, it returns:
|
||||
- `min` if `obj <=> min` is less than zero.
|
||||
- `max` if `obj <=> max` is greater than zero.
|
||||
- `obj` otherwise.
|
||||
- In the `(range)` form, it returns:
|
||||
- `range.begin` if `obj <=> range.begin` is less than zero.
|
||||
- `range.end` if `obj <=> range.end` is greater than zero (and `range.end` is not `nil` and the range is inclusive).
|
||||
- `obj` otherwise.
|
||||
- If `range.begin` is `nil`, it is considered smaller than `obj`.
|
||||
- If `range.end` is `nil`, it is considered greater than `obj`.
|
||||
|
||||
**Examples:**
|
||||
|
||||
```ruby
|
||||
# Using min and max arguments
|
||||
12.clamp(0, 100) #=> 12
|
||||
523.clamp(0, 100) #=> 100
|
||||
-3.123.clamp(0, 100) #=> 0
|
||||
|
||||
'd'.clamp('a', 'f') #=> 'd'
|
||||
'z'.clamp('a', 'f') #=> 'f'
|
||||
|
||||
# Using a Range argument
|
||||
12.clamp(0..100) #=> 12
|
||||
523.clamp(0..100) #=> 100
|
||||
-3.123.clamp(0..100) #=> 0
|
||||
|
||||
'd'.clamp('a'..'f') #=> 'd'
|
||||
'z'.clamp('a'..'f') #=> 'f'
|
||||
|
||||
# Using ranges with nil begin or end
|
||||
-20.clamp(0..) #=> 0
|
||||
523.clamp(..100) #=> 100
|
||||
```
|
||||
|
||||
**Error Handling:**
|
||||
|
||||
- Raises an `ArgumentError` if an exclusive range (e.g., `0...100`) is provided as the `range` argument when `range.end` is not `nil`.
|
||||
- Raises an `ArgumentError` if `min` and `max` arguments cannot be compared (e.g., a `String` and an `Integer`).
|
||||
- Raises an `ArgumentError` if the `min` argument is greater than the `max` argument.
|
||||
|
||||
```ruby
|
||||
100.clamp(0...100) # ArgumentError: cannot clamp with an exclusive range
|
||||
10.clamp("a", "z") # ArgumentError: comparison of String with String failed (depending on mruby version, may also be other errors if types are incompatible)
|
||||
100.clamp(10, 0) # ArgumentError: min argument must be smaller than max argument
|
||||
```
|
||||
@@ -20,6 +20,10 @@
|
||||
#include <string.h>
|
||||
#include <mruby/internal.h>
|
||||
|
||||
#define mrbc_malloc(s) mrb_basic_alloc_func(NULL,(s))
|
||||
#define mrbc_realloc(p,s) mrb_basic_alloc_func((p),(s))
|
||||
#define mrbc_free(p) mrb_basic_alloc_func((p),0)
|
||||
|
||||
#ifndef MRB_CODEGEN_LEVEL_MAX
|
||||
#define MRB_CODEGEN_LEVEL_MAX 256
|
||||
#endif
|
||||
@@ -48,7 +52,7 @@ struct loopinfo {
|
||||
|
||||
typedef struct scope {
|
||||
mrb_state *mrb;
|
||||
mrb_mempool *mpool;
|
||||
mempool *mpool;
|
||||
|
||||
struct scope *prev;
|
||||
|
||||
@@ -124,27 +128,27 @@ codegen_error(codegen_scope *s, const char *message)
|
||||
while (s->prev) {
|
||||
codegen_scope *tmp = s->prev;
|
||||
if (s->irep) {
|
||||
mrb_free(s->mrb, s->iseq);
|
||||
mrbc_free(s->iseq);
|
||||
for (int i=0; i<s->irep->plen; i++) {
|
||||
mrb_irep_pool *p = &s->pool[i];
|
||||
if ((p->tt & 0x3) == IREP_TT_STR || p->tt == IREP_TT_BIGINT) {
|
||||
mrb_free(s->mrb, (void*)p->u.str);
|
||||
mrbc_free((void*)p->u.str);
|
||||
}
|
||||
}
|
||||
mrb_free(s->mrb, s->pool);
|
||||
mrb_free(s->mrb, s->syms);
|
||||
mrb_free(s->mrb, s->catch_table);
|
||||
mrbc_free(s->pool);
|
||||
mrbc_free(s->syms);
|
||||
mrbc_free(s->catch_table);
|
||||
if (s->reps) {
|
||||
/* copied from mrb_irep_free() in state.c */
|
||||
for (int i=0; i<s->irep->rlen; i++) {
|
||||
if (s->reps[i])
|
||||
mrb_irep_decref(s->mrb, (mrb_irep*)s->reps[i]);
|
||||
}
|
||||
mrb_free(s->mrb, s->reps);
|
||||
mrbc_free(s->reps);
|
||||
}
|
||||
mrb_free(s->mrb, s->lines);
|
||||
mrbc_free(s->lines);
|
||||
}
|
||||
mrb_mempool_close(s->mpool);
|
||||
mempool_close(s->mpool);
|
||||
s = tmp;
|
||||
}
|
||||
MRB_THROW(s->mrb->jmp);
|
||||
@@ -153,21 +157,12 @@ codegen_error(codegen_scope *s, const char *message)
|
||||
static void*
|
||||
codegen_palloc(codegen_scope *s, size_t len)
|
||||
{
|
||||
void *p = mrb_mempool_alloc(s->mpool, len);
|
||||
void *p = mempool_alloc(s->mpool, len);
|
||||
|
||||
if (!p) codegen_error(s, "pool memory allocation");
|
||||
return p;
|
||||
}
|
||||
|
||||
static void*
|
||||
codegen_realloc(codegen_scope *s, void *p, size_t len)
|
||||
{
|
||||
p = mrb_realloc_simple(s->mrb, p, len);
|
||||
|
||||
if (!p && len > 0) codegen_error(s, "mrb_realloc");
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
check_no_ext_ops(codegen_scope *s, uint16_t a, uint16_t b)
|
||||
{
|
||||
@@ -195,9 +190,9 @@ emit_B(codegen_scope *s, uint32_t pc, uint8_t i)
|
||||
else {
|
||||
s->icapa *= 2;
|
||||
}
|
||||
s->iseq = (mrb_code*)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
|
||||
s->iseq = (mrb_code*)mrbc_realloc(s->iseq, sizeof(mrb_code)*s->icapa);
|
||||
if (s->lines) {
|
||||
s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->icapa);
|
||||
s->lines = (uint16_t*)mrbc_realloc(s->lines, sizeof(uint16_t)*s->icapa);
|
||||
}
|
||||
}
|
||||
if (s->lines) {
|
||||
@@ -588,9 +583,8 @@ static void gen_int(codegen_scope *s, uint16_t dst, mrb_int i);
|
||||
static void
|
||||
gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
|
||||
{
|
||||
if (nopeep || no_peephole(s)) goto normal;
|
||||
else if (dst == src) return;
|
||||
else {
|
||||
if (dst == src) return;
|
||||
if (!(nopeep || no_peephole(s))) {
|
||||
struct mrb_insn_data data = mrb_last_insn(s);
|
||||
|
||||
switch (data.insn) {
|
||||
@@ -599,7 +593,7 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
|
||||
if (data.a == src) {
|
||||
if (data.b == dst) /* skip swapping MOVE */
|
||||
return;
|
||||
if (data.a < s->nlocals) goto normal;
|
||||
if (data.a < s->nlocals) break;
|
||||
rewind_pc(s);
|
||||
s->lastpc = addr_pc(s, mrb_prev_pc(s, data.addr));
|
||||
gen_move(s, dst, data.b, FALSE);
|
||||
@@ -611,34 +605,34 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
|
||||
gen_move(s, dst, src, FALSE);
|
||||
return;
|
||||
}
|
||||
goto normal;
|
||||
break;
|
||||
case OP_LOADNIL: case OP_LOADSELF: case OP_LOADT: case OP_LOADF:
|
||||
case OP_LOADI__1:
|
||||
case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
|
||||
case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
|
||||
if (data.a != src || data.a < s->nlocals) goto normal;
|
||||
if (data.a != src || data.a < s->nlocals) break;
|
||||
rewind_pc(s);
|
||||
genop_1(s, data.insn, dst);
|
||||
return;
|
||||
case OP_HASH:
|
||||
if (data.b != 0) goto normal;
|
||||
if (data.b != 0) break;
|
||||
/* fall through */
|
||||
case OP_LOADI8: case OP_LOADINEG:
|
||||
case OP_LOADL: case OP_LOADSYM:
|
||||
case OP_GETGV: case OP_GETSV: case OP_GETIV: case OP_GETCV:
|
||||
case OP_GETCONST: case OP_STRING:
|
||||
case OP_LAMBDA: case OP_BLOCK: case OP_METHOD: case OP_BLKPUSH:
|
||||
if (data.a != src || data.a < s->nlocals) goto normal;
|
||||
if (data.a != src || data.a < s->nlocals) break;
|
||||
rewind_pc(s);
|
||||
genop_2(s, data.insn, dst, data.b);
|
||||
return;
|
||||
case OP_LOADI16:
|
||||
if (data.a != src || data.a < s->nlocals) goto normal;
|
||||
if (data.a != src || data.a < s->nlocals) break;
|
||||
rewind_pc(s);
|
||||
genop_2S(s, data.insn, dst, data.b);
|
||||
return;
|
||||
case OP_LOADI32:
|
||||
if (data.a != src || data.a < s->nlocals) goto normal;
|
||||
if (data.a != src || data.a < s->nlocals) break;
|
||||
else {
|
||||
uint32_t i = (uint32_t)data.b<<16|data.c;
|
||||
rewind_pc(s);
|
||||
@@ -646,7 +640,7 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
|
||||
}
|
||||
return;
|
||||
case OP_ARRAY:
|
||||
if (data.a != src || data.a < s->nlocals || data.a < dst) goto normal;
|
||||
if (data.a != src || data.a < s->nlocals || data.a < dst) break;
|
||||
rewind_pc(s);
|
||||
if (data.b == 0 || dst == data.a)
|
||||
genop_2(s, OP_ARRAY, dst, 0);
|
||||
@@ -654,22 +648,21 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
|
||||
genop_3(s, OP_ARRAY2, dst, data.a, data.b);
|
||||
return;
|
||||
case OP_ARRAY2:
|
||||
if (data.a != src || data.a < s->nlocals || data.a < dst) goto normal;
|
||||
if (data.a != src || data.a < s->nlocals || data.a < dst) break;
|
||||
rewind_pc(s);
|
||||
genop_3(s, OP_ARRAY2, dst, data.b, data.c);
|
||||
return;
|
||||
case OP_AREF:
|
||||
case OP_GETUPVAR:
|
||||
if (data.a != src || data.a < s->nlocals) goto normal;
|
||||
if (data.a != src || data.a < s->nlocals) break;
|
||||
rewind_pc(s);
|
||||
genop_3(s, data.insn, dst, data.b, data.c);
|
||||
return;
|
||||
case OP_ADDI: case OP_SUBI:
|
||||
if (addr_pc(s, data.addr) == s->lastlabel || data.a != src || data.a < s->nlocals) goto normal;
|
||||
if (addr_pc(s, data.addr) == s->lastlabel || data.a != src || data.a < s->nlocals) break;
|
||||
else {
|
||||
struct mrb_insn_data data0 = mrb_decode_insn(mrb_prev_pc(s, data.addr));
|
||||
if (data0.insn != OP_MOVE || data0.a != data.a || data0.b != dst) goto normal;
|
||||
s->pc = addr_pc(s, data0.addr);
|
||||
if (data0.insn != OP_MOVE || data0.a != data.a || data0.b != dst) break;
|
||||
if (addr_pc(s, data0.addr) != s->lastlabel) {
|
||||
/* constant folding */
|
||||
data0 = mrb_decode_insn(mrb_prev_pc(s, data0.addr));
|
||||
@@ -684,13 +677,12 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
|
||||
}
|
||||
}
|
||||
}
|
||||
genop_2(s, data.insn, dst, data.b);
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
normal:
|
||||
|
||||
genop_2(s, OP_MOVE, dst, src);
|
||||
return;
|
||||
}
|
||||
@@ -805,13 +797,13 @@ realloc_pool_str(codegen_scope *s, mrb_irep_pool *p, mrb_int len)
|
||||
{
|
||||
char *str;
|
||||
if ((p->tt & 3) == IREP_TT_SSTR) {
|
||||
str = (char*)codegen_realloc(s, NULL, len+1);
|
||||
str = (char*)mrbc_malloc(len+1);
|
||||
}
|
||||
else {
|
||||
str = (char*)p->u.str;
|
||||
str = (char*)codegen_realloc(s, str, len+1);
|
||||
str = (char*)mrbc_realloc(str, len+1);
|
||||
}
|
||||
p->tt = len<<2 | IREP_TT_STR;
|
||||
p->tt = (uint32_t)(len<<2 | IREP_TT_STR);
|
||||
str[len] = '\0';
|
||||
p->u.str = (const char*)str;
|
||||
}
|
||||
@@ -820,7 +812,7 @@ static void
|
||||
free_pool_str(codegen_scope *s, mrb_irep_pool *p)
|
||||
{
|
||||
if ((p->tt & 3) != IREP_TT_SSTR) {
|
||||
codegen_realloc(s, (char*)p->u.str, 0);
|
||||
mrbc_free((char*)p->u.str);
|
||||
}
|
||||
p->u.str = NULL;
|
||||
s->irep->plen--;
|
||||
@@ -838,7 +830,7 @@ merge_op_string(codegen_scope *s, uint16_t dst, uint16_t b1, uint16_t b2, const
|
||||
struct mrb_insn_data data = mrb_decode_insn(i);
|
||||
if (data.insn == OP_STRING) {
|
||||
if (data.b == b1) used |= 1;
|
||||
else if (data.b == b2) used |= 2;
|
||||
if (data.b == b2) used |= 2;
|
||||
}
|
||||
switch (i[0]) {
|
||||
case OP_EXT1:
|
||||
@@ -860,7 +852,7 @@ merge_op_string(codegen_scope *s, uint16_t dst, uint16_t b1, uint16_t b2, const
|
||||
mrb_irep_pool *p2 = &s->pool[b2];
|
||||
mrb_int len1 = p1->tt>>2;
|
||||
mrb_int len2 = p2->tt>>2;
|
||||
int off = find_pool_str(s, p1->u.str, len1, p2->u.str, len2);;
|
||||
int off = find_pool_str(s, p1->u.str, len1, p2->u.str, len2);
|
||||
|
||||
if (off < 0) {
|
||||
switch (used) {
|
||||
@@ -1095,7 +1087,7 @@ lit_pool_extend(codegen_scope *s)
|
||||
{
|
||||
if (s->irep->plen == s->pcapa) {
|
||||
s->pcapa *= 2;
|
||||
s->pool = (mrb_irep_pool*)codegen_realloc(s, s->pool, sizeof(mrb_irep_pool)*s->pcapa);
|
||||
s->pool = (mrb_irep_pool*)mrbc_realloc(s->pool, sizeof(mrb_irep_pool)*s->pcapa);
|
||||
}
|
||||
|
||||
return &s->pool[s->irep->plen++];
|
||||
@@ -1125,7 +1117,7 @@ new_litbint(codegen_scope *s, const char *p, int base)
|
||||
|
||||
char *buf;
|
||||
pv->tt = IREP_TT_BIGINT;
|
||||
buf = (char*)codegen_realloc(s, NULL, plen+3);
|
||||
buf = (char*)mrbc_malloc(plen+3);
|
||||
buf[0] = (char)plen;
|
||||
buf[1] = base;
|
||||
memcpy(buf+2, p, plen);
|
||||
@@ -1172,7 +1164,7 @@ new_lit_str2(codegen_scope *s, const char *str1, mrb_int len1, const char *str2,
|
||||
else {
|
||||
char *p;
|
||||
pool->tt = (uint32_t)(len<<2) | IREP_TT_STR;
|
||||
p = (char*)codegen_realloc(s, NULL, len+1);
|
||||
p = (char*)mrbc_malloc(len+1);
|
||||
memcpy(p, str1, len1);
|
||||
if (str2) memcpy(p+len1, str2, len2);
|
||||
p[len] = '\0';
|
||||
@@ -1266,7 +1258,7 @@ new_sym(codegen_scope *s, mrb_sym sym)
|
||||
if (s->scapa > 0xffff) {
|
||||
codegen_error(s, "too many symbols");
|
||||
}
|
||||
s->syms = (mrb_sym*)codegen_realloc(s, s->syms, sizeof(mrb_sym)*s->scapa);
|
||||
s->syms = (mrb_sym*)mrbc_realloc(s->syms, sizeof(mrb_sym)*s->scapa);
|
||||
}
|
||||
s->syms[s->irep->slen] = sym;
|
||||
return s->irep->slen++;
|
||||
@@ -3223,9 +3215,12 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
if (tree && tree->cdr && tree->cdr->cdr) {
|
||||
codegen(s, tree->cdr->cdr, VAL);
|
||||
}
|
||||
else {
|
||||
else if (s2) {
|
||||
gen_blkmove(s, 0, lv);
|
||||
}
|
||||
else {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
}
|
||||
n = 0;
|
||||
}
|
||||
s->sp = sp;
|
||||
@@ -3626,13 +3621,12 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
int off = new_lit_str(s, p, len);
|
||||
int sym;
|
||||
|
||||
genop_1(s, OP_LOADSELF, cursp());
|
||||
push();
|
||||
genop_2(s, OP_STRING, cursp(), off);
|
||||
push(); push();
|
||||
pop_n(3);
|
||||
sym = new_sym(s, MRB_OPSYM_2(s->mrb, tick)); /* ` */
|
||||
genop_3(s, OP_SEND, cursp(), sym, 1);
|
||||
genop_3(s, OP_SSEND, cursp(), sym, 1);
|
||||
if (val) push();
|
||||
}
|
||||
break;
|
||||
@@ -3966,7 +3960,7 @@ scope_add_irep(codegen_scope *s)
|
||||
s->irep = irep = mrb_add_irep(s->mrb);
|
||||
if (prev->irep->rlen == prev->rcapa) {
|
||||
prev->rcapa *= 2;
|
||||
prev->reps = (mrb_irep**)codegen_realloc(s, prev->reps, sizeof(mrb_irep*)*prev->rcapa);
|
||||
prev->reps = (mrb_irep**)mrbc_realloc(prev->reps, sizeof(mrb_irep*)*prev->rcapa);
|
||||
}
|
||||
prev->reps[prev->irep->rlen] = irep;
|
||||
prev->irep->rlen++;
|
||||
@@ -3977,8 +3971,8 @@ static codegen_scope*
|
||||
scope_new(mrb_state *mrb, codegen_scope *prev, node *nlv)
|
||||
{
|
||||
static const codegen_scope codegen_scope_zero = { 0 };
|
||||
mrb_mempool *pool = mrb_mempool_open(mrb);
|
||||
codegen_scope *s = (codegen_scope*)mrb_mempool_alloc(pool, sizeof(codegen_scope));
|
||||
mempool *pool = mempool_open();
|
||||
codegen_scope *s = (codegen_scope*)mempool_alloc(pool, sizeof(codegen_scope));
|
||||
|
||||
if (!s) {
|
||||
if (prev)
|
||||
@@ -3996,26 +3990,26 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *nlv)
|
||||
scope_add_irep(s);
|
||||
|
||||
s->rcapa = 8;
|
||||
s->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*s->rcapa);
|
||||
s->reps = (mrb_irep**)mrbc_malloc(sizeof(mrb_irep*)*s->rcapa);
|
||||
|
||||
s->icapa = 1024;
|
||||
s->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*s->icapa);
|
||||
s->iseq = (mrb_code*)mrbc_malloc(sizeof(mrb_code)*s->icapa);
|
||||
|
||||
s->pcapa = 32;
|
||||
s->pool = (mrb_irep_pool*)mrb_malloc(mrb, sizeof(mrb_irep_pool)*s->pcapa);
|
||||
s->pool = (mrb_irep_pool*)mrbc_malloc(sizeof(mrb_irep_pool)*s->pcapa);
|
||||
|
||||
s->scapa = 256;
|
||||
s->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*s->scapa);
|
||||
s->syms = (mrb_sym*)mrbc_malloc(sizeof(mrb_sym)*s->scapa);
|
||||
|
||||
s->lv = nlv;
|
||||
s->sp += node_len(nlv)+1; /* add self */
|
||||
s->nlocals = s->sp;
|
||||
s->nlocals = s->nregs = s->sp;
|
||||
if (nlv) {
|
||||
mrb_sym *lv;
|
||||
node *n = nlv;
|
||||
size_t i = 0;
|
||||
|
||||
s->irep->lv = lv = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*(s->nlocals-1));
|
||||
s->irep->lv = lv = (mrb_sym*)mrbc_malloc(sizeof(mrb_sym)*(s->nlocals-1));
|
||||
for (i=0, n=nlv; n; i++,n=n->cdr) {
|
||||
lv[i] = lv_name(n);
|
||||
}
|
||||
@@ -4025,7 +4019,7 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *nlv)
|
||||
|
||||
s->filename_sym = prev->filename_sym;
|
||||
if (s->filename_sym) {
|
||||
s->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*s->icapa);
|
||||
s->lines = (uint16_t*)mrbc_malloc(sizeof(short)*s->icapa);
|
||||
}
|
||||
s->lineno = prev->lineno;
|
||||
|
||||
@@ -4057,7 +4051,7 @@ scope_finish(codegen_scope *s)
|
||||
irep->flags = 0;
|
||||
if (s->iseq) {
|
||||
size_t catchsize = sizeof(struct mrb_irep_catch_handler) * irep->clen;
|
||||
irep->iseq = (const mrb_code*)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc + catchsize);
|
||||
irep->iseq = (const mrb_code*)mrbc_realloc(s->iseq, sizeof(mrb_code)*s->pc + catchsize);
|
||||
irep->ilen = s->pc;
|
||||
if (irep->clen > 0) {
|
||||
memcpy((void*)(irep->iseq + irep->ilen), s->catch_table, catchsize);
|
||||
@@ -4066,11 +4060,11 @@ scope_finish(codegen_scope *s)
|
||||
else {
|
||||
irep->clen = 0;
|
||||
}
|
||||
mrb_free(s->mrb, s->catch_table);
|
||||
mrbc_free(s->catch_table);
|
||||
s->catch_table = NULL;
|
||||
irep->pool = (const mrb_irep_pool*)codegen_realloc(s, s->pool, sizeof(mrb_irep_pool)*irep->plen);
|
||||
irep->syms = (const mrb_sym*)codegen_realloc(s, s->syms, sizeof(mrb_sym)*irep->slen);
|
||||
irep->reps = (const mrb_irep**)codegen_realloc(s, s->reps, sizeof(mrb_irep*)*irep->rlen);
|
||||
irep->pool = (const mrb_irep_pool*)mrbc_realloc(s->pool, sizeof(mrb_irep_pool)*irep->plen);
|
||||
irep->syms = (const mrb_sym*)mrbc_realloc(s->syms, sizeof(mrb_sym)*irep->slen);
|
||||
irep->reps = (const mrb_irep**)mrbc_realloc(s->reps, sizeof(mrb_irep*)*irep->rlen);
|
||||
if (s->filename_sym) {
|
||||
mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
|
||||
const char *filename = mrb_sym_name_len(s->mrb, fname, NULL);
|
||||
@@ -4078,13 +4072,13 @@ scope_finish(codegen_scope *s)
|
||||
mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
|
||||
filename, s->lines, s->debug_start_pos, s->pc);
|
||||
}
|
||||
mrb_free(s->mrb, s->lines);
|
||||
mrbc_free(s->lines);
|
||||
|
||||
irep->nlocals = s->nlocals;
|
||||
irep->nregs = s->nregs;
|
||||
|
||||
mrb_gc_arena_restore(mrb, s->ai);
|
||||
mrb_mempool_close(s->mpool);
|
||||
mempool_close(s->mpool);
|
||||
}
|
||||
|
||||
static struct loopinfo*
|
||||
@@ -4175,7 +4169,7 @@ static int
|
||||
catch_handler_new(codegen_scope *s)
|
||||
{
|
||||
size_t newsize = sizeof(struct mrb_irep_catch_handler) * (s->irep->clen + 1);
|
||||
s->catch_table = (struct mrb_irep_catch_handler*)codegen_realloc(s, (void*)s->catch_table, newsize);
|
||||
s->catch_table = (struct mrb_irep_catch_handler*)mrbc_realloc((void*)s->catch_table, newsize);
|
||||
return s->irep->clen++;
|
||||
}
|
||||
|
||||
@@ -4213,7 +4207,7 @@ generate_code(mrb_state *mrb, parser_state *p, int val)
|
||||
codegen(scope, p->tree, val);
|
||||
proc = mrb_proc_new(mrb, scope->irep);
|
||||
mrb_irep_decref(mrb, scope->irep);
|
||||
mrb_mempool_close(scope->mpool);
|
||||
mempool_close(scope->mpool);
|
||||
proc->c = NULL;
|
||||
if (mrb->c->cibase && mrb->c->cibase->proc == proc->upper) {
|
||||
proc->upper = NULL;
|
||||
@@ -4223,7 +4217,7 @@ generate_code(mrb_state *mrb, parser_state *p, int val)
|
||||
}
|
||||
MRB_CATCH(mrb->jmp) {
|
||||
mrb_irep_decref(mrb, scope->irep);
|
||||
mrb_mempool_close(scope->mpool);
|
||||
mempool_close(scope->mpool);
|
||||
mrb->jmp = prev_jmp;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
|
||||
#define YYLEX_PARAM p
|
||||
|
||||
#define mrbc_malloc(s) mrb_basic_alloc_func(NULL,(s))
|
||||
#define mrbc_realloc(p,s) mrb_basic_alloc_func((p),(s))
|
||||
#define mrbc_free(p) mrb_basic_alloc_func((p),0)
|
||||
|
||||
typedef mrb_ast_node node;
|
||||
typedef struct mrb_parser_state parser_state;
|
||||
typedef struct mrb_parser_heredoc_info parser_heredoc_info;
|
||||
@@ -111,7 +115,7 @@ cons_free_gen(parser_state *p, node *cons)
|
||||
static void*
|
||||
parser_palloc(parser_state *p, size_t size)
|
||||
{
|
||||
void *m = mrb_mempool_alloc(p->pool, size);
|
||||
void *m = mempool_alloc(p->pool, size);
|
||||
|
||||
if (!m) {
|
||||
MRB_THROW(p->mrb->jmp);
|
||||
@@ -1079,7 +1083,7 @@ static node*
|
||||
composite_string_node(parser_state *p, node *a, node *b)
|
||||
{
|
||||
size_t newlen = (size_t)a->cdr + (size_t)b->cdr;
|
||||
char *str = (char*)mrb_mempool_realloc(p->pool, a->car, (size_t)a->cdr + 1, newlen + 1);
|
||||
char *str = (char*)mempool_realloc(p->pool, a->car, (size_t)a->cdr + 1, newlen + 1);
|
||||
memcpy(str + (size_t)a->cdr, b->car, (size_t)b->cdr);
|
||||
str[newlen] = '\0';
|
||||
a->car = (node*)str;
|
||||
@@ -1453,6 +1457,31 @@ heredoc_end(parser_state *p)
|
||||
}
|
||||
#define is_strterm_type(p,str_func) ((p)->lex_strterm->type & (str_func))
|
||||
|
||||
static void
|
||||
prohibit_literals(parser_state *p, node *n)
|
||||
{
|
||||
if (n == 0) {
|
||||
yyerror(NULL, p, "can't define singleton method for ().");
|
||||
}
|
||||
else {
|
||||
switch (typen(n->car)) {
|
||||
case NODE_INT:
|
||||
case NODE_STR:
|
||||
case NODE_DSTR:
|
||||
case NODE_XSTR:
|
||||
case NODE_DXSTR:
|
||||
case NODE_DREGX:
|
||||
case NODE_MATCH:
|
||||
case NODE_FLOAT:
|
||||
case NODE_ARRAY:
|
||||
case NODE_HEREDOC:
|
||||
yyerror(NULL, p, "can't define singleton method for literals");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* xxx ----------------------------- */
|
||||
|
||||
%}
|
||||
@@ -1515,7 +1544,7 @@ heredoc_end(parser_state *p)
|
||||
modifier_while "'while' modifier"
|
||||
modifier_until "'until' modifier"
|
||||
modifier_rescue "'rescue' modifier"
|
||||
keyword_alias "'alis'"
|
||||
keyword_alias "'alias'"
|
||||
keyword_BEGIN "'BEGIN'"
|
||||
keyword_END "'END'"
|
||||
keyword__LINE__ "'__LINE__'"
|
||||
@@ -4009,30 +4038,13 @@ opt_f_block_arg : ',' f_block_arg
|
||||
|
||||
singleton : var_ref
|
||||
{
|
||||
prohibit_literals(p, $1);
|
||||
$$ = $1;
|
||||
if (!$$) $$ = new_nil(p);
|
||||
}
|
||||
| '(' {p->lstate = EXPR_BEG;} expr rparen
|
||||
{
|
||||
if ($3 == 0) {
|
||||
yyerror(&@1, p, "can't define singleton method for ().");
|
||||
}
|
||||
else {
|
||||
switch (typen($3->car)) {
|
||||
case NODE_STR:
|
||||
case NODE_DSTR:
|
||||
case NODE_XSTR:
|
||||
case NODE_DXSTR:
|
||||
case NODE_DREGX:
|
||||
case NODE_MATCH:
|
||||
case NODE_FLOAT:
|
||||
case NODE_ARRAY:
|
||||
case NODE_HEREDOC:
|
||||
yyerror(&@1, p, "can't define singleton method for literals");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
prohibit_literals(p, $3);
|
||||
$$ = $3;
|
||||
}
|
||||
;
|
||||
@@ -4481,7 +4493,7 @@ static int
|
||||
newtok(parser_state *p)
|
||||
{
|
||||
if (p->tokbuf != p->buf) {
|
||||
mrb_free(p->mrb, p->tokbuf);
|
||||
mrbc_free(p->tokbuf);
|
||||
p->tokbuf = p->buf;
|
||||
p->tsiz = MRB_PARSER_TOKBUF_SIZE;
|
||||
}
|
||||
@@ -4534,11 +4546,11 @@ tokadd(parser_state *p, int32_t c)
|
||||
}
|
||||
p->tsiz *= 2;
|
||||
if (p->tokbuf == p->buf) {
|
||||
p->tokbuf = (char*)mrb_malloc(p->mrb, p->tsiz);
|
||||
p->tokbuf = (char*)mrbc_malloc(p->tsiz);
|
||||
memcpy(p->tokbuf, p->buf, MRB_PARSER_TOKBUF_SIZE);
|
||||
}
|
||||
else {
|
||||
p->tokbuf = (char*)mrb_realloc(p->mrb, p->tokbuf, p->tsiz);
|
||||
p->tokbuf = (char*)mrbc_realloc(p->tokbuf, p->tsiz);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
@@ -6625,7 +6637,7 @@ parser_update_cxt(parser_state *p, mrb_ccontext *cxt)
|
||||
i++;
|
||||
n = n->cdr;
|
||||
}
|
||||
cxt->syms = (mrb_sym*)mrb_realloc(p->mrb, cxt->syms, i*sizeof(mrb_sym));
|
||||
cxt->syms = (mrb_sym*)mrbc_realloc(cxt->syms, i*sizeof(mrb_sym));
|
||||
cxt->slen = i;
|
||||
for (i=0, n=n0; n; i++,n=n->cdr) {
|
||||
cxt->syms[i] = sym(n->car);
|
||||
@@ -6676,13 +6688,13 @@ mrb_parser_parse(parser_state *p, mrb_ccontext *c)
|
||||
MRB_API parser_state*
|
||||
mrb_parser_new(mrb_state *mrb)
|
||||
{
|
||||
mrb_mempool *pool;
|
||||
mempool *pool;
|
||||
parser_state *p;
|
||||
static const parser_state parser_state_zero = { 0 };
|
||||
|
||||
pool = mrb_mempool_open(mrb);
|
||||
pool = mempool_open();
|
||||
if (!pool) return NULL;
|
||||
p = (parser_state*)mrb_mempool_alloc(pool, sizeof(parser_state));
|
||||
p = (parser_state*)mempool_alloc(pool, sizeof(parser_state));
|
||||
if (!p) return NULL;
|
||||
|
||||
*p = parser_state_zero;
|
||||
@@ -6718,23 +6730,26 @@ mrb_parser_new(mrb_state *mrb)
|
||||
MRB_API void
|
||||
mrb_parser_free(parser_state *p) {
|
||||
if (p->tokbuf != p->buf) {
|
||||
mrb_free(p->mrb, p->tokbuf);
|
||||
mrbc_free(p->tokbuf);
|
||||
}
|
||||
mrb_mempool_close(p->pool);
|
||||
mempool_close(p->pool);
|
||||
}
|
||||
|
||||
MRB_API mrb_ccontext*
|
||||
mrb_ccontext_new(mrb_state *mrb)
|
||||
{
|
||||
return (mrb_ccontext*)mrb_calloc(mrb, 1, sizeof(mrb_ccontext));
|
||||
static const mrb_ccontext cc_zero = { 0 };
|
||||
mrb_ccontext *cc = (mrb_ccontext*)mrbc_malloc(sizeof(mrb_ccontext));
|
||||
*cc = cc_zero;
|
||||
return cc;
|
||||
}
|
||||
|
||||
MRB_API void
|
||||
mrb_ccontext_free(mrb_state *mrb, mrb_ccontext *cxt)
|
||||
{
|
||||
mrb_free(mrb, cxt->filename);
|
||||
mrb_free(mrb, cxt->syms);
|
||||
mrb_free(mrb, cxt);
|
||||
mrbc_free(cxt->filename);
|
||||
mrbc_free(cxt->syms);
|
||||
mrbc_free(cxt);
|
||||
}
|
||||
|
||||
MRB_API const char*
|
||||
@@ -6742,12 +6757,12 @@ mrb_ccontext_filename(mrb_state *mrb, mrb_ccontext *c, const char *s)
|
||||
{
|
||||
if (s) {
|
||||
size_t len = strlen(s);
|
||||
char *p = (char*)mrb_malloc_simple(mrb, len + 1);
|
||||
char *p = (char*)mrbc_malloc(len + 1);
|
||||
|
||||
if (p == NULL) return NULL;
|
||||
memcpy(p, s, len + 1);
|
||||
if (c->filename) {
|
||||
mrb_free(mrb, c->filename);
|
||||
mrbc_free(c->filename);
|
||||
}
|
||||
c->filename = p;
|
||||
}
|
||||
@@ -6755,17 +6770,17 @@ mrb_ccontext_filename(mrb_state *mrb, mrb_ccontext *c, const char *s)
|
||||
}
|
||||
|
||||
MRB_API void
|
||||
mrb_ccontext_partial_hook(mrb_state *mrb, mrb_ccontext *c, int (*func)(struct mrb_parser_state*), void *data)
|
||||
mrb_ccontext_partial_hook(mrb_ccontext *c, int (*func)(struct mrb_parser_state*), void *data)
|
||||
{
|
||||
c->partial_hook = func;
|
||||
c->partial_data = data;
|
||||
}
|
||||
|
||||
MRB_API void
|
||||
mrb_ccontext_cleanup_local_variables(mrb_state *mrb, mrb_ccontext *c)
|
||||
mrb_ccontext_cleanup_local_variables(mrb_ccontext *c)
|
||||
{
|
||||
if (c->syms) {
|
||||
mrb_free(mrb, c->syms);
|
||||
mrbc_free(c->syms);
|
||||
c->syms = NULL;
|
||||
c->slen = 0;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,55 @@
|
||||
# mruby-complex
|
||||
|
||||
mruby-complex is an mrbgem that provides a `Complex` class for mruby, allowing for the representation and manipulation of complex numbers. It is designed to be compatible with the Complex class in standard Ruby.
|
||||
|
||||
## Functionality
|
||||
|
||||
The `Complex` class provided by this mrbgem supports:
|
||||
|
||||
- Creation of complex numbers from real and imaginary parts, or using the `i` suffix for numbers.
|
||||
- Basic arithmetic operations: addition (`+`), subtraction (`-`), multiplication (`*`), division (`/`).
|
||||
- Methods to access the real and imaginary parts (`real`, `imaginary` or `imag`).
|
||||
- Calculation of absolute value (`abs`, `magnitude`), argument/angle (`arg`, `angle`, `phase`), and square of the absolute value (`abs2`).
|
||||
- Complex conjugate (`conjugate`, `conj`).
|
||||
- Conversion to polar coordinates (`polar`).
|
||||
- Conversion to other numeric types where appropriate (`to_f`, `to_i`, `to_r`, `to_c`).
|
||||
- Inspection and string representation (`inspect`, `to_s`).
|
||||
|
||||
## Usage Examples
|
||||
|
||||
Here are some basic examples of how to use the `Complex` class:
|
||||
|
||||
```ruby
|
||||
# Creating complex numbers
|
||||
c1 = Complex(1, 2) # => (1+2i)
|
||||
c2 = 3 + 4i # => (3+4i)
|
||||
c3 = Complex.polar(5, Math::PI/2) # => (0.0+5.0i) (approximately)
|
||||
|
||||
# Arithmetic operations
|
||||
puts c1 + c2 # => (4+6i)
|
||||
puts c1 - c2 # => (-2-2i)
|
||||
puts c1 * c2 # => (-5+10i)
|
||||
puts c1 / c2 # => (0.44+0.08i)
|
||||
|
||||
# Accessing parts
|
||||
puts c1.real # => 1
|
||||
puts c1.imaginary # => 2
|
||||
|
||||
# Other methods
|
||||
puts c2.abs # => 5.0
|
||||
puts c2.arg # => 0.9272952180016122 (radians)
|
||||
puts c2.conjugate # => (3-4i)
|
||||
puts c1.polar # => [2.23606797749979, 1.1071487177940904]
|
||||
|
||||
# Numerics can be converted to Complex
|
||||
puts 5.to_c # => (5+0i)
|
||||
puts 2.3.to_c # => (2.3+0i)
|
||||
|
||||
# The `i` method on numerics creates a complex number with zero real part
|
||||
puts 5i # => (0+5i)
|
||||
puts 2.3i # => (0+2.3i)
|
||||
```
|
||||
|
||||
## Note
|
||||
|
||||
This mrbgem aims to provide functionality similar to the `Complex` class found in the standard Ruby library. Refer to the Ruby documentation for `Complex` for more detailed information on the behavior of various methods.
|
||||
@@ -0,0 +1,126 @@
|
||||
# mruby-data
|
||||
|
||||
The `mruby-data` mrbgem provides a way to define simple classes in mruby that act as data structures, similar to Ruby's `Struct` class. It allows you to bundle a number of attributes together and access them using accessor methods.
|
||||
|
||||
## Purpose
|
||||
|
||||
`mruby-data` is useful when you need to create lightweight objects that primarily serve to hold and provide access to a set of data attributes without the need to write a full class definition manually.
|
||||
|
||||
## Functionality
|
||||
|
||||
### Defining a Data Class
|
||||
|
||||
You can define a new data class using the `Data.define` class method. It accepts one or more symbols as arguments, which will become the attribute names for the instances of the generated class.
|
||||
|
||||
```ruby
|
||||
# Defines a new class 'Point' with attributes :x and :y
|
||||
Point = Data.define(:x, :y)
|
||||
|
||||
# Defines a new class 'Customer' with attributes :name, :address, and :zip
|
||||
Customer = Data.define(:name, :address, :zip)
|
||||
```
|
||||
|
||||
### Creating Instances
|
||||
|
||||
Once a data class is defined, you can create instances of it using the `new` method, providing values for each attribute in the order they were defined.
|
||||
|
||||
```ruby
|
||||
# Create an instance of Point
|
||||
point1 = Point.new(10, 20)
|
||||
|
||||
# Create an instance of Customer
|
||||
customer1 = Customer.new("John Doe", "123 Main St", 12345)
|
||||
```
|
||||
|
||||
Alternatively, you can pass keyword arguments (available if mruby is compiled with `MRB_KW_ARGS`):
|
||||
|
||||
```ruby
|
||||
customer2 = Customer.new(name: "Jane Doe", address: "456 Oak Ave", zip: 67890)
|
||||
```
|
||||
|
||||
### Accessing Attributes
|
||||
|
||||
Instances of data classes have accessor methods for each defined attribute.
|
||||
|
||||
```ruby
|
||||
puts point1.x # Output: 10
|
||||
puts point1.y # Output: 20
|
||||
|
||||
puts customer1.name # Output: "John Doe"
|
||||
```
|
||||
|
||||
### Instance Methods
|
||||
|
||||
Instances of classes created by `Data.define` have several useful methods:
|
||||
|
||||
- **`members`**: Returns an array of symbols representing the names of the attributes.
|
||||
|
||||
```ruby
|
||||
p customer1.members # Output: [:name, :address, :zip]
|
||||
```
|
||||
|
||||
- **`== (other)`**: Returns `true` if `other` is an instance of the same data class and all attribute values are equal.
|
||||
|
||||
```ruby
|
||||
point2 = Point.new(10, 20)
|
||||
point3 = Point.new(0, 0)
|
||||
|
||||
puts point1 == point2 # Output: true
|
||||
puts point1 == point3 # Output: false
|
||||
```
|
||||
|
||||
- **`eql?(other)`**: Similar to `==`, checks if `other` is an instance of the same data class and all attribute values are `eql?`.
|
||||
|
||||
- **`to_h`**: Converts the data instance into a hash where keys are the attribute symbols and values are their corresponding values.
|
||||
|
||||
```ruby
|
||||
p customer1.to_h
|
||||
# Output: {:name=>"John Doe", :address=>"123 Main St", :zip=>12345}
|
||||
```
|
||||
|
||||
- **`to_s` / `inspect`**: Returns a string representation of the data instance.
|
||||
|
||||
```ruby
|
||||
puts customer1 # Output: #<data Customer name="John Doe", address="123 Main St", zip=12345>
|
||||
p customer1 # Output: #<data Customer name="John Doe", address="123 Main St", zip=12345>
|
||||
```
|
||||
|
||||
## Freezing
|
||||
|
||||
By default, instances of data classes are frozen after initialization, meaning their attributes cannot be modified after creation.
|
||||
|
||||
```ruby
|
||||
point = Point.new(1, 2)
|
||||
# The following would raise an error as the object is frozen:
|
||||
# point.x = 100
|
||||
```
|
||||
|
||||
## Example Usage
|
||||
|
||||
```ruby
|
||||
# Define a class for 2D vectors
|
||||
Vector2D = Data.define(:x, :y)
|
||||
|
||||
# Create some vector instances
|
||||
v1 = Vector2D.new(3, 4)
|
||||
v2 = Vector2D.new(1, 5)
|
||||
|
||||
# Access attributes
|
||||
puts "Vector v1: (#{v1.x}, #{v1.y})"
|
||||
puts "Vector v2: (#{v2.x}, #{v2.y})"
|
||||
|
||||
# Use instance methods
|
||||
puts "v1 members: #{v1.members}"
|
||||
puts "v1 as hash: #{v1.to_h}"
|
||||
|
||||
# Comparison
|
||||
v3 = Vector2D.new(3, 4)
|
||||
puts "v1 == v2: #{v1 == v2}" # false
|
||||
puts "v1 == v3: #{v1 == v3}" # true
|
||||
```
|
||||
|
||||
This mrbgem simplifies the creation of simple value objects in mruby.
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
@@ -493,7 +493,7 @@ mrb_mruby_data_gem_init(mrb_state* mrb)
|
||||
mrb_define_method_id(mrb, d, MRB_OPSYM(eq), mrb_data_equal, MRB_ARGS_REQ(1));
|
||||
mrb_define_method_id(mrb, d, MRB_SYM(members), mrb_data_members, MRB_ARGS_NONE());
|
||||
mrb_define_method_id(mrb, d, MRB_SYM(initialize), mrb_data_initialize, MRB_ARGS_ANY());
|
||||
mrb_define_method_id(mrb, d, MRB_SYM(initialize_copy), mrb_data_init_copy, MRB_ARGS_ANY());
|
||||
mrb_define_private_method_id(mrb, d, MRB_SYM(initialize_copy), mrb_data_init_copy, MRB_ARGS_ANY());
|
||||
mrb_define_method_id(mrb, d, MRB_SYM_Q(eql), mrb_data_eql, MRB_ARGS_REQ(1));
|
||||
|
||||
mrb_define_method_id(mrb, d, MRB_SYM(to_h), mrb_data_to_h, MRB_ARGS_NONE());
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
# mruby-encoding
|
||||
|
||||
This mrbgem provides a lightweight, "poorman's" encoding functionality for mruby. It is designed to offer basic encoding support, primarily focused on UTF-8 and ASCII-8BIT.
|
||||
|
||||
## Summary
|
||||
|
||||
- **License:** MIT
|
||||
- **Author:** mruby developers
|
||||
- **Supported Encodings:**
|
||||
- `Encoding::UTF_8`
|
||||
- `Encoding::ASCII_8BIT` (aliased as `Encoding::BINARY`)
|
||||
|
||||
## Functionality
|
||||
|
||||
This gem introduces an `Encoding` module and extends the `String` and `Integer` classes with encoding-related methods.
|
||||
|
||||
### `Encoding` Module
|
||||
|
||||
A module (not a class, unlike standard Ruby) that holds encoding constants.
|
||||
|
||||
- `Encoding::UTF_8`: Represents the UTF-8 encoding.
|
||||
- `Encoding::ASCII_8BIT`: Represents the ASCII-8BIT encoding.
|
||||
- `Encoding::BINARY`: An alias for `Encoding::ASCII_8BIT`.
|
||||
|
||||
### `String` Methods
|
||||
|
||||
- `string.valid_encoding? -> true or false`
|
||||
- Returns `true` if the string is correctly encoded (particularly useful for UTF-8 strings). For `ASCII-8BIT` strings, it generally returns `true`.
|
||||
- `string.encoding -> EncodingConstant`
|
||||
- Returns the encoding of the string. This will be `Encoding::UTF_8` or `Encoding::BINARY`.
|
||||
- `string.force_encoding(encoding_name) -> string`
|
||||
- Changes the string's reported encoding to the specified `encoding_name` (e.g., "UTF-8", "ASCII-8BIT", "BINARY").
|
||||
- The actual byte sequence of the string is not changed.
|
||||
- Raises an `ArgumentError` if an unsupported encoding name is provided.
|
||||
|
||||
### `Integer` Method
|
||||
|
||||
- `integer.chr(encoding_name = Encoding::BINARY) -> String`
|
||||
- Returns a single-character string represented by the integer.
|
||||
- If `encoding_name` is "UTF-8", the integer is treated as a Unicode codepoint.
|
||||
- If `encoding_name` is "ASCII-8BIT" or "BINARY" (the default), the integer is treated as a byte value (0-255).
|
||||
- Raises a `RangeError` if the integer is out of the valid range for the specified encoding.
|
||||
- Raises an `ArgumentError` for unknown encoding names.
|
||||
|
||||
## Usage Example
|
||||
|
||||
```ruby
|
||||
# main.rb
|
||||
if __ENCODING__ == "UTF-8"
|
||||
s = "helloあ"
|
||||
puts s.encoding #=> Encoding::UTF_8
|
||||
puts s.valid_encoding? #=> true
|
||||
|
||||
s2 = "\xff".force_encoding("UTF-8")
|
||||
puts s2.valid_encoding? #=> false
|
||||
|
||||
s3 = "world"
|
||||
s3.force_encoding("BINARY")
|
||||
puts s3.encoding #=> Encoding::BINARY
|
||||
puts s3.valid_encoding? #=> true (ASCII-8BIT strings are generally considered valid)
|
||||
|
||||
puts 65.chr #=> "A" (defaults to ASCII-8BIT)
|
||||
puts 230.chr("UTF-8") #=> "æ" (if U+00E6 is æ)
|
||||
# For mruby, this might be different based on actual UTF-8 char mapping
|
||||
# For example, 12354.chr("UTF-8") might be "あ"
|
||||
else
|
||||
s = "hello"
|
||||
puts s.encoding #=> Encoding::BINARY (or ASCII-8BIT)
|
||||
|
||||
# Attempting to force to UTF-8 in a non-UTF-8 mruby build might be limited
|
||||
# or behave as ASCII-8BIT depending on mruby's core string handling.
|
||||
end
|
||||
|
||||
# Force encoding
|
||||
my_string = "\xE3\x81\x82" # UTF-8 bytes for "あ"
|
||||
puts my_string.encoding # Might be BINARY by default if not created as UTF-8 literal
|
||||
|
||||
my_string.force_encoding("UTF-8")
|
||||
puts my_string.encoding #=> Encoding::UTF_8
|
||||
puts my_string #=> あ
|
||||
|
||||
invalid_utf8 = "\xff\xfe"
|
||||
invalid_utf8.force_encoding("UTF-8")
|
||||
puts invalid_utf8.valid_encoding? #=> false
|
||||
|
||||
# Integer#chr
|
||||
puts 65.chr # => "A"
|
||||
puts 65.chr("BINARY") # => "A"
|
||||
|
||||
# When mruby is compiled with MRB_UTF8_STRING
|
||||
if Object.const_defined?(:MRB_UTF8_STRING)
|
||||
puts 12354.chr("UTF-8") # => "あ"
|
||||
# puts 0x110000.chr("UTF-8") #=> RangeError
|
||||
end
|
||||
|
||||
```
|
||||
@@ -0,0 +1,80 @@
|
||||
# mruby-enum-chain
|
||||
|
||||
## Description
|
||||
|
||||
This mrbgem provides the `Enumerator::Chain` class, which allows you to chain multiple enumerable objects together, treating them as a single, continuous enumerable.
|
||||
|
||||
This is useful when you have multiple collections (e.g., arrays, ranges, or other enumerators) and you want to iterate over all of them sequentially without first concatenating them into a single, larger collection.
|
||||
|
||||
## How to Use
|
||||
|
||||
There are three main ways to create an `Enumerator::Chain` instance:
|
||||
|
||||
### 1. Using `Enumerable#chain`
|
||||
|
||||
You can call the `chain` method on any object that includes the `Enumerable` module.
|
||||
|
||||
```ruby
|
||||
a = [1, 2, 3]
|
||||
b = (4..6)
|
||||
c = {foo: 7, bar: 8}.each_key # Enumerator for keys
|
||||
|
||||
chained_enum = a.chain(b, c)
|
||||
chained_enum.to_a # => [1, 2, 3, 4, 5, 6, :foo, :bar]
|
||||
```
|
||||
|
||||
### 2. Using `Enumerator#+`
|
||||
|
||||
You can use the `+` operator on an `Enumerator` instance to chain it with another enumerable object.
|
||||
|
||||
```ruby
|
||||
enum1 = [1, 2].each
|
||||
enum2 = %w(a b).each
|
||||
|
||||
chained_enum = enum1 + enum2
|
||||
chained_enum.to_a # => [1, 2, "a", "b"]
|
||||
|
||||
# You can chain multiple times
|
||||
enum3 = (10..11).each
|
||||
chained_enum_2 = enum1 + enum2 + enum3
|
||||
chained_enum_2.to_a # => [1, 2, "a", "b", 10, 11]
|
||||
```
|
||||
|
||||
### 3. Using `Enumerator::Chain.new`
|
||||
|
||||
You can directly instantiate `Enumerator::Chain` by passing enumerable objects to its constructor.
|
||||
|
||||
```ruby
|
||||
arr = [10, 20]
|
||||
rng = (30..31)
|
||||
|
||||
chained_enum = Enumerator::Chain.new(arr, rng)
|
||||
chained_enum.to_a # => [10, 20, 30, 31]
|
||||
```
|
||||
|
||||
## Key Features
|
||||
|
||||
- **`each(&block)`**: Iterates through each element of the chained enumerables in the order they were added. Returns an enumerator if no block is given.
|
||||
- **`size`**: Returns the total number of elements in all chained enumerables. If any of the chained enumerables do not respond to `size` (e.g., an infinite enumerator or one with an unknown size), this method will return `nil`.
|
||||
|
||||
```ruby
|
||||
([1, 2].chain([3, 4])).size # => 4
|
||||
([1, 2].chain( (1..Float::INFINITY) )).size # => nil
|
||||
```
|
||||
|
||||
- **`rewind`**: Rewinds all of the chained enumerables that respond to the `rewind` method. This resets the iteration state to the beginning.
|
||||
|
||||
```ruby
|
||||
e = [1,2].chain(3..4)
|
||||
e.next # => 1
|
||||
e.next # => 2
|
||||
e.next # => 3
|
||||
e.rewind
|
||||
e.next # => 1
|
||||
```
|
||||
|
||||
- **`+(other)`**: Creates a new `Enumerator::Chain` by appending another enumerable to the current chain.
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
@@ -0,0 +1,487 @@
|
||||
# mruby-enum-ext
|
||||
|
||||
This mrbgem extends the `Enumerable` module in mruby with additional useful methods.
|
||||
|
||||
## Added Methods
|
||||
|
||||
Below is a list of methods added to the `Enumerable` module, along with a brief description and example for each.
|
||||
|
||||
---
|
||||
|
||||
### `drop(n)`
|
||||
|
||||
Drops the first `n` elements from an enumerable and returns the rest of the elements in an array.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
a = [1, 2, 3, 4, 5, 0]
|
||||
a.drop(3) #=> [4, 5, 0]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `drop_while { |obj| block }`
|
||||
|
||||
Drops elements up to, but not including, the first element for which the block returns `nil` or `false`. Returns an array containing the remaining elements. If no block is given, an enumerator is returned.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
a = [1, 2, 3, 4, 5, 0]
|
||||
a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `take(n)`
|
||||
|
||||
Returns the first `n` elements from an enumerable as an array.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
a = [1, 2, 3, 4, 5, 0]
|
||||
a.take(3) #=> [1, 2, 3]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `take_while { |obj| block }`
|
||||
|
||||
Passes elements to the block until the block returns `nil` or `false`, then stops iterating and returns an array of all prior elements. If no block is given, an enumerator is returned.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
a = [1, 2, 3, 4, 5, 0]
|
||||
a.take_while {|i| i < 3 } #=> [1, 2]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `each_cons(n) { |a| block }`
|
||||
|
||||
Iterates the given block for each array of consecutive `n` elements. If no block is given, an enumerator is returned.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
(1..10).each_cons(3) {|a| p a}
|
||||
# outputs below
|
||||
# [1, 2, 3]
|
||||
# [2, 3, 4]
|
||||
# [3, 4, 5]
|
||||
# [4, 5, 6]
|
||||
# [5, 6, 7]
|
||||
# [6, 7, 8]
|
||||
# [7, 8, 9]
|
||||
# [8, 9, 10]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `each_slice(n) { |a| block }`
|
||||
|
||||
Iterates the given block for each slice of `n` elements. If no block is given, an enumerator is returned.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
(1..10).each_slice(3) {|a| p a}
|
||||
# outputs below
|
||||
# [1, 2, 3]
|
||||
# [4, 5, 6]
|
||||
# [7, 8, 9]
|
||||
# [10]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `group_by { |obj| block }`
|
||||
|
||||
Groups the collection by the result of the block. Returns a hash where keys are the evaluated result from the block and values are arrays of elements corresponding to the key. If no block is given, an enumerator is returned.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
(1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `sort_by { |obj| block }`
|
||||
|
||||
Sorts the enumerable using a set of keys generated by mapping the values in the enumerable through the given block. Returns an array. If no block is given, an enumerator is returned. (Note: `Array#sort_by` and `Array#sort_by!` are also implemented for optimized in-place sorting for arrays).
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
%w(apple pear fig).sort_by { |word| word.length }
|
||||
#=> ["fig", "pear", "apple"]
|
||||
```
|
||||
|
||||
_(Example adapted, original was for `Array#sort_by`)_
|
||||
|
||||
---
|
||||
|
||||
### `first` / `first(n)`
|
||||
|
||||
Returns the first element, or the first `n` elements, of the enumerable. If the enumerable is empty, `first` returns `nil`, and `first(n)` returns an empty array.
|
||||
|
||||
_Examples:_
|
||||
|
||||
```ruby
|
||||
a = [1, 2, 3, 4, 5]
|
||||
a.first #=> 1
|
||||
a.first(3) #=> [1, 2, 3]
|
||||
[].first #=> nil
|
||||
[].first(3) #=> []
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `count` / `count(item)` / `count { |obj| block }`
|
||||
|
||||
Returns the number of items in the enumerable.
|
||||
|
||||
- If an argument `item` is given, counts items equal to `item`.
|
||||
- If a block is given, counts elements yielding a true value.
|
||||
- If no argument or block is given, counts all items.
|
||||
|
||||
_Examples:_
|
||||
|
||||
```ruby
|
||||
[1, 2, 3, 2].count #=> 4
|
||||
[1, 2, 3, 2].count(2) #=> 2
|
||||
[1, 2, 3, 4].count { |x| x%2 == 0 } #=> 2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `flat_map { |obj| block }` (alias: `collect_concat`)
|
||||
|
||||
Returns a new array with the concatenated results of running the block once for every element. If no block is given, an enumerator is returned.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
[1, 2, 3, 4].flat_map { |e| [e, -e] } #=> [1, -1, 2, -2, 3, -3, 4, -4]
|
||||
[[1, 2], [3, 4]].flat_map { |e| e + [100] } #=> [1, 2, 100, 3, 4, 100]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `max_by { |obj| block }`
|
||||
|
||||
Returns the object in the enumerable that gives the maximum value from the given block. If no block is given, an enumerator is returned.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
%w[albatross dog horse].max_by {|x| x.length } #=> "albatross"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `min_by { |obj| block }`
|
||||
|
||||
Returns the object in the enumerable that gives the minimum value from the given block. If no block is given, an enumerator is returned.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
%w[albatross dog horse].min_by {|x| x.length } #=> "dog"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `minmax` / `minmax { |a, b| block }`
|
||||
|
||||
Returns a two-element array containing the minimum and maximum values. The first form assumes objects implement `Comparable`; the second uses the block to return `a <=> b`.
|
||||
|
||||
_Examples:_
|
||||
|
||||
```ruby
|
||||
a = %w(albatross dog horse)
|
||||
a.minmax #=> ["albatross", "horse"]
|
||||
a.minmax { |a, b| a.length <=> b.length } #=> ["dog", "albatross"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `minmax_by { |obj| block }`
|
||||
|
||||
Returns a two-element array containing the objects that correspond to the minimum and maximum values from the given block. If no block is given, an enumerator is returned.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
%w(albatross dog horse).minmax_by { |x| x.length } #=> ["dog", "albatross"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `none?` / `none? { |obj| block }` / `none?(pattern)`
|
||||
|
||||
- With a block: Returns `true` if the block never returns `true` for any element.
|
||||
- With a pattern: Returns `true` if `pattern === element` is never true for any element.
|
||||
- With no argument or block: Returns `true` if none of the collection members are truthy.
|
||||
|
||||
_Examples:_
|
||||
|
||||
```ruby
|
||||
%w(ant bear cat).none? { |word| word.length == 5 } #=> true
|
||||
%w(ant bear cat).none? { |word| word.length >= 4 } #=> false
|
||||
%w{ant bear cat}.none?(/d/) #=> true
|
||||
[1, 3.14, 42].none?(Float) #=> false
|
||||
[].none? #=> true
|
||||
[nil, false].none? #=> true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `one?` / `one? { |obj| block }` / `one?(pattern)`
|
||||
|
||||
- With a block: Returns `true` if the block returns `true` exactly once.
|
||||
- With a pattern: Returns `true` if `pattern === element` is true for exactly one element.
|
||||
- With no argument or block: Returns `true` if exactly one of the collection members is truthy.
|
||||
|
||||
_Examples:_
|
||||
|
||||
```ruby
|
||||
%w(ant bear cat).one? { |word| word.length == 4 } #=> true
|
||||
%w(ant bear cat).one? { |word| word.length > 4 } #=> false
|
||||
%w{ant bear cat}.one?(/t/) #=> false # (Note: original example might be specific to mruby version, "ant" and "cat" contain "t")
|
||||
[nil, true, false].one? #=> true
|
||||
[nil, true, 99].one?(Integer) #=> true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `all?` / `all? { |obj| block }` / `all?(pattern)`
|
||||
|
||||
- With a block: Returns `true` if the block never returns `false` or `nil` for any element.
|
||||
- With a pattern: Returns `true` if `pattern === element` is true for every element.
|
||||
- With no argument or block: Returns `true` if all collection members are truthy.
|
||||
|
||||
_Examples:_
|
||||
|
||||
```ruby
|
||||
%w[ant bear cat].all? { |word| word.length >= 3 } #=> true
|
||||
%w[ant bear cat].all? { |word| word.length >= 4 } #=> false
|
||||
[1, 2i, 3.14].all?(Numeric) #=> true
|
||||
[nil, true, 99].all? #=> false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `any?` / `any? { |obj| block }` / `any?(pattern)`
|
||||
|
||||
- With a block: Returns `true` if the block ever returns a truthy value for an element.
|
||||
- With a pattern: Returns `true` if `pattern === element` is true for any element.
|
||||
- With no argument or block: Returns `true` if at least one collection member is truthy.
|
||||
|
||||
_Examples:_
|
||||
|
||||
```ruby
|
||||
%w[ant bear cat].any? { |word| word.length >= 3 } #=> true
|
||||
%w[ant bear cat].any?(/d/) #=> false
|
||||
[nil, true, 99].any?(Integer) #=> true
|
||||
[nil, true, 99].any? #=> true
|
||||
[].any? #=> false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `each_with_object(obj) { |(*args), memo_obj| ... }`
|
||||
|
||||
Iterates the given block for each element with an arbitrary object `obj` given, and returns the initially given `obj`. If no block is given, an enumerator is returned.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
(1..10).each_with_object([]) { |i, a| a << i*2 }
|
||||
#=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `reverse_each { |item| block }`
|
||||
|
||||
Builds a temporary array and traverses that array in reverse order, executing the block for each item. If no block is given, an enumerator is returned.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
(1..3).reverse_each { |v| p v }
|
||||
# produces:
|
||||
# 3
|
||||
# 2
|
||||
# 1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `cycle(n=nil) { |obj| block }`
|
||||
|
||||
Calls the block for each element repeatedly `n` times, or forever if `n` is `nil`. If `n` is non-positive or the collection is empty, does nothing. Returns `nil` if the loop finishes. If no block is given, an enumerator is returned.
|
||||
|
||||
_Examples:_
|
||||
|
||||
```ruby
|
||||
a = ["a", "b", "c"]
|
||||
# a.cycle { |x| puts x } # print, a, b, c, a, b, c,.. forever.
|
||||
a.cycle(2) { |x| puts x } # print, a, b, c, a, b, c.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `find_index(value)` / `find_index { |obj| block }`
|
||||
|
||||
Compares each entry with `value` or passes to `block`. Returns the index for the first non-false evaluation. If no object matches, returns `nil`. If no argument or block is given, an enumerator is returned.
|
||||
|
||||
_Examples:_
|
||||
|
||||
```ruby
|
||||
(1..100).find_index { |i| i % 5 == 0 and i % 7 == 0 } #=> 34
|
||||
(1..100).find_index(50) #=> 49
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `zip(arg, ...) { |arr| block }`
|
||||
|
||||
Takes one element from the enumerable and merges corresponding elements from each `arg`. Generates a sequence of n-element arrays. The length will be `enum#size`. If any argument is shorter, `nil` values are supplied. If a block is given, it's invoked for each output array; otherwise, an array of arrays is returned.
|
||||
|
||||
_Examples:_
|
||||
|
||||
```ruby
|
||||
a = [ 4, 5, 6 ]
|
||||
b = [ 7, 8, 9 ]
|
||||
a.zip(b) #=> [[4, 7], [5, 8], [6, 9]]
|
||||
[1, 2].zip(a, b) #=> [[1, 4, 7], [2, 5, 8]]
|
||||
c = []
|
||||
a.zip(b) { |x, y| c << x + y } #=> nil
|
||||
c #=> [11, 13, 15]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `to_h { |element| block }`
|
||||
|
||||
Returns a hash by interpreting the enumerable as a list of `[key, value]` pairs. If a block is given, it's used to transform elements before they are converted into pairs.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
%i[hello world].each_with_index.to_h
|
||||
# => {:hello => 0, :world => 1}
|
||||
|
||||
# With a block (example assumes a suitable block)
|
||||
# (0..3).to_h {|x| [x, x*x] } # => {0=>0, 1=>1, 2=>4, 3=>9} (Conceptual example)
|
||||
```
|
||||
|
||||
_(The `to_h` method in the source is a bit complex with its block handling; the example is simplified.)_
|
||||
|
||||
---
|
||||
|
||||
### `uniq { |item| block }`
|
||||
|
||||
Returns a new array by removing duplicate values. If a block is given, it will use the return value of the block for uniqueness comparison.
|
||||
|
||||
_Examples:_
|
||||
|
||||
```ruby
|
||||
[1, 2, 2, 3, 1].uniq #=> [1, 2, 3]
|
||||
["a", "B", "c", "b"].uniq { |s| s.downcase } #=> ["a", "B", "c"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `filter_map { |obj| block }`
|
||||
|
||||
Returns a new array containing the truthy results of running the block for every element. If no block is given, an enumerator is returned.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
[-2, -1, 0, 1, 2].filter_map { |x| x*2 if x > 0 } #=> [2, 4]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `grep_v(pattern) { |obj| block }`
|
||||
|
||||
Returns an array of elements that do NOT match the `pattern`. If a block is given, the elements of the result are passed to the block and the block's results are returned.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
a = ["apple", "banana", "orange", "grape"]
|
||||
a.grep_v(/an/) #=> ["apple", "orange", "grape"]
|
||||
a.grep_v(/an/) { |s| s.upcase } #=> ["APPLE", "ORANGE", "GRAPE"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `tally`
|
||||
|
||||
Tallies the collection. Returns a hash where keys are elements and values are their counts.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
["a", "b", "c", "b"].tally #=> {"a"=>1, "b"=>2, "c"=>1}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `sum(initial=0) { |obj| block }`
|
||||
|
||||
Returns the sum of elements. If a block is given, each element is processed by the block before addition. `initial` is the starting value for the sum.
|
||||
|
||||
_Examples:_
|
||||
|
||||
```ruby
|
||||
[1, 2, 3].sum #=> 6
|
||||
[1, 2, 3].sum(10) #=> 16
|
||||
[1, 2, 3].sum { |x| x * 2 } #=> 12
|
||||
({a:1, b:2, c:3}).sum {|k,v| v} #=> 6 (Example from Ruby docs, assuming similar behavior)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `each_entry(*args) { |obj| block }`
|
||||
|
||||
Calls block once for each element, passing that element as a parameter (converting multiple values from yield to an array). If no block is given, an enumerator is returned.
|
||||
|
||||
_Example:_
|
||||
|
||||
```ruby
|
||||
class Foo
|
||||
include Enumerable
|
||||
def each
|
||||
yield 1
|
||||
yield 1, 2
|
||||
yield
|
||||
end
|
||||
end
|
||||
Foo.new.each_entry{ |o| p o }
|
||||
# produces:
|
||||
# 1
|
||||
# [1, 2]
|
||||
# nil
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Note on `Array#sort_by` and `Array#sort_by!`**
|
||||
|
||||
The gem also provides optimized `sort_by` and `sort_by!` methods directly on the `Array` class. `sort_by!` sorts the array in place.
|
||||
|
||||
```ruby
|
||||
arr = ["apple", "pear", "fig"]
|
||||
arr.sort_by! { |word| word.length }
|
||||
p arr #=> ["fig", "pear", "apple"]
|
||||
```
|
||||
@@ -820,8 +820,8 @@ module Enumerable
|
||||
return to_enum(:filter_map) unless blk
|
||||
|
||||
ary = []
|
||||
self.each do |x|
|
||||
x = blk.call(x)
|
||||
self.each do |*x|
|
||||
x = blk.call(*x)
|
||||
ary.push x if x
|
||||
end
|
||||
ary
|
||||
@@ -851,7 +851,8 @@ module Enumerable
|
||||
# ["a", "b", "c", "b"].tally #=> {"a"=>1, "b"=>2, "c"=>1}
|
||||
def tally
|
||||
hash = {}
|
||||
self.each do |x|
|
||||
self.each do |*x|
|
||||
x = x.__svalue
|
||||
hash[x] = (hash[x]||0)+1
|
||||
end
|
||||
hash
|
||||
@@ -870,12 +871,12 @@ module Enumerable
|
||||
def sum(init=0,&block)
|
||||
result=init
|
||||
if block
|
||||
self.each do |e|
|
||||
result += block.call(e)
|
||||
self.each do |*e|
|
||||
result += block.call(*e)
|
||||
end
|
||||
else
|
||||
self.each do |e|
|
||||
result += e
|
||||
self.each do |*e|
|
||||
result += e.__svalue
|
||||
end
|
||||
end
|
||||
result
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
# mruby-enum-lazy
|
||||
|
||||
## Overview
|
||||
|
||||
This mrbgem provides lazy evaluation for Enumerable objects in mruby. It introduces the `Enumerable#lazy` method, which returns an instance of `Enumerator::Lazy`. This allows for more efficient processing of collections, especially large or potentially infinite sequences, by evaluating elements only when they are needed.
|
||||
|
||||
## Functionality
|
||||
|
||||
When you call `.lazy` on an Enumerable object (like an Array or Range), you get back an `Enumerator::Lazy` object. This object behaves much like a regular Enumerator, but with a key difference: methods that transform the collection are deferred until the results are actually required.
|
||||
|
||||
The following methods are implemented to act lazily:
|
||||
|
||||
- `map` / `collect`
|
||||
- `select` / `find_all`
|
||||
- `reject`
|
||||
- `grep`
|
||||
- `grep_v`
|
||||
- `drop`
|
||||
- `drop_while`
|
||||
- `take`
|
||||
- `take_while`
|
||||
- `flat_map` / `collect_concat`
|
||||
- `zip`
|
||||
- `uniq`
|
||||
|
||||
To trigger the evaluation of the lazy operations and retrieve all results (if finite), you can use methods like `force` or `to_a`.
|
||||
|
||||
### How it works
|
||||
|
||||
Operations on an `Enumerator::Lazy` object are chained together. The actual computation of each element is postponed until it's requested (e.g., by `force`, `to_a`, or iterating with `each`). This can lead to significant performance improvements by avoiding unnecessary computations and memory allocations, particularly when dealing with large data sets or when only a subset of results is needed.
|
||||
|
||||
## Usage Example
|
||||
|
||||
Here's a simple example demonstrating lazy evaluation:
|
||||
|
||||
```ruby
|
||||
# Without lazy evaluation
|
||||
# This would attempt to create an infinite array, which is not feasible.
|
||||
# (1..Float::INFINITY).map { |x| x * x }.select { |x| x % 2 == 0 }.take(5).to_a
|
||||
|
||||
# With lazy evaluation
|
||||
p (1..Float::INFINITY).lazy.map { |x| x * x }.select { |x| x % 2 == 0 }.take(5).force
|
||||
# Output: [4, 16, 36, 64, 100]
|
||||
|
||||
# Another example:
|
||||
a = [1, 2, 3, 4, 5]
|
||||
lazy_sequence = a.lazy.map do |x|
|
||||
puts "mapping #{x}"
|
||||
x * 10
|
||||
end.select do |x|
|
||||
puts "selecting #{x}"
|
||||
x > 20
|
||||
end
|
||||
|
||||
puts "Applying force..."
|
||||
result = lazy_sequence.force
|
||||
# Output:
|
||||
# mapping 1
|
||||
# selecting 10
|
||||
# mapping 2
|
||||
# selecting 20
|
||||
# mapping 3
|
||||
# selecting 30
|
||||
# mapping 4
|
||||
# selecting 40
|
||||
# mapping 5
|
||||
# selecting 50
|
||||
# Applying force...
|
||||
p result # Output: [30, 40, 50]
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
This gem depends on the following mruby core gems:
|
||||
|
||||
- `mruby-enumerator`
|
||||
- `mruby-enum-ext`
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
|
||||
## Author
|
||||
|
||||
mruby developers
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
Based on <https://github.com/yhara/enumerable-lazy>
|
||||
Inspired by <https://github.com/antimon2/enumerable_lz>
|
||||
Reference: <http://jp.rubyist.net/magazine/?0034-Enumerable_lz> (ja)
|
||||
@@ -0,0 +1,89 @@
|
||||
# mruby-enumerator
|
||||
|
||||
The `mruby-enumerator` mrbgem provides the `Enumerator` class, which allows for both internal and external iteration in mruby.
|
||||
|
||||
## Purpose and Functionality
|
||||
|
||||
Enumerators are useful when you want to work with collections of data in a flexible way. They allow you to:
|
||||
|
||||
- **Iterate externally:** Fetch elements one by one using methods like `next`.
|
||||
- **Chain operations:** Combine multiple iteration steps (e.g., mapping and then selecting) without creating intermediate arrays.
|
||||
- **Create custom iterators:** Define your own iteration logic.
|
||||
|
||||
## Creating an Enumerator
|
||||
|
||||
You can create an `Enumerator` in several ways:
|
||||
|
||||
1. **Using `Kernel#to_enum` or `Kernel#enum_for`:** This is the most common way. You can turn any object that has an `each` method (or a similar iteration method) into an Enumerator.
|
||||
|
||||
```ruby
|
||||
e = [1, 2, 3].to_enum # Creates an enumerator for the array
|
||||
e = "hello".enum_for(:each_byte) # Creates an enumerator for iterating over bytes
|
||||
```
|
||||
|
||||
2. **Using `Enumerator.new`:** You can create an Enumerator by providing a block that defines how values are yielded.
|
||||
|
||||
```ruby
|
||||
fib = Enumerator.new do |yielder|
|
||||
a = b = 1
|
||||
loop do
|
||||
yielder << a
|
||||
a, b = b, a + b
|
||||
end
|
||||
end
|
||||
|
||||
fib.take(5) # => [1, 1, 2, 3, 5]
|
||||
```
|
||||
|
||||
## Key Methods
|
||||
|
||||
The `Enumerator` class includes many helpful methods from the `Enumerable` module, as well as some of its own:
|
||||
|
||||
- **`next`**: Returns the next value from the enumerator. Raises `StopIteration` if the enumerator is at the end.
|
||||
- **`peek`**: Returns the next value without advancing the iterator.
|
||||
- **`rewind`**: Resets the enumerator to its beginning.
|
||||
- **`with_index(offset = 0)`**: Iterates over elements, providing both the element and its index (with an optional offset). Returns a new Enumerator if no block is given.
|
||||
|
||||
```ruby
|
||||
["a", "b"].each.with_index(1) do |char, index|
|
||||
puts "#{index}: #{char}"
|
||||
end
|
||||
# Output:
|
||||
# 1: a
|
||||
# 2: b
|
||||
```
|
||||
|
||||
- **`each_with_index`**: Similar to `with_index(0)`.
|
||||
- **`with_object(obj)`**: Iterates over elements, passing an arbitrary object along with each element. Returns the given object. Returns a new Enumerator if no block is given.
|
||||
|
||||
```ruby
|
||||
(1..3).each.with_object([]) do |i, arr|
|
||||
arr << i * 2
|
||||
end # => [2, 4, 6]
|
||||
```
|
||||
|
||||
- **`each(*args)`**: Iterates over the enumerator. If arguments are provided, they are passed to the underlying iteration method.
|
||||
- **`feed(value)`**: Sets a value to be returned by the `yield` inside the enumerator on its next call.
|
||||
|
||||
## Chaining Enumerators
|
||||
|
||||
One of the powerful features of Enumerators is the ability to chain operations:
|
||||
|
||||
```ruby
|
||||
data = [1, 2, 3, 4, 5]
|
||||
|
||||
result = data.to_enum
|
||||
.with_index # [[1, 0], [2, 1], [3, 2], [4, 3], [5, 4]]
|
||||
.select { |num, idx| num.even? } # [[2, 1], [4, 3]]
|
||||
.map { |num, idx| "#{idx}:#{num}" } # ["1:2", "3:4"]
|
||||
|
||||
p result # => ["1:2", "3:4"]
|
||||
```
|
||||
|
||||
This avoids creating intermediate arrays for each step, making the code more efficient and readable for complex data transformations.
|
||||
|
||||
## Integration
|
||||
|
||||
This mrbgem integrates the `Enumerator` class into mruby, making it available for use in your mruby projects. It also extends `Kernel` with `to_enum` and `enum_for`, and `Enumerable` with methods like `zip`, `chunk`, and `chunk_while` that leverage `Enumerator`.
|
||||
|
||||
Refer to the source code and tests for more detailed examples and advanced usage.
|
||||
@@ -132,7 +132,7 @@ class Enumerator
|
||||
@stop_exc = false
|
||||
end
|
||||
|
||||
def initialize_copy(obj)
|
||||
private def initialize_copy(obj)
|
||||
raise TypeError, "can't copy type #{obj.class}" unless obj.kind_of? Enumerator
|
||||
raise TypeError, "can't copy execution context" if obj.instance_eval{@fib}
|
||||
meth = args = kwd = fib = nil
|
||||
|
||||
@@ -2,6 +2,64 @@
|
||||
|
||||
Errno module for mruby
|
||||
|
||||
This mrbgem provides the `Errno` module, which allows mruby programs to access system error numbers and their corresponding error messages. This is particularly useful for handling errors returned by underlying system calls.
|
||||
|
||||
## Functionality
|
||||
|
||||
The `mruby-errno` gem defines the `Errno` module and the `SystemCallError` class.
|
||||
|
||||
### Accessing Error Constants
|
||||
|
||||
The `Errno` module provides constants for various system errors. Each error constant corresponds to a specific system error number.
|
||||
|
||||
Example:
|
||||
|
||||
```ruby
|
||||
p Errno::EPERM::Errno # Output: 1 (or the system-specific value for EPERM)
|
||||
p Errno::EPERM.new.message # Output: "Operation not permitted"
|
||||
```
|
||||
|
||||
### Raising and Rescuing System Call Errors
|
||||
|
||||
The `SystemCallError` class is the base class for system call errors. You can raise instances of `SystemCallError` or its subclasses (like `Errno::EPERM`) and rescue them in your code.
|
||||
|
||||
Example:
|
||||
|
||||
```ruby
|
||||
begin
|
||||
raise Errno::EACCES, "my_method"
|
||||
rescue SystemCallError => e
|
||||
p e.class # Output: Errno::EACCES
|
||||
p e.errno # Output: 13 (or the system-specific value for EACCES)
|
||||
p e.message # Output: "Permission denied - my_method"
|
||||
p e.to_s # Output: "Permission denied - my_method"
|
||||
end
|
||||
|
||||
# You can also rescue specific Errno constants
|
||||
begin
|
||||
# Simulate a system call that might fail
|
||||
# For example, trying to open a file without permissions
|
||||
raise Errno::ENOENT, "missing_file.txt"
|
||||
rescue Errno::ENOENT => e
|
||||
puts "Caught an ENOENT error: #{e.message}"
|
||||
# Output: Caught an ENOENT error: No such file or directory - missing_file.txt
|
||||
end
|
||||
```
|
||||
|
||||
### Errno::NOERROR
|
||||
|
||||
The `Errno::NOERROR` constant represents the absence of an error, typically with a value of 0.
|
||||
|
||||
Example:
|
||||
|
||||
```ruby
|
||||
p Errno::NOERROR::Errno # Output: 0
|
||||
```
|
||||
|
||||
## Defining Error Types
|
||||
|
||||
New error types and their corresponding numbers are defined in the `known_errors.def` file. The `gen.rb` script processes this file to generate the necessary C and Ruby code for the `Errno` module. This allows `mruby-errno` to be easily extended with new system error definitions.
|
||||
|
||||
## License
|
||||
|
||||
Copyright (c) 2013 Internet Initiative Japan Inc.
|
||||
|
||||
@@ -24,7 +24,7 @@ assert('SystemCallError#errno') do
|
||||
end
|
||||
|
||||
assert('SystemCallError#inspect') do
|
||||
assert_equal("unknown error - a (SystemCallError)", SystemCallError.new("a").inspect)
|
||||
assert_equal("#<SystemCallError: unknown error - a>", SystemCallError.new("a").inspect)
|
||||
end
|
||||
|
||||
assert('Errno::NOERROR') do
|
||||
@@ -50,9 +50,8 @@ assert('Errno::EPERM#message') do
|
||||
end
|
||||
|
||||
assert('Errno::EPERM#inspect') do
|
||||
msg = Errno::EPERM.new.message
|
||||
assert_equal("#{msg} (Errno::EPERM)", Errno::EPERM.new.inspect)
|
||||
|
||||
msg = Errno::EPERM.new.message
|
||||
assert_equal("#{msg} - a (Errno::EPERM)", Errno::EPERM.new("a").inspect)
|
||||
e = Errno::EPERM.new
|
||||
msg = e.message
|
||||
assert_equal("#<Errno::EPERM: #{msg}>", e.inspect)
|
||||
assert_equal("#<Errno::EPERM: #{msg} - a>", Errno::EPERM.new("a").inspect)
|
||||
end
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
# mruby-error
|
||||
|
||||
The `mruby-error` mrbgem provides a set of C-level APIs for structured exception handling within mruby. These functions allow C extensions or embedded mruby code to implement error handling patterns similar to Ruby's `begin`, `rescue`, and `ensure` keywords. This is particularly useful when writing C code that needs to interact with mruby's exception system in a robust way.
|
||||
|
||||
## `mrb_protect`
|
||||
|
||||
The `mrb_protect` function is used to execute a C function (`body`) and capture any exceptions that might be raised during its execution. This allows you to run potentially unsafe operations and handle errors gracefully.
|
||||
|
||||
**C Signature:**
|
||||
|
||||
```c
|
||||
mrb_value mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state);
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `mrb_state *mrb`: The current mruby state.
|
||||
- `mrb_func_t body`: A function pointer to the C function to be executed. This function should have the signature `mrb_value (*body)(mrb_state *mrb, mrb_value data)`.
|
||||
- `mrb_value data`: A `mrb_value` that will be passed as an argument to the `body` function.
|
||||
- `mrb_bool *state`: A pointer to a boolean. After `mrb_protect` returns, this boolean will be:
|
||||
- `FALSE` (0) if the `body` function executed without raising an exception.
|
||||
- `TRUE` (1) if an exception was raised within the `body` function.
|
||||
|
||||
**Return Value:**
|
||||
|
||||
- If no exception occurs (`*state` is `FALSE`), `mrb_protect` returns the value returned by the `body` function.
|
||||
- If an exception occurs (`*state` is `TRUE`), `mrb_protect` returns the exception object.
|
||||
|
||||
## `mrb_ensure`
|
||||
|
||||
The `mrb_ensure` function ensures that a specific C function (`ensure`) is executed, regardless of whether another C function (`body`) completes normally or raises an exception. This is analogous to Ruby's `ensure` clause.
|
||||
|
||||
**C Signature:**
|
||||
|
||||
```c
|
||||
mrb_value mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t ensure, mrb_value e_data);
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `mrb_state *mrb`: The current mruby state.
|
||||
- `mrb_func_t body`: A function pointer to the main C function to be executed.
|
||||
- `mrb_value b_data`: A `mrb_value` passed as data to the `body` function.
|
||||
- `mrb_func_t ensure`: A function pointer to the C function that will always be executed after the `body` function.
|
||||
- `mrb_value e_data`: A `mrb_value` passed as data to the `ensure` function.
|
||||
|
||||
**Behavior:**
|
||||
The `body` function is executed first. After its completion (either normally or due to an exception), the `ensure` function is executed. If the `body` function raised an exception, that exception is re-thrown after the `ensure` function has finished. The return value of `mrb_ensure` is the result of the `body` function if no exception occurred.
|
||||
|
||||
## `mrb_rescue`
|
||||
|
||||
The `mrb_rescue` function executes a C function (`body`) and, if an exception that is a `StandardError` (or a subclass of `StandardError`) is raised, it executes a specified `rescue` C function. This is similar to a `rescue` clause in Ruby that doesn't specify a particular exception type (which defaults to `StandardError`).
|
||||
|
||||
**C Signature:**
|
||||
|
||||
```c
|
||||
mrb_value mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t rescue, mrb_value r_data);
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `mrb_state *mrb`: The current mruby state.
|
||||
- `mrb_func_t body`: A function pointer to the main C function to be executed.
|
||||
- `mrb_value b_data`: A `mrb_value` passed as data to the `body` function.
|
||||
- `mrb_func_t rescue`: A function pointer to the C function that will be executed if a `StandardError` (or its subclass) is caught.
|
||||
- `mrb_value r_data`: A `mrb_value` passed as data to the `rescue` function.
|
||||
|
||||
**Behavior:**
|
||||
If the `body` function executes without raising an exception, its result is returned. If a `StandardError` (or one of its descendants) is raised, the `rescue` function is executed, and its result becomes the return value of `mrb_rescue`. If an exception occurs that is not a `StandardError` (or its subclass), it is not caught by this function and will propagate up the call stack. Similarly, if the `rescue` block itself raises an exception, that exception will propagate.
|
||||
|
||||
## `mrb_rescue_exceptions`
|
||||
|
||||
The `mrb_rescue_exceptions` function provides more fine-grained exception handling than `mrb_rescue`. It executes a C function (`body`) and, if an exception matching one of the specified classes is raised, it executes a `rescue` C function. This is analogous to Ruby's `rescue SpecificError1, SpecificError2 => e` syntax.
|
||||
|
||||
**C Signature:**
|
||||
|
||||
```c
|
||||
mrb_value mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t rescue, mrb_value r_data, mrb_int len, struct RClass **classes);
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `mrb_state *mrb`: The current mruby state.
|
||||
- `mrb_func_t body`: A function pointer to the main C function to be executed.
|
||||
- `mrb_value b_data`: A `mrb_value` passed as data to the `body` function.
|
||||
- `mrb_func_t rescue`: A function pointer to the C function that will be executed if a matching exception is caught.
|
||||
- `mrb_value r_data`: A `mrb_value` passed as data to the `rescue` function.
|
||||
- `mrb_int len`: The number of exception classes provided in the `classes` array.
|
||||
- `struct RClass **classes`: An array of pointers to mruby `RClass` objects representing the exception classes to be rescued.
|
||||
|
||||
**Behavior:**
|
||||
If the `body` function executes without raising an exception, its result is returned. If an exception is raised that is an instance of one of the classes specified in the `classes` array (or a subclass of one of them), the `rescue` function is executed, and its result becomes the return value of `mrb_rescue_exceptions`. If an exception occurs that does not match any of the specified classes, it is not caught and will propagate. If the `rescue` block itself raises an exception, that exception will propagate.
|
||||
|
||||
## Usage Examples
|
||||
|
||||
The C functions provided by this mrbgem are typically used when writing mruby C extensions that need to interact with Ruby code or manage resources carefully in the presence of potential exceptions.
|
||||
|
||||
For concrete examples of how these functions are used, please refer to the test files within this mrbgem:
|
||||
|
||||
- `test/exception.c`: Shows how these C functions are called directly.
|
||||
- `test/exception.rb`: Demonstrates the behavior of these C functions from the Ruby side, through the `ExceptionTest` module (defined in `test/exception.c`).
|
||||
|
||||
These tests illustrate how to set up callback functions and how the error handling mechanisms behave in practice.
|
||||
@@ -0,0 +1,26 @@
|
||||
# mruby-eval
|
||||
|
||||
This mrbgem provides methods for evaluating Ruby code from strings in mruby.
|
||||
|
||||
## Features
|
||||
|
||||
The `mruby-eval` gem implements the following methods:
|
||||
|
||||
- **`eval`**: Evaluates a string as Ruby code. This is a private method on `Kernel`.
|
||||
- **`instance_eval`**: Evaluates a string or a block within the context of an object. This is a method on `BasicObject`.
|
||||
- **`class_eval` / `module_eval`**: Evaluates a string or a block within the context of a class or module. This is a method on `Module`.
|
||||
- **`Binding#eval`**: Evaluates a string within the context of a `Binding` object.
|
||||
|
||||
## Usage
|
||||
|
||||
For detailed usage and examples, please refer to the standard Ruby documentation for these methods. The mruby implementation aims to be compatible with the behavior of these methods in CRuby.
|
||||
|
||||
## Contributing
|
||||
|
||||
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
|
||||
|
||||
Please make sure to update tests as appropriate.
|
||||
|
||||
## License
|
||||
|
||||
mruby-eval is released under the MIT License. See the [LICENSE.txt](https://github.com/mruby/mruby/blob/master/LICENSE.txt) file in the main mruby repository for details.
|
||||
@@ -142,11 +142,15 @@ create_proc_from_string(mrb_state *mrb, const char *s, mrb_int len, mrb_value bi
|
||||
static mrb_value
|
||||
exec_irep(mrb_state *mrb, mrb_value self, struct RProc *proc)
|
||||
{
|
||||
mrb_callinfo *ci = mrb->c->ci;
|
||||
|
||||
/* no argument passed from eval() */
|
||||
mrb->c->ci->n = 0;
|
||||
mrb->c->ci->nk = 0;
|
||||
ci->n = 0;
|
||||
ci->nk = 0;
|
||||
/* clear visibility */
|
||||
MRB_CI_SET_VISIBILITY_BREAK(ci);
|
||||
/* clear block */
|
||||
mrb->c->ci->stack[1] = mrb_nil_value();
|
||||
ci->stack[1] = mrb_nil_value();
|
||||
return mrb_exec_irep(mrb, self, proc);
|
||||
}
|
||||
|
||||
@@ -158,6 +162,10 @@ binding_eval_error_check(mrb_state *mrb, struct mrb_parser_state *p, const char
|
||||
}
|
||||
|
||||
if (0 < p->nerr) {
|
||||
if (p->mrb->exc) {
|
||||
mrb_exc_raise(mrb, mrb_obj_value(p->mrb->exc));
|
||||
}
|
||||
|
||||
mrb_value str;
|
||||
|
||||
if (file) {
|
||||
|
||||
@@ -160,3 +160,26 @@ assert('Module#class_eval with string') do
|
||||
b = c.class_eval("class A; def a; 55; end; end; class B; def b; A; end; end; B")
|
||||
assert_equal 55, b.new.b.new.a
|
||||
end
|
||||
|
||||
assert 'method visibility with eval' do
|
||||
c = Class.new do
|
||||
eval <<~CODE
|
||||
private
|
||||
def bad!
|
||||
"BAD!"
|
||||
end
|
||||
CODE
|
||||
|
||||
def good!
|
||||
"GOOD!"
|
||||
end
|
||||
end
|
||||
|
||||
assert_raise NoMethodError do
|
||||
c.new.bad!
|
||||
end
|
||||
|
||||
assert_equal "GOOD!" do
|
||||
c.new.good!
|
||||
end
|
||||
end
|
||||
|
||||
@@ -21,7 +21,7 @@ fiber_s_yield_by_c_method(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
fiber_resume_by_c_func(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
int ci_index = mrb->c->ci - mrb->c->cibase;
|
||||
ptrdiff_t ci_index = mrb->c->ci - mrb->c->cibase;
|
||||
mrb_value ret = mrb_fiber_resume(mrb, self, 0, NULL);
|
||||
if (ci_index != mrb->c->ci - mrb->c->cibase) {
|
||||
mrb_raisef(mrb, E_EXCEPTION,
|
||||
@@ -34,7 +34,7 @@ fiber_resume_by_c_func(mrb_state *mrb, mrb_value self)
|
||||
static mrb_value
|
||||
fiber_resume_by_c_method(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
int ci_index = mrb->c->ci - mrb->c->cibase;
|
||||
ptrdiff_t ci_index = mrb->c->ci - mrb->c->cibase;
|
||||
mrb_value ret = mrb_funcall_argv(mrb, self, mrb_intern_lit(mrb, "resume"), 0, NULL);
|
||||
if (ci_index != mrb->c->ci - mrb->c->cibase) {
|
||||
mrb_raisef(mrb, E_EXCEPTION,
|
||||
|
||||
@@ -0,0 +1,392 @@
|
||||
# mruby-hash-ext
|
||||
|
||||
This mrbgem extends the core `Hash` class in mruby, providing a collection of additional methods to enhance its functionality. These extensions offer more ways to manipulate and interact with hashes, drawing inspiration from common Ruby hash methods.
|
||||
|
||||
## How to Use
|
||||
|
||||
To incorporate `mruby-hash-ext` into your mruby project, add it to your `build_config.rb` file. For example:
|
||||
|
||||
```ruby
|
||||
MRuby::Build.new do |conf|
|
||||
# ... other configurations ...
|
||||
conf.gem :github => 'mruby/mruby-hash-ext'
|
||||
# or if you have it locally:
|
||||
# conf.gem "#{root}/mrbgems/mruby-hash-ext"
|
||||
end
|
||||
```
|
||||
|
||||
Then, rebuild your mruby project. The extended hash methods will then be available for use.
|
||||
|
||||
## Implemented Methods
|
||||
|
||||
This gem implements the following methods for the `Hash` class:
|
||||
|
||||
- `values_at(*keys)`: Returns an array containing the values associated with the given keys.
|
||||
- `slice(*keys)`: Returns a hash containing only the given keys and their values.
|
||||
- `except(*keys)`: Returns a hash excluding the given keys and their values.
|
||||
- `Hash.[](*object)`: Creates a new hash populated with the given objects.
|
||||
- `#merge!(other_hash..)`, `#update(other_hash..)`: Adds the contents of `other_hash` to `hsh`.
|
||||
- `#compact!`: Removes all nil values from the hash.
|
||||
- `#compact`: Returns a new hash with the nil values/key pairs removed.
|
||||
- `#fetch(key [, default])`, `#fetch(key) {| key | block }`: Returns a value from the hash for the given key.
|
||||
- `#delete_if {| key, value | block }`: Deletes every key-value pair from `hsh` for which `block` evaluates to `true`.
|
||||
- `#flatten`: Returns a new array that is a one-dimensional flattening of this hash.
|
||||
- `#invert`: Returns a new hash created by using `hsh`'s values as keys, and the keys as values.
|
||||
- `#keep_if {| key, value | block }`: Deletes every key-value pair from `hsh` for which `block` evaluates to false.
|
||||
- `#key(value)`: Returns the key of an occurrence of a given value.
|
||||
- `#to_h`: Returns `self`. If called on a subclass of Hash, converts the receiver to a Hash object.
|
||||
- `#< other_hash`: Returns `true` if `hsh` is a subset of `other_hash`.
|
||||
- `#<= other_hash`: Returns `true` if `hsh` is a subset of `other_hash` or equal to `other_hash`.
|
||||
- `#> other_hash`: Returns `true` if `other_hash` is a subset of `hsh`.
|
||||
- `#>= other_hash`: Returns `true` if `other_hash` is a subset of `hsh` or equal to `hsh`.
|
||||
- `#dig(key, ...)`: Extracts the nested value specified by the sequence of keys.
|
||||
- `#transform_keys {|key| block }`: Returns a new hash with keys transformed by the block.
|
||||
- `#transform_keys! {|key| block }`: Modifies the hash by transforming its keys using the block.
|
||||
- `#transform_values {|value| block }`: Returns a new hash with values transformed by the block.
|
||||
- `#transform_values! {|value| block }`: Modifies the hash by transforming its values using the block.
|
||||
- `#to_proc`: Returns a proc that maps a key to its value in the hash.
|
||||
- `#fetch_values(key, ...)`: Returns an array of values for the given keys, raising KeyError if any are not found.
|
||||
- `#filter {| key, value | block }` (Alias for `select`): Returns a new hash containing entries for which the block returns true.
|
||||
- `#filter! {| key, value | block }` (Alias for `select!`): Modifies the hash, keeping only entries for which the block returns true.
|
||||
|
||||
### `values_at(*keys) -> array`
|
||||
|
||||
Returns an array containing the values associated with the given keys. If a key is not found, `nil` is returned for that key's position in the array.
|
||||
|
||||
```ruby
|
||||
h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
|
||||
h.values_at("cow", "cat") #=> ["bovine", "feline"]
|
||||
h.values_at("dog", "mouse") #=> ["canine", nil]
|
||||
h.values_at() #=> []
|
||||
```
|
||||
|
||||
### `slice(*keys) -> new_hash`
|
||||
|
||||
Returns a new hash containing only the given keys and their associated values from the original hash. If a key is not found in the original hash, it's ignored.
|
||||
|
||||
```ruby
|
||||
h = { a: 100, b: 200, c: 300 }
|
||||
h.slice(:a) #=> {a: 100}
|
||||
h.slice(:b, :c, :d) #=> {b: 200, c: 300} (ignores :d as it's not in h)
|
||||
h.slice() #=> {}
|
||||
```
|
||||
|
||||
### `except(*keys) -> new_hash`
|
||||
|
||||
Returns a new hash containing all key-value pairs from the original hash except for those specified by the given keys. If a key is not found in the original hash, it's ignored.
|
||||
|
||||
```ruby
|
||||
h = { a: 100, b: 200, c: 300 }
|
||||
h.except(:a) #=> {b: 200, c: 300}
|
||||
h.except(:b, :c, :d) #=> {a: 100} (ignores :d as it's not in h)
|
||||
h.except() #=> {a: 100, b: 200, c: 300}
|
||||
```
|
||||
|
||||
### `Hash.[](*object)`
|
||||
|
||||
Creates a new hash populated with the given objects.
|
||||
|
||||
- **`Hash[key, value, ...]`**: Creates a new hash with key-value pairs.
|
||||
- **`Hash[[ [key, value], ... ]]`**: Creates a new hash from an array of key-value pairs.
|
||||
- **`Hash[object]`**: Creates a new hash from an object convertible to a hash.
|
||||
|
||||
```ruby
|
||||
h1 = Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200}
|
||||
h2 = Hash[[ ["a", 100], ["b", 200] ]] #=> {"a"=>100, "b"=>200}
|
||||
h3 = Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200}
|
||||
```
|
||||
|
||||
### `#merge!(other_hash..) -> hsh`
|
||||
|
||||
### `#merge!(other_hash..){|key, oldval, newval| block} -> hsh`
|
||||
|
||||
(Alias: `#update`)
|
||||
|
||||
Adds the contents of `other_hash` to `hsh`. If no block is specified, entries with duplicate keys are overwritten with the values from `other_hash`. Otherwise, the value of each duplicate key is determined by calling the block with the key, its value in `hsh`, and its value in `other_hash`.
|
||||
|
||||
```ruby
|
||||
h1 = { "a" => 100, "b" => 200 }
|
||||
h2 = { "b" => 254, "c" => 300 }
|
||||
h1.merge!(h2) #=> {"a"=>100, "b"=>254, "c"=>300}
|
||||
|
||||
h1 = { "a" => 100, "b" => 200 }
|
||||
h2 = { "b" => 254, "c" => 300 }
|
||||
h1.merge!(h2) { |key, v1, v2| v1 }
|
||||
#=> {"a"=>100, "b"=>200, "c"=>300}
|
||||
```
|
||||
|
||||
### `#compact! -> hsh`
|
||||
|
||||
Removes all nil values from the hash. Returns the hash. Returns `nil` if the hash does not contain nil values.
|
||||
|
||||
```ruby
|
||||
h = { a: 1, b: false, c: nil }
|
||||
h.compact! #=> { a: 1, b: false }
|
||||
```
|
||||
|
||||
### `#compact -> new_hsh`
|
||||
|
||||
Returns a new hash with the nil values/key pairs removed.
|
||||
|
||||
```ruby
|
||||
h = { a: 1, b: false, c: nil }
|
||||
h.compact #=> { a: 1, b: false }
|
||||
h #=> { a: 1, b: false, c: nil }
|
||||
```
|
||||
|
||||
### `#fetch(key [, default] ) -> obj`
|
||||
|
||||
### `#fetch(key) {| key | block } -> obj`
|
||||
|
||||
Returns a value from the hash for the given key.
|
||||
If the key can't be found, there are several options:
|
||||
|
||||
- With no other arguments, it will raise a `KeyError` exception.
|
||||
- If `default` is given, then that will be returned.
|
||||
- If the optional code block is specified, then that will be run and its result returned.
|
||||
|
||||
```ruby
|
||||
h = { "a" => 100, "b" => 200 }
|
||||
h.fetch("a") #=> 100
|
||||
h.fetch("z", "go fish") #=> "go fish"
|
||||
h.fetch("z") { |el| "go fish, #{el}"} #=> "go fish, z"
|
||||
|
||||
# h.fetch("z") # Raises KeyError: key not found: "z"
|
||||
```
|
||||
|
||||
### `#delete_if {| key, value | block } -> hsh`
|
||||
|
||||
### `#delete_if -> an_enumerator`
|
||||
|
||||
Deletes every key-value pair from `hsh` for which `block` evaluates to `true`.
|
||||
If no block is given, an enumerator is returned instead.
|
||||
|
||||
```ruby
|
||||
h = { "a" => 100, "b" => 200, "c" => 300 }
|
||||
h.delete_if {|key, value| key >= "b" } #=> {"a"=>100}
|
||||
```
|
||||
|
||||
### `#flatten -> an_array`
|
||||
|
||||
### `#flatten(level) -> an_array`
|
||||
|
||||
Returns a new array that is a one-dimensional flattening of this hash. That is, for every key or value that is an array, extract its elements into the new array. Unlike `Array#flatten`, this method does not flatten recursively by default. The optional `level` argument determines the level of recursion to flatten.
|
||||
|
||||
```ruby
|
||||
a = {1=> "one", 2 => [2,"two"], 3 => "three"}
|
||||
a.flatten # => [1, "one", 2, [2, "two"], 3, "three"]
|
||||
a.flatten(2) # => [1, "one", 2, 2, "two", 3, "three"]
|
||||
```
|
||||
|
||||
### `#invert -> new_hash`
|
||||
|
||||
Returns a new hash created by using `hsh`'s values as keys, and the keys as values. If a value appears more than once, the last key encountered will be used due to hash key uniqueness.
|
||||
|
||||
```ruby
|
||||
h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
|
||||
h.invert #=> {0=>"a", 100=>"m", 200=>"d", 300=>"y"}
|
||||
```
|
||||
|
||||
### `#keep_if {| key, value | block } -> hsh`
|
||||
|
||||
### `#keep_if -> an_enumerator`
|
||||
|
||||
Deletes every key-value pair from `hsh` for which `block` evaluates to `false`.
|
||||
If no block is given, an enumerator is returned instead.
|
||||
|
||||
```ruby
|
||||
h = { "a" => 1, "b" => 2, "c" => 3, "d" => 4 }
|
||||
h.keep_if {|key, value| value % 2 == 0 } #=> {"b"=>2, "d"=>4}
|
||||
```
|
||||
|
||||
### `#key(value) -> key`
|
||||
|
||||
Returns the key of an occurrence of a given value. If the value is not found, returns `nil`.
|
||||
|
||||
```ruby
|
||||
h = { "a" => 100, "b" => 200, "c" => 300, "d" => 300 }
|
||||
h.key(200) #=> "b"
|
||||
h.key(300) #=> "c" (returns the first key found for the value)
|
||||
h.key(999) #=> nil
|
||||
```
|
||||
|
||||
### `#to_h -> hsh or new_hash`
|
||||
|
||||
Returns `self`. If called on a subclass of Hash, converts the receiver to a Hash object. For a Hash instance, it simply returns `self`.
|
||||
|
||||
```ruby
|
||||
h = { "a" => 1, "b" => 2 }
|
||||
h.to_h #=> {"a"=>1, "b"=>2}
|
||||
|
||||
class MyHash < Hash; end
|
||||
my_h = MyHash["c" => 3, "d" => 4]
|
||||
my_h.to_h #=> {"c"=>3, "d"=>4} (returns a Hash object, not MyHash)
|
||||
```
|
||||
|
||||
### `#< other_hash -> true or false`
|
||||
|
||||
Returns `true` if `hsh` is a proper subset of `other_hash` (i.e., `other_hash` contains all key/value pairs of `hsh`, and `other_hash` has at least one additional key/value pair).
|
||||
|
||||
```ruby
|
||||
h1 = {a:1, b:2}
|
||||
h2 = {a:1, b:2, c:3}
|
||||
h1 < h2 #=> true
|
||||
h2 < h1 #=> false
|
||||
h1 < h1 #=> false
|
||||
```
|
||||
|
||||
### `#<= other_hash -> true or false`
|
||||
|
||||
Returns `true` if `hsh` is a subset of `other_hash` or is equal to `other_hash` (i.e., `other_hash` contains all key/value pairs of `hsh`).
|
||||
|
||||
```ruby
|
||||
h1 = {a:1, b:2}
|
||||
h2 = {a:1, b:2, c:3}
|
||||
h1 <= h2 #=> true
|
||||
h2 <= h1 #=> false
|
||||
h1 <= h1 #=> true
|
||||
```
|
||||
|
||||
### `#> other_hash -> true or false`
|
||||
|
||||
Returns `true` if `other_hash` is a proper subset of `hsh` (i.e., `hsh` contains all key/value pairs of `other_hash`, and `hsh` has at least one additional key/value pair).
|
||||
|
||||
```ruby
|
||||
h1 = {a:1, b:2}
|
||||
h2 = {a:1, b:2, c:3}
|
||||
h1 > h2 #=> false
|
||||
h2 > h1 #=> true
|
||||
h1 > h1 #=> false
|
||||
```
|
||||
|
||||
### `#>= other_hash -> true or false`
|
||||
|
||||
Returns `true` if `other_hash` is a subset of `hsh` or is equal to `hsh` (i.e., `hsh` contains all key/value pairs of `other_hash`).
|
||||
|
||||
```ruby
|
||||
h1 = {a:1, b:2}
|
||||
h2 = {a:1, b:2, c:3}
|
||||
h1 >= h2 #=> false
|
||||
h2 >= h1 #=> true
|
||||
h1 >= h1 #=> true
|
||||
```
|
||||
|
||||
### `#dig(key,...) -> object`
|
||||
|
||||
Extracts the nested value specified by the sequence of `key` objects by calling `dig` at each step. Returns `nil` if any intermediate step is `nil`.
|
||||
|
||||
```ruby
|
||||
h = { a: { b: { c: 1 } } }
|
||||
h.dig(:a, :b, :c) #=> 1
|
||||
h.dig(:a, :x, :c) #=> nil
|
||||
|
||||
g = { a: [1, 2, {b: 3}] }
|
||||
g.dig(:a, 2, :b) #=> 3
|
||||
g.dig(:a, 1, :b) #=> nil (element at index 1 is 2, which does not respond to #dig)
|
||||
```
|
||||
|
||||
### `#transform_keys {|key| block } -> new_hash`
|
||||
|
||||
### `#transform_keys -> an_enumerator`
|
||||
|
||||
Returns a new hash, with the keys computed from running the block once for each key in the hash, and the values unchanged.
|
||||
If no block is given, an enumerator is returned instead.
|
||||
|
||||
```ruby
|
||||
h = { a: 1, b: 2, c: 3 }
|
||||
h.transform_keys {|k| k.to_s.upcase } #=> {"A"=>1, "B"=>2, "C"=>3}
|
||||
```
|
||||
|
||||
### `#transform_keys! {|key| block } -> hsh`
|
||||
|
||||
### `#transform_keys! -> an_enumerator`
|
||||
|
||||
Invokes the given block once for each key in `hsh`, replacing it with the new key returned by the block, and then returns `hsh`.
|
||||
If no block is given, an enumerator is returned instead.
|
||||
|
||||
```ruby
|
||||
h = { a: 1, b: 2, c: 3 }
|
||||
h.transform_keys! {|k| k.to_s.upcase } #=> {"A"=>1, "B"=>2, "C"=>3}
|
||||
h #=> {"A"=>1, "B"=>2, "C"=>3}
|
||||
```
|
||||
|
||||
### `#transform_values {|value| block } -> new_hash`
|
||||
|
||||
### `#transform_values -> an_enumerator`
|
||||
|
||||
Returns a new hash with the results of running the block once for every value. This method does not change the keys.
|
||||
If no block is given, an enumerator is returned instead.
|
||||
|
||||
```ruby
|
||||
h = { a: 1, b: 2, c: 3 }
|
||||
h.transform_values {|v| v * v } #=> {a: 1, b: 4, c: 9}
|
||||
```
|
||||
|
||||
### `#transform_values! {|value| block } -> hsh`
|
||||
|
||||
### `#transform_values! -> an_enumerator`
|
||||
|
||||
Invokes the given block once for each value in the hash, replacing it with the new value returned by the block, and then returns `hsh`.
|
||||
If no block is given, an enumerator is returned instead.
|
||||
|
||||
```ruby
|
||||
h = { a: 1, b: 2, c: 3 }
|
||||
h.transform_values! {|v| v * v } #=> {a: 1, b: 4, c: 9}
|
||||
h #=> {a: 1, b: 4, c: 9}
|
||||
```
|
||||
|
||||
### `#to_proc -> a_proc`
|
||||
|
||||
Returns a `Proc` object that maps a key to its corresponding value in the hash. This allows a hash to be used as a block argument.
|
||||
|
||||
```ruby
|
||||
h = {a: 1, b: 2}
|
||||
p = h.to_proc
|
||||
p.call(:a) #=> 1
|
||||
|
||||
['a', 'b', 'c'].map(&h) #=> [1, 2, nil] (uses h[x] for each element)
|
||||
```
|
||||
|
||||
### `#fetch_values(key, ...) -> array`
|
||||
|
||||
### `#fetch_values(key, ...) { |key| block } -> array`
|
||||
|
||||
Returns an array containing the values associated with the given keys. Raises `KeyError` if any of the keys can't be found, unless a block is provided to compute a default value.
|
||||
|
||||
```ruby
|
||||
h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
|
||||
|
||||
h.fetch_values("cow", "cat") #=> ["bovine", "feline"]
|
||||
# h.fetch_values("cow", "bird") # raises KeyError: key not found: "bird"
|
||||
h.fetch_values("cow", "bird") { |k| k.upcase } #=> ["bovine", "BIRD"]
|
||||
```
|
||||
|
||||
### `#filter {| key, value | block } -> new_hsh`
|
||||
|
||||
### `#filter -> an_enumerator`
|
||||
|
||||
(Alias for `select`)
|
||||
Returns a new hash consisting of entries for which the block returns a true value.
|
||||
If no block is given, an enumerator is returned instead.
|
||||
|
||||
```ruby
|
||||
h = { "a" => 100, "b" => 200, "c" => 300 }
|
||||
h.filter {|key, value| key < "b"} #=> {"a"=>100}
|
||||
h.filter {|key, value| value < 200} #=> {"a"=>100}
|
||||
```
|
||||
|
||||
### `#filter! {| key, value | block } -> hsh_or_nil`
|
||||
|
||||
### `#filter! -> an_enumerator`
|
||||
|
||||
(Alias for `select!`)
|
||||
Equivalent to `Hash#keep_if`, but returns `nil` if no changes were made.
|
||||
Deletes every key-value pair from `hsh` for which `block` evaluates to `false`.
|
||||
If no block is given, an enumerator is returned instead.
|
||||
|
||||
```ruby
|
||||
h = { "a" => 100, "b" => 200, "c" => 300 }
|
||||
h.filter! {|key, value| key < "b"} #=> {"a"=>100}
|
||||
h #=> {"a"=>100}
|
||||
h.filter! {|key, value| key < "a"} #=> nil (no changes)
|
||||
```
|
||||
@@ -13,6 +13,17 @@ module Kernel
|
||||
end
|
||||
end
|
||||
|
||||
private def p(*a)
|
||||
for e in a
|
||||
$stdout.write e.inspect
|
||||
$stdout.write "\n"
|
||||
end
|
||||
len = a.size
|
||||
return nil if len == 0
|
||||
return a[0] if len == 1
|
||||
a
|
||||
end
|
||||
|
||||
private def print(...)
|
||||
$stdout.print(...)
|
||||
end
|
||||
|
||||
+30
-31
@@ -245,11 +245,9 @@ mrb_file_basename(mrb_state *mrb, mrb_value klass)
|
||||
#if defined(_WIN32)
|
||||
char bname[_MAX_DIR];
|
||||
char extname[_MAX_EXT];
|
||||
char buffer[_MAX_DIR + _MAX_EXT];
|
||||
mrb_value s;
|
||||
char *path;
|
||||
|
||||
mrb_get_args(mrb, "S", &s);
|
||||
char *path = mrb_str_to_cstr(mrb, s);
|
||||
mrb_get_args(mrb, "z", &path);
|
||||
size_t ridx = strlen(path);
|
||||
if (ridx > 0) {
|
||||
ridx--;
|
||||
@@ -257,22 +255,22 @@ mrb_file_basename(mrb_state *mrb, mrb_value klass)
|
||||
path[ridx] = '\0';
|
||||
ridx--;
|
||||
}
|
||||
if (strncmp(path, "/", 2) == 0) {
|
||||
if (ridx == 0 && path[0] == '/') {
|
||||
return mrb_str_new_cstr(mrb, path);
|
||||
}
|
||||
}
|
||||
_splitpath((const char*)path, NULL, NULL, bname, extname);
|
||||
snprintf(buffer, _MAX_DIR + _MAX_EXT, "%s%s", bname, extname);
|
||||
return mrb_str_new_cstr(mrb, buffer);
|
||||
mrb_value buffer = mrb_str_new_cstr(mrb, bname);
|
||||
mrb_str_cat_cstr(mrb, buffer, extname);
|
||||
return buffer;
|
||||
#else
|
||||
mrb_value s;
|
||||
mrb_get_args(mrb, "S", &s);
|
||||
char *path = mrb_str_to_cstr(mrb, s);
|
||||
char *bname;
|
||||
char *path, *bname;
|
||||
|
||||
mrb_get_args(mrb, "z", &path);
|
||||
if ((bname = basename(path)) == NULL) {
|
||||
mrb_sys_fail(mrb, "basename");
|
||||
}
|
||||
if (strncmp(bname, "//", 3) == 0) bname[1] = '\0'; /* patch for Cygwin */
|
||||
if (strcmp(bname, "//") == 0) bname[1] = '\0'; /* patch for Cygwin */
|
||||
return mrb_str_new_cstr(mrb, bname);
|
||||
#endif
|
||||
}
|
||||
@@ -281,10 +279,10 @@ static mrb_value
|
||||
mrb_file_realpath(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
mrb_value pathname, dir_string;
|
||||
mrb_int argc = mrb_get_args(mrb, "S|S", &pathname, &dir_string);
|
||||
if (argc == 2) {
|
||||
|
||||
if (mrb_get_args(mrb, "S|S", &pathname, &dir_string) == 2) {
|
||||
mrb_value s = mrb_str_dup(mrb, dir_string);
|
||||
s = mrb_str_append(mrb, s, mrb_str_new_cstr(mrb, FILE_SEPARATOR));
|
||||
s = mrb_str_cat_cstr(mrb, s, FILE_SEPARATOR);
|
||||
s = mrb_str_append(mrb, s, pathname);
|
||||
pathname = s;
|
||||
}
|
||||
@@ -363,7 +361,7 @@ path_parse(mrb_state *mrb, mrb_value ary, const char *path, int ai)
|
||||
SKIP_DIRSEP(path);
|
||||
const char *path0 = path;
|
||||
NEXT_DIRSEP(path);
|
||||
int len = path - path0;
|
||||
ptrdiff_t len = path - path0;
|
||||
if (len == 0) {
|
||||
break;
|
||||
}
|
||||
@@ -414,7 +412,7 @@ path_gethome(mrb_state *mrb, const char **pathp)
|
||||
|
||||
const char *username = ++*pathp;
|
||||
NEXT_DIRSEP(*pathp);
|
||||
int len = *pathp - username;
|
||||
ptrdiff_t len = *pathp - username;
|
||||
|
||||
if (len == 0) {
|
||||
home = getenv("HOME");
|
||||
@@ -431,7 +429,7 @@ path_gethome(mrb_state *mrb, const char **pathp)
|
||||
}
|
||||
}
|
||||
else {
|
||||
const char *uname = RSTRING_CSTR(mrb, mrb_str_new(mrb, username, len));
|
||||
const char *uname = RSTRING_CSTR(mrb, mrb_str_new(mrb, username, (mrb_int)len));
|
||||
#if defined(_WIN32) || defined(MRB_IO_NO_PWNAM)
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "user %s doesn't exist", uname);
|
||||
#else
|
||||
@@ -458,7 +456,7 @@ path_expand(mrb_state *mrb, const char *path, const char *base, mrb_bool tilda)
|
||||
{
|
||||
mrb_value ary;
|
||||
|
||||
// split path conponents as array and normalization
|
||||
// split path components as array and normalization
|
||||
if (tilda && path[0] == '~') {
|
||||
base = path_gethome(mrb, &path);
|
||||
ary = path_split(mrb, path, base, NULL);
|
||||
@@ -639,7 +637,7 @@ mrb_file_flock(mrb_state *mrb, mrb_value self)
|
||||
}
|
||||
/* FALLTHRU - should not happen */
|
||||
default:
|
||||
mrb_sys_fail(mrb, "flock failed");
|
||||
mrb_sys_fail(mrb, "flock");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -653,10 +651,10 @@ mrb_file_size(mrb_state *mrb, mrb_value self)
|
||||
mrb_stat st;
|
||||
int fd = mrb_io_fileno(mrb, self);
|
||||
if (mrb_fstat(fd, &st) == -1) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "fstat failed");
|
||||
mrb_sys_fail(mrb, "fstat");
|
||||
}
|
||||
|
||||
if (st.st_size > MRB_INT_MAX) {
|
||||
if (sizeof(st.st_size) >= sizeof(mrb_int) && st.st_size > MRB_INT_MAX) {
|
||||
#ifdef MRB_NO_FLOAT
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "File#size too large for MRB_NO_FLOAT");
|
||||
#else
|
||||
@@ -702,7 +700,7 @@ mrb_file_truncate(mrb_state *mrb, mrb_value self)
|
||||
int fd = mrb_io_fileno(mrb, self);
|
||||
mrb_int length = mrb_as_int(mrb, lenv);
|
||||
if (mrb_ftruncate(fd, length) != 0) {
|
||||
mrb_raise(mrb, E_IO_ERROR, "ftruncate failed");
|
||||
mrb_sys_fail(mrb, "ftruncate");
|
||||
}
|
||||
|
||||
return mrb_fixnum_value(0);
|
||||
@@ -740,6 +738,7 @@ mrb_file_s_chmod(mrb_state *mrb, mrb_value klass)
|
||||
|
||||
mrb_get_args(mrb, "i*", &mode, &filenames, &argc);
|
||||
for (int i = 0; i < argc; i++) {
|
||||
mrb_ensure_string_type(mrb, filenames[i]);
|
||||
const char *utf8_path = RSTRING_CSTR(mrb, filenames[i]);
|
||||
char *path = mrb_locale_from_utf8(utf8_path, -1);
|
||||
if (CHMOD(path, mode) == -1) {
|
||||
@@ -761,17 +760,16 @@ mrb_file_s_readlink(mrb_state *mrb, mrb_value klass)
|
||||
return mrb_nil_value(); // unreachable
|
||||
#else
|
||||
const char *path;
|
||||
char *buf, *tmp;
|
||||
size_t bufsize = 100;
|
||||
ssize_t rc;
|
||||
mrb_value ret;
|
||||
|
||||
mrb_get_args(mrb, "z", &path);
|
||||
tmp = mrb_locale_from_utf8(path, -1);
|
||||
|
||||
buf = (char*)mrb_malloc(mrb, bufsize);
|
||||
while ((rc = readlink(tmp, buf, bufsize)) == (ssize_t)bufsize && rc != -1) {
|
||||
bufsize *= 2;
|
||||
char *tmp = mrb_locale_from_utf8(path, -1);
|
||||
char *buf = (char*)mrb_malloc(mrb, bufsize);
|
||||
|
||||
ssize_t rc;
|
||||
while ((rc = readlink(tmp, buf, bufsize)) == (ssize_t)bufsize) {
|
||||
bufsize += 100;
|
||||
buf = (char*)mrb_realloc(mrb, buf, bufsize);
|
||||
}
|
||||
mrb_locale_free(tmp);
|
||||
@@ -780,7 +778,8 @@ mrb_file_s_readlink(mrb_state *mrb, mrb_value klass)
|
||||
mrb_sys_fail(mrb, path);
|
||||
}
|
||||
tmp = mrb_utf8_from_locale(buf, -1);
|
||||
ret = mrb_str_new(mrb, tmp, rc);
|
||||
|
||||
mrb_value ret = mrb_str_new(mrb, tmp, rc);
|
||||
mrb_utf8_free(tmp);
|
||||
mrb_free(mrb, buf);
|
||||
|
||||
|
||||
@@ -1923,7 +1923,7 @@ mrb_init_io(mrb_state *mrb)
|
||||
#endif
|
||||
|
||||
mrb_define_method_id(mrb, io, MRB_SYM(initialize), io_init, MRB_ARGS_ARG(1,2));
|
||||
mrb_define_method_id(mrb, io, MRB_SYM(initialize_copy), io_init_copy, MRB_ARGS_REQ(1));
|
||||
mrb_define_private_method_id(mrb, io, MRB_SYM(initialize_copy), io_init_copy, MRB_ARGS_REQ(1));
|
||||
mrb_define_method_id(mrb, io, MRB_SYM(isatty), io_isatty, MRB_ARGS_NONE());
|
||||
mrb_define_method_id(mrb, io, MRB_SYM_Q(eof), io_eof, MRB_ARGS_NONE()); /* 15.2.20.5.6 */
|
||||
mrb_define_method_id(mrb, io, MRB_SYM(getc), io_getc, MRB_ARGS_NONE()); /* 15.2.20.5.8 */
|
||||
|
||||
@@ -276,7 +276,7 @@ mrb_mruby_io_gem_test(mrb_state* mrb)
|
||||
}
|
||||
#endif
|
||||
if (env_home) {
|
||||
char *utf8 = mrb_utf8_from_locale(env_home, strlen(env_home));
|
||||
char *utf8 = mrb_utf8_from_locale(env_home, -1);
|
||||
mrb_value path = mrb_str_new_cstr(mrb, utf8);
|
||||
#ifdef _WIN32
|
||||
char *pathp = RSTRING_PTR(path);
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
# mruby-kernel-ext
|
||||
|
||||
This mrbgem extends the `Kernel` module in mruby with additional useful methods.
|
||||
|
||||
## Methods
|
||||
|
||||
### `fail(*args)`
|
||||
|
||||
Raises a `RuntimeError`. This is an alias for `raise`.
|
||||
|
||||
Example:
|
||||
|
||||
```ruby
|
||||
fail "Something went wrong"
|
||||
# Raises RuntimeError: Something went wrong
|
||||
```
|
||||
|
||||
### `caller(start=1, length=nil) -> array | nil`
|
||||
|
||||
### `caller(range) -> array | nil`
|
||||
|
||||
Returns the current execution stack (backtrace).
|
||||
|
||||
- If `start` is provided, it indicates the number of frames to skip.
|
||||
- If `length` is provided, it limits the number of frames returned.
|
||||
- If a `range` is provided, it specifies the portion of the stack to return.
|
||||
|
||||
Returns `nil` if `start` is greater than or equal to the number of frames in the stack.
|
||||
|
||||
Example:
|
||||
|
||||
```ruby
|
||||
def foo
|
||||
bar
|
||||
end
|
||||
|
||||
def bar
|
||||
puts caller(0) # Show all frames starting from the current one
|
||||
puts caller(1) # Skip one frame
|
||||
end
|
||||
|
||||
foo
|
||||
```
|
||||
|
||||
### `__method__ -> symbol | nil`
|
||||
|
||||
Returns the name of the current method as a `Symbol`. If called outside of a method, it returns `nil`.
|
||||
|
||||
Example:
|
||||
|
||||
```ruby
|
||||
class MyClass
|
||||
def my_method
|
||||
puts __method__
|
||||
end
|
||||
end
|
||||
|
||||
MyClass.new.my_method
|
||||
# Output: :my_method
|
||||
```
|
||||
|
||||
### `__callee__ -> symbol | nil`
|
||||
|
||||
Returns the called name of the current method as a `Symbol`. If called outside of a method, it returns `nil`. This can be different from `__method__` when using aliases.
|
||||
|
||||
Example:
|
||||
|
||||
```ruby
|
||||
class MyClass
|
||||
def original_method
|
||||
puts __callee__
|
||||
end
|
||||
|
||||
alias aliased_method original_method
|
||||
end
|
||||
|
||||
obj = MyClass.new
|
||||
obj.original_method # Output: :original_method
|
||||
obj.aliased_method # Output: :aliased_method
|
||||
```
|
||||
|
||||
### `Integer(arg, base=0) -> integer`
|
||||
|
||||
Converts `arg` to an `Integer`.
|
||||
|
||||
- Numeric types are converted directly (floating-point numbers are truncated).
|
||||
- If `arg` is a `String`, `base` (0, or between 2 and 36) is used as the base for conversion.
|
||||
- If `base` is omitted or zero, radix indicators (`0`, `0b`, `0x`) in the string are honored.
|
||||
- Strings must strictly conform to numeric representation, unlike `String#to_i`.
|
||||
- Passing `nil` raises a `TypeError`.
|
||||
|
||||
Examples:
|
||||
|
||||
```ruby
|
||||
Integer(123.999) #=> 123
|
||||
Integer("0x1a") #=> 26
|
||||
Integer("0930", 10) #=> 930
|
||||
Integer("111", 2) #=> 7
|
||||
# Integer(nil) #=> TypeError
|
||||
# Integer("invalid") #=> ArgumentError
|
||||
```
|
||||
|
||||
### `Float(arg) -> float`
|
||||
|
||||
Converts `arg` to a `Float`.
|
||||
|
||||
- Numeric types are converted directly.
|
||||
- Other types are converted using `arg.to_f`.
|
||||
- Passing `nil` raises a `TypeError`.
|
||||
|
||||
Examples:
|
||||
|
||||
```ruby
|
||||
Float(1) #=> 1.0
|
||||
Float(123.456) #=> 123.456
|
||||
Float("123.456") #=> 123.456
|
||||
# Float(nil) #=> TypeError
|
||||
# Float("invalid") #=> ArgumentError
|
||||
```
|
||||
|
||||
### `String(arg) -> string`
|
||||
|
||||
Converts `arg` to a `String` using its `to_s` method.
|
||||
|
||||
Examples:
|
||||
|
||||
```ruby
|
||||
String(self) #=> "main"
|
||||
String(self.class) #=> "Object"
|
||||
String(123456) #=> "123456"
|
||||
String(:symbol) #=> "symbol"
|
||||
```
|
||||
|
||||
### `Array(arg) -> array`
|
||||
|
||||
Converts `arg` to an `Array`.
|
||||
|
||||
- If `arg` responds to `to_a`, it calls `to_a` to convert.
|
||||
- Otherwise, it returns a new array containing `arg` as its single element.
|
||||
|
||||
Examples:
|
||||
|
||||
```ruby
|
||||
Array(1..5) #=> [1, 2, 3, 4, 5]
|
||||
Array([1, 2, 3]) #=> [1, 2, 3]
|
||||
Array("hello") #=> ["hello"] # If String does not have to_a
|
||||
Array({ a: 1, b: 2 }) #=> [[:a, 1], [:b, 2]] # If Hash has to_a
|
||||
```
|
||||
|
||||
### `Hash(arg) -> hash`
|
||||
|
||||
Converts `arg` to a `Hash`.
|
||||
|
||||
- If `arg` is already a `Hash`, it is returned.
|
||||
- If `arg` is `nil` or an empty `Array`, an empty `Hash` is returned.
|
||||
- Otherwise, it raises a `TypeError`.
|
||||
|
||||
Examples:
|
||||
|
||||
```ruby
|
||||
Hash({ key: :value }) #=> { key: :value }
|
||||
Hash(nil) #=> {}
|
||||
Hash([]) #=> {}
|
||||
# Hash([1, 2, 3]) #=> TypeError
|
||||
```
|
||||
@@ -0,0 +1,77 @@
|
||||
# mruby-math
|
||||
|
||||
This mrbgem provides a comprehensive set of mathematical functions for mruby. It allows you to perform common mathematical operations within your mruby applications.
|
||||
|
||||
This gem is a standard component of mruby and provides functionalities similar to the `Math` module in standard Ruby.
|
||||
|
||||
## Available Functions
|
||||
|
||||
### Trigonometric Functions
|
||||
|
||||
- `Math.sin(x)`: Computes the sine of x (expressed in radians). Returns -1..1.
|
||||
- `Math.cos(x)`: Computes the cosine of x (expressed in radians). Returns -1..1.
|
||||
- `Math.tan(x)`: Returns the tangent of x (expressed in radians).
|
||||
|
||||
### Inverse Trigonometric Functions
|
||||
|
||||
- `Math.asin(x)`: Computes the arc sine of x. Returns computed value between `-(PI/2)` and `(PI/2)`.
|
||||
- `Math.acos(x)`: Computes the arc cosine of x. Returns 0..PI.
|
||||
- `Math.atan(x)`: Computes the arc tangent of x. Returns `-(PI/2) .. (PI/2)`.
|
||||
- `Math.atan2(y, x)`: Computes the arc tangent given y and x. Returns -PI..PI.
|
||||
|
||||
### Hyperbolic Trigonometric Functions
|
||||
|
||||
- `Math.sinh(x)`: Computes the hyperbolic sine of x (expressed in radians).
|
||||
- `Math.cosh(x)`: Computes the hyperbolic cosine of x (expressed in radians).
|
||||
- `Math.tanh(x)`: Computes the hyperbolic tangent of x (expressed in radians).
|
||||
|
||||
### Inverse Hyperbolic Trigonometric Functions
|
||||
|
||||
- `Math.asinh(x)`: Computes the inverse hyperbolic sine of x.
|
||||
- `Math.acosh(x)`: Computes the inverse hyperbolic cosine of x.
|
||||
- `Math.atanh(x)`: Computes the inverse hyperbolic tangent of x.
|
||||
|
||||
### Exponential and Logarithmic Functions
|
||||
|
||||
- `Math.exp(x)`: Returns e\*\*x.
|
||||
- `Math.log(numeric)` or `Math.log(num,base)`: Returns the natural logarithm of numeric. If additional second argument is given, it will be the base of logarithm.
|
||||
- `Math.log2(numeric)`: Returns the base 2 logarithm of numeric.
|
||||
- `Math.log10(numeric)`: Returns the base 10 logarithm of numeric.
|
||||
|
||||
### Other Functions
|
||||
|
||||
- `Math.sqrt(numeric)`: Returns the square root of numeric.
|
||||
- `Math.cbrt(numeric)`: Returns the cube root of numeric.
|
||||
- `Math.frexp(numeric)`: Returns a two-element array containing the normalized fraction (a Float) and exponent (a Integer) of numeric.
|
||||
- `Math.ldexp(flt, int)`: Returns the value of flt\*(2\*\*int).
|
||||
- `Math.hypot(x, y)`: Returns sqrt(x**2 + y**2), the hypotenuse of a right-angled triangle with sides x and y.
|
||||
- `Math.erf(x)`: Calculates the error function of x.
|
||||
- `Math.erfc(x)`: Calculates the complementary error function of x.
|
||||
|
||||
## Usage Examples
|
||||
|
||||
```ruby
|
||||
# Basic trigonometric functions
|
||||
puts Math.sin(Math::PI / 2) # Output: 1.0
|
||||
puts Math.cos(0) # Output: 1.0
|
||||
puts Math.tan(Math::PI / 4) # Output: 1.0 (approximately, due to float precision)
|
||||
|
||||
# Square root
|
||||
puts Math.sqrt(16) # Output: 4.0
|
||||
puts Math.sqrt(2) # Output: 1.4142135623730951
|
||||
|
||||
# Cube root
|
||||
puts Math.cbrt(8) # Output: 2.0
|
||||
puts Math.cbrt(27) # Output: 3.0
|
||||
|
||||
# Exponential and Logarithm
|
||||
puts Math.exp(0) # Output: 1.0
|
||||
puts Math.exp(1) # Output: 2.718281828459045 (Math::E)
|
||||
puts Math.log(Math::E) # Output: 1.0
|
||||
puts Math.log(100, 10) # Output: 2.0
|
||||
puts Math.log2(16) # Output: 4.0
|
||||
puts Math.log10(1000) # Output: 3.0
|
||||
|
||||
# Hypotenuse
|
||||
puts Math.hypot(3, 4) # Output: 5.0
|
||||
```
|
||||
@@ -0,0 +1,123 @@
|
||||
# mruby-metaprog
|
||||
|
||||
This mrbgem provides a collection of methods for metaprogramming in mruby. Metaprogramming is the ability of a program to inspect, modify, and create its own code at runtime.
|
||||
|
||||
## Functionality
|
||||
|
||||
The `mruby-metaprog` mrbgem offers methods for:
|
||||
|
||||
- **Instance Variable Manipulation:**
|
||||
- `instance_variable_defined?(symbol)`: Checks if an instance variable is defined in an object.
|
||||
- `instance_variable_get(symbol)`: Retrieves the value of an instance variable.
|
||||
- `instance_variable_set(symbol, value)`: Sets the value of an instance variable.
|
||||
- `instance_variables()`: Returns an array of instance variable names in an object.
|
||||
- **Method Inspection:**
|
||||
- `methods(regular=true)`: Returns a list of public and protected methods of an object.
|
||||
- `private_methods(all=true)`: Returns a list of private methods accessible to an object.
|
||||
- `protected_methods(all=true)`: Returns a list of protected methods accessible to an object.
|
||||
- `public_methods(all=true)`: Returns a list of public methods accessible to an object.
|
||||
- `singleton_methods(all=true)`: Returns an array of singleton method names for an object.
|
||||
- **Singleton Method Definition:**
|
||||
- `define_singleton_method(name, &block)`: Defines a singleton method for an object.
|
||||
- **Class Variable Manipulation:**
|
||||
- `class_variable_defined?(symbol)`: Checks if a class variable is defined in a module.
|
||||
- `class_variable_get(symbol)`: Retrieves the value of a class variable.
|
||||
- `class_variable_set(symbol, value)`: Sets the value of a class variable.
|
||||
- `class_variables(inherit=true)`: Returns an array of class variable names in a module.
|
||||
- `remove_class_variable(symbol)`: Removes a class variable from a module.
|
||||
- **Module Inspection:**
|
||||
- `included_modules()`: Returns a list of modules included in a module or class.
|
||||
- `instance_methods(include_super=true)`: Returns an array of public and protected instance methods in a module or class.
|
||||
- `public_instance_methods(include_super=true)`: Returns an array of public instance methods in a module or class.
|
||||
- `private_instance_methods(include_super=true)`: Returns an array of private instance methods in a module or class.
|
||||
- `protected_instance_methods(include_super=true)`: Returns an array of protected instance methods in a module or class.
|
||||
- `undefined_instance_methods()`: Returns an array of undefined instance methods in a module/class.
|
||||
- **Method Removal:**
|
||||
- `remove_method(symbol)`: Removes a method from a class.
|
||||
- **Constant Inspection:**
|
||||
- `constants(inherit=true)`: Returns an array of constant names defined in a module.
|
||||
- **Module Nesting:**
|
||||
- `Module.nesting()`: Returns an array representing the current module nesting.
|
||||
- **Message Sending:**
|
||||
- `send(symbol, *args, &block)`: Invokes a method on an object.
|
||||
- `public_send(symbol, *args, &block)`: Invokes a public method on an object.
|
||||
- **Variable Inspection:**
|
||||
- `global_variables()`: Returns an array of global variable names.
|
||||
- `local_variables()`: Returns an array of local variable names in the current scope.
|
||||
|
||||
## Examples
|
||||
|
||||
### Working with Instance Variables
|
||||
|
||||
```ruby
|
||||
class MyClass
|
||||
def initialize(value)
|
||||
@my_var = value
|
||||
end
|
||||
end
|
||||
|
||||
obj = MyClass.new(10)
|
||||
|
||||
p obj.instance_variable_defined?(:@my_var) #=> true
|
||||
p obj.instance_variable_get(:@my_var) #=> 10
|
||||
obj.instance_variable_set(:@another_var, "hello")
|
||||
p obj.instance_variables #=> [:@my_var, :@another_var]
|
||||
```
|
||||
|
||||
### Inspecting Methods
|
||||
|
||||
```ruby
|
||||
class AnotherClass
|
||||
def public_method; end
|
||||
protected
|
||||
def protected_method; end
|
||||
private
|
||||
def private_method; end
|
||||
end
|
||||
|
||||
obj = AnotherClass.new
|
||||
p obj.public_methods(false) #=> [:public_method]
|
||||
p obj.protected_methods(false) #=> [:protected_method]
|
||||
p obj.private_methods(false) #=> [:private_method]
|
||||
|
||||
def obj.singleton_method_example; end
|
||||
p obj.singleton_methods #=> [:singleton_method_example]
|
||||
```
|
||||
|
||||
### Defining Singleton Methods
|
||||
|
||||
```ruby
|
||||
obj = Object.new
|
||||
obj.define_singleton_method(:greet) do |name|
|
||||
"Hello, #{name}!"
|
||||
end
|
||||
p obj.greet("World") #=> "Hello, World!"
|
||||
```
|
||||
|
||||
### Working with Class Variables
|
||||
|
||||
```ruby
|
||||
class ParentClass
|
||||
@@parent_cvar = 100
|
||||
end
|
||||
|
||||
class ChildClass < ParentClass
|
||||
@@child_cvar = 200
|
||||
|
||||
def self.get_parent_cvar
|
||||
class_variable_get(:@@parent_cvar)
|
||||
end
|
||||
end
|
||||
|
||||
p ChildClass.class_variable_defined?(:@@child_cvar) #=> true
|
||||
p ChildClass.class_variable_get(:@@child_cvar) #=> 200
|
||||
ChildClass.class_variable_set(:@@new_cvar, 300)
|
||||
p ChildClass.class_variables.sort #=> [:@@child_cvar, :@@new_cvar, :@@parent_cvar] (order may vary)
|
||||
p ChildClass.get_parent_cvar #=> 100
|
||||
ChildClass.remove_class_variable(:@@new_cvar)
|
||||
p ChildClass.class_variables.sort #=> [:@@child_cvar, :@@parent_cvar] (order may vary)
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This mrbgem is licensed under the [MIT License](LICENSE).
|
||||
@@ -182,11 +182,9 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass *kl
|
||||
}
|
||||
|
||||
ary = mrb_ary_new_capa(mrb, kh_size(set));
|
||||
for (khint_t i=0; i<kh_end(set); i++) {
|
||||
if (kh_exist(set, i)) {
|
||||
if (kh_val(set, i)) {
|
||||
mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set, i)));
|
||||
}
|
||||
KHASH_FOREACH(mrb, set, k) {
|
||||
if (kh_val(set, k)) {
|
||||
mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set, k)));
|
||||
}
|
||||
}
|
||||
kh_destroy(st, mrb, set);
|
||||
@@ -297,10 +295,8 @@ mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj)
|
||||
}
|
||||
|
||||
ary = mrb_ary_new(mrb);
|
||||
for (khint_t i=0;i<kh_end(set);i++) {
|
||||
if (kh_exist(set, i)) {
|
||||
mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set, i)));
|
||||
}
|
||||
KHASH_FOREACH(mrb, set, k) {
|
||||
mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set, k)));
|
||||
}
|
||||
kh_destroy(st, mrb, set);
|
||||
|
||||
@@ -643,8 +639,29 @@ mrb_mod_remove_method(mrb_state *mrb, mrb_value mod)
|
||||
static mrb_value
|
||||
mrb_mod_s_constants(mrb_state *mrb, mrb_value mod)
|
||||
{
|
||||
mrb_raise(mrb, E_NOTIMP_ERROR, "Module.constants not implemented");
|
||||
return mrb_nil_value(); /* not reached */
|
||||
if (mrb_get_argc(mrb) > 0 || mrb_class_ptr(mod) != mrb->module_class) {
|
||||
return mrb_mod_constants(mrb, mod);
|
||||
}
|
||||
|
||||
const struct RProc *proc = mrb->c->ci[-1].proc;
|
||||
struct RClass *c = MRB_PROC_TARGET_CLASS(proc);
|
||||
mrb_value ary = mrb_ary_new(mrb);
|
||||
|
||||
if (!c) c = mrb->object_class;
|
||||
mrb_mod_const_at(mrb, c, ary);
|
||||
proc = proc->upper;
|
||||
while (proc) {
|
||||
struct RClass *c2 = MRB_PROC_TARGET_CLASS(proc);
|
||||
if (!c2) c2 = mrb->object_class;
|
||||
mrb_mod_const_at(mrb, c2, ary);
|
||||
proc = proc->upper;
|
||||
}
|
||||
while (c) {
|
||||
mrb_mod_const_at(mrb, c, ary);
|
||||
c = c->super;
|
||||
if (c == mrb->object_class) break;
|
||||
}
|
||||
return ary;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
@@ -691,6 +708,7 @@ mrb_mruby_metaprog_gem_init(mrb_state* mrb)
|
||||
mrb_define_method_id(mrb, krn, MRB_SYM(singleton_methods), mrb_obj_singleton_methods_m, MRB_ARGS_OPT(1)); /* 15.3.1.3.45 */
|
||||
mrb_define_method_id(mrb, krn, MRB_SYM(define_singleton_method), mod_define_singleton_method, MRB_ARGS_REQ(1)|MRB_ARGS_BLOCK());
|
||||
mrb_define_method_id(mrb, krn, MRB_SYM(send), mrb_f_send, MRB_ARGS_REQ(1)|MRB_ARGS_REST()|MRB_ARGS_BLOCK()); /* 15.3.1.3.44 */
|
||||
mrb_define_method_id(mrb, krn, MRB_SYM(public_send), mrb_f_public_send, MRB_ARGS_REQ(1)|MRB_ARGS_REST()|MRB_ARGS_BLOCK());
|
||||
|
||||
mrb_define_method_id(mrb, mod, MRB_SYM(class_variables), mrb_mod_class_variables, MRB_ARGS_OPT(1)); /* 15.2.2.4.19 */
|
||||
mrb_define_method_id(mrb, mod, MRB_SYM(remove_class_variable), mrb_mod_remove_cvar, MRB_ARGS_REQ(1)); /* 15.2.2.4.39 */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# mruby-method
|
||||
|
||||
An implementation of class **Method** and **UnboundMethod** for mruby
|
||||
The `mruby-method` mrbgem provides implementations for the `Method` and `UnboundMethod` classes. These classes allow for powerful introspection and manipulation of methods in mruby. This includes obtaining information like method name, owner, receiver, parameters, and source location, as well as features like creating method objects from existing methods, binding unbound methods to objects, and unbinding methods from their receivers.
|
||||
|
||||
```ruby
|
||||
p Enumerable.instance_method(:find_all).source_location
|
||||
@@ -22,36 +22,43 @@ end
|
||||
|
||||
## Kernel
|
||||
|
||||
- `Kernel#method`
|
||||
- `Kernel#singleton_method`
|
||||
- `Kernel#method(sym)`: Returns a Method object corresponding to the method identified by `sym` for the receiver.
|
||||
- `Kernel#singleton_method(sym)`: Returns a Method object corresponding to the singleton method identified by `sym` for the receiver.
|
||||
|
||||
## Module
|
||||
|
||||
- `Module#instance_method`
|
||||
- `Module#instance_method(sym)`: Returns an UnboundMethod object corresponding to the instance method identified by `sym` in the module/class.
|
||||
|
||||
## Method class
|
||||
|
||||
- `Method#name`
|
||||
- `Method#call`
|
||||
- `Method#super_method`
|
||||
- `Method#arity`
|
||||
- `Method#unbind`
|
||||
- `Method#[]`
|
||||
- `Method#owner`
|
||||
- `Method#receiver`
|
||||
- `Method#parameters`
|
||||
- `Method#source_location`
|
||||
- `Method#to_proc`
|
||||
- `Method#name`: Returns the name of the method.
|
||||
- `Method#owner`: Returns the class or module that defines the method.
|
||||
- `Method#receiver`: Returns the object to which the method is bound.
|
||||
- `Method#arity`: Returns an integer indicating the number of arguments accepted by the method. A negative number indicates optional arguments.
|
||||
- `Method#parameters`: Returns an array of arrays, each describing a parameter (e.g., `[[:req, :foo]]`).
|
||||
- `Method#source_location`: Returns a two-element array `[filename, line_number]` indicating where the method was defined in Ruby code, or `nil` if not available. (Requires debug mode).
|
||||
- `Method#call(*args, **opts, &block)`: Invokes the method with the given arguments and block, returning the result.
|
||||
- `Method#[](*args, **opts, &block)`: Alias for `call`. Invokes the method.
|
||||
- `Method#super_method`: Returns a Method object representing the superclass's version of this method. Returns `nil` if no superclass method exists.
|
||||
- `Method#unbind`: Returns an UnboundMethod object based on this method.
|
||||
- `Method#to_proc`: Converts the Method object into a Proc object that can be called.
|
||||
- `Method#<< (other_method_or_proc)`: Returns a new Proc that represents the composition of this method and another method or proc (`self(other(...))`).
|
||||
- `Method#>> (other_method_or_proc)`: Returns a new Proc that represents the composition of another method or proc and this method (`other(self(...))`).
|
||||
- `Method#== (other)` / `Method#eql?(other)`: Returns `true` if the method is the same as `other` (same receiver, owner, and proc/name).
|
||||
- `Method#inspect`: Returns a string representation of the Method object, including its class, name, owner, and source location if available. (Alias for `to_s`).
|
||||
|
||||
## UnboundMethod class
|
||||
|
||||
- `UnboundMethod#name`
|
||||
- `UnboundMethod#bind`
|
||||
- `UnboundMethod#super_method`
|
||||
- `UnboundMethod#arity`
|
||||
- `UnboundMethod#owner`
|
||||
- `UnboundMethod#parameters`
|
||||
- `UnboundMethod#source_location`
|
||||
- `UnboundMethod#name`: Returns the name of the method.
|
||||
- `UnboundMethod#owner`: Returns the class or module that originally defined the method.
|
||||
- `UnboundMethod#arity`: Returns an integer indicating the number of arguments accepted by the method. A negative number indicates optional arguments.
|
||||
- `UnboundMethod#parameters`: Returns an array of arrays, each describing a parameter (e.g., `[[:req, :foo]]`).
|
||||
- `UnboundMethod#source_location`: Returns a two-element array `[filename, line_number]` indicating where the method was defined in Ruby code, or `nil` if not available. (Requires debug mode).
|
||||
- `UnboundMethod#bind(obj)`: Binds the UnboundMethod to `obj` and returns a Method object. Raises `TypeError` if `obj` is not an instance of the method's owner or its descendants.
|
||||
- `UnboundMethod#bind_call(obj, *args, **opts, &block)`: Binds the UnboundMethod to `obj` and then calls it with the given arguments and block.
|
||||
- `UnboundMethod#super_method`: Returns an UnboundMethod object representing the superclass's version of this method. Returns `nil` if no superclass method exists.
|
||||
- `UnboundMethod#== (other)` / `UnboundMethod#eql?(other)`: Returns `true` if the unbound method is the same as `other` (same owner and proc/name).
|
||||
- `UnboundMethod#inspect`: Returns a string representation of the UnboundMethod object, including its class, name, owner, and source location if available. (Alias for `to_s`).
|
||||
|
||||
# See also
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
# mruby-numeric-ext
|
||||
|
||||
## Purpose
|
||||
|
||||
This mrbgem extends the `Numeric` and `Integer` classes in mruby with additional methods for common numerical operations and checks.
|
||||
|
||||
## Functionality
|
||||
|
||||
This gem adds the following methods:
|
||||
|
||||
### Numeric Class
|
||||
|
||||
- `zero?`: Returns `true` if the number is zero, `false` otherwise.
|
||||
- `nonzero?`: Returns the number itself if it's not zero, `nil` otherwise.
|
||||
- `positive?`: Returns `true` if the number is greater than 0, `false` otherwise.
|
||||
- `negative?`: Returns `true` if the number is less than 0, `false` otherwise.
|
||||
- `integer?`: Returns `true` if the number is an `Integer` (this is overridden in the `Integer` class).
|
||||
|
||||
### Integer Class
|
||||
|
||||
- `allbits?(mask)`: Returns `true` if all bits of `self & mask` are 1.
|
||||
- `anybits?(mask)`: Returns `true` if any bits of `self & mask` are 1.
|
||||
- `nobits?(mask)`: Returns `true` if no bits of `self & mask` are 1.
|
||||
- `ceildiv(other)`: Returns the result of `self` divided by `other`, rounded up to the nearest integer.
|
||||
- `integer?`: Returns `true` (overrides `Numeric#integer?`).
|
||||
- `remainder(numeric)`: Returns the remainder of `self` divided by `numeric`. Equivalent to `x - y * (x / y).truncate`.
|
||||
- `pow(numeric)`: Returns `self` raised to the power of `numeric`.
|
||||
- `pow(integer, integer)`: Returns modular exponentiation (`(self ** exponent) % modulus`).
|
||||
- `digits(base=10)`: Returns an array of integers representing the base-radix digits of `self`. The first element is the least significant digit.
|
||||
- `size`: Returns the number of bytes in the machine representation of the integer.
|
||||
- `odd?`: Returns `true` if the integer is odd, `false` otherwise.
|
||||
- `even?`: Returns `true` if the integer is even, `false` otherwise.
|
||||
- `Integer.sqrt(integer)`: (Class method) Returns the integer square root of the given non-negative integer.
|
||||
|
||||
## How to use
|
||||
|
||||
To use this mrbgem, add it to your `build_config.rb`:
|
||||
|
||||
```ruby
|
||||
MRuby::Build.new do |conf|
|
||||
# ... (other configurations)
|
||||
conf.gem :core => 'mruby-numeric-ext'
|
||||
end
|
||||
```
|
||||
|
||||
Then you can use the extended methods:
|
||||
|
||||
```ruby
|
||||
p 5.positive? # => true
|
||||
p (-3).negative? # => true
|
||||
p 0.zero? # => true
|
||||
p 5.nonzero? # => 5
|
||||
p 0.nonzero? # => nil
|
||||
|
||||
p 7.allbits?(3) # => false (binary 111 & 011 is 011, not 011)
|
||||
p 7.anybits?(3) # => true
|
||||
p 7.nobits?(8) # => true (binary 111 & 1000 is 000)
|
||||
|
||||
p 10.ceildiv(3) # => 4
|
||||
p (-10).ceildiv(3) # => -3
|
||||
|
||||
p 10.remainder(3) # => 1
|
||||
p (-10).remainder(3) # => -1
|
||||
|
||||
p 2.pow(3) # => 8
|
||||
p 2.pow(3, 5) # => 3 ( (2**3) % 5 )
|
||||
|
||||
p 12345.digits # => [5, 4, 3, 2, 1]
|
||||
p 12345.digits(16) # => [9, 3, 0, 3]
|
||||
|
||||
p 42.size # => (depends on machine, e.g., 4 or 8)
|
||||
p 5.odd? # => true
|
||||
p 4.even? # => true
|
||||
p Integer.sqrt(16) # => 4
|
||||
p Integer.sqrt(17) # => 4
|
||||
```
|
||||
@@ -262,6 +262,46 @@ flo_remainder(mrb_state *mrb, mrb_value self)
|
||||
}
|
||||
#endif
|
||||
|
||||
static mrb_int
|
||||
isqrt(mrb_int n)
|
||||
{
|
||||
mrb_assert(n >= 0);
|
||||
if (n < 2) return n;
|
||||
|
||||
mrb_int x = n;
|
||||
mrb_int y = (x + 1) / 2;
|
||||
|
||||
// Babylonian method (integer version)
|
||||
while (y < x) {
|
||||
x = y;
|
||||
y = (x + n / x) / 2;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
int_sqrt(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value arg = mrb_get_arg1(mrb);
|
||||
|
||||
if (mrb_integer_p(arg)) {
|
||||
mrb_int n = mrb_integer(arg);
|
||||
if (n < 0) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "non-negative integer required");
|
||||
}
|
||||
return mrb_int_value(mrb, isqrt(n));
|
||||
}
|
||||
#ifdef MRB_USE_BIGINT
|
||||
else if (mrb_bigint_p(arg)) {
|
||||
return mrb_bint_sqrt(mrb, arg);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "expected Integer");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mrb_mruby_numeric_ext_gem_init(mrb_state* mrb)
|
||||
{
|
||||
@@ -275,6 +315,7 @@ mrb_mruby_numeric_ext_gem_init(mrb_state* mrb)
|
||||
mrb_define_method_id(mrb, ic, MRB_SYM(size), int_size, MRB_ARGS_NONE());
|
||||
mrb_define_method_id(mrb, ic, MRB_SYM_Q(odd), int_odd, MRB_ARGS_NONE());
|
||||
mrb_define_method_id(mrb, ic, MRB_SYM_Q(even), int_even, MRB_ARGS_NONE());
|
||||
mrb_define_class_method_id(mrb, ic, MRB_SYM(sqrt), int_sqrt, MRB_ARGS_REQ(1));
|
||||
|
||||
#ifndef MRB_NO_FLOAT
|
||||
struct RClass *fc = mrb->float_class;
|
||||
|
||||
@@ -81,3 +81,9 @@ assert('Integer#digits') do
|
||||
assert_equal([4, 6, 6, 0, 5], 12345.digits(7))
|
||||
assert_equal([45, 23, 1], 12345.digits(100))
|
||||
end
|
||||
|
||||
assert('Integer.sqrt') do
|
||||
assert_equal(4, Integer.sqrt(16))
|
||||
assert_equal(10, Integer.sqrt(100))
|
||||
assert_equal(85, Integer.sqrt(7244))
|
||||
end
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
# mruby-object-ext
|
||||
|
||||
This mrbgem provides several extension methods to core objects in mruby, enhancing their functionality and providing useful utilities for common programming patterns.
|
||||
|
||||
## Core Extension Methods
|
||||
|
||||
This gem extends core mruby objects with the following methods:
|
||||
|
||||
### `Kernel#yield_self` (aliased as `then`)
|
||||
|
||||
Yields the receiver (self) to the given block and returns the result of the block. This is useful for chaining operations in a readable way.
|
||||
|
||||
**Signature:**
|
||||
|
||||
```ruby
|
||||
obj.yield_self {|current_obj| ... } > an_object
|
||||
obj.then {|current_obj| ... } -> an_object
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```ruby
|
||||
result = "hello"
|
||||
.yield_self {|s| s.upcase }
|
||||
.then {|s| s + " WORLD" }
|
||||
|
||||
puts result #=> "HELLO WORLD"
|
||||
|
||||
# Another example with a different data type
|
||||
(1..5)
|
||||
.yield_self {|range| range.to_a }
|
||||
.then {|arr| arr.select(&:even?) }
|
||||
.then {|evens| evens.map {|n| n * n } }
|
||||
.then {|squares| puts squares.inspect } #=> [4, 16]
|
||||
```
|
||||
|
||||
### `Kernel#tap`
|
||||
|
||||
Yields the receiver (self) to the given block and then returns the receiver itself. This method is primarily used for "tapping into" a method chain to perform operations on intermediate results without affecting the final result of the chain.
|
||||
|
||||
**Signature:**
|
||||
|
||||
```ruby
|
||||
obj.tap {|current_obj| ... } -> obj
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```ruby
|
||||
(1..10)
|
||||
.to_a
|
||||
.tap {|arr| puts "Array: #{arr.inspect}" }
|
||||
.select(&:even?)
|
||||
.tap {|evens| puts "Evens: #{evens.inspect}" }
|
||||
.map {|n| n * n }
|
||||
.tap {|squares| puts "Squares: #{squares.inspect}" }
|
||||
# Output:
|
||||
# Array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
# Evens: [2, 4, 6, 8, 10]
|
||||
# Squares: [4, 16, 36, 64, 100]
|
||||
```
|
||||
|
||||
### `Kernel#itself`
|
||||
|
||||
Returns the receiver (self). While simple, it can be useful in certain chaining or meta-programming scenarios.
|
||||
|
||||
**Signature:**
|
||||
|
||||
```ruby
|
||||
obj.itself -> obj
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```ruby
|
||||
string = "my string"
|
||||
puts string.itself.object_id == string.object_id #=> true
|
||||
|
||||
# Can be useful with methods expecting a callable
|
||||
data = { a: 1, b: 2 }
|
||||
transformed_data = data.transform_values(&:itself) # No change if values are already what you want
|
||||
puts transformed_data #=> {:a=>1, :b=>2} (in mruby hash output format)
|
||||
```
|
||||
|
||||
### `BasicObject#instance_exec`
|
||||
|
||||
Executes the given block within the context of the receiver (obj). This means that inside the block, `self` is set to `obj`, giving the code access to `obj`'s instance variables and private methods. Arguments passed to `instance_exec` are passed as block parameters.
|
||||
|
||||
**Signature:**
|
||||
|
||||
```ruby
|
||||
obj.instance_exec(arg...) {|var...| block } -> result_of_block
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```ruby
|
||||
class MyClass
|
||||
def initialize(value)
|
||||
@secret = value
|
||||
end
|
||||
|
||||
def reveal_secret(multiplier, &block)
|
||||
# self here is MyClass instance
|
||||
instance_exec(multiplier, &block)
|
||||
end
|
||||
end
|
||||
|
||||
instance = MyClass.new(10)
|
||||
result = instance.reveal_secret(5) {|m| @secret * m }
|
||||
puts result #=> 50
|
||||
|
||||
# Example without a class context
|
||||
num = 42
|
||||
num.instance_exec("Number is: ") {|prefix| puts prefix + self.to_s } #=> Number is: 42
|
||||
```
|
||||
|
||||
## `NilClass` Extensions
|
||||
|
||||
This gem also adds convenient type conversion methods to `NilClass`:
|
||||
|
||||
- **`nil.to_a`**: Returns an empty Array (`[]`).
|
||||
|
||||
```ruby
|
||||
p nil.to_a #=> []
|
||||
```
|
||||
|
||||
- **`nil.to_f`**: Returns `0.0`.
|
||||
|
||||
```ruby
|
||||
p nil.to_f #=> 0.0
|
||||
```
|
||||
|
||||
- **`nil.to_h`**: Returns an empty Hash (`{}`).
|
||||
|
||||
```ruby
|
||||
p nil.to_h #=> {}
|
||||
```
|
||||
|
||||
- **`nil.to_i`**: Returns `0`.
|
||||
|
||||
```ruby
|
||||
p nil.to_i #=> 0
|
||||
```
|
||||
@@ -0,0 +1,59 @@
|
||||
# mruby-objectspace
|
||||
|
||||
This mrbgem provides the `ObjectSpace` module for mruby, allowing introspection of live objects within the mruby environment.
|
||||
|
||||
## Purpose
|
||||
|
||||
The `ObjectSpace` module offers methods to count and iterate over objects currently allocated by the mruby interpreter. This can be useful for debugging, memory profiling, or understanding the internal state of your mruby application.
|
||||
|
||||
## Functionality
|
||||
|
||||
### `ObjectSpace.count_objects([result_hash]) -> Hash`
|
||||
|
||||
Counts all objects currently alive in the mruby process, categorized by their types.
|
||||
|
||||
- **`result_hash` (optional `Hash`):** If provided, this hash will be cleared and populated with the results. This can be useful to avoid allocating a new hash during sensitive operations like memory profiling, potentially reducing probe effect.
|
||||
|
||||
- **Returns:** A `Hash` where keys are symbols representing object types (e.g., `:T_OBJECT`, `:T_CLASS`, `:T_STRING`) or, in some cases, internal type integers. The values are the counts of objects for each type. The hash also includes special keys:
|
||||
- `:TOTAL`: The total number of objects (including free slots).
|
||||
- `:FREE`: The number of free (unallocated) object slots.
|
||||
|
||||
**Example of the returned hash structure:**
|
||||
|
||||
```ruby
|
||||
{
|
||||
:TOTAL=>10000,
|
||||
:FREE=>3011,
|
||||
:T_OBJECT=>6,
|
||||
:T_CLASS=>404,
|
||||
:T_STRING=>500,
|
||||
# ... other types
|
||||
}
|
||||
```
|
||||
|
||||
### `ObjectSpace.each_object([module]) {|obj| ... } -> Fixnum`
|
||||
|
||||
Iterates over each live object in the mruby process, calling the provided block once for each object.
|
||||
|
||||
- **`module` (optional `Module` or `Class`):** If this argument is provided, the block will only be called for objects that are instances of the given `module` or one of its subclasses.
|
||||
|
||||
- **Block (`{|obj| ... }`):** A block that will be executed with each object (`obj`) found.
|
||||
|
||||
- **Returns:** A `Fixnum` representing the total number of objects iterated over.
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
```ruby
|
||||
# Iterate over all objects
|
||||
total_objects = ObjectSpace.each_object do |obj|
|
||||
# Do something with obj
|
||||
p obj
|
||||
end
|
||||
puts "Total objects found: #{total_objects}"
|
||||
|
||||
# Iterate only over Array objects
|
||||
array_count = ObjectSpace.each_object(Array) do |arr|
|
||||
p arr
|
||||
end
|
||||
puts "Found #{array_count} Arrays."
|
||||
```
|
||||
@@ -0,0 +1,75 @@
|
||||
# mruby-os-memsize
|
||||
|
||||
## Description
|
||||
|
||||
The `mruby-os-memsize` mrbgem extends the `ObjectSpace` module in mruby, providing tools to inspect the approximate amount of heap memory allocated for objects. This can be useful for debugging memory usage and understanding the memory footprint of your mruby application.
|
||||
|
||||
## Usage / API
|
||||
|
||||
This gem adds two class methods to the `ObjectSpace` module:
|
||||
|
||||
### `ObjectSpace.memsize_of(obj) -> Numeric`
|
||||
|
||||
Returns the approximate amount of heap memory allocated for the given `obj` in bytes.
|
||||
|
||||
- The returned value is platform-dependent, as it's based on the `size_t` type of the underlying C implementation.
|
||||
- Immediate values (e.g., integers, booleans, symbols) and some small, embedded objects (like short strings or small arrays that fit directly into an object pointer) will typically report a size of 0 or a very small, fixed size representing the object pointer itself.
|
||||
- The accuracy of the reported size can vary depending on the object's type and internal structure.
|
||||
|
||||
**Example:**
|
||||
|
||||
```ruby
|
||||
str = "This is a test string"
|
||||
array = [1, 2, 3, 4, 5]
|
||||
|
||||
puts "Size of string: #{ObjectSpace.memsize_of(str)} bytes"
|
||||
puts "Size of array: #{ObjectSpace.memsize_of(array)} bytes"
|
||||
puts "Size of 123: #{ObjectSpace.memsize_of(123)}" # Likely 0
|
||||
puts "Size of :symbol: #{ObjectSpace.memsize_of(:symbol)}" # Likely 0
|
||||
|
||||
class MyClass
|
||||
def initialize
|
||||
@data = "some internal data"
|
||||
end
|
||||
end
|
||||
instance = MyClass.new
|
||||
puts "Size of MyClass instance: #{ObjectSpace.memsize_of(instance)}"
|
||||
```
|
||||
|
||||
### `ObjectSpace.memsize_of_all([klass]) -> Numeric`
|
||||
|
||||
Returns the total approximate heap memory allocated for all living objects in the mruby environment.
|
||||
|
||||
- If an optional `klass` argument (a Class object) is provided, it returns the total memory size only for instances of that specific class.
|
||||
|
||||
**Example:**
|
||||
|
||||
```ruby
|
||||
# Get total memory size of all objects
|
||||
total_memory = ObjectSpace.memsize_of_all
|
||||
puts "Total heap memory used by all objects: #{total_memory} bytes"
|
||||
|
||||
# Get total memory size for all String objects
|
||||
total_string_memory = ObjectSpace.memsize_of_all(String)
|
||||
puts "Total heap memory used by Strings: #{total_string_memory} bytes"
|
||||
|
||||
class Person
|
||||
def initialize(name)
|
||||
@name = name
|
||||
end
|
||||
end
|
||||
|
||||
p1 = Person.new("Alice")
|
||||
p2 = Person.new("Bob")
|
||||
|
||||
total_person_memory = ObjectSpace.memsize_of_all(Person)
|
||||
puts "Total heap memory used by Person instances: #{total_person_memory} bytes"
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This mrbgem is released under the MIT License. (See `mrbgem.rake` for details within the mruby distribution).
|
||||
|
||||
## Author
|
||||
|
||||
mruby developers
|
||||
@@ -1,53 +1,111 @@
|
||||
# mruby-pack (pack / unpack)
|
||||
# mruby-pack
|
||||
|
||||
mruby-pack provides `Array#pack` and `String#unpack` for mruby.
|
||||
The `mruby-pack` mrbgem enhances mruby by providing `Array#pack` and `String#unpack` methods. These methods facilitate the conversion between Ruby data types (specifically arrays and strings) and binary data representations, offering a powerful way to handle binary data.
|
||||
|
||||
## Installation
|
||||
|
||||
Add the line below into your build configuration:
|
||||
|
||||
```
|
||||
conf.gem :core => 'mruby-pack'
|
||||
```ruby
|
||||
conf.gem :core => 'mruby-pack'
|
||||
```
|
||||
|
||||
There is no dependency on other mrbgems.
|
||||
|
||||
## Supported template string
|
||||
## `Array#pack`
|
||||
|
||||
- A : arbitrary binary string (space padded, count is width)
|
||||
- a : arbitrary binary string (null padded, count is width)
|
||||
- B : bit string (descending)
|
||||
- b : bit string (ascending)
|
||||
- C : 8-bit unsigned (unsigned char)
|
||||
- c : 8-bit signed (signed char)
|
||||
- D, d: 64-bit float, native format
|
||||
- E : 64-bit float, little endian byte order
|
||||
- e : 32-bit float, little endian byte order
|
||||
- F, f: 32-bit float, native format
|
||||
- G : 64-bit float, network (big-endian) byte order
|
||||
- g : 32-bit float, network (big-endian) byte order
|
||||
- H : hex string (high nibble first)
|
||||
- h : hex string (low nibble first)
|
||||
- I : unsigned integer, native endian (`unsigned int` in C)
|
||||
- i : signed integer, native endian (`int` in C)
|
||||
- J : unsigned integer, native endian (`uintptr_t` in C)
|
||||
- j : signed integer, native endian (`intptr_t` in C)
|
||||
- L : 32-bit unsigned, native endian (`uint32_t`)
|
||||
- l : 32-bit signed, native endian (`int32_t`)
|
||||
- m : base64 encoded string (see RFC 2045, count is width)
|
||||
- N : 32-bit unsigned, network (big-endian) byte order
|
||||
- n : 16-bit unsigned, network (big-endian) byte order
|
||||
- Q : 64-bit unsigned, native endian (`uint64_t`)
|
||||
- q : 64-bit signed, native endian (`int64_t`)
|
||||
- S : 16-bit unsigned, native endian (`uint16_t`)
|
||||
- s : 16-bit signed, native endian (`int16_t`)
|
||||
- U : UTF-8 character
|
||||
- V : 32-bit unsigned, VAX (little-endian) byte order
|
||||
- v : 16-bit unsigned, VAX (little-endian) byte order
|
||||
- x : null byte
|
||||
- X : back up bytes
|
||||
- Z : same as "a", except that null is added with \*
|
||||
- @ : absolute position
|
||||
The `Array#pack` method converts an array into a binary string. It takes a template string as an argument, which dictates how each element in the array should be converted and packed into the resulting binary string. The template string consists of directives, where each directive specifies the type and format of the data to be packed.
|
||||
|
||||
**Example:**
|
||||
|
||||
```ruby
|
||||
arr = [65, 66, 67]
|
||||
binary_string = arr.pack("ccc") # Packs three 8-bit signed integers
|
||||
# binary_string will be "ABC"
|
||||
|
||||
arr2 = [72, 101, 108, 108, 111]
|
||||
binary_string2 = arr2.pack("C*") # Packs all elements as 8-bit unsigned integers
|
||||
# binary_string2 will be "Hello"
|
||||
|
||||
arr3 = [0x1234, 0x5678]
|
||||
binary_string3 = arr3.pack("S>2") # Packs two 16-bit unsigned integers, big-endian
|
||||
# binary_string3 will be "\x12\x34\x56\x78" (depending on native endianness if S is used without > or <)
|
||||
# Using "n2" would be more explicit for network (big-endian) byte order:
|
||||
# binary_string3 = arr3.pack("n2") # Packs two 16-bit unsigned, network (big-endian) byte order
|
||||
# binary_string3 will be "\x12\x34\x56\x78"
|
||||
```
|
||||
|
||||
## `String#unpack`
|
||||
|
||||
The `String#unpack` method performs the reverse operation of `Array#pack`. It takes a binary string and a template string as input. It extracts data from the binary string according to the directives in the template and converts it into an array of Ruby objects.
|
||||
|
||||
**Example:**
|
||||
|
||||
```ruby
|
||||
binary_data = "test"
|
||||
arr = binary_data.unpack("aaaa")
|
||||
# arr will be ["t", "e", "s", "t"]
|
||||
|
||||
binary_data2 = "\x01\x02\x03"
|
||||
arr2 = binary_data2.unpack("C3") # Unpacks three 8-bit unsigned integers
|
||||
# arr2 will be [1, 2, 3]
|
||||
|
||||
binary_data3 = "Hello\x00World"
|
||||
arr3 = binary_data3.unpack("Z*Z*") # Unpacks two null-terminated strings
|
||||
# arr3 will be ["Hello", "World"]
|
||||
```
|
||||
|
||||
## Supported Template Directives
|
||||
|
||||
The template string is a sequence of characters that specify the type and format of the data to be packed or unpacked. Each directive can be followed by a count (e.g., "C4" for four 8-bit unsigned integers) or `*` to consume all remaining items/bytes.
|
||||
|
||||
Here is a list of supported template characters and their meanings:
|
||||
|
||||
| Directive | Description |
|
||||
| --------- | ------------------------------------------------------------------------------------------------------- |
|
||||
| `A` | Arbitrary binary string (space padded, count is width) |
|
||||
| `a` | Arbitrary binary string (null padded, count is width) |
|
||||
| `B` | Bit string (descending bit order) |
|
||||
| `b` | Bit string (ascending bit order) |
|
||||
| `C` | 8-bit unsigned integer (unsigned char) |
|
||||
| `c` | 8-bit signed integer (signed char) |
|
||||
| `D`, `d` | Double-precision float, native format (64-bit) |
|
||||
| `E` | Double-precision float, little-endian (64-bit) |
|
||||
| `e` | Single-precision float, little-endian (32-bit) |
|
||||
| `F`, `f` | Single-precision float, native format (32-bit) |
|
||||
| `G` | Double-precision float, network (big-endian) byte order (64-bit) |
|
||||
| `g` | Single-precision float, network (big-endian) byte order (32-bit) |
|
||||
| `H` | Hex string (high nibble first) |
|
||||
| `h` | Hex string (low nibble first) |
|
||||
| `I` | Unsigned integer, native endian (`unsigned int` in C) |
|
||||
| `i` | Signed integer, native endian (`int` in C) |
|
||||
| `J` | Unsigned integer, native endian (`uintptr_t` in C) |
|
||||
| `j` | Signed integer, native endian (`intptr_t` in C) |
|
||||
| `L` | 32-bit unsigned integer, native endian (`uint32_t`) |
|
||||
| `l` | 32-bit signed integer, native endian (`int32_t`) |
|
||||
| `m` | Base64 encoded string (see RFC 2045, count is input bytes for pack, output chars for unpack) |
|
||||
| `N` | 32-bit unsigned integer, network (big-endian) byte order |
|
||||
| `n` | 16-bit unsigned integer, network (big-endian) byte order |
|
||||
| `Q` | 64-bit unsigned integer, native endian (`uint64_t`) |
|
||||
| `q` | 64-bit signed integer, native endian (`int64_t`) |
|
||||
| `S` | 16-bit unsigned integer, native endian (`uint16_t`) (Use `S>` for big-endian, `S<` for little-endian) |
|
||||
| `s` | 16-bit signed integer, native endian (`int16_t`) (Use `s>` for big-endian, `s<` for little-endian) |
|
||||
| `U` | UTF-8 character |
|
||||
| `V` | 32-bit unsigned integer, VAX (little-endian) byte order |
|
||||
| `v` | 16-bit unsigned integer, VAX (little-endian) byte order |
|
||||
| `x` | Null byte (skip forward one byte) |
|
||||
| `X` | Back up one byte |
|
||||
| `Z` | Null-terminated string (when unpacking, reads until NULL; when packing, appends a NULL if count is `*`) |
|
||||
| `@` | Moves to absolute position (offset from the beginning of the string) |
|
||||
|
||||
**Modifiers:**
|
||||
|
||||
Some directives can be followed by modifiers that affect their behavior:
|
||||
|
||||
- `>`: Big-endian (for `S`, `s`, `L`, `l`, `Q`, `q`, etc., when native order is not desired).
|
||||
- `<`: Little-endian (for `S`, `s`, `L`, `l`, `Q`, `q`, etc., when native order is not desired).
|
||||
|
||||
These modifiers are typically used with integer and float types to specify byte order explicitly. For network byte order (big-endian), directives like `n` (16-bit) and `N` (32-bit) are commonly used.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -1188,7 +1188,7 @@ pack_nul(mrb_state *mrb, mrb_value dst, mrb_int didx, int count)
|
||||
}
|
||||
|
||||
static void
|
||||
check_x(mrb_state *mrb, int a, int count, char c)
|
||||
check_x(mrb_state *mrb, mrb_int a, mrb_int count, char c)
|
||||
{
|
||||
if (a < count) {
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "%c outside of string", c);
|
||||
@@ -1209,7 +1209,7 @@ has_tmpl(const struct tmpl *tmpl)
|
||||
}
|
||||
|
||||
static enum pack_dir
|
||||
read_tmpl(mrb_state *mrb, struct tmpl *tmpl, enum pack_type *typep, int *sizep, int *countp, unsigned int *flagsp)
|
||||
read_tmpl(mrb_state *mrb, struct tmpl *tmpl, enum pack_type *typep, mrb_int *sizep, mrb_int *countp, unsigned int *flagsp)
|
||||
{
|
||||
mrb_int t, tlen;
|
||||
int ch, size = 0;
|
||||
@@ -1505,7 +1505,7 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary)
|
||||
mrb_value o, result;
|
||||
struct tmpl tmpl;
|
||||
enum pack_type type;
|
||||
int count, size;
|
||||
mrb_int count, size;
|
||||
unsigned int flags;
|
||||
enum pack_dir dir;
|
||||
|
||||
@@ -1627,16 +1627,15 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary)
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
pack_unpack(mrb_state *mrb, mrb_value str, int single)
|
||||
pack_unpack(mrb_state *mrb, mrb_value str, mrb_bool single)
|
||||
{
|
||||
mrb_value result;
|
||||
struct tmpl tmpl;
|
||||
int count;
|
||||
mrb_int count;
|
||||
unsigned int flags;
|
||||
enum pack_dir dir;
|
||||
enum pack_type type;
|
||||
int size;
|
||||
int srcidx, srclen;
|
||||
mrb_int size, srcidx, srclen;
|
||||
const unsigned char *sptr;
|
||||
|
||||
prepare_tmpl(mrb, &tmpl);
|
||||
@@ -1749,13 +1748,13 @@ pack_unpack(mrb_state *mrb, mrb_value str, int single)
|
||||
static mrb_value
|
||||
mrb_pack_unpack(mrb_state *mrb, mrb_value str)
|
||||
{
|
||||
return pack_unpack(mrb, str, 0);
|
||||
return pack_unpack(mrb, str, FALSE);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_pack_unpack1(mrb_state *mrb, mrb_value str)
|
||||
{
|
||||
return pack_unpack(mrb, str, 1);
|
||||
return pack_unpack(mrb, str, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user