Skip to content

Implementation of alternative syntax for conditional blocks, loops and jump tables #2

@wmysterio

Description

@wmysterio

⚠️ The syntax is an experiment and there is no guarantee that it will be added in the final build.

The essence of the introduction of the new syntax

Currently, the following code is available to emulate conditions for Sanny Builder:

and( PlayerActor.is_dead(), delegate { // THEN-END
    // then...
    wait( 0 );
} );

or( PlayerActor.is_dead(), delegate { // THEN-ELSE-END
    // then...
    wait( 0 );
}, delegate {
    // else...
    wait( 1000 );
} );

For trained C# programmers, this code is not a problem. But for beginners, it can be intimidating and uncomfortable. Alternatively, I've temporarily implemented property based syntax.

New syntax

The Script class has new properties: AND and OR. The list of conditions is written inside square brackets, as in a regular array. Further along the chain, another property is proposed (THEN). Inside the square brackets, you need to write methods that will be executed if the condition is true. Further down the chain, the ELSE property and the END method are proposed. The END method ends the chain, and for ELSE, in square brackets, you need to write the methods that will be executed if the condition is not met. Further along the chain, the END method is proposed, the essence of which I have already described. At the moment, the code at the beginning of the post can be written like this:

AND[  PlayerActor.is_dead()  ].THEN[
    // then...
    wait( 0 ),
    wait( 1 )
].END();

OR[   PlayerActor.is_dead()  ].THEN[
    // then...
    wait( 0 ),
    wait( 1 )
].ELSE[
    // else...
    wait( 1000 ),
    wait( 2000 )
].END();

Pros of the new syntax

  1. Lack of anonymous methods;
  2. Beginner friendly;
  3. Nested conditions are easier to perceive with the eyes;
  4. The length of the code has not changed significantly;
  5. Since these blocks are implemented in classes, they can be supplemented and changed for convenience. For example, adding an event to terminate:
AND[  PlayerActor.is_dead()  ].JumpIfTrue += LABEL_METHOD;
AND[  PlayerActor.is_dead()  ].JumpIfFalse += LABEL_METHOD;
AND[  PlayerActor.is_dead()  ].GosubIfFalse += LABEL_METHOD;

Cons of the new syntax

  1. In order to use commands in a block, it must return a special type, which can potentially slow down execution speed:
void wait( AnyInt duration ) { /* ... */ } // before
IBlock wait( AnyInt duration ) { /* ... */ return Blocks.Block.Empty; } // after
  1. The presence of this type makes it necessary to additionally implement the IBlock interface in order to preserve the ability to call methods of entities along the chain:
AND[  PlayerActor.is_dead()  ].THEN[
    PlayerActor.set_coorditates( .0, .0,  .0 ) // FAIL
].END();
// --- ---
public class Actor : /*...*/ , IBlock { /* ... */

AND[  PlayerActor.is_dead()  ].THEN[
    PlayerActor.set_coorditates( .0, .0,  .0 ) // GOOD
].END();
  1. The implementation of the interface will make it possible to pass a reference to an object as a command, which i would like to avoid;
AND[  PlayerActor.is_dead()  ].THEN[
       PlayerActor, PlayerChar, Stat, Clock // WTF?
].END()
  1. Termination events cannot be used inside other conditions. Events implicit return type void and cannot be converted to IBlock dynamically:
AND[  PlayerActor.is_dead()  ].JumpIfTrue += LABEL_METHOD; // GOOD

AND[  PlayerActor.is_dead()  ].THEN[
    AND[  PlayerActor.is_dead()  ].JumpIfTrue += LABEL_METHOD // FAIL
].END();
  1. May break the logic of previously available tricks:
void @return() => /* ... */
and( PlayerActor.is_dead(), @return ); // GOOD
// ...
IBlock @return() { /* ... */ return Blocks.Block.Empty; }
and( PlayerActor.is_dead(), @return ); // FAIL

Other

  1. Mandatory presence of the END method at the end of the blocks. It can be used as a property, but then the root condition tree will need to be stored in a useless variable or call a useless method derived from the property. This is a requirement of the C# syntax:
AND[  PlayerActor.is_dead()  ].THEN[
    AND[  PlayerActor.is_dead()  ].THEN[
       wait( 0 )
    ].END // GOOD
].END; // FAIL

var uselessVariable = AND[  PlayerActor.is_dead()  ].THEN[ wait( 0 ) ].END; // GOOD
// OR
AND[  PlayerActor.is_dead()  ].THEN[ wait( 0 ) ].END.ToString(); // GOOD
  1. Mandatory use of the symbol , instead of ;. This can be confusing for those who are already used to completing methods normally;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions