makepad_shader_compiler/
shader_ast.rs

1use {
2    std::{
3        cell::{Cell, RefCell},
4        collections::HashMap,
5        collections::BTreeSet,
6        collections::BTreeMap,
7        fmt,
8        rc::Rc,
9        ops::Deref,
10        ops::DerefMut
11    },
12    makepad_live_id::*,
13    makepad_live_compiler::*,
14    makepad_live_compiler::makepad_math::*,
15};
16//use crate::shaderregistry::ShaderResourceId;
17
18// all the Live node pointer newtypes
19
20#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
21pub struct FnPtr(pub LivePtr);
22impl Deref for FnPtr {type Target = LivePtr; fn deref(&self) -> &Self::Target {&self.0}}
23impl DerefMut for FnPtr {fn deref_mut(&mut self) -> &mut Self::Target {&mut self.0}}
24
25#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
26pub struct StructPtr(pub LivePtr);
27impl Deref for StructPtr {type Target = LivePtr; fn deref(&self) -> &Self::Target {&self.0}}
28impl DerefMut for StructPtr {fn deref_mut(&mut self) -> &mut Self::Target {&mut self.0}}
29
30#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
31pub struct DrawShaderPtr(pub LivePtr);
32impl Deref for DrawShaderPtr {type Target = LivePtr; fn deref(&self) -> &Self::Target {&self.0}}
33impl DerefMut for DrawShaderPtr {fn deref_mut(&mut self) -> &mut Self::Target {&mut self.0}}
34
35//#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
36//pub struct ConstPtr(pub LivePtr);
37//impl Deref for ConstPtr{type Target = LivePtr;fn deref(&self) -> &Self::Target {&self.0}}
38//impl DerefMut for ConstPtr{fn deref_mut(&mut self) -> &mut Self::Target {&mut self.0}}
39
40#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
41pub struct ValuePtr(pub LivePtr);
42impl Deref for ValuePtr {type Target = LivePtr; fn deref(&self) -> &Self::Target {&self.0}}
43impl DerefMut for ValuePtr {fn deref_mut(&mut self) -> &mut Self::Target {&mut self.0}}
44
45#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
46pub struct VarDefPtr(pub LivePtr);
47impl Deref for VarDefPtr {type Target = LivePtr; fn deref(&self) -> &Self::Target {&self.0}}
48impl DerefMut for VarDefPtr {fn deref_mut(&mut self) -> &mut Self::Target {&mut self.0}}
49
50#[derive(Clone, Default, Debug)]
51pub struct ConstTableItem {
52    pub offset: usize,
53    pub slots: usize
54}
55
56#[derive(Clone, Debug)]
57pub struct ConstTableSpan {
58    pub token_id: LiveTokenId,
59    pub offset: usize,
60    pub slots: usize
61}
62
63#[derive(Clone, Default, Debug)]
64pub struct DrawShaderConstTable {
65    pub table: Vec<f32>,
66    pub offsets: BTreeMap<FnPtr, usize>,
67    pub table_index: BTreeMap<LiveTokenId, ConstTableItem>
68}
69
70#[derive(Clone, Copy, Default, Debug)]
71pub struct DrawShaderFlags {
72    pub debug: bool,
73    pub draw_call_nocompare: bool,
74    pub draw_call_always: bool,
75}
76
77#[derive(Clone, Default, Debug)]
78pub struct DrawShaderDef {
79    pub flags: DrawShaderFlags,
80    //pub default_geometry: Option<ShaderResourceId>,
81    pub fields: Vec<DrawShaderFieldDef>,
82    pub methods: Vec<FnPtr>,
83    pub enums: Vec<LiveType>,
84    // analysis results:
85    //pub all_const_refs: RefCell<BTreeSet<ConstPtr>>,
86    pub all_live_refs: RefCell<BTreeMap<ValuePtr, Ty >>,
87    pub all_fns: RefCell<Vec<FnPtr >>,
88    pub vertex_fns: RefCell<Vec<FnPtr >>,
89    pub pixel_fns: RefCell<Vec<FnPtr >>,
90    pub all_structs: RefCell<Vec<StructPtr >>,
91    pub vertex_structs: RefCell<Vec<StructPtr >>,
92    pub pixel_structs: RefCell<Vec<StructPtr >>,
93    // ok these 2 things dont belong here
94    //pub const_table: DrawShaderConstTable,
95    //pub var_inputs: RefCell<DrawShaderVarInputs>
96}
97
98#[derive(Clone, Debug)]
99pub struct DrawShaderFieldDef {
100    pub span: TokenSpan,
101    pub ident: Ident,
102    pub ty_expr: TyExpr,
103    pub kind: DrawShaderFieldKind
104}
105
106/*
107#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
108pub enum DrawShaderInputType {
109    VarDef(LivePtr),
110    ShaderResourceId(ShaderResourceId)
111}*/
112
113
114
115#[derive(Clone, Debug)]
116pub enum DrawShaderFieldKind {
117    Geometry {
118        is_used_in_pixel_shader: Cell<bool >,
119        var_def_ptr: Option<VarDefPtr>,
120    },
121    Instance {
122        is_used_in_pixel_shader: Cell<bool >,
123        live_field_kind: LiveFieldKind,
124        var_def_ptr: Option<VarDefPtr>,
125        //input_type: DrawShaderInputType,
126    },
127    Texture {
128        var_def_ptr: Option<VarDefPtr>,
129        //input_type: DrawShaderInputType,
130    },
131    Uniform {
132        var_def_ptr: Option<VarDefPtr>,
133        //input_type: DrawShaderInputType,
134        block_ident: Ident,
135    },
136    Varying {
137        var_def_ptr: VarDefPtr,
138    }
139}
140
141#[derive(Clone, Debug)]
142pub struct ConstDef {
143    pub span: TokenSpan,
144    pub ident: Ident,
145    pub ty_expr: TyExpr,
146    pub expr: Expr,
147}
148
149// the unique identification of a fn call
150//#[derive(Clone, Copy, Debug, Ord, PartialOrd, Eq, PartialEq)]
151//pub enum Callee {
152//    PlainFn {fn_node_ptr: FnNodePtr},
153//    DrawShaderMethod {shader_node_ptr: DrawShaderNodePtr, ident: Ident},
154//    StructMethod {struct_node_ptr: StructNodePtr, ident: Ident},
155//}
156
157#[derive(Clone, Copy, Eq, Hash, PartialEq, Ord, PartialOrd, Debug)]
158pub enum FnSelfKind {
159    Struct(StructPtr),
160    DrawShader(DrawShaderPtr)
161}
162
163impl FnSelfKind {
164    pub fn to_ty_expr_kind(self) -> TyExprKind {
165        match self {
166            FnSelfKind::DrawShader(shader_ptr) => {
167                TyExprKind::DrawShader(shader_ptr)
168            },
169            FnSelfKind::Struct(struct_ptr) => {
170                TyExprKind::Struct(struct_ptr)
171            },
172        }
173    }
174}
175
176#[derive(Clone, Copy, Eq, Hash, PartialEq, Ord, PartialOrd, Debug)]
177pub enum HiddenArgKind {
178    Geometries,
179    Instances,
180    Varyings,
181    Textures,
182    Uniform(Ident),
183    LiveUniforms,
184}
185
186#[derive(Clone, Debug)]
187pub struct FnDef {
188    pub fn_ptr: FnPtr,
189    
190    pub ident: Ident,
191    
192    pub self_kind: Option<FnSelfKind>,
193    pub has_return: Cell<bool>,
194    
195    pub callees: RefCell<Option<BTreeSet<FnPtr >> >,
196    pub builtin_deps: RefCell<Option<BTreeSet<Ident >> >,
197    // pub closure_deps: RefCell<Option<BTreeSet<Ident >> >,
198    
199    // the const table (per function)
200    pub const_table: RefCell<Option<Vec<f32 >> >,
201    pub const_table_spans: RefCell<Option<Vec<ConstTableSpan >> >,
202    
203    pub hidden_args: RefCell<Option<BTreeSet<HiddenArgKind >> >,
204    pub draw_shader_refs: RefCell<Option<BTreeSet<Ident >> >,
205    //pub const_refs: RefCell<Option<BTreeSet<ConstPtr >> >,
206    pub live_refs: RefCell<Option<BTreeMap<ValuePtr, Ty >> >,
207    
208    pub struct_refs: RefCell<Option<BTreeSet<StructPtr >> >,
209    pub constructor_fn_deps: RefCell<Option<BTreeSet<(TyLit, Vec<Ty>) >> >,
210    
211    pub closure_defs: Vec<ClosureDef>,
212    pub closure_sites: RefCell<Option<Vec<ClosureSite >> >,
213    
214    // base
215    pub span: TokenSpan,
216    pub return_ty: RefCell<Option<Ty >>,
217    pub params: Vec<Param>,
218    pub return_ty_expr: Option<TyExpr>,
219    pub block: Block,
220}
221
222
223#[derive(Clone, Debug, Copy, Eq, Hash, PartialEq, Ord, PartialOrd)]
224pub struct ClosureDefIndex(pub usize);
225
226#[derive(Clone, Debug)]
227pub struct ClosureParam {
228    pub span: TokenSpan,
229    pub ident: Ident,
230    pub shadow: Cell<Option<ScopeSymShadow >>
231}
232
233#[derive(Clone, Debug)]
234pub struct ClosureDef {
235    pub span: TokenSpan,
236    pub closed_over_syms: RefCell<Option<Vec<Sym >> >,
237    pub params: Vec<ClosureParam>,
238    pub kind: ClosureDefKind
239}
240
241#[derive(Clone, Debug)]
242pub enum ClosureDefKind {
243    Expr(Expr),
244    Block(Block)
245}
246
247#[derive(Clone, Debug)]
248pub struct ClosureSite { //
249    pub call_to: FnPtr,
250    pub all_closed_over: BTreeSet<Sym>,
251    pub closure_args: Vec<ClosureSiteArg>
252}
253
254#[derive(Clone, Copy, Debug)]
255pub struct ClosureSiteArg {
256    pub param_index: usize,
257    pub closure_def_index: ClosureDefIndex
258}
259
260#[derive(Clone, Debug)]
261pub struct StructDef {
262    pub span: TokenSpan,
263    //pub ident: Ident,
264    pub struct_refs: RefCell<Option<BTreeSet<StructPtr >> >,
265    pub fields: Vec<StructFieldDef>,
266    pub methods: Vec<FnPtr>,
267}
268
269#[derive(Clone, Debug)]
270pub struct StructFieldDef {
271    pub var_def_ptr: VarDefPtr,
272    pub span: TokenSpan,
273    pub ident: Ident,
274    pub ty_expr: TyExpr,
275}
276
277impl StructDef {
278    pub fn find_field(&self, ident: Ident) -> Option<&StructFieldDef> {
279        self.fields.iter().find( | field | field.ident == ident)
280    }
281    
282}
283
284
285#[derive(Clone, Debug)]
286pub struct Param {
287    pub span: TokenSpan,
288    pub is_inout: bool,
289    pub ident: Ident,
290    pub shadow: Cell<Option<ScopeSymShadow >>,
291    pub ty_expr: TyExpr,
292}
293
294#[derive(Clone, Debug)]
295pub struct Block {
296    pub stmts: Vec<Stmt>,
297}
298
299#[derive(Clone, Debug)]
300pub enum Stmt {
301    Break {
302        span: TokenSpan,
303    },
304    Continue {
305        span: TokenSpan,
306    },
307    For {
308        span: TokenSpan,
309        ident: Ident,
310        from_expr: Expr,
311        to_expr: Expr,
312        step_expr: Option<Expr>,
313        block: Box<Block>,
314    },
315    If {
316        span: TokenSpan,
317        expr: Expr,
318        block_if_true: Box<Block>,
319        block_if_false: Option<Box<Block >>,
320    },
321    Match {
322        span: TokenSpan,
323        expr: Expr,
324        matches: Vec<Match>,
325    },
326    
327    Let {
328        span: TokenSpan,
329        ty: RefCell<Option<Ty >>,
330        shadow: Cell<Option<ScopeSymShadow >>,
331        ident: Ident,
332        ty_expr: Option<TyExpr>,
333        expr: Option<Expr>,
334    },
335    Return {
336        span: TokenSpan,
337        expr: Option<Expr>,
338    },
339    Block {
340        span: TokenSpan,
341        block: Box<Block>,
342    },
343    Expr {
344        span: TokenSpan,
345        expr: Expr,
346    },
347}
348
349#[derive(Clone, Debug)]
350pub struct Match {
351    pub span: TokenSpan,
352    pub enum_name: Ident,
353    pub enum_variant: Ident,
354    pub enum_value: Cell<Option<usize >>,
355    pub block: Block
356}
357
358#[derive(Clone, Debug)]
359pub struct Expr {
360    pub span: TokenSpan,
361    pub ty: RefCell<Option<Ty >>,
362    pub const_val: RefCell<Option<Option<Val >> >,
363    pub const_index: Cell<Option<usize >>,
364    pub kind: ExprKind,
365}
366
367#[derive(Clone, Debug)]
368pub enum ExprKind {
369    Cond {
370        span: TokenSpan,
371        expr: Box<Expr>,
372        expr_if_true: Box<Expr>,
373        expr_if_false: Box<Expr>,
374    },
375    Bin {
376        span: TokenSpan,
377        op: BinOp,
378        left_expr: Box<Expr>,
379        right_expr: Box<Expr>,
380    },
381    Un {
382        span: TokenSpan,
383        op: UnOp,
384        expr: Box<Expr>,
385    },
386    Field {
387        span: TokenSpan,
388        expr: Box<Expr>,
389        field_ident: Ident,
390    },
391    Index {
392        span: TokenSpan,
393        expr: Box<Expr>,
394        index_expr: Box<Expr>,
395    },
396    MethodCall {
397        span: TokenSpan,
398        ident: Ident,
399        closure_site_index: Cell<Option<usize >>,
400        arg_exprs: Vec<Expr>,
401    },
402    PlainCall { // not very pretty but otherwise closures cannot override a normal fn
403        // possible solution is to capture it in a refcell sub-enum.
404        span: TokenSpan,
405        fn_ptr: Option<FnPtr>,
406        ident: Option<Ident>,
407        param_index: Cell<Option<usize >>, // used by the closure case
408        closure_site_index: Cell<Option<usize >>, // used by the plain fn case
409        arg_exprs: Vec<Expr>,
410    },
411    BuiltinCall {
412        span: TokenSpan,
413        ident: Ident,
414        arg_exprs: Vec<Expr>,
415    },
416    ClosureDef(ClosureDefIndex),
417    ConsCall {
418        span: TokenSpan,
419        ty_lit: TyLit,
420        arg_exprs: Vec<Expr>,
421    },
422    StructCons {
423        struct_ptr: StructPtr,
424        span: TokenSpan,
425        args: Vec<(Ident, Expr)>
426    },
427    Var {
428        span: TokenSpan,
429        ident: Option<Ident>,
430        kind: Cell<Option<VarKind >>,
431        var_resolve: VarResolve,
432        //ident_path: IdentPath,
433    },
434    Lit {
435        span: TokenSpan,
436        lit: Lit,
437    },
438}
439
440pub enum PlainCallType {
441    Plain {
442        
443    }
444}
445
446#[derive(Clone, Copy, Debug)]
447pub enum VarResolve {
448    NotFound,
449    Function(FnPtr),
450    LiveValue(ValuePtr, TyLit)
451}
452
453#[derive(Clone, Copy, Debug)]
454pub enum VarKind {
455    Local {ident: Ident, shadow: ScopeSymShadow},
456    MutLocal {ident: Ident, shadow: ScopeSymShadow},
457    LiveValue(ValuePtr)
458}
459
460#[derive(Clone, Debug)]
461pub struct TyExpr {
462    pub span: TokenSpan,
463    pub ty: RefCell<Option<Ty >>,
464    pub kind: TyExprKind,
465}
466
467#[derive(Clone, Debug)]
468pub enum TyExprKind {
469    Array {
470        elem_ty_expr: Box<TyExpr>,
471        len: u32,
472    },
473    Struct(StructPtr),
474    Enum(LiveType),
475    DrawShader(DrawShaderPtr),
476    Lit {
477        ty_lit: TyLit,
478    },
479    ClosureDecl {
480        return_ty: RefCell<Option<Ty >>,
481        return_ty_expr: Box<Option<TyExpr >>,
482        params: Vec<Param>
483    },
484}
485
486
487#[derive(Clone, Copy)]
488pub enum MacroCallAnalysis {
489}
490
491#[derive(Clone, Copy, Debug)]
492pub enum BinOp {
493    Assign,
494    AddAssign,
495    SubAssign,
496    MulAssign,
497    DivAssign,
498    Or,
499    And,
500    Eq,
501    Ne,
502    Lt,
503    Le,
504    Gt,
505    Ge,
506    Add,
507    Sub,
508    Mul,
509    Div,
510}
511
512
513
514#[derive(Clone, Copy, Debug)]
515pub enum UnOp {
516    Not,
517    Neg,
518}
519
520#[derive(Clone, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
521pub enum ShaderTy {
522    Void,
523    Bool,
524    Int,
525    Float,
526    Bvec2,
527    Bvec3,
528    Bvec4,
529    Ivec2,
530    Ivec3,
531    Ivec4,
532    Vec2,
533    Vec3,
534    Vec4,
535    Mat2,
536    Mat3,
537    Mat4,
538    Texture2D,
539    Array {elem_ty: Rc<ShaderTy>, len: usize},
540    Struct(StructPtr),
541    Enum(LiveType),
542    DrawShader(DrawShaderPtr),
543    ClosureDef(ClosureDefIndex),
544    ClosureDecl
545}
546
547pub type Ty = ShaderTy;
548
549
550#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
551pub enum TyLit {
552    Bool,
553    Int,
554    Float,
555    Bvec2,
556    Bvec3,
557    Bvec4,
558    Ivec2,
559    Ivec3,
560    Ivec4,
561    Vec2,
562    Vec3,
563    Vec4,
564    Mat2,
565    Mat3,
566    Mat4,
567    Texture2D,
568}
569
570#[derive(Clone, Copy, PartialEq, Debug)]
571pub enum Lit {
572    Bool(bool),
573    Int(i32),
574    Float(f32),
575    Color(u32),
576}
577
578#[derive(Clone, PartialEq, Debug)]
579pub enum Val {
580    Bool(bool),
581    Int(i32),
582    Float(f32),
583    Vec4(Vec4),
584}
585
586
587pub type Scope = HashMap<Ident, ScopeSym>;
588
589#[derive(Clone, Debug)]
590pub struct Scopes {
591    pub scopes: Vec<Scope>,
592    pub closure_scopes: RefCell<HashMap<ClosureDefIndex, Vec<Scope >> >,
593    pub closure_sites: RefCell<Vec<ClosureSite >>,
594}
595
596#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
597pub struct ScopeSymShadow(pub usize);
598
599#[derive(Clone, Eq, Hash, PartialEq, Ord, PartialOrd, Debug)]
600pub struct Sym {
601    pub ident: Ident,
602    pub ty: Ty,
603    pub shadow: ScopeSymShadow, // how many times this symbol has been shadowed
604}
605
606#[derive(Clone, Debug)]
607pub struct ScopeSym {
608    pub span: TokenSpan,
609    pub sym: Sym,
610    pub referenced: Cell<bool>,
611    pub kind: ScopeSymKind
612}
613
614#[derive(Clone, Debug)]
615pub enum ScopeSymKind {
616    Local,
617    MutLocal,
618    Closure {
619        return_ty: Ty,
620        param_index: usize,
621        params: Vec<Param>
622    }
623}
624
625impl Scopes {
626    pub fn new() -> Scopes {
627        Scopes {
628            closure_scopes: RefCell::new(HashMap::new()),
629            closure_sites: RefCell::new(Vec::new()),
630            scopes: Vec::new(),
631        }
632    }
633    
634    pub fn find_sym_on_scopes(&self, ident: Ident, _span: TokenSpan) -> Option<&ScopeSym> {
635        let ret = self.scopes.iter().rev().find_map( | scope | scope.get(&ident));
636        if ret.is_some() {
637            return Some(ret.unwrap())
638        }
639        return None
640    }
641    
642    pub fn capture_closure_scope(&self, index: ClosureDefIndex) {
643        self.closure_scopes.borrow_mut().insert(index, self.scopes.clone());
644    }
645    
646    pub fn push_scope(&mut self) {
647        self.scopes.push(Scope::new())
648    }
649    
650    pub fn pop_scope(&mut self) {
651        self.scopes.pop().unwrap();
652    }
653    
654    pub fn clear_referenced_syms(&self) {
655        for scope in self.scopes.iter().rev() {
656            for (_, sym) in scope {
657                sym.referenced.set(false);
658            }
659        }
660    }
661    
662    pub fn all_referenced_syms(&self) -> Vec<Sym> {
663        let mut ret = Vec::new();
664        for scope in self.scopes.iter().rev() {
665            for (_, sym) in scope {
666                if sym.referenced.get() {
667                    ret.push(sym.sym.clone());
668                }
669            }
670        }
671        ret
672    }
673    
674    pub fn insert_sym(&mut self, span: TokenSpan, ident: Ident, ty: Ty, sym_kind: ScopeSymKind) -> ScopeSymShadow {
675        
676        if let Some(item) = self.scopes.last_mut().unwrap().get_mut(&ident) {
677            item.sym.shadow = ScopeSymShadow(item.sym.shadow.0 + 1);
678            item.kind = sym_kind;
679            item.sym.shadow
680        }
681        else {
682            // find it anyway
683            let shadow = if let Some(ret) = self.scopes.iter().rev().find_map( | scope | scope.get(&ident)) {
684                ScopeSymShadow(ret.sym.shadow.0 + 1)
685            }
686            else {
687                ScopeSymShadow(0)
688            };
689            self.scopes.last_mut().unwrap().insert(ident, ScopeSym {
690                sym: Sym {
691                    ty,
692                    ident,
693                    shadow,
694                },
695                span,
696                referenced: Cell::new(false),
697                kind: sym_kind
698            });
699            shadow
700        }
701    }
702}
703
704#[derive(Clone, Copy, Ord, PartialOrd, Default, Eq, Hash, PartialEq)]
705pub struct Ident(pub LiveId);
706
707
708impl StructDef {
709    pub fn init_analysis(&self) {
710        *self.struct_refs.borrow_mut() = Some(BTreeSet::new());
711    }
712}
713
714
715impl FnDef {
716    
717    pub fn new(
718        fn_ptr: FnPtr,
719        span: TokenSpan,
720        ident: Ident,
721        self_kind: Option<FnSelfKind>,
722        params: Vec<Param>,
723        return_ty_expr: Option<TyExpr>,
724        block: Block,
725        closure_defs: Vec<ClosureDef>
726    ) -> Self {
727        FnDef {
728            fn_ptr,
729            span,
730            ident,
731            self_kind,
732            params,
733            return_ty_expr,
734            block,
735            closure_defs,
736            has_return: Cell::new(false),
737            hidden_args: RefCell::new(None),
738            closure_sites: RefCell::new(None),
739            live_refs: RefCell::new(None),
740            struct_refs: RefCell::new(None),
741            draw_shader_refs: RefCell::new(None),
742            return_ty: RefCell::new(None),
743            callees: RefCell::new(None),
744            builtin_deps: RefCell::new(None),
745            constructor_fn_deps: RefCell::new(None),
746            const_table: RefCell::new(None),
747            const_table_spans: RefCell::new(None),
748        }
749    }
750    
751    pub fn init_analysis(&self) {
752        *self.struct_refs.borrow_mut() = Some(BTreeSet::new());
753        *self.callees.borrow_mut() = Some(BTreeSet::new());
754        *self.builtin_deps.borrow_mut() = Some(BTreeSet::new());
755        //*self.closure_deps.borrow_mut() = Some(BTreeSet::new());
756        *self.constructor_fn_deps.borrow_mut() = Some(BTreeSet::new());
757        *self.draw_shader_refs.borrow_mut() = Some(BTreeSet::new());
758        *self.live_refs.borrow_mut() = Some(BTreeMap::new());
759        *self.const_table.borrow_mut() = Some(Vec::new());
760        *self.const_table_spans.borrow_mut() = Some(Vec::new());
761    }
762    
763    pub fn has_closure_args(&self) -> bool {
764        for param in &self.params {
765            if let TyExprKind::ClosureDecl {..} = &param.ty_expr.kind {
766                return true
767            }
768        }
769        return false
770    }
771}
772
773impl DrawShaderDef {
774    
775    pub fn find_field(&self, ident: Ident) -> Option<&DrawShaderFieldDef> {
776        self.fields.iter().find( | decl | {
777            decl.ident == ident
778        })
779    }
780    
781    pub fn fields_as_uniform_blocks(&self) -> BTreeMap<Ident, Vec<(usize, Ident) >> {
782        let mut uniform_blocks = BTreeMap::new();
783        for (field_index, field) in self.fields.iter().enumerate() {
784            match &field.kind {
785                DrawShaderFieldKind::Uniform {
786                    block_ident,
787                    ..
788                } => {
789                    let uniform_block = uniform_blocks
790                        .entry(*block_ident)
791                        .or_insert(Vec::new());
792                    uniform_block.push((field_index, field.ident));
793                }
794                _ => {}
795            }
796        }
797        uniform_blocks
798    }
799    
800    pub fn add_uniform(&mut self, id: LiveId, block: LiveId, ty: Ty, span: TokenSpan) {
801        self.fields.push(
802            DrawShaderFieldDef {
803                kind: DrawShaderFieldKind::Uniform {
804                    block_ident: Ident(block),
805                    var_def_ptr: None
806                },
807                span,
808                ident: Ident(id),
809                ty_expr: ty.to_ty_expr(),
810            }
811        )
812    }
813    
814    pub fn add_instance(&mut self, id: LiveId, ty: Ty, span: TokenSpan, live_field_kind: LiveFieldKind) {
815        self.fields.push(
816            DrawShaderFieldDef {
817                kind: DrawShaderFieldKind::Instance {
818                    live_field_kind,
819                    is_used_in_pixel_shader: Cell::new(false),
820                    var_def_ptr: None
821                },
822                span,
823                ident: Ident(id),
824                ty_expr: ty.to_ty_expr(),
825            }
826        )
827    }
828    
829    pub fn add_geometry(&mut self, id: LiveId, ty: Ty, span: TokenSpan) {
830        self.fields.push(
831            DrawShaderFieldDef {
832                kind: DrawShaderFieldKind::Geometry {
833                    is_used_in_pixel_shader: Cell::new(false),
834                    var_def_ptr: None
835                },
836                span,
837                ident: Ident(id),
838                ty_expr: ty.to_ty_expr(),
839            }
840        )
841    }
842    
843    
844    pub fn add_texture(&mut self, id: LiveId, ty: Ty, span: TokenSpan) {
845        self.fields.push(
846            DrawShaderFieldDef {
847                kind: DrawShaderFieldKind::Texture {
848                    var_def_ptr: None
849                },
850                span,
851                ident: Ident(id),
852                ty_expr: ty.to_ty_expr(),
853            }
854        )
855    }
856}
857
858impl BinOp {
859    pub fn from_assign_op(token: LiveToken) -> Option<BinOp> {
860        match token {
861            LiveToken::Punct(live_id!( =)) => Some(BinOp::Assign),
862            LiveToken::Punct(live_id!( +=)) => Some(BinOp::AddAssign),
863            LiveToken::Punct(live_id!( -=)) => Some(BinOp::SubAssign),
864            LiveToken::Punct(live_id!( *=)) => Some(BinOp::MulAssign),
865            LiveToken::Punct(live_id!( /=)) => Some(BinOp::DivAssign),
866            _ => None,
867        }
868    }
869    
870    pub fn from_or_op(token: LiveToken) -> Option<BinOp> {
871        match token {
872            LiveToken::Punct(live_id!( ||)) => Some(BinOp::Or),
873            _ => None,
874        }
875    }
876    
877    pub fn from_and_op(token: LiveToken) -> Option<BinOp> {
878        match token {
879            LiveToken::Punct(live_id!( &&)) => Some(BinOp::And),
880            _ => None,
881        }
882    }
883    
884    pub fn from_eq_op(token: LiveToken) -> Option<BinOp> {
885        match token {
886            LiveToken::Punct(live_id!( ==)) => Some(BinOp::Eq),
887            LiveToken::Punct(live_id!( !=)) => Some(BinOp::Ne),
888            _ => None,
889        }
890    }
891    
892    pub fn from_rel_op(token: LiveToken) -> Option<BinOp> {
893        match token {
894            LiveToken::Punct(live_id!(<)) => Some(BinOp::Lt),
895            LiveToken::Punct(live_id!( <=)) => Some(BinOp::Le),
896            LiveToken::Punct(live_id!(>)) => Some(BinOp::Gt),
897            LiveToken::Punct(live_id!( >=)) => Some(BinOp::Ge),
898            _ => None,
899        }
900    }
901    
902    pub fn from_add_op(token: LiveToken) -> Option<BinOp> {
903        match token {
904            LiveToken::Punct(live_id!( +)) => Some(BinOp::Add),
905            LiveToken::Punct(live_id!(-)) => Some(BinOp::Sub),
906            _ => None,
907        }
908    }
909    
910    pub fn from_mul_op(token: LiveToken) -> Option<BinOp> {
911        match token {
912            LiveToken::Punct(live_id!(*)) => Some(BinOp::Mul),
913            LiveToken::Punct(live_id!( /)) => Some(BinOp::Div),
914            _ => None,
915        }
916    }
917}
918
919impl fmt::Display for BinOp {
920    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
921        write!(
922            f,
923            "{}",
924            match self {
925                BinOp::Assign => "=",
926                BinOp::AddAssign => "+=",
927                BinOp::SubAssign => "-=",
928                BinOp::MulAssign => "*=",
929                BinOp::DivAssign => "/=",
930                BinOp::Or => "||",
931                BinOp::And => "&&",
932                BinOp::Eq => "==",
933                BinOp::Ne => "!=",
934                BinOp::Lt => "<",
935                BinOp::Le => "<=",
936                BinOp::Gt => ">",
937                BinOp::Ge => ">=",
938                BinOp::Add => "+",
939                BinOp::Sub => "-",
940                BinOp::Mul => "*",
941                BinOp::Div => "/",
942            }
943        )
944    }
945}
946
947impl UnOp {
948    pub fn from_un_op(token: LiveToken) -> Option<UnOp> {
949        match token {
950            LiveToken::Punct(live_id!(!)) => Some(UnOp::Not),
951            LiveToken::Punct(live_id!(-)) => Some(UnOp::Neg),
952            _ => None,
953        }
954    }
955}
956
957impl fmt::Display for UnOp {
958    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
959        write!(
960            f,
961            "{}",
962            match self {
963                UnOp::Not => "!",
964                UnOp::Neg => "-",
965            }
966        )
967    }
968}
969
970
971impl Ty {
972    
973    pub fn maybe_ty_lit(&self) -> Option<TyLit> {
974        match self {
975            Ty::Void => None,
976            Ty::Bool => Some(TyLit::Bool),
977            Ty::Int => Some(TyLit::Int),
978            Ty::Float => Some(TyLit::Float),
979            Ty::Bvec2 => Some(TyLit::Bvec2),
980            Ty::Bvec3 => Some(TyLit::Bvec3),
981            Ty::Bvec4 => Some(TyLit::Bvec4),
982            Ty::Ivec2 => Some(TyLit::Ivec2),
983            Ty::Ivec3 => Some(TyLit::Ivec3),
984            Ty::Ivec4 => Some(TyLit::Ivec4),
985            Ty::Vec2 => Some(TyLit::Vec2),
986            Ty::Vec3 => Some(TyLit::Vec3),
987            Ty::Vec4 => Some(TyLit::Vec4),
988            Ty::Mat2 => Some(TyLit::Mat2),
989            Ty::Mat3 => Some(TyLit::Mat3),
990            Ty::Mat4 => Some(TyLit::Mat4),
991            Ty::Texture2D => Some(TyLit::Bool),
992            Ty::Array {..} => None,
993            Ty::Struct(_) => None,
994            Ty::Enum(_) => None,
995            Ty::DrawShader(_) => None,
996            Ty::ClosureDecl => None,
997            Ty::ClosureDef {..} => None
998        }
999    }
1000    
1001    pub fn is_scalar(&self) -> bool {
1002        match self {
1003            Ty::Bool | Ty::Int | Ty::Float => true,
1004            _ => false,
1005        }
1006    }
1007    
1008    pub fn is_vector(&self) -> bool {
1009        match self {
1010            Ty::Bvec2
1011                | Ty::Bvec3
1012                | Ty::Bvec4
1013                | Ty::Ivec2
1014                | Ty::Ivec3
1015                | Ty::Ivec4
1016                | Ty::Vec2
1017                | Ty::Vec3
1018                | Ty::Vec4 => true,
1019            _ => false,
1020        }
1021    }
1022    
1023    pub fn is_matrix(&self) -> bool {
1024        match self {
1025            Ty::Mat2 | Ty::Mat3 | Ty::Mat4 => true,
1026            _ => false,
1027        }
1028    }
1029    
1030    pub fn slots(&self) -> usize {
1031        match self {
1032            Ty::Void => 0,
1033            Ty::Bool | Ty::Int | Ty::Float => 1,
1034            Ty::Bvec2 | Ty::Ivec2 | Ty::Vec2 => 2,
1035            Ty::Bvec3 | Ty::Ivec3 | Ty::Vec3 => 3,
1036            Ty::Bvec4 | Ty::Ivec4 | Ty::Vec4 | Ty::Mat2 => 4,
1037            Ty::Mat3 => 9,
1038            Ty::Mat4 => 16,
1039            Ty::Texture2D {..} => panic!(),
1040            Ty::Array {elem_ty, len} => elem_ty.slots() * len,
1041            Ty::Enum(_) => 1,
1042            Ty::Struct(_) => panic!(),
1043            Ty::DrawShader(_) => panic!(),
1044            Ty::ClosureDecl => panic!(),
1045            Ty::ClosureDef {..} => panic!(),
1046        }
1047    }
1048    
1049    pub fn to_ty_expr(&self) -> TyExpr {
1050        TyExpr {
1051            ty: RefCell::new(None),
1052            span: TokenSpan::default(),
1053            kind: match self {
1054                Ty::Void => panic!(),
1055                Ty::Bool => TyExprKind::Lit {ty_lit: TyLit::Bool},
1056                Ty::Int => TyExprKind::Lit {ty_lit: TyLit::Int},
1057                Ty::Float => TyExprKind::Lit {ty_lit: TyLit::Float},
1058                Ty::Bvec2 => TyExprKind::Lit {ty_lit: TyLit::Bvec2},
1059                Ty::Bvec3 => TyExprKind::Lit {ty_lit: TyLit::Bvec3},
1060                Ty::Bvec4 => TyExprKind::Lit {ty_lit: TyLit::Bvec4},
1061                Ty::Ivec2 => TyExprKind::Lit {ty_lit: TyLit::Ivec2},
1062                Ty::Ivec3 => TyExprKind::Lit {ty_lit: TyLit::Ivec3},
1063                Ty::Ivec4 => TyExprKind::Lit {ty_lit: TyLit::Ivec4},
1064                Ty::Vec2 => TyExprKind::Lit {ty_lit: TyLit::Vec2},
1065                Ty::Vec3 => TyExprKind::Lit {ty_lit: TyLit::Vec3},
1066                Ty::Vec4 => TyExprKind::Lit {ty_lit: TyLit::Vec4},
1067                Ty::Mat2 => TyExprKind::Lit {ty_lit: TyLit::Mat2},
1068                Ty::Mat3 => TyExprKind::Lit {ty_lit: TyLit::Mat3},
1069                Ty::Mat4 => TyExprKind::Lit {ty_lit: TyLit::Mat4},
1070                Ty::Texture2D => TyExprKind::Lit {ty_lit: TyLit::Texture2D},
1071                Ty::Array {elem_ty, len} => {
1072                    TyExprKind::Array {
1073                        elem_ty_expr: Box::new(elem_ty.to_ty_expr()),
1074                        len: *len as u32
1075                    }
1076                }
1077                Ty::Struct(struct_node_ptr) => {
1078                    TyExprKind::Struct(*struct_node_ptr)
1079                }
1080                Ty::DrawShader(draw_shader_node_ptr) => {
1081                    TyExprKind::DrawShader(*draw_shader_node_ptr)
1082                },
1083                Ty::Enum(live_type) => {
1084                    TyExprKind::Enum(*live_type)
1085                },
1086                Ty::ClosureDef(_) => panic!(),
1087                Ty::ClosureDecl => panic!()
1088            }
1089        }
1090    }
1091    
1092    pub fn from_live_eval(live_eval: LiveEval) -> Option<Self> {
1093        match live_eval {
1094            LiveEval::Bool(_) => Some(Self::Float),
1095            LiveEval::Int64(_) => Some(Self::Int),
1096            LiveEval::Float64(_) => Some(Self::Float),
1097            LiveEval::Vec2(_) => Some(Self::Vec2),
1098            LiveEval::Vec3(_) => Some(Self::Vec3),
1099            LiveEval::Vec4(_) => Some(Self::Vec4),
1100            _ => None
1101        }
1102    }
1103    
1104    pub fn from_live_node(live_registry: &LiveRegistry, index: usize, nodes: &[LiveNode]) -> Result<Self,
1105    LiveError> {
1106        Ok(match &nodes[index].value {
1107            LiveValue::Expr {..} => {
1108                match live_eval(live_registry, index, &mut (index + 1), nodes) ? {
1109                    LiveEval::Bool(_) => Self::Float,
1110                    LiveEval::Int64(_) => Self::Int,
1111                    LiveEval::Float64(_) => Self::Float,
1112                    LiveEval::Vec2(_) => Self::Vec2,
1113                    LiveEval::Vec3(_) => Self::Vec3,
1114                    LiveEval::Vec4(_) => Self::Vec4,
1115                    v => {
1116                        return Err(LiveError {
1117                            origin: live_error_origin!(),
1118                            message: format!("Expression return type does not resolve to a shader {:?}", v),
1119                            span: nodes[index].origin.token_id().unwrap().into()
1120                        })
1121                    }
1122                }
1123            }
1124            LiveValue::Id(id) => match id {
1125                live_id!(bool) => Self::Bool,
1126                live_id!(int) => Self::Int,
1127                live_id!(float) => Self::Float,
1128                live_id!(vec2) => Self::Vec2,
1129                live_id!(vec3) => Self::Vec3,
1130                live_id!(vec4) => Self::Vec4,
1131                live_id!(texture2d) => Self::Texture2D,
1132                _ => {
1133                    return Err(LiveError {
1134                        origin: live_error_origin!(),
1135                        message: format!("Id does not resolve to a shader type {}", id),
1136                        span: nodes[index].origin.token_id().unwrap().into()
1137                    })
1138                }
1139            }
1140            LiveValue::Bool(_) => Self::Int,
1141            LiveValue::Int64(_) => Self::Int,
1142            LiveValue::Float32(_) => Self::Float,
1143            LiveValue::Float64(_) => Self::Float,
1144            LiveValue::Color(_) => Self::Vec4,
1145            LiveValue::Vec2(_) => Self::Vec2,
1146            LiveValue::Vec3(_) => Self::Vec3,
1147            LiveValue::Vec4(_) => Self::Vec4,
1148            _ => return Err(LiveError {
1149                origin: live_error_origin!(),
1150                message: format!("Live value {:?} does not resolve to a shader type", nodes[index].value),
1151                span: nodes[index].origin.token_id().unwrap().into()
1152            })
1153        })
1154    }
1155}
1156
1157impl fmt::Display for Ty {
1158    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1159        match self {
1160            Ty::Void => write!(f, "void"),
1161            Ty::Bool => write!(f, "bool"),
1162            Ty::Int => write!(f, "int"),
1163            Ty::Float => write!(f, "float"),
1164            Ty::Bvec2 => write!(f, "bvec2"),
1165            Ty::Bvec3 => write!(f, "bvec3"),
1166            Ty::Bvec4 => write!(f, "bvec4"),
1167            Ty::Ivec2 => write!(f, "ivec2"),
1168            Ty::Ivec3 => write!(f, "ivec3"),
1169            Ty::Ivec4 => write!(f, "ivec4"),
1170            Ty::Vec2 => write!(f, "vec2"),
1171            Ty::Vec3 => write!(f, "vec3"),
1172            Ty::Vec4 => write!(f, "vec4"),
1173            Ty::Mat2 => write!(f, "mat2"),
1174            Ty::Mat3 => write!(f, "mat3"),
1175            Ty::Mat4 => write!(f, "mat4"),
1176            Ty::Texture2D => write!(f, "texture2D"),
1177            Ty::Array {elem_ty, len} => write!(f, "{}[{}]", elem_ty, len),
1178            Ty::Struct(struct_ptr) => write!(f, "Struct:{:?}", struct_ptr),
1179            Ty::DrawShader(shader_ptr) => write!(f, "DrawShader:{:?}", shader_ptr),
1180            Ty::Enum(_) => write!(f, "Enum"),
1181            Ty::ClosureDecl => write!(f, "ClosureDecl"),
1182            Ty::ClosureDef {..} => write!(f, "ClosureDef"),
1183        }
1184    }
1185}
1186
1187impl TyLit {
1188    pub fn from_id(id: LiveId) -> Option<TyLit> {
1189        match id {
1190            live_id!(vec4) => Some(TyLit::Vec4),
1191            live_id!(vec3) => Some(TyLit::Vec3),
1192            live_id!(vec2) => Some(TyLit::Vec2),
1193            live_id!(mat4) => Some(TyLit::Mat4),
1194            live_id!(mat3) => Some(TyLit::Mat3),
1195            live_id!(mat2) => Some(TyLit::Mat2),
1196            live_id!(float) => Some(TyLit::Float),
1197            live_id!(bool) => Some(TyLit::Bool),
1198            live_id!(int) => Some(TyLit::Int),
1199            live_id!(bvec2) => Some(TyLit::Bvec2),
1200            live_id!(bvec3) => Some(TyLit::Bvec3),
1201            live_id!(bvec4) => Some(TyLit::Bvec4),
1202            live_id!(ivec2) => Some(TyLit::Ivec4),
1203            live_id!(ivec3) => Some(TyLit::Ivec4),
1204            live_id!(ivec4) => Some(TyLit::Ivec4),
1205            live_id!(texture2D) => Some(TyLit::Texture2D),
1206            _ => None
1207        }
1208    }
1209    
1210    pub fn to_ty(self) -> Ty {
1211        match self {
1212            TyLit::Bool => Ty::Bool,
1213            TyLit::Int => Ty::Int,
1214            TyLit::Float => Ty::Float,
1215            TyLit::Bvec2 => Ty::Bvec2,
1216            TyLit::Bvec3 => Ty::Bvec3,
1217            TyLit::Bvec4 => Ty::Bvec4,
1218            TyLit::Ivec2 => Ty::Ivec2,
1219            TyLit::Ivec3 => Ty::Ivec3,
1220            TyLit::Ivec4 => Ty::Ivec4,
1221            TyLit::Vec2 => Ty::Vec2,
1222            TyLit::Vec3 => Ty::Vec3,
1223            TyLit::Vec4 => Ty::Vec4,
1224            TyLit::Mat2 => Ty::Mat2,
1225            TyLit::Mat3 => Ty::Mat3,
1226            TyLit::Mat4 => Ty::Mat4,
1227            TyLit::Texture2D => Ty::Texture2D,
1228        }
1229    }
1230    
1231}
1232
1233impl fmt::Display for TyLit {
1234    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1235        write!(
1236            f,
1237            "{}",
1238            match self {
1239                TyLit::Bool => "bool",
1240                TyLit::Int => "int",
1241                TyLit::Float => "float",
1242                TyLit::Bvec2 => "bvec2",
1243                TyLit::Bvec3 => "bvec3",
1244                TyLit::Bvec4 => "bvec4",
1245                TyLit::Ivec2 => "ivec2",
1246                TyLit::Ivec3 => "ivec3",
1247                TyLit::Ivec4 => "ivec4",
1248                TyLit::Vec2 => "vec2",
1249                TyLit::Vec3 => "vec3",
1250                TyLit::Vec4 => "vec4",
1251                TyLit::Mat2 => "mat2",
1252                TyLit::Mat3 => "mat3",
1253                TyLit::Mat4 => "mat4",
1254                TyLit::Texture2D => "texture2D",
1255            }
1256        )
1257    }
1258}
1259
1260
1261impl Lit {
1262    pub fn to_ty(self) -> Ty {
1263        match self {
1264            Lit::Bool(_) => Ty::Bool,
1265            Lit::Int(_) => Ty::Int,
1266            Lit::Float(_) => Ty::Float,
1267            Lit::Color(_) => Ty::Vec4
1268        }
1269    }
1270    
1271    pub fn to_val(self) -> Val {
1272        match self {
1273            Lit::Bool(v) => Val::Bool(v),
1274            Lit::Int(v) => Val::Int(v),
1275            Lit::Float(v) => Val::Float(v),
1276            Lit::Color(v) => Val::Vec4(Vec4::from_u32(v))
1277        }
1278    }
1279    
1280    pub fn from_token(token: &LiveToken) -> Option<Lit> {
1281        match token {
1282            LiveToken::Bool(v) => Some(Lit::Bool(*v)),
1283            LiveToken::Int(v) => Some(Lit::Int(*v as i32)),
1284            LiveToken::Float(v) => Some(Lit::Float(*v as f32)),
1285            LiveToken::Color(v) => Some(Lit::Color(*v)),
1286            _ => None
1287        }
1288    }
1289}
1290
1291impl fmt::Display for Lit {
1292    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1293        match self {
1294            Lit::Bool(lit) => write!(f, "{}", lit),
1295            Lit::Int(lit) => write!(f, "{}", lit),
1296            Lit::Float(lit) => write!(f, "{}", PrettyPrintedF32(*lit)),
1297            Lit::Color(lit) => {
1298                let v = Vec4::from_u32(*lit);
1299                write!(
1300                    f,
1301                    "vec4({},{},{},{})",
1302                    PrettyPrintedF32(v.x),
1303                    PrettyPrintedF32(v.y),
1304                    PrettyPrintedF32(v.z),
1305                    PrettyPrintedF32(v.w)
1306                )
1307            }
1308        }
1309    }
1310}
1311
1312
1313impl Ident {
1314    pub fn to_id(self) -> LiveId {self.0}
1315    
1316}
1317
1318impl fmt::Debug for Ident {
1319    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1320        write!(f, "{}", self.0)
1321    }
1322}
1323
1324impl fmt::Display for Ident {
1325    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1326        write!(f, "{}", self.0)
1327    }
1328}
1329
1330#[derive(Clone, Default, Copy, Eq, PartialEq, Hash, PartialOrd, Ord)]
1331pub struct IdentPath {
1332    pub segs: [LiveId; 6],
1333    pub len: usize
1334}
1335
1336impl IdentPath {
1337    
1338    pub fn len(&self) -> usize {
1339        self.len
1340    }
1341    
1342    pub fn push(&mut self, ident: Ident) -> bool {
1343        if self.len >= self.segs.len() {
1344            return false
1345        }
1346        self.segs[self.len] = ident.0;
1347        self.len += 1;
1348        return true
1349    }
1350}
1351
1352impl fmt::Debug for IdentPath {
1353    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1354        for i in 0..self.len {
1355            if i != 0 {
1356                let _ = write!(f, "::").unwrap();
1357            }
1358            let _ = write!(f, "{}", self.segs[i]);
1359        }
1360        Ok(())
1361    }
1362}
1363
1364impl fmt::Display for IdentPath {
1365    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1366        for i in 0..self.len {
1367            if i != 0 {
1368                let _ = write!(f, "::").unwrap();
1369            }
1370            let _ = write!(f, "{}", self.segs[i]);
1371        }
1372        Ok(())
1373    }
1374}
1375
1376impl Val {
1377    pub fn to_bool(&self) -> Option<bool> {
1378        match *self {
1379            Val::Bool(val) => Some(val),
1380            _ => None,
1381        }
1382    }
1383    
1384    pub fn to_int(&self) -> Option<i32> {
1385        match *self {
1386            Val::Int(val) => Some(val),
1387            Val::Float(val) => Some(val as i32),
1388            _ => None,
1389        }
1390    }
1391}
1392
1393impl fmt::Display for Val {
1394    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1395        match *self {
1396            Val::Bool(val) => write!(f, "{}", val),
1397            Val::Int(val) => write!(f, "{}", val),
1398            Val::Float(v) => write!(f, "{}", PrettyPrintedF32(v)),
1399            Val::Vec4(val) => write!(f, "{}", val),
1400        }
1401    }
1402}
1403
1404impl fmt::Display for StructPtr {
1405    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1406        write!(f, "struct_{}", self.0)
1407    }
1408}
1409
1410impl fmt::Display for FnPtr {
1411    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1412        write!(f, "fn_{}", self.0)
1413    }
1414}
1415
1416impl fmt::Display for ValuePtr {
1417    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1418        write!(f, "live_{}", self.0)
1419    }
1420}