Refactored function type a little.

On the whole I think this might have been a lateral move,
but oh well.
2 files changed, 89 insertions(+), 97 deletions(-)

M src/compile/mod.rs
M src/verify.rs
M src/compile/mod.rs +84 -92
@@ 83,10 83,10 @@ impl CContext {
             ("w".into(), TypeDef::F32),
         ]));
         // f32 -> f32
-        s.add_type(&TypeDef::Function(
+        s.add_type(&TypeDef::Function((
             vec![TypeDef::F32],
             Box::new(TypeDef::F32),
-        ));
+        )));
         s.add_type(&TypeDef::Bool);
         s.add_type(&TypeDef::Unit);
         s

          
@@ 269,7 269,7 @@ impl CContext {
                     n
                 }
             }
-            TypeDef::Function(params, returns) => {
+            TypeDef::Function((params, returns)) => {
                 if let Some(val) = self.typetable.get(typedef) {
                     // Function already exists
                     *val

          
@@ 351,18 351,13 @@ impl CContext {
                     .functions
                     .get(fname)
                     .expect("Function does not exist for funcall");
-                if let verify::TypeDef::Function(ref _params, ref rettype) =
-                    functiondef.functiontype
-                {
-                    // TODO: Tail call optimization would go here if it went anywhere.
-                    let rettype_word = self.get_type(rettype);
-                    let value_word =
-                        self.b
-                            .function_call(rettype_word, None, binding.address, param_words)?;
-                    (value_word, rettype_word)
-                } else {
-                    unreachable!("Function type is not TypeDef::Function")
-                }
+                let (ref _params, ref rettype) = functiondef.functiontype;
+                // TODO: Tail call optimization would go here if it went anywhere.
+                let rettype_word = self.get_type(rettype);
+                let value_word =
+                    self.b
+                        .function_call(rettype_word, None, binding.address, param_words)?;
+                (value_word, rettype_word)
             }
             ast::Expr::Block(exprs) => {
                 assert!(

          
@@ 576,7 571,7 @@ impl CContext {
         // Not sure if SPIR-V can really have function pointers though so idk if they
         // can be first-class objects.
         // I think this is good now, we treat function types like all the other types.
-        let ftype = self.add_type(&def.functiontype);
+        let ftype = self.add_type(&verify::TypeDef::Function(def.functiontype.clone()));
 
         let f_word = self.b.begin_function(
             function_returns,

          
@@ 636,95 631,92 @@ impl CContext {
         // Dig up the function def, and declare input/output global vars for it.
         // TODO: Name strings for input/output vars?
         let def = ctx.get_defined_function(name);
-        if let verify::TypeDef::Function(ref params, ref rettype) = def.functiontype {
-            // Value, value type, pointer type.
-            let input_words: Vec<(spirv::Word, spirv::Word, spirv::Word)> = params
-                .iter()
-                .enumerate()
-                .map(|(i, p)| {
-                    let t_word = self.get_type(p);
-                    // We don't bother storing pointer types in our typetable for now,
-                    // this is basically the only place they're used.
-                    let t_ptr_word = self
-                        .b
-                        .type_pointer(None, spirv::StorageClass::Input, t_word);
-                    let value_word =
-                        self.b
-                            .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())],
-                    );
-                    (value_word, t_word, t_ptr_word)
-                })
-                .collect();
-
-            let (output_word, t_word, _t_ptr_word) = {
-                let t_word = self.get_type(rettype);
+        let (ref params, ref rettype) = def.functiontype;
+        // Value, value type, pointer type.
+        let input_words: Vec<(spirv::Word, spirv::Word, spirv::Word)> = params
+            .iter()
+            .enumerate()
+            .map(|(i, p)| {
+                let t_word = self.get_type(p);
+                // We don't bother storing pointer types in our typetable for now,
+                // this is basically the only place they're used.
                 let t_ptr_word = self
                     .b
-                    .type_pointer(None, spirv::StorageClass::Output, t_word);
+                    .type_pointer(None, spirv::StorageClass::Input, t_word);
                 let value_word =
                     self.b
-                        .variable(t_ptr_word, None, spirv::StorageClass::Output, None);
-                // Output word is always just location=0
+                        .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(0)],
+                    [rspirv::mr::Operand::LiteralInt32(u32::try_from(i).unwrap())],
                 );
                 (value_word, t_word, t_ptr_word)
-            };
+            })
+            .collect();
 
-            // Now actually compile the function that calls our real function.
-            let functype_word = self.add_type(&verify::TypeDef::Function(
-                vec![],
-                Box::new(verify::TypeDef::Unit),
-            ));
-            let voidtype_word = self.add_type(&verify::TypeDef::Unit);
+        let (output_word, t_word, _t_ptr_word) = {
+            let t_word = self.get_type(rettype);
+            let t_ptr_word = self
+                .b
+                .type_pointer(None, spirv::StorageClass::Output, t_word);
+            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)],
+            );
+            (value_word, t_word, t_ptr_word)
+        };
+
+        // Now actually compile the function that calls our real function.
+        let functype_word = self.add_type(&verify::TypeDef::Function((
+            vec![],
+            Box::new(verify::TypeDef::Unit),
+        )));
+        let voidtype_word = self.add_type(&verify::TypeDef::Unit);
 
-            let f_word = self.b.begin_function(
-                voidtype_word,
-                None,
-                spirv::FunctionControl::DONT_INLINE | spirv::FunctionControl::CONST,
-                functype_word,
-            )?;
-            self.b.begin_basic_block(None)?;
-            // Load inputs
-            let r_inputs: Result<Vec<spirv::Word>, _> = input_words
-                .clone()
-                .into_iter()
-                .map(|(v_word, t_word, _t_ptr_word)| self.b.load(t_word, None, v_word, None, []))
-                .collect();
-            let inputs = r_inputs?;
-            // Call function
-            let fun_binding = *self.lookup_var(name);
-            let funcall_result_word = self
-                .b
-                .function_call(t_word, None, fun_binding.address, &inputs)
-                .unwrap();
-            // Save output
-            self.b.store(output_word, funcall_result_word, None, [])?;
-            self.b.ret()?;
-            self.b.end_function()?;
+        let f_word = self.b.begin_function(
+            voidtype_word,
+            None,
+            spirv::FunctionControl::DONT_INLINE | spirv::FunctionControl::CONST,
+            functype_word,
+        )?;
+        self.b.begin_basic_block(None)?;
+        // Load inputs
+        let r_inputs: Result<Vec<spirv::Word>, _> = input_words
+            .clone()
+            .into_iter()
+            .map(|(v_word, t_word, _t_ptr_word)| self.b.load(t_word, None, v_word, None, []))
+            .collect();
+        let inputs = r_inputs?;
+        // Call function
+        let fun_binding = *self.lookup_var(name);
+        let funcall_result_word = self
+            .b
+            .function_call(t_word, None, fun_binding.address, &inputs)
+            .unwrap();
+        // Save output
+        self.b.store(output_word, funcall_result_word, None, [])?;
+        self.b.ret()?;
+        self.b.end_function()?;
 
-            // We must also return the function's interface, that is, the words of
-            // all the global variables it touches.
-            let mut interface: Vec<u32> = input_words
-                .into_iter()
-                .map(|(input_word, _, _)| input_word)
-                .collect();
-            interface.push(output_word);
+        // We must also return the function's interface, that is, the words of
+        // all the global variables it touches.
+        let mut interface: Vec<u32> = input_words
+            .into_iter()
+            .map(|(input_word, _, _)| input_word)
+            .collect();
+        interface.push(output_word);
 
-            // That's it!  The actual OpEntryPoint instructions and names and stuff
-            // get handled by the caller.
-            Ok((f_word, interface))
-        } else {
-            unreachable!("Function type is not TypeDef::Function")
-        }
+        // That's it!  The actual OpEntryPoint instructions and names and stuff
+        // get handled by the caller.
+        Ok((f_word, interface))
     }
 
     /// Okay, so SPIR-V is a bit persnickity about entry points.

          
M src/verify.rs +5 -5
@@ 79,10 79,10 @@ pub enum TypeDef {
     Bool,
     Unit,
     Struct(Vec<(String, TypeDef)>),
-    Function(Vec<TypeDef>, Box<TypeDef>),
+    Function(FunctionType),
 }
 
-//RAR pub type FunctionType = (Vec<TypeDef>, Box<TypeDef>)
+pub type FunctionType = (Vec<TypeDef>, Box<TypeDef>);
 
 /// A function definition; the AST and whatever
 /// other information we care about that can get

          
@@ 90,7 90,7 @@ pub enum TypeDef {
 #[derive(Clone, Debug)]
 pub struct FunctionDef {
     pub decl: FunctionDecl,
-    pub functiontype: TypeDef,
+    pub functiontype: FunctionType,
 }
 
 /// Verification context.

          
@@ 267,12 267,12 @@ pub fn verify(program: Vec<Decl>) -> Res
                     .iter()
                     .map(|p| ctx.get_defined_type(&p.typ).clone())
                     .collect();
-                let functiontype = TypeDef::Function(param_types, Box::new(return_type.clone()));
+                let functiontype = (param_types, Box::new(return_type.clone()));
                 // TODO: This is stupid but easy, make it better sometime.
                 let function_type_name = format!("{:?}", functiontype);
                 // Functions may define the same type multiple times and it's not an error...
                 if !ctx.type_exists(&function_type_name) {
-                    ctx.define_type(&function_type_name, functiontype.clone())?;
+                    ctx.define_type(&function_type_name, TypeDef::Function(functiontype.clone()))?;
                 }
                 // This clone may be expensive, but it only
                 // happens once and if the definition fails