Support multiple function arguments

This commit is contained in:
2024-03-29 11:01:19 +01:00
parent 07521f2b58
commit e04a816024
8 changed files with 137 additions and 50 deletions

View File

@ -14,6 +14,10 @@ namespace elna::source
void empty_visitor::visit(procedure_definition *definition)
{
for (auto& parameter : definition->parameters())
{
parameter->accept(this);
}
definition->body().accept(this);
}

View File

@ -42,8 +42,16 @@ namespace elna::source
{
if (scope == nullptr)
{
enter("writei", std::make_shared<intrinsic_info>());
enter("writeb", std::make_shared<intrinsic_info>());
auto writei = std::make_shared<intrinsic_info>();
writei->parameter_infos.emplace_back(int_type);
enter("writei", writei);
auto writeb = std::make_shared<intrinsic_info>();
writeb->parameter_infos.emplace_back(boolean_type);
enter("writeb", writeb);
enter("Boolean", std::make_shared<type_info>(boolean_type));
enter("Int", std::make_shared<type_info>(int_type));
}
}
@ -108,10 +116,20 @@ namespace elna::source
return m_value;
}
variable_info::variable_info(const class type& type)
: m_type(type)
{
}
variable_info::~variable_info()
{
}
const class type& variable_info::type() const noexcept
{
return m_type;
}
parameter_info::parameter_info(const class type& type)
: m_type(type)
{
@ -126,6 +144,15 @@ namespace elna::source
return m_type;
}
intrinsic_info::~intrinsic_info()
{
}
std::size_t intrinsic_info::parameter_stack_size() const noexcept
{
return this->parameter_infos.size() * sizeof(std::int32_t);
}
procedure_info::procedure_info(std::shared_ptr<symbol_table> outer_scope)
: local_table(std::make_shared<symbol_table>(outer_scope))
{
@ -135,22 +162,13 @@ namespace elna::source
{
}
std::size_t procedure_info::stack_size() const noexcept
{
return this->local_stack_size;
}
void procedure_info::stack_size(const std::size_t size) noexcept
{
this->local_stack_size = size;
}
std::shared_ptr<symbol_table> procedure_info::scope()
{
return local_table;
}
intrinsic_info::~intrinsic_info()
std::size_t procedure_info::stack_size() const noexcept
{
return local_stack_size + argument_stack_size;
}
}

View File

@ -16,8 +16,9 @@ namespace elna::source
void name_analysis_visitor::visit(declaration *declaration)
{
auto declaration_type = std::dynamic_pointer_cast<type_info>(table->lookup(declaration->type()));
this->table->enter(declaration->identifier(),
std::make_shared<variable_info>(variable_info()));
std::make_shared<variable_info>(declaration_type->type()));
}
void name_analysis_visitor::visit(program *program)
@ -31,7 +32,15 @@ namespace elna::source
auto info = std::make_shared<procedure_info>(this->table);
this->table->enter(procedure->identifier(), info);
this->table = info->scope();
empty_visitor::visit(procedure);
for (auto& parameter : procedure->parameters())
{
auto declaration_type = std::dynamic_pointer_cast<type_info>(table->lookup(parameter->type()));
this->table->enter(parameter->identifier(),
std::make_shared<parameter_info>(declaration_type->type()));
}
procedure->body().accept(this);
this->table = info->scope()->scope();
}
@ -42,22 +51,49 @@ namespace elna::source
void allocator_visitor::visit(declaration *declaration)
{
this->offset -= sizeof(std::int32_t);
auto declaration_info = this->table->lookup(declaration->identifier());
if (auto variable = std::dynamic_pointer_cast<variable_info>(declaration_info))
{
this->local_offset -= sizeof(std::int32_t);
variable->offset = this->local_offset;
}
else if (auto parameter = std::dynamic_pointer_cast<parameter_info>(declaration_info))
{
parameter->offset = this->argument_offset;
this->argument_offset += sizeof(std::int32_t);
}
}
void allocator_visitor::visit(program *program)
{
this->offset = 0;
this->local_offset = 0;
this->argument_offset = 0;
empty_visitor::visit(program);
std::dynamic_pointer_cast<procedure_info>(table->lookup("main"))
->stack_size(std::abs(this->offset));
std::dynamic_pointer_cast<procedure_info>(table->lookup("main"))->local_stack_size =
std::abs(this->local_offset);
}
void allocator_visitor::visit(procedure_definition *procedure)
{
this->offset = 0;
this->local_offset = 0;
this->argument_offset = 0;
auto info = std::dynamic_pointer_cast<procedure_info>(this->table->lookup(procedure->identifier()));
this->table = info->scope();
empty_visitor::visit(procedure);
std::dynamic_pointer_cast<procedure_info>(table->lookup(procedure->identifier()))
->stack_size(std::abs(this->offset));
this->table = info->scope()->scope();
info->local_stack_size = std::abs(this->local_offset);
info->argument_stack_size = this->argument_offset;
}
void allocator_visitor::visit(call_statement *statement)
{
auto call_info = std::dynamic_pointer_cast<intrinsic_info>(this->table->lookup(statement->name()));
this->argument_offset = std::max(static_cast<std::size_t>(this->argument_offset),
call_info->parameter_stack_size());
}
}