diff --git a/crates/aiken-lang/src/ast.rs b/crates/aiken-lang/src/ast.rs index a2b1ad89..81acaa96 100644 --- a/crates/aiken-lang/src/ast.rs +++ b/crates/aiken-lang/src/ast.rs @@ -475,6 +475,7 @@ impl Constant { } pub type TypedCallArg = CallArg; +pub type ParsedCallArg = CallArg>; #[derive(Debug, Clone, PartialEq, Eq)] pub struct CallArg { diff --git a/crates/aiken-lang/src/expr.rs b/crates/aiken-lang/src/expr.rs index cf66cb82..73bdf354 100644 --- a/crates/aiken-lang/src/expr.rs +++ b/crates/aiken-lang/src/expr.rs @@ -4,9 +4,9 @@ use vec1::Vec1; use crate::{ ast::{ - Annotation, Arg, AssignmentKind, BinOp, ByteArrayFormatPreference, CallArg, - DefinitionLocation, IfBranch, Pattern, RecordUpdateSpread, Span, TraceKind, TypedClause, - TypedRecordUpdateArg, UnOp, UntypedClause, UntypedRecordUpdateArg, + self, Annotation, Arg, AssignmentKind, BinOp, ByteArrayFormatPreference, CallArg, + DefinitionLocation, IfBranch, ParsedCallArg, Pattern, RecordUpdateSpread, Span, TraceKind, + TypedClause, TypedRecordUpdateArg, UnOp, UntypedClause, UntypedRecordUpdateArg, }, builtins::void, parser::token::Base, @@ -564,6 +564,88 @@ impl UntypedExpr { } } + pub fn tuple_index(self, index: usize, location: Span) -> Self { + UntypedExpr::TupleIndex { + location: self.location().union(location), + index, + tuple: Box::new(self), + } + } + + pub fn field_access(self, label: String, location: Span) -> Self { + UntypedExpr::FieldAccess { + location: self.location().union(location), + label, + container: Box::new(self), + } + } + + pub fn call(self, args: Vec, location: Span) -> Self { + let mut holes = Vec::new(); + + let args = args + .into_iter() + .enumerate() + .map(|(index, a)| match a { + CallArg { + value: Some(value), + label, + location, + } => CallArg { + value, + label, + location, + }, + CallArg { + value: None, + label, + location, + } => { + let name = format!("{}__{index}", ast::CAPTURE_VARIABLE); + + holes.push(ast::Arg { + location: Span::empty(), + annotation: None, + arg_name: ast::ArgName::Named { + label: name.clone(), + name, + location: Span::empty(), + is_validator_param: false, + }, + tipo: (), + }); + + ast::CallArg { + label, + location, + value: UntypedExpr::Var { + location, + name: format!("{}__{index}", ast::CAPTURE_VARIABLE), + }, + } + } + }) + .collect(); + + let call = UntypedExpr::Call { + location: self.location().union(location), + fun: Box::new(self), + arguments: args, + }; + + if holes.is_empty() { + call + } else { + UntypedExpr::Fn { + location: call.location(), + fn_style: FnStyle::Capture, + arguments: holes, + body: Box::new(call), + return_annotation: None, + } + } + } + pub fn append_in_sequence(self, next: Self) -> Self { let location = Span { start: self.location().start, diff --git a/crates/aiken-lang/src/parser/chain/call.rs b/crates/aiken-lang/src/parser/chain/call.rs index 42e7b222..a60b9abe 100644 --- a/crates/aiken-lang/src/parser/chain/call.rs +++ b/crates/aiken-lang/src/parser/chain/call.rs @@ -1,8 +1,8 @@ use chumsky::prelude::*; -use super::{Chain, ParserArg}; +use super::Chain; use crate::{ - ast, + ast::CallArg, expr::UntypedExpr, parser::{token::Token, ParseError}, }; @@ -15,20 +15,19 @@ pub(crate) fn parser( .then_ignore(just(Token::Colon)) .or_not() .then(expression) - .map_with_span(|(label, value), span| { - ParserArg::Arg(Box::new(ast::CallArg { - label, - location: span, - value, - })) + .map_with_span(|(label, value), location| CallArg { + label, + location, + value: Some(value), }), select! { Token::Name { name } => name } .then_ignore(just(Token::Colon)) .or_not() .then_ignore(select! {Token::DiscardName {name} => name }) - .map_with_span(|label, span| ParserArg::Hole { - location: span, + .map_with_span(|label, location| CallArg { + location, label, + value: None, }), )) .separated_by(just(Token::Comma)) diff --git a/crates/aiken-lang/src/parser/chain/mod.rs b/crates/aiken-lang/src/parser/chain/mod.rs index baad4516..c56ff929 100644 --- a/crates/aiken-lang/src/parser/chain/mod.rs +++ b/crates/aiken-lang/src/parser/chain/mod.rs @@ -1,22 +1,11 @@ -use crate::ast::{self, Span}; -use crate::expr::UntypedExpr; +use crate::ast::{ParsedCallArg, Span}; pub(crate) mod call; pub(crate) mod field_access; pub(crate) mod tuple_index; pub(crate) enum Chain { - Call(Vec, Span), + Call(Vec, Span), FieldAccess(String, Span), TupleIndex(usize, Span), } - -// Parsing a function call into the appropriate structure -#[derive(Debug)] -pub(crate) enum ParserArg { - Arg(Box>), - Hole { - location: Span, - label: Option, - }, -} diff --git a/crates/aiken-lang/src/parser/expr/chained.rs b/crates/aiken-lang/src/parser/expr/chained.rs index 2a12e96d..b09927e3 100644 --- a/crates/aiken-lang/src/parser/expr/chained.rs +++ b/crates/aiken-lang/src/parser/expr/chained.rs @@ -16,13 +16,9 @@ use super::var::parser as var; use super::when::parser as when; use crate::{ - ast::{self, Span}, - expr::{FnStyle, UntypedExpr}, + expr::UntypedExpr, parser::{ - chain::{ - call::parser as call, field_access, tuple_index::parser as tuple_index, Chain, - ParserArg, - }, + chain::{call::parser as call, field_access, tuple_index::parser as tuple_index, Chain}, error::ParseError, token::Token, }, @@ -40,71 +36,17 @@ pub fn parser<'a>( chain_start(sequence, expression) .then(chain.repeated()) .foldl(|expr, chain| match chain { - Chain::Call(args, span) => { - let mut holes = Vec::new(); - - let args = args - .into_iter() - .enumerate() - .map(|(index, a)| match a { - ParserArg::Arg(arg) => *arg, - ParserArg::Hole { location, label } => { - let name = format!("{}__{index}", ast::CAPTURE_VARIABLE); - - holes.push(ast::Arg { - location: Span::empty(), - annotation: None, - arg_name: ast::ArgName::Named { - label: name.clone(), - name, - location: Span::empty(), - is_validator_param: false, - }, - tipo: (), - }); - - ast::CallArg { - label, - location, - value: UntypedExpr::Var { - location, - name: format!("{}__{index}", ast::CAPTURE_VARIABLE), - }, - } - } - }) - .collect(); - - let call = UntypedExpr::Call { - location: expr.location().union(span), - fun: Box::new(expr), - arguments: args, - }; - - if holes.is_empty() { - call - } else { - UntypedExpr::Fn { - location: call.location(), - fn_style: FnStyle::Capture, - arguments: holes, - body: Box::new(call), - return_annotation: None, - } - } - } - - Chain::FieldAccess(label, span) => UntypedExpr::FieldAccess { - location: expr.location().union(span), - label, - container: Box::new(expr), - }, - - Chain::TupleIndex(index, span) => UntypedExpr::TupleIndex { - location: expr.location().union(span), - index, - tuple: Box::new(expr), + Chain::Call(args, span) => expr.call(args, span), + Chain::FieldAccess(label, span) => expr.field_access(label, span), + Chain::TupleIndex(index, span) => expr.tuple_index(index, span), + }) + .then(just(Token::Question).or_not()) + .map_with_span(|(value, token), location| match token { + Some(_) => UntypedExpr::TraceIfFalse { + value: Box::new(value), + location, }, + None => value, }) } diff --git a/crates/aiken-lang/src/parser/expr/mod.rs b/crates/aiken-lang/src/parser/expr/mod.rs index 4f651c0d..1f5cd277 100644 --- a/crates/aiken-lang/src/parser/expr/mod.rs +++ b/crates/aiken-lang/src/parser/expr/mod.rs @@ -53,16 +53,6 @@ pub fn pure_expression<'a>( sequence: Recursive<'a, Token, UntypedExpr, ParseError>, expression: Recursive<'a, Token, UntypedExpr, ParseError>, ) -> impl Parser + 'a { - let chained_debugged = chained(sequence, expression) - .then(just(Token::Question).or_not()) - .map_with_span(|(value, token), location| match token { - Some(_) => UntypedExpr::TraceIfFalse { - value: Box::new(value), - location, - }, - None => value, - }); - // Negate let op = choice(( just(Token::Bang).to(ast::UnOp::Not), @@ -85,7 +75,7 @@ pub fn pure_expression<'a>( let unary = op .map_with_span(|op, span| (op, span)) .repeated() - .then(chained_debugged) + .then(chained(sequence, expression)) .foldr(|(un_op, span), value| UntypedExpr::UnOp { op: un_op, location: span.union(value.location()),