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