Compare commits

...

102 Commits

Author SHA1 Message Date
Yukihiro "Matz" Matsumoto 31ea49319a Merge pull request #6876 from dkgkdfg65/backport/7dfd560d-stable
[stable] backport: cap IO#puts recursion depth on cyclic arrays (mruby-io)
2026-05-31 08:18:35 +09:00
Yukihiro "Matz" Matsumoto 3533335aa0 mruby-io: cap puts recursion depth to prevent C stack overflow
io_puts_ary recursed unconditionally on nested arrays. For cyclic
arrays (a = []; a << a; puts a) or pathologically deep arrays,
this caused a C stack overflow.

Add a depth cap (IO_PUTS_MAX_DEPTH = 16); on overflow, write
"[...]\n" and return, matching CRuby's behavior on cycles. The
pattern mirrors mruby-set's MAX_NESTED_DEPTH for the same problem
shape (pure C recursion not dispatched as a Ruby method).

Reported by OSS-Fuzz (clusterfuzz testcase 6233530857488384).

Co-authored-by: Claude <noreply@anthropic.com>
(cherry picked from commit 7dfd560df8)
2026-05-30 01:31:48 +08:00
mimaki 831da26b90 Update version and release date. (mruby 4.0.0 (2026-04-20)) 2026-04-20 17:43:06 +09:00
mimaki 65eb1df5a3 Update version to 4.0.0RC4. 2026-04-13 18:54:26 +09:00
mimaki 3b483db61d Merge branch 'master' into stable 2026-04-13 18:51:16 +09:00
Yukihiro "Matz" Matsumoto d65f7a9c5a Merge pull request #6784 from mruby/fix/news-security-updates 2026-04-13 09:01:38 +09:00
Yukihiro "Matz" Matsumoto e0aadaf6c4 NEWS.md: add security fixes and merged PRs (#6780, #6781, #6783)
Co-authored-by: Claude <noreply@anthropic.com>
2026-04-13 08:39:21 +09:00
Yukihiro "Matz" Matsumoto dfd4eb52cc Merge pull request #6783 from jbampton/pin-actions 2026-04-13 08:16:14 +09:00
John Bampton ebed2d32a2 gha: pin workflows to hash 2026-04-11 17:51:28 +10:00
Yukihiro "Matz" Matsumoto 48fc4220d3 Merge pull request #6781 from mruby/fix/sprintf-uaf 2026-04-11 16:33:05 +09:00
Yukihiro "Matz" Matsumoto 18ba02662b Merge pull request #6780 from mruby/fix/string-prepend-overflow 2026-04-11 16:32:24 +09:00
Yukihiro "Matz" Matsumoto 59552ecb8e mruby-sprintf: protect format string from mutation during callbacks
mrb_str_format captured raw C pointers (p, end) into the format
string's buffer before the main loop. The %s and %p specifiers call
to_s and inspect, which can invoke Ruby code that mutates the format
string via String#replace, freeing or reallocating its buffer. The
loop then continued iterating with dangling pointers, reading freed
memory and potentially leaking adjacent heap contents into the result.

Duplicate the format string with mrb_str_dup() before the loop. This
is O(1) because mrb_str_dup shares the underlying buffer; if the
original is later mutated via String#replace, str_replace decrements
the shared refcount, leaving our duplicate's buffer intact.

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-10 14:51:59 +09:00
Yukihiro "Matz" Matsumoto af6f23ddb3 mruby-string-ext: fix String#prepend with self-referencing arguments
String#prepend(s, s) read RSTRING_LEN(argv[i]) in the copy loop after
mrb_str_resize had already updated the receiver's length, causing the
memcpy to write past the allocated buffer.

Detect self-references with mrb_obj_eq() and read from the memmoved
original data at p + total_prepend_len using the captured self_len.
This also handles mixed cases like s.prepend("X", s) where earlier
writes would otherwise corrupt the source of later reads.

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-10 14:44:46 +09:00
Yukihiro "Matz" Matsumoto 4eb4884219 Merge pull request #6778 from mruby/dependabot/github_actions/github-actions-dependencies-6289042708 2026-04-09 07:55:37 +09:00
dependabot[bot] c394525da6 build(deps): bump super-linter/super-linter
Bumps the github-actions-dependencies group with 1 update: [super-linter/super-linter](https://github.com/super-linter/super-linter).


Updates `super-linter/super-linter` from 8.5.0 to 8.6.0
- [Release notes](https://github.com/super-linter/super-linter/releases)
- [Changelog](https://github.com/super-linter/super-linter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/super-linter/super-linter/compare/v8.5.0...v8.6.0)

---
updated-dependencies:
- dependency-name: super-linter/super-linter
  dependency-version: 8.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-08 14:54:46 +00:00
Yukihiro "Matz" Matsumoto 5d5cf0c3ea Merge pull request #6772 from mruby/fix/update-news 2026-04-02 20:33:46 +09:00
Yukihiro "Matz" Matsumoto 3a5c45f282 NEWS.md: update for recent changes
Add entries for language changes (case/in NoMatchingPatternError,
compound statement in tLPAREN_ARG), C API additions (mrb_bigint_p(),
RVALUE union), compiler optimizations (literal chunking), build
fixes (MSYS2), security fixes, and 26 merged pull requests.

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-02 20:17:19 +09:00
mimaki 6c121b9708 Update version to 4.0.0RC3. 2026-04-02 11:23:31 +09:00
mimaki d06cb40725 Merge branch 'master' into stable 2026-04-02 10:31:49 +09:00
Yukihiro "Matz" Matsumoto 0cc4caad2b Merge pull request #6769 from khasinski/fix-socket-recvfrom-nonblock 2026-04-01 09:23:00 +09:00
Yukihiro "Matz" Matsumoto 0cef3e5414 Merge pull request #6770 from jbampton/patch-2 2026-04-01 09:17:38 +09:00
Yukihiro "Matz" Matsumoto 825d4c388e Merge pull request #6771 from mruby/dependabot/pre_commit/pre-commit-hooks-820b35f878 2026-04-01 09:16:17 +09:00
dependabot[bot] 141a8bc406 build(deps): bump https://github.com/rhysd/actionlint
Bumps the pre-commit-hooks group with 1 update: [https://github.com/rhysd/actionlint](https://github.com/rhysd/actionlint).


Updates `https://github.com/rhysd/actionlint` from v1.7.11 to 1.7.12
- [Release notes](https://github.com/rhysd/actionlint/releases)
- [Changelog](https://github.com/rhysd/actionlint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rhysd/actionlint/compare/v1.7.11...v1.7.12)

---
updated-dependencies:
- dependency-name: https://github.com/rhysd/actionlint
  dependency-version: 1.7.12
  dependency-type: direct:production
  dependency-group: pre-commit-hooks
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-31 15:00:01 +00:00
John Bampton a6aa0fdb24 Dependabot: add cooldown to pre-commit ecosystem 2026-04-01 00:46:24 +10:00
Chris Hasiński b85c520843 Remove stale self-corruption workaround in recvfrom_nonblock
The s = self workaround and XXX comment in recvfrom_nonblock date back
to the initial import of mruby-socket. The underlying bug where self
became a SystemcallException inside ensure blocks has since been fixed.

Verified that self correctly refers to the socket object in ensure
blocks after exceptions from recvfrom.
2026-03-30 22:14:26 +02:00
Yukihiro "Matz" Matsumoto d522bd5aa2 Merge pull request #6768 from hasumikin/fix/envadjust 2026-03-30 21:18:06 +09:00
HASUMI Hitoshi d95ebe4a23 Fix stack extension bug causing HardFault
This patch fixes a bug in the stack extension logic that could cause a HardFault on certain configurations when the stack is reallocated to a new address.

## Background

When the mruby VM's stack runs out, stack_extend_alloc() calls mrb_realloc to grow it.
If reallocation moves the block to a new address, envadjust() adjusts all ci->stack pointers to point into the new allocation.

## The bug

The bug happened under the configuration below:

- MRB_INT64 on MRB_32BIT (`sizeof(mrb_value) == 16` because MRB_NO_BOXING is now mandatory)
- Allocator with 8-byte alignment (eg. PICORB_ALLOC_ALIGN=8 in PicoRuby for Raspi Pico)

The delta was computed via mrb_value* pointer subtraction:

```c
ptrdiff_t delta = newbase - oldbase;  // units of sizeof(mrb_value)
```

If :
- Old address: 0x2004c508
- New address: 0x2004c510 (8-byte difference)

The pointer subtraction truncated: 8 / 16 = 0.
envadjust() was misleaded as `delta == 0` and returned early without adjusting any ci->stack pointers.
The stbase was updated to the new address, but all stack pointers still pointed 8 bytes before it.
Every register access was shifted, reading garbage, ultimately causing a HardFault.

## The fix

Byte-level char* calculation instead of mrb_value* calculation:

```c
ptrdiff_t off = (char*)newbase - (char*)oldbase;
// ...
ci->stack = (mrb_value*)((char*)ci->stack + off);
```

This ensures the adjustment is exact regardless of sizeof(mrb_value) and allocator alignment.
2026-03-30 16:25:46 +09:00
Yukihiro "Matz" Matsumoto ac9f7aedd2 Merge pull request #6767 from mruby/fix/lparen-arg-compstmt 2026-03-30 07:54:31 +09:00
Yukihiro "Matz" Matsumoto 919cbd8fea mruby-compiler: allow compound statement in tLPAREN_ARG
Change the grammar rule for tLPAREN_ARG from accepting only a
single stmt to accepting compstmt. This allows compound
statements with semicolons inside parenthesized arguments when
the parenthesis is preceded by a space, e.g., `p (f1; f2)`.

This matches the behavior of CRuby 3.3+.

Fixes #6766.

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-30 07:06:30 +09:00
Yukihiro "Matz" Matsumoto 801eefeab6 Merge pull request #6765 from khasinski/fix-lazy-flat-map 2026-03-29 22:55:13 +09:00
Chris Hasiński 8f71887e46 Improve flat_map test descriptions for clarity 2026-03-28 23:14:46 +01:00
Chris Hasiński 3f52ef6cfc Fix Lazy#flat_map to handle non-enumerable block return values
When the block passed to Lazy#flat_map returns a non-enumerable value
(e.g. an Integer), mruby raised NoMethodError because it unconditionally
called #each on the result. CRuby yields non-enumerable values directly.

Use respond_to?(:each) to match CRuby behavior: iterate enumerable
results, yield non-enumerable results as-is.
2026-03-28 22:59:11 +01:00
Yukihiro "Matz" Matsumoto 28c5b1b17b Merge pull request #6763 from mruby/dependabot/github_actions/github-actions-dependencies-19ba90ca6e 2026-03-26 14:27:05 +09:00
dependabot[bot] d50932c50f build(deps): bump j178/prek-action
Bumps the github-actions-dependencies group with 1 update: [j178/prek-action](https://github.com/j178/prek-action).


Updates `j178/prek-action` from 1 to 2
- [Release notes](https://github.com/j178/prek-action/releases)
- [Commits](https://github.com/j178/prek-action/compare/v1...v2)

---
updated-dependencies:
- dependency-name: j178/prek-action
  dependency-version: '2'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-25 14:54:41 +00:00
Yukihiro "Matz" Matsumoto b7e3743130 Merge pull request #6762 from mruby/fix-test-build-race 2026-03-25 15:49:46 +09:00
Yukihiro "Matz" Matsumoto 805e6dbc33 Merge pull request #6761 from mruby/fix-gc-unregister-leak 2026-03-25 15:44:44 +09:00
Yukihiro "Matz" Matsumoto e8c5e7c0cd mruby-test: write generated C files atomically to avoid race condition
With `rake -m`, the C compiler can start reading a partially-written
gem_test.c before generation completes. Write to a .tmp file first,
then rename to the final path.

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-25 15:32:36 +09:00
Yukihiro "Matz" Matsumoto ab249864cc gc.c: remove all matching entries in mrb_gc_unregister()
Previously only the first match was removed, leaking duplicate
entries when the same object was registered multiple times.
Use two-pointer compaction for O(N) removal.

Fixes #6760.

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-25 15:29:27 +09:00
Yukihiro "Matz" Matsumoto c2b588139f Merge pull request #6758 from dearblue/vm 2026-03-25 15:17:02 +09:00
Yukihiro "Matz" Matsumoto 21dc829903 Merge pull request #6759 from dearblue/bigint 2026-03-25 15:15:49 +09:00
dearblue 6c4a8c09db Define mrb_bigint_p() always.
Define the `mrb_bigint_p()` macro function, which returns false if `MRB_USE_BIGINT` is undefined.
2026-03-24 22:16:15 +09:00
dearblue c52faebb7f Don't assign the result of mrb_funcall() directly to regs
There are two reasons:

  - If the mruby call stack is extended, the `ci` variable may become invalid.
  - The C language does not specify the order in which the left-hand and right-hand sides of an assignment expression are evaluated.
    Therefore, if the mruby data stack is extended, `ci->stack` may become invalid.
2026-03-24 21:25:46 +09:00
Yukihiro "Matz" Matsumoto f61ab96689 Merge pull request #6756 from dearblue/array-ext 2026-03-24 15:04:58 +09:00
Yukihiro "Matz" Matsumoto 07a6c6e56b Merge pull request #6757 from mruby/dependabot/pre_commit/pre-commit-hooks-ae77450b09 2026-03-24 09:30:46 +09:00
dependabot[bot] 45ebb3d0c8 build(deps): bump https://github.com/rubocop/rubocop
Bumps the pre-commit-hooks group with 1 update: [https://github.com/rubocop/rubocop](https://github.com/rubocop/rubocop).


Updates `https://github.com/rubocop/rubocop` from v1.85.1 to 1.86.0
- [Release notes](https://github.com/rubocop/rubocop/releases)
- [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop/compare/v1.85.1...v1.86.0)

---
updated-dependencies:
- dependency-name: https://github.com/rubocop/rubocop
  dependency-version: 1.86.0
  dependency-type: direct:production
  dependency-group: pre-commit-hooks
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-23 15:23:09 +00:00
dearblue 2135088ada Avoid the impact of object modifications caused by calls to mrb_vm_exec()
Several methods defined in mruby-array-ext are written in C and may call `mrb_vm_exec()`.
If array objects are modified on the Ruby side, problems may arise in subsequent processing.

  - Using objects that have been removed from the array and garbage collected
  - Using pointers or array lengths that have become invalid due to changes to the array object
  - Modifying the contents of a shared array object directly

ref: https://github.com/mruby/mruby/issues/6662
2026-03-22 23:05:37 +09:00
Yukihiro "Matz" Matsumoto 04f998238e Merge pull request #6755 from leviongit/vm/karg/delete-return 2026-03-21 17:03:27 +09:00
Yukihiro "Matz" Matsumoto affcbb000b Merge pull request #6754 from leviongit/core/attr_accessor/nullary 2026-03-21 17:02:24 +09:00
Yukihiro "Matz" Matsumoto ff5e6a2491 Merge pull request #6753 from dearblue/array.product 2026-03-21 16:57:49 +09:00
leviongit e8d0750458 reload ci after mrb_hash_delete_key 2026-03-20 21:35:26 +01:00
leviongit 88e356e7da remove redundant mrb_hash_get call
`mrb_hash_delete` returns the removed element (which is guaranteed to
exist due to the `mrb_hash_key_p` check), this prevents the hash from
being searched twice.
2026-03-20 21:20:18 +01:00
leviongit 95ece95e37 prefer marking the procs implementing attr_reader methods as noarg
this commit works on #6752 so it doesn't require a call to
`mrb_get_args`
2026-03-20 19:14:54 +01:00
dearblue 98d763603c Further optimize Array#product
Replace `__product_group` method with `__product_generate` and `__product_next`.
This change eliminates the need for Ruby to perform internal state calculations, allowing it to simply receive the results.
2026-03-20 21:13:52 +09:00
Yukihiro "Matz" Matsumoto 01ce2f8c71 Merge pull request #6747 from katafrakt/handle-hash-default-arg 2026-03-20 16:44:27 +09:00
Yukihiro "Matz" Matsumoto f08dede1d9 Merge pull request #6752 from khasinski/fix-attr-reader-arity 2026-03-20 16:40:45 +09:00
Yukihiro "Matz" Matsumoto 3bfe703f80 Merge pull request #6750 from dearblue/array.product 2026-03-20 10:24:10 +09:00
Yukihiro "Matz" Matsumoto e82fa70004 Merge pull request #6749 from hasumikin/fix/microcontroller-profile 2026-03-20 10:22:32 +09:00
Yukihiro "Matz" Matsumoto 8d53f65b96 Merge pull request #6748 from jbampton/clean-up-workflows 2026-03-20 10:21:45 +09:00
Chris Hasiński c0b1e87c09 Fix attr_reader-generated methods accepting extra arguments
attr_reader-generated getter methods silently ignored any arguments
passed to them. CRuby raises ArgumentError in this case.

Add mrb_get_args(mrb, "") to enforce zero arguments, matching CRuby.
2026-03-19 23:12:14 +01:00
dearblue 8441eaf633 Fixed "Out-of-bounds Read" and "Divide-by-Zero" in ary_product_group()
Reproduction:

  - Out-of-bounds Read

    ```console
    % build/host/bin/mruby -e '([nil] * 256).__product_group([[nil] * 256], 1 << 32, 256)'
    zsh: segmentation fault (core dumped)  build/host/bin/mruby -e
    ```

  - Divide-by-Zero

    ```console
    % build/host/bin/mruby -e '([nil] * 256).__product_group([[]], 1 << 32, 256)'
    zsh: floating point exception (core dumped)  build/host/bin/mruby -e '([nil] * 256).__product_group([[]], 1 << 32, 256)'
    ```
2026-03-19 23:11:06 +09:00
HASUMI Hitoshi 736a72cdc9 [skip ci] Update include/mrbconf.h
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-19 09:50:15 +09:00
HASUMI Hitoshi 5e9eed2d0c Fix KHASH_DEFAULT_SIZE to KHASH_INITIAL_SIZE rename inconsistencies
Commit 250bf6edd renamed KHASH_DEFAULT_SIZE to KHASH_INITIAL_SIZE but
missed updating build_config files and documentation. Also restore the
default value in khash.h to 32, consistent with the documented default
and the profile hierarchy (MRB_CONSTRAINED_BASELINE_PROFILE reduces it
to 16).
2026-03-19 09:38:36 +09:00
John Bampton 80d84188fd pre-commit bump Node.js 2026-03-18 17:57:33 +10:00
John Bampton 55ef8e1728 Update workflows 2026-03-18 17:57:05 +10:00
Paweł Świątkowski 13d9d770fc Correctly handle empty hash as default named argument
```
def func(arg: {})
  p arg
end
```

This used to work in earlier mruby versions, but broke somewhere recently.
2026-03-18 08:53:20 +01:00
Yukihiro "Matz" Matsumoto a41eeaed33 Merge pull request #6735 from dearblue/presym 2026-03-16 21:55:22 +09:00
Yukihiro "Matz" Matsumoto 4ed4326dd5 Merge pull request #6746 from mruby/dependabot/pre_commit/pre-commit-hooks-6e50fbf5c1 2026-03-16 21:47:31 +09:00
dearblue 000acedc35 Prevent full recompilation without changes to presym file
Commit b9a1a1fb23 is a revert of commit 8df9a22a85, differing only in the comment.
This means the issue from https://github.com/mruby/mruby/issues/6721 has reappeared.

The cause of https://github.com/mruby/mruby/issues/6721, as stated in the commit message for commit 8df9a22a85, is that each ".o" file has an indirect dependency on all ".pi" files through the presym file.

This patch therefore adds a proxy-like task `gensym:update:#{build.name}` between tasks.
Its purpose is to hide the direct dependency from ".o" files to the presym file from the rake system.
2026-03-14 17:14:37 +09:00
dependabot[bot] 14e98c60c3 build(deps): bump the pre-commit-hooks group across 1 directory with 8 updates
Bumps the pre-commit-hooks group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [https://github.com/gitleaks/gitleaks](https://github.com/gitleaks/gitleaks) | `v8.30.0` | `8.30.1` |
| [https://github.com/oxipng/oxipng](https://github.com/oxipng/oxipng) | `v10.0.0` | `10.1.0` |
| [https://github.com/Lucas-C/pre-commit-hooks](https://github.com/Lucas-C/pre-commit-hooks) | `v1.5.5` | `1.5.6` |
| [https://github.com/rhysd/actionlint](https://github.com/rhysd/actionlint) | `v1.7.9` | `1.7.11` |
| [https://github.com/codespell-project/codespell](https://github.com/codespell-project/codespell) | `v2.4.1` | `2.4.2` |
| [https://github.com/igorshubovych/markdownlint-cli](https://github.com/igorshubovych/markdownlint-cli) | `v0.46.0` | `0.48.0` |
| [https://github.com/rubocop/rubocop](https://github.com/rubocop/rubocop) | `v1.81.7` | `1.85.1` |
| [https://github.com/adrienverge/yamllint](https://github.com/adrienverge/yamllint) | `v1.37.1` | `1.38.0` |



Updates `https://github.com/gitleaks/gitleaks` from v8.30.0 to 8.30.1
- [Release notes](https://github.com/gitleaks/gitleaks/releases)
- [Commits](https://github.com/gitleaks/gitleaks/compare/v8.30.0...v8.30.1)

Updates `https://github.com/oxipng/oxipng` from v10.0.0 to 10.1.0
- [Release notes](https://github.com/oxipng/oxipng/releases)
- [Changelog](https://github.com/oxipng/oxipng/blob/master/CHANGELOG.md)
- [Commits](https://github.com/oxipng/oxipng/compare/v10.0.0...v10.1.0)

Updates `https://github.com/Lucas-C/pre-commit-hooks` from v1.5.5 to 1.5.6
- [Release notes](https://github.com/Lucas-C/pre-commit-hooks/releases)
- [Commits](https://github.com/Lucas-C/pre-commit-hooks/compare/v1.5.5...v1.5.6)

Updates `https://github.com/rhysd/actionlint` from v1.7.9 to 1.7.11
- [Release notes](https://github.com/rhysd/actionlint/releases)
- [Changelog](https://github.com/rhysd/actionlint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rhysd/actionlint/compare/v1.7.9...v1.7.11)

Updates `https://github.com/codespell-project/codespell` from v2.4.1 to 2.4.2
- [Release notes](https://github.com/codespell-project/codespell/releases)
- [Commits](https://github.com/codespell-project/codespell/compare/v2.4.1...v2.4.2)

Updates `https://github.com/igorshubovych/markdownlint-cli` from v0.46.0 to 0.48.0
- [Release notes](https://github.com/igorshubovych/markdownlint-cli/releases)
- [Commits](https://github.com/igorshubovych/markdownlint-cli/compare/v0.46.0...v0.48.0)

Updates `https://github.com/rubocop/rubocop` from v1.81.7 to 1.85.1
- [Release notes](https://github.com/rubocop/rubocop/releases)
- [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop/compare/v1.81.7...v1.85.1)

Updates `https://github.com/adrienverge/yamllint` from v1.37.1 to 1.38.0
- [Release notes](https://github.com/adrienverge/yamllint/releases)
- [Changelog](https://github.com/adrienverge/yamllint/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/adrienverge/yamllint/compare/v1.37.1...v1.38.0)

---
updated-dependencies:
- dependency-name: https://github.com/gitleaks/gitleaks
  dependency-version: 8.30.1
  dependency-type: direct:production
  dependency-group: pre-commit-hooks
- dependency-name: https://github.com/oxipng/oxipng
  dependency-version: 10.1.0
  dependency-type: direct:production
  dependency-group: pre-commit-hooks
- dependency-name: https://github.com/Lucas-C/pre-commit-hooks
  dependency-version: 1.5.6
  dependency-type: direct:production
  dependency-group: pre-commit-hooks
- dependency-name: https://github.com/rhysd/actionlint
  dependency-version: 1.7.11
  dependency-type: direct:production
  dependency-group: pre-commit-hooks
- dependency-name: https://github.com/codespell-project/codespell
  dependency-version: 2.4.2
  dependency-type: direct:production
  dependency-group: pre-commit-hooks
- dependency-name: https://github.com/igorshubovych/markdownlint-cli
  dependency-version: 0.48.0
  dependency-type: direct:production
  dependency-group: pre-commit-hooks
- dependency-name: https://github.com/rubocop/rubocop
  dependency-version: 1.85.1
  dependency-type: direct:production
  dependency-group: pre-commit-hooks
- dependency-name: https://github.com/adrienverge/yamllint
  dependency-version: 1.38.0
  dependency-type: direct:production
  dependency-group: pre-commit-hooks
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-13 14:57:23 +00:00
mimaki 9d523e2f74 Update version to 4.0.0RC2. 2026-03-12 19:07:19 +09:00
mimaki 380c459d37 Merge branch 'master' into stable 2026-03-12 19:01:29 +09:00
Yukihiro "Matz" Matsumoto eb7d0b86d7 Merge pull request #6736 from jbampton/add-dependabot-pre-commit 2026-03-12 17:16:48 +09:00
John Bampton 9bdf998faa Add pre-commit ecosystem to Dependabot
Group dependabot updates to reduce repo noise

Add descriptive group labels

https://github.blog/changelog/2026-03-10-dependabot-now-supports-pre-commit-hooks/

https://docs.github.com/en/code-security/reference/supply-chain-security/dependabot-options-reference#package-ecosystem-
2026-03-12 16:59:11 +10:00
Yukihiro "Matz" Matsumoto 457a50b485 Merge pull request #6744 from mruby/fix/case-in-no-match-error 2026-03-12 14:36:46 +09:00
Yukihiro "Matz" Matsumoto 143959b94b doc: fix prettier formatting in markdown files
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-12 14:33:37 +09:00
Yukihiro "Matz" Matsumoto d8de35b635 codegen.c: raise NoMatchingPatternError in case/in without else
case/in without else clause now raises NoMatchingPatternError
when no pattern matches, matching CRuby behavior. Fixes #6741.

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-12 14:28:17 +09:00
Yukihiro "Matz" Matsumoto b34b7206f9 Merge pull request #6738 from jbampton/add-manual-hooks-workflow 2026-03-12 14:20:02 +09:00
Yukihiro "Matz" Matsumoto 03d1f7d6ec Merge pull request #6743 from mruby/fix/words-chunking 2026-03-12 14:17:38 +09:00
Yukihiro "Matz" Matsumoto 9239a9e0ef pre-commit: fix prettier formatting in doc/guides/capi.md
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-12 14:05:48 +09:00
Yukihiro "Matz" Matsumoto 62cf0dc17a codegen.c: chunk %w() and %i() literals to reduce register pressure
Apply the same chunking strategy used for regular array literals
to %w() and %i() literal arrays in gen_literal_array(). Fixes #6740.

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-12 12:12:50 +09:00
Yukihiro "Matz" Matsumoto 12af8f513e Merge pull request #6742 from mruby/fix/remove-markdown-link-check 2026-03-12 11:52:45 +09:00
Yukihiro "Matz" Matsumoto 6a7561da5f pre-commit: remove JSON references from prettier hook
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-12 11:41:17 +09:00
Yukihiro "Matz" Matsumoto ab378ec01e Merge pull request #6690 from jbampton/cleanup-prettier-pre-commit 2026-03-12 11:37:25 +09:00
Yukihiro "Matz" Matsumoto 2d00f4a284 Merge pull request #6739 from mimaki/fix-msys2-build-error 2026-03-12 11:36:53 +09:00
Yukihiro "Matz" Matsumoto 628cf498a7 pre-commit: remove markdown-link-check hook
External link checkers are inherently flaky in CI due to
websites blocking automated requests (e.g. 403 errors).
Also remove JSON hooks (pretty-format-json, check-json)
since no JSON files remain in the repository.

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-12 11:32:37 +09:00
mimaki 77f6ffecc7 Updates build script to support MSYS2 drive letters, fixing build error with MSYS2. 2026-03-11 11:31:55 +09:00
John Bampton 626b2fa469 Put manual hooks in separate workflow file 2026-03-11 10:29:57 +10:00
Yukihiro "Matz" Matsumoto cfc83bb6ac Merge pull request #6734 from mruby/fix/array-chunking 2026-03-10 17:01:28 +09:00
Yukihiro "Matz" Matsumoto 46e8101c03 Merge pull request #6733 from mruby/fix/presym-include 2026-03-10 16:59:51 +09:00
Yukihiro "Matz" Matsumoto fff7db05bf Merge pull request #6732 from mruby/fix/language-md-markup 2026-03-10 16:58:34 +09:00
Yukihiro "Matz" Matsumoto f98d6414dc codegen.c: chunk array literals at 64 elements to reduce register pressure
Array literals were being built by loading all elements into registers
before constructing the array, requiring nregs proportional to the array
size (e.g. nregs=99 for 100 elements). This exceeds mruby/c's register
limit. Restore 3.4-era chunking at GEN_LIT_ARY_MAX (64) elements.

fixes mruby/mruby#6731

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-09 16:50:59 +09:00
Yukihiro "Matz" Matsumoto 8956c5abb5 mruby.h: include mruby/presym.h for all source files
Since presym is now mandatory, mruby.h includes presym.h so that
MRB_SYM() macros are available everywhere without explicit include.
Remove redundant #include <mruby/presym.h> from all source files.

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-09 16:50:58 +09:00
Yukihiro "Matz" Matsumoto 8f3917f361 language.md: remove unnecessary bold markup from "operator"
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-09 16:50:54 +09:00
Yukihiro "Matz" Matsumoto 72c9e5d027 Merge pull request #6598 from dearblue/method_missing 2026-03-09 16:38:08 +09:00
Yukihiro "Matz" Matsumoto 295b40534f Merge pull request #6730 from dearblue/presym 2026-03-09 10:35:42 +09:00
Yukihiro "Matz" Matsumoto 5acc520a1e Merge pull request #6729 from dearblue/gensym 2026-03-09 10:34:02 +09:00
dearblue f6f1a42039 Simplifying presym file generation actions
By performing output to presym files after header files, there is no longer a need to check for the existence of header files.
Furthermore, concentrating the file output logic into an "if" block eliminates the need for the `update` variable.

Strict atomicity between presym files and header files is still not guaranteed, as before.
If atomicity is truly required, it can be achieved by deleting the presym file before updating the header files.
2026-03-08 22:45:45 +09:00
dearblue 9fff63b436 Simplifying dependency addition for gensym task
The `gensym_task` variable was only used for dependency addition and is no longer needed.
2026-03-08 22:43:47 +09:00
Yukihiro "Matz" Matsumoto 17ab42d4c9 Merge pull request #6728 from mruby/dependabot/github_actions/actions/upload-artifact-7 2026-03-06 08:17:12 +09:00
dependabot[bot] fcb665b88c build(deps): bump actions/upload-artifact from 6 to 7
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-05 14:52:19 +00:00
John Bampton 3c7d19d41b prettier: set pass_filenames: false to avoid multiple passes
Updated `.prettierignore` to ingnore the typical Python environment files from `.venv`

If you are running pre-commit locally you probably have a Python environment setup.

This PR speeds up the prettier hook and avoids multiple passes through the targetted files.
2025-12-30 01:53:03 +10:00
dearblue 550d10adb7 Fixed heap buffer overflow in #method_missing
When `ci->n == CALL_MAXARGS`, the correct value is `argv[1] = argv[1]`.
However, it was always `args[1] = args[ci->n]`, which caused objects outside the range to be picked up.

fixed #6584
2025-07-30 21:35:55 +09:00
119 changed files with 3867 additions and 3247 deletions
+18
View File
@@ -5,11 +5,29 @@ updates:
directory: "/" directory: "/"
schedule: schedule:
interval: "daily" interval: "daily"
groups:
bundler-dependencies:
patterns:
- "*"
cooldown: cooldown:
default-days: 7 default-days: 7
- package-ecosystem: "github-actions" - package-ecosystem: "github-actions"
directory: "/" directory: "/"
schedule: schedule:
interval: "daily" interval: "daily"
groups:
github-actions-dependencies:
patterns:
- "*"
cooldown:
default-days: 7
- package-ecosystem: "pre-commit"
directory: "/"
schedule:
interval: "daily"
groups:
pre-commit-hooks:
patterns:
- "*"
cooldown: cooldown:
default-days: 7 default-days: 7
-26
View File
@@ -1,26 +0,0 @@
{
"retryOn429": true,
"retryCount": 3,
"aliveStatusCodes": [
200,
206,
502
],
"ignorePatterns": [
{
"pattern": "^https://github.com/mruby/mruby/commit/"
},
{
"pattern": "^http://jp.rubyist.net/magazine/\\?0034-Enumerable_lz"
},
{
"pattern": "^https://ruby-doc.org/core-2.3.3"
},
{
"pattern": "^mailto:"
},
{
"pattern": "^https://www.iso.org/"
}
]
}
+10 -4
View File
@@ -31,7 +31,9 @@ jobs:
LD: ${{ matrix.cc }} LD: ${{ matrix.cc }}
steps: steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Ruby version - name: Ruby version
run: ruby -v run: ruby -v
- name: Compiler version - name: Compiler version
@@ -44,11 +46,13 @@ jobs:
timeout-minutes: 15 timeout-minutes: 15
steps: steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Ruby version - name: Ruby version
run: ruby -v run: ruby -v
- name: Cache cosmocc - name: Cache cosmocc
uses: actions/cache@v5 uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
id: cache-cosmocc id: cache-cosmocc
with: with:
path: ~/cosmo path: ~/cosmo
@@ -70,7 +74,9 @@ jobs:
MRUBY_CONFIG: ci/msvc MRUBY_CONFIG: ci/msvc
steps: steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Ruby version - name: Ruby version
run: ruby -v run: ruby -v
- name: Build and test - name: Build and test
+3 -1
View File
@@ -18,7 +18,9 @@ jobs:
language: ["actions"] language: ["actions"]
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v6 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v4 uses: github/codeql-action/init@v4
with: with:
+7 -2
View File
@@ -2,6 +2,9 @@ name: Coverage
on: [push] on: [push]
permissions:
contents: read
jobs: jobs:
coverage: coverage:
name: Coverage name: Coverage
@@ -16,7 +19,9 @@ jobs:
LDFLAGS: --coverage LDFLAGS: --coverage
steps: steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Ruby version - name: Ruby version
run: ruby -v run: ruby -v
- name: Compiler version - name: Compiler version
@@ -34,7 +39,7 @@ jobs:
echo \`\`\` echo \`\`\`
} > "$GITHUB_STEP_SUMMARY" } > "$GITHUB_STEP_SUMMARY"
- name: Upload coverage report - name: Upload coverage report
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
name: coverage-${{ github.sha }} name: coverage-${{ github.sha }}
path: coverage/ path: coverage/
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
pull-requests: write pull-requests: write
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/labeler@v6 - uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1
with: with:
repo-token: "${{ secrets.GITHUB_TOKEN }}" repo-token: "${{ secrets.GITHUB_TOKEN }}"
sync-labels: true sync-labels: true
+4 -2
View File
@@ -11,7 +11,9 @@ jobs:
name: Run ls-lint name: Run ls-lint
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ls-lint/action@v2.3.1 with:
persist-credentials: false
- uses: ls-lint/action@02e380fe8733d499cbfc9e22276de5085508a5bd # v2.3.1
with: with:
config: .github/linters/.ls-lint.yml config: .github/linters/.ls-lint.yml
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
fuzz-seconds: 600 fuzz-seconds: 600
dry-run: false dry-run: false
- name: Upload Crash - name: Upload Crash
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: failure() if: failure()
with: with:
name: artifacts name: artifacts
+22
View File
@@ -0,0 +1,22 @@
# https://github.com/j178/prek
name: Manual hooks
on: [pull_request]
permissions:
contents: read
jobs:
pre-commit:
name: Run pre-commit
runs-on: ubuntu-latest
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: j178/prek-action@53276d8b0d10f8b6672aa85b4588c6921d0370cc # v2.0.1
with:
install-only: true
- name: Run manual pre-commit hooks
run: prek run --color=always --all-files --hook-stage manual
+4 -4
View File
@@ -12,9 +12,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: j178/prek-action@v1 with:
persist-credentials: false
- uses: j178/prek-action@53276d8b0d10f8b6672aa85b4588c6921d0370cc # v2.0.1
with: with:
extra-args: --all-files extra-args: --all-files
- name: Run manual pre-commit hooks
run: prek run --color=always --all-files --hook-stage manual
+3 -1
View File
@@ -19,7 +19,9 @@ jobs:
fail-fast: false fail-fast: false
steps: steps:
- name: "Checkout ${{ github.ref_name }} ( ${{ github.sha }} )" - name: "Checkout ${{ github.ref_name }} ( ${{ github.sha }} )"
uses: actions/checkout@v6 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Builds - name: Builds
id: builds id: builds
run: | run: |
+3 -2
View File
@@ -15,12 +15,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )" - name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v6 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
# Full git history is needed to get a proper list of changed files within `super-linter` # Full git history is needed to get a proper list of changed files within `super-linter`
fetch-depth: 0 fetch-depth: 0
persist-credentials: false
- name: Lint Code Base - name: Lint Code Base
uses: super-linter/super-linter/slim@v8.5.0 uses: super-linter/super-linter/slim@9e863354e3ff62e0727d37183162c4a88873df41 # v8.6.0
env: env:
# VALIDATE_BASH_EXEC: true # VALIDATE_BASH_EXEC: true
VALIDATE_DOCKERFILE_HADOLINT: true VALIDATE_DOCKERFILE_HADOLINT: true
+12 -24
View File
@@ -3,7 +3,7 @@
default_stages: [pre-commit, pre-push] default_stages: [pre-commit, pre-push]
default_language_version: default_language_version:
python: python3 python: python3
node: 24.11.1 node: 24.14.0
minimum_pre_commit_version: "3.2.0" minimum_pre_commit_version: "3.2.0"
exclude: "^tools/lrama/" exclude: "^tools/lrama/"
repos: repos:
@@ -20,10 +20,11 @@ repos:
- id: prettier - id: prettier
name: run prettier name: run prettier
description: format files with prettier description: format files with prettier
entry: prettier --write '**/*.json' '**/*.md' '**/*.yaml' '**/*.yml' entry: prettier --write '**/*.md' '**/*.yaml' '**/*.yml'
files: \.(json|md|ya?ml)$ files: \.(md|ya?ml)$
language: node language: node
additional_dependencies: ["prettier@3.7.4"] additional_dependencies: ["prettier@3.7.4"]
pass_filenames: false
stages: [manual] stages: [manual]
- id: check-zip-file-is-not-committed - id: check-zip-file-is-not-committed
name: disallow zip files name: disallow zip files
@@ -34,13 +35,13 @@ repos:
track and have security implications. Please remove the zip file from the repository. track and have security implications. Please remove the zip file from the repository.
files: \.zip$ files: \.zip$
- repo: https://github.com/gitleaks/gitleaks - repo: https://github.com/gitleaks/gitleaks
rev: v8.30.0 rev: v8.30.1
hooks: hooks:
- id: gitleaks - id: gitleaks
name: run gitleaks name: run gitleaks
description: detect hardcoded secrets with gitleaks description: detect hardcoded secrets with gitleaks
- repo: https://github.com/oxipng/oxipng - repo: https://github.com/oxipng/oxipng
rev: v10.0.0 rev: v10.1.0
hooks: hooks:
- id: oxipng - id: oxipng
name: run oxipng name: run oxipng
@@ -55,9 +56,6 @@ repos:
- id: check-executables-have-shebangs - id: check-executables-have-shebangs
exclude: ^test/t/lang\.rb$ exclude: ^test/t/lang\.rb$
- id: check-illegal-windows-names - id: check-illegal-windows-names
- id: pretty-format-json
args: [--autofix, --no-sort-keys]
- id: check-json
- id: check-merge-conflict - id: check-merge-conflict
- id: check-shebang-scripts-are-executable - id: check-shebang-scripts-are-executable
- id: check-vcs-permalinks - id: check-vcs-permalinks
@@ -75,7 +73,7 @@ repos:
- id: mixed-line-ending - id: mixed-line-ending
- id: trailing-whitespace - id: trailing-whitespace
- repo: https://github.com/Lucas-C/pre-commit-hooks - repo: https://github.com/Lucas-C/pre-commit-hooks
rev: v1.5.5 rev: v1.5.6
hooks: hooks:
- id: forbid-tabs - id: forbid-tabs
name: run no-tabs checker name: run no-tabs checker
@@ -87,19 +85,19 @@ repos:
args: [--whitespaces-count, "2"] args: [--whitespaces-count, "2"]
exclude: Makefile$ exclude: Makefile$
- repo: https://github.com/rhysd/actionlint - repo: https://github.com/rhysd/actionlint
rev: v1.7.9 rev: v1.7.12
hooks: hooks:
- id: actionlint - id: actionlint
name: run actionlint name: run actionlint
description: lint GitHub Actions workflow files description: lint GitHub Actions workflow files
- repo: https://github.com/codespell-project/codespell - repo: https://github.com/codespell-project/codespell
rev: v2.4.1 rev: v2.4.2
hooks: hooks:
- id: codespell - id: codespell
name: run codespell name: run codespell
description: check spelling with codespell description: check spelling with codespell
- repo: https://github.com/igorshubovych/markdownlint-cli - repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.46.0 rev: v0.48.0
hooks: hooks:
- id: markdownlint - id: markdownlint
name: run markdownlint name: run markdownlint
@@ -107,18 +105,8 @@ repos:
args: [--config=.github/linters/.markdown-lint.yml] args: [--config=.github/linters/.markdown-lint.yml]
types: [markdown] types: [markdown]
files: \.md$ files: \.md$
- repo: https://github.com/tcort/markdown-link-check
rev: v3.14.2
hooks:
- id: markdown-link-check
name: run markdown-link-check
description: checks hyperlinks in Markdown files
args: [--config=.github/linters/mlc_config.json, -q]
stages: [manual]
types: [markdown]
files: \.md$
- repo: https://github.com/rubocop/rubocop - repo: https://github.com/rubocop/rubocop
rev: v1.81.7 rev: v1.86.0
hooks: hooks:
- id: rubocop - id: rubocop
name: run rubocop name: run rubocop
@@ -132,7 +120,7 @@ repos:
name: run shellcheck name: run shellcheck
description: check shell scripts with a static analysis tool description: check shell scripts with a static analysis tool
- repo: https://github.com/adrienverge/yamllint - repo: https://github.com/adrienverge/yamllint
rev: v1.37.1 rev: v1.38.0
hooks: hooks:
- id: yamllint - id: yamllint
name: run yamllint name: run yamllint
+1
View File
@@ -3,3 +3,4 @@ build
coverage coverage
doc/internal/opcode.md doc/internal/opcode.md
tools/lrama tools/lrama
.venv
+1 -1
View File
@@ -48,7 +48,7 @@ PROJECT_NAME = mruby
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = 3.4.0 PROJECT_NUMBER = 4.0.0
# Using the PROJECT_BRIEF tag one can provide an optional one line description # 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 # for a project that appears at the top of each page and should give viewer a
+44
View File
@@ -23,6 +23,8 @@ mruby now supports pattern matching (case/in) syntax:
- Trailing comma in method definition parameters: `def foo(a, b,)` ([f78334b](https://github.com/mruby/mruby/commit/f78334b)) - Trailing comma in method definition parameters: `def foo(a, b,)` ([f78334b](https://github.com/mruby/mruby/commit/f78334b))
- Array/Hash/String subclasses can now override `[]` and `[]=` methods ([#6675](https://github.com/mruby/mruby/pull/6675)) - Array/Hash/String subclasses can now override `[]` and `[]=` methods ([#6675](https://github.com/mruby/mruby/pull/6675))
- `OP_SETIDX` optimization for Array and Hash ([ddd8fe1](https://github.com/mruby/mruby/commit/ddd8fe1)) - `OP_SETIDX` optimization for Array and Hash ([ddd8fe1](https://github.com/mruby/mruby/commit/ddd8fe1))
- `case`/`in` without `else` now raises `NoMatchingPatternError` ([d8de35b](https://github.com/mruby/mruby/commit/d8de35b))
- Allow compound statement in parenthesized argument context ([919cbd8](https://github.com/mruby/mruby/commit/919cbd8))
# Changes in C API # Changes in C API
@@ -37,6 +39,8 @@ mruby now supports pattern matching (case/in) syntax:
- `mrb_open()` returns mrb_state with exc set on init failure ([05ffe0c](https://github.com/mruby/mruby/commit/05ffe0c)) - `mrb_open()` returns mrb_state with exc set on init failure ([05ffe0c](https://github.com/mruby/mruby/commit/05ffe0c))
- `mrb_utf8_to_buf()` for UTF-8 encoding consolidation ([7e28e68](https://github.com/mruby/mruby/commit/7e28e68)) - `mrb_utf8_to_buf()` for UTF-8 encoding consolidation ([7e28e68](https://github.com/mruby/mruby/commit/7e28e68))
- `kh_is_end()` macro for safe khash iteration ([893cc75](https://github.com/mruby/mruby/commit/893cc75)) - `kh_is_end()` macro for safe khash iteration ([893cc75](https://github.com/mruby/mruby/commit/893cc75))
- `mrb_bigint_p()` always defined regardless of bigint gem presence ([6c4a8c0](https://github.com/mruby/mruby/commit/6c4a8c0))
- `RInteger` and `RFloat` added to `RVALUE` union ([13dbca0](https://github.com/mruby/mruby/commit/13dbca0))
# ROM Method Tables # ROM Method Tables
@@ -76,6 +80,7 @@ mruby-symbol-ext, mruby-range-ext, mruby-object-ext.
- Emscripten: use native WASM exception handling ([ca364e3](https://github.com/mruby/mruby/commit/ca364e3)) - Emscripten: use native WASM exception handling ([ca364e3](https://github.com/mruby/mruby/commit/ca364e3))
- HAL (Hardware Abstraction Layer) for platform abstraction in mruby-io, mruby-socket, mruby-dir, mruby-task ([74ca22f](https://github.com/mruby/mruby/commit/74ca22f)) - HAL (Hardware Abstraction Layer) for platform abstraction in mruby-io, mruby-socket, mruby-dir, mruby-task ([74ca22f](https://github.com/mruby/mruby/commit/74ca22f))
- `MRUBY_MIRB_READLINE` environment variable to control readline library selection ([0aafb83](https://github.com/mruby/mruby/commit/0aafb83)) - `MRUBY_MIRB_READLINE` environment variable to control readline library selection ([0aafb83](https://github.com/mruby/mruby/commit/0aafb83))
- MSYS2 drive letter support in build script ([77f6ffe](https://github.com/mruby/mruby/commit/77f6ffe))
- Inter-gem headers separated from external API headers ([#6671](https://github.com/mruby/mruby/pull/6671)) - Inter-gem headers separated from external API headers ([#6671](https://github.com/mruby/mruby/pull/6671))
# Changes in mrbgems # Changes in mrbgems
@@ -110,6 +115,7 @@ mruby-symbol-ext, mruby-range-ext, mruby-object-ext.
## Other Gem Changes ## Other Gem Changes
- **_NOTE_**: `Hash#deconstruct_keys` removed for CRuby compatibility ([34b9412](https://github.com/mruby/mruby/commit/34b9412)) - **_NOTE_**: `Hash#deconstruct_keys` removed for CRuby compatibility ([34b9412](https://github.com/mruby/mruby/commit/34b9412))
- **mruby-enum-lazy**: Fix `Lazy#flat_map` to handle non-enumerable block return values ([#6765](https://github.com/mruby/mruby/pull/6765))
- **mruby-array-ext**: Add `Array#find` and `Array#rfind` methods - **mruby-array-ext**: Add `Array#find` and `Array#rfind` methods
- **mruby-io**: Add `IO#putc` and `Kernel#putc` ([baff6e6](https://github.com/mruby/mruby/commit/baff6e6)) - **mruby-io**: Add `IO#putc` and `Kernel#putc` ([baff6e6](https://github.com/mruby/mruby/commit/baff6e6))
- **mruby-random**: Replace xoshiro with PCG for better memory efficiency ([f1bab01](https://github.com/mruby/mruby/commit/f1bab01)) - **mruby-random**: Replace xoshiro with PCG for better memory efficiency ([f1bab01](https://github.com/mruby/mruby/commit/f1bab01))
@@ -125,6 +131,8 @@ mruby-symbol-ext, mruby-range-ext, mruby-object-ext.
- Optimized masgn to generate literals directly into target registers ([fb5d966](https://github.com/mruby/mruby/commit/fb5d966)) - Optimized masgn to generate literals directly into target registers ([fb5d966](https://github.com/mruby/mruby/commit/fb5d966))
- Optimized splat of literal arrays in args/literals ([1cb8d73](https://github.com/mruby/mruby/commit/1cb8d73)) - Optimized splat of literal arrays in args/literals ([1cb8d73](https://github.com/mruby/mruby/commit/1cb8d73))
- Early termination after too many parse errors ([510ebd7](https://github.com/mruby/mruby/commit/510ebd7)) - Early termination after too many parse errors ([510ebd7](https://github.com/mruby/mruby/commit/510ebd7))
- Chunk array literals at 64 elements to reduce register pressure ([f98d641](https://github.com/mruby/mruby/commit/f98d641))
- Chunk `%w()` and `%i()` literals to reduce register pressure ([62cf0dc](https://github.com/mruby/mruby/commit/62cf0dc))
# VM Optimizations # VM Optimizations
@@ -185,6 +193,10 @@ Other optimizations:
- [#6705](https://github.com/mruby/mruby/issues/6705) Can't get outer class of an object in C - [#6705](https://github.com/mruby/mruby/issues/6705) Can't get outer class of an object in C
- [#6713](https://github.com/mruby/mruby/issues/6713) mruby-polarssl not work - [#6713](https://github.com/mruby/mruby/issues/6713) mruby-polarssl not work
- [#6720](https://github.com/mruby/mruby/issues/6720) Random float range: different behavior from CRuby - [#6720](https://github.com/mruby/mruby/issues/6720) Random float range: different behavior from CRuby
- [#6722](https://github.com/mruby/mruby/issues/6722) RBreak size overflow on 32-bit platforms with MRB_NO_BOXING
- [#6740](https://github.com/mruby/mruby/issues/6740) `%w()`/`%i()` register pressure with large literals
- [#6741](https://github.com/mruby/mruby/issues/6741) `case`/`in` without `else` should raise `NoMatchingPatternError`
- [#6760](https://github.com/mruby/mruby/issues/6760) `mrb_gc_unregister()` not removing all matching entries
# Merged Pull Requests # Merged Pull Requests
@@ -260,6 +272,7 @@ Other optimizations:
- [#6589](https://github.com/mruby/mruby/pull/6589) Add pre-commit hook `check-zip-file-is-not-committed` - [#6589](https://github.com/mruby/mruby/pull/6589) Add pre-commit hook `check-zip-file-is-not-committed`
- [#6591](https://github.com/mruby/mruby/pull/6591) mruby-eval fix license link in README - [#6591](https://github.com/mruby/mruby/pull/6591) mruby-eval fix license link in README
- [#6593](https://github.com/mruby/mruby/pull/6593) README: Add Contributors Avatars, Star History, Table of Contents - [#6593](https://github.com/mruby/mruby/pull/6593) README: Add Contributors Avatars, Star History, Table of Contents
- [#6598](https://github.com/mruby/mruby/pull/6598) Fix heap buffer overflow in `#method_missing`
- [#6599](https://github.com/mruby/mruby/pull/6599) pre-commit: run `markdown-link-check`, `oxipng`, `prettier` manually - [#6599](https://github.com/mruby/mruby/pull/6599) pre-commit: run `markdown-link-check`, `oxipng`, `prettier` manually
- [#6600](https://github.com/mruby/mruby/pull/6600) `dreamcast_shelf build config`: update to use KallistiOS wrappers - [#6600](https://github.com/mruby/mruby/pull/6600) `dreamcast_shelf build config`: update to use KallistiOS wrappers
- [#6601](https://github.com/mruby/mruby/pull/6601) fix: skip local build_config.rb when working in MRUBY_ROOT - [#6601](https://github.com/mruby/mruby/pull/6601) fix: skip local build_config.rb when working in MRUBY_ROOT
@@ -303,6 +316,33 @@ Other optimizations:
- [#6716](https://github.com/mruby/mruby/pull/6716) Fixes identity for proc object - [#6716](https://github.com/mruby/mruby/pull/6716) Fixes identity for proc object
- [#6717](https://github.com/mruby/mruby/pull/6717) Fix mruby-task: wrapping by critical section and setting initial task receiver - [#6717](https://github.com/mruby/mruby/pull/6717) Fix mruby-task: wrapping by critical section and setting initial task receiver
- [#6718](https://github.com/mruby/mruby/pull/6718) Add installation instructions for conda and Homebrew - [#6718](https://github.com/mruby/mruby/pull/6718) Add installation instructions for conda and Homebrew
- [#6723](https://github.com/mruby/mruby/pull/6723) Add `RInteger` and `RFloat` to `RVALUE`
- [#6727](https://github.com/mruby/mruby/pull/6727) Language documentation: update wording of "overloading" section
- [#6729](https://github.com/mruby/mruby/pull/6729) Simplifying dependency addition for gensym task
- [#6730](https://github.com/mruby/mruby/pull/6730) Simplifying presym file generation actions
- [#6733](https://github.com/mruby/mruby/pull/6733) Include `mruby/presym.h` for all source files
- [#6734](https://github.com/mruby/mruby/pull/6734) Chunk array literals at 64 elements to reduce register pressure
- [#6735](https://github.com/mruby/mruby/pull/6735) Prevent full recompilation without changes to presym file
- [#6739](https://github.com/mruby/mruby/pull/6739) Fix MSYS2 build error with drive letters
- [#6743](https://github.com/mruby/mruby/pull/6743) Chunk `%w()` and `%i()` literals to reduce register pressure
- [#6744](https://github.com/mruby/mruby/pull/6744) Raise `NoMatchingPatternError` in `case`/`in` without `else`
- [#6747](https://github.com/mruby/mruby/pull/6747) Correctly handle empty hash as default named argument
- [#6749](https://github.com/mruby/mruby/pull/6749) Fix microcontroller profile
- [#6750](https://github.com/mruby/mruby/pull/6750) Fix out-of-bounds read and divide-by-zero in `Array#product`
- [#6752](https://github.com/mruby/mruby/pull/6752) Fix `attr_reader`-generated methods accepting extra arguments
- [#6753](https://github.com/mruby/mruby/pull/6753) Further optimize `Array#product`
- [#6754](https://github.com/mruby/mruby/pull/6754) Mark `attr_reader` procs as noarg
- [#6755](https://github.com/mruby/mruby/pull/6755) Reload `ci` after `mrb_hash_delete_key()` in keyword argument handling
- [#6756](https://github.com/mruby/mruby/pull/6756) Avoid impact of object modifications caused by `mrb_vm_exec()` calls
- [#6758](https://github.com/mruby/mruby/pull/6758) Don't assign result of `mrb_funcall()` directly to `regs`
- [#6759](https://github.com/mruby/mruby/pull/6759) Define `mrb_bigint_p()` always
- [#6761](https://github.com/mruby/mruby/pull/6761) Fix `mrb_gc_unregister()` to remove all matching entries
- [#6762](https://github.com/mruby/mruby/pull/6762) Write generated test C files atomically to avoid build race condition
- [#6765](https://github.com/mruby/mruby/pull/6765) Fix `Lazy#flat_map` to handle non-enumerable block return values
- [#6767](https://github.com/mruby/mruby/pull/6767) Allow compound statement in parenthesized argument context
- [#6780](https://github.com/mruby/mruby/pull/6780) Fix `String#prepend` with self-referencing arguments
- [#6781](https://github.com/mruby/mruby/pull/6781) Protect `sprintf` format string from mutation during callbacks
- [#6783](https://github.com/mruby/mruby/pull/6783) Pin GitHub Actions workflows to commit hashes
# Security Fixes # Security Fixes
@@ -320,4 +360,8 @@ Other optimizations:
- Heap-use-after-free in insertion_sort ([099d2c47](https://github.com/mruby/mruby/commit/099d2c47)) - Heap-use-after-free in insertion_sort ([099d2c47](https://github.com/mruby/mruby/commit/099d2c47))
- Integer overflow in str_check_length ([6afff1c3](https://github.com/mruby/mruby/commit/6afff1c3)) - Integer overflow in str_check_length ([6afff1c3](https://github.com/mruby/mruby/commit/6afff1c3))
- Integer overflow in Integer#lcm ([070bef24](https://github.com/mruby/mruby/commit/070bef24)) - Integer overflow in Integer#lcm ([070bef24](https://github.com/mruby/mruby/commit/070bef24))
- Heap buffer overflow in `#method_missing` ([550d10a](https://github.com/mruby/mruby/commit/550d10a))
- Out-of-bounds read and divide-by-zero in `Array#product` ([8441eaf](https://github.com/mruby/mruby/commit/8441eaf))
- Heap buffer overflow in `String#prepend` with self-referencing arguments ([18ba026](https://github.com/mruby/mruby/commit/18ba026))
- Use-after-free in `sprintf` via `to_s` callback mutating format string ([48fc422](https://github.com/mruby/mruby/commit/48fc422))
- Multiple memory leak fixes in bigint, Set, Array, and Task gems - Multiple memory leak fixes in bigint, Set, Array, and Task gems
+1 -1
View File
@@ -51,7 +51,7 @@ To get mruby, you can download the stable version 4.0.0 from the official mruby
GitHub repository or clone the trunk of the mruby source tree with the "git 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), [rvm](https://github.com/rvm/rvm), [conda](https://anaconda.org/channels/conda-forge/packages/mruby/overview) or [Homebrew](https://formulae.brew.sh/formula/mruby). 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), [rvm](https://github.com/rvm/rvm), [conda](https://anaconda.org/channels/conda-forge/packages/mruby/overview) or [Homebrew](https://formulae.brew.sh/formula/mruby).
The release candidate version 4.0.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/4.0.0-rc.zip](https://github.com/mruby/mruby/archive/4.0.0-rc.zip) The release candidate version 4.0.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/4.0.0-rc3.zip](https://github.com/mruby/mruby/archive/4.0.0-rc3.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 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)
+1 -1
View File
@@ -30,7 +30,7 @@ MRuby::CrossBuild.new("ArduinoDue") do |conf|
#configuration for low memory environment #configuration for low memory environment
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64) cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
cc.defines << %w(KHASH_DEFAULT_SIZE=8) cc.defines << %w(KHASH_INITIAL_SIZE=8)
cc.defines << %w(MRB_GC_STRESS) cc.defines << %w(MRB_GC_STRESS)
#cc.defines << %w(MRB_NO_STDIO) #if you don't need stdio. #cc.defines << %w(MRB_NO_STDIO) #if you don't need stdio.
#cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval #cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval
+1 -1
View File
@@ -16,7 +16,7 @@ MRuby::CrossBuild.new("RX630") do |conf|
#configuration for low memory environment #configuration for low memory environment
cc.defines << %w(MRB_USE_FLOAT32) cc.defines << %w(MRB_USE_FLOAT32)
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64) cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
cc.defines << %w(KHASH_DEFAULT_SIZE=8) cc.defines << %w(KHASH_INITIAL_SIZE=8)
cc.defines << %w(MRB_GC_STRESS) cc.defines << %w(MRB_GC_STRESS)
cc.defines << %w(MRB_NO_STDIO) #if you don't need stdio. cc.defines << %w(MRB_NO_STDIO) #if you don't need stdio.
#cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval #cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval
+1 -1
View File
@@ -27,7 +27,7 @@ MRuby::CrossBuild.new("chipKITMax32") do |conf|
#configuration for low memory environment #configuration for low memory environment
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64) cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
cc.defines << %w(KHASH_DEFAULT_SIZE=8) cc.defines << %w(KHASH_INITIAL_SIZE=8)
cc.defines << %w(MRB_GC_STRESS) cc.defines << %w(MRB_GC_STRESS)
#cc.defines << %w(MRB_NO_STDIO) #if you don't need stdio. #cc.defines << %w(MRB_NO_STDIO) #if you don't need stdio.
#cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval #cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval
+30 -30
View File
@@ -4,44 +4,44 @@
New to mruby? Start here: New to mruby? Start here:
| Document | Description | | Document | Description |
| -------- | ----------- | | -------------------------------------------- | -------------------------------------- |
| [Getting Started](guides/getting-started.md) | Build mruby and run your first program | | [Getting Started](guides/getting-started.md) | Build mruby and run your first program |
| [Language Features](guides/language.md) | Ruby subset supported by mruby | | [Language Features](guides/language.md) | Ruby subset supported by mruby |
| [Limitations](limitations.md) | Behavioral differences from CRuby | | [Limitations](limitations.md) | Behavioral differences from CRuby |
## Guides (for embedders and gem authors) ## Guides (for embedders and gem authors)
### Embedding mruby in C ### Embedding mruby in C
| Document | Description | | Document | Description |
| -------- | ----------- | | --------------------------------------- | ------------------------------------------------ |
| [C API Reference](guides/capi.md) | Values, classes, methods, error handling, fibers | | [C API Reference](guides/capi.md) | Values, classes, methods, error handling, fibers |
| [GC Arena](guides/gc-arena-howto.md) | Managing temporary objects in C extensions | | [GC Arena](guides/gc-arena-howto.md) | Managing temporary objects in C extensions |
| [Linking](guides/link.md) | Linking with `libmruby` | | [Linking](guides/link.md) | Linking with `libmruby` |
| [Amalgamation](guides/amalgamation.md) | Single-file build for easy integration | | [Amalgamation](guides/amalgamation.md) | Single-file build for easy integration |
| [Precompiled Symbols](guides/symbol.md) | Compile-time symbol allocation | | [Precompiled Symbols](guides/symbol.md) | Compile-time symbol allocation |
### Building and Configuring ### Building and Configuring
| Document | Description | | Document | Description |
| -------- | ----------- | | ---------------------------------------- | ------------------------------------------- |
| [Compilation](guides/compile.md) | Build system, cross-compilation, toolchains | | [Compilation](guides/compile.md) | Build system, cross-compilation, toolchains |
| [Build Configuration](guides/mrbconf.md) | Compile-time macros (`MRB_*` flags) | | [Build Configuration](guides/mrbconf.md) | Compile-time macros (`MRB_*` flags) |
| [mrbgems](guides/mrbgems.md) | Creating and managing gems | | [mrbgems](guides/mrbgems.md) | Creating and managing gems |
| [Memory](guides/memory.md) | Allocator customization and heap regions | | [Memory](guides/memory.md) | Allocator customization and heap regions |
### Tools ### Tools
| Document | Description | | Document | Description |
| -------- | ----------- | | ----------------------------------------------- | ----------------------------------------------- |
| [Debugger](guides/debugger.md) | Using `mrdb` for debugging | | [Debugger](guides/debugger.md) | Using `mrdb` for debugging |
| [ROM Method Tables](guides/rom-method-table.md) | Read-only method tables for constrained devices | | [ROM Method Tables](guides/rom-method-table.md) | Read-only method tables for constrained devices |
### Reference ### Reference
| Document | Description | | Document | Description |
| -------- | ----------- | | ------------------------------------- | ------------------ |
| [Directory Structure](guides/hier.md) | Source tree layout | | [Directory Structure](guides/hier.md) | Source tree layout |
## Internals (for mruby contributors) ## Internals (for mruby contributors)
@@ -49,14 +49,14 @@ New to mruby? Start here:
Start with [Architecture](internal/architecture.md) for an overview, Start with [Architecture](internal/architecture.md) for an overview,
then dive into the subsystem you need: then dive into the subsystem you need:
| Document | Description | | Document | Description |
| -------- | ----------- | | ----------------------------------------- | -------------------------------------------------- |
| [Architecture](internal/architecture.md) | Overview of object model, VM, GC, compiler | | [Architecture](internal/architecture.md) | Overview of object model, VM, GC, compiler |
| [Virtual Machine](internal/vm.md) | Dispatch loop, call frames, method lookup, fibers | | [Virtual Machine](internal/vm.md) | Dispatch loop, call frames, method lookup, fibers |
| [Garbage Collector](internal/gc.md) | Tri-color marking, write barriers, generational GC | | [Garbage Collector](internal/gc.md) | Tri-color marking, write barriers, generational GC |
| [Compiler Pipeline](internal/compiler.md) | Parser, code generator, IRep, binary format | | [Compiler Pipeline](internal/compiler.md) | Parser, code generator, IRep, binary format |
| [Opcodes](internal/opcode.md) | VM instruction set reference | | [Opcodes](internal/opcode.md) | VM instruction set reference |
| [Value Boxing](internal/boxing.md) | How `mrb_value` encodes types | | [Value Boxing](internal/boxing.md) | How `mrb_value` encodes types |
## Release Notes ## Release Notes
+68 -68
View File
@@ -99,23 +99,23 @@ mrb_str_to_cstr(mrb, v) /* const char* from String value */
### Value Types ### Value Types
| `mrb_vtype` | Ruby Class | Notes | | `mrb_vtype` | Ruby Class | Notes |
| ----------- | ---------- | ----- | | ------------------ | ------------------- | ------------------------ |
| `MRB_TT_FALSE` | FalseClass/NilClass | `nil` has `MRB_TT_FALSE` | | `MRB_TT_FALSE` | FalseClass/NilClass | `nil` has `MRB_TT_FALSE` |
| `MRB_TT_TRUE` | TrueClass | | | `MRB_TT_TRUE` | TrueClass | |
| `MRB_TT_INTEGER` | Integer | Immediate value | | `MRB_TT_INTEGER` | Integer | Immediate value |
| `MRB_TT_FLOAT` | Float | May be immediate | | `MRB_TT_FLOAT` | Float | May be immediate |
| `MRB_TT_SYMBOL` | Symbol | Immediate value | | `MRB_TT_SYMBOL` | Symbol | Immediate value |
| `MRB_TT_STRING` | String | Heap object | | `MRB_TT_STRING` | String | Heap object |
| `MRB_TT_ARRAY` | Array | Heap object | | `MRB_TT_ARRAY` | Array | Heap object |
| `MRB_TT_HASH` | Hash | Heap object | | `MRB_TT_HASH` | Hash | Heap object |
| `MRB_TT_OBJECT` | Object | User-defined classes | | `MRB_TT_OBJECT` | Object | User-defined classes |
| `MRB_TT_CLASS` | Class | | | `MRB_TT_CLASS` | Class | |
| `MRB_TT_MODULE` | Module | | | `MRB_TT_MODULE` | Module | |
| `MRB_TT_PROC` | Proc | | | `MRB_TT_PROC` | Proc | |
| `MRB_TT_CDATA` | (C data) | Wrapped C structs | | `MRB_TT_CDATA` | (C data) | Wrapped C structs |
| `MRB_TT_EXCEPTION` | Exception | | | `MRB_TT_EXCEPTION` | Exception | |
| `MRB_TT_FIBER` | Fiber | | | `MRB_TT_FIBER` | Fiber | |
## Defining Classes and Modules ## Defining Classes and Modules
@@ -165,15 +165,15 @@ mrb_define_module_function(mrb, mod, "name", my_method, MRB_ARGS_ANY());
### Argument Specifiers ### Argument Specifiers
| Macro | Meaning | | Macro | Meaning |
| ----- | ------- | | ---------------------- | ------------------------------------- |
| `MRB_ARGS_NONE()` | No arguments | | `MRB_ARGS_NONE()` | No arguments |
| `MRB_ARGS_REQ(n)` | `n` required arguments | | `MRB_ARGS_REQ(n)` | `n` required arguments |
| `MRB_ARGS_OPT(n)` | `n` optional arguments | | `MRB_ARGS_OPT(n)` | `n` optional arguments |
| `MRB_ARGS_ARG(r,o)` | `r` required + `o` optional | | `MRB_ARGS_ARG(r,o)` | `r` required + `o` optional |
| `MRB_ARGS_REST()` | Splat (`*args`) | | `MRB_ARGS_REST()` | Splat (`*args`) |
| `MRB_ARGS_BLOCK()` | Block (`&block`) | | `MRB_ARGS_BLOCK()` | Block (`&block`) |
| `MRB_ARGS_ANY()` | Any number (same as REST) | | `MRB_ARGS_ANY()` | Any number (same as REST) |
| `MRB_ARGS_KEY(n,rest)` | `n` keyword args, `rest`=1 for `**kw` | | `MRB_ARGS_KEY(n,rest)` | `n` keyword args, `rest`=1 for `**kw` |
These can be combined with `|`: These can be combined with `|`:
@@ -192,27 +192,27 @@ mrb_int mrb_get_args(mrb_state *mrb, const char *format, ...);
### Format Specifiers ### Format Specifiers
| Spec | Ruby Type | C Type(s) | Notes | | Spec | Ruby Type | C Type(s) | Notes |
| ---- | --------- | --------- | ----- | | ---- | ------------- | --------------------------- | -------------------------------- |
| `o` | any | `mrb_value` | No type check | | `o` | any | `mrb_value` | No type check |
| `i` | Numeric | `mrb_int` | Coerces to integer | | `i` | Numeric | `mrb_int` | Coerces to integer |
| `f` | Numeric | `mrb_float` | Coerces to float | | `f` | Numeric | `mrb_float` | Coerces to float |
| `b` | any | `mrb_bool` | Truthiness | | `b` | any | `mrb_bool` | Truthiness |
| `n` | String/Symbol | `mrb_sym` | Converts to symbol | | `n` | String/Symbol | `mrb_sym` | Converts to symbol |
| `s` | String | `const char*, mrb_int` | Pointer + length | | `s` | String | `const char*, mrb_int` | Pointer + length |
| `z` | String | `const char*` | Null-terminated | | `z` | String | `const char*` | Null-terminated |
| `S` | String | `mrb_value` | String value | | `S` | String | `mrb_value` | String value |
| `A` | Array | `mrb_value` | Array value | | `A` | Array | `mrb_value` | Array value |
| `H` | Hash | `mrb_value` | Hash value | | `H` | Hash | `mrb_value` | Hash value |
| `C` | Class | `mrb_value` | Class/Module value | | `C` | Class | `mrb_value` | Class/Module value |
| `c` | Class | `struct RClass*` | Class pointer | | `c` | Class | `struct RClass*` | Class pointer |
| `a` | Array | `const mrb_value*, mrb_int` | Array pointer + length | | `a` | Array | `const mrb_value*, mrb_int` | Array pointer + length |
| `d` | C Data | `void*` | Requires `mrb_data_type*` | | `d` | C Data | `void*` | Requires `mrb_data_type*` |
| `&` | Block | `mrb_value` | Block argument | | `&` | Block | `mrb_value` | Block argument |
| `*` | rest | `const mrb_value*, mrb_int` | Rest arguments | | `*` | rest | `const mrb_value*, mrb_int` | Rest arguments |
| `\|` | — | — | Following args are optional | | `\|` | — | — | Following args are optional |
| `?` | — | `mrb_bool` | Was previous optional arg given? | | `?` | — | `mrb_bool` | Was previous optional arg given? |
| `:` | keywords | `mrb_kwargs` | Keyword arguments | | `:` | keywords | `mrb_kwargs` | Keyword arguments |
Adding `!` to `S`, `A`, `H`, `C`, `c`, `s`, `z`, `a`, `d` allows `nil` Adding `!` to `S`, `A`, `H`, `C`, `c`, `s`, `z`, `a`, `d` allows `nil`
(returns NULL/zero for nil). (returns NULL/zero for nil).
@@ -608,14 +608,14 @@ my_yield_method(mrb_state *mrb, mrb_value self)
### Fiber States ### Fiber States
| State | Meaning | | State | Meaning |
| ----- | ------- | | ----------------------- | -------------------------------- |
| `MRB_FIBER_CREATED` | Created but not yet resumed | | `MRB_FIBER_CREATED` | Created but not yet resumed |
| `MRB_FIBER_RUNNING` | Currently executing | | `MRB_FIBER_RUNNING` | Currently executing |
| `MRB_FIBER_RESUMED` | Resumed another fiber | | `MRB_FIBER_RESUMED` | Resumed another fiber |
| `MRB_FIBER_SUSPENDED` | Yielded, waiting to resume | | `MRB_FIBER_SUSPENDED` | Yielded, waiting to resume |
| `MRB_FIBER_TRANSFERRED` | Transferred via `Fiber#transfer` | | `MRB_FIBER_TRANSFERRED` | Transferred via `Fiber#transfer` |
| `MRB_FIBER_TERMINATED` | Finished execution | | `MRB_FIBER_TERMINATED` | Finished execution |
**Limitation:** fibers cannot yield across C function boundaries. **Limitation:** fibers cannot yield across C function boundaries.
You cannot call `mrb_fiber_yield` from within a C-implemented You cannot call `mrb_fiber_yield` from within a C-implemented
@@ -644,13 +644,13 @@ mrb_ccontext_free(mrb, cxt);
The `mrb_ccontext` structure provides several flags: The `mrb_ccontext` structure provides several flags:
| Field | Purpose | | Field | Purpose |
| ----- | ------- | | ---------------- | --------------------------------------- |
| `capture_errors` | Collect parse errors instead of raising | | `capture_errors` | Collect parse errors instead of raising |
| `no_exec` | Compile without executing (get RProc) | | `no_exec` | Compile without executing (get RProc) |
| `no_optimize` | Disable peephole optimizations | | `no_optimize` | Disable peephole optimizations |
| `no_ext_ops` | Disable extended operand instructions | | `no_ext_ops` | Disable extended operand instructions |
| `keep_lv` | Preserve local variables across loads | | `keep_lv` | Preserve local variables across loads |
### Loading with Context ### Loading with Context
@@ -843,14 +843,14 @@ $ build/host/bin/mruby-config --libs # libraries
Key macros that affect ABI: Key macros that affect ABI:
| Macro | Effect | | Macro | Effect |
| ----- | ------ | | ----------------- | ---------------------------------------- |
| `MRB_NO_BOXING` | Struct-based values (larger, debuggable) | | `MRB_NO_BOXING` | Struct-based values (larger, debuggable) |
| `MRB_WORD_BOXING` | Single-word values (fast, 32-bit safe) | | `MRB_WORD_BOXING` | Single-word values (fast, 32-bit safe) |
| `MRB_NAN_BOXING` | NaN-tagged values (default on 32-bit) | | `MRB_NAN_BOXING` | NaN-tagged values (default on 32-bit) |
| `MRB_NO_FLOAT` | Disable Float support | | `MRB_NO_FLOAT` | Disable Float support |
| `MRB_INT64` | 64-bit integers | | `MRB_INT64` | 64-bit integers |
| `MRB_USE_FLOAT32` | 32-bit floats | | `MRB_USE_FLOAT32` | 32-bit floats |
Mismatching these between library and application causes silent Mismatching these between library and application causes silent
data corruption. data corruption.
+1 -1
View File
@@ -40,7 +40,7 @@ To confirm mrdb was installed properly, run mrdb with the `--version` option:
```bash ```bash
$ mrdb --version $ mrdb --version
mruby 3.4.0 (2025-04-20) mruby 4.0.0 (2026-04-20)
``` ```
## 2.2 Basic Operation ## 2.2 Basic Operation
+89 -89
View File
@@ -205,11 +205,11 @@ mruby's numeric type sizes depend on the boxing mode and platform.
### Integer ### Integer
| Configuration | Range | | Configuration | Range |
| ------------- | ----- | | -------------------------------------- | ---------------- |
| 64-bit word boxing (default on 64-bit) | roughly +/- 2^62 | | 64-bit word boxing (default on 64-bit) | roughly +/- 2^62 |
| 32-bit word boxing (default on 32-bit) | roughly +/- 2^30 | | 32-bit word boxing (default on 32-bit) | roughly +/- 2^30 |
| NaN boxing (64-bit only) | -2^31 to 2^31-1 | | NaN boxing (64-bit only) | -2^31 to 2^31-1 |
Integer overflow raises a `RangeError` unless the `mruby-bigint` gem Integer overflow raises a `RangeError` unless the `mruby-bigint` gem
is included, in which case integers automatically promote to is included, in which case integers automatically promote to
@@ -235,32 +235,32 @@ With word boxing on 64-bit, many float values are stored inline
These classes are always available in mruby (no gem required): These classes are always available in mruby (no gem required):
| Class | Notes | | Class | Notes |
| ----- | ----- | | ------------- | -------------------------------------- |
| Object | Base class for all objects | | Object | Base class for all objects |
| Module | Module definition and mixin | | Module | Module definition and mixin |
| Class | Class definition and instantiation | | Class | Class definition and instantiation |
| NilClass | Singleton `nil` | | NilClass | Singleton `nil` |
| TrueClass | Singleton `true` | | TrueClass | Singleton `true` |
| FalseClass | Singleton `false` | | FalseClass | Singleton `false` |
| Integer | Fixed-precision integer | | Integer | Fixed-precision integer |
| Float | Floating-point (unless `MRB_NO_FLOAT`) | | Float | Floating-point (unless `MRB_NO_FLOAT`) |
| Symbol | Interned identifier | | Symbol | Interned identifier |
| String | Mutable byte string | | String | Mutable byte string |
| Array | Ordered collection | | Array | Ordered collection |
| Hash | Key-value mapping | | Hash | Key-value mapping |
| Range | Interval representation | | Range | Interval representation |
| Proc | Closure / callable object | | Proc | Closure / callable object |
| Exception | Exception hierarchy root | | Exception | Exception hierarchy root |
| StandardError | Common error base | | StandardError | Common error base |
### Core Modules ### Core Modules
| Module | Notes | | Module | Notes |
| ------ | ----- | | ---------- | ----------------------------------------- |
| Kernel | Core methods (`puts`, `p`, `raise`, etc.) | | Kernel | Core methods (`puts`, `p`, `raise`, etc.) |
| Comparable | Comparison operators via `<=>` | | Comparable | Comparison operators via `<=>` |
| Enumerable | Collection iteration methods | | Enumerable | Collection iteration methods |
## Standard Library (via gemboxes) ## Standard Library (via gemboxes)
@@ -270,70 +270,70 @@ gembox provides the class or feature you need:
### Classes and Modules ### Classes and Modules
| Class/Module | Gembox | Gem | | Class/Module | Gembox | Gem |
| ------------ | ------ | --- | | --------------------- | ---------- | ----------------- |
| Fiber | stdlib | mruby-fiber | | Fiber | stdlib | mruby-fiber |
| Enumerator | stdlib | mruby-enumerator | | Enumerator | stdlib | mruby-enumerator |
| Enumerator::Lazy | stdlib | mruby-enum-lazy | | Enumerator::Lazy | stdlib | mruby-enum-lazy |
| Set | stdlib | mruby-set | | Set | stdlib | mruby-set |
| ObjectSpace | stdlib | mruby-objectspace | | ObjectSpace | stdlib | mruby-objectspace |
| Time | stdlib-ext | mruby-time | | Time | stdlib-ext | mruby-time |
| Struct | stdlib-ext | mruby-struct | | Struct | stdlib-ext | mruby-struct |
| Data | stdlib-ext | mruby-data | | Data | stdlib-ext | mruby-data |
| Random | stdlib-ext | mruby-random | | Random | stdlib-ext | mruby-random |
| IO, File | stdlib-io | mruby-io | | IO, File | stdlib-io | mruby-io |
| Socket | stdlib-io | mruby-socket | | Socket | stdlib-io | mruby-socket |
| Dir | stdlib-io | mruby-dir | | Dir | stdlib-io | mruby-dir |
| Errno | stdlib-io | mruby-errno | | Errno | stdlib-io | mruby-errno |
| Math | math | mruby-math | | Math | math | mruby-math |
| Rational | math | mruby-rational | | Rational | math | mruby-rational |
| Complex | math | mruby-complex | | Complex | math | mruby-complex |
| Bigint | math | mruby-bigint | | Bigint | math | mruby-bigint |
| Method, UnboundMethod | metaprog | mruby-method | | Method, UnboundMethod | metaprog | mruby-method |
### Methods and Features ### Methods and Features
| Feature | Gembox | Gem | | Feature | Gembox | Gem |
| ------- | ------ | --- | | ----------------------------- | ---------- | ------------------ |
| `catch`/`throw` | stdlib | mruby-catch | | `catch`/`throw` | stdlib | mruby-catch |
| `Kernel#sprintf`, `String#%` | stdlib-ext | mruby-sprintf | | `Kernel#sprintf`, `String#%` | stdlib-ext | mruby-sprintf |
| `Array#pack`, `String#unpack` | stdlib-ext | mruby-pack | | `Array#pack`, `String#unpack` | stdlib-ext | mruby-pack |
| `Kernel#rand` | stdlib-ext | mruby-random | | `Kernel#rand` | stdlib-ext | mruby-random |
| `Kernel#eval` | metaprog | mruby-eval | | `Kernel#eval` | metaprog | mruby-eval |
| `Kernel#binding` | metaprog | mruby-binding | | `Kernel#binding` | metaprog | mruby-binding |
| `Proc#binding` | metaprog | mruby-proc-binding | | `Proc#binding` | metaprog | mruby-proc-binding |
| Runtime compiler | metaprog | mruby-compiler | | Runtime compiler | metaprog | mruby-compiler |
### Core Class Extensions ### Core Class Extensions
The `stdlib` gembox also extends built-in classes with additional The `stdlib` gembox also extends built-in classes with additional
methods. These are included by default: methods. These are included by default:
| Extension | Examples | | Extension | Examples |
| --------- | -------- | | ----------------------- | ---------------------------------------------- |
| Array extensions | `#dig`, `#union`, `#difference` | | Array extensions | `#dig`, `#union`, `#difference` |
| Hash extensions | `#dig`, `#transform_keys`, `#transform_values` | | Hash extensions | `#dig`, `#transform_keys`, `#transform_values` |
| String extensions | `#encode`, `#bytes`, `#chars` | | String extensions | `#encode`, `#bytes`, `#chars` |
| Numeric extensions | `Integer#digits`, `Integer#pow` | | Numeric extensions | `Integer#digits`, `Integer#pow` |
| Comparable extensions | `#clamp` | | Comparable extensions | `#clamp` |
| Enumerable extensions | `#sort_by`, `#min_by`, `#max_by`, `#tally` | | Enumerable extensions | `#sort_by`, `#min_by`, `#max_by`, `#tally` |
| Range extensions | `#size`, `#cover?` | | Range extensions | `#size`, `#cover?` |
| Proc extensions | `#<<`, `#>>` (composition) | | Proc extensions | `#<<`, `#>>` (composition) |
| Symbol extensions | `#to_proc` | | Symbol extensions | `#to_proc` |
| Object extensions | `#then`, `#yield_self` | | Object extensions | `#then`, `#yield_self` |
| Kernel extensions | `#__method__` | | Kernel extensions | `#__method__` |
| Class/Module extensions | `Module#name` | | Class/Module extensions | `Module#name` |
### Gembox Summary ### Gembox Summary
| Gembox | Contents | Notes | | Gembox | Contents | Notes |
| ------ | -------- | ----- | | ------------ | --------------------------------------------- | -------------------------------------------- |
| `stdlib` | Core class extensions, Fiber, Enumerator, Set | Works with `MRB_NO_STDIO` and `MRB_NO_FLOAT` | | `stdlib` | Core class extensions, Fiber, Enumerator, Set | Works with `MRB_NO_STDIO` and `MRB_NO_FLOAT` |
| `stdlib-ext` | Time, Struct, Data, Random, sprintf, pack | Works with `MRB_NO_STDIO` and `MRB_NO_FLOAT` | | `stdlib-ext` | Time, Struct, Data, Random, sprintf, pack | Works with `MRB_NO_STDIO` and `MRB_NO_FLOAT` |
| `stdlib-io` | IO, File, Dir, Socket, Errno | Requires stdio | | `stdlib-io` | IO, File, Dir, Socket, Errno | Requires stdio |
| `math` | Math, Rational, Complex, Bigint | Works with `MRB_NO_STDIO` | | `math` | Math, Rational, Complex, Bigint | Works with `MRB_NO_STDIO` |
| `metaprog` | eval, binding, Method, compiler | Works with `MRB_NO_STDIO` and `MRB_NO_FLOAT` | | `metaprog` | eval, binding, Method, compiler | Works with `MRB_NO_STDIO` and `MRB_NO_FLOAT` |
| `default` | All of the above + CLI tools | Full installation | | `default` | All of the above + CLI tools | Full installation |
## Key Differences from CRuby ## Key Differences from CRuby
@@ -378,8 +378,8 @@ This means subclassing `Array` or `String` and adding `@fields` will raise an er
### Operator Overriding ### Operator Overriding
Operators of primitive classes cannot be overridden by user code. Operators of primitive classes cannot be overridden by user code.
Redefining `String#+` has no effect on the behavior of the `+` __operator__. Redefining `String#+` has no effect on the behavior of the `+` operator.
### Module Loading Hooks ### Module Loading Hooks
@@ -416,15 +416,15 @@ differently on 32-bit or NaN boxing configurations.
Key compile-time macros that affect language behavior: Key compile-time macros that affect language behavior:
| Macro | Effect | | Macro | Effect |
| ----- | ------ | | -------------------- | ---------------------------------- |
| `MRB_NO_FLOAT` | Remove all float support | | `MRB_NO_FLOAT` | Remove all float support |
| `MRB_USE_FLOAT32` | Use 32-bit float instead of double | | `MRB_USE_FLOAT32` | Use 32-bit float instead of double |
| `MRB_UTF8_STRING` | Enable UTF-8 string handling | | `MRB_UTF8_STRING` | Enable UTF-8 string handling |
| `MRB_INT32` | Force 32-bit integer | | `MRB_INT32` | Force 32-bit integer |
| `MRB_INT64` | Force 64-bit integer | | `MRB_INT64` | Force 64-bit integer |
| `MRB_STR_LENGTH_MAX` | Max string length (default 1MB) | | `MRB_STR_LENGTH_MAX` | Max string length (default 1MB) |
| `MRB_ARY_LENGTH_MAX` | Max array length (default 2^17) | | `MRB_ARY_LENGTH_MAX` | Max array length (default 2^17) |
See [mrbconf.md](mrbconf.md) for the complete list of configuration See [mrbconf.md](mrbconf.md) for the complete list of configuration
macros. macros.
+4 -4
View File
@@ -202,10 +202,10 @@ any other heap page. The only differences are:
The page size is controlled by `MRB_HEAP_PAGE_SIZE` (default: 1024 slots). The page size is controlled by `MRB_HEAP_PAGE_SIZE` (default: 1024 slots).
Each page occupies: Each page occupies:
| Platform | Slot size | Page size (approx) | | Platform | Slot size | Page size (approx) |
|----------|-----------|---------------------| | -------- | --------- | ------------------ |
| 64-bit | 40 bytes | ~41 KB | | 64-bit | 40 bytes | ~41 KB |
| 32-bit | 24 bytes | ~25 KB | | 32-bit | 24 bytes | ~25 KB |
To estimate pages for a given buffer: `pages = buffer_size / sizeof(mrb_heap_page)`. To estimate pages for a given buffer: `pages = buffer_size / sizeof(mrb_heap_page)`.
Each page provides `MRB_HEAP_PAGE_SIZE` object slots. Each page provides `MRB_HEAP_PAGE_SIZE` object slots.
+3 -3
View File
@@ -233,10 +233,10 @@ end
- Specifies 4th argument(`argc`) max value of `mrb_funcall`. - Specifies 4th argument(`argc`) max value of `mrb_funcall`.
- Raises `ArgumentError` when the `argc` argument is bigger then this value `mrb_funcall`. - Raises `ArgumentError` when the `argc` argument is bigger then this value `mrb_funcall`.
`KHASH_DEFAULT_SIZE` `KHASH_INITIAL_SIZE`
- Default value is `32`. - Default value is `32`.
- Specifies default size of khash table bucket. - Specifies initial size of khash table bucket.
- Used in `kh_init_ ## name` function. - Used in `kh_init_ ## name` function.
`MRB_NO_METHOD_CACHE` `MRB_NO_METHOD_CACHE`
@@ -272,7 +272,7 @@ deployment targets. Define one of the following:
`MRB_CONSTRAINED_BASELINE_PROFILE` `MRB_CONSTRAINED_BASELINE_PROFILE`
- For micro controllers. - For micro controllers.
- Enables `MRB_NO_METHOD_CACHE`, reduces `KHASH_DEFAULT_SIZE` to `16`, - Enables `MRB_NO_METHOD_CACHE`, reduces `KHASH_INITIAL_SIZE` to `16`,
and `MRB_HEAP_PAGE_SIZE` to `256`. and `MRB_HEAP_PAGE_SIZE` to `256`.
`MRB_BASELINE_PROFILE` `MRB_BASELINE_PROFILE`
-1
View File
@@ -79,7 +79,6 @@ Include `<mruby/class.h>` (which provides `mrb_mt_entry`,
```c ```c
#include <mruby/class.h> #include <mruby/class.h>
#include <mruby/presym.h>
static const mrb_mt_entry my_rom_entries[] = { static const mrb_mt_entry my_rom_entries[] = {
MRB_MT_ENTRY(my_method_a, MRB_SYM(method_a), MRB_ARGS_REQ(1)), MRB_MT_ENTRY(my_method_a, MRB_SYM(method_a), MRB_ARGS_REQ(1)),
+51 -51
View File
@@ -31,17 +31,17 @@ struct RBasic (8 bytes on 64-bit)
All object structs embed this header via `MRB_OBJECT_HEADER`: All object structs embed this header via `MRB_OBJECT_HEADER`:
| Struct | Ruby Type | Extra Fields | | Struct | Ruby Type | Extra Fields |
| ------ | --------- | ------------ | | ------------ | ---------------- | ---------------------------------- |
| `RObject` | Object instances | `iv` (instance variables) | | `RObject` | Object instances | `iv` (instance variables) |
| `RClass` | Class/Module | `iv`, `mt` (method table), `super` | | `RClass` | Class/Module | `iv`, `mt` (method table), `super` |
| `RString` | String | embedded or heap buffer, length | | `RString` | String | embedded or heap buffer, length |
| `RArray` | Array | embedded or heap buffer, length | | `RArray` | Array | embedded or heap buffer, length |
| `RHash` | Hash | hash table or k-v array | | `RHash` | Hash | hash table or k-v array |
| `RProc` | Proc/Lambda | `irep` or C function, environment | | `RProc` | Proc/Lambda | `irep` or C function, environment |
| `RData` | C data wrapper | `void *data`, `mrb_data_type` | | `RData` | C data wrapper | `void *data`, `mrb_data_type` |
| `RFiber` | Fiber | `mrb_context` | | `RFiber` | Fiber | `mrb_context` |
| `RException` | Exception | `iv` | | `RException` | Exception | `iv` |
Immediate values (Integer, Symbol, `true`, `false`, `nil`) are encoded Immediate values (Integer, Symbol, `true`, `false`, `nil`) are encoded
directly in `mrb_value` without heap allocation. The encoding depends on directly in `mrb_value` without heap allocation. The encoding depends on
@@ -111,52 +111,52 @@ See [compiler.md](compiler.md) for detailed compiler internals,
### Core (`src/`) ### Core (`src/`)
| File | Responsibility | | File | Responsibility |
| ---- | -------------- | | ------------- | ---------------------------------------------- |
| `vm.c` | Bytecode dispatch loop, method invocation | | `vm.c` | Bytecode dispatch loop, method invocation |
| `state.c` | `mrb_state` init/close, irep management | | `state.c` | `mrb_state` init/close, irep management |
| `gc.c` | Garbage collector (mark-sweep, incremental) | | `gc.c` | Garbage collector (mark-sweep, incremental) |
| `class.c` | Class/module definition, method tables | | `class.c` | Class/module definition, method tables |
| `object.c` | Core object operations | | `object.c` | Core object operations |
| `variable.c` | Instance/class/global variables, object shapes | | `variable.c` | Instance/class/global variables, object shapes |
| `proc.c` | Proc/Lambda/closure handling | | `proc.c` | Proc/Lambda/closure handling |
| `array.c` | Array implementation | | `array.c` | Array implementation |
| `string.c` | String implementation (embedded, shared, heap) | | `string.c` | String implementation (embedded, shared, heap) |
| `hash.c` | Hash implementation (open addressing) | | `hash.c` | Hash implementation (open addressing) |
| `numeric.c` | Integer/Float arithmetic | | `numeric.c` | Integer/Float arithmetic |
| `symbol.c` | Symbol table and interning | | `symbol.c` | Symbol table and interning |
| `range.c` | Range implementation | | `range.c` | Range implementation |
| `error.c` | Exception creation, raise, backtrace | | `error.c` | Exception creation, raise, backtrace |
| `kernel.c` | Kernel module methods | | `kernel.c` | Kernel module methods |
| `load.c` | `.mrb` bytecode loading | | `load.c` | `.mrb` bytecode loading |
| `dump.c` | Bytecode serialization (write `.mrb`) | | `dump.c` | Bytecode serialization (write `.mrb`) |
| `print.c` | Print/puts/p output | | `print.c` | Print/puts/p output |
| `backtrace.c` | Stack trace generation | | `backtrace.c` | Stack trace generation |
### Compiler (`mrbgems/mruby-compiler/core/`) ### Compiler (`mrbgems/mruby-compiler/core/`)
| File | Responsibility | | File | Responsibility |
| ---- | -------------- | | ----------- | ------------------------------- |
| `parse.y` | Yacc grammar → AST | | `parse.y` | Yacc grammar → AST |
| `y.tab.c` | Generated parser (from parse.y) | | `y.tab.c` | Generated parser (from parse.y) |
| `codegen.c` | AST → bytecode (irep) | | `codegen.c` | AST → bytecode (irep) |
| `node.h` | AST node type definitions | | `node.h` | AST node type definitions |
### Key Headers (`include/mruby/`) ### Key Headers (`include/mruby/`)
| Header | Contents | | Header | Contents |
| ------ | -------- | | ------------ | ------------------------------------- |
| `mruby.h` | `mrb_state`, core API declarations | | `mruby.h` | `mrb_state`, core API declarations |
| `value.h` | `mrb_value`, type enums, value macros | | `value.h` | `mrb_value`, type enums, value macros |
| `object.h` | `RBasic`, `RObject`, object header | | `object.h` | `RBasic`, `RObject`, object header |
| `class.h` | `RClass`, method table types | | `class.h` | `RClass`, method table types |
| `string.h` | `RString`, string macros | | `string.h` | `RString`, string macros |
| `array.h` | `RArray`, array macros | | `array.h` | `RArray`, array macros |
| `hash.h` | `RHash`, hash API | | `hash.h` | `RHash`, hash API |
| `data.h` | `RData`, C data wrapping | | `data.h` | `RData`, C data wrapping |
| `irep.h` | `mrb_irep`, bytecode structures | | `irep.h` | `mrb_irep`, bytecode structures |
| `compile.h` | Compiler context, `mrb_load_string` | | `compile.h` | Compiler context, `mrb_load_string` |
| `boxing_*.h` | Value boxing implementations | | `boxing_*.h` | Value boxing implementations |
## mrbgems System ## mrbgems System
+10 -10
View File
@@ -77,16 +77,16 @@ No boxing represents `mrb_value` by the C struct with `type` and the value union
## Comparison ## Comparison
| Property | Word Boxing | NaN Boxing | No Boxing | | Property | Word Boxing | NaN Boxing | No Boxing |
| ---------------------- | ------------------ | ------------------ | -------------------- | | ---------------------- | ----------------- | ---------------- | -------------------- |
| `mrb_value` size | 1 word (4/8 byte) | 8 bytes | 2 words (8/16 bytes) | | `mrb_value` size | 1 word (4/8 byte) | 8 bytes | 2 words (8/16 bytes) |
| Default on | most platforms | (manual opt-in) | `host-debug` | | Default on | most platforms | (manual opt-in) | `host-debug` |
| Macro | `MRB_WORD_BOXING` | `MRB_NAN_BOXING` | `MRB_NO_BOXING` | | Macro | `MRB_WORD_BOXING` | `MRB_NAN_BOXING` | `MRB_NO_BOXING` |
| Inline integers | yes (31/63 bit) | yes (32 bit) | yes (full width) | | Inline integers | yes (31/63 bit) | yes (32 bit) | yes (full width) |
| Inline floats (64-bit) | yes (rotation) | yes (native) | yes (struct field) | | Inline floats (64-bit) | yes (rotation) | yes (native) | yes (struct field) |
| Inline floats (32-bit) | no (heap RFloat) | yes (native) | yes (struct field) | | Inline floats (32-bit) | no (heap RFloat) | yes (native) | yes (struct field) |
| Pointer size limit | none | 48 bits | none | | Pointer size limit | none | 48 bits | none |
| Debugger friendly | no | no | yes | | Debugger friendly | no | no | yes |
## ABI Compatibility ## ABI Compatibility
+59 -59
View File
@@ -40,18 +40,18 @@ file: `mrbgems/mruby-compiler/core/parse.y`.
The parser maintains extensive state in `mrb_parser_state`: The parser maintains extensive state in `mrb_parser_state`:
- **lstate**: current lexer state (EXPR\_BEG, EXPR\_END, EXPR\_ARG, - **lstate**: current lexer state (EXPR_BEG, EXPR_END, EXPR_ARG,
EXPR\_DOT, EXPR\_FNAME, etc.). Controls how tokens like `+`/`-` EXPR_DOT, EXPR_FNAME, etc.). Controls how tokens like `+`/`-`
are interpreted (sign vs operator) and whether newlines are are interpreted (sign vs operator) and whether newlines are
significant. significant.
- **locals**: stack of local variable lists (one per scope), stored - **locals**: stack of local variable lists (one per scope), stored
as cons-lists of symbols. as cons-lists of symbols.
- **lex\_strterm**: string/heredoc parsing state for handling nested - **lex_strterm**: string/heredoc parsing state for handling nested
interpolation. interpolation.
- **cond\_stack**, **cmdarg\_stack**: bit stacks tracking - **cond_stack**, **cmdarg_stack**: bit stacks tracking
conditional and command argument contexts. conditional and command argument contexts.
- **tree**: root AST node after successful parse. - **tree**: root AST node after successful parse.
- **error\_buffer**: accumulated parse errors. - **error_buffer**: accumulated parse errors.
### AST Nodes ### AST Nodes
@@ -123,10 +123,10 @@ reuse temporaries within an expression.
Instructions are emitted via helper functions: Instructions are emitted via helper functions:
- `genop_0(opcode)`: no operands - `genop_0(opcode)`: no operands
- `genop_1(opcode, a)`: one operand (auto-extends with OP\_EXT1 - `genop_1(opcode, a)`: one operand (auto-extends with OP_EXT1
if a > 255) if a > 255)
- `genop_2(opcode, a, b)`: two operands (auto-extends with - `genop_2(opcode, a, b)`: two operands (auto-extends with
OP\_EXT1/2/3 as needed) OP_EXT1/2/3 as needed)
- `genop_3(opcode, a, b, c)`: three operands - `genop_3(opcode, a, b, c)`: three operands
- `genop_W(opcode, a)`: 24-bit operand - `genop_W(opcode, a)`: 24-bit operand
- `genop_2S(opcode, a, b)`: one 8-bit + one 16-bit operand - `genop_2S(opcode, a, b)`: one 8-bit + one 16-bit operand
@@ -176,14 +176,14 @@ mrb_irep
Pool entries store constants referenced by instructions: Pool entries store constants referenced by instructions:
| Type | Tag | Description | | Type | Tag | Description |
| ---- | --- | ----------- | | ---------------- | --- | ------------------------------- |
| `IREP_TT_STR` | 0 | Dynamic string (heap allocated) | | `IREP_TT_STR` | 0 | Dynamic string (heap allocated) |
| `IREP_TT_SSTR` | 2 | Static string (read-only) | | `IREP_TT_SSTR` | 2 | Static string (read-only) |
| `IREP_TT_INT32` | 1 | 32-bit integer | | `IREP_TT_INT32` | 1 | 32-bit integer |
| `IREP_TT_INT64` | 3 | 64-bit integer | | `IREP_TT_INT64` | 3 | 64-bit integer |
| `IREP_TT_FLOAT` | 5 | Floating-point number | | `IREP_TT_FLOAT` | 5 | Floating-point number |
| `IREP_TT_BIGINT` | 7 | Arbitrary-precision integer | | `IREP_TT_BIGINT` | 7 | Arbitrary-precision integer |
The code generator deduplicates pool entries: identical strings The code generator deduplicates pool entries: identical strings
and equal numeric values share the same pool index. and equal numeric values share the same pool index.
@@ -209,28 +209,28 @@ During exception unwinding, handlers are searched in reverse order
Standard instructions use 8-bit operands. When a value exceeds Standard instructions use 8-bit operands. When a value exceeds
255, extension prefixes widen operands to 16 bits: 255, extension prefixes widen operands to 16 bits:
| Prefix | Effect | | Prefix | Effect |
| ------ | ------ | | --------- | --------------------------------- |
| `OP_EXT1` | First operand (a) becomes 16-bit | | `OP_EXT1` | First operand (a) becomes 16-bit |
| `OP_EXT2` | Second operand (b) becomes 16-bit | | `OP_EXT2` | Second operand (b) becomes 16-bit |
| `OP_EXT3` | Both a and b become 16-bit | | `OP_EXT3` | Both a and b become 16-bit |
Instruction formats: Instruction formats:
| Format | Layout | Size | | Format | Layout | Size |
| ------ | ------ | ---- | | ------ | ----------------------------- | ------- |
| Z | opcode only | 1 byte | | Z | opcode only | 1 byte |
| B | opcode + a(8) | 2 bytes | | B | opcode + a(8) | 2 bytes |
| BB | opcode + a(8) + b(8) | 3 bytes | | BB | opcode + a(8) + b(8) | 3 bytes |
| BBB | opcode + a(8) + b(8) + c(8) | 4 bytes | | BBB | opcode + a(8) + b(8) + c(8) | 4 bytes |
| BS | opcode + a(8) + b(16) | 4 bytes | | BS | opcode + a(8) + b(16) | 4 bytes |
| BSS | opcode + a(8) + b(16) + c(16) | 6 bytes | | BSS | opcode + a(8) + b(16) + c(16) | 6 bytes |
| S | opcode + a(16) | 3 bytes | | S | opcode + a(16) | 3 bytes |
| W | opcode + a(24) | 4 bytes | | W | opcode + a(24) | 4 bytes |
See [opcode.md](opcode.md) for the full instruction table. See [opcode.md](opcode.md) for the full instruction table.
## OP\_ENTER: Argument Specification ## OP_ENTER: Argument Specification
`OP_ENTER` encodes a method's argument layout in a 24-bit value `OP_ENTER` encodes a method's argument layout in a 24-bit value
(W format). The bit fields are defined by the `MRB_ARGS_*` macros: (W format). The bit fields are defined by the `MRB_ARGS_*` macros:
@@ -258,16 +258,16 @@ string interning for common symbols.
Generated by `lib/mruby/presym.rb`, the presym table maps symbol Generated by `lib/mruby/presym.rb`, the presym table maps symbol
names to compile-time constants: names to compile-time constants:
| Macro | Example | Symbol | | Macro | Example | Symbol |
| ----- | ------- | ------ | | ----------------- | --------------------- | ------------- |
| `MRB_SYM(name)` | `MRB_SYM(initialize)` | `:initialize` | | `MRB_SYM(name)` | `MRB_SYM(initialize)` | `:initialize` |
| `MRB_SYM_B(name)` | `MRB_SYM_B(map)` | `:map!` | | `MRB_SYM_B(name)` | `MRB_SYM_B(map)` | `:map!` |
| `MRB_SYM_Q(name)` | `MRB_SYM_Q(nil)` | `:nil?` | | `MRB_SYM_Q(name)` | `MRB_SYM_Q(nil)` | `:nil?` |
| `MRB_SYM_E(name)` | `MRB_SYM_E(name)` | `:name=` | | `MRB_SYM_E(name)` | `MRB_SYM_E(name)` | `:name=` |
| `MRB_OPSYM(op)` | `MRB_OPSYM(add)` | `:+` | | `MRB_OPSYM(op)` | `MRB_OPSYM(add)` | `:+` |
| `MRB_IVSYM(name)` | `MRB_IVSYM(name)` | `:@name` | | `MRB_IVSYM(name)` | `MRB_IVSYM(name)` | `:@name` |
| `MRB_CVSYM(name)` | `MRB_CVSYM(count)` | `:@@count` | | `MRB_CVSYM(name)` | `MRB_CVSYM(count)` | `:@@count` |
| `MRB_GVSYM(name)` | `MRB_GVSYM(stdout)` | `:$stdout` | | `MRB_GVSYM(name)` | `MRB_GVSYM(stdout)` | `:$stdout` |
## Binary Format (.mrb) ## Binary Format (.mrb)
@@ -299,25 +299,25 @@ mrbc -Boutput source.rb # C array format
## Compilation Limits ## Compilation Limits
| Limit | Value | | Limit | Value |
| ----- | ----- | | ---------------------- | ----------------------------- |
| Max nesting depth | 256 (`MRB_CODEGEN_LEVEL_MAX`) | | Max nesting depth | 256 (`MRB_CODEGEN_LEVEL_MAX`) |
| Max local variables | 255 (uint16 `nlocals`) | | Max local variables | 255 (uint16 `nlocals`) |
| Max symbols per irep | 65535 | | Max symbols per irep | 65535 |
| Max operand (standard) | 255 (8-bit) | | Max operand (standard) | 255 (8-bit) |
| Max operand (extended) | 65535 (16-bit) | | Max operand (extended) | 65535 (16-bit) |
## Source Files ## Source Files
| File | Contents | | File | Contents |
| ---- | -------- | | --------------------------------------- | ------------------------- |
| `mrbgems/mruby-compiler/core/parse.y` | Lrama/Bison grammar | | `mrbgems/mruby-compiler/core/parse.y` | Lrama/Bison grammar |
| `mrbgems/mruby-compiler/core/y.tab.c` | Generated parser | | `mrbgems/mruby-compiler/core/y.tab.c` | Generated parser |
| `mrbgems/mruby-compiler/core/codegen.c` | Code generator | | `mrbgems/mruby-compiler/core/codegen.c` | Code generator |
| `mrbgems/mruby-compiler/core/node.h` | AST node types | | `mrbgems/mruby-compiler/core/node.h` | AST node types |
| `include/mruby/irep.h` | IRep structure definition | | `include/mruby/irep.h` | IRep structure definition |
| `include/mruby/compile.h` | Compiler context API | | `include/mruby/compile.h` | Compiler context API |
| `include/mruby/ops.h` | Opcode definitions | | `include/mruby/ops.h` | Opcode definitions |
| `src/load.c` | Binary format loader | | `src/load.c` | Binary format loader |
| `src/dump.c` | Binary format writer | | `src/dump.c` | Binary format writer |
| `lib/mruby/presym.rb` | Presym table generator | | `lib/mruby/presym.rb` | Presym table generator |
+22 -22
View File
@@ -26,12 +26,12 @@ pauses.
Every heap-allocated object has a color stored in Every heap-allocated object has a color stored in
`RBasic::gc_color` (3 bits): `RBasic::gc_color` (3 bits):
| Color | Value | Meaning | | Color | Value | Meaning |
| ----- | ----- | ------- | | -------------- | ------ | ------------------------------------ |
| White (A or B) | 1 or 2 | Unmarked, candidate for collection | | White (A or B) | 1 or 2 | Unmarked, candidate for collection |
| Gray | 0 | Marked, but children not yet scanned | | Gray | 0 | Marked, but children not yet scanned |
| Black | 4 | Fully marked and scanned | | Black | 4 | Fully marked and scanned |
| Red | 7 | Static/ROM object, never collected | | Red | 7 | Static/ROM object, never collected |
The GC uses two white types (A and B) in a flip-flop scheme. At the The GC uses two white types (A and B) in a flip-flop scheme. At the
start of each GC cycle, the meaning of "current white" is flipped by start of each GC cycle, the meaning of "current white" is flipped by
@@ -107,7 +107,7 @@ The GC operates as a three-state machine:
GC_STATE_ROOT --> GC_STATE_MARK --> GC_STATE_SWEEP --> GC_STATE_ROOT GC_STATE_ROOT --> GC_STATE_MARK --> GC_STATE_SWEEP --> GC_STATE_ROOT
``` ```
### Root Scan (GC\_STATE\_ROOT) ### Root Scan (GC_STATE_ROOT)
Marks objects directly reachable from the VM: Marks objects directly reachable from the VM:
@@ -121,7 +121,7 @@ Marks objects directly reachable from the VM:
After root scanning, the white color is flipped. After root scanning, the white color is flipped.
### Incremental Marking (GC\_STATE\_MARK) ### Incremental Marking (GC_STATE_MARK)
Gray objects are popped from the gray stack and their children Gray objects are popped from the gray stack and their children
marked. Each step processes a limited number of objects: marked. Each step processes a limited number of objects:
@@ -137,7 +137,7 @@ When the gray stack is exhausted, the final marking phase re-marks
the arena and global variables to catch objects created during the arena and global variables to catch objects created during
marking, then transitions to sweep. marking, then transitions to sweep.
### Sweep (GC\_STATE\_SWEEP) ### Sweep (GC_STATE_SWEEP)
Iterates through heap pages. For each object: Iterates through heap pages. For each object:
@@ -325,15 +325,15 @@ From Ruby: `GC.start`.
### Compile-Time ### Compile-Time
| Macro | Default | Description | | Macro | Default | Description |
| ----- | ------- | ----------- | | ------------------------------ | ------- | --------------------------------------- |
| `MRB_HEAP_PAGE_SIZE` | 1024 | Objects per heap page | | `MRB_HEAP_PAGE_SIZE` | 1024 | Objects per heap page |
| `MRB_GRAY_STACK_SIZE` | 1024 | Gray stack capacity | | `MRB_GRAY_STACK_SIZE` | 1024 | Gray stack capacity |
| `MRB_GC_ARENA_SIZE` | 100 | Arena size (fixed mode) or initial size | | `MRB_GC_ARENA_SIZE` | 100 | Arena size (fixed mode) or initial size |
| `MRB_GC_FIXED_ARENA` | off | Use fixed-size arena | | `MRB_GC_FIXED_ARENA` | off | Use fixed-size arena |
| `MRB_GC_TURN_OFF_GENERATIONAL` | off | Disable generational mode | | `MRB_GC_TURN_OFF_GENERATIONAL` | off | Disable generational mode |
| `MRB_GC_STRESS` | off | Full GC on every allocation (debug) | | `MRB_GC_STRESS` | off | Full GC on every allocation (debug) |
| `MRB_USE_MALLOC_TRIM` | off | Call `malloc_trim()` after full GC | | `MRB_USE_MALLOC_TRIM` | off | Call `malloc_trim()` after full GC |
### Runtime ### Runtime
@@ -350,8 +350,8 @@ GC.disable # disable GC
## Source Files ## Source Files
| File | Contents | | File | Contents |
| ---- | -------- | | -------------------- | --------------------------------- |
| `src/gc.c` | GC implementation (~1400 lines) | | `src/gc.c` | GC implementation (~1400 lines) |
| `include/mruby/gc.h` | `mrb_gc` structure, public GC API | | `include/mruby/gc.h` | `mrb_gc` structure, public GC API |
| `include/mruby.h` | Arena save/restore macros | | `include/mruby.h` | Arena save/restore macros |
+19 -19
View File
@@ -97,12 +97,12 @@ return n + 1 (skip self)
### Call Context Info (cci) ### Call Context Info (cci)
| Value | Name | Meaning | | Value | Name | Meaning |
| ----- | ---- | ------- | | ----- | --------------- | ------------------------------------- |
| 0 | `CINFO_NONE` | Normal VM-to-VM call | | 0 | `CINFO_NONE` | Normal VM-to-VM call |
| 1 | `CINFO_DIRECT` | Explicit VM call (block, lambda.call) | | 1 | `CINFO_DIRECT` | Explicit VM call (block, lambda.call) |
| 2 | `CINFO_SKIP` | Skip frame in stack traces | | 2 | `CINFO_SKIP` | Skip frame in stack traces |
| 3 | `CINFO_RESUMED` | Fiber resumed (stop execution) | | 3 | `CINFO_RESUMED` | Fiber resumed (stop execution) |
## Dispatch Loop ## Dispatch Loop
@@ -241,13 +241,13 @@ correctness.
### Proc Types ### Proc Types
| Flag | Meaning | | Flag | Meaning |
| ---- | ------- | | ------------------- | ------------------------------ |
| `MRB_PROC_CFUNC_FL` | C function (not irep-based) | | `MRB_PROC_CFUNC_FL` | C function (not irep-based) |
| `MRB_PROC_STRICT` | Lambda (strict argument check) | | `MRB_PROC_STRICT` | Lambda (strict argument check) |
| `MRB_PROC_ORPHAN` | No environment attachment | | `MRB_PROC_ORPHAN` | No environment attachment |
| `MRB_PROC_ENVSET` | Has captured environment | | `MRB_PROC_ENVSET` | Has captured environment |
| `MRB_PROC_SCOPE` | Defines a new variable scope | | `MRB_PROC_SCOPE` | Defines a new variable scope |
## Fiber Switching ## Fiber Switching
@@ -317,9 +317,9 @@ ensuring the incremental GC correctly tracks live references.
## Source Files ## Source Files
| File | Contents | | File | Contents |
| ---- | -------- | | ----------------------- | ---------------------------------------------- |
| `src/vm.c` | Dispatch loop, method invocation (~1900 lines) | | `src/vm.c` | Dispatch loop, method invocation (~1900 lines) |
| `include/mruby.h` | `mrb_state`, `mrb_callinfo`, `mrb_context` | | `include/mruby.h` | `mrb_state`, `mrb_callinfo`, `mrb_context` |
| `include/mruby/proc.h` | `RProc`, `REnv` structures | | `include/mruby/proc.h` | `RProc`, `REnv` structures |
| `include/mruby/throw.h` | `MRB_TRY`/`MRB_CATCH` macros | | `include/mruby/throw.h` | `MRB_TRY`/`MRB_CATCH` macros |
+3 -3
View File
@@ -274,11 +274,11 @@ enabled with the `MRB_UTF8_STRING` compile flag.
Integer size depends on the value boxing configuration: Integer size depends on the value boxing configuration:
| Configuration | Integer range | | Configuration | Integer range |
| ------------- | ------------- | | ----------------------------- | ---------------- |
| Word boxing, 64-bit (default) | roughly +/- 2^62 | | Word boxing, 64-bit (default) | roughly +/- 2^62 |
| Word boxing, 32-bit (default) | roughly +/- 2^30 | | Word boxing, 32-bit (default) | roughly +/- 2^30 |
| NaN boxing (64-bit only) | -2^31 to 2^31-1 | | NaN boxing (64-bit only) | -2^31 to 2^31-1 |
Code relying on 64-bit integer precision may behave differently Code relying on 64-bit integer precision may behave differently
across configurations. The `mruby-bigint` gem provides across configurations. The `mruby-bigint` gem provides
+367
View File
@@ -0,0 +1,367 @@
# User visible changes in `mruby4.0` from `mruby3.4`
"**_NOTE_**:" are changes to be aware of.
# The language
## Pattern Matching
mruby now supports pattern matching (case/in) syntax:
- Basic pattern matching with `case`/`in` syntax ([dadfac6](https://github.com/mruby/mruby/commit/dadfac6))
- Array pattern matching ([ec67fd9](https://github.com/mruby/mruby/commit/ec67fd9))
- Hash pattern matching ([2147263](https://github.com/mruby/mruby/commit/2147263))
- Find pattern matching (`[*pre, target, *post]`) ([6c4d98b](https://github.com/mruby/mruby/commit/6c4d98b))
- Pin operator (`^variable`) ([1de6340](https://github.com/mruby/mruby/commit/1de6340))
- Guard clauses (`if`/`unless` conditions) ([07ac110](https://github.com/mruby/mruby/commit/07ac110))
- One-line pattern matching (`expr in pattern`) ([e76ce24](https://github.com/mruby/mruby/commit/e76ce24))
- Brace-less hash pattern support ([e8096bf](https://github.com/mruby/mruby/commit/e8096bf))
## Other Language Changes
- `&nil` in formal parameters to explicitly opt out of block arguments ([b07518e](https://github.com/mruby/mruby/commit/b07518e))
- Trailing comma in method definition parameters: `def foo(a, b,)` ([f78334b](https://github.com/mruby/mruby/commit/f78334b))
- Array/Hash/String subclasses can now override `[]` and `[]=` methods ([#6675](https://github.com/mruby/mruby/pull/6675))
- `OP_SETIDX` optimization for Array and Hash ([ddd8fe1](https://github.com/mruby/mruby/commit/ddd8fe1))
- `case`/`in` without `else` now raises `NoMatchingPatternError` ([d8de35b](https://github.com/mruby/mruby/commit/d8de35b))
- Allow compound statement in parenthesized argument context ([919cbd8](https://github.com/mruby/mruby/commit/919cbd8))
# Changes in C API
- **_NOTE_**: `mrb_alloca()` renamed to `mrb_temp_alloc()` ([7fe5c2e](https://github.com/mruby/mruby/commit/7fe5c2e))
- **_NOTE_**: `mruby/ext/io.h` renamed to `mruby/io.h` ([2813f79](https://github.com/mruby/mruby/commit/2813f79))
- `mrb_gc_add_region()` for contiguous heap region support ([072855a](https://github.com/mruby/mruby/commit/072855a))
- `mrb_class_outer()` to get the outer class/module ([3a1b771](https://github.com/mruby/mruby/commit/3a1b771))
- `MRB_ENSURE()` macro for exception-safe cleanup ([3ac682b](https://github.com/mruby/mruby/commit/3ac682b))
- `mrb_time_get_tm()` for accessing struct tm ([daaaafe](https://github.com/mruby/mruby/commit/daaaafe))
- `MRB_OPEN_FAILURE()` macro for checking mrb_open result ([40b0cb9](https://github.com/mruby/mruby/commit/40b0cb9))
- `mrb_print_error()` now handles NULL gracefully ([8e50a45](https://github.com/mruby/mruby/commit/8e50a45))
- `mrb_open()` returns mrb_state with exc set on init failure ([05ffe0c](https://github.com/mruby/mruby/commit/05ffe0c))
- `mrb_utf8_to_buf()` for UTF-8 encoding consolidation ([7e28e68](https://github.com/mruby/mruby/commit/7e28e68))
- `kh_is_end()` macro for safe khash iteration ([893cc75](https://github.com/mruby/mruby/commit/893cc75))
- `mrb_bigint_p()` always defined regardless of bigint gem presence ([6c4a8c0](https://github.com/mruby/mruby/commit/6c4a8c0))
- `RInteger` and `RFloat` added to `RVALUE` union ([13dbca0](https://github.com/mruby/mruby/commit/13dbca0))
# ROM Method Tables
All built-in classes and most extension gems now use read-only method
tables stored in `.rodata` instead of heap-allocated hash tables. Method
definitions no longer consume heap memory, significantly reducing memory
footprint for embedded use.
Core classes converted: BasicObject, Object, Module, Class, Kernel,
String, Array, Hash, Numeric, Integer, Float, NilClass, TrueClass,
FalseClass, Range, Symbol, Exception, Proc.
Extension gems converted: mruby-string-ext, mruby-array-ext, mruby-set,
mruby-struct, mruby-class-ext, mruby-numeric-ext, mruby-random,
mruby-kernel-ext, mruby-complex, mruby-rational, mruby-io, mruby-socket,
mruby-method, mruby-metaprog, mruby-time, mruby-hash-ext, mruby-proc-ext,
mruby-symbol-ext, mruby-range-ext, mruby-object-ext.
# GC and Memory
- **_NOTE_**: `MRB_NO_PRESYM` removed; presym is now always enabled ([81689045](https://github.com/mruby/mruby/commit/81689045))
- Replace `gcnext` gray linked list with fixed-size gray stack, reducing per-object overhead ([31fea170](https://github.com/mruby/mruby/commit/31fea170))
- `mrb_gc_add_region()` for providing contiguous memory buffers as GC heap pages ([072855a](https://github.com/mruby/mruby/commit/072855a))
- Chunk-based pool for symbol string allocation ([e05bd8f](https://github.com/mruby/mruby/commit/e05bd8f))
- Reduce `IV_INITIAL_SIZE` from 4 to 2 ([6bd1f51](https://github.com/mruby/mruby/commit/6bd1f51))
- Lossless float encoding using rotation in word boxing ([b6148c8](https://github.com/mruby/mruby/commit/b6148c8))
- Lossless rotation encoding for 32-bit float32 word boxing ([14a5cfb](https://github.com/mruby/mruby/commit/14a5cfb))
- Consolidated irep allocation for .mrb loading ([74fb045](https://github.com/mruby/mruby/commit/74fb045))
- Object shapes (hidden classes) for `MRB_TT_OBJECT` IV storage, sharing key layouts across objects with the same instance variable assignment order ([8d10056](https://github.com/mruby/mruby/commit/8d10056))
# Build & Configuration
- **_NOTE_**: `MRB_WORDBOX_NO_FLOAT_TRUNCATE` renamed to `MRB_WORDBOX_NO_INLINE_FLOAT` (old name still works) ([59e1fe2](https://github.com/mruby/mruby/commit/59e1fe2))
- **_NOTE_**: `MRB_INT64` on 32-bit now requires `MRB_NO_BOXING` (other boxing modes cannot guarantee alignment for heap-allocated 64-bit integers) ([eaaa66b](https://github.com/mruby/mruby/commit/eaaa66b))
- Amalgamation support via `rake amalgam` task ([d995ca2](https://github.com/mruby/mruby/commit/d995ca2))
- New Platform: Cosmopolitan Libc ([#6681](https://github.com/mruby/mruby/pull/6681))
- Emscripten: use native WASM exception handling ([ca364e3](https://github.com/mruby/mruby/commit/ca364e3))
- HAL (Hardware Abstraction Layer) for platform abstraction in mruby-io, mruby-socket, mruby-dir, mruby-task ([74ca22f](https://github.com/mruby/mruby/commit/74ca22f))
- `MRUBY_MIRB_READLINE` environment variable to control readline library selection ([0aafb83](https://github.com/mruby/mruby/commit/0aafb83))
- MSYS2 drive letter support in build script ([77f6ffe](https://github.com/mruby/mruby/commit/77f6ffe))
- Inter-gem headers separated from external API headers ([#6671](https://github.com/mruby/mruby/pull/6671))
# Changes in mrbgems
## New Gems
- **mruby-task**: Cooperative multitasking with preemptive scheduling ([ae0d7a0](https://github.com/mruby/mruby/commit/ae0d7a0))
- **mruby-benchmark**: Benchmarking gem ([2f40f3d](https://github.com/mruby/mruby/commit/2f40f3d))
- **mruby-strftime**: Time#strftime implementation ([b31e22f](https://github.com/mruby/mruby/commit/b31e22f))
## mruby-bin-mirb Improvements
- Custom multi-line editor replacing readline ([527018c](https://github.com/mruby/mruby/commit/527018c))
- Syntax highlighting for keywords, strings, result values, hash key symbols ([624272b](https://github.com/mruby/mruby/commit/624272b), [1713d4a](https://github.com/mruby/mruby/commit/1713d4a))
- Automatic light/dark theme detection via OSC 11 ([db4c8d9](https://github.com/mruby/mruby/commit/db4c8d9))
- Tab completion support ([2f15282](https://github.com/mruby/mruby/commit/2f15282))
- Colored output for prompts and errors ([b36e0b4](https://github.com/mruby/mruby/commit/b36e0b4))
- Auto-indentation and auto-dedent ([d52f318](https://github.com/mruby/mruby/commit/d52f318), [e901b6d](https://github.com/mruby/mruby/commit/e901b6d))
- Command history with Up/Down navigation ([5f85c1b](https://github.com/mruby/mruby/commit/5f85c1b))
- Line numbers in multi-line prompts ([5a3f0e2](https://github.com/mruby/mruby/commit/5a3f0e2))
- UTF-8 multibyte character support ([4a97da3](https://github.com/mruby/mruby/commit/4a97da3))
## mruby-bigint Improvements
- Toom-3 multiplication for large numbers ([99620804](https://github.com/mruby/mruby/commit/99620804))
- Karatsuba multiplication for medium-sized numbers ([85e81072](https://github.com/mruby/mruby/commit/85e81072))
- Balance multiplication for asymmetric operands ([0220ec2b](https://github.com/mruby/mruby/commit/0220ec2b))
- Divide-and-conquer optimization for `to_s` ([990ff90f](https://github.com/mruby/mruby/commit/990ff90f))
- Consolidated mpn layer for low-level limb operations ([9ef3362f](https://github.com/mruby/mruby/commit/9ef3362f))
- Always use 32-bit limbs by default ([c747c77f](https://github.com/mruby/mruby/commit/c747c77f))
## Other Gem Changes
- **_NOTE_**: `Hash#deconstruct_keys` removed for CRuby compatibility ([34b9412](https://github.com/mruby/mruby/commit/34b9412))
- **mruby-enum-lazy**: Fix `Lazy#flat_map` to handle non-enumerable block return values ([#6765](https://github.com/mruby/mruby/pull/6765))
- **mruby-array-ext**: Add `Array#find` and `Array#rfind` methods
- **mruby-io**: Add `IO#putc` and `Kernel#putc` ([baff6e6](https://github.com/mruby/mruby/commit/baff6e6))
- **mruby-random**: Replace xoshiro with PCG for better memory efficiency ([f1bab01](https://github.com/mruby/mruby/commit/f1bab01))
- **mruby-compiler**: Variable-sized AST nodes for reduced memory usage
- **mruby-compiler**: `no_return_value` context flag for script optimization ([613b03a](https://github.com/mruby/mruby/commit/613b03a))
- `initialize_copy` and `respond_to_missing?` defined as private ([#6708](https://github.com/mruby/mruby/pull/6708))
- Struct keyword argument initialization ([#6574](https://github.com/mruby/mruby/pull/6574))
# Compiler Improvements
- Variable-sized AST nodes for reduced memory consumption ([821b989](https://github.com/mruby/mruby/commit/821b989))
- Pattern matching bytecode optimizations ([21d4135](https://github.com/mruby/mruby/commit/21d4135))
- Optimized masgn to generate literals directly into target registers ([fb5d966](https://github.com/mruby/mruby/commit/fb5d966))
- Optimized splat of literal arrays in args/literals ([1cb8d73](https://github.com/mruby/mruby/commit/1cb8d73))
- Early termination after too many parse errors ([510ebd7](https://github.com/mruby/mruby/commit/510ebd7))
- Chunk array literals at 64 elements to reduce register pressure ([f98d641](https://github.com/mruby/mruby/commit/f98d641))
- Chunk `%w()` and `%i()` literals to reduce register pressure ([62cf0dc](https://github.com/mruby/mruby/commit/62cf0dc))
# VM Optimizations
New super-instructions that fuse common opcode sequences to reduce bytecode size and improve performance:
- `OP_SEND0`/`OP_SSEND0`: Zero-argument method call, avoiding argument count setup ([9123ef4](https://github.com/mruby/mruby/commit/9123ef4))
- `OP_TDEF`/`OP_SDEF`: Fused method definition combining TCLASS/SCLASS+METHOD+DEF into single instruction, saving 4 bytes per method ([8d4f47e](https://github.com/mruby/mruby/commit/8d4f47e))
- `OP_GETIDX0`: Fast path for `array[0]` and `Array#first` access ([680f7ec](https://github.com/mruby/mruby/commit/680f7ec))
- `OP_ADDILV`/`OP_SUBILV`: Local variable increment/decrement fusion for `i += n` patterns ([43f64b9](https://github.com/mruby/mruby/commit/43f64b9))
- `OP_RETSELF`: Single-byte instruction for `return self` pattern ([a71db8c](https://github.com/mruby/mruby/commit/a71db8c))
- `OP_RETNIL`: Single-byte instruction for `return nil` pattern ([64e30bf](https://github.com/mruby/mruby/commit/64e30bf))
- `OP_RETTRUE`/`OP_RETFALSE`: Single-byte instructions for `return true`/`return false` patterns ([0b15727](https://github.com/mruby/mruby/commit/0b15727))
- `OP_MATCHERR`: Pattern matching error with conditional execution ([944168a](https://github.com/mruby/mruby/commit/944168a))
- `OP_BLKCALL`: Direct block call for `yield`, bypassing method dispatch (13-17% faster) ([3aa2872](https://github.com/mruby/mruby/commit/3aa2872))
Other optimizations:
- 1.5x stack growth instead of linear growth for reduced reallocations ([f7988c93](https://github.com/mruby/mruby/commit/f7988c93))
- Skip keyword argument hash duplication ([5970e350](https://github.com/mruby/mruby/commit/5970e350))
# Fixed GitHub Issues
- [#5531](https://github.com/mruby/mruby/issues/5531) Hash recursion detection
- [#6506](https://github.com/mruby/mruby/issues/6506) Constant lookup in singleton class
- [#6507](https://github.com/mruby/mruby/issues/6507) tally multi-values
- [#6508](https://github.com/mruby/mruby/issues/6508) Enumerable#sum index
- [#6509](https://github.com/mruby/mruby/issues/6509) scope_new nregs initialization
- [#6515](https://github.com/mruby/mruby/issues/6515) y.tab.c in repository
- [#6516](https://github.com/mruby/mruby/issues/6516) Private backquote
- [#6554](https://github.com/mruby/mruby/issues/6554) Socket private #initialize
- [#6570](https://github.com/mruby/mruby/issues/6570) instance_eval crash
- [#6613](https://github.com/mruby/mruby/issues/6613) const_added hook during bootstrapping
- [#6635](https://github.com/mruby/mruby/issues/6635), [#6636](https://github.com/mruby/mruby/issues/6636) Colon3 constant lookup
- [#6637](https://github.com/mruby/mruby/issues/6637) arm64 mingw64 builtin setjmp/longjmp
- [#6642](https://github.com/mruby/mruby/issues/6642) Task segfault when sleep called from C
- [#6645](https://github.com/mruby/mruby/issues/6645) Set memory leak from double initialization
- [#6646](https://github.com/mruby/mruby/issues/6646) IO#gets negative length
- [#6647](https://github.com/mruby/mruby/issues/6647) IO#ungetc buffer overflow
- [#6648](https://github.com/mruby/mruby/issues/6648) sprintf buffer overread
- [#6649](https://github.com/mruby/mruby/issues/6649) Array#sort! use-after-realloc
- [#6650](https://github.com/mruby/mruby/issues/6650) Array#fill validation
- [#6652](https://github.com/mruby/mruby/issues/6652) Array comparison use-after-realloc
- [#6657](https://github.com/mruby/mruby/issues/6657) Exception handling for ||= on class variables
- [#6659](https://github.com/mruby/mruby/issues/6659) Super with keyword arguments
- [#6660](https://github.com/mruby/mruby/issues/6660) Regression on struct/array/hash == override with super
- [#6662](https://github.com/mruby/mruby/issues/6662) Array set operations use-after-free
- [#6664](https://github.com/mruby/mruby/issues/6664) Set#flatten memory leak
- [#6666](https://github.com/mruby/mruby/issues/6666) Regexp literal with encoding
- [#6668](https://github.com/mruby/mruby/issues/6668) Method#== for aliased methods and comparison bug
- [#6671](https://github.com/mruby/mruby/issues/6671) Separate inter-gem headers from external API headers
- [#6674](https://github.com/mruby/mruby/issues/6674) Document pattern matching limitations
- [#6675](https://github.com/mruby/mruby/issues/6675) Allow Hash#[] to be aliased again
- [#6687](https://github.com/mruby/mruby/issues/6687) Expand MRB_SYM/MRB_GVSYM support for symbols with special characters
- [#6698](https://github.com/mruby/mruby/issues/6698) Bigint tests fail on architectures other than x86_64 and i386
- [#6701](https://github.com/mruby/mruby/issues/6701) Heap-use-after-free in mrb_vm_exec involving mruby-rational / mruby-bigint
- [#6702](https://github.com/mruby/mruby/issues/6702) mruby-bigint doesn't compile in C++ project
- [#6704](https://github.com/mruby/mruby/issues/6704) Heap-buffer-overflow in mrb_vm_exec via malformed source code
- [#6705](https://github.com/mruby/mruby/issues/6705) Can't get outer class of an object in C
- [#6713](https://github.com/mruby/mruby/issues/6713) mruby-polarssl not work
- [#6720](https://github.com/mruby/mruby/issues/6720) Random float range: different behavior from CRuby
- [#6722](https://github.com/mruby/mruby/issues/6722) RBreak size overflow on 32-bit platforms with MRB_NO_BOXING
- [#6740](https://github.com/mruby/mruby/issues/6740) `%w()`/`%i()` register pressure with large literals
- [#6741](https://github.com/mruby/mruby/issues/6741) `case`/`in` without `else` should raise `NoMatchingPatternError`
- [#6760](https://github.com/mruby/mruby/issues/6760) `mrb_gc_unregister()` not removing all matching entries
# Merged Pull Requests
- [#6418](https://github.com/mruby/mruby/pull/6418) Add `ls-lint` with GitHub Actions
- [#6492](https://github.com/mruby/mruby/pull/6492) fix a typo, update specs
- [#6493](https://github.com/mruby/mruby/pull/6493) Fix TYPO in memory.md
- [#6495](https://github.com/mruby/mruby/pull/6495) Remove `MRB_ENDIAN_LOHI()` that is no longer in use
- [#6497](https://github.com/mruby/mruby/pull/6497) gha: update `build.yml` try `windows-2025` image
- [#6498](https://github.com/mruby/mruby/pull/6498) Clean up and standardize the pre-commit config
- [#6501](https://github.com/mruby/mruby/pull/6501) Update pre-commit Node.js version to `v22.14.0 LTS`
- [#6502](https://github.com/mruby/mruby/pull/6502) pre-commit: update prettier to the latest version
- [#6503](https://github.com/mruby/mruby/pull/6503) misc: fix typos
- [#6505](https://github.com/mruby/mruby/pull/6505) mrbgems: fix spelling
- [#6510](https://github.com/mruby/mruby/pull/6510) Fixed class method visibility via `module_function`
- [#6511](https://github.com/mruby/mruby/pull/6511) Exclude the external project "lrama" from pre-commit
- [#6513](https://github.com/mruby/mruby/pull/6513) mruby 3.4.0 released
- [#6517](https://github.com/mruby/mruby/pull/6517) core/codegen.c: remove unneeded duplicate semicolon
- [#6518](https://github.com/mruby/mruby/pull/6518) Change mrbc_args.flags bit width from 2 to 3
- [#6519](https://github.com/mruby/mruby/pull/6519) Add `tools/lrama` to `.prettierignore`
- [#6520](https://github.com/mruby/mruby/pull/6520) pre-commit: autoupdate and update node LTS version
- [#6521](https://github.com/mruby/mruby/pull/6521) Add codespell config file `.codespellrc`
- [#6522](https://github.com/mruby/mruby/pull/6522) gha: label more files
- [#6523](https://github.com/mruby/mruby/pull/6523) add `rand(Range)` and unify implementations of `Random#rand` and `Kernel#rand`
- [#6524](https://github.com/mruby/mruby/pull/6524) Fix Kernel#p when no argument
- [#6525](https://github.com/mruby/mruby/pull/6525) Skip adding empty input to mirb history
- [#6526](https://github.com/mruby/mruby/pull/6526) Add build config for Luckfox Pico embedded SBC
- [#6528](https://github.com/mruby/mruby/pull/6528) misc: fix spelling
- [#6530](https://github.com/mruby/mruby/pull/6530) Revert "class.c (find_visibility_scope): when callinfo returns, \*ep == NULL; #6512"
- [#6531](https://github.com/mruby/mruby/pull/6531) Improve method table performance by rehashing at 75% load factor
- [#6532](https://github.com/mruby/mruby/pull/6532) Reverted method table optimizations to prioritize memory savings
- [#6533](https://github.com/mruby/mruby/pull/6533) Fix calling `extended` callback
- [#6534](https://github.com/mruby/mruby/pull/6534) Add descriptive comment to mrb_read_float function
- [#6535](https://github.com/mruby/mruby/pull/6535) Added descriptive comments for functions/macros in src/mempool.c
- [#6536](https://github.com/mruby/mruby/pull/6536) Add descriptive comments to public functions in src/debug.c
- [#6537](https://github.com/mruby/mruby/pull/6537) Updated comments in `cdump.c` to remove the `@brief` tag
- [#6539](https://github.com/mruby/mruby/pull/6539) Add descriptive comments for functions in src/load.c
- [#6540](https://github.com/mruby/mruby/pull/6540) Add descriptive comments to MRB_API functions in object.c
- [#6541](https://github.com/mruby/mruby/pull/6541) Add descriptive comments for MRB_API functions in src/array.c
- [#6542](https://github.com/mruby/mruby/pull/6542) Add descriptive comments to MRB_API functions in src/symbol.c
- [#6543](https://github.com/mruby/mruby/pull/6543) Add descriptive comments to several functions in src/dump.c
- [#6544](https://github.com/mruby/mruby/pull/6544) Fix build strings that must be mutable
- [#6545](https://github.com/mruby/mruby/pull/6545) Add descriptive comments for MRB_API functions in src/class.c
- [#6548](https://github.com/mruby/mruby/pull/6548) Add descriptive comments to MRB_API functions in src/etc.c
- [#6549](https://github.com/mruby/mruby/pull/6549) Add descriptive comments to kernel functions
- [#6550](https://github.com/mruby/mruby/pull/6550) Add descriptive comments for MRB_API functions in src/proc.c
- [#6551](https://github.com/mruby/mruby/pull/6551) Add descriptive comments for MRB_API functions in src/state.c
- [#6552](https://github.com/mruby/mruby/pull/6552) Fix: Correct placement of comments in src/variable.c
- [#6553](https://github.com/mruby/mruby/pull/6553) Add descriptive comments for MRB_API functions in src/vm.c
- [#6555](https://github.com/mruby/mruby/pull/6555) `mrb_mt_foreach()` needs to update the pointer at each loop
- [#6556](https://github.com/mruby/mruby/pull/6556) `iv_foreach()` needs to update the pointer at each loop
- [#6560](https://github.com/mruby/mruby/pull/6560) Refactor: Improve Set GC marking and freeing
- [#6561](https://github.com/mruby/mruby/pull/6561) pre-commit updates and fix prettier entrypoint
- [#6562](https://github.com/mruby/mruby/pull/6562) misc: fix spelling word case
- [#6563](https://github.com/mruby/mruby/pull/6563) pre-commit add rubocop with one rule spaces for indentation
- [#6564](https://github.com/mruby/mruby/pull/6564) Remove jumanjihouse pre-commit hooks no longer maintained
- [#6565](https://github.com/mruby/mruby/pull/6565) Rubocop: fix target Ruby version; add two more cops; fix lint error
- [#6566](https://github.com/mruby/mruby/pull/6566) Removed unreferenced variables in `CrossBuild#run_bintest`
- [#6567](https://github.com/mruby/mruby/pull/6567) Avoid array object creation in `cmd_bin` method in bintest
- [#6568](https://github.com/mruby/mruby/pull/6568) mruby-bin-debugger depends on mruby-bin-mrbc in bintest
- [#6569](https://github.com/mruby/mruby/pull/6569) sed s/Mruby/MRuby/g
- [#6571](https://github.com/mruby/mruby/pull/6571) Update limitations.md to add behavior on small hash
- [#6572](https://github.com/mruby/mruby/pull/6572) Add Claude Code GitHub Workflow
- [#6573](https://github.com/mruby/mruby/pull/6573) pre-commit fixes and updates
- [#6574](https://github.com/mruby/mruby/pull/6574) Support initializing structs via keyword arguments
- [#6575](https://github.com/mruby/mruby/pull/6575) Fix typo in file time methods
- [#6581](https://github.com/mruby/mruby/pull/6581) Merge `mrb_obj_iv_inspect()` into `mrb_obj_inspect()`
- [#6582](https://github.com/mruby/mruby/pull/6582) Stricter type tag in `mrb_obj_alloc()`
- [#6583](https://github.com/mruby/mruby/pull/6583) Add fallback to local build_config.rb before using default configuration
- [#6585](https://github.com/mruby/mruby/pull/6585) Fix typo in mruby3.2 docs
- [#6586](https://github.com/mruby/mruby/pull/6586) Makefile: refactor add docs and add command line `help` target
- [#6587](https://github.com/mruby/mruby/pull/6587) Add Set#hash tests
- [#6588](https://github.com/mruby/mruby/pull/6588) Add CodeQL Analysis for GitHub Actions
- [#6589](https://github.com/mruby/mruby/pull/6589) Add pre-commit hook `check-zip-file-is-not-committed`
- [#6591](https://github.com/mruby/mruby/pull/6591) mruby-eval fix license link in README
- [#6593](https://github.com/mruby/mruby/pull/6593) README: Add Contributors Avatars, Star History, Table of Contents
- [#6598](https://github.com/mruby/mruby/pull/6598) Fix heap buffer overflow in `#method_missing`
- [#6599](https://github.com/mruby/mruby/pull/6599) pre-commit: run `markdown-link-check`, `oxipng`, `prettier` manually
- [#6600](https://github.com/mruby/mruby/pull/6600) `dreamcast_shelf build config`: update to use KallistiOS wrappers
- [#6601](https://github.com/mruby/mruby/pull/6601) fix: skip local build_config.rb when working in MRUBY_ROOT
- [#6602](https://github.com/mruby/mruby/pull/6602) Improved iseq annotations for `new` and `!=`
- [#6604](https://github.com/mruby/mruby/pull/6604) pre-commit config updates
- [#6607](https://github.com/mruby/mruby/pull/6607) fix bigint on raspberry pi
- [#6610](https://github.com/mruby/mruby/pull/6610) Extract golden ratio prime into constant
- [#6614](https://github.com/mruby/mruby/pull/6614) Fix uninitialized variable in io_gets causing segmentation fault
- [#6617](https://github.com/mruby/mruby/pull/6617) Fix various minor problems and speed up build
- [#6618](https://github.com/mruby/mruby/pull/6618) Stop generating unnecessary C++ files in mruby-bin-mruby
- [#6621](https://github.com/mruby/mruby/pull/6621) Set up all GEMS before mruby core tasks definition
- [#6624](https://github.com/mruby/mruby/pull/6624) Fixed wrong `MRuby::Build.current` at the top level of `mrbgem.rake`
- [#6628](https://github.com/mruby/mruby/pull/6628) Revert `File.absolute_path` logic
- [#6629](https://github.com/mruby/mruby/pull/6629) pre-commit update
- [#6631](https://github.com/mruby/mruby/pull/6631) Revert "Rakefile: make the whole thing parallel unless SERIAL=1"
- [#6633](https://github.com/mruby/mruby/pull/6633) Fix a heap-buffer-overflow in str strip! methods
- [#6643](https://github.com/mruby/mruby/pull/6643) Fix crash caused by an incorrect node type check in `codegen_masgn`
- [#6651](https://github.com/mruby/mruby/pull/6651) Address stack-use-after-return in the mruby bigint implementation
- [#6653](https://github.com/mruby/mruby/pull/6653) Improve HAL-related components for MinGW
- [#6655](https://github.com/mruby/mruby/pull/6655) Preventing Memory Leaks in `Array#__combination_init`
- [#6656](https://github.com/mruby/mruby/pull/6656) Fix integer overflow in allocation size calculation
- [#6663](https://github.com/mruby/mruby/pull/6663) Added the `kh_is_end()` macro function
- [#6665](https://github.com/mruby/mruby/pull/6665) Fixed use-after-free with `Set#join`
- [#6670](https://github.com/mruby/mruby/pull/6670) Arranging VM dispatch macros
- [#6673](https://github.com/mruby/mruby/pull/6673) Adjust broken license links; clean up Markdown
- [#6677](https://github.com/mruby/mruby/pull/6677) gha: run pre-commit with `--color=always`
- [#6678](https://github.com/mruby/mruby/pull/6678) Put ls-lint and pre-commit in separate workflow files
- [#6679](https://github.com/mruby/mruby/pull/6679) pre-commit autoupdate; update node and prettier
- [#6681](https://github.com/mruby/mruby/pull/6681) Add Cosmopolitan Libc build configuration
- [#6689](https://github.com/mruby/mruby/pull/6689) docs: fix pre-commit manual hooks; fix link
- [#6694](https://github.com/mruby/mruby/pull/6694) Fix mirb build under Cosmopolitan
- [#6695](https://github.com/mruby/mruby/pull/6695) Dependabot: add a cooldown period for new releases
- [#6696](https://github.com/mruby/mruby/pull/6696) Fix parse error with required kwargs and omitted parens
- [#6699](https://github.com/mruby/mruby/pull/6699) Fix mruby-task for PicoRuby Integration
- [#6700](https://github.com/mruby/mruby/pull/6700) Fix float/double pack/unpack on s390x
- [#6706](https://github.com/mruby/mruby/pull/6706) Refactor task class to use symbol IDs
- [#6708](https://github.com/mruby/mruby/pull/6708) `initialize_copy` and `respond_to_missing?` defined as private
- [#6709](https://github.com/mruby/mruby/pull/6709) Add the `MRB_ENSURE()` macro
- [#6711](https://github.com/mruby/mruby/pull/6711) Fix out of bounds read and write in IO.select
- [#6714](https://github.com/mruby/mruby/pull/6714) Fix OP_DEBUG operand type and add NULL check for debug_op_hook
- [#6716](https://github.com/mruby/mruby/pull/6716) Fixes identity for proc object
- [#6717](https://github.com/mruby/mruby/pull/6717) Fix mruby-task: wrapping by critical section and setting initial task receiver
- [#6718](https://github.com/mruby/mruby/pull/6718) Add installation instructions for conda and Homebrew
- [#6723](https://github.com/mruby/mruby/pull/6723) Add `RInteger` and `RFloat` to `RVALUE`
- [#6727](https://github.com/mruby/mruby/pull/6727) Language documentation: update wording of "overloading" section
- [#6729](https://github.com/mruby/mruby/pull/6729) Simplifying dependency addition for gensym task
- [#6730](https://github.com/mruby/mruby/pull/6730) Simplifying presym file generation actions
- [#6733](https://github.com/mruby/mruby/pull/6733) Include `mruby/presym.h` for all source files
- [#6734](https://github.com/mruby/mruby/pull/6734) Chunk array literals at 64 elements to reduce register pressure
- [#6735](https://github.com/mruby/mruby/pull/6735) Prevent full recompilation without changes to presym file
- [#6739](https://github.com/mruby/mruby/pull/6739) Fix MSYS2 build error with drive letters
- [#6743](https://github.com/mruby/mruby/pull/6743) Chunk `%w()` and `%i()` literals to reduce register pressure
- [#6744](https://github.com/mruby/mruby/pull/6744) Raise `NoMatchingPatternError` in `case`/`in` without `else`
- [#6747](https://github.com/mruby/mruby/pull/6747) Correctly handle empty hash as default named argument
- [#6749](https://github.com/mruby/mruby/pull/6749) Fix microcontroller profile
- [#6750](https://github.com/mruby/mruby/pull/6750) Fix out-of-bounds read and divide-by-zero in `Array#product`
- [#6752](https://github.com/mruby/mruby/pull/6752) Fix `attr_reader`-generated methods accepting extra arguments
- [#6753](https://github.com/mruby/mruby/pull/6753) Further optimize `Array#product`
- [#6754](https://github.com/mruby/mruby/pull/6754) Mark `attr_reader` procs as noarg
- [#6755](https://github.com/mruby/mruby/pull/6755) Reload `ci` after `mrb_hash_delete_key()` in keyword argument handling
- [#6756](https://github.com/mruby/mruby/pull/6756) Avoid impact of object modifications caused by `mrb_vm_exec()` calls
- [#6758](https://github.com/mruby/mruby/pull/6758) Don't assign result of `mrb_funcall()` directly to `regs`
- [#6759](https://github.com/mruby/mruby/pull/6759) Define `mrb_bigint_p()` always
- [#6761](https://github.com/mruby/mruby/pull/6761) Fix `mrb_gc_unregister()` to remove all matching entries
- [#6762](https://github.com/mruby/mruby/pull/6762) Write generated test C files atomically to avoid build race condition
- [#6765](https://github.com/mruby/mruby/pull/6765) Fix `Lazy#flat_map` to handle non-enumerable block return values
- [#6767](https://github.com/mruby/mruby/pull/6767) Allow compound statement in parenthesized argument context
- [#6780](https://github.com/mruby/mruby/pull/6780) Fix `String#prepend` with self-referencing arguments
- [#6781](https://github.com/mruby/mruby/pull/6781) Protect `sprintf` format string from mutation during callbacks
- [#6783](https://github.com/mruby/mruby/pull/6783) Pin GitHub Actions workflows to commit hashes
# Security Fixes
- Buffer overflow in bigint uadd ([3f2611e](https://github.com/mruby/mruby/commit/3f2611e))
- Stack buffer overflow in Montgomery reduction ([edce0a3](https://github.com/mruby/mruby/commit/edce0a3))
- Buffer overflow in pack_uu encoding ([2993302](https://github.com/mruby/mruby/commit/2993302))
- Buffer overflow in IO#ungetc ([01ab2ff](https://github.com/mruby/mruby/commit/01ab2ff))
- Heap-buffer-overflow in pattern alternation codegen ([eea9e30](https://github.com/mruby/mruby/commit/eea9e30))
- Out of bounds read and write in IO.select ([44831711](https://github.com/mruby/mruby/commit/44831711))
- Off-by-one in bounds check for symbol names and pool strings in load.c ([b3b8c01](https://github.com/mruby/mruby/commit/b3b8c01))
- Use-after-free in Set operations ([a6b55e7](https://github.com/mruby/mruby/commit/a6b55e7))
- Use-after-free in Array set operations ([729b84c](https://github.com/mruby/mruby/commit/729b84c))
- Use-after-free in Set#join ([0e653eb](https://github.com/mruby/mruby/commit/0e653eb))
- Use-after-realloc in Array#sort! ([eb39897](https://github.com/mruby/mruby/commit/eb39897))
- Heap-use-after-free in insertion_sort ([099d2c47](https://github.com/mruby/mruby/commit/099d2c47))
- Integer overflow in str_check_length ([6afff1c3](https://github.com/mruby/mruby/commit/6afff1c3))
- Integer overflow in Integer#lcm ([070bef24](https://github.com/mruby/mruby/commit/070bef24))
- Heap buffer overflow in `#method_missing` ([550d10a](https://github.com/mruby/mruby/commit/550d10a))
- Out-of-bounds read and divide-by-zero in `Array#product` ([8441eaf](https://github.com/mruby/mruby/commit/8441eaf))
- Heap buffer overflow in `String#prepend` with self-referencing arguments ([18ba026](https://github.com/mruby/mruby/commit/18ba026))
- Use-after-free in `sprintf` via `to_s` callback mutating format string ([48fc422](https://github.com/mruby/mruby/commit/48fc422))
- Multiple memory leak fixes in bigint, Set, Array, and Task gems
@@ -15,11 +15,6 @@
*/ */
#include <mruby/internal.h> #include <mruby/internal.h>
/*
* The "mruby/presym.h" file is placed at the end of the mruby header file.
*/
#include <mruby/presym.h>
/* /*
* Define your own struct RBigint. * Define your own struct RBigint.
* *
+4 -4
View File
@@ -138,8 +138,8 @@
/* turn off generational GC by default */ /* turn off generational GC by default */
//#define MRB_GC_TURN_OFF_GENERATIONAL //#define MRB_GC_TURN_OFF_GENERATIONAL
/* default size of khash table bucket */ /* initial size of khash table bucket */
//#define KHASH_DEFAULT_SIZE 32 //#define KHASH_INITIAL_SIZE 32
/* allocated memory address alignment */ /* allocated memory address alignment */
//#define POOL_ALIGNMENT 4 //#define POOL_ALIGNMENT 4
@@ -208,8 +208,8 @@
# define MRB_NO_METHOD_CACHE # define MRB_NO_METHOD_CACHE
# endif # endif
# ifndef KHASH_DEFAULT_SIZE # ifndef KHASH_INITIAL_SIZE
# define KHASH_DEFAULT_SIZE 16 # define KHASH_INITIAL_SIZE 16
# endif # endif
# ifndef MRB_HEAP_PAGE_SIZE # ifndef MRB_HEAP_PAGE_SIZE
+3 -1
View File
@@ -1015,7 +1015,7 @@ typedef const char *mrb_args_format;
* mrb_value str, kw_rest; * mrb_value str, kw_rest;
* uint32_t kw_num = 3; * uint32_t kw_num = 3;
* uint32_t kw_required = 1; * uint32_t kw_required = 1;
* // Note that `#include <mruby/presym.h>` is required beforehand because `MRB_SYM()` is used. * // `MRB_SYM()` is available via `mruby.h` (which includes `mruby/presym.h`).
* // If the usage of `MRB_SYM()` is not desired, replace it with `mrb_intern_lit()`. * // If the usage of `MRB_SYM()` is not desired, replace it with `mrb_intern_lit()`.
* mrb_sym kw_names[] = { MRB_SYM(x), MRB_SYM(y), MRB_SYM(z) }; * mrb_sym kw_names[] = { MRB_SYM(x), MRB_SYM(y), MRB_SYM(z) };
* mrb_value kw_values[kw_num]; * mrb_value kw_values[kw_num];
@@ -1594,6 +1594,8 @@ MRB_API mrb_value mrb_format(mrb_state *mrb, const char *format, ...);
#ifdef MRB_PRESYM_SCANNING #ifdef MRB_PRESYM_SCANNING
# include <mruby/presym/scanning.h> # include <mruby/presym/scanning.h>
#else
# include <mruby/presym.h>
#endif #endif
#if 0 #if 0
+1 -1
View File
@@ -21,7 +21,7 @@ typedef uint32_t khint_t;
typedef khint_t khiter_t; typedef khint_t khiter_t;
#ifndef KHASH_INITIAL_SIZE #ifndef KHASH_INITIAL_SIZE
# define KHASH_INITIAL_SIZE 8 # define KHASH_INITIAL_SIZE 32
#endif #endif
#define KHASH_MIN_SIZE 8 #define KHASH_MIN_SIZE 8
#define KHASH_SMALL_LIMIT 4 #define KHASH_SMALL_LIMIT 4
+4
View File
@@ -316,7 +316,11 @@ struct RCptr {
#endif #endif
#define mrb_test(o) mrb_bool(o) #define mrb_test(o) mrb_bool(o)
#ifndef mrb_bigint_p #ifndef mrb_bigint_p
#ifdef MRB_USE_BIGINT
#define mrb_bigint_p(o) (mrb_type(o) == MRB_TT_BIGINT) #define mrb_bigint_p(o) (mrb_type(o) == MRB_TT_BIGINT)
#else
#define mrb_bigint_p(o) FALSE
#endif
#endif #endif
/** /**
+3 -3
View File
@@ -57,7 +57,7 @@ MRB_BEGIN_DECL
/* /*
* Patch level string. (optional) * Patch level string. (optional)
*/ */
#define MRUBY_PATCHLEVEL_STR "RC" #define MRUBY_PATCHLEVEL_STR ""
#ifndef MRUBY_PATCHLEVEL_STR #ifndef MRUBY_PATCHLEVEL_STR
# if MRUBY_PATCHLEVEL < 0 # if MRUBY_PATCHLEVEL < 0
@@ -85,12 +85,12 @@ MRB_BEGIN_DECL
/* /*
* Release month. * Release month.
*/ */
#define MRUBY_RELEASE_MONTH 3 #define MRUBY_RELEASE_MONTH 4
/* /*
* Release day. * Release day.
*/ */
#define MRUBY_RELEASE_DAY 5 #define MRUBY_RELEASE_DAY 20
/* /*
* Release date as a string. * Release date as a string.
+2 -1
View File
@@ -109,7 +109,8 @@ module MRuby
if build.kind_of?(MRuby::CrossBuild) if build.kind_of?(MRuby::CrossBuild)
return %w(x86_64-w64-mingw32 i686-w64-mingw32).include?(build.host_target) return %w(x86_64-w64-mingw32 i686-w64-mingw32).include?(build.host_target)
elsif build.kind_of?(MRuby::Build) elsif build.kind_of?(MRuby::Build)
return ('A'..'Z').to_a.any? { |vol| Dir.exist?("#{vol}:") } return ('A'..'Z').to_a.any? { |vol| Dir.exist?("#{vol}:") } ||
('a'..'z').to_a.any? { |vol| Dir.exist?("/#{vol}/") }
end end
return false return false
end end
@@ -11,7 +11,6 @@
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/class.h> #include <mruby/class.h>
#include <mruby/error.h> #include <mruby/error.h>
#include <mruby/presym.h>
#include "socket_hal.h" #include "socket_hal.h"
#include <sys/types.h> #include <sys/types.h>
-1
View File
@@ -15,7 +15,6 @@
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/class.h> #include <mruby/class.h>
#include <mruby/error.h> #include <mruby/error.h>
#include <mruby/presym.h>
#include "socket_hal.h" #include "socket_hal.h"
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
+7 -29
View File
@@ -611,37 +611,15 @@ class Array
# ary.product(*arys) -> array # ary.product(*arys) -> array
# ary.product(*arys) { |item| ... } -> self # ary.product(*arys) { |item| ... } -> self
def product(*arys, &block) def product(*arys, &block)
size = arys.size gen = __product_generate(arys, &block)
i = size return gen unless block
while i > 0
i -= 1 if gen
unless arys[i].kind_of?(Array) while group = __product_next(arys, gen)
raise TypeError, "no implicit conversion into Array" yield group
end end
end end
self
i = size
total = self.size
total *= arys[i -= 1].size while i > 0
if block
i = 0
while i < total
group = self.__product_group(arys, i, size + 1)
block.call(group)
i += 1
end
return self
else
result = [nil] * total
i = 0
while i < total
group = self.__product_group(arys, i, size + 1)
result[i] = group
i += 1
end
return result
end
end end
## ##
+147 -42
View File
@@ -6,8 +6,8 @@
#include <mruby/hash.h> #include <mruby/hash.h>
#include <mruby/data.h> #include <mruby/data.h>
#include <mruby/class.h> #include <mruby/class.h>
#include <mruby/numeric.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#include <mruby/khash.h> #include <mruby/khash.h>
#include <mruby/error.h> #include <mruby/error.h>
@@ -79,11 +79,14 @@ ary_assoc(mrb_state *mrb, mrb_value ary)
{ {
mrb_value k = mrb_get_arg1(mrb); mrb_value k = mrb_get_arg1(mrb);
int ai = mrb_gc_arena_save(mrb);
for (mrb_int i = 0; i < RARRAY_LEN(ary); i++) { for (mrb_int i = 0; i < RARRAY_LEN(ary); i++) {
mrb_value v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]); mrb_value v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]);
mrb_gc_protect(mrb, v); // v may be removed from ary by mrb_equal()
if (!mrb_nil_p(v) && RARRAY_LEN(v) > 0 && if (!mrb_nil_p(v) && RARRAY_LEN(v) > 0 &&
mrb_equal(mrb, RARRAY_PTR(v)[0], k)) mrb_equal(mrb, RARRAY_PTR(v)[0], k))
return v; return v;
mrb_gc_arena_restore(mrb, ai);
} }
return mrb_nil_value(); return mrb_nil_value();
} }
@@ -107,12 +110,15 @@ ary_rassoc(mrb_state *mrb, mrb_value ary)
{ {
mrb_value value = mrb_get_arg1(mrb); mrb_value value = mrb_get_arg1(mrb);
int ai = mrb_gc_arena_save(mrb);
for (mrb_int i = 0; i < RARRAY_LEN(ary); i++) { for (mrb_int i = 0; i < RARRAY_LEN(ary); i++) {
mrb_value v = RARRAY_PTR(ary)[i]; mrb_value v = RARRAY_PTR(ary)[i];
mrb_gc_protect(mrb, v); // v may be removed from ary by mrb_equal()
if (mrb_array_p(v) && if (mrb_array_p(v) &&
RARRAY_LEN(v) > 1 && RARRAY_LEN(v) > 1 &&
mrb_equal(mrb, RARRAY_PTR(v)[1], value)) mrb_equal(mrb, RARRAY_PTR(v)[1], value))
return v; return v;
mrb_gc_arena_restore(mrb, ai);
} }
return mrb_nil_value(); return mrb_nil_value();
} }
@@ -410,9 +416,12 @@ ary_init_temp_set(mrb_state *mrb, ary_set_t *set, mrb_int capacity)
static void static void
ary_populate_temp_set(mrb_state *mrb, ary_set_t *set, mrb_value ary) ary_populate_temp_set(mrb_state *mrb, ary_set_t *set, mrb_value ary)
{ {
mrb_int len = RARRAY_LEN(ary); int ai = mrb_gc_arena_save(mrb);
for (mrb_int i = 0; i < len; i++) { for (mrb_int i = 0; i < RARRAY_LEN(ary); i++) {
kh_put(ary_set, mrb, set, RARRAY_PTR(ary)[i]); mrb_value p = RARRAY_PTR(ary)[i];
mrb_gc_protect(mrb, p); // p may be removed from ary by kh_put(ary_set, ...)
kh_put(ary_set, mrb, set, p);
mrb_gc_arena_restore(mrb, ai);
} }
} }
@@ -461,12 +470,15 @@ ary_subtract_body(mrb_state *mrb, void *data)
ary_populate_temp_set(mrb, ctx->set, ctx->argv[i]); ary_populate_temp_set(mrb, ctx->set, ctx->argv[i]);
} }
int ai = mrb_gc_arena_save(mrb);
for (mrb_int i = 0; i < RARRAY_LEN(ctx->self); i++) { for (mrb_int i = 0; i < RARRAY_LEN(ctx->self); i++) {
mrb_value p = RARRAY_PTR(ctx->self)[i]; mrb_value p = RARRAY_PTR(ctx->self)[i];
mrb_gc_protect(mrb, p); // p may be removed from self by kh_get(ary_set, ...)
khiter_t k = kh_get(ary_set, mrb, ctx->set, p); khiter_t k = kh_get(ary_set, mrb, ctx->set, p);
if (kh_is_end(ctx->set, k)) { /* key doesn't exist in any ary */ if (kh_is_end(ctx->set, k)) { /* key doesn't exist in any ary */
mrb_ary_push(mrb, ctx->result, p); mrb_ary_push(mrb, ctx->result, p);
} }
mrb_gc_arena_restore(mrb, ai);
} }
return ctx->result; return ctx->result;
@@ -500,13 +512,13 @@ ary_subtract_internal(mrb_state *mrb, mrb_value self, mrb_int argc, const mrb_va
} }
} }
else { else {
mrb_int self_len = RARRAY_LEN(self); int ai = mrb_gc_arena_save(mrb);
for (mrb_int i = 0; i < self_len; i++) { for (mrb_int i = 0; i < RARRAY_LEN(self); i++) {
mrb_value p = RARRAY_PTR(self)[i]; mrb_value p = RARRAY_PTR(self)[i];
mrb_gc_protect(mrb, p); // p may be removed from self by mrb_equal()
mrb_bool found = FALSE; mrb_bool found = FALSE;
for (mrb_int j = 0; j < argc; j++) { for (mrb_int j = 0; j < argc; j++) {
mrb_int len = RARRAY_LEN(argv[j]); for (mrb_int k = 0; k < RARRAY_LEN(argv[j]); k++) {
for (mrb_int k = 0; k < len; k++) {
if (mrb_equal(mrb, p, RARRAY_PTR(argv[j])[k])) { if (mrb_equal(mrb, p, RARRAY_PTR(argv[j])[k])) {
found = TRUE; found = TRUE;
break; break;
@@ -517,6 +529,7 @@ ary_subtract_internal(mrb_state *mrb, mrb_value self, mrb_int argc, const mrb_va
if (!found) { if (!found) {
mrb_ary_push(mrb, result, p); mrb_ary_push(mrb, result, p);
} }
mrb_gc_arena_restore(mrb, ai);
} }
} }
@@ -560,12 +573,10 @@ ary_difference(mrb_state *mrb, mrb_value self)
return ary_subtract_internal(mrb, self, argc, argv); return ary_subtract_internal(mrb, self, argc, argv);
} }
static void static void
add_uniq(mrb_state *mrb, mrb_value item, mrb_value result) add_uniq(mrb_state *mrb, mrb_value item, mrb_value result)
{ {
const mrb_int len = RARRAY_LEN(result); for (mrb_int i = 0; i < RARRAY_LEN(result); i++) {
for (mrb_int i = 0; i < len; i++) {
if (mrb_eql(mrb, item, RARRAY_PTR(result)[i])) { if (mrb_eql(mrb, item, RARRAY_PTR(result)[i])) {
return; return;
} }
@@ -585,15 +596,18 @@ static mrb_value
ary_union_body(mrb_state *mrb, void *data) ary_union_body(mrb_state *mrb, void *data)
{ {
struct ary_union_ctx *ctx = (struct ary_union_ctx *)data; struct ary_union_ctx *ctx = (struct ary_union_ctx *)data;
int ai = mrb_gc_arena_save(mrb);
/* Add unique elements from self */ /* Add unique elements from self */
for (mrb_int i = 0; i < RARRAY_LEN(ctx->self_copy); i++) { for (mrb_int i = 0; i < RARRAY_LEN(ctx->self_copy); i++) {
mrb_value elem = RARRAY_PTR(ctx->self_copy)[i]; mrb_value elem = RARRAY_PTR(ctx->self_copy)[i];
mrb_gc_protect(mrb, elem); // elem may be removed from self_copy by kh_get(ary_set, ...)
khiter_t k = kh_get(ary_set, mrb, ctx->set, elem); khiter_t k = kh_get(ary_set, mrb, ctx->set, elem);
if (kh_is_end(ctx->set, k)) { if (kh_is_end(ctx->set, k)) {
kh_put(ary_set, mrb, ctx->set, elem); kh_put(ary_set, mrb, ctx->set, elem);
mrb_ary_push(mrb, ctx->result, elem); mrb_ary_push(mrb, ctx->result, elem);
} }
mrb_gc_arena_restore(mrb, ai);
} }
/* Add unique elements from others */ /* Add unique elements from others */
@@ -601,11 +615,13 @@ ary_union_body(mrb_state *mrb, void *data)
mrb_value other = ctx->argv[i]; mrb_value other = ctx->argv[i];
for (mrb_int j = 0; j < RARRAY_LEN(other); j++) { for (mrb_int j = 0; j < RARRAY_LEN(other); j++) {
mrb_value elem = RARRAY_PTR(other)[j]; mrb_value elem = RARRAY_PTR(other)[j];
mrb_gc_protect(mrb, elem); // elem may be removed from other by kh_get(ary_set, ...)
khiter_t k = kh_get(ary_set, mrb, ctx->set, elem); khiter_t k = kh_get(ary_set, mrb, ctx->set, elem);
if (kh_is_end(ctx->set, k)) { if (kh_is_end(ctx->set, k)) {
kh_put(ary_set, mrb, ctx->set, elem); kh_put(ary_set, mrb, ctx->set, elem);
mrb_ary_push(mrb, ctx->result, elem); mrb_ary_push(mrb, ctx->result, elem);
} }
mrb_gc_arena_restore(mrb, ai);
} }
} }
@@ -637,19 +653,25 @@ ary_union_internal(mrb_state *mrb, mrb_value self, mrb_int argc, const mrb_value
} }
} }
else { else {
int ai = mrb_gc_arena_save(mrb);
/* Use linear search for small arrays */ /* Use linear search for small arrays */
/* Add unique elements from self */ /* Add unique elements from self */
mrb_int alen = RARRAY_LEN(self); for (mrb_int i = 0; i < RARRAY_LEN(self); i++) {
for (mrb_int i = 0; i < alen; i++) { mrb_value p = RARRAY_PTR(self)[i];
add_uniq(mrb, RARRAY_PTR(self)[i], result); mrb_gc_protect(mrb, p); // p may be removed from self by add_uniq()
add_uniq(mrb, p, result);
mrb_gc_arena_restore(mrb, ai);
} }
/* Add unique elements from others */ /* Add unique elements from others */
for (mrb_int i = 0; i < argc; i++) { for (mrb_int i = 0; i < argc; i++) {
mrb_value other = argv[i]; mrb_value other = argv[i];
mrb_int olen = RARRAY_LEN(other); for (mrb_int j = 0; j < RARRAY_LEN(other); j++) {
for (mrb_int j = 0; j < olen; j++) { mrb_value p = RARRAY_PTR(other)[j];
add_uniq(mrb, RARRAY_PTR(other)[j], result); mrb_gc_protect(mrb, p); // p may be removed from other by add_uniq()
add_uniq(mrb, p, result);
mrb_gc_arena_restore(mrb, ai);
} }
} }
} }
@@ -712,13 +734,16 @@ ary_intersection_body(mrb_state *mrb, void *data)
ary_populate_temp_set(mrb, ctx->set, ctx->argv[i]); ary_populate_temp_set(mrb, ctx->set, ctx->argv[i]);
} }
int ai = mrb_gc_arena_save(mrb);
for (mrb_int i = 0; i < RARRAY_LEN(ctx->self); i++) { for (mrb_int i = 0; i < RARRAY_LEN(ctx->self); i++) {
mrb_value p = RARRAY_PTR(ctx->self)[i]; mrb_value p = RARRAY_PTR(ctx->self)[i];
mrb_gc_protect(mrb, p); // p may be removed from self by kh_get(ary_set, ...)
khiter_t k = kh_get(ary_set, mrb, ctx->set, p); khiter_t k = kh_get(ary_set, mrb, ctx->set, p);
if (!kh_is_end(ctx->set, k)) { if (!kh_is_end(ctx->set, k)) {
mrb_ary_push(mrb, ctx->result, p); mrb_ary_push(mrb, ctx->result, p);
kh_del(ary_set, mrb, ctx->set, k); kh_del(ary_set, mrb, ctx->set, k);
} }
mrb_gc_arena_restore(mrb, ai);
} }
return ctx->result; return ctx->result;
@@ -752,15 +777,15 @@ ary_intersection_internal(mrb_state *mrb, mrb_value self, mrb_int argc, const mr
} }
} }
else { else {
mrb_int self_len = RARRAY_LEN(self); int ai = mrb_gc_arena_save(mrb);
for (mrb_int i = 0; i < self_len; i++) { for (mrb_int i = 0; i < RARRAY_LEN(self); i++) {
mrb_value p = RARRAY_PTR(self)[i]; mrb_value p = RARRAY_PTR(self)[i];
mrb_gc_protect(mrb, p); // p may be removed from self by mrb_equal()
mrb_bool found_in_all = TRUE; mrb_bool found_in_all = TRUE;
for (mrb_int j = 0; j < argc; j++) { for (mrb_int j = 0; j < argc; j++) {
mrb_bool found_in_current_other = FALSE; mrb_bool found_in_current_other = FALSE;
mrb_int len = RARRAY_LEN(argv[j]); for (mrb_int k = 0; k < RARRAY_LEN(argv[j]); k++) {
for (mrb_int k = 0; k < len; k++) {
if (mrb_equal(mrb, p, RARRAY_PTR(argv[j])[k])) { if (mrb_equal(mrb, p, RARRAY_PTR(argv[j])[k])) {
found_in_current_other = TRUE; found_in_current_other = TRUE;
break; break;
@@ -774,8 +799,7 @@ ary_intersection_internal(mrb_state *mrb, mrb_value self, mrb_int argc, const mr
if (found_in_all) { if (found_in_all) {
mrb_bool already_added = FALSE; mrb_bool already_added = FALSE;
mrb_int result_len = RARRAY_LEN(result); for (mrb_int j = 0; j < RARRAY_LEN(result); j++) {
for (mrb_int j = 0; j < result_len; j++) {
if (mrb_equal(mrb, p, RARRAY_PTR(result)[j])) { if (mrb_equal(mrb, p, RARRAY_PTR(result)[j])) {
already_added = TRUE; already_added = TRUE;
break; break;
@@ -785,6 +809,7 @@ ary_intersection_internal(mrb_state *mrb, mrb_value self, mrb_int argc, const mr
mrb_ary_push(mrb, result, p); mrb_ary_push(mrb, result, p);
} }
} }
mrb_gc_arena_restore(mrb, ai);
} }
} }
return result; return result;
@@ -855,8 +880,12 @@ ary_intersect_p_body(mrb_state *mrb, void *data)
ary_populate_temp_set(mrb, ctx->set, ctx->shorter_ary_copy); ary_populate_temp_set(mrb, ctx->set, ctx->shorter_ary_copy);
int ai = mrb_gc_arena_save(mrb);
for (mrb_int i = 0; i < RARRAY_LEN(ctx->longer_ary); i++) { for (mrb_int i = 0; i < RARRAY_LEN(ctx->longer_ary); i++) {
khiter_t k = kh_get(ary_set, mrb, ctx->set, RARRAY_PTR(ctx->longer_ary)[i]); mrb_value p = RARRAY_PTR(ctx->longer_ary)[i];
mrb_gc_protect(mrb, p); // p may be removed from longer_ary by kh_get(ary_set, ...)
khiter_t k = kh_get(ary_set, mrb, ctx->set, p);
mrb_gc_arena_restore(mrb, ai);
if (!kh_is_end(ctx->set, k)) { if (!kh_is_end(ctx->set, k)) {
*ctx->found = TRUE; *ctx->found = TRUE;
break; break;
@@ -906,12 +935,16 @@ ary_intersect_p(mrb_state *mrb, mrb_value self)
} }
} }
else { else {
int ai = mrb_gc_arena_save(mrb);
for (mrb_int i = 0; i < RARRAY_LEN(longer_ary); i++) { for (mrb_int i = 0; i < RARRAY_LEN(longer_ary); i++) {
mrb_value p = RARRAY_PTR(longer_ary)[i];
mrb_gc_protect(mrb, p); // p may be removed from longer_ary by mrb_equal()
for (mrb_int j = 0; j < RARRAY_LEN(shorter_ary); j++) { for (mrb_int j = 0; j < RARRAY_LEN(shorter_ary); j++) {
if (mrb_equal(mrb, RARRAY_PTR(longer_ary)[i], RARRAY_PTR(shorter_ary)[j])) { if (mrb_equal(mrb, p, RARRAY_PTR(shorter_ary)[j])) {
return mrb_true_value(); return mrb_true_value();
} }
} }
mrb_gc_arena_restore(mrb, ai);
} }
} }
@@ -1042,6 +1075,7 @@ ary_fill_exec(mrb_state *mrb, mrb_value self)
} }
/* Fill the array */ /* Fill the array */
mrb_ary_modify(mrb, ary);
mrb_value *ptr = ARY_PTR(ary) + start; mrb_value *ptr = ARY_PTR(ary) + start;
for (mrb_int i = 0; i < length; i++) { for (mrb_int i = 0; i < length; i++) {
ptr[i] = obj; ptr[i] = obj;
@@ -1059,7 +1093,6 @@ struct ary_uniq_bang_ctx {
mrb_value self_copy; mrb_value self_copy;
mrb_value self; mrb_value self;
mrb_int *write_pos; mrb_int *write_pos;
mrb_int len;
}; };
static mrb_value static mrb_value
@@ -1069,15 +1102,19 @@ ary_uniq_bang_body(mrb_state *mrb, void *data)
ary_populate_temp_set(mrb, ctx->set, ctx->self_copy); ary_populate_temp_set(mrb, ctx->set, ctx->self_copy);
for (mrb_int read_pos = 0; read_pos < ctx->len; read_pos++) { int ai = mrb_gc_arena_save(mrb);
for (mrb_int read_pos = 0; read_pos < RARRAY_LEN(ctx->self); read_pos++) {
mrb_value elem = RARRAY_PTR(ctx->self)[read_pos]; mrb_value elem = RARRAY_PTR(ctx->self)[read_pos];
mrb_gc_protect(mrb, elem); // elem may be removed from self by kh_get(ary_set, ...)
khiter_t k = kh_get(ary_set, mrb, ctx->set, elem); khiter_t k = kh_get(ary_set, mrb, ctx->set, elem);
if (!kh_is_end(ctx->set, k)) { if (!kh_is_end(ctx->set, k)) {
if (*ctx->write_pos != read_pos) { if (*ctx->write_pos != read_pos && *ctx->write_pos < RARRAY_LEN(ctx->self)) {
mrb_ary_modify(mrb, mrb_ary_ptr(ctx->self));
RARRAY_PTR(ctx->self)[*ctx->write_pos] = elem; RARRAY_PTR(ctx->self)[*ctx->write_pos] = elem;
} }
(*ctx->write_pos)++; (*ctx->write_pos)++;
kh_del(ary_set, mrb, ctx->set, k); kh_del(ary_set, mrb, ctx->set, k);
mrb_gc_arena_restore(mrb, ai);
} }
} }
@@ -1104,28 +1141,32 @@ ary_uniq_bang(mrb_state *mrb, mrb_value self)
ary_set_t *set = &set_struct; ary_set_t *set = &set_struct;
ary_init_temp_set(mrb, set, len); ary_init_temp_set(mrb, set, len);
struct ary_uniq_bang_ctx ctx = { set, self_copy, self, &write_pos, len }; struct ary_uniq_bang_ctx ctx = { set, self_copy, self, &write_pos };
mrb_value result; mrb_value result;
MRB_ENSURE(mrb, result, ary_uniq_bang_body, &ctx) { MRB_ENSURE(mrb, result, ary_uniq_bang_body, &ctx) {
ary_destroy_temp_set(mrb, set); ary_destroy_temp_set(mrb, set);
} }
} }
else { else {
for (mrb_int read_pos = 0; read_pos < len; read_pos++) { int ai = mrb_gc_arena_save(mrb);
for (mrb_int read_pos = 0; read_pos < RARRAY_LEN(self); read_pos++) {
mrb_value elem = RARRAY_PTR(self)[read_pos]; mrb_value elem = RARRAY_PTR(self)[read_pos];
mrb_gc_protect(mrb, elem); // elem may be removed from self by mrb_equal()
mrb_bool found = FALSE; mrb_bool found = FALSE;
for (mrb_int j = 0; j < write_pos; j++) { for (mrb_int j = 0; j < write_pos && j < RARRAY_LEN(self); j++) {
if (mrb_equal(mrb, elem, RARRAY_PTR(self)[j])) { if (mrb_equal(mrb, elem, RARRAY_PTR(self)[j])) {
found = TRUE; found = TRUE;
break; break;
} }
} }
if (!found) { if (!found) {
if (write_pos != read_pos) { if (write_pos != read_pos && write_pos < RARRAY_LEN(self)) {
mrb_ary_modify(mrb, mrb_ary_ptr(self));
RARRAY_PTR(self)[write_pos] = elem; RARRAY_PTR(self)[write_pos] = elem;
} }
write_pos++; write_pos++;
} }
mrb_gc_arena_restore(mrb, ai);
} }
} }
@@ -1374,6 +1415,13 @@ ary_insert(mrb_state *mrb, mrb_value self)
return self; return self;
} }
struct ary_product_generator {
mrb_int total;
mrb_int cursor;
};
static struct mrb_data_type ary_product_generator_type = { "ary_product_generator", mrb_free };
/* /*
* Internal helper for Array#product to construct a group array. * Internal helper for Array#product to construct a group array.
* Takes the base array (self), the array of other arrays (arys), * Takes the base array (self), the array of other arrays (arys),
@@ -1381,29 +1429,85 @@ ary_insert(mrb_state *mrb, mrb_value self)
* of the group array (group_len). * of the group array (group_len).
*/ */
static mrb_value static mrb_value
ary_product_group(mrb_state *mrb, mrb_value self_ary) ary_product_fetch(mrb_state *mrb, mrb_value self_ary, mrb_value arys_ary, mrb_int n)
{ {
mrb_value arys_ary;
mrb_int current_i, group_len;
mrb_get_args(mrb, "Aii", &arys_ary, &current_i, &group_len);
mrb_value group = mrb_ary_new_capa(mrb, group_len);
mrb_int j = RARRAY_LEN(arys_ary); // Corresponds to 'size' in Ruby mrb_int j = RARRAY_LEN(arys_ary); // Corresponds to 'size' in Ruby
mrb_int n = current_i; mrb_value group = mrb_ary_new_capa(mrb, j + 1 /* self_ary */);
while (j > 0) { while (j-- > 0) {
j -= 1;
mrb_value a = RARRAY_PTR(arys_ary)[j]; // arys[j] mrb_value a = RARRAY_PTR(arys_ary)[j]; // arys[j]
mrb_check_type(mrb, a, MRB_TT_ARRAY); mrb_check_type(mrb, a, MRB_TT_ARRAY);
mrb_int b = RARRAY_LEN(a); // a.size mrb_int b = RARRAY_LEN(a); // a.size
if (b <= 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "cannot compute product with an empty array");
}
mrb_ary_set(mrb, group, j + 1, RARRAY_PTR(a)[n % b]); mrb_ary_set(mrb, group, j + 1, RARRAY_PTR(a)[n % b]);
n /= b; n /= b;
} }
if (n >= RARRAY_LEN(self_ary)) {
mrb_raise(mrb, E_INDEX_ERROR, "index out of range");
}
mrb_ary_set(mrb, group, 0, RARRAY_PTR(self_ary)[n]); mrb_ary_set(mrb, group, 0, RARRAY_PTR(self_ary)[n]);
return group; return group;
} }
static mrb_value
ary_product_generate(mrb_state *mrb, mrb_value self)
{
mrb_value arys_ary, block;
mrb_get_args(mrb, "A&", &arys_ary, &block);
mrb_int total = RARRAY_LEN(self);
for (mrb_int i = 0; i < RARRAY_LEN(arys_ary); i++) {
mrb_value a = RARRAY_PTR(arys_ary)[i];
mrb_check_type(mrb, a, MRB_TT_ARRAY);
mrb_int n = RARRAY_LEN(a);
if (n == 0) {
total = 0;
break;
}
if (mrb_int_mul_overflow(total, n, &total)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "result too big");
}
}
if (mrb_nil_p(block)) {
mrb_value result = mrb_ary_new_capa(mrb, total);
for (mrb_int i = 0; i < total; i++) {
mrb_value group = ary_product_fetch(mrb, self, arys_ary, i);
mrb_ary_push(mrb, result, group);
}
return result;
}
else if (total > 0) {
struct RData *d;
struct ary_product_generator *g;
Data_Make_Struct(mrb, mrb->object_class, struct ary_product_generator,
&ary_product_generator_type, g, d);
g->total = total;
g->cursor = 0;
return mrb_obj_value(d);
}
else {
return mrb_nil_value();
}
}
static mrb_value
ary_product_next(mrb_state *mrb, mrb_value self)
{
mrb_value arys;
struct ary_product_generator *g;
mrb_get_args(mrb, "Ad", &arys, &g, &ary_product_generator_type);
if (g->cursor >= g->total) {
return mrb_nil_value();
}
return ary_product_fetch(mrb, self, arys, g->cursor++);
}
/* /*
* call-seq: * call-seq:
* ary.deconstruct -> ary * ary.deconstruct -> ary
@@ -1564,7 +1668,8 @@ static const mrb_mt_entry array_ext_rom_entries[] = {
MRB_MT_ENTRY(ary_fetch, MRB_SYM(__fetch), MRB_ARGS_REQ(3)), MRB_MT_ENTRY(ary_fetch, MRB_SYM(__fetch), MRB_ARGS_REQ(3)),
MRB_MT_ENTRY(ary_insert, MRB_SYM(insert), MRB_ARGS_ARG(1,-1)), MRB_MT_ENTRY(ary_insert, MRB_SYM(insert), MRB_ARGS_ARG(1,-1)),
MRB_MT_ENTRY(ary_deconstruct, MRB_SYM(deconstruct), MRB_ARGS_NONE()), MRB_MT_ENTRY(ary_deconstruct, MRB_SYM(deconstruct), MRB_ARGS_NONE()),
MRB_MT_ENTRY(ary_product_group, MRB_SYM(__product_group), MRB_ARGS_REQ(3)), MRB_MT_ENTRY(ary_product_generate, MRB_SYM(__product_generate), MRB_ARGS_REQ(1)),
MRB_MT_ENTRY(ary_product_next, MRB_SYM(__product_next), MRB_ARGS_REQ(2)),
MRB_MT_ENTRY(ary_combination_init, MRB_SYM(__combination_init), MRB_ARGS_REQ(2)), MRB_MT_ENTRY(ary_combination_init, MRB_SYM(__combination_init), MRB_ARGS_REQ(2)),
MRB_MT_ENTRY(ary_combination_next, MRB_SYM(__combination_next), MRB_ARGS_REQ(1)), MRB_MT_ENTRY(ary_combination_next, MRB_SYM(__combination_next), MRB_ARGS_REQ(1)),
}; };
@@ -12,7 +12,6 @@
#include <mruby/numeric.h> #include <mruby/numeric.h>
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#include "apiprint.h" #include "apiprint.h"
static void static void
-1
View File
@@ -19,7 +19,6 @@
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/variable.h> #include <mruby/variable.h>
#include <mruby/error.h> #include <mruby/error.h>
#include <mruby/presym.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <stdlib.h> #include <stdlib.h>
@@ -12,7 +12,6 @@
#include <mruby/variable.h> #include <mruby/variable.h>
#include <mruby/proc.h> #include <mruby/proc.h>
#include <mruby/error.h> #include <mruby/error.h>
#include <mruby/presym.h>
#if defined(_WIN32) #if defined(_WIN32)
# include <io.h> /* for setmode */ # include <io.h> /* for setmode */
-1
View File
@@ -4,7 +4,6 @@
#include <mruby/hash.h> #include <mruby/hash.h>
#include <mruby/proc.h> #include <mruby/proc.h>
#include <mruby/variable.h> #include <mruby/variable.h>
#include <mruby/presym.h>
#include <mruby/opcode.h> #include <mruby/opcode.h>
#include <mruby/debug.h> #include <mruby/debug.h>
#include <mruby/internal.h> #include <mruby/internal.h>
-1
View File
@@ -1,5 +1,4 @@
#include <mruby.h> #include <mruby.h>
#include <mruby/presym.h>
static mrb_value static mrb_value
binding_in_c(mrb_state *mrb, mrb_value self) binding_in_c(mrb_state *mrb, mrb_value self)
-1
View File
@@ -4,7 +4,6 @@
#include <mruby/error.h> #include <mruby/error.h>
#include <mruby/proc.h> #include <mruby/proc.h>
#include <mruby/opcode.h> #include <mruby/opcode.h>
#include <mruby/presym.h>
/* Pre-defined symbols used by catch implementation */ /* Pre-defined symbols used by catch implementation */
MRB_PRESYM_DEFINE_VAR_AND_INITER(catch_syms, 3, MRB_SYM(Object), MRB_SYM(new), MRB_SYM(call)) MRB_PRESYM_DEFINE_VAR_AND_INITER(catch_syms, 3, MRB_SYM(Object), MRB_SYM(new), MRB_SYM(call))
-1
View File
@@ -5,7 +5,6 @@
#include <mruby/proc.h> #include <mruby/proc.h>
#include <mruby/variable.h> #include <mruby/variable.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
/* /*
* Get the name of a module/class. * Get the name of a module/class.
-1
View File
@@ -10,7 +10,6 @@
*/ */
#include <mruby.h> #include <mruby.h>
#include <mruby/presym.h>
#ifdef MRB_NO_FLOAT #ifdef MRB_NO_FLOAT
# error CMath conflicts with 'MRB_NO_FLOAT' configuration # error CMath conflicts with 'MRB_NO_FLOAT' configuration
+35 -9
View File
@@ -46,7 +46,6 @@
#include <mruby/numeric.h> #include <mruby/numeric.h>
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/debug.h> #include <mruby/debug.h>
#include <mruby/presym.h>
#include "node.h" #include "node.h"
#include <mruby/opcode.h> #include <mruby/opcode.h>
#include <mruby/re.h> #include <mruby/re.h>
@@ -3176,8 +3175,12 @@ gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
{ {
if (val) { if (val) {
int array_size = 0; int array_size = 0;
int first = 1;
int slimit = GEN_LIT_ARY_MAX;
node *current = tree; node *current = tree;
if (cursp() >= slimit) slimit = GEN_VAL_STACK_MAX;
/* Process each segment separated by NODE_LITERAL_DELIM */ /* Process each segment separated by NODE_LITERAL_DELIM */
while (current) { while (current) {
/* Find the segment boundaries without allocating */ /* Find the segment boundaries without allocating */
@@ -3214,6 +3217,24 @@ gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
/* Only process non-empty segments */ /* Only process non-empty segments */
if (!is_empty_segment) { if (!is_empty_segment) {
/* Flush accumulated elements when stack is full */
if (cursp() >= slimit) {
if (array_size > 0) {
pop_n(array_size);
if (first) {
genop_2(s, OP_ARRAY, cursp(), array_size);
push();
first = 0;
}
else {
pop();
genop_2(s, OP_ARYPUSH, cursp(), array_size);
push();
}
array_size = 0;
}
}
/* Temporarily terminate the segment by saving and clearing the cdr */ /* Temporarily terminate the segment by saving and clearing the cdr */
node *saved_cdr = NULL; node *saved_cdr = NULL;
if (segment_prev) { if (segment_prev) {
@@ -3244,8 +3265,14 @@ gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
} }
} }
/* Generate the array from pushed elements */ /* Handle remaining elements */
if (array_size > 0) { if (!first) {
if (array_size > 0) {
pop_n(array_size + 1);
genop_2(s, OP_ARYPUSH, cursp(), array_size);
}
}
else if (array_size > 0) {
pop_n(array_size); pop_n(array_size);
genop_2(s, OP_ARRAY, cursp(), array_size); genop_2(s, OP_ARRAY, cursp(), array_size);
} }
@@ -3821,7 +3848,7 @@ codegen_array(codegen_scope *s, node *varnode, int val)
node *elements = array->elements; node *elements = array->elements;
int regular_elements = 0; int regular_elements = 0;
int first = 1; int first = 1;
int slimit = GEN_VAL_STACK_MAX; int slimit = GEN_LIT_ARY_MAX;
if (!val) return; if (!val) return;
@@ -3831,7 +3858,7 @@ codegen_array(codegen_scope *s, node *varnode, int val)
return; return;
} }
if (cursp() >= GEN_LIT_ARY_MAX) slimit = INT16_MAX; if (cursp() >= slimit) slimit = GEN_VAL_STACK_MAX;
/* Process each element using cons-list iteration, handling splats */ /* Process each element using cons-list iteration, handling splats */
node *current = elements; node *current = elements;
@@ -4428,10 +4455,9 @@ codegen_case_match(codegen_scope *s, node *varnode, int val)
current_in = current_in->cdr; current_in = current_in->cdr;
} }
/* No pattern matched - generate nil or error */ /* No pattern matched - raise NoMatchingPatternError */
if (val) { genop_1(s, OP_LOADFALSE, cursp());
genop_1(s, OP_LOADNIL, cursp()); genop_1(s, OP_MATCHERR, cursp());
}
/* Dispatch all end jumps */ /* Dispatch all end jumps */
if (case_end_jumps != JMPLINK_START) { if (case_end_jumps != JMPLINK_START) {
+3 -4
View File
@@ -23,7 +23,6 @@
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/dump.h> #include <mruby/dump.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#include "node.h" #include "node.h"
#define YYLEX_PARAM p #define YYLEX_PARAM p
@@ -3261,7 +3260,7 @@ primary : literal
$<stack>$ = p->cmdarg_stack; $<stack>$ = p->cmdarg_stack;
p->cmdarg_stack = 0; p->cmdarg_stack = 0;
} }
stmt {p->lstate = EXPR_ENDARG;} rparen compstmt {p->lstate = EXPR_ENDARG;} rparen
{ {
p->cmdarg_stack = $<stack>2; p->cmdarg_stack = $<stack>2;
$$ = $3; $$ = $3;
@@ -4564,13 +4563,13 @@ f_label : tIDENTIFIER tLABEL_TAG
{ {
$$ = $1; $$ = $1;
local_nest(p); local_nest(p);
p->lstate = EXPR_ARG; /* make newlines significant after label */ p->lstate = EXPR_MID; /* make newlines significant after label */
} }
| tNUMPARAM tLABEL_TAG | tNUMPARAM tLABEL_TAG
{ {
$$ = intern_numparam($1); $$ = intern_numparam($1);
local_nest(p); local_nest(p);
p->lstate = EXPR_ARG; /* make newlines significant after label */ p->lstate = EXPR_MID; /* make newlines significant after label */
} }
; ;
File diff suppressed because it is too large Load Diff
-1
View File
@@ -2,7 +2,6 @@
#include <mruby/class.h> #include <mruby/class.h>
#include <mruby/numeric.h> #include <mruby/numeric.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#include <float.h> #include <float.h>
#ifdef MRB_NO_FLOAT #ifdef MRB_NO_FLOAT
-1
View File
@@ -13,7 +13,6 @@
#include <mruby/hash.h> #include <mruby/hash.h>
#include <mruby/proc.h> #include <mruby/proc.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#define RDATA_LEN(st) RARRAY_LEN(st) #define RDATA_LEN(st) RARRAY_LEN(st)
#define RDATA_PTR(st) RARRAY_PTR(st) #define RDATA_PTR(st) RARRAY_PTR(st)
-1
View File
@@ -10,7 +10,6 @@
#include <mruby/data.h> #include <mruby/data.h>
#include <mruby/error.h> #include <mruby/error.h>
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/presym.h>
#include "dir_hal.h" #include "dir_hal.h"
#include <string.h> #include <string.h>
-1
View File
@@ -2,7 +2,6 @@
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/variable.h> #include <mruby/variable.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#define ENC_ASCII_8BIT "ASCII-8BIT" #define ENC_ASCII_8BIT "ASCII-8BIT"
#define ENC_BINARY "BINARY" #define ENC_BINARY "BINARY"
+6 -5
View File
@@ -291,11 +291,12 @@ class Enumerator
# #
def flat_map(&block) def flat_map(&block)
Lazy.new(self){|yielder, val| Lazy.new(self){|yielder, val|
ary = block.call(val) result = block.call(val)
# TODO: check ary is an Array if result.respond_to?(:each)
ary.each {|x| result.each {|x| yielder << x }
yielder << x else
} yielder << result
end
} }
end end
alias collect_concat flat_map alias collect_concat flat_map
+12
View File
@@ -46,6 +46,18 @@ assert("Enumerator::Lazy#to_enum") do
assert_equal [0*1, 2*3, 4*5, 6*7], lazy_enum.map { |a| a.first * a.last }.first(4) assert_equal [0*1, 2*3, 4*5, 6*7], lazy_enum.map { |a| a.first * a.last }.first(4)
end end
assert("Enumerator::Lazy#flat_map with array from block") do
assert_equal [1, 10, 2, 20, 3, 30], [1, 2, 3].lazy.flat_map {|x| [x, x*10]}.force
end
assert("Enumerator::Lazy#flat_map with non-enumerable from block") do
assert_equal [1, 2, 3], [1, 2, 3].lazy.flat_map {|x| x}.force
end
assert("Enumerator::Lazy#flat_map with nested array from block") do
assert_equal [[1, 2], [3, 4]], [1, 3].lazy.flat_map {|x| [[x, x+1]]}.force
end
assert("Enumerator::Lazy#grep_v") do assert("Enumerator::Lazy#grep_v") do
lazy_grep_v = (0..).lazy.grep_v(2..4) lazy_grep_v = (0..).lazy.grep_v(2..4)
assert_kind_of Enumerator::Lazy, lazy_grep_v assert_kind_of Enumerator::Lazy, lazy_grep_v
-1
View File
@@ -7,7 +7,6 @@
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/variable.h> #include <mruby/variable.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
-1
View File
@@ -6,7 +6,6 @@
#include <mruby/proc.h> #include <mruby/proc.h>
#include <mruby/opcode.h> #include <mruby/opcode.h>
#include <mruby/error.h> #include <mruby/error.h>
#include <mruby/presym.h>
#include <mruby/variable.h> #include <mruby/variable.h>
#include <mruby/internal.h> #include <mruby/internal.h>
-1
View File
@@ -2,7 +2,6 @@
#include <mruby.h> #include <mruby.h>
#include <mruby/error.h> #include <mruby/error.h>
#include <mruby/variable.h> #include <mruby/variable.h>
#include <mruby/presym.h>
#ifndef EXIT_SUCCESS #ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0 # define EXIT_SUCCESS 0
-1
View File
@@ -6,7 +6,6 @@
#include <mruby/numeric.h> #include <mruby/numeric.h>
#include <mruby/proc.h> #include <mruby/proc.h>
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/presym.h>
#define fiber_ptr(o) ((struct RFiber*)mrb_ptr(o)) #define fiber_ptr(o) ((struct RFiber*)mrb_ptr(o))
-1
View File
@@ -9,7 +9,6 @@
#include <mruby/hash.h> #include <mruby/hash.h>
#include <mruby/class.h> #include <mruby/class.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
/* /*
* call-seq: * call-seq:
-1
View File
@@ -10,7 +10,6 @@
#include <mruby/io.h> #include <mruby/io.h>
#include <mruby/error.h> #include <mruby/error.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#include "io_hal.h" #include "io_hal.h"
#include <sys/types.h> #include <sys/types.h>
-1
View File
@@ -8,7 +8,6 @@
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/io.h> #include <mruby/io.h>
#include <mruby/error.h> #include <mruby/error.h>
#include <mruby/presym.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include "io_hal.h" #include "io_hal.h"
+13 -4
View File
@@ -12,7 +12,6 @@
#include <mruby/io.h> #include <mruby/io.h>
#include <mruby/error.h> #include <mruby/error.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#include "io_hal.h" #include "io_hal.h"
#include <sys/types.h> #include <sys/types.h>
@@ -993,10 +992,20 @@ io_puts_str(mrb_state *mrb, int fd, mrb_value str)
} }
} }
/* Maximum nesting depth for puts with arrays; guards against cyclic and
pathologically deep arrays causing C stack overflow. */
#define IO_PUTS_MAX_DEPTH 16
/* Recursive helper for puts with arrays */ /* Recursive helper for puts with arrays */
static void static void
io_puts_ary(mrb_state *mrb, int fd, mrb_value ary) io_puts_ary(mrb_state *mrb, int fd, mrb_value ary, int depth)
{ {
if (depth >= IO_PUTS_MAX_DEPTH) {
mrb_value mark = mrb_str_new_lit(mrb, "[...]\n");
fd_write(mrb, fd, mark);
return;
}
mrb_int len = RARRAY_LEN(ary); mrb_int len = RARRAY_LEN(ary);
if (len == 0) { if (len == 0) {
@@ -1009,7 +1018,7 @@ io_puts_ary(mrb_state *mrb, int fd, mrb_value ary)
for (mrb_int i = 0; i < len; i++) { for (mrb_int i = 0; i < len; i++) {
mrb_value elem = RARRAY_PTR(ary)[i]; mrb_value elem = RARRAY_PTR(ary)[i];
if (mrb_array_p(elem)) { if (mrb_array_p(elem)) {
io_puts_ary(mrb, fd, elem); /* Recursive call for nested arrays */ io_puts_ary(mrb, fd, elem, depth + 1);
} }
else { else {
io_puts_str(mrb, fd, elem); io_puts_str(mrb, fd, elem);
@@ -1041,7 +1050,7 @@ io_puts(mrb_state *mrb, mrb_value io)
for (mrb_int i = 0; i < argc; i++) { for (mrb_int i = 0; i < argc; i++) {
mrb_value arg = argv[i]; mrb_value arg = argv[i];
if (mrb_array_p(arg)) { if (mrb_array_p(arg)) {
io_puts_ary(mrb, fd, arg); io_puts_ary(mrb, fd, arg, 0);
} }
else { else {
io_puts_str(mrb, fd, arg); io_puts_str(mrb, fd, arg);
-1
View File
@@ -8,7 +8,6 @@
#include <mruby/proc.h> #include <mruby/proc.h>
#include <mruby/class.h> #include <mruby/class.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
/* /*
* call-seq: * call-seq:
-1
View File
@@ -11,7 +11,6 @@
#endif #endif
#include <mruby/array.h> #include <mruby/array.h>
#include <mruby/presym.h>
static void static void
domain_error(mrb_state *mrb, const char *func) domain_error(mrb_state *mrb, const char *func)
-1
View File
@@ -7,7 +7,6 @@
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/khash.h> #include <mruby/khash.h>
#include <mruby/presym.h>
#define MT_PROTECTED MRB_METHOD_PROTECTED_FL #define MT_PROTECTED MRB_METHOD_PROTECTED_FL
#define MT_NOPRIV (MRB_METHOD_PRIVATE_FL|MT_PROTECTED) #define MT_NOPRIV (MRB_METHOD_PRIVATE_FL|MT_PROTECTED)
-1
View File
@@ -5,7 +5,6 @@
#include <mruby/proc.h> #include <mruby/proc.h>
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
// Defined by mruby-proc-ext on which mruby-method depends // Defined by mruby-proc-ext on which mruby-method depends
mrb_value mrb_proc_parameters(mrb_state *mrb, mrb_value proc); mrb_value mrb_proc_parameters(mrb_state *mrb, mrb_value proc);
+1 -6
View File
@@ -4,7 +4,6 @@
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/class.h> #include <mruby/class.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#ifndef MRB_NO_FLOAT #ifndef MRB_NO_FLOAT
static mrb_value flo_remainder(mrb_state *mrb, mrb_value self); static mrb_value flo_remainder(mrb_state *mrb, mrb_value self);
@@ -191,11 +190,7 @@ int_powm(mrb_state *mrb, mrb_value x)
return mrb_int_pow(mrb, x, mrb_get_arg1(mrb)); return mrb_int_pow(mrb, x, mrb_get_arg1(mrb));
} }
mrb_get_args(mrb, "oo", &e, &m); mrb_get_args(mrb, "oo", &e, &m);
if (!mrb_integer_p(e) if (!mrb_integer_p(e) && !mrb_bigint_p(e)) {
#ifdef MRB_USE_BIGINT
&& !mrb_bigint_p(e)
#endif
) {
mrb_raise(mrb, E_TYPE_ERROR, "int.pow(n,m): 2nd argument not allowed unless 1st argument is an integer"); mrb_raise(mrb, E_TYPE_ERROR, "int.pow(n,m): 2nd argument not allowed unless 1st argument is an integer");
} }
#ifdef MRB_USE_BIGINT #ifdef MRB_USE_BIGINT
-1
View File
@@ -4,7 +4,6 @@
#include <mruby/hash.h> #include <mruby/hash.h>
#include <mruby/proc.h> #include <mruby/proc.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
/* /*
* call-seq: * call-seq:
@@ -10,7 +10,6 @@
#include <mruby/proc.h> #include <mruby/proc.h>
#include <mruby/value.h> #include <mruby/value.h>
#include <mruby/range.h> #include <mruby/range.h>
#include <mruby/presym.h>
struct os_count_struct { struct os_count_struct {
mrb_int total; mrb_int total;
-1
View File
@@ -11,7 +11,6 @@
#include <mruby/variable.h> #include <mruby/variable.h>
#include <mruby/endian.h> #include <mruby/endian.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
@@ -1,5 +1,4 @@
#include <mruby.h> #include <mruby.h>
#include <mruby/presym.h>
#include <mruby/proc.h> #include <mruby/proc.h>
#include <mruby/variable.h> #include <mruby/variable.h>
-1
View File
@@ -6,7 +6,6 @@
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/debug.h> #include <mruby/debug.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
/* /*
* call-seq: * call-seq:
-1
View File
@@ -11,7 +11,6 @@
#include <mruby/data.h> #include <mruby/data.h>
#include <mruby/array.h> #include <mruby/array.h>
#include <mruby/istruct.h> #include <mruby/istruct.h>
#include <mruby/presym.h>
#include <mruby/range.h> #include <mruby/range.h>
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/internal.h> #include <mruby/internal.h>
-1
View File
@@ -2,7 +2,6 @@
#include <mruby/range.h> #include <mruby/range.h>
#include <mruby/class.h> #include <mruby/class.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
static mrb_bool static mrb_bool
r_less(mrb_state *mrb, mrb_value a, mrb_value b, mrb_bool excl) r_less(mrb_state *mrb, mrb_value a, mrb_value b, mrb_bool excl)
-1
View File
@@ -2,7 +2,6 @@
#include <mruby/class.h> #include <mruby/class.h>
#include <mruby/numeric.h> #include <mruby/numeric.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#ifndef MRB_NO_FLOAT #ifndef MRB_NO_FLOAT
#include <math.h> #include <math.h>
-1
View File
@@ -13,7 +13,6 @@
#include <mruby/proc.h> #include <mruby/proc.h>
#include <mruby/data.h> #include <mruby/data.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#include <mruby/error.h> #include <mruby/error.h>
#include <mruby/khash.h> #include <mruby/khash.h>
-1
View File
@@ -37,7 +37,6 @@
#endif #endif
#include <mruby.h> #include <mruby.h>
#include <mruby/presym.h>
/* /*
* call-seq: * call-seq:
+1 -3
View File
@@ -701,13 +701,11 @@ class UDPSocket < IPSocket
# data, addr = sock.recvfrom_nonblock(1024) # data, addr = sock.recvfrom_nonblock(1024)
# #
def recvfrom_nonblock(*args) def recvfrom_nonblock(*args)
s = self
begin begin
self._setnonblock(true) self._setnonblock(true)
self.recvfrom(*args) self.recvfrom(*args)
ensure ensure
# XXX: self is a SystemcallException here! (should be bug) self._setnonblock(false)
s._setnonblock(false)
end end
end end
-1
View File
@@ -36,7 +36,6 @@
#include <mruby/variable.h> #include <mruby/variable.h>
#include <mruby/error.h> #include <mruby/error.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#include <mruby/io.h> #include <mruby/io.h>
#include "socket_hal.h" #include "socket_hal.h"
+7 -1
View File
@@ -8,7 +8,6 @@
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/hash.h> #include <mruby/hash.h>
#include <mruby/numeric.h> #include <mruby/numeric.h>
#include <mruby/presym.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
@@ -381,6 +380,13 @@ mrb_str_format(mrb_state *mrb, mrb_int argc, const mrb_value *argv, mrb_value fm
argc++; argc++;
argv--; argv--;
mrb_ensure_string_type(mrb, fmt); mrb_ensure_string_type(mrb, fmt);
/* Duplicate the format string so that to_s/inspect callbacks invoked
during the loop cannot invalidate p/end by mutating the original
via String#replace or similar. mrb_str_dup shares the underlying
buffer, so this is O(1); String#replace on the original goes
through str_replace which decrements the shared refcount, leaving
our copy's buffer intact. */
fmt = mrb_str_dup(mrb, fmt);
p = RSTRING_PTR(fmt); p = RSTRING_PTR(fmt);
end = p + RSTRING_LEN(fmt); end = p + RSTRING_LEN(fmt);
blen = 0; blen = 0;
+16
View File
@@ -90,3 +90,19 @@ assert("String#% invalid format") do
"%?" % "" "%?" % ""
end end
end end
assert("sprintf with to_s mutating format string") do
# The to_s callback must not be able to invalidate sprintf's internal
# iteration pointers by mutating the format string.
fmt = "%s" + "B" * 200
mutator = Object.new
$sprintf_test_fmt = fmt
def mutator.to_s
$sprintf_test_fmt.replace("Z")
"ok"
end
result = sprintf(fmt, mutator)
assert_equal 202, result.length
assert_equal "ok", result[0, 2]
assert_equal "B" * 200, result[2..]
end
-1
View File
@@ -8,7 +8,6 @@
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/time.h> #include <mruby/time.h>
#include <mruby/class.h> #include <mruby/class.h>
#include <mruby/presym.h>
#include <time.h> #include <time.h>
#include <string.h> #include <string.h>
+15 -4
View File
@@ -5,7 +5,6 @@
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/range.h> #include <mruby/range.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#define ENC_ASCII_8BIT "ASCII-8BIT" #define ENC_ASCII_8BIT "ASCII-8BIT"
#define ENC_BINARY "BINARY" #define ENC_BINARY "BINARY"
@@ -2202,15 +2201,27 @@ str_prepend(mrb_state *mrb, mrb_value self)
char *p = RSTRING_PTR(self); char *p = RSTRING_PTR(self);
/* Move original content to the end */ /* Move original content to the end. The original self data now lives
at p + total_prepend_len, which we use as the source for any
self-referencing arguments (e.g., s.prepend(s, s)) to avoid reading
data that has already been overwritten by earlier copies. */
memmove(p + total_prepend_len, p, self_len); memmove(p + total_prepend_len, p, self_len);
/* Copy prepended strings in order */ /* Copy prepended strings in order */
mrb_int offset = 0; mrb_int offset = 0;
for (mrb_int i = 0; i < argc; i++) { for (mrb_int i = 0; i < argc; i++) {
mrb_int arg_len = RSTRING_LEN(argv[i]); const char *src;
mrb_int arg_len;
if (mrb_obj_eq(mrb, self, argv[i])) {
src = p + total_prepend_len;
arg_len = self_len;
}
else {
src = RSTRING_PTR(argv[i]);
arg_len = RSTRING_LEN(argv[i]);
}
if (arg_len > 0) { if (arg_len > 0) {
memcpy(p + offset, RSTRING_PTR(argv[i]), arg_len); memcpy(p + offset, src, arg_len);
offset += arg_len; offset += arg_len;
} }
} }
+15
View File
@@ -492,6 +492,21 @@ assert('String#prepend') do
g = "world" g = "world"
assert_equal "hello world", g.prepend("", "hello ", "") assert_equal "hello world", g.prepend("", "hello ", "")
assert_equal "hello world", g assert_equal "hello world", g
# Self-referencing arguments (GHSA-3hgj-g76g-878c)
h = "A" * 100
h.prepend(h, h)
assert_equal 300, h.length
assert_equal "A" * 300, h
# Mixed self-reference and literal
i = "AB"
i.prepend("XYZ", i)
assert_equal "XYZABAB", i
j = "AB"
j.prepend(j, "X", j)
assert_equal "ABXABAB", j
end end
assert('String#ljust') do assert('String#ljust') do
-1
View File
@@ -14,7 +14,6 @@
#include <mruby/range.h> #include <mruby/range.h>
#include <mruby/proc.h> #include <mruby/proc.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#define RSTRUCT_LEN(st) RARRAY_LEN(st) #define RSTRUCT_LEN(st) RARRAY_LEN(st)
#define RSTRUCT_PTR(st) RARRAY_PTR(st) #define RSTRUCT_PTR(st) RARRAY_PTR(st)
-1
View File
@@ -3,7 +3,6 @@
#include <mruby/class.h> #include <mruby/class.h>
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
/* /*
* call-seq: * call-seq:
-1
View File
@@ -12,7 +12,6 @@
#include <mruby/gc.h> #include <mruby/gc.h>
#include <mruby/hash.h> #include <mruby/hash.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#include <mruby/proc.h> #include <mruby/proc.h>
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/variable.h> #include <mruby/variable.h>
+9 -3
View File
@@ -19,9 +19,11 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
file assert_c => [assert_rb, build.mrbcfile] do |t| file assert_c => [assert_rb, build.mrbcfile] do |t|
_pp "GEN", t.name.relative_path _pp "GEN", t.name.relative_path
mkdir_p File.dirname(t.name) mkdir_p File.dirname(t.name)
open(t.name, 'w') do |f| tmpfile = t.name + ".tmp"
open(tmpfile, 'w') do |f|
mrbc.run f, assert_rb, 'mrbtest_assert_irep', cdump: false mrbc.run f, assert_rb, 'mrbtest_assert_irep', cdump: false
end end
File.rename(tmpfile, t.name)
end end
gem_table = build.gems.generate_gem_table build gem_table = build.gems.generate_gem_table build
@@ -36,7 +38,8 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
file g.test_rbireps => [g.test_rbfiles, build.mrbcfile].flatten do |t| file g.test_rbireps => [g.test_rbfiles, build.mrbcfile].flatten do |t|
_pp "GEN", t.name.relative_path _pp "GEN", t.name.relative_path
mkdir_p File.dirname(t.name) mkdir_p File.dirname(t.name)
open(t.name, 'w') do |f| tmpfile = t.name + ".tmp"
open(tmpfile, 'w') do |f|
g.print_gem_test_header(f) g.print_gem_test_header(f)
test_preload = g.test_preload and [g.dir, MRUBY_ROOT].map {|dir| test_preload = g.test_preload and [g.dir, MRUBY_ROOT].map {|dir|
File.expand_path(g.test_preload, dir) File.expand_path(g.test_preload, dir)
@@ -117,6 +120,7 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
end end
f.puts %Q[}] f.puts %Q[}]
end end
File.rename(tmpfile, t.name)
end end
end end
@@ -134,7 +138,8 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
file clib => ["#{build.build_dir}/mrbgems/active_gems.txt", build.mrbcfile, __FILE__] do |_t| file clib => ["#{build.build_dir}/mrbgems/active_gems.txt", build.mrbcfile, __FILE__] do |_t|
_pp "GEN", clib.relative_path _pp "GEN", clib.relative_path
mkdir_p File.dirname(clib) mkdir_p File.dirname(clib)
open(clib, 'w') do |f| tmpfile = clib + ".tmp"
open(tmpfile, 'w') do |f|
f.puts %Q[/*] f.puts %Q[/*]
f.puts %Q[ * This file contains a list of all] f.puts %Q[ * This file contains a list of all]
f.puts %Q[ * test functions.] f.puts %Q[ * test functions.]
@@ -169,5 +174,6 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
end end
f.puts %Q[}] f.puts %Q[}]
end end
File.rename(tmpfile, clib)
end end
end end
-1
View File
@@ -11,7 +11,6 @@
#include <mruby/time.h> #include <mruby/time.h>
#include <mruby/string.h> #include <mruby/string.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#ifdef MRB_NO_STDIO #ifdef MRB_NO_STDIO
#include <string.h> #include <string.h>
-1
View File
@@ -11,7 +11,6 @@
#include <mruby/range.h> #include <mruby/range.h>
#include <mruby/proc.h> #include <mruby/proc.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#include "value_array.h" #include "value_array.h"
#define ARY_DEFAULT_LEN 4 #define ARY_DEFAULT_LEN 4
-1
View File
@@ -15,7 +15,6 @@
#include <mruby/numeric.h> #include <mruby/numeric.h>
#include <mruby/data.h> #include <mruby/data.h>
#include <mruby/internal.h> #include <mruby/internal.h>
#include <mruby/presym.h>
#define MAX_IREP_REFCNT UINT16_MAX #define MAX_IREP_REFCNT UINT16_MAX
#define UNKNOWN_LINENO -1 #define UNKNOWN_LINENO -1
-1
View File
@@ -456,7 +456,6 @@ mrb_dump_irep_cstruct(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE
"#include <mruby/irep.h>\n" "#include <mruby/irep.h>\n"
"#include <mruby/debug.h>\n" "#include <mruby/debug.h>\n"
"#include <mruby/proc.h>\n" "#include <mruby/proc.h>\n"
"#include <mruby/presym.h>\n"
"\n") < 0) { "\n") < 0) {
return MRB_DUMP_WRITE_FAULT; return MRB_DUMP_WRITE_FAULT;
} }

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