From bc785673b2c2537f1dc514819523956cb1b40ceb Mon Sep 17 00:00:00 2001 From: KtorZ Date: Thu, 8 Dec 2022 14:45:26 +0100 Subject: [PATCH] Fix compilation errors for the newly introduce test & add type inference. Tests are basically functions for which the return type should unify with bool. In principle, the type checker could also check that a test function has no arguments but, a test function with arguments wouldn't parse in the first place; feels a bit hacky but it works when considering the pipeline as a whole. Note that the code generation is still to be done. --- crates/lang/src/parser.rs | 2 +- crates/lang/src/tipo/environment.rs | 24 +++++++++++++++++++++++- crates/lang/src/tipo/infer.rs | 14 +++++++++++++- crates/project/src/lib.rs | 3 +++ examples/sample/validators/swap.ak | 4 ++++ 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/crates/lang/src/parser.rs b/crates/lang/src/parser.rs index e7275c6d..d2c98f1c 100644 --- a/crates/lang/src/parser.rs +++ b/crates/lang/src/parser.rs @@ -279,7 +279,7 @@ pub fn test_parser() -> impl Parser Environment<'a> { definition @ (Definition::TypeAlias { .. } | Definition::DataType { .. } | Definition::Use { .. } + | Definition::Test { .. } | Definition::ModuleConstant { .. }) => definition, } } @@ -911,7 +912,10 @@ impl<'a> Environment<'a> { } } - Definition::Fn { .. } | Definition::Use { .. } | Definition::ModuleConstant { .. } => {} + Definition::Fn { .. } + | Definition::Test { .. } + | Definition::Use { .. } + | Definition::ModuleConstant { .. } => {} } Ok(()) @@ -990,6 +994,24 @@ impl<'a> Environment<'a> { } } + Definition::Test(Function { name, location, .. }) => { + hydrators.insert(name.clone(), Hydrator::new()); + let arg_types = vec![]; + let return_type = builtins::bool(); + self.insert_variable( + name.clone(), + ValueConstructorVariant::ModuleFn { + name: name.clone(), + field_map: None, + module: module_name.to_owned(), + arity: 0, + location: *location, + builtin: None, + }, + function(arg_types, return_type), + ); + } + Definition::DataType(DataType { location, public, diff --git a/crates/lang/src/tipo/infer.rs b/crates/lang/src/tipo/infer.rs index 907b731d..9fc64e0a 100644 --- a/crates/lang/src/tipo/infer.rs +++ b/crates/lang/src/tipo/infer.rs @@ -6,6 +6,7 @@ use crate::{ RecordConstructorArg, TypeAlias, TypedDefinition, TypedModule, UntypedDefinition, UntypedModule, Use, }, + builtins, builtins::function, parser::token::Token, IdGenerator, @@ -66,8 +67,8 @@ impl UntypedModule { for def in self.definitions().cloned() { match def { Definition::ModuleConstant { .. } => consts.push(def), - Definition::Fn { .. } + | Definition::Test { .. } | Definition::TypeAlias { .. } | Definition::DataType { .. } | Definition::Use { .. } => not_consts.push(def), @@ -233,6 +234,17 @@ fn infer_definition( })) } + Definition::Test(f) => { + if let Definition::Fn(f) = + infer_definition(Definition::Fn(f), module_name, hydrators, environment)? + { + environment.unify(f.return_type.clone(), builtins::bool(), f.location)?; + Ok(Definition::Test(f)) + } else { + unreachable!("test defintion inferred as something else than a function?") + } + } + Definition::TypeAlias(TypeAlias { doc, location, diff --git a/crates/project/src/lib.rs b/crates/project/src/lib.rs index ab44c08d..e580c803 100644 --- a/crates/project/src/lib.rs +++ b/crates/project/src/lib.rs @@ -336,6 +336,9 @@ impl Project { func, ); } + Definition::Test(_) => { + todo!() + } Definition::TypeAlias(ta) => { type_aliases.insert((module.name.clone(), ta.alias.clone()), ta); } diff --git a/examples/sample/validators/swap.ak b/examples/sample/validators/swap.ak index e1bc32b2..8764f3b6 100644 --- a/examples/sample/validators/swap.ak +++ b/examples/sample/validators/swap.ak @@ -11,3 +11,7 @@ pub fn spend(datum: sample.Datum, rdmr: sample.Redeemer, _ctx: Nil) -> Bool { z == #(#[222], #[222]) } + +test foo() { + 1 + 1 == 2 +}