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 +6/−0
- cbits/souffle/CompiledSouffle.h +2/−0
- cbits/souffle/RecordTable.h +1/−574
- cbits/souffle/SignalHandler.h +12/−6
- cbits/souffle/SouffleInterface.h +12/−9
- cbits/souffle/SymbolTable.h +70/−63
- cbits/souffle/datastructure/BTree.h +6/−5
- cbits/souffle/datastructure/BTreeDelete.h +7/−4
- cbits/souffle/datastructure/Brie.h +6/−6
- cbits/souffle/datastructure/ConcurrentInsertOnlyHashMap.h +8/−5
- cbits/souffle/datastructure/EquivalenceRelation.h +4/−8
- cbits/souffle/datastructure/LambdaBTree.h +5/−5
- cbits/souffle/datastructure/PiggyList.h +12/−10
- cbits/souffle/datastructure/RecordTableImpl.h +599/−0
- cbits/souffle/datastructure/SymbolTableImpl.h +133/−0
- cbits/souffle/datastructure/Table.h +7/−1
- cbits/souffle/io/ReadStreamCSV.h +2/−2
- cbits/souffle/io/ReadStreamSQLite.h +5/−0
- cbits/souffle/io/WriteStreamSQLite.h +12/−5
- cbits/souffle/io/gzfstream.h +9/−8
- cbits/souffle/utility/ContainerUtil.h +14/−0
- cbits/souffle/utility/EvaluatorUtil.h +21/−3
- cbits/souffle/utility/FileUtil.h +97/−38
- cbits/souffle/utility/Iteration.h +25/−7
- cbits/souffle/utility/MiscUtil.h +21/−13
- cbits/souffle/utility/ParallelUtil.h +18/−0
- cbits/souffle/utility/tinyformat.h +8/−6
- souffle-haskell.cabal +27/−19
- tests/fixtures/edge_cases.cpp +44/−42
- tests/fixtures/path.cpp +15/−13
- tests/fixtures/round_trip.cpp +16/−14
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: