62 lines
1.5 KiB
C++
62 lines
1.5 KiB
C++
|
|
class SymbolTable{
|
|
private:
|
|
enum Kind
|
|
{
|
|
kModule,
|
|
kFunction,
|
|
kBlock,
|
|
};
|
|
|
|
std::forward_list<std::pair<Kind, std::unordered_map<std::string, Value*>>> Scopes;
|
|
|
|
public:
|
|
struct ModuleScope {
|
|
SymbolTable& tables_ref;
|
|
ModuleScope(SymbolTable& tables) : tables_ref(tables) {
|
|
tables.enter(kModule);
|
|
}
|
|
~ModuleScope() { tables_ref.exit(); }
|
|
};
|
|
struct FunctionScope {
|
|
SymbolTable& tables_ref;
|
|
FunctionScope(SymbolTable& tables) : tables_ref(tables) {
|
|
tables.enter(kFunction);
|
|
}
|
|
~FunctionScope() { tables_ref.exit(); }
|
|
};
|
|
struct BlockScope {
|
|
SymbolTable& tables_ref;
|
|
BlockScope(SymbolTable& tables) : tables_ref(tables) {
|
|
tables.enter(kBlock);
|
|
}
|
|
~BlockScope() { tables_ref.exit(); }
|
|
};
|
|
|
|
SymbolTable() = default;
|
|
|
|
bool isModuleScope() const { return Scopes.front().first == kModule; }
|
|
bool isFunctionScope() const { return Scopes.front().first == kFunction; }
|
|
bool isBlockScope() const { return Scopes.front().first == kBlock; }
|
|
Value *lookup(const std::string &name) const {
|
|
for (auto &scope : Scopes) {
|
|
auto iter = scope.second.find(name);
|
|
if (iter != scope.second.end())
|
|
return iter->second;
|
|
}
|
|
return nullptr;
|
|
}
|
|
auto insert(const std::string &name, Value *value) {
|
|
assert(not Scopes.empty());
|
|
return Scopes.front().second.emplace(name, value);
|
|
}
|
|
private:
|
|
void enter(Kind kind) {
|
|
Scopes.emplace_front();
|
|
Scopes.front().first = kind;
|
|
}
|
|
void exit() {
|
|
Scopes.pop_front();
|
|
}
|
|
|
|
}; |