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