kopia lustrzana https://github.com/backface/turtlestitch
moved reporterizing infix expressions to search-blocks field
thanks, @bromagosa, for the brilliant idea!pull/29/head
rodzic
955aabfc93
commit
41e55064a2
140
blocks.js
140
blocks.js
|
@ -12330,8 +12330,7 @@ CommentMorph.prototype.fixLayout = function () {
|
|||
|
||||
CommentMorph.prototype.userMenu = function () {
|
||||
var menu = new MenuMorph(this),
|
||||
myself = this,
|
||||
block = this.blockify();
|
||||
myself = this;
|
||||
|
||||
menu.addItem(
|
||||
"duplicate",
|
||||
|
@ -12354,24 +12353,6 @@ CommentMorph.prototype.userMenu = function () {
|
|||
},
|
||||
'open a new window\nwith a picture of this comment'
|
||||
);
|
||||
if (block) {
|
||||
menu.addLine();
|
||||
menu.addItem(
|
||||
block,
|
||||
function () {
|
||||
var world = myself.world(),
|
||||
ide = myself.parentThatIsA(IDE_Morph);
|
||||
block.pickUp(world);
|
||||
if (ide) {
|
||||
world.hand.grabOrigin = {
|
||||
origin: ide.palette,
|
||||
position: ide.palette.center()
|
||||
};
|
||||
}
|
||||
},
|
||||
'blockify this expression'
|
||||
);
|
||||
}
|
||||
return menu;
|
||||
};
|
||||
|
||||
|
@ -12508,125 +12489,6 @@ CommentMorph.prototype.stackHeight = function () {
|
|||
return this.height();
|
||||
};
|
||||
|
||||
// CommentMorph parsing simple arithmetic expressions to reporters
|
||||
|
||||
CommentMorph.prototype.blockify = function () {
|
||||
// highly experimental Christmas Easter Egg 2016 :-)
|
||||
var ast;
|
||||
|
||||
function parseInfix(expression, operator, already) {
|
||||
// very basic binary infix parser for arithmetic expressions
|
||||
// with strict left-to-right operator precedence (like in Smalltalk)
|
||||
// which can be overriden by - nested - parentheses.
|
||||
// assumes well-formed expressions, no graceful error handling yet.
|
||||
|
||||
var inputs = ['', ''],
|
||||
idx = 0,
|
||||
ch;
|
||||
|
||||
function format(value) {
|
||||
return value instanceof Array || isNaN(+value) ? value : +value;
|
||||
}
|
||||
|
||||
function nested() {
|
||||
var level = 1,
|
||||
expr = '';
|
||||
while (idx < expression.length) {
|
||||
ch = expression[idx];
|
||||
idx += 1;
|
||||
switch (ch) {
|
||||
case '(':
|
||||
level += 1;
|
||||
break;
|
||||
case ')':
|
||||
level -= 1;
|
||||
if (!level) {
|
||||
return expr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
expr += ch;
|
||||
}
|
||||
}
|
||||
|
||||
while (idx < expression.length) {
|
||||
ch = expression[idx];
|
||||
idx += 1;
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
break;
|
||||
case '(':
|
||||
inputs[operator ? 1 : 0] = parseInfix(nested());
|
||||
break;
|
||||
case '-':
|
||||
case '+':
|
||||
case '*':
|
||||
case '/':
|
||||
if (!operator && !inputs[0].length) {
|
||||
inputs[0] += ch;
|
||||
} else if (operator) {
|
||||
return parseInfix(
|
||||
expression.slice(idx),
|
||||
ch,
|
||||
[operator, already, format(inputs[1])]
|
||||
);
|
||||
} else {
|
||||
operator = ch;
|
||||
already = format(inputs[0]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
inputs[operator ? 1 : 0] += ch;
|
||||
}
|
||||
}
|
||||
if (operator) {
|
||||
return [operator, already, format(inputs[1])];
|
||||
}
|
||||
return format(inputs[0]);
|
||||
}
|
||||
|
||||
function blockFromAST(ast) {
|
||||
var block, selectors, i, inps;
|
||||
selectors = {
|
||||
'+': 'reportSum',
|
||||
'-': 'reportDifference',
|
||||
'*': 'reportProduct',
|
||||
'/': 'reportQuotient'
|
||||
};
|
||||
block = SpriteMorph.prototype.blockForSelector(selectors[ast[0]], true);
|
||||
block.isDraggable = true;
|
||||
inps = block.inputs();
|
||||
for (i = 1; i < 3; i += 1) {
|
||||
if (ast[i] instanceof Array) {
|
||||
block.silentReplaceInput(inps[i - 1], blockFromAST(ast[i]));
|
||||
} else if (isString(ast[i])) {
|
||||
block.silentReplaceInput(
|
||||
inps[i - 1],
|
||||
SpriteMorph.prototype.variableBlock(ast[i])
|
||||
);
|
||||
} else { // number
|
||||
inps[i - 1].setContents(ast[i]);
|
||||
}
|
||||
}
|
||||
block.fixLayout();
|
||||
block.fixBlockColor(null, true);
|
||||
return block;
|
||||
}
|
||||
|
||||
if (this.contents.text.length > 100) {return null; }
|
||||
if (Process.prototype.isCatchingErrors) {
|
||||
try {
|
||||
ast = parseInfix(this.contents.text);
|
||||
return ast instanceof Array ? blockFromAST(ast) : null;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
ast = parseInfix(this.contents.text);
|
||||
return ast instanceof Array ? blockFromAST(ast) : null;
|
||||
}
|
||||
};
|
||||
|
||||
// ScriptFocusMorph //////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
|
|
|
@ -3196,7 +3196,7 @@ http://snap.berkeley.edu/run#cloud:Username=jens&ProjectName=rotation
|
|||
161219
|
||||
------
|
||||
* GUI: new url-switch: &noExitWarning
|
||||
* Blocks: highly experimental infix-expression-to-reporter parser
|
||||
* Blocks, Objects: highly experimental infix-expression-to-reporter parser
|
||||
|
||||
|
||||
== v4.10 === (in development)
|
||||
|
@ -3211,7 +3211,7 @@ Features:
|
|||
* new url option switch: &noExitWarning
|
||||
* svg support for images from the web (svg files have been supported for a long time)
|
||||
* use media dialog for browsing and importing sounds
|
||||
* highly experimental infix-expression-to-reporter parser
|
||||
* highly experimental infix-expression-to-reporter parser. Thanks, Bernat, for the brilliant idea to add it to the search-blocks field!
|
||||
|
||||
Fixes:
|
||||
* Music (play note) to work again in new and recent browser versions (Chrome 55)
|
||||
|
|
129
objects.js
129
objects.js
|
@ -82,7 +82,7 @@ SpeechBubbleMorph, RingMorph, isNil, FileReader, TableDialogMorph,
|
|||
BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, localize,
|
||||
TableMorph, TableFrameMorph, normalizeCanvas, BooleanSlotMorph*/
|
||||
|
||||
modules.objects = '2016-December-09';
|
||||
modules.objects = '2016-December-19';
|
||||
|
||||
var SpriteMorph;
|
||||
var StageMorph;
|
||||
|
@ -2425,7 +2425,8 @@ SpriteMorph.prototype.blocksMatching = function (
|
|||
blocksDict,
|
||||
myself = this,
|
||||
search = searchString.toLowerCase(),
|
||||
stage = this.parentThatIsA(StageMorph);
|
||||
stage = this.parentThatIsA(StageMorph),
|
||||
reporterized;
|
||||
|
||||
if (!types || !types.length) {
|
||||
types = ['hat', 'command', 'reporter', 'predicate', 'ring'];
|
||||
|
@ -2498,6 +2499,15 @@ SpriteMorph.prototype.blocksMatching = function (
|
|||
}
|
||||
}
|
||||
});
|
||||
// infix arithmetic expression
|
||||
if (contains(types, 'reporter')) {
|
||||
reporterized = this.reporterize(searchString);
|
||||
if (reporterized) {
|
||||
// reporterized.isTemplate = true;
|
||||
// reporterized.isDraggable = false;
|
||||
blocks.push([reporterized, '']);
|
||||
}
|
||||
}
|
||||
blocks.sort(function (x, y) {return x[1] < y[1] ? -1 : 1; });
|
||||
return blocks.map(function (each) {return each[0]; });
|
||||
};
|
||||
|
@ -2624,6 +2634,121 @@ SpriteMorph.prototype.searchBlocks = function (
|
|||
if (searchString) {searchPane.reactToKeystroke(); }
|
||||
};
|
||||
|
||||
// SpritMorph parsing simple arithmetic expressions to reporter blocks
|
||||
|
||||
SpriteMorph.prototype.reporterize = function (expressionString) {
|
||||
// highly experimental Christmas Easter Egg 2016 :-)
|
||||
var ast,
|
||||
myself = this;
|
||||
|
||||
function parseInfix(expression, operator, already) {
|
||||
// very basic binary infix parser for arithmetic expressions
|
||||
// with strict left-to-right operator precedence (like in Smalltalk)
|
||||
// which can be overriden by - nested - parentheses.
|
||||
// assumes well-formed expressions, no graceful error handling yet.
|
||||
|
||||
var inputs = ['', ''],
|
||||
idx = 0,
|
||||
ch;
|
||||
|
||||
function format(value) {
|
||||
return value instanceof Array || isNaN(+value) ? value : +value;
|
||||
}
|
||||
|
||||
function nested() {
|
||||
var level = 1,
|
||||
expr = '';
|
||||
while (idx < expression.length) {
|
||||
ch = expression[idx];
|
||||
idx += 1;
|
||||
switch (ch) {
|
||||
case '(':
|
||||
level += 1;
|
||||
break;
|
||||
case ')':
|
||||
level -= 1;
|
||||
if (!level) {
|
||||
return expr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
expr += ch;
|
||||
}
|
||||
}
|
||||
|
||||
while (idx < expression.length) {
|
||||
ch = expression[idx];
|
||||
idx += 1;
|
||||
switch (ch) {
|
||||
case ' ':
|
||||
break;
|
||||
case '(':
|
||||
inputs[operator ? 1 : 0] = parseInfix(nested());
|
||||
break;
|
||||
case '-':
|
||||
case '+':
|
||||
case '*':
|
||||
case '/':
|
||||
if (!operator && !inputs[0].length) {
|
||||
inputs[0] += ch;
|
||||
} else if (operator) {
|
||||
return parseInfix(
|
||||
expression.slice(idx),
|
||||
ch,
|
||||
[operator, already, format(inputs[1])]
|
||||
);
|
||||
} else {
|
||||
operator = ch;
|
||||
already = format(inputs[0]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
inputs[operator ? 1 : 0] += ch;
|
||||
}
|
||||
}
|
||||
if (operator) {
|
||||
return [operator, already, format(inputs[1])];
|
||||
}
|
||||
return format(inputs[0]);
|
||||
}
|
||||
|
||||
function blockFromAST(ast) {
|
||||
var block, selectors, i, inps;
|
||||
selectors = {
|
||||
'+': 'reportSum',
|
||||
'-': 'reportDifference',
|
||||
'*': 'reportProduct',
|
||||
'/': 'reportQuotient'
|
||||
};
|
||||
block = myself.blockForSelector(selectors[ast[0]], true);
|
||||
block.isDraggable = true;
|
||||
inps = block.inputs();
|
||||
for (i = 1; i < 3; i += 1) {
|
||||
if (ast[i] instanceof Array) {
|
||||
block.silentReplaceInput(inps[i - 1], blockFromAST(ast[i]));
|
||||
} else if (isString(ast[i])) {
|
||||
block.silentReplaceInput(
|
||||
inps[i - 1],
|
||||
myself.variableBlock(ast[i])
|
||||
);
|
||||
} else { // number
|
||||
inps[i - 1].setContents(ast[i]);
|
||||
}
|
||||
}
|
||||
block.fixLayout();
|
||||
block.fixBlockColor(null, true);
|
||||
return block;
|
||||
}
|
||||
|
||||
if (expressionString > 100) {return null; }
|
||||
try {
|
||||
ast = parseInfix(expressionString);
|
||||
return ast instanceof Array ? blockFromAST(ast) : null;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// SpriteMorph variable management
|
||||
|
||||
SpriteMorph.prototype.addVariable = function (name, isGlobal) {
|
||||
|
|
Ładowanie…
Reference in New Issue