October commit
- custom parser support and infra - type-tagging and traits (untested) - match expressions
This commit is contained in:
@@ -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}")?;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user