From 1428ce0639f7ec715ce4707c2a3ef7ddbfb2fdbe Mon Sep 17 00:00:00 2001
From: Marko Budiselic <marko.budiselic@memgraph.io>
Date: Sat, 11 Mar 2017 13:47:11 +0100
Subject: [PATCH] Add basic interpreter skeleton.

---
 src/query/frontend/ast/ast.hpp                | 43 ++++++++++
 src/query/frontend/interpret/interpret.hpp    | 18 ++++
 src/query/frontend/logical/operator.hpp       | 82 +++++++++++++++++++
 src/query/frontend/typecheck/symbol_table.hpp | 34 ++++++++
 4 files changed, 177 insertions(+)
 create mode 100644 src/query/frontend/ast/ast.hpp
 create mode 100644 src/query/frontend/interpret/interpret.hpp
 create mode 100644 src/query/frontend/logical/operator.hpp
 create mode 100644 src/query/frontend/typecheck/symbol_table.hpp

diff --git a/src/query/frontend/ast/ast.hpp b/src/query/frontend/ast/ast.hpp
new file mode 100644
index 000000000..ef2f9dd30
--- /dev/null
+++ b/src/query/frontend/ast/ast.hpp
@@ -0,0 +1,43 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+
+#include "database/graph_db.hpp"
+
+namespace query {
+
+template <typename T>
+using sptr = std::shared_ptr<T>;
+
+template <typename T>
+using uptr = std::unique_ptr<T>;
+
+class Tree {
+public:
+    Tree(const int uid) : uid_(uid) {}
+    int uid() const { return uid_; }
+private:
+    const int uid_;
+};
+
+class Expr : public Tree {
+};
+
+class Ident : public Tree {
+public:
+    std::string identifier_;
+};
+
+class Part {
+};
+
+class NodePart : public Part {
+public:
+    Ident identifier_;
+    // TODO: Mislav call GraphDb::label(label_name) to populate labels_!
+    std::vector<GraphDb::Label> labels_;
+    // TODO: properties
+};
+
+}
diff --git a/src/query/frontend/interpret/interpret.hpp b/src/query/frontend/interpret/interpret.hpp
new file mode 100644
index 000000000..7a2240094
--- /dev/null
+++ b/src/query/frontend/interpret/interpret.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <vector>
+
+#include "query/backend/cpp/typed_value.hpp"
+
+class Frame {
+ public:
+  Frame(int size) : size_(size), elems_(size_) {}
+
+  auto& operator[](int pos) { return elems_[pos]; }
+  const auto& operator[](int pos) const { return elems_[pos]; }
+
+ private:
+  int size_;
+  std::vector<TypedValue> elems_;
+};
+
diff --git a/src/query/frontend/logical/operator.hpp b/src/query/frontend/logical/operator.hpp
new file mode 100644
index 000000000..96deb7132
--- /dev/null
+++ b/src/query/frontend/logical/operator.hpp
@@ -0,0 +1,82 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+
+#include "database/graph_db_accessor.hpp"
+#include "query/frontend/ast/ast.hpp"
+#include "query/frontend/interpret/interpret.hpp"
+#include "query/frontend/typecheck/symbol_table.hpp"
+
+namespace query {
+class Cursor {
+ public:
+  virtual bool pull(Frame&, SymbolTable&) = 0;
+  virtual ~Cursor() {}
+};
+
+class LogicalOperator {
+ public:
+  auto children() { return children_; };
+  virtual uptr<Cursor> MakeCursor(GraphDbAccessor db) = 0;
+  virtual ~LogicalOperator() {}
+
+ protected:
+  std::vector<std::shared_ptr<LogicalOperator>> children_;
+};
+
+class ScanAll : public LogicalOperator {
+ public:
+  ScanAll(sptr<NodePart> node_part) : node_part_(node_part) {}
+
+ private:
+  class ScanAllCursor : public Cursor {
+   public:
+    ScanAllCursor(ScanAll& parent, GraphDbAccessor db)
+        : parent_(parent), db_(db), vertices_(db.vertices()) {}
+    bool pull(Frame& frame, SymbolTable& symbol_table) override {
+      while (vertices_ != vertices_.end()) {
+        auto& vertex = *vertices_++;
+        if (evaluate(frame, symbol_table, vertex)) {
+          return true;
+        }
+      }
+      return false;
+    }
+
+   private:
+    ScanAll& parent_;
+    GraphDbAccessor db_;
+    decltype(db_.vertices()) vertices_;
+
+    bool evaluate(Frame& frame, SymbolTable& symbol_table,
+                  VertexAccessor& vertex) {
+      auto node_part = parent_.node_part_;
+      for (auto label : node_part->labels_) {
+        if (!vertex.has_label(label)) return false;
+      }
+      frame[symbol_table[parent_.node_part_->identifier_].position_] = vertex;
+      return true;
+    }
+  };
+
+ public:
+  uptr<Cursor> MakeCursor(GraphDbAccessor db) override {
+    return new ScanAllCursor(*this, db);
+  }
+
+  friend class ScanAll::ScanAllCursor;
+  sptr<NodePart> node_part_;
+};
+
+class Produce : public LogicalOperator {
+ public:
+  Produce(sptr<LogicalOperator> op, std::vector<sptr<Expr>> exprs)
+      : exprs_(exprs) {
+    children_.emplace_back(op);
+  }
+
+ private:
+  std::vector<sptr<Expr>> exprs_;
+};
+}
diff --git a/src/query/frontend/typecheck/symbol_table.hpp b/src/query/frontend/typecheck/symbol_table.hpp
new file mode 100644
index 000000000..f5305fc89
--- /dev/null
+++ b/src/query/frontend/typecheck/symbol_table.hpp
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <map>
+#include <string>
+
+#include "query/frontend/ast/ast.hpp"
+
+namespace query {
+struct Symbol {
+  Symbol(std::string& name, int position) : name_(name), position_(position) {}
+  std::string name_;
+  int position_;
+};
+
+class SymbolTable {
+ public:
+  Symbol CreateSymbol(std::string& name) {
+    int position = position_++;
+    return Symbol(name, position);
+  }
+
+  void AssignSymbol(const Tree& tree, Symbol symbol) {
+    table_[tree.uid()] = symbol;
+  }
+
+  auto& operator[](const Tree& tree) { return table_[tree.uid()]; }
+
+  int max_position() const { return position_; }
+
+ private:
+  int position_{0};
+  std::map<int, Symbol> table_;
+};
+}