Implement external functions

This commit is contained in:
Eugen Wissner 2025-01-16 15:09:58 +01:00
parent 1e45d66359
commit ef667e3ace
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
7 changed files with 98 additions and 73 deletions

View File

@ -36,7 +36,7 @@ program = [ "type" type_definitions ";" ]
[ variable_part ] [ variable_part ]
compound_statement "."; compound_statement ".";
procedure_definition = "proc" ident formal_parameter_list ";" block ";"; procedure_definition = "proc" ident formal_parameter_list ";" ( block | "extern" ) ";";
block = [ constant_part ] block = [ constant_part ]
[ variable_part ] [ variable_part ]

View File

@ -119,6 +119,8 @@ begin
writei(x) writei(x)
end; end;
proc exit(code: Int); extern;
begin begin
test_primitive(); test_primitive();
test_string(); test_string();
@ -129,5 +131,7 @@ begin
test_if(); test_if();
test_not(); test_not();
test_param(8, 7); test_param(8, 7);
test_const_char() test_const_char();
exit(0)
end. end.

View File

@ -132,12 +132,14 @@ namespace gcc
enter_scope(); enter_scope();
for (const auto& definition : program->value_definitions) for (const auto definition : program->value_definitions)
{ {
definition->accept(this); 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); append_to_statement_list(return_stmt, &this->current_statements);
tree_symbol_mapping mapping = leave_scope(); tree_symbol_mapping mapping = leave_scope();
@ -155,53 +157,64 @@ namespace gcc
void generic_visitor::visit(source::procedure_definition *definition) 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, 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->main_fndecl = build_fn_decl(definition->identifier().c_str(), declaration_type);
this->symbol_map->enter(definition->identifier(), source::make_info(this->main_fndecl)); this->symbol_map->enter(definition->identifier(), source::make_info(this->main_fndecl));
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, if (definition->body() != nullptr)
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)
{ {
auto parameter = definition->parameters().at(i); 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)
{
auto parameter = definition->parameters.at(i);
tree declaration_tree = build_decl(get_location(&parameter->position()), PARM_DECL, tree declaration_tree = build_decl(get_location(&parameter->position()), PARM_DECL,
get_identifier(parameter->identifier().c_str()), parameter_types[i]); get_identifier(parameter->identifier().c_str()), parameter_types[i]);
DECL_CONTEXT(declaration_tree) = this->main_fndecl; DECL_CONTEXT(declaration_tree) = this->main_fndecl;
DECL_ARG_TYPE(declaration_tree) = parameter_types[i]; DECL_ARG_TYPE(declaration_tree) = parameter_types[i];
this->symbol_map->enter(parameter->identifier(), source::make_info(declaration_tree)); if (definition->body() != nullptr)
{
this->symbol_map->enter(parameter->identifier(), source::make_info(declaration_tree));
}
argument_chain.append(declaration_tree); argument_chain.append(declaration_tree);
} }
DECL_ARGUMENTS(this->main_fndecl) = argument_chain.head(); DECL_ARGUMENTS(this->main_fndecl) = argument_chain.head();
definition->body().accept(this);
tree_symbol_mapping mapping = leave_scope(); if (definition->body() != nullptr)
{
definition->body()->accept(this);
tree_symbol_mapping mapping = leave_scope();
BLOCK_SUPERCONTEXT(mapping.block()) = this->main_fndecl; BLOCK_SUPERCONTEXT(mapping.block()) = this->main_fndecl;
DECL_INITIAL(this->main_fndecl) = mapping.block(); DECL_INITIAL(this->main_fndecl) = mapping.block();
DECL_SAVED_TREE(this->main_fndecl) = mapping.bind_expression(); DECL_SAVED_TREE(this->main_fndecl) = mapping.bind_expression();
DECL_EXTERNAL(this->main_fndecl) = 0; DECL_EXTERNAL(this->main_fndecl) = 0;
DECL_PRESERVE_P(this->main_fndecl) = 1; DECL_PRESERVE_P(this->main_fndecl) = 1;
gimplify_function_tree(this->main_fndecl); gimplify_function_tree(this->main_fndecl);
cgraph_node::finalize_function(this->main_fndecl, true); cgraph_node::finalize_function(this->main_fndecl, true);
}
else
{
DECL_EXTERNAL(this->main_fndecl) = 1;
}
} }
void generic_visitor::enter_scope() void generic_visitor::enter_scope()

View File

@ -386,21 +386,21 @@ namespace source
*/ */
class procedure_definition : public definition class procedure_definition : public definition
{ {
block *m_body; block *m_body{ nullptr };
std::vector<variable_declaration *> m_parameters;
public: public:
std::vector<variable_declaration *> parameters;
/** /**
* \param position Source code position. * \param position Source code position.
* \param identifier Procedure name. * \param identifier Procedure name.
* \param body Procedure body. * \param body Procedure body.
*/ */
procedure_definition(const struct position position, const std::string& identifier, procedure_definition(const struct position position, const std::string& identifier,
block *body); block *body = nullptr);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
block& body(); block *body();
std::vector<variable_declaration *>& parameters();
virtual ~procedure_definition() override; virtual ~procedure_definition() override;
}; };
@ -603,17 +603,14 @@ namespace source
class block : public node class block : public node
{ {
statement *m_body;
public: public:
std::vector<definition *> value_definitions; std::vector<definition *> value_definitions;
std::vector<statement *> body;
block(const struct position position, std::vector<definition *>&& value_definitions, block(const struct position position, std::vector<definition *>&& value_definitions,
statement *body); std::vector<statement *>&& body);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
statement& body();
virtual ~block() override; virtual ~block() override;
}; };
@ -623,7 +620,7 @@ namespace source
std::vector<definition *> type_definitions; std::vector<definition *> type_definitions;
program(const struct position position, 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 void accept(parser_visitor *visitor) override;
virtual ~program() override; virtual ~program() override;

View File

@ -18,11 +18,14 @@ namespace source
void empty_visitor::visit(procedure_definition *definition) void empty_visitor::visit(procedure_definition *definition)
{ {
for (auto parameter : definition->parameters()) for (auto parameter : definition->parameters)
{ {
parameter->accept(this); parameter->accept(this);
} }
definition->body().accept(this); if (definition->body() != nullptr)
{
definition->body()->accept(this);
}
} }
void empty_visitor::visit(type_definition *definition) void empty_visitor::visit(type_definition *definition)
@ -65,11 +68,14 @@ namespace source
void empty_visitor::visit(block *block) void empty_visitor::visit(block *block)
{ {
for (const auto& definition : block->value_definitions) for (const auto definition : block->value_definitions)
{ {
definition->accept(this); definition->accept(this);
} }
block->body().accept(this); for (const auto body_statement : block->body)
{
body_statement->accept(this);
}
} }
void empty_visitor::visit(program *program) void empty_visitor::visit(program *program)
@ -407,20 +413,18 @@ namespace source
visitor->visit(this); visitor->visit(this);
} }
block& procedure_definition::body() block *procedure_definition::body()
{ {
return *m_body; return m_body;
}
std::vector<variable_declaration *>& procedure_definition::parameters()
{
return m_parameters;
} }
procedure_definition::~procedure_definition() procedure_definition::~procedure_definition()
{ {
delete m_body; if (m_body != nullptr)
for (auto parameter : m_parameters) {
delete m_body;
}
for (auto parameter : parameters)
{ {
delete parameter; delete parameter;
} }
@ -448,8 +452,8 @@ namespace source
} }
block::block(const struct position position, std::vector<definition *>&& value_definitions, block::block(const struct position position, std::vector<definition *>&& value_definitions,
statement *body) std::vector<statement *>&& body)
: node(position), m_body(std::move(body)), value_definitions(std::move(value_definitions)) : node(position), value_definitions(std::move(value_definitions)), body(std::move(body))
{ {
} }
@ -458,24 +462,22 @@ namespace source
visitor->visit(this); visitor->visit(this);
} }
statement& block::body()
{
return *m_body;
}
block::~block() block::~block()
{ {
for (auto definition : value_definitions) for (auto definition : this->value_definitions)
{ {
delete definition; delete definition;
} }
delete m_body; for (auto body_statement : this->body)
{
delete body_statement;
}
} }
program::program(const struct position position, program::program(const struct position position,
std::vector<definition *>&& type_definitions, std::vector<definition *>&& type_definitions,
std::vector<definition *>&& value_definitions, statement *body) std::vector<definition *>&& value_definitions, std::vector<statement *>&& body)
: block(position, std::move(value_definitions), body), : block(position, std::move(value_definitions), std::move(body)),
type_definitions(std::move(type_definitions)) type_definitions(std::move(type_definitions))
{ {
} }

View File

@ -55,6 +55,9 @@ begin {
end { end {
return yy::parser::make_END_BLOCK(this->location); return yy::parser::make_END_BLOCK(this->location);
} }
extern {
return yy::parser::make_EXTERN(this->location);
}
const { const {
return yy::parser::make_CONST(this->location); return yy::parser::make_CONST(this->location);
} }

View File

@ -64,7 +64,7 @@
%token <bool> BOOLEAN %token <bool> BOOLEAN
%token IF WHILE DO %token IF WHILE DO
%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD %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 LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
%token AND OR NOT %token AND OR NOT
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS %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; %type <std::vector<std::pair<std::string, elna::source::type_expression *>>> field_list;
%% %%
program: 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 *> definitions($1.size() + $3.size());
std::vector<elna::source::definition *>::iterator definition = definitions.begin(); std::vector<elna::source::definition *>::iterator definition = definitions.begin();
@ -124,11 +124,11 @@ program:
*value_definition++ = variable; *value_definition++ = variable;
} }
auto tree = new elna::source::program(elna::source::position{}, 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); 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 *> definitions($1.size() + $2.size());
std::vector<elna::source::definition *>::iterator definition = definitions.begin(); std::vector<elna::source::definition *>::iterator definition = definitions.begin();
@ -142,15 +142,21 @@ block: constant_part variable_part statement
*definition++ = variable; *definition++ = variable;
} }
$$ = new elna::source::block(elna::source::position{}, $$ = new elna::source::block(elna::source::position{},
std::move(definitions), std::move($3)); std::move(definitions), std::move($4));
}; }
procedure_definition: procedure_definition:
PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON block SEMICOLON PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON block SEMICOLON
{ {
$$ = new elna::source::procedure_definition(elna::source::position{}, $$ = new elna::source::procedure_definition(elna::source::position{},
std::move($2), $5); 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_definitions:
procedure_definition procedure_definitions procedure_definition procedure_definitions
{ {