diff --git a/HISTORY.md b/HISTORY.md index 09610797..c6d33f4f 100755 --- a/HISTORY.md +++ b/HISTORY.md @@ -26,6 +26,7 @@ * new "get pen attribute" reporter * new "write" command in pen category (used to be "label" in tools) * new "map","keep", "combine" and "for each" primitives in list category + * new "for" loop primitive in the Control category * added "neg", "lg" (log2) and "2^" selectors to monadic function reporter in Operators * added "^" reporter (power of) in the Operators category * added "width" and "height" as attribute selectors of the OF primitive for the stage @@ -69,8 +70,9 @@ * French ### 2019-04-24 -* Threads: new "combine" primitive in list category +* Threads, Objects: new "combine" primitive in list category * Threads: added type-assertions for the new HOF prims +* Threads, Objects: new "for" loop primitive in Control category ### 2019-04-23 * Threads: fixed JS stack overflow issue for MAP primitive diff --git a/src/objects.js b/src/objects.js index 6786b728..31b5d49b 100644 --- a/src/objects.js +++ b/src/objects.js @@ -736,6 +736,12 @@ SpriteMorph.prototype.initBlocks = function () { category: 'control', spec: 'repeat until %b %loop' }, + doFor: { + type: 'command', + category: 'control', + spec: 'for %upvar = %n to %n %cla', + defaults: ['i', 1, 10] + }, doIf: { type: 'command', category: 'control', @@ -2172,6 +2178,7 @@ SpriteMorph.prototype.blockTemplates = function (category) { blocks.push(block('doForever')); blocks.push(block('doRepeat')); blocks.push(block('doUntil')); + blocks.push(block('doFor')); blocks.push('-'); blocks.push(block('doIf')); blocks.push(block('doIfElse')); @@ -7747,6 +7754,7 @@ StageMorph.prototype.blockTemplates = function (category) { blocks.push(block('doForever')); blocks.push(block('doRepeat')); blocks.push(block('doUntil')); + blocks.push(block('doFor')); blocks.push('-'); blocks.push(block('doIf')); blocks.push(block('doIfElse')); diff --git a/src/threads.js b/src/threads.js index aae3c344..47b0f0f1 100644 --- a/src/threads.js +++ b/src/threads.js @@ -2098,6 +2098,37 @@ Process.prototype.doForEach = function (upvar, list, script) { this.evaluate(script, new List(), true); }; +Process.prototype.doFor = function (upvar, start, end, script) { + // perform a script for every integer step between start and stop, + // assigning the current iteration index to a variable with the + // name specified in the "upvar" parameter, so it can be referenced + // within the script. + + var dta; + if (this.context.aggregation === null) { + this.context.aggregation = { + idx : Math.floor(start), + test : start < end ? + function () {return this.idx > end; } + : function () {return this.idx < end; }, + step : start < end ? 1 : -1, + parms : new List() // empty parameters, reusable to avoid GC + }; + } + + dta = this.context.aggregation; + this.context.outerContext.variables.addVar(upvar); + this.context.outerContext.variables.setVar( + upvar, + dta.idx + ); + if (dta.test()) {return; } + dta.idx += dta.step; + this.pushContext('doYield'); + this.pushContext(); + this.evaluate(script, dta.parms, true); +}; + // Process interpolated HOF primitives /*