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/core/SkSpan.h" 12 #include "include/private/SkSLDefines.h" 13 #include "include/private/base/SkTArray.h" 14 #include "include/sksl/DSLBlock.h" 15 #include "include/sksl/DSLExpression.h" 16 #include "include/sksl/DSLModifiers.h" 17 #include "include/sksl/DSLStatement.h" 18 #include "include/sksl/DSLVar.h" 19 #include "include/sksl/SkSLPosition.h" 20 21 #include <string_view> 22 #include <utility> 23 24 namespace SkSL { 25 26 class FunctionDeclaration; 27 28 namespace dsl { 29 30 class DSLType; 31 32 class DSLFunction { 33 public: 34 template<class... Parameters> DSLFunction(const DSLType & returnType,std::string_view name,Parameters &...parameters)35 DSLFunction(const DSLType& returnType, std::string_view name, Parameters&... parameters) 36 : DSLFunction(DSLModifiers(), returnType, name, parameters...) {} 37 38 template<class... Parameters> DSLFunction(const DSLModifiers & modifiers,const DSLType & returnType,std::string_view name,Parameters &...parameters)39 DSLFunction(const DSLModifiers& modifiers, const DSLType& returnType, std::string_view name, 40 Parameters&... parameters) { 41 SkTArray<DSLParameter*> parameterArray; 42 parameterArray.reserve_back(sizeof...(parameters)); 43 (parameterArray.push_back(¶meters), ...); 44 45 // We can't have a default parameter and a template parameter pack at the same time, so 46 // unfortunately we can't capture position from this overload. 47 this->init(modifiers, returnType, name, parameterArray, Position()); 48 } 49 50 DSLFunction(std::string_view name, const DSLModifiers& modifiers, const DSLType& returnType, 51 SkSpan<DSLParameter*> parameters, Position pos = {}) { 52 this->init(modifiers, returnType, name, parameters, pos); 53 } 54 DSLFunction(SkSL::FunctionDeclaration * decl)55 DSLFunction(SkSL::FunctionDeclaration* decl) 56 : fDecl(decl) {} 57 58 virtual ~DSLFunction() = default; 59 60 template<class... Stmt> define(Stmt...stmts)61 void define(Stmt... stmts) { 62 DSLBlock block = DSLBlock(DSLStatement(std::move(stmts))...); 63 this->define(std::move(block)); 64 } 65 66 void define(DSLBlock block, Position pos = {}); 67 68 void prototype(); 69 70 /** 71 * Invokes the function with the given arguments. 72 */ 73 template<class... Args> operator()74 DSLExpression operator()(Args&&... args) { 75 ExpressionArray argArray; 76 argArray.reserve_back(sizeof...(args)); 77 this->collectArgs(argArray, std::forward<Args>(args)...); 78 return this->call(std::move(argArray)); 79 } 80 81 /** 82 * Invokes the function with the given arguments. 83 */ 84 DSLExpression call(SkSpan<DSLExpression> args, Position pos = {}); 85 86 DSLExpression call(ExpressionArray args, Position pos = {}); 87 88 private: collectArgs(ExpressionArray & args)89 void collectArgs(ExpressionArray& args) {} 90 91 template<class... RemainingArgs> collectArgs(ExpressionArray & args,DSLVar & var,RemainingArgs &&...remaining)92 void collectArgs(ExpressionArray& args, DSLVar& var, RemainingArgs&&... remaining) { 93 args.push_back(DSLExpression(var).release()); 94 collectArgs(args, std::forward<RemainingArgs>(remaining)...); 95 } 96 97 template<class... RemainingArgs> collectArgs(ExpressionArray & args,DSLExpression expr,RemainingArgs &&...remaining)98 void collectArgs(ExpressionArray& args, DSLExpression expr, RemainingArgs&&... remaining) { 99 args.push_back(expr.release()); 100 collectArgs(args, std::forward<RemainingArgs>(remaining)...); 101 } 102 103 void init(DSLModifiers modifiers, const DSLType& returnType, std::string_view name, 104 SkSpan<DSLParameter*> params, Position pos); 105 106 SkSL::FunctionDeclaration* fDecl = nullptr; 107 SkSL::Position fPosition; 108 }; 109 110 } // namespace dsl 111 112 } // namespace SkSL 113 114 #endif 115