Basic interpreter implementation.
This commit is contained in:
parent
9030454132
commit
0eeb1fc5b4
@ -1,14 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include "antlr4-runtime.h"
|
||||
#include "database/graph_db_accessor.hpp"
|
||||
#include "query/frontend/ast/cypher_main_visitor.hpp"
|
||||
|
||||
class TypedcheckedTree {};
|
||||
|
||||
class LogicalPlan {};
|
||||
|
||||
class Context;
|
||||
|
||||
class LogicalPlanGenerator {
|
||||
public:
|
||||
std::vector<LogicalPlan> Generate(TypedcheckedTree&, Context&) {
|
||||
return {LogicalPlan()};
|
||||
}
|
||||
};
|
||||
|
||||
struct Config {
|
||||
LogicalPlanGenerator logical_plan_generator;
|
||||
};
|
||||
|
||||
class Context {
|
||||
public:
|
||||
int uid_counter;
|
||||
Context(Config config, GraphDbAccessor& db_accessor)
|
||||
: config(config), db_accessor(db_accessor) {}
|
||||
|
||||
Config config;
|
||||
GraphDbAccessor& db_accessor;
|
||||
};
|
||||
|
||||
class LogicalPlanner {
|
||||
public:
|
||||
LogicalPlanner(Context ctx) : ctx_(ctx) {}
|
||||
|
||||
LogicalPlan Apply(TypedcheckedTree typedchecked_tree) {
|
||||
return ctx_.config.logical_plan_generator.Generate(typedchecked_tree,
|
||||
ctx_)[0];
|
||||
}
|
||||
|
||||
private:
|
||||
Context ctx_;
|
||||
};
|
||||
|
||||
class HighLevelAstConversion {
|
||||
void Apply(const Context &ctx, antlr4::tree::ParseTree *tree) {
|
||||
public:
|
||||
void Apply(const Context& ctx, antlr4::tree::ParseTree* tree) {
|
||||
query::frontend::CypherMainVisitor visitor(ctx);
|
||||
visitor.visit(tree);
|
||||
}
|
||||
|
@ -2,21 +2,44 @@
|
||||
|
||||
#include "database/graph_db_accessor.hpp"
|
||||
#include "query/frontend/opencypher/parser.hpp"
|
||||
#include "query/context.hpp"
|
||||
|
||||
namespace query {
|
||||
|
||||
template <typename Stream>
|
||||
class Engine {
|
||||
public:
|
||||
Engine() {}
|
||||
Engine() {
|
||||
}
|
||||
auto Execute(const std::string &query, GraphDbAccessor &db_accessor,
|
||||
Stream &stream) {
|
||||
frontend::opencypher::Parser parser(query);
|
||||
Config config;
|
||||
Context ctx(config, db_accessor);
|
||||
::frontend::opencypher::Parser parser(query);
|
||||
auto low_level_tree = parser.tree();
|
||||
// high level tree
|
||||
// typechecked tree
|
||||
// logical tree
|
||||
auto high_level_tree = low2high_tree.Apply(ctx, low_level_tree);
|
||||
TypedcheckedTree typechecked_tree;
|
||||
auto logical_plan = LogicalPlanner(ctx).Apply(typechecked_tree);
|
||||
|
||||
// interpret & stream results
|
||||
// generate frame based on symbol table max_position
|
||||
Frame frame(size);
|
||||
auto cursor = logical_plan.MakeCursor(frame);
|
||||
logical_plan.WriteHeader(stream);
|
||||
auto symbols = logical_plan.OutputSymbols(symbol_table);
|
||||
while (cursor.pull(frame, context)) {
|
||||
std::vector<TypedValue> values(symbols.size());
|
||||
for (auto symbol : symbols) {
|
||||
values.emplace_back(frame[symbol]);
|
||||
}
|
||||
stream.Result(values);
|
||||
}
|
||||
stream.Summary({"type": "r"});
|
||||
|
||||
}
|
||||
private:
|
||||
Context ctx;
|
||||
HighLevelAstConversion low2high_tree;
|
||||
|
||||
};
|
||||
}
|
||||
|
@ -7,4 +7,7 @@ TypedValue Ident::Evaluate(Frame& frame, SymbolTable& symbol_table) {
|
||||
return frame[symbol_table[*this].position_];
|
||||
}
|
||||
|
||||
void NamedExpr::Evaluate(Frame& frame, SymbolTable& symbol_table) {
|
||||
frame[symbol_table[*ident_].position_] = expr_->Evaluate(frame, symbol_table);
|
||||
}
|
||||
}
|
||||
|
@ -50,24 +50,24 @@ class TreeVisitorBase {
|
||||
};
|
||||
|
||||
class Tree {
|
||||
public:
|
||||
public:
|
||||
Tree(const int uid) : uid_(uid) {}
|
||||
int uid() const { return uid_; }
|
||||
virtual void Accept(TreeVisitorBase& visitor) = 0;
|
||||
|
||||
private:
|
||||
private:
|
||||
const int uid_;
|
||||
};
|
||||
|
||||
class Expr : public Tree {
|
||||
public:
|
||||
virtual TypedValue Evaluate(Frame &, SymbolTable &) = 0;
|
||||
public:
|
||||
virtual TypedValue Evaluate(Frame&, SymbolTable&) = 0;
|
||||
};
|
||||
|
||||
class Ident : public Expr {
|
||||
public:
|
||||
public:
|
||||
std::string identifier_;
|
||||
TypedValue Evaluate(Frame &frame, SymbolTable &symbol_table) override;
|
||||
TypedValue Evaluate(Frame& frame, SymbolTable& symbol_table) override;
|
||||
void Accept(TreeVisitorBase& visitor) override {
|
||||
visitor.PreVisit(*this);
|
||||
visitor.Visit(*this);
|
||||
@ -77,8 +77,15 @@ public:
|
||||
|
||||
class Part : public Tree {};
|
||||
|
||||
class NamedExpr : public Tree {
|
||||
public:
|
||||
std::shared_ptr<Ident> ident_;
|
||||
std::shared_ptr<Expr> expr_;
|
||||
void Evaluate(Frame& frame, SymbolTable& symbol_table);
|
||||
};
|
||||
|
||||
class NodePart : public Part {
|
||||
public:
|
||||
public:
|
||||
Ident identifier_;
|
||||
// TODO: Mislav call GraphDb::label(label_name) to populate labels_!
|
||||
std::vector<GraphDb::Label> labels_;
|
||||
@ -92,7 +99,7 @@ public:
|
||||
};
|
||||
|
||||
class EdgePart : public Part {
|
||||
public:
|
||||
public:
|
||||
Ident identifier_;
|
||||
// TODO: finish this: properties, types...
|
||||
void Accept(TreeVisitorBase& visitor) override {
|
||||
@ -106,7 +113,7 @@ public:
|
||||
class Clause : public Tree {};
|
||||
|
||||
class Pattern : public Tree {
|
||||
public:
|
||||
public:
|
||||
std::vector<std::shared_ptr<NodePart>> node_parts_;
|
||||
void Accept(TreeVisitorBase& visitor) override {
|
||||
visitor.PreVisit(*this);
|
||||
@ -119,7 +126,7 @@ public:
|
||||
};
|
||||
|
||||
class Query : public Tree {
|
||||
public:
|
||||
public:
|
||||
std::vector<std::unique_ptr<Clause>> clauses_;
|
||||
void Accept(TreeVisitorBase& visitor) override {
|
||||
visitor.PreVisit(*this);
|
||||
@ -132,7 +139,7 @@ public:
|
||||
};
|
||||
|
||||
class Match : public Clause {
|
||||
public:
|
||||
public:
|
||||
std::vector<std::unique_ptr<Pattern>> patterns_;
|
||||
void Accept(TreeVisitorBase& visitor) override {
|
||||
visitor.PreVisit(*this);
|
||||
@ -145,7 +152,7 @@ public:
|
||||
};
|
||||
|
||||
class Return : public Clause {
|
||||
public:
|
||||
public:
|
||||
std::vector<std::shared_ptr<Expr>> exprs_;
|
||||
void Accept(TreeVisitorBase& visitor) override {
|
||||
visitor.PreVisit(*this);
|
||||
|
@ -9,6 +9,24 @@
|
||||
#include "query/frontend/typecheck/symbol_table.hpp"
|
||||
|
||||
namespace query {
|
||||
|
||||
class ConsoleResultStream : public Loggable {
|
||||
public:
|
||||
ConsoleResultStream() : Loggable("ConsoleResultStream") {}
|
||||
|
||||
void Header(const std::vector<std::string>&) { logger.info("header"); }
|
||||
|
||||
void Result(std::vector<TypedValue>& values) {
|
||||
for (auto value : values) {
|
||||
logger.info(" result");
|
||||
}
|
||||
}
|
||||
|
||||
void Summary(const std::map<std::string, TypedValue>&) {
|
||||
logger.info("summary");
|
||||
}
|
||||
};
|
||||
|
||||
class Cursor {
|
||||
public:
|
||||
virtual bool pull(Frame&, SymbolTable&) = 0;
|
||||
@ -19,6 +37,10 @@ class LogicalOperator {
|
||||
public:
|
||||
auto children() { return children_; };
|
||||
virtual std::unique_ptr<Cursor> MakeCursor(GraphDbAccessor db) = 0;
|
||||
virtual void WriteHeader(ConsoleResultStream&) {}
|
||||
virtual std::vector<Symbol> OutputSymbols(SymbolTable& symbol_table) {
|
||||
return {};
|
||||
}
|
||||
virtual ~LogicalOperator() {}
|
||||
|
||||
protected:
|
||||
@ -32,8 +54,10 @@ class ScanAll : public LogicalOperator {
|
||||
private:
|
||||
class ScanAllCursor : public Cursor {
|
||||
public:
|
||||
ScanAllCursor(ScanAll& parent, GraphDbAccessor db)
|
||||
: parent_(parent), db_(db), vertices_(db.vertices()),
|
||||
ScanAllCursor(ScanAll& self, GraphDbAccessor db)
|
||||
: self_(self),
|
||||
db_(db),
|
||||
vertices_(db.vertices()),
|
||||
vertices_it_(vertices_.begin()) {}
|
||||
|
||||
bool pull(Frame& frame, SymbolTable& symbol_table) override {
|
||||
@ -47,14 +71,14 @@ class ScanAll : public LogicalOperator {
|
||||
}
|
||||
|
||||
private:
|
||||
ScanAll& parent_;
|
||||
ScanAll& self_;
|
||||
GraphDbAccessor db_;
|
||||
decltype(db_.vertices()) vertices_;
|
||||
decltype(vertices_.begin()) vertices_it_;
|
||||
|
||||
bool evaluate(Frame& frame, SymbolTable& symbol_table,
|
||||
VertexAccessor& vertex) {
|
||||
auto node_part = parent_.node_part_;
|
||||
auto node_part = self_.node_part_;
|
||||
for (auto label : node_part->labels_) {
|
||||
if (!vertex.has_label(label)) return false;
|
||||
}
|
||||
@ -65,8 +89,7 @@ class ScanAll : public LogicalOperator {
|
||||
|
||||
public:
|
||||
std::unique_ptr<Cursor> MakeCursor(GraphDbAccessor db) override {
|
||||
Cursor* cursor = new ScanAllCursor(*this, db);
|
||||
return std::unique_ptr<Cursor>(cursor);
|
||||
return std::make_unique<Cursor>(ScanAllCursor(*this, db));
|
||||
}
|
||||
|
||||
private:
|
||||
@ -76,29 +99,56 @@ class ScanAll : public LogicalOperator {
|
||||
|
||||
class Produce : public LogicalOperator {
|
||||
public:
|
||||
Produce(std::shared_ptr<LogicalOperator> op, std::vector<std::shared_ptr<Expr>> exprs)
|
||||
: exprs_(exprs) {
|
||||
children_.emplace_back(op);
|
||||
Produce(std::shared_ptr<LogicalOperator> input,
|
||||
std::vector<std::shared_ptr<NamedExpr>> exprs)
|
||||
: input_(input), exprs_(exprs) {
|
||||
children_.emplace_back(input);
|
||||
}
|
||||
|
||||
void WriteHeader(ConsoleResultStream& stream) override {
|
||||
// TODO: write real result
|
||||
stream.Header({"n"});
|
||||
}
|
||||
|
||||
std::unique_ptr<Cursor> MakeCursor(GraphDbAccessor db) override {
|
||||
return std::make_unique<Cursor>(ProduceCursor(*this, db));
|
||||
}
|
||||
|
||||
std::vector<Symbol> OutputSymbols(SymbolTable& symbol_table) override {
|
||||
std::vector<Symbol> result(exprs_.size());
|
||||
for (auto named_expr : exprs_) {
|
||||
result.emplace_back(symbol_table[*named_expr->ident_]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
class ProduceCursor : public Cursor {
|
||||
public:
|
||||
ProduceCursor(Produce& parent) : parent_(parent) {}
|
||||
bool pull(Frame &frame, SymbolTable& symbol_table) override {
|
||||
for (auto expr : parent_.exprs_) {
|
||||
frame[symbol_table[*expr].position_] = expr->Evaluate(frame, symbol_table);
|
||||
ProduceCursor(Produce& self, GraphDbAccessor db)
|
||||
: self_(self), self_cursor_(self_.MakeCursor(db)) {}
|
||||
bool pull(Frame& frame, SymbolTable& symbol_table) override {
|
||||
if (self_cursor_->pull(frame, symbol_table)) {
|
||||
for (auto expr : self_.exprs_) {
|
||||
expr->Evaluate(frame, symbol_table);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
Produce& parent_;
|
||||
Produce& self_;
|
||||
std::unique_ptr<Cursor> self_cursor_;
|
||||
};
|
||||
|
||||
public:
|
||||
std::unique_ptr<Cursor> MakeCursor(GraphDbAccessor) override {
|
||||
return std::unique_ptr<Cursor>(new ProduceCursor(*this));
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<Expr>> exprs_;
|
||||
std::shared_ptr<LogicalOperator> input_;
|
||||
std::vector<std::shared_ptr<NamedExpr>> exprs_;
|
||||
};
|
||||
}
|
||||
|
@ -10,23 +10,6 @@ using std::cout;
|
||||
using std::cin;
|
||||
using std::endl;
|
||||
|
||||
class ConsoleResultStream : public Loggable {
|
||||
public:
|
||||
ConsoleResultStream() : Loggable("ConsoleResultStream") {}
|
||||
|
||||
void Header(const std::vector<std::string>&) { logger.info("header"); }
|
||||
|
||||
void Result(std::vector<TypedValue>& values) {
|
||||
for (auto value : values) {
|
||||
logger.info(" result");
|
||||
}
|
||||
}
|
||||
|
||||
void Summary(const std::map<std::string, TypedValue>&) {
|
||||
logger.info("summary");
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// init arguments
|
||||
REGISTER_ARGS(argc, argv);
|
||||
|
Loading…
Reference in New Issue
Block a user