makepad_shader_compiler/
analyse.rs

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