diff options
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/ast.cc | 4 | ||||
| -rw-r--r-- | boot/parser.yy | 6 | ||||
| -rw-r--r-- | boot/semantic.cc | 57 | ||||
| -rw-r--r-- | boot/symbol.cc | 5 |
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) { |
