aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/elna/boot/ast.h47
-rw-r--r--include/elna/boot/semantic.h42
-rw-r--r--include/elna/boot/symbol.h72
-rw-r--r--include/elna/gcc/elna-generic.h1
4 files changed, 99 insertions, 63 deletions
diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h
index b6aad70..42e7666 100644
--- a/include/elna/boot/ast.h
+++ b/include/elna/boot/ast.h
@@ -55,7 +55,6 @@ namespace elna::boot
};
class variable_declaration;
- class constant_declaration;
class procedure_declaration;
class type_declaration;
class procedure_call;
@@ -74,6 +73,7 @@ namespace elna::boot
class type_expression;
class array_type_expression;
class pointer_type_expression;
+ class constant_type_expression;
class record_type_expression;
class procedure_type_expression;
class enumeration_type_expression;
@@ -94,7 +94,6 @@ namespace elna::boot
struct parser_visitor
{
virtual void visit(variable_declaration *) = 0;
- virtual void visit(constant_declaration *) = 0;
virtual void visit(procedure_declaration *) = 0;
virtual void visit(type_declaration *) = 0;
virtual void visit(procedure_call *) = 0;
@@ -114,6 +113,7 @@ namespace elna::boot
virtual void visit(unary_expression *) = 0;
virtual void visit(array_type_expression *) = 0;
virtual void visit(pointer_type_expression *) = 0;
+ virtual void visit(constant_type_expression *) = 0;
virtual void visit(record_type_expression *) = 0;
virtual void visit(procedure_type_expression *) = 0;
virtual void visit(enumeration_type_expression *) = 0;
@@ -138,13 +138,13 @@ namespace elna::boot
public:
[[noreturn]] virtual void visit(array_type_expression *) override;
[[noreturn]] virtual void visit(pointer_type_expression *) override;
+ [[noreturn]] virtual void visit(constant_type_expression *) override;
[[noreturn]] virtual void visit(type_declaration *) override;
[[noreturn]] virtual void visit(record_type_expression *) override;
[[noreturn]] virtual void visit(procedure_type_expression *) override;
[[noreturn]] virtual void visit(enumeration_type_expression *) override;
[[noreturn]] virtual void visit(variable_declaration *) override;
- [[noreturn]] virtual void visit(constant_declaration *) override;
[[noreturn]] virtual void visit(procedure_declaration *) override;
[[noreturn]] virtual void visit(assign_statement *) override;
[[noreturn]] virtual void visit(if_statement *) override;
@@ -182,13 +182,13 @@ namespace elna::boot
public:
virtual void visit(array_type_expression *) override;
virtual void visit(pointer_type_expression *) override;
+ virtual void visit(constant_type_expression *) override;
virtual void visit(type_declaration *) override;
virtual void visit(record_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;
@@ -280,6 +280,7 @@ namespace elna::boot
virtual named_expression *is_named();
virtual array_type_expression *is_array();
virtual pointer_type_expression *is_pointer();
+ virtual constant_type_expression *is_constant();
virtual record_type_expression *is_record();
virtual procedure_type_expression *is_procedure();
virtual enumeration_type_expression *is_enumeration();
@@ -316,6 +317,20 @@ namespace elna::boot
type_expression& base();
};
+ class constant_type_expression : public type_expression
+ {
+ type_expression *m_base;
+
+ public:
+ constant_type_expression(const source_position position, type_expression *base);
+ ~constant_type_expression() override;
+
+ void accept(parser_visitor *visitor) override;
+ constant_type_expression *is_constant() override;
+
+ type_expression& base();
+ };
+
using field_declaration = std::pair<std::vector<identifier>, std::shared_ptr<type_expression>>;
class record_type_expression : public type_expression
@@ -430,23 +445,6 @@ namespace elna::boot
};
/**
- * Constant definition.
- */
- class constant_declaration : public declaration
- {
- expression *m_initializer;
-
- public:
- constant_declaration(const source_position position, identifier_definition identifier,
- expression *initializer);
- void accept(parser_visitor *visitor) override;
-
- expression& initializer();
-
- virtual ~constant_declaration() override;
- };
-
- /**
* Procedure type.
*/
class procedure_type_expression : public type_expression
@@ -467,15 +465,13 @@ namespace elna::boot
struct procedure_body
{
- const std::vector<constant_declaration *> constants;
const std::vector<variable_declaration *> variables;
const std::vector<statement *> entry_point;
expression *const return_expression{ nullptr };
- procedure_body(std::vector<constant_declaration *>&& constants,
- std::vector<variable_declaration *>&& variables,
+ procedure_body(std::vector<variable_declaration *>&& variables,
std::vector<statement *>&& entry_point,
- expression *return_expr = nullptr);
+ expression *return_expression = nullptr);
procedure_body(const procedure_body&) = delete;
procedure_body(procedure_body&& that);
@@ -773,7 +769,6 @@ namespace elna::boot
unit(const source_position position);
unit(const source_position position,
std::vector<import_declaration *>&& imports,
- std::vector<constant_declaration *>&& constants,
std::vector<type_declaration *>&& types,
std::vector<variable_declaration *>&& variables,
std::vector<procedure_declaration *>&& procedures,
diff --git a/include/elna/boot/semantic.h b/include/elna/boot/semantic.h
index 0f8f6c7..3d2de10 100644
--- a/include/elna/boot/semantic.h
+++ b/include/elna/boot/semantic.h
@@ -85,6 +85,19 @@ namespace elna::boot
};
/**
+ * 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;
+ };
+
+ /**
* Attempted to access a field that does not exist on the given type.
*/
class field_not_found_error : public error
@@ -199,8 +212,20 @@ namespace elna::boot
symbol_bag bag;
std::shared_ptr<procedure_info> current_procedure;
- bool check_unresolved_symbol(std::shared_ptr<alias_type> alias,
+ /*
+ * Whether an expression of type assignment can be assigned to a variable
+ * of type assignee.
+ */
+ static bool is_assignable_from(const type& assignee, const type& assignment);
+ /*
+ * Checks whether derived has base in its parent chain.
+ * base should not be null, derived can be null.
+ */
+ static bool is_base_of(const std::shared_ptr<record_type>& base,
+ const std::shared_ptr<record_type>& derived);
+ static bool check_unresolved_symbol(std::shared_ptr<alias_type> alias,
std::vector<std::string>& path);
+
public:
explicit type_analysis_visitor(symbol_bag bag);
@@ -231,7 +256,6 @@ namespace elna::boot
class name_analysis_visitor final : public walking_visitor, public error_container
{
type current_type;
- constant_info::variant current_literal;
symbol_bag bag;
@@ -244,7 +268,6 @@ namespace elna::boot
const bool is_extern, const source_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:
@@ -252,6 +275,7 @@ namespace elna::boot
void visit(array_type_expression *expression) override;
void visit(pointer_type_expression *expression) override;
+ void visit(constant_type_expression *expression) override;
void visit(type_declaration *declaration) override;
void visit(record_type_expression *expression) override;
void visit(record_constructor_expression *expression) override;
@@ -260,7 +284,6 @@ namespace elna::boot
void visit(enumeration_type_expression *expression) override;
void visit(variable_declaration *declaration) override;
- void visit(constant_declaration *declaration) override;
void visit(procedure_declaration *declaration) override;
void visit(procedure_call *call) override;
@@ -297,16 +320,5 @@ namespace elna::boot
void visit(type_declaration *declaration) override;
void visit(procedure_declaration *declaration) override;
void visit(variable_declaration *declaration) override;
- void visit(constant_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 ec5a051..6884dd7 100644
--- a/include/elna/boot/symbol.h
+++ b/include/elna/boot/symbol.h
@@ -32,6 +32,7 @@ namespace elna::boot
class primitive_type;
class record_type;
class pointer_type;
+ class constant_type;
class array_type;
class procedure_type;
class enumeration_type;
@@ -45,6 +46,7 @@ namespace elna::boot
primitive,
record,
pointer,
+ constant,
array,
procedure,
enumeration
@@ -56,6 +58,7 @@ namespace elna::boot
std::shared_ptr<primitive_type> primitive;
std::shared_ptr<record_type> record;
std::shared_ptr<pointer_type> pointer;
+ std::shared_ptr<constant_type> constant;
std::shared_ptr<array_type> array;
std::shared_ptr<procedure_type> procedure;
std::shared_ptr<enumeration_type> enumeration;
@@ -70,6 +73,7 @@ namespace elna::boot
explicit type(std::shared_ptr<primitive_type> primitive);
explicit type(std::shared_ptr<record_type> record);
explicit type(std::shared_ptr<pointer_type> pointer);
+ explicit type(std::shared_ptr<constant_type> constant);
explicit type(std::shared_ptr<array_type> array);
explicit type(std::shared_ptr<procedure_type> procedure);
explicit type(std::shared_ptr<enumeration_type> enumeration);
@@ -112,6 +116,13 @@ namespace elna::boot
explicit pointer_type(type base);
};
+ struct constant_type
+ {
+ const type unqualified;
+
+ explicit constant_type(type unqualified);
+ };
+
struct array_type
{
const type base;
@@ -156,7 +167,6 @@ namespace elna::boot
class type_info;
class procedure_info;
- class constant_info;
class variable_info;
class info : public std::enable_shared_from_this<info>
@@ -169,7 +179,6 @@ namespace elna::boot
virtual std::shared_ptr<type_info> is_type();
virtual std::shared_ptr<procedure_info> is_procedure();
- virtual std::shared_ptr<constant_info> is_constant();
virtual std::shared_ptr<variable_info> is_variable();
};
@@ -332,18 +341,6 @@ namespace elna::boot
bool is_extern() const;
};
- class constant_info : public info
- {
- public:
- using variant = typename
- std::variant<std::int32_t, std::uint32_t, double, bool, unsigned char, std::nullptr_t, std::string>;
-
- const variant symbol;
-
- explicit constant_info(const variant& symbol);
- std::shared_ptr<constant_info> is_constant() override;
- };
-
/**
* Variable symbol information.
*/
@@ -467,13 +464,46 @@ namespace elna::boot
};
/**
- * 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.
+ * Resolves alias chains and type qualifiers until the underlying type is
+ * reached. If the given type is neither an alias nor qualified, it is
+ * returned as is.
+ *
+ * \param alias The type to resolve.
+ * \return The underlying, unqualified type.
+ */
+ type resolve_underlying_type(const type& alias);
+
+ /**
+ * \overload
+ */
+ type resolve_underlying_type(std::shared_ptr<alias_type> alias);
+
+ /**
+ * Resolves an alias chain until the underlying type or a qualified type is
+ * reached.
+ *
+ * \param checked The type to resolve.
+ * \return The first non-alias type in the chain.
+ */
+ type resolve_aliases(const type& checked);
+
+ /**
+ * Checks whether the given type is the built-in type \a name.
+ *
+ * \param checked The type to check.
+ * \param name The name of the primitive type to compare against.
+ * \return Whether the type is the primitive type with the given name.
+ */
+ bool is_primitive_type(const type& checked, const std::string& name);
+
+ /**
+ * Checks whether the given type is a pointer type.
+ *
+ * A pointer type is considered to be a variable pointer, a procedure
+ * pointer, or a built-in Pointer.
*
- * \param alias The type to lookup the innermost declaration for.
- * \return Innermost type declaration.
+ * \param checked The type to check.
+ * \return Whether the type is a pointer type.
*/
- type inner_aliased_type(const type& alias);
- type inner_aliased_type(std::shared_ptr<alias_type> alias);
+ bool is_any_pointer_type(const type& checked);
}
diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h
index e0f20f3..a1689be 100644
--- a/include/elna/gcc/elna-generic.h
+++ b/include/elna/gcc/elna-generic.h
@@ -76,7 +76,6 @@ 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 *declaration) override;
void visit(boot::variable_declaration *declaration) override;
void visit(boot::named_expression *expression) override;
void visit(boot::array_access_expression *expression) override;