makepad_shader_compiler/
generate.rs

1use{
2    std::{
3        cell::{Cell, RefCell},
4        fmt,
5        fmt::Write,
6        collections::BTreeSet,
7    },
8    crate::{
9        makepad_live_id::{LiveId, live_id},
10        makepad_live_compiler::{
11            makepad_math::PrettyPrintedF32,
12            TokenSpan
13        },
14        shader_ast::*,
15        shader_registry::ShaderRegistry
16    }
17};
18
19
20struct VoidWrap();
21impl VoidWrap{
22    pub fn unwrap(&self){}
23}
24
25macro_rules! write {
26    ($dst:expr, $($arg:tt)*) => ({let _ =$dst.write_fmt(std::format_args!($($arg)*));VoidWrap()})
27}
28
29macro_rules! writeln {
30    ($dst:expr $(,)?) => (
31        write!($dst, "\n")
32    );
33    ($dst:expr, $($arg:tt)*) => (
34        {let _ = $dst.write_fmt(std::format_args!($($arg)*));VoidWrap()}
35    );
36}
37
38#[derive(Clone)]
39pub struct ClosureSiteInfo<'a> {
40    pub site_index: usize,
41    pub closure_site: &'a ClosureSite,
42    pub call_ptr: FnPtr
43}
44
45pub enum StructConsType{
46    Paren,
47    Brace,
48    ConsFn
49}
50
51pub trait BackendWriter {
52    fn get_struct_cons_type(&self)->StructConsType;
53    fn needs_mul_fn_for_matrix_multiplication(&self) -> bool;
54    fn needs_unpack_for_matrix_multiplication(&self) -> bool;
55    fn const_table_is_vec4(&self) -> bool;
56    
57    fn enum_is_float(&self)->bool;
58    
59    fn use_cons_fn(&self, what: &str) -> bool;
60
61    fn write_var_decl(
62        &self,
63        string: &mut String,
64        sep: &'static str,
65        is_inout: bool,
66        is_packed: bool,
67        ident: &dyn fmt::Display,
68        ty: &Ty,
69    ) -> bool;
70
71    fn write_call_expr_hidden_args(&self, string: &mut String, hidden_args:&BTreeSet<HiddenArgKind >, sep: &str);
72    fn write_fn_def_hidden_params(&self, string: &mut String, hidden_args:&BTreeSet<HiddenArgKind >, sep: &str);
73    
74    fn generate_live_value_prefix(&self, string: &mut String);
75    fn generate_draw_shader_field_expr(&self, string: &mut String, field_ident: Ident, ty:&Ty);
76    
77    fn write_ty_lit(&self, string: &mut String, ty_lit: TyLit);
78    fn write_builtin_call_ident(&self, string: &mut String, ident: Ident, arg_exprs: &[Expr]);
79    
80}
81
82pub struct BlockGenerator<'a> {
83    pub fn_def: &'a FnDef,
84    pub closure_site_info: Option<ClosureSiteInfo<'a >>,
85    // pub env: &'a Env,
86    pub shader_registry: &'a ShaderRegistry,
87    pub backend_writer: &'a dyn BackendWriter,
88    pub const_table_offset: Option<usize>,
89    //pub use_generated_cons_fns: bool,
90    pub indent_level: usize,
91    pub string: &'a mut String,
92}
93
94    
95pub fn generate_cons_fn(backend_writer:&dyn BackendWriter, string: &mut String, ty_lit: TyLit, param_tys: &[Ty]) {
96    let mut cons_name = format!("consfn_{}", ty_lit);
97    for param_ty in param_tys {
98        write!(cons_name, "_{}", param_ty).unwrap();
99    }
100    if !backend_writer.use_cons_fn(&cons_name) {
101        return
102    }
103    backend_writer.write_ty_lit(string, ty_lit);
104    write!(string, " {}(", cons_name).unwrap();
105    
106    let mut sep = "";
107    if param_tys.len() == 1 {
108        backend_writer.write_var_decl(string, sep, false, false, &Ident(live_id!(x)), &param_tys[0]);
109    } else {
110        for (index, param_ty) in param_tys.iter().enumerate() {
111            //write!(string, "{}", sep).unwrap();
112            backend_writer.write_var_decl(string, sep, false, false,&DisplaConstructorArg(index), param_ty);
113            sep = ", ";
114        }
115    }
116    
117    writeln!(string, ") {{").unwrap();
118    write!(string, "    return ").unwrap();
119    backend_writer.write_ty_lit(string, ty_lit);
120    write!(string, "(").unwrap();
121    let ty = ty_lit.to_ty();
122    if param_tys.len() == 1 {
123        let param_ty = &param_tys[0];
124        match param_ty {
125            Ty::Bool | Ty::Int | Ty::Float => {
126                let mut sep = "";
127                for _ in 0..ty.slots() {
128                    write!(string, "{}x", sep).unwrap();
129                    sep = ", ";
130                }
131            }
132            Ty::Mat2 | Ty::Mat3 | Ty::Mat4 => {
133                let dst_size = match ty {
134                    Ty::Mat2 => 2,
135                    Ty::Mat3 => 3,
136                    Ty::Mat4 => 4,
137                    _ => panic!(),
138                };
139                let src_size = match param_ty {
140                    Ty::Mat2 => 2,
141                    Ty::Mat3 => 3,
142                    Ty::Mat4 => 4,
143                    _ => panic!(),
144                };
145                let mut sep = "";
146                for col_index in 0..dst_size {
147                    for row_index in 0..dst_size {
148                        if row_index < src_size && col_index < src_size {
149                            write!(string, "{}x[{}][{}]", sep, col_index, row_index)
150                                .unwrap();
151                        } else {
152                            write!(
153                                string,
154                                "{}{}",
155                                sep,
156                                if col_index == row_index {1.0} else {0.0}
157                            )
158                                .unwrap();
159                        }
160                        sep = ", ";
161                    }
162                }
163            }
164            _ => panic!(),
165        }
166    } else {
167        let mut sep = "";
168        for (index_0, param_ty) in param_tys.iter().enumerate() {
169            if param_ty.slots() == 1 {
170                write!(string, "{}x{}", sep, index_0).unwrap();
171                sep = ", ";
172            } else {
173                for index_1 in 0..param_ty.slots() {
174                    write!(string, "{}x{}[{}]", sep, index_0, index_1).unwrap();
175                    sep = ", ";
176                }
177            }
178        }
179    }
180    writeln!(string, ");").unwrap();
181    writeln!(string, "}}\n").unwrap();
182}
183
184impl<'a> BlockGenerator<'a> {
185    pub fn generate_block(&mut self, block: &Block) {
186        write!(self.string, "{{\n").unwrap();
187        self.write_indent();
188        if !block.stmts.is_empty() {
189            self.indent_level += 1;
190            for stmt in &block.stmts {
191                self.generate_stmt(stmt);
192                writeln!(self.string).unwrap();
193            }
194            self.indent_level -= 1;
195            self.write_indent();
196        }
197        write!(self.string, "}}").unwrap();
198    }
199    
200    fn generate_stmt(&mut self, stmt: &Stmt) {
201        self.write_indent();
202        match *stmt {
203            Stmt::Break {span} => self.generate_break_stmt(span),
204            Stmt::Continue {span} => self.generate_continue_stmt(span),
205            Stmt::For {
206                span,
207                ident,
208                ref from_expr,
209                ref to_expr,
210                ref step_expr,
211                ref block,
212            } => self.generate_for_stmt(span, ident, from_expr, to_expr, step_expr, block),
213            Stmt::If {
214                span,
215                ref expr,
216                ref block_if_true,
217                ref block_if_false,
218            } => self.generate_if_stmt(span, expr, block_if_true, block_if_false),
219            Stmt::Match {
220                span,
221                ref expr,
222                ref matches,
223            } => self.generate_match_stmt(span, expr, matches),
224            Stmt::Let {
225                span,
226                ref ty,
227                ident,
228                ref ty_expr,
229                ref expr,
230                ref shadow
231            } => self.generate_let_stmt(span, ty, ident, ty_expr, expr, shadow),
232            Stmt::Return {span, ref expr} => self.generate_return_stmt(span, expr),
233            Stmt::Block {span, ref block} => self.generate_block_stmt(span, block),
234            Stmt::Expr {span, ref expr} => self.generate_expr_stmt(span, expr),
235        }
236    }
237    
238    fn generate_break_stmt(&mut self, _span: TokenSpan) {
239        writeln!(self.string, "break;").unwrap();
240    }
241    
242    fn generate_continue_stmt(&mut self, _span: TokenSpan) {
243        writeln!(self.string, "continue;").unwrap();
244    }
245    
246    fn generate_for_stmt(
247        &mut self,
248        _span: TokenSpan,
249        ident: Ident,
250        from_expr: &Expr,
251        to_expr: &Expr,
252        step_expr: &Option<Expr>,
253        block: &Block,
254    ) {
255        let from = from_expr
256            .const_val
257            .borrow()
258            .as_ref()
259            .unwrap()
260            .as_ref()
261            .unwrap()
262            .to_int()
263            .unwrap();
264        let to = to_expr
265            .const_val
266            .borrow()
267            .as_ref()
268            .unwrap()
269            .as_ref()
270            .unwrap()
271            .to_int()
272            .unwrap();
273        let step = if let Some(step_expr) = step_expr {
274            step_expr
275                .const_val
276                .borrow()
277                .as_ref()
278                .unwrap()
279                .as_ref()
280                .unwrap()
281                .to_int()
282                .unwrap()
283        } else if from < to {
284            1
285        } else {
286            -1
287        };
288        write!(
289            self.string,
290            "for (int {0} = {1}; {0} {2} {3}; {0} {4} {5}) ",
291            ident,
292            if from <= to {from} else {from - 1},
293            if from <= to {"<"} else {">="},
294            to,
295            if step > 0 {"+="} else {"-="},
296            step.abs()
297        )
298            .unwrap();
299        self.generate_block(block);
300        writeln!(self.string).unwrap();
301    }
302    
303    fn generate_if_stmt(
304        &mut self,
305        _span: TokenSpan,
306        expr: &Expr,
307        block_if_true: &Block,
308        block_if_false: &Option<Box<Block >>,
309    ) {
310        write!(self.string, "if").unwrap();
311        self.generate_expr(expr);
312        write!(self.string, " ").unwrap();
313        self.generate_block(block_if_true);
314        if let Some(block_if_false) = block_if_false {
315            write!(self.string, "else").unwrap();
316            self.generate_block(block_if_false);
317        }
318        writeln!(self.string).unwrap();
319    }
320    
321    fn generate_match_stmt(
322        &mut self,
323        _span: TokenSpan,
324        expr: &Expr,
325        matches: &Vec<Match>,
326    ) {
327        for (index,match_item) in matches.iter().enumerate(){
328            
329            if index != 0{
330                write!(self.string, "else  ").unwrap();
331            }
332
333            if self.backend_writer.enum_is_float(){
334                write!(self.string, "if(").unwrap();
335                self.backend_writer.write_builtin_call_ident(&mut self.string, Ident(live_id!(abs)),&[]);
336                write!(self.string, "(");
337                self.generate_expr(expr);
338                //write!(self.string, ")").unwrap();
339                //self.generate_expr(expr);
340                write!(self.string, " - {}.0)<0.5)", match_item.enum_value.get().unwrap()).unwrap();
341            }
342            else {
343                write!(self.string, "if(").unwrap();
344                self.generate_expr(expr);
345                write!(self.string, " == {})", match_item.enum_value.get().unwrap()).unwrap();
346            }
347            
348            self.generate_block(&match_item.block);
349        }
350    }
351    
352    fn generate_let_stmt(
353        &mut self,
354        _span: TokenSpan,
355        ty: &RefCell<Option<Ty >>,
356        ident: Ident,
357        _ty_expr: &Option<TyExpr>,
358        expr: &Option<Expr>,
359        shadow: &Cell<Option<ScopeSymShadow >>
360    ) {
361        self.backend_writer.write_var_decl(
362            &mut self.string,
363            "",
364            false, 
365            false,
366            &DisplayVarName(ident, shadow.get().unwrap()),
367            ty.borrow().as_ref().unwrap()
368        );
369        if let Some(expr) = expr {
370            write!(self.string, " = ").unwrap();
371            self.generate_expr(expr);
372        }
373        writeln!(self.string, ";").unwrap();
374    }
375    
376    fn generate_return_stmt(&mut self, _span: TokenSpan, expr: &Option<Expr>) {
377        write!(self.string, "return").unwrap();
378        if let Some(expr) = expr {
379            write!(self.string, " ").unwrap();
380            self.generate_expr(expr);
381        }
382        writeln!(self.string, ";").unwrap();
383    }
384    
385    fn generate_block_stmt(&mut self, _span: TokenSpan, block: &Block) {
386        self.generate_block(block);
387        writeln!(self.string).unwrap();
388    }
389    
390    fn generate_expr_stmt(&mut self, _span: TokenSpan, expr: &Expr) {
391        self.generate_expr(expr);
392        writeln!(self.string, ";").unwrap();
393    }
394    
395    fn generate_expr(&mut self, expr: &Expr) {
396        ExprGenerator {
397            closure_site_info: self.closure_site_info.clone(),
398            fn_def: Some(self.fn_def),
399            shader_registry: self.shader_registry,
400            backend_writer: self.backend_writer,
401            const_table_offset: self.const_table_offset,
402            //use_hidden_params: self.use_hidden_params,
403            //use_generated_cons_fns: self.use_generated_cons_fns,
404            string: self.string,
405        }
406        .generate_expr(expr)
407    }
408    
409    fn write_indent(&mut self) {
410        for _ in 0..self.indent_level {
411            write!(self.string, "    ").unwrap();
412        }
413    }
414    
415    //fn write_var_decl(&mut self, is_inout: bool, is_packed: bool, ident: Ident, ty: &Ty) {
416    //    self.backend_writer
417    //       .write_var_decl(&mut self.string, is_inout, is_packed, &ident, ty);
418    // }
419}
420
421pub struct ExprGenerator<'a> {
422    pub fn_def: Option<&'a FnDef>,
423    pub closure_site_info: Option<ClosureSiteInfo<'a >>,
424    // pub env: &'a Env,
425    pub shader_registry: &'a ShaderRegistry,
426    pub backend_writer: &'a dyn BackendWriter,
427    pub const_table_offset: Option<usize>,
428    //pub use_hidden_params2: bool,
429    //pub use_generated_cons_fns: bool,
430    pub string: &'a mut String,
431}
432
433impl<'a> ExprGenerator<'a> {
434    pub fn generate_expr(&mut self, in_expr: &Expr) {
435        fn const_table_index_to_vec4(string: &mut String, index: usize) {
436            let base = index >> 2;
437            let sub = index - (base << 2);
438            match sub {
439                0 => write!(string, "[{}].x", base).unwrap(),
440                1 => write!(string, "[{}].y", base).unwrap(),
441                2 => write!(string, "[{}].z", base).unwrap(),
442                _ => write!(string, "[{}].w", base).unwrap(),
443            };
444        }
445        match (in_expr.const_val.borrow().as_ref(), in_expr.const_index.get()) {
446            (Some(Some(Val::Vec4(_))), Some(mut index)) if self.const_table_offset.is_some() => {
447                let const_table_offset = self.const_table_offset.unwrap();
448                self.write_ty_lit(TyLit::Vec4);
449                write!(self.string, "(").unwrap();
450                let mut sep = "";
451                for _ in 0..4 {
452                    write!(self.string, "{}const_table", sep).unwrap();
453                    if self.backend_writer.const_table_is_vec4() {
454                        const_table_index_to_vec4(self.string, index + const_table_offset);
455                    }
456                    else {
457                        write!(self.string, "[{}]", index + const_table_offset).unwrap();
458                    }
459                    sep = ", ";
460                    index += 1;
461                }
462                write!(self.string, ")").unwrap();
463            },
464            (Some(Some(Val::Float(_))), Some(index)) if self.const_table_offset.is_some() => {
465                let const_table_offset = self.const_table_offset.unwrap();
466                write!(self.string, "const_table").unwrap();
467                if self.backend_writer.const_table_is_vec4() {
468                    const_table_index_to_vec4(self.string, index + const_table_offset);
469                }
470                else {
471                    write!(self.string, "[{}]", index + const_table_offset).unwrap();
472                }
473            }
474            // TODO: Extract the next three cases into a write_val function
475            (Some(Some(Val::Vec4(val))), _) => {
476                self.write_ty_lit(TyLit::Vec4);
477                write!(
478                    self.string,
479                    "({}, {}, {}, {})",
480                    PrettyPrintedF32(val.x),
481                    PrettyPrintedF32(val.y),
482                    PrettyPrintedF32(val.z),
483                    PrettyPrintedF32(val.w),
484                ).unwrap();
485            }
486            (Some(Some(Val::Float(val))), _) => {
487                write!(self.string, "{}f", PrettyPrintedF32(*val)).unwrap();
488            },
489            (Some(Some(val)), _) => {
490                write!(self.string, "{}", val).unwrap();
491            },
492            _ => match in_expr.kind {
493                ExprKind::Cond {
494                    span,
495                    ref expr,
496                    ref expr_if_true,
497                    ref expr_if_false,
498                } => self.generate_cond_expr(span, expr, expr_if_true, expr_if_false),
499                ExprKind::Bin {
500                    span,
501                    op,
502                    ref left_expr,
503                    ref right_expr,
504                } => self.generate_bin_expr(span, op, left_expr, right_expr),
505                ExprKind::Un {span, op, ref expr} => self.generate_un_expr(span, op, expr),
506                ExprKind::Field {
507                    span,
508                    ref expr,
509                    field_ident,
510                } => self.generate_field_expr(span, expr, field_ident, in_expr.ty.borrow().as_ref().unwrap()),
511                ExprKind::Index {
512                    span,
513                    ref expr,
514                    ref index_expr,
515                } => self.generate_index_expr(span, expr, index_expr),
516                ExprKind::MethodCall {
517                    span,
518                    ident,
519                    ref arg_exprs,
520                    ref closure_site_index,
521                } => self.generate_method_call_expr(span, ident, arg_exprs, closure_site_index),
522                ExprKind::PlainCall {
523                    span,
524                    fn_ptr,
525                    ident,
526                    ref arg_exprs,
527                    ref closure_site_index,
528                    ref param_index,
529                } => self.generate_plain_call_expr(span, ident, fn_ptr, arg_exprs, closure_site_index, param_index),
530                ExprKind::BuiltinCall {
531                    span,
532                    ident,
533                    ref arg_exprs,
534                } => self.generate_builtin_call_expr(span, ident, arg_exprs),
535                /*ExprKind::ClosureCall {
536                    span,
537                    ident,
538                    ref arg_exprs,
539                    ref param_index,
540                } => self.generate_closure_call_expr(span, arg_exprs, param_index),*/
541                ExprKind::ClosureDef(_) => (),
542                ExprKind::ConsCall {
543                    span,
544                    ty_lit,
545                    ref arg_exprs,
546                } => self.generate_cons_call_expr(span, ty_lit, arg_exprs),
547                ExprKind::StructCons {
548                    struct_ptr,
549                    span,
550                    ref args
551                } => self.generate_struct_cons(struct_ptr, span, args),
552                ExprKind::Var {
553                    span,
554                    ref kind,
555                    ..
556                } => self.generate_var_expr(span, kind, &in_expr.ty.borrow()),
557                ExprKind::Lit {span, lit} => self.generate_lit_expr(span, lit),
558            },
559        }
560    }
561    
562    fn generate_cond_expr(
563        &mut self,
564        _span: TokenSpan,
565        expr: &Expr,
566        expr_if_true: &Expr,
567        expr_if_false: &Expr,
568    ) {
569        write!(self.string, "(").unwrap();
570        self.generate_expr(expr);
571        write!(self.string, " ? ").unwrap();
572        self.generate_expr(expr_if_true);
573        write!(self.string, " : ").unwrap();
574        self.generate_expr(expr_if_false);
575        write!(self.string, ")").unwrap();
576    }
577    
578    fn generate_bin_expr(&mut self, _span: TokenSpan, op: BinOp, left_expr: &Expr, right_expr: &Expr) {
579        
580        // if left_expr or right_expr is a matrix, HLSL needs to use mul()
581        let left_is_mat = match left_expr.ty.borrow().as_ref().unwrap() {
582            Ty::Mat2 | Ty::Mat3 | Ty::Mat4 => true,
583            _ => false
584        };
585        let right_is_mat = match right_expr.ty.borrow().as_ref().unwrap() {
586            Ty::Mat2 | Ty::Mat3 | Ty::Mat4 => true,
587            _ => false
588        };
589        
590        if self.backend_writer.needs_mul_fn_for_matrix_multiplication() {
591            if left_is_mat || right_is_mat {
592                write!(self.string, "mul(").unwrap();
593                self.generate_expr(left_expr);
594                write!(self.string, ", ").unwrap();
595                self.generate_expr(right_expr);
596                write!(self.string, ")").unwrap();
597                return
598            }
599        }
600        else if self.backend_writer.needs_unpack_for_matrix_multiplication() {
601            if left_is_mat && !right_is_mat {
602                match right_expr.ty.borrow().as_ref().unwrap() {
603                    Ty::Vec4 => {
604                        write!(self.string, "(").unwrap();
605                        self.generate_expr(left_expr);
606                        write!(self.string, " {} ", op).unwrap();
607                        self.backend_writer.write_ty_lit(self.string, TyLit::Vec4);
608                        write!(self.string, "(").unwrap();
609                        self.generate_expr(right_expr);
610                        write!(self.string, "))").unwrap();
611                        return
612                    },
613                    Ty::Vec3 => {
614                        write!(self.string, "(").unwrap();
615                        self.generate_expr(left_expr);
616                        write!(self.string, " {} ", op).unwrap();
617                        self.backend_writer.write_ty_lit(self.string, TyLit::Vec3);
618                        write!(self.string, "(").unwrap();
619                        self.generate_expr(right_expr);
620                        write!(self.string, "))").unwrap();
621                        return
622                    },
623                    _ => ()
624                };
625            }
626            else if !left_is_mat && right_is_mat {
627                match left_expr.ty.borrow().as_ref().unwrap() {
628                    Ty::Vec4 => {
629                        write!(self.string, "(").unwrap();
630                        self.backend_writer.write_ty_lit(self.string, TyLit::Vec4);
631                        write!(self.string, "(").unwrap();
632                        self.generate_expr(left_expr);
633                        write!(self.string, ") {} ", op).unwrap();
634                        self.generate_expr(right_expr);
635                        write!(self.string, ")").unwrap();
636                        return
637                    },
638                    Ty::Vec3 => {
639                        write!(self.string, "(").unwrap();
640                        self.backend_writer.write_ty_lit(self.string, TyLit::Vec3);
641                        write!(self.string, "(").unwrap();
642                        self.generate_expr(left_expr);
643                        write!(self.string, ") {} ", op).unwrap();
644                        self.generate_expr(right_expr);
645                        write!(self.string, ")").unwrap();
646                        return
647                    },
648                    _ => ()
649                };
650            }
651        }
652        
653        write!(self.string, "(").unwrap();
654        self.generate_expr(left_expr);
655        write!(self.string, " {} ", op).unwrap();
656        self.generate_expr(right_expr);
657        write!(self.string, ")").unwrap();
658    }
659    
660    fn generate_un_expr(&mut self, _span: TokenSpan, op: UnOp, expr: &Expr) {
661        write!(self.string, "{}", op).unwrap();
662        self.generate_expr(expr);
663    }
664    
665    fn generate_method_call_expr(&mut self, _span: TokenSpan, ident: Ident, arg_exprs: &[Expr], closure_site_index: &Cell<Option<usize >>) {
666        // alright so. what if we have
667        // lets check if this is a call with closure args
668        
669        // ok so. what is expr
670        match arg_exprs[0].ty.borrow().as_ref().unwrap() {
671            Ty::Struct(struct_ptr) => {
672                let fn_def = self.shader_registry.struct_method_decl_from_ident(
673                    self.shader_registry.structs.get(struct_ptr).unwrap(),
674                    ident
675                ).unwrap();
676                
677                self.generate_call_body(_span, fn_def, arg_exprs, closure_site_index);
678            }
679            Ty::DrawShader(shader_ptr) => {
680                let fn_def = self.shader_registry.draw_shader_method_decl_from_ident(
681                    self.shader_registry.draw_shader_defs.get(shader_ptr).unwrap(),
682                    ident
683                ).unwrap();
684                
685                if fn_def.has_closure_args() {
686                    // ok so..
687                    
688                }
689                self.generate_call_body(_span, fn_def, &arg_exprs[1..], closure_site_index);
690            }
691            _ => panic!(),
692        }
693    }
694    
695    
696    fn generate_call_body(&mut self, _span: TokenSpan, fn_def: &FnDef, arg_exprs: &[Expr], closure_site_index: &Cell<Option<usize >>) {
697        // lets create a fn name for this thing.
698        if let Some(closure_site_index) = closure_site_index.get() {
699            // ok so.. we have closure args. this means we have a callsite
700            let call_def = self.fn_def.unwrap();
701            let closure_sites = &call_def.closure_sites.borrow();
702
703            let closure_site = &closure_sites.as_ref().unwrap()[closure_site_index];
704            // ok our function name is different now:
705            
706            // and then our args
707            write!(self.string, "{} (", DisplayFnNameWithClosureArgs(
708                closure_site_index,
709                call_def.fn_ptr,
710                fn_def.ident
711            )).unwrap();
712            
713            let mut sep = "";
714            for arg_expr in arg_exprs {
715                // check if the args is a closure, ifso skip it
716                match arg_expr.ty.borrow().as_ref().unwrap(){
717                    Ty::ClosureDef(_)=>{
718                        continue;
719                    },
720                    _=>()
721                }
722                
723                write!(self.string, "{}", sep).unwrap();
724                self.generate_expr(arg_expr);
725                sep = ", ";
726            }
727            // and now the closed over values
728            for sym in &closure_site.all_closed_over {
729                match sym.ty{
730                    Ty::DrawShader(_)=>{
731                        continue;
732                    }
733                    Ty::ClosureDef(_) | Ty::ClosureDecl=>panic!(),
734                    _=>()
735                }
736                write!(self.string, "{}", sep).unwrap();
737                write!(self.string, "{}", DisplayVarName(sym.ident, sym.shadow)).unwrap();
738                sep = ", ";
739            }
740
741            let mut merged_hidden_args = BTreeSet::new();
742            merged_hidden_args.extend(fn_def.hidden_args.borrow().as_ref().unwrap().iter().cloned());
743            merged_hidden_args.extend(call_def.hidden_args.borrow().as_ref().unwrap().iter().cloned());
744            self.backend_writer.write_call_expr_hidden_args(self.string, &merged_hidden_args, sep);
745
746            write!(self.string, ")").unwrap();
747        }
748        else {
749            write!(self.string, "{}_{} (", fn_def.fn_ptr, fn_def.ident).unwrap();
750            let mut sep = "";
751            for arg_expr in arg_exprs {
752                write!(self.string, "{}", sep).unwrap();
753                self.generate_expr(arg_expr);
754                sep = ", ";
755            }
756
757            self.backend_writer.write_call_expr_hidden_args(self.string, fn_def.hidden_args.borrow().as_ref().unwrap(), sep);
758
759            write!(self.string, ")").unwrap();
760        }
761    }
762    
763    fn generate_field_expr(&mut self, _span: TokenSpan, expr: &Expr, field_ident: Ident, ty:&Ty) {
764        match expr.ty.borrow().as_ref() {
765            Some(Ty::DrawShader(_)) => {
766                self.backend_writer.generate_draw_shader_field_expr(&mut self.string, field_ident, ty);
767                //write!(self.string, "{}", &DisplayDsIdent(field_ident)).unwrap();
768            }
769            Some(Ty::Struct{..})=>{
770                self.generate_expr(expr);
771                write!(self.string, ".{}", &DisplayStructField(field_ident)).unwrap();
772            }
773            _=>{
774                self.generate_expr(expr);
775                write!(self.string, ".{}", field_ident).unwrap();
776            }
777        }
778    }
779    
780    fn generate_struct_cons(
781        &mut self,
782        struct_ptr: StructPtr,
783        _span: TokenSpan,
784        args: &Vec<(Ident, Expr)>,
785    ) {
786        let struct_decl = self.shader_registry.structs.get(&struct_ptr).unwrap();
787        
788        let term = match self.backend_writer.get_struct_cons_type(){
789            StructConsType::Brace=>{
790                write!(self.string, "{}{{", struct_ptr).unwrap();
791                "}"
792            }
793            StructConsType::Paren=>{
794                write!(self.string, "{}(", struct_ptr).unwrap();
795                ")"
796            }
797            StructConsType::ConsFn=>{
798                write!(self.string, "consfn_{}(", struct_ptr).unwrap();
799                ")"
800            }
801        };
802        
803        for (index, field) in struct_decl.fields.iter().enumerate() {
804            if index != 0 {
805                write!(self.string, ",").unwrap();
806            }
807            let arg = args.iter().find( | (ident, _) | field.ident == *ident).unwrap();
808            self.generate_expr(&arg.1);
809        }
810        write!(self.string, "{}", term).unwrap();
811    }
812    
813    fn generate_index_expr(&mut self, _span: TokenSpan, expr: &Expr, index_expr: &Expr) {
814        self.generate_expr(expr);
815        write!(self.string, "[").unwrap();
816        self.generate_expr(index_expr);
817        write!(self.string, "]").unwrap();
818    }
819    
820    
821    fn generate_builtin_call_expr(&mut self, _span: TokenSpan, ident: Ident, arg_exprs: &[Expr]) {
822        // lets create a fn name for this thing.
823        
824        self.backend_writer.write_builtin_call_ident(&mut self.string, ident, arg_exprs);
825        
826        write!(self.string, "(").unwrap();
827        let mut sep = "";
828        for arg_expr in arg_exprs {
829            write!(self.string, "{}", sep).unwrap();
830            
831            self.generate_expr(arg_expr);
832            
833            sep = ", ";
834        }
835        
836        write!(self.string, ")").unwrap();
837    }
838    
839    
840    fn generate_plain_call_expr(&mut self, _span: TokenSpan, _ident: Option<Ident>, fn_ptr: Option<FnPtr>, arg_exprs: &[Expr], closure_site_index: &Cell<Option<usize >>, param_index: &Cell<Option<usize >>) {
841        // lets create a fn name for this thing.
842        if param_index.get().is_some(){ // its a closure
843            self.generate_closure_call_expr(_span, arg_exprs, param_index);
844        }
845        else{
846            let fn_def = self.shader_registry.all_fns.get(&fn_ptr.unwrap()).unwrap();
847            self.generate_call_body(_span, fn_def, arg_exprs, closure_site_index);
848        }
849    }
850    
851    
852    fn generate_closure_call_expr(&mut self, _span: TokenSpan, arg_exprs: &[Expr], param_index: &Cell<Option<usize >>) {
853        
854        let param_index = param_index.get().unwrap();
855        
856        let closure_site_info = self.closure_site_info.as_ref().unwrap();
857        // find our closure def
858        let closure_def_index = closure_site_info.closure_site.closure_args.iter().find( | arg | arg.param_index == param_index).unwrap().closure_def_index;
859        let call_def = self.shader_registry.all_fns.get(&closure_site_info.call_ptr).unwrap();
860        let closure_def = &call_def.closure_defs[closure_def_index.0];
861        
862        write!(self.string, "{}", DisplayClosureName(closure_site_info.call_ptr, closure_def_index)).unwrap();
863        
864        write!(self.string, "(").unwrap();
865        let mut sep = "";
866        for arg_expr in arg_exprs {
867            write!(self.string, "{}", sep).unwrap();
868            self.generate_expr(arg_expr);
869            sep = ", ";
870        }
871        // alright now we have to pass in the closed over syms IN order
872        for sym in closure_def.closed_over_syms.borrow().as_ref().unwrap() {
873            if let Ty::DrawShader(_) = sym.ty {
874                continue;
875            }
876            write!(self.string, "{}", sep).unwrap();
877            write!(self.string, "{}", DisplayClosedOverArg(sym.ident, sym.shadow)).unwrap();
878            sep = ", ";
879        }
880        
881        // we need to merge both the fn_def as well as the call_ptr
882        let mut merged_hidden_args = BTreeSet::new();
883        merged_hidden_args.extend(self.fn_def.unwrap().hidden_args.borrow().as_ref().unwrap().iter().cloned());
884        merged_hidden_args.extend(call_def.hidden_args.borrow().as_ref().unwrap().iter().cloned());
885        self.backend_writer.write_call_expr_hidden_args(self.string, &merged_hidden_args, sep);
886        
887        write!(self.string, ")").unwrap();
888        
889    }
890    
891    fn generate_macro_call_expr(
892        &mut self,
893        _analysis: &Cell<Option<MacroCallAnalysis >>,
894        _span: TokenSpan,
895        _ident: Ident,
896        _arg_exprs: &[Expr],
897    ) {
898        
899    }
900    
901    fn generate_cons_call_expr(&mut self, _span: TokenSpan, ty_lit: TyLit, arg_exprs: &[Expr]) {
902        // lets build the constructor name
903        let mut cons_name = format!("consfn_{}", ty_lit);
904        for arg_expr in arg_exprs {
905            write!(cons_name, "_{}", arg_expr.ty.borrow().as_ref().unwrap()).unwrap();
906        }
907        if self.backend_writer.use_cons_fn(&cons_name) {
908            write!(self.string, "{}", cons_name).unwrap();
909        } else {
910            self.write_ty_lit(ty_lit);
911        }
912        write!(self.string, "(").unwrap();
913        let mut sep = "";
914        for arg_expr in arg_exprs {
915            write!(self.string, "{}", sep).unwrap();
916            self.generate_expr(arg_expr);
917            sep = ", ";
918        }
919        write!(self.string, ")").unwrap();
920    }
921    
922    fn generate_var_expr(&mut self, _span: TokenSpan, kind: &Cell<Option<VarKind >>, _ty: &Option<Ty>) {
923        // ok so we have a few varkinds
924        match kind.get().unwrap() {
925            VarKind::Local {ident, shadow} => {
926                write!(self.string, "{}", DisplayVarName(ident, shadow)).unwrap();
927            }
928            VarKind::MutLocal {ident, shadow} => {
929                write!(self.string, "{}", DisplayVarName(ident, shadow)).unwrap();
930            }
931            VarKind::LiveValue(value_node_ptr) => {
932                // this is a live value.. also prefix needed
933                self.backend_writer.generate_live_value_prefix(self.string);
934                write!(self.string, "{}", value_node_ptr).unwrap();
935            }
936        }
937    }
938    
939    fn generate_lit_expr(&mut self, _span: TokenSpan, lit: Lit) {
940        write!(self.string, "{}", lit).unwrap();
941    }
942    
943    //fn write_ident(&mut self, ident: Ident) {
944    //    self.backend_writer.write_ident(&mut self.string, ident);
945    //}
946    
947    fn write_ty_lit(&mut self, ty_lit: TyLit) {
948        self.backend_writer.write_ty_lit(&mut self.string, ty_lit);
949    }
950}
951
952pub struct FnDefGenerator<'a> {
953    pub fn_def: &'a FnDef,
954    pub shader_registry: &'a ShaderRegistry,
955    pub const_table_offset: Option<usize>,
956    pub string: &'a mut String,
957    pub backend_writer: &'a dyn BackendWriter
958}
959
960impl<'a> FnDefGenerator<'a> {
961    pub fn generate_fn_def(&mut self) {
962        
963        self.backend_writer.write_var_decl(
964            &mut self.string,
965            "",
966            false,
967            false,
968            &DisplayFnName(self.fn_def.fn_ptr, self.fn_def.ident), // here we must expand IdentPath to something
969            self.fn_def.return_ty.borrow().as_ref().unwrap()
970        );
971        write!(self.string, "(").unwrap();
972        let mut sep = "";
973        for param in &self.fn_def.params {
974            if !param.shadow.get().is_none() {
975                if self.backend_writer.write_var_decl(
976                    &mut self.string,
977                    sep,
978                    param.is_inout,
979                    false,
980                    &DisplayVarName(param.ident, param.shadow.get().unwrap()),
981                    param.ty_expr.ty.borrow().as_ref().unwrap(),
982                ) {
983                    sep = ", ";
984                }
985            }
986        }
987        self.backend_writer.write_fn_def_hidden_params(self.string, self.fn_def.hidden_args.borrow().as_ref().unwrap(), sep);
988        write!(self.string, ") ").unwrap();
989        self.generate_block(&self.fn_def.block);
990        writeln!(self.string).unwrap();
991        //self.visited.insert(self.decl.ident_path);
992    }
993    
994    fn generate_block(&mut self, block: &Block) {
995        BlockGenerator {
996            shader_registry: self.shader_registry,
997            closure_site_info: None,
998            //env: self.env,
999            fn_def: self.fn_def,
1000            backend_writer: self.backend_writer,
1001            const_table_offset: self.const_table_offset,
1002            indent_level: 0,
1003            string: self.string,
1004        }
1005        .generate_block(block)
1006    }
1007}
1008
1009pub struct FnDefWithClosureArgsGenerator<'a> {
1010    pub closure_site_info: ClosureSiteInfo<'a>,
1011    pub fn_def: &'a FnDef,
1012    pub call_def: &'a FnDef,
1013    pub shader_registry: &'a ShaderRegistry,
1014    pub const_table_offset: Option<usize>,
1015    pub string: &'a mut String,
1016    pub backend_writer: &'a dyn BackendWriter
1017}
1018
1019
1020impl<'a> FnDefWithClosureArgsGenerator<'a> {
1021    pub fn generate_fn_def_with_all_closures(
1022        string:&mut String,
1023        shader_registry: &ShaderRegistry,
1024        fn_def: &FnDef,
1025        call_def: &FnDef,
1026        backend_writer: &dyn BackendWriter,
1027        const_table_offset: Option<usize>
1028    ) {
1029        // so first we are collecting the closures in defs that are actually used
1030        for (closure_def_index, closure_def) in call_def.closure_defs.iter().enumerate() {
1031            let closure_def_index = ClosureDefIndex(closure_def_index);
1032            for site in call_def.closure_sites.borrow().as_ref().unwrap() {
1033                if site.call_to == fn_def.fn_ptr { // alright this site calls the fn_def
1034                    for closure_site_arg in &site.closure_args {
1035                        if closure_site_arg.closure_def_index == closure_def_index {
1036                            // alright lets generate this closure
1037                            ClosureDefGenerator {
1038                                closure_site_arg: *closure_site_arg,
1039                                closure_def,
1040                                fn_def,
1041                                call_def,
1042                                shader_registry: shader_registry,
1043                                //env:self.env,
1044                                const_table_offset,
1045                                backend_writer,
1046                                string: string,
1047                            }
1048                            .generate_fn_def()
1049                        }
1050                    }
1051                }
1052            }
1053        }
1054        
1055        for (site_index, closure_site) in call_def.closure_sites.borrow().as_ref().unwrap().iter().enumerate() {
1056            // for each site
1057            if closure_site.call_to == fn_def.fn_ptr { // alright this site calls the fn_def
1058                // alright we need a fn def for this site_index
1059                FnDefWithClosureArgsGenerator {
1060                    closure_site_info: ClosureSiteInfo {
1061                        site_index,
1062                        closure_site,
1063                        call_ptr: call_def.fn_ptr,
1064                    },
1065                    fn_def,
1066                    call_def,
1067                    shader_registry,
1068                    //env:self.env,
1069                    const_table_offset,
1070                    backend_writer,
1071                    string,
1072                }
1073                .generate_fn_def_with_closure_args()
1074            }
1075        }
1076    }
1077    
1078    pub fn generate_fn_def_with_closure_args(&mut self) {
1079        
1080        self.backend_writer.write_var_decl(
1081            &mut self.string,
1082            "",
1083            false,
1084            false,
1085            &DisplayFnNameWithClosureArgs(
1086                self.closure_site_info.site_index,
1087                self.call_def.fn_ptr,
1088                self.fn_def.ident
1089            ), // here we must expand IdentPath to something
1090            self.fn_def.return_ty.borrow().as_ref().unwrap()
1091        );
1092        write!(self.string, "(").unwrap();
1093        let mut sep = "";
1094        for param in &self.fn_def.params {
1095            if !param.shadow.get().is_none() {
1096                if self.backend_writer.write_var_decl(
1097                    &mut self.string,
1098                    sep,
1099                    param.is_inout,
1100                    false,
1101                    &DisplayVarName(param.ident, param.shadow.get().unwrap()),
1102                    param.ty_expr.ty.borrow().as_ref().unwrap(),
1103                ) {
1104                    sep = ", ";
1105                }
1106            }
1107        }
1108        // now we iterate over the closures in our site,
1109        // and we need to merge the set of closed over args.
1110        for sym in &self.closure_site_info.closure_site.all_closed_over {
1111            if self.backend_writer.write_var_decl(
1112                &mut self.string,
1113                sep,
1114                false,
1115                false,
1116                &DisplayClosedOverArg(sym.ident, sym.shadow),
1117                &sym.ty,
1118            ) {
1119                sep = ", ";
1120            }
1121        }
1122        // we need the union of the call def and the fn def
1123        let mut merged_hidden_args = BTreeSet::new();
1124        merged_hidden_args.extend(self.fn_def.hidden_args.borrow().as_ref().unwrap().iter().cloned());
1125        merged_hidden_args.extend(self.call_def.hidden_args.borrow().as_ref().unwrap().iter().cloned());
1126        self.backend_writer.write_fn_def_hidden_params(self.string, &merged_hidden_args, sep);
1127        
1128        write!(self.string, ") ").unwrap();
1129        // alright so here the block is generated.. however
1130        // we need to know the names and the closed-over-args passthrough
1131        self.generate_block(&self.fn_def.block);
1132        
1133        
1134        writeln!(self.string).unwrap();
1135        //self.visited.insert(self.decl.ident_path);
1136    }
1137    
1138    fn generate_block(&mut self, block: &Block) {
1139        BlockGenerator {
1140            shader_registry: self.shader_registry,
1141            closure_site_info: Some(self.closure_site_info.clone()),
1142            //env: self.env,
1143            fn_def: self.fn_def,
1144            backend_writer: self.backend_writer,
1145            const_table_offset: self.const_table_offset,
1146            indent_level: 0,
1147            string: self.string,
1148        }
1149        .generate_block(block)
1150    }
1151}
1152
1153pub struct ClosureDefGenerator<'a> {
1154    pub closure_def: &'a ClosureDef,
1155    pub closure_site_arg: ClosureSiteArg,
1156    pub fn_def: &'a FnDef,
1157    pub call_def: &'a FnDef,
1158    pub shader_registry: &'a ShaderRegistry,
1159    pub const_table_offset: Option<usize>,
1160    pub string: &'a mut String,
1161    pub backend_writer: &'a dyn BackendWriter
1162}
1163
1164impl<'a> ClosureDefGenerator<'a> {
1165    pub fn generate_fn_def(&mut self) {
1166        
1167        let fn_param = &self.fn_def.params[self.closure_site_arg.param_index];
1168        
1169        let mut sep = "";
1170        
1171        if let TyExprKind::ClosureDecl {params, return_ty, ..} = &fn_param.ty_expr.kind {
1172            
1173            self.backend_writer.write_var_decl(
1174                &mut self.string,
1175                "",
1176                false,
1177                false,
1178                &DisplayClosureName(self.call_def.fn_ptr, self.closure_site_arg.closure_def_index), // here we must expand IdentPath to something
1179                return_ty.borrow().as_ref().unwrap(),
1180            );
1181            write!(self.string, "(").unwrap();
1182            
1183            // ok we have now params and names
1184            for (param_index, param) in params.iter().enumerate() {
1185                // lets fetch the name of this thing
1186                let closure_param = &self.closure_def.params[param_index];
1187                let shadow = closure_param.shadow.get().unwrap();
1188                if self.backend_writer.write_var_decl(
1189                    &mut self.string,
1190                    sep,
1191                    param.is_inout,
1192                    false,
1193                    &DisplayVarName(closure_param.ident, shadow),
1194                    param.ty_expr.ty.borrow().as_ref().unwrap(),
1195                ) {
1196                    sep = ", ";
1197                }
1198            }
1199        }
1200        else {
1201            panic!()
1202        }
1203        
1204        for sym in self.closure_def.closed_over_syms.borrow().as_ref().unwrap() {
1205            if self.backend_writer.write_var_decl(
1206                &mut self.string,
1207                sep,
1208                false,
1209                false,
1210                &DisplayVarName(sym.ident, sym.shadow),
1211                &sym.ty,
1212            ) {
1213                sep = ", ";
1214            }
1215        } 
1216
1217        let mut merged_hidden_args = BTreeSet::new();
1218        merged_hidden_args.extend(self.fn_def.hidden_args.borrow().as_ref().unwrap().iter().cloned());
1219        merged_hidden_args.extend(self.call_def.hidden_args.borrow().as_ref().unwrap().iter().cloned());
1220        self.backend_writer.write_fn_def_hidden_params(self.string, &merged_hidden_args, sep);
1221        
1222        writeln!(self.string, ") {{").unwrap();
1223        
1224        match &self.closure_def.kind {
1225            ClosureDefKind::Expr(expr) => {
1226                write!(self.string, "    return ").unwrap();
1227                self.generate_expr(expr);
1228                writeln!(self.string, ";").unwrap();
1229                writeln!(self.string, "}}").unwrap();
1230            }
1231            ClosureDefKind::Block(block) => {
1232                self.generate_block(block);
1233                writeln!(self.string).unwrap();
1234            }
1235        }
1236        //self.visited.insert(self.decl.ident_path);
1237    }
1238    
1239    fn generate_block(&mut self, block: &Block) {
1240        BlockGenerator {
1241            shader_registry: self.shader_registry,
1242            closure_site_info: None,
1243            //env: self.env,
1244            fn_def: self.fn_def,
1245            backend_writer: self.backend_writer,
1246            const_table_offset: self.const_table_offset,
1247            indent_level: 0,
1248            string: self.string,
1249        }
1250        .generate_block(block)
1251    }
1252    
1253    
1254    fn generate_expr(&mut self, expr: &Expr) {
1255        ExprGenerator {
1256            shader_registry: self.shader_registry,
1257            closure_site_info: None,
1258            //env: self.env,
1259            fn_def: Some(self.fn_def),
1260            backend_writer: self.backend_writer,
1261            const_table_offset: self.const_table_offset,
1262            string: self.string,
1263        }
1264        .generate_expr(expr)
1265    }
1266}
1267
1268pub struct DisplayDsIdent(pub Ident);
1269impl fmt::Display for DisplayDsIdent {
1270    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1271        write!(f, "ds_{}", self.0);
1272        fmt::Result::Ok(())
1273    }
1274}
1275
1276pub struct DisplayPadding(pub usize);
1277impl fmt::Display for DisplayPadding {
1278    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1279        write!(f, "pad_{}", self.0);
1280        fmt::Result::Ok(())
1281    }
1282}
1283
1284pub struct DisplayStructField(pub Ident);
1285impl fmt::Display for DisplayStructField {
1286    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1287        write!(f, "f_{}", self.0);
1288        fmt::Result::Ok(())
1289    }
1290}
1291
1292pub struct DisplayFnName(pub FnPtr, pub Ident);
1293impl fmt::Display for DisplayFnName {
1294    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1295        write!(f, "{}_{}", self.0, self.1);
1296        fmt::Result::Ok(())
1297    }
1298}
1299
1300pub struct DisplayFnNameWithClosureArgs(pub usize, pub FnPtr, pub Ident);
1301impl fmt::Display for DisplayFnNameWithClosureArgs {
1302    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1303        write!(f, "site_{}_of_{}_{}", self.0, self.1, self.2);
1304        fmt::Result::Ok(())
1305    }
1306}
1307
1308pub struct DisplayClosureName(pub FnPtr, pub ClosureDefIndex);
1309impl fmt::Display for DisplayClosureName {
1310    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1311        write!(f, "closure_{}_in_{}", self.1.0, self.0);
1312        fmt::Result::Ok(())
1313    }
1314}
1315
1316pub struct DisplayVarName(pub Ident, pub ScopeSymShadow);
1317impl fmt::Display for DisplayVarName {
1318    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1319        write!(f, "var_{}_{}", self.0, self.1.0);
1320        fmt::Result::Ok(())
1321    }
1322}
1323
1324pub struct DisplayClosedOverArg(pub Ident, pub ScopeSymShadow);
1325impl fmt::Display for DisplayClosedOverArg {
1326    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1327        write!(f, "pass_{}_{}", self.0, self.1.0);
1328        fmt::Result::Ok(())
1329    }
1330}
1331
1332pub struct DisplaConstructorArg(pub usize);
1333impl fmt::Display for DisplaConstructorArg {
1334    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1335        write!(f, "x{}", self.0);
1336        fmt::Result::Ok(())
1337    }
1338}