optimized hyper-if/else to skip repeated evaluation of literal true/false cases

snap8
Jens Mönig 2022-02-21 08:03:36 +01:00
rodzic 59d32302f3
commit 9fce4ae9a1
3 zmienionych plików z 41 dodań i 9 usunięć

Wyświetl plik

@ -13,6 +13,9 @@
* **Documentation Updates:**
* **Translation Updates:**
### 2022-02-21
* threads: optimized hyper-if/else to skip repeated evaluation of literal true/false cases
### 2022-02-18
* new MQTT extension and library, thanks, Simon and Xavier!

Wyświetl plik

@ -17,7 +17,7 @@
<script src="src/symbols.js?version=2021-03-03"></script>
<script src="src/widgets.js?version=2021-17-09"></script>
<script src="src/blocks.js?version=2022-02-09"></script>
<script src="src/threads.js?version=2022-02-16"></script>
<script src="src/threads.js?version=2022-02-21"></script>
<script src="src/objects.js?version=2022-02-07"></script>
<script src="src/scenes.js?version=2021-11-24"></script>
<script src="src/gui.js?version=2022-02-18"></script>

Wyświetl plik

@ -64,7 +64,7 @@ SnapExtensions, AlignmentMorph, TextMorph, Cloud, HatBlockMorph*/
/*jshint esversion: 6*/
modules.threads = '2022-February-16';
modules.threads = '2022-February-21';
var ThreadManager;
var Process;
@ -2349,8 +2349,11 @@ Process.prototype.doIfElse = function () {
Process.prototype.reportIfElse = function (block) {
var inputs = this.context.inputs,
accumulator,
condition,
expression;
expression,
trueIsBlock,
falseIsBlock;
if (inputs.length < 1) {
// evaluate the first input, either a Boolean or a (nested) list
@ -2361,22 +2364,48 @@ Process.prototype.reportIfElse = function (block) {
if (inputs[0] instanceof List && this.enableHyperOps) {
// hyperize a (nested) list of Booleans
if (this.context.accumulator === null) {
this.context.accumulator = [];
// cache literal true/false cases for optimized evaluation
trueIsBlock = block.inputs()[1] instanceof BlockMorph;
falseIsBlock = block.inputs()[2] instanceof BlockMorph;
this.context.accumulator = {
results : [],
trueIsLiteral : !trueIsBlock,
trueCase : trueIsBlock ? null : block.inputs()[1].evaluate(),
falseIsLiteral : !falseIsBlock,
falseCase : falseIsBlock ? null : block.inputs()[2].evaluate()
};
} else if (inputs.length > 1) {
// retrieve & remember previous result & remove it from the inputs
this.context.accumulator.push(inputs.pop());
this.context.accumulator.results.push(inputs.pop());
}
if (this.context.accumulator.length === inputs[0].length()) {
accumulator = this.context.accumulator;
if (accumulator.results.length === inputs[0].length()) {
// done with all the conditions in the current list
this.returnValueToParentContext(
new List(this.context.accumulator)
new List(accumulator.results)
);
this.popContext();
return;
}
condition = inputs[0].at(this.context.accumulator.length + 1);
condition = inputs[0].at(accumulator.results.length + 1);
// optimize literal true-/false- cases for atomic conditions:
if (!(condition instanceof List)) {
if (condition && accumulator.trueIsLiteral) {
accumulator.results.push(accumulator.trueCase);
return;
}
if (!condition && accumulator.falseIsLiteral) {
accumulator.results.push(accumulator.falseCase);
return;
}
}
this.pushContext(block); // recursive call
this.context.addInput(condition); //
this.context.addInput(condition);
// optimize evaluation of literals:
this.context.accumulator = copy(accumulator);
this.context.accumulator.results = [];
return;
}