• 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/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(&parameters), ...);
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