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->takeOwnershipOfSymbol(
55 std::make_unique<UnresolvedFunction>(functions));
56 }
57 }
58 }
59 }
60 return entry->second;
61}
62
63const String* SymbolTable::takeOwnershipOfString(std::unique_ptr<String> n) {
64 String* result = n.get();
65 fOwnedStrings.push_back(std::move(n));
66 return result;
67}
68
69void SymbolTable::addWithoutOwnership(StringFragment name, const Symbol* symbol) {
70 const auto& existing = fSymbols.find(name);
71 if (existing == fSymbols.end()) {
72 fSymbols[name] = symbol;
73 } else if (symbol->fKind == Symbol::kFunctionDeclaration_Kind) {
74 const Symbol* oldSymbol = existing->second;
75 if (oldSymbol->fKind == Symbol::kFunctionDeclaration_Kind) {
76 std::vector<const FunctionDeclaration*> functions;
77 functions.push_back((const FunctionDeclaration*) oldSymbol);
78 functions.push_back((const FunctionDeclaration*) symbol);
79 std::unique_ptr<const Symbol> u = std::unique_ptr<const Symbol>(
80 new UnresolvedFunction(std::move(functions)));
81 fSymbols[name] = this->takeOwnershipOfSymbol(std::move(u));
82 } else if (oldSymbol->fKind == Symbol::kUnresolvedFunction_Kind) {
83 std::vector<const FunctionDeclaration*> functions;
84 for (const auto* f : ((UnresolvedFunction&) *oldSymbol).fFunctions) {
85 functions.push_back(f);
86 }
87 functions.push_back((const FunctionDeclaration*) symbol);
88 std::unique_ptr<const Symbol> u = std::unique_ptr<const Symbol>(
89 new UnresolvedFunction(std::move(functions)));
90 fSymbols[name] = this->takeOwnershipOfSymbol(std::move(u));
91 }
92 } else {
93 fErrorReporter.error(symbol->fOffset, "symbol '" + name + "' was already defined");
94 }
95}
96
97std::unordered_map<StringFragment, const Symbol*>::iterator SymbolTable::begin() {
98 return fSymbols.begin();
99}
100
101std::unordered_map<StringFragment, const Symbol*>::iterator SymbolTable::end() {
102 return fSymbols.end();
103}
104
105} // namespace SkSL
106