| 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..fc4502a1a00c6ecc0fd1defa2a3d07cc145f61af
|
| --- /dev/null
|
| +++ b/src/sksl/ir/SkSLSymbolTable.h
|
| @@ -0,0 +1,99 @@
|
| +/*
|
| + * 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 "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() {}
|
| +
|
| + SymbolTable(std::shared_ptr<SymbolTable> parent)
|
| + : fParent(parent) {}
|
| +
|
| + std::shared_ptr<Symbol> 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 = 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) {
|
| + // FIXME need to report duplicate symbols
|
| + auto existing = fSymbols.find(name);
|
| + if (existing == fSymbols.end()) {
|
| + fSymbols[name] = symbol;
|
| + } else {
|
| + ASSERT(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));
|
| + }
|
| + }
|
| + }
|
| +
|
| + const std::shared_ptr<SymbolTable> fParent;
|
| +
|
| +private:
|
| + std::unordered_map<std::string, std::shared_ptr<Symbol>> fSymbols;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +#endif
|
|
|