From 4acf1896bd9fa57d3dbe3f4721b6790c6f3b0d56 Mon Sep 17 00:00:00 2001 From: Jens Mönig Date: Sat, 21 Mar 2015 11:12:43 +0100 Subject: Prototypal inheritance of sprite-local variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (experimental) slotwise inheritance à la Henry Lieberman for sprite-local variables. see http://web.media.mit.edu/~lieber/Lieberary/OOP/Delegation/Delegation.htm l Let a sprite inherit another sprite’s local variables by making it the “parent” in the sprite-icon’s context menu (the button icon in the sprite corral underneath the stage). The child not only inherits the variable slot but also - dynamically - the parent variable’s value. Changing the parent’s variable value also changes it for every child. If a child uses SET or CHANGE on an inherited variable it automatically “shadows” it with its own value, thereby stopping dynamic participation in the parent slot’s value (in effect dis-inheriting that slot). Deleting a shadowed variable slot once again reinstates its inheritance status. inherited variables are shown as “ghosted” both in the child’s variables palette and in such stage watchers. “Shadowing” them un-ghosts both the variable blob template in the palette and the watcher onstage (if any). Deleting a shadowed variable once again ghosts the watcher and the palette block template. Delete a (shadowed) variable either via the “Delete a variable” button in the IDE or using the new “Delete” block in the variables category --- threads.js | 73 +++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 22 deletions(-) (limited to 'threads.js') diff --git a/threads.js b/threads.js index 50af8dd..d3dcfc9 100644 --- a/threads.js +++ b/threads.js @@ -83,7 +83,7 @@ ArgLabelMorph, localize, XML_Element, hex_sha512*/ // Global stuff //////////////////////////////////////////////////////// -modules.threads = '2015-February-28'; +modules.threads = '2015-March-21'; var ThreadManager; var Process; @@ -1159,7 +1159,7 @@ Process.prototype.doSetVar = function (varName, value) { name = name.expression.blockSpec; } } - varFrame.setVar(name, value); + varFrame.setVar(name, value, this.blockReceiver()); }; Process.prototype.doChangeVar = function (varName, value) { @@ -1171,7 +1171,7 @@ Process.prototype.doChangeVar = function (varName, value) { name = name.expression.blockSpec; } } - varFrame.changeVar(name, value); + varFrame.changeVar(name, value, this.blockReceiver()); }; Process.prototype.reportGetVar = function () { @@ -1295,6 +1295,20 @@ Process.prototype.doRemoveTemporaries = function () { } }; +// Process sprite inheritance primitives + +Process.prototype.doDeleteAttr = function (attrName) { + // currently only variables are deletable + var name = attrName; + + if (name instanceof Context) { + if (name.expression.selector === 'reportGetVar') { + name = name.expression.blockSpec; + } + } + this.blockReceiver().deleteVariable(name); +}; + // Process lists primitives Process.prototype.reportNewList = function (elements) { @@ -3103,35 +3117,50 @@ VariableFrame.prototype.silentFind = function (name) { return null; }; -VariableFrame.prototype.setVar = function (name, value) { -/* - change the specified variable if it exists - else throw an error, because variables need to be - declared explicitly (e.g. through a "script variables" block), - before they can be accessed. -*/ +VariableFrame.prototype.setVar = function (name, value, sender) { + // change the specified variable if it exists + // else throw an error, because variables need to be + // declared explicitly (e.g. through a "script variables" block), + // before they can be accessed. + // if the found frame is inherited by the sender sprite + // shadow it (create an explicit one for the sender) + // before setting the value ("create-on-write") + var frame = this.find(name); if (frame) { - frame.vars[name].value = value; + if (sender instanceof SpriteMorph && + (frame.owner instanceof SpriteMorph) && + (sender !== frame.owner)) { + sender.shadowVar(name, value); + } else { + frame.vars[name].value = value; + } } }; -VariableFrame.prototype.changeVar = function (name, delta) { -/* - change the specified variable if it exists - else throw an error, because variables need to be - declared explicitly (e.g. through a "script variables" block, - before they can be accessed. -*/ +VariableFrame.prototype.changeVar = function (name, delta, sender) { + // change the specified variable if it exists + // else throw an error, because variables need to be + // declared explicitly (e.g. through a "script variables" block, + // before they can be accessed. + // if the found frame is inherited by the sender sprite + // shadow it (create an explicit one for the sender) + // before changing the value ("create-on-write") + var frame = this.find(name), - value; + value, + newValue; if (frame) { value = parseFloat(frame.vars[name].value); - if (isNaN(value)) { - frame.vars[name].value = delta; + newValue = isNaN(value) ? delta : value + parseFloat(delta); + if (sender instanceof SpriteMorph && + (frame.owner instanceof SpriteMorph) && + (sender !== frame.owner)) { + sender.shadowVar(name, newValue); } else { - frame.vars[name].value = value + parseFloat(delta); + frame.vars[name].value = newValue; } + } }; -- cgit v1.3.1