Label loops
This commit is contained in:
		
							
								
								
									
										86
									
								
								boot/ast.cc
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								boot/ast.cc
									
									
									
									
									
								
							@@ -33,36 +33,6 @@ namespace elna::boot
 | 
			
		||||
        return this->source_position;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    assign_statement *statement::is_assign()
 | 
			
		||||
    {
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if_statement *statement::is_if()
 | 
			
		||||
    {
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while_statement *statement::is_while()
 | 
			
		||||
    {
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return_statement *statement::is_return()
 | 
			
		||||
    {
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    defer_statement *statement::is_defer()
 | 
			
		||||
    {
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    procedure_call *statement::is_call_statement()
 | 
			
		||||
    {
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    cast_expression *expression::is_cast()
 | 
			
		||||
    {
 | 
			
		||||
        return nullptr;
 | 
			
		||||
@@ -447,11 +417,6 @@ namespace elna::boot
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    defer_statement *defer_statement::is_defer()
 | 
			
		||||
    {
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    defer_statement::~defer_statement()
 | 
			
		||||
    {
 | 
			
		||||
        for (statement *body_statement : statements)
 | 
			
		||||
@@ -676,11 +641,6 @@ namespace elna::boot
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    procedure_call *procedure_call::is_call_statement()
 | 
			
		||||
    {
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    procedure_call *procedure_call::is_call_expression()
 | 
			
		||||
    {
 | 
			
		||||
        return this;
 | 
			
		||||
@@ -754,8 +714,8 @@ namespace elna::boot
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    conditional_statements::conditional_statements(expression *prerequisite)
 | 
			
		||||
        : m_prerequisite(prerequisite)
 | 
			
		||||
    conditional_statements::conditional_statements(expression *prerequisite, std::vector<statement *>&& statements)
 | 
			
		||||
        : m_prerequisite(prerequisite), statements(std::move(statements))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -783,11 +743,6 @@ namespace elna::boot
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return_statement *return_statement::is_return()
 | 
			
		||||
    {
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return_statement::~return_statement()
 | 
			
		||||
    {
 | 
			
		||||
        delete this->return_expression;
 | 
			
		||||
@@ -820,11 +775,6 @@ namespace elna::boot
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    assign_statement *assign_statement::is_assign()
 | 
			
		||||
    {
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    variable_expression *designator_expression::is_variable()
 | 
			
		||||
    {
 | 
			
		||||
        return nullptr;
 | 
			
		||||
@@ -871,11 +821,6 @@ namespace elna::boot
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if_statement *if_statement::is_if()
 | 
			
		||||
    {
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    conditional_statements& if_statement::body()
 | 
			
		||||
    {
 | 
			
		||||
        return *m_body;
 | 
			
		||||
@@ -891,8 +836,26 @@ namespace elna::boot
 | 
			
		||||
        delete this->alternative;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while_statement::while_statement(const struct position position, conditional_statements *body)
 | 
			
		||||
        : node(position), m_body(body)
 | 
			
		||||
    escape_statement::escape_statement(const struct position position,
 | 
			
		||||
            escape_direction direction, const std::string& label)
 | 
			
		||||
        : node(position), direction(direction), label(label)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void escape_statement::accept(parser_visitor *visitor)
 | 
			
		||||
    {
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while_statement::while_statement(const struct position position, conditional_statements *body,
 | 
			
		||||
            std::vector<conditional_statements *>&& branches)
 | 
			
		||||
        : node(position), m_body(body), branches(std::move(branches))
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while_statement::while_statement(const struct position position, conditional_statements *body,
 | 
			
		||||
            std::vector<conditional_statements *>&& branches, const std::string& label)
 | 
			
		||||
        : node(position), m_body(body), branches(std::move(branches)), label(label)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -901,11 +864,6 @@ namespace elna::boot
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while_statement *while_statement::is_while()
 | 
			
		||||
    {
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    conditional_statements& while_statement::body()
 | 
			
		||||
    {
 | 
			
		||||
        return *m_body;
 | 
			
		||||
 
 | 
			
		||||
@@ -125,6 +125,12 @@ or                     {
 | 
			
		||||
return                  {
 | 
			
		||||
                            return yy::parser::make_RETURN(this->location);
 | 
			
		||||
                        }
 | 
			
		||||
break                   {
 | 
			
		||||
                            return yy::parser::make_BREAK(this->location);
 | 
			
		||||
                        }
 | 
			
		||||
repeat                  {
 | 
			
		||||
                            return yy::parser::make_REPEAT(this->location);
 | 
			
		||||
                        }
 | 
			
		||||
cast                    {
 | 
			
		||||
                            return yy::parser::make_CAST(this->location);
 | 
			
		||||
                        }
 | 
			
		||||
 
 | 
			
		||||
@@ -108,6 +108,8 @@ along with GCC; see the file COPYING3.  If not see
 | 
			
		||||
    ELSE "else"
 | 
			
		||||
    ELSIF "elsif"
 | 
			
		||||
    RETURN "return"
 | 
			
		||||
    REPEAT "repeat"
 | 
			
		||||
    BREAK "break"
 | 
			
		||||
    BEGIN_BLOCK "begin"
 | 
			
		||||
    END_BLOCK "end"
 | 
			
		||||
    DEFER "defer"
 | 
			
		||||
@@ -247,8 +249,7 @@ cast_expression: "cast" "(" expression ":" type_expression ")"
 | 
			
		||||
elsif_do_statements:
 | 
			
		||||
    "elsif" expression "do" statements elsif_do_statements
 | 
			
		||||
        {
 | 
			
		||||
            boot::conditional_statements *branch = new boot::conditional_statements($2);
 | 
			
		||||
            std::swap(branch->statements, $4);
 | 
			
		||||
            boot::conditional_statements *branch = new boot::conditional_statements($2, std::move($4));
 | 
			
		||||
            std::swap($5, $$);
 | 
			
		||||
            $$.emplace($$.begin(), branch);
 | 
			
		||||
        }
 | 
			
		||||
@@ -256,18 +257,21 @@ elsif_do_statements:
 | 
			
		||||
else_statements:
 | 
			
		||||
    "else" statements { $$ = new std::vector<boot::statement *>(std::move($2)); }
 | 
			
		||||
    | { $$ = nullptr; }
 | 
			
		||||
while_statement: "while" expression "do" statements elsif_do_statements "end"
 | 
			
		||||
while_statement:
 | 
			
		||||
    "while" expression "do" statements elsif_do_statements "end"
 | 
			
		||||
        {
 | 
			
		||||
            auto body = new boot::conditional_statements($2);
 | 
			
		||||
            std::swap($4, body->statements);
 | 
			
		||||
            $$ = new boot::while_statement(boot::make_position(@1), body);
 | 
			
		||||
            std::swap($5, $$->branches);
 | 
			
		||||
            boot::conditional_statements *body = new boot::conditional_statements($2, std::move($4));
 | 
			
		||||
            $$ = new boot::while_statement(boot::make_position(@1), body, std::move($5));
 | 
			
		||||
        }
 | 
			
		||||
    | "while" expression "," IDENTIFIER "do" statements elsif_do_statements "end"
 | 
			
		||||
        {
 | 
			
		||||
            boot::conditional_statements *body = new boot::conditional_statements($2, std::move($6));
 | 
			
		||||
            $$ = new boot::while_statement(boot::make_position(@1), body, std::move($7), $4);
 | 
			
		||||
        }
 | 
			
		||||
elsif_then_statements:
 | 
			
		||||
    "elsif" expression "then" statements elsif_then_statements
 | 
			
		||||
        {
 | 
			
		||||
            boot::conditional_statements *branch = new boot::conditional_statements($2);
 | 
			
		||||
            std::swap(branch->statements, $4);
 | 
			
		||||
            boot::conditional_statements *branch = new boot::conditional_statements($2, std::move($4));
 | 
			
		||||
            std::swap($5, $$);
 | 
			
		||||
            $$.emplace($$.begin(), branch);
 | 
			
		||||
        }
 | 
			
		||||
@@ -417,13 +421,16 @@ statement:
 | 
			
		||||
    | while_statement { $$ = $1; }
 | 
			
		||||
    | "if" expression "then" statements elsif_then_statements else_statements "end"
 | 
			
		||||
        {
 | 
			
		||||
            auto then = new boot::conditional_statements($2);
 | 
			
		||||
            std::swap($4, then->statements);
 | 
			
		||||
            boot::conditional_statements *then = new boot::conditional_statements($2, std::move($4));
 | 
			
		||||
            auto result = new boot::if_statement(boot::make_position(@1), then, $6);
 | 
			
		||||
            std::swap($5, result->branches);
 | 
			
		||||
			$$ = result;
 | 
			
		||||
            $$ = result;
 | 
			
		||||
        }
 | 
			
		||||
    | return_statement { $$ = $1; }
 | 
			
		||||
    | "break" IDENTIFIER
 | 
			
		||||
        { $$ = new boot::escape_statement(boot::make_position(@1), boot::escape_direction::end, $2); }
 | 
			
		||||
    | "repeat" IDENTIFIER
 | 
			
		||||
        { $$ = new boot::escape_statement(boot::make_position(@1), boot::escape_direction::begin, $2); }
 | 
			
		||||
    | call_expression { $$ = $1; }
 | 
			
		||||
    | "defer" statements "end" { $$ = new boot::defer_statement(boot::make_position(@1), std::move($2)); }
 | 
			
		||||
    | "case" expression "of" switch_cases else_statements "end"
 | 
			
		||||
@@ -523,7 +530,7 @@ variable_declarations:
 | 
			
		||||
variable_part:
 | 
			
		||||
    /* no variable declarations */ {}
 | 
			
		||||
    | "var" variable_declarations { std::swap($$, $2); }
 | 
			
		||||
constant_definition: identifier_definition "=" expression
 | 
			
		||||
constant_definition: identifier_definition ":=" expression
 | 
			
		||||
        {
 | 
			
		||||
            $$ = new boot::constant_definition(boot::make_position(@1), $1.first, $1.second, $3);
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -239,6 +239,10 @@ namespace elna::boot
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(escape_statement *)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(while_statement *statement)
 | 
			
		||||
    {
 | 
			
		||||
        statement->body().prerequisite().accept(this);
 | 
			
		||||
 
 | 
			
		||||
@@ -1174,7 +1174,7 @@ namespace elna::gcc
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(boot::if_statement *statement)
 | 
			
		||||
    {
 | 
			
		||||
        tree endif_label_decl = build_label_decl("endif", UNKNOWN_LOCATION);
 | 
			
		||||
        tree endif_label_decl = create_artificial_label(UNKNOWN_LOCATION);
 | 
			
		||||
        tree goto_endif = build1(GOTO_EXPR, void_type_node, endif_label_decl);
 | 
			
		||||
 | 
			
		||||
        make_if_branch(statement->body(), goto_endif);
 | 
			
		||||
@@ -1202,7 +1202,7 @@ namespace elna::gcc
 | 
			
		||||
        if (TREE_TYPE(this->current_expression) != elna_bool_type_node)
 | 
			
		||||
        {
 | 
			
		||||
            error_at(get_location(&branch.prerequisite().position()),
 | 
			
		||||
                    "expected expression of boolean type but its type is %s",
 | 
			
		||||
                    "Expected expression of boolean type but its type is %s",
 | 
			
		||||
                    print_type(TREE_TYPE(this->current_expression)).c_str());
 | 
			
		||||
            this->current_expression = error_mark_node;
 | 
			
		||||
            return;
 | 
			
		||||
@@ -1229,13 +1229,46 @@ namespace elna::gcc
 | 
			
		||||
        append_statement(else_label_expr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(boot::escape_statement *statement)
 | 
			
		||||
    {
 | 
			
		||||
        for (const auto& [begin, end] : this->loops)
 | 
			
		||||
        {
 | 
			
		||||
            if (statement->label == IDENTIFIER_POINTER(DECL_NAME(begin)))
 | 
			
		||||
            {
 | 
			
		||||
                tree target_declaration{ NULL_TREE };
 | 
			
		||||
 | 
			
		||||
                switch (statement->direction)
 | 
			
		||||
                {
 | 
			
		||||
                    case boot::escape_direction::begin:
 | 
			
		||||
                        target_declaration = begin;
 | 
			
		||||
                        break;
 | 
			
		||||
                    case boot::escape_direction::end:
 | 
			
		||||
                        target_declaration = end;
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        gcc_unreachable();
 | 
			
		||||
                }
 | 
			
		||||
                tree goto_expression = build1(GOTO_EXPR, void_type_node, target_declaration);
 | 
			
		||||
                TREE_USED(target_declaration) = 1;
 | 
			
		||||
                append_statement(goto_expression);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        error_at(get_location(&statement->position()), "Unknown loop labeled '%s'", statement->label.c_str());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(boot::while_statement *statement)
 | 
			
		||||
    {
 | 
			
		||||
        auto prerequisite_location = get_location(&statement->body().prerequisite().position());
 | 
			
		||||
        auto prerequisite_label_decl = build_label_decl("while_check", prerequisite_location);
 | 
			
		||||
        std::string loop_identifier = statement->label.value_or("while");
 | 
			
		||||
        location_t prerequisite_location = get_location(&statement->body().prerequisite().position());
 | 
			
		||||
        tree prerequisite_label_decl = build_label_decl(loop_identifier.c_str(), prerequisite_location);
 | 
			
		||||
        auto prerequisite_label_expr = build1_loc(prerequisite_location, LABEL_EXPR,
 | 
			
		||||
                void_type_node, prerequisite_label_decl);
 | 
			
		||||
        auto goto_check = build1(GOTO_EXPR, void_type_node, prerequisite_label_decl);
 | 
			
		||||
        tree branch_end_declaration = build_label_decl(loop_identifier.c_str(), UNKNOWN_LOCATION);
 | 
			
		||||
        tree branch_end_expression = build1_loc(UNKNOWN_LOCATION, LABEL_EXPR, void_type_node, branch_end_declaration);
 | 
			
		||||
 | 
			
		||||
        this->loops.push_front({ prerequisite_label_decl, branch_end_declaration });
 | 
			
		||||
 | 
			
		||||
        append_statement(prerequisite_label_expr);
 | 
			
		||||
        make_if_branch(statement->body(), goto_check);
 | 
			
		||||
@@ -1244,6 +1277,7 @@ namespace elna::gcc
 | 
			
		||||
        {
 | 
			
		||||
            make_if_branch(*branch, goto_check);
 | 
			
		||||
        }
 | 
			
		||||
        append_statement(branch_end_expression);
 | 
			
		||||
        this->current_expression = NULL_TREE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include "elna/boot/result.h"
 | 
			
		||||
 | 
			
		||||
namespace elna::boot
 | 
			
		||||
@@ -52,6 +53,12 @@ namespace elna::boot
 | 
			
		||||
        minus
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum class escape_direction
 | 
			
		||||
    {
 | 
			
		||||
        begin,
 | 
			
		||||
        end
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class variable_declaration;
 | 
			
		||||
    class constant_definition;
 | 
			
		||||
    class procedure_definition;
 | 
			
		||||
@@ -60,6 +67,7 @@ namespace elna::boot
 | 
			
		||||
    class cast_expression;
 | 
			
		||||
    class assign_statement;
 | 
			
		||||
    class if_statement;
 | 
			
		||||
    class escape_statement;
 | 
			
		||||
    class while_statement;
 | 
			
		||||
    class return_statement;
 | 
			
		||||
    class case_statement;
 | 
			
		||||
@@ -99,6 +107,7 @@ namespace elna::boot
 | 
			
		||||
        virtual void visit(traits_expression *) = 0;
 | 
			
		||||
        virtual void visit(assign_statement *) = 0;
 | 
			
		||||
        virtual void visit(if_statement *) = 0;
 | 
			
		||||
        virtual void visit(escape_statement *) = 0;
 | 
			
		||||
        virtual void visit(while_statement *) = 0;
 | 
			
		||||
        virtual void visit(return_statement *) = 0;
 | 
			
		||||
        virtual void visit(defer_statement *) = 0;
 | 
			
		||||
@@ -152,13 +161,6 @@ namespace elna::boot
 | 
			
		||||
 | 
			
		||||
    class statement : public virtual node
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        virtual assign_statement *is_assign();
 | 
			
		||||
        virtual if_statement *is_if();
 | 
			
		||||
        virtual while_statement *is_while();
 | 
			
		||||
        virtual return_statement *is_return();
 | 
			
		||||
        virtual defer_statement *is_defer();
 | 
			
		||||
        virtual procedure_call *is_call_statement();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class expression : public virtual node
 | 
			
		||||
@@ -428,9 +430,9 @@ namespace elna::boot
 | 
			
		||||
        expression *m_prerequisite;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        std::vector<statement *> statements;
 | 
			
		||||
        const std::vector<statement *> statements;
 | 
			
		||||
 | 
			
		||||
        conditional_statements(expression *prerequisite);
 | 
			
		||||
        conditional_statements(expression *prerequisite, std::vector<statement *>&& statements);
 | 
			
		||||
 | 
			
		||||
        expression& prerequisite();
 | 
			
		||||
 | 
			
		||||
@@ -444,7 +446,6 @@ namespace elna::boot
 | 
			
		||||
 | 
			
		||||
        return_statement(const struct position position, expression *return_expression = nullptr);
 | 
			
		||||
        void accept(parser_visitor *visitor) override;
 | 
			
		||||
        virtual return_statement *is_return() override;
 | 
			
		||||
 | 
			
		||||
        virtual ~return_statement() override;
 | 
			
		||||
    };
 | 
			
		||||
@@ -558,7 +559,6 @@ namespace elna::boot
 | 
			
		||||
 | 
			
		||||
        procedure_call(const struct position position, designator_expression *callable);
 | 
			
		||||
        void accept(parser_visitor *visitor) override;
 | 
			
		||||
        virtual procedure_call *is_call_statement() override;
 | 
			
		||||
        virtual procedure_call *is_call_expression() override;
 | 
			
		||||
 | 
			
		||||
        designator_expression& callable();
 | 
			
		||||
@@ -585,7 +585,6 @@ namespace elna::boot
 | 
			
		||||
        expression& rvalue();
 | 
			
		||||
 | 
			
		||||
        virtual ~assign_statement() override;
 | 
			
		||||
        assign_statement *is_assign() override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -602,13 +601,23 @@ namespace elna::boot
 | 
			
		||||
        if_statement(const struct position position, conditional_statements *body,
 | 
			
		||||
                std::vector<statement *> *alternative = nullptr);
 | 
			
		||||
        void accept(parser_visitor *visitor) override;
 | 
			
		||||
        virtual if_statement *is_if() override;
 | 
			
		||||
 | 
			
		||||
        conditional_statements& body();
 | 
			
		||||
 | 
			
		||||
        virtual ~if_statement() override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class escape_statement : public statement
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        const escape_direction direction;
 | 
			
		||||
        const std::string label;
 | 
			
		||||
 | 
			
		||||
        escape_statement(const struct position position,
 | 
			
		||||
                escape_direction direction, const std::string& label);
 | 
			
		||||
        void accept(parser_visitor *visitor) override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * While-statement.
 | 
			
		||||
     */
 | 
			
		||||
@@ -617,10 +626,14 @@ namespace elna::boot
 | 
			
		||||
        conditional_statements *m_body;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        std::vector<conditional_statements *> branches;
 | 
			
		||||
        while_statement(const struct position position, conditional_statements *body);
 | 
			
		||||
        const std::vector<conditional_statements *> branches;
 | 
			
		||||
        const std::optional<std::string> label;
 | 
			
		||||
 | 
			
		||||
        while_statement(const struct position position, conditional_statements *body,
 | 
			
		||||
                std::vector<conditional_statements *>&& branches);
 | 
			
		||||
        while_statement(const struct position position, conditional_statements *body,
 | 
			
		||||
                std::vector<conditional_statements *>&& branches, const std::string& label);
 | 
			
		||||
        void accept(parser_visitor *visitor) override;
 | 
			
		||||
        while_statement *is_while() override;
 | 
			
		||||
 | 
			
		||||
        conditional_statements& body();
 | 
			
		||||
 | 
			
		||||
@@ -676,7 +689,6 @@ namespace elna::boot
 | 
			
		||||
 | 
			
		||||
        defer_statement(const struct position position, std::vector<statement *>&& statements);
 | 
			
		||||
        void accept(parser_visitor *visitor) override;
 | 
			
		||||
        defer_statement *is_defer() override;
 | 
			
		||||
 | 
			
		||||
        virtual ~defer_statement() override;
 | 
			
		||||
    };
 | 
			
		||||
 
 | 
			
		||||
@@ -75,6 +75,7 @@ namespace elna::boot
 | 
			
		||||
        void visit(procedure_definition *definition) override;
 | 
			
		||||
        void visit(assign_statement *statement) override;
 | 
			
		||||
        void visit(if_statement *statement) override;
 | 
			
		||||
        void visit(escape_statement *) override;
 | 
			
		||||
        void visit(while_statement *statement) override;
 | 
			
		||||
        void visit(return_statement *statement) override;
 | 
			
		||||
        void visit(defer_statement *statement) override;
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3.  If not see
 | 
			
		||||
#include "tree-iterator.h"
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <forward_list>
 | 
			
		||||
 | 
			
		||||
namespace elna::gcc
 | 
			
		||||
{
 | 
			
		||||
@@ -45,6 +46,7 @@ namespace elna::gcc
 | 
			
		||||
        tree current_expression{ NULL_TREE };
 | 
			
		||||
        std::shared_ptr<symbol_table> symbols;
 | 
			
		||||
        std::unordered_map<std::string, tree> unresolved;
 | 
			
		||||
        std::forward_list<std::pair<tree, tree>> loops;
 | 
			
		||||
 | 
			
		||||
        void declare_procedure(boot::procedure_definition *const definition);
 | 
			
		||||
        tree build_procedure_type(boot::procedure_type_expression& type);
 | 
			
		||||
@@ -100,6 +102,7 @@ namespace elna::gcc
 | 
			
		||||
        void visit(boot::block *block) override;
 | 
			
		||||
        void visit(boot::assign_statement *statement) override;
 | 
			
		||||
        void visit(boot::if_statement *statement) override;
 | 
			
		||||
        void visit(boot::escape_statement *statement) override;
 | 
			
		||||
        void visit(boot::while_statement *statement) override;
 | 
			
		||||
        void visit(boot::named_type_expression *type) override;
 | 
			
		||||
        void visit(boot::array_type_expression *type) override;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								source.elna
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								source.elna
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
			
		||||
const
 | 
			
		||||
  SEEK_SET* = 0;
 | 
			
		||||
  SEEK_CUR* = 1;
 | 
			
		||||
  SEEK_END* = 2;
 | 
			
		||||
  SEEK_SET* := 0;
 | 
			
		||||
  SEEK_CUR* := 1;
 | 
			
		||||
  SEEK_END* := 2;
 | 
			
		||||
 | 
			
		||||
type
 | 
			
		||||
  TokenKind* = (
 | 
			
		||||
@@ -404,9 +404,15 @@ begin
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc skip_spaces(source_code: ^SourceCode);
 | 
			
		||||
var
 | 
			
		||||
  current: Char;
 | 
			
		||||
begin
 | 
			
		||||
  while ~source_code_empty(source_code) & is_space(source_code_head(source_code^)) do
 | 
			
		||||
    if source_code_head(source_code^) = '\n' then
 | 
			
		||||
  while ~source_code_empty(source_code), loop do
 | 
			
		||||
    current := source_code_head(source_code^);
 | 
			
		||||
 | 
			
		||||
    if ~is_space(current) then
 | 
			
		||||
      break loop
 | 
			
		||||
    elsif current = '\n' then
 | 
			
		||||
      source_code_break(source_code)
 | 
			
		||||
	end;
 | 
			
		||||
	source_code_advance(source_code)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user