(and ...) combinator in patterns

This commit is contained in:
Chris Fallin
2021-09-07 00:47:03 -07:00
parent 602b8308ce
commit 1ceef04680
6 changed files with 61 additions and 7 deletions

View File

@@ -1,4 +1,3 @@
- `and` combinator in input.
- inputs to external extractors? "polarity" of args?
- "extractor macros" rather than full rule reversal? (rule ...) and (pattern ...)?
- Document semantics carefully, especially wrt extractors.

View File

@@ -0,0 +1,17 @@
(type u32 (primitive u32))
(type A (enum (A1 (x u32))))
(decl Ext1 (u32) A)
(decl Ext2 (u32) A)
(extractor Ext1 ext1)
(extractor Ext2 ext2)
(decl Lower (A) A)
(rule
(Lower
(and
a
(Ext1 x)
(Ext2 =x)))
a)

View File

@@ -83,6 +83,8 @@ pub enum Pattern {
Term { sym: Ident, args: Vec<Pattern> },
/// An operator that matches anything.
Wildcard,
/// N sub-patterns that must all match.
And { subpats: Vec<Pattern> },
}
/// An expression: the right-hand side of a rule.

View File

@@ -253,6 +253,13 @@ impl PatternSequence {
}
}
}
&Pattern::And(_ty, ref children) => {
let input = input.unwrap();
for child in children {
self.gen_pattern(Some(input), typeenv, termenv, child, vars);
}
None
}
&Pattern::Wildcard(_ty) => {
// Nothing!
None

View File

@@ -305,13 +305,23 @@ impl<'a> Parser<'a> {
}
} else if self.is_lparen() {
self.lparen()?;
let sym = self.parse_ident()?;
let mut args = vec![];
while !self.is_rparen() {
args.push(self.parse_pattern()?);
if self.is_sym_str("and") {
self.symbol()?;
let mut subpats = vec![];
while !self.is_rparen() {
subpats.push(self.parse_pattern()?);
}
self.rparen()?;
Ok(Pattern::And { subpats })
} else {
let sym = self.parse_ident()?;
let mut args = vec![];
while !self.is_rparen() {
args.push(self.parse_pattern()?);
}
self.rparen()?;
Ok(Pattern::Term { sym, args })
}
self.rparen()?;
Ok(Pattern::Term { sym, args })
} else {
Err(self.error(pos.unwrap(), "Unexpected pattern".into()))
}

View File

@@ -123,6 +123,7 @@ pub enum Pattern {
ConstInt(TypeId, i64),
Term(TypeId, TermId, Vec<Pattern>),
Wildcard(TypeId),
And(TypeId, Vec<Pattern>),
}
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -141,6 +142,7 @@ impl Pattern {
&Self::ConstInt(t, ..) => t,
&Self::Term(t, ..) => t,
&Self::Wildcard(t, ..) => t,
&Self::And(t, ..) => t,
}
}
}
@@ -293,11 +295,13 @@ impl TypeEnv {
}
}
#[derive(Clone)]
struct Bindings {
next_var: usize,
vars: Vec<BoundVar>,
}
#[derive(Clone)]
struct BoundVar {
name: Sym,
id: VarId,
@@ -548,6 +552,21 @@ impl TermEnv {
})?;
Ok((Pattern::Wildcard(ty), ty))
}
&ast::Pattern::And { ref subpats } => {
let mut expected_ty = expected_ty;
let mut children = vec![];
for subpat in subpats {
let (subpat, ty) =
self.translate_pattern(tyenv, pos, &*subpat, expected_ty, bindings)?;
expected_ty = expected_ty.or(Some(ty));
children.push(subpat);
}
if expected_ty.is_none() {
return Err(tyenv.error(pos, "No type for (and ...) form.".to_string()));
}
let ty = expected_ty.unwrap();
Ok((Pattern::And(ty, children), ty))
}
&ast::Pattern::BindPattern {
ref var,
ref subpat,