use std::borrow::Borrow;
use std::cell::RefCell;
use std::collections::{HashMap, HashSet, VecDeque};
use std::fmt::{Debug, Error, Formatter};
use std::hash::{Hash, Hasher};
use std::rc::Rc;
use generational_arena::{Arena, Index};
use indextree::{Arena as TreeArena, NodeId as TreeIndex};
use phreak_facts::{FactCore, Facts};
use phreak_rules::ProductionCallback;
use crate::jointest::*;
use crate::memory::*;
use crate::segment::Segment;
pub(crate) type ClassNodeId = String;
pub(crate) type AlphaNodeId = Index;
pub(crate) type BetaNodeId = TreeIndex;
pub(crate) type SegmentId = TreeIndex;
pub(crate) type TokenId = TreeIndex;
#[derive(Clone)]
pub enum Action {
InsertFact(Rc<FactCore>),
DeleteFact(Rc<FactCore>),
InsertToken(TokenId),
DeleteToken(TokenId),
DeleteChildToken(TokenId, TokenId),
}
impl Debug for Action {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
match self {
Action::InsertFact(rc) => {
write!(f, "InsertFact({},{},{})", &*rc.0, &*rc.1, &*rc.2)
}
Action::DeleteFact(rc) => {
write!(f, "DeleteFact({},{},{})", &*rc.0, &*rc.1, &*rc.2)
}
Action::InsertToken(id) => {
write!(f, "InsertToken({:?})", id)
}
Action::DeleteToken(id) => {
write!(f, "DeleteToken({:?})", id)
}
Action::DeleteChildToken(parent, id) => {
write!(f, "DeleteChildToken({:?}, {:?})", parent, id)
}
}
}
}
#[derive(Debug)]
pub(crate) enum StackAction {
ProcessClassNode(ClassNodeId),
ProcessAlphaNode(AlphaNodeId),
ProcessBetaNode(BetaNodeId),
ProcessSegment(SegmentId),
}
#[derive(Debug)]
pub(crate) struct ClassNode {
pub(crate) alphanodes: HashMap<WmeMatch, AlphaNodeId>,
}
impl ClassNode {
pub(crate) fn new() -> ClassNode {
ClassNode { alphanodes: HashMap::new() }
}
pub(crate) fn add_facts(&self, facts: &Facts, alphanodes: &Arena<AlphaNode>) -> HashSet<AlphaNodeId> {
let mut mutated = HashSet::new();
for fact in facts.iter_attrs() {
let mut wme = WmeMatch::new(Memory::Any, Memory::Value(fact.1.to_string()), Memory::Any);
self.alphanodes.get(&wme).and_then(
|index| alphanodes.get(*index).and_then(
|node| {
node.add_fact(fact);
mutated.insert(*index);
Some(())
}
)
);
wme.f2 = Memory::Any;
self.alphanodes.get(&wme).and_then(
|index| alphanodes.get(*index).and_then(
|node| {
node.add_fact(fact);
mutated.insert(*index);
Some(())
}
)
);
wme.f1 = Memory::Value(fact.0.to_string());
self.alphanodes.get(&wme).and_then(
|index| alphanodes.get(*index).and_then(
|node| {
node.add_fact(fact);
mutated.insert(*index);
Some(())
}
)
);
wme.f2 = Memory::Value(fact.1.to_string());
self.alphanodes.get(&wme).and_then(
|index| alphanodes.get(*index).and_then(
|node| {
node.add_fact(fact);
mutated.insert(*index);
Some(())
}
)
);
wme.f3 = Memory::Value(fact.2.to_string());
self.alphanodes.get(&wme).and_then(
|index| alphanodes.get(*index).and_then(
|node| {
node.add_fact(fact);
mutated.insert(*index);
Some(())
}
)
);
wme.f1 = Memory::Any;
self.alphanodes.get(&wme).and_then(
|index| alphanodes.get(*index).and_then(
|node| {
node.add_fact(fact);
mutated.insert(*index);
Some(())
}
)
);
wme.f2 = Memory::Any;
self.alphanodes.get(&wme).and_then(
|index| alphanodes.get(*index).and_then(
|node| {
node.add_fact(fact);
mutated.insert(*index);
Some(())
}
)
);
wme.f1 = Memory::Value(fact.0.to_string());
self.alphanodes.get(&wme).and_then(
|index| alphanodes.get(*index).and_then(
|node| {
node.add_fact(fact);
mutated.insert(*index);
Some(())
}
)
);
}
mutated
}
pub(crate) fn remove_facts(&self, facts: &Facts, alphanodes: &Arena<AlphaNode>) -> HashSet<AlphaNodeId> {
let mut mutated = HashSet::new();
for fact in facts.iter_attrs() {
let mut wme = WmeMatch::new(Memory::Any, Memory::Value(fact.1.to_string()), Memory::Any);
self.alphanodes.get(&wme).and_then(
|index| alphanodes.get(*index).and_then(
|node| {
node.remove_fact(fact);
mutated.insert(*index);
Some(())
}
)
);
wme.f2 = Memory::Any;
self.alphanodes.get(&wme).and_then(
|index| alphanodes.get(*index).and_then(
|node| {
node.remove_fact(fact);
mutated.insert(*index);
Some(())
}
)
);
wme.f1 = Memory::Value(fact.0.to_string());
self.alphanodes.get(&wme).and_then(
|index| alphanodes.get(*index).and_then(
|node| {
node.remove_fact(fact);
mutated.insert(*index);
Some(())
}
)
);
wme.f2 = Memory::Value(fact.1.to_string());
self.alphanodes.get(&wme).and_then(
|index| alphanodes.get(*index).and_then(
|node| {
node.remove_fact(fact);
mutated.insert(*index);
Some(())
}
)
);
wme.f3 = Memory::Value(fact.2.to_string());
self.alphanodes.get(&wme).and_then(
|index| alphanodes.get(*index).and_then(
|node| {
node.remove_fact(fact);
mutated.insert(*index);
Some(())
}
)
);
wme.f1 = Memory::Any;
self.alphanodes.get(&wme).and_then(
|index| alphanodes.get(*index).and_then(
|node| {
node.remove_fact(fact);
mutated.insert(*index);
Some(())
}
)
);
wme.f2 = Memory::Any;
self.alphanodes.get(&wme).and_then(
|index| alphanodes.get(*index).and_then(
|node| {
node.remove_fact(fact);
mutated.insert(*index);
Some(())
}
)
);
wme.f1 = Memory::Value(fact.0.to_string());
self.alphanodes.get(&wme).and_then(
|index| alphanodes.get(*index).and_then(
|node| {
node.remove_fact(fact);
mutated.insert(*index);
Some(())
}
)
);
}
mutated
}
}
#[derive(Debug)]
pub(crate) struct AlphaNode {
pub(crate) children: VecDeque<BetaNodeId>,
pub(crate) cell: RefCell<AlphaNodeCell>,
}
pub(crate) struct AlphaNodeCell {
pub(crate) scheduled_actions: Vec<Action>,
pub(crate) items: HashSet<Item>,
}
pub(crate) struct Item {
data: Rc<FactCore>
}
impl Item {
fn new(data: Rc<FactCore>) -> Self { Item { data } }
fn borrow(&self) -> &FactCore {
self.data.borrow()
}
}
impl Hash for Item {
fn hash<H: Hasher>(&self, state: &mut H) {
let data: &FactCore = &*self.data.borrow();
data.0.as_bytes().hash(state);
data.1.as_bytes().hash(state);
data.2.as_bytes().hash(state);
}
}
impl PartialEq for Item {
fn eq(&self, other: &Self) -> bool {
let left: &FactCore = &*self.data.borrow();
let right: &FactCore = &*other.data.borrow();
left.0.as_bytes() == right.0.as_bytes() &&
left.1.as_bytes() == right.1.as_bytes() &&
left.2.as_bytes() == right.2.as_bytes()
}
}
impl Eq for Item {}
impl Debug for Item {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
let data: &FactCore = &*self.data.borrow();
write!(f, "Item{{ {}, {}, {} }}", data.0.to_string(), data.1.to_string(), data.2.to_string())
}
}
impl AlphaNode {
pub(crate) fn new() -> AlphaNode {
AlphaNode { children: VecDeque::new(), cell: RefCell::new(AlphaNodeCell { scheduled_actions: vec![], items: HashSet::new() }) }
}
pub(crate) fn add_fact(&self, fact: &Rc<FactCore>) {
self.cell.borrow_mut().scheduled_actions.push(
Action::InsertFact(fact.clone()));
}
pub(crate) fn remove_fact(&self, fact: &Rc<FactCore>) {
self.cell.borrow_mut().scheduled_actions.push(
Action::DeleteFact(fact.clone()));
}
pub(crate) fn process_pending(&self, betanodes: &TreeArena<BetaNode>, segments: &TreeArena<Segment>) {
let cell = &mut *self.cell.borrow_mut();
let mut from_empty_to_nonempty = false;
let mut from_nonempty_to_empty = false;
for action in cell.scheduled_actions.iter() {
match action {
Action::InsertFact(fact) => {
if cell.items.is_empty() { from_empty_to_nonempty = true; }
cell.items.insert(Item::new(fact.clone()));
}
Action::DeleteFact(fact) => {
let item = Item::new(fact.clone());
cell.items.remove(&item);
println!("deleted");
if cell.items.is_empty() {
from_nonempty_to_empty = true;
}
}
_ => { unimplemented!() }
}
}
for action in cell.scheduled_actions.iter() {
println!("Process {:?}", action);
for child in self.children.iter() {
let node = betanodes.get(*child).unwrap().get();
let segment = segments[node.get_segment()].get();
if from_empty_to_nonempty {
segment.set_linked_and_modified(*child, true, true);
} else if from_nonempty_to_empty {
segment.set_linked_and_modified(*child, false, true);
} else {
segment.set_modified(*child, true);
}
node.schedule_action((*action).clone());
}
}
cell.scheduled_actions.clear();
}
}
impl Debug for AlphaNodeCell {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
write!(f, "AlphaNodeCell{{ {:?}, size_of_items: {} }}", self.scheduled_actions, self.items.len())
}
}
#[derive(Debug)]
pub(crate) enum BetaNode {
RootNode(RootNodeData),
MemoryNode(MemoryNodeData),
JoinNode(JoinNodeData),
NegativeNode(),
NccNode(),
NccPartnerNode(),
ProductionNode(ProductionNodeData),
QueryNode(),
}
impl BetaNode {
pub(crate) fn new_rootnode(segment: SegmentId) -> BetaNode {
let r = BetaNode::RootNode(RootNodeData {
segment,
root_token: None,
});
r
}
pub(crate) fn new_memorynode(segment: SegmentId) -> BetaNode {
BetaNode::MemoryNode(MemoryNodeData {
segment,
cell: RefCell::new(
MemoryNodeCell { scheduled_actions: vec![], tokens: VecDeque::new() }
),
})
}
pub(crate) fn new_joinnode(amem: AlphaNodeId, tests: Vec<JoinNodeTest>, segment: SegmentId) -> BetaNode {
BetaNode::JoinNode(JoinNodeData { amem, tests, segment, cell: RefCell::new(JoinNodeCell { scheduled_actions: vec![] }) })
}
pub(crate) fn new_negativenode() -> BetaNode {
BetaNode::NegativeNode()
}
pub(crate) fn new_nccnode() -> BetaNode {
BetaNode::NccNode()
}
pub(crate) fn new_nccpartnernode() -> BetaNode {
BetaNode::NccPartnerNode()
}
pub(crate) fn new_productionnode(segment: SegmentId, callback: Box<dyn ProductionCallback>) -> BetaNode {
BetaNode::ProductionNode(ProductionNodeData { segment, callback, cell: RefCell::new(ProductionNodeCell { scheduled_actions: vec![] }) })
}
pub(crate) fn new_querynode() -> BetaNode {
BetaNode::QueryNode()
}
}
impl BetaNode {
pub(crate) fn set_root_token(&mut self, root_token: TokenId) {
match self {
BetaNode::RootNode(rn) => {
debug_assert_eq!(rn.root_token, None);
rn.root_token = Some(root_token);
}
_ => { panic!("invalid use of set_root_token"); }
}
}
}
impl BetaNode {
pub(crate) fn get_segment(&self) -> SegmentId {
match self {
BetaNode::RootNode(data) => { data.segment }
BetaNode::MemoryNode(data) => { data.segment }
BetaNode::JoinNode(data) => { data.segment }
BetaNode::ProductionNode(data) => { data.segment }
_ => {
unimplemented!()
}
}
}
#[inline]
pub(crate) fn is_rootnode(&self) -> bool {
match self {
BetaNode::RootNode(_) => true,
_ => false,
}
}
#[inline]
pub(crate) fn is_memorynode(&self) -> bool {
match self {
BetaNode::MemoryNode(_) => true,
_ => false,
}
}
#[inline]
pub(crate) fn is_joinnode(&self) -> bool {
match self {
BetaNode::JoinNode(_) => true,
_ => false,
}
}
#[inline]
pub(crate) fn is_negativenode(&self) -> bool {
match self {
BetaNode::NegativeNode() => true,
_ => false,
}
}
#[inline]
pub(crate) fn is_nccnode(&self) -> bool {
match self {
BetaNode::NccNode() => true,
_ => false,
}
}
#[inline]
pub(crate) fn is_nccpartnernode(&self) -> bool {
match self {
BetaNode::NccPartnerNode() => true,
_ => false,
}
}
#[inline]
pub(crate) fn is_productionnode(&self) -> bool {
match self {
BetaNode::ProductionNode(_) => true,
_ => false,
}
}
#[inline]
pub(crate) fn is_querynode(&self) -> bool {
match self {
BetaNode::QueryNode() => true,
_ => false,
}
}
}
impl BetaNode {
fn schedule_action(&self, action: Action) {
match self {
BetaNode::RootNode(_) => { panic!("Cant push action to rootnode, {:?} {:?}", &self, action); }
BetaNode::MemoryNode(d) => { d.cell.borrow_mut().scheduled_actions.push(action); }
BetaNode::JoinNode(d) => { d.cell.borrow_mut().scheduled_actions.push(action); }
BetaNode::ProductionNode(d) => { d.cell.borrow_mut().scheduled_actions.push(action); }
_ => { unimplemented!() }
}
}
pub(crate) fn process_actions(&self,
self_id: BetaNodeId,
alphanodes: &Arena<AlphaNode>,
betanodes: &TreeArena<BetaNode>,
segments: &TreeArena<Segment>,
tokens: &mut TreeArena<Token>,
) {
println!("Process actions in node {:?} {:?}", self_id, self);
match self {
BetaNode::RootNode(_d) => {}
BetaNode::JoinNode(d) => {
let cellref = &mut *d.cell.borrow_mut();
let mut ignore = HashSet::with_capacity(cellref.scheduled_actions.capacity());
for action in cellref.scheduled_actions.iter() {
match action {
Action::InsertToken(token_id) => {
ignore.insert(token_id.clone());
}
_ => {}
}
}
for action in cellref.scheduled_actions.iter() {
println!("BetaNode::JoinNode {:?}", action);
println!("BetaNode::JoinNode {:?}", self_id);
println!("BetaNode::JoinNode {:?}", betanodes[self_id]);
match action {
Action::InsertFact(rc) => {
let fact = &**rc;
let parent = betanodes[betanodes[self_id].parent().unwrap()].get();
match parent {
BetaNode::RootNode(rn) => {
println!("--- {:?}", tokens[rn.root_token.unwrap()]);
for child in self_id.children(betanodes) {
let new = tokens.new_node(
Token::new(rc.clone(), child)
);
rn.root_token.unwrap().prepend(new, tokens);
let bn = betanodes.get(child).unwrap().get();
bn.schedule_action(
Action::InsertToken(new)
);
segments[bn.get_segment()].get().set_modified(child, true);
}
}
BetaNode::MemoryNode(mn) => {
println!("--- {:?}", &mn.cell.borrow().tokens);
for token in mn.cell.borrow().tokens.iter() {
if ignore.contains(token) {
continue;
}
let mut success = true;
println!("test token {} against ({}, {}, {})", print_token(*token, &tokens), &*fact.0, &*fact.1, &*fact.2);
for test in d.tests.iter() {
success &= execute_join_test(token, test, fact, tokens);
if !success { break; }
}
if success {
println!("MATCH {:?}", print_token(*token, &tokens));
for child in self_id.children(betanodes) {
let new = tokens.new_node(
Token::new(rc.clone(), child)
);
token.prepend(new, tokens);
let bn = betanodes.get(child).unwrap().get();
bn.schedule_action(
Action::InsertToken(new)
);
segments[bn.get_segment()].get().set_modified(child, true);
}
}
}
}
_ => { unreachable!() }
};
}
Action::DeleteFact(rc) => {
let parent = betanodes[betanodes[self_id].parent().unwrap()].get();
match parent {
BetaNode::RootNode(rn) => {
for child in rn.root_token.unwrap().children(tokens) {
let token: &Token = tokens[child].borrow().get();
if Rc::ptr_eq(&token.fact, rc) {
println!("delete child token from root");
betanodes[token.owner].borrow().get()
.schedule_action(Action::DeleteToken(child));
}
}
}
BetaNode::MemoryNode(mn) => {
for child in mn.cell.borrow().tokens.iter() {
let token: &Token = tokens[*child].borrow().get();
if Rc::ptr_eq(&token.fact, rc) {
println!("delete child token from betamemory");
betanodes[token.owner].borrow().get()
.schedule_action(Action::DeleteToken(*child));
}
}
}
_ => { unreachable!(); }
}
}
Action::InsertToken(token) => {
let amem = &alphanodes[d.amem];
let cell = amem.cell.borrow();
for fact in cell.items.iter() {
let mut success = true;
let f: &FactCore = &*fact.data.borrow();
println!("test token {} against ({}, {}, {})", print_token(*token, &tokens), &*f.0, &*f.1, &*f.2);
for test in d.tests.iter() {
success &= execute_join_test(token, test, fact.data.borrow(), tokens);
if !success { break; }
}
if success {
println!("MATCH {:?}", print_token(*token, &tokens));
for child in self_id.children(betanodes) {
let new = tokens.new_node(
Token::new(fact.data.clone(), child)
);
token.prepend(new, tokens);
let bn = betanodes.get(child).unwrap().get();
bn.schedule_action(
Action::InsertToken(new)
);
segments[bn.get_segment()].get().set_modified(child, true);
}
}
}
}
Action::DeleteToken(token_id) => { unreachable!() }
Action::DeleteChildToken(parent_id, sub_id) => {
unreachable!()
}
}
}
cellref.scheduled_actions.clear();
segments[self.get_segment()].get().set_modified(self_id, false);
}
BetaNode::MemoryNode(d) => {
{
let mut cell = d.cell.borrow_mut();
let cellref = &mut *cell;
for action in cellref.scheduled_actions.iter() {
println!("BetaNode::MemoryNode {:?}", action);
match action {
Action::InsertToken(token_id) => {
cellref.tokens.push_front(*token_id);
for child in self_id.children(betanodes) {
let bn = betanodes.get(child).unwrap().get();
bn.schedule_action(
Action::InsertToken(*token_id)
);
segments[bn.get_segment()].get().set_modified(child, true);
}
}
Action::DeleteToken(token_id) => {
let pos = cellref.tokens.iter()
.position(|element| element == token_id)
.expect("Token was expected in this list");
cellref.tokens.remove(pos);
for child in token_id.children(tokens) {
let child_token = tokens.get(child).unwrap().get();
let bn = betanodes.get(child_token.owner).unwrap().get();
bn.schedule_action(Action::DeleteChildToken(*token_id, child));
}
}
Action::DeleteChildToken(parent_id, sub_id) => {
let pos = cellref.tokens.iter()
.position(|element| element == sub_id)
.expect("Token was expected in this list");
cellref.tokens.remove(pos);
for child in sub_id.children(tokens) {
let child_token = tokens.get(child).unwrap().get();
let bn = betanodes.get(child_token.owner).unwrap().get();
bn.schedule_action(Action::DeleteChildToken(*parent_id, child));
}
}
_ => { unimplemented!() }
}
}
cellref.scheduled_actions.clear();
segments[self.get_segment()].get().set_modified(self_id, false);
}
}
BetaNode::ProductionNode(d) => {
let cellref = &mut *d.cell.borrow_mut();
for action in cellref.scheduled_actions.iter() {
match action {
Action::InsertFact(_) => {
println!("Production ACTIVATED {:?} by {:?}", d, action);
d.callback.activate();
}
Action::DeleteFact(_) => { unreachable!("Production has no alphamemory links") }
Action::InsertToken(_) => {
println!("Production ACTIVATED {:?} by {:?}", d, action);
d.callback.activate();
}
Action::DeleteToken(token_id) => {
println!("Production DEACTIVATED {:?} by {:?}", d, action);
d.callback.deactivate();
token_id.remove(tokens);
}
Action::DeleteChildToken(parent_id, sub_id) => {
println!("Production DEACTIVATED {:?} by {:?}", d, action);
d.callback.deactivate();
let mut current_id = *sub_id;
while current_id != *parent_id {
let current = tokens.get(current_id).unwrap();
if current.first_child().is_some() {
break;
}
let next_id = current.parent().unwrap();
current_id.remove(tokens);
current_id = next_id;
}
}
}
}
cellref.scheduled_actions.clear();
segments[self.get_segment()].get().set_modified(self_id, false);
}
_ => { unimplemented!() }
}
}
}
#[derive(Debug)]
pub(crate) struct RootNodeData {
pub(crate) segment: SegmentId,
pub(crate) root_token: Option<TokenId>,
}
#[derive(Debug)]
pub(crate) struct MemoryNodeData {
pub(crate) segment: SegmentId,
pub(crate) cell: RefCell<MemoryNodeCell>,
}
#[derive(Debug)]
pub(crate) struct MemoryNodeCell {
scheduled_actions: Vec<Action>,
tokens: VecDeque<TokenId>,
}
#[derive(Debug)]
pub(crate) struct JoinNodeData {
pub(crate) segment: SegmentId,
pub(crate) amem: AlphaNodeId,
pub(crate) tests: Vec<JoinNodeTest>,
pub(crate) cell: RefCell<JoinNodeCell>,
}
#[derive(Debug)]
pub(crate) struct JoinNodeCell {
pub(crate) scheduled_actions: Vec<Action>,
}
#[derive(Debug)]
pub(crate) struct ProductionNodeData {
pub(crate) segment: SegmentId,
pub(crate) callback: Box<dyn ProductionCallback>,
pub(crate) cell: RefCell<ProductionNodeCell>,
}
#[derive(Debug)]
pub(crate) struct ProductionNodeCell {
pub(crate) scheduled_actions: Vec<Action>,
}
pub(crate) struct Token {
fact: Rc<FactCore>,
owner: BetaNodeId,
}
impl Token {
pub(crate) fn new(fact: Rc<FactCore>, owner: BetaNodeId) -> Self {
Token { fact, owner }
}
}
impl Debug for Token {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
let fact: &FactCore = self.fact.borrow();
write!(f, "TokenData{{ <{}, {}, {}> }}", fact.0.to_string(), fact.1.to_string(), fact.2.to_string())
}
}
pub(crate) fn print_token(token_id: TokenId, tokens: &TreeArena<Token>) -> String {
let token = &tokens[token_id];
let facts: &FactCore = token.get().fact.borrow();
let data = "<".to_owned() + facts.0.as_ref() + "," + facts.1.as_ref() + "," + facts.2.as_ref() + ">";
let parent = token.parent();
match parent {
None => { "".to_owned() }
Some(p) => { print_token(p, tokens) + ", " + data.as_str() }
}
}
fn we_can_skip_proccing_this_node(segment_id: SegmentId, segments: &TreeArena<Segment>) -> bool {
let segment = segments[segment_id].get();
!*segment.needs_processing.borrow()
}
fn execute_join_test(token: &TokenId, test: &JoinNodeTest, fact: &FactCore, tokens: &mut TreeArena<Token>) -> bool {
println!("testing if Fact{{ {},{},{} }} matches Token {:?} by rule {:?}",
fact.0.to_string(), fact.1.to_string(), fact.2.to_string(),
print_token(*token, &tokens), test);
let mut current = *token;
let n: &FactCore =
if test.condition_number_of_arg2 == 0 {
fact
} else {
let mut i = test.condition_number_of_arg2 - 1;
while i > 0 {
current = tokens[current].parent().unwrap();
i = i - 1;
}
tokens[current].get().fact.borrow()
};
let left = match test.f1 {
JoinTestField::Field1 => &fact.0,
JoinTestField::Field2 => &fact.1,
JoinTestField::Field3 => &fact.2,
};
let right = match test.f2 {
JoinTestField::Field1 => &n.0,
JoinTestField::Field2 => &n.1,
JoinTestField::Field3 => &n.2,
};
println!("Testing {:?} == {:?}", left.to_string(), right.to_string());
left.to_string() == right.to_string()
}
#[cfg(test)]
mod tests {
use compact::CString;
use test_case::test_case;
use super::*;
#[test_case(JoinTestField::Field1, JoinTestField::Field1 => true)]
#[test_case(JoinTestField::Field2, JoinTestField::Field2 => true)]
#[test_case(JoinTestField::Field3, JoinTestField::Field3 => true)]
#[test_case(JoinTestField::Field1, JoinTestField::Field2 => false)]
#[test_case(JoinTestField::Field1, JoinTestField::Field3 => false)]
#[test_case(JoinTestField::Field2, JoinTestField::Field1 => false)]
#[test_case(JoinTestField::Field2, JoinTestField::Field3 => false)]
#[test_case(JoinTestField::Field3, JoinTestField::Field1 => false)]
#[test_case(JoinTestField::Field3, JoinTestField::Field2 => false)]
fn test_joins_self_check(f1: JoinTestField, f2: JoinTestField) -> bool {
let mut tokens = TreeArena::new();
let mut betanodes = TreeArena::new();
let mut segments = TreeArena::new();
let root_segment_id = segments.new_node(Segment::new());
let root_node = betanodes.new_node(BetaNode::new_rootnode(root_segment_id));
let root_fact = Rc::new(FactCore(CString::new(), CString::new(), CString::new()));
let root = tokens.new_node(Token::new(root_fact, root_node));
execute_join_test(&root,
&JoinNodeTest { f1, condition_number_of_arg2: 0, f2 },
&FactCore(
CString::from("1".to_owned()),
CString::from("2".to_owned()),
CString::from("3".to_owned()),
), &mut tokens)
}
#[test_case(JoinTestField::Field1, JoinTestField::Field1 => (true, false))]
#[test_case(JoinTestField::Field2, JoinTestField::Field2 => (true, false))]
#[test_case(JoinTestField::Field3, JoinTestField::Field3 => (true, false))]
#[test_case(JoinTestField::Field1, JoinTestField::Field2 => (false, false))]
#[test_case(JoinTestField::Field1, JoinTestField::Field3 => (false, false))]
#[test_case(JoinTestField::Field2, JoinTestField::Field1 => (false, false))]
#[test_case(JoinTestField::Field2, JoinTestField::Field3 => (false, false))]
#[test_case(JoinTestField::Field3, JoinTestField::Field1 => (false, false))]
#[test_case(JoinTestField::Field3, JoinTestField::Field2 => (false, false))]
fn test_joins_token_1_level(f1: JoinTestField, f2: JoinTestField) -> (bool, bool) {
let mut tokens = TreeArena::new();
let mut betanodes = TreeArena::new();
let mut segments = TreeArena::new();
let root_segment_id = segments.new_node(Segment::new());
let root_node = betanodes.new_node(BetaNode::new_rootnode(root_segment_id));
let root_fact = Rc::new(FactCore(CString::new(), CString::new(), CString::new()));
let root = tokens.new_node(Token::new(root_fact, root_node));
let child_fact1 = Rc::new(FactCore(CString::from("1".to_owned()),
CString::from("2".to_owned()),
CString::from("3".to_owned())));
let child1_node = betanodes.new_node(BetaNode::new_memorynode(root_segment_id));
let child1 = tokens.new_node(Token::new(child_fact1, child1_node));
root.append(child1, &mut tokens);
let child_fact2 = Rc::new(FactCore(CString::from("not1".to_owned()),
CString::from("not2".to_owned()),
CString::from("not3".to_owned())));
let child2_node = betanodes.new_node(BetaNode::new_memorynode(root_segment_id));
let child2 = tokens.new_node(Token::new(child_fact2, child2_node));
root.prepend(child2, &mut tokens);
(execute_join_test(&child1,
&JoinNodeTest { f1, condition_number_of_arg2: 1, f2 },
&FactCore(
CString::from("1".to_owned()),
CString::from("2".to_owned()),
CString::from("3".to_owned()),
), &mut tokens),
execute_join_test(&child2,
&JoinNodeTest { f1, condition_number_of_arg2: 1, f2 },
&FactCore(
CString::from("1".to_owned()),
CString::from("2".to_owned()),
CString::from("3".to_owned()),
), &mut tokens))
}
}