Skip to content

Commit

Permalink
Improve type checking tests
Browse files Browse the repository at this point in the history
  • Loading branch information
JonathanBrouwer committed Nov 24, 2023
1 parent 0ae9ee7 commit 165cba0
Show file tree
Hide file tree
Showing 67 changed files with 243 additions and 215 deletions.
58 changes: 57 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions compiler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ lalrpop = "0.20.0"
[dev-dependencies]
test_each_file = "0.1.1"
tempfile = "3.8.1"
enum-display = "0.1.3"
derive-name = "1.1.0"
2 changes: 1 addition & 1 deletion compiler/src/passes/validate/constrain/apply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub fn constrain_apply<'p>(env: &mut Env<'_, 'p>, span: Span, fun: Box<Meta<Span

let p_typ = env.uf.get(fun.meta.index).clone();
let PartialType::Fn { params, typ } = p_typ else {
return Err(TypeError::TypeMismatchExpectFn {
return Err(TypeError::MismatchedExpectFn {
got: p_typ.to_string(&mut env.uf),
span_got: fun.meta.span,
});
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/passes/validate/constrain/break.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub fn constrain_break<'p>(env: &mut Env<'_, 'p>, span: Span, bdy: Box<Meta<Span
let bdy = expr::constrain_expr(*bdy, env)?;
env.uf
.expect_equal(bdy.meta.index, loop_type, |got, expect| {
TypeError::TypeMismatchLoop {
TypeError::MismatchedLoop {
expect,
got,
span_break: bdy.meta.span,
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/passes/validate/constrain/struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub fn constrain_struct<'p>(env: &mut Env<'_, 'p>, span: Span, sym: Meta<Span, U

expect(
seen_fields.insert(field_sym.inner),
TypeError::VariableConstructDuplicateField {
TypeError::ConstructDuplicateField {
sym: field_sym.to_string(),
span: field_sym.meta,
},
Expand Down Expand Up @@ -67,7 +67,7 @@ pub fn constrain_struct<'p>(env: &mut Env<'_, 'p>, span: Span, sym: Meta<Span, U
for (def_sym, (def_span, _)) in def_fields {
expect(
seen_fields.contains(def_sym),
TypeError::VariableConstructMissingField {
TypeError::ConstructMissingField {
sym: def_sym.to_string(),
struct_span: sym.meta,
def_span,
Expand Down
32 changes: 7 additions & 25 deletions compiler/src/passes/validate/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use miette::Diagnostic;
use thiserror::Error;
#[cfg(test)]
use derive_name::VariantName;

#[cfg_attr(test, derive(VariantName))]
#[derive(Debug, Error, Diagnostic)]
pub enum TypeError {
#[error("Encountered an undeclared variable.")]
Expand All @@ -9,23 +12,6 @@ pub enum TypeError {
#[label = "This variable `{sym}` was not declared yet"]
span: (usize, usize),
},
// #[error("Type was mismatched.")]
// MismatchedType {
// expect: Type<String>,
// got: Type<String>,
// #[label = "Expected this to be of type `{expect}`, but got `{got}`"]
// span: (usize, usize),
// },

// #[error("Types were mismatched. Expected '{t1}' and '{t2}' to be equal.")]
// MismatchedTypes {
// t1: Type<String>,
// t2: Type<String>,
// #[label = "This has type `{t1}`"]
// span_t1: (usize, usize),
// #[label = "but this has type `{t2}`"]
// span_t2: (usize, usize),
// },
// #[error("There are multiple functions named `{sym}`.")]
// DuplicateFunction { sym: String },
// #[error("Function `{sym}` has duplicate argument names.")]
Expand Down Expand Up @@ -55,30 +41,26 @@ pub enum TypeError {
#[label = "This should be a struct."]
span: (usize, usize),
},
// #[error("The name `{sym}` should refer to a struct type.'")]
// VariableShouldBeStruct { sym: String },
#[error("Unknown struct field.")]
UnknownStructField {
sym: String,
#[label = "The field `{sym}` is not present in the struct definition."]
span: (usize, usize),
},
#[error("Missing struct field.")]
VariableConstructMissingField {
ConstructMissingField {
sym: String,
#[label = "The field `{sym}` is missing in the struct."]
struct_span: (usize, usize),
#[label = "It was defined here."]
def_span: (usize, usize),
},
#[error("Duplicate struct field.")]
VariableConstructDuplicateField {
ConstructDuplicateField {
sym: String,
#[label = "The field `{sym}` was already provided earlier."]
span: (usize, usize),
},
// #[error("The type `{typ}` should be a struct type.'")]
// TypeShouldBeStruct { typ: Type<String> },
#[error("Unsized type.")]
UnsizedType {
sym: String,
Expand Down Expand Up @@ -185,15 +167,15 @@ pub enum TypeError {
},

#[error("Types did not match.")]
TypeMismatchExpectFn {
MismatchedExpectFn {
got: String,

#[label = "Expected function, but found '{got}'"]
span_got: (usize, usize),
},

#[error("Types did not match.")]
TypeMismatchLoop {
MismatchedLoop {
expect: String,
got: String,

Expand Down
14 changes: 9 additions & 5 deletions compiler/src/passes/validate/tests.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
use derive_name::VariantName;
use crate::passes::parse::parse::parse_program;
use crate::utils::split_test::split_test;
use miette::{NamedSource, Report};
use test_each_file::test_each_file;

fn validate([test]: [&str; 1]) {
fn validate([test]: [&str; 1], good: bool) {
let (_, _, _, expected_error) = split_test(test);
assert_eq!(good, expected_error.is_none());

let result = parse_program(test).unwrap().validate();

match (result, expected_error) {
(Ok(_), None) => {}
(Ok(p), Some(expected_error)) => {
(Ok(_), Some(expected_error)) => {
panic!("Expected validation to fail with: {expected_error}.")
}
(Err(error), None) => {
Expand All @@ -21,9 +23,11 @@ fn validate([test]: [&str; 1]) {
println!("{report}");
panic!("Expected validation to succeed.")
}
(Err(_), Some(_)) => {}
(Err(e), Some(expected_error)) => {
assert_eq!(e.variant_name(), expected_error);
}
}
}

test_each_file! { for ["test"] in "./programs/good" as validate_succeed => validate }
test_each_file! { for ["test"] in "./programs/fail/validate" as validate_fail => validate }
test_each_file! { for ["test"] in "./programs/good" as validate_succeed => |i| validate(i, true) }
test_each_file! { for ["test"] in "./programs/fail/validate" as validate_fail => |i| validate(i, false) }
4 changes: 0 additions & 4 deletions programs/fail/validate/add_bool.test

This file was deleted.

4 changes: 0 additions & 4 deletions programs/fail/validate/and_num.test

This file was deleted.

6 changes: 6 additions & 0 deletions programs/fail/validate/arg_count_mismatch.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//* err: ArgCountMismatch
fn test() {}

fn main() {
test(true);
}
9 changes: 0 additions & 9 deletions programs/fail/validate/bad_return.test

This file was deleted.

4 changes: 0 additions & 4 deletions programs/fail/validate/bad_return_simple.test

This file was deleted.

6 changes: 3 additions & 3 deletions programs/fail/validate/break_outside_loop.test
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//* err: todo!
fn main() -> Unit {
break
//* err: BreakOutsideLoop
fn main() {
break;
}
11 changes: 11 additions & 0 deletions programs/fail/validate/construct_duplicate_field.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//* err: ConstructDuplicateField
struct TestStruct {
field_1: I64,
}

fn main() {
let x = TestStruct {
field_1: 13,
field_1: 8,
};
}
11 changes: 11 additions & 0 deletions programs/fail/validate/construct_missing_field.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//* err: ConstructMissingField
struct TestStruct {
field_1: I64,
field_2: I64,
}

fn main() {
let x = TestStruct {
field_1: 13,
};
}
4 changes: 4 additions & 0 deletions programs/fail/validate/continue_outside_loop.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//* err: ContinueOutsideLoop
fn main() {
continue;
}
Empty file.
Empty file.
4 changes: 0 additions & 4 deletions programs/fail/validate/eq_unmatched.test

This file was deleted.

6 changes: 6 additions & 0 deletions programs/fail/validate/fn_arg_expect.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//* err: FnArgExpect
fn test(x: Bool) {}

fn main() {
test(42i64);
}
5 changes: 0 additions & 5 deletions programs/fail/validate/fn_rtrn_1.test

This file was deleted.

4 changes: 0 additions & 4 deletions programs/fail/validate/fn_rtrn_2.test

This file was deleted.

4 changes: 4 additions & 0 deletions programs/fail/validate/if_expect_bool.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//* err: IfExpectBool
fn main() {
if 5i64 { unit };
}
8 changes: 8 additions & 0 deletions programs/fail/validate/if_expect_equal_1.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//* err: IfExpectEqual
fn main() {
if true {
5i64
} else {
true
};
}
6 changes: 6 additions & 0 deletions programs/fail/validate/if_expect_equal_2.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//* err: IfExpectEqual
fn main() {
if true {
5i64
};
}
8 changes: 0 additions & 8 deletions programs/fail/validate/if_num.test

This file was deleted.

8 changes: 0 additions & 8 deletions programs/fail/validate/if_unmatched.test

This file was deleted.

Loading

0 comments on commit 165cba0

Please sign in to comment.