1use{
2 std::{
3 cell::{RefCell, Cell},
4 collections::{BTreeMap, BTreeSet, HashMap}
5 },
6 crate::{
7 makepad_live_compiler::{
8 makepad_live_id::{
9 live_id,
10 LiveId,
11 },
12 LiveRegistry,
13 LiveError,
14 live_error_origin,
15 LiveErrorOrigin,
16 TokenSpan
17 },
18 shader_ast::*,
19 const_eval::ConstEvaluator,
20 const_gather::ConstGatherer,
21 dep_analyse::DepAnalyser,
22 ty_check::TyChecker,
23 shader_registry::ShaderRegistry
24 }
25};
26
27
28#[derive(Clone, Copy)]
29pub struct ShaderAnalyseOptions {
30 pub no_const_collapse: bool,
31 pub const_gather_active: bool
32}
33
34pub struct StructAnalyser<'a> {
35 pub struct_def: &'a StructDef,
36 pub scopes: &'a mut Scopes,
37 pub live_registry: &'a LiveRegistry,
38 pub shader_registry: &'a ShaderRegistry,
39 pub options: ShaderAnalyseOptions,
40}
41
42impl<'a> StructAnalyser<'a> {
43 fn ty_checker(&self) -> TyChecker {
44 TyChecker {
45 live_registry: self.live_registry,
46 shader_registry: self.shader_registry,
47 scopes: self.scopes,
48 }
49 }
50
51 pub fn analyse_struct(&mut self) -> Result<(), LiveError> {
52 self.scopes.push_scope();
53 self.struct_def.init_analysis();
54 for field in &self.struct_def.fields {
56 self.analyse_field_def(field) ?;
57 }
58 for fn_node_ptr in &self.struct_def.methods {
60 let fn_decl = self.shader_registry.all_fns.get(fn_node_ptr).unwrap();
61 self.analyse_method_decl(fn_decl) ?;
62 }
63 for fn_node_ptr in &self.struct_def.methods {
65 let fn_def = self.shader_registry.all_fns.get(fn_node_ptr).unwrap();
66 FnDefAnalyser {
67 live_registry: self.live_registry,
68 shader_registry: self.shader_registry,
69 closure_return_ty: None,
70 fn_def,
71 scopes: &mut self.scopes,
72 options: self.options,
73 is_inside_loop: false,
74 }
75 .analyse_fn_def() ?;
76 }
77 self.scopes.pop_scope();
78 Ok(())
79 }
80
81 fn analyse_field_def(&mut self, field_def: &StructFieldDef) -> Result<(), LiveError> {
82 self.ty_checker().ty_check_ty_expr(&field_def.ty_expr) ?;
83 match field_def.ty_expr.ty.borrow().as_ref().unwrap() {
85 Ty::Struct(struct_ptr) => {
86 self.struct_def.struct_refs.borrow_mut().as_mut().unwrap().insert(*struct_ptr);
87 }
88 Ty::Array {..} => {
89 todo!();
90 }
91 _ => ()
92 }
93 Ok(())
94 }
95
96 fn analyse_method_decl(&mut self, decl: &FnDef) -> Result<(), LiveError> {
97 for param in &decl.params {
98 self.ty_checker().ty_check_ty_expr(¶m.ty_expr) ?;
99 }
100 let return_ty = decl
101 .return_ty_expr
102 .as_ref()
103 .map( | return_ty_expr | self.ty_checker().ty_check_ty_expr(return_ty_expr))
104 .transpose() ?
105 .unwrap_or(Ty::Void);
106 *decl.return_ty.borrow_mut() = Some(return_ty);
107 *decl.hidden_args.borrow_mut() = Some(BTreeSet::new());
108 Ok(())
109 }
110
111}
112
113pub struct DrawShaderAnalyser<'a> {
114 pub draw_shader_def: &'a DrawShaderDef,
115 pub scopes: &'a mut Scopes,
116 pub live_registry: &'a LiveRegistry,
117 pub shader_registry: &'a ShaderRegistry,
118 pub options: ShaderAnalyseOptions,
119}
120
121impl<'a> DrawShaderAnalyser<'a> {
122 fn ty_checker(&self) -> TyChecker {
123 TyChecker {
124 live_registry: self.live_registry,
125 scopes: self.scopes,
126 shader_registry: self.shader_registry,
127 }
128 }
129
130 pub fn analyse_shader(&mut self) -> Result<(), LiveError> {
131 self.scopes.push_scope();
132
133 for field in &self.draw_shader_def.fields {
135 self.analyse_field_decl(field) ?;
136 }
137
138 for fn_node_ptr in &self.draw_shader_def.methods {
140 let fn_def = self.shader_registry.all_fns.get(fn_node_ptr).unwrap();
141 self.analyse_method_def(fn_def) ?;
142 }
143
144 for fn_node_ptr in &self.draw_shader_def.methods {
146 let fn_def = self.shader_registry.all_fns.get(fn_node_ptr).unwrap();
147 FnDefAnalyser {
148 live_registry: self.live_registry,
149 shader_registry: self.shader_registry,
150 closure_return_ty: None,
151 fn_def,
152 scopes: &mut self.scopes,
153 options: self.options,
154 is_inside_loop: false,
155 }
156 .analyse_fn_def() ?;
157 }
158
159 self.scopes.pop_scope();
160
161 let mut all_fns = Vec::new();
162 let mut vertex_fns = Vec::new();
163 self.analyse_call_tree(
166 &mut Vec::new(),
167 self.shader_registry.draw_shader_method_decl_from_ident(self.draw_shader_def, Ident(live_id!(vertex))).unwrap(),
168 &mut vertex_fns,
169 &mut all_fns,
170 ) ?;
171
172 let mut pixel_fns = Vec::new();
173 self.analyse_call_tree(
174 &mut Vec::new(),
175 self.shader_registry.draw_shader_method_decl_from_ident(self.draw_shader_def, Ident(live_id!(fragment))).unwrap(),
176 &mut pixel_fns,
177 &mut all_fns,
178 ) ?;
179
180 for pixel_fn in &pixel_fns {
182 if let Some(fn_def) = self.shader_registry.all_fns.get(pixel_fn) {
184 if let Some(FnSelfKind::DrawShader(_)) = fn_def.self_kind {
185 for dsr in fn_def.draw_shader_refs.borrow().as_ref().unwrap() {
187 for field in &self.draw_shader_def.fields {
189 if field.ident == *dsr { match &field.kind {
191 DrawShaderFieldKind::Geometry {ref is_used_in_pixel_shader, ..} => {
192 is_used_in_pixel_shader.set(true);
193 }
194 DrawShaderFieldKind::Instance {ref is_used_in_pixel_shader, ..} => {
195 is_used_in_pixel_shader.set(true);
196 }
197 _ => ()
198 }
199 }
200 }
201 }
202 }
203 }
204 }
205
206 let mut all_structs = Vec::new();
207 let mut pixel_structs = Vec::new();
208 let mut vertex_structs = Vec::new();
209 let mut all_live_refs = BTreeMap::new();
210
211 for pixel_fn in &pixel_fns {
212 let fn_decl = self.shader_registry.all_fns.get(pixel_fn).unwrap();
213 for struct_ptr in fn_decl.struct_refs.borrow().as_ref().unwrap().iter() {
215 let struct_def = self.shader_registry.structs.get(struct_ptr).unwrap();
216 self.analyse_struct_tree(&mut Vec::new(), *struct_ptr, struct_def, &mut pixel_structs, &mut all_structs) ?;
217 }
218 }
219 for vertex_fn in &vertex_fns {
220 let fn_decl = self.shader_registry.all_fns.get(vertex_fn).unwrap();
221 for struct_ptr in fn_decl.struct_refs.borrow().as_ref().unwrap().iter() {
223 let struct_def = self.shader_registry.structs.get(struct_ptr).unwrap();
224 self.analyse_struct_tree(&mut Vec::new(), *struct_ptr, struct_def, &mut vertex_structs, &mut all_structs) ?;
225 }
226 }
227
228 for any_fn in all_fns.iter().rev() {
229 let fn_def = self.shader_registry.all_fns.get(any_fn).unwrap();
230 all_live_refs.extend(fn_def.live_refs.borrow().as_ref().cloned().unwrap());
231 self.analyse_hidden_args(fn_def);
234 }
236 let mut uses_time = false;
237 for all_fn in &all_fns {
238 if let Some(fn_def) = self.shader_registry.all_fns.get(all_fn) {
240 if let Some(FnSelfKind::DrawShader(_)) = fn_def.self_kind {
241 for dsr in fn_def.draw_shader_refs.borrow().as_ref().unwrap() {
243 for field in &self.draw_shader_def.fields {
245 if field.ident == *dsr { match &field.kind {
247 DrawShaderFieldKind::Uniform { ..} => {
248 if field.ident == Ident(live_id!(time)){
249 uses_time = true;
250 }
251 }
252 _ => ()
253 }
254 }
255 }
256 }
257 }
258 }
259 }
260
261 *self.draw_shader_def.all_live_refs.borrow_mut() = all_live_refs;
262
263 *self.draw_shader_def.all_fns.borrow_mut() = all_fns;
264 *self.draw_shader_def.vertex_fns.borrow_mut() = vertex_fns;
265 *self.draw_shader_def.pixel_fns.borrow_mut() = pixel_fns;
266
267 *self.draw_shader_def.all_structs.borrow_mut() = all_structs;
268 *self.draw_shader_def.vertex_structs.borrow_mut() = vertex_structs;
269 *self.draw_shader_def.pixel_structs.borrow_mut() = pixel_structs;
270 self.draw_shader_def.uses_time.set(uses_time);
271 Ok(())
272 }
273
274 fn analyse_hidden_args(&mut self, fn_def: &FnDef) {
275 let mut hidden_args = BTreeSet::new();
277 for ident in fn_def.draw_shader_refs.borrow().as_ref().unwrap() {
278 let field_def = self.draw_shader_def.fields.iter().find( | field | field.ident == *ident).unwrap();
279 match &field_def.kind {
280 DrawShaderFieldKind::Geometry {is_used_in_pixel_shader, ..} => {
281 if is_used_in_pixel_shader.get() {
282 hidden_args.insert(HiddenArgKind::Varyings);
283 }
284 else {
285 hidden_args.insert(HiddenArgKind::Geometries);
286 }
287 }
288 DrawShaderFieldKind::Instance {is_used_in_pixel_shader, ..} => {
289 if is_used_in_pixel_shader.get() {
290 hidden_args.insert(HiddenArgKind::Varyings);
291 }
292 else {
293 hidden_args.insert(HiddenArgKind::Instances);
294 }
295 }
296 DrawShaderFieldKind::Texture {..} => {
297 hidden_args.insert(HiddenArgKind::Textures);
298 }
299 DrawShaderFieldKind::Uniform {block_ident, ..} => {
300 hidden_args.insert(HiddenArgKind::Uniform(*block_ident));
301 }
302 DrawShaderFieldKind::Varying {..} => {
303 hidden_args.insert(HiddenArgKind::Varyings);
304 }
305 }
306 }
307 if fn_def.live_refs.borrow().as_ref().unwrap().len() > 0 {
308 hidden_args.insert(HiddenArgKind::LiveUniforms);
309 }
310 for callee in fn_def.callees.borrow().as_ref().unwrap().iter() {
312 let other_fn_def = self.shader_registry.all_fns.get(callee).unwrap();
313
314 hidden_args.extend(other_fn_def.hidden_args.borrow().as_ref().unwrap().iter().cloned());
315 }
316 *fn_def.hidden_args.borrow_mut() = Some(hidden_args);
317 }
318
319
320 fn analyse_field_decl(&mut self, decl: &DrawShaderFieldDef) -> Result<(), LiveError> {
321 let ty = match decl.kind {
322 DrawShaderFieldKind::Geometry {..} => {
323 let ty = self.ty_checker().ty_check_ty_expr(&decl.ty_expr) ?;
324 match ty {
325 Ty::Float | Ty::Vec2 | Ty::Vec3 | Ty::Vec4 | Ty::Mat4 => {}
326 _ => {
327 return Err(LiveError {
328 origin: live_error_origin!(),
329 span: decl.span.into(),
330 message: String::from(
331 "attribute must be either a floating-point scalar or vector or mat4",
332 ),
333 })
334 }
335 }
336 ty
337 }
338 DrawShaderFieldKind::Instance {..} => {
339 let ty = self.ty_checker().ty_check_ty_expr(&decl.ty_expr) ?;
340 match ty {
341 Ty::Float | Ty::Vec2 | Ty::Vec3 | Ty::Vec4 | Ty::Mat2 | Ty::Mat3 | Ty::Mat4 | Ty::Enum(_) => {}
342 _ => {
343 return Err(LiveError {
344 origin: live_error_origin!(),
345 span: decl.span.into(),
346 message: String::from(
347 "attribute must be either a floating-point scalar or vector or mat4",
348 ),
349 })
350 }
351 }
352 ty
353 }
354 DrawShaderFieldKind::Texture {..} => {
355 let ty = self.ty_checker().ty_check_ty_expr(&decl.ty_expr) ?;
356 match ty {
357 Ty::Texture2D | Ty::TextureOES => {}
358 _ => {
359 return Err(LiveError {
360 origin: live_error_origin!(),
361 span: decl.span.into(),
362 message: String::from("texture must be either a texture2D or a textureOES (android)"),
363 })
364 }
365 }
366 ty
367 }
368 DrawShaderFieldKind::Uniform {..} => {
369 let ty = self.ty_checker().ty_check_ty_expr(&decl.ty_expr) ?;
370 ty
371 },
372 DrawShaderFieldKind::Varying {..} => {
373 let ty = self.ty_checker().ty_check_ty_expr(&decl.ty_expr) ?;
374 match ty {
375 Ty::Float | Ty::Vec2 | Ty::Vec3 | Ty::Vec4 => {}
376 _ => {
377 return Err(LiveError {
378 origin: live_error_origin!(),
379 span: decl.span.into(),
380 message: String::from(
381 "varying must be either a floating-point scalar or vector",
382 ),
383 })
384 }
385 }
386 ty
387 }
388 };
389 *decl.ty_expr.ty.borrow_mut() = Some(ty);
390 Ok(())
391 }
392
393 fn analyse_method_def(&mut self, def: &FnDef) -> Result<(), LiveError> {
394 for param in &def.params {
395 self.ty_checker().ty_check_ty_expr(¶m.ty_expr) ?;
396 }
397 let return_ty = def
398 .return_ty_expr
399 .as_ref()
400 .map( | return_ty_expr | self.ty_checker().ty_check_ty_expr(return_ty_expr))
401 .transpose() ?
402 .unwrap_or(Ty::Void);
403
404 if def.ident == Ident(live_id!(vertex)) {
405 match return_ty {
406 Ty::Vec4 => {}
407 _ => {
408 return Err(LiveError {
409 origin: live_error_origin!(),
410 span: def.span.into(),
411 message: String::from(
412 "function `vertex` must return a value of type `vec4`",
413 ),
414 })
415 }
416 }
417 } else if def.ident == Ident(live_id!(fragment)) {
418 match return_ty {
419 Ty::Vec4 => {}
420 _ => {
421 return Err(LiveError {
422 origin: live_error_origin!(),
423 span: def.span.into(),
424 message: String::from(
425 "function `fragment` must return a value of type `vec4`",
426 ),
427 })
428 }
429 }
430 } else {
431 match return_ty {
432 Ty::Array {..} => {
433 return Err(LiveError {
434 origin: live_error_origin!(),
435 span: def.span.into(),
436 message: String::from("functions can't return arrays"),
437 })
438 }
439 _ => {}
440 }
441 }
442 *def.return_ty.borrow_mut() = Some(return_ty);
443 Ok(())
445 }
446
447 fn analyse_struct_tree(
448 &self,
449 call_stack: &mut Vec<StructPtr>,
450 struct_ptr: StructPtr,
451 struct_def: &StructDef,
452 deps: &mut Vec<StructPtr>,
453 all_deps: &mut Vec<StructPtr>,
454 ) -> Result<(), LiveError> {
455 if let Some(index) = deps.iter().position( | v | v == &struct_ptr) {
457 deps.remove(index);
458 }
459 deps.push(struct_ptr);
460
461 if let Some(index) = all_deps.iter().position( | v | v == &struct_ptr) {
462 all_deps.remove(index);
463 }
464 all_deps.push(struct_ptr);
465
466 call_stack.push(struct_ptr);
467
468 for sub_ptr in struct_def.struct_refs.borrow().as_ref().unwrap().iter() {
469 let sub_decl = self.shader_registry.structs.get(sub_ptr).unwrap();
471 if call_stack.contains(&sub_ptr) {
472 return Err(LiveError {
473 origin: live_error_origin!(),
474 span: sub_decl.span.into(),
475 message: format!("Struct has recursively dependency"),
476 });
477 }
478
479 self.analyse_struct_tree(call_stack, *sub_ptr, sub_decl, deps, all_deps) ?;
480 }
481 call_stack.pop();
482 Ok(())
483 }
484
485
486 fn analyse_call_tree(
487 &self,
488 call_stack: &mut Vec<FnPtr>,
489 def: &FnDef,
490 deps: &mut Vec<FnPtr>,
492 all_deps: &mut Vec<FnPtr>,
493 ) -> Result<(), LiveError> {
494 if let Some(index) = deps.iter().position( | v | v == &def.fn_ptr) {
496 deps.remove(index);
497 }
498 deps.push(def.fn_ptr);
499
500 if let Some(index) = all_deps.iter().position( | v | v == &def.fn_ptr) {
501 all_deps.remove(index);
502 }
503 all_deps.push(def.fn_ptr);
504
505 call_stack.push(def.fn_ptr);
506 for callee in def.callees.borrow().as_ref().unwrap().iter() {
507 let callee_decl = self.shader_registry.all_fns.get(&callee).unwrap();
509 if call_stack.contains(&callee_decl.fn_ptr) {
510 return Err(LiveError {
511 origin: live_error_origin!(),
512 span: def.span.into(),
513 message: format!("function `{}` recursively calls `{}`", def.ident, callee_decl.ident),
514 });
515 }
516
517 self.analyse_call_tree(call_stack, callee_decl, deps, all_deps) ?;
518 }
519 call_stack.pop();
520
521 Ok(())
522 }
523}
524
525pub struct ConstAnalyser<'a> {
526 pub const_def: &'a ConstDef,
527 pub scopes: &'a mut Scopes,
528 pub live_registry: &'a LiveRegistry,
529 pub shader_registry: &'a ShaderRegistry,
530 pub options: ShaderAnalyseOptions,
531}
532
533impl<'a> ConstAnalyser<'a> {
534 fn ty_checker(&self) -> TyChecker {
535 TyChecker {
536 live_registry: self.live_registry,
537 shader_registry: self.shader_registry,
538 scopes: self.scopes,
539 }
540 }
541
542 fn const_evaluator(&self) -> ConstEvaluator {
543 ConstEvaluator {
544 options: self.options
545 }
546 }
547
548 pub fn analyse_const_decl(&mut self) -> Result<(), LiveError> {
549 let expected_ty = self.ty_checker().ty_check_ty_expr(&self.const_def.ty_expr) ?;
550 let actual_ty = self.ty_checker().ty_check_expr_with_expected_ty(
551 self.const_def.span,
552 &self.const_def.expr,
553 &expected_ty,
554 ) ?;
555 if expected_ty != actual_ty {
556 return Err(LiveError {
557 origin: live_error_origin!(),
558 span: self.const_def.span.into(),
559 message: String::from("Declared type and inferred type not the same"),
560 } .into());
561 }
562 self.const_evaluator().const_eval_expr(&self.const_def.expr) ?;
563 Ok(())
564 }
565}
566
567pub struct FnDefAnalyser<'a> {
568 pub fn_def: &'a FnDef,
569 pub closure_return_ty: Option<&'a RefCell<Option<Ty >> >,
570 pub scopes: &'a mut Scopes,
571 pub live_registry: &'a LiveRegistry,
572 pub shader_registry: &'a ShaderRegistry,
573 pub options: ShaderAnalyseOptions,
574 pub is_inside_loop: bool,
575}
576
577impl<'a> FnDefAnalyser<'a> {
578 fn ty_checker(&self) -> TyChecker {
579 TyChecker {
580 live_registry: self.live_registry,
581 shader_registry: self.shader_registry,
582 scopes: self.scopes,
583 }
584 }
585
586 fn const_evaluator(&self) -> ConstEvaluator {
587 ConstEvaluator {
588 options: self.options
589 }
590 }
591
592 fn const_gatherer(&self) -> ConstGatherer {
593 ConstGatherer {
594 fn_def: self.fn_def,
595 const_gather_active: self.options.const_gather_active
596 }
597 }
598
599 fn dep_analyser(&self) -> DepAnalyser {
600 DepAnalyser {
601 shader_registry: self.shader_registry,
602 fn_def: self.fn_def,
603 scopes: &self.scopes,
604 }
605 }
606
607 pub fn analyse_fn_decl(&mut self) -> Result<(), LiveError> {
608 for param in &self.fn_def.params {
609 self.ty_checker().ty_check_ty_expr(¶m.ty_expr) ?;
610 }
611 let return_ty = self.fn_def
612 .return_ty_expr
613 .as_ref()
614 .map( | return_ty_expr | self.ty_checker().ty_check_ty_expr(return_ty_expr))
615 .transpose() ?
616 .unwrap_or(Ty::Void);
617 *self.fn_def.return_ty.borrow_mut() = Some(return_ty);
618 Ok(())
619 }
620
621 pub fn analyse_fn_def(&mut self) -> Result<(), LiveError> {
622 self.scopes.push_scope();
623 for (param_index, param) in self.fn_def.params.iter().enumerate() {
624 match ¶m.ty_expr.kind {
625 TyExprKind::ClosureDecl {return_ty, params, ..} => {
626 self.scopes.insert_sym(
627 param.span,
628 param.ident,
629 Ty::ClosureDecl,
630 ScopeSymKind::Closure {
631 param_index,
632 return_ty: return_ty.borrow().clone().unwrap(),
633 params: params.clone()
634 },
635 );
636 }
637 _ => {
638 let shadow = self.scopes.insert_sym(
639 param.span,
640 param.ident,
641 param.ty_expr.ty.borrow().as_ref().unwrap().clone(),
642 ScopeSymKind::MutLocal,
643 );
644 param.shadow.set(Some(shadow));
645 }
646 }
647
648 }
649 *self.fn_def.return_ty.borrow_mut() = Some(
650 self.fn_def
651 .return_ty_expr
652 .as_ref()
653 .map( | return_ty_expr | return_ty_expr.ty.borrow().as_ref().unwrap().clone())
654 .unwrap_or(Ty::Void),
655 );
656 self.fn_def.init_analysis();
657 self.analyse_block(&self.fn_def.block) ?;
658 self.scopes.pop_scope();
659 self.analyse_closures() ?;
664
665 if let Some(ty_expr) = &self.fn_def.return_ty_expr {
669 if let Ty::Void = ty_expr.ty.borrow().as_ref().unwrap() {
670 }
671 else {
672 if !self.fn_def.has_return.get() {
673 return Err(LiveError {
674 origin: live_error_origin!(),
675 span: self.fn_def.span.into(),
676 message: format!(
677 "Function has no return",
678 ),
679 });
680 }
681 }
682 }
683
684 Ok(())
685 }
686
687 fn analyse_closures(&mut self) -> Result<(), LiveError> {
688
689 let mut closure_sites = self.scopes.closure_sites.replace(Vec::new());
690 let mut closure_scopes = self.scopes.closure_scopes.replace(HashMap::new());
691
692 for closure_site in &mut closure_sites {
693 let fn_decl = self.shader_registry.all_fns.get(&closure_site.call_to).unwrap();
694
695 for closure_arg in &closure_site.closure_args {
697
698 let mut scopes = closure_scopes.get_mut(&closure_arg.closure_def_index).unwrap();
699 std::mem::swap(&mut self.scopes.scopes, &mut scopes);
701
702 let closure_def = &self.fn_def.closure_defs[closure_arg.closure_def_index.0];
705 let fn_param = &fn_decl.params[closure_arg.param_index];
706
707 if let TyExprKind::ClosureDecl {params, return_ty, ..} = &fn_param.ty_expr.kind {
708 self.scopes.clear_referenced_syms();
709 self.scopes.push_scope();
710 if closure_def.params.len() != params.len() {
713 return Err(LiveError {
714 origin: live_error_origin!(),
715 span: closure_def.span.into(),
716 message: format!(
717 "Closure does not have the same number of arguments as function decl: {} expected: {}",
718 closure_def.params.len(),
719 params.len()
720 ),
721 });
722 }
723 for i in 0..closure_def.params.len() {
725 let def_param = &closure_def.params[i];
726 let decl_param = ¶ms[i];
727 let shadow = self.scopes.insert_sym(
730 def_param.span,
731 def_param.ident,
732 decl_param.ty_expr.ty.borrow().as_ref().unwrap().clone(),
733 ScopeSymKind::MutLocal,
734 );
735 def_param.shadow.set(Some(shadow));
736 }
737 match &closure_def.kind {
739 ClosureDefKind::Expr(expr) => {
740 self.analyse_expr_stmt(closure_def.span, expr) ?;
741 if expr.ty.borrow().as_ref() != return_ty.borrow().as_ref() {
743 return Err(LiveError {
744 origin: live_error_origin!(),
745 span: closure_def.span.into(),
746 message: format!(
747 "Closure return type not correct: {} expected: {}",
748 expr.ty.borrow().as_ref().unwrap(),
749 return_ty.borrow().as_ref().unwrap()
750 ),
751 });
752 }
753 }
754 ClosureDefKind::Block(block) => {
755 self.closure_return_ty = Some(return_ty);
756 self.analyse_block(block) ?;
759 self.closure_return_ty = None;
760 }
761 }
762 self.scopes.pop_scope();
765 let all_syms = self.scopes.all_referenced_syms();
768 for sym in &all_syms {
769 closure_site.all_closed_over.insert(sym.clone());
770 }
771 *closure_def.closed_over_syms.borrow_mut() = Some(all_syms);
772 }
773 else {
774 panic!()
775 }
776 std::mem::swap(&mut self.scopes.scopes, &mut scopes);
778 }
779 }
781 let mut closure_sites_out = self.fn_def.closure_sites.borrow_mut();
783 if closure_sites_out.is_some() {
784 closure_sites_out.as_mut().unwrap().extend(closure_sites);
785 }
786 else {
787 *closure_sites_out = Some(closure_sites);
788 }
789 if self.scopes.closure_sites.borrow().len()>0 {
791 return Err(LiveError {
792 origin: live_error_origin!(),
793 span: self.fn_def.span.into(),
794 message: format!("Nesting closures is not supported at the moment"),
795 });
796
797 }
798 Ok(())
799 }
800
801 fn analyse_block(&mut self, block: &Block) -> Result<(), LiveError> {
802 for stmt in &block.stmts {
803 self.analyse_stmt(stmt) ?;
804 }
805 Ok(())
806 }
807
808 fn analyse_stmt(&mut self, stmt: &Stmt) -> Result<(), LiveError> {
809 match *stmt {
810 Stmt::Break {span} => self.analyse_break_stmt(span),
811 Stmt::Continue {span} => self.analyse_continue_stmt(span),
812 Stmt::For {
813 span,
814 ident,
815 ref from_expr,
816 ref to_expr,
817 ref step_expr,
818 ref block,
819 } => self.analyse_for_stmt(span, ident, from_expr, to_expr, step_expr, block),
820 Stmt::If {
821 span,
822 ref expr,
823 ref block_if_true,
824 ref block_if_false,
825 } => self.analyse_if_stmt(span, expr, block_if_true, block_if_false),
826 Stmt::Match {
827 span,
828 ref expr,
829 ref matches,
830 } => self.analyse_match_stmt(span, expr, matches),
831 Stmt::Let {
832 span,
833 ref ty,
834 ident,
835 ref shadow,
836 ref ty_expr,
837 ref expr,
838 } => self.analyse_let_stmt(span, ty, ident, ty_expr, expr, shadow),
839 Stmt::Return {span, ref expr} => self.analyse_return_stmt(span, expr),
840 Stmt::Block {span, ref block} => self.analyse_block_stmt(span, block),
841 Stmt::Expr {span, ref expr} => self.analyse_expr_stmt(span, expr),
842 }
843 }
844
845 fn analyse_break_stmt(&self, span: TokenSpan) -> Result<(), LiveError> {
846 if !self.is_inside_loop {
847 return Err(LiveError {
848 origin: live_error_origin!(),
849 span:span.into(),
850 message: String::from("break outside loop"),
851 } .into());
852 }
853 Ok(())
854 }
855
856 fn analyse_continue_stmt(&self, span: TokenSpan) -> Result<(), LiveError> {
857 if !self.is_inside_loop {
858 return Err(LiveError {
859 origin: live_error_origin!(),
860 span:span.into(),
861 message: String::from("continue outside loop"),
862 } .into());
863 }
864 Ok(())
865 }
866
867 fn analyse_for_stmt(
868 &mut self,
869 span: TokenSpan,
870 ident: Ident,
871 from_expr: &Expr,
872 to_expr: &Expr,
873 step_expr: &Option<Expr>,
874 block: &Block,
875 ) -> Result<(), LiveError> {
876
877 self.ty_checker()
878 .ty_check_expr_with_expected_ty(span, from_expr, &Ty::Float) ?;
879
880 let from = self
881 .const_evaluator()
882 .const_eval_expr(from_expr) ?
883 .to_int()
884 .unwrap();
885
886 self.dep_analyser().dep_analyse_expr(from_expr);
887
888 self.ty_checker()
889 .ty_check_expr_with_expected_ty(span, to_expr, &Ty::Float) ?;
890
891 let to = self
892 .const_evaluator()
893 .const_eval_expr(to_expr) ?
894 .to_int()
895 .unwrap();
896 self.dep_analyser().dep_analyse_expr(to_expr);
897 if let Some(step_expr) = step_expr {
898 self.ty_checker()
899 .ty_check_expr_with_expected_ty(span, step_expr, &Ty::Float) ?;
900 let step = self
901 .const_evaluator()
902 .const_eval_expr(step_expr) ?
903 .to_int()
904 .unwrap();
905 if step == 0 {
906 return Err(LiveError {
907 origin: live_error_origin!(),
908 span:span.into(),
909 message: String::from("step must not be zero"),
910 } .into());
911 }
912 if from < to && step < 0 {
913 return Err(LiveError {
914 origin: live_error_origin!(),
915 span:span.into(),
916 message: String::from("step must not be positive"),
917 } .into());
918 }
919 if from > to && step > 0 {
920 return Err(LiveError {
921 origin: live_error_origin!(),
922 span:span.into(),
923 message: String::from("step must not be negative"),
924 } .into());
925 }
926 self.dep_analyser().dep_analyse_expr(step_expr);
927 }
928 self.scopes.push_scope();
929 self.scopes.insert_sym(
930 span,
931 ident,
932 Ty::Int,
933 ScopeSymKind::Local,
934 );
935 let was_inside_loop = self.is_inside_loop;
936 self.is_inside_loop = true;
937 self.analyse_block(block) ?;
938 self.is_inside_loop = was_inside_loop;
939 self.scopes.pop_scope();
940 Ok(())
941 }
942
943 fn analyse_if_stmt(
944 &mut self,
945 span: TokenSpan,
946 expr: &Expr,
947 block_if_true: &Block,
948 block_if_false: &Option<Box<Block >>,
949 ) -> Result<(), LiveError> {
950 self.ty_checker()
951 .ty_check_expr_with_expected_ty(span, expr, &Ty::Bool) ?;
952 self.const_evaluator().try_const_eval_expr(expr);
953 self.const_gatherer().const_gather_expr(expr);
954 self.dep_analyser().dep_analyse_expr(expr);
955 self.scopes.push_scope();
956 self.analyse_block(block_if_true) ?;
957 self.scopes.pop_scope();
958 if let Some(block_if_false) = block_if_false {
959 self.scopes.push_scope();
960 self.analyse_block(block_if_false) ?;
961 self.scopes.pop_scope();
962 }
963 Ok(())
964 }
965
966 fn analyse_match_stmt(
967 &mut self,
968 span: TokenSpan,
969 expr: &Expr,
970 matches: &Vec<Match>,
971 ) -> Result<(), LiveError> {
972 let ty = self.ty_checker()
973 .ty_check_expr(expr) ?;
974 if let Ty::Enum(live_type) = ty {
976 self.const_evaluator().try_const_eval_expr(expr);
977 self.const_gatherer().const_gather_expr(expr);
978 self.dep_analyser().dep_analyse_expr(expr);
979
980 for match_item in matches {
981 let shader_enum = self.shader_registry.enums.get(&live_type).unwrap();
983 if match_item.enum_name.0 != shader_enum.enum_name{
985 return Err(LiveError {
986 origin: live_error_origin!(),
987 span:span.into(),
988 message: format!("Enum name mismatched, expected {} got {}", shader_enum.enum_name, match_item.enum_name.0),
989 } .into())
990 }
991
992 if let Some(pos) = shader_enum.variants.iter().position( | id | *id == match_item.enum_variant.0) {
993 match_item.enum_value.set(Some(pos + 1));
994 }
995 else{
996 return Err(LiveError {
997 origin: live_error_origin!(),
998 span:span.into(),
999 message: format!("Variant not found on enum {}::{}", match_item.enum_name.0, match_item.enum_variant.0),
1000 } .into())
1001 }
1002
1003 self.scopes.push_scope();
1005 self.analyse_block(&match_item.block) ?;
1006 self.scopes.pop_scope();
1007 }
1008 Ok(())
1009 }
1010 else {
1011 Err(LiveError {
1012 origin: live_error_origin!(),
1013 span:span.into(),
1014 message: String::from("Can only match on enum types"),
1015 } .into())
1016 }
1017 }
1018
1019 fn analyse_let_stmt(
1020 &mut self,
1021 span: TokenSpan,
1022 ty: &RefCell<Option<Ty >>,
1023 ident: Ident,
1024 ty_expr: &Option<TyExpr>,
1025 expr: &Option<Expr>,
1026 shadow: &Cell<Option<ScopeSymShadow >>,
1027 ) -> Result<(), LiveError> {
1028 *ty.borrow_mut() = Some(if let Some(ty_expr) = ty_expr {
1029 if expr.is_none() {
1030 return Err(LiveError {
1031 origin: live_error_origin!(),
1032 span:span.into(),
1033 message: format!("cannot define an uninitialised variable `{}`", ident),
1034 });
1035 }
1036 let expected_ty = self.ty_checker().ty_check_ty_expr(ty_expr) ?;
1037 if let Some(expr) = expr {
1038 let actual_ty =
1039 self.ty_checker()
1040 .ty_check_expr_with_expected_ty(span, expr, &expected_ty) ?;
1041 self.dep_analyser().dep_analyse_expr(expr);
1042 actual_ty
1043 } else {
1044 expected_ty
1045 }
1046
1047 } else if let Some(expr) = expr {
1048 let ty = self.ty_checker().ty_check_expr(expr) ?;
1049 if ty == Ty::Void {
1050 return Err(LiveError {
1051 origin: live_error_origin!(),
1052 span:span.into(),
1053 message: String::from("init expression cannot be void")
1054 });
1055 }
1056 self.const_evaluator().try_const_eval_expr(expr);
1057 self.const_gatherer().const_gather_expr(expr);
1058 self.dep_analyser().dep_analyse_expr(expr);
1059 ty
1060 } else {
1061 return Err(LiveError {
1062 origin: live_error_origin!(),
1063 span:span.into(),
1064 message: format!("can't infer type of variable `{}`", ident),
1065 });
1066 });
1067 let new_shadow = self.scopes.insert_sym(
1068 span,
1069 ident,
1070 ty.borrow().as_ref().unwrap().clone(),
1071 ScopeSymKind::MutLocal,
1072 );
1073 shadow.set(Some(new_shadow));
1074 Ok(())
1075 }
1076
1077 fn analyse_return_stmt(&mut self, span: TokenSpan, expr: &Option<Expr>) -> Result<(), LiveError> {
1078
1079 self.fn_def.has_return.set(true);
1080 if let Some(expr) = expr {
1081 if let Some(ty) = self.closure_return_ty {
1082 self.ty_checker().ty_check_expr_with_expected_ty(
1083 span,
1084 expr,
1085 ty.borrow().as_ref().unwrap()
1086 ) ?;
1087 }
1088 else {
1089 self.ty_checker().ty_check_expr_with_expected_ty(
1090 span,
1091 expr,
1092 self.fn_def.return_ty.borrow().as_ref().unwrap()
1093 ) ?;
1094 }
1095
1096 self.const_evaluator().try_const_eval_expr(expr);
1097 self.const_gatherer().const_gather_expr(expr);
1098 self.dep_analyser().dep_analyse_expr(expr);
1099 } else if self.fn_def.return_ty.borrow().as_ref().unwrap() != &Ty::Void {
1100 return Err(LiveError {
1101 origin: live_error_origin!(),
1102 span:span.into(),
1103 message: String::from("missing return expression"),
1104 } .into());
1105 }
1106 Ok(())
1107 }
1108
1109 fn analyse_block_stmt(&mut self, _span: TokenSpan, block: &Block) -> Result<(), LiveError> {
1110 self.scopes.push_scope();
1111 self.analyse_block(block) ?;
1112 self.scopes.pop_scope();
1113 Ok(())
1114 }
1115
1116 fn analyse_expr_stmt(&mut self, _span: TokenSpan, expr: &Expr) -> Result<(), LiveError> {
1117 self.ty_checker().ty_check_expr(expr)?;
1118 self.const_evaluator().try_const_eval_expr(expr);
1119 self.const_gatherer().const_gather_expr(expr);
1120 self.dep_analyser().dep_analyse_expr(expr);
1121 Ok(())
1122 }
1123}
1124
1125#[derive(Clone, Copy, Debug)]
1126enum ShaderKind {
1127 Vertex,
1128 Fragment,
1129}