From 3ce3453e9c8efb52d3eaad2344d9baf441c481f6 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 27 Feb 2026 19:03:29 +0900 Subject: [PATCH] docs: improve usability of new documentation language.md: reorganize stdlib tables by class name instead of gem name so users can quickly find "does mruby have Time/File/Set?" capi.md: fix mrb_protect example (mrb->exc is cleared after protect, so mrb_print_error does not work; show mrb_inspect instead); fix fiber yield example to show correct usage as return value. gc.md, compiler.md, vm.md: add "read this if" guidance paragraphs to help developers decide whether they need each document. Co-authored-by: Claude --- doc/guides/capi.md | 30 +++++++--- doc/guides/language.md | 121 +++++++++++++++++++-------------------- doc/internal/compiler.md | 5 ++ doc/internal/gc.md | 11 +++- doc/internal/vm.md | 4 ++ 5 files changed, 100 insertions(+), 71 deletions(-) diff --git a/doc/guides/capi.md b/doc/guides/capi.md index 12ffbad0b..7faabc802 100644 --- a/doc/guides/capi.md +++ b/doc/guides/capi.md @@ -402,12 +402,18 @@ safe_operation(mrb_state *mrb, mrb_value data) mrb_bool error; mrb_value result = mrb_protect(mrb, safe_operation, data, &error); if (error) { - /* result contains the exception object */ - mrb_print_error(mrb); + /* result contains the exception object; mrb->exc is cleared */ + mrb_value inspect = mrb_inspect(mrb, result); + fprintf(stderr, "Error: %s\n", mrb_str_to_cstr(mrb, inspect)); } ``` -For lower-level protection without `mrb_value` callback signature: +**Note:** `mrb_protect` clears `mrb->exc` after catching the +exception. The exception is returned as `result`. Do not use +`mrb_print_error()` after `mrb_protect` — it reads `mrb->exc` +which is already `NULL`. + +For lower-level protection with a `void*` callback: ```c static mrb_value @@ -561,14 +567,24 @@ mrb_value fiber = mrb_fiber_new(mrb, proc); mrb_value args[] = { mrb_fixnum_value(1) }; mrb_value result = mrb_fiber_resume(mrb, fiber, 1, args); -/* Yield from within a fiber (typically called from Ruby code) */ -mrb_value yield_args[] = { mrb_str_new_lit(mrb, "yielded") }; -mrb_fiber_yield(mrb, 1, yield_args); - /* Check if fiber is still alive */ mrb_bool alive = mrb_test(mrb_fiber_alive_p(mrb, fiber)); ``` +### Yielding from C + +`mrb_fiber_yield()` can only be used as the return value of a C +function — no code may execute after it: + +```c +static mrb_value +my_yield_method(mrb_state *mrb, mrb_value self) +{ + mrb_value yield_args[] = { mrb_str_new_lit(mrb, "yielded") }; + return mrb_fiber_yield(mrb, 1, yield_args); /* must be returned directly */ +} +``` + ### Fiber States | State | Meaning | diff --git a/doc/guides/language.md b/doc/guides/language.md index 8dab96734..134e4fa0e 100644 --- a/doc/guides/language.md +++ b/doc/guides/language.md @@ -252,76 +252,75 @@ These classes are always available in mruby (no gem required): ## Standard Library (via gemboxes) mruby's standard library is organized into gemboxes. The `default` -gembox includes all of the below. +gembox includes all of the below. Use this table to find which +gembox provides the class or feature you need: -### stdlib gembox +### Classes and Modules -Extensions to core classes and additional 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 | -| Gem | Provides | -| --- | -------- | -| mruby-compar-ext | `Comparable#clamp` | -| mruby-enum-ext | `Enumerable#sort_by`, `#min_by`, etc. | -| mruby-string-ext | `String#encode`, `#bytes`, etc. | -| mruby-numeric-ext | `Integer#digits`, etc. | -| mruby-array-ext | `Array#dig`, `#union`, etc. | -| mruby-hash-ext | `Hash#dig`, `#transform_keys`, etc. | -| mruby-range-ext | `Range#size`, `#cover?`, etc. | -| mruby-proc-ext | `Proc#<<`, `#>>`, etc. | -| mruby-symbol-ext | `Symbol#to_proc` | -| mruby-object-ext | `Object#then`, `#yield_self` | -| mruby-objectspace | `ObjectSpace.count_objects` | -| mruby-set | `Set` class | -| mruby-fiber | `Fiber` class (coroutines) | -| mruby-enumerator | `Enumerator` class | -| mruby-enum-lazy | `Enumerator::Lazy` | -| mruby-enum-chain | `Enumerator::Chain` | -| mruby-toplevel-ext | Top-level `define_method` | -| mruby-kernel-ext | `Kernel#__method__` | -| mruby-class-ext | `Module#name`, etc. | -| mruby-catch | `catch`/`throw` | +### Methods and Features -### stdlib-ext gembox +| 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 | -| Gem | Provides | -| --- | -------- | -| mruby-pack | `Array#pack`, `String#unpack` | -| mruby-sprintf | `Kernel#sprintf`, `String#%` | -| mruby-time | `Time` class | -| mruby-struct | `Struct` class | -| mruby-data | `Data` class | -| mruby-random | `Random` class, `Kernel#rand` | +### Core Class Extensions -### stdlib-io gembox +The `stdlib` gembox also extends built-in classes with additional +methods. These are included by default: -Requires `stdio` support (not available with `MRB_NO_STDIO`). +| 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` | -| Gem | Provides | -| --- | -------- | -| mruby-io | `IO`, `File` classes | -| mruby-socket | `Socket` classes | -| mruby-errno | `Errno` module | -| mruby-dir | `Dir` class | +### Gembox Summary -### math gembox - -| Gem | Provides | -| --- | -------- | -| mruby-math | `Math` module (`sin`, `cos`, `sqrt`, `PI`, etc.) | -| mruby-rational | `Rational` class | -| mruby-complex | `Complex` class | -| mruby-bigint | Arbitrary-precision `Integer` | - -### metaprog gembox - -| Gem | Provides | -| --- | -------- | -| mruby-metaprog | `respond_to_missing?`, etc. | -| mruby-method | `Method`, `UnboundMethod` classes | -| mruby-eval | `Kernel#eval` | -| mruby-binding | `Kernel#binding` | -| mruby-proc-binding | `Proc#binding` | -| mruby-compiler | Runtime compiler access | +| 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 diff --git a/doc/internal/compiler.md b/doc/internal/compiler.md index 23f3c8868..92cbac614 100644 --- a/doc/internal/compiler.md +++ b/doc/internal/compiler.md @@ -5,6 +5,11 @@ This document describes mruby's compilation pipeline for developers working on the parser, code generator, or bytecode format. +**Read this if you are:** adding new syntax or modifying the parser, +debugging codegen issues (wrong registers, missing opcodes), +working with the `.mrb` binary format, or understanding how Ruby +constructs map to bytecode. + ## Pipeline Overview ```text diff --git a/doc/internal/gc.md b/doc/internal/gc.md index 6cffef5d5..87cc264fe 100644 --- a/doc/internal/gc.md +++ b/doc/internal/gc.md @@ -5,9 +5,14 @@ This document describes the internals of mruby's garbage collector for developers working on `src/gc.c` and related code. -For user-facing GC documentation, see -[gc-arena-howto.md](../guides/gc-arena-howto.md) and -[memory.md](../guides/memory.md). +**Read this if you are:** modifying core data structures that hold +object references (and need to add write barriers), debugging +memory leaks or GC-related crashes, tuning GC performance for an +embedded target, or working on the GC code itself. + +**For user-facing GC docs**, see +[gc-arena-howto.md](../guides/gc-arena-howto.md) (arena usage in C +extensions) and [memory.md](../guides/memory.md) (heap regions). ## Overview diff --git a/doc/internal/vm.md b/doc/internal/vm.md index a2586a664..bbbf4338f 100644 --- a/doc/internal/vm.md +++ b/doc/internal/vm.md @@ -5,6 +5,10 @@ This document describes mruby's virtual machine for developers working on `src/vm.c` and related code. +**Read this if you are:** debugging method dispatch or call frame +issues, working on exception handling, implementing new opcodes, +modifying fiber/coroutine behavior, or optimizing the dispatch loop. + For the instruction set, see [opcode.md](opcode.md). For the compiler that generates bytecode, see [compiler.md](compiler.md).