You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
3.6 KiB

//! Basic stack operations: push a value, pop a value, swap, etc.
use crate::prelude::*;
use crate::tile::prelude::*;
/// Pushes a value on the stack, then lets the signal through
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Push {
value: Value
}
impl Push {
pub fn new(value: Value) -> Self {
Self {
value
}
}
}
impl Default for Push {
fn default() -> Self {
Self::new(Value::Number(0.0))
}
}
impl Tile for Push {
fn update<'b>(&'b mut self, mut context: UpdateContext<'b>) {
if let Some(mut signal) = context.take_signal() {
signal.push(self.value.clone());
if let Some(coords) = context.offset(signal.direction().into_offset()) {
context.send(coords, signal.direction(), signal).unwrap_or_else(|_| unreachable!());
}
}
if context.state() != State::Idle {
context.next_state();
}
}
fn draw_simple(&self, ctx: DrawContext) -> TextChar {
TextChar::from_state('p', ctx.state)
}
}
/// Pops `n` values from the top of the stack, then lets the signal through
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Pop {
amount: usize,
}
impl Pop {
pub fn new(amount: usize) -> Self {
Self {
amount
}
}
}
impl Default for Pop {
fn default() -> Self {
Self::new(1)
}
}
impl Tile for Pop {
fn update<'b>(&'b mut self, mut context: UpdateContext<'b>) {
if let Some(mut signal) = context.take_signal() {
for _ in 0..self.amount {
let _ = signal.pop();
}
if let Some(coords) = context.offset(signal.direction().into_offset()) {
context.send(coords, signal.direction(), signal).unwrap_or_else(|_| unreachable!());
}
}
if context.state() != State::Idle {
context.next_state();
}
}
fn draw_simple(&self, ctx: DrawContext) -> TextChar {
if self.amount == 1 {
TextChar::from_state('P', ctx.state)
} else {
TextChar::from_state(ctx.blink.scroll(&format!("PPP{}", self.amount)), ctx.state)
}
}
}
/// Reverses the order of the top `n` values from the stack, then lets the signal through
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Swap {
amount: usize,
}
impl Swap {
pub fn new(amount: usize) -> Self {
Self {
amount
}
}
}
impl Default for Swap {
fn default() -> Self {
Self::new(2)
}
}
impl Tile for Swap {
fn update<'b>(&'b mut self, mut context: UpdateContext<'b>) {
if let Some(mut signal) = context.take_signal() {
let len = signal.stack().len();
let last_elements = if self.amount > len {
&mut signal.stack_mut()[..]
} else {
&mut signal.stack_mut()[(len - self.amount)..len]
};
last_elements.reverse();
if let Some(coords) = context.offset(signal.direction().into_offset()) {
context.send(coords, signal.direction(), signal).unwrap_or_else(|_| unreachable!());
}
}
if context.state() != State::Idle {
context.next_state();
}
}
fn draw_simple(&self, ctx: DrawContext) -> TextChar {
if self.amount == 2 {
TextChar::from_state('s', ctx.state)
} else {
TextChar::from_state(ctx.blink.scroll(&format!("sss{}", self.amount)), ctx.state)
}
}
}
// TODO: SwapN, RotateLeft, RotateRight, RotateLeftN, RotateRightN