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 
8 #include "SkSLSymbolTable.h"
9 #include "SkSLUnresolvedFunction.h"
10 
11 namespace SkSL {
12 
GetFunctions(const Symbol & s)13 std::vector<const FunctionDeclaration*> SymbolTable::GetFunctions(const Symbol& s) {
14     switch (s.fKind) {
15         case Symbol::kFunctionDeclaration_Kind:
16             return { &((FunctionDeclaration&) s) };
17         case Symbol::kUnresolvedFunction_Kind:
18             return ((UnresolvedFunction&) s).fFunctions;
19         default:
20             return std::vector<const FunctionDeclaration*>();
21     }
22 }
23 
operator [](StringFragment name)24 const Symbol* SymbolTable::operator[](StringFragment name) {
25     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) {
33         auto functions = GetFunctions(*entry->second);
34         if (functions.size() > 0) {
35             bool modified = false;
36             const Symbol* previous = (*fParent)[name];
37             if (previous) {
38                 auto previousFunctions = GetFunctions(*previous);
39                 for (const FunctionDeclaration* prev : previousFunctions) {
40                     bool found = false;
41                     for (const FunctionDeclaration* current : functions) {
42                         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                     SkASSERT(functions.size() > 1);
54                     return this->takeOwnership(new UnresolvedFunction(functions));
55                 }
56             }
57         }
58     }
59     return entry->second;
60 }
61 
takeOwnership(Symbol * s)62 Symbol* SymbolTable::takeOwnership(Symbol* s) {
63     fOwnedSymbols.emplace_back(s);
64     return s;
65 }
66 
takeOwnership(IRNode * n)67 IRNode* SymbolTable::takeOwnership(IRNode* n) {
68     fOwnedNodes.emplace_back(n);
69     return n;
70 }
71 
add(StringFragment name,std::unique_ptr<Symbol> symbol)72 void SymbolTable::add(StringFragment name, std::unique_ptr<Symbol> symbol) {
73     this->addWithoutOwnership(name, symbol.get());
74     this->takeOwnership(symbol.release());
75 }
76 
addWithoutOwnership(StringFragment name,const Symbol * symbol)77 void SymbolTable::addWithoutOwnership(StringFragment name, const Symbol* symbol) {
78     const auto& existing = fSymbols.find(name);
79     if (existing == fSymbols.end()) {
80         fSymbols[name] = symbol;
81     } else if (symbol->fKind == Symbol::kFunctionDeclaration_Kind) {
82         const Symbol* oldSymbol = existing->second;
83         if (oldSymbol->fKind == Symbol::kFunctionDeclaration_Kind) {
84             std::vector<const FunctionDeclaration*> functions;
85             functions.push_back((const FunctionDeclaration*) oldSymbol);
86             functions.push_back((const FunctionDeclaration*) symbol);
87             UnresolvedFunction* u = new UnresolvedFunction(std::move(functions));
88             fSymbols[name] = u;
89             this->takeOwnership(u);
90         } else if (oldSymbol->fKind == Symbol::kUnresolvedFunction_Kind) {
91             std::vector<const FunctionDeclaration*> functions;
92             for (const auto* f : ((UnresolvedFunction&) *oldSymbol).fFunctions) {
93                 functions.push_back(f);
94             }
95             functions.push_back((const FunctionDeclaration*) symbol);
96             UnresolvedFunction* u = new UnresolvedFunction(std::move(functions));
97             fSymbols[name] = u;
98             this->takeOwnership(u);
99         }
100     } else {
101         fErrorReporter.error(symbol->fOffset, "symbol '" + name + "' was already defined");
102     }
103 }
104 
105 
markAllFunctionsBuiltin()106 void SymbolTable::markAllFunctionsBuiltin() {
107     for (const auto& pair : fSymbols) {
108         switch (pair.second->fKind) {
109             case Symbol::kFunctionDeclaration_Kind:
110                 ((FunctionDeclaration&) *pair.second).fBuiltin = true;
111                 break;
112             case Symbol::kUnresolvedFunction_Kind:
113                 for (auto& f : ((UnresolvedFunction&) *pair.second).fFunctions) {
114                     ((FunctionDeclaration*) f)->fBuiltin = true;
115                 }
116                 break;
117             default:
118                 break;
119         }
120     }
121 }
122 
begin()123 std::unordered_map<StringFragment, const Symbol*>::iterator SymbolTable::begin() {
124     return fSymbols.begin();
125 }
126 
end()127 std::unordered_map<StringFragment, const Symbol*>::iterator SymbolTable::end() {
128     return fSymbols.end();
129 }
130 
131 
132 } // namespace
133