1 /*
2 * Copyright 2020 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 #include "include/sksl/DSLExpression.h"
9
10 #include "include/core/SkTypes.h"
11 #include "include/private/SkSLDefines.h"
12 #include "include/sksl/DSLCore.h"
13 #include "include/sksl/DSLType.h"
14 #include "include/sksl/DSLVar.h"
15 #include "include/sksl/SkSLOperator.h"
16 #include "src/sksl/SkSLThreadContext.h"
17 #include "src/sksl/dsl/priv/DSLWriter.h"
18 #include "src/sksl/ir/SkSLBinaryExpression.h"
19 #include "src/sksl/ir/SkSLExpression.h"
20 #include "src/sksl/ir/SkSLFieldAccess.h"
21 #include "src/sksl/ir/SkSLFunctionCall.h"
22 #include "src/sksl/ir/SkSLIndexExpression.h"
23 #include "src/sksl/ir/SkSLLiteral.h"
24 #include "src/sksl/ir/SkSLPoison.h"
25 #include "src/sksl/ir/SkSLPostfixExpression.h"
26 #include "src/sksl/ir/SkSLPrefixExpression.h"
27 #include "src/sksl/ir/SkSLVariableReference.h"
28
29 #include <utility>
30
31 namespace SkSL {
32
33 namespace dsl {
34
DSLExpression()35 DSLExpression::DSLExpression() {}
36
DSLExpression(DSLExpression && other)37 DSLExpression::DSLExpression(DSLExpression&& other)
38 : fExpression(std::move(other.fExpression)) {}
39
DSLExpression(std::unique_ptr<SkSL::Expression> expression,Position pos)40 DSLExpression::DSLExpression(std::unique_ptr<SkSL::Expression> expression, Position pos)
41 : fExpression(expression ? std::move(expression)
42 : SkSL::Poison::Make(pos, ThreadContext::Context())) {
43 // If a position was passed in, it must match the expression's position.
44 SkASSERTF(!pos.valid() || this->position() == pos,
45 "expected expression position (%d-%d), but received (%d-%d)",
46 pos.startOffset(), pos.endOffset(),
47 this->position().startOffset(), this->position().endOffset());
48 }
49
DSLExpression(float value,Position pos)50 DSLExpression::DSLExpression(float value, Position pos)
51 : fExpression(SkSL::Literal::MakeFloat(ThreadContext::Context(),
52 pos,
53 value)) {}
54
DSLExpression(int value,Position pos)55 DSLExpression::DSLExpression(int value, Position pos)
56 : fExpression(SkSL::Literal::MakeInt(ThreadContext::Context(),
57 pos,
58 value)) {}
59
DSLExpression(int64_t value,Position pos)60 DSLExpression::DSLExpression(int64_t value, Position pos)
61 : fExpression(SkSL::Literal::MakeInt(ThreadContext::Context(),
62 pos,
63 value)) {}
64
DSLExpression(unsigned int value,Position pos)65 DSLExpression::DSLExpression(unsigned int value, Position pos)
66 : fExpression(SkSL::Literal::MakeInt(ThreadContext::Context(),
67 pos,
68 value)) {}
69
DSLExpression(bool value,Position pos)70 DSLExpression::DSLExpression(bool value, Position pos)
71 : fExpression(SkSL::Literal::MakeBool(ThreadContext::Context(),
72 pos,
73 value)) {}
74
DSLExpression(DSLVarBase & var,Position pos)75 DSLExpression::DSLExpression(DSLVarBase& var, Position pos)
76 : fExpression(std::make_unique<SkSL::VariableReference>(
77 pos, DSLWriter::Var(var), SkSL::VariableReference::RefKind::kRead)) {}
78
DSLExpression(DSLVarBase && var,Position pos)79 DSLExpression::DSLExpression(DSLVarBase&& var, Position pos)
80 : DSLExpression(var) {}
81
~DSLExpression()82 DSLExpression::~DSLExpression() {}
83
Poison(Position pos)84 DSLExpression DSLExpression::Poison(Position pos) {
85 return DSLExpression(SkSL::Poison::Make(pos, ThreadContext::Context()));
86 }
87
isValid() const88 bool DSLExpression::isValid() const {
89 return this->hasValue() && !fExpression->is<SkSL::Poison>();
90 }
91
swap(DSLExpression & other)92 void DSLExpression::swap(DSLExpression& other) {
93 std::swap(fExpression, other.fExpression);
94 }
95
release()96 std::unique_ptr<SkSL::Expression> DSLExpression::release() {
97 SkASSERT(this->hasValue());
98 return std::move(fExpression);
99 }
100
releaseIfPossible()101 std::unique_ptr<SkSL::Expression> DSLExpression::releaseIfPossible() {
102 return std::move(fExpression);
103 }
104
type() const105 DSLType DSLExpression::type() const {
106 if (!this->hasValue()) {
107 return kVoid_Type;
108 }
109 return &fExpression->type();
110 }
111
description() const112 std::string DSLExpression::description() const {
113 SkASSERT(this->hasValue());
114 return fExpression->description();
115 }
116
position() const117 Position DSLExpression::position() const {
118 SkASSERT(this->hasValue());
119 return fExpression->fPosition;
120 }
121
setPosition(Position pos)122 void DSLExpression::setPosition(Position pos) {
123 SkASSERT(this->hasValue());
124 fExpression->fPosition = pos;
125 }
126
x(Position pos)127 DSLExpression DSLExpression::x(Position pos) {
128 return Swizzle(std::move(*this), X, pos);
129 }
130
y(Position pos)131 DSLExpression DSLExpression::y(Position pos) {
132 return Swizzle(std::move(*this), Y, pos);
133 }
134
z(Position pos)135 DSLExpression DSLExpression::z(Position pos) {
136 return Swizzle(std::move(*this), Z, pos);
137 }
138
w(Position pos)139 DSLExpression DSLExpression::w(Position pos) {
140 return Swizzle(std::move(*this), W, pos);
141 }
142
r(Position pos)143 DSLExpression DSLExpression::r(Position pos) {
144 return Swizzle(std::move(*this), R, pos);
145 }
146
g(Position pos)147 DSLExpression DSLExpression::g(Position pos) {
148 return Swizzle(std::move(*this), G, pos);
149 }
150
b(Position pos)151 DSLExpression DSLExpression::b(Position pos) {
152 return Swizzle(std::move(*this), B, pos);
153 }
154
a(Position pos)155 DSLExpression DSLExpression::a(Position pos) {
156 return Swizzle(std::move(*this), A, pos);
157 }
158
field(std::string_view name,Position pos)159 DSLExpression DSLExpression::field(std::string_view name, Position pos) {
160 return DSLExpression(FieldAccess::Convert(ThreadContext::Context(), pos,
161 *ThreadContext::SymbolTable(), this->release(), name), pos);
162 }
163
assign(DSLExpression right)164 DSLExpression DSLExpression::assign(DSLExpression right) {
165 Position pos = this->position().rangeThrough(right.position());
166 return DSLExpression(BinaryExpression::Convert(ThreadContext::Context(), pos, this->release(),
167 SkSL::Operator::Kind::EQ, right.release()));
168 }
169
operator [](DSLExpression right)170 DSLExpression DSLExpression::operator[](DSLExpression right) {
171 Position pos = this->position().rangeThrough(right.position());
172 return DSLExpression(IndexExpression::Convert(ThreadContext::Context(),
173 *ThreadContext::SymbolTable(), pos,
174 this->release(), right.release()));
175 }
176
index(DSLExpression index,Position pos)177 DSLExpression DSLExpression::index(DSLExpression index, Position pos) {
178 std::unique_ptr<SkSL::Expression> result = IndexExpression::Convert(ThreadContext::Context(),
179 *ThreadContext::SymbolTable(), pos, this->release(), index.release());
180 return DSLExpression(std::move(result), pos);
181 }
182
operator ()(SkTArray<DSLExpression> args,Position pos)183 DSLExpression DSLExpression::operator()(SkTArray<DSLExpression> args, Position pos) {
184 ExpressionArray converted;
185 converted.reserve_back(args.size());
186 for (DSLExpression& arg : args) {
187 converted.push_back(arg.release());
188 }
189 return (*this)(std::move(converted), pos);
190 }
191
operator ()(ExpressionArray args,Position pos)192 DSLExpression DSLExpression::operator()(ExpressionArray args, Position pos) {
193 return DSLExpression(SkSL::FunctionCall::Convert(ThreadContext::Context(), pos, this->release(),
194 std::move(args)), pos);
195 }
196
prefix(Operator::Kind op,Position pos)197 DSLExpression DSLExpression::prefix(Operator::Kind op, Position pos) {
198 std::unique_ptr<SkSL::Expression> result = PrefixExpression::Convert(ThreadContext::Context(),
199 pos, op, this->release());
200 return DSLExpression(std::move(result), pos);
201 }
202
postfix(Operator::Kind op,Position pos)203 DSLExpression DSLExpression::postfix(Operator::Kind op, Position pos) {
204 std::unique_ptr<SkSL::Expression> result = PostfixExpression::Convert(ThreadContext::Context(),
205 pos, this->release(), op);
206 return DSLExpression(std::move(result), pos);
207 }
208
binary(Operator::Kind op,DSLExpression right,Position pos)209 DSLExpression DSLExpression::binary(Operator::Kind op, DSLExpression right, Position pos) {
210 std::unique_ptr<SkSL::Expression> result = BinaryExpression::Convert(ThreadContext::Context(),
211 pos, this->release(), op, right.release());
212 return DSLExpression(std::move(result), pos);
213 }
214
215 #define OP(op, token) \
216 DSLExpression operator op(DSLExpression left, DSLExpression right) { \
217 return DSLExpression(BinaryExpression::Convert(ThreadContext::Context(), \
218 Position(), \
219 left.release(), \
220 Operator::Kind::token, \
221 right.release())); \
222 }
223
224 #define PREFIXOP(op, token) \
225 DSLExpression operator op(DSLExpression expr) { \
226 return DSLExpression(PrefixExpression::Convert(ThreadContext::Context(), \
227 Position(), \
228 Operator::Kind::token, \
229 expr.release())); \
230 }
231
232 #define POSTFIXOP(op, token) \
233 DSLExpression operator op(DSLExpression expr, int) { \
234 return DSLExpression(PostfixExpression::Convert(ThreadContext::Context(), \
235 Position(), \
236 expr.release(), \
237 Operator::Kind::token)); \
238 }
239
240 OP(+, PLUS)
241 OP(+=, PLUSEQ)
242 OP(-, MINUS)
243 OP(-=, MINUSEQ)
244 OP(*, STAR)
245 OP(*=, STAREQ)
246 OP(/, SLASH)
247 OP(/=, SLASHEQ)
248 OP(%, PERCENT)
249 OP(%=, PERCENTEQ)
250 OP(<<, SHL)
251 OP(<<=, SHLEQ)
252 OP(>>, SHR)
253 OP(>>=, SHREQ)
254 OP(&&, LOGICALAND)
255 OP(||, LOGICALOR)
256 OP(&, BITWISEAND)
257 OP(&=, BITWISEANDEQ)
258 OP(|, BITWISEOR)
259 OP(|=, BITWISEOREQ)
260 OP(^, BITWISEXOR)
261 OP(^=, BITWISEXOREQ)
LogicalXor(DSLExpression left,DSLExpression right)262 DSLExpression LogicalXor(DSLExpression left, DSLExpression right) {
263 return DSLExpression(BinaryExpression::Convert(ThreadContext::Context(),
264 Position(),
265 left.release(),
266 SkSL::Operator::Kind::LOGICALXOR,
267 right.release()));
268 }
269 OP(==, EQEQ)
270 OP(!=, NEQ)
271 OP(>, GT)
272 OP(<, LT)
273 OP(>=, GTEQ)
274 OP(<=, LTEQ)
275
276 PREFIXOP(+, PLUS)
277 PREFIXOP(-, MINUS)
278 PREFIXOP(!, LOGICALNOT)
279 PREFIXOP(~, BITWISENOT)
280 PREFIXOP(++, PLUSPLUS)
281 POSTFIXOP(++, PLUSPLUS)
282 PREFIXOP(--, MINUSMINUS)
283 POSTFIXOP(--, MINUSMINUS)
284
operator ,(DSLExpression left,DSLExpression right)285 DSLExpression operator,(DSLExpression left, DSLExpression right) {
286 return DSLExpression(BinaryExpression::Convert(ThreadContext::Context(),
287 Position(),
288 left.release(),
289 SkSL::Operator::Kind::COMMA,
290 right.release()));
291 }
292
293 } // namespace dsl
294
295 } // namespace SkSL
296