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