aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boot/ast.cc96
-rw-r--r--boot/evaluator.cc12
-rw-r--r--boot/lexer.ll3
-rw-r--r--boot/name_analysis.cc40
-rw-r--r--boot/parser.yy7
-rw-r--r--boot/symbol.cc21
-rw-r--r--boot/type_check.cc5
-rw-r--r--gcc/gcc/elna-builtins.cc13
-rw-r--r--gcc/gcc/elna-generic.cc141
-rw-r--r--gcc/gcc/elna1.cc2
-rw-r--r--include/elna/boot/ast.h47
-rw-r--r--include/elna/boot/evaluator.h2
-rw-r--r--include/elna/boot/name_analysis.h2
-rw-r--r--include/elna/boot/symbol.h10
-rw-r--r--include/elna/boot/type_check.h1
-rw-r--r--include/elna/gcc/elna-generic.h1
-rw-r--r--source/command_line_interface.elna2
-rw-r--r--source/main.elna2
-rw-r--r--testsuite/compilable/slice_index.elna11
19 files changed, 404 insertions, 14 deletions
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<enumeration_type>() != 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<slice_type>() != nullptr)
+ {
+ return target.pointer_size + target.word_size;
+ }
else if (is_primitive_type(resolved, "Pointer")
|| resolved.get<pointer_type>() != 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<slice_type>())
+ {
+ if (field_name == "length")
+ {
+ return lookup_primitive_type("Word");
+ }
+ else if (field_name == "ptr")
+ {
+ return type(std::make_shared<pointer_type>(slice->base));
+ }
+ }
else if (auto primitive = resolved_type.get<primitive_type>(); primitive != nullptr && primitive->identifier == "String")
{
if (field_name == "length")
@@ -209,6 +220,12 @@ namespace elna::boot
this->current_type = type(std::make_shared<array_type>(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<slice_type>(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<array_type>(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<pointer_type>())
+ {
+ expression->type_decoration = type(std::make_shared<slice_type>(pointer->base));
+ }
+ else if (auto array = resolved_base.get<array_type>())
+ {
+ expression->type_decoration = type(std::make_shared<slice_type>(array->base));
+ }
+ else if (auto slice = resolved_base.get<slice_type>())
+ {
+ expression->type_decoration = type(slice);
+ }
+ }
+
void name_analysis_visitor::visit(procedure_type_expression *expression)
{
std::shared_ptr<procedure_type> 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<slice_type>())
+ {
+ 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_type> slice)
+ : payload(slice)
+ {
+ }
+
type::type(std::shared_ptr<procedure_type> procedure)
: payload(procedure)
{
@@ -86,6 +91,7 @@ namespace elna::boot
template std::shared_ptr<record_type> type::get<record_type>() const;
template std::shared_ptr<pointer_type> type::get<pointer_type>() const;
template std::shared_ptr<array_type> type::get<array_type>() const;
+ template std::shared_ptr<slice_type> type::get<slice_type>() const;
template std::shared_ptr<constant_type> type::get<constant_type>() const;
template std::shared_ptr<procedure_type> type::get<procedure_type>() const;
template std::shared_ptr<enumeration_type> type::get<enumeration_type>() 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<slice_type>())
+ {
+ auto right_slice = resolved_that.get<slice_type>();
+
+ return right_slice != nullptr && left_slice->base == right_slice->base;
+ }
if (auto left_procedure = resolved_this.get<procedure_type>())
{
auto right_procedure = resolved_that.get<procedure_type>();
@@ -176,6 +188,10 @@ namespace elna::boot
{
return "[" + std::to_string(payload->size) + "]" + payload->base.to_string();
}
+ else if constexpr (std::is_same_v<T, std::shared_ptr<slice_type>>)
+ {
+ return "[]" + payload->base.to_string();
+ }
else if constexpr (std::is_same_v<T, std::shared_ptr<record_type>>)
{
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<boot::slice_type>())
+ {
+ 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<boot::procedure_type>())
{
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<constructor_elt, va_gc> *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<boot::slice_type>() != 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<boot::slice_type>() != 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,6 +625,7 @@ 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;
@@ -608,6 +633,28 @@ namespace elna::boot
};
/**
+ * 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.
*/
class named_expression : public designator_expression, public type_expression
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<pointer_type>,
std::shared_ptr<constant_type>,
std::shared_ptr<array_type>,
+ std::shared_ptr<slice_type>,
std::shared_ptr<procedure_type>,
std::shared_ptr<enumeration_type>
> payload;
@@ -62,6 +64,7 @@ namespace elna::boot
explicit type(std::shared_ptr<pointer_type> pointer);
explicit type(std::shared_ptr<constant_type> constant);
explicit type(std::shared_ptr<array_type> array);
+ explicit type(std::shared_ptr<slice_type> slice);
explicit type(std::shared_ptr<procedure_type> procedure);
explicit type(std::shared_ptr<enumeration_type> 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.