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 SKSL_DSL_FUNCTION 9 #define SKSL_DSL_FUNCTION 10 11 #include "include/sksl/DSLBlock.h" 12 #include "include/sksl/DSLExpression.h" 13 #include "include/sksl/DSLType.h" 14 #include "include/sksl/DSLVar.h" 15 #include "include/sksl/DSLWrapper.h" 16 17 namespace SkSL { 18 19 class Block; 20 class FunctionDeclaration; 21 class Variable; 22 23 namespace dsl { 24 25 class DSLType; 26 27 class DSLFunction { 28 public: 29 template<class... Parameters> DSLFunction(const DSLType & returnType,const char * name,Parameters &...parameters)30 DSLFunction(const DSLType& returnType, const char* name, Parameters&... parameters) { 31 SkTArray<DSLVar*> parameterArray; 32 parameterArray.reserve_back(sizeof...(parameters)); 33 34 // in C++17, we could just do: 35 // (parameterArray.push_back(¶meters), ...); 36 int unused[] = {0, (static_cast<void>(parameterArray.push_back(¶meters)), 0)...}; 37 static_cast<void>(unused); 38 this->init(returnType, name, std::move(parameterArray)); 39 } 40 DSLFunction(const DSLType & returnType,const char * name,SkTArray<DSLVar * > parameters)41 DSLFunction(const DSLType& returnType, const char* name, SkTArray<DSLVar*> parameters) { 42 this->init(returnType, name, std::move(parameters)); 43 } 44 45 virtual ~DSLFunction() = default; 46 47 template<class... Stmt> define(Stmt...stmts)48 void define(Stmt... stmts) { 49 DSLBlock block = DSLBlock(DSLStatement(std::move(stmts))...); 50 this->define(std::move(block)); 51 } 52 53 void define(DSLBlock block); 54 55 /** 56 * Invokes the function with the given arguments. 57 */ 58 template<class... Args> operator()59 DSLExpression operator()(Args&&... args) { 60 SkTArray<DSLWrapper<DSLExpression>> argArray; 61 argArray.reserve_back(sizeof...(args)); 62 this->collectArgs(argArray, std::forward<Args>(args)...); 63 return this->call(std::move(argArray)); 64 } 65 66 /** 67 * Invokes the function with the given arguments. 68 */ 69 DSLExpression call(SkTArray<DSLWrapper<DSLExpression>> args); 70 71 private: collectArgs(SkTArray<DSLWrapper<DSLExpression>> & args)72 void collectArgs(SkTArray<DSLWrapper<DSLExpression>>& args) {} 73 74 template<class... RemainingArgs> collectArgs(SkTArray<DSLWrapper<DSLExpression>> & args,DSLVar & var,RemainingArgs &&...remaining)75 void collectArgs(SkTArray<DSLWrapper<DSLExpression>>& args, DSLVar& var, 76 RemainingArgs&&... remaining) { 77 args.push_back(DSLWrapper<DSLExpression>(var)); 78 collectArgs(args, std::forward<RemainingArgs>(remaining)...); 79 } 80 81 template<class... RemainingArgs> collectArgs(SkTArray<DSLWrapper<DSLExpression>> & args,DSLExpression expr,RemainingArgs &&...remaining)82 void collectArgs(SkTArray<DSLWrapper<DSLExpression>>& args, DSLExpression expr, 83 RemainingArgs&&... remaining) { 84 args.push_back(DSLWrapper<DSLExpression>(std::move(expr))); 85 collectArgs(args, std::forward<RemainingArgs>(remaining)...); 86 } 87 88 void init(const DSLType& returnType, const char* name, SkTArray<DSLVar*> params); 89 90 const SkSL::FunctionDeclaration* fDecl = nullptr; 91 }; 92 93 } // namespace dsl 94 95 } // namespace SkSL 96 97 #endif 98