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