diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/elna/boot/ast.h | 32 | ||||
| -rw-r--r-- | include/elna/boot/name_analysis.h | 98 | ||||
| -rw-r--r-- | include/elna/boot/type_check.h | 14 | ||||
| -rw-r--r-- | include/elna/gcc/elna-generic.h | 2 | ||||
| -rw-r--r-- | include/elna/gcc/elna-tree.h | 1 | ||||
| -rw-r--r-- | include/elna/gcc/elna1.h | 7 |
6 files changed, 80 insertions, 74 deletions
diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 6080155..b50eb75 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 for_statement; class case_statement; class traits_expression; class unit; @@ -117,6 +118,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(for_statement *) = 0; virtual void visit(defer_statement *) = 0; virtual void visit(case_statement *) = 0; virtual void visit(empty_statement *) = 0; @@ -164,6 +166,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(for_statement *) override; [[noreturn]] void visit(defer_statement *) override; [[noreturn]] void visit(empty_statement *) override; [[noreturn]] void visit(case_statement *) override; @@ -210,6 +213,7 @@ namespace elna::boot void visit(if_statement *) override; void visit(import_declaration *) override; void visit(while_statement *statement) override; + void visit(for_statement *statement) override; void visit(defer_statement *statement) override; void visit(empty_statement *) override; void visit(case_statement *statement) override; @@ -819,6 +823,34 @@ namespace elna::boot ~while_statement() override; }; + /** + * for-statement. + */ + class for_statement : public statement + { + expression *m_initial_value; + expression *m_final_value; + + public: + const identifier control_variable; + const std::vector<statement *> body; + expression *const step; + std::shared_ptr<symbol_table> symbols; + + for_statement(const source_position position, identifier&& control_variable, + expression *initial_value, expression *final_value, + std::vector<statement *>&& body, expression *step = nullptr); + ~for_statement() override; + + void accept(parser_visitor *visitor) override; + + expression& initial_value(); + expression& final_value(); + }; + + /** + * Stores module-level definitions. + */ class unit : public node, public procedure_body { public: diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h index 5afe102..d18b813 100644 --- a/include/elna/boot/name_analysis.h +++ b/include/elna/boot/name_analysis.h @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #include <memory> #include <map> #include <optional> +#include <variant> #include "elna/boot/ast.h" #include "elna/boot/result.h" @@ -29,102 +30,60 @@ along with GCC; see the file COPYING3. If not see namespace elna::boot { /** - * Error declaring a symbol. + * Error declaring or using a symbol (undeclared, redefinition, + * local export). */ - class declaration_error : public error + class symbol_error : public error { public: - enum class kind - { - undeclared, - local_export - }; + struct undeclared { std::string name; }; + struct local_export { std::string name; }; + struct redefinition { std::string name; std::optional<source_position> original; }; + using payload_type = std::variant<undeclared, local_export, redefinition>; - declaration_error(const kind error_kind, - const boot::identifier& identifier); + symbol_error(const source_position position, payload_type payload); std::string what() const override; + std::optional<std::pair<std::string, source_position>> note() const override; private: - std::string identifier; - kind error_kind; + payload_type payload; }; /** - * Attempted to redefine a name that is already in use in the - * current scope. + * \c const qualifier used incorrectly — wrong position or + * duplicate. */ - class redefinition_error : public error + class const_qualifier_error : public error { - std::string identifier; - std::optional<source_position> original; - public: - redefinition_error(const boot::identifier& identifier, - std::optional<source_position> original); - - std::string what() const override; + enum class kind { array_position, duplicate }; - std::optional<std::pair<std::string, source_position>> note() const override; - }; - - /** - * Array size before \c const is not valid — only \c const [n]T is - * accepted, not \c [n]const T. - */ - class const_array_error : public error - { - public: - explicit const_array_error(const source_position position); + const_qualifier_error(const source_position position, kind error_kind); std::string what() const override; - }; - - /** - * Direct \c const \c const T is not valid — write it once. - * Merging through an alias is fine (C++ rule). - */ - class double_const_error : public error - { - public: - explicit double_const_error(const source_position position); - std::string what() const override; + private: + kind error_kind; }; /** - * Access to a field that does not exist in the given type. + * Error accessing or defining a member of a record or enumeration. */ - class field_not_found_error : public error + class member_error : public error { - std::string field_name; - type composite_type; - public: - field_not_found_error(const identifier& field_name, - type composite_type); + struct not_found { std::string name; type composite; }; + struct duplicate { std::string name; type aggregate; std::optional<source_position> original; std::optional<std::string> base; }; + using payload_type = std::variant<not_found, duplicate>; - std::string what() const override; - }; - - /** - * Field with the same name is already declared in this type. - */ - class duplicate_member_error : public error - { - std::string member_name; - type aggregate; - std::optional<source_position> original; - std::optional<std::string> base_name; - - public: - duplicate_member_error(const boot::identifier& member_name, - type aggregate, std::optional<source_position> original = std::nullopt, - std::optional<std::string> base_name = std::nullopt); + member_error(const source_position position, payload_type payload); std::string what() const override; - std::optional<std::pair<std::string, source_position>> note() const override; + + private: + payload_type payload; }; /** @@ -200,6 +159,9 @@ namespace elna::boot void visit(array_access_expression *expression) override; void visit(field_access_expression *expression) override; void visit(dereference_expression *expression) override; + + void visit(for_statement *statement) override; + void visit(literal<std::int32_t> *literal) override; void visit(literal<std::uint32_t> *literal) override; void visit(literal<double> *literal) override; diff --git a/include/elna/boot/type_check.h b/include/elna/boot/type_check.h index 1680077..5fdc5cb 100644 --- a/include/elna/boot/type_check.h +++ b/include/elna/boot/type_check.h @@ -165,6 +165,19 @@ namespace elna::boot }; /** + * 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. * * Populate \c ctx with pre-resolved types, then call \c run(). @@ -231,6 +244,7 @@ namespace elna::boot void visit(record_type_expression *expression) override; void visit(procedure_call *call) override; void visit(case_statement *statement) override; + void visit(for_statement *statement) override; void visit(record_constructor_expression *expression) override; void visit(array_constructor_expression *expression) override; void visit(slicing_expression *expression) override; diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index 04b91fb..de95a7e 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -89,7 +89,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::import_declaration *) override; + void visit(boot::for_statement *statement) override; void visit(boot::while_statement *statement) override; void visit(boot::defer_statement *statement) override; void visit(boot::empty_statement *) override; diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h index d826f25..1d48b00 100644 --- a/include/elna/gcc/elna-tree.h +++ b/include/elna/gcc/elna-tree.h @@ -66,7 +66,6 @@ namespace elna::gcc tree find_field_by_name(location_t expression_location, tree type, const std::string& field_name); tree build_static_array_type(tree type, const std::uint64_t size); tree build_enumeration_type(const std::vector<std::string>& members); - tree build_label_decl(const char *name, location_t loc); tree extract_constant(tree expression); diff --git a/include/elna/gcc/elna1.h b/include/elna/gcc/elna1.h index b05cdf2..34cf091 100644 --- a/include/elna/gcc/elna1.h +++ b/include/elna/gcc/elna1.h @@ -73,16 +73,15 @@ struct GTY ((chain_next ("%h.level_chain"))) binding_level // Defer statement coupled with statements following it. vec<defer_scope, va_gc> *defers; + + // Variables local to a block. + tree names; }; struct GTY (()) language_function { - // Local variables and constants. - tree names; - // Lexical scope. struct binding_level *binding_level; }; #define f_binding_level DECL_STRUCT_FUNCTION(current_function_decl)->language->binding_level -#define f_names DECL_STRUCT_FUNCTION(current_function_decl)->language->names |
