diff --git a/src/project/rule_collector.rs b/src/project/rule_collector.rs index 1a8902e..a9db930 100644 --- a/src/project/rule_collector.rs +++ b/src/project/rule_collector.rs @@ -26,7 +26,7 @@ pub struct Module { pub type RuleCollectionResult = Result, ModuleError>; pub fn rule_collector( - mut load_mod: F, + load_mod: F, prelude: Vec ) -> Cache<'static, Mrc<[String]>, RuleCollectionResult> where @@ -131,7 +131,7 @@ where } else { Err(ModuleError::None) } } })); - let mut name_resolver_rc = RefCell::new(NameResolver::new({ + let name_resolver_rc = RefCell::new(NameResolver::new({ let modname = Rc::clone(&modname); move |path| { Some(modname.try_find(&path).ok()?.as_ref().clone()) diff --git a/src/rule/executor/execute.rs b/src/rule/executor/execute.rs index 5ec399f..c1d06bc 100644 --- a/src/rule/executor/execute.rs +++ b/src/rule/executor/execute.rs @@ -1,7 +1,7 @@ use hashbrown::HashMap; use mappable_rc::Mrc; -use crate::{expression::{Expr, Clause}, utils::{iter::{box_once, into_boxed_iter}, to_mrc_slice}}; +use crate::{expression::{Expr, Clause}, utils::{iter::{box_once, into_boxed_iter}, to_mrc_slice, one_mrc_slice}}; use super::{super::RuleError, state::{State, Entry}, slice_matcher::SliceMatcherDnC}; fn verify_scalar_vec(pattern: &Expr, is_vec: &mut HashMap) @@ -92,12 +92,14 @@ fn write_slice(state: &State, tpl: &Mrc<[Expr]>) -> Mrc<[Expr]> { tpl.iter().flat_map(|Expr(clause, xpr_typ)| match clause { Clause::Auto(name_opt, typ, body) => box_once(Expr(Clause::Auto( name_opt.as_ref().and_then(|name| { - let state_key = name.strip_prefix('$') - .expect("Auto template may only reference, never enforce the name"); - match &state[state_key] { - Entry::NameOpt(name) => name.as_ref().map(|s| s.as_ref().to_owned()), - Entry::Name(name) => Some(name.as_ref().to_owned()), - _ => panic!("Auto template name may only be derived from Auto or Lambda name") + if let Some(state_key) = name.strip_prefix('$') { + match &state[state_key] { + Entry::NameOpt(name) => name.as_ref().map(|s| s.as_ref().to_owned()), + Entry::Name(name) => Some(name.as_ref().to_owned()), + _ => panic!("Auto template name may only be derived from Auto or Lambda name") + } + } else { + Some(name.to_owned()) } }), write_slice(state, typ), @@ -118,9 +120,17 @@ fn write_slice(state: &State, tpl: &Mrc<[Expr]>) -> Mrc<[Expr]> { *c, write_slice(state, body) ), xpr_typ.to_owned())), - Clause::Placeh{key, vec: None} => if let Entry::Scalar(x) = &state[key] { - box_once(x.as_ref().to_owned()) - } else {panic!("Scalar template may only be derived from scalar placeholder")}, + Clause::Placeh{key, vec: None} => { + let real_key = if let Some(real_key) = key.strip_prefix('_') {real_key} else {key}; + match &state[real_key] { + Entry::Scalar(x) => box_once(x.as_ref().to_owned()), + Entry::Name(n) => box_once(Expr(Clause::Name { + local: Some(n.as_ref().to_owned()), + qualified: one_mrc_slice(n.as_ref().to_owned()) + }, None)), + _ => panic!("Scalar template may only be derived from scalar placeholder"), + } + }, Clause::Placeh{key, vec: Some(_)} => if let Entry::Vec(v) = &state[key] { into_boxed_iter(v.as_ref().to_owned()) } else {panic!("Vectorial template may only be derived from vectorial placeholder")}, diff --git a/src/rule/executor/slice_matcher.rs b/src/rule/executor/slice_matcher.rs index 0d0bd34..a85bcd8 100644 --- a/src/rule/executor/slice_matcher.rs +++ b/src/rule/executor/slice_matcher.rs @@ -217,8 +217,12 @@ impl SliceMatcherDnC { (Clause::Literal(val), Clause::Literal(tgt)) => { if val == tgt {Some(own_state)} else {None} } - (Clause::Placeh{key, vec: None}, _) => { - own_state.insert_scalar(&key, &target[pos]) + (Clause::Placeh{key, vec: None}, tgt_clause) => { + if let Some(real_key) = key.strip_prefix('_') { + if let Clause::Name { local: Some(value), .. } = tgt_clause { + own_state.insert_name(real_key, value) + } else {None} + } else {own_state.insert_scalar(&key, &target[pos])} } (Clause::S(c, _), Clause::S(c_tgt, body_range)) => { if c != c_tgt {return None} @@ -257,12 +261,10 @@ impl SliceMatcherDnC { // Step through valid slicings based on reported size constraints in order // from longest own section to shortest and from left to right for (left, own, right) in self.valid_subdivisions(target) { - let sides_result = unwrap_or_continue!( - self.apply_side_with_cache(Side::Left, left, cache) - ) + self.apply_side_with_cache(Side::Right, right, cache); return Some(unwrap_or_continue!( - unwrap_or_continue!(sides_result) - .insert_vec(name, own.as_ref()) + self.apply_side_with_cache(Side::Left, left, cache) + .and_then(|lres| lres + self.apply_side_with_cache(Side::Right, right, cache)) + .and_then(|side_res| side_res.insert_vec(name, own.as_ref())) )) } None @@ -276,11 +278,10 @@ impl SliceMatcherDnC { if self.pattern.is_empty() { return if target.is_empty() {Some(State::new())} else {None} } - match self.clause.as_ref() { - Clause::Placeh{key, vec: Some(_)} => - self.match_range_vectorial_cached(key, target, cache), - _ => self.match_range_scalar_cached(target, cache) - } + if self.clause_is_vectorial() { + let key = self.state_key().expect("Vectorial implies key"); + self.match_range_vectorial_cached(key, target, cache) + } else {self.match_range_scalar_cached(target, cache)} } pub fn get_matcher_cache<'a>() diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 8d7b491..fd0fdba 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -4,6 +4,7 @@ mod side; mod merge_sorted; mod unwrap_or_continue; pub mod iter; + pub use cache::Cache; use mappable_rc::Mrc; pub use substack::Stackframe; @@ -32,3 +33,7 @@ pub fn collect_to_mrc(iter: I) -> Mrc<[I::Item]> where I: Iterator { pub fn mrc_derive_slice(mv: &Mrc>) -> Mrc<[T]> { mrc_derive(mv, |v| v.as_slice()) } + +pub fn one_mrc_slice(t: T) -> Mrc<[T]> { + Mrc::map(Mrc::new([t; 1]), |v| v.as_slice()) +}