Compare commits

..

1 Commits

Author SHA1 Message Date
Yukihiro "Matz" Matsumoto 7ac96912e9 pre-commit: fix prettier formatting in doc/guides/capi.md
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-12 13:09:44 +09:00
19 changed files with 303 additions and 370 deletions
-16
View File
@@ -5,27 +5,11 @@ updates:
directory: "/"
schedule:
interval: "daily"
groups:
bundler-dependencies:
patterns:
- "*"
cooldown:
default-days: 7
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
groups:
github-actions-dependencies:
patterns:
- "*"
cooldown:
default-days: 7
- package-ecosystem: "pre-commit"
directory: "/"
schedule:
interval: "daily"
groups:
pre-commit-hooks:
patterns:
- "*"
-20
View File
@@ -1,20 +0,0 @@
# 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@v6
- uses: j178/prek-action@v1
with:
install-only: true
- name: Run manual pre-commit hooks
run: prek run --color=always --all-files --hook-stage manual
+2
View File
@@ -16,3 +16,5 @@ jobs:
- uses: j178/prek-action@v1
with:
extra-args: --all-files
- name: Run manual pre-commit hooks
run: prek run --color=always --all-files --hook-stage manual
-1
View File
@@ -24,7 +24,6 @@ repos:
files: \.(md|ya?ml)$
language: node
additional_dependencies: ["prettier@3.7.4"]
pass_filenames: false
stages: [manual]
- id: check-zip-file-is-not-committed
name: disallow zip files
-1
View File
@@ -3,4 +3,3 @@ build
coverage
doc/internal/opcode.md
tools/lrama
.venv
-2
View File
@@ -51,8 +51,6 @@ 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
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-rc2.zip](https://github.com/mruby/mruby/archive/4.0.0-rc2.zip)
The latest development version of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/zipball/master](https://github.com/mruby/mruby/zipball/master)
The trunk of the mruby source tree can be checked out with the
+30 -30
View File
@@ -4,44 +4,44 @@
New to mruby? Start here:
| Document | Description |
| -------------------------------------------- | -------------------------------------- |
| Document | Description |
| -------- | ----------- |
| [Getting Started](guides/getting-started.md) | Build mruby and run your first program |
| [Language Features](guides/language.md) | Ruby subset supported by mruby |
| [Limitations](limitations.md) | Behavioral differences from CRuby |
| [Language Features](guides/language.md) | Ruby subset supported by mruby |
| [Limitations](limitations.md) | Behavioral differences from CRuby |
## Guides (for embedders and gem authors)
### Embedding mruby in C
| Document | Description |
| --------------------------------------- | ------------------------------------------------ |
| [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 |
| [Linking](guides/link.md) | Linking with `libmruby` |
| [Amalgamation](guides/amalgamation.md) | Single-file build for easy integration |
| [Precompiled Symbols](guides/symbol.md) | Compile-time symbol allocation |
| Document | Description |
| -------- | ----------- |
| [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 |
| [Linking](guides/link.md) | Linking with `libmruby` |
| [Amalgamation](guides/amalgamation.md) | Single-file build for easy integration |
| [Precompiled Symbols](guides/symbol.md) | Compile-time symbol allocation |
### Building and Configuring
| Document | Description |
| ---------------------------------------- | ------------------------------------------- |
| [Compilation](guides/compile.md) | Build system, cross-compilation, toolchains |
| [Build Configuration](guides/mrbconf.md) | Compile-time macros (`MRB_*` flags) |
| [mrbgems](guides/mrbgems.md) | Creating and managing gems |
| [Memory](guides/memory.md) | Allocator customization and heap regions |
| Document | Description |
| -------- | ----------- |
| [Compilation](guides/compile.md) | Build system, cross-compilation, toolchains |
| [Build Configuration](guides/mrbconf.md) | Compile-time macros (`MRB_*` flags) |
| [mrbgems](guides/mrbgems.md) | Creating and managing gems |
| [Memory](guides/memory.md) | Allocator customization and heap regions |
### Tools
| Document | Description |
| ----------------------------------------------- | ----------------------------------------------- |
| [Debugger](guides/debugger.md) | Using `mrdb` for debugging |
| Document | Description |
| -------- | ----------- |
| [Debugger](guides/debugger.md) | Using `mrdb` for debugging |
| [ROM Method Tables](guides/rom-method-table.md) | Read-only method tables for constrained devices |
### Reference
| Document | Description |
| ------------------------------------- | ------------------ |
| Document | Description |
| -------- | ----------- |
| [Directory Structure](guides/hier.md) | Source tree layout |
## Internals (for mruby contributors)
@@ -49,14 +49,14 @@ New to mruby? Start here:
Start with [Architecture](internal/architecture.md) for an overview,
then dive into the subsystem you need:
| Document | Description |
| ----------------------------------------- | -------------------------------------------------- |
| [Architecture](internal/architecture.md) | Overview of object model, VM, GC, compiler |
| [Virtual Machine](internal/vm.md) | Dispatch loop, call frames, method lookup, fibers |
| [Garbage Collector](internal/gc.md) | Tri-color marking, write barriers, generational GC |
| [Compiler Pipeline](internal/compiler.md) | Parser, code generator, IRep, binary format |
| [Opcodes](internal/opcode.md) | VM instruction set reference |
| [Value Boxing](internal/boxing.md) | How `mrb_value` encodes types |
| Document | Description |
| -------- | ----------- |
| [Architecture](internal/architecture.md) | Overview of object model, VM, GC, compiler |
| [Virtual Machine](internal/vm.md) | Dispatch loop, call frames, method lookup, fibers |
| [Garbage Collector](internal/gc.md) | Tri-color marking, write barriers, generational GC |
| [Compiler Pipeline](internal/compiler.md) | Parser, code generator, IRep, binary format |
| [Opcodes](internal/opcode.md) | VM instruction set reference |
| [Value Boxing](internal/boxing.md) | How `mrb_value` encodes types |
## Release Notes
+87 -87
View File
@@ -205,11 +205,11 @@ mruby's numeric type sizes depend on the boxing mode and platform.
### Integer
| Configuration | Range |
| -------------------------------------- | ---------------- |
| Configuration | Range |
| ------------- | ----- |
| 64-bit word boxing (default on 64-bit) | roughly +/- 2^62 |
| 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
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):
| Class | Notes |
| ------------- | -------------------------------------- |
| Object | Base class for all objects |
| Module | Module definition and mixin |
| Class | Class definition and instantiation |
| NilClass | Singleton `nil` |
| TrueClass | Singleton `true` |
| FalseClass | Singleton `false` |
| Integer | Fixed-precision integer |
| Float | Floating-point (unless `MRB_NO_FLOAT`) |
| Symbol | Interned identifier |
| String | Mutable byte string |
| Array | Ordered collection |
| Hash | Key-value mapping |
| Range | Interval representation |
| Proc | Closure / callable object |
| Exception | Exception hierarchy root |
| StandardError | Common error base |
| Class | Notes |
| ----- | ----- |
| Object | Base class for all objects |
| Module | Module definition and mixin |
| Class | Class definition and instantiation |
| NilClass | Singleton `nil` |
| TrueClass | Singleton `true` |
| FalseClass | Singleton `false` |
| Integer | Fixed-precision integer |
| Float | Floating-point (unless `MRB_NO_FLOAT`) |
| Symbol | Interned identifier |
| String | Mutable byte string |
| Array | Ordered collection |
| Hash | Key-value mapping |
| Range | Interval representation |
| Proc | Closure / callable object |
| Exception | Exception hierarchy root |
| StandardError | Common error base |
### Core Modules
| Module | Notes |
| ---------- | ----------------------------------------- |
| Kernel | Core methods (`puts`, `p`, `raise`, etc.) |
| Comparable | Comparison operators via `<=>` |
| Enumerable | Collection iteration methods |
| Module | Notes |
| ------ | ----- |
| Kernel | Core methods (`puts`, `p`, `raise`, etc.) |
| Comparable | Comparison operators via `<=>` |
| Enumerable | Collection iteration methods |
## Standard Library (via gemboxes)
@@ -270,70 +270,70 @@ gembox provides the class or feature you need:
### Classes and Modules
| Class/Module | Gembox | Gem |
| --------------------- | ---------- | ----------------- |
| Fiber | stdlib | mruby-fiber |
| Enumerator | stdlib | mruby-enumerator |
| Enumerator::Lazy | stdlib | mruby-enum-lazy |
| Set | stdlib | mruby-set |
| ObjectSpace | stdlib | mruby-objectspace |
| Time | stdlib-ext | mruby-time |
| Struct | stdlib-ext | mruby-struct |
| Data | stdlib-ext | mruby-data |
| Random | stdlib-ext | mruby-random |
| IO, File | stdlib-io | mruby-io |
| Socket | stdlib-io | mruby-socket |
| Dir | stdlib-io | mruby-dir |
| Errno | stdlib-io | mruby-errno |
| Math | math | mruby-math |
| Rational | math | mruby-rational |
| Complex | math | mruby-complex |
| Bigint | math | mruby-bigint |
| Method, UnboundMethod | metaprog | mruby-method |
| Class/Module | Gembox | Gem |
| ------------ | ------ | --- |
| Fiber | stdlib | mruby-fiber |
| Enumerator | stdlib | mruby-enumerator |
| Enumerator::Lazy | stdlib | mruby-enum-lazy |
| Set | stdlib | mruby-set |
| ObjectSpace | stdlib | mruby-objectspace |
| Time | stdlib-ext | mruby-time |
| Struct | stdlib-ext | mruby-struct |
| Data | stdlib-ext | mruby-data |
| Random | stdlib-ext | mruby-random |
| IO, File | stdlib-io | mruby-io |
| Socket | stdlib-io | mruby-socket |
| Dir | stdlib-io | mruby-dir |
| Errno | stdlib-io | mruby-errno |
| Math | math | mruby-math |
| Rational | math | mruby-rational |
| Complex | math | mruby-complex |
| Bigint | math | mruby-bigint |
| Method, UnboundMethod | metaprog | mruby-method |
### Methods and Features
| Feature | Gembox | Gem |
| ----------------------------- | ---------- | ------------------ |
| `catch`/`throw` | stdlib | mruby-catch |
| `Kernel#sprintf`, `String#%` | stdlib-ext | mruby-sprintf |
| `Array#pack`, `String#unpack` | stdlib-ext | mruby-pack |
| `Kernel#rand` | stdlib-ext | mruby-random |
| `Kernel#eval` | metaprog | mruby-eval |
| `Kernel#binding` | metaprog | mruby-binding |
| `Proc#binding` | metaprog | mruby-proc-binding |
| Runtime compiler | metaprog | mruby-compiler |
| Feature | Gembox | Gem |
| ------- | ------ | --- |
| `catch`/`throw` | stdlib | mruby-catch |
| `Kernel#sprintf`, `String#%` | stdlib-ext | mruby-sprintf |
| `Array#pack`, `String#unpack` | stdlib-ext | mruby-pack |
| `Kernel#rand` | stdlib-ext | mruby-random |
| `Kernel#eval` | metaprog | mruby-eval |
| `Kernel#binding` | metaprog | mruby-binding |
| `Proc#binding` | metaprog | mruby-proc-binding |
| Runtime compiler | metaprog | mruby-compiler |
### Core Class Extensions
The `stdlib` gembox also extends built-in classes with additional
methods. These are included by default:
| Extension | Examples |
| ----------------------- | ---------------------------------------------- |
| Array extensions | `#dig`, `#union`, `#difference` |
| Hash extensions | `#dig`, `#transform_keys`, `#transform_values` |
| String extensions | `#encode`, `#bytes`, `#chars` |
| Numeric extensions | `Integer#digits`, `Integer#pow` |
| Comparable extensions | `#clamp` |
| Enumerable extensions | `#sort_by`, `#min_by`, `#max_by`, `#tally` |
| Range extensions | `#size`, `#cover?` |
| Proc extensions | `#<<`, `#>>` (composition) |
| Symbol extensions | `#to_proc` |
| Object extensions | `#then`, `#yield_self` |
| Kernel extensions | `#__method__` |
| Class/Module extensions | `Module#name` |
| Extension | Examples |
| --------- | -------- |
| Array extensions | `#dig`, `#union`, `#difference` |
| Hash extensions | `#dig`, `#transform_keys`, `#transform_values` |
| String extensions | `#encode`, `#bytes`, `#chars` |
| Numeric extensions | `Integer#digits`, `Integer#pow` |
| Comparable extensions | `#clamp` |
| Enumerable extensions | `#sort_by`, `#min_by`, `#max_by`, `#tally` |
| Range extensions | `#size`, `#cover?` |
| Proc extensions | `#<<`, `#>>` (composition) |
| Symbol extensions | `#to_proc` |
| Object extensions | `#then`, `#yield_self` |
| Kernel extensions | `#__method__` |
| Class/Module extensions | `Module#name` |
### Gembox Summary
| Gembox | Contents | Notes |
| ------------ | --------------------------------------------- | -------------------------------------------- |
| `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-io` | IO, File, Dir, Socket, Errno | Requires 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` |
| `default` | All of the above + CLI tools | Full installation |
| Gembox | Contents | Notes |
| ------ | -------- | ----- |
| `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-io` | IO, File, Dir, Socket, Errno | Requires 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` |
| `default` | All of the above + CLI tools | Full installation |
## Key Differences from CRuby
@@ -416,15 +416,15 @@ differently on 32-bit or NaN boxing configurations.
Key compile-time macros that affect language behavior:
| Macro | Effect |
| -------------------- | ---------------------------------- |
| `MRB_NO_FLOAT` | Remove all float support |
| `MRB_USE_FLOAT32` | Use 32-bit float instead of double |
| `MRB_UTF8_STRING` | Enable UTF-8 string handling |
| `MRB_INT32` | Force 32-bit integer |
| `MRB_INT64` | Force 64-bit integer |
| `MRB_STR_LENGTH_MAX` | Max string length (default 1MB) |
| `MRB_ARY_LENGTH_MAX` | Max array length (default 2^17) |
| Macro | Effect |
| ----- | ------ |
| `MRB_NO_FLOAT` | Remove all float support |
| `MRB_USE_FLOAT32` | Use 32-bit float instead of double |
| `MRB_UTF8_STRING` | Enable UTF-8 string handling |
| `MRB_INT32` | Force 32-bit integer |
| `MRB_INT64` | Force 64-bit integer |
| `MRB_STR_LENGTH_MAX` | Max string length (default 1MB) |
| `MRB_ARY_LENGTH_MAX` | Max array length (default 2^17) |
See [mrbconf.md](mrbconf.md) for the complete list of configuration
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).
Each page occupies:
| Platform | Slot size | Page size (approx) |
| -------- | --------- | ------------------ |
| 64-bit | 40 bytes | ~41 KB |
| 32-bit | 24 bytes | ~25 KB |
| Platform | Slot size | Page size (approx) |
|----------|-----------|---------------------|
| 64-bit | 40 bytes | ~41 KB |
| 32-bit | 24 bytes | ~25 KB |
To estimate pages for a given buffer: `pages = buffer_size / sizeof(mrb_heap_page)`.
Each page provides `MRB_HEAP_PAGE_SIZE` object slots.
+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`:
| Struct | Ruby Type | Extra Fields |
| ------------ | ---------------- | ---------------------------------- |
| `RObject` | Object instances | `iv` (instance variables) |
| `RClass` | Class/Module | `iv`, `mt` (method table), `super` |
| `RString` | String | embedded or heap buffer, length |
| `RArray` | Array | embedded or heap buffer, length |
| `RHash` | Hash | hash table or k-v array |
| `RProc` | Proc/Lambda | `irep` or C function, environment |
| `RData` | C data wrapper | `void *data`, `mrb_data_type` |
| `RFiber` | Fiber | `mrb_context` |
| `RException` | Exception | `iv` |
| Struct | Ruby Type | Extra Fields |
| ------ | --------- | ------------ |
| `RObject` | Object instances | `iv` (instance variables) |
| `RClass` | Class/Module | `iv`, `mt` (method table), `super` |
| `RString` | String | embedded or heap buffer, length |
| `RArray` | Array | embedded or heap buffer, length |
| `RHash` | Hash | hash table or k-v array |
| `RProc` | Proc/Lambda | `irep` or C function, environment |
| `RData` | C data wrapper | `void *data`, `mrb_data_type` |
| `RFiber` | Fiber | `mrb_context` |
| `RException` | Exception | `iv` |
Immediate values (Integer, Symbol, `true`, `false`, `nil`) are encoded
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/`)
| File | Responsibility |
| ------------- | ---------------------------------------------- |
| `vm.c` | Bytecode dispatch loop, method invocation |
| `state.c` | `mrb_state` init/close, irep management |
| `gc.c` | Garbage collector (mark-sweep, incremental) |
| `class.c` | Class/module definition, method tables |
| `object.c` | Core object operations |
| `variable.c` | Instance/class/global variables, object shapes |
| `proc.c` | Proc/Lambda/closure handling |
| `array.c` | Array implementation |
| `string.c` | String implementation (embedded, shared, heap) |
| `hash.c` | Hash implementation (open addressing) |
| `numeric.c` | Integer/Float arithmetic |
| `symbol.c` | Symbol table and interning |
| `range.c` | Range implementation |
| `error.c` | Exception creation, raise, backtrace |
| `kernel.c` | Kernel module methods |
| `load.c` | `.mrb` bytecode loading |
| `dump.c` | Bytecode serialization (write `.mrb`) |
| `print.c` | Print/puts/p output |
| `backtrace.c` | Stack trace generation |
| File | Responsibility |
| ---- | -------------- |
| `vm.c` | Bytecode dispatch loop, method invocation |
| `state.c` | `mrb_state` init/close, irep management |
| `gc.c` | Garbage collector (mark-sweep, incremental) |
| `class.c` | Class/module definition, method tables |
| `object.c` | Core object operations |
| `variable.c` | Instance/class/global variables, object shapes |
| `proc.c` | Proc/Lambda/closure handling |
| `array.c` | Array implementation |
| `string.c` | String implementation (embedded, shared, heap) |
| `hash.c` | Hash implementation (open addressing) |
| `numeric.c` | Integer/Float arithmetic |
| `symbol.c` | Symbol table and interning |
| `range.c` | Range implementation |
| `error.c` | Exception creation, raise, backtrace |
| `kernel.c` | Kernel module methods |
| `load.c` | `.mrb` bytecode loading |
| `dump.c` | Bytecode serialization (write `.mrb`) |
| `print.c` | Print/puts/p output |
| `backtrace.c` | Stack trace generation |
### Compiler (`mrbgems/mruby-compiler/core/`)
| File | Responsibility |
| ----------- | ------------------------------- |
| `parse.y` | Yacc grammar → AST |
| `y.tab.c` | Generated parser (from parse.y) |
| `codegen.c` | AST → bytecode (irep) |
| `node.h` | AST node type definitions |
| File | Responsibility |
| ---- | -------------- |
| `parse.y` | Yacc grammar → AST |
| `y.tab.c` | Generated parser (from parse.y) |
| `codegen.c` | AST → bytecode (irep) |
| `node.h` | AST node type definitions |
### Key Headers (`include/mruby/`)
| Header | Contents |
| ------------ | ------------------------------------- |
| `mruby.h` | `mrb_state`, core API declarations |
| `value.h` | `mrb_value`, type enums, value macros |
| `object.h` | `RBasic`, `RObject`, object header |
| `class.h` | `RClass`, method table types |
| `string.h` | `RString`, string macros |
| `array.h` | `RArray`, array macros |
| `hash.h` | `RHash`, hash API |
| `data.h` | `RData`, C data wrapping |
| `irep.h` | `mrb_irep`, bytecode structures |
| `compile.h` | Compiler context, `mrb_load_string` |
| `boxing_*.h` | Value boxing implementations |
| Header | Contents |
| ------ | -------- |
| `mruby.h` | `mrb_state`, core API declarations |
| `value.h` | `mrb_value`, type enums, value macros |
| `object.h` | `RBasic`, `RObject`, object header |
| `class.h` | `RClass`, method table types |
| `string.h` | `RString`, string macros |
| `array.h` | `RArray`, array macros |
| `hash.h` | `RHash`, hash API |
| `data.h` | `RData`, C data wrapping |
| `irep.h` | `mrb_irep`, bytecode structures |
| `compile.h` | Compiler context, `mrb_load_string` |
| `boxing_*.h` | Value boxing implementations |
## 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
| Property | Word Boxing | NaN Boxing | No Boxing |
| ---------------------- | ----------------- | ---------------- | -------------------- |
| `mrb_value` size | 1 word (4/8 byte) | 8 bytes | 2 words (8/16 bytes) |
| Default on | most platforms | (manual opt-in) | `host-debug` |
| Macro | `MRB_WORD_BOXING` | `MRB_NAN_BOXING` | `MRB_NO_BOXING` |
| 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 (32-bit) | no (heap RFloat) | yes (native) | yes (struct field) |
| Pointer size limit | none | 48 bits | none |
| Debugger friendly | no | no | yes |
| Property | Word Boxing | NaN Boxing | No Boxing |
| ---------------------- | ------------------ | ------------------ | -------------------- |
| `mrb_value` size | 1 word (4/8 byte) | 8 bytes | 2 words (8/16 bytes) |
| Default on | most platforms | (manual opt-in) | `host-debug` |
| Macro | `MRB_WORD_BOXING` | `MRB_NAN_BOXING` | `MRB_NO_BOXING` |
| 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 (32-bit) | no (heap RFloat) | yes (native) | yes (struct field) |
| Pointer size limit | none | 48 bits | none |
| Debugger friendly | no | no | yes |
## 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`:
- **lstate**: current lexer state (EXPR_BEG, EXPR_END, EXPR_ARG,
EXPR_DOT, EXPR_FNAME, etc.). Controls how tokens like `+`/`-`
- **lstate**: current lexer state (EXPR\_BEG, EXPR\_END, EXPR\_ARG,
EXPR\_DOT, EXPR\_FNAME, etc.). Controls how tokens like `+`/`-`
are interpreted (sign vs operator) and whether newlines are
significant.
- **locals**: stack of local variable lists (one per scope), stored
as cons-lists of symbols.
- **lex_strterm**: string/heredoc parsing state for handling nested
- **lex\_strterm**: string/heredoc parsing state for handling nested
interpolation.
- **cond_stack**, **cmdarg_stack**: bit stacks tracking
- **cond\_stack**, **cmdarg\_stack**: bit stacks tracking
conditional and command argument contexts.
- **tree**: root AST node after successful parse.
- **error_buffer**: accumulated parse errors.
- **error\_buffer**: accumulated parse errors.
### AST Nodes
@@ -123,10 +123,10 @@ reuse temporaries within an expression.
Instructions are emitted via helper functions:
- `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)
- `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_W(opcode, a)`: 24-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:
| Type | Tag | Description |
| ---------------- | --- | ------------------------------- |
| `IREP_TT_STR` | 0 | Dynamic string (heap allocated) |
| `IREP_TT_SSTR` | 2 | Static string (read-only) |
| `IREP_TT_INT32` | 1 | 32-bit integer |
| `IREP_TT_INT64` | 3 | 64-bit integer |
| `IREP_TT_FLOAT` | 5 | Floating-point number |
| `IREP_TT_BIGINT` | 7 | Arbitrary-precision integer |
| Type | Tag | Description |
| ---- | --- | ----------- |
| `IREP_TT_STR` | 0 | Dynamic string (heap allocated) |
| `IREP_TT_SSTR` | 2 | Static string (read-only) |
| `IREP_TT_INT32` | 1 | 32-bit integer |
| `IREP_TT_INT64` | 3 | 64-bit integer |
| `IREP_TT_FLOAT` | 5 | Floating-point number |
| `IREP_TT_BIGINT` | 7 | Arbitrary-precision integer |
The code generator deduplicates pool entries: identical strings
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
255, extension prefixes widen operands to 16 bits:
| Prefix | Effect |
| --------- | --------------------------------- |
| `OP_EXT1` | First operand (a) becomes 16-bit |
| Prefix | Effect |
| ------ | ------ |
| `OP_EXT1` | First operand (a) 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:
| Format | Layout | Size |
| ------ | ----------------------------- | ------- |
| Z | opcode only | 1 byte |
| B | opcode + a(8) | 2 bytes |
| BB | opcode + a(8) + b(8) | 3 bytes |
| BBB | opcode + a(8) + b(8) + c(8) | 4 bytes |
| BS | opcode + a(8) + b(16) | 4 bytes |
| BSS | opcode + a(8) + b(16) + c(16) | 6 bytes |
| S | opcode + a(16) | 3 bytes |
| W | opcode + a(24) | 4 bytes |
| Format | Layout | Size |
| ------ | ------ | ---- |
| Z | opcode only | 1 byte |
| B | opcode + a(8) | 2 bytes |
| BB | opcode + a(8) + b(8) | 3 bytes |
| BBB | opcode + a(8) + b(8) + c(8) | 4 bytes |
| BS | opcode + a(8) + b(16) | 4 bytes |
| BSS | opcode + a(8) + b(16) + c(16) | 6 bytes |
| S | opcode + a(16) | 3 bytes |
| W | opcode + a(24) | 4 bytes |
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
(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
names to compile-time constants:
| Macro | Example | Symbol |
| ----------------- | --------------------- | ------------- |
| `MRB_SYM(name)` | `MRB_SYM(initialize)` | `:initialize` |
| `MRB_SYM_B(name)` | `MRB_SYM_B(map)` | `:map!` |
| `MRB_SYM_Q(name)` | `MRB_SYM_Q(nil)` | `:nil?` |
| `MRB_SYM_E(name)` | `MRB_SYM_E(name)` | `:name=` |
| `MRB_OPSYM(op)` | `MRB_OPSYM(add)` | `:+` |
| `MRB_IVSYM(name)` | `MRB_IVSYM(name)` | `:@name` |
| `MRB_CVSYM(name)` | `MRB_CVSYM(count)` | `:@@count` |
| `MRB_GVSYM(name)` | `MRB_GVSYM(stdout)` | `:$stdout` |
| Macro | Example | Symbol |
| ----- | ------- | ------ |
| `MRB_SYM(name)` | `MRB_SYM(initialize)` | `:initialize` |
| `MRB_SYM_B(name)` | `MRB_SYM_B(map)` | `:map!` |
| `MRB_SYM_Q(name)` | `MRB_SYM_Q(nil)` | `:nil?` |
| `MRB_SYM_E(name)` | `MRB_SYM_E(name)` | `:name=` |
| `MRB_OPSYM(op)` | `MRB_OPSYM(add)` | `:+` |
| `MRB_IVSYM(name)` | `MRB_IVSYM(name)` | `:@name` |
| `MRB_CVSYM(name)` | `MRB_CVSYM(count)` | `:@@count` |
| `MRB_GVSYM(name)` | `MRB_GVSYM(stdout)` | `:$stdout` |
## Binary Format (.mrb)
@@ -299,25 +299,25 @@ mrbc -Boutput source.rb # C array format
## Compilation Limits
| Limit | Value |
| ---------------------- | ----------------------------- |
| Max nesting depth | 256 (`MRB_CODEGEN_LEVEL_MAX`) |
| Max local variables | 255 (uint16 `nlocals`) |
| Max symbols per irep | 65535 |
| Max operand (standard) | 255 (8-bit) |
| Max operand (extended) | 65535 (16-bit) |
| Limit | Value |
| ----- | ----- |
| Max nesting depth | 256 (`MRB_CODEGEN_LEVEL_MAX`) |
| Max local variables | 255 (uint16 `nlocals`) |
| Max symbols per irep | 65535 |
| Max operand (standard) | 255 (8-bit) |
| Max operand (extended) | 65535 (16-bit) |
## Source Files
| File | Contents |
| --------------------------------------- | ------------------------- |
| `mrbgems/mruby-compiler/core/parse.y` | Lrama/Bison grammar |
| `mrbgems/mruby-compiler/core/y.tab.c` | Generated parser |
| `mrbgems/mruby-compiler/core/codegen.c` | Code generator |
| `mrbgems/mruby-compiler/core/node.h` | AST node types |
| `include/mruby/irep.h` | IRep structure definition |
| `include/mruby/compile.h` | Compiler context API |
| `include/mruby/ops.h` | Opcode definitions |
| `src/load.c` | Binary format loader |
| `src/dump.c` | Binary format writer |
| `lib/mruby/presym.rb` | Presym table generator |
| File | Contents |
| ---- | -------- |
| `mrbgems/mruby-compiler/core/parse.y` | Lrama/Bison grammar |
| `mrbgems/mruby-compiler/core/y.tab.c` | Generated parser |
| `mrbgems/mruby-compiler/core/codegen.c` | Code generator |
| `mrbgems/mruby-compiler/core/node.h` | AST node types |
| `include/mruby/irep.h` | IRep structure definition |
| `include/mruby/compile.h` | Compiler context API |
| `include/mruby/ops.h` | Opcode definitions |
| `src/load.c` | Binary format loader |
| `src/dump.c` | Binary format writer |
| `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
`RBasic::gc_color` (3 bits):
| Color | Value | Meaning |
| -------------- | ------ | ------------------------------------ |
| White (A or B) | 1 or 2 | Unmarked, candidate for collection |
| Gray | 0 | Marked, but children not yet scanned |
| Black | 4 | Fully marked and scanned |
| Red | 7 | Static/ROM object, never collected |
| Color | Value | Meaning |
| ----- | ----- | ------- |
| White (A or B) | 1 or 2 | Unmarked, candidate for collection |
| Gray | 0 | Marked, but children not yet scanned |
| Black | 4 | Fully marked and scanned |
| Red | 7 | Static/ROM object, never collected |
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
@@ -107,7 +107,7 @@ The GC operates as a three-state machine:
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:
@@ -121,7 +121,7 @@ Marks objects directly reachable from the VM:
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
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
marking, then transitions to sweep.
### Sweep (GC_STATE_SWEEP)
### Sweep (GC\_STATE\_SWEEP)
Iterates through heap pages. For each object:
@@ -325,15 +325,15 @@ From Ruby: `GC.start`.
### Compile-Time
| Macro | Default | Description |
| ------------------------------ | ------- | --------------------------------------- |
| `MRB_HEAP_PAGE_SIZE` | 1024 | Objects per heap page |
| `MRB_GRAY_STACK_SIZE` | 1024 | Gray stack capacity |
| `MRB_GC_ARENA_SIZE` | 100 | Arena size (fixed mode) or initial size |
| `MRB_GC_FIXED_ARENA` | off | Use fixed-size arena |
| `MRB_GC_TURN_OFF_GENERATIONAL` | off | Disable generational mode |
| `MRB_GC_STRESS` | off | Full GC on every allocation (debug) |
| `MRB_USE_MALLOC_TRIM` | off | Call `malloc_trim()` after full GC |
| Macro | Default | Description |
| ----- | ------- | ----------- |
| `MRB_HEAP_PAGE_SIZE` | 1024 | Objects per heap page |
| `MRB_GRAY_STACK_SIZE` | 1024 | Gray stack capacity |
| `MRB_GC_ARENA_SIZE` | 100 | Arena size (fixed mode) or initial size |
| `MRB_GC_FIXED_ARENA` | off | Use fixed-size arena |
| `MRB_GC_TURN_OFF_GENERATIONAL` | off | Disable generational mode |
| `MRB_GC_STRESS` | off | Full GC on every allocation (debug) |
| `MRB_USE_MALLOC_TRIM` | off | Call `malloc_trim()` after full GC |
### Runtime
@@ -350,8 +350,8 @@ GC.disable # disable GC
## Source Files
| File | Contents |
| -------------------- | --------------------------------- |
| `src/gc.c` | GC implementation (~1400 lines) |
| File | Contents |
| ---- | -------- |
| `src/gc.c` | GC implementation (~1400 lines) |
| `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)
| Value | Name | Meaning |
| ----- | --------------- | ------------------------------------- |
| 0 | `CINFO_NONE` | Normal VM-to-VM call |
| 1 | `CINFO_DIRECT` | Explicit VM call (block, lambda.call) |
| 2 | `CINFO_SKIP` | Skip frame in stack traces |
| 3 | `CINFO_RESUMED` | Fiber resumed (stop execution) |
| Value | Name | Meaning |
| ----- | ---- | ------- |
| 0 | `CINFO_NONE` | Normal VM-to-VM call |
| 1 | `CINFO_DIRECT` | Explicit VM call (block, lambda.call) |
| 2 | `CINFO_SKIP` | Skip frame in stack traces |
| 3 | `CINFO_RESUMED` | Fiber resumed (stop execution) |
## Dispatch Loop
@@ -241,13 +241,13 @@ correctness.
### Proc Types
| Flag | Meaning |
| ------------------- | ------------------------------ |
| `MRB_PROC_CFUNC_FL` | C function (not irep-based) |
| `MRB_PROC_STRICT` | Lambda (strict argument check) |
| `MRB_PROC_ORPHAN` | No environment attachment |
| `MRB_PROC_ENVSET` | Has captured environment |
| `MRB_PROC_SCOPE` | Defines a new variable scope |
| Flag | Meaning |
| ---- | ------- |
| `MRB_PROC_CFUNC_FL` | C function (not irep-based) |
| `MRB_PROC_STRICT` | Lambda (strict argument check) |
| `MRB_PROC_ORPHAN` | No environment attachment |
| `MRB_PROC_ENVSET` | Has captured environment |
| `MRB_PROC_SCOPE` | Defines a new variable scope |
## Fiber Switching
@@ -317,9 +317,9 @@ ensuring the incremental GC correctly tracks live references.
## Source Files
| File | Contents |
| ----------------------- | ---------------------------------------------- |
| `src/vm.c` | Dispatch loop, method invocation (~1900 lines) |
| `include/mruby.h` | `mrb_state`, `mrb_callinfo`, `mrb_context` |
| `include/mruby/proc.h` | `RProc`, `REnv` structures |
| `include/mruby/throw.h` | `MRB_TRY`/`MRB_CATCH` macros |
| File | Contents |
| ---- | -------- |
| `src/vm.c` | Dispatch loop, method invocation (~1900 lines) |
| `include/mruby.h` | `mrb_state`, `mrb_callinfo`, `mrb_context` |
| `include/mruby/proc.h` | `RProc`, `REnv` structures |
| `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:
| Configuration | Integer range |
| ----------------------------- | ---------------- |
| Configuration | Integer range |
| ------------- | ------------- |
| Word boxing, 64-bit (default) | roughly +/- 2^62 |
| 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
across configurations. The `mruby-bigint` gem provides
+4 -4
View File
@@ -57,7 +57,7 @@ MRB_BEGIN_DECL
/*
* Patch level string. (optional)
*/
#define MRUBY_PATCHLEVEL_STR "RC2"
#define MRUBY_PATCHLEVEL_STR ""
#ifndef MRUBY_PATCHLEVEL_STR
# if MRUBY_PATCHLEVEL < 0
@@ -80,17 +80,17 @@ MRB_BEGIN_DECL
/*
* Release year.
*/
#define MRUBY_RELEASE_YEAR 2026
#define MRUBY_RELEASE_YEAR 2025
/*
* Release month.
*/
#define MRUBY_RELEASE_MONTH 3
#define MRUBY_RELEASE_MONTH 4
/*
* Release day.
*/
#define MRUBY_RELEASE_DAY 12
#define MRUBY_RELEASE_DAY 20
/*
* Release date as a string.
+1 -2
View File
@@ -109,8 +109,7 @@ module MRuby
if build.kind_of?(MRuby::CrossBuild)
return %w(x86_64-w64-mingw32 i686-w64-mingw32).include?(build.host_target)
elsif build.kind_of?(MRuby::Build)
return ('A'..'Z').to_a.any? { |vol| Dir.exist?("#{vol}:") } ||
('a'..'z').to_a.any? { |vol| Dir.exist?("/#{vol}/") }
return ('A'..'Z').to_a.any? { |vol| Dir.exist?("#{vol}:") }
end
return false
end
+6 -33
View File
@@ -3175,12 +3175,8 @@ gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
{
if (val) {
int array_size = 0;
int first = 1;
int slimit = GEN_LIT_ARY_MAX;
node *current = tree;
if (cursp() >= slimit) slimit = GEN_VAL_STACK_MAX;
/* Process each segment separated by NODE_LITERAL_DELIM */
while (current) {
/* Find the segment boundaries without allocating */
@@ -3217,24 +3213,6 @@ gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
/* Only process non-empty segments */
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 */
node *saved_cdr = NULL;
if (segment_prev) {
@@ -3265,14 +3243,8 @@ gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
}
}
/* Handle remaining elements */
if (!first) {
if (array_size > 0) {
pop_n(array_size + 1);
genop_2(s, OP_ARYPUSH, cursp(), array_size);
}
}
else if (array_size > 0) {
/* Generate the array from pushed elements */
if (array_size > 0) {
pop_n(array_size);
genop_2(s, OP_ARRAY, cursp(), array_size);
}
@@ -4455,9 +4427,10 @@ codegen_case_match(codegen_scope *s, node *varnode, int val)
current_in = current_in->cdr;
}
/* No pattern matched - raise NoMatchingPatternError */
genop_1(s, OP_LOADFALSE, cursp());
genop_1(s, OP_MATCHERR, cursp());
/* No pattern matched - generate nil or error */
if (val) {
genop_1(s, OP_LOADNIL, cursp());
}
/* Dispatch all end jumps */
if (case_end_jumps != JMPLINK_START) {
+5 -6
View File
@@ -1246,13 +1246,12 @@ assert('pattern matching - NoMatchingPatternError') do
assert_true e.message.is_a?(String)
end
# case/in without else raises NoMatchingPatternError
assert_raise(NoMatchingPatternError) do
case 5
in 1 then :one
in 2 then :two
end
# case/in without else returns nil (no match)
result = case 5
in 1 then :one
in 2 then :two
end
assert_nil result
end
assert('pattern matching - complex patterns') do