| Index: src/sksl/ir/SkSLSymbolTable.cpp
|
| diff --git a/src/sksl/ir/SkSLSymbolTable.cpp b/src/sksl/ir/SkSLSymbolTable.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1732009809ae7ec221ee900f6fc42a218fa377b0
|
| --- /dev/null
|
| +++ b/src/sksl/ir/SkSLSymbolTable.cpp
|
| @@ -0,0 +1,85 @@
|
| +/*
|
| + * Copyright 2016 Google Inc.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + */
|
| +
|
| + #include "SkSLSymbolTable.h"
|
| +
|
| +namespace SkSL {
|
| +
|
| +std::vector<std::shared_ptr<FunctionDeclaration>> SymbolTable::GetFunctions(
|
| + std::shared_ptr<Symbol> s) {
|
| + switch (s->fKind) {
|
| + case Symbol::kFunctionDeclaration_Kind:
|
| + return { std::static_pointer_cast<FunctionDeclaration>(s) };
|
| + case Symbol::kUnresolvedFunction_Kind:
|
| + return std::static_pointer_cast<UnresolvedFunction>(s)->fFunctions;
|
| + default:
|
| + return { };
|
| + }
|
| +}
|
| +
|
| +std::shared_ptr<Symbol> SymbolTable::operator[](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 = GetFunctions(entry->second);
|
| + if (functions.size() > 0) {
|
| + bool modified = false;
|
| + std::shared_ptr<Symbol> previous = (*fParent)[name];
|
| + if (previous != nullptr) {
|
| + auto previousFunctions = GetFunctions(previous);
|
| + 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 SymbolTable::add(std::string name, std::shared_ptr<Symbol> symbol) {
|
| + 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");
|
| + }
|
| + }
|
| +} // namespace
|
|
|