Support while … else
This commit is contained in:
		
							
								
								
									
										40
									
								
								boot/ast.cc
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								boot/ast.cc
									
									
									
									
									
								
							@@ -223,9 +223,9 @@ namespace elna::boot
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    variable_declaration::variable_declaration(const struct position position, const std::string& identifier,
 | 
			
		||||
            std::shared_ptr<type_expression> variable_type, const bool exported)
 | 
			
		||||
        : definition(position, identifier, exported), m_variable_type(variable_type)
 | 
			
		||||
    variable_declaration::variable_declaration(const struct position position, identifier_definition identifier,
 | 
			
		||||
            std::shared_ptr<type_expression> variable_type)
 | 
			
		||||
        : definition(position, identifier), m_variable_type(variable_type)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -239,14 +239,14 @@ namespace elna::boot
 | 
			
		||||
        return *m_variable_type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    definition::definition(const struct position position, const std::string& identifier, const bool exported)
 | 
			
		||||
        : node(position), identifier(identifier), exported(exported)
 | 
			
		||||
    definition::definition(const struct position position, identifier_definition identifier)
 | 
			
		||||
        : node(position), identifier(identifier)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    constant_definition::constant_definition(const struct position position, const std::string& identifier,
 | 
			
		||||
            const bool exported, expression *body)
 | 
			
		||||
        : definition(position, identifier, exported), m_body(body)
 | 
			
		||||
    constant_definition::constant_definition(const struct position position, identifier_definition identifier,
 | 
			
		||||
            expression *body)
 | 
			
		||||
        : definition(position, identifier), m_body(body)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -307,9 +307,9 @@ namespace elna::boot
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
 | 
			
		||||
            const bool exported, procedure_type_expression *heading, block *body)
 | 
			
		||||
        : definition(position, identifier, exported), m_heading(heading), body(body)
 | 
			
		||||
    procedure_definition::procedure_definition(const struct position position, identifier_definition identifier,
 | 
			
		||||
            procedure_type_expression *heading, block *body)
 | 
			
		||||
        : definition(position, identifier), m_heading(heading), body(body)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -329,9 +329,9 @@ namespace elna::boot
 | 
			
		||||
        delete body;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    type_definition::type_definition(const struct position position, const std::string& identifier,
 | 
			
		||||
            const bool exported, type_expression *body)
 | 
			
		||||
        : definition(position, identifier, exported), m_body(body)
 | 
			
		||||
    type_definition::type_definition(const struct position position, identifier_definition identifier,
 | 
			
		||||
            type_expression *body)
 | 
			
		||||
        : definition(position, identifier), m_body(body)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -811,8 +811,9 @@ namespace elna::boot
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if_statement::if_statement(const struct position position, conditional_statements *body,
 | 
			
		||||
            std::vector<conditional_statements *>&& branches,
 | 
			
		||||
            std::vector<statement *> *alternative)
 | 
			
		||||
        : node(position), m_body(body), alternative(alternative)
 | 
			
		||||
        : node(position), m_body(body), branches(std::move(branches)), alternative(alternative)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -848,14 +849,15 @@ namespace elna::boot
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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))
 | 
			
		||||
            std::vector<conditional_statements *>&& branches, std::vector<statement *> *alternative)
 | 
			
		||||
        : node(position), m_body(body), branches(std::move(branches)), alternative(alternative)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
            std::vector<conditional_statements *>&& branches, const std::string& label,
 | 
			
		||||
            std::vector<statement *> *alternative)
 | 
			
		||||
        : node(position), m_body(body), branches(std::move(branches)), label(label), alternative(alternative)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -161,8 +161,8 @@ along with GCC; see the file COPYING3.  If not see
 | 
			
		||||
%type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements;
 | 
			
		||||
%type <std::vector<elna::boot::statement *> *> else_statements;
 | 
			
		||||
%type <elna::boot::cast_expression *> cast_expression;
 | 
			
		||||
%type <std::pair<std::string, bool>> identifier_definition;
 | 
			
		||||
%type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
 | 
			
		||||
%type <elna::boot::identifier_definition> identifier_definition;
 | 
			
		||||
%type <std::vector<elna::boot::identifier_definition>> identifier_definitions;
 | 
			
		||||
%type <std::vector<std::string>> identifiers;
 | 
			
		||||
%%
 | 
			
		||||
program:
 | 
			
		||||
@@ -187,14 +187,8 @@ block: constant_part variable_part "begin" statements "end"
 | 
			
		||||
            std::swap($$->body, $4);
 | 
			
		||||
        }
 | 
			
		||||
identifier_definition:
 | 
			
		||||
    IDENTIFIER "*"
 | 
			
		||||
        {
 | 
			
		||||
            $$ = std::make_pair($1, true);
 | 
			
		||||
        }
 | 
			
		||||
    | IDENTIFIER
 | 
			
		||||
        {
 | 
			
		||||
            $$ = std::make_pair($1, false);
 | 
			
		||||
        }
 | 
			
		||||
    IDENTIFIER "*" { $$ = boot::identifier_definition{ $1, true }; }
 | 
			
		||||
    | IDENTIFIER { $$ = boot::identifier_definition{ $1, false }; }
 | 
			
		||||
identifier_definitions:
 | 
			
		||||
    identifier_definition "," identifier_definitions
 | 
			
		||||
        {
 | 
			
		||||
@@ -219,12 +213,12 @@ procedure_heading:
 | 
			
		||||
procedure_definition:
 | 
			
		||||
    "proc" identifier_definition procedure_heading ";" block
 | 
			
		||||
        {
 | 
			
		||||
            $$ = new boot::procedure_definition(boot::make_position(@1), $2.first, $2.second, $3.second, $5);
 | 
			
		||||
            $$ = new boot::procedure_definition(boot::make_position(@1), std::move($2), $3.second, $5);
 | 
			
		||||
            std::swap($3.first, $$->parameter_names);
 | 
			
		||||
        }
 | 
			
		||||
    | "proc" identifier_definition procedure_heading ";" "extern"
 | 
			
		||||
        {
 | 
			
		||||
            $$ = new boot::procedure_definition(boot::make_position(@1), $2.first, $2.second, $3.second);
 | 
			
		||||
            $$ = new boot::procedure_definition(boot::make_position(@1), std::move($2), $3.second);
 | 
			
		||||
            std::swap($3.first, $$->parameter_names);
 | 
			
		||||
        }
 | 
			
		||||
procedure_definitions:
 | 
			
		||||
@@ -243,9 +237,7 @@ call_expression: designator_expression actual_parameter_list
 | 
			
		||||
            std::swap($$->arguments, $2);
 | 
			
		||||
        }
 | 
			
		||||
cast_expression: "cast" "(" expression ":" type_expression ")"
 | 
			
		||||
        {
 | 
			
		||||
            $$ = new boot::cast_expression(boot::make_position(@1), $5, $3);
 | 
			
		||||
        }
 | 
			
		||||
        { $$ = new boot::cast_expression(boot::make_position(@1), $5, $3); }
 | 
			
		||||
elsif_do_statements:
 | 
			
		||||
    "elsif" expression "do" statements elsif_do_statements
 | 
			
		||||
        {
 | 
			
		||||
@@ -258,15 +250,15 @@ else_statements:
 | 
			
		||||
    "else" statements { $$ = new std::vector<boot::statement *>(std::move($2)); }
 | 
			
		||||
    | { $$ = nullptr; }
 | 
			
		||||
while_statement:
 | 
			
		||||
    "while" expression "do" statements elsif_do_statements "end"
 | 
			
		||||
    "while" expression "do" statements elsif_do_statements else_statements "end"
 | 
			
		||||
        {
 | 
			
		||||
            boot::conditional_statements *body = new boot::conditional_statements($2, std::move($4));
 | 
			
		||||
            $$ = new boot::while_statement(boot::make_position(@1), body, std::move($5));
 | 
			
		||||
            $$ = new boot::while_statement(boot::make_position(@1), body, std::move($5), $6);
 | 
			
		||||
        }
 | 
			
		||||
    | "while" expression "," IDENTIFIER "do" statements elsif_do_statements "end"
 | 
			
		||||
    | "while" expression "," IDENTIFIER "do" statements elsif_do_statements else_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);
 | 
			
		||||
            $$ = new boot::while_statement(boot::make_position(@1), body, std::move($7), $4, $8);
 | 
			
		||||
        }
 | 
			
		||||
elsif_then_statements:
 | 
			
		||||
    "elsif" expression "then" statements elsif_then_statements
 | 
			
		||||
@@ -422,9 +414,7 @@ statement:
 | 
			
		||||
    | "if" expression "then" statements elsif_then_statements else_statements "end"
 | 
			
		||||
        {
 | 
			
		||||
            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;
 | 
			
		||||
            $$ = new boot::if_statement(boot::make_position(@1), then, std::move($5), $6);
 | 
			
		||||
        }
 | 
			
		||||
    | return_statement { $$ = $1; }
 | 
			
		||||
    | "break" IDENTIFIER
 | 
			
		||||
@@ -512,32 +502,32 @@ variable_declaration: identifier_definitions ":" type_expression
 | 
			
		||||
        {
 | 
			
		||||
            std::shared_ptr<boot::type_expression> shared_type{ $3 };
 | 
			
		||||
 | 
			
		||||
            for (const std::pair<std::string, bool>& identifier : $1)
 | 
			
		||||
            for (boot::identifier_definition& identifier : $1)
 | 
			
		||||
            {
 | 
			
		||||
                boot::variable_declaration *declaration = new boot::variable_declaration(
 | 
			
		||||
                        boot::make_position(@2), identifier.first, shared_type, identifier.second);
 | 
			
		||||
                        boot::make_position(@2), std::move(identifier), shared_type);
 | 
			
		||||
                $$.push_back(declaration);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
variable_declarations:
 | 
			
		||||
    variable_declaration ";" variable_declarations
 | 
			
		||||
    /* no variable declarations */ {}
 | 
			
		||||
    | variable_declaration variable_declarations
 | 
			
		||||
        {
 | 
			
		||||
            std::swap($$, $1);
 | 
			
		||||
            $$.reserve($$.size() + $3.size());
 | 
			
		||||
            $$.insert(std::end($$), std::begin($3), std::end($3));
 | 
			
		||||
            $$.reserve($$.size() + $2.size());
 | 
			
		||||
            $$.insert(std::end($$), std::begin($2), std::end($2));
 | 
			
		||||
        }
 | 
			
		||||
    | /* no variable declarations */ {}
 | 
			
		||||
variable_part:
 | 
			
		||||
    /* no variable declarations */ {}
 | 
			
		||||
    | "var" variable_declarations { std::swap($$, $2); }
 | 
			
		||||
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), std::move($1), $3);
 | 
			
		||||
        }
 | 
			
		||||
constant_definitions:
 | 
			
		||||
    constant_definition ";" constant_definitions
 | 
			
		||||
    constant_definition constant_definitions
 | 
			
		||||
        {
 | 
			
		||||
            std::swap($$, $3);
 | 
			
		||||
            std::swap($$, $2);
 | 
			
		||||
            $$.insert($$.cbegin(), $1);
 | 
			
		||||
        }
 | 
			
		||||
    | /* no constant definitions */ {}
 | 
			
		||||
@@ -546,12 +536,12 @@ constant_part:
 | 
			
		||||
    | "const" constant_definitions { std::swap($$, $2); }
 | 
			
		||||
type_definition: identifier_definition "=" type_expression
 | 
			
		||||
        {
 | 
			
		||||
            $$ = new boot::type_definition(boot::make_position(@1), $1.first, $1.second, $3);
 | 
			
		||||
            $$ = new boot::type_definition(boot::make_position(@1), std::move($1), $3);
 | 
			
		||||
        }
 | 
			
		||||
type_definitions:
 | 
			
		||||
    type_definition ";" type_definitions
 | 
			
		||||
    type_definition type_definitions
 | 
			
		||||
        {
 | 
			
		||||
            std::swap($$, $3);
 | 
			
		||||
            std::swap($$, $2);
 | 
			
		||||
            $$.insert($$.cbegin(), $1);
 | 
			
		||||
        }
 | 
			
		||||
    | /* no type definitions */ {}
 | 
			
		||||
 
 | 
			
		||||
@@ -77,10 +77,12 @@ namespace elna::boot
 | 
			
		||||
    {
 | 
			
		||||
        for (type_definition *const type : program->types)
 | 
			
		||||
        {
 | 
			
		||||
            if (!this->unresolved.insert({ type->identifier, std::make_shared<alias_type>(type->identifier) }).second
 | 
			
		||||
                    || this->symbols->contains(type->identifier))
 | 
			
		||||
            const std::string& type_identifier = type->identifier.identifier;
 | 
			
		||||
 | 
			
		||||
            if (!this->unresolved.insert({ type_identifier, std::make_shared<alias_type>(type_identifier) }).second
 | 
			
		||||
                    || this->symbols->contains(type_identifier))
 | 
			
		||||
            {
 | 
			
		||||
                add_error<already_declared_error>(type->identifier, this->input_file, type->position());
 | 
			
		||||
                add_error<already_declared_error>(type->identifier.identifier, this->input_file, type->position());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        for (type_definition *const type : program->types)
 | 
			
		||||
@@ -109,7 +111,7 @@ namespace elna::boot
 | 
			
		||||
    void declaration_visitor::visit(type_definition *definition)
 | 
			
		||||
    {
 | 
			
		||||
        definition->body().accept(this);
 | 
			
		||||
        auto unresolved_declaration = this->unresolved.at(definition->identifier);
 | 
			
		||||
        auto unresolved_declaration = this->unresolved.at(definition->identifier.identifier);
 | 
			
		||||
 | 
			
		||||
        unresolved_declaration->reference = this->current_type;
 | 
			
		||||
    }
 | 
			
		||||
@@ -193,7 +195,8 @@ namespace elna::boot
 | 
			
		||||
    {
 | 
			
		||||
        definition->body().accept(this);
 | 
			
		||||
 | 
			
		||||
        this->symbols->enter(definition->identifier, std::make_shared<constant_info>(this->current_literal));
 | 
			
		||||
        this->symbols->enter(definition->identifier.identifier,
 | 
			
		||||
                std::make_shared<constant_info>(this->current_literal));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(procedure_definition *definition)
 | 
			
		||||
@@ -201,7 +204,7 @@ namespace elna::boot
 | 
			
		||||
        std::shared_ptr<procedure_info> info = std::make_shared<procedure_info>(
 | 
			
		||||
                build_procedure(definition->heading()), definition->parameter_names);
 | 
			
		||||
 | 
			
		||||
        this->symbols->enter(definition->identifier, info);
 | 
			
		||||
        this->symbols->enter(definition->identifier.identifier, info);
 | 
			
		||||
        if (definition->body != nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            definition->body->accept(this);
 | 
			
		||||
 
 | 
			
		||||
@@ -267,8 +267,8 @@ namespace elna::gcc
 | 
			
		||||
    void generic_visitor::declare_procedure(boot::procedure_definition *const definition)
 | 
			
		||||
    {
 | 
			
		||||
        tree declaration_type = build_procedure_type(definition->heading());
 | 
			
		||||
        tree fndecl = build_fn_decl(definition->identifier.c_str(), declaration_type);
 | 
			
		||||
        this->symbols->enter(definition->identifier, fndecl);
 | 
			
		||||
        tree fndecl = build_fn_decl(definition->identifier.identifier.c_str(), declaration_type);
 | 
			
		||||
        this->symbols->enter(definition->identifier.identifier, fndecl);
 | 
			
		||||
 | 
			
		||||
        if (definition->heading().return_type.no_return)
 | 
			
		||||
        {
 | 
			
		||||
@@ -296,7 +296,7 @@ namespace elna::gcc
 | 
			
		||||
            ++parameter_name;
 | 
			
		||||
        }
 | 
			
		||||
        DECL_ARGUMENTS(fndecl) = argument_chain;
 | 
			
		||||
        TREE_PUBLIC(fndecl) = definition->exported;
 | 
			
		||||
        TREE_PUBLIC(fndecl) = definition->identifier.exported;
 | 
			
		||||
        TREE_ADDRESSABLE(fndecl) = 1;
 | 
			
		||||
        DECL_EXTERNAL(fndecl) = definition->body == nullptr;
 | 
			
		||||
    }
 | 
			
		||||
@@ -386,7 +386,7 @@ namespace elna::gcc
 | 
			
		||||
        {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        tree fndecl = this->symbols->lookup(definition->identifier);
 | 
			
		||||
        tree fndecl = this->symbols->lookup(definition->identifier.identifier);
 | 
			
		||||
 | 
			
		||||
        push_struct_function(fndecl, false);
 | 
			
		||||
        DECL_STRUCT_FUNCTION(fndecl)->language = ggc_cleared_alloc<language_function>();
 | 
			
		||||
@@ -778,15 +778,15 @@ namespace elna::gcc
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        tree definition_tree = build_decl(definition_location, CONST_DECL,
 | 
			
		||||
                get_identifier(definition->identifier.c_str()), TREE_TYPE(this->current_expression));
 | 
			
		||||
        auto result = this->symbols->enter(definition->identifier, definition_tree);
 | 
			
		||||
                get_identifier(definition->identifier.identifier.c_str()), TREE_TYPE(this->current_expression));
 | 
			
		||||
        auto result = this->symbols->enter(definition->identifier.identifier, definition_tree);
 | 
			
		||||
 | 
			
		||||
        if (result)
 | 
			
		||||
        {
 | 
			
		||||
            DECL_INITIAL(definition_tree) = this->current_expression;
 | 
			
		||||
            TREE_CONSTANT(definition_tree) = 1;
 | 
			
		||||
            TREE_READONLY(definition_tree) = 1;
 | 
			
		||||
            TREE_PUBLIC(definition_tree) = definition->exported;
 | 
			
		||||
            TREE_PUBLIC(definition_tree) = definition->identifier.exported;
 | 
			
		||||
 | 
			
		||||
            if (!lang_hooks.decls.global_bindings_p())
 | 
			
		||||
            {
 | 
			
		||||
@@ -798,7 +798,7 @@ namespace elna::gcc
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            error_at(definition_location, "Variable '%s' already declared in this scope",
 | 
			
		||||
                    definition->identifier.c_str());
 | 
			
		||||
                    definition->identifier.identifier.c_str());
 | 
			
		||||
        }
 | 
			
		||||
        this->current_expression = NULL_TREE;
 | 
			
		||||
    }
 | 
			
		||||
@@ -806,16 +806,16 @@ namespace elna::gcc
 | 
			
		||||
    void generic_visitor::visit(boot::type_definition *definition)
 | 
			
		||||
    {
 | 
			
		||||
        location_t definition_location = get_location(&definition->position());
 | 
			
		||||
        this->current_expression = this->unresolved.at(definition->identifier);
 | 
			
		||||
        this->current_expression = this->unresolved.at(definition->identifier.identifier);
 | 
			
		||||
        definition->body().accept(this);
 | 
			
		||||
 | 
			
		||||
        tree definition_tree = build_decl(definition_location, TYPE_DECL,
 | 
			
		||||
                get_identifier(definition->identifier.c_str()), this->current_expression);
 | 
			
		||||
                get_identifier(definition->identifier.identifier.c_str()), this->current_expression);
 | 
			
		||||
 | 
			
		||||
        TREE_PUBLIC(definition_tree) = definition->exported;
 | 
			
		||||
        TYPE_NAME(this->current_expression) = get_identifier(definition->identifier.c_str());
 | 
			
		||||
        TREE_PUBLIC(definition_tree) = definition->identifier.exported;
 | 
			
		||||
        TYPE_NAME(this->current_expression) = get_identifier(definition->identifier.identifier.c_str());
 | 
			
		||||
 | 
			
		||||
        auto result = this->symbols->enter(definition->identifier, definition_tree);
 | 
			
		||||
        auto result = this->symbols->enter(definition->identifier.identifier, definition_tree);
 | 
			
		||||
        gcc_assert(result);
 | 
			
		||||
 | 
			
		||||
        this->current_expression = NULL_TREE;
 | 
			
		||||
@@ -878,8 +878,8 @@ namespace elna::gcc
 | 
			
		||||
 | 
			
		||||
        location_t declaration_location = get_location(&declaration->position());
 | 
			
		||||
        tree declaration_tree = build_decl(declaration_location, VAR_DECL,
 | 
			
		||||
                get_identifier(declaration->identifier.c_str()), this->current_expression);
 | 
			
		||||
        bool result = this->symbols->enter(declaration->identifier, declaration_tree);
 | 
			
		||||
                get_identifier(declaration->identifier.identifier.c_str()), this->current_expression);
 | 
			
		||||
        bool result = this->symbols->enter(declaration->identifier.identifier, declaration_tree);
 | 
			
		||||
 | 
			
		||||
        if (POINTER_TYPE_P(this->current_expression))
 | 
			
		||||
        {
 | 
			
		||||
@@ -889,7 +889,7 @@ namespace elna::gcc
 | 
			
		||||
        if (!result)
 | 
			
		||||
        {
 | 
			
		||||
            error_at(declaration_location, "variable '%s' already declared in this scope",
 | 
			
		||||
                    declaration->identifier.c_str());
 | 
			
		||||
                    declaration->identifier.identifier.c_str());
 | 
			
		||||
        }
 | 
			
		||||
        else if (lang_hooks.decls.global_bindings_p())
 | 
			
		||||
        {
 | 
			
		||||
@@ -1277,6 +1277,13 @@ namespace elna::gcc
 | 
			
		||||
        {
 | 
			
		||||
            make_if_branch(*branch, goto_check);
 | 
			
		||||
        }
 | 
			
		||||
        if (statement->alternative != nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            enter_scope();
 | 
			
		||||
            visit_statements(*statement->alternative);
 | 
			
		||||
            tree mapping = leave_scope();
 | 
			
		||||
            append_statement(mapping);
 | 
			
		||||
        }
 | 
			
		||||
        append_statement(branch_end_expression);
 | 
			
		||||
        this->current_expression = NULL_TREE;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -175,17 +175,22 @@ namespace elna::boot
 | 
			
		||||
        virtual literal_expression *is_literal();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct identifier_definition
 | 
			
		||||
    {
 | 
			
		||||
        std::string identifier;
 | 
			
		||||
        bool exported;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Symbol definition.
 | 
			
		||||
     */
 | 
			
		||||
    class definition : public node
 | 
			
		||||
    {
 | 
			
		||||
    protected:
 | 
			
		||||
        definition(const struct position position, const std::string& identifier, const bool exported);
 | 
			
		||||
        definition(const struct position position, identifier_definition identifier);
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        const std::string identifier;
 | 
			
		||||
        const bool exported;
 | 
			
		||||
        const identifier_definition identifier;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -298,8 +303,8 @@ namespace elna::boot
 | 
			
		||||
        std::shared_ptr<type_expression> m_variable_type;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        variable_declaration(const struct position position, const std::string& identifier,
 | 
			
		||||
                std::shared_ptr<type_expression> variable_type, const bool exported = false);
 | 
			
		||||
        variable_declaration(const struct position position, identifier_definition identifier,
 | 
			
		||||
                std::shared_ptr<type_expression> variable_type);
 | 
			
		||||
 | 
			
		||||
        void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
@@ -326,8 +331,8 @@ namespace elna::boot
 | 
			
		||||
        expression *m_body;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        constant_definition(const struct position position, const std::string& identifier,
 | 
			
		||||
                const bool exported, expression *body);
 | 
			
		||||
        constant_definition(const struct position position, identifier_definition identifier,
 | 
			
		||||
                expression *body);
 | 
			
		||||
        void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        expression& body();
 | 
			
		||||
@@ -364,8 +369,8 @@ namespace elna::boot
 | 
			
		||||
        block *const body;
 | 
			
		||||
        std::vector<std::string> parameter_names;
 | 
			
		||||
 | 
			
		||||
        procedure_definition(const struct position position, const std::string& identifier,
 | 
			
		||||
                const bool exported, procedure_type_expression *heading, block *body = nullptr);
 | 
			
		||||
        procedure_definition(const struct position position, identifier_definition identifier,
 | 
			
		||||
                procedure_type_expression *heading, block *body = nullptr);
 | 
			
		||||
        void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        procedure_type_expression& heading();
 | 
			
		||||
@@ -381,8 +386,8 @@ namespace elna::boot
 | 
			
		||||
        type_expression *m_body;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        type_definition(const struct position position, const std::string& identifier,
 | 
			
		||||
                const bool exported, type_expression *expression);
 | 
			
		||||
        type_definition(const struct position position, identifier_definition identifier,
 | 
			
		||||
                type_expression *expression);
 | 
			
		||||
        ~type_definition();
 | 
			
		||||
 | 
			
		||||
        void accept(parser_visitor *visitor) override;
 | 
			
		||||
@@ -595,10 +600,11 @@ namespace elna::boot
 | 
			
		||||
        conditional_statements *m_body;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        std::vector<conditional_statements *> branches;
 | 
			
		||||
        const std::vector<conditional_statements *> branches;
 | 
			
		||||
        const std::vector<statement *> *alternative;
 | 
			
		||||
 | 
			
		||||
        if_statement(const struct position position, conditional_statements *body,
 | 
			
		||||
                std::vector<conditional_statements *>&& branches,
 | 
			
		||||
                std::vector<statement *> *alternative = nullptr);
 | 
			
		||||
        void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
@@ -628,11 +634,13 @@ namespace elna::boot
 | 
			
		||||
    public:
 | 
			
		||||
        const std::vector<conditional_statements *> branches;
 | 
			
		||||
        const std::optional<std::string> label;
 | 
			
		||||
        const std::vector<statement *> *alternative;
 | 
			
		||||
 | 
			
		||||
        while_statement(const struct position position, conditional_statements *body,
 | 
			
		||||
                std::vector<conditional_statements *>&& branches);
 | 
			
		||||
                std::vector<conditional_statements *>&& branches, std::vector<statement *> *alternative = nullptr);
 | 
			
		||||
        while_statement(const struct position position, conditional_statements *body,
 | 
			
		||||
                std::vector<conditional_statements *>&& branches, const std::string& label);
 | 
			
		||||
                std::vector<conditional_statements *>&& branches, const std::string& label,
 | 
			
		||||
                std::vector<statement *> *alternative = nullptr);
 | 
			
		||||
        void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        conditional_statements& body();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										92
									
								
								source.elna
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								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* = (
 | 
			
		||||
@@ -65,27 +65,27 @@ type
 | 
			
		||||
    _defer,
 | 
			
		||||
    exclamation,
 | 
			
		||||
    arrow
 | 
			
		||||
  );
 | 
			
		||||
  )
 | 
			
		||||
  Position* = record
 | 
			
		||||
    line: Word;
 | 
			
		||||
	column: Word
 | 
			
		||||
  end;
 | 
			
		||||
  end
 | 
			
		||||
  Location* = record
 | 
			
		||||
    first: Position;
 | 
			
		||||
	last: Position
 | 
			
		||||
  end;
 | 
			
		||||
  end
 | 
			
		||||
  SourceFile* = record
 | 
			
		||||
	buffer: [1024]Char;
 | 
			
		||||
	handle: ^FILE;
 | 
			
		||||
	size: Word;
 | 
			
		||||
	index: Word
 | 
			
		||||
  end;
 | 
			
		||||
  FILE* = record end;
 | 
			
		||||
  end
 | 
			
		||||
  FILE* = record end
 | 
			
		||||
  StringBuffer* = record
 | 
			
		||||
    data: ^Byte;
 | 
			
		||||
    size: Word;
 | 
			
		||||
    capacity: Word
 | 
			
		||||
  end;
 | 
			
		||||
  end
 | 
			
		||||
  SourceCode = record
 | 
			
		||||
    position: Position;
 | 
			
		||||
 | 
			
		||||
@@ -93,7 +93,7 @@ type
 | 
			
		||||
	empty: proc(^Byte) -> Bool;
 | 
			
		||||
	advance: proc(^Byte);
 | 
			
		||||
	head: proc(^Byte) -> Char
 | 
			
		||||
  end;
 | 
			
		||||
  end
 | 
			
		||||
  Token* = record
 | 
			
		||||
    kind: TokenKind;
 | 
			
		||||
    value: union
 | 
			
		||||
@@ -103,12 +103,12 @@ type
 | 
			
		||||
	  char_value: Char
 | 
			
		||||
    end;
 | 
			
		||||
	location: Location
 | 
			
		||||
  end;
 | 
			
		||||
  end
 | 
			
		||||
  CommandLine* = record
 | 
			
		||||
    input: ^Char;
 | 
			
		||||
	tokenize: Bool;
 | 
			
		||||
	syntax_tree: Bool
 | 
			
		||||
  end;
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
(*
 | 
			
		||||
  External procedures.
 | 
			
		||||
@@ -171,9 +171,9 @@ end
 | 
			
		||||
 | 
			
		||||
proc write_i(value: Int);
 | 
			
		||||
var
 | 
			
		||||
  digit: Int;
 | 
			
		||||
  n: Word;
 | 
			
		||||
  buffer: [10]Char;
 | 
			
		||||
  digit: Int
 | 
			
		||||
  n: Word
 | 
			
		||||
  buffer: [10]Char
 | 
			
		||||
begin
 | 
			
		||||
  n := 10u;
 | 
			
		||||
 | 
			
		||||
@@ -230,7 +230,7 @@ end
 | 
			
		||||
 | 
			
		||||
proc string_dup(origin: String) -> String;
 | 
			
		||||
var
 | 
			
		||||
  copy: ^Char;
 | 
			
		||||
  copy: ^Char
 | 
			
		||||
begin
 | 
			
		||||
  copy := cast(malloc(origin.length): ^Char);
 | 
			
		||||
  strncpy(copy, origin.ptr, origin.length);
 | 
			
		||||
@@ -240,7 +240,7 @@ end
 | 
			
		||||
 | 
			
		||||
proc string_buffer_new() -> StringBuffer;
 | 
			
		||||
var
 | 
			
		||||
  result: StringBuffer;
 | 
			
		||||
  result: StringBuffer
 | 
			
		||||
begin
 | 
			
		||||
  result.capacity := 64u;
 | 
			
		||||
  result.data := malloc(result.capacity);
 | 
			
		||||
@@ -266,7 +266,7 @@ end
 | 
			
		||||
 | 
			
		||||
proc string_buffer_clear(buffer: ^StringBuffer) -> String;
 | 
			
		||||
var
 | 
			
		||||
  result: String;
 | 
			
		||||
  result: String
 | 
			
		||||
begin
 | 
			
		||||
  result := String(cast(buffer^.data: ^Char), buffer^.size);
 | 
			
		||||
  buffer^.size := 0u;
 | 
			
		||||
@@ -284,8 +284,8 @@ end
 | 
			
		||||
 | 
			
		||||
proc read_source(filename: ^Char) -> ^SourceFile;
 | 
			
		||||
var
 | 
			
		||||
  result: ^SourceFile;
 | 
			
		||||
  file_handle: ^FILE;
 | 
			
		||||
  result: ^SourceFile
 | 
			
		||||
  file_handle: ^FILE
 | 
			
		||||
begin
 | 
			
		||||
  file_handle := fopen(filename, "rb\0".ptr);
 | 
			
		||||
 | 
			
		||||
@@ -300,7 +300,7 @@ end
 | 
			
		||||
 | 
			
		||||
proc escape_char(escape: Char, result: ^Char) -> Bool;
 | 
			
		||||
var
 | 
			
		||||
  successful: Bool;
 | 
			
		||||
  successful: Bool
 | 
			
		||||
begin
 | 
			
		||||
  if escape = 'n' then
 | 
			
		||||
	result^ := '\n';
 | 
			
		||||
@@ -346,7 +346,7 @@ end
 | 
			
		||||
 | 
			
		||||
proc source_file_empty(source_input: ^Byte) -> Bool;
 | 
			
		||||
var
 | 
			
		||||
  source_file: ^SourceFile;
 | 
			
		||||
  source_file: ^SourceFile
 | 
			
		||||
begin
 | 
			
		||||
  source_file := cast(source_input: ^SourceFile);
 | 
			
		||||
 | 
			
		||||
@@ -360,7 +360,7 @@ end
 | 
			
		||||
 | 
			
		||||
proc source_file_head(source_input: ^Byte) -> Char;
 | 
			
		||||
var
 | 
			
		||||
  source_file: ^SourceFile;
 | 
			
		||||
  source_file: ^SourceFile
 | 
			
		||||
begin
 | 
			
		||||
  source_file := cast(source_input: ^SourceFile);
 | 
			
		||||
 | 
			
		||||
@@ -369,7 +369,7 @@ end
 | 
			
		||||
 | 
			
		||||
proc source_file_advance(source_input: ^Byte);
 | 
			
		||||
var
 | 
			
		||||
  source_file: ^SourceFile;
 | 
			
		||||
  source_file: ^SourceFile
 | 
			
		||||
begin
 | 
			
		||||
  source_file := cast(source_input: ^SourceFile);
 | 
			
		||||
 | 
			
		||||
@@ -405,7 +405,7 @@ end
 | 
			
		||||
 | 
			
		||||
proc skip_spaces(source_code: ^SourceCode);
 | 
			
		||||
var
 | 
			
		||||
  current: Char;
 | 
			
		||||
  current: Char
 | 
			
		||||
begin
 | 
			
		||||
  while ~source_code_empty(source_code), loop do
 | 
			
		||||
    current := source_code_head(source_code^);
 | 
			
		||||
@@ -426,7 +426,7 @@ end
 | 
			
		||||
 | 
			
		||||
proc lex_identifier(source_code: ^SourceCode, token_content: ^StringBuffer);
 | 
			
		||||
var
 | 
			
		||||
  content_length: Word;
 | 
			
		||||
  content_length: Word
 | 
			
		||||
begin
 | 
			
		||||
  while ~source_code_empty(source_code) & is_ident(source_code_head(source_code^)) do
 | 
			
		||||
    string_buffer_push(token_content, source_code_head(source_code^));
 | 
			
		||||
@@ -436,7 +436,7 @@ end
 | 
			
		||||
 | 
			
		||||
proc lex_comment(source_code: ^SourceCode, token_content: ^StringBuffer) -> Bool;
 | 
			
		||||
var
 | 
			
		||||
  trailing: Word;
 | 
			
		||||
  trailing: Word
 | 
			
		||||
begin
 | 
			
		||||
  trailing := 0u;
 | 
			
		||||
 | 
			
		||||
@@ -459,7 +459,7 @@ end
 | 
			
		||||
 | 
			
		||||
proc lex_character(source_code: ^SourceCode, token_content: ^Char) -> Bool;
 | 
			
		||||
var
 | 
			
		||||
  successful: Bool;
 | 
			
		||||
  successful: Bool
 | 
			
		||||
begin
 | 
			
		||||
  successful := ~source_code_empty(source_code);
 | 
			
		||||
 | 
			
		||||
@@ -481,10 +481,10 @@ end
 | 
			
		||||
 | 
			
		||||
proc lex_string(source_code: ^SourceCode, token_content: ^StringBuffer) -> Bool;
 | 
			
		||||
var
 | 
			
		||||
  token_end, constructed_string: ^Char;
 | 
			
		||||
  token_length: Word;
 | 
			
		||||
  is_valid: Bool;
 | 
			
		||||
  next_char: Char;
 | 
			
		||||
  token_end, constructed_string: ^Char
 | 
			
		||||
  token_length: Word
 | 
			
		||||
  is_valid: Bool
 | 
			
		||||
  next_char: Char
 | 
			
		||||
begin
 | 
			
		||||
  is_valid := true;
 | 
			
		||||
 | 
			
		||||
@@ -517,8 +517,8 @@ end
 | 
			
		||||
 | 
			
		||||
proc print_tokens(tokens: ^Token, tokens_size: Word);
 | 
			
		||||
var
 | 
			
		||||
  current_token: ^Token;
 | 
			
		||||
  i: Word;
 | 
			
		||||
  current_token: ^Token
 | 
			
		||||
  i: Word
 | 
			
		||||
begin
 | 
			
		||||
  i := 0u;
 | 
			
		||||
  while i < tokens_size do
 | 
			
		||||
@@ -667,7 +667,7 @@ end
 | 
			
		||||
 | 
			
		||||
proc categorize_identifier(token_content: String) -> Token;
 | 
			
		||||
var
 | 
			
		||||
  current_token: Token;
 | 
			
		||||
  current_token: Token
 | 
			
		||||
begin
 | 
			
		||||
  if "if" = token_content then
 | 
			
		||||
	current_token.kind := TokenKind._if
 | 
			
		||||
@@ -737,9 +737,9 @@ end
 | 
			
		||||
 | 
			
		||||
proc tokenize(source_code: SourceCode, tokens_size: ^Word) -> ^Token;
 | 
			
		||||
var
 | 
			
		||||
  tokens, current_token: ^Token;
 | 
			
		||||
  first_char: Char;
 | 
			
		||||
  token_buffer: StringBuffer;
 | 
			
		||||
  tokens, current_token: ^Token
 | 
			
		||||
  first_char: Char
 | 
			
		||||
  token_buffer: StringBuffer
 | 
			
		||||
begin
 | 
			
		||||
  tokens_size^ := 0u;
 | 
			
		||||
  tokens := nil;
 | 
			
		||||
@@ -914,9 +914,9 @@ end
 | 
			
		||||
 | 
			
		||||
proc parse_command_line*(argc: Int, argv: ^^Char) -> ^CommandLine;
 | 
			
		||||
var
 | 
			
		||||
  parameter: ^^Char;
 | 
			
		||||
  i: Int;
 | 
			
		||||
  result: ^CommandLine;
 | 
			
		||||
  parameter: ^^Char
 | 
			
		||||
  i: Int
 | 
			
		||||
  result: ^CommandLine
 | 
			
		||||
begin
 | 
			
		||||
  i := 1;
 | 
			
		||||
  result := cast(malloc(#size(CommandLine)): ^CommandLine);
 | 
			
		||||
@@ -955,11 +955,11 @@ end
 | 
			
		||||
 | 
			
		||||
proc process(argc: Int, argv: ^^Char) -> Int;
 | 
			
		||||
var
 | 
			
		||||
  tokens: ^Token;
 | 
			
		||||
  tokens_size: Word;
 | 
			
		||||
  source_code: SourceCode;
 | 
			
		||||
  command_line: ^CommandLine;
 | 
			
		||||
  return_code: Int;
 | 
			
		||||
  tokens: ^Token
 | 
			
		||||
  tokens_size: Word
 | 
			
		||||
  source_code: SourceCode
 | 
			
		||||
  command_line: ^CommandLine
 | 
			
		||||
  return_code: Int
 | 
			
		||||
begin
 | 
			
		||||
  return_code := 0;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user