From 8a0c1a6e91531f7ee16398d448fb4374277d31bb Mon Sep 17 00:00:00 2001 From: Edgar Date: Thu, 4 Jan 2024 18:38:44 +0100 Subject: [PATCH 01/13] possible initial ast --- crates/concrete_ast/src/common.rs | 21 ++++++ crates/concrete_ast/src/constants.rs | 18 ++++++ crates/concrete_ast/src/expressions.rs | 89 ++++++++++++++++++++++++++ crates/concrete_ast/src/functions.rs | 41 ++++++++++++ crates/concrete_ast/src/imports.rs | 13 ++++ crates/concrete_ast/src/lib.rs | 23 +++---- crates/concrete_ast/src/modules.rs | 24 +++++++ crates/concrete_ast/src/statements.rs | 75 ++++++++++++++++++++++ crates/concrete_ast/src/structs.rs | 19 ++++++ crates/concrete_ast/src/types.rs | 18 ++++++ 10 files changed, 327 insertions(+), 14 deletions(-) create mode 100644 crates/concrete_ast/src/common.rs create mode 100644 crates/concrete_ast/src/constants.rs create mode 100644 crates/concrete_ast/src/expressions.rs create mode 100644 crates/concrete_ast/src/functions.rs create mode 100644 crates/concrete_ast/src/imports.rs create mode 100644 crates/concrete_ast/src/modules.rs create mode 100644 crates/concrete_ast/src/statements.rs create mode 100644 crates/concrete_ast/src/structs.rs create mode 100644 crates/concrete_ast/src/types.rs diff --git a/crates/concrete_ast/src/common.rs b/crates/concrete_ast/src/common.rs new file mode 100644 index 0000000..564811d --- /dev/null +++ b/crates/concrete_ast/src/common.rs @@ -0,0 +1,21 @@ +#[derive(Debug, Clone, Copy)] +pub struct Span { + pub from: usize, + pub to: usize, +} + +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct DocString { + contents: String, +} + +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct Ident { + pub name: String, +} + +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct TypeParam { + pub name: Ident, + pub params: Vec, +} diff --git a/crates/concrete_ast/src/constants.rs b/crates/concrete_ast/src/constants.rs new file mode 100644 index 0000000..50b4a4c --- /dev/null +++ b/crates/concrete_ast/src/constants.rs @@ -0,0 +1,18 @@ +use crate::{ + common::{DocString, Ident}, + expressions::Expression, + types::TypeSpec, +}; + +#[derive(Clone, Debug, PartialEq)] +pub struct ConstantDecl { + pub doc_string: Option, + pub name: Ident, + pub r#type: TypeSpec, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct ConstantDef { + decl: ConstantDecl, + pub value: Expression, +} diff --git a/crates/concrete_ast/src/expressions.rs b/crates/concrete_ast/src/expressions.rs new file mode 100644 index 0000000..fe37729 --- /dev/null +++ b/crates/concrete_ast/src/expressions.rs @@ -0,0 +1,89 @@ +use std::collections::HashMap; + +use crate::{common::Ident, types::TypeSpec}; + +#[derive(Clone, Debug, PartialEq)] +pub enum PathSegment { + SlotAccess(Ident), + PtrSlotAccess(Ident), + ArrayIndex(Box), +} + +#[derive(Clone, Debug, PartialEq)] +pub struct PathExpr { + pub first: Ident, + pub extra: Vec, +} + +#[derive(Clone, Debug, PartialEq)] +pub enum Expression { + Compound(CompoundExpr), + Atomic(AtomicExpr), +} + +#[derive(Clone, Debug, PartialEq)] +pub enum CompoundExpr { + Compare(CmpExpr), + Logic(LogicExpr), + Arith(ArithExpr), + Cast(CastExpr), +} + +#[derive(Clone, Debug, PartialEq)] +pub enum AtomicExpr { + ConstBool(bool), + ConstChar(char), + ConstIint(u64), + ConstFloat(f64), + ConstStr(String), + FnCall(FnCallExpr), + Path(PathExpr), + RefPath(PathExpr), + Paren(Box), +} + +#[derive(Clone, Debug, PartialEq)] +pub enum CmpExpr { + Eq(AtomicExpr, AtomicExpr), + NotEq(AtomicExpr, AtomicExpr), + Lt(AtomicExpr, AtomicExpr), + LtEq(AtomicExpr, AtomicExpr), + Gt(AtomicExpr, AtomicExpr), + GtEq(AtomicExpr, AtomicExpr), +} + +#[derive(Clone, Debug, PartialEq)] +pub enum LogicExpr { + And(AtomicExpr, AtomicExpr), + Or(AtomicExpr, AtomicExpr), + Not(AtomicExpr), +} + +#[derive(Clone, Debug, PartialEq)] +pub enum ArithExpr { + Add(AtomicExpr, AtomicExpr), + Sub(AtomicExpr, AtomicExpr), + Mul(AtomicExpr, AtomicExpr), + Div(AtomicExpr, AtomicExpr), + Neg(AtomicExpr), +} + +#[derive(Clone, Debug, PartialEq)] +pub struct CastExpr { + pub value: AtomicExpr, + pub r#type: TypeSpec, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct FnCallExpr { + pub target: Ident, + pub args: FnCallArgs, +} + +#[derive(Clone, Debug, Default, PartialEq)] +pub enum FnCallArgs { + #[default] + Empty, + Positional(Vec), + Named(HashMap), +} diff --git a/crates/concrete_ast/src/functions.rs b/crates/concrete_ast/src/functions.rs new file mode 100644 index 0000000..e130d6d --- /dev/null +++ b/crates/concrete_ast/src/functions.rs @@ -0,0 +1,41 @@ +use crate::{ + common::{DocString, Ident, TypeParam}, + statements::Statement, + types::TypeSpec, +}; + +#[derive(Clone, Debug, PartialEq)] +pub struct FunctionDecl { + pub doc_string: Option, + pub type_params: Vec, + pub name: Ident, + pub params: Vec, + pub ret_type: TypeSpec, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct FunctionDef { + pub decl: FunctionDecl, + pub body: Vec, +} + +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct MethodDecl { + pub doc_string: Option, + pub type_params: Vec, + pub name: Ident, + pub params: Vec, + pub ret_ty: TypeSpec, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct MethodDef { + pub decl: MethodDecl, + pub body: Vec, +} + +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct Param { + pub name: Ident, + pub r#type: TypeSpec, +} diff --git a/crates/concrete_ast/src/imports.rs b/crates/concrete_ast/src/imports.rs new file mode 100644 index 0000000..0811cb9 --- /dev/null +++ b/crates/concrete_ast/src/imports.rs @@ -0,0 +1,13 @@ +use crate::common::Ident; + +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct ImportStmt { + module: Vec, + symbols: Vec, +} + +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct ImportedSymbol { + import_name: Ident, + rename_into: Option, +} diff --git a/crates/concrete_ast/src/lib.rs b/crates/concrete_ast/src/lib.rs index 7d12d9a..bdf5e9a 100644 --- a/crates/concrete_ast/src/lib.rs +++ b/crates/concrete_ast/src/lib.rs @@ -1,14 +1,9 @@ -pub fn add(left: usize, right: usize) -> usize { - left + right -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} +pub mod common; +pub mod constants; +pub mod expressions; +pub mod functions; +pub mod imports; +pub mod modules; +pub mod statements; +pub mod structs; +pub mod types; diff --git a/crates/concrete_ast/src/modules.rs b/crates/concrete_ast/src/modules.rs new file mode 100644 index 0000000..933dcf5 --- /dev/null +++ b/crates/concrete_ast/src/modules.rs @@ -0,0 +1,24 @@ +use crate::{ + common::{DocString, Ident}, + constants::ConstantDef, + functions::FunctionDef, + imports::ImportStmt, + structs::StructDecl, + types::TypeDecl, +}; + +#[derive(Clone, Debug, PartialEq)] +pub struct ModuleBase { + pub doc_string: Option, + pub imports: Vec, + pub name: Ident, + pub contents: Vec, +} + +#[derive(Clone, Debug, PartialEq)] +pub enum ModuleDefItem { + Constant(ConstantDef), + Function(FunctionDef), + Record(StructDecl), + Type(TypeDecl), +} diff --git a/crates/concrete_ast/src/statements.rs b/crates/concrete_ast/src/statements.rs new file mode 100644 index 0000000..b0f6112 --- /dev/null +++ b/crates/concrete_ast/src/statements.rs @@ -0,0 +1,75 @@ +use crate::{ + common::Ident, + expressions::{Expression, PathExpr}, + types::TypeSpec, +}; + +#[derive(Clone, Debug, PartialEq)] +pub enum Statement { + Assign(AssignStmt), + Match(MatchStmt), + For(ForStmt), + If(IfStmt), + Let(LetStmt), + Return(Expression), + While(WhileStmt), +} + +#[derive(Clone, Debug, PartialEq)] +pub enum LetStmtTarget { + Simple { name: Ident, r#type: TypeSpec }, + Destructure(Vec), +} + +#[derive(Clone, Debug, PartialEq)] +pub struct LetStmt { + pub is_mutable: bool, + pub target: LetStmtTarget, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct AssignStmt { + pub target: PathExpr, + pub value: Expression, +} + +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct Binding { + pub name: Ident, + pub rename: Option, + pub r#type: TypeSpec, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct MatchStmt { + pub value: Expression, + pub variants: Vec, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct MatchWhen { + pub ident: Ident, + pub bindings: Vec, + pub block: Vec, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct ForStmt { + pub name: Ident, + pub from: Expression, + pub to: Expression, + pub contents: Vec, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct IfStmt { + pub value: Expression, + pub contents: Vec, + pub r#else: Option>, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct WhileStmt { + pub value: Expression, + pub contents: Vec, +} diff --git a/crates/concrete_ast/src/structs.rs b/crates/concrete_ast/src/structs.rs new file mode 100644 index 0000000..b664d07 --- /dev/null +++ b/crates/concrete_ast/src/structs.rs @@ -0,0 +1,19 @@ +use crate::{ + common::{DocString, Ident, TypeParam}, + types::TypeSpec, +}; + +#[derive(Clone, Debug, PartialEq)] +pub struct StructDecl { + doc_string: Option, + name: Ident, + type_params: Vec, + fields: Vec, +} + +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct Field { + doc_string: Option, + name: Ident, + r#type: TypeSpec, +} diff --git a/crates/concrete_ast/src/types.rs b/crates/concrete_ast/src/types.rs new file mode 100644 index 0000000..75e3c0e --- /dev/null +++ b/crates/concrete_ast/src/types.rs @@ -0,0 +1,18 @@ +use crate::common::{DocString, Ident}; + +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub enum TypeSpec { + Simple { + name: Ident, + }, + Generic { + name: Ident, + type_params: Vec, + }, +} + +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct TypeDecl { + pub doc_string: Option, + pub name: Ident, +} From b32f589e4d97dd393ec49c6b66374e9549f06f9f Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Thu, 4 Jan 2024 19:07:28 +0100 Subject: [PATCH 02/13] typo --- crates/concrete_ast/src/expressions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/concrete_ast/src/expressions.rs b/crates/concrete_ast/src/expressions.rs index fe37729..15a5f83 100644 --- a/crates/concrete_ast/src/expressions.rs +++ b/crates/concrete_ast/src/expressions.rs @@ -33,7 +33,7 @@ pub enum CompoundExpr { pub enum AtomicExpr { ConstBool(bool), ConstChar(char), - ConstIint(u64), + ConstInt(u64), ConstFloat(f64), ConstStr(String), FnCall(FnCallExpr), From f23610f58b4b0be063379293aedad29501e346bf Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Thu, 4 Jan 2024 19:08:50 +0100 Subject: [PATCH 03/13] naming --- crates/concrete_ast/src/expressions.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/concrete_ast/src/expressions.rs b/crates/concrete_ast/src/expressions.rs index 15a5f83..3a5385b 100644 --- a/crates/concrete_ast/src/expressions.rs +++ b/crates/concrete_ast/src/expressions.rs @@ -4,8 +4,8 @@ use crate::{common::Ident, types::TypeSpec}; #[derive(Clone, Debug, PartialEq)] pub enum PathSegment { - SlotAccess(Ident), - PtrSlotAccess(Ident), + FieldAccess(Ident), + PtrFieldAccess(Ident), ArrayIndex(Box), } From e512062c3fc3ce3944dfc7a2e33620d66f0042e2 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Thu, 4 Jan 2024 19:09:53 +0100 Subject: [PATCH 04/13] unsure if we have ptrs --- crates/concrete_ast/src/expressions.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/concrete_ast/src/expressions.rs b/crates/concrete_ast/src/expressions.rs index 3a5385b..983e554 100644 --- a/crates/concrete_ast/src/expressions.rs +++ b/crates/concrete_ast/src/expressions.rs @@ -5,7 +5,6 @@ use crate::{common::Ident, types::TypeSpec}; #[derive(Clone, Debug, PartialEq)] pub enum PathSegment { FieldAccess(Ident), - PtrFieldAccess(Ident), ArrayIndex(Box), } From 133da04a07b94bc8738dbcaecaf79c6454670534 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Fri, 5 Jan 2024 12:05:08 +0100 Subject: [PATCH 05/13] add tokens to parser --- Cargo.lock | 1 + crates/concrete_parser/Cargo.toml | 1 + crates/concrete_parser/src/grammar.lalrpop | 50 ++++++++++++- crates/concrete_parser/src/tokens.rs | 84 +++++++++++++++++++++- 4 files changed, 133 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b14312d..95c98c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -88,6 +88,7 @@ version = "0.1.0" name = "concrete_parser" version = "0.1.0" dependencies = [ + "concrete_ast", "lalrpop", "lalrpop-util", "logos", diff --git a/crates/concrete_parser/Cargo.toml b/crates/concrete_parser/Cargo.toml index 2f232e0..93abf1a 100644 --- a/crates/concrete_parser/Cargo.toml +++ b/crates/concrete_parser/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" lalrpop-util = { version = "0.20.0", features = ["unicode"] } logos = "0.13.0" tracing.workspace = true +concrete_ast = { path = "../concrete_ast"} [build-dependencies] lalrpop = "0.20.0" diff --git a/crates/concrete_parser/src/grammar.lalrpop b/crates/concrete_parser/src/grammar.lalrpop index 9d4b0b0..7647c2d 100644 --- a/crates/concrete_parser/src/grammar.lalrpop +++ b/crates/concrete_parser/src/grammar.lalrpop @@ -1,4 +1,5 @@ use crate::tokens::Token; +use concrete_ast as ast; grammar; @@ -7,10 +8,55 @@ extern { type Error = LexicalError; enum Token { - "ident" => Token::Identifier(), + // keywords + "let" => Token::KeywordLet, + "const" => Token::KeywordConst, + "fn" => Token::KeywordFn, + "return" => Token::KeywordReturn, + "struct" => Token::KeywordStruct, + "if" => Token::KeywordIf, + "else" => Token::KeywordElse, + "while" => Token::KeywordWhile, + "for" => Token::KeywordFor, + "match" => Token::KeywordMatch, + "mod" => Token::KeywordMod, + "pub" => Token::KeywordPub, + + // literals + "identifier" => Token::Identifier(), + "integer" => Token::String(), + "boolean" => Token::Boolean(), + + // Other + + "(" => Token::LeftParen, + ")" => Token::RightParen, + "{" => Token::LeftBracket, + "}" => Token::RightBracket, + "[" => Token::LeftSquareBracket, + "]" => Token::RightSquareBracket, + "=" => Token::Assign, + ";" => Token::Semicolon, + ":" => Token::Colon, + "->" => Token::Arrow, + "," => Token::Coma, + "<" => Token::LessThanSign, + ">" => Token::MoreThanSign, + + // operators + "+" => Token::OperatorAdd, + "-" => Token::OperatorSub, + "*" => Token::OperatorMul, + "/" => Token::OperatorDiv, + "%" => Token::OperatorRem, + "&&" => Token::OperatorAnd, + "||" => Token::OperatorOr, + "==" => Token::OperatorEq, + "!=" => Token::OperatorNe, + "!" => Token::OperatorNot, } } pub Term: () = { - "ident" => (), + "identifier" => (), } diff --git a/crates/concrete_parser/src/tokens.rs b/crates/concrete_parser/src/tokens.rs index b787487..f8bfcc8 100644 --- a/crates/concrete_parser/src/tokens.rs +++ b/crates/concrete_parser/src/tokens.rs @@ -23,6 +23,88 @@ impl From for LexingError { #[derive(Logos, Debug, PartialEq, Clone)] #[logos(error = LexingError, skip r"[ \t\n\f]+", skip r"//.*\n?", skip r"/\*(?:[^*]|\*[^/])*\*/")] pub enum Token { - #[regex(r"[a-zA-Z][a-zA-Z\d]*", |lex| lex.slice().parse())] + #[token("let")] + KeywordLet, + #[token("const")] + KeywordConst, + #[token("fn")] + KeywordFn, + #[token("return")] + KeywordReturn, + #[token("struct")] + KeywordStruct, + #[token("if")] + KeywordIf, + #[token("else")] + KeywordElse, + #[token("while")] + KeywordWhile, + #[token("for")] + KeywordFor, + #[token("match")] + KeywordMatch, + #[token("mod")] + KeywordMod, + #[token("pub")] + KeywordPub, + + // Modern way of allowing identifiers, read: https://unicode.org/reports/tr31/ + #[regex(r"_?\p{XID_Start}\p{XID_Continue}*", |lex| lex.slice().to_string())] Identifier(String), + + // Literals + #[regex(r"\d+", |lex| lex.slice().to_string())] + Integer(String), + #[regex(r#""(?:[^"]|\\")*""#, |lex| lex.slice().to_string())] + String(String), + #[regex(r"(true|false)", |lex| lex.slice().parse::().unwrap())] + Boolean(bool), + + #[token("(")] + LeftParen, + #[token(")")] + RightParen, + #[token("{")] + LeftBracket, + #[token("}")] + RightBracket, + #[token("[")] + LeftSquareBracket, + #[token("]")] + RightSquareBracket, + #[token("=")] + Assign, + #[token(";")] + Semicolon, + #[token(":")] + Colon, + #[token("->")] + Arrow, + #[token(",")] + Coma, + #[token("<")] + LessThanSign, + #[token(">")] + MoreThanSign, + + #[token("+")] + OperatorAdd, + #[token("-")] + OperatorSub, + #[token("*")] + OperatorMul, + #[token("/")] + OperatorDiv, + #[token("%")] + OperatorRem, + #[token("&&")] + OperatorAnd, + #[token("||")] + OperatorOr, + #[token("==")] + OperatorEq, + #[token("!=")] + OperatorNe, + #[token("!")] + OperatorNot, } From 685cef2ddb08484bb9e41b6455442bd5fac59207 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Fri, 5 Jan 2024 12:38:16 +0100 Subject: [PATCH 06/13] work in progress parser --- crates/concrete_ast/src/common.rs | 9 ++- crates/concrete_ast/src/constants.rs | 2 +- crates/concrete_parser/src/grammar.lalrpop | 82 +++++++++++++++++++++- crates/concrete_parser/src/lib.rs | 22 ++++++ crates/concrete_parser/src/tokens.rs | 5 +- 5 files changed, 113 insertions(+), 7 deletions(-) diff --git a/crates/concrete_ast/src/common.rs b/crates/concrete_ast/src/common.rs index 564811d..30039f3 100644 --- a/crates/concrete_ast/src/common.rs +++ b/crates/concrete_ast/src/common.rs @@ -1,9 +1,15 @@ -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Span { pub from: usize, pub to: usize, } +impl Span { + pub fn new(from: usize, to: usize) -> Self { + Self { from, to } + } +} + #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct DocString { contents: String, @@ -12,6 +18,7 @@ pub struct DocString { #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct Ident { pub name: String, + pub span: Span, } #[derive(Clone, Debug, Eq, Hash, PartialEq)] diff --git a/crates/concrete_ast/src/constants.rs b/crates/concrete_ast/src/constants.rs index 50b4a4c..e42d9a1 100644 --- a/crates/concrete_ast/src/constants.rs +++ b/crates/concrete_ast/src/constants.rs @@ -13,6 +13,6 @@ pub struct ConstantDecl { #[derive(Clone, Debug, PartialEq)] pub struct ConstantDef { - decl: ConstantDecl, + pub decl: ConstantDecl, pub value: Expression, } diff --git a/crates/concrete_parser/src/grammar.lalrpop b/crates/concrete_parser/src/grammar.lalrpop index 7647c2d..2974afb 100644 --- a/crates/concrete_parser/src/grammar.lalrpop +++ b/crates/concrete_parser/src/grammar.lalrpop @@ -1,5 +1,7 @@ use crate::tokens::Token; +use crate::lexer::LexicalError; use concrete_ast as ast; +use std::str::FromStr; grammar; @@ -24,7 +26,8 @@ extern { // literals "identifier" => Token::Identifier(), - "integer" => Token::String(), + "integer" => Token::Integer(), + "string" => Token::String(), "boolean" => Token::Boolean(), // Other @@ -57,6 +60,79 @@ extern { } } -pub Term: () = { - "identifier" => (), +Comma: Vec = { + ",")*> => match e { + None => v, + Some(e) => { + v.push(e); + v + } + } +}; + +SemiColonSeparated: Vec = { + ";" => vec![<>], + > ";" ";" => { + s.push(n); + s + } +}; + +pub(crate) Ident: ast::common::Ident = { + => ast::common::Ident { + name, + span: ast::common::Span::new(lo, hi), + } +} + +pub Program: Vec = { + => vec![<>], + => { + s.push(n); + s + }, +} + +pub(crate) ModuleBase: ast::modules::ModuleBase = { + "mod" "{" > "}" => { + ast::modules::ModuleBase { + doc_string: None, + imports: vec![], // todo: add imports + name, + contents + } + } +} + +pub(crate) ModuleDefItem: ast::modules::ModuleDefItem = { + "const" ":" "=" => { + ast::modules::ModuleDefItem::Constant(ast::constants::ConstantDef { + decl: ast::constants::ConstantDecl { + doc_string: None, + name, + r#type: type_spec + }, + value: exp, + }) + } +} + +pub(crate) TypeSpec: ast::types::TypeSpec = { + => ast::types::TypeSpec::Simple { + name + }, + "<" > ">" => ast::types::TypeSpec::Generic { + name, + type_params + } +} + +pub(crate) Expression: ast::expressions::Expression = { + => ast::expressions::Expression::Atomic(<>), +} + +pub(crate) AtomicExpr: ast::expressions::AtomicExpr = { + <"integer"> => ast::expressions::AtomicExpr::ConstInt(<>), + <"boolean"> => ast::expressions::AtomicExpr::ConstBool(<>), + <"string"> => ast::expressions::AtomicExpr::ConstStr(<>), } diff --git a/crates/concrete_parser/src/lib.rs b/crates/concrete_parser/src/lib.rs index 32ce3d2..889ffec 100644 --- a/crates/concrete_parser/src/lib.rs +++ b/crates/concrete_parser/src/lib.rs @@ -1,4 +1,26 @@ #![allow(unused)] +use lalrpop_util::lalrpop_mod; + mod lexer; pub mod tokens; + +lalrpop_mod!(pub grammar); + +#[cfg(test)] +mod tests { + use crate::{grammar, lexer::Lexer}; + + #[test] + fn parse_program() { + let source = r##" +mod ModuleName { + const MY_CONSTANT: u8 = 2; +} + "##; + let lexer = Lexer::new(source); + let parser = grammar::ProgramParser::new(); + let mut ast = parser.parse(lexer).unwrap(); + dbg!(ast); + } +} diff --git a/crates/concrete_parser/src/tokens.rs b/crates/concrete_parser/src/tokens.rs index f8bfcc8..189d284 100644 --- a/crates/concrete_parser/src/tokens.rs +++ b/crates/concrete_parser/src/tokens.rs @@ -1,4 +1,5 @@ use logos::Logos; +use std::str::FromStr; use std::{convert::Infallible, fmt}; // to implement the Display trait #[derive(Debug, PartialEq, Clone, Default)] @@ -53,8 +54,8 @@ pub enum Token { Identifier(String), // Literals - #[regex(r"\d+", |lex| lex.slice().to_string())] - Integer(String), + #[regex(r"\d+", |lex| lex.slice().parse::().unwrap())] + Integer(u64), #[regex(r#""(?:[^"]|\\")*""#, |lex| lex.slice().to_string())] String(String), #[regex(r"(true|false)", |lex| lex.slice().parse::().unwrap())] From 42fa817e32bf4bd160da14be79d76c3c0581be3e Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Fri, 5 Jan 2024 12:42:24 +0100 Subject: [PATCH 07/13] type checker crate --- Cargo.toml | 2 +- crates/concrete_type_checker/Cargo.toml | 8 ++++++++ crates/concrete_type_checker/src/lib.rs | 14 ++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 crates/concrete_type_checker/Cargo.toml create mode 100644 crates/concrete_type_checker/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 3cc6eba..bb78b90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [workspace] resolver = "2" -members = [ "crates/concrete","crates/concrete_ast", "crates/concrete_codegen_mlir", "crates/concrete_driver", "crates/concrete_parser"] +members = [ "crates/concrete","crates/concrete_ast", "crates/concrete_codegen_mlir", "crates/concrete_driver", "crates/concrete_parser", "crates/concrete_type_checker"] [profile.release] lto = true diff --git a/crates/concrete_type_checker/Cargo.toml b/crates/concrete_type_checker/Cargo.toml new file mode 100644 index 0000000..44762dd --- /dev/null +++ b/crates/concrete_type_checker/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "concrete_type_checker" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/crates/concrete_type_checker/src/lib.rs b/crates/concrete_type_checker/src/lib.rs new file mode 100644 index 0000000..7d12d9a --- /dev/null +++ b/crates/concrete_type_checker/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: usize, right: usize) -> usize { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} From c7b79b138476b8b44cb2f444d2ab26898293ebc9 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Fri, 5 Jan 2024 12:59:41 +0100 Subject: [PATCH 08/13] fix --- Cargo.lock | 4 ++++ crates/concrete_parser/src/grammar.lalrpop | 2 +- crates/concrete_parser/src/lib.rs | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 95c98c0..d2c9182 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,6 +95,10 @@ dependencies = [ "tracing", ] +[[package]] +name = "concrete_type_checker" +version = "0.1.0" + [[package]] name = "crunchy" version = "0.2.2" diff --git a/crates/concrete_parser/src/grammar.lalrpop b/crates/concrete_parser/src/grammar.lalrpop index 2974afb..bca350d 100644 --- a/crates/concrete_parser/src/grammar.lalrpop +++ b/crates/concrete_parser/src/grammar.lalrpop @@ -72,7 +72,7 @@ Comma: Vec = { SemiColonSeparated: Vec = { ";" => vec![<>], - > ";" ";" => { + > ";" => { s.push(n); s } diff --git a/crates/concrete_parser/src/lib.rs b/crates/concrete_parser/src/lib.rs index 889ffec..05c9961 100644 --- a/crates/concrete_parser/src/lib.rs +++ b/crates/concrete_parser/src/lib.rs @@ -16,6 +16,8 @@ mod tests { let source = r##" mod ModuleName { const MY_CONSTANT: u8 = 2; + const MY_CONSTANT2: bool = true; + const MY_CONSTANT3: string = "hello world!"; } "##; let lexer = Lexer::new(source); From a21fd754c77441d8910f8d552dcc5c53ef8e7833 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Fri, 5 Jan 2024 18:19:54 +0100 Subject: [PATCH 09/13] progress --- Cargo.lock | 7 + crates/concrete_ast/src/common.rs | 2 +- crates/concrete_ast/src/expressions.rs | 24 +-- crates/concrete_ast/src/functions.rs | 21 +-- crates/concrete_ast/src/statements.rs | 14 +- crates/concrete_ast/src/structs.rs | 4 +- crates/concrete_parser/Cargo.toml | 3 + crates/concrete_parser/src/grammar.lalrpop | 186 ++++++++++++++++++++- crates/concrete_parser/src/lib.rs | 57 ++++++- crates/concrete_parser/src/tokens.rs | 6 +- 10 files changed, 274 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d2c9182..471da72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -92,6 +92,7 @@ dependencies = [ "lalrpop", "lalrpop-util", "logos", + "owo-colors", "tracing", ] @@ -349,6 +350,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "owo-colors" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f" + [[package]] name = "parking_lot" version = "0.12.1" diff --git a/crates/concrete_ast/src/common.rs b/crates/concrete_ast/src/common.rs index 30039f3..1833256 100644 --- a/crates/concrete_ast/src/common.rs +++ b/crates/concrete_ast/src/common.rs @@ -22,7 +22,7 @@ pub struct Ident { } #[derive(Clone, Debug, Eq, Hash, PartialEq)] -pub struct TypeParam { +pub struct GenericParam { pub name: Ident, pub params: Vec, } diff --git a/crates/concrete_ast/src/expressions.rs b/crates/concrete_ast/src/expressions.rs index 983e554..6f33d4b 100644 --- a/crates/concrete_ast/src/expressions.rs +++ b/crates/concrete_ast/src/expressions.rs @@ -1,6 +1,10 @@ use std::collections::HashMap; -use crate::{common::Ident, types::TypeSpec}; +use crate::{ + common::Ident, + statements::{IfStmt, MatchStmt, ReturnStmt}, + types::TypeSpec, +}; #[derive(Clone, Debug, PartialEq)] pub enum PathSegment { @@ -41,6 +45,13 @@ pub enum AtomicExpr { Paren(Box), } +#[derive(Clone, Debug, PartialEq)] +pub enum StatementExpr { + Match(MatchStmt), + If(IfStmt), + Return(ReturnStmt), +} + #[derive(Clone, Debug, PartialEq)] pub enum CmpExpr { Eq(AtomicExpr, AtomicExpr), @@ -64,6 +75,7 @@ pub enum ArithExpr { Sub(AtomicExpr, AtomicExpr), Mul(AtomicExpr, AtomicExpr), Div(AtomicExpr, AtomicExpr), + Mod(AtomicExpr, AtomicExpr), Neg(AtomicExpr), } @@ -76,13 +88,5 @@ pub struct CastExpr { #[derive(Clone, Debug, PartialEq)] pub struct FnCallExpr { pub target: Ident, - pub args: FnCallArgs, -} - -#[derive(Clone, Debug, Default, PartialEq)] -pub enum FnCallArgs { - #[default] - Empty, - Positional(Vec), - Named(HashMap), + pub args: Vec, } diff --git a/crates/concrete_ast/src/functions.rs b/crates/concrete_ast/src/functions.rs index e130d6d..8e084ce 100644 --- a/crates/concrete_ast/src/functions.rs +++ b/crates/concrete_ast/src/functions.rs @@ -1,5 +1,5 @@ use crate::{ - common::{DocString, Ident, TypeParam}, + common::{DocString, GenericParam, Ident}, statements::Statement, types::TypeSpec, }; @@ -7,10 +7,10 @@ use crate::{ #[derive(Clone, Debug, PartialEq)] pub struct FunctionDecl { pub doc_string: Option, - pub type_params: Vec, + pub generic_params: Vec, pub name: Ident, pub params: Vec, - pub ret_type: TypeSpec, + pub ret_type: Option, } #[derive(Clone, Debug, PartialEq)] @@ -19,21 +19,6 @@ pub struct FunctionDef { pub body: Vec, } -#[derive(Clone, Debug, Eq, Hash, PartialEq)] -pub struct MethodDecl { - pub doc_string: Option, - pub type_params: Vec, - pub name: Ident, - pub params: Vec, - pub ret_ty: TypeSpec, -} - -#[derive(Clone, Debug, PartialEq)] -pub struct MethodDef { - pub decl: MethodDecl, - pub body: Vec, -} - #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct Param { pub name: Ident, diff --git a/crates/concrete_ast/src/statements.rs b/crates/concrete_ast/src/statements.rs index b0f6112..96bad3a 100644 --- a/crates/concrete_ast/src/statements.rs +++ b/crates/concrete_ast/src/statements.rs @@ -11,7 +11,7 @@ pub enum Statement { For(ForStmt), If(IfStmt), Let(LetStmt), - Return(Expression), + Return(ReturnStmt), While(WhileStmt), } @@ -27,6 +27,11 @@ pub struct LetStmt { pub target: LetStmtTarget, } +#[derive(Clone, Debug, PartialEq)] +pub struct ReturnStmt { + pub value: Expression, +} + #[derive(Clone, Debug, PartialEq)] pub struct AssignStmt { pub target: PathExpr, @@ -43,13 +48,12 @@ pub struct Binding { #[derive(Clone, Debug, PartialEq)] pub struct MatchStmt { pub value: Expression, - pub variants: Vec, + pub variants: Vec, } #[derive(Clone, Debug, PartialEq)] -pub struct MatchWhen { - pub ident: Ident, - pub bindings: Vec, +pub struct MatchVariant { + pub case: Expression, pub block: Vec, } diff --git a/crates/concrete_ast/src/structs.rs b/crates/concrete_ast/src/structs.rs index b664d07..53613b3 100644 --- a/crates/concrete_ast/src/structs.rs +++ b/crates/concrete_ast/src/structs.rs @@ -1,5 +1,5 @@ use crate::{ - common::{DocString, Ident, TypeParam}, + common::{DocString, GenericParam, Ident}, types::TypeSpec, }; @@ -7,7 +7,7 @@ use crate::{ pub struct StructDecl { doc_string: Option, name: Ident, - type_params: Vec, + type_params: Vec, fields: Vec, } diff --git a/crates/concrete_parser/Cargo.toml b/crates/concrete_parser/Cargo.toml index 93abf1a..8ad0c19 100644 --- a/crates/concrete_parser/Cargo.toml +++ b/crates/concrete_parser/Cargo.toml @@ -13,3 +13,6 @@ concrete_ast = { path = "../concrete_ast"} [build-dependencies] lalrpop = "0.20.0" + +[dev-dependencies] +owo-colors = "4.0.0" diff --git a/crates/concrete_parser/src/grammar.lalrpop b/crates/concrete_parser/src/grammar.lalrpop index bca350d..d2dce8a 100644 --- a/crates/concrete_parser/src/grammar.lalrpop +++ b/crates/concrete_parser/src/grammar.lalrpop @@ -45,6 +45,7 @@ extern { "," => Token::Coma, "<" => Token::LessThanSign, ">" => Token::MoreThanSign, + "." => Token::Dot, // operators "+" => Token::OperatorAdd, @@ -60,6 +61,8 @@ extern { } } +// lalrpop macros + Comma: Vec = { ",")*> => match e { None => v, @@ -70,6 +73,17 @@ Comma: Vec = { } }; +PlusSeparated: Vec = { + "+")*> => match e { + None => v, + Some(e) => { + v.push(e); + v + } + } +}; + +// Requires the semicolon at end SemiColonSeparated: Vec = { ";" => vec![<>], > ";" => { @@ -78,6 +92,8 @@ SemiColonSeparated: Vec = { } }; +// -- Common + pub(crate) Ident: ast::common::Ident = { => ast::common::Ident { name, @@ -85,6 +101,33 @@ pub(crate) Ident: ast::common::Ident = { } } +pub(crate) TypeSpec: ast::types::TypeSpec = { + => ast::types::TypeSpec::Simple { + name + }, + "<" > ">" => ast::types::TypeSpec::Generic { + name, + type_params + } +} + +pub(crate) GenericParam: ast::common::GenericParam = { + => ast::common::GenericParam { + name, + params: vec![], + }, + ":" > => ast::common::GenericParam { + name, + params, + }, +} + +pub(crate) GenericParams: Vec = { + "<" > ">" => <> +} + +// Module list + pub Program: Vec = { => vec![<>], => { @@ -93,6 +136,8 @@ pub Program: Vec = { }, } +// Modules + pub(crate) ModuleBase: ast::modules::ModuleBase = { "mod" "{" > "}" => { ast::modules::ModuleBase { @@ -105,34 +150,157 @@ pub(crate) ModuleBase: ast::modules::ModuleBase = { } pub(crate) ModuleDefItem: ast::modules::ModuleDefItem = { + => { + ast::modules::ModuleDefItem::Constant(<>) + }, + => { + ast::modules::ModuleDefItem::Function(<>) + } +} + +// Constants + +pub(crate) ConstantDef: ast::constants::ConstantDef = { "const" ":" "=" => { - ast::modules::ModuleDefItem::Constant(ast::constants::ConstantDef { + ast::constants::ConstantDef { decl: ast::constants::ConstantDecl { doc_string: None, name, r#type: type_spec }, value: exp, - }) - } + } + }, } -pub(crate) TypeSpec: ast::types::TypeSpec = { - => ast::types::TypeSpec::Simple { - name - }, - "<" > ">" => ast::types::TypeSpec::Generic { +// -- Functions + +pub(crate) FunctionRetType: ast::types::TypeSpec = { + "->" => <> +} + +pub(crate) Param: ast::functions::Param = { + ":" => ast::functions::Param { name, - type_params + r#type: param_type + } +} + +pub(crate) FunctionDef: ast::functions::FunctionDef = { + "fn" "(" > ")" "{" + > + "}" => { + ast::functions::FunctionDef { + decl: ast::functions::FunctionDecl { + doc_string: None, + generic_params: generic_params.unwrap_or(vec![]), + name, + params, + ret_type, + }, + body: statements + } } } +// -- Expressions + pub(crate) Expression: ast::expressions::Expression = { => ast::expressions::Expression::Atomic(<>), + => ast::expressions::Expression::Compound(<>), } pub(crate) AtomicExpr: ast::expressions::AtomicExpr = { <"integer"> => ast::expressions::AtomicExpr::ConstInt(<>), <"boolean"> => ast::expressions::AtomicExpr::ConstBool(<>), <"string"> => ast::expressions::AtomicExpr::ConstStr(<>), + =>ast::expressions::AtomicExpr::Path(<>), + =>ast::expressions::AtomicExpr::FnCall(<>), +} + +pub(crate) CompoundExpr: ast::expressions::CompoundExpr = { + => ast::expressions::CompoundExpr::Arith(<>), +} + +pub(crate) StatementExpr: ast::expressions::StatementExpr = { + => ast::expressions::StatementExpr::Match(<>), + => ast::expressions::StatementExpr::Return(<>), +} + +pub(crate) ArithExpr: ast::expressions::ArithExpr = { + #[precedence(level="1")] + "*" => ast::expressions::ArithExpr::Mul(lhs, rhs), + "/" => ast::expressions::ArithExpr::Div(lhs, rhs), + "%" => ast::expressions::ArithExpr::Mod(lhs, rhs), + #[precedence(level="2")] #[assoc(side="left")] + "+" => ast::expressions::ArithExpr::Add(lhs, rhs), + "-" => ast::expressions::ArithExpr::Sub(lhs, rhs), + #[precedence(level="3")] #[assoc(side="left")] + "-" => ast::expressions::ArithExpr::Neg(value), +} + +pub(crate) PathExpr: ast::expressions::PathExpr = { + => ast::expressions::PathExpr { + first, + extra: extra.unwrap_or(vec![]), + } +} + +pub(crate) PathSegment: ast::expressions::PathSegment = { + "." => ast::expressions::PathSegment::FieldAccess(<>), + "[" "]" => ast::expressions::PathSegment::ArrayIndex(Box::new(e)), +} + +pub PathSegments: Vec = { + => vec![<>], + => { + s.push(n); + s + }, +} + +pub(crate) FnCallExpr: ast::expressions::FnCallExpr = { + "(" > ")" => ast::expressions::FnCallExpr { + target, + args + } +} + +// -- Statements + +pub(crate) Statement: ast::statements::Statement = { + => ast::statements::Statement::Match(<>), + => ast::statements::Statement::Return(<>), +} + +pub(crate) MatchStmt: ast::statements::MatchStmt = { + "match" "{" > "}" => { + ast::statements::MatchStmt { + value, + variants + } + } +} + +pub(crate) MatchVariant: ast::statements::MatchVariant = { + // 0 -> 1 + "->" => { + ast::statements::MatchVariant { + case, + block: vec![stmt] + } + }, + // x -> { ... } + "->" "{" > "}" => { + ast::statements::MatchVariant { + case, + block: stmts + } + } +} + +pub(crate) ReturnStmt: ast::statements::ReturnStmt = { + "return"? => ast::statements::ReturnStmt { + value, + }, } diff --git a/crates/concrete_parser/src/lib.rs b/crates/concrete_parser/src/lib.rs index 05c9961..d333f11 100644 --- a/crates/concrete_parser/src/lib.rs +++ b/crates/concrete_parser/src/lib.rs @@ -9,10 +9,17 @@ lalrpop_mod!(pub grammar); #[cfg(test)] mod tests { - use crate::{grammar, lexer::Lexer}; + use lalrpop_util::ParseError; + use owo_colors::OwoColorize; + + use crate::{ + grammar, + lexer::{Lexer, LexicalError}, + tokens::Token, + }; #[test] - fn parse_program() { + fn parse_simple_program() { let source = r##" mod ModuleName { const MY_CONSTANT: u8 = 2; @@ -23,6 +30,50 @@ mod ModuleName { let lexer = Lexer::new(source); let parser = grammar::ProgramParser::new(); let mut ast = parser.parse(lexer).unwrap(); - dbg!(ast); + // dbg!(ast); + } + + #[test] + fn parse_factorial() { + let source = r##"mod FactorialModule { + pub fn factorial(x: u64) -> u64 { + match x { + 0 -> 1, + n -> n * factorial(n-1), + } + } +}"##; + 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), + } + } + + fn print_parser_error(source: &str, err: ParseError) { + match err { + ParseError::InvalidToken { location } => todo!(), + ParseError::UnrecognizedEof { location, expected } => todo!(), + ParseError::UnrecognizedToken { token, expected } => { + let (l, 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 { token } => todo!(), + ParseError::User { error } => todo!(), + } + panic!("error parsing"); } } diff --git a/crates/concrete_parser/src/tokens.rs b/crates/concrete_parser/src/tokens.rs index 189d284..5ee980c 100644 --- a/crates/concrete_parser/src/tokens.rs +++ b/crates/concrete_parser/src/tokens.rs @@ -22,7 +22,7 @@ impl From for LexingError { } #[derive(Logos, Debug, PartialEq, Clone)] -#[logos(error = LexingError, skip r"[ \t\n\f]+", skip r"//.*\n?", skip r"/\*(?:[^*]|\*[^/])*\*/")] +#[logos(error = LexingError, skip r"[ \t\n\f]+", skip r"//[^\n]*", skip r"/\*(?:[^*]|\*[^/])*\*/")] pub enum Token { #[token("let")] KeywordLet, @@ -50,7 +50,7 @@ pub enum Token { KeywordPub, // Modern way of allowing identifiers, read: https://unicode.org/reports/tr31/ - #[regex(r"_?\p{XID_Start}\p{XID_Continue}*", |lex| lex.slice().to_string())] + #[regex(r"[\p{XID_Start}_]\p{XID_Continue}*", |lex| lex.slice().to_string())] Identifier(String), // Literals @@ -83,6 +83,8 @@ pub enum Token { Arrow, #[token(",")] Coma, + #[token(".")] + Dot, #[token("<")] LessThanSign, #[token(">")] From cc657bce9bdd4e9ecd39b6915304126cdb551c28 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Fri, 5 Jan 2024 18:48:10 +0100 Subject: [PATCH 10/13] progress 2 --- crates/concrete_ast/src/constants.rs | 3 +- crates/concrete_ast/src/expressions.rs | 92 ++------------ crates/concrete_ast/src/lib.rs | 3 +- crates/concrete_ast/src/operations.rs | 82 +++++++++++++ crates/concrete_ast/src/statements.rs | 29 ++--- crates/concrete_parser/src/grammar.lalrpop | 136 ++++++++++++--------- crates/concrete_parser/src/lib.rs | 10 +- 7 files changed, 189 insertions(+), 166 deletions(-) create mode 100644 crates/concrete_ast/src/operations.rs diff --git a/crates/concrete_ast/src/constants.rs b/crates/concrete_ast/src/constants.rs index e42d9a1..5cc4e42 100644 --- a/crates/concrete_ast/src/constants.rs +++ b/crates/concrete_ast/src/constants.rs @@ -1,7 +1,6 @@ use crate::{ common::{DocString, Ident}, - expressions::Expression, - types::TypeSpec, + types::TypeSpec, expressions::Expression, }; #[derive(Clone, Debug, PartialEq)] diff --git a/crates/concrete_ast/src/expressions.rs b/crates/concrete_ast/src/expressions.rs index 6f33d4b..1a4d272 100644 --- a/crates/concrete_ast/src/expressions.rs +++ b/crates/concrete_ast/src/expressions.rs @@ -1,92 +1,24 @@ -use std::collections::HashMap; - -use crate::{ - common::Ident, - statements::{IfStmt, MatchStmt, ReturnStmt}, - types::TypeSpec, -}; - -#[derive(Clone, Debug, PartialEq)] -pub enum PathSegment { - FieldAccess(Ident), - ArrayIndex(Box), -} - -#[derive(Clone, Debug, PartialEq)] -pub struct PathExpr { - pub first: Ident, - pub extra: Vec, -} +use crate::{operations::Operation, statements::Statement}; #[derive(Clone, Debug, PartialEq)] pub enum Expression { - Compound(CompoundExpr), - Atomic(AtomicExpr), -} - -#[derive(Clone, Debug, PartialEq)] -pub enum CompoundExpr { - Compare(CmpExpr), - Logic(LogicExpr), - Arith(ArithExpr), - Cast(CastExpr), + Match(MatchExpr), + Operation(Operation), + // Block(Vec), } -#[derive(Clone, Debug, PartialEq)] -pub enum AtomicExpr { - ConstBool(bool), - ConstChar(char), - ConstInt(u64), - ConstFloat(f64), - ConstStr(String), - FnCall(FnCallExpr), - Path(PathExpr), - RefPath(PathExpr), - Paren(Box), -} - -#[derive(Clone, Debug, PartialEq)] -pub enum StatementExpr { - Match(MatchStmt), - If(IfStmt), - Return(ReturnStmt), -} - -#[derive(Clone, Debug, PartialEq)] -pub enum CmpExpr { - Eq(AtomicExpr, AtomicExpr), - NotEq(AtomicExpr, AtomicExpr), - Lt(AtomicExpr, AtomicExpr), - LtEq(AtomicExpr, AtomicExpr), - Gt(AtomicExpr, AtomicExpr), - GtEq(AtomicExpr, AtomicExpr), -} - -#[derive(Clone, Debug, PartialEq)] -pub enum LogicExpr { - And(AtomicExpr, AtomicExpr), - Or(AtomicExpr, AtomicExpr), - Not(AtomicExpr), -} - -#[derive(Clone, Debug, PartialEq)] -pub enum ArithExpr { - Add(AtomicExpr, AtomicExpr), - Sub(AtomicExpr, AtomicExpr), - Mul(AtomicExpr, AtomicExpr), - Div(AtomicExpr, AtomicExpr), - Mod(AtomicExpr, AtomicExpr), - Neg(AtomicExpr), +pub struct BlockExpr { + pub statements: Vec } #[derive(Clone, Debug, PartialEq)] -pub struct CastExpr { - pub value: AtomicExpr, - pub r#type: TypeSpec, +pub struct MatchExpr { + pub value: Operation, + pub variants: Vec, } #[derive(Clone, Debug, PartialEq)] -pub struct FnCallExpr { - pub target: Ident, - pub args: Vec, +pub struct MatchVariant { + pub case: Operation, + pub block: Vec, } diff --git a/crates/concrete_ast/src/lib.rs b/crates/concrete_ast/src/lib.rs index bdf5e9a..c712594 100644 --- a/crates/concrete_ast/src/lib.rs +++ b/crates/concrete_ast/src/lib.rs @@ -1,9 +1,10 @@ pub mod common; pub mod constants; -pub mod expressions; +pub mod operations; pub mod functions; pub mod imports; pub mod modules; pub mod statements; pub mod structs; pub mod types; +pub mod expressions; diff --git a/crates/concrete_ast/src/operations.rs b/crates/concrete_ast/src/operations.rs new file mode 100644 index 0000000..095f56a --- /dev/null +++ b/crates/concrete_ast/src/operations.rs @@ -0,0 +1,82 @@ +use crate::{ + common::Ident, + statements::{IfStmt, ReturnStmt}, + types::TypeSpec, +}; + +#[derive(Clone, Debug, PartialEq)] +pub enum PathSegment { + FieldAccess(Ident), + ArrayIndex(Box), +} + +#[derive(Clone, Debug, PartialEq)] +pub struct PathOp { + pub first: Ident, + pub extra: Vec, +} + +#[derive(Clone, Debug, PartialEq)] +pub enum Operation { + Compound(CompoundOp), + Atomic(AtomicOp), +} + +#[derive(Clone, Debug, PartialEq)] +pub enum CompoundOp { + Compare(CmpOp), + Logic(LogicOp), + Arith(ArithOp), + Cast(CastOp), +} + +#[derive(Clone, Debug, PartialEq)] +pub enum AtomicOp { + ConstBool(bool), + ConstChar(char), + ConstInt(u64), + ConstFloat(f64), + ConstStr(String), + FnCall(FnCallOp), + Path(PathOp), + Paren(Box), +} + +#[derive(Clone, Debug, PartialEq)] +pub enum CmpOp { + Eq(AtomicOp, AtomicOp), + NotEq(AtomicOp, AtomicOp), + Lt(AtomicOp, AtomicOp), + LtEq(AtomicOp, AtomicOp), + Gt(AtomicOp, AtomicOp), + GtEq(AtomicOp, AtomicOp), +} + +#[derive(Clone, Debug, PartialEq)] +pub enum LogicOp { + And(AtomicOp, AtomicOp), + Or(AtomicOp, AtomicOp), + Not(AtomicOp), +} + +#[derive(Clone, Debug, PartialEq)] +pub enum ArithOp { + Add(AtomicOp, AtomicOp), + Sub(AtomicOp, AtomicOp), + Mul(AtomicOp, AtomicOp), + Div(AtomicOp, AtomicOp), + Mod(AtomicOp, AtomicOp), + Neg(AtomicOp), +} + +#[derive(Clone, Debug, PartialEq)] +pub struct CastOp { + pub value: AtomicOp, + pub r#type: TypeSpec, +} + +#[derive(Clone, Debug, 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 96bad3a..c3f6efe 100644 --- a/crates/concrete_ast/src/statements.rs +++ b/crates/concrete_ast/src/statements.rs @@ -1,13 +1,13 @@ use crate::{ common::Ident, - expressions::{Expression, PathExpr}, - types::TypeSpec, + operations::{Operation, PathOp}, + types::TypeSpec, expressions::{Expression, MatchExpr}, }; #[derive(Clone, Debug, PartialEq)] pub enum Statement { Assign(AssignStmt), - Match(MatchStmt), + Match(MatchExpr), For(ForStmt), If(IfStmt), Let(LetStmt), @@ -25,6 +25,7 @@ pub enum LetStmtTarget { pub struct LetStmt { pub is_mutable: bool, pub target: LetStmtTarget, + pub value: Expression, } #[derive(Clone, Debug, PartialEq)] @@ -34,7 +35,7 @@ pub struct ReturnStmt { #[derive(Clone, Debug, PartialEq)] pub struct AssignStmt { - pub target: PathExpr, + pub target: PathOp, pub value: Expression, } @@ -45,35 +46,23 @@ pub struct Binding { pub r#type: TypeSpec, } -#[derive(Clone, Debug, PartialEq)] -pub struct MatchStmt { - pub value: Expression, - pub variants: Vec, -} - -#[derive(Clone, Debug, PartialEq)] -pub struct MatchVariant { - pub case: Expression, - pub block: Vec, -} - #[derive(Clone, Debug, PartialEq)] pub struct ForStmt { pub name: Ident, - pub from: Expression, - pub to: Expression, + pub from: Operation, + pub to: Operation, pub contents: Vec, } #[derive(Clone, Debug, PartialEq)] pub struct IfStmt { - pub value: Expression, + pub value: Operation, pub contents: Vec, pub r#else: Option>, } #[derive(Clone, Debug, PartialEq)] pub struct WhileStmt { - pub value: Expression, + pub value: Operation, pub contents: Vec, } diff --git a/crates/concrete_parser/src/grammar.lalrpop b/crates/concrete_parser/src/grammar.lalrpop index d2dce8a..23075d4 100644 --- a/crates/concrete_parser/src/grammar.lalrpop +++ b/crates/concrete_parser/src/grammar.lalrpop @@ -73,6 +73,16 @@ Comma: Vec = { } }; +SemiColon: Vec = { + ";")*> => match e { + None => v, + Some(e) => { + v.push(e); + v + } + } +}; + PlusSeparated: Vec = { "+")*> => match e { None => v, @@ -139,7 +149,7 @@ pub Program: Vec = { // Modules pub(crate) ModuleBase: ast::modules::ModuleBase = { - "mod" "{" > "}" => { + "mod" "{" "}" => { ast::modules::ModuleBase { doc_string: None, imports: vec![], // todo: add imports @@ -149,8 +159,16 @@ pub(crate) ModuleBase: ast::modules::ModuleBase = { } } +pub(crate) ModuleItems: Vec = { + => vec![<>], + => { + s.push(n); + s + }, +} + pub(crate) ModuleDefItem: ast::modules::ModuleDefItem = { - => { + ";" => { ast::modules::ModuleDefItem::Constant(<>) }, => { @@ -203,55 +221,83 @@ pub(crate) FunctionDef: ast::functions::FunctionDef = { } } -// -- Expressions +// Expressions pub(crate) Expression: ast::expressions::Expression = { - => ast::expressions::Expression::Atomic(<>), - => ast::expressions::Expression::Compound(<>), + => ast::expressions::Expression::Match(<>), + => ast::expressions::Expression::Operation(<>), +} + +pub(crate) MatchExpr: ast::expressions::MatchExpr = { + "match" "{" > "}" => { + ast::expressions::MatchExpr { + value, + variants + } + } +} + +pub(crate) MatchVariant: ast::expressions::MatchVariant = { + // 0 -> 1 + "->" => { + ast::expressions::MatchVariant { + case, + block: vec![stmt] + } + }, + // x -> { ... } + "->" "{" > "}" => { + ast::expressions::MatchVariant { + case, + block: stmts + } + } } -pub(crate) AtomicExpr: ast::expressions::AtomicExpr = { - <"integer"> => ast::expressions::AtomicExpr::ConstInt(<>), - <"boolean"> => ast::expressions::AtomicExpr::ConstBool(<>), - <"string"> => ast::expressions::AtomicExpr::ConstStr(<>), - =>ast::expressions::AtomicExpr::Path(<>), - =>ast::expressions::AtomicExpr::FnCall(<>), +// -- Operations + +pub(crate) Operation: ast::operations::Operation = { + => ast::operations::Operation::Atomic(<>), + => ast::operations::Operation::Compound(<>), } -pub(crate) CompoundExpr: ast::expressions::CompoundExpr = { - => ast::expressions::CompoundExpr::Arith(<>), +pub(crate) AtomicOp: ast::operations::AtomicOp = { + <"integer"> => ast::operations::AtomicOp::ConstInt(<>), + <"boolean"> => ast::operations::AtomicOp::ConstBool(<>), + <"string"> => ast::operations::AtomicOp::ConstStr(<>), + =>ast::operations::AtomicOp::Path(<>), + =>ast::operations::AtomicOp::FnCall(<>), } -pub(crate) StatementExpr: ast::expressions::StatementExpr = { - => ast::expressions::StatementExpr::Match(<>), - => ast::expressions::StatementExpr::Return(<>), +pub(crate) CompoundOp: ast::operations::CompoundOp = { + => ast::operations::CompoundOp::Arith(<>), } -pub(crate) ArithExpr: ast::expressions::ArithExpr = { +pub(crate) ArithOp: ast::operations::ArithOp = { #[precedence(level="1")] - "*" => ast::expressions::ArithExpr::Mul(lhs, rhs), - "/" => ast::expressions::ArithExpr::Div(lhs, rhs), - "%" => ast::expressions::ArithExpr::Mod(lhs, rhs), + "*" => ast::operations::ArithOp::Mul(lhs, rhs), + "/" => ast::operations::ArithOp::Div(lhs, rhs), + "%" => ast::operations::ArithOp::Mod(lhs, rhs), #[precedence(level="2")] #[assoc(side="left")] - "+" => ast::expressions::ArithExpr::Add(lhs, rhs), - "-" => ast::expressions::ArithExpr::Sub(lhs, rhs), + "+" => ast::operations::ArithOp::Add(lhs, rhs), + "-" => ast::operations::ArithOp::Sub(lhs, rhs), #[precedence(level="3")] #[assoc(side="left")] - "-" => ast::expressions::ArithExpr::Neg(value), + "-" => ast::operations::ArithOp::Neg(value), } -pub(crate) PathExpr: ast::expressions::PathExpr = { - => ast::expressions::PathExpr { +pub(crate) PathOp: ast::operations::PathOp = { + => ast::operations::PathOp { first, extra: extra.unwrap_or(vec![]), } } -pub(crate) PathSegment: ast::expressions::PathSegment = { - "." => ast::expressions::PathSegment::FieldAccess(<>), - "[" "]" => ast::expressions::PathSegment::ArrayIndex(Box::new(e)), +pub(crate) PathSegment: ast::operations::PathSegment = { + "." => ast::operations::PathSegment::FieldAccess(<>), + "[" "]" => ast::operations::PathSegment::ArrayIndex(Box::new(e)), } -pub PathSegments: Vec = { +pub PathSegments: Vec = { => vec![<>], => { s.push(n); @@ -259,8 +305,8 @@ pub PathSegments: Vec = { }, } -pub(crate) FnCallExpr: ast::expressions::FnCallExpr = { - "(" > ")" => ast::expressions::FnCallExpr { +pub(crate) FnCallOp: ast::operations::FnCallOp = { + "(" > ")" => ast::operations::FnCallOp { target, args } @@ -269,36 +315,10 @@ pub(crate) FnCallExpr: ast::expressions::FnCallExpr = { // -- Statements pub(crate) Statement: ast::statements::Statement = { - => ast::statements::Statement::Match(<>), + // => ast::statements::Statement::Match(<>), => ast::statements::Statement::Return(<>), } -pub(crate) MatchStmt: ast::statements::MatchStmt = { - "match" "{" > "}" => { - ast::statements::MatchStmt { - value, - variants - } - } -} - -pub(crate) MatchVariant: ast::statements::MatchVariant = { - // 0 -> 1 - "->" => { - ast::statements::MatchVariant { - case, - block: vec![stmt] - } - }, - // x -> { ... } - "->" "{" > "}" => { - ast::statements::MatchVariant { - case, - block: stmts - } - } -} - pub(crate) ReturnStmt: ast::statements::ReturnStmt = { "return"? => ast::statements::ReturnStmt { value, diff --git a/crates/concrete_parser/src/lib.rs b/crates/concrete_parser/src/lib.rs index d333f11..f1a4a7c 100644 --- a/crates/concrete_parser/src/lib.rs +++ b/crates/concrete_parser/src/lib.rs @@ -37,10 +37,10 @@ mod ModuleName { fn parse_factorial() { let source = r##"mod FactorialModule { pub fn factorial(x: u64) -> u64 { - match x { + return match x { 0 -> 1, n -> n * factorial(n-1), - } + }; } }"##; let lexer = Lexer::new(source); @@ -55,11 +55,11 @@ mod ModuleName { } fn print_parser_error(source: &str, err: ParseError) { - match err { + match &err { ParseError::InvalidToken { location } => todo!(), ParseError::UnrecognizedEof { location, expected } => todo!(), ParseError::UnrecognizedToken { token, expected } => { - let (l, tok, r) = token; + let (l, ref tok, r) = *token; let before = &source[0..l]; let after = &source[r..]; @@ -74,6 +74,6 @@ mod ModuleName { ParseError::ExtraToken { token } => todo!(), ParseError::User { error } => todo!(), } - panic!("error parsing"); + panic!("error parsing: {:#?}", err); } } From 8a5dacdbb870f42993d12042bf757b956aca9467 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Fri, 5 Jan 2024 18:52:11 +0100 Subject: [PATCH 11/13] explicit return for now --- crates/concrete_ast/src/constants.rs | 3 ++- crates/concrete_ast/src/expressions.rs | 2 +- crates/concrete_ast/src/lib.rs | 4 ++-- crates/concrete_ast/src/statements.rs | 3 ++- crates/concrete_parser/src/grammar.lalrpop | 4 ++-- crates/concrete_parser/src/lib.rs | 4 ++-- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/crates/concrete_ast/src/constants.rs b/crates/concrete_ast/src/constants.rs index 5cc4e42..e42d9a1 100644 --- a/crates/concrete_ast/src/constants.rs +++ b/crates/concrete_ast/src/constants.rs @@ -1,6 +1,7 @@ use crate::{ common::{DocString, Ident}, - types::TypeSpec, expressions::Expression, + expressions::Expression, + types::TypeSpec, }; #[derive(Clone, Debug, PartialEq)] diff --git a/crates/concrete_ast/src/expressions.rs b/crates/concrete_ast/src/expressions.rs index 1a4d272..4ce4f55 100644 --- a/crates/concrete_ast/src/expressions.rs +++ b/crates/concrete_ast/src/expressions.rs @@ -8,7 +8,7 @@ pub enum Expression { } pub struct BlockExpr { - pub statements: Vec + pub statements: Vec, } #[derive(Clone, Debug, PartialEq)] diff --git a/crates/concrete_ast/src/lib.rs b/crates/concrete_ast/src/lib.rs index c712594..59b5882 100644 --- a/crates/concrete_ast/src/lib.rs +++ b/crates/concrete_ast/src/lib.rs @@ -1,10 +1,10 @@ pub mod common; pub mod constants; -pub mod operations; +pub mod expressions; pub mod functions; pub mod imports; pub mod modules; +pub mod operations; pub mod statements; pub mod structs; pub mod types; -pub mod expressions; diff --git a/crates/concrete_ast/src/statements.rs b/crates/concrete_ast/src/statements.rs index c3f6efe..653dc9d 100644 --- a/crates/concrete_ast/src/statements.rs +++ b/crates/concrete_ast/src/statements.rs @@ -1,7 +1,8 @@ use crate::{ common::Ident, + expressions::{Expression, MatchExpr}, operations::{Operation, PathOp}, - types::TypeSpec, expressions::{Expression, MatchExpr}, + types::TypeSpec, }; #[derive(Clone, Debug, PartialEq)] diff --git a/crates/concrete_parser/src/grammar.lalrpop b/crates/concrete_parser/src/grammar.lalrpop index 23075d4..3a1cdaa 100644 --- a/crates/concrete_parser/src/grammar.lalrpop +++ b/crates/concrete_parser/src/grammar.lalrpop @@ -315,12 +315,12 @@ pub(crate) FnCallOp: ast::operations::FnCallOp = { // -- Statements pub(crate) Statement: ast::statements::Statement = { - // => ast::statements::Statement::Match(<>), + ";" => ast::statements::Statement::Match(<>), => ast::statements::Statement::Return(<>), } pub(crate) ReturnStmt: ast::statements::ReturnStmt = { - "return"? => ast::statements::ReturnStmt { + "return" => ast::statements::ReturnStmt { value, }, } diff --git a/crates/concrete_parser/src/lib.rs b/crates/concrete_parser/src/lib.rs index f1a4a7c..e5c87c9 100644 --- a/crates/concrete_parser/src/lib.rs +++ b/crates/concrete_parser/src/lib.rs @@ -38,8 +38,8 @@ mod ModuleName { let source = r##"mod FactorialModule { pub fn factorial(x: u64) -> u64 { return match x { - 0 -> 1, - n -> n * factorial(n-1), + 0 -> return 1, + n -> return n * factorial(n-1), }; } }"##; From edb031896a10769ab1b559898bdccc7e8f8175c1 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Fri, 5 Jan 2024 18:58:34 +0100 Subject: [PATCH 12/13] format --- crates/concrete_ast/src/operations.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/concrete_ast/src/operations.rs b/crates/concrete_ast/src/operations.rs index 095f56a..17c6dff 100644 --- a/crates/concrete_ast/src/operations.rs +++ b/crates/concrete_ast/src/operations.rs @@ -1,8 +1,4 @@ -use crate::{ - common::Ident, - statements::{IfStmt, ReturnStmt}, - types::TypeSpec, -}; +use crate::{common::Ident, types::TypeSpec}; #[derive(Clone, Debug, PartialEq)] pub enum PathSegment { From 661745d04ba4544721adf1ada5c0be7bb1077cef Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Fri, 5 Jan 2024 19:05:44 +0100 Subject: [PATCH 13/13] cleanup --- crates/concrete_codegen_mlir/src/lib.rs | 13 ------------- crates/concrete_driver/src/lib.rs | 13 ------------- crates/concrete_type_checker/src/lib.rs | 13 ------------- 3 files changed, 39 deletions(-) diff --git a/crates/concrete_codegen_mlir/src/lib.rs b/crates/concrete_codegen_mlir/src/lib.rs index 7d12d9a..8b13789 100644 --- a/crates/concrete_codegen_mlir/src/lib.rs +++ b/crates/concrete_codegen_mlir/src/lib.rs @@ -1,14 +1 @@ -pub fn add(left: usize, right: usize) -> usize { - left + right -} -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} diff --git a/crates/concrete_driver/src/lib.rs b/crates/concrete_driver/src/lib.rs index 7d12d9a..8b13789 100644 --- a/crates/concrete_driver/src/lib.rs +++ b/crates/concrete_driver/src/lib.rs @@ -1,14 +1 @@ -pub fn add(left: usize, right: usize) -> usize { - left + right -} -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} diff --git a/crates/concrete_type_checker/src/lib.rs b/crates/concrete_type_checker/src/lib.rs index 7d12d9a..8b13789 100644 --- a/crates/concrete_type_checker/src/lib.rs +++ b/crates/concrete_type_checker/src/lib.rs @@ -1,14 +1 @@ -pub fn add(left: usize, right: usize) -> usize { - left + right -} -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -}