diff --git a/editor-solidjs/src/RightPane.module.css b/editor-solidjs/src/RightPane.module.css index c8ed5fa..d5491a1 100644 --- a/editor-solidjs/src/RightPane.module.css +++ b/editor-solidjs/src/RightPane.module.css @@ -16,6 +16,7 @@ font-size: inherit; margin: 0; color: white; + font-weight: normal; } .h3 { diff --git a/editor-solidjs/src/Tile.jsx b/editor-solidjs/src/Tile.jsx index f2d257c..cba1619 100644 --- a/editor-solidjs/src/Tile.jsx +++ b/editor-solidjs/src/Tile.jsx @@ -9,16 +9,19 @@ import Number from "./input/Number.jsx"; import Value from "./input/Value.jsx"; import Bool from "./input/Bool.jsx"; import CmpOp from "./input/CmpOp.jsx"; +import ArithOp from "./input/ArithOp.jsx"; export const COMPONENTS = new Map(); COMPONENTS.set("Signal", (props) => ); COMPONENTS.set("Direction", Direction); COMPONENTS.set("Orientation", Orientation); +COMPONENTS.set("Orientation|NotAny", (props) => Orientation({...props, not_any: true})); COMPONENTS.set("Uint", (props) => ); COMPONENTS.set("Int", Number); COMPONENTS.set("Value", Value); COMPONENTS.set("CmpOp", CmpOp); +COMPONENTS.set("ArithOp", ArithOp); export default function Tile(props) { let {full_tile, set_full_tile} = props; @@ -58,7 +61,7 @@ export default function Tile(props) { } return (<> -

Tile:

+

Tile: {tile_name()}

No tile}>
    @@ -66,10 +69,12 @@ export default function Tile(props) { {([label, type, value]) => { if (COMPONENTS.has(type)) { let setValue = bindSetValue(label, value); - return (
  1. ); + return (
  2. + {/* */} +
  3. ); } else { return (
  4. {label}: diff --git a/editor-solidjs/src/input/ArithOp.jsx b/editor-solidjs/src/input/ArithOp.jsx new file mode 100644 index 0000000..815fb27 --- /dev/null +++ b/editor-solidjs/src/input/ArithOp.jsx @@ -0,0 +1,20 @@ +import {createEffect} from "solid-js"; + +import styles from "./input.module.css"; + +export default function ArithOp(props) { + let {value, setValue} = props; + let select; + + createEffect(() => { + select.value = value(); + }); + + return (); +} diff --git a/editor-solidjs/src/input/Orientation.jsx b/editor-solidjs/src/input/Orientation.jsx index bebbf6b..24307da 100644 --- a/editor-solidjs/src/input/Orientation.jsx +++ b/editor-solidjs/src/input/Orientation.jsx @@ -11,7 +11,7 @@ export default function Orientation(props) { }); return (); diff --git a/stackline/Cargo.toml b/stackline/Cargo.toml index 5a9355a..7e9a113 100755 --- a/stackline/Cargo.toml +++ b/stackline/Cargo.toml @@ -15,6 +15,7 @@ veccell = { version = "0.4.0", features = ["serde"] } pathfinding = "3.0" colored = "2.0" serde = { version = "1", features = ["derive"] } +serde_with = "2.0.0" [dev-dependencies] criterion = { version = "0.3.5", features = ["html_reports"] } diff --git a/stackline/src/signal.rs b/stackline/src/signal.rs index 4d78d56..3d272dc 100644 --- a/stackline/src/signal.rs +++ b/stackline/src/signal.rs @@ -224,6 +224,12 @@ impl PartialEq for Signal { } } +impl Default for Signal { + fn default() -> Self { + Self::empty(Direction::default()) + } +} + /// Creates a signal with initial values in its stack. /// /// The syntax for the macro is `signal!(position, direction, [value1, value2, ...])`, where: diff --git a/stackline/tests/common/mod.rs b/stackline/tests/common/mod.rs index 0f98ad0..71df3f3 100644 --- a/stackline/tests/common/mod.rs +++ b/stackline/tests/common/mod.rs @@ -73,17 +73,17 @@ macro_rules! assert_stored { let guard = $world .get_as::(($x, $y)) .unwrap_or_else(|| panic!("Couldn't get store tile at {}:{}", $x, $y)); - let signal = guard.signal().cloned(); + let signal = guard.signal().clone(); assert!( - signal.is_some(), + !signal.is_stack_empty(), "Expected stored signal at {}:{}!\n{}", $x, $y, $world ); - signal.unwrap() + signal }}; ( $world:expr, $x:expr, $y:expr, $signal:expr ) => {{ @@ -108,7 +108,7 @@ macro_rules! assert_no_stored { let signal = guard.signal(); assert!( - signal.is_none(), + signal.is_stack_empty(), "Expected no stored signal at {}:{}!\n{}", $x, $y, diff --git a/stackline/tests/logic.rs b/stackline/tests/logic.rs index 8aa065c..7ef8bac 100644 --- a/stackline/tests/logic.rs +++ b/stackline/tests/logic.rs @@ -8,7 +8,7 @@ fn test_if() { let mut world = load_test!("tests/logic/if.json"); world.init(); - world.set_signal((0, 0), signal!([0])); + world.set_signal((0, 0), signal!([-1, 0])); run!(world, 8); @@ -18,7 +18,7 @@ fn test_if() { let mut world = load_test!("tests/logic/if.json"); world.init(); - world.set_signal((0, 0), signal!([1])); + world.set_signal((0, 0), signal!([-1, 1])); run!(world, 8); diff --git a/stackline/tests/other/prime.json b/stackline/tests/other/prime.json index 685c55e..131fe66 100644 --- a/stackline/tests/other/prime.json +++ b/stackline/tests/other/prime.json @@ -1 +1 @@ -{"panes":{"main":{"tiles":[{"cell":{"Diode":"Down"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Any"},"signal":null,"state":"Idle","updated":false},{"cell":{"Push":{"value":{"Number":1.0}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Push":{"value":{"Number":2.0}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Add":null},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Down"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":{"Stacker":{"signal":null,"orientation":"Vertical"}},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Any"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":{"Push":{"value":{"Number":2.0}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":{"Reader":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":{"Store":{"signal":null}},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Any"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":{"Reader":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":{"Resistor":{"direction":"Left","signal":null}},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Store":{"signal":{"direction":"Right","stack":[]}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Push":{"value":{"Number":2.0}}},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Any"},"signal":null,"state":"Idle","updated":false},{"cell":{"If":{"invert":false}},"signal":null,"state":"Idle","updated":false},{"cell":{"Cmp":"Gt"},"signal":null,"state":"Idle","updated":false},{"cell":{"Duplicate":{"offset":2}},"signal":null,"state":"Idle","updated":false},{"cell":{"Mul":null},"signal":null,"state":"Idle","updated":false},{"cell":{"Duplicate":{"offset":0}},"signal":null,"state":"Idle","updated":false},{"cell":{"Duplicate":{"offset":0}},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":{"Pop":{"amount":1}},"signal":null,"state":"Idle","updated":false},{"cell":{"Duplicate":{"offset":1}},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":{"Teleporter":{"coordinates":["main",3,1]}},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Duplicate":{"offset":1}},"signal":null,"state":"Idle","updated":false},{"cell":{"Mod":null},"signal":null,"state":"Idle","updated":false},{"cell":{"If":{"invert":false}},"signal":null,"state":"Idle","updated":false},{"cell":{"Push":{"value":{"Number":1.0}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Add":null},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false}],"width":11,"height":8,"position":[0,0]}},"blink_speed":{"secs":0,"nanos":250000000}} \ No newline at end of file +{"panes":{"main":{"tiles":[{"cell":{"Diode":"Down"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Any"},"signal":null,"state":"Idle","updated":false},{"cell":{"Push":{"value":{"Number":1.0}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Push":{"value":{"Number":2.0}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Arithmetic":"Add"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Down"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":{"Stacker":{"signal":null,"orientation":"Vertical"}},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Any"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":{"Push":{"value":{"Number":2.0}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":{"Reader":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":{"Store":{"signal":null}},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Any"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":{"Reader":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":{"Resistor":{"direction":"Left","signal":null}},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Store":{"signal":{"direction":"Right","stack":[]}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Push":{"value":{"Number":2.0}}},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Any"},"signal":null,"state":"Idle","updated":false},{"cell":{"If":{"invert":false}},"signal":null,"state":"Idle","updated":false},{"cell":{"Cmp":"Gt"},"signal":null,"state":"Idle","updated":false},{"cell":{"Duplicate":{"offset":2}},"signal":null,"state":"Idle","updated":false},{"cell":{"Arithmetic":"Mul"},"signal":null,"state":"Idle","updated":false},{"cell":{"Duplicate":{"offset":0}},"signal":null,"state":"Idle","updated":false},{"cell":{"Duplicate":{"offset":0}},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":{"Pop":{"amount":1}},"signal":null,"state":"Idle","updated":false},{"cell":{"Duplicate":{"offset":1}},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":{"Teleporter":{"coordinates":["main",3,1]}},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Duplicate":{"offset":1}},"signal":null,"state":"Idle","updated":false},{"cell":{"Arithmetic":"Mod"},"signal":null,"state":"Idle","updated":false},{"cell":{"If":{"invert":false}},"signal":null,"state":"Idle","updated":false},{"cell":{"Push":{"value":{"Number":1.0}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Arithmetic":"Add"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Horizontal"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false}],"width":11,"height":8,"position":[0,0]}},"blink_speed":{"secs":0,"nanos":250000000}} diff --git a/stackline/tests/storage/counter.json b/stackline/tests/storage/counter.json index 33c6a8b..db2efc5 100644 --- a/stackline/tests/storage/counter.json +++ b/stackline/tests/storage/counter.json @@ -1 +1 @@ -{"panes":{"main":{"tiles":[{"cell":{"Diode":"Down"},"signal":null,"state":"Idle","updated":false},{"cell":{"Add":null},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Push":{"value":{"Number":1.0}}},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Store":{"signal":{"direction":"Up","stack":[{"Number":0.0}]}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Reader":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false}],"width":4,"height":4,"position":[0,0]}},"blink_speed":{"secs":0,"nanos":250000000}} \ No newline at end of file +{"panes":{"main":{"tiles":[{"cell":{"Diode":"Down"},"signal":null,"state":"Idle","updated":false},{"cell":{"Arithmetic":"Add"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Push":{"value":{"Number":1.0}}},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Store":{"signal":{"direction":"Up","stack":[{"Number":0.0}]}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Reader":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false}],"width":4,"height":4,"position":[0,0]}},"blink_speed":{"secs":0,"nanos":250000000}} diff --git a/stackline/tests/storage/natural.json b/stackline/tests/storage/natural.json index 87937cd..573ba9a 100644 --- a/stackline/tests/storage/natural.json +++ b/stackline/tests/storage/natural.json @@ -1 +1 @@ -{"panes":{"main":{"tiles":[{"cell":{"Diode":"Down"},"signal":null,"state":"Idle","updated":false},{"cell":{"Add":null},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Push":{"value":{"Number":1.0}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Down"},"signal":null,"state":"Idle","updated":false},{"cell":{"Store":{"signal":{"direction":"Right","stack":[{"Number":0.0}]}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Reader":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Any"},"signal":null,"state":"Idle","updated":false},{"cell":{"Stacker":{"signal":null,"orientation":"Vertical"}},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":{"Resistor":{"direction":"Right","signal":null}},"signal":null,"state":"Idle","updated":false},{"cell":{"Reader":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Any"},"signal":null,"state":"Idle","updated":false},{"cell":{"Resistor":{"direction":"Right","signal":null}},"signal":null,"state":"Idle","updated":false},{"cell":{"Resistor":{"direction":"Down","signal":null}},"signal":null,"state":"Idle","updated":false},{"cell":{"Store":{"signal":{"direction":"Right","stack":[]}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":{"Resistor":{"direction":"Up","signal":null}},"signal":null,"state":"Idle","updated":false},{"cell":{"Resistor":{"direction":"Left","signal":null}},"signal":null,"state":"Idle","updated":false},{"cell":{"Resistor":{"direction":"Left","signal":null}},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false}],"width":5,"height":6,"position":[0,0]}},"blink_speed":{"secs":0,"nanos":250000000}} \ No newline at end of file +{"panes":{"main":{"tiles":[{"cell":{"Diode":"Down"},"signal":null,"state":"Idle","updated":false},{"cell":{"Arithmetic":"Add"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":{"Push":{"value":{"Number":1.0}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Down"},"signal":null,"state":"Idle","updated":false},{"cell":{"Store":{"signal":{"direction":"Right","stack":[{"Number":0.0}]}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Reader":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Any"},"signal":null,"state":"Idle","updated":false},{"cell":{"Stacker":{"signal":null,"orientation":"Vertical"}},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Right"},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":{"Resistor":{"direction":"Right","signal":null}},"signal":null,"state":"Idle","updated":false},{"cell":{"Reader":"Up"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Vertical"},"signal":null,"state":"Idle","updated":false},{"cell":{"Wire":"Any"},"signal":null,"state":"Idle","updated":false},{"cell":{"Resistor":{"direction":"Right","signal":null}},"signal":null,"state":"Idle","updated":false},{"cell":{"Resistor":{"direction":"Down","signal":null}},"signal":null,"state":"Idle","updated":false},{"cell":{"Store":{"signal":{"direction":"Right","stack":[]}}},"signal":null,"state":"Idle","updated":false},{"cell":{"Diode":"Left"},"signal":null,"state":"Idle","updated":false},{"cell":{"Resistor":{"direction":"Up","signal":null}},"signal":null,"state":"Idle","updated":false},{"cell":{"Resistor":{"direction":"Left","signal":null}},"signal":null,"state":"Idle","updated":false},{"cell":{"Resistor":{"direction":"Left","signal":null}},"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false},{"cell":null,"signal":null,"state":"Idle","updated":false}],"width":5,"height":6,"position":[0,0]}},"blink_speed":{"secs":0,"nanos":250000000}} diff --git a/stackline/tiles/arithmetic.rs b/stackline/tiles/arithmetic.rs index 83ffe93..5977298 100644 --- a/stackline/tiles/arithmetic.rs +++ b/stackline/tiles/arithmetic.rs @@ -28,130 +28,89 @@ macro_rules! binary_op { } } -/// Adds two values together: `[..., a, b] -> [..., a+b]` #[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct Add; +pub struct Arithmetic(ArithOp); -impl Add { - fn binary_op(&self, left: Value, right: Value) -> Option { - Some(left + right) - } -} - -impl Tile for Add { - binary_op!(); - - fn draw_simple(&self, ctx: DrawContext) -> TextChar { - TextChar::from_state('\u{2295}', ctx.state) // CIRCLED PLUS +impl Arithmetic { + pub fn new(op: ArithOp) -> Self { + Self(op) } -} -/// Subtracts two values: `[..., a, b] -> [..., a-b]` -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct Sub; - -impl Sub { fn binary_op(&self, left: Value, right: Value) -> Option { - use Value::*; - - match (left, right) { - (Number(x), Number(y)) => Some(Number(x - y)), - (String(mut x), Number(y)) => { - x.truncate(y as usize); - Some(String(x)) - } - (String(x), String(y)) => { - Some(String(x.split(&y).collect())) - } - _ => None - } + self.0.binary_op(left, right) } } -impl Tile for Sub { +impl Tile for Arithmetic { binary_op!(); fn draw_simple(&self, ctx: DrawContext) -> TextChar { - TextChar::from_state('\u{2296}', ctx.state) // CIRCLED MINUS - } -} - -/// Multiplies two values together: `[..., a, b] -> [..., a*b]` -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct Mul; + use ArithOp::*; -impl Mul { - fn binary_op(&self, left: Value, right: Value) -> Option { - use Value::*; - - match (left, right) { - (Number(x), Number(y)) => Some(Number(x * y)), - (String(x), Number(y)) => Some(String(x.repeat(y as usize))), - _ => None + match self.0 { + Add => TextChar::from_state('\u{2295}', ctx.state), // CIRCLED PLUS + Sub => TextChar::from_state('\u{2296}', ctx.state), // CIRCLED MINUS + Mul => TextChar::from_state('\u{2297}', ctx.state), // CIRCLED TIMES + Div => TextChar::from_state('\u{2298}', ctx.state), // CIRCLED DIVISION SLASH + Mod => TextChar::from_state('\u{2299}', ctx.state), // CIRCLED DOT OPERATOR } } -} - -impl Tile for Mul { - binary_op!(); - - fn draw_simple(&self, ctx: DrawContext) -> TextChar { - TextChar::from_state('\u{2297}', ctx.state) // CIRCLED TIMES - } -} - -/// Divides two values together: `[..., a, b] -> [..., a/b]` -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct Div; -impl Div { - fn binary_op(&self, left: Value, right: Value) -> Option { - use Value::*; - - match (left, right) { - (Number(x), Number(y)) => Some(Number(x / y)), - _ => None - } + fn schema(&self) -> TileSchema { + TileSchema::value("Operator", "ArithOp") } } -impl Tile for Div { - binary_op!(); - - fn draw_simple(&self, ctx: DrawContext) -> TextChar { - TextChar::from_state('\u{2298}', ctx.state) // CIRCLED DIVISION SLASH - } +#[derive(Debug, Clone, Serialize, Deserialize, Copy, PartialEq, Eq)] +pub enum ArithOp { + Add, + Sub, + Mul, + Div, + Mod } -/// Computes the modulo of two values: `[..., a, b] -> [..., a%b]` -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct Mod; - -impl Mod { +impl ArithOp { fn binary_op(&self, left: Value, right: Value) -> Option { use Value::*; - - match (left, right) { - (Number(x), Number(y)) => Some(Number(x % y)), + use ArithOp::*; + match (self, left, right) { + // == Add == + (Add, left, right) => Some(left + right), + // == Sub == + (Sub, Number(x), Number(y)) => Some(Number(x - y)), + (Sub, String(mut x), Number(y)) => { + x.truncate(y as usize); + Some(String(x)) + } + (Sub, String(x), String(y)) => { + Some(String(x.split(&y).collect())) + } + // == Mul == + (Mul, Number(x), Number(y)) => Some(Number(x * y)), + (Mul, String(x), Number(y)) => Some(String(x.repeat(y as usize))), + // == Div == + (Div, Number(x), Number(y)) => Some(Number(x / y)), + // == Mod == + (Mod, Number(x), Number(y)) => Some(Number(x % y)), + // Default _ => None } } } -impl Tile for Mod { - binary_op!(); - - fn draw_simple(&self, ctx: DrawContext) -> TextChar { - TextChar::from_state('\u{2299}', ctx.state) // CIRCLED DOT OPERATOR +impl Default for ArithOp { + fn default() -> Self { + Self::Add } } /// Compares the top two values: `[..., a, b] -> [..., a ?? b]` #[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct Cmp(Operation); +pub struct Cmp(CmpOp); #[derive(Debug, Clone, Serialize, Deserialize, Copy, PartialEq, Eq)] -pub enum Operation { +pub enum CmpOp { Eq, Neq, Gt, @@ -163,7 +122,7 @@ pub enum Operation { impl Cmp { fn binary_op(&self, left: Value, right: Value) -> Option { use Value::*; - use Operation::*; + use CmpOp::*; let res = match (self.0, left, right) { (Eq, Number(x), Number(y)) => Some(x == y), @@ -195,7 +154,7 @@ impl Tile for Cmp { binary_op!(); fn draw_simple(&self, ctx: DrawContext) -> TextChar { - use Operation::*; + use CmpOp::*; match self.0 { Eq => TextChar::from_state('\u{229c}', ctx.state), // CIRCLED EQUALS @@ -208,11 +167,11 @@ impl Tile for Cmp { } fn schema(&self) -> TileSchema { - TileSchema::value("Operation", "CmpOp") + TileSchema::value("CmpOp", "CmpOp") } } -impl Default for Operation { +impl Default for CmpOp { fn default() -> Self { Self::Eq } diff --git a/stackline/tiles/storage.rs b/stackline/tiles/storage.rs index 8dea7fb..e304a48 100644 --- a/stackline/tiles/storage.rs +++ b/stackline/tiles/storage.rs @@ -3,16 +3,23 @@ use crate::prelude::*; use crate::tile::prelude::*; +use serde_with::{serde_as, DefaultOnNull}; use veccell::VecRef; +#[serde_as] #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct Store { - signal: Option, + #[serde_as(deserialize_as = "DefaultOnNull")] + signal: Signal, } impl Store { - pub fn signal(&self) -> Option<&Signal> { - self.signal.as_ref() + pub fn signal(&self) -> &Signal { + &self.signal + } + + pub fn is_empty(&self) -> bool { + self.signal.is_stack_empty() } } @@ -25,7 +32,7 @@ impl Tile for Store { // but by delaying the write we can read from a `Store` without being order-dependent context.callback(move |pane| { if let Some(mut this) = pane.borrow_mut_as::(position) { - this.signal = Some(signal); + this.signal = signal; } }); } @@ -36,10 +43,10 @@ impl Tile for Store { } fn draw_simple(&self, ctx: DrawContext) -> TextChar { - if self.signal.is_some() { - TextChar::from_state('\u{25c9}', ctx.state) // FISHEYE - } else { + if self.is_empty() { TextChar::from_state('\u{25cb}', ctx.state) // WHITE CIRCLE + } else { + TextChar::from_state('\u{25c9}', ctx.state) // FISHEYE } } @@ -80,7 +87,7 @@ impl Tile for Reader { let _: Option<()> = try { let store_position = context.offset(self.0.opposite().into_offset())?; let store = context.get(store_position).and_then(get_store)?; - let signal = store.signal.clone()?; + let signal = store.signal.clone(); drop(store); let target_position = context.offset(self.0.into_offset())?; @@ -118,7 +125,7 @@ impl Tile for StorageCount { for dir in Orientation::Any.into_directions() { if let Some(store_position) = context.offset(dir.into_offset()) { if let Some(store) = context.get(store_position).and_then(get_store) { - count += store.signal.is_some() as u8; + count += (!store.is_empty()) as u8; } } } @@ -140,9 +147,11 @@ impl Tile for StorageCount { } } +#[serde_as] #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Stacker { - signal: Option, + #[serde_as(deserialize_as = "DefaultOnNull")] + signal: Signal, /// May only be Horizontal or Vertical orientation: Orientation, } @@ -150,13 +159,17 @@ pub struct Stacker { impl Stacker { pub fn new(orientation: Orientation) -> Self { Self { - signal: None, + signal: Signal::empty(Direction::default()), orientation, } } - pub fn signal(&self) -> Option<&Signal> { - self.signal.as_ref() + pub fn signal(&self) -> &Signal { + &self.signal + } + + pub fn is_empty(&self) -> bool { + self.signal.is_stack_empty() } } @@ -171,9 +184,7 @@ impl Tile for Stacker { if let Some(mut signal) = context.take_signal() { if self.orientation.contains(signal.direction()) { // Stack the stored signal on top of the incomming signal - if let Some(ref stored) = self.signal { - signal.append(stored); - } + signal.append(&self.signal); if let Some(target_position) = context.offset(signal.direction().into_offset()) { let _ = context.send(target_position, signal.direction(), signal); @@ -184,7 +195,7 @@ impl Tile for Stacker { } } else { // Store the signal inside of ourselves - self.signal = Some(signal); + self.signal = signal; context.set_state(State::Idle); } @@ -206,7 +217,7 @@ impl Tile for Stacker { fn schema(&self) -> TileSchema { TileSchema::map() .add("signal", TileSchema::value("Signal to stack", "Signal")) - .add("orientation", TileSchema::value("Orientation", "Orientation")) + .add("orientation", TileSchema::value("Orientation", "Orientation|NotAny")) } }