From d221254eccf1bd37b8578924a8dd7c4d06cf6164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20M=C3=B6nig?= Date: Wed, 27 Apr 2022 18:46:15 +0200 Subject: [PATCH] custom block definition api, highly experimental, very much under construction --- HISTORY.md | 3 +++ snap.html | 4 ++-- src/byob.js | 33 +++++++++++++++++++++++++++- src/threads.js | 58 +++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 94 insertions(+), 4 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 63c73f96..e5e9778f 100755 --- a/HISTORY.md +++ b/HISTORY.md @@ -44,6 +44,9 @@ * **Translation Updates:** * German +### 2022-04-27 +* threads, byob: custom block definition api, highly experimental, very much under construction + ### 2022-04-26 * gui: distinguish between embedded blocks code and raw data in PNGs * morphic: fixed bulk-drop of images diff --git a/snap.html b/snap.html index a82a687e..4e4210c7 100755 --- a/snap.html +++ b/snap.html @@ -17,13 +17,13 @@ - + - + diff --git a/src/byob.js b/src/byob.js index 1c9ceae8..2757d3cb 100644 --- a/src/byob.js +++ b/src/byob.js @@ -111,7 +111,7 @@ ArgLabelMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.byob = '2022-April-20'; +modules.byob = '2022-April-27'; // Declarations @@ -530,6 +530,37 @@ CustomBlockDefinition.prototype.updateTranslations = function (text) { }); }; +// CustomBlockDefinition API, highly experimental & under construction + +CustomBlockDefinition.prototype.setBlockLabel = function (abstractSpec) { + // private - only to be called from a Process that also does housekeeping + // abstract block specs replace the inputs with underscores, + // e.g. "move _ steps", "say _", "_ + _" + var count = abstractSpec.split(' ').filter(word => word === '_').length, + inputNames = this.inputNames(), + parts = [], + spec = abstractSpec; + + if (count !== inputNames.length) { // not yet sure about this... (jens) + throw new Error('expecting the number of inputs to match'); + } + if (spec.startsWith('_ ')) { + parts.push(''); + spec = spec.slice(2); + } + if (spec.endsWith(' _')) { + spec = spec.slice(0, -2); + } + parts = parts.concat(spec.split(' _ ')); + spec = ''; + parts.forEach((part, i) => + spec += (part + ( + inputNames[i] ? ' %\'' + inputNames[i] + '\' ' : '') + ) + ); + this.spec = spec.trim(); +}; + // CustomBlockDefinition picturing CustomBlockDefinition.prototype.scriptsPicture = function () { diff --git a/src/threads.js b/src/threads.js index a13e936b..ef01a2c0 100644 --- a/src/threads.js +++ b/src/threads.js @@ -65,7 +65,7 @@ StagePickerMorph*/ /*jshint esversion: 11, bitwise: false, evil: true*/ -modules.threads = '2022-April-20'; +modules.threads = '2022-April-27'; var ThreadManager; var Process; @@ -5624,6 +5624,62 @@ Process.prototype.reportBasicBlockAttribute = function (attribute, block) { return ''; }; +Process.prototype.doSetBlockAttribute = function (attribute, block, val) { + // highly experimental & under construction + var choice = this.inputOption(attribute), + rcvr = this.blockReceiver(), + ide = rcvr.parentThatIsA(IDE_Morph), + oldSpec, + count = 1, + expr, + def, + template; + + this.assertType(block, ['command', 'reporter', 'predicate']); + expr = block.expression; + def = expr.isGlobal ? expr.definition : rcvr.getMethod(expr.semanticSpec); + oldSpec = def.blockSpec(); + + switch (choice) { + case 'label': + def.setBlockLabel(val); + break; + case 'definition': + return; + case 'category': + return; + case 'global?': + return; + } + + // make sure the spec is unique + while (rcvr.doubleDefinitionsFor(def).length > 0) { + count += 1; + def.spec += (' (' + count + ')'); + } + + // update all block instances: + // refer to "updateDefinition()" of BlockEditorMorph: + template = rcvr.paletteBlockInstance(def); + + if (def.isGlobal) { + rcvr.allBlockInstances(def).reverse().forEach( + block => block.refresh() + ); + } else { + rcvr.allDependentInvocationsOf(oldSpec).reverse().forEach( + block => block.refresh(def) + ); + } + if (template) { + template.refreshDefaults(); + } + ide.flushPaletteCache(); + ide.categories.refreshEmpty(); + ide.refreshPalette(); + ide.recordUnsavedChanges(); +}; + Process.prototype.reportAttributeOf = function (attribute, name) { // hyper-dyadic // note: specifying strings in the left input only accesses