double values[16];
size_t numSlots = expr.type().slotCount(); if (numSlots > std::size(values)) { // The expression has more slots than we expected. return nullptr;
}
for (size_t index = 0; index < numSlots; ++index) { if (std::optional<double> slotValue = expr.getConstantValue(index)) {
values[index] = fn(*slotValue); if (elementType.checkForOutOfRangeLiteral(context, values[index], pos)) { // We can't simplify the expression if the new value is out-of-range for the type. return nullptr;
}
} else { // There's a non-constant element; we can't simplify this expression. return nullptr;
}
} return ConstructorCompound::MakeFromConstants(context, pos, expr.type(), values);
}
static std::unique_ptr<Expression> simplify_negation(const Context& context,
Position pos, const Expression& originalExpr) { const Expression* value = ConstantFolder::GetConstantValueForVariable(originalExpr); switch (value->kind()) { case Expression::Kind::kLiteral: case Expression::Kind::kConstructorSplat: case Expression::Kind::kConstructorCompound: { // Convert `-vecN(literal, ...)` into `vecN(-literal, ...)`. if (std::unique_ptr<Expression> expr = apply_to_elements(context, pos, *value,
negate_value)) { return expr;
} break;
} case Expression::Kind::kPrefix: { // Convert `-(-expression)` into `expression`. const PrefixExpression& prefix = value->as<PrefixExpression>(); if (prefix.getOperator().kind() == Operator::Kind::MINUS) { return prefix.operand()->clone(pos);
} break;
} case Expression::Kind::kConstructorArray: // Convert `-array[N](literal, ...)` into `array[N](-literal, ...)`. if (Analysis::IsCompileTimeConstant(*value)) { const ConstructorArray& ctor = value->as<ConstructorArray>(); return ConstructorArray::Make(context, pos, ctor.type(),
negate_operands(context, pos, ctor.arguments()));
} break;
case Expression::Kind::kConstructorDiagonalMatrix: // Convert `-matrix(literal)` into `matrix(-literal)`. if (Analysis::IsCompileTimeConstant(*value)) { const ConstructorDiagonalMatrix& ctor = value->as<ConstructorDiagonalMatrix>(); if (std::unique_ptr<Expression> simplified = simplify_negation(context,
pos,
*ctor.argument())) { return ConstructorDiagonalMatrix::Make(context, pos, ctor.type(),
std::move(simplified));
}
} break;
default: break;
} return nullptr;
}
static ExpressionArray negate_operands(const Context& context,
Position pos, const ExpressionArray& array) {
ExpressionArray replacement;
replacement.reserve_exact(array.size()); for (const std::unique_ptr<Expression>& expr : array) { // The logic below is very similar to `negate_operand`, but with different ownership rules. if (std::unique_ptr<Expression> simplified = simplify_negation(context, pos, *expr)) {
replacement.push_back(std::move(simplified));
} else {
replacement.push_back(std::make_unique<PrefixExpression>(pos, Operator::Kind::MINUS,
expr->clone()));
}
} return replacement;
}
static std::unique_ptr<Expression> negate_operand(const Context& context,
Position pos,
std::unique_ptr<Expression> value) { // Attempt to simplify this negation (e.g. eliminate double negation, literal values) if (std::unique_ptr<Expression> simplified = simplify_negation(context, pos, *value)) { return simplified;
}
// No simplified form; convert expression to Prefix(MINUS, expression). return std::make_unique<PrefixExpression>(pos, Operator::Kind::MINUS, std::move(value));
}
static std::unique_ptr<Expression> logical_not_operand(const Context& context,
Position pos,
std::unique_ptr<Expression> operand) { const Expression* value = ConstantFolder::GetConstantValueForVariable(*operand); switch (value->kind()) { case Expression::Kind::kLiteral: { // Convert !boolLiteral(true) to boolLiteral(false).
SkASSERT(value->type().isBoolean()); const Literal& b = value->as<Literal>(); return Literal::MakeBool(pos, !b.boolValue(), &operand->type());
} case Expression::Kind::kPrefix: { // Convert `!(!expression)` into `expression`.
PrefixExpression& prefix = operand->as<PrefixExpression>(); if (prefix.getOperator().kind() == Operator::Kind::LOGICALNOT) {
prefix.operand()->fPosition = pos; return std::move(prefix.operand());
} break;
} case Expression::Kind::kBinary: {
BinaryExpression& binary = operand->as<BinaryExpression>();
std::optional<Operator> replacement; switch (binary.getOperator().kind()) { case OperatorKind::EQEQ: replacement = OperatorKind::NEQ; break; case OperatorKind::NEQ: replacement = OperatorKind::EQEQ; break; case OperatorKind::LT: replacement = OperatorKind::GTEQ; break; case OperatorKind::LTEQ: replacement = OperatorKind::GT; break; case OperatorKind::GT: replacement = OperatorKind::LTEQ; break; case OperatorKind::GTEQ: replacement = OperatorKind::LT; break; default: break;
} if (replacement.has_value()) { return BinaryExpression::Make(context, pos, std::move(binary.left()),
*replacement, std::move(binary.right()),
&binary.type());
} break;
} default: break;
}
// No simplified form; convert expression to Prefix(LOGICALNOT, expression). return std::make_unique<PrefixExpression>(pos, Operator::Kind::LOGICALNOT, std::move(operand));
}
caseOperator::Kind::BITWISENOT:
SkASSERT(!context.fConfig->strictES2Mode());
SkASSERT(!baseType.isArray());
SkASSERT(baseType.componentType().isInteger()); if (baseType.isLiteral()) { // The expression `~123` is no longer a literal; coerce to the actual type.
base = baseType.scalarTypeForLiteral().coerceExpression(std::move(base), context);
SkASSERT(base);
} return bitwise_not_operand(context, pos, std::move(base));
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.