/* Final validation after constant folding.
Copyright (C) 2025 Free Software Foundation, Inc.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
. */
#include "elna/boot/validation.h"
#include
namespace elna::boot
{
validation_error::validation_error(const source_position position, source_position first)
: diagnostic(position), first(first)
{
}
std::string validation_error::what() const
{
return "Duplicate case label";
}
std::optional validation_error::note() const
{
return previous_declaration_note(this->first, "Previous label here");
}
validation_visitor::validation_visitor(symbol_bag& bag, const target_info& target)
: bag(bag), constant_evaluator(this->bag, target)
{
}
void validation_visitor::visit_statements(const std::vector& statements)
{
for (statement *const body_statement : statements)
{
body_statement->accept(this);
}
}
void validation_visitor::visit(unit *unit)
{
for (declaration *unit_declaration : unit->declarations)
{
unit_declaration->accept(this);
}
if (unit->entry_point.has_value())
{
auto entry_point = this->bag.lookup("")->is_procedure();
this->bag.enter(entry_point->scope);
visit_statements(unit->entry_point->statements);
this->bag.leave();
}
}
void validation_visitor::visit(type_declaration *)
{
}
void validation_visitor::visit(variable_declaration *)
{
}
void validation_visitor::visit(procedure_declaration *declaration)
{
if (declaration->body.has_value())
{
auto procedure = this->bag.lookup(declaration->identifier.name())->is_procedure();
this->bag.enter(procedure->scope);
visit_statements(declaration->body.value().statements);
this->bag.leave();
}
}
void validation_visitor::visit(case_statement *statement)
{
for (const switch_case& case_block : statement->cases)
{
visit_statements(case_block.statements);
}
if (statement->alternative != nullptr)
{
visit_statements(*statement->alternative);
}
std::unordered_map seen;
for (const auto& case_block : statement->cases)
{
for (auto *label : case_block.labels)
{
auto value = this->constant_evaluator.evaluate(*label);
if (!value.has_value())
{
add_error(label->position(),
non_constant_expression_error::case_label{});
continue;
}
auto [case_position, inserted] = seen.try_emplace(value.value(), label->position());
if (!inserted)
{
add_error(label->position(), case_position->second);
}
}
}
}
void validation_visitor::visit(assign_statement *)
{
}
void validation_visitor::visit(if_statement *statement)
{
visit_statements(statement->branch().statements);
for (const conditional_statements *branch : statement->branches)
{
visit_statements(branch->statements);
}
if (statement->alternative != nullptr)
{
visit_statements(*statement->alternative);
}
}
void validation_visitor::visit(while_statement *statement)
{
visit_statements(statement->branch().statements);
for (const conditional_statements *branch : statement->branches)
{
visit_statements(branch->statements);
}
}
void validation_visitor::visit(repeat_statement *statement)
{
visit_statements(statement->body);
}
void validation_visitor::visit(for_statement *statement)
{
visit_statements(statement->body);
}
void validation_visitor::visit(defer_statement *statement)
{
visit_statements(statement->statements);
}
void validation_visitor::visit(empty_statement *)
{
}
void validation_visitor::visit(procedure_call *)
{
}
}