aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
Diffstat (limited to 'boot')
-rw-r--r--boot/evaluator.cc73
-rw-r--r--boot/result.cc26
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);
}