Skip to content

Commit

Permalink
Transpile trailing closure syntax and add std functions for if, try a…
Browse files Browse the repository at this point in the history
…nd for
  • Loading branch information
antoniusnaumann committed Jan 6, 2024
1 parent 97213bf commit 2b03218
Show file tree
Hide file tree
Showing 19 changed files with 319 additions and 47 deletions.
78 changes: 78 additions & 0 deletions galvan-ast/src/item/closure.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use crate::{
Block, ConstructorCall, Expression, FunctionCall, Ident, MemberFieldAccess, MemberFunctionCall,
TypeElement,
};
use from_pest::pest::iterators::Pairs;
use from_pest::ConversionError::NoMatch;
use from_pest::{ConversionError, FromPest, Void};
use galvan_pest::Rule;
use typeunion::type_union;

#[derive(Debug, PartialEq, Eq)]
pub struct Closure {
pub arguments: Vec<ClosureArgument>,
pub block: Block,
}

impl FromPest<'_> for Closure {
type Rule = Rule;
type FatalError = Void;

fn from_pest(
pairs: &mut Pairs<'_, Self::Rule>,
) -> Result<Self, ConversionError<Self::FatalError>> {
let Some(pair) = pairs.next() else {
return Err(NoMatch);
};
if pair.as_rule() != Rule::closure && pair.as_rule() != Rule::trailing_closure {
return Err(NoMatch);
}

let mut pairs = pair.into_inner();
let arguments = Vec::<ClosureArgument>::from_pest(&mut pairs)?;
let block = Block::from_pest(&mut pairs)?;

Ok(Self { arguments, block })
}
}

#[derive(Debug, PartialEq, Eq, FromPest)]
#[pest_ast(rule(Rule::closure_argument))]
pub struct ClosureArgument {
pub ident: Ident,
pub ty: Option<TypeElement>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct ElseExpression {
pub receiver: Box<Expression>,
pub block: Block,
}

#[type_union(super = Expression)]
#[derive(Debug, PartialEq, Eq, FromPest)]
#[pest_ast(rule(Rule::allowed_before_else_expression))]
type AllowedBeforeElseExpression =
FunctionCall + ConstructorCall + MemberFunctionCall + MemberFieldAccess + Ident;

impl FromPest<'_> for ElseExpression {
type Rule = Rule;
type FatalError = Void;

fn from_pest(
pairs: &mut Pairs<'_, Self::Rule>,
) -> Result<Self, ConversionError<Self::FatalError>> {
let Some(pair) = pairs.next() else {
return Err(NoMatch);
};
if pair.as_rule() != Rule::else_expression {
return Err(NoMatch);
}

let mut pairs = pair.into_inner();
let receiver = Box::new(AllowedBeforeElseExpression::from_pest(&mut pairs)?.into());
let block = Block::from_pest(&mut pairs)?;

Ok(Self { receiver, block })
}
}
2 changes: 1 addition & 1 deletion galvan-ast/src/item/fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use super::*;
#[pest_ast(rule(Rule::function))]
pub struct FnDecl {
pub signature: FnSignature,
pub block: Block,
pub block: Body,
}

#[derive(Debug, PartialEq, Eq, FromPest)]
Expand Down
82 changes: 78 additions & 4 deletions galvan-ast/src/item/function_call.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,95 @@
use crate::{DeclModifier, Expression, Ident, TypeIdent};
use crate::{
ArithmeticOperation, BooleanLiteral, Closure, CollectionOperation, ComparisonOperation,
DeclModifier, Expression, Ident, LogicalOperation, NumberLiteral, StringLiteral, TypeIdent,
};
use derive_more::From;
use from_pest::pest::iterators::Pairs;
use from_pest::ConversionError::NoMatch;
use from_pest::{ConversionError, FromPest, Void};
use galvan_pest::Rule;
use typeunion::type_union;

#[derive(Debug, PartialEq, Eq, FromPest)]
#[pest_ast(rule(Rule::function_call))]
#[derive(Debug, PartialEq, Eq)]
pub struct FunctionCall {
pub identifier: Ident,
pub arguments: Vec<FunctionCallArg>,
}

#[derive(Debug, PartialEq, Eq, From, FromPest)]
impl FromPest<'_> for FunctionCall {
type Rule = Rule;
type FatalError = Void;

fn from_pest(
pairs: &mut Pairs<'_, Self::Rule>,
) -> Result<Self, ConversionError<Self::FatalError>> {
let Some(pair) = pairs.next() else {
return Err(NoMatch);
};
let rule = pair.as_rule();
match rule {
Rule::function_call | Rule::trailing_closure_call => {
let mut pairs = pair.into_inner();
let identifier = Ident::from_pest(&mut pairs)?;

let arguments = if rule == Rule::function_call {
Vec::<FunctionCallArg>::from_pest(&mut pairs)?
} else {
let arguments = Vec::<TrailingClosureCallArg>::from_pest(&mut pairs)?;
let closure = Closure::from_pest(&mut pairs)?;
let mut arguments = arguments
.into_iter()
.map(|arg| FunctionCallArg {
modifier: arg.modifier,
expression: arg.expression.into(),
})
.collect::<Vec<_>>();
arguments.push(FunctionCallArg {
modifier: DeclModifier::Inherited,
expression: closure.into(),
});
arguments
};

Ok(Self {
identifier,
arguments,
})
}
_ => Err(NoMatch),
}
}
}

#[derive(Debug, PartialEq, Eq, FromPest)]
#[pest_ast(rule(Rule::function_call_arg))]
pub struct FunctionCallArg {
pub modifier: DeclModifier,
pub expression: Expression,
}

#[derive(Debug, PartialEq, Eq, FromPest)]
#[pest_ast(rule(Rule::trailing_closure_call_arg))]
struct TrailingClosureCallArg {
modifier: DeclModifier,
expression: AllowedInTrailingClosureCall,
}

#[type_union(super = Expression)]
#[derive(Debug, PartialEq, Eq, FromPest)]
#[pest_ast(rule(Rule::allowed_in_trailing_closure_call))]
type AllowedInTrailingClosureCall = LogicalOperation
+ ComparisonOperation
+ CollectionOperation
+ ArithmeticOperation
+ FunctionCall
+ ConstructorCall
+ MemberFunctionCall
+ MemberFieldAccess
+ BooleanLiteral
+ StringLiteral
+ NumberLiteral
+ Ident;

#[derive(Debug, PartialEq, Eq, FromPest)]
#[pest_ast(rule(Rule::member_function_call))]
pub struct MemberFunctionCall {
Expand Down
2 changes: 2 additions & 0 deletions galvan-ast/src/item/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod assignment;
mod closure;
mod r#fn;
mod function_call;
mod ident;
Expand All @@ -12,6 +13,7 @@ mod r#type;
mod type_item;

pub use assignment::*;
pub use closure::*;
pub use function_call::*;
pub use ident::*;
pub use literal::*;
Expand Down
15 changes: 12 additions & 3 deletions galvan-ast/src/item/statement.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
use super::*;
use crate::item::closure::Closure;
use galvan_pest::Rule;
use typeunion::type_union;

#[derive(Debug, PartialEq, Eq, FromPest)]
#[pest_ast(rule(Rule::body))]
pub struct Block {
pub struct Body {
pub statements: Vec<Statement>,
}

#[derive(Debug, PartialEq, Eq, FromPest)]
#[pest_ast(rule(Rule::block))]
pub struct Block {
pub body: Body,
}

#[type_union]
#[derive(Debug, PartialEq, Eq, FromPest)]
#[pest_ast(rule(Rule::statement))]
pub type Statement = Assignment + Expression + Declaration;
pub type Statement = Assignment + Expression + Declaration + Block;

#[derive(Debug, PartialEq, Eq, FromPest)]
#[pest_ast(rule(Rule::declaration))]
Expand All @@ -25,7 +32,9 @@ pub struct Declaration {
#[type_union]
#[derive(Debug, PartialEq, Eq, FromPest)]
#[pest_ast(rule(Rule::expression))]
pub type Expression = LogicalOperation
pub type Expression = ElseExpression
+ Closure
+ LogicalOperation
+ ComparisonOperation
+ CollectionOperation
+ ArithmeticOperation
Expand Down
8 changes: 4 additions & 4 deletions galvan-ast/src/item/tasks.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
use galvan_pest::Rule;

use super::{Block, Ident, StringLiteral};
use super::{Body, Ident, StringLiteral};

#[derive(Debug, PartialEq, Eq, FromPest)]
#[pest_ast(rule(Rule::main))]
pub struct MainDecl {
pub body: Block,
pub body: Body,
}

#[derive(Debug, PartialEq, Eq, FromPest)]
#[pest_ast(rule(Rule::test))]
pub struct TestDecl {
pub name: Option<StringLiteral>,
pub body: Block,
pub body: Body,
}

#[derive(Debug, PartialEq, Eq, FromPest)]
#[pest_ast(rule(Rule::task))]
pub struct TaskDecl {
pub ident: Ident,
// name: Option<String>,
pub body: Block,
pub body: Body,
}
2 changes: 1 addition & 1 deletion galvan-ast/src/item/toplevel.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use derive_more::From;
use galvan_pest::Rule;

use super::{FnDecl, MainDecl, TaskDecl, TestDecl, TypeDecl};
use super::{FnDecl, MainDecl, TestDecl, TypeDecl};

#[derive(Debug, PartialEq, Eq, From, FromPest)]
#[pest_ast(rule(Rule::toplevel))]
Expand Down
12 changes: 6 additions & 6 deletions galvan-ast/tests/test_ast_conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mod test_utils {

pub fn main(statements: Vec<Statement>) -> RootItem {
RootItem::Main(MainDecl {
body: Block { statements },
body: Body { statements },
})
}

Expand Down Expand Up @@ -117,7 +117,7 @@ mod test_utils {
name: &str,
parameters: ParamList,
return_type: Option<TypeElement>,
block: Block,
block: Body,
) -> FnDecl {
FnDecl {
signature: FnSignature {
Expand All @@ -143,12 +143,12 @@ mod test_utils {
}
}

pub fn empty_body() -> Block {
Block { statements: vec![] }
pub fn empty_body() -> Body {
Body { statements: vec![] }
}

pub fn body(statements: Vec<Statement>) -> Block {
Block { statements }
pub fn body(statements: Vec<Statement>) -> Body {
Body { statements }
}

pub fn number(value: &str) -> Expression {
Expand Down
Loading

0 comments on commit 2b03218

Please sign in to comment.