Declare an additional name analysis visitor
This commit is contained in:
		
							
								
								
									
										291
									
								
								boot/semantic.cc
									
									
									
									
									
								
							
							
						
						
									
										291
									
								
								boot/semantic.cc
									
									
									
									
									
								
							@@ -43,11 +43,6 @@ namespace elna::boot
 | 
			
		||||
        return "Symbol '" + identifier + "' has been already declared";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    declaration_visitor::declaration_visitor(const char *path, std::shared_ptr<symbol_table> symbols)
 | 
			
		||||
        : error_container(path), symbols(symbols)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    field_duplication_error::field_duplication_error(const std::string& field_name,
 | 
			
		||||
            const char *path, const struct position)
 | 
			
		||||
        : error(path, position), field_name(field_name)
 | 
			
		||||
@@ -59,7 +54,24 @@ namespace elna::boot
 | 
			
		||||
        return "Repeated field name '" + field_name + "'";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    procedure_type declaration_visitor::build_procedure(procedure_type_expression& type_expression)
 | 
			
		||||
    cyclic_declaration_error::cyclic_declaration_error(const std::vector<std::string>& cycle,
 | 
			
		||||
            const char *path, const struct position)
 | 
			
		||||
        : error(path, position), cycle(cycle)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string cyclic_declaration_error::what() const
 | 
			
		||||
    {
 | 
			
		||||
        return "Type declaration forms a cycle";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    name_analysis_visitor::name_analysis_visitor(const char *path, std::shared_ptr<symbol_table> symbols,
 | 
			
		||||
                std::unordered_map<std::string, std::shared_ptr<alias_type>>&& unresolved)
 | 
			
		||||
        : error_container(path), symbols(symbols), unresolved(std::move(unresolved))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    procedure_type name_analysis_visitor::build_procedure(procedure_type_expression& type_expression)
 | 
			
		||||
    {
 | 
			
		||||
        procedure_type::return_t result_return;
 | 
			
		||||
 | 
			
		||||
@@ -86,7 +98,7 @@ namespace elna::boot
 | 
			
		||||
        return result_type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(program *program)
 | 
			
		||||
    void name_analysis_visitor::visit(program *program)
 | 
			
		||||
    {
 | 
			
		||||
        visit(static_cast<unit *>(program));
 | 
			
		||||
 | 
			
		||||
@@ -96,7 +108,7 @@ namespace elna::boot
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(type_declaration *definition)
 | 
			
		||||
    void name_analysis_visitor::visit(type_declaration *definition)
 | 
			
		||||
    {
 | 
			
		||||
        definition->body().accept(this);
 | 
			
		||||
        auto unresolved_declaration = this->unresolved.at(definition->identifier.identifier);
 | 
			
		||||
@@ -104,7 +116,7 @@ namespace elna::boot
 | 
			
		||||
        unresolved_declaration->reference = this->current_type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(named_type_expression *type_expression)
 | 
			
		||||
    void name_analysis_visitor::visit(named_type_expression *type_expression)
 | 
			
		||||
    {
 | 
			
		||||
        auto unresolved_alias = this->unresolved.find(type_expression->name);
 | 
			
		||||
 | 
			
		||||
@@ -123,19 +135,19 @@ namespace elna::boot
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(pointer_type_expression *type_expression)
 | 
			
		||||
    void name_analysis_visitor::visit(pointer_type_expression *type_expression)
 | 
			
		||||
    {
 | 
			
		||||
        type_expression->base().accept(this);
 | 
			
		||||
        this->current_type = type(std::make_shared<pointer_type>(this->current_type));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(array_type_expression *type_expression)
 | 
			
		||||
    void name_analysis_visitor::visit(array_type_expression *type_expression)
 | 
			
		||||
    {
 | 
			
		||||
        type_expression->base().accept(this);
 | 
			
		||||
        this->current_type = type(std::make_shared<array_type>(this->current_type, type_expression->size));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::vector<type_field> declaration_visitor::build_composite_type(const std::vector<field_declaration>& fields)
 | 
			
		||||
    std::vector<type_field> name_analysis_visitor::build_composite_type(const std::vector<field_declaration>& fields)
 | 
			
		||||
    {
 | 
			
		||||
        std::vector<type_field> result;
 | 
			
		||||
        std::set<std::string> field_names;
 | 
			
		||||
@@ -156,7 +168,7 @@ namespace elna::boot
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(record_type_expression *type_expression)
 | 
			
		||||
    void name_analysis_visitor::visit(record_type_expression *type_expression)
 | 
			
		||||
    {
 | 
			
		||||
        auto result_type = std::make_shared<record_type>();
 | 
			
		||||
 | 
			
		||||
@@ -165,7 +177,7 @@ namespace elna::boot
 | 
			
		||||
        this->current_type = type(result_type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(union_type_expression *type_expression)
 | 
			
		||||
    void name_analysis_visitor::visit(union_type_expression *type_expression)
 | 
			
		||||
    {
 | 
			
		||||
        auto result_type = std::make_shared<union_type>();
 | 
			
		||||
 | 
			
		||||
@@ -174,7 +186,7 @@ namespace elna::boot
 | 
			
		||||
        this->current_type = type(result_type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(procedure_type_expression *type_expression)
 | 
			
		||||
    void name_analysis_visitor::visit(procedure_type_expression *type_expression)
 | 
			
		||||
    {
 | 
			
		||||
        std::shared_ptr<procedure_type> result_type =
 | 
			
		||||
            std::make_shared<procedure_type>(std::move(build_procedure(*type_expression)));
 | 
			
		||||
@@ -182,14 +194,14 @@ namespace elna::boot
 | 
			
		||||
        this->current_type = type(result_type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(enumeration_type_expression *type_expression)
 | 
			
		||||
    void name_analysis_visitor::visit(enumeration_type_expression *type_expression)
 | 
			
		||||
    {
 | 
			
		||||
        std::shared_ptr<enumeration_type> result_type = std::make_shared<enumeration_type>(type_expression->members);
 | 
			
		||||
 | 
			
		||||
        this->current_type = type(result_type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(variable_declaration *declaration)
 | 
			
		||||
    void name_analysis_visitor::visit(variable_declaration *declaration)
 | 
			
		||||
    {
 | 
			
		||||
        declaration->variable_type().accept(this);
 | 
			
		||||
 | 
			
		||||
@@ -197,7 +209,7 @@ namespace elna::boot
 | 
			
		||||
                std::make_shared<variable_info>(this->current_type));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(constant_declaration *definition)
 | 
			
		||||
    void name_analysis_visitor::visit(constant_declaration *definition)
 | 
			
		||||
    {
 | 
			
		||||
        definition->body().accept(this);
 | 
			
		||||
 | 
			
		||||
@@ -205,7 +217,7 @@ namespace elna::boot
 | 
			
		||||
                std::make_shared<constant_info>(this->current_literal));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(procedure_declaration *definition)
 | 
			
		||||
    void name_analysis_visitor::visit(procedure_declaration *definition)
 | 
			
		||||
    {
 | 
			
		||||
        std::shared_ptr<procedure_info> info;
 | 
			
		||||
 | 
			
		||||
@@ -238,13 +250,13 @@ namespace elna::boot
 | 
			
		||||
        this->symbols->enter(definition->identifier.identifier, info);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(assign_statement *statement)
 | 
			
		||||
    void name_analysis_visitor::visit(assign_statement *statement)
 | 
			
		||||
    {
 | 
			
		||||
        statement->lvalue().accept(this);
 | 
			
		||||
        statement->rvalue().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(if_statement *statement)
 | 
			
		||||
    void name_analysis_visitor::visit(if_statement *statement)
 | 
			
		||||
    {
 | 
			
		||||
        statement->body().prerequisite().accept(this);
 | 
			
		||||
        for (struct statement *const statement : statement->body().statements)
 | 
			
		||||
@@ -269,11 +281,11 @@ namespace elna::boot
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(import_declaration *)
 | 
			
		||||
    void name_analysis_visitor::visit(import_declaration *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(while_statement *statement)
 | 
			
		||||
    void name_analysis_visitor::visit(while_statement *statement)
 | 
			
		||||
    {
 | 
			
		||||
        statement->body().prerequisite().accept(this);
 | 
			
		||||
        for (struct statement *const statement : statement->body().statements)
 | 
			
		||||
@@ -291,12 +303,12 @@ namespace elna::boot
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(return_statement *statement)
 | 
			
		||||
    void name_analysis_visitor::visit(return_statement *statement)
 | 
			
		||||
    {
 | 
			
		||||
        statement->return_expression().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(defer_statement *statement)
 | 
			
		||||
    void name_analysis_visitor::visit(defer_statement *statement)
 | 
			
		||||
    {
 | 
			
		||||
        for (struct statement *const statement : statement->statements)
 | 
			
		||||
        {
 | 
			
		||||
@@ -304,7 +316,7 @@ namespace elna::boot
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(case_statement *statement)
 | 
			
		||||
    void name_analysis_visitor::visit(case_statement *statement)
 | 
			
		||||
    {
 | 
			
		||||
        statement->condition().accept(this);
 | 
			
		||||
        for (const switch_case& case_block : statement->cases)
 | 
			
		||||
@@ -327,7 +339,7 @@ namespace elna::boot
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(procedure_call *call)
 | 
			
		||||
    void name_analysis_visitor::visit(procedure_call *call)
 | 
			
		||||
    {
 | 
			
		||||
        call->callable().accept(this);
 | 
			
		||||
        for (expression *const argument: call->arguments)
 | 
			
		||||
@@ -336,18 +348,8 @@ namespace elna::boot
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(unit *unit)
 | 
			
		||||
    void name_analysis_visitor::visit(unit *unit)
 | 
			
		||||
    {
 | 
			
		||||
        for (type_declaration *const type : unit->types)
 | 
			
		||||
        {
 | 
			
		||||
            const std::string& type_identifier = type->identifier.identifier;
 | 
			
		||||
 | 
			
		||||
            if (!this->unresolved.insert({ type_identifier, std::make_shared<alias_type>(type_identifier) }).second
 | 
			
		||||
                    || this->symbols->contains(type_identifier))
 | 
			
		||||
            {
 | 
			
		||||
                add_error<already_declared_error>(type->identifier.identifier, this->input_file, type->position());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        for (type_declaration *const type : unit->types)
 | 
			
		||||
        {
 | 
			
		||||
            type->accept(this);
 | 
			
		||||
@@ -367,7 +369,7 @@ namespace elna::boot
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(traits_expression *trait)
 | 
			
		||||
    void name_analysis_visitor::visit(traits_expression *trait)
 | 
			
		||||
    {
 | 
			
		||||
        if (!trait->parameters.empty())
 | 
			
		||||
        {
 | 
			
		||||
@@ -376,76 +378,239 @@ namespace elna::boot
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(cast_expression *expression)
 | 
			
		||||
    void name_analysis_visitor::visit(cast_expression *expression)
 | 
			
		||||
    {
 | 
			
		||||
        expression->value().accept(this);
 | 
			
		||||
        expression->target().accept(this);
 | 
			
		||||
        expression->expression_type = this->current_type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(binary_expression *expression)
 | 
			
		||||
    void name_analysis_visitor::visit(binary_expression *expression)
 | 
			
		||||
    {
 | 
			
		||||
        expression->lhs().accept(this);
 | 
			
		||||
        expression->rhs().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(unary_expression *expression)
 | 
			
		||||
    void name_analysis_visitor::visit(unary_expression *expression)
 | 
			
		||||
    {
 | 
			
		||||
        expression->operand().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void name_analysis_visitor::visit(variable_expression *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void name_analysis_visitor::visit(array_access_expression *expression)
 | 
			
		||||
    {
 | 
			
		||||
        expression->base().accept(this);
 | 
			
		||||
        expression->index().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void name_analysis_visitor::visit(field_access_expression *expression)
 | 
			
		||||
    {
 | 
			
		||||
        expression->base().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void name_analysis_visitor::visit(dereference_expression *expression)
 | 
			
		||||
    {
 | 
			
		||||
        expression->base().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void name_analysis_visitor::visit(literal<std::int32_t> *literal)
 | 
			
		||||
    {
 | 
			
		||||
        this->current_literal = literal->value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void name_analysis_visitor::visit(literal<std::uint32_t> *literal)
 | 
			
		||||
    {
 | 
			
		||||
        this->current_literal = literal->value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void name_analysis_visitor::visit(literal<double> *literal)
 | 
			
		||||
    {
 | 
			
		||||
        this->current_literal = literal->value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void name_analysis_visitor::visit(literal<bool> *literal)
 | 
			
		||||
    {
 | 
			
		||||
        this->current_literal = literal->value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void name_analysis_visitor::visit(literal<unsigned char> *literal)
 | 
			
		||||
    {
 | 
			
		||||
        this->current_literal = literal->value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void name_analysis_visitor::visit(literal<std::nullptr_t> *literal)
 | 
			
		||||
    {
 | 
			
		||||
        this->current_literal = literal->value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void name_analysis_visitor::visit(literal<std::string> *literal)
 | 
			
		||||
    {
 | 
			
		||||
        this->current_literal = literal->value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    declaration_visitor::declaration_visitor(const char *path)
 | 
			
		||||
        : error_container(path)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(named_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(array_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(pointer_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(program *program)
 | 
			
		||||
    {
 | 
			
		||||
        visit(static_cast<unit *>(program));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(type_declaration *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(record_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(union_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(procedure_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(enumeration_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(variable_declaration *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(constant_declaration *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(procedure_declaration *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(assign_statement *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(if_statement *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(import_declaration *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(while_statement *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(return_statement *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(defer_statement *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(case_statement *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(procedure_call *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(unit *unit)
 | 
			
		||||
    {
 | 
			
		||||
        for (type_declaration *const type : unit->types)
 | 
			
		||||
        {
 | 
			
		||||
            const std::string& type_identifier = type->identifier.identifier;
 | 
			
		||||
 | 
			
		||||
            if (!this->unresolved.insert({ type_identifier, std::make_shared<alias_type>(type_identifier) }).second)
 | 
			
		||||
            {
 | 
			
		||||
                add_error<already_declared_error>(type->identifier.identifier, this->input_file, type->position());
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                type->accept(this);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(cast_expression *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(traits_expression *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(binary_expression *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(unary_expression *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(variable_expression *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(array_access_expression *expression)
 | 
			
		||||
    void declaration_visitor::visit(array_access_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        expression->base().accept(this);
 | 
			
		||||
        expression->index().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(field_access_expression *expression)
 | 
			
		||||
    void declaration_visitor::visit(field_access_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        expression->base().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(dereference_expression *expression)
 | 
			
		||||
    void declaration_visitor::visit(dereference_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        expression->base().accept(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(literal<std::int32_t> *literal)
 | 
			
		||||
    void declaration_visitor::visit(literal<std::int32_t> *)
 | 
			
		||||
    {
 | 
			
		||||
        this->current_literal = literal->value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(literal<std::uint32_t> *literal)
 | 
			
		||||
    void declaration_visitor::visit(literal<std::uint32_t> *)
 | 
			
		||||
    {
 | 
			
		||||
        this->current_literal = literal->value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(literal<double> *literal)
 | 
			
		||||
    void declaration_visitor::visit(literal<double> *)
 | 
			
		||||
    {
 | 
			
		||||
        this->current_literal = literal->value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(literal<bool> *literal)
 | 
			
		||||
    void declaration_visitor::visit(literal<bool> *)
 | 
			
		||||
    {
 | 
			
		||||
        this->current_literal = literal->value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(literal<unsigned char> *literal)
 | 
			
		||||
    void declaration_visitor::visit(literal<unsigned char> *)
 | 
			
		||||
    {
 | 
			
		||||
        this->current_literal = literal->value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(literal<std::nullptr_t> *literal)
 | 
			
		||||
    void declaration_visitor::visit(literal<std::nullptr_t> *)
 | 
			
		||||
    {
 | 
			
		||||
        this->current_literal = literal->value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(literal<std::string> *literal)
 | 
			
		||||
    void declaration_visitor::visit(literal<std::string> *)
 | 
			
		||||
    {
 | 
			
		||||
        this->current_literal = literal->value;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -764,7 +764,7 @@ namespace elna::gcc
 | 
			
		||||
        this->current_expression = NULL_TREE;
 | 
			
		||||
        if (!result)
 | 
			
		||||
        {
 | 
			
		||||
            error_at(declaration_location, "variable '%s' already declared in this scope",
 | 
			
		||||
            error_at(declaration_location, "Variable '%s' already declared in this scope",
 | 
			
		||||
                    declaration->identifier.identifier.c_str());
 | 
			
		||||
        }
 | 
			
		||||
        else if (lang_hooks.decls.global_bindings_p())
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								gcc/elna1.cc
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								gcc/elna1.cc
									
									
									
									
									
								
							@@ -84,16 +84,26 @@ static void elna_parse_file(const char *filename)
 | 
			
		||||
    {
 | 
			
		||||
        for (const std::unique_ptr<elna::boot::program>& module_tree : outcome.modules)
 | 
			
		||||
        {
 | 
			
		||||
            elna::boot::declaration_visitor declaration_visitor(filename, info_table);
 | 
			
		||||
 | 
			
		||||
            elna::boot::declaration_visitor declaration_visitor(filename);
 | 
			
		||||
            declaration_visitor.visit(module_tree.get());
 | 
			
		||||
 | 
			
		||||
            if (declaration_visitor.errors().empty())
 | 
			
		||||
            {
 | 
			
		||||
                elna::gcc::do_semantic_analysis(info_table, symbol_table);
 | 
			
		||||
                elna::boot::name_analysis_visitor name_analysis_visitor(filename, info_table,
 | 
			
		||||
                        std::move(declaration_visitor.unresolved));
 | 
			
		||||
                name_analysis_visitor.visit(module_tree.get());
 | 
			
		||||
 | 
			
		||||
                elna::gcc::generic_visitor generic_visitor{ symbol_table, info_table };
 | 
			
		||||
                generic_visitor.visit(module_tree.get());
 | 
			
		||||
                if (name_analysis_visitor.errors().empty())
 | 
			
		||||
                {
 | 
			
		||||
                    elna::gcc::do_semantic_analysis(info_table, symbol_table);
 | 
			
		||||
 | 
			
		||||
                    elna::gcc::generic_visitor generic_visitor{ symbol_table, info_table };
 | 
			
		||||
                    generic_visitor.visit(module_tree.get());
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    elna::gcc::report_errors(name_analysis_visitor.errors());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ namespace elna::boot
 | 
			
		||||
{
 | 
			
		||||
    class undeclared_error : public error
 | 
			
		||||
    {
 | 
			
		||||
        std::string identifier;
 | 
			
		||||
        const std::string identifier;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        undeclared_error(const std::string& identifier, const char *path, const struct position position);
 | 
			
		||||
@@ -40,7 +40,7 @@ namespace elna::boot
 | 
			
		||||
 | 
			
		||||
    class already_declared_error : public error
 | 
			
		||||
    {
 | 
			
		||||
        std::string identifier;
 | 
			
		||||
        const std::string identifier;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        already_declared_error(const std::string& identifier, const char *path, const struct position position);
 | 
			
		||||
@@ -50,7 +50,7 @@ namespace elna::boot
 | 
			
		||||
 | 
			
		||||
    class field_duplication_error : public error
 | 
			
		||||
    {
 | 
			
		||||
        std::string field_name;
 | 
			
		||||
        const std::string field_name;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        field_duplication_error(const std::string& field_name, const char *path, const struct position);
 | 
			
		||||
@@ -58,7 +58,20 @@ namespace elna::boot
 | 
			
		||||
        std::string what() const override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class declaration_visitor final : public parser_visitor, public error_container
 | 
			
		||||
    class cyclic_declaration_error : public error
 | 
			
		||||
    {
 | 
			
		||||
        const std::vector<std::string> cycle;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        cyclic_declaration_error(const std::vector<std::string>& cycle, const char *path, const struct position);
 | 
			
		||||
 | 
			
		||||
        std::string what() const override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Performs name analysis.
 | 
			
		||||
     */
 | 
			
		||||
    class name_analysis_visitor final : public parser_visitor, public error_container
 | 
			
		||||
    {
 | 
			
		||||
        type current_type;
 | 
			
		||||
        constant_info::variant current_literal;
 | 
			
		||||
@@ -70,7 +83,8 @@ namespace elna::boot
 | 
			
		||||
        std::vector<type_field> build_composite_type(const std::vector<field_declaration>& fields);
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        explicit declaration_visitor(const char *path, std::shared_ptr<symbol_table> symbols);
 | 
			
		||||
        explicit name_analysis_visitor(const char *path, std::shared_ptr<symbol_table> symbols,
 | 
			
		||||
                std::unordered_map<std::string, std::shared_ptr<alias_type>>&& unresolved);
 | 
			
		||||
 | 
			
		||||
        void visit(named_type_expression *type_expression) override;
 | 
			
		||||
        void visit(array_type_expression *type_expression) override;
 | 
			
		||||
@@ -110,4 +124,53 @@ namespace elna::boot
 | 
			
		||||
        void visit(literal<std::nullptr_t> *literal) override;
 | 
			
		||||
        void visit(literal<std::string> *literal) override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Collects global declarations.
 | 
			
		||||
     */
 | 
			
		||||
    class declaration_visitor final : public parser_visitor, public error_container
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        std::unordered_map<std::string, std::shared_ptr<alias_type>> unresolved;
 | 
			
		||||
 | 
			
		||||
        explicit declaration_visitor(const char *path);
 | 
			
		||||
 | 
			
		||||
        void visit(named_type_expression *) override;
 | 
			
		||||
        void visit(array_type_expression *) override;
 | 
			
		||||
        void visit(pointer_type_expression *) override;
 | 
			
		||||
        void visit(program *program) override;
 | 
			
		||||
        void visit(type_declaration *) override;
 | 
			
		||||
        void visit(record_type_expression *) override;
 | 
			
		||||
        void visit(union_type_expression *) override;
 | 
			
		||||
        void visit(procedure_type_expression *) override;
 | 
			
		||||
        void visit(enumeration_type_expression *) override;
 | 
			
		||||
 | 
			
		||||
        void visit(variable_declaration *) override;
 | 
			
		||||
        void visit(constant_declaration *) override;
 | 
			
		||||
        void visit(procedure_declaration *) override;
 | 
			
		||||
        void visit(assign_statement *) override;
 | 
			
		||||
        void visit(if_statement *) override;
 | 
			
		||||
        void visit(import_declaration *) override;
 | 
			
		||||
        void visit(while_statement *) override;
 | 
			
		||||
        void visit(return_statement *) override;
 | 
			
		||||
        void visit(defer_statement *) override;
 | 
			
		||||
        void visit(case_statement *) override;
 | 
			
		||||
        void visit(procedure_call *) override;
 | 
			
		||||
        void visit(unit *unit) override;
 | 
			
		||||
        void visit(cast_expression *) override;
 | 
			
		||||
        void visit(traits_expression *) override;
 | 
			
		||||
        void visit(binary_expression *) override;
 | 
			
		||||
        void visit(unary_expression *) override;
 | 
			
		||||
        void visit(variable_expression *) override;
 | 
			
		||||
        void visit(array_access_expression *) override;
 | 
			
		||||
        void visit(field_access_expression *) override;
 | 
			
		||||
        void visit(dereference_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;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user