Unify the build_type function

This commit is contained in:
Eugen Wissner 2025-03-06 22:59:41 +01:00
parent dbeaca7cbf
commit dc5760394b
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
8 changed files with 261 additions and 175 deletions

View File

@ -464,7 +464,8 @@ namespace boot
return *m_base;
}
record_type_expression::record_type_expression(const struct position position, fields_t&& fields)
record_type_expression::record_type_expression(const struct position position,
std::vector<field_declaration>&& fields)
: type_expression(position), fields(std::move(fields))
{
}
@ -479,7 +480,8 @@ namespace boot
return std::static_pointer_cast<record_type_expression>(shared_from_this());
}
union_type_expression::union_type_expression(const struct position position, fields_t&& fields)
union_type_expression::union_type_expression(const struct position position,
std::vector<field_declaration>&& fields)
: type_expression(position), fields(std::move(fields))
{
}

View File

@ -145,7 +145,7 @@ along with GCC; see the file COPYING3. If not see
%type <elna::boot::type_definition *> type_definition;
%type <std::vector<elna::boot::type_definition *>> type_definitions type_part;
%type <elna::boot::block *> block;
%type <elna::boot::field_t> field_declaration;
%type <elna::boot::field_declaration> field_declaration;
%type <std::vector<std::pair<std::string, std::shared_ptr<elna::boot::type_expression>>>>
optional_fields required_fields;
%type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements;

View File

@ -21,33 +21,104 @@ namespace elna
{
namespace boot
{
alias_type *type::is_alias()
{
return nullptr;
}
primitive_type *type::is_primitive()
{
return nullptr;
}
record_type *type::is_record()
{
return nullptr;
}
union_type *type::is_union()
{
return nullptr;
}
type::~type()
type::type(alias_type *alias)
: payload({ .alias = alias }), tag(type_tag::alias)
{
}
alias_type *alias_type::is_alias()
type::type(primitive_type *primitive)
: payload({ .primitive = primitive }), tag(type_tag::primitive)
{
}
type::type(record_type *record)
: payload({ .record = record }), tag(type_tag::record)
{
}
type::type(union_type *_union)
: payload({ ._union = _union }), tag(type_tag::_union)
{
}
type::type(pointer_type *pointer)
: payload({ .pointer = pointer }), tag(type_tag::pointer)
{
}
template<>
alias_type *const type::get<alias_type>() const
{
if (tag == type_tag::alias)
{
return payload.alias;
}
else
{
return nullptr;
}
}
template<>
primitive_type *const type::get<primitive_type>() const
{
if (tag == type_tag::primitive)
{
return payload.primitive;
}
else
{
return nullptr;
}
}
template<>
record_type *const type::get<record_type>() const
{
if (tag == type_tag::record)
{
return payload.record;
}
else
{
return nullptr;
}
}
template<>
union_type *const type::get<union_type>() const
{
if (tag == type_tag::_union)
{
return payload._union;
}
else
{
return nullptr;
}
}
template<>
pointer_type *const type::get<pointer_type>() const
{
if (tag == type_tag::pointer)
{
return payload.pointer;
}
else
{
return nullptr;
}
}
bool type::empty() const
{
return tag == type_tag::empty;
}
pointer_type::pointer_type(type base)
: base(base)
{
return this;
}
primitive_type::primitive_type(const std::string& identifier)
@ -55,19 +126,67 @@ namespace boot
{
}
primitive_type *primitive_type::is_primitive()
void declaration_visitor::visit(program *program)
{
return this;
for (type_definition *const type : program->types)
{
this->unresolved.insert({ type->identifier, new alias_type() });
}
for (type_definition *const type : program->types)
{
type->accept(this);
}
}
record_type *record_type::is_record()
void declaration_visitor::visit(type_definition *definition)
{
return this;
auto unresolved_declaration = this->unresolved.at(definition->identifier);
definition->body().accept(this);
unresolved_declaration->reference = this->current_type;
}
union_type *union_type::is_union()
void declaration_visitor::visit(primitive_type_expression *type_expression)
{
auto unresolved_alias = this->unresolved.find(type_expression->name);
if (unresolved_alias != this->unresolved.end())
{
this->current_type = type(unresolved_alias->second);
}
else
{
this->current_type = type(new primitive_type(type_expression->name));
}
}
void declaration_visitor::visit(array_type_expression *type_expression)
{
}
void declaration_visitor::visit(pointer_type_expression *type_expression)
{
type_expression->base().accept(this);
this->current_type = type(new pointer_type(this->current_type));
}
void declaration_visitor::visit(record_type_expression *type_expression)
{
auto type_definition = new record_type();
this->current_type = type(type_definition);
}
void declaration_visitor::visit(union_type_expression *type_expression)
{
auto type_definition = new union_type();
this->current_type = type(type_definition);
}
void declaration_visitor::visit(procedure_type_expression *type_expression)
{
return this;
}
}
}

View File

@ -38,112 +38,41 @@ namespace elna
{
namespace gcc
{
declaration_visitor::declaration_visitor(std::shared_ptr<symbol_table> symbol_table)
: symbols(symbol_table)
static tree get_inner_alias(std::shared_ptr<symbol_table> symbol_table, const boot::type& type)
{
this->symbols->enter("Int", elna_int_type_node);
this->symbols->enter("Word", elna_word_type_node);
this->symbols->enter("Char", elna_char_type_node);
this->symbols->enter("Bool", elna_bool_type_node);
this->symbols->enter("Byte", elna_byte_type_node);
this->symbols->enter("Float", elna_float_type_node);
this->symbols->enter("String", elna_string_type_node);
}
tree declaration_visitor::get_inner_alias(const boot::alias_type& t)
{
if (t.reference == nullptr)
if (auto reference = type.get<boot::primitive_type>())
{
return NULL_TREE;
return symbol_table->lookup(reference->identifier);
}
else if (auto reference = t.reference->is_primitive())
{
return this->symbols->lookup(reference->identifier);
}
else if (auto reference = t.reference->is_alias())
{
return get_inner_alias(*reference);
}
else if (auto reference = t.reference->is_record())
else if (auto reference = type.get<boot::record_type>())
{
return make_node(RECORD_TYPE);
}
else if (auto reference = t.reference->is_union())
else if (auto reference = type.get<boot::union_type>())
{
return make_node(UNION_TYPE);
}
return NULL_TREE;
else if (auto reference = type.get<boot::pointer_type>())
{
return build_pointer_type_for_mode(get_inner_alias(symbol_table, reference->base), VOIDmode, true);
}
else if (auto reference = type.get<boot::alias_type>())
{
return get_inner_alias(symbol_table, reference->reference);
}
return error_mark_node;
}
boot::type *declaration_visitor::build_type(boot::type_expression *type_expression)
void do_semantic_analysis(std::shared_ptr<symbol_table> symbols, std::unique_ptr<boot::program>& ast)
{
if (auto alias_node = type_expression->is_primitive())
{
return this->unresolved.at(alias_node->name);
}
else if (auto alias_node = type_expression->is_record())
{
return build_record(alias_node.get());
}
else if (auto alias_node = type_expression->is_union())
{
return build_union(alias_node.get());
}
return nullptr;
}
boot::declaration_visitor declaration_visitor;
boot::record_type *declaration_visitor::build_record(boot::record_type_expression *type_expression)
{
return new boot::record_type();
}
boot::union_type *declaration_visitor::build_union(boot::union_type_expression *type_expression)
{
return new boot::union_type();
}
void declaration_visitor::visit(boot::program *program)
{
for (boot::type_definition *const type : program->types)
declaration_visitor.visit(ast.get());
for (auto unresolved : declaration_visitor.unresolved)
{
type->accept(this);
auto inner_alias = elna::gcc::get_inner_alias(symbols, boot::type(unresolved.second));
symbols->enter(unresolved.first, inner_alias);
}
for (boot::type_definition *const type : program->types)
{
auto unresolved_declaration = this->unresolved.at(type->identifier);
if (auto alias_node = type->body().is_primitive())
{
auto unresolved_alias = this->unresolved.find(alias_node->name);
if (unresolved_alias != this->unresolved.end())
{
unresolved_declaration->reference = unresolved_alias->second;
}
else
{
unresolved_declaration->reference = new boot::primitive_type(alias_node->name);
}
}
else if (auto alias_node = type->body().is_record())
{
unresolved_declaration->reference = build_record(alias_node.get());
}
else if (auto alias_node = type->body().is_union())
{
unresolved_declaration->reference = build_union(alias_node.get());
}
}
for (auto unresolved : this->unresolved)
{
auto inner_alias = get_inner_alias(*unresolved.second);
this->symbols->enter(unresolved.first, inner_alias);
}
}
void declaration_visitor::visit(boot::type_definition *definition)
{
this->unresolved.insert({ definition->identifier, new boot::alias_type() });
}
generic_visitor::generic_visitor(std::shared_ptr<symbol_table> symbol_table)

View File

@ -90,10 +90,17 @@ static void elna_parse_file(const char *filename)
{
std::shared_ptr<elna::gcc::symbol_table> symbol_table = std::make_shared<elna::gcc::symbol_table>();
elna::gcc::declaration_visitor declaration_visitor{ symbol_table };
symbol_table->enter("Int", elna_int_type_node);
symbol_table->enter("Word", elna_word_type_node);
symbol_table->enter("Char", elna_char_type_node);
symbol_table->enter("Bool", elna_bool_type_node);
symbol_table->enter("Byte", elna_byte_type_node);
symbol_table->enter("Float", elna_float_type_node);
symbol_table->enter("String", elna_string_type_node);
elna::gcc::do_semantic_analysis(symbol_table, driver.tree);
elna::gcc::generic_visitor generic_visitor{ symbol_table };
declaration_visitor.visit(driver.tree.get());
generic_visitor.visit(driver.tree.get());
}
linemap_add(line_table, LC_LEAVE, 0, NULL, 0);

View File

@ -294,15 +294,14 @@ namespace boot
type_expression& base();
};
using field_t = std::pair<std::string, std::shared_ptr<type_expression>>;
using fields_t = std::vector<field_t>;
using field_declaration = std::pair<std::string, std::shared_ptr<type_expression>>;
class record_type_expression : public type_expression
{
public:
fields_t fields;
const std::vector<field_declaration> fields;
record_type_expression(const struct position position, fields_t&& fields);
record_type_expression(const struct position position, std::vector<field_declaration>&& fields);
void accept(parser_visitor *visitor);
std::shared_ptr<record_type_expression> is_record() override;
@ -311,9 +310,9 @@ namespace boot
class union_type_expression : public type_expression
{
public:
fields_t fields;
std::vector<field_declaration> fields;
union_type_expression(const struct position position, fields_t&& fields);
union_type_expression(const struct position position, std::vector<field_declaration>&& fields);
void accept(parser_visitor *visitor);
std::shared_ptr<union_type_expression> is_union() override;

View File

@ -17,59 +17,105 @@ along with GCC; see the file COPYING3. If not see
#include <string>
#include <vector>
#include <unordered_map>
#include "elna/boot/ast.h"
namespace elna
{
namespace boot
{
class alias_type;
class primitive_type;
class record_type;
class union_type;
class primitive_type;
class pointer_type;
class type
{
public:
virtual alias_type *is_alias();
virtual primitive_type *is_primitive();
virtual record_type *is_record();
virtual union_type *is_union();
enum class type_tag
{
empty,
alias,
primitive,
record,
_union,
pointer,
};
union
{
nullptr_t empty;
alias_type *alias;
primitive_type *primitive;
record_type *record;
union_type *_union;
pointer_type *pointer;
} payload{ .empty = nullptr };
virtual ~type() = 0;
type_tag tag{ type_tag::empty };
public:
type() = default;
explicit type(alias_type *alias);
explicit type(primitive_type *primitive);
explicit type(record_type *record);
explicit type(union_type *_union);
explicit type(pointer_type *pointer);
template<typename T>
T *const get() const;
bool empty() const;
};
class alias_type : public type
struct alias_type
{
public:
alias_type *is_alias() override;
type *reference{ nullptr };
type reference;
};
class primitive_type : public type
struct pointer_type
{
public:
std::string identifier;
const type base;
primitive_type(const std::string& identifier);
primitive_type *is_primitive() override;
explicit pointer_type(type base);
};
class record_type : public type
struct primitive_type
{
public:
std::vector<std::pair<std::string, type *>> fields;
const std::string identifier;
record_type *is_record() override;
explicit primitive_type(const std::string& identifier);
};
class union_type : public type
{
public:
std::vector<std::pair<std::string, type *>> fields;
using type_field = typename std::pair<std::string, type>;
union_type *is_union() override;
struct record_type
{
std::vector<type_field> fields;
};
struct union_type
{
std::vector<type_field> fields;
};
class declaration_visitor final : public empty_visitor
{
type current_type;
public:
std::unordered_map<std::string, alias_type *> unresolved;
declaration_visitor() = default;
void visit(primitive_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;
void visit(type_definition *definition) override;
void visit(record_type_expression *type_expression) override;
void visit(union_type_expression *type_expression) override;
void visit(procedure_type_expression *type_expression) override;
};
}
}

View File

@ -28,29 +28,13 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "tree-iterator.h"
#include <unordered_map>
#include <string>
namespace elna
{
namespace gcc
{
class declaration_visitor final : public boot::empty_visitor
{
std::shared_ptr<symbol_table> symbols;
std::unordered_map<std::string, boot::alias_type *> unresolved;
boot::type *build_type(boot::type_expression *type_expression);
boot::record_type *build_record(boot::record_type_expression *type_expression);
boot::union_type *build_union(boot::union_type_expression *type_expression);
tree get_inner_alias(const boot::alias_type& t);
public:
declaration_visitor(std::shared_ptr<symbol_table> symbol_table);
void visit(boot::program *program) override;
void visit(boot::type_definition *definition) override;
};
void do_semantic_analysis(std::shared_ptr<symbol_table> symbols, std::unique_ptr<boot::program>& ast);
class generic_visitor final : public boot::empty_visitor
{