Chromium Code Reviews| Index: src/sksl/ir/SkSLSymbolTable.h |
| diff --git a/src/sksl/ir/SkSLSymbolTable.h b/src/sksl/ir/SkSLSymbolTable.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..304ce986e97f5bb5986e10597cb111a620dcd1b3 |
| --- /dev/null |
| +++ b/src/sksl/ir/SkSLSymbolTable.h |
| @@ -0,0 +1,104 @@ |
| +/* |
| + * 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_SYMBOLTABLE |
| +#define SKSL_SYMBOLTABLE |
| + |
| +#include <memory> |
| +#include <unordered_map> |
| +#include "SkSLErrorReporter.h" |
| +#include "SkSLSymbol.h" |
| +#include "SkSLUnresolvedFunction.h" |
| + |
| +namespace SkSL { |
| + |
| +std::vector<std::shared_ptr<FunctionDeclaration>> get_functions(std::shared_ptr<Symbol> s); |
| + |
| +/** |
| + * Maps identifiers to symbols. Functions, in particular, are mapped to either FunctionDeclaration |
| + * or UnresolvedFunction depending on whether they are overloaded or not. |
| + */ |
| +class SymbolTable { |
| +public: |
| + SymbolTable(ErrorReporter& errorReporter) |
| + : fErrorReporter(errorReporter) {} |
| + |
| + SymbolTable(std::shared_ptr<SymbolTable> parent, ErrorReporter& errorReporter) |
| + : fParent(parent) |
| + , fErrorReporter(errorReporter) {} |
| + |
| + std::shared_ptr<Symbol> operator[](std::string name) { |
|
dogben
2016/06/23 15:25:12
nit: const std::string& name
|
| + auto entry = fSymbols.find(name); |
| + if (entry == fSymbols.end()) { |
| + if (fParent != nullptr) { |
| + return (*fParent)[name]; |
| + } |
| + return nullptr; |
| + } |
| + if (fParent != nullptr) { |
| + auto functions = get_functions(entry->second); |
| + if (functions.size() > 0) { |
| + bool modified = false; |
| + std::shared_ptr<Symbol> previous = (*fParent)[name]; |
| + auto previousFunctions = get_functions(entry->second); |
| + for (std::shared_ptr<FunctionDeclaration> prev : previousFunctions) { |
| + bool found = false; |
| + for (std::shared_ptr<FunctionDeclaration> current : functions) { |
| + if (current->matches(prev)) { |
| + found = true; |
| + break; |
| + } |
| + } |
| + if (!found) { |
| + functions.push_back(prev); |
| + modified = true; |
| + } |
| + } |
| + if (modified) { |
| + ASSERT(functions.count() > 1); |
| + return std::shared_ptr<Symbol>(new UnresolvedFunction(functions)); |
| + } |
| + } |
| + } |
| + return entry->second; |
| + } |
| + |
| + void add(std::string name, std::shared_ptr<Symbol> symbol) { |
|
dogben
2016/06/23 15:25:12
nit: const std::string& name
|
| + auto existing = fSymbols.find(name); |
| + if (existing == fSymbols.end()) { |
| + fSymbols[name] = symbol; |
| + } else if (symbol->fKind == Symbol::kFunctionDeclaration_Kind) { |
| + std::shared_ptr<Symbol> oldSymbol = existing->second; |
| + if (oldSymbol->fKind == Symbol::kFunctionDeclaration_Kind) { |
| + std::vector<std::shared_ptr<FunctionDeclaration>> functions; |
| + functions.push_back(std::static_pointer_cast<FunctionDeclaration>(oldSymbol)); |
| + functions.push_back(std::static_pointer_cast<FunctionDeclaration>(symbol)); |
| + fSymbols[name] = std::shared_ptr<Symbol>(new UnresolvedFunction(functions)); |
| + } else if (oldSymbol->fKind == Symbol::kUnresolvedFunction_Kind) { |
| + std::vector<std::shared_ptr<FunctionDeclaration>> functions; |
| + for (auto f : std::static_pointer_cast<UnresolvedFunction>(oldSymbol)->fFunctions) { |
| + functions.push_back(f); |
| + } |
| + functions.push_back(std::static_pointer_cast<FunctionDeclaration>(symbol)); |
| + fSymbols[name] = std::shared_ptr<Symbol>(new UnresolvedFunction(functions)); |
| + } |
| + } else { |
| + fErrorReporter.error(symbol->fPosition, "symbol '" + name + "' was already defined"); |
| + } |
| + } |
| + |
| + const std::shared_ptr<SymbolTable> fParent; |
| + |
| +private: |
| + std::unordered_map<std::string, std::shared_ptr<Symbol>> fSymbols; |
| + |
| + ErrorReporter& fErrorReporter; |
| +}; |
| + |
| +} // namespace |
| + |
| +#endif |