Move String's 46 method definitions from runtime
mrb_define_method_id() calls to a static ROM method table
sorted at init time. mrb_mt_init_rom() sorts the parallel
vals/keys arrays by presym ID and sets the readonly flag.
Expose mt_tbl and related types in internal.h so ROM tables
can be defined in individual source files.
When MRB_NO_PRESYM is defined, falls back to traditional
runtime method registration.
Co-authored-by: Claude <noreply@anthropic.com>
Add next pointer and readonly flag to mt_tbl struct to support
chained ROM method table layers. mt_get() walks the chain,
mt_copy() shares ROM layers, mt_free() and mrb_gc_mark_mt() skip
readonly layers. COW in mrb_define_method_raw() creates a mutable
top layer when the existing table is readonly. mt_flatten() merges
all layers for the rare remove_method case.
No ROM tables exist yet -- all tables have next==NULL and no
readonly flag, so behavior is identical to the previous code.
Co-authored-by: Claude <noreply@anthropic.com>
iso.org blocks automated HTTP requests with 403 Forbidden.
Also update the ISO 30170 URLs to current format in README.md
and CONTRIBUTING.md.
Co-authored-by: Claude <noreply@anthropic.com>
Encode 0.0, -0.0, +Inf, -Inf, and NaN as small sentinel constants
with the float tag pattern, avoiding heap allocation for these common
special values. All NaN bit patterns are normalized to a single
canonical NaN. The 5 obscure floats near 2^(-255) whose rotation
encoding would collide with a sentinel are heap-allocated instead.
Co-authored-by: Claude <noreply@anthropic.com>
Replace lossy 2-bit truncation with rotation-based encoding for
64-bit word boxing with float64. The new scheme uses
rotl64(float_bits - ADDEND, 3) to embed floats inline with full
52-bit mantissa precision. Floats with exponents outside [-255,+256]
(0.0, NaN, Inf, very small/large values) fall back to heap-allocated
RFloat.
Co-authored-by: Claude <noreply@anthropic.com>
Add Hash#__pat_values(keys) that returns an array of values if all
keys exist, or false if any key is missing. This replaces per-key
key?() + []() calls (2N hash lookups) with a single method call
(N hash lookups). The compiler generates __pat_values() followed by
array indexing to extract each value for pattern matching.
Co-authored-by: Claude <noreply@anthropic.com>
Extract the keys-to-array loop (load keys + OP_ARRAY) into
gen_pat_keys_ary() helper. The pattern appeared in both
deconstruct_keys argument and __except argument generation.
Co-authored-by: Claude <noreply@anthropic.com>
Reduce code duplication by extracting the key-loading pattern
(NODE_SYM check + OP_LOADSYM/codegen) into gen_pat_key() helper.
The pattern appeared 4 times in NODE_PAT_HASH codegen.
Co-authored-by: Claude <noreply@anthropic.com>
Simplify deconstruct_keys argument logic from 3 branches to 2:
- pass nil when rest pattern is present or no keys (all keys needed)
- pass keys array only for partial match without rest
This avoids building keys array twice when **rest is present.
Co-authored-by: Claude <noreply@anthropic.com>
mrb_get_args(mrb, "*", ...) internally allocates an array when
arguments are on the stack, so passing keys as direct arguments
did not actually avoid allocation. Change __except to take a
single array argument instead, which is simpler and GC-safe.
Co-authored-by: Claude <noreply@anthropic.com>
When a hash pattern has 15 or more keys, pack them into an array
before calling __except via OP_SEND with CALL_MAXARGS, since the
OP_SEND instruction can only encode up to 14 direct arguments.
Co-authored-by: Claude <noreply@anthropic.com>
Add Hash#__except that returns a new hash excluding specified keys,
used by the compiler for **rest capture in hash patterns. Takes keys
as direct arguments to avoid array allocation. The compiler passes
matched key symbols directly on the stack via OP_SEND.
Co-authored-by: Claude <noreply@anthropic.com>
Add key existence check using key?() before value access, so that
missing keys correctly fail to match (e.g. {b: 1} no longer matches
{a: nil} pattern). Implement **nil and empty {} exact match via
hash.size == num_keys check. Fix **rest to properly exclude matched
keys using dup + __delete instead of copying the entire hash.
Co-authored-by: Claude <noreply@anthropic.com>
CRuby's Hash#deconstruct_keys simply returns self regardless of
arguments. The mruby-hash-ext version filtered keys, which was
unnecessary since the compiler accesses individual keys via []
after calling deconstruct_keys. The Ruby implementation in
mrblib/hash.rb (returning self) is sufficient and CRuby-compatible.
Co-authored-by: Claude <noreply@anthropic.com>
mpz_abs() internally allocates via mpz_init_heap(), so
pre-allocating abs_x/abs_y with mpz_init_temp() leaked the
original allocations. let mpz_abs() handle allocation directly.
also use divide-first formula (abs_x/gcd)*abs_y to reduce
intermediate product size, and add bint_norm() for the result.
reported by OSS-Fuzz (clusterfuzz-testcase-6501272051318784).
Co-authored-by: Claude <noreply@anthropic.com>
check for overflow using mrb_int_mul_overflow() in the LCM
computation to avoid undefined behavior when the result exceeds
mrb_int range. raises RangeError instead.
reported by OSS-Fuzz (clusterfuzz-testcase-6501272051318784).
Co-authored-by: Claude <noreply@anthropic.com>
move fd, fd2, pid fields before the bitfield flags while keeping
the pointer field last. this preserves the 24-byte struct size
(same as 3.4.0) while restoring fd to offset 0 (same as 3.3.0).
some external gems (e.g. mruby-polarssl) pass struct mrb_io
pointers directly to libraries like mbedtls that expect an int fd
at offset 0. the 3.4.0 reorder moved bitfield flags to offset 0,
causing these gems to read garbage instead of the file descriptor.
fixes#6713
Co-authored-by: Claude <noreply@anthropic.com>
The prek-action already passes --color=always internally,
so passing it again via extra-args causes a CLI error.
Co-authored-by: Claude <noreply@anthropic.com>