feat: implement new validator parsing
This commit is contained in:
parent
c98e32d3e9
commit
0de5cbc74e
|
@ -541,10 +541,11 @@ pub type UntypedValidator = Validator<(), UntypedArg, UntypedExpr>;
|
|||
pub struct Validator<T, Arg, Expr> {
|
||||
pub doc: Option<String>,
|
||||
pub end_position: usize,
|
||||
pub fun: Function<T, Expr, Arg>,
|
||||
pub other_fun: Option<Function<T, Expr, Arg>>,
|
||||
pub handlers: Vec<Function<T, Expr, Arg>>,
|
||||
pub location: Span,
|
||||
pub name: String,
|
||||
pub params: Vec<Arg>,
|
||||
pub fallback: Function<T, Expr, Arg>,
|
||||
}
|
||||
|
||||
impl TypedValidator {
|
||||
|
@ -552,12 +553,12 @@ impl TypedValidator {
|
|||
self.params
|
||||
.iter()
|
||||
.find_map(|arg| arg.find_node(byte_index))
|
||||
.or_else(|| self.fun.find_node(byte_index))
|
||||
.or_else(|| {
|
||||
self.other_fun
|
||||
.as_ref()
|
||||
.and_then(|f| f.find_node(byte_index))
|
||||
self.handlers
|
||||
.iter()
|
||||
.find_map(|func| func.find_node(byte_index))
|
||||
})
|
||||
.or_else(|| self.fallback.find_node(byte_index))
|
||||
}
|
||||
|
||||
pub fn into_function_definition<'a, F>(
|
||||
|
@ -568,27 +569,28 @@ impl TypedValidator {
|
|||
where
|
||||
F: Fn(&'a TypedFunction, Option<&'a TypedFunction>) -> Option<&'a TypedFunction> + 'a,
|
||||
{
|
||||
match select(&self.fun, self.other_fun.as_ref()) {
|
||||
None => None,
|
||||
Some(fun) => {
|
||||
let mut fun = fun.clone();
|
||||
// match select(&self.fun, self.other_fun.as_ref()) {
|
||||
// None => None,
|
||||
// Some(fun) => {
|
||||
// let mut fun = fun.clone();
|
||||
|
||||
fun.arguments = self
|
||||
.params
|
||||
.clone()
|
||||
.into_iter()
|
||||
.chain(fun.arguments)
|
||||
.collect();
|
||||
// fun.arguments = self
|
||||
// .params
|
||||
// .clone()
|
||||
// .into_iter()
|
||||
// .chain(fun.arguments)
|
||||
// .collect();
|
||||
|
||||
Some((
|
||||
FunctionAccessKey {
|
||||
module_name: module_name.to_string(),
|
||||
function_name: fun.name.clone(),
|
||||
},
|
||||
fun,
|
||||
))
|
||||
}
|
||||
}
|
||||
// Some((
|
||||
// FunctionAccessKey {
|
||||
// module_name: module_name.to_string(),
|
||||
// function_name: fun.name.clone(),
|
||||
// },
|
||||
// fun,
|
||||
// ))
|
||||
// }
|
||||
// }
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -236,11 +236,11 @@ impl<'comments> Formatter<'comments> {
|
|||
|
||||
Definition::Validator(Validator {
|
||||
end_position,
|
||||
fun,
|
||||
other_fun,
|
||||
handlers,
|
||||
fallback,
|
||||
params,
|
||||
..
|
||||
}) => self.definition_validator(params, fun, other_fun, *end_position),
|
||||
}) => self.definition_validator(params, handlers, fallback, *end_position),
|
||||
|
||||
Definition::Test(Function {
|
||||
name,
|
||||
|
@ -582,8 +582,8 @@ impl<'comments> Formatter<'comments> {
|
|||
fn definition_validator<'a>(
|
||||
&mut self,
|
||||
params: &'a [UntypedArg],
|
||||
fun: &'a UntypedFunction,
|
||||
other_fun: &'a Option<UntypedFunction>,
|
||||
handlers: &'a [UntypedFunction],
|
||||
fallback: &'a UntypedFunction,
|
||||
end_position: usize,
|
||||
) -> Document<'a> {
|
||||
// validator(params)
|
||||
|
|
|
@ -1,66 +1,117 @@
|
|||
use chumsky::prelude::*;
|
||||
|
||||
use crate::{
|
||||
ast,
|
||||
parser::{error::ParseError, token::Token},
|
||||
ast::{self, ArgBy, ArgName},
|
||||
expr::UntypedExpr,
|
||||
parser::{annotation, error::ParseError, expr, token::Token},
|
||||
};
|
||||
|
||||
use super::function;
|
||||
use super::function::param;
|
||||
|
||||
pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
|
||||
just(Token::Validator)
|
||||
.ignore_then(
|
||||
function::param(true)
|
||||
.ignore_then(select! {Token::Name {name} => name})
|
||||
.then(
|
||||
param(true)
|
||||
.separated_by(just(Token::Comma))
|
||||
.allow_trailing()
|
||||
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
|
||||
.map_with_span(|arguments, span| (arguments, span))
|
||||
.or_not(),
|
||||
)
|
||||
// so far: validator my_validator(arg1: Whatever)
|
||||
.then(
|
||||
function()
|
||||
select! {Token::Name {name} => name}
|
||||
.then(args_and_body())
|
||||
.map(|(name, mut function)| {
|
||||
function.name = name;
|
||||
|
||||
function
|
||||
})
|
||||
.repeated()
|
||||
.at_least(1)
|
||||
.at_most(2)
|
||||
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace))
|
||||
.map(|defs| {
|
||||
defs.into_iter().map(|def| {
|
||||
let ast::UntypedDefinition::Fn(fun) = def else {
|
||||
unreachable!("It should be a fn definition");
|
||||
};
|
||||
|
||||
fun
|
||||
})
|
||||
}),
|
||||
.then(just(Token::Else).ignore_then(args_and_body()).or_not())
|
||||
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
|
||||
)
|
||||
.map_with_span(|(opt_extra_params, mut functions), span| {
|
||||
let (params, params_span) = opt_extra_params.unwrap_or((
|
||||
vec![],
|
||||
ast::Span {
|
||||
start: 0,
|
||||
end: span.start + "validator".len(),
|
||||
},
|
||||
));
|
||||
.map_with_span(
|
||||
|((name, opt_extra_params), (handlers, opt_catch_all)), span| {
|
||||
let (params, params_span) = opt_extra_params.unwrap_or((
|
||||
vec![],
|
||||
ast::Span {
|
||||
start: 0,
|
||||
end: span.start + "validator".len(),
|
||||
},
|
||||
));
|
||||
|
||||
let fun = functions
|
||||
.next()
|
||||
.expect("unwrapping safe because there's 'at_least(1)' function");
|
||||
ast::UntypedDefinition::Validator(ast::Validator {
|
||||
doc: None,
|
||||
name,
|
||||
handlers,
|
||||
location: ast::Span {
|
||||
start: span.start,
|
||||
// capture the span from the optional params
|
||||
end: params_span.end,
|
||||
},
|
||||
params,
|
||||
end_position: span.end - 1,
|
||||
fallback: opt_catch_all.unwrap_or(ast::Function {
|
||||
arguments: vec![ast::UntypedArg {
|
||||
by: ArgBy::ByName(ArgName::Discarded {
|
||||
name: "_ctx".to_string(),
|
||||
label: "_ctx".to_string(),
|
||||
location: ast::Span::empty(),
|
||||
}),
|
||||
location: ast::Span::empty(),
|
||||
annotation: None,
|
||||
doc: None,
|
||||
is_validator_param: false,
|
||||
}],
|
||||
body: UntypedExpr::fail(None, ast::Span::empty()),
|
||||
doc: None,
|
||||
location: ast::Span::empty(),
|
||||
end_position: span.end - 1,
|
||||
name: "fallback".to_string(),
|
||||
public: true,
|
||||
return_annotation: None,
|
||||
return_type: (),
|
||||
on_test_failure: ast::OnTestFailure::FailImmediately,
|
||||
}),
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
let other_fun = functions.next();
|
||||
|
||||
ast::UntypedDefinition::Validator(ast::Validator {
|
||||
pub fn args_and_body() -> impl Parser<Token, ast::UntypedFunction, Error = ParseError> {
|
||||
param(false)
|
||||
.separated_by(just(Token::Comma))
|
||||
.allow_trailing()
|
||||
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
|
||||
.map_with_span(|arguments, span| (arguments, span))
|
||||
.then(just(Token::RArrow).ignore_then(annotation()).or_not())
|
||||
.then(
|
||||
expr::sequence()
|
||||
.or_not()
|
||||
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
|
||||
)
|
||||
.map_with_span(
|
||||
|(((arguments, args_span), return_annotation), body), span| ast::Function {
|
||||
arguments,
|
||||
body: body.unwrap_or_else(|| UntypedExpr::todo(None, span)),
|
||||
doc: None,
|
||||
fun,
|
||||
other_fun,
|
||||
location: ast::Span {
|
||||
start: span.start,
|
||||
// capture the span from the optional params
|
||||
end: params_span.end,
|
||||
end: return_annotation
|
||||
.as_ref()
|
||||
.map(|l| l.location().end)
|
||||
.unwrap_or_else(|| args_span.end),
|
||||
},
|
||||
params,
|
||||
end_position: span.end - 1,
|
||||
})
|
||||
})
|
||||
name: "temp".to_string(),
|
||||
public: true,
|
||||
return_annotation,
|
||||
return_type: (),
|
||||
on_test_failure: ast::OnTestFailure::FailImmediately,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -71,8 +122,8 @@ mod tests {
|
|||
fn validator() {
|
||||
assert_definition!(
|
||||
r#"
|
||||
validator {
|
||||
fn foo(datum, rdmr, ctx) {
|
||||
validator hello {
|
||||
spend (datum, rdmr, ctx) {
|
||||
True
|
||||
}
|
||||
}
|
||||
|
@ -84,16 +135,37 @@ mod tests {
|
|||
fn double_validator() {
|
||||
assert_definition!(
|
||||
r#"
|
||||
validator {
|
||||
fn foo(datum, rdmr, ctx) {
|
||||
validator thing {
|
||||
spend (datum, rdmr, ctx) {
|
||||
True
|
||||
}
|
||||
|
||||
fn bar(rdmr, ctx) {
|
||||
mint (rdmr, ctx) {
|
||||
True
|
||||
}
|
||||
}
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fallback() {
|
||||
assert_definition!(
|
||||
r#"
|
||||
validator thing {
|
||||
spend (datum, rdmr, ctx) {
|
||||
True
|
||||
}
|
||||
|
||||
mint (rdmr, ctx) {
|
||||
True
|
||||
}
|
||||
|
||||
else (_) {
|
||||
fail
|
||||
}
|
||||
}
|
||||
"#
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue