Removed a copious amount of premature Rc-s

This commit is contained in:
2023-06-18 04:22:20 +01:00
parent aebbf51228
commit 79e28883db
56 changed files with 716 additions and 636 deletions

View File

@@ -2,12 +2,15 @@ use std::rc::Rc;
use super::state::State;
use crate::ast::Expr;
use crate::Sym;
pub type RuleExpr = Expr<Sym>;
/// Cacheable optimized structures for matching patterns on slices. This is
/// injected to allow experimentation in the matcher implementation.
pub trait Matcher {
/// Build matcher for a pattern
fn new(pattern: Rc<Vec<Expr>>) -> Self;
fn new(pattern: Rc<Vec<RuleExpr>>) -> Self;
/// Apply matcher to a token sequence
fn apply<'a>(&self, source: &'a [Expr]) -> Option<State<'a>>;
fn apply<'a>(&self, source: &'a [RuleExpr]) -> Option<State<'a>>;
}

View File

@@ -1,12 +1,12 @@
use super::scal_match::scalv_match;
use super::shared::AnyMatcher;
use super::vec_match::vec_match;
use crate::ast::Expr;
use crate::rule::matcher::RuleExpr;
use crate::rule::state::State;
pub fn any_match<'a>(
matcher: &AnyMatcher,
seq: &'a [Expr],
seq: &'a [RuleExpr],
) -> Option<State<'a>> {
match matcher {
AnyMatcher::Scalar(scalv) => scalv_match(scalv, seq),

View File

@@ -1,16 +1,18 @@
use itertools::Itertools;
use super::shared::{AnyMatcher, ScalMatcher, VecMatcher};
use crate::ast::{Clause, Expr, PHClass, Placeholder};
use crate::ast::{Clause, PHClass, Placeholder};
use crate::interner::Tok;
use crate::rule::matcher::RuleExpr;
use crate::rule::vec_attrs::vec_attrs;
use crate::utils::Side;
pub type MaxVecSplit<'a> = (&'a [Expr], (Tok<String>, u64, bool), &'a [Expr]);
pub type MaxVecSplit<'a> =
(&'a [RuleExpr], (Tok<String>, u64, bool), &'a [RuleExpr]);
/// Derive the details of the central vectorial and the two sides from a
/// slice of Expr's
fn split_at_max_vec(pattern: &[Expr]) -> Option<MaxVecSplit> {
fn split_at_max_vec(pattern: &[RuleExpr]) -> Option<MaxVecSplit> {
let rngidx = pattern.iter().position_max_by_key(|expr| {
vec_attrs(expr).map(|attrs| attrs.1 as i64).unwrap_or(-1)
})?;
@@ -21,11 +23,11 @@ fn split_at_max_vec(pattern: &[Expr]) -> Option<MaxVecSplit> {
vec_attrs(placeh).map(|attrs| (left, attrs, right))
}
fn scal_cnt<'a>(iter: impl Iterator<Item = &'a Expr>) -> usize {
fn scal_cnt<'a>(iter: impl Iterator<Item = &'a RuleExpr>) -> usize {
iter.take_while(|expr| vec_attrs(expr).is_none()).count()
}
pub fn mk_any(pattern: &[Expr]) -> AnyMatcher {
pub fn mk_any(pattern: &[RuleExpr]) -> AnyMatcher {
let left_split = scal_cnt(pattern.iter());
if pattern.len() <= left_split {
return AnyMatcher::Scalar(mk_scalv(pattern));
@@ -41,12 +43,12 @@ pub fn mk_any(pattern: &[Expr]) -> AnyMatcher {
}
/// Pattern MUST NOT contain vectorial placeholders
fn mk_scalv(pattern: &[Expr]) -> Vec<ScalMatcher> {
fn mk_scalv(pattern: &[RuleExpr]) -> Vec<ScalMatcher> {
pattern.iter().map(mk_scalar).collect()
}
/// Pattern MUST start and end with a vectorial placeholder
fn mk_vec(pattern: &[Expr]) -> VecMatcher {
fn mk_vec(pattern: &[RuleExpr]) -> VecMatcher {
debug_assert!(!pattern.is_empty(), "pattern cannot be empty");
debug_assert!(
pattern.first().map(vec_attrs).is_some(),
@@ -97,7 +99,7 @@ fn mk_vec(pattern: &[Expr]) -> VecMatcher {
}
/// Pattern MUST NOT be a vectorial placeholder
fn mk_scalar(pattern: &Expr) -> ScalMatcher {
fn mk_scalar(pattern: &RuleExpr) -> ScalMatcher {
match &pattern.value {
Clause::P(p) => ScalMatcher::P(p.clone()),
Clause::Name(n) => ScalMatcher::Name(*n),

View File

@@ -1,11 +1,12 @@
use super::any_match::any_match;
use super::shared::ScalMatcher;
use crate::ast::{Clause, Expr};
use crate::ast::Clause;
use crate::rule::matcher::RuleExpr;
use crate::rule::state::{State, StateEntry};
pub fn scal_match<'a>(
matcher: &ScalMatcher,
expr: &'a Expr,
expr: &'a RuleExpr,
) -> Option<State<'a>> {
match (matcher, &expr.value) {
(ScalMatcher::P(p1), Clause::P(p2)) if p1 == p2 => Some(State::new()),
@@ -25,7 +26,7 @@ pub fn scal_match<'a>(
pub fn scalv_match<'a>(
matchers: &[ScalMatcher],
seq: &'a [Expr],
seq: &'a [RuleExpr],
) -> Option<State<'a>> {
if seq.len() != matchers.len() {
return None;

View File

@@ -3,12 +3,12 @@ use std::rc::Rc;
use super::any_match::any_match;
use super::build::mk_any;
use crate::ast::Expr;
use crate::interner::{InternedDisplay, Interner, Sym, Tok};
use crate::interner::{InternedDisplay, Interner, Tok};
use crate::representations::Primitive;
use crate::rule::matcher::Matcher;
use crate::rule::matcher::{Matcher, RuleExpr};
use crate::rule::state::State;
use crate::utils::{sym2string, unwrap_or, Side};
use crate::Sym;
pub enum ScalMatcher {
P(Primitive),
@@ -54,11 +54,11 @@ pub enum AnyMatcher {
Vec { left: Vec<ScalMatcher>, mid: VecMatcher, right: Vec<ScalMatcher> },
}
impl Matcher for AnyMatcher {
fn new(pattern: Rc<Vec<Expr>>) -> Self {
fn new(pattern: Rc<Vec<RuleExpr>>) -> Self {
mk_any(&pattern)
}
fn apply<'a>(&self, source: &'a [Expr]) -> Option<State<'a>> {
fn apply<'a>(&self, source: &'a [RuleExpr]) -> Option<State<'a>> {
any_match(self, source)
}
}
@@ -183,11 +183,11 @@ impl InternedDisplay for AnyMatcher {
/// vectorial placeholders and handles the scalars on leaves.
pub struct VectreeMatcher(AnyMatcher);
impl Matcher for VectreeMatcher {
fn new(pattern: Rc<Vec<Expr>>) -> Self {
fn new(pattern: Rc<Vec<RuleExpr>>) -> Self {
Self(AnyMatcher::new(pattern))
}
fn apply<'a>(&self, source: &'a [Expr]) -> Option<State<'a>> {
fn apply<'a>(&self, source: &'a [RuleExpr]) -> Option<State<'a>> {
self.0.apply(source)
}
}

View File

@@ -4,13 +4,13 @@ use itertools::Itertools;
use super::scal_match::scalv_match;
use super::shared::VecMatcher;
use crate::ast::Expr;
use crate::rule::matcher::RuleExpr;
use crate::rule::state::{State, StateEntry};
use crate::utils::unwrap_or;
pub fn vec_match<'a>(
matcher: &VecMatcher,
seq: &'a [Expr],
seq: &'a [RuleExpr],
) -> Option<State<'a>> {
match matcher {
VecMatcher::Placeh { key, nonzero } => {

View File

@@ -1,24 +1,24 @@
use std::rc::Rc;
use hashbrown::HashMap;
use itertools::Itertools;
use super::matcher::RuleExpr;
use super::vec_attrs::vec_attrs;
use super::RuleError;
use crate::ast::{Clause, Expr, PHClass, Placeholder, Rule};
use crate::interner::{Interner, Tok};
use crate::representations::location::Location;
use crate::Sym;
/// Ensure that the rule's source begins and ends with a vectorial without
/// changing its meaning
fn pad(mut rule: Rule, i: &Interner) -> Rule {
fn pad(mut rule: Rule<Sym>, i: &Interner) -> Rule<Sym> {
let class: PHClass = PHClass::Vec { nonzero: false, prio: 0 };
let empty: &[Expr] = &[];
let prefix: &[Expr] = &[Expr {
let empty: &[Expr<Sym>] = &[];
let prefix: &[Expr<Sym>] = &[Expr {
location: Location::Unknown,
value: Clause::Placeh(Placeholder { name: i.i("::prefix"), class }),
}];
let suffix: &[Expr] = &[Expr {
let suffix: &[Expr<Sym>] = &[Expr {
location: Location::Unknown,
value: Clause::Placeh(Placeholder { name: i.i("::suffix"), class }),
}];
@@ -28,22 +28,14 @@ fn pad(mut rule: Rule, i: &Interner) -> Rule {
let suffix_explicit = vec_attrs(rule_tail).is_some();
let prefix_v = if prefix_explicit { empty } else { prefix };
let suffix_v = if suffix_explicit { empty } else { suffix };
rule.pattern = Rc::new(
prefix_v
.iter()
.chain(rule.pattern.iter())
.chain(suffix_v.iter())
.cloned()
.collect(),
);
rule.template = Rc::new(
prefix_v
.iter()
.chain(rule.template.iter())
.chain(suffix_v.iter())
.cloned()
.collect(),
);
rule.pattern = (prefix_v.iter().cloned())
.chain(rule.pattern.into_iter())
.chain(suffix_v.iter().cloned())
.collect();
rule.template = (prefix_v.iter().cloned())
.chain(rule.template.into_iter())
.chain(suffix_v.iter().cloned())
.collect();
rule
}
@@ -62,7 +54,7 @@ impl From<PHClass> for PHType {
}
fn check_rec_expr(
expr: &Expr,
expr: &RuleExpr,
types: &mut HashMap<Tok<String>, PHType>,
in_template: bool,
) -> Result<(), RuleError> {
@@ -95,7 +87,7 @@ fn check_rec_expr(
}
fn check_rec_exprv(
exprv: &[Expr],
exprv: &[RuleExpr],
types: &mut HashMap<Tok<String>, PHType>,
in_template: bool,
) -> Result<(), RuleError> {
@@ -115,7 +107,10 @@ fn check_rec_exprv(
}
}
pub fn prepare_rule(rule: Rule, i: &Interner) -> Result<Rule, RuleError> {
pub fn prepare_rule(
rule: Rule<Sym>,
i: &Interner,
) -> Result<Rule<Sym>, RuleError> {
// Dimension check
let mut types = HashMap::new();
check_rec_exprv(&rule.pattern, &mut types, false)?;

View File

@@ -5,19 +5,20 @@ use std::rc::Rc;
use hashbrown::HashSet;
use ordered_float::NotNan;
use super::matcher::Matcher;
use super::matcher::{Matcher, RuleExpr};
use super::prepare_rule::prepare_rule;
use super::state::apply_exprv;
use super::{update_first_seq, RuleError, VectreeMatcher};
use crate::ast::{Expr, Rule};
use crate::interner::{InternedDisplay, Interner, Sym};
use crate::ast::Rule;
use crate::interner::{InternedDisplay, Interner};
use crate::utils::Substack;
use crate::Sym;
#[derive(Debug)]
pub struct CachedRule<M: Matcher> {
matcher: M,
pattern: Rc<Vec<Expr>>,
template: Rc<Vec<Expr>>,
pattern: Vec<RuleExpr>,
template: Vec<RuleExpr>,
}
impl<M: InternedDisplay + Matcher> InternedDisplay for CachedRule<M> {
@@ -48,9 +49,9 @@ pub struct Repository<M: Matcher> {
impl<M: Matcher> Repository<M> {
/// Build a new repository to hold the given set of rules
pub fn new(
mut rules: Vec<Rule>,
mut rules: Vec<Rule<Sym>>,
i: &Interner,
) -> Result<Self, (Rule, RuleError)> {
) -> Result<Self, (Rule<Sym>, RuleError)> {
rules.sort_by_key(|r| -r.prio);
let cache = rules
.into_iter()
@@ -60,10 +61,10 @@ impl<M: Matcher> Repository<M> {
let mut glossary = HashSet::new();
for e in rule.pattern.iter() {
e.visit_names(Substack::Bottom, &mut |op| {
glossary.insert(op);
glossary.insert(*op);
})
}
let matcher = M::new(rule.pattern.clone());
let matcher = M::new(Rc::new(rule.pattern.clone()));
let prep = CachedRule {
matcher,
pattern: rule.pattern,
@@ -76,10 +77,10 @@ impl<M: Matcher> Repository<M> {
}
/// Attempt to run each rule in priority order once
pub fn step(&self, code: &Expr) -> Option<Expr> {
pub fn step(&self, code: &RuleExpr) -> Option<RuleExpr> {
let mut glossary = HashSet::new();
code.visit_names(Substack::Bottom, &mut |op| {
glossary.insert(op);
glossary.insert(*op);
});
for (rule, deps, _) in self.cache.iter() {
if !deps.is_subset(&glossary) {
@@ -100,7 +101,7 @@ impl<M: Matcher> Repository<M> {
/// Keep running the matching rule with the highest priority until no
/// rules match. WARNING: this function might not terminate
#[allow(unused)]
pub fn pass(&self, code: &Expr) -> Option<Expr> {
pub fn pass(&self, code: &RuleExpr) -> Option<RuleExpr> {
if let Some(mut processed) = self.step(code) {
while let Some(out) = self.step(&processed) {
processed = out
@@ -114,7 +115,11 @@ impl<M: Matcher> Repository<M> {
/// Attempt to run each rule in priority order `limit` times. Returns
/// the final tree and the number of iterations left to the limit.
#[allow(unused)]
pub fn long_step(&self, code: &Expr, mut limit: usize) -> (Expr, usize) {
pub fn long_step(
&self,
code: &RuleExpr,
mut limit: usize,
) -> (RuleExpr, usize) {
if limit == 0 {
return (code.clone(), 0);
}

View File

@@ -3,18 +3,19 @@ use std::rc::Rc;
use hashbrown::HashMap;
use itertools::Itertools;
use super::matcher::RuleExpr;
use crate::ast::{Clause, Expr, PHClass, Placeholder};
use crate::interner::Tok;
use crate::utils::unwrap_or;
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum StateEntry<'a> {
Vec(&'a [Expr]),
Scalar(&'a Expr),
Vec(&'a [RuleExpr]),
Scalar(&'a RuleExpr),
}
pub type State<'a> = HashMap<Tok<String>, StateEntry<'a>>;
pub fn apply_exprv(template: &[Expr], state: &State) -> Vec<Expr> {
pub fn apply_exprv(template: &[RuleExpr], state: &State) -> Vec<RuleExpr> {
template
.iter()
.map(|e| apply_expr(e, state))
@@ -22,7 +23,7 @@ pub fn apply_exprv(template: &[Expr], state: &State) -> Vec<Expr> {
.collect()
}
pub fn apply_expr(template: &Expr, state: &State) -> Vec<Expr> {
pub fn apply_expr(template: &RuleExpr, state: &State) -> Vec<RuleExpr> {
let Expr { location, value } = template;
match value {
Clause::P(_) | Clause::Name(_) => vec![template.clone()],

View File

@@ -1,15 +1,17 @@
use std::rc::Rc;
use super::matcher::RuleExpr;
use crate::ast::{Clause, Expr};
use crate::utils::replace_first;
use crate::Sym;
/// Traverse the tree, calling pred on every sibling list until it returns
/// some vec then replace the sibling list with that vec and return true
/// return false if pred never returned some
pub fn exprv<F: FnMut(Rc<Vec<Expr>>) -> Option<Rc<Vec<Expr>>>>(
input: Rc<Vec<Expr>>,
pub fn exprv<F: FnMut(Rc<Vec<RuleExpr>>) -> Option<Rc<Vec<RuleExpr>>>>(
input: Rc<Vec<RuleExpr>>,
pred: &mut F,
) -> Option<Rc<Vec<Expr>>> {
) -> Option<Rc<Vec<RuleExpr>>> {
if let Some(v) = pred(input.clone()) {
return Some(v);
}
@@ -17,18 +19,18 @@ pub fn exprv<F: FnMut(Rc<Vec<Expr>>) -> Option<Rc<Vec<Expr>>>>(
.map(|i| Rc::new(i.collect()))
}
pub fn expr<F: FnMut(Rc<Vec<Expr>>) -> Option<Rc<Vec<Expr>>>>(
input: &Expr,
pub fn expr<F: FnMut(Rc<Vec<RuleExpr>>) -> Option<Rc<Vec<RuleExpr>>>>(
input: &RuleExpr,
pred: &mut F,
) -> Option<Expr> {
) -> Option<RuleExpr> {
clause(&input.value, pred)
.map(|value| Expr { value, location: input.location.clone() })
}
pub fn clause<F: FnMut(Rc<Vec<Expr>>) -> Option<Rc<Vec<Expr>>>>(
c: &Clause,
pub fn clause<F: FnMut(Rc<Vec<RuleExpr>>) -> Option<Rc<Vec<RuleExpr>>>>(
c: &Clause<Sym>,
pred: &mut F,
) -> Option<Clause> {
) -> Option<Clause<Sym>> {
match c {
Clause::P(_) | Clause::Placeh { .. } | Clause::Name { .. } => None,
Clause::Lambda(arg, body) =>

View File

@@ -1,9 +1,10 @@
use crate::ast::{Clause, Expr, PHClass, Placeholder};
use super::matcher::RuleExpr;
use crate::ast::{Clause, PHClass, Placeholder};
use crate::interner::Tok;
/// Returns the name, priority and nonzero of the expression if it is
/// a vectorial placeholder
pub fn vec_attrs(expr: &Expr) -> Option<(Tok<String>, u64, bool)> {
pub fn vec_attrs(expr: &RuleExpr) -> Option<(Tok<String>, u64, bool)> {
if let Clause::Placeh(Placeholder {
class: PHClass::Vec { prio, nonzero },
name,