ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 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 | */ |
Ethan Nicholas | 0df1b04 | 2017-03-31 13:56:23 -0400 | [diff] [blame] | 7 | |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 8 | #ifndef SKSL_SYMBOLTABLE |
| 9 | #define SKSL_SYMBOLTABLE |
| 10 | |
Ethan Nicholas | daed259 | 2021-03-04 14:30:25 -0500 | [diff] [blame] | 11 | #include "include/private/SkSLString.h" |
Ethan Nicholas | 24c1772 | 2021-03-09 13:10:59 -0500 | [diff] [blame] | 12 | #include "include/private/SkSLSymbol.h" |
John Stiles | 6bef6a7 | 2020-12-02 14:26:04 -0500 | [diff] [blame] | 13 | #include "include/private/SkTArray.h" |
John Stiles | efe767d | 2020-10-09 12:48:04 -0400 | [diff] [blame] | 14 | #include "include/private/SkTHash.h" |
Ethan Nicholas | 4a5e22a | 2021-08-13 17:29:51 -0400 | [diff] [blame] | 15 | #include "include/sksl/SkSLErrorReporter.h" |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 16 | |
John Stiles | bf9dff6 | 2021-04-21 09:55:09 -0400 | [diff] [blame] | 17 | #include <forward_list> |
John Stiles | efe767d | 2020-10-09 12:48:04 -0400 | [diff] [blame] | 18 | #include <memory> |
| 19 | #include <vector> |
| 20 | |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 21 | namespace SkSL { |
| 22 | |
Ethan Nicholas | ed84b73 | 2020-10-08 11:45:44 -0400 | [diff] [blame] | 23 | class FunctionDeclaration; |
ethannicholas | d598f79 | 2016-07-25 10:08:54 -0700 | [diff] [blame] | 24 | |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 25 | /** |
| 26 | * Maps identifiers to symbols. Functions, in particular, are mapped to either FunctionDeclaration |
| 27 | * or UnresolvedFunction depending on whether they are overloaded or not. |
| 28 | */ |
| 29 | class SymbolTable { |
| 30 | public: |
Ethan Nicholas | c7774a7 | 2021-08-27 15:34:05 -0400 | [diff] [blame] | 31 | SymbolTable(const Context& context, bool builtin) |
John Stiles | 7c3515b | 2020-10-16 18:38:39 -0400 | [diff] [blame] | 32 | : fBuiltin(builtin) |
Ethan Nicholas | c7774a7 | 2021-08-27 15:34:05 -0400 | [diff] [blame] | 33 | , fContext(context) {} |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 34 | |
John Stiles | 7c3515b | 2020-10-16 18:38:39 -0400 | [diff] [blame] | 35 | SymbolTable(std::shared_ptr<SymbolTable> parent, bool builtin) |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 36 | : fParent(parent) |
John Stiles | 7c3515b | 2020-10-16 18:38:39 -0400 | [diff] [blame] | 37 | , fBuiltin(builtin) |
Ethan Nicholas | c7774a7 | 2021-08-27 15:34:05 -0400 | [diff] [blame] | 38 | , fContext(parent->fContext) {} |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 39 | |
John Stiles | 6a1a98c | 2021-01-14 18:35:34 -0500 | [diff] [blame] | 40 | /** |
| 41 | * If the input is a built-in symbol table, returns a new empty symbol table as a child of the |
| 42 | * input table. If the input is not a built-in symbol table, returns it as-is. Built-in symbol |
| 43 | * tables must not be mutated after creation, so they must be wrapped if mutation is necessary. |
| 44 | */ |
John Stiles | 82f373c | 2020-10-20 13:58:05 -0400 | [diff] [blame] | 45 | static std::shared_ptr<SymbolTable> WrapIfBuiltin(std::shared_ptr<SymbolTable> symbolTable) { |
| 46 | if (!symbolTable) { |
| 47 | return nullptr; |
| 48 | } |
| 49 | if (!symbolTable->isBuiltin()) { |
| 50 | return symbolTable; |
| 51 | } |
| 52 | return std::make_shared<SymbolTable>(std::move(symbolTable), /*builtin=*/false); |
| 53 | } |
| 54 | |
John Stiles | 2630ea3 | 2020-12-04 10:51:21 -0500 | [diff] [blame] | 55 | /** |
| 56 | * Looks up the requested symbol and returns it. If a function has overloads, an |
| 57 | * UnresolvedFunction symbol (pointing to all of the candidates) will be added to the symbol |
| 58 | * table and returned. |
| 59 | */ |
Ethan Nicholas | 962dec4 | 2021-06-10 13:06:39 -0400 | [diff] [blame] | 60 | const Symbol* operator[](skstd::string_view name); |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 61 | |
John Stiles | 6a1a98c | 2021-01-14 18:35:34 -0500 | [diff] [blame] | 62 | /** |
| 63 | * Creates a new name for a symbol which already exists; does not take ownership of Symbol*. |
| 64 | */ |
Ethan Nicholas | 962dec4 | 2021-06-10 13:06:39 -0400 | [diff] [blame] | 65 | void addAlias(skstd::string_view name, const Symbol* symbol); |
John Stiles | 6a1a98c | 2021-01-14 18:35:34 -0500 | [diff] [blame] | 66 | |
Brian Osman | 5bf3e20 | 2020-10-13 10:34:18 -0400 | [diff] [blame] | 67 | void addWithoutOwnership(const Symbol* symbol); |
ethannicholas | d598f79 | 2016-07-25 10:08:54 -0700 | [diff] [blame] | 68 | |
John Stiles | 3ae071e | 2020-08-05 15:29:29 -0400 | [diff] [blame] | 69 | template <typename T> |
Brian Osman | 5bf3e20 | 2020-10-13 10:34:18 -0400 | [diff] [blame] | 70 | const T* add(std::unique_ptr<T> symbol) { |
| 71 | const T* ptr = symbol.get(); |
John Stiles | b8cc665 | 2020-10-08 09:12:07 -0400 | [diff] [blame] | 72 | this->addWithoutOwnership(ptr); |
John Stiles | 311dd9d | 2020-08-13 17:09:29 -0400 | [diff] [blame] | 73 | this->takeOwnershipOfSymbol(std::move(symbol)); |
| 74 | return ptr; |
| 75 | } |
| 76 | |
| 77 | template <typename T> |
Brian Osman | 5bf3e20 | 2020-10-13 10:34:18 -0400 | [diff] [blame] | 78 | const T* takeOwnershipOfSymbol(std::unique_ptr<T> symbol) { |
| 79 | const T* ptr = symbol.get(); |
John Stiles | 3ae071e | 2020-08-05 15:29:29 -0400 | [diff] [blame] | 80 | fOwnedSymbols.push_back(std::move(symbol)); |
| 81 | return ptr; |
| 82 | } |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 83 | |
John Stiles | 3ae071e | 2020-08-05 15:29:29 -0400 | [diff] [blame] | 84 | template <typename T> |
Brian Osman | 5bf3e20 | 2020-10-13 10:34:18 -0400 | [diff] [blame] | 85 | const T* takeOwnershipOfIRNode(std::unique_ptr<T> node) { |
| 86 | const T* ptr = node.get(); |
John Stiles | 3ae071e | 2020-08-05 15:29:29 -0400 | [diff] [blame] | 87 | fOwnedNodes.push_back(std::move(node)); |
| 88 | return ptr; |
| 89 | } |
Ethan Nicholas | aae47c8 | 2017-11-10 15:34:03 -0500 | [diff] [blame] | 90 | |
John Stiles | 6bef6a7 | 2020-12-02 14:26:04 -0500 | [diff] [blame] | 91 | /** |
John Stiles | a217950 | 2020-12-03 14:37:57 -0500 | [diff] [blame] | 92 | * Given type = `float` and arraySize = 5, creates the array type `float[5]` in the symbol |
Brian Osman | b42c383 | 2021-08-27 15:19:03 -0400 | [diff] [blame^] | 93 | * table. The created array type is returned. If zero is passed, the base type is returned |
| 94 | * unchanged. |
John Stiles | 6bef6a7 | 2020-12-02 14:26:04 -0500 | [diff] [blame] | 95 | */ |
John Stiles | a217950 | 2020-12-03 14:37:57 -0500 | [diff] [blame] | 96 | const Type* addArrayDimension(const Type* type, int arraySize); |
John Stiles | 6bef6a7 | 2020-12-02 14:26:04 -0500 | [diff] [blame] | 97 | |
John Stiles | efe767d | 2020-10-09 12:48:04 -0400 | [diff] [blame] | 98 | // Call fn for every symbol in the table. You may not mutate anything. |
| 99 | template <typename Fn> |
| 100 | void foreach(Fn&& fn) const { |
| 101 | fSymbols.foreach( |
| 102 | [&fn](const SymbolKey& key, const Symbol* symbol) { fn(key.fName, symbol); }); |
| 103 | } |
| 104 | |
| 105 | size_t count() { |
| 106 | return fSymbols.count(); |
| 107 | } |
| 108 | |
John Stiles | 2630ea3 | 2020-12-04 10:51:21 -0500 | [diff] [blame] | 109 | /** Returns true if this is a built-in SymbolTable. */ |
John Stiles | 7c3515b | 2020-10-16 18:38:39 -0400 | [diff] [blame] | 110 | bool isBuiltin() const { |
| 111 | return fBuiltin; |
| 112 | } |
| 113 | |
John Stiles | d51c979 | 2021-03-18 11:40:14 -0400 | [diff] [blame] | 114 | const String* takeOwnershipOfString(String n); |
Ethan Nicholas | 70728ef | 2020-05-28 07:09:00 -0400 | [diff] [blame] | 115 | |
Brian Osman | 1313d1a | 2020-09-08 10:34:30 -0400 | [diff] [blame] | 116 | std::shared_ptr<SymbolTable> fParent; |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 117 | |
Ethan Nicholas | c18bb51 | 2020-07-28 14:46:53 -0400 | [diff] [blame] | 118 | std::vector<std::unique_ptr<const Symbol>> fOwnedSymbols; |
| 119 | |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 120 | private: |
John Stiles | efe767d | 2020-10-09 12:48:04 -0400 | [diff] [blame] | 121 | struct SymbolKey { |
Ethan Nicholas | 962dec4 | 2021-06-10 13:06:39 -0400 | [diff] [blame] | 122 | skstd::string_view fName; |
John Stiles | efe767d | 2020-10-09 12:48:04 -0400 | [diff] [blame] | 123 | uint32_t fHash; |
| 124 | |
| 125 | bool operator==(const SymbolKey& that) const { return fName == that.fName; } |
| 126 | bool operator!=(const SymbolKey& that) const { return fName != that.fName; } |
| 127 | struct Hash { |
| 128 | uint32_t operator()(const SymbolKey& key) const { return key.fHash; } |
| 129 | }; |
| 130 | }; |
| 131 | |
Ethan Nicholas | 962dec4 | 2021-06-10 13:06:39 -0400 | [diff] [blame] | 132 | static SymbolKey MakeSymbolKey(skstd::string_view name) { |
John Stiles | efe767d | 2020-10-09 12:48:04 -0400 | [diff] [blame] | 133 | return SymbolKey{name, SkOpts::hash_fn(name.data(), name.size(), 0)}; |
| 134 | } |
| 135 | |
John Stiles | bcd1fc0 | 2020-10-16 18:39:13 -0400 | [diff] [blame] | 136 | const Symbol* lookup(SymbolTable* writableSymbolTable, const SymbolKey& key); |
John Stiles | 6a1a98c | 2021-01-14 18:35:34 -0500 | [diff] [blame] | 137 | |
ethannicholas | d598f79 | 2016-07-25 10:08:54 -0700 | [diff] [blame] | 138 | static std::vector<const FunctionDeclaration*> GetFunctions(const Symbol& s); |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 139 | |
John Stiles | 7c3515b | 2020-10-16 18:38:39 -0400 | [diff] [blame] | 140 | bool fBuiltin = false; |
Ethan Nicholas | aae47c8 | 2017-11-10 15:34:03 -0500 | [diff] [blame] | 141 | std::vector<std::unique_ptr<IRNode>> fOwnedNodes; |
John Stiles | bf9dff6 | 2021-04-21 09:55:09 -0400 | [diff] [blame] | 142 | std::forward_list<String> fOwnedStrings; |
Brian Osman | 5bf3e20 | 2020-10-13 10:34:18 -0400 | [diff] [blame] | 143 | SkTHashMap<SymbolKey, const Symbol*, SymbolKey::Hash> fSymbols; |
Ethan Nicholas | c7774a7 | 2021-08-27 15:34:05 -0400 | [diff] [blame] | 144 | const Context& fContext; |
Ethan Nicholas | c18bb51 | 2020-07-28 14:46:53 -0400 | [diff] [blame] | 145 | |
| 146 | friend class Dehydrator; |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 147 | }; |
| 148 | |
John Stiles | a6841be | 2020-08-06 14:11:56 -0400 | [diff] [blame] | 149 | } // namespace SkSL |
ethannicholas | b3058bd | 2016-07-01 08:22:01 -0700 | [diff] [blame] | 150 | |
| 151 | #endif |