1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2016 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SKSL_BLOCK 9*c8dee2aaSAndroid Build Coastguard Worker #define SKSL_BLOCK 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLDefines.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLPosition.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLIRNode.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLStatement.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLSymbolTable.h" 16*c8dee2aaSAndroid Build Coastguard Worker 17*c8dee2aaSAndroid Build Coastguard Worker #include <memory> 18*c8dee2aaSAndroid Build Coastguard Worker #include <string> 19*c8dee2aaSAndroid Build Coastguard Worker #include <utility> 20*c8dee2aaSAndroid Build Coastguard Worker 21*c8dee2aaSAndroid Build Coastguard Worker namespace SkSL { 22*c8dee2aaSAndroid Build Coastguard Worker 23*c8dee2aaSAndroid Build Coastguard Worker /** 24*c8dee2aaSAndroid Build Coastguard Worker * A block of multiple statements functioning as a single statement. 25*c8dee2aaSAndroid Build Coastguard Worker */ 26*c8dee2aaSAndroid Build Coastguard Worker class Block final : public Statement { 27*c8dee2aaSAndroid Build Coastguard Worker public: 28*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr Kind kIRNodeKind = Kind::kBlock; 29*c8dee2aaSAndroid Build Coastguard Worker 30*c8dee2aaSAndroid Build Coastguard Worker // "kBracedScope" represents an actual language-level block. Other kinds of block are used to 31*c8dee2aaSAndroid Build Coastguard Worker // pass around multiple statements as if they were a single unit, with no semantic impact. 32*c8dee2aaSAndroid Build Coastguard Worker enum class Kind { 33*c8dee2aaSAndroid Build Coastguard Worker kUnbracedBlock, // Represents a group of statements without curly braces. 34*c8dee2aaSAndroid Build Coastguard Worker kBracedScope, // Represents a language-level Block, with curly braces. 35*c8dee2aaSAndroid Build Coastguard Worker kCompoundStatement, // A block which conceptually represents a single statement, such as 36*c8dee2aaSAndroid Build Coastguard Worker // `int a, b;`. (SkSL represents this internally as two statements: 37*c8dee2aaSAndroid Build Coastguard Worker // `int a; int b;`) Allowed to optimize away to its interior Statement. 38*c8dee2aaSAndroid Build Coastguard Worker // Treated as a single statement by the debugger. 39*c8dee2aaSAndroid Build Coastguard Worker }; 40*c8dee2aaSAndroid Build Coastguard Worker 41*c8dee2aaSAndroid Build Coastguard Worker Block(Position pos, 42*c8dee2aaSAndroid Build Coastguard Worker StatementArray statements, 43*c8dee2aaSAndroid Build Coastguard Worker Kind kind = Kind::kBracedScope, 44*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SymbolTable> symbols = nullptr) INHERITED(pos,kIRNodeKind)45*c8dee2aaSAndroid Build Coastguard Worker : INHERITED(pos, kIRNodeKind) 46*c8dee2aaSAndroid Build Coastguard Worker , fSymbolTable(std::move(symbols)) 47*c8dee2aaSAndroid Build Coastguard Worker , fChildren(std::move(statements)) 48*c8dee2aaSAndroid Build Coastguard Worker , fBlockKind(kind) {} 49*c8dee2aaSAndroid Build Coastguard Worker 50*c8dee2aaSAndroid Build Coastguard Worker // Make is allowed to simplify compound statements. For a single-statement unscoped Block, 51*c8dee2aaSAndroid Build Coastguard Worker // Make can return the Statement as-is. For an empty unscoped Block, Make can return Nop. 52*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<Statement> Make(Position pos, 53*c8dee2aaSAndroid Build Coastguard Worker StatementArray statements, 54*c8dee2aaSAndroid Build Coastguard Worker Kind kind = Kind::kBracedScope, 55*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SymbolTable> symbols = nullptr); 56*c8dee2aaSAndroid Build Coastguard Worker 57*c8dee2aaSAndroid Build Coastguard Worker // MakeCompoundStatement wraps two Statements into a single compound-statement Block. 58*c8dee2aaSAndroid Build Coastguard Worker // If either statement is empty, no Block will be created; the non-empty Statement is returned. 59*c8dee2aaSAndroid Build Coastguard Worker // If the first Statement is _already_ a compound-statement Block, the second statement will be 60*c8dee2aaSAndroid Build Coastguard Worker // appended to that block. 61*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<Statement> MakeCompoundStatement(std::unique_ptr<Statement> existing, 62*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Statement> additional); 63*c8dee2aaSAndroid Build Coastguard Worker 64*c8dee2aaSAndroid Build Coastguard Worker // MakeBlock always makes a real Block object. This is important because many callers rely on 65*c8dee2aaSAndroid Build Coastguard Worker // Blocks specifically; e.g. a function body must be a scoped Block, nothing else will do. 66*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<Block> MakeBlock(Position pos, 67*c8dee2aaSAndroid Build Coastguard Worker StatementArray statements, 68*c8dee2aaSAndroid Build Coastguard Worker Kind kind = Kind::kBracedScope, 69*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SymbolTable> symbols = nullptr); 70*c8dee2aaSAndroid Build Coastguard Worker children()71*c8dee2aaSAndroid Build Coastguard Worker const StatementArray& children() const { 72*c8dee2aaSAndroid Build Coastguard Worker return fChildren; 73*c8dee2aaSAndroid Build Coastguard Worker } 74*c8dee2aaSAndroid Build Coastguard Worker children()75*c8dee2aaSAndroid Build Coastguard Worker StatementArray& children() { 76*c8dee2aaSAndroid Build Coastguard Worker return fChildren; 77*c8dee2aaSAndroid Build Coastguard Worker } 78*c8dee2aaSAndroid Build Coastguard Worker isScope()79*c8dee2aaSAndroid Build Coastguard Worker bool isScope() const { 80*c8dee2aaSAndroid Build Coastguard Worker return fBlockKind == Kind::kBracedScope; 81*c8dee2aaSAndroid Build Coastguard Worker } 82*c8dee2aaSAndroid Build Coastguard Worker blockKind()83*c8dee2aaSAndroid Build Coastguard Worker Kind blockKind() const { 84*c8dee2aaSAndroid Build Coastguard Worker return fBlockKind; 85*c8dee2aaSAndroid Build Coastguard Worker } 86*c8dee2aaSAndroid Build Coastguard Worker setBlockKind(Kind kind)87*c8dee2aaSAndroid Build Coastguard Worker void setBlockKind(Kind kind) { 88*c8dee2aaSAndroid Build Coastguard Worker fBlockKind = kind; 89*c8dee2aaSAndroid Build Coastguard Worker } 90*c8dee2aaSAndroid Build Coastguard Worker symbolTable()91*c8dee2aaSAndroid Build Coastguard Worker SymbolTable* symbolTable() const { 92*c8dee2aaSAndroid Build Coastguard Worker return fSymbolTable.get(); 93*c8dee2aaSAndroid Build Coastguard Worker } 94*c8dee2aaSAndroid Build Coastguard Worker isEmpty()95*c8dee2aaSAndroid Build Coastguard Worker bool isEmpty() const override { 96*c8dee2aaSAndroid Build Coastguard Worker for (const std::unique_ptr<Statement>& stmt : this->children()) { 97*c8dee2aaSAndroid Build Coastguard Worker if (!stmt->isEmpty()) { 98*c8dee2aaSAndroid Build Coastguard Worker return false; 99*c8dee2aaSAndroid Build Coastguard Worker } 100*c8dee2aaSAndroid Build Coastguard Worker } 101*c8dee2aaSAndroid Build Coastguard Worker return true; 102*c8dee2aaSAndroid Build Coastguard Worker } 103*c8dee2aaSAndroid Build Coastguard Worker 104*c8dee2aaSAndroid Build Coastguard Worker std::string description() const override; 105*c8dee2aaSAndroid Build Coastguard Worker 106*c8dee2aaSAndroid Build Coastguard Worker private: 107*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SymbolTable> fSymbolTable; 108*c8dee2aaSAndroid Build Coastguard Worker StatementArray fChildren; 109*c8dee2aaSAndroid Build Coastguard Worker Kind fBlockKind; 110*c8dee2aaSAndroid Build Coastguard Worker 111*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = Statement; 112*c8dee2aaSAndroid Build Coastguard Worker }; 113*c8dee2aaSAndroid Build Coastguard Worker 114*c8dee2aaSAndroid Build Coastguard Worker } // namespace SkSL 115*c8dee2aaSAndroid Build Coastguard Worker 116*c8dee2aaSAndroid Build Coastguard Worker #endif 117