aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-07-10 17:06:21 +0200
committerEugen Wissner <belka@caraus.de>2026-07-10 17:06:21 +0200
commitb7dd49c1d5832ac7d82edba27316884ab53e614c (patch)
tree24afc27b83974c9322088e5469d2d1894c0eb314 /include
parent36440faa345bf842c348711325312c2b02e4cc23 (diff)
downloadelna-b7dd49c1d5832ac7d82edba27316884ab53e614c.tar.gz
Report if the base type of a record is not a record
Diffstat (limited to 'include')
-rw-r--r--include/elna/boot/ast.h107
-rw-r--r--include/elna/boot/semantic.h62
-rw-r--r--include/elna/boot/symbol.h11
-rw-r--r--include/elna/gcc/elna-generic.h4
4 files changed, 115 insertions, 69 deletions
diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h
index fe502a4..1c27166 100644
--- a/include/elna/boot/ast.h
+++ b/include/elna/boot/ast.h
@@ -111,7 +111,6 @@ namespace elna::boot
virtual void visit(unit *) = 0;
virtual void visit(binary_expression *) = 0;
virtual void visit(unary_expression *) = 0;
- virtual void visit(type_expression *) = 0;
virtual void visit(array_type_expression *) = 0;
virtual void visit(pointer_type_expression *) = 0;
virtual void visit(record_type_expression *) = 0;
@@ -139,7 +138,6 @@ namespace elna::boot
[[noreturn]] void not_implemented();
public:
- [[noreturn]] virtual void visit(type_expression *) override;
[[noreturn]] virtual void visit(array_type_expression *) override;
[[noreturn]] virtual void visit(pointer_type_expression *) override;
[[noreturn]] virtual void visit(type_declaration *) override;
@@ -179,6 +177,50 @@ namespace elna::boot
};
/**
+ * Abstract visitor that visits all nodes recursively.
+ */
+ class walking_visitor : public parser_visitor
+ {
+ public:
+ virtual void visit(array_type_expression *) override;
+ virtual void visit(pointer_type_expression *) override;
+ virtual void visit(type_declaration *) override;
+ virtual void visit(record_type_expression *) override;
+ virtual void visit(union_type_expression *) override;
+ virtual void visit(procedure_type_expression *) override;
+ virtual void visit(enumeration_type_expression *) override;
+
+ virtual void visit(variable_declaration *) override;
+ virtual void visit(constant_declaration *) override;
+ virtual void visit(procedure_declaration *) override;
+ virtual void visit(assign_statement *) override;
+ virtual void visit(if_statement *) override;
+ virtual void visit(import_declaration *) override;
+ virtual void visit(while_statement *statement) override;
+ virtual void visit(return_statement *statement) override;
+ virtual void visit(defer_statement *statement) override;
+ virtual void visit(empty_statement *) override;
+ virtual void visit(case_statement *statement) override;
+ virtual void visit(procedure_call *call) override;
+ virtual void visit(unit *unit) override;
+ virtual void visit(cast_expression *expression) override;
+ virtual void visit(traits_expression *trait) override;
+ virtual void visit(binary_expression *expression) override;
+ virtual void visit(unary_expression *expression) override;
+ virtual void visit(named_expression *) override;
+ virtual void visit(array_access_expression *expression) override;
+ virtual void visit(field_access_expression *expression) override;
+ virtual void visit(dereference_expression *expression) override;
+ virtual void visit(literal<std::int32_t> *) override;
+ virtual void visit(literal<std::uint32_t> *) override;
+ virtual void visit(literal<double> *) override;
+ virtual void visit(literal<bool> *) override;
+ virtual void visit(literal<unsigned char> *) override;
+ virtual void visit(literal<std::nullptr_t> *) override;
+ virtual void visit(literal<std::string> *) override;
+ };
+
+ /**
* AST node.
*/
class node
@@ -242,9 +284,6 @@ namespace elna::boot
virtual union_type_expression *is_union();
virtual procedure_type_expression *is_procedure();
virtual enumeration_type_expression *is_enumeration();
-
- void accept(parser_visitor *visitor) override;
- ~type_expression() = 0;
};
class array_type_expression : public type_expression
@@ -331,7 +370,7 @@ namespace elna::boot
public:
variable_declaration(const struct position position,
std::vector<identifier_definition>&& identifier, std::shared_ptr<type_expression> variable_type,
- expression *body = nullptr);
+ expression *initializer = nullptr);
variable_declaration(const struct position position,
std::vector<identifier_definition>&& identifier, std::shared_ptr<type_expression> variable_type,
std::monostate);
@@ -342,7 +381,7 @@ namespace elna::boot
const std::vector<identifier_definition> identifiers;
type_expression& variable_type();
- expression *const body{ nullptr };
+ expression *const initializer{ nullptr };
const bool is_extern{ false };
};
@@ -360,14 +399,14 @@ namespace elna::boot
*/
class constant_declaration : public declaration
{
- expression *m_body;
+ expression *m_initializer;
public:
constant_declaration(const struct position position, identifier_definition identifier,
- expression *body);
+ expression *initializer);
void accept(parser_visitor *visitor) override;
- expression& body();
+ expression& initializer();
virtual ~constant_declaration() override;
};
@@ -391,27 +430,27 @@ namespace elna::boot
procedure_type_expression *is_procedure() override;
};
- struct block
+ struct procedure_body
{
- block(std::vector<constant_declaration*>&& constants, std::vector<variable_declaration *>&& variables,
- std::vector<statement *>&& body);
- block(std::vector<constant_declaration*>&& constants, std::vector<variable_declaration *>&& variables);
- block(const block&) = delete;
- block(block&& that);
+ procedure_body(std::vector<constant_declaration*>&& constants,
+ std::vector<variable_declaration *>&& variables, std::vector<statement *>&& statements);
+ procedure_body(std::vector<constant_declaration*>&& constants, std::vector<variable_declaration *>&& variables);
+ procedure_body(const procedure_body&) = delete;
+ procedure_body(procedure_body&& that);
- block& operator=(const block&) = delete;
- block& operator=(block&& that);
+ procedure_body& operator=(const procedure_body&) = delete;
+ procedure_body& operator=(procedure_body&& that);
const std::vector<variable_declaration *>& variables();
const std::vector<constant_declaration *>& constants();
- const std::vector<statement *>& body();
+ const std::vector<statement *>& statements();
- virtual ~block();
+ virtual ~procedure_body();
private:
std::vector<variable_declaration *> m_variables;
std::vector<constant_declaration *> m_constants;
- std::vector<statement *> m_body;
+ std::vector<statement *> m_statements;
};
@@ -423,10 +462,10 @@ namespace elna::boot
procedure_type_expression *m_heading;
public:
- std::optional<block> body;
+ std::optional<procedure_body> body;
procedure_declaration(const struct position position, identifier_definition identifier,
- procedure_type_expression *heading, block&& body);
+ procedure_type_expression *heading, procedure_body&& body);
procedure_declaration(const struct position position, identifier_definition identifier,
procedure_type_expression *heading);
void accept(parser_visitor *visitor) override;
@@ -441,16 +480,16 @@ namespace elna::boot
*/
class type_declaration : public declaration
{
- type_expression *m_body;
+ type_expression *m_underlying_type;
public:
type_declaration(const struct position position, identifier_definition identifier,
type_expression *expression);
- ~type_declaration();
+ ~type_declaration() override;
void accept(parser_visitor *visitor) override;
- type_expression& body();
+ type_expression& underlying_type();
};
/**
@@ -660,18 +699,18 @@ namespace elna::boot
*/
class if_statement : public statement
{
- conditional_statements *m_body;
+ conditional_statements *m_branch;
public:
const std::vector<conditional_statements *> branches;
const std::vector<statement *> *alternative;
- if_statement(const struct position position, conditional_statements *body,
+ if_statement(const struct position position, conditional_statements *branch,
std::vector<conditional_statements *>&& branches,
std::vector<statement *> *alternative = nullptr);
void accept(parser_visitor *visitor) override;
- conditional_statements& body();
+ conditional_statements& branch();
virtual ~if_statement() override;
};
@@ -693,16 +732,16 @@ namespace elna::boot
*/
class while_statement : public statement
{
- conditional_statements *m_body;
+ conditional_statements *m_branch;
public:
const std::vector<conditional_statements *> branches;
- while_statement(const struct position position, conditional_statements *body,
+ while_statement(const struct position position, conditional_statements *branch,
std::vector<conditional_statements *>&& branches);
void accept(parser_visitor *visitor) override;
- conditional_statements& body();
+ conditional_statements& branch();
virtual ~while_statement() override;
};
@@ -710,7 +749,7 @@ namespace elna::boot
class unit : public node
{
public:
- std::optional<std::vector<statement *>> body;
+ const std::optional<std::vector<statement *>> entry_point;
std::vector<import_declaration *> imports;
std::vector<constant_declaration *> constants;
@@ -719,7 +758,7 @@ namespace elna::boot
std::vector<procedure_declaration *> procedures;
unit(const struct position position);
- unit(const struct position position, std::vector<statement *>&& body);
+ unit(const struct position position, std::vector<statement *>&& entry_point);
virtual void accept(parser_visitor *visitor) override;
virtual ~unit() override;
diff --git a/include/elna/boot/semantic.h b/include/elna/boot/semantic.h
index c6ad19d..9d79b14 100644
--- a/include/elna/boot/semantic.h
+++ b/include/elna/boot/semantic.h
@@ -28,6 +28,9 @@ along with GCC; see the file COPYING3. If not see
namespace elna::boot
{
+ /**
+ * Undeclared identifier.
+ */
class undeclared_error : public error
{
const std::string identifier;
@@ -38,6 +41,9 @@ namespace elna::boot
std::string what() const override;
};
+ /**
+ * A symbol was already declared in this scope.
+ */
class already_declared_error : public error
{
const std::string identifier;
@@ -48,6 +54,9 @@ namespace elna::boot
std::string what() const override;
};
+ /**
+ * Field with the same name is already declared in this type.
+ */
class field_duplication_error : public error
{
const std::string field_name;
@@ -58,6 +67,9 @@ namespace elna::boot
std::string what() const override;
};
+ /**
+ * Cyclic type declaration.
+ */
class cyclic_declaration_error : public error
{
const std::vector<std::string> cycle;
@@ -68,6 +80,9 @@ namespace elna::boot
std::string what() const override;
};
+ /**
+ * Procedure with a return type does not return.
+ */
class return_error : public error
{
const std::string identifier;
@@ -78,6 +93,9 @@ namespace elna::boot
std::string what() const override;
};
+ /**
+ * Base type of a record is not a record.
+ */
class base_type_error : public error
{
const std::string base;
@@ -91,7 +109,7 @@ namespace elna::boot
/**
* Checks types.
*/
- class type_analysis_visitor final : public empty_visitor, public error_container
+ class type_analysis_visitor final : public walking_visitor, public error_container
{
bool returns;
symbol_bag bag;
@@ -102,23 +120,16 @@ namespace elna::boot
public:
explicit type_analysis_visitor(symbol_bag bag);
- void visit(procedure_declaration *definition) override;
- void visit(assign_statement *) override;
- void visit(if_statement *) override;
- void visit(while_statement *) override;
- void visit(return_statement *) override;
- void visit(defer_statement *) override;
- void visit(empty_statement *) override;
- void visit(case_statement *) override;
- void visit(procedure_call *) override;
- void visit(unit *unit) override;
- void visit(type_declaration *definition) override;
+ void visit(procedure_declaration *declaration) override;
+ void visit(return_statement *statement) override;
+ void visit(type_declaration *declaration) override;
+ void visit(record_type_expression *expression) override;
};
/**
* Performs name analysis.
*/
- class name_analysis_visitor final : public parser_visitor, public error_container
+ class name_analysis_visitor final : public walking_visitor, public error_container
{
type current_type;
constant_info::variant current_literal;
@@ -134,36 +145,23 @@ namespace elna::boot
public:
name_analysis_visitor(symbol_bag bag);
- void visit(type_expression *) override;
void visit(array_type_expression *expression) override;
void visit(pointer_type_expression *expression) override;
- void visit(type_declaration *definition) override;
+ void visit(type_declaration *declaration) override;
void visit(record_type_expression *expression) override;
void visit(union_type_expression *expression) override;
void visit(procedure_type_expression *expression) override;
void visit(enumeration_type_expression *expression) override;
void visit(variable_declaration *declaration) override;
- void visit(constant_declaration *definition) override;
- void visit(procedure_declaration *definition) override;
- void visit(assign_statement *statement) override;
- void visit(if_statement *statement) override;
- void visit(import_declaration *) override;
- void visit(while_statement *statement) override;
- void visit(return_statement *statement) override;
- void visit(defer_statement *) override;
- void visit(empty_statement *statement) override;
- void visit(case_statement *statement) override;
+ void visit(constant_declaration *declaration) override;
+ void visit(procedure_declaration *declaration) override;
+
void visit(procedure_call *call) override;
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,8 +183,6 @@ namespace elna::boot
void visit(import_declaration *) override;
void visit(unit *unit) override;
- void visit(type_declaration *definition) override;
- void visit(variable_declaration *) override;
- void visit(procedure_declaration *definition) override;
+ void visit(type_declaration *declaration) override;
};
}
diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h
index beb44e2..6258760 100644
--- a/include/elna/boot/symbol.h
+++ b/include/elna/boot/symbol.h
@@ -457,4 +457,15 @@ namespace elna::boot
*/
void add_import(const symbol_bag& bag);
};
+
+ /**
+ * If a type is a declared name for another type, look up recursively
+ * the declared type. If the given type is not an alias, then this function
+ * returns its argument.
+ *
+ * \param alias The type to lookup the innermost declaration for.
+ * \return Innermost type declaration.
+ */
+ type inner_aliased_type(type alias);
+ type inner_aliased_type(std::shared_ptr<alias_type> alias);
}
diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h
index 7ee251b..28bfe2d 100644
--- a/include/elna/gcc/elna-generic.h
+++ b/include/elna/gcc/elna-generic.h
@@ -65,7 +65,7 @@ namespace elna::gcc
public:
generic_visitor(std::shared_ptr<symbol_table> symbol_table, elna::boot::symbol_bag bag);
- void visit(boot::procedure_declaration *definition) override;
+ void visit(boot::procedure_declaration *declaration) override;
void visit(boot::procedure_call *call) override;
void visit(boot::cast_expression *expression) override;
void visit(boot::traits_expression *trait) override;
@@ -78,7 +78,7 @@ namespace elna::gcc
void visit(boot::literal<std::string> *string) override;
void visit(boot::binary_expression *expression) override;
void visit(boot::unary_expression *expression) override;
- void visit(boot::constant_declaration *definition) override;
+ void visit(boot::constant_declaration *declaration) override;
void visit(boot::variable_declaration *declaration) override;
void visit(boot::named_expression *expression) override;
void visit(boot::array_access_expression *expression) override;