• 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,skstd::string_view name,Parameters &...parameters)30     DSLFunction(const DSLType& returnType, skstd::string_view name, Parameters&... parameters)
31         : DSLFunction(DSLModifiers(), returnType, name, parameters...) {}
32 
33     template<class... Parameters>
DSLFunction(const DSLModifiers & modifiers,const DSLType & returnType,skstd::string_view name,Parameters &...parameters)34     DSLFunction(const DSLModifiers& modifiers, const DSLType& returnType, skstd::string_view name,
35                 Parameters&... parameters) {
36         SkTArray<DSLParameter*> parameterArray;
37         parameterArray.reserve_back(sizeof...(parameters));
38 
39         // in C++17, we could just do:
40         // (parameterArray.push_back(&parameters), ...);
41         int unused[] = {0, (static_cast<void>(parameterArray.push_back(&parameters)), 0)...};
42         static_cast<void>(unused);
43         // We can't have a default parameter and a template parameter pack at the same time, so
44         // unfortunately we can't capture position info from this overload.
45         this->init(modifiers, returnType, name, std::move(parameterArray), PositionInfo());
46     }
47 
48     DSLFunction(const DSLType& returnType, skstd::string_view name,
49                 SkTArray<DSLParameter*> parameters, PositionInfo pos = PositionInfo::Capture()) {
50         this->init(DSLModifiers(), returnType, name, std::move(parameters), pos);
51     }
52 
53     DSLFunction(const DSLModifiers& modifiers, const DSLType& returnType, skstd::string_view name,
54                 SkTArray<DSLParameter*> parameters, PositionInfo pos = PositionInfo::Capture()) {
55         this->init(modifiers, returnType, name, std::move(parameters), pos);
56     }
57 
DSLFunction(const SkSL::FunctionDeclaration * decl)58     DSLFunction(const SkSL::FunctionDeclaration* decl)
59         : fDecl(decl) {}
60 
61     virtual ~DSLFunction() = default;
62 
63     template<class... Stmt>
define(Stmt...stmts)64     void define(Stmt... stmts) {
65         DSLBlock block = DSLBlock(DSLStatement(std::move(stmts))...);
66         this->define(std::move(block));
67     }
68 
69     void define(DSLBlock block, PositionInfo pos = PositionInfo::Capture());
70 
71     /**
72      * Invokes the function with the given arguments.
73      */
74     template<class... Args>
operator()75     DSLExpression operator()(Args&&... args) {
76         ExpressionArray argArray;
77         argArray.reserve_back(sizeof...(args));
78         this->collectArgs(argArray, std::forward<Args>(args)...);
79         return this->call(std::move(argArray));
80     }
81 
82     /**
83      * Invokes the function with the given arguments.
84      */
85     DSLExpression call(SkTArray<DSLWrapper<DSLExpression>> args,
86             PositionInfo pos = PositionInfo::Capture());
87 
88     DSLExpression call(ExpressionArray args, PositionInfo pos = PositionInfo::Capture());
89 
90 private:
collectArgs(ExpressionArray & args)91     void collectArgs(ExpressionArray& args) {}
92 
93     template<class... RemainingArgs>
collectArgs(ExpressionArray & args,DSLVar & var,RemainingArgs &&...remaining)94     void collectArgs(ExpressionArray& args, DSLVar& var, RemainingArgs&&... remaining) {
95         args.push_back(DSLExpression(var).release());
96         collectArgs(args, std::forward<RemainingArgs>(remaining)...);
97     }
98 
99     template<class... RemainingArgs>
collectArgs(ExpressionArray & args,DSLExpression expr,RemainingArgs &&...remaining)100     void collectArgs(ExpressionArray& args, DSLExpression expr, RemainingArgs&&... remaining) {
101         args.push_back(expr.release());
102         collectArgs(args, std::forward<RemainingArgs>(remaining)...);
103     }
104 
105     void init(DSLModifiers modifiers, const DSLType& returnType, skstd::string_view name,
106               SkTArray<DSLParameter*> params, PositionInfo pos);
107 
108     const SkSL::FunctionDeclaration* fDecl = nullptr;
109     SkSL::PositionInfo fPosition;
110 };
111 
112 } // namespace dsl
113 
114 } // namespace SkSL
115 
116 #endif
117