use std::collections::HashMap; use std::convert::TryInto; use std::sync::mpsc::{SyncSender, Receiver}; use crate::actor::{Value, Type, Actorful, Slot}; use crate::number::Number; use crate::world::World; #[derive(Clone)] pub struct Constant { pub r#type: Type, pub value: Value, } impl Actorful for Constant { fn inputs(&self) -> Vec { vec![] } fn outputs(&self) -> Vec { vec![Slot { name: "Value".to_string(), r#type: self.r#type.clone() }] } fn launch(&self, _input_channels: HashMap>, output_channels: HashMap>, _world: &mut World) -> Box { let value = self.value.clone(); Box::new(move || { loop { let _ = output_channels["Value"].try_send(value.clone()); } }) } fn boxed_clone(&self) -> Box { Box::new(self.clone()) } } #[derive(Clone)] pub struct Add; impl Actorful for Add { fn inputs(&self) -> Vec { vec![ Slot { name: "N1".to_string(), r#type: Type::AnyNumber }, Slot { name: "N2".to_string(), r#type: Type::AnyNumber }, ] } fn outputs(&self) -> Vec { vec![Slot { name: "Result".to_string(), r#type: Type::AnyNumber }] } fn launch(&self, mut input_channels: HashMap>, output_channels: HashMap>, _world: &mut World) -> Box { let n1 = input_channels.remove("N1").unwrap(); let n2 = input_channels.remove("N2").unwrap(); Box::new(move || { for (n1, n2) in n1.iter().zip(n2.iter()) { if let (Value::Number(n1), Value::Number(n2)) = (n1, n2) { let _ = output_channels["Result"].try_send(Value::Number(n1 + n2)); } } }) } fn boxed_clone(&self) -> Box { Box::new(self.clone()) } } #[derive(Clone)] pub struct Multiply; impl Actorful for Multiply { fn inputs(&self) -> Vec { vec![ Slot { name: "N1".to_string(), r#type: Type::AnyNumber }, Slot { name: "N2".to_string(), r#type: Type::AnyNumber }, ] } fn outputs(&self) -> Vec { vec![Slot { name: "Result".to_string(), r#type: Type::AnyNumber }] } fn launch(&self, mut input_channels: HashMap>, output_channels: HashMap>, _world: &mut World) -> Box { let n1 = input_channels.remove("N1").unwrap(); let n2 = input_channels.remove("N2").unwrap(); Box::new(move || { for (n1, n2) in n1.iter().zip(n2.iter()) { if let (Value::Number(n1), Value::Number(n2)) = (n1, n2) { let _ = output_channels["Result"].try_send(Value::Number(n1 * n2)); } } }) } fn boxed_clone(&self) -> Box { Box::new(self.clone()) } } #[derive(Clone)] pub struct RepeatValue { pub r#type: Type, } impl Actorful for RepeatValue { fn inputs(&self) -> Vec { let nonnegative_integer = Type::NumberInRange { min: Some(Number::from(0)), max: None, }; vec![ Slot { name: "Value".to_string(), r#type: self.r#type.clone() }, Slot { name: "Count".to_string(), r#type: nonnegative_integer }, ] } fn outputs(&self) -> Vec { vec![Slot { name: "List".to_string(), r#type: Type::List { contents: Box::new(self.r#type.clone()) } }] } fn launch(&self, mut input_channels: HashMap>, output_channels: HashMap>, _world: &mut World) -> Box { let value = input_channels.remove("Value").unwrap(); let count = input_channels.remove("Count").unwrap(); Box::new(move || { for (value, count) in value.iter().zip(count.iter()) { if let Value::Number(count) = count { let count: usize = count.try_into().unwrap(); let vec = vec![value; count]; let _ = output_channels["List"].try_send(Value::List(vec)); } } }) } fn boxed_clone(&self) -> Box { Box::new(self.clone()) } } #[derive(Clone)] pub struct SetListItem { pub r#type: Type, } impl Actorful for SetListItem { fn inputs(&self) -> Vec { let nonnegative_integer = Type::NumberInRange { min: Some(Number::from(0)), max: None, }; vec![ Slot { name: "List".to_string(), r#type: Type::List { contents: Box::new(self.r#type.clone()) } }, Slot { name: "Index".to_string(), r#type: nonnegative_integer }, Slot { name: "Value".to_string(), r#type: self.r#type.clone() }, ] } fn outputs(&self) -> Vec { vec![Slot { name: "List".to_string(), r#type: Type::List { contents: Box::new(self.r#type.clone()) } }] } fn launch(&self, mut input_channels: HashMap>, output_channels: HashMap>, _world: &mut World) -> Box { let list = input_channels.remove("List").unwrap(); let index = input_channels.remove("Index").unwrap(); let value = input_channels.remove("Value").unwrap(); Box::new(move || { for ((list, index), value) in list.iter().zip(index.iter()).zip(value.iter()) { if let (Value::List(mut list), Value::Number(index)) = (list, index) { let index: usize = index.try_into().unwrap(); list[index] = value; let _ = output_channels["List"].try_send(Value::List(list)); } } }) } fn boxed_clone(&self) -> Box { Box::new(self.clone()) } } #[derive(Clone)] pub struct DeconstructRecord { pub record_type: Type, } impl Actorful for DeconstructRecord { fn inputs(&self) -> Vec { vec![Slot { name: "Record".to_string(), r#type: self.record_type.clone() }] } fn outputs(&self) -> Vec { if let Type::Record { name: _, fields } = &self.record_type { fields.clone() } else { panic!("bruh that's the wrong goddamn type") } } fn launch(&self, mut input_channels: HashMap>, output_channels: HashMap>, _world: &mut World) -> Box { let record = input_channels.remove("Record").unwrap(); Box::new(move || { for record in record.iter() { if let Value::Record(fields) = record { for (label, value) in fields { let _ = output_channels[&label].try_send(value); } } } }) } fn boxed_clone(&self) -> Box { Box::new(self.clone()) } }