Check for duplicate fields in the declaration visitor

This commit is contained in:
2025-03-15 23:01:05 +01:00
parent fa73f14070
commit f6e0ead4fb
9 changed files with 88 additions and 151 deletions

View File

@ -50,5 +50,20 @@ namespace gcc
TYPE_FIELDS(elna_string_type_node) = chainon(elna_string_ptr_field_node, elna_string_length_field_node);
layout_type(elna_string_type_node);
}
std::shared_ptr<symbol_table> builtin_symbol_table()
{
std::shared_ptr<elna::gcc::symbol_table> symbol_table = std::make_shared<elna::gcc::symbol_table>();
symbol_table->enter("Int", elna_int_type_node);
symbol_table->enter("Word", elna_word_type_node);
symbol_table->enter("Char", elna_char_type_node);
symbol_table->enter("Bool", elna_bool_type_node);
symbol_table->enter("Byte", elna_byte_type_node);
symbol_table->enter("Float", elna_float_type_node);
symbol_table->enter("String", elna_string_type_node);
return symbol_table;
}
}
}

View File

@ -16,6 +16,7 @@ along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include <array>
#include <set>
#include "elna/gcc/elna-generic.h"
#include "elna/gcc/elna-diagnostic.h"
@ -32,21 +33,16 @@ along with GCC; see the file COPYING3. If not see
#include "varasm.h"
#include "fold-const.h"
#include "langhooks.h"
#include <set>
namespace elna
{
namespace gcc
{
tree handle_symbol(const std::string& symbol_name, const boot::type& type,
std::shared_ptr<boot::symbol_table> from, std::shared_ptr<symbol_table> to);
tree get_inner_alias(const boot::type& type,
std::shared_ptr<boot::symbol_table> from, std::shared_ptr<symbol_table> to)
tree get_inner_alias(const boot::type& type, std::shared_ptr<symbol_table> symbols)
{
if (auto reference = type.get<boot::primitive_type>())
{
return to->lookup(reference->identifier);
return symbols->lookup(reference->identifier);
}
else if (auto reference = type.get<boot::record_type>())
{
@ -58,7 +54,7 @@ namespace gcc
}
else if (auto reference = type.get<boot::pointer_type>())
{
return build_pointer_type_for_mode(get_inner_alias(reference->base, from, to), VOIDmode, true);
return build_pointer_type_for_mode(get_inner_alias(reference->base, symbols), VOIDmode, true);
}
else if (auto reference = type.get<boot::array_type>())
{
@ -66,45 +62,40 @@ namespace gcc
tree upper_bound = build_int_cst_type(integer_type_node, reference->size);
tree range_type = build_range_type(integer_type_node, lower_bound, upper_bound);
return build_array_type(get_inner_alias(reference->base, from, to), range_type);
return build_array_type(get_inner_alias(reference->base, symbols), range_type);
}
else if (auto reference = type.get<boot::alias_type>())
{
return handle_symbol(reference->name, reference->reference, from, to);
return handle_symbol(reference->name, reference->reference, symbols);
}
return error_mark_node;
}
tree handle_symbol(const std::string& symbol_name, const boot::type& type,
std::shared_ptr<boot::symbol_table> from, std::shared_ptr<symbol_table> to)
tree handle_symbol(const std::string& symbol_name, const boot::type& type, std::shared_ptr<symbol_table> symbols)
{
auto looked_up = to->lookup(symbol_name);
auto looked_up = symbols->lookup(symbol_name);
if (looked_up == NULL_TREE)
{
looked_up = get_inner_alias(type, from, to);
to->enter(symbol_name, looked_up);
looked_up = get_inner_alias(type, symbols);
symbols->enter(symbol_name, looked_up);
}
return looked_up;
}
std::deque<std::unique_ptr<boot::error>> do_semantic_analysis(const char *path,
std::unique_ptr<boot::program>& ast, std::shared_ptr<symbol_table> symbols)
std::unique_ptr<boot::program>& ast, std::shared_ptr<boot::symbol_table> info_table,
std::shared_ptr<symbol_table> symbols)
{
auto info_table = boot::builtin_symbol_table();
boot::declaration_visitor declaration_visitor(path, info_table);
declaration_visitor.visit(ast.get());
if (declaration_visitor.errors().empty())
{
for (auto& [symbol_name, symbol_info] : *info_table)
for (auto& [symbol_name, symbol_info] : declaration_visitor.unresolved)
{
handle_symbol(symbol_name, symbol_info->is_type()->symbol, info_table, symbols);
}
for (auto& [symbol_name, symbol_info] : *info_table)
{
// printf("%s\n", symbol_name.c_str());
handle_symbol(symbol_name, boot::type(symbol_info), symbols);
}
}
return std::move(declaration_visitor.errors());
@ -418,11 +409,6 @@ namespace gcc
return bind_expr;
}
tree generic_visitor::lookup(const std::string& name)
{
return this->symbols->lookup(name);
}
void generic_visitor::visit(boot::number_literal<std::int32_t> *literal)
{
this->current_expression = build_int_cst(elna_int_type_node, literal->value);
@ -775,7 +761,7 @@ namespace gcc
void generic_visitor::visit(boot::type_definition *definition)
{
location_t definition_location = get_location(&definition->position());
this->current_expression = lookup(definition->identifier);
this->current_expression = this->symbols->lookup(definition->identifier);
definition->body().accept(this);
tree definition_tree = build_decl(definition_location, TYPE_DECL,
@ -809,6 +795,36 @@ namespace gcc
return build_function_type_array(return_type, type.parameters.size(), parameter_types.data());
}
void generic_visitor::build_composite_type(const std::vector<boot::field_declaration>& fields,
tree composite_type_node)
{
std::set<std::string> field_names;
for (auto& field : fields)
{
if (field_names.find(field.first) != field_names.cend())
{
error_at(get_location(&field.second->position()), "repeated field name");
this->current_expression = error_mark_node;
return;
}
field_names.insert(field.first);
field.second->accept(this);
if (this->current_expression == NULL_TREE || this->current_expression == error_mark_node)
{
return;
}
tree field_declaration = build_field(get_location(&field.second->position()),
composite_type_node, field.first, this->current_expression);
TYPE_FIELDS(composite_type_node) = chainon(TYPE_FIELDS(composite_type_node), field_declaration);
this->current_expression = NULL_TREE;
}
layout_type(composite_type_node);
this->current_expression = composite_type_node;
}
void generic_visitor::visit(boot::variable_declaration *declaration)
{
declaration->variable_type().accept(this);
@ -847,7 +863,7 @@ namespace gcc
void generic_visitor::visit(boot::variable_expression *expression)
{
auto symbol = lookup(expression->name);
auto symbol = this->symbols->lookup(expression->name);
if (symbol == NULL_TREE)
{
@ -1140,7 +1156,7 @@ namespace gcc
void generic_visitor::visit(boot::primitive_type_expression *type)
{
tree symbol = lookup(type->name);
tree symbol = this->symbols->lookup(type->name);
if (symbol == NULL_TREE || !TYPE_P(symbol))
{
@ -1181,66 +1197,20 @@ namespace gcc
void generic_visitor::visit(boot::record_type_expression *type)
{
std::set<std::string> field_names;
tree composite_type_node = this->current_expression == NULL_TREE
? make_node(RECORD_TYPE)
: this->current_expression;
for (auto& field : type->fields)
{
if (field_names.find(field.first) != field_names.cend())
{
error_at(get_location(&field.second->position()), "repeated field name");
this->current_expression = error_mark_node;
return;
}
field_names.insert(field.first);
field.second->accept(this);
if (this->current_expression == NULL_TREE || this->current_expression == error_mark_node)
{
return;
}
tree field_declaration = build_field(get_location(&field.second->position()),
composite_type_node, field.first, this->current_expression);
TYPE_FIELDS(composite_type_node) = chainon(TYPE_FIELDS(composite_type_node), field_declaration);
this->current_expression = NULL_TREE;
}
layout_type(composite_type_node);
this->current_expression = composite_type_node;
build_composite_type(type->fields, composite_type_node);
}
void generic_visitor::visit(boot::union_type_expression *type)
{
std::set<std::string> field_names;
tree composite_type_node = this->current_expression == NULL_TREE
? make_node(UNION_TYPE)
: this->current_expression;
for (auto& field : type->fields)
{
if (field_names.find(field.first) != field_names.cend())
{
error_at(get_location(&field.second->position()), "repeated field name");
this->current_expression = error_mark_node;
return;
}
field_names.insert(field.first);
field.second->accept(this);
if (this->current_expression == NULL_TREE || this->current_expression == error_mark_node)
{
return;
}
tree field_declaration = build_field(get_location(&field.second->position()),
composite_type_node, field.first, this->current_expression);
TYPE_FIELDS(composite_type_node) = chainon(TYPE_FIELDS(composite_type_node), field_declaration);
this->current_expression = NULL_TREE;
}
layout_type(composite_type_node);
this->current_expression = composite_type_node;
build_composite_type(type->fields, composite_type_node);
}
void generic_visitor::visit(boot::procedure_type_expression *type)

View File

@ -83,17 +83,10 @@ static void elna_parse_file(const char *filename)
}
else
{
std::shared_ptr<elna::gcc::symbol_table> symbol_table = std::make_shared<elna::gcc::symbol_table>();
std::shared_ptr<elna::boot::symbol_table> info_table = elna::boot::builtin_symbol_table();
std::shared_ptr<elna::gcc::symbol_table> symbol_table = elna::gcc::builtin_symbol_table();
symbol_table->enter("Int", elna_int_type_node);
symbol_table->enter("Word", elna_word_type_node);
symbol_table->enter("Char", elna_char_type_node);
symbol_table->enter("Bool", elna_bool_type_node);
symbol_table->enter("Byte", elna_byte_type_node);
symbol_table->enter("Float", elna_float_type_node);
symbol_table->enter("String", elna_string_type_node);
auto semantic_errors = elna::gcc::do_semantic_analysis(filename, driver.tree, symbol_table);
auto semantic_errors = elna::gcc::do_semantic_analysis(filename, driver.tree, info_table, symbol_table);
if (semantic_errors.empty())
{