#include "elna/source/semantic.hpp" #include namespace elna::source { name_analysis_visitor::name_analysis_visitor(std::shared_ptr table) : table(table) { } void name_analysis_visitor::visit(constant_definition *definition) { this->table->enter(definition->identifier(), std::make_shared(constant_info(definition->body().number()))); } void name_analysis_visitor::visit(declaration *declaration) { auto declaration_type = std::dynamic_pointer_cast(table->lookup(declaration->type())); this->table->enter(declaration->identifier(), std::make_shared(declaration_type->type())); } void name_analysis_visitor::visit(program *program) { this->table->enter("main", std::make_shared(this->table)); empty_visitor::visit(program); } void name_analysis_visitor::visit(procedure_definition *procedure) { auto info = std::make_shared(this->table); this->table->enter(procedure->identifier(), info); this->table = info->scope(); for (auto& parameter : procedure->parameters()) { auto declaration_type = std::dynamic_pointer_cast(table->lookup(parameter->type())); this->table->enter(parameter->identifier(), std::make_shared(declaration_type->type())); } procedure->body().accept(this); this->table = info->scope()->scope(); } allocator_visitor::allocator_visitor(std::shared_ptr table) : table(table) { } void allocator_visitor::visit(declaration *declaration) { auto declaration_info = this->table->lookup(declaration->identifier()); if (auto variable = std::dynamic_pointer_cast(declaration_info)) { this->local_offset -= sizeof(std::int32_t); variable->offset = this->local_offset; } else if (auto parameter = std::dynamic_pointer_cast(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(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(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(this->table->lookup(statement->name())); this->argument_offset = std::max(static_cast(this->argument_offset), call_info->parameter_stack_size()); } }