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