void act(ActionBlock &action_block, Relation &results, Index &assertions, Index &retractions) { if (action_block.action_variables.begin != action_block.action_variables.end) { cerr << "[ERROR] Action variables are unsupported." << endl; return; } Action *action = action_block.actions.begin; for (; action != action_block.actions.end; ++action) { switch (action->type) { case ASSERT_FACT: case RETRACT_FACT: { if (action->get.atom.type == ATOM) { if (action->type == RETRACT_FACT) { cerr << "[ERROR] Retraction of atoms is currently unsupported." << endl; return; } act(action->get.atom.get.atom, results); continue; } if (action->get.atom.type != FRAME) { cerr << "[ERROR] For now, supporting only assertion of frames/triples." << endl; return; } Frame frame = action->get.atom.get.frame; Tuple triple(3); if (frame.object.type == LIST || frame.object.type == FUNCTION) { cerr << "[ERROR] Not supporting lists or functions in action target." << endl; return; } if (frame.object.type == CONSTANT) { triple[0] = frame.object.get.constant; } pair<Term, Term> *slot = frame.slots.begin; for (; slot != frame.slots.end; ++slot) { if (slot->first.type == LIST || slot->first.type == FUNCTION || slot->second.type == LIST || slot->second.type == FUNCTION) { cerr << "[ERROR] Not supporting lists or function in action target." << endl; return; } if (slot->first.type == CONSTANT) { triple[1] = slot->first.get.constant; } if (slot->second.type == CONSTANT) { triple[2] = slot->second.get.constant; } if (!results.empty() && frame.object.type == CONSTANT && slot->first.type == CONSTANT && slot->second.type == CONSTANT) { if (action->type == ASSERT_FACT) { assertions.insert(triple); } else { retractions.insert(triple); } continue; } Relation::iterator tuple = results.begin(); for (; tuple != results.end(); ++tuple) { if (frame.object.type == VARIABLE) { triple[0] = tuple->at(frame.object.get.variable); } if (slot->first.type == VARIABLE) { triple[1] = tuple->at(slot->first.get.variable); } if (slot->second.type == VARIABLE) { triple[2] = tuple->at(slot->second.get.variable); } if (action->type == ASSERT_FACT) { assertions.insert(triple); } else { retractions.insert(triple); } } } return; } default: { cerr << "[ERROR] Currently supporting on ASSERT_FACT and RETRACT_FACT actions." << endl; return; } } } }
void query(Condition &condition, set<varint_t> &allvars, Relation &results) { deque<void*> negated; Relation intermediate; switch (condition.type) { case ATOMIC: { query(condition.get.atom, allvars, results); return; } case CONJUNCTION: { Condition *subformula = condition.get.subformulas.begin; for (; subformula != condition.get.subformulas.end; ++subformula) { if (subformula->type == NEGATION) { negated.push_back((void*)subformula->get.subformulas.begin); continue; } Relation subresult; set<varint_t> newvars; // TODO vvv this won't work right if a non-special query // has not been performed first if (special(*subformula, intermediate, subresult)) { if (subformula == condition.get.subformulas.begin) { cerr << "[ERROR] Must have non-special query at beginning of conjunction." << endl; } intermediate.swap(subresult); continue; } query(*subformula, newvars, subresult); if (subformula == condition.get.subformulas.begin) { intermediate.swap(subresult); } else { vector<size_t> joinvars(allvars.size() + newvars.size()); vector<size_t>::iterator jit = set_intersection(allvars.begin(), allvars.end(), newvars.begin(), newvars.end(), joinvars.begin()); joinvars.resize(jit - joinvars.begin()); join(intermediate, subresult, joinvars, intermediate); } allvars.insert(newvars.begin(), newvars.end()); } break; } case DISJUNCTION: { cerr << "[ERROR] Disjunction is not supported." << endl; return; } case EXISTENTIAL: { // assuming all quantified variables are uniquely named in the scope of the rule Condition *subformula = condition.get.subformulas.begin; for (; subformula != condition.get.subformulas.end; ++subformula) { if (subformula->type == NEGATION) { negated.push_back((void*)subformula->get.subformulas.begin); } Relation subresult; query(*subformula, allvars, subresult); intermediate.splice(intermediate.end(), subresult); } break; } case NEGATION: { cerr << "[ERROR] This should never happen. query should not be called directly on negated formulas." << endl; return; } default: { cerr << "[ERROR] Unhandled case " << (int)condition.type << " on line " << __LINE__ << endl; return; } } // TODO deal with negation later, if at all #if 1 deque<void*>::iterator it = negated.begin(); for (; !intermediate.empty() && it != negated.end(); ++it) { Relation negresult; Condition *cond = (Condition*) *it; if (special(*cond, intermediate, negresult)) { intermediate.sort(); negresult.sort(); Relation leftover(intermediate.size()); Relation::iterator iit = set_difference(intermediate.begin(), intermediate.end(), negresult.begin(), negresult.end(), leftover.begin()); Relation newinter; newinter.splice(newinter.end(), leftover, leftover.begin(), iit); intermediate.swap(newinter); continue; } query(*((Condition*)(*it)), allvars, negresult); minusrel(intermediate, negresult, intermediate); } #endif results.swap(intermediate); }