Convert Operators namespace to first-class Operator object.

This lets us write `op.isAssignment()` instead of
`Operators::IsAssignment(op)`.

Change-Id: If35f2ac500b6ccabc364f9104faaad6e62564667
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/369958
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
This commit is contained in:
John Stiles 2021-02-16 10:55:27 -05:00 committed by Skia Commit-Bot
parent 4a3ec173b3
commit 4599050369
31 changed files with 480 additions and 405 deletions

View File

@ -17,7 +17,7 @@ String ASTNode::description() const {
case Kind::kNull: return "";
case Kind::kBinary:
return "(" + this->begin()->description() + " " +
Operators::OperatorName(getToken().fKind) + " " +
getOperator().operatorName() + " " +
(this->begin() + 1)->description() + ")";
case Kind::kBlock: {
String result = "{\n";
@ -162,9 +162,9 @@ String ASTNode::description() const {
return result;
}
case Kind::kPostfix:
return this->begin()->description() + Operators::OperatorName(getToken().fKind);
return this->begin()->description() + getOperator().operatorName();
case Kind::kPrefix:
return Operators::OperatorName(getToken().fKind) + this->begin()->description();
return getOperator().operatorName() + this->begin()->description();
case Kind::kReturn:
if (this->begin() != this->end()) {
return "return " + this->begin()->description() + ";";

View File

@ -9,6 +9,7 @@
#define SKSL_ASTNODE
#include "src/sksl/SkSLLexer.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/SkSLString.h"
#include "src/sksl/ir/SkSLModifiers.h"
@ -53,7 +54,7 @@ struct ASTNode {
};
enum class Kind {
// data: operator(Token), children: left, right
// data: operator, children: left, right
kBinary,
// children: statements
kBlock,
@ -97,9 +98,9 @@ struct ASTNode {
kNull,
// data: ParameterData, children: type, arraySize1, arraySize2, ..., value?
kParameter,
// data: operator(Token), children: operand
// data: operator, children: operand
kPostfix,
// data: operator(Token), children: operand
// data: operator, children: operand
kPrefix,
// children: value
kReturn,
@ -250,7 +251,7 @@ struct ASTNode {
};
struct NodeData {
char fBytes[std::max({sizeof(Token),
char fBytes[std::max({sizeof(Token::Kind),
sizeof(StringFragment),
sizeof(bool),
sizeof(SKSL_INT),
@ -263,7 +264,7 @@ struct ASTNode {
sizeof(SectionData)})];
enum class Kind {
kToken,
kOperator,
kStringFragment,
kBool,
kInt,
@ -278,8 +279,9 @@ struct ASTNode {
NodeData() = default;
NodeData(Token data)
: fKind(Kind::kToken) {
NodeData(Operator op)
: fKind(Kind::kOperator) {
Token::Kind data = op.kind();
memcpy(fBytes, &data, sizeof(data));
}
@ -341,12 +343,13 @@ struct ASTNode {
ASTNode(std::vector<ASTNode>* nodes, int offset, Kind kind)
: fNodes(nodes)
, fOffset(offset)
, fKind(kind) {
, fKind(kind) {
switch (kind) {
case Kind::kBinary:
case Kind::kPostfix:
case Kind::kPrefix:
fData.fKind = NodeData::Kind::kToken;
fData.fKind = NodeData::Kind::kOperator;
break;
case Kind::kBool:
@ -398,9 +401,9 @@ struct ASTNode {
}
}
ASTNode(std::vector<ASTNode>* nodes, int offset, Kind kind, Token t)
ASTNode(std::vector<ASTNode>* nodes, int offset, Kind kind, Operator op)
: fNodes(nodes)
, fData(t)
, fData(op)
, fOffset(offset)
, fKind(kind) {}
@ -450,11 +453,11 @@ struct ASTNode {
return fKind != Kind::kNull;
}
Token getToken() const {
SkASSERT(fData.fKind == NodeData::Kind::kToken);
Token result;
memcpy(&result, fData.fBytes, sizeof(result));
return result;
Operator getOperator() const {
SkASSERT(fData.fKind == NodeData::Kind::kOperator);
Token::Kind tokenKind;
memcpy(&tokenKind, fData.fBytes, sizeof(tokenKind));
return Operator{tokenKind};
}
bool getBool() const {

View File

@ -538,7 +538,7 @@ static const char* invalid_for_ES2(const ForStatement& loop,
return "expected loop index on left hand side of condition";
}
// relational_operator is one of: > >= < <= == or !=
switch (cond.getOperator()) {
switch (cond.getOperator().kind()) {
case Token::Kind::TK_GT:
case Token::Kind::TK_GTEQ:
case Token::Kind::TK_LT:
@ -575,7 +575,7 @@ static const char* invalid_for_ES2(const ForStatement& loop,
if (!getConstant(next.right(), &loopInfo.fDelta)) {
return "loop index must be modified by a constant expression";
}
switch (next.getOperator()) {
switch (next.getOperator().kind()) {
case Token::Kind::TK_PLUSEQ: break;
case Token::Kind::TK_MINUSEQ: loopInfo.fDelta = -loopInfo.fDelta; break;
default:
@ -587,7 +587,7 @@ static const char* invalid_for_ES2(const ForStatement& loop,
if (!is_loop_index(next.operand())) {
return "expected loop index in loop expression";
}
switch (next.getOperator()) {
switch (next.getOperator().kind()) {
case Token::Kind::TK_PLUSPLUS: loopInfo.fDelta = 1; break;
case Token::Kind::TK_MINUSMINUS: loopInfo.fDelta = -1; break;
default:
@ -599,7 +599,7 @@ static const char* invalid_for_ES2(const ForStatement& loop,
if (!is_loop_index(next.operand())) {
return "expected loop index in loop expression";
}
switch (next.getOperator()) {
switch (next.getOperator().kind()) {
case Token::Kind::TK_PLUSPLUS: loopInfo.fDelta = 1; break;
case Token::Kind::TK_MINUSMINUS: loopInfo.fDelta = -1; break;
default:
@ -624,7 +624,7 @@ static const char* invalid_for_ES2(const ForStatement& loop,
double val = loopInfo.fStart;
auto evalCond = [&]() {
switch (cond.getOperator()) {
switch (cond.getOperator().kind()) {
case Token::Kind::TK_GT: return val > loopEnd;
case Token::Kind::TK_GTEQ: return val >= loopEnd;
case Token::Kind::TK_LT: return val < loopEnd;

View File

@ -197,7 +197,7 @@ bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* it
switch (expr->kind()) {
case Expression::Kind::kBinary: {
BinaryExpression& b = expr->as<BinaryExpression>();
if (b.getOperator() == Token::Kind::TK_EQ) {
if (b.getOperator().kind() == Token::Kind::TK_EQ) {
if (!this->tryRemoveLValueBefore(iter, b.left().get())) {
return false;
}
@ -349,8 +349,8 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
switch ((*e)->kind()) {
case Expression::Kind::kBinary: {
BinaryExpression& b = e->get()->as<BinaryExpression>();
Token::Kind op = b.getOperator();
switch (op) {
Operator op = b.getOperator();
switch (op.kind()) {
case Token::Kind::TK_LOGICALAND: // fall through
case Token::Kind::TK_LOGICALOR: {
// this isn't as precise as it could be -- we don't bother to track that if we
@ -374,8 +374,7 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
break;
}
default:
this->addExpression(cfg, &b.left(),
!Operators::IsAssignment(b.getOperator()));
this->addExpression(cfg, &b.left(), !b.getOperator().isAssignment());
this->addExpression(cfg, &b.right(), constantPropagate);
cfg.currentBlock().fNodes.push_back(
BasicBlock::MakeExpression(e, constantPropagate));
@ -421,9 +420,10 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
}
case Expression::Kind::kPrefix: {
PrefixExpression& p = e->get()->as<PrefixExpression>();
this->addExpression(cfg, &p.operand(), constantPropagate &&
p.getOperator() != Token::Kind::TK_PLUSPLUS &&
p.getOperator() != Token::Kind::TK_MINUSMINUS);
this->addExpression(cfg, &p.operand(),
constantPropagate &&
p.getOperator().kind() != Token::Kind::TK_PLUSPLUS &&
p.getOperator().kind() != Token::Kind::TK_MINUSMINUS);
cfg.currentBlock().fNodes.push_back(BasicBlock::MakeExpression(e, constantPropagate));
break;
}

View File

@ -72,10 +72,10 @@ void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
Precedence parentPrecedence) {
const Expression& left = *b.left();
const Expression& right = *b.right();
Token::Kind op = b.getOperator();
if (op == Token::Kind::TK_PERCENT) {
Operator op = b.getOperator();
if (op.kind() == Token::Kind::TK_PERCENT) {
// need to use "%%" instead of "%" b/c the code will be inside of a printf
Precedence precedence = Operators::GetBinaryPrecedence(op);
Precedence precedence = op.getBinaryPrecedence();
if (precedence >= parentPrecedence) {
this->write("(");
}

View File

@ -25,7 +25,7 @@ public:
bool generateCode() override;
private:
using Precedence = Operators::Precedence;
using Precedence = Operator::Precedence;
void writef(const char* s, va_list va) SK_PRINTF_LIKE(2, 0);

View File

@ -431,7 +431,7 @@ static bool is_dead(const Expression& lvalue, ProgramUsage* usage) {
* to a dead target and lack of side effects on the left hand side.
*/
static bool dead_assignment(const BinaryExpression& b, ProgramUsage* usage) {
if (!Operators::IsAssignment(b.getOperator())) {
if (!b.getOperator().isAssignment()) {
return false;
}
return is_dead(*b.left(), usage);
@ -477,7 +477,7 @@ static bool is_matching_expression_tree(const Expression& left, const Expression
}
static bool self_assignment(const BinaryExpression& b) {
return b.getOperator() == Token::Kind::TK_EQ &&
return b.getOperator().kind() == Token::Kind::TK_EQ &&
is_matching_expression_tree(*b.left(), *b.right());
}
@ -576,7 +576,7 @@ static void delete_left(BasicBlock* b,
std::unique_ptr<Expression>& rightPointer = bin.right();
SkASSERT(!left.hasSideEffects());
bool result;
if (bin.getOperator() == Token::Kind::TK_EQ) {
if (bin.getOperator().kind() == Token::Kind::TK_EQ) {
result = b->tryRemoveLValueBefore(iter, &left);
} else {
result = b->tryRemoveExpressionBefore(iter, &left);
@ -764,7 +764,7 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
(!rightType.isScalar() && !rightType.isVector())) {
break;
}
switch (bin->getOperator()) {
switch (bin->getOperator().kind()) {
case Token::Kind::TK_STAR:
if (is_constant(left, 1)) {
if (leftType.isVector() && rightType.isScalar()) {

View File

@ -24,17 +24,17 @@
namespace SkSL {
static std::unique_ptr<Expression> eliminate_no_op_boolean(const Expression& left,
Token::Kind op,
Operator op,
const Expression& right) {
SkASSERT(right.is<BoolLiteral>());
bool rightVal = right.as<BoolLiteral>().value();
// Detect no-op Boolean expressions and optimize them away.
if ((op == Token::Kind::TK_LOGICALAND && rightVal) || // (expr && true) -> (expr)
(op == Token::Kind::TK_LOGICALOR && !rightVal) || // (expr || false) -> (expr)
(op == Token::Kind::TK_LOGICALXOR && !rightVal) || // (expr ^^ false) -> (expr)
(op == Token::Kind::TK_EQEQ && rightVal) || // (expr == true) -> (expr)
(op == Token::Kind::TK_NEQ && !rightVal)) { // (expr != false) -> (expr)
if ((op.kind() == Token::Kind::TK_LOGICALAND && rightVal) || // (expr && true) -> (expr)
(op.kind() == Token::Kind::TK_LOGICALOR && !rightVal) || // (expr || false) -> (expr)
(op.kind() == Token::Kind::TK_LOGICALXOR && !rightVal) || // (expr ^^ false) -> (expr)
(op.kind() == Token::Kind::TK_EQEQ && rightVal) || // (expr == true) -> (expr)
(op.kind() == Token::Kind::TK_NEQ && !rightVal)) { // (expr != false) -> (expr)
return left.clone();
}
@ -43,14 +43,14 @@ static std::unique_ptr<Expression> eliminate_no_op_boolean(const Expression& lef
}
static std::unique_ptr<Expression> short_circuit_boolean(const Expression& left,
Token::Kind op,
Operator op,
const Expression& right) {
SkASSERT(left.is<BoolLiteral>());
bool leftVal = left.as<BoolLiteral>().value();
// When the literal is on the left, we can sometimes eliminate the other expression entirely.
if ((op == Token::Kind::TK_LOGICALAND && !leftVal) || // (false && expr) -> (false)
(op == Token::Kind::TK_LOGICALOR && leftVal)) { // (true || expr) -> (true)
if ((op.kind() == Token::Kind::TK_LOGICALAND && !leftVal) || // (false && expr) -> (false)
(op.kind() == Token::Kind::TK_LOGICALOR && leftVal)) { // (true || expr) -> (true)
return left.clone();
}
@ -67,15 +67,15 @@ static std::unique_ptr<Expression> short_circuit_boolean(const Expression& left,
template <typename T, typename U = T>
static std::unique_ptr<Expression> simplify_vector(const Context& context,
const Expression& left,
Token::Kind op,
Operator op,
const Expression& right) {
SkASSERT(left.type().isVector());
SkASSERT(left.type() == right.type());
const Type& type = left.type();
// Handle boolean operations: == !=
if (op == Token::Kind::TK_EQEQ || op == Token::Kind::TK_NEQ) {
bool equality = (op == Token::Kind::TK_EQEQ);
if (op.kind() == Token::Kind::TK_EQEQ || op.kind() == Token::Kind::TK_NEQ) {
bool equality = (op.kind() == Token::Kind::TK_EQEQ);
switch (left.compareConstant(right)) {
case Expression::ComparisonResult::kNotEqual:
@ -102,7 +102,7 @@ static std::unique_ptr<Expression> simplify_vector(const Context& context,
return std::make_unique<Constructor>(left.fOffset, &type, std::move(args));
};
switch (op) {
switch (op.kind()) {
case Token::Kind::TK_PLUS: return vectorComponentwiseFold([](U a, U b) { return a + b; });
case Token::Kind::TK_MINUS: return vectorComponentwiseFold([](U a, U b) { return a - b; });
case Token::Kind::TK_STAR: return vectorComponentwiseFold([](U a, U b) { return a * b; });
@ -167,9 +167,9 @@ static bool contains_constant_zero(const Expression& expr) {
(ConstantFolder::GetConstantFloat(expr, &floatValue) && floatValue == 0.0f);
}
bool ConstantFolder::ErrorOnDivideByZero(const Context& context, int offset, Token::Kind op,
bool ConstantFolder::ErrorOnDivideByZero(const Context& context, int offset, Operator op,
const Expression& right) {
switch (op) {
switch (op.kind()) {
case Token::Kind::TK_SLASH:
case Token::Kind::TK_SLASHEQ:
case Token::Kind::TK_PERCENT:
@ -187,11 +187,11 @@ bool ConstantFolder::ErrorOnDivideByZero(const Context& context, int offset, Tok
std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
int offset,
const Expression& left,
Token::Kind op,
Operator op,
const Expression& right) {
// If this is the comma operator, the left side is evaluated but not otherwise used in any way.
// So if the left side has no side effects, it can just be eliminated entirely.
if (op == Token::Kind::TK_COMMA && !left.hasSideEffects()) {
if (op.kind() == Token::Kind::TK_COMMA && !left.hasSideEffects()) {
return right.clone();
}
@ -200,7 +200,7 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
bool leftVal = left.as<BoolLiteral>().value();
bool rightVal = right.as<BoolLiteral>().value();
bool result;
switch (op) {
switch (op.kind()) {
case Token::Kind::TK_LOGICALAND: result = leftVal && rightVal; break;
case Token::Kind::TK_LOGICALOR: result = leftVal || rightVal; break;
case Token::Kind::TK_LOGICALXOR: result = leftVal ^ rightVal; break;
@ -249,7 +249,7 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
if (left.is<IntLiteral>() && right.is<IntLiteral>()) {
SKSL_INT leftVal = left.as<IntLiteral>().value();
SKSL_INT rightVal = right.as<IntLiteral>().value();
switch (op) {
switch (op.kind()) {
case Token::Kind::TK_PLUS: return URESULT(Int, +);
case Token::Kind::TK_MINUS: return URESULT(Int, -);
case Token::Kind::TK_STAR: return URESULT(Int, *);
@ -298,7 +298,7 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
if (left.is<FloatLiteral>() && right.is<FloatLiteral>()) {
SKSL_FLOAT leftVal = left.as<FloatLiteral>().value();
SKSL_FLOAT rightVal = right.as<FloatLiteral>().value();
switch (op) {
switch (op.kind()) {
case Token::Kind::TK_PLUS: return RESULT(Float, +);
case Token::Kind::TK_MINUS: return RESULT(Float, -);
case Token::Kind::TK_STAR: return RESULT(Float, *);
@ -354,7 +354,7 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
// Perform constant folding on pairs of matrices.
if (leftType.isMatrix() && rightType.isMatrix()) {
bool equality;
switch (op) {
switch (op.kind()) {
case Token::Kind::TK_EQEQ:
equality = true;
break;

View File

@ -11,7 +11,7 @@
#include <memory>
#include "src/sksl/SkSLDefines.h"
#include "src/sksl/SkSLLexer.h"
#include "src/sksl/SkSLOperators.h"
namespace SkSL {
@ -41,14 +41,14 @@ public:
* Reports an error and returns true if op is a division / mod operator and right is zero or
* contains a zero element.
*/
static bool ErrorOnDivideByZero(const Context& context, int offset, Token::Kind op,
static bool ErrorOnDivideByZero(const Context& context, int offset, Operator op,
const Expression& right);
/** Simplifies the binary expression `left OP right`. Returns null if it can't be simplified. */
static std::unique_ptr<Expression> Simplify(const Context& context,
int offset,
const Expression& left,
Token::Kind op,
Operator op,
const Expression& right);
};

View File

@ -119,9 +119,9 @@ void DefinitionMap::addDefinitions(const Context& context, const BasicBlock::Nod
switch (expr->kind()) {
case Expression::Kind::kBinary: {
BinaryExpression* b = &expr->as<BinaryExpression>();
if (b->getOperator() == Token::Kind::TK_EQ) {
if (b->getOperator().kind() == Token::Kind::TK_EQ) {
this->addDefinition(context, b->left().get(), &b->right());
} else if (Operators::IsAssignment(b->getOperator())) {
} else if (b->getOperator().isAssignment()) {
this->addDefinition(
context, b->left().get(),
(std::unique_ptr<Expression>*)&context.fDefined_Expression);
@ -142,8 +142,8 @@ void DefinitionMap::addDefinitions(const Context& context, const BasicBlock::Nod
}
case Expression::Kind::kPrefix: {
const PrefixExpression* p = &expr->as<PrefixExpression>();
if (p->getOperator() == Token::Kind::TK_MINUSMINUS ||
p->getOperator() == Token::Kind::TK_PLUSPLUS) {
if (p->getOperator().kind() == Token::Kind::TK_MINUSMINUS ||
p->getOperator().kind() == Token::Kind::TK_PLUSPLUS) {
this->addDefinition(
context, p->operand().get(),
(std::unique_ptr<Expression>*)&context.fDefined_Expression);
@ -152,8 +152,8 @@ void DefinitionMap::addDefinitions(const Context& context, const BasicBlock::Nod
}
case Expression::Kind::kPostfix: {
const PostfixExpression* p = &expr->as<PostfixExpression>();
if (p->getOperator() == Token::Kind::TK_MINUSMINUS ||
p->getOperator() == Token::Kind::TK_PLUSPLUS) {
if (p->getOperator().kind() == Token::Kind::TK_MINUSMINUS ||
p->getOperator().kind() == Token::Kind::TK_PLUSPLUS) {
this->addDefinition(
context, p->operand().get(),
(std::unique_ptr<Expression>*)&context.fDefined_Expression);

View File

@ -262,7 +262,7 @@ void Dehydrator::write(const Expression* e) {
const BinaryExpression& b = e->as<BinaryExpression>();
this->writeCommand(Rehydrator::kBinary_Command);
this->write(b.left().get());
this->writeU8((int) b.getOperator());
this->writeU8((int) b.getOperator().kind());
this->write(b.right().get());
this->write(b.type());
break;
@ -332,14 +332,14 @@ void Dehydrator::write(const Expression* e) {
case Expression::Kind::kPostfix: {
const PostfixExpression& p = e->as<PostfixExpression>();
this->writeCommand(Rehydrator::kPostfix_Command);
this->writeU8((int) p.getOperator());
this->writeU8((int) p.getOperator().kind());
this->write(p.operand().get());
break;
}
case Expression::Kind::kPrefix: {
const PrefixExpression& p = e->as<PrefixExpression>();
this->writeCommand(Rehydrator::kPrefix_Command);
this->writeU8((int) p.getOperator());
this->writeU8((int) p.getOperator().kind());
this->write(p.operand().get());
break;
}

View File

@ -509,7 +509,7 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
arguments.size() == 2 &&
arguments[1]->kind() == Expression::Kind::kPrefix) {
const PrefixExpression& p = (PrefixExpression&) *arguments[1];
if (p.getOperator() == Token::Kind::TK_MINUS) {
if (p.getOperator().kind() == Token::Kind::TK_MINUS) {
this->write("atan(");
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write(", -1.0 * ");
@ -862,21 +862,21 @@ void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
Precedence parentPrecedence) {
const Expression& left = *b.left();
const Expression& right = *b.right();
Token::Kind op = b.getOperator();
Operator op = b.getOperator();
if (fProgram.fCaps->unfoldShortCircuitAsTernary() &&
(op == Token::Kind::TK_LOGICALAND || op == Token::Kind::TK_LOGICALOR)) {
(op.kind() == Token::Kind::TK_LOGICALAND || op.kind() == Token::Kind::TK_LOGICALOR)) {
this->writeShortCircuitWorkaroundExpression(b, parentPrecedence);
return;
}
Precedence precedence = Operators::GetBinaryPrecedence(op);
Precedence precedence = op.getBinaryPrecedence();
if (precedence >= parentPrecedence) {
this->write("(");
}
bool positionWorkaround = fProgramKind == Program::Kind::kVertex_Kind &&
Operators::IsAssignment(op) &&
left.kind() == Expression::Kind::kFieldAccess &&
is_sk_position((FieldAccess&) left) &&
op.isAssignment() &&
left.is<FieldAccess>() &&
is_sk_position(left.as<FieldAccess>()) &&
!right.containsRTAdjust() &&
!fProgram.fCaps->canUseFragCoord();
if (positionWorkaround) {
@ -884,7 +884,7 @@ void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
}
this->writeExpression(left, precedence);
this->write(" ");
this->write(Operators::OperatorName(op));
this->write(op.operatorName());
this->write(" ");
this->writeExpression(right, precedence);
if (positionWorkaround) {
@ -906,14 +906,14 @@ void GLSLCodeGenerator::writeShortCircuitWorkaroundExpression(const BinaryExpres
// a || b => a ? true : b
this->writeExpression(*b.left(), Precedence::kTernary);
this->write(" ? ");
if (b.getOperator() == Token::Kind::TK_LOGICALAND) {
if (b.getOperator().kind() == Token::Kind::TK_LOGICALAND) {
this->writeExpression(*b.right(), Precedence::kTernary);
} else {
BoolLiteral boolTrue(fContext, -1, true);
this->writeBoolLiteral(boolTrue);
}
this->write(" : ");
if (b.getOperator() == Token::Kind::TK_LOGICALAND) {
if (b.getOperator().kind() == Token::Kind::TK_LOGICALAND) {
BoolLiteral boolFalse(fContext, -1, false);
this->writeBoolLiteral(boolFalse);
} else {
@ -944,7 +944,7 @@ void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p,
if (Precedence::kPrefix >= parentPrecedence) {
this->write("(");
}
this->write(Operators::OperatorName(p.getOperator()));
this->write(p.getOperator().operatorName());
this->writeExpression(*p.operand(), Precedence::kPrefix);
if (Precedence::kPrefix >= parentPrecedence) {
this->write(")");
@ -957,7 +957,7 @@ void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p,
this->write("(");
}
this->writeExpression(*p.operand(), Precedence::kPostfix);
this->write(Operators::OperatorName(p.getOperator()));
this->write(p.getOperator().operatorName());
if (Precedence::kPostfix >= parentPrecedence) {
this->write(")");
}
@ -1332,7 +1332,7 @@ void GLSLCodeGenerator::writeForStatement(const ForStatement& f) {
if (f.test()) {
if (fProgram.fCaps->addAndTrueToLoopCondition()) {
std::unique_ptr<Expression> and_true(new BinaryExpression(
-1, f.test()->clone(), Token::Kind::TK_LOGICALAND,
/*offset=*/-1, f.test()->clone(), Token::Kind::TK_LOGICALAND,
std::make_unique<BoolLiteral>(fContext, -1, true),
fContext.fTypes.fBool.get()));
this->writeExpression(*and_true, Precedence::kTopLevel);

View File

@ -61,7 +61,7 @@ public:
bool generateCode() override;
protected:
using Precedence = Operators::Precedence;
using Precedence = Operator::Precedence;
void write(const char* s);

View File

@ -934,10 +934,12 @@ std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
// sk_Position.w);
SkASSERT(skPerVertex && fRTAdjust);
auto Ref = [](const Variable* var) -> std::unique_ptr<Expression> {
return std::make_unique<VariableReference>(-1, var, VariableReference::RefKind::kRead);
return std::make_unique<VariableReference>(/*offset=*/-1, var,
VariableReference::RefKind::kRead);
};
auto WRef = [](const Variable* var) -> std::unique_ptr<Expression> {
return std::make_unique<VariableReference>(-1, var, VariableReference::RefKind::kWrite);
return std::make_unique<VariableReference>(/*offset=*/-1, var,
VariableReference::RefKind::kWrite);
};
auto Field = [&](const Variable* var, int idx) -> std::unique_ptr<Expression> {
return std::make_unique<FieldAccess>(Ref(var), idx,
@ -957,8 +959,8 @@ std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
};
auto Op = [&](std::unique_ptr<Expression> left, Token::Kind op,
std::unique_ptr<Expression> right) -> std::unique_ptr<Expression> {
return std::make_unique<BinaryExpression>(-1, std::move(left), op, std::move(right),
fContext.fTypes.fFloat2.get());
return std::make_unique<BinaryExpression>(/*offset=*/-1, std::move(left), op,
std::move(right), fContext.fTypes.fFloat2.get());
};
static const ComponentArray kXYIndices{0, 1};
@ -1720,8 +1722,8 @@ std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr
return this->convertConstructor(offset, type.scalarTypeForLiteral(), std::move(args));
}
static bool is_matrix_multiply(const Type& left, Token::Kind op, const Type& right) {
if (op != Token::Kind::TK_STAR && op != Token::Kind::TK_STAREQ) {
static bool is_matrix_multiply(const Type& left, Operator op, const Type& right) {
if (op.kind() != Token::Kind::TK_STAR && op.kind() != Token::Kind::TK_STAREQ) {
return false;
}
if (left.isMatrix()) {
@ -1730,98 +1732,19 @@ static bool is_matrix_multiply(const Type& left, Token::Kind op, const Type& rig
return left.isVector() && right.isMatrix();
}
/**
* Defines the set of logical (comparison) operators.
*/
static bool op_is_logical(Token::Kind op) {
switch (op) {
case Token::Kind::TK_LT:
case Token::Kind::TK_GT:
case Token::Kind::TK_LTEQ:
case Token::Kind::TK_GTEQ:
return true;
default:
return false;
}
}
/**
* Defines the set of operators which are only valid on integral types.
*/
static bool op_only_valid_for_integral_types(Token::Kind op) {
switch (op) {
case Token::Kind::TK_SHL:
case Token::Kind::TK_SHR:
case Token::Kind::TK_BITWISEAND:
case Token::Kind::TK_BITWISEOR:
case Token::Kind::TK_BITWISEXOR:
case Token::Kind::TK_PERCENT:
case Token::Kind::TK_SHLEQ:
case Token::Kind::TK_SHREQ:
case Token::Kind::TK_BITWISEANDEQ:
case Token::Kind::TK_BITWISEOREQ:
case Token::Kind::TK_BITWISEXOREQ:
case Token::Kind::TK_PERCENTEQ:
return true;
default:
return false;
}
}
/**
* Defines the set of operators which perform vector/matrix math.
*/
static bool op_valid_for_matrix_or_vector(Token::Kind op) {
switch (op) {
case Token::Kind::TK_PLUS:
case Token::Kind::TK_MINUS:
case Token::Kind::TK_STAR:
case Token::Kind::TK_SLASH:
case Token::Kind::TK_PERCENT:
case Token::Kind::TK_SHL:
case Token::Kind::TK_SHR:
case Token::Kind::TK_BITWISEAND:
case Token::Kind::TK_BITWISEOR:
case Token::Kind::TK_BITWISEXOR:
case Token::Kind::TK_PLUSEQ:
case Token::Kind::TK_MINUSEQ:
case Token::Kind::TK_STAREQ:
case Token::Kind::TK_SLASHEQ:
case Token::Kind::TK_PERCENTEQ:
case Token::Kind::TK_SHLEQ:
case Token::Kind::TK_SHREQ:
case Token::Kind::TK_BITWISEANDEQ:
case Token::Kind::TK_BITWISEOREQ:
case Token::Kind::TK_BITWISEXOREQ:
return true;
default:
return false;
}
}
/*
* Defines the set of operators allowed by The OpenGL ES Shading Language 1.00, Section 5.1.
* The set of illegal (reserved) operators are the ones that only make sense with integral types.
* This is not a coincidence: It's because ES2 doesn't require 'int' to be anything but syntactic
* sugar for floats with truncation after each operation).
*/
static bool op_allowed_in_strict_es2_mode(Token::Kind op) {
return !op_only_valid_for_integral_types(op);
}
/**
* 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.
*/
static bool determine_binary_type(const Context& context,
bool allowNarrowing,
Token::Kind op,
Operator op,
const Type& left,
const Type& right,
const Type** outLeftType,
const Type** outRightType,
const Type** outResultType) {
switch (op) {
switch (op.kind()) {
case Token::Kind::TK_EQ: // left = right
*outLeftType = &left;
*outRightType = &left;
@ -1876,7 +1799,7 @@ static bool determine_binary_type(const Context& context,
return false;
}
bool isAssignment = Operators::IsAssignment(op);
bool isAssignment = op.isAssignment();
if (is_matrix_multiply(left, op, right)) { // left * right
// Determine final component type.
if (!determine_binary_type(context, allowNarrowing, op,
@ -1907,13 +1830,13 @@ static bool determine_binary_type(const Context& context,
}
bool leftIsVectorOrMatrix = left.isVector() || left.isMatrix();
bool validMatrixOrVectorOp = op_valid_for_matrix_or_vector(op);
bool validMatrixOrVectorOp = op.isValidForMatrixOrVector();
if (leftIsVectorOrMatrix && validMatrixOrVectorOp && right.isScalar()) {
if (determine_binary_type(context, allowNarrowing, op, left.componentType(), right,
outLeftType, outRightType, outResultType)) {
*outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
if (!op_is_logical(op)) {
if (!op.isLogical()) {
*outResultType = &(*outResultType)->toCompound(context, left.columns(),
left.rows());
}
@ -1928,7 +1851,7 @@ static bool determine_binary_type(const Context& context,
if (determine_binary_type(context, allowNarrowing, op, left, right.componentType(),
outLeftType, outRightType, outResultType)) {
*outRightType = &(*outRightType)->toCompound(context, right.columns(), right.rows());
if (!op_is_logical(op)) {
if (!op.isLogical()) {
*outResultType = &(*outResultType)->toCompound(context, right.columns(),
right.rows());
}
@ -1942,7 +1865,7 @@ static bool determine_binary_type(const Context& context,
: left.coercionCost(right);
if ((left.isScalar() && right.isScalar()) || (leftIsVectorOrMatrix && validMatrixOrVectorOp)) {
if (op_only_valid_for_integral_types(op)) {
if (op.isOnlyValidForIntegralTypes()) {
if (!leftComponentType.isInteger() || !rightComponentType.isInteger()) {
return false;
}
@ -1960,7 +1883,7 @@ static bool determine_binary_type(const Context& context,
} else {
return false;
}
if (op_is_logical(op)) {
if (op.isLogical()) {
*outResultType = context.fTypes.fBool.get();
}
return true;
@ -1975,17 +1898,17 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(const ASTNode&
if (!left) {
return nullptr;
}
Token::Kind op = expression.getToken().fKind;
std::unique_ptr<Expression> right = this->convertExpression(*(iter++));
if (!right) {
return nullptr;
}
return this->convertBinaryExpression(std::move(left), op, std::move(right));
return this->convertBinaryExpression(std::move(left), expression.getOperator(),
std::move(right));
}
std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
std::unique_ptr<Expression> left,
Token::Kind op,
Operator op,
std::unique_ptr<Expression> right) {
if (!left || !right) {
return nullptr;
@ -2006,13 +1929,13 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
} else {
rawRightType = &right->type();
}
if (this->strictES2Mode() && !op_allowed_in_strict_es2_mode(op)) {
this->errorReporter().error(
offset, String("operator '") + Operators::OperatorName(op) + "' is not allowed");
if (this->strictES2Mode() && !op.isAllowedInStrictES2Mode()) {
this->errorReporter().error(offset,
String("operator '") + op.operatorName() + "' is not allowed");
return nullptr;
}
bool isAssignment = Operators::IsAssignment(op);
if (isAssignment && !this->setRefKind(*left, op != Token::Kind::TK_EQ
bool isAssignment = op.isAssignment();
if (isAssignment && !this->setRefKind(*left, op.kind() != Token::Kind::TK_EQ
? VariableReference::RefKind::kReadWrite
: VariableReference::RefKind::kWrite)) {
return nullptr;
@ -2020,7 +1943,7 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
if (!determine_binary_type(fContext, fSettings->fAllowNarrowingConversions, op,
*rawLeftType, *rawRightType, &leftType, &rightType, &resultType)) {
this->errorReporter().error(
offset, String("type mismatch: '") + Operators::OperatorName(op) +
offset, String("type mismatch: '") + op.operatorName() +
"' cannot operate on '" + left->type().displayName() + "', '" +
right->type().displayName() + "'");
return nullptr;
@ -2441,13 +2364,13 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode&
if (!base) {
return nullptr;
}
return this->convertPrefixExpression(expression.getToken().fKind, std::move(base));
return this->convertPrefixExpression(expression.getOperator(), std::move(base));
}
std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(Token::Kind op,
std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(Operator op,
std::unique_ptr<Expression> base) {
const Type& baseType = base->type();
switch (op) {
switch (op.kind()) {
case Token::Kind::TK_PLUS:
if (!baseType.componentType().isNumber()) {
this->errorReporter().error(
@ -2477,7 +2400,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(Token::Kind op,
case Token::Kind::TK_PLUSPLUS:
if (!baseType.isNumber()) {
this->errorReporter().error(base->fOffset,
String("'") + Operators::OperatorName(op) +
String("'") + op.operatorName() +
"' cannot operate on '" + baseType.displayName() + "'");
return nullptr;
}
@ -2488,7 +2411,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(Token::Kind op,
case Token::Kind::TK_MINUSMINUS:
if (!baseType.isNumber()) {
this->errorReporter().error(base->fOffset,
String("'") + Operators::OperatorName(op) +
String("'") + op.operatorName() +
"' cannot operate on '" + baseType.displayName() + "'");
return nullptr;
}
@ -2499,7 +2422,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(Token::Kind op,
case Token::Kind::TK_LOGICALNOT:
if (!baseType.isBoolean()) {
this->errorReporter().error(base->fOffset,
String("'") + Operators::OperatorName(op) +
String("'") + op.operatorName() +
"' cannot operate on '" + baseType.displayName() + "'");
return nullptr;
}
@ -2512,14 +2435,14 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(Token::Kind op,
case Token::Kind::TK_BITWISENOT:
if (this->strictES2Mode()) {
// GLSL ES 1.00, Section 5.1
this->errorReporter().error(base->fOffset,
String("operator '") + Operators::OperatorName(op) +
"' is not allowed");
this->errorReporter().error(
base->fOffset,
String("operator '") + op.operatorName() + "' is not allowed");
return nullptr;
}
if (!baseType.isInteger()) {
this->errorReporter().error(base->fOffset,
String("'") + Operators::OperatorName(op) +
String("'") + op.operatorName() +
"' cannot operate on '" + baseType.displayName() + "'");
return nullptr;
}
@ -2918,15 +2841,15 @@ std::unique_ptr<Expression> IRGenerator::convertPostfixExpression(const ASTNode&
if (!base) {
return nullptr;
}
return this->convertPostfixExpression(std::move(base), expression.getToken().fKind);
return this->convertPostfixExpression(std::move(base), expression.getOperator());
}
std::unique_ptr<Expression> IRGenerator::convertPostfixExpression(std::unique_ptr<Expression> base,
Token::Kind op) {
Operator op) {
const Type& baseType = base->type();
if (!baseType.isNumber()) {
this->errorReporter().error(base->fOffset,
"'" + String(Operators::OperatorName(op)) +
"'" + String(op.operatorName()) +
"' cannot operate on '" + baseType.displayName() + "'");
return nullptr;
}

View File

@ -14,6 +14,7 @@
#include "src/sksl/SkSLASTFile.h"
#include "src/sksl/SkSLASTNode.h"
#include "src/sksl/SkSLErrorReporter.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/ir/SkSLBlock.h"
#include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLExtension.h"
@ -185,9 +186,9 @@ private:
int convertArraySize(const Type& type, int offset, const ASTNode& s);
int convertArraySize(const Type& type, std::unique_ptr<Expression> s);
bool containsConstantZero(Expression& expr);
bool dividesByZero(Token::Kind op, Expression& right);
bool dividesByZero(Operator op, Expression& right);
std::unique_ptr<Expression> convertBinaryExpression(std::unique_ptr<Expression> left,
Token::Kind op,
Operator op,
std::unique_ptr<Expression> right);
std::unique_ptr<Block> convertBlock(const ASTNode& block);
std::unique_ptr<Statement> convertBreak(const ASTNode& b);
@ -245,9 +246,9 @@ private:
std::unique_ptr<Expression> convertIndex(std::unique_ptr<Expression> base,
std::unique_ptr<Expression> index);
std::unique_ptr<Expression> convertPostfixExpression(std::unique_ptr<Expression> base,
Token::Kind op);
Operator op);
std::unique_ptr<Expression> convertPostfixExpression(const ASTNode& expression);
std::unique_ptr<Expression> convertPrefixExpression(Token::Kind op,
std::unique_ptr<Expression> convertPrefixExpression(Operator op,
std::unique_ptr<Expression> base);
std::unique_ptr<Expression> convertScopeExpression(const ASTNode& expression);
std::unique_ptr<StructDefinition> convertStructDefinition(const ASTNode& expression);

View File

@ -1004,9 +1004,9 @@ public:
// It is illegal for side-effects from x() or y() to occur. The simplest way to
// enforce that rule is to avoid inlining the right side entirely. However, it is
// safe for other types of binary expression to inline both sides.
Token::Kind op = binaryExpr.getOperator();
bool shortCircuitable = (op == Token::Kind::TK_LOGICALAND ||
op == Token::Kind::TK_LOGICALOR);
Operator op = binaryExpr.getOperator();
bool shortCircuitable = (op.kind() == Token::Kind::TK_LOGICALAND ||
op.kind() == Token::Kind::TK_LOGICALOR);
if (!shortCircuitable) {
this->visitExpression(&binaryExpr.right());
}

View File

@ -22,10 +22,10 @@
namespace SkSL {
const char* MetalCodeGenerator::OperatorName(Token::Kind op) {
switch (op) {
const char* MetalCodeGenerator::OperatorName(Operator op) {
switch (op.kind()) {
case Token::Kind::TK_LOGICALXOR: return "!=";
default: return Operators::OperatorName(op);
default: return op.operatorName();
}
}
@ -1257,10 +1257,10 @@ void MetalCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
const Expression& right = *b.right();
const Type& leftType = left.type();
const Type& rightType = right.type();
Token::Kind op = b.getOperator();
Precedence precedence = Operators::GetBinaryPrecedence(b.getOperator());
Operator op = b.getOperator();
Precedence precedence = op.getBinaryPrecedence();
bool needParens = precedence >= parentPrecedence;
switch (op) {
switch (op.kind()) {
case Token::Kind::TK_EQEQ:
if (leftType.isVector()) {
this->write("all");
@ -1280,16 +1280,16 @@ void MetalCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
this->write("(");
}
if (leftType.isMatrix() && rightType.isMatrix()) {
if (op == Token::Kind::TK_STAREQ) {
if (op.kind() == Token::Kind::TK_STAREQ) {
this->writeMatrixTimesEqualHelper(leftType, rightType, b.type());
} else if (op == Token::Kind::TK_EQEQ) {
} else if (op.kind() == Token::Kind::TK_EQEQ) {
this->writeMatrixEqualityHelper(leftType, rightType);
} else if (op == Token::Kind::TK_NEQ) {
} else if (op.kind() == Token::Kind::TK_NEQ) {
this->writeMatrixInequalityHelper(leftType, rightType);
}
}
this->writeExpression(left, precedence);
if (op != Token::Kind::TK_EQ && Operators::IsAssignment(op) &&
if (op.kind() != Token::Kind::TK_EQ && op.isAssignment() &&
left.kind() == Expression::Kind::kSwizzle && !left.hasSideEffects()) {
// This doesn't compile in Metal:
// float4 x = float4(1);

View File

@ -68,7 +68,7 @@ public:
bool generateCode() override;
protected:
using Precedence = Operators::Precedence;
using Precedence = Operator::Precedence;
typedef int Requirements;
static constexpr Requirements kNo_Requirements = 0;
@ -109,7 +109,7 @@ protected:
kTexture_IntrinsicKind,
};
static const char* OperatorName(Token::Kind op);
static const char* OperatorName(Operator op);
class GlobalStructVisitor;
void visitGlobalStruct(GlobalStructVisitor* visitor);

View File

@ -9,123 +9,222 @@
#include "src/sksl/SkSLOperators.h"
namespace SkSL {
namespace Operators {
Precedence GetBinaryPrecedence(Token::Kind op) {
switch (op) {
case Token::Kind::TK_STAR: // fall through
case Token::Kind::TK_SLASH: // fall through
case Token::Kind::TK_PERCENT: return Precedence::kMultiplicative;
case Token::Kind::TK_PLUS: // fall through
case Token::Kind::TK_MINUS: return Precedence::kAdditive;
case Token::Kind::TK_SHL: // fall through
case Token::Kind::TK_SHR: return Precedence::kShift;
case Token::Kind::TK_LT: // fall through
case Token::Kind::TK_GT: // fall through
case Token::Kind::TK_LTEQ: // fall through
case Token::Kind::TK_GTEQ: return Precedence::kRelational;
case Token::Kind::TK_EQEQ: // fall through
case Token::Kind::TK_NEQ: return Precedence::kEquality;
case Token::Kind::TK_BITWISEAND: return Precedence::kBitwiseAnd;
case Token::Kind::TK_BITWISEXOR: return Precedence::kBitwiseXor;
case Token::Kind::TK_BITWISEOR: return Precedence::kBitwiseOr;
case Token::Kind::TK_LOGICALAND: return Precedence::kLogicalAnd;
case Token::Kind::TK_LOGICALXOR: return Precedence::kLogicalXor;
case Token::Kind::TK_LOGICALOR: return Precedence::kLogicalOr;
case Token::Kind::TK_EQ: // fall through
case Token::Kind::TK_PLUSEQ: // fall through
case Token::Kind::TK_MINUSEQ: // fall through
case Token::Kind::TK_STAREQ: // fall through
case Token::Kind::TK_SLASHEQ: // fall through
case Token::Kind::TK_PERCENTEQ: // fall through
case Token::Kind::TK_SHLEQ: // fall through
case Token::Kind::TK_SHREQ: // fall through
case Token::Kind::TK_BITWISEANDEQ: // fall through
case Token::Kind::TK_BITWISEXOREQ: // fall through
case Token::Kind::TK_BITWISEOREQ: return Precedence::kAssignment;
case Token::Kind::TK_COMMA: return Precedence::kSequence;
Operator::Precedence Operator::getBinaryPrecedence() const {
switch (fKind) {
case Kind::TK_STAR: // fall through
case Kind::TK_SLASH: // fall through
case Kind::TK_PERCENT: return Precedence::kMultiplicative;
case Kind::TK_PLUS: // fall through
case Kind::TK_MINUS: return Precedence::kAdditive;
case Kind::TK_SHL: // fall through
case Kind::TK_SHR: return Precedence::kShift;
case Kind::TK_LT: // fall through
case Kind::TK_GT: // fall through
case Kind::TK_LTEQ: // fall through
case Kind::TK_GTEQ: return Precedence::kRelational;
case Kind::TK_EQEQ: // fall through
case Kind::TK_NEQ: return Precedence::kEquality;
case Kind::TK_BITWISEAND: return Precedence::kBitwiseAnd;
case Kind::TK_BITWISEXOR: return Precedence::kBitwiseXor;
case Kind::TK_BITWISEOR: return Precedence::kBitwiseOr;
case Kind::TK_LOGICALAND: return Precedence::kLogicalAnd;
case Kind::TK_LOGICALXOR: return Precedence::kLogicalXor;
case Kind::TK_LOGICALOR: return Precedence::kLogicalOr;
case Kind::TK_EQ: // fall through
case Kind::TK_PLUSEQ: // fall through
case Kind::TK_MINUSEQ: // fall through
case Kind::TK_STAREQ: // fall through
case Kind::TK_SLASHEQ: // fall through
case Kind::TK_PERCENTEQ: // fall through
case Kind::TK_SHLEQ: // fall through
case Kind::TK_SHREQ: // fall through
case Kind::TK_BITWISEANDEQ: // fall through
case Kind::TK_BITWISEXOREQ: // fall through
case Kind::TK_BITWISEOREQ: return Precedence::kAssignment;
case Kind::TK_COMMA: return Precedence::kSequence;
default: SK_ABORT("unsupported binary operator");
}
}
const char* OperatorName(Token::Kind op) {
switch (op) {
case Token::Kind::TK_PLUS: return "+";
case Token::Kind::TK_MINUS: return "-";
case Token::Kind::TK_STAR: return "*";
case Token::Kind::TK_SLASH: return "/";
case Token::Kind::TK_PERCENT: return "%";
case Token::Kind::TK_SHL: return "<<";
case Token::Kind::TK_SHR: return ">>";
case Token::Kind::TK_LOGICALNOT: return "!";
case Token::Kind::TK_LOGICALAND: return "&&";
case Token::Kind::TK_LOGICALOR: return "||";
case Token::Kind::TK_LOGICALXOR: return "^^";
case Token::Kind::TK_BITWISENOT: return "~";
case Token::Kind::TK_BITWISEAND: return "&";
case Token::Kind::TK_BITWISEOR: return "|";
case Token::Kind::TK_BITWISEXOR: return "^";
case Token::Kind::TK_EQ: return "=";
case Token::Kind::TK_EQEQ: return "==";
case Token::Kind::TK_NEQ: return "!=";
case Token::Kind::TK_LT: return "<";
case Token::Kind::TK_GT: return ">";
case Token::Kind::TK_LTEQ: return "<=";
case Token::Kind::TK_GTEQ: return ">=";
case Token::Kind::TK_PLUSEQ: return "+=";
case Token::Kind::TK_MINUSEQ: return "-=";
case Token::Kind::TK_STAREQ: return "*=";
case Token::Kind::TK_SLASHEQ: return "/=";
case Token::Kind::TK_PERCENTEQ: return "%=";
case Token::Kind::TK_SHLEQ: return "<<=";
case Token::Kind::TK_SHREQ: return ">>=";
case Token::Kind::TK_BITWISEANDEQ: return "&=";
case Token::Kind::TK_BITWISEOREQ: return "|=";
case Token::Kind::TK_BITWISEXOREQ: return "^=";
case Token::Kind::TK_PLUSPLUS: return "++";
case Token::Kind::TK_MINUSMINUS: return "--";
case Token::Kind::TK_COMMA: return ",";
default:
SK_ABORT("unsupported operator: %d\n", (int) op);
}
}
bool IsAssignment(Token::Kind op) {
switch (op) {
case Token::Kind::TK_EQ: // fall through
case Token::Kind::TK_PLUSEQ: // fall through
case Token::Kind::TK_MINUSEQ: // fall through
case Token::Kind::TK_STAREQ: // fall through
case Token::Kind::TK_SLASHEQ: // fall through
case Token::Kind::TK_PERCENTEQ: // fall through
case Token::Kind::TK_SHLEQ: // fall through
case Token::Kind::TK_SHREQ: // fall through
case Token::Kind::TK_BITWISEOREQ: // fall through
case Token::Kind::TK_BITWISEXOREQ: // fall through
case Token::Kind::TK_BITWISEANDEQ:
bool Operator::isOperator() const {
switch (this->kind()) {
case Kind::TK_PLUS:
case Kind::TK_MINUS:
case Kind::TK_STAR:
case Kind::TK_SLASH:
case Kind::TK_PERCENT:
case Kind::TK_SHL:
case Kind::TK_SHR:
case Kind::TK_LOGICALNOT:
case Kind::TK_LOGICALAND:
case Kind::TK_LOGICALOR:
case Kind::TK_LOGICALXOR:
case Kind::TK_BITWISENOT:
case Kind::TK_BITWISEAND:
case Kind::TK_BITWISEOR:
case Kind::TK_BITWISEXOR:
case Kind::TK_EQ:
case Kind::TK_EQEQ:
case Kind::TK_NEQ:
case Kind::TK_LT:
case Kind::TK_GT:
case Kind::TK_LTEQ:
case Kind::TK_GTEQ:
case Kind::TK_PLUSEQ:
case Kind::TK_MINUSEQ:
case Kind::TK_STAREQ:
case Kind::TK_SLASHEQ:
case Kind::TK_PERCENTEQ:
case Kind::TK_SHLEQ:
case Kind::TK_SHREQ:
case Kind::TK_BITWISEANDEQ:
case Kind::TK_BITWISEOREQ:
case Kind::TK_BITWISEXOREQ:
case Kind::TK_PLUSPLUS:
case Kind::TK_MINUSMINUS:
case Kind::TK_COMMA:
return true;
default:
return false;
}
}
Token::Kind RemoveAssignment(Token::Kind op) {
switch (op) {
case Token::Kind::TK_PLUSEQ: return Token::Kind::TK_PLUS;
case Token::Kind::TK_MINUSEQ: return Token::Kind::TK_MINUS;
case Token::Kind::TK_STAREQ: return Token::Kind::TK_STAR;
case Token::Kind::TK_SLASHEQ: return Token::Kind::TK_SLASH;
case Token::Kind::TK_PERCENTEQ: return Token::Kind::TK_PERCENT;
case Token::Kind::TK_SHLEQ: return Token::Kind::TK_SHL;
case Token::Kind::TK_SHREQ: return Token::Kind::TK_SHR;
case Token::Kind::TK_BITWISEOREQ: return Token::Kind::TK_BITWISEOR;
case Token::Kind::TK_BITWISEXOREQ: return Token::Kind::TK_BITWISEXOR;
case Token::Kind::TK_BITWISEANDEQ: return Token::Kind::TK_BITWISEAND;
default: return op;
const char* Operator::operatorName() const {
switch (fKind) {
case Kind::TK_PLUS: return "+";
case Kind::TK_MINUS: return "-";
case Kind::TK_STAR: return "*";
case Kind::TK_SLASH: return "/";
case Kind::TK_PERCENT: return "%";
case Kind::TK_SHL: return "<<";
case Kind::TK_SHR: return ">>";
case Kind::TK_LOGICALNOT: return "!";
case Kind::TK_LOGICALAND: return "&&";
case Kind::TK_LOGICALOR: return "||";
case Kind::TK_LOGICALXOR: return "^^";
case Kind::TK_BITWISENOT: return "~";
case Kind::TK_BITWISEAND: return "&";
case Kind::TK_BITWISEOR: return "|";
case Kind::TK_BITWISEXOR: return "^";
case Kind::TK_EQ: return "=";
case Kind::TK_EQEQ: return "==";
case Kind::TK_NEQ: return "!=";
case Kind::TK_LT: return "<";
case Kind::TK_GT: return ">";
case Kind::TK_LTEQ: return "<=";
case Kind::TK_GTEQ: return ">=";
case Kind::TK_PLUSEQ: return "+=";
case Kind::TK_MINUSEQ: return "-=";
case Kind::TK_STAREQ: return "*=";
case Kind::TK_SLASHEQ: return "/=";
case Kind::TK_PERCENTEQ: return "%=";
case Kind::TK_SHLEQ: return "<<=";
case Kind::TK_SHREQ: return ">>=";
case Kind::TK_BITWISEANDEQ: return "&=";
case Kind::TK_BITWISEOREQ: return "|=";
case Kind::TK_BITWISEXOREQ: return "^=";
case Kind::TK_PLUSPLUS: return "++";
case Kind::TK_MINUSMINUS: return "--";
case Kind::TK_COMMA: return ",";
default:
SK_ABORT("unsupported operator: %d\n", (int) fKind);
}
}
bool Operator::isAssignment() const {
switch (fKind) {
case Kind::TK_EQ: // fall through
case Kind::TK_PLUSEQ: // fall through
case Kind::TK_MINUSEQ: // fall through
case Kind::TK_STAREQ: // fall through
case Kind::TK_SLASHEQ: // fall through
case Kind::TK_PERCENTEQ: // fall through
case Kind::TK_SHLEQ: // fall through
case Kind::TK_SHREQ: // fall through
case Kind::TK_BITWISEOREQ: // fall through
case Kind::TK_BITWISEXOREQ: // fall through
case Kind::TK_BITWISEANDEQ:
return true;
default:
return false;
}
}
Operator Operator::removeAssignment() const {
switch (fKind) {
case Kind::TK_PLUSEQ: return Operator{Kind::TK_PLUS};
case Kind::TK_MINUSEQ: return Operator{Kind::TK_MINUS};
case Kind::TK_STAREQ: return Operator{Kind::TK_STAR};
case Kind::TK_SLASHEQ: return Operator{Kind::TK_SLASH};
case Kind::TK_PERCENTEQ: return Operator{Kind::TK_PERCENT};
case Kind::TK_SHLEQ: return Operator{Kind::TK_SHL};
case Kind::TK_SHREQ: return Operator{Kind::TK_SHR};
case Kind::TK_BITWISEOREQ: return Operator{Kind::TK_BITWISEOR};
case Kind::TK_BITWISEXOREQ: return Operator{Kind::TK_BITWISEXOR};
case Kind::TK_BITWISEANDEQ: return Operator{Kind::TK_BITWISEAND};
default: return *this;
}
}
bool Operator::isLogical() const {
switch (kind()) {
case Token::Kind::TK_LT:
case Token::Kind::TK_GT:
case Token::Kind::TK_LTEQ:
case Token::Kind::TK_GTEQ:
return true;
default:
return false;
}
}
bool Operator::isOnlyValidForIntegralTypes() const {
switch (kind()) {
case Token::Kind::TK_SHL:
case Token::Kind::TK_SHR:
case Token::Kind::TK_BITWISEAND:
case Token::Kind::TK_BITWISEOR:
case Token::Kind::TK_BITWISEXOR:
case Token::Kind::TK_PERCENT:
case Token::Kind::TK_SHLEQ:
case Token::Kind::TK_SHREQ:
case Token::Kind::TK_BITWISEANDEQ:
case Token::Kind::TK_BITWISEOREQ:
case Token::Kind::TK_BITWISEXOREQ:
case Token::Kind::TK_PERCENTEQ:
return true;
default:
return false;
}
}
bool Operator::isValidForMatrixOrVector() const {
switch (kind()) {
case Token::Kind::TK_PLUS:
case Token::Kind::TK_MINUS:
case Token::Kind::TK_STAR:
case Token::Kind::TK_SLASH:
case Token::Kind::TK_PERCENT:
case Token::Kind::TK_SHL:
case Token::Kind::TK_SHR:
case Token::Kind::TK_BITWISEAND:
case Token::Kind::TK_BITWISEOR:
case Token::Kind::TK_BITWISEXOR:
case Token::Kind::TK_PLUSEQ:
case Token::Kind::TK_MINUSEQ:
case Token::Kind::TK_STAREQ:
case Token::Kind::TK_SLASHEQ:
case Token::Kind::TK_PERCENTEQ:
case Token::Kind::TK_SHLEQ:
case Token::Kind::TK_SHREQ:
case Token::Kind::TK_BITWISEANDEQ:
case Token::Kind::TK_BITWISEOREQ:
case Token::Kind::TK_BITWISEXOREQ:
return true;
default:
return false;
}
}
} // namespace Operators
} // namespace SkSL

View File

@ -8,10 +8,19 @@
#ifndef SKSL_OPERATORS
#define SKSL_OPERATORS
#include "src/sksl/SkSLDefines.h"
#include "src/sksl/SkSLLexer.h"
namespace SkSL {
namespace Operators {
class Operator {
public:
using Kind = Token::Kind;
// Allow implicit conversion from Token::Kind, since this is just a utility wrapper on top.
Operator(Token::Kind t) : fKind(t) {
SkASSERTF(this->isOperator(), "token-kind %d is not an operator", fKind);
}
enum class Precedence {
kParentheses = 1,
@ -34,18 +43,53 @@ namespace Operators {
kTopLevel = kSequence
};
Precedence GetBinaryPrecedence(Token::Kind op);
Token::Kind kind() const { return fKind; }
const char* OperatorName(Token::Kind op);
Precedence getBinaryPrecedence() const;
const char* operatorName() const;
// Returns true if op is '=' or any compound assignment operator ('+=', '-=', etc.)
bool IsAssignment(Token::Kind op);
bool isAssignment() const;
// Given a compound assignment operator, returns the non-assignment version of the operator
// (e.g. '+=' becomes '+')
Token::Kind RemoveAssignment(Token::Kind op);
Operator removeAssignment() const;
/**
* Defines the set of logical (comparison) operators:
* < <= > >=
*/
bool isLogical() const;
/**
* Defines the set of operators which are only valid on integral types:
* << <<= >> >>= & &= | |= ^ ^= % %=
*/
bool isOnlyValidForIntegralTypes() const;
/**
* Defines the set of operators which perform vector/matrix math.
* + += - -= * *= / /= % %= << <<= >> >>= & &= | |= ^ ^=
*/
bool isValidForMatrixOrVector() const;
/*
* Defines the set of operators allowed by The OpenGL ES Shading Language 1.00, Section 5.1.
* The set of illegal (reserved) operators are the ones that only make sense with integral
* types. This is not a coincidence: It's because ES2 doesn't require 'int' to be anything but
* syntactic sugar for floats with truncation after each operation.
*/
bool isAllowedInStrictES2Mode() const {
return !this->isOnlyValidForIntegralTypes();
}
private:
bool isOperator() const;
Kind fKind;
};
} // namespace Operators
} // namespace SkSL
#endif

View File

@ -1610,7 +1610,8 @@ ASTNode::ID Parser::expression() {
if (!right) {
return ASTNode::ID::Invalid();
}
ASTNode::ID newResult = this->createNode(t.fOffset, ASTNode::Kind::kBinary, std::move(t));
ASTNode::ID newResult = this->createNode(t.fOffset, ASTNode::Kind::kBinary,
Operator(t.fKind));
getNode(newResult).addChild(result);
getNode(newResult).addChild(right);
result = newResult;
@ -1650,7 +1651,7 @@ ASTNode::ID Parser::assignmentExpression() {
return ASTNode::ID::Invalid();
}
ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
ASTNode::Kind::kBinary, std::move(t));
ASTNode::Kind::kBinary, Operator(t.fKind));
getNode(newResult).addChild(result);
getNode(newResult).addChild(right);
result = newResult;
@ -1710,7 +1711,7 @@ ASTNode::ID Parser::logicalOrExpression() {
return ASTNode::ID::Invalid();
}
ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
std::move(t));
Operator(t.fKind));
getNode(newResult).addChild(result);
getNode(newResult).addChild(right);
result = newResult;
@ -1735,7 +1736,7 @@ ASTNode::ID Parser::logicalXorExpression() {
return ASTNode::ID::Invalid();
}
ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
std::move(t));
Operator(t.fKind));
getNode(newResult).addChild(result);
getNode(newResult).addChild(right);
result = newResult;
@ -1760,7 +1761,7 @@ ASTNode::ID Parser::logicalAndExpression() {
return ASTNode::ID::Invalid();
}
ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
std::move(t));
Operator(t.fKind));
getNode(newResult).addChild(result);
getNode(newResult).addChild(right);
result = newResult;
@ -1784,8 +1785,8 @@ ASTNode::ID Parser::bitwiseOrExpression() {
if (!right) {
return ASTNode::ID::Invalid();
}
ASTNode::ID newResult =
this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
Operator(t.fKind));
getNode(newResult).addChild(result);
getNode(newResult).addChild(right);
result = newResult;
@ -1809,7 +1810,8 @@ ASTNode::ID Parser::bitwiseXorExpression() {
if (!right) {
return ASTNode::ID::Invalid();
}
ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
Operator(t.fKind));
getNode(newResult).addChild(result);
getNode(newResult).addChild(right);
result = newResult;
@ -1834,7 +1836,7 @@ ASTNode::ID Parser::bitwiseAndExpression() {
return ASTNode::ID::Invalid();
}
ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
std::move(t));
Operator(t.fKind));
getNode(newResult).addChild(result);
getNode(newResult).addChild(right);
result = newResult;
@ -1862,7 +1864,7 @@ ASTNode::ID Parser::equalityExpression() {
return ASTNode::ID::Invalid();
}
ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
ASTNode::Kind::kBinary, std::move(t));
ASTNode::Kind::kBinary, Operator(t.fKind));
getNode(newResult).addChild(result);
getNode(newResult).addChild(right);
result = newResult;
@ -1896,7 +1898,7 @@ ASTNode::ID Parser::relationalExpression() {
return ASTNode::ID::Invalid();
}
ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
ASTNode::Kind::kBinary, std::move(t));
ASTNode::Kind::kBinary, Operator(t.fKind));
getNode(newResult).addChild(result);
getNode(newResult).addChild(right);
result = newResult;
@ -1928,7 +1930,7 @@ ASTNode::ID Parser::shiftExpression() {
return ASTNode::ID::Invalid();
}
ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
ASTNode::Kind::kBinary, std::move(t));
ASTNode::Kind::kBinary, Operator(t.fKind));
getNode(newResult).addChild(result);
getNode(newResult).addChild(right);
result = newResult;
@ -1960,7 +1962,7 @@ ASTNode::ID Parser::additiveExpression() {
return ASTNode::ID::Invalid();
}
ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
ASTNode::Kind::kBinary, std::move(t));
ASTNode::Kind::kBinary, Operator(t.fKind));
getNode(newResult).addChild(result);
getNode(newResult).addChild(right);
result = newResult;
@ -1993,7 +1995,7 @@ ASTNode::ID Parser::multiplicativeExpression() {
return ASTNode::ID::Invalid();
}
ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
ASTNode::Kind::kBinary, std::move(t));
ASTNode::Kind::kBinary, Operator(t.fKind));
getNode(newResult).addChild(result);
getNode(newResult).addChild(right);
result = newResult;
@ -2023,7 +2025,8 @@ ASTNode::ID Parser::unaryExpression() {
if (!expr) {
return ASTNode::ID::Invalid();
}
ASTNode::ID result = this->createNode(t.fOffset, ASTNode::Kind::kPrefix, std::move(t));
ASTNode::ID result = this->createNode(t.fOffset, ASTNode::Kind::kPrefix,
Operator(t.fKind));
getNode(result).addChild(expr);
return result;
}
@ -2160,7 +2163,8 @@ ASTNode::ID Parser::suffix(ASTNode::ID base) {
}
case Token::Kind::TK_PLUSPLUS: // fall through
case Token::Kind::TK_MINUSMINUS: {
ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kPostfix, next);
ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kPostfix,
Operator(next.fKind));
getNode(result).addChild(base);
return result;
}

View File

@ -50,7 +50,7 @@ public:
void generateCode();
private:
using Precedence = Operators::Precedence;
using Precedence = Operator::Precedence;
void write(const char* s);
void writeLine(const char* s = nullptr);
@ -476,15 +476,15 @@ void PipelineStageCodeGenerator::writeBinaryExpression(const BinaryExpression& b
Precedence parentPrecedence) {
const Expression& left = *b.left();
const Expression& right = *b.right();
Token::Kind op = b.getOperator();
Operator op = b.getOperator();
Precedence precedence = Operators::GetBinaryPrecedence(op);
Precedence precedence = op.getBinaryPrecedence();
if (precedence >= parentPrecedence) {
this->write("(");
}
this->writeExpression(left, precedence);
this->write(" ");
this->write(Operators::OperatorName(op));
this->write(op.operatorName());
this->write(" ");
this->writeExpression(right, precedence);
if (precedence >= parentPrecedence) {
@ -512,7 +512,7 @@ void PipelineStageCodeGenerator::writePrefixExpression(const PrefixExpression& p
if (Precedence::kPrefix >= parentPrecedence) {
this->write("(");
}
this->write(Operators::OperatorName(p.getOperator()));
this->write(p.getOperator().operatorName());
this->writeExpression(*p.operand(), Precedence::kPrefix);
if (Precedence::kPrefix >= parentPrecedence) {
this->write(")");
@ -525,7 +525,7 @@ void PipelineStageCodeGenerator::writePostfixExpression(const PostfixExpression&
this->write("(");
}
this->writeExpression(*p.operand(), Precedence::kPostfix);
this->write(Operators::OperatorName(p.getOperator()));
this->write(p.getOperator().operatorName());
if (Precedence::kPostfix >= parentPrecedence) {
this->write(")");
}

View File

@ -2233,11 +2233,11 @@ static std::unique_ptr<Expression> create_literal_1(const Context& context, cons
}
}
SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs, Token::Kind op,
SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs, Operator op,
const Type& rightType, SpvId rhs,
const Type& resultType, OutputStream& out) {
// The comma operator ignores the type of the left-hand side entirely.
if (op == Token::Kind::TK_COMMA) {
if (op.kind() == Token::Kind::TK_COMMA) {
return rhs;
}
// overall type we are operating on: float2, int, uint4...
@ -2246,14 +2246,14 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
// handling in SPIR-V
if (this->getActualType(leftType) != this->getActualType(rightType)) {
if (leftType.isVector() && rightType.isNumber()) {
if (op == Token::Kind::TK_SLASH) {
if (op.kind() == Token::Kind::TK_SLASH) {
SpvId one = this->writeExpression(*create_literal_1(fContext, rightType), out);
SpvId inverse = this->nextId();
this->writeInstruction(SpvOpFDiv, this->getType(rightType), inverse, one, rhs, out);
rhs = inverse;
op = Token::Kind::TK_STAR;
}
if (op == Token::Kind::TK_STAR) {
if (op.kind() == Token::Kind::TK_STAR) {
SpvId result = this->nextId();
this->writeInstruction(SpvOpVectorTimesScalar, this->getType(resultType),
result, lhs, rhs, out);
@ -2271,7 +2271,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
rhs = vec;
operandType = &leftType;
} else if (rightType.isVector() && leftType.isNumber()) {
if (op == Token::Kind::TK_STAR) {
if (op.kind() == Token::Kind::TK_STAR) {
SpvId result = this->nextId();
this->writeInstruction(SpvOpVectorTimesScalar, this->getType(resultType),
result, rhs, lhs, out);
@ -2320,7 +2320,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
operandType = &this->getActualType(leftType);
SkASSERT(*operandType == this->getActualType(rightType));
}
switch (op) {
switch (op.kind()) {
case Token::Kind::TK_EQEQ: {
if (operandType->isMatrix()) {
return this->writeMatrixComparison(*operandType, lhs, rhs, SpvOpFOrdEqual,
@ -2438,9 +2438,9 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, OutputStream& out) {
const Expression& left = *b.left();
const Expression& right = *b.right();
Token::Kind op = b.getOperator();
Operator op = b.getOperator();
// handle cases where we don't necessarily evaluate both LHS and RHS
switch (op) {
switch (op.kind()) {
case Token::Kind::TK_EQ: {
SpvId rhs = this->writeExpression(right, out);
this->getLValue(left, out)->store(rhs, out);
@ -2456,7 +2456,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, Outpu
std::unique_ptr<LValue> lvalue;
SpvId lhs;
if (Operators::IsAssignment(op)) {
if (op.isAssignment()) {
lvalue = this->getLValue(left, out);
lhs = lvalue->load(out);
} else {
@ -2464,7 +2464,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, Outpu
lhs = this->writeExpression(left, out);
}
SpvId rhs = this->writeExpression(right, out);
SpvId result = this->writeBinaryExpression(left.type(), lhs, Operators::RemoveAssignment(op),
SpvId result = this->writeBinaryExpression(left.type(), lhs, op.removeAssignment(),
right.type(), rhs, b.type(), out);
if (lvalue) {
lvalue->store(result, out);
@ -2473,7 +2473,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, Outpu
}
SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, OutputStream& out) {
SkASSERT(a.getOperator() == Token::Kind::TK_LOGICALAND);
SkASSERT(a.getOperator().kind() == Token::Kind::TK_LOGICALAND);
BoolLiteral falseLiteral(fContext, -1, false);
SpvId falseConstant = this->writeBoolLiteral(falseLiteral);
SpvId lhs = this->writeExpression(*a.left(), out);
@ -2494,7 +2494,7 @@ SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, OutputStrea
}
SpvId SPIRVCodeGenerator::writeLogicalOr(const BinaryExpression& o, OutputStream& out) {
SkASSERT(o.getOperator() == Token::Kind::TK_LOGICALOR);
SkASSERT(o.getOperator().kind() == Token::Kind::TK_LOGICALOR);
BoolLiteral trueLiteral(fContext, -1, true);
SpvId trueConstant = this->writeBoolLiteral(trueLiteral);
SpvId lhs = this->writeExpression(*o.left(), out);
@ -2553,7 +2553,7 @@ SpvId SPIRVCodeGenerator::writeTernaryExpression(const TernaryExpression& t, Out
SpvId SPIRVCodeGenerator::writePrefixExpression(const PrefixExpression& p, OutputStream& out) {
const Type& type = p.type();
if (p.getOperator() == Token::Kind::TK_MINUS) {
if (p.getOperator().kind() == Token::Kind::TK_MINUS) {
SpvId result = this->nextId();
SpvId typeId = this->getType(type);
SpvId expr = this->writeExpression(*p.operand(), out);
@ -2567,7 +2567,7 @@ SpvId SPIRVCodeGenerator::writePrefixExpression(const PrefixExpression& p, Outpu
this->writePrecisionModifier(type, result);
return result;
}
switch (p.getOperator()) {
switch (p.getOperator().kind()) {
case Token::Kind::TK_PLUS:
return this->writeExpression(*p.operand(), out);
case Token::Kind::TK_PLUSPLUS: {
@ -2611,7 +2611,7 @@ SpvId SPIRVCodeGenerator::writePostfixExpression(const PostfixExpression& p, Out
std::unique_ptr<LValue> lv = this->getLValue(*p.operand(), out);
SpvId result = lv->load(out);
SpvId one = this->writeExpression(*create_literal_1(fContext, type), out);
switch (p.getOperator()) {
switch (p.getOperator().kind()) {
case Token::Kind::TK_PLUSPLUS: {
SpvId temp = this->writeBinaryOperation(type, type, result, one, SpvOpFAdd,
SpvOpIAdd, SpvOpIAdd, SpvOpUndef, out);

View File

@ -307,7 +307,7 @@ private:
SpvId writeBinaryOperation(const BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt,
SpvOp_ ifUInt, OutputStream& out);
SpvId writeBinaryExpression(const Type& leftType, SpvId lhs, Token::Kind op,
SpvId writeBinaryExpression(const Type& leftType, SpvId lhs, Operator op,
const Type& rightType, SpvId rhs, const Type& resultType,
OutputStream& out);

View File

@ -529,8 +529,8 @@ size_t SkVMGenerator::getSlot(const Variable& v) {
Value SkVMGenerator::writeBinaryExpression(const BinaryExpression& b) {
const Expression& left = *b.left();
const Expression& right = *b.right();
Token::Kind op = b.getOperator();
if (op == Token::Kind::TK_EQ) {
Operator op = b.getOperator();
if (op.kind() == Token::Kind::TK_EQ) {
return this->writeStore(left, this->writeExpression(right));
}
@ -538,14 +538,14 @@ Value SkVMGenerator::writeBinaryExpression(const BinaryExpression& b) {
const Type& rType = right.type();
bool lVecOrMtx = (lType.isVector() || lType.isMatrix());
bool rVecOrMtx = (rType.isVector() || rType.isMatrix());
bool isAssignment = Operators::IsAssignment(op);
bool isAssignment = op.isAssignment();
if (isAssignment) {
op = Operators::RemoveAssignment(op);
op = op.removeAssignment();
}
Type::NumberKind nk = base_number_kind(lType);
// A few ops require special treatment:
switch (op) {
switch (op.kind()) {
case Token::Kind::TK_LOGICALAND: {
SkASSERT(!isAssignment);
SkASSERT(nk == Type::NumberKind::kBoolean);
@ -576,7 +576,7 @@ Value SkVMGenerator::writeBinaryExpression(const BinaryExpression& b) {
rVal = this->writeExpression(right);
// Special case for M*V, V*M, M*M (but not V*V!)
if (op == Token::Kind::TK_STAR
if (op.kind() == Token::Kind::TK_STAR
&& lVecOrMtx && rVecOrMtx && !(lType.isVector() && rType.isVector())) {
int rCols = rType.columns(),
rRows = rType.rows(),
@ -624,7 +624,7 @@ Value SkVMGenerator::writeBinaryExpression(const BinaryExpression& b) {
return skvm::F32{};
};
switch (op) {
switch (op.kind()) {
case Token::Kind::TK_EQEQ: {
SkASSERT(!isAssignment);
Value cmp = binary([](skvm::F32 x, skvm::F32 y) { return x == y; },
@ -1311,10 +1311,10 @@ Value SkVMGenerator::writeExternalFunctionCall(const ExternalFunctionCall& c) {
Value SkVMGenerator::writePrefixExpression(const PrefixExpression& p) {
Value val = this->writeExpression(*p.operand());
switch (p.getOperator()) {
switch (p.getOperator().kind()) {
case Token::Kind::TK_PLUSPLUS:
case Token::Kind::TK_MINUSMINUS: {
bool incr = p.getOperator() == Token::Kind::TK_PLUSPLUS;
bool incr = p.getOperator().kind() == Token::Kind::TK_PLUSPLUS;
switch (base_number_kind(p.type())) {
case Type::NumberKind::kFloat:
@ -1350,13 +1350,13 @@ Value SkVMGenerator::writePrefixExpression(const PrefixExpression& p) {
}
Value SkVMGenerator::writePostfixExpression(const PostfixExpression& p) {
switch (p.getOperator()) {
switch (p.getOperator().kind()) {
case Token::Kind::TK_PLUSPLUS:
case Token::Kind::TK_MINUSMINUS: {
Value old = this->writeExpression(*p.operand()),
val = old;
SkASSERT(val.slots() == 1);
bool incr = p.getOperator() == Token::Kind::TK_PLUSPLUS;
bool incr = p.getOperator().kind() == Token::Kind::TK_PLUSPLUS;
switch (base_number_kind(p.type())) {
case Type::NumberKind::kFloat:

View File

@ -104,7 +104,7 @@ DSLExpression DSLWriter::Construct(const SkSL::Type& type, std::vector<DSLExpres
std::move(args)));
}
DSLExpression DSLWriter::ConvertBinary(std::unique_ptr<Expression> left, Token::Kind op,
DSLExpression DSLWriter::ConvertBinary(std::unique_ptr<Expression> left, Operator op,
std::unique_ptr<Expression> right) {
return IRGenerator().convertBinaryExpression(std::move(left), op, std::move(right));
}
@ -118,11 +118,11 @@ DSLExpression DSLWriter::ConvertIndex(std::unique_ptr<Expression> base,
return IRGenerator().convertIndex(std::move(base), std::move(index));
}
DSLExpression DSLWriter::ConvertPostfix(std::unique_ptr<Expression> expr, Token::Kind op) {
DSLExpression DSLWriter::ConvertPostfix(std::unique_ptr<Expression> expr, Operator op) {
return IRGenerator().convertPostfixExpression(std::move(expr), op);
}
DSLExpression DSLWriter::ConvertPrefix(Token::Kind op, std::unique_ptr<Expression> expr) {
DSLExpression DSLWriter::ConvertPrefix(Operator op, std::unique_ptr<Expression> expr) {
return IRGenerator().convertPrefixExpression(op, std::move(expr));
}

View File

@ -9,6 +9,7 @@
#define SKSL_DSLWRITER
#include "src/sksl/SkSLMangler.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/dsl/DSLExpression.h"
#include "src/sksl/dsl/DSLStatement.h"
#include "src/sksl/ir/SkSLExpressionStatement.h"
@ -133,7 +134,7 @@ public:
static DSLExpression Construct(const SkSL::Type& type, std::vector<DSLExpression> rawArgs);
static DSLExpression ConvertBinary(std::unique_ptr<Expression> left, Token::Kind op,
static DSLExpression ConvertBinary(std::unique_ptr<Expression> left, Operator op,
std::unique_ptr<Expression> right);
static DSLExpression ConvertField(std::unique_ptr<Expression> base, const char* name);
@ -141,9 +142,9 @@ public:
static DSLExpression ConvertIndex(std::unique_ptr<Expression> base,
std::unique_ptr<Expression> index);
static DSLExpression ConvertPostfix(std::unique_ptr<Expression> expr, Token::Kind op);
static DSLExpression ConvertPostfix(std::unique_ptr<Expression> expr, Operator op);
static DSLExpression ConvertPrefix(Token::Kind op, std::unique_ptr<Expression> expr);
static DSLExpression ConvertPrefix(Operator op, std::unique_ptr<Expression> expr);
static DSLStatement ConvertSwitch(std::unique_ptr<Expression> value,
ExpressionArray caseValues,

View File

@ -49,14 +49,14 @@ class BinaryExpression final : public Expression {
public:
static constexpr Kind kExpressionKind = Kind::kBinary;
BinaryExpression(int offset, std::unique_ptr<Expression> left, Token::Kind op,
BinaryExpression(int offset, std::unique_ptr<Expression> left, Operator op,
std::unique_ptr<Expression> right, const Type* type)
: INHERITED(offset, kExpressionKind, type)
, fLeft(std::move(left))
, fOperator(op)
, fRight(std::move(right)) {
// If we are assigning to a VariableReference, ensure that it is set to Write or ReadWrite
SkASSERT(!Operators::IsAssignment(op) || check_ref(*this->left()));
SkASSERT(!op.isAssignment() || check_ref(*this->left()));
}
std::unique_ptr<Expression>& left() {
@ -75,7 +75,7 @@ public:
return fRight;
}
Token::Kind getOperator() const {
Operator getOperator() const {
return fOperator;
}
@ -90,7 +90,7 @@ public:
}
bool hasProperty(Property property) const override {
if (property == Property::kSideEffects && Operators::IsAssignment(this->getOperator())) {
if (property == Property::kSideEffects && this->getOperator().isAssignment()) {
return true;
}
return this->left()->hasProperty(property) || this->right()->hasProperty(property);
@ -106,13 +106,13 @@ public:
String description() const override {
return "(" + this->left()->description() + " " +
Operators::OperatorName(this->getOperator()) + " " + this->right()->description() +
this->getOperator().operatorName() + " " + this->right()->description() +
")";
}
private:
std::unique_ptr<Expression> fLeft;
Token::Kind fOperator;
Operator fOperator;
std::unique_ptr<Expression> fRight;
using INHERITED = Expression;

View File

@ -21,12 +21,12 @@ class PostfixExpression final : public Expression {
public:
static constexpr Kind kExpressionKind = Kind::kPostfix;
PostfixExpression(std::unique_ptr<Expression> operand, Token::Kind op)
PostfixExpression(std::unique_ptr<Expression> operand, Operator op)
: INHERITED(operand->fOffset, kExpressionKind, &operand->type())
, fOperand(std::move(operand))
, fOperator(op) {}
Token::Kind getOperator() const {
Operator getOperator() const {
return fOperator;
}
@ -51,12 +51,12 @@ public:
}
String description() const override {
return this->operand()->description() + Operators::OperatorName(this->getOperator());
return this->operand()->description() + this->getOperator().operatorName();
}
private:
std::unique_ptr<Expression> fOperand;
Token::Kind fOperator;
Operator fOperator;
using INHERITED = Expression;
};

View File

@ -38,7 +38,7 @@ static std::unique_ptr<Expression> negate_operand(const Expression& operand) {
std::unique_ptr<Expression> PrefixExpression::constantPropagate(const IRGenerator& irGenerator,
const DefinitionMap& definitions) {
if (this->operand()->isCompileTimeConstant()) {
if (this->getOperator() == Token::Kind::TK_MINUS) {
if (this->getOperator().kind() == Token::Kind::TK_MINUS) {
// Constant-propagate negation onto compile-time constants.
switch (this->operand()->kind()) {
case Expression::Kind::kFloatLiteral:
@ -66,7 +66,7 @@ std::unique_ptr<Expression> PrefixExpression::constantPropagate(const IRGenerato
default:
break;
}
} else if (this->getOperator() == Token::Kind::TK_LOGICALNOT) {
} else if (this->getOperator().kind() == Token::Kind::TK_LOGICALNOT) {
if (this->operand()->is<BoolLiteral>()) {
// Convert !boolLiteral(true) to boolLiteral(false).
const BoolLiteral& b = this->operand()->as<BoolLiteral>();

View File

@ -22,12 +22,12 @@ class PrefixExpression final : public Expression {
public:
static constexpr Kind kExpressionKind = Kind::kPrefix;
PrefixExpression(Token::Kind op, std::unique_ptr<Expression> operand)
PrefixExpression(Operator op, std::unique_ptr<Expression> operand)
: INHERITED(operand->fOffset, kExpressionKind, &operand->type())
, fOperator(op)
, fOperand(std::move(operand)) {}
Token::Kind getOperator() const {
Operator getOperator() const {
return fOperator;
}
@ -41,8 +41,8 @@ public:
bool hasProperty(Property property) const override {
if (property == Property::kSideEffects &&
(this->getOperator() == Token::Kind::TK_PLUSPLUS ||
this->getOperator() == Token::Kind::TK_MINUSMINUS)) {
(this->getOperator().kind() == Token::Kind::TK_PLUSPLUS ||
this->getOperator().kind() == Token::Kind::TK_MINUSMINUS)) {
return true;
}
return this->operand()->hasProperty(property);
@ -57,11 +57,11 @@ public:
}
String description() const override {
return Operators::OperatorName(this->getOperator()) + this->operand()->description();
return this->getOperator().operatorName() + this->operand()->description();
}
private:
Token::Kind fOperator;
Operator fOperator;
std::unique_ptr<Expression> fOperand;
using INHERITED = Expression;