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::BTreeMap;
use lexpr::Value;
use crate::{
graph::{
NodeId,
ShaderGraph,
},
lisp::Val,
};
pub type FnDef = (Vec<String>, Vec<Value>);
#[derive(Debug)]
pub struct Scope<T> {
items: Vec<BTreeMap<String, T>>,
}
impl<T> Scope<T> {
pub fn new() -> Self {
Scope {
items: vec![BTreeMap::new()],
}
}
pub fn get(&self, name: &str) -> Result<&T, String> {
for item in self.items.iter().rev() {
if let Some(item) = item.get(name) {
return Ok(item);
}
}
Err(format!("Item `{}` is not defined", name))
}
pub fn set(&mut self, name: String, item: T) {
self.items.last_mut().unwrap().insert(name, item);
}
pub fn enter_scope(&mut self) { self.items.push(BTreeMap::new()) }
pub fn exit_scope(&mut self) -> BTreeMap<String, T> {
self.items.pop().unwrap()
}
}
pub type ExternalFn =
Box<dyn Fn(&mut ShaderGraph, &[NodeId]) -> Result<NodeId, String>>;
pub type External = BTreeMap<String, ExternalFn>;
pub struct Env {
vars: Scope<Val>,
functions: Scope<FnDef>,
shaders: BTreeMap<String, String>,
external: External,
}
impl std::fmt::Debug for Env {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Env")
.field("vars", &self.vars)
.field("functions", &self.functions)
.field("shaders", &self.shaders.keys().collect::<Vec<&String>>())
.field("external", &self.external.keys().collect::<Vec<&String>>())
.finish()
}
}
impl Env {
pub fn new(shaders: BTreeMap<String, String>, external: External) -> Env {
Env {
vars: Scope::new(),
functions: Scope::new(),
shaders,
external,
}
}
pub fn get(&self, name: &str) -> Result<&Val, String> {
self.vars.get(name)
}
pub fn set(&mut self, name: String, item: Val) { self.vars.set(name, item) }
pub fn get_fn(&self, name: &str) -> Result<&FnDef, String> {
self.functions.get(name)
}
pub fn set_fn(&mut self, name: String, item: FnDef) {
self.functions.set(name, item)
}
pub fn enter_scope(&mut self) {
self.vars.enter_scope();
self.functions.enter_scope();
}
pub fn exit_scope(&mut self) {
self.vars.exit_scope();
self.functions.exit_scope();
}
pub fn shader(&self, name: &str) -> Result<&String, String> {
self.shaders.get(name).ok_or(format!(
"Could not load shader `{}`, it is not defined",
name
))
}
pub fn external(&self, name: &str) -> Result<&ExternalFn, String> {
self.external.get(name).ok_or(format!(
"Could not load external function `{}`, it is not defined",
name
))
}
}