Flutter Engine
The Flutter Engine
SkSLIsSameExpressionTree.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 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
22
23#include <cstddef>
24#include <memory>
25
26namespace SkSL {
27
28bool Analysis::IsSameExpressionTree(const Expression& left, const Expression& right) {
29 if (left.kind() != right.kind() || !left.type().matches(right.type())) {
30 return false;
31 }
32
33 // This isn't a fully exhaustive list of expressions by any stretch of the imagination; for
34 // instance, `x[y+1] = x[y+1]` isn't detected because we don't look at BinaryExpressions.
35 // Since this is intended to be used for optimization purposes, handling the common cases is
36 // sufficient.
37 switch (left.kind()) {
39 return left.as<Literal>().value() == right.as<Literal>().value();
40
41 case Expression::Kind::kConstructorArray:
42 case Expression::Kind::kConstructorArrayCast:
43 case Expression::Kind::kConstructorCompound:
44 case Expression::Kind::kConstructorCompoundCast:
45 case Expression::Kind::kConstructorDiagonalMatrix:
46 case Expression::Kind::kConstructorMatrixResize:
47 case Expression::Kind::kConstructorScalarCast:
48 case Expression::Kind::kConstructorStruct:
49 case Expression::Kind::kConstructorSplat: {
50 if (left.kind() != right.kind()) {
51 return false;
52 }
53 const AnyConstructor& leftCtor = left.asAnyConstructor();
54 const AnyConstructor& rightCtor = right.asAnyConstructor();
55 const auto leftSpan = leftCtor.argumentSpan();
56 const auto rightSpan = rightCtor.argumentSpan();
57 if (leftSpan.size() != rightSpan.size()) {
58 return false;
59 }
60 for (size_t index = 0; index < leftSpan.size(); ++index) {
61 if (!IsSameExpressionTree(*leftSpan[index], *rightSpan[index])) {
62 return false;
63 }
64 }
65 return true;
66 }
67 case Expression::Kind::kFieldAccess:
68 return left.as<FieldAccess>().fieldIndex() == right.as<FieldAccess>().fieldIndex() &&
70 *right.as<FieldAccess>().base());
71
73 return IsSameExpressionTree(*left.as<IndexExpression>().index(),
74 *right.as<IndexExpression>().index()) &&
76 *right.as<IndexExpression>().base());
77
78 case Expression::Kind::kPrefix:
79 return (left.as<PrefixExpression>().getOperator().kind() ==
80 right.as<PrefixExpression>().getOperator().kind()) &&
82 *right.as<PrefixExpression>().operand());
83
84 case Expression::Kind::kSwizzle:
85 return left.as<Swizzle>().components() == right.as<Swizzle>().components() &&
86 IsSameExpressionTree(*left.as<Swizzle>().base(), *right.as<Swizzle>().base());
87
88 case Expression::Kind::kVariableReference:
89 return left.as<VariableReference>().variable() ==
90 right.as<VariableReference>().variable();
91
92 default:
93 return false;
94 }
95}
96
97} // namespace SkSL
virtual SkSpan< std::unique_ptr< Expression > > argumentSpan()=0
std::unique_ptr< Expression > & base()
std::unique_ptr< Expression > & base()
std::unique_ptr< Expression > & index()
Kind kind() const
Definition: SkSLOperator.h:85
Operator getOperator() const
std::unique_ptr< Expression > & operand()
std::unique_ptr< Expression > & base()
Definition: SkSLSwizzle.h:82
uint8_t value
bool IsSameExpressionTree(const Expression &left, const Expression &right)