feat(backpassing): implements multi patterns

The main trick here was transforming Assignment
to contain `Vec<UntypedPattern, Option<Annotation>>`
in a field called patterns. This then meant that I
could remove the `pattern` and `annotation` field
from `Assignment`. The parser handles `=` and `<-`
just fine because in the future `=` with multi
patterns will mean some kind of optimization on tuples.
But, since we don't have that optimization yet, when
someone uses multi patterns with an `=` there will be an
error returned from the type checker right where `infer_seq`
looks for `backpassing`. From there the rest of the work
was in `Project::backpassing` where I only needed to rework
some things to work with a list of patterns instead of just one.
This commit is contained in:
rvcas
2024-03-11 18:23:17 -04:00
committed by Lucas
parent f02b9b0f0c
commit b6b52ba508
26 changed files with 592 additions and 292 deletions

View File

@@ -14,20 +14,24 @@ Test(
location: 45..50,
name: "False",
},
pattern: Constructor {
is_record: false,
location: 38..42,
name: "True",
arguments: [],
module: None,
constructor: (),
with_spread: false,
tipo: (),
},
patterns: [
(
Constructor {
is_record: false,
location: 38..42,
name: "True",
arguments: [],
module: None,
constructor: (),
with_spread: false,
tipo: (),
},
None,
),
],
kind: Expect {
backpassing: false,
},
annotation: None,
},
Var {
location: 54..59,

View File

@@ -25,14 +25,18 @@ Fn(
},
},
},
pattern: Var {
location: 17..18,
name: "x",
},
patterns: [
(
Var {
location: 17..18,
name: "x",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
},
doc: None,
location: 0..8,

View File

@@ -9,23 +9,30 @@ 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())
.ignore_then(
pattern()
.then(just(Token::Colon).ignore_then(annotation()).or_not())
.separated_by(just(Token::Comma))
.at_least(1),
)
.then(choice((just(Token::Equal), just(Token::LArrow))))
.then(r.clone())
.validate(move |(((pattern, annotation), kind), value), span, emit| {
.validate(move |((patterns, kind), value), span, emit| {
if matches!(value, UntypedExpr::Assignment { .. }) {
emit(ParseError::invalid_assignment_right_hand_side(span))
}
let patterns = patterns
.try_into()
.expect("We use at_least(1) so this should never be empty");
UntypedExpr::Assignment {
location: span,
value: Box::new(value),
pattern,
patterns,
kind: ast::AssignmentKind::Let {
backpassing: kind == Token::LArrow,
},
annotation,
}
})
}
@@ -37,14 +44,20 @@ pub fn expect(
.ignore_then(
pattern()
.then(just(Token::Colon).ignore_then(annotation()).or_not())
.separated_by(just(Token::Comma))
.at_least(1)
.then(choice((just(Token::Equal), just(Token::LArrow))))
.or_not(),
)
.then(r.clone())
.validate(move |(opt_pattern, value), span, emit| {
let ((pattern, annotation), kind) = opt_pattern.unwrap_or_else(|| {
if matches!(value, UntypedExpr::Assignment { .. }) {
emit(ParseError::invalid_assignment_right_hand_side(span))
}
let (patterns, kind) = opt_pattern.unwrap_or_else(|| {
(
(
vec![(
ast::UntypedPattern::Constructor {
is_record: false,
location: span,
@@ -56,23 +69,22 @@ pub fn expect(
tipo: (),
},
None,
),
)],
Token::Equal,
)
});
if matches!(value, UntypedExpr::Assignment { .. }) {
emit(ParseError::invalid_assignment_right_hand_side(span))
}
let patterns = patterns
.try_into()
.expect("We use at_least(1) so this should never be empty");
UntypedExpr::Assignment {
location: span,
patterns,
value: Box::new(value),
pattern,
kind: ast::AssignmentKind::Expect {
backpassing: kind == Token::LArrow,
},
annotation,
}
})
}

View File

@@ -16,14 +16,18 @@ Assignment {
numeric_underscore: false,
},
},
pattern: Var {
location: 16..17,
name: "x",
},
patterns: [
(
Var {
location: 16..17,
name: "x",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
},
BinOp {
location: 24..29,
@@ -42,12 +46,16 @@ Assignment {
},
],
},
pattern: Var {
location: 4..5,
name: "b",
},
patterns: [
(
Var {
location: 4..5,
name: "b",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
}

View File

@@ -12,27 +12,31 @@ Assignment {
name: "something",
},
},
pattern: Constructor {
is_record: false,
location: 7..14,
name: "Some",
arguments: [
CallArg {
label: None,
location: 12..13,
value: Var {
location: 12..13,
name: "x",
},
patterns: [
(
Constructor {
is_record: false,
location: 7..14,
name: "Some",
arguments: [
CallArg {
label: None,
location: 12..13,
value: Var {
location: 12..13,
name: "x",
},
},
],
module: None,
constructor: (),
with_spread: false,
tipo: (),
},
],
module: None,
constructor: (),
with_spread: false,
tipo: (),
},
None,
),
],
kind: Expect {
backpassing: false,
},
annotation: None,
}

View File

@@ -20,18 +20,22 @@ Assignment {
name: "wow",
},
},
pattern: Constructor {
is_record: false,
location: 0..29,
name: "True",
arguments: [],
module: None,
constructor: (),
with_spread: false,
tipo: (),
},
patterns: [
(
Constructor {
is_record: false,
location: 0..29,
name: "True",
arguments: [],
module: None,
constructor: (),
with_spread: false,
tipo: (),
},
None,
),
],
kind: Expect {
backpassing: false,
},
annotation: None,
}

View File

@@ -16,29 +16,37 @@ Assignment {
numeric_underscore: false,
},
},
pattern: Var {
location: 13..14,
name: "a",
},
patterns: [
(
Var {
location: 13..14,
name: "a",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
},
],
},
pattern: Constructor {
is_record: false,
location: 0..21,
name: "True",
arguments: [],
module: None,
constructor: (),
with_spread: false,
tipo: (),
},
patterns: [
(
Constructor {
is_record: false,
location: 0..21,
name: "True",
arguments: [],
module: None,
constructor: (),
with_spread: false,
tipo: (),
},
None,
),
],
kind: Expect {
backpassing: false,
},
annotation: None,
}

View File

@@ -16,23 +16,31 @@ Assignment {
numeric_underscore: false,
},
},
pattern: Var {
location: 14..15,
name: "b",
},
patterns: [
(
Var {
location: 14..15,
name: "b",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
},
],
},
pattern: Var {
location: 4..5,
name: "a",
},
patterns: [
(
Var {
location: 4..5,
name: "a",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
}

View File

@@ -16,23 +16,31 @@ Assignment {
numeric_underscore: false,
},
},
pattern: Var {
location: 14..15,
name: "b",
},
patterns: [
(
Var {
location: 14..15,
name: "b",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
},
],
},
pattern: Var {
location: 4..5,
name: "a",
},
patterns: [
(
Var {
location: 4..5,
name: "a",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
}

View File

@@ -16,14 +16,18 @@ Assignment {
numeric_underscore: false,
},
},
pattern: Var {
location: 16..17,
name: "b",
},
patterns: [
(
Var {
location: 16..17,
name: "b",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
},
Var {
location: 25..26,
@@ -31,12 +35,16 @@ Assignment {
},
],
},
pattern: Var {
location: 4..5,
name: "a",
},
patterns: [
(
Var {
location: 4..5,
name: "a",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
}

View File

@@ -11,18 +11,22 @@ Assignment {
name: "foo",
},
},
pattern: Constructor {
is_record: false,
location: 0..11,
name: "True",
arguments: [],
module: None,
constructor: (),
with_spread: false,
tipo: (),
},
patterns: [
(
Constructor {
is_record: false,
location: 0..11,
name: "True",
arguments: [],
module: None,
constructor: (),
with_spread: false,
tipo: (),
},
None,
),
],
kind: Expect {
backpassing: false,
},
annotation: None,
}

View File

@@ -27,14 +27,18 @@ Sequence {
},
location: 8..18,
},
pattern: Var {
location: 4..5,
name: "x",
},
patterns: [
(
Var {
location: 4..5,
name: "x",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
},
Assignment {
location: 20..65,
@@ -113,14 +117,18 @@ Sequence {
},
return_annotation: None,
},
pattern: Var {
location: 24..33,
name: "map_add_x",
},
patterns: [
(
Var {
location: 24..33,
name: "map_add_x",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
},
Call {
arguments: [

View File

@@ -14,14 +14,18 @@ Sequence {
numeric_underscore: true,
},
},
pattern: Var {
location: 8..9,
name: "i",
},
patterns: [
(
Var {
location: 8..9,
name: "i",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
},
Assignment {
location: 24..41,
@@ -32,14 +36,18 @@ Sequence {
numeric_underscore: true,
},
},
pattern: Var {
location: 28..29,
name: "j",
},
patterns: [
(
Var {
location: 28..29,
name: "j",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
},
Assignment {
location: 44..59,
@@ -54,14 +62,18 @@ Sequence {
},
},
},
pattern: Var {
location: 48..49,
name: "k",
},
patterns: [
(
Var {
location: 48..49,
name: "k",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
},
],
}

View File

@@ -28,12 +28,16 @@ Assignment {
],
tail: None,
},
pattern: Var {
location: 4..9,
name: "thing",
},
patterns: [
(
Var {
location: 4..9,
name: "thing",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
}

View File

@@ -40,14 +40,18 @@ Sequence {
},
],
},
pattern: Var {
location: 4..9,
name: "tuple",
},
patterns: [
(
Var {
location: 4..9,
name: "tuple",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
},
BinOp {
location: 25..70,

View File

@@ -27,14 +27,18 @@ Sequence {
},
location: 8..15,
},
pattern: Var {
location: 4..5,
name: "a",
},
patterns: [
(
Var {
location: 4..5,
name: "a",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
},
Tuple {
location: 16..23,

View File

@@ -85,14 +85,18 @@ When {
numeric_underscore: false,
},
},
pattern: Var {
location: 55..62,
name: "amazing",
},
patterns: [
(
Var {
location: 55..62,
name: "amazing",
},
None,
),
],
kind: Let {
backpassing: false,
},
annotation: None,
},
Var {
location: 71..78,