@@ -282,6 +282,110 @@ const LEOPARD_RESERVED_SPRITE_PROPERTIES = [
282282 "stamp"
283283] ;
284284
285+ enum DesirableTraits {
286+ /**
287+ * Indicates an exact boolean (true/false) value is desired.
288+ */
289+ IsBoolean ,
290+
291+ /**
292+ * Indicates a number value is desired (typeof x === 'number').
293+ * By default, this indicates it's OK to leave NaN as it is.
294+ * Other non-number values will be cast to zero, but if the
295+ * value is NaN to begin with, that will be left as-is.
296+ *
297+ * Behavior can be customized by specifying, alongside IsNumber,
298+ * IsCastToNaN or IsCastToZero.
299+ */
300+ IsNumber ,
301+
302+ /**
303+ * Indicates an index value is desired - this is a normal number,
304+ * but decremented by one compared to its value in Scratch.
305+ *
306+ * The traits for customizing IsNumber don't apply to IsIndex.
307+ */
308+ IsIndex ,
309+
310+ /**
311+ * Indicates a string value is desired (typeof x === 'string').
312+ */
313+ IsString ,
314+
315+ /**
316+ * Indicates a series of stack blocks is desired.
317+ */
318+ IsStack ,
319+
320+ /**
321+ * Indicates that if a value can't be converted to a number
322+ * (according to `toNumber(expr, true)` rules), NaN should be
323+ * returned. NaN itself is also returned as NaN.
324+ *
325+ * May only be specified alongside IsNumber.
326+ */
327+ IsCastToNaN ,
328+
329+ /**
330+ * Indicates that if a value can't be converted to a number,
331+ * or if the value is NaN itself, zero shuold be returned.
332+ *
333+ * May only be specifeid alongside IsNumber.
334+ */
335+ IsCastToZero
336+ }
337+
338+ enum SatisfyingTraits {
339+ /**
340+ * Indicates an exact boolean (true/false) value is satisfied.
341+ */
342+ IsBoolean ,
343+
344+ /**
345+ * Indicates a number value is satisfied (typeof x === 'number').
346+ * By default, this implies the number value may be NaN, but this
347+ * can be ruled out by specifying, alongside IsNumber, IsNotNaN.
348+ */
349+ IsNumber ,
350+
351+ /**
352+ * Indicates an index is satisfied. Within the definition for a
353+ * particular reporter, this means the reporter already took care
354+ * of decrementing its numeric return value by one.
355+ */
356+ IsIndex ,
357+
358+ /**
359+ * Indicates a string value is satisfied (typeof x === 'string').
360+ */
361+ IsString ,
362+
363+ /**
364+ * Indicates that the satisfied number value isn't NaN - i.e,
365+ * it's a non-NaN number.
366+ *
367+ * May only be specified alongside IsNumber.
368+ */
369+ IsNotNaN
370+ }
371+
372+ type DesirableTraitCombo =
373+ | [ ]
374+ | [ DesirableTraits . IsBoolean ]
375+ | [ DesirableTraits . IsNumber ]
376+ | [ DesirableTraits . IsNumber , DesirableTraits . IsCastToNaN ]
377+ | [ DesirableTraits . IsNumber , DesirableTraits . IsCastToZero ]
378+ | [ DesirableTraits . IsIndex ]
379+ | [ DesirableTraits . IsStack ]
380+ | [ DesirableTraits . IsString ] ;
381+
382+ type SatisfyingTraitCombo =
383+ | [ ]
384+ | [ SatisfyingTraits . IsBoolean ]
385+ | [ SatisfyingTraits . IsNumber ]
386+ | [ SatisfyingTraits . IsNumber , SatisfyingTraits . IsNotNaN ]
387+ | [ SatisfyingTraits . IsString ] ;
388+
285389/**
286390 * Input shapes are the basic attribute controlling which of a set of syntaxes
287391 * is returned for any given block (or primitive value). Provide an input shape
@@ -686,7 +790,7 @@ export default function toLeopard(
686790 }
687791 }
688792
689- function blockToJS ( block : Block , desiredInputShape ?: InputShape ) : string {
793+ function blockToJS ( block : Block , desiredInputShape ?: InputShape , desiredTraits : DesirableTraitCombo = [ ] ) : string {
690794 const warp =
691795 script && script . hat && script . hat . opcode === OpCode . procedures_definition && script . hat . inputs . WARP . value ;
692796
@@ -715,6 +819,7 @@ export default function toLeopard(
715819 const stage = "this" + ( target . isStage ? "" : ".stage" ) ;
716820
717821 let satisfiesInputShape : InputShape ;
822+ let satisfiesTraits : SatisfyingTraitCombo = [ ] ;
718823 let blockSource : string ;
719824
720825 makeBlockSource: switch ( block . opcode ) {
@@ -2494,31 +2599,73 @@ export default function toLeopard(
24942599 }
24952600 }
24962601
2497- switch ( desiredInputShape ) {
2498- case satisfiesInputShape : {
2499- return blockSource ;
2602+ if ( ! desiredTraits . length ) {
2603+ return blockSource ;
2604+ }
2605+
2606+ if ( desiredTraits [ 0 ] === DesirableTraits . IsStack ) {
2607+ return blockSource ;
2608+ }
2609+
2610+ if ( desiredTraits [ 0 ] === DesirableTraits . IsNumber ) {
2611+ if ( desiredTraits [ 1 ] === DesirableTraits . IsCastToNaN ) {
2612+ if ( satisfiesTraits . length && satisfiesTraits [ 0 ] === SatisfyingTraits . IsNumber ) {
2613+ return blockSource ;
2614+ }
2615+
2616+ return `this.toNumber(${ blockSource } , true)` ;
25002617 }
25012618
2502- case InputShape . Number : {
2619+ if ( desiredTraits [ 1 ] === DesirableTraits . IsCastToZero ) {
2620+ if (
2621+ satisfiesTraits . length &&
2622+ satisfiesTraits [ 0 ] === SatisfyingTraits . IsNumber &&
2623+ satisfiesTraits [ 1 ] === SatisfyingTraits . IsNotNaN
2624+ ) {
2625+ return blockSource ;
2626+ }
2627+
25032628 return `this.toNumber(${ blockSource } )` ;
25042629 }
25052630
2506- case InputShape . Index : {
2507- return `( ${ blockSource } ) - 1` ;
2631+ if ( satisfiesTraits . length && satisfiesTraits [ 0 ] === SatisfyingTraits . IsNumber ) {
2632+ return blockSource ;
25082633 }
25092634
2510- case InputShape . Boolean : {
2511- return `this.toBoolean(${ blockSource } )` ;
2635+ return `this.toNumber(${ blockSource } )` ;
2636+ }
2637+
2638+ if ( desiredTraits [ 0 ] === DesirableTraits . IsIndex ) {
2639+ if ( satisfiesTraits . length ) {
2640+ if ( satisfiesTraits [ 0 ] === SatisfyingTraits . IsIndex ) {
2641+ return blockSource ;
2642+ }
2643+
2644+ if ( satisfiesTraits [ 0 ] === SatisfyingTraits . IsNumber && satisfiesTraits [ 1 ] === SatisfyingTraits . IsNotNaN ) {
2645+ return `(${ blockSource } ) - 1` ;
2646+ }
25122647 }
25132648
2514- case InputShape . String : {
2515- return `this.toString(${ blockSource } )` ;
2649+ return `this.toNumber(${ blockSource } ) - 1` ;
2650+ }
2651+
2652+ if ( desiredTraits [ 0 ] === DesirableTraits . IsString ) {
2653+ if ( satisfiesTraits . length && satisfiesTraits [ 0 ] === SatisfyingTraits . IsString ) {
2654+ return blockSource ;
25162655 }
25172656
2518- default : {
2657+ return `this.toString(${ blockSource } )` ;
2658+ }
2659+
2660+ if ( desiredTraits [ 0 ] === DesirableTraits . IsBoolean ) {
2661+ if ( satisfiesTraits . length && satisfiesTraits [ 0 ] === SatisfyingTraits . IsBoolean ) {
25192662 return blockSource ;
25202663 }
2664+
2665+ return `this.toBoolean(${ blockSource } )` ;
25212666 }
2667+
2668+ return blockSource ;
25222669 }
25232670 }
25242671
0 commit comments