Remove type visiting in generic visitor
This commit is contained in:
		
							
								
								
									
										185
									
								
								boot/ast.cc
									
									
									
									
									
								
							
							
						
						
									
										185
									
								
								boot/ast.cc
									
									
									
									
									
								
							@@ -19,6 +19,191 @@ along with GCC; see the file COPYING3.  If not see
 | 
			
		||||
 | 
			
		||||
namespace elna::boot
 | 
			
		||||
{
 | 
			
		||||
    void empty_visitor::not_implemented()
 | 
			
		||||
    {
 | 
			
		||||
        __builtin_unreachable();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(named_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(array_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(pointer_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(program *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(type_declaration *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(record_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(union_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(procedure_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(enumeration_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(variable_declaration *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(constant_declaration *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(procedure_declaration *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(assign_statement *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(if_statement *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(import_declaration *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(while_statement *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(return_statement *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(defer_statement *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(case_statement *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(procedure_call *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(unit *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(cast_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(traits_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(binary_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(unary_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(variable_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(array_access_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(field_access_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(dereference_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(literal<std::int32_t> *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(literal<std::uint32_t> *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(literal<double> *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(literal<bool> *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(literal<unsigned char> *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(literal<std::nullptr_t> *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(literal<std::string> *)
 | 
			
		||||
    {
 | 
			
		||||
        not_implemented();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    node::node(const struct position position)
 | 
			
		||||
        : source_position(position)
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ namespace elna::boot
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dependency read_sources(std::istream& entry_point, const char *entry_path)
 | 
			
		||||
    dependency read_source(std::istream& entry_point, const char *entry_path)
 | 
			
		||||
    {
 | 
			
		||||
        driver parse_driver{ entry_path };
 | 
			
		||||
        lexer tokenizer(entry_point);
 | 
			
		||||
@@ -60,6 +60,25 @@ namespace elna::boot
 | 
			
		||||
        return outcome;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    error_list analyze_semantics(const char *path, std::unique_ptr<unit>& tree, symbol_bag bag)
 | 
			
		||||
    {
 | 
			
		||||
        name_analysis_visitor name_analyser(path, bag);
 | 
			
		||||
        tree->accept(&name_analyser);
 | 
			
		||||
 | 
			
		||||
        if (name_analyser.has_errors())
 | 
			
		||||
        {
 | 
			
		||||
            return std::move(name_analyser.errors());
 | 
			
		||||
        }
 | 
			
		||||
        type_analysis_visitor type_analyzer(path);
 | 
			
		||||
        tree->accept(&type_analyzer);
 | 
			
		||||
 | 
			
		||||
        if (type_analyzer.has_errors())
 | 
			
		||||
        {
 | 
			
		||||
            return std::move(type_analyzer.errors());
 | 
			
		||||
        }
 | 
			
		||||
        return error_list{};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::filesystem::path build_path(const std::vector<std::string>& segments)
 | 
			
		||||
    {
 | 
			
		||||
        std::filesystem::path result;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										210
									
								
								boot/semantic.cc
									
									
									
									
									
								
							
							
						
						
									
										210
									
								
								boot/semantic.cc
									
									
									
									
									
								
							@@ -32,7 +32,6 @@ namespace elna::boot
 | 
			
		||||
        return "Type '" + identifier + "' not declared";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    already_declared_error::already_declared_error(const std::string& identifier,
 | 
			
		||||
            const char *path, const struct position position)
 | 
			
		||||
        : error(path, position), identifier(identifier)
 | 
			
		||||
@@ -74,6 +73,83 @@ namespace elna::boot
 | 
			
		||||
        return message;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return_error::return_error(const std::string& identifier, const char *path, const struct position position)
 | 
			
		||||
        : error(path, position), identifier(identifier)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string return_error::what() const
 | 
			
		||||
    {
 | 
			
		||||
        return "Procedure '" + identifier + "' is expected to return, but does not have a return statement";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    type_analysis_visitor::type_analysis_visitor(const char *path)
 | 
			
		||||
        : error_container(path)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void type_analysis_visitor::visit(program *program)
 | 
			
		||||
    {
 | 
			
		||||
        visit(static_cast<unit *>(program));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void type_analysis_visitor::visit(procedure_declaration *definition)
 | 
			
		||||
    {
 | 
			
		||||
        if (definition->body.has_value() && definition->heading().return_type.proper_type != nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            for (statement *const statement : definition->body.value().body())
 | 
			
		||||
            {
 | 
			
		||||
                statement->accept(this);
 | 
			
		||||
            }
 | 
			
		||||
            if (!this->returns)
 | 
			
		||||
            {
 | 
			
		||||
                add_error<return_error>(definition->identifier.identifier, this->input_file, definition->position());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void type_analysis_visitor::visit(assign_statement *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void type_analysis_visitor::visit(if_statement *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void type_analysis_visitor::visit(import_declaration *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void type_analysis_visitor::visit(while_statement *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void type_analysis_visitor::visit(return_statement *)
 | 
			
		||||
    {
 | 
			
		||||
        this->returns = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void type_analysis_visitor::visit(defer_statement *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void type_analysis_visitor::visit(case_statement *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void type_analysis_visitor::visit(procedure_call *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void type_analysis_visitor::visit(unit *unit)
 | 
			
		||||
    {
 | 
			
		||||
        for (procedure_declaration *const procedure : unit->procedures)
 | 
			
		||||
        {
 | 
			
		||||
            this->returns = false;
 | 
			
		||||
            procedure->accept(this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    name_analysis_visitor::name_analysis_visitor(const char *path, symbol_bag bag)
 | 
			
		||||
        : error_container(path), bag(bag)
 | 
			
		||||
    {
 | 
			
		||||
@@ -484,87 +560,15 @@ namespace elna::boot
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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 (import_declaration *const _import : unit->imports)
 | 
			
		||||
@@ -581,64 +585,4 @@ namespace elna::boot
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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 *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(field_access_expression *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(dereference_expression *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(literal<std::int32_t> *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(literal<std::uint32_t> *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(literal<double> *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(literal<bool> *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(literal<unsigned char> *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(literal<std::nullptr_t> *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(literal<std::string> *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -77,7 +77,7 @@ namespace elna::gcc
 | 
			
		||||
 | 
			
		||||
        if (!VOID_TYPE_P(TREE_VALUE(current_parameter)))
 | 
			
		||||
        {
 | 
			
		||||
                error_at(call_location, "too few arguments, expected %i, got %lu",
 | 
			
		||||
                error_at(call_location, "Too few arguments, expected %i, got %lu",
 | 
			
		||||
                        list_length(TYPE_ARG_TYPES(symbol_type)) - 1, arguments.size());
 | 
			
		||||
                this->current_expression = error_mark_node;
 | 
			
		||||
        }
 | 
			
		||||
@@ -1179,46 +1179,6 @@ namespace elna::gcc
 | 
			
		||||
        this->current_expression = NULL_TREE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(boot::named_type_expression *type)
 | 
			
		||||
    {
 | 
			
		||||
        this->current_expression = TREE_TYPE(this->symbols->lookup(type->name));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(boot::array_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        gcc_unreachable();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(boot::pointer_type_expression *type)
 | 
			
		||||
    {
 | 
			
		||||
        type->base().accept(this);
 | 
			
		||||
 | 
			
		||||
        if (this->current_expression != NULL_TREE && this->current_expression != error_mark_node)
 | 
			
		||||
        {
 | 
			
		||||
            this->current_expression = build_global_pointer_type(this->current_expression);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(boot::record_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        gcc_unreachable();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(boot::union_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        gcc_unreachable();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(boot::procedure_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        gcc_unreachable();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(boot::enumeration_type_expression *)
 | 
			
		||||
    {
 | 
			
		||||
        gcc_unreachable();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(boot::defer_statement *statement)
 | 
			
		||||
    {
 | 
			
		||||
        enter_scope();
 | 
			
		||||
 
 | 
			
		||||
@@ -74,7 +74,7 @@ static elna::boot::dependency elna_parse_file(dependency_state& state, const cha
 | 
			
		||||
        fatal_error(UNKNOWN_LOCATION, "Cannot open filename %s: %m", filename);
 | 
			
		||||
    }
 | 
			
		||||
    linemap_add(line_table, LC_ENTER, 0, filename, 1);
 | 
			
		||||
    elna::boot::dependency outcome = elna::boot::read_sources(entry_point, filename);
 | 
			
		||||
    elna::boot::dependency outcome = elna::boot::read_source(entry_point, filename);
 | 
			
		||||
 | 
			
		||||
    if (outcome.has_errors())
 | 
			
		||||
    {
 | 
			
		||||
@@ -92,12 +92,11 @@ static elna::boot::dependency elna_parse_file(dependency_state& state, const cha
 | 
			
		||||
        }
 | 
			
		||||
        outcome_bag.add_import(state.cache.find(sub_path)->second);
 | 
			
		||||
    }
 | 
			
		||||
    elna::boot::name_analysis_visitor name_analysis_visitor(filename, outcome_bag);
 | 
			
		||||
    outcome.tree->accept(&name_analysis_visitor);
 | 
			
		||||
    elna::boot::error_list semantic_errors = analyze_semantics(filename, outcome.tree, outcome_bag);
 | 
			
		||||
 | 
			
		||||
    if (name_analysis_visitor.has_errors())
 | 
			
		||||
    if (!semantic_errors.empty())
 | 
			
		||||
    {
 | 
			
		||||
        elna::gcc::report_errors(name_analysis_visitor.errors());
 | 
			
		||||
        elna::gcc::report_errors(semantic_errors);
 | 
			
		||||
    }
 | 
			
		||||
    state.cache.insert({ filename, outcome_bag });
 | 
			
		||||
    elna::gcc::rewrite_symbol_table(module_table, state.custom);
 | 
			
		||||
 
 | 
			
		||||
@@ -131,6 +131,53 @@ namespace elna::boot
 | 
			
		||||
        virtual void visit(literal<std::string> *) = 0;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Abstract visitor that doesn't visit any nodes by default.
 | 
			
		||||
     */
 | 
			
		||||
    class empty_visitor : public parser_visitor
 | 
			
		||||
    {
 | 
			
		||||
        [[noreturn]] void not_implemented();
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        [[noreturn]] virtual void visit(named_type_expression *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(array_type_expression *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(pointer_type_expression *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(program *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(type_declaration *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(record_type_expression *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(union_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;
 | 
			
		||||
        [[noreturn]] virtual void visit(import_declaration *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(while_statement *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(return_statement *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(defer_statement *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(case_statement *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(procedure_call *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(unit *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(cast_expression *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(traits_expression *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(binary_expression *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(unary_expression *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(variable_expression *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(array_access_expression *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(field_access_expression *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(dereference_expression *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(literal<std::int32_t> *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(literal<std::uint32_t> *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(literal<double> *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(literal<bool> *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(literal<unsigned char> *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(literal<std::nullptr_t> *) override;
 | 
			
		||||
        [[noreturn]] virtual void visit(literal<std::string> *) override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * AST node.
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -35,15 +35,16 @@ namespace elna::boot
 | 
			
		||||
        explicit dependency(const char *path);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    dependency read_sources(std::istream& entry_point, const char *entry_path);
 | 
			
		||||
    dependency read_source(std::istream& entry_point, const char *entry_path);
 | 
			
		||||
    std::filesystem::path build_path(const std::vector<std::string>& segments);
 | 
			
		||||
    error_list analyze_semantics(const char *path, std::unique_ptr<unit>& tree, symbol_bag bag);
 | 
			
		||||
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    struct dependency_state
 | 
			
		||||
    {
 | 
			
		||||
        const std::shared_ptr<symbol_table> globals;
 | 
			
		||||
        T custom;
 | 
			
		||||
        std::unordered_map<std::filesystem::path, elna::boot::symbol_bag> cache;
 | 
			
		||||
        std::unordered_map<std::filesystem::path, symbol_bag> cache;
 | 
			
		||||
 | 
			
		||||
        explicit dependency_state(T custom)
 | 
			
		||||
            : globals(elna::boot::builtin_symbol_table()), custom(custom)
 | 
			
		||||
 
 | 
			
		||||
@@ -69,6 +69,40 @@ namespace elna::boot
 | 
			
		||||
        std::string what() const override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class return_error : public error
 | 
			
		||||
    {
 | 
			
		||||
        const std::string identifier;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        return_error(const std::string& identifier, const char *path, const struct position position);
 | 
			
		||||
 | 
			
		||||
        std::string what() const override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks types.
 | 
			
		||||
     */
 | 
			
		||||
    class type_analysis_visitor final : public empty_visitor, public error_container
 | 
			
		||||
    {
 | 
			
		||||
        bool returns;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        explicit type_analysis_visitor(const char *path);
 | 
			
		||||
 | 
			
		||||
        void visit(program *program) override;
 | 
			
		||||
 | 
			
		||||
        void visit(procedure_declaration *definition) 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;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Performs name analysis.
 | 
			
		||||
     */
 | 
			
		||||
@@ -128,51 +162,17 @@ namespace elna::boot
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Collects global declarations.
 | 
			
		||||
     * Collects global declarations without resolving any symbols.
 | 
			
		||||
     */
 | 
			
		||||
    class declaration_visitor final : public parser_visitor, public error_container
 | 
			
		||||
    class declaration_visitor final : public empty_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;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 | 
			
		||||
 | 
			
		||||
namespace elna::gcc
 | 
			
		||||
{
 | 
			
		||||
    class generic_visitor final : public boot::parser_visitor
 | 
			
		||||
    class generic_visitor final : public boot::empty_visitor
 | 
			
		||||
    {
 | 
			
		||||
        tree current_expression{ NULL_TREE };
 | 
			
		||||
        elna::boot::symbol_bag bag;
 | 
			
		||||
@@ -91,13 +91,6 @@ namespace elna::gcc
 | 
			
		||||
        void visit(boot::if_statement *statement) override;
 | 
			
		||||
        void visit(boot::import_declaration *) override;
 | 
			
		||||
        void visit(boot::while_statement *statement) override;
 | 
			
		||||
        void visit(boot::named_type_expression *type) override;
 | 
			
		||||
        void visit(boot::array_type_expression *) override;
 | 
			
		||||
        void visit(boot::pointer_type_expression *type) override;
 | 
			
		||||
        void visit(boot::record_type_expression *) override;
 | 
			
		||||
        void visit(boot::union_type_expression *) override;
 | 
			
		||||
        void visit(boot::procedure_type_expression *) override;
 | 
			
		||||
        void visit(boot::enumeration_type_expression *) override;
 | 
			
		||||
        void visit(boot::return_statement *statement) override;
 | 
			
		||||
        void visit(boot::defer_statement *statement) override;
 | 
			
		||||
        void visit(boot::case_statement *statement) override;
 | 
			
		||||
 
 | 
			
		||||
@@ -1074,12 +1074,6 @@ begin
 | 
			
		||||
  return return_code
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
proc f();
 | 
			
		||||
var x: Char;
 | 
			
		||||
begin
 | 
			
		||||
  x := '\x4'
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
begin
 | 
			
		||||
  exit(process(count, parameters))
 | 
			
		||||
end.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user