kopia lustrzana https://github.com/backface/turtlestitch
support for compiling reporters (experimental)
currently “hidden” behind shift-click in the settings menuupd4.2
rodzic
dad8875afd
commit
07ce8493b4
|
@ -148,7 +148,7 @@ CustomCommandBlockMorph, SymbolMorph, ToggleButtonMorph, DialMorph*/
|
|||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
modules.blocks = '2018-January-25';
|
||||
modules.blocks = '2018-February-15';
|
||||
|
||||
var SyntaxElementMorph;
|
||||
var BlockMorph;
|
||||
|
@ -5873,6 +5873,7 @@ RingMorph.prototype.vanishForSimilar = function () {
|
|||
if (block.selector === 'reportGetVar' ||
|
||||
block.selector === 'reportJSFunction' ||
|
||||
block.selector == 'reportAttributeOf' ||
|
||||
block.selector == 'reportCompiled' ||
|
||||
(block instanceof RingMorph)
|
||||
) {
|
||||
this.parent.silentReplaceInput(this, block);
|
||||
|
|
16
gui.js
16
gui.js
|
@ -75,7 +75,7 @@ isRetinaSupported, SliderMorph, Animation, BoxMorph, MediaRecorder*/
|
|||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
modules.gui = '2018-February-09';
|
||||
modules.gui = '2018-February-15';
|
||||
|
||||
// Declarations
|
||||
|
||||
|
@ -2970,6 +2970,20 @@ IDE_Morph.prototype.settingsMenu = function () {
|
|||
'EXPERIMENTAL! check to enable\n live custom control structures',
|
||||
true
|
||||
);
|
||||
addPreference(
|
||||
'JIT compiler support',
|
||||
function () {
|
||||
Process.prototype.enableCompiling =
|
||||
!Process.prototype.enableCompiling;
|
||||
myself.currentSprite.blocksCache.operators = null;
|
||||
myself.currentSprite.paletteCache.operators = null;
|
||||
myself.refreshPalette();
|
||||
},
|
||||
Process.prototype.enableCompiling,
|
||||
'EXPERIMENTAL! uncheck to disable live\nsupport for compiling',
|
||||
'EXPERIMENTAL! check to enable\nsupport for compiling',
|
||||
true
|
||||
);
|
||||
menu.addLine(); // everything below this line is stored in the project
|
||||
addPreference(
|
||||
'Thread safe scripts',
|
||||
|
|
|
@ -3952,12 +3952,18 @@ Translation Updates:
|
|||
* Threads: Allow JS-functions for invoke()
|
||||
* Threads, Objects: Small compilation experiment
|
||||
|
||||
180215
|
||||
------
|
||||
* Threads, Blocks, Objects: experimental JIT compiler
|
||||
|
||||
|
||||
=== v4.1.2 features ===
|
||||
|
||||
v4.1.2 New Features:
|
||||
* experimental JIT compiler (in progress)
|
||||
|
||||
Notable Changes:
|
||||
* new cloud backend
|
||||
|
||||
Notable Fixes:
|
||||
|
||||
|
|
|
@ -185,7 +185,7 @@ SnapTranslator.dict.de = {
|
|||
'translator_e-mail':
|
||||
'jens@moenig.org', // optional
|
||||
'last_changed':
|
||||
'2018-01-25', // this, too, will appear in the Translators tab
|
||||
'2018-02-15', // this, too, will appear in the Translators tab
|
||||
|
||||
// GUI
|
||||
// control bar:
|
||||
|
@ -628,6 +628,8 @@ SnapTranslator.dict.de = {
|
|||
'ist %s identisch mit %s ?',
|
||||
'JavaScript function ( %mult%s ) { %code }':
|
||||
'JavaScript Funktion ( %mult%s ) { %code }',
|
||||
'compile %repRing':
|
||||
'kompiliere %repRing',
|
||||
|
||||
'type of %s':
|
||||
'Typ von %s',
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
/*global modules, contains*/
|
||||
|
||||
modules.locale = '2018-February-9';
|
||||
modules.locale = '2018-February-15';
|
||||
|
||||
// Global stuff
|
||||
|
||||
|
@ -160,7 +160,7 @@ SnapTranslator.dict.de = {
|
|||
'translator_e-mail':
|
||||
'jens@moenig.org',
|
||||
'last_changed':
|
||||
'2018-01-25'
|
||||
'2018-02-15'
|
||||
};
|
||||
|
||||
SnapTranslator.dict.it = {
|
||||
|
|
15
objects.js
15
objects.js
|
@ -81,9 +81,9 @@ modules, IDE_Morph, VariableDialogMorph, HTMLCanvasElement, Context, List,
|
|||
SpeechBubbleMorph, RingMorph, isNil, FileReader, TableDialogMorph,
|
||||
BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, localize,
|
||||
TableMorph, TableFrameMorph, normalizeCanvas, BooleanSlotMorph, HandleMorph,
|
||||
AlignmentMorph*/
|
||||
AlignmentMorph, Process*/
|
||||
|
||||
modules.objects = '2018-February-13';
|
||||
modules.objects = '2018-February-15';
|
||||
|
||||
var SpriteMorph;
|
||||
var StageMorph;
|
||||
|
@ -1079,8 +1079,7 @@ SpriteMorph.prototype.initBlocks = function () {
|
|||
spec: '%txtfun of %s',
|
||||
defaults: [null, "Abelson & Sussman"]
|
||||
},
|
||||
reportCompiled: { // only in dev mode - experimental
|
||||
dev: true,
|
||||
reportCompiled: { // experimental
|
||||
type: 'reporter',
|
||||
category: 'operators',
|
||||
spec: 'compile %repRing'
|
||||
|
@ -2134,6 +2133,9 @@ SpriteMorph.prototype.blockTemplates = function (category) {
|
|||
if (true) { // (Process.prototype.enableJS) {
|
||||
blocks.push('-');
|
||||
blocks.push(block('reportJSFunction'));
|
||||
if (Process.prototype.enableCompiling) {
|
||||
blocks.push(block('reportCompiled'));
|
||||
}
|
||||
}
|
||||
|
||||
// for debugging: ///////////////
|
||||
|
@ -2149,7 +2151,6 @@ SpriteMorph.prototype.blockTemplates = function (category) {
|
|||
blocks.push('-');
|
||||
blocks.push(block('reportTypeOf'));
|
||||
blocks.push(block('reportTextFunction'));
|
||||
blocks.push(block('reportCompiled'));
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
|
@ -7268,6 +7269,9 @@ StageMorph.prototype.blockTemplates = function (category) {
|
|||
if (true) { // (Process.prototype.enableJS) {
|
||||
blocks.push('-');
|
||||
blocks.push(block('reportJSFunction'));
|
||||
if (Process.prototype.enableCompiling) {
|
||||
blocks.push(block('reportCompiled'));
|
||||
}
|
||||
}
|
||||
|
||||
// for debugging: ///////////////
|
||||
|
@ -7283,7 +7287,6 @@ StageMorph.prototype.blockTemplates = function (category) {
|
|||
blocks.push('-');
|
||||
blocks.push(block('reportTypeOf'));
|
||||
blocks.push(block('reportTextFunction'));
|
||||
blocks.push(block('reportCompiled'));
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
|
|
152
threads.js
152
threads.js
|
@ -61,7 +61,7 @@ StageMorph, SpriteMorph, StagePrompterMorph, Note, modules, isString, copy,
|
|||
isNil, WatcherMorph, List, ListWatcherMorph, alert, console, TableMorph,
|
||||
TableFrameMorph, ColorSlotMorph, isSnapObject*/
|
||||
|
||||
modules.threads = '2018-February-13';
|
||||
modules.threads = '2018-February-15';
|
||||
|
||||
var ThreadManager;
|
||||
var Process;
|
||||
|
@ -527,6 +527,7 @@ Process.prototype.timeout = 500; // msecs after which to force yield
|
|||
Process.prototype.isCatchingErrors = true;
|
||||
Process.prototype.enableLiveCoding = false; // experimental
|
||||
Process.prototype.enableSingleStepping = false; // experimental
|
||||
Process.prototype.enableCompiling = false; // experimental
|
||||
Process.prototype.flashTime = 0; // experimental
|
||||
// Process.prototype.enableJS = false;
|
||||
|
||||
|
@ -740,64 +741,121 @@ Process.prototype.evaluateBlock = function (block, argCount) {
|
|||
// ** highly experimental and heavily under construction **
|
||||
|
||||
Process.prototype.reportCompiled = function (context) {
|
||||
this.assertType(context, 'reporter');
|
||||
this.assertType(context, ['reporter', 'predicate']);
|
||||
return this.compileFunction(context.expression, context.inputs);
|
||||
};
|
||||
|
||||
Process.prototype.compileFunction = function (block, parameters) {
|
||||
// private
|
||||
return this.compileExpression(block);
|
||||
|
||||
// parameter binding is commented out for now
|
||||
/*
|
||||
var selector = block.selector,
|
||||
args = this.compileInputs(block),
|
||||
body = 'return Cfunc.apply(null, [' + args.toString() + ']);',
|
||||
method = this[selector] ||
|
||||
(this.context.receiver || this.receiver)[selector];
|
||||
|
||||
// global!
|
||||
Cfunc = function () {return method.apply(null, arguments); };
|
||||
|
||||
return Function.apply(null, parameters.concat([body]));
|
||||
*/
|
||||
// first test for unbound variables
|
||||
block.allChildren().forEach(function (morph) {
|
||||
if (morph.selector === 'reportGetVar' &&
|
||||
!contains(parameters, morph.blockSpec)
|
||||
) {
|
||||
throw new Error(
|
||||
'compiling does not yet support\n' +
|
||||
'variables that are not\nformal parameters'
|
||||
);
|
||||
}
|
||||
});
|
||||
return Function.apply(
|
||||
null,
|
||||
parameters.concat(['return ' + this.compileExpression(block)])
|
||||
);
|
||||
};
|
||||
|
||||
Process.prototype.compileExpression = function (block) {
|
||||
// private
|
||||
var selector = block.selector,
|
||||
args = this.compileInputs(block),
|
||||
method = this[selector] ||
|
||||
(this.context.receiver || this.receiver)[selector];
|
||||
inputs = block.inputs(),
|
||||
src,
|
||||
rcvr,
|
||||
args;
|
||||
|
||||
function evalArg(value) {
|
||||
return value instanceof Function ? value() : value;
|
||||
}
|
||||
|
||||
return function () {return method.apply(null, args.map(evalArg)); };
|
||||
// first check for special forms and infix operators
|
||||
switch (selector) {
|
||||
case 'reportOr':
|
||||
return this.compileInfix('||', inputs);
|
||||
case 'reportAnd':
|
||||
return this.compileInfix('&&', inputs);
|
||||
case 'evaluateCustomBlock':
|
||||
throw new Error(
|
||||
'compiling does not yet support\n' +
|
||||
'custom blocks'
|
||||
);
|
||||
default:
|
||||
src = this[selector] ? this : (this.context.receiver || this.receiver);
|
||||
rcvr = src.constructor.name + '.prototype';
|
||||
args = this.compileInputs(inputs);
|
||||
return rcvr + '.' + selector + '.apply('+ rcvr + ', [' + args +'])';
|
||||
}
|
||||
};
|
||||
|
||||
Process.prototype.compileInputs = function (block) {
|
||||
var args = [],
|
||||
myself = this;
|
||||
block.inputs().forEach(function (inp) {
|
||||
if (inp.isEmptySlot && inp.isEmptySlot()) {
|
||||
// implicit parameter
|
||||
} else if (inp instanceof ArgMorph) {
|
||||
// literal - evaluate inline
|
||||
args.push(inp.evaluate());
|
||||
} else if (inp instanceof BlockMorph) {
|
||||
if (inp.selector === 'reportGetVar') {
|
||||
args.push(inp.blockSpec);
|
||||
} else {
|
||||
// recurse
|
||||
args.push(myself.compileExpression(inp));
|
||||
}
|
||||
} else {
|
||||
// raise error about unsupported slot
|
||||
}
|
||||
Process.prototype.compileInfix = function (operator, inputs) {
|
||||
return '(' + this.compileInput(inputs[0]) + ' ' + operator + ' ' +
|
||||
this.compileInput(inputs[1]) +')';
|
||||
};
|
||||
|
||||
Process.prototype.compileInputs = function (array) {
|
||||
var args = '',
|
||||
myself = this;
|
||||
|
||||
array.forEach(function (inp) {
|
||||
if (args.length) {
|
||||
args += ', ';
|
||||
}
|
||||
args += myself.compileInput(inp);
|
||||
});
|
||||
return args;
|
||||
return args;
|
||||
};
|
||||
|
||||
Process.prototype.compileInput = function (inp) {
|
||||
var value, type;
|
||||
|
||||
if (inp.isEmptySlot && inp.isEmptySlot()) {
|
||||
// implicit parameter - unsupported for now
|
||||
throw new Error(
|
||||
'compiling does not yet support\n' +
|
||||
'implicit parameters\n(empty input slots)'
|
||||
);
|
||||
} else if (inp instanceof MultiArgMorph) {
|
||||
if (inp.isStatic) {
|
||||
return 'new List([' + this.compileInputs(inp.inputs()) + '])';
|
||||
} else {
|
||||
return '' + this.compileInputs(inp.inputs());
|
||||
}
|
||||
} else if (inp instanceof ArgMorph) {
|
||||
// literal - evaluate inline
|
||||
value = inp.evaluate();
|
||||
type = this.reportTypeOf(value);
|
||||
switch (type) {
|
||||
case 'number':
|
||||
case 'Boolean':
|
||||
return '' + value;
|
||||
case 'text':
|
||||
// enclose in double quotes
|
||||
return '"' + value + '"';
|
||||
case 'list':
|
||||
return 'new List([' + this.compileInputs(value) + '])';
|
||||
default:
|
||||
throw new Error(
|
||||
'compiling does not yet support\n' +
|
||||
'inputs of type\n' +
|
||||
type
|
||||
);
|
||||
}
|
||||
} else if (inp instanceof BlockMorph) {
|
||||
if (inp.selector === 'reportGetVar') {
|
||||
// un-quoted string:
|
||||
return inp.blockSpec;
|
||||
} else {
|
||||
return this.compileExpression(inp);
|
||||
}
|
||||
} else {
|
||||
throw new Error(
|
||||
'compiling does not yet support\n' +
|
||||
'input slots of type\n' +
|
||||
inp.constructor.name
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Process: Special Forms Blocks Primitives
|
||||
|
|
Ładowanie…
Reference in New Issue