119 lines
3.8 KiB
C++
119 lines
3.8 KiB
C++
#include "elna/source/semantic.hpp"
|
|
#include "elna/source/types.hpp"
|
|
#include <cstdlib>
|
|
|
|
namespace elna::source
|
|
{
|
|
name_analysis_visitor::name_analysis_visitor(std::shared_ptr<symbol_table> table)
|
|
: table(table)
|
|
{
|
|
}
|
|
|
|
void name_analysis_visitor::visit(constant_definition *definition)
|
|
{
|
|
this->table->enter(definition->identifier(),
|
|
std::make_shared<constant_info>(constant_info(definition->body().number())));
|
|
}
|
|
|
|
std::shared_ptr<const type> name_analysis_visitor::convert_declaration_type(const type_expression& ast_type) const
|
|
{
|
|
auto variable_type = std::dynamic_pointer_cast<type_info>(table->lookup(ast_type.base()))
|
|
->type();
|
|
std::shared_ptr<type> declaration_type;
|
|
|
|
if (ast_type.is_pointer())
|
|
{
|
|
return std::make_shared<pointer_type>(variable_type, 4);
|
|
}
|
|
else
|
|
{
|
|
return variable_type;
|
|
}
|
|
}
|
|
|
|
void name_analysis_visitor::visit(declaration *declaration)
|
|
{
|
|
std::shared_ptr<const type> declaration_type = convert_declaration_type(declaration->type());
|
|
|
|
this->table->enter(declaration->identifier(),
|
|
std::make_shared<variable_info>(declaration_type));
|
|
}
|
|
|
|
void name_analysis_visitor::visit(program *program)
|
|
{
|
|
this->table->enter("main", std::make_shared<procedure_info>(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();
|
|
|
|
for (auto& parameter : procedure->parameters())
|
|
{
|
|
auto declaration_type = convert_declaration_type(parameter->type());
|
|
|
|
this->table->enter(parameter->identifier(),
|
|
std::make_shared<parameter_info>(declaration_type));
|
|
}
|
|
procedure->body().accept(this);
|
|
|
|
this->table = info->scope()->scope();
|
|
}
|
|
|
|
allocator_visitor::allocator_visitor(std::shared_ptr<symbol_table> table)
|
|
: table(table)
|
|
{
|
|
}
|
|
|
|
void allocator_visitor::visit(declaration *declaration)
|
|
{
|
|
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->local_offset = 0;
|
|
this->argument_offset = 0;
|
|
|
|
empty_visitor::visit(program);
|
|
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->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);
|
|
|
|
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());
|
|
}
|
|
}
|