Provide default annotation to validators (incl. fallback)
Without that, we may encounter weird error messages when writing validators without an explicit `else`. Since we automatically fill it with a `fail`; without annotation, it unifies to a generic parameter. The existing check that would look for the body being an error term is ill-advised as it doesn't work as soon as one adds tracing, or make the validator a parameterized validator. Plus, it may simply trigger the wrong behavior as one can now annotate a validator with _whatever_ and get pass the type-checker by plucking a `fail` keyword as body.
This commit is contained in:
parent
1198d7a5ae
commit
af9a785d65
|
@ -1,12 +1,10 @@
|
||||||
use chumsky::prelude::*;
|
use super::function::param;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{self, ArgBy, ArgName},
|
ast::{self, ArgBy, ArgName},
|
||||||
expr::UntypedExpr,
|
expr::UntypedExpr,
|
||||||
parser::{annotation, error::ParseError, expr, token::Token},
|
parser::{annotation, error::ParseError, expr, token::Token},
|
||||||
};
|
};
|
||||||
|
use chumsky::prelude::*;
|
||||||
use super::function::param;
|
|
||||||
|
|
||||||
pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
|
pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
|
||||||
just(Token::Validator)
|
just(Token::Validator)
|
||||||
|
@ -52,36 +50,38 @@ pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
|
let location = ast::Span {
|
||||||
|
start: span.start,
|
||||||
|
// capture the span from the optional params
|
||||||
|
end: params_span.end,
|
||||||
|
};
|
||||||
|
|
||||||
ast::UntypedDefinition::Validator(ast::Validator {
|
ast::UntypedDefinition::Validator(ast::Validator {
|
||||||
doc: None,
|
doc: None,
|
||||||
name,
|
name,
|
||||||
handlers,
|
handlers,
|
||||||
location: ast::Span {
|
location,
|
||||||
start: span.start,
|
|
||||||
// capture the span from the optional params
|
|
||||||
end: params_span.end,
|
|
||||||
},
|
|
||||||
params,
|
params,
|
||||||
end_position: span.end - 1,
|
end_position: span.end - 1,
|
||||||
fallback: opt_catch_all.unwrap_or(ast::Function {
|
fallback: opt_catch_all.unwrap_or(ast::Function {
|
||||||
arguments: vec![ast::UntypedArg {
|
arguments: vec![ast::UntypedArg {
|
||||||
by: ArgBy::ByName(ArgName::Discarded {
|
by: ArgBy::ByName(ArgName::Discarded {
|
||||||
name: "_ctx".to_string(),
|
name: "_".to_string(),
|
||||||
label: "_ctx".to_string(),
|
label: "_".to_string(),
|
||||||
location: ast::Span::empty(),
|
location,
|
||||||
}),
|
}),
|
||||||
location: ast::Span::empty(),
|
location,
|
||||||
annotation: None,
|
annotation: None,
|
||||||
doc: None,
|
doc: None,
|
||||||
is_validator_param: false,
|
is_validator_param: false,
|
||||||
}],
|
}],
|
||||||
body: UntypedExpr::fail(None, ast::Span::empty()),
|
body: UntypedExpr::fail(None, location),
|
||||||
doc: None,
|
doc: None,
|
||||||
location: ast::Span::empty(),
|
location,
|
||||||
end_position: span.end - 1,
|
end_position: location.end - 1,
|
||||||
name: "else".to_string(),
|
name: "else".to_string(),
|
||||||
public: true,
|
public: true,
|
||||||
return_annotation: None,
|
return_annotation: Some(ast::Annotation::boolean(location)),
|
||||||
return_type: (),
|
return_type: (),
|
||||||
on_test_failure: ast::OnTestFailure::FailImmediately,
|
on_test_failure: ast::OnTestFailure::FailImmediately,
|
||||||
}),
|
}),
|
||||||
|
@ -103,23 +103,28 @@ pub fn args_and_body() -> impl Parser<Token, ast::UntypedFunction, Error = Parse
|
||||||
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
|
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
|
||||||
)
|
)
|
||||||
.map_with_span(
|
.map_with_span(
|
||||||
|(((arguments, args_span), return_annotation), body), span| ast::Function {
|
|(((arguments, args_span), return_annotation), body), span| {
|
||||||
arguments,
|
let location = ast::Span {
|
||||||
body: body.unwrap_or_else(|| UntypedExpr::todo(None, span)),
|
|
||||||
doc: None,
|
|
||||||
location: ast::Span {
|
|
||||||
start: span.start,
|
start: span.start,
|
||||||
end: return_annotation
|
end: return_annotation
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|l| l.location().end)
|
.map(|l| l.location().end)
|
||||||
.unwrap_or_else(|| args_span.end),
|
.unwrap_or_else(|| args_span.end),
|
||||||
},
|
};
|
||||||
|
|
||||||
|
ast::Function {
|
||||||
|
arguments,
|
||||||
|
body: body.unwrap_or_else(|| UntypedExpr::todo(None, span)),
|
||||||
|
doc: None,
|
||||||
|
location,
|
||||||
end_position: span.end - 1,
|
end_position: span.end - 1,
|
||||||
name: "temp".to_string(),
|
name: "temp".to_string(),
|
||||||
public: true,
|
public: true,
|
||||||
return_annotation,
|
return_annotation: return_annotation
|
||||||
|
.or(Some(ast::Annotation::boolean(location))),
|
||||||
return_type: (),
|
return_type: (),
|
||||||
on_test_failure: ast::OnTestFailure::FailImmediately,
|
on_test_failure: ast::OnTestFailure::FailImmediately,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,8 +259,7 @@ fn infer_definition(
|
||||||
|
|
||||||
typed_fallback.name = old_name;
|
typed_fallback.name = old_name;
|
||||||
|
|
||||||
if !typed_fallback.body.is_error_term() && !typed_fallback.return_type.is_bool()
|
if !typed_fallback.return_type.is_bool() {
|
||||||
{
|
|
||||||
return Err(Error::ValidatorMustReturnBool {
|
return Err(Error::ValidatorMustReturnBool {
|
||||||
return_type: typed_fallback.return_type.clone(),
|
return_type: typed_fallback.return_type.clone(),
|
||||||
location: typed_fallback.location,
|
location: typed_fallback.location,
|
||||||
|
|
|
@ -100,9 +100,7 @@ pub fn eval_phase_two_raw(
|
||||||
.or_else(|_| MultiEraTx::decode_for_era(Era::Babbage, tx_bytes))
|
.or_else(|_| MultiEraTx::decode_for_era(Era::Babbage, tx_bytes))
|
||||||
.or_else(|_| MultiEraTx::decode_for_era(Era::Alonzo, tx_bytes))?;
|
.or_else(|_| MultiEraTx::decode_for_era(Era::Alonzo, tx_bytes))?;
|
||||||
|
|
||||||
let cost_mdls = cost_mdls_bytes
|
let cost_mdls = cost_mdls_bytes.map(CostMdls::decode_fragment).transpose()?;
|
||||||
.map(|x| CostMdls::decode_fragment(x))
|
|
||||||
.transpose()?;
|
|
||||||
|
|
||||||
let budget = ExBudget {
|
let budget = ExBudget {
|
||||||
cpu: initial_budget.0 as i64,
|
cpu: initial_budget.0 as i64,
|
||||||
|
|
Loading…
Reference in New Issue