Type check the return statement
This commit is contained in:
		
							
								
								
									
										191
									
								
								boot/ast.cc
									
									
									
									
									
								
							
							
						
						
									
										191
									
								
								boot/ast.cc
									
									
									
									
									
								
							@@ -33,14 +33,6 @@ namespace elna::boot
 | 
				
			|||||||
        return this->source_position;
 | 
					        return this->source_position;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    statement::statement()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    statement::~statement()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    assign_statement *statement::is_assign()
 | 
					    assign_statement *statement::is_assign()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return nullptr;
 | 
					        return nullptr;
 | 
				
			||||||
@@ -71,14 +63,6 @@ namespace elna::boot
 | 
				
			|||||||
        return nullptr;
 | 
					        return nullptr;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    expression::expression()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    expression::~expression()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cast_expression *expression::is_cast()
 | 
					    cast_expression *expression::is_cast()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return nullptr;
 | 
					        return nullptr;
 | 
				
			||||||
@@ -114,39 +98,6 @@ namespace elna::boot
 | 
				
			|||||||
        return nullptr;
 | 
					        return nullptr;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void expression::accept(parser_visitor *visitor)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (cast_expression *node = is_cast())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (traits_expression *node = is_traits())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (binary_expression *node = is_binary())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (unary_expression *node = is_unary())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (designator_expression *node = is_designator())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (procedure_call *node = is_call_expression())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (literal_expression *node = is_literal())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        __builtin_unreachable();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    type_expression::type_expression(const struct position position)
 | 
					    type_expression::type_expression(const struct position position)
 | 
				
			||||||
        : node(position)
 | 
					        : node(position)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -182,35 +133,6 @@ namespace elna::boot
 | 
				
			|||||||
        return nullptr;
 | 
					        return nullptr;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void type_expression::accept(parser_visitor *visitor)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (std::shared_ptr<primitive_type_expression> node = is_primitive())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (std::shared_ptr<array_type_expression> node = is_array())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (std::shared_ptr<pointer_type_expression> node = is_pointer())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (std::shared_ptr<record_type_expression> node = is_record())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (std::shared_ptr<union_type_expression> node = is_union())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (std::shared_ptr<procedure_type_expression> node = is_procedure())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        __builtin_unreachable();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    primitive_type_expression::primitive_type_expression(const struct position position, const std::string& name)
 | 
					    primitive_type_expression::primitive_type_expression(const struct position position, const std::string& name)
 | 
				
			||||||
        : type_expression(position), name(name)
 | 
					        : type_expression(position), name(name)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -301,8 +223,8 @@ namespace elna::boot
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    variable_declaration::variable_declaration(const struct position position, const std::string& identifier,
 | 
					    variable_declaration::variable_declaration(const struct position position, const std::string& identifier,
 | 
				
			||||||
            std::shared_ptr<type_expression> type, const bool exported)
 | 
					            std::shared_ptr<type_expression> variable_type, const bool exported)
 | 
				
			||||||
        : definition(position, identifier, exported), m_type(type)
 | 
					        : definition(position, identifier, exported), m_variable_type(variable_type)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -313,7 +235,7 @@ namespace elna::boot
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    type_expression& variable_declaration::variable_type()
 | 
					    type_expression& variable_declaration::variable_type()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return *m_type;
 | 
					        return *m_variable_type;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    definition::definition(const struct position position, const std::string& identifier, const bool exported)
 | 
					    definition::definition(const struct position position, const std::string& identifier, const bool exported)
 | 
				
			||||||
@@ -462,47 +384,16 @@ namespace elna::boot
 | 
				
			|||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void literal_expression::accept(parser_visitor *visitor)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (literal<std::int32_t> *node = is_int())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (literal<std::uint32_t> *node = is_word())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (literal<double> *node = is_float())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (literal<bool> *node = is_bool())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (literal<unsigned char> *node = is_char())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (literal<std::nullptr_t> *node = is_nil())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (literal<std::string> *node = is_string())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return node->accept(visitor);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            __builtin_unreachable();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    defer_statement::defer_statement(const struct position position)
 | 
					    defer_statement::defer_statement(const struct position position)
 | 
				
			||||||
        : node(position)
 | 
					        : node(position)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void defer_statement::accept(parser_visitor *visitor)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        visitor->visit(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    defer_statement *defer_statement::is_defer()
 | 
					    defer_statement *defer_statement::is_defer()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
@@ -529,11 +420,37 @@ namespace elna::boot
 | 
				
			|||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void designator_expression::accept(parser_visitor *visitor)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (variable_expression *node = is_variable())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return visitor->visit(node);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (array_access_expression *node = is_array_access())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return visitor->visit(node);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (field_access_expression *node = is_field_access())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return visitor->visit(node);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (dereference_expression *node = is_dereference())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return visitor->visit(node);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        __builtin_unreachable();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    variable_expression::variable_expression(const struct position position, const std::string& name)
 | 
					    variable_expression::variable_expression(const struct position position, const std::string& name)
 | 
				
			||||||
        : node(position), name(name)
 | 
					        : node(position), name(name)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void variable_expression::accept(parser_visitor *visitor)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        visitor->visit(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    variable_expression *variable_expression::is_variable()
 | 
					    variable_expression *variable_expression::is_variable()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
@@ -545,6 +462,11 @@ namespace elna::boot
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void array_access_expression::accept(parser_visitor *visitor)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        visitor->visit(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    expression& array_access_expression::index()
 | 
					    expression& array_access_expression::index()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return *m_index;
 | 
					        return *m_index;
 | 
				
			||||||
@@ -572,6 +494,11 @@ namespace elna::boot
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void field_access_expression::accept(parser_visitor *visitor)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        visitor->visit(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    expression& field_access_expression::base()
 | 
					    expression& field_access_expression::base()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return *m_base;
 | 
					        return *m_base;
 | 
				
			||||||
@@ -598,6 +525,11 @@ namespace elna::boot
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void dereference_expression::accept(parser_visitor *visitor)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        visitor->visit(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    expression& dereference_expression::base()
 | 
					    expression& dereference_expression::base()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return *m_base;
 | 
					        return *m_base;
 | 
				
			||||||
@@ -686,6 +618,11 @@ namespace elna::boot
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void procedure_call::accept(parser_visitor *visitor)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        visitor->visit(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    procedure_call *procedure_call::is_call_statement()
 | 
					    procedure_call *procedure_call::is_call_statement()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
@@ -780,6 +717,11 @@ namespace elna::boot
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void return_statement::accept(parser_visitor *visitor)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        visitor->visit(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return_statement *return_statement::is_return()
 | 
					    return_statement *return_statement::is_return()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
@@ -801,6 +743,11 @@ namespace elna::boot
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void assign_statement::accept(parser_visitor *visitor)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        visitor->visit(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assign_statement *assign_statement::is_assign()
 | 
					    assign_statement *assign_statement::is_assign()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
@@ -847,6 +794,11 @@ namespace elna::boot
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void if_statement::accept(parser_visitor *visitor)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        visitor->visit(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if_statement *if_statement::is_if()
 | 
					    if_statement *if_statement::is_if()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
@@ -877,6 +829,11 @@ namespace elna::boot
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void while_statement::accept(parser_visitor *visitor)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        visitor->visit(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while_statement *while_statement::is_while()
 | 
					    while_statement *while_statement::is_while()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -286,10 +286,15 @@ if_statement:
 | 
				
			|||||||
            $$ = new boot::if_statement(boot::make_position(@1), then, _else);
 | 
					            $$ = new boot::if_statement(boot::make_position(@1), then, _else);
 | 
				
			||||||
            std::swap($5, $$->branches);
 | 
					            std::swap($5, $$->branches);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
return_statement: "return" expression
 | 
					return_statement:
 | 
				
			||||||
 | 
					    "return" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new boot::return_statement(boot::make_position(@1), $2);
 | 
					            $$ = new boot::return_statement(boot::make_position(@1), $2);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    | "return"
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            $$ = new boot::return_statement(boot::make_position(@1));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
defer_statement: DEFER statements "end"
 | 
					defer_statement: DEFER statements "end"
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new boot::defer_statement(boot::make_position(@1));
 | 
					            $$ = new boot::defer_statement(boot::make_position(@1));
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										157
									
								
								boot/semantic.cc
									
									
									
									
									
								
							
							
						
						
									
										157
									
								
								boot/semantic.cc
									
									
									
									
									
								
							@@ -65,6 +65,18 @@ namespace elna::boot
 | 
				
			|||||||
            auto info = std::make_shared<type_info>(type_info(type(unresolved.second)));
 | 
					            auto info = std::make_shared<type_info>(type_info(type(unresolved.second)));
 | 
				
			||||||
            this->symbols->enter(std::move(unresolved.first), info);
 | 
					            this->symbols->enter(std::move(unresolved.first), info);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        for (variable_declaration *const variable : program->variables)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            variable->accept(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for (procedure_definition *const procedure : program->procedures)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            procedure->accept(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for (statement *const statement : program->body)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            statement->accept(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(type_definition *definition)
 | 
					    void declaration_visitor::visit(type_definition *definition)
 | 
				
			||||||
@@ -120,128 +132,191 @@ namespace elna::boot
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(variable_declaration *)
 | 
					    void declaration_visitor::visit(variable_declaration *declaration)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					        declaration->variable_type().accept(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(constant_definition *)
 | 
					    void declaration_visitor::visit(constant_definition *)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(procedure_definition *)
 | 
					    void declaration_visitor::visit(procedure_definition *definition)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					        for (auto heading_parameter : definition->heading().parameters)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            heading_parameter->accept(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (definition->heading().return_type.type != nullptr)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            definition->heading().return_type.type->accept(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (definition->body != nullptr)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            definition->body->accept(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(assign_statement *)
 | 
					    void declaration_visitor::visit(assign_statement *statement)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					        statement->lvalue().accept(this);
 | 
				
			||||||
 | 
					        statement->rvalue().accept(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(if_statement *)
 | 
					    void declaration_visitor::visit(if_statement *statement)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					        statement->body().prerequisite().accept(this);
 | 
				
			||||||
 | 
					        for (struct statement *const statement : statement->body().statements)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            statement->accept(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for (const auto branch : statement->branches)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            branch->prerequisite().accept(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (struct statement *const statement : branch->statements)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                statement->accept(this);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (statement->alternative() != nullptr)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            for (struct statement *const statement : *statement->alternative())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                statement->accept(this);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(while_statement *)
 | 
					    void declaration_visitor::visit(while_statement *statement)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					        statement->body().prerequisite().accept(this);
 | 
				
			||||||
 | 
					        for (struct statement *const statement : statement->body().statements)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            statement->accept(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for (const auto branch : statement->branches)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            branch->prerequisite().accept(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (struct statement *const statement : branch->statements)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                statement->accept(this);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(return_statement *)
 | 
					    void declaration_visitor::visit(return_statement *statement)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					        if (statement->return_expression() != nullptr)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            statement->return_expression()->accept(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(defer_statement *)
 | 
					    void declaration_visitor::visit(defer_statement *statement)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					        for (struct statement *const statement : statement->statements)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            statement->accept(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(procedure_call *)
 | 
					    void declaration_visitor::visit(procedure_call *call)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					        call->callable().accept(this);
 | 
				
			||||||
 | 
					        for (expression *const argument: call->arguments)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            argument->accept(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(block *)
 | 
					    void declaration_visitor::visit(block *block)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					        for (constant_definition *const constant : block->constants)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            constant->accept(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for (variable_declaration *const variable : block->variables)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            variable->accept(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for (statement *const statement : block->body)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            statement->accept(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(traits_expression *)
 | 
					    void declaration_visitor::visit(traits_expression *trait)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					        if (!trait->parameters.empty())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            trait->parameters.front()->accept(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(cast_expression *)
 | 
					    void declaration_visitor::visit(cast_expression *expression)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					        expression->value().accept(this);
 | 
				
			||||||
 | 
					        expression->target().accept(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(binary_expression *)
 | 
					    void declaration_visitor::visit(binary_expression *expression)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					        expression->lhs().accept(this);
 | 
				
			||||||
 | 
					        expression->rhs().accept(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(unary_expression *)
 | 
					    void declaration_visitor::visit(unary_expression *expression)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					        expression->operand().accept(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(variable_expression *)
 | 
					    void declaration_visitor::visit(variable_expression *)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(array_access_expression *)
 | 
					    void declaration_visitor::visit(array_access_expression *expression)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					        expression->base().accept(this);
 | 
				
			||||||
 | 
					        expression->index().accept(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(field_access_expression *)
 | 
					    void declaration_visitor::visit(field_access_expression *expression)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					        expression->base().accept(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(dereference_expression *)
 | 
					    void declaration_visitor::visit(dereference_expression *expression)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					        expression->base().accept(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(literal<std::int32_t> *)
 | 
					    void declaration_visitor::visit(literal<std::int32_t> *)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(literal<std::uint32_t> *)
 | 
					    void declaration_visitor::visit(literal<std::uint32_t> *)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(literal<double> *)
 | 
					    void declaration_visitor::visit(literal<double> *)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(literal<bool> *)
 | 
					    void declaration_visitor::visit(literal<bool> *)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(literal<unsigned char> *)
 | 
					    void declaration_visitor::visit(literal<unsigned char> *)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(literal<std::nullptr_t> *)
 | 
					    void declaration_visitor::visit(literal<std::nullptr_t> *)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(literal<std::string> *)
 | 
					    void declaration_visitor::visit(literal<std::string> *)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        __builtin_unreachable();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,11 +36,20 @@ along with GCC; see the file COPYING3.  If not see
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace elna::gcc
 | 
					namespace elna::gcc
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    tree get_inner_alias(const boot::type& type, std::shared_ptr<symbol_table> symbols)
 | 
					    tree get_inner_alias(const boot::type& type, std::shared_ptr<symbol_table> symbols,
 | 
				
			||||||
 | 
					            std::unordered_map<std::string, tree>& unresolved)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (auto reference = type.get<boot::primitive_type>())
 | 
					        if (auto reference = type.get<boot::primitive_type>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return symbols->lookup(reference->identifier);
 | 
					            auto looked_up = unresolved.find(reference->identifier);
 | 
				
			||||||
 | 
					            if (looked_up == unresolved.cend())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return symbols->lookup(reference->identifier);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return looked_up->second;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (auto reference = type.get<boot::record_type>())
 | 
					        else if (auto reference = type.get<boot::record_type>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -52,7 +61,7 @@ namespace elna::gcc
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (auto reference = type.get<boot::pointer_type>())
 | 
					        else if (auto reference = type.get<boot::pointer_type>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return build_pointer_type_for_mode(get_inner_alias(reference->base, symbols), VOIDmode, true);
 | 
					            return build_pointer_type_for_mode(get_inner_alias(reference->base, symbols, unresolved), VOIDmode, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (auto reference = type.get<boot::array_type>())
 | 
					        else if (auto reference = type.get<boot::array_type>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -60,30 +69,31 @@ namespace elna::gcc
 | 
				
			|||||||
            tree upper_bound = build_int_cst_type(integer_type_node, reference->size);
 | 
					            tree upper_bound = build_int_cst_type(integer_type_node, reference->size);
 | 
				
			||||||
            tree range_type = build_range_type(integer_type_node, lower_bound, upper_bound);
 | 
					            tree range_type = build_range_type(integer_type_node, lower_bound, upper_bound);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return build_array_type(get_inner_alias(reference->base, symbols), range_type);
 | 
					            return build_array_type(get_inner_alias(reference->base, symbols, unresolved), range_type);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (auto reference = type.get<boot::alias_type>())
 | 
					        else if (auto reference = type.get<boot::alias_type>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return handle_symbol(reference->name, reference->reference, symbols);
 | 
					            return handle_symbol(reference->name, reference->reference, symbols, unresolved);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return error_mark_node;
 | 
					        return error_mark_node;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tree handle_symbol(const std::string& symbol_name, const boot::type& type, std::shared_ptr<symbol_table> symbols)
 | 
					    tree handle_symbol(const std::string& symbol_name, const boot::type& type,
 | 
				
			||||||
 | 
					            std::shared_ptr<symbol_table> symbols, std::unordered_map<std::string, tree>& unresolved)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        auto looked_up = symbols->lookup(symbol_name);
 | 
					        auto looked_up = symbols->lookup(symbol_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (looked_up == NULL_TREE)
 | 
					        if (looked_up == NULL_TREE)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            looked_up = get_inner_alias(type, symbols);
 | 
					            looked_up = get_inner_alias(type, symbols, unresolved);
 | 
				
			||||||
            symbols->enter(symbol_name, looked_up);
 | 
					            unresolved.insert({ symbol_name, looked_up });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return looked_up;
 | 
					        return looked_up;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::deque<std::unique_ptr<boot::error>> do_semantic_analysis(const char *path,
 | 
					    std::deque<std::unique_ptr<boot::error>> do_semantic_analysis(const char *path,
 | 
				
			||||||
            std::unique_ptr<boot::program>& ast, std::shared_ptr<boot::symbol_table> info_table,
 | 
					            std::unique_ptr<boot::program>& ast, std::shared_ptr<boot::symbol_table> info_table,
 | 
				
			||||||
            std::shared_ptr<symbol_table> symbols)
 | 
					            std::shared_ptr<symbol_table> symbols, std::unordered_map<std::string, tree>& unresolved)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        boot::declaration_visitor declaration_visitor(path, info_table);
 | 
					        boot::declaration_visitor declaration_visitor(path, info_table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -93,15 +103,16 @@ namespace elna::gcc
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            for (auto& [symbol_name, symbol_info] : declaration_visitor.unresolved)
 | 
					            for (auto& [symbol_name, symbol_info] : declaration_visitor.unresolved)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                handle_symbol(symbol_name, boot::type(symbol_info), symbols);
 | 
					                handle_symbol(symbol_name, boot::type(symbol_info), symbols, unresolved);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return std::move(declaration_visitor.errors());
 | 
					        return std::move(declaration_visitor.errors());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    generic_visitor::generic_visitor(std::shared_ptr<symbol_table> symbol_table)
 | 
					    generic_visitor::generic_visitor(std::shared_ptr<symbol_table> symbol_table,
 | 
				
			||||||
 | 
					            std::unordered_map<std::string, tree>&& unresolved)
 | 
				
			||||||
 | 
					        : symbols(symbol_table), unresolved(std::move(unresolved))
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        this->symbols = symbol_table;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void generic_visitor::build_procedure_call(location_t call_location,
 | 
					    void generic_visitor::build_procedure_call(location_t call_location,
 | 
				
			||||||
@@ -763,8 +774,7 @@ namespace elna::gcc
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            error_at(definition_location,
 | 
					            error_at(definition_location, "Variable '%s' already declared in this scope",
 | 
				
			||||||
                    "variable '%s' already declared in this scope",
 | 
					 | 
				
			||||||
                    definition->identifier.c_str());
 | 
					                    definition->identifier.c_str());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this->current_expression = NULL_TREE;
 | 
					        this->current_expression = NULL_TREE;
 | 
				
			||||||
@@ -773,12 +783,13 @@ namespace elna::gcc
 | 
				
			|||||||
    void generic_visitor::visit(boot::type_definition *definition)
 | 
					    void generic_visitor::visit(boot::type_definition *definition)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        location_t definition_location = get_location(&definition->position());
 | 
					        location_t definition_location = get_location(&definition->position());
 | 
				
			||||||
        this->current_expression = this->symbols->lookup(definition->identifier);
 | 
					        this->current_expression = this->unresolved.at(definition->identifier);
 | 
				
			||||||
        definition->body().accept(this);
 | 
					        definition->body().accept(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tree definition_tree = build_decl(definition_location, TYPE_DECL,
 | 
					        tree definition_tree = build_decl(definition_location, TYPE_DECL,
 | 
				
			||||||
                get_identifier(definition->identifier.c_str()), this->current_expression);
 | 
					                get_identifier(definition->identifier.c_str()), this->current_expression);
 | 
				
			||||||
        auto result = this->symbols->enter(definition->identifier, this->current_expression);
 | 
					        auto result = this->symbols->enter(definition->identifier, this->current_expression);
 | 
				
			||||||
 | 
					        gcc_assert(result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TREE_PUBLIC(definition_tree) = definition->exported;
 | 
					        TREE_PUBLIC(definition_tree) = definition->exported;
 | 
				
			||||||
        TYPE_NAME(this->current_expression) = get_identifier(definition->identifier.c_str());
 | 
					        TYPE_NAME(this->current_expression) = get_identifier(definition->identifier.c_str());
 | 
				
			||||||
@@ -1225,29 +1236,61 @@ namespace elna::gcc
 | 
				
			|||||||
    void generic_visitor::visit(boot::return_statement *statement)
 | 
					    void generic_visitor::visit(boot::return_statement *statement)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        boot::expression *return_expression = statement->return_expression();
 | 
					        boot::expression *return_expression = statement->return_expression();
 | 
				
			||||||
 | 
					        location_t statement_position = get_location(&statement->position());
 | 
				
			||||||
 | 
					        tree set_result{ NULL_TREE };
 | 
				
			||||||
 | 
					        tree return_type = TREE_TYPE(TREE_TYPE(current_function_decl));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (return_expression == nullptr)
 | 
					        if (TREE_THIS_VOLATILE(current_function_decl) == 1)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            error_at(statement_position, "This procedure is not allowed to return");
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return_expression->accept(this);
 | 
					        if (return_expression != nullptr)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
        tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(current_function_decl),
 | 
					            return_expression->accept(this);
 | 
				
			||||||
                this->current_expression);
 | 
					 | 
				
			||||||
        tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
 | 
					 | 
				
			||||||
        append_statement(return_stmt);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(current_function_decl),
 | 
				
			||||||
 | 
					                    this->current_expression);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (return_type == void_type_node && set_result != NULL_TREE)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            error_at(statement_position, "Proper procedure is not allowed to return a value");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (return_type != void_type_node && set_result == NULL_TREE)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            error_at(statement_position, "Procedure is expected to return a value of type '%s'",
 | 
				
			||||||
 | 
					                    print_type(return_type).c_str());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (return_type != void_type_node && !is_assignable_from(return_type, this->current_expression))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            error_at(statement_position, "Cannot return '%s' from a procedure returning '%s'",
 | 
				
			||||||
 | 
					                    print_type(return_type).c_str(),
 | 
				
			||||||
 | 
					                    print_type(TREE_TYPE(this->current_expression)).c_str());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            tree return_stmt = build1_loc(statement_position, RETURN_EXPR, void_type_node, set_result);
 | 
				
			||||||
 | 
					            append_statement(return_stmt);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        this->current_expression = NULL_TREE;
 | 
					        this->current_expression = NULL_TREE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void generic_visitor::visit(boot::primitive_type_expression *type)
 | 
					    void generic_visitor::visit(boot::primitive_type_expression *type)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        tree symbol = this->symbols->lookup(type->name);
 | 
					        auto looked_up = this->unresolved.find(type->name);
 | 
				
			||||||
 | 
					        tree symbol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (looked_up == this->unresolved.cend())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            symbol = this->symbols->lookup(type->name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            symbol = looked_up->second;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        if (symbol == NULL_TREE || !TYPE_P(symbol))
 | 
					        if (symbol == NULL_TREE || !TYPE_P(symbol))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            error_at(get_location(&type->position()),
 | 
					            error_at(get_location(&type->position()), "Type '%s' not declared", type->name.c_str());
 | 
				
			||||||
                    "type '%s' not declared", type->name.c_str());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this->current_expression = error_mark_node;
 | 
					            this->current_expression = error_mark_node;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -85,12 +85,14 @@ static void elna_parse_file(const char *filename)
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        std::shared_ptr<elna::boot::symbol_table> info_table = elna::boot::builtin_symbol_table();
 | 
					        std::shared_ptr<elna::boot::symbol_table> info_table = elna::boot::builtin_symbol_table();
 | 
				
			||||||
        std::shared_ptr<elna::gcc::symbol_table> symbol_table = elna::gcc::builtin_symbol_table();
 | 
					        std::shared_ptr<elna::gcc::symbol_table> symbol_table = elna::gcc::builtin_symbol_table();
 | 
				
			||||||
 | 
					        std::unordered_map<std::string, tree> unresolved;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto semantic_errors = elna::gcc::do_semantic_analysis(filename, driver.tree, info_table, symbol_table);
 | 
					        auto semantic_errors = elna::gcc::do_semantic_analysis(filename, driver.tree,
 | 
				
			||||||
 | 
					                info_table, symbol_table, unresolved);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (semantic_errors.empty())
 | 
					        if (semantic_errors.empty())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            elna::gcc::generic_visitor generic_visitor{ symbol_table };
 | 
					            elna::gcc::generic_visitor generic_visitor{ symbol_table, std::move(unresolved) };
 | 
				
			||||||
            generic_visitor.visit(driver.tree.get());
 | 
					            generic_visitor.visit(driver.tree.get());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -138,6 +138,7 @@ namespace elna::boot
 | 
				
			|||||||
        explicit node(const position position);
 | 
					        explicit node(const position position);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
 | 
					        virtual void accept(parser_visitor *visitor) = 0;
 | 
				
			||||||
        virtual ~node() = 0;
 | 
					        virtual ~node() = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
@@ -155,41 +156,6 @@ namespace elna::boot
 | 
				
			|||||||
        virtual return_statement *is_return();
 | 
					        virtual return_statement *is_return();
 | 
				
			||||||
        virtual defer_statement *is_defer();
 | 
					        virtual defer_statement *is_defer();
 | 
				
			||||||
        virtual procedure_call *is_call_statement();
 | 
					        virtual procedure_call *is_call_statement();
 | 
				
			||||||
 | 
					 | 
				
			||||||
        template<typename V>
 | 
					 | 
				
			||||||
        void accept(V *visitor)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (assign_statement *node = is_assign())
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return visitor->visit(node);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (if_statement *node = is_if())
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return visitor->visit(node);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (while_statement *node = is_while())
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return visitor->visit(node);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (return_statement *node = is_return())
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return visitor->visit(node);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (defer_statement *node = is_defer())
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return visitor->visit(node);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (procedure_call *node = is_call_statement())
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return visitor->visit(node);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            __builtin_unreachable();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ~statement() = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected:
 | 
					 | 
				
			||||||
        statement();
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class expression : public virtual node
 | 
					    class expression : public virtual node
 | 
				
			||||||
@@ -202,12 +168,6 @@ namespace elna::boot
 | 
				
			|||||||
        virtual designator_expression *is_designator();
 | 
					        virtual designator_expression *is_designator();
 | 
				
			||||||
        virtual procedure_call *is_call_expression();
 | 
					        virtual procedure_call *is_call_expression();
 | 
				
			||||||
        virtual literal_expression *is_literal();
 | 
					        virtual literal_expression *is_literal();
 | 
				
			||||||
 | 
					 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					 | 
				
			||||||
        ~expression() = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected:
 | 
					 | 
				
			||||||
        expression();
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -236,8 +196,6 @@ namespace elna::boot
 | 
				
			|||||||
        virtual std::shared_ptr<union_type_expression> is_union();
 | 
					        virtual std::shared_ptr<union_type_expression> is_union();
 | 
				
			||||||
        virtual std::shared_ptr<procedure_type_expression> is_procedure();
 | 
					        virtual std::shared_ptr<procedure_type_expression> is_procedure();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected:
 | 
					    protected:
 | 
				
			||||||
        type_expression(const struct position position);
 | 
					        type_expression(const struct position position);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@@ -251,7 +209,7 @@ namespace elna::boot
 | 
				
			|||||||
        const std::string name;
 | 
					        const std::string name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        primitive_type_expression(const struct position position, const std::string& name);
 | 
					        primitive_type_expression(const struct position position, const std::string& name);
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        std::shared_ptr<primitive_type_expression> is_primitive() override;
 | 
					        std::shared_ptr<primitive_type_expression> is_primitive() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -264,7 +222,7 @@ namespace elna::boot
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        array_type_expression(const struct position position,
 | 
					        array_type_expression(const struct position position,
 | 
				
			||||||
                std::shared_ptr<type_expression> base, const std::uint32_t size);
 | 
					                std::shared_ptr<type_expression> base, const std::uint32_t size);
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        std::shared_ptr<array_type_expression> is_array() override;
 | 
					        std::shared_ptr<array_type_expression> is_array() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        type_expression& base();
 | 
					        type_expression& base();
 | 
				
			||||||
@@ -276,7 +234,7 @@ namespace elna::boot
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        pointer_type_expression(const struct position position, std::shared_ptr<type_expression> base);
 | 
					        pointer_type_expression(const struct position position, std::shared_ptr<type_expression> base);
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        std::shared_ptr<pointer_type_expression> is_pointer() override;
 | 
					        std::shared_ptr<pointer_type_expression> is_pointer() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        type_expression& base();
 | 
					        type_expression& base();
 | 
				
			||||||
@@ -291,7 +249,7 @@ namespace elna::boot
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        record_type_expression(const struct position position, std::vector<field_declaration>&& fields);
 | 
					        record_type_expression(const struct position position, std::vector<field_declaration>&& fields);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        std::shared_ptr<record_type_expression> is_record() override;
 | 
					        std::shared_ptr<record_type_expression> is_record() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -302,7 +260,7 @@ namespace elna::boot
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        union_type_expression(const struct position position, std::vector<field_declaration>&& fields);
 | 
					        union_type_expression(const struct position position, std::vector<field_declaration>&& fields);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        std::shared_ptr<union_type_expression> is_union() override;
 | 
					        std::shared_ptr<union_type_expression> is_union() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -311,12 +269,12 @@ namespace elna::boot
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    class variable_declaration : public definition
 | 
					    class variable_declaration : public definition
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::shared_ptr<type_expression> m_type;
 | 
					        std::shared_ptr<type_expression> m_variable_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        variable_declaration(const struct position position, const std::string& identifier,
 | 
					        variable_declaration(const struct position position, const std::string& identifier,
 | 
				
			||||||
                std::shared_ptr<type_expression> type, const bool exported = false);
 | 
					                std::shared_ptr<type_expression> variable_type, const bool exported = false);
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        type_expression& variable_type();
 | 
					        type_expression& variable_type();
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@@ -336,7 +294,6 @@ namespace elna::boot
 | 
				
			|||||||
        virtual literal<std::string> *is_string() = 0;
 | 
					        virtual literal<std::string> *is_string() = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        literal_expression *is_literal() override;
 | 
					        literal_expression *is_literal() override;
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected:
 | 
					    protected:
 | 
				
			||||||
        literal_expression();
 | 
					        literal_expression();
 | 
				
			||||||
@@ -350,14 +307,9 @@ namespace elna::boot
 | 
				
			|||||||
        literal_expression *m_body;
 | 
					        literal_expression *m_body;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        /**
 | 
					 | 
				
			||||||
         * \param position Source code position.
 | 
					 | 
				
			||||||
         * \param identifier Constant name.
 | 
					 | 
				
			||||||
         * \param body Constant value.
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        constant_definition(const struct position position, const std::string& identifier,
 | 
					        constant_definition(const struct position position, const std::string& identifier,
 | 
				
			||||||
                const bool exported, literal_expression *body);
 | 
					                const bool exported, literal_expression *body);
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        literal_expression& body();
 | 
					        literal_expression& body();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -389,7 +341,7 @@ namespace elna::boot
 | 
				
			|||||||
        procedure_type_expression(const struct position position,
 | 
					        procedure_type_expression(const struct position position,
 | 
				
			||||||
                return_declaration return_type = return_declaration());
 | 
					                return_declaration return_type = return_declaration());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        std::shared_ptr<procedure_type_expression> is_procedure() override;
 | 
					        std::shared_ptr<procedure_type_expression> is_procedure() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -406,7 +358,7 @@ namespace elna::boot
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        procedure_definition(const struct position position, const std::string& identifier,
 | 
					        procedure_definition(const struct position position, const std::string& identifier,
 | 
				
			||||||
                const bool exported, std::shared_ptr<procedure_type_expression> heading, block *body = nullptr);
 | 
					                const bool exported, std::shared_ptr<procedure_type_expression> heading, block *body = nullptr);
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        procedure_type_expression& heading();
 | 
					        procedure_type_expression& heading();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -423,7 +375,7 @@ namespace elna::boot
 | 
				
			|||||||
    public:
 | 
					    public:
 | 
				
			||||||
        type_definition(const struct position position, const std::string& identifier,
 | 
					        type_definition(const struct position position, const std::string& identifier,
 | 
				
			||||||
                const bool exported, std::shared_ptr<type_expression> expression);
 | 
					                const bool exported, std::shared_ptr<type_expression> expression);
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        type_expression& body();
 | 
					        type_expression& body();
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@@ -438,7 +390,7 @@ namespace elna::boot
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        cast_expression(const struct position position, std::shared_ptr<type_expression> target, expression *value);
 | 
					        cast_expression(const struct position position, std::shared_ptr<type_expression> target, expression *value);
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        cast_expression *is_cast() override;
 | 
					        cast_expression *is_cast() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        type_expression& target();
 | 
					        type_expression& target();
 | 
				
			||||||
@@ -454,7 +406,7 @@ namespace elna::boot
 | 
				
			|||||||
        const std::string name;
 | 
					        const std::string name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        traits_expression(const struct position position, const std::string& name);
 | 
					        traits_expression(const struct position position, const std::string& name);
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        traits_expression *is_traits() override;
 | 
					        traits_expression *is_traits() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -480,17 +432,12 @@ namespace elna::boot
 | 
				
			|||||||
        expression *m_return_expression{ nullptr };
 | 
					        expression *m_return_expression{ nullptr };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        return_statement(const struct position position, expression *return_expression);
 | 
					        return_statement(const struct position position, expression *return_expression = nullptr);
 | 
				
			||||||
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        template<typename V>
 | 
					        virtual return_statement *is_return() override;
 | 
				
			||||||
        void accept(V *visitor)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            visitor->visit(this);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        expression *return_expression();
 | 
					        expression *return_expression();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual return_statement *is_return() override;
 | 
					 | 
				
			||||||
        virtual ~return_statement() override;
 | 
					        virtual ~return_statement() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -502,29 +449,8 @@ namespace elna::boot
 | 
				
			|||||||
        virtual field_access_expression *is_field_access();
 | 
					        virtual field_access_expression *is_field_access();
 | 
				
			||||||
        virtual dereference_expression *is_dereference();
 | 
					        virtual dereference_expression *is_dereference();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template<typename V>
 | 
					 | 
				
			||||||
        void accept(V *visitor)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (variable_expression *node = is_variable())
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return visitor->visit(node);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (array_access_expression *node = is_array_access())
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return visitor->visit(node);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (field_access_expression *node = is_field_access())
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return visitor->visit(node);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (dereference_expression *node = is_dereference())
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return visitor->visit(node);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            __builtin_unreachable();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        designator_expression *is_designator() override;
 | 
					        designator_expression *is_designator() override;
 | 
				
			||||||
 | 
					        void accept(parser_visitor *visitor);
 | 
				
			||||||
        ~designator_expression() = 0;
 | 
					        ~designator_expression() = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected:
 | 
					    protected:
 | 
				
			||||||
@@ -537,12 +463,7 @@ namespace elna::boot
 | 
				
			|||||||
        const std::string name;
 | 
					        const std::string name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        variable_expression(const struct position position, const std::string& name);
 | 
					        variable_expression(const struct position position, const std::string& name);
 | 
				
			||||||
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        template<typename V>
 | 
					 | 
				
			||||||
        void accept(V *visitor)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            visitor->visit(this);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        variable_expression *is_variable() override;
 | 
					        variable_expression *is_variable() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@@ -554,12 +475,7 @@ namespace elna::boot
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        array_access_expression(const struct position position, expression *base, expression *index);
 | 
					        array_access_expression(const struct position position, expression *base, expression *index);
 | 
				
			||||||
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        template<typename V>
 | 
					 | 
				
			||||||
        void accept(V *visitor)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            visitor->visit(this);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        expression& base();
 | 
					        expression& base();
 | 
				
			||||||
        expression& index();
 | 
					        expression& index();
 | 
				
			||||||
@@ -577,12 +493,7 @@ namespace elna::boot
 | 
				
			|||||||
    public:
 | 
					    public:
 | 
				
			||||||
        field_access_expression(const struct position position, expression *base,
 | 
					        field_access_expression(const struct position position, expression *base,
 | 
				
			||||||
                const std::string& field);
 | 
					                const std::string& field);
 | 
				
			||||||
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        template<typename V>
 | 
					 | 
				
			||||||
        void accept(V *visitor)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            visitor->visit(this);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        expression& base();
 | 
					        expression& base();
 | 
				
			||||||
        std::string& field();
 | 
					        std::string& field();
 | 
				
			||||||
@@ -598,16 +509,12 @@ namespace elna::boot
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        dereference_expression(const struct position position, expression *base);
 | 
					        dereference_expression(const struct position position, expression *base);
 | 
				
			||||||
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        template<typename V>
 | 
					 | 
				
			||||||
        void accept(parser_visitor *visitor)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            visitor->visit(this);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        expression& base();
 | 
					        expression& base();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        dereference_expression *is_dereference() override;
 | 
					        dereference_expression *is_dereference() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ~dereference_expression() override;
 | 
					        ~dereference_expression() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -622,17 +529,12 @@ namespace elna::boot
 | 
				
			|||||||
        std::vector<expression *> arguments;
 | 
					        std::vector<expression *> arguments;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        procedure_call(const struct position position, designator_expression *callable);
 | 
					        procedure_call(const struct position position, designator_expression *callable);
 | 
				
			||||||
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        template<typename V>
 | 
					        virtual procedure_call *is_call_statement() override;
 | 
				
			||||||
        void accept(V *visitor)
 | 
					        virtual procedure_call *is_call_expression() override;
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            visitor->visit(this);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        designator_expression& callable();
 | 
					        designator_expression& callable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual procedure_call *is_call_statement() override;
 | 
					 | 
				
			||||||
        virtual procedure_call *is_call_expression() override;
 | 
					 | 
				
			||||||
        virtual ~procedure_call() override;
 | 
					        virtual ~procedure_call() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -649,18 +551,13 @@ namespace elna::boot
 | 
				
			|||||||
         */
 | 
					         */
 | 
				
			||||||
        assign_statement(const struct position position, designator_expression *lvalue,
 | 
					        assign_statement(const struct position position, designator_expression *lvalue,
 | 
				
			||||||
                expression *rvalue);
 | 
					                expression *rvalue);
 | 
				
			||||||
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        template<typename V>
 | 
					 | 
				
			||||||
        void accept(V *visitor)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            visitor->visit(this);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        designator_expression& lvalue();
 | 
					        designator_expression& lvalue();
 | 
				
			||||||
        expression& rvalue();
 | 
					        expression& rvalue();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assign_statement *is_assign() override;
 | 
					 | 
				
			||||||
        virtual ~assign_statement() override;
 | 
					        virtual ~assign_statement() override;
 | 
				
			||||||
 | 
					        assign_statement *is_assign() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -676,17 +573,12 @@ namespace elna::boot
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if_statement(const struct position position, conditional_statements *body,
 | 
					        if_statement(const struct position position, conditional_statements *body,
 | 
				
			||||||
                std::vector<statement *> *alternative = nullptr);
 | 
					                std::vector<statement *> *alternative = nullptr);
 | 
				
			||||||
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        template<typename V>
 | 
					        virtual if_statement *is_if() override;
 | 
				
			||||||
        void accept(V *visitor)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            visitor->visit(this);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        conditional_statements& body();
 | 
					        conditional_statements& body();
 | 
				
			||||||
        std::vector<statement *> *alternative();
 | 
					        std::vector<statement *> *alternative();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual if_statement *is_if() override;
 | 
					 | 
				
			||||||
        virtual ~if_statement() override;
 | 
					        virtual ~if_statement() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -700,16 +592,11 @@ namespace elna::boot
 | 
				
			|||||||
    public:
 | 
					    public:
 | 
				
			||||||
        std::vector<conditional_statements *> branches;
 | 
					        std::vector<conditional_statements *> branches;
 | 
				
			||||||
        while_statement(const struct position position, conditional_statements *body);
 | 
					        while_statement(const struct position position, conditional_statements *body);
 | 
				
			||||||
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        template<typename V>
 | 
					        while_statement *is_while() override;
 | 
				
			||||||
        void accept(V *visitor)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            visitor->visit(this);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        conditional_statements& body();
 | 
					        conditional_statements& body();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        while_statement *is_while() override;
 | 
					 | 
				
			||||||
        virtual ~while_statement() override;
 | 
					        virtual ~while_statement() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -721,7 +608,7 @@ namespace elna::boot
 | 
				
			|||||||
        std::vector<statement *> body;
 | 
					        std::vector<statement *> body;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        block(const struct position position);
 | 
					        block(const struct position position);
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					        virtual void accept(parser_visitor *visitor) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual ~block() override;
 | 
					        virtual ~block() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@@ -733,7 +620,7 @@ namespace elna::boot
 | 
				
			|||||||
        std::vector<procedure_definition *> procedures;
 | 
					        std::vector<procedure_definition *> procedures;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        program(const struct position position);
 | 
					        program(const struct position position);
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual ~program() override;
 | 
					        virtual ~program() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@@ -833,8 +720,7 @@ namespace elna::boot
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template<typename V>
 | 
					        void accept(parser_visitor *visitor) override
 | 
				
			||||||
        void accept(V *visitor)
 | 
					 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            visitor->visit(this);
 | 
					            visitor->visit(this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -846,14 +732,9 @@ namespace elna::boot
 | 
				
			|||||||
        std::vector<statement *> statements;
 | 
					        std::vector<statement *> statements;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        defer_statement(const struct position position);
 | 
					        defer_statement(const struct position position);
 | 
				
			||||||
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        template<typename V>
 | 
					 | 
				
			||||||
        void accept(V *visitor)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            visitor->visit(this);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        defer_statement *is_defer() override;
 | 
					        defer_statement *is_defer() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual ~defer_statement() override;
 | 
					        virtual ~defer_statement() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -867,7 +748,7 @@ namespace elna::boot
 | 
				
			|||||||
        binary_expression(const struct position position, expression *lhs,
 | 
					        binary_expression(const struct position position, expression *lhs,
 | 
				
			||||||
                expression *rhs, const binary_operator operation);
 | 
					                expression *rhs, const binary_operator operation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        binary_expression *is_binary() override;
 | 
					        binary_expression *is_binary() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        expression& lhs();
 | 
					        expression& lhs();
 | 
				
			||||||
@@ -886,7 +767,7 @@ namespace elna::boot
 | 
				
			|||||||
        unary_expression(const struct position position, expression *operand,
 | 
					        unary_expression(const struct position position, expression *operand,
 | 
				
			||||||
                const unary_operator operation);
 | 
					                const unary_operator operation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void accept(parser_visitor *visitor);
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        unary_expression *is_unary() override;
 | 
					        unary_expression *is_unary() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        expression& operand();
 | 
					        expression& operand();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -65,24 +65,24 @@ namespace elna::boot
 | 
				
			|||||||
        void visit(union_type_expression *) override;
 | 
					        void visit(union_type_expression *) override;
 | 
				
			||||||
        void visit(procedure_type_expression *) override;
 | 
					        void visit(procedure_type_expression *) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void visit(variable_declaration *) override;
 | 
					        void visit(variable_declaration *declaration) override;
 | 
				
			||||||
        void visit(constant_definition *) override;
 | 
					        void visit(constant_definition *) override;
 | 
				
			||||||
        void visit(procedure_definition *) override;
 | 
					        void visit(procedure_definition *definition) override;
 | 
				
			||||||
        void visit(assign_statement *) override;
 | 
					        void visit(assign_statement *statement) override;
 | 
				
			||||||
        void visit(if_statement *) override;
 | 
					        void visit(if_statement *statement) override;
 | 
				
			||||||
        void visit(while_statement *) override;
 | 
					        void visit(while_statement *statement) override;
 | 
				
			||||||
        void visit(return_statement *) override;
 | 
					        void visit(return_statement *statement) override;
 | 
				
			||||||
        void visit(defer_statement *) override;
 | 
					        void visit(defer_statement *statement) override;
 | 
				
			||||||
        void visit(procedure_call *) override;
 | 
					        void visit(procedure_call *call) override;
 | 
				
			||||||
        void visit(block *) override;
 | 
					        void visit(block *block) override;
 | 
				
			||||||
        void visit(cast_expression *) override;
 | 
					        void visit(cast_expression *expression) override;
 | 
				
			||||||
        void visit(traits_expression *) override;
 | 
					        void visit(traits_expression *trait) override;
 | 
				
			||||||
        void visit(binary_expression *) override;
 | 
					        void visit(binary_expression *expression) override;
 | 
				
			||||||
        void visit(unary_expression *) override;
 | 
					        void visit(unary_expression *expression) override;
 | 
				
			||||||
        void visit(variable_expression *) override;
 | 
					        void visit(variable_expression *) override;
 | 
				
			||||||
        void visit(array_access_expression *) override;
 | 
					        void visit(array_access_expression *expression) override;
 | 
				
			||||||
        void visit(field_access_expression *) override;
 | 
					        void visit(field_access_expression *expression) override;
 | 
				
			||||||
        void visit(dereference_expression *) override;
 | 
					        void visit(dereference_expression *expression) override;
 | 
				
			||||||
        void visit(literal<std::int32_t> *) override;
 | 
					        void visit(literal<std::int32_t> *) override;
 | 
				
			||||||
        void visit(literal<std::uint32_t> *) override;
 | 
					        void visit(literal<std::uint32_t> *) override;
 | 
				
			||||||
        void visit(literal<double> *) override;
 | 
					        void visit(literal<double> *) override;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,13 +34,15 @@ namespace elna::gcc
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    std::deque<std::unique_ptr<boot::error>> do_semantic_analysis(const char *path,
 | 
					    std::deque<std::unique_ptr<boot::error>> do_semantic_analysis(const char *path,
 | 
				
			||||||
            std::unique_ptr<boot::program>& ast, std::shared_ptr<boot::symbol_table> info_table,
 | 
					            std::unique_ptr<boot::program>& ast, std::shared_ptr<boot::symbol_table> info_table,
 | 
				
			||||||
            std::shared_ptr<symbol_table> symbols);
 | 
					            std::shared_ptr<symbol_table> symbols, std::unordered_map<std::string, tree>& unresolved);
 | 
				
			||||||
    tree handle_symbol(const std::string& symbol_name, const boot::type& type, std::shared_ptr<symbol_table> symbols);
 | 
					    tree handle_symbol(const std::string& symbol_name, const boot::type& type,
 | 
				
			||||||
 | 
					            std::shared_ptr<symbol_table> symbols, std::unordered_map<std::string, tree>& unresolved);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class generic_visitor final : public boot::parser_visitor
 | 
					    class generic_visitor final : public boot::parser_visitor
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        tree current_expression{ NULL_TREE };
 | 
					        tree current_expression{ NULL_TREE };
 | 
				
			||||||
        std::shared_ptr<symbol_table> symbols;
 | 
					        std::shared_ptr<symbol_table> symbols;
 | 
				
			||||||
 | 
					        std::unordered_map<std::string, tree> unresolved;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tree build_label_decl(const char *name, location_t loc);
 | 
					        tree build_label_decl(const char *name, location_t loc);
 | 
				
			||||||
        tree build_procedure_type(boot::procedure_type_expression& type);
 | 
					        tree build_procedure_type(boot::procedure_type_expression& type);
 | 
				
			||||||
@@ -68,7 +70,8 @@ namespace elna::gcc
 | 
				
			|||||||
        void visit_statements(const std::vector<boot::statement *>& statements);
 | 
					        void visit_statements(const std::vector<boot::statement *>& statements);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        generic_visitor(std::shared_ptr<symbol_table> symbol_table);
 | 
					        generic_visitor(std::shared_ptr<symbol_table> symbol_table,
 | 
				
			||||||
 | 
					                std::unordered_map<std::string, tree>&& unresolved);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void visit(boot::program *program) override;
 | 
					        void visit(boot::program *program) override;
 | 
				
			||||||
        void visit(boot::procedure_definition *definition) override;
 | 
					        void visit(boot::procedure_definition *definition) override;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user