Document and tweak the generic visitor

Summary:
Document and tweak the generic visitor
Use the generic visitor for AST visiting

Reviewers: buda, mislav.bradac, florijan

Reviewed By: buda

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D128
This commit is contained in:
Teon Banek 2017-03-15 16:07:46 +01:00
parent 6c7372b3c5
commit 74991c8289
6 changed files with 83 additions and 55 deletions

View File

@ -5,14 +5,14 @@
#include "database/graph_db.hpp"
#include "query/frontend/ast/ast_visitor.hpp"
#include "utils/visitor/visitable.hpp"
namespace query {
class Tree {
public:
class Tree : public ::utils::Visitable<TreeVisitorBase> {
public:
Tree(int uid) : uid_(uid) {}
int uid() const { return uid_; }
virtual void Accept(TreeVisitorBase &visitor) = 0;
private:
const int uid_;
@ -27,10 +27,7 @@ class Identifier : public Expression {
public:
Identifier(int uid, const std::string &name) : Expression(uid), name_(name) {}
void Accept(TreeVisitorBase &visitor) override {
visitor.Visit(*this);
visitor.PostVisit(*this);
}
DEFVISITABLE(TreeVisitorBase)
std::string name_;
};

View File

@ -1,5 +1,7 @@
#pragma once
#include "utils/visitor/visitor.hpp"
namespace query {
// Forward declares for TreeVisitorBase
@ -13,32 +15,8 @@ class Pattern;
class NodeAtom;
class EdgeAtom;
class TreeVisitorBase {
public:
virtual ~TreeVisitorBase() {}
// Start of the tree is a Query.
virtual void Visit(Query&) {}
virtual void PostVisit(Query&) {}
// Expressions
virtual void Visit(NamedExpression&) {}
virtual void PostVisit(NamedExpression&) {}
virtual void Visit(Identifier&) {}
virtual void PostVisit(Identifier&) {}
virtual void PreVisit(PropertyLookup&) {}
virtual void Visit(PropertyLookup&) {}
virtual void PostVisit(PropertyLookup&) {}
// Clauses
virtual void Visit(Match&) {}
virtual void PostVisit(Match&) {}
virtual void Visit(Return&) {}
virtual void PostVisit(Return&) {}
// Pattern and its subparts.
virtual void Visit(Pattern&) {}
virtual void PostVisit(Pattern&) {}
virtual void Visit(NodeAtom&) {}
virtual void PostVisit(NodeAtom&) {}
virtual void Visit(EdgeAtom&) {}
virtual void PostVisit(EdgeAtom&) {}
};
using TreeVisitorBase =
::utils::Visitor<Query, NamedExpression, Identifier, PropertyLookup, Match,
Return, Pattern, NodeAtom, EdgeAtom>;
}

View File

@ -40,6 +40,9 @@ class ExpressionEvaluator : public TreeVisitorBase {
return last;
}
using TreeVisitorBase::Visit;
using TreeVisitorBase::PostVisit;
void PostVisit(NamedExpression &named_expression) override {
auto symbol = symbol_table_[named_expression];
frame_[symbol.position_] = PopBack();

View File

@ -10,6 +10,9 @@ class SymbolGenerator : public TreeVisitorBase {
public:
SymbolGenerator(SymbolTable& symbol_table) : symbol_table_(symbol_table) {}
using TreeVisitorBase::Visit;
using TreeVisitorBase::PostVisit;
// Clauses
void PostVisit(Return& ret) override {
for (auto &named_expr : ret.named_expressions_) {

View File

@ -1,7 +1,32 @@
#pragma once
template <class T>
struct Visitable {
namespace utils {
// Inherit from this class to allow visiting from TVisitor class.
// Example usage:
// class Expression : public Visitable<ExpressionVisitor> {
// };
// class Identifier : public ExpressionVisitor {
// public:
// DEFVISITABLE(ExpressionVisitor) // Use default Accept implementation
// ....
// };
// class Literal : public Expression {
// public:
// void Accept(ExpressionVisitor &visitor) override {
// // Implement custom Accept.
// }
// };
template <class TVisitor>
class Visitable {
public:
virtual ~Visitable() = default;
virtual void accept(T& visitor) = 0;
virtual void Accept(TVisitor&) = 0;
#define DEFVISITABLE(TVisitor) \
void Accept(TVisitor &visitor) override \
{ visitor.Visit(*this); visitor.PostVisit(*this); }
};
}

View File

@ -1,37 +1,59 @@
#pragma once
namespace detail {
namespace {
template <typename T>
struct VisitorBase {
class VisitorBase {
public:
virtual ~VisitorBase() = default;
virtual void visit(T&) {}
virtual void post_visit(T&) {}
virtual void Visit(T&) {}
virtual void PostVisit(T&) {}
};
template <typename... T>
struct RecursiveVisitorBase;
class RecursiveVisitorBase;
template <typename Head, typename... Tail>
struct RecursiveVisitorBase<Head, Tail...> : VisitorBase<Head>,
RecursiveVisitorBase<Tail...> {
using VisitorBase<Head>::visit;
using VisitorBase<Head>::post_visit;
class RecursiveVisitorBase<Head, Tail...> : public VisitorBase<Head>,
public RecursiveVisitorBase<Tail...> {
public:
using VisitorBase<Head>::Visit;
using VisitorBase<Head>::PostVisit;
using RecursiveVisitorBase<Tail...>::visit;
using RecursiveVisitorBase<Tail...>::post_visit;
using RecursiveVisitorBase<Tail...>::Visit;
using RecursiveVisitorBase<Tail...>::PostVisit;
};
template <typename T>
struct RecursiveVisitorBase<T> : public VisitorBase<T> {
using VisitorBase<T>::visit;
using VisitorBase<T>::post_visit;
class RecursiveVisitorBase<T> : public VisitorBase<T> {
public:
using VisitorBase<T>::Visit;
using VisitorBase<T>::PostVisit;
};
}
template <typename... T>
struct Visitor : public detail::RecursiveVisitorBase<T...> {
using detail::RecursiveVisitorBase<T...>::visit;
using detail::RecursiveVisitorBase<T...>::post_visit;
namespace utils {
// Inherit from this class if you want to visit TVisitable types.
// Example usage:
// // Typedef for convenience or to establish a base class of visitors.
// typedef Visitor<Identifier, Literal> ExpressionVisitorBase;
// class ExpressionVisitor : public ExpressionVisitorBase {
// public:
// using ExpressionVisitorBase::Visit;
// using ExpressionVisitorBase::PostVisit;
//
// void Visit(Identifier &identifier) override {
// // Custom implementation of visiting Identifier.
// }
// };
template <typename... TVisitable>
class Visitor : public RecursiveVisitorBase<TVisitable...> {
public:
using RecursiveVisitorBase<TVisitable...>::Visit;
using RecursiveVisitorBase<TVisitable...>::PostVisit;
};
}