-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Summary
Add support for Ruby's to_s and to_i type conversion methods in the Smalruby editor. These methods should convert to native Scratch operator blocks (operator_join and operator_add) instead of falling through to ruby_expression blocks.
Motivation
Users write Ruby code like:
kakaku = gets.to_i
puts kakaku * 0.7Currently, to_s and to_i fall through to ruby_expression blocks and are executed via Opal at runtime. Converting them to native Scratch blocks will:
- Make the block view clearer and more visual
- Provide better performance
- Ensure consistent behavior with Scratch's built-in type coercion
Proposed Implementation
Conversion Pattern
value.to_s→operator_join(value, "")with comment marker@ruby:to_svalue.to_i→operator_add(value, 0)with comment marker@ruby:to_i
Files to Modify
-
Ruby-to-Blocks Converter (
packages/scratch-gui/src/lib/ruby-to-blocks-converter/operators.js)- Register
to_smethod: converts tooperator_joinblock with empty string - Register
to_imethod: converts tooperator_addblock with zero - Attach comment markers using
converter._createComment()
- Register
-
Code Generator (
packages/scratch-gui/src/lib/ruby-generator/operators.js)- Update
Generator.operator_join: detect@ruby:to_scomment and generate.to_s - Update
Generator.operator_add: detect@ruby:to_icomment and generate.to_i
- Update
-
Unit Tests (
packages/scratch-gui/test/unit/lib/ruby-to-blocks-converter/operators.test.js)- Test
to_swith number literal, string literal, and variables - Test
to_iwith string literal, number literal, and variables
- Test
-
Integration Tests (
packages/scratch-gui/test/integration/operators.test.js)- Test round-trip conversion (Ruby → Blocks → Ruby)
- Verify comment markers are preserved
Code Snippets
Ruby-to-Blocks Registration (add after line 161 in operators.js):
// to_s method: convert to operator_join with empty string
converter.registerOnSend(['variable', 'number', 'string', 'block'], 'to_s', 0, params => {
const {receiver} = params;
const block = converter._createBlock('operator_join', 'value');
converter._addTextInput(block, 'STRING1', receiver, '');
converter._addTextInput(block, 'STRING2', '', '');
block.comment = converter._createComment('@ruby:to_s', block.id);
return block;
});
// to_i method: convert to operator_add with zero
converter.registerOnSend(['variable', 'number', 'string', 'block'], 'to_i', 0, params => {
const {receiver} = params;
const block = converter._createBlock('operator_add', 'value');
converter._addNumberInput(block, 'NUM1', 'math_number', receiver, '');
converter._addNumberInput(block, 'NUM2', 'math_number', 0, '');
block.comment = converter._createComment('@ruby:to_i', block.id);
return block;
});Code Generator Enhancement (modify in ruby-generator/operators.js):
Generator.operator_join = function (block) {
const comment = Generator.getCommentText(block);
if (comment === '@ruby:to_s') {
const value = Generator.valueToCode(block, 'STRING1', Generator.ORDER_FUNCTION_CALL) || Generator.quote_('');
return [`${value}.to_s`, Generator.ORDER_FUNCTION_CALL];
}
const order = Generator.ORDER_ADDITIVE;
const rightStr = Generator.valueToCode(block, 'STRING1', order) || Generator.quote_('');
const leftStr = Generator.valueToCode(block, 'STRING2', order) || Generator.quote_('');
return [`${rightStr} + ${leftStr}`, order];
};
Generator.operator_add = function (block) {
const comment = Generator.getCommentText(block);
if (comment === '@ruby:to_i') {
const value = Generator.valueToCode(block, 'NUM1', Generator.ORDER_FUNCTION_CALL) || 0;
return [`${value}.to_i`, Generator.ORDER_FUNCTION_CALL];
}
const order = Generator.ORDER_ADDITIVE;
const num1 = Generator.valueToCode(block, 'NUM1', order) || 0;
const num2 = Generator.valueToCode(block, 'NUM2', order) || 0;
return [`${num1} + ${num2}`, order];
};Testing
Unit Tests
- Test
to_sandto_iwith various receiver types (numbers, strings, variables, blocks) - Verify correct block type and comment marker creation
Integration Tests
- Test complete example code round-trip conversion
- Verify comment markers are preserved through conversion
Manual Verification
docker compose up app
# Visit http://localhost:8601
# Enter Ruby code with to_s and to_i
# Switch to blocks view and verify operator_join/operator_add blocks
# Switch back to Ruby and verify .to_s/.to_i notationSuccess Criteria
- ✅
to_smethod calls convert tooperator_joinblocks with empty string - ✅
to_imethod calls convert tooperator_addblocks with zero - ✅ Blocks convert back to Ruby with
.to_sand.to_imethod notation - ✅ All tests pass (unit + integration + lint)
- ✅ Example code works correctly:
kakaku = gets.to_i; puts kakaku * 0.7 - ✅ Round-trip conversion preserves semantics
Related Files
packages/scratch-gui/src/lib/ruby-to-blocks-converter/operators.jspackages/scratch-gui/src/lib/ruby-generator/operators.jspackages/scratch-gui/test/unit/lib/ruby-to-blocks-converter/operators.test.jspackages/scratch-gui/test/integration/operators.test.js