souffle  2.0.2-371-g6315b36
Visitor.h
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file Visitor.h
12  *
13  * Defines a visitor pattern for AST
14  *
15  ***********************************************************************/
16 
17 #pragma once
18 
19 #include "ast/Aggregator.h"
20 #include "ast/AlgebraicDataType.h"
21 #include "ast/Argument.h"
22 #include "ast/Atom.h"
23 #include "ast/Attribute.h"
24 #include "ast/BinaryConstraint.h"
25 #include "ast/BooleanConstraint.h"
26 #include "ast/BranchInit.h"
27 #include "ast/Clause.h"
28 #include "ast/Component.h"
29 #include "ast/ComponentInit.h"
30 #include "ast/ComponentType.h"
31 #include "ast/Constant.h"
32 #include "ast/Constraint.h"
33 #include "ast/Counter.h"
34 #include "ast/Functor.h"
35 #include "ast/IntrinsicFunctor.h"
36 #include "ast/Literal.h"
37 #include "ast/Negation.h"
38 #include "ast/NilConstant.h"
39 #include "ast/Node.h"
40 #include "ast/NumericConstant.h"
41 #include "ast/Pragma.h"
42 #include "ast/Program.h"
43 #include "ast/ProvenanceNegation.h"
44 #include "ast/RecordInit.h"
45 #include "ast/RecordType.h"
46 #include "ast/Relation.h"
47 #include "ast/StringConstant.h"
48 #include "ast/SubroutineArgument.h"
49 #include "ast/SubsetType.h"
50 #include "ast/Term.h"
51 #include "ast/Type.h"
52 #include "ast/TypeCast.h"
53 #include "ast/UnionType.h"
54 #include "ast/UnnamedVariable.h"
55 #include "ast/UserDefinedFunctor.h"
56 #include "ast/Variable.h"
59 #include <cstddef>
60 #include <functional>
61 #include <memory>
62 #include <type_traits>
63 #include <typeinfo>
64 #include <vector>
65 
66 namespace souffle::ast {
67 
68 /** A tag type required for the is_ast_visitor type trait to identify AstVisitors */
69 struct ast_visitor_tag {};
70 
71 /**
72  * The generic base type of all AstVisitors realizing the dispatching of
73  * visitor calls. Each visitor may define a return type R and a list of
74  * extra parameters to be passed along with the visited Nodes to the
75  * corresponding visitor function.
76  *
77  * @tparam R the result type produced by a visit call
78  * @tparam Params extra parameters to be passed to the visit call
79  */
80 template <typename R = void, typename... Params>
81 struct Visitor : public ast_visitor_tag {
82  /** A virtual destructor */
83  virtual ~Visitor() = default;
84 
85  /** The main entry for the user allowing visitors to be utilized as functions */
86  R operator()(const Node& node, Params... args) {
87  return visit(node, args...);
88  }
89 
90  /**
91  * The main entry for a visit process conducting the dispatching of
92  * a visit to the various sub-types of Nodes. Sub-classes may override
93  * this implementation to conduct pre-visit operations.
94  *
95  * @param node the node to be visited
96  * @param args a list of extra parameters to be forwarded
97  */
98  virtual R visit(const Node& node, Params... args) {
99  // dispatch node processing based on dynamic type
100 
101 #define FORWARD(Kind) \
102  if (const auto* n = dynamic_cast<const Kind*>(&node)) return visit##Kind(*n, args...);
103 
104  // types
109 
110  // arguments
124 
125  // literals
126  FORWARD(Atom)
131 
132  // components
136 
137  // rest
139  FORWARD(Clause);
140  FORWARD(Relation);
141  FORWARD(Program);
142  FORWARD(Pragma);
143 
144 #undef FORWARD
145 
146  // did not work ...
147 
148  fatal("unsupported type: %s", typeid(node).name());
149  }
150 
151 protected:
152 #define LINK(Node, Parent) \
153  virtual R visit##Node(const Node& n, Params... args) { \
154  return visit##Parent(n, args...); \
155  }
156 
157  // -- types --
158  LINK(SubsetType, Type);
159  LINK(RecordType, Type);
160  LINK(AlgebraicDataType, Type);
161  LINK(UnionType, Type);
162  LINK(Type, Node);
163 
164  // -- arguments --
165  LINK(Variable, Argument)
166  LINK(UnnamedVariable, Argument)
167  LINK(Counter, Argument)
168  LINK(TypeCast, Argument)
169  LINK(SubroutineArgument, Argument)
170  LINK(BranchInit, Argument)
171 
172  LINK(NumericConstant, Constant)
173  LINK(StringConstant, Constant)
174  LINK(NilConstant, Constant)
175  LINK(Constant, Argument)
176 
177  LINK(IntrinsicFunctor, Functor)
178  LINK(UserDefinedFunctor, Functor)
179 
180  LINK(RecordInit, Term)
181  LINK(Functor, Term)
182 
183  LINK(Term, Argument)
184 
185  LINK(Aggregator, Argument)
186 
187  LINK(Argument, Node);
188 
189  // literals
190  LINK(Atom, Literal)
191  LINK(ProvenanceNegation, Negation)
192  LINK(Negation, Literal)
193  LINK(Literal, Node);
194 
195  LINK(BooleanConstraint, Constraint)
196  LINK(BinaryConstraint, Constraint)
197  LINK(Constraint, Literal)
198 
199  // components
200  LINK(ComponentType, Node);
201  LINK(ComponentInit, Node);
202  LINK(Component, Node);
203 
204  // -- others --
205  LINK(Program, Node);
206  LINK(Attribute, Node);
207  LINK(Clause, Node);
208  LINK(Relation, Node);
209  LINK(Pragma, Node);
210 
211 #undef LINK
212 
213  /** The base case for all visitors -- if no more specific overload was defined */
214  virtual R visitNode(const Node& /*node*/, Params... /*args*/) {
215  return R();
216  }
217 };
218 
219 /**
220  * A utility function visiting all nodes within the ast rooted by the given node
221  * recursively in a depth-first pre-order fashion applying the given visitor to each
222  * encountered node.
223  *
224  * @param root the root of the AST to be visited
225  * @param visitor the visitor to be applied on each node
226  * @param args a list of extra parameters to be forwarded to the visitor
227  */
228 template <typename R, typename... Ps, typename... Args>
229 void visitDepthFirstPreOrder(const Node& root, Visitor<R, Ps...>& visitor, Args&... args) {
230  visitor(root, args...);
231  for (const Node* cur : root.getChildNodes()) {
232  if (cur != nullptr) {
233  visitDepthFirstPreOrder(*cur, visitor, args...);
234  }
235  }
236 }
237 
238 /**
239  * A utility function visiting all nodes within the ast rooted by the given node
240  * recursively in a depth-first post-order fashion applying the given visitor to each
241  * encountered node.
242  *
243  * @param root the root of the AST to be visited
244  * @param visitor the visitor to be applied on each node
245  * @param args a list of extra parameters to be forwarded to the visitor
246  */
247 template <typename R, typename... Ps, typename... Args>
248 void visitDepthFirstPostOrder(const Node& root, Visitor<R, Ps...>& visitor, Args&... args) {
249  for (const Node* cur : root.getChildNodes()) {
250  if (cur != nullptr) {
251  visitDepthFirstPostOrder(*cur, visitor, args...);
252  }
253  }
254  visitor(root, args...);
255 }
256 
257 /**
258  * A utility function visiting all nodes within the ast rooted by the given node
259  * recursively in a depth-first pre-order fashion applying the given visitor to each
260  * encountered node.
261  *
262  * @param root the root of the AST to be visited
263  * @param visitor the visitor to be applied on each node
264  * @param args a list of extra parameters to be forwarded to the visitor
265  */
266 template <typename R, typename... Ps, typename... Args>
267 void visitDepthFirst(const Node& root, Visitor<R, Ps...>& visitor, Args&... args) {
268  visitDepthFirstPreOrder(root, visitor, args...);
269 }
270 
271 namespace detail {
272 
273 /**
274  * A specialized visitor wrapping a lambda function -- an auxiliary type required
275  * for visitor convenience functions.
276  */
277 template <typename R, typename N>
278 struct LambdaVisitor : public Visitor<void> {
279  std::function<R(const N&)> lambda;
280  LambdaVisitor(std::function<R(const N&)> lambda) : lambda(std::move(lambda)) {}
281  void visit(const Node& node) override {
282  if (const auto* n = dynamic_cast<const N*>(&node)) {
283  lambda(*n);
284  }
285  }
286 };
287 
288 /**
289  * A factory function for creating LambdaVisitor instances.
290  */
291 template <typename R, typename N>
292 LambdaVisitor<R, N> makeLambdaVisitor(const std::function<R(const N&)>& fun) {
293  return LambdaVisitor<R, N>(fun);
294 }
295 
296 /**
297  * A type trait determining whether a given type is a visitor or not.
298  */
299 template <typename T>
300 struct is_ast_visitor {
301  static constexpr size_t value = std::is_base_of<ast_visitor_tag, T>::value;
302 };
303 
304 template <typename T>
305 struct is_ast_visitor<const T> : public is_ast_visitor<T> {};
306 
307 template <typename T>
308 struct is_ast_visitor<T&> : public is_ast_visitor<T> {};
309 } // namespace detail
310 
311 /**
312  * A utility function visiting all nodes within the ast rooted by the given node
313  * recursively in a depth-first pre-order fashion applying the given function to each
314  * encountered node.
315  *
316  * @param root the root of the AST to be visited
317  * @param fun the function to be applied
318  * @param args a list of extra parameters to be forwarded to the visitor
319  */
320 template <typename R, typename N>
321 void visitDepthFirst(const Node& root, const std::function<R(const N&)>& fun) {
322  auto visitor = detail::makeLambdaVisitor(fun);
323  visitDepthFirst<void>(root, visitor);
324 }
325 
326 /**
327  * A utility function visiting all nodes within the ast rooted by the given node
328  * recursively in a depth-first pre-order fashion applying the given function to each
329  * encountered node.
330  *
331  * @param root the root of the AST to be visited
332  * @param fun the function to be applied
333  * @param args a list of extra parameters to be forwarded to the visitor
334  */
335 template <typename Lambda, typename R = typename lambda_traits<Lambda>::result_type,
336  typename N = typename lambda_traits<Lambda>::arg0_type>
337 typename std::enable_if<!detail::is_ast_visitor<Lambda>::value, void>::type visitDepthFirst(
338  const Node& root, const Lambda& fun) {
339  visitDepthFirst(root, std::function<R(const N&)>(fun));
340 }
341 
342 /**
343  * A utility function visiting all nodes within a given list of AST root nodes
344  * recursively in a depth-first pre-order fashion applying the given function to each
345  * encountered node.
346  *
347  * @param list the list of roots of the ASTs to be visited
348  * @param fun the function to be applied
349  * @param args a list of extra parameters to be forwarded to the visitor
350  */
351 template <typename T, typename Lambda>
352 void visitDepthFirst(const std::vector<T*>& list, const Lambda& fun) {
353  for (const auto& cur : list) {
354  visitDepthFirst(*cur, fun);
355  }
356 }
357 
358 /**
359  * A utility function visiting all nodes within a given list of AST root nodes
360  * recursively in a depth-first pre-order fashion applying the given function to each
361  * encountered node.
362  *
363  * @param list the list of roots of the ASTs to be visited
364  * @param fun the function to be applied
365  * @param args a list of extra parameters to be forwarded to the visitor
366  */
367 template <typename T, typename Lambda>
368 void visitDepthFirst(const VecOwn<T>& list, const Lambda& fun) {
369  for (const auto& cur : list) {
370  visitDepthFirst(*cur, fun);
371  }
372 }
373 
374 /**
375  * A utility function visiting all nodes within the ast rooted by the given node
376  * recursively in a depth-first post-order fashion applying the given function to each
377  * encountered node.
378  *
379  * @param root the root of the AST to be visited
380  * @param fun the function to be applied
381  * @param args a list of extra parameters to be forwarded to the visitor
382  */
383 template <typename R, typename N>
384 void visitDepthFirstPostOrder(const Node& root, const std::function<R(const N&)>& fun) {
385  auto visitor = detail::makeLambdaVisitor(fun);
386  visitDepthFirstPostOrder<void>(root, visitor);
387 }
388 
389 /**
390  * A utility function visiting all nodes within the ast rooted by the given node
391  * recursively in a depth-first post-order fashion applying the given function to each
392  * encountered node.
393  *
394  * @param root the root of the AST to be visited
395  * @param fun the function to be applied
396  * @param args a list of extra parameters to be forwarded to the visitor
397  */
398 template <typename Lambda, typename R = typename lambda_traits<Lambda>::result_type,
399  typename N = typename lambda_traits<Lambda>::arg0_type>
400 typename std::enable_if<!detail::is_ast_visitor<Lambda>::value, void>::type visitDepthFirstPostOrder(
401  const Node& root, const Lambda& fun) {
402  visitDepthFirstPostOrder(root, std::function<R(const N&)>(fun));
403 }
404 
405 } // namespace souffle::ast
ProvenanceNegation.h
Functor.h
NilConstant.h
souffle::ast::Visitor
The generic base type of all AstVisitors realizing the dispatching of visitor calls.
Definition: Visitor.h:87
souffle::ast::BooleanConstraint
Boolean constraint class.
Definition: BooleanConstraint.h:45
souffle::ast::visitDepthFirstPostOrder
void visitDepthFirstPostOrder(const Node &root, Visitor< R, Ps... > &visitor, Args &... args)
A utility function visiting all nodes within the ast rooted by the given node recursively in a depth-...
Definition: Visitor.h:254
UnnamedVariable.h
souffle::ast::detail::LambdaVisitor::LambdaVisitor
LambdaVisitor(std::function< R(const N &)> lambda)
Definition: Visitor.h:286
Component.h
souffle::lambda_traits
A type trait enabling the deduction of type properties of lambdas.
Definition: FunctionalUtil.h:94
UnionType.h
souffle::ast::detail::makeLambdaVisitor
LambdaVisitor< R, N > makeLambdaVisitor(const std::function< R(const N &)> &fun)
A factory function for creating LambdaVisitor instances.
Definition: Visitor.h:298
MiscUtil.h
souffle::ast::Visitor::LINK
LINK(SubsetType, Type)
souffle::ast::detail::LambdaVisitor
A specialized visitor wrapping a lambda function – an auxiliary type required for visitor convenience...
Definition: Visitor.h:284
souffle::ast::ComponentInit
Component initialization class.
Definition: ComponentInit.h:47
souffle::ast::NilConstant
Defines the nil constant.
Definition: NilConstant.h:36
souffle::ast::Relation
Defines a relation with a name, attributes, qualifiers, and internal representation.
Definition: Relation.h:49
souffle::ast::Clause
Intermediate representation of a horn clause.
Definition: Clause.h:51
souffle::ast::analysis::SubsetType
A type being a subset of another type.
Definition: TypeSystem.h:108
Constraint.h
souffle::ast::analysis::UnionType
A union type combining a list of types into a new, aggregated type.
Definition: TypeSystem.h:146
souffle::ast::SubroutineArgument
Defines the argument class for subrountines.
Definition: SubroutineArgument.h:39
souffle::ast::Visitor::visitNode
virtual R visitNode(const Node &, Params...)
The base case for all visitors – if no more specific overload was defined.
Definition: Visitor.h:220
BooleanConstraint.h
ComponentInit.h
souffle::ast::UserDefinedFunctor
User-Defined functor class.
Definition: UserDefinedFunctor.h:46
souffle::ast::analysis::Variable
A variable to be utilized within constraints to be handled by the constraint solver.
Definition: ConstraintSystem.h:41
Relation.h
IntrinsicFunctor.h
souffle::ast::Atom
An atom class.
Definition: Atom.h:51
n
var n
Definition: htmlJsChartistMin.h:15
souffle::ram::Node::getChildNodes
virtual std::vector< const Node * > getChildNodes() const
Obtain list of all embedded child nodes.
Definition: Node.h:93
souffle::ast::Attribute
Attribute class.
Definition: Attribute.h:42
souffle::ast::Counter
counter functor (incrementing a value after each invocation)
Definition: Counter.h:34
souffle::ast::analysis::RecordType
A record type combining a list of fields into a new, aggregated type.
Definition: TypeSystem.h:170
Constant.h
UserDefinedFunctor.h
Attribute.h
souffle::ast::ComponentType
Component type of a component.
Definition: ComponentType.h:45
souffle::ast::ast_visitor_tag
A tag type required for the is_ast_visitor type trait to identify AstVisitors.
Definition: Visitor.h:75
StringConstant.h
Argument.h
souffle::ast::Program
The program class consists of relations, clauses and types.
Definition: Program.h:52
TypeCast.h
souffle::ram::Node
Node is a superclass for all RAM IR classes.
Definition: Node.h:42
souffle::ast::Pragma
Representation of a global option.
Definition: Pragma.h:37
souffle::ast::Visitor::visit
virtual R visit(const Node &node, Params... args)
The main entry for a visit process conducting the dispatching of a visit to the various sub-types of ...
Definition: Visitor.h:104
souffle::ast::ProvenanceNegation
Subclass of Literal that represents a negated atom, * e.g., !parent(x,y).
Definition: ProvenanceNegation.h:40
souffle::ast::detail::LambdaVisitor::lambda
std::function< R(const N &)> lambda
Definition: Visitor.h:285
Term.h
souffle::ast::Visitor::operator()
R operator()(const Node &node, Params... args)
The main entry for the user allowing visitors to be utilized as functions.
Definition: Visitor.h:92
souffle::ast::TypeCast
Defines a type cast class for expressions.
Definition: TypeCast.h:46
souffle::ast::Negation
Negation of an atom negated atom.
Definition: Negation.h:50
souffle::ast::IntrinsicFunctor
Intrinsic Functor class for functors are in-built.
Definition: IntrinsicFunctor.h:47
Atom.h
Literal.h
souffle::ast::visitDepthFirstPreOrder
void visitDepthFirstPreOrder(const Node &root, Visitor< R, Ps... > &visitor, Args &... args)
A utility function visiting all nodes within the ast rooted by the given node recursively in a depth-...
Definition: Visitor.h:235
Type.h
ComponentType.h
Negation.h
BranchInit.h
souffle::ast::Component
Component class.
Definition: Component.h:58
Node.h
Pragma.h
souffle::ast::BinaryConstraint
Binary constraint class.
Definition: BinaryConstraint.h:53
souffle::ast::detail::LambdaVisitor::visit
void visit(const Node &node) override
Definition: Visitor.h:287
Aggregator.h
SubroutineArgument.h
SubsetType.h
souffle::ast::Node
Abstract class for syntactic elements in an input program.
Definition: Node.h:40
souffle::ast::Aggregator
Defines the aggregator class.
Definition: Aggregator.h:53
Program.h
RecordType.h
souffle::fatal
void fatal(const char *format, const Args &... args)
Definition: MiscUtil.h:198
Clause.h
souffle::ast::detail::is_ast_visitor
A type trait determining whether a given type is a visitor or not.
Definition: Visitor.h:306
souffle::ast::BranchInit
Initialization of ADT instance.
Definition: BranchInit.h:49
souffle::ast::UnnamedVariable
Unnamed variable class.
Definition: UnnamedVariable.h:34
Counter.h
BinaryConstraint.h
souffle::ast::visitDepthFirst
void visitDepthFirst(const Node &root, Visitor< R, Ps... > &visitor, Args &... args)
A utility function visiting all nodes within the ast rooted by the given node recursively in a depth-...
Definition: Visitor.h:273
AlgebraicDataType.h
FunctionalUtil.h
souffle::ast
Definition: Aggregator.h:35
souffle::ast::NumericConstant
Numeric Constant.
Definition: NumericConstant.h:43
souffle::ast::detail::is_ast_visitor::value
static constexpr size_t value
Definition: Visitor.h:307
souffle::ast::StringConstant
String constant class.
Definition: StringConstant.h:37
souffle::VecOwn
std::vector< Own< A > > VecOwn
Definition: ContainerUtil.h:45
FORWARD
#define FORWARD(Kind)
souffle::ast::AlgebraicDataType
Combination of types using sums and products.
Definition: AlgebraicDataType.h:55
RecordInit.h
souffle::ast::RecordInit
Defines a record initialization class.
Definition: RecordInit.h:42
NumericConstant.h
std::type
ElementType type
Definition: span.h:640
Variable.h
souffle::ast::Visitor::~Visitor
virtual ~Visitor()=default
A virtual destructor.