Connection check playbook

This document shows ways to use connection checks.

Value examples

When you are defining connection checks for inputs and outputs, usually you should think of the checks as representing types.

Inputs' checks should include every "type" they accept, and outputs' checks should include exactly what they "return".

Accept a single type

In the most basic case where you want create a block that "accepts" or "returns" one type, you need to include that type in the connection's connection check.

a value block that accepts a single type

Accept multiple types

To create a block that "accepts" multiple types, you need to include every accepted type in the input's connection check.

a value block that accepts multiple types

By convention, if an output can sometimes be accepted in multiple situations (e.g. if you allow numbers to sometimes be used as strings) the output should be more restrictive, and the input(s) should be more permissive. This convention makes sure that outputs don't connect where they're not supported.

Accept any type

To create a block that "accepts" any type, you need to set the input's connection check to null.

a value block that accepts any type

Return subtypes

To create a block that "returns" a subtype, you need to include both the type and the supertype in the output's connection check.

a value block that returns its type and its supertype

In the case of subtypes, it is okay to have multiple checks in an output check, because the block always "returns" both types.

Return parameterized types

To create a block that "returns" a parameterized type, you need to include both the parameterized version and the unparameterized version in the output's connection check.

Depending on how strict you want your block language to be, you may also want to include the type's variance(s).

a value block that returns its parameterized type and its unparameterized
type

Just like with subtypes, it is okay to have multiple checks in an output check in this case, because the block always "returns" both types.

Stack or statement examples

There are a few common ways developers define checks for previous and next connections. Usually you think of these as restricting the ordering of blocks.

Next connections should include which blocks should follow the current one, and previous connections include what the current block "is".

Keep blocks in order

To create a set of blocks that connect in a defined order, you need to include which blocks should follow the current one in the next connection check, and what the current block "is" in the previous connection check.

statement blocks that have a forced order

Allow lots of middle blocks

To create a set of ordered blocks that allow lots of middle blocks, you need to include at least one entry from the middle block's previous connection check in the middle block's next connection check. This allows the block to be followed by more of itself.

statement blocks that allow lots of middle blocks

Allow no middle blocks

To create a set of ordered blocks where the middle blocks are optional, you need to include at least one entry from both the middle block's previous connection check, and the last block's previous connection check in the first block's next connection check. This allows the first block to be followed by either a middle block, or a last block.

statement blocks that allow no middle blocks

Either-or stacks

To create a block that can only be followed by blocks from one group, or blocks from another (and not both), you need to do two things:

  1. You need to include at least one entry from both of the groups previous connection checks in the first block's next connection check.

  2. You need to define the groups' next connection checks to only include values which are in their previous connection checks (so they can only be followed by blocks of the same group).

statement blocks that can be followed by multiple of one type of block, or
multiple of another, but not both