diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-07-29 01:16:18 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-07-29 01:16:18 +0200 |
| commit | f8daedce5c73e02dfb2fc59d75777190185584df (patch) | |
| tree | 9ec211b96c3d7efd2fca0da37baeaa8b341e31fb /include | |
| parent | 36a274c9a8bca944234589220def025d3920b3ef (diff) | |
| download | elna-f8daedce5c73e02dfb2fc59d75777190185584df.tar.gz | |
Validate cast compatibility during semantic analysis
Diffstat (limited to 'include')
| -rw-r--r-- | include/elna/boot/ast.h | 2 | ||||
| -rw-r--r-- | include/elna/boot/name_analysis.h | 43 | ||||
| -rw-r--r-- | include/elna/boot/symbol.h | 11 | ||||
| -rw-r--r-- | include/elna/boot/type_check.h | 139 | ||||
| -rw-r--r-- | include/elna/gcc/elna-diagnostic.h | 1 | ||||
| -rw-r--r-- | include/elna/gcc/elna-tree.h | 1 |
6 files changed, 68 insertions, 129 deletions
diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 9697d1c..cc5878b 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -972,6 +972,4 @@ namespace elna::boot ~unary_expression() override; }; - - const char *print_binary_operator(const binary_operator operation); } diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h index 8f53260..626e9f2 100644 --- a/include/elna/boot/name_analysis.h +++ b/include/elna/boot/name_analysis.h @@ -35,27 +35,20 @@ namespace elna::boot class declaration_error : public error { public: - struct undeclared - { - std::string name; - }; - struct local_export - { - std::string name; - }; + enum class kind { undeclared_type, undeclared_trait, undeclared_symbol, local_export }; struct redefinition { - std::string name; std::optional<source_position> original; }; - using payload_type = std::variant<undeclared, local_export, redefinition>; + using payload_type = std::variant<redefinition, kind>; - declaration_error(const source_position position, payload_type payload); + declaration_error(const source_position position, const std::string& name, payload_type payload); std::string what() const override; std::optional<std::pair<std::string, source_position>> note() const override; private: + std::string name; payload_type payload; }; @@ -84,46 +77,31 @@ namespace elna::boot public: 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>; - member_error(const source_position position, payload_type payload); + member_error(const source_position position, const std::string& name, + const type& composite, payload_type payload); std::string what() const override; std::optional<std::pair<std::string, source_position>> note() const override; private: + std::string name; + type composite; payload_type payload; }; /** - * Trait is not applicable to the given type. - */ - class unsupported_trait_type_error : public error - { - type actual; - std::string trait_name; - - public: - unsupported_trait_type_error(const identifier& trait, type actual); - - std::string what() const override; - }; - - /** * Origin of a field in a composite type. */ struct field_origin { - std::optional<source_position> declaration; + std::optional<source_position> position; type base_type; }; @@ -139,8 +117,7 @@ namespace elna::boot std::pair<procedure_type, std::vector<std::string>> build_procedure( procedure_type_expression& expression); ordered_map<type> build_composite_type(const std::vector<field_declaration>& fields, - ordered_map<field_origin>& field_names, - const type& aggregate); + ordered_map<field_origin>& field_names, const type& aggregate); std::shared_ptr<variable_info> register_variable(const std::string& name, const bool is_extern, const source_position position); diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h index dd3e8ff..01eedb1 100644 --- a/include/elna/boot/symbol.h +++ b/include/elna/boot/symbol.h @@ -577,6 +577,17 @@ namespace elna::boot bool is_any_pointer_type(const type& checked); /** + * Checks whether the given type is a scalar type. + * + * Scalar types are discrete types, floating point numbers, enumerations, + * any pointers. + * + * \param checked The type to check. + * \return Whether the type is a scalar type. + */ + bool is_scalar_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/boot/type_check.h b/include/elna/boot/type_check.h index bd32c08..628af06 100644 --- a/include/elna/boot/type_check.h +++ b/include/elna/boot/type_check.h @@ -32,33 +32,50 @@ namespace elna::boot */ class type_mismatch_error : public error { - type expected; - type actual; - public: + struct expected_type + { + type value; + }; + struct return_type + { + std::string identifier; + }; + struct unary + { + unary_operator operation; + }; + struct binary + { + type right; + binary_operator operation; + }; + struct invalid_cast + { + type target; + }; + enum class kind { + record_base, + for_range, + condition, + constant_assignment, + array_index, + non_indexable, + dereference_of_non_pointer + }; + using payload_type = std::variant<expected_type, return_type, unary, binary, invalid_cast, kind>; + type_mismatch_error(const source_position position, - type expected, type actual); + type actual, payload_type payload); std::string what() const override; - }; - - /** - * Attempted to assign a value whose type contains constant members. - */ - class constant_assignment_error : public error - { - type assignee; - public: - constant_assignment_error(const source_position position, type assignee); - - std::string what() const override; + private: + type actual; + payload_type payload; }; /** - * Attempted to access a field that does not exist on the given type. - */ - /** * Cyclic type declaration. */ class cyclic_declaration_error : public error @@ -72,42 +89,6 @@ namespace elna::boot }; /** - * Procedure with a return type does not return. - */ - class return_error : public error - { - std::string identifier; - type return_type; - - public: - return_error(const std::string& identifier, const source_position position, - type return_type = type()); - - std::string what() const override; - }; - - /** - * Unexpected kind of a type at specific position. - */ - class type_kind_error : public error - { - public: - enum class kind - { - record_base, - for_loop, - condition - }; - type_kind_error(const source_position position, kind type_kind, const type& actual); - - std::string what() const override; - - private: - kind type_kind; - type actual; - }; - - /** * Argument count in a procedure call or array constructor doesn't match * the expected number of parameters or elements. */ @@ -124,21 +105,23 @@ namespace elna::boot }; /** - * A trait invocation has invalid arguments. + * A trait invocation is invalid. */ class trait_error : public error { public: - /// Wrong number of arguments passed to a trait. struct argument_count { std::size_t expected; std::size_t actual; }; - /// \c \#offset second argument is not a field name. struct offset_not_field_name {}; + struct unsupported_type + { + type actual; + }; - using payload_type = std::variant<argument_count, offset_not_field_name>; + using payload_type = std::variant<argument_count, offset_not_field_name, unsupported_type>; trait_error(const source_position position, const std::string& trait_name, payload_type payload); @@ -147,40 +130,7 @@ namespace elna::boot private: std::string trait_name; - payload_type m_payload; - }; - - /** - * A unary operator is applied to an unsupported type. - */ - class unary_operation_error : public error - { - type actual; - unary_operator op; - - static char unary_operator_symbol(unary_operator operation); - - public: - unary_operation_error(const source_position position, type actual, - unary_operator operation); - - std::string what() const override; - }; - - /** - * A binary operator is applied to unsupported types. - */ - class binary_operation_error : public error - { - type left; - type right; - binary_operator op; - - public: - binary_operation_error(const source_position position, - type left, type right, binary_operator operation); - - std::string what() const override; + payload_type payload; }; /** @@ -258,6 +208,9 @@ namespace elna::boot void visit(array_constructor_expression *expression) override; void visit(traits_expression *trait) override; void visit(slicing_expression *expression) override; + void visit(array_access_expression *expression) override; + void visit(dereference_expression *expression) override; + void visit(cast_expression *expression) override; void visit(unary_expression *expression) override; void visit(binary_expression *expression) override; }; diff --git a/include/elna/gcc/elna-diagnostic.h b/include/elna/gcc/elna-diagnostic.h index 2cb30f5..3e0dd51 100644 --- a/include/elna/gcc/elna-diagnostic.h +++ b/include/elna/gcc/elna-diagnostic.h @@ -43,6 +43,5 @@ namespace elna::gcc location_t get_location(const boot::source_position *position); location_t make_range(const boot::source_position& position); - std::string print_type(tree type); void report_errors(const std::deque<std::unique_ptr<boot::error>>& errors); } diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h index 71cc13b..41f5cc3 100644 --- a/include/elna/gcc/elna-tree.h +++ b/include/elna/gcc/elna-tree.h @@ -63,6 +63,7 @@ namespace elna::gcc tree build_field(location_t location, tree record_type, const std::string& name, tree type); 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_slice(tree slice_type, tree ptr, tree length); tree build_enumeration_type(const std::vector<std::string>& members); const elna::boot::target_info& get_host_target(); |
