feat(tests): implement a way to express that tests can fail
This commit is contained in:
parent
65bf4a85e4
commit
a124a16a61
|
@ -118,6 +118,7 @@ fn str_to_keyword(word: &str) -> Option<Token> {
|
||||||
"test" => Some(Token::Test),
|
"test" => Some(Token::Test),
|
||||||
"error" => Some(Token::ErrorTerm),
|
"error" => Some(Token::ErrorTerm),
|
||||||
"validator" => Some(Token::Validator),
|
"validator" => Some(Token::Validator),
|
||||||
|
"fail" => Some(Token::Fail),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,6 +137,7 @@ pub struct Function<T, Expr> {
|
||||||
pub return_annotation: Option<Annotation>,
|
pub return_annotation: Option<Annotation>,
|
||||||
pub return_type: T,
|
pub return_type: T,
|
||||||
pub end_position: usize,
|
pub end_position: usize,
|
||||||
|
pub can_error: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type TypedTypeAlias = TypeAlias<Arc<Type>>;
|
pub type TypedTypeAlias = TypeAlias<Arc<Type>>;
|
||||||
|
|
|
@ -681,6 +681,7 @@ pub fn prelude_functions(id_gen: &IdGenerator) -> IndexMap<FunctionAccessKey, Ty
|
||||||
annotation: None,
|
annotation: None,
|
||||||
tipo: bool(),
|
tipo: bool(),
|
||||||
}],
|
}],
|
||||||
|
can_error: false,
|
||||||
doc: None,
|
doc: None,
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
name: "not".to_string(),
|
name: "not".to_string(),
|
||||||
|
@ -731,6 +732,7 @@ pub fn prelude_functions(id_gen: &IdGenerator) -> IndexMap<FunctionAccessKey, Ty
|
||||||
annotation: None,
|
annotation: None,
|
||||||
tipo: a_var.clone(),
|
tipo: a_var.clone(),
|
||||||
}],
|
}],
|
||||||
|
can_error: false,
|
||||||
body: TypedExpr::Var {
|
body: TypedExpr::Var {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
constructor: ValueConstructor {
|
constructor: ValueConstructor {
|
||||||
|
@ -766,6 +768,7 @@ pub fn prelude_functions(id_gen: &IdGenerator) -> IndexMap<FunctionAccessKey, Ty
|
||||||
variant_name: "".to_string(),
|
variant_name: "".to_string(),
|
||||||
},
|
},
|
||||||
Function {
|
Function {
|
||||||
|
can_error: false,
|
||||||
arguments: vec![
|
arguments: vec![
|
||||||
Arg {
|
Arg {
|
||||||
arg_name: ArgName::Named {
|
arg_name: ArgName::Named {
|
||||||
|
@ -828,6 +831,7 @@ pub fn prelude_functions(id_gen: &IdGenerator) -> IndexMap<FunctionAccessKey, Ty
|
||||||
variant_name: "".to_string(),
|
variant_name: "".to_string(),
|
||||||
},
|
},
|
||||||
Function {
|
Function {
|
||||||
|
can_error: false,
|
||||||
arguments: vec![Arg {
|
arguments: vec![Arg {
|
||||||
arg_name: ArgName::Named {
|
arg_name: ArgName::Named {
|
||||||
name: "f".to_string(),
|
name: "f".to_string(),
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
expr,
|
expr,
|
||||||
};
|
};
|
||||||
use chumsky::prelude::*;
|
use chumsky::{chain::Chain, prelude::*};
|
||||||
use error::ParseError;
|
use error::ParseError;
|
||||||
use extra::ModuleExtra;
|
use extra::ModuleExtra;
|
||||||
use token::Token;
|
use token::Token;
|
||||||
|
@ -73,7 +73,8 @@ pub fn module(
|
||||||
result
|
result
|
||||||
});
|
});
|
||||||
|
|
||||||
let definitions = module_parser().parse(chumsky::Stream::from_iter(span(len), tokens))?;
|
let definitions =
|
||||||
|
module_parser().parse(chumsky::Stream::from_iter(span(tokens.len()), tokens))?;
|
||||||
|
|
||||||
let module = ast::UntypedModule {
|
let module = ast::UntypedModule {
|
||||||
kind,
|
kind,
|
||||||
|
@ -329,6 +330,7 @@ pub fn fn_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseEr
|
||||||
public: opt_pub.is_some(),
|
public: opt_pub.is_some(),
|
||||||
return_annotation,
|
return_annotation,
|
||||||
return_type: (),
|
return_type: (),
|
||||||
|
can_error: true,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -336,7 +338,8 @@ pub fn fn_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseEr
|
||||||
|
|
||||||
pub fn test_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
|
pub fn test_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
|
||||||
just(Token::Test)
|
just(Token::Test)
|
||||||
.ignore_then(select! {Token::Name {name} => name})
|
.ignore_then(just(Token::Fail).ignored().or_not())
|
||||||
|
.then(select! {Token::Name {name} => name})
|
||||||
.then_ignore(just(Token::LeftParen))
|
.then_ignore(just(Token::LeftParen))
|
||||||
.then_ignore(just(Token::RightParen))
|
.then_ignore(just(Token::RightParen))
|
||||||
.map_with_span(|name, span| (name, span))
|
.map_with_span(|name, span| (name, span))
|
||||||
|
@ -345,7 +348,7 @@ pub fn test_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = Parse
|
||||||
.or_not()
|
.or_not()
|
||||||
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
|
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
|
||||||
)
|
)
|
||||||
.map_with_span(|((name, span_end), body), span| {
|
.map_with_span(|(((fail, name), span_end), body), span| {
|
||||||
ast::UntypedDefinition::Test(ast::Function {
|
ast::UntypedDefinition::Test(ast::Function {
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: body.unwrap_or_else(|| expr::UntypedExpr::todo(span, None)),
|
body: body.unwrap_or_else(|| expr::UntypedExpr::todo(span, None)),
|
||||||
|
@ -356,6 +359,7 @@ pub fn test_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = Parse
|
||||||
public: false,
|
public: false,
|
||||||
return_annotation: None,
|
return_annotation: None,
|
||||||
return_type: (),
|
return_type: (),
|
||||||
|
can_error: fail.is_some(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,7 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = ParseError> {
|
||||||
"todo" => Token::Todo,
|
"todo" => Token::Todo,
|
||||||
"type" => Token::Type,
|
"type" => Token::Type,
|
||||||
"when" => Token::When,
|
"when" => Token::When,
|
||||||
|
"fail" => Token::Fail,
|
||||||
"validator" => Token::Validator,
|
"validator" => Token::Validator,
|
||||||
_ => {
|
_ => {
|
||||||
if s.chars().next().map_or(false, |c| c.is_uppercase()) {
|
if s.chars().next().map_or(false, |c| c.is_uppercase()) {
|
||||||
|
|
|
@ -80,6 +80,7 @@ pub enum Token {
|
||||||
When,
|
When,
|
||||||
Trace,
|
Trace,
|
||||||
Validator,
|
Validator,
|
||||||
|
Fail,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Token {
|
impl fmt::Display for Token {
|
||||||
|
@ -164,6 +165,7 @@ impl fmt::Display for Token {
|
||||||
Token::Test => "test",
|
Token::Test => "test",
|
||||||
Token::ErrorTerm => "error",
|
Token::ErrorTerm => "error",
|
||||||
Token::Validator => "validator",
|
Token::Validator => "validator",
|
||||||
|
Token::Fail => "fail",
|
||||||
};
|
};
|
||||||
write!(f, "\"{s}\"")
|
write!(f, "\"{s}\"")
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,60 @@ fn windows_newline() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fail() {
|
||||||
|
let code = indoc! {r#"
|
||||||
|
test fail invalid_inputs() {
|
||||||
|
expect True = False
|
||||||
|
|
||||||
|
False
|
||||||
|
}
|
||||||
|
"#};
|
||||||
|
|
||||||
|
assert_definitions(
|
||||||
|
code,
|
||||||
|
vec![ast::UntypedDefinition::Test(ast::Function {
|
||||||
|
arguments: vec![],
|
||||||
|
body: expr::UntypedExpr::Sequence {
|
||||||
|
location: Span::new((), 31..59),
|
||||||
|
expressions: vec![
|
||||||
|
expr::UntypedExpr::Assignment {
|
||||||
|
location: Span::new((), 31..50),
|
||||||
|
value: Box::new(expr::UntypedExpr::Var {
|
||||||
|
location: Span::new((), 45..50),
|
||||||
|
name: "False".to_string(),
|
||||||
|
}),
|
||||||
|
pattern: ast::UntypedPattern::Constructor {
|
||||||
|
is_record: false,
|
||||||
|
location: Span::new((), 38..42),
|
||||||
|
name: "True".to_string(),
|
||||||
|
arguments: vec![],
|
||||||
|
module: None,
|
||||||
|
constructor: (),
|
||||||
|
with_spread: false,
|
||||||
|
tipo: (),
|
||||||
|
},
|
||||||
|
kind: ast::AssignmentKind::Expect,
|
||||||
|
annotation: None,
|
||||||
|
},
|
||||||
|
expr::UntypedExpr::Var {
|
||||||
|
location: Span::new((), 54..59),
|
||||||
|
name: "False".to_string(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
doc: None,
|
||||||
|
location: Span::new((), 0..26),
|
||||||
|
name: "invalid_inputs".to_string(),
|
||||||
|
public: false,
|
||||||
|
return_annotation: None,
|
||||||
|
return_type: (),
|
||||||
|
end_position: 60,
|
||||||
|
can_error: true,
|
||||||
|
})],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn validator() {
|
fn validator() {
|
||||||
let code = indoc! {r#"
|
let code = indoc! {r#"
|
||||||
|
@ -54,6 +108,7 @@ fn validator() {
|
||||||
doc: None,
|
doc: None,
|
||||||
end_position: 54,
|
end_position: 54,
|
||||||
fun: Function {
|
fun: Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![
|
arguments: vec![
|
||||||
ast::Arg {
|
ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
|
@ -128,6 +183,7 @@ fn double_validator() {
|
||||||
doc: None,
|
doc: None,
|
||||||
end_position: 90,
|
end_position: 90,
|
||||||
fun: Function {
|
fun: Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![
|
arguments: vec![
|
||||||
ast::Arg {
|
ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
|
@ -176,6 +232,7 @@ fn double_validator() {
|
||||||
end_position: 52,
|
end_position: 52,
|
||||||
},
|
},
|
||||||
other_fun: Some(Function {
|
other_fun: Some(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![
|
arguments: vec![
|
||||||
ast::Arg {
|
ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
|
@ -487,6 +544,7 @@ fn empty_function() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Trace {
|
body: expr::UntypedExpr::Trace {
|
||||||
kind: ast::TraceKind::Todo,
|
kind: ast::TraceKind::Todo,
|
||||||
|
@ -522,6 +580,7 @@ fn expect() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Sequence {
|
body: expr::UntypedExpr::Sequence {
|
||||||
location: Span::new((), 19..69),
|
location: Span::new((), 19..69),
|
||||||
|
@ -592,6 +651,7 @@ fn plus_binop() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![ast::Arg {
|
arguments: vec![ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
label: "a".to_string(),
|
label: "a".to_string(),
|
||||||
|
@ -644,6 +704,7 @@ fn pipeline() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![ast::Arg {
|
arguments: vec![ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
name: "a".to_string(),
|
name: "a".to_string(),
|
||||||
|
@ -715,6 +776,7 @@ fn if_expression() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::If {
|
body: expr::UntypedExpr::If {
|
||||||
location: Span::new((), 13..106),
|
location: Span::new((), 13..106),
|
||||||
|
@ -813,6 +875,7 @@ fn let_bindings() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![ast::Arg {
|
arguments: vec![ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
label: "a".to_string(),
|
label: "a".to_string(),
|
||||||
|
@ -940,6 +1003,7 @@ fn block() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![ast::Arg {
|
arguments: vec![ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
label: "a".to_string(),
|
label: "a".to_string(),
|
||||||
|
@ -1034,6 +1098,7 @@ fn when() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![ast::Arg {
|
arguments: vec![ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
label: "a".to_string(),
|
label: "a".to_string(),
|
||||||
|
@ -1159,6 +1224,7 @@ fn anonymous_function() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Sequence {
|
body: expr::UntypedExpr::Sequence {
|
||||||
location: Span::new((), 25..83),
|
location: Span::new((), 25..83),
|
||||||
|
@ -1252,6 +1318,7 @@ fn field_access() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![ast::Arg {
|
arguments: vec![ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
label: "user".to_string(),
|
label: "user".to_string(),
|
||||||
|
@ -1302,6 +1369,7 @@ fn call() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Sequence {
|
body: expr::UntypedExpr::Sequence {
|
||||||
location: Span::new((), 15..108),
|
location: Span::new((), 15..108),
|
||||||
|
@ -1461,6 +1529,7 @@ fn record_update() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![
|
arguments: vec![
|
||||||
ast::Arg {
|
ast::Arg {
|
||||||
arg_name: ast::ArgName::Named {
|
arg_name: ast::ArgName::Named {
|
||||||
|
@ -1555,6 +1624,7 @@ fn record_create_labeled() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(ast::Function {
|
vec![ast::UntypedDefinition::Fn(ast::Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Call {
|
body: expr::UntypedExpr::Call {
|
||||||
arguments: vec![
|
arguments: vec![
|
||||||
|
@ -1612,6 +1682,7 @@ fn record_create_labeled_with_field_access() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(ast::Function {
|
vec![ast::UntypedDefinition::Fn(ast::Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Call {
|
body: expr::UntypedExpr::Call {
|
||||||
arguments: vec![
|
arguments: vec![
|
||||||
|
@ -1673,6 +1744,7 @@ fn record_create_unlabeled() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(ast::Function {
|
vec![ast::UntypedDefinition::Fn(ast::Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Call {
|
body: expr::UntypedExpr::Call {
|
||||||
arguments: vec![
|
arguments: vec![
|
||||||
|
@ -1726,6 +1798,7 @@ fn parse_tuple() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Sequence {
|
body: expr::UntypedExpr::Sequence {
|
||||||
location: Span::new((), 13..85),
|
location: Span::new((), 13..85),
|
||||||
|
@ -1829,6 +1902,7 @@ fn parse_tuple2() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Sequence {
|
body: expr::UntypedExpr::Sequence {
|
||||||
location: Span::new((), 13..38),
|
location: Span::new((), 13..38),
|
||||||
|
@ -1957,6 +2031,7 @@ fn base16_bytearray_literals() {
|
||||||
tipo: (),
|
tipo: (),
|
||||||
}),
|
}),
|
||||||
ast::UntypedDefinition::Fn(Function {
|
ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::BinOp {
|
body: expr::UntypedExpr::BinOp {
|
||||||
location: Span::new((), 55..80),
|
location: Span::new((), 55..80),
|
||||||
|
@ -1992,6 +2067,7 @@ fn function_def() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
doc: None,
|
doc: None,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Trace {
|
body: expr::UntypedExpr::Trace {
|
||||||
|
@ -2026,6 +2102,7 @@ fn function_invoke() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
doc: None,
|
doc: None,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Assignment {
|
body: expr::UntypedExpr::Assignment {
|
||||||
|
@ -2089,6 +2166,7 @@ fn function_ambiguous_sequence() {
|
||||||
code,
|
code,
|
||||||
vec![
|
vec![
|
||||||
ast::UntypedDefinition::Fn(Function {
|
ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Sequence {
|
body: expr::UntypedExpr::Sequence {
|
||||||
location: Span::new((), 15..32),
|
location: Span::new((), 15..32),
|
||||||
|
@ -2121,6 +2199,7 @@ fn function_ambiguous_sequence() {
|
||||||
end_position: 34,
|
end_position: 34,
|
||||||
}),
|
}),
|
||||||
ast::UntypedDefinition::Fn(Function {
|
ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Sequence {
|
body: expr::UntypedExpr::Sequence {
|
||||||
location: Span::new((), 52..69),
|
location: Span::new((), 52..69),
|
||||||
|
@ -2153,6 +2232,7 @@ fn function_ambiguous_sequence() {
|
||||||
end_position: 71,
|
end_position: 71,
|
||||||
}),
|
}),
|
||||||
ast::UntypedDefinition::Fn(Function {
|
ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Assignment {
|
body: expr::UntypedExpr::Assignment {
|
||||||
location: Span::new((), 89..103),
|
location: Span::new((), 89..103),
|
||||||
|
@ -2184,6 +2264,7 @@ fn function_ambiguous_sequence() {
|
||||||
end_position: 104,
|
end_position: 104,
|
||||||
}),
|
}),
|
||||||
ast::UntypedDefinition::Fn(Function {
|
ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Sequence {
|
body: expr::UntypedExpr::Sequence {
|
||||||
location: Span::new((), 122..153),
|
location: Span::new((), 122..153),
|
||||||
|
@ -2296,6 +2377,7 @@ fn tuple_pattern() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::UntypedDefinition::Fn(Function {
|
vec![ast::UntypedDefinition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::When {
|
body: expr::UntypedExpr::When {
|
||||||
location: Span::new((), 13..49),
|
location: Span::new((), 13..49),
|
||||||
|
@ -2349,6 +2431,7 @@ fn subtraction_vs_negate() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::Definition::Fn(Function {
|
vec![ast::Definition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Sequence {
|
body: expr::UntypedExpr::Sequence {
|
||||||
location: Span::new((), 14..61),
|
location: Span::new((), 14..61),
|
||||||
|
@ -2465,6 +2548,7 @@ fn clause_guards() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::Definition::Fn(Function {
|
vec![ast::Definition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::When {
|
body: expr::UntypedExpr::When {
|
||||||
location: Span::new((), 13..250),
|
location: Span::new((), 13..250),
|
||||||
|
@ -2719,6 +2803,7 @@ fn scope_logical_expression() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::Definition::Fn(Function {
|
vec![ast::Definition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Sequence {
|
body: expr::UntypedExpr::Sequence {
|
||||||
location: Span::new((), 13..61),
|
location: Span::new((), 13..61),
|
||||||
|
@ -2817,6 +2902,7 @@ fn trace_expressions() {
|
||||||
assert_definitions(
|
assert_definitions(
|
||||||
code,
|
code,
|
||||||
vec![ast::Definition::Fn(Function {
|
vec![ast::Definition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Sequence {
|
body: expr::UntypedExpr::Sequence {
|
||||||
location: Span::new((), 13..131),
|
location: Span::new((), 13..131),
|
||||||
|
@ -2942,6 +3028,7 @@ fn parse_keyword_error() {
|
||||||
code,
|
code,
|
||||||
vec![
|
vec![
|
||||||
ast::Definition::Fn(Function {
|
ast::Definition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Trace {
|
body: expr::UntypedExpr::Trace {
|
||||||
kind: ast::TraceKind::Error,
|
kind: ast::TraceKind::Error,
|
||||||
|
@ -2963,6 +3050,7 @@ fn parse_keyword_error() {
|
||||||
end_position: 38,
|
end_position: 38,
|
||||||
}),
|
}),
|
||||||
ast::Definition::Fn(Function {
|
ast::Definition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::When {
|
body: expr::UntypedExpr::When {
|
||||||
location: Span::new((), 54..110),
|
location: Span::new((), 54..110),
|
||||||
|
@ -3041,6 +3129,7 @@ fn parse_keyword_todo() {
|
||||||
code,
|
code,
|
||||||
vec![
|
vec![
|
||||||
ast::Definition::Fn(Function {
|
ast::Definition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::Trace {
|
body: expr::UntypedExpr::Trace {
|
||||||
kind: ast::TraceKind::Todo,
|
kind: ast::TraceKind::Todo,
|
||||||
|
@ -3062,6 +3151,7 @@ fn parse_keyword_todo() {
|
||||||
end_position: 37,
|
end_position: 37,
|
||||||
}),
|
}),
|
||||||
ast::Definition::Fn(Function {
|
ast::Definition::Fn(Function {
|
||||||
|
can_error: true,
|
||||||
arguments: vec![],
|
arguments: vec![],
|
||||||
body: expr::UntypedExpr::When {
|
body: expr::UntypedExpr::When {
|
||||||
location: Span::new((), 53..121),
|
location: Span::new((), 53..121),
|
||||||
|
|
|
@ -197,6 +197,7 @@ impl<'a> Environment<'a> {
|
||||||
return_annotation,
|
return_annotation,
|
||||||
return_type,
|
return_type,
|
||||||
end_position,
|
end_position,
|
||||||
|
can_error,
|
||||||
}) => {
|
}) => {
|
||||||
// Lookup the inferred function information
|
// Lookup the inferred function information
|
||||||
let function = self
|
let function = self
|
||||||
|
@ -241,6 +242,7 @@ impl<'a> Environment<'a> {
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
end_position,
|
end_position,
|
||||||
|
can_error,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -160,6 +160,7 @@ fn infer_definition(
|
||||||
body,
|
body,
|
||||||
return_annotation,
|
return_annotation,
|
||||||
end_position,
|
end_position,
|
||||||
|
can_error,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
if public && kind.is_validator() {
|
if public && kind.is_validator() {
|
||||||
|
@ -246,6 +247,7 @@ fn infer_definition(
|
||||||
.return_type()
|
.return_type()
|
||||||
.expect("Could not find return type for fn"),
|
.expect("Could not find return type for fn"),
|
||||||
body,
|
body,
|
||||||
|
can_error,
|
||||||
end_position,
|
end_position,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -670,7 +670,12 @@ where
|
||||||
let mut programs = Vec::new();
|
let mut programs = Vec::new();
|
||||||
|
|
||||||
for (input_path, module_name, func_def) in scripts {
|
for (input_path, module_name, func_def) in scripts {
|
||||||
let Function { name, body, .. } = func_def;
|
let Function {
|
||||||
|
name,
|
||||||
|
body,
|
||||||
|
can_error,
|
||||||
|
..
|
||||||
|
} = func_def;
|
||||||
|
|
||||||
if verbose {
|
if verbose {
|
||||||
self.event_listener.handle_event(Event::GeneratingUPLCFor {
|
self.event_listener.handle_event(Event::GeneratingUPLCFor {
|
||||||
|
@ -711,6 +716,7 @@ where
|
||||||
input_path,
|
input_path,
|
||||||
module_name,
|
module_name,
|
||||||
name.to_string(),
|
name.to_string(),
|
||||||
|
*can_error,
|
||||||
program.try_into().unwrap(),
|
program.try_into().unwrap(),
|
||||||
evaluation_hint,
|
evaluation_hint,
|
||||||
);
|
);
|
||||||
|
@ -737,7 +743,7 @@ where
|
||||||
let mut eval_result = script.program.clone().eval(initial_budget);
|
let mut eval_result = script.program.clone().eval(initial_budget);
|
||||||
|
|
||||||
EvalInfo {
|
EvalInfo {
|
||||||
success: !eval_result.failed(),
|
success: !eval_result.failed(script.can_error),
|
||||||
script,
|
script,
|
||||||
spent_budget: eval_result.cost(),
|
spent_budget: eval_result.cost(),
|
||||||
logs: eval_result.logs(),
|
logs: eval_result.logs(),
|
||||||
|
|
|
@ -8,6 +8,7 @@ pub struct Script {
|
||||||
pub input_path: PathBuf,
|
pub input_path: PathBuf,
|
||||||
pub module: String,
|
pub module: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub can_error: bool,
|
||||||
pub program: Program<NamedDeBruijn>,
|
pub program: Program<NamedDeBruijn>,
|
||||||
pub evaluation_hint: Option<EvalHint>,
|
pub evaluation_hint: Option<EvalHint>,
|
||||||
}
|
}
|
||||||
|
@ -19,6 +20,7 @@ impl Script {
|
||||||
input_path: PathBuf,
|
input_path: PathBuf,
|
||||||
module: String,
|
module: String,
|
||||||
name: String,
|
name: String,
|
||||||
|
can_error: bool,
|
||||||
program: Program<NamedDeBruijn>,
|
program: Program<NamedDeBruijn>,
|
||||||
evaluation_hint: Option<EvalHint>,
|
evaluation_hint: Option<EvalHint>,
|
||||||
) -> Script {
|
) -> Script {
|
||||||
|
@ -27,6 +29,7 @@ impl Script {
|
||||||
module,
|
module,
|
||||||
name,
|
name,
|
||||||
program,
|
program,
|
||||||
|
can_error,
|
||||||
evaluation_hint,
|
evaluation_hint,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ fn assert_uplc(source_code: &str, expected: Term<Name>, should_fail: bool) {
|
||||||
let mut eval = debruijn_program.eval(ExBudget::default());
|
let mut eval = debruijn_program.eval(ExBudget::default());
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
eval.failed(),
|
eval.failed(false),
|
||||||
should_fail,
|
should_fail,
|
||||||
"logs - {}\n",
|
"logs - {}\n",
|
||||||
format!("{:#?}", eval.logs())
|
format!("{:#?}", eval.logs())
|
||||||
|
|
|
@ -32,11 +32,15 @@ impl EvalResult {
|
||||||
std::mem::take(&mut self.logs)
|
std::mem::take(&mut self.logs)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn failed(&self) -> bool {
|
pub fn failed(&self, can_error: bool) -> bool {
|
||||||
|
if can_error {
|
||||||
|
!matches!(self.result, Err(_))
|
||||||
|
} else {
|
||||||
matches!(self.result, Err(_))
|
matches!(self.result, Err(_))
|
||||||
|| matches!(self.result, Ok(Term::Error))
|
|| matches!(self.result, Ok(Term::Error))
|
||||||
|| matches!(self.result, Ok(Term::Constant(ref con)) if matches!(con.as_ref(), Constant::Bool(false)))
|
|| matches!(self.result, Ok(Term::Constant(ref con)) if matches!(con.as_ref(), Constant::Bool(false)))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn result(self) -> Result<Term<NamedDeBruijn>, Error> {
|
pub fn result(self) -> Result<Term<NamedDeBruijn>, Error> {
|
||||||
self.result
|
self.result
|
||||||
|
|
Loading…
Reference in New Issue