new DEFINE BLOCK primitive

snap8
Jens Mönig 2022-05-02 18:51:34 +02:00
rodzic e41dd6c281
commit 4252c1bef0
5 zmienionych plików z 69 dodań i 14 usunięć

Wyświetl plik

@ -49,6 +49,7 @@
* blocks, threads: programmatically change the type of unused custom blocks
* blocks, threads: new "scope" choice in block menu dropdown
* blocks, threads: programmatically change the scope of unused custom blocks
* blocks, objects, threads: new DEFINE BLOCK primitive
### 2022-05-01
* byob: programmatically reduce the number of inputs in a custom block

Wyświetl plik

@ -18,7 +18,7 @@
<script src="src/widgets.js?version=2021-17-09"></script>
<script src="src/blocks.js?version=2022-05-02"></script>
<script src="src/threads.js?version=2022-05-02"></script>
<script src="src/objects.js?version=2022-04-28"></script>
<script src="src/objects.js?version=2022-05-02"></script>
<script src="src/scenes.js?version=2022-03-03"></script>
<script src="src/gui.js?version=2022-04-26"></script>
<script src="src/paint.js?version=2021-07-05"></script>

Wyświetl plik

@ -111,7 +111,7 @@ ArgLabelMorph*/
// Global stuff ////////////////////////////////////////////////////////
modules.byob = '2022-May-01';
modules.byob = '2022-May-02';
// Declarations
@ -564,25 +564,29 @@ CustomBlockDefinition.prototype.setBlockLabel = function (abstractSpec) {
CustomBlockDefinition.prototype.setBlockDefinition = function (aContext) {
// private - only to be called from a Process that also does housekeeping
var oldInputs = this.inputNames(),
newInputs = aContext.inputs,
newInputs = aContext.inputs,
declarations = this.declarations,
parts = [],
suffix = [],
body = aContext,
reportBlock,
spec;
// remove excess inputs or add missing ones
this.addInputs(newInputs.length - oldInputs.length);
spec = this.abstractBlockSpec();
oldInputs = this.inputNames();
// change the input names in the spec to those of the given context
if (spec.startsWith('_ ')) {
while (spec.startsWith('_ ')) {
parts.push('');
spec = spec.slice(2);
}
if (spec.endsWith(' _')) {
while (spec.endsWith(' _')) {
spec = spec.slice(0, -2);
suffix.push('');
}
parts = parts.concat(spec.split(' _ '));
parts = parts.concat(spec.split(' _ ')).concat(suffix);
spec = '';
parts.forEach((part, i) =>
spec += (part + (
@ -599,7 +603,20 @@ CustomBlockDefinition.prototype.setBlockDefinition = function (aContext) {
}
// replace the definition body with the given context
this.body = aContext;
if (body.expression instanceof Array) {
this.body = null;
return;
} else if (body.expression instanceof ReporterBlockMorph) {
// turn reporter epressions into a command stack with "report"
body = copy(aContext);
reportBlock = SpriteMorph.prototype.blockForSelector('doReport');
reportBlock.replaceInput(
reportBlock.inputs()[0],
body.expression.fullCopy()
);
body.expression = reportBlock;
}
this.body = body;
};
CustomBlockDefinition.prototype.addInputs = function (count) {

Wyświetl plik

@ -94,7 +94,7 @@ embedMetadataPNG*/
/*jshint esversion: 6*/
modules.objects = '2022-April-28';
modules.objects = '2022-May-02';
var SpriteMorph;
var StageMorph;
@ -1105,6 +1105,11 @@ SpriteMorph.prototype.initBlocks = function () {
spec: 'set %byob of block %repRing to %s',
defaults: [['definition']]
},
reportDefineBlock: {
type: 'reporter',
category: 'sensing',
spec: 'define block %s %repRing'
},
// Operators
reifyScript: {
@ -2698,6 +2703,7 @@ SpriteMorph.prototype.blockTemplates = function (
blocks.push(block('reportDate'));
blocks.push(block('reportBlockAttribute'));
blocks.push(block('doSetBlockAttribute'));
blocks.push(block('reportDefineBlock'));
// for debugging: ///////////////
if (devMode) {
@ -9166,6 +9172,7 @@ StageMorph.prototype.blockTemplates = function (
blocks.push(block('reportDate'));
blocks.push(block('reportBlockAttribute'));
blocks.push(block('doSetBlockAttribute'));
blocks.push(block('reportDefineBlock'));
// for debugging: ///////////////
if (this.world().isDevMode) {

Wyświetl plik

@ -61,7 +61,7 @@ StageMorph, SpriteMorph, StagePrompterMorph, Note, modules, isString, copy, Map,
isNil, WatcherMorph, List, ListWatcherMorph, alert, console, TableMorph, BLACK,
TableFrameMorph, ColorSlotMorph, isSnapObject, newCanvas, Symbol, SVG_Costume,
SnapExtensions, AlignmentMorph, TextMorph, Cloud, HatBlockMorph,
StagePickerMorph*/
StagePickerMorph, CustomBlockDefinition*/
/*jshint esversion: 11, bitwise: false, evil: true*/
@ -5636,7 +5636,6 @@ Process.prototype.doSetBlockAttribute = function (attribute, block, val) {
rcvr = this.blockReceiver(),
ide = rcvr.parentThatIsA(IDE_Morph),
types = ['command', 'reporter', 'predicate'],
count = 1,
oldSpec,
expr,
def,
@ -5672,7 +5671,7 @@ Process.prototype.doSetBlockAttribute = function (attribute, block, val) {
def.setBlockLabel(val);
break;
case 'definition':
this.assertType(val, 'command');
this.assertType(val, types);
def.setBlockDefinition(val);
break;
case 'category':
@ -5726,8 +5725,7 @@ Process.prototype.doSetBlockAttribute = function (attribute, block, val) {
// make sure the spec is unique
while (rcvr.doubleDefinitionsFor(def).length > 0) {
count += 1;
def.spec += (' (' + count + ')');
def.spec += (' (2)');
}
// update all block instances:
@ -5752,6 +5750,38 @@ Process.prototype.doSetBlockAttribute = function (attribute, block, val) {
ide.recordUnsavedChanges();
};
Process.prototype.reportDefineBlock = function (label, context) {
// highly experimental & under construction
var rcvr = this.blockReceiver(),
ide = rcvr.parentThatIsA(IDE_Morph),
def;
this.assertType(label, 'text');
if (label === '') {return ''; }
this.assertType(context, ['command', 'reporter', 'predicate']);
// make a new custom block definition
def = new CustomBlockDefinition('BYOB'); // haha!
def.type = this.reportTypeOf(context);
def.category = 'other';
def.isGlobal = true;
def.setBlockDefinition(context);
def.setBlockLabel(label);
ide.stage.globalBlocks.push(def);
// make sure the spec is unique
while (rcvr.doubleDefinitionsFor(def).length > 0) {
def.spec += (' (2)');
}
// update the IDE
ide.flushPaletteCache();
ide.categories.refreshEmpty();
ide.refreshPalette();
ide.recordUnsavedChanges();
return def.blockInstance().reify();
};
Process.prototype.reportAttributeOf = function (attribute, name) {
// hyper-dyadic
// note: specifying strings in the left input only accesses