Implement parser & formater for 'TraceIfFalse'
Interestingly enough, chumsky seems to fail when given a 'choice' with more than 25 elements. That's why this commit groups together some of the choices as another nested 'choice'.
This commit is contained in:
parent
60390fe4f0
commit
6a50bde666
|
@ -1280,6 +1280,16 @@ pub fn expr_parser(
|
|||
},
|
||||
});
|
||||
|
||||
let debug = chained.then(just(Token::Question).or_not()).map_with_span(
|
||||
|(value, token), location| match token {
|
||||
Some(_) => expr::UntypedExpr::TraceIfFalse {
|
||||
value: Box::new(value),
|
||||
location,
|
||||
},
|
||||
None => value,
|
||||
},
|
||||
);
|
||||
|
||||
// Negate
|
||||
let op = choice((
|
||||
just(Token::Bang).to(UnOp::Not),
|
||||
|
@ -1289,7 +1299,7 @@ pub fn expr_parser(
|
|||
let unary = op
|
||||
.map_with_span(|op, span| (op, span))
|
||||
.repeated()
|
||||
.then(chained)
|
||||
.then(debug)
|
||||
.foldr(|(un_op, span), value| expr::UntypedExpr::UnOp {
|
||||
op: un_op,
|
||||
location: span.union(value.location()),
|
||||
|
|
|
@ -35,10 +35,13 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = ParseError> {
|
|||
just('.').to(Token::Dot),
|
||||
just("!=").to(Token::NotEqual),
|
||||
just('!').to(Token::Bang),
|
||||
just("<=").to(Token::LessEqual),
|
||||
just('<').to(Token::Less),
|
||||
just(">=").to(Token::GreaterEqual),
|
||||
just('>').to(Token::Greater),
|
||||
just('?').to(Token::Question),
|
||||
choice((
|
||||
just("<=").to(Token::LessEqual),
|
||||
just('<').to(Token::Less),
|
||||
just(">=").to(Token::GreaterEqual),
|
||||
just('>').to(Token::Greater),
|
||||
)),
|
||||
just('+').to(Token::Plus),
|
||||
just("->").to(Token::RArrow),
|
||||
just('-').to(Token::Minus),
|
||||
|
|
|
@ -39,8 +39,9 @@ pub enum Token {
|
|||
// Other Punctuation
|
||||
Colon,
|
||||
Comma,
|
||||
Hash, // '#'
|
||||
Bang, // '!'
|
||||
Hash, // '#'
|
||||
Bang, // '!'
|
||||
Question, // '?'
|
||||
Equal,
|
||||
EqualEqual, // '=='
|
||||
NotEqual, // '!='
|
||||
|
@ -125,6 +126,7 @@ impl fmt::Display for Token {
|
|||
Token::Hash => "#",
|
||||
Token::Bang => "!",
|
||||
Token::Equal => "=",
|
||||
Token::Question => "?",
|
||||
Token::EqualEqual => "==",
|
||||
Token::NotEqual => "!=",
|
||||
Token::Vbar => "|",
|
||||
|
|
|
@ -255,3 +255,46 @@ fn trace_non_strings() {
|
|||
Err((_, Error::CouldNotUnify { .. }))
|
||||
))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trace_if_false_ok() {
|
||||
let source_code = r#"
|
||||
fn or(a: Bool, b: Bool) {
|
||||
(a || b)?
|
||||
}
|
||||
|
||||
test foo() {
|
||||
or(True, False)?
|
||||
}
|
||||
|
||||
test bar() {
|
||||
let must_be_signed = True
|
||||
must_be_signed?
|
||||
}
|
||||
"#;
|
||||
|
||||
assert!(check(parse(source_code)).is_ok())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trace_if_false_ko() {
|
||||
let source_code = r#"
|
||||
fn add(a: Int, b: Int) {
|
||||
(a + b)?
|
||||
}
|
||||
|
||||
test foo() {
|
||||
add(14, 42) == 12
|
||||
}
|
||||
|
||||
test bar() {
|
||||
let must_be_signed = #"FF00"
|
||||
must_be_signed? == #"FF00"
|
||||
}
|
||||
"#;
|
||||
|
||||
assert!(matches!(
|
||||
check(parse(source_code)),
|
||||
Err((_, Error::CouldNotUnify { .. }))
|
||||
))
|
||||
}
|
||||
|
|
|
@ -400,3 +400,18 @@ fn format_trace_todo_error() {
|
|||
|
||||
assert_fmt(src, src);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trace_if_false() {
|
||||
let src = indoc! {r#"
|
||||
fn foo() {
|
||||
my_expression?
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
(True && False)? || foo()?
|
||||
}
|
||||
"#};
|
||||
|
||||
assert_fmt(src, src);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue