souffle  2.0.2-371-g6315b36
ClauseTranslator.cpp
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file ClauseTranslator.h
12  *
13  * Translator for clauses from AST to RAM
14  *
15  ***********************************************************************/
16 
18 #include "Global.h"
19 #include "ast/Aggregator.h"
20 #include "ast/Clause.h"
21 #include "ast/IntrinsicFunctor.h"
22 #include "ast/NumericConstant.h"
23 #include "ast/RecordInit.h"
24 #include "ast/UnnamedVariable.h"
25 #include "ast/analysis/Functor.h"
28 #include "ast/utility/Utils.h"
29 #include "ast/utility/Visitor.h"
31 #include "ast2ram/Location.h"
32 #include "ast2ram/ValueIndex.h"
33 #include "ram/Aggregate.h"
34 #include "ram/Break.h"
35 #include "ram/Conjunction.h"
36 #include "ram/Constraint.h"
37 #include "ram/EmptinessCheck.h"
38 #include "ram/Filter.h"
39 #include "ram/Negation.h"
41 #include "ram/Project.h"
42 #include "ram/Query.h"
43 #include "ram/Relation.h"
44 #include "ram/Scan.h"
45 #include "ram/TupleElement.h"
46 #include "ram/UnpackRecord.h"
47 #include "ram/utility/Utils.h"
49 #include <map>
50 #include <vector>
51 
52 namespace souffle::ast2ram {
53 
54 /** generate RAM code for a clause */
55 Own<ram::Statement> ClauseTranslator::translateClause(
56  const ast::Clause& clause, const ast::Clause& originalClause, const int version) {
57  if (auto reorderedClause = getReorderedClause(clause, version)) {
58  // translate reordered clause
59  return translateClause(*reorderedClause, originalClause, version);
60  }
61 
62  // get extract some details
63  const ast::Atom* head = clause.getHead();
64 
65  // handle facts
66  if (isFact(clause)) {
67  // translate arguments
69  for (auto& arg : head->getArguments()) {
70  values.push_back(translator.translateValue(arg, ValueIndex()));
71  }
72 
73  // create a fact statement
74  return mk<ram::Query>(mk<ram::Project>(translator.translateRelation(head), std::move(values)));
75  }
76 
77  // the rest should be rules
78  assert(isRule(clause));
79 
80  createValueIndex(clause);
81 
82  // -- create RAM statement --
83 
85 
86  /* add equivalence constraints imposed by variable binding */
87  for (const auto& cur : valueIndex->getVariableReferences()) {
88  // the first appearance
89  const Location& first = *cur.second.begin();
90  // all other appearances
91  for (const Location& loc : cur.second) {
92  if (first != loc && !valueIndex->isGenerator(loc.identifier)) {
93  // FIXME: equiv' for float types (`FEQ`)
94  op = mk<ram::Filter>(
95  mk<ram::Constraint>(BinaryConstraintOp::EQ, translator.makeRamTupleElement(first),
97  std::move(op));
98  }
99  }
100  }
101 
102  /* add conditions caused by atoms, negations, and binary relations */
103  for (const auto& lit : clause.getBodyLiterals()) {
104  if (auto condition = translator.translateConstraint(lit, *valueIndex)) {
105  op = mk<ram::Filter>(std::move(condition), std::move(op));
106  }
107  }
108 
109  // add aggregator conditions
110  size_t curLevel = op_nesting.size() - 1;
111  for (auto it = op_nesting.rbegin(); it != op_nesting.rend(); ++it, --curLevel) {
112  const ast::Node* cur = *it;
113 
114  if (const auto* atom = dynamic_cast<const ast::Atom*>(cur)) {
115  // add constraints
116  size_t pos = 0;
117  for (auto arg : atom->getArguments()) {
118  if (auto* agg = dynamic_cast<ast::Aggregator*>(arg)) {
119  auto loc = valueIndex->getGeneratorLoc(*agg);
120  // FIXME: equiv' for float types (`FEQ`)
121  op = mk<ram::Filter>(
122  mk<ram::Constraint>(BinaryConstraintOp::EQ, mk<ram::TupleElement>(curLevel, pos),
124  std::move(op));
125  }
126  ++pos;
127  }
128  }
129  }
130 
131  // add generator levels
132  --level;
133  for (auto* cur : reverse(generators)) {
134  if (auto agg = dynamic_cast<const ast::Aggregator*>(cur)) {
135  // condition for aggregate and helper function to add terms
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);
139  };
140 
141  // translate constraints of sub-clause
142  for (auto&& lit : agg->getBodyLiterals()) {
143  if (auto newCondition = translator.translateConstraint(lit, *valueIndex)) {
144  addAggCondition(std::move(newCondition));
145  }
146  }
147 
148  // get the first predicate of the sub-clause
149  // NB: at most one atom is permitted in a sub-clause
150  const ast::Atom* atom = nullptr;
151  for (auto&& lit : agg->getBodyLiterals()) {
152  if (atom == nullptr) {
153  atom = dynamic_cast<const ast::Atom*>(lit);
154  } else {
155  assert(!isA<ast::Atom>(lit) && "Unsupported complex aggregation body encountered!");
156  }
157  }
158 
159  // translate arguments's of atom (if exists) to conditions
160  if (atom != nullptr) {
161  size_t pos = 0;
162  auto addAggEqCondition = [&](Own<ram::Expression> value) {
163  if (isUndefValue(value.get())) return;
164 
165  // FIXME: equiv' for float types (`FEQ`)
166  addAggCondition(mk<ram::Constraint>(
167  BinaryConstraintOp::EQ, mk<ram::TupleElement>(level, pos), std::move(value)));
168  };
169  for (auto* arg : atom->getArguments()) {
170  // variable bindings are issued differently since we don't want self
171  // referential variable bindings
172  if (auto* var = dynamic_cast<const ast::Variable*>(arg)) {
173  for (auto&& loc : valueIndex->getVariableReferences().find(var->getName())->second) {
174  if (level != loc.identifier || (int)pos != loc.element) {
175  addAggEqCondition(translator.makeRamTupleElement(loc));
176  break;
177  }
178  }
179  } else if (auto value = translator.translateValue(arg, *valueIndex)) {
180  addAggEqCondition(std::move(value));
181  }
182  ++pos;
183  }
184  }
185 
186  // translate aggregate expression
187  auto expr = translator.translateValue(agg->getTargetExpression(), *valueIndex);
188 
189  // add Ram-Aggregation layer
190  op = mk<ram::Aggregate>(std::move(op), agg->getFinalType().value(),
191  translator.translateRelation(atom), expr ? std::move(expr) : mk<ram::UndefValue>(),
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()) {
196  args.push_back(translator.translateValue(x, *valueIndex));
197  }
198 
199  auto func_op = [&]() -> ram::NestedIntrinsicOp {
200  switch (func->getFinalOpType().value()) {
204 
205  default: fatal("missing case handler or bad code-gen");
206  }
207  };
208 
209  op = mk<ram::NestedIntrinsicOperator>(func_op(), std::move(args), std::move(op), level);
210  }
211 
212  --level;
213  }
214 
215  // build operation bottom-up
216  while (!op_nesting.empty()) {
217  // get next operator
218  const ast::Node* cur = op_nesting.back();
219  op_nesting.pop_back();
220 
221  // get current nesting level
222  auto level = op_nesting.size();
223 
224  if (const auto* atom = dynamic_cast<const ast::Atom*>(cur)) {
225  // add constraints
226  // TODO: do we wish to enable constraints by header functor? record inits do so...
227  op = filterByConstraints(level, atom->getArguments(), std::move(op), false);
228 
229  // check whether all arguments are unnamed variables
230  bool isAllArgsUnnamed = true;
231  for (auto* argument : atom->getArguments()) {
232  if (!isA<ast::UnnamedVariable>(argument)) {
233  isAllArgsUnnamed = false;
234  }
235  }
236 
237  // add check for emptiness for an atom
238  op = mk<ram::Filter>(
239  mk<ram::Negation>(mk<ram::EmptinessCheck>(translator.translateRelation(atom))),
240  std::move(op));
241 
242  // add a scan level
243  if (atom->getArity() != 0 && !isAllArgsUnnamed) {
244  if (head->getArity() == 0) {
245  op = mk<ram::Break>(
246  mk<ram::Negation>(mk<ram::EmptinessCheck>(translator.translateRelation(head))),
247  std::move(op));
248  }
249  if (Global::config().has("profile")) {
250  std::stringstream ss;
251  ss << head->getQualifiedName();
252  ss.str("");
253  ss << "@frequency-atom" << ';';
254  ss << originalClause.getHead()->getQualifiedName() << ';';
255  ss << version << ';';
256  ss << stringify(toString(clause)) << ';';
257  ss << stringify(toString(*atom)) << ';';
258  ss << stringify(toString(originalClause)) << ';';
259  ss << level << ';';
260  op = mk<ram::Scan>(translator.translateRelation(atom), level, std::move(op), ss.str());
261  } else {
262  op = mk<ram::Scan>(translator.translateRelation(atom), level, std::move(op));
263  }
264  }
265 
266  // TODO: support constants in nested records!
267  } else if (const auto* rec = dynamic_cast<const ast::RecordInit*>(cur)) {
268  // add constant constraints
269  op = filterByConstraints(level, rec->getArguments(), std::move(op));
270 
271  // add an unpack level
272  const Location& loc = valueIndex->getDefinitionPoint(*rec);
273  op = mk<ram::UnpackRecord>(
274  std::move(op), level, translator.makeRamTupleElement(loc), rec->getArguments().size());
275  } else {
276  fatal("Unsupported AST node for creation of scan-level!");
277  }
278  }
279 
280  /* generate the final RAM Insert statement */
281  Own<ram::Condition> cond = createCondition(originalClause);
282  if (cond != nullptr) {
283  return mk<ram::Query>(mk<ram::Filter>(std::move(cond), std::move(op)));
284  } else {
285  return mk<ram::Query>(std::move(op));
286  }
287 }
288 
289 Own<ram::Operation> ClauseTranslator::createOperation(const ast::Clause& clause) {
290  const auto head = clause.getHead();
291 
292  VecOwn<ram::Expression> values;
293  for (ast::Argument* arg : head->getArguments()) {
294  values.push_back(translator.translateValue(arg, *valueIndex));
295  }
296 
297  Own<ram::Operation> project = mk<ram::Project>(translator.translateRelation(head), std::move(values));
298 
299  if (head->getArity() == 0) {
300  project = mk<ram::Filter>(
301  mk<ram::EmptinessCheck>(translator.translateRelation(head)), std::move(project));
302  }
303 
304  // build up insertion call
305  return project; // start with innermost
306 }
307 
308 Own<ram::Condition> ClauseTranslator::createCondition(const ast::Clause& originalClause) {
309  const auto head = originalClause.getHead();
310 
311  // add stopping criteria for nullary relations
312  // (if it contains already the null tuple, don't re-compute)
313  if (head->getArity() == 0) {
314  return mk<ram::EmptinessCheck>(translator.translateRelation(head));
315  }
316  return nullptr;
317 }
318 
320  const std::vector<ast::Argument*>& args, Own<ram::Operation> op, bool constrainByFunctors) {
321  size_t pos = 0;
322 
323  auto mkFilter = [&](bool isFloatArg, Own<ram::Expression> rhs) {
324  return mk<ram::Filter>(
325  mk<ram::Constraint>(isFloatArg ? BinaryConstraintOp::FEQ : BinaryConstraintOp::EQ,
326  mk<ram::TupleElement>(level, pos), std::move(rhs)),
327  std::move(op));
328  };
329 
330  for (auto* a : args) {
331  if (auto* c = dynamic_cast<const ast::Constant*>(a)) {
332  auto* const c_num = dynamic_cast<const ast::NumericConstant*>(c);
333  assert((!c_num || c_num->getFinalType().has_value()) &&
334  "numeric constant wasn't bound to a type");
335  op = mkFilter(c_num && c_num->getFinalType().value() == ast::NumericConstant::Type::Float,
337  } else if (auto* func = dynamic_cast<const ast::Functor*>(a)) {
338  if (constrainByFunctors) {
340  op = mkFilter(
342  }
343  }
344 
345  ++pos;
346  }
347 
348  return op;
349 }
350 
351 Own<ast::Clause> ClauseTranslator::getReorderedClause(const ast::Clause& clause, const int version) const {
352  const auto plan = clause.getExecutionPlan();
353 
354  // check whether there is an imposed order constraint
355  if (plan == nullptr) {
356  // no plan, so reorder it according to the internal heuristic
358  *translator.getSipsMetric(), &clause)) {
359  return Own<ast::Clause>(reorderedClause);
360  }
361  return nullptr;
362  }
363  auto orders = plan->getOrders();
364  if (orders.find(version) == orders.end()) {
365  return nullptr;
366  }
367 
368  // get the imposed order
369  const auto& order = orders[version];
370 
371  // create a copy and fix order
372  Own<ast::Clause> reorderedClause(clause.clone());
373 
374  // Change order to start at zero
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; });
378 
379  // re-order atoms
380  reorderedClause.reset(reorderAtoms(reorderedClause.get(), newOrder));
381 
382  // clear other order and fix plan
383  reorderedClause->clearExecutionPlan();
384 
385  return reorderedClause;
386 }
387 
388 void ClauseTranslator::indexValues(const ast::Node* curNode, const std::vector<ast::Argument*>& curNodeArgs,
389  std::map<const ast::Node*, int>& nodeLevel, const ram::Relation* relation) {
390  for (size_t pos = 0; pos < curNodeArgs.size(); ++pos) {
391  // get argument
392  auto& arg = curNodeArgs[pos];
393 
394  // check for variable references
395  if (auto var = dynamic_cast<const ast::Variable*>(arg)) {
396  if (pos < relation->getArity()) {
397  valueIndex->addVarReference(*var, nodeLevel[curNode], pos, relation->getName());
398  } else {
399  valueIndex->addVarReference(*var, nodeLevel[curNode], pos);
400  }
401  }
402 
403  // check for nested records
404  if (auto rec = dynamic_cast<const ast::RecordInit*>(arg)) {
405  // introduce new nesting level for unpack
406  op_nesting.push_back(rec);
407  nodeLevel[rec] = level++;
408 
409  // register location of record
410  valueIndex->setRecordDefinition(*rec, nodeLevel[curNode], pos);
411 
412  // resolve nested components
413  indexValues(rec, rec->getArguments(), nodeLevel, relation);
414  }
415  }
416 }
417 
418 /** index values in rule */
419 void ClauseTranslator::createValueIndex(const ast::Clause& clause) {
420  for (const auto* atom : ast::getBodyLiterals<ast::Atom>(clause)) {
421  // map from each list of arguments to its nesting level
422  std::map<const ast::Node*, int> nodeLevel;
423 
424  // give the atom the current level
425  nodeLevel[atom] = level++;
426  op_nesting.push_back(atom);
427 
428  // index each value in the atom
429  indexValues(atom, atom->getArguments(), nodeLevel,
431  }
432 
433  // add aggregation functions
434  visitDepthFirstPostOrder(clause, [&](const ast::Argument& arg) {
435  // returns the write-location for this generator (or none if an equiv arg was already seen)
436  auto addGenerator = [&]() -> std::optional<int> {
437  // The by-value compare means that we're effectively doing CSE for any
438  // generator args during code-gen. This is a weird place to do this.
439  if (dynamic_cast<const ast::Aggregator*>(&arg) != nullptr &&
440  any_of(generators, [&](auto* x) { return *x == arg; }))
441  return {};
442  generators.push_back(&arg);
443 
444  int aggLoc = level++;
445  valueIndex->setGeneratorLoc(arg, Location({aggLoc, 0}));
446  return aggLoc;
447  };
448 
449  if (auto agg = dynamic_cast<const ast::Aggregator*>(&arg)) {
450  if (auto aggLoc = addGenerator()) {
451  // bind aggregator variables to locations
452  const ast::Atom* atom = nullptr;
453  for (auto lit : agg->getBodyLiterals()) {
454  if (atom == nullptr) {
455  atom = dynamic_cast<const ast::Atom*>(lit);
456  } else {
457  break;
458  }
459  }
460  if (atom != nullptr) {
461  size_t pos = 0;
462  for (auto* arg : atom->getArguments()) {
463  if (const auto* var = dynamic_cast<const ast::Variable*>(arg)) {
464  valueIndex->addVarReference(
465  *var, *aggLoc, (int)pos, translator.translateRelation(atom));
466  }
467  ++pos;
468  }
469  }
470  }
471  }
472 
473  auto* func = as<ast::IntrinsicFunctor>(arg);
475  addGenerator();
476  }
477  });
478 
479  // add multi-result functor introductions
480  visitDepthFirst(clause, [&](const ast::BinaryConstraint& bc) {
481  if (!isEqConstraint(bc.getBaseOperator())) return;
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;
486  valueIndex->addVarReference(*lhs, valueIndex->getGeneratorLoc(*rhs));
487  });
488 }
489 
490 } // namespace souffle::ast2ram
Aggregate.h
souffle::ast::analysis::FunctorAnalysis::isMultiResult
static bool isMultiResult(const Functor &functor)
Definition: Functor.cpp:53
souffle::ast2ram::ClauseTranslator::createValueIndex
void createValueIndex(const ast::Clause &clause)
index values in rule
Definition: ClauseTranslator.cpp:425
souffle::ast::Atom::getArguments
std::vector< Argument * > getArguments() const
Return arguments.
Definition: Atom.h:77
souffle::ast::visitDepthFirstPostOrder
void visitDepthFirstPostOrder(const Node &root, Visitor< R, Ps... > &visitor, Args &... args)
A utility function visiting all nodes within the ast rooted by the given node recursively in a depth-...
Definition: Visitor.h:254
Constraint.h
UnnamedVariable.h
Scan.h
TypeAttribute
Type attribute class.
souffle::ram::isUndefValue
bool isUndefValue(const Expression *expr)
Determines if an expression represents an undefined value.
Definition: Utils.h:40
Negation.h
souffle::ast::reorderAtoms
Clause * reorderAtoms(const Clause *clause, const std::vector< unsigned int > &newOrder)
Reorders the atoms of a clause to be in the given order.
Definition: Utils.cpp:264
Project.h
AstToRamTranslator.h
souffle::FunctorOp::URANGE
@ URANGE
souffle::ast2ram::ClauseTranslator::translator
AstToRamTranslator & translator
Definition: ClauseTranslator.h:49
souffle::ram::NestedIntrinsicOp::RANGE
@ RANGE
souffle::Own
std::unique_ptr< A > Own
Definition: ContainerUtil.h:42
relation
Relation & relation
Definition: Reader.h:130
souffle::BinaryConstraintOp::EQ
@ EQ
souffle::ram::NestedIntrinsicOp::FRANGE
@ FRANGE
souffle::ast2ram::Location
Definition: Location.h:29
souffle::ast::isFact
bool isFact(const Clause &clause)
Returns whether the given clause is a fact.
Definition: Utils.cpp:214
Filter.h
souffle::ast2ram::AstToRamTranslator::translateRelation
std::string translateRelation(const ast::Atom *atom)
a utility to translate atoms to relations
Definition: AstToRamTranslator.cpp:219
EmptinessCheck.h
souffle::ast::analysis::Variable
A variable to be utilized within constraints to be handled by the constraint solver.
Definition: ConstraintSystem.h:41
IntrinsicFunctor.h
rhs
Own< Argument > rhs
Definition: ResolveAliases.cpp:185
souffle::ast2ram::ClauseTranslator::translateClause
Own< ram::Statement > translateClause(const ast::Clause &clause, const ast::Clause &originalClause, const int version=0)
generate RAM code for a clause
Definition: ClauseTranslator.cpp:61
souffle::BinaryConstraintOp::FEQ
@ FEQ
souffle::ast::Atom
An atom class.
Definition: Atom.h:51
Utils.h
souffle::ram::NestedIntrinsicOp::URANGE
@ URANGE
souffle::ast::Argument
An abstract class for arguments.
Definition: Argument.h:33
Global.h
souffle::ast2ram::AstToRamTranslator::getFunctorAnalysis
const ast::analysis::FunctorAnalysis * getFunctorAnalysis() const
Definition: AstToRamTranslator.h:80
lhs
Own< Argument > lhs
Definition: ResolveAliases.cpp:184
souffle::toString
const std::string & toString(const std::string &str)
A generic function converting strings into strings (trivial case).
Definition: StringUtil.h:234
souffle::FunctorOp::FRANGE
@ FRANGE
souffle::ast::Atom::getQualifiedName
const QualifiedName & getQualifiedName() const
Return qualified name.
Definition: Atom.h:57
souffle::stringify
std::string stringify(const std::string &input)
Stringify a string using escapes for escape, newline, tab, double-quotes and semicolons.
Definition: StringUtil.h:334
souffle::ast2ram::Location::element
const int element
Definition: Location.h:35
i
size_t i
Definition: json11.h:663
souffle::ast2ram::AstToRamTranslator::lookupRelation
const ram::Relation * lookupRelation(const std::string &name) const
Definition: AstToRamTranslator.h:116
Relation.h
NestedIntrinsicOperator.h
souffle::ast2ram::AstToRamTranslator::translateConstraint
Own< ram::Condition > translateConstraint(const ast::Literal *arg, const ValueIndex &index)
translate an AST constraint to a RAM condition
Definition: AstToRamTranslator.cpp:340
souffle::ast::transform::ReorderLiteralsTransformer::reorderClauseWithSips
static Clause * reorderClauseWithSips(const SipsMetric &sips, const Clause *clause)
Reorder the clause based on a given SIPS function.
Definition: ReorderLiterals.cpp:46
souffle::ast2ram::ValueIndex
Definition: ValueIndex.h:36
souffle::FunctorOp::RANGE
@ RANGE
StringUtil.h
souffle::any_of
bool any_of(const Container &c, UnaryPredicate p)
A generic test checking whether any elements within a container satisfy a certain predicate.
Definition: FunctionalUtil.h:124
souffle::ast::Constant
Abstract constant class.
Definition: Constant.h:38
souffle::ast::analysis::FunctorAnalysis::getReturnType
TypeAttribute getReturnType(const Functor *functor) const
Return return type of functor.
Definition: Functor.cpp:40
PolymorphicObjects.h
UnpackRecord.h
Utils.h
souffle::ast2ram::ClauseTranslator::getReorderedClause
Own< ast::Clause > getReorderedClause(const ast::Clause &clause, const int version) const
Definition: ClauseTranslator.cpp:357
souffle::ast2ram::AstToRamTranslator::getSipsMetric
const ast::SipsMetric * getSipsMetric() const
Definition: AstToRamTranslator.h:88
souffle::ast::Functor
Abstract functor class.
Definition: Functor.h:36
Break.h
souffle::ram::NestedIntrinsicOp
NestedIntrinsicOp
Definition: NestedIntrinsicOperator.h:38
souffle::isEqConstraint
bool isEqConstraint(const BinaryConstraintOp constraintOp)
Definition: BinaryConstraintOps.h:124
souffle::ast::Atom::getArity
size_t getArity() const
Return arity of the atom.
Definition: Atom.h:62
Location.h
souffle::ast2ram::ClauseTranslator::op_nesting
std::vector< const ast::Node * > op_nesting
Definition: ClauseTranslator.h:68
Aggregator.h
souffle::Global::config
static MainConfig & config()
Definition: Global.h:141
souffle::ast2ram::AstToRamTranslator::makeRamTupleElement
static Own< ram::TupleElement > makeRamTupleElement(const Location &loc)
create a RAM element access node
Definition: AstToRamTranslator.cpp:150
TupleElement.h
ReorderLiterals.h
souffle::ast::Aggregator
Defines the aggregator class.
Definition: Aggregator.h:53
Functor.h
std
Definition: Brie.h:3053
ValueIndex.h
Query.h
souffle::ast2ram::ClauseTranslator::createOperation
virtual Own< ram::Operation > createOperation(const ast::Clause &clause)
Definition: ClauseTranslator.cpp:295
souffle::ast2ram::ClauseTranslator::createCondition
virtual Own< ram::Condition > createCondition(const ast::Clause &originalClause)
Definition: ClauseTranslator.cpp:314
souffle::fatal
void fatal(const char *format, const Args &... args)
Definition: MiscUtil.h:198
souffle::ast2ram::AstToRamTranslator::translateValue
Own< ram::Expression > translateValue(const ast::Argument *arg, const ValueIndex &index)
translate an AST argument to a RAM value
Definition: AstToRamTranslator.cpp:236
Visitor.h
souffle::ast2ram
Definition: AstToRamTranslator.cpp:132
Clause.h
souffle::ast2ram::ClauseTranslator::valueIndex
Own< ValueIndex > valueIndex
Definition: ClauseTranslator.h:52
souffle::ast2ram::ClauseTranslator::generators
std::vector< const ast::Argument * > generators
Definition: ClauseTranslator.h:65
souffle::ast::visitDepthFirst
void visitDepthFirst(const Node &root, Visitor< R, Ps... > &visitor, Args &... args)
A utility function visiting all nodes within the ast rooted by the given node recursively in a depth-...
Definition: Visitor.h:273
souffle::ast2ram::AstToRamTranslator::translateConstant
Own< ram::Expression > translateConstant(ast::Constant const &c)
translate RAM code for a constant value
Definition: AstToRamTranslator.cpp:437
souffle::ast2ram::ClauseTranslator::indexValues
void indexValues(const ast::Node *curNode, const std::vector< ast::Argument * > &curNodeArgs, std::map< const ast::Node *, int > &nodeLevel, const ram::Relation *relation)
Definition: ClauseTranslator.cpp:394
souffle::ast::NumericConstant::Type::Float
@ Float
ClauseTranslator.h
souffle::ast::NumericConstant
Numeric Constant.
Definition: NumericConstant.h:43
souffle::TypeAttribute::Float
@ Float
souffle::ast2ram::ClauseTranslator::filterByConstraints
Own< ram::Operation > filterByConstraints(size_t level, const std::vector< ast::Argument * > &args, Own< ram::Operation > op, bool constrainByFunctors=true)
apply constraint filters to a given operation
Definition: ClauseTranslator.cpp:325
souffle::VecOwn
std::vector< Own< A > > VecOwn
Definition: ContainerUtil.h:45
RecordInit.h
souffle::ast::RecordInit
Defines a record initialization class.
Definition: RecordInit.h:42
NumericConstant.h
souffle::ast::isRule
bool isRule(const Clause &clause)
Returns whether the given clause is a rule.
Definition: Utils.cpp:238
souffle::ast2ram::ClauseTranslator::level
int level
Definition: ClauseTranslator.h:55
souffle::profile::ss
class souffle::profile::Tui ss
Definition: Tui.h:336
Conjunction.h
souffle::ast2ram::Location::identifier
const int identifier
Definition: Location.h:34