Hmm ok basic structs work

Ok uh I guess we need to be able to stick generics in em now?
5 files changed, 106 insertions(+), 2 deletions(-)

M fml/src/typeck.rs
M fml/tests/main.rs
A => fml/tests/test_struct1.gt
A => fml/tests/test_struct2.gt
A => fml/tests/test_struct3.gt
M fml/src/typeck.rs +31 -2
@@ 126,6 126,20 @@ impl Tck {
                 }
                 self.unify(symtbl, a_o, b_o)
             }
+            (Struct(body1), Struct(body2)) => {
+                for (nm, t1) in body1.iter() {
+                    let t2 = body2[nm];
+                    self.unify(symtbl, *t1, t2)?;
+                }
+                // Now we just do it again the other way around
+                // which is a dumb but effective way of making sure
+                // struct2 doesn't have any fields that struct1 doesn't.
+                for (nm, t2) in body2.iter() {
+                    let t1 = body1[nm];
+                    self.unify(symtbl, t1, *t2)?;
+                }
+                Ok(())
+            }
             (TypeParam(s1), TypeParam(s2)) if s1 == s2 => Ok(()),
             // If no previous attempts to unify were successful, raise an error
             (a, b) => Err(format!("Conflict between {:?} and {:?}", a, b)),

          
@@ 186,7 200,6 @@ impl Tck {
                     .map(|t| self.instantiate(named_types, t))
                     .collect();
                 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

          
@@ 459,7 472,23 @@ fn typecheck_expr(
             Ok(rettype_var)
         }
 
-        StructCtor { body: _ } => todo!("Struct ctor"),
+        StructCtor { body } => {
+            let body_types: Result<HashMap<_, _>, _> = body
+                .iter()
+                .map(|(name, expr)| {
+                    // ? in map doesn't work too well...
+                    match typecheck_expr(tck, symtbl, expr) {
+                        Ok(t) => Ok((name.to_string(), t)),
+                        Err(s) => Err(s),
+                    }
+                })
+                .collect();
+            let body_types = body_types?;
+            let struct_type = TypeInfo::Struct(body_types);
+            let typeid = tck.insert(struct_type);
+            tck.set_expr_type(expr, typeid);
+            Ok(typeid)
+        }
         TypeCtor { name, body } => {
             let named_type = symtbl.get_type(name).expect("Unknown type constructor");
             println!("Got type named {}: is {:?}", name, named_type);

          
M fml/tests/main.rs +13 -0
@@ 99,3 99,16 @@ fn test_struct1() {
     let src = include_str!("test_struct1.gt");
     let _output = fml::compile("test_struct1.gt", src);
 }
+
+#[test]
+fn test_struct2() {
+    let src = include_str!("test_struct2.gt");
+    let _output = fml::compile("test_struct2.gt", src);
+}
+
+#[test]
+#[should_panic]
+fn test_struct3() {
+    let src = include_str!("test_struct3.gt");
+    let _output = fml::compile("test_struct3.gt", src);
+}

          
A => fml/tests/test_struct1.gt +19 -0
@@ 0,0 1,19 @@ 
+
+type Foo = struct
+    a: I32,
+    b: Bool
+end
+
+fn id(x: @T): @T =
+    x
+end
+
+
+fn main(): I32 =
+    let f1: Foo = id($Foo(struct {
+        a = 3,
+        b = false
+    }))
+    let f2: struct a: I32, b: Bool end = id(struct { a = 3, b = false })
+    3
+end

          
A => fml/tests/test_struct2.gt +22 -0
@@ 0,0 1,22 @@ 
+
+type Foo = struct
+    a: I32,
+    b: Bool
+end
+
+fn thing(i: I32): Foo =
+    $Foo(struct {
+        a = i,
+        b = false,
+    })
+end
+
+
+fn main(): I32 =
+    let f1: Foo = $Foo(struct {
+        a = 3,
+        b = false
+    })
+    let f2: Foo = thing(4)
+    3
+end

          
A => fml/tests/test_struct3.gt +21 -0
@@ 0,0 1,21 @@ 
+
+type Foo = struct
+    a: I32,
+    b: Bool
+end
+
+fn thing(i: I32): Foo =
+    $Foo(struct {
+        a = i,
+        b = false,
+    })
+end
+
+
+fn main(): I32 =
+    let f1: Foo = $Foo(struct {
+        a = 3,
+    })
+    let f2: Foo = thing(4)
+    3
+end