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
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                    ASSERT(functions.size() > 1);
54                    return this->takeOwnership(new UnresolvedFunction(functions));
55                }
56            }
57        }
58    }
59    return entry->second;
60}
61
62Symbol* SymbolTable::takeOwnership(Symbol* s) {
63    fOwnedSymbols.emplace_back(s);
64    return s;
65}
66
67IRNode* SymbolTable::takeOwnership(IRNode* n) {
68    fOwnedNodes.emplace_back(n);
69    return n;
70}
71
72void SymbolTable::add(StringFragment name, std::unique_ptr<Symbol> symbol) {
73    this->addWithoutOwnership(name, symbol.get());
74    this->takeOwnership(symbol.release());
75}
76
77void 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
106void 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
123std::map<StringFragment, const Symbol*>::iterator SymbolTable::begin() {
124    return fSymbols.begin();
125}
126
127std::map<StringFragment, const Symbol*>::iterator SymbolTable::end() {
128    return fSymbols.end();
129}
130
131
132} // namespace
133