| /* |
| * Copyright 2021 Google LLC. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SKSL_DSL_FUNCTION |
| #define SKSL_DSL_FUNCTION |
| |
| #include "include/private/SkSLDefines.h" |
| #include "include/private/SkTArray.h" |
| #include "include/sksl/DSLBlock.h" |
| #include "include/sksl/DSLExpression.h" |
| #include "include/sksl/DSLModifiers.h" |
| #include "include/sksl/DSLStatement.h" |
| #include "include/sksl/DSLVar.h" |
| #include "include/sksl/SkSLPosition.h" |
| |
| #include <string_view> |
| #include <utility> |
| |
| namespace SkSL { |
| |
| class FunctionDeclaration; |
| |
| namespace dsl { |
| |
| class DSLType; |
| |
| class DSLFunction { |
| public: |
| template<class... Parameters> |
| DSLFunction(const DSLType& returnType, std::string_view name, Parameters&... parameters) |
| : DSLFunction(DSLModifiers(), returnType, name, parameters...) {} |
| |
| template<class... Parameters> |
| DSLFunction(const DSLModifiers& modifiers, const DSLType& returnType, std::string_view name, |
| Parameters&... parameters) { |
| SkTArray<DSLParameter*> parameterArray; |
| parameterArray.reserve_back(sizeof...(parameters)); |
| (parameterArray.push_back(¶meters), ...); |
| |
| // We can't have a default parameter and a template parameter pack at the same time, so |
| // unfortunately we can't capture position from this overload. |
| this->init(modifiers, returnType, name, std::move(parameterArray), Position()); |
| } |
| |
| DSLFunction(const DSLType& returnType, std::string_view name, |
| SkTArray<DSLParameter*> parameters, Position pos = {}) { |
| this->init(DSLModifiers(), returnType, name, std::move(parameters), pos); |
| } |
| |
| DSLFunction(const DSLModifiers& modifiers, const DSLType& returnType, std::string_view name, |
| SkTArray<DSLParameter*> parameters, Position pos = {}) { |
| this->init(modifiers, returnType, name, std::move(parameters), pos); |
| } |
| |
| DSLFunction(const SkSL::FunctionDeclaration* decl) |
| : fDecl(decl) {} |
| |
| virtual ~DSLFunction() = default; |
| |
| template<class... Stmt> |
| void define(Stmt... stmts) { |
| DSLBlock block = DSLBlock(DSLStatement(std::move(stmts))...); |
| this->define(std::move(block)); |
| } |
| |
| void define(DSLBlock block, Position pos = {}); |
| |
| /** |
| * Invokes the function with the given arguments. |
| */ |
| template<class... Args> |
| DSLExpression operator()(Args&&... args) { |
| ExpressionArray argArray; |
| argArray.reserve_back(sizeof...(args)); |
| this->collectArgs(argArray, std::forward<Args>(args)...); |
| return this->call(std::move(argArray)); |
| } |
| |
| /** |
| * Invokes the function with the given arguments. |
| */ |
| DSLExpression call(SkTArray<DSLExpression> args, Position pos = {}); |
| |
| DSLExpression call(ExpressionArray args, Position pos = {}); |
| |
| private: |
| void collectArgs(ExpressionArray& args) {} |
| |
| template<class... RemainingArgs> |
| void collectArgs(ExpressionArray& args, DSLVar& var, RemainingArgs&&... remaining) { |
| args.push_back(DSLExpression(var).release()); |
| collectArgs(args, std::forward<RemainingArgs>(remaining)...); |
| } |
| |
| template<class... RemainingArgs> |
| void collectArgs(ExpressionArray& args, DSLExpression expr, RemainingArgs&&... remaining) { |
| args.push_back(expr.release()); |
| collectArgs(args, std::forward<RemainingArgs>(remaining)...); |
| } |
| |
| void init(DSLModifiers modifiers, const DSLType& returnType, std::string_view name, |
| SkTArray<DSLParameter*> params, Position pos); |
| |
| const SkSL::FunctionDeclaration* fDecl = nullptr; |
| SkSL::Position fPosition; |
| }; |
| |
| } // namespace dsl |
| |
| } // namespace SkSL |
| |
| #endif |