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