Allow only one return
This commit is contained in:
		
							
								
								
									
										62
									
								
								boot/ast.cc
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								boot/ast.cc
									
									
									
									
									
								
							@@ -86,24 +86,6 @@ namespace boot
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(return_statement *statement)
 | 
			
		||||
    {
 | 
			
		||||
        expression *return_expression = statement->return_expression();
 | 
			
		||||
 | 
			
		||||
        if (return_expression != nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            return_expression->accept(this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(defer_statement *defer)
 | 
			
		||||
    {
 | 
			
		||||
        for (statement *const body_statement : defer->statements)
 | 
			
		||||
        {
 | 
			
		||||
            body_statement->accept(this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void empty_visitor::visit(block *block)
 | 
			
		||||
    {
 | 
			
		||||
        for (constant_definition *const constant : block->constants)
 | 
			
		||||
@@ -448,8 +430,9 @@ namespace boot
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
 | 
			
		||||
            const bool exported, std::shared_ptr<procedure_type> heading, block *body)
 | 
			
		||||
        : definition(position, identifier, exported), m_heading(heading), body(body)
 | 
			
		||||
            const bool exported, std::shared_ptr<procedure_type> heading,
 | 
			
		||||
            block *const body, expression *const returning)
 | 
			
		||||
        : definition(position, identifier, exported), m_heading(heading), body(body), returning(returning)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -466,6 +449,7 @@ namespace boot
 | 
			
		||||
    procedure_definition::~procedure_definition()
 | 
			
		||||
    {
 | 
			
		||||
        delete body;
 | 
			
		||||
        delete returning;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    type_definition::type_definition(const struct position position, const std::string& identifier,
 | 
			
		||||
@@ -536,24 +520,6 @@ namespace boot
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    defer_statement::defer_statement(const struct position position)
 | 
			
		||||
        : node(position)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void defer_statement::accept(parser_visitor *visitor)
 | 
			
		||||
    {
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    defer_statement::~defer_statement()
 | 
			
		||||
    {
 | 
			
		||||
        for (statement *body_statement : statements)
 | 
			
		||||
        {
 | 
			
		||||
            delete body_statement;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    designator_expression::designator_expression()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
@@ -805,26 +771,6 @@ namespace boot
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return_statement::return_statement(const struct position position, expression *return_expression)
 | 
			
		||||
        : node(position), m_return_expression(return_expression)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void return_statement::accept(parser_visitor *visitor)
 | 
			
		||||
    {
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    expression *return_statement::return_expression()
 | 
			
		||||
    {
 | 
			
		||||
        return m_return_expression;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return_statement::~return_statement()
 | 
			
		||||
    {
 | 
			
		||||
        delete m_return_expression;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void assign_statement::accept(parser_visitor *visitor)
 | 
			
		||||
    {
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
 
 | 
			
		||||
@@ -125,9 +125,6 @@ return                  {
 | 
			
		||||
cast                    {
 | 
			
		||||
                            return yy::parser::make_CAST(this->location);
 | 
			
		||||
                        }
 | 
			
		||||
defer                   {
 | 
			
		||||
                            return yy::parser::make_DEFER(this->location);
 | 
			
		||||
                        }
 | 
			
		||||
[A-Za-z_][A-Za-z0-9_]*  {
 | 
			
		||||
                            return yy::parser::make_IDENTIFIER(yytext, this->location);
 | 
			
		||||
                        }
 | 
			
		||||
 
 | 
			
		||||
@@ -106,7 +106,6 @@ along with GCC; see the file COPYING3.  If not see
 | 
			
		||||
    RETURN "return"
 | 
			
		||||
    BEGIN_BLOCK "begin"
 | 
			
		||||
    END_BLOCK "end"
 | 
			
		||||
    DEFER "defer"
 | 
			
		||||
%token OR "or" AND "and" XOR "xor"
 | 
			
		||||
    EQUALS "=" NOT_EQUAL "<>" LESS_THAN "<" GREATER_THAN ">" LESS_EQUAL "<=" GREATER_EQUAL ">="
 | 
			
		||||
    SHIFT_LEFT "<<" SHIFT_RIGHT ">>"
 | 
			
		||||
@@ -134,12 +133,12 @@ along with GCC; see the file COPYING3.  If not see
 | 
			
		||||
%type <elna::boot::procedure_call*> call_expression;
 | 
			
		||||
%type <elna::boot::while_statement *> while_statement;
 | 
			
		||||
%type <elna::boot::if_statement *> if_statement;
 | 
			
		||||
%type <elna::boot::return_statement *> return_statement;
 | 
			
		||||
%type <elna::boot::expression *> return_statement;
 | 
			
		||||
%type <elna::boot::statement *> statement;
 | 
			
		||||
%type <std::vector<elna::boot::statement *>> statements optional_statements;
 | 
			
		||||
%type <std::vector<elna::boot::statement *>> statements statement_part;
 | 
			
		||||
%type <elna::boot::procedure_definition *> procedure_definition;
 | 
			
		||||
%type <std::shared_ptr<elna::boot::procedure_type>> procedure_heading;
 | 
			
		||||
%type <std::vector<elna::boot::procedure_definition *>> procedure_definitions procedure_part;
 | 
			
		||||
%type <std::vector<elna::boot::procedure_definition *>> procedure_definitions;
 | 
			
		||||
%type <elna::boot::type_definition *> type_definition;
 | 
			
		||||
%type <std::vector<elna::boot::type_definition *>> type_definitions type_part;
 | 
			
		||||
%type <elna::boot::block *> block;
 | 
			
		||||
@@ -147,12 +146,11 @@ along with GCC; see the file COPYING3.  If not see
 | 
			
		||||
%type <std::vector<std::pair<std::string, std::shared_ptr<elna::boot::top_type>>>> optional_fields fields;
 | 
			
		||||
%type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements;
 | 
			
		||||
%type <elna::boot::cast_expression *> cast_expression;
 | 
			
		||||
%type <elna::boot::defer_statement *> defer_statement;
 | 
			
		||||
%type <std::pair<std::string, bool>> identifier_definition;
 | 
			
		||||
%type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
 | 
			
		||||
%%
 | 
			
		||||
program:
 | 
			
		||||
    constant_part type_part variable_part procedure_part "begin" optional_statements "end" "."
 | 
			
		||||
    constant_part type_part variable_part procedure_definitions "begin" statements "end" "."
 | 
			
		||||
        {
 | 
			
		||||
            auto tree = new elna::boot::program(elna::boot::make_position(@5));
 | 
			
		||||
 | 
			
		||||
@@ -164,13 +162,13 @@ program:
 | 
			
		||||
 | 
			
		||||
            driver.tree.reset(tree);
 | 
			
		||||
        }
 | 
			
		||||
block: constant_part variable_part "begin" optional_statements "end"
 | 
			
		||||
block: constant_part variable_part statement_part
 | 
			
		||||
        {
 | 
			
		||||
            $$ = new elna::boot::block(elna::boot::make_position(@3));
 | 
			
		||||
            $$ = new elna::boot::block(elna::boot::make_position(@1));
 | 
			
		||||
 | 
			
		||||
            std::swap($$->constants, $1);
 | 
			
		||||
            std::swap($$->variables, $2);
 | 
			
		||||
            std::swap($$->body, $4);
 | 
			
		||||
            std::swap($$->body, $3);
 | 
			
		||||
        }
 | 
			
		||||
identifier_definition:
 | 
			
		||||
    IDENTIFIER "*"
 | 
			
		||||
@@ -205,9 +203,10 @@ procedure_heading:
 | 
			
		||||
            std::swap($1, $$->parameters);
 | 
			
		||||
        }
 | 
			
		||||
procedure_definition:
 | 
			
		||||
    "proc" identifier_definition procedure_heading ";" block
 | 
			
		||||
    "proc" identifier_definition procedure_heading ";" block return_statement "end"
 | 
			
		||||
        {
 | 
			
		||||
            $$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), $2.first, $2.second, $3, $5);
 | 
			
		||||
            $$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), $2.first, $2.second,
 | 
			
		||||
                $3, $5, $6);
 | 
			
		||||
        }
 | 
			
		||||
    | "proc" identifier_definition procedure_heading ";" "extern"
 | 
			
		||||
        {
 | 
			
		||||
@@ -219,10 +218,7 @@ procedure_definitions:
 | 
			
		||||
            std::swap($$, $2);
 | 
			
		||||
            $$.emplace($$.cbegin(), std::move($1));
 | 
			
		||||
        }
 | 
			
		||||
    | procedure_definition { $$.emplace_back(std::move($1)); }
 | 
			
		||||
procedure_part:
 | 
			
		||||
    /* no procedure definitions */ {}
 | 
			
		||||
    | procedure_definitions { std::swap($$, $1); }
 | 
			
		||||
    | /* no procedure definitions */ {}
 | 
			
		||||
assign_statement: designator_expression ":=" expression
 | 
			
		||||
        {
 | 
			
		||||
            $$ = new elna::boot::assign_statement(elna::boot::make_position(@1), $1, $3);
 | 
			
		||||
@@ -237,7 +233,7 @@ cast_expression: "cast" "(" expression ":" type_expression ")"
 | 
			
		||||
            $$ = new elna::boot::cast_expression(elna::boot::make_position(@1), $5, $3);
 | 
			
		||||
        }
 | 
			
		||||
elsif_do_statements:
 | 
			
		||||
    "elsif" expression "do" optional_statements elsif_do_statements
 | 
			
		||||
    "elsif" expression "do" statements elsif_do_statements
 | 
			
		||||
        {
 | 
			
		||||
            elna::boot::conditional_statements *branch = new elna::boot::conditional_statements($2);
 | 
			
		||||
            std::swap(branch->statements, $4);
 | 
			
		||||
@@ -245,7 +241,7 @@ elsif_do_statements:
 | 
			
		||||
            $$.emplace($$.begin(), branch);
 | 
			
		||||
        }
 | 
			
		||||
    | {}
 | 
			
		||||
while_statement: "while" expression "do" optional_statements elsif_do_statements "end"
 | 
			
		||||
while_statement: "while" expression "do" statements elsif_do_statements "end"
 | 
			
		||||
        {
 | 
			
		||||
            auto body = new elna::boot::conditional_statements($2);
 | 
			
		||||
            std::swap($4, body->statements);
 | 
			
		||||
@@ -253,7 +249,7 @@ while_statement: "while" expression "do" optional_statements elsif_do_statements
 | 
			
		||||
            std::swap($5, $$->branches);
 | 
			
		||||
        }
 | 
			
		||||
elsif_then_statements:
 | 
			
		||||
    "elsif" expression "then" optional_statements elsif_then_statements
 | 
			
		||||
    "elsif" expression "then" statements elsif_then_statements
 | 
			
		||||
        {
 | 
			
		||||
            elna::boot::conditional_statements *branch = new elna::boot::conditional_statements($2);
 | 
			
		||||
            std::swap(branch->statements, $4);
 | 
			
		||||
@@ -262,14 +258,14 @@ elsif_then_statements:
 | 
			
		||||
        }
 | 
			
		||||
    | {}
 | 
			
		||||
if_statement:
 | 
			
		||||
    "if" expression "then" optional_statements elsif_then_statements "end"
 | 
			
		||||
    "if" expression "then" statements elsif_then_statements "end"
 | 
			
		||||
        {
 | 
			
		||||
            auto then = new elna::boot::conditional_statements($2);
 | 
			
		||||
            std::swap($4, then->statements);
 | 
			
		||||
            $$ = new elna::boot::if_statement(elna::boot::make_position(@1), then);
 | 
			
		||||
            std::swap($5, $$->branches);
 | 
			
		||||
        }
 | 
			
		||||
    | "if" expression "then" optional_statements elsif_then_statements "else" optional_statements "end"
 | 
			
		||||
    | "if" expression "then" statements elsif_then_statements "else" statements "end"
 | 
			
		||||
        {
 | 
			
		||||
            auto then = new elna::boot::conditional_statements($2);
 | 
			
		||||
            std::swap($4, then->statements);
 | 
			
		||||
@@ -277,15 +273,12 @@ if_statement:
 | 
			
		||||
            $$ = new elna::boot::if_statement(elna::boot::make_position(@1), then, _else);
 | 
			
		||||
            std::swap($5, $$->branches);
 | 
			
		||||
        }
 | 
			
		||||
return_statement: "return" expression
 | 
			
		||||
return_statement:
 | 
			
		||||
    "return" expression
 | 
			
		||||
        {
 | 
			
		||||
            $$ = new elna::boot::return_statement(elna::boot::make_position(@1), $2);
 | 
			
		||||
        }
 | 
			
		||||
defer_statement: DEFER optional_statements "end"
 | 
			
		||||
        {
 | 
			
		||||
            $$ = new elna::boot::defer_statement(elna::boot::make_position(@1));
 | 
			
		||||
            std::swap($2, $$->statements);
 | 
			
		||||
            $$ = $2;
 | 
			
		||||
        }
 | 
			
		||||
    | /* no return statement */ { $$ = nullptr; }
 | 
			
		||||
literal:
 | 
			
		||||
    INTEGER
 | 
			
		||||
        {
 | 
			
		||||
@@ -454,19 +447,17 @@ statement:
 | 
			
		||||
    assign_statement { $$ = $1; }
 | 
			
		||||
    | while_statement { $$ = $1; }
 | 
			
		||||
    | if_statement { $$ = $1; }
 | 
			
		||||
    | return_statement { $$ = $1; }
 | 
			
		||||
    | call_expression { $$ = $1; }
 | 
			
		||||
    | defer_statement { $$ = $1; }
 | 
			
		||||
statements:
 | 
			
		||||
    statement statements
 | 
			
		||||
        {
 | 
			
		||||
            std::swap($$, $2);
 | 
			
		||||
            $$.emplace($$.cbegin(), $1);
 | 
			
		||||
        }
 | 
			
		||||
    | statement { $$.push_back($1); }
 | 
			
		||||
optional_statements:
 | 
			
		||||
    statements { std::swap($$, $1); }
 | 
			
		||||
    | /* no statements */ {}
 | 
			
		||||
statement_part:
 | 
			
		||||
    "begin" statements { std::swap($$, $2); }
 | 
			
		||||
    | {}
 | 
			
		||||
field_declaration:
 | 
			
		||||
    IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); }
 | 
			
		||||
fields:
 | 
			
		||||
 
 | 
			
		||||
@@ -294,6 +294,7 @@ namespace gcc
 | 
			
		||||
        if (definition->body != nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            definition->body->accept(this);
 | 
			
		||||
            visit_return(definition->returning);
 | 
			
		||||
            tree mapping = leave_scope();
 | 
			
		||||
 | 
			
		||||
            BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl;
 | 
			
		||||
@@ -334,7 +335,7 @@ namespace gcc
 | 
			
		||||
        {
 | 
			
		||||
            BLOCK_SUPERCONTEXT(it) = new_block;
 | 
			
		||||
        }
 | 
			
		||||
        tree bind_expr = build3(BIND_EXPR, void_type_node, variables, chain_defer(), new_block);
 | 
			
		||||
        tree bind_expr = build3(BIND_EXPR, void_type_node, variables, f_binding_level->statement_list, new_block);
 | 
			
		||||
        this->symbol_map = this->symbol_map->scope();
 | 
			
		||||
 | 
			
		||||
        f_binding_level = f_binding_level->level_chain;
 | 
			
		||||
@@ -1174,10 +1175,8 @@ namespace gcc
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(boot::return_statement *statement)
 | 
			
		||||
    void generic_visitor::visit_return(boot::expression *const return_expression)
 | 
			
		||||
    {
 | 
			
		||||
        boot::expression *return_expression = statement->return_expression();
 | 
			
		||||
 | 
			
		||||
        if (return_expression == nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            return;
 | 
			
		||||
@@ -1191,12 +1190,5 @@ namespace gcc
 | 
			
		||||
 | 
			
		||||
        this->current_expression = NULL_TREE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(boot::defer_statement *statement)
 | 
			
		||||
    {
 | 
			
		||||
        enter_scope();
 | 
			
		||||
        visit_statements(statement->statements);
 | 
			
		||||
        defer(leave_scope());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -91,40 +91,7 @@ namespace gcc
 | 
			
		||||
 | 
			
		||||
    void append_statement(tree statement_tree)
 | 
			
		||||
    {
 | 
			
		||||
        if (!vec_safe_is_empty(f_binding_level->defers))
 | 
			
		||||
        {
 | 
			
		||||
            append_to_statement_list(statement_tree, &f_binding_level->defers->begin()->try_statements);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            append_to_statement_list(statement_tree, &f_binding_level->statement_list);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void defer(tree statement_tree)
 | 
			
		||||
    {
 | 
			
		||||
        defer_scope new_defer{ statement_tree, alloc_stmt_list() };
 | 
			
		||||
        vec_safe_insert(f_binding_level->defers, 0, new_defer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tree chain_defer()
 | 
			
		||||
    {
 | 
			
		||||
        if (vec_safe_is_empty(f_binding_level->defers))
 | 
			
		||||
        {
 | 
			
		||||
            return f_binding_level->statement_list;
 | 
			
		||||
        }
 | 
			
		||||
        defer_scope *defer_iterator = f_binding_level->defers->begin();
 | 
			
		||||
        tree defer_tree = build2(TRY_FINALLY_EXPR, void_type_node,
 | 
			
		||||
                defer_iterator->try_statements, defer_iterator->defer_block);
 | 
			
		||||
        int i;
 | 
			
		||||
 | 
			
		||||
        FOR_EACH_VEC_ELT_FROM(*f_binding_level->defers, i, defer_iterator, 1)
 | 
			
		||||
        {
 | 
			
		||||
            append_to_statement_list(defer_tree, &defer_iterator->try_statements);
 | 
			
		||||
            defer_tree = build2(TRY_FINALLY_EXPR, void_type_node,
 | 
			
		||||
                    defer_iterator->try_statements, defer_iterator->defer_block);
 | 
			
		||||
        }
 | 
			
		||||
        return build2(COMPOUND_EXPR, TREE_TYPE(defer_tree), f_binding_level->statement_list, defer_tree);
 | 
			
		||||
        append_to_statement_list(statement_tree, &f_binding_level->statement_list);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tree build_field(location_t location, tree record_type, const std::string name, tree type)
 | 
			
		||||
 
 | 
			
		||||
@@ -63,7 +63,6 @@ namespace boot
 | 
			
		||||
    class assign_statement;
 | 
			
		||||
    class if_statement;
 | 
			
		||||
    class while_statement;
 | 
			
		||||
    class return_statement;
 | 
			
		||||
    class traits_expression;
 | 
			
		||||
    class block;
 | 
			
		||||
    class program;
 | 
			
		||||
@@ -81,7 +80,6 @@ namespace boot
 | 
			
		||||
    class dereference_expression;
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    class number_literal;
 | 
			
		||||
    class defer_statement;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Interface for AST visitors.
 | 
			
		||||
@@ -98,8 +96,6 @@ namespace boot
 | 
			
		||||
        virtual void visit(assign_statement *) = 0;
 | 
			
		||||
        virtual void visit(if_statement *) = 0;
 | 
			
		||||
        virtual void visit(while_statement *) = 0;
 | 
			
		||||
        virtual void visit(return_statement *) = 0;
 | 
			
		||||
        virtual void visit(defer_statement *) = 0;
 | 
			
		||||
        virtual void visit(block *) = 0;
 | 
			
		||||
        virtual void visit(program *) = 0;
 | 
			
		||||
        virtual void visit(binary_expression *) = 0;
 | 
			
		||||
@@ -138,8 +134,6 @@ namespace boot
 | 
			
		||||
        virtual void visit(assign_statement *statement) override;
 | 
			
		||||
        virtual void visit(if_statement *) override;
 | 
			
		||||
        virtual void visit(while_statement *) override;
 | 
			
		||||
        virtual void visit(return_statement *) override;
 | 
			
		||||
        virtual void visit(defer_statement *defer) override;
 | 
			
		||||
        virtual void visit(block *block) override;
 | 
			
		||||
        virtual void visit(program *program) override;
 | 
			
		||||
        virtual void visit(binary_expression *expression) override;
 | 
			
		||||
@@ -383,9 +377,11 @@ namespace boot
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        block *const body;
 | 
			
		||||
        expression *const returning;
 | 
			
		||||
 | 
			
		||||
        procedure_definition(const struct position position, const std::string& identifier,
 | 
			
		||||
                const bool exported, std::shared_ptr<procedure_type> heading, block *body = nullptr);
 | 
			
		||||
                const bool exported, std::shared_ptr<procedure_type> heading,
 | 
			
		||||
                block *const body = nullptr, expression *const returning = nullptr);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        procedure_type& heading();
 | 
			
		||||
@@ -456,19 +452,6 @@ namespace boot
 | 
			
		||||
        virtual ~conditional_statements();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class return_statement : public statement
 | 
			
		||||
    {
 | 
			
		||||
        expression *m_return_expression{ nullptr };
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        return_statement(const struct position position, expression *return_expression);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        expression *return_expression();
 | 
			
		||||
 | 
			
		||||
        virtual ~return_statement() override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class designator_expression : public expression
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
@@ -661,17 +644,6 @@ namespace boot
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class defer_statement : public statement
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        std::vector<statement *> statements;
 | 
			
		||||
 | 
			
		||||
        defer_statement(const struct position position);
 | 
			
		||||
        virtual void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        virtual ~defer_statement() override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class binary_expression : public expression
 | 
			
		||||
    {
 | 
			
		||||
        expression *m_lhs;
 | 
			
		||||
 
 | 
			
		||||
@@ -61,6 +61,7 @@ namespace gcc
 | 
			
		||||
        void build_record_call(location_t call_location,
 | 
			
		||||
                tree symbol, const std::vector<boot::expression *>& arguments);
 | 
			
		||||
        void visit_statements(const std::vector<boot::statement *>& statements);
 | 
			
		||||
        void visit_return(boot::expression *const return_expression);
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        generic_visitor(std::shared_ptr<symbol_table> symbol_table);
 | 
			
		||||
@@ -90,8 +91,6 @@ namespace gcc
 | 
			
		||||
        void visit(boot::assign_statement *statement) override;
 | 
			
		||||
        void visit(boot::if_statement *statement) override;
 | 
			
		||||
        void visit(boot::while_statement *statement) override;
 | 
			
		||||
        void visit(boot::return_statement *statement) override;
 | 
			
		||||
        void visit(boot::defer_statement *statement) override;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -72,8 +72,6 @@ namespace gcc
 | 
			
		||||
    bool is_assignable_from(tree assignee, tree assignment);
 | 
			
		||||
 | 
			
		||||
    void append_statement(tree statement_tree);
 | 
			
		||||
    void defer(tree statement_tree);
 | 
			
		||||
    tree chain_defer();
 | 
			
		||||
 | 
			
		||||
    tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right);
 | 
			
		||||
    tree build_binary_operation(bool condition, boot::binary_expression *expression,
 | 
			
		||||
 
 | 
			
		||||
@@ -58,12 +58,6 @@ struct GTY (()) lang_decl
 | 
			
		||||
{
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct GTY (()) defer_scope
 | 
			
		||||
{
 | 
			
		||||
    tree defer_block;
 | 
			
		||||
    tree try_statements;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct GTY ((chain_next ("%h.level_chain"))) binding_level
 | 
			
		||||
{
 | 
			
		||||
    // A block chain is needed to call defer statements beloning to each block.
 | 
			
		||||
@@ -74,9 +68,6 @@ struct GTY ((chain_next ("%h.level_chain"))) binding_level
 | 
			
		||||
 | 
			
		||||
    // Statements before the first defer has been seen.
 | 
			
		||||
    tree statement_list;
 | 
			
		||||
 | 
			
		||||
    // Defer statement coupled with statements following it.
 | 
			
		||||
    vec<defer_scope, va_gc> *defers;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct GTY (()) language_function
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								source.elna
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								source.elna
									
									
									
									
									
								
							@@ -140,7 +140,6 @@ proc exit(code: Int) -> !; extern
 | 
			
		||||
  Standard procedures.
 | 
			
		||||
*)
 | 
			
		||||
proc reallocarray(ptr: ^Byte, n: Word, size: Word) -> ^Byte;
 | 
			
		||||
begin
 | 
			
		||||
  return realloc(ptr, n * size)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@@ -198,32 +197,26 @@ begin
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc is_digit(c: Char) -> Bool;
 | 
			
		||||
begin
 | 
			
		||||
  return cast(c: Int) >= cast('0': Int) and cast(c: Int) <= cast('9': Int)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc is_alpha(c: Char) -> Bool;
 | 
			
		||||
begin
 | 
			
		||||
  return cast(c: Int) >= cast('A': Int) and cast(c: Int) <= cast('z': Int)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc is_alnum(c: Char) -> Bool;
 | 
			
		||||
begin
 | 
			
		||||
  return is_digit(c) or is_alpha(c)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc is_space(c: Char) -> Bool;
 | 
			
		||||
begin
 | 
			
		||||
  return c = ' ' or c = '\n' or c = '\t'
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc substring(string: String, start: Word, count: Word) -> String;
 | 
			
		||||
begin
 | 
			
		||||
  return String(string.ptr + start, count)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc open_substring(string: String, start: Word) -> String;
 | 
			
		||||
begin
 | 
			
		||||
  return substring(string, start, string.length - start)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@@ -277,7 +270,6 @@ end
 | 
			
		||||
*)
 | 
			
		||||
 | 
			
		||||
proc make_position() -> Position;
 | 
			
		||||
begin
 | 
			
		||||
  return Position(1u, 1u)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@@ -376,12 +368,10 @@ begin
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc source_code_empty(source_code: ^SourceCode) -> Bool;
 | 
			
		||||
begin
 | 
			
		||||
  return source_code^.empty(source_code^.input)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc source_code_head(source_code: SourceCode) -> Char;
 | 
			
		||||
begin
 | 
			
		||||
  return source_code.head(source_code.input)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@@ -398,7 +388,6 @@ begin
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc source_code_expect(source_code: ^SourceCode, expected: Char) -> Bool;
 | 
			
		||||
begin
 | 
			
		||||
  return not source_code_empty(source_code) and source_code_head(source_code^) = expected
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@@ -413,7 +402,6 @@ begin
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
proc is_ident(char: Char) -> Bool;
 | 
			
		||||
begin
 | 
			
		||||
  return is_alnum(char) or char = '_'
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@@ -916,7 +904,7 @@ begin
 | 
			
		||||
  result^.syntax_tree := false
 | 
			
		||||
  result^.input := nil
 | 
			
		||||
 | 
			
		||||
  while i < argc do
 | 
			
		||||
  while i < argc and result <> nil do
 | 
			
		||||
    parameter := argv + i
 | 
			
		||||
 | 
			
		||||
    if strcmp(parameter^, "--tokenize\0".ptr) = 0 then
 | 
			
		||||
@@ -932,14 +920,14 @@ begin
 | 
			
		||||
      write_z(parameter^)
 | 
			
		||||
      write_s(".\n")
 | 
			
		||||
 | 
			
		||||
      return nil
 | 
			
		||||
      result := nil
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    i := i + 1
 | 
			
		||||
  end
 | 
			
		||||
  if result^.input = nil then
 | 
			
		||||
  if result <> nil and result^.input = nil then
 | 
			
		||||
    write_s("Fatal error: no input files.\n")
 | 
			
		||||
	return nil
 | 
			
		||||
	result := nil
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  return result
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user