October commit

- custom parser support and infra
- type-tagging and traits (untested)
- match expressions
This commit is contained in:
2023-10-24 22:17:37 +01:00
parent c961506a3a
commit f77e4fd90a
73 changed files with 1904 additions and 558 deletions

View File

@@ -18,13 +18,20 @@ use crate::Sym;
pub struct CachedRule<M: Matcher> {
matcher: M,
pattern: Vec<RuleExpr>,
pat_glossary: HashSet<Sym>,
template: Vec<RuleExpr>,
save_location: HashSet<Sym>,
}
impl<M: Display + Matcher> Display for CachedRule<M> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let patterns = self.pattern.iter().join(" ");
write!(f, "{patterns} is matched by {}", self.matcher)
write!(
f,
"{patterns} is matched by {} and generates {}",
self.matcher,
self.template.iter().map(|e| e.to_string()).join(" ")
)
}
}
@@ -36,7 +43,7 @@ impl<M: Display + Matcher> Display for CachedRule<M> {
///
/// If you don't know what to put in the generic parameter, use [Repo]
pub struct Repository<M: Matcher> {
cache: Vec<(CachedRule<M>, HashSet<Sym>, NotNan<f64>)>,
cache: Vec<(CachedRule<M>, NotNan<f64>)>,
}
impl<M: Matcher> Repository<M> {
/// Build a new repository to hold the given set of rules
@@ -48,19 +55,27 @@ impl<M: Matcher> Repository<M> {
let cache = rules
.into_iter()
.map(|r| {
let prio = r.prio;
let rule = prepare_rule(r.clone(), i).map_err(|e| (r, e))?;
let mut glossary = HashSet::new();
for e in rule.pattern.iter() {
glossary.extend(e.value.collect_names().into_iter());
}
let matcher = M::new(Rc::new(rule.pattern.clone()));
let Rule { pattern, prio, template } =
prepare_rule(r.clone(), i).map_err(|e| (r, e))?;
let mut pat_glossary = HashSet::new();
pat_glossary.extend(
pattern.iter().flat_map(|e| e.value.collect_names().into_iter()),
);
let mut tpl_glossary = HashSet::new();
tpl_glossary.extend(
template.iter().flat_map(|e| e.value.collect_names().into_iter()),
);
let save_location =
pat_glossary.intersection(&tpl_glossary).cloned().collect();
let matcher = M::new(Rc::new(pattern.clone()));
let prep = CachedRule {
matcher,
pattern: rule.pattern,
template: rule.template,
pattern,
template,
pat_glossary,
save_location,
};
Ok((prep, glossary, prio))
Ok((prep, prio))
})
.collect::<Result<Vec<_>, _>>()?;
Ok(Self { cache })
@@ -70,12 +85,13 @@ impl<M: Matcher> Repository<M> {
#[must_use]
pub fn step(&self, code: &RuleExpr) -> Option<RuleExpr> {
let glossary = code.value.collect_names();
for (rule, deps, _) in self.cache.iter() {
if !deps.is_subset(&glossary) {
for (rule, _) in self.cache.iter() {
if !rule.pat_glossary.is_subset(&glossary) {
continue;
}
let product = update_first_seq::expr(code, &mut |exprv| {
let state = rule.matcher.apply(exprv.as_slice())?;
let save_loc = |n| rule.save_location.contains(&n);
let state = rule.matcher.apply(exprv.as_slice(), &save_loc)?;
let result = apply_exprv(&rule.template, &state);
Some(Rc::new(result))
});
@@ -142,9 +158,10 @@ impl<M: Debug + Matcher> Debug for Repository<M> {
impl<M: Display + Matcher> Display for Repository<M> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "Repository[")?;
for (rule, deps, p) in self.cache.iter() {
for (rule, p) in self.cache.iter() {
let prio = print_nat16(*p);
let deps = deps.iter().map(|t| t.extern_vec().join("::")).join(", ");
let deps =
rule.pat_glossary.iter().map(|t| t.extern_vec().join("::")).join(", ");
writeln!(f, " priority: {prio}\tdependencies: [{deps}]")?;
writeln!(f, " {rule}")?;
}