aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-07-11 22:33:03 +0200
committerEugen Wissner <belka@caraus.de>2026-07-11 22:33:03 +0200
commit14d4977e2ab2409bb7344395ca01d19e49f130f1 (patch)
tree5e08f1356a970b53f16ee554642eb555550d1491 /include
parentb7dd49c1d5832ac7d82edba27316884ab53e614c (diff)
downloadelna-14d4977e2ab2409bb7344395ca01d19e49f130f1.tar.gz
Implement record extension
Diffstat (limited to 'include')
-rw-r--r--include/elna/boot/ast.h6
-rw-r--r--include/elna/boot/result.h5
-rw-r--r--include/elna/boot/semantic.h79
-rw-r--r--include/elna/boot/symbol.h7
4 files changed, 82 insertions, 15 deletions
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 <string>
#include <unordered_map>
#include <memory>
+#include <set>
#include <deque>
#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;
};
/**
@@ -107,23 +126,47 @@ namespace elna::boot
};
/**
+ * 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.
*/
class type_analysis_visitor final : public walking_visitor, public error_container
{
bool returns;
symbol_bag bag;
+ std::shared_ptr<procedure_info> current_procedure;
bool check_unresolved_symbol(std::shared_ptr<alias_type> alias,
std::vector<std::string>& path);
+ std::size_t match_record_fields(const std::shared_ptr<record_type>& record,
+ std::vector<expression *>::const_iterator& argument_it,
+ const std::vector<expression *>::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<procedure_type, std::vector<std::string>> build_procedure(
procedure_type_expression& expression);
- std::vector<type_field> build_composite_type(const std::vector<field_declaration>& fields);
+ std::vector<type_field> build_composite_type(const std::vector<field_declaration>& fields,
+ std::set<std::string>& known_names);
std::shared_ptr<variable_info> 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<std::int32_t> *literal) override;
void visit(literal<std::uint32_t> *literal) override;
void visit(literal<double> *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<typename T>
std::shared_ptr<T> 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_type> alias);
}