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>