parent
c264001ee0
commit
399883d8ba
@ -0,0 +1,143 @@
|
||||
//! 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
|
Loading…
Reference in new issue