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