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