Create a generic type for types with an error list
This commit is contained in:
		@@ -42,20 +42,10 @@ namespace boot
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    driver::driver(const char *input_file)
 | 
			
		||||
        : input_file(input_file)
 | 
			
		||||
        : error_container(input_file)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void driver::error(const yy::location& loc, const std::string& message)
 | 
			
		||||
    {
 | 
			
		||||
        m_errors.emplace_back(new boot::syntax_error(message, input_file, loc));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const std::list<std::unique_ptr<struct error>>& driver::errors() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return m_errors;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    char escape_char(char escape)
 | 
			
		||||
    {
 | 
			
		||||
        switch (escape)
 | 
			
		||||
 
 | 
			
		||||
@@ -290,6 +290,6 @@ defer                   {
 | 
			
		||||
                            std::stringstream ss;
 | 
			
		||||
 | 
			
		||||
                            ss << "Illegal character 0x" << std::hex << static_cast<unsigned int>(yytext[0]);
 | 
			
		||||
                            driver.error(this->location, ss.str());
 | 
			
		||||
                            driver.add_error<elna::boot::syntax_error>(ss.str(), driver.input_file, this->location);
 | 
			
		||||
                        }
 | 
			
		||||
%%
 | 
			
		||||
 
 | 
			
		||||
@@ -578,5 +578,5 @@ actual_parameter_list:
 | 
			
		||||
 | 
			
		||||
void yy::parser::error(const location_type& loc, const std::string& message)
 | 
			
		||||
{
 | 
			
		||||
    driver.error(loc, message);
 | 
			
		||||
    driver.add_error<elna::boot::syntax_error>(message, driver.input_file, loc);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -35,5 +35,15 @@ namespace boot
 | 
			
		||||
    {
 | 
			
		||||
        return this->position.column;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    error_container::error_container(const char *input_file)
 | 
			
		||||
        : input_file(input_file)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::deque<std::unique_ptr<error>>& error_container::errors()
 | 
			
		||||
    {
 | 
			
		||||
        return m_errors;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ namespace boot
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    declaration_visitor::declaration_visitor(const char *path, std::shared_ptr<symbol_table> symbols)
 | 
			
		||||
        : path(path), symbols(symbols)
 | 
			
		||||
        : error_container(path), symbols(symbols)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -66,10 +66,8 @@ namespace boot
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            auto new_error = std::make_unique<declaration_error>(type_expression->name,
 | 
			
		||||
                    path, type_expression->position());
 | 
			
		||||
            this->errors.emplace_back(std::move(new_error));
 | 
			
		||||
            // TODO: Delete the next line.
 | 
			
		||||
            // TODO:
 | 
			
		||||
            // add_error<declaration_error>(type_expression->name, this->input_file, type_expression->position());
 | 
			
		||||
            this->current_type = type(std::make_shared<primitive_type>(type_expression->name));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -133,5 +133,15 @@ namespace gcc
 | 
			
		||||
        }
 | 
			
		||||
        gcc_unreachable();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void report_errors(const std::deque<std::unique_ptr<boot::error>>& errors)
 | 
			
		||||
    {
 | 
			
		||||
        for (const auto& error : errors)
 | 
			
		||||
        {
 | 
			
		||||
            auto gcc_location = elna::gcc::get_location(&error->position);
 | 
			
		||||
 | 
			
		||||
            error_at(gcc_location, error->what().c_str());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -63,18 +63,23 @@ namespace gcc
 | 
			
		||||
        return error_mark_node;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void do_semantic_analysis(const char *path, std::unique_ptr<boot::program>& ast,
 | 
			
		||||
            std::shared_ptr<symbol_table> symbols)
 | 
			
		||||
    std::deque<std::unique_ptr<boot::error>> do_semantic_analysis(const char *path,
 | 
			
		||||
            std::unique_ptr<boot::program>& ast, std::shared_ptr<symbol_table> symbols)
 | 
			
		||||
    {
 | 
			
		||||
        auto info_table = boot::builtin_symbol_table();
 | 
			
		||||
        boot::declaration_visitor declaration_visitor(path, info_table);
 | 
			
		||||
 | 
			
		||||
        declaration_visitor.visit(ast.get());
 | 
			
		||||
        for (auto unresolved : declaration_visitor.unresolved)
 | 
			
		||||
 | 
			
		||||
        if (declaration_visitor.errors().empty())
 | 
			
		||||
        {
 | 
			
		||||
            auto inner_alias = get_inner_alias(symbols, boot::type(unresolved.second));
 | 
			
		||||
            symbols->enter(unresolved.first, inner_alias);
 | 
			
		||||
            for (auto unresolved : declaration_visitor.unresolved)
 | 
			
		||||
            {
 | 
			
		||||
                auto inner_alias = get_inner_alias(symbols, boot::type(unresolved.second));
 | 
			
		||||
                symbols->enter(unresolved.first, inner_alias);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return std::move(declaration_visitor.errors());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    generic_visitor::generic_visitor(std::shared_ptr<symbol_table> symbol_table)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								gcc/elna1.cc
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								gcc/elna1.cc
									
									
									
									
									
								
							@@ -79,12 +79,7 @@ static void elna_parse_file(const char *filename)
 | 
			
		||||
    linemap_add(line_table, LC_ENTER, 0, filename, 1);
 | 
			
		||||
    if (parser())
 | 
			
		||||
    {
 | 
			
		||||
        for (const auto& error : driver.errors())
 | 
			
		||||
        {
 | 
			
		||||
            auto gcc_location = elna::gcc::get_location(&error->position);
 | 
			
		||||
 | 
			
		||||
            error_at(gcc_location, error->what().c_str());
 | 
			
		||||
        }
 | 
			
		||||
        elna::gcc::report_errors(driver.errors());
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
@@ -98,10 +93,17 @@ static void elna_parse_file(const char *filename)
 | 
			
		||||
        symbol_table->enter("Float", elna_float_type_node);
 | 
			
		||||
        symbol_table->enter("String", elna_string_type_node);
 | 
			
		||||
 | 
			
		||||
        elna::gcc::do_semantic_analysis(filename, driver.tree, symbol_table);
 | 
			
		||||
        elna::gcc::generic_visitor generic_visitor{ symbol_table };
 | 
			
		||||
        auto semantic_errors = elna::gcc::do_semantic_analysis(filename, driver.tree, symbol_table);
 | 
			
		||||
 | 
			
		||||
        generic_visitor.visit(driver.tree.get());
 | 
			
		||||
        if (semantic_errors.empty())
 | 
			
		||||
        {
 | 
			
		||||
            elna::gcc::generic_visitor generic_visitor{ symbol_table };
 | 
			
		||||
            generic_visitor.visit(driver.tree.get());
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            elna::gcc::report_errors(semantic_errors);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,6 @@ along with GCC; see the file COPYING3.  If not see
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include "elna/boot/ast.h"
 | 
			
		||||
#include "location.hh"
 | 
			
		||||
@@ -39,18 +38,12 @@ namespace boot
 | 
			
		||||
        virtual std::string what() const override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class driver
 | 
			
		||||
    class driver : public error_container
 | 
			
		||||
    {
 | 
			
		||||
        std::list<std::unique_ptr<struct error>> m_errors;
 | 
			
		||||
        const char *input_file;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        std::unique_ptr<program> tree;
 | 
			
		||||
 | 
			
		||||
        driver(const char *input_file);
 | 
			
		||||
 | 
			
		||||
        void error(const yy::location& loc, const std::string& message);
 | 
			
		||||
        const std::list<std::unique_ptr<struct error>>& errors() const noexcept;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    constexpr char escape_invalid_char = '\xff';
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,8 @@ along with GCC; see the file COPYING3.  If not see
 | 
			
		||||
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <deque>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
namespace elna
 | 
			
		||||
{
 | 
			
		||||
@@ -59,5 +61,25 @@ namespace boot
 | 
			
		||||
        /// Error column in the source text.
 | 
			
		||||
        std::size_t column() const;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class error_container
 | 
			
		||||
    {
 | 
			
		||||
    protected:
 | 
			
		||||
        std::deque<std::unique_ptr<error>> m_errors;
 | 
			
		||||
 | 
			
		||||
        error_container(const char *input_file);
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        const char *input_file;
 | 
			
		||||
 | 
			
		||||
        std::deque<std::unique_ptr<error>>& errors();
 | 
			
		||||
 | 
			
		||||
        template<typename T, typename... Args>
 | 
			
		||||
        void add_error(Args... arguments)
 | 
			
		||||
        {
 | 
			
		||||
            auto new_error = std::make_unique<T>(arguments...);
 | 
			
		||||
            m_errors.emplace_back(std::move(new_error));
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ along with GCC; see the file COPYING3.  If not see
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <deque>
 | 
			
		||||
 | 
			
		||||
#include "elna/boot/ast.h"
 | 
			
		||||
#include "elna/boot/result.h"
 | 
			
		||||
@@ -37,12 +38,10 @@ namespace boot
 | 
			
		||||
        virtual std::string what() const override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class declaration_visitor final : public empty_visitor
 | 
			
		||||
    class declaration_visitor final : public empty_visitor, public error_container
 | 
			
		||||
    {
 | 
			
		||||
        type current_type;
 | 
			
		||||
        const char *path;
 | 
			
		||||
        symbol_table symbols;
 | 
			
		||||
        std::vector<std::unique_ptr<error>> errors;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        std::unordered_map<std::string, std::shared_ptr<alias_type>> unresolved;
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,10 @@ along with GCC; see the file COPYING3.  If not see
 | 
			
		||||
#include "coretypes.h"
 | 
			
		||||
#include "input.h"
 | 
			
		||||
#include "tree.h"
 | 
			
		||||
#include "diagnostic.h"
 | 
			
		||||
 | 
			
		||||
#include <deque>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
#include "elna/boot/result.h"
 | 
			
		||||
 | 
			
		||||
@@ -30,7 +34,7 @@ namespace elna
 | 
			
		||||
namespace gcc
 | 
			
		||||
{
 | 
			
		||||
    location_t get_location(const boot::position *position);
 | 
			
		||||
 | 
			
		||||
    std::string print_type(tree type);
 | 
			
		||||
    void report_errors(const std::deque<std::unique_ptr<boot::error>>& errors);
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -34,8 +34,8 @@ namespace elna
 | 
			
		||||
{
 | 
			
		||||
namespace gcc
 | 
			
		||||
{
 | 
			
		||||
    void do_semantic_analysis(const char *path, std::unique_ptr<boot::program>& ast,
 | 
			
		||||
            std::shared_ptr<symbol_table> symbols);
 | 
			
		||||
    std::deque<std::unique_ptr<boot::error>> do_semantic_analysis(const char *path,
 | 
			
		||||
            std::unique_ptr<boot::program>& ast, std::shared_ptr<symbol_table> symbols);
 | 
			
		||||
 | 
			
		||||
    class generic_visitor final : public boot::empty_visitor
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user