27         assert(relationMap.find(relation.getName()) == relationMap.end() && 
"double-naming of relations");
 
   28         relationMap[relation.getName()] = &relation;
 
   35         if (isA<ram::Query>(&node)) {
 
   39             encodeIndexPos(*indexSearch);
 
   40             encodeView(indexSearch);
 
   42             encodeIndexPos(*exists);
 
   44         } 
else if (
const auto* provExists = 
dynamic_cast<const ram::ProvenanceExistenceCheck*
>(&node)) {
 
   45             encodeIndexPos(*provExists);
 
   46             encodeView(provExists);
 
   53 NodePtr NodeGenerator::visitConstant(
const ram::Constant& num) {
 
   54     return mk<Constant>(I_Constant, &num);
 
   57 NodePtr NodeGenerator::visitTupleElement(
const ram::TupleElement& access) {
 
   58     auto tupleId = access.getTupleId();
 
   59     auto elementId = access.getElement();
 
   60     auto newElementId = orderingContext.mapOrder(tupleId, elementId);
 
   61     return mk<TupleElement>(I_TupleElement, &access, tupleId, newElementId);
 
   65     return mk<AutoIncrement>(I_AutoIncrement, &inc);
 
   71         children.push_back(visit(arg));
 
   73     return mk<IntrinsicOperator>(I_IntrinsicOperator, &op, std::move(children));
 
   79         children.push_back(visit(arg));
 
   81     return mk<UserDefinedOperator>(I_UserDefinedOperator, &op, std::move(children));
 
   86     orderingContext.addNewTuple(op.
getTupleId(), arity);
 
   89         children.push_back(visit(arg));
 
   91     children.push_back(visitTupleOperation(op));
 
   92     return mk<NestedIntrinsicOperator>(I_NestedIntrinsicOperator, &op, std::move(children));
 
   98         children.push_back(visit(arg));
 
  100     return mk<PackRecord>(I_PackRecord, &pr, std::move(children));
 
  104     return mk<SubroutineArgument>(I_SubroutineArgument, &arg);
 
  109     return mk<True>(I_True, <rue);
 
  113     return mk<False>(I_False, &lfalse);
 
  117     return mk<Conjunction>(I_Conjunction, &conj, visit(conj.
getLHS()), visit(conj.
getRHS()));
 
  121     return mk<Negation>(I_Negation, &neg, visit(neg.
getOperand()));
 
  126     auto rel = getRelationHandle(relId);
 
  128     return mk<EmptinessCheck>(
type, &emptiness, 
rel);
 
  132     size_t relId = encodeRelation(
size.getRelation());
 
  133     auto rel = getRelationHandle(relId);
 
  142     for (
const auto& cur : exists.
getValues()) {
 
  149     return mk<ExistenceCheck>(
type, &exists, isTotal, encodeView(&exists), std::move(superOp),
 
  150             ramRelation.isTemp(), ramRelation.getName());
 
  153 NodePtr NodeGenerator::visitProvenanceExistenceCheck(
const ram::ProvenanceExistenceCheck& provExists) {
 
  154     SuperInstruction superOp = getExistenceSuperInstInfo(provExists);
 
  156     return mk<ProvenanceExistenceCheck>(
type, &provExists, visit(provExists.getChildNodes().back()),
 
  157             encodeView(&provExists), std::move(superOp));
 
  161     return mk<Constraint>(I_Constraint, &relOp, visit(relOp.
getLHS()), visit(relOp.
getRHS()));
 
  169     if (engine.profileEnabled) {
 
  170         return mk<TupleOperation>(I_TupleOperation, &search, visit(search.
getOperation()));
 
  176     orderingContext.addTupleWithDefaultOrder(scan.
getTupleId(), scan);
 
  178     auto rel = getRelationHandle(relId);
 
  180     return mk<Scan>(
type, &scan, 
rel, visitTupleOperation(scan));
 
  184     orderingContext.addTupleWithDefaultOrder(pScan.
getTupleId(), pScan);
 
  185     size_t relId = encodeRelation(pScan.
getRelation());
 
  186     auto rel = getRelationHandle(relId);
 
  188     auto res = mk<ParallelScan>(
type, &pScan, 
rel, visitTupleOperation(pScan));
 
  189     res->setViewContext(parentQueryViewContext);
 
  194     orderingContext.addTupleWithIndexOrder(iScan.
getTupleId(), iScan);
 
  197     return mk<IndexScan>(
 
  198             type, &iScan, 
nullptr, visitTupleOperation(iScan), encodeView(&iScan), std::move(indexOperation));
 
  202     orderingContext.addTupleWithIndexOrder(piscan.
getTupleId(), piscan);
 
  204     size_t relId = encodeRelation(piscan.
getRelation());
 
  205     auto rel = getRelationHandle(relId);
 
  207     auto res = mk<ParallelIndexScan>(
type, &piscan, 
rel, visitTupleOperation(piscan), encodeIndexPos(piscan),
 
  208             std::move(indexOperation));
 
  209     res->setViewContext(parentQueryViewContext);
 
  214     orderingContext.addTupleWithDefaultOrder(choice.
getTupleId(), choice);
 
  215     size_t relId = encodeRelation(choice.
getRelation());
 
  216     auto rel = getRelationHandle(relId);
 
  222     orderingContext.addTupleWithDefaultOrder(pChoice.
getTupleId(), pChoice);
 
  223     size_t relId = encodeRelation(pChoice.
getRelation());
 
  224     auto rel = getRelationHandle(relId);
 
  226     auto res = mk<ParallelChoice>(
 
  228     res->setViewContext(parentQueryViewContext);
 
  233     orderingContext.addTupleWithIndexOrder(iChoice.
getTupleId(), iChoice);
 
  236     return mk<IndexChoice>(
type, &iChoice, 
nullptr, visit(iChoice.
getCondition()),
 
  237             visitTupleOperation(iChoice), encodeView(&iChoice), std::move(indexOperation));
 
  241     orderingContext.addTupleWithIndexOrder(piChoice.
getTupleId(), piChoice);
 
  243     size_t relId = encodeRelation(piChoice.
getRelation());
 
  244     auto rel = getRelationHandle(relId);
 
  247             visit(piChoice.
getOperation()), encodeIndexPos(piChoice), std::move(indexOperation));
 
  248     res->setViewContext(parentQueryViewContext);
 
  254     return mk<UnpackRecord>(
 
  255             I_UnpackRecord, &unpack, visit(unpack.
getExpression()), visitTupleOperation(unpack));
 
  262     orderingContext.addTupleWithDefaultOrder(aggregate.
getTupleId(), aggregate);
 
  265     orderingContext.addNewTuple(aggregate.
getTupleId(), 1);
 
  266     NodePtr nested = visitTupleOperation(aggregate);
 
  267     size_t relId = encodeRelation(aggregate.
getRelation());
 
  268     auto rel = getRelationHandle(relId);
 
  270     return mk<Aggregate>(
type, &aggregate, 
rel, std::move(expr), std::move(cond), std::move(nested));
 
  274     orderingContext.addTupleWithDefaultOrder(pAggregate.
getTupleId(), pAggregate);
 
  277     orderingContext.addNewTuple(pAggregate.
getTupleId(), 1);
 
  278     NodePtr nested = visitTupleOperation(pAggregate);
 
  279     size_t relId = encodeRelation(pAggregate.
getRelation());
 
  280     auto rel = getRelationHandle(relId);
 
  282     auto res = mk<ParallelAggregate>(
 
  283             type, &pAggregate, 
rel, std::move(expr), std::move(cond), std::move(nested));
 
  284     res->setViewContext(parentQueryViewContext);
 
  290     orderingContext.addTupleWithIndexOrder(iAggregate.
getTupleId(), iAggregate);
 
  295     NodePtr nested = visitTupleOperation(iAggregate);
 
  296     size_t relId = encodeRelation(iAggregate.
getRelation());
 
  297     auto rel = getRelationHandle(relId);
 
  299     return mk<IndexAggregate>(
type, &iAggregate, 
rel, std::move(expr), std::move(cond), std::move(nested),
 
  300             encodeView(&iAggregate), std::move(indexOperation));
 
  304     orderingContext.addTupleWithIndexOrder(piAggregate.
getTupleId(), piAggregate);
 
  309     NodePtr nested = visitTupleOperation(piAggregate);
 
  310     size_t relId = encodeRelation(piAggregate.
getRelation());
 
  311     auto rel = getRelationHandle(relId);
 
  313     auto res = mk<ParallelIndexAggregate>(
type, &piAggregate, 
rel, std::move(expr), std::move(cond),
 
  314             std::move(nested), encodeView(&piAggregate), std::move(indexOperation));
 
  315     res->setViewContext(parentQueryViewContext);
 
  329     size_t relId = encodeRelation(project.
getRelation());
 
  330     auto rel = getRelationHandle(relId);
 
  332     return mk<Project>(
type, &project, 
rel, std::move(superOp));
 
  337     for (
const auto& value : ret.
getValues()) {
 
  338         children.push_back(visit(value));
 
  340     return mk<SubroutineReturn>(I_SubroutineReturn, &ret, std::move(children));
 
  346         children.push_back(visit(value));
 
  348     return mk<Sequence>(I_Sequence, &seq, std::move(children));
 
  355         children.push_back(visit(value));
 
  357     return mk<Parallel>(I_Parallel, ¶llel, std::move(children));
 
  361     return mk<Loop>(I_Loop, &loop, visit(loop.
getBody()));
 
  364 NodePtr NodeGenerator::visitExit(
const ram::Exit& exit) {
 
  365     return mk<Exit>(I_Exit, &exit, visit(exit.getCondition()));
 
  374     auto subs = engine.tUnit.getProgram().getSubroutines();
 
  375     size_t subroutineId = distance(subs.begin(), subs.find(call.
getName()));
 
  376     return mk<Call>(I_Call, &call, subroutineId);
 
  380     size_t relId = encodeRelation(timer.
getRelation());
 
  381     auto rel = getRelationHandle(relId);
 
  382     return mk<LogRelationTimer>(I_LogRelationTimer, &timer, visit(timer.
getStatement()), 
rel);
 
  386     return mk<LogTimer>(I_LogTimer, &timer, visit(timer.
getStatement()));
 
  395     auto rel = getRelationHandle(relId);
 
  397     return mk<Clear>(
type, &clear, 
rel);
 
  401     size_t relId = encodeRelation(
size.getRelation());
 
  402     auto rel = getRelationHandle(relId);
 
  403     return mk<LogSize>(I_LogSize, &
size, 
rel);
 
  408     auto rel = getRelationHandle(relId);
 
  409     return mk<IO>(I_IO, &io, 
rel);
 
  413     std::shared_ptr<ViewContext> viewContext = std::make_shared<ViewContext>();
 
  414     parentQueryViewContext = viewContext;
 
  419     std::vector<const ram::Condition*> freeOfView;
 
  421         next = &
filter->getOperation();
 
  425         for (
auto const& cur : conditions) {
 
  426             bool needView = 
false;
 
  428                 if (requireView(&node)) {
 
  430                     const auto& 
rel = getViewRelation(&node);
 
  431                     viewContext->addViewInfoForFilter(
 
  432                             encodeRelation(
rel), indexTable[&node], encodeView(&node));
 
  437                 viewContext->addViewOperationForFilter(visit(*cur));
 
  439                 viewContext->addViewFreeOperationForFilter(visit(*cur));
 
  445         if (requireView(&node)) {
 
  446             const auto& 
rel = getViewRelation(&node);
 
  447             viewContext->addViewInfoForNested(encodeRelation(
rel), indexTable[&node], encodeView(&node));
 
  451     visitDepthFirst(*next, [&](
const ram::AbstractParallel&) { viewContext->isParallel = 
true; });
 
  453     auto res = mk<Query>(I_Query, &query, visit(*next));
 
  454     res->setViewContext(parentQueryViewContext);
 
  458 NodePtr NodeGenerator::visitExtend(
const ram::Extend& extend) {
 
  459     size_t src = encodeRelation(extend.getFirstRelation());
 
  460     size_t target = encodeRelation(extend.getSecondRelation());
 
  461     return mk<Extend>(I_Extend, &extend, src, target);
 
  467     return mk<Swap>(I_Swap, &swap, src, target);
 
  475     fatal(
"unsupported node type: %s", 
typeid(node).name());
 
  478 void NodeGenerator::newQueryBlock() {
 
  483 size_t NodeGenerator::getNewRelId() {
 
  487 size_t NodeGenerator::getNextViewId() {
 
  491 template <
class RamNode>
 
  492 size_t NodeGenerator::encodeIndexPos(RamNode& node) {
 
  493     const std::string& name = node.getRelation();
 
  494     auto& orderSet = engine.isa->getIndexes(name);
 
  500     auto i = orderSet.getLexOrderNum(signature);
 
  501     indexTable[&node] = 
i;
 
  505 size_t NodeGenerator::encodeView(
const ram::Node* node) {
 
  506     auto pos = viewTable.find(node);
 
  507     if (pos != viewTable.end()) {
 
  510     size_t id = getNextViewId();
 
  511     viewTable[node] = 
id;
 
  515 const ram::Relation& NodeGenerator::lookup(
const std::string& relName) {
 
  516     auto it = relationMap.find(relName);
 
  517     assert(it != relationMap.end() && 
"relation not found");
 
  521 size_t NodeGenerator::getArity(
const std::string& relName) {
 
  522     auto rel = lookup(relName);
 
  523     return rel.getArity();
 
  526 size_t NodeGenerator::encodeRelation(
const std::string& relName) {
 
  527     auto pos = relTable.find(relName);
 
  528     if (pos != relTable.end()) {
 
  531     size_t id = getNewRelId();
 
  532     relTable[relName] = 
id;
 
  533     engine.createRelation(lookup(relName), 
id);
 
  537 RelationHandle* NodeGenerator::getRelationHandle(
const size_t idx) {
 
  538     return engine.relations[idx].get();
 
  541 bool NodeGenerator::requireView(
const ram::Node* node) {
 
  542     if (isA<ram::AbstractExistenceCheck>(node)) {
 
  544     } 
else if (isA<ram::IndexOperation>(node)) {
 
  550 const std::string& NodeGenerator::getViewRelation(
const ram::Node* node) {
 
  552         return exist->getRelation();
 
  553     } 
else if (
const auto* index = 
dynamic_cast<const ram::IndexOperation*
>(node)) {
 
  554         return index->getRelation();
 
  557     fatal(
"The ram::Node does not require a view.");
 
  560 SuperInstruction NodeGenerator::getIndexSuperInstInfo(
const ram::IndexOperation& ramIndex) {
 
  562     auto interpreterRel = encodeRelation(ramIndex.
getRelation());
 
  563     auto indexId = encodeIndexPos(ramIndex);
 
  564     auto order = (*getRelationHandle(interpreterRel))->getIndexOrder(indexId);
 
  567     for (
size_t i = 0; 
i < arity; ++
i) {
 
  570         auto& 
low = first[order[
i]];
 
  579         if (isA<ram::Constant>(
low)) {
 
  585         if (isA<ram::TupleElement>(
low)) {
 
  588             size_t elementId = lowTuple->getElement();
 
  589             size_t newElementId = orderingContext.mapOrder(tupleId, elementId);
 
  590             indexOperation.
tupleFirst.push_back({
i, tupleId, newElementId});
 
  595         indexOperation.
exprFirst.push_back(std::pair<
size_t, Own<Node>>(
i, visit(
low)));
 
  598     for (
size_t i = 0; 
i < arity; ++
i) {
 
  599         auto& hig = second[order[
i]];
 
  608         if (isA<ram::Constant>(hig)) {
 
  609             indexOperation.
second[
i] = 
dynamic_cast<ram::Constant*
>(hig)->getConstant();
 
  614         if (isA<ram::TupleElement>(hig)) {
 
  615             auto highTuple = 
dynamic_cast<ram::TupleElement*
>(hig);
 
  616             size_t tupleId = highTuple->getTupleId();
 
  617             size_t elementId = highTuple->getElement();
 
  618             size_t newElementId = orderingContext.mapOrder(tupleId, elementId);
 
  619             indexOperation.
tupleSecond.push_back({
i, tupleId, newElementId});
 
  624         indexOperation.
exprSecond.push_back(std::pair<
size_t, Own<Node>>(
i, visit(hig)));
 
  626     return indexOperation;
 
  629 SuperInstruction NodeGenerator::getExistenceSuperInstInfo(
const ram::AbstractExistenceCheck& abstractExist) {
 
  630     auto interpreterRel = encodeRelation(abstractExist.getRelation());
 
  632     if (isA<ram::ExistenceCheck>(&abstractExist)) {
 
  633         indexId = encodeIndexPos(*
dynamic_cast<const ram::ExistenceCheck*
>(&abstractExist));
 
  634     } 
else if (isA<ram::ProvenanceExistenceCheck>(&abstractExist)) {
 
  637         fatal(
"Unrecognized ram::AbstractExistenceCheck.");
 
  639     auto order = (*getRelationHandle(interpreterRel))->getIndexOrder(indexId);
 
  640     size_t arity = getArity(abstractExist.getRelation());
 
  641     SuperInstruction superOp(arity);
 
  642     const auto& children = abstractExist.getValues();
 
  643     for (
size_t i = 0; 
i < arity; ++
i) {
 
  644         auto& child = children[order[
i]];
 
  654         if (isA<ram::Constant>(child)) {
 
  655             superOp.
first[
i] = 
dynamic_cast<ram::Constant*
>(child)->getConstant();
 
  661         if (isA<ram::TupleElement>(child)) {
 
  662             auto tuple = 
dynamic_cast<ram::TupleElement*
>(child);
 
  663             size_t tupleId = tuple->getTupleId();
 
  664             size_t elementId = tuple->getElement();
 
  665             size_t newElementId = orderingContext.mapOrder(tupleId, elementId);
 
  666             superOp.
tupleFirst.push_back({
i, tupleId, newElementId});
 
  671         superOp.
exprFirst.push_back(std::pair<
size_t, Own<Node>>(
i, visit(child)));
 
  676 SuperInstruction NodeGenerator::getProjectSuperInstInfo(
const ram::Project& exist) {
 
  677     size_t arity = getArity(exist.getRelation());
 
  678     SuperInstruction superOp(arity);
 
  679     const auto& children = exist.getValues();
 
  680     for (
size_t i = 0; 
i < arity; ++
i) {
 
  681         auto& child = children[
i];
 
  683         if (isA<ram::Constant>(child)) {
 
  689         if (isA<ram::TupleElement>(child)) {
 
  691             size_t tupleId = 
tuple->getTupleId();
 
  692             size_t elementId = 
tuple->getElement();
 
  693             size_t newElementId = orderingContext.mapOrder(tupleId, elementId);
 
  694             superOp.
tupleFirst.push_back({
i, tupleId, newElementId});
 
  699         superOp.
exprFirst.push_back(std::pair<
size_t, Own<Node>>(
i, visit(child)));
 
  706 NodeGenerator::OrderingContext::OrderingContext(NodeGenerator& generator) : generator(generator) {}
 
  709     std::vector<uint32_t> order;
 
  710     for (
size_t i = 0; 
i < arity; ++
i) {
 
  711         order.push_back((uint32_t)
i);
 
  716 template <
class RamNode>
 
  718     auto interpreterRel = generator.encodeRelation(node.getRelation());
 
  719     insertOrder(tupleId, (*generator.getRelationHandle(interpreterRel))->getIndexOrder(0));
 
  722 template <
class RamNode>
 
  724     auto interpreterRel = generator.encodeRelation(node.getRelation());
 
  725     auto indexId = generator.encodeIndexPos(node);
 
  726     auto order = (*generator.getRelationHandle(interpreterRel))->getIndexOrder(indexId);
 
  727     insertOrder(tupleId, order);
 
  731     return tupleOrders[tupleId][elementId];
 
  735     if (tupleId >= tupleOrders.size()) {
 
  736         tupleOrders.resize(tupleId + 1);
 
  739     std::vector<uint32_t> decodeOrder(order.
size());
 
  740     for (
size_t i = 0; 
i < order.
size(); ++
i) {
 
  741         decodeOrder[order[
i]] = 
i;
 
  744     tupleOrders[tupleId] = std::move(decodeOrder);