Commit Graph

556 Commits

Author SHA1 Message Date
Yukihiro "Matz" Matsumoto c46f9e0793 mruby-compiler: fix uninitialized memory in realloc_pool_str()
when converting a shared/static string (IREP_TT_SSTR) to heap-allocated
(IREP_TT_STR), copy the original content to the new buffer.

previously, the original content was lost when allocating new memory,
leaving the first bytes uninitialized. this caused find_pool_str() to
read uninitialized memory via memcmp() when searching for duplicate
strings.

reported by OSS-Fuzz.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-08 12:58:22 +09:00
Yukihiro "Matz" Matsumoto 2e4a8e8edd mruby-compiler: fix sp tracking in pattern match failure path
After pattern matching code generation, the sp (stack pointer) must
be restored to match the success path value. The failure path (after
RAISEIF) left sp in a different state, causing incorrect register
allocation in subsequent code like string interpolation.

This caused OP_STRCAT to use the wrong register, leading to
null-dereference when trying to modify a non-string value as a string.

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-04 09:12:35 +09:00
Yukihiro "Matz" Matsumoto af3f9b65f1 mruby-compiler: fix sp imbalance in pattern matching with rescue
The => pattern matching codegen was doing push() after RAISEIF, even though
RAISEIF never returns. This caused sp to be off by 1 when success and failure
paths joined, resulting in wrong register allocation for subsequent operations.

For string interpolation like "#{ expr => pattern rescue body }", the base
string would be at R2 but STRCAT would incorrectly use R3, causing memory
corruption and crashes.

Test case: %{#{.=>.,. rescue def .()end}} (from oss-fuzz)

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-03 20:21:44 +09:00
Yukihiro "Matz" Matsumoto 9f0950da13 codegen.c: fix stack tracking in pattern match branching code
When generating code for pattern matching with potential failures, the
success and failure paths both need to pop the matched value. At
runtime, only one path executes. But during codegen, both pop() calls
affected the compile-time stack pointer (cursp), corrupting register
allocation and causing heap-buffer-overflow when accessing symbol
tables with wrong indices.

Fix by saving/restoring the stack pointer around the branch point, so
each path correctly tracks the stack state independently.

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-29 22:28:45 +09:00
Yukihiro "Matz" Matsumoto da2d652ec9 codegen.c: fix NODE_MATCH_PAT to push result when val is true
Pattern matching expressions were not pushing a result value in several
code paths when used in value context (e.g., string interpolation).
This caused crashes when the result was expected on the stack.

Fix all code paths in NODE_MATCH_PAT to push the appropriate value:
- 'in' pattern returns true/false
- '=>' pattern returns nil (matches CRuby behavior)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-29 19:09:06 +09:00
Yukihiro "Matz" Matsumoto f6f8124406 codegen.c: fix crash in parallel assignment optimization
The direct literal generation optimization for parallel assignment was
using the RHS count as the loop bound but only filling registers for
LHS variables. When RHS has more elements than LHS (e.g., `a,=1,2`),
this caused uninitialized register indices to be used, generating
garbage opcodes that crashed the VM.

Fix by counting LHS variables and only applying the optimization when
LHS and RHS counts match exactly.

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-29 18:19:58 +09:00
Yukihiro "Matz" Matsumoto d1aa722a98 mruby-compiler: fix JMPNOT+JMP optimization for nested alternatives
The previous optimization for converting JMPNOT+JMP to JMPIF in
alternative patterns had two bugs:

1. It triggered incorrectly for nested alternatives like `1 | 2 | 3`
   (parsed as `((1|2)|3)`), causing memory corruption.

2. The chain end detection was wrong - it checked `prev_offset == 0`
   but the chain actually ends when `(pos+2) + offset == 0`.

Fix by:
- Only applying optimization when left pattern is not NODE_PAT_ALT
- Correctly detecting chain end by checking if next_addr == 0
- Properly unlinking the last JMPNOT from the fail chain

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-25 18:01:43 +09:00
Yukihiro "Matz" Matsumoto bbd5dd690b mruby-compiler: optimize pattern matching for array literals
When the match target is a known array literal, apply these optimizations:
1. Skip #deconstruct call - array literals are already arrays
2. Skip runtime #size check - verify size at compile time
3. Use GETIDX opcode instead of SEND :[] for element access

For the general (non-array-literal) case, improve efficiency by:
- Using EQ opcode instead of SEND :== for size comparison
- Using GE opcode instead of SEND :>= for minimum length check

This reduces bytecode size by ~27% for patterns like:
  [1,2] in Array|[Integer,Integer]

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-25 18:01:43 +09:00
Yukihiro "Matz" Matsumoto e042557d53 mruby-compiler: fix pattern matching === operand order bug
When matching array/hash element patterns like `[Integer]` against
values, the element register was being overwritten by codegen before
the comparison. This caused `[1] in [Integer]|[String]` to incorrectly
return false because the bytecode was effectively doing `1.===(Integer)`
instead of `Integer.===(1)`.

Fix by preserving the element value with push() before calling
codegen_pattern, so the element stays at cursp()-1 while the pattern
value is generated at cursp().

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-24 08:20:31 +09:00
Yukihiro "Matz" Matsumoto 42cea9d3ee mruby-compiler: optimize JMPNOT+JMP to JMPIF in alternative patterns
In alternative patterns (e.g., `Integer|String`), when the left pattern
has a single JMPNOT immediately before the JMP to success, convert the
JMPNOT to JMPIF and eliminate the JMP instruction.

This saves 3 bytes per optimized alternative pattern.

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-24 07:45:40 +09:00
Yukihiro "Matz" Matsumoto fd01a0af73 mruby-compiler: optimize array literal pattern matching
When pattern matching an array literal against an array pattern with
matching sizes (e.g., `[1,2] => a,b`), skip the runtime calls to
#deconstruct and #size. Instead, directly extract elements using the
VM's GETIDX opcode.

This reduces bytecode from 72 to 28 bytes (61% reduction) and
eliminates 4 method calls per pattern match.

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-24 07:35:55 +09:00
Yukihiro "Matz" Matsumoto 2b72d8a7c1 mruby-compiler: optimize JMPNOT+JMP to JMPIF in pattern matching
For patterns with a single failure check (like `1 => String`), invert
JMPNOT to JMPIF and eliminate the following JMP instruction.

Before: JMPNOT fail; JMP end; fail: error; end: (8 bytes for jumps)
After:  JMPIF end; error; end: (4 bytes for jump)

The optimization only applies when:
1. There's exactly one JMPNOT in the failure chain
2. The JMPNOT is immediately before the JMP (no code between)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-23 20:12:28 +09:00
Yukihiro "Matz" Matsumoto 3af15e0012 mruby-compiler: optimize simple variable pattern to match assignment
For `1 => a`, generate the same bytecode as `a = 1` by leveraging
gen_move's peephole optimization. The peephole optimizer rewrites
LOADI+MOVE into a single LOADI to the target register.

Before: LOADI_1 R2; MOVE R1 R2 (6 bytes)
After:  LOADI_1 R1 (3 bytes)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-23 15:28:15 +09:00
Yukihiro "Matz" Matsumoto 9d4ad58adc mruby-compiler: optimize pattern matching for always-matching patterns
Skip generating failure handling code (JMP, GETCONST, STRING, SEND,
RAISEIF) when the pattern always succeeds (e.g., simple variable
binding like `1 => a`).

Before: 27 bytes for `1 => a; p a`
After: 13 bytes (52% reduction)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-23 15:19:21 +09:00
Yukihiro "Matz" Matsumoto e06ec699a4 mruby-compiler: rename get_node_type to node_type
Resolve static function name collision between parse.y and codegen.c
for amalgamation support.

- parse.y: rename get_node_type() to node_type() (keeps validation)
- codegen.c: replace with node_type() macro (NULL-safe via NODE_TYPE)
- node.h: rename VAR_NODE_TYPE() to NODE_TYPE()

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-23 12:27:12 +09:00
Yukihiro "Matz" Matsumoto acc82da637 codegen.c: rename new_sym to sym_idx
The function registers a symbol in the IREP symbol table and returns
its index. The new name better reflects this behavior and avoids
collision with parse.y's new_sym (which creates AST nodes).

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-23 11:44:22 +09:00
Yukihiro "Matz" Matsumoto 613b03ac18 mruby-compiler: add no_return_value context flag for script optimization
when running scripts via mruby -e or file, return values are unused.
this adds a no_return_value flag to skip generating unnecessary code.

for parallel assignment like a,b = 1,2:
- before: 18 bytes, 5 registers, creates temporary array
- after: 5 bytes, 3 registers, direct register assignment, no RETURN

the flag is set only for the main program, not for libraries loaded
with -r option. eval() and mirb continue returning values correctly.

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-21 17:26:49 +09:00
Yukihiro "Matz" Matsumoto fb5d966a45 mruby-compiler: optimize masgn to generate literals directly into target registers
When all lhs are local variables and all rhs are simple literals
(integers, nil, true, false), generate values directly into target
registers instead of using temporaries and MOVE instructions.

For example, `a,b = 1,2` now generates:
  LOADI_1 R1
  LOADI_2 R2
instead of:
  LOADI_1 R3
  LOADI_2 R4
  MOVE R1 R3
  MOVE R2 R4

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-21 17:26:49 +09:00
Yukihiro "Matz" Matsumoto e84f7bb3b0 mruby-compiler: remove unnecessary MOVE/APOST in simple masgn
For simple parallel assignment like `a,b = 1,2` without rest or post
variables, skip generating APOST instruction and unnecessary MOVE.
The values are already extracted via AREF.

Before (27 bytes):
    LOADI_1 R3
    LOADI_2 R4
    ARRAY   R3 2
    AREF    R1 R3 0
    AREF    R2 R3 1
    MOVE    R4 R3
    APOST   R4 2 0
    MOVE    R4 R3
    RETURN  R3

After (18 bytes):
    LOADI_1 R3
    LOADI_2 R4
    ARRAY   R3 2
    AREF    R1 R3 0
    AREF    R2 R3 1
    RETURN  R3

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-21 17:26:42 +09:00
Yukihiro "Matz" Matsumoto 6c4d98be8b mruby-compiler: implement find pattern matching
add support for find patterns in case/in expressions:
- [*pre, elem, *post] - find elem anywhere in array
- [*, elem, *] - anonymous rest (discarded)
- [*pre, a, b, *post] - multiple middle elements

implementation includes:
- grammar rules for find patterns with p_args, p_rest in parse.y
- NODE_PAT_FIND codegen with iterative search loop
- pre/post variable binding via range slicing
- p_const rule to prevent conflict with array literals

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-18 16:27:26 +09:00
Yukihiro "Matz" Matsumoto e76ce24860 mruby-compiler: add one-line pattern matching
add support for one-line pattern matching syntax:
- 'expr in pattern' returns true/false
- 'expr => pattern' raises NoMatchingPatternError on mismatch

add NODE_MATCH_PAT node type for both forms, distinguished by
raise_on_fail flag. grammar rules placed at expr level to avoid
conflict with rescue clause's exception variable syntax.

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-18 16:27:26 +09:00
Yukihiro "Matz" Matsumoto 1de6340f1b mruby-compiler: add pin operator to pattern matching
Add pin operator `^var` that matches against existing variable values
instead of creating new bindings. Also add bracket-less array pattern
syntax at top level: `in 1, 2, x` is equivalent to `in [1, 2, x]`.

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-18 16:27:26 +09:00
Yukihiro "Matz" Matsumoto 21472638b9 mruby-compiler: implement hash pattern matching
Add support for hash patterns in pattern matching expressions:
- {key:} shorthand binds to variable with same name
- {key: pattern} matches key against pattern
- {**rest} captures remaining keys
- {**nil} requires exact match (no extra keys)
- {**} ignores extra keys without capturing

Parser adds new grammar rules (p_hash, p_hash_body, p_hash_elems,
p_hash_elem, p_kwrest) and new_pat_hash() constructor.

Codegen generates code to call deconstruct_keys on the target hash,
then iterates through key-pattern pairs to match each key's value.

Adds Hash#deconstruct_keys method that returns self for pattern matching.

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-18 16:27:26 +09:00
Yukihiro "Matz" Matsumoto ec67fd9587 mruby-compiler: implement array pattern matching
add support for array destructuring patterns in case/in expressions:
- [a, b, c] - fixed length match
- [first, *rest] - head + rest
- [*init, last] - init + tail
- [first, *middle, last] - head + middle + tail
- [1, x, 3] - mixed value and variable patterns
- [first, *, last] - anonymous rest (discarded)

implementation includes:
- grammar rules for p_array, p_array_body, p_rest in parse.y
- NODE_PAT_ARRAY codegen with deconstruct call and length checks
- rest variable binding via range slicing (arr[pre..-(post+1)])
- Array#deconstruct method (returns self)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-18 16:27:26 +09:00
Yukihiro "Matz" Matsumoto 07ac110ddd mruby-compiler: add guard clauses to pattern matching
Add support for if/unless guards in case/in pattern matching:

  case value
  in x if x > 0 then :positive
  in x unless x == 0 then :non_zero
  end

Uses modifier_if/modifier_unless tokens since guards appear after
an expression. Disable peephole optimization for pattern variable
binding to prevent gen_move() from being optimized away when failed
guard jumps target the binding instruction.

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-18 16:27:25 +09:00
Yukihiro "Matz" Matsumoto dadfac678d mruby-compiler: add pattern matching (case/in) support
Implement Phase 1 of Ruby pattern matching:
- value patterns (literals, constants, nil/true/false)
- variable patterns (binds matched value)
- alternative patterns (pat1 | pat2)
- as patterns (pattern => var)

Pattern matching uses === operator for value comparison,
allowing type checking with class patterns (e.g., in Integer).

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-18 16:27:25 +09:00
Yukihiro "Matz" Matsumoto 82180d040b codegen.c: fix regexp literal with encoding to pass nil for options; fix #6666
restore correct argument passing for Regexp.compile when encoding is
present but flags are not. regexp literals like /a/n should compile to
Regexp.compile("a", nil, "n") with 3 arguments, not
Regexp.compile("a", "n") with 2 arguments.

the bug was introduced during refactoring when the nil-insertion logic
for the options parameter was accidentally omitted. now properly inserts
OP_LOADNIL when flags are absent but encoding is present.

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-20 14:08:21 +09:00
Yukihiro "Matz" Matsumoto cc622f718c mruby-compiler: fix super with keyword arguments; fix #6659
allocate ** keyword dictionary register when methods have keyword
arguments (parse.y new_args_tail), broken in commit 26ea71260 during
cons-list to struct migration. reconstruct keyword hash after KEYEND
from extracted keyword local variables so super can access keyword
values. encode block parameter flag in ainfo bit 13 and generate
LOADNIL for block register in codegen_zsuper when parent has keywords
but no block parameter.

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-08 17:37:56 +09:00
Yukihiro "Matz" Matsumoto e682b20f1d mruby-compiler: restore exception handling for ||= on class variables; fix #6657
Restore exception handling for `||=` operator on class variables and constants
that was inadvertently removed in commit 0ca48e24f. When reading an undefined
class variable with GETCV opcode raises NameError, the exception handler
catches it and loads false, allowing the assignment to proceed.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-28 09:46:51 +09:00
Yukihiro "Matz" Matsumoto 8455c41a74 mruby-compiler: combine variable declaration with initialization 2025-10-27 08:24:07 +09:00
Yukihiro "Matz" Matsumoto f5f0b9ac51 mruby-compiler: fix pr #6643 to use array_node elements field
pr #6643 fixed node type check but introduced a bug by accessing t->cdr
on a NODE_ARRAY structure. NODE_ARRAY nodes use the elements field, not
cdr. additionally, the fixed rhs path needs to update rhs_reg to point
to where values are actually pushed on the stack.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-19 07:29:32 +09:00
Meder Kydyraliev af33eec793 Fix crash caused by an incorrect node type check in codegen_masgn
Use the dedicated function `get_node_type(t)` to correctly determine the node type, instead of the incorrect `node_to_int(t->car)` check.

OSS-Fuzz issue details:
https://oss-fuzz.com/testcase-detail/4760884737277952
https://g-issues.oss-fuzz.com/issues/449498801
2025-10-17 10:03:01 +11:00
Yukihiro "Matz" Matsumoto bc10fbd49e mruby-compiler: fix memory leak in gen_literal_array
segment nodes allocated with mrbc_malloc were leaked if gen_string
raised an exception via longjmp. fix by avoiding allocation entirely:
temporarily modify tree structure by saving and clearing cdr pointer,
call gen_string, then restore cdr. no memory is allocated so nothing
leaks even on longjmp.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-15 07:50:51 +09:00
Yukihiro "Matz" Matsumoto 4982997b04 mruby-compiler: fix colon3 constant lookup; fix #6635, #6636
The bug was in codegen_colon3 which used genop_2(OP_OCLASS, sym)
treating OCLASS as BB format, but OCLASS is B format that only
loads ::Object without a symbol parameter. The fix uses the correct
two-instruction pattern: OCLASS to load Object class, then GETMCNST
to retrieve the constant from it.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-08 23:52:32 +09:00
Yukihiro "Matz" Matsumoto 01091984e7 mruby-compiler: add explicit cast to fix c++ compilation warning
cast uint8_t node_type field to enum node_type to satisfy c++ stricter
type checking while maintaining memory efficiency of 1-byte storage.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-04 10:02:02 +09:00
Yukihiro "Matz" Matsumoto 149dd03619 mruby-compiler: improve codegen.c comments to reflect current state
Remove migration-stage "Phase" and "Group" references from comments,
replacing them with descriptions of actual code organization.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:27 +09:00
Yukihiro "Matz" Matsumoto ee80a2ef26 mruby-compiler: replace accessor macros with direct member access
replaced all *_NODE_* accessor macros (e.g., SYM_NODE_VALUE,
INT_NODE_VALUE, CALL_NODE_METHOD) with direct member access using
casting macros (e.g., sym_node(n)->symbol, int_node(n)->value,
call_node(n)->method_name). this eliminates an unnecessary abstraction
layer and improves code readability by making field access explicit.

the accessor macros simply wrapped cast_func(n)->field, providing no
real benefit. direct member access makes it clear what field is being
accessed and reduces macro indirection.

affected files:
- node.h: removed ~100 accessor macro definitions
- codegen.c: replaced 19 macro uses with direct access
- parse.y: replaced 152 macro uses with direct access

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:27 +09:00
Yukihiro "Matz" Matsumoto 3e7078cef3 mruby-compiler: use direct member access instead of macros in codegen.c
replaced unnecessary macro usage with direct struct member access when
struct pointers are already available:
- return_n->args instead of RETURN_NODE_ARGS(return_n)
- yield_n->args instead of YIELD_NODE_ARGS(yield_n)
- for_n->var/iterable/body instead of FOR_NODE_VAR/ITERABLE/BODY(for_n)
- class_n->name/superclass/body instead of CLASS_NODE_* macros
- module_n->name/body instead of MODULE_NODE_NAME/BODY(module_n)
- sclass_n->obj/body instead of SCLASS_NODE_OBJ/BODY(sclass_n)
- hash->pairs instead of HASH_NODE_PAIRS(hash)
- call->method_name/safe_call instead of CALL_NODE_METHOD/SAFE(call)
- array->elements and an->elements instead of ARRAY_NODE_ELEMENTS macro
- splat->value instead of SPLAT_NODE_VALUE macro

improves code readability by removing unnecessary indirection.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:27 +09:00
Yukihiro "Matz" Matsumoto 6c923dc12c mruby-compiler: eliminate NODE_STR wrapper in NODE_DSYM implementation
Refactored NODE_DSYM to use unified structure directly instead of wrapping
NODE_STR. This eliminates unnecessary allocation and simplifies the AST.

Changes:
- new_dsym() now creates NODE_DSYM directly with mrb_ast_str_node structure
- Parser calls new_dsym(p, n) instead of new_dsym(p, new_str(p, n))
- codegen_dsym() uses gen_string() for proper string generation
- NODE_DSYM dump uses dump_str() for consistent string list handling
- Removed redundant mrb_ast_dsym_node struct definition

This maintains identical functionality while reducing memory overhead
and architectural complexity, with proper string handling to prevent
mrbtest crashes.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:26 +09:00
Yukihiro "Matz" Matsumoto 791f631191 mruby-compiler: add NODE_MARG for parameter destructuring
Implement NODE_MARG as a dedicated node type for parameter destructuring
to separate it architecturally from general multiple assignment (NODE_MASGN).
This resolves crashes when dumping parameter destructuring nodes and
improves code organization.

Key changes:
- Add NODE_MARG to node type enum
- Create new_marg() function for parameter destructuring
- Consolidate new_masgn() and new_marg() using shared helper
- Fix parameter context checks in lambda_body() to use NODE_MARG only
- Enable shared dumping logic for both NODE_MASGN and NODE_MARG
- Optimize memory management with immediate RHS cleanup
- Combine gen_assignment() cases for code deduplication

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-03 19:46:25 +09:00
Yukihiro "Matz" Matsumoto 759c1b1eff mruby-compiler: refactor NODE_MASGN structure and fix parameter destructuring
Refactored NODE_MASGN from single lhs field to separate pre/rest/post
fields for cleaner multiple assignment handling. Fixed segfault when
compiling methods with destructured parameters by properly handling
parameter destructuring in lambda_body function.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:25 +09:00
Yukihiro "Matz" Matsumoto 1cb8d73ede mruby-compiler: optimize splat of literal arrays in args/literals
- Skip no-op splats of empty array literals (`*[]` / zarray) in
  call argument generation and array literal codegen.
- Inline non-empty literal splat arrays without inner splats
  (e.g. `*[a,b]`) as regular positional args/elements, avoiding
  building a temporary array and ARYCAT.

This removes unnecessary `LOADNIL` + `ARRAY 0` + `ARYCAT` sequences
(e.g. `mruby -ve 'p *[]'`) and reduces temporary allocations while
preserving semantics and evaluation order. Falls back to the generic
path when nested splats are present or counts exceed fixed-arity.

No behavior change intended; only codegen improvements.

Co-authored-by: Codex <codex@openai.com>
2025-10-03 19:46:24 +09:00
Yukihiro "Matz" Matsumoto a49e4db4b6 mruby-compiler: rename gen_*_var functions to codegen_*
Now that all cons-list based codegen_* functions have been removed,
rename the gen_*_var functions to use the consistent codegen_* prefix.
This affects 70 functions and improves code clarity by establishing
a single naming convention for all code generation functions.

- gen_scope_var renamed to codegen_scope_node to avoid conflict with codegen_scope type
- All other gen_*_var functions renamed to codegen_* (removing _var suffix)
- Updated all function calls throughout codegen.c

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:24 +09:00
Yukihiro "Matz" Matsumoto a29afe7fe7 mruby-compiler: remove unused NODE_MATCH node type and related code
Remove NODE_MATCH enum value, structure definition, accessor macro,
parser dump case, codegen case, and gen_match_var function. This
node type was never actually used in the parser.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:23 +09:00
Yukihiro "Matz" Matsumoto 7d72da2842 mruby-compiler: remove old NODE_REGX and consolidate with NODE_DREGX
Remove the original NODE_REGX node type and related infrastructure,
then rename NODE_DREGX to NODE_REGX to consolidate regex handling
under a single node type.

Changes based on git diff:
- Remove original mrb_ast_regx_node structure with pattern fields
- Remove gen_regx_var() function handling literal regex patterns
- Remove NODE_REGX case from codegen and parser dump
- Rename NODE_DREGX to NODE_REGX for dynamic regex expressions
- Update all related functions and structure references

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:23 +09:00
Yukihiro "Matz" Matsumoto dc67cb795f mruby-compiler: inline codegen_regx into gen_regx_var to eliminate cons list
Remove the last cons list dependency in codegen.c by inlining codegen_regx()
directly into gen_regx_var(). This eliminates the need to create temporary
cons list structures and directly accesses regex pattern, flags, and
encoding from the variable-sized node structure.

Changes:
- Inline codegen_regx() logic into gen_regx_var()
- Remove codegen_regx() function entirely
- Access regex data directly from mrb_ast_regx_node fields
- Eliminate temporary cons list node creation

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:22 +09:00
Yukihiro "Matz" Matsumoto 39cf3038c6 mruby-compiler: remove redundant fields from call node structure
Remove argc, has_kwargs, has_block, and reserved fields from
mrb_ast_call_node since this information can be determined from the
callargs structure at runtime. Simplify new_call() and call_with_block()
functions to eliminate field analysis during parsing.

Add callargs_empty() helper function to check for empty arguments and
update gen_if_var() to use it instead of accessing removed argc field.

This change reduces memory usage per call node while maintaining full
functionality through runtime analysis of the callargs structure.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:22 +09:00
Yukihiro "Matz" Matsumoto 0c25c0d95f mruby-compiler: refactor gen_string to use single loop
Eliminate code duplication in gen_string by using a single loop with
a first-element flag instead of separate first element processing.

The previous structure had ~20 lines of duplicated string literal and
expression processing logic. The refactored version uses a unified loop
that handles concatenation only for non-first elements, reducing code
duplication and improving maintainability.

Functionality remains identical - all string interpolation, regex
patterns, and heredoc processing work correctly.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:22 +09:00
Yukihiro "Matz" Matsumoto fdfdedaa4f mruby-compiler: rename codegen_cons_list_string() to gen_string()
Rename the overly long and poorly descriptive codegen_cons_list_string()
function to gen_string() which is more concise and follows the existing
naming convention where gen_ prefix indicates code generation functions.

This function generates string bytecode from cons-list structures
containing mixed string literals and expressions for interpolation,
used in string interpolation, regex patterns, and heredocs.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:21 +09:00
Yukihiro "Matz" Matsumoto 821b989b33 mruby-compiler: update mrb_parser_dump for variable-sized nodes
Modernize the parser dump functionality to support the post-NODE_VARIABLE
hybrid AST architecture with both variable-sized nodes and traditional
cons-list nodes.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:21 +09:00