Skip to content

Commit

Permalink
Parse record and tuple patterns
Browse files Browse the repository at this point in the history
  • Loading branch information
Kmeakin committed Dec 11, 2022
1 parent af33a7b commit 9359fbb
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 24 deletions.
33 changes: 23 additions & 10 deletions fathom/src/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub struct ItemDef<'arena, Range> {
/// The label that identifies this definition
label: (Range, StringId),
/// Parameter patterns
patterns: &'arena [(Pattern<Range>, Option<&'arena Term<'arena, Range>>)],
patterns: &'arena [(Pattern<'arena, Range>, Option<&'arena Term<'arena, Range>>)],
/// An optional type annotation for the defined expression
// FIXME: raw identifiers in LALRPOP grammars https://github.com/lalrpop/lalrpop/issues/613
type_: Option<&'arena Term<'arena, Range>>,
Expand All @@ -76,7 +76,7 @@ pub struct ItemDef<'arena, Range> {

/// Surface patterns.
#[derive(Debug, Clone)]
pub enum Pattern<Range> {
pub enum Pattern<'arena, Range> {
/// Named patterns, eg. `x`, `true`, `false`
Name(Range, StringId),
/// Placeholder patterns, eg. `_`
Expand All @@ -93,8 +93,10 @@ pub enum Pattern<Range> {
NumberLiteral(Range, StringId),
/// Boolean literal patterns
BooleanLiteral(Range, bool),
// TODO: Record literal patterns
// RecordLiteral(Range, &'arena [((ByteRange, StringId), Pattern<'arena, Range>)]),
/// Record literal patterns
RecordLiteral(Range, &'arena [PatternField<'arena, Range>]),
/// Tuple literal patterns
Tuple(Range, &'arena [Pattern<'arena, Range>]),
}

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

impl<Range: Clone> Pattern<Range> {
impl<'arena, Range: Clone> Pattern<'arena, Range> {
pub fn range(&self) -> Range {
match self {
Pattern::Name(range, _)
| Pattern::Placeholder(range)
| Pattern::StringLiteral(range, _)
| Pattern::NumberLiteral(range, _)
| Pattern::BooleanLiteral(range, _) => range.clone(),
| Pattern::BooleanLiteral(range, _)
| Pattern::RecordLiteral(range, _)
| Pattern::Tuple(range, _) => range.clone(),
}
}
}
Expand All @@ -181,7 +185,7 @@ pub enum Term<'arena, Range> {
/// Let expressions.
Let(
Range,
Pattern<Range>,
Pattern<'arena, Range>,
Option<&'arena Term<'arena, Range>>,
&'arena Term<'arena, Range>,
&'arena Term<'arena, Range>,
Expand All @@ -197,7 +201,7 @@ pub enum Term<'arena, Range> {
Match(
Range,
&'arena Term<'arena, Range>,
&'arena [(Pattern<Range>, Term<'arena, Range>)],
&'arena [(Pattern<'arena, Range>, Term<'arena, Range>)],
),
/// The type of types.
Universe(Range),
Expand All @@ -210,13 +214,13 @@ pub enum Term<'arena, Range> {
/// Dependent function types.
FunType(
Range,
&'arena [(Pattern<Range>, Option<&'arena Term<'arena, Range>>)],
&'arena [(Pattern<'arena, Range>, Option<&'arena Term<'arena, Range>>)],
&'arena Term<'arena, Range>,
),
/// Function literals.
FunLiteral(
Range,
&'arena [(Pattern<Range>, Option<&'arena Term<'arena, Range>>)],
&'arena [(Pattern<'arena, Range>, Option<&'arena Term<'arena, Range>>)],
&'arena Term<'arena, Range>,
),
/// Applications.
Expand Down Expand Up @@ -373,6 +377,15 @@ pub struct ExprField<'arena, Range> {
expr: Term<'arena, Range>,
}

/// A field definition in a record pattern
#[derive(Debug, Clone)]
pub struct PatternField<'arena, Range> {
/// Label identifying the field
label: (Range, StringId),
/// The pattern that this field will match
pattern: Pattern<'arena, Range>,
}

/// Messages produced during parsing
#[derive(Clone, Debug)]
pub enum ParseMessage {
Expand Down
8 changes: 4 additions & 4 deletions fathom/src/surface/distillation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,15 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
Term::NumberLiteral((), number)
}

fn check_boolean_pattern(&mut self, boolean: bool) -> Pattern<()> {
fn check_boolean_pattern(&mut self, boolean: bool) -> Pattern<'arena, ()> {
let name = match boolean {
true => self.interner.borrow_mut().get_or_intern("true"),
false => self.interner.borrow_mut().get_or_intern("false"),
};
Pattern::Name((), name)
}

fn check_number_pattern<T: std::fmt::Display>(&mut self, number: T) -> Pattern<()> {
fn check_number_pattern<T: std::fmt::Display>(&mut self, number: T) -> Pattern<'arena, ()> {
let number = self.interner.borrow_mut().get_or_intern(number.to_string());
Pattern::NumberLiteral((), number)
}
Expand All @@ -146,14 +146,14 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
&mut self,
number: T,
style: UIntStyle,
) -> Pattern<()> {
) -> Pattern<'arena, ()> {
// TODO: Share with check_number_literal_styled
let string = style.format(number);
let number = self.interner.borrow_mut().get_or_intern(string);
Pattern::NumberLiteral((), number)
}

fn check_constant_pattern(&mut self, r#const: &core::Const) -> Pattern<()> {
fn check_constant_pattern(&mut self, r#const: &core::Const) -> Pattern<'arena, ()> {
match r#const {
core::Const::Bool(boolean) => self.check_boolean_pattern(*boolean),
core::Const::U8(number, style) => self.check_number_pattern_styled(number, *style),
Expand Down
15 changes: 10 additions & 5 deletions fathom/src/surface/elaboration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,8 +456,9 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
});
}

let filtered_fields = (fields.iter().enumerate())
.filter_map(move |(index, field)| (!duplicate_indices.contains(&index)).then_some(field));
let filtered_fields = (fields.iter().enumerate()).filter_map(move |(index, field)| {
(!duplicate_indices.contains(&index)).then_some(field)
});

(labels.into(), filtered_fields)
}
Expand Down Expand Up @@ -775,6 +776,8 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
None => CheckedPattern::ReportedError(*range),
}
}
Pattern::RecordLiteral(_, _) => todo!(),
Pattern::Tuple(_, _) => todo!(),
}
}

Expand Down Expand Up @@ -811,6 +814,8 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
let r#type = self.bool_type.clone();
(CheckedPattern::ConstLit(*range, r#const), r#type)
}
Pattern::RecordLiteral(_, _) => todo!(),
Pattern::Tuple(_, _) => todo!(),
}
}

Expand Down Expand Up @@ -1965,7 +1970,7 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
&mut self,
match_info: &MatchInfo<'arena>,
is_reachable: bool,
mut equations: impl Iterator<Item = &'a (Pattern<ByteRange>, Term<'a, ByteRange>)>,
mut equations: impl Iterator<Item = &'a (Pattern<'a, ByteRange>, Term<'a, ByteRange>)>,
) -> core::Term<'arena> {
match equations.next() {
Some((pattern, body_expr)) => {
Expand Down Expand Up @@ -2042,7 +2047,7 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
match_info: &MatchInfo<'arena>,
is_reachable: bool,
(const_range, r#const, body_expr): (ByteRange, Const, core::Term<'arena>),
mut equations: impl Iterator<Item = &'a (Pattern<ByteRange>, Term<'a, ByteRange>)>,
mut equations: impl Iterator<Item = &'a (Pattern<'a, ByteRange>, Term<'a, ByteRange>)>,
) -> core::Term<'arena> {
// The full range of this series of patterns
let mut full_span = Span::merge(&const_range.into(), &body_expr.span());
Expand Down Expand Up @@ -2146,7 +2151,7 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
fn elab_match_unreachable<'a>(
&mut self,
match_info: &MatchInfo<'arena>,
equations: impl Iterator<Item = &'a (Pattern<ByteRange>, Term<'a, ByteRange>)>,
equations: impl Iterator<Item = &'a (Pattern<'a, ByteRange>, Term<'a, ByteRange>)>,
) {
self.elab_match(match_info, false, equations);
}
Expand Down
4 changes: 4 additions & 0 deletions fathom/src/surface/elaboration/order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,8 @@ fn push_pattern(pattern: &Pattern<ByteRange>, local_names: &mut Vec<StringId>) {
Pattern::StringLiteral(_, _) => {}
Pattern::NumberLiteral(_, _) => {}
Pattern::BooleanLiteral(_, _) => {}
Pattern::RecordLiteral(_, _) => todo!(),
Pattern::Tuple(_, _) => todo!(),
}
}

Expand All @@ -344,5 +346,7 @@ fn pop_pattern(pattern: &Pattern<ByteRange>, local_names: &mut Vec<StringId>) {
Pattern::StringLiteral(_, _) => {}
Pattern::NumberLiteral(_, _) => {}
Pattern::BooleanLiteral(_, _) => {}
Pattern::RecordLiteral(_, _) => todo!(),
Pattern::Tuple(_, _) => todo!(),
}
}
16 changes: 11 additions & 5 deletions fathom/src/surface/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use scoped_arena::Scope;
use std::cell::RefCell;

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

grammar<'arena, 'source>(
Expand Down Expand Up @@ -88,16 +88,18 @@ Item: Item<'arena, ByteRange> = {
},
};

Pattern: Pattern<ByteRange> = {
Pattern: Pattern<'arena, ByteRange> = {
<start: @L> <name: Name> <end: @R> => Pattern::Name(ByteRange::new(file_id, start, end), name),
<start: @L> "_" <end: @R> => Pattern::Placeholder(ByteRange::new(file_id, start, end)),
<start: @L> <string: StringLiteral> <end: @R> => Pattern::StringLiteral(ByteRange::new(file_id, start, end), string),
<start: @L> <number: NumberLiteral> <end: @R> => Pattern::NumberLiteral(ByteRange::new(file_id, start, end), number),
<start: @L> "true" <end: @R> => Pattern::BooleanLiteral(ByteRange::new(file_id, start, end), true),
<start: @L> "false" <end: @R> => Pattern::BooleanLiteral(ByteRange::new(file_id, start, end), false),
<start: @L> "{" <fields: Seq<PatternField,",">> "}" <end: @R> => Pattern::RecordLiteral(ByteRange::new(file_id, start, end), fields),
<start: @L> <patterns: Tuple<Pattern>> <end: @R> => Pattern::Tuple(ByteRange::new(file_id, start, end), patterns),
};

AnnPattern: (Pattern<ByteRange>, Option<&'arena Term<'arena, ByteRange>>) = {
AnnPattern: (Pattern<'arena, ByteRange>, Option<&'arena Term<'arena, ByteRange>>) = {
<pattern: Pattern> => (pattern, None),
"(" <pattern: Pattern> ":" <type_: LetTerm> ")" => (pattern, Some(scope.to_scope(type_))),
};
Expand Down Expand Up @@ -260,6 +262,10 @@ ExprField: ExprField<'arena, ByteRange> = {
<label: RangedName> "=" <expr: Term> => ExprField { label, expr },
};

PatternField: PatternField<'arena, ByteRange> = {
<label: RangedName> "=" <pattern: Pattern> => PatternField { label, pattern },
};

BinExpr<Lhs, Op, Rhs>: Term<'arena, ByteRange> = {
<start: @L> <lhs: Lhs> <op: Op> <rhs: Rhs> <end: @R> => {
Term::BinOp(
Expand Down Expand Up @@ -290,8 +296,8 @@ BinOpGte: BinOp<ByteRange> = <start: @L> ">=" <end: @R> => BinOp::Gte(ByteRange:

Tuple<Elem>: &'arena [Elem] = {
"(" ")" => &[],
"(" <term: Term> "," ")" => scope.to_scope_from_iter([term]),
"(" <terms: Seq2<Term, ",">> ")" => terms,
"(" <term: Elem> "," ")" => scope.to_scope_from_iter([term]),
"(" <terms: Seq2<Elem, ",">> ")" => terms,
};

#[inline]
Expand Down
2 changes: 2 additions & 0 deletions fathom/src/surface/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
true => self.text("true"),
false => self.text("false"),
},
Pattern::RecordLiteral(_, _) => todo!(),
Pattern::Tuple(_, _) => todo!(),
}
}

Expand Down

0 comments on commit 9359fbb

Please sign in to comment.