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.
148 lines
3.8 KiB
148 lines
3.8 KiB
2 years ago
|
//! Arithmetic operations: add, subtract, etc.
|
||
|
|
||
|
use crate::prelude::*;
|
||
|
use crate::tile::prelude::*;
|
||
|
|
||
|
macro_rules! binary_op {
|
||
|
() => {
|
||
|
fn update<'b>(&'b mut self, mut context: UpdateContext<'b>) {
|
||
|
if let Some(mut signal) = context.take_signal() {
|
||
|
if signal.len() >= 2 {
|
||
|
let first = signal.pop().unwrap_or_else(|| unreachable!());
|
||
|
let second = signal.pop().unwrap_or_else(|| unreachable!());
|
||
|
|
||
|
if let Some(res) = self.binary_op(second, first) {
|
||
|
signal.push(res);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Adds two values together: `[..., a, b] -> [..., a+b]`
|
||
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||
|
pub struct Add;
|
||
|
|
||
|
impl Add {
|
||
|
fn binary_op(&self, left: Value, right: Value) -> Option<Value> {
|
||
|
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
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// 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<Value> {
|
||
|
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
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Tile for Sub {
|
||
|
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;
|
||
|
|
||
|
impl Mul {
|
||
|
fn binary_op(&self, left: Value, right: Value) -> Option<Value> {
|
||
|
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
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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<Value> {
|
||
|
use Value::*;
|
||
|
|
||
|
match (left, right) {
|
||
|
(Number(x), Number(y)) => Some(Number(x / y)),
|
||
|
_ => None
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Tile for Div {
|
||
|
binary_op!();
|
||
|
|
||
|
fn draw_simple(&self, ctx: DrawContext) -> TextChar {
|
||
|
TextChar::from_state('\u{2298}', ctx.state) // CIRCLED DIVISION SLASH
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Computes the modulo of two values: `[..., a, b] -> [..., a%b]`
|
||
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||
|
pub struct Mod;
|
||
|
|
||
|
impl Mod {
|
||
|
fn binary_op(&self, left: Value, right: Value) -> Option<Value> {
|
||
|
use Value::*;
|
||
|
|
||
|
match (left, right) {
|
||
|
(Number(x), Number(y)) => Some(Number(x % y)),
|
||
|
_ => None
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Tile for Mod {
|
||
|
binary_op!();
|
||
|
|
||
|
fn draw_simple(&self, ctx: DrawContext) -> TextChar {
|
||
|
TextChar::from_state('\u{2299}', ctx.state) // CIRCLED DOT OPERATOR
|
||
|
}
|
||
|
}
|