Implement external functions
This commit is contained in:
parent
1e45d66359
commit
ef667e3ace
@ -36,7 +36,7 @@ program = [ "type" type_definitions ";" ]
|
||||
[ variable_part ]
|
||||
compound_statement ".";
|
||||
|
||||
procedure_definition = "proc" ident formal_parameter_list ";" block ";";
|
||||
procedure_definition = "proc" ident formal_parameter_list ";" ( block | "extern" ) ";";
|
||||
|
||||
block = [ constant_part ]
|
||||
[ variable_part ]
|
||||
|
@ -119,6 +119,8 @@ begin
|
||||
writei(x)
|
||||
end;
|
||||
|
||||
proc exit(code: Int); extern;
|
||||
|
||||
begin
|
||||
test_primitive();
|
||||
test_string();
|
||||
@ -129,5 +131,7 @@ begin
|
||||
test_if();
|
||||
test_not();
|
||||
test_param(8, 7);
|
||||
test_const_char()
|
||||
test_const_char();
|
||||
|
||||
exit(0)
|
||||
end.
|
||||
|
@ -132,12 +132,14 @@ namespace gcc
|
||||
|
||||
enter_scope();
|
||||
|
||||
for (const auto& definition : program->value_definitions)
|
||||
for (const auto definition : program->value_definitions)
|
||||
{
|
||||
definition->accept(this);
|
||||
}
|
||||
program->body().accept(this);
|
||||
|
||||
for (const auto body_statement : program->body)
|
||||
{
|
||||
body_statement->accept(this);
|
||||
}
|
||||
append_to_statement_list(return_stmt, &this->current_statements);
|
||||
tree_symbol_mapping mapping = leave_scope();
|
||||
|
||||
@ -155,41 +157,47 @@ namespace gcc
|
||||
|
||||
void generic_visitor::visit(source::procedure_definition *definition)
|
||||
{
|
||||
std::vector<tree> parameter_types(definition->parameters().size());
|
||||
std::vector<tree> parameter_types(definition->parameters.size());
|
||||
|
||||
for (std::size_t i = 0; i < definition->parameters().size(); ++i)
|
||||
for (std::size_t i = 0; i < definition->parameters.size(); ++i)
|
||||
{
|
||||
parameter_types[i] = build_type(definition->parameters().at(i)->type());
|
||||
parameter_types[i] = build_type(definition->parameters.at(i)->type());
|
||||
}
|
||||
tree declaration_type = build_function_type_array(void_type_node,
|
||||
definition->parameters().size(), parameter_types.data());
|
||||
definition->parameters.size(), parameter_types.data());
|
||||
this->main_fndecl = build_fn_decl(definition->identifier().c_str(), declaration_type);
|
||||
|
||||
this->symbol_map->enter(definition->identifier(), source::make_info(this->main_fndecl));
|
||||
|
||||
if (definition->body() != nullptr)
|
||||
{
|
||||
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL,
|
||||
NULL_TREE, TREE_TYPE(TREE_TYPE(this->main_fndecl)));
|
||||
DECL_CONTEXT(resdecl) = this->main_fndecl;
|
||||
DECL_RESULT(this->main_fndecl) = resdecl;
|
||||
|
||||
enter_scope();
|
||||
|
||||
}
|
||||
gcc::tree_chain argument_chain;
|
||||
for (std::size_t i = 0; i < definition->parameters().size(); ++i)
|
||||
for (std::size_t i = 0; i < definition->parameters.size(); ++i)
|
||||
{
|
||||
auto parameter = definition->parameters().at(i);
|
||||
auto parameter = definition->parameters.at(i);
|
||||
|
||||
tree declaration_tree = build_decl(get_location(¶meter->position()), PARM_DECL,
|
||||
get_identifier(parameter->identifier().c_str()), parameter_types[i]);
|
||||
DECL_CONTEXT(declaration_tree) = this->main_fndecl;
|
||||
DECL_ARG_TYPE(declaration_tree) = parameter_types[i];
|
||||
|
||||
if (definition->body() != nullptr)
|
||||
{
|
||||
this->symbol_map->enter(parameter->identifier(), source::make_info(declaration_tree));
|
||||
}
|
||||
argument_chain.append(declaration_tree);
|
||||
}
|
||||
DECL_ARGUMENTS(this->main_fndecl) = argument_chain.head();
|
||||
definition->body().accept(this);
|
||||
|
||||
if (definition->body() != nullptr)
|
||||
{
|
||||
definition->body()->accept(this);
|
||||
tree_symbol_mapping mapping = leave_scope();
|
||||
|
||||
BLOCK_SUPERCONTEXT(mapping.block()) = this->main_fndecl;
|
||||
@ -203,6 +211,11 @@ namespace gcc
|
||||
|
||||
cgraph_node::finalize_function(this->main_fndecl, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
DECL_EXTERNAL(this->main_fndecl) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void generic_visitor::enter_scope()
|
||||
{
|
||||
|
@ -386,21 +386,21 @@ namespace source
|
||||
*/
|
||||
class procedure_definition : public definition
|
||||
{
|
||||
block *m_body;
|
||||
std::vector<variable_declaration *> m_parameters;
|
||||
block *m_body{ nullptr };
|
||||
|
||||
public:
|
||||
std::vector<variable_declaration *> parameters;
|
||||
|
||||
/**
|
||||
* \param position Source code position.
|
||||
* \param identifier Procedure name.
|
||||
* \param body Procedure body.
|
||||
*/
|
||||
procedure_definition(const struct position position, const std::string& identifier,
|
||||
block *body);
|
||||
block *body = nullptr);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
|
||||
block& body();
|
||||
std::vector<variable_declaration *>& parameters();
|
||||
block *body();
|
||||
|
||||
virtual ~procedure_definition() override;
|
||||
};
|
||||
@ -603,17 +603,14 @@ namespace source
|
||||
|
||||
class block : public node
|
||||
{
|
||||
statement *m_body;
|
||||
|
||||
public:
|
||||
std::vector<definition *> value_definitions;
|
||||
std::vector<statement *> body;
|
||||
|
||||
block(const struct position position, std::vector<definition *>&& value_definitions,
|
||||
statement *body);
|
||||
std::vector<statement *>&& body);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
|
||||
statement& body();
|
||||
|
||||
virtual ~block() override;
|
||||
};
|
||||
|
||||
@ -623,7 +620,7 @@ namespace source
|
||||
std::vector<definition *> type_definitions;
|
||||
|
||||
program(const struct position position, std::vector<definition *>&& type_definitions,
|
||||
std::vector<definition *>&& value_definitions, statement *body);
|
||||
std::vector<definition *>&& value_definitions, std::vector<statement *>&& body);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
|
||||
virtual ~program() override;
|
||||
|
@ -18,11 +18,14 @@ namespace source
|
||||
|
||||
void empty_visitor::visit(procedure_definition *definition)
|
||||
{
|
||||
for (auto parameter : definition->parameters())
|
||||
for (auto parameter : definition->parameters)
|
||||
{
|
||||
parameter->accept(this);
|
||||
}
|
||||
definition->body().accept(this);
|
||||
if (definition->body() != nullptr)
|
||||
{
|
||||
definition->body()->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void empty_visitor::visit(type_definition *definition)
|
||||
@ -65,11 +68,14 @@ namespace source
|
||||
|
||||
void empty_visitor::visit(block *block)
|
||||
{
|
||||
for (const auto& definition : block->value_definitions)
|
||||
for (const auto definition : block->value_definitions)
|
||||
{
|
||||
definition->accept(this);
|
||||
}
|
||||
block->body().accept(this);
|
||||
for (const auto body_statement : block->body)
|
||||
{
|
||||
body_statement->accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
void empty_visitor::visit(program *program)
|
||||
@ -407,20 +413,18 @@ namespace source
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
block& procedure_definition::body()
|
||||
block *procedure_definition::body()
|
||||
{
|
||||
return *m_body;
|
||||
}
|
||||
|
||||
std::vector<variable_declaration *>& procedure_definition::parameters()
|
||||
{
|
||||
return m_parameters;
|
||||
return m_body;
|
||||
}
|
||||
|
||||
procedure_definition::~procedure_definition()
|
||||
{
|
||||
if (m_body != nullptr)
|
||||
{
|
||||
delete m_body;
|
||||
for (auto parameter : m_parameters)
|
||||
}
|
||||
for (auto parameter : parameters)
|
||||
{
|
||||
delete parameter;
|
||||
}
|
||||
@ -448,8 +452,8 @@ namespace source
|
||||
}
|
||||
|
||||
block::block(const struct position position, std::vector<definition *>&& value_definitions,
|
||||
statement *body)
|
||||
: node(position), m_body(std::move(body)), value_definitions(std::move(value_definitions))
|
||||
std::vector<statement *>&& body)
|
||||
: node(position), value_definitions(std::move(value_definitions)), body(std::move(body))
|
||||
{
|
||||
}
|
||||
|
||||
@ -458,24 +462,22 @@ namespace source
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
statement& block::body()
|
||||
{
|
||||
return *m_body;
|
||||
}
|
||||
|
||||
block::~block()
|
||||
{
|
||||
for (auto definition : value_definitions)
|
||||
for (auto definition : this->value_definitions)
|
||||
{
|
||||
delete definition;
|
||||
}
|
||||
delete m_body;
|
||||
for (auto body_statement : this->body)
|
||||
{
|
||||
delete body_statement;
|
||||
}
|
||||
}
|
||||
|
||||
program::program(const struct position position,
|
||||
std::vector<definition *>&& type_definitions,
|
||||
std::vector<definition *>&& value_definitions, statement *body)
|
||||
: block(position, std::move(value_definitions), body),
|
||||
std::vector<definition *>&& value_definitions, std::vector<statement *>&& body)
|
||||
: block(position, std::move(value_definitions), std::move(body)),
|
||||
type_definitions(std::move(type_definitions))
|
||||
{
|
||||
}
|
||||
|
@ -55,6 +55,9 @@ begin {
|
||||
end {
|
||||
return yy::parser::make_END_BLOCK(this->location);
|
||||
}
|
||||
extern {
|
||||
return yy::parser::make_EXTERN(this->location);
|
||||
}
|
||||
const {
|
||||
return yy::parser::make_CONST(this->location);
|
||||
}
|
||||
|
@ -64,7 +64,7 @@
|
||||
%token <bool> BOOLEAN
|
||||
%token IF WHILE DO
|
||||
%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD
|
||||
%token BEGIN_BLOCK END_BLOCK
|
||||
%token BEGIN_BLOCK END_BLOCK EXTERN
|
||||
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
|
||||
%token AND OR NOT
|
||||
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
|
||||
@ -100,7 +100,7 @@
|
||||
%type <std::vector<std::pair<std::string, elna::source::type_expression *>>> field_list;
|
||||
%%
|
||||
program:
|
||||
type_part constant_part procedure_part variable_part compound_statement DOT
|
||||
type_part constant_part procedure_part variable_part BEGIN_BLOCK optional_statements END_BLOCK DOT
|
||||
{
|
||||
std::vector<elna::source::definition *> definitions($1.size() + $3.size());
|
||||
std::vector<elna::source::definition *>::iterator definition = definitions.begin();
|
||||
@ -124,11 +124,11 @@ program:
|
||||
*value_definition++ = variable;
|
||||
}
|
||||
auto tree = new elna::source::program(elna::source::position{},
|
||||
std::move(definitions), std::move(value_definitions), std::move($5));
|
||||
std::move(definitions), std::move(value_definitions), std::move($6));
|
||||
|
||||
driver.tree.reset(tree);
|
||||
}
|
||||
block: constant_part variable_part statement
|
||||
block: constant_part variable_part BEGIN_BLOCK optional_statements END_BLOCK
|
||||
{
|
||||
std::vector<elna::source::definition *> definitions($1.size() + $2.size());
|
||||
std::vector<elna::source::definition *>::iterator definition = definitions.begin();
|
||||
@ -142,15 +142,21 @@ block: constant_part variable_part statement
|
||||
*definition++ = variable;
|
||||
}
|
||||
$$ = new elna::source::block(elna::source::position{},
|
||||
std::move(definitions), std::move($3));
|
||||
};
|
||||
std::move(definitions), std::move($4));
|
||||
}
|
||||
procedure_definition:
|
||||
PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON block SEMICOLON
|
||||
{
|
||||
$$ = new elna::source::procedure_definition(elna::source::position{},
|
||||
std::move($2), $5);
|
||||
std::swap($$->parameters(), $3);
|
||||
};
|
||||
std::swap($$->parameters, $3);
|
||||
}
|
||||
| PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON EXTERN SEMICOLON
|
||||
{
|
||||
$$ = new elna::source::procedure_definition(elna::source::position{},
|
||||
std::move($2));
|
||||
std::swap($$->parameters, $3);
|
||||
}
|
||||
procedure_definitions:
|
||||
procedure_definition procedure_definitions
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user