diff options
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/evaluator.cc | 73 | ||||
| -rw-r--r-- | boot/result.cc | 26 |
2 files changed, 74 insertions, 25 deletions
diff --git a/boot/evaluator.cc b/boot/evaluator.cc index 407370a..14ca889 100644 --- a/boot/evaluator.cc +++ b/boot/evaluator.cc @@ -370,7 +370,7 @@ namespace elna::boot } auto& index_literal = std::get<integer_literal>(evaluated_index.value()); - return index_literal.is_negative() ? std::nullopt : index_literal.to_unsigned(); + return index_literal < 0 ? std::nullopt : index_literal.try_to<std::size_t>(); } std::optional<constant_value> evaluator::evaluate_slicing(slicing_expression& subject) @@ -694,6 +694,66 @@ namespace elna::boot }, lhs.value()); } + std::optional<constant_value> evaluator::cast_to_int(const constant_value& source_expression) + { + return std::visit([](auto&& source_value) -> std::optional<constant_value> { + using T = std::decay_t<decltype(source_value)>; + + if constexpr (std::is_same_v<T, integer_literal>) + { + std::optional<std::ptrdiff_t> signed_value = source_value.template try_to<std::ptrdiff_t>(); + + return signed_value.has_value() + ? std::optional(integer_literal::from(signed_value.value())) + : std::nullopt; + } + else if constexpr (std::is_same_v<T, double> + || std::is_same_v<T, bool> + || std::is_same_v<T, unsigned char>) + { + return integer_literal::from(static_cast<std::ptrdiff_t>(source_value)); + } + else if constexpr (std::is_same_v<T, std::nullptr_t>) + { + return integer_literal::from<std::ptrdiff_t>(0); + } + else + { + return std::nullopt; + } + }, source_expression); + } + + std::optional<constant_value> evaluator::cast_to_word(const constant_value& source_expression) + { + return std::visit([](auto&& source_value) -> std::optional<constant_value> { + using T = std::decay_t<decltype(source_value)>; + + if constexpr (std::is_same_v<T, integer_literal>) + { + std::optional<std::size_t> unsigned_value = source_value.template try_to<std::size_t>(); + + return unsigned_value.has_value() + ? std::optional(integer_literal::from(unsigned_value.value())) + : std::nullopt; + } + else if constexpr (std::is_same_v<T, double> + || std::is_same_v<T, bool> + || std::is_same_v<T, unsigned char>) + { + return integer_literal::from(static_cast<std::size_t>(source_value)); + } + else if constexpr (std::is_same_v<T, std::nullptr_t>) + { + return integer_literal::from<std::ptrdiff_t>(0U); + } + else + { + return std::nullopt; + } + }, source_expression); + } + std::optional<constant_value> evaluator::evaluate_cast(cast_expression& subject) { auto value = evaluate(subject.value()); @@ -702,6 +762,17 @@ namespace elna::boot { return std::nullopt; } + const type resolved = resolve_underlying_type(subject.type_decoration); + + if (is_primitive_type(resolved, "Int")) + { + return cast_to_int(value.value()); + } + else if (is_primitive_type(resolved, "Word")) + { + return cast_to_word(value.value()); + } + return constant_value{ value.value() }; } diff --git a/boot/result.cc b/boot/result.cc index e9090de..30b4576 100644 --- a/boot/result.cc +++ b/boot/result.cc @@ -328,28 +328,6 @@ namespace elna::boot return *this; } - std::optional<std::ptrdiff_t> integer_literal::to_signed() const - { - if (is_negative_minimum(sizeof(std::ptrdiff_t) * CHAR_BIT)) - { - return std::numeric_limits<ptrdiff_t>::min(); - } - auto [written, rop] = export_to_words<std::ptrdiff_t>(); - - if (written > 1 || rop < 0) - { - return std::nullopt; - } - return is_negative() ? -rop : rop; - } - - std::optional<std::size_t> integer_literal::to_unsigned() const - { - auto [written, rop] = export_to_words<std::size_t>(); - - return written > 1 ? std::nullopt : std::make_optional(rop); - } - bool integer_literal::fit_into(const std::size_t target_size) { if (fits_in(target_size * CHAR_BIT)) @@ -485,14 +463,14 @@ std::size_t std::hash<elna::boot::integer_literal>::operator()(const elna::boot: { if (key.is_signed()) { - if (auto converted = key.to_signed()) + if (auto converted = key.try_to<std::ptrdiff_t>()) { return std::hash<std::ptrdiff_t>{}(*converted); } } else { - if (auto converted = key.to_unsigned()) + if (auto converted = key.try_to<std::size_t>()) { return std::hash<std::size_t>{}(*converted); } |
