Enums from Pins
Before this: Option and Result
Next steps: Game Enums
Pins carry numbers, and an enum without data is a number underneath. This
lesson turns a count of button presses into an enum with FromInt, and then
passes an enum from one chip to another over a wire.
Contents
chip2 "Counter"
chip "Dimmer"
button Held -> chip2 pressed
chip2 presses -> chip presses
chip brightness -> light Brightness
chip label -> decal Text
switch Enabled -> light Enabled
Code
enum Mode { Off, Dim, Bright }
@left in presses: int
let mode = Mode.FromInt(presses % 3)
@right out brightness = match mode {
Off => 0.0,
Dim => 20.0,
Bright => 100.0,
}
@right out label = match mode {
Off => "Off",
Dim => "Dim",
Bright => "Bright",
}
Mode.FromInt(n) gives the variant whose number is n: 0 is Off, 1 is
Dim, 2 is Bright, in the order they are declared. presses % 3 keeps the
number in that range, so each press moves to the next mode and the fourth
press comes back to Off.
After four presses, which mode is the light in? After nine?
Run
-
Compile the chip and paste it in-game. Place a Button, a Point Light, a Switch and a brick with a Text Decal.
-
Paste a counter chip too, the press counter from Remembering Values with its count on a pin:
@left in pressed: exec var count: int = 0 @right out presses = count.Value on pressed { count += 1 } -
Wire the Button’s Held to the counter’s
pressedand the counter’spressesto the dimmer’spresses. Wirebrightnessto the Point Light’s Brightness, andlabelto the Text Decal’s Text. Wire the Switch’s Enabled to the light’s Enabled and flip it on. -
Press the button. The light steps dim, bright, off, and the sign names each mode.
Under the Hood
Open the dimmer chip. FromInt has no gate. The Modulo for
presses % 3 is the mode. Its output is the variant’s number, and a Mode
is that number.
The two matches share three Equal gates, one per variant, and each
has three Selects of its own. Matching the same value twice costs only
the Selects.
Enum pins
An enum without data can be a pin. It travels as its number, and on the other side it is the enum again. Here one chip works out the mode, and a second chip shows it:
enum Mode { Off, Dim, Bright }
@left in presses: int
@right out mode: Mode = Mode.FromInt(presses % 3)
enum Mode { Off, Dim, Bright }
@left in mode: Mode
@right out label = match mode {
Off => "Off",
Dim => "Dim",
Bright => "Bright",
}
Paste both, wire the counter’s presses to the first chip’s presses, the
first chip’s mode to the second chip’s mode, and the second’s label to
a sign. The wire between them is an int.
A variant with data cannot cross a pin, since a pin carries one wire and the data needs more:
enum Mode { Off, Dim(float), Bright }
@left in mode: Mode
@right out label = match mode {
Off => "Off",
Dim(level) => "Dim",
Bright => "Bright",
}
Error: [WS049] `mode` holds an enum value (`Mode`), so it can't cross this port: an enum is a tag plus a slot per payload field and a pin carries a single wire. Only a top-level `in`/`out` port of an enum with no payloads (a built-in game enum included) carries one, as its tag. Pass it to a `mod`, pass a chip a `*Mode` (which wires each part), or pass the tag and payload as plain values (`.Discriminant`, a `match` result) and build the enum inside
Modify
- Replace the Switch with the mode itself: add
@right out lit = !(mode is Mode.Off)and wire it to the light’s Enabled. - Add a fourth mode,
Medium, betweenDimandBright. Bothmatches stop compiling until they have aMediumarm, and% 3must become% 4. - Take out the
% 3. After the third press, the number matches no variant. Watch what the light and the sign do then.
Make
Make a two-chip fan control. The first chip reads two Switches as a
number from 0 to 3 (the first switch counts 1 and the second counts 2, so
a + b * 2), and sends a Speed enum out of a pin. The second chip takes the Speed and sets a light’s brightness and
a sign.
chip "Switches"
chip2 "Fan"
switch1 Enabled -> chip a
switch2 Enabled -> chip b
chip speed -> chip2 speed
chip2 brightness -> light Brightness
chip2 label -> decal Text
switch3 Enabled -> light Enabled
Good to Know
- A number that matches no variant makes a
matchwith no_arm fall through to a default value: 0 for a number, empty text for a string. Keep the number in range, as% 3does, or end thematchwith a_arm, which catches a number no variant has. - The two chips are compiled separately, so nothing checks that they agree.
If one lists
DimbeforeOff, the wire still carries 0, 1 or 2, and the second chip reads the wrong mode. Declare the enum the same way in both.
See Enums at ports and Enum and int conversion.
Next: Game Enums.