diff --git a/docs/dev/lcp.md b/docs/dev/lcp.md index 727ac5814..35829dfc2 100644 --- a/docs/dev/lcp.md +++ b/docs/dev/lcp.md @@ -481,8 +481,24 @@ Proto, we simply enumerate all derived types inside the union of a base type. Multiple inheritance is a different beast and as such is not directly supported. -Most form of inheritance should actually be a simple composition, and we can -treat parent classes as being composed inside our derived type. +One way to use multiple inheritance is only to implement the interface of pure +virtual classes without any members (i.e. interface classes). In such a case, +you do not want to serialize any other base class except the primary one. To +let LCP know that is the case, use `:ignore-other-base-classes t`. LCP will +only try to serialize the base class that is the first (leftmost) in the list +of super classes. + +```lisp +(lcp:define-class derived (primary-base some-interface other-interface) + ... + (:serialize :capnp :ignore-other-base-classes t)) +``` + +Another form of multiple inheritance is reusing some common code. In +actuality, this is a very bad code practice and should be replaced with +composition. If it would take too long to fix such code to use composition +proper, we can tell LCP to treat such inheritance as if they are indeed +composed. This is done via `:inherit-compose` option. For example: diff --git a/src/lisp/lcp.lisp b/src/lisp/lcp.lisp index d32498450..4d143fa67 100644 --- a/src/lisp/lcp.lisp +++ b/src/lisp/lcp.lisp @@ -339,7 +339,9 @@ CPP-TYPE has no namespace, return an empty string." (type-args nil :read-only t) ;; In case of multiple inheritance, list of classes which should be handled ;; as a composition. - (inherit-compose nil :read-only t)) + (inherit-compose nil :read-only t) + ;; In case of multiple inheritance, pretend we only inherit the 1st base class. + (ignore-other-base-classes nil :type boolean :read-only t)) (defclass cpp-class (cpp-type) ((structp :type boolean :initarg :structp :initform nil @@ -658,8 +660,16 @@ Cap'n Proto schema." (declare (type (or symbol cpp-class) cpp-class)) (let ((class-name (if (symbolp cpp-class) cpp-class (cpp-type-base-name cpp-class)))) (remove-if (lambda (subclass) - (member class-name - (capnp-opts-inherit-compose (cpp-class-capnp-opts subclass)))) + (let ((capnp-opts (cpp-class-capnp-opts subclass))) + (or + ;; Remove if we are a parent that should be ignored (not + ;; the 1st in the list). + (and (capnp-opts-ignore-other-base-classes capnp-opts) + (not (eq class-name (car (cpp-class-super-classes subclass))))) + ;; Remove if we are a parent that should be treated as + ;; composition. + (member class-name + (capnp-opts-inherit-compose (cpp-class-capnp-opts subclass)))))) (direct-subclasses-of cpp-class)))) (defun capnp-union-and-compose-parents (cpp-class) @@ -668,17 +678,23 @@ secondary value contains parents which are modeled as being composed inside CPP-CLASS." (declare (type (or symbol cpp-class) cpp-class)) (let* ((class (if (symbolp cpp-class) (find-cpp-class cpp-class) cpp-class)) - (capnp-opts (cpp-class-capnp-opts class)) - union compose) + (capnp-opts (cpp-class-capnp-opts class))) (when (not capnp-opts) (error "Class ~A should be marked for capnp serialization, or its derived classes set as :CAPNP :BASE T" (cpp-type-base-name class))) (when (not (capnp-opts-base capnp-opts)) - (dolist (parent (cpp-class-super-classes class)) - (if (member parent (capnp-opts-inherit-compose capnp-opts)) - (push parent compose) - (push parent union)))) - (values union compose))) + (if (capnp-opts-ignore-other-base-classes capnp-opts) + ;; Since we are ignoring multiple inheritance, return the 1st class + ;; (as union parent). + (list (car (cpp-class-super-classes class))) + ;; We aren't ignoring multiple inheritance, collect union and + ;; compose parents. + (let (union compose) + (dolist (parent (cpp-class-super-classes class)) + (if (member parent (capnp-opts-inherit-compose capnp-opts)) + (push parent compose) + (push parent union))) + (values union compose)))))) (defun capnp-union-parents-rec (cpp-class) "Return a list of all parent clases recursively for CPP-CLASS that should be diff --git a/src/query/frontend/ast/ast.lcp b/src/query/frontend/ast/ast.lcp index 8995406ad..e5d8e2a6b 100644 --- a/src/query/frontend/ast/ast.lcp +++ b/src/query/frontend/ast/ast.lcp @@ -150,8 +150,7 @@ class AstStorage { }; cpp<# -(lcp:define-class tree ("::utils::Visitable<HierarchicalTreeVisitor>" - "::utils::Visitable<TreeVisitor<TypedValue>>") +(lcp:define-class tree ("::utils::Visitable<HierarchicalTreeVisitor>") ((uid :int32_t :scope :public)) (:abstractp t) (:public @@ -159,7 +158,6 @@ cpp<# Tree() = default; using ::utils::Visitable<HierarchicalTreeVisitor>::Accept; - using ::utils::Visitable<TreeVisitor<TypedValue>>::Accept; virtual Tree *Clone(AstStorage &storage) const = 0; cpp<#) @@ -187,11 +185,18 @@ cpp<# saved_uids->push_back(self.uid_); cpp<#))) -(lcp:define-class expression (tree) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Expressions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(lcp:define-class expression (tree "::utils::Visitable<ExpressionVisitor<TypedValue>>") () (:abstractp t) (:public #>cpp + using ::utils::Visitable<ExpressionVisitor<TypedValue>>::Accept; + using Tree::Accept; + Expression() = default; Expression *Clone(AstStorage &storage) const override = 0; @@ -204,7 +209,7 @@ cpp<# #>cpp friend class AstStorage; cpp<#) - (:serialize :capnp)) + (:serialize :capnp :ignore-other-base-classes t)) (lcp:define-class where (tree) ((expression "Expression *" :initval "nullptr" :scope :public @@ -215,7 +220,6 @@ cpp<# #>cpp Where() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { expression_->Accept(visitor); @@ -304,7 +308,7 @@ cpp<# (:public (let ((cpp-name (lcp::cpp-type-name ',op))) #>cpp - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { expression1_->Accept(visitor) && expression2_->Accept(visitor); @@ -335,7 +339,7 @@ cpp<# (:public (let ((cpp-name (lcp::cpp-type-name ',op))) #>cpp - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { expression_->Accept(visitor); @@ -377,7 +381,7 @@ cpp<# return op_strings[static_cast<int>(op)]; } - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { if (expression1_) expression1_->Accept(visitor); @@ -432,7 +436,7 @@ cpp<# #>cpp ListSlicingOperator() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { bool cont = list_->Accept(visitor); @@ -486,7 +490,7 @@ cpp<# #>cpp IfOperator() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { condition_->Accept(visitor) && then_expression_->Accept(visitor) && @@ -551,7 +555,7 @@ cpp<# #>cpp PrimitiveLiteral() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); DEFVISITABLE(HierarchicalTreeVisitor); PrimitiveLiteral *Clone(AstStorage &storage) const override { @@ -583,7 +587,7 @@ cpp<# #>cpp ListLiteral() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { for (auto expr_ptr : elements_) @@ -622,7 +626,7 @@ cpp<# #>cpp MapLiteral() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { for (auto pair : elements_) @@ -659,7 +663,7 @@ cpp<# #>cpp Identifier() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); DEFVISITABLE(HierarchicalTreeVisitor); Identifier *Clone(AstStorage &storage) const override { @@ -689,7 +693,7 @@ cpp<# #>cpp PropertyLookup() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { expression_->Accept(visitor); @@ -739,7 +743,7 @@ cpp<# #>cpp LabelsTest() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { expression_->Accept(visitor); @@ -781,7 +785,7 @@ cpp<# #>cpp Function() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { for (auto *argument : arguments_) { @@ -848,7 +852,7 @@ cpp<# #>cpp Reduce() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { accumulator_->Accept(visitor) && initializer_->Accept(visitor) && @@ -893,7 +897,7 @@ cpp<# #>cpp Coalesce() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { for (auto *expr : expressions_) { @@ -942,7 +946,7 @@ cpp<# #>cpp Extract() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { identifier_->Accept(visitor) && list_->Accept(visitor) && @@ -989,7 +993,7 @@ cpp<# #>cpp All() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { identifier_->Accept(visitor) && list_expression_->Accept(visitor) && @@ -1019,9 +1023,9 @@ cpp<# cpp<#) (:serialize :capnp)) -;;;; TODO: This is pretty much copy pasted from All. Consider merging Reduce, -;;;; All, Any and Single into something like a higher-order function call which -;;;; takes a list argument and a function which is applied on list elements. +;; TODO: This is pretty much copy pasted from All. Consider merging Reduce, +;; All, Any and Single into something like a higher-order function call which +;; takes a list argument and a function which is applied on list elements. (lcp:define-class single (expression) ((identifier "Identifier *" :initval "nullptr" :scope :public :capnp-type "Tree" :capnp-init nil @@ -1039,7 +1043,7 @@ cpp<# #>cpp Single() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { identifier_->Accept(visitor) && list_expression_->Accept(visitor) && @@ -1076,7 +1080,7 @@ cpp<# #>cpp ParameterLookup() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); DEFVISITABLE(HierarchicalTreeVisitor); ParameterLookup *Clone(AstStorage &storage) const override { @@ -1095,7 +1099,7 @@ cpp<# cpp<#) (:serialize :capnp)) -(lcp:define-class named-expression (tree) +(lcp:define-class named-expression (tree "::utils::Visitable<ExpressionVisitor<TypedValue>>") ((name "std::string" :scope :public) (expression "Expression *" :initval "nullptr" :scope :public :capnp-type "Tree" :capnp-init nil @@ -1105,9 +1109,11 @@ cpp<# :documentation "This field contains token position of first token in named expression used to create name_. If NamedExpression object is not created from query or it is aliased leave this value at -1.")) (:public #>cpp + using ::utils::Visitable<ExpressionVisitor<TypedValue>>::Accept; + NamedExpression() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); + DEFVISITABLE(ExpressionVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { expression_->Accept(visitor); @@ -1137,7 +1143,11 @@ cpp<# #>cpp friend class AstStorage; cpp<#) - (:serialize :capnp)) + (:serialize :capnp :ignore-other-base-classes t)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; END Expressions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (lcp:define-class pattern-atom (tree) ((identifier "Identifier *" :initval "nullptr" :scope :public @@ -1178,7 +1188,6 @@ cpp<# :scope :public)) (:public #>cpp - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { bool cont = identifier_->Accept(visitor); @@ -1273,7 +1282,6 @@ cpp<# :load-args '((storage "AstStorage *") (loaded-uids "std::vector<int32_t> *")))) #>cpp - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { bool cont = identifier_->Accept(visitor); @@ -1366,7 +1374,6 @@ cpp<# #>cpp Pattern() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { bool cont = identifier_->Accept(visitor); @@ -1427,7 +1434,6 @@ cpp<# #>cpp SingleQuery() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { for (auto &clause : clauses_) { @@ -1467,7 +1473,6 @@ cpp<# #>cpp CypherUnion() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { single_query_->Accept(visitor); @@ -1534,7 +1539,6 @@ cpp<# #>cpp CypherQuery() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { bool should_continue = single_query_->Accept(visitor); @@ -1576,7 +1580,6 @@ cpp<# #>cpp ExplainQuery() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { cypher_query_->Accept(visitor); @@ -1614,7 +1617,6 @@ cpp<# #>cpp IndexQuery() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); DEFVISITABLE(HierarchicalTreeVisitor); IndexQuery *Clone(AstStorage &storage) const override { @@ -1644,7 +1646,6 @@ cpp<# #>cpp Create() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { for (auto &pattern : patterns_) { @@ -1689,7 +1690,6 @@ cpp<# #>cpp Match() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { bool cont = true; @@ -1799,7 +1799,6 @@ cpp<# #>cpp Return() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { bool cont = true; @@ -1850,7 +1849,6 @@ cpp<# #>cpp With() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { bool cont = true; @@ -1905,7 +1903,6 @@ cpp<# #>cpp Delete() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { for (auto &expr : expressions_) { @@ -1949,7 +1946,6 @@ cpp<# #>cpp SetProperty() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { property_lookup_->Accept(visitor) && expression_->Accept(visitor); @@ -1990,7 +1986,6 @@ cpp<# #>cpp SetProperties() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { identifier_->Accept(visitor) && expression_->Accept(visitor); @@ -2035,7 +2030,6 @@ cpp<# #>cpp SetLabels() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { identifier_->Accept(visitor); @@ -2069,7 +2063,6 @@ cpp<# #>cpp RemoveProperty() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { property_lookup_->Accept(visitor); @@ -2109,7 +2102,6 @@ cpp<# #>cpp RemoveLabels() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { identifier_->Accept(visitor); @@ -2153,7 +2145,6 @@ cpp<# #>cpp Merge() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { bool cont = pattern_->Accept(visitor); @@ -2214,7 +2205,6 @@ cpp<# #>cpp Unwind() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { named_expression_->Accept(visitor); @@ -2266,7 +2256,6 @@ cpp<# #>cpp AuthQuery() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { if (password_) password_->Accept(visitor); @@ -2346,7 +2335,6 @@ cpp<# #>cpp StreamQuery() = default; - DEFVISITABLE(TreeVisitor<TypedValue>); bool Accept(HierarchicalTreeVisitor &visitor) override { if (visitor.PreVisit(*this)) { bool cont = true; diff --git a/src/query/frontend/ast/ast_visitor.hpp b/src/query/frontend/ast/ast_visitor.hpp index 860b37944..d8bc80781 100644 --- a/src/query/frontend/ast/ast_visitor.hpp +++ b/src/query/frontend/ast/ast_visitor.hpp @@ -92,19 +92,18 @@ class HierarchicalTreeVisitor : public TreeCompositeVisitor, using typename TreeLeafVisitor::ReturnType; }; -template <typename TResult> -using TreeVisitor = ::utils::Visitor< - TResult, CypherQuery, ExplainQuery, SingleQuery, CypherUnion, - NamedExpression, OrOperator, XorOperator, AndOperator, NotOperator, - AdditionOperator, SubtractionOperator, MultiplicationOperator, - DivisionOperator, ModOperator, NotEqualOperator, EqualOperator, - LessOperator, GreaterOperator, LessEqualOperator, GreaterEqualOperator, - InListOperator, SubscriptOperator, ListSlicingOperator, IfOperator, - UnaryPlusOperator, UnaryMinusOperator, IsNullOperator, ListLiteral, - MapLiteral, PropertyLookup, LabelsTest, Aggregation, Function, Reduce, - Coalesce, Extract, All, Single, ParameterLookup, Create, Match, Return, - With, Pattern, NodeAtom, EdgeAtom, Delete, Where, SetProperty, - SetProperties, SetLabels, RemoveProperty, RemoveLabels, Merge, Unwind, - Identifier, PrimitiveLiteral, IndexQuery, AuthQuery, StreamQuery>; +template <class TResult> +class ExpressionVisitor + : public ::utils::Visitor< + TResult, NamedExpression, OrOperator, XorOperator, AndOperator, + NotOperator, AdditionOperator, SubtractionOperator, + MultiplicationOperator, DivisionOperator, ModOperator, + NotEqualOperator, EqualOperator, LessOperator, GreaterOperator, + LessEqualOperator, GreaterEqualOperator, InListOperator, + SubscriptOperator, ListSlicingOperator, IfOperator, UnaryPlusOperator, + UnaryMinusOperator, IsNullOperator, ListLiteral, MapLiteral, + PropertyLookup, LabelsTest, Aggregation, Function, Reduce, Coalesce, + Extract, All, Single, ParameterLookup, Identifier, PrimitiveLiteral> { +}; } // namespace query diff --git a/src/query/interpret/eval.hpp b/src/query/interpret/eval.hpp index bb1091db9..295b2a784 100644 --- a/src/query/interpret/eval.hpp +++ b/src/query/interpret/eval.hpp @@ -18,7 +18,7 @@ namespace query { -class ExpressionEvaluator : public TreeVisitor<TypedValue> { +class ExpressionEvaluator : public ExpressionVisitor<TypedValue> { public: ExpressionEvaluator(Frame *frame, const SymbolTable &symbol_table, const EvaluationContext &ctx, @@ -29,39 +29,7 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> { dba_(dba), graph_view_(graph_view) {} - using TreeVisitor<TypedValue>::Visit; - -#define BLOCK_VISIT(TREE_TYPE) \ - TypedValue Visit(TREE_TYPE &) override { \ - LOG(FATAL) << "ExpressionEvaluator should not visit " #TREE_TYPE; \ - } - - BLOCK_VISIT(CypherQuery); - BLOCK_VISIT(ExplainQuery); - BLOCK_VISIT(CypherUnion); - BLOCK_VISIT(SingleQuery); - BLOCK_VISIT(Create); - BLOCK_VISIT(Match); - BLOCK_VISIT(Return); - BLOCK_VISIT(With); - BLOCK_VISIT(Pattern); - BLOCK_VISIT(NodeAtom); - BLOCK_VISIT(EdgeAtom); - BLOCK_VISIT(Delete); - BLOCK_VISIT(Where); - BLOCK_VISIT(SetProperty); - BLOCK_VISIT(SetProperties); - BLOCK_VISIT(SetLabels); - BLOCK_VISIT(RemoveProperty); - BLOCK_VISIT(RemoveLabels); - BLOCK_VISIT(Merge); - BLOCK_VISIT(Unwind); - BLOCK_VISIT(IndexQuery); - BLOCK_VISIT(AuthQuery); - BLOCK_VISIT(StreamQuery); - - -#undef BLOCK_VISIT + using ExpressionVisitor<TypedValue>::Visit; TypedValue Visit(NamedExpression &named_expression) override { const auto &symbol = symbol_table_->at(named_expression);