aboutsummaryrefslogtreecommitdiff
path: root/src/basic_actors.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic_actors.rs')
-rw-r--r--src/basic_actors.rs136
1 files changed, 136 insertions, 0 deletions
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<Slot> {
+ vec![]
+ }
+
+ fn outputs(&self) -> Vec<Slot> {
+ vec![Slot { name: "Value".to_string(), r#type: self.r#type.clone() }]
+ }
+
+ fn launch(&self, _input_channels: HashMap<String, Receiver<Value>>, output_channels: HashMap<String, Sender<Value>>, _world: &mut World) {
+ loop {
+ output_channels["Value"].send(self.value.clone()).unwrap()
+ }
+ }
+
+ fn boxed_clone(&self) -> Box<dyn Actorful + Send> {
+ Box::new(self.clone())
+ }
+}
+
+#[derive(Clone)]
+pub struct Add;
+
+impl Actorful for Add {
+ fn inputs(&self) -> Vec<Slot> {
+ vec![
+ Slot { name: "N1".to_string(), r#type: Type::AnyNumber },
+ Slot { name: "N2".to_string(), r#type: Type::AnyNumber },
+ ]
+ }
+
+ fn outputs(&self) -> Vec<Slot> {
+ vec![Slot { name: "Result".to_string(), r#type: Type::AnyNumber }]
+ }
+
+ fn launch(&self, mut input_channels: HashMap<String, Receiver<Value>>, output_channels: HashMap<String, Sender<Value>>, _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<dyn Actorful + Send> {
+ Box::new(self.clone())
+ }
+}
+
+#[derive(Clone)]
+pub struct RepeatValue {
+ pub(crate) r#type: Type,
+}
+
+impl Actorful for RepeatValue {
+ fn inputs(&self) -> Vec<Slot> {
+ 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<Slot> {
+ vec![Slot { name: "List".to_string(), r#type: Type::List { contents: Box::new(self.r#type.clone()) } }]
+ }
+
+ fn launch(&self, mut input_channels: HashMap<String, Receiver<Value>>, output_channels: HashMap<String, Sender<Value>>, _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<dyn Actorful + Send> {
+ Box::new(self.clone())
+ }
+}
+
+#[derive(Clone)]
+pub struct DeconstructRecord {
+ pub record_type: Type,
+}
+
+impl Actorful for DeconstructRecord {
+ fn inputs(&self) -> Vec<Slot> {
+ vec![Slot { name: "Record".to_string(), r#type: self.record_type.clone() }]
+ }
+
+ fn outputs(&self) -> Vec<Slot> {
+ 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<String, Receiver<Value>>, output_channels: HashMap<String, Sender<Value>>, _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<dyn Actorful + Send> {
+ Box::new(self.clone())
+ }
+}