blob: 9d8c0063c555fd43064dccbd0d79d0468fcda7fe [file] [log] [blame]
ethannicholasb3058bd2016-07-01 08:22:01 -07001/*
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
ethannicholasd598f792016-07-25 10:08:54 -07008#include "SkSLSymbolTable.h"
9#include "SkSLUnresolvedFunction.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070010
11namespace SkSL {
12
ethannicholasd598f792016-07-25 10:08:54 -070013std::vector<const FunctionDeclaration*> SymbolTable::GetFunctions(const Symbol& s) {
14 switch (s.fKind) {
ethannicholasb3058bd2016-07-01 08:22:01 -070015 case Symbol::kFunctionDeclaration_Kind:
ethannicholasd598f792016-07-25 10:08:54 -070016 return { &((FunctionDeclaration&) s) };
ethannicholasb3058bd2016-07-01 08:22:01 -070017 case Symbol::kUnresolvedFunction_Kind:
ethannicholasd598f792016-07-25 10:08:54 -070018 return ((UnresolvedFunction&) s).fFunctions;
ethannicholasb3058bd2016-07-01 08:22:01 -070019 default:
ethannicholas0730be72016-09-01 07:59:02 -070020 return std::vector<const FunctionDeclaration*>();
ethannicholasb3058bd2016-07-01 08:22:01 -070021 }
22}
23
ethannicholasd598f792016-07-25 10:08:54 -070024const Symbol* SymbolTable::operator[](const std::string& name) {
ethannicholasb3058bd2016-07-01 08:22:01 -070025 const auto& entry = fSymbols.find(name);
26 if (entry == fSymbols.end()) {
27 if (fParent) {
28 return (*fParent)[name];
29 }
30 return nullptr;
31 }
32 if (fParent) {
ethannicholasd598f792016-07-25 10:08:54 -070033 auto functions = GetFunctions(*entry->second);
ethannicholasb3058bd2016-07-01 08:22:01 -070034 if (functions.size() > 0) {
35 bool modified = false;
ethannicholasd598f792016-07-25 10:08:54 -070036 const Symbol* previous = (*fParent)[name];
ethannicholasb3058bd2016-07-01 08:22:01 -070037 if (previous) {
ethannicholasd598f792016-07-25 10:08:54 -070038 auto previousFunctions = GetFunctions(*previous);
39 for (const FunctionDeclaration* prev : previousFunctions) {
ethannicholasb3058bd2016-07-01 08:22:01 -070040 bool found = false;
ethannicholasd598f792016-07-25 10:08:54 -070041 for (const FunctionDeclaration* current : functions) {
ethannicholasb3058bd2016-07-01 08:22:01 -070042 if (current->matches(*prev)) {
43 found = true;
44 break;
45 }
46 }
47 if (!found) {
48 functions.push_back(prev);
49 modified = true;
50 }
51 }
52 if (modified) {
53 ASSERT(functions.size() > 1);
ethannicholasd598f792016-07-25 10:08:54 -070054 return this->takeOwnership(new UnresolvedFunction(functions));
ethannicholasb3058bd2016-07-01 08:22:01 -070055 }
56 }
57 }
58 }
59 return entry->second;
60}
61
ethannicholasd598f792016-07-25 10:08:54 -070062Symbol* SymbolTable::takeOwnership(Symbol* s) {
63 fOwnedPointers.push_back(std::unique_ptr<Symbol>(s));
64 return s;
65}
66
67void SymbolTable::add(const std::string& name, std::unique_ptr<Symbol> symbol) {
68 this->addWithoutOwnership(name, symbol.get());
69 fOwnedPointers.push_back(std::move(symbol));
70}
71
72void SymbolTable::addWithoutOwnership(const std::string& name, const Symbol* symbol) {
73 const auto& existing = fSymbols.find(name);
74 if (existing == fSymbols.end()) {
75 fSymbols[name] = symbol;
76 } else if (symbol->fKind == Symbol::kFunctionDeclaration_Kind) {
77 const Symbol* oldSymbol = existing->second;
78 if (oldSymbol->fKind == Symbol::kFunctionDeclaration_Kind) {
79 std::vector<const FunctionDeclaration*> functions;
80 functions.push_back((const FunctionDeclaration*) oldSymbol);
81 functions.push_back((const FunctionDeclaration*) symbol);
82 UnresolvedFunction* u = new UnresolvedFunction(std::move(functions));
83 fSymbols[name] = u;
84 this->takeOwnership(u);
85 } else if (oldSymbol->fKind == Symbol::kUnresolvedFunction_Kind) {
86 std::vector<const FunctionDeclaration*> functions;
87 for (const auto* f : ((UnresolvedFunction&) *oldSymbol).fFunctions) {
88 functions.push_back(f);
ethannicholasb3058bd2016-07-01 08:22:01 -070089 }
ethannicholasd598f792016-07-25 10:08:54 -070090 functions.push_back((const FunctionDeclaration*) symbol);
91 UnresolvedFunction* u = new UnresolvedFunction(std::move(functions));
92 fSymbols[name] = u;
93 this->takeOwnership(u);
ethannicholasb3058bd2016-07-01 08:22:01 -070094 }
ethannicholasd598f792016-07-25 10:08:54 -070095 } else {
96 fErrorReporter.error(symbol->fPosition, "symbol '" + name + "' was already defined");
ethannicholasb3058bd2016-07-01 08:22:01 -070097 }
ethannicholasd598f792016-07-25 10:08:54 -070098}
99
ethannicholasb3058bd2016-07-01 08:22:01 -0700100} // namespace