1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
use std::collections::HashMap;
use std::sync::mpsc::{Receiver, SyncSender};
use std::thread;
use uuid::Uuid;
use crate::number::Number;
use crate::world::World;
#[derive(Clone, Hash, Copy, Eq, PartialEq)]
pub struct ActorId(Uuid);
#[derive(Clone)]
pub enum Type {
String,
Record {
name: String,
fields: Vec<Slot>
},
AnyNumber,
NumberInRange {
min: Option<Number>,
max: Option<Number>,
},
List {
contents: Box<Type>,
},
}
#[derive(Clone)]
pub enum Value {
String(String),
Record(Vec<(String, Value)>),
Number(Number),
List(Vec<Value>),
}
#[derive(Clone)]
pub struct Slot {
pub name: String,
pub r#type: Type,
}
pub trait Actorful {
fn inputs(&self) -> Vec<Slot>;
fn outputs(&self) -> Vec<Slot>;
fn launch(&self, input_channels: HashMap<String, Receiver<Value>>,
output_channels: HashMap<String, SyncSender<Value>>, world: &mut World) -> Box<dyn FnOnce() + Send>;
fn boxed_clone(&self) -> Box<dyn Actorful + Send>;
}
#[derive(Clone)]
pub enum ProducerSlotID {
Input(String),
ChildOutput(ActorId, String),
}
#[derive(Clone)]
pub enum ConsumerSlotID {
Output(String),
ChildInput(ActorId, String),
}
#[derive(Clone, Default)]
pub struct ProgrammableActor {
pub inputs: Vec<Slot>,
pub outputs: Vec<Slot>,
pub children: HashMap<ActorId, String>,
pub cables: Vec<(ProducerSlotID, ConsumerSlotID)>,
}
impl ProgrammableActor {
pub fn add_child(&mut self, actor_type: String) -> ActorId {
let id = ActorId(Uuid::new_v4());
self.children.insert(id, actor_type);
id
}
pub fn add_cable(&mut self, in_slot: ProducerSlotID, out_slot: ConsumerSlotID) {
self.cables.push((in_slot, out_slot));
}
}
impl Actorful for ProgrammableActor {
fn inputs(&self) -> Vec<Slot> {
self.inputs.clone()
}
fn outputs(&self) -> Vec<Slot> {
self.outputs.clone()
}
fn launch(&self, mut input_channels: HashMap<String, Receiver<Value>>,
mut output_channels: HashMap<String, SyncSender<Value>>, world: &mut World) -> Box<dyn FnOnce() + Send> {
let mut child_inputs = HashMap::new();
let mut child_outputs = HashMap::new();
for (&child_id, child_type) in &self.children {
let (_, my_inputs, my_outputs) = world.spawn_actor(child_type);
child_inputs.extend(my_inputs.into_iter().map(|(name, sender)| ((child_id, name), sender)));
child_outputs.extend(my_outputs.into_iter().map(|(name, receiver)| ((child_id, name), receiver)));
}
let cables = self.cables.clone();
Box::new(move || {
for (source, dest) in cables {
let source = match source {
ProducerSlotID::Input(name) => input_channels.remove(&name).unwrap(),
ProducerSlotID::ChildOutput(id, name) => child_outputs.remove(&(id, name)).unwrap()
};
let dest = match dest {
ConsumerSlotID::Output(name) => output_channels.remove(&name).unwrap(),
ConsumerSlotID::ChildInput(id, name) => child_inputs.remove(&(id, name)).unwrap()
};
thread::spawn(move || {
for val in source.iter() {
dest.send(val).unwrap()
}
});
}
})
}
fn boxed_clone(&self) -> Box<dyn Actorful + Send> {
Box::new(self.clone())
}
}
|