56 const ast::Clause& clause,
const ast::Clause& originalClause,
const int version) {
87 for (
const auto& cur :
valueIndex->getVariableReferences()) {
89 const Location& first = *cur.second.begin();
91 for (
const Location& loc : cur.second) {
103 for (
const auto& lit : clause.getBodyLiterals()) {
105 op = mk<ram::Filter>(std::move(condition), std::move(op));
112 const ast::Node* cur = *it;
114 if (
const auto* atom =
dynamic_cast<const ast::Atom*
>(cur)) {
117 for (
auto arg : atom->getArguments()) {
118 if (
auto* agg =
dynamic_cast<ast::Aggregator*
>(arg)) {
121 op = mk<ram::Filter>(
134 if (
auto agg =
dynamic_cast<const ast::Aggregator*
>(cur)) {
136 Own<ram::Condition> aggCond;
137 auto addAggCondition = [&](Own<ram::Condition> arg) {
138 aggCond = aggCond ? mk<ram::Conjunction>(std::move(aggCond), std::move(arg)) :
std::move(arg);
142 for (
auto&& lit : agg->getBodyLiterals()) {
144 addAggCondition(std::move(newCondition));
150 const ast::Atom* atom =
nullptr;
151 for (
auto&& lit : agg->getBodyLiterals()) {
152 if (atom ==
nullptr) {
153 atom =
dynamic_cast<const ast::Atom*
>(lit);
155 assert(!isA<ast::Atom>(lit) &&
"Unsupported complex aggregation body encountered!");
160 if (atom !=
nullptr) {
162 auto addAggEqCondition = [&](Own<ram::Expression> value) {
166 addAggCondition(mk<ram::Constraint>(
169 for (
auto* arg : atom->getArguments()) {
172 if (
auto* var =
dynamic_cast<const ast::Variable*
>(arg)) {
173 for (
auto&& loc :
valueIndex->getVariableReferences().find(var->getName())->second) {
180 addAggEqCondition(std::move(value));
190 op = mk<ram::Aggregate>(std::move(op), agg->getFinalType().value(),
192 aggCond ? std::move(aggCond) : mk<ram::True>(),
level);
193 }
else if (
const auto* func =
dynamic_cast<const ast::IntrinsicFunctor*
>(cur)) {
194 VecOwn<ram::Expression> args;
195 for (
auto&& x : func->getArguments()) {
200 switch (func->getFinalOpType().value()) {
205 default:
fatal(
"missing case handler or bad code-gen");
209 op = mk<ram::NestedIntrinsicOperator>(func_op(), std::move(args), std::move(op),
level);
224 if (
const auto* atom =
dynamic_cast<const ast::Atom*
>(cur)) {
230 bool isAllArgsUnnamed =
true;
231 for (
auto* argument : atom->getArguments()) {
232 if (!isA<ast::UnnamedVariable>(argument)) {
233 isAllArgsUnnamed =
false;
238 op = mk<ram::Filter>(
243 if (atom->getArity() != 0 && !isAllArgsUnnamed) {
250 std::stringstream
ss;
253 ss <<
"@frequency-atom" <<
';';
254 ss << originalClause.getHead()->getQualifiedName() <<
';';
255 ss << version <<
';';
267 }
else if (
const auto* rec =
dynamic_cast<const ast::RecordInit*
>(cur)) {
272 const Location& loc =
valueIndex->getDefinitionPoint(*rec);
273 op = mk<ram::UnpackRecord>(
276 fatal(
"Unsupported AST node for creation of scan-level!");
282 if (cond !=
nullptr) {
283 return mk<ram::Query>(mk<ram::Filter>(std::move(cond), std::move(op)));
285 return mk<ram::Query>(std::move(op));
290 const auto head = clause.getHead();
292 VecOwn<ram::Expression> values;
300 project = mk<ram::Filter>(
309 const auto head = originalClause.getHead();
320 const std::vector<ast::Argument*>& args,
Own<ram::Operation> op,
bool constrainByFunctors) {
324 return mk<ram::Filter>(
326 mk<ram::TupleElement>(
level, pos), std::move(
rhs)),
330 for (
auto* a : args) {
333 assert((!c_num || c_num->getFinalType().has_value()) &&
334 "numeric constant wasn't bound to a type");
337 }
else if (
auto* func =
dynamic_cast<const ast::Functor*
>(a)) {
338 if (constrainByFunctors) {
352 const auto plan = clause.getExecutionPlan();
355 if (plan ==
nullptr) {
363 auto orders = plan->getOrders();
364 if (orders.find(version) == orders.end()) {
369 const auto& order = orders[version];
372 Own<ast::Clause> reorderedClause(clause.clone());
375 std::vector<unsigned int> newOrder(order->getOrder().size());
376 std::transform(order->getOrder().begin(), order->getOrder().end(), newOrder.begin(),
377 [](
unsigned int i) ->
unsigned int { return i - 1; });
380 reorderedClause.reset(
reorderAtoms(reorderedClause.get(), newOrder));
383 reorderedClause->clearExecutionPlan();
385 return reorderedClause;
389 std::map<const ast::Node*, int>& nodeLevel,
const ram::Relation*
relation) {
390 for (
size_t pos = 0; pos < curNodeArgs.size(); ++pos) {
392 auto& arg = curNodeArgs[pos];
396 if (pos < relation->getArity()) {
399 valueIndex->addVarReference(*var, nodeLevel[curNode], pos);
407 nodeLevel[rec] =
level++;
410 valueIndex->setRecordDefinition(*rec, nodeLevel[curNode], pos);
420 for (
const auto* atom : ast::getBodyLiterals<ast::Atom>(clause)) {
422 std::map<const ast::Node*, int> nodeLevel;
436 auto addGenerator = [&]() -> std::optional<int> {
444 int aggLoc =
level++;
445 valueIndex->setGeneratorLoc(arg, Location({aggLoc, 0}));
449 if (
auto agg =
dynamic_cast<const ast::Aggregator*
>(&arg)) {
450 if (
auto aggLoc = addGenerator()) {
452 const ast::Atom* atom =
nullptr;
453 for (
auto lit : agg->getBodyLiterals()) {
454 if (atom ==
nullptr) {
455 atom =
dynamic_cast<const ast::Atom*
>(lit);
460 if (atom !=
nullptr) {
462 for (
auto* arg : atom->getArguments()) {
463 if (
const auto* var =
dynamic_cast<const ast::Variable*
>(arg)) {
473 auto* func = as<ast::IntrinsicFunctor>(arg);
482 const auto*
lhs =
dynamic_cast<const ast::Variable*
>(bc.getLHS());
483 const auto*
rhs =
dynamic_cast<const ast::IntrinsicFunctor*
>(bc.getRHS());
484 if (
lhs ==
nullptr ||
rhs ==
nullptr)
return;