forked from Orchid/orchid
Dead end with macros
This commit is contained in:
@@ -1,13 +1,16 @@
|
||||
use std::iter;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use mappable_rc::Mrc;
|
||||
|
||||
use crate::unwrap_or;
|
||||
use crate::utils::{to_mrc_slice, one_mrc_slice, mrc_empty_slice};
|
||||
use crate::utils::{to_mrc_slice, one_mrc_slice, mrc_empty_slice, replace_first};
|
||||
use crate::utils::iter::{box_once, into_boxed_iter};
|
||||
use crate::ast::{Expr, Clause};
|
||||
use super::slice_matcher::SliceMatcherDnC;
|
||||
use super::state::{State, Entry};
|
||||
use super::super::RuleError;
|
||||
use super::update_first_seq_rec;
|
||||
|
||||
fn verify_scalar_vec(pattern: &Expr, is_vec: &mut HashMap<String, bool>)
|
||||
-> Result<(), String> {
|
||||
@@ -62,30 +65,12 @@ fn slice_to_vec(src: &mut Mrc<[Expr]>, tgt: &mut Mrc<[Expr]>) {
|
||||
*tgt = to_mrc_slice(prefix_vec.iter().chain(tgt.iter()).chain(postfix_vec.iter()).cloned().collect());
|
||||
}
|
||||
|
||||
/// 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
|
||||
fn update_first_seq_rec<F>(input: Mrc<[Expr]>, pred: &mut F) -> Option<Mrc<[Expr]>>
|
||||
where F: FnMut(Mrc<[Expr]>) -> Option<Mrc<[Expr]>> {
|
||||
if let o@Some(_) = pred(Mrc::clone(&input)) {o} else {
|
||||
for Expr(cls, _) in input.iter() {
|
||||
if let Some(t) = cls.typ() {
|
||||
if let o@Some(_) = update_first_seq_rec(t, pred) {return o}
|
||||
}
|
||||
if let Some(b) = cls.body() {
|
||||
if let o@Some(_) = update_first_seq_rec(b, pred) {return o}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// keep re-probing the input with pred until it stops matching
|
||||
fn update_all_seqs<F>(input: Mrc<[Expr]>, pred: &mut F) -> Option<Mrc<[Expr]>>
|
||||
where F: FnMut(Mrc<[Expr]>) -> Option<Mrc<[Expr]>> {
|
||||
let mut tmp = update_first_seq_rec(input, pred);
|
||||
let mut tmp = update_first_seq_rec::exprv(input, pred);
|
||||
while let Some(xv) = tmp {
|
||||
tmp = update_first_seq_rec(Mrc::clone(&xv), pred);
|
||||
tmp = update_first_seq_rec::exprv(Mrc::clone(&xv), pred);
|
||||
if tmp.is_none() {return Some(xv)}
|
||||
}
|
||||
None
|
||||
@@ -151,14 +136,12 @@ fn write_expr_rec(state: &State, Expr(tpl_clause, tpl_typ): &Expr) -> Box<dyn It
|
||||
)).into_expr())
|
||||
},
|
||||
// Explicit base case so that we get an error if Clause gets new values
|
||||
c@Clause::Literal(_) | c@Clause::Name { .. } | c@Clause::ExternFn(_) | c@Clause::Atom(_) =>
|
||||
box_once(Expr(c.to_owned(), out_typ.to_owned()))
|
||||
c@Clause::P(_) | c@Clause::Name { .. } => box_once(Expr(c.to_owned(), out_typ.to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Fill in a template from a state as produced by a pattern
|
||||
fn write_slice_rec(state: &State, tpl: &Mrc<[Expr]>) -> Mrc<[Expr]> {
|
||||
eprintln!("Writing {tpl:?} with state {state:?}");
|
||||
tpl.iter().flat_map(|xpr| write_expr_rec(state, xpr)).collect()
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ mod slice_matcher;
|
||||
mod state;
|
||||
mod execute;
|
||||
mod split_at_max_vec;
|
||||
mod update_first_seq_rec;
|
||||
|
||||
use state::State;
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ impl SliceMatcherDnC {
|
||||
+ self.apply_side_with_cache(Side::Right, mrc_derive(&target, |t| &t[pos+1..]), cache)
|
||||
)?;
|
||||
match (self.clause.as_ref(), &target.as_ref()[pos].0) {
|
||||
(Clause::Literal(val), Clause::Literal(tgt)) => {
|
||||
(Clause::P(val), Clause::P(tgt)) => {
|
||||
if val == tgt {Some(own_state)} else {None}
|
||||
}
|
||||
(Clause::Placeh{key, vec: None}, tgt_clause) => {
|
||||
|
||||
53
src/rule/executor/update_first_seq_rec.rs
Normal file
53
src/rule/executor/update_first_seq_rec.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
use mappable_rc::Mrc;
|
||||
|
||||
use crate::{ast::{Expr, Clause}, utils::{replace_first, to_mrc_slice}};
|
||||
|
||||
/// 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>(input: Mrc<[Expr]>, pred: &mut F) -> Option<Mrc<[Expr]>>
|
||||
where F: FnMut(Mrc<[Expr]>) -> Option<Mrc<[Expr]>> {
|
||||
if let o@Some(_) = pred(Mrc::clone(&input)) {return o}
|
||||
replace_first(input.as_ref(), |ex| expr(ex, pred))
|
||||
.map(|i| to_mrc_slice(i.collect()))
|
||||
}
|
||||
|
||||
pub fn expr<F>(Expr(cls, typ): &Expr, pred: &mut F) -> Option<Expr>
|
||||
where F: FnMut(Mrc<[Expr]>) -> Option<Mrc<[Expr]>> {
|
||||
if let Some(t) = clausev(Mrc::clone(typ), pred) {return Some(Expr(cls.clone(), t))}
|
||||
if let Some(c) = clause(cls, pred) {return Some(Expr(c, Mrc::clone(typ)))}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn clausev<F>(input: Mrc<[Clause]>, pred: &mut F) -> Option<Mrc<[Clause]>>
|
||||
where F: FnMut(Mrc<[Expr]>) -> Option<Mrc<[Expr]>> {
|
||||
replace_first(input.as_ref(), |c| clause(c, pred))
|
||||
.map(|i| to_mrc_slice(i.collect()))
|
||||
}
|
||||
|
||||
pub fn clause<F>(c: &Clause, pred: &mut F) -> Option<Clause>
|
||||
where F: FnMut(Mrc<[Expr]>) -> Option<Mrc<[Expr]>> {
|
||||
match c {
|
||||
Clause::P(_) | Clause::Placeh {..} | Clause::Name {..} => None,
|
||||
Clause::Lambda(n, typ, body) => {
|
||||
if let Some(b) = exprv(Mrc::clone(body), pred) {
|
||||
return Some(Clause::Lambda(n.clone(), Mrc::clone(typ), b))
|
||||
}
|
||||
if let Some(t) = exprv(Mrc::clone(typ), pred) {
|
||||
return Some(Clause::Lambda(n.clone(), t, Mrc::clone(body)))
|
||||
}
|
||||
None
|
||||
}
|
||||
Clause::Auto(n, typ, body) => {
|
||||
if let Some(b) = exprv(Mrc::clone(body), pred) {
|
||||
return Some(Clause::Auto(n.clone(), Mrc::clone(typ), b))
|
||||
}
|
||||
if let Some(t) = exprv(Mrc::clone(typ), pred) {
|
||||
return Some(Clause::Auto(n.clone(), t, Mrc::clone(body)))
|
||||
}
|
||||
None
|
||||
}
|
||||
Clause::S(c, body) => Some(Clause::S(*c, exprv(Mrc::clone(body), pred)?)),
|
||||
Clause::Explicit(t) => Some(Clause::Explicit(Mrc::new(expr(t, pred)?)))
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,22 @@ use super::{super::ast::Rule, executor::execute, RuleError};
|
||||
pub struct Repository(Vec<Rule>);
|
||||
impl Repository {
|
||||
pub fn new(mut rules: Vec<Rule>) -> Self {
|
||||
rules.sort_by_key(|r| r.prio);
|
||||
rules.sort_by_key(|r| -r.prio);
|
||||
Self(rules)
|
||||
}
|
||||
|
||||
pub fn step(&self, code: Mrc<[Expr]>) -> Result<Option<Mrc<[Expr]>>, RuleError> {
|
||||
for rule in self.0.iter() {
|
||||
if let Some(out) = execute(
|
||||
Mrc::clone(&rule.source), Mrc::clone(&rule.target),
|
||||
Mrc::clone(&code)
|
||||
)? {return Ok(Some(out))}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Attempt to run each rule in priority order once
|
||||
pub fn step(&self, mut code: Mrc<[Expr]>) -> Result<Option<Mrc<[Expr]>>, RuleError> {
|
||||
pub fn pass(&self, mut code: Mrc<[Expr]>) -> Result<Option<Mrc<[Expr]>>, RuleError> {
|
||||
let mut ran_once = false;
|
||||
for rule in self.0.iter() {
|
||||
if let Some(tmp) = execute(
|
||||
@@ -33,7 +43,7 @@ impl Repository {
|
||||
/// tree and the number of iterations left to the limit.
|
||||
pub fn long_step(&self, mut code: Mrc<[Expr]>, mut limit: usize)
|
||||
-> Result<(Mrc<[Expr]>, usize), RuleError> {
|
||||
while let Some(tmp) = self.step(Mrc::clone(&code))? {
|
||||
while let Some(tmp) = self.pass(Mrc::clone(&code))? {
|
||||
if 0 >= limit {break}
|
||||
limit -= 1;
|
||||
code = tmp
|
||||
|
||||
Reference in New Issue
Block a user