Support procedure calls without arguments
This commit is contained in:
@ -19,7 +19,10 @@ namespace elna::source
|
||||
|
||||
void empty_visitor::visit(call_statement *statement)
|
||||
{
|
||||
statement->arguments().accept(this);
|
||||
for (auto& argument : statement->arguments())
|
||||
{
|
||||
argument->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void empty_visitor::visit(compound_statement *statement)
|
||||
@ -87,8 +90,8 @@ namespace elna::source
|
||||
{
|
||||
}
|
||||
|
||||
declaration::declaration(const std::string& identifier)
|
||||
: m_identifier(identifier)
|
||||
declaration::declaration(const std::string& identifier, const std::string& type)
|
||||
: m_identifier(identifier), m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
@ -102,6 +105,11 @@ namespace elna::source
|
||||
return m_identifier;
|
||||
}
|
||||
|
||||
std::string& declaration::type() noexcept
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
definition::definition(const std::string& identifier)
|
||||
: m_identifier(identifier)
|
||||
{
|
||||
@ -142,12 +150,16 @@ namespace elna::source
|
||||
return *m_body;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<declaration>>& procedure_definition::parameters() noexcept
|
||||
{
|
||||
return m_parameters;
|
||||
}
|
||||
|
||||
block::block(std::vector<std::unique_ptr<definition>>&& definitions,
|
||||
std::vector<std::unique_ptr<declaration>>&& declarations,
|
||||
std::unique_ptr<statement>&& body)
|
||||
: m_definitions(std::move(definitions)),
|
||||
m_declarations(std::move(declarations)), m_body(std::move(body)),
|
||||
m_table(std::make_shared<symbol_table>())
|
||||
m_declarations(std::move(declarations)), m_body(std::move(body))
|
||||
{
|
||||
}
|
||||
|
||||
@ -171,11 +183,6 @@ namespace elna::source
|
||||
return m_declarations;
|
||||
}
|
||||
|
||||
std::shared_ptr<symbol_table> block::table()
|
||||
{
|
||||
return m_table;
|
||||
}
|
||||
|
||||
program::program(std::vector<std::unique_ptr<definition>>&& definitions,
|
||||
std::vector<std::unique_ptr<declaration>>&& declarations,
|
||||
std::unique_ptr<statement>&& body)
|
||||
@ -276,8 +283,8 @@ namespace elna::source
|
||||
return m_operator;
|
||||
}
|
||||
|
||||
call_statement::call_statement(const std::string& name, std::unique_ptr<expression>&& body)
|
||||
: m_name(name), m_body(std::move(body))
|
||||
call_statement::call_statement(const std::string& name)
|
||||
: m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
@ -291,9 +298,9 @@ namespace elna::source
|
||||
return m_name;
|
||||
}
|
||||
|
||||
expression& call_statement::arguments()
|
||||
std::vector<std::unique_ptr<expression>>& call_statement::arguments() noexcept
|
||||
{
|
||||
return *m_body;
|
||||
return m_arguments;
|
||||
}
|
||||
|
||||
compound_statement::compound_statement(std::vector<std::unique_ptr<statement>>&& statements)
|
||||
@ -537,7 +544,8 @@ namespace elna::source
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_unique<declaration>(declaration_identifier.value().get().identifier());
|
||||
return std::make_unique<declaration>(declaration_identifier.value().get().identifier(),
|
||||
type_identifier.value().get().identifier());
|
||||
}
|
||||
|
||||
std::unique_ptr<statement> parser::parse_statement()
|
||||
@ -573,11 +581,27 @@ namespace elna::source
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
auto bang_body = parse_expression();
|
||||
auto call = std::make_unique<call_statement>(function_name->get().identifier());
|
||||
std::unique_ptr<expression> argument_expression;
|
||||
|
||||
if (bang_body != nullptr && iterator.skip(token::type::right_paren))
|
||||
if (iterator.current(token::type::right_paren))
|
||||
{
|
||||
return std::make_unique<call_statement>(function_name->get().identifier(), std::move(bang_body));
|
||||
++iterator;
|
||||
return call;
|
||||
}
|
||||
while ((argument_expression = parse_expression()) != nullptr)
|
||||
{
|
||||
call->arguments().push_back(std::move(argument_expression));
|
||||
|
||||
if (iterator.current(token::type::right_paren))
|
||||
{
|
||||
++iterator;
|
||||
return call;
|
||||
}
|
||||
if (!iterator.skip(token::type::comma))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -27,23 +27,39 @@ namespace elna::source
|
||||
return "Name '" + name + "' was already defined";
|
||||
}
|
||||
|
||||
symbol_table::symbol_table()
|
||||
type::type(const std::size_t byte_size)
|
||||
: byte_size(byte_size)
|
||||
{
|
||||
enter("writei", std::make_shared<intrinsic_info>());
|
||||
enter("writeb", std::make_shared<intrinsic_info>());
|
||||
}
|
||||
|
||||
primitive_type::primitive_type(const std::string& type_name, const std::size_t byte_size)
|
||||
: type(byte_size), type_name(type_name)
|
||||
{
|
||||
}
|
||||
|
||||
symbol_table::symbol_table(std::shared_ptr<symbol_table> scope)
|
||||
: outer_scope(scope)
|
||||
{
|
||||
if (scope == nullptr)
|
||||
{
|
||||
enter("writei", std::make_shared<intrinsic_info>());
|
||||
enter("writeb", std::make_shared<intrinsic_info>());
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<info> symbol_table::lookup(const std::string& name)
|
||||
{
|
||||
auto entry = entries.find(name);
|
||||
if (entry == entries.cend())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
|
||||
if (entry != entries.cend())
|
||||
{
|
||||
return entry->second;
|
||||
}
|
||||
if (this->outer_scope != nullptr)
|
||||
{
|
||||
return this->outer_scope->lookup(name);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void symbol_table::enter(const std::string& name, std::shared_ptr<info> entry)
|
||||
@ -51,6 +67,11 @@ namespace elna::source
|
||||
entries.insert_or_assign(name, entry);
|
||||
}
|
||||
|
||||
std::shared_ptr<symbol_table> symbol_table::scope()
|
||||
{
|
||||
return this->outer_scope;
|
||||
}
|
||||
|
||||
info::~info()
|
||||
{
|
||||
}
|
||||
@ -59,6 +80,20 @@ namespace elna::source
|
||||
{
|
||||
}
|
||||
|
||||
type_info::type_info(const class type& type)
|
||||
: info(), m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
type_info::~type_info()
|
||||
{
|
||||
}
|
||||
|
||||
const class type& type_info::type() const noexcept
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
constant_info::constant_info(const std::int32_t value)
|
||||
: m_value(value)
|
||||
{
|
||||
@ -77,6 +112,25 @@ namespace elna::source
|
||||
{
|
||||
}
|
||||
|
||||
parameter_info::parameter_info(const class type& type)
|
||||
: m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
parameter_info::~parameter_info()
|
||||
{
|
||||
}
|
||||
|
||||
const class type& parameter_info::type() const noexcept
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
procedure_info::procedure_info(std::shared_ptr<symbol_table> outer_scope)
|
||||
: local_table(std::make_shared<symbol_table>(outer_scope))
|
||||
{
|
||||
}
|
||||
|
||||
procedure_info::~procedure_info()
|
||||
{
|
||||
}
|
||||
@ -91,6 +145,11 @@ namespace elna::source
|
||||
this->local_stack_size = size;
|
||||
}
|
||||
|
||||
std::shared_ptr<symbol_table> procedure_info::scope()
|
||||
{
|
||||
return local_table;
|
||||
}
|
||||
|
||||
intrinsic_info::~intrinsic_info()
|
||||
{
|
||||
}
|
||||
|
@ -3,6 +3,11 @@
|
||||
|
||||
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(),
|
||||
@ -15,12 +20,24 @@ namespace elna::source
|
||||
std::make_shared<variable_info>(variable_info()));
|
||||
}
|
||||
|
||||
void name_analysis_visitor::visit(block *block)
|
||||
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();
|
||||
empty_visitor::visit(procedure);
|
||||
this->table = info->scope()->scope();
|
||||
}
|
||||
|
||||
allocator_visitor::allocator_visitor(std::shared_ptr<symbol_table> table)
|
||||
: table(table)
|
||||
{
|
||||
this->table = block->table();
|
||||
empty_visitor::visit(block);
|
||||
this->table->enter("main",
|
||||
std::make_shared<procedure_info>());
|
||||
}
|
||||
|
||||
void allocator_visitor::visit(declaration *declaration)
|
||||
@ -28,11 +45,19 @@ namespace elna::source
|
||||
this->offset -= sizeof(std::int32_t);
|
||||
}
|
||||
|
||||
void allocator_visitor::visit(block *block)
|
||||
void allocator_visitor::visit(program *program)
|
||||
{
|
||||
this->offset = 0;
|
||||
empty_visitor::visit(block);
|
||||
std::dynamic_pointer_cast<procedure_info>(block->table()->lookup("main"))
|
||||
empty_visitor::visit(program);
|
||||
std::dynamic_pointer_cast<procedure_info>(table->lookup("main"))
|
||||
->stack_size(std::abs(this->offset));
|
||||
}
|
||||
|
||||
void allocator_visitor::visit(procedure_definition *procedure)
|
||||
{
|
||||
this->offset = 0;
|
||||
empty_visitor::visit(procedure);
|
||||
std::dynamic_pointer_cast<procedure_info>(table->lookup(procedure->identifier()))
|
||||
->stack_size(std::abs(this->offset));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user