From bb4f474cb2247e0e314beab5d7d72e673ff4e8b6 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Fri, 24 Jul 2026 03:11:32 +0200 Subject: Implement a repeat loop --- include/elna/boot/ast.h | 40 ++++++++++++++++++++++++++++++--------- include/elna/boot/name_analysis.h | 20 +++++++++++++++----- include/elna/boot/symbol.h | 10 ++++++++++ include/elna/boot/type_check.h | 30 ++++++++++++----------------- include/elna/gcc/elna-generic.h | 5 +++++ include/elna/gcc/elna-tree.h | 1 - 6 files changed, 73 insertions(+), 33 deletions(-) (limited to 'include') diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index b50eb75..d6804df 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -75,6 +75,7 @@ namespace elna::boot class if_statement; class import_declaration; class while_statement; + class repeat_statement; class for_statement; class case_statement; class traits_expression; @@ -118,6 +119,7 @@ namespace elna::boot virtual void visit(if_statement *) = 0; virtual void visit(import_declaration *) = 0; virtual void visit(while_statement *) = 0; + virtual void visit(repeat_statement *) = 0; virtual void visit(for_statement *) = 0; virtual void visit(defer_statement *) = 0; virtual void visit(case_statement *) = 0; @@ -146,7 +148,9 @@ namespace elna::boot }; /** - * Abstract visitor that doesn't visit any nodes by default. + * Abstract visitor that asserts on any node visitation. Child visitors + * override only the node types they care about, with the guarantee that + * unimplemented nodes are never silently ignored. */ class empty_visitor : public parser_visitor { @@ -166,6 +170,7 @@ namespace elna::boot [[noreturn]] void visit(if_statement *) override; [[noreturn]] void visit(import_declaration *) override; [[noreturn]] void visit(while_statement *) override; + [[noreturn]] void visit(repeat_statement *) override; [[noreturn]] void visit(for_statement *) override; [[noreturn]] void visit(defer_statement *) override; [[noreturn]] void visit(empty_statement *) override; @@ -213,6 +218,7 @@ namespace elna::boot void visit(if_statement *) override; void visit(import_declaration *) override; void visit(while_statement *statement) override; + void visit(repeat_statement *statement) override; void visit(for_statement *statement) override; void visit(defer_statement *statement) override; void visit(empty_statement *) override; @@ -824,28 +830,44 @@ namespace elna::boot }; /** - * for-statement. + * for-to-statement. + */ + class repeat_statement : public statement + { + expression *m_condition; + + public: + const std::vector body; + + repeat_statement(const source_position position, std::vector&& body, + expression *condition); + ~repeat_statement() override; + + void accept(parser_visitor *visitor) override; + + expression& condition(); + }; + + /** + * for-of-statement. */ class for_statement : public statement { - expression *m_initial_value; - expression *m_final_value; + expression *m_range; public: const identifier control_variable; + identifier *const counter; const std::vector body; - expression *const step; std::shared_ptr symbols; for_statement(const source_position position, identifier&& control_variable, - expression *initial_value, expression *final_value, - std::vector&& body, expression *step = nullptr); + expression *range, std::vector&& body, identifier *const counter); ~for_statement() override; void accept(parser_visitor *visitor) override; - expression& initial_value(); - expression& final_value(); + expression& range(); }; /** diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h index d18b813..68fe6da 100644 --- a/include/elna/boot/name_analysis.h +++ b/include/elna/boot/name_analysis.h @@ -33,15 +33,25 @@ namespace elna::boot * Error declaring or using a symbol (undeclared, redefinition, * local export). */ - class symbol_error : public error + class declaration_error : public error { public: - struct undeclared { std::string name; }; - struct local_export { std::string name; }; - struct redefinition { std::string name; std::optional original; }; + struct undeclared + { + std::string name; + }; + struct local_export + { + std::string name; + }; + struct redefinition + { + std::string name; + std::optional original; + }; using payload_type = std::variant; - symbol_error(const source_position position, payload_type payload); + declaration_error(const source_position position, payload_type payload); std::string what() const override; std::optional> note() const override; diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h index ea418b1..4e97205 100644 --- a/include/elna/boot/symbol.h +++ b/include/elna/boot/symbol.h @@ -73,6 +73,7 @@ namespace elna::boot bool operator==(const std::nullptr_t&) const; bool operator==(const type& other) const; + explicit operator bool() const; bool empty() const; @@ -523,4 +524,13 @@ namespace elna::boot * \return Whether the type is a pointer type. */ bool is_any_pointer_type(const type& checked); + + /** + * If \a range is an array or a slice gives its base type, otherwise + * returns an empty type. + * + * \param range The type to check. + * \return The base type, or an empty type. + */ + type get_range_base_type(const type& range); } diff --git a/include/elna/boot/type_check.h b/include/elna/boot/type_check.h index 5fdc5cb..e500007 100644 --- a/include/elna/boot/type_check.h +++ b/include/elna/boot/type_check.h @@ -88,16 +88,23 @@ namespace elna::boot }; /** - * Base type of a record is not a record. + * Unexpected kind of a type at specific position. */ - class base_type_error : public error + class type_kind_error : public error { - type actual; - public: - base_type_error(type actual, const source_position position); + enum class kind + { + record_base, + for_loop + }; + type_kind_error(const source_position position, kind type_kind, const type& actual); std::string what() const override; + + private: + kind type_kind; + type actual; }; /** @@ -164,19 +171,6 @@ namespace elna::boot std::string what() const override; }; - /** - * FOR loop variable must be \c Int or \c Word. - */ - class for_loop_type_error : public error - { - type actual; - - public: - for_loop_type_error(const source_position position, type actual); - - std::string what() const override; - }; - /** * Chain of responsibility for type compatibility checks. * diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index de95a7e..1ac829f 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -60,6 +60,10 @@ namespace elna::gcc bool expect_trait_type_only(boot::traits_expression *trait); void visit_statements(const std::vector& statements); bool assert_constant(location_t expression_location); + tree declare_local_variable(const boot::identifier& name, + const boot::variable_info& info, tree initial_value); + std::pair build_loop_head(tree control_variable_declaration, tree limit, + tree_code comparison, location_t check_location); public: generic_visitor(std::shared_ptr symbol_table, @@ -89,6 +93,7 @@ namespace elna::gcc void visit(boot::slicing_expression *expression) override; void visit(boot::assign_statement *statement) override; void visit(boot::if_statement *statement) override; + void visit(boot::repeat_statement *statement) override; void visit(boot::for_statement *statement) override; void visit(boot::while_statement *statement) override; void visit(boot::defer_statement *statement) override; diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h index 1d48b00..ac97e41 100644 --- a/include/elna/gcc/elna-tree.h +++ b/include/elna/gcc/elna-tree.h @@ -36,7 +36,6 @@ namespace elna::gcc using symbol_table = boot::symbol_map; bool is_integral_type(tree type); - bool is_numeric_type(tree type); bool is_unique_type(tree type); bool is_void_type(tree type); -- cgit v1.2.3