• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&parameters), ...);
36         int unused[] = {0, (static_cast<void>(parameterArray.push_back(&parameters)), 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