Flutter Engine
The Flutter Engine
SkSLSymbolTable.h
Go to the documentation of this file.
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#ifndef SKSL_SYMBOLTABLE
9#define SKSL_SYMBOLTABLE
10
12#include "src/core/SkChecksum.h"
13#include "src/core/SkTHash.h"
15
16#include <cstddef>
17#include <cstdint>
18#include <forward_list>
19#include <memory>
20#include <string>
21#include <string_view>
22#include <utility>
23#include <vector>
24
25namespace SkSL {
26
27class Context;
28class Expression;
29class Position;
30class Type;
31
32/**
33 * Maps identifiers to symbols.
34 */
36public:
37 explicit SymbolTable(bool builtin)
38 : fBuiltin(builtin) {}
39
40 explicit SymbolTable(SymbolTable* parent, bool builtin)
41 : fParent(parent)
42 , fBuiltin(builtin) {}
43
44 /**
45 * Creates a new, empty SymbolTable between this SymbolTable and its current parent.
46 * The new symbol table is returned, and is also accessible as `this->fParent`.
47 * The original parent is accessible as `this->fParent->fParent`.
48 */
49 std::unique_ptr<SymbolTable> insertNewParent();
50
51 /**
52 * Looks up the requested symbol and returns a const pointer.
53 */
54 const Symbol* find(std::string_view name) const {
55 return this->lookup(MakeSymbolKey(name));
56 }
57
58 /**
59 * Looks up the requested symbol, only searching the built-in symbol tables. Always const.
60 */
61 const Symbol* findBuiltinSymbol(std::string_view name) const;
62
63 /**
64 * Looks up the requested symbol and returns a mutable pointer. Use caution--mutating a symbol
65 * will have program-wide impact, and built-in symbol tables must never be mutated.
66 */
67 Symbol* findMutable(std::string_view name) const {
68 return this->lookup(MakeSymbolKey(name));
69 }
70
71 /**
72 * Looks up the requested symbol and instantiates an Expression reference to it; will return a
73 * VariableReference, TypeReference, FunctionReference, FieldAccess, or nullptr.
74 */
75 std::unique_ptr<Expression> instantiateSymbolRef(const Context& context,
76 std::string_view name,
78
79 /**
80 * Assigns a new name to the passed-in symbol. The old name will continue to exist in the symbol
81 * table and point to the symbol.
82 */
83 void renameSymbol(const Context& context, Symbol* symbol, std::string_view newName);
84
85 /**
86 * Removes a symbol from the symbol table. If this symbol table had ownership of the symbol, the
87 * symbol is returned (and can be deleted or reinserted as desired); if not, null is returned.
88 * In either event, the name will no longer correspond to the symbol.
89 */
90 std::unique_ptr<Symbol> removeSymbol(const Symbol* symbol);
91
92 /**
93 * Moves a symbol from this symbol table to another one. If this symbol table had ownership of
94 * the symbol, the ownership will be transferred as well. (If the symbol does not actually exist
95 * in this table at all, it will still be added to the other table.)
96 */
97 void moveSymbolTo(SymbolTable* otherTable, Symbol* sym, const Context& context);
98
99 /**
100 * Returns true if the name refers to a type (user or built-in) in the current symbol table.
101 */
102 bool isType(std::string_view name) const;
103
104 /**
105 * Returns true if the name refers to a builtin type.
106 */
107 bool isBuiltinType(std::string_view name) const;
108
109 /**
110 * Adds a symbol to this symbol table, without conferring ownership. The caller is responsible
111 * for keeping the Symbol alive throughout the lifetime of the program/module.
112 */
113 void addWithoutOwnershipOrDie(Symbol* symbol);
114 void addWithoutOwnership(const Context& context, Symbol* symbol);
115
116 /**
117 * Adds a symbol to this symbol table, conferring ownership. The symbol table will always be
118 * updated to reference the new symbol. If the symbol already exists, an error will be reported.
119 */
120 template <typename T>
121 T* add(const Context& context, std::unique_ptr<T> symbol) {
122 T* ptr = symbol.get();
123 this->addWithoutOwnership(context, this->takeOwnershipOfSymbol(std::move(symbol)));
124 return ptr;
125 }
126
127 /**
128 * Adds a symbol to this symbol table, conferring ownership. The symbol table will always be
129 * updated to reference the new symbol. If the symbol already exists, abort.
130 */
131 template <typename T>
132 T* addOrDie(std::unique_ptr<T> symbol) {
133 T* ptr = symbol.get();
134 this->addWithoutOwnershipOrDie(this->takeOwnershipOfSymbol(std::move(symbol)));
135 return ptr;
136 }
137
138 /**
139 * Forces a symbol into this symbol table, without conferring ownership. Replaces any existing
140 * symbol with the same name, if one exists.
141 */
142 void injectWithoutOwnership(Symbol* symbol);
143
144 /**
145 * Forces a symbol into this symbol table, conferring ownership. Replaces any existing symbol
146 * with the same name, if one exists.
147 */
148 template <typename T>
149 T* inject(std::unique_ptr<T> symbol) {
150 T* ptr = symbol.get();
151 this->injectWithoutOwnership(this->takeOwnershipOfSymbol(std::move(symbol)));
152 return ptr;
153 }
154
155 /**
156 * Confers ownership of a symbol without adding its name to the lookup table.
157 */
158 template <typename T>
159 T* takeOwnershipOfSymbol(std::unique_ptr<T> symbol) {
160 T* ptr = symbol.get();
161 fOwnedSymbols.push_back(std::move(symbol));
162 return ptr;
163 }
164
165 /**
166 * Given type = `float` and arraySize = 5, creates the array type `float[5]` in the symbol
167 * table. The created array type is returned. If zero is passed, the base type is returned
168 * unchanged.
169 */
170 const Type* addArrayDimension(const Context& context, const Type* type, int arraySize);
171
172 // Call fn for every symbol in the table. You may not mutate anything.
173 template <typename Fn>
174 void foreach(Fn&& fn) const {
175 fSymbols.foreach(
176 [&fn](const SymbolKey& key, const Symbol* symbol) { fn(key.fName, symbol); });
177 }
178
179 // Checks `this` directly against `other` to see if the two symbol tables have any names in
180 // common. Parent tables are not considered.
181 bool wouldShadowSymbolsFrom(const SymbolTable* other) const;
182
183 size_t count() const {
184 return fSymbols.count();
185 }
186
187 /** Returns true if this is a built-in SymbolTable. */
188 bool isBuiltin() const {
189 return fBuiltin;
190 }
191
192 const std::string* takeOwnershipOfString(std::string n);
193
194 /**
195 * Indicates that this symbol table's parent is in a different module than this one.
196 */
198 fAtModuleBoundary = true;
199 }
200
202
203 std::vector<std::unique_ptr<Symbol>> fOwnedSymbols;
204
205private:
206 struct SymbolKey {
207 std::string_view fName;
208 uint32_t fHash;
209
210 bool operator==(const SymbolKey& that) const { return fName == that.fName; }
211 bool operator!=(const SymbolKey& that) const { return fName != that.fName; }
212 struct Hash {
213 uint32_t operator()(const SymbolKey& key) const { return key.fHash; }
214 };
215 };
216
217 static SymbolKey MakeSymbolKey(std::string_view name) {
218 return SymbolKey{name, SkChecksum::Hash32(name.data(), name.size())};
219 }
220
221 Symbol* lookup(const SymbolKey& key) const;
222 bool addWithoutOwnership(Symbol* symbol);
223
224 bool fBuiltin = false;
225 bool fAtModuleBoundary = false;
226 std::forward_list<std::string> fOwnedStrings;
228};
229
230} // namespace SkSL
231
232#endif
const char * fName
SkPoint pos
GLenum type
void addWithoutOwnership(const Context &context, Symbol *symbol)
T * inject(std::unique_ptr< T > symbol)
const Type * addArrayDimension(const Context &context, const Type *type, int arraySize)
bool isType(std::string_view name) const
T * addOrDie(std::unique_ptr< T > symbol)
void renameSymbol(const Context &context, Symbol *symbol, std::string_view newName)
bool isBuiltinType(std::string_view name) const
const Symbol * find(std::string_view name) const
bool wouldShadowSymbolsFrom(const SymbolTable *other) const
void injectWithoutOwnership(Symbol *symbol)
size_t count() const
SymbolTable(SymbolTable *parent, bool builtin)
std::vector< std::unique_ptr< Symbol > > fOwnedSymbols
const std::string * takeOwnershipOfString(std::string n)
void addWithoutOwnershipOrDie(Symbol *symbol)
SymbolTable * fParent
bool isBuiltin() const
std::unique_ptr< Expression > instantiateSymbolRef(const Context &context, std::string_view name, Position pos)
SymbolTable(bool builtin)
T * takeOwnershipOfSymbol(std::unique_ptr< T > symbol)
const Symbol * findBuiltinSymbol(std::string_view name) const
T * add(const Context &context, std::unique_ptr< T > symbol)
void moveSymbolTo(SymbolTable *otherTable, Symbol *sym, const Context &context)
std::unique_ptr< SymbolTable > insertNewParent()
Symbol * findMutable(std::string_view name) const
std::unique_ptr< Symbol > removeSymbol(const Symbol *symbol)
uint32_t Hash32(const void *data, size_t bytes, uint32_t seed)
Definition: SkChecksum.cpp:113
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
bool operator==(C p1, const scoped_nsprotocol< C > &p2)
bool operator!=(C p1, const scoped_nsprotocol< C > &p2)
#define T
Definition: precompiler.cc:65
uint32_t operator()(const SymbolKey &key) const