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
|
// Negate
|
||||||
let op = choice((
|
let op = choice((
|
||||||
just(Token::Bang).to(UnOp::Not),
|
just(Token::Bang).to(UnOp::Not),
|
||||||
|
@ -1289,7 +1299,7 @@ pub fn expr_parser(
|
||||||
let unary = op
|
let unary = op
|
||||||
.map_with_span(|op, span| (op, span))
|
.map_with_span(|op, span| (op, span))
|
||||||
.repeated()
|
.repeated()
|
||||||
.then(chained)
|
.then(debug)
|
||||||
.foldr(|(un_op, span), value| expr::UntypedExpr::UnOp {
|
.foldr(|(un_op, span), value| expr::UntypedExpr::UnOp {
|
||||||
op: un_op,
|
op: un_op,
|
||||||
location: span.union(value.location()),
|
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::Dot),
|
||||||
just("!=").to(Token::NotEqual),
|
just("!=").to(Token::NotEqual),
|
||||||
just('!').to(Token::Bang),
|
just('!').to(Token::Bang),
|
||||||
just("<=").to(Token::LessEqual),
|
just('?').to(Token::Question),
|
||||||
just('<').to(Token::Less),
|
choice((
|
||||||
just(">=").to(Token::GreaterEqual),
|
just("<=").to(Token::LessEqual),
|
||||||
just('>').to(Token::Greater),
|
just('<').to(Token::Less),
|
||||||
|
just(">=").to(Token::GreaterEqual),
|
||||||
|
just('>').to(Token::Greater),
|
||||||
|
)),
|
||||||
just('+').to(Token::Plus),
|
just('+').to(Token::Plus),
|
||||||
just("->").to(Token::RArrow),
|
just("->").to(Token::RArrow),
|
||||||
just('-').to(Token::Minus),
|
just('-').to(Token::Minus),
|
||||||
|
|
|
@ -39,8 +39,9 @@ pub enum Token {
|
||||||
// Other Punctuation
|
// Other Punctuation
|
||||||
Colon,
|
Colon,
|
||||||
Comma,
|
Comma,
|
||||||
Hash, // '#'
|
Hash, // '#'
|
||||||
Bang, // '!'
|
Bang, // '!'
|
||||||
|
Question, // '?'
|
||||||
Equal,
|
Equal,
|
||||||
EqualEqual, // '=='
|
EqualEqual, // '=='
|
||||||
NotEqual, // '!='
|
NotEqual, // '!='
|
||||||
|
@ -125,6 +126,7 @@ impl fmt::Display for Token {
|
||||||
Token::Hash => "#",
|
Token::Hash => "#",
|
||||||
Token::Bang => "!",
|
Token::Bang => "!",
|
||||||
Token::Equal => "=",
|
Token::Equal => "=",
|
||||||
|
Token::Question => "?",
|
||||||
Token::EqualEqual => "==",
|
Token::EqualEqual => "==",
|
||||||
Token::NotEqual => "!=",
|
Token::NotEqual => "!=",
|
||||||
Token::Vbar => "|",
|
Token::Vbar => "|",
|
||||||
|
|
|
@ -255,3 +255,46 @@ fn trace_non_strings() {
|
||||||
Err((_, Error::CouldNotUnify { .. }))
|
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);
|
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