feat: Ruby module/include (MixIn) support with cross-sprite sync#296
Merged
takaokouji merged 14 commits intodevelopfrom Mar 14, 2026
Merged
feat: Ruby module/include (MixIn) support with cross-sprite sync#296takaokouji merged 14 commits intodevelopfrom
takaokouji merged 14 commits intodevelopfrom
Conversation
Add visitModuleNode to parse Ruby module definitions and store method ASTs in context. Modify visitClassNode to handle include statements, expanding module methods as procedures_definition blocks with @ruby:module_source:ModuleName comments. Add error handling for v1, nested modules, undefined modules, and non-method statements in modules. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
In procedure.js, detect @ruby:module_source:ModuleName comments on procedures_definition blocks, store the generated code separately in _moduleMethodCodes, and suppress from main output. In finish(), generate module...end blocks before the class definition. In _wrapWithClass(), parse include=ModuleName from class comment and generate include statements inside the class body. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Create module-sync.js with utilities to detect module changes, find affected sprites, and sync module definitions by regenerating Ruby code, replacing the module definition, and re-converting. Integrate sync into ruby-tab.jsx after code-to-blocks conversion (v2 only). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
🚀 Preview deployed: https://smalruby.jp/smalruby3-editor/feature/module-include/ |
In finishTargets(), extract all module...end blocks from the combined multi-target code, keep unique ones, and place them once before the class definitions. This prevents duplicate module definitions when multiple sprites include the same module. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add module_function and extend error detection in converter. Prevent switching to Ruby v1 when v2 features (module/class) are in use. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The generateTargetCode function in module-sync.js was using withSpriteNew: true, which caused the generated Ruby to include set_costumes/set_sounds calls that fail validation during reconversion. Removing this option generates clean class definitions that can be successfully re-converted. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Round-trip tests: single method, multiple methods, multiple modules, no-argument method - Sync test: verifies adding a method to a module in one sprite propagates the new method definition to another sprite Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ude on stage - When a sprite uses `include Mod` without defining the module locally, the converter automatically searches other sprites for `@ruby:module_source:Mod` comments, generates Ruby from that sprite, extracts the module definition, parses it, and makes it available for include expansion. - Module definitions and include statements are now blocked on Stage targets since stage and sprite have different available methods. - Added Japanese locale translations for all module-related error messages. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…d modules When using the execute button on the Ruby tab, the editor content was not updated to reflect auto-imported modules. This adds a call to updateRubyCodeTargetState after block application so the editor immediately shows the full module definition obtained from other sprites. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…andler The updateRubyCodeTargetState call was placed after the block ID lookup, which could be skipped via early return when the cursor line has no executable block (e.g. class declaration). Moving it to right after converter.apply() ensures the editor always reflects auto-imported modules. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Redux-based updateRubyCodeTargetState approach did not reliably update the Monaco editor content within the execute callback because @monaco-editor/react value prop changes may not be applied in the same render cycle. Instead, directly call editorRef.current.setValue() with the regenerated Ruby code from RubyGenerator.targetToCode(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When clicking "カーソル行を実行" and a module is auto-imported, setValue() resets the cursor to line 1. This fix remembers the cursor line content before setValue and restores the cursor to the matching line in the regenerated code, then scrolls it to center. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add furigana annotations: module→モジュール作成, end→作成終了, include→取り込む - Update smalruby-language-spec.md to document module/include (Version 2) - Update Gemini system prompt to include module/include methods and examples - Update furigana-mapping.md with new entries - Add 4 unit tests for module/include furigana Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Gemini was ignoring the system prompt and incorrectly stating that module/include is not supported. Added stronger emphasis and a sample program to ensure correct code generation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
github-actions bot
pushed a commit
that referenced
this pull request
Mar 14, 2026
…e-include feat: Ruby module/include (MixIn) support with cross-sprite sync
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ruby の
module/include(MixIn) をサポートし、複数スプライトでメソッド定義を共有できるようにする。Ruby version 2 専用。Closes #295
Implementation Steps
Changes Made
Phase 1: Ruby → Blocks (Converter)
visitModuleNode: Parsemoduledefinitions, store method ASTs in contextvisitClassNode: Handleinclude ModuleName, expand module methods asprocedures_definitionblocks with@ruby:module_source:ModuleNamecommentsinclude=ModuleNamefor orderingPhase 2: Blocks → Ruby (Generator)
procedure.js: Detect@ruby:module_sourcecomment, store code in_moduleMethodCodes, suppress from main outputfinish(): Generatemodule...endblocks before class definition_wrapWithClass(): Parseinclude=from class comment, generateincludestatements inside classPhase 3: Module Sync
module-sync.js: Cross-sprite module sync after Ruby→Blocks conversionwithSpriteNew: truefromgenerateTargetCodeto prevent costume validation errors during reconversionPhase 4: File Output Deduplication
finishTargets(): Regex-based module extraction and deduplication across targetsPhase 5: Error Handling + v1 Switch Prevention
module_functionandextenderror detection in convertercannotSwitchToV1alert messageTest Coverage
DoD Verification (Playwright MCP)