blob: 5058b441de2ebd31a0beba5cddcf6e07c839e6be [file] [log] [blame]
* Copyright 2016 Google Inc.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
#ifndef SKSL_BLOCK
#define SKSL_BLOCK
#include "include/private/SkSLDefines.h"
#include "src/sksl/SkSLPosition.h"
#include "src/sksl/ir/SkSLIRNode.h"
#include "src/sksl/ir/SkSLStatement.h"
#include <memory>
#include <string>
#include <utility>
namespace SkSL {
class SymbolTable;
* A block of multiple statements functioning as a single statement.
class Block final : public Statement {
inline static constexpr Kind kIRNodeKind = Kind::kBlock;
// "kBracedScope" represents an actual language-level block. Other kinds of block are used to
// pass around multiple statements as if they were a single unit, with no semantic impact.
enum class Kind {
kUnbracedBlock, // Represents a group of statements without curly braces.
kBracedScope, // Represents a language-level Block, with curly braces.
kCompoundStatement, // A block which conceptually represents a single statement, such as
// `int a, b;`. (SkSL represents this internally as two statements:
// `int a; int b;`) Allowed to optimize away to its interior Statement.
// Treated as a single statement by the debugger.
Block(Position pos,
StatementArray statements,
Kind kind = Kind::kBracedScope,
const std::shared_ptr<SymbolTable> symbols = nullptr)
: INHERITED(pos, kIRNodeKind)
, fChildren(std::move(statements))
, fBlockKind(kind)
, fSymbolTable(std::move(symbols)) {}
// Make is allowed to simplify compound statements. For a single-statement unscoped Block,
// Make can return the Statement as-is. For an empty unscoped Block, Make can return Nop.
static std::unique_ptr<Statement> Make(Position pos,
StatementArray statements,
Kind kind = Kind::kBracedScope,
std::shared_ptr<SymbolTable> symbols = nullptr);
// MakeCompoundStatement wraps two Statements into a single compound-statement Block.
// If either statement is empty, no Block will be created; the non-empty Statement is returned.
// If the first Statement is _already_ a compound-statement Block, the second statement will be
// appended to that block.
static std::unique_ptr<Statement> MakeCompoundStatement(std::unique_ptr<Statement> existing,
std::unique_ptr<Statement> additional);
// MakeBlock always makes a real Block object. This is important because many callers rely on
// Blocks specifically; e.g. a function body must be a scoped Block, nothing else will do.
static std::unique_ptr<Block> MakeBlock(Position pos,
StatementArray statements,
Kind kind = Kind::kBracedScope,
std::shared_ptr<SymbolTable> symbols = nullptr);
const StatementArray& children() const {
return fChildren;
StatementArray& children() {
return fChildren;
bool isScope() const {
return fBlockKind == Kind::kBracedScope;
Kind blockKind() const {
return fBlockKind;
void setBlockKind(Kind kind) {
fBlockKind = kind;
std::shared_ptr<SymbolTable> symbolTable() const {
return fSymbolTable;
bool isEmpty() const override {
for (const std::unique_ptr<Statement>& stmt : this->children()) {
if (!stmt->isEmpty()) {
return false;
return true;
std::unique_ptr<Statement> clone() const override;
std::string description() const override;
StatementArray fChildren;
Kind fBlockKind;
std::shared_ptr<SymbolTable> fSymbolTable;
using INHERITED = Statement;
} // namespace SkSL