1use std::rc::Rc;
2
3use glium::backend::Context;
4use lexpr::Value;
5
6use crate::{
7 graph::{
8 NodeId,
9 ShaderGraph,
10 },
11 reload::ShaderDir,
12};
13
14mod env;
15mod load;
16mod val;
17
18pub use env::{
19 Env,
20 External,
21};
22pub use load::load_shaders;
23pub use val::Val;
24
25pub fn graph_from_sexp(
31 context: &Rc<Context>,
32 shader_dir: ShaderDir,
33 external: External,
34) -> Result<ShaderGraph, String> {
35 let mut graph = ShaderGraph::new(context);
36 let mut env = Env::new(shader_dir.shaders, external);
37
38 let sexp = lexpr::from_str(&format!("({})", shader_dir.lisp))
40 .map_err(|e| format!("{}", e))?;
41
42 begin(&mut graph, &mut env, &sexp)?;
43
44 Ok(graph)
45}
46
47fn into_iter(sexp: &Value) -> Result<lexpr::cons::ListIter<'_>, String> {
48 sexp.list_iter()
49 .ok_or_else(|| "Expected a form".to_string())
50}
51
52fn next_item<'a>(
53 iter: &mut lexpr::cons::ListIter<'a>,
54) -> Result<&'a Value, String> {
55 iter.next()
56 .ok_or_else(|| "Expected a non-empty form".to_string())
57}
58
59fn next_symbol<'a>(
60 iter: &mut lexpr::cons::ListIter<'a>,
61) -> Result<&'a str, String> {
62 return next_item(iter)?
63 .as_symbol()
64 .ok_or_else(|| "Expected a symbol".to_string());
65}
66
67fn iter_finish(iter: lexpr::cons::ListIter<'_>) -> Result<(), String> {
68 if !iter.is_empty() {
69 Err("Unexpected extra args while parsing form".to_string())
70 } else {
71 Ok(())
72 }
73}
74
75fn begin(
76 mut graph: &mut ShaderGraph,
77 env: &mut Env,
78 sexp: &Value,
79) -> Result<(), String> {
80 for declaration in into_iter(sexp)? {
81 declare(&mut graph, env, declaration)?;
82 }
83
84 Ok(())
85}
86
87fn declare(
88 graph: &mut ShaderGraph,
89 env: &mut Env,
90 sexp: &Value,
91) -> Result<(), String> {
92 let mut iter = into_iter(sexp)?;
93 let keyword = next_symbol(&mut iter)?;
94
95 match keyword {
96 "input" => {
97 let var = next_symbol(&mut iter)?;
98 let input = graph.add_input();
99 env.set(var.to_string(), Val::Node(input));
100 },
101 "output" => {
102 let id = next_symbol(&mut iter)?;
103 graph.mark_output(env.get(id)?.to_node()?);
104 },
105 "define" => {
106 let list = next_item(&mut iter)?;
108 let mut signature = into_iter(list)?;
109 let name = next_symbol(&mut signature)?;
110
111 let mut args = vec![];
113 for arg in signature {
114 args.push(
115 arg.as_symbol()
116 .ok_or_else(|| {
117 "Expected symbol in signature".to_string()
118 })?
119 .to_string(),
120 );
121 }
122
123 let forms: Vec<Value> = iter.map(|f| f.to_owned()).collect();
124 if forms.is_empty() {
125 return Err(format!(
126 "Definition `{}` must have at least one expression in body",
127 name
128 ));
129 }
130 env.set_fn(name.to_string(), (args, forms));
131 return Ok(());
132 },
133 "let" => {
134 let var = next_symbol(&mut iter)?;
135 let val = expr(graph, env, next_item(&mut iter)?)?;
136 env.set(var.to_string(), val);
137 },
138 "repeat" => {
139 let times = expr(graph, env, next_item(&mut iter)?)?.to_nat()?;
140 let forms: Vec<Value> = iter.map(|f| f.to_owned()).collect();
141 for _ in 0..times {
142 for form in forms.iter() {
143 declare(graph, env, form)?;
144 }
145 }
146 return Ok(());
147 },
148 other => {
149 return Err(format!(
150 "Expected a statement keyword, found `{}`",
151 other
152 ))
153 },
154 }
155
156 iter_finish(iter)
157}
158
159fn expr(
160 graph: &mut ShaderGraph,
161 env: &mut Env,
162 value: &Value,
163) -> Result<Val, String> {
164 let val = match value {
165 Value::Number(n) => {
166 if let Some(float) = n.as_f64() {
167 Val::Number(float)
168 } else {
169 return Err("unexpected number type".to_string());
170 }
171 },
172
173 Value::Bool(b) => Val::Bool(*b),
174 Value::String(_) => Val::String(value.as_str().unwrap().to_string()),
175 Value::Symbol(_) => env.get(value.as_symbol().unwrap())?.clone(),
176
177 x if x.is_list() => node(graph, env, x)?,
178
179 other => return Err(format!("unexpected value `{}`", other)),
180 };
181
182 Ok(val)
183}
184
185fn shader(
186 graph: &mut ShaderGraph,
187 env: &mut Env,
188 mut iter: lexpr::cons::ListIter<'_>,
189) -> Result<(String, u32, u32, Vec<NodeId>), String> {
190 let name = expr(graph, env, next_item(&mut iter)?)?.to_string()?;
191 let width = expr(graph, env, next_item(&mut iter)?)?.to_nat()?;
192 let height = expr(graph, env, next_item(&mut iter)?)?.to_nat()?;
193 let mut inputs = vec![];
194 for remaining in iter {
195 let node_id = expr(graph, env, remaining)?.to_node()?;
196 inputs.push(node_id);
197 }
198 Ok((name, width as u32, height as u32, inputs))
199}
200
201fn external(
202 graph: &mut ShaderGraph,
203 env: &mut Env,
204 mut iter: lexpr::cons::ListIter<'_>,
205) -> Result<(String, Vec<NodeId>), String> {
206 let name = expr(graph, env, next_item(&mut iter)?)?.to_string()?;
207 let mut inputs = vec![];
208 for remaining in iter {
209 let node_id = expr(graph, env, remaining)?.to_node()?;
210 inputs.push(node_id);
211 }
212 Ok((name, inputs))
213}
214
215fn node(
216 graph: &mut ShaderGraph,
217 env: &mut Env,
218 sexp: &Value,
219) -> Result<Val, String> {
220 let mut iter = into_iter(sexp)?;
221 let function = next_symbol(&mut iter)?;
222
223 match function {
224 "shader" => {
225 let (name, width, height, inputs) = shader(graph, env, iter)?;
226 let node_id = graph.add_shader(
227 env.shader(&name)?,
228 inputs,
229 width as u32,
230 height as u32,
231 )?;
232 Ok(Val::Node(node_id))
233 },
234 "shader-param" => {
235 let decl = into_iter(next_item(&mut iter)?)?;
238 let (name, width, height, inputs) = shader(graph, env, decl)?;
239 let mut source = env.shader(&name)?.to_string();
240
241 for form in iter {
244 source = subst(graph, env, form, source)?;
245 }
246
247 let node_id = graph.add_shader(
248 &source,
249 inputs,
250 width as u32,
251 height as u32,
252 )?;
253 Ok(Val::Node(node_id))
254 },
255 "shader-rec" => {
256 let (name, width, height, inputs) = shader(graph, env, iter)?;
257 let node_id = graph.add_rec_shader(
258 env.shader(&name)?,
259 inputs,
260 width as u32,
261 height as u32,
262 )?;
263 Ok(Val::Node(node_id))
264 },
265 "extern" => {
266 let (name, inputs) = external(graph, env, iter)?;
267 let adder = env.external(&name)?;
268 let node_id = adder(graph, &inputs).map_err(|e| {
269 format!("While adding external function `{}`: {}", name, e)
270 })?;
271 Ok(Val::Node(node_id))
272 },
273 user_defined => {
274 let mut args = vec![];
276 for arg in iter {
277 args.push(expr(graph, env, arg)?);
278 }
279
280 if let Some(val) = builtin(user_defined, &args) {
281 return val;
282 }
283
284 let (params, body) = env.get_fn(user_defined)?.clone();
286
287 if params.len() != args.len() {
289 return Err(format!(
290 "function `{}` expected {} args, but found {}",
291 user_defined,
292 params.len(),
293 args.len(),
294 ));
295 }
296
297 env.enter_scope();
301 for (name, val) in params.iter().zip(args.iter()) {
302 env.set(name.to_string(), val.to_owned())
303 }
304
305 let last = body.last().unwrap();
308 let declarations = &body[..body.len() - 1];
309 for declaration in declarations {
310 declare(graph, env, declaration)?;
311 }
312
313 let ret = expr(graph, env, last)?.to_node()?;
316 env.exit_scope();
317 Ok(Val::Node(ret))
318 },
319 }
320}
321
322fn builtin(name: &str, args: &[Val]) -> Option<Result<Val, String>> {
323 let result: fn(Vec<f64>) -> Val = match name {
324 "+" => |n| Val::Number(n.into_iter().sum()),
325 "-" => |n| {
326 let iter = n.into_iter();
327 Val::Number(iter.reduce(|a, b| a - b).unwrap_or(0.0))
328 },
329 "*" => |n| Val::Number(n.into_iter().product()),
330 "/" => |n| {
331 let iter = n.into_iter();
332 Val::Number(iter.reduce(|a, b| a / b).unwrap_or(1.0))
333 },
334 _ => {
335 return None;
336 },
337 };
338
339 let numbers = args
340 .iter()
341 .map(|v| v.to_float())
342 .collect::<Result<Vec<f64>, _>>();
343
344 let numbers = match numbers {
345 Err(e) => {
346 return Some(Err(e));
347 },
348 Ok(ok) => ok,
349 };
350
351 Some(Ok(result(numbers)))
352}
353
354fn subst(
355 graph: &mut ShaderGraph,
356 env: &mut Env,
357 form: &Value,
358 source: String,
359) -> Result<String, String> {
360 let mut subst_iter = into_iter(form)?;
361 let op = next_symbol(&mut subst_iter)?;
362
363 let (name, subst) = match op {
364 "define" => {
365 let name =
366 expr(graph, env, next_item(&mut subst_iter)?)?.to_string()?;
367 let val =
368 expr(graph, env, next_item(&mut subst_iter)?)?.to_string()?;
369 let subst = format!("#define {} {}", name, val);
370 (name, subst)
371 },
372 "ifdef" => {
373 let name =
374 expr(graph, env, next_item(&mut subst_iter)?)?.to_string()?;
375 let should_define =
376 expr(graph, env, next_item(&mut subst_iter)?)?.to_bool()?;
377 if should_define {
378 (name.clone(), format!("#define {} 1", name))
379 } else {
380 (name, String::new())
381 }
382 },
383 other => {
384 return Err(format!("Invalid param substitution type `{}`", other));
385 },
386 };
387
388 iter_finish(subst_iter)?;
389 return Ok(source.replace(&format!("<{}>", name), &subst));
390}