aboutsummaryrefslogtreecommitdiff
path: root/boot/evaluator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'boot/evaluator.cc')
-rw-r--r--boot/evaluator.cc101
1 files changed, 75 insertions, 26 deletions
diff --git a/boot/evaluator.cc b/boot/evaluator.cc
index b49a9ec..bff727d 100644
--- a/boot/evaluator.cc
+++ b/boot/evaluator.cc
@@ -218,7 +218,7 @@ namespace elna::boot
}
if (is_primitive_type(decoration, "Word"))
{
- return constant_value{ static_cast<literal<std::uint32_t>&>(subject).value };
+ return constant_value{ static_cast<literal<integer_literal>&>(subject).value };
}
if (is_primitive_type(decoration, "Float"))
{
@@ -279,9 +279,9 @@ namespace elna::boot
}
position = static_cast<std::size_t>(*int_index);
}
- else if (auto *word_index = std::get_if<std::uint32_t>(&index.value()))
+ else if (auto *word_index = std::get_if<integer_literal>(&index.value()))
{
- position = *word_index;
+ position = word_index->to<std::uint32_t>();
}
else
{
@@ -416,7 +416,7 @@ namespace elna::boot
return std::visit([](const auto& value) -> std::optional<constant_value> {
using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_integral_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (is_integral<T> || std::is_same_v<T, integer_literal>)
{
return constant_value{ ~value };
}
@@ -433,7 +433,7 @@ namespace elna::boot
template<typename T>
static std::optional<T> add_overflow(T lhs, T rhs)
{
- if constexpr (std::is_integral_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (is_integral<T>)
{
T result;
return __builtin_add_overflow(lhs, rhs, &result)
@@ -446,7 +446,7 @@ namespace elna::boot
template<typename T>
static std::optional<T> sub_overflow(T lhs, T rhs)
{
- if constexpr (std::is_integral_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (is_integral<T>)
{
T result;
return __builtin_sub_overflow(lhs, rhs, &result)
@@ -459,7 +459,7 @@ namespace elna::boot
template<typename T>
static std::optional<T> mul_overflow(T lhs, T rhs)
{
- if constexpr (std::is_integral_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (is_integral<T>)
{
T result;
return __builtin_mul_overflow(lhs, rhs, &result)
@@ -506,7 +506,14 @@ namespace elna::boot
{
using enum binary_operator;
case sum:
- if constexpr (std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (std::is_same_v<T, integer_literal>)
+ {
+ if (auto result = lhs.add(rhs))
+ {
+ return constant_value{ result.value() };
+ }
+ }
+ else if constexpr (is_arithmetic<T>)
{
if (auto result = add_overflow(lhs, rhs))
{
@@ -515,7 +522,14 @@ namespace elna::boot
}
return std::nullopt;
case subtraction:
- if constexpr (std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (std::is_same_v<T, integer_literal>)
+ {
+ if (auto result = lhs.sub(rhs))
+ {
+ return constant_value{ result.value() };
+ }
+ }
+ else if constexpr (is_arithmetic<T>)
{
if (auto result = sub_overflow(lhs, rhs))
{
@@ -524,7 +538,14 @@ namespace elna::boot
}
return std::nullopt;
case multiplication:
- if constexpr (std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (std::is_same_v<T, integer_literal>)
+ {
+ if (auto result = lhs.mul(rhs))
+ {
+ return constant_value{ result.value() };
+ }
+ }
+ else if constexpr (is_arithmetic<T>)
{
if (auto result = mul_overflow(lhs, rhs))
{
@@ -533,7 +554,14 @@ namespace elna::boot
}
return std::nullopt;
case division:
- if constexpr (std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (std::is_same_v<T, integer_literal>)
+ {
+ if (auto result = lhs.div(rhs))
+ {
+ return constant_value{ result.value() };
+ }
+ }
+ else if constexpr (is_arithmetic<T>)
{
if (rhs != static_cast<T>(0))
{
@@ -542,7 +570,14 @@ namespace elna::boot
}
return std::nullopt;
case remainder:
- if constexpr (std::is_integral_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (std::is_same_v<T, integer_literal>)
+ {
+ if (auto result = lhs.mod(rhs))
+ {
+ return constant_value{ result.value() };
+ }
+ }
+ else if constexpr (is_integral<T>)
{
if (rhs != static_cast<T>(0))
{
@@ -552,21 +587,21 @@ namespace elna::boot
return std::nullopt;
case disjunction:
case bitwise_disjunction:
- if constexpr (std::is_integral_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (is_integral<T> || std::is_same_v<T, integer_literal>)
{
return constant_value{ lhs | rhs };
}
return std::nullopt;
case conjunction:
case bitwise_conjunction:
- if constexpr (std::is_integral_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (is_integral<T> || std::is_same_v<T, integer_literal>)
{
return constant_value{ lhs & rhs };
}
return std::nullopt;
case exclusive_disjunction:
case bitwise_exclusive_disjunction:
- if constexpr (std::is_integral_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (is_integral<T> || std::is_same_v<T, integer_literal>)
{
return constant_value{ lhs ^ rhs };
}
@@ -590,7 +625,14 @@ namespace elna::boot
}
return std::nullopt;
case shift_left:
- if constexpr (std::is_integral_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (std::is_same_v<T, integer_literal>)
+ {
+ if (auto result = lhs.shl(rhs))
+ {
+ return constant_value{ result.value() };
+ }
+ }
+ else if constexpr (is_integral<T>)
{
if (rhs < 0 || static_cast<std::make_unsigned_t<T>>(rhs) >= std::numeric_limits<T>::digits)
{
@@ -600,7 +642,14 @@ namespace elna::boot
}
return std::nullopt;
case shift_right:
- if constexpr (std::is_integral_v<T>)
+ if constexpr (std::is_same_v<T, integer_literal>)
+ {
+ if (auto result = lhs.shr(rhs))
+ {
+ return constant_value{ result.value() };
+ }
+ }
+ else if constexpr (std::is_integral_v<T>)
{
return constant_value{ lhs >> rhs };
}
@@ -610,25 +659,25 @@ namespace elna::boot
case not_equals:
return constant_value{ lhs != rhs };
case less:
- if constexpr (std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (is_arithmetic<T> || std::is_same_v<T, integer_literal>)
{
return constant_value{ lhs < rhs };
}
return std::nullopt;
case greater:
- if constexpr (std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (is_arithmetic<T> || std::is_same_v<T, integer_literal>)
{
return constant_value{ lhs > rhs };
}
return std::nullopt;
case less_equal:
- if constexpr (std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (is_arithmetic<T> || std::is_same_v<T, integer_literal>)
{
return constant_value{ lhs <= rhs };
}
return std::nullopt;
case greater_equal:
- if constexpr (std::is_arithmetic_v<T> && !std::is_same_v<T, bool>)
+ if constexpr (is_arithmetic<T> || std::is_same_v<T, integer_literal>)
{
return constant_value{ lhs >= rhs };
}
@@ -690,14 +739,14 @@ namespace elna::boot
{
if (auto size = evaluate_traits_size(subject.types.front()))
{
- return constant_value{ static_cast<std::uint32_t>(size.value()) };
+ return constant_value{ integer_literal::from(static_cast<std::uint32_t>(size.value())) };
}
}
else if (subject.name.name() == "alignment")
{
if (auto alignment = evaluate_traits_alignment(subject.types.front()))
{
- return constant_value{ static_cast<std::uint32_t>(alignment.value()) };
+ return constant_value{ integer_literal::from(static_cast<std::uint32_t>(alignment.value())) };
}
}
else if (subject.name.name() == "min")
@@ -710,7 +759,7 @@ namespace elna::boot
}
if (is_primitive_type(resolved, "Word"))
{
- return constant_value{ static_cast<std::uint32_t>(0) };
+ return constant_value{ integer_literal::from(static_cast<std::uint32_t>(0)) };
}
if (is_primitive_type(resolved, "Char"))
{
@@ -739,7 +788,7 @@ namespace elna::boot
}
if (is_primitive_type(resolved, "Word"))
{
- return constant_value{ std::numeric_limits<std::uint32_t>::max() };
+ return constant_value{ integer_literal::from(std::numeric_limits<std::uint32_t>::max()) };
}
if (is_primitive_type(resolved, "Char"))
{
@@ -772,7 +821,7 @@ namespace elna::boot
if (field_search != std::cend(record_layout.value().offset_map))
{
- return constant_value{ static_cast<std::uint32_t>(field_search->second) };
+ return constant_value{ integer_literal::from(static_cast<std::uint32_t>(field_search->second)) };
}
}
}