Revert "skslc switch support"
This reverts commit 2b1e468dab
.
Reason for revert: bot breakage
Original change's description:
> skslc switch support
>
> BUG=skia:
>
> Change-Id: Ida7f9e80139aa1e4f43804cafbcac640e47fab25
> Reviewed-on: https://skia-review.googlesource.com/8771
> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
> Reviewed-by: Ben Wagner <benjaminwagner@google.com>
>
TBR=benjaminwagner@google.com,ethannicholas@google.com,reviews@skia.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=skia:
Change-Id: Iaaa35d10a15704279c6883d4d68f6d4ad5078320
Reviewed-on: https://skia-review.googlesource.com/8792
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
d196cbe9c2
commit
7d975fc200
@ -20,7 +20,6 @@
|
||||
#include "ir/SkSLPrefixExpression.h"
|
||||
#include "ir/SkSLReturnStatement.h"
|
||||
#include "ir/SkSLSwizzle.h"
|
||||
#include "ir/SkSLSwitchStatement.h"
|
||||
#include "ir/SkSLTernaryExpression.h"
|
||||
#include "ir/SkSLVarDeclarationsStatement.h"
|
||||
#include "ir/SkSLWhileStatement.h"
|
||||
@ -153,17 +152,13 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
|
||||
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
|
||||
constantPropagate, e, nullptr });
|
||||
break;
|
||||
case Expression::kPrefix_Kind: {
|
||||
PrefixExpression* p = (PrefixExpression*) e->get();
|
||||
this->addExpression(cfg, &p->fOperand, constantPropagate &&
|
||||
p->fOperator != Token::PLUSPLUS &&
|
||||
p->fOperator != Token::MINUSMINUS);
|
||||
case Expression::kPrefix_Kind:
|
||||
this->addExpression(cfg, &((PrefixExpression*) e->get())->fOperand, constantPropagate);
|
||||
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
|
||||
constantPropagate, e, nullptr });
|
||||
break;
|
||||
}
|
||||
case Expression::kPostfix_Kind:
|
||||
this->addExpression(cfg, &((PostfixExpression*) e->get())->fOperand, false);
|
||||
this->addExpression(cfg, &((PostfixExpression*) e->get())->fOperand, constantPropagate);
|
||||
cfg.fBlocks[cfg.fCurrent].fNodes.push_back({ BasicBlock::Node::kExpression_Kind,
|
||||
constantPropagate, e, nullptr });
|
||||
break;
|
||||
@ -350,34 +345,6 @@ void CFGGenerator::addStatement(CFG& cfg, const Statement* s) {
|
||||
cfg.fCurrent = loopExit;
|
||||
break;
|
||||
}
|
||||
case Statement::kSwitch_Kind: {
|
||||
SwitchStatement* ss = (SwitchStatement*) s;
|
||||
this->addExpression(cfg, &ss->fValue, true);
|
||||
BlockId start = cfg.fCurrent;
|
||||
BlockId switchExit = cfg.newIsolatedBlock();
|
||||
fLoopExits.push(switchExit);
|
||||
for (const auto& c : ss->fCases) {
|
||||
cfg.newBlock();
|
||||
cfg.addExit(start, cfg.fCurrent);
|
||||
if (c->fValue) {
|
||||
// technically this should go in the start block, but it doesn't actually matter
|
||||
// because it must be constant. Not worth running two loops for.
|
||||
this->addExpression(cfg, &c->fValue, true);
|
||||
}
|
||||
for (const auto& caseStatement : c->fStatements) {
|
||||
this->addStatement(cfg, caseStatement.get());
|
||||
}
|
||||
}
|
||||
cfg.addExit(cfg.fCurrent, switchExit);
|
||||
// note that unlike GLSL, our grammar requires the default case to be last
|
||||
if (0 == ss->fCases.size() || ss->fCases[ss->fCases.size() - 1]->fValue) {
|
||||
// switch does not have a default clause, mark that it can skip straight to the end
|
||||
cfg.addExit(start, switchExit);
|
||||
}
|
||||
fLoopExits.pop();
|
||||
cfg.fCurrent = switchExit;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("statement: %s\n", s->description().c_str());
|
||||
ABORT("unsupported statement kind");
|
||||
|
@ -286,12 +286,8 @@ void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
|
||||
if (e1 != e2) {
|
||||
// definition has changed, merge and add exit block to worklist
|
||||
workList->insert(exitId);
|
||||
if (e1 && e2) {
|
||||
exit.fBefore[pair.first] =
|
||||
exit.fBefore[pair.first] =
|
||||
(std::unique_ptr<Expression>*) &fContext.fDefined_Expression;
|
||||
} else {
|
||||
exit.fBefore[pair.first] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -681,9 +681,6 @@ void GLSLCodeGenerator::writeStatement(const Statement& s) {
|
||||
case Statement::kDo_Kind:
|
||||
this->writeDoStatement((DoStatement&) s);
|
||||
break;
|
||||
case Statement::kSwitch_Kind:
|
||||
this->writeSwitchStatement((SwitchStatement&) s);
|
||||
break;
|
||||
case Statement::kBreak_Kind:
|
||||
this->write("break;");
|
||||
break;
|
||||
@ -753,30 +750,6 @@ void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) {
|
||||
this->write(");");
|
||||
}
|
||||
|
||||
void GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
|
||||
this->write("switch (");
|
||||
this->writeExpression(*s.fValue, kTopLevel_Precedence);
|
||||
this->writeLine(") {");
|
||||
fIndentation++;
|
||||
for (const auto& c : s.fCases) {
|
||||
if (c->fValue) {
|
||||
this->write("case ");
|
||||
this->writeExpression(*c->fValue, kTopLevel_Precedence);
|
||||
this->writeLine(":");
|
||||
} else {
|
||||
this->writeLine("default:");
|
||||
}
|
||||
fIndentation++;
|
||||
for (const auto& stmt : c->fStatements) {
|
||||
this->writeStatement(*stmt);
|
||||
this->writeLine();
|
||||
}
|
||||
fIndentation--;
|
||||
}
|
||||
fIndentation--;
|
||||
this->write("}");
|
||||
}
|
||||
|
||||
void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
|
||||
this->write("return");
|
||||
if (r.fExpression) {
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include "ir/SkSLProgramElement.h"
|
||||
#include "ir/SkSLReturnStatement.h"
|
||||
#include "ir/SkSLStatement.h"
|
||||
#include "ir/SkSLSwitchStatement.h"
|
||||
#include "ir/SkSLSwizzle.h"
|
||||
#include "ir/SkSLTernaryExpression.h"
|
||||
#include "ir/SkSLVarDeclarations.h"
|
||||
@ -156,8 +155,6 @@ private:
|
||||
|
||||
void writeDoStatement(const DoStatement& d);
|
||||
|
||||
void writeSwitchStatement(const SwitchStatement& s);
|
||||
|
||||
void writeReturnStatement(const ReturnStatement& r);
|
||||
|
||||
const Context& fContext;
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "SkSLIRGenerator.h"
|
||||
|
||||
#include "limits.h"
|
||||
#include <unordered_set>
|
||||
|
||||
#include "SkSLCompiler.h"
|
||||
#include "ast/SkSLASTBoolLiteral.h"
|
||||
@ -40,8 +39,6 @@
|
||||
#include "ir/SkSLPostfixExpression.h"
|
||||
#include "ir/SkSLPrefixExpression.h"
|
||||
#include "ir/SkSLReturnStatement.h"
|
||||
#include "ir/SkSLSwitchCase.h"
|
||||
#include "ir/SkSLSwitchStatement.h"
|
||||
#include "ir/SkSLSwizzle.h"
|
||||
#include "ir/SkSLTernaryExpression.h"
|
||||
#include "ir/SkSLUnresolvedFunction.h"
|
||||
@ -84,27 +81,12 @@ public:
|
||||
IRGenerator* fIR;
|
||||
};
|
||||
|
||||
class AutoSwitchLevel {
|
||||
public:
|
||||
AutoSwitchLevel(IRGenerator* ir)
|
||||
: fIR(ir) {
|
||||
fIR->fSwitchLevel++;
|
||||
}
|
||||
|
||||
~AutoSwitchLevel() {
|
||||
fIR->fSwitchLevel--;
|
||||
}
|
||||
|
||||
IRGenerator* fIR;
|
||||
};
|
||||
|
||||
IRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> symbolTable,
|
||||
ErrorReporter& errorReporter)
|
||||
: fContext(*context)
|
||||
, fCurrentFunction(nullptr)
|
||||
, fSymbolTable(std::move(symbolTable))
|
||||
, fLoopLevel(0)
|
||||
, fSwitchLevel(0)
|
||||
, fErrors(errorReporter) {}
|
||||
|
||||
void IRGenerator::pushSymbolTable() {
|
||||
@ -171,8 +153,6 @@ std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& sta
|
||||
return this->convertWhile((ASTWhileStatement&) statement);
|
||||
case ASTStatement::kDo_Kind:
|
||||
return this->convertDo((ASTDoStatement&) statement);
|
||||
case ASTStatement::kSwitch_Kind:
|
||||
return this->convertSwitch((ASTSwitchStatement&) statement);
|
||||
case ASTStatement::kReturn_Kind:
|
||||
return this->convertReturn((ASTReturnStatement&) statement);
|
||||
case ASTStatement::kBreak_Kind:
|
||||
@ -377,60 +357,6 @@ std::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) {
|
||||
std::move(test)));
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTSwitchStatement& s) {
|
||||
AutoSwitchLevel level(this);
|
||||
std::unique_ptr<Expression> value = this->convertExpression(*s.fValue);
|
||||
if (!value) {
|
||||
return nullptr;
|
||||
}
|
||||
if (value->fType != *fContext.fUInt_Type) {
|
||||
value = this->coerce(std::move(value), *fContext.fInt_Type);
|
||||
if (!value) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
AutoSymbolTable table(this);
|
||||
std::unordered_set<int> caseValues;
|
||||
std::vector<std::unique_ptr<SwitchCase>> cases;
|
||||
for (const auto& c : s.fCases) {
|
||||
std::unique_ptr<Expression> caseValue;
|
||||
if (c->fValue) {
|
||||
caseValue = this->convertExpression(*c->fValue);
|
||||
if (!caseValue) {
|
||||
return nullptr;
|
||||
}
|
||||
if (caseValue->fType != *fContext.fUInt_Type) {
|
||||
caseValue = this->coerce(std::move(caseValue), *fContext.fInt_Type);
|
||||
if (!caseValue) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (!caseValue->isConstant()) {
|
||||
fErrors.error(caseValue->fPosition, "case value must be a constant");
|
||||
return nullptr;
|
||||
}
|
||||
ASSERT(caseValue->fKind == Expression::kIntLiteral_Kind);
|
||||
int64_t v = ((IntLiteral&) *caseValue).fValue;
|
||||
if (caseValues.find(v) != caseValues.end()) {
|
||||
fErrors.error(caseValue->fPosition, "duplicate case value");
|
||||
}
|
||||
caseValues.insert(v);
|
||||
}
|
||||
std::vector<std::unique_ptr<Statement>> statements;
|
||||
for (const auto& s : c->fStatements) {
|
||||
std::unique_ptr<Statement> converted = this->convertStatement(*s);
|
||||
if (!converted) {
|
||||
return nullptr;
|
||||
}
|
||||
statements.push_back(std::move(converted));
|
||||
}
|
||||
cases.emplace_back(new SwitchCase(c->fPosition, std::move(caseValue),
|
||||
std::move(statements)));
|
||||
}
|
||||
return std::unique_ptr<Statement>(new SwitchStatement(s.fPosition, std::move(value),
|
||||
std::move(cases)));
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(
|
||||
const ASTExpressionStatement& s) {
|
||||
std::unique_ptr<Expression> e = this->convertExpression(*s.fExpression);
|
||||
@ -467,10 +393,10 @@ std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement&
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTBreakStatement& b) {
|
||||
if (fLoopLevel > 0 || fSwitchLevel > 0) {
|
||||
if (fLoopLevel > 0) {
|
||||
return std::unique_ptr<Statement>(new BreakStatement(b.fPosition));
|
||||
} else {
|
||||
fErrors.error(b.fPosition, "break statement must be inside a loop or switch");
|
||||
fErrors.error(b.fPosition, "break statement must be inside a loop");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "ast/SkSLASTReturnStatement.h"
|
||||
#include "ast/SkSLASTStatement.h"
|
||||
#include "ast/SkSLASTSuffixExpression.h"
|
||||
#include "ast/SkSLASTSwitchStatement.h"
|
||||
#include "ast/SkSLASTTernaryExpression.h"
|
||||
#include "ast/SkSLASTVarDeclaration.h"
|
||||
#include "ast/SkSLASTVarDeclarationStatement.h"
|
||||
@ -141,7 +140,6 @@ private:
|
||||
std::unique_ptr<Statement> convertContinue(const ASTContinueStatement& c);
|
||||
std::unique_ptr<Statement> convertDiscard(const ASTDiscardStatement& d);
|
||||
std::unique_ptr<Statement> convertDo(const ASTDoStatement& d);
|
||||
std::unique_ptr<Statement> convertSwitch(const ASTSwitchStatement& s);
|
||||
std::unique_ptr<Expression> convertBinaryExpression(const ASTBinaryExpression& expression);
|
||||
std::unique_ptr<Extension> convertExtension(const ASTExtension& e);
|
||||
std::unique_ptr<Statement> convertExpressionStatement(const ASTExpressionStatement& s);
|
||||
@ -172,12 +170,10 @@ private:
|
||||
std::unordered_map<SkString, CapValue> fCapsMap;
|
||||
std::shared_ptr<SymbolTable> fSymbolTable;
|
||||
int fLoopLevel;
|
||||
int fSwitchLevel;
|
||||
ErrorReporter& fErrors;
|
||||
|
||||
friend class AutoSymbolTable;
|
||||
friend class AutoLoopLevel;
|
||||
friend class AutoSwitchLevel;
|
||||
friend class Compiler;
|
||||
};
|
||||
|
||||
|
@ -63,8 +63,6 @@
|
||||
#include "ast/SkSLASTReturnStatement.h"
|
||||
#include "ast/SkSLASTStatement.h"
|
||||
#include "ast/SkSLASTSuffixExpression.h"
|
||||
#include "ast/SkSLASTSwitchCase.h"
|
||||
#include "ast/SkSLASTSwitchStatement.h"
|
||||
#include "ast/SkSLASTTernaryExpression.h"
|
||||
#include "ast/SkSLASTType.h"
|
||||
#include "ast/SkSLASTVarDeclaration.h"
|
||||
@ -772,8 +770,6 @@ std::unique_ptr<ASTStatement> Parser::statement() {
|
||||
return this->doStatement();
|
||||
case Token::WHILE:
|
||||
return this->whileStatement();
|
||||
case Token::SWITCH:
|
||||
return this->switchStatement();
|
||||
case Token::RETURN:
|
||||
return this->returnStatement();
|
||||
case Token::BREAK:
|
||||
@ -979,85 +975,6 @@ std::unique_ptr<ASTWhileStatement> Parser::whileStatement() {
|
||||
std::move(statement)));
|
||||
}
|
||||
|
||||
/* CASE expression COLON statement* */
|
||||
std::unique_ptr<ASTSwitchCase> Parser::switchCase() {
|
||||
if (!this->expect(Token::CASE, "'case'")) {
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr<ASTExpression> value = this->expression();
|
||||
if (!value) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!this->expect(Token::COLON, "':'")) {
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<std::unique_ptr<ASTStatement>> statements;
|
||||
while (this->peek().fKind != Token::RBRACE && this->peek().fKind != Token::CASE &&
|
||||
this->peek().fKind != Token::DEFAULT) {
|
||||
std::unique_ptr<ASTStatement> s = this->statement();
|
||||
if (!s) {
|
||||
return nullptr;
|
||||
}
|
||||
statements.push_back(std::move(s));
|
||||
}
|
||||
return std::unique_ptr<ASTSwitchCase>(new ASTSwitchCase(value->fPosition, std::move(value),
|
||||
std::move(statements)));
|
||||
}
|
||||
|
||||
/* SWITCH LPAREN expression RPAREN LBRACE switchCase* (DEFAULT COLON statement*)? RBRACE */
|
||||
std::unique_ptr<ASTStatement> Parser::switchStatement() {
|
||||
Token start;
|
||||
if (!this->expect(Token::SWITCH, "'switch'", &start)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!this->expect(Token::LPAREN, "'('")) {
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr<ASTExpression> value(this->expression());
|
||||
if (!value) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!this->expect(Token::RPAREN, "')'")) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!this->expect(Token::LBRACE, "'{'")) {
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<std::unique_ptr<ASTSwitchCase>> cases;
|
||||
while (this->peek().fKind == Token::CASE) {
|
||||
std::unique_ptr<ASTSwitchCase> c = this->switchCase();
|
||||
if (!c) {
|
||||
return nullptr;
|
||||
}
|
||||
cases.push_back(std::move(c));
|
||||
}
|
||||
// Requiring default: to be last (in defiance of C and GLSL) was a deliberate decision. Other
|
||||
// parts of the compiler may rely upon this assumption.
|
||||
if (this->peek().fKind == Token::DEFAULT) {
|
||||
Token defaultStart;
|
||||
SkAssertResult(this->expect(Token::DEFAULT, "'default'", &defaultStart));
|
||||
if (!this->expect(Token::COLON, "':'")) {
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<std::unique_ptr<ASTStatement>> statements;
|
||||
while (this->peek().fKind != Token::RBRACE) {
|
||||
std::unique_ptr<ASTStatement> s = this->statement();
|
||||
if (!s) {
|
||||
return nullptr;
|
||||
}
|
||||
statements.push_back(std::move(s));
|
||||
}
|
||||
cases.emplace_back(new ASTSwitchCase(defaultStart.fPosition, nullptr,
|
||||
std::move(statements)));
|
||||
}
|
||||
if (!this->expect(Token::RBRACE, "'}'")) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<ASTStatement>(new ASTSwitchStatement(start.fPosition,
|
||||
std::move(value),
|
||||
std::move(cases)));
|
||||
}
|
||||
|
||||
/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
|
||||
STATEMENT */
|
||||
std::unique_ptr<ASTForStatement> Parser::forStatement() {
|
||||
|
@ -37,8 +37,6 @@ struct ASTPrecision;
|
||||
struct ASTReturnStatement;
|
||||
struct ASTStatement;
|
||||
struct ASTSuffix;
|
||||
struct ASTSwitchCase;
|
||||
struct ASTSwitchStatement;
|
||||
struct ASTType;
|
||||
struct ASTWhileStatement;
|
||||
struct ASTVarDeclarations;
|
||||
@ -145,10 +143,6 @@ private:
|
||||
|
||||
std::unique_ptr<ASTForStatement> forStatement();
|
||||
|
||||
std::unique_ptr<ASTSwitchCase> switchCase();
|
||||
|
||||
std::unique_ptr<ASTStatement> switchStatement();
|
||||
|
||||
std::unique_ptr<ASTReturnStatement> returnStatement();
|
||||
|
||||
std::unique_ptr<ASTBreakStatement> breakStatement();
|
||||
|
@ -82,9 +82,6 @@ struct Token {
|
||||
FOR,
|
||||
WHILE,
|
||||
DO,
|
||||
SWITCH,
|
||||
CASE,
|
||||
DEFAULT,
|
||||
RETURN,
|
||||
BREAK,
|
||||
CONTINUE,
|
||||
|
@ -26,7 +26,6 @@ struct ASTStatement : public ASTPositionNode {
|
||||
kFor_Kind,
|
||||
kWhile_Kind,
|
||||
kDo_Kind,
|
||||
kSwitch_Kind,
|
||||
kReturn_Kind,
|
||||
kBreak_Kind,
|
||||
kContinue_Kind,
|
||||
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SKSL_ASTSWITCHCASE
|
||||
#define SKSL_ASTSWITCHCASE
|
||||
|
||||
#include "SkSLASTStatement.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
/**
|
||||
* A single case of a 'switch' statement.
|
||||
*/
|
||||
struct ASTSwitchCase : public ASTStatement {
|
||||
// a null value means "default:"
|
||||
ASTSwitchCase(Position position, std::unique_ptr<ASTExpression> value,
|
||||
std::vector<std::unique_ptr<ASTStatement>> statements)
|
||||
: INHERITED(position, kSwitch_Kind)
|
||||
, fValue(std::move(value))
|
||||
, fStatements(std::move(statements)) {}
|
||||
|
||||
SkString description() const override {
|
||||
SkString result;
|
||||
if (fValue) {
|
||||
result.appendf("case %s:\n", fValue->description().c_str());
|
||||
} else {
|
||||
result += "default:\n";
|
||||
}
|
||||
for (const auto& s : fStatements) {
|
||||
result += s->description() + "\n";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// null value implies "default" case
|
||||
const std::unique_ptr<ASTExpression> fValue;
|
||||
const std::vector<std::unique_ptr<ASTStatement>> fStatements;
|
||||
|
||||
typedef ASTStatement INHERITED;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SKSL_ASTSWITCHSTATEMENT
|
||||
#define SKSL_ASTSWITCHSTATEMENT
|
||||
|
||||
#include "SkSLASTStatement.h"
|
||||
#include "SkSLASTSwitchCase.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
/**
|
||||
* A 'switch' statement.
|
||||
*/
|
||||
struct ASTSwitchStatement : public ASTStatement {
|
||||
ASTSwitchStatement(Position position, std::unique_ptr<ASTExpression> value,
|
||||
std::vector<std::unique_ptr<ASTSwitchCase>> cases)
|
||||
: INHERITED(position, kSwitch_Kind)
|
||||
, fValue(std::move(value))
|
||||
, fCases(std::move(cases)) {}
|
||||
|
||||
SkString description() const override {
|
||||
SkString result = SkStringPrintf("switch (%s) {\n", + fValue->description().c_str());
|
||||
for (const auto& c : fCases) {
|
||||
result += c->description();
|
||||
}
|
||||
result += "}";
|
||||
return result;
|
||||
}
|
||||
|
||||
const std::unique_ptr<ASTExpression> fValue;
|
||||
const std::vector<std::unique_ptr<ASTSwitchCase>> fCases;
|
||||
|
||||
typedef ASTStatement INHERITED;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
@ -27,7 +27,6 @@ struct Statement : public IRNode {
|
||||
kFor_Kind,
|
||||
kIf_Kind,
|
||||
kReturn_Kind,
|
||||
kSwitch_Kind,
|
||||
kVarDeclarations_Kind,
|
||||
kWhile_Kind
|
||||
};
|
||||
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SKSL_SWITCHCASE
|
||||
#define SKSL_SWITCHCASE
|
||||
|
||||
#include "SkSLStatement.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
/**
|
||||
* A single case of a 'switch' statement.
|
||||
*/
|
||||
struct SwitchCase : public Statement {
|
||||
SwitchCase(Position position, std::unique_ptr<Expression> value,
|
||||
std::vector<std::unique_ptr<Statement>> statements)
|
||||
: INHERITED(position, kSwitch_Kind)
|
||||
, fValue(std::move(value))
|
||||
, fStatements(std::move(statements)) {}
|
||||
|
||||
SkString description() const override {
|
||||
SkString result;
|
||||
if (fValue) {
|
||||
result.appendf("case %s:\n", fValue->description().c_str());
|
||||
} else {
|
||||
result += "default:\n";
|
||||
}
|
||||
for (const auto& s : fStatements) {
|
||||
result += s->description() + "\n";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// null value implies "default" case
|
||||
std::unique_ptr<Expression> fValue;
|
||||
std::vector<std::unique_ptr<Statement>> fStatements;
|
||||
|
||||
typedef Statement INHERITED;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SKSL_SWITCHSTATEMENT
|
||||
#define SKSL_SWITCHSTATEMENT
|
||||
|
||||
#include "SkSLStatement.h"
|
||||
#include "SkSLSwitchCase.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
/**
|
||||
* A 'switch' statement.
|
||||
*/
|
||||
struct SwitchStatement : public Statement {
|
||||
SwitchStatement(Position position, std::unique_ptr<Expression> value,
|
||||
std::vector<std::unique_ptr<SwitchCase>> cases)
|
||||
: INHERITED(position, kSwitch_Kind)
|
||||
, fValue(std::move(value))
|
||||
, fCases(std::move(cases)) {}
|
||||
|
||||
SkString description() const override {
|
||||
SkString result = SkStringPrintf("switch (%s) {\n", + fValue->description().c_str());
|
||||
for (const auto& c : fCases) {
|
||||
result += c->description();
|
||||
}
|
||||
result += "}";
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> fValue;
|
||||
std::vector<std::unique_ptr<SwitchCase>> fCases;
|
||||
|
||||
typedef Statement INHERITED;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -46,12 +46,6 @@ while { return SkSL::Token::WHILE; }
|
||||
|
||||
do { return SkSL::Token::DO; }
|
||||
|
||||
switch { return SkSL::Token::SWITCH; }
|
||||
|
||||
case { return SkSL::Token::CASE; }
|
||||
|
||||
default { return SkSL::Token::DEFAULT; }
|
||||
|
||||
break { return SkSL::Token::BREAK; }
|
||||
|
||||
continue { return SkSL::Token::CONTINUE; }
|
||||
|
@ -337,10 +337,6 @@ DEF_TEST(SkSLUseWithoutInitialize, r) {
|
||||
test_failure(r,
|
||||
"void main() { bool x; if (true && (false || x)) return; }",
|
||||
"error: 1: 'x' has not been assigned\n1 error\n");
|
||||
test_failure(r,
|
||||
"void main() { int x; switch (3) { case 0: x = 0; case 1: x = 1; }"
|
||||
"sk_FragColor = vec4(x); }",
|
||||
"error: 1: 'x' has not been assigned\n1 error\n");
|
||||
}
|
||||
|
||||
DEF_TEST(SkSLUnreachable, r) {
|
||||
@ -370,16 +366,13 @@ DEF_TEST(SkSLNoReturn, r) {
|
||||
DEF_TEST(SkSLBreakOutsideLoop, r) {
|
||||
test_failure(r,
|
||||
"void foo() { while(true) {} if (true) break; }",
|
||||
"error: 1: break statement must be inside a loop or switch\n1 error\n");
|
||||
"error: 1: break statement must be inside a loop\n1 error\n");
|
||||
}
|
||||
|
||||
DEF_TEST(SkSLContinueOutsideLoop, r) {
|
||||
test_failure(r,
|
||||
"void foo() { for(;;); continue; }",
|
||||
"error: 1: continue statement must be inside a loop\n1 error\n");
|
||||
test_failure(r,
|
||||
"void foo() { switch (1) { default: continue; } }",
|
||||
"error: 1: continue statement must be inside a loop\n1 error\n");
|
||||
}
|
||||
|
||||
DEF_TEST(SkSLStaticIfError, r) {
|
||||
@ -437,25 +430,4 @@ DEF_TEST(SkSLUnsupportedGLSLIdentifiers, r) {
|
||||
"error: 1: unknown identifier 'gl_FragColor'\n1 error\n");
|
||||
}
|
||||
|
||||
DEF_TEST(SkSLWrongSwitchTypes, r) {
|
||||
test_failure(r,
|
||||
"void main() { switch (vec2(1)) { case 1: break; } }",
|
||||
"error: 1: expected 'int', but found 'vec2'\n1 error\n");
|
||||
test_failure(r,
|
||||
"void main() { switch (1) { case vec2(1): break; } }",
|
||||
"error: 1: expected 'int', but found 'vec2'\n1 error\n");
|
||||
}
|
||||
|
||||
DEF_TEST(SkSLNonConstantCase, r) {
|
||||
test_failure(r,
|
||||
"void main() { int x = 1; switch (1) { case x: break; } }",
|
||||
"error: 1: case value must be a constant\n1 error\n");
|
||||
}
|
||||
|
||||
DEF_TEST(SkSLDuplicateCase, r) {
|
||||
test_failure(r,
|
||||
"void main() { switch (1) { case 0: case 1: case 0: break; } }",
|
||||
"error: 1: duplicate case value\n1 error\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -777,91 +777,4 @@ DEF_TEST(SkSLGeometry, r) {
|
||||
SkSL::Program::kGeometry_Kind);
|
||||
}
|
||||
|
||||
DEF_TEST(SkSLSwitch, r) {
|
||||
test(r,
|
||||
"void main() {"
|
||||
" float x;"
|
||||
" switch (1) {"
|
||||
" case 0:"
|
||||
" x = 0.0;"
|
||||
" break;"
|
||||
" case 1:"
|
||||
" x = 1.0;"
|
||||
" break;"
|
||||
" default:"
|
||||
" x = 2.0;"
|
||||
" }"
|
||||
" sk_FragColor = vec4(x);"
|
||||
"}",
|
||||
*SkSL::ShaderCapsFactory::Default(),
|
||||
"#version 400\n"
|
||||
"out vec4 sk_FragColor;\n"
|
||||
"void main() {\n"
|
||||
" float x;\n"
|
||||
" switch (1) {\n"
|
||||
" case 0:\n"
|
||||
" x = 0.0;\n"
|
||||
" break;\n"
|
||||
" case 1:\n"
|
||||
" x = 1.0;\n"
|
||||
" break;\n"
|
||||
" default:\n"
|
||||
" x = 2.0;\n"
|
||||
" }\n"
|
||||
" sk_FragColor = vec4(x);\n"
|
||||
"}\n");
|
||||
test(r,
|
||||
"void main() {"
|
||||
" float x;"
|
||||
" switch (2) {"
|
||||
" case 0:"
|
||||
" x = 0.0;"
|
||||
" case 1:"
|
||||
" x = 1.0;"
|
||||
" default:"
|
||||
" x = 2.0;"
|
||||
" }"
|
||||
" sk_FragColor = vec4(x);"
|
||||
"}",
|
||||
*SkSL::ShaderCapsFactory::Default(),
|
||||
"#version 400\n"
|
||||
"out vec4 sk_FragColor;\n"
|
||||
"void main() {\n"
|
||||
" float x;\n"
|
||||
" switch (2) {\n"
|
||||
" case 0:\n"
|
||||
" x = 0.0;\n"
|
||||
" case 1:\n"
|
||||
" x = 1.0;\n"
|
||||
" default:\n"
|
||||
" x = 2.0;\n"
|
||||
" }\n"
|
||||
" sk_FragColor = vec4(2.0);\n"
|
||||
"}\n");
|
||||
test(r,
|
||||
"void main() {"
|
||||
" float x = 0.0;"
|
||||
" switch (3) {"
|
||||
" case 0:"
|
||||
" x = 0.0;"
|
||||
" case 1:"
|
||||
" x = 1.0;"
|
||||
" }"
|
||||
" sk_FragColor = vec4(x);"
|
||||
"}",
|
||||
*SkSL::ShaderCapsFactory::Default(),
|
||||
"#version 400\n"
|
||||
"out vec4 sk_FragColor;\n"
|
||||
"void main() {\n"
|
||||
" float x = 0.0;\n"
|
||||
" switch (3) {\n"
|
||||
" case 0:\n"
|
||||
" x = 0.0;\n"
|
||||
" case 1:\n"
|
||||
" x = 1.0;\n"
|
||||
" }\n"
|
||||
" sk_FragColor = vec4(x);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user