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
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
|