Forbid redefenition of builtin types

This commit is contained in:
2025-03-14 11:22:11 +01:00
parent ac084be7f5
commit fa73f14070
6 changed files with 124 additions and 39 deletions

View File

@ -15,6 +15,8 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include <set>
#include "elna/boot/semantic.h"
namespace elna
@ -52,7 +54,8 @@ namespace boot
{
for (type_definition *const type : program->types)
{
if (!this->unresolved.insert({ type->identifier, std::make_shared<alias_type>() }).second)
if (!this->unresolved.insert({ type->identifier, std::make_shared<alias_type>(type->identifier) }).second
|| this->symbols->contains(type->identifier))
{
add_error<already_declared_error>(type->identifier, this->input_file, type->position());
}
@ -61,6 +64,11 @@ namespace boot
{
type->accept(this);
}
for (auto& unresolved : this->unresolved)
{
auto info = std::make_shared<type_info>(type_info(type(unresolved.second)));
this->symbols->enter(std::move(unresolved.first), info);
}
}
void declaration_visitor::visit(type_definition *definition)
@ -79,7 +87,7 @@ namespace boot
{
this->current_type = type(unresolved_alias->second);
}
else if (auto from_symbol_table = this->symbols.lookup(type_expression->name))
else if (auto from_symbol_table = this->symbols->lookup(type_expression->name))
{
this->current_type = from_symbol_table->is_type()->symbol;
}
@ -102,32 +110,54 @@ namespace boot
this->current_type = type(std::make_shared<array_type>(this->current_type, type_expression->size));
}
bool declaration_visitor::build_composite_type(const std::vector<field_declaration>& declarations,
std::vector<type_field>& fields)
{
std::set<std::string> field_names;
for (auto& field : declarations)
{
if (field_names.find(field.first) != field_names.cend())
{
add_error<already_declared_error>(field.first, this->input_file, field.second->position());
this->current_type = type();
return false;
}
field.second->accept(this);
if (!this->current_type.empty())
{
fields.push_back({ field.first, type(this->current_type) });
}
}
return true;
}
void declaration_visitor::visit(record_type_expression *type_expression)
{
auto type_definition = std::make_shared<record_type>();
for (auto& field : type_expression->fields)
if (build_composite_type(type_expression->fields, type_definition->fields))
{
field.second->accept(this);
if (!this->current_type.empty())
{
type_definition->fields.push_back({ field.first, type(this->current_type) });
}
this->current_type = type(type_definition);
}
else
{
this->current_type = type();
}
this->current_type = type(type_definition);
}
void declaration_visitor::visit(union_type_expression *type_expression)
{
auto type_definition = std::make_shared<union_type>();
for (auto& field : type_expression->fields)
if (build_composite_type(type_expression->fields, type_definition->fields))
{
field.second->accept(this);
type_definition->fields.push_back({ field.first, type(this->current_type) });
this->current_type = type(type_definition);
}
else
{
this->current_type = type();
}
this->current_type = type(type_definition);
}
void declaration_visitor::visit(procedure_type_expression *type_expression)

View File

@ -247,6 +247,11 @@ namespace boot
return tag == type_tag::empty;
}
alias_type::alias_type(const std::string& name)
: name(name), reference()
{
}
pointer_type::pointer_type(type base)
: base(base)
{