conlang: Add Tuple-Struct Patterns

- Patterns are no longer parsed with the highest precedence
- Function calls with just a path and a tuple of args can now be transformed into a Pattern
This commit is contained in:
John 2025-02-22 01:37:08 -06:00
parent 5d2c714bc1
commit 697d139cfd
9 changed files with 46 additions and 5 deletions

View File

@ -424,6 +424,7 @@ pub enum Pattern {
Tuple(Vec<Pattern>), Tuple(Vec<Pattern>),
Array(Vec<Pattern>), Array(Vec<Pattern>),
Struct(Path, Vec<(Sym, Option<Pattern>)>), Struct(Path, Vec<(Sym, Option<Pattern>)>),
TupleStruct(Path, Vec<Pattern>),
} }
/// A `match` expression: `match` `{` ([MatchArm] `,`)* [MatchArm]? `}` /// A `match` expression: `match` `{` ([MatchArm] `,`)* [MatchArm]? `}`

View File

@ -487,6 +487,10 @@ mod display {
} }
Ok(()) Ok(())
} }
Pattern::TupleStruct(path, items) => {
write!(f, "{path}")?;
separate(items, ", ")(f.delimit(INLINE_PARENS))
}
} }
} }
} }
@ -884,8 +888,19 @@ mod convert {
.map(|e| Pattern::try_from(e.kind)) .map(|e| Pattern::try_from(e.kind))
.collect::<Result<_, _>>()?, .collect::<Result<_, _>>()?,
), ),
// ExprKind::Index(index) => todo!(), ExprKind::Binary(Binary { kind: BinaryKind::Call, parts }) => {
// ExprKind::Member(member) => todo!(), let (ExprKind::Path(path), args) = *parts else {
return Err(parts.0);
};
match args {
ExprKind::Empty | ExprKind::Tuple(_) => {}
_ => return Err(args),
}
let Pattern::Tuple(args) = Pattern::try_from(args)? else {
unreachable!("Arguments should be convertible to pattern!")
};
Pattern::TupleStruct(path, args)
}
ExprKind::Structor(Structor { to, init }) => { ExprKind::Structor(Structor { to, init }) => {
let fields = init let fields = init
.into_iter() .into_iter()

View File

@ -267,6 +267,13 @@ pub trait Fold {
.map(|(name, bind)| (name, bind.map(|p| self.fold_pattern(p)))) .map(|(name, bind)| (name, bind.map(|p| self.fold_pattern(p))))
.collect(), .collect(),
), ),
Pattern::TupleStruct(path, items) => Pattern::TupleStruct(
self.fold_path(path),
items
.into_iter()
.map(|bind| self.fold_pattern(bind))
.collect(),
),
} }
} }

View File

@ -234,6 +234,10 @@ pub trait Visit<'a>: Sized {
}); });
}); });
} }
Pattern::TupleStruct(path, items) => {
self.visit_path(path);
items.iter().for_each(|bind| self.visit_pattern(bind));
}
} }
} }

View File

@ -127,6 +127,10 @@ impl<'a> Visit<'a> for CollectUpvars<'_> {
}); });
}); });
} }
Pattern::TupleStruct(path, items) => {
self.visit_path(path);
items.iter().for_each(|bind| self.visit_pattern(bind));
}
} }
} }
} }

View File

@ -320,6 +320,9 @@ mod assignment {
None => set.push(name), None => set.push(name),
}); });
} }
Pattern::TupleStruct(_path, items) => {
items.iter().for_each(|pat| patvars(set, pat));
}
} }
} }
let mut set = Vec::new(); let mut set = Vec::new();

View File

@ -1080,7 +1080,7 @@ impl Parse<'_> for Return {
impl Parse<'_> for Pattern { impl Parse<'_> for Pattern {
fn parse(p: &mut Parser<'_>) -> PResult<Self> { fn parse(p: &mut Parser<'_>) -> PResult<Self> {
let value = prec::exprkind(p, prec::Precedence::Highest.level())?; let value = prec::exprkind(p, prec::Precedence::Pattern.level())?;
Pattern::try_from(value) Pattern::try_from(value)
.map_err(|_| p.error(ExpectedParsing { want: Parsing::Pattern }, Parsing::Pattern)) .map_err(|_| p.error(ExpectedParsing { want: Parsing::Pattern }, Parsing::Pattern))
} }

View File

@ -255,8 +255,8 @@ pub enum Precedence {
Index, Index,
Cast, Cast,
Member, // left-associative Member, // left-associative
Pattern,
Call, Call,
Highest,
} }
impl Precedence { impl Precedence {

View File

@ -438,13 +438,20 @@ pub mod yamlify {
Pattern::Struct(path, items) => { Pattern::Struct(path, items) => {
{ {
let mut y = y.key("Struct"); let mut y = y.key("Struct");
y.pair("name", path); y.yaml(path);
for (name, item) in items { for (name, item) in items {
y.pair(name, item); y.pair(name, item);
} }
} }
y y
} }
Pattern::TupleStruct(path, items) => {
{
let mut y = y.key("TupleStruct");
y.yaml(path).list(items);
}
y
}
}; };
} }
} }