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