Commit Graph

757 Commits

Author SHA1 Message Date
Yukihiro "Matz" Matsumoto f01cc52835 mruby-compiler: implement variable-sized AST nodes for expression operations
Add support for variable-sized AST nodes for logical and control expression
operations including AND, OR, RETURN, YIELD, and SUPER.

Changes:
- Add variable-sized node structures for expression nodes in node.h
- Add casting and value access macros for expression nodes
- Modify existing expression functions to conditionally use variable-sized versions
- Implement variable-sized node creation functions (new_and_var, new_or_var, etc.)
- Add codegen support for variable-sized expression nodes
- All expression types (AND, OR, RETURN, YIELD, SUPER) now support variable-sized allocation

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:04 +09:00
Yukihiro "Matz" Matsumoto e3d52cec12 mruby-compiler: implement variable-sized AST nodes for assignment operations
Add support for variable-sized AST nodes for assignment operations including
simple assignment, multiple assignment, and operator assignment.

Changes:
- Add variable-sized node structures for assignment nodes in node.h
- Add casting and value access macros for assignment nodes
- Modify existing assignment functions to conditionally use variable-sized versions
- Implement variable-sized node creation functions (new_asgn_var, new_masgn_var, new_op_asgn_var)
- Add codegen support for variable-sized assignment nodes
- All assignment types (simple, multiple, operator) now support variable-sized allocation

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:03 +09:00
Yukihiro "Matz" Matsumoto 21037456df mruby-compiler: implement variable-sized AST nodes for control flow constructs
Add variable-sized node structures for all control flow statements:
- IF/ELSIF/ELSE statements with optimized condition handling
- WHILE and UNTIL loops with proper jump generation
- FOR loops with iterator support
- CASE/WHEN statements with multiple condition matching

Key changes:
- Added variable-sized node structures (mrb_ast_if_node, mrb_ast_while_node,
  mrb_ast_until_node, mrb_ast_case_node, mrb_ast_for_node) to node.h
- Implemented parser functions with size class allocation in parse.y
- Added comprehensive codegen support with proper jump handling and
  stack management in codegen.c
- All control flow nodes now use NODE_VARIABLE wrapper for consistency
- Variable-sized nodes enabled by default for improved memory efficiency

This provides memory-efficient storage for control flow constructs while
maintaining full compatibility with existing functionality.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:03 +09:00
Yukihiro "Matz" Matsumoto b534621957 mruby-compiler: implement variable-sized ast nodes for control flow
This completes the implementation of variable-sized AST nodes for control flow
structures (if, while, for, case), further reducing memory usage. Changes were
verified with AddressSanitizer.

Co-authored-by: Gemini <gemini@google.com>
2025-10-03 19:46:03 +09:00
Yukihiro "Matz" Matsumoto 392f4fabc0 mruby-compiler: use variable-sized ast nodes for call, array, and hash
Introduces variable-sized AST nodes for method calls (NODE_CALL),
arrays (NODE_ARRAY), and hashes (NODE_HASH). This change improves
memory efficiency by storing elements directly within the AST node,
avoiding an extra layer of pointer indirection for their data.

This is achieved by adding new data structures and functions in both
the parser and the code generator to handle these new node types.
Variable-sized nodes are now enabled by default.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:03 +09:00
Yukihiro "Matz" Matsumoto ac02635ba5 mruby-compiler: add infrastructure for variable-sized ast nodes
This commit introduces the core infrastructure for variable-sized AST
nodes, designed to improve memory efficiency. The previous fixed-size
nodes are replaced by nodes that can store data inline, such as
strings and integers, reducing pointer indirection and memory overhead.

Key changes include:
- A generic variable-sized node header (`mrb_ast_var_header`).
- A size-class-based memory allocation system for these nodes.
- Implementation of variable-sized nodes for core types: symbols,
  strings, integers, and variables (lvar, gvar, ivar, cvar).
- Integration into the parser and code generator, controlled by a
  feature flag.
- Centralized and improved type-casting macros for AST nodes.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:03 +09:00
Yukihiro "Matz" Matsumoto 8c36e227e7 mruby-compiler: implement head-only location optimization for ast nodes
This implements a memory optimization for AST nodes that stores location
information (lineno, filename_index) only in head nodes rather than in
every node, reducing memory usage for structure nodes.

Key changes:
- Split node types: mrb_ast_node (structure nodes without location),
  mrb_ast_head_node (with location info). Sizes are platform-dependent:
  8/12 bytes on 32-bit, 16/24 bytes on 64-bit platforms
- Separate allocation: cons() creates structure nodes, cons_head()
  creates head nodes with location information
- Node recycling: all nodes are recycled when freed, but only smaller
  structure nodes are reused from the free list to maintain type safety
- Updated macro: added headn() for consistent head node casting
- Removed NODE_LINENO macro: eliminated redundant location copying
  since head-only optimization already provides adequate location info
- Fixed codegen to properly access location fields via head node casts

This optimization reduces AST memory usage while preserving all
debugging and location information functionality.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:03 +09:00
Yukihiro "Matz" Matsumoto e41d18a49c mruby-compiler: add helper functions for common load operation patterns
Add helper functions to reduce code duplication in codegen load operations:

- gen_load_op1/gen_load_op2: for simple literal load operations following
  the pattern "if (!val) return; genop_X(...); push();"
- gen_load_nil: for conditional nil loading with "if (!val) return;" check
- gen_load_lit: for literal loading with push

Refactor 8 literal loading functions (codegen_self, codegen_nil, codegen_true,
codegen_false, codegen_sym, codegen_float, codegen_back_ref, codegen_nth_ref)
and multiple inline nil loading patterns throughout codegen.c.

Each refactored function reduced from 5-8 lines to 2-4 lines while maintaining
identical bytecode generation behavior. All 1730 tests pass.

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-03 19:46:02 +09:00
Yukihiro "Matz" Matsumoto 1e178b0860 codegen.c: complete monolithic function refactoring
Extract final complex cases (NODE_OP_ASGN, NODE_MASGN), unify while/until
loop handling, apply early return pattern to reduce indentation, and achieve
complete switch statement consistency.

The original 5000+ line monolithic function is now organized into 60+ focused
functions while preserving all functionality and performance.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-03 19:46:02 +09:00
dearblue db1578c123 Separating the build setup portion from the GEMS setup block
The issue resolved by the preceding patch was solely the C++ exception task within the mruby core.
This patch aims to resolve a similar sequencing issue that also exists in GEMS.

In practice, `mruby-compiler` is sometimes loaded via dependencies rather than being explicitly specified in the build configuration file.
In such cases, when `mruby-compiler/mrbgem.rake` is loaded, it is not yet determined whether C++ exceptions will be used. Consequently, even if it later becomes clear that `core/codegen-cxx.cxx` and `core/y.tab-cxx.cxx` are required, the system could not handle this.

To resolve this issue, we introduce the `MRuby::Gem::Specification#build_settings` method as a mechanism for lazily evaluating build setup.
However, for backward compatibility, the commands are cloned twice in `gem.setup` and `gem.setup_build`.
This is because many existing GEMS configure commands directly within the setup block.

ref. https://github.com/mruby/mruby/issues/6615
2025-09-11 22:53:06 +09:00
Yukihiro "Matz" Matsumoto 2cbb99c16d mruby-compiler: make mrb_ast_node an opaque struct in compile.h
Move the definition of struct mrb_ast_node to a private header to
hide implementation details from the public API.

Co-authored-by: Gemini <gemini@google.com>
2025-08-21 07:23:14 +09:00
Yukihiro "Matz" Matsumoto ae7e125388 mruby-compiler: encapsulate string and heredoc types
Move STR_FUNC_* macros, enum mrb_string_type, and struct
mrb_parser_heredoc_info from include/mruby/compile.h to
mrbgems/mruby-compiler/core/node.h.

These types are internal to the mruby compiler gem and are used by
both parse.y and codegen.c. Moving them to node.h encapsulates them
within the compiler gem, cleaning up the public mruby/compile.h header.

Co-authored-by: Gemini <gemini@google.com>
2025-08-21 07:23:13 +09:00
Yukihiro "Matz" Matsumoto e6071d5331 mruby-compiler: simplify the code for NODE_WHILE_MOD & NODE_UNTIL_MOD
Instead of having dedicated code, we now share the fundamental part with
normal NODE_WHILE and NODE_UNTIL.
2025-07-11 10:09:35 +09:00
Yukihiro "Matz" Matsumoto ee30d1d0f8 mruby-compiler: allow at-least-once loop behavior for mruby
mruby does not provide `begin ... end while cond` that behave at-least-once
loop, like CRuby does. It remains in TODO.md for long time. But finally we have
implemented the behavior.
2025-07-11 10:09:34 +09:00
Yukihiro "Matz" Matsumoto ebc10f3c57 Add NODE_BEGIN for explicit begin...end blocks
This commit introduces NODE_BEGIN as a distinct AST node type for
explicit begin...end blocks, separate from NODE_STMTS which represents
general statement sequences. This distinction will be essential for
implementing CRuby-compatible begin...end while/until constructs.

Key changes:
- Added NODE_BEGIN enum in node.h
- Added new_begin() function in parse.y using optimized cons() structure
- Modified begin...end grammar rule to generate NODE_BEGIN nodes
- Added NODE_BEGIN codegen support in codegen.c
- Added NODE_BEGIN to parser dump functionality

NODE_BEGIN uses a simpler cons() structure instead of list2() for
better memory efficiency, as it only contains a single body node.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-11 10:09:34 +09:00
Yukihiro "Matz" Matsumoto dc0a5f433f mruby-compiler: optimize NODE_STMTS nesting to reduce AST depth
Modify new_stmts to flatten unnecessary nesting by returning existing
NODE_STMTS directly instead of wrapping them. This reduces memory usage
and AST complexity when multiple parentheses levels are used.

Before: (((expr1; expr2))) creates nested NODE_STMTS
After: (((expr1; expr2))) creates single NODE_STMTS with statements

Co-authored-by: Claude <noreply@anthropic.com>
2025-07-11 10:09:33 +09:00
Yukihiro "Matz" Matsumoto f6c166cbb0 mruby-compiler: rename NODE_BEGIN to NODE_STMTS for clarity
Rename NODE_BEGIN to NODE_STMTS to better reflect its purpose as a
container for statement sequences, not specifically begin-end blocks.
This prepares for adding a dedicated node type for explicit begin-end
constructs.

- Rename NODE_BEGIN enum to NODE_STMTS in node.h
- Update all references in parse.y and codegen.c
- Rename new_begin function to new_stmts

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-11 10:09:33 +09:00
Yukihiro "Matz" Matsumoto bfc6daa845 mruby-compiler: add README.md │
Co-authored-by: Gemini <gemini@google.com>
2025-07-02 07:14:04 +09:00
Yukihiro "Matz" Matsumoto 4e08fae75a mruby-compiler: add comprehensive comments to codegen.c 2025-06-24 09:50:37 +09:00
Yukihiro "Matz" Matsumoto 1726b61481 mruby-compiler (gen_move): avoid unnecessary goto's 2025-05-20 18:31:51 +09:00
Yukihiro "Matz" Matsumoto d329d9af79 mruby-compiler (gen_move): avoid optimization of ADDI/SUBI
ADDI/SUBI may fall back to method call that may clear block argument
place holder, which may be a live register. So we cannot directly call
ADDI/SUBI over local variables.
2025-05-20 18:31:21 +09:00
Yukihiro "Matz" Matsumoto 31ebcb349e mruby-compiler: add y.tab.c in the repository again; close #6515
Since we have introduced lrama, everyone can generate same `y.tab.c`
on any platform, without installing Bison. That was the reason we have
removed `y.tab.c` from the repository. But this change cause #6515 and
bothered out-of-tree builds. So we (reluctantly) added `y.tab.c` again.
2025-05-19 08:00:37 +09:00
Yukihiro "Matz" Matsumoto 96cbde7988 mruby-compiler: remove mrb_free dependency from codegen.c 2025-05-19 08:00:36 +09:00
Yukihiro "Matz" Matsumoto bb712f9467 mruby-compiler: remove mrb_calloc dependency from parse.y 2025-05-19 08:00:36 +09:00
Yukihiro "Matz" Matsumoto 9fc58852e3 mruby-compiler: removed mrb_state dependency from two functions
- mrb_ccontext_partial_hook
- mrb_ccontext_cleanup_local_variables
2025-05-19 08:00:36 +09:00
Yukihiro "Matz" Matsumoto 75466f9aab mruby-compiler: use mrb_basic_alloc_func() directly from compiler
As a side effect, memory allocation failure may cause segmentation
fault. Maybe we have to add error detection later.
2025-05-13 13:20:06 +09:00
Yukihiro "Matz" Matsumoto 9ef2f551b7 mruby-compiler: use new mempool API 2025-05-13 08:13:48 +09:00
Yukihiro "Matz" Matsumoto 1b39c7d7da mruby-compiler (codegen): private backquote should be called; fix #6516 2025-04-28 10:40:05 +09:00
John Bampton fe201dc72f core/codegen.c: remove unneeded duplicate semicolon 2025-04-25 05:10:24 +10:00
Yukihiro "Matz" Matsumoto 1fdd961041 mruby-compiler (scope_new): need to initialize nregs; fix #6509
`nregs` should not be smaller than `nlocals`.
2025-04-07 11:35:19 +09:00
John Bampton b1d910f6f4 mrbgems: fix spelling 2025-04-04 15:05:13 +10:00
Yukihiro "Matz" Matsumoto b446b0d547 mruby-compiler: add type cast to silence warning 2025-03-25 08:10:04 +09:00
Yukihiro "Matz" Matsumoto d1909320d9 mruby-compiler: fixed a bug in string literal merge; fix #6491 2025-03-17 09:17:38 +09:00
Yukihiro "Matz" Matsumoto eb455c19fe mruby-compiler: prohibit singleton methods for literals
We have checked `def (literal).m` style but not `def literal.m` style.
In addition, `NODE_INT` check is newly added.
2025-03-14 23:28:42 +09:00
Yukihiro "Matz" Matsumoto 5bc00bf199 mruby-compiler: detect super without surrounding method; close #6271 2025-03-11 21:21:50 +09:00
Yukihiro "Matz" Matsumoto 111fe4b3be mruby-compiler: generate OP_SSEND from Complex and Rational literals 2025-03-07 17:17:45 +09:00
Yukihiro "Matz" Matsumoto 37d3d34036 mruby-compiler: use OP_SSEND for backquote calls 2025-03-07 17:17:42 +09:00
Yukihiro "Matz" Matsumoto 4ea5510937 mruby-compiler (merge_op_string): fix #6477
If two merging strings are the same and registered at the bottom of the
pool, we should not remove the slot from the pool.
2025-03-07 17:17:37 +09:00
Yukihiro "Matz" Matsumoto cb3b94346e mruby-complier (gen_call): remove duplicate MRB_OPSYM_2(); #6471 2025-01-27 12:36:14 +09:00
Yukihiro "Matz" Matsumoto 69024d9a36 mruby-compiler (gen_call): operator optimization with self; close #6471
If the left operand is `self`, the previous (reverted) change disabled
optimization with operators. This is sort of a hack, but it works.
2025-01-26 23:14:19 +09:00
Yukihiro "Matz" Matsumoto acddb3945b mruby-compiler (gen_call): adjust spacing 2025-01-26 20:08:01 +09:00
Yukihiro "Matz" Matsumoto 6731d59f06 Revert "mruby-compiler (gen_call): use OP_SSEND for self.foo() calls"
This reverts commit 583aa985c8f3117a833a38f0d27753a090503f17; #6471
2025-01-26 19:52:01 +09:00
Yukihiro "Matz" Matsumoto d7559253de mruby-compiler: need to add proper type cast for C++ 2024-12-28 11:39:22 +09:00
Yukihiro "Matz" Matsumoto 32d11d86ff mruby-compiler (new_lit_str2): move declarations to the point needed 2024-12-26 09:58:01 +09:00
Yukihiro "Matz" Matsumoto 648495a4b3 mruby-compiler (mrb_prev_pc): remove unnecessary local variable 2024-12-25 12:40:33 +09:00
Yukihiro "Matz" Matsumoto 160935dc24 mruby-compiler (mrb_prev_pc): add assertion to ensure pc within iseq 2024-12-25 12:39:57 +09:00
Yukihiro "Matz" Matsumoto dbcb5b5a6d mruby-compiler (merge_pool_str): check whether merged string is in the pool 2024-12-25 12:39:34 +09:00
Yukihiro "Matz" Matsumoto 890a8362b6 mruby-compiler (new_lit_str2): fixed a bug in pool string equality check 2024-12-25 12:39:34 +09:00
Yukihiro "Matz" Matsumoto 6687bddba3 mruby-compiler (gen_addsub): merge 2 literal strings str + str
Unlike previous attempt, this change can merge sequence of plus
operations (e.g. `str + str + str`). Need more tests though.
2024-12-25 12:39:34 +09:00
Yukihiro "Matz" Matsumoto b44372599e mruby-compiler (codegen): combine literal str + str to one string 2024-12-25 12:39:34 +09:00