diff options
Diffstat (limited to 'boot/semantic.cc')
| -rw-r--r-- | boot/semantic.cc | 57 |
1 files changed, 47 insertions, 10 deletions
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(); } } |
