Implement enumeration type
This commit is contained in:
		
							
								
								
									
										38
									
								
								boot/ast.cc
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								boot/ast.cc
									
									
									
									
									
								
							@@ -103,7 +103,7 @@ namespace elna::boot
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    primitive_type_expression *type_expression::is_primitive()
 | 
					    named_type_expression *type_expression::is_named()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return nullptr;
 | 
					        return nullptr;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -133,17 +133,22 @@ namespace elna::boot
 | 
				
			|||||||
        return nullptr;
 | 
					        return nullptr;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    primitive_type_expression::primitive_type_expression(const struct position position, const std::string& name)
 | 
					    enumeration_type_expression *type_expression::is_enumeration()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    named_type_expression::named_type_expression(const struct position position, const std::string& name)
 | 
				
			||||||
        : type_expression(position), name(name)
 | 
					        : type_expression(position), name(name)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void primitive_type_expression::accept(parser_visitor *visitor)
 | 
					    void named_type_expression::accept(parser_visitor *visitor)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        visitor->visit(this);
 | 
					        visitor->visit(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    primitive_type_expression *primitive_type_expression::is_primitive()
 | 
					    named_type_expression *named_type_expression::is_named()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -312,6 +317,26 @@ namespace elna::boot
 | 
				
			|||||||
        visitor->visit(this);
 | 
					        visitor->visit(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    procedure_type_expression *procedure_type_expression::is_procedure()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enumeration_type_expression::enumeration_type_expression(const struct position position, std::vector<std::string>&& members)
 | 
				
			||||||
 | 
					        : type_expression(position), members(members)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void enumeration_type_expression::accept(parser_visitor *visitor)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        visitor->visit(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enumeration_type_expression *enumeration_type_expression::is_enumeration()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
 | 
					    procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
 | 
				
			||||||
            const bool exported, procedure_type_expression *heading, block *body)
 | 
					            const bool exported, procedure_type_expression *heading, block *body)
 | 
				
			||||||
        : definition(position, identifier, exported), m_heading(heading), body(body)
 | 
					        : definition(position, identifier, exported), m_heading(heading), body(body)
 | 
				
			||||||
@@ -323,11 +348,6 @@ namespace elna::boot
 | 
				
			|||||||
        visitor->visit(this);
 | 
					        visitor->visit(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    procedure_type_expression *procedure_type_expression::is_procedure()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    procedure_type_expression& procedure_definition::heading()
 | 
					    procedure_type_expression& procedure_definition::heading()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return *m_heading;
 | 
					        return *m_heading;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -157,6 +157,7 @@ along with GCC; see the file COPYING3.  If not see
 | 
				
			|||||||
%type <elna::boot::defer_statement *> defer_statement;
 | 
					%type <elna::boot::defer_statement *> defer_statement;
 | 
				
			||||||
%type <std::pair<std::string, bool>> identifier_definition;
 | 
					%type <std::pair<std::string, bool>> identifier_definition;
 | 
				
			||||||
%type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
 | 
					%type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
 | 
				
			||||||
 | 
					%type <std::vector<std::string>> identifiers;
 | 
				
			||||||
%%
 | 
					%%
 | 
				
			||||||
program:
 | 
					program:
 | 
				
			||||||
    constant_part type_part variable_part procedure_part "begin" statements "end" "."
 | 
					    constant_part type_part variable_part procedure_part "begin" statements "end" "."
 | 
				
			||||||
@@ -507,10 +508,21 @@ type_expression:
 | 
				
			|||||||
            std::swap(result->parameters, $3);
 | 
					            std::swap(result->parameters, $3);
 | 
				
			||||||
            $$ = result;
 | 
					            $$ = result;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    | "(" identifiers ")"
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            $$ = new boot::enumeration_type_expression(boot::make_position(@1), std::move($2));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    | IDENTIFIER
 | 
					    | IDENTIFIER
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $$ = new boot::primitive_type_expression(boot::make_position(@1), $1);
 | 
					            $$ = new boot::named_type_expression(boot::make_position(@1), $1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					identifiers:
 | 
				
			||||||
 | 
					    IDENTIFIER "," identifiers
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::swap($$, $3);
 | 
				
			||||||
 | 
					            $$.emplace($$.cbegin(), std::move($1));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    | IDENTIFIER { $$.emplace_back(std::move($1)); }
 | 
				
			||||||
variable_declaration: identifier_definitions ":" type_expression
 | 
					variable_declaration: identifier_definitions ":" type_expression
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::shared_ptr<boot::type_expression> shared_type{ $3 };
 | 
					            std::shared_ptr<boot::type_expression> shared_type{ $3 };
 | 
				
			||||||
@@ -561,16 +573,14 @@ type_definitions:
 | 
				
			|||||||
type_part:
 | 
					type_part:
 | 
				
			||||||
    /* no type definitions */ {}
 | 
					    /* no type definitions */ {}
 | 
				
			||||||
    | "type" type_definitions { std::swap($$, $2); }
 | 
					    | "type" type_definitions { std::swap($$, $2); }
 | 
				
			||||||
formal_parameter: IDENTIFIER ":" type_expression
 | 
					formal_parameter:
 | 
				
			||||||
        {
 | 
					    IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); }
 | 
				
			||||||
            $$ = std::make_pair($1, $3);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
formal_parameters:
 | 
					formal_parameters:
 | 
				
			||||||
    /* no formal parameters */ {}
 | 
					    /* no formal parameters */ {}
 | 
				
			||||||
    | formal_parameter "," formal_parameters
 | 
					    | formal_parameter "," formal_parameters
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::swap($$, $3);
 | 
					            std::swap($$, $3);
 | 
				
			||||||
            $$.emplace($$.cbegin(), $1);
 | 
					            $$.emplace($$.cbegin(), std::move($1));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    | formal_parameter { $$.emplace_back(std::move($1)); }
 | 
					    | formal_parameter { $$.emplace_back(std::move($1)); }
 | 
				
			||||||
actual_parameter_list:
 | 
					actual_parameter_list:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -114,7 +114,7 @@ namespace elna::boot
 | 
				
			|||||||
        unresolved_declaration->reference = this->current_type;
 | 
					        unresolved_declaration->reference = this->current_type;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(primitive_type_expression *type_expression)
 | 
					    void declaration_visitor::visit(named_type_expression *type_expression)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        auto unresolved_alias = this->unresolved.find(type_expression->name);
 | 
					        auto unresolved_alias = this->unresolved.find(type_expression->name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -177,13 +177,23 @@ namespace elna::boot
 | 
				
			|||||||
        this->current_type = type(result_type);
 | 
					        this->current_type = type(result_type);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void declaration_visitor::visit(enumeration_type_expression *type_expression)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::shared_ptr<enumeration_type> result_type = std::make_shared<enumeration_type>(type_expression->members);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this->current_type = type(result_type);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(variable_declaration *declaration)
 | 
					    void declaration_visitor::visit(variable_declaration *declaration)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        declaration->variable_type().accept(this);
 | 
					        declaration->variable_type().accept(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(constant_definition *)
 | 
					    void declaration_visitor::visit(constant_definition *definition)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        definition->body().accept(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this->symbols->enter(definition->identifier, std::make_shared<constant_info>(this->current_literal));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(procedure_definition *definition)
 | 
					    void declaration_visitor::visit(procedure_definition *definition)
 | 
				
			||||||
@@ -333,31 +343,38 @@ namespace elna::boot
 | 
				
			|||||||
        expression->base().accept(this);
 | 
					        expression->base().accept(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(literal<std::int32_t> *)
 | 
					    void declaration_visitor::visit(literal<std::int32_t> *literal)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        this->current_literal = literal->value;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(literal<std::uint32_t> *)
 | 
					    void declaration_visitor::visit(literal<std::uint32_t> *literal)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        this->current_literal = literal->value;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(literal<double> *)
 | 
					    void declaration_visitor::visit(literal<double> *literal)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        this->current_literal = literal->value;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(literal<bool> *)
 | 
					    void declaration_visitor::visit(literal<bool> *literal)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        this->current_literal = literal->value;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(literal<unsigned char> *)
 | 
					    void declaration_visitor::visit(literal<unsigned char> *literal)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        this->current_literal = literal->value;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(literal<std::nullptr_t> *)
 | 
					    void declaration_visitor::visit(literal<std::nullptr_t> *literal)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        this->current_literal = literal->value;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void declaration_visitor::visit(literal<std::string> *)
 | 
					    void declaration_visitor::visit(literal<std::string> *literal)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        this->current_literal = literal->value;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,6 +58,11 @@ namespace elna::boot
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    type::type(std::shared_ptr<enumeration_type> enumeration)
 | 
				
			||||||
 | 
					        : tag(type_tag::enumeration), enumeration(enumeration)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void type::copy(const type& other)
 | 
					    void type::copy(const type& other)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        switch (other.tag)
 | 
					        switch (other.tag)
 | 
				
			||||||
@@ -85,6 +90,9 @@ namespace elna::boot
 | 
				
			|||||||
        case type_tag::procedure:
 | 
					        case type_tag::procedure:
 | 
				
			||||||
            new (&procedure) std::shared_ptr<procedure_type>(other.procedure);
 | 
					            new (&procedure) std::shared_ptr<procedure_type>(other.procedure);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					        case type_tag::enumeration:
 | 
				
			||||||
 | 
					            new (&enumeration) std::shared_ptr<enumeration_type>(other.enumeration);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -121,6 +129,9 @@ namespace elna::boot
 | 
				
			|||||||
        case type_tag::procedure:
 | 
					        case type_tag::procedure:
 | 
				
			||||||
            new (&procedure) std::shared_ptr<procedure_type>(std::move(other.procedure));
 | 
					            new (&procedure) std::shared_ptr<procedure_type>(std::move(other.procedure));
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					        case type_tag::enumeration:
 | 
				
			||||||
 | 
					            new (&enumeration) std::shared_ptr<enumeration_type>(std::move(other.enumeration));
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -178,6 +189,9 @@ namespace elna::boot
 | 
				
			|||||||
        case type_tag::procedure:
 | 
					        case type_tag::procedure:
 | 
				
			||||||
            this->procedure.~shared_ptr<procedure_type>();
 | 
					            this->procedure.~shared_ptr<procedure_type>();
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					        case type_tag::enumeration:
 | 
				
			||||||
 | 
					            this->enumeration.~shared_ptr<enumeration_type>();
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -223,6 +237,12 @@ namespace elna::boot
 | 
				
			|||||||
        return tag == type_tag::procedure ? this->procedure : nullptr;
 | 
					        return tag == type_tag::procedure ? this->procedure : nullptr;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<>
 | 
				
			||||||
 | 
					    std::shared_ptr<enumeration_type> type::get<enumeration_type>() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return tag == type_tag::enumeration ? this->enumeration : nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool type::empty() const
 | 
					    bool type::empty() const
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return tag == type_tag::empty;
 | 
					        return tag == type_tag::empty;
 | 
				
			||||||
@@ -253,6 +273,11 @@ namespace elna::boot
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enumeration_type::enumeration_type(const std::vector<std::string>& members)
 | 
				
			||||||
 | 
					        : members(members)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    info::~info()
 | 
					    info::~info()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -287,6 +312,11 @@ namespace elna::boot
 | 
				
			|||||||
        return std::static_pointer_cast<procedure_info>(shared_from_this());
 | 
					        return std::static_pointer_cast<procedure_info>(shared_from_this());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constant_info::constant_info(const variant& symbol)
 | 
				
			||||||
 | 
					        : symbol(symbol)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::shared_ptr<symbol_table> builtin_symbol_table()
 | 
					    std::shared_ptr<symbol_table> builtin_symbol_table()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        auto result = std::make_shared<symbol_table>();
 | 
					        auto result = std::make_shared<symbol_table>();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -78,7 +78,7 @@ namespace elna::gcc
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            return "()";
 | 
					            return "()";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (is_pointer_type(unqualified_type))
 | 
					        else if (POINTER_TYPE_P(unqualified_type))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            tree pointer_target_type = TREE_TYPE(type);
 | 
					            tree pointer_target_type = TREE_TYPE(type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -129,6 +129,10 @@ namespace elna::gcc
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            return print_aggregate_name(unqualified_type, "union");
 | 
					            return print_aggregate_name(unqualified_type, "union");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        else if (TREE_CODE(type) == ENUMERAL_TYPE)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return print_aggregate_name(unqualified_type, "enumeration");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return "<<unknown-type>>";
 | 
					            return "<<unknown-type>>";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,6 +57,10 @@ namespace elna::gcc
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            return make_node(UNION_TYPE);
 | 
					            return make_node(UNION_TYPE);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        else if (auto reference = type.get<boot::enumeration_type>())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return make_node(ENUMERAL_TYPE);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        else if (auto reference = type.get<boot::pointer_type>())
 | 
					        else if (auto reference = type.get<boot::pointer_type>())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return build_global_pointer_type(get_inner_alias(reference->base, symbols, unresolved, path));
 | 
					            return build_global_pointer_type(get_inner_alias(reference->base, symbols, unresolved, path));
 | 
				
			||||||
@@ -227,7 +231,7 @@ namespace elna::gcc
 | 
				
			|||||||
                    build_global_pointer_type(expression_type), this->current_expression);
 | 
					                    build_global_pointer_type(expression_type), this->current_expression);
 | 
				
			||||||
            build_procedure_call(call_location, this->current_expression, call->arguments);
 | 
					            build_procedure_call(call_location, this->current_expression, call->arguments);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (is_pointer_type(expression_type) && TREE_CODE(TREE_TYPE(expression_type)) == FUNCTION_TYPE)
 | 
					        else if (POINTER_TYPE_P(expression_type) && TREE_CODE(TREE_TYPE(expression_type)) == FUNCTION_TYPE)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            build_procedure_call(call_location, this->current_expression, call->arguments);
 | 
					            build_procedure_call(call_location, this->current_expression, call->arguments);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -247,8 +251,7 @@ namespace elna::gcc
 | 
				
			|||||||
        expression->value().accept(this);
 | 
					        expression->value().accept(this);
 | 
				
			||||||
        tree cast_source = TREE_TYPE(this->current_expression);
 | 
					        tree cast_source = TREE_TYPE(this->current_expression);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((is_primitive_type(cast_target) || is_pointer_type(cast_target))
 | 
					        if (is_castable_type(cast_target) && (is_castable_type(cast_source)))
 | 
				
			||||||
                && (is_primitive_type(cast_source) || is_pointer_type(cast_source)))
 | 
					 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            this->current_expression = build1_loc(get_location(&expression->position()), CONVERT_EXPR,
 | 
					            this->current_expression = build1_loc(get_location(&expression->position()), CONVERT_EXPR,
 | 
				
			||||||
                    cast_target, this->current_expression);
 | 
					                    cast_target, this->current_expression);
 | 
				
			||||||
@@ -303,7 +306,8 @@ namespace elna::gcc
 | 
				
			|||||||
        for (boot::constant_definition *const constant : program->constants)
 | 
					        for (boot::constant_definition *const constant : program->constants)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            constant->accept(this);
 | 
					            constant->accept(this);
 | 
				
			||||||
        } for (boot::type_definition *const type : program->types)
 | 
					        }
 | 
				
			||||||
 | 
					        for (boot::type_definition *const type : program->types)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            type->accept(this);
 | 
					            type->accept(this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -514,7 +518,7 @@ namespace elna::gcc
 | 
				
			|||||||
    tree generic_visitor::build_comparison_operation(boot::binary_expression *expression,
 | 
					    tree generic_visitor::build_comparison_operation(boot::binary_expression *expression,
 | 
				
			||||||
            tree_code operator_code, tree left, tree right)
 | 
					            tree_code operator_code, tree left, tree right)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return build_binary_operation(is_numeric_type(TREE_TYPE(left)) || is_pointer_type(TREE_TYPE(left)),
 | 
					        return build_binary_operation(is_numeric_type(TREE_TYPE(left)) || POINTER_TYPE_P(TREE_TYPE(left)),
 | 
				
			||||||
                expression, operator_code, left, right, elna_bool_type_node);
 | 
					                expression, operator_code, left, right, elna_bool_type_node);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -624,7 +628,7 @@ namespace elna::gcc
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        location_t expression_location = get_location(&expression->position());
 | 
					        location_t expression_location = get_location(&expression->position());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((is_pointer_type(left_type) || is_pointer_type(right_type))
 | 
					        if ((POINTER_TYPE_P(left_type) || POINTER_TYPE_P(right_type))
 | 
				
			||||||
                && (expression->operation() == boot::binary_operator::sum
 | 
					                && (expression->operation() == boot::binary_operator::sum
 | 
				
			||||||
                    || expression->operation() == boot::binary_operator::subtraction))
 | 
					                    || expression->operation() == boot::binary_operator::subtraction))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -867,7 +871,7 @@ namespace elna::gcc
 | 
				
			|||||||
                get_identifier(declaration->identifier.c_str()), this->current_expression);
 | 
					                get_identifier(declaration->identifier.c_str()), this->current_expression);
 | 
				
			||||||
        bool result = this->symbols->enter(declaration->identifier, declaration_tree);
 | 
					        bool result = this->symbols->enter(declaration->identifier, declaration_tree);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (is_pointer_type(this->current_expression))
 | 
					        if (POINTER_TYPE_P(this->current_expression))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            DECL_INITIAL(declaration_tree) = elna_pointer_nil_node;
 | 
					            DECL_INITIAL(declaration_tree) = elna_pointer_nil_node;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -976,7 +980,7 @@ namespace elna::gcc
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (!is_integral_type(this->current_expression))
 | 
					        else if (!is_integral_type(this->current_expression) && TREE_CODE(this->current_expression) != ENUMERAL_TYPE)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            error_at(get_location(&trait->position()), "Type '%s' does not support trait '%s'",
 | 
					            error_at(get_location(&trait->position()), "Type '%s' does not support trait '%s'",
 | 
				
			||||||
                    print_type(this->current_expression).c_str(), trait->name.c_str());
 | 
					                    print_type(this->current_expression).c_str(), trait->name.c_str());
 | 
				
			||||||
@@ -1030,7 +1034,7 @@ namespace elna::gcc
 | 
				
			|||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            trait->parameters.front()->accept(this);
 | 
					            trait->parameters.front()->accept(this);
 | 
				
			||||||
            auto field_type = trait->parameters.at(1)->is_primitive();
 | 
					            auto field_type = trait->parameters.at(1)->is_named();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (field_type == nullptr)
 | 
					            if (field_type == nullptr)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@@ -1076,6 +1080,21 @@ namespace elna::gcc
 | 
				
			|||||||
            this->current_expression = build1(ADDR_EXPR,
 | 
					            this->current_expression = build1(ADDR_EXPR,
 | 
				
			||||||
                    build_qualified_type(ptr_type, TYPE_QUAL_CONST), this->current_expression);
 | 
					                    build_qualified_type(ptr_type, TYPE_QUAL_CONST), this->current_expression);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        else if (TREE_CODE(aggregate_type) == ENUMERAL_TYPE)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            tree iterator{ NULL_TREE };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (iterator = TYPE_VALUES(aggregate_type); iterator != NULL_TREE; iterator = TREE_CHAIN(iterator))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (IDENTIFIER_POINTER(TREE_PURPOSE(iterator)) == expression->field())
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    this->current_expression = TREE_VALUE(iterator);
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            this->current_expression = error_mark_node;
 | 
				
			||||||
 | 
					            error_at(expression_location, "Unknown enumeration member '%s'", expression->field().c_str());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            tree field_declaration = find_field_by_name(expression_location,
 | 
					            tree field_declaration = find_field_by_name(expression_location,
 | 
				
			||||||
@@ -1096,7 +1115,7 @@ namespace elna::gcc
 | 
				
			|||||||
        location_t expression_location = get_location(&expression->position());
 | 
					        location_t expression_location = get_location(&expression->position());
 | 
				
			||||||
        tree expression_type = TREE_TYPE(this->current_expression);
 | 
					        tree expression_type = TREE_TYPE(this->current_expression);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (is_pointer_type(expression_type))
 | 
					        if (POINTER_TYPE_P(expression_type))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            this->current_expression = build1_loc(expression_location, INDIRECT_REF,
 | 
					            this->current_expression = build1_loc(expression_location, INDIRECT_REF,
 | 
				
			||||||
                    TREE_TYPE(expression_type), this->current_expression);
 | 
					                    TREE_TYPE(expression_type), this->current_expression);
 | 
				
			||||||
@@ -1285,7 +1304,7 @@ namespace elna::gcc
 | 
				
			|||||||
        this->current_expression = NULL_TREE;
 | 
					        this->current_expression = NULL_TREE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void generic_visitor::visit(boot::primitive_type_expression *type)
 | 
					    void generic_visitor::visit(boot::named_type_expression *type)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        auto looked_up = this->unresolved.find(type->name);
 | 
					        auto looked_up = this->unresolved.find(type->name);
 | 
				
			||||||
        tree symbol;
 | 
					        tree symbol;
 | 
				
			||||||
@@ -1362,6 +1381,44 @@ namespace elna::gcc
 | 
				
			|||||||
        this->current_expression = build_global_pointer_type(procedure_type_node);
 | 
					        this->current_expression = build_global_pointer_type(procedure_type_node);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void generic_visitor::visit(boot::enumeration_type_expression *type)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        tree composite_type_node = this->current_expression == NULL_TREE
 | 
				
			||||||
 | 
					            ? make_node(ENUMERAL_TYPE)
 | 
				
			||||||
 | 
					            : this->current_expression;
 | 
				
			||||||
 | 
					        location_t enum_location = get_location(&type->position());
 | 
				
			||||||
 | 
					        const tree base_type = integer_type_node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        TREE_TYPE(composite_type_node) = base_type;
 | 
				
			||||||
 | 
					        ENUM_IS_SCOPED(composite_type_node) = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tree *pp = &TYPE_VALUES(composite_type_node);
 | 
				
			||||||
 | 
					        std::size_t order{ 1 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (const std::string& member : type->members)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            tree member_name = get_identifier(member.c_str());
 | 
				
			||||||
 | 
					            tree member_declaration = build_decl(enum_location, CONST_DECL, member_name, composite_type_node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            DECL_CONTEXT(member_declaration) = composite_type_node;
 | 
				
			||||||
 | 
					            DECL_INITIAL(member_declaration) = build_int_cst_type(composite_type_node, order++);
 | 
				
			||||||
 | 
					            TREE_CONSTANT(member_declaration) = 1;
 | 
				
			||||||
 | 
					            TREE_READONLY(member_declaration) = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            TYPE_MAX_VALUE(composite_type_node) = DECL_INITIAL(member_declaration);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            *pp = build_tree_list(member_name, member_declaration);
 | 
				
			||||||
 | 
					            pp = &TREE_CHAIN(*pp);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        TYPE_MIN_VALUE(composite_type_node) = DECL_INITIAL(TREE_VALUE(TYPE_VALUES(composite_type_node)));
 | 
				
			||||||
 | 
					        TYPE_UNSIGNED(composite_type_node) = TYPE_UNSIGNED(base_type);
 | 
				
			||||||
 | 
					        SET_TYPE_ALIGN(composite_type_node, TYPE_ALIGN(base_type));
 | 
				
			||||||
 | 
					        TYPE_SIZE(composite_type_node) = NULL_TREE;
 | 
				
			||||||
 | 
					        TYPE_PRECISION(composite_type_node) = TYPE_PRECISION(base_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        layout_type(composite_type_node);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void generic_visitor::visit(boot::defer_statement *statement)
 | 
					    void generic_visitor::visit(boot::defer_statement *statement)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        enter_scope();
 | 
					        enter_scope();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,12 +26,6 @@ along with GCC; see the file COPYING3.  If not see
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace elna::gcc
 | 
					namespace elna::gcc
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    bool is_pointer_type(tree type)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        gcc_assert(TYPE_P(type));
 | 
					 | 
				
			||||||
        return TREE_CODE(type) == POINTER_TYPE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool is_integral_type(tree type)
 | 
					    bool is_integral_type(tree type)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        gcc_assert(TYPE_P(type));
 | 
					        gcc_assert(TYPE_P(type));
 | 
				
			||||||
@@ -62,10 +56,12 @@ namespace elna::gcc
 | 
				
			|||||||
        return type == NULL_TREE || type == void_type_node;
 | 
					        return type == NULL_TREE || type == void_type_node;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool is_aggregate_type(tree type)
 | 
					    bool is_castable_type(tree type)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        gcc_assert(TYPE_P(type));
 | 
					        gcc_assert(TYPE_P(type));
 | 
				
			||||||
        return TREE_CODE(type) == RECORD_TYPE || TREE_CODE(type) == UNION_TYPE;
 | 
					        auto code = TREE_CODE(type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return is_primitive_type(type) || POINTER_TYPE_P(type) || code == ENUMERAL_TYPE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool are_compatible_pointers(tree lhs_type, tree rhs)
 | 
					    bool are_compatible_pointers(tree lhs_type, tree rhs)
 | 
				
			||||||
@@ -73,8 +69,8 @@ namespace elna::gcc
 | 
				
			|||||||
        gcc_assert(TYPE_P(lhs_type));
 | 
					        gcc_assert(TYPE_P(lhs_type));
 | 
				
			||||||
        tree rhs_type = TREE_TYPE(rhs);
 | 
					        tree rhs_type = TREE_TYPE(rhs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return (is_pointer_type(lhs_type) && rhs == elna_pointer_nil_node)
 | 
					        return (POINTER_TYPE_P(lhs_type) && rhs == elna_pointer_nil_node)
 | 
				
			||||||
            || (is_pointer_type(lhs_type) && lhs_type == rhs_type);
 | 
					            || (POINTER_TYPE_P(lhs_type) && lhs_type == rhs_type);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tree prepare_rvalue(tree rvalue)
 | 
					    tree prepare_rvalue(tree rvalue)
 | 
				
			||||||
@@ -152,12 +148,12 @@ namespace elna::gcc
 | 
				
			|||||||
            tree pointer{ NULL_TREE };
 | 
					            tree pointer{ NULL_TREE };
 | 
				
			||||||
            tree offset{ NULL_TREE };
 | 
					            tree offset{ NULL_TREE };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (is_pointer_type(left_type) && is_integral_type(right_type))
 | 
					            if (POINTER_TYPE_P(left_type) && is_integral_type(right_type))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                pointer = left;
 | 
					                pointer = left;
 | 
				
			||||||
                offset = right;
 | 
					                offset = right;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (is_integral_type(left_type) && is_pointer_type(right_type))
 | 
					            else if (is_integral_type(left_type) && POINTER_TYPE_P(right_type))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                pointer = right;
 | 
					                pointer = right;
 | 
				
			||||||
                offset = left;
 | 
					                offset = left;
 | 
				
			||||||
@@ -175,7 +171,7 @@ namespace elna::gcc
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (binary_operator == boot::binary_operator::subtraction)
 | 
					        else if (binary_operator == boot::binary_operator::subtraction)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (is_pointer_type(left_type) && is_integral_type(right_type))
 | 
					            if (POINTER_TYPE_P(left_type) && is_integral_type(right_type))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                tree pointer_type = left_type;
 | 
					                tree pointer_type = left_type;
 | 
				
			||||||
                tree offset_type = right_type;
 | 
					                tree offset_type = right_type;
 | 
				
			||||||
@@ -187,7 +183,7 @@ namespace elna::gcc
 | 
				
			|||||||
                convert_expression = fold_build1(NEGATE_EXPR, sizetype, convert_expression);
 | 
					                convert_expression = fold_build1(NEGATE_EXPR, sizetype, convert_expression);
 | 
				
			||||||
                return fold_build2(POINTER_PLUS_EXPR, pointer_type, left, convert_expression);
 | 
					                return fold_build2(POINTER_PLUS_EXPR, pointer_type, left, convert_expression);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (is_pointer_type(left_type) && is_pointer_type(right_type) && left_type == right_type)
 | 
					            else if (POINTER_TYPE_P(left_type) && POINTER_TYPE_P(right_type) && left_type == right_type)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return fold_build2(POINTER_DIFF_EXPR, ssizetype, left, right);
 | 
					                return fold_build2(POINTER_DIFF_EXPR, ssizetype, left, right);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -224,9 +220,9 @@ namespace elna::gcc
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        tree field_declaration = TYPE_FIELDS(type);
 | 
					        tree field_declaration = TYPE_FIELDS(type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!is_aggregate_type(type))
 | 
					        if (!RECORD_OR_UNION_TYPE_P(type))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            error_at(expression_location, "type '%s' does not have a field named '%s'",
 | 
					            error_at(expression_location, "Type '%s' does not have a field named '%s'",
 | 
				
			||||||
                    print_type(type).c_str(), field_name.c_str());
 | 
					                    print_type(type).c_str(), field_name.c_str());
 | 
				
			||||||
            return error_mark_node;
 | 
					            return error_mark_node;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -243,7 +239,7 @@ namespace elna::gcc
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        if (field_declaration == NULL_TREE)
 | 
					        if (field_declaration == NULL_TREE)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            error_at(expression_location, "record type does not have a field named '%s'", field_name.c_str());
 | 
					            error_at(expression_location, "Aggregate type does not have a field '%s'", field_name.c_str());
 | 
				
			||||||
            return error_mark_node;
 | 
					            return error_mark_node;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return field_declaration;
 | 
					        return field_declaration;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -67,12 +67,13 @@ namespace elna::boot
 | 
				
			|||||||
    class program;
 | 
					    class program;
 | 
				
			||||||
    class binary_expression;
 | 
					    class binary_expression;
 | 
				
			||||||
    class unary_expression;
 | 
					    class unary_expression;
 | 
				
			||||||
    class primitive_type_expression;
 | 
					    class named_type_expression;
 | 
				
			||||||
    class array_type_expression;
 | 
					    class array_type_expression;
 | 
				
			||||||
    class pointer_type_expression;
 | 
					    class pointer_type_expression;
 | 
				
			||||||
    class record_type_expression;
 | 
					    class record_type_expression;
 | 
				
			||||||
    class union_type_expression;
 | 
					    class union_type_expression;
 | 
				
			||||||
    class procedure_type_expression;
 | 
					    class procedure_type_expression;
 | 
				
			||||||
 | 
					    class enumeration_type_expression;
 | 
				
			||||||
    class variable_expression;
 | 
					    class variable_expression;
 | 
				
			||||||
    class array_access_expression;
 | 
					    class array_access_expression;
 | 
				
			||||||
    class field_access_expression;
 | 
					    class field_access_expression;
 | 
				
			||||||
@@ -104,12 +105,13 @@ namespace elna::boot
 | 
				
			|||||||
        virtual void visit(program *) = 0;
 | 
					        virtual void visit(program *) = 0;
 | 
				
			||||||
        virtual void visit(binary_expression *) = 0;
 | 
					        virtual void visit(binary_expression *) = 0;
 | 
				
			||||||
        virtual void visit(unary_expression *) = 0;
 | 
					        virtual void visit(unary_expression *) = 0;
 | 
				
			||||||
        virtual void visit(primitive_type_expression *) = 0;
 | 
					        virtual void visit(named_type_expression *) = 0;
 | 
				
			||||||
        virtual void visit(array_type_expression *) = 0;
 | 
					        virtual void visit(array_type_expression *) = 0;
 | 
				
			||||||
        virtual void visit(pointer_type_expression *) = 0;
 | 
					        virtual void visit(pointer_type_expression *) = 0;
 | 
				
			||||||
        virtual void visit(record_type_expression *) = 0;
 | 
					        virtual void visit(record_type_expression *) = 0;
 | 
				
			||||||
        virtual void visit(union_type_expression *) = 0;
 | 
					        virtual void visit(union_type_expression *) = 0;
 | 
				
			||||||
        virtual void visit(procedure_type_expression *) = 0;
 | 
					        virtual void visit(procedure_type_expression *) = 0;
 | 
				
			||||||
 | 
					        virtual void visit(enumeration_type_expression *) = 0;
 | 
				
			||||||
        virtual void visit(variable_expression *) = 0;
 | 
					        virtual void visit(variable_expression *) = 0;
 | 
				
			||||||
        virtual void visit(array_access_expression *) = 0;
 | 
					        virtual void visit(array_access_expression *) = 0;
 | 
				
			||||||
        virtual void visit(field_access_expression *) = 0;
 | 
					        virtual void visit(field_access_expression *) = 0;
 | 
				
			||||||
@@ -188,28 +190,29 @@ namespace elna::boot
 | 
				
			|||||||
    class type_expression : public node
 | 
					    class type_expression : public node
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        virtual primitive_type_expression *is_primitive();
 | 
					        virtual named_type_expression *is_named();
 | 
				
			||||||
        virtual array_type_expression *is_array();
 | 
					        virtual array_type_expression *is_array();
 | 
				
			||||||
        virtual pointer_type_expression *is_pointer();
 | 
					        virtual pointer_type_expression *is_pointer();
 | 
				
			||||||
        virtual record_type_expression *is_record();
 | 
					        virtual record_type_expression *is_record();
 | 
				
			||||||
        virtual union_type_expression *is_union();
 | 
					        virtual union_type_expression *is_union();
 | 
				
			||||||
        virtual procedure_type_expression *is_procedure();
 | 
					        virtual procedure_type_expression *is_procedure();
 | 
				
			||||||
 | 
					        virtual enumeration_type_expression *is_enumeration();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected:
 | 
					    protected:
 | 
				
			||||||
        type_expression(const struct position position);
 | 
					        type_expression(const struct position position);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Expression defining a basic type.
 | 
					     * Expression refering to a type by its name.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    class primitive_type_expression : public type_expression
 | 
					    class named_type_expression : public type_expression
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        const std::string name;
 | 
					        const std::string name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        primitive_type_expression(const struct position position, const std::string& name);
 | 
					        named_type_expression(const struct position position, const std::string& name);
 | 
				
			||||||
        void accept(parser_visitor *visitor) override;
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
        primitive_type_expression *is_primitive() override;
 | 
					        named_type_expression *is_named() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class array_type_expression : public type_expression
 | 
					    class array_type_expression : public type_expression
 | 
				
			||||||
@@ -269,6 +272,20 @@ namespace elna::boot
 | 
				
			|||||||
        union_type_expression *is_union() override;
 | 
					        union_type_expression *is_union() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Enumeration type.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    class enumeration_type_expression : public type_expression
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        const std::vector<std::string> members;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        enumeration_type_expression(const struct position, std::vector<std::string>&& members);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void accept(parser_visitor *visitor) override;
 | 
				
			||||||
 | 
					        enumeration_type_expression *is_enumeration() override;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Variable declaration.
 | 
					     * Variable declaration.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@@ -291,14 +308,6 @@ namespace elna::boot
 | 
				
			|||||||
    class literal_expression : public expression
 | 
					    class literal_expression : public expression
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        virtual literal<std::int32_t> *is_int() = 0;
 | 
					 | 
				
			||||||
        virtual literal<std::uint32_t> *is_word() = 0;
 | 
					 | 
				
			||||||
        virtual literal<double> *is_float() = 0;
 | 
					 | 
				
			||||||
        virtual literal<bool> *is_bool() = 0;
 | 
					 | 
				
			||||||
        virtual literal<unsigned char> *is_char() = 0;
 | 
					 | 
				
			||||||
        virtual literal<std::nullptr_t> *is_nil() = 0;
 | 
					 | 
				
			||||||
        virtual literal<std::string> *is_string() = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        literal_expression *is_literal() override;
 | 
					        literal_expression *is_literal() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected:
 | 
					    protected:
 | 
				
			||||||
@@ -635,90 +644,6 @@ namespace elna::boot
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        literal<std::int32_t> *is_int() override
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (std::is_same<T, std::int32_t>::value)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return reinterpret_cast<literal<std::int32_t> *>(this);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return nullptr;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        literal<std::uint32_t> *is_word() override
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (std::is_same<T, std::uint32_t>::value)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return reinterpret_cast<literal<std::uint32_t> *>(this);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return nullptr;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        literal<double> *is_float() override
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (std::is_same<T, double>::value)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return reinterpret_cast<literal<double> *>(this);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return nullptr;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        literal<bool> *is_bool() override
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (std::is_same<T, bool>::value)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return reinterpret_cast<literal<bool> *>(this);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return nullptr;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        literal<unsigned char> *is_char() override
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (std::is_same<T, unsigned char>::value)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return reinterpret_cast<literal<unsigned char> *>(this);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return nullptr;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        literal<std::nullptr_t> *is_nil() override
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (std::is_same<T, std::nullptr_t>::value)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return reinterpret_cast<literal<std::nullptr_t> *>(this);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return nullptr;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        literal<std::string> *is_string() override
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (std::is_same<T, std::string>::value)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return reinterpret_cast<literal<std::string> *>(this);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return nullptr;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        void accept(parser_visitor *visitor) override
 | 
					        void accept(parser_visitor *visitor) override
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            visitor->visit(this);
 | 
					            visitor->visit(this);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,6 +49,8 @@ namespace elna::boot
 | 
				
			|||||||
    class declaration_visitor final : public parser_visitor, public error_container
 | 
					    class declaration_visitor final : public parser_visitor, public error_container
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        type current_type;
 | 
					        type current_type;
 | 
				
			||||||
 | 
					        constant_info::variant current_literal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::shared_ptr<symbol_table> symbols;
 | 
					        std::shared_ptr<symbol_table> symbols;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        procedure_type build_procedure(procedure_type_expression& type_expression);
 | 
					        procedure_type build_procedure(procedure_type_expression& type_expression);
 | 
				
			||||||
@@ -58,7 +60,7 @@ namespace elna::boot
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        explicit declaration_visitor(const char *path, std::shared_ptr<symbol_table> symbols);
 | 
					        explicit declaration_visitor(const char *path, std::shared_ptr<symbol_table> symbols);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void visit(primitive_type_expression *type_expression) override;
 | 
					        void visit(named_type_expression *type_expression) override;
 | 
				
			||||||
        void visit(array_type_expression *type_expression) override;
 | 
					        void visit(array_type_expression *type_expression) override;
 | 
				
			||||||
        void visit(pointer_type_expression *type_expression) override;
 | 
					        void visit(pointer_type_expression *type_expression) override;
 | 
				
			||||||
        void visit(program *program) override;
 | 
					        void visit(program *program) override;
 | 
				
			||||||
@@ -66,9 +68,10 @@ namespace elna::boot
 | 
				
			|||||||
        void visit(record_type_expression *type_expression) override;
 | 
					        void visit(record_type_expression *type_expression) override;
 | 
				
			||||||
        void visit(union_type_expression *type_expression) override;
 | 
					        void visit(union_type_expression *type_expression) override;
 | 
				
			||||||
        void visit(procedure_type_expression *type_expression) override;
 | 
					        void visit(procedure_type_expression *type_expression) override;
 | 
				
			||||||
 | 
					        void visit(enumeration_type_expression *type_expression) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void visit(variable_declaration *declaration) override;
 | 
					        void visit(variable_declaration *declaration) override;
 | 
				
			||||||
        void visit(constant_definition *) override;
 | 
					        void visit(constant_definition *definition) override;
 | 
				
			||||||
        void visit(procedure_definition *definition) override;
 | 
					        void visit(procedure_definition *definition) override;
 | 
				
			||||||
        void visit(assign_statement *statement) override;
 | 
					        void visit(assign_statement *statement) override;
 | 
				
			||||||
        void visit(if_statement *statement) override;
 | 
					        void visit(if_statement *statement) override;
 | 
				
			||||||
@@ -85,12 +88,12 @@ namespace elna::boot
 | 
				
			|||||||
        void visit(array_access_expression *expression) override;
 | 
					        void visit(array_access_expression *expression) override;
 | 
				
			||||||
        void visit(field_access_expression *expression) override;
 | 
					        void visit(field_access_expression *expression) override;
 | 
				
			||||||
        void visit(dereference_expression *expression) override;
 | 
					        void visit(dereference_expression *expression) override;
 | 
				
			||||||
        void visit(literal<std::int32_t> *) override;
 | 
					        void visit(literal<std::int32_t> *literal) override;
 | 
				
			||||||
        void visit(literal<std::uint32_t> *) override;
 | 
					        void visit(literal<std::uint32_t> *literal) override;
 | 
				
			||||||
        void visit(literal<double> *) override;
 | 
					        void visit(literal<double> *literal) override;
 | 
				
			||||||
        void visit(literal<bool> *) override;
 | 
					        void visit(literal<bool> *literal) override;
 | 
				
			||||||
        void visit(literal<unsigned char> *) override;
 | 
					        void visit(literal<unsigned char> *literal) override;
 | 
				
			||||||
        void visit(literal<std::nullptr_t> *) override;
 | 
					        void visit(literal<std::nullptr_t> *literal) override;
 | 
				
			||||||
        void visit(literal<std::string> *) override;
 | 
					        void visit(literal<std::string> *literal) override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,6 +34,7 @@ namespace elna::boot
 | 
				
			|||||||
    class pointer_type;
 | 
					    class pointer_type;
 | 
				
			||||||
    class array_type;
 | 
					    class array_type;
 | 
				
			||||||
    class procedure_type;
 | 
					    class procedure_type;
 | 
				
			||||||
 | 
					    class enumeration_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class type
 | 
					    class type
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -46,7 +47,8 @@ namespace elna::boot
 | 
				
			|||||||
            _union,
 | 
					            _union,
 | 
				
			||||||
            pointer,
 | 
					            pointer,
 | 
				
			||||||
            array,
 | 
					            array,
 | 
				
			||||||
            procedure
 | 
					            procedure,
 | 
				
			||||||
 | 
					            enumeration
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        type_tag tag{ type_tag::empty };
 | 
					        type_tag tag{ type_tag::empty };
 | 
				
			||||||
        union
 | 
					        union
 | 
				
			||||||
@@ -58,6 +60,7 @@ namespace elna::boot
 | 
				
			|||||||
            std::shared_ptr<pointer_type> pointer;
 | 
					            std::shared_ptr<pointer_type> pointer;
 | 
				
			||||||
            std::shared_ptr<array_type> array;
 | 
					            std::shared_ptr<array_type> array;
 | 
				
			||||||
            std::shared_ptr<procedure_type> procedure;
 | 
					            std::shared_ptr<procedure_type> procedure;
 | 
				
			||||||
 | 
					            std::shared_ptr<enumeration_type> enumeration;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void copy(const type& other);
 | 
					        void copy(const type& other);
 | 
				
			||||||
@@ -72,6 +75,7 @@ namespace elna::boot
 | 
				
			|||||||
        explicit type(std::shared_ptr<pointer_type> pointer);
 | 
					        explicit type(std::shared_ptr<pointer_type> pointer);
 | 
				
			||||||
        explicit type(std::shared_ptr<array_type> array);
 | 
					        explicit type(std::shared_ptr<array_type> array);
 | 
				
			||||||
        explicit type(std::shared_ptr<procedure_type> procedure);
 | 
					        explicit type(std::shared_ptr<procedure_type> procedure);
 | 
				
			||||||
 | 
					        explicit type(std::shared_ptr<enumeration_type> enumeration);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        type(const type& other);
 | 
					        type(const type& other);
 | 
				
			||||||
        type& operator=(const type& other);
 | 
					        type& operator=(const type& other);
 | 
				
			||||||
@@ -141,8 +145,16 @@ namespace elna::boot
 | 
				
			|||||||
        procedure_type(return_t return_type = return_t());
 | 
					        procedure_type(return_t return_type = return_t());
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct enumeration_type
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<std::string> members;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        explicit enumeration_type(const std::vector<std::string>& members);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class type_info;
 | 
					    class type_info;
 | 
				
			||||||
    class procedure_info;
 | 
					    class procedure_info;
 | 
				
			||||||
 | 
					    class constant_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class info : public std::enable_shared_from_this<info>
 | 
					    class info : public std::enable_shared_from_this<info>
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -174,6 +186,17 @@ namespace elna::boot
 | 
				
			|||||||
        std::shared_ptr<procedure_info> is_procedure() override;
 | 
					        std::shared_ptr<procedure_info> is_procedure() override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class constant_info : public info
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        using variant = typename
 | 
				
			||||||
 | 
					            std::variant<std::int32_t, std::uint32_t, double, bool, unsigned char, std::nullptr_t, std::string>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const variant symbol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        explicit constant_info(const variant& symbol);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Symbol table.
 | 
					     * Symbol table.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -101,12 +101,13 @@ namespace elna::gcc
 | 
				
			|||||||
        void visit(boot::assign_statement *statement) override;
 | 
					        void visit(boot::assign_statement *statement) override;
 | 
				
			||||||
        void visit(boot::if_statement *statement) override;
 | 
					        void visit(boot::if_statement *statement) override;
 | 
				
			||||||
        void visit(boot::while_statement *statement) override;
 | 
					        void visit(boot::while_statement *statement) override;
 | 
				
			||||||
        void visit(boot::primitive_type_expression *type) override;
 | 
					        void visit(boot::named_type_expression *type) override;
 | 
				
			||||||
        void visit(boot::array_type_expression *type) override;
 | 
					        void visit(boot::array_type_expression *type) override;
 | 
				
			||||||
        void visit(boot::pointer_type_expression *type) override;
 | 
					        void visit(boot::pointer_type_expression *type) override;
 | 
				
			||||||
        void visit(boot::record_type_expression *type) override;
 | 
					        void visit(boot::record_type_expression *type) override;
 | 
				
			||||||
        void visit(boot::union_type_expression *type) override;
 | 
					        void visit(boot::union_type_expression *type) override;
 | 
				
			||||||
        void visit(boot::procedure_type_expression *type) override;
 | 
					        void visit(boot::procedure_type_expression *type) override;
 | 
				
			||||||
 | 
					        void visit(boot::enumeration_type_expression *type) override;
 | 
				
			||||||
        void visit(boot::return_statement *statement) override;
 | 
					        void visit(boot::return_statement *statement) override;
 | 
				
			||||||
        void visit(boot::defer_statement *statement) override;
 | 
					        void visit(boot::defer_statement *statement) override;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,7 +33,6 @@ namespace elna::gcc
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    using symbol_table = boot::symbol_map<tree, tree, NULL_TREE>;
 | 
					    using symbol_table = boot::symbol_map<tree, tree, NULL_TREE>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool is_pointer_type(tree type);
 | 
					 | 
				
			||||||
    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_primitive_type(tree type);
 | 
					    bool is_primitive_type(tree type);
 | 
				
			||||||
@@ -42,9 +41,9 @@ namespace elna::gcc
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * \param type The type to evaluate.
 | 
					     * \param type The type to evaluate.
 | 
				
			||||||
     * \return Whether the given type is record or union.
 | 
					     * \return Whether this type can be converted to another type.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    bool is_aggregate_type(tree type);
 | 
					    bool is_castable_type(tree type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * \param lhs Left hand value.
 | 
					     * \param lhs Left hand value.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										384
									
								
								source.elna
									
									
									
									
									
								
							
							
						
						
									
										384
									
								
								source.elna
									
									
									
									
									
								
							@@ -3,67 +3,69 @@ const
 | 
				
			|||||||
  SEEK_CUR* = 1;
 | 
					  SEEK_CUR* = 1;
 | 
				
			||||||
  SEEK_END* = 2;
 | 
					  SEEK_END* = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  TOKEN_IDENTIFIER* = 1;
 | 
					 | 
				
			||||||
  TOKEN_IF* = 2;
 | 
					 | 
				
			||||||
  TOKEN_THEN* = 3;
 | 
					 | 
				
			||||||
  TOKEN_ELSE* = 4;
 | 
					 | 
				
			||||||
  TOKEN_ELSIF* = 5;
 | 
					 | 
				
			||||||
  TOKEN_WHILE* = 6;
 | 
					 | 
				
			||||||
  TOKEN_DO* = 7;
 | 
					 | 
				
			||||||
  TOKEN_PROC* = 8;
 | 
					 | 
				
			||||||
  TOKEN_BEGIN* = 9;
 | 
					 | 
				
			||||||
  TOKEN_END* = 10;
 | 
					 | 
				
			||||||
  TOKEN_EXTERN* = 11;
 | 
					 | 
				
			||||||
  TOKEN_CONST* = 12;
 | 
					 | 
				
			||||||
  TOKEN_VAR* = 13;
 | 
					 | 
				
			||||||
  TOKEN_ARRAY* = 14;
 | 
					 | 
				
			||||||
  TOKEN_OF* = 15;
 | 
					 | 
				
			||||||
  TOKEN_TYPE* = 16;
 | 
					 | 
				
			||||||
  TOKEN_RECORD* = 17;
 | 
					 | 
				
			||||||
  TOKEN_UNION* = 18;
 | 
					 | 
				
			||||||
  TOKEN_POINTER* = 19;
 | 
					 | 
				
			||||||
  TOKEN_TO* = 20;
 | 
					 | 
				
			||||||
  TOKEN_BOOLEAN* = 21;
 | 
					 | 
				
			||||||
  TOKEN_NIL* = 22;
 | 
					 | 
				
			||||||
  TOKEN_AND* = 23;
 | 
					 | 
				
			||||||
  TOKEN_OR* = 24;
 | 
					 | 
				
			||||||
  TOKEN_NOT* = 25;
 | 
					 | 
				
			||||||
  TOKEN_RETURN* = 26;
 | 
					 | 
				
			||||||
  TOKEN_CAST* = 27;
 | 
					 | 
				
			||||||
  TOKEN_SHIFT_LEFT* = 28;
 | 
					 | 
				
			||||||
  TOKEN_SHIFT_RIGHT* = 29;
 | 
					 | 
				
			||||||
  TOKEN_LEFT_PAREN* = 30;
 | 
					 | 
				
			||||||
  TOKEN_RIGHT_PAREN* = 31;
 | 
					 | 
				
			||||||
  TOKEN_LEFT_SQUARE* = 32;
 | 
					 | 
				
			||||||
  TOKEN_RIGHT_SQUARE* = 33;
 | 
					 | 
				
			||||||
  TOKEN_GREATER_EQUAL* = 34;
 | 
					 | 
				
			||||||
  TOKEN_LESS_EQUAL* = 35;
 | 
					 | 
				
			||||||
  TOKEN_GREATER_THAN* = 36;
 | 
					 | 
				
			||||||
  TOKEN_LESS_THAN* = 37;
 | 
					 | 
				
			||||||
  TOKEN_NOT_EQUAL* = 38;
 | 
					 | 
				
			||||||
  TOKEN_EQUAL* = 39;
 | 
					 | 
				
			||||||
  TOKEN_SEMICOLON* = 40;
 | 
					 | 
				
			||||||
  TOKEN_DOT* = 41;
 | 
					 | 
				
			||||||
  TOKEN_COMMA* = 42;
 | 
					 | 
				
			||||||
  TOKEN_PLUS* = 43;
 | 
					 | 
				
			||||||
  TOKEN_MINUS* = 44;
 | 
					 | 
				
			||||||
  TOKEN_MULTIPLICATION* = 45;
 | 
					 | 
				
			||||||
  TOKEN_DIVISION* = 46;
 | 
					 | 
				
			||||||
  TOKEN_REMAINDER* = 47;
 | 
					 | 
				
			||||||
  TOKEN_ASSIGNMENT* = 48;
 | 
					 | 
				
			||||||
  TOKEN_COLON* = 49;
 | 
					 | 
				
			||||||
  TOKEN_HAT* = 50;
 | 
					 | 
				
			||||||
  TOKEN_AT* = 51;
 | 
					 | 
				
			||||||
  TOKEN_COMMENT* = 52;
 | 
					 | 
				
			||||||
  TOKEN_INTEGER* = 53;
 | 
					 | 
				
			||||||
  TOKEN_WORD* = 54;
 | 
					 | 
				
			||||||
  TOKEN_CHARACTER* = 55;
 | 
					 | 
				
			||||||
  TOKEN_STRING* = 56;
 | 
					 | 
				
			||||||
  TOKEN_DEFER* = 57;
 | 
					 | 
				
			||||||
  TOKEN_EXCLAMATION* = 58;
 | 
					 | 
				
			||||||
  TOKEN_ARROW = 59;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type
 | 
					type
 | 
				
			||||||
 | 
					  TokenKind* = (
 | 
				
			||||||
 | 
					    unknown,
 | 
				
			||||||
 | 
					    identifier,
 | 
				
			||||||
 | 
					    _if,
 | 
				
			||||||
 | 
					    _then,
 | 
				
			||||||
 | 
					    _else,
 | 
				
			||||||
 | 
					    _elsif,
 | 
				
			||||||
 | 
					    _while,
 | 
				
			||||||
 | 
					    _do,
 | 
				
			||||||
 | 
					    _proc,
 | 
				
			||||||
 | 
					    _begin,
 | 
				
			||||||
 | 
					    _end,
 | 
				
			||||||
 | 
					    _extern,
 | 
				
			||||||
 | 
					    _const,
 | 
				
			||||||
 | 
					    _var,
 | 
				
			||||||
 | 
					    array,
 | 
				
			||||||
 | 
					    of,
 | 
				
			||||||
 | 
					    _type,
 | 
				
			||||||
 | 
					    _record,
 | 
				
			||||||
 | 
					    _union,
 | 
				
			||||||
 | 
					    pointer,
 | 
				
			||||||
 | 
					    to,
 | 
				
			||||||
 | 
					    boolean,
 | 
				
			||||||
 | 
					    _nil,
 | 
				
			||||||
 | 
					    and,
 | 
				
			||||||
 | 
					    or,
 | 
				
			||||||
 | 
					    not,
 | 
				
			||||||
 | 
					    _return,
 | 
				
			||||||
 | 
					    _cast,
 | 
				
			||||||
 | 
					    shift_left,
 | 
				
			||||||
 | 
					    shift_right,
 | 
				
			||||||
 | 
					    left_paren,
 | 
				
			||||||
 | 
					    right_paren,
 | 
				
			||||||
 | 
					    left_square,
 | 
				
			||||||
 | 
					    right_square,
 | 
				
			||||||
 | 
					    greater_equal,
 | 
				
			||||||
 | 
					    less_equal,
 | 
				
			||||||
 | 
					    greater_than,
 | 
				
			||||||
 | 
					    less_than,
 | 
				
			||||||
 | 
					    not_equal,
 | 
				
			||||||
 | 
					    equal,
 | 
				
			||||||
 | 
					    semicolon,
 | 
				
			||||||
 | 
					    dot,
 | 
				
			||||||
 | 
					    comma,
 | 
				
			||||||
 | 
					    plus,
 | 
				
			||||||
 | 
					    minus,
 | 
				
			||||||
 | 
					    multiplication,
 | 
				
			||||||
 | 
					    division,
 | 
				
			||||||
 | 
					    remainder,
 | 
				
			||||||
 | 
					    assignment,
 | 
				
			||||||
 | 
					    colon,
 | 
				
			||||||
 | 
					    hat,
 | 
				
			||||||
 | 
					    at,
 | 
				
			||||||
 | 
					    comment,
 | 
				
			||||||
 | 
					    integer,
 | 
				
			||||||
 | 
					    word,
 | 
				
			||||||
 | 
					    character,
 | 
				
			||||||
 | 
					    string,
 | 
				
			||||||
 | 
					    _defer,
 | 
				
			||||||
 | 
					    exclamation,
 | 
				
			||||||
 | 
					    arrow
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
  Position* = record
 | 
					  Position* = record
 | 
				
			||||||
    line: Word;
 | 
					    line: Word;
 | 
				
			||||||
	column: Word
 | 
						column: Word
 | 
				
			||||||
@@ -93,7 +95,7 @@ type
 | 
				
			|||||||
	head: proc(^Byte) -> Char
 | 
						head: proc(^Byte) -> Char
 | 
				
			||||||
  end;
 | 
					  end;
 | 
				
			||||||
  Token* = record
 | 
					  Token* = record
 | 
				
			||||||
    kind: Int;
 | 
					    kind: TokenKind;
 | 
				
			||||||
    value: union
 | 
					    value: union
 | 
				
			||||||
      int_value: Int;
 | 
					      int_value: Int;
 | 
				
			||||||
      string: String;
 | 
					      string: String;
 | 
				
			||||||
@@ -516,137 +518,137 @@ begin
 | 
				
			|||||||
  while i < tokens_size do
 | 
					  while i < tokens_size do
 | 
				
			||||||
    current_token := tokens + i;
 | 
					    current_token := tokens + i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if current_token^.kind = TOKEN_IF then
 | 
					    if current_token^.kind = TokenKind._if then
 | 
				
			||||||
	  write_s("IF")
 | 
						  write_s("IF")
 | 
				
			||||||
    elsif current_token^.kind = TOKEN_THEN then
 | 
					    elsif current_token^.kind = TokenKind._then then
 | 
				
			||||||
	  write_s("THEN")
 | 
						  write_s("THEN")
 | 
				
			||||||
    elsif current_token^.kind = TOKEN_ELSE then
 | 
					    elsif current_token^.kind = TokenKind._else then
 | 
				
			||||||
	  write_s("ELSE")
 | 
						  write_s("ELSE")
 | 
				
			||||||
    elsif current_token^.kind = TOKEN_ELSIF then
 | 
					    elsif current_token^.kind = TokenKind._elsif then
 | 
				
			||||||
	  write_s("ELSIF")
 | 
						  write_s("ELSIF")
 | 
				
			||||||
    elsif current_token^.kind = TOKEN_WHILE then
 | 
					    elsif current_token^.kind = TokenKind._while then
 | 
				
			||||||
	  write_s("WHILE")
 | 
						  write_s("WHILE")
 | 
				
			||||||
    elsif current_token^.kind = TOKEN_DO then
 | 
					    elsif current_token^.kind = TokenKind._do then
 | 
				
			||||||
	  write_s("DO")
 | 
						  write_s("DO")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_PROC then
 | 
						elsif current_token^.kind = TokenKind._proc then
 | 
				
			||||||
	  write_s("PROC")
 | 
						  write_s("PROC")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_BEGIN then
 | 
						elsif current_token^.kind = TokenKind._begin then
 | 
				
			||||||
	  write_s("BEGIN")
 | 
						  write_s("BEGIN")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_END then
 | 
						elsif current_token^.kind = TokenKind._end then
 | 
				
			||||||
	  write_s("END")
 | 
						  write_s("END")
 | 
				
			||||||
   	elsif current_token^.kind = TOKEN_EXTERN then
 | 
					   	elsif current_token^.kind = TokenKind._extern then
 | 
				
			||||||
	  write_s("EXTERN")
 | 
						  write_s("EXTERN")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_CONST then
 | 
						elsif current_token^.kind = TokenKind._const then
 | 
				
			||||||
	  write_s("CONST")
 | 
						  write_s("CONST")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_VAR then
 | 
						elsif current_token^.kind = TokenKind._var then
 | 
				
			||||||
	  write_s("VAR")
 | 
						  write_s("VAR")
 | 
				
			||||||
   	elsif current_token^.kind = TOKEN_ARRAY then
 | 
					   	elsif current_token^.kind = TokenKind.array then
 | 
				
			||||||
	  write_s("ARRAY")
 | 
						  write_s("ARRAY")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_OF then
 | 
						elsif current_token^.kind = TokenKind.of then
 | 
				
			||||||
	  write_s("OF")
 | 
						  write_s("OF")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_TYPE then
 | 
						elsif current_token^.kind = TokenKind._type then
 | 
				
			||||||
	  write_s("TYPE")
 | 
						  write_s("TYPE")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_RECORD then
 | 
						elsif current_token^.kind = TokenKind._record then
 | 
				
			||||||
	  write_s("RECORD")
 | 
						  write_s("RECORD")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_UNION then
 | 
						elsif current_token^.kind = TokenKind._union then
 | 
				
			||||||
	  write_s("UNION")
 | 
						  write_s("UNION")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_POINTER then
 | 
						elsif current_token^.kind = TokenKind.pointer then
 | 
				
			||||||
	  write_s("POINTER")
 | 
						  write_s("POINTER")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_TO then
 | 
						elsif current_token^.kind = TokenKind.to then
 | 
				
			||||||
	  write_s("TO")
 | 
						  write_s("TO")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_BOOLEAN then
 | 
						elsif current_token^.kind = TokenKind.boolean then
 | 
				
			||||||
	  write_s("BOOLEAN<");
 | 
						  write_s("BOOLEAN<");
 | 
				
			||||||
	  write_b(current_token^.value.boolean_value);
 | 
						  write_b(current_token^.value.boolean_value);
 | 
				
			||||||
	  write_c('>')
 | 
						  write_c('>')
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_NIL then
 | 
						elsif current_token^.kind = TokenKind._nil then
 | 
				
			||||||
	  write_s("NIL")
 | 
						  write_s("NIL")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_AND then
 | 
						elsif current_token^.kind = TokenKind.and then
 | 
				
			||||||
	  write_s("AND")
 | 
						  write_s("AND")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_OR then
 | 
						elsif current_token^.kind = TokenKind.or then
 | 
				
			||||||
	  write_s("OR")
 | 
						  write_s("OR")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_NOT then
 | 
						elsif current_token^.kind = TokenKind.not then
 | 
				
			||||||
	  write_s("NOT")
 | 
						  write_s("NOT")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_RETURN then
 | 
						elsif current_token^.kind = TokenKind._return then
 | 
				
			||||||
	  write_s("RETURN")
 | 
						  write_s("RETURN")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_CAST then
 | 
						elsif current_token^.kind = TokenKind._cast then
 | 
				
			||||||
	  write_s("CAST")
 | 
						  write_s("CAST")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_SHIFT_LEFT then
 | 
						elsif current_token^.kind = TokenKind.shift_left then
 | 
				
			||||||
	  write_s("<<")
 | 
						  write_s("<<")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_SHIFT_RIGHT then
 | 
						elsif current_token^.kind = TokenKind.shift_right then
 | 
				
			||||||
	  write_s(">>")
 | 
						  write_s(">>")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_IDENTIFIER then
 | 
						elsif current_token^.kind = TokenKind.identifier then
 | 
				
			||||||
	  write_c('<');
 | 
						  write_c('<');
 | 
				
			||||||
      write_s(current_token^.value.string);
 | 
					      write_s(current_token^.value.string);
 | 
				
			||||||
	  write_c('>')
 | 
						  write_c('>')
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_LEFT_PAREN then
 | 
						elsif current_token^.kind = TokenKind.left_paren then
 | 
				
			||||||
	  write_s("(")
 | 
						  write_s("(")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_RIGHT_PAREN then
 | 
						elsif current_token^.kind = TokenKind.right_paren then
 | 
				
			||||||
	  write_s(")")
 | 
						  write_s(")")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_LEFT_SQUARE then
 | 
						elsif current_token^.kind = TokenKind.left_square then
 | 
				
			||||||
	  write_s("[")
 | 
						  write_s("[")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_RIGHT_SQUARE then
 | 
						elsif current_token^.kind = TokenKind.right_square then
 | 
				
			||||||
	  write_s("]")
 | 
						  write_s("]")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_GREATER_EQUAL then
 | 
						elsif current_token^.kind = TokenKind.greater_equal then
 | 
				
			||||||
	  write_s(">=")
 | 
						  write_s(">=")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_LESS_EQUAL then
 | 
						elsif current_token^.kind = TokenKind.less_equal then
 | 
				
			||||||
	  write_s("<=")
 | 
						  write_s("<=")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_GREATER_THAN then
 | 
						elsif current_token^.kind = TokenKind.greater_than then
 | 
				
			||||||
	  write_s(">")
 | 
						  write_s(">")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_LESS_THAN then
 | 
						elsif current_token^.kind = TokenKind.less_than then
 | 
				
			||||||
	  write_s("<")
 | 
						  write_s("<")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_EQUAL then
 | 
						elsif current_token^.kind = TokenKind.equal then
 | 
				
			||||||
	  write_s("=")
 | 
						  write_s("=")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_NOT_EQUAL then
 | 
						elsif current_token^.kind = TokenKind.not_equal then
 | 
				
			||||||
	  write_s("<>")
 | 
						  write_s("<>")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_SEMICOLON then
 | 
						elsif current_token^.kind = TokenKind.semicolon then
 | 
				
			||||||
	  write_c(';')
 | 
						  write_c(';')
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_DOT then
 | 
						elsif current_token^.kind = TokenKind.dot then
 | 
				
			||||||
	  write_c('.')
 | 
						  write_c('.')
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_COMMA then
 | 
						elsif current_token^.kind = TokenKind.comma then
 | 
				
			||||||
	  write_c(',')
 | 
						  write_c(',')
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_PLUS then
 | 
						elsif current_token^.kind = TokenKind.plus then
 | 
				
			||||||
	  write_c('+')
 | 
						  write_c('+')
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_MINUS then
 | 
						elsif current_token^.kind = TokenKind.minus then
 | 
				
			||||||
	  write_c('-')
 | 
						  write_c('-')
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_MULTIPLICATION then
 | 
						elsif current_token^.kind = TokenKind.multiplication then
 | 
				
			||||||
	  write_c('*')
 | 
						  write_c('*')
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_DIVISION then
 | 
						elsif current_token^.kind = TokenKind.division then
 | 
				
			||||||
	  write_c('/')
 | 
						  write_c('/')
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_REMAINDER then
 | 
						elsif current_token^.kind = TokenKind.remainder then
 | 
				
			||||||
	  write_c('%')
 | 
						  write_c('%')
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_ASSIGNMENT then
 | 
						elsif current_token^.kind = TokenKind.assignment then
 | 
				
			||||||
	  write_s(":=")
 | 
						  write_s(":=")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_COLON then
 | 
						elsif current_token^.kind = TokenKind.colon then
 | 
				
			||||||
	  write_c(':')
 | 
						  write_c(':')
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_HAT then
 | 
						elsif current_token^.kind = TokenKind.hat then
 | 
				
			||||||
	  write_c('^')
 | 
						  write_c('^')
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_AT then
 | 
						elsif current_token^.kind = TokenKind.at then
 | 
				
			||||||
	  write_c('@')
 | 
						  write_c('@')
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_COMMENT then
 | 
						elsif current_token^.kind = TokenKind.comment then
 | 
				
			||||||
	  write_s("(* COMMENT *)")
 | 
						  write_s("(* COMMENT *)")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_INTEGER then
 | 
						elsif current_token^.kind = TokenKind.integer then
 | 
				
			||||||
	  write_c('<');
 | 
						  write_c('<');
 | 
				
			||||||
      write_i(current_token^.value.int_value);
 | 
					      write_i(current_token^.value.int_value);
 | 
				
			||||||
	  write_c('>')
 | 
						  write_c('>')
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_WORD then
 | 
						elsif current_token^.kind = TokenKind.word then
 | 
				
			||||||
	  write_c('<');
 | 
						  write_c('<');
 | 
				
			||||||
      write_i(current_token^.value.int_value);
 | 
					      write_i(current_token^.value.int_value);
 | 
				
			||||||
	  write_s("u>")
 | 
						  write_s("u>")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_CHARACTER then
 | 
						elsif current_token^.kind = TokenKind.character then
 | 
				
			||||||
	  write_c('<');
 | 
						  write_c('<');
 | 
				
			||||||
      write_i(cast(current_token^.value.char_value: Int));
 | 
					      write_i(cast(current_token^.value.char_value: Int));
 | 
				
			||||||
	  write_s("c>")
 | 
						  write_s("c>")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_STRING then
 | 
						elsif current_token^.kind = TokenKind.string then
 | 
				
			||||||
	  write_s("\"...\"")
 | 
						  write_s("\"...\"")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_DEFER then
 | 
						elsif current_token^.kind = TokenKind._defer then
 | 
				
			||||||
	  write_s("DEFER")
 | 
						  write_s("DEFER")
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_EXCLAMATION then
 | 
						elsif current_token^.kind = TokenKind.exclamation then
 | 
				
			||||||
	  write_c('!')
 | 
						  write_c('!')
 | 
				
			||||||
	elsif current_token^.kind = TOKEN_ARROW then
 | 
						elsif current_token^.kind = TokenKind.arrow then
 | 
				
			||||||
	  write_s("->")
 | 
						  write_s("->")
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	  write_s("UNKNOWN<");
 | 
						  write_s("UNKNOWN<");
 | 
				
			||||||
	  write_i(current_token^.kind);
 | 
						  write_i(cast(current_token^.kind: Int));
 | 
				
			||||||
	  write_c('>')
 | 
						  write_c('>')
 | 
				
			||||||
	end;
 | 
						end;
 | 
				
			||||||
	write_c(' ');
 | 
						write_c(' ');
 | 
				
			||||||
@@ -661,65 +663,65 @@ var
 | 
				
			|||||||
  current_token: Token;
 | 
					  current_token: Token;
 | 
				
			||||||
begin
 | 
					begin
 | 
				
			||||||
  if "if" = token_content then
 | 
					  if "if" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_IF
 | 
						current_token.kind := TokenKind._if
 | 
				
			||||||
  elsif "then" = token_content then
 | 
					  elsif "then" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_THEN
 | 
						current_token.kind := TokenKind._then
 | 
				
			||||||
  elsif "else" = token_content then
 | 
					  elsif "else" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_ELSE
 | 
						current_token.kind := TokenKind._else
 | 
				
			||||||
  elsif "elsif" = token_content then
 | 
					  elsif "elsif" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_ELSIF
 | 
						current_token.kind := TokenKind._elsif
 | 
				
			||||||
  elsif "while" = token_content then
 | 
					  elsif "while" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_WHILE
 | 
						current_token.kind := TokenKind._while
 | 
				
			||||||
  elsif "do" = token_content then
 | 
					  elsif "do" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_DO
 | 
						current_token.kind := TokenKind._do
 | 
				
			||||||
  elsif "proc" = token_content then
 | 
					  elsif "proc" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_PROC
 | 
						current_token.kind := TokenKind._proc
 | 
				
			||||||
  elsif "begin" = token_content then
 | 
					  elsif "begin" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_BEGIN
 | 
						current_token.kind := TokenKind._begin
 | 
				
			||||||
  elsif "end" = token_content then
 | 
					  elsif "end" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_END
 | 
						current_token.kind := TokenKind._end
 | 
				
			||||||
  elsif "extern" = token_content then
 | 
					  elsif "extern" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_EXTERN
 | 
						current_token.kind := TokenKind._extern
 | 
				
			||||||
  elsif "const" = token_content then
 | 
					  elsif "const" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_CONST
 | 
						current_token.kind := TokenKind._const
 | 
				
			||||||
  elsif "var" = token_content then
 | 
					  elsif "var" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_VAR
 | 
						current_token.kind := TokenKind._var
 | 
				
			||||||
  elsif "array" = token_content then
 | 
					  elsif "array" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_ARRAY
 | 
						current_token.kind := TokenKind.array
 | 
				
			||||||
  elsif "of" = token_content then
 | 
					  elsif "of" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_OF
 | 
						current_token.kind := TokenKind.of
 | 
				
			||||||
  elsif "type" = token_content then
 | 
					  elsif "type" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_TYPE
 | 
						current_token.kind := TokenKind._type
 | 
				
			||||||
  elsif "record" = token_content then
 | 
					  elsif "record" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_RECORD
 | 
						current_token.kind := TokenKind._record
 | 
				
			||||||
  elsif "union" = token_content then
 | 
					  elsif "union" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_UNION
 | 
						current_token.kind := TokenKind._union
 | 
				
			||||||
  elsif "pointer" = token_content then
 | 
					  elsif "pointer" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_POINTER
 | 
						current_token.kind := TokenKind.pointer
 | 
				
			||||||
  elsif "to" = token_content then
 | 
					  elsif "to" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_TO
 | 
						current_token.kind := TokenKind.to
 | 
				
			||||||
  elsif "true" = token_content then
 | 
					  elsif "true" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_BOOLEAN;
 | 
						current_token.kind := TokenKind.boolean;
 | 
				
			||||||
	current_token.value.boolean_value := true
 | 
						current_token.value.boolean_value := true
 | 
				
			||||||
  elsif "false" = token_content then
 | 
					  elsif "false" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_BOOLEAN;
 | 
						current_token.kind := TokenKind.boolean;
 | 
				
			||||||
	current_token.value.boolean_value := false
 | 
						current_token.value.boolean_value := false
 | 
				
			||||||
  elsif "nil" = token_content then
 | 
					  elsif "nil" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_NIL
 | 
						current_token.kind := TokenKind._nil
 | 
				
			||||||
  elsif "and" = token_content then
 | 
					  elsif "and" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_AND
 | 
						current_token.kind := TokenKind.and
 | 
				
			||||||
  elsif "or" = token_content then
 | 
					  elsif "or" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_OR
 | 
						current_token.kind := TokenKind.or
 | 
				
			||||||
  elsif "not" = token_content then
 | 
					  elsif "not" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_NOT
 | 
						current_token.kind := TokenKind.not
 | 
				
			||||||
  elsif "return" = token_content then
 | 
					  elsif "return" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_RETURN
 | 
						current_token.kind := TokenKind._return
 | 
				
			||||||
  elsif "cast" = token_content then
 | 
					  elsif "cast" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_CAST
 | 
						current_token.kind := TokenKind._cast
 | 
				
			||||||
  elsif "defer" = token_content then
 | 
					  elsif "defer" = token_content then
 | 
				
			||||||
	current_token.kind := TOKEN_DEFER
 | 
						current_token.kind := TokenKind._defer
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
	current_token.kind := TOKEN_IDENTIFIER;
 | 
						current_token.kind := TokenKind.identifier;
 | 
				
			||||||
	current_token.value.string := string_dup(token_content)
 | 
						current_token.value.string := string_dup(token_content)
 | 
				
			||||||
  end;
 | 
					  end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -750,147 +752,147 @@ begin
 | 
				
			|||||||
	  lex_number(@source_code, @current_token^.value.int_value);
 | 
						  lex_number(@source_code, @current_token^.value.int_value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  if source_code_expect(@source_code, 'u') then
 | 
						  if source_code_expect(@source_code, 'u') then
 | 
				
			||||||
	    current_token^.kind := TOKEN_WORD;
 | 
						    current_token^.kind := TokenKind.word;
 | 
				
			||||||
        source_code_advance(@source_code)
 | 
					        source_code_advance(@source_code)
 | 
				
			||||||
	  else
 | 
						  else
 | 
				
			||||||
	    current_token^.kind := TOKEN_INTEGER
 | 
						    current_token^.kind := TokenKind.integer
 | 
				
			||||||
	  end
 | 
						  end
 | 
				
			||||||
	elsif first_char = '(' then
 | 
						elsif first_char = '(' then
 | 
				
			||||||
	  source_code_advance(@source_code);
 | 
						  source_code_advance(@source_code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  if source_code_empty(@source_code) then
 | 
						  if source_code_empty(@source_code) then
 | 
				
			||||||
	    current_token^.kind := TOKEN_LEFT_PAREN
 | 
						    current_token^.kind := TokenKind.left_paren
 | 
				
			||||||
	  elsif source_code_head(source_code) = '*' then
 | 
						  elsif source_code_head(source_code) = '*' then
 | 
				
			||||||
	    source_code_advance(@source_code);
 | 
						    source_code_advance(@source_code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if lex_comment(@source_code, @token_buffer) then
 | 
							if lex_comment(@source_code, @token_buffer) then
 | 
				
			||||||
	      current_token^.value.string := string_dup(string_buffer_clear(@token_buffer));
 | 
						      current_token^.value.string := string_dup(string_buffer_clear(@token_buffer));
 | 
				
			||||||
		  current_token^.kind := TOKEN_COMMENT
 | 
							  current_token^.kind := TokenKind.comment
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
	      current_token^.kind := 0
 | 
						      current_token^.kind := TokenKind.unknown
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
	  else
 | 
						  else
 | 
				
			||||||
	    current_token^.kind := TOKEN_LEFT_PAREN
 | 
						    current_token^.kind := TokenKind.left_paren
 | 
				
			||||||
	  end
 | 
						  end
 | 
				
			||||||
	elsif first_char = ')' then
 | 
						elsif first_char = ')' then
 | 
				
			||||||
	  current_token^.kind := TOKEN_RIGHT_PAREN;
 | 
						  current_token^.kind := TokenKind.right_paren;
 | 
				
			||||||
	  source_code_advance(@source_code)
 | 
						  source_code_advance(@source_code)
 | 
				
			||||||
	elsif first_char = '\'' then
 | 
						elsif first_char = '\'' then
 | 
				
			||||||
      source_code_advance(@source_code);
 | 
					      source_code_advance(@source_code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  if lex_character(@source_code, @current_token^.value.char_value) & source_code_expect(@source_code, '\'') then
 | 
						  if lex_character(@source_code, @current_token^.value.char_value) & source_code_expect(@source_code, '\'') then
 | 
				
			||||||
	  	current_token^.kind := TOKEN_CHARACTER;
 | 
						  	current_token^.kind := TokenKind.character;
 | 
				
			||||||
	    source_code_advance(@source_code)
 | 
						    source_code_advance(@source_code)
 | 
				
			||||||
	  else
 | 
						  else
 | 
				
			||||||
	    current_token^.kind := 0
 | 
						    current_token^.kind := TokenKind.unknown
 | 
				
			||||||
	  end
 | 
						  end
 | 
				
			||||||
	elsif first_char = '"' then
 | 
						elsif first_char = '"' then
 | 
				
			||||||
      source_code_advance(@source_code);
 | 
					      source_code_advance(@source_code);
 | 
				
			||||||
	  
 | 
						  
 | 
				
			||||||
      if lex_string(@source_code, @token_buffer) then
 | 
					      if lex_string(@source_code, @token_buffer) then
 | 
				
			||||||
		current_token^.kind := TOKEN_STRING;
 | 
							current_token^.kind := TokenKind.string;
 | 
				
			||||||
		current_token^.value.string := string_dup(string_buffer_clear(@token_buffer))
 | 
							current_token^.value.string := string_dup(string_buffer_clear(@token_buffer))
 | 
				
			||||||
	  else
 | 
						  else
 | 
				
			||||||
	    current_token^.kind := 0
 | 
						    current_token^.kind := TokenKind.unknown
 | 
				
			||||||
	  end
 | 
						  end
 | 
				
			||||||
	elsif first_char = '[' then
 | 
						elsif first_char = '[' then
 | 
				
			||||||
	  current_token^.kind := TOKEN_LEFT_SQUARE;
 | 
						  current_token^.kind := TokenKind.left_square;
 | 
				
			||||||
	  source_code_advance(@source_code)
 | 
						  source_code_advance(@source_code)
 | 
				
			||||||
	elsif first_char = ']' then
 | 
						elsif first_char = ']' then
 | 
				
			||||||
	  current_token^.kind := TOKEN_RIGHT_SQUARE;
 | 
						  current_token^.kind := TokenKind.right_square;
 | 
				
			||||||
	  source_code_advance(@source_code)
 | 
						  source_code_advance(@source_code)
 | 
				
			||||||
	elsif first_char = '>' then
 | 
						elsif first_char = '>' then
 | 
				
			||||||
	  source_code_advance(@source_code);
 | 
						  source_code_advance(@source_code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if source_code_empty(@source_code) then
 | 
					      if source_code_empty(@source_code) then
 | 
				
			||||||
	    current_token^.kind := TOKEN_GREATER_THAN
 | 
						    current_token^.kind := TokenKind.greater_than
 | 
				
			||||||
	  elsif source_code_head(source_code) = '=' then
 | 
						  elsif source_code_head(source_code) = '=' then
 | 
				
			||||||
	    current_token^.kind := TOKEN_GREATER_EQUAL;
 | 
						    current_token^.kind := TokenKind.greater_equal;
 | 
				
			||||||
	    source_code_advance(@source_code)
 | 
						    source_code_advance(@source_code)
 | 
				
			||||||
	  elsif source_code_head(source_code) = '>' then
 | 
						  elsif source_code_head(source_code) = '>' then
 | 
				
			||||||
	    current_token^.kind := TOKEN_SHIFT_RIGHT;
 | 
						    current_token^.kind := TokenKind.shift_right;
 | 
				
			||||||
	    source_code_advance(@source_code)
 | 
						    source_code_advance(@source_code)
 | 
				
			||||||
	  else
 | 
						  else
 | 
				
			||||||
	    current_token^.kind := TOKEN_GREATER_THAN
 | 
						    current_token^.kind := TokenKind.greater_than
 | 
				
			||||||
	  end
 | 
						  end
 | 
				
			||||||
	elsif first_char = '<' then
 | 
						elsif first_char = '<' then
 | 
				
			||||||
	  source_code_advance(@source_code);
 | 
						  source_code_advance(@source_code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  if source_code_empty(@source_code) then
 | 
						  if source_code_empty(@source_code) then
 | 
				
			||||||
	    current_token^.kind := TOKEN_LESS_THAN
 | 
						    current_token^.kind := TokenKind.less_than
 | 
				
			||||||
	  elsif source_code_head(source_code) = '=' then
 | 
						  elsif source_code_head(source_code) = '=' then
 | 
				
			||||||
	    current_token^.kind := TOKEN_LESS_EQUAL;
 | 
						    current_token^.kind := TokenKind.less_equal;
 | 
				
			||||||
	    source_code_advance(@source_code)
 | 
						    source_code_advance(@source_code)
 | 
				
			||||||
	  elsif source_code_head(source_code) = '<' then
 | 
						  elsif source_code_head(source_code) = '<' then
 | 
				
			||||||
	    current_token^.kind := TOKEN_SHIFT_LEFT;
 | 
						    current_token^.kind := TokenKind.shift_left;
 | 
				
			||||||
	    source_code_advance(@source_code)
 | 
						    source_code_advance(@source_code)
 | 
				
			||||||
	  elsif source_code_head(source_code) = '>' then
 | 
						  elsif source_code_head(source_code) = '>' then
 | 
				
			||||||
	    current_token^.kind := TOKEN_NOT_EQUAL;
 | 
						    current_token^.kind := TokenKind.not_equal;
 | 
				
			||||||
	    source_code_advance(@source_code)
 | 
						    source_code_advance(@source_code)
 | 
				
			||||||
	  else
 | 
						  else
 | 
				
			||||||
	    current_token^.kind := TOKEN_LESS_THAN
 | 
						    current_token^.kind := TokenKind.less_than
 | 
				
			||||||
	  end
 | 
						  end
 | 
				
			||||||
	elsif first_char = '=' then
 | 
						elsif first_char = '=' then
 | 
				
			||||||
	  current_token^.kind := TOKEN_EQUAL;
 | 
						  current_token^.kind := TokenKind.equal;
 | 
				
			||||||
	  source_code_advance(@source_code)
 | 
						  source_code_advance(@source_code)
 | 
				
			||||||
	elsif first_char = ';' then
 | 
						elsif first_char = ';' then
 | 
				
			||||||
	  current_token^.kind := TOKEN_SEMICOLON;
 | 
						  current_token^.kind := TokenKind.semicolon;
 | 
				
			||||||
	  source_code_advance(@source_code)
 | 
						  source_code_advance(@source_code)
 | 
				
			||||||
	elsif first_char = '.' then
 | 
						elsif first_char = '.' then
 | 
				
			||||||
	  current_token^.kind := TOKEN_DOT;
 | 
						  current_token^.kind := TokenKind.dot;
 | 
				
			||||||
	  source_code_advance(@source_code)
 | 
						  source_code_advance(@source_code)
 | 
				
			||||||
	elsif first_char = ',' then
 | 
						elsif first_char = ',' then
 | 
				
			||||||
	  current_token^.kind := TOKEN_COMMA;
 | 
						  current_token^.kind := TokenKind.comma;
 | 
				
			||||||
	  source_code_advance(@source_code)
 | 
						  source_code_advance(@source_code)
 | 
				
			||||||
	elsif first_char = '+' then
 | 
						elsif first_char = '+' then
 | 
				
			||||||
	  current_token^.kind := TOKEN_PLUS;
 | 
						  current_token^.kind := TokenKind.plus;
 | 
				
			||||||
	  source_code_advance(@source_code)
 | 
						  source_code_advance(@source_code)
 | 
				
			||||||
	elsif first_char = '-' then
 | 
						elsif first_char = '-' then
 | 
				
			||||||
	  source_code_advance(@source_code);
 | 
						  source_code_advance(@source_code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if source_code_empty(@source_code) then
 | 
					      if source_code_empty(@source_code) then
 | 
				
			||||||
	    current_token^.kind := TOKEN_MINUS
 | 
						    current_token^.kind := TokenKind.minus
 | 
				
			||||||
	  elsif source_code_head(source_code) = '>' then
 | 
						  elsif source_code_head(source_code) = '>' then
 | 
				
			||||||
	    current_token^.kind := TOKEN_ARROW;
 | 
						    current_token^.kind := TokenKind.arrow;
 | 
				
			||||||
	    source_code_advance(@source_code)
 | 
						    source_code_advance(@source_code)
 | 
				
			||||||
	  else
 | 
						  else
 | 
				
			||||||
	    current_token^.kind := TOKEN_MINUS
 | 
						    current_token^.kind := TokenKind.minus
 | 
				
			||||||
	  end
 | 
						  end
 | 
				
			||||||
	elsif first_char = '*' then
 | 
						elsif first_char = '*' then
 | 
				
			||||||
	  current_token^.kind := TOKEN_MULTIPLICATION;
 | 
						  current_token^.kind := TokenKind.multiplication;
 | 
				
			||||||
	  source_code_advance(@source_code)
 | 
						  source_code_advance(@source_code)
 | 
				
			||||||
	elsif first_char = '/' then
 | 
						elsif first_char = '/' then
 | 
				
			||||||
	  current_token^.kind := TOKEN_DIVISION;
 | 
						  current_token^.kind := TokenKind.division;
 | 
				
			||||||
	  source_code_advance(@source_code)
 | 
						  source_code_advance(@source_code)
 | 
				
			||||||
	elsif first_char = '%' then
 | 
						elsif first_char = '%' then
 | 
				
			||||||
	  current_token^.kind := TOKEN_REMAINDER;
 | 
						  current_token^.kind := TokenKind.remainder;
 | 
				
			||||||
	  source_code_advance(@source_code)
 | 
						  source_code_advance(@source_code)
 | 
				
			||||||
	elsif first_char = ':' then
 | 
						elsif first_char = ':' then
 | 
				
			||||||
	  source_code_advance(@source_code);
 | 
						  source_code_advance(@source_code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  if source_code_empty(@source_code) then
 | 
						  if source_code_empty(@source_code) then
 | 
				
			||||||
	    current_token^.kind := TOKEN_COLON
 | 
						    current_token^.kind := TokenKind.colon
 | 
				
			||||||
	  elsif source_code_head(source_code) = '=' then
 | 
						  elsif source_code_head(source_code) = '=' then
 | 
				
			||||||
	    current_token^.kind := TOKEN_ASSIGNMENT;
 | 
						    current_token^.kind := TokenKind.assignment;
 | 
				
			||||||
	    source_code_advance(@source_code)
 | 
						    source_code_advance(@source_code)
 | 
				
			||||||
	  else
 | 
						  else
 | 
				
			||||||
	    current_token^.kind := TOKEN_COLON
 | 
						    current_token^.kind := TokenKind.colon
 | 
				
			||||||
	  end
 | 
						  end
 | 
				
			||||||
	elsif first_char = '^' then
 | 
						elsif first_char = '^' then
 | 
				
			||||||
	  current_token^.kind := TOKEN_HAT;
 | 
						  current_token^.kind := TokenKind.hat;
 | 
				
			||||||
	  source_code_advance(@source_code)
 | 
						  source_code_advance(@source_code)
 | 
				
			||||||
	elsif first_char = '@' then
 | 
						elsif first_char = '@' then
 | 
				
			||||||
	  current_token^.kind := TOKEN_AT;
 | 
						  current_token^.kind := TokenKind.at;
 | 
				
			||||||
	  source_code_advance(@source_code)
 | 
						  source_code_advance(@source_code)
 | 
				
			||||||
	elsif first_char = '!' then
 | 
						elsif first_char = '!' then
 | 
				
			||||||
	  current_token^.kind := TOKEN_EXCLAMATION;
 | 
						  current_token^.kind := TokenKind.exclamation;
 | 
				
			||||||
	  source_code_advance(@source_code)
 | 
						  source_code_advance(@source_code)
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	  current_token^.kind := 0;
 | 
						  current_token^.kind := TokenKind.unknown;
 | 
				
			||||||
	  source_code_advance(@source_code)
 | 
						  source_code_advance(@source_code)
 | 
				
			||||||
	end;
 | 
						end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if current_token^.kind <> 0 then
 | 
						if current_token^.kind <> TokenKind.unknown then
 | 
				
			||||||
      tokens_size^ := tokens_size^ + 1u;
 | 
					      tokens_size^ := tokens_size^ + 1u;
 | 
				
			||||||
      skip_spaces(@source_code)
 | 
					      skip_spaces(@source_code)
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user