makepad_render/
shadergen.rs

1// Shared shader-compiler code for generating GLSL and Metal shading language
2
3use std::hash::{Hash, Hasher};
4use crate::shader::*;
5
6#[derive(Default, Clone, PartialEq)]
7pub struct ShaderGen {
8    pub log: i32,
9    pub name: String,
10    pub geometry_vertices: Vec<f32>,
11    pub geometry_indices: Vec<u32>,
12    pub asts: Vec<ShAst>,
13}
14
15impl Eq for ShaderGen {}
16
17impl Hash for ShaderGen {
18    fn hash<H: Hasher>(&self, state: &mut H) {
19        self.log.hash(state);
20        self.name.hash(state);
21        self.geometry_indices.hash(state);
22        for vertex in &self.geometry_vertices {
23            vertex.to_bits().hash(state);
24        }
25        self.asts.hash(state);
26    }
27}
28
29impl ShaderGen {
30    pub fn new() -> Self {
31        let sg = ShaderGen::default();
32        let sg = CxShader::def_builtins(sg);
33        let sg = CxShader::def_df(sg);
34        let sg = CxPass::def_uniforms(sg);
35        let sg = CxView::def_uniforms(sg);
36        sg
37    }
38    
39    pub fn compose(mut self, ast: ShAst) -> Self {
40        self.asts.push(ast);
41        self
42    }
43    
44    // flatten our
45    pub fn flat_vars<F>(&self, cb:F) -> Vec<ShVar> 
46    where F: Fn(&ShVarStore)->bool{
47        let mut ret = Vec::new();
48        for ast in self.asts.iter() {
49            for shvar in &ast.vars {
50                if cb(&shvar.store){
51                    ret.push(shvar.clone());
52                }
53            }
54        }
55        ret
56    }
57    
58    // flatten our
59    pub fn flat_consts(&self) -> Vec<ShConst> {
60        let mut ret = Vec::new();
61        for ast in self.asts.iter().rev() {
62            for shconst in &ast.consts {
63                ret.push(shconst.clone());
64            }
65        };
66        ret
67    }
68    
69    // find a function
70    pub fn find_fn(&self, name: &str) -> Option<&ShFn> {
71        for ast in self.asts.iter().rev() {
72            for shfn in &ast.fns {
73                if shfn.name == name {
74                    return Some(&shfn)
75                }
76            }
77        }
78        None
79    }
80    
81    pub fn find_var(&self, name: &str) -> Option<&ShVar> {
82        for ast in self.asts.iter().rev() {
83            for shvar in &ast.vars {
84                if shvar.name == name {
85                    return Some(&shvar)
86                }
87            }
88        }
89        None
90    }
91    
92    pub fn find_const(&self, name: &str) -> Option<&ShConst> {
93        for ast in self.asts.iter().rev() {
94            for shconst in &ast.consts {
95                if shconst.name == name {
96                    return Some(&shconst)
97                }
98            }
99        }
100        None
101    }
102    
103    pub fn find_type(&self, name: &str) -> Option<&ShType> {
104        for ast in self.asts.iter().rev() {
105            for shtype in &ast.types {
106                if shtype.name == name {
107                    return Some(&shtype)
108                }
109            }
110        }
111        None
112    }
113    
114    pub fn get_type_slots(&self, name: &str) -> usize {
115        if let Some(ty) = self.find_type(name) {
116            return ty.slots;
117        }
118        0
119    }
120    
121    pub fn compute_slot_total(&self, vars: &Vec<ShVar>) -> usize {
122        let mut slots: usize = 0;
123        for var in vars {
124            slots += self.get_type_slots(&var.ty);
125        }
126        slots
127    }
128}
129
130
131// The AST block
132#[derive(Clone, Hash, PartialEq)]
133pub struct ShAst {
134    pub types: Vec<ShType>,
135    pub vars: Vec<ShVar>,
136    pub consts: Vec<ShConst>,
137    pub fns: Vec<ShFn>
138}
139
140#[derive(Clone, Hash, PartialEq)]
141pub struct ShFnArg {
142    pub name: String,
143    pub ty: String
144}
145
146
147#[inline(never)]
148pub fn sh_fnarg(name:&str, ty:&str)->ShFnArg{
149    ShFnArg{
150        name:name.to_string(),
151        ty:ty.to_string()
152    }
153}
154
155impl ShFnArg {
156    pub fn new(name: &str, ty: &str) -> Self {
157        Self {
158            name: name.to_string(),
159            ty: ty.to_string()
160        }
161    }
162}
163
164#[derive(Clone, Hash, PartialEq)]
165pub struct ShFn {
166    pub name: String,
167    pub args: Vec<ShFnArg>,
168    pub ret: String,
169    pub block: Option<ShBlock>,
170}
171
172#[inline(never)]
173pub fn sh_fn(name:&str, args:&[ShFnArg], ret:&str, block:Option<ShBlock>)->ShFn{
174    ShFn{
175        name:name.to_string(),
176        args:args.to_vec(),
177        ret:ret.to_string(),
178        block:block
179    }
180    
181}
182
183#[derive(Clone, Hash, PartialEq)]
184pub enum UniformType {
185    Color(UniformColor),
186    Vec4(UniformVec4),
187    Vec3(UniformVec3),
188    Vec2(UniformVec2),
189    Float(UniformFloat)
190}
191
192impl UniformType{
193    fn type_name(&self)->String{
194        match self{
195            UniformType::Color(_)=>"vec4".to_string(),
196            UniformType::Vec4(_)=>"vec4".to_string(),
197            UniformType::Vec3(_)=>"vec3".to_string(),
198            UniformType::Vec2(_)=>"vec2".to_string(),
199            UniformType::Float(_)=>"float".to_string(),
200        }
201    }
202}
203
204#[derive(Clone, Hash, PartialEq)]
205pub enum InstanceType {
206    Color(InstanceColor),
207    Vec4(InstanceVec4),
208    Vec3(InstanceVec3),
209    Vec2(InstanceVec2),
210    Float(InstanceFloat)
211}
212
213impl InstanceType{
214    fn type_name(&self)->String{
215        match self{
216            InstanceType::Color(_)=>"vec4".to_string(),
217            InstanceType::Vec4(_)=>"vec4".to_string(),
218            InstanceType::Vec3(_)=>"vec3".to_string(),
219            InstanceType::Vec2(_)=>"vec2".to_string(),
220            InstanceType::Float(_)=>"float".to_string(),
221        }
222    }
223}
224
225#[derive(Clone, Hash, PartialEq)]
226pub enum ShVarStore {
227    Uniform(UniformType),
228    UniformColor(ColorId),
229    DrawUniform,
230    ViewUniform,
231    PassUniform,
232    Instance(InstanceType),
233    Geometry,
234    Texture,
235    Local,
236    Varying,
237}
238
239#[derive(Clone, Hash, PartialEq)]
240pub struct ShVar {
241    pub name: String,
242    pub ty: String,
243    pub store: ShVarStore
244}
245
246
247#[inline(never)]
248pub fn sh_var(name:&str, ty:&str, store:ShVarStore)->ShVar{
249    ShVar{
250        name:name.to_string(),
251        ty:ty.to_string(),
252        store:store
253    }
254}
255
256#[derive(Clone, Hash, PartialEq)]
257pub struct ShConst {
258    pub name: String,
259    pub ty: String,
260    pub value: ShExpr
261}
262
263#[derive(Clone, Hash, PartialEq)]
264pub struct ShTypeField {
265    pub name: String,
266    pub ty: String,
267}
268
269impl ShTypeField {
270    pub fn new(name: &str, ty: &str) -> Self {
271        Self {
272            name: name.to_string(),
273            ty: ty.to_string()
274        }
275    }
276}
277
278#[derive(Clone, Hash, PartialEq)]
279pub struct ShType {
280    pub name: String,
281    pub slots: usize,
282    pub prim: bool,
283    pub fields: Vec<ShTypeField>
284}
285
286// AST tree nodes
287
288#[derive(Clone, Hash, PartialEq)]
289pub enum ShExpr {
290    ShId(ShId),
291    ShLit(ShLit),
292    ShField(ShField),
293    ShIndex(ShIndex),
294    ShAssign(ShAssign),
295    ShAssignOp(ShAssignOp),
296    ShBinary(ShBinary),
297    ShUnary(ShUnary),
298    ShParen(ShParen),
299    ShBlock(ShBlock),
300    ShCall(ShCall),
301    ShIf(ShIf),
302    ShWhile(ShWhile),
303    ShForLoop(ShForLoop),
304    ShReturn(ShReturn),
305    ShBreak(ShBreak),
306    ShContinue(ShContinue)
307}
308
309#[derive(Clone, Hash, PartialEq)]
310pub enum ShOp {
311    Add,
312    Sub,
313    Mul,
314    Div,
315    Rem,
316    And,
317    Or,
318    BitXor,
319    BitAnd,
320    BitOr,
321    Shl,
322    Shr,
323    Eq,
324    Lt,
325    Le,
326    Ne,
327    Ge,
328    Gt,
329    AddEq,
330    SubEq,
331    MulEq,
332    DivEq,
333    RemEq,
334    BitXorEq,
335    BitAndEq,
336    BitOrEq,
337    ShlEq,
338    ShrEq
339}
340
341impl ShOp {
342    pub fn to_string(&self) -> &str {
343        match self {
344            ShOp::Add => "+",
345            ShOp::Sub => "-",
346            ShOp::Mul => "*",
347            ShOp::Div => "/",
348            ShOp::Rem => "%",
349            ShOp::And => "&&",
350            ShOp::Or => "||",
351            ShOp::BitXor => "^",
352            ShOp::BitAnd => "&",
353            ShOp::BitOr => "|",
354            ShOp::Shl => "<<",
355            ShOp::Shr => ">>",
356            ShOp::Eq => "==",
357            ShOp::Lt => "<",
358            ShOp::Le => "<=",
359            ShOp::Ne => "!=",
360            ShOp::Ge => ">=",
361            ShOp::Gt => ">",
362            ShOp::AddEq => "+=",
363            ShOp::SubEq => "-=",
364            ShOp::MulEq => "*=",
365            ShOp::DivEq => "/=",
366            ShOp::RemEq => "%=",
367            ShOp::BitXorEq => "^=",
368            ShOp::BitAndEq => "&=",
369            ShOp::BitOrEq => "|=",
370            ShOp::ShlEq => "<<=",
371            ShOp::ShrEq => ">>=",
372        }
373    }
374}
375
376#[derive(Clone, Hash, PartialEq)]
377pub struct ShId {
378    pub name: String
379}
380
381#[inline(never)]
382pub fn sh_id(name:&str)->ShExpr{
383    ShExpr::ShId(ShId{name:name.to_string()})
384}
385
386#[derive(Clone)]
387pub enum ShLit {
388    Int(i64),
389    Float(f64),
390    Str(String),
391    Bool(bool)
392}
393
394#[inline(never)]
395pub fn sh_int(val:i64)->ShExpr{
396    ShExpr::ShLit(ShLit::Int(val))
397}
398
399#[inline(never)]
400pub fn sh_fl(val:f64)->ShExpr{
401    ShExpr::ShLit(ShLit::Float(val))
402}
403
404
405#[inline(never)]
406pub fn sh_str(val:&str)->ShExpr{
407    ShExpr::ShLit(ShLit::Str(val.to_string()))
408}
409
410#[inline(never)]
411pub fn sh_bool(val:bool)->ShExpr{
412    ShExpr::ShLit(ShLit::Bool(val))
413}
414
415
416impl Hash for ShLit {
417    fn hash<H: Hasher>(&self, state: &mut H) {
418        match self {
419            ShLit::Int(iv) => iv.hash(state),
420            ShLit::Float(fv) => fv.to_bits().hash(state),
421            ShLit::Str(sv) => sv.hash(state),
422            ShLit::Bool(bv) => bv.hash(state)
423        }
424    }
425}
426
427impl PartialEq for ShLit {
428    fn eq(&self, other: &ShLit) -> bool {
429        match self {
430            ShLit::Int(iv) => match other {
431                ShLit::Int(ov) => iv == ov,
432                _ => false
433            },
434            ShLit::Float(iv) => match other {
435                ShLit::Float(ov) => iv.to_bits() == ov.to_bits(),
436                _ => false
437            },
438            ShLit::Str(iv) => match other {
439                ShLit::Str(ov) => iv == ov,
440                _ => false
441            },
442            ShLit::Bool(iv) => match other {
443                ShLit::Bool(ov) => iv == ov,
444                _ => false
445            },
446        }
447    }
448}
449
450#[derive(Clone, Hash, PartialEq)]
451pub struct ShField {
452    pub base: Box<ShExpr>,
453    pub member: String
454}
455
456#[inline(never)]
457pub fn sh_fd(base:ShExpr, member:&str)->ShExpr{
458      ShExpr::ShField(ShField{
459        base:Box::new(base),
460        member:member.to_string()
461    })
462}
463
464
465#[derive(Clone, Hash, PartialEq)]
466pub struct ShIndex {
467    pub base: Box<ShExpr>,
468    pub index: Box<ShExpr>
469}
470
471#[inline(never)]
472pub fn sh_idx(base:ShExpr, index:ShExpr)->ShExpr{
473      ShExpr::ShIndex(ShIndex{
474        base:Box::new(base),
475        index:Box::new(index)
476    })
477}
478
479
480
481#[derive(Clone, Hash, PartialEq)]
482pub struct ShAssign {
483    pub left: Box<ShExpr>,
484    pub right: Box<ShExpr>
485}
486
487#[inline(never)]
488pub fn sh_asn(left:ShExpr, right:ShExpr)->ShExpr{
489      ShExpr::ShAssign(ShAssign{
490        left:Box::new(left),
491        right:Box::new(right)
492    })
493}
494
495#[derive(Clone, Hash, PartialEq)]
496pub struct ShAssignOp {
497    pub left: Box<ShExpr>,
498    pub right: Box<ShExpr>,
499    pub op: ShOp
500}
501
502#[inline(never)]
503pub fn sh_asn_op(left:ShExpr, right:ShExpr, op:ShOp)->ShExpr{
504      ShExpr::ShAssignOp(ShAssignOp{
505        left:Box::new(left),
506        right:Box::new(right),
507        op:op
508    })
509}
510
511
512#[derive(Clone, Hash, PartialEq)]
513pub struct ShBinary {
514    pub left: Box<ShExpr>,
515    pub right: Box<ShExpr>,
516    pub op: ShOp
517}
518
519#[inline(never)]
520pub fn sh_bin(left:ShExpr, right:ShExpr, op:ShOp)->ShExpr{
521    ShExpr::ShBinary(ShBinary{
522        left:Box::new(left),
523        right:Box::new(right),
524        op:op
525    })
526}
527
528#[derive(Clone, Hash, PartialEq)]
529pub enum ShUnaryOp {
530    Not,
531    Neg
532}
533
534impl ShUnaryOp {
535    pub fn to_string(&self) -> &str {
536        match self {
537            ShUnaryOp::Not => "!",
538            ShUnaryOp::Neg => "-"
539        }
540    }
541}
542
543#[derive(Clone, Hash, PartialEq)]
544pub struct ShUnary {
545    pub expr: Box<ShExpr>,
546    pub op: ShUnaryOp
547}
548
549#[inline(never)]
550pub fn sh_unary(expr:ShExpr, op:ShUnaryOp)->ShExpr{
551    ShExpr::ShUnary(ShUnary{
552        expr:Box::new(expr),
553        op:op
554    })
555}
556
557
558#[derive(Clone, Hash, PartialEq)]
559pub struct ShParen {
560    pub expr: Box<ShExpr>,
561}
562
563#[inline(never)]
564pub fn sh_par(expr:ShExpr)->ShExpr{
565    ShExpr::ShParen(ShParen{expr:Box::new(expr)})
566}
567
568#[derive(Clone, Hash, PartialEq)]
569pub enum ShStmt {
570    ShLet(ShLet),
571    ShExpr(ShExpr),
572    ShSemi(ShExpr)
573}
574
575#[inline(never)]
576pub fn sh_sems(expr:ShExpr)->ShStmt{
577    ShStmt::ShSemi(expr)
578}
579
580#[inline(never)]
581pub fn sh_exps(expr:ShExpr)->ShStmt{
582    ShStmt::ShExpr(expr)
583}
584
585#[derive(Clone, Hash, PartialEq)]
586pub struct ShBlock {
587    pub stmts: Vec<ShStmt>
588}
589
590#[inline(never)]
591pub fn sh_block(stmts:&[ShStmt])->ShBlock{
592    ShBlock{stmts:stmts.to_vec()}
593}
594
595#[derive(Clone, Hash, PartialEq)]
596pub struct ShCall {
597    pub call: String,
598    pub args: Vec<ShExpr>
599}
600
601#[inline(never)]
602pub fn sh_call(call:&str, args:&[ShExpr])->ShExpr{
603    ShExpr::ShCall(ShCall{
604        call:call.to_string(),
605        args:args.to_vec()
606    })
607}
608
609#[derive(Clone, Hash, PartialEq)]
610pub struct ShIf {
611    pub cond: Box<ShExpr>,
612    pub then_branch: ShBlock,
613    pub else_branch: Option<Box<ShExpr>>,
614}
615
616#[inline(never)]
617pub fn sh_if(cond:ShExpr, then_branch:ShBlock)->ShExpr{
618    ShExpr::ShIf(ShIf{
619        cond:Box::new(cond),
620        then_branch:then_branch,
621        else_branch:None
622    })
623}
624
625#[inline(never)]
626pub fn sh_if_else(cond:ShExpr, then_branch:ShBlock, else_branch:ShExpr)->ShExpr{
627    ShExpr::ShIf(ShIf{
628        cond:Box::new(cond),
629        then_branch:then_branch,
630        else_branch:Some(Box::new(else_branch))
631    })
632}
633
634#[derive(Clone, Hash, PartialEq)]
635pub struct ShWhile {
636    pub cond: Box<ShExpr>,
637    pub body: ShBlock,
638}
639
640#[inline(never)]
641pub fn sh_while(cond:ShExpr, body:ShBlock)->ShExpr{
642    ShExpr::ShWhile(ShWhile{
643        cond:Box::new(cond),
644        body:body
645    })
646}
647
648
649#[derive(Clone, Hash, PartialEq)]
650pub struct ShForLoop {
651    pub iter: String,
652    pub from: Box<ShExpr>,
653    pub to: Box<ShExpr>,
654    pub body: ShBlock
655}
656
657#[inline(never)]
658pub fn sh_for(iter:&str, from_ts:ShExpr, to_ts:ShExpr, body:ShBlock)->ShExpr{
659      ShExpr::ShForLoop(ShForLoop{
660        iter:iter.to_string(),
661        from:Box::new(from_ts),
662        to:Box::new(to_ts),
663        body:body
664    })
665}
666
667#[derive(Clone, Hash, PartialEq)]
668pub struct ShReturn {
669    pub expr: Option<Box<ShExpr>>
670}
671
672#[inline(never)]
673pub fn sh_ret(expr:ShExpr)->ShExpr{
674    ShExpr::ShReturn(ShReturn{
675        expr:Some(Box::new(expr)),
676    })
677}
678
679#[inline(never)]
680pub fn sh_retn()->ShExpr{
681    ShExpr::ShReturn(ShReturn{
682        expr:None
683    })
684}
685
686
687#[derive(Clone, Hash, PartialEq)]
688pub struct ShBreak {
689}
690
691#[derive(Clone, Hash, PartialEq)]
692pub struct ShContinue {
693}
694
695#[derive(Clone, Hash, PartialEq)]
696pub struct ShLet {
697    pub name: String,
698    pub ty: String,
699    pub init: Box<ShExpr>
700}
701
702
703#[inline(never)]
704pub fn sh_let(name:&str, ty:&str, init:ShExpr)->ShStmt{
705    ShStmt::ShLet(ShLet{
706        name:name.to_string(),
707        ty:ty.to_string(),
708        init:Box::new(init)
709    })
710}
711
712#[derive(Clone)]
713pub struct Sl {
714    pub sl: String,
715    pub ty: String
716}
717
718#[derive(Clone)]
719pub struct SlErr {
720    pub msg: String
721}
722
723pub struct SlDecl {
724    pub name: String,
725    pub ty: String
726}
727
728#[derive(Clone)]
729pub enum SlTarget {
730    Pixel,
731    Vertex,
732    Constant
733}
734
735pub struct SlCx<'a> {
736    pub depth: usize,
737    pub target: SlTarget,
738    pub defargs_fn: String,
739    pub defargs_call: String,
740    pub call_prefix: String,
741    pub shader_gen: &'a ShaderGen,
742    pub scope: Vec<SlDecl>,
743    pub fn_deps: Vec<String>,
744    pub fn_done: Vec<Sl>,
745    pub auto_vary: Vec<ShVar>
746}
747
748pub enum MapCallResult {
749    Rename(String),
750    Rewrite(String, String),
751    None
752}
753
754impl<'a> SlCx<'a> {
755    pub fn scan_scope(&self, name: &str) -> Option<&str> {
756        if let Some(decl) = self.scope.iter().find( | i | i.name == name) {
757            return Some(&decl.ty);
758        }
759        None
760    }
761    pub fn get_type(&self, name: &str) -> Result<&ShType,
762    SlErr> {
763        if let Some(ty) = self.shader_gen.find_type(name) {
764            return Ok(ty);
765        }
766        Err(SlErr {msg: format!("Cannot find type {}", name)})
767    }
768}
769
770impl ShExpr {
771    pub fn sl(&self, slcx: &mut SlCx) -> Result<Sl, SlErr> {
772        match self {
773            ShExpr::ShId(x) => x.sl(slcx),
774            ShExpr::ShLit(x) => x.sl(slcx),
775            ShExpr::ShAssign(x) => x.sl(slcx),
776            ShExpr::ShCall(x) => x.sl(slcx),
777            ShExpr::ShBinary(x) => x.sl(slcx),
778            ShExpr::ShUnary(x) => x.sl(slcx),
779            ShExpr::ShAssignOp(x) => x.sl(slcx),
780            ShExpr::ShIf(x) => x.sl(slcx),
781            ShExpr::ShWhile(x) => x.sl(slcx),
782            ShExpr::ShForLoop(x) => x.sl(slcx),
783            ShExpr::ShBlock(x) => x.sl(slcx),
784            ShExpr::ShField(x) => x.sl(slcx),
785            ShExpr::ShIndex(x) => x.sl(slcx),
786            ShExpr::ShParen(x) => x.sl(slcx),
787            ShExpr::ShReturn(x) => x.sl(slcx),
788            ShExpr::ShBreak(x) => x.sl(slcx),
789            ShExpr::ShContinue(x) => x.sl(slcx),
790        }
791    }
792}
793
794
795impl ShId {
796    pub fn sl(&self, slcx: &mut SlCx) -> Result<Sl, SlErr> {
797        // ok so. we have to find our id on
798        if let Some(ty) = slcx.scan_scope(&self.name) {
799            Ok(Sl {sl: self.name.to_string(), ty: ty.to_string()})
800        }
801        else if let Some(cnst) = slcx.shader_gen.find_const(&self.name) {
802            Ok(Sl {sl: self.name.to_string(), ty: cnst.ty.to_string()})
803        }
804        else if let Some(var) = slcx.shader_gen.find_var(&self.name) {
805            Ok(Sl {sl: slcx.map_var(var), ty: var.ty.to_string()})
806        }
807        else { // id not found.. lets give an error
808            Err(SlErr {
809                msg: format!("Id {} not resolved, is it declared?", self.name)
810            })
811        }
812    }
813}
814
815impl ShLit {
816    pub fn sl(&self, _slcx: &mut SlCx) -> Result<Sl, SlErr> {
817        // we do a literal
818        match self {
819            ShLit::Int(val) => {
820                Ok(Sl {sl: format!("{}", val), ty: "int".to_string()})
821            }
822            ShLit::Str(val) => {
823                Ok(Sl {sl: format!("{}", val), ty: "string".to_string()})
824            }
825            ShLit::Float(val) => {
826                if val.ceil() == *val {
827                    Ok(Sl {sl: format!("{}.0", val), ty: "float".to_string()})
828                }
829                else {
830                    Ok(Sl {sl: format!("{}", val), ty: "float".to_string()})
831                }
832            }
833            ShLit::Bool(val) => {
834                Ok(Sl {sl: format!("{}", val), ty: "bool".to_string()})
835            }
836        }
837    }
838}
839
840impl ShField {
841    pub fn sl(&self, slcx: &mut SlCx) -> Result<Sl, SlErr> {
842        let base = self.base.sl(slcx) ?;
843        // we now have to figure out the type of member
844        let shty = slcx.get_type(&base.ty) ?;
845        // lets get our member
846        if let Some(field) = shty.fields.iter().find( | i | i.name == self.member) {
847            Ok(Sl {
848                sl: format!("{}.{}", base.sl, self.member),
849                ty: field.ty.to_string()
850            })
851        }
852        else {
853            let mut mode = 0;
854            let slots = shty.slots;
855            
856            if shty.name != "float" && shty.name != "vec2" && shty.name != "vec3" && shty.name != "vec4" {
857                return Err(SlErr {
858                    msg: format!("member {} not found {}", self.member, base.ty)
859                })
860            }
861            if self.member.len() >4 {
862                return Err(SlErr {
863                    msg: format!("member {} not found or a valid swizzle of {} {}", self.member, base.ty, base.sl)
864                })
865            }
866            for chr in self.member.chars() {
867                if chr == 'x' || chr == 'y' || chr == 'z' || chr == 'w' {
868                    if chr == 'y' && slots<2 {mode = 3;}
869                    else if chr == 'z' && slots<3 {mode = 3;}
870                    else if chr == 'w' && slots<4 {mode = 3;};
871                    if mode == 0 {mode = 1;}
872                    else if mode != 1 {
873                        return Err(SlErr {
874                            msg: format!("member {} not a valid swizzle of {} {}", self.member, base.ty, base.sl)
875                        })
876                    }
877                }
878                else if chr == 'r' || chr == 'g' || chr == 'b' || chr == 'a' {
879                    if chr == 'r' && slots<2 {mode = 3;}
880                    else if chr == 'g' && slots<3 {mode = 3;}
881                    else if chr == 'b' && slots<4 {mode = 3;};
882                    if mode == 0 {mode = 2;}
883                    else if mode != 2 {
884                        return Err(SlErr {
885                            msg: format!("member {} not a valid swizzle of {} {}", self.member, base.ty, base.sl)
886                        })
887                    }
888                }
889            }
890            
891            match self.member.len() {
892                1 => return Ok(Sl {
893                    sl: format!("{}.{}", base.sl, self.member),
894                    ty: "float".to_string()
895                }),
896                2 => return Ok(Sl {
897                    sl: format!("{}.{}", base.sl, self.member),
898                    ty: "vec2".to_string()
899                }),
900                3 => return Ok(Sl {
901                    sl: format!("{}.{}", base.sl, self.member),
902                    ty: "vec3".to_string()
903                }),
904                4 => return Ok(Sl {
905                    sl: format!("{}.{}", base.sl, self.member),
906                    ty: "vec4".to_string()
907                }),
908                _ => Err(SlErr {
909                    msg: format!("member {} not cannot be found on type {} {}", self.member, base.ty, base.sl)
910                })
911            }
912        }
913    }
914}
915
916impl ShIndex {
917    pub fn sl(&self, slcx: &mut SlCx) -> Result<Sl, SlErr> {
918        let base = self.base.sl(slcx) ?;
919        let index = self.index.sl(slcx) ?;
920        // limit base type to vec2/3/4
921        if base.ty != "vec2" && base.ty != "vec3" && base.ty != "vec4" {
922            Err(SlErr {
923                msg: format!("index on unsupported type {}", base.ty)
924            })
925        }
926        else {
927            Ok(Sl {
928                sl: format!("{}[{}]", base.sl, index.sl),
929                ty: "float".to_string()
930            })
931        }
932    }
933}
934
935impl ShAssign {
936    pub fn sl(&self, slcx: &mut SlCx) -> Result<Sl, SlErr> {
937        // if we are assigning to a geom
938        
939        let left = self.left.sl(slcx) ?;
940        let right = self.right.sl(slcx) ?;
941        if left.ty != right.ty {
942            Err(SlErr {
943                msg: format!("Left type {} not the same as right {} in assign {}={}", left.ty, right.ty, left.sl, right.sl)
944            })
945        }
946        else {
947            Ok(Sl {
948                sl: format!("{} = {}", left.sl, right.sl),
949                ty: left.ty
950            })
951        }
952    }
953}
954
955impl ShAssignOp {
956    pub fn sl(&self, slcx: &mut SlCx) -> Result<Sl, SlErr> {
957        let left = self.left.sl(slcx) ?;
958        let right = self.right.sl(slcx) ?;
959        
960        if left.ty != right.ty {
961            Err(SlErr {
962                msg: format!("Left type {} not the same as right {} in assign op {}{}{}", left.ty, self.op.to_string(), right.ty, left.sl, right.sl)
963            })
964        }
965        else {
966            Ok(Sl {
967                sl: format!("{}{}{}", left.sl, self.op.to_string(), right.sl),
968                ty: left.ty
969            })
970        }
971    }
972}
973
974impl ShBinary {
975    pub fn sl(&self, slcx: &mut SlCx) -> Result<Sl, SlErr> {
976        let left = self.left.sl(slcx) ?;
977        let right = self.right.sl(slcx) ?;
978        if left.ty != right.ty {
979            if left.ty == "float" && (right.ty == "vec2" || right.ty == "vec3" || right.ty == "vec4") {
980                Ok(Sl {
981                    sl: format!("{}{}{}", left.sl, self.op.to_string(), right.sl),
982                    ty: right.ty
983                })
984            }
985            else if right.ty == "float" && (left.ty == "vec2" || left.ty == "vec3" || left.ty == "vec4") {
986                Ok(Sl {
987                    sl: format!("{}{}{}", left.sl, self.op.to_string(), right.sl),
988                    ty: left.ty
989                })
990            }
991            else if right.ty == "mat4" && left.ty == "vec4" {
992                Ok(Sl {
993                    sl: slcx.mat_mul(&left.sl, &right.sl),
994                    ty: left.ty
995                })
996            }
997            else if right.ty == "mat3" && left.ty == "vec3" {
998                Ok(Sl {
999                    sl: slcx.mat_mul(&left.sl, &right.sl),
1000                    ty: left.ty
1001                })
1002            }
1003            else if right.ty == "mat2" && left.ty == "vec2" {
1004                Ok(Sl {
1005                    sl: slcx.mat_mul(&left.sl, &right.sl),
1006                    ty: left.ty
1007                })
1008            }
1009            else if left.ty == "mat4" && right.ty == "vec4" {
1010                Ok(Sl {
1011                    sl: slcx.mat_mul(&left.sl, &right.sl),
1012                    ty: right.ty
1013                })
1014            }
1015            else if left.ty == "mat3" && right.ty == "vec3" {
1016                Ok(Sl {
1017                    sl: slcx.mat_mul(&left.sl, &right.sl),
1018                    ty: right.ty
1019                })
1020            }
1021            else if left.ty == "mat2" && right.ty == "vec2" {
1022                Ok(Sl {
1023                    sl: slcx.mat_mul(&left.sl, &right.sl),
1024                    ty: right.ty
1025                })
1026            }
1027            else {
1028                Err(SlErr {
1029                    msg: format!("Left type {} not the same as right {} in binary op {}{}{}", left.ty, right.ty, left.sl, self.op.to_string(), right.sl)
1030                })
1031            }
1032        }
1033        else {
1034            if left.ty == "mat4" || left.ty == "mat3" || left.ty == "mat2" {
1035                Ok(Sl {
1036                    sl: slcx.mat_mul(&left.sl, &right.sl),
1037                    ty: left.ty
1038                })
1039                
1040            }
1041            else {
1042                Ok(Sl {
1043                    sl: format!("{}{}{}", left.sl, self.op.to_string(), right.sl),
1044                    ty: left.ty
1045                })
1046            }
1047        }
1048    }
1049}
1050
1051impl ShUnary {
1052    pub fn sl(&self, slcx: &mut SlCx) -> Result<Sl, SlErr> {
1053        let expr = self.expr.sl(slcx) ?;
1054        Ok(Sl {
1055            sl: format!("{}{}", self.op.to_string(), expr.sl),
1056            ty: expr.ty
1057        })
1058    }
1059}
1060
1061impl ShParen {
1062    pub fn sl(&self, slcx: &mut SlCx) -> Result<Sl, SlErr> {
1063        let expr = self.expr.sl(slcx) ?;
1064        Ok(Sl {
1065            sl: format!("({})", expr.sl),
1066            ty: expr.ty
1067        })
1068    }
1069}
1070
1071impl ShBlock {
1072    pub fn sl(&self, slcx: &mut SlCx) -> Result<Sl, SlErr> {
1073        let mut sl = String::new();
1074        sl.push_str("{\n");
1075        slcx.depth += 1;
1076        for stmt in &self.stmts {
1077            for _i in 0..slcx.depth {
1078                sl.push_str("  ");
1079            }
1080            match stmt {
1081                ShStmt::ShLet(stmt) => {
1082                    let out = stmt.sl(slcx) ?;
1083                    sl.push_str(&out.sl);
1084                },
1085                ShStmt::ShExpr(stmt) => {
1086                    let out = stmt.sl(slcx) ?;
1087                    sl.push_str(&out.sl);
1088                }
1089                ShStmt::ShSemi(stmt) => {
1090                    let out = stmt.sl(slcx) ?;
1091                    sl.push_str(&out.sl);
1092                }
1093            }
1094            sl.push_str(";\n");
1095        }
1096        slcx.depth -= 1;
1097        sl.push_str("}");
1098        Ok(Sl {
1099            sl: sl,
1100            ty: "void".to_string()
1101        })
1102    }
1103}
1104
1105impl ShCall {
1106    pub fn sl(&self, slcx: &mut SlCx) -> Result<Sl, SlErr> {
1107        // we have a call, look up the call type on cx
1108        let mut out = String::new();
1109        if let Some(shfn) = slcx.shader_gen.find_fn(&self.call) {
1110            let mut defargs_call = "".to_string();
1111            
1112            if let Some(_block) = &shfn.block { // not internal, so its a dep
1113                let index = slcx.fn_deps.iter().position( | i | **i == self.call);
1114                if let Some(index) = index {
1115                    slcx.fn_deps.remove(index);
1116                }
1117                slcx.fn_deps.push(self.call.clone());
1118                defargs_call = slcx.defargs_call.to_string();
1119                out.push_str(&slcx.call_prefix);
1120            };
1121            
1122            
1123            // lets check our args and compose return type
1124            let mut gen_t = "".to_string();
1125            
1126            let mut args_gl = Vec::new();
1127            // loop over args and typecheck / fill in generics
1128            for arg in &self.args {
1129                let arg_gl = arg.sl(slcx) ?;
1130                args_gl.push(arg_gl);
1131            };
1132            
1133            let map_call = slcx.map_call(&self.call, &args_gl);
1134            let ret_ty;
1135            
1136            if let MapCallResult::Rewrite(rewrite, rty) = map_call {
1137                out.push_str(&rewrite);
1138                ret_ty = rty;
1139            }
1140            else {
1141                if let MapCallResult::Rename(name) = map_call {
1142                    out.push_str(&name);
1143                }
1144                else {
1145                    out.push_str(&self.call);
1146                }
1147                out.push_str("(");
1148                
1149                // loop over args and typecheck / fill in generics
1150                for (i, arg_gl) in args_gl.iter().enumerate() {
1151                    //let arg_gl = args_gl[i];//.sl(cx)?;
1152                    let in_ty = arg_gl.ty.clone();
1153                    if i != 0 {
1154                        out.push_str(", ");
1155                    }
1156                    out.push_str(&arg_gl.sl);
1157                    // lets check the type against our shfn
1158                    if i >= shfn.args.len() {
1159                        return Err(SlErr {
1160                            msg: format!("Too many function arguments for call {} got:{} can use:{}", self.call, i + 1, shfn.args.len())
1161                        })
1162                    }
1163                    // lets check our arg type
1164                    let fnarg = &shfn.args[i];
1165                    // lets see if ty is "T" or "O" or "F" or "B"
1166                    if fnarg.ty == "T" {
1167                        // we already have a gen_t but its not the same
1168                        if gen_t != "" && gen_t != in_ty {
1169                            return Err(SlErr {
1170                                msg: format!("Function type T incorrectly redefined for call {} type was {} given {} for arg {}", self.call, gen_t, in_ty, i)
1171                            })
1172                        }
1173                        gen_t = in_ty;
1174                    }
1175                    else if fnarg.ty == "F" { // we have to be a float type
1176                        if in_ty != "float" && in_ty != "vec2" && in_ty != "vec3" && in_ty != "vec4" {
1177                            return Err(SlErr {
1178                                msg: format!("Function type F is not a float-ty type for call {} for arg {} type {}", self.call, i, in_ty)
1179                            })
1180                        }
1181                    }
1182                    else if fnarg.ty == "B" { // have to be a boolvec
1183                        if in_ty != "bool" && in_ty != "bvec2" && in_ty != "bvec3" && in_ty != "bvec4" {
1184                            return Err(SlErr {
1185                                msg: format!("Function arg is not a bool-ty type for call {} for arg {} type {}", self.call, i, in_ty)
1186                            })
1187                        }
1188                        gen_t = in_ty;
1189                    }
1190                    else if fnarg.ty != in_ty {
1191                        return Err(SlErr {
1192                            msg: format!("Arg wrong type for call {} for arg {} expected type {} got type {}", self.call, i, fnarg.ty, in_ty)
1193                        })
1194                    }
1195                }
1196                // we have less args provided than the fn signature
1197                // check if they were optional
1198                if self.args.len() < shfn.args.len() {
1199                    for i in self.args.len()..shfn.args.len() {
1200                        let fnarg = &shfn.args[i];
1201                        if fnarg.ty != "O" {
1202                            return Err(SlErr {
1203                                msg: format!("Not enough args for call {} not enough args provided at {}, possible {}", self.call, i, shfn.args.len())
1204                            })
1205                        }
1206                    }
1207                };
1208                ret_ty = if shfn.ret == "T" || shfn.ret == "B" {
1209                    gen_t
1210                }
1211                else {
1212                    shfn.ret.clone()
1213                };
1214                if defargs_call.len() != 0 {
1215                    if self.args.len() != 0 {
1216                        out.push_str(", ");
1217                    }
1218                    out.push_str(&defargs_call);
1219                }
1220                out.push_str(")");
1221            }
1222            // check our arg types
1223            // if our return type is T,
1224            // use one of the args marked T as its type
1225            // make sure all args are the same type T
1226            Ok(Sl {
1227                sl: out,
1228                ty: ret_ty
1229            })
1230        }
1231        else {
1232            // its a constructor call
1233            if let Some(slty) = slcx.shader_gen.find_type(&self.call) {
1234                
1235                // HLSL doesn't allow vec3(0.) so we have to polyfill it
1236                // vec3(x), vec3(xy,z) vec3(x,yz), 
1237                let mut args = Vec::new();
1238                
1239                // TODO check args
1240                let mut arg_slots = 0;
1241                for arg in &self.args {
1242                    let arg_sl = arg.sl(slcx) ?;
1243                    if let Some(arg_ty) = slcx.shader_gen.find_type(&arg_sl.ty) {
1244                        arg_slots += arg_ty.slots;
1245                    }
1246                    else{
1247                        return Err(SlErr {
1248                            msg: format!("Cannot find constructor arg type {}", arg_sl.ty)
1249                        })
1250                    }
1251                    args.push(arg_sl);
1252                }
1253                if arg_slots > slty.slots{
1254                    let mut out = String::new();
1255                    out.push_str(&self.call);
1256                    out.push_str("(");
1257                    for (i,arg) in args.iter().enumerate(){
1258                        if i != 0{
1259                            out.push_str(", ")
1260                        }
1261                        out.push_str(&arg.sl);
1262                    }
1263                    out.push_str(")");
1264                    return Err(SlErr {
1265                        msg: format!("Constructor slots don't match given {} need {} - {}", arg_slots, slty.slots, out)
1266                    })
1267                }
1268                
1269                // lets sum up the arg type slots and see if it fits in our constructor
1270                // if it does lets pass it to map_constructor so each platform can polyfill it
1271                
1272                out.push_str(&slcx.map_constructor(&self.call, &args));
1273                Ok(Sl {
1274                    sl: out,
1275                    ty: slty.name.clone()
1276                })
1277            }
1278            else {
1279                Err(SlErr {
1280                    msg: format!("Cannot find function {}", self.call)
1281                })
1282            }
1283        }
1284        
1285    }
1286}
1287
1288impl ShIf {
1289    pub fn sl(&self, cx: &mut SlCx) -> Result<Sl, SlErr> {
1290        let mut out = "".to_string();
1291        out.push_str("if(");
1292        let cond = self.cond.sl(cx) ?;
1293        out.push_str(&cond.sl);
1294        out.push_str(")");
1295        
1296        let then = self.then_branch.sl(cx) ?;
1297        
1298        out.push_str(&then.sl);
1299        if let Some(else_branch) = &self.else_branch {
1300            let else_gl = else_branch.sl(cx) ?;
1301            out.push_str("else ");
1302            out.push_str(&else_gl.sl);
1303        }
1304        
1305        Ok(Sl {
1306            sl: out,
1307            ty: "void".to_string()
1308        })
1309    }
1310}
1311
1312impl ShWhile {
1313    pub fn sl(&self, cx: &mut SlCx) -> Result<Sl, SlErr> {
1314        let mut out = "".to_string();
1315        out.push_str("while(");
1316        let cond = self.cond.sl(cx) ?;
1317        out.push_str(&cond.sl);
1318        out.push_str(")");
1319        
1320        let body = self.body.sl(cx) ?;
1321        
1322        out.push_str(&body.sl);
1323        
1324        Ok(Sl {
1325            sl: out,
1326            ty: "void".to_string()
1327        })
1328    }
1329}
1330
1331impl ShForLoop {
1332    pub fn sl(&self, cx: &mut SlCx) -> Result<Sl, SlErr> {
1333        let mut out = "".to_string();
1334        
1335        out.push_str("for(int ");
1336        out.push_str(&self.iter);
1337        out.push_str("=");
1338        
1339        let from = self.from.sl(cx) ?;
1340        out.push_str(&from.sl);
1341        
1342        out.push_str(";");
1343        out.push_str(&self.iter);
1344        out.push_str(" < ");
1345        
1346        let to = self.to.sl(cx) ?;
1347        out.push_str(&to.sl);
1348        
1349        out.push_str(";");
1350        out.push_str(&self.iter);
1351        out.push_str("++)");
1352        
1353        let body = self.body.sl(cx) ?;
1354        
1355        out.push_str(&body.sl);
1356        
1357        Ok(Sl {
1358            sl: out,
1359            ty: "void".to_string()
1360        })
1361    }
1362}
1363
1364impl ShReturn {
1365    pub fn sl(&self, cx: &mut SlCx) -> Result<Sl, SlErr> {
1366        let mut out = "".to_string();
1367        if let Some(expr) = &self.expr {
1368            let expr_gl = expr.sl(cx) ?;
1369            out.push_str("return ");
1370            out.push_str(&expr_gl.sl);
1371        }
1372        else {
1373            out.push_str("return;");
1374        }
1375        Ok(Sl {
1376            sl: out,
1377            ty: "void".to_string()
1378        })
1379    }
1380}
1381
1382impl ShBreak {
1383    pub fn sl(&self, _cx: &mut SlCx) -> Result<Sl, SlErr> {
1384        Ok(Sl {
1385            sl: "break".to_string(),
1386            ty: "void".to_string()
1387        })
1388    }
1389}
1390
1391impl ShContinue {
1392    pub fn sl(&self, _cx: &mut SlCx) -> Result<Sl, SlErr> {
1393        Ok(Sl {
1394            sl: "continue".to_string(),
1395            ty: "void".to_string()
1396        })
1397    }
1398}
1399
1400impl ShLet {
1401    pub fn sl(&self, cx: &mut SlCx) -> Result<Sl, SlErr> {
1402        let mut out = "".to_string();
1403        let init = self.init.sl(cx) ?;
1404        
1405        let ty = init.ty.clone();
1406        if self.ty != "" && self.ty != init.ty {
1407            return Err(SlErr {
1408                msg: format!("Let definition {} type {} is different from initializer {}", self.name, self.ty, init.ty)
1409            })
1410        }
1411        
1412        out.push_str(&cx.map_type(&ty));
1413        out.push_str(" ");
1414        out.push_str(&self.name);
1415        out.push_str(" = ");
1416        
1417        // lets define our identifier on scope
1418        cx.scope.push(SlDecl {
1419            name: self.name.clone(),
1420            ty: init.ty.clone()
1421        });
1422        
1423        out.push_str(&init.sl);
1424        Ok(Sl {
1425            sl: out,
1426            ty: "void".to_string()
1427        })
1428    }
1429}
1430
1431impl ShFn {
1432    pub fn sl(&self, cx: &mut SlCx) -> Result<Sl, SlErr> {
1433        let mut out = "".to_string();
1434        out.push_str(&cx.map_type(&self.ret));
1435        out.push_str(" ");
1436        out.push_str(&cx.call_prefix);
1437        out.push_str(&self.name);
1438        out.push_str("(");
1439        for (i, arg) in self.args.iter().enumerate() {
1440            if i != 0 {
1441                out.push_str(", ");
1442            }
1443            out.push_str(&cx.map_type(&arg.ty));
1444            out.push_str(" ");
1445            out.push_str(&arg.name);
1446            cx.scope.push(SlDecl {
1447                name: arg.name.clone(),
1448                ty: arg.ty.clone()
1449            });
1450        };
1451        if cx.defargs_fn.len() != 0 {
1452            if self.args.len() != 0 {
1453                out.push_str(", ");
1454            }
1455            out.push_str(&cx.defargs_fn);
1456        }
1457        out.push_str(")");
1458        if let Some(block) = &self.block {
1459            let block = block.sl(cx) ?;
1460            out.push_str(&block.sl);
1461        };
1462        Ok(Sl {
1463            sl: out,
1464            ty: self.name.clone()
1465        })
1466    }
1467}
1468
1469pub fn assemble_fn_and_deps(sg: &ShaderGen, cx: &mut SlCx) -> Result<String, SlErr> {
1470    
1471    let mut fn_local = Vec::new();
1472    loop {
1473        
1474        // find what deps we haven't done yet
1475        let fn_not_done = cx.fn_deps.iter().find( | cxfn | {
1476            if let Some(_done) = cx.fn_done.iter().find( | i | i.ty == **cxfn) {
1477                false
1478            }
1479            else {
1480                true
1481            }
1482        });
1483        // do that dep.
1484        if let Some(fn_not_done) = fn_not_done {
1485            let fn_name = fn_not_done.clone();
1486            let fn_to_do = sg.find_fn(&fn_name);
1487            if let Some(fn_to_do) = fn_to_do {
1488                cx.scope.clear();
1489                let result = fn_to_do.sl(cx) ?;
1490                cx.fn_done.push(result.clone());
1491                fn_local.push((fn_name, result.clone()));
1492            }
1493            else {
1494                return Err(SlErr {msg: format!("Cannot find entry function {}", fn_not_done)})
1495            }
1496        }
1497        else {
1498            break;
1499        }
1500    }
1501    // ok lets reverse concatinate it
1502    let mut out = String::new();
1503    for dep in cx.fn_deps.iter().rev() {
1504        if let Some((_, fnd)) = fn_local.iter().find( | (name, _) | name == dep) {
1505            out.push_str(&fnd.sl);
1506            out.push_str("\n");
1507        }
1508    };
1509    Ok(out)
1510}
1511
1512pub fn assemble_const_init(cnst: &ShConst, cx: &mut SlCx) -> Result<Sl, SlErr> {
1513    // lets process the expr of a constant
1514    let result = cnst.value.sl(cx) ?;
1515    if cx.fn_deps.len() > 0 {
1516        return Err(SlErr {msg: "Const cant have function call deps".to_string()});
1517    }
1518    return Ok(result)
1519}
1520