OperatorPrecedence Operator::getBinaryPrecedence() const { switch (this->kind()) { case Kind::STAR: // fall through case Kind::SLASH: // fall through case Kind::PERCENT: return OperatorPrecedence::kMultiplicative; case Kind::PLUS: // fall through case Kind::MINUS: return OperatorPrecedence::kAdditive; case Kind::SHL: // fall through case Kind::SHR: return OperatorPrecedence::kShift; case Kind::LT: // fall through case Kind::GT: // fall through case Kind::LTEQ: // fall through case Kind::GTEQ: return OperatorPrecedence::kRelational; case Kind::EQEQ: // fall through case Kind::NEQ: return OperatorPrecedence::kEquality; case Kind::BITWISEAND: return OperatorPrecedence::kBitwiseAnd; case Kind::BITWISEXOR: return OperatorPrecedence::kBitwiseXor; case Kind::BITWISEOR: return OperatorPrecedence::kBitwiseOr; case Kind::LOGICALAND: return OperatorPrecedence::kLogicalAnd; case Kind::LOGICALXOR: return OperatorPrecedence::kLogicalXor; case Kind::LOGICALOR: return OperatorPrecedence::kLogicalOr; case Kind::EQ: // fall through case Kind::PLUSEQ: // fall through case Kind::MINUSEQ: // fall through case Kind::STAREQ: // fall through case Kind::SLASHEQ: // fall through case Kind::PERCENTEQ: // fall through case Kind::SHLEQ: // fall through case Kind::SHREQ: // fall through case Kind::BITWISEANDEQ: // fall through case Kind::BITWISEXOREQ: // fall through case Kind::BITWISEOREQ: return OperatorPrecedence::kAssignment; case Kind::COMMA: return OperatorPrecedence::kSequence; default: SK_ABORT("unsupported binary operator");
}
}
constchar* Operator::operatorName() const { switch (this->kind()) { case Kind::PLUS: return" + "; case Kind::MINUS: return" - "; case Kind::STAR: return" * "; case Kind::SLASH: return" / "; case Kind::PERCENT: return" % "; case Kind::SHL: return" << "; case Kind::SHR: return" >> "; case Kind::LOGICALNOT: return"!"; case Kind::LOGICALAND: return" && "; case Kind::LOGICALOR: return" || "; case Kind::LOGICALXOR: return" ^^ "; case Kind::BITWISENOT: return"~"; case Kind::BITWISEAND: return" & "; case Kind::BITWISEOR: return" | "; case Kind::BITWISEXOR: return" ^ "; case Kind::EQ: return" = "; case Kind::EQEQ: return" == "; case Kind::NEQ: return" != "; case Kind::LT: return" < "; case Kind::GT: return" > "; case Kind::LTEQ: return" <= "; case Kind::GTEQ: return" >= "; case Kind::PLUSEQ: return" += "; case Kind::MINUSEQ: return" -= "; case Kind::STAREQ: return" *= "; case Kind::SLASHEQ: return" /= "; case Kind::PERCENTEQ: return" %= "; case Kind::SHLEQ: return" <<= "; case Kind::SHREQ: return" >>= "; case Kind::BITWISEANDEQ: return" &= "; case Kind::BITWISEOREQ: return" |= "; case Kind::BITWISEXOREQ: return" ^= "; case Kind::PLUSPLUS: return"++"; case Kind::MINUSMINUS: return"--"; case Kind::COMMA: return", "; default: SkUNREACHABLE;
}
}
std::string_view Operator::tightOperatorName() const {
std::string_view name = this->operatorName(); if (skstd::starts_with(name, ' ')) {
name.remove_prefix(1);
} if (skstd::ends_with(name, ' ')) {
name.remove_suffix(1);
} return name;
}
boolOperator::isAssignment() const { switch (this->kind()) { case Kind::EQ: // fall through case Kind::PLUSEQ: // fall through case Kind::MINUSEQ: // fall through case Kind::STAREQ: // fall through case Kind::SLASHEQ: // fall through case Kind::PERCENTEQ: // fall through case Kind::SHLEQ: // fall through case Kind::SHREQ: // fall through case Kind::BITWISEOREQ: // fall through case Kind::BITWISEXOREQ: // fall through case Kind::BITWISEANDEQ: returntrue; default: returnfalse;
}
}
OperatorOperator::removeAssignment() const { switch (this->kind()) { case Kind::PLUSEQ: return Kind::PLUS; case Kind::MINUSEQ: return Kind::MINUS; case Kind::STAREQ: return Kind::STAR; case Kind::SLASHEQ: return Kind::SLASH; case Kind::PERCENTEQ: return Kind::PERCENT; case Kind::SHLEQ: return Kind::SHL; case Kind::SHREQ: return Kind::SHR; case Kind::BITWISEOREQ: return Kind::BITWISEOR; case Kind::BITWISEXOREQ: return Kind::BITWISEXOR; case Kind::BITWISEANDEQ: return Kind::BITWISEAND; default: return *this;
}
}
boolOperator::isRelational() const { switch (this->kind()) { case Kind::LT: case Kind::GT: case Kind::LTEQ: case Kind::GTEQ: returntrue; default: returnfalse;
}
}
boolOperator::isOnlyValidForIntegralTypes() const { switch (this->kind()) { case Kind::SHL: case Kind::SHR: case Kind::BITWISEAND: case Kind::BITWISEOR: case Kind::BITWISEXOR: case Kind::PERCENT: case Kind::SHLEQ: case Kind::SHREQ: case Kind::BITWISEANDEQ: case Kind::BITWISEOREQ: case Kind::BITWISEXOREQ: case Kind::PERCENTEQ: returntrue; default: returnfalse;
}
}
boolOperator::isValidForMatrixOrVector() const { switch (this->kind()) { case Kind::PLUS: case Kind::MINUS: case Kind::STAR: case Kind::SLASH: case Kind::PERCENT: case Kind::SHL: case Kind::SHR: case Kind::BITWISEAND: case Kind::BITWISEOR: case Kind::BITWISEXOR: case Kind::PLUSEQ: case Kind::MINUSEQ: case Kind::STAREQ: case Kind::SLASHEQ: case Kind::PERCENTEQ: case Kind::SHLEQ: case Kind::SHREQ: case Kind::BITWISEANDEQ: case Kind::BITWISEOREQ: case Kind::BITWISEXOREQ: returntrue; default: returnfalse;
}
}
/** * Determines the operand and result types of a binary expression. Returns true if the expression is * legal, false otherwise. If false, the values of the out parameters are undefined.
*/ boolOperator::determineBinaryType(const Context& context, const Type& left, const Type& right, const Type** outLeftType, const Type** outRightType, const Type** outResultType) const { constbool allowNarrowing = context.fConfig->fSettings.fAllowNarrowingConversions; switch (this->kind()) { case Kind::EQ: // left = right if (left.isVoid()) { returnfalse;
}
*outLeftType = &left;
*outRightType = &left;
*outResultType = &left; return right.canCoerceTo(left, allowNarrowing);
case Kind::EQEQ: // left == right case Kind::NEQ: { // left != right if (left.isVoid() || left.isOpaque()) { returnfalse;
}
CoercionCost rightToLeft = right.coercionCost(left),
leftToRight = left.coercionCost(right); if (rightToLeft < leftToRight) { if (rightToLeft.isPossible(allowNarrowing)) {
*outLeftType = &left;
*outRightType = &left;
*outResultType = context.fTypes.fBool.get(); returntrue;
}
} else { if (leftToRight.isPossible(allowNarrowing)) {
*outLeftType = &right;
*outRightType = &right;
*outResultType = context.fTypes.fBool.get(); returntrue;
}
} returnfalse;
} case Kind::LOGICALOR: // left || right case Kind::LOGICALAND: // left && right case Kind::LOGICALXOR: // left ^^ right
*outLeftType = context.fTypes.fBool.get();
*outRightType = context.fTypes.fBool.get();
*outResultType = context.fTypes.fBool.get(); return left.canCoerceTo(*context.fTypes.fBool, allowNarrowing) &&
right.canCoerceTo(*context.fTypes.fBool, allowNarrowing);
// Boolean types only support the operators listed above (, = == != || && ^^). // If we've gotten this far with a boolean, we have an unsupported operator. const Type& leftComponentType = left.componentType(); const Type& rightComponentType = right.componentType(); if (leftComponentType.isBoolean() || rightComponentType.isBoolean()) { returnfalse;
}
bool isAssignment = this->isAssignment(); if (this->isMatrixMultiply(left, right)) { // left * right // Determine final component type. if (!this->determineBinaryType(context, left.componentType(), right.componentType(),
outLeftType, outRightType, outResultType)) { returnfalse;
} // Convert component type to compound.
*outLeftType = &(*outResultType)->toCompound(context, left.columns(), left.rows());
*outRightType = &(*outResultType)->toCompound(context, right.columns(), right.rows()); int leftColumns = left.columns(), leftRows = left.rows(); int rightColumns = right.columns(), rightRows = right.rows(); if (right.isVector()) { // `matrix * vector` treats the vector as a column vector; we need to transpose it.
std::swap(rightColumns, rightRows);
SkASSERT(rightColumns == 1);
} if (rightColumns > 1) {
*outResultType = &(*outResultType)->toCompound(context, rightColumns, leftRows);
} else { // The result was a column vector. Transpose it back to a row.
*outResultType = &(*outResultType)->toCompound(context, leftRows, rightColumns);
} if (isAssignment && ((*outResultType)->columns() != leftColumns ||
(*outResultType)->rows() != leftRows)) { returnfalse;
} return leftColumns == rightRows;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.