Select Git revision
test_checkpointing_IQuadratureDescriptor.cpp
SymbolTable.hpp 7.50 KiB
#ifndef SYMBOL_TABLE_HPP
#define SYMBOL_TABLE_HPP
#include <language/ast/ASTNodeDataType.hpp>
#include <language/utils/DataVariant.hpp>
#include <language/utils/EmbedderTable.hpp>
#include <language/utils/FunctionTable.hpp>
#include <utils/PugsMacros.hpp>
#include <pegtl/position.hpp>
#include <iostream>
class TypeDescriptor;
class IBuiltinFunctionEmbedder;
class SymbolTable
{
public:
class Attributes
{
private:
TAO_PEGTL_NAMESPACE::position m_position;
int32_t m_context_id;
bool m_is_initialized{false};
ASTNodeDataType m_data_type;
DataVariant m_value;
public:
bool
hasLocalContext() const
{
return m_context_id != -1;
}
const int32_t&
contextId() const
{
return m_context_id;
}
auto&
value()
{
return m_value;
}
const auto&
value() const
{
return m_value;
}
const bool&
isInitialized() const
{
return m_is_initialized;
}
void
setIsInitialized()
{
m_is_initialized = true;
}
const ASTNodeDataType&
dataType() const
{
return m_data_type;
}
auto
position() const
{
return m_position;
}
void
setDataType(const ASTNodeDataType& data_type)
{
Assert(m_data_type == ASTNodeDataType::undefined_t, "data type has already been defined!");
m_data_type = data_type;
}
friend std::ostream&
operator<<(std::ostream& os, const Attributes& attributes)
{
os << rang::fg::green;
if (attributes.m_data_type == ASTNodeDataType::function_t) {
os << "function_id";
} else {
os << dataTypeName(attributes.dataType());
}
os << rang::style::reset << ':' << attributes.m_value;
return os;
}
Attributes(const TAO_PEGTL_NAMESPACE::position& position, int32_t context_id)
: m_position{position}, m_context_id{context_id}
{}
Attributes(const Attributes&) = default;
};
class Symbol // LCOV_EXCL_LINE
{
private:
std::string m_name;
Attributes m_attributes;
public:
PUGS_INLINE
const std::string&
name() const
{
return m_name;
}
PUGS_INLINE
const Attributes&
attributes() const
{
return m_attributes;
}
PUGS_INLINE
Attributes&
attributes()
{
return m_attributes;
}
Symbol(const std::string& name, const Attributes& attributes) : m_name(name), m_attributes(attributes) {}
Symbol& operator=(Symbol&&) = default;
Symbol& operator=(const Symbol&) = default;
Symbol(const Symbol&) = default;
Symbol(Symbol&&) = default;
~Symbol() = default;
};
class Context
{
private:
inline static int32_t next_context_id{0};
int32_t m_id;
size_t m_size{0};
public:
PUGS_INLINE
int32_t
id() const
{
return m_id;
}
PUGS_INLINE
size_t
size() const
{
return m_size;
}
PUGS_INLINE
size_t
getNextSymbolId()
{
return m_size++;
}
Context() : m_id{next_context_id++} {}
Context& operator=(const Context&) = default; // clazy:exclude=function-args-by-value
Context& operator=(Context&&) = default;
Context(const Context&) = default;
Context(Context&&) = default;
~Context() = default;
};
private:
std::vector<Symbol> m_symbol_list;
std::shared_ptr<SymbolTable> m_parent_table;
std::shared_ptr<Context> m_context;
std::shared_ptr<FunctionTable> m_function_table;
std::shared_ptr<EmbedderTable<IBuiltinFunctionEmbedder>> m_builtin_function_embedder_table;
std::shared_ptr<EmbedderTable<TypeDescriptor>> m_type_embedder_table;
public:
bool
hasContext() const
{
return bool{m_context};
}
const Context&
context() const
{
Assert(m_context);
return *m_context;
}
const FunctionTable&
functionTable() const
{
Assert(m_function_table);
return *m_function_table;
}
FunctionTable&
functionTable()
{
Assert(m_function_table);
return *m_function_table;
}
const auto&
builtinFunctionEmbedderTable() const
{
Assert(m_builtin_function_embedder_table);
return *m_builtin_function_embedder_table;
}
auto&
builtinFunctionEmbedderTable()
{
Assert(m_builtin_function_embedder_table);
return *m_builtin_function_embedder_table;
}
auto&
typeEmbedderTable()
{
Assert(m_type_embedder_table);
return *m_type_embedder_table;
}
const auto&
typeEmbedderTable() const
{
Assert(m_type_embedder_table);
return *m_type_embedder_table;
}
friend std::ostream&
operator<<(std::ostream& os, const SymbolTable& symbol_table)
{
os << "-- Symbol table state -- parent : " << symbol_table.m_parent_table.get() << "\n";
for (auto i_symbol : symbol_table.m_symbol_list) {
if (i_symbol.attributes().dataType() != ASTNodeDataType::builtin_function_t) {
os << ' ' << i_symbol.name() << ": " << std::boolalpha << i_symbol.attributes() << '\n';
}
}
os << "------------------------\n";
return os;
}
void
clearValues()
{
for (auto& symbol : m_symbol_list) {
std::visit(
[](auto&& value) {
using T = std::decay_t<decltype(value)>;
value = T{};
},
symbol.attributes().value());
}
}
auto
find(const std::string& symbol, const TAO_PEGTL_NAMESPACE::position& use_position)
{
auto i_symbol = m_symbol_list.end();
for (auto i_stored_symbol = m_symbol_list.begin(); i_stored_symbol != m_symbol_list.end(); ++i_stored_symbol) {
if (i_stored_symbol->name() == symbol) {
i_symbol = i_stored_symbol;
break;
}
}
if (i_symbol != m_symbol_list.end() and (use_position.byte >= i_symbol->attributes().position().byte)) {
return std::make_pair(i_symbol, true);
} else {
if (m_parent_table) {
return m_parent_table->find(symbol, use_position);
} else {
return std::make_pair(i_symbol, false);
}
}
}
auto
add(const std::string& symbol_name, const TAO_PEGTL_NAMESPACE::position& symbol_position)
{
for (auto i_stored_symbol = m_symbol_list.begin(); i_stored_symbol != m_symbol_list.end(); ++i_stored_symbol) {
if (i_stored_symbol->name() == symbol_name) {
return std::make_pair(i_stored_symbol, false);
}
}
int32_t context_id = this->hasContext() ? m_context->id() : -1;
auto i_symbol =
m_symbol_list.emplace(m_symbol_list.end(), Symbol{symbol_name, Attributes{symbol_position, context_id}});
if (this->hasContext()) {
i_symbol->attributes().value() = m_context->getNextSymbolId();
}
return std::make_pair(i_symbol, true);
}
SymbolTable(const std::shared_ptr<SymbolTable>& parent_table, const std::shared_ptr<Context>& context)
: m_parent_table{parent_table},
m_context{context},
m_function_table{parent_table->m_function_table},
m_builtin_function_embedder_table{parent_table->m_builtin_function_embedder_table},
m_type_embedder_table{parent_table->m_type_embedder_table}
{
;
}
SymbolTable(const std::shared_ptr<SymbolTable>& parent_table) : SymbolTable{parent_table, parent_table->m_context}
{
;
}
SymbolTable()
: m_parent_table{nullptr},
m_context{nullptr},
m_function_table{std::make_shared<FunctionTable>()},
m_builtin_function_embedder_table{std::make_shared<EmbedderTable<IBuiltinFunctionEmbedder>>()},
m_type_embedder_table{std::make_shared<EmbedderTable<TypeDescriptor>>()}
{
;
}
};
#endif // SYMBOL_TABLE_HPP