From 44d6e8a27294e5ca7300ab11900011b73d9336d4 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Tue, 21 Jul 2026 01:55:56 +0200 Subject: Implement slices --- boot/ast.cc | 96 +++++++++++++++++++++++ boot/evaluator.cc | 12 ++- boot/lexer.ll | 3 + boot/name_analysis.cc | 40 ++++++++++ boot/parser.yy | 7 ++ boot/symbol.cc | 21 +++++ boot/type_check.cc | 5 ++ gcc/gcc/elna-builtins.cc | 13 ++++ gcc/gcc/elna-generic.cc | 141 +++++++++++++++++++++++++++++++--- gcc/gcc/elna1.cc | 2 + include/elna/boot/ast.h | 47 ++++++++++++ include/elna/boot/evaluator.h | 2 + include/elna/boot/name_analysis.h | 2 + include/elna/boot/symbol.h | 10 +++ include/elna/boot/type_check.h | 1 + include/elna/gcc/elna-generic.h | 1 + source/command_line_interface.elna | 2 +- source/main.elna | 2 +- testsuite/compilable/slice_index.elna | 11 +++ 19 files changed, 404 insertions(+), 14 deletions(-) create mode 100644 testsuite/compilable/slice_index.elna diff --git a/boot/ast.cc b/boot/ast.cc index 9b3fbe4..3727aba 100644 --- a/boot/ast.cc +++ b/boot/ast.cc @@ -26,6 +26,11 @@ namespace elna::boot __builtin_unreachable(); } + void empty_visitor::visit(slice_type_expression *) + { + __builtin_unreachable(); + } + void empty_visitor::visit(pointer_type_expression *) { __builtin_unreachable(); @@ -126,6 +131,11 @@ namespace elna::boot __builtin_unreachable(); } + void empty_visitor::visit(slicing_expression *) + { + __builtin_unreachable(); + } + void empty_visitor::visit(traits_expression *) { __builtin_unreachable(); @@ -363,6 +373,11 @@ namespace elna::boot expression->base().accept(this); } + void walking_visitor::visit(slice_type_expression *expression) + { + expression->base().accept(this); + } + void walking_visitor::visit(pointer_type_expression *expression) { expression->base().accept(this); @@ -420,6 +435,13 @@ namespace elna::boot } } + void walking_visitor::visit(slicing_expression *expression) + { + expression->base().accept(this); + expression->offset().accept(this); + expression->length().accept(this); + } + void walking_visitor::visit(traits_expression *trait) { if (!trait->arguments.empty()) @@ -549,6 +571,11 @@ namespace elna::boot return nullptr; } + slice_type_expression *type_expression::is_slice() + { + return nullptr; + } + array_type_expression *type_expression::is_array() { return nullptr; @@ -605,6 +632,32 @@ namespace elna::boot return *m_base; } + slice_type_expression::slice_type_expression(const source_position position, + type_expression *base) + : node(position), m_base(base) + { + } + + slice_type_expression::~slice_type_expression() + { + delete m_base; + } + + void slice_type_expression::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + + slice_type_expression *slice_type_expression::is_slice() + { + return this; + } + + type_expression& slice_type_expression::base() + { + return *m_base; + } + pointer_type_expression::pointer_type_expression(const source_position position, type_expression *base) : node(position), m_base(base) @@ -1016,6 +1069,44 @@ namespace elna::boot } } + slicing_expression::slicing_expression(const source_position position, + expression *base, expression *offset, expression *length) + : node(position), m_base(base), m_offset(offset), m_length(length) + { + } + + void slicing_expression::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + + slicing_expression *slicing_expression::is_slicing() + { + return this; + } + + slicing_expression::~slicing_expression() + { + delete m_base; + delete m_offset; + delete m_length; + } + + expression& slicing_expression::base() + { + return *this->m_base; + } + + expression& slicing_expression::offset() + { + return *this->m_offset; + } + + expression& slicing_expression::length() + { + return *this->m_length; + } + named_expression::named_expression(const source_position position, const std::string& name) : node(position), name(name) { @@ -1339,6 +1430,11 @@ namespace elna::boot return nullptr; } + slicing_expression *designator_expression::is_slicing() + { + return nullptr; + } + designator_expression& assign_statement::lvalue() { return *m_lvalue; diff --git a/boot/evaluator.cc b/boot/evaluator.cc index 7eb612b..990f358 100644 --- a/boot/evaluator.cc +++ b/boot/evaluator.cc @@ -399,7 +399,8 @@ namespace elna::boot { type const resolved = resolve_underlying_type(subject); - if (is_primitive_type(resolved, "Int")) + if (is_primitive_type(resolved, "Int") + || resolved.get() != nullptr) { return target.int_size; } @@ -415,6 +416,15 @@ namespace elna::boot { return target.float_size; } + else if (is_primitive_type(resolved, "Bool")) + { + return target.bool_size; + } + else if (is_primitive_type(resolved, "String") + || resolved.get() != nullptr) + { + return target.pointer_size + target.word_size; + } else if (is_primitive_type(resolved, "Pointer") || resolved.get() != nullptr) { diff --git a/boot/lexer.ll b/boot/lexer.ll index e84af85..9fe0398 100644 --- a/boot/lexer.ll +++ b/boot/lexer.ll @@ -152,6 +152,9 @@ case { of { return yy::parser::make_OF(this->location); } +to { + return yy::parser::make_TO(this->location); +} {ID1}{ID2}* { return yy::parser::make_IDENTIFIER(yytext, this->location); } diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc index 54a2d1a..a2cacb2 100644 --- a/boot/name_analysis.cc +++ b/boot/name_analysis.cc @@ -156,6 +156,17 @@ namespace elna::boot return lookup_field(record->base, field_name); } } + else if (auto slice = resolved_type.get()) + { + if (field_name == "length") + { + return lookup_primitive_type("Word"); + } + else if (field_name == "ptr") + { + return type(std::make_shared(slice->base)); + } + } else if (auto primitive = resolved_type.get(); primitive != nullptr && primitive->identifier == "String") { if (field_name == "length") @@ -209,6 +220,12 @@ namespace elna::boot this->current_type = type(std::make_shared(this->current_type, expression->size)); } + void name_analysis_visitor::visit(slice_type_expression *expression) + { + walking_visitor::visit(expression); + this->current_type = type(std::make_shared(this->current_type)); + } + /** * Collects field names from a record type recursively, base first. */ @@ -358,6 +375,25 @@ namespace elna::boot expression->type_decoration = type(std::make_shared(element_type, expression->size)); } + void name_analysis_visitor::visit(slicing_expression *expression) + { + walking_visitor::visit(expression); + auto resolved_base = resolve_underlying_type(expression->base().type_decoration); + + if (auto pointer = resolved_base.get()) + { + expression->type_decoration = type(std::make_shared(pointer->base)); + } + else if (auto array = resolved_base.get()) + { + expression->type_decoration = type(std::make_shared(array->base)); + } + else if (auto slice = resolved_base.get()) + { + expression->type_decoration = type(slice); + } + } + void name_analysis_visitor::visit(procedure_type_expression *expression) { std::shared_ptr const result_type = @@ -613,6 +649,10 @@ for (const auto& member : expression->members) { expression->type_decoration = array->base; } + else if (auto slice = resolved_base.get()) + { + expression->type_decoration = slice->base; + } else if (resolved_base == lookup_primitive_type("String")) { expression->type_decoration = lookup_primitive_type("Char"); diff --git a/boot/parser.yy b/boot/parser.yy index aad5769..bc2ddb5 100644 --- a/boot/parser.yy +++ b/boot/parser.yy @@ -112,6 +112,7 @@ along with GCC; see the file COPYING3. If not see DEFER "defer" CASE "case" OF "of" + TO "to" PIPE "|" %token OR "or" AND "&" XOR "xor" EQUALS "=" NOT_EQUAL "<>" LESS_THAN "<" GREATER_THAN ">" LESS_EQUAL "<=" GREATER_EQUAL ">=" @@ -372,6 +373,8 @@ type_expressions: designator_expression: simple_expression "[" expression "]" { $$ = new boot::array_access_expression(boot::make_position(@$), $1, $3); } + | simple_expression "[" expression "to" expression "]" + { $$ = new boot::slicing_expression(boot::make_position(@$), $1, $3, $5); } | simple_expression "." identifier { $$ = new boot::field_access_expression(boot::make_position(@$), $1, std::move(*$3)); } | simple_expression "^" @@ -446,6 +449,10 @@ type_expression: { $$ = new boot::array_type_expression(boot::make_position(@$), $4, $2); } + | "[" "]" type_expression + { + $$ = new boot::slice_type_expression(boot::make_position(@$), $3); + } | "const" type_expression { $$ = new boot::constant_type_expression(boot::make_position(@$), $2); diff --git a/boot/symbol.cc b/boot/symbol.cc index d7a1cae..738e4e1 100644 --- a/boot/symbol.cc +++ b/boot/symbol.cc @@ -51,6 +51,11 @@ namespace elna::boot { } + type::type(std::shared_ptr slice) + : payload(slice) + { + } + type::type(std::shared_ptr procedure) : payload(procedure) { @@ -86,6 +91,7 @@ namespace elna::boot template std::shared_ptr type::get() const; template std::shared_ptr type::get() const; template std::shared_ptr type::get() const; + template std::shared_ptr type::get() const; template std::shared_ptr type::get() const; template std::shared_ptr type::get() const; template std::shared_ptr type::get() const; @@ -133,6 +139,12 @@ namespace elna::boot return right_array != nullptr && left_array->size == right_array->size && left_array->base == right_array->base; } + if (auto left_slice = resolved_this.get()) + { + auto right_slice = resolved_that.get(); + + return right_slice != nullptr && left_slice->base == right_slice->base; + } if (auto left_procedure = resolved_this.get()) { auto right_procedure = resolved_that.get(); @@ -176,6 +188,10 @@ namespace elna::boot { return "[" + std::to_string(payload->size) + "]" + payload->base.to_string(); } + else if constexpr (std::is_same_v>) + { + return "[]" + payload->base.to_string(); + } else if constexpr (std::is_same_v>) { return payload->base.empty() @@ -226,6 +242,11 @@ namespace elna::boot { } + slice_type::slice_type(type base) + : base(std::move(base)) + { + } + primitive_type::primitive_type(const std::string& identifier) : identifier(identifier) { diff --git a/boot/type_check.cc b/boot/type_check.cc index c5fb062..5d0c7a6 100644 --- a/boot/type_check.cc +++ b/boot/type_check.cc @@ -629,6 +629,11 @@ namespace elna::boot } } + void type_analysis_visitor::visit(slicing_expression *expression) + { + walking_visitor::visit(expression); + } + void type_analysis_visitor::visit(unary_expression *expression) { walking_visitor::visit(expression); diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc index 5284563..141b34f 100644 --- a/gcc/gcc/elna-builtins.cc +++ b/gcc/gcc/elna-builtins.cc @@ -154,6 +154,19 @@ namespace elna::gcc return build_static_array_type(base, reference->size); } + else if (auto reference = type.get()) + { + tree base_type = get_inner_alias(reference->base, symbols); + tree slice_record = make_node(RECORD_TYPE); + tree ptr_field = build_field(UNKNOWN_LOCATION, slice_record, "ptr", + build_pointer_type(base_type)); + tree length_field = build_field(UNKNOWN_LOCATION, slice_record, "length", + elna_word_type_node); + + TYPE_FIELDS(slice_record) = chainon(ptr_field, length_field); + layout_type(slice_record); + return slice_record; + } else if (auto reference = type.get()) { auto procedure = build_procedure_type(*reference, symbols); diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc index 8561ac4..ea209df 100644 --- a/gcc/gcc/elna-generic.cc +++ b/gcc/gcc/elna-generic.cc @@ -219,6 +219,49 @@ namespace elna::gcc this->current_expression = build_constructor(array_type, tree_arguments); } + void generic_visitor::visit(boot::slicing_expression *expression) + { + location_t location = get_location(&expression->position()); + tree slice_type = get_inner_alias(expression->type_decoration, this->symbols); + tree ptr_field = TYPE_FIELDS(slice_type); + tree length_field = TREE_CHAIN(ptr_field); + + expression->base().accept(this); + tree base = this->current_expression; + tree base_type = TREE_TYPE(base); + + expression->offset().accept(this); + tree offset = fold_convert(elna_word_type_node, this->current_expression); + offset = build2(MINUS_EXPR, elna_word_type_node, offset, size_one_node); + + tree slice_ptr; + if (TREE_CODE(base_type) == ARRAY_TYPE) + { + slice_ptr = build4_loc(location, ARRAY_REF, TREE_TYPE(base_type), + base, offset, size_one_node, NULL_TREE); + slice_ptr = build1(ADDR_EXPR, build_pointer_type(TREE_TYPE(base_type)), slice_ptr); + } + else + { + tree ptr = build3_loc(location, COMPONENT_REF, TREE_TYPE(ptr_field), + base, ptr_field, NULL_TREE); + slice_ptr = do_pointer_arithmetic(boot::binary_operator::sum, ptr, offset, location); + } + + expression->length().accept(this); + tree end_index = fold_convert(elna_word_type_node, this->current_expression); + expression->offset().accept(this); + tree start_index = fold_convert(elna_word_type_node, this->current_expression); + tree slice_length = build2(MINUS_EXPR, elna_word_type_node, + end_index, start_index); + slice_length = build2(PLUS_EXPR, elna_word_type_node, slice_length, size_one_node); + + vec *tree_arguments = nullptr; + CONSTRUCTOR_APPEND_ELT(tree_arguments, ptr_field, slice_ptr); + CONSTRUCTOR_APPEND_ELT(tree_arguments, length_field, slice_length); + this->current_expression = build_constructor(slice_type, tree_arguments); + } + void generic_visitor::visit(boot::unit *unit) { for (boot::import_declaration *const declaration : unit->imports) @@ -531,6 +574,44 @@ namespace elna::gcc return build2(combination_code, elna_bool_type_node, length_equality, equals_zero); } + else if (expression->lhs().type_decoration.get() != nullptr) + { + tree lhs_ptr_field = TYPE_FIELDS(TREE_TYPE(left)); + tree lhs_length_field = TREE_CHAIN(lhs_ptr_field); + + tree lhs_length = build3(COMPONENT_REF, TREE_TYPE(lhs_length_field), + left, lhs_length_field, NULL_TREE); + tree lhs_ptr = build3(COMPONENT_REF, TREE_TYPE(lhs_ptr_field), + left, lhs_ptr_field, NULL_TREE); + + tree rhs_length = build3(COMPONENT_REF, TREE_TYPE(lhs_length_field), + right, lhs_length_field, NULL_TREE); + tree rhs_ptr = build3(COMPONENT_REF, TREE_TYPE(lhs_ptr_field), + right, lhs_ptr_field, NULL_TREE); + + tree element_size = fold_convert(elna_word_type_node, + size_in_bytes(TREE_TYPE(TREE_TYPE(lhs_ptr_field)))); + tree byte_length = build2(MULT_EXPR, elna_word_type_node, lhs_length, element_size); + + tree length_equality = build2(equality_code, elna_bool_type_node, lhs_length, rhs_length); + tree memcmp_call = call_built_in(UNKNOWN_LOCATION, "__builtin_memcmp", integer_type_node, + lhs_ptr, rhs_ptr, byte_length); + tree equals_zero = build2(equality_code, elna_bool_type_node, memcmp_call, integer_zero_node); + + return build2(combination_code, elna_bool_type_node, length_equality, equals_zero); + } + else if (TREE_CODE(TREE_TYPE(left)) == RECORD_TYPE) + { + tree size = fold_convert(elna_word_type_node, + size_in_bytes(TREE_TYPE(left))); + tree lhs_addr = build1(ADDR_EXPR, + build_pointer_type(TREE_TYPE(left)), left); + tree rhs_addr = build1(ADDR_EXPR, + build_pointer_type(TREE_TYPE(right)), right); + tree memcmp_call = call_built_in(UNKNOWN_LOCATION, "__builtin_memcmp", + integer_type_node, lhs_addr, rhs_addr, size); + return build2(equality_code, elna_bool_type_node, memcmp_call, integer_zero_node); + } else { return build2_loc(expression_location, equality_code, elna_bool_type_node, left, right); @@ -828,13 +909,17 @@ namespace elna::gcc this->current_expression = build4_loc(location, ARRAY_REF, element_type, designator, offset, size_one_node, NULL_TREE); } - else if (TREE_TYPE(designator) == elna_string_type_node) + else if (TREE_TYPE(designator) == elna_string_type_node + || expression->base().type_decoration.get() != nullptr) { + tree ptr_field = (TREE_TYPE(designator) == elna_string_type_node) + ? elna_string_ptr_field_node + : TYPE_FIELDS(TREE_TYPE(designator)); offset = build2(MINUS_EXPR, elna_word_type_node, offset, size_one_node); - tree string_ptr = build3_loc(location, COMPONENT_REF, TREE_TYPE(elna_string_ptr_field_node), - designator, elna_string_ptr_field_node, NULL_TREE); + tree slice_ptr = build3_loc(location, COMPONENT_REF, TREE_TYPE(ptr_field), + designator, ptr_field, NULL_TREE); - tree target_pointer = do_pointer_arithmetic(boot::binary_operator::sum, string_ptr, offset, location); + tree target_pointer = do_pointer_arithmetic(boot::binary_operator::sum, slice_ptr, offset, location); this->current_expression = build_simple_mem_ref_loc(location, target_pointer); } @@ -864,13 +949,48 @@ namespace elna::gcc { location_t trait_location = get_location(&trait->position()); - if (trait->name == "size" || trait->name == "alignment" - || trait->name == "min" || trait->name == "max") + if (trait->name == "size") + { + if (expect_trait_type_only(trait)) + { + if (auto value = this->const_evaluator->evaluate_traits(*trait)) + { + this->current_expression = constant_to_tree(*value); + } + else + { + 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)) + { + if (auto value = this->const_evaluator->evaluate_traits(*trait)) + { + this->current_expression = constant_to_tree(*value); + } + else + { + this->current_expression = build_int_cstu(elna_word_type_node, + TYPE_ALIGN_UNIT(this->current_expression)); + } + } + } + else if (trait->name == "min" || trait->name == "max") { if (expect_trait_type_only(trait)) { - this->current_expression = constant_to_tree( - *this->const_evaluator->evaluate_traits(*trait)); + if (auto value = this->const_evaluator->evaluate_traits(*trait)) + { + this->current_expression = constant_to_tree(*value); + } + else + { + this->current_expression = error_mark_node; + } } } else if (trait->name == "offset") @@ -883,7 +1003,7 @@ namespace elna::gcc return; } this->current_expression = get_inner_alias(trait->types.front(), this->symbols); - auto field_type = trait->arguments.at(1)->is_named(); + auto *field_type = trait->arguments.at(1)->is_named(); if (field_type == nullptr) { @@ -1015,8 +1135,7 @@ namespace elna::gcc result = leave_scope(); } - auto& branches = statement->branches; - for (auto& branch : branches | std::views::reverse) + for (const auto& branch : statement->branches | std::views::reverse) { result = make_if_branch(*branch, result); } diff --git a/gcc/gcc/elna1.cc b/gcc/gcc/elna1.cc index e75277e..94055e5 100644 --- a/gcc/gcc/elna1.cc +++ b/gcc/gcc/elna1.cc @@ -67,6 +67,8 @@ static const elna::boot::target_info& get_host_target() target_info.char_alignment = TYPE_ALIGN_UNIT(elna_char_type_node); target_info.float_size = TYPE_PRECISION(elna_float_type_node) / BITS_PER_UNIT; target_info.float_alignment = TYPE_ALIGN_UNIT(elna_float_type_node); + target_info.bool_size = TYPE_PRECISION(elna_bool_type_node) / BITS_PER_UNIT; + target_info.bool_alignment = TYPE_ALIGN_UNIT(elna_bool_type_node); return target_info; }(); diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 4e35f02..9cc1419 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -62,6 +62,7 @@ namespace elna::boot class cast_expression; class record_constructor_expression; class array_constructor_expression; + class slicing_expression; class assign_statement; class if_statement; class import_declaration; @@ -73,6 +74,7 @@ namespace elna::boot class unary_expression; class type_expression; class array_type_expression; + class slice_type_expression; class pointer_type_expression; class constant_type_expression; class record_type_expression; @@ -101,6 +103,7 @@ namespace elna::boot virtual void visit(cast_expression *) = 0; virtual void visit(record_constructor_expression *) = 0; virtual void visit(array_constructor_expression *) = 0; + virtual void visit(slicing_expression *) = 0; virtual void visit(traits_expression *) = 0; virtual void visit(assign_statement *) = 0; virtual void visit(if_statement *) = 0; @@ -113,6 +116,7 @@ namespace elna::boot virtual void visit(binary_expression *) = 0; virtual void visit(unary_expression *) = 0; virtual void visit(array_type_expression *) = 0; + virtual void visit(slice_type_expression *) = 0; virtual void visit(pointer_type_expression *) = 0; virtual void visit(constant_type_expression *) = 0; virtual void visit(record_type_expression *) = 0; @@ -138,6 +142,7 @@ namespace elna::boot { public: [[noreturn]] void visit(array_type_expression *) override; + [[noreturn]] void visit(slice_type_expression *) override; [[noreturn]] void visit(pointer_type_expression *) override; [[noreturn]] void visit(constant_type_expression *) override; [[noreturn]] void visit(type_declaration *) override; @@ -159,6 +164,7 @@ namespace elna::boot [[noreturn]] void visit(cast_expression *) override; [[noreturn]] void visit(record_constructor_expression *) override; [[noreturn]] void visit(array_constructor_expression *) override; + [[noreturn]] void visit(slicing_expression *) override; [[noreturn]] void visit(traits_expression *) override; [[noreturn]] void visit(binary_expression *) override; [[noreturn]] void visit(unary_expression *) override; @@ -182,6 +188,7 @@ namespace elna::boot { public: void visit(array_type_expression *) override; + void visit(slice_type_expression *) override; void visit(pointer_type_expression *) override; void visit(constant_type_expression *) override; void visit(type_declaration *) override; @@ -203,6 +210,7 @@ namespace elna::boot void visit(cast_expression *expression) override; void visit(record_constructor_expression *expression) override; void visit(array_constructor_expression *expression) override; + void visit(slicing_expression *expression) override; void visit(traits_expression *trait) override; void visit(binary_expression *expression) override; void visit(unary_expression *expression) override; @@ -287,6 +295,7 @@ namespace elna::boot virtual record_type_expression *is_record(); virtual procedure_type_expression *is_procedure(); virtual enumeration_type_expression *is_enumeration(); + virtual slice_type_expression *is_slice(); }; class array_type_expression : public type_expression @@ -306,6 +315,21 @@ namespace elna::boot type_expression& base(); }; + class slice_type_expression : public type_expression + { + type_expression *m_base; + + public: + slice_type_expression(const source_position position, + type_expression *base); + ~slice_type_expression() override; + + void accept(parser_visitor *visitor) override; + slice_type_expression *is_slice() override; + + type_expression& base(); + }; + class pointer_type_expression : public type_expression { type_expression *m_base; @@ -601,12 +625,35 @@ namespace elna::boot virtual array_access_expression *is_array_access(); virtual field_access_expression *is_field_access(); virtual dereference_expression *is_dereference(); + virtual slicing_expression *is_slicing(); designator_expression *is_designator() override; void accept(parser_visitor *visitor) override; ~designator_expression() override = 0; }; + /** + * Slicing expression. + */ + class slicing_expression : public designator_expression + { + expression *m_base; + expression *m_offset; + expression *m_length; + + public: + slicing_expression(const source_position position, + expression *base, expression *offset, expression *length); + void accept(parser_visitor *visitor) override; + slicing_expression *is_slicing() override; + + expression& base(); + expression& offset(); + expression& length(); + + ~slicing_expression() override; + }; + /** * Expression refering to an entity by its name. */ diff --git a/include/elna/boot/evaluator.h b/include/elna/boot/evaluator.h index 08aec6b..b8a9956 100644 --- a/include/elna/boot/evaluator.h +++ b/include/elna/boot/evaluator.h @@ -43,6 +43,8 @@ namespace elna::boot std::size_t char_alignment{0}; std::size_t float_size{0}; std::size_t float_alignment{0}; + std::size_t bool_size{0}; + std::size_t bool_alignment{0}; }; /** diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h index 6f40bec..bb66c7a 100644 --- a/include/elna/boot/name_analysis.h +++ b/include/elna/boot/name_analysis.h @@ -125,12 +125,14 @@ namespace elna::boot name_analysis_visitor(symbol_bag bag); void visit(array_type_expression *expression) override; + void visit(slice_type_expression *expression) override; void visit(pointer_type_expression *expression) override; void visit(constant_type_expression *expression) override; void visit(type_declaration *declaration) override; void visit(record_type_expression *expression) override; void visit(record_constructor_expression *expression) override; void visit(array_constructor_expression *expression) override; + void visit(slicing_expression *expression) override; void visit(procedure_type_expression *expression) override; void visit(enumeration_type_expression *expression) override; diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h index 9505e5a..ea418b1 100644 --- a/include/elna/boot/symbol.h +++ b/include/elna/boot/symbol.h @@ -36,6 +36,7 @@ namespace elna::boot struct pointer_type; struct constant_type; struct array_type; + struct slice_type; struct procedure_type; struct enumeration_type; @@ -49,6 +50,7 @@ namespace elna::boot std::shared_ptr, std::shared_ptr, std::shared_ptr, + std::shared_ptr, std::shared_ptr, std::shared_ptr > payload; @@ -62,6 +64,7 @@ namespace elna::boot explicit type(std::shared_ptr pointer); explicit type(std::shared_ptr constant); explicit type(std::shared_ptr array); + explicit type(std::shared_ptr slice); explicit type(std::shared_ptr procedure); explicit type(std::shared_ptr enumeration); @@ -110,6 +113,13 @@ namespace elna::boot array_type(type base, std::uint64_t size); }; + struct slice_type + { + const type base; + + explicit slice_type(type base); + }; + struct primitive_type { const std::string identifier; diff --git a/include/elna/boot/type_check.h b/include/elna/boot/type_check.h index 51aa04d..32da10c 100644 --- a/include/elna/boot/type_check.h +++ b/include/elna/boot/type_check.h @@ -259,6 +259,7 @@ namespace elna::boot void visit(case_statement *statement) override; void visit(record_constructor_expression *expression) override; void visit(array_constructor_expression *expression) override; + void visit(slicing_expression *expression) override; void visit(unary_expression *expression) override; }; } diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index aa4bde1..1d98675 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -88,6 +88,7 @@ namespace elna::gcc void visit(boot::unit *unit) override; void visit(boot::record_constructor_expression *expression) override; void visit(boot::array_constructor_expression *expression) override; + void visit(boot::slicing_expression *expression) override; void visit(boot::assign_statement *statement) override; void visit(boot::if_statement *statement) override; void visit(boot::import_declaration *) override; diff --git a/source/command_line_interface.elna b/source/command_line_interface.elna index 54eb87f..6aaf440 100644 --- a/source/command_line_interface.elna +++ b/source/command_line_interface.elna @@ -23,7 +23,7 @@ var parsed: Bool begin i := 1; - result := cast(malloc(#size(CommandLine)): ^CommandLine); + result := malloc(#size(CommandLine)); result^.lex := false; result^.parse := false; result^.input := nil; diff --git a/source/main.elna b/source/main.elna index 8f0250b..4a23898 100644 --- a/source/main.elna +++ b/source/main.elna @@ -98,7 +98,7 @@ begin file_handle := fopen(filename, "rb\0".ptr); if file_handle <> nil then - result := cast(malloc(#size(SourceFile)): ^SourceFile); + result := malloc(#size(SourceFile)); result^.handle := file_handle; result^.size := 0u; result^.index := 1u diff --git a/testsuite/compilable/slice_index.elna b/testsuite/compilable/slice_index.elna new file mode 100644 index 0000000..70d26ae --- /dev/null +++ b/testsuite/compilable/slice_index.elna @@ -0,0 +1,11 @@ +proc f() +var + a: []Int + x: Int + p: ^Int +begin + x := a[1]; + a := p[1u to 10u] +return + +end. -- cgit v1.2.3