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) |     void variable_declaration::accept(parser_visitor *visitor) | ||||||
|     { |     { | ||||||
|         visitor->visit(this); |         visitor->visit(this); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     bool variable_declaration::has_initializer() const | ||||||
|  |     { | ||||||
|  |         return this->is_extern || this->body != nullptr; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     type_expression& variable_declaration::variable_type() |     type_expression& variable_declaration::variable_type() | ||||||
|     { |     { | ||||||
|         return *m_variable_type; |         return *m_variable_type; | ||||||
|   | |||||||
| @@ -508,6 +508,12 @@ variable_declaration: | |||||||
|             std::shared_ptr<boot::type_expression> shared_type{ $3 }; |             std::shared_ptr<boot::type_expression> shared_type{ $3 }; | ||||||
|             $$ = new boot::variable_declaration( boot::make_position(@2), std::move($1), shared_type); |             $$ = 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 ";" |     | identifier_definitions ":" type_expression ":=" expression ";" | ||||||
|         { |         { | ||||||
|             std::shared_ptr<boot::type_expression> shared_type{ $3 }; |             std::shared_ptr<boot::type_expression> shared_type{ $3 }; | ||||||
|   | |||||||
| @@ -609,7 +609,7 @@ namespace elna::boot | |||||||
|  |  | ||||||
|     void declaration_visitor::visit(variable_declaration *declaration) |     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()); |             add_error<variable_initializer_error>(this->input_file, declaration->position()); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -774,6 +774,7 @@ namespace elna::gcc | |||||||
|             { |             { | ||||||
|                 DECL_INITIAL(declaration_tree) = elna_pointer_nil_node; |                 DECL_INITIAL(declaration_tree) = elna_pointer_nil_node; | ||||||
|             } |             } | ||||||
|  |             DECL_EXTERNAL(declaration_tree) = declaration->is_extern; | ||||||
|             TREE_PUBLIC(declaration_tree) = variable_identifier.exported; |             TREE_PUBLIC(declaration_tree) = variable_identifier.exported; | ||||||
|             this->current_expression = NULL_TREE; |             this->current_expression = NULL_TREE; | ||||||
|             if (!result) |             if (!result) | ||||||
|   | |||||||
| @@ -348,12 +348,18 @@ namespace elna::boot | |||||||
|         variable_declaration(const struct position position, |         variable_declaration(const struct position position, | ||||||
|                 std::vector<identifier_definition>&& identifier, std::shared_ptr<type_expression> variable_type, |                 std::vector<identifier_definition>&& identifier, std::shared_ptr<type_expression> variable_type, | ||||||
|                 expression *body = nullptr); |                 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; |         void accept(parser_visitor *visitor) override; | ||||||
|  |  | ||||||
|  |         bool has_initializer() const; | ||||||
|  |  | ||||||
|         const std::vector<identifier_definition> identifiers; |         const std::vector<identifier_definition> identifiers; | ||||||
|         type_expression& variable_type(); |         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); | proc write_s*(value: String); | ||||||
| begin | begin | ||||||
|  |   (* fwrite(cast(value.ptr: Pointer), value.length, 1u, stdout) *) | ||||||
|   write(1, cast(value.ptr: Pointer), cast(value.length: Int)) |   write(1, cast(value.ptr: Pointer), cast(value.length: Int)) | ||||||
| end; | end; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,14 +6,20 @@ module; | |||||||
| type | type | ||||||
|   FILE* = record end; |   FILE* = record end; | ||||||
|  |  | ||||||
| proc fopen(pathname: ^Char, mode: ^Char) -> ^FILE; extern; | var | ||||||
| proc fclose(stream: ^FILE) -> Int; extern; |   stdin*: ^FILE := extern; | ||||||
| proc fseek(stream: ^FILE, off: Int, whence: Int) -> Int; extern; |   stdout*: ^FILE := extern; | ||||||
| proc rewind(stream: ^FILE); extern; |   stderr*: ^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 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; | proc perror(s: ^Char); extern; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -624,7 +624,7 @@ end; | |||||||
| proc parse(tokens: ^Token, tokens_size: Word); | proc parse(tokens: ^Token, tokens_size: Word); | ||||||
| var | var | ||||||
|   current_token: ^Token; |   current_token: ^Token; | ||||||
|   i: Word := 0; |   i: Word := 0u; | ||||||
| begin | begin | ||||||
|   while i < tokens_size do |   while i < tokens_size do | ||||||
|     current_token := tokens + i; |     current_token := tokens + i; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user