/* Abstract syntax tree representation. Copyright (C) 2025 Free Software Foundation, Inc. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ #include "elna/boot/ast.h" #include namespace elna::boot { void empty_visitor::visit(array_type_expression *) { __builtin_unreachable(); } void empty_visitor::visit(pointer_type_expression *) { __builtin_unreachable(); } void empty_visitor::visit(constant_type_expression *) { __builtin_unreachable(); } void empty_visitor::visit(type_declaration *) { __builtin_unreachable(); } void empty_visitor::visit(record_type_expression *) { __builtin_unreachable(); } void empty_visitor::visit(procedure_type_expression *) { __builtin_unreachable(); } void empty_visitor::visit(enumeration_type_expression *) { __builtin_unreachable(); } void empty_visitor::visit(variable_declaration *) { __builtin_unreachable(); } void empty_visitor::visit(procedure_declaration *) { __builtin_unreachable(); } void empty_visitor::visit(assign_statement *) { __builtin_unreachable(); } void empty_visitor::visit(if_statement *) { __builtin_unreachable(); } void empty_visitor::visit(import_declaration *) { __builtin_unreachable(); } void empty_visitor::visit(while_statement *) { __builtin_unreachable(); } void empty_visitor::visit(defer_statement *) { __builtin_unreachable(); } void empty_visitor::visit(empty_statement *) { __builtin_unreachable(); } void empty_visitor::visit(case_statement *) { __builtin_unreachable(); } void empty_visitor::visit(procedure_call *) { __builtin_unreachable(); } void empty_visitor::visit(unit *) { __builtin_unreachable(); } void empty_visitor::visit(cast_expression *) { __builtin_unreachable(); } void empty_visitor::visit(record_constructor_expression *) { __builtin_unreachable(); } void empty_visitor::visit(array_constructor_expression *) { __builtin_unreachable(); } void empty_visitor::visit(traits_expression *) { __builtin_unreachable(); } void empty_visitor::visit(binary_expression *) { __builtin_unreachable(); } void empty_visitor::visit(unary_expression *) { __builtin_unreachable(); } void empty_visitor::visit(named_expression *) { __builtin_unreachable(); } void empty_visitor::visit(array_access_expression *) { __builtin_unreachable(); } void empty_visitor::visit(field_access_expression *) { __builtin_unreachable(); } void empty_visitor::visit(dereference_expression *) { __builtin_unreachable(); } void empty_visitor::visit(literal *) { __builtin_unreachable(); } void empty_visitor::visit(literal *) { __builtin_unreachable(); } void empty_visitor::visit(literal *) { __builtin_unreachable(); } void empty_visitor::visit(literal *) { __builtin_unreachable(); } void empty_visitor::visit(literal *) { __builtin_unreachable(); } void empty_visitor::visit(literal *) { __builtin_unreachable(); } void empty_visitor::visit(literal *) { __builtin_unreachable(); } void walking_visitor::visit(import_declaration *) { } void walking_visitor::visit(procedure_declaration *declaration) { for (const field_declaration& parameter : declaration->heading().parameters) { parameter.second->accept(this); } if (declaration->heading().return_type.proper_type != nullptr) { declaration->heading().return_type.proper_type->accept(this); } if (declaration->body.has_value()) { for (variable_declaration *variable : declaration->body.value().variables) { variable->accept(this); } for (auto *statement : declaration->body.value().entry_point) { statement->accept(this); } if (declaration->body.value().return_expression != nullptr) { declaration->body.value().return_expression->accept(this); } } } void walking_visitor::visit(assign_statement *statement) { statement->lvalue().accept(this); statement->rvalue().accept(this); } void walking_visitor::visit(if_statement *statement) { statement->branch().prerequisite().accept(this); for (auto *branch_statement : statement->branch().statements) { branch_statement->accept(this); } for (conditional_statements *branch : statement->branches) { branch->prerequisite().accept(this); for (auto *branch_statement : branch->statements) { branch_statement->accept(this); } } if (statement->alternative != nullptr) { for (auto *branch_statement : *statement->alternative) { branch_statement->accept(this); } } } void walking_visitor::visit(while_statement *statement) { statement->branch().prerequisite().accept(this); for (auto *branch_statement : statement->branch().statements) { branch_statement->accept(this); } for (conditional_statements *branch : statement->branches) { branch->prerequisite().accept(this); for (auto *branch_statement : branch->statements) { branch_statement->accept(this); } } } void walking_visitor::visit(defer_statement *statement) { for (auto *block_statement : statement->statements) { block_statement->accept(this); } } void walking_visitor::visit(empty_statement *) { } void walking_visitor::visit(case_statement *statement) { statement->condition().accept(this); for (const switch_case& case_block : statement->cases) { for (expression *case_label : case_block.labels) { case_label->accept(this); } for (auto *block_statement : case_block.statements) { block_statement->accept(this); } } if (statement->alternative != nullptr) { for (auto *block_statement : *statement->alternative) { block_statement->accept(this); } } } void walking_visitor::visit(procedure_call *call) { call->callable().accept(this); for (expression *argument : call->arguments) { argument->accept(this); } } void walking_visitor::visit(unit *unit) { for (import_declaration *_import : unit->imports) { _import->accept(this); } for (type_declaration *type : unit->types) { type->accept(this); } for (variable_declaration *variable : unit->variables) { variable->accept(this); } for (procedure_declaration *procedure : unit->procedures) { procedure->accept(this); } for (auto *entry_statement : unit->entry_point) { entry_statement->accept(this); } } void walking_visitor::visit(type_declaration *declaration) { declaration->underlying_type().accept(this); } void walking_visitor::visit(variable_declaration *declaration) { declaration->variable_type().accept(this); if (declaration->initializer != nullptr) { declaration->initializer->accept(this); } } void walking_visitor::visit(array_type_expression *expression) { expression->base().accept(this); } void walking_visitor::visit(pointer_type_expression *expression) { expression->base().accept(this); } void walking_visitor::visit(constant_type_expression *expression) { expression->base().accept(this); } void walking_visitor::visit(record_type_expression *expression) { for (const field_declaration& field : expression->fields) { field.second->accept(this); } } void walking_visitor::visit(procedure_type_expression *expression) { for (const field_declaration& field : expression->parameters) { field.second->accept(this); } if (expression->return_type.proper_type != nullptr) { expression->return_type.proper_type->accept(this); } } void walking_visitor::visit(enumeration_type_expression *) { } void walking_visitor::visit(cast_expression *expression) { expression->value().accept(this); expression->target().accept(this); } void walking_visitor::visit(record_constructor_expression *expression) { for (const field_initializer& initializer : expression->field_initializers) { initializer.value().accept(this); } } void walking_visitor::visit(array_constructor_expression *expression) { expression->m_element_type->accept(this); for (auto *element : expression->elements) { element->accept(this); } } void walking_visitor::visit(traits_expression *trait) { if (!trait->arguments.empty()) { trait->arguments.front()->accept(this); } } void walking_visitor::visit(binary_expression *expression) { expression->lhs().accept(this); expression->rhs().accept(this); } void walking_visitor::visit(unary_expression *expression) { expression->operand().accept(this); } void walking_visitor::visit(named_expression *) { } void walking_visitor::visit(array_access_expression *expression) { expression->base().accept(this); expression->index().accept(this); } void walking_visitor::visit(field_access_expression *expression) { expression->base().accept(this); } void walking_visitor::visit(dereference_expression *expression) { expression->base().accept(this); } void walking_visitor::visit(literal *) { } void walking_visitor::visit(literal *) { } void walking_visitor::visit(literal *) { } void walking_visitor::visit(literal *) { } void walking_visitor::visit(literal *) { } void walking_visitor::visit(literal *) { } void walking_visitor::visit(literal *) { } node::node(const source_position position) : m_position(position) { } node::~node() = default; const source_position& node::position() const { return this->m_position; } cast_expression *expression::is_cast() { return nullptr; } traits_expression *expression::is_traits() { return nullptr; } binary_expression *expression::is_binary() { return nullptr; } unary_expression *expression::is_unary() { return nullptr; } designator_expression *expression::is_designator() { return nullptr; } procedure_call *expression::is_call_expression() { return nullptr; } literal_expression *expression::is_literal() { return nullptr; } record_constructor_expression *expression::is_record_constructor() { return nullptr; } array_constructor_expression *expression::is_array_constructor() { return nullptr; } named_expression *type_expression::is_named() { return nullptr; } array_type_expression *type_expression::is_array() { return nullptr; } pointer_type_expression *type_expression::is_pointer() { return nullptr; } constant_type_expression *type_expression::is_constant() { return nullptr; } record_type_expression *type_expression::is_record() { return nullptr; } procedure_type_expression *type_expression::is_procedure() { return nullptr; } enumeration_type_expression *type_expression::is_enumeration() { return nullptr; } array_type_expression::array_type_expression(const source_position position, type_expression *base, const std::uint32_t size) : node(position), m_base(base), size(size) { } array_type_expression::~array_type_expression() { delete m_base; } void array_type_expression::accept(parser_visitor *visitor) { visitor->visit(this); } array_type_expression *array_type_expression::is_array() { return this; } type_expression& array_type_expression::base() { return *m_base; } pointer_type_expression::pointer_type_expression(const source_position position, type_expression *base) : node(position), m_base(base) { } pointer_type_expression::~pointer_type_expression() { delete m_base; } void pointer_type_expression::accept(parser_visitor *visitor) { visitor->visit(this); } pointer_type_expression *pointer_type_expression::is_pointer() { return this; } type_expression& pointer_type_expression::base() { return *m_base; } constant_type_expression::constant_type_expression(const source_position position, type_expression *base) : node(position), m_base(base) { } constant_type_expression::~constant_type_expression() { delete m_base; } void constant_type_expression::accept(parser_visitor *visitor) { visitor->visit(this); } constant_type_expression *constant_type_expression::is_constant() { return this; } type_expression& constant_type_expression::base() { return *m_base; } record_type_expression::record_type_expression(const source_position position, std::vector&& fields) : node(position), fields(std::move(fields)) { } record_type_expression::record_type_expression(const source_position position, std::vector&& fields, identifier&& base) : node(position), fields(std::move(fields)), base(std::make_optional(std::move(base))) { } void record_type_expression::accept(parser_visitor *visitor) { visitor->visit(this); } record_type_expression *record_type_expression::is_record() { return this; } field_initializer::field_initializer(identifier name, expression *value) : m_name(std::move(name)), m_value(value) { } field_initializer::~field_initializer() { delete this->m_value; } field_initializer::field_initializer(field_initializer&& other) noexcept : m_name(std::move(other.m_name)), m_value(other.m_value) { other.m_value = nullptr; } field_initializer& field_initializer::operator=(field_initializer&& other) noexcept { delete this->m_value; this->m_name = std::move(other.m_name); this->m_value = other.m_value; other.m_value = nullptr; return *this; } const std::string& field_initializer::name() const { return this->m_name.name(); } const identifier& field_initializer::id() const { return this->m_name; } expression& field_initializer::value() const { return *this->m_value; } record_constructor_expression::record_constructor_expression(const source_position position, identifier&& type_name, std::vector&& field_initializers) : node(position), type_name(std::move(type_name)), field_initializers(std::move(field_initializers)) { } void record_constructor_expression::accept(parser_visitor *visitor) { visitor->visit(this); } record_constructor_expression *record_constructor_expression::is_record_constructor() { return this; } array_constructor_expression::array_constructor_expression(const source_position position, std::uint32_t size, type_expression *element_type, std::vector&& elements) : node(position), size(size), m_element_type(element_type), elements(std::move(elements)) { } void array_constructor_expression::accept(parser_visitor *visitor) { visitor->visit(this); } array_constructor_expression *array_constructor_expression::is_array_constructor() { return this; } array_constructor_expression::~array_constructor_expression() { delete m_element_type; for (const expression *element : elements) { delete element; } } variable_declaration::variable_declaration(const source_position position, std::vector&& identifier, std::shared_ptr variable_type, expression *initializer) : node(position), m_variable_type(std::move(variable_type)), identifiers(std::move(identifier)), initializer(initializer) { } variable_declaration::variable_declaration(const source_position position, std::vector&& identifier, std::shared_ptr variable_type, std::monostate) : node(position), m_variable_type(std::move(variable_type)), identifiers(std::move(identifier)), is_extern(true) { } void variable_declaration::accept(parser_visitor *visitor) { visitor->visit(this); } bool variable_declaration::has_initializer() const { return this->is_extern || this->initializer != nullptr; } type_expression& variable_declaration::variable_type() { return *m_variable_type; } declaration::declaration(const source_position position, identifier_definition identifier) : node(position), identifier(std::move(identifier)) { } procedure_type_expression::procedure_type_expression(const source_position position, std::vector&& parameters, return_t return_type) : node(position), return_type(return_type), parameters(std::move(parameters)) { } procedure_type_expression::~procedure_type_expression() { delete return_type.proper_type; } void procedure_type_expression::accept(parser_visitor *visitor) { visitor->visit(this); } procedure_type_expression *procedure_type_expression::is_procedure() { return this; } enumeration_type_expression::enumeration_type_expression(const source_position position, std::vector&& members) : node(position), members(std::move(members)) { } void enumeration_type_expression::accept(parser_visitor *visitor) { visitor->visit(this); } enumeration_type_expression *enumeration_type_expression::is_enumeration() { return this; } procedure_declaration::procedure_declaration(const source_position position, identifier_definition identifier, procedure_type_expression *heading, procedure_body&& body) : declaration(position, std::move(identifier)), m_heading(heading), body(std::make_optional(std::move(body))) { } procedure_declaration::procedure_declaration(const source_position position, identifier_definition identifier, procedure_type_expression *heading) : declaration(position, std::move(identifier)), m_heading(heading) { } void procedure_declaration::accept(parser_visitor *visitor) { visitor->visit(this); } procedure_type_expression& procedure_declaration::heading() { return *m_heading; } procedure_declaration::~procedure_declaration() { delete m_heading; } type_declaration::type_declaration(const source_position position, identifier_definition identifier, type_expression *underlying_type) : declaration(position, std::move(identifier)), m_underlying_type(underlying_type) { } type_declaration::~type_declaration() { delete m_underlying_type; } void type_declaration::accept(parser_visitor *visitor) { visitor->visit(this); } type_expression& type_declaration::underlying_type() { return *m_underlying_type; } procedure_body::procedure_body(std::vector&& variables, std::vector&& entry_point, expression *return_expression) : variables(std::move(variables)), entry_point(std::move(entry_point)), return_expression(return_expression) { } procedure_body::procedure_body(procedure_body&& that) : variables(std::move(const_cast&>(that.variables))), entry_point(std::move(const_cast&>(that.entry_point))), return_expression(that.return_expression) { } procedure_body::~procedure_body() { for (const statement *body_statement : this->entry_point) { delete body_statement; } for (const variable_declaration *variable : this->variables) { delete variable; } } unit::unit(const source_position position) : node(position), procedure_body(std::vector{}, std::vector{}, nullptr) { } unit::unit(const source_position position, std::vector&& imports, std::vector&& types, std::vector&& variables, std::vector&& procedures, std::vector&& entry_point) : node(position), procedure_body(std::move(variables), std::move(entry_point)), imports(std::move(imports)), types(std::move(types)), procedures(std::move(procedures)) { } void unit::accept(parser_visitor *visitor) { visitor->visit(this); } bool unit::has_body() const { return !this->entry_point.empty(); } unit::~unit() { for (const procedure_declaration *procedure : this->procedures) { delete procedure; } for (const type_declaration *type : this->types) { delete type; } for (const import_declaration *declaration : this->imports) { delete declaration; } } literal_expression *literal_expression::is_literal() { return this; } defer_statement::defer_statement(const source_position position, std::vector&& statements) : node(position), statements(std::move(statements)) { } void defer_statement::accept(parser_visitor *visitor) { visitor->visit(this); } defer_statement::~defer_statement() { for (const statement *body_statement : statements) { delete body_statement; } } void empty_statement::accept(parser_visitor *visitor) { visitor->visit(this); } empty_statement::empty_statement(const source_position position) : node(position) { } designator_expression::~designator_expression() = default; designator_expression *designator_expression::is_designator() { return this; } void designator_expression::accept(parser_visitor *visitor) { if (named_expression *node = is_named()) { visitor->visit(node); } else if (array_access_expression *node = is_array_access()) { visitor->visit(node); } else if (field_access_expression *node = is_field_access()) { visitor->visit(node); } else if (dereference_expression *node = is_dereference()) { visitor->visit(node); } else { __builtin_unreachable(); } } named_expression::named_expression(const source_position position, const std::string& name) : node(position), name(name) { } void named_expression::accept(parser_visitor *visitor) { visitor->visit(this); } named_expression *named_expression::is_named() { return this; } array_access_expression::array_access_expression(const source_position position, expression *base, expression *index) : node(position), m_base(base), m_index(index) { } void array_access_expression::accept(parser_visitor *visitor) { visitor->visit(this); } expression& array_access_expression::index() { return *m_index; } expression& array_access_expression::base() { return *m_base; } array_access_expression *array_access_expression::is_array_access() { return this; } array_access_expression::~array_access_expression() { delete m_index; delete m_base; } field_access_expression::field_access_expression(const source_position position, expression *base, identifier&& field) : node(position), m_base(base), m_field(std::move(field)) { } void field_access_expression::accept(parser_visitor *visitor) { visitor->visit(this); } expression& field_access_expression::base() { return *m_base; } const identifier& field_access_expression::field() { return m_field; } field_access_expression *field_access_expression::is_field_access() { return this; } field_access_expression::~field_access_expression() { delete m_base; } dereference_expression::dereference_expression(const source_position position, expression *base) : node(position), m_base(base) { } void dereference_expression::accept(parser_visitor *visitor) { visitor->visit(this); } expression& dereference_expression::base() { return *m_base; } dereference_expression *dereference_expression::is_dereference() { return this; } dereference_expression::~dereference_expression() { delete m_base; } binary_expression::binary_expression(const source_position position, expression *lhs, expression *rhs, const binary_operator operation) : node(position), m_lhs(lhs), m_rhs(rhs), m_operator(operation) { } void binary_expression::accept(parser_visitor *visitor) { visitor->visit(this); } binary_expression *binary_expression::is_binary() { return this; } expression& binary_expression::lhs() { return *m_lhs; } expression& binary_expression::rhs() { return *m_rhs; } binary_operator binary_expression::operation() const { return m_operator; } binary_expression::~binary_expression() { delete m_lhs; delete m_rhs; } unary_expression::unary_expression(const source_position position, expression *operand, const unary_operator operation) : node(position), m_operand(operand), m_operator(operation) { } void unary_expression::accept(parser_visitor *visitor) { visitor->visit(this); } unary_expression *unary_expression::is_unary() { return this; } expression& unary_expression::operand() { return *m_operand; } unary_operator unary_expression::operation() const { return this->m_operator; } unary_expression::~unary_expression() { delete m_operand; } procedure_call::procedure_call(const source_position position, designator_expression *callable, std::vector&& arguments) : node(position), m_callable(callable), arguments(std::move(arguments)) { } void procedure_call::accept(parser_visitor *visitor) { visitor->visit(this); } procedure_call *procedure_call::is_call_expression() { return this; } designator_expression& procedure_call::callable() { return *m_callable; } procedure_call::~procedure_call() { for (const expression *argument : arguments) { delete argument; } delete m_callable; } cast_expression::cast_expression(const source_position position, type_expression *target, expression *value) : node(position), m_target(target), m_value(value) { } void cast_expression::accept(parser_visitor *visitor) { visitor->visit(this); } cast_expression *cast_expression::is_cast() { return this; } type_expression& cast_expression::target() { return *m_target; } expression& cast_expression::value() { return *m_value; } cast_expression::~cast_expression() { delete m_target; delete m_value; } traits_expression::traits_expression(const source_position position, identifier&& name, std::vector&& arguments) : node(position), arguments(std::move(arguments)), name(std::move(name)) { } traits_expression::~traits_expression() { for (const type_expression *argument : this->arguments) { delete argument; } } void traits_expression::accept(parser_visitor *visitor) { visitor->visit(this); } traits_expression *traits_expression::is_traits() { return this; } conditional_statements::conditional_statements(expression *prerequisite, std::vector&& statements) : m_prerequisite(prerequisite), statements(std::move(statements)) { } expression& conditional_statements::prerequisite() { return *m_prerequisite; } conditional_statements::~conditional_statements() { delete m_prerequisite; for (auto *statement : statements) { delete statement; } } case_statement::case_statement(const source_position position, expression *condition, std::vector&& cases, std::vector *alternative) : node(position), m_condition(condition), cases(std::move(cases)), alternative(alternative) { } void case_statement::accept(parser_visitor *visitor) { visitor->visit(this); } expression& case_statement::condition() { return *m_condition; } assign_statement::assign_statement(const source_position position, designator_expression *lvalue, expression *rvalue) : node(position), m_lvalue(lvalue), m_rvalue(rvalue) { } void assign_statement::accept(parser_visitor *visitor) { visitor->visit(this); } named_expression *designator_expression::is_named() { return nullptr; } array_access_expression *designator_expression::is_array_access() { return nullptr; } field_access_expression *designator_expression::is_field_access() { return nullptr; } dereference_expression *designator_expression::is_dereference() { return nullptr; } designator_expression& assign_statement::lvalue() { return *m_lvalue; } expression& assign_statement::rvalue() { return *m_rvalue; } assign_statement::~assign_statement() { delete m_rvalue; } if_statement::if_statement(const source_position position, conditional_statements *branch, std::vector&& branches, std::vector *alternative) : node(position), m_branch(branch), branches(std::move(branches)), alternative(alternative) { } void if_statement::accept(parser_visitor *visitor) { visitor->visit(this); } conditional_statements& if_statement::branch() { return *m_branch; } if_statement::~if_statement() { delete m_branch; for (const conditional_statements *branch : branches) { delete branch; } delete this->alternative; } import_declaration::import_declaration(const source_position position, std::vector&& segments) : node(position), segments(std::move(segments)) { } void import_declaration::accept(parser_visitor *visitor) { visitor->visit(this); } while_statement::while_statement(const source_position position, conditional_statements *branch, std::vector&& branches) : node(position), m_branch(branch), branches(std::move(branches)) { } void while_statement::accept(parser_visitor *visitor) { visitor->visit(this); } conditional_statements& while_statement::branch() { return *m_branch; } while_statement::~while_statement() { delete m_branch; for (const conditional_statements *branch : branches) { delete branch; } } const char *print_binary_operator(const binary_operator operation) { switch (operation) { using enum binary_operator; case sum: return "+"; case subtraction: return "-"; case multiplication: return "*"; case division: return "/"; case remainder: return "%"; case equals: return "="; case not_equals: return "<>"; case less: return "<"; case less_equal: return "<="; case greater: return ">"; case greater_equal: return ">="; case conjunction: return "and"; case disjunction: return "or"; case exclusive_disjunction: return "xor"; case shift_left: return "<<"; case shift_right: return ">>"; } __builtin_unreachable(); }; }