Implement procedure pointers
This commit is contained in:
		
							
								
								
									
										18
									
								
								boot/ast.cc
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								boot/ast.cc
									
									
									
									
									
								
							@@ -46,7 +46,7 @@ namespace boot
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void empty_visitor::visit(call_expression *expression)
 | 
					    void empty_visitor::visit(call_expression *expression)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        for (auto& argument : expression->arguments())
 | 
					        for (struct expression *const argument : expression->arguments)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            argument->accept(this);
 | 
					            argument->accept(this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -734,8 +734,8 @@ namespace boot
 | 
				
			|||||||
        delete m_operand;
 | 
					        delete m_operand;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    call_expression::call_expression(const struct position position, const std::string& name)
 | 
					    call_expression::call_expression(const struct position position, designator_expression *callable)
 | 
				
			||||||
        : expression(position), m_name(name)
 | 
					        : expression(position), m_callable(callable)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -744,22 +744,18 @@ namespace boot
 | 
				
			|||||||
        visitor->visit(this);
 | 
					        visitor->visit(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::string& call_expression::name()
 | 
					    designator_expression& call_expression::callable()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return m_name;
 | 
					        return *m_callable;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::vector<expression *>& call_expression::arguments()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return m_arguments;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    call_expression::~call_expression()
 | 
					    call_expression::~call_expression()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        for (auto argument : m_arguments)
 | 
					        for (expression *const argument : arguments)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            delete argument;
 | 
					            delete argument;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        delete m_callable;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cast_expression::cast_expression(const struct position position,
 | 
					    cast_expression::cast_expression(const struct position position,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										191
									
								
								boot/parser.yy
									
									
									
									
									
								
							
							
						
						
									
										191
									
								
								boot/parser.yy
									
									
									
									
									
								
							@@ -74,25 +74,49 @@ along with GCC; see the file COPYING3.  If not see
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
%start program;
 | 
					%start program;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%token <std::string> IDENTIFIER "identifier"
 | 
					%token <std::string> IDENTIFIER
 | 
				
			||||||
%token <std::int32_t> INTEGER "integer"
 | 
					%token <std::int32_t> INTEGER
 | 
				
			||||||
%token <std::uint32_t> WORD "word"
 | 
					%token <std::uint32_t> WORD
 | 
				
			||||||
%token <float> FLOAT "float"
 | 
					%token <float> FLOAT
 | 
				
			||||||
%token <std::string> CHARACTER "character"
 | 
					%token <std::string> CHARACTER
 | 
				
			||||||
%token <std::string> STRING "string"
 | 
					%token <std::string> STRING
 | 
				
			||||||
%token <bool> BOOLEAN
 | 
					%token <bool> BOOLEAN
 | 
				
			||||||
%token IF WHILE DO THEN ELSE ELSIF RETURN
 | 
					%token LEFT_PAREN "(" RIGHT_PAREN ")" LEFT_SQUARE "[" RIGHT_SQUARE "]"
 | 
				
			||||||
%token CONST VAR PROCEDURE TYPE RECORD UNION
 | 
					%token ASSIGNMENT ":="
 | 
				
			||||||
%token BEGIN_BLOCK END_BLOCK EXTERN DEFER
 | 
					    ARROW "->" EXCLAMATION "!"
 | 
				
			||||||
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
 | 
					    AT "@" HAT "^"
 | 
				
			||||||
%token NOT CAST EXCLAMATION
 | 
					    COLON ":" SEMICOLON ";" DOT "." COMMA ","
 | 
				
			||||||
%token ASSIGNMENT COLON HAT AT NIL ARROW
 | 
					%token NOT "not"
 | 
				
			||||||
 | 
					    CAST "cast"
 | 
				
			||||||
 | 
					    NIL "nil"
 | 
				
			||||||
 | 
					    CONST "const"
 | 
				
			||||||
 | 
					    VAR "var"
 | 
				
			||||||
 | 
					    PROCEDURE "proc"
 | 
				
			||||||
 | 
					    TYPE "type"
 | 
				
			||||||
 | 
					    RECORD "record"
 | 
				
			||||||
 | 
					    UNION "union"
 | 
				
			||||||
 | 
					    EXTERN "extern"
 | 
				
			||||||
 | 
					    IF "if"
 | 
				
			||||||
 | 
					    WHILE "while"
 | 
				
			||||||
 | 
					    DO "do"
 | 
				
			||||||
 | 
					    THEN "then"
 | 
				
			||||||
 | 
					    ELSE "else"
 | 
				
			||||||
 | 
					    ELSIF "elsif"
 | 
				
			||||||
 | 
					    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 ">>"
 | 
				
			||||||
 | 
					    PLUS "+" MINUS "-"
 | 
				
			||||||
 | 
					    MULTIPLICATION "*" DIVISION "/" REMAINDER "%"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%left OR AND XOR
 | 
					%left "or" "and" "xor"
 | 
				
			||||||
%left EQUALS NOT_EQUAL LESS_THAN GREATER_THAN LESS_EQUAL GREATER_EQUAL
 | 
					%left "=" "<>" "<" ">" "<=" ">="
 | 
				
			||||||
%left SHIFT_LEFT SHIFT_RIGHT
 | 
					%left "<<" ">>"
 | 
				
			||||||
%left PLUS MINUS
 | 
					%left "+" "-"
 | 
				
			||||||
%left MULTIPLICATION DIVISION REMAINDER
 | 
					%left "*" "/" "%"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%type <elna::boot::literal *> literal;
 | 
					%type <elna::boot::literal *> literal;
 | 
				
			||||||
%type <elna::boot::constant_definition *> constant_definition;
 | 
					%type <elna::boot::constant_definition *> constant_definition;
 | 
				
			||||||
@@ -126,7 +150,7 @@ along with GCC; see the file COPYING3.  If not see
 | 
				
			|||||||
%type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
 | 
					%type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
 | 
				
			||||||
%%
 | 
					%%
 | 
				
			||||||
program:
 | 
					program:
 | 
				
			||||||
    constant_part type_part variable_part procedure_part BEGIN_BLOCK optional_statements END_BLOCK DOT
 | 
					    constant_part type_part variable_part procedure_part "begin" optional_statements "end" "."
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            auto tree = new elna::boot::program(elna::boot::make_position(@5));
 | 
					            auto tree = new elna::boot::program(elna::boot::make_position(@5));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -138,7 +162,7 @@ program:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            driver.tree.reset(tree);
 | 
					            driver.tree.reset(tree);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
block: constant_part variable_part BEGIN_BLOCK optional_statements END_BLOCK
 | 
					block: constant_part variable_part "begin" optional_statements "end"
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::block(elna::boot::make_position(@3));
 | 
					            $$ = new elna::boot::block(elna::boot::make_position(@3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -147,7 +171,7 @@ block: constant_part variable_part BEGIN_BLOCK optional_statements END_BLOCK
 | 
				
			|||||||
            std::swap($$->body, $4);
 | 
					            std::swap($$->body, $4);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
identifier_definition:
 | 
					identifier_definition:
 | 
				
			||||||
    IDENTIFIER MULTIPLICATION
 | 
					    IDENTIFIER "*"
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = std::make_pair($1, true);
 | 
					            $$ = std::make_pair($1, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -156,7 +180,7 @@ identifier_definition:
 | 
				
			|||||||
            $$ = std::make_pair($1, false);
 | 
					            $$ = std::make_pair($1, false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
identifier_definitions:
 | 
					identifier_definitions:
 | 
				
			||||||
    identifier_definition COMMA identifier_definitions
 | 
					    identifier_definition "," identifier_definitions
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::swap($$, $3);
 | 
					            std::swap($$, $3);
 | 
				
			||||||
            $$.emplace($$.cbegin(), $1);
 | 
					            $$.emplace($$.cbegin(), $1);
 | 
				
			||||||
@@ -168,22 +192,22 @@ procedure_heading:
 | 
				
			|||||||
            $$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1));
 | 
					            $$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1));
 | 
				
			||||||
            std::swap($1, $$->parameters);
 | 
					            std::swap($1, $$->parameters);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | formal_parameter_list ARROW EXCLAMATION
 | 
					    | formal_parameter_list "->" "!"
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1), elna::boot::no_return);
 | 
					            $$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1), elna::boot::no_return);
 | 
				
			||||||
            std::swap($1, $$->parameters);
 | 
					            std::swap($1, $$->parameters);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | formal_parameter_list ARROW type_expression
 | 
					    | formal_parameter_list "->" type_expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1), $3);
 | 
					            $$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1), $3);
 | 
				
			||||||
            std::swap($1, $$->parameters);
 | 
					            std::swap($1, $$->parameters);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
procedure_definition:
 | 
					procedure_definition:
 | 
				
			||||||
    PROCEDURE identifier_definition procedure_heading SEMICOLON block
 | 
					    "proc" identifier_definition procedure_heading ";" block
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = 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);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | PROCEDURE identifier_definition procedure_heading SEMICOLON EXTERN
 | 
					    | "proc" identifier_definition procedure_heading ";" "extern"
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), $2.first, $2.second, $3);
 | 
					            $$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), $2.first, $2.second, $3);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -197,21 +221,21 @@ procedure_definitions:
 | 
				
			|||||||
procedure_part:
 | 
					procedure_part:
 | 
				
			||||||
    /* no procedure definitions */ {}
 | 
					    /* no procedure definitions */ {}
 | 
				
			||||||
    | procedure_definitions { std::swap($$, $1); }
 | 
					    | procedure_definitions { std::swap($$, $1); }
 | 
				
			||||||
assign_statement: designator_expression ASSIGNMENT expression
 | 
					assign_statement: designator_expression ":=" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::assign_statement(elna::boot::make_position(@1), $1, $3);
 | 
					            $$ = new elna::boot::assign_statement(elna::boot::make_position(@1), $1, $3);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
call_expression: IDENTIFIER actual_parameter_list
 | 
					call_expression: designator_expression actual_parameter_list
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::call_expression(elna::boot::make_position(@1), $1);
 | 
					            $$ = new elna::boot::call_expression(elna::boot::make_position(@1), $1);
 | 
				
			||||||
            std::swap($$->arguments(), $2);
 | 
					            std::swap($$->arguments, $2);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
cast_expression: CAST LEFT_PAREN expression COLON type_expression RIGHT_PAREN
 | 
					cast_expression: "cast" "(" expression ":" type_expression ")"
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::cast_expression(elna::boot::make_position(@1), $5, $3);
 | 
					            $$ = new elna::boot::cast_expression(elna::boot::make_position(@1), $5, $3);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
elsif_do_statements:
 | 
					elsif_do_statements:
 | 
				
			||||||
    ELSIF expression DO optional_statements elsif_do_statements
 | 
					    "elsif" expression "do" optional_statements elsif_do_statements
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            elna::boot::conditional_statements *branch = new elna::boot::conditional_statements($2);
 | 
					            elna::boot::conditional_statements *branch = new elna::boot::conditional_statements($2);
 | 
				
			||||||
            std::swap(branch->statements, $4);
 | 
					            std::swap(branch->statements, $4);
 | 
				
			||||||
@@ -219,7 +243,7 @@ elsif_do_statements:
 | 
				
			|||||||
            $$.emplace($$.begin(), branch);
 | 
					            $$.emplace($$.begin(), branch);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | {}
 | 
					    | {}
 | 
				
			||||||
while_statement: WHILE expression DO optional_statements elsif_do_statements END_BLOCK
 | 
					while_statement: "while" expression "do" optional_statements elsif_do_statements "end"
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            auto body = new elna::boot::conditional_statements($2);
 | 
					            auto body = new elna::boot::conditional_statements($2);
 | 
				
			||||||
            std::swap($4, body->statements);
 | 
					            std::swap($4, body->statements);
 | 
				
			||||||
@@ -227,7 +251,7 @@ while_statement: WHILE expression DO optional_statements elsif_do_statements END
 | 
				
			|||||||
            std::swap($5, $$->branches);
 | 
					            std::swap($5, $$->branches);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
elsif_then_statements:
 | 
					elsif_then_statements:
 | 
				
			||||||
    ELSIF expression THEN optional_statements elsif_then_statements
 | 
					    "elsif" expression "then" optional_statements elsif_then_statements
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            elna::boot::conditional_statements *branch = new elna::boot::conditional_statements($2);
 | 
					            elna::boot::conditional_statements *branch = new elna::boot::conditional_statements($2);
 | 
				
			||||||
            std::swap(branch->statements, $4);
 | 
					            std::swap(branch->statements, $4);
 | 
				
			||||||
@@ -236,14 +260,14 @@ elsif_then_statements:
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    | {}
 | 
					    | {}
 | 
				
			||||||
if_statement:
 | 
					if_statement:
 | 
				
			||||||
    IF expression THEN optional_statements elsif_then_statements END_BLOCK
 | 
					    "if" expression "then" optional_statements elsif_then_statements "end"
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            auto then = new elna::boot::conditional_statements($2);
 | 
					            auto then = new elna::boot::conditional_statements($2);
 | 
				
			||||||
            std::swap($4, then->statements);
 | 
					            std::swap($4, then->statements);
 | 
				
			||||||
            $$ = new elna::boot::if_statement(elna::boot::make_position(@1), then);
 | 
					            $$ = new elna::boot::if_statement(elna::boot::make_position(@1), then);
 | 
				
			||||||
            std::swap($5, $$->branches);
 | 
					            std::swap($5, $$->branches);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | IF expression THEN optional_statements elsif_then_statements ELSE optional_statements END_BLOCK
 | 
					    | "if" expression "then" optional_statements elsif_then_statements "else" optional_statements "end"
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            auto then = new elna::boot::conditional_statements($2);
 | 
					            auto then = new elna::boot::conditional_statements($2);
 | 
				
			||||||
            std::swap($4, then->statements);
 | 
					            std::swap($4, then->statements);
 | 
				
			||||||
@@ -251,11 +275,11 @@ if_statement:
 | 
				
			|||||||
            $$ = new elna::boot::if_statement(elna::boot::make_position(@1), then, _else);
 | 
					            $$ = new elna::boot::if_statement(elna::boot::make_position(@1), then, _else);
 | 
				
			||||||
            std::swap($5, $$->branches);
 | 
					            std::swap($5, $$->branches);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
return_statement: RETURN expression
 | 
					return_statement: "return" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::return_statement(elna::boot::make_position(@1), $2);
 | 
					            $$ = new elna::boot::return_statement(elna::boot::make_position(@1), $2);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
defer_statement: DEFER optional_statements END_BLOCK
 | 
					defer_statement: DEFER optional_statements "end"
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::defer_statement(elna::boot::make_position(@1));
 | 
					            $$ = new elna::boot::defer_statement(elna::boot::make_position(@1));
 | 
				
			||||||
            std::swap($2, $$->statements);
 | 
					            std::swap($2, $$->statements);
 | 
				
			||||||
@@ -281,7 +305,7 @@ literal:
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::number_literal<unsigned char>(elna::boot::make_position(@1), $1.at(0));
 | 
					            $$ = new elna::boot::number_literal<unsigned char>(elna::boot::make_position(@1), $1.at(0));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | NIL
 | 
					    | "nil"
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::number_literal<std::nullptr_t>(elna::boot::make_position(@1), nullptr);
 | 
					            $$ = new elna::boot::number_literal<std::nullptr_t>(elna::boot::make_position(@1), nullptr);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -292,129 +316,126 @@ literal:
 | 
				
			|||||||
operand:
 | 
					operand:
 | 
				
			||||||
    literal { $$ = $1; }
 | 
					    literal { $$ = $1; }
 | 
				
			||||||
    | designator_expression { $$ = $1; }
 | 
					    | designator_expression { $$ = $1; }
 | 
				
			||||||
    | LEFT_PAREN type_expression RIGHT_PAREN
 | 
					    | "(" type_expression ")" { $$ = new elna::boot::type_expression(elna::boot::make_position(@1), $2); }
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            $$ = new elna::boot::type_expression(elna::boot::make_position(@1), $2);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    | cast_expression { $$ = $1; }
 | 
					    | cast_expression { $$ = $1; }
 | 
				
			||||||
    | call_expression { $$ = $1; }
 | 
					    | call_expression { $$ = $1; }
 | 
				
			||||||
    | LEFT_PAREN expression RIGHT_PAREN { $$ = $2; }
 | 
					    | "(" expression ")" { $$ = $2; }
 | 
				
			||||||
expression:
 | 
					expression:
 | 
				
			||||||
    unary { $$ = $1; }
 | 
					    unary { $$ = $1; }
 | 
				
			||||||
    | expression MULTIPLICATION expression
 | 
					    | expression "*" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
					            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
				
			||||||
                elna::boot::binary_operator::multiplication);
 | 
					                elna::boot::binary_operator::multiplication);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | expression DIVISION expression
 | 
					    | expression "/" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
					            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
				
			||||||
                elna::boot::binary_operator::division);
 | 
					                elna::boot::binary_operator::division);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | expression REMAINDER expression
 | 
					    | expression "%" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
					            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
				
			||||||
                elna::boot::binary_operator::remainder);
 | 
					                elna::boot::binary_operator::remainder);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | expression PLUS expression
 | 
					    | expression "+" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
					            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
				
			||||||
                elna::boot::binary_operator::sum);
 | 
					                elna::boot::binary_operator::sum);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | expression MINUS expression
 | 
					    | expression "-" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
					            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
				
			||||||
                elna::boot::binary_operator::subtraction);
 | 
					                elna::boot::binary_operator::subtraction);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | expression EQUALS expression
 | 
					    | expression "=" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
					            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
				
			||||||
                elna::boot::binary_operator::equals);
 | 
					                elna::boot::binary_operator::equals);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | expression NOT_EQUAL expression
 | 
					    | expression "<>" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
					            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
				
			||||||
                elna::boot::binary_operator::not_equals);
 | 
					                elna::boot::binary_operator::not_equals);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | expression LESS_THAN expression
 | 
					    | expression "<" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
					            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
				
			||||||
                elna::boot::binary_operator::less);
 | 
					                elna::boot::binary_operator::less);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | expression GREATER_THAN expression
 | 
					    | expression ">" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
					            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
				
			||||||
                elna::boot::binary_operator::greater);
 | 
					                elna::boot::binary_operator::greater);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | expression LESS_EQUAL expression
 | 
					    | expression "<=" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
					            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
				
			||||||
                elna::boot::binary_operator::less_equal);
 | 
					                elna::boot::binary_operator::less_equal);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | expression GREATER_EQUAL expression
 | 
					    | expression ">=" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
					            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
				
			||||||
                elna::boot::binary_operator::greater_equal);
 | 
					                elna::boot::binary_operator::greater_equal);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | expression AND expression
 | 
					    | expression "and" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
					            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
				
			||||||
                elna::boot::binary_operator::conjunction);
 | 
					                elna::boot::binary_operator::conjunction);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | expression OR expression
 | 
					    | expression "or" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
					            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
				
			||||||
                elna::boot::binary_operator::disjunction);
 | 
					                elna::boot::binary_operator::disjunction);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | expression XOR expression
 | 
					    | expression "xor" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
					            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
				
			||||||
                elna::boot::binary_operator::exclusive_disjunction);
 | 
					                elna::boot::binary_operator::exclusive_disjunction);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | expression SHIFT_LEFT expression
 | 
					    | expression "<<" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
					            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
				
			||||||
                elna::boot::binary_operator::shift_left);
 | 
					                elna::boot::binary_operator::shift_left);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | expression SHIFT_RIGHT expression
 | 
					    | expression ">>" expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
					            $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
 | 
				
			||||||
                elna::boot::binary_operator::shift_right);
 | 
					                elna::boot::binary_operator::shift_right);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
unary:
 | 
					unary:
 | 
				
			||||||
    AT operand
 | 
					    "@" operand
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::unary_expression(elna::boot::make_position(@1), $2,
 | 
					            $$ = new elna::boot::unary_expression(elna::boot::make_position(@1), $2,
 | 
				
			||||||
                elna::boot::unary_operator::reference);
 | 
					                elna::boot::unary_operator::reference);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | NOT operand
 | 
					    | "not" operand
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::unary_expression(elna::boot::make_position(@1), $2,
 | 
					            $$ = new elna::boot::unary_expression(elna::boot::make_position(@1), $2,
 | 
				
			||||||
                elna::boot::unary_operator::negation);
 | 
					                elna::boot::unary_operator::negation);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | MINUS operand
 | 
					    | "-" operand
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::unary_expression(elna::boot::make_position(@1), $2,
 | 
					            $$ = new elna::boot::unary_expression(elna::boot::make_position(@1), $2,
 | 
				
			||||||
                elna::boot::unary_operator::minus);
 | 
					                elna::boot::unary_operator::minus);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | operand { $$ = $1; }
 | 
					    | operand { $$ = $1; }
 | 
				
			||||||
expressions:
 | 
					expressions:
 | 
				
			||||||
    expression COMMA expressions
 | 
					    expression "," expressions
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::swap($$, $3);
 | 
					            std::swap($$, $3);
 | 
				
			||||||
            $$.emplace($$.cbegin(), $1);
 | 
					            $$.emplace($$.cbegin(), $1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | expression { $$.emplace_back(std::move($1)); }
 | 
					    | expression { $$.emplace_back(std::move($1)); }
 | 
				
			||||||
designator_expression:
 | 
					designator_expression:
 | 
				
			||||||
    operand LEFT_SQUARE expression RIGHT_SQUARE
 | 
					    operand "[" expression "]"
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::array_access_expression(elna::boot::make_position(@2), $1, $3);
 | 
					            $$ = new elna::boot::array_access_expression(elna::boot::make_position(@2), $1, $3);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | operand DOT IDENTIFIER
 | 
					    | operand "." IDENTIFIER
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::field_access_expression(elna::boot::make_position(@2), $1, $3);
 | 
					            $$ = new elna::boot::field_access_expression(elna::boot::make_position(@2), $1, $3);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | operand HAT
 | 
					    | operand "^"
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::dereference_expression(elna::boot::make_position(@1), $1);
 | 
					            $$ = new elna::boot::dereference_expression(elna::boot::make_position(@1), $1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -443,7 +464,7 @@ optional_statements:
 | 
				
			|||||||
    statements { std::swap($$, $1); }
 | 
					    statements { std::swap($$, $1); }
 | 
				
			||||||
    | /* no statements */ {}
 | 
					    | /* no statements */ {}
 | 
				
			||||||
field_declaration:
 | 
					field_declaration:
 | 
				
			||||||
    IDENTIFIER COLON type_expression { $$ = std::make_pair($1, $3); }
 | 
					    IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); }
 | 
				
			||||||
fields:
 | 
					fields:
 | 
				
			||||||
    field_declaration fields
 | 
					    field_declaration fields
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -455,23 +476,23 @@ optional_fields:
 | 
				
			|||||||
    fields { std::swap($$, $1); }
 | 
					    fields { std::swap($$, $1); }
 | 
				
			||||||
    | /* no fields */ {}
 | 
					    | /* no fields */ {}
 | 
				
			||||||
type_expression:
 | 
					type_expression:
 | 
				
			||||||
    LEFT_SQUARE INTEGER RIGHT_SQUARE type_expression
 | 
					    "[" INTEGER "]" type_expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = std::make_shared<elna::boot::array_type>(elna::boot::make_position(@1), $4, $2);
 | 
					            $$ = std::make_shared<elna::boot::array_type>(elna::boot::make_position(@1), $4, $2);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | HAT type_expression
 | 
					    | "^" type_expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = std::make_shared<elna::boot::pointer_type>(elna::boot::make_position(@1), $2);
 | 
					            $$ = std::make_shared<elna::boot::pointer_type>(elna::boot::make_position(@1), $2);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | RECORD optional_fields END_BLOCK
 | 
					    | "record" optional_fields "end"
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = std::make_shared<elna::boot::record_type>(elna::boot::make_position(@1), std::move($2));
 | 
					            $$ = std::make_shared<elna::boot::record_type>(elna::boot::make_position(@1), std::move($2));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | UNION fields END_BLOCK
 | 
					    | "union" fields "end"
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = std::make_shared<elna::boot::union_type>(elna::boot::make_position(@1), std::move($2));
 | 
					            $$ = std::make_shared<elna::boot::union_type>(elna::boot::make_position(@1), std::move($2));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | PROCEDURE procedure_heading
 | 
					    | "proc" procedure_heading
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = $2;
 | 
					            $$ = $2;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -479,7 +500,7 @@ type_expression:
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = std::make_shared<elna::boot::basic_type>(elna::boot::make_position(@1), $1);
 | 
					            $$ = std::make_shared<elna::boot::basic_type>(elna::boot::make_position(@1), $1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
variable_declaration: identifier_definitions COLON type_expression
 | 
					variable_declaration: identifier_definitions ":" type_expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            for (const std::pair<std::string, bool>& identifier : $1)
 | 
					            for (const std::pair<std::string, bool>& identifier : $1)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@@ -498,8 +519,8 @@ variable_declarations:
 | 
				
			|||||||
    | variable_declaration { std::swap($$, $1); }
 | 
					    | variable_declaration { std::swap($$, $1); }
 | 
				
			||||||
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 EQUALS literal
 | 
					constant_definition: identifier_definition "=" literal
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::constant_definition(elna::boot::make_position(@1), $1.first, $1.second, $3);
 | 
					            $$ = new elna::boot::constant_definition(elna::boot::make_position(@1), $1.first, $1.second, $3);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -512,9 +533,9 @@ constant_definitions:
 | 
				
			|||||||
    | constant_definition { $$.emplace_back(std::move($1)); }
 | 
					    | constant_definition { $$.emplace_back(std::move($1)); }
 | 
				
			||||||
constant_part:
 | 
					constant_part:
 | 
				
			||||||
    /* no constant definitions */ {}
 | 
					    /* no constant definitions */ {}
 | 
				
			||||||
    | CONST {}
 | 
					    | "const" {}
 | 
				
			||||||
    | CONST constant_definitions { std::swap($$, $2); }
 | 
					    | "const" constant_definitions { std::swap($$, $2); }
 | 
				
			||||||
type_definition: identifier_definition EQUALS type_expression
 | 
					type_definition: identifier_definition "=" type_expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::type_definition(elna::boot::make_position(@1), $1.first, $1.second, $3);
 | 
					            $$ = new elna::boot::type_definition(elna::boot::make_position(@1), $1.first, $1.second, $3);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -527,25 +548,25 @@ type_definitions:
 | 
				
			|||||||
    | type_definition { $$.emplace_back(std::move($1)); }
 | 
					    | type_definition { $$.emplace_back(std::move($1)); }
 | 
				
			||||||
type_part:
 | 
					type_part:
 | 
				
			||||||
    /* no type definitions */ {}
 | 
					    /* no type definitions */ {}
 | 
				
			||||||
    | TYPE {}
 | 
					    | "type" {}
 | 
				
			||||||
    | TYPE type_definitions { std::swap($$, $2); }
 | 
					    | "type" type_definitions { std::swap($$, $2); }
 | 
				
			||||||
formal_parameter: IDENTIFIER COLON type_expression
 | 
					formal_parameter: IDENTIFIER ":" type_expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new elna::boot::variable_declaration(elna::boot::make_position(@2), $1, $3);
 | 
					            $$ = new elna::boot::variable_declaration(elna::boot::make_position(@2), $1, $3);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
formal_parameters:
 | 
					formal_parameters:
 | 
				
			||||||
    formal_parameter COMMA formal_parameters
 | 
					    formal_parameter "," formal_parameters
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::swap($$, $3);
 | 
					            std::swap($$, $3);
 | 
				
			||||||
            $$.emplace($$.cbegin(), $1);
 | 
					            $$.emplace($$.cbegin(), $1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | formal_parameter { $$.emplace_back(std::move($1)); }
 | 
					    | formal_parameter { $$.emplace_back(std::move($1)); }
 | 
				
			||||||
formal_parameter_list:
 | 
					formal_parameter_list:
 | 
				
			||||||
    LEFT_PAREN RIGHT_PAREN {}
 | 
					    "(" ")" {}
 | 
				
			||||||
    | LEFT_PAREN formal_parameters RIGHT_PAREN { std::swap($$, $2); }
 | 
					    | "(" formal_parameters ")" { std::swap($$, $2); }
 | 
				
			||||||
actual_parameter_list:
 | 
					actual_parameter_list:
 | 
				
			||||||
    LEFT_PAREN RIGHT_PAREN {}
 | 
					    "(" ")" {}
 | 
				
			||||||
    | LEFT_PAREN expressions RIGHT_PAREN { std::swap($$, $2); }
 | 
					    | "(" expressions ")" { std::swap($$, $2); }
 | 
				
			||||||
%%
 | 
					%%
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void yy::parser::error(const location_type& loc, const std::string& message)
 | 
					void yy::parser::error(const location_type& loc, const std::string& message)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -80,9 +80,18 @@ namespace gcc
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (is_pointer_type(type))
 | 
					        else if (is_pointer_type(type))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return std::string("^" + print_type(TREE_TYPE(type)));
 | 
					            tree pointer_target_type = TREE_TYPE(type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (TREE_CODE(pointer_target_type) == FUNCTION_TYPE)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return print_type(pointer_target_type);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return std::string("^" + print_type(pointer_target_type));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (is_procedure_type(type))
 | 
					        else if (TREE_CODE(type) == FUNCTION_TYPE)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::string output = "proc(";
 | 
					            std::string output = "proc(";
 | 
				
			||||||
            tree parameter_type = TYPE_ARG_TYPES(type);
 | 
					            tree parameter_type = TYPE_ARG_TYPES(type);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,10 +44,12 @@ namespace gcc
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void generic_visitor::build_procedure_call(location_t call_location,
 | 
					    void generic_visitor::build_procedure_call(location_t call_location,
 | 
				
			||||||
            tree symbol, const std::vector<boot::expression *>& arguments)
 | 
					            tree procedure_address, const std::vector<boot::expression *>& arguments)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        vec<tree, va_gc> *argument_trees = nullptr;
 | 
					        vec<tree, va_gc> *argument_trees = nullptr;
 | 
				
			||||||
        tree current_parameter = TYPE_ARG_TYPES(TREE_TYPE(symbol));
 | 
					        tree symbol_type = TREE_TYPE(TREE_TYPE(procedure_address));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tree current_parameter = TYPE_ARG_TYPES(symbol_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        vec_alloc(argument_trees, arguments.size());
 | 
					        vec_alloc(argument_trees, arguments.size());
 | 
				
			||||||
        for (boot::expression *const argument : arguments)
 | 
					        for (boot::expression *const argument : arguments)
 | 
				
			||||||
@@ -56,11 +58,12 @@ namespace gcc
 | 
				
			|||||||
            if (is_void_type(TREE_VALUE(current_parameter)))
 | 
					            if (is_void_type(TREE_VALUE(current_parameter)))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                error_at(argument_location, "too many arguments, expected %i, got %lu",
 | 
					                error_at(argument_location, "too many arguments, expected %i, got %lu",
 | 
				
			||||||
                        list_length(TYPE_ARG_TYPES(TREE_TYPE(symbol))) - 1, arguments.size());
 | 
					                        list_length(TYPE_ARG_TYPES(symbol_type)) - 1, arguments.size());
 | 
				
			||||||
                this->current_expression = error_mark_node;
 | 
					                this->current_expression = error_mark_node;
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            argument->accept(this);
 | 
					            argument->accept(this);
 | 
				
			||||||
 | 
					            this->current_expression = prepare_rvalue(this->current_expression);
 | 
				
			||||||
            if (!is_assignable_from(TREE_VALUE(current_parameter), this->current_expression))
 | 
					            if (!is_assignable_from(TREE_VALUE(current_parameter), this->current_expression))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                error_at(argument_location,
 | 
					                error_at(argument_location,
 | 
				
			||||||
@@ -72,15 +75,16 @@ namespace gcc
 | 
				
			|||||||
            current_parameter = TREE_CHAIN(current_parameter);
 | 
					            current_parameter = TREE_CHAIN(current_parameter);
 | 
				
			||||||
            argument_trees->quick_push(this->current_expression);
 | 
					            argument_trees->quick_push(this->current_expression);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        tree stmt = build_call_expr_loc_vec(call_location, symbol, argument_trees);
 | 
					        tree stmt = fold_build_call_array_loc(call_location, TREE_TYPE(symbol_type),
 | 
				
			||||||
 | 
					                procedure_address, vec_safe_length(argument_trees), vec_safe_address(argument_trees));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!is_void_type(TREE_VALUE(current_parameter)))
 | 
					        if (!is_void_type(TREE_VALUE(current_parameter)))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
                error_at(call_location, "too few arguments, expected %i, got %lu",
 | 
					                error_at(call_location, "too few arguments, expected %i, got %lu",
 | 
				
			||||||
                        list_length(TYPE_ARG_TYPES(TREE_TYPE(symbol))) - 1, arguments.size());
 | 
					                        list_length(TYPE_ARG_TYPES(symbol_type)) - 1, arguments.size());
 | 
				
			||||||
                this->current_expression = error_mark_node;
 | 
					                this->current_expression = error_mark_node;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (TREE_TYPE(TREE_TYPE(symbol)) == void_type_node)
 | 
					        else if (TREE_TYPE(symbol_type) == void_type_node)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            append_statement(stmt);
 | 
					            append_statement(stmt);
 | 
				
			||||||
            this->current_expression = NULL_TREE;
 | 
					            this->current_expression = NULL_TREE;
 | 
				
			||||||
@@ -134,27 +138,31 @@ namespace gcc
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void generic_visitor::visit(boot::call_expression *expression)
 | 
					    void generic_visitor::visit(boot::call_expression *expression)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        tree symbol = this->lookup(expression->name());
 | 
					 | 
				
			||||||
        location_t call_location = get_location(&expression->position());
 | 
					        location_t call_location = get_location(&expression->position());
 | 
				
			||||||
 | 
					        expression->callable().accept(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (symbol == NULL_TREE)
 | 
					        tree expression_type = TYPE_P(this->current_expression)
 | 
				
			||||||
 | 
					            ? this->current_expression
 | 
				
			||||||
 | 
					            : TREE_TYPE(this->current_expression);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (TYPE_P(this->current_expression) && TREE_CODE(expression_type) == RECORD_TYPE)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            error_at(call_location, "procedure '%s' not declared",
 | 
					            build_record_call(call_location, this->current_expression, expression->arguments);
 | 
				
			||||||
                    expression->name().c_str());
 | 
					 | 
				
			||||||
            this->current_expression = error_mark_node;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (DECL_P(symbol) && is_procedure_type(TREE_TYPE(symbol)))
 | 
					        else if (TREE_CODE(expression_type) == FUNCTION_TYPE)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            build_procedure_call(call_location, symbol, expression->arguments());
 | 
					            this->current_expression = build1(ADDR_EXPR,
 | 
				
			||||||
 | 
					                    build_pointer_type_for_mode(expression_type, VOIDmode, true), this->current_expression);
 | 
				
			||||||
 | 
					            build_procedure_call(call_location, this->current_expression, expression->arguments);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (TYPE_P(symbol) && TREE_CODE(symbol) == RECORD_TYPE)
 | 
					        else if (is_pointer_type(expression_type) && TREE_CODE(TREE_TYPE(expression_type)) == FUNCTION_TYPE)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            build_record_call(call_location, symbol, expression->arguments());
 | 
					            build_procedure_call(call_location, this->current_expression, expression->arguments);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            error_at(call_location, "'%s' cannot be called, it is neither a procedure nor record",
 | 
					            error_at(call_location, "'%s' cannot be called, it is neither a procedure nor record",
 | 
				
			||||||
                    print_type(TYPE_P(symbol) ? symbol : TREE_TYPE(symbol)).c_str());
 | 
					                    print_type(expression_type).c_str());
 | 
				
			||||||
            this->current_expression = error_mark_node;
 | 
					            this->current_expression = error_mark_node;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -242,7 +250,7 @@ namespace gcc
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void generic_visitor::visit(boot::procedure_definition *definition)
 | 
					    void generic_visitor::visit(boot::procedure_definition *definition)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        tree declaration_type = build_type(definition->heading());
 | 
					        tree declaration_type = build_procedure_type(definition->heading());
 | 
				
			||||||
        tree fndecl = build_fn_decl(definition->identifier.c_str(), declaration_type);
 | 
					        tree fndecl = build_fn_decl(definition->identifier.c_str(), declaration_type);
 | 
				
			||||||
        this->symbol_map->enter(definition->identifier, fndecl);
 | 
					        this->symbol_map->enter(definition->identifier, fndecl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -281,6 +289,7 @@ namespace gcc
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        DECL_ARGUMENTS(fndecl) = argument_chain;
 | 
					        DECL_ARGUMENTS(fndecl) = argument_chain;
 | 
				
			||||||
        TREE_PUBLIC(fndecl) = definition->exported;
 | 
					        TREE_PUBLIC(fndecl) = definition->exported;
 | 
				
			||||||
 | 
					        TREE_ADDRESSABLE(fndecl) = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (definition->body != nullptr)
 | 
					        if (definition->body != nullptr)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -647,6 +656,7 @@ namespace gcc
 | 
				
			|||||||
        switch (expression->operation())
 | 
					        switch (expression->operation())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            case boot::unary_operator::reference:
 | 
					            case boot::unary_operator::reference:
 | 
				
			||||||
 | 
					                this->current_expression = prepare_rvalue(this->current_expression);
 | 
				
			||||||
                TREE_ADDRESSABLE(this->current_expression) = 1;
 | 
					                TREE_ADDRESSABLE(this->current_expression) = 1;
 | 
				
			||||||
                this->current_expression = build_fold_addr_expr_with_type_loc(location,
 | 
					                this->current_expression = build_fold_addr_expr_with_type_loc(location,
 | 
				
			||||||
                        this->current_expression,
 | 
					                        this->current_expression,
 | 
				
			||||||
@@ -739,6 +749,21 @@ namespace gcc
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tree generic_visitor::build_procedure_type(boot::procedure_type& type)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<tree> parameter_types(type.parameters.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (std::size_t i = 0; i < type.parameters.size(); ++i)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            parameter_types[i] = build_type(type.parameters.at(i)->variable_type());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        tree return_type = type.return_type == nullptr
 | 
				
			||||||
 | 
					            ? void_type_node
 | 
				
			||||||
 | 
					            : build_type(*type.return_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return build_function_type_array(return_type, type.parameters.size(), parameter_types.data());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tree generic_visitor::build_type(boot::top_type& type)
 | 
					    tree generic_visitor::build_type(boot::top_type& type)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (std::shared_ptr<boot::basic_type> basic_type = type.is_basic())
 | 
					        if (std::shared_ptr<boot::basic_type> basic_type = type.is_basic())
 | 
				
			||||||
@@ -834,18 +859,8 @@ namespace gcc
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (std::shared_ptr<boot::procedure_type> procedure_type = type.is_procedure())
 | 
					        else if (std::shared_ptr<boot::procedure_type> procedure_type = type.is_procedure())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::vector<tree> parameter_types(procedure_type->parameters.size());
 | 
					            tree procedure_type_node = build_procedure_type(*procedure_type);
 | 
				
			||||||
 | 
					            return build_pointer_type_for_mode(procedure_type_node, VOIDmode, true);
 | 
				
			||||||
            for (std::size_t i = 0; i < procedure_type->parameters.size(); ++i)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                parameter_types[i] = build_type(procedure_type->parameters.at(i)->variable_type());
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            tree return_type = procedure_type->return_type == nullptr
 | 
					 | 
				
			||||||
                ? void_type_node
 | 
					 | 
				
			||||||
                : build_type(*procedure_type->return_type);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return build_function_type_array(return_type,
 | 
					 | 
				
			||||||
                    procedure_type->parameters.size(), parameter_types.data());
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return NULL_TREE;
 | 
					        return NULL_TREE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -893,14 +908,10 @@ namespace gcc
 | 
				
			|||||||
        if (symbol == NULL_TREE)
 | 
					        if (symbol == NULL_TREE)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            error_at(get_location(&expression->position()),
 | 
					            error_at(get_location(&expression->position()),
 | 
				
			||||||
                    "variable '%s' not declared in the current scope",
 | 
					                    "symbol '%s' not declared in the current scope",
 | 
				
			||||||
                    expression->name().c_str());
 | 
					                    expression->name().c_str());
 | 
				
			||||||
            this->current_expression = error_mark_node;
 | 
					            this->current_expression = error_mark_node;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (TREE_CODE(symbol) == FUNCTION_DECL)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            this->current_expression = build1(ADDR_EXPR, build_pointer_type(TREE_TYPE(symbol)), symbol);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            this->current_expression = symbol;
 | 
					            this->current_expression = symbol;
 | 
				
			||||||
@@ -1029,10 +1040,11 @@ namespace gcc
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        statement->lvalue().accept(this);
 | 
					        statement->lvalue().accept(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto lvalue = this->current_expression;
 | 
					        tree lvalue = this->current_expression;
 | 
				
			||||||
        auto statement_location = get_location(&statement->position());
 | 
					        location_t statement_location = get_location(&statement->position());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        statement->rvalue().accept(this);
 | 
					        statement->rvalue().accept(this);
 | 
				
			||||||
 | 
					        tree rvalue = prepare_rvalue(this->current_expression);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (TREE_CODE(lvalue) == CONST_DECL)
 | 
					        if (TREE_CODE(lvalue) == CONST_DECL)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -1040,10 +1052,9 @@ namespace gcc
 | 
				
			|||||||
                    statement->lvalue().is_variable()->name().c_str());
 | 
					                    statement->lvalue().is_variable()->name().c_str());
 | 
				
			||||||
            this->current_expression = error_mark_node;
 | 
					            this->current_expression = error_mark_node;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (is_assignable_from(TREE_TYPE(lvalue), this->current_expression))
 | 
					        else if (is_assignable_from(TREE_TYPE(lvalue), rvalue))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            tree assignment = build2_loc(statement_location, MODIFY_EXPR,
 | 
					            tree assignment = build2_loc(statement_location, MODIFY_EXPR, void_type_node, lvalue, rvalue);
 | 
				
			||||||
                    void_type_node, lvalue, this->current_expression);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            append_statement(assignment);
 | 
					            append_statement(assignment);
 | 
				
			||||||
            this->current_expression = NULL_TREE;
 | 
					            this->current_expression = NULL_TREE;
 | 
				
			||||||
@@ -1052,7 +1063,7 @@ namespace gcc
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            error_at(statement_location,
 | 
					            error_at(statement_location,
 | 
				
			||||||
                    "cannot assign value of type '%s' to variable of type '%s'",
 | 
					                    "cannot assign value of type '%s' to variable of type '%s'",
 | 
				
			||||||
                    print_type(TREE_TYPE(this->current_expression)).c_str(),
 | 
					                    print_type(TREE_TYPE(rvalue)).c_str(),
 | 
				
			||||||
                    print_type(TREE_TYPE(lvalue)).c_str());
 | 
					                    print_type(TREE_TYPE(lvalue)).c_str());
 | 
				
			||||||
            this->current_expression = error_mark_node;
 | 
					            this->current_expression = error_mark_node;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,12 +51,6 @@ namespace gcc
 | 
				
			|||||||
        return TREE_CODE(type) == ARRAY_TYPE;
 | 
					        return TREE_CODE(type) == ARRAY_TYPE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool is_procedure_type(tree type)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        gcc_assert(TYPE_P(type));
 | 
					 | 
				
			||||||
        return TREE_CODE(type) == FUNCTION_TYPE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool is_void_type(tree type)
 | 
					    bool is_void_type(tree type)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return type == NULL_TREE || type == void_type_node;
 | 
					        return type == NULL_TREE || type == void_type_node;
 | 
				
			||||||
@@ -77,6 +71,18 @@ namespace gcc
 | 
				
			|||||||
            || (is_pointer_type(lhs_type) && lhs_type == rhs_type);
 | 
					            || (is_pointer_type(lhs_type) && lhs_type == rhs_type);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tree prepare_rvalue(tree rvalue)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (DECL_P(rvalue) && TREE_CODE(TREE_TYPE(rvalue)) == FUNCTION_TYPE)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return build1(ADDR_EXPR, build_pointer_type_for_mode(TREE_TYPE(rvalue), VOIDmode, true), rvalue);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return rvalue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool is_assignable_from(tree assignee, tree assignment)
 | 
					    bool is_assignable_from(tree assignee, tree assignment)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return get_qualified_type(TREE_TYPE(assignment), TYPE_UNQUALIFIED) == assignee
 | 
					        return get_qualified_type(TREE_TYPE(assignment), TYPE_UNQUALIFIED) == assignee
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -417,28 +417,6 @@ namespace boot
 | 
				
			|||||||
        top_type& body();
 | 
					        top_type& body();
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Procedure call expression.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    class call_expression : public expression
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        std::string m_name;
 | 
					 | 
				
			||||||
        std::vector<expression *> m_arguments;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public:
 | 
					 | 
				
			||||||
        /**
 | 
					 | 
				
			||||||
         * \param position Source code position.
 | 
					 | 
				
			||||||
         * \param name Callable's name.
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        call_expression(const struct position position, const std::string& name);
 | 
					 | 
				
			||||||
        virtual void accept(parser_visitor *visitor) override;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::string& name();
 | 
					 | 
				
			||||||
        std::vector<expression *>& arguments();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        virtual ~call_expression() override;
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Cast expression.
 | 
					     * Cast expression.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@@ -589,6 +567,24 @@ namespace boot
 | 
				
			|||||||
        ~dereference_expression() override;
 | 
					        ~dereference_expression() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Procedure call expression.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    class call_expression : public expression
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        designator_expression *m_callable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        std::vector<expression *> arguments;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        call_expression(const struct position position, designator_expression *callable);
 | 
				
			||||||
 | 
					        virtual void accept(parser_visitor *visitor) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        designator_expression& callable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        virtual ~call_expression() override;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class assign_statement : public statement
 | 
					    class assign_statement : public statement
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        designator_expression *m_lvalue;
 | 
					        designator_expression *m_lvalue;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,6 +40,7 @@ namespace gcc
 | 
				
			|||||||
        std::shared_ptr<symbol_table> symbol_map;
 | 
					        std::shared_ptr<symbol_table> symbol_map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tree build_label_decl(const char *name, location_t loc);
 | 
					        tree build_label_decl(const char *name, location_t loc);
 | 
				
			||||||
 | 
					        tree build_procedure_type(boot::procedure_type& type);
 | 
				
			||||||
        tree build_type(boot::top_type& type);
 | 
					        tree build_type(boot::top_type& type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void enter_scope();
 | 
					        void enter_scope();
 | 
				
			||||||
@@ -56,7 +57,7 @@ namespace gcc
 | 
				
			|||||||
        tree build_bit_logic_operation(boot::binary_expression *expression, tree left, tree right);
 | 
					        tree build_bit_logic_operation(boot::binary_expression *expression, tree left, tree right);
 | 
				
			||||||
        tree build_equality_operation(boot::binary_expression *expression, tree left, tree right);
 | 
					        tree build_equality_operation(boot::binary_expression *expression, tree left, tree right);
 | 
				
			||||||
        void build_procedure_call(location_t call_location,
 | 
					        void build_procedure_call(location_t call_location,
 | 
				
			||||||
                tree symbol, const std::vector<boot::expression *>& arguments);
 | 
					                tree procedure_address, const std::vector<boot::expression *>& arguments);
 | 
				
			||||||
        void build_record_call(location_t call_location,
 | 
					        void build_record_call(location_t call_location,
 | 
				
			||||||
                tree symbol, const std::vector<boot::expression *>& arguments);
 | 
					                tree symbol, const std::vector<boot::expression *>& arguments);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,7 +39,6 @@ namespace gcc
 | 
				
			|||||||
    bool is_integral_type(tree type);
 | 
					    bool is_integral_type(tree type);
 | 
				
			||||||
    bool is_numeric_type(tree type);
 | 
					    bool is_numeric_type(tree type);
 | 
				
			||||||
    bool is_array_type(tree type);
 | 
					    bool is_array_type(tree type);
 | 
				
			||||||
    bool is_procedure_type(tree type);
 | 
					 | 
				
			||||||
    bool is_void_type(tree type);
 | 
					    bool is_void_type(tree type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -55,6 +54,16 @@ namespace gcc
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    bool are_compatible_pointers(tree lhs_type, tree rhs);
 | 
					    bool are_compatible_pointers(tree lhs_type, tree rhs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Prepares a value to be bound to a variable or parameter.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * If rvalue is a procedure declaration, builds a procedure pointer.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * \param rvalue Value to be assigned.
 | 
				
			||||||
 | 
					     * \return Processed value.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    tree prepare_rvalue(tree rvalue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * \param assignee Assignee.
 | 
					     * \param assignee Assignee.
 | 
				
			||||||
     * \param assignee Assignment.
 | 
					     * \param assignee Assignment.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								source.elna
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								source.elna
									
									
									
									
									
								
							@@ -891,19 +891,6 @@ begin
 | 
				
			|||||||
  return 0
 | 
					  return 0
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc f();
 | 
					 | 
				
			||||||
begin
 | 
					begin
 | 
				
			||||||
  write_s("In f\n")
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
proc g();
 | 
					 | 
				
			||||||
var x: ^proc()
 | 
					 | 
				
			||||||
begin
 | 
					 | 
				
			||||||
  x := cast(f: ^proc())
 | 
					 | 
				
			||||||
  (* x() *)
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
begin
 | 
					 | 
				
			||||||
  g()
 | 
					 | 
				
			||||||
  exit(process(cast(count: Int), cast(parameters: ^^Char)))
 | 
					  exit(process(cast(count: Int), cast(parameters: ^^Char)))
 | 
				
			||||||
end.
 | 
					end.
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user