packages feed

souffle-haskell-3.5.0: cbits/souffle/CompiledSouffle.h

/*
 * Souffle - A Datalog Compiler
 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved
 * Licensed under the Universal Permissive License v 1.0 as shown at:
 * - https://opensource.org/licenses/UPL
 * - <souffle root>/licenses/SOUFFLE-UPL.txt
 */

/************************************************************************
 *
 * @file CompiledSouffle.h
 *
 * Main include file for generated C++ classes of Souffle
 *
 ***********************************************************************/

#pragma once

#include "souffle/RamTypes.h"
#include "souffle/RecordTable.h"
#include "souffle/SignalHandler.h"
#include "souffle/SouffleInterface.h"
#include "souffle/SymbolTable.h"
#include "souffle/datastructure/BTreeDelete.h"
#include "souffle/datastructure/Brie.h"
#include "souffle/datastructure/EquivalenceRelation.h"
#include "souffle/datastructure/RecordTableImpl.h"
#include "souffle/datastructure/SymbolTableImpl.h"
#include "souffle/datastructure/Table.h"
#include "souffle/io/IOSystem.h"
#include "souffle/io/WriteStream.h"
#include "souffle/utility/EvaluatorUtil.h"
#ifndef __EMBEDDED_SOUFFLE__
#include "souffle/CompiledOptions.h"
#endif

#if defined(_OPENMP)
#include <omp.h>
#endif

namespace souffle {

extern "C" {
inline souffle::SouffleProgram* getInstance(const char* p) {
    return souffle::ProgramFactory::newInstance(p);
}
}

/**
 * Relation wrapper used internally in the generated Datalog program
 */
template <class RelType>
class RelationWrapper : public souffle::Relation {
public:
    static constexpr arity_type Arity = RelType::Arity;
    using TupleType = Tuple<RamDomain, Arity>;
    using AttrStrSeq = std::array<const char*, Arity>;

private:
    RelType& relation;
    SouffleProgram& program;
    std::string name;
    AttrStrSeq attrTypes;
    AttrStrSeq attrNames;
    const uint32_t id;
    const arity_type numAuxAttribs;

    // NB: internal wrapper. does not satisfy the `iterator` concept.
    class iterator_wrapper : public iterator_base {
        typename RelType::iterator it;
        const Relation* relation;
        tuple t;

    public:
        iterator_wrapper(uint32_t arg_id, const Relation* rel, typename RelType::iterator arg_it)
                : iterator_base(arg_id), it(std::move(arg_it)), relation(rel), t(rel) {}
        void operator++() override {
            ++it;
        }
        tuple& operator*() override {
            auto&& value = *it;
            t.rewind();
            for (std::size_t i = 0; i < Arity; i++)
                t[i] = value[i];
            return t;
        }
        iterator_base* clone() const override {
            return new iterator_wrapper(*this);
        }

    protected:
        bool equal(const iterator_base& o) const override {
            const auto& casted = asAssert<iterator_wrapper>(o);
            return it == casted.it;
        }
    };

public:
    RelationWrapper(uint32_t id, RelType& r, SouffleProgram& p, std::string name, const AttrStrSeq& t,
            const AttrStrSeq& n, arity_type numAuxAttribs)
            : relation(r), program(p), name(std::move(name)), attrTypes(t), attrNames(n), id(id),
              numAuxAttribs(numAuxAttribs) {}

    iterator begin() const override {
        return iterator(mk<iterator_wrapper>(id, this, relation.begin()));
    }
    iterator end() const override {
        return iterator(mk<iterator_wrapper>(id, this, relation.end()));
    }

    void insert(const tuple& arg) override {
        TupleType t;
        assert(&arg.getRelation() == this && "wrong relation");
        assert(arg.size() == Arity && "wrong tuple arity");
        for (std::size_t i = 0; i < Arity; i++) {
            t[i] = arg[i];
        }
        relation.insert(t);
    }
    bool contains(const tuple& arg) const override {
        TupleType t;
        assert(arg.size() == Arity && "wrong tuple arity");
        for (std::size_t i = 0; i < Arity; i++) {
            t[i] = arg[i];
        }
        return relation.contains(t);
    }
    std::size_t size() const override {
        return relation.size();
    }
    std::string getName() const override {
        return name;
    }
    const char* getAttrType(std::size_t arg) const override {
        assert(arg < Arity && "attribute out of bound");
        return attrTypes[arg];
    }
    const char* getAttrName(std::size_t arg) const override {
        assert(arg < Arity && "attribute out of bound");
        return attrNames[arg];
    }
    arity_type getArity() const override {
        return Arity;
    }
    arity_type getAuxiliaryArity() const override {
        return numAuxAttribs;
    }
    SymbolTable& getSymbolTable() const override {
        return program.getSymbolTable();
    }

    /** Eliminate all the tuples in relation*/
    void purge() override {
        relation.purge();
    }
};

/** Nullary relations */
class t_nullaries {
private:
    std::atomic<bool> data{false};

public:
    static constexpr Relation::arity_type Arity = 0;

    t_nullaries() = default;
    using t_tuple = Tuple<RamDomain, 0>;
    struct context {};
    context createContext() {
        return context();
    }
    class iterator {
        bool value;

    public:
        using iterator_category = std::forward_iterator_tag;
        using value_type = RamDomain*;
        using difference_type = ptrdiff_t;
        using pointer = value_type*;
        using reference = value_type&;

        iterator(bool v = false) : value(v) {}

        const RamDomain* operator*() {
            return nullptr;
        }

        bool operator==(const iterator& other) const {
            return other.value == value;
        }

        bool operator!=(const iterator& other) const {
            return other.value != value;
        }

        iterator& operator++() {
            if (value) {
                value = false;
            }
            return *this;
        }
    };
    iterator begin() const {
        return iterator(data);
    }
    iterator end() const {
        return iterator();
    }
    void insert(const t_tuple& /* t */) {
        data = true;
    }
    void insert(const t_tuple& /* t */, context& /* ctxt */) {
        data = true;
    }
    void insert(const RamDomain* /* ramDomain */) {
        data = true;
    }
    bool insert() {
        bool result = data;
        data = true;
        return !result;
    }
    bool contains(const t_tuple& /* t */) const {
        return data;
    }
    bool contains(const t_tuple& /* t */, context& /* ctxt */) const {
        return data;
    }
    std::size_t size() const {
        return data ? 1 : 0;
    }
    bool empty() const {
        return !data;
    }
    void purge() {
        data = false;
    }
    void printStatistics(std::ostream& /* o */) const {}
};

/** Info relations */
template <Relation::arity_type Arity_>
class t_info {
public:
    static constexpr Relation::arity_type Arity = Arity_;

    t_info() = default;
    using t_tuple = Tuple<RamDomain, Arity>;
    struct context {};
    context createContext() {
        return context();
    }
    class iterator : public std::iterator<std::forward_iterator_tag, Tuple<RamDomain, Arity>> {
        typename std::vector<Tuple<RamDomain, Arity>>::const_iterator it;

    public:
        iterator(const typename std::vector<t_tuple>::const_iterator& o) : it(o) {}

        const t_tuple operator*() {
            return *it;
        }

        bool operator==(const iterator& other) const {
            return other.it == it;
        }

        bool operator!=(const iterator& other) const {
            return !(*this == other);
        }

        iterator& operator++() {
            it++;
            return *this;
        }
    };
    iterator begin() const {
        return iterator(data.begin());
    }
    iterator end() const {
        return iterator(data.end());
    }
    void insert(const t_tuple& t) {
        insert_lock.lock();
        if (!contains(t)) {
            data.push_back(t);
        }
        insert_lock.unlock();
    }
    void insert(const t_tuple& t, context& /* ctxt */) {
        insert(t);
    }
    void insert(const RamDomain* ramDomain) {
        insert_lock.lock();
        t_tuple t;
        for (std::size_t i = 0; i < Arity; ++i) {
            t.data[i] = ramDomain[i];
        }
        data.push_back(t);
        insert_lock.unlock();
    }
    bool contains(const t_tuple& t) const {
        for (const auto& o : data) {
            if (t == o) {
                return true;
            }
        }
        return false;
    }
    bool contains(const t_tuple& t, context& /* ctxt */) const {
        return contains(t);
    }
    std::size_t size() const {
        return data.size();
    }
    bool empty() const {
        return data.size() == 0;
    }
    void purge() {
        data.clear();
    }
    void printStatistics(std::ostream& /* o */) const {}

private:
    std::vector<Tuple<RamDomain, Arity>> data;
    Lock insert_lock;
};

/** Equivalence relations */
struct t_eqrel {
    static constexpr Relation::arity_type Arity = 2;
    using t_tuple = Tuple<RamDomain, 2>;
    using t_ind = EquivalenceRelation<t_tuple>;
    t_ind ind;
    class iterator_0 : public std::iterator<std::forward_iterator_tag, t_tuple> {
        using nested_iterator = typename t_ind::iterator;
        nested_iterator nested;
        t_tuple value;

    public:
        iterator_0(const nested_iterator& iter) : nested(iter), value(*iter) {}
        iterator_0(const iterator_0& other) = default;
        iterator_0& operator=(const iterator_0& other) = default;
        bool operator==(const iterator_0& other) const {
            return nested == other.nested;
        }
        bool operator!=(const iterator_0& other) const {
            return !(*this == other);
        }
        const t_tuple& operator*() const {
            return value;
        }
        const t_tuple* operator->() const {
            return &value;
        }
        iterator_0& operator++() {
            ++nested;
            value = *nested;
            return *this;
        }
    };
    class iterator_1 : public std::iterator<std::forward_iterator_tag, t_tuple> {
        using nested_iterator = typename t_ind::iterator;
        nested_iterator nested;
        t_tuple value;

    public:
        iterator_1(const nested_iterator& iter) : nested(iter), value(reorder(*iter)) {}
        iterator_1(const iterator_1& other) = default;
        iterator_1& operator=(const iterator_1& other) = default;
        bool operator==(const iterator_1& other) const {
            return nested == other.nested;
        }
        bool operator!=(const iterator_1& other) const {
            return !(*this == other);
        }
        const t_tuple& operator*() const {
            return value;
        }
        const t_tuple* operator->() const {
            return &value;
        }
        iterator_1& operator++() {
            ++nested;
            value = reorder(*nested);
            return *this;
        }
    };
    using iterator = iterator_0;
    struct context {
        t_ind::operation_hints hints;
    };
    context createContext() {
        return context();
    }
    bool insert(const t_tuple& t) {
        return ind.insert(t[0], t[1]);
    }
    bool insert(const t_tuple& t, context& h) {
        return ind.insert(t[0], t[1], h.hints);
    }
    bool insert(const RamDomain* ramDomain) {
        RamDomain data[2];
        std::copy(ramDomain, ramDomain + 2, data);
        auto& tuple = reinterpret_cast<const t_tuple&>(data);
        context h;
        return insert(tuple, h);
    }
    bool insert(RamDomain a1, RamDomain a2) {
        RamDomain data[2] = {a1, a2};
        return insert(data);
    }
    void extendAndInsert(t_eqrel& other) {
        ind.extendAndInsert(other.ind);
    }
    bool contains(const t_tuple& t) const {
        return ind.contains(t[0], t[1]);
    }
    bool contains(const t_tuple& t, context&) const {
        return ind.contains(t[0], t[1]);
    }
    std::size_t size() const {
        return ind.size();
    }
    iterator find(const t_tuple& t) const {
        return ind.find(t);
    }
    iterator find(const t_tuple& t, context&) const {
        return ind.find(t);
    }
    range<iterator> lowerUpperRange_10(const t_tuple& lower, const t_tuple& /*upper*/, context& h) const {
        auto r = ind.template getBoundaries<1>((lower), h.hints);
        return make_range(iterator(r.begin()), iterator(r.end()));
    }
    range<iterator> lowerUpperRange_10(const t_tuple& lower, const t_tuple& upper) const {
        context h;
        return lowerUpperRange_10(lower, upper, h);
    }
    range<iterator_1> lowerUpperRange_01(const t_tuple& lower, const t_tuple& /*upper*/, context& h) const {
        auto r = ind.template getBoundaries<1>(reorder(lower), h.hints);
        return make_range(iterator_1(r.begin()), iterator_1(r.end()));
    }
    range<iterator_1> lowerUpperRange_01(const t_tuple& lower, const t_tuple& upper) const {
        context h;
        return lowerUpperRange_01(lower, upper, h);
    }
    range<iterator> lowerUpperRange_11(const t_tuple& lower, const t_tuple& /*upper*/, context& h) const {
        auto r = ind.template getBoundaries<2>((lower), h.hints);
        return make_range(iterator(r.begin()), iterator(r.end()));
    }
    range<iterator> lowerUpperRange_11(const t_tuple& lower, const t_tuple& upper) const {
        context h;
        return lowerUpperRange_11(lower, upper, h);
    }
    bool empty() const {
        return ind.size() == 0;
    }
    std::vector<range<iterator>> partition() const {
        std::vector<range<iterator>> res;
        for (const auto& cur : ind.partition(10000)) {
            res.push_back(make_range(iterator(cur.begin()), iterator(cur.end())));
        }
        return res;
    }
    void purge() {
        ind.clear();
    }
    iterator begin() const {
        return iterator(ind.begin());
    }
    iterator end() const {
        return iterator(ind.end());
    }
    static t_tuple reorder(const t_tuple& t) {
        t_tuple res;
        res[0] = t[1];
        res[1] = t[0];
        return res;
    }
    void printStatistics(std::ostream& /* o */) const {}
};

}  // namespace souffle