From 36d5ff553a1d65d70da5251b8865d62294c929f6 Mon Sep 17 00:00:00 2001 From: Melody Horn Date: Sun, 7 Mar 2021 09:12:47 -0700 Subject: tear it all up and implement super basic actors --- src/basic_actors.rs | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 src/basic_actors.rs (limited to 'src/basic_actors.rs') diff --git a/src/basic_actors.rs b/src/basic_actors.rs new file mode 100644 index 0000000..6f514d6 --- /dev/null +++ b/src/basic_actors.rs @@ -0,0 +1,136 @@ +use std::collections::HashMap; +use std::sync::mpsc::{Sender, 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) { + loop { + output_channels["Value"].send(self.value.clone()).unwrap() + } + } + + 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) { + let n1 = input_channels.remove("N1").unwrap(); + let n2 = input_channels.remove("N2").unwrap(); + for (n1, n2) in n1.iter().zip(n2.iter()) { + if let (Value::Number(n1), Value::Number(n2)) = (n1, n2) { + output_channels["Result"].send(Value::Number(n1 + n2)).unwrap(); + } + } + } + + fn boxed_clone(&self) -> Box { + Box::new(self.clone()) + } +} + +#[derive(Clone)] +pub struct RepeatValue { + pub(crate) 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) { + let value = input_channels.remove("Value").unwrap(); + let count = input_channels.remove("Count").unwrap(); + for (value, count) in value.iter().zip(count.iter()) { + if let Value::Number(count) = count { + // TODO figure out what a smart thing to do would be here instead + // this API design is deliberately suboptimal because i'd like to not do it + let count: usize = format!("{}", count).parse().unwrap(); + let vec = vec![value; count]; + output_channels["List"].send(Value::List(vec)).unwrap(); + } + } + } + + 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) { + let record = input_channels.remove("Record").unwrap(); + for record in record.iter() { + if let Value::Record(fields) = record { + for (label, value) in fields { + output_channels[&label].send(value).unwrap(); + } + } + } + } + + fn boxed_clone(&self) -> Box { + Box::new(self.clone()) + } +} -- cgit v1.2.3