30#include <forward_list>
38 return "switch (" + this->
value()->description() +
") " + this->
caseBlock()->description();
43 std::forward_list<const SwitchCase*> duplicateCases;
45 bool foundDefault =
false;
47 for (
const std::unique_ptr<Statement>& stmt : cases) {
51 duplicateCases.push_front(sc);
58 duplicateCases.push_front(sc);
65 return duplicateCases;
71 bool visitStatementPtr(std::unique_ptr<Statement>& stmt)
override {
76 return ProgramWriter::visitStatementPtr(stmt);
79 bool visitExpressionPtr(std::unique_ptr<Expression>& expr)
override {
83 RemoveBreaksWriter{}.visitStatementPtr(stmt);
98 auto iter = cases.
begin();
99 for (; iter != cases.
end(); ++iter) {
101 if (&sc == caseToCapture) {
109 auto startIter = iter;
110 bool removeBreakStatements =
false;
111 for (; iter != cases.
end(); ++iter) {
112 std::unique_ptr<Statement>& stmt = (*iter)->
as<
SwitchCase>().statement();
120 removeBreakStatements =
true;
131 int numElements =
SkToInt(std::distance(startIter, iter));
132 for (
int index = 0; index < numElements; ++index, ++startIter) {
140 if (removeBreakStatements) {
150 std::unique_ptr<Expression> value,
153 std::unique_ptr<SymbolTable> symbolTable) {
162 for (
int i = 0; i < caseValues.
size(); ++i) {
164 Position casePos = caseValues[i]->fPosition;
166 std::unique_ptr<Expression> caseValue =
value->type().coerceExpression(
167 std::move(caseValues[i]), context);
173 context.
fErrors->
error(casePos,
"case value must be a constant integer");
185 if (!duplicateCases.empty()) {
186 duplicateCases.reverse();
188 if (sc->isDefault()) {
189 context.
fErrors->
error(sc->fPosition,
"duplicate default case");
191 context.
fErrors->
error(sc->fPosition,
"duplicate case value '" +
192 std::to_string(sc->value()) +
"'");
201 Block::MakeBlock(
pos,
203 Block::Kind::kBracedScope,
204 std::move(symbolTable)));
209 std::unique_ptr<Expression> value,
210 std::unique_ptr<Statement> caseBlock) {
214 return stmt->is<SwitchCase>();
226 for (
const std::unique_ptr<Statement>& stmt :
cases) {
233 if (sc.
value() == switchValue) {
247 matchingCase = defaultCase;
258 auto stmt = std::make_unique<SwitchStatement>(
pos, std::move(
value), std::move(
caseBlock));
constexpr int SkToInt(S x)
const std::unique_ptr< Type > fInt
static bool GetConstantInt(const Expression &value, SKSL_INT *out)
const BuiltinTypes & fTypes
void error(Position position, std::string_view msg)
static std::unique_ptr< Statement > Make()
static std::unique_ptr< SwitchCase > MakeDefault(Position pos, std::unique_ptr< Statement > statement)
static std::unique_ptr< SwitchCase > Make(Position pos, SKSL_INT value, std::unique_ptr< Statement > statement)
std::unique_ptr< Statement > & statement()
std::unique_ptr< Expression > & value()
std::string description() const override
std::unique_ptr< Statement > & caseBlock()
static std::unique_ptr< Statement > Make(const Context &context, Position pos, std::unique_ptr< Expression > value, std::unique_ptr< Statement > caseBlock)
static std::unique_ptr< Statement > Convert(const Context &context, Position pos, std::unique_ptr< Expression > value, ExpressionArray caseValues, StatementArray caseStatements, std::unique_ptr< SymbolTable > symbolTable)
bool contains(const T &item) const
EMSCRIPTEN_KEEPALIVE void empty()
bool SwitchCaseContainsUnconditionalExit(const Statement &stmt)
bool SwitchCaseContainsConditionalExit(const Statement &stmt)
static std::forward_list< const SwitchCase * > find_duplicate_case_values(const StatementArray &cases)
static void remove_break_statements(std::unique_ptr< Statement > &stmt)
static bool block_for_case(Statement *caseBlock, SwitchCase *caseToCapture)
ProgramSettings fSettings