summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--blocks.js33
-rwxr-xr-xhistory.txt9
-rw-r--r--lists.js5
-rw-r--r--threads.js20
4 files changed, 53 insertions, 14 deletions
diff --git a/blocks.js b/blocks.js
index 73ef884..82ef601 100644
--- a/blocks.js
+++ b/blocks.js
@@ -155,7 +155,7 @@ DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph, Costume*/
// Global stuff ////////////////////////////////////////////////////////
-modules.blocks = '2014-October-01';
+modules.blocks = '2014-November-17';
var SyntaxElementMorph;
@@ -394,10 +394,8 @@ SyntaxElementMorph.prototype.allInputs = function () {
};
SyntaxElementMorph.prototype.allEmptySlots = function () {
-/*
- answer empty input slots of all children excluding myself,
- but omit those in nested rings (lambdas) and JS-Function primitives
-*/
+ // answer empty input slots of all children excluding myself,
+ // but omit those in nested rings (lambdas) and JS-Function primitives
var empty = [];
if (!(this instanceof RingMorph) &&
(this.selector !== 'reportJSFunction')) {
@@ -412,6 +410,21 @@ SyntaxElementMorph.prototype.allEmptySlots = function () {
return empty;
};
+SyntaxElementMorph.prototype.allReportBlocks = function () {
+ // answer report blocks of all children including myself,
+ // but omit those in nested rings (lambdas)
+ if (this.selector === 'doReport') {return [this]; }
+ var reports = [];
+ if (!(this instanceof RingMorph)) {
+ this.children.forEach(function (morph) {
+ if (morph.allReportBlocks) {
+ reports = reports.concat(morph.allReportBlocks());
+ }
+ });
+ }
+ return reports;
+};
+
SyntaxElementMorph.prototype.replaceInput = function (oldArg, newArg) {
var scripts = this.parentThatIsA(ScriptsMorph),
replacement = newArg,
@@ -3169,9 +3182,13 @@ BlockMorph.prototype.snap = function () {
I inherit from BlockMorph adding the following most important
public accessors:
- nextBlock() - set / get the block attached to my bottom
- bottomBlock() - answer the bottom block of my stack
- blockSequence() - answer an array of blocks starting with myself
+ nextBlock() - set / get the block attached to my bottom
+ bottomBlock() - answer the bottom block of my stack
+ blockSequence() - answer an array of blocks starting with myself
+
+ and the following "lexical awareness" indicator:
+
+ partOfCustomCommand - temporary bool set by the evaluator
*/
// CommandBlockMorph inherits from BlockMorph:
diff --git a/history.txt b/history.txt
index b3bc7da..c26599c 100755
--- a/history.txt
+++ b/history.txt
@@ -2317,3 +2317,12 @@ ______
141114
------
* Threads, Store: Fix reporting out of nested custom C-shaped blocks
+
+141117
+------
+* Threads, Blocks: Treat REPORT blocks inside custom command definitions as STOP THIS BLOCK / IGNORE INPUTS
+
+141120
+------
+* Lists: Fixed #642 avoid “freezing” when calling CONS on non-list/null
+* Threads: Fixed #364 avoid “freezing” when calling LAUNCH on empty ring
diff --git a/lists.js b/lists.js
index a4aff6c..bd856fe 100644
--- a/lists.js
+++ b/lists.js
@@ -61,7 +61,7 @@ PushButtonMorph, SyntaxElementMorph, Color, Point, WatcherMorph,
StringMorph, SpriteMorph, ScrollFrameMorph, CellMorph, ArrowMorph,
MenuMorph, snapEquals, Morph, isNil, localize, MorphicPreferences*/
-modules.lists = '2014-July-28';
+modules.lists = '2014-November-20';
var List;
var ListWatcherMorph;
@@ -125,6 +125,9 @@ List.prototype.changed = function () {
List.prototype.cons = function (car, cdr) {
var answer = new List();
+ if (!(cdr instanceof List || isNil(cdr))) {
+ throw new Error("cdr isn't a list: " + cdr);
+ }
answer.first = isNil(car) ? null : car;
answer.rest = cdr || null;
answer.isLinked = true;
diff --git a/threads.js b/threads.js
index dfa335e..c6b0fde 100644
--- a/threads.js
+++ b/threads.js
@@ -83,7 +83,7 @@ ArgLabelMorph, localize, XML_Element, hex_sha512*/
// Global stuff ////////////////////////////////////////////////////////
-modules.threads = '2014-November-15';
+modules.threads = '2014-November-20';
var ThreadManager;
var Process;
@@ -225,8 +225,9 @@ ThreadManager.prototype.removeTerminatedProcesses = function () {
var remaining = [];
this.processes.forEach(function (proc) {
if (!proc.isRunning() && !proc.errorFlag && !proc.isDead) {
- proc.topBlock.removeHighlight();
-
+ if (proc.topBlock instanceof BlockMorph) {
+ proc.topBlock.removeHighlight();
+ }
if (proc.prompter) {
proc.prompter.destroy();
if (proc.homeContext.receiver.stopTalking) {
@@ -880,6 +881,9 @@ Process.prototype.fork = function (context, args) {
'continuations cannot be forked'
);
}
+ if (!(context instanceof Context)) {
+ throw new Error('expecting a ring but getting ' + context);
+ }
var outer = new Context(null, null, context.outerContext),
runnable = new Context(null,
@@ -945,6 +949,9 @@ Process.prototype.fork = function (context, args) {
};
Process.prototype.doReport = function (value) {
+ if (this.context.expression.partOfCustomCommand) {
+ return this.doStopBlock();
+ }
while (this.context && this.context.expression !== 'exitReporter') {
if (this.context.expression === 'doStopWarping') {
this.doStopWarping();
@@ -1042,8 +1049,6 @@ Process.prototype.evaluateCustomBlock = function () {
}
if (runnable.expression instanceof CommandBlockMorph) {
- runnable.expression = runnable.expression.blockSequence();
-
// insert a reporter exit tag for the
// CALL SCRIPT primitive variant
if (this.context.expression.definition.type !== 'command') {
@@ -1054,7 +1059,12 @@ Process.prototype.evaluateCustomBlock = function () {
outer.receiver
);
runnable.parentContext = exit;
+ } else { // mark all REPORT blocks as being part of a custom command
+ runnable.expression.allReportBlocks().forEach(function (rb) {
+ rb.partOfCustomCommand = true;
+ });
}
+ runnable.expression = runnable.expression.blockSequence();
}
};