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    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        // we need to analyse the fields and put them somewhere.
55        for field in &self.struct_def.fields {
56            self.analyse_field_def(field) ?;
57        }
58        // first analyse decls
59        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        // now analyse the functions
64        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        // ok so. if this thing depends on structs, lets store them.
84        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(&param.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        //let mut var_inputs = DrawShaderVarInputs::default();
134        for field in &self.draw_shader_def.fields {
135            self.analyse_field_decl(field) ?;
136        }
137        
138        // first analyse decls
139        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        // now analyse the methods
145        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        // we should insert our vertex call
164        
165        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        // mark all the draw_shader_refs we reference in pixelshaders.
181        for pixel_fn in &pixel_fns {
182            // if we run into a DrawShaderMethod mark it as
183            if let Some(fn_def) = self.shader_registry.all_fns.get(pixel_fn) {
184                if let Some(FnSelfKind::DrawShader(_)) = fn_def.self_kind {
185                    // lets iterate all
186                    for dsr in fn_def.draw_shader_refs.borrow().as_ref().unwrap() {
187                        // ok we have a draw shader ident we use, now mark it on our draw_shader_decl.
188                        for field in &self.draw_shader_def.fields {
189                            if field.ident == *dsr { // we found it
190                                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            // lets collect all structs
214            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            // lets collect all structs
222            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            // fill in fns where hidden args is none
232           // if fn_def.hidden_args.borrow().is_none() {
233                self.analyse_hidden_args(fn_def);
234           // }
235        } 
236        let mut uses_time = false;
237        for all_fn in &all_fns {
238            // if we run into a DrawShaderMethod mark it as
239            if let Some(fn_def) = self.shader_registry.all_fns.get(all_fn) {
240                if let Some(FnSelfKind::DrawShader(_)) = fn_def.self_kind {
241                    // lets iterate all
242                    for dsr in fn_def.draw_shader_refs.borrow().as_ref().unwrap() {
243                        // ok we have a draw shader ident we use, now mark it on our draw_shader_decl.
244                        for field in &self.draw_shader_def.fields {
245                            if field.ident == *dsr { // we found it
246                                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        // ok so.. lets build it up
276        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        // merge in the others
311        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(&param.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        //self.env.insert_sym(decl.span, decl.ident, Sym::Fn).ok();
444        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        // lets see if callee is already in the vec, ifso remove it
456        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            // ok now we need a fn decl for this callee
470            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        //callee: Callee,
491        deps: &mut Vec<FnPtr>,
492        all_deps: &mut Vec<FnPtr>,
493    ) -> Result<(), LiveError> {
494        // lets see if callee is already in the vec, ifso remove it
495        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            // ok now we need a fn decl for this callee
508            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(&param.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 &param.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        // alright we have closures to analyse
660        // let closure_isntances = self.
661        // lets move the closures from env to
662        // then analyse it
663        self.analyse_closures() ?;
664        
665        // lets build up our fn_args_hidden and combine it
666        // with our callees
667        
668        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            // lets start the closure
696            for closure_arg in &closure_site.closure_args {
697                
698                let mut scopes = closure_scopes.get_mut(&closure_arg.closure_def_index).unwrap();
699                // lets swap our scopes for the closure scopes
700                std::mem::swap(&mut self.scopes.scopes, &mut scopes);
701                
702                // ok now we analyse the closure
703                // lets fetch the fn_decl
704                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                    // alright we have a fn_decl and a closure_def
711                    // lets get the closure-decl
712                    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                    // lets now push the argument idents on the scope
724                    for i in 0..closure_def.params.len() {
725                        let def_param = &closure_def.params[i];
726                        let decl_param = &params[i];
727                        // the decl params should already be analysed
728                        // the def params not.
729                        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                    // ok and now we go analyse the body.
738                    match &closure_def.kind {
739                        ClosureDefKind::Expr(expr) => {
740                            self.analyse_expr_stmt(closure_def.span, expr) ?;
741                            // check the expr ty vs return ty
742                            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                            // ohdear. the return should be checked against the closure
757                            // not the fndef.
758                            self.analyse_block(block) ?;
759                            self.closure_return_ty = None;
760                        }
761                    }
762                    // TODO CHECK THE RETURN TYPE
763                    
764                    self.scopes.pop_scope();
765                    // ok we also have something else.
766                    // ok we have to store the variables we have accessed on frpm scope
767                    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                // lets figure out what the
777                std::mem::swap(&mut self.scopes.scopes, &mut scopes);
778            }
779            // ok now we declare the inputs of the closure on the scope stack
780        }
781        // move or extend
782        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        // recur
790        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        // ok so the ty MUST be an Enum
975        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                // lets fetch our Enum + Variant and see if its the same live_type
982                let shader_enum = self.shader_registry.enums.get(&live_type).unwrap();
983                // ok so.. our match_item
984                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                // lets see if we have the right name
1004                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}