From 857f747524a436e9c059529218af54ad66c0c957 Mon Sep 17 00:00:00 2001 From: Romain Paquet Date: Wed, 5 Nov 2025 20:23:17 +0100 Subject: [PATCH] refactor: split project into multiple crates --- Cargo.toml | 45 +++------- flake.nix | 9 +- lila-ast/Cargo.toml | 10 +++ {src/ast => lila-ast/src}/expr.rs | 2 +- src/ast/mod.rs => lila-ast/src/lib.rs | 3 +- lila-ast/src/typing/error.rs | 56 ++++++++++++ lila-ast/src/typing/mod.rs | 73 +++++++++++++++ lila-checking/Cargo.toml | 11 +++ src/typing/mod.rs => lila-checking/src/lib.rs | 88 +++---------------- {src/typing => lila-checking/src}/tests.rs | 12 +-- lila-cli/Cargo.toml | 22 +++++ {src => lila-cli/src}/main.rs | 19 ++-- lila-jit/Cargo.toml | 15 ++++ src/jit/mod.rs => lila-jit/src/lib.rs | 39 ++++---- lila-parsing/Cargo.toml | 29 ++++++ .../src}/backend/handmade/lex.rs | 0 .../src}/backend/handmade/mod.rs | 0 .../src}/backend/mod.rs | 0 .../src}/backend/pest/grammar.pest | 0 .../src}/backend/pest/mod.rs | 10 +-- .../src}/backend/tree_sitter/mod.rs | 0 src/parsing/mod.rs => lila-parsing/src/lib.rs | 2 +- {src/parsing => lila-parsing/src}/tests.rs | 6 +- lila/Cargo.toml | 8 ++ lila/src/lib.rs | 2 + src/typing/error.rs => lila/src/report.rs | 67 ++------------ {src => lila/src}/source.rs | 2 +- 27 files changed, 308 insertions(+), 222 deletions(-) create mode 100644 lila-ast/Cargo.toml rename {src/ast => lila-ast/src}/expr.rs (98%) rename src/ast/mod.rs => lila-ast/src/lib.rs (99%) create mode 100644 lila-ast/src/typing/error.rs create mode 100644 lila-ast/src/typing/mod.rs create mode 100644 lila-checking/Cargo.toml rename src/typing/mod.rs => lila-checking/src/lib.rs (86%) rename {src/typing => lila-checking/src}/tests.rs (87%) create mode 100644 lila-cli/Cargo.toml rename {src => lila-cli/src}/main.rs (93%) create mode 100644 lila-jit/Cargo.toml rename src/jit/mod.rs => lila-jit/src/lib.rs (95%) create mode 100644 lila-parsing/Cargo.toml rename {src/parsing => lila-parsing/src}/backend/handmade/lex.rs (100%) rename {src/parsing => lila-parsing/src}/backend/handmade/mod.rs (100%) rename {src/parsing => lila-parsing/src}/backend/mod.rs (100%) rename {src/parsing => lila-parsing/src}/backend/pest/grammar.pest (100%) rename {src/parsing => lila-parsing/src}/backend/pest/mod.rs (98%) rename {src/parsing => lila-parsing/src}/backend/tree_sitter/mod.rs (100%) rename src/parsing/mod.rs => lila-parsing/src/lib.rs (93%) rename {src/parsing => lila-parsing/src}/tests.rs (97%) create mode 100644 lila/Cargo.toml create mode 100644 lila/src/lib.rs rename src/typing/error.rs => lila/src/report.rs (79%) rename {src => lila/src}/source.rs (95%) diff --git a/Cargo.toml b/Cargo.toml index 099e507..1c8d111 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,34 +1,13 @@ -[package] -name = "lilac" +[workspace] +resolver = "3" +members = [ + "lila", + "lila-ast", + "lila-checking", + "lila-cli", + "lila-jit", + "lila-parsing", +] + +[workspace.package] version = "0.0.1" -edition = "2021" - -[features] -default = ["pest"] -pest = ["dep:pest", "dep:pest_derive"] -tree-sitter = ["dep:tree-sitter", "dep:tree-sitter-lila"] - -[dependencies] -clap = { version = "4.5.7", features = ["derive"] } -cranelift = "0.109.0" -cranelift-jit = "0.109.0" -cranelift-module = "0.109.0" -cranelift-native = "0.109.0" -lazy_static = "1.4.0" -pest = { version = "2.7.4", optional = true } -pest_derive = { version = "2.7.4", optional = true } -tree-sitter = { version = "0.22", optional = true } -ariadne = "0.4.1" -anyhow = "1.0.86" - -[dependencies.tree-sitter-lila] -version = "0.0.1" -optional = true -git = "https://git.sr.ht/~rpqt/tree-sitter-lila" -branch = "main" - -[dev-dependencies] -pretty_assertions = "1.4.0" - -[build-dependencies] -cc = "*" diff --git a/flake.nix b/flake.nix index 0fdd578..191db59 100644 --- a/flake.nix +++ b/flake.nix @@ -26,10 +26,15 @@ let craneLib = crane.mkLib pkgs; - pestFilter = path: _type: (builtins.match ".*\.pest$" path) != null; - sourceFilter = path: type: (craneLib.filterCargoSources path type) || (pestFilter path type); + sourceFilter = + path: type: + builtins.any (suffix: lib.hasSuffix suffix path) [ + ".pest" + ] + || (craneLib.filterCargoSources path type); lilac-crate = craneLib.buildPackage ({ + pname = "lilac"; src = lib.cleanSourceWith { src = ./.; filter = sourceFilter; diff --git a/lila-ast/Cargo.toml b/lila-ast/Cargo.toml new file mode 100644 index 0000000..e0eb123 --- /dev/null +++ b/lila-ast/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "lila-ast" +version = "0.0.1" +edition = "2021" + +[features] +ariadne = [ "dep:ariadne" ] + +[dependencies] +ariadne = { version = "0.4.1", optional = true } diff --git a/src/ast/expr.rs b/lila-ast/src/expr.rs similarity index 98% rename from src/ast/expr.rs rename to lila-ast/src/expr.rs index 71ec649..0d06d48 100644 --- a/src/ast/expr.rs +++ b/lila-ast/src/expr.rs @@ -1,5 +1,5 @@ -use crate::ast::*; use crate::typing::Type; +use crate::*; #[derive(Debug, PartialEq)] pub struct SExpr { diff --git a/src/ast/mod.rs b/lila-ast/src/lib.rs similarity index 99% rename from src/ast/mod.rs rename to lila-ast/src/lib.rs index 6da7ed3..2ee43a2 100644 --- a/src/ast/mod.rs +++ b/lila-ast/src/lib.rs @@ -1,10 +1,10 @@ pub mod expr; +pub mod typing; pub use expr::{BinaryExpression, Expr, SExpr}; use crate::typing::Type; -use ariadne; use std::{fmt::Display, path::Path}; #[derive(Debug, PartialEq, Clone)] @@ -54,6 +54,7 @@ pub struct Span { pub end: usize, } +#[cfg(feature = "ariadne")] impl ariadne::Span for Span { type SourceId = SourceId; diff --git a/lila-ast/src/typing/error.rs b/lila-ast/src/typing/error.rs new file mode 100644 index 0000000..16a2983 --- /dev/null +++ b/lila-ast/src/typing/error.rs @@ -0,0 +1,56 @@ +use std::fmt::Debug; + +use crate::{BinaryOperator, Identifier, ModulePath, Span, Type, UnaryOperator}; + +#[derive(Debug, PartialEq)] +pub struct TypeError { + pub file: Option, + pub module: ModulePath, + pub function: Option, + pub kind: TypeErrorKind, +} + +#[derive(PartialEq, Debug)] +pub struct TypeAndSpan { + pub ty: Type, + pub span: Span, +} + +#[derive(PartialEq, Debug)] +pub struct BinOpAndSpan { + pub op: BinaryOperator, + pub span: Span, +} + +#[derive(Debug, PartialEq)] +pub enum TypeErrorKind { + InvalidBinaryOperator { + operator: BinOpAndSpan, + lhs: TypeAndSpan, + rhs: TypeAndSpan, + }, + BlockTypeDoesNotMatchFunctionType { + block_type: Type, + }, + ReturnTypeDoesNotMatchFunctionType { + return_expr: Option, + return_stmt: TypeAndSpan, + }, + UnknownIdentifier { + identifier: String, + }, + AssignmentMismatch { + lht: Type, + rht: Type, + }, + AssignUndeclared, + VariableRedeclaration, + UnknownFunctionCalled(Identifier), + WrongFunctionArguments, + ConditionIsNotBool, + IfElseMismatch, + InvalidUnaryOperator { + operator: UnaryOperator, + inner: Type, + }, +} diff --git a/lila-ast/src/typing/mod.rs b/lila-ast/src/typing/mod.rs new file mode 100644 index 0000000..2e2c355 --- /dev/null +++ b/lila-ast/src/typing/mod.rs @@ -0,0 +1,73 @@ +pub mod error; + +use crate::{FunctionDefinition, Identifier}; +use std::fmt::Display; + +#[derive(Debug, PartialEq, Clone)] +pub enum Type { + /// Not a real type, used for parsing pass + Undefined, + Bool, + Int, + Float, + Unit, + Str, + Function { + params: Vec, + returns: Box, + }, + Custom(Identifier), +} + +impl Display for Type { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Type::Undefined => f.write_str("UNDEFINED"), + Type::Bool => f.write_str("Bool"), + Type::Int => f.write_str("Int"), + Type::Float => f.write_str("Float"), + Type::Unit => f.write_str("Unit"), + Type::Str => f.write_str("Str"), + Type::Custom(identifier) => f.write_str(identifier), + Type::Function { params, returns } => { + f.write_str("Fn(")?; + for param in params { + f.write_fmt(format_args!("{param}, "))?; + } + f.write_str(") -> ")?; + f.write_fmt(format_args!("{returns}")) + } + } + } +} + +impl From<&str> for Type { + fn from(value: &str) -> Self { + match value { + "int" => Type::Int, + "float" => Type::Float, + "bool" => Type::Bool, + _ => Type::Custom(Identifier::from(value)), + } + } +} + +#[derive(Debug, PartialEq, Clone)] +pub struct Signature(pub Vec, pub Type); + +impl From for Type { + fn from(val: Signature) -> Self { + Type::Function { + params: val.0, + returns: Box::new(val.1), + } + } +} + +impl FunctionDefinition { + pub fn signature(&self) -> Signature { + let return_type = self.return_type.clone().unwrap_or(Type::Unit); + let params_types = self.parameters.iter().map(|p| p.typ.clone()).collect(); + Signature(params_types, return_type) + } +} diff --git a/lila-checking/Cargo.toml b/lila-checking/Cargo.toml new file mode 100644 index 0000000..94a4110 --- /dev/null +++ b/lila-checking/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "lila-checking" +version = "0.0.1" +edition = "2021" + +[dependencies] +lila-ast = { path = "../lila-ast" } + +[dev-dependencies] +lila-parsing = { path = "../lila-parsing" } +pretty_assertions = "1.4.0" diff --git a/src/typing/mod.rs b/lila-checking/src/lib.rs similarity index 86% rename from src/typing/mod.rs rename to lila-checking/src/lib.rs index 3023ae7..58e97f8 100644 --- a/src/typing/mod.rs +++ b/lila-checking/src/lib.rs @@ -1,87 +1,21 @@ -mod error; - -use crate::ast::*; -use crate::typing::error::{TypeAndSpan, TypeError, TypeErrorKind}; use std::collections::HashMap; -use std::fmt::Display; + +use lila_ast::typing::error::{BinOpAndSpan, TypeAndSpan, TypeError, TypeErrorKind}; +use lila_ast::typing::{Signature, Type}; +use lila_ast::*; #[cfg(test)] mod tests; -#[derive(Debug, PartialEq, Clone)] -pub enum Type { - /// Not a real type, used for parsing pass - Undefined, - Bool, - Int, - Float, - Unit, - Str, - Function { - params: Vec, - returns: Box, - }, - Custom(Identifier), -} - -impl Display for Type { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Type::Undefined => f.write_str("UNDEFINED"), - Type::Bool => f.write_str("Bool"), - Type::Int => f.write_str("Int"), - Type::Float => f.write_str("Float"), - Type::Unit => f.write_str("Unit"), - Type::Str => f.write_str("Str"), - Type::Custom(identifier) => f.write_str(identifier), - Type::Function { params, returns } => { - f.write_str("Fn(")?; - for param in params { - f.write_fmt(format_args!("{}, ", param))?; - } - f.write_str(") -> ")?; - f.write_fmt(format_args!("{}", returns)) - } - } - } -} - -impl From<&str> for Type { - fn from(value: &str) -> Self { - match value { - "int" => Type::Int, - "float" => Type::Float, - "bool" => Type::Bool, - _ => Type::Custom(Identifier::from(value)), - } - } -} - -#[derive(Debug, PartialEq, Clone)] -pub struct Signature(Vec, Type); - -impl From for Type { - fn from(val: Signature) -> Self { - Type::Function { - params: val.0, - returns: Box::new(val.1), - } - } -} - -impl FunctionDefinition { - fn signature(&self) -> Signature { - let return_type = self.return_type.clone().unwrap_or(Type::Unit); - let params_types = self.parameters.iter().map(|p| p.typ.clone()).collect(); - Signature(params_types, return_type) - } -} - #[derive(Debug, PartialEq)] pub struct CheckedModule(pub Module); -impl Module { - pub fn type_check(&mut self) -> Result<(), Vec> { +pub trait TypeCheckModule { + fn type_check(&mut self) -> Result<(), Vec>; +} + +impl TypeCheckModule for Module { + fn type_check(&mut self) -> Result<(), Vec> { let mut ctx = TypingContext::new(self.path.clone()); ctx.file.clone_from(&self.file); @@ -325,7 +259,7 @@ impl TypeCheck for Expr { typ, op_span, }) => { - let operator = error::BinOpAndSpan { + let operator = BinOpAndSpan { op: op.clone(), span: *op_span, }; diff --git a/src/typing/tests.rs b/lila-checking/src/tests.rs similarity index 87% rename from src/typing/tests.rs rename to lila-checking/src/tests.rs index 79fa13e..55288ba 100644 --- a/src/typing/tests.rs +++ b/lila-checking/src/tests.rs @@ -1,11 +1,7 @@ -use crate::{ - ast::ModulePath, - parsing::{DefaultParser, Parser}, - typing::error::*, - typing::*, -}; - -#[cfg(test)] +use crate::TypeCheckModule; +use lila_ast::typing::{error::*, Type}; +use lila_ast::ModulePath; +use lila_parsing::{DefaultParser, Parser}; use pretty_assertions::assert_eq; #[test] diff --git a/lila-cli/Cargo.toml b/lila-cli/Cargo.toml new file mode 100644 index 0000000..4bd4a6f --- /dev/null +++ b/lila-cli/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "lila-cli" +version = "0.0.1" +edition = "2021" + +[dependencies] +anyhow = "1.0.86" +ariadne = "0.4.1" +clap = { version = "4.5.7", features = ["derive"] } +lila = { path = "../lila" } +lila-ast = { path = "../lila-ast", features = ["ariadne"] } +lila-checking = { path = "../lila-checking" } +lila-jit = { path = "../lila-jit" } +lila-parsing = { path = "../lila-parsing" } + +[dev-dependencies] +pretty_assertions = "1.4.0" + +[[bin]] +name = "lilac" +path = "src/main.rs" + diff --git a/src/main.rs b/lila-cli/src/main.rs similarity index 93% rename from src/main.rs rename to lila-cli/src/main.rs index d5d6cd0..b2515ce 100644 --- a/src/main.rs +++ b/lila-cli/src/main.rs @@ -1,18 +1,15 @@ -pub mod ast; -pub mod jit; -pub mod parsing; -pub mod source; -pub mod typing; - use std::default::Default; use std::io::Write as _; use std::path::PathBuf; use clap::{Parser as ClapParser, Subcommand}; -use crate::ast::Module; -use crate::parsing::Parser; -use crate::source::SourceCache; +use lila::report::ToReport; +use lila::source::SourceCache; +use lila_ast::Module; +use lila_checking::TypeCheckModule; +use lila_jit as jit; +use lila_parsing::{DefaultParser as LilaParser, Parser as _}; /// Experimental compiler for lila #[derive(ClapParser, Debug)] @@ -59,13 +56,13 @@ enum Commands { } fn parse(files: &[String]) -> Vec { - let mut parser = parsing::DefaultParser::default(); + let mut parser = LilaParser::default(); let paths = files.iter().map(std::path::Path::new); paths .enumerate() .map(|(i, path)| match parser.parse_file(path, i as u32) { Ok(module) => module, - Err(e) => panic!("Parsing error: {:#?}", e), + Err(e) => panic!("Parsing error: {e:#?}"), }) .collect() } diff --git a/lila-jit/Cargo.toml b/lila-jit/Cargo.toml new file mode 100644 index 0000000..670a60b --- /dev/null +++ b/lila-jit/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "lila-jit" +version = "0.0.1" +edition = "2021" + +[dependencies] +ariadne = "0.4.1" # TODO: use ariadne only in CLI +cranelift = "0.109.0" +cranelift-jit = "0.109.0" +cranelift-module = "0.109.0" +cranelift-native = "0.109.0" +lila = { path = "../lila" } +lila-ast = { path = "../lila-ast", features = ["ariadne"] } # TODO: don't include ariadne feature +lila-checking = { path = "../lila-checking" } +lila-parsing = { path = "../lila-parsing" } diff --git a/src/jit/mod.rs b/lila-jit/src/lib.rs similarity index 95% rename from src/jit/mod.rs rename to lila-jit/src/lib.rs index feb05f1..877505b 100644 --- a/src/jit/mod.rs +++ b/lila-jit/src/lib.rs @@ -1,16 +1,17 @@ -use crate::{ - ast::{ - self, expr::BinaryExpression, BinaryOperator, Expr, FunctionDefinition, ModulePath, - ReturnStatement, SourceId, Statement, UnaryOperator, - }, - parsing::{DefaultParser, Parser}, - typing::Type, - SourceCache, -}; use ariadne::Cache as _; use cranelift::{codegen::ir::UserFuncName, prelude::*}; use cranelift_jit::{JITBuilder, JITModule}; use cranelift_module::{DataDescription, FuncId, FuncOrDataId, Linkage, Module}; +use lila::report::ToReport as _; +use lila::source::SourceCache; +use lila_ast as ast; +use lila_ast::typing::{self, Type}; +use lila_ast::{ + expr::BinaryExpression, BinaryOperator, Expr, FunctionDefinition, ModulePath, ReturnStatement, + SourceId, Statement, UnaryOperator, +}; +use lila_checking::TypeCheckModule as _; +use lila_parsing::{DefaultParser, Parser}; use std::collections::HashMap; /// The basic JIT class. @@ -44,7 +45,7 @@ impl Default for JIT { flag_builder.set("is_pic", "false").unwrap(); let isa_builder = cranelift_native::builder().unwrap_or_else(|msg| { - panic!("host machine is not supported: {}", msg); + panic!("host machine is not supported: {msg}"); }); let isa = isa_builder @@ -137,12 +138,12 @@ impl JIT { for param in &func.parameters { assert_ne!(param.typ, Type::Unit); - sig.params.append(&mut Vec::from(¶m.typ)); + sig.params.append(&mut to_abi_params(¶m.typ)); } if let Some(return_type) = &func.return_type { if *return_type != Type::Unit { - sig.returns = return_type.into(); + sig.returns = to_abi_params(return_type); } }; @@ -235,14 +236,12 @@ impl JIT { } } -impl From<&Type> for Vec { - fn from(value: &Type) -> Self { - match value { - Type::Bool => vec![AbiParam::new(types::I8)], - Type::Int => vec![AbiParam::new(types::I32)], - Type::Float => vec![AbiParam::new(types::F32)], - _ => unimplemented!(), - } +fn to_abi_params(value: &Type) -> Vec { + match value { + Type::Bool => vec![AbiParam::new(types::I8)], + Type::Int => vec![AbiParam::new(types::I32)], + Type::Float => vec![AbiParam::new(types::F32)], + _ => unimplemented!(), } } diff --git a/lila-parsing/Cargo.toml b/lila-parsing/Cargo.toml new file mode 100644 index 0000000..ac500ae --- /dev/null +++ b/lila-parsing/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "lila-parsing" +version = "0.0.1" +edition = "2021" + +[features] +default = ["pest"] +pest = ["dep:pest", "dep:pest_derive", "dep:lazy_static"] +tree-sitter = ["dep:tree-sitter", "dep:tree-sitter-lila"] + +[dependencies] +anyhow = "1.0.86" +lazy_static = { version = "1.4.0", optional = true } +lila-ast = { path = "../lila-ast" } +pest = { version = "2.7.4", optional = true } +pest_derive = { version = "2.7.4", optional = true } +tree-sitter = { version = "0.22", optional = true } + +[dependencies.tree-sitter-lila] +version = "0.0.1" +optional = true +git = "https://git.sr.ht/~rpqt/tree-sitter-lila" +branch = "main" + +[build-dependencies] +cc = "*" + +[dev-dependencies] +pretty_assertions = "1.4.0" diff --git a/src/parsing/backend/handmade/lex.rs b/lila-parsing/src/backend/handmade/lex.rs similarity index 100% rename from src/parsing/backend/handmade/lex.rs rename to lila-parsing/src/backend/handmade/lex.rs diff --git a/src/parsing/backend/handmade/mod.rs b/lila-parsing/src/backend/handmade/mod.rs similarity index 100% rename from src/parsing/backend/handmade/mod.rs rename to lila-parsing/src/backend/handmade/mod.rs diff --git a/src/parsing/backend/mod.rs b/lila-parsing/src/backend/mod.rs similarity index 100% rename from src/parsing/backend/mod.rs rename to lila-parsing/src/backend/mod.rs diff --git a/src/parsing/backend/pest/grammar.pest b/lila-parsing/src/backend/pest/grammar.pest similarity index 100% rename from src/parsing/backend/pest/grammar.pest rename to lila-parsing/src/backend/pest/grammar.pest diff --git a/src/parsing/backend/pest/mod.rs b/lila-parsing/src/backend/pest/mod.rs similarity index 98% rename from src/parsing/backend/pest/mod.rs rename to lila-parsing/src/backend/pest/mod.rs index 3dd58fa..e387c21 100644 --- a/src/parsing/backend/pest/mod.rs +++ b/lila-parsing/src/backend/pest/mod.rs @@ -1,14 +1,12 @@ -use expr::BinaryExpression; +use lila_ast::typing::Type; use pest::iterators::Pair; use pest::pratt_parser::PrattParser; use pest::Parser as PestParser; -use ReturnStatement; -use crate::ast::*; -use crate::typing::Type; +use lila_ast::*; #[derive(pest_derive::Parser)] -#[grammar = "parsing/backend/pest/grammar.pest"] +#[grammar = "src/backend/pest/grammar.pest"] struct LilaParser; use lazy_static; @@ -34,7 +32,7 @@ pub struct Parser { source: SourceId, } -impl crate::parsing::Parser for Parser { +impl crate::Parser for Parser { fn parse_as_module( &mut self, source: &str, diff --git a/src/parsing/backend/tree_sitter/mod.rs b/lila-parsing/src/backend/tree_sitter/mod.rs similarity index 100% rename from src/parsing/backend/tree_sitter/mod.rs rename to lila-parsing/src/backend/tree_sitter/mod.rs diff --git a/src/parsing/mod.rs b/lila-parsing/src/lib.rs similarity index 93% rename from src/parsing/mod.rs rename to lila-parsing/src/lib.rs index 5984bfd..78aeec7 100644 --- a/src/parsing/mod.rs +++ b/lila-parsing/src/lib.rs @@ -1,7 +1,7 @@ mod backend; mod tests; -use crate::ast::{Module, ModulePath, SourceId}; +use lila_ast::{Module, ModulePath, SourceId}; pub trait Parser: Default { fn parse_file(&mut self, path: &std::path::Path, id: SourceId) -> anyhow::Result { diff --git a/src/parsing/tests.rs b/lila-parsing/src/tests.rs similarity index 97% rename from src/parsing/tests.rs rename to lila-parsing/src/tests.rs index 0bedf1b..49ea10e 100644 --- a/src/parsing/tests.rs +++ b/lila-parsing/src/tests.rs @@ -3,9 +3,9 @@ use pretty_assertions::assert_eq; #[test] fn test_addition_function() { - use crate::ast::*; - use crate::parsing::*; - use crate::typing::*; + use crate::*; + use lila_ast::typing::*; + use lila_ast::*; let source = "fn add(a: int, b: int) int { a + b }"; let path = ModulePath::from("test"); diff --git a/lila/Cargo.toml b/lila/Cargo.toml new file mode 100644 index 0000000..5291fe0 --- /dev/null +++ b/lila/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "lila" +version = "0.0.1" +edition = "2021" + +[dependencies] +ariadne = "0.4.1" # TODO: only CLI should use ariadne +lila-ast = { path = "../lila-ast" } diff --git a/lila/src/lib.rs b/lila/src/lib.rs new file mode 100644 index 0000000..53ef511 --- /dev/null +++ b/lila/src/lib.rs @@ -0,0 +1,2 @@ +pub mod report; +pub mod source; diff --git a/src/typing/error.rs b/lila/src/report.rs similarity index 79% rename from src/typing/error.rs rename to lila/src/report.rs index 11366a6..115c8db 100644 --- a/src/typing/error.rs +++ b/lila/src/report.rs @@ -1,64 +1,14 @@ use ariadne::{ColorGenerator, Fmt, Label, Report, ReportKind, Span as _}; -use std::fmt::Debug; +use lila_ast::typing::error::{TypeError, TypeErrorKind}; +use lila_ast::typing::Type; +use lila_ast::{Module, Span}; -use super::{Span, UnaryOperator}; -use crate::typing::{BinaryOperator, Identifier, ModulePath, Type}; - -#[derive(Debug, PartialEq)] -pub struct TypeError { - pub file: Option, - pub module: ModulePath, - pub function: Option, - pub kind: TypeErrorKind, +pub trait ToReport { + fn to_report(&self, ast: &Module) -> Report; } -#[derive(PartialEq, Debug)] -pub struct TypeAndSpan { - pub ty: Type, - pub span: Span, -} - -#[derive(PartialEq, Debug)] -pub struct BinOpAndSpan { - pub op: BinaryOperator, - pub span: Span, -} - -#[derive(Debug, PartialEq)] -pub enum TypeErrorKind { - InvalidBinaryOperator { - operator: BinOpAndSpan, - lhs: TypeAndSpan, - rhs: TypeAndSpan, - }, - BlockTypeDoesNotMatchFunctionType { - block_type: Type, - }, - ReturnTypeDoesNotMatchFunctionType { - return_expr: Option, - return_stmt: TypeAndSpan, - }, - UnknownIdentifier { - identifier: String, - }, - AssignmentMismatch { - lht: Type, - rht: Type, - }, - AssignUndeclared, - VariableRedeclaration, - UnknownFunctionCalled(Identifier), - WrongFunctionArguments, - ConditionIsNotBool, - IfElseMismatch, - InvalidUnaryOperator { - operator: UnaryOperator, - inner: Type, - }, -} - -impl TypeError { - pub fn to_report(&self, ast: &crate::ast::Module) -> Report { +impl ToReport for TypeError { + fn to_report(&self, ast: &Module) -> Report { let mut colors = ColorGenerator::new(); let c0 = colors.next(); let c1 = colors.next(); @@ -85,6 +35,7 @@ impl TypeError { .with_color(c2) .with_order(1), ]) + // TODO: add hint for conversion .finish() } @@ -129,7 +80,7 @@ impl TypeError { if let Some(span) = function.return_type_span { report.add_label( Label::new(span) - .with_message(format!("The signature shows {}", func_return_type_text)) + .with_message(format!("The signature shows {func_return_type_text}")) .with_color(signature_color), ); } diff --git a/src/source.rs b/lila/src/source.rs similarity index 95% rename from src/source.rs rename to lila/src/source.rs index 9f53cd7..1148718 100644 --- a/src/source.rs +++ b/lila/src/source.rs @@ -1,5 +1,5 @@ -use crate::ast::SourceId; use ariadne::FileCache; +use lila_ast::SourceId; pub struct SourceCache { pub paths: Vec,