|
2 | 2 |
|
3 | 3 | #include "symbol_table.h"
|
4 | 4 |
|
| 5 | +#include <algorithm> |
5 | 6 | #include <util/invariant.h>
|
| 7 | +#include <util/validate.h> |
6 | 8 |
|
7 | 9 | /// Move or copy a new symbol to the symbol table
|
8 | 10 | /// \remark: This is a nicer interface than move and achieves the same
|
@@ -114,3 +116,97 @@ void symbol_tablet::erase(const symbolst::const_iterator &entry)
|
114 | 116 |
|
115 | 117 | internal_symbols.erase(entry);
|
116 | 118 | }
|
| 119 | + |
| 120 | +/// Check whether the symbol table is in a valid state |
| 121 | +/// \param vm Determine whether to throw exceptions or trigger INVARIANT |
| 122 | +/// when validation fails |
| 123 | +void symbol_tablet::validate(const validation_modet vm) const |
| 124 | +{ |
| 125 | + // Check that identifiers are mapped to the correct symbol |
| 126 | + for(const auto &elem : symbols) |
| 127 | + { |
| 128 | + const auto symbol_key = elem.first; |
| 129 | + const auto &symbol = elem.second; |
| 130 | + |
| 131 | + // Check that symbols[id].name == id |
| 132 | + DATA_CHECK_WITH_DIAGNOSTICS( |
| 133 | + symbol.name == symbol_key, |
| 134 | + "Symbol table entry must map to a symbol with the correct identifier", |
| 135 | + "Symbol table key '", |
| 136 | + symbol_key, |
| 137 | + "' maps to symbol '", |
| 138 | + symbol.name, |
| 139 | + "'"); |
| 140 | + |
| 141 | + // Check that the symbol basename is mapped to its full name |
| 142 | + if(!symbol.base_name.empty()) |
| 143 | + { |
| 144 | + const auto base_map_search = |
| 145 | + symbol_base_map.equal_range(symbol.base_name); |
| 146 | + const bool base_map_matches_symbol = |
| 147 | + std::find_if( |
| 148 | + base_map_search.first, |
| 149 | + base_map_search.second, |
| 150 | + [&symbol_key](const typename symbol_base_mapt::value_type &match) { |
| 151 | + return match.second == symbol_key; |
| 152 | + }) != symbol_base_map.end(); |
| 153 | + |
| 154 | + DATA_CHECK_WITH_DIAGNOSTICS( |
| 155 | + base_map_matches_symbol, |
| 156 | + "The base_name of a symbol should map to itself", |
| 157 | + "Symbol table key '", |
| 158 | + symbol_key, |
| 159 | + "' has a base_name '", |
| 160 | + symbol.base_name, |
| 161 | + "' which does not map to itself"); |
| 162 | + } |
| 163 | + |
| 164 | + // Check that the module name of the symbol is mapped to the full name |
| 165 | + if(!symbol.module.empty()) |
| 166 | + { |
| 167 | + auto module_map_search = symbol_module_map.equal_range(symbol.module); |
| 168 | + bool module_map_matches_symbol = |
| 169 | + std::find_if( |
| 170 | + module_map_search.first, |
| 171 | + module_map_search.second, |
| 172 | + [&symbol_key](const typename symbol_module_mapt::value_type &match) { |
| 173 | + return match.second == symbol_key; |
| 174 | + }) != symbol_module_map.end(); |
| 175 | + |
| 176 | + DATA_CHECK_WITH_DIAGNOSTICS( |
| 177 | + module_map_matches_symbol, |
| 178 | + "Symbol table module map should map to symbol", |
| 179 | + "Symbol table key '", |
| 180 | + symbol_key, |
| 181 | + "' has a module name of '", |
| 182 | + symbol.module, |
| 183 | + "' which does not map to itself"); |
| 184 | + } |
| 185 | + } |
| 186 | + |
| 187 | + // Check that all base name map entries point to a symbol entry |
| 188 | + for(auto base_map_entry : symbol_base_map) |
| 189 | + { |
| 190 | + DATA_CHECK_WITH_DIAGNOSTICS( |
| 191 | + has_symbol(base_map_entry.second), |
| 192 | + "Symbol table base_name map entries must map to a symbol name", |
| 193 | + "base_name map entry '", |
| 194 | + base_map_entry.first, |
| 195 | + "' maps to non-existant symbol name '", |
| 196 | + base_map_entry.second, |
| 197 | + "'"); |
| 198 | + } |
| 199 | + |
| 200 | + // Check that all module map entries point to a symbol entry |
| 201 | + for(auto module_map_entry : symbol_module_map) |
| 202 | + { |
| 203 | + DATA_CHECK_WITH_DIAGNOSTICS( |
| 204 | + has_symbol(module_map_entry.second), |
| 205 | + "Symbol table module map entries must map to a symbol name", |
| 206 | + "base_name map entry '", |
| 207 | + module_map_entry.first, |
| 208 | + "' maps to non-existant symbol name '", |
| 209 | + module_map_entry.second, |
| 210 | + "'"); |
| 211 | + } |
| 212 | +} |
0 commit comments