refactor: split project into multiple crates
This commit is contained in:
parent
486af67fc2
commit
857f747524
27 changed files with 308 additions and 222 deletions
45
Cargo.toml
45
Cargo.toml
|
|
@ -1,34 +1,13 @@
|
||||||
[package]
|
[workspace]
|
||||||
name = "lilac"
|
resolver = "3"
|
||||||
|
members = [
|
||||||
|
"lila",
|
||||||
|
"lila-ast",
|
||||||
|
"lila-checking",
|
||||||
|
"lila-cli",
|
||||||
|
"lila-jit",
|
||||||
|
"lila-parsing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[workspace.package]
|
||||||
version = "0.0.1"
|
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 = "*"
|
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,15 @@
|
||||||
let
|
let
|
||||||
craneLib = crane.mkLib pkgs;
|
craneLib = crane.mkLib pkgs;
|
||||||
|
|
||||||
pestFilter = path: _type: (builtins.match ".*\.pest$" path) != null;
|
sourceFilter =
|
||||||
sourceFilter = path: type: (craneLib.filterCargoSources path type) || (pestFilter path type);
|
path: type:
|
||||||
|
builtins.any (suffix: lib.hasSuffix suffix path) [
|
||||||
|
".pest"
|
||||||
|
]
|
||||||
|
|| (craneLib.filterCargoSources path type);
|
||||||
|
|
||||||
lilac-crate = craneLib.buildPackage ({
|
lilac-crate = craneLib.buildPackage ({
|
||||||
|
pname = "lilac";
|
||||||
src = lib.cleanSourceWith {
|
src = lib.cleanSourceWith {
|
||||||
src = ./.;
|
src = ./.;
|
||||||
filter = sourceFilter;
|
filter = sourceFilter;
|
||||||
|
|
|
||||||
10
lila-ast/Cargo.toml
Normal file
10
lila-ast/Cargo.toml
Normal file
|
|
@ -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 }
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::ast::*;
|
|
||||||
use crate::typing::Type;
|
use crate::typing::Type;
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct SExpr {
|
pub struct SExpr {
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
pub mod expr;
|
pub mod expr;
|
||||||
|
pub mod typing;
|
||||||
|
|
||||||
pub use expr::{BinaryExpression, Expr, SExpr};
|
pub use expr::{BinaryExpression, Expr, SExpr};
|
||||||
|
|
||||||
use crate::typing::Type;
|
use crate::typing::Type;
|
||||||
|
|
||||||
use ariadne;
|
|
||||||
use std::{fmt::Display, path::Path};
|
use std::{fmt::Display, path::Path};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
|
@ -54,6 +54,7 @@ pub struct Span {
|
||||||
pub end: usize,
|
pub end: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ariadne")]
|
||||||
impl ariadne::Span for Span {
|
impl ariadne::Span for Span {
|
||||||
type SourceId = SourceId;
|
type SourceId = SourceId;
|
||||||
|
|
||||||
56
lila-ast/src/typing/error.rs
Normal file
56
lila-ast/src/typing/error.rs
Normal file
|
|
@ -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<std::path::PathBuf>,
|
||||||
|
pub module: ModulePath,
|
||||||
|
pub function: Option<String>,
|
||||||
|
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<TypeAndSpan>,
|
||||||
|
return_stmt: TypeAndSpan,
|
||||||
|
},
|
||||||
|
UnknownIdentifier {
|
||||||
|
identifier: String,
|
||||||
|
},
|
||||||
|
AssignmentMismatch {
|
||||||
|
lht: Type,
|
||||||
|
rht: Type,
|
||||||
|
},
|
||||||
|
AssignUndeclared,
|
||||||
|
VariableRedeclaration,
|
||||||
|
UnknownFunctionCalled(Identifier),
|
||||||
|
WrongFunctionArguments,
|
||||||
|
ConditionIsNotBool,
|
||||||
|
IfElseMismatch,
|
||||||
|
InvalidUnaryOperator {
|
||||||
|
operator: UnaryOperator,
|
||||||
|
inner: Type,
|
||||||
|
},
|
||||||
|
}
|
||||||
73
lila-ast/src/typing/mod.rs
Normal file
73
lila-ast/src/typing/mod.rs
Normal file
|
|
@ -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<Type>,
|
||||||
|
returns: Box<Type>,
|
||||||
|
},
|
||||||
|
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<Type>, pub Type);
|
||||||
|
|
||||||
|
impl From<Signature> 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
11
lila-checking/Cargo.toml
Normal file
11
lila-checking/Cargo.toml
Normal file
|
|
@ -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"
|
||||||
|
|
@ -1,87 +1,21 @@
|
||||||
mod error;
|
|
||||||
|
|
||||||
use crate::ast::*;
|
|
||||||
use crate::typing::error::{TypeAndSpan, TypeError, TypeErrorKind};
|
|
||||||
use std::collections::HashMap;
|
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)]
|
#[cfg(test)]
|
||||||
mod tests;
|
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<Type>,
|
|
||||||
returns: Box<Type>,
|
|
||||||
},
|
|
||||||
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>, Type);
|
|
||||||
|
|
||||||
impl From<Signature> 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)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct CheckedModule(pub Module);
|
pub struct CheckedModule(pub Module);
|
||||||
|
|
||||||
impl Module {
|
pub trait TypeCheckModule {
|
||||||
pub fn type_check(&mut self) -> Result<(), Vec<TypeError>> {
|
fn type_check(&mut self) -> Result<(), Vec<TypeError>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeCheckModule for Module {
|
||||||
|
fn type_check(&mut self) -> Result<(), Vec<TypeError>> {
|
||||||
let mut ctx = TypingContext::new(self.path.clone());
|
let mut ctx = TypingContext::new(self.path.clone());
|
||||||
ctx.file.clone_from(&self.file);
|
ctx.file.clone_from(&self.file);
|
||||||
|
|
||||||
|
|
@ -325,7 +259,7 @@ impl TypeCheck for Expr {
|
||||||
typ,
|
typ,
|
||||||
op_span,
|
op_span,
|
||||||
}) => {
|
}) => {
|
||||||
let operator = error::BinOpAndSpan {
|
let operator = BinOpAndSpan {
|
||||||
op: op.clone(),
|
op: op.clone(),
|
||||||
span: *op_span,
|
span: *op_span,
|
||||||
};
|
};
|
||||||
|
|
@ -1,11 +1,7 @@
|
||||||
use crate::{
|
use crate::TypeCheckModule;
|
||||||
ast::ModulePath,
|
use lila_ast::typing::{error::*, Type};
|
||||||
parsing::{DefaultParser, Parser},
|
use lila_ast::ModulePath;
|
||||||
typing::error::*,
|
use lila_parsing::{DefaultParser, Parser};
|
||||||
typing::*,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
22
lila-cli/Cargo.toml
Normal file
22
lila-cli/Cargo.toml
Normal file
|
|
@ -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"
|
||||||
|
|
||||||
|
|
@ -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::default::Default;
|
||||||
use std::io::Write as _;
|
use std::io::Write as _;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use clap::{Parser as ClapParser, Subcommand};
|
use clap::{Parser as ClapParser, Subcommand};
|
||||||
|
|
||||||
use crate::ast::Module;
|
use lila::report::ToReport;
|
||||||
use crate::parsing::Parser;
|
use lila::source::SourceCache;
|
||||||
use crate::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
|
/// Experimental compiler for lila
|
||||||
#[derive(ClapParser, Debug)]
|
#[derive(ClapParser, Debug)]
|
||||||
|
|
@ -59,13 +56,13 @@ enum Commands {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse(files: &[String]) -> Vec<Module> {
|
fn parse(files: &[String]) -> Vec<Module> {
|
||||||
let mut parser = parsing::DefaultParser::default();
|
let mut parser = LilaParser::default();
|
||||||
let paths = files.iter().map(std::path::Path::new);
|
let paths = files.iter().map(std::path::Path::new);
|
||||||
paths
|
paths
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, path)| match parser.parse_file(path, i as u32) {
|
.map(|(i, path)| match parser.parse_file(path, i as u32) {
|
||||||
Ok(module) => module,
|
Ok(module) => module,
|
||||||
Err(e) => panic!("Parsing error: {:#?}", e),
|
Err(e) => panic!("Parsing error: {e:#?}"),
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
15
lila-jit/Cargo.toml
Normal file
15
lila-jit/Cargo.toml
Normal file
|
|
@ -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" }
|
||||||
|
|
@ -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 ariadne::Cache as _;
|
||||||
use cranelift::{codegen::ir::UserFuncName, prelude::*};
|
use cranelift::{codegen::ir::UserFuncName, prelude::*};
|
||||||
use cranelift_jit::{JITBuilder, JITModule};
|
use cranelift_jit::{JITBuilder, JITModule};
|
||||||
use cranelift_module::{DataDescription, FuncId, FuncOrDataId, Linkage, Module};
|
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;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
/// The basic JIT class.
|
/// The basic JIT class.
|
||||||
|
|
@ -44,7 +45,7 @@ impl Default for JIT {
|
||||||
flag_builder.set("is_pic", "false").unwrap();
|
flag_builder.set("is_pic", "false").unwrap();
|
||||||
|
|
||||||
let isa_builder = cranelift_native::builder().unwrap_or_else(|msg| {
|
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
|
let isa = isa_builder
|
||||||
|
|
@ -137,12 +138,12 @@ impl JIT {
|
||||||
|
|
||||||
for param in &func.parameters {
|
for param in &func.parameters {
|
||||||
assert_ne!(param.typ, Type::Unit);
|
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 let Some(return_type) = &func.return_type {
|
||||||
if *return_type != Type::Unit {
|
if *return_type != Type::Unit {
|
||||||
sig.returns = return_type.into();
|
sig.returns = to_abi_params(return_type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -235,15 +236,13 @@ impl JIT {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Type> for Vec<AbiParam> {
|
fn to_abi_params(value: &Type) -> Vec<AbiParam> {
|
||||||
fn from(value: &Type) -> Self {
|
|
||||||
match value {
|
match value {
|
||||||
Type::Bool => vec![AbiParam::new(types::I8)],
|
Type::Bool => vec![AbiParam::new(types::I8)],
|
||||||
Type::Int => vec![AbiParam::new(types::I32)],
|
Type::Int => vec![AbiParam::new(types::I32)],
|
||||||
Type::Float => vec![AbiParam::new(types::F32)],
|
Type::Float => vec![AbiParam::new(types::F32)],
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A collection of state used for translating from AST nodes
|
/// A collection of state used for translating from AST nodes
|
||||||
29
lila-parsing/Cargo.toml
Normal file
29
lila-parsing/Cargo.toml
Normal file
|
|
@ -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"
|
||||||
|
|
@ -1,14 +1,12 @@
|
||||||
use expr::BinaryExpression;
|
use lila_ast::typing::Type;
|
||||||
use pest::iterators::Pair;
|
use pest::iterators::Pair;
|
||||||
use pest::pratt_parser::PrattParser;
|
use pest::pratt_parser::PrattParser;
|
||||||
use pest::Parser as PestParser;
|
use pest::Parser as PestParser;
|
||||||
use ReturnStatement;
|
|
||||||
|
|
||||||
use crate::ast::*;
|
use lila_ast::*;
|
||||||
use crate::typing::Type;
|
|
||||||
|
|
||||||
#[derive(pest_derive::Parser)]
|
#[derive(pest_derive::Parser)]
|
||||||
#[grammar = "parsing/backend/pest/grammar.pest"]
|
#[grammar = "src/backend/pest/grammar.pest"]
|
||||||
struct LilaParser;
|
struct LilaParser;
|
||||||
|
|
||||||
use lazy_static;
|
use lazy_static;
|
||||||
|
|
@ -34,7 +32,7 @@ pub struct Parser {
|
||||||
source: SourceId,
|
source: SourceId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::parsing::Parser for Parser {
|
impl crate::Parser for Parser {
|
||||||
fn parse_as_module(
|
fn parse_as_module(
|
||||||
&mut self,
|
&mut self,
|
||||||
source: &str,
|
source: &str,
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
mod backend;
|
mod backend;
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use crate::ast::{Module, ModulePath, SourceId};
|
use lila_ast::{Module, ModulePath, SourceId};
|
||||||
|
|
||||||
pub trait Parser: Default {
|
pub trait Parser: Default {
|
||||||
fn parse_file(&mut self, path: &std::path::Path, id: SourceId) -> anyhow::Result<Module> {
|
fn parse_file(&mut self, path: &std::path::Path, id: SourceId) -> anyhow::Result<Module> {
|
||||||
|
|
@ -3,9 +3,9 @@ use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_addition_function() {
|
fn test_addition_function() {
|
||||||
use crate::ast::*;
|
use crate::*;
|
||||||
use crate::parsing::*;
|
use lila_ast::typing::*;
|
||||||
use crate::typing::*;
|
use lila_ast::*;
|
||||||
|
|
||||||
let source = "fn add(a: int, b: int) int { a + b }";
|
let source = "fn add(a: int, b: int) int { a + b }";
|
||||||
let path = ModulePath::from("test");
|
let path = ModulePath::from("test");
|
||||||
8
lila/Cargo.toml
Normal file
8
lila/Cargo.toml
Normal file
|
|
@ -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" }
|
||||||
2
lila/src/lib.rs
Normal file
2
lila/src/lib.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod report;
|
||||||
|
pub mod source;
|
||||||
|
|
@ -1,64 +1,14 @@
|
||||||
use ariadne::{ColorGenerator, Fmt, Label, Report, ReportKind, Span as _};
|
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};
|
pub trait ToReport {
|
||||||
use crate::typing::{BinaryOperator, Identifier, ModulePath, Type};
|
fn to_report(&self, ast: &Module) -> Report<Span>;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub struct TypeError {
|
|
||||||
pub file: Option<std::path::PathBuf>,
|
|
||||||
pub module: ModulePath,
|
|
||||||
pub function: Option<String>,
|
|
||||||
pub kind: TypeErrorKind,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
impl ToReport for TypeError {
|
||||||
pub struct TypeAndSpan {
|
fn to_report(&self, ast: &Module) -> Report<Span> {
|
||||||
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<TypeAndSpan>,
|
|
||||||
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<Span> {
|
|
||||||
let mut colors = ColorGenerator::new();
|
let mut colors = ColorGenerator::new();
|
||||||
let c0 = colors.next();
|
let c0 = colors.next();
|
||||||
let c1 = colors.next();
|
let c1 = colors.next();
|
||||||
|
|
@ -85,6 +35,7 @@ impl TypeError {
|
||||||
.with_color(c2)
|
.with_color(c2)
|
||||||
.with_order(1),
|
.with_order(1),
|
||||||
])
|
])
|
||||||
|
// TODO: add hint for conversion
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,7 +80,7 @@ impl TypeError {
|
||||||
if let Some(span) = function.return_type_span {
|
if let Some(span) = function.return_type_span {
|
||||||
report.add_label(
|
report.add_label(
|
||||||
Label::new(span)
|
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),
|
.with_color(signature_color),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::ast::SourceId;
|
|
||||||
use ariadne::FileCache;
|
use ariadne::FileCache;
|
||||||
|
use lila_ast::SourceId;
|
||||||
|
|
||||||
pub struct SourceCache {
|
pub struct SourceCache {
|
||||||
pub paths: Vec<std::path::PathBuf>,
|
pub paths: Vec<std::path::PathBuf>,
|
||||||
Loading…
Add table
Add a link
Reference in a new issue