• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkSLProgramVisitor_DEFINED
9 #define SkSLProgramVisitor_DEFINED
10 
11 #include <memory>
12 
13 namespace SkSL {
14 
15 struct Program;
16 class Expression;
17 class Statement;
18 class ProgramElement;
19 
20 /**
21  * Utility class to visit every element, statement, and expression in an SkSL program IR.
22  * This is intended for simple analysis and accumulation, where custom visitation behavior is only
23  * needed for a limited set of expression kinds.
24  *
25  * Subclasses should override visitExpression/visitStatement/visitProgramElement as needed and
26  * intercept elements of interest. They can then invoke the base class's function to visit all
27  * sub expressions. They can also choose not to call the base function to arrest recursion, or
28  * implement custom recursion.
29  *
30  * The visit functions return a bool that determines how the default implementation recurses. Once
31  * any visit call returns true, the default behavior stops recursing and propagates true up the
32  * stack.
33  */
34 template <typename T>
35 class TProgramVisitor {
36 public:
37     virtual ~TProgramVisitor() = default;
38 
39 protected:
40     virtual bool visitExpression(typename T::Expression& expression);
41     virtual bool visitStatement(typename T::Statement& statement);
42     virtual bool visitProgramElement(typename T::ProgramElement& programElement);
43 
44     virtual bool visitExpressionPtr(typename T::UniquePtrExpression& expr) = 0;
45     virtual bool visitStatementPtr(typename T::UniquePtrStatement& stmt) = 0;
46 };
47 
48 // ProgramVisitors take const types; ProgramWriters do not.
49 struct ProgramVisitorTypes {
50     using Program = const SkSL::Program;
51     using Expression = const SkSL::Expression;
52     using Statement = const SkSL::Statement;
53     using ProgramElement = const SkSL::ProgramElement;
54     using UniquePtrExpression = const std::unique_ptr<SkSL::Expression>;
55     using UniquePtrStatement = const std::unique_ptr<SkSL::Statement>;
56 };
57 
58 // Squelch bogus Clang warning about template vtables: https://bugs.llvm.org/show_bug.cgi?id=18733
59 #if defined(__clang__)
60 #pragma clang diagnostic push
61 #pragma clang diagnostic ignored "-Wweak-template-vtables"
62 #endif
63 extern template class TProgramVisitor<ProgramVisitorTypes>;
64 #if defined(__clang__)
65 #pragma clang diagnostic pop
66 #endif
67 
68 class ProgramVisitor : public TProgramVisitor<ProgramVisitorTypes> {
69 public:
70     bool visit(const Program& program);
71 
72 private:
73     // ProgramVisitors shouldn't need access to unique_ptrs, and marking these as final should help
74     // these accessors inline away. Use ProgramWriter if you need the unique_ptrs.
visitExpressionPtr(const std::unique_ptr<Expression> & e)75     bool visitExpressionPtr(const std::unique_ptr<Expression>& e) final {
76         return this->visitExpression(*e);
77     }
visitStatementPtr(const std::unique_ptr<Statement> & s)78     bool visitStatementPtr(const std::unique_ptr<Statement>& s) final {
79         return this->visitStatement(*s);
80     }
81 };
82 
83 } // namespace SkSL
84 
85 #endif
86