diff options
| -rw-r--r-- | boot/evaluator.cc | 93 | ||||
| -rw-r--r-- | boot/result.cc | 6 | ||||
| -rw-r--r-- | boot/symbol.cc | 12 | ||||
| -rw-r--r-- | gcc/gcc/elna-generic.cc | 19 | ||||
| -rw-r--r-- | gcc/gcc/elna-tree.cc | 38 | ||||
| -rw-r--r-- | include/elna/boot/result.h | 19 | ||||
| -rw-r--r-- | include/elna/boot/symbol.h | 8 | ||||
| -rw-r--r-- | include/elna/gcc/elna-tree.h | 8 | ||||
| -rw-r--r-- | source/main.elna | 2 | ||||
| -rw-r--r-- | testsuite/compilable/const_pointer_conversion.elna | 14 | ||||
| -rw-r--r-- | testsuite/runnable/compile_time_address_not_equal.elna | 7 | ||||
| -rw-r--r-- | testsuite/runnable/constant_string_initializer.elna | 6 |
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. |
