aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boot/ast.cc45
-rw-r--r--boot/parser.yy6
-rw-r--r--boot/semantic.cc93
-rw-r--r--gcc/gcc/elna-generic.cc97
-rw-r--r--include/elna/boot/ast.h24
-rw-r--r--include/elna/boot/semantic.h18
-rw-r--r--include/elna/gcc/elna-generic.h1
7 files changed, 122 insertions, 162 deletions
diff --git a/boot/ast.cc b/boot/ast.cc
index 3599308..b6ce4b3 100644
--- a/boot/ast.cc
+++ b/boot/ast.cc
@@ -39,11 +39,6 @@ namespace elna::boot
not_implemented();
}
- void empty_visitor::visit(program *)
- {
- not_implemented();
- }
-
void empty_visitor::visit(type_declaration *)
{
not_implemented();
@@ -383,8 +378,14 @@ namespace elna::boot
}
record_type_expression::record_type_expression(const struct position position,
- std::vector<field_declaration>&& fields, std::optional<std::string> base)
- : node(position), fields(std::move(fields)), base(base)
+ std::vector<field_declaration>&& fields)
+ : node(position), fields(std::move(fields))
+ {
+ }
+
+ record_type_expression::record_type_expression(const struct position position,
+ std::vector<field_declaration>&& fields, std::string&& base)
+ : node(position), fields(std::move(fields)), base(std::make_optional<std::string>(std::move(base)))
{
}
@@ -493,7 +494,8 @@ namespace elna::boot
return this;
}
- enumeration_type_expression::enumeration_type_expression(const struct position position, std::vector<std::string>&& members)
+ enumeration_type_expression::enumeration_type_expression(const struct position position,
+ std::vector<std::string>&& members)
: node(position), members(members)
{
}
@@ -510,13 +512,13 @@ namespace elna::boot
procedure_declaration::procedure_declaration(const struct position position, identifier_definition identifier,
procedure_type_expression *heading, block&& body)
- : declaration(position, identifier), m_heading(heading), body(std::move(body))
+ : declaration(position, identifier), m_heading(heading), body(std::make_optional<block>(std::move(body)))
{
}
procedure_declaration::procedure_declaration(const struct position position, identifier_definition identifier,
procedure_type_expression *heading)
- : declaration(position, identifier), m_heading(heading), body(std::nullopt)
+ : declaration(position, identifier), m_heading(heading)
{
}
@@ -618,6 +620,11 @@ namespace elna::boot
{
}
+ unit::unit(const struct position position, std::vector<statement *>&& body)
+ : node(position), body(std::make_optional<std::vector<statement *>>(std::move(body)))
+ {
+ }
+
void unit::accept(parser_visitor *visitor)
{
visitor->visit(this);
@@ -647,24 +654,6 @@ namespace elna::boot
}
}
- program::program(const struct position position)
- : unit(position)
- {
- }
-
- void program::accept(parser_visitor *visitor)
- {
- visitor->visit(this);
- }
-
- program::~program()
- {
- for (statement *body_statement : this->body)
- {
- delete body_statement;
- }
- }
-
literal_expression *literal_expression::is_literal()
{
return this;
diff --git a/boot/parser.yy b/boot/parser.yy
index 7797dd1..42840ff 100644
--- a/boot/parser.yy
+++ b/boot/parser.yy
@@ -164,8 +164,8 @@ program:
{
if ($6)
{
- boot::program *tree = new boot::program(boot::make_position(@1));
- std::swap(tree->body, *$6.release());
+ boot::unit *tree = new boot::unit(boot::make_position(@1));
+ tree->body = std::make_optional<std::vector<boot::statement *>>(std::move(*$6.release()));
driver.tree.reset(tree);
}
@@ -460,7 +460,7 @@ type_expression:
}
| "record" optional_fields "end"
{
- $$ = new boot::record_type_expression(boot::make_position(@1), std::move($2), std::nullopt);
+ $$ = new boot::record_type_expression(boot::make_position(@1), std::move($2));
}
| "record" "(" IDENTIFIER ")" optional_fields "end"
{
diff --git a/boot/semantic.cc b/boot/semantic.cc
index a48226b..0530448 100644
--- a/boot/semantic.cc
+++ b/boot/semantic.cc
@@ -96,11 +96,6 @@ namespace elna::boot
{
}
- void type_analysis_visitor::visit(program *program)
- {
- visit(static_cast<unit *>(program));
- }
-
void type_analysis_visitor::visit(procedure_declaration *definition)
{
if (definition->body.has_value() && definition->heading().return_type.proper_type != nullptr)
@@ -195,17 +190,17 @@ namespace elna::boot
}
std::pair<procedure_type, std::vector<std::string>> name_analysis_visitor::build_procedure(
- procedure_type_expression& type_expression)
+ procedure_type_expression& expression)
{
procedure_type::return_t result_return;
- if (type_expression.return_type.no_return)
+ if (expression.return_type.no_return)
{
result_return = procedure_type::return_t(std::monostate{});
}
- else if (type_expression.return_type.proper_type != nullptr)
+ else if (expression.return_type.proper_type != nullptr)
{
- type_expression.return_type.proper_type->accept(this);
+ expression.return_type.proper_type->accept(this);
result_return = procedure_type::return_t(this->current_type);
}
else
@@ -215,7 +210,7 @@ namespace elna::boot
std::pair<procedure_type, std::vector<std::string>> result_type{
procedure_type(result_return), std::vector<std::string>()
};
- for (auto& [parameter_names, parameters_type] : type_expression.parameters)
+ for (auto& [parameter_names, parameters_type] : expression.parameters)
{
parameters_type->accept(this);
for (auto& parameter_name : parameter_names)
@@ -227,26 +222,6 @@ namespace elna::boot
return result_type;
}
- void name_analysis_visitor::visit(program *program)
- {
- visit(static_cast<unit *>(program));
-
- this->bag.enter();
- auto variable_type = this->bag.lookup("Int")->is_type()->symbol;
- this->bag.enter("count", std::make_shared<variable_info>(variable_type, false));
-
- variable_type = this->bag.lookup("Char")->is_type()->symbol;
- variable_type = type(std::make_shared<pointer_type>(variable_type));
- variable_type = type(std::make_shared<pointer_type>(variable_type));
- this->bag.enter("parameters", std::make_shared<variable_info>(variable_type, false));
-
- for (statement *const statement : program->body)
- {
- statement->accept(this);
- }
- this->bag.leave();
- }
-
void name_analysis_visitor::visit(type_declaration *definition)
{
definition->body().accept(this);
@@ -261,16 +236,16 @@ namespace elna::boot
{
}
- void name_analysis_visitor::visit(pointer_type_expression *type_expression)
+ void name_analysis_visitor::visit(pointer_type_expression *expression)
{
- type_expression->base().accept(this);
+ expression->base().accept(this);
this->current_type = type(std::make_shared<pointer_type>(this->current_type));
}
- void name_analysis_visitor::visit(array_type_expression *type_expression)
+ void name_analysis_visitor::visit(array_type_expression *expression)
{
- type_expression->base().accept(this);
- auto result_type{ std::make_shared<array_type>(this->current_type, type_expression->size) };
+ expression->base().accept(this);
+ auto result_type = std::make_shared<array_type>(this->current_type, expression->size);
this->current_type = type(result_type);
}
@@ -299,16 +274,16 @@ namespace elna::boot
return result;
}
- void name_analysis_visitor::visit(record_type_expression *type_expression)
+ void name_analysis_visitor::visit(record_type_expression *expression)
{
std::shared_ptr<record_type> result_type;
- if (type_expression->base.has_value())
+ if (expression->base.has_value())
{
- if (auto unresolved_alias = this->bag.declared(type_expression->base.value()))
+ if (auto unresolved_alias = this->bag.declared(expression->base.value()))
{
result_type = std::make_shared<record_type>(type(unresolved_alias));
}
- else if (auto base_symbol = this->bag.lookup(type_expression->base.value()))
+ else if (auto base_symbol = this->bag.lookup(expression->base.value()))
{
if (auto base_type_info = base_symbol->is_type())
{
@@ -316,14 +291,14 @@ namespace elna::boot
}
else
{
- add_error<base_type_error>(type_expression->base.value(), type_expression->position());
+ add_error<base_type_error>(expression->base.value(), expression->position());
this->current_type = type();
return;
}
}
else
{
- add_error<undeclared_error>(type_expression->base.value(), type_expression->position());
+ add_error<undeclared_error>(expression->base.value(), expression->position());
this->current_type = type();
return;
}
@@ -332,31 +307,31 @@ namespace elna::boot
{
result_type = std::make_shared<record_type>();
}
- result_type->fields = build_composite_type(type_expression->fields);
+ result_type->fields = build_composite_type(expression->fields);
this->current_type = type(result_type);
}
- void name_analysis_visitor::visit(union_type_expression *type_expression)
+ void name_analysis_visitor::visit(union_type_expression *expression)
{
auto result_type = std::make_shared<union_type>();
- result_type->fields = build_composite_type(type_expression->fields);
+ result_type->fields = build_composite_type(expression->fields);
this->current_type = type(result_type);
}
- void name_analysis_visitor::visit(procedure_type_expression *type_expression)
+ void name_analysis_visitor::visit(procedure_type_expression *expression)
{
std::shared_ptr<procedure_type> result_type =
- std::make_shared<procedure_type>(std::move(build_procedure(*type_expression).first));
+ std::make_shared<procedure_type>(std::move(build_procedure(*expression).first));
this->current_type = type(result_type);
}
- void name_analysis_visitor::visit(enumeration_type_expression *type_expression)
+ void name_analysis_visitor::visit(enumeration_type_expression *expression)
{
- std::shared_ptr<enumeration_type> result_type = std::make_shared<enumeration_type>(type_expression->members);
+ std::shared_ptr<enumeration_type> result_type = std::make_shared<enumeration_type>(expression->members);
this->current_type = type(result_type);
}
@@ -561,6 +536,23 @@ namespace elna::boot
{
procedure->accept(this);
}
+ if (unit->body.has_value())
+ {
+ this->bag.enter();
+ auto variable_type = this->bag.lookup("Int")->is_type()->symbol;
+ this->bag.enter("count", std::make_shared<variable_info>(variable_type, false));
+
+ variable_type = this->bag.lookup("Char")->is_type()->symbol;
+ variable_type = type(std::make_shared<pointer_type>(variable_type));
+ variable_type = type(std::make_shared<pointer_type>(variable_type));
+ this->bag.enter("parameters", std::make_shared<variable_info>(variable_type, false));
+
+ for (statement *const statement : unit->body.value())
+ {
+ statement->accept(this);
+ }
+ this->bag.leave();
+ }
}
void name_analysis_visitor::visit(traits_expression *trait)
@@ -666,11 +658,6 @@ namespace elna::boot
{
}
- void declaration_visitor::visit(program *program)
- {
- visit(static_cast<unit *>(program));
- }
-
void declaration_visitor::visit(import_declaration *)
{
}
diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc
index eb30b4d..a3d022d 100644
--- a/gcc/gcc/elna-generic.cc
+++ b/gcc/gcc/elna-generic.cc
@@ -235,56 +235,6 @@ namespace elna::gcc
}
}
- void generic_visitor::visit(boot::program *program)
- {
- visit(static_cast<boot::unit *>(program));
-
- tree declaration_type = build_function_type_list(elna_int_type_node,
- elna_int_type_node,
- build_global_pointer_type(build_global_pointer_type(elna_char_type_node)),
- NULL_TREE);
- tree fndecl = build_fn_decl("main", declaration_type);
-
- tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node);
- DECL_CONTEXT(resdecl) = fndecl;
- DECL_RESULT(fndecl) = resdecl;
-
- push_struct_function(fndecl, false);
- DECL_STRUCT_FUNCTION(fndecl)->language = ggc_cleared_alloc<language_function>();
-
- enter_scope();
-
- tree parameter_type = TYPE_ARG_TYPES(declaration_type);
- for (const char *argument_name : std::array<const char *, 2>{ "count", "parameters" })
- {
- tree declaration_tree = build_decl(UNKNOWN_LOCATION, PARM_DECL,
- get_identifier(argument_name), TREE_VALUE(parameter_type));
- DECL_CONTEXT(declaration_tree) = fndecl;
- DECL_ARG_TYPE(declaration_tree) = TREE_VALUE(parameter_type);
-
- this->symbols->enter(argument_name, declaration_tree);
- DECL_ARGUMENTS(fndecl) = chainon(DECL_ARGUMENTS(fndecl), declaration_tree);
- parameter_type = TREE_CHAIN(parameter_type);
- }
- visit_statements(program->body);
- tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(fndecl),
- build_int_cst_type(integer_type_node, 0));
- tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
- append_statement(return_stmt);
- tree mapping = leave_scope();
-
- BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl;
- DECL_INITIAL(fndecl) = BIND_EXPR_BLOCK(mapping);
- DECL_SAVED_TREE(fndecl) = mapping;
-
- DECL_EXTERNAL(fndecl) = 0;
- DECL_PRESERVE_P(fndecl) = 1;
-
- pop_cfun();
- gimplify_function_tree(fndecl);
- cgraph_node::finalize_function(fndecl, true);
- }
-
void generic_visitor::visit(boot::unit *unit)
{
for (boot::import_declaration *const declaration : unit->imports)
@@ -303,6 +253,53 @@ namespace elna::gcc
{
procedure->accept(this);
}
+ if (unit->body.has_value())
+ {
+ tree declaration_type = build_function_type_list(elna_int_type_node,
+ elna_int_type_node,
+ build_global_pointer_type(build_global_pointer_type(elna_char_type_node)),
+ NULL_TREE);
+ tree fndecl = build_fn_decl("main", declaration_type);
+
+ tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node);
+ DECL_CONTEXT(resdecl) = fndecl;
+ DECL_RESULT(fndecl) = resdecl;
+
+ push_struct_function(fndecl, false);
+ DECL_STRUCT_FUNCTION(fndecl)->language = ggc_cleared_alloc<language_function>();
+
+ enter_scope();
+
+ tree parameter_type = TYPE_ARG_TYPES(declaration_type);
+ for (const char *argument_name : std::array<const char *, 2>{ "count", "parameters" })
+ {
+ tree declaration_tree = build_decl(UNKNOWN_LOCATION, PARM_DECL,
+ get_identifier(argument_name), TREE_VALUE(parameter_type));
+ DECL_CONTEXT(declaration_tree) = fndecl;
+ DECL_ARG_TYPE(declaration_tree) = TREE_VALUE(parameter_type);
+
+ this->symbols->enter(argument_name, declaration_tree);
+ DECL_ARGUMENTS(fndecl) = chainon(DECL_ARGUMENTS(fndecl), declaration_tree);
+ parameter_type = TREE_CHAIN(parameter_type);
+ }
+ visit_statements(unit->body.value());
+ tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(fndecl),
+ build_int_cst_type(integer_type_node, 0));
+ tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
+ append_statement(return_stmt);
+ tree mapping = leave_scope();
+
+ BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl;
+ DECL_INITIAL(fndecl) = BIND_EXPR_BLOCK(mapping);
+ DECL_SAVED_TREE(fndecl) = mapping;
+
+ DECL_EXTERNAL(fndecl) = 0;
+ DECL_PRESERVE_P(fndecl) = 1;
+
+ pop_cfun();
+ gimplify_function_tree(fndecl);
+ cgraph_node::finalize_function(fndecl, true);
+ }
}
void generic_visitor::visit(boot::procedure_declaration *definition)
diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h
index 6942ca5..fe502a4 100644
--- a/include/elna/boot/ast.h
+++ b/include/elna/boot/ast.h
@@ -68,7 +68,6 @@ namespace elna::boot
class case_statement;
class traits_expression;
class unit;
- class program;
class binary_expression;
class unary_expression;
class type_expression;
@@ -110,7 +109,6 @@ namespace elna::boot
virtual void visit(case_statement *) = 0;
virtual void visit(empty_statement *) = 0;
virtual void visit(unit *) = 0;
- virtual void visit(program *) = 0;
virtual void visit(binary_expression *) = 0;
virtual void visit(unary_expression *) = 0;
virtual void visit(type_expression *) = 0;
@@ -144,7 +142,6 @@ namespace elna::boot
[[noreturn]] virtual void visit(type_expression *) override;
[[noreturn]] virtual void visit(array_type_expression *) override;
[[noreturn]] virtual void visit(pointer_type_expression *) override;
- [[noreturn]] virtual void visit(program *) override;
[[noreturn]] virtual void visit(type_declaration *) override;
[[noreturn]] virtual void visit(record_type_expression *) override;
[[noreturn]] virtual void visit(union_type_expression *) override;
@@ -290,7 +287,9 @@ namespace elna::boot
const std::optional<std::string> base;
record_type_expression(const struct position position,
- std::vector<field_declaration>&& fields, std::optional<std::string> base);
+ std::vector<field_declaration>&& fields);
+ record_type_expression(const struct position position,
+ std::vector<field_declaration>&& fields, std::string&& base);
void accept(parser_visitor *visitor) override;
record_type_expression *is_record() override;
@@ -315,7 +314,8 @@ namespace elna::boot
public:
const std::vector<std::string> members;
- enumeration_type_expression(const struct position, std::vector<std::string>&& members);
+ enumeration_type_expression(const struct position,
+ std::vector<std::string>&& members);
void accept(parser_visitor *visitor) override;
enumeration_type_expression *is_enumeration() override;
@@ -710,6 +710,8 @@ namespace elna::boot
class unit : public node
{
public:
+ std::optional<std::vector<statement *>> body;
+
std::vector<import_declaration *> imports;
std::vector<constant_declaration *> constants;
std::vector<type_declaration *> types;
@@ -717,22 +719,12 @@ namespace elna::boot
std::vector<procedure_declaration *> procedures;
unit(const struct position position);
+ unit(const struct position position, std::vector<statement *>&& body);
virtual void accept(parser_visitor *visitor) override;
virtual ~unit() override;
};
- class program : public unit
- {
- public:
- std::vector<statement *> body;
-
- program(const struct position position);
- void accept(parser_visitor *visitor) override;
-
- virtual ~program() override;
- };
-
template<typename T>
class literal : public literal_expression
{
diff --git a/include/elna/boot/semantic.h b/include/elna/boot/semantic.h
index 6bc7fe0..c6ad19d 100644
--- a/include/elna/boot/semantic.h
+++ b/include/elna/boot/semantic.h
@@ -102,8 +102,6 @@ namespace elna::boot
public:
explicit type_analysis_visitor(symbol_bag bag);
- void visit(program *program) override;
-
void visit(procedure_declaration *definition) override;
void visit(assign_statement *) override;
void visit(if_statement *) override;
@@ -128,7 +126,7 @@ namespace elna::boot
symbol_bag bag;
std::pair<procedure_type, std::vector<std::string>> build_procedure(
- procedure_type_expression& type_expression);
+ procedure_type_expression& expression);
std::vector<type_field> build_composite_type(const std::vector<field_declaration>& fields);
std::shared_ptr<variable_info> register_variable(const std::string& name,
const bool is_extern, const struct position position);
@@ -137,14 +135,13 @@ namespace elna::boot
name_analysis_visitor(symbol_bag bag);
void visit(type_expression *) override;
- void visit(array_type_expression *type_expression) override;
- void visit(pointer_type_expression *type_expression) override;
- void visit(program *program) override;
+ void visit(array_type_expression *expression) override;
+ void visit(pointer_type_expression *expression) override;
void visit(type_declaration *definition) override;
- void visit(record_type_expression *type_expression) override;
- void visit(union_type_expression *type_expression) override;
- void visit(procedure_type_expression *type_expression) override;
- void visit(enumeration_type_expression *type_expression) override;
+ void visit(record_type_expression *expression) override;
+ void visit(union_type_expression *expression) override;
+ void visit(procedure_type_expression *expression) override;
+ void visit(enumeration_type_expression *expression) override;
void visit(variable_declaration *declaration) override;
void visit(constant_declaration *definition) override;
@@ -186,7 +183,6 @@ namespace elna::boot
explicit declaration_visitor();
- void visit(program *program) override;
void visit(import_declaration *) override;
void visit(unit *unit) override;
void visit(type_declaration *definition) override;
diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h
index 77fd792..7ee251b 100644
--- a/include/elna/gcc/elna-generic.h
+++ b/include/elna/gcc/elna-generic.h
@@ -65,7 +65,6 @@ namespace elna::gcc
public:
generic_visitor(std::shared_ptr<symbol_table> symbol_table, elna::boot::symbol_bag bag);
- void visit(boot::program *program) override;
void visit(boot::procedure_declaration *definition) override;
void visit(boot::procedure_call *call) override;
void visit(boot::cast_expression *expression) override;