Flutter Engine
The Flutter Engine
SkSLSymbolTable.cpp
Go to the documentation of this file.
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
9
17
18namespace SkSL {
19
20std::unique_ptr<SymbolTable> SymbolTable::insertNewParent() {
21 auto newTable = std::make_unique<SymbolTable>(fParent, fBuiltin);
22 fParent = newTable.get();
23 return newTable;
24}
25
26bool SymbolTable::isType(std::string_view name) const {
27 const Symbol* symbol = this->find(name);
28 return symbol && symbol->is<Type>();
29}
30
31bool SymbolTable::isBuiltinType(std::string_view name) const {
32 if (!this->isBuiltin()) {
33 return fParent && fParent->isBuiltinType(name);
34 }
35 return this->isType(name);
36}
37
38const Symbol* SymbolTable::findBuiltinSymbol(std::string_view name) const {
39 if (!this->isBuiltin()) {
40 return fParent ? fParent->findBuiltinSymbol(name) : nullptr;
41 }
42 return this->find(name);
43}
44
46 // We are checking two hash maps for overlap; we always iterate over the smaller one to minimize
47 // the total number of checks.
48 const SymbolTable* self = this;
49 if (self->count() > other->count()) {
50 std::swap(self, other);
51 }
52
53 bool foundShadow = false;
54
55 self->fSymbols.foreach([&](const SymbolKey& key, const Symbol* symbol) {
56 if (foundShadow) {
57 // We've already found a shadowed symbol; stop searching.
58 return;
59 }
60 if (other->fSymbols.find(key) != nullptr) {
61 foundShadow = true;
62 }
63 });
64
65 return foundShadow;
66}
67
68Symbol* SymbolTable::lookup(const SymbolKey& key) const {
69 Symbol** symbolPPtr = fSymbols.find(key);
70 if (symbolPPtr) {
71 return *symbolPPtr;
72 }
73
74 // The symbol wasn't found; recurse into the parent symbol table.
75 return fParent ? fParent->lookup(key) : nullptr;
76}
77
78void SymbolTable::renameSymbol(const Context& context, Symbol* symbol, std::string_view newName) {
79 if (symbol->is<FunctionDeclaration>()) {
80 // This is a function declaration, so we need to rename the entire overload set.
81 for (FunctionDeclaration* fn = &symbol->as<FunctionDeclaration>(); fn != nullptr;
82 fn = fn->mutableNextOverload()) {
83 fn->setName(newName);
84 }
85 } else {
86 // Other types of symbols don't allow multiple symbols with the same name.
87 symbol->setName(newName);
88 }
89
90 this->addWithoutOwnership(context, symbol);
91}
92
93std::unique_ptr<Symbol> SymbolTable::removeSymbol(const Symbol* symbol) {
94 // Remove the symbol from our symbol lookup table.
95 if (fSymbols.removeIfExists(MakeSymbolKey(symbol->name()))) {
96 // Transfer ownership of the symbol if we own it. (This will leave a nullptr behind in the
97 // `fOwnedSymbols` list, which should be harmless.)
98 for (std::unique_ptr<Symbol>& owned : fOwnedSymbols) {
99 if (symbol == owned.get()) {
100 return std::move(owned);
101 }
102 }
103 }
104
105 // We don't own the symbol after all.
106 return nullptr;
107}
108
109void SymbolTable::moveSymbolTo(SymbolTable* otherTable, Symbol* sym, const Context& context) {
110 if (std::unique_ptr<Symbol> ownedSymbol = this->removeSymbol(sym)) {
111 otherTable->add(context, std::move(ownedSymbol));
112 } else {
113 otherTable->addWithoutOwnership(context, sym);
114 }
115}
116
117const std::string* SymbolTable::takeOwnershipOfString(std::string str) {
118 fOwnedStrings.push_front(std::move(str));
119 // Because fOwnedStrings is a linked list, pointers to elements are stable.
120 return &fOwnedStrings.front();
121}
122
123void SymbolTable::addWithoutOwnership(const Context& context, Symbol* symbol) {
124 if (!this->addWithoutOwnership(symbol)) {
125 context.fErrors->error(symbol->position(),
126 "symbol '" + std::string(symbol->name()) + "' was already defined");
127 }
128}
129
131 if (!this->addWithoutOwnership(symbol)) {
132 SK_ABORT("symbol '%.*s' was already defined",
133 (int)symbol->name().size(), symbol->name().data());
134 }
135}
136
138 if (symbol->name().empty()) {
139 // We have legitimate use cases of nameless symbols, such as anonymous function parameters.
140 // If we find one here, we don't need to add its name to the symbol table.
141 return true;
142 }
143 auto key = MakeSymbolKey(symbol->name());
144
145 // If this is a function declaration, we need to keep the overload chain in sync.
146 if (symbol->is<FunctionDeclaration>()) {
147 // If we have a function with the same name...
148 Symbol* existingSymbol = this->lookup(key);
149 if (existingSymbol && existingSymbol->is<FunctionDeclaration>()) {
150 // ... add the existing function as the next overload in the chain.
151 FunctionDeclaration* existingDecl = &existingSymbol->as<FunctionDeclaration>();
152 symbol->as<FunctionDeclaration>().setNextOverload(existingDecl);
153 fSymbols[key] = symbol;
154 return true;
155 }
156 }
157
158 if (fAtModuleBoundary && fParent && fParent->lookup(key)) {
159 // We are attempting to declare a symbol at global scope that already exists in a parent
160 // module. This is a duplicate symbol and should be rejected.
161 return false;
162 }
163
164 std::swap(symbol, fSymbols[key]);
165 return symbol == nullptr;
166}
167
169 auto key = MakeSymbolKey(symbol->name());
170 fSymbols[key] = symbol;
171}
172
174 const Type* type,
175 int arraySize) {
176 if (arraySize == 0) {
177 return type;
178 }
179 // If we are making an array of a builtin type, we add it as high as possible in the symbol
180 // table tree (at the module boundary), to enable additional reuse of the array-type.
181 if (fParent && !fAtModuleBoundary && !context.fConfig->fIsBuiltinCode && type->isBuiltin()) {
182 return fParent->addArrayDimension(context, type, arraySize);
183 }
184 // Reuse an existing array type with this name if one already exists in our symbol table.
185 std::string arrayName = type->getArrayName(arraySize);
186 if (const Symbol* existingType = this->find(arrayName)) {
187 return &existingType->as<Type>();
188 }
189 // Add a new array type to the symbol table.
190 const std::string* arrayNamePtr = this->takeOwnershipOfString(std::move(arrayName));
191 return this->add(context, Type::MakeArrayType(context, *arrayNamePtr, *type, arraySize));
192}
193
194std::unique_ptr<Expression> SymbolTable::instantiateSymbolRef(const Context& context,
195 std::string_view name,
196 Position pos) {
197 if (const Symbol* symbol = this->find(name)) {
198 return symbol->instantiate(context, pos);
199 }
200 context.fErrors->error(pos, "unknown identifier '" + std::string(name) + "'");
201 return nullptr;
202}
203
204} // namespace SkSL
SkPoint pos
#define SK_ABORT(message,...)
Definition: SkAssert.h:70
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition: SkRefCnt.h:341
GLenum type
ErrorReporter * fErrors
Definition: SkSLContext.h:36
ProgramConfig * fConfig
Definition: SkSLContext.h:33
void error(Position position, std::string_view msg)
FunctionDeclaration * mutableNextOverload() const
Position position() const
Definition: SkSLIRNode.h:111
bool is() const
Definition: SkSLIRNode.h:124
const T & as() const
Definition: SkSLIRNode.h:133
void addWithoutOwnership(const Context &context, Symbol *symbol)
const Type * addArrayDimension(const Context &context, const Type *type, int arraySize)
bool isType(std::string_view name) const
void renameSymbol(const Context &context, Symbol *symbol, std::string_view newName)
bool isBuiltinType(std::string_view name) const
const Symbol * find(std::string_view name) const
bool wouldShadowSymbolsFrom(const SymbolTable *other) const
void injectWithoutOwnership(Symbol *symbol)
size_t count() const
std::vector< std::unique_ptr< Symbol > > fOwnedSymbols
const std::string * takeOwnershipOfString(std::string n)
void addWithoutOwnershipOrDie(Symbol *symbol)
SymbolTable * fParent
bool isBuiltin() const
std::unique_ptr< Expression > instantiateSymbolRef(const Context &context, std::string_view name, Position pos)
const Symbol * findBuiltinSymbol(std::string_view name) const
T * add(const Context &context, std::unique_ptr< T > symbol)
void moveSymbolTo(SymbolTable *otherTable, Symbol *sym, const Context &context)
std::unique_ptr< SymbolTable > insertNewParent()
std::unique_ptr< Symbol > removeSymbol(const Symbol *symbol)
std::string_view name() const
Definition: SkSLSymbol.h:51
void setName(std::string_view newName)
Definition: SkSLSymbol.h:58
std::unique_ptr< Expression > instantiate(const Context &context, Position pos) const
Definition: SkSLSymbol.cpp:24
static std::unique_ptr< Type > MakeArrayType(const Context &context, std::string_view name, const Type &componentType, int columns)
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32