diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c4aa1a --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ + +# dot files +.vscode +.DS_Store + +# bazel +bazel-* + diff --git a/BUILD b/BUILD new file mode 100644 index 0000000..04e4d6e --- /dev/null +++ b/BUILD @@ -0,0 +1,44 @@ +# Bazel Build File For Type system + + +cc_library( + name="graph", + visibility = ["//visibility:public"], + hdrs=glob([ + "src/**/*.h*", + ]), + srcs=glob([ + "src/**/*.c*" + ]), + includes=[ + "src" + ], + copts = select({ + "@bazel_tools//src/conditions:windows": ["/std:c++17"], + "@bazel_tools//src/conditions:darwin": ["-std=c++17"], + "//conditions:default": ["-std=c++17"], + }), + deps=[ + "@stdext//:stdext", + "@spdlog//:headers", + ] +) + + + +cc_test( + name = "test", + srcs = glob([ + "test/**/*.h*", + "test/**/*.cpp" + ]), + copts = select({ + "@bazel_tools//src/conditions:windows": ["/std:c++17"], + "@bazel_tools//src/conditions:darwin": ["-std=c++17"], + "//conditions:default": ["-std=c++17"], + }), + deps = [ + ":graph", + "@catch//:single_include", + ], +) \ No newline at end of file diff --git a/WORKSPACE b/WORKSPACE new file mode 100644 index 0000000..e64bb0a --- /dev/null +++ b/WORKSPACE @@ -0,0 +1,36 @@ +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "catch", + url = "https://github.com/cgrinker/Catch2/archive/5e6488fd9949cb41d717a72c8c4603b7e37d68cd.zip", + sha256 = "91e3e0610572adefa301a6e55ac48ab0a3c8ff61787ce6930e346ff36e86905c", + strip_prefix = "Catch2-5e6488fd9949cb41d717a72c8c4603b7e37d68cd", +) + +######################## +# spdlog: + +http_archive( + name = "spdlog", + urls = ["https://github.com/cgrinker/spdlog/archive/3bf4a07dc286e10fa32d6503fded647c9ee02d26.zip"], + strip_prefix = "spdlog-3bf4a07dc286e10fa32d6503fded647c9ee02d26", + sha256 = "d00ccd202e2abae832441b9121330a4b8b82fdc60564edb315c89506fa3772c3", +) + +######################## +# stdext +http_archive( + name = "stdext", + urls = ["https://github.com/cultlang/stdext/archive/v1.0.0.zip"], + strip_prefix = "stdext-1.0.0", + sha256 = "2c008ad1de4e520c2b7ef24ea6d20e677afd1cf411274cb89da7aa08e853b3f1", +) + +######################## +# Fmt +http_archive( + name = "fmt", + urls = ["https://github.com/cgrinker/fmt/archive/f16f77297e6bb4df38d4c858edb3295f55716cb4.zip"], + strip_prefix = "fmt-f16f77297e6bb4df38d4c858edb3295f55716cb4", + sha256 = "edcacda20bf46be208fbc49cedee2a8a321005dd833752ccc6aa7a1a9d75dc23", +) diff --git a/src/graph/algo.hpp b/src/graph/algo.hpp new file mode 100644 index 0000000..3e3f199 --- /dev/null +++ b/src/graph/algo.hpp @@ -0,0 +1,79 @@ +#pragma once + +#include +#include + +#include "util.hpp" + +/* + * This file contains the various minor algorithms and is laid out as follows: + * + * - edgeIsIncoming + * - findNode + * - collectEdges + * - collectNodes + * - copyGraph (TODO) + */ + +namespace graph +{ + template + bool edgeIsIncoming(typename TGraph::Node const* n, typename TGraph::Edge const* e) + { + return (e->nodes[0] != n) != TGraph::isEdgeInverted(e); + } + template + bool edgeIsOutgoing(typename TGraph::Node const* n, typename TGraph::Edge const* e) + { + return (e->nodes[0] == n) != TGraph::isEdgeInverted(e); + } + + template + typename TGraph::Node const* findNode(TGraph const& g, typename TGraph::CoreData const& v) + { + typename TGraph::Node const* res = nullptr; + g.forAllNodes([&](auto n) + { + if (n->data == v) + res = n; + return n->data != v; + }); + return res; + } + + template + typename std::vector collectEdges(TGraph const& g, typename TGraph::Node const* n, Func const& func) + { + typename std::vector res; + g.forAllEdgesOnNode(n, [&](auto e) + { + if (func(e)) + res.push_back(e); + }); + return res; + } + + template + typename std::vector collectNodes(TGraph const& g, typename TGraph::Edge const* e, Func const& func) + { + typename std::vector res; + g.forAllNodesInEdge(e, [&](auto n) + { + if (func(n)) + res.push_back(n); + }); + return res; + } + + template + void copyGraph(TGraph& dst, TGraph const& src) + { + // TODO: need a copy data-section function to copy types and other data + //std::map _labelMap; + + src.forAllLabels([&](auto l) + { + dst.addLabel(l->data); + }); + } +} diff --git a/src/graph/graph.hpp b/src/graph/graph.hpp new file mode 100644 index 0000000..ac15849 --- /dev/null +++ b/src/graph/graph.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +/* + This header only graph library has some very specific design constraints: + + * Highly configurable, it should be usable in a lot of circumstances. + * C friendly potential. + * Supports node labels, properties, and sorted n-ary edges. + * Supports parent graphs, which it can override locally. + * This necessitates component style storage. + * Supports type based helper lookups. +*/ + +#include "util.hpp" + +#include "model/core.hpp" +#include "model/typed.hpp" +#include "model/todo.hpp" +#include "model/final.hpp" + +#include "algo.hpp" + +#include "query/engine.hpp" +#include "query/query.hpp" +#include "query/query_library_core.hpp" + +namespace graph +{ + template typename TGraphQueryLibrary = GraphQueryLibraryCore> + GraphQuery query(TGraph* g) + { + return GraphQuery(g); + } +} diff --git a/src/graph/model/core.hpp b/src/graph/model/core.hpp new file mode 100644 index 0000000..f18d431 --- /dev/null +++ b/src/graph/model/core.hpp @@ -0,0 +1,404 @@ +#pragma once + +#include +#include + +#include "../util.hpp" + +namespace graph +{ + struct void_t + { + }; + + template + struct basic_core_config : public TBase + { + using CoreData = TCoreData; + + using LabelData = void_t; + using NodeData = void_t; + using EdgeData = void_t; + using PropData = void_t; + + // support plf colony? + template + using Storage = std::deque; + }; + + // TODO, another graph type that is more effeciently organized + // maybe by not supporting parent overrides + template + class GraphCore + { + // This type types: + public: + // TODO move value kind out of this + // TODO a way for this to be used by wrapping templates + enum class MetaFlags : uint32_t + { + None = 0, + + Mask_Kind = (4 - 1) << 1, + Value_Kind_Label = ((uint8_t)GraphKind::Label - 1) << 1, + Value_Kind_Node = ((uint8_t)GraphKind::Node - 1) << 1, + Value_Kind_Edge = ((uint8_t)GraphKind::Edge - 1) << 1, + Value_Kind_Prop = ((uint8_t)GraphKind::Prop - 1) << 1, + + Flag_InverseEdge = 1 << 3, + //Flag_Override = 1 << 4, + }; + + // Graph types: + public: + using Config = TConfig; + + using CoreData = typename Config::CoreData; + + using LabelData = typename Config::LabelData; + using NodeData = typename Config::NodeData; + using EdgeData = typename Config::EdgeData; + using PropData = typename Config::PropData; + + template + using Storage = typename Config::template Storage; + + struct Core + { + public: + CoreData data; + MetaFlags flags; + }; + + struct Label; + struct Node; + struct Edge; + struct Prop; + + // A graph "label" metadata + struct Label + { + public: + LabelData label_data; + + std::vector nodes; + }; + + // A graph "node" metadata + struct Node + { + public: + NodeData node_data; + + std::vector labels; + std::vector edges; + std::vector props; + }; + + // A graph "edge" metadata + struct Edge + { + public: + EdgeData edge_data; + + std::vector nodes; + std::vector props; + }; + + // A graph "prop" metadata + struct Prop + { + public: + PropData prop_data; + + Core* owner; + }; + + // Actual type + public: + template + class Actual + { + public: + using MetaFlags = typename TFinal::MetaFlags; + using CoreData = typename TFinal::CoreData; + + using Label = typename TFinal::Label; + using Node = typename TFinal::Node; + using Edge = typename TFinal::Edge; + using Prop = typename TFinal::Prop; + + protected: + using LabelStorage = typename TFinal::template Storage