blob: af83f7a456241abe4615a92e702d7084da5dc497 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkSLSymbolTable.h"
namespace SkSL {
std::vector<std::shared_ptr<FunctionDeclaration>> SymbolTable::GetFunctions(
const std::shared_ptr<Symbol>& s) {
switch (s->fKind) {
case Symbol::kFunctionDeclaration_Kind:
return { std::static_pointer_cast<FunctionDeclaration>(s) };
case Symbol::kUnresolvedFunction_Kind:
return ((UnresolvedFunction&) *s).fFunctions;
default:
return { };
}
}
std::shared_ptr<Symbol> SymbolTable::operator[](const std::string& name) {
const auto& entry = fSymbols.find(name);
if (entry == fSymbols.end()) {
if (fParent) {
return (*fParent)[name];
}
return nullptr;
}
if (fParent) {
auto functions = GetFunctions(entry->second);
if (functions.size() > 0) {
bool modified = false;
std::shared_ptr<Symbol> previous = (*fParent)[name];
if (previous) {
auto previousFunctions = GetFunctions(previous);
for (const std::shared_ptr<FunctionDeclaration>& prev : previousFunctions) {
bool found = false;
for (const 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.size() > 1);
return std::shared_ptr<Symbol>(new UnresolvedFunction(functions));
}
}
}
}
return entry->second;
}
void SymbolTable::add(const std::string& name, std::shared_ptr<Symbol> symbol) {
const auto& existing = fSymbols.find(name);
if (existing == fSymbols.end()) {
fSymbols[name] = symbol;
} else if (symbol->fKind == Symbol::kFunctionDeclaration_Kind) {
const 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].reset(new UnresolvedFunction(std::move(functions)));
} else if (oldSymbol->fKind == Symbol::kUnresolvedFunction_Kind) {
std::vector<std::shared_ptr<FunctionDeclaration>> functions;
for (const auto& f : ((UnresolvedFunction&) *oldSymbol).fFunctions) {
functions.push_back(f);
}
functions.push_back(std::static_pointer_cast<FunctionDeclaration>(symbol));
fSymbols[name].reset(new UnresolvedFunction(std::move(functions)));
}
} else {
fErrorReporter.error(symbol->fPosition, "symbol '" + name + "' was already defined");
}
}
} // namespace
|