/* * 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/sksl/DSLBlock.h" #include "include/sksl/DSLExpression.h" #include "include/sksl/DSLType.h" #include "include/sksl/DSLVar.h" #include "include/sksl/DSLWrapper.h" namespace SkSL { class Block; class FunctionDeclaration; class Variable; namespace dsl { class DSLType; class DSLFunction { public: template DSLFunction(const DSLType& returnType, const char* name, Parameters&... parameters) { SkTArray parameterArray; parameterArray.reserve_back(sizeof...(parameters)); // in C++17, we could just do: // (parameterArray.push_back(¶meters), ...); int unused[] = {0, (static_cast(parameterArray.push_back(¶meters)), 0)...}; static_cast(unused); this->init(returnType, name, std::move(parameterArray)); } DSLFunction(const DSLType& returnType, const char* name, SkTArray parameters) { this->init(returnType, name, std::move(parameters)); } virtual ~DSLFunction() = default; template void define(Stmt... stmts) { DSLBlock block = DSLBlock(DSLStatement(std::move(stmts))...); this->define(std::move(block)); } void define(DSLBlock block); /** * Invokes the function with the given arguments. */ template DSLExpression operator()(Args&&... args) { SkTArray> argArray; argArray.reserve_back(sizeof...(args)); this->collectArgs(argArray, std::forward(args)...); return this->call(std::move(argArray)); } /** * Invokes the function with the given arguments. */ DSLExpression call(SkTArray> args); private: void collectArgs(SkTArray>& args) {} template void collectArgs(SkTArray>& args, DSLVar& var, RemainingArgs&&... remaining) { args.push_back(DSLWrapper(var)); collectArgs(args, std::forward(remaining)...); } template void collectArgs(SkTArray>& args, DSLExpression expr, RemainingArgs&&... remaining) { args.push_back(DSLWrapper(std::move(expr))); collectArgs(args, std::forward(remaining)...); } void init(const DSLType& returnType, const char* name, SkTArray params); const SkSL::FunctionDeclaration* fDecl = nullptr; }; } // namespace dsl } // namespace SkSL #endif