1 /*
2  * Copyright 2017 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SKSL_SWITCHSTATEMENT
9 #define SKSL_SWITCHSTATEMENT
10 
11 #include "include/private/SkSLStatement.h"
12 #include "src/sksl/ir/SkSLSwitchCase.h"
13 
14 #include <memory>
15 #include <vector>
16 
17 namespace SkSL {
18 
19 class Expression;
20 class SymbolTable;
21 
22 /**
23  * A 'switch' statement.
24  */
25 class SwitchStatement final : public Statement {
26 public:
27     static constexpr Kind kStatementKind = Kind::kSwitch;
28 
SwitchStatement(int offset,bool isStatic,std::unique_ptr<Expression> value,StatementArray cases,std::shared_ptr<SymbolTable> symbols)29     SwitchStatement(int offset, bool isStatic, std::unique_ptr<Expression> value,
30                     StatementArray cases, std::shared_ptr<SymbolTable> symbols)
31         : INHERITED(offset, kStatementKind)
32         , fIsStatic(isStatic)
33         , fValue(std::move(value))
34         , fCases(std::move(cases))
35         , fSymbols(std::move(symbols)) {}
36 
37     // Create a `switch` statement with an array of case-values and case-statements.
38     // Coerces case values to the proper type and reports an error if cases are duplicated.
39     // Reports errors via the ErrorReporter.
40     static std::unique_ptr<Statement> Convert(const Context& context,
41                                               int offset,
42                                               bool isStatic,
43                                               std::unique_ptr<Expression> value,
44                                               ExpressionArray caseValues,
45                                               StatementArray caseStatements,
46                                               std::shared_ptr<SymbolTable> symbolTable);
47 
48     // Create a `switch` statement with an array of SwitchCases. The array of SwitchCases must
49     // already contain non-overlapping, correctly-typed case values. Reports errors via ASSERT.
50     static std::unique_ptr<Statement> Make(const Context& context,
51                                            int offset,
52                                            bool isStatic,
53                                            std::unique_ptr<Expression> value,
54                                            StatementArray cases,
55                                            std::shared_ptr<SymbolTable> symbolTable);
56 
57     // Returns a block containing all of the statements that will be run if the given case matches
58     // (which, owing to the statements being owned by unique_ptrs, means the switch itself will be
59     // disassembled by this call and must then be discarded).
60     // Returns null (and leaves the switch unmodified) if no such simple reduction is possible, such
61     // as when break statements appear inside conditionals.
62     static std::unique_ptr<Statement> BlockForCase(StatementArray* cases,
63                                                    SwitchCase* caseToCapture,
64                                                    std::shared_ptr<SymbolTable> symbolTable);
65 
value()66     std::unique_ptr<Expression>& value() {
67         return fValue;
68     }
69 
value()70     const std::unique_ptr<Expression>& value() const {
71         return fValue;
72     }
73 
cases()74     StatementArray& cases() {
75         return fCases;
76     }
77 
cases()78     const StatementArray& cases() const {
79         return fCases;
80     }
81 
isStatic()82     bool isStatic() const {
83         return fIsStatic;
84     }
85 
symbols()86     const std::shared_ptr<SymbolTable>& symbols() const {
87         return fSymbols;
88     }
89 
90     std::unique_ptr<Statement> clone() const override;
91 
92     String description() const override;
93 
94 private:
95     bool fIsStatic;
96     std::unique_ptr<Expression> fValue;
97     StatementArray fCases;  // every Statement inside fCases must be a SwitchCase
98     std::shared_ptr<SymbolTable> fSymbols;
99 
100     using INHERITED = Statement;
101 };
102 
103 }  // namespace SkSL
104 
105 #endif
106