diff options
Diffstat (limited to 'boot/type_check.cc')
| -rw-r--r-- | boot/type_check.cc | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/boot/type_check.cc b/boot/type_check.cc index b42792b..b310e34 100644 --- a/boot/type_check.cc +++ b/boot/type_check.cc @@ -21,6 +21,16 @@ along with GCC; see the file COPYING3. If not see namespace elna::boot { + non_constant_initializer_error::non_constant_initializer_error(const source_position position) + : error(position) + { + } + + std::string non_constant_initializer_error::what() const + { + return "Variable initializers must be constant expressions"; + } + type_mismatch_error::type_mismatch_error(const source_position position, type expected, type actual) : error(position), expected(expected), actual(actual) @@ -354,8 +364,8 @@ namespace elna::boot }.run(); } - type_analysis_visitor::type_analysis_visitor(symbol_bag bag) - : error_container(), bag(bag) + type_analysis_visitor::type_analysis_visitor(symbol_bag bag, const target_info& target) + : error_container(), bag(bag), target(target) { } @@ -424,10 +434,26 @@ namespace elna::boot { walking_visitor::visit(declaration); - if (declaration->initializer == nullptr) + if (declaration->initializer == nullptr || has_errors()) { return; } + evaluator constant_evaluator(this->bag, this->target, this->evaluated_initializers); + if (!constant_evaluator.evaluate(*declaration->initializer)) + { + add_error<non_constant_initializer_error>(declaration->initializer->position()); + return; + } + // Record const variable initializers so later declarations + // can chain through them. + for (const auto& id : declaration->identifiers) + { + if (auto var = this->bag.lookup(id.name())->is_variable(); + resolve_aliases(var->symbol).get<constant_type>() != nullptr) + { + this->evaluated_initializers[id.name()] = declaration->initializer; + } + } for (const identifier_definition& variable_identifier : declaration->identifiers) { auto variable_symbol = this->bag.lookup(variable_identifier.name())->is_variable(); |
