Implement enumeration type

This commit is contained in:
2025-04-04 22:48:12 +02:00
parent 50970f3289
commit 18c4e79012
14 changed files with 612 additions and 416 deletions

View File

@ -62,17 +62,19 @@ namespace elna::boot
class if_statement;
class while_statement;
class return_statement;
class case_statement;
class traits_expression;
class block;
class program;
class binary_expression;
class unary_expression;
class primitive_type_expression;
class named_type_expression;
class array_type_expression;
class pointer_type_expression;
class record_type_expression;
class union_type_expression;
class procedure_type_expression;
class enumeration_type_expression;
class variable_expression;
class array_access_expression;
class field_access_expression;
@ -100,16 +102,18 @@ namespace elna::boot
virtual void visit(while_statement *) = 0;
virtual void visit(return_statement *) = 0;
virtual void visit(defer_statement *) = 0;
virtual void visit(case_statement *) = 0;
virtual void visit(block *) = 0;
virtual void visit(program *) = 0;
virtual void visit(binary_expression *) = 0;
virtual void visit(unary_expression *) = 0;
virtual void visit(primitive_type_expression *) = 0;
virtual void visit(named_type_expression *) = 0;
virtual void visit(array_type_expression *) = 0;
virtual void visit(pointer_type_expression *) = 0;
virtual void visit(record_type_expression *) = 0;
virtual void visit(union_type_expression *) = 0;
virtual void visit(procedure_type_expression *) = 0;
virtual void visit(enumeration_type_expression *) = 0;
virtual void visit(variable_expression *) = 0;
virtual void visit(array_access_expression *) = 0;
virtual void visit(field_access_expression *) = 0;
@ -188,28 +192,29 @@ namespace elna::boot
class type_expression : public node
{
public:
virtual primitive_type_expression *is_primitive();
virtual named_type_expression *is_named();
virtual array_type_expression *is_array();
virtual pointer_type_expression *is_pointer();
virtual record_type_expression *is_record();
virtual union_type_expression *is_union();
virtual procedure_type_expression *is_procedure();
virtual enumeration_type_expression *is_enumeration();
protected:
type_expression(const struct position position);
};
/**
* Expression defining a basic type.
* Expression refering to a type by its name.
*/
class primitive_type_expression : public type_expression
class named_type_expression : public type_expression
{
public:
const std::string name;
primitive_type_expression(const struct position position, const std::string& name);
named_type_expression(const struct position position, const std::string& name);
void accept(parser_visitor *visitor) override;
primitive_type_expression *is_primitive() override;
named_type_expression *is_named() override;
};
class array_type_expression : public type_expression
@ -269,6 +274,20 @@ namespace elna::boot
union_type_expression *is_union() override;
};
/**
* Enumeration type.
*/
class enumeration_type_expression : public type_expression
{
public:
const std::vector<std::string> members;
enumeration_type_expression(const struct position, std::vector<std::string>&& members);
void accept(parser_visitor *visitor) override;
enumeration_type_expression *is_enumeration() override;
};
/**
* Variable declaration.
*/
@ -291,14 +310,6 @@ namespace elna::boot
class literal_expression : public expression
{
public:
virtual literal<std::int32_t> *is_int() = 0;
virtual literal<std::uint32_t> *is_word() = 0;
virtual literal<double> *is_float() = 0;
virtual literal<bool> *is_bool() = 0;
virtual literal<unsigned char> *is_char() = 0;
virtual literal<std::nullptr_t> *is_nil() = 0;
virtual literal<std::string> *is_string() = 0;
literal_expression *is_literal() override;
protected:
@ -428,18 +439,34 @@ namespace elna::boot
class return_statement : public statement
{
expression *m_return_expression{ nullptr };
public:
expression *const return_expression{ nullptr };
return_statement(const struct position position, expression *return_expression = nullptr);
void accept(parser_visitor *visitor) override;
virtual return_statement *is_return() override;
expression *return_expression();
virtual ~return_statement() override;
};
struct switch_case
{
std::vector<literal_expression *> labels;
std::vector<statement *> statements;
};
class case_statement : public statement
{
expression *m_condition;
public:
const std::vector<switch_case> cases;
case_statement(const struct position position, expression *condition, std::vector<switch_case>&& cases);
void accept(parser_visitor *visitor) override;
expression& condition();
};
class designator_expression : public expression
{
public:
@ -635,90 +662,6 @@ namespace elna::boot
{
}
literal<std::int32_t> *is_int() override
{
if (std::is_same<T, std::int32_t>::value)
{
return reinterpret_cast<literal<std::int32_t> *>(this);
}
else
{
return nullptr;
}
}
literal<std::uint32_t> *is_word() override
{
if (std::is_same<T, std::uint32_t>::value)
{
return reinterpret_cast<literal<std::uint32_t> *>(this);
}
else
{
return nullptr;
}
}
literal<double> *is_float() override
{
if (std::is_same<T, double>::value)
{
return reinterpret_cast<literal<double> *>(this);
}
else
{
return nullptr;
}
}
literal<bool> *is_bool() override
{
if (std::is_same<T, bool>::value)
{
return reinterpret_cast<literal<bool> *>(this);
}
else
{
return nullptr;
}
}
literal<unsigned char> *is_char() override
{
if (std::is_same<T, unsigned char>::value)
{
return reinterpret_cast<literal<unsigned char> *>(this);
}
else
{
return nullptr;
}
}
literal<std::nullptr_t> *is_nil() override
{
if (std::is_same<T, std::nullptr_t>::value)
{
return reinterpret_cast<literal<std::nullptr_t> *>(this);
}
else
{
return nullptr;
}
}
literal<std::string> *is_string() override
{
if (std::is_same<T, std::string>::value)
{
return reinterpret_cast<literal<std::string> *>(this);
}
else
{
return nullptr;
}
}
void accept(parser_visitor *visitor) override
{
visitor->visit(this);
@ -728,9 +671,9 @@ namespace elna::boot
class defer_statement : public statement
{
public:
std::vector<statement *> statements;
const std::vector<statement *> statements;
defer_statement(const struct position position);
defer_statement(const struct position position, std::vector<statement *>&& statements);
void accept(parser_visitor *visitor) override;
defer_statement *is_defer() override;

View File

@ -49,6 +49,8 @@ namespace elna::boot
class declaration_visitor final : public parser_visitor, public error_container
{
type current_type;
constant_info::variant current_literal;
std::shared_ptr<symbol_table> symbols;
procedure_type build_procedure(procedure_type_expression& type_expression);
@ -58,7 +60,7 @@ namespace elna::boot
explicit declaration_visitor(const char *path, std::shared_ptr<symbol_table> symbols);
void visit(primitive_type_expression *type_expression) override;
void visit(named_type_expression *type_expression) override;
void visit(array_type_expression *type_expression) override;
void visit(pointer_type_expression *type_expression) override;
void visit(program *program) override;
@ -66,15 +68,17 @@ namespace elna::boot
void visit(record_type_expression *type_expression) override;
void visit(union_type_expression *type_expression) override;
void visit(procedure_type_expression *type_expression) override;
void visit(enumeration_type_expression *type_expression) override;
void visit(variable_declaration *declaration) override;
void visit(constant_definition *) override;
void visit(constant_definition *definition) override;
void visit(procedure_definition *definition) override;
void visit(assign_statement *statement) override;
void visit(if_statement *statement) override;
void visit(while_statement *statement) override;
void visit(return_statement *statement) override;
void visit(defer_statement *statement) override;
void visit(case_statement *statement) override;
void visit(procedure_call *call) override;
void visit(block *block) override;
void visit(cast_expression *expression) override;
@ -85,12 +89,12 @@ namespace elna::boot
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> *) override;
void visit(literal<std::uint32_t> *) override;
void visit(literal<double> *) override;
void visit(literal<bool> *) override;
void visit(literal<unsigned char> *) override;
void visit(literal<std::nullptr_t> *) override;
void visit(literal<std::string> *) override;
void visit(literal<std::int32_t> *literal) override;
void visit(literal<std::uint32_t> *literal) override;
void visit(literal<double> *literal) override;
void visit(literal<bool> *literal) override;
void visit(literal<unsigned char> *literal) override;
void visit(literal<std::nullptr_t> *literal) override;
void visit(literal<std::string> *literal) override;
};
}

View File

@ -34,6 +34,7 @@ namespace elna::boot
class pointer_type;
class array_type;
class procedure_type;
class enumeration_type;
class type
{
@ -46,7 +47,8 @@ namespace elna::boot
_union,
pointer,
array,
procedure
procedure,
enumeration
};
type_tag tag{ type_tag::empty };
union
@ -58,6 +60,7 @@ namespace elna::boot
std::shared_ptr<pointer_type> pointer;
std::shared_ptr<array_type> array;
std::shared_ptr<procedure_type> procedure;
std::shared_ptr<enumeration_type> enumeration;
};
void copy(const type& other);
@ -72,6 +75,7 @@ namespace elna::boot
explicit type(std::shared_ptr<pointer_type> pointer);
explicit type(std::shared_ptr<array_type> array);
explicit type(std::shared_ptr<procedure_type> procedure);
explicit type(std::shared_ptr<enumeration_type> enumeration);
type(const type& other);
type& operator=(const type& other);
@ -141,8 +145,16 @@ namespace elna::boot
procedure_type(return_t return_type = return_t());
};
struct enumeration_type
{
std::vector<std::string> members;
explicit enumeration_type(const std::vector<std::string>& members);
};
class type_info;
class procedure_info;
class constant_info;
class info : public std::enable_shared_from_this<info>
{
@ -174,6 +186,17 @@ namespace elna::boot
std::shared_ptr<procedure_info> is_procedure() override;
};
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);
};
/**
* Symbol table.
*/

View File

@ -47,7 +47,6 @@ namespace elna::gcc
std::unordered_map<std::string, tree> unresolved;
void declare_procedure(boot::procedure_definition *const definition);
tree build_label_decl(const char *name, location_t loc);
tree build_procedure_type(boot::procedure_type_expression& type);
void build_composite_type(const std::vector<boot::field_declaration>& fields,
tree composite_type_node);
@ -101,13 +100,15 @@ namespace elna::gcc
void visit(boot::assign_statement *statement) override;
void visit(boot::if_statement *statement) override;
void visit(boot::while_statement *statement) override;
void visit(boot::primitive_type_expression *type) override;
void visit(boot::named_type_expression *type) override;
void visit(boot::array_type_expression *type) override;
void visit(boot::pointer_type_expression *type) override;
void visit(boot::record_type_expression *type) override;
void visit(boot::union_type_expression *type) override;
void visit(boot::procedure_type_expression *type) override;
void visit(boot::enumeration_type_expression *type) override;
void visit(boot::return_statement *statement) override;
void visit(boot::defer_statement *statement) override;
void visit(boot::case_statement *statement) override;
};
}

View File

@ -33,7 +33,6 @@ namespace elna::gcc
{
using symbol_table = boot::symbol_map<tree, tree, NULL_TREE>;
bool is_pointer_type(tree type);
bool is_integral_type(tree type);
bool is_numeric_type(tree type);
bool is_primitive_type(tree type);
@ -42,9 +41,9 @@ namespace elna::gcc
/**
* \param type The type to evaluate.
* \return Whether the given type is record or union.
* \return Whether this type can be converted to another type.
*/
bool is_aggregate_type(tree type);
bool is_castable_type(tree type);
/**
* \param lhs Left hand value.
@ -82,4 +81,5 @@ 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_global_pointer_type(tree type);
tree build_label_decl(const char *name, location_t loc);
}