aaaaaaaaaa lambdas appear to work
M fml/src/parser.rs +2 -4
@@ 411,12 411,10 @@ impl<'input> Parser<'input> {
 
     fn parse_fn_type(&mut self) -> Type {
         // TODO: Parse generic stuffs?
-        let mut params = self.parse_fn_type_args();
+        let params = self.parse_fn_type_args();
         self.expect(T::Colon);
         let rettype = self.parse_type();
-        params.push(rettype);
-        todo!()
-        //TypeInfo::Func()
+        Type::Func(params, Box::new(rettype))
     }
 
     fn parse_fn_type_args(&mut self) -> Vec<Type> {

          
M fml/src/typeck.rs +40 -6
@@ 168,8 168,8 @@ impl Tck {
                     .iter()
                     .map(|t| self.instantiate(named_types, t))
                     .collect();
-                TypeInfo::Named(s.clone(), inst_args);
-                todo!("Double check this is correct")
+                TypeInfo::Named(s.clone(), inst_args)
+                //todo!("Double check this is correct")
             }
             Type::Generic(s) => {
                 // If we know this is is a particular generic, match wiht it

          
@@ 331,10 331,44 @@ fn typecheck_expr(
             symtbl.add_var(varname, var_type);
             Ok(var_type)
         }
-        Lambda {
-            signature: _,
-            body: _,
-        } => todo!("idk mang"),
+        Lambda { signature, body } => {
+            let mut params = vec![];
+            for (_paramname, paramtype) in &signature.params {
+                let p = tck.insert_known(paramtype);
+                params.push(p);
+                if let Some(name) = paramtype.generic_name() {
+                    symtbl.add_generic(name, p);
+                }
+            }
+            let rettype = tck.insert_known(&signature.rettype);
+            let f = tck.insert(TypeInfo::Func(params, rettype));
+
+            // Add params to function's scope
+            let _guard = symtbl.push_scope();
+            for (paramname, paramtype) in &signature.params {
+                let p = tck.insert_known(paramtype);
+                symtbl.add_var(paramname, p);
+            }
+
+            // Typecheck body
+            for expr in body {
+                typecheck_expr(tck, symtbl, expr).expect("Typecheck failure");
+                // TODO here: unit type for expressions and such
+            }
+            let last_expr = body.last().expect("empty body, aieeee");
+            let last_expr_type = tck.get_expr_type(last_expr);
+            tck.unify(&symtbl, last_expr_type, rettype)
+                .expect("Unification of function body failed, aieeee");
+
+            println!("Typechecked lambda, types are");
+            let mut vars_report: Vec<_> = tck.vars.iter().collect();
+            vars_report.sort_by(|(k1, _), (k2, _)| k1.cmp(k2));
+            for (k, v) in vars_report.iter() {
+                print!("  ${} => {:?}\n", k.0, v);
+            }
+            tck.set_expr_type(expr, f);
+            Ok(f)
+        }
         TupleCtor { body } => {
             let body_types: Result<Vec<_>, _> = body
                 .iter()

          
M fml/tests/main.rs +31 -0
@@ 44,3 44,34 @@ fn test_tuple3() {
     let src = include_str!("test_tuple3.gt");
     let _output = fml::compile("test_tuple3.gt", src);
 }
+
+#[test]
+fn test_lambda1() {
+    let src = include_str!("test_lambda1.gt");
+    let _output = fml::compile("test_lambda1.gt", src);
+}
+
+#[test]
+fn test_lambda2() {
+    let src = include_str!("test_lambda2.gt");
+    let _output = fml::compile("test_lambda2.gt", src);
+}
+
+#[test]
+fn test_lambda3() {
+    let src = include_str!("test_lambda3.gt");
+    let _output = fml::compile("test_lambda3.gt", src);
+}
+
+#[test]
+fn test_lambda4() {
+    let src = include_str!("test_lambda4.gt");
+    let _output = fml::compile("test_lambda4.gt", src);
+}
+
+#[test]
+#[should_panic]
+fn test_lambda5() {
+    let src = include_str!("test_lambda5.gt");
+    let _output = fml::compile("test_lambda5.gt", src);
+}

          
A => fml/tests/test_lambda1.gt +6 -0
@@ 0,0 1,6 @@ 
+
+fn main(): I32 =
+    let f: fn(Bool): Bool = fn(val: Bool): Bool = val end
+    let a: Bool = f(true)
+    3
+end

          
A => fml/tests/test_lambda2.gt +11 -0
@@ 0,0 1,11 @@ 
+
+fn apply_bool(f: fn(Bool): Bool, arg: Bool): Bool =
+    f(arg)
+end
+
+
+fn main(): I32 =
+    let f: fn(Bool): Bool = fn(val: Bool): Bool = val end
+    let a: Bool = apply_bool(f, true)
+    3
+end

          
A => fml/tests/test_lambda3.gt +11 -0
@@ 0,0 1,11 @@ 
+
+fn apply(f: fn(@T): @T, arg: @T): @T =
+    f(arg)
+end
+
+
+fn main(): I32 =
+    let f: fn(Bool): Bool = fn(val: Bool): Bool = val end
+    let a: Bool = apply(f, true)
+    3
+end

          
A => fml/tests/test_lambda4.gt +13 -0
@@ 0,0 1,13 @@ 
+
+fn apply(f: fn(@In): @Out, arg: @In): @Out =
+    f(arg)
+end
+
+
+fn main(): I32 =
+    let f1: fn(Bool): Bool = fn(val: Bool): Bool = val end
+    let f2: fn(Bool): I32 = fn(val: Bool): I32 = 4 end
+    let a: Bool = apply(f1, true)
+    let b: I32 = apply(f2, true)
+    3
+end

          
A => fml/tests/test_lambda5.gt +11 -0
@@ 0,0 1,11 @@ 
+
+fn apply(f: fn(@In): @Out, arg: @In): @Out =
+    f(arg)
+end
+
+
+fn main(): I32 =
+    let f1: fn(Bool): Bool = fn(val: Bool): Bool = val end
+    let a: I32 = apply(f1, true)
+    3
+end