-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathregistry.rs
More file actions
126 lines (109 loc) · 3.35 KB
/
Copy pathregistry.rs
File metadata and controls
126 lines (109 loc) · 3.35 KB
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
126
//! Runtime handler registry and callable function signatures.
use crate::handler::argument::{Argument, ParameterNode, Thunk};
use crate::runtime::execution::value_store::ValueStore;
use crate::runtime::functions::ALL_FUNCTION_SETS;
use crate::types::signal::Signal;
use std::collections::HashMap;
/// Handler function type.
/// - For eager params, the executor will already convert them to Argument::Eval(Value).
/// - For lazy params, the executor will pass Argument::Thunk(thunk).
/// - If a handler wants to execute a lazy arg, it calls run(thunk).
pub type ThunkRunner<'runner> = dyn FnMut(&Thunk, &mut ValueStore) -> Signal + 'runner;
pub type HandlerFn = for<'runner> fn(
args: &[Argument],
ctx: &mut ValueStore,
run: &mut ThunkRunner<'runner>,
) -> Signal;
#[derive(Clone, Copy)]
pub enum ParamSpec {
/// All parameters are evaluated eagerly.
AllEager(u8),
/// Per-parameter evaluation mode.
Explicit(&'static [ParameterNode]),
}
impl ParamSpec {
pub fn mode_at(self, index: usize) -> ParameterNode {
match self {
ParamSpec::AllEager(_) => ParameterNode::Eager,
ParamSpec::Explicit(modes) => modes.get(index).copied().unwrap_or(ParameterNode::Eager),
}
}
}
#[derive(Clone, Copy)]
pub struct HandlerFunctionEntry {
/// Callable implementation.
pub handler: HandlerFn,
/// Evaluation strategy for the handler parameters.
pub param_spec: ParamSpec,
}
impl HandlerFunctionEntry {
pub const fn eager(handler: HandlerFn, param_count: u8) -> Self {
Self {
handler,
param_spec: ParamSpec::AllEager(param_count),
}
}
pub const fn modes(handler: HandlerFn, param_modes: &'static [ParameterNode]) -> Self {
Self {
handler,
param_spec: ParamSpec::Explicit(param_modes),
}
}
pub fn param_mode(&self, index: usize) -> ParameterNode {
self.param_spec.mode_at(index)
}
}
#[derive(Clone, Copy)]
pub struct FunctionRegistration {
pub id: &'static str,
pub entry: HandlerFunctionEntry,
}
impl FunctionRegistration {
pub const fn eager(id: &'static str, handler: HandlerFn, param_count: u8) -> Self {
Self {
id,
entry: HandlerFunctionEntry::eager(handler, param_count),
}
}
pub const fn modes(
id: &'static str,
handler: HandlerFn,
param_modes: &'static [ParameterNode],
) -> Self {
Self {
id,
entry: HandlerFunctionEntry::modes(handler, param_modes),
}
}
}
/// Holds all registered handlers.
pub struct FunctionStore {
functions: HashMap<&'static str, HandlerFunctionEntry>,
}
impl Default for FunctionStore {
fn default() -> Self {
let mut store = Self::new();
for set in ALL_FUNCTION_SETS {
store.populate(set);
}
store
}
}
impl FunctionStore {
/// Create a new, empty store.
pub fn new() -> Self {
FunctionStore {
functions: HashMap::new(),
}
}
/// Look up a handler by its ID.
pub fn get(&self, id: &str) -> Option<&HandlerFunctionEntry> {
self.functions.get(id)
}
/// Register a group of handlers.
pub fn populate(&mut self, regs: &[FunctionRegistration]) {
for reg in regs {
self.functions.insert(reg.id, reg.entry);
}
}
}