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 "src/sksl/ir/SkSLSymbolTable.h"
9#include "src/sksl/ir/SkSLUnresolvedFunction.h"
10
11namespace SkSL {
12
13std::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
24const 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(std::unique_ptr<Symbol>(
55 new UnresolvedFunction(functions)));
56 }
57 }
58 }
59 }
60 return entry->second;
61}
62
63Symbol* SymbolTable::takeOwnership(std::unique_ptr<Symbol> s) {
64 Symbol* result = s.get();
65 fOwnedSymbols.push_back(std::move(s));
66 return result;
67}
68
69IRNode* SymbolTable::takeOwnership(std::unique_ptr<IRNode> n) {
70 IRNode* result = n.get();
71 fOwnedNodes.push_back(std::move(n));
72 return result;
73}
74
75void SymbolTable::add(StringFragment name, std::unique_ptr<Symbol> symbol) {
76 this->addWithoutOwnership(name, symbol.get());
77 this->takeOwnership(std::move(symbol));
78}
79
80void SymbolTable::addWithoutOwnership(StringFragment name, const Symbol* symbol) {
81 const auto& existing = fSymbols.find(name);
82 if (existing == fSymbols.end()) {
83 fSymbols[name] = symbol;
84 } else if (symbol->fKind == Symbol::kFunctionDeclaration_Kind) {
85 const Symbol* oldSymbol = existing->second;
86 if (oldSymbol->fKind == Symbol::kFunctionDeclaration_Kind) {
87 std::vector<const FunctionDeclaration*> functions;
88 functions.push_back((const FunctionDeclaration*) oldSymbol);
89 functions.push_back((const FunctionDeclaration*) symbol);
90 std::unique_ptr<Symbol> u = std::unique_ptr<Symbol>(new UnresolvedFunction(std::move(
91 functions)));
92 fSymbols[name] = this->takeOwnership(std::move(u));
93 } else if (oldSymbol->fKind == Symbol::kUnresolvedFunction_Kind) {
94 std::vector<const FunctionDeclaration*> functions;
95 for (const auto* f : ((UnresolvedFunction&) *oldSymbol).fFunctions) {
96 functions.push_back(f);
97 }
98 functions.push_back((const FunctionDeclaration*) symbol);
99 std::unique_ptr<Symbol> u = std::unique_ptr<Symbol>(new UnresolvedFunction(std::move(
100 functions)));
101 fSymbols[name] = this->takeOwnership(std::move(u));
102 }
103 } else {
104 fErrorReporter.error(symbol->fOffset, "symbol '" + name + "' was already defined");
105 }
106}
107
108
109void SymbolTable::markAllFunctionsBuiltin() {
110 for (const auto& pair : fSymbols) {
111 switch (pair.second->fKind) {
112 case Symbol::kFunctionDeclaration_Kind:
113 ((FunctionDeclaration&)*pair.second).fBuiltin = true;
114 break;
115 case Symbol::kUnresolvedFunction_Kind:
116 for (auto& f : ((UnresolvedFunction&) *pair.second).fFunctions) {
117 if (!((FunctionDeclaration*)f)->fDefined) {
118 ((FunctionDeclaration*)f)->fBuiltin = true;
119 }
120 }
121 break;
122 default:
123 break;
124 }
125 }
126}
127
128std::unordered_map<StringFragment, const Symbol*>::iterator SymbolTable::begin() {
129 return fSymbols.begin();
130}
131
132std::unordered_map<StringFragment, const Symbol*>::iterator SymbolTable::end() {
133 return fSymbols.end();
134}
135
136
137} // namespace
138