Skip to content

Commit 7c82b1a

Browse files
committed
control_repeat
1 parent e2f30b0 commit 7c82b1a

File tree

4 files changed

+125
-2
lines changed

4 files changed

+125
-2
lines changed

src/lib/ruby-generator/control.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export default function (Generator) {
1010
};
1111

1212
Generator.control_repeat = function (block) {
13-
const times = Generator.valueToCode(block, 'TIMES', Generator.ORDER_NONE) || 0;
13+
const times = Generator.valueToCode(block, 'TIMES', Generator.ORDER_ATOMIC) || 0;
1414
const branch = Generator.statementToCode(block, 'SUBSTACK') || '';
1515
return `${times}.times do\n${branch}${Generator.INDENT}wait\nend\n`;
1616
};

src/lib/ruby-to-blocks-converter/control.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/* global Opal */
2+
23
/**
34
* Control converter
45
*/
@@ -15,6 +16,21 @@ const ControlConverter = {
1516
}
1617
break;
1718
}
19+
} else if (this._isNumberOrBlock(receiver)) {
20+
switch (name) {
21+
case 'times':
22+
if (args.length === 0 &&
23+
rubyBlockArgs && rubyBlockArgs.length === 0 &&
24+
rubyBlock && rubyBlock.length >= 1) {
25+
const waitBlock = this._popWaitBlock(rubyBlock);
26+
if (waitBlock) {
27+
block = this._createBlock('control_repeat', 'statement');
28+
this._addNumberInput(block, 'TIMES', 'math_whole_number', receiver, 10);
29+
this._addSubstack(block, rubyBlock);
30+
}
31+
}
32+
break;
33+
}
1834
}
1935
return block;
2036
}

src/lib/ruby-to-blocks-converter/index.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,13 @@ class RubyToBlocksConverter {
529529
}
530530

531531
_isFalseOrBooleanBlock (block) {
532-
if (block === false || this._getBlockType(block) === 'value_boolean') {
532+
if (block === false) {
533+
return true;
534+
}
535+
if (!this._isBlock(block)) {
536+
return false;
537+
}
538+
if (this._getBlockType(block) === 'value_boolean') {
533539
return true;
534540
}
535541
if (block.opcode === 'argument_reporter_string_number') {

test/unit/lib/ruby-to-blocks-converter/control.test.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,107 @@ describe('RubyToBlocksConverter/Control', () => {
8383
});
8484
});
8585

86+
describe('control_repeat', () => {
87+
test('number', () => {
88+
code = '10.times { move(10); wait }';
89+
expected = [
90+
{
91+
opcode: 'control_repeat',
92+
inputs: [
93+
{
94+
name: 'TIMES',
95+
block: expectedInfo.makeNumber(10, 'math_whole_number')
96+
}
97+
],
98+
branches: [
99+
rubyToExpected(converter, target, 'move(10)')[0]
100+
]
101+
}
102+
];
103+
convertAndExpectToEqualBlocks(converter, target, code, expected);
104+
105+
code = '10.times { move(10); bounce_if_on_edge; wait }';
106+
expected = [
107+
{
108+
opcode: 'control_repeat',
109+
inputs: [
110+
{
111+
name: 'TIMES',
112+
block: expectedInfo.makeNumber(10, 'math_whole_number')
113+
}
114+
],
115+
branches: [
116+
rubyToExpected(converter, target, 'move(10); bounce_if_on_edge')[0]
117+
]
118+
}
119+
];
120+
convertAndExpectToEqualBlocks(converter, target, code, expected);
121+
});
122+
123+
test('value block', () => {
124+
code = 'x.times { move(10); wait }';
125+
expected = [
126+
{
127+
opcode: 'control_repeat',
128+
inputs: [
129+
{
130+
name: 'TIMES',
131+
block: rubyToExpected(converter, target, 'x')[0],
132+
shadow: expectedInfo.makeNumber(10, 'math_whole_number')
133+
}
134+
],
135+
branches: [
136+
rubyToExpected(converter, target, 'move(10)')[0]
137+
]
138+
}
139+
];
140+
convertAndExpectToEqualBlocks(converter, target, code, expected);
141+
});
142+
143+
test('boolean block', () => {
144+
code = '(touching?("_edge_")).times { move(10); wait }';
145+
expected = [
146+
{
147+
opcode: 'control_repeat',
148+
inputs: [
149+
{
150+
name: 'TIMES',
151+
block: rubyToExpected(converter, target, 'touching?("_edge_")')[0],
152+
shadow: expectedInfo.makeNumber(10, 'math_whole_number')
153+
}
154+
],
155+
branches: [
156+
rubyToExpected(converter, target, 'move(10)')[0]
157+
]
158+
}
159+
];
160+
convertAndExpectToEqualBlocks(converter, target, code, expected);
161+
});
162+
163+
test('invalid', () => {
164+
[
165+
'10.times',
166+
'10.times(1)'
167+
].forEach(c => {
168+
convertAndExpectToEqualRubyStatement(converter, target, c, c);
169+
});
170+
171+
[
172+
'10.times {}',
173+
'10.times { wait; move(10) }',
174+
'10.times { |i| wait }',
175+
'"10".times { wait }'
176+
].forEach(c => {
177+
const res = converter.targetCodeToBlocks(target, c);
178+
expect(converter.errors).toHaveLength(0);
179+
const scriptIds = Object.keys(converter.blocks).filter(id => converter.blocks[id].topLevel);
180+
expect(scriptIds).toHaveLength(1);
181+
expect(converter.blocks[scriptIds[0]]).toHaveProperty('opcode', 'ruby_statement_with_block');
182+
expect(res).toBeTruthy();
183+
});
184+
});
185+
});
186+
86187
test('control_forever', () => {
87188
code = 'loop { bounce_if_on_edge; wait }';
88189
expected = [

0 commit comments

Comments
 (0)