forked from Orchid/orchid
Removed a copious amount of premature Rc-s
This commit is contained in:
@@ -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>>;
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 } => {
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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()],
|
||||
|
||||
@@ -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) =>
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user