fix: spans for backpassing args
closes #882 Co-authored-by: Kasey White <kwhitemsg@gmail.com>
This commit is contained in:
parent
8495f98c1d
commit
898ef74457
|
@ -1176,6 +1176,21 @@ impl<A, B> Pattern<A, B> {
|
|||
}
|
||||
}
|
||||
|
||||
impl UntypedPattern {
|
||||
pub fn true_(location: Span) -> UntypedPattern {
|
||||
UntypedPattern::Constructor {
|
||||
location,
|
||||
name: "True".to_string(),
|
||||
arguments: vec![],
|
||||
constructor: (),
|
||||
with_spread: false,
|
||||
tipo: (),
|
||||
module: None,
|
||||
is_record: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TypedPattern {
|
||||
pub fn find_node<'a>(&'a self, byte_index: usize, value: &Rc<Type>) -> Option<Located<'a>> {
|
||||
if !self.location().contains(byte_index) {
|
||||
|
@ -1440,13 +1455,19 @@ impl Default for Bls12_381Point {
|
|||
pub struct AssignmentPattern {
|
||||
pub pattern: UntypedPattern,
|
||||
pub annotation: Option<Annotation>,
|
||||
pub location: Span,
|
||||
}
|
||||
|
||||
impl AssignmentPattern {
|
||||
pub fn new(pattern: UntypedPattern, annotation: Option<Annotation>) -> AssignmentPattern {
|
||||
pub fn new(
|
||||
pattern: UntypedPattern,
|
||||
annotation: Option<Annotation>,
|
||||
location: Span,
|
||||
) -> AssignmentPattern {
|
||||
Self {
|
||||
pattern,
|
||||
annotation,
|
||||
location,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1300,7 +1300,7 @@ impl UntypedExpr {
|
|||
}
|
||||
|
||||
pub fn lambda(
|
||||
names: Vec<(String, Option<Annotation>)>,
|
||||
names: Vec<(String, Span, Option<Annotation>)>,
|
||||
expressions: Vec<UntypedExpr>,
|
||||
location: Span,
|
||||
) -> Self {
|
||||
|
@ -1309,7 +1309,7 @@ impl UntypedExpr {
|
|||
fn_style: FnStyle::Plain,
|
||||
arguments: names
|
||||
.into_iter()
|
||||
.map(|(name, annotation)| Arg {
|
||||
.map(|(name, location, annotation)| Arg {
|
||||
location,
|
||||
doc: None,
|
||||
annotation,
|
||||
|
|
|
@ -697,6 +697,7 @@ impl<'comments> Formatter<'comments> {
|
|||
name, module: None, ..
|
||||
},
|
||||
annotation,
|
||||
location: _,
|
||||
} if name == "True"
|
||||
&& annotation.is_none()
|
||||
&& kind.is_expect()
|
||||
|
@ -709,6 +710,7 @@ impl<'comments> Formatter<'comments> {
|
|||
|AssignmentPattern {
|
||||
pattern,
|
||||
annotation,
|
||||
location: _,
|
||||
}| {
|
||||
self.pop_empty_lines(pattern.location().end);
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ Test(
|
|||
tipo: (),
|
||||
},
|
||||
annotation: None,
|
||||
location: 38..42,
|
||||
},
|
||||
],
|
||||
kind: Expect {
|
||||
|
|
|
@ -32,6 +32,7 @@ Fn(
|
|||
name: "x",
|
||||
},
|
||||
annotation: None,
|
||||
location: 17..18,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
ast,
|
||||
ast::{self, Span},
|
||||
expr::UntypedExpr,
|
||||
parser::{annotation, error::ParseError, pattern, token::Token},
|
||||
};
|
||||
|
@ -9,17 +9,7 @@ pub fn let_(
|
|||
r: Recursive<'_, Token, UntypedExpr, ParseError>,
|
||||
) -> impl Parser<Token, UntypedExpr, Error = ParseError> + '_ {
|
||||
just(Token::Let)
|
||||
.ignore_then(
|
||||
pattern()
|
||||
.then(just(Token::Colon).ignore_then(annotation()).or_not())
|
||||
.map(|(pattern, annotation)| ast::AssignmentPattern {
|
||||
pattern,
|
||||
annotation,
|
||||
})
|
||||
.separated_by(just(Token::Comma))
|
||||
.allow_trailing()
|
||||
.at_least(1),
|
||||
)
|
||||
.ignore_then(assignment_patterns())
|
||||
.then(choice((just(Token::Equal), just(Token::LArrow))))
|
||||
.then(r.clone())
|
||||
.validate(move |((patterns, kind), value), span, emit| {
|
||||
|
@ -42,20 +32,25 @@ pub fn let_(
|
|||
})
|
||||
}
|
||||
|
||||
fn assignment_patterns() -> impl Parser<Token, Vec<ast::AssignmentPattern>, Error = ParseError> {
|
||||
pattern()
|
||||
.then(just(Token::Colon).ignore_then(annotation()).or_not())
|
||||
.map_with_span(|(pattern, annotation), span| ast::AssignmentPattern {
|
||||
pattern,
|
||||
annotation,
|
||||
location: span,
|
||||
})
|
||||
.separated_by(just(Token::Comma))
|
||||
.allow_trailing()
|
||||
.at_least(1)
|
||||
}
|
||||
|
||||
pub fn expect(
|
||||
r: Recursive<'_, Token, UntypedExpr, ParseError>,
|
||||
) -> impl Parser<Token, UntypedExpr, Error = ParseError> + '_ {
|
||||
just(Token::Expect)
|
||||
.ignore_then(
|
||||
pattern()
|
||||
.then(just(Token::Colon).ignore_then(annotation()).or_not())
|
||||
.map(|(pattern, annotation)| ast::AssignmentPattern {
|
||||
pattern,
|
||||
annotation,
|
||||
})
|
||||
.separated_by(just(Token::Comma))
|
||||
.allow_trailing()
|
||||
.at_least(1)
|
||||
assignment_patterns()
|
||||
.then(choice((just(Token::Equal), just(Token::LArrow))))
|
||||
.or_not(),
|
||||
)
|
||||
|
@ -66,22 +61,13 @@ pub fn expect(
|
|||
}
|
||||
|
||||
let (patterns, kind) = opt_pattern.unwrap_or_else(|| {
|
||||
(
|
||||
vec![ast::AssignmentPattern {
|
||||
pattern: ast::UntypedPattern::Constructor {
|
||||
is_record: false,
|
||||
location: span,
|
||||
name: "True".to_string(),
|
||||
arguments: vec![],
|
||||
module: None,
|
||||
constructor: (),
|
||||
with_spread: false,
|
||||
tipo: (),
|
||||
},
|
||||
annotation: None,
|
||||
}],
|
||||
Token::Equal,
|
||||
)
|
||||
let filler_true = ast::AssignmentPattern::new(
|
||||
ast::UntypedPattern::true_(span),
|
||||
None,
|
||||
Span::empty(),
|
||||
);
|
||||
|
||||
(vec![filler_true], Token::Equal)
|
||||
});
|
||||
|
||||
let patterns = patterns
|
||||
|
|
|
@ -23,6 +23,7 @@ Assignment {
|
|||
name: "x",
|
||||
},
|
||||
annotation: None,
|
||||
location: 16..17,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
@ -53,6 +54,7 @@ Assignment {
|
|||
name: "b",
|
||||
},
|
||||
annotation: None,
|
||||
location: 4..5,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
|
|
@ -34,6 +34,7 @@ Assignment {
|
|||
tipo: (),
|
||||
},
|
||||
annotation: None,
|
||||
location: 7..14,
|
||||
},
|
||||
],
|
||||
kind: Expect {
|
||||
|
|
|
@ -33,6 +33,7 @@ Assignment {
|
|||
tipo: (),
|
||||
},
|
||||
annotation: None,
|
||||
location: 0..0,
|
||||
},
|
||||
],
|
||||
kind: Expect {
|
||||
|
|
|
@ -23,6 +23,7 @@ Assignment {
|
|||
name: "a",
|
||||
},
|
||||
annotation: None,
|
||||
location: 13..14,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
@ -44,6 +45,7 @@ Assignment {
|
|||
tipo: (),
|
||||
},
|
||||
annotation: None,
|
||||
location: 0..0,
|
||||
},
|
||||
],
|
||||
kind: Expect {
|
||||
|
|
|
@ -23,6 +23,7 @@ Assignment {
|
|||
name: "b",
|
||||
},
|
||||
annotation: None,
|
||||
location: 14..15,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
@ -38,6 +39,7 @@ Assignment {
|
|||
name: "a",
|
||||
},
|
||||
annotation: None,
|
||||
location: 4..5,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
|
|
@ -23,6 +23,7 @@ Assignment {
|
|||
name: "b",
|
||||
},
|
||||
annotation: None,
|
||||
location: 14..15,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
@ -38,6 +39,7 @@ Assignment {
|
|||
name: "a",
|
||||
},
|
||||
annotation: None,
|
||||
location: 4..5,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
|
|
@ -23,6 +23,7 @@ Assignment {
|
|||
name: "b",
|
||||
},
|
||||
annotation: None,
|
||||
location: 16..17,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
@ -42,6 +43,7 @@ Assignment {
|
|||
name: "a",
|
||||
},
|
||||
annotation: None,
|
||||
location: 4..5,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
|
|
@ -24,6 +24,7 @@ Assignment {
|
|||
tipo: (),
|
||||
},
|
||||
annotation: None,
|
||||
location: 0..0,
|
||||
},
|
||||
],
|
||||
kind: Expect {
|
||||
|
|
|
@ -34,6 +34,7 @@ Sequence {
|
|||
name: "x",
|
||||
},
|
||||
annotation: None,
|
||||
location: 4..5,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
@ -124,6 +125,7 @@ Sequence {
|
|||
name: "map_add_x",
|
||||
},
|
||||
annotation: None,
|
||||
location: 24..33,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
|
|
@ -21,6 +21,7 @@ Sequence {
|
|||
name: "i",
|
||||
},
|
||||
annotation: None,
|
||||
location: 8..9,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
@ -43,6 +44,7 @@ Sequence {
|
|||
name: "j",
|
||||
},
|
||||
annotation: None,
|
||||
location: 28..29,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
@ -69,6 +71,7 @@ Sequence {
|
|||
name: "k",
|
||||
},
|
||||
annotation: None,
|
||||
location: 48..49,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
|
|
@ -35,6 +35,7 @@ Assignment {
|
|||
name: "thing",
|
||||
},
|
||||
annotation: None,
|
||||
location: 4..9,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
|
|
@ -47,6 +47,7 @@ Sequence {
|
|||
name: "tuple",
|
||||
},
|
||||
annotation: None,
|
||||
location: 4..9,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
|
|
@ -34,6 +34,7 @@ Sequence {
|
|||
name: "a",
|
||||
},
|
||||
annotation: None,
|
||||
location: 4..5,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
|
|
@ -92,6 +92,7 @@ When {
|
|||
name: "amazing",
|
||||
},
|
||||
annotation: None,
|
||||
location: 55..62,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
|
|
@ -26,6 +26,7 @@ Module {
|
|||
name: "a",
|
||||
},
|
||||
annotation: None,
|
||||
location: 19..20,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
@ -70,6 +71,7 @@ Module {
|
|||
name: "a",
|
||||
},
|
||||
annotation: None,
|
||||
location: 56..57,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
@ -125,6 +127,7 @@ Module {
|
|||
name: "a",
|
||||
},
|
||||
annotation: None,
|
||||
location: 93..94,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
@ -176,6 +179,7 @@ Module {
|
|||
name: "a",
|
||||
},
|
||||
annotation: None,
|
||||
location: 126..127,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
|
|
@ -31,6 +31,7 @@ Module {
|
|||
name: "x",
|
||||
},
|
||||
annotation: None,
|
||||
location: 17..18,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
|
|
@ -29,6 +29,7 @@ Module {
|
|||
name: "x",
|
||||
},
|
||||
annotation: None,
|
||||
location: 17..18,
|
||||
},
|
||||
],
|
||||
kind: Let {
|
||||
|
|
|
@ -1984,3 +1984,27 @@ fn allow_expect_on_var_patterns_that_are_opaque() {
|
|||
|
||||
assert!(check(parse(source_code)).is_ok())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn correct_span_for_backpassing_args() {
|
||||
let source_code = r#"
|
||||
fn fold(list: List<a>, acc: b, f: fn(a, b) -> b) -> b {
|
||||
when list is {
|
||||
[] -> acc
|
||||
[x, ..xs] -> fold(xs, f(x, acc), f)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sum(list: List<Int>) -> Int {
|
||||
let a, b <- fold(list, 0)
|
||||
|
||||
a + 1
|
||||
}
|
||||
"#;
|
||||
|
||||
let (warnings, _ast) = check(parse(source_code)).unwrap();
|
||||
|
||||
assert!(
|
||||
matches!(&warnings[0], Warning::UnusedVariable { ref name, location } if name == "b" && location.start == 245 && location.end == 246)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -268,6 +268,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
let AssignmentPattern {
|
||||
pattern,
|
||||
annotation,
|
||||
location: _,
|
||||
} = patterns.into_vec().swap_remove(0);
|
||||
|
||||
self.infer_assignment(pattern, *value, kind, &annotation, location)
|
||||
|
@ -959,7 +960,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
value: UntypedExpr::Assignment {
|
||||
location,
|
||||
value: untyped_value.into(),
|
||||
patterns: AssignmentPattern::new(untyped_pattern, Some(ann)).into(),
|
||||
patterns: AssignmentPattern::new(untyped_pattern, Some(ann), Span::empty())
|
||||
.into(),
|
||||
kind,
|
||||
},
|
||||
});
|
||||
|
@ -1008,15 +1010,24 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
name: "...".to_string(),
|
||||
location: Span::empty(),
|
||||
}),
|
||||
patterns: AssignmentPattern::new(untyped_pattern, None)
|
||||
.into(),
|
||||
patterns: AssignmentPattern::new(
|
||||
untyped_pattern,
|
||||
None,
|
||||
Span::empty(),
|
||||
)
|
||||
.into(),
|
||||
kind: AssignmentKind::Let { backpassing: true },
|
||||
}
|
||||
}
|
||||
_ => UntypedExpr::Assignment {
|
||||
location: Span::empty(),
|
||||
value: Box::new(untyped_value),
|
||||
patterns: AssignmentPattern::new(untyped_pattern, None).into(),
|
||||
patterns: AssignmentPattern::new(
|
||||
untyped_pattern,
|
||||
None,
|
||||
Span::empty(),
|
||||
)
|
||||
.into(),
|
||||
kind: AssignmentKind::let_(),
|
||||
},
|
||||
},
|
||||
|
@ -1725,7 +1736,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
mut continuation: Vec<UntypedExpr>,
|
||||
) -> UntypedExpr {
|
||||
let UntypedExpr::Assignment {
|
||||
location: assign_location,
|
||||
location: _,
|
||||
value,
|
||||
kind,
|
||||
patterns,
|
||||
|
@ -1750,6 +1761,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
let AssignmentPattern {
|
||||
pattern,
|
||||
annotation,
|
||||
location: assignment_pattern_location,
|
||||
} = assignment_pattern;
|
||||
|
||||
// In case where we have a Pattern that isn't simply a let-binding to a name, we do insert an extra let-binding
|
||||
|
@ -1759,7 +1771,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
Pattern::Var { name, location: _ } | Pattern::Discard { name, location: _ }
|
||||
if kind.is_let() =>
|
||||
{
|
||||
names.push((name.clone(), annotation));
|
||||
names.push((name.clone(), assignment_pattern_location, annotation));
|
||||
}
|
||||
_ => {
|
||||
let name = format!("{}_{}", ast::BACKPASS_VARIABLE, index);
|
||||
|
@ -1767,13 +1779,18 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
continuation.insert(
|
||||
0,
|
||||
UntypedExpr::Assignment {
|
||||
location: assign_location,
|
||||
location: assignment_pattern_location,
|
||||
value: UntypedExpr::Var {
|
||||
location: value_location,
|
||||
location: assignment_pattern_location,
|
||||
name: name.clone(),
|
||||
}
|
||||
.into(),
|
||||
patterns: AssignmentPattern::new(pattern, annotation.clone()).into(),
|
||||
patterns: AssignmentPattern::new(
|
||||
pattern,
|
||||
annotation.clone(),
|
||||
assignment_pattern_location,
|
||||
)
|
||||
.into(),
|
||||
// erase backpassing while preserving assignment kind.
|
||||
kind: match kind {
|
||||
AssignmentKind::Let { .. } => AssignmentKind::let_(),
|
||||
|
@ -1782,7 +1799,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
},
|
||||
);
|
||||
|
||||
names.push((name, annotation));
|
||||
names.push((name, assignment_pattern_location, annotation));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2192,7 +2209,12 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
|||
sample: UntypedExpr::Assignment {
|
||||
location: Span::empty(),
|
||||
value: Box::new(subject.clone()),
|
||||
patterns: AssignmentPattern::new(clauses[0].patterns[0].clone(), None).into(),
|
||||
patterns: AssignmentPattern::new(
|
||||
clauses[0].patterns[0].clone(),
|
||||
None,
|
||||
Span::empty(),
|
||||
)
|
||||
.into(),
|
||||
kind: AssignmentKind::let_(),
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue