From 14d4977e2ab2409bb7344395ca01d19e49f130f1 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sat, 11 Jul 2026 22:33:03 +0200 Subject: Implement record extension --- include/elna/boot/ast.h | 6 ++-- include/elna/boot/result.h | 5 +++ include/elna/boot/semantic.h | 79 +++++++++++++++++++++++++++++++++++++++----- include/elna/boot/symbol.h | 7 ++-- 4 files changed, 82 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 1c27166..17a0dc1 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -135,8 +135,6 @@ namespace elna::boot */ class empty_visitor : public parser_visitor { - [[noreturn]] void not_implemented(); - public: [[noreturn]] virtual void visit(array_type_expression *) override; [[noreturn]] virtual void visit(pointer_type_expression *) override; @@ -250,6 +248,8 @@ namespace elna::boot class expression : public virtual node { public: + type type_decoration; + virtual cast_expression *is_cast(); virtual traits_expression *is_traits(); virtual binary_expression *is_binary(); @@ -501,8 +501,6 @@ namespace elna::boot expression *m_value; public: - type expression_type; - cast_expression(const struct position position, type_expression *target, expression *value); void accept(parser_visitor *visitor) override; cast_expression *is_cast() override; diff --git a/include/elna/boot/result.h b/include/elna/boot/result.h index 3a84229..1b04bfb 100644 --- a/include/elna/boot/result.h +++ b/include/elna/boot/result.h @@ -100,6 +100,11 @@ namespace elna::boot { } + bool operator==(const return_declaration& other) const + { + return this->proper_type == other.proper_type && this->no_return == other.no_return; + } + T proper_type{}; bool no_return{ false }; }; diff --git a/include/elna/boot/semantic.h b/include/elna/boot/semantic.h index 9d79b14..e351258 100644 --- a/include/elna/boot/semantic.h +++ b/include/elna/boot/semantic.h @@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see #include #include #include +#include #include #include "elna/boot/ast.h" @@ -29,29 +30,47 @@ along with GCC; see the file COPYING3. If not see namespace elna::boot { /** - * Undeclared identifier. + * Error declaring a symbol. */ - class undeclared_error : public error + class declaration_error : public error { const std::string identifier; public: - undeclared_error(const std::string& identifier, const struct position position); + enum class kind + { + undeclared, + already + }; + + declaration_error(const kind error_kind, + const std::string& identifier, const struct position position); std::string what() const override; + + private: + const kind error_kind; }; /** * A symbol was already declared in this scope. */ - class already_declared_error : public error + class type_expectation_error : public error { - const std::string identifier; - public: - already_declared_error(const std::string& identifier, const struct position position); + enum class kind + { + assignment, + result, + argument + }; + + type_expectation_error(const kind error_kind, const struct position position); std::string what() const override; + + private: + const kind error_kind; }; /** @@ -106,6 +125,22 @@ namespace elna::boot std::string what() const override; }; + /** + * Argument count in a procedure or record call doesn't match + * the expected number of parameters or fields. + */ + class argument_count_error : public error + { + const std::size_t expected; + const std::size_t actual; + + public: + argument_count_error(std::size_t expected, std::size_t actual, + const struct position position); + + std::string what() const override; + }; + /** * Checks types. */ @@ -113,17 +148,25 @@ namespace elna::boot { bool returns; symbol_bag bag; + std::shared_ptr current_procedure; bool check_unresolved_symbol(std::shared_ptr alias, std::vector& path); + std::size_t match_record_fields(const std::shared_ptr& record, + std::vector::const_iterator& argument_it, + const std::vector::const_iterator& argument_end); public: explicit type_analysis_visitor(symbol_bag bag); void visit(procedure_declaration *declaration) override; void visit(return_statement *statement) override; + void visit(assign_statement *statement) override; + void visit(variable_declaration *declaration) override; void visit(type_declaration *declaration) override; void visit(record_type_expression *expression) override; + void visit(procedure_call *call) override; + void visit(case_statement *statement) override; }; /** @@ -138,10 +181,15 @@ namespace elna::boot std::pair> build_procedure( procedure_type_expression& expression); - std::vector build_composite_type(const std::vector& fields); + std::vector build_composite_type(const std::vector& fields, + std::set& known_names); std::shared_ptr register_variable(const std::string& name, const bool is_extern, const struct position position); + type lookup_primitive_type(const std::string& name); + type type_of_constant(const constant_info::variant& value); + type lookup_field(const type& composite_type, const std::string& field_name); + public: name_analysis_visitor(symbol_bag bag); @@ -161,7 +209,12 @@ namespace elna::boot void visit(unit *unit) override; void visit(cast_expression *expression) override; void visit(traits_expression *trait) override; + void visit(binary_expression *expression) override; + void visit(unary_expression *expression) override; void visit(named_expression *expression) override; + void visit(array_access_expression *expression) override; + void visit(field_access_expression *expression) override; + void visit(dereference_expression *expression) override; void visit(literal *literal) override; void visit(literal *literal) override; void visit(literal *literal) override; @@ -185,4 +238,14 @@ namespace elna::boot void visit(unit *unit) override; void visit(type_declaration *declaration) override; }; + + /** + * Whether an expression of type \a assignment can be assigned to a variable + * of type \a assignee. + * + * \param assignee Assignee. + * \param assignment Assignment. + * \return Whether the assignment can be performed. + */ + bool is_assignable_from(const type& assignee, const type& assignment); } diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h index 6258760..85532db 100644 --- a/include/elna/boot/symbol.h +++ b/include/elna/boot/symbol.h @@ -84,13 +84,14 @@ namespace elna::boot type(type&& other); type& operator=(type&& other); - bool operator==(const std::nullptr_t&); - ~type(); template std::shared_ptr get() const; + bool operator==(const std::nullptr_t&) const; + bool operator==(const type& other) const; + bool empty() const; }; @@ -466,6 +467,6 @@ namespace elna::boot * \param alias The type to lookup the innermost declaration for. * \return Innermost type declaration. */ - type inner_aliased_type(type alias); + type inner_aliased_type(const type& alias); type inner_aliased_type(std::shared_ptr alias); } -- cgit v1.2.3