• 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_OPERATOR
9 #define SKSL_OPERATOR
10 
11 #include <cstdint>
12 #include <string_view>
13 
14 namespace SkSL {
15 
16 class Context;
17 class Type;
18 
19 enum class OperatorKind : uint8_t {
20     PLUS,
21     MINUS,
22     STAR,
23     SLASH,
24     PERCENT,
25     SHL,
26     SHR,
27     LOGICALNOT,
28     LOGICALAND,
29     LOGICALOR,
30     LOGICALXOR,
31     BITWISENOT,
32     BITWISEAND,
33     BITWISEOR,
34     BITWISEXOR,
35     EQ,
36     EQEQ,
37     NEQ,
38     LT,
39     GT,
40     LTEQ,
41     GTEQ,
42     PLUSEQ,
43     MINUSEQ,
44     STAREQ,
45     SLASHEQ,
46     PERCENTEQ,
47     SHLEQ,
48     SHREQ,
49     BITWISEANDEQ,
50     BITWISEOREQ,
51     BITWISEXOREQ,
52     PLUSPLUS,
53     MINUSMINUS,
54     COMMA
55 };
56 
57 enum class OperatorPrecedence : uint8_t {
58     kParentheses    =  1,
59     kPostfix        =  2,
60     kPrefix         =  3,
61     kMultiplicative =  4,
62     kAdditive       =  5,
63     kShift          =  6,
64     kRelational     =  7,
65     kEquality       =  8,
66     kBitwiseAnd     =  9,
67     kBitwiseXor     = 10,
68     kBitwiseOr      = 11,
69     kLogicalAnd     = 12,
70     kLogicalXor     = 13,
71     kLogicalOr      = 14,
72     kTernary        = 15,
73     kAssignment     = 16,
74     kSequence       = 17,
75     kTopLevel       = kSequence
76 };
77 
78 class Operator {
79 public:
80     using Kind = OperatorKind;
81 
Operator(Kind op)82     Operator(Kind op) : fKind(op) {}
83 
kind()84     Kind kind() const { return fKind; }
85 
isEquality()86     bool isEquality() const {
87         return fKind == Kind::EQEQ || fKind == Kind::NEQ;
88     }
89 
90     OperatorPrecedence getBinaryPrecedence() const;
91 
92     // Returns the operator name surrounded by the expected whitespace for a tidy binary expression.
93     const char* operatorName() const;
94 
95     // Returns the operator name without any surrounding whitespace.
96     std::string_view tightOperatorName() const;
97 
98     // Returns true if op is '=' or any compound assignment operator ('+=', '-=', etc.)
99     bool isAssignment() const;
100 
101     // Given a compound assignment operator, returns the non-assignment version of the operator
102     // (e.g. '+=' becomes '+')
103     Operator removeAssignment() const;
104 
105     /**
106      * Defines the set of relational (comparison) operators:
107      *     <  <=  >  >=
108      */
109     bool isRelational() const;
110 
111     /**
112      * Defines the set of operators which are only valid on integral types:
113      *   <<  <<=  >>  >>=  &  &=  |  |=  ^  ^=  %  %=
114      */
115     bool isOnlyValidForIntegralTypes() const;
116 
117     /**
118      * Defines the set of operators which perform vector/matrix math.
119      *   +  +=  -  -=  *  *=  /  /=  %  %=  <<  <<=  >>  >>=  &  &=  |  |=  ^  ^=
120      */
121     bool isValidForMatrixOrVector() const;
122 
123     /*
124      * Defines the set of operators allowed by The OpenGL ES Shading Language 1.00, Section 5.1.
125      * The set of illegal (reserved) operators are the ones that only make sense with integral
126      * types. This is not a coincidence: It's because ES2 doesn't require 'int' to be anything but
127      * syntactic sugar for floats with truncation after each operation.
128      */
isAllowedInStrictES2Mode()129     bool isAllowedInStrictES2Mode() const {
130         return !this->isOnlyValidForIntegralTypes();
131     }
132 
133     /**
134      * Determines the operand and result types of a binary expression. Returns true if the
135      * expression is legal, false otherwise. If false, the values of the out parameters are
136      * undefined.
137      */
138     bool determineBinaryType(const Context& context,
139                              const Type& left,
140                              const Type& right,
141                              const Type** outLeftType,
142                              const Type** outRightType,
143                              const Type** outResultType) const;
144 
145 private:
146     bool isOperator() const;
147     bool isMatrixMultiply(const Type& left, const Type& right) const;
148 
149     Kind fKind;
150 };
151 
152 }  // namespace SkSL
153 
154 #endif
155