Skip to content

Commit

Permalink
Addressed comments on benchmarking PR
Browse files Browse the repository at this point in the history
  • Loading branch information
Riley-Kilgore committed Jan 14, 2025
1 parent f8d4e8a commit c7657ce
Show file tree
Hide file tree
Showing 18 changed files with 254 additions and 352 deletions.
57 changes: 25 additions & 32 deletions crates/aiken-lang/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,23 +606,29 @@ impl<'comments> Formatter<'comments> {
}

#[allow(clippy::too_many_arguments)]
fn definition_test<'a>(
fn definition_test_or_bench<'a>(
&mut self,
keyword: &'static str,
name: &'a str,
args: &'a [UntypedArgVia],
body: &'a UntypedExpr,
end_location: usize,
on_test_failure: &'a OnTestFailure,
) -> Document<'a> {
// Fn name and args
let head = "test "
let head = keyword
.to_doc()
.append(" ")
.append(name)
.append(wrap_args(args.iter().map(|e| (self.fn_arg_via(e), false))))
.append(match on_test_failure {
OnTestFailure::FailImmediately => "",
OnTestFailure::SucceedEventually => " fail",
OnTestFailure::SucceedImmediately => " fail once",
.append(if keyword == "test" {
match on_test_failure {
OnTestFailure::FailImmediately => "",
OnTestFailure::SucceedEventually => " fail",
OnTestFailure::SucceedImmediately => " fail once",
}
} else {
""
})
.group();

Expand All @@ -643,40 +649,27 @@ impl<'comments> Formatter<'comments> {
}

#[allow(clippy::too_many_arguments)]
fn definition_benchmark<'a>(
fn definition_test<'a>(
&mut self,
name: &'a str,
args: &'a [UntypedArgVia],
body: &'a UntypedExpr,
end_location: usize,
on_test_failure: &'a OnTestFailure,
) -> Document<'a> {
// Fn name and args
let head = "bench "
.to_doc()
.append(name)
.append(wrap_args(args.iter().map(|e| (self.fn_arg_via(e), false))))
.append(match on_test_failure {
OnTestFailure::FailImmediately => "",
OnTestFailure::SucceedEventually => "",
OnTestFailure::SucceedImmediately => "",
})
.group();

// Format body
let body = self.expr(body, true);

// Add any trailing comments
let body = match printed_comments(self.pop_comments(end_location), false) {
Some(comments) => body.append(line()).append(comments),
None => body,
};
self.definition_test_or_bench("test", name, args, body, end_location, on_test_failure)
}

// Stick it all together
head.append(" {")
.append(line().append(body).nest(INDENT).group())
.append(line())
.append("}")
#[allow(clippy::too_many_arguments)]
fn definition_benchmark<'a>(
&mut self,
name: &'a str,
args: &'a [UntypedArgVia],
body: &'a UntypedExpr,
end_location: usize,
on_test_failure: &'a OnTestFailure,
) -> Document<'a> {
self.definition_test_or_bench("bench", name, args, body, end_location, on_test_failure)
}

fn definition_validator<'a>(
Expand Down
123 changes: 2 additions & 121 deletions crates/aiken-lang/src/parser/definition/benchmark.rs
Original file line number Diff line number Diff line change
@@ -1,130 +1,11 @@
use crate::{
ast,
ast::OnTestFailure,
expr::UntypedExpr,
parser::{
annotation,
chain::{call::parser as call, field_access, tuple_index::parser as tuple_index, Chain},
error::ParseError,
expr::{self, bytearray, int as uint, list, string, tuple, var},
pattern,
token::Token,
},
parser::{error::ParseError, token::Token},
};
use chumsky::prelude::*;

pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
just(Token::Benchmark)
.ignore_then(select! {Token::Name {name} => name})
.then(
via()
.separated_by(just(Token::Comma))
.allow_trailing()
.delimited_by(just(Token::LeftParen), just(Token::RightParen)),
)
.then(
just(Token::Fail)
.ignore_then(just(Token::Once).ignored().or_not().map(|once| {
once.map(|_| OnTestFailure::SucceedImmediately)
.unwrap_or(OnTestFailure::SucceedEventually)
}))
.or_not(),
)
.map_with_span(|name, span| (name, span))
.then(
expr::sequence()
.or_not()
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
)
.map_with_span(|((((name, arguments), fail), span_end), body), span| {
ast::UntypedDefinition::Benchmark(ast::Function {
arguments,
body: body.unwrap_or_else(|| UntypedExpr::todo(None, span)),
doc: None,
location: span_end,
end_position: span.end - 1,
name,
public: false,
return_annotation: None,
return_type: (),
on_test_failure: fail.unwrap_or(OnTestFailure::FailImmediately),
})
})
}

pub fn via() -> impl Parser<Token, ast::UntypedArgVia, Error = ParseError> {
choice((
select! {Token::DiscardName {name} => name}.map_with_span(|name, span| {
ast::ArgBy::ByName(ast::ArgName::Discarded {
label: name.clone(),
name,
location: span,
})
}),
select! {Token::Name {name} => name}.map_with_span(|name, location| {
ast::ArgBy::ByName(ast::ArgName::Named {
label: name.clone(),
name,
location,
})
}),
pattern().map(ast::ArgBy::ByPattern),
))
.then(just(Token::Colon).ignore_then(annotation()).or_not())
.map_with_span(|(arg_name, annotation), location| (arg_name, annotation, location))
.then_ignore(just(Token::Via))
.then(fuzzer())
.map(|((by, annotation, location), via)| ast::ArgVia {
arg: ast::UntypedArg {
by,
annotation,
location,
doc: None,
is_validator_param: false,
},
via,
})
}

pub fn fuzzer<'a>() -> impl Parser<Token, UntypedExpr, Error = ParseError> + 'a {
recursive(|expression| {
let chain = choice((
tuple_index(),
field_access::parser(),
call(expression.clone()),
));

let int = || {
just(Token::Minus)
.to(ast::UnOp::Negate)
.map_with_span(|op, span| (op, span))
.or_not()
.then(uint())
.map(|(op, value)| match op {
None => value,
Some((op, location)) => UntypedExpr::UnOp {
op,
location,
value: Box::new(value),
},
})
};

choice((
int(),
string(),
bytearray(),
tuple(expression.clone()),
list(expression.clone()),
var(),
))
.then(chain.repeated())
.foldl(|expr, chain| match chain {
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),
})
})
crate::parser::definition::test_like::parser(Token::Benchmark)
}

#[cfg(test)]
Expand Down
1 change: 1 addition & 0 deletions crates/aiken-lang/src/parser/definition/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod data_type;
mod function;
pub mod import;
mod test;
pub mod test_like;
mod type_alias;
mod validator;

Expand Down
121 changes: 2 additions & 119 deletions crates/aiken-lang/src/parser/definition/test.rs
Original file line number Diff line number Diff line change
@@ -1,131 +1,14 @@
use crate::{
ast,
ast::OnTestFailure,
expr::UntypedExpr,
parser::{
annotation,
chain::{call::parser as call, field_access, tuple_index::parser as tuple_index, Chain},
error::ParseError,
expr::{self, bytearray, int as uint, list, string, tuple, var},
pattern,
token::Token,
},
parser::{error::ParseError, token::Token},
};
use chumsky::prelude::*;

pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
just(Token::Test)
.ignore_then(select! {Token::Name {name} => name})
.then(
via()
.separated_by(just(Token::Comma))
.allow_trailing()
.delimited_by(just(Token::LeftParen), just(Token::RightParen)),
)
.then(
just(Token::Fail)
.ignore_then(just(Token::Once).ignored().or_not().map(|once| {
once.map(|_| OnTestFailure::SucceedImmediately)
.unwrap_or(OnTestFailure::SucceedEventually)
}))
.or_not(),
)
.map_with_span(|name, span| (name, span))
.then(
expr::sequence()
.or_not()
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
)
.map_with_span(|((((name, arguments), fail), span_end), body), span| {
ast::UntypedDefinition::Test(ast::Function {
arguments,
body: body.unwrap_or_else(|| UntypedExpr::todo(None, span)),
doc: None,
location: span_end,
end_position: span.end - 1,
name,
public: false,
return_annotation: None,
return_type: (),
on_test_failure: fail.unwrap_or(OnTestFailure::FailImmediately),
})
})
crate::parser::definition::test_like::parser(Token::Test)
}

pub fn via() -> impl Parser<Token, ast::UntypedArgVia, Error = ParseError> {
choice((
select! {Token::DiscardName {name} => name}.map_with_span(|name, span| {
ast::ArgBy::ByName(ast::ArgName::Discarded {
label: name.clone(),
name,
location: span,
})
}),
select! {Token::Name {name} => name}.map_with_span(|name, location| {
ast::ArgBy::ByName(ast::ArgName::Named {
label: name.clone(),
name,
location,
})
}),
pattern().map(ast::ArgBy::ByPattern),
))
.then(just(Token::Colon).ignore_then(annotation()).or_not())
.map_with_span(|(arg_name, annotation), location| (arg_name, annotation, location))
.then_ignore(just(Token::Via))
.then(fuzzer())
.map(|((by, annotation, location), via)| ast::ArgVia {
arg: ast::UntypedArg {
by,
annotation,
location,
doc: None,
is_validator_param: false,
},
via,
})
}

pub fn fuzzer<'a>() -> impl Parser<Token, UntypedExpr, Error = ParseError> + 'a {
recursive(|expression| {
let chain = choice((
tuple_index(),
field_access::parser(),
call(expression.clone()),
));

let int = || {
just(Token::Minus)
.to(ast::UnOp::Negate)
.map_with_span(|op, span| (op, span))
.or_not()
.then(uint())
.map(|(op, value)| match op {
None => value,
Some((op, location)) => UntypedExpr::UnOp {
op,
location,
value: Box::new(value),
},
})
};

choice((
int(),
string(),
bytearray(),
tuple(expression.clone()),
list(expression.clone()),
var(),
))
.then(chain.repeated())
.foldl(|expr, chain| match chain {
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),
})
})
}

#[cfg(test)]
mod tests {
Expand Down
Loading

0 comments on commit c7657ce

Please sign in to comment.