Allow extern variables
This commit is contained in:
		
							
								
								
									
										12
									
								
								boot/ast.cc
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								boot/ast.cc
									
									
									
									
									
								
							@@ -415,11 +415,23 @@ namespace elna::boot
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    variable_declaration::variable_declaration(const struct position position,
 | 
			
		||||
            std::vector<identifier_definition>&& identifier, std::shared_ptr<type_expression> variable_type,
 | 
			
		||||
            std::monostate)
 | 
			
		||||
        : node(position), m_variable_type(variable_type), identifiers(std::move(identifier)), is_extern(true)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void variable_declaration::accept(parser_visitor *visitor)
 | 
			
		||||
    {
 | 
			
		||||
        visitor->visit(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool variable_declaration::has_initializer() const
 | 
			
		||||
    {
 | 
			
		||||
        return this->is_extern || this->body != nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    type_expression& variable_declaration::variable_type()
 | 
			
		||||
    {
 | 
			
		||||
        return *m_variable_type;
 | 
			
		||||
 
 | 
			
		||||
@@ -508,6 +508,12 @@ variable_declaration:
 | 
			
		||||
            std::shared_ptr<boot::type_expression> shared_type{ $3 };
 | 
			
		||||
            $$ = new boot::variable_declaration( boot::make_position(@2), std::move($1), shared_type);
 | 
			
		||||
        }
 | 
			
		||||
    | identifier_definitions ":" type_expression ":=" "extern" ";"
 | 
			
		||||
        {
 | 
			
		||||
            std::shared_ptr<boot::type_expression> shared_type{ $3 };
 | 
			
		||||
            $$ = new boot::variable_declaration( boot::make_position(@2), std::move($1), shared_type,
 | 
			
		||||
                std::monostate{});
 | 
			
		||||
        }
 | 
			
		||||
    | identifier_definitions ":" type_expression ":=" expression ";"
 | 
			
		||||
        {
 | 
			
		||||
            std::shared_ptr<boot::type_expression> shared_type{ $3 };
 | 
			
		||||
@@ -550,7 +556,7 @@ import_declarations:
 | 
			
		||||
            std::swap($$, $3);
 | 
			
		||||
            $$.emplace($$.cbegin(), new boot::import_declaration(boot::make_position(@1), std::move($1)));
 | 
			
		||||
        }
 | 
			
		||||
	| import_declaration
 | 
			
		||||
    | import_declaration
 | 
			
		||||
        {
 | 
			
		||||
            $$.emplace_back(new boot::import_declaration(boot::make_position(@1), std::move($1)));
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -609,7 +609,7 @@ namespace elna::boot
 | 
			
		||||
 | 
			
		||||
    void declaration_visitor::visit(variable_declaration *declaration)
 | 
			
		||||
    {
 | 
			
		||||
        if (declaration->body != nullptr && declaration->identifiers.size() > 1)
 | 
			
		||||
        if (declaration->has_initializer() && declaration->identifiers.size() > 1)
 | 
			
		||||
        {
 | 
			
		||||
            add_error<variable_initializer_error>(this->input_file, declaration->position());
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -108,7 +108,7 @@ namespace elna::gcc
 | 
			
		||||
            if (!is_assignable_from(unqualified_field, this->current_expression))
 | 
			
		||||
            {
 | 
			
		||||
                error_at(argument_location,
 | 
			
		||||
                        "cannot assign value of type '%s' to variable of type '%s'",
 | 
			
		||||
                        "Cannot assign value of type '%s' to variable of type '%s'",
 | 
			
		||||
                        print_type(TREE_TYPE(this->current_expression)).c_str(),
 | 
			
		||||
                        print_type(TREE_TYPE(record_fields)).c_str());
 | 
			
		||||
                this->current_expression = error_mark_node;
 | 
			
		||||
@@ -756,6 +756,7 @@ namespace elna::gcc
 | 
			
		||||
                    get_identifier(variable_identifier.identifier.c_str()), this->current_expression);
 | 
			
		||||
            bool result = this->symbols->enter(variable_identifier.identifier, declaration_tree);
 | 
			
		||||
 | 
			
		||||
            // Set initializer if given.
 | 
			
		||||
            if (declaration->body != nullptr)
 | 
			
		||||
            {
 | 
			
		||||
                declaration->body->accept(this);
 | 
			
		||||
@@ -774,6 +775,7 @@ namespace elna::gcc
 | 
			
		||||
            {
 | 
			
		||||
                DECL_INITIAL(declaration_tree) = elna_pointer_nil_node;
 | 
			
		||||
            }
 | 
			
		||||
            DECL_EXTERNAL(declaration_tree) = declaration->is_extern;
 | 
			
		||||
            TREE_PUBLIC(declaration_tree) = variable_identifier.exported;
 | 
			
		||||
            this->current_expression = NULL_TREE;
 | 
			
		||||
            if (!result)
 | 
			
		||||
 
 | 
			
		||||
@@ -348,12 +348,18 @@ namespace elna::boot
 | 
			
		||||
        variable_declaration(const struct position position,
 | 
			
		||||
                std::vector<identifier_definition>&& identifier, std::shared_ptr<type_expression> variable_type,
 | 
			
		||||
                expression *body = nullptr);
 | 
			
		||||
        variable_declaration(const struct position position,
 | 
			
		||||
                std::vector<identifier_definition>&& identifier, std::shared_ptr<type_expression> variable_type,
 | 
			
		||||
                std::monostate);
 | 
			
		||||
 | 
			
		||||
        void accept(parser_visitor *visitor) override;
 | 
			
		||||
 | 
			
		||||
        bool has_initializer() const;
 | 
			
		||||
 | 
			
		||||
        const std::vector<identifier_definition> identifiers;
 | 
			
		||||
        type_expression& variable_type();
 | 
			
		||||
        expression *const body;
 | 
			
		||||
        expression *const body{ nullptr };
 | 
			
		||||
        const bool is_extern{ false };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@ proc write*(fd: Int, buf: Pointer, Word: Int) -> Int; extern;
 | 
			
		||||
 | 
			
		||||
proc write_s*(value: String);
 | 
			
		||||
begin
 | 
			
		||||
  (* fwrite(cast(value.ptr: Pointer), value.length, 1u, stdout) *)
 | 
			
		||||
  write(1, cast(value.ptr: Pointer), cast(value.length: Int))
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,14 +6,20 @@ module;
 | 
			
		||||
type
 | 
			
		||||
  FILE* = record end;
 | 
			
		||||
 | 
			
		||||
proc fopen(pathname: ^Char, mode: ^Char) -> ^FILE; extern;
 | 
			
		||||
proc fclose(stream: ^FILE) -> Int; extern;
 | 
			
		||||
proc fseek(stream: ^FILE, off: Int, whence: Int) -> Int; extern;
 | 
			
		||||
proc rewind(stream: ^FILE); extern;
 | 
			
		||||
proc ftell(stream: ^FILE) -> Int; extern;
 | 
			
		||||
proc fflush(stream: ^FILE) -> Int; extern;
 | 
			
		||||
var
 | 
			
		||||
  stdin*: ^FILE := extern;
 | 
			
		||||
  stdout*: ^FILE := extern;
 | 
			
		||||
  stderr*: ^FILE := extern;
 | 
			
		||||
 | 
			
		||||
proc fread(ptr: Pointer, size: Word, nmemb: Word, stream: ^FILE) -> Word; extern;
 | 
			
		||||
proc fopen*(pathname: ^Char, mode: ^Char) -> ^FILE; extern;
 | 
			
		||||
proc fclose*(stream: ^FILE) -> Int; extern;
 | 
			
		||||
proc fseek*(stream: ^FILE, off: Int, whence: Int) -> Int; extern;
 | 
			
		||||
proc rewind*(stream: ^FILE); extern;
 | 
			
		||||
proc ftell*(stream: ^FILE) -> Int; extern;
 | 
			
		||||
proc fflush*(stream: ^FILE) -> Int; extern;
 | 
			
		||||
 | 
			
		||||
proc fread*(ptr: Pointer, size: Word, nmemb: Word, stream: ^FILE) -> Word; extern;
 | 
			
		||||
proc fwrite*(ptr: Pointer, size: Word, nitems: Word, stream: ^FILE) -> Word; extern;
 | 
			
		||||
 | 
			
		||||
proc perror(s: ^Char); extern;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -624,7 +624,7 @@ end;
 | 
			
		||||
proc parse(tokens: ^Token, tokens_size: Word);
 | 
			
		||||
var
 | 
			
		||||
  current_token: ^Token;
 | 
			
		||||
  i: Word := 0;
 | 
			
		||||
  i: Word := 0u;
 | 
			
		||||
begin
 | 
			
		||||
  while i < tokens_size do
 | 
			
		||||
    current_token := tokens + i;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user