• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Google LLC
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 #include "src/sksl/ir/SkSLBlock.h"
9 #include "src/sksl/ir/SkSLNop.h"
10 
11 #include <iterator>
12 
13 namespace SkSL {
14 
MakeUnscoped(int line,StatementArray statements)15 std::unique_ptr<Statement> Block::MakeUnscoped(int line, StatementArray statements) {
16     // If the Block is completely empty, synthesize a Nop.
17     if (statements.empty()) {
18         return Nop::Make();
19     }
20 
21     if (statements.size() > 1) {
22         // The statement array contains multiple statements, but some of those might be no-ops.
23         // If the statement array only contains one real statement, we can return that directly and
24         // avoid creating an additional Block node.
25         std::unique_ptr<Statement>* foundStatement = nullptr;
26         for (std::unique_ptr<Statement>& stmt : statements) {
27             if (!stmt->isEmpty()) {
28                 if (!foundStatement) {
29                     // We found a single non-empty statement. Remember it and keep looking.
30                     foundStatement = &stmt;
31                     continue;
32                 }
33                 // We found more than one non-empty statement. We actually do need a Block.
34                 return std::make_unique<Block>(line, std::move(statements),
35                                                /*symbols=*/nullptr, /*isScope=*/false);
36             }
37         }
38 
39         // The array wrapped one valid Statement. Avoid allocating a Block by returning it directly.
40         if (foundStatement) {
41             return std::move(*foundStatement);
42         }
43 
44         // The statement array contained nothing but empty statements!
45         // In this case, we don't actually need to allocate a Block.
46         // We can just return one of those empty statements. Fall through to...
47     }
48 
49     return std::move(statements.front());
50 }
51 
Make(int line,StatementArray statements,std::shared_ptr<SymbolTable> symbols,bool isScope)52 std::unique_ptr<Block> Block::Make(int line,
53                                    StatementArray statements,
54                                    std::shared_ptr<SymbolTable> symbols,
55                                    bool isScope) {
56     // Nothing to optimize here--eliminating empty statements doesn't actually improve the generated
57     // code, and we promise to return a Block.
58     return std::make_unique<Block>(line, std::move(statements), std::move(symbols), isScope);
59 }
60 
clone() const61 std::unique_ptr<Statement> Block::clone() const {
62     StatementArray cloned;
63     cloned.reserve_back(this->children().size());
64     for (const std::unique_ptr<Statement>& stmt : this->children()) {
65         cloned.push_back(stmt->clone());
66     }
67     return std::make_unique<Block>(fLine,
68                                    std::move(cloned),
69                                    SymbolTable::WrapIfBuiltin(this->symbolTable()),
70                                    this->isScope());
71 }
72 
description() const73 String Block::description() const {
74     String result;
75     if (fIsScope) {
76         result += "{";
77     }
78     for (const std::unique_ptr<Statement>& stmt : this->children()) {
79         result += "\n";
80         result += stmt->description();
81     }
82     result += fIsScope ? "\n}\n" : "\n";
83     return result;
84 }
85 
86 }  // namespace SkSL
87