From 7f318d9e1cb0ee97d78db3a810dbd4666324435c Mon Sep 17 00:00:00 2001 From: Mark <> Date: Wed, 3 Jul 2024 20:24:14 +0200 Subject: [PATCH] add some basic tests --- mers_lib/src/lib.rs | 27 ++----------- mers_lib/tests/lang.rs | 91 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 24 deletions(-) create mode 100644 mers_lib/tests/lang.rs diff --git a/mers_lib/src/lib.rs b/mers_lib/src/lib.rs index a7108c4..3424094 100755 --- a/mers_lib/src/lib.rs +++ b/mers_lib/src/lib.rs @@ -25,31 +25,10 @@ pub mod prelude_compile { /// can be used to extend the mers config. /// with this, you can add values (usually functions), -/// or add your own types to the language: +/// or your own custom types to the language. /// -/// use mers_lib::prelude_extend_config::Config; -/// fn add_thing(cfg: Config) -> Config { -/// // use the methods on Config to add things (see the Config source code for examples) -/// cfg.add_var("my_var".to_owned(), todo!()) -/// } -/// -/// then use the Config when compiling and running your code, and your customizations will be available. +/// Your customizations will only be available if you use +/// the infos you got from calling `.infos()` on your `Config` after customizing it. pub mod prelude_extend_config { pub use crate::program::configs::Config; } - -#[test] -fn test_examples() { - for example in std::fs::read_dir("../examples").unwrap() { - let path = example.unwrap().path(); - eprintln!("Checking file {path:?}."); - let src = prelude_compile::Source::new_from_file(path).unwrap(); - let (mut i1, _, mut i3) = prelude_compile::Config::new().bundle_std().infos(); - prelude_compile::parse(&mut src.clone(), &std::sync::Arc::new(src)) - .unwrap() - .compile(&mut i1, program::parsed::CompInfo::default()) - .unwrap() - .check(&mut i3, None) - .unwrap(); - } -} diff --git a/mers_lib/tests/lang.rs b/mers_lib/tests/lang.rs new file mode 100644 index 0000000..705db94 --- /dev/null +++ b/mers_lib/tests/lang.rs @@ -0,0 +1,91 @@ +use std::{fmt::Debug, sync::Arc}; + +use mers_lib::prelude_compile::*; + +use mers_lib::{ + data::{self, Data, Type}, + errors::CheckError, +}; + +#[test] +fn variable() -> Res { + for n in -100..=100 { + let n = n * n; + assert_eq!( + run_code(Config::new(), format!("x := {n}, x"))?, + TypedData( + Type::new(data::int::IntT), + Data::new(data::int::Int(n as _)) + ) + ); + } + Ok(()) +} + +#[test] +fn mutating_a_variable() -> Res { + assert_eq!( + run_code(Config::new(), "x := 5, &x = 2, x")?, + TypedData(Type::new(data::int::IntT), Data::new(data::int::Int(2))) + ); + Ok(()) +} + +#[test] +fn variable_shadowing() -> Res { + assert_eq!( + run_code(Config::new(), "x := 5, { x := 2, &x = 3 }, x")?, + TypedData(Type::new(data::int::IntT), Data::new(data::int::Int(5))) + ); + Ok(()) +} + +#[test] +fn identity_function() -> Res { + assert_eq!( + run_code(Config::new(), "id := x -> x, 4.id")?, + TypedData(Type::new(data::int::IntT), Data::new(data::int::Int(4))) + ); + Ok(()) +} + +type Res = Result<(), CheckError>; + +fn run_code(cfg: Config, code: impl Into) -> Result { + let mut src = Source::new_from_string(code.into()); + let srca = Arc::new(src.clone()); + let parsed = parse(&mut src, &srca)?; + let (mut i1, mut i2, mut i3) = cfg.infos(); + let compiled = parsed.compile(&mut i1, Default::default())?; + let output_type = compiled.check(&mut i3, Default::default())?; + let output_data = compiled.run(&mut i2)?; + Ok(TypedData(output_type, output_data)) +} + +struct TypedData(Type, Data); +impl Debug for TypedData { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Type: {}, Data: {}", self.0, self.1.get()) + } +} +impl PartialEq for TypedData { + fn eq(&self, other: &Self) -> bool { + let t1 = self.0.is_same_type_as(&other.0); + let t2 = other.0.is_same_type_as(&self.0); + let d1 = self.1 == other.1; + let d2 = other.1 == self.1; + if t1 && !t2 { + panic!("self is same type as other, but other is not same type as self (non-symmetrical eq)! self={}, other={}", self.0, other.0); + } + if t2 && !t1 { + panic!("other is same type as self, but self is not same type as other (non-symmetrical eq)! other={}, self={}", other.0, self.0); + } + if d1 && !d2 { + panic!("self is same data as other, but other is not same data as self (non-symmetrical eq)! self={}, other={}", self.1.get(), other.1.get()); + } + if d2 && !d1 { + panic!("other is same data as self, but self is not same data as other (non-symmetrical eq)! other={}, self={}", other.1.get(), self.1.get()); + } + t1 && d1 + } +}