Introduce a procedure type

This commit is contained in:
2024-05-19 00:43:59 +02:00
parent 9f2c5ad9e3
commit ebd68d7878
8 changed files with 128 additions and 32 deletions

View File

@ -5,15 +5,16 @@
namespace elna::source
{
name_analysis_visitor::name_analysis_visitor(std::shared_ptr<symbol_table> table,
const std::filesystem::path& filename)
: table(table), filename(filename)
const std::filesystem::path& filename, const std::size_t target_pointer_size)
: table(table), filename(filename), pointer_size(target_pointer_size)
{
}
void name_analysis_visitor::visit(constant_definition *definition)
{
auto constant_type = std::make_shared<const class type>(int_type);
this->table->enter(definition->identifier(),
std::make_shared<constant_info>(constant_info(definition->body().number())));
std::make_shared<constant_info>(constant_type, definition->body().number()));
}
std::shared_ptr<const type> name_analysis_visitor::convert_declaration_type(const type_expression& ast_type) const
@ -42,22 +43,30 @@ namespace elna::source
void name_analysis_visitor::visit(program *program)
{
this->table->enter("main", std::make_shared<procedure_info>(this->table));
class procedure_type main_type{ std::vector<std::shared_ptr<const class type>>(), this->pointer_size };
this->table->enter("main", std::make_shared<procedure_info>(main_type, this->table));
empty_visitor::visit(program);
}
void name_analysis_visitor::visit(procedure_definition *procedure)
{
auto info = std::make_shared<procedure_info>(this->table);
this->table->enter(procedure->identifier(), info);
this->table = info->scope();
std::vector<std::shared_ptr<const type>> arguments;
for (auto& parameter : procedure->parameters())
{
auto declaration_type = convert_declaration_type(parameter->type());
arguments.push_back(declaration_type);
}
procedure_type definition_type{ std::move(arguments), this->pointer_size };
auto info = std::make_shared<procedure_info>(definition_type, this->table);
this->table->enter(parameter->identifier(),
std::make_shared<parameter_info>(declaration_type));
this->table->enter(procedure->identifier(), info);
this->table = info->scope();
for (std::size_t i = 0; i < procedure->parameters().size(); ++i)
{
this->table->enter(procedure->parameters().at(i)->identifier(),
std::make_shared<parameter_info>(definition_type.arguments.at(i)));
}
procedure->body().accept(this);
@ -123,7 +132,7 @@ namespace elna::source
}
type_analysis_visitor::type_analysis_visitor(std::shared_ptr<symbol_table> table,
const std::filesystem::path& filename, std::size_t target_pointer_size)
const std::filesystem::path& filename, const std::size_t target_pointer_size)
: table(table), filename(filename), pointer_size(target_pointer_size)
{
}
@ -140,9 +149,14 @@ namespace elna::source
program->body().accept(this);
}
void type_analysis_visitor::visit(procedure_definition *definition)
void type_analysis_visitor::visit(procedure_definition *procedure)
{
definition->body().accept(this);
auto info = std::dynamic_pointer_cast<procedure_info>(this->table->lookup(procedure->identifier()));
this->table = info->scope();
procedure->body().accept(this);
this->table = info->scope()->scope();
}
void type_analysis_visitor::visit(integer_literal *literal)
@ -182,6 +196,32 @@ namespace elna::source
}
}
void type_analysis_visitor::visit(call_statement *statement)
{
auto call_info = std::dynamic_pointer_cast<intrinsic_info>(this->table->lookup(statement->name()));
std::size_t i{ 0 };
for (const auto& argument : statement->arguments())
{
argument->accept(this);
if (argument->data_type != nullptr && i < call_info->type()->arguments.size()
&& call_info->type()->arguments[i] != argument->data_type)
{
auto new_error = std::make_unique<type_mismatch>(argument->data_type,
type_mismatch::operation::argument, this->filename, argument->position());
m_errors.push_back(std::move(new_error));
}
++i;
}
}
void type_analysis_visitor::visit(constant_definition *definition)
{
definition->body().accept(this);
}
const std::list<std::unique_ptr<error>>& type_analysis_visitor::errors() const noexcept
{
return m_errors;

View File

@ -55,8 +55,8 @@ namespace elna::source
return m_type;
}
constant_info::constant_info(const std::int32_t value)
: m_value(value)
constant_info::constant_info(const std::shared_ptr<const class type> type, const std::int32_t value)
: m_type(type), m_value(value)
{
}
@ -64,6 +64,11 @@ namespace elna::source
{
}
std::shared_ptr<const class type> constant_info::type() const noexcept
{
return m_type;
}
std::int32_t constant_info::value() const noexcept
{
return m_value;
@ -97,17 +102,27 @@ namespace elna::source
return m_type;
}
intrinsic_info::intrinsic_info(const class procedure_type& type)
: m_type(std::make_shared<procedure_type>(type))
{
}
intrinsic_info::~intrinsic_info()
{
}
std::size_t intrinsic_info::parameter_stack_size() const noexcept
std::shared_ptr<const class procedure_type> intrinsic_info::type() const noexcept
{
return this->parameter_infos.size() * sizeof(std::int32_t);
return m_type;
}
procedure_info::procedure_info(std::shared_ptr<symbol_table> outer_scope)
: local_table(std::make_shared<symbol_table>(outer_scope))
std::size_t intrinsic_info::parameter_stack_size() const noexcept
{
return type()->arguments.size() * sizeof(std::int32_t);
}
procedure_info::procedure_info(const class procedure_type& type, std::shared_ptr<symbol_table> outer_scope)
: intrinsic_info(type), local_table(std::make_shared<symbol_table>(outer_scope))
{
}

View File

@ -21,4 +21,9 @@ namespace elna::source
: type(byte_size), base_type(base_type)
{
}
procedure_type::procedure_type(std::vector<std::shared_ptr<const type>> arguments, const std::size_t byte_size)
: arguments(std::move(arguments)), type(byte_size)
{
}
}