Define vector4f type.

You can't actually do anything with it at the moment except
construct it, so it's pretty easy!  But hopefully that will
be enough to get a shader actually functioning.
4 files changed, 104 insertions(+), 26 deletions(-)

M examples/rendy.rs
M src/ast.rs
M src/compile/mod.rs
M src/verify.rs
M examples/rendy.rs +0 -2
@@ 39,7 39,6 @@ fn compile_shader() -> Vec<u8> {
         returns: Type("F32".into()),
         //body: vec![Expr::Var("input".into())],
         body: vec![Expr::Literal(Lit::F32(0.1))],
-
     });
     let program = vec![vert, frag];
     let ctx = ch::verify::verify(program).unwrap();

          
@@ 50,7 49,6 @@ fn compile_shader() -> Vec<u8> {
 
 use rendy::mesh::AsVertex;
 
-
 type Backend = rendy::vulkan::Backend;
 
 lazy_static::lazy_static! {

          
M src/ast.rs +12 -0
@@ 58,6 58,7 @@ pub enum Decl {
 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize, PartialOrd)]
 pub enum Lit {
     F32(f32),
+    Vec4F(f32, f32, f32, f32),
     Bool(bool),
     Unit,
 }

          
@@ 66,6 67,7 @@ impl Lit {
     pub fn type_of(&self) -> Type {
         match self {
             Lit::F32(_) => Type("F32".into()),
+            Lit::Vec4F(_, _, _, _) => Type("Vec4F".into()),
             Lit::Bool(_) => Type("Bool".into()),
             Lit::Unit => Type("()".into()),
         }

          
@@ 92,6 94,16 @@ impl std::hash::Hash for Lit {
                 };
                 f_bits.hash(state)
             }
+            Lit::Vec4F(x, y, z, w) => {
+                for f in &[x, y, z, w][..] {
+                    let f_bits = if f.is_nan() {
+                        std::f32::NAN.to_bits()
+                    } else {
+                        f.to_bits()
+                    };
+                    f_bits.hash(state)
+                }
+            }
             Lit::Bool(b) => b.hash(state),
             Lit::Unit => ().hash(state),
         }

          
M src/compile/mod.rs +85 -19
@@ 74,7 74,8 @@ impl CContext {
         // unit testing easier.
         use verify::TypeDef;
         s.add_type(&TypeDef::F32);
-        // vec4<f32>
+        s.add_type(&TypeDef::Vec4F);
+        // Struct4<f32>
         s.add_type(&TypeDef::Struct(vec![
             ("x".into(), TypeDef::F32),
             ("y".into(), TypeDef::F32),

          
@@ 137,26 138,72 @@ impl CContext {
         // causes borrowing issues.  :|
         let type_float = self.get_type(&verify::TypeDef::F32);
         let type_bool = self.get_type(&verify::TypeDef::Bool);
+        let type_vec4f = self.get_type(&verify::TypeDef::Vec4F);
         //let type_unit = self.get_type(&verify::TypeDef::Unit);
 
         let consts = &mut self.consts;
-        let b = &mut self.b;
-        *consts.entry(vl.clone()).or_insert_with(|| match vl {
-            ast::Lit::F32(f) => b.constant_f32(type_float, f),
-            ast::Lit::Bool(bl) => {
-                if bl {
-                    b.constant_true(type_bool)
-                } else {
-                    b.constant_false(type_bool)
+        // Entry API doesn't work here 'cause we might have to recursively
+        // make several modifications to the type table.
+        if let Some(res) = consts.get(&vl) {
+            *res
+        } else {
+            match vl {
+                ast::Lit::F32(f) => self.b.constant_f32(type_float, f),
+                ast::Lit::Bool(bl) => {
+                    if bl {
+                        self.b.constant_true(type_bool)
+                    } else {
+                        self.b.constant_false(type_bool)
+                    }
+                }
+                ast::Lit::Vec4F(x, y, z, w) => {
+                    let components = [
+                        self.define_const(ast::Lit::F32(x)),
+                        self.define_const(ast::Lit::F32(y)),
+                        self.define_const(ast::Lit::F32(z)),
+                        self.define_const(ast::Lit::F32(w)),
+                    ];
+                    self.b.constant_composite(type_vec4f, &components)
+                }
+                // TODO: This is WRONG WRONG WRONG but
+                // I'm not entirely sure how to make it right
+                // yet.  Unit is not actually a value, so.
+                ast::Lit::Unit => {
+                    0;
+                    unimplemented!()
+                    //b.constant_null(type_unit),
                 }
             }
-            // TODO: This is WRONG WRONG WRONG but
-            // I'm not entirely sure how to make it right
-            // yet.  Unit is not actually a value, so.
-            ast::Lit::Unit =>
-                0
-                //b.constant_null(type_unit),
-        })
+        }
+        /*
+                *consts.entry(vl.clone()).or_insert_with(|| match vl {
+                    ast::Lit::F32(f) => b.constant_f32(type_float, f),
+                    ast::Lit::Bool(bl) => {
+                        if bl {
+                            b.constant_true(type_bool)
+                        } else {
+                            b.constant_false(type_bool)
+                        }
+                    }
+                    ast::Lit::Vec4F(x, y, z, w) => {
+                        let components = [
+                            self.define_const(ast::Lit::F32(x)),
+                            self.define_const(ast::Lit::F32(y)),
+                            self.define_const(ast::Lit::F32(z)),
+                            self.define_const(ast::Lit::F32(w)),
+                        ];
+                        b.constant_composite(type_vec4f, &components)
+                    }
+                    // TODO: This is WRONG WRONG WRONG but
+                    // I'm not entirely sure how to make it right
+                    // yet.  Unit is not actually a value, so.
+                    ast::Lit::Unit => {
+                        unimplemented!();
+                        0
+                        //b.constant_null(type_unit),
+                    }
+                })
+        */
     }
 
     /// Panics if the type does not exist.

          
@@ 192,6 239,17 @@ impl CContext {
                     .entry(typedef.clone())
                     .or_insert_with(|| b.type_float(32))
             }
+            TypeDef::Vec4F => {
+                if let Some(val) = self.typetable.get(typedef) {
+                    // Vec4F already exists
+                    *val
+                } else {
+                    let f_type_word = self.add_type(&verify::TypeDef::F32);
+                    let vec_type_word = self.b.type_vector(f_type_word, 4);
+                    self.typetable.insert(typedef.clone(), vec_type_word);
+                    vec_type_word
+                }
+            }
             TypeDef::Bool => {
                 let b = &mut self.b;
                 *self

          
@@ 625,7 683,11 @@ impl CContext {
                             .variable(t_ptr_word, None, spirv::StorageClass::Input, None);
                     // Gotta tell it what locations/etc the inputs are.
                     // FOR NOW we just enumerate the function args in order.
-                    self.b.decorate(value_word, spirv::Decoration::Location, [rspirv::mr::Operand::LiteralInt32(u32::try_from(i).unwrap())]);
+                    self.b.decorate(
+                        value_word,
+                        spirv::Decoration::Location,
+                        [rspirv::mr::Operand::LiteralInt32(u32::try_from(i).unwrap())],
+                    );
                     (value_word, t_word, t_ptr_word)
                 })
                 .collect();

          
@@ 638,8 700,12 @@ impl CContext {
                 let value_word =
                     self.b
                         .variable(t_ptr_word, None, spirv::StorageClass::Output, None);
-                    // Output word is always just location=0
-                    self.b.decorate(value_word, spirv::Decoration::Location, [rspirv::mr::Operand::LiteralInt32(0)]);
+                // Output word is always just location=0
+                self.b.decorate(
+                    value_word,
+                    spirv::Decoration::Location,
+                    [rspirv::mr::Operand::LiteralInt32(0)],
+                );
                 (value_word, t_word, t_ptr_word)
             };
 

          
M src/verify.rs +7 -5
@@ 67,6 67,7 @@ use crate::Error;
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub enum TypeDef {
     F32,
+    Vec4F,
     Bool,
     Unit,
     Struct(Vec<(String, TypeDef)>),

          
@@ 102,10 103,11 @@ impl Default for VContext {
         {
             // Default types.
             types.insert("F32".into(), TypeDef::F32);
+            types.insert("Vec4F".into(), TypeDef::Vec4F);
             types.insert("Bool".into(), TypeDef::Bool);
             types.insert("()".into(), TypeDef::Unit);
             types.insert(
-                "Vec4F".into(),
+                "Struct4F".into(),
                 TypeDef::Struct(vec![
                     ("x".into(), TypeDef::F32),
                     ("y".into(), TypeDef::F32),

          
@@ 310,9 312,9 @@ mod tests {
         let vert = Decl::Function(FunctionDecl {
             name: String::from("vertex"),
             params: vec![],
-            returns: Type("Vec4F".into()),
+            returns: Type("Struct4F".into()),
             body: vec![Expr::Structure(
-                String::from("Vec4F"),
+                String::from("Struct4F"),
                 vec![
                     (String::from("x"), Expr::Literal(Lit::F32(1.0))),
                     (String::from("y"), Expr::Literal(Lit::F32(1.0))),

          
@@ 352,9 354,9 @@ mod tests {
         let f = Decl::Function(FunctionDecl {
             name: String::from("foo"),
             params: vec![],
-            returns: Type("Vec4F".into()),
+            returns: Type("Struct4F".into()),
             body: vec![Expr::Structure(
-                String::from("Vec4F"),
+                String::from("Struct4F"),
                 vec![
                     (String::from("x"), Expr::Literal(Lit::F32(1.0))),
                     (String::from("y"), Expr::Literal(Lit::F32(1.0))),