packages feed

souffle-haskell 3.4.0 → 3.5.0

raw patch · 31 files changed

+1224/−866 lines, 31 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -3,6 +3,12 @@ All notable changes to this project (as seen by library users) will be documented in this file. The CHANGELOG is available on [Github](https://github.com/luc-tielen/souffle-haskell.git/CHANGELOG.md). +## [3.5.0] - 2022-06-04++### Changed++- souffle-haskell now supports Souffle version 2.3.+ ## [3.4.0] - 2022-05-15  ### Changed
cbits/souffle/CompiledSouffle.h view
@@ -24,6 +24,8 @@ #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"
cbits/souffle/RecordTable.h view
@@ -18,469 +18,11 @@ #pragma once  #include "souffle/RamTypes.h"-#include "souffle/datastructure/ConcurrentFlyweight.h" #include "souffle/utility/span.h"-#include <cassert>-#include <cstddef>-#include <limits>-#include <memory>-#include <utility>-#include <vector>+#include <initializer_list>  namespace souffle { -namespace details {--// Helper to unroll for loop-template <auto Start, auto End, auto Inc, class F>-constexpr void constexpr_for(F&& f) {-    if constexpr (Start < End) {-        f(std::integral_constant<decltype(Start), Start>());-        constexpr_for<Start + Inc, End, Inc>(f);-    }-}--/// @brief The data-type of RamDomain records of any size.-using GenericRecord = std::vector<RamDomain>;--/// @brief The data-type of RamDomain records of specialized size.-template <std::size_t Arity>-using SpecializedRecord = std::array<RamDomain, Arity>;--/// @brief A view in a sequence of RamDomain value.-// TODO: use a `span`.-struct GenericRecordView {-    explicit GenericRecordView(const RamDomain* Data, const std::size_t Arity) : Data(Data), Arity(Arity) {}-    GenericRecordView(const GenericRecordView& Other) : Data(Other.Data), Arity(Other.Arity) {}-    GenericRecordView(GenericRecordView&& Other) : Data(Other.Data), Arity(Other.Arity) {}--    const RamDomain* const Data;-    const std::size_t Arity;--    const RamDomain* data() const {-        return Data;-    }--    const RamDomain& operator[](int I) const {-        assert(I >= 0 && static_cast<std::size_t>(I) < Arity);-        return Data[I];-    }-};--template <std::size_t Arity>-struct SpecializedRecordView {-    explicit SpecializedRecordView(const RamDomain* Data) : Data(Data) {}-    SpecializedRecordView(const SpecializedRecordView& Other) : Data(Other.Data) {}-    SpecializedRecordView(SpecializedRecordView&& Other) : Data(Other.Data) {}--    const RamDomain* const Data;--    const RamDomain* data() const {-        return Data;-    }--    const RamDomain& operator[](int I) const {-        assert(I >= 0 && static_cast<std::size_t>(I) < Arity);-        return Data[I];-    }-};--/// @brief Hash function object for a RamDomain record.-struct GenericRecordHash {-    explicit GenericRecordHash(const std::size_t Arity) : Arity(Arity) {}-    GenericRecordHash(const GenericRecordHash& Other) : Arity(Other.Arity) {}-    GenericRecordHash(GenericRecordHash&& Other) : Arity(Other.Arity) {}--    const std::size_t Arity;-    std::hash<RamDomain> domainHash;--    template <typename T>-    std::size_t operator()(const T& Record) const {-        std::size_t Seed = 0;-        for (std::size_t I = 0; I < Arity; ++I) {-            Seed ^= domainHash(Record[I]) + 0x9e3779b9 + (Seed << 6) + (Seed >> 2);-        }-        return Seed;-    }-};--template <std::size_t Arity>-struct SpecializedRecordHash {-    explicit SpecializedRecordHash() {}-    SpecializedRecordHash(const SpecializedRecordHash& Other) : DomainHash(Other.DomainHash) {}-    SpecializedRecordHash(SpecializedRecordHash&& Other) : DomainHash(Other.DomainHash) {}--    std::hash<RamDomain> DomainHash;--    template <typename T>-    std::size_t operator()(const T& Record) const {-        std::size_t Seed = 0;-        constexpr_for<0, Arity, 1>(-                [&](auto I) { Seed ^= DomainHash(Record[I]) + 0x9e3779b9 + (Seed << 6) + (Seed >> 2); });-        return Seed;-    }-};--template <>-struct SpecializedRecordHash<0> {-    explicit SpecializedRecordHash() {}-    SpecializedRecordHash(const SpecializedRecordHash&) {}-    SpecializedRecordHash(SpecializedRecordHash&&) {}--    template <typename T>-    std::size_t operator()(const T&) const {-        return 0;-    }-};--/// @brief Equality function object for RamDomain records.-struct GenericRecordEqual {-    explicit GenericRecordEqual(const std::size_t Arity) : Arity(Arity) {}-    GenericRecordEqual(const GenericRecordEqual& Other) : Arity(Other.Arity) {}-    GenericRecordEqual(GenericRecordEqual&& Other) : Arity(Other.Arity) {}--    const std::size_t Arity;--    template <typename T, typename U>-    bool operator()(const T& A, const U& B) const {-        return (std::memcmp(A.data(), B.data(), Arity * sizeof(RamDomain)) == 0);-    }-};--template <std::size_t Arity>-struct SpecializedRecordEqual {-    explicit SpecializedRecordEqual() {}-    SpecializedRecordEqual(const SpecializedRecordEqual&) {}-    SpecializedRecordEqual(SpecializedRecordEqual&&) {}--    template <typename T, typename U>-    bool operator()(const T& A, const U& B) const {-        constexpr std::size_t Len = Arity * sizeof(RamDomain);-        return (std::memcmp(A.data(), B.data(), Len) == 0);-    }-};--template <>-struct SpecializedRecordEqual<0> {-    explicit SpecializedRecordEqual() {}-    SpecializedRecordEqual(const SpecializedRecordEqual&) {}-    SpecializedRecordEqual(SpecializedRecordEqual&&) {}--    template <typename T, typename U>-    bool operator()(const T&, const U&) const {-        return true;-    }-};--/// @brief Less function object for RamDomain records.-struct GenericRecordLess {-    explicit GenericRecordLess(const std::size_t Arity) : Arity(Arity) {}-    GenericRecordLess(const GenericRecordLess& Other) : Arity(Other.Arity) {}-    GenericRecordLess(GenericRecordLess&& Other) : Arity(Other.Arity) {}--    const std::size_t Arity;--    template <typename T, typename U>-    bool operator()(const T& A, const U& B) const {-        return (std::memcmp(A.data(), B.data(), Arity * sizeof(RamDomain)) < 0);-    }-};--template <std::size_t Arity>-struct SpecializedRecordLess {-    explicit SpecializedRecordLess() {}-    SpecializedRecordLess(const SpecializedRecordLess&) {}-    SpecializedRecordLess(SpecializedRecordLess&&) {}--    template <typename T, typename U>-    bool operator()(const T& A, const U& B) const {-        constexpr std::size_t Len = Arity * sizeof(RamDomain);-        return (std::memcmp(A.data(), B.data(), Len) < 0);-    }-};--template <>-struct SpecializedRecordLess<0> {-    explicit SpecializedRecordLess() {}-    SpecializedRecordLess(const SpecializedRecordLess&) {}-    SpecializedRecordLess(SpecializedRecordLess&&) {}--    template <typename T, typename U>-    bool operator()(const T&, const U&) const {-        return false;-    }-};--/// @brief Compare function object for RamDomain records.-struct GenericRecordCmp {-    explicit GenericRecordCmp(const std::size_t Arity) : Arity(Arity) {}-    GenericRecordCmp(const GenericRecordCmp& Other) : Arity(Other.Arity) {}-    GenericRecordCmp(GenericRecordCmp&& Other) : Arity(Other.Arity) {}--    const std::size_t Arity;--    template <typename T, typename U>-    int operator()(const T& A, const U& B) const {-        return std::memcmp(A.data(), B.data(), Arity * sizeof(RamDomain));-    }-};--template <std::size_t Arity>-struct SpecializedRecordCmp {-    explicit SpecializedRecordCmp() {}-    SpecializedRecordCmp(const SpecializedRecordCmp&) {}-    SpecializedRecordCmp(SpecializedRecordCmp&&) {}--    template <typename T, typename U>-    bool operator()(const T& A, const U& B) const {-        constexpr std::size_t Len = Arity * sizeof(RamDomain);-        return std::memcmp(A.data(), B.data(), Len);-    }-};--template <>-struct SpecializedRecordCmp<0> {-    explicit SpecializedRecordCmp() {}-    SpecializedRecordCmp(const SpecializedRecordCmp&) {}-    SpecializedRecordCmp(SpecializedRecordCmp&&) {}--    template <typename T, typename U>-    bool operator()(const T&, const U&) const {-        return 0;-    }-};--/// @brief Factory of RamDomain record.-struct GenericRecordFactory {-    using value_type = GenericRecord;-    using pointer = GenericRecord*;-    using reference = GenericRecord&;--    explicit GenericRecordFactory(const std::size_t Arity) : Arity(Arity) {}-    GenericRecordFactory(const GenericRecordFactory& Other) : Arity(Other.Arity) {}-    GenericRecordFactory(GenericRecordFactory&& Other) : Arity(Other.Arity) {}--    const std::size_t Arity;--    reference replace(reference Place, const std::vector<RamDomain>& V) {-        assert(V.size() == Arity);-        Place = V;-        return Place;-    }--    reference replace(reference Place, const GenericRecordView& V) {-        Place.clear();-        Place.insert(Place.begin(), V.data(), V.data() + Arity);-        return Place;-    }--    reference replace(reference Place, const RamDomain* V) {-        Place.clear();-        Place.insert(Place.begin(), V, V + Arity);-        return Place;-    }-};--template <std::size_t Arity>-struct SpecializedRecordFactory {-    using value_type = SpecializedRecord<Arity>;-    using pointer = SpecializedRecord<Arity>*;-    using reference = SpecializedRecord<Arity>&;--    explicit SpecializedRecordFactory() {}-    SpecializedRecordFactory(const SpecializedRecordFactory&) {}-    SpecializedRecordFactory(SpecializedRecordFactory&&) {}--    reference replace(reference Place, const SpecializedRecord<Arity>& V) {-        assert(V.size() == Arity);-        Place = V;-        return Place;-    }--    reference replace(reference Place, const SpecializedRecordView<Arity>& V) {-        constexpr std::size_t Len = Arity * sizeof(RamDomain);-        std::memcpy(Place.data(), V.data(), Len);-        return Place;-    }--    reference replace(reference Place, const RamDomain* V) {-        constexpr std::size_t Len = Arity * sizeof(RamDomain);-        std::memcpy(Place.data(), V, Len);-        return Place;-    }-};--template <>-struct SpecializedRecordFactory<0> {-    using value_type = SpecializedRecord<0>;-    using pointer = SpecializedRecord<0>*;-    using reference = SpecializedRecord<0>&;--    explicit SpecializedRecordFactory() {}-    SpecializedRecordFactory(const SpecializedRecordFactory&) {}-    SpecializedRecordFactory(SpecializedRecordFactory&&) {}--    reference replace(reference Place, const SpecializedRecord<0>&) {-        return Place;-    }--    reference replace(reference Place, const SpecializedRecordView<0>&) {-        return Place;-    }--    reference replace(reference Place, const RamDomain*) {-        return Place;-    }-};--}  // namespace details--/** @brief Interface of bidirectional mappping between records and record references. */-class RecordMap {-public:-    virtual ~RecordMap() {}-    virtual void setNumLanes(const std::size_t NumLanes) = 0;-    virtual RamDomain pack(const std::vector<RamDomain>& Vector) = 0;-    virtual RamDomain pack(const RamDomain* Tuple) = 0;-    virtual RamDomain pack(const std::initializer_list<RamDomain>& List) = 0;-    virtual const RamDomain* unpack(RamDomain index) const = 0;-};--/** @brief Bidirectional mappping between records and record references, for any record arity. */-class GenericRecordMap : public RecordMap,-                         protected FlyweightImpl<details::GenericRecord, details::GenericRecordHash,-                                 details::GenericRecordEqual, details::GenericRecordFactory> {-    using Base = FlyweightImpl<details::GenericRecord, details::GenericRecordHash,-            details::GenericRecordEqual, details::GenericRecordFactory>;--    const std::size_t Arity;--public:-    explicit GenericRecordMap(const std::size_t lane_count, const std::size_t arity)-            : Base(lane_count, 8, true, details::GenericRecordHash(arity), details::GenericRecordEqual(arity),-                      details::GenericRecordFactory(arity)),-              Arity(arity) {}--    virtual ~GenericRecordMap() {}--    void setNumLanes(const std::size_t NumLanes) override {-        Base::setNumLanes(NumLanes);-    }--    /** @brief converts record to a record reference */-    RamDomain pack(const std::vector<RamDomain>& Vector) override {-        return findOrInsert(Vector).first;-    };--    /** @brief converts record to a record reference */-    RamDomain pack(const RamDomain* Tuple) override {-        details::GenericRecordView View{Tuple, Arity};-        return findOrInsert(View).first;-    }--    /** @brief converts record to a record reference */-    RamDomain pack(const std::initializer_list<RamDomain>& List) override {-        details::GenericRecordView View{std::data(List), Arity};-        return findOrInsert(View).first;-    }--    /** @brief convert record reference to a record pointer */-    const RamDomain* unpack(RamDomain Index) const override {-        return fetch(Index).data();-    }-};--/** @brief Bidirectional mappping between records and record references, specialized for a record arity. */-template <std::size_t Arity>-class SpecializedRecordMap-        : public RecordMap,-          protected FlyweightImpl<details::SpecializedRecord<Arity>, details::SpecializedRecordHash<Arity>,-                  details::SpecializedRecordEqual<Arity>, details::SpecializedRecordFactory<Arity>> {-    using Record = details::SpecializedRecord<Arity>;-    using RecordView = details::SpecializedRecordView<Arity>;-    using RecordHash = details::SpecializedRecordHash<Arity>;-    using RecordEqual = details::SpecializedRecordEqual<Arity>;-    using RecordFactory = details::SpecializedRecordFactory<Arity>;-    using Base = FlyweightImpl<Record, RecordHash, RecordEqual, RecordFactory>;--public:-    SpecializedRecordMap(const std::size_t LaneCount)-            : Base(LaneCount, 8, true, RecordHash(), RecordEqual(), RecordFactory()) {}--    virtual ~SpecializedRecordMap() {}--    void setNumLanes(const std::size_t NumLanes) override {-        Base::setNumLanes(NumLanes);-    }--    /** @brief converts record to a record reference */-    RamDomain pack(const std::vector<RamDomain>& Vector) override {-        assert(Vector.size() == Arity);-        RecordView View{Vector.data()};-        return Base::findOrInsert(View).first;-    };--    /** @brief converts record to a record reference */-    RamDomain pack(const RamDomain* Tuple) override {-        RecordView View{Tuple};-        return Base::findOrInsert(View).first;-    }--    /** @brief converts record to a record reference */-    RamDomain pack(const std::initializer_list<RamDomain>& List) override {-        assert(List.size() == Arity);-        RecordView View{std::data(List)};-        return Base::findOrInsert(View).first;-    }--    /** @brief convert record reference to a record pointer */-    const RamDomain* unpack(RamDomain Index) const override {-        return Base::fetch(Index).data();-    }-};--/** Record map specialized for arity 0 */-template <>-class SpecializedRecordMap<0> : public RecordMap {-    // The empty record always at index 1-    // The index 0 of each map is reserved.-    static constexpr RamDomain EmptyRecordIndex = 1;--    // To comply with previous behavior, the empty record-    // has no data:-    const RamDomain* EmptyRecordData = nullptr;--public:-    SpecializedRecordMap(const std::size_t /* LaneCount */) {}--    virtual ~SpecializedRecordMap() {}--    void setNumLanes(const std::size_t) override {}--    /** @brief converts record to a record reference */-    RamDomain pack([[maybe_unused]] const std::vector<RamDomain>& Vector) override {-        assert(Vector.size() == 0);-        return EmptyRecordIndex;-    };--    /** @brief converts record to a record reference */-    RamDomain pack(const RamDomain*) override {-        return EmptyRecordIndex;-    }--    /** @brief converts record to a record reference */-    RamDomain pack([[maybe_unused]] const std::initializer_list<RamDomain>& List) override {-        assert(List.size() == 0);-        return EmptyRecordIndex;-    }--    /** @brief convert record reference to a record pointer */-    const RamDomain* unpack([[maybe_unused]] RamDomain Index) const override {-        assert(Index == EmptyRecordIndex);-        return EmptyRecordData;-    }-};- /** The interface of any Record Table. */ class RecordTable { public:@@ -493,121 +35,6 @@     virtual RamDomain pack(const std::initializer_list<RamDomain>& List) = 0;      virtual const RamDomain* unpack(const RamDomain Ref, const std::size_t Arity) const = 0;-};--/** A concurrent Record Table with some specialized record maps. */-template <std::size_t... SpecializedArities>-class SpecializedRecordTable : public RecordTable {-private:-    // The current size of the Maps vector.-    std::size_t Size;--    // The record maps, indexed by arity.-    std::vector<RecordMap*> Maps;--    // The concurrency manager.-    mutable ConcurrentLanes Lanes;--    template <std::size_t Arity, std::size_t... Arities>-    void CreateSpecializedMaps() {-        if (Arity >= Size) {-            Size = Arity + 1;-            Maps.reserve(Size);-            Maps.resize(Size);-        }-        Maps[Arity] = new SpecializedRecordMap<Arity>(Lanes.lanes());-        if constexpr (sizeof...(Arities) > 0) {-            CreateSpecializedMaps<Arities...>();-        }-    }--public:-    /** @brief Construct a record table with the number of concurrent access lanes. */-    SpecializedRecordTable(const std::size_t LaneCount) : Size(0), Lanes(LaneCount) {-        CreateSpecializedMaps<SpecializedArities...>();-    }--    SpecializedRecordTable() : SpecializedRecordTable(1) {}--    virtual ~SpecializedRecordTable() {-        for (auto Map : Maps) {-            delete Map;-        }-    }--    /**-     * @brief set the number of concurrent access lanes.-     * Not thread-safe, use only when the datastructure is not being used.-     */-    virtual void setNumLanes(const std::size_t NumLanes) override {-        Lanes.setNumLanes(NumLanes);-        for (auto& Map : Maps) {-            if (Map) {-                Map->setNumLanes(NumLanes);-            }-        }-    }--    /** @brief convert tuple to record reference */-    virtual RamDomain pack(const RamDomain* Tuple, const std::size_t Arity) override {-        auto Guard = Lanes.guard();-        return lookupMap(Arity).pack(Tuple);-    }--    /** @brief convert tuple to record reference */-    virtual RamDomain pack(const std::initializer_list<RamDomain>& List) override {-        auto Guard = Lanes.guard();-        return lookupMap(List.size()).pack(std::data(List));-    }--    /** @brief convert record reference to a record */-    virtual const RamDomain* unpack(const RamDomain Ref, const std::size_t Arity) const override {-        auto Guard = Lanes.guard();-        return lookupMap(Arity).unpack(Ref);-    }--private:-    /** @brief lookup RecordMap for a given arity; the map for that arity must exist. */-    RecordMap& lookupMap(const std::size_t Arity) const {-        assert(Arity < Size && "Lookup for an arity while there is no record for that arity.");-        auto* Map = Maps[Arity];-        assert(Map != nullptr && "Lookup for an arity while there is no record for that arity.");-        return *Map;-    }--    /** @brief lookup RecordMap for a given arity; if it does not exist, create new RecordMap */-    RecordMap& lookupMap(const std::size_t Arity) {-        if (Arity < Size) {-            auto* Map = Maps[Arity];-            if (Map) {-                return *Map;-            }-        }--        createMap(Arity);-        return *Maps[Arity];-    }--    /** @brief create the RecordMap for the given arity. */-    void createMap(const std::size_t Arity) {-        Lanes.beforeLockAllBut();-        if (Arity < Size && Maps[Arity] != nullptr) {-            // Map of required arity has been created concurrently-            Lanes.beforeUnlockAllBut();-            return;-        }-        Lanes.lockAllBut();--        if (Arity >= Size) {-            Size = Arity + 1;-            Maps.reserve(Size);-            Maps.resize(Size);-        }-        Maps[Arity] = new GenericRecordMap(Lanes.lanes(), Arity);--        Lanes.beforeUnlockAllBut();-        Lanes.unlockAllBut();-    } };  /** @brief helper to convert tuple to record reference for the synthesiser */
cbits/souffle/SignalHandler.h view
@@ -26,12 +26,12 @@ #include <mutex> #include <string> -#ifdef _WIN32-#include <io.h>-#define STDERR_FILENO 2 /* Standard error output.  */-#else+#ifndef _MSC_VER #include <unistd.h>-#endif  //_WIN32+#else+#include <io.h>+#define STDERR_FILENO 2+#endif  namespace souffle { @@ -180,7 +180,13 @@                 // assign to variable to suppress ignored-return-value error.                 // I don't think we care enough to handle this fringe failure mode.                 // Worse case we don't get an error message.-                [[maybe_unused]] auto _ = ::write(STDERR_FILENO, msg, ::strlen(msg));+#ifdef _MSC_VER+                [[maybe_unused]] auto _ =+                        ::_write(STDERR_FILENO, msg, static_cast<unsigned int>(::strlen(msg)));+#else+                [[maybe_unused]] auto _ =+                        ::write(STDERR_FILENO, msg, static_cast<unsigned int>(::strlen(msg)));+#endif             }         }; 
cbits/souffle/SouffleInterface.h view
@@ -43,7 +43,7 @@  */ class Relation { public:-    using arity_type = uint32_t;+    using arity_type = std::size_t;  protected:     /**@@ -67,15 +67,15 @@          *          * TODO (Honghyw) : Provide a clear documentation of what id is used for.          */-        uint32_t id;+        std::size_t id;      public:         /**          * Get the ID of the iterator_base object.          *-         * @return ID of the iterator_base object (unit32_t)+         * @return ID of the iterator_base object (std::size_t)          */-        virtual uint32_t getId() const {+        virtual std::size_t getId() const {             return id;         } @@ -84,9 +84,9 @@          *          * Create an instance of iterator_base and set its ID to be arg_id.          *-         * @param arg_id ID of an iterator object (unit32_t)+         * @param arg_id ID of an iterator object (std::size_t)          */-        iterator_base(uint32_t arg_id) : id(arg_id) {}+        iterator_base(std::size_t arg_id) : id(arg_id) {}          /**          * Destructor.@@ -332,7 +332,8 @@     /**      * Get the attribute type of a relation at the column specified by the parameter.      * The attribute type is in the form "<primitive type>:<type name>".-     * <primitive type> can be s, f, u, or i standing for symbol, float, unsigned, and integer respectively,+     * <primitive type> can be s, f, u, i, r, or + standing for symbol, float,+     * unsigned, integer, record, and ADT respectively,      * which are the primitive types in Souffle.      * <type name> is the name given by the user in the Souffle program      *@@ -576,7 +577,8 @@      */     tuple& operator<<(RamSigned integer) {         assert(pos < size() && "exceeded tuple's size");-        assert((*relation.getAttrType(pos) == 'i' || *relation.getAttrType(pos) == 'r') &&+        assert((*relation.getAttrType(pos) == 'i' || *relation.getAttrType(pos) == 'r' ||+                       *relation.getAttrType(pos) == '+') &&                 "wrong element type");         array[pos++] = integer;         return *this;@@ -633,7 +635,8 @@      */     tuple& operator>>(RamSigned& integer) {         assert(pos < size() && "exceeded tuple's size");-        assert((*relation.getAttrType(pos) == 'i' || *relation.getAttrType(pos) == 'r') &&+        assert((*relation.getAttrType(pos) == 'i' || *relation.getAttrType(pos) == 'r' ||+                       *relation.getAttrType(pos) == '+') &&                 "wrong element type");         integer = ramBitCast<RamSigned>(array[pos++]);         return *this;
cbits/souffle/SymbolTable.h view
@@ -17,95 +17,105 @@ #pragma once  #include "souffle/RamTypes.h"-#include "souffle/datastructure/ConcurrentFlyweight.h"-#include "souffle/utility/MiscUtil.h"-#include "souffle/utility/ParallelUtil.h"-#include "souffle/utility/StreamUtil.h"-#include <algorithm>-#include <cstdlib>-#include <deque>-#include <initializer_list>-#include <iostream>++#include <memory> #include <string>-#include <unordered_map>-#include <utility>-#include <vector>  namespace souffle { +/** Interface of a generic SymbolTable iterator. */+class SymbolTableIteratorInterface {+public:+    virtual ~SymbolTableIteratorInterface() {}++    virtual const std::pair<const std::string, const std::size_t>& get() const = 0;++    virtual bool equals(const SymbolTableIteratorInterface& other) = 0;++    virtual SymbolTableIteratorInterface& incr() = 0;++    virtual std::unique_ptr<SymbolTableIteratorInterface> copy() const = 0;+};+ /**  * @class SymbolTable  *  * SymbolTable encodes symbols to numbers and decodes numbers to symbols.  */-class SymbolTable : protected FlyweightImpl<std::string> {-private:-    using Base = FlyweightImpl<std::string>;-+class SymbolTable { public:-    using iterator = typename Base::iterator;+    virtual ~SymbolTable() {} -    /** @brief Construct a symbol table with the given number of concurrent access lanes. */-    SymbolTable(const std::size_t LaneCount = 1) : Base(LaneCount) {}+    /**+     * @brief Iterator on a symbol table.+     *+     * Iterator over pairs of a symbol and its encoding index.+     */+    class Iterator {+    public:+        using value_type = const std::pair<const std::string, const std::size_t>;+        using reference = value_type&;+        using pointer = value_type*; -    /** @brief Construct a symbol table with the given initial symbols. */-    SymbolTable(std::initializer_list<std::string> symbols) : Base(1, symbols.size()) {-        for (const auto& symbol : symbols) {-            findOrInsert(symbol);+        Iterator(std::unique_ptr<SymbolTableIteratorInterface> ptr) : impl(std::move(ptr)) {}++        Iterator(const Iterator& it) : impl(it.impl->copy()) {}++        Iterator(Iterator&& it) : impl(std::move(it.impl)) {}++        reference operator*() const {+            return impl->get();         }-    } -    /** @brief Construct a symbol table with the given number of concurrent access lanes and initial symbols.-     */-    SymbolTable(const std::size_t LaneCount, std::initializer_list<std::string> symbols)-            : Base(LaneCount, symbols.size()) {-        for (const auto& symbol : symbols) {-            findOrInsert(symbol);+        pointer operator->() const {+            return &impl->get();         }-    } -    /**-     * @brief Set the number of concurrent access lanes.-     * This function is not thread-safe, do not call when other threads are using the datastructure.-     */-    void setNumLanes(const std::size_t NumLanes) {-        Base::setNumLanes(NumLanes);-    }+        Iterator& operator++() {+            impl->incr();+            return *this;+        } +        Iterator operator++(int) {+            Iterator prev(impl->copy());+            impl->incr();+            return prev;+        }++        bool operator==(const Iterator& I) const {+            return impl->equals(*I.impl);+        }++        bool operator!=(const Iterator& I) const {+            return !impl->equals(*I.impl);+        }++    private:+        std::unique_ptr<SymbolTableIteratorInterface> impl;+    };++    using iterator = Iterator;+     /** @brief Return an iterator on the first symbol. */-    iterator begin() const {-        return Base::begin();-    }+    virtual iterator begin() const = 0;      /** @brief Return an iterator past the last symbol. */-    iterator end() const {-        return Base::end();-    }+    virtual iterator end() const = 0;      /** @brief Check if the given symbol exist. */-    bool weakContains(const std::string& symbol) const {-        return Base::weakContains(symbol);-    }+    virtual bool weakContains(const std::string& symbol) const = 0;      /** @brief Encode a symbol to a symbol index. */-    RamDomain encode(const std::string& symbol) {-        return Base::findOrInsert(symbol).first;-    }+    virtual RamDomain encode(const std::string& symbol) = 0;      /** @brief Decode a symbol index to a symbol. */-    const std::string& decode(const RamDomain index) const {-        return Base::fetch(index);-    }+    virtual const std::string& decode(const RamDomain index) const = 0;      /** @brief Encode a symbol to a symbol index; aliases encode. */-    RamDomain unsafeEncode(const std::string& symbol) {-        return encode(symbol);-    }+    virtual RamDomain unsafeEncode(const std::string& symbol) = 0;      /** @brief Decode a symbol index to a symbol; aliases decode. */-    const std::string& unsafeDecode(const RamDomain index) const {-        return decode(index);-    }+    virtual const std::string& unsafeDecode(const RamDomain index) const = 0;      /**      * @brief Encode the symbol, it is inserted if it does not exist.@@ -113,10 +123,7 @@      * @return the symbol index and a boolean indicating if an insertion      * happened.      */-    std::pair<RamDomain, bool> findOrInsert(const std::string& symbol) {-        auto Res = Base::findOrInsert(symbol);-        return std::make_pair(Res.first, Res.second);-    }+    virtual std::pair<RamDomain, bool> findOrInsert(const std::string& symbol) = 0; };  }  // namespace souffle
cbits/souffle/datastructure/BTree.h view
@@ -624,7 +624,7 @@                         }                     } -                    pos = (i > other->numElements) ? 0 : i;+                    pos = (i > static_cast<unsigned>(other->numElements)) ? 0 : static_cast<unsigned>(i);                     other->insert_inner(root, root_lock, pos, predecessor, key, newNode, locked_nodes); #else                     other->insert_inner(root, root_lock, pos, predecessor, key, newNode);@@ -1340,7 +1340,8 @@                  // split this node                 auto old_root = root;-                idx -= cur->rebalance_or_split(const_cast<node**>(&root), root_lock, idx, parents);+                idx -= cur->rebalance_or_split(+                        const_cast<node**>(&root), root_lock, static_cast<int>(idx), parents);                  // release parent lock                 for (auto it = parents.rbegin(); it != parents.rend(); ++it) {@@ -1372,7 +1373,7 @@             assert(cur->numElements < node::maxKeys && "Split required!");              // move keys-            for (int j = cur->numElements; j > idx; --j) {+            for (int j = static_cast<int>(cur->numElements); j > static_cast<int>(idx); --j) {                 cur->keys[j] = cur->keys[j - 1];             } @@ -1960,7 +1961,7 @@         const int N = node::maxKeys;          // divide range in N+1 sub-ranges-        int length = (b - a) + 1;+        int64_t length = (b - a) + 1;          // terminal case: length is less then maxKeys         if (length <= N) {@@ -1977,7 +1978,7 @@          // recursive case - compute step size         int numKeys = N;-        int step = ((length - numKeys) / (numKeys + 1));+        int64_t step = ((length - numKeys) / (numKeys + 1));          while (numKeys > 1 && (step < N / 2)) {             numKeys--;
cbits/souffle/datastructure/BTreeDelete.h view
@@ -904,8 +904,10 @@     /**      * The iterator type to be utilized for scanning through btree instances.      */-    class iterator : public std::iterator<std::bidirectional_iterator_tag, Key> {-    public:+    class iterator {+        friend class souffle::detail::btree_delete<Key, Comparator, Allocator, blockSize, SearchStrategy,+                true, WeakComparator, Updater>;+         // a pointer to the node currently referred to         // node const* cur;         node* cur;@@ -913,6 +915,7 @@         // the index of the element currently addressed within the referenced node         field_index_type pos = 0; +    public:         using iterator_category = std::forward_iterator_tag;         using value_type = Key;         using difference_type = ptrdiff_t;@@ -1578,7 +1581,7 @@         } else {             auto lower_iter = internal_lower_bound(k);             if (lower_iter != end() && equal(*lower_iter, k)) {-                return distance(lower_iter, internal_upper_bound(k));+                return std::distance(lower_iter, internal_upper_bound(k));             } else {                 return 0;             }@@ -1605,7 +1608,7 @@         } else {             iterator lower_iter = internal_lower_bound(k);             if (lower_iter != end() && equal(*lower_iter, k)) {-                size_type count = distance(lower_iter, internal_upper_bound(k));+                size_type count = std::distance(lower_iter, internal_upper_bound(k));                 for (size_type i = 0; i < count; i++) {                     erase(lower_iter);                 }
cbits/souffle/datastructure/Brie.h view
@@ -1612,7 +1612,7 @@  /**  * A sparse bit-map is a bit map virtually assigning a bit value to every value if the- * uint32_t domain. However, only 1-bits are stored utilizing a nested sparse array+ * uint64_t domain. However, only 1-bits are stored utilizing a nested sparse array  * structure.  *  * @tparam BITS similar to the BITS parameter of the sparse array type@@ -1640,7 +1640,7 @@      // some constants for manipulating stored values     static constexpr std::size_t BITS_PER_ENTRY = sizeof(value_t) * CHAR_BIT;-    static constexpr std::size_t LEAF_INDEX_WIDTH = __builtin_ctz(BITS_PER_ENTRY);+    static constexpr std::size_t LEAF_INDEX_WIDTH = __builtin_ctz(static_cast<unsigned long>(BITS_PER_ENTRY));     static constexpr uint64_t LEAF_INDEX_MASK = BITS_PER_ENTRY - 1;      static uint64_t toMask(const value_t& value) {@@ -1936,8 +1936,8 @@     // remove ref-qual (if any); this can happen if we're a iterator-view     using iter_core_arg_type = typename std::remove_reference_t<IterCore>::store_iter; -    Value value;         // the value currently pointed to-    IterCore iter_core;  // the wrapped iterator+    Value value = {};         // the value currently pointed to+    IterCore iter_core = {};  // the wrapped iterator      // return an ephemeral nested iterator-view (view -> mutating us mutates our parent)     // NB: be careful that the lifetime of this iterator-view doesn't exceed that of its parent.@@ -2887,9 +2887,9 @@         if (this->empty()) return res;          // use top-level elements for partitioning-        int step = std::max(store.size() / chunks, std::size_t(1));+        size_t step = std::max(store.size() / chunks, std::size_t(1)); -        int c = 1;+        size_t c = 1;         auto priv = begin();         for (auto it = store.begin(); it != store.end(); ++it, c++) {             if (c % step != 0 || c == 1) {
cbits/souffle/datastructure/ConcurrentInsertOnlyHashMap.h view
@@ -46,7 +46,7 @@     for (std::size_t I = 0; I < ToPrime.size(); ++I) {         const uint64_t N = ToPrime[I].first;         const uint64_t K = ToPrime[I].second;-        const uint64_t Prime = (1UL << N) - K;+        const uint64_t Prime = (1ULL << N) - K;         if (Prime >= LowerBound) {             return Prime;         }@@ -145,7 +145,7 @@         }         LoadFactor = 1.0;         Buckets = std::make_unique<std::atomic<BucketList*>[]>(BucketCount);-        MaxSizeBeforeGrow = std::ceil(LoadFactor * (double)BucketCount);+        MaxSizeBeforeGrow = static_cast<std::size_t>(std::ceil(LoadFactor * (double)BucketCount));     }      ConcurrentInsertOnlyHashMap(const Hash& hash = Hash(), const KeyEqual& key_equal = KeyEqual(),@@ -412,12 +412,14 @@             // Chose a prime number of buckets that ensures the desired load factor             // given the current number of elements in the map.             const std::size_t CurrentSize = Size;-            const std::size_t NeededBucketCount = std::ceil((double)CurrentSize / LoadFactor);+            assert(LoadFactor > 0);+            const std::size_t NeededBucketCount =+                    static_cast<std::size_t>(std::ceil(static_cast<double>(CurrentSize) / LoadFactor));             std::size_t NewBucketCount = NeededBucketCount;             for (std::size_t I = 0; I < details::ToPrime.size(); ++I) {                 const uint64_t N = details::ToPrime[I].first;                 const uint64_t K = details::ToPrime[I].second;-                const uint64_t Prime = (1UL << N) - K;+                const uint64_t Prime = (1ULL << N) - K;                 if (Prime >= NeededBucketCount) {                     NewBucketCount = Prime;                     break;@@ -451,7 +453,8 @@              Buckets = std::move(NewBuckets);             BucketCount = NewBucketCount;-            MaxSizeBeforeGrow = ((double)NewBucketCount * LoadFactor);+            MaxSizeBeforeGrow =+                    static_cast<std::size_t>(std::ceil(static_cast<double>(NewBucketCount) * LoadFactor));         }          Lanes.beforeUnlockAllBut(H);
cbits/souffle/datastructure/EquivalenceRelation.h view
@@ -114,14 +114,10 @@         other.genAllDisjointSetLists();          // iterate over partitions at a time-        for (typename StatesMap::chunk it : other.equivalencePartition.getChunks(MAX_THREADS)) {-            for (auto& p : it) {-                value_type rep = p.first;-                StatesList& pl = *p.second;-                const std::size_t ksize = pl.size();-                for (std::size_t i = 0; i < ksize; ++i) {-                    this->sds.unionNodes(rep, pl.get(i));-                }+        for (auto&& [rep, pl] : other.equivalencePartition) {+            const std::size_t ksize = pl->size();+            for (std::size_t i = 0; i < ksize; ++i) {+                this->sds.unionNodes(rep, pl->get(i));             }         }         // invalidate iterators unconditionally
cbits/souffle/datastructure/LambdaBTree.h view
@@ -313,8 +313,8 @@                  // split this node                 auto old_root = this->root;-                idx -= cur->rebalance_or_split(-                        const_cast<typename parenttype::node**>(&this->root), this->root_lock, idx, parents);+                idx -= cur->rebalance_or_split(const_cast<typename parenttype::node**>(&this->root),+                        this->root_lock, static_cast<int>(idx), parents);                  // release parent lock                 for (auto it = parents.rbegin(); it != parents.rend(); ++it) {@@ -346,7 +346,7 @@             assert(cur->numElements < parenttype::node::maxKeys && "Split required!");              // move keys-            for (int j = cur->numElements; j > idx; --j) {+            for (int j = static_cast<int>(cur->numElements); j > idx; --j) {                 cur->keys[j] = cur->keys[j - 1];             } @@ -444,8 +444,8 @@              if (cur->numElements >= parenttype::node::maxKeys) {                 // split this node-                idx -= cur->rebalance_or_split(-                        const_cast<typename parenttype::node**>(&this->root), this->root_lock, idx);+                idx -= cur->rebalance_or_split(const_cast<typename parenttype::node**>(&this->root),+                        this->root_lock, static_cast<int>(idx));                  // insert element in right fragment                 if (((typename parenttype::size_type)idx) > cur->numElements) {
cbits/souffle/datastructure/PiggyList.h view
@@ -9,18 +9,14 @@ #include <iterator>  #ifdef _WIN32+#include <intrin.h> /**  * Some versions of MSVC do not provide a builtin for counting leading zeroes  * like gcc, so we have to implement it ourselves.  */ #if defined(_MSC_VER)-unsigned long __inline __builtin_clzll(unsigned long long value) {-    unsigned long msb = 0;--    if (_BitScanReverse64(&msb, value))-        return 63 - msb;-    else-        return 64;+int __inline __builtin_clzll(unsigned long long value) {+    return static_cast<int>(__lzcnt64(value)); } #endif  // _MSC_VER #endif  // _WIN32@@ -112,7 +108,7 @@         numElements.store(0);     }     const std::size_t BLOCKBITS = 16ul;-    const std::size_t INITIALBLOCKSIZE = (1ul << BLOCKBITS);+    const std::size_t INITIALBLOCKSIZE = (((std::size_t)1ul) << BLOCKBITS);      // number of elements currently stored within     std::atomic<std::size_t> numElements{0};@@ -252,11 +248,17 @@         container_size = 0;     } -    class iterator : std::iterator<std::forward_iterator_tag, T> {+    class iterator {         std::size_t cIndex = 0;         PiggyList* bl;      public:+        using iterator_category = std::forward_iterator_tag;+        using value_type = T;+        using difference_type = void;+        using pointer = T*;+        using reference = T&;+         // default ctor, to silence         iterator() = default; @@ -299,7 +301,7 @@         return iterator(this, size());     }     const std::size_t BLOCKBITS = 16ul;-    const std::size_t BLOCKSIZE = (1ul << BLOCKBITS);+    const std::size_t BLOCKSIZE = (((std::size_t)1ul) << BLOCKBITS);      // number of inserted     std::atomic<std::size_t> num_containers = 0;
+ cbits/souffle/datastructure/RecordTableImpl.h view
@@ -0,0 +1,599 @@+/*+ * Souffle - A Datalog Compiler+ * Copyright (c) 2022, The Souffle Developers. 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 RecordTableImpl.h+ *+ * RecordTable definition+ */++#pragma once++#include "souffle/RamTypes.h"+#include "souffle/RecordTable.h"+#include "souffle/datastructure/ConcurrentFlyweight.h"+#include "souffle/utility/span.h"++#include <cassert>+#include <cstddef>+#include <limits>+#include <memory>+#include <utility>+#include <vector>++namespace souffle {++namespace details {++// Helper to unroll for loop+template <auto Start, auto End, auto Inc, class F>+constexpr void constexpr_for(F&& f) {+    if constexpr (Start < End) {+        f(std::integral_constant<decltype(Start), Start>());+        constexpr_for<Start + Inc, End, Inc>(f);+    }+}++/// @brief The data-type of RamDomain records of any size.+using GenericRecord = std::vector<RamDomain>;++/// @brief The data-type of RamDomain records of specialized size.+template <std::size_t Arity>+using SpecializedRecord = std::array<RamDomain, Arity>;++/// @brief A view in a sequence of RamDomain value.+// TODO: use a `span`.+struct GenericRecordView {+    explicit GenericRecordView(const RamDomain* Data, const std::size_t Arity) : Data(Data), Arity(Arity) {}+    GenericRecordView(const GenericRecordView& Other) : Data(Other.Data), Arity(Other.Arity) {}+    GenericRecordView(GenericRecordView&& Other) : Data(Other.Data), Arity(Other.Arity) {}++    const RamDomain* const Data;+    const std::size_t Arity;++    const RamDomain* data() const {+        return Data;+    }++    const RamDomain& operator[](int I) const {+        assert(I >= 0 && static_cast<std::size_t>(I) < Arity);+        return Data[I];+    }+};++template <std::size_t Arity>+struct SpecializedRecordView {+    explicit SpecializedRecordView(const RamDomain* Data) : Data(Data) {}+    SpecializedRecordView(const SpecializedRecordView& Other) : Data(Other.Data) {}+    SpecializedRecordView(SpecializedRecordView&& Other) : Data(Other.Data) {}++    const RamDomain* const Data;++    const RamDomain* data() const {+        return Data;+    }++    const RamDomain& operator[](int I) const {+        assert(I >= 0 && static_cast<std::size_t>(I) < Arity);+        return Data[I];+    }+};++/// @brief Hash function object for a RamDomain record.+struct GenericRecordHash {+    explicit GenericRecordHash(const std::size_t Arity) : Arity(Arity) {}+    GenericRecordHash(const GenericRecordHash& Other) : Arity(Other.Arity) {}+    GenericRecordHash(GenericRecordHash&& Other) : Arity(Other.Arity) {}++    const std::size_t Arity;+    std::hash<RamDomain> domainHash;++    template <typename T>+    std::size_t operator()(const T& Record) const {+        std::size_t Seed = 0;+        for (std::size_t I = 0; I < Arity; ++I) {+            Seed ^= domainHash(Record[(int)I]) + 0x9e3779b9U + (Seed << 6U) + (Seed >> 2U);+        }+        return Seed;+    }+};++template <std::size_t Arity>+struct SpecializedRecordHash {+    explicit SpecializedRecordHash() {}+    SpecializedRecordHash(const SpecializedRecordHash& Other) : DomainHash(Other.DomainHash) {}+    SpecializedRecordHash(SpecializedRecordHash&& Other) : DomainHash(Other.DomainHash) {}++    std::hash<RamDomain> DomainHash;++    template <typename T>+    std::size_t operator()(const T& Record) const {+        std::size_t Seed = 0;+        constexpr_for<0, Arity, 1>([&](auto I) {+            Seed ^= DomainHash(Record[(int)I]) + 0x9e3779b9U + (Seed << 6U) + (Seed >> 2U);+        });+        return Seed;+    }+};++template <>+struct SpecializedRecordHash<0> {+    explicit SpecializedRecordHash() {}+    SpecializedRecordHash(const SpecializedRecordHash&) {}+    SpecializedRecordHash(SpecializedRecordHash&&) {}++    template <typename T>+    std::size_t operator()(const T&) const {+        return 0;+    }+};++/// @brief Equality function object for RamDomain records.+struct GenericRecordEqual {+    explicit GenericRecordEqual(const std::size_t Arity) : Arity(Arity) {}+    GenericRecordEqual(const GenericRecordEqual& Other) : Arity(Other.Arity) {}+    GenericRecordEqual(GenericRecordEqual&& Other) : Arity(Other.Arity) {}++    const std::size_t Arity;++    template <typename T, typename U>+    bool operator()(const T& A, const U& B) const {+        return (std::memcmp(A.data(), B.data(), Arity * sizeof(RamDomain)) == 0);+    }+};++template <std::size_t Arity>+struct SpecializedRecordEqual {+    explicit SpecializedRecordEqual() {}+    SpecializedRecordEqual(const SpecializedRecordEqual&) {}+    SpecializedRecordEqual(SpecializedRecordEqual&&) {}++    template <typename T, typename U>+    bool operator()(const T& A, const U& B) const {+        constexpr std::size_t Len = Arity * sizeof(RamDomain);+        return (std::memcmp(A.data(), B.data(), Len) == 0);+    }+};++template <>+struct SpecializedRecordEqual<0> {+    explicit SpecializedRecordEqual() {}+    SpecializedRecordEqual(const SpecializedRecordEqual&) {}+    SpecializedRecordEqual(SpecializedRecordEqual&&) {}++    template <typename T, typename U>+    bool operator()(const T&, const U&) const {+        return true;+    }+};++/// @brief Less function object for RamDomain records.+struct GenericRecordLess {+    explicit GenericRecordLess(const std::size_t Arity) : Arity(Arity) {}+    GenericRecordLess(const GenericRecordLess& Other) : Arity(Other.Arity) {}+    GenericRecordLess(GenericRecordLess&& Other) : Arity(Other.Arity) {}++    const std::size_t Arity;++    template <typename T, typename U>+    bool operator()(const T& A, const U& B) const {+        return (std::memcmp(A.data(), B.data(), Arity * sizeof(RamDomain)) < 0);+    }+};++template <std::size_t Arity>+struct SpecializedRecordLess {+    explicit SpecializedRecordLess() {}+    SpecializedRecordLess(const SpecializedRecordLess&) {}+    SpecializedRecordLess(SpecializedRecordLess&&) {}++    template <typename T, typename U>+    bool operator()(const T& A, const U& B) const {+        constexpr std::size_t Len = Arity * sizeof(RamDomain);+        return (std::memcmp(A.data(), B.data(), Len) < 0);+    }+};++template <>+struct SpecializedRecordLess<0> {+    explicit SpecializedRecordLess() {}+    SpecializedRecordLess(const SpecializedRecordLess&) {}+    SpecializedRecordLess(SpecializedRecordLess&&) {}++    template <typename T, typename U>+    bool operator()(const T&, const U&) const {+        return false;+    }+};++/// @brief Compare function object for RamDomain records.+struct GenericRecordCmp {+    explicit GenericRecordCmp(const std::size_t Arity) : Arity(Arity) {}+    GenericRecordCmp(const GenericRecordCmp& Other) : Arity(Other.Arity) {}+    GenericRecordCmp(GenericRecordCmp&& Other) : Arity(Other.Arity) {}++    const std::size_t Arity;++    template <typename T, typename U>+    int operator()(const T& A, const U& B) const {+        return std::memcmp(A.data(), B.data(), Arity * sizeof(RamDomain));+    }+};++template <std::size_t Arity>+struct SpecializedRecordCmp {+    explicit SpecializedRecordCmp() {}+    SpecializedRecordCmp(const SpecializedRecordCmp&) {}+    SpecializedRecordCmp(SpecializedRecordCmp&&) {}++    template <typename T, typename U>+    bool operator()(const T& A, const U& B) const {+        constexpr std::size_t Len = Arity * sizeof(RamDomain);+        return std::memcmp(A.data(), B.data(), Len);+    }+};++template <>+struct SpecializedRecordCmp<0> {+    explicit SpecializedRecordCmp() {}+    SpecializedRecordCmp(const SpecializedRecordCmp&) {}+    SpecializedRecordCmp(SpecializedRecordCmp&&) {}++    template <typename T, typename U>+    bool operator()(const T&, const U&) const {+        return 0;+    }+};++/// @brief Factory of RamDomain record.+struct GenericRecordFactory {+    using value_type = GenericRecord;+    using pointer = GenericRecord*;+    using reference = GenericRecord&;++    explicit GenericRecordFactory(const std::size_t Arity) : Arity(Arity) {}+    GenericRecordFactory(const GenericRecordFactory& Other) : Arity(Other.Arity) {}+    GenericRecordFactory(GenericRecordFactory&& Other) : Arity(Other.Arity) {}++    const std::size_t Arity;++    reference replace(reference Place, const std::vector<RamDomain>& V) {+        assert(V.size() == Arity);+        Place = V;+        return Place;+    }++    reference replace(reference Place, const GenericRecordView& V) {+        Place.clear();+        Place.insert(Place.begin(), V.data(), V.data() + Arity);+        return Place;+    }++    reference replace(reference Place, const RamDomain* V) {+        Place.clear();+        Place.insert(Place.begin(), V, V + Arity);+        return Place;+    }+};++template <std::size_t Arity>+struct SpecializedRecordFactory {+    using value_type = SpecializedRecord<Arity>;+    using pointer = SpecializedRecord<Arity>*;+    using reference = SpecializedRecord<Arity>&;++    explicit SpecializedRecordFactory() {}+    SpecializedRecordFactory(const SpecializedRecordFactory&) {}+    SpecializedRecordFactory(SpecializedRecordFactory&&) {}++    reference replace(reference Place, const SpecializedRecord<Arity>& V) {+        assert(V.size() == Arity);+        Place = V;+        return Place;+    }++    reference replace(reference Place, const SpecializedRecordView<Arity>& V) {+        constexpr std::size_t Len = Arity * sizeof(RamDomain);+        std::memcpy(Place.data(), V.data(), Len);+        return Place;+    }++    reference replace(reference Place, const RamDomain* V) {+        constexpr std::size_t Len = Arity * sizeof(RamDomain);+        std::memcpy(Place.data(), V, Len);+        return Place;+    }+};++template <>+struct SpecializedRecordFactory<0> {+    using value_type = SpecializedRecord<0>;+    using pointer = SpecializedRecord<0>*;+    using reference = SpecializedRecord<0>&;++    explicit SpecializedRecordFactory() {}+    SpecializedRecordFactory(const SpecializedRecordFactory&) {}+    SpecializedRecordFactory(SpecializedRecordFactory&&) {}++    reference replace(reference Place, const SpecializedRecord<0>&) {+        return Place;+    }++    reference replace(reference Place, const SpecializedRecordView<0>&) {+        return Place;+    }++    reference replace(reference Place, const RamDomain*) {+        return Place;+    }+};++}  // namespace details++/** @brief Interface of bidirectional mappping between records and record references. */+class RecordMap {+public:+    virtual ~RecordMap() {}+    virtual void setNumLanes(const std::size_t NumLanes) = 0;+    virtual RamDomain pack(const std::vector<RamDomain>& Vector) = 0;+    virtual RamDomain pack(const RamDomain* Tuple) = 0;+    virtual RamDomain pack(const std::initializer_list<RamDomain>& List) = 0;+    virtual const RamDomain* unpack(RamDomain index) const = 0;+};++/** @brief Bidirectional mappping between records and record references, for any record arity. */+class GenericRecordMap : public RecordMap,+                         protected FlyweightImpl<details::GenericRecord, details::GenericRecordHash,+                                 details::GenericRecordEqual, details::GenericRecordFactory> {+    using Base = FlyweightImpl<details::GenericRecord, details::GenericRecordHash,+            details::GenericRecordEqual, details::GenericRecordFactory>;++    const std::size_t Arity;++public:+    explicit GenericRecordMap(const std::size_t lane_count, const std::size_t arity)+            : Base(lane_count, 8, true, details::GenericRecordHash(arity), details::GenericRecordEqual(arity),+                      details::GenericRecordFactory(arity)),+              Arity(arity) {}++    virtual ~GenericRecordMap() {}++    void setNumLanes(const std::size_t NumLanes) override {+        Base::setNumLanes(NumLanes);+    }++    /** @brief converts record to a record reference */+    RamDomain pack(const std::vector<RamDomain>& Vector) override {+        return findOrInsert(Vector).first;+    };++    /** @brief converts record to a record reference */+    RamDomain pack(const RamDomain* Tuple) override {+        details::GenericRecordView View{Tuple, Arity};+        return findOrInsert(View).first;+    }++    /** @brief converts record to a record reference */+    RamDomain pack(const std::initializer_list<RamDomain>& List) override {+        details::GenericRecordView View{std::data(List), Arity};+        return findOrInsert(View).first;+    }++    /** @brief convert record reference to a record pointer */+    const RamDomain* unpack(RamDomain Index) const override {+        return fetch(Index).data();+    }+};++/** @brief Bidirectional mappping between records and record references, specialized for a record arity. */+template <std::size_t Arity>+class SpecializedRecordMap+        : public RecordMap,+          protected FlyweightImpl<details::SpecializedRecord<Arity>, details::SpecializedRecordHash<Arity>,+                  details::SpecializedRecordEqual<Arity>, details::SpecializedRecordFactory<Arity>> {+    using Record = details::SpecializedRecord<Arity>;+    using RecordView = details::SpecializedRecordView<Arity>;+    using RecordHash = details::SpecializedRecordHash<Arity>;+    using RecordEqual = details::SpecializedRecordEqual<Arity>;+    using RecordFactory = details::SpecializedRecordFactory<Arity>;+    using Base = FlyweightImpl<Record, RecordHash, RecordEqual, RecordFactory>;++public:+    SpecializedRecordMap(const std::size_t LaneCount)+            : Base(LaneCount, 8, true, RecordHash(), RecordEqual(), RecordFactory()) {}++    virtual ~SpecializedRecordMap() {}++    void setNumLanes(const std::size_t NumLanes) override {+        Base::setNumLanes(NumLanes);+    }++    /** @brief converts record to a record reference */+    RamDomain pack(const std::vector<RamDomain>& Vector) override {+        assert(Vector.size() == Arity);+        RecordView View{Vector.data()};+        return Base::findOrInsert(View).first;+    };++    /** @brief converts record to a record reference */+    RamDomain pack(const RamDomain* Tuple) override {+        RecordView View{Tuple};+        return Base::findOrInsert(View).first;+    }++    /** @brief converts record to a record reference */+    RamDomain pack(const std::initializer_list<RamDomain>& List) override {+        assert(List.size() == Arity);+        RecordView View{std::data(List)};+        return Base::findOrInsert(View).first;+    }++    /** @brief convert record reference to a record pointer */+    const RamDomain* unpack(RamDomain Index) const override {+        return Base::fetch(Index).data();+    }+};++/** Record map specialized for arity 0 */+template <>+class SpecializedRecordMap<0> : public RecordMap {+    // The empty record always at index 1+    // The index 0 of each map is reserved.+    static constexpr RamDomain EmptyRecordIndex = 1;++    // To comply with previous behavior, the empty record+    // has no data:+    const RamDomain* EmptyRecordData = nullptr;++public:+    SpecializedRecordMap(const std::size_t /* LaneCount */) {}++    virtual ~SpecializedRecordMap() {}++    void setNumLanes(const std::size_t) override {}++    /** @brief converts record to a record reference */+    RamDomain pack([[maybe_unused]] const std::vector<RamDomain>& Vector) override {+        assert(Vector.size() == 0);+        return EmptyRecordIndex;+    };++    /** @brief converts record to a record reference */+    RamDomain pack(const RamDomain*) override {+        return EmptyRecordIndex;+    }++    /** @brief converts record to a record reference */+    RamDomain pack([[maybe_unused]] const std::initializer_list<RamDomain>& List) override {+        assert(List.size() == 0);+        return EmptyRecordIndex;+    }++    /** @brief convert record reference to a record pointer */+    const RamDomain* unpack([[maybe_unused]] RamDomain Index) const override {+        assert(Index == EmptyRecordIndex);+        return EmptyRecordData;+    }+};++/** A concurrent Record Table with some specialized record maps. */+template <std::size_t... SpecializedArities>+class SpecializedRecordTable : public RecordTable {+private:+    // The current size of the Maps vector.+    std::size_t Size;++    // The record maps, indexed by arity.+    std::vector<RecordMap*> Maps;++    // The concurrency manager.+    mutable ConcurrentLanes Lanes;++    template <std::size_t Arity, std::size_t... Arities>+    void CreateSpecializedMaps() {+        if (Arity >= Size) {+            Size = Arity + 1;+            Maps.reserve(Size);+            Maps.resize(Size);+        }+        Maps[Arity] = new SpecializedRecordMap<Arity>(Lanes.lanes());+        if constexpr (sizeof...(Arities) > 0) {+            CreateSpecializedMaps<Arities...>();+        }+    }++public:+    /** @brief Construct a record table with the number of concurrent access lanes. */+    SpecializedRecordTable(const std::size_t LaneCount) : Size(0), Lanes(LaneCount) {+        CreateSpecializedMaps<SpecializedArities...>();+    }++    SpecializedRecordTable() : SpecializedRecordTable(1) {}++    virtual ~SpecializedRecordTable() {+        for (auto Map : Maps) {+            delete Map;+        }+    }++    /**+     * @brief set the number of concurrent access lanes.+     * Not thread-safe, use only when the datastructure is not being used.+     */+    virtual void setNumLanes(const std::size_t NumLanes) override {+        Lanes.setNumLanes(NumLanes);+        for (auto& Map : Maps) {+            if (Map) {+                Map->setNumLanes(NumLanes);+            }+        }+    }++    /** @brief convert tuple to record reference */+    virtual RamDomain pack(const RamDomain* Tuple, const std::size_t Arity) override {+        auto Guard = Lanes.guard();+        return lookupMap(Arity).pack(Tuple);+    }++    /** @brief convert tuple to record reference */+    virtual RamDomain pack(const std::initializer_list<RamDomain>& List) override {+        auto Guard = Lanes.guard();+        return lookupMap(List.size()).pack(std::data(List));+    }++    /** @brief convert record reference to a record */+    virtual const RamDomain* unpack(const RamDomain Ref, const std::size_t Arity) const override {+        auto Guard = Lanes.guard();+        return lookupMap(Arity).unpack(Ref);+    }++private:+    /** @brief lookup RecordMap for a given arity; the map for that arity must exist. */+    RecordMap& lookupMap(const std::size_t Arity) const {+        assert(Arity < Size && "Lookup for an arity while there is no record for that arity.");+        auto* Map = Maps[Arity];+        assert(Map != nullptr && "Lookup for an arity while there is no record for that arity.");+        return *Map;+    }++    /** @brief lookup RecordMap for a given arity; if it does not exist, create new RecordMap */+    RecordMap& lookupMap(const std::size_t Arity) {+        if (Arity < Size) {+            auto* Map = Maps[Arity];+            if (Map) {+                return *Map;+            }+        }++        createMap(Arity);+        return *Maps[Arity];+    }++    /** @brief create the RecordMap for the given arity. */+    void createMap(const std::size_t Arity) {+        Lanes.beforeLockAllBut();+        if (Arity < Size && Maps[Arity] != nullptr) {+            // Map of required arity has been created concurrently+            Lanes.beforeUnlockAllBut();+            return;+        }+        Lanes.lockAllBut();++        if (Arity >= Size) {+            Size = Arity + 1;+            Maps.reserve(Size);+            Maps.resize(Size);+        }+        Maps[Arity] = new GenericRecordMap(Lanes.lanes(), Arity);++        Lanes.beforeUnlockAllBut();+        Lanes.unlockAllBut();+    }+};++}  // namespace souffle
+ cbits/souffle/datastructure/SymbolTableImpl.h view
@@ -0,0 +1,133 @@+/*+ * Souffle - A Datalog Compiler+ * Copyright (c) 2022, The Souffle Developers. 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 SymbolTableImpl.h+ *+ * SymbolTable definition+ */++#pragma once++#include "souffle/SymbolTable.h"+#include "souffle/datastructure/ConcurrentFlyweight.h"+#include "souffle/utility/MiscUtil.h"+#include "souffle/utility/ParallelUtil.h"+#include "souffle/utility/StreamUtil.h"++#include <algorithm>+#include <cstdlib>+#include <deque>+#include <initializer_list>+#include <iostream>+#include <memory>+#include <string>+#include <unordered_map>+#include <utility>+#include <vector>++namespace souffle {++/**+ * @class SymbolTableImpl+ *+ * Implementation of the symbol table.+ */+class SymbolTableImpl : public SymbolTable, protected FlyweightImpl<std::string> {+private:+    using Base = FlyweightImpl<std::string>;++public:+    class IteratorImpl : public SymbolTableIteratorInterface, private Base::iterator {+    public:+        IteratorImpl(Base::iterator&& it) : Base::iterator(it) {}++        IteratorImpl(const Base::iterator& it) : Base::iterator(it) {}++        const std::pair<const std::string, const std::size_t>& get() const {+            return **this;+        }++        bool equals(const SymbolTableIteratorInterface& other) {+            return (*this) == static_cast<const IteratorImpl&>(other);+        }++        SymbolTableIteratorInterface& incr() {+            ++(*this);+            return *this;+        }++        std::unique_ptr<SymbolTableIteratorInterface> copy() const {+            return std::make_unique<IteratorImpl>(*this);+        }+    };++    using iterator = SymbolTable::Iterator;++    /** @brief Construct a symbol table with the given number of concurrent access lanes. */+    SymbolTableImpl(const std::size_t LaneCount = 1) : Base(LaneCount) {}++    /** @brief Construct a symbol table with the given initial symbols. */+    SymbolTableImpl(std::initializer_list<std::string> symbols) : Base(1, symbols.size()) {+        for (const auto& symbol : symbols) {+            findOrInsert(symbol);+        }+    }++    /** @brief Construct a symbol table with the given number of concurrent access lanes and initial symbols.+     */+    SymbolTableImpl(const std::size_t LaneCount, std::initializer_list<std::string> symbols)+            : Base(LaneCount, symbols.size()) {+        for (const auto& symbol : symbols) {+            findOrInsert(symbol);+        }+    }++    /**+     * @brief Set the number of concurrent access lanes.+     * This function is not thread-safe, do not call when other threads are using the datastructure.+     */+    void setNumLanes(const std::size_t NumLanes) {+        Base::setNumLanes(NumLanes);+    }++    iterator begin() const override {+        return SymbolTable::Iterator(std::make_unique<IteratorImpl>(Base::begin()));+    }++    iterator end() const override {+        return SymbolTable::Iterator(std::make_unique<IteratorImpl>(Base::end()));+    }++    bool weakContains(const std::string& symbol) const override {+        return Base::weakContains(symbol);+    }++    RamDomain encode(const std::string& symbol) override {+        return Base::findOrInsert(symbol).first;+    }++    const std::string& decode(const RamDomain index) const override {+        return Base::fetch(index);+    }++    RamDomain unsafeEncode(const std::string& symbol) override {+        return encode(symbol);+    }++    const std::string& unsafeDecode(const RamDomain index) const override {+        return decode(index);+    }++    std::pair<RamDomain, bool> findOrInsert(const std::string& symbol) override {+        auto Res = Base::findOrInsert(symbol);+        return std::make_pair(static_cast<RamDomain>(Res.first), Res.second);+    }+};++}  // namespace souffle
cbits/souffle/datastructure/Table.h view
@@ -49,11 +49,17 @@     std::size_t count = 0;  public:-    class iterator : public std::iterator<std::forward_iterator_tag, T> {+    class iterator {         Block* block;         unsigned pos;      public:+        using iterator_category = std::forward_iterator_tag;+        using value_type = T;+        using difference_type = void;+        using pointer = T*;+        using reference = T&;+         iterator(Block* block = nullptr, unsigned pos = 0) : block(block), pos(pos) {}          iterator(const iterator&) = default;
cbits/souffle/io/ReadStreamCSV.h view
@@ -347,8 +347,8 @@      */     static std::string getFileName(const std::map<std::string, std::string>& rwOperation) {         auto name = getOr(rwOperation, "filename", rwOperation.at("name") + ".facts");-        if (name.front() != '/') {-            name = getOr(rwOperation, "fact-dir", ".") + "/" + name;+        if (!isAbsolute(name)) {+            name = getOr(rwOperation, "fact-dir", ".") + pathSeparator + name;         }         return name;     }
cbits/souffle/io/ReadStreamSQLite.h view
@@ -127,6 +127,7 @@     }      void openDB() {+        sqlite3_config(SQLITE_CONFIG_URI, 1);         if (sqlite3_open(dbFilename.c_str(), &db) != SQLITE_OK) {             throwError("SQLite error in sqlite3_open: ");         }@@ -170,6 +171,10 @@         // convert dbname to filename         auto name = getOr(rwOperation, "dbname", rwOperation.at("name") + ".sqlite");         name = getOr(rwOperation, "filename", name);++        if (name.rfind("file:", 0) == 0 || name.rfind(":memory:", 0) == 0) {+            return name;+        }          if (name.front() != '/') {             name = getOr(rwOperation, "fact-dir", ".") + "/" + name;
cbits/souffle/io/WriteStreamSQLite.h view
@@ -65,9 +65,11 @@             }  #if RAM_DOMAIN_SIZE == 64-            if (sqlite3_bind_int64(insertStatement, i + 1, value) != SQLITE_OK) {+            if (sqlite3_bind_int64(insertStatement, static_cast<int>(i + 1),+                        static_cast<sqlite3_int64>(value)) != SQLITE_OK) { #else-            if (sqlite3_bind_int(insertStatement, i + 1, value) != SQLITE_OK) {+            if (sqlite3_bind_int(insertStatement, static_cast<int>(i + 1), static_cast<int>(value)) !=+                    SQLITE_OK) { #endif                 throwError("SQLite error in sqlite3_bind_text: ");             }@@ -102,7 +104,7 @@         throw std::invalid_argument(error.str());     } -    uint64_t getSymbolTableIDFromDB(int index) {+    uint64_t getSymbolTableIDFromDB(std::size_t index) {         if (sqlite3_bind_text(symbolSelectStatement, 1, symbolTable.decode(index).c_str(), -1,                     SQLITE_TRANSIENT) != SQLITE_OK) {             throwError("SQLite error in sqlite3_bind_text: ");@@ -115,7 +117,7 @@         sqlite3_reset(symbolSelectStatement);         return rowid;     }-    uint64_t getSymbolTableID(int index) {+    uint64_t getSymbolTableID(std::size_t index) {         if (dbSymbolTable.count(index) != 0) {             return dbSymbolTable[index];         }@@ -140,8 +142,9 @@     }      void openDB() {+        sqlite3_config(SQLITE_CONFIG_URI, 1);         if (sqlite3_open(dbFilename.c_str(), &db) != SQLITE_OK) {-            throwError("SQLite error in sqlite3_open");+            throwError("SQLite error in sqlite3_open: ");         }         sqlite3_extended_result_codes(db, 1);         executeSQL("PRAGMA synchronous = OFF", db);@@ -269,6 +272,10 @@         // convert dbname to filename         auto name = getOr(rwOperation, "dbname", rwOperation.at("name") + ".sqlite");         name = getOr(rwOperation, "filename", name);++        if (name.rfind("file:", 0) == 0 || name.rfind(":memory:", 0) == 0) {+            return name;+        }          if (name.front() != '/') {             name = getOr(rwOperation, "output-dir", ".") + "/" + name;
cbits/souffle/io/gzfstream.h view
@@ -91,8 +91,8 @@             *pptr() = c;             pbump(1);         }-        int toWrite = pptr() - pbase();-        if (gzwrite(fileHandle, pbase(), toWrite) != toWrite) {+        const int toWrite = static_cast<int>(pptr() - pbase());+        if (gzwrite(fileHandle, pbase(), static_cast<unsigned int>(toWrite)) != toWrite) {             return EOF;         }         pbump(-toWrite);@@ -108,13 +108,14 @@             return traits_type::to_int_type(*gptr());         } -        unsigned charsPutBack = gptr() - eback();+        std::size_t charsPutBack = gptr() - eback();         if (charsPutBack > reserveSize) {             charsPutBack = reserveSize;         }         memcpy(buffer + reserveSize - charsPutBack, gptr() - charsPutBack, charsPutBack); -        int charsRead = gzread(fileHandle, buffer + reserveSize, bufferSize - reserveSize);+        int charsRead =+                gzread(fileHandle, buffer + reserveSize, static_cast<unsigned int>(bufferSize - reserveSize));         if (charsRead <= 0) {             return EOF;         }@@ -126,8 +127,8 @@      int sync() override {         if ((pptr() != nullptr) && pptr() > pbase()) {-            int toWrite = pptr() - pbase();-            if (gzwrite(fileHandle, pbase(), toWrite) != toWrite) {+            const int toWrite = static_cast<int>(pptr() - pbase());+            if (gzwrite(fileHandle, pbase(), static_cast<unsigned int>(toWrite)) != toWrite) {                 return -1;             }             pbump(-toWrite);@@ -136,8 +137,8 @@     }  private:-    static constexpr unsigned int bufferSize = 65536;-    static constexpr unsigned int reserveSize = 16;+    static constexpr std::size_t bufferSize = 65536;+    static constexpr std::size_t reserveSize = 16;      char buffer[bufferSize] = {};     gzFile fileHandle = {};
cbits/souffle/utility/ContainerUtil.h view
@@ -219,6 +219,20 @@     return equal_targets(a, b, comp_deref<Own<T>>()); } +#ifdef _MSC_VER+// issue:+// https://developercommunity.visualstudio.com/t/c-template-template-not-recognized-as-class-templa/558979+template <typename T>+bool equal_targets(const std::vector<Own<T>>& a, const std::vector<Own<T>>& b) {+    return equal_targets(a, b, comp_deref<Own<T>>());+}++template <typename T>+bool equal_targets(const std::vector<T>& a, const std::vector<T>& b) {+    return equal_targets(a, b, comp_deref<T>());+}+#endif+ /**  * A function testing whether two maps of unique pointers are referencing to equivalent  * targets.
cbits/souffle/utility/EvaluatorUtil.h view
@@ -24,7 +24,7 @@ namespace souffle::evaluator {  template <typename A, typename F /* Tuple<RamDomain,1> -> void */>-void runRange(A from, A to, A step, F&& go) {+void runRange(const A from, const A to, const A step, F&& go) { #define GO(x) go(Tuple<RamDomain, 1>{ramBitCast(x)})     if (0 < step) {         for (auto x = from; x < to; x += step) {@@ -42,8 +42,26 @@ }  template <typename A, typename F /* Tuple<RamDomain,1> -> void */>-void runRange(A from, A to, F&& go) {-    return runRange(from, to, A(from <= to ? 1 : -1), std::forward<F>(go));+void runRangeBackward(const A from, const A to, F&& func) {+    assert(from > to);+    if (from > to) {+        for (auto x = from; x > to; --x) {+            func(Tuple<RamDomain, 1>{ramBitCast(x)});+        }+    }+}++template <typename A, typename F /* Tuple<RamDomain,1> -> void */>+void runRange(const A from, const A to, F&& go) {+    if constexpr (std::is_unsigned<A>()) {+        if (from <= to) {+            runRange(from, to, static_cast<A>(1U), std::forward<F>(go));+        } else {+            runRangeBackward(from, to, std::forward<F>(go));+        }+    } else {+        return runRange(from, to, A(from <= to ? 1 : -1), std::forward<F>(go));+    } }  template <typename A>
cbits/souffle/utility/FileUtil.h view
@@ -16,36 +16,39 @@  #pragma once +#include <algorithm> #include <climits> #include <cstdio> #include <cstdlib>+#include <filesystem> #include <fstream>+#include <map>+#include <optional> #include <sstream> #include <string> #include <utility> #include <sys/stat.h> +// -------------------------------------------------------------------------------+//                               File Utils+// -------------------------------------------------------------------------------+ #ifndef _WIN32 #include <unistd.h> #else+#define NOMINMAX+#define NOGDI #include <fcntl.h> #include <io.h> #include <stdlib.h> #include <windows.h>  // --------------------------------------------------------------------------------//                               File Utils+//                               Windows // ------------------------------------------------------------------------------- -#define X_OK 1 /* execute permission - unsupported in windows*/- #define PATH_MAX 260 -/**- * access and realpath are missing on windows, we use their windows equivalents- * as work-arounds.- */-#define access _access inline char* realpath(const char* path, char* resolved_path) {     return _fullpath(resolved_path, path, PATH_MAX); }@@ -57,19 +60,52 @@ #define pclose _pclose #endif +// -------------------------------------------------------------------------------+//                               All systems+// -------------------------------------------------------------------------------+ namespace souffle { +// The separator in the PATH variable+#ifdef _MSC_VER+const char PATHdelimiter = ';';+const char pathSeparator = '/';+#else+const char PATHdelimiter = ':';+const char pathSeparator = '/';+#endif++inline std::string& makePreferred(std::string& name) {+    std::replace(name.begin(), name.end(), '\\', '/');+    // std::replace(name.begin(), name.end(), '/', pathSeparator);+    return name;+}++inline bool isAbsolute(const std::string& path) {+    std::filesystem::path P(path);+    return P.is_absolute();+}+ /**  *  Check whether a file exists in the file system  */ inline bool existFile(const std::string& name) {+    static std::map<std::string, bool> existFileCache{};+    auto it = existFileCache.find(name);+    if (it != existFileCache.end()) {+        return it->second;+    }+    std::filesystem::path P(name);+    bool result = std::filesystem::exists(P);+    /*bool result = false;     struct stat buffer = {};-    if (stat(name.c_str(), &buffer) == 0) {+    if (stat(P.native().c_str(), &buffer) == 0) {         if ((buffer.st_mode & S_IFMT) != 0) {-            return true;+            result = true;         }-    }-    return false;+    }*/+    existFileCache[name] = result;+    return result; }  /**@@ -88,16 +124,24 @@ /**  * Check whether a given file exists and it is an executable  */+#ifdef _WIN32 inline bool isExecutable(const std::string& name) {+    return existFile(+            name);  // there is no EXECUTABLE bit on Windows, so theoretically any file may be executable+}+#else+inline bool isExecutable(const std::string& name) {     return existFile(name) && (access(name.c_str(), X_OK) == 0); }+#endif  /**  * Simple implementation of a which tool  */ inline std::string which(const std::string& name) {     // Check if name has path components in it and if so return it immediately-    if (name.find('/') != std::string::npos) {+    std::filesystem::path P(name);+    if (P.has_parent_path()) {         return name;     }     // Get PATH from environment, if it exists.@@ -111,8 +155,8 @@     std::string sub;      // Check for existence of a binary called 'name' in PATH-    while (std::getline(sstr, sub, ':')) {-        std::string path = sub + "/" + name;+    while (std::getline(sstr, sub, PATHdelimiter)) {+        std::string path = sub + pathSeparator + name;         if ((::realpath(path.c_str(), buf) != nullptr) && isExecutable(path) && !existDir(path)) {             return buf;         }@@ -127,19 +171,27 @@     if (name.empty()) {         return ".";     }-    std::size_t lastNotSlash = name.find_last_not_of('/');++    std::filesystem::path P(name);+    if (P.has_parent_path()) {+        return P.parent_path().string();+    } else {+        return ".";+    }++    std::size_t lastNotSlash = name.find_last_not_of(pathSeparator);     // All '/'     if (lastNotSlash == std::string::npos) {         return "/";     }-    std::size_t leadingSlash = name.find_last_of('/', lastNotSlash);+    std::size_t leadingSlash = name.find_last_of(pathSeparator, lastNotSlash);     // No '/'     if (leadingSlash == std::string::npos) {         return ".";     }     // dirname is '/'     if (leadingSlash == 0) {-        return "/";+        return std::string(1, pathSeparator);     }     return name.substr(0, leadingSlash); }@@ -157,15 +209,17 @@  *  Join two paths together; note that this does not resolve overlaps or relative paths.  */ inline std::string pathJoin(const std::string& first, const std::string& second) {-    unsigned firstPos = static_cast<unsigned>(first.size()) - 1;-    while (first.at(firstPos) == '/') {+    return (std::filesystem::path(first) / std::filesystem::path(second)).string();++    /*unsigned firstPos = static_cast<unsigned>(first.size()) - 1;+    while (first.at(firstPos) == pathSeparator) {         firstPos--;     }     unsigned secondPos = 0;-    while (second.at(secondPos) == '/') {+    while (second.at(secondPos) == pathSeparator) {         secondPos++;     }-    return first.substr(0, firstPos + 1) + '/' + second.substr(secondPos);+    return first.substr(0, firstPos + 1) + pathSeparator + second.substr(secondPos);*/ }  /*@@ -173,18 +227,19 @@  * relative to the directory given by @ base. A path here refers a  * colon-separated list of directories.  */-inline std::string findTool(const std::string& tool, const std::string& base, const std::string& path) {-    std::string dir = dirName(base);+inline std::optional<std::string> findTool(+        const std::string& tool, const std::string& base, const std::string& path) {+    std::filesystem::path dir(dirName(base));     std::stringstream sstr(path);     std::string sub;      while (std::getline(sstr, sub, ':')) {-        std::string subpath = dir + "/" + sub + '/' + tool;-        if (isExecutable(subpath)) {-            return absPath(subpath);+        auto subpath = (dir / sub / tool);+        if (std::filesystem::exists(subpath)) {+            return absPath(subpath.string());         }     }-    return "";+    return {}; }  /*@@ -195,12 +250,12 @@         return ".";     } -    std::size_t lastNotSlash = filename.find_last_not_of('/');+    std::size_t lastNotSlash = filename.find_last_not_of(pathSeparator);     if (lastNotSlash == std::string::npos) {-        return "/";+        return std::string(1, pathSeparator);     } -    std::size_t lastSlashBeforeBasename = filename.find_last_of('/', lastNotSlash - 1);+    std::size_t lastSlashBeforeBasename = filename.find_last_of(pathSeparator, lastNotSlash - 1);     if (lastSlashBeforeBasename == std::string::npos) {         lastSlashBeforeBasename = static_cast<std::size_t>(-1);     }@@ -217,7 +272,7 @@     if (lastDot == std::string::npos) {         return name;     }-    const std::size_t lastSlash = name.find_last_of('/');+    const std::size_t lastSlash = name.find_last_of(pathSeparator);     // last slash occurs after last dot, so no extension     if (lastSlash != std::string::npos && lastSlash > lastDot) {         return name;@@ -236,7 +291,7 @@     if (lastDot == std::string::npos) {         return std::string();     }-    const std::size_t lastSlash = name.find_last_of('/');+    const std::size_t lastSlash = name.find_last_of(pathSeparator);     // last slash occurs after last dot, so no extension     if (lastSlash != std::string::npos && lastSlash > lastDot) {         return std::string();@@ -250,10 +305,11 @@  */ inline std::string tempFile() { #ifdef _WIN32+    char ctempl[L_tmpnam];     std::string templ;     std::FILE* f = nullptr;     while (f == nullptr) {-        templ = std::tmpnam(nullptr);+        templ = std::tmpnam(ctempl);         f = fopen(templ.c_str(), "wx");     }     fclose(f);@@ -268,13 +324,16 @@ inline std::stringstream execStdOut(char const* cmd) {     FILE* in = popen(cmd, "r");     std::stringstream data;-    while (in != nullptr) {++    if (in == nullptr) {+        return data;+    }++    while (!feof(in)) {         int c = fgetc(in);-        if (feof(in) != 0) {-            break;-        }         data << static_cast<char>(c);     }+     pclose(in);     return data; }
cbits/souffle/utility/Iteration.h view
@@ -26,7 +26,18 @@ namespace souffle {  namespace detail {-+#ifdef _MSC_VER+#pragma warning(push)+#pragma warning(disable : 4172)+#elif defined(__GNUC__) && (__GNUC__ >= 7)+#pragma GCC diagnostic push+#pragma GCC diagnostic ignored "-Wreturn-local-addr"+#elif defined(__has_warning)+#pragma clang diagnostic push+#if __has_warning("-Wreturn-stack-address")+#pragma clang diagnostic ignored "-Wreturn-stack-address"+#endif+#endif // This is a helper in the cases when the lambda is stateless template <typename F> F makeFun() {@@ -34,9 +45,16 @@     // Even thought the lambda is stateless, it has no default ctor     // Is this gross?  Yes, yes it is.     // FIXME: Remove after C++20-    typename std::aligned_storage<sizeof(F)>::type fakeLam;+    typename std::aligned_storage<sizeof(F)>::type fakeLam{};     return reinterpret_cast<F const&>(fakeLam); }+#ifdef _MSC_VER+#pragma warning(pop)+#elif defined(__GNUC__) && (__GNUC__ >= 7)+#pragma GCC diagnostic pop+#elif defined(__has_warning)+#pragma clang diagnostic pop+#endif }  // namespace detail  // -------------------------------------------------------------@@ -101,7 +119,7 @@     }      /* Support for the pointer operator. */-    auto operator-> () const {+    auto operator->() const {         return &**this;     } @@ -265,9 +283,9 @@     }      // splits up this range into the given number of partitions-    std::vector<range> partition(int np = 100) {+    std::vector<range> partition(std::size_t np = 100) {         // obtain the size-        int n = 0;+        std::size_t n = 0;         for (auto i = a; i != b; ++i) {             n++;         }@@ -279,8 +297,8 @@         res.reserve(np);         auto cur = a;         auto last = cur;-        int i = 0;-        int p = 0;+        std::size_t i = 0;+        std::size_t p = 0;         while (cur != b) {             ++cur;             i++;
cbits/souffle/utility/MiscUtil.h view
@@ -30,19 +30,14 @@ #include <utility>  #ifdef _WIN32+#define NOMINMAX+#define NOGDI #include <fcntl.h> #include <io.h> #include <stdlib.h> #include <windows.h>  /**- * Windows headers define these and they interfere with the standard library- * functions.- */-#undef min-#undef max--/**  * On windows, the following gcc builtins are missing.  *  * In the case of popcountll, __popcnt64 is the windows equivalent.@@ -54,21 +49,34 @@ #define __builtin_popcountll __popcnt64  #if defined(_MSC_VER)-constexpr unsigned long __builtin_ctz(unsigned long value) {+// return the number of trailing zeroes in value, or 32 if value is zero.+inline constexpr unsigned long __builtin_ctz(unsigned long value) {     unsigned long trailing_zeroes = 0;+    if (value == 0) return 32;     while ((value = value >> 1) ^ 1) {         ++trailing_zeroes;     }     return trailing_zeroes; } -inline unsigned long __builtin_ctzll(unsigned long long value) {-    unsigned long trailing_zero = 0;+// return the number of trailing zeroes in value, or 64 if value is zero.+inline constexpr int __builtin_ctzll_constexpr(unsigned long long value) {+    int trailing_zeroes = 0; -    if (_BitScanForward64(&trailing_zero, value)) {-        return trailing_zero;+    if (value == 0) return 64;+    while ((value = value >> 1) ^ 1) {+        ++trailing_zeroes;+    }+    return trailing_zeroes;+}++inline int __builtin_ctzll(unsigned long long value) {+    unsigned long trailing_zeroes = 0;++    if (_BitScanForward64(&trailing_zeroes, value)) {+        return static_cast<int>(trailing_zeroes);     } else {-        return 64;+        return 64;  // return 64 like GCC would when value == 0     } } #endif  // _MSC_VER
cbits/souffle/utility/ParallelUtil.h view
@@ -48,14 +48,28 @@ #include <sched.h> // pthread_yield is deprecated and should be replaced by sched_yield #define pthread_yield sched_yield+#elif defined _MSC_VER+#include <thread>+#define NOMINMAX+#include <windows.h>+#define pthread_yield std::this_thread::yield #endif +#ifdef _MSC_VER // support for a parallel region+#define PARALLEL_START __pragma(omp parallel) {+#define PARALLEL_END }++// support for parallel loops+#define pfor __pragma(omp for schedule(dynamic)) for+#else+// support for a parallel region #define PARALLEL_START _Pragma("omp parallel") { #define PARALLEL_END }  // support for parallel loops #define pfor _Pragma("omp for schedule(dynamic)") for+#endif  // spawn and sync are processed sequentially (overhead to expensive) #define task_spawn@@ -221,10 +235,14 @@ namespace detail {  /* Pause instruction to prevent excess processor bus usage */+#if defined _MSC_VER+#define cpu_relax() YieldProcessor()+#else #ifdef __x86_64__ #define cpu_relax() asm volatile("pause\n" : : : "memory") #else #define cpu_relax() asm volatile("" : : : "memory")+#endif #endif  /**
cbits/souffle/utility/tinyformat.h view
@@ -792,27 +792,29 @@             break;         case 'X':             out.setf(std::ios::uppercase);-            // Falls through-        case 'x': case 'p':+            [[fallthrough]];+        case 'x':+            [[fallthrough]]; +        case 'p':             out.setf(std::ios::hex, std::ios::basefield);             intConversion = true;             break;         case 'E':             out.setf(std::ios::uppercase);-            // Falls through+            [[fallthrough]];         case 'e':             out.setf(std::ios::scientific, std::ios::floatfield);             out.setf(std::ios::dec, std::ios::basefield);             break;         case 'F':             out.setf(std::ios::uppercase);-            // Falls through+            [[fallthrough]];         case 'f':             out.setf(std::ios::fixed, std::ios::floatfield);             break;         case 'A':             out.setf(std::ios::uppercase);-            // Falls through+            [[fallthrough]];         case 'a': #           ifdef _MSC_VER             // Workaround https://developercommunity.visualstudio.com/content/problem/520472/hexfloat-stream-output-does-not-ignore-precision-a.html@@ -824,7 +826,7 @@             break;         case 'G':             out.setf(std::ios::uppercase);-            // Falls through+            [[fallthrough]];         case 'g':             out.setf(std::ios::dec, std::ios::basefield);             // As in boost::format, let stream decide float format.
souffle-haskell.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           souffle-haskell-version:        3.4.0+version:        3.5.0 synopsis:       Souffle Datalog bindings for Haskell description:    Souffle Datalog bindings for Haskell. category:       Logic Programming, Foreign Binding, Bindings@@ -32,6 +32,8 @@     cbits/souffle/datastructure/EquivalenceRelation.h     cbits/souffle/datastructure/LambdaBTree.h     cbits/souffle/datastructure/PiggyList.h+    cbits/souffle/datastructure/RecordTableImpl.h+    cbits/souffle/datastructure/SymbolTableImpl.h     cbits/souffle/datastructure/Table.h     cbits/souffle/datastructure/UnionFind.h     cbits/souffle/io/gzfstream.h@@ -102,9 +104,6 @@       souffle/CompiledSouffle.h       souffle/RamTypes.h       souffle/RecordTable.h-      souffle/datastructure/ConcurrentFlyweight.h-      souffle/datastructure/ConcurrentInsertOnlyHashMap.h-      souffle/utility/ParallelUtil.h       souffle/utility/span.h       souffle/SignalHandler.h       souffle/SouffleInterface.h@@ -114,18 +113,23 @@       souffle/utility/Iteration.h       souffle/utility/Types.h       souffle/utility/tinyformat.h-      souffle/utility/StreamUtil.h-      souffle/utility/ContainerUtil.h-      souffle/utility/DynamicCasting.h       souffle/datastructure/BTreeDelete.h       souffle/datastructure/BTreeUtil.h       souffle/utility/CacheUtil.h+      souffle/utility/ContainerUtil.h+      souffle/utility/DynamicCasting.h+      souffle/utility/ParallelUtil.h       souffle/datastructure/Brie.h+      souffle/utility/StreamUtil.h       souffle/datastructure/EquivalenceRelation.h       souffle/datastructure/LambdaBTree.h       souffle/datastructure/BTree.h       souffle/datastructure/PiggyList.h       souffle/datastructure/UnionFind.h+      souffle/datastructure/RecordTableImpl.h+      souffle/datastructure/ConcurrentFlyweight.h+      souffle/datastructure/ConcurrentInsertOnlyHashMap.h+      souffle/datastructure/SymbolTableImpl.h       souffle/datastructure/Table.h       souffle/io/IOSystem.h       souffle/io/ReadStream.h@@ -194,9 +198,6 @@       souffle/CompiledSouffle.h       souffle/RamTypes.h       souffle/RecordTable.h-      souffle/datastructure/ConcurrentFlyweight.h-      souffle/datastructure/ConcurrentInsertOnlyHashMap.h-      souffle/utility/ParallelUtil.h       souffle/utility/span.h       souffle/SignalHandler.h       souffle/SouffleInterface.h@@ -206,18 +207,23 @@       souffle/utility/Iteration.h       souffle/utility/Types.h       souffle/utility/tinyformat.h-      souffle/utility/StreamUtil.h-      souffle/utility/ContainerUtil.h-      souffle/utility/DynamicCasting.h       souffle/datastructure/BTreeDelete.h       souffle/datastructure/BTreeUtil.h       souffle/utility/CacheUtil.h+      souffle/utility/ContainerUtil.h+      souffle/utility/DynamicCasting.h+      souffle/utility/ParallelUtil.h       souffle/datastructure/Brie.h+      souffle/utility/StreamUtil.h       souffle/datastructure/EquivalenceRelation.h       souffle/datastructure/LambdaBTree.h       souffle/datastructure/BTree.h       souffle/datastructure/PiggyList.h       souffle/datastructure/UnionFind.h+      souffle/datastructure/RecordTableImpl.h+      souffle/datastructure/ConcurrentFlyweight.h+      souffle/datastructure/ConcurrentInsertOnlyHashMap.h+      souffle/datastructure/SymbolTableImpl.h       souffle/datastructure/Table.h       souffle/io/IOSystem.h       souffle/io/ReadStream.h@@ -281,9 +287,6 @@       souffle/CompiledSouffle.h       souffle/RamTypes.h       souffle/RecordTable.h-      souffle/datastructure/ConcurrentFlyweight.h-      souffle/datastructure/ConcurrentInsertOnlyHashMap.h-      souffle/utility/ParallelUtil.h       souffle/utility/span.h       souffle/SignalHandler.h       souffle/SouffleInterface.h@@ -293,18 +296,23 @@       souffle/utility/Iteration.h       souffle/utility/Types.h       souffle/utility/tinyformat.h-      souffle/utility/StreamUtil.h-      souffle/utility/ContainerUtil.h-      souffle/utility/DynamicCasting.h       souffle/datastructure/BTreeDelete.h       souffle/datastructure/BTreeUtil.h       souffle/utility/CacheUtil.h+      souffle/utility/ContainerUtil.h+      souffle/utility/DynamicCasting.h+      souffle/utility/ParallelUtil.h       souffle/datastructure/Brie.h+      souffle/utility/StreamUtil.h       souffle/datastructure/EquivalenceRelation.h       souffle/datastructure/LambdaBTree.h       souffle/datastructure/BTree.h       souffle/datastructure/PiggyList.h       souffle/datastructure/UnionFind.h+      souffle/datastructure/RecordTableImpl.h+      souffle/datastructure/ConcurrentFlyweight.h+      souffle/datastructure/ConcurrentInsertOnlyHashMap.h+      souffle/datastructure/SymbolTableImpl.h       souffle/datastructure/Table.h       souffle/io/IOSystem.h       souffle/io/ReadStream.h
tests/fixtures/edge_cases.cpp view
@@ -1,8 +1,10 @@  #include "souffle/CompiledSouffle.h" -extern "C" {+namespace functors {+ extern "C" { }+}  namespace souffle { static const RamDomain RAM_BIT_SHIFT_MASK = RAM_DOMAIN_SIZE - 1;@@ -14,7 +16,7 @@   return (ramBitCast<RamSigned>(a[0]) < ramBitCast<RamSigned>(b[0])) ? -1 : (ramBitCast<RamSigned>(a[0]) > ramBitCast<RamSigned>(b[0])) ? 1 :((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1])) ? -1 : (ramBitCast<RamSigned>(a[1]) > ramBitCast<RamSigned>(b[1])) ? 1 :((ramBitCast<RamSigned>(a[2]) < ramBitCast<RamSigned>(b[2])) ? -1 : (ramBitCast<RamSigned>(a[2]) > ramBitCast<RamSigned>(b[2])) ? 1 :(0)));  } bool less(const t_tuple& a, const t_tuple& b) const {-  return (ramBitCast<RamSigned>(a[0]) < ramBitCast<RamSigned>(b[0]))|| (ramBitCast<RamSigned>(a[0]) == ramBitCast<RamSigned>(b[0])) && ((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1]))|| (ramBitCast<RamSigned>(a[1]) == ramBitCast<RamSigned>(b[1])) && ((ramBitCast<RamSigned>(a[2]) < ramBitCast<RamSigned>(b[2]))));+  return (ramBitCast<RamSigned>(a[0]) < ramBitCast<RamSigned>(b[0]))|| ((ramBitCast<RamSigned>(a[0]) == ramBitCast<RamSigned>(b[0])) && ((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1]))|| ((ramBitCast<RamSigned>(a[1]) == ramBitCast<RamSigned>(b[1])) && ((ramBitCast<RamSigned>(a[2]) < ramBitCast<RamSigned>(b[2]))))));  } bool equal(const t_tuple& a, const t_tuple& b) const { return (ramBitCast<RamSigned>(a[0]) == ramBitCast<RamSigned>(b[0]))&&(ramBitCast<RamSigned>(a[1]) == ramBitCast<RamSigned>(b[1]))&&(ramBitCast<RamSigned>(a[2]) == ramBitCast<RamSigned>(b[2]));@@ -220,7 +222,7 @@   return (ramBitCast<RamUnsigned>(a[0]) < ramBitCast<RamUnsigned>(b[0])) ? -1 : (ramBitCast<RamUnsigned>(a[0]) > ramBitCast<RamUnsigned>(b[0])) ? 1 :((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1])) ? -1 : (ramBitCast<RamSigned>(a[1]) > ramBitCast<RamSigned>(b[1])) ? 1 :((ramBitCast<RamFloat>(a[2]) < ramBitCast<RamFloat>(b[2])) ? -1 : (ramBitCast<RamFloat>(a[2]) > ramBitCast<RamFloat>(b[2])) ? 1 :(0)));  } bool less(const t_tuple& a, const t_tuple& b) const {-  return (ramBitCast<RamUnsigned>(a[0]) < ramBitCast<RamUnsigned>(b[0]))|| (ramBitCast<RamUnsigned>(a[0]) == ramBitCast<RamUnsigned>(b[0])) && ((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1]))|| (ramBitCast<RamSigned>(a[1]) == ramBitCast<RamSigned>(b[1])) && ((ramBitCast<RamFloat>(a[2]) < ramBitCast<RamFloat>(b[2]))));+  return (ramBitCast<RamUnsigned>(a[0]) < ramBitCast<RamUnsigned>(b[0]))|| ((ramBitCast<RamUnsigned>(a[0]) == ramBitCast<RamUnsigned>(b[0])) && ((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1]))|| ((ramBitCast<RamSigned>(a[1]) == ramBitCast<RamSigned>(b[1])) && ((ramBitCast<RamFloat>(a[2]) < ramBitCast<RamFloat>(b[2]))))));  } bool equal(const t_tuple& a, const t_tuple& b) const { return (ramBitCast<RamUnsigned>(a[0]) == ramBitCast<RamUnsigned>(b[0]))&&(ramBitCast<RamSigned>(a[1]) == ramBitCast<RamSigned>(b[1]))&&(ramBitCast<RamFloat>(a[2]) == ramBitCast<RamFloat>(b[2]));@@ -327,7 +329,7 @@ } public: // -- initialize symbol table ---SymbolTable symTable{+SymbolTableImpl symTable{ 	R"_()_", 	R"_(abc)_", 	R"_(long_string_from_DL:...............................................................................................................................................................................................................................................................................................end)_",@@ -381,7 +383,7 @@     // set default threads (in embedded mode)     // if this is not set, and omp is used, the default omp setting of number of cores is used. #if defined(_OPENMP)-    if (0 < getNumThreads()) { omp_set_num_threads(getNumThreads()); }+    if (0 < getNumThreads()) { omp_set_num_threads(static_cast<int>(getNumThreads())); } #endif      signalHandler->set();@@ -413,29 +415,25 @@ } public: void printAll(std::string outputDirectoryArg = "") override {-try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","s\ts2\tn"},{"auxArity","0"},{"name","empty_strings"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 3, \"params\": [\"s\", \"s2\", \"n\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 3, \"types\": [\"s:symbol\", \"s:symbol\", \"i:number\"]}}"}});-if (!outputDirectoryArg.empty()) {directiveMap["output-dir"] = outputDirectoryArg;}-IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_1_empty_strings);-} catch (std::exception& e) {std::cerr << e.what();exit(1);} try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","s"},{"auxArity","0"},{"name","long_strings"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"s\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"s:symbol\"]}}"}}); if (!outputDirectoryArg.empty()) {directiveMap["output-dir"] = outputDirectoryArg;} IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_2_long_strings); } catch (std::exception& e) {std::cerr << e.what();exit(1);}-try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","u\tn\tf"},{"auxArity","0"},{"name","no_strings"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 3, \"params\": [\"u\", \"n\", \"f\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 3, \"types\": [\"u:unsigned\", \"i:number\", \"f:float\"]}}"}});-if (!outputDirectoryArg.empty()) {directiveMap["output-dir"] = outputDirectoryArg;}-IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_3_no_strings);-} catch (std::exception& e) {std::cerr << e.what();exit(1);} try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","s"},{"auxArity","0"},{"name","unicode"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"s\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"s:symbol\"]}}"}}); if (!outputDirectoryArg.empty()) {directiveMap["output-dir"] = outputDirectoryArg;} IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_4_unicode); } catch (std::exception& e) {std::cerr << e.what();exit(1);}+try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","s\ts2\tn"},{"auxArity","0"},{"name","empty_strings"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 3, \"params\": [\"s\", \"s2\", \"n\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 3, \"types\": [\"s:symbol\", \"s:symbol\", \"i:number\"]}}"}});+if (!outputDirectoryArg.empty()) {directiveMap["output-dir"] = outputDirectoryArg;}+IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_1_empty_strings);+} catch (std::exception& e) {std::cerr << e.what();exit(1);}+try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","u\tn\tf"},{"auxArity","0"},{"name","no_strings"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 3, \"params\": [\"u\", \"n\", \"f\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 3, \"types\": [\"u:unsigned\", \"i:number\", \"f:float\"]}}"}});+if (!outputDirectoryArg.empty()) {directiveMap["output-dir"] = outputDirectoryArg;}+IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_3_no_strings);+} catch (std::exception& e) {std::cerr << e.what();exit(1);} } public: void loadAll(std::string inputDirectoryArg = "") override {-try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","s"},{"auxArity","0"},{"fact-dir","."},{"name","long_strings"},{"operation","input"},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"s\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"s:symbol\"]}}"}});-if (!inputDirectoryArg.empty()) {directiveMap["fact-dir"] = inputDirectoryArg;}-IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_2_long_strings);-} catch (std::exception& e) {std::cerr << "Error loading long_strings data: " << e.what() << '\n';} try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","u\tn\tf"},{"auxArity","0"},{"fact-dir","."},{"name","no_strings"},{"operation","input"},{"params","{\"records\": {}, \"relation\": {\"arity\": 3, \"params\": [\"u\", \"n\", \"f\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 3, \"types\": [\"u:unsigned\", \"i:number\", \"f:float\"]}}"}}); if (!inputDirectoryArg.empty()) {directiveMap["fact-dir"] = inputDirectoryArg;} IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_3_no_strings);@@ -448,17 +446,15 @@ if (!inputDirectoryArg.empty()) {directiveMap["fact-dir"] = inputDirectoryArg;} IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_4_unicode); } catch (std::exception& e) {std::cerr << "Error loading unicode data: " << e.what() << '\n';}+try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","s"},{"auxArity","0"},{"fact-dir","."},{"name","long_strings"},{"operation","input"},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"s\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"s:symbol\"]}}"}});+if (!inputDirectoryArg.empty()) {directiveMap["fact-dir"] = inputDirectoryArg;}+IOSystem::getInstance().getReader(directiveMap, symTable, recordTable)->readAll(*rel_2_long_strings);+} catch (std::exception& e) {std::cerr << "Error loading long_strings data: " << e.what() << '\n';} } public: void dumpInputs() override { try {std::map<std::string, std::string> rwOperation; rwOperation["IO"] = "stdout";-rwOperation["name"] = "long_strings";-rwOperation["types"] = "{\"relation\": {\"arity\": 1, \"auxArity\": 0, \"types\": [\"s:symbol\"]}}";-IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_2_long_strings);-} catch (std::exception& e) {std::cerr << e.what();exit(1);}-try {std::map<std::string, std::string> rwOperation;-rwOperation["IO"] = "stdout"; rwOperation["name"] = "no_strings"; rwOperation["types"] = "{\"relation\": {\"arity\": 3, \"auxArity\": 0, \"types\": [\"u:unsigned\", \"i:number\", \"f:float\"]}}"; IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_3_no_strings);@@ -475,32 +471,38 @@ rwOperation["types"] = "{\"relation\": {\"arity\": 1, \"auxArity\": 0, \"types\": [\"s:symbol\"]}}"; IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_4_unicode); } catch (std::exception& e) {std::cerr << e.what();exit(1);}+try {std::map<std::string, std::string> rwOperation;+rwOperation["IO"] = "stdout";+rwOperation["name"] = "long_strings";+rwOperation["types"] = "{\"relation\": {\"arity\": 1, \"auxArity\": 0, \"types\": [\"s:symbol\"]}}";+IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_2_long_strings);+} catch (std::exception& e) {std::cerr << e.what();exit(1);} } public: void dumpOutputs() override { try {std::map<std::string, std::string> rwOperation; rwOperation["IO"] = "stdout";-rwOperation["name"] = "empty_strings";-rwOperation["types"] = "{\"relation\": {\"arity\": 3, \"auxArity\": 0, \"types\": [\"s:symbol\", \"s:symbol\", \"i:number\"]}}";-IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_1_empty_strings);+rwOperation["name"] = "long_strings";+rwOperation["types"] = "{\"relation\": {\"arity\": 1, \"auxArity\": 0, \"types\": [\"s:symbol\"]}}";+IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_2_long_strings); } catch (std::exception& e) {std::cerr << e.what();exit(1);} try {std::map<std::string, std::string> rwOperation; rwOperation["IO"] = "stdout";-rwOperation["name"] = "long_strings";+rwOperation["name"] = "unicode"; rwOperation["types"] = "{\"relation\": {\"arity\": 1, \"auxArity\": 0, \"types\": [\"s:symbol\"]}}";-IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_2_long_strings);+IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_4_unicode); } catch (std::exception& e) {std::cerr << e.what();exit(1);} try {std::map<std::string, std::string> rwOperation; rwOperation["IO"] = "stdout";-rwOperation["name"] = "no_strings";-rwOperation["types"] = "{\"relation\": {\"arity\": 3, \"auxArity\": 0, \"types\": [\"u:unsigned\", \"i:number\", \"f:float\"]}}";-IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_3_no_strings);+rwOperation["name"] = "empty_strings";+rwOperation["types"] = "{\"relation\": {\"arity\": 3, \"auxArity\": 0, \"types\": [\"s:symbol\", \"s:symbol\", \"i:number\"]}}";+IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_1_empty_strings); } catch (std::exception& e) {std::cerr << e.what();exit(1);} try {std::map<std::string, std::string> rwOperation; rwOperation["IO"] = "stdout";-rwOperation["name"] = "unicode";-rwOperation["types"] = "{\"relation\": {\"arity\": 1, \"auxArity\": 0, \"types\": [\"s:symbol\"]}}";-IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_4_unicode);+rwOperation["name"] = "no_strings";+rwOperation["types"] = "{\"relation\": {\"arity\": 3, \"auxArity\": 0, \"types\": [\"u:unsigned\", \"i:number\", \"f:float\"]}}";+IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_3_no_strings); } catch (std::exception& e) {std::cerr << e.what();exit(1);} } public:@@ -541,21 +543,21 @@ } catch (std::exception& e) {std::cerr << "Error loading empty_strings data: " << e.what() << '\n';} } signalHandler->setMsg(R"_(empty_strings("","",42).-in file /home/luc/personal/souffle-haskell/tests/fixtures/edge_cases.dl [20:1-20:27])_");+in file edge_cases.dl [20:1-20:27])_"); [&](){ CREATE_OP_CONTEXT(rel_1_empty_strings_op_ctxt,rel_1_empty_strings->createContext()); Tuple<RamDomain,3> tuple{{ramBitCast(RamSigned(0)),ramBitCast(RamSigned(0)),ramBitCast(RamSigned(42))}}; rel_1_empty_strings->insert(tuple,READ_OP_CONTEXT(rel_1_empty_strings_op_ctxt)); } ();signalHandler->setMsg(R"_(empty_strings("","abc",42).-in file /home/luc/personal/souffle-haskell/tests/fixtures/edge_cases.dl [21:1-21:30])_");+in file edge_cases.dl [21:1-21:30])_"); [&](){ CREATE_OP_CONTEXT(rel_1_empty_strings_op_ctxt,rel_1_empty_strings->createContext()); Tuple<RamDomain,3> tuple{{ramBitCast(RamSigned(0)),ramBitCast(RamSigned(1)),ramBitCast(RamSigned(42))}}; rel_1_empty_strings->insert(tuple,READ_OP_CONTEXT(rel_1_empty_strings_op_ctxt)); } ();signalHandler->setMsg(R"_(empty_strings("abc","",42).-in file /home/luc/personal/souffle-haskell/tests/fixtures/edge_cases.dl [22:1-22:30])_");+in file edge_cases.dl [22:1-22:30])_"); [&](){ CREATE_OP_CONTEXT(rel_1_empty_strings_op_ctxt,rel_1_empty_strings->createContext()); Tuple<RamDomain,3> tuple{{ramBitCast(RamSigned(1)),ramBitCast(RamSigned(0)),ramBitCast(RamSigned(42))}};@@ -582,7 +584,7 @@ } catch (std::exception& e) {std::cerr << "Error loading long_strings data: " << e.what() << '\n';} } signalHandler->setMsg(R"_(long_strings("long_string_from_DL:...............................................................................................................................................................................................................................................................................................end").-in file /home/luc/personal/souffle-haskell/tests/fixtures/edge_cases.dl [25:1-25:328])_");+in file edge_cases.dl [25:1-25:328])_"); [&](){ CREATE_OP_CONTEXT(rel_2_long_strings_op_ctxt,rel_2_long_strings->createContext()); Tuple<RamDomain,1> tuple{{ramBitCast(RamSigned(2))}};@@ -609,14 +611,14 @@ } catch (std::exception& e) {std::cerr << "Error loading no_strings data: " << e.what() << '\n';} } signalHandler->setMsg(R"_(no_strings(42,-100,1.5).-in file /home/luc/personal/souffle-haskell/tests/fixtures/edge_cases.dl [33:1-33:27])_");+in file edge_cases.dl [33:1-33:27])_"); [&](){ CREATE_OP_CONTEXT(rel_3_no_strings_op_ctxt,rel_3_no_strings->createContext()); Tuple<RamDomain,3> tuple{{ramBitCast(RamUnsigned(42)),ramBitCast(RamSigned(-100)),ramBitCast(RamFloat(1.5))}}; rel_3_no_strings->insert(tuple,READ_OP_CONTEXT(rel_3_no_strings_op_ctxt)); } ();signalHandler->setMsg(R"_(no_strings(123,-456,3.14).-in file /home/luc/personal/souffle-haskell/tests/fixtures/edge_cases.dl [34:1-34:29])_");+in file edge_cases.dl [34:1-34:29])_"); [&](){ CREATE_OP_CONTEXT(rel_3_no_strings_op_ctxt,rel_3_no_strings->createContext()); Tuple<RamDomain,3> tuple{{ramBitCast(RamUnsigned(123)),ramBitCast(RamSigned(-456)),ramBitCast(RamFloat(3.1400001))}};@@ -643,14 +645,14 @@ } catch (std::exception& e) {std::cerr << "Error loading unicode data: " << e.what() << '\n';} } signalHandler->setMsg(R"_(unicode("∀").-in file /home/luc/personal/souffle-haskell/tests/fixtures/edge_cases.dl [30:1-30:16])_");+in file edge_cases.dl [30:1-30:16])_"); [&](){ CREATE_OP_CONTEXT(rel_4_unicode_op_ctxt,rel_4_unicode->createContext()); Tuple<RamDomain,1> tuple{{ramBitCast(RamSigned(3))}}; rel_4_unicode->insert(tuple,READ_OP_CONTEXT(rel_4_unicode_op_ctxt)); } ();signalHandler->setMsg(R"_(unicode("∀∀").-in file /home/luc/personal/souffle-haskell/tests/fixtures/edge_cases.dl [31:1-31:19])_");+in file edge_cases.dl [31:1-31:19])_"); [&](){ CREATE_OP_CONTEXT(rel_4_unicode_op_ctxt,rel_4_unicode->createContext()); Tuple<RamDomain,1> tuple{{ramBitCast(RamSigned(4))}};
tests/fixtures/path.cpp view
@@ -1,8 +1,10 @@  #include "souffle/CompiledSouffle.h" -extern "C" {+namespace functors {+ extern "C" { }+}  namespace souffle { static const RamDomain RAM_BIT_SHIFT_MASK = RAM_DOMAIN_SIZE - 1;@@ -14,7 +16,7 @@   return (ramBitCast<RamSigned>(a[0]) < ramBitCast<RamSigned>(b[0])) ? -1 : (ramBitCast<RamSigned>(a[0]) > ramBitCast<RamSigned>(b[0])) ? 1 :((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1])) ? -1 : (ramBitCast<RamSigned>(a[1]) > ramBitCast<RamSigned>(b[1])) ? 1 :(0));  } bool less(const t_tuple& a, const t_tuple& b) const {-  return (ramBitCast<RamSigned>(a[0]) < ramBitCast<RamSigned>(b[0]))|| (ramBitCast<RamSigned>(a[0]) == ramBitCast<RamSigned>(b[0])) && ((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1])));+  return (ramBitCast<RamSigned>(a[0]) < ramBitCast<RamSigned>(b[0]))|| ((ramBitCast<RamSigned>(a[0]) == ramBitCast<RamSigned>(b[0])) && ((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1]))));  } bool equal(const t_tuple& a, const t_tuple& b) const { return (ramBitCast<RamSigned>(a[0]) == ramBitCast<RamSigned>(b[0]))&&(ramBitCast<RamSigned>(a[1]) == ramBitCast<RamSigned>(b[1]));@@ -117,7 +119,7 @@   return (ramBitCast<RamSigned>(a[0]) < ramBitCast<RamSigned>(b[0])) ? -1 : (ramBitCast<RamSigned>(a[0]) > ramBitCast<RamSigned>(b[0])) ? 1 :((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1])) ? -1 : (ramBitCast<RamSigned>(a[1]) > ramBitCast<RamSigned>(b[1])) ? 1 :(0));  } bool less(const t_tuple& a, const t_tuple& b) const {-  return (ramBitCast<RamSigned>(a[0]) < ramBitCast<RamSigned>(b[0]))|| (ramBitCast<RamSigned>(a[0]) == ramBitCast<RamSigned>(b[0])) && ((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1])));+  return (ramBitCast<RamSigned>(a[0]) < ramBitCast<RamSigned>(b[0]))|| ((ramBitCast<RamSigned>(a[0]) == ramBitCast<RamSigned>(b[0])) && ((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1]))));  } bool equal(const t_tuple& a, const t_tuple& b) const { return (ramBitCast<RamSigned>(a[0]) == ramBitCast<RamSigned>(b[0]))&&(ramBitCast<RamSigned>(a[1]) == ramBitCast<RamSigned>(b[1]));@@ -236,7 +238,7 @@ } public: // -- initialize symbol table ---SymbolTable symTable{+SymbolTableImpl symTable{ 	R"_(a)_", 	R"_(b)_", 	R"_(c)_",@@ -282,7 +284,7 @@     // set default threads (in embedded mode)     // if this is not set, and omp is used, the default omp setting of number of cores is used. #if defined(_OPENMP)-    if (0 < getNumThreads()) { omp_set_num_threads(getNumThreads()); }+    if (0 < getNumThreads()) { omp_set_num_threads(static_cast<int>(getNumThreads())); } #endif      signalHandler->set();@@ -378,14 +380,14 @@ } catch (std::exception& e) {std::cerr << "Error loading edge data: " << e.what() << '\n';} } signalHandler->setMsg(R"_(edge("a","b").-in file /home/luc/personal/souffle-haskell/tests/fixtures/path.dl [11:1-11:16])_");+in file path.dl [11:1-11:16])_"); [&](){ CREATE_OP_CONTEXT(rel_1_edge_op_ctxt,rel_1_edge->createContext()); Tuple<RamDomain,2> tuple{{ramBitCast(RamSigned(0)),ramBitCast(RamSigned(1))}}; rel_1_edge->insert(tuple,READ_OP_CONTEXT(rel_1_edge_op_ctxt)); } ();signalHandler->setMsg(R"_(edge("b","c").-in file /home/luc/personal/souffle-haskell/tests/fixtures/path.dl [12:1-12:16])_");+in file path.dl [12:1-12:16])_"); [&](){ CREATE_OP_CONTEXT(rel_1_edge_op_ctxt,rel_1_edge->createContext()); Tuple<RamDomain,2> tuple{{ramBitCast(RamSigned(1)),ramBitCast(RamSigned(2))}};@@ -407,11 +409,11 @@ void subroutine_1(const std::vector<RamDomain>& args, std::vector<RamDomain>& ret) { signalHandler->setMsg(R"_(reachable(x,y) :-     edge(x,y).-in file /home/luc/personal/souffle-haskell/tests/fixtures/path.dl [14:1-14:31])_");+in file path.dl [14:1-14:31])_"); if(!(rel_1_edge->empty())) { [&](){-CREATE_OP_CONTEXT(rel_2_reachable_op_ctxt,rel_2_reachable->createContext()); CREATE_OP_CONTEXT(rel_1_edge_op_ctxt,rel_1_edge->createContext());+CREATE_OP_CONTEXT(rel_2_reachable_op_ctxt,rel_2_reachable->createContext()); for(const auto& env0 : *rel_1_edge) { Tuple<RamDomain,2> tuple{{ramBitCast(env0[0]),ramBitCast(env0[1])}}; rel_2_reachable->insert(tuple,READ_OP_CONTEXT(rel_2_reachable_op_ctxt));@@ -431,12 +433,12 @@ signalHandler->setMsg(R"_(reachable(x,z) :-     edge(x,y),    reachable(y,z).-in file /home/luc/personal/souffle-haskell/tests/fixtures/path.dl [15:1-15:48])_");+in file path.dl [15:1-15:48])_"); if(!(rel_1_edge->empty()) && !(rel_3_delta_reachable->empty())) { [&](){-CREATE_OP_CONTEXT(rel_2_reachable_op_ctxt,rel_2_reachable->createContext());-CREATE_OP_CONTEXT(rel_4_new_reachable_op_ctxt,rel_4_new_reachable->createContext()); CREATE_OP_CONTEXT(rel_1_edge_op_ctxt,rel_1_edge->createContext());+CREATE_OP_CONTEXT(rel_4_new_reachable_op_ctxt,rel_4_new_reachable->createContext());+CREATE_OP_CONTEXT(rel_2_reachable_op_ctxt,rel_2_reachable->createContext()); CREATE_OP_CONTEXT(rel_3_delta_reachable_op_ctxt,rel_3_delta_reachable->createContext()); for(const auto& env0 : *rel_1_edge) { auto range = rel_3_delta_reachable->lowerUpperRange_10(Tuple<RamDomain,2>{{ramBitCast(env0[1]), ramBitCast<RamDomain>(MIN_RAM_SIGNED)}},Tuple<RamDomain,2>{{ramBitCast(env0[1]), ramBitCast<RamDomain>(MAX_RAM_SIGNED)}},READ_OP_CONTEXT(rel_3_delta_reachable_op_ctxt));@@ -451,8 +453,8 @@ ();} if(rel_4_new_reachable->empty()) break; [&](){-CREATE_OP_CONTEXT(rel_2_reachable_op_ctxt,rel_2_reachable->createContext()); CREATE_OP_CONTEXT(rel_4_new_reachable_op_ctxt,rel_4_new_reachable->createContext());+CREATE_OP_CONTEXT(rel_2_reachable_op_ctxt,rel_2_reachable->createContext()); for(const auto& env0 : *rel_4_new_reachable) { Tuple<RamDomain,2> tuple{{ramBitCast(env0[0]),ramBitCast(env0[1])}}; rel_2_reachable->insert(tuple,READ_OP_CONTEXT(rel_2_reachable_op_ctxt));
tests/fixtures/round_trip.cpp view
@@ -1,8 +1,10 @@  #include "souffle/CompiledSouffle.h" -extern "C" {+namespace functors {+ extern "C" { }+}  namespace souffle { static const RamDomain RAM_BIT_SHIFT_MASK = RAM_DOMAIN_SIZE - 1;@@ -117,7 +119,7 @@   return (ramBitCast<RamSigned>(a[0]) < ramBitCast<RamSigned>(b[0])) ? -1 : (ramBitCast<RamSigned>(a[0]) > ramBitCast<RamSigned>(b[0])) ? 1 :((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1])) ? -1 : (ramBitCast<RamSigned>(a[1]) > ramBitCast<RamSigned>(b[1])) ? 1 :((ramBitCast<RamSigned>(a[2]) < ramBitCast<RamSigned>(b[2])) ? -1 : (ramBitCast<RamSigned>(a[2]) > ramBitCast<RamSigned>(b[2])) ? 1 :((ramBitCast<RamSigned>(a[3]) < ramBitCast<RamSigned>(b[3])) ? -1 : (ramBitCast<RamSigned>(a[3]) > ramBitCast<RamSigned>(b[3])) ? 1 :(0))));  } bool less(const t_tuple& a, const t_tuple& b) const {-  return (ramBitCast<RamSigned>(a[0]) < ramBitCast<RamSigned>(b[0]))|| (ramBitCast<RamSigned>(a[0]) == ramBitCast<RamSigned>(b[0])) && ((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1]))|| (ramBitCast<RamSigned>(a[1]) == ramBitCast<RamSigned>(b[1])) && ((ramBitCast<RamSigned>(a[2]) < ramBitCast<RamSigned>(b[2]))|| (ramBitCast<RamSigned>(a[2]) == ramBitCast<RamSigned>(b[2])) && ((ramBitCast<RamSigned>(a[3]) < ramBitCast<RamSigned>(b[3])))));+  return (ramBitCast<RamSigned>(a[0]) < ramBitCast<RamSigned>(b[0]))|| ((ramBitCast<RamSigned>(a[0]) == ramBitCast<RamSigned>(b[0])) && ((ramBitCast<RamSigned>(a[1]) < ramBitCast<RamSigned>(b[1]))|| ((ramBitCast<RamSigned>(a[1]) == ramBitCast<RamSigned>(b[1])) && ((ramBitCast<RamSigned>(a[2]) < ramBitCast<RamSigned>(b[2]))|| ((ramBitCast<RamSigned>(a[2]) == ramBitCast<RamSigned>(b[2])) && ((ramBitCast<RamSigned>(a[3]) < ramBitCast<RamSigned>(b[3]))))))));  } bool equal(const t_tuple& a, const t_tuple& b) const { return (ramBitCast<RamSigned>(a[0]) == ramBitCast<RamSigned>(b[0]))&&(ramBitCast<RamSigned>(a[1]) == ramBitCast<RamSigned>(b[1]))&&(ramBitCast<RamSigned>(a[2]) == ramBitCast<RamSigned>(b[2]))&&(ramBitCast<RamSigned>(a[3]) == ramBitCast<RamSigned>(b[3]));@@ -430,7 +432,7 @@ } public: // -- initialize symbol table ---SymbolTable symTable;// -- initialize record table --+SymbolTableImpl symTable;// -- initialize record table -- SpecializedRecordTable<0> recordTable{}; // -- Table: float_fact Own<t_btree_f__0__1> rel_1_float_fact = mk<t_btree_f__0__1>();@@ -483,7 +485,7 @@     // set default threads (in embedded mode)     // if this is not set, and omp is used, the default omp setting of number of cores is used. #if defined(_OPENMP)-    if (0 < getNumThreads()) { omp_set_num_threads(getNumThreads()); }+    if (0 < getNumThreads()) { omp_set_num_threads(static_cast<int>(getNumThreads())); } #endif      signalHandler->set();@@ -519,10 +521,6 @@ } public: void printAll(std::string outputDirectoryArg = "") override {-try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","x"},{"auxArity","0"},{"name","float_fact"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"x\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"f:float\"]}}"}});-if (!outputDirectoryArg.empty()) {directiveMap["output-dir"] = outputDirectoryArg;}-IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_1_float_fact);-} catch (std::exception& e) {std::cerr << e.what();exit(1);} try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","a\tb\tc\td"},{"auxArity","0"},{"name","large_record"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 4, \"params\": [\"a\", \"b\", \"c\", \"d\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 4, \"types\": [\"i:number\", \"i:number\", \"i:number\", \"i:number\"]}}"}}); if (!outputDirectoryArg.empty()) {directiveMap["output-dir"] = outputDirectoryArg;} IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_2_large_record);@@ -539,6 +537,10 @@ if (!outputDirectoryArg.empty()) {directiveMap["output-dir"] = outputDirectoryArg;} IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_5_unsigned_fact); } catch (std::exception& e) {std::cerr << e.what();exit(1);}+try {std::map<std::string, std::string> directiveMap({{"IO","file"},{"attributeNames","x"},{"auxArity","0"},{"name","float_fact"},{"operation","output"},{"output-dir","."},{"params","{\"records\": {}, \"relation\": {\"arity\": 1, \"params\": [\"x\"]}}"},{"types","{\"ADTs\": {}, \"records\": {}, \"relation\": {\"arity\": 1, \"types\": [\"f:float\"]}}"}});+if (!outputDirectoryArg.empty()) {directiveMap["output-dir"] = outputDirectoryArg;}+IOSystem::getInstance().getWriter(directiveMap, symTable, recordTable)->writeAll(*rel_1_float_fact);+} catch (std::exception& e) {std::cerr << e.what();exit(1);} } public: void loadAll(std::string inputDirectoryArg = "") override {@@ -600,12 +602,6 @@ void dumpOutputs() override { try {std::map<std::string, std::string> rwOperation; rwOperation["IO"] = "stdout";-rwOperation["name"] = "float_fact";-rwOperation["types"] = "{\"relation\": {\"arity\": 1, \"auxArity\": 0, \"types\": [\"f:float\"]}}";-IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_1_float_fact);-} catch (std::exception& e) {std::cerr << e.what();exit(1);}-try {std::map<std::string, std::string> rwOperation;-rwOperation["IO"] = "stdout"; rwOperation["name"] = "large_record"; rwOperation["types"] = "{\"relation\": {\"arity\": 4, \"auxArity\": 0, \"types\": [\"i:number\", \"i:number\", \"i:number\", \"i:number\"]}}"; IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_2_large_record);@@ -627,6 +623,12 @@ rwOperation["name"] = "unsigned_fact"; rwOperation["types"] = "{\"relation\": {\"arity\": 1, \"auxArity\": 0, \"types\": [\"u:unsigned\"]}}"; IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_5_unsigned_fact);+} catch (std::exception& e) {std::cerr << e.what();exit(1);}+try {std::map<std::string, std::string> rwOperation;+rwOperation["IO"] = "stdout";+rwOperation["name"] = "float_fact";+rwOperation["types"] = "{\"relation\": {\"arity\": 1, \"auxArity\": 0, \"types\": [\"f:float\"]}}";+IOSystem::getInstance().getWriter(rwOperation, symTable, recordTable)->writeAll(*rel_1_float_fact); } catch (std::exception& e) {std::cerr << e.what();exit(1);} } public: