From 82733c6af4f1006ead008bd045cbb3724e397ac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabrielle=20Guimar=C3=A3es=20de=20Oliveira?= Date: Sun, 12 May 2024 10:50:42 -0300 Subject: [PATCH] fix(sol-driver): improve driver suite architeture --- sol-driver/src/suite.rs | 67 ++++++++++++++----- .../church_encoding.expect | 0 .../{ => church_encoding}/church_encoding.sol | 0 sol-driver/tests/mod.rs | 4 +- sol-eval/src/domain.rs | 2 +- sol-eval/src/lib.rs | 3 +- sol-thir-lowering/src/lib.rs | 24 +++---- sol-thir/src/debruijin.rs | 31 +++------ sol-thir/src/lib.rs | 9 ++- sol-thir/src/sexpr.rs | 0 sol-thir/src/shared.rs | 26 ++++++- 11 files changed, 109 insertions(+), 57 deletions(-) rename sol-driver/suite/{ => church_encoding}/church_encoding.expect (100%) rename sol-driver/suite/{ => church_encoding}/church_encoding.sol (100%) create mode 100644 sol-thir/src/sexpr.rs diff --git a/sol-driver/src/suite.rs b/sol-driver/src/suite.rs index 2b5204a..efed52a 100644 --- a/sol-driver/src/suite.rs +++ b/sol-driver/src/suite.rs @@ -13,32 +13,68 @@ use crate::RootDb; #[macro_export] macro_rules! make_test { - ($name:ident, $run:expr) => { + ($category: expr, $name:ident, $run:expr) => { #[test] fn $name() { - let source_code = - std::fs::read_to_string(concat!("suite/", stringify!($name), ".sol")).unwrap(); - let expect = std::fs::read_to_string(concat!("suite/", stringify!($name), ".expect")) - .unwrap_or_default(); - $crate::suite::run_test_suite(stringify!($name), &source_code, &expect, $run); + let source_code = std::fs::read_to_string(concat!( + "suite/", + stringify!($category), + "/", + stringify!($name), + ".sol" + )) + .expect("can't find the source code"); + let expect = std::fs::read_to_string(concat!( + "suite/", + stringify!($category), + "/", + stringify!($name), + ".expect" + )) + .unwrap_or_default(); + $crate::suite::run_test_suite( + stringify!($category), + stringify!($name), + &source_code, + &expect, + $run, + ); } }; - ($name:ident, $file:expr, $run:expr) => { + ($category: expr, $name:ident, $file:expr, $run:expr) => { #[test] fn $name() { - let source_code = std::fs::read_to_string(concat!("suite/", $file, ".sol")).unwrap(); - let expect = - std::fs::read_to_string(concat!("suite/", $file, ".expect")).unwrap_or_default(); - $crate::suite::run_test_suite($file, &source_code, &expect, $run); + let source_code = std::fs::read_to_string(concat!( + "suite/", + stringify!($category), + "/", + $file, + ".sol" + )) + .unwrap(); + let expect = std::fs::read_to_string(concat!( + "suite/", + stringify!($category), + "/", + $file, + ".expect" + )) + .unwrap_or_default(); + $crate::suite::run_test_suite( + stringify!($category), + $file, + &source_code, + &expect, + $run, + ); } }; } #[macro_export] macro_rules! make_test_suite { - (tests ($e:expr) {$($name:ident $file:expr)*} run $run:expr) => { - const _: &str = $e; - $($crate::make_test!($name, $file, $run);)* + (tests $e:ident {$($name:ident)*} run $run:expr) => { + $($crate::make_test!($e, $name, $run);)* }; } @@ -47,6 +83,7 @@ type Expect<'a> = &'a mut dyn Write; /// Runs a test suite, with the given `name` and `f`. pub fn run_test_suite( + category: &str, file: &str, source_code: &str, expect: &str, @@ -66,7 +103,7 @@ pub fn run_test_suite( let output = strip_ansi_escapes::strip_str(String::from_utf8_lossy(&output)); if expect.is_empty() { - std::fs::write(format!("suite/{file}.expect"), output).unwrap(); + std::fs::write(format!("suite/{category}/{file}.expect"), output).unwrap(); return; } if output != expect { diff --git a/sol-driver/suite/church_encoding.expect b/sol-driver/suite/church_encoding/church_encoding.expect similarity index 100% rename from sol-driver/suite/church_encoding.expect rename to sol-driver/suite/church_encoding/church_encoding.expect diff --git a/sol-driver/suite/church_encoding.sol b/sol-driver/suite/church_encoding/church_encoding.sol similarity index 100% rename from sol-driver/suite/church_encoding.sol rename to sol-driver/suite/church_encoding/church_encoding.sol diff --git a/sol-driver/tests/mod.rs b/sol-driver/tests/mod.rs index 7d4665c..eb49f64 100644 --- a/sol-driver/tests/mod.rs +++ b/sol-driver/tests/mod.rs @@ -9,8 +9,8 @@ use utils::create_package; pub mod utils; make_test_suite! { - tests ("church_encoding") { - church_encoding "church_encoding" + tests church_encoding { + church_encoding } run |db, source, output| { let file = SourceFile::new(&db, "repl".into(), "Repl".into(), source); diff --git a/sol-eval/src/domain.rs b/sol-eval/src/domain.rs index c18deae..0a029a6 100644 --- a/sol-eval/src/domain.rs +++ b/sol-eval/src/domain.rs @@ -5,7 +5,7 @@ use std::ops::Deref; use std::panic::{RefUnwindSafe, UnwindSafe}; use std::sync::Arc; -use sol_thir::Value; +use sol_thir::value::Value; use crate::stack::Stack; diff --git a/sol-eval/src/lib.rs b/sol-eval/src/lib.rs index dbd2961..028d90a 100644 --- a/sol-eval/src/lib.rs +++ b/sol-eval/src/lib.rs @@ -12,7 +12,7 @@ use sol_hir::source::{ type_rep::TypeRep, HirSource, }; -use sol_thir::{Env, Value}; +use sol_thir::{shared::Env, value::Value}; pub mod domain; pub mod logic; @@ -66,7 +66,6 @@ pub fn eval_expr(_db: &dyn sol_hir::HirDb, stack: stack::Stack, _env: Env, expr: match expr { Expr::Empty | Expr::Error(_) => stack.unwind("empty expressions can't be evaluated"), Expr::Path(_) => todo!(), - Expr::Meta(_) => todo!(), Expr::Literal(_) => todo!(), Expr::Call(_) => todo!(), Expr::Ann(_) => todo!(), diff --git a/sol-thir-lowering/src/lib.rs b/sol-thir-lowering/src/lib.rs index b8e5684..329c2e6 100644 --- a/sol-thir-lowering/src/lib.rs +++ b/sol-thir-lowering/src/lib.rs @@ -6,37 +6,33 @@ #![feature(trait_upcasting)] use salsa::DbWithJar; -use sol_diagnostic::{Diagnostic, DiagnosticDb, ErrorId, ErrorKind}; use sol_hir::{ - debruijin::{Index, Level}, - lowering::HirLowering, - package::HasManifest, primitives::PrimitiveProvider, solver::{Definition, Reference}, source::{ - expr::{Expr, Meta}, - literal::Literal, - pattern::Pattern, - type_rep::TypeRep, - HirElement, HirError, Location, + expr::Expr, literal::Literal, pattern::Pattern, type_rep::TypeRep, HirElement, HirError, + Location, }, HirDb, }; -use sol_syntax::ParseDb; use sol_thir::{ - shared::{ConstructorKind, Context}, + debruijin::Level, + shared::{Context, Env}, source::Term, value::{Type, Value}, + ThirDb, }; +extern crate salsa_2022 as salsa; + #[salsa::jar(db = ThirLoweringDb)] -pub struct Jar(thir_lower, thir_eval, thir_quote, thir_infer, thir_quote); +pub struct Jar(thir_eval, thir_infer, thir_check, thir_quote); /// The database that stores all the information about the source code. It is /// implemented using the [`salsa`] crate, and it's used by the [`sol-driver`] crate. pub trait ThirLoweringDb: ThirDb + DbWithJar {} -impl ThirLoweringDb for T where T: HirDb + DbWithJar {} +impl ThirLoweringDb for T where T: ThirDb + DbWithJar {} #[salsa::tracked] fn thir_eval(db: &dyn ThirLoweringDb, env: Env, term: Term) -> Value { @@ -53,6 +49,8 @@ fn thir_quote(db: &dyn ThirLoweringDb, lvl: Level, value: Value) -> Term { #[salsa::tracked] fn thir_infer(db: &dyn ThirLoweringDb, ctx: Context, expr: Expr) -> (Term, Type) { ctx.location(db).update(expr.location(db)); + + todo!() } /// The check function to check the type of the term. diff --git a/sol-thir/src/debruijin.rs b/sol-thir/src/debruijin.rs index 5f9ea84..7430ca4 100644 --- a/sol-thir/src/debruijin.rs +++ b/sol-thir/src/debruijin.rs @@ -6,10 +6,12 @@ use super::*; /// Defines a debruijin level. It does represent the level of the context/environment /// /// It can be transformed into a debruijin index by using the [`Level::as_idx`] method. -#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct Level(pub usize); +#[salsa::tracked] +pub struct Level { + pub value: usize, +} -#[derive(thiserror::Error, Debug, Clone)] +#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)] pub enum Level2IdxError { /// The level is greater than the index. #[error("expected l > x")] @@ -19,34 +21,21 @@ pub enum Level2IdxError { LevelEqualToZero, } +#[salsa::tracked] impl Level { /// Transforms a level into a debruijin index. - pub fn as_idx(&self, Level(l): Level) -> Result { - let Level(x) = *self; - if l > x { + #[salsa::tracked] + pub fn as_idx(self, db: &dyn crate::ThirDb, l: Level) -> Result { + if l.value(db) > self.value(db) { return Err(Level2IdxError::LevelGreaterThanIndex); } - if l == 0 { + if l.value(db) == 0 { return Err(Level2IdxError::LevelEqualToZero); } Ok(Index(0)) } } -impl std::ops::Add for Level { - type Output = Self; - - fn add(self, rhs: usize) -> Self::Output { - Self(self.0 + rhs) - } -} - -impl std::ops::AddAssign for Level { - fn add_assign(&mut self, rhs: usize) { - self.0 += rhs - } -} - /// Defines a debruijin index. That can be converted by two levels. /// /// It's used to represent a variable in the syntax tree. diff --git a/sol-thir/src/lib.rs b/sol-thir/src/lib.rs index 6e74f47..2116caf 100644 --- a/sol-thir/src/lib.rs +++ b/sol-thir/src/lib.rs @@ -27,12 +27,19 @@ use crate::{ extern crate salsa_2022 as salsa; pub mod debruijin; +pub mod sexpr; pub mod shared; pub mod source; pub mod value; #[salsa::jar(db = ThirDb)] -pub struct Jar(shared::Env, shared::Context, debruijin::Indices); +pub struct Jar( + shared::Env, + shared::Context, + debruijin::Indices, + debruijin::Level, + debruijin::Level_as_idx, +); pub trait ThirDb: PrimitiveProvider diff --git a/sol-thir/src/sexpr.rs b/sol-thir/src/sexpr.rs new file mode 100644 index 0000000..e69de29 diff --git a/sol-thir/src/shared.rs b/sol-thir/src/shared.rs index 2c9c6cb..fab0afe 100644 --- a/sol-thir/src/shared.rs +++ b/sol-thir/src/shared.rs @@ -1,4 +1,7 @@ -use std::sync::{Arc, Mutex}; +use std::{ + hash::Hash, + sync::{Arc, Mutex}, +}; use super::*; @@ -14,7 +17,6 @@ pub struct Context { pub location: CurrentLocation, } -#[derive(Debug, Clone, Hash, Eq)] pub struct CurrentLocation(Arc>); impl CurrentLocation { @@ -31,12 +33,32 @@ impl CurrentLocation { } } +impl Clone for CurrentLocation { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +impl std::fmt::Debug for CurrentLocation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.lock().unwrap().fmt(f) + } +} + +impl Hash for CurrentLocation { + fn hash(&self, state: &mut H) { + self.0.lock().unwrap().hash(state) + } +} + impl PartialEq for CurrentLocation { fn eq(&self, other: &Self) -> bool { Arc::ptr_eq(&self.0, &other.0) } } +impl Eq for CurrentLocation {} + #[salsa::tracked] pub struct Env { pub values: Vec,