use super::super::pair_span;
use crate::ast::{Expr, FunctionParameter, Span, Statement, TypeAnnotation};
use crate::error::Result;
use crate::parser::Rule;
use pest::iterators::Pair;
pub fn parse_function_expr(pair: Pair<Rule>) -> Result<Expr> {
match pair.as_rule() {
Rule::function_expr => {
let inner_pairs: Vec<_> = pair.clone().into_inner().collect();
if !inner_pairs.is_empty() && inner_pairs[0].as_rule() == Rule::pipe_lambda {
parse_pipe_lambda(inner_pairs.into_iter().next().unwrap())
} else {
parse_regular_function_expr(pair)
}
}
Rule::pipe_lambda => parse_pipe_lambda(pair),
_ => parse_regular_function_expr(pair),
}
}
pub fn parse_pipe_lambda(pair: Pair<Rule>) -> Result<Expr> {
let span = pair_span(&pair);
let inner = pair.into_inner();
let mut params = vec![];
let mut body_expr = None;
let mut body_stmts = vec![];
for part in inner {
match part.as_rule() {
Rule::function_params => {
for param_pair in part.into_inner() {
if param_pair.as_rule() == Rule::function_param {
params.push(crate::parser::functions::parse_function_param(param_pair)?);
}
}
}
Rule::expression => {
body_expr = Some(super::parse_expression(part)?);
}
Rule::function_body => {
body_stmts = crate::parser::statements::parse_statements(part.into_inner())?;
}
_ => {}
}
}
let body = if let Some(expr) = body_expr {
vec![Statement::Return(Some(expr), Span::DUMMY)]
} else {
body_stmts
};
Ok(Expr::FunctionExpr {
params,
return_type: None,
body,
span,
})
}
pub fn parse_arrow_function(pair: Pair<Rule>) -> Result<Expr> {
let span = pair_span(&pair);
let inner = pair.into_inner();
let mut params = vec![];
let mut return_type: Option<TypeAnnotation> = None;
let mut body_expr = None;
let mut body_stmts = vec![];
for part in inner {
match part.as_rule() {
Rule::ident => {
let pattern = crate::ast::DestructurePattern::Identifier(
part.as_str().to_string(),
pair_span(&part),
);
params.push(FunctionParameter {
pattern,
is_const: false,
is_reference: false,
is_mut_reference: false,
is_out: false,
type_annotation: None,
default_value: None,
});
}
Rule::function_params => {
for param_pair in part.into_inner() {
if param_pair.as_rule() == Rule::function_param {
params.push(crate::parser::functions::parse_function_param(param_pair)?);
}
}
}
Rule::function_param => {
params.push(crate::parser::functions::parse_function_param(part)?);
}
Rule::return_type => {
return_type = Some(crate::parser::parse_type_annotation(
part.into_inner().next().unwrap(),
)?);
}
Rule::expression => {
body_expr = Some(super::parse_expression(part)?);
}
Rule::function_body => {
body_stmts = crate::parser::statements::parse_statements(part.into_inner())?;
}
_ => {}
}
}
let body = if let Some(expr) = body_expr {
vec![Statement::Return(Some(expr), Span::DUMMY)]
} else {
body_stmts
};
Ok(Expr::FunctionExpr {
params,
return_type,
body,
span,
})
}
pub fn parse_regular_function_expr(pair: Pair<Rule>) -> Result<Expr> {
let span = pair_span(&pair);
let inner_pairs: Vec<_> = if pair.as_rule() == Rule::function_expr {
pair.into_inner().collect()
} else {
vec![pair]
};
let mut params = vec![];
let mut return_type: Option<TypeAnnotation> = None;
let mut body = vec![];
for part in inner_pairs {
match part.as_rule() {
Rule::function_params => {
for param_pair in part.into_inner() {
if param_pair.as_rule() == Rule::function_param {
params.push(crate::parser::functions::parse_function_param(param_pair)?);
}
}
}
Rule::return_type => {
return_type = Some(crate::parser::parse_type_annotation(
part.into_inner().next().unwrap(),
)?);
}
Rule::function_body => {
for stmt_pair in part.into_inner() {
if stmt_pair.as_rule() == Rule::statement {
body.push(crate::parser::statements::parse_statement(stmt_pair)?);
}
}
}
_ => {}
}
}
Ok(Expr::FunctionExpr {
params,
return_type,
body,
span,
})
}
pub fn parse_arg_list(pair: Pair<Rule>) -> Result<(Vec<Expr>, Vec<(String, Expr)>)> {
let mut positional_args = Vec::new();
let mut named_args = Vec::new();
if let Some(arg_list) = pair.into_inner().next() {
for argument in arg_list.into_inner() {
match argument.as_rule() {
Rule::argument => {
let inner = argument.into_inner().next().unwrap();
match inner.as_rule() {
Rule::named_arg => {
let mut parts = inner.into_inner();
let name = parts.next().unwrap().as_str().to_string();
let value = super::parse_expression(parts.next().unwrap())?;
named_args.push((name, value));
}
_ => {
positional_args.push(super::parse_expression(inner)?);
}
}
}
Rule::named_arg => {
let mut parts = argument.into_inner();
let name = parts.next().unwrap().as_str().to_string();
let value = super::parse_expression(parts.next().unwrap())?;
named_args.push((name, value));
}
_ => {
positional_args.push(super::parse_expression(argument)?);
}
}
}
}
Ok((positional_args, named_args))
}