makepad_shader_compiler/
shader_registry.rs

1use {
2    std::{
3        collections::{BTreeMap, HashSet, HashMap},
4        cell::{Cell, RefCell},
5    },
6    crate::{
7        makepad_error_log::*,
8        makepad_live_compiler::*,
9        makepad_live_id::*,
10        shader_ast::*,
11        analyse::*,
12        shader_parser::{ShaderParser, ShaderParserDep},
13        builtin::{Builtin, generate_builtins},
14    }
15};
16
17
18pub struct ShaderRegistry {
19    pub all_fns: HashMap<FnPtr, FnDef>,
20    pub draw_shader_defs: HashMap<DrawShaderPtr, DrawShaderDef>,
21    pub structs: HashMap<StructPtr, StructDef>,
22    pub builtins: HashMap<Ident, Builtin>,
23    pub enums: HashMap<LiveType, ShaderEnum>,
24}
25
26pub struct ShaderEnum {
27    pub enum_name: LiveId,
28    pub variants: Vec<LiveId>
29}
30
31impl ShaderRegistry {
32    pub fn new() -> Self {
33        Self {
34            structs: HashMap::new(),
35            enums: HashMap::new(),
36            draw_shader_defs: HashMap::new(),
37            all_fns: HashMap::new(),
38            builtins: generate_builtins()
39        }
40    }
41}
42
43#[derive(Debug)]
44pub enum LiveNodeFindResult {
45    NotFound,
46    Component(LivePtr),
47    Struct(StructPtr),
48    Function(FnPtr),
49    PossibleStatic(StructPtr, FnPtr),
50    LiveValue(ValuePtr, TyLit),
51    Error(LiveError)
52}
53
54pub enum DrawShaderQuery {
55    DrawShader,
56    Geometry,
57}
58
59impl ShaderRegistry {
60    
61    pub fn flush_registry(&mut self){
62        self.all_fns.clear();
63        self.draw_shader_defs.clear();
64        self.structs.clear();
65    }
66    
67    pub fn register_enum(&mut self, live_type: LiveType, shader_enum: ShaderEnum) {
68        self.enums.insert(live_type, shader_enum);
69    }
70    
71    pub fn compute_const_table(&self, draw_shader_ptr: DrawShaderPtr/*, filter_file_id: LiveFileId*/) -> DrawShaderConstTable {
72        
73        let draw_shader_def = self.draw_shader_defs.get(&draw_shader_ptr).unwrap();
74        
75        let mut offsets = BTreeMap::new();
76        let mut table = Vec::new();
77        let mut offset = 0;
78        let mut table_index = BTreeMap::new();
79        
80        for callee in draw_shader_def.all_fns.borrow().iter() {
81            let fn_decl = self.all_fns.get(callee).unwrap();
82            //if fn_decl.span.file_id == filter_file_id {
83            let sub_table = fn_decl.const_table.borrow();
84            table.extend(sub_table.as_ref().unwrap().iter());
85            
86            for ct_span in fn_decl.const_table_spans.borrow().as_ref().unwrap().iter() {
87                table_index.insert(
88                    ct_span.token_id,
89                    ConstTableItem {
90                        offset: offset + ct_span.offset,
91                        slots: ct_span.slots
92                    }
93                );
94            }
95            offsets.insert(*callee, offset);
96            offset += sub_table.as_ref().unwrap().len();
97        }
98        
99        let size = table.len();
100        let align_gap = 4 - (size - ((size >> 2) << 2));
101        for _ in 0..align_gap {
102            table.push(0.0);
103        }
104        DrawShaderConstTable {
105            table,
106            offsets,
107            table_index
108        }
109    }
110    
111    pub fn fn_ident_from_ptr(&self, live_registry: &LiveRegistry, fn_node_ptr: FnPtr) -> Ident {
112        let node = live_registry.ptr_to_node(fn_node_ptr.0);
113        Ident(node.id)
114    }
115    
116    pub fn draw_shader_method_ptr_from_ident(&self, draw_shader_def: &DrawShaderDef, ident: Ident) -> Option<FnPtr> {
117        for fn_node_ptr in &draw_shader_def.methods {
118            let fn_decl = self.all_fns.get(fn_node_ptr).unwrap();
119            if fn_decl.ident == ident {
120                return Some(*fn_node_ptr);
121            }
122        }
123        None
124    }
125    
126    pub fn struct_method_ptr_from_ident(&self, struct_def: &StructDef, ident: Ident) -> Option<FnPtr> {
127        for fn_node_ptr in &struct_def.methods {
128            let fn_decl = self.all_fns.get(fn_node_ptr).unwrap();
129            if fn_decl.ident == ident {
130                return Some(*fn_node_ptr);
131            }
132        }
133        None
134    }
135    
136    pub fn draw_shader_method_decl_from_ident(&self, draw_shader_def: &DrawShaderDef, ident: Ident) -> Option<&FnDef> {
137        for fn_node_ptr in &draw_shader_def.methods {
138            let fn_decl = self.all_fns.get(fn_node_ptr).unwrap();
139            if fn_decl.ident == ident {
140                return Some(fn_decl)
141            }
142        }
143        None
144    }
145    
146    pub fn struct_method_decl_from_ident(&self, struct_def: &StructDef, ident: Ident) -> Option<&FnDef> {
147        for fn_node_ptr in &struct_def.methods {
148            let fn_decl = self.all_fns.get(fn_node_ptr).unwrap();
149            if fn_decl.ident == ident {
150                return Some(fn_decl)
151            }
152        }
153        None
154    }
155    
156    pub fn find_live_node_by_path(&self, live_registry: &LiveRegistry, base_ptr: LivePtr, ids: &[LiveId]) -> LiveNodeFindResult {
157        
158        let doc = &live_registry.ptr_to_doc(base_ptr);
159        
160        let ret = walk_recur(live_registry, None, base_ptr.file_id, base_ptr.generation, base_ptr.index as usize, &doc.nodes, ids);
161        return ret;
162        // ok so we got a node. great. now what
163        fn walk_recur(live_registry: &LiveRegistry, struct_ptr: Option<LivePtr>, file_id: LiveFileId, generation:LiveFileGeneration, index: usize, nodes: &[LiveNode], ids: &[LiveId]) -> LiveNodeFindResult {
164            let node = &nodes[index];
165            
166            if ids.len() != 0 && !node.value.is_class() && !node.value.is_clone() && !node.value.is_object() {
167                return LiveNodeFindResult::NotFound;
168            }
169            
170            let now_ptr = LivePtr {file_id, index: index as u32, generation};
171            //let first_def = node.origin.first_def().unwrap();
172            match node.value {
173                LiveValue::Bool(_) => {
174                    return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), TyLit::Bool)
175                },
176                LiveValue::Int64(_)=> {
177                    return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), TyLit::Int)
178                }
179                LiveValue::Float32(_)  => {
180                    return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), TyLit::Float)
181                }
182                LiveValue::Float64(_)  => {
183                    return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), TyLit::Float)
184                }
185                LiveValue::Color(_)  => {
186                    return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), TyLit::Vec4)
187                }
188                LiveValue::Vec2(_)  => {
189                    return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), TyLit::Vec2)
190                }
191                LiveValue::Vec3(_)  => {
192                    return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), TyLit::Vec3)
193                }
194                LiveValue::Vec4(_) => {
195                    return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), TyLit::Vec4)
196                }
197                LiveValue::Expr{..} => {
198                    // ok lets eval the expr to get a type
199                    match live_eval(live_registry, index, &mut (index + 1), nodes){
200                        Ok(value) => {
201                            if let Some(ty) = Ty::from_live_eval(value){
202                                if let Some(ty_lit) = ty.maybe_ty_lit(){
203                                    return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), ty_lit)
204                                }
205                            }
206                            return LiveNodeFindResult::Error(
207                                LiveError {
208                                    origin: live_error_origin!(),
209                                    message: format!("Type of eval result not valid for shader"),
210                                    span: nodes[index].origin.token_id().unwrap().into()
211                                }
212                            );
213                        }
214                        Err(err)=>{
215                            error!("Cannot find node in expression");
216                            return LiveNodeFindResult::Error(err)
217                        }
218                    }
219                }
220                LiveValue::DSL {token_start, ..} => {
221                    // lets get the first token
222                    let origin_doc = live_registry.token_id_to_origin_doc(node.origin.token_id().unwrap());
223                    match origin_doc.tokens[token_start as usize].token {
224                        LiveToken::Ident(live_id!(fn)) => {
225                            if let Some(struct_ptr) = struct_ptr {
226                                return LiveNodeFindResult::PossibleStatic(StructPtr(struct_ptr), FnPtr(now_ptr));
227                            }
228                            return LiveNodeFindResult::Function(FnPtr(now_ptr));
229                        }
230                        _ => LiveNodeFindResult::NotFound
231                    }
232                }
233                LiveValue::Class {..} => {
234                    if ids.len() == 0 {
235                        return LiveNodeFindResult::Component(now_ptr);
236                    }
237                    match nodes.child_by_name(index, ids[0].as_instance()) {
238                        Some(child_index) => {
239                            return walk_recur(live_registry, None, file_id, generation, child_index, nodes, &ids[1..])
240                        }
241                        None => {
242                            return LiveNodeFindResult::NotFound;
243                        }
244                    }
245                }
246                LiveValue::Clone(clone) => {
247                    if ids.len() == 0 {
248                        if clone == live_id!(struct) {
249                            return LiveNodeFindResult::Struct(StructPtr(now_ptr));
250                        }
251                        return LiveNodeFindResult::Component(now_ptr);
252                    }
253                    match nodes.child_by_name(index, ids[0].as_instance()) {
254                        Some(child_index) => {
255                            let struct_ptr = if clone == live_id!(struct) {
256                                Some(now_ptr)
257                            }
258                            else {
259                                None
260                            };
261                            return walk_recur(live_registry, struct_ptr, file_id,  generation, child_index, nodes, &ids[1..])
262                        }
263                        None => {
264                            return LiveNodeFindResult::NotFound;
265                        }
266                    }
267                }
268                LiveValue::Object => {
269                    if ids.len() == 0 {
270                        return LiveNodeFindResult::NotFound;
271                    }
272                    match nodes.child_by_name(index, ids[0].as_instance()) {
273                        Some(child_index) => {
274                            return walk_recur(live_registry, None, file_id,  generation,  child_index, nodes, &ids[1..])
275                        }
276                        None => {
277                            return LiveNodeFindResult::NotFound;
278                        }
279                    }
280                }
281                _ => {
282                    return LiveNodeFindResult::NotFound;
283                }
284            }
285        }
286    }
287    
288    pub fn analyse_deps(&mut self, live_registry: &LiveRegistry, deps: &[ShaderParserDep]) -> Result<(), LiveError> {
289        // recur on used types
290        for dep in deps {
291            match dep {
292                /*ShaderParserDep::Const(dep) => {
293                    self.analyse_const(live_registry, *dep) ?;
294                },*/
295                ShaderParserDep::Struct(dep) => {
296                    self.analyse_struct(live_registry, *dep) ?;
297                },
298                ShaderParserDep::Function(struct_ptr, fn_ptr) => {
299                    self.analyse_plain_fn(live_registry, *struct_ptr, *fn_ptr) ?
300                }
301            }
302        }
303        Ok(())
304    }
305    
306    
307    // lets compile the thing
308    pub fn analyse_plain_fn(&mut self, live_registry: &LiveRegistry, struct_ptr: Option<StructPtr>, fn_ptr: FnPtr) -> Result<(), LiveError> {
309        
310        if self.all_fns.get(&fn_ptr).is_some() {
311            return Ok(());
312        }
313        // alright lets parse and analyse a plain fn
314        let fn_node = live_registry.ptr_to_node(fn_ptr.0);
315        match fn_node.value {
316            LiveValue::DSL {token_start, token_count, expand_index} => {
317                let id = fn_node.id;
318                let mut parser_deps = Vec::new();
319                // lets parse this thing
320                let origin_doc = &live_registry.token_id_to_origin_doc(fn_node.origin.token_id().unwrap());
321                
322                let parser = ShaderParser::new(
323                    live_registry,
324                    self,
325                    origin_doc.get_tokens(token_start as usize, token_count as usize),
326                    &mut parser_deps,
327                    if let Some(struct_ptr) = struct_ptr {Some(FnSelfKind::Struct(struct_ptr))}else {None},
328                    expand_index.unwrap() as usize,
329                    fn_node.origin.token_id().unwrap().file_id().unwrap(),
330                    token_start as usize
331                    //Some(struct_full_ptr)
332                );
333                
334                let fn_def = parser.expect_plain_fn_def(
335                    fn_ptr,
336                    Ident(id),
337                ) ?;
338                self.all_fns.insert(fn_ptr, fn_def);
339                
340                self.analyse_deps(live_registry, &parser_deps) ?;
341                
342                // ok analyse the struct methods now.
343                let mut fa = FnDefAnalyser {
344                    live_registry,
345                    closure_return_ty: None,
346                    fn_def: self.all_fns.get(&fn_ptr).unwrap(),
347                    scopes: &mut Scopes::new(),
348                    shader_registry: self,
349                    is_inside_loop: false,
350                    options: ShaderAnalyseOptions {
351                        no_const_collapse: true
352                    }
353                };
354                fa.analyse_fn_decl() ?;
355                fa.analyse_fn_def() ?;
356                
357                Ok(())
358            }
359            _ => panic!()
360        }
361    }
362    
363    
364    // lets compile the thing
365    pub fn analyse_struct(&mut self, live_registry: &LiveRegistry, struct_ptr: StructPtr) -> Result<(), LiveError> {
366        
367        if self.structs.get(&struct_ptr).is_some() {
368            return Ok(());
369        }
370        
371        let (doc, struct_node) = live_registry.ptr_to_doc_node(struct_ptr.0);
372        
373        match struct_node.value {
374            LiveValue::Clone(clone) => {
375                if clone != live_id!(struct) {
376                    panic!()
377                }
378                let mut struct_def = StructDef {
379                    span: struct_node.origin.token_id().unwrap().into(),
380                    struct_refs: RefCell::new(None),
381                    fields: Vec::new(),
382                    methods: Vec::new()
383                };
384                
385                let mut parser_deps = Vec::new();
386                
387                // ok how do we iterate children of this node
388                let mut node_iter = doc.nodes.first_child(struct_ptr.node_index());
389                while let Some(node_index) = node_iter {
390                    let prop_ptr = struct_ptr.with_index(node_index);
391                    let prop = &doc.nodes[node_index];
392                    
393                    match prop.value {
394                        LiveValue::DSL {token_start, token_count, expand_index} => {
395                            let id = prop.id;
396                            let origin_doc = &live_registry.token_id_to_origin_doc(prop.origin.token_id().unwrap());
397                            
398                            let parser = ShaderParser::new(
399                                live_registry,
400                                self,
401                                origin_doc.get_tokens(token_start as usize, token_count as usize),
402                                &mut parser_deps,
403                                Some(FnSelfKind::Struct(struct_ptr)),
404                                expand_index.unwrap() as usize,
405                                prop.origin.token_id().unwrap().file_id().unwrap(),
406                                token_start as usize
407                                //Some(struct_full_ptr)
408                            );
409                            match origin_doc.tokens[token_start as usize].token {
410                                LiveToken::Ident(live_id!(fn)) => {
411                                    
412                                    let fn_def = parser.expect_method_def(
413                                        FnPtr(prop_ptr),
414                                        Ident(id),
415                                    ) ?;
416                                    // if we get false, this was not a method but could be static.
417                                    // statics need a pointer to their struct to resolve Self
418                                    // so we can't treat them purely as loose methods
419                                    if let Some(fn_def) = fn_def {
420                                        struct_def.methods.push(fn_def.fn_ptr);
421                                        self.all_fns.insert(fn_def.fn_ptr, fn_def);
422                                    }
423                                }
424                                _ => {
425                                    return Err(LiveError {
426                                        origin: live_error_origin!(),
427                                        span: prop.origin.token_id().unwrap().into(),
428                                        message: format!("Unexpected DSL node")
429                                    })
430                                    /*
431                                    let def = parser.expect_field(Ident(id), VarDefPtr(prop_ptr)) ?;
432                                    if let Some(def) = def {
433                                        struct_def.fields.push(def);
434                                    }*/
435                                }
436                            }
437                        },
438                        LiveValue::Id(type_name) if live_registry.get_node_prefix(prop.origin) == Some(live_id!(field)) => {
439                            // lets fetch the span
440                            
441                            if let Some(ty_lit) = TyLit::from_id(type_name) {
442                                struct_def.fields.push(StructFieldDef {
443                                    var_def_ptr: VarDefPtr(prop_ptr),
444                                    span:prop.origin.token_id().unwrap().into(),
445                                    ident: Ident(prop.id),
446                                    ty_expr: ty_lit.to_ty().to_ty_expr()
447                                })
448                            }
449                            else {
450                                // TODO support structs as fields here
451                                return Err(LiveError {
452                                    origin: live_error_origin!(),
453                                    span: prop.origin.token_id().unwrap().into(),
454                                    message: format!("Type not found for struct field {}", type_name)
455                                })
456                            }
457                        },
458                        _ => {
459                            return Err(LiveError {
460                                origin: live_error_origin!(),
461                                span: prop.origin.token_id().unwrap().into(),
462                                message: format!("Cannot use {:?} in struct", prop.value)
463                            })
464                        }
465                    }
466                    node_iter = doc.nodes.next_child(node_index);
467                }
468                // we should store the structs
469                self.structs.insert(struct_ptr, struct_def);
470                
471                self.analyse_deps(live_registry, &parser_deps) ?;
472                
473                // ok analyse the struct methods now.
474                let mut sa = StructAnalyser {
475                    live_registry,
476                    struct_def: self.structs.get(&struct_ptr).unwrap(),
477                    scopes: &mut Scopes::new(),
478                    shader_registry: self,
479                    options: ShaderAnalyseOptions {
480                        no_const_collapse: true
481                    }
482                };
483                sa.analyse_struct() ?;
484                //println!("STRUCT");
485                
486            }
487            _ => ()
488        }
489        
490        Ok(())
491    }
492    
493    // lets compile the thing
494    pub fn analyse_draw_shader<F>(&mut self, live_registry: &LiveRegistry, draw_shader_ptr: DrawShaderPtr, mut ext_self: F) -> Result<(),
495        LiveError>
496    where F: FnMut(&LiveRegistry, &ShaderRegistry, TokenSpan, DrawShaderQuery, LiveType, &mut DrawShaderDef)
497    {
498        let mut draw_shader_def = DrawShaderDef::default();
499        
500        // lets insert the 2D drawshader uniforms
501        draw_shader_def.add_uniform(id_lut!(camera_projection), id_lut!(pass), Ty::Mat4, TokenSpan::default());
502        draw_shader_def.add_uniform(id_lut!(camera_view), id_lut!(pass), Ty::Mat4, TokenSpan::default());
503        draw_shader_def.add_uniform(id_lut!(camera_inv), id_lut!(pass), Ty::Mat4, TokenSpan::default());
504        draw_shader_def.add_uniform(id_lut!(dpi_factor), id_lut!(pass), Ty::Float, TokenSpan::default());
505        draw_shader_def.add_uniform(id_lut!(dpi_dilate), id_lut!(pass), Ty::Float, TokenSpan::default());
506        draw_shader_def.add_uniform(id_lut!(time), id_lut!(pass), Ty::Float, TokenSpan::default());
507        draw_shader_def.add_uniform(id_lut!(view_transform), id_lut!(view), Ty::Mat4, TokenSpan::default());
508        draw_shader_def.add_uniform(id_lut!(draw_zbias), id_lut!(draw), Ty::Float, TokenSpan::default());
509        
510        let (doc, class_node) = live_registry.ptr_to_doc_node(draw_shader_ptr.0);
511
512        match &class_node.value {
513            LiveValue::Class {live_type, ..} => {
514                
515                ext_self(
516                    live_registry,
517                    self,
518                    class_node.origin.token_id().unwrap().into(),
519                    DrawShaderQuery::DrawShader,
520                    *live_type,
521                    &mut draw_shader_def
522                );
523                
524                let mut parser_deps = Vec::new();
525                
526                let mut node_iter = doc.nodes.first_child(draw_shader_ptr.node_index());
527                let mut method_set = HashSet::new();
528                while let Some(node_index) = node_iter {
529                    let prop = &doc.nodes[node_index];
530                    let prop_ptr = draw_shader_ptr.with_index(node_index);
531                    if prop.id == live_id!(debug_id){
532                        node_iter = doc.nodes.next_child(node_index);
533                        continue;
534                    }
535                    match prop.value {
536                        LiveValue::Bool(_) |
537                        LiveValue::Id(_)  |
538                        LiveValue::Int64(_) |
539                        LiveValue::Float32(_) |
540                        LiveValue::Float64(_) |
541                        LiveValue::Color(_) |
542                        LiveValue::Vec2(_) |
543                        LiveValue::Vec3(_) |
544                        LiveValue::Vec4(_) | 
545                        LiveValue::Expr{..} => {
546                            //let before = live_registry.get_node_prefix(prop.origin);
547                            if prop.origin.prop_type() != LivePropType::Field{
548                                /*if before == Some(live_id!(const)){
549                                    node_iter = doc.nodes.next_child(node_index);
550                                    continue;
551                                }*/
552                                return Err(LiveError {
553                                    origin: live_error_origin!(),
554                                    span: prop.origin.token_id().unwrap().into(),
555                                    message: format!("Can only support field colon : values don't use =")
556                                })
557                            }
558                            if prop.id == live_id!(size){
559                                
560                            }
561                            let first_def = prop.origin.first_def().unwrap();
562                            let before = live_registry.get_node_prefix(prop.origin);
563                           
564                            let ty = match ShaderTy::from_live_node(live_registry, node_index, &doc.nodes){
565                                Ok(ty)=>ty,
566                                Err(_)=>{
567                                    // just ignore it
568                                    node_iter = doc.nodes.next_child(node_index);
569                                    continue;
570                                    //return Err(err)
571                                }
572                            };
573                            let ty_expr = ty.to_ty_expr();
574                            match before {
575                                Some(live_id!(geometry)) => {
576                                    draw_shader_def.fields.push(DrawShaderFieldDef {
577                                        kind: DrawShaderFieldKind::Geometry {
578                                            is_used_in_pixel_shader: Cell::new(false),
579                                            var_def_ptr: Some(VarDefPtr(prop_ptr)),
580                                        },
581                                        span: first_def.into(),
582                                        ident: Ident(prop.id),
583                                        ty_expr
584                                    });
585                                },
586                                Some(live_id!(instance)) => {
587                                    let decl = DrawShaderFieldDef {
588                                        kind: DrawShaderFieldKind::Instance {
589                                            is_used_in_pixel_shader: Cell::new(false),
590                                            live_field_kind: LiveFieldKind::Live,
591                                            var_def_ptr: Some(VarDefPtr(prop_ptr)),
592                                        },
593                                        span: first_def.into(),
594                                        ident: Ident(prop.id),
595                                        ty_expr
596                                    };
597                                    // find from the start the first instancefield
598                                    // without a var_def_node_prt
599                                    if let Some(index) = draw_shader_def.fields.iter().position( | field | {
600                                        if let DrawShaderFieldKind::Instance {var_def_ptr, ..} = field.kind {
601                                            if var_def_ptr.is_none() {
602                                                return true
603                                            }
604                                        }
605                                        false
606                                    }) {
607                                        draw_shader_def.fields.insert(index, decl);
608                                    }
609                                    else {
610                                        draw_shader_def.fields.push(decl);
611                                    }
612                                    
613                                },
614                                Some(live_id!(uniform)) => {
615                                    draw_shader_def.fields.push(DrawShaderFieldDef {
616                                        kind: DrawShaderFieldKind::Uniform {
617                                            var_def_ptr: Some(VarDefPtr(prop_ptr)),
618                                            block_ident: Ident(live_id!(user)),
619                                        },
620                                        span: first_def.into(),
621                                        ident: Ident(prop.id),
622                                        ty_expr
623                                    });
624                                },
625                                Some(live_id!(varying)) => {
626                                    draw_shader_def.fields.push(DrawShaderFieldDef {
627                                        kind: DrawShaderFieldKind::Varying {
628                                            var_def_ptr: VarDefPtr(prop_ptr),
629                                        },
630                                        span: first_def.into(),
631                                        ident: Ident(prop.id),
632                                        ty_expr
633                                    });
634                                },
635                                Some(live_id!(texture)) => {
636                                    draw_shader_def.fields.push(DrawShaderFieldDef {
637                                        kind: DrawShaderFieldKind::Texture {
638                                            var_def_ptr: Some(VarDefPtr(prop_ptr)),
639                                        },
640                                        span: first_def.into(),
641                                        ident: Ident(prop.id),
642                                        ty_expr
643                                    });
644                                }
645                                None => {
646                                    if let LiveValue::Bool(val) = prop.value {
647                                        match prop.id {
648                                            live_id!(debug) => {
649                                                draw_shader_def.flags.debug = val;
650                                            }
651                                            live_id!(draw_call_compare) => {
652                                                draw_shader_def.flags.draw_call_nocompare = val;
653                                            }
654                                            live_id!(draw_call_always) => {
655                                                draw_shader_def.flags.draw_call_always = val;
656                                            }
657                                            _ => {} // could be input value
658                                        }
659                                    }
660                                },
661                                _ => {
662                                    return Err(LiveError {
663                                        origin: live_error_origin!(),
664                                        span: first_def.into(),
665                                        message: format!("Unexpected variable prefix {:?}", before)
666                                    })
667                                }
668                            };
669                        }
670                        LiveValue::Class {live_type, ..} => {
671                            if prop.id == live_id!(geometry) {
672                                ext_self(
673                                    live_registry,
674                                    self,
675                                    prop.origin.token_id().unwrap().into(),
676                                    DrawShaderQuery::Geometry,
677                                    live_type,
678                                    &mut draw_shader_def
679                                );
680                            }
681                        }
682                        LiveValue::DSL {token_start, token_count, expand_index} => {
683                            let origin_doc = live_registry.token_id_to_origin_doc(prop.origin.token_id().unwrap());
684                            
685                            let parser = ShaderParser::new(
686                                live_registry,
687                                self,
688                                origin_doc.get_tokens(token_start as usize, token_count as usize),
689                                &mut parser_deps,
690                                Some(FnSelfKind::DrawShader(draw_shader_ptr)),
691                                expand_index.unwrap() as usize,
692                                prop.origin.token_id().unwrap().file_id().unwrap(),
693                                token_start as usize
694                                //None
695                            );
696                            
697                            let token = &origin_doc.tokens[token_start as usize];
698                            match token.token {
699                                LiveToken::Ident(live_id!(fn)) => {
700                                    let fn_def = parser.expect_method_def(
701                                        FnPtr(prop_ptr),
702                                        Ident(prop.id),
703                                    ) ?;
704                                    if let Some(fn_def) = fn_def {
705                                        method_set.insert(prop.id);
706                                        draw_shader_def.methods.push(fn_def.fn_ptr);
707                                        self.all_fns.insert(fn_def.fn_ptr, fn_def);
708                                    }
709                                }
710                                _ => {
711                                    return Err(LiveError {
712                                        origin: live_error_origin!(),
713                                        span: token.span.into(),
714                                        message: format!("Unexpected in shader body {}", token)
715                                    })
716                                    /*
717                                    let decl = parser.expect_self_decl(Ident(prop.id), prop_ptr) ?;
718                                    if let Some(decl) = decl {
719                                        // lets see where to inject this.
720                                        // if its an instance var it needs to
721                                        // go above the var_def_node_ptr one
722                                        if let DrawShaderFieldKind::Instance {..} = decl.kind {
723                                            // find from the start the first instancefield
724                                            // without a var_def_node_prt
725                                            if let Some(index) = draw_shader_def.fields.iter().position( | field | {
726                                                if let DrawShaderFieldKind::Instance {var_def_ptr, ..} = field.kind {
727                                                    if var_def_ptr.is_none() {
728                                                        return true
729                                                    }
730                                                }
731                                                false
732                                            }) {
733                                                draw_shader_def.fields.insert(index, decl);
734                                            }
735                                            else {
736                                                draw_shader_def.fields.push(decl);
737                                            }
738                                        }
739                                        else {
740                                            draw_shader_def.fields.push(decl);
741                                        }
742                                    }*/
743                                }
744                            }
745                            
746                        },
747                        _ => ()
748                    }
749                    node_iter = doc.nodes.next_child(node_index);
750                }
751                // lets check for duplicate fields
752                for i in 0..draw_shader_def.fields.len() {
753                    for j in (i + 1)..draw_shader_def.fields.len() {
754                        let field_a = &draw_shader_def.fields[i];
755                        let field_b = &draw_shader_def.fields[j];
756                        if field_a.ident == field_b.ident && !field_a.ident.0.is_empty() {
757                            //let doc = live_registry.ptr_to_doc(draw_shader_ptr.0);
758                            //doc.nodes.to_string(draw_shader_ptr.index as usize,100)
759                            
760                            return Err(LiveError {
761                                origin: live_error_origin!(),
762                                span: field_a.span.into(),
763                                message: format!("Field double declaration  {}",field_a.ident)
764                            })
765                        }
766                    }
767                }
768                
769                self.draw_shader_defs.insert(draw_shader_ptr, draw_shader_def);
770                
771                if !method_set.contains(&live_id!(vertex)) {
772                    return Err(LiveError {
773                        origin: live_error_origin!(),
774                        span: class_node.origin.token_id().unwrap().into(),
775                        message: format!("analyse_draw_shader missing vertex method")
776                    })
777                }
778                
779                if !method_set.contains(&live_id!(pixel)) {
780                    return Err(LiveError {
781                        origin: live_error_origin!(),
782                        span: class_node.origin.token_id().unwrap().into(),
783                        message: format!("analyse_draw_shader missing pixel method")
784                    })
785                }
786                
787                self.analyse_deps(live_registry, &parser_deps) ?;
788                
789                let draw_shader_def = self.draw_shader_defs.get(&draw_shader_ptr).unwrap();
790                let mut sa = DrawShaderAnalyser {
791                    live_registry,
792                    shader_registry: self,
793                    draw_shader_def: draw_shader_def,
794                    scopes: &mut Scopes::new(),
795                    options: ShaderAnalyseOptions {
796                        no_const_collapse: true
797                    }
798                };
799                sa.analyse_shader() ?;
800                // ok we have all structs
801                return Ok(())
802            }
803            x => return Err(LiveError {
804                origin: live_error_origin!(),
805                span: class_node.origin.token_id().unwrap().into(),
806                message: format!("analyse_draw_shader could not find shader class {:?}", x)
807            })
808        }
809    }
810    
811}