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