Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions packages/scratch-gui/src/lib/ruby-generator/smalruby-ruby.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* @returns {object} same as param.
*/
export default function (Generator) {
Generator.smalrubyRuby_stringMethodR = function (block) {
Generator.smalrubyRuby_methodR = function (block) {
const order = Generator.ORDER_FUNCTION_CALL;
const string = Generator.valueToCode(block, 'STRING', order) || Generator.quote_('');
const method = Generator.getFieldValue(block, 'METHOD') || 'delete';
Expand All @@ -25,11 +25,16 @@ export default function (Generator) {
return [`${string}.${method}(${args.join(', ')})`, order];
};

Generator.smalrubyRuby_stringMethodC = function (block) {
Generator.smalrubyRuby_methodC = function (block) {
const order = Generator.ORDER_FUNCTION_CALL;
const varName = Generator.getFieldValue(block, 'STRING') || '';
const string = Generator.variableNameByName(varName) || 'nil';
const method = Generator.getFieldValue(block, 'METHOD') || 'delete!';
const hasArg1 = block.inputs && block.inputs.ARG1;
if (!hasArg1) {
return `${string}.${method}\n`;
}

const arg1 = Generator.valueToCode(block, 'ARG1', order) || Generator.quote_('');
const arg2 = Generator.valueToCode(block, 'ARG2', order);

Expand Down
251 changes: 226 additions & 25 deletions packages/scratch-gui/src/lib/ruby-to-blocks-converter/smalruby-ruby.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ describe('RubyGenerator/SmalrubyRuby', () => {
};
});

describe('smalrubyRuby_stringMethodR', () => {
describe('smalrubyRuby_methodR', () => {
test('should generate reverse method call (no args)', () => {
RubyGenerator.valueToCode = (block, name, _order) => {
const map = {STRING: '"Jimmy"'};
return map[name] || '';
};

const block = {
opcode: 'smalrubyRuby_stringMethodR',
opcode: 'smalrubyRuby_methodR',
fields: {METHOD: {value: 'reverse'}}
};
const result = RubyGenerator.smalrubyRuby_stringMethodR(block);
const result = RubyGenerator.smalrubyRuby_methodR(block);
expect(result[0]).toEqual('"Jimmy".reverse');
});

Expand All @@ -35,23 +35,23 @@ describe('RubyGenerator/SmalrubyRuby', () => {
};

const block = {
opcode: 'smalrubyRuby_stringMethodR',
opcode: 'smalrubyRuby_methodR',
fields: {METHOD: {value: 'delete'}},
inputs: {ARG1: {}}
};
const result = RubyGenerator.smalrubyRuby_stringMethodR(block);
const result = RubyGenerator.smalrubyRuby_methodR(block);
expect(result[0]).toEqual('"hello world".delete("l")');
});

test('should use default values when inputs are empty', () => {
RubyGenerator.valueToCode = () => '';

const block = {
opcode: 'smalrubyRuby_stringMethodR',
opcode: 'smalrubyRuby_methodR',
fields: {METHOD: {value: 'delete'}},
inputs: {ARG1: {}}
};
const result = RubyGenerator.smalrubyRuby_stringMethodR(block);
const result = RubyGenerator.smalrubyRuby_methodR(block);
expect(result[0]).toEqual('"".delete("")');
});

Expand All @@ -66,11 +66,11 @@ describe('RubyGenerator/SmalrubyRuby', () => {
};

const block = {
opcode: 'smalrubyRuby_stringMethodR',
opcode: 'smalrubyRuby_methodR',
fields: {METHOD: {value: 'delete'}},
inputs: {ARG1: {}, ARG2: {}}
};
const result = RubyGenerator.smalrubyRuby_stringMethodR(block);
const result = RubyGenerator.smalrubyRuby_methodR(block);
expect(result[0]).toEqual('"hello".delete("l", "o")');
});

Expand All @@ -80,16 +80,16 @@ describe('RubyGenerator/SmalrubyRuby', () => {
return map[name] || '';
};
const block = {
opcode: 'smalrubyRuby_stringMethodR',
opcode: 'smalrubyRuby_methodR',
fields: {METHOD: {value: 'gsub'}},
inputs: {ARG1: {}, ARG2: {}}
};
const result = RubyGenerator.smalrubyRuby_stringMethodR(block);
const result = RubyGenerator.smalrubyRuby_methodR(block);
expect(result[0]).toEqual('"hello".gsub("l", "r")');
});
});

describe('smalrubyRuby_stringMethodC', () => {
describe('smalrubyRuby_methodC', () => {
test('should generate delete! with variable receiver', () => {
RubyGenerator.variableNameByName = name => name;
RubyGenerator.valueToCode = (block, name, _order) => {
Expand All @@ -98,13 +98,14 @@ describe('RubyGenerator/SmalrubyRuby', () => {
};

const block = {
opcode: 'smalrubyRuby_stringMethodC',
opcode: 'smalrubyRuby_methodC',
fields: {
STRING: {value: 'my_var'},
METHOD: {value: 'delete!'}
}
},
inputs: {ARG1: {}}
};
const result = RubyGenerator.smalrubyRuby_stringMethodC(block);
const result = RubyGenerator.smalrubyRuby_methodC(block);
expect(result).toEqual('my_var.delete!("l")\n');
});

Expand All @@ -113,13 +114,14 @@ describe('RubyGenerator/SmalrubyRuby', () => {
RubyGenerator.valueToCode = () => '';

const block = {
opcode: 'smalrubyRuby_stringMethodC',
opcode: 'smalrubyRuby_methodC',
fields: {
STRING: {value: ''},
METHOD: {value: 'delete!'}
}
},
inputs: {ARG1: {}}
};
const result = RubyGenerator.smalrubyRuby_stringMethodC(block);
const result = RubyGenerator.smalrubyRuby_methodC(block);
expect(result).toEqual('nil.delete!("")\n');
});

Expand All @@ -131,14 +133,30 @@ describe('RubyGenerator/SmalrubyRuby', () => {
};

const block = {
opcode: 'smalrubyRuby_stringMethodC',
opcode: 'smalrubyRuby_methodC',
fields: {
STRING: {value: 'x'},
METHOD: {value: 'delete!'}
}
},
inputs: {ARG1: {}, ARG2: {}}
};
const result = RubyGenerator.smalrubyRuby_stringMethodC(block);
const result = RubyGenerator.smalrubyRuby_methodC(block);
expect(result).toEqual('x.delete!("l", "o")\n');
});

test('should generate sort! without args', () => {
RubyGenerator.variableNameByName = name => name;
RubyGenerator.valueToCode = () => '';

const block = {
opcode: 'smalrubyRuby_methodC',
fields: {
STRING: {value: 'ticket'},
METHOD: {value: 'sort!'}
}
};
const result = RubyGenerator.smalrubyRuby_methodC(block);
expect(result).toEqual('ticket.sort!\n');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('RubyToBlocksConverter/SmalrubyRuby', () => {
const code = '"Jimmy".reverse';
const expected = [
{
opcode: 'smalrubyRuby_stringMethodR',
opcode: 'smalrubyRuby_methodR',
fields: [
{name: 'METHOD', value: 'reverse'}
],
Expand Down Expand Up @@ -48,7 +48,7 @@ describe('RubyToBlocksConverter/SmalrubyRuby', () => {
const code = '"hello world".delete("l")';
const expected = [
{
opcode: 'smalrubyRuby_stringMethodR',
opcode: 'smalrubyRuby_methodR',
fields: [
{name: 'METHOD', value: 'delete'}
],
Expand All @@ -73,7 +73,7 @@ describe('RubyToBlocksConverter/SmalrubyRuby', () => {
const code = '"hello world".gsub("l", "r")';
const expected = [
{
opcode: 'smalrubyRuby_stringMethodR',
opcode: 'smalrubyRuby_methodR',
fields: [
{name: 'METHOD', value: 'gsub'}
],
Expand Down Expand Up @@ -114,4 +114,48 @@ describe('RubyToBlocksConverter/SmalrubyRuby', () => {
await convertAndExpectRubyBlockError(converter, target, '"hello".gsub!("l")');
});
});

describe('New methods (Phase 1 #4-#9)', () => {
test('String#lines should convert', async () => {
const code = '"hello\\nworld".lines';
const result = await converter.targetCodeToBlocks(target, code);
expect(result).toBe(true);
});

test('Array#max should convert', async () => {
const code = 'ticket = [12, 47, 35]\nticket.max';
const result = await converter.targetCodeToBlocks(target, code);
expect(result).toBe(true);
});

test('Array#sort should convert', async () => {
const code = 'ticket = [12, 47, 35]\nticket.sort';
const result = await converter.targetCodeToBlocks(target, code);
expect(result).toBe(true);
});

test('Array#join should convert without args', async () => {
const code = 'ticket = [12, 47, 35]\nticket.join';
const result = await converter.targetCodeToBlocks(target, code);
expect(result).toBe(true);
});

test('Array#join should convert with separator arg', async () => {
const code = 'ticket = [12, 47, 35]\nticket.join(", ")';
const result = await converter.targetCodeToBlocks(target, code);
expect(result).toBe(true);
});

test('Hash#keys should convert', async () => {
const code = 'books = {}\nbooks.keys';
const result = await converter.targetCodeToBlocks(target, code);
expect(result).toBe(true);
});

test('Hash#values should convert', async () => {
const code = 'books = {}\nbooks.values';
const result = await converter.targetCodeToBlocks(target, code);
expect(result).toBe(true);
});
});
});
Loading
Loading