aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boot/evaluator.cc93
-rw-r--r--boot/result.cc6
-rw-r--r--boot/symbol.cc12
-rw-r--r--gcc/gcc/elna-generic.cc19
-rw-r--r--gcc/gcc/elna-tree.cc38
-rw-r--r--include/elna/boot/result.h19
-rw-r--r--include/elna/boot/symbol.h8
-rw-r--r--include/elna/gcc/elna-tree.h8
-rw-r--r--source/main.elna2
-rw-r--r--testsuite/compilable/const_pointer_conversion.elna14
-rw-r--r--testsuite/runnable/compile_time_address_not_equal.elna7
-rw-r--r--testsuite/runnable/constant_string_initializer.elna6
12 files changed, 92 insertions, 140 deletions
diff --git a/boot/evaluator.cc b/boot/evaluator.cc
index 56ba270..afa72db 100644
--- a/boot/evaluator.cc
+++ b/boot/evaluator.cc
@@ -231,6 +231,10 @@ namespace elna::boot
{
return constant_value{ std::nullptr_t{} };
}
+ else if (is_string_type(decoration))
+ {
+ return constant_value{ static_cast<literal<std::string>&>(subject).value };
+ }
return std::nullopt;
}
@@ -356,72 +360,59 @@ namespace elna::boot
std::optional<constant_value> evaluator::evaluate_unary(unary_expression& subject)
{
- if (subject.operation() == unary_operator::reference)
- {
- if (auto *designator = subject.operand().is_designator())
- {
- if (auto *named = designator->is_named())
- {
- return constant_value{ global_address{ .name = named->name } };
- }
- }
- return std::nullopt;
- }
auto operand = evaluate(subject.operand());
if (!operand)
{
return std::nullopt;
}
- if (subject.operation() == unary_operator::minus)
+ switch (subject.operation())
{
- return std::visit([](auto&& value) -> std::optional<constant_value> {
- using T = std::decay_t<decltype(value)>;
+ using enum unary_operator;
+ case minus:
+ return std::visit([](auto&& value) -> std::optional<constant_value> {
+ using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, integer_literal>)
- {
- if (auto result = value.neg())
+ if constexpr (std::is_same_v<T, integer_literal>)
+ {
+ if (auto result = value.neg())
+ {
+ return constant_value{ result.value() };
+ }
+ return std::nullopt;
+ }
+ if constexpr (std::is_same_v<T, double>)
{
- return constant_value{ result.value() };
+ return constant_value{ -value };
}
return std::nullopt;
- }
- if constexpr (std::is_same_v<T, double>)
- {
- return constant_value{ -value };
- }
- return std::nullopt;
- }, operand.value());
- }
- if (subject.operation() == unary_operator::logical_negation)
- {
- return std::visit([](const auto& value) -> std::optional<constant_value> {
- using T = std::decay_t<decltype(value)>;
+ }, operand.value());
+ case logical_negation:
+ return std::visit([](const auto& value) -> std::optional<constant_value> {
+ using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, bool>)
- {
- return constant_value{ !value };
- }
- return std::nullopt;
- }, operand.value());
- }
- if (subject.operation() == unary_operator::bitwise_negation)
- {
- return std::visit([](const auto& value) -> std::optional<constant_value> {
- using T = std::decay_t<decltype(value)>;
+ if constexpr (std::is_same_v<T, bool>)
+ {
+ return constant_value{ !value };
+ }
+ return std::nullopt;
+ }, operand.value());
+ case bitwise_negation:
+ return std::visit([](const auto& value) -> std::optional<constant_value> {
+ using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, integer_literal>)
- {
- return constant_value{ ~value };
- }
+ if constexpr (std::is_same_v<T, integer_literal>)
+ {
+ return constant_value{ ~value };
+ }
+ return std::nullopt;
+ }, operand.value());
+ case plus:
+ return operand;
+ case negation:
+ case reference:
return std::nullopt;
- }, operand.value());
}
- if (subject.operation() == unary_operator::plus)
- {
- return operand;
- }
- return std::nullopt;
}
template<typename T>
diff --git a/boot/result.cc b/boot/result.cc
index f769625..b56046b 100644
--- a/boot/result.cc
+++ b/boot/result.cc
@@ -443,12 +443,6 @@ std::size_t std::hash<elna::boot::identifier>::operator()(
return std::hash<std::string>{}(key.name());
}
-std::size_t std::hash<elna::boot::global_address>::operator()(
- const elna::boot::global_address& key) const noexcept
-{
- return std::hash<std::string>{}(key.name);
-}
-
std::size_t std::hash<elna::boot::constant_aggregate<std::vector>>::operator()(
const elna::boot::constant_aggregate<std::vector>& key) const noexcept
{
diff --git a/boot/symbol.cc b/boot/symbol.cc
index a51ee01..6172621 100644
--- a/boot/symbol.cc
+++ b/boot/symbol.cc
@@ -456,6 +456,18 @@ namespace elna::boot
|| checked.get<enumeration_type>() != nullptr;
}
+ bool is_string_type(const type& checked)
+ {
+ if (auto slice = checked.get<slice_type>())
+ {
+ if (auto base = resolve_aliases(slice->base).get<constant_type>())
+ {
+ return is_primitive_type(resolve_aliases(base->unqualified), "Char");
+ }
+ }
+ return false;
+ }
+
type get_range_base_type(const type& range)
{
if (auto array = range.get<array_type>())
diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc
index 969e929..e59a438 100644
--- a/gcc/gcc/elna-generic.cc
+++ b/gcc/gcc/elna-generic.cc
@@ -515,24 +515,9 @@ namespace elna::gcc
void generic_visitor::visit(boot::literal<std::string> *string)
{
- tree index_constant = build_int_cstu(elna_word_type_node, string->value.size());
- tree char_array_type = build_array_type(elna_char_type_node, build_index_type(index_constant));
+ tree slice_type = get_inner_alias(string->type_decoration, symbols);
- tree string_literal = build_string(string->value.size(), string->value.c_str());
- TREE_TYPE(string_literal) = char_array_type;
- TREE_CONSTANT(string_literal) = 1;
- TREE_READONLY(string_literal) = 1;
- TREE_STATIC(string_literal) = 1;
-
- tree slice_type = get_inner_alias(string->type_decoration, this->symbols);
- tree ptr_field = TYPE_FIELDS(slice_type);
-
- tree ptr_type = TREE_TYPE(ptr_field);
- string_literal = build4(ARRAY_REF, elna_char_type_node,
- string_literal, integer_zero_node, NULL_TREE, NULL_TREE);
- string_literal = build1(ADDR_EXPR, ptr_type, string_literal);
-
- this->current_expression = build_slice(slice_type, string_literal, index_constant);
+ this->current_expression = constant_to_tree(boot::constant_value{ string->value }, this->symbols, slice_type);
}
void generic_visitor::visit(boot::traits_expression *trait)
diff --git a/gcc/gcc/elna-tree.cc b/gcc/gcc/elna-tree.cc
index 6aaf6f9..addb686 100644
--- a/gcc/gcc/elna-tree.cc
+++ b/gcc/gcc/elna-tree.cc
@@ -63,17 +63,6 @@ namespace elna::gcc
return RECORD_OR_UNION_TYPE_P(type) || TREE_CODE(type) == ENUMERAL_TYPE;
}
- bool is_void_type(tree type)
- {
- return type == NULL_TREE || type == void_type_node;
- }
-
- bool is_castable_type(tree type)
- {
- gcc_assert(TYPE_P(type));
- return INTEGRAL_TYPE_P(type) || POINTER_TYPE_P(type) || TREE_CODE(type) == REAL_TYPE;
- }
-
tree prepare_rvalue(tree rvalue)
{
if (DECL_P(rvalue) && TREE_CODE(TREE_TYPE(rvalue)) == FUNCTION_TYPE)
@@ -328,15 +317,26 @@ namespace elna::gcc
{
return null_pointer_node;
}
- else if (std::holds_alternative<boot::global_address>(constant_value))
+ else if (std::holds_alternative<std::string>(constant_value))
{
- const auto& address = std::get<boot::global_address>(constant_value);
- tree decl = symbols->lookup(address.name);
- if (decl == NULL_TREE)
- {
- return NULL_TREE;
- }
- return build1(ADDR_EXPR, build_pointer_type(TREE_TYPE(decl)), decl);
+ const auto& string_value = std::get<std::string>(constant_value);
+ tree index_constant = build_int_cstu(elna_word_type_node, string_value.size());
+ tree char_array_type = build_array_type(elna_char_type_node, build_index_type(index_constant));
+
+ tree string_literal = build_string(string_value.size(), string_value.c_str());
+ TREE_TYPE(string_literal) = char_array_type;
+ TREE_CONSTANT(string_literal) = 1;
+ TREE_READONLY(string_literal) = 1;
+ TREE_STATIC(string_literal) = 1;
+
+ tree ptr_field = TYPE_FIELDS(type);
+
+ tree ptr_type = TREE_TYPE(ptr_field);
+ string_literal = build4(ARRAY_REF, elna_char_type_node,
+ string_literal, integer_zero_node, NULL_TREE, NULL_TREE);
+ string_literal = build1(ADDR_EXPR, ptr_type, string_literal);
+
+ return build_slice(type, string_literal, index_constant);
}
else if (std::holds_alternative<boot::constant_aggregate<boot::ordered_map>>(constant_value))
{
diff --git a/include/elna/boot/result.h b/include/elna/boot/result.h
index 56884ff..1455371 100644
--- a/include/elna/boot/result.h
+++ b/include/elna/boot/result.h
@@ -507,17 +507,6 @@ namespace elna::boot
type_properties bool_properties;
};
- /**
- * Address of a module-level variable, tracked by name so that
- * different variables have distinct addresses at compile time.
- */
- struct global_address
- {
- std::string name;
-
- bool operator==(const global_address&) const = default;
- };
-
template<template<typename, typename> typename C, template<typename> typename Alloc = std::allocator>
class constant_aggregate;
@@ -533,7 +522,7 @@ namespace elna::boot
bool,
unsigned char,
std::nullptr_t,
- global_address,
+ std::string,
constant_aggregate<ordered_map>,
constant_aggregate<std::vector>
>;
@@ -655,12 +644,6 @@ struct std::hash<elna::boot::identifier>
};
template<>
-struct std::hash<elna::boot::global_address>
-{
- std::size_t operator()(const elna::boot::global_address& key) const noexcept;
-};
-
-template<>
struct std::hash<elna::boot::constant_aggregate<std::vector>>
{
std::size_t operator()(const elna::boot::constant_aggregate<std::vector>& key) const noexcept;
diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h
index 01eedb1..5000ab8 100644
--- a/include/elna/boot/symbol.h
+++ b/include/elna/boot/symbol.h
@@ -588,6 +588,14 @@ namespace elna::boot
bool is_scalar_type(const type& checked);
/**
+ * Checks whether the given type is a string (slice of const Char).
+ *
+ * \param checked The type t o check.
+ * \return Whether the type is a string type.
+ */
+ bool is_string_type(const type& checked);
+
+ /**
* If \a range is an array or a slice gives its base type, otherwise
* returns an empty type.
*
diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h
index 41f5cc3..219acb1 100644
--- a/include/elna/gcc/elna-tree.h
+++ b/include/elna/gcc/elna-tree.h
@@ -36,14 +36,6 @@ namespace elna::gcc
bool is_integral_type(tree type);
bool is_unique_type(tree type);
- bool is_void_type(tree type);
-
- /**
- * \param type The type to evaluate.
- * \return Whether this type can be converted to another type.
- */
- bool is_castable_type(tree type);
-
/**
* Prepares a value to be bound to a variable or parameter.
*
diff --git a/source/main.elna b/source/main.elna
index c127ba4..369d013 100644
--- a/source/main.elna
+++ b/source/main.elna
@@ -34,6 +34,8 @@ var
stderr: ^FILE
stdin: ^FILE
+ t: Word := [3]Int{ 1, 2, 3 }.length
+
(*
Standard procedures.
*)
diff --git a/testsuite/compilable/const_pointer_conversion.elna b/testsuite/compilable/const_pointer_conversion.elna
deleted file mode 100644
index 003fbea..0000000
--- a/testsuite/compilable/const_pointer_conversion.elna
+++ /dev/null
@@ -1,14 +0,0 @@
-var
- x: Int
- c: const Int
- p: ^Int
- pc: ^const Int
- v: Pointer
- cv: const Pointer := nil
- cv2: const Pointer := @x
- cv3: const Pointer := @c
-
-begin
- v := p;
- v := @x
-end.
diff --git a/testsuite/runnable/compile_time_address_not_equal.elna b/testsuite/runnable/compile_time_address_not_equal.elna
deleted file mode 100644
index b011227..0000000
--- a/testsuite/runnable/compile_time_address_not_equal.elna
+++ /dev/null
@@ -1,7 +0,0 @@
-var
- x, y: const Int
- z: const Bool := @x = @y
-
-begin
- assert(~z)
-end.
diff --git a/testsuite/runnable/constant_string_initializer.elna b/testsuite/runnable/constant_string_initializer.elna
new file mode 100644
index 0000000..e2ffb25
--- /dev/null
+++ b/testsuite/runnable/constant_string_initializer.elna
@@ -0,0 +1,6 @@
+var
+ s: []const Char := "String value"
+
+begin
+ assert(s = "String value")
+end.