diff --git a/doc/README.md b/doc/README.md index 13febf02b..0d6f6e617 100644 --- a/doc/README.md +++ b/doc/README.md @@ -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 diff --git a/doc/guides/language.md b/doc/guides/language.md index f6a9e8cbf..31c9b074d 100644 --- a/doc/guides/language.md +++ b/doc/guides/language.md @@ -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. diff --git a/doc/guides/memory.md b/doc/guides/memory.md index c48945daf..5f3652850 100644 --- a/doc/guides/memory.md +++ b/doc/guides/memory.md @@ -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. diff --git a/doc/internal/architecture.md b/doc/internal/architecture.md index b57e95561..438dc823d 100644 --- a/doc/internal/architecture.md +++ b/doc/internal/architecture.md @@ -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 diff --git a/doc/internal/boxing.md b/doc/internal/boxing.md index 33dcbd860..653d8c3a1 100644 --- a/doc/internal/boxing.md +++ b/doc/internal/boxing.md @@ -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 diff --git a/doc/internal/compiler.md b/doc/internal/compiler.md index 92cbac614..7f83ab16f 100644 --- a/doc/internal/compiler.md +++ b/doc/internal/compiler.md @@ -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 | diff --git a/doc/internal/gc.md b/doc/internal/gc.md index 87cc264fe..3171bcbe1 100644 --- a/doc/internal/gc.md +++ b/doc/internal/gc.md @@ -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 | diff --git a/doc/internal/vm.md b/doc/internal/vm.md index bbbf4338f..10af1a282 100644 --- a/doc/internal/vm.md +++ b/doc/internal/vm.md @@ -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 | diff --git a/doc/limitations.md b/doc/limitations.md index 575ddf00b..5d7a3181f 100644 --- a/doc/limitations.md +++ b/doc/limitations.md @@ -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 diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 1b804a4f6..48cae6569 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -4455,10 +4455,9 @@ codegen_case_match(codegen_scope *s, node *varnode, int val) current_in = current_in->cdr; } - /* No pattern matched - generate nil or error */ - if (val) { - genop_1(s, OP_LOADNIL, cursp()); - } + /* No pattern matched - raise NoMatchingPatternError */ + genop_1(s, OP_LOADFALSE, cursp()); + genop_1(s, OP_MATCHERR, cursp()); /* Dispatch all end jumps */ if (case_end_jumps != JMPLINK_START) { diff --git a/test/t/syntax.rb b/test/t/syntax.rb index 42a6d4198..a02ca1d8a 100644 --- a/test/t/syntax.rb +++ b/test/t/syntax.rb @@ -1246,12 +1246,13 @@ assert('pattern matching - NoMatchingPatternError') do assert_true e.message.is_a?(String) end - # case/in without else returns nil (no match) - result = case 5 - in 1 then :one - in 2 then :two + # case/in without else raises NoMatchingPatternError + assert_raise(NoMatchingPatternError) do + case 5 + in 1 then :one + in 2 then :two + end end - assert_nil result end assert('pattern matching - complex patterns') do