Attempt to make generic inference work.

It's uh...  there's some weird fucking shit going on in there.  I've updated
what I have in the issue: https://todo.sr.ht/~icefox/garnetc/21
43 files changed, 131 insertions(+), 122 deletions(-)

M src/hir.rs
M src/passes/generic_infer.rs
M tests/programs/function_generics1.gt
M tests/programs/function_generics2.gt
M tests/programs/test1.gt
M tests/programs/test2.gt
M tests/programs/test_array1.gt
M tests/programs/test_eq_module.gt
M tests/programs/test_failure.gt
M tests/programs/test_forever1.gt
M tests/programs/test_lambda3.gt
M tests/programs/test_lambda4.gt
M tests/programs/test_lambda5.gt
M tests/programs/test_let1.gt
M tests/programs/test_let2.gt
M tests/programs/test_module1.gt
M tests/programs/test_module2.gt
M tests/programs/test_module3.gt
M tests/programs/test_module4.gt
M tests/programs/test_module6.gt
M tests/programs/test_module7.gt
M tests/programs/test_module_specialization1.gt
M tests/programs/test_monad.gt
M tests/programs/test_monomorphization1.gt
M tests/programs/test_monomorphization2.gt
M tests/programs/test_monomorphization3.gt
M tests/programs/test_result1.gt
M tests/programs/test_struct1.gt
M tests/programs/test_struct5.gt
M tests/programs/test_struct6.gt
M tests/programs/test_sum2.gt
M tests/programs/test_tuple2.gt
M tests/programs/test_tuple3.gt
M tests/programs/test_tuple4.gt
M tests/programs/test_typedef3.gt
M tests/programs/test_typedef4.gt
M tests/programs/test_typedef6.gt
M tests/programs/test_typedef7.gt
M tests/programs/test_typedef8.gt
M tests/programs/test_unnamed_failure1.gt
M tests/programs/test_unnamed_failure2.gt
M tests/programs/test_unnamed_failure3.gt
M tests/programs/test_unnamed_generic.gt
M src/hir.rs +6 -1
@@ 108,7 108,12 @@ impl fmt::Display for Decl {
                 typedecl,
                 params,
             } => {
-                writeln!(f, "type {}({:?}) = {}", name, params, typedecl.get_name())?;
+                let mut buf = String::new();
+                for param in params {
+                    buf += &*param.val();
+                    buf += ", ";
+                }
+                writeln!(f, "type {}({}) = {}", name, buf, typedecl.get_name())?;
             }
             D::Import { name, localname } => {
                 writeln!(f, "import {} as {}", name, localname)?;

          
M src/passes/generic_infer.rs +2 -0
@@ 74,7 74,9 @@ pub(super) fn generic_infer(ir: Ir) -> I
             }
             D::Const { name, typ, init } => {
                 let _guard = symtbl.push_scope();
+                dbg!("dealing with const", name);
                 for name in typ.get_type_params() {
+                    dbg!(name);
                     symtbl.add_type(name, &Type::Generic(name));
                 }
                 D::Const {

          
M tests/programs/function_generics1.gt +3 -3
@@ 9,15 9,15 @@ 
 --     42
 --     42
 
-fn foo(i @T) @T =
+fn foo(|T| i T) T =
     i
 end
 
-fn first(a @T1, b @T2) @T1 =
+fn first(|T1, T2| a T1, b T2) T1 =
     a
 end
 
-fn second(a @T1, b @T2) @T2 =
+fn second(|T1, T2| a T1, b T2) T2 =
     b
 end
 

          
M tests/programs/function_generics2.gt +3 -3
@@ 3,15 3,15 @@ 
 -- Compile:
 --   status: error
 --
-fn foo(i @T) @T =
+fn foo(i T) T =
     i
 end
 
-fn first(a @T1, b @T2) @T1 =
+fn first(a T1, b T2) T1 =
     a
 end
 
-fn second(a @T1, b @T2) @T2 =
+fn second(a T1, b T2) T2 =
     b
 end
 

          
M tests/programs/test1.gt +1 -1
@@ 32,7 32,7 @@ fn invalid2(x I32) Bool =
 end
 -/
 
-fn identity(i @T) @T =
+fn identity(|T| i T) T =
     i
 end
 

          
M tests/programs/test2.gt +2 -2
@@ 8,8 8,8 @@ 
 --     1
 --     false
 
-fn identity(i @T) @T =
-    let y @T = i
+fn identity(|T| i T) T =
+    let y T = i
     y
 end
 

          
M tests/programs/test_array1.gt +3 -3
@@ 3,12 3,12 @@ 
 -- Compile:
 --   status: success
 
-fn identity(i @T) @T =
-    let y @T = i
+fn identity(|T| i T) T =
+    let y T = i
     y
 end
 
-fn foo(i [3]@T) [3]@T =
+fn foo(|T| i [3]T) [3]T =
     i
 end
 

          
M tests/programs/test_eq_module.gt +3 -3
@@ 9,8 9,8 @@ 
 --     true
 
 
-type Eq(@T) = struct
-    eq: fn(@T, @T) Bool,
+type Eq(T) = struct
+    eq: fn(T, T) Bool,
 end
 
 const IntEq Eq(I32) = Eq {

          
@@ 21,7 21,7 @@ const BoolEq Eq(Bool) = Eq {
     .eq = fn(lhs Bool, rhs Bool) Bool = lhs == rhs end,
 }
 
-fn all(|@T| eq_impl Eq(@T), val @T, array [3]@T) Bool =
+fn all(|T| eq_impl Eq(T), val T, array [3]T) Bool =
 	let mut i I32 = 0
 	loop
 		if i == 3 then break end

          
M tests/programs/test_failure.gt +2 -2
@@ 16,11 16,11 @@ fn baz(x Bool) Bool =
     x
 end
 
-fn identity(i @T) @T =
+fn identity(i T) T =
     i
 end
 
-fn identity2(i @X) @X =
+fn identity2(i X) X =
     identity(i)
 end
 

          
M tests/programs/test_forever1.gt +1 -1
@@ 6,7 6,7 @@ 
 -- Who doesn't like infinite recursion?
 -- Actually I'm not sure what this should do.
 -- ...According to OCaml and Rust, the *type checking* is fine.
-fn zoom(i @T) @T =
+fn zoom(|T| i T) T =
     zoom(i)
 end
 

          
M tests/programs/test_lambda3.gt +1 -1
@@ 4,7 4,7 @@ 
 --   status: success
 
 
-fn apply(f fn(@T) @T, arg @T) @T =
+fn apply(|T| f fn(T) T, arg T) T =
     f(arg)
 end
 

          
M tests/programs/test_lambda4.gt +1 -1
@@ 4,7 4,7 @@ 
 --   status: success
 
 
-fn apply(f fn(@In) @Out, arg @In) @Out =
+fn apply(|In, Out| f fn(In) Out, arg In) Out =
     f(arg)
 end
 

          
M tests/programs/test_lambda5.gt +1 -1
@@ 4,7 4,7 @@ 
 --   status: error
 
 
-fn apply(f fn(@In) @Out, arg @In) @Out =
+fn apply(f fn(In) Out, arg In) Out =
     f(arg)
 end
 

          
M tests/programs/test_let1.gt +1 -1
@@ 4,7 4,7 @@ 
 --   status: success
 
 
-fn id(|@T| x @T) @T =
+fn id(|T| x T) T =
     x
 end
 

          
M tests/programs/test_let2.gt +3 -3
@@ 4,12 4,12 @@ 
 --   status: success
 
 
-type Foo(@Thing) = struct
-    a: @Thing,
+type Foo(Thing) = struct
+    a: Thing,
     b: Bool
 end
 
-fn id(|@T| x @T) @T =
+fn id(|T| x T) T =
     x
 end
 

          
M tests/programs/test_module1.gt +3 -3
@@ 14,9 14,9 @@ 
 --
 -- No associated types either, so we just make it a type param for now,
 -- which surprisingly appears to work.
-type Hasher(@Selff, @Out) = struct
-    write: fn(@Selff, I32) @Selff,
-    finish: fn(@Selff) @Out,
+type Hasher(Selff, Out) = struct
+    write: fn(Selff, I32) Selff,
+    finish: fn(Selff) Out,
 end
 
 type DumbHashState = I32

          
M tests/programs/test_module2.gt +3 -3
@@ 11,8 11,8 @@ type String = I32
 
 -- TODO: Make the compiler mangle "Self" since it's a keyword in Rust
 -- Also "self" and "impl"
-type Show(@Selff) = struct
-    show: fn(@Selff) String
+type Show(Selff) = struct
+    show: fn(Selff) String
 end
 
 -- To make this work we need monomorphization, 'cause Rust refuses to

          
@@ 21,7 21,7 @@ const IntShow Show(I32) = Show {
     .show = fn(x I32) String = String(x) end
 }
 
-fn show(show Show(@T), val @T) String =
+fn show(show Show(T), val T) String =
   show$.show(val)
 end
 

          
M tests/programs/test_module3.gt +19 -19
@@ 11,8 11,8 @@ 
 
 -- Fine let's try something simpler.
 
-type Eq(@Selff) = struct
-    eq: fn(@Selff, @Selff) Bool,
+type Eq(Selff) = struct
+    eq: fn(Selff, Selff) Bool,
 end
 
 -- The name here has to be something other than Eq(I32) 'cause we

          
@@ 28,8 28,8 @@ const IntEq Eq(I32) = Eq {
     end,
 }
 
-type Ord(@Selff) = struct
-    cmp: fn(@Selff, @Selff) I32,
+type Ord(Selff) = struct
+    cmp: fn(Selff, Selff) I32,
 end
 
 const IntOrd Ord(I32) = Ord {

          
@@ 39,47 39,47 @@ const IntOrd Ord(I32) = Ord {
 }
 
 
-type From(@Selff, @In) = struct
-    from: fn(@In) @Selff
+type From(Selff, In) = struct
+    from: fn(In) Selff
 end
 
 const BoolFromInt From(Bool, I32) = From {
     .from = fn(i I32) Bool = false end
 }
 
-type List(@T) = struct
-    dummy_data: @T,
+type List(T) = struct
+    dummy_data: T,
 end
 
 
-type Idx(@Selff, @Output) = struct
-    idx: fn(@Selff, I32) @Output,
+type Idx(Selff, Output) = struct
+    idx: fn(Selff, I32) Output,
 end
 
-type Len(@Selff) = struct
-    len: fn(@Selff) I32,
+type Len(Selff) = struct
+    len: fn(Selff) I32,
 end
 
-const ListLen Len(List(@T)) = Len {
-    .len = fn(selff List(@T)) I32 = 0 end
+const ListLen Len(List(T)) = Len {
+    .len = fn(selff List(T)) I32 = 0 end
 }
 
-fn module_len(impll Len(@T), l @T) I32 =
+fn module_len(impll Len(T), l T) I32 =
     let total I32 = 0
     impll$.len(l)
 end
 
 -- Specialize it just to make sure everything fits together...
-fn list_len(l List(@T)) I32 =
+fn list_len(l List(T)) I32 =
     module_len(ListLen, l)
 end
 
-const ListIdx Idx(List(@T), @T) = Idx {
-    .idx = fn(selff List(@T), i I32) @T = selff$.dummy_data end
+const ListIdx Idx(List(T), T) = Idx {
+    .idx = fn(selff List(T), i I32) T = selff$.dummy_data end
 }
 
 -- Generalized thingy...
-fn idx(l List(@T)) @T =
+fn idx(l List(T)) T =
     let total I32 = 3
     ListIdx$.idx(l, total)
 end

          
M tests/programs/test_module4.gt +4 -4
@@ 3,12 3,12 @@ 
 -- Compile:
 --   status: error
 
-type Idx(@Self, @Output) = struct
-    idx: fn(@Self, I32) @Output,
+type Idx(Self, Output) = struct
+    idx: fn(Self, I32) Output,
 end
 
-type List(@T) = struct
-    dummy_data: @T,
+type List(T) = struct
+    dummy_data: T,
 end
 
 fn foo(self List(I32), i I32) Bar =

          
M tests/programs/test_module6.gt +9 -9
@@ 7,26 7,26 @@ 
 --   stdout: 3
 
 -- A generic functional map from a key to a value
-type Map(@T, @K, @V) = struct(@T, @K, @V)
-    get: fn(@T, @K) @V,
-    set: fn(@T, @K, @V) @T,
+type Map(T, K, V) = struct(T, K, V)
+    get: fn(T, K) V,
+    set: fn(T, K, V) T,
 end
 
 -- Implement Map for a cell type
-type Cell(@K, @V) = struct(@K, @V)
-    key: @K,
-    val: @V
+type Cell(K, V) = struct(K, V)
+    key: K,
+    val: V
 end
 
-fn make_cell_map(|@K, @V| k @K, v @V) Map(Cell(@K, @V), @K, @V) =
+fn make_cell_map(|K, V| k K, v V) Map(Cell(K, V), K, V) =
     let module = Map {
         -- I guess we pretend this always succeeds,
         -- since I don't really feel like implementing if's
-        .get = fn(t Cell(@K, @V), key @K) @V =
+        .get = fn(t Cell(K, V), key K) V =
             t$.val
         end,
         -- Just create a new cell with the given key and val
-        .set = fn(t Cell(@K, @V), key @K, val @V) Cell(@K, @V) =
+        .set = fn(t Cell(K, V), key K, val V) Cell(K, V) =
             Cell {
                 .key = key,
                 .val = val,

          
M tests/programs/test_module7.gt +6 -6
@@ 18,19 18,19 @@ module type Functor = sig
 end
 -/
 
-type Functor(@T1, @T2) = struct
-    map: fn(@T1) @T2,
+type Functor(T1, T2) = struct
+    map: fn(T1) T2,
 end
 
 -- Implement Map for a cell type
-type Cell(@V) = struct
-    val: @V
+type Cell(V) = struct
+    val: V
 end
 
-fn make_cell_functor(f fn(@A) @B) Functor(Cell(@A), Cell(@B)) =
+fn make_cell_functor(f fn(A) B) Functor(Cell(A), Cell(B)) =
     -- to work this needs closures, 'cause it
     -- captures f()
-    let m = fn(c Cell(@A)) Cell(@B) =
+    let m = fn(c Cell(A)) Cell(B) =
         Cell({
             .val = f(c$.val)
         })

          
M tests/programs/test_module_specialization1.gt +6 -4
@@ 8,13 8,13 @@ 
 --     4
 
 
-type List(@T) = struct
-    dummy_data: @T,
+type List(T) = struct
+    dummy_data: T,
 end
 
 
-type Idx(@Selff, @Output) = struct
-    idx: fn(@Selff, I32) @Output,
+type Idx(Selff, Output) = struct
+    idx: fn(Selff, I32) Output,
 end
 
 -- Can we make an instance for a specialization of List(T)?

          
@@ 23,8 23,10 @@ const IntListIdx Idx(List(I32), I32) = I
 }
 
 fn main() {} =
+/-
     let x = List { .dummy_data = 4_I32 }
     let y = IntListIdx$.idx(x, 3)
     __println(y); -- gfd parser ambiguity
+    -/
     {}
 end

          
M tests/programs/test_monad.gt +3 -3
@@ 43,8 43,8 @@ end
 -- The bad news is, we don't seem to be able to implement real monads
 -- The good news is, we don't seem to be able to implement real monads
 -- I think if we had associated types?
-type Monad(@A, @M) = struct
-   return_: fn(@A) @M(@A),
-   bind: fn(@M(@A), fn(@A) @M(@B)) @M(@B)
+type Monad(A, M) = struct
+   return_: fn(A) M(A),
+   bind: fn(M(A), fn(A) M(B)) M(B)
 end
 

          
M tests/programs/test_monomorphization1.gt +1 -1
@@ 11,7 11,7 @@ 
 
 -- Test case for monomorphization of functions.
 
-fn identity(i @T) @T =
+fn identity(i T) T =
     let y = i
     y
 end

          
M tests/programs/test_monomorphization2.gt +2 -2
@@ 9,9 9,9 @@ 
 --     2
 
 
-fn identity(i @T) @T =
+fn identity(i T) T =
     -- Does it work properly when we have a declared type for our var?
-    let y @T = i
+    let y T = i
     y
 end
 

          
M tests/programs/test_monomorphization3.gt +2 -2
@@ 18,11 18,11 @@ fn main() {} =
     __println_bool(y.1)
 end
 
-fn thing2(x @A) {I32, @A} =
+fn thing2(x A) {I32, A} =
     thing1(3, x)
 end
 
-fn thing1(i I32, x @A) {I32, @A} =
+fn thing1(i I32, x A) {I32, A} =
     {i, x}
 end
 

          
M tests/programs/test_result1.gt +3 -3
@@ 3,9 3,9 @@ 
 -- Compile:
 --   status: error
 
-type Result(@T, @E) = sum
-    Ok @T,
-    Err @E,
+type Result(T, E) = sum
+    Ok T,
+    Err E,
 end
 
 -- TODO: This should probably succeed

          
M tests/programs/test_struct1.gt +1 -1
@@ 13,7 13,7 @@ type Foo = struct
     b: Bool
 end
 
-fn id(x @T) @T =
+fn id(|T| x T) T =
     x
 end
 

          
M tests/programs/test_struct5.gt +3 -3
@@ 3,12 3,12 @@ 
 -- Compile:
 --   status: error
 
-type Foo(@Thing) = struct
-    a: @Blarg,
+type Foo(Thing) = struct
+    a: Blarg,
     b: Bool
 end
 
-fn id(x @T) @T =
+fn id(x T) T =
     x
 end
 

          
M tests/programs/test_struct6.gt +2 -2
@@ 3,8 3,8 @@ 
 -- Compile:
 --   status: error
 
-type List(@T) = struct
-    dummy_data: @T,
+type List(T) = struct
+    dummy_data: T,
 end
 
 fn foo(self List(I32), i I32) Bar =

          
M tests/programs/test_sum2.gt +5 -5
@@ 12,10 12,10 @@ TFW your typechecker catches a real bug.
 Especially one you don't know how to fix.
 We lower the constructors for this type into functions,
 and then it complains that the function Option.None()
-returns Option(@T) and it has no way of knowing what
-the @T is for that function.
+returns Option(T) and it has no way of knowing what
+the T is for that function.
 
-This should technically be fine because @T is
+This should technically be fine because T is
 instantiated and figured out wherever Option.None()
 is actually called, but I don't know how to tell the
 typechecker that.

          
@@ 30,8 30,8 @@ Added explicit type args to sum types an
 but leaving this note here for now just in case
 it pops up again later.
 -/
-type Option(@T) = sum(@T)
-    Some @T,
+type Option(T) = sum(T)
+    Some T,
     None {},
 end
 

          
M tests/programs/test_tuple2.gt +2 -2
@@ 4,8 4,8 @@ 
 --   status: success
 
 
-fn identity(i @T) @T =
-    let y @T = i
+fn identity(|T| i T) T =
+    let y T = i
     y
 end
 

          
M tests/programs/test_tuple3.gt +2 -2
@@ 4,8 4,8 @@ 
 --   status: error
 
 
-fn identity(i @T) @T =
-    let y @T = i
+fn identity(i T) T =
+    let y T = i
     y
 end
 

          
M tests/programs/test_tuple4.gt +1 -1
@@ 4,7 4,7 @@ 
 --   status: success
 
 
-fn thing(i {@T1, @T2}) {@T1, @T2} =
+fn thing(|T1, T2| i {T1, T2}) {T1, T2} =
     i
 end
 

          
M tests/programs/test_typedef3.gt +2 -2
@@ 4,9 4,9 @@ 
 --   status: error
 
 
-type Foo = {I32, @A}
+type Foo = {I32, A}
 
-fn thing(i I32, x @A) Foo =
+fn thing(i I32, x A) Foo =
     Foo{i, x}
 end
 

          
M tests/programs/test_typedef4.gt +3 -3
@@ 4,13 4,13 @@ 
 --   status: success
 
 
-type Foo(@A) = {I32, @A}
+type Foo(A) = {I32, A}
 
-fn thing(i I32, x @A) Foo(@A) =
+fn thing(|A| i I32, x A) Foo(A) =
     Foo{i, x}
 end
 
-fn thing2(i I32, x @A) {I32, @A} =
+fn thing2(|A| i I32, x A) {I32, A} =
     {i, x}
 end
 

          
M tests/programs/test_typedef6.gt +1 -1
@@ 3,7 3,7 @@ 
 -- Compile:
 --   status: success
 
-type Foo(@T) = {I32, @T}
+type Foo(T) = {I32, T}
 
 fn thing(i I32, x Bool) Foo(Bool) =
     Foo{i, x}

          
M tests/programs/test_typedef7.gt +1 -1
@@ 3,7 3,7 @@ 
 -- Compile:
 --   status: error
 
-type Foo(@T) = {I32, @T}
+type Foo(T) = {I32, T}
 
 fn thing(i I32, x Bool) Foo(Bool) =
     Foo{i, x}

          
M tests/programs/test_typedef8.gt +2 -2
@@ 3,9 3,9 @@ 
 -- Compile:
 --   status: error
 
-type Foo(@T) = {I32, @T}
+type Foo(T) = {I32, T}
 
-fn thing2(i I32, x @Whatever) Foo(@Whatever) =
+fn thing2(i I32, x Whatever) Foo(Whatever) =
     Foo{i, x}
 end
 

          
M tests/programs/test_unnamed_failure1.gt +2 -2
@@ 3,8 3,8 @@ 
 -- Compile:
 --   status: error
 
-type List(@T) = struct
-    dummy_data: @T,
+type List(T) = struct
+    dummy_data: T,
 end
 
 fn should_fail() Bar =

          
M tests/programs/test_unnamed_failure2.gt +4 -4
@@ 7,12 7,12 @@ 
 --     ...Conflict between Bool and Foo()...
 --     ...
 
-type Idx(@Self, @Output) = struct
-    idx: fn(@Self, I32) @Output,
+type Idx(Self, Output) = struct
+    idx: fn(Self, I32) Output,
 end
 
-type List(@T) = struct
-    dummy_data: @T,
+type List(T) = struct
+    dummy_data: T,
 end
 
 

          
M tests/programs/test_unnamed_failure3.gt +4 -4
@@ 7,12 7,12 @@ 
 --     ...Conflict between I32 and Foo()...
 --     ...
 
-type Idx(@Self, @Output) = struct
-    idx: fn(@Self, I32) @Output,
+type Idx(Self, Output) = struct
+    idx: fn(Self, I32) Output,
 end
 
-type List(@T) = struct
-    dummy_data: @T,
+type List(T) = struct
+    dummy_data: T,
 end
 
 

          
M tests/programs/test_unnamed_generic.gt +2 -2
@@ 4,8 4,8 @@ 
 --   status: error
 
 
-fn identity(i @T) @T =
-    let y @Heck = i
+fn identity(i T) T =
+    let y Heck = i
     y
 end