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, // a comma-separated sequence 75 kExpression = kSequence, // a top-level expression, anywhere in a statement 76 kStatement = 18, // a standalone expression-statement 77 }; 78 79 class Operator { 80 public: 81 using Kind = OperatorKind; 82 Operator(Kind op)83 Operator(Kind op) : fKind(op) {} 84 kind()85 Kind kind() const { return fKind; } 86 isEquality()87 bool isEquality() const { 88 return fKind == Kind::EQEQ || fKind == Kind::NEQ; 89 } 90 91 OperatorPrecedence getBinaryPrecedence() const; 92 93 // Returns the operator name surrounded by the expected whitespace for a tidy binary expression. 94 const char* operatorName() const; 95 96 // Returns the operator name without any surrounding whitespace. 97 std::string_view tightOperatorName() const; 98 99 // Returns true if op is `=` or any compound-assignment operator (`+=`, `-=`, etc.) 100 bool isAssignment() const; 101 102 // Returns true if op is any compound-assignment operator (`+=`, `-=`, etc.) but false for `=` 103 bool isCompoundAssignment() const; 104 105 // Given a compound-assignment operator, returns the non-assignment version of the operator 106 // (e.g. `+=` becomes `+`) 107 Operator removeAssignment() const; 108 109 /** 110 * Defines the set of relational (comparison) operators: 111 * < <= > >= 112 */ 113 bool isRelational() const; 114 115 /** 116 * Defines the set of operators which are only valid on integral types: 117 * << <<= >> >>= & &= | |= ^ ^= % %= 118 */ 119 bool isOnlyValidForIntegralTypes() const; 120 121 /** 122 * Defines the set of operators which perform vector/matrix math. 123 * + += - -= * *= / /= % %= << <<= >> >>= & &= | |= ^ ^= 124 */ 125 bool isValidForMatrixOrVector() const; 126 127 /* 128 * Defines the set of operators allowed by The OpenGL ES Shading Language 1.00, Section 5.1. 129 * The set of illegal (reserved) operators are the ones that only make sense with integral 130 * types. This is not a coincidence: It's because ES2 doesn't require 'int' to be anything but 131 * syntactic sugar for floats with truncation after each operation. 132 */ isAllowedInStrictES2Mode()133 bool isAllowedInStrictES2Mode() const { 134 return !this->isOnlyValidForIntegralTypes(); 135 } 136 137 /** 138 * Determines the operand and result types of a binary expression. Returns true if the 139 * expression is legal, false otherwise. If false, the values of the out parameters are 140 * undefined. 141 */ 142 bool determineBinaryType(const Context& context, 143 const Type& left, 144 const Type& right, 145 const Type** outLeftType, 146 const Type** outRightType, 147 const Type** outResultType) const; 148 149 private: 150 bool isOperator() const; 151 bool isMatrixMultiply(const Type& left, const Type& right) const; 152 153 Kind fKind; 154 }; 155 156 } // namespace SkSL 157 158 #endif 159