From b3c9bb155e22996269ccfd1871094fd2e8602268 Mon Sep 17 00:00:00 2001 From: Esteve Soler Arderiu Date: Tue, 9 Jan 2024 17:56:50 +0100 Subject: [PATCH 1/3] Fix annoying `Cargo.toml` issues. --- crates/concrete_ast/Cargo.toml | 2 +- crates/concrete_driver/Cargo.toml | 3 ++- crates/concrete_parser/Cargo.toml | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/concrete_ast/Cargo.toml b/crates/concrete_ast/Cargo.toml index 54267ce..d91a8e3 100644 --- a/crates/concrete_ast/Cargo.toml +++ b/crates/concrete_ast/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -tracing.workspace = true +tracing = { workspace = true } diff --git a/crates/concrete_driver/Cargo.toml b/crates/concrete_driver/Cargo.toml index 2338c6d..d329044 100644 --- a/crates/concrete_driver/Cargo.toml +++ b/crates/concrete_driver/Cargo.toml @@ -7,9 +7,10 @@ edition = "2021" [dependencies] clap = { version = "4.4.13", features = ["derive"] } -tracing.workspace = true +tracing = { workspace = true } tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } concrete_ast = { path = "../concrete_ast"} concrete_parser = { path = "../concrete_parser"} concrete_session = { path = "../concrete_session"} concrete_codegen_mlir = { path = "../concrete_codegen_mlir"} +salsa = { git = "https://github.com/salsa-rs/salsa.git", package = "salsa-2022" } diff --git a/crates/concrete_parser/Cargo.toml b/crates/concrete_parser/Cargo.toml index 1040ae9..7f03898 100644 --- a/crates/concrete_parser/Cargo.toml +++ b/crates/concrete_parser/Cargo.toml @@ -8,9 +8,10 @@ edition = "2021" [dependencies] lalrpop-util = { version = "0.20.0", features = ["unicode"] } logos = "0.13.0" -tracing.workspace = true +tracing = { workspace = true } concrete_ast = { path = "../concrete_ast"} owo-colors = "4.0.0" +salsa = { git = "https://github.com/salsa-rs/salsa.git", package = "salsa-2022" } [build-dependencies] lalrpop = "0.20.0" From 03cf9672300df654100d0d2d3fd39fe3cd443e48 Mon Sep 17 00:00:00 2001 From: Esteve Soler Arderiu Date: Tue, 9 Jan 2024 17:57:16 +0100 Subject: [PATCH 2/3] Add salsa and intern the parser's output. --- Cargo.lock | 167 +++++++++++++++++++++++++ crates/concrete_ast/src/constants.rs | 4 +- crates/concrete_ast/src/expressions.rs | 8 +- crates/concrete_ast/src/functions.rs | 4 +- crates/concrete_ast/src/lib.rs | 2 +- crates/concrete_ast/src/modules.rs | 4 +- crates/concrete_ast/src/operations.rs | 22 ++-- crates/concrete_ast/src/statements.rs | 14 +-- crates/concrete_ast/src/structs.rs | 2 +- crates/concrete_driver/src/db.rs | 29 +++++ crates/concrete_driver/src/lib.rs | 15 ++- crates/concrete_parser/src/db.rs | 10 ++ crates/concrete_parser/src/lib.rs | 44 +++---- crates/concrete_parser/src/tokens.rs | 3 +- 14 files changed, 269 insertions(+), 59 deletions(-) create mode 100644 crates/concrete_driver/src/db.rs create mode 100644 crates/concrete_parser/src/db.rs diff --git a/Cargo.lock b/Cargo.lock index 8f2bd1e..f234aa9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,18 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.2" @@ -17,6 +29,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "anstream" version = "0.6.5" @@ -71,6 +89,12 @@ version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +[[package]] +name = "arc-swap" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" + [[package]] name = "ascii-canvas" version = "3.0.0" @@ -324,6 +348,7 @@ dependencies = [ "concrete_codegen_mlir", "concrete_parser", "concrete_session", + "salsa-2022", "tracing", "tracing-subscriber", ] @@ -337,6 +362,7 @@ dependencies = [ "lalrpop-util", "logos", "owo-colors", + "salsa-2022", "tracing", ] @@ -366,6 +392,62 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + [[package]] name = "crunchy" version = "0.2.2" @@ -530,6 +612,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "eyre" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6267a1fa6f59179ea4afc8e50fd8612a3cc60bc858f786ff877a4a8cb042799" +dependencies = [ + "indenter", + "once_cell", +] + [[package]] name = "fancy-regex" version = "0.11.0" @@ -584,6 +676,19 @@ name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown", +] [[package]] name = "heck" @@ -612,6 +717,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + [[package]] name = "indexmap" version = "2.1.0" @@ -1184,6 +1295,36 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" +[[package]] +name = "salsa-2022" +version = "0.1.0" +source = "git+https://github.com/salsa-rs/salsa.git#f1d318a2795e87081e316a5f31ef02f0cd6a1c83" +dependencies = [ + "arc-swap", + "crossbeam", + "crossbeam-utils", + "dashmap", + "hashlink", + "indexmap", + "log", + "parking_lot", + "rustc-hash", + "salsa-2022-macros", + "smallvec", +] + +[[package]] +name = "salsa-2022-macros" +version = "0.1.0" +source = "git+https://github.com/salsa-rs/salsa.git#f1d318a2795e87081e316a5f31ef02f0cd6a1c83" +dependencies = [ + "eyre", + "heck", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "same-file" version = "1.0.6" @@ -1552,6 +1693,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "walkdir" version = "2.4.0" @@ -1811,3 +1958,23 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.47", +] diff --git a/crates/concrete_ast/src/constants.rs b/crates/concrete_ast/src/constants.rs index e42d9a1..7dd0412 100644 --- a/crates/concrete_ast/src/constants.rs +++ b/crates/concrete_ast/src/constants.rs @@ -4,14 +4,14 @@ use crate::{ types::TypeSpec, }; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct ConstantDecl { pub doc_string: Option, pub name: Ident, pub r#type: TypeSpec, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct ConstantDef { pub decl: ConstantDecl, pub value: Expression, diff --git a/crates/concrete_ast/src/expressions.rs b/crates/concrete_ast/src/expressions.rs index dbb78de..81eddc6 100644 --- a/crates/concrete_ast/src/expressions.rs +++ b/crates/concrete_ast/src/expressions.rs @@ -1,26 +1,26 @@ use crate::{operations::Operation, statements::Statement}; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum Expression { Match(MatchExpr), If(IfExpr), Operation(Operation), } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct MatchExpr { pub value: Operation, pub variants: Vec, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct IfExpr { pub value: Operation, pub contents: Vec, pub r#else: Option>, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct MatchVariant { pub case: Operation, pub block: Vec, diff --git a/crates/concrete_ast/src/functions.rs b/crates/concrete_ast/src/functions.rs index 8e084ce..3635665 100644 --- a/crates/concrete_ast/src/functions.rs +++ b/crates/concrete_ast/src/functions.rs @@ -4,7 +4,7 @@ use crate::{ types::TypeSpec, }; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct FunctionDecl { pub doc_string: Option, pub generic_params: Vec, @@ -13,7 +13,7 @@ pub struct FunctionDecl { pub ret_type: Option, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct FunctionDef { pub decl: FunctionDecl, pub body: Vec, diff --git a/crates/concrete_ast/src/lib.rs b/crates/concrete_ast/src/lib.rs index a08098d..a54db00 100644 --- a/crates/concrete_ast/src/lib.rs +++ b/crates/concrete_ast/src/lib.rs @@ -11,7 +11,7 @@ pub mod statements; pub mod structs; pub mod types; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Program { pub modules: Vec, } diff --git a/crates/concrete_ast/src/modules.rs b/crates/concrete_ast/src/modules.rs index a5cb032..00f01c6 100644 --- a/crates/concrete_ast/src/modules.rs +++ b/crates/concrete_ast/src/modules.rs @@ -7,7 +7,7 @@ use crate::{ types::TypeDecl, }; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Module { pub doc_string: Option, pub imports: Vec, @@ -15,7 +15,7 @@ pub struct Module { pub contents: Vec, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum ModuleDefItem { Constant(ConstantDef), Function(FunctionDef), diff --git a/crates/concrete_ast/src/operations.rs b/crates/concrete_ast/src/operations.rs index 17c6dff..18381e0 100644 --- a/crates/concrete_ast/src/operations.rs +++ b/crates/concrete_ast/src/operations.rs @@ -1,24 +1,24 @@ use crate::{common::Ident, types::TypeSpec}; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum PathSegment { FieldAccess(Ident), ArrayIndex(Box), } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct PathOp { pub first: Ident, pub extra: Vec, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum Operation { Compound(CompoundOp), Atomic(AtomicOp), } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum CompoundOp { Compare(CmpOp), Logic(LogicOp), @@ -26,19 +26,19 @@ pub enum CompoundOp { Cast(CastOp), } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum AtomicOp { ConstBool(bool), ConstChar(char), ConstInt(u64), - ConstFloat(f64), + ConstFloat(()), ConstStr(String), FnCall(FnCallOp), Path(PathOp), Paren(Box), } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum CmpOp { Eq(AtomicOp, AtomicOp), NotEq(AtomicOp, AtomicOp), @@ -48,14 +48,14 @@ pub enum CmpOp { GtEq(AtomicOp, AtomicOp), } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum LogicOp { And(AtomicOp, AtomicOp), Or(AtomicOp, AtomicOp), Not(AtomicOp), } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum ArithOp { Add(AtomicOp, AtomicOp), Sub(AtomicOp, AtomicOp), @@ -65,13 +65,13 @@ pub enum ArithOp { Neg(AtomicOp), } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct CastOp { pub value: AtomicOp, pub r#type: TypeSpec, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct FnCallOp { pub target: Ident, pub args: Vec, diff --git a/crates/concrete_ast/src/statements.rs b/crates/concrete_ast/src/statements.rs index 4eb7df8..73e6a5a 100644 --- a/crates/concrete_ast/src/statements.rs +++ b/crates/concrete_ast/src/statements.rs @@ -5,7 +5,7 @@ use crate::{ types::TypeSpec, }; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum Statement { Assign(AssignStmt), Match(MatchExpr), @@ -17,25 +17,25 @@ pub enum Statement { FnCall(FnCallOp), } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum LetStmtTarget { Simple { name: Ident, r#type: TypeSpec }, Destructure(Vec), } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct LetStmt { pub is_mutable: bool, pub target: LetStmtTarget, pub value: Expression, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct ReturnStmt { pub value: Expression, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct AssignStmt { pub target: PathOp, pub value: Expression, @@ -48,7 +48,7 @@ pub struct Binding { pub r#type: TypeSpec, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct ForStmt { pub name: Ident, pub from: Operation, @@ -56,7 +56,7 @@ pub struct ForStmt { pub contents: Vec, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct WhileStmt { pub value: Operation, pub contents: Vec, diff --git a/crates/concrete_ast/src/structs.rs b/crates/concrete_ast/src/structs.rs index 53613b3..2eb44e5 100644 --- a/crates/concrete_ast/src/structs.rs +++ b/crates/concrete_ast/src/structs.rs @@ -3,7 +3,7 @@ use crate::{ types::TypeSpec, }; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct StructDecl { doc_string: Option, name: Ident, diff --git a/crates/concrete_driver/src/db.rs b/crates/concrete_driver/src/db.rs new file mode 100644 index 0000000..3ca1f02 --- /dev/null +++ b/crates/concrete_driver/src/db.rs @@ -0,0 +1,29 @@ +#[salsa::jar(db = Db)] +pub struct Jar( + // TODO: Add stuff. +); + +pub trait Db +where + Self: salsa::DbWithJar + salsa::DbWithJar, +{ +} + +impl Db for T where T: ?Sized + salsa::DbWithJar + salsa::DbWithJar +{} + +#[derive(Default)] +#[salsa::db(Jar, concrete_parser::db::Jar)] +pub(crate) struct Database { + storage: salsa::Storage, +} + +impl salsa::Database for Database {} + +impl salsa::ParallelDatabase for Database { + fn snapshot(&self) -> salsa::Snapshot { + salsa::Snapshot::new(Self { + storage: self.storage.snapshot(), + }) + } +} diff --git a/crates/concrete_driver/src/lib.rs b/crates/concrete_driver/src/lib.rs index 4276898..3d55266 100644 --- a/crates/concrete_driver/src/lib.rs +++ b/crates/concrete_driver/src/lib.rs @@ -1,11 +1,13 @@ -use std::{error::Error, path::PathBuf, time::Instant}; - use clap::Parser; use concrete_codegen_mlir::linker::{link_binary, link_shared_lib}; +use concrete_parser::ProgramSource; use concrete_session::{ config::{DebugInfo, OptLevel}, Session, }; +use std::{error::Error, path::PathBuf, time::Instant}; + +pub mod db; #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] @@ -29,9 +31,10 @@ pub fn main() -> Result<(), Box> { let args = CompilerArgs::parse(); - let source = std::fs::read_to_string(args.input.clone())?; - tracing::debug!("source code:\n{}", source); - let program = concrete_parser::parse_ast(&source); + let db = crate::db::Database::default(); + let source = ProgramSource::new(&db, std::fs::read_to_string(args.input.clone())?); + tracing::debug!("source code:\n{}", source.input(&db)); + let program = concrete_parser::parse_ast(&db, source); let cwd = std::env::current_dir()?; // todo: find a better name, "target" would clash with rust if running in the source tree. @@ -55,7 +58,7 @@ pub fn main() -> Result<(), Box> { } else { OptLevel::None }, - source, + source: source.input(&db).to_string(), library: args.library, target_dir, output_file, diff --git a/crates/concrete_parser/src/db.rs b/crates/concrete_parser/src/db.rs new file mode 100644 index 0000000..9bfd1c8 --- /dev/null +++ b/crates/concrete_parser/src/db.rs @@ -0,0 +1,10 @@ +#[salsa::jar(db = Db)] +pub struct Jar(crate::parse_ast, crate::ProgramSource); + +pub trait Db +where + Self: salsa::DbWithJar, +{ +} + +impl Db for T where T: ?Sized + salsa::DbWithJar {} diff --git a/crates/concrete_parser/src/lib.rs b/crates/concrete_parser/src/lib.rs index 966548c..75a8688 100644 --- a/crates/concrete_parser/src/lib.rs +++ b/crates/concrete_parser/src/lib.rs @@ -1,28 +1,38 @@ -#![allow(unused)] - -use std::error::Error; - use concrete_ast::Program; -use lalrpop_util::lalrpop_mod; use lalrpop_util::ParseError; use lexer::{Lexer, LexicalError}; use owo_colors::OwoColorize; use tokens::Token; +pub mod db; mod lexer; pub mod tokens; -lalrpop_mod!(pub grammar); +pub mod grammar { + #![allow(dead_code, unused_imports, unused_variables)] + + pub use self::grammar::*; + use lalrpop_util::lalrpop_mod; + + lalrpop_mod!(pub grammar); +} + +#[salsa::interned(jar = crate::db::Jar)] +pub struct ProgramSource { + #[return_ref] + pub input: String, +} // Todo: better error handling -pub fn parse_ast(source: &str) -> Program { - let lexer = Lexer::new(source); +#[salsa::tracked(jar = crate::db::Jar)] +pub fn parse_ast(db: &dyn crate::db::Db, source: ProgramSource) -> Program { + let lexer = Lexer::new(source.input(db)); let parser = grammar::ProgramParser::new(); match parser.parse(lexer) { Ok(ast) => ast, Err(e) => { - print_parser_error(source, e); + print_parser_error(source.input(db), e); panic!() } } @@ -31,7 +41,7 @@ pub fn parse_ast(source: &str) -> Program { /// TODO: replace with something better pub fn print_parser_error(source: &str, err: ParseError) { match &err { - ParseError::InvalidToken { location } => todo!(), + ParseError::InvalidToken { .. } => todo!(), ParseError::UnrecognizedEof { location, expected } => { let location = *location; let before = &source[0..location]; @@ -54,22 +64,14 @@ pub fn print_parser_error(source: &str, err: ParseError todo!(), - ParseError::User { error } => todo!(), + ParseError::ExtraToken { .. } => todo!(), + ParseError::User { .. } => todo!(), } } #[cfg(test)] mod tests { - use lalrpop_util::ParseError; - use owo_colors::OwoColorize; - - use crate::{ - grammar, - lexer::{Lexer, LexicalError}, - print_parser_error, - tokens::Token, - }; + use crate::{grammar, lexer::Lexer, print_parser_error}; #[test] fn parse_simple_program() { diff --git a/crates/concrete_parser/src/tokens.rs b/crates/concrete_parser/src/tokens.rs index cee55a4..cc5f535 100644 --- a/crates/concrete_parser/src/tokens.rs +++ b/crates/concrete_parser/src/tokens.rs @@ -1,6 +1,5 @@ use logos::Logos; -use std::str::FromStr; -use std::{convert::Infallible, fmt}; // to implement the Display trait +use std::convert::Infallible; #[derive(Debug, PartialEq, Clone, Default)] pub enum LexingError { From f3fe7d1c2a9439604f3837efb0c28ac32e9dbbf9 Mon Sep 17 00:00:00 2001 From: Esteve Soler Arderiu Date: Tue, 9 Jan 2024 18:24:17 +0100 Subject: [PATCH 3/3] Improve error diagnostics with salsa. --- crates/concrete_driver/src/lib.rs | 16 ++++- crates/concrete_parser/src/db.rs | 6 +- crates/concrete_parser/src/error.rs | 44 ++++++++++++++ crates/concrete_parser/src/lib.rs | 90 ++++------------------------- 4 files changed, 74 insertions(+), 82 deletions(-) create mode 100644 crates/concrete_parser/src/error.rs diff --git a/crates/concrete_driver/src/lib.rs b/crates/concrete_driver/src/lib.rs index 3d55266..437bc91 100644 --- a/crates/concrete_driver/src/lib.rs +++ b/crates/concrete_driver/src/lib.rs @@ -1,6 +1,6 @@ use clap::Parser; use concrete_codegen_mlir::linker::{link_binary, link_shared_lib}; -use concrete_parser::ProgramSource; +use concrete_parser::{error::Diagnostics, ProgramSource}; use concrete_session::{ config::{DebugInfo, OptLevel}, Session, @@ -34,7 +34,19 @@ pub fn main() -> Result<(), Box> { let db = crate::db::Database::default(); let source = ProgramSource::new(&db, std::fs::read_to_string(args.input.clone())?); tracing::debug!("source code:\n{}", source.input(&db)); - let program = concrete_parser::parse_ast(&db, source); + let program = match concrete_parser::parse_ast(&db, source) { + Some(x) => x, + None => { + Diagnostics::dump( + &db, + source, + &concrete_parser::parse_ast::accumulated::( + &db, source, + ), + ); + panic!(); + } + }; let cwd = std::env::current_dir()?; // todo: find a better name, "target" would clash with rust if running in the source tree. diff --git a/crates/concrete_parser/src/db.rs b/crates/concrete_parser/src/db.rs index 9bfd1c8..ce58542 100644 --- a/crates/concrete_parser/src/db.rs +++ b/crates/concrete_parser/src/db.rs @@ -1,5 +1,9 @@ #[salsa::jar(db = Db)] -pub struct Jar(crate::parse_ast, crate::ProgramSource); +pub struct Jar( + crate::error::Diagnostics, + crate::parse_ast, + crate::ProgramSource, +); pub trait Db where diff --git a/crates/concrete_parser/src/error.rs b/crates/concrete_parser/src/error.rs new file mode 100644 index 0000000..81c1e95 --- /dev/null +++ b/crates/concrete_parser/src/error.rs @@ -0,0 +1,44 @@ +use crate::{db::Db, lexer::LexicalError, tokens::Token, ProgramSource}; +use lalrpop_util::ParseError; +use owo_colors::OwoColorize; + +pub type Error = ParseError; + +#[salsa::accumulator(jar = crate::db::Jar)] +pub struct Diagnostics(Error); + +impl Diagnostics { + pub fn dump(db: &dyn Db, source: ProgramSource, errors: &[Error]) { + let source = source.input(db); + + for err in errors { + match &err { + ParseError::InvalidToken { .. } => todo!(), + ParseError::UnrecognizedEof { location, expected } => { + let location = *location; + let before = &source[0..location]; + let after = &source[location..]; + + print!("{}", before); + print!("$Got EOF, expected {:?}$", expected.green().bold()); + print!("{}", after); + } + ParseError::UnrecognizedToken { token, expected } => { + let (l, ref tok, r) = *token; + let before = &source[0..l]; + let after = &source[r..]; + + print!("{}", before); + print!( + "$Got {:?}, expected {:?}$", + tok.bold().red(), + expected.green().bold() + ); + print!("{}", after); + } + ParseError::ExtraToken { .. } => todo!(), + ParseError::User { .. } => todo!(), + } + } + } +} diff --git a/crates/concrete_parser/src/lib.rs b/crates/concrete_parser/src/lib.rs index 750bdf8..4c5875a 100644 --- a/crates/concrete_parser/src/lib.rs +++ b/crates/concrete_parser/src/lib.rs @@ -1,10 +1,8 @@ use concrete_ast::Program; -use lalrpop_util::ParseError; -use lexer::{Lexer, LexicalError}; -use owo_colors::OwoColorize; -use tokens::Token; +use lexer::Lexer; pub mod db; +pub mod error; mod lexer; pub mod tokens; @@ -25,53 +23,22 @@ pub struct ProgramSource { // Todo: better error handling #[salsa::tracked(jar = crate::db::Jar)] -pub fn parse_ast(db: &dyn crate::db::Db, source: ProgramSource) -> Program { +pub fn parse_ast(db: &dyn crate::db::Db, source: ProgramSource) -> Option { let lexer = Lexer::new(source.input(db)); let parser = grammar::ProgramParser::new(); match parser.parse(lexer) { - Ok(ast) => ast, + Ok(ast) => Some(ast), Err(e) => { - print_parser_error(source.input(db), e); - panic!() + crate::error::Diagnostics::push(db, e); + None } } } -/// TODO: replace with something better -pub fn print_parser_error(source: &str, err: ParseError) { - match &err { - ParseError::InvalidToken { .. } => todo!(), - ParseError::UnrecognizedEof { location, expected } => { - let location = *location; - let before = &source[0..location]; - let after = &source[location..]; - - print!("{}", before); - print!("$Got EOF, expected {:?}$", expected.green().bold()); - print!("{}", after); - } - ParseError::UnrecognizedToken { token, expected } => { - let (l, ref tok, r) = *token; - let before = &source[0..l]; - let after = &source[r..]; - - print!("{}", before); - print!( - "$Got {:?}, expected {:?}$", - tok.bold().red(), - expected.green().bold() - ); - print!("{}", after); - } - ParseError::ExtraToken { .. } => todo!(), - ParseError::User { .. } => todo!(), - } -} - #[cfg(test)] mod tests { - use crate::{grammar, lexer::Lexer, print_parser_error}; + use crate::{grammar, lexer::Lexer}; #[test] fn parse_simple_program() { @@ -120,15 +87,7 @@ mod ModuleName { "##; let lexer = Lexer::new(source); let parser = grammar::ProgramParser::new(); - match parser.parse(lexer) { - Ok(ast) => { - dbg!(ast); - } - Err(e) => { - print_parser_error(source, e); - panic!() - } - } + dbg!(parser.parse(lexer).unwrap()); } #[test] @@ -143,16 +102,7 @@ mod ModuleName { }"##; let lexer = Lexer::new(source); let parser = grammar::ProgramParser::new(); - - match parser.parse(lexer) { - Ok(ast) => { - dbg!(ast); - } - Err(e) => { - print_parser_error(source, e); - panic!() - } - } + dbg!(parser.parse(lexer).unwrap()); } #[test] @@ -164,16 +114,7 @@ mod ModuleName { }"##; let lexer = Lexer::new(source); let parser = grammar::ProgramParser::new(); - - match parser.parse(lexer) { - Ok(ast) => { - dbg!(ast); - } - Err(e) => { - print_parser_error(source, e); - panic!() - } - } + dbg!(parser.parse(lexer).unwrap()); } #[test] @@ -185,15 +126,6 @@ mod ModuleName { }"##; let lexer = Lexer::new(source); let parser = grammar::ProgramParser::new(); - - match parser.parse(lexer) { - Ok(ast) => { - dbg!(ast); - } - Err(e) => { - print_parser_error(source, e); - panic!() - } - } + dbg!(parser.parse(lexer).unwrap()); } }