aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-07-20 16:09:24 +0200
committerEugen Wissner <belka@caraus.de>2026-07-20 16:09:24 +0200
commit6b131c925dee7a5f97516edd581e051e08bb52d8 (patch)
tree680ae83121442f777e03aa0a0d1299cc364b95dd
parentcbbe1593bb0893654bd71e611ca610df03bac768 (diff)
downloadelna-6b131c925dee7a5f97516edd581e051e08bb52d8.tar.gz
Implement min and max for booleans and floats
-rw-r--r--boot/evaluator.cc16
-rw-r--r--boot/name_analysis.cc5
-rw-r--r--gcc/gcc/elna-generic.cc31
-rw-r--r--include/elna/boot/evaluator.h2
-rw-r--r--include/elna/gcc/elna-generic.h5
5 files changed, 31 insertions, 28 deletions
diff --git a/boot/evaluator.cc b/boot/evaluator.cc
index b7edd3a..7eb612b 100644
--- a/boot/evaluator.cc
+++ b/boot/evaluator.cc
@@ -534,6 +534,14 @@ namespace elna::boot
{
return constant_value{ static_cast<unsigned char>(0) };
}
+ if (is_primitive_type(resolved, "Bool"))
+ {
+ return constant_value{ false };
+ }
+ if (is_primitive_type(resolved, "Float"))
+ {
+ return constant_value{ -std::numeric_limits<double>::max() };
+ }
if (auto enumeration = resolved.get<enumeration_type>())
{
return constant_value{ 1 };
@@ -555,6 +563,14 @@ namespace elna::boot
{
return constant_value{ std::numeric_limits<unsigned char>::max() };
}
+ if (is_primitive_type(resolved, "Bool"))
+ {
+ return constant_value{ true };
+ }
+ if (is_primitive_type(resolved, "Float"))
+ {
+ return constant_value{ std::numeric_limits<double>::max() };
+ }
if (auto enumeration = resolved.get<enumeration_type>())
{
return constant_value{ static_cast<std::int32_t>(enumeration->members.size()) };
diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc
index 22b7814..54a2d1a 100644
--- a/boot/name_analysis.cc
+++ b/boot/name_analysis.cc
@@ -539,9 +539,10 @@ for (const auto& member : expression->members)
if (!trait->type_decoration.empty())
{
type const resolved = resolve_underlying_type(trait->type_decoration);
- bool const is_enum = resolved.get<enumeration_type>() != nullptr;
- if (!is_enum && !is_discrete_type(resolved))
+ if (resolved.get<enumeration_type>() == nullptr
+ && !is_primitive_type(resolved, "Float")
+ && !is_discrete_type(resolved))
{
add_error<unsupported_trait_type_error>(trait->name,
trait->type_decoration);
diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc
index 79207cc..8561ac4 100644
--- a/gcc/gcc/elna-generic.cc
+++ b/gcc/gcc/elna-generic.cc
@@ -39,6 +39,8 @@ namespace elna::gcc
generic_visitor::generic_visitor(std::shared_ptr<symbol_table> symbol_table,
boot::symbol_bag bag, const boot::target_info& target)
: bag(bag), symbols(symbol_table), target(target)
+ , const_evaluator(std::make_unique<boot::evaluator>(this->bag, this->target,
+ this->evaluated_initializers))
{
}
@@ -862,34 +864,13 @@ namespace elna::gcc
{
location_t trait_location = get_location(&trait->position());
- if (trait->name == "size")
+ if (trait->name == "size" || trait->name == "alignment"
+ || trait->name == "min" || trait->name == "max")
{
if (expect_trait_type_only(trait))
{
- this->current_expression = fold_convert_loc(trait_location, elna_word_type_node,
- size_in_bytes(this->current_expression));
- }
- }
- else if (trait->name == "alignment")
- {
- if (expect_trait_type_only(trait))
- {
- this->current_expression = build_int_cstu(elna_word_type_node,
- TYPE_ALIGN_UNIT(this->current_expression));
- }
- }
- else if (trait->name == "min")
- {
- if (expect_trait_type_only(trait))
- {
- this->current_expression = TYPE_MIN_VALUE(this->current_expression);
- }
- }
- else if (trait->name == "max")
- {
- if (expect_trait_type_only(trait))
- {
- this->current_expression = TYPE_MAX_VALUE(this->current_expression);
+ this->current_expression = constant_to_tree(
+ *this->const_evaluator->evaluate_traits(*trait));
}
}
else if (trait->name == "offset")
diff --git a/include/elna/boot/evaluator.h b/include/elna/boot/evaluator.h
index f1a5437..08aec6b 100644
--- a/include/elna/boot/evaluator.h
+++ b/include/elna/boot/evaluator.h
@@ -80,11 +80,11 @@ namespace elna::boot
std::optional<constant_value> evaluate_unary(unary_expression& subject);
std::optional<constant_value> evaluate_binary(binary_expression& subject);
std::optional<constant_value> evaluate_cast(cast_expression& subject);
- std::optional<constant_value> evaluate_traits(traits_expression& subject);
std::optional<std::size_t> evaluate_traits_size(const type& subject);
std::optional<std::size_t> evaluate_traits_alignment(const type& subject);
public:
+ std::optional<constant_value> evaluate_traits(traits_expression& subject);
explicit evaluator(symbol_bag& bag, const target_info& target,
const std::map<std::string, expression*>& evaluated_initializers);
diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h
index 9dea83b..aa4bde1 100644
--- a/include/elna/gcc/elna-generic.h
+++ b/include/elna/gcc/elna-generic.h
@@ -17,8 +17,11 @@ along with GCC; see the file COPYING3. If not see
#pragma once
+#include <map>
+#include <memory>
#include <string>
#include "elna/boot/ast.h"
+#include "elna/boot/evaluator.h"
#include "elna/boot/symbol.h"
#include "elna/gcc/elna-tree.h"
@@ -36,6 +39,8 @@ namespace elna::gcc
elna::boot::symbol_bag bag;
std::shared_ptr<symbol_table> symbols;
const elna::boot::target_info& target;
+ std::map<std::string, boot::expression *> evaluated_initializers;
+ std::unique_ptr<boot::evaluator> const_evaluator;
void enter_scope();
tree leave_scope();