Skip to content

Commit 9359fbb

Browse files
committed
Parse record and tuple patterns
1 parent af33a7b commit 9359fbb

File tree

6 files changed

+54
-24
lines changed

6 files changed

+54
-24
lines changed

fathom/src/surface.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub struct ItemDef<'arena, Range> {
6666
/// The label that identifies this definition
6767
label: (Range, StringId),
6868
/// Parameter patterns
69-
patterns: &'arena [(Pattern<Range>, Option<&'arena Term<'arena, Range>>)],
69+
patterns: &'arena [(Pattern<'arena, Range>, Option<&'arena Term<'arena, Range>>)],
7070
/// An optional type annotation for the defined expression
7171
// FIXME: raw identifiers in LALRPOP grammars https://github.com/lalrpop/lalrpop/issues/613
7272
type_: Option<&'arena Term<'arena, Range>>,
@@ -76,7 +76,7 @@ pub struct ItemDef<'arena, Range> {
7676

7777
/// Surface patterns.
7878
#[derive(Debug, Clone)]
79-
pub enum Pattern<Range> {
79+
pub enum Pattern<'arena, Range> {
8080
/// Named patterns, eg. `x`, `true`, `false`
8181
Name(Range, StringId),
8282
/// Placeholder patterns, eg. `_`
@@ -93,8 +93,10 @@ pub enum Pattern<Range> {
9393
NumberLiteral(Range, StringId),
9494
/// Boolean literal patterns
9595
BooleanLiteral(Range, bool),
96-
// TODO: Record literal patterns
97-
// RecordLiteral(Range, &'arena [((ByteRange, StringId), Pattern<'arena, Range>)]),
96+
/// Record literal patterns
97+
RecordLiteral(Range, &'arena [PatternField<'arena, Range>]),
98+
/// Tuple literal patterns
99+
Tuple(Range, &'arena [Pattern<'arena, Range>]),
98100
}
99101

100102
#[derive(Debug, Clone, Copy)]
@@ -151,14 +153,16 @@ impl<Range> fmt::Display for BinOp<Range> {
151153
}
152154
}
153155

154-
impl<Range: Clone> Pattern<Range> {
156+
impl<'arena, Range: Clone> Pattern<'arena, Range> {
155157
pub fn range(&self) -> Range {
156158
match self {
157159
Pattern::Name(range, _)
158160
| Pattern::Placeholder(range)
159161
| Pattern::StringLiteral(range, _)
160162
| Pattern::NumberLiteral(range, _)
161-
| Pattern::BooleanLiteral(range, _) => range.clone(),
163+
| Pattern::BooleanLiteral(range, _)
164+
| Pattern::RecordLiteral(range, _)
165+
| Pattern::Tuple(range, _) => range.clone(),
162166
}
163167
}
164168
}
@@ -181,7 +185,7 @@ pub enum Term<'arena, Range> {
181185
/// Let expressions.
182186
Let(
183187
Range,
184-
Pattern<Range>,
188+
Pattern<'arena, Range>,
185189
Option<&'arena Term<'arena, Range>>,
186190
&'arena Term<'arena, Range>,
187191
&'arena Term<'arena, Range>,
@@ -197,7 +201,7 @@ pub enum Term<'arena, Range> {
197201
Match(
198202
Range,
199203
&'arena Term<'arena, Range>,
200-
&'arena [(Pattern<Range>, Term<'arena, Range>)],
204+
&'arena [(Pattern<'arena, Range>, Term<'arena, Range>)],
201205
),
202206
/// The type of types.
203207
Universe(Range),
@@ -210,13 +214,13 @@ pub enum Term<'arena, Range> {
210214
/// Dependent function types.
211215
FunType(
212216
Range,
213-
&'arena [(Pattern<Range>, Option<&'arena Term<'arena, Range>>)],
217+
&'arena [(Pattern<'arena, Range>, Option<&'arena Term<'arena, Range>>)],
214218
&'arena Term<'arena, Range>,
215219
),
216220
/// Function literals.
217221
FunLiteral(
218222
Range,
219-
&'arena [(Pattern<Range>, Option<&'arena Term<'arena, Range>>)],
223+
&'arena [(Pattern<'arena, Range>, Option<&'arena Term<'arena, Range>>)],
220224
&'arena Term<'arena, Range>,
221225
),
222226
/// Applications.
@@ -373,6 +377,15 @@ pub struct ExprField<'arena, Range> {
373377
expr: Term<'arena, Range>,
374378
}
375379

380+
/// A field definition in a record pattern
381+
#[derive(Debug, Clone)]
382+
pub struct PatternField<'arena, Range> {
383+
/// Label identifying the field
384+
label: (Range, StringId),
385+
/// The pattern that this field will match
386+
pattern: Pattern<'arena, Range>,
387+
}
388+
376389
/// Messages produced during parsing
377390
#[derive(Clone, Debug)]
378391
pub enum ParseMessage {

fathom/src/surface/distillation.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,15 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
129129
Term::NumberLiteral((), number)
130130
}
131131

132-
fn check_boolean_pattern(&mut self, boolean: bool) -> Pattern<()> {
132+
fn check_boolean_pattern(&mut self, boolean: bool) -> Pattern<'arena, ()> {
133133
let name = match boolean {
134134
true => self.interner.borrow_mut().get_or_intern("true"),
135135
false => self.interner.borrow_mut().get_or_intern("false"),
136136
};
137137
Pattern::Name((), name)
138138
}
139139

140-
fn check_number_pattern<T: std::fmt::Display>(&mut self, number: T) -> Pattern<()> {
140+
fn check_number_pattern<T: std::fmt::Display>(&mut self, number: T) -> Pattern<'arena, ()> {
141141
let number = self.interner.borrow_mut().get_or_intern(number.to_string());
142142
Pattern::NumberLiteral((), number)
143143
}
@@ -146,14 +146,14 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
146146
&mut self,
147147
number: T,
148148
style: UIntStyle,
149-
) -> Pattern<()> {
149+
) -> Pattern<'arena, ()> {
150150
// TODO: Share with check_number_literal_styled
151151
let string = style.format(number);
152152
let number = self.interner.borrow_mut().get_or_intern(string);
153153
Pattern::NumberLiteral((), number)
154154
}
155155

156-
fn check_constant_pattern(&mut self, r#const: &core::Const) -> Pattern<()> {
156+
fn check_constant_pattern(&mut self, r#const: &core::Const) -> Pattern<'arena, ()> {
157157
match r#const {
158158
core::Const::Bool(boolean) => self.check_boolean_pattern(*boolean),
159159
core::Const::U8(number, style) => self.check_number_pattern_styled(number, *style),

fathom/src/surface/elaboration.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -456,8 +456,9 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
456456
});
457457
}
458458

459-
let filtered_fields = (fields.iter().enumerate())
460-
.filter_map(move |(index, field)| (!duplicate_indices.contains(&index)).then_some(field));
459+
let filtered_fields = (fields.iter().enumerate()).filter_map(move |(index, field)| {
460+
(!duplicate_indices.contains(&index)).then_some(field)
461+
});
461462

462463
(labels.into(), filtered_fields)
463464
}
@@ -775,6 +776,8 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
775776
None => CheckedPattern::ReportedError(*range),
776777
}
777778
}
779+
Pattern::RecordLiteral(_, _) => todo!(),
780+
Pattern::Tuple(_, _) => todo!(),
778781
}
779782
}
780783

@@ -811,6 +814,8 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
811814
let r#type = self.bool_type.clone();
812815
(CheckedPattern::ConstLit(*range, r#const), r#type)
813816
}
817+
Pattern::RecordLiteral(_, _) => todo!(),
818+
Pattern::Tuple(_, _) => todo!(),
814819
}
815820
}
816821

@@ -1965,7 +1970,7 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
19651970
&mut self,
19661971
match_info: &MatchInfo<'arena>,
19671972
is_reachable: bool,
1968-
mut equations: impl Iterator<Item = &'a (Pattern<ByteRange>, Term<'a, ByteRange>)>,
1973+
mut equations: impl Iterator<Item = &'a (Pattern<'a, ByteRange>, Term<'a, ByteRange>)>,
19691974
) -> core::Term<'arena> {
19701975
match equations.next() {
19711976
Some((pattern, body_expr)) => {
@@ -2042,7 +2047,7 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
20422047
match_info: &MatchInfo<'arena>,
20432048
is_reachable: bool,
20442049
(const_range, r#const, body_expr): (ByteRange, Const, core::Term<'arena>),
2045-
mut equations: impl Iterator<Item = &'a (Pattern<ByteRange>, Term<'a, ByteRange>)>,
2050+
mut equations: impl Iterator<Item = &'a (Pattern<'a, ByteRange>, Term<'a, ByteRange>)>,
20462051
) -> core::Term<'arena> {
20472052
// The full range of this series of patterns
20482053
let mut full_span = Span::merge(&const_range.into(), &body_expr.span());
@@ -2146,7 +2151,7 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
21462151
fn elab_match_unreachable<'a>(
21472152
&mut self,
21482153
match_info: &MatchInfo<'arena>,
2149-
equations: impl Iterator<Item = &'a (Pattern<ByteRange>, Term<'a, ByteRange>)>,
2154+
equations: impl Iterator<Item = &'a (Pattern<'a, ByteRange>, Term<'a, ByteRange>)>,
21502155
) {
21512156
self.elab_match(match_info, false, equations);
21522157
}

fathom/src/surface/elaboration/order.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,8 @@ fn push_pattern(pattern: &Pattern<ByteRange>, local_names: &mut Vec<StringId>) {
332332
Pattern::StringLiteral(_, _) => {}
333333
Pattern::NumberLiteral(_, _) => {}
334334
Pattern::BooleanLiteral(_, _) => {}
335+
Pattern::RecordLiteral(_, _) => todo!(),
336+
Pattern::Tuple(_, _) => todo!(),
335337
}
336338
}
337339

@@ -344,5 +346,7 @@ fn pop_pattern(pattern: &Pattern<ByteRange>, local_names: &mut Vec<StringId>) {
344346
Pattern::StringLiteral(_, _) => {}
345347
Pattern::NumberLiteral(_, _) => {}
346348
Pattern::BooleanLiteral(_, _) => {}
349+
Pattern::RecordLiteral(_, _) => todo!(),
350+
Pattern::Tuple(_, _) => todo!(),
347351
}
348352
}

fathom/src/surface/grammar.lalrpop

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use scoped_arena::Scope;
22
use std::cell::RefCell;
33

44
use crate::source::{ByteRange, FileId, StringId, StringInterner};
5-
use crate::surface::{ExprField, FormatField, Item, ItemDef, Module, ParseMessage, Pattern, Term, TypeField, BinOp};
5+
use crate::surface::{ExprField, FormatField, Item, ItemDef, Module, ParseMessage, Pattern, PatternField, Term, TypeField, BinOp};
66
use crate::surface::lexer::{Error as LexerError, Token};
77

88
grammar<'arena, 'source>(
@@ -88,16 +88,18 @@ Item: Item<'arena, ByteRange> = {
8888
},
8989
};
9090

91-
Pattern: Pattern<ByteRange> = {
91+
Pattern: Pattern<'arena, ByteRange> = {
9292
<start: @L> <name: Name> <end: @R> => Pattern::Name(ByteRange::new(file_id, start, end), name),
9393
<start: @L> "_" <end: @R> => Pattern::Placeholder(ByteRange::new(file_id, start, end)),
9494
<start: @L> <string: StringLiteral> <end: @R> => Pattern::StringLiteral(ByteRange::new(file_id, start, end), string),
9595
<start: @L> <number: NumberLiteral> <end: @R> => Pattern::NumberLiteral(ByteRange::new(file_id, start, end), number),
9696
<start: @L> "true" <end: @R> => Pattern::BooleanLiteral(ByteRange::new(file_id, start, end), true),
9797
<start: @L> "false" <end: @R> => Pattern::BooleanLiteral(ByteRange::new(file_id, start, end), false),
98+
<start: @L> "{" <fields: Seq<PatternField,",">> "}" <end: @R> => Pattern::RecordLiteral(ByteRange::new(file_id, start, end), fields),
99+
<start: @L> <patterns: Tuple<Pattern>> <end: @R> => Pattern::Tuple(ByteRange::new(file_id, start, end), patterns),
98100
};
99101

100-
AnnPattern: (Pattern<ByteRange>, Option<&'arena Term<'arena, ByteRange>>) = {
102+
AnnPattern: (Pattern<'arena, ByteRange>, Option<&'arena Term<'arena, ByteRange>>) = {
101103
<pattern: Pattern> => (pattern, None),
102104
"(" <pattern: Pattern> ":" <type_: LetTerm> ")" => (pattern, Some(scope.to_scope(type_))),
103105
};
@@ -260,6 +262,10 @@ ExprField: ExprField<'arena, ByteRange> = {
260262
<label: RangedName> "=" <expr: Term> => ExprField { label, expr },
261263
};
262264

265+
PatternField: PatternField<'arena, ByteRange> = {
266+
<label: RangedName> "=" <pattern: Pattern> => PatternField { label, pattern },
267+
};
268+
263269
BinExpr<Lhs, Op, Rhs>: Term<'arena, ByteRange> = {
264270
<start: @L> <lhs: Lhs> <op: Op> <rhs: Rhs> <end: @R> => {
265271
Term::BinOp(
@@ -290,8 +296,8 @@ BinOpGte: BinOp<ByteRange> = <start: @L> ">=" <end: @R> => BinOp::Gte(ByteRange:
290296

291297
Tuple<Elem>: &'arena [Elem] = {
292298
"(" ")" => &[],
293-
"(" <term: Term> "," ")" => scope.to_scope_from_iter([term]),
294-
"(" <terms: Seq2<Term, ",">> ")" => terms,
299+
"(" <term: Elem> "," ")" => scope.to_scope_from_iter([term]),
300+
"(" <terms: Seq2<Elem, ",">> ")" => terms,
295301
};
296302

297303
#[inline]

fathom/src/surface/pretty.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
9494
true => self.text("true"),
9595
false => self.text("false"),
9696
},
97+
Pattern::RecordLiteral(_, _) => todo!(),
98+
Pattern::Tuple(_, _) => todo!(),
9799
}
98100
}
99101

0 commit comments

Comments
 (0)