souffle  2.0.2-371-g6315b36
Public Member Functions | Private Types | Private Member Functions | Private Attributes
souffle::interpreter::Engine Class Reference

This class translate the RAM Program into executable format and interpreter it. More...

#include <Engine.h>

Collaboration diagram for souffle::interpreter::Engine:
Collaboration graph

Public Member Functions

 Engine (ram::TranslationUnit &tUnit)
 
void executeMain ()
 Execute the main program. More...
 
void executeSubroutine (const std::string &name, const std::vector< RamDomain > &args, std::vector< RamDomain > &ret)
 Execute the subroutine program. More...
 

Private Types

using RelationHandle = Own< RelationWrapper >
 

Private Member Functions

void createRelation (const ram::Relation &id, const size_t idx)
 Create and add relation into the runtime environment. More...
 
void dropRelation (const size_t relId)
 Remove a relation from the environment. More...
 
template<typename Aggregate , typename Iter >
RamDomain evalAggregate (const Aggregate &aggregate, const Node &filter, const Node *expression, const Node &nestedOperation, const Iter &ranges, Context &ctxt)
 
template<typename Rel >
RamDomain evalChoice (const Rel &rel, const ram::Choice &cur, const Choice &shadow, Context &ctxt)
 
template<typename Rel >
RamDomain evalExistenceCheck (const ExistenceCheck &shadow, Context &ctxt)
 
template<typename Rel >
RamDomain evalIndexAggregate (const ram::IndexAggregate &cur, const IndexAggregate &shadow, Context &ctxt)
 
template<typename Rel >
RamDomain evalIndexChoice (const ram::IndexChoice &cur, const IndexChoice &shadow, Context &ctxt)
 
template<typename Rel >
RamDomain evalIndexScan (const ram::IndexScan &cur, const IndexScan &shadow, Context &ctxt)
 
template<typename Rel >
RamDomain evalParallelAggregate (const Rel &rel, const ram::ParallelAggregate &cur, const ParallelAggregate &shadow, Context &ctxt)
 
template<typename Rel >
RamDomain evalParallelChoice (const Rel &rel, const ram::ParallelChoice &cur, const ParallelChoice &shadow, Context &ctxt)
 
template<typename Rel >
RamDomain evalParallelIndexAggregate (const ram::ParallelIndexAggregate &cur, const ParallelIndexAggregate &shadow, Context &ctxt)
 
template<typename Rel >
RamDomain evalParallelIndexChoice (const Rel &rel, const ram::ParallelIndexChoice &cur, const ParallelIndexChoice &shadow, Context &ctxt)
 
template<typename Rel >
RamDomain evalParallelIndexScan (const Rel &rel, const ram::ParallelIndexScan &cur, const ParallelIndexScan &shadow, Context &ctxt)
 
template<typename Rel >
RamDomain evalParallelScan (const Rel &rel, const ram::ParallelScan &cur, const ParallelScan &shadow, Context &ctxt)
 
template<typename Rel >
RamDomain evalProject (Rel &rel, const Project &shadow, Context &ctxt)
 
template<typename Rel >
RamDomain evalProvenanceExistenceCheck (const ProvenanceExistenceCheck &shadow, Context &ctxt)
 
template<typename Rel >
RamDomain evalScan (const Rel &rel, const ram::Scan &cur, const Scan &shadow, Context &ctxt)
 
RamDomain execute (const Node *, Context &)
 Execute the program. More...
 
void generateIR ()
 Generate intermediate representation from RAM. More...
 
size_t getIterationNumber () const
 Return current iteration number for loop operation. More...
 
void * getMethodHandle (const std::string &method)
 Return method handler. More...
 
RecordTablegetRecordTable ()
 Return the record table. More...
 
RelationHandlegetRelationHandle (const size_t idx)
 Return a reference to the relation on the given index. More...
 
VecOwn< RelationHandle > & getRelationMap ()
 Return the relation map. More...
 
SymbolTablegetSymbolTable ()
 Return the string symbol table. More...
 
ram::TranslationUnitgetTranslationUnit ()
 Return the ram::TranslationUnit. More...
 
int incCounter ()
 Increment the counter. More...
 
void incIterationNumber ()
 Increase iteration number by one. More...
 
const std::vector< void * > & loadDLL ()
 Load DLL. More...
 
void resetIterationNumber ()
 Reset iteration number. More...
 
void swapRelation (const size_t ramRel1, const size_t ramRel2)
 Swap the content of two relations. More...
 

Private Attributes

std::atomic< RamDomaincounter {0}
 Profile counter. More...
 
std::vector< void * > dll
 DLL. More...
 
std::map< std::string, std::deque< std::atomic< size_t > > > frequencies
 Profile for rule frequencies. More...
 
ram::analysis::IndexAnalysisisa
 IndexAnalysis. More...
 
const bool isProvenance
 If running a provenance program. More...
 
size_t iteration = 0
 Loop iteration counter. More...
 
Own< Nodemain
 main program More...
 
friend NodeGenerator
 
size_t numOfThreads
 Number of threads enabled for this program. More...
 
const bool profileEnabled
 If profile is enable in this program. More...
 
friend ProgInterface
 
std::map< std::string, std::atomic< size_t > > reads
 Profile for relation reads. More...
 
RecordTable recordTable
 Record Table. More...
 
VecOwn< RelationHandlerelations
 Symbol table for relations. More...
 
VecOwn< Nodesubroutine
 subroutines More...
 
ram::TranslationUnittUnit
 Program. More...
 

Detailed Description

This class translate the RAM Program into executable format and interpreter it.

Definition at line 56 of file Engine.h.

Member Typedef Documentation

◆ RelationHandle

Definition at line 57 of file Engine.h.

Constructor & Destructor Documentation

◆ Engine()

souffle::interpreter::Engine::Engine ( ram::TranslationUnit tUnit)

Definition at line 146 of file Engine.cpp.

146  {
147  omp_set_num_threads(numOfThreads);
148  }
149 #endif
150 }
151 
153  return *relations[idx];
154 }
155 

Member Function Documentation

◆ createRelation()

void souffle::interpreter::Engine::createRelation ( const ram::Relation id,
const size_t  idx 
)
private

Create and add relation into the runtime environment.


Definition at line 198 of file Engine.cpp.

200  {
201  res = createEqrelRelation(id, orderSet);
202  } else {
203  if (isProvenance) {
204  res = createProvenanceRelation(id, orderSet);
205  } else {
206  res = createBTreeRelation(id, orderSet);
207  }
208  }
209  relations[idx] = mk<RelationHandle>(std::move(res));
210 }
211 
212 const std::vector<void*>& Engine::loadDLL() {
213  if (!dll.empty()) {
214  return dll;
215  }

References souffle::interpreter::createEqrelRelation().

Here is the call graph for this function:

◆ dropRelation()

void souffle::interpreter::Engine::dropRelation ( const size_t  relId)
private

Remove a relation from the environment.

◆ evalAggregate()

template<typename Aggregate , typename Iter >
RamDomain souffle::interpreter::Engine::evalAggregate ( const Aggregate aggregate,
const Node filter,
const Node expression,
const Node nestedOperation,
const Iter &  ranges,
Context ctxt 
)
private

Definition at line 1511 of file Engine.cpp.

1516  {
1517  case AggregateOp::MIN: res = ramBitCast(MAX_RAM_SIGNED); break;
1518  case AggregateOp::UMIN: res = ramBitCast(MAX_RAM_UNSIGNED); break;
1519  case AggregateOp::FMIN: res = ramBitCast(MAX_RAM_FLOAT); break;
1520 
1521  case AggregateOp::MAX: res = ramBitCast(MIN_RAM_SIGNED); break;
1522  case AggregateOp::UMAX: res = ramBitCast(MIN_RAM_UNSIGNED); break;
1523  case AggregateOp::FMAX: res = ramBitCast(MIN_RAM_FLOAT); break;
1524 
1525  case AggregateOp::SUM:
1526  res = ramBitCast(static_cast<RamSigned>(0));
1527  shouldRunNested = true;
1528  break;
1529  case AggregateOp::USUM:
1530  res = ramBitCast(static_cast<RamUnsigned>(0));
1531  shouldRunNested = true;
1532  break;
1533  case AggregateOp::FSUM:
1534  res = ramBitCast(static_cast<RamFloat>(0));
1535  shouldRunNested = true;
1536  break;
1537 
1538  case AggregateOp::MEAN:
1539  res = 0;
1540  accumulateMean = {0, 0};
1541  break;
1542 
1543  case AggregateOp::COUNT:
1544  res = 0;
1545  shouldRunNested = true;
1546  break;
1547  }
1548 
1549  for (const auto& tuple : ranges) {
1550  ctxt[aggregate.getTupleId()] = tuple.data();
1551 
1552  if (!execute(&filter, ctxt)) {
1553  continue;
1554  }
1555 
1556  shouldRunNested = true;
1557 
1558  // count is a special case.
1559  if (aggregate.getFunction() == AggregateOp::COUNT) {
1560  ++res;
1561  continue;
1562  }
1563 
1564  // eval target expression
1565  assert(expression); // only case where this is null is `COUNT`
1566  RamDomain val = execute(expression, ctxt);
1567 
1568  switch (aggregate.getFunction()) {
1569  case AggregateOp::MIN: res = std::min(res, val); break;
1570  case AggregateOp::FMIN:
1571  res = ramBitCast(std::min(ramBitCast<RamFloat>(res), ramBitCast<RamFloat>(val)));
1572  break;
1573  case AggregateOp::UMIN:
1574  res = ramBitCast(std::min(ramBitCast<RamUnsigned>(res), ramBitCast<RamUnsigned>(val)));
1575  break;
1576 
1577  case AggregateOp::MAX: res = std::max(res, val); break;
1578  case AggregateOp::FMAX:
1579  res = ramBitCast(std::max(ramBitCast<RamFloat>(res), ramBitCast<RamFloat>(val)));
1580  break;
1581  case AggregateOp::UMAX:
1582  res = ramBitCast(std::max(ramBitCast<RamUnsigned>(res), ramBitCast<RamUnsigned>(val)));
1583  break;
1584 
1585  case AggregateOp::SUM: res += val; break;
1586  case AggregateOp::FSUM:
1587  res = ramBitCast(ramBitCast<RamFloat>(res) + ramBitCast<RamFloat>(val));
1588  break;
1589  case AggregateOp::USUM:
1590  res = ramBitCast(ramBitCast<RamUnsigned>(res) + ramBitCast<RamUnsigned>(val));
1591  break;
1592 
1593  case AggregateOp::MEAN:
1594  accumulateMean.first += ramBitCast<RamFloat>(val);
1595  accumulateMean.second++;
1596  break;
1597 
1598  case AggregateOp::COUNT: fatal("This should never be executed");
1599  }
1600  }
1601 
1602  if (aggregate.getFunction() == AggregateOp::MEAN && accumulateMean.second != 0) {
1603  res = ramBitCast(accumulateMean.first / accumulateMean.second);
1604  }
1605 
1606  // write result to environment
1608  tuple[0] = res;
1609  ctxt[aggregate.getTupleId()] = tuple.data();
1610 
1611  if (!shouldRunNested) {
1612  return true;
1613  } else {
1614  return execute(&nestedOperation, ctxt);
1615  }
1616 }
1617 template <typename Rel>
1619  const Rel& rel, const ram::ParallelAggregate& cur, const ParallelAggregate& shadow, Context& ctxt) {
1620  // TODO (rdowavic): make parallel
1621  auto viewContext = shadow.getViewContext();

References souffle::MAX_RAM_FLOAT, souffle::MAX_RAM_SIGNED, souffle::MAX_RAM_UNSIGNED, souffle::MIN_RAM_FLOAT, souffle::MIN_RAM_SIGNED, souffle::MIN_RAM_UNSIGNED, and souffle::ramBitCast().

Here is the call graph for this function:

◆ evalChoice()

template<typename Rel >
RamDomain souffle::interpreter::Engine::evalChoice ( const Rel &  rel,
const ram::Choice cur,
const Choice shadow,
Context ctxt 
)
private

Definition at line 1416 of file Engine.cpp.

1425  {
1426  auto viewContext = shadow.getViewContext();

◆ evalExistenceCheck()

template<typename Rel >
RamDomain souffle::interpreter::Engine::evalExistenceCheck ( const ExistenceCheck shadow,
Context ctxt 
)
private

Definition at line 1237 of file Engine.cpp.

1242  {
1244  TUPLE_COPY_FROM(tuple, superInfo.first);
1245  /* TupleElement */
1246  for (const auto& tupleElement : superInfo.tupleFirst) {
1247  tuple[tupleElement[0]] = ctxt[tupleElement[1]][tupleElement[2]];
1248  }
1249  /* Generic */
1250  for (const auto& expr : superInfo.exprFirst) {
1251  tuple[expr.first] = execute(expr.second.get(), ctxt);
1252  }
1253  return Rel::castView(ctxt.getView(viewPos))->contains(tuple);
1254  }
1255 
1256  // for partial we search for lower and upper boundaries
1259  TUPLE_COPY_FROM(low, superInfo.first);
1260  TUPLE_COPY_FROM(high, superInfo.second);
1261 
1262  /* TupleElement */
1263  for (const auto& tupleElement : superInfo.tupleFirst) {
1264  low[tupleElement[0]] = ctxt[tupleElement[1]][tupleElement[2]];
1265  high[tupleElement[0]] = low[tupleElement[0]];
1266  }
1267  /* Generic */
1268  for (const auto& expr : superInfo.exprFirst) {
1269  low[expr.first] = execute(expr.second.get(), ctxt);
1270  high[expr.first] = low[expr.first];
1271  }
1272 
1273  return Rel::castView(ctxt.getView(viewPos))->contains(low, high);
1274 }
1275 
1276 template <typename Rel>
1277 RamDomain Engine::evalProvenanceExistenceCheck(const ProvenanceExistenceCheck& shadow, Context& ctxt) {
1278  // construct the pattern tuple
1279  constexpr size_t Arity = Rel::Arity;

◆ evalIndexAggregate()

template<typename Rel >
RamDomain souffle::interpreter::Engine::evalIndexAggregate ( const ram::IndexAggregate cur,
const IndexAggregate shadow,
Context ctxt 
)
private

Definition at line 1664 of file Engine.cpp.

1676  {
1677  constexpr size_t Arity = Rel::Arity;
1678  const auto& superInfo = shadow.getSuperInst();

◆ evalIndexChoice()

template<typename Rel >
RamDomain souffle::interpreter::Engine::evalIndexChoice ( const ram::IndexChoice cur,
const IndexChoice shadow,
Context ctxt 
)
private

Definition at line 1454 of file Engine.cpp.

1459  : view->range(low, high)) {
1460  ctxt[cur.getTupleId()] = tuple.data();
1461  if (execute(shadow.getCondition(), ctxt)) {
1462  execute(shadow.getNestedOperation(), ctxt);
1463  break;
1464  }
1465  }
1466  return true;
1467 }
1468 
1469 template <typename Rel>
1470 RamDomain Engine::evalParallelIndexChoice(const Rel& rel, const ram::ParallelIndexChoice& cur,
1471  const ParallelIndexChoice& shadow, Context& ctxt) {
1472  auto viewContext = shadow.getViewContext();

◆ evalIndexScan()

template<typename Rel >
RamDomain souffle::interpreter::Engine::evalIndexScan ( const ram::IndexScan cur,
const IndexScan shadow,
Context ctxt 
)
private

Definition at line 1363 of file Engine.cpp.

1369  : view->range(low, high)) {
1370  ctxt[cur.getTupleId()] = tuple.data();
1371  if (!execute(shadow.getNestedOperation(), ctxt)) {
1372  break;
1373  }
1374  }
1375  return true;
1376 }
1377 
1378 template <typename Rel>
1380  const Rel& rel, const ram::ParallelIndexScan& cur, const ParallelIndexScan& shadow, Context& ctxt) {
1381  auto viewContext = shadow.getViewContext();

◆ evalParallelAggregate()

template<typename Rel >
RamDomain souffle::interpreter::Engine::evalParallelAggregate ( const Rel &  rel,
const ram::ParallelAggregate cur,
const ParallelAggregate shadow,
Context ctxt 
)
private

Definition at line 1623 of file Engine.cpp.

1625  : viewInfo) {
1626  newCtxt.createView(*getRelationHandle(info[0]), info[1], info[2]);
1627  }
1628  return evalAggregate(
1629  cur, *shadow.getCondition(), shadow.getExpr(), *shadow.getNestedOperation(), rel.scan(), newCtxt);
1630 }
1631 
1632 template <typename Rel>
1634  const ram::ParallelIndexAggregate& cur, const ParallelIndexAggregate& shadow, Context& ctxt) {
1635  // TODO (rdowavic): make parallel

◆ evalParallelChoice()

template<typename Rel >
RamDomain souffle::interpreter::Engine::evalParallelChoice ( const Rel &  rel,
const ram::ParallelChoice cur,
const ParallelChoice shadow,
Context ctxt 
)
private

Definition at line 1429 of file Engine.cpp.

1432  : viewInfo) {
1433  newCtxt.createView(*getRelationHandle(info[0]), info[1], info[2]);
1434  }
1435  pfor(auto it = pStream.begin(); it < pStream.end(); it++) {
1436  for (const auto& tuple : *it) {
1437  newCtxt[cur.getTupleId()] = tuple.data();
1438  if (execute(shadow.getCondition(), newCtxt)) {
1439  execute(shadow.getNestedOperation(), newCtxt);
1440  break;
1441  }
1442  }
1443  }
1444  PARALLEL_END
1445  return true;
1446 }
1447 
1448 template <typename Rel>
1449 RamDomain Engine::evalIndexChoice(const ram::IndexChoice& cur, const IndexChoice& shadow, Context& ctxt) {
1450  constexpr size_t Arity = Rel::Arity;
1451  const auto& superInfo = shadow.getSuperInst();

◆ evalParallelIndexAggregate()

template<typename Rel >
RamDomain souffle::interpreter::Engine::evalParallelIndexAggregate ( const ram::ParallelIndexAggregate cur,
const ParallelIndexAggregate shadow,
Context ctxt 
)
private

Definition at line 1638 of file Engine.cpp.

1640  : viewInfo) {
1641  newCtxt.createView(*getRelationHandle(info[0]), info[1], info[2]);
1642  }
1643  // init temporary tuple for this level
1644  constexpr size_t Arity = Rel::Arity;
1645  const auto& superInfo = shadow.getSuperInst();
1646  // get lower and upper boundaries for iteration
1649  CAL_SEARCH_BOUND(superInfo, low, high);
1650 
1651  size_t viewId = shadow.getViewId();
1652  auto view = Rel::castView(newCtxt.getView(viewId));
1653 
1654  return evalAggregate(cur, *shadow.getCondition(), shadow.getExpr(), *shadow.getNestedOperation(),
1655  view->range(low, high), newCtxt);
1656 }
1657 
1658 template <typename Rel>
1660  const ram::IndexAggregate& cur, const IndexAggregate& shadow, Context& ctxt) {
1661  // init temporary tuple for this level

◆ evalParallelIndexChoice()

template<typename Rel >
RamDomain souffle::interpreter::Engine::evalParallelIndexChoice ( const Rel &  rel,
const ram::ParallelIndexChoice cur,
const ParallelIndexChoice shadow,
Context ctxt 
)
private

Definition at line 1475 of file Engine.cpp.

1488  : viewInfo) {
1489  newCtxt.createView(*getRelationHandle(info[0]), info[1], info[2]);
1490  }
1491  pfor(auto it = pStream.begin(); it < pStream.end(); it++) {
1492  for (const auto& tuple : *it) {
1493  newCtxt[cur.getTupleId()] = tuple.data();
1494  if (execute(shadow.getCondition(), newCtxt)) {
1495  execute(shadow.getNestedOperation(), newCtxt);
1496  break;
1497  }
1498  }
1499  }
1500  PARALLEL_END
1501 
1502  return true;
1503 }
1504 
1505 template <typename Aggregate, typename Iter>
1506 RamDomain Engine::evalAggregate(const Aggregate& aggregate, const Node& filter, const Node* expression,
1507  const Node& nestedOperation, const Iter& ranges, Context& ctxt) {
1508  bool shouldRunNested = false;

◆ evalParallelIndexScan()

template<typename Rel >
RamDomain souffle::interpreter::Engine::evalParallelIndexScan ( const Rel &  rel,
const ram::ParallelIndexScan cur,
const ParallelIndexScan shadow,
Context ctxt 
)
private

Definition at line 1384 of file Engine.cpp.

1395  : viewInfo) {
1396  newCtxt.createView(*getRelationHandle(info[0]), info[1], info[2]);
1397  }
1398  pfor(auto it = pStream.begin(); it < pStream.end(); it++) {
1399  for (const auto& tuple : *it) {
1400  newCtxt[cur.getTupleId()] = tuple.data();
1401  if (!execute(shadow.getNestedOperation(), newCtxt)) {
1402  break;
1403  }
1404  }
1405  }
1406  PARALLEL_END
1407  return true;
1408 }
1409 
1410 template <typename Rel>
1411 RamDomain Engine::evalChoice(const Rel& rel, const ram::Choice& cur, const Choice& shadow, Context& ctxt) {
1412  // use simple iterator
1413  for (const auto& tuple : rel.scan()) {

◆ evalParallelScan()

template<typename Rel >
RamDomain souffle::interpreter::Engine::evalParallelScan ( const Rel &  rel,
const ram::ParallelScan cur,
const ParallelScan shadow,
Context ctxt 
)
private

Definition at line 1338 of file Engine.cpp.

1342  : viewInfo) {
1343  newCtxt.createView(*getRelationHandle(info[0]), info[1], info[2]);
1344  }
1345  pfor(auto it = pStream.begin(); it < pStream.end(); it++) {
1346  for (const auto& tuple : *it) {
1347  newCtxt[cur.getTupleId()] = tuple.data();
1348  if (!execute(shadow.getNestedOperation(), newCtxt)) {
1349  break;
1350  }
1351  }
1352  }
1353  PARALLEL_END
1354  return true;
1355 }
1356 
1357 template <typename Rel>
1358 RamDomain Engine::evalIndexScan(const ram::IndexScan& cur, const IndexScan& shadow, Context& ctxt) {
1359  constexpr size_t Arity = Rel::Arity;
1360  // create pattern tuple for range query

◆ evalProject()

template<typename Rel >
RamDomain souffle::interpreter::Engine::evalProject ( Rel &  rel,
const Project shadow,
Context ctxt 
)
private

Definition at line 1681 of file Engine.cpp.

1683  : superInfo.tupleFirst) {
1684  tuple[tupleElement[0]] = ctxt[tupleElement[1]][tupleElement[2]];
1685  }
1686  /* Generic */
1687  for (const auto& expr : superInfo.exprFirst) {
1688  tuple[expr.first] = execute(expr.second.get(), ctxt);
1689  }
1690 
1691  // insert in target relation
1692  rel.insert(tuple);
1693  return true;
1694 }
1695 
1696 } // namespace souffle::interpreter

◆ evalProvenanceExistenceCheck()

template<typename Rel >
RamDomain souffle::interpreter::Engine::evalProvenanceExistenceCheck ( const ProvenanceExistenceCheck shadow,
Context ctxt 
)
private

Definition at line 1282 of file Engine.cpp.

1289  : superInfo.tupleFirst) {
1290  low[tupleElement[0]] = ctxt[tupleElement[1]][tupleElement[2]];
1291  high[tupleElement[0]] = low[tupleElement[0]];
1292  }
1293  /* Generic */
1294  for (const auto& expr : superInfo.exprFirst) {
1295  assert(expr.second.get() != nullptr &&
1296  "ProvenanceExistenceCheck should always be specified for payload");
1297  low[expr.first] = execute(expr.second.get(), ctxt);
1298  high[expr.first] = low[expr.first];
1299  }
1300 
1301  low[Arity - 2] = MIN_RAM_SIGNED;
1302  low[Arity - 1] = MIN_RAM_SIGNED;
1303  high[Arity - 2] = MAX_RAM_SIGNED;
1304  high[Arity - 1] = MAX_RAM_SIGNED;
1305 
1306  // obtain view
1307  size_t viewPos = shadow.getViewId();
1308 
1309  // get an equalRange
1310  auto equalRange = Rel::castView(ctxt.getView(viewPos))->range(low, high);
1311 
1312  // if range is empty
1313  if (equalRange.begin() == equalRange.end()) {
1314  return false;
1315  }
1316 
1317  // check whether the height is less than the current height
1318  return (*equalRange.begin())[Arity - 1] <= execute(shadow.getChild(), ctxt);
1319 }
1320 
1321 template <typename Rel>
1322 RamDomain Engine::evalScan(const Rel& rel, const ram::Scan& cur, const Scan& shadow, Context& ctxt) {
1323  for (const auto& tuple : rel.scan()) {
1324  ctxt[cur.getTupleId()] = tuple.data();

◆ evalScan()

template<typename Rel >
RamDomain souffle::interpreter::Engine::evalScan ( const Rel &  rel,
const ram::Scan cur,
const Scan shadow,
Context ctxt 
)
private

Definition at line 1327 of file Engine.cpp.

1334  {
1335  auto viewContext = shadow.getViewContext();

◆ execute()

RamDomain souffle::interpreter::Engine::execute ( const Node node,
Context ctxt 
)
private

Execute the program.

Unary Functor Operators

numeric coersions follow C++ semantics.

Binary Functor Operators

Ternary Functor Operators

Definition at line 359 of file Engine.cpp.

367  : { \
368  return [&]() -> RamDomain { \
369  [[maybe_unused]] const auto& shadow = *static_cast<const interpreter::Kind*>(node); \
370  [[maybe_unused]] const auto& cur = *static_cast<const ram::Kind*>(node->getShadow());
371 // EXTEND_CASE also defer the relation type
372 #define EXTEND_CASE(Kind, Structure, Arity) \
373  case (I_##Kind##_##Structure##_##Arity): { \
374  return [&]() -> RamDomain { \
375  [[maybe_unused]] const auto& shadow = *static_cast<const interpreter::Kind*>(node); \
376  [[maybe_unused]] const auto& cur = *static_cast<const ram::Kind*>(node->getShadow());\
377  using RelType = Relation<Arity, interpreter::Structure>;
378 #define ESAC(Kind) \
379  } \
380  (); \
381  }
382 
383 #define TUPLE_COPY_FROM(dst, src) \
384  assert(dst.size() == src.size()); \
385  std::copy_n(src.begin(), dst.size(), dst.begin())
386 
387 #define CAL_SEARCH_BOUND(superInfo, low, high) \
388  /** Unbounded and Constant */ \
389  TUPLE_COPY_FROM(low, superInfo.first); \
390  TUPLE_COPY_FROM(high, superInfo.second); \
391  /* TupleElement */ \
392  for (const auto& tupleElement : superInfo.tupleFirst) { \
393  low[tupleElement[0]] = ctxt[tupleElement[1]][tupleElement[2]]; \
394  } \
395  for (const auto& tupleElement : superInfo.tupleSecond) { \
396  high[tupleElement[0]] = ctxt[tupleElement[1]][tupleElement[2]]; \
397  } \
398  /* Generic */ \
399  for (const auto& expr : superInfo.exprFirst) { \
400  low[expr.first] = execute(expr.second.get(), ctxt); \
401  } \
402  for (const auto& expr : superInfo.exprSecond) { \
403  high[expr.first] = execute(expr.second.get(), ctxt); \
404  }
405 
406  switch (node->getType()) {
407  CASE(Constant)
408  return cur.getConstant();
409  ESAC(Constant)
410 
411  CASE(TupleElement)
412  return ctxt[shadow.getTupleId()][shadow.getElement()];
413  ESAC(TupleElement)
414 
415  CASE(AutoIncrement)
416  return incCounter();
417  ESAC(AutoIncrement)
418 
419  CASE(IntrinsicOperator)
420 // clang-format off
421 #define BINARY_OP_TYPED(ty, op) return ramBitCast(static_cast<ty>(EVAL_CHILD(ty, 0) op EVAL_CHILD(ty, 1)))
422 
423 #define BINARY_OP_LOGICAL(opcode, op) BINARY_OP_INTEGRAL(opcode, op)
424 #define BINARY_OP_INTEGRAL(opcode, op) \
425  case FunctorOp:: opcode: BINARY_OP_TYPED(RamSigned , op); \
426  case FunctorOp::U##opcode: BINARY_OP_TYPED(RamUnsigned, op);
427 #define BINARY_OP_NUMERIC(opcode, op) \
428  BINARY_OP_INTEGRAL(opcode, op) \
429  case FunctorOp::F##opcode: BINARY_OP_TYPED(RamFloat, op);
430 
431 #define BINARY_OP_SHIFT_MASK(ty, op) \
432  return ramBitCast(EVAL_CHILD(ty, 0) op (EVAL_CHILD(ty, 1) & RAM_BIT_SHIFT_MASK))
433 #define BINARY_OP_INTEGRAL_SHIFT(opcode, op, tySigned, tyUnsigned) \
434  case FunctorOp:: opcode: BINARY_OP_SHIFT_MASK(tySigned , op); \
435  case FunctorOp::U##opcode: BINARY_OP_SHIFT_MASK(tyUnsigned , op);
436 
437 #define MINMAX_OP_SYM(op) \
438  { \
439  auto result = EVAL_CHILD(RamDomain, 0); \
440  auto* result_val = &getSymbolTable().resolve(result); \
441  for (size_t i = 1; i < args.size(); i++) { \
442  auto alt = EVAL_CHILD(RamDomain, i); \
443  if (alt == result) continue; \
444  \
445  const auto& alt_val = getSymbolTable().resolve(alt); \
446  if (*result_val op alt_val) { \
447  result_val = &alt_val; \
448  result = alt; \
449  } \
450  } \
451  return result; \
452  }
453 #define MINMAX_OP(ty, op) \
454  { \
455  auto result = EVAL_CHILD(ty, 0); \
456  for (size_t i = 1; i < args.size(); i++) { \
457  result = op(result, EVAL_CHILD(ty, i)); \
458  } \
459  return ramBitCast(result); \
460  }
461 #define MINMAX_NUMERIC(opCode, op) \
462  case FunctorOp:: opCode: MINMAX_OP(RamSigned , op) \
463  case FunctorOp::U##opCode: MINMAX_OP(RamUnsigned, op) \
464  case FunctorOp::F##opCode: MINMAX_OP(RamFloat , op)
465 
466 #define UNARY_OP(op, ty, func) \
467  case FunctorOp::op: { \
468  auto x = EVAL_CHILD(ty, 0); \
469  return ramBitCast(func(x)); \
470  }
471 #define CONV_TO_STRING(op, ty) \
472  case FunctorOp::op: return getSymbolTable().lookup(std::to_string(EVAL_CHILD(ty, 0)));
473 #define CONV_FROM_STRING(op, ty) \
474  case FunctorOp::op: return evaluator::symbol2numeric<ty>( \
475  getSymbolTable().resolve(EVAL_CHILD(RamDomain, 0)));
476  // clang-format on
477 
478  const auto& args = cur.getArguments();
479  switch (cur.getOperator()) {
480  /** Unary Functor Operators */
481  case FunctorOp::ORD: return execute(shadow.getChild(0), ctxt);
482  case FunctorOp::STRLEN:
483  return getSymbolTable().resolve(execute(shadow.getChild(0), ctxt)).size();
484  case FunctorOp::NEG: return -execute(shadow.getChild(0), ctxt);
485  case FunctorOp::FNEG: {
486  RamDomain result = execute(shadow.getChild(0), ctxt);
487  return ramBitCast(-ramBitCast<RamFloat>(result));
488  }
489  case FunctorOp::BNOT: return ~execute(shadow.getChild(0), ctxt);
490  case FunctorOp::UBNOT: {
491  RamDomain result = execute(shadow.getChild(0), ctxt);
492  return ramBitCast(~ramBitCast<RamUnsigned>(result));
493  }
494  case FunctorOp::LNOT: return !execute(shadow.getChild(0), ctxt);
495 
496  case FunctorOp::ULNOT: {
497  RamDomain result = execute(shadow.getChild(0), ctxt);
498  // Casting is a bit tricky here, since ! returns a boolean.
499  return ramBitCast(static_cast<RamUnsigned>(!ramBitCast<RamUnsigned>(result)));
500  }
501 
502  // clang-format off
503  /** numeric coersions follow C++ semantics. */
504  UNARY_OP(F2I, RamFloat , static_cast<RamSigned>)
505  UNARY_OP(F2U, RamFloat , static_cast<RamUnsigned>)
506  UNARY_OP(I2U, RamSigned , static_cast<RamUnsigned>)
507  UNARY_OP(I2F, RamSigned , static_cast<RamFloat>)
508  UNARY_OP(U2I, RamUnsigned, static_cast<RamSigned>)
509  UNARY_OP(U2F, RamUnsigned, static_cast<RamFloat>)
510 
514 
518 
519  /** Binary Functor Operators */
520  BINARY_OP_NUMERIC(ADD, +)
521  BINARY_OP_NUMERIC(SUB, -)
522  BINARY_OP_NUMERIC(MUL, *)
523  BINARY_OP_NUMERIC(DIV, /)
524  // clang-format on
525 
526  case FunctorOp::EXP: {
527  return std::pow(execute(shadow.getChild(0), ctxt), execute(shadow.getChild(1), ctxt));
528  }
529 
530  case FunctorOp::UEXP: {
531  auto first = ramBitCast<RamUnsigned>(execute(shadow.getChild(0), ctxt));
532  auto second = ramBitCast<RamUnsigned>(execute(shadow.getChild(1), ctxt));
533  // Extra casting required: pow returns a floating point.
534  return ramBitCast(static_cast<RamUnsigned>(std::pow(first, second)));
535  }
536 
537  case FunctorOp::FEXP: {
538  auto first = ramBitCast<RamFloat>(execute(shadow.getChild(0), ctxt));
539  auto second = ramBitCast<RamFloat>(execute(shadow.getChild(1), ctxt));
540  return ramBitCast(static_cast<RamFloat>(std::pow(first, second)));
541  }
542 
543  // clang-format off
544  BINARY_OP_INTEGRAL(MOD, %)
545  BINARY_OP_INTEGRAL(BAND, &)
546  BINARY_OP_INTEGRAL(BOR, |)
547  BINARY_OP_INTEGRAL(BXOR, ^)
548  // Handle left-shift as unsigned to match Java semantics of `<<`, namely:
549  // "... `n << s` is `n` left-shifted `s` bit positions; ..."
550  // Using `RamSigned` would imply UB due to signed overflow when shifting negatives.
552  // For right-shift, we do need sign extension.
554  BINARY_OP_INTEGRAL_SHIFT(BSHIFT_R_UNSIGNED, >>, RamUnsigned, RamUnsigned)
555 
556  BINARY_OP_LOGICAL(LAND, &&)
557  BINARY_OP_LOGICAL(LOR , ||)
558  BINARY_OP_LOGICAL(LXOR, + souffle::evaluator::lxor_infix() +)
559 
560  MINMAX_NUMERIC(MAX, std::max)
561  MINMAX_NUMERIC(MIN, std::min)
562 
563  case FunctorOp::SMAX: MINMAX_OP_SYM(<)
564  case FunctorOp::SMIN: MINMAX_OP_SYM(>)
565  // clang-format on
566 
567  case FunctorOp::CAT: {
568  std::stringstream ss;
569  for (size_t i = 0; i < args.size(); i++) {
570  ss << getSymbolTable().resolve(execute(shadow.getChild(i), ctxt));
571  }
572  return getSymbolTable().lookup(ss.str());
573  }
574  /** Ternary Functor Operators */
575  case FunctorOp::SUBSTR: {
576  auto symbol = execute(shadow.getChild(0), ctxt);
577  const std::string& str = getSymbolTable().resolve(symbol);
578  auto idx = execute(shadow.getChild(1), ctxt);
579  auto len = execute(shadow.getChild(2), ctxt);
580  std::string sub_str;
581  try {
582  sub_str = str.substr(idx, len);
583  } catch (...) {
584  std::cerr << "warning: wrong index position provided by substr(\"";
585  std::cerr << str << "\"," << (int32_t)idx << "," << (int32_t)len << ") functor.\n";
586  }
587  return getSymbolTable().lookup(sub_str);
588  }
589 
590  case FunctorOp::RANGE:
591  case FunctorOp::URANGE:
592  case FunctorOp::FRANGE:
593  fatal("ICE: functor `%s` must map onto `NestedIntrinsicOperator`", cur.getOperator());
594  }
595 
597 
598 #undef BINARY_OP_LOGICAL
599 #undef BINARY_OP_INTEGRAL
600 #undef BINARY_OP_NUMERIC
601 #undef BINARY_OP_SHIFT_MASK
602 #undef BINARY_OP_INTEGRAL_SHIFT
603 #undef MINMAX_OP_SYM
604 #undef MINMAX_OP
605 #undef MINMAX_NUMERIC
606 #undef UNARY_OP
607 #undef CONV_TO_STRING
608 #undef CONV_FROM_STRING
609  ESAC(IntrinsicOperator)
610 
611  CASE(NestedIntrinsicOperator)
612  auto numArgs = cur.getArguments().size();
613  auto runNested = [&](auto&& tuple) {
614  ctxt[cur.getTupleId()] = tuple.data();
615  execute(shadow.getChild(numArgs), ctxt);
616  };
617 
618 #define RUN_RANGE(ty) \
619  numArgs == 3 \
620  ? evaluator::runRange<ty>(EVAL_CHILD(ty, 0), EVAL_CHILD(ty, 1), EVAL_CHILD(ty, 2), runNested) \
621  : evaluator::runRange<ty>(EVAL_CHILD(ty, 0), EVAL_CHILD(ty, 1), runNested), \
622  true
623 
624  switch (cur.getFunction()) {
628  }
629 
631 #undef RUN_RANGE
632  ESAC(NestedIntrinsicOperator)
633 
634  CASE(UserDefinedOperator)
635  const std::string& name = cur.getName();
636 
637  auto fn = reinterpret_cast<void (*)()>(getMethodHandle(name));
638  if (fn == nullptr) fatal("cannot find user-defined operator `%s`", name);
639  size_t arity = cur.getArguments().size();
640 
641  if (cur.isStateful()) {
642  // prepare dynamic call environment
643  ffi_cif cif;
644  ffi_type* args[arity + 2];
645  void* values[arity + 2];
646  RamDomain intVal[arity];
647  ffi_arg rc;
648 
649  /* Initialize arguments for ffi-call */
650  args[0] = args[1] = &ffi_type_pointer;
651  void* symbolTable = (void*)&getSymbolTable();
652  values[0] = &symbolTable;
653  void* recordTable = (void*)&getRecordTable();
654  values[1] = &recordTable;
655  for (size_t i = 0; i < arity; i++) {
656  intVal[i] = execute(shadow.getChild(i), ctxt);
657  args[i + 2] = &FFI_RamSigned;
658  values[i + 2] = &intVal[i];
659  }
660 
661  // Set codomain.
662  auto codomain = &FFI_RamSigned;
663 
664  // Call the external function.
665  const auto prepStatus = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, arity + 2, codomain, args);
666  if (prepStatus != FFI_OK) {
667  fatal("Failed to prepare CIF for user-defined operator `%s`; error code = %d", name,
668  prepStatus);
669  }
670  ffi_call(&cif, fn, &rc, values);
671  return static_cast<RamDomain>(rc);
672  } else {
673  // get name and type
674  const std::vector<TypeAttribute>& type = cur.getArgsTypes();
675 
676  // prepare dynamic call environment
677  ffi_cif cif;
678  ffi_type* args[arity];
679  void* values[arity];
680  RamDomain intVal[arity];
681  RamUnsigned uintVal[arity];
682  RamFloat floatVal[arity];
683  const char* strVal[arity];
684  ffi_arg rc;
685 
686  /* Initialize arguments for ffi-call */
687  for (size_t i = 0; i < arity; i++) {
688  RamDomain arg = execute(shadow.getChild(i), ctxt);
689  switch (type[i]) {
691  args[i] = &FFI_Symbol;
692  strVal[i] = getSymbolTable().resolve(arg).c_str();
693  values[i] = &strVal[i];
694  break;
696  args[i] = &FFI_RamSigned;
697  intVal[i] = arg;
698  values[i] = &intVal[i];
699  break;
701  args[i] = &FFI_RamUnsigned;
702  uintVal[i] = ramBitCast<RamUnsigned>(arg);
703  values[i] = &uintVal[i];
704  break;
706  args[i] = &FFI_RamFloat;
707  floatVal[i] = ramBitCast<RamFloat>(arg);
708  values[i] = &floatVal[i];
709  break;
710  case TypeAttribute::ADT: fatal("ADT support is not implemented");
711  case TypeAttribute::Record: fatal("Record support is not implemented");
712  }
713  }
714 
715  // Get codomain.
716  auto codomain = &FFI_RamSigned;
717  switch (cur.getReturnType()) {
718  // initialize for string value.
719  case TypeAttribute::Symbol: codomain = &FFI_Symbol; break;
720  case TypeAttribute::Signed: codomain = &FFI_RamSigned; break;
721  case TypeAttribute::Unsigned: codomain = &FFI_RamUnsigned; break;
722  case TypeAttribute::Float: codomain = &FFI_RamFloat; break;
723  case TypeAttribute::ADT: fatal("Not implemented");
724  case TypeAttribute::Record: fatal("Not implemented");
725  }
726 
727  // Call the external function.
728  const auto prepStatus = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, arity, codomain, args);
729  if (prepStatus != FFI_OK) {
730  fatal("Failed to prepare CIF for user-defined operator `%s`; error code = %d", name,
731  prepStatus);
732  }
733  ffi_call(&cif, fn, &rc, values);
734 
735  switch (cur.getReturnType()) {
736  case TypeAttribute::Signed: return static_cast<RamDomain>(rc);
738  return getSymbolTable().lookup(reinterpret_cast<const char*>(rc));
739 
740  case TypeAttribute::Unsigned: return ramBitCast(static_cast<RamUnsigned>(rc));
741  case TypeAttribute::Float: return ramBitCast(static_cast<RamFloat>(rc));
742  case TypeAttribute::ADT: fatal("Not implemented");
743  case TypeAttribute::Record: fatal("Not implemented");
744  }
745  fatal("Unsupported user defined operator");
746  }
747 
748  ESAC(UserDefinedOperator)
749 
750  CASE(PackRecord)
751  auto values = cur.getArguments();
752  size_t arity = values.size();
753  RamDomain data[arity];
754  for (size_t i = 0; i < arity; ++i) {
755  data[i] = execute(shadow.getChild(i), ctxt);
756  }
757  return getRecordTable().pack(data, arity);
758  ESAC(PackRecord)
759 
760  CASE(SubroutineArgument)
761  return ctxt.getArgument(cur.getArgument());
762  ESAC(SubroutineArgument)
763 
764  CASE(True)
765  return true;
766  ESAC(True)
767 
768  CASE(False)
769  return false;
770  ESAC(False)
771 
772  CASE(Conjunction)
773  return execute(shadow.getLhs(), ctxt) && execute(shadow.getRhs(), ctxt);
774  ESAC(Conjunction)
775 
776  CASE(Negation)
777  return !execute(shadow.getChild(), ctxt);
778  ESAC(Negation)
779 
780 #define EMPTINESS_CHECK(Structure, Arity, ...) \
781  CASE(EmptinessCheck, Structure, Arity) \
782  const auto& rel = *static_cast<RelType*>(node->getRelation()); \
783  return rel.empty(); \
784  ESAC(EmptinessCheck)
785 
787 #undef EMPTINESS_CHECK
788 
789 #define RELATION_SIZE(Structure, Arity, ...) \
790  CASE(RelationSize, Structure, Arity) \
791  const auto& rel = *static_cast<RelType*>(node->getRelation()); \
792  return rel.size(); \
793  ESAC(RelationSize)
794 
796 #undef RELATION_SIZE
797 
798 #define EXISTENCE_CHECK(Structure, Arity, ...) \
799  CASE(ExistenceCheck, Structure, Arity) \
800  return evalExistenceCheck<RelType>(shadow, ctxt); \
801  ESAC(ExistenceCheck)
802 
804 #undef EXISTENCE_CHECK
805 
806 #define PROVENANCE_EXISTENCE_CHECK(Structure, Arity, ...) \
807  CASE(ProvenanceExistenceCheck, Structure, Arity) \
808  return evalProvenanceExistenceCheck<RelType>(shadow, ctxt); \
809  ESAC(ProvenanceExistenceCheck)
810 
812 #undef PROVENANCE_EXISTENCE_CHECK
813 
814  CASE(Constraint)
815  // clang-format off
816 #define COMPARE_NUMERIC(ty, op) return EVAL_LEFT(ty) op EVAL_RIGHT(ty)
817 #define COMPARE_STRING(op) \
818  return (getSymbolTable().resolve(EVAL_LEFT(RamDomain)) op \
819  getSymbolTable().resolve(EVAL_RIGHT(RamDomain)))
820 #define COMPARE_EQ_NE(opCode, op) \
821  case BinaryConstraintOp:: opCode: COMPARE_NUMERIC(RamDomain , op); \
822  case BinaryConstraintOp::F##opCode: COMPARE_NUMERIC(RamFloat , op);
823 #define COMPARE(opCode, op) \
824  case BinaryConstraintOp:: opCode: COMPARE_NUMERIC(RamSigned , op); \
825  case BinaryConstraintOp::U##opCode: COMPARE_NUMERIC(RamUnsigned, op); \
826  case BinaryConstraintOp::F##opCode: COMPARE_NUMERIC(RamFloat , op); \
827  case BinaryConstraintOp::S##opCode: COMPARE_STRING(op);
828  // clang-format on
829 
830  switch (cur.getOperator()) {
831  COMPARE_EQ_NE(EQ, ==)
832  COMPARE_EQ_NE(NE, !=)
833 
834  COMPARE(LT, <)
835  COMPARE(LE, <=)
836  COMPARE(GT, >)
837  COMPARE(GE, >=)
838 
839  case BinaryConstraintOp::MATCH: {
840  RamDomain left = execute(shadow.getLhs(), ctxt);
841  RamDomain right = execute(shadow.getRhs(), ctxt);
842  const std::string& pattern = getSymbolTable().resolve(left);
843  const std::string& text = getSymbolTable().resolve(right);
844  bool result = false;
845  try {
846  result = std::regex_match(text, std::regex(pattern));
847  } catch (...) {
848  std::cerr << "warning: wrong pattern provided for match(\"" << pattern << "\",\""
849  << text << "\").\n";
850  }
851  return result;
852  }
854  RamDomain left = execute(shadow.getLhs(), ctxt);
855  RamDomain right = execute(shadow.getRhs(), ctxt);
856  const std::string& pattern = getSymbolTable().resolve(left);
857  const std::string& text = getSymbolTable().resolve(right);
858  bool result = false;
859  try {
860  result = !std::regex_match(text, std::regex(pattern));
861  } catch (...) {
862  std::cerr << "warning: wrong pattern provided for !match(\"" << pattern << "\",\""
863  << text << "\").\n";
864  }
865  return result;
866  }
868  RamDomain left = execute(shadow.getLhs(), ctxt);
869  RamDomain right = execute(shadow.getRhs(), ctxt);
870  const std::string& pattern = getSymbolTable().resolve(left);
871  const std::string& text = getSymbolTable().resolve(right);
872  return text.find(pattern) != std::string::npos;
873  }
875  RamDomain left = execute(shadow.getLhs(), ctxt);
876  RamDomain right = execute(shadow.getRhs(), ctxt);
877  const std::string& pattern = getSymbolTable().resolve(left);
878  const std::string& text = getSymbolTable().resolve(right);
879  return text.find(pattern) == std::string::npos;
880  }
881  }
882 
884 
885 #undef COMPARE_NUMERIC
886 #undef COMPARE_STRING
887 #undef COMPARE
888 #undef COMPARE_EQ_NE
889  ESAC(Constraint)
890 
891  CASE(TupleOperation)
892  bool result = execute(shadow.getChild(), ctxt);
893 
894  if (profileEnabled && !cur.getProfileText().empty()) {
895  auto& currentFrequencies = frequencies[cur.getProfileText()];
896  while (currentFrequencies.size() <= getIterationNumber()) {
897 #pragma omp critical(frequencies)
898  currentFrequencies.emplace_back(0);
899  }
900  frequencies[cur.getProfileText()][getIterationNumber()]++;
901  }
902  return result;
903  ESAC(TupleOperation)
904 
905 #define SCAN(Structure, Arity, ...) \
906  CASE(Scan, Structure, Arity) \
907  const auto& rel = *static_cast<RelType*>(node->getRelation()); \
908  return evalScan(rel, cur, shadow, ctxt); \
909  ESAC(Scan)
910 
911  FOR_EACH(SCAN)
912 #undef SCAN
913 
914 #define PARALLEL_SCAN(Structure, Arity, ...) \
915  CASE(ParallelScan, Structure, Arity) \
916  const auto& rel = *static_cast<RelType*>(node->getRelation()); \
917  return evalParallelScan(rel, cur, shadow, ctxt); \
918  ESAC(ParallelScan)
920 #undef PARALLEL_SCAN
921 
922 #define INDEX_SCAN(Structure, Arity, ...) \
923  CASE(IndexScan, Structure, Arity) \
924  return evalIndexScan<RelType>(cur, shadow, ctxt); \
925  ESAC(IndexScan)
926 
928 #undef INDEX_SCAN
929 
930 #define PARALLEL_INDEX_SCAN(Structure, Arity, ...) \
931  CASE(ParallelIndexScan, Structure, Arity) \
932  const auto& rel = *static_cast<RelType*>(node->getRelation()); \
933  return evalParallelIndexScan(rel, cur, shadow, ctxt); \
934  ESAC(ParallelIndexScan)
935 
937 #undef PARALLEL_INDEX_SCAN
938 
939 #define CHOICE(Structure, Arity, ...) \
940  CASE(Choice, Structure, Arity) \
941  const auto& rel = *static_cast<RelType*>(node->getRelation()); \
942  return evalChoice(rel, cur, shadow, ctxt); \
943  ESAC(Choice)
944 
946 #undef CHOICE
947 
948 #define PARALLEL_CHOICE(Structure, Arity, ...) \
949  CASE(ParallelChoice, Structure, Arity) \
950  const auto& rel = *static_cast<RelType*>(node->getRelation()); \
951  return evalParallelChoice(rel, cur, shadow, ctxt); \
952  ESAC(ParallelChoice)
953 
955 #undef PARALLEL_CHOICE
956 
957 #define INDEX_CHOICE(Structure, Arity, ...) \
958  CASE(IndexChoice, Structure, Arity) \
959  return evalIndexChoice<RelType>(cur, shadow, ctxt); \
960  ESAC(IndexChoice)
961 
963 #undef INDEX_CHOICE
964 
965 #define PARALLEL_INDEX_CHOICE(Structure, Arity, ...) \
966  CASE(ParallelIndexChoice, Structure, Arity) \
967  const auto& rel = *static_cast<RelType*>(node->getRelation()); \
968  return evalParallelIndexChoice(rel, cur, shadow, ctxt); \
969  ESAC(ParallelIndexChoice)
970 
972 #undef PARALLEL_INDEX_CHOICE
973 
974  CASE(UnpackRecord)
975  RamDomain ref = execute(shadow.getExpr(), ctxt);
976 
977  // check for nil
978  if (ref == 0) {
979  return true;
980  }
981 
982  // update environment variable
983  size_t arity = cur.getArity();
984  const RamDomain* tuple = getRecordTable().unpack(ref, arity);
985 
986  // save reference to temporary value
987  ctxt[cur.getTupleId()] = tuple;
988 
989  // run nested part - using base class visitor
990  return execute(shadow.getNestedOperation(), ctxt);
991  ESAC(UnpackRecord)
992 
993 #define PARALLEL_AGGREGATE(Structure, Arity, ...) \
994  CASE(ParallelAggregate, Structure, Arity) \
995  const auto& rel = *static_cast<RelType*>(node->getRelation()); \
996  return evalParallelAggregate(rel, cur, shadow, ctxt); \
997  ESAC(ParallelAggregate)
998 
1000 #undef PARALLEL_AGGREGATE
1001 
1002 #define AGGREGATE(Structure, Arity, ...) \
1003  CASE(Aggregate, Structure, Arity) \
1004  const auto& rel = *static_cast<RelType*>(node->getRelation()); \
1005  return evalAggregate(cur, *shadow.getCondition(), shadow.getExpr(), *shadow.getNestedOperation(), \
1006  rel.scan(), ctxt); \
1007  ESAC(Aggregate)
1008 
1010 #undef AGGREGATE
1011 
1012 #define PARALLEL_INDEX_AGGREGATE(Structure, Arity, ...) \
1013  CASE(ParallelIndexAggregate, Structure, Arity) \
1014  return evalParallelIndexAggregate<RelType>(cur, shadow, ctxt); \
1015  ESAC(ParallelIndexAggregate)
1016 
1018 #undef PARALLEL_INDEX_AGGREGATE
1019 
1020 #define INDEX_AGGREGATE(Structure, Arity, ...) \
1021  CASE(IndexAggregate, Structure, Arity) \
1022  return evalIndexAggregate<RelType>(cur, shadow, ctxt); \
1023  ESAC(IndexAggregate)
1024 
1026 #undef INDEX_AGGREGATE
1027 
1028  CASE(Break)
1029  // check condition
1030  if (execute(shadow.getCondition(), ctxt)) {
1031  return false;
1032  }
1033  return execute(shadow.getNestedOperation(), ctxt);
1034  ESAC(Break)
1035 
1036  CASE(Filter)
1037  bool result = true;
1038  // check condition
1039  if (execute(shadow.getCondition(), ctxt)) {
1040  // process nested
1041  result = execute(shadow.getNestedOperation(), ctxt);
1042  }
1043 
1044  if (profileEnabled && !cur.getProfileText().empty()) {
1045  auto& currentFrequencies = frequencies[cur.getProfileText()];
1046  while (currentFrequencies.size() <= getIterationNumber()) {
1047  currentFrequencies.emplace_back(0);
1048  }
1049  frequencies[cur.getProfileText()][getIterationNumber()]++;
1050  }
1051  return result;
1052  ESAC(Filter)
1053 
1054 #define PROJECT(Structure, Arity, ...) \
1055  CASE(Project, Structure, Arity) \
1056  auto& rel = *static_cast<RelType*>(node->getRelation()); \
1057  return evalProject(rel, shadow, ctxt); \
1058  ESAC(Project)
1059 
1060  FOR_EACH(PROJECT)
1061 #undef PROJECT
1062 
1063  CASE(SubroutineReturn)
1064  for (size_t i = 0; i < cur.getValues().size(); ++i) {
1065  if (shadow.getChild(i) == nullptr) {
1066  ctxt.addReturnValue(0);
1067  } else {
1068  ctxt.addReturnValue(execute(shadow.getChild(i), ctxt));
1069  }
1070  }
1071  return true;
1072  ESAC(SubroutineReturn)
1073 
1074  CASE(Sequence)
1075  for (const auto& child : shadow.getChildren()) {
1076  if (!execute(child.get(), ctxt)) {
1077  return false;
1078  }
1079  }
1080  return true;
1081  ESAC(Sequence)
1082 
1083  CASE(Parallel)
1084  for (const auto& child : shadow.getChildren()) {
1085  if (!execute(child.get(), ctxt)) {
1086  return false;
1087  }
1088  }
1089  return true;
1090  ESAC(Parallel)
1091 
1092  CASE(Loop)
1094  while (execute(shadow.getChild(), ctxt)) {
1096  }
1098  return true;
1099  ESAC(Loop)
1100 
1101  CASE(Exit)
1102  return !execute(shadow.getChild(), ctxt);
1103  ESAC(Exit)
1104 
1105  CASE(LogRelationTimer)
1106  Logger logger(cur.getMessage(), getIterationNumber(),
1107  std::bind(&RelationWrapper::size, node->getRelation()));
1108  return execute(shadow.getChild(), ctxt);
1109  ESAC(LogRelationTimer)
1110 
1111  CASE(LogTimer)
1112  Logger logger(cur.getMessage(), getIterationNumber());
1113  return execute(shadow.getChild(), ctxt);
1114  ESAC(LogTimer)
1115 
1116  CASE(DebugInfo)
1117  SignalHandler::instance()->setMsg(cur.getMessage().c_str());
1118  return execute(shadow.getChild(), ctxt);
1119  ESAC(DebugInfo)
1120 
1121 #define CLEAR(Structure, Arity, ...) \
1122  CASE(Clear, Structure, Arity) \
1123  auto& rel = *static_cast<RelType*>(node->getRelation()); \
1124  rel.__purge(); \
1125  return true; \
1126  ESAC(Clear)
1127 
1128  FOR_EACH(CLEAR)
1129 #undef CLEAR
1130 
1131  CASE(Call)
1132  execute(subroutine[shadow.getSubroutineId()].get(), ctxt);
1133  return true;
1134  ESAC(Call)
1135 
1136  CASE(LogSize)
1137  const auto& rel = *node->getRelation();
1139  cur.getMessage(), rel.size(), getIterationNumber());
1140  return true;
1141  ESAC(LogSize)
1142 
1143  CASE(IO)
1144  const auto& directive = cur.getDirectives();
1145  const std::string& op = cur.get("operation");
1146  auto& rel = *node->getRelation();
1147 
1148  if (op == "input") {
1149  try {
1151  .getReader(directive, getSymbolTable(), getRecordTable())
1152  ->readAll(rel);
1153  } catch (std::exception& e) {
1154  std::cerr << "Error loading data: " << e.what() << "\n";
1155  }
1156  return true;
1157  } else if (op == "output" || op == "printsize") {
1158  try {
1160  .getWriter(directive, getSymbolTable(), getRecordTable())
1161  ->writeAll(rel);
1162  } catch (std::exception& e) {
1163  std::cerr << e.what();
1164  exit(EXIT_FAILURE);
1165  }
1166  return true;
1167  } else {
1168  assert("wrong i/o operation");
1169  return true;
1170  }
1171  ESAC(IO)
1172 
1173  CASE(Query)
1174  ViewContext* viewContext = shadow.getViewContext();
1175 
1176  // Execute view-free operations in outer filter if any.
1177  auto& viewFreeOps = viewContext->getOuterFilterViewFreeOps();
1178  for (auto& op : viewFreeOps) {
1179  if (!execute(op.get(), ctxt)) {
1180  return true;
1181  }
1182  }
1183 
1184  // Create Views for outer filter operation if any.
1185  auto& viewsForOuter = viewContext->getViewInfoForFilter();
1186  for (auto& info : viewsForOuter) {
1187  ctxt.createView(*getRelationHandle(info[0]), info[1], info[2]);
1188  }
1189 
1190  // Execute outer filter operation.
1191  auto& viewOps = viewContext->getOuterFilterViewOps();
1192  for (auto& op : viewOps) {
1193  if (!execute(op.get(), ctxt)) {
1194  return true;
1195  }
1196  }
1197 
1198  if (viewContext->isParallel) {
1199  // If Parallel is true, holds views creation unitl parallel instructions.
1200  } else {
1201  // Issue views for nested operation.
1202  auto& viewsForNested = viewContext->getViewInfoForNested();
1203  for (auto& info : viewsForNested) {
1204  ctxt.createView(*getRelationHandle(info[0]), info[1], info[2]);
1205  }
1206  }
1207  execute(shadow.getChild(), ctxt);
1208  return true;
1209  ESAC(Query)
1210 
1211  CASE(Extend)
1212  auto& src = *static_cast<EqrelRelation*>(getRelationHandle(shadow.getSourceId()).get());
1213  auto& trg = *static_cast<EqrelRelation*>(getRelationHandle(shadow.getTargetId()).get());
1214  src.extend(trg);
1215  trg.insert(src);
1216  return true;
1217  ESAC(Extend)
1218 
1219  CASE(Swap)
1220  swapRelation(shadow.getSourceId(), shadow.getTargetId());
1221  return true;
1222  ESAC(Swap)
1223  }
1224 
1226 
1227 #undef EVAL_CHILD
1228 #undef DEBUG
1229 }
1230 
1231 template <typename Rel>
1232 RamDomain Engine::evalExistenceCheck(const ExistenceCheck& shadow, Context& ctxt) {
1233  constexpr size_t Arity = Rel::Arity;
1234  size_t viewPos = shadow.getViewId();

References souffle::ADD, souffle::interpreter::Context::addReturnValue(), AGGREGATE, souffle::BAND, BINARY_OP_INTEGRAL, BINARY_OP_INTEGRAL_SHIFT, BINARY_OP_LOGICAL, BINARY_OP_NUMERIC, souffle::BOR, souffle::BSHIFT_L, souffle::BSHIFT_R, souffle::BSHIFT_R_UNSIGNED, souffle::BXOR, CASE, CHOICE, CLEAR, COMPARE, COMPARE_EQ_NE, CONV_FROM_STRING, CONV_TO_STRING, souffle::interpreter::Context::createView(), TCB_SPAN_NAMESPACE_NAME::detail::data(), souffle::tuple::data, souffle::DIV, e, EMPTINESS_CHECK, souffle::EQ, ESAC, EXISTENCE_CHECK, souffle::interpreter::EqrelRelation::extend(), souffle::F2I, souffle::F2S, souffle::F2U, souffle::fatal(), FFI_RamFloat, FFI_RamSigned, FFI_RamUnsigned, FFI_Symbol, FOR_EACH, FOR_EACH_PROVENANCE, souffle::GE, souffle::interpreter::Context::getArgument(), souffle::getInstance(), souffle::interpreter::ViewContext::getOuterFilterViewFreeOps(), souffle::interpreter::ViewContext::getOuterFilterViewOps(), souffle::interpreter::Node::getRelation(), souffle::interpreter::ViewContext::getViewInfoForFilter(), souffle::interpreter::ViewContext::getViewInfoForNested(), souffle::GT, i, souffle::I2F, souffle::I2S, souffle::I2U, INDEX_AGGREGATE, INDEX_CHOICE, INDEX_SCAN, souffle::interpreter::ViewContext::isParallel, souffle::LAND, souffle::LE, souffle::LOR, souffle::LT, souffle::LXOR, souffle::MAX, souffle::MIN, MINMAX_NUMERIC, MINMAX_OP_SYM, souffle::MOD, souffle::MUL, souffle::NE, PARALLEL_AGGREGATE, PARALLEL_CHOICE, PARALLEL_INDEX_AGGREGATE, PARALLEL_INDEX_CHOICE, PARALLEL_INDEX_SCAN, PARALLEL_SCAN, PROJECT, PROVENANCE_EXISTENCE_CHECK, souffle::ramBitCast(), rel(), RELATION_SIZE, RUN_RANGE, souffle::S2F, souffle::S2I, souffle::S2U, SCAN, TCB_SPAN_NAMESPACE_NAME::detail::size(), souffle::profile::ss, str, souffle::SUB, souffle::U2F, souffle::U2I, souffle::U2S, UNARY_OP, and UNREACHABLE_BAD_CASE_ANALYSIS.

Here is the call graph for this function:

◆ executeMain()

void souffle::interpreter::Engine::executeMain ( )

Execute the main program.

Definition at line 272 of file Engine.cpp.

278  {
279  Context ctxt;
280  execute(main.get(), ctxt);
281  } else {
283  // Prepare the frequency table for threaded use
284  const ram::Program& program = tUnit.getProgram();
285  ram::visitDepthFirst(program, [&](const ram::TupleOperation& node) {
286  if (!node.getProfileText().empty()) {
287  frequencies.emplace(node.getProfileText(), std::deque<std::atomic<size_t>>());
288  frequencies[node.getProfileText()].emplace_back(0);
289  }
290  });
291  // Enable profiling for execution of main
293  ProfileEventSingleton::instance().makeTimeEvent("@time;starttime");
294  // Store configuration
295  for (const auto& cur : Global::config().data()) {
296  ProfileEventSingleton::instance().makeConfigRecord(cur.first, cur.second);
297  }
298  // Store count of relations
299  size_t relationCount = 0;
300  for (auto rel : tUnit.getProgram().getRelations()) {
301  if (rel->getName()[0] != '@') {
302  ++relationCount;
303  reads[rel->getName()] = 0;
304  }
305  }
306  ProfileEventSingleton::instance().makeConfigRecord("relationCount", std::to_string(relationCount));
307 
308  // Store count of rules
309  size_t ruleCount = 0;
310  ram::visitDepthFirst(program, [&](const ram::Query&) { ++ruleCount; });
311  ProfileEventSingleton::instance().makeConfigRecord("ruleCount", std::to_string(ruleCount));
312 
313  Context ctxt;
314  execute(main.get(), ctxt);
316  for (auto const& cur : frequencies) {
317  for (size_t i = 0; i < cur.second.size(); ++i) {
318  ProfileEventSingleton::instance().makeQuantityEvent(cur.first, cur.second[i], i);
319  }
320  }
321  for (auto const& cur : reads) {
323  "@relation-reads;" + cur.first, cur.second, 0);
324  }
325  }
327 }
328 
329 void Engine::generateIR() {
330  const ram::Program& program = tUnit.getProgram();
331  NodeGenerator generator(*this);
332  if (subroutine.empty()) {

◆ executeSubroutine()

void souffle::interpreter::Engine::executeSubroutine ( const std::string &  name,
const std::vector< RamDomain > &  args,
std::vector< RamDomain > &  ret 
)

Execute the subroutine program.

Definition at line 347 of file Engine.cpp.

354  {
355 #define DEBUG(Kind) std::cout << "Running Node: " << #Kind << "\n";
356 #define EVAL_CHILD(ty, idx) ramBitCast<ty>(execute(shadow.getChild(idx), ctxt))
357 #define EVAL_LEFT(ty) ramBitCast<ty>(execute(shadow.getLhs(), ctxt))

◆ generateIR()

void souffle::interpreter::Engine::generateIR ( )
private

Generate intermediate representation from RAM.

Definition at line 334 of file Engine.cpp.

337  {
338  main = generator.generateTree(program.getMain());
339  }
340 }
341 
343  const std::string& name, const std::vector<RamDomain>& args, std::vector<RamDomain>& ret) {
344  Context ctxt;
345  ctxt.setReturnValues(ret);

◆ getIterationNumber()

size_t souffle::interpreter::Engine::getIterationNumber ( ) const
private

Return current iteration number for loop operation.

Definition at line 262 of file Engine.cpp.

263  {
264  iteration = 0;

◆ getMethodHandle()

void * souffle::interpreter::Engine::getMethodHandle ( const std::string &  method)
private

Return method handler.

Definition at line 183 of file Engine.cpp.

189  {
190  return relations;
191 }
192 

◆ getRecordTable()

RecordTable & souffle::interpreter::Engine::getRecordTable ( )
private

Return the record table.

Definition at line 175 of file Engine.cpp.

◆ getRelationHandle()

Engine::RelationHandle & souffle::interpreter::Engine::getRelationHandle ( const size_t  idx)
private

Return a reference to the relation on the given index.

Definition at line 157 of file Engine.cpp.

◆ getRelationMap()

VecOwn< Engine::RelationHandle > & souffle::interpreter::Engine::getRelationMap ( )
private

Return the relation map.

Definition at line 194 of file Engine.cpp.

194  {
195  relations.resize(idx + 1);
196  }

References relations.

◆ getSymbolTable()

SymbolTable & souffle::interpreter::Engine::getSymbolTable ( )
private

Return the string symbol table.

Definition at line 171 of file Engine.cpp.

◆ getTranslationUnit()

ram::TranslationUnit & souffle::interpreter::Engine::getTranslationUnit ( )
private

Return the ram::TranslationUnit.

Definition at line 179 of file Engine.cpp.

180  : loadDLL()) {
181  auto* methodHandle = dlsym(libHandle, method.c_str());

◆ incCounter()

int souffle::interpreter::Engine::incCounter ( )
private

Increment the counter.

Definition at line 167 of file Engine.cpp.

◆ incIterationNumber()

void souffle::interpreter::Engine::incIterationNumber ( )
private

Increase iteration number by one.

Definition at line 265 of file Engine.cpp.

267  {

◆ loadDLL()

const std::vector< void * > & souffle::interpreter::Engine::loadDLL ( )
private

Load DLL.

Definition at line 217 of file Engine.cpp.

217  {
218  Global::config().set("libraries", "functors");
219  }
220  if (!Global::config().has("library-dir")) {
221  Global::config().set("library-dir", ".");
222  }
223 
224  for (const std::string& library : splitString(Global::config().get("libraries"), ' ')) {
225  // The library may be blank
226  if (library.empty()) {
227  continue;
228  }
229  auto paths = splitString(Global::config().get("library-dir"), ' ');
230  // Set up our paths to have a library appended
231  for (std::string& path : paths) {
232  if (path.back() != '/') {
233  path += '/';
234  }
235  }
236 
237  if (library.find('/') != std::string::npos) {
238  paths.clear();
239  }
240 
241  paths.push_back("");
242 
243  void* tmp = nullptr;
244  for (const std::string& path : paths) {
245  std::string fullpath = path + "lib" + library + dynamicLibSuffix;
246  tmp = dlopen(fullpath.c_str(), RTLD_LAZY);
247  if (tmp != nullptr) {
248  dll.push_back(tmp);
249  break;
250  }
251  }
252  }
253 
254  return dll;
255 }
256 
257 size_t Engine::getIterationNumber() const {
258  return iteration;
259 }

◆ resetIterationNumber()

void souffle::interpreter::Engine::resetIterationNumber ( )
private

Reset iteration number.

Definition at line 268 of file Engine.cpp.

◆ swapRelation()

void souffle::interpreter::Engine::swapRelation ( const size_t  ramRel1,
const size_t  ramRel2 
)
private

Swap the content of two relations.

Definition at line 161 of file Engine.cpp.

162  {
163  return counter++;
164 }
165 

Field Documentation

◆ counter

std::atomic<RamDomain> souffle::interpreter::Engine::counter {0}
private

Profile counter.

Definition at line 168 of file Engine.h.

◆ dll

std::vector<void*> souffle::interpreter::Engine::dll
private

DLL.

Definition at line 176 of file Engine.h.

◆ frequencies

std::map<std::string, std::deque<std::atomic<size_t> > > souffle::interpreter::Engine::frequencies
private

Profile for rule frequencies.

Definition at line 172 of file Engine.h.

◆ isa

ram::analysis::IndexAnalysis* souffle::interpreter::Engine::isa
private

IndexAnalysis.

Definition at line 180 of file Engine.h.

◆ isProvenance

const bool souffle::interpreter::Engine::isProvenance
private

If running a provenance program.

Definition at line 160 of file Engine.h.

◆ iteration

size_t souffle::interpreter::Engine::iteration = 0
private

Loop iteration counter.

Definition at line 170 of file Engine.h.

◆ main

Own<Node> souffle::interpreter::Engine::main
private

main program

Definition at line 164 of file Engine.h.

◆ NodeGenerator

friend souffle::interpreter::Engine::NodeGenerator
private

Definition at line 59 of file Engine.h.

◆ numOfThreads

size_t souffle::interpreter::Engine::numOfThreads
private

Number of threads enabled for this program.

Definition at line 166 of file Engine.h.

◆ profileEnabled

const bool souffle::interpreter::Engine::profileEnabled
private

If profile is enable in this program.

Definition at line 158 of file Engine.h.

◆ ProgInterface

friend souffle::interpreter::Engine::ProgInterface
private

Definition at line 58 of file Engine.h.

◆ reads

std::map<std::string, std::atomic<size_t> > souffle::interpreter::Engine::reads
private

Profile for relation reads.

Definition at line 174 of file Engine.h.

◆ recordTable

RecordTable souffle::interpreter::Engine::recordTable
private

Record Table.

Definition at line 182 of file Engine.h.

◆ relations

VecOwn<RelationHandle> souffle::interpreter::Engine::relations
private

Symbol table for relations.

Definition at line 184 of file Engine.h.

◆ subroutine

VecOwn<Node> souffle::interpreter::Engine::subroutine
private

subroutines

Definition at line 162 of file Engine.h.

◆ tUnit

ram::TranslationUnit& souffle::interpreter::Engine::tUnit
private

Program.

Definition at line 178 of file Engine.h.


The documentation for this class was generated from the following files:
souffle::FunctorOp::UEXP
@ UEXP
souffle::interpreter::Engine::dll
std::vector< void * > dll
DLL.
Definition: Engine.h:176
souffle::interpreter::Engine::numOfThreads
size_t numOfThreads
Number of threads enabled for this program.
Definition: Engine.h:166
souffle::interpreter::Engine::executeSubroutine
void executeSubroutine(const std::string &name, const std::vector< RamDomain > &args, std::vector< RamDomain > &ret)
Execute the subroutine program.
Definition: Engine.cpp:347
souffle::RamUnsigned
uint32_t RamUnsigned
Definition: RamTypes.h:58
souffle::AggregateOp::MIN
@ MIN
souffle::interpreter::Engine::relations
VecOwn< RelationHandle > relations
Symbol table for relations.
Definition: Engine.h:184
souffle::SignalHandler::setMsg
void setMsg(const char *m)
Definition: SignalHandler.h:60
TCB_SPAN_NAMESPACE_NAME::detail::size
constexpr auto size(const C &c) -> decltype(c.size())
Definition: span.h:198
souffle::AggregateOp::USUM
@ USUM
UNREACHABLE_BAD_CASE_ANALYSIS
#define UNREACHABLE_BAD_CASE_ANALYSIS
Definition: MiscUtil.h:206
souffle::TypeAttribute::Record
@ Record
souffle::interpreter::Engine::incCounter
int incCounter()
Increment the counter.
Definition: Engine.cpp:167
BINARY_OP_INTEGRAL_SHIFT
#define BINARY_OP_INTEGRAL_SHIFT(opcode, op, tySigned, tyUnsigned)
souffle::interpreter::Engine::counter
std::atomic< RamDomain > counter
Profile counter.
Definition: Engine.h:168
souffle::SymbolTable::resolve
const std::string & resolve(const RamDomain index) const
Find a symbol in the table by its index, note that this gives an error if the index is out of bounds.
Definition: SymbolTable.h:154
BINARY_OP_INTEGRAL
#define BINARY_OP_INTEGRAL(opcode, op)
souffle::MAX_RAM_SIGNED
constexpr RamSigned MAX_RAM_SIGNED
Definition: RamTypes.h:97
souffle::AggregateOp::FSUM
@ FSUM
souffle::interpreter::Engine::getRecordTable
RecordTable & getRecordTable()
Return the record table.
Definition: Engine.cpp:175
INDEX_AGGREGATE
#define INDEX_AGGREGATE(Structure, Arity,...)
souffle::RamDomain
int32_t RamDomain
Definition: RamTypes.h:56
FOR_EACH
#define FOR_EACH(func,...)
Definition: Util.h:116
souffle::interpreter::createEqrelRelation
Own< RelationWrapper > createEqrelRelation(const ram::Relation &id, const ram::analysis::MinIndexSelection &orderSet)
Definition: EqrelIndex.cpp:29
PARALLEL_AGGREGATE
#define PARALLEL_AGGREGATE(Structure, Arity,...)
souffle::interpreter::Engine::evalParallelIndexChoice
RamDomain evalParallelIndexChoice(const Rel &rel, const ram::ParallelIndexChoice &cur, const ParallelIndexChoice &shadow, Context &ctxt)
Definition: Engine.cpp:1475
AGGREGATE
#define AGGREGATE(Structure, Arity,...)
souffle::interpreter::createBTreeRelation
Own< RelationWrapper > createBTreeRelation(const ram::Relation &id, const ram::analysis::MinIndexSelection &orderSet)
Definition: BTreeIndex.cpp:35
souffle::interpreter::Engine::evalExistenceCheck
RamDomain evalExistenceCheck(const ExistenceCheck &shadow, Context &ctxt)
Definition: Engine.cpp:1237
low
d d low
Definition: htmlJsChartistMin.h:15
souffle::FunctorOp::URANGE
@ URANGE
high
d high
Definition: htmlJsChartistMin.h:15
souffle::ProfileEventSingleton::stopTimer
void stopTimer()
Stop timer.
Definition: ProfileEvent.h:161
souffle::interpreter::Engine::evalAggregate
RamDomain evalAggregate(const Aggregate &aggregate, const Node &filter, const Node *expression, const Node &nestedOperation, const Iter &ranges, Context &ctxt)
Definition: Engine.cpp:1511
souffle::interpreter::Engine::isProvenance
const bool isProvenance
If running a provenance program.
Definition: Engine.h:160
souffle::ProfileEventSingleton::instance
static ProfileEventSingleton & instance()
get instance
Definition: ProfileEvent.h:70
souffle::ram::NestedIntrinsicOp::RANGE
@ RANGE
RUN_RANGE
#define RUN_RANGE(ty)
souffle::TypeAttribute::Symbol
@ Symbol
UNARY_OP
#define UNARY_OP(op, ty, func)
e
l j a showGridBackground &&c b raw series this eventEmitter e
Definition: htmlJsChartistMin.h:15
souffle::RamFloat
float RamFloat
Definition: RamTypes.h:60
souffle::ram::NestedIntrinsicOp::FRANGE
@ FRANGE
SCAN
#define SCAN(Structure, Arity,...)
souffle::FunctorOp::STRLEN
@ STRLEN
CLEAR
#define CLEAR(Structure, Arity,...)
souffle::interpreter::Engine::profileEnabled
const bool profileEnabled
If profile is enable in this program.
Definition: Engine.h:158
souffle::interpreter::Engine::iteration
size_t iteration
Loop iteration counter.
Definition: Engine.h:170
souffle::FunctorOp::NEG
@ NEG
souffle::MIN_RAM_FLOAT
constexpr RamFloat MIN_RAM_FLOAT
Definition: RamTypes.h:102
souffle::FunctorOp::ORD
@ ORD
Unary Functor Operators.
souffle::FunctorOp::FNEG
@ FNEG
PARALLEL_INDEX_AGGREGATE
#define PARALLEL_INDEX_AGGREGATE(Structure, Arity,...)
souffle::FunctorOp::LNOT
@ LNOT
souffle::interpreter::createProvenanceRelation
Own< RelationWrapper > createProvenanceRelation(const ram::Relation &id, const ram::analysis::MinIndexSelection &orderSet)
Definition: ProvenanceIndex.cpp:32
PROJECT
#define PROJECT(Structure, Arity,...)
souffle::interpreter::Engine::getMethodHandle
void * getMethodHandle(const std::string &method)
Return method handler.
Definition: Engine.cpp:183
souffle::ram::NestedIntrinsicOp::URANGE
@ URANGE
souffle::interpreter::Engine::swapRelation
void swapRelation(const size_t ramRel1, const size_t ramRel2)
Swap the content of two relations.
Definition: Engine.cpp:161
souffle::TypeAttribute::Signed
@ Signed
souffle::IOSystem::getInstance
static IOSystem & getInstance()
Definition: IOSystem.h:45
souffle::interpreter::Engine::tUnit
ram::TranslationUnit & tUnit
Program.
Definition: Engine.h:178
souffle::interpreter::Engine::getRelationHandle
RelationHandle & getRelationHandle(const size_t idx)
Return a reference to the relation on the given index.
Definition: Engine.cpp:157
str
const std::string & str
Definition: json11.h:662
dynamicLibSuffix
#define dynamicLibSuffix
Definition: Engine.cpp:126
souffle::FunctorOp::UBNOT
@ UBNOT
souffle::ram::TranslationUnit::getProgram
Program & getProgram() const
Get the RAM Program of the translation unit
Definition: TranslationUnit.h:107
souffle::AggregateOp::UMIN
@ UMIN
souffle::SymbolTable::lookup
RamDomain lookup(const std::string &symbol)
Find the index of a symbol in the table, inserting a new symbol if it does not exist there already.
Definition: SymbolTable.h:124
EXISTENCE_CHECK
#define EXISTENCE_CHECK(Structure, Arity,...)
souffle::MAX_RAM_UNSIGNED
constexpr RamUnsigned MAX_RAM_UNSIGNED
Definition: RamTypes.h:100
souffle::RecordTable::unpack
const RamDomain * unpack(RamDomain ref, size_t arity) const
convert record reference to a record
Definition: RecordTable.h:124
souffle::FunctorOp::FRANGE
@ FRANGE
CONV_TO_STRING
#define CONV_TO_STRING(op, ty)
FFI_RamUnsigned
#define FFI_RamUnsigned
Definition: Engine.cpp:136
souffle::interpreter::Engine::recordTable
RecordTable recordTable
Record Table.
Definition: Engine.h:182
souffle::TypeAttribute::Unsigned
@ Unsigned
souffle::interpreter::Engine::NodeGenerator
friend NodeGenerator
Definition: Engine.h:59
i
size_t i
Definition: json11.h:663
souffle::interpreter::Engine::evalScan
RamDomain evalScan(const Rel &rel, const ram::Scan &cur, const Scan &shadow, Context &ctxt)
Definition: Engine.cpp:1327
souffle::filter
std::vector< A > filter(std::vector< A > xs, F &&f)
Filter a vector to include certain elements.
Definition: FunctionalUtil.h:155
souffle::MAX_RAM_FLOAT
constexpr RamFloat MAX_RAM_FLOAT
Definition: RamTypes.h:103
CAL_SEARCH_BOUND
#define CAL_SEARCH_BOUND(superInfo, low, high)
PARALLEL_SCAN
#define PARALLEL_SCAN(Structure, Arity,...)
RELATION_SIZE
#define RELATION_SIZE(Structure, Arity,...)
FFI_RamFloat
#define FFI_RamFloat
Definition: Engine.cpp:137
souffle::AggregateOp::MAX
@ MAX
souffle::interpreter::Engine::evalProvenanceExistenceCheck
RamDomain evalProvenanceExistenceCheck(const ProvenanceExistenceCheck &shadow, Context &ctxt)
Definition: Engine.cpp:1282
CASE
#define CASE(...)
EMPTINESS_CHECK
#define EMPTINESS_CHECK(Structure, Arity,...)
souffle::FunctorOp::RANGE
@ RANGE
souffle::AggregateOp::UMAX
@ UMAX
souffle::AggregateOp::FMIN
@ FMIN
souffle::interpreter::Engine::resetIterationNumber
void resetIterationNumber()
Reset iteration number.
Definition: Engine.cpp:268
souffle::AggregateOp::FMAX
@ FMAX
TCB_SPAN_NAMESPACE_NAME::get
constexpr auto get(span< E, S > s) -> decltype(s[N])
Definition: span.h:599
souffle::interpreter::Engine::evalParallelIndexScan
RamDomain evalParallelIndexScan(const Rel &rel, const ram::ParallelIndexScan &cur, const ParallelIndexScan &shadow, Context &ctxt)
Definition: Engine.cpp:1384
souffle::ProfileEventSingleton::makeQuantityEvent
void makeQuantityEvent(const std::string &txt, size_t number, int iteration)
create quantity event
Definition: ProfileEvent.h:96
souffle::IOSystem::getWriter
Own< WriteStream > getWriter(const std::map< std::string, std::string > &rwOperation, const SymbolTable &symbolTable, const RecordTable &recordTable) const
Return a new WriteStream.
Definition: IOSystem.h:61
souffle::Tuple
std::array< A, N > Tuple
Definition: RamTypes.h:36
souffle::BinaryConstraintOp
BinaryConstraintOp
Binary Constraint Operators.
Definition: BinaryConstraintOps.h:41
PARALLEL_END
#define PARALLEL_END
Definition: ParallelUtil.h:65
souffle::MIN_RAM_SIGNED
constexpr RamSigned MIN_RAM_SIGNED
lower and upper boundaries for the ram types
Definition: RamTypes.h:96
INDEX_CHOICE
#define INDEX_CHOICE(Structure, Arity,...)
souffle::RecordTable::pack
RamDomain pack(const RamDomain *tuple, size_t arity)
convert record to record reference
Definition: RecordTable.h:120
souffle::interpreter::Engine::execute
RamDomain execute(const Node *, Context &)
Execute the program.
Definition: Engine.cpp:359
souffle::TypeAttribute::ADT
@ ADT
COMPARE
#define COMPARE(opCode, op)
souffle::ram::Program::getRelations
std::vector< Relation * > getRelations() const
Get all relations of RAM program
Definition: Program.h:92
FFI_Symbol
#define FFI_Symbol
Definition: Engine.cpp:140
BINARY_OP_LOGICAL
#define BINARY_OP_LOGICAL(opcode, op)
souffle::FunctorOp::BNOT
@ BNOT
souffle::ProfileEventSingleton::setOutputFile
void setOutputFile(std::string outputFilename)
Definition: ProfileEvent.h:140
souffle::FunctorOp::FEXP
@ FEXP
souffle::interpreter::Engine::subroutine
VecOwn< Node > subroutine
subroutines
Definition: Engine.h:162
souffle::interpreter::Engine::getIterationNumber
size_t getIterationNumber() const
Return current iteration number for loop operation.
Definition: Engine.cpp:262
souffle::interpreter::Engine::evalIndexScan
RamDomain evalIndexScan(const ram::IndexScan &cur, const IndexScan &shadow, Context &ctxt)
Definition: Engine.cpp:1363
souffle::FunctorOp
FunctorOp
Definition: FunctorOps.h:35
souffle::ProfileEventSingleton::makeConfigRecord
void makeConfigRecord(const std::string &key, const std::string &value)
create config record
Definition: ProfileEvent.h:76
pfor
#define pfor
Definition: ParallelUtil.h:68
souffle::AggregateOp::COUNT
@ COUNT
souffle::AggregateOp::SUM
@ SUM
souffle::SignalHandler::enableLogging
void enableLogging()
Definition: SignalHandler.h:56
souffle::interpreter::Engine::RelationHandle
Own< RelationWrapper > RelationHandle
Definition: Engine.h:57
CHOICE
#define CHOICE(Structure, Arity,...)
souffle::MIN_RAM_UNSIGNED
constexpr RamUnsigned MIN_RAM_UNSIGNED
Definition: RamTypes.h:99
souffle::Global::config
static MainConfig & config()
Definition: Global.h:141
PARALLEL_INDEX_CHOICE
#define PARALLEL_INDEX_CHOICE(Structure, Arity,...)
souffle::BinaryConstraintOp::CONTAINS
@ CONTAINS
souffle::interpreter::Engine::evalIndexChoice
RamDomain evalIndexChoice(const ram::IndexChoice &cur, const IndexChoice &shadow, Context &ctxt)
Definition: Engine.cpp:1454
FOR_EACH_PROVENANCE
#define FOR_EACH_PROVENANCE(func,...)
Definition: Util.h:34
MINMAX_OP_SYM
#define MINMAX_OP_SYM(op)
souffle::AggregateOp::MEAN
@ MEAN
souffle::interpreter::Engine::evalParallelIndexAggregate
RamDomain evalParallelIndexAggregate(const ram::ParallelIndexAggregate &cur, const ParallelIndexAggregate &shadow, Context &ctxt)
Definition: Engine.cpp:1638
std
Definition: Brie.h:3053
souffle::ProfileEventSingleton::makeTimeEvent
void makeTimeEvent(const std::string &txt)
create time event
Definition: ProfileEvent.h:81
CONV_FROM_STRING
#define CONV_FROM_STRING(op, ty)
souffle::interpreter::Engine::main
Own< Node > main
main program
Definition: Engine.h:164
souffle::splitString
std::vector< std::string > splitString(const std::string &str, char delimiter)
Splits a string given a delimiter.
Definition: StringUtil.h:321
MINMAX_NUMERIC
#define MINMAX_NUMERIC(opCode, op)
souffle::interpreter::Engine::reads
std::map< std::string, std::atomic< size_t > > reads
Profile for relation reads.
Definition: Engine.h:174
PARALLEL_CHOICE
#define PARALLEL_CHOICE(Structure, Arity,...)
souffle::fatal
void fatal(const char *format, const Args &... args)
Definition: MiscUtil.h:198
souffle::SignalHandler::instance
static SignalHandler * instance()
Definition: SignalHandler.h:50
souffle
Definition: AggregateOp.h:25
TCB_SPAN_NAMESPACE_NAME::detail::data
constexpr auto data(C &c) -> decltype(c.data())
Definition: span.h:210
FFI_RamSigned
#define FFI_RamSigned
Definition: Engine.cpp:135
souffle::ramBitCast
To ramBitCast(From source)
In C++20 there will be a new way to cast between types by reinterpreting bits (std::bit_cast),...
Definition: RamTypes.h:87
souffle::interpreter::Engine::evalParallelAggregate
RamDomain evalParallelAggregate(const Rel &rel, const ram::ParallelAggregate &cur, const ParallelAggregate &shadow, Context &ctxt)
Definition: Engine.cpp:1623
souffle::RamSigned
RamDomain RamSigned
Definition: RamTypes.h:57
souffle::interpreter::Engine::evalIndexAggregate
RamDomain evalIndexAggregate(const ram::IndexAggregate &cur, const IndexAggregate &shadow, Context &ctxt)
Definition: Engine.cpp:1664
souffle::ram::visitDepthFirst
void visitDepthFirst(const Node &root, Visitor< R, Ps... > &visitor, Args &... args)
A utility function visiting all nodes within the RAM fragments rooted by the given node recursively i...
Definition: Visitor.h:357
souffle::TypeAttribute::Float
@ Float
rel
void rel(size_t limit, bool showLimit=true)
Definition: Tui.h:1086
souffle::interpreter::Engine::incIterationNumber
void incIterationNumber()
Increase iteration number by one.
Definition: Engine.cpp:265
souffle::interpreter::RelationWrapper::size
virtual size_t size() const =0
souffle::interpreter::Engine::generateIR
void generateIR()
Generate intermediate representation from RAM.
Definition: Engine.cpp:334
BINARY_OP_NUMERIC
#define BINARY_OP_NUMERIC(opcode, op)
souffle::FunctorOp::SUBSTR
@ SUBSTR
Ternary Functor Operators.
souffle::BinaryConstraintOp::NOT_MATCH
@ NOT_MATCH
PARALLEL_INDEX_SCAN
#define PARALLEL_INDEX_SCAN(Structure, Arity,...)
INDEX_SCAN
#define INDEX_SCAN(Structure, Arity,...)
ESAC
#define ESAC(Kind)
souffle::SignalHandler::reset
void reset()
Definition: SignalHandler.h:113
TUPLE_COPY_FROM
#define TUPLE_COPY_FROM(dst, src)
souffle::interpreter::Engine::evalChoice
RamDomain evalChoice(const Rel &rel, const ram::Choice &cur, const Choice &shadow, Context &ctxt)
Definition: Engine.cpp:1416
COMPARE_EQ_NE
#define COMPARE_EQ_NE(opCode, op)
souffle::interpreter::Engine::loadDLL
const std::vector< void * > & loadDLL()
Load DLL.
Definition: Engine.cpp:217
souffle::interpreter::Engine::frequencies
std::map< std::string, std::deque< std::atomic< size_t > > > frequencies
Profile for rule frequencies.
Definition: Engine.h:172
std::type
ElementType type
Definition: span.h:640
souffle::ProfileEventSingleton::startTimer
void startTimer()
Start timer.
Definition: ProfileEvent.h:156
souffle::BinaryConstraintOp::NOT_CONTAINS
@ NOT_CONTAINS
souffle::profile::ss
class souffle::profile::Tui ss
Definition: Tui.h:336
PROVENANCE_EXISTENCE_CHECK
#define PROVENANCE_EXISTENCE_CHECK(Structure, Arity,...)
souffle::interpreter::Engine::getSymbolTable
SymbolTable & getSymbolTable()
Return the string symbol table.
Definition: Engine.cpp:171
souffle::IOSystem::getReader
Own< ReadStream > getReader(const std::map< std::string, std::string > &rwOperation, SymbolTable &symbolTable, RecordTable &recordTable) const
Return a new ReadStream.
Definition: IOSystem.h:72
souffle::FunctorOp::ULNOT
@ ULNOT