aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
Diffstat (limited to 'boot')
-rw-r--r--boot/ast.cc4
-rw-r--r--boot/parser.yy6
-rw-r--r--boot/semantic.cc57
-rw-r--r--boot/symbol.cc5
4 files changed, 59 insertions, 13 deletions
diff --git a/boot/ast.cc b/boot/ast.cc
index 5885cff..3599308 100644
--- a/boot/ast.cc
+++ b/boot/ast.cc
@@ -383,8 +383,8 @@ namespace elna::boot
}
record_type_expression::record_type_expression(const struct position position,
- std::vector<field_declaration>&& fields)
- : node(position), fields(std::move(fields))
+ std::vector<field_declaration>&& fields, std::optional<std::string> base)
+ : node(position), fields(std::move(fields)), base(base)
{
}
diff --git a/boot/parser.yy b/boot/parser.yy
index b05b544..7797dd1 100644
--- a/boot/parser.yy
+++ b/boot/parser.yy
@@ -460,7 +460,11 @@ type_expression:
}
| "record" optional_fields "end"
{
- $$ = new boot::record_type_expression(boot::make_position(@1), std::move($2));
+ $$ = new boot::record_type_expression(boot::make_position(@1), std::move($2), std::nullopt);
+ }
+ | "record" "(" IDENTIFIER ")" optional_fields "end"
+ {
+ $$ = new boot::record_type_expression(boot::make_position(@1), std::move($5), std::move($3));
}
| "union" required_fields "end"
{
diff --git a/boot/semantic.cc b/boot/semantic.cc
index bc7c2d2..a48226b 100644
--- a/boot/semantic.cc
+++ b/boot/semantic.cc
@@ -78,7 +78,17 @@ namespace elna::boot
std::string return_error::what() const
{
- return "Procedure '" + identifier + "' is expected to return, but does not have a return statement";
+ return "Procedure '" + this->identifier + "' is expected to return, but does not have a return statement";
+ }
+
+ base_type_error::base_type_error(const std::string& base, const struct position position)
+ : error(position), base(base)
+ {
+ }
+
+ std::string base_type_error::what() const
+ {
+ return "Record base type '" + this->base + "' is not a record.";
}
type_analysis_visitor::type_analysis_visitor(symbol_bag bag)
@@ -291,8 +301,37 @@ namespace elna::boot
void name_analysis_visitor::visit(record_type_expression *type_expression)
{
- auto result_type = std::make_shared<record_type>();
-
+ std::shared_ptr<record_type> result_type;
+ if (type_expression->base.has_value())
+ {
+ if (auto unresolved_alias = this->bag.declared(type_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()))
+ {
+ if (auto base_type_info = base_symbol->is_type())
+ {
+ result_type = std::make_shared<record_type>(base_type_info->symbol);
+ }
+ else
+ {
+ add_error<base_type_error>(type_expression->base.value(), type_expression->position());
+ this->current_type = type();
+ return;
+ }
+ }
+ else
+ {
+ add_error<undeclared_error>(type_expression->base.value(), type_expression->position());
+ this->current_type = type();
+ return;
+ }
+ }
+ else
+ {
+ result_type = std::make_shared<record_type>();
+ }
result_type->fields = build_composite_type(type_expression->fields);
this->current_type = type(result_type);
@@ -498,7 +537,7 @@ namespace elna::boot
{
call->callable().accept(this);
}
- for (expression *const argument: call->arguments)
+ for (expression *const argument : call->arguments)
{
argument->accept(this);
}
@@ -551,15 +590,13 @@ namespace elna::boot
expression->operand().accept(this);
}
- void name_analysis_visitor::visit(named_expression *type_expression)
+ void name_analysis_visitor::visit(named_expression *expression)
{
- auto unresolved_alias = this->bag.declared(type_expression->name);
-
- if (unresolved_alias != nullptr)
+ if (auto unresolved_alias = this->bag.declared(expression->name))
{
this->current_type = type(unresolved_alias);
}
- else if (auto from_symbol_table = this->bag.lookup(type_expression->name))
+ else if (auto from_symbol_table = this->bag.lookup(expression->name))
{
if (auto type_symbol = from_symbol_table->is_type())
{
@@ -568,7 +605,7 @@ namespace elna::boot
}
else
{
- add_error<undeclared_error>(type_expression->name, type_expression->position());
+ add_error<undeclared_error>(expression->name, expression->position());
this->current_type = type();
}
}
diff --git a/boot/symbol.cc b/boot/symbol.cc
index 902d331..d01eb8e 100644
--- a/boot/symbol.cc
+++ b/boot/symbol.cc
@@ -268,6 +268,11 @@ namespace elna::boot
{
}
+ record_type::record_type(type base)
+ : base(base)
+ {
+ }
+
procedure_type::procedure_type(return_t return_type)
: return_type(return_type)
{