Generate top-level code from symbol tables
This commit is contained in:
@ -17,6 +17,8 @@ along with GCC; see the file COPYING3. If not see
|
||||
|
||||
#include "elna/boot/semantic.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace elna::boot
|
||||
{
|
||||
undeclared_error::undeclared_error(const std::string& identifier, const char *path, const struct position position)
|
||||
@ -46,6 +48,17 @@ namespace elna::boot
|
||||
{
|
||||
}
|
||||
|
||||
field_duplication_error::field_duplication_error(const std::string& field_name,
|
||||
const char *path, const struct position)
|
||||
: error(path, position), field_name(field_name)
|
||||
{
|
||||
}
|
||||
|
||||
std::string field_duplication_error::what() const
|
||||
{
|
||||
return "Repeated field name '" + field_name + "'";
|
||||
}
|
||||
|
||||
procedure_type declaration_visitor::build_procedure(procedure_type_expression& type_expression)
|
||||
{
|
||||
procedure_type::return_t result_return;
|
||||
@ -122,15 +135,33 @@ namespace elna::boot
|
||||
this->current_type = type(std::make_shared<array_type>(this->current_type, type_expression->size));
|
||||
}
|
||||
|
||||
std::vector<type_field> declaration_visitor::build_composite_type(const std::vector<field_declaration>& fields)
|
||||
{
|
||||
std::vector<type_field> result;
|
||||
std::set<std::string> field_names;
|
||||
|
||||
for (auto& field : fields)
|
||||
{
|
||||
if (field_names.find(field.first) != field_names.cend())
|
||||
{
|
||||
add_error<field_duplication_error>(field.first, this->input_file, field.second->position());
|
||||
}
|
||||
else
|
||||
{
|
||||
field_names.insert(field.first);
|
||||
field.second->accept(this);
|
||||
result.push_back(std::make_pair(field.first, this->current_type));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(record_type_expression *type_expression)
|
||||
{
|
||||
auto result_type = std::make_shared<record_type>();
|
||||
|
||||
for (auto& field : type_expression->fields)
|
||||
{
|
||||
field.second->accept(this);
|
||||
result_type->fields.push_back(std::make_pair(field.first, this->current_type));
|
||||
}
|
||||
result_type->fields = build_composite_type(type_expression->fields);
|
||||
|
||||
this->current_type = type(result_type);
|
||||
}
|
||||
|
||||
@ -138,11 +169,8 @@ namespace elna::boot
|
||||
{
|
||||
auto result_type = std::make_shared<union_type>();
|
||||
|
||||
for (const field_declaration& field : type_expression->fields)
|
||||
{
|
||||
field.second->accept(this);
|
||||
result_type->fields.push_back(std::make_pair(field.first, this->current_type));
|
||||
}
|
||||
result_type->fields = build_composite_type(type_expression->fields);
|
||||
|
||||
this->current_type = type(result_type);
|
||||
}
|
||||
|
||||
@ -179,14 +207,15 @@ namespace elna::boot
|
||||
|
||||
void declaration_visitor::visit(procedure_declaration *definition)
|
||||
{
|
||||
std::shared_ptr<procedure_info> info = std::make_shared<procedure_info>(
|
||||
build_procedure(definition->heading()), definition->parameter_names);
|
||||
|
||||
this->symbols->enter(definition->identifier.identifier, info);
|
||||
this->symbols = std::make_shared<symbol_table>(this->symbols);
|
||||
std::shared_ptr<procedure_info> info;
|
||||
|
||||
if (definition->body.has_value())
|
||||
{
|
||||
info = std::make_shared<procedure_info>(build_procedure(definition->heading()),
|
||||
definition->parameter_names, this->symbols);
|
||||
|
||||
this->symbols = info->symbols;
|
||||
|
||||
for (constant_declaration *const constant : definition->body.value().constants())
|
||||
{
|
||||
constant->accept(this);
|
||||
@ -199,8 +228,14 @@ namespace elna::boot
|
||||
{
|
||||
statement->accept(this);
|
||||
}
|
||||
this->symbols = this->symbols->scope();
|
||||
}
|
||||
this->symbols = this->symbols->scope();
|
||||
else
|
||||
{
|
||||
info = std::make_shared<procedure_info>(build_procedure(definition->heading()),
|
||||
definition->parameter_names);
|
||||
}
|
||||
this->symbols->enter(definition->identifier.identifier, info);
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(assign_statement *statement)
|
||||
@ -283,6 +318,13 @@ namespace elna::boot
|
||||
statement->accept(this);
|
||||
}
|
||||
}
|
||||
if (statement->alternative != nullptr)
|
||||
{
|
||||
for (struct statement *const statement : *statement->alternative)
|
||||
{
|
||||
statement->accept(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(procedure_call *call)
|
||||
@ -330,6 +372,7 @@ namespace elna::boot
|
||||
if (!trait->parameters.empty())
|
||||
{
|
||||
trait->parameters.front()->accept(this);
|
||||
trait->types.push_back(this->current_type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,6 +380,7 @@ namespace elna::boot
|
||||
{
|
||||
expression->value().accept(this);
|
||||
expression->target().accept(this);
|
||||
expression->expression_type = this->current_type;
|
||||
}
|
||||
|
||||
void declaration_visitor::visit(binary_expression *expression)
|
||||
|
@ -312,9 +312,14 @@ namespace elna::boot
|
||||
return std::static_pointer_cast<type_info>(shared_from_this());
|
||||
}
|
||||
|
||||
procedure_info::procedure_info(const procedure_type symbol, const std::vector<std::string> names)
|
||||
procedure_info::procedure_info(const procedure_type symbol, const std::vector<std::string> names,
|
||||
std::shared_ptr<symbol_table> parent_table)
|
||||
: symbol(symbol), names(names)
|
||||
{
|
||||
if (parent_table != nullptr)
|
||||
{
|
||||
this->symbols = std::make_shared<symbol_table>(parent_table);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<procedure_info> procedure_info::is_procedure()
|
||||
|
Reference in New Issue
Block a user