diff --git a/boot/ast.cc b/boot/ast.cc index 3014848..becc164 100644 --- a/boot/ast.cc +++ b/boot/ast.cc @@ -415,11 +415,23 @@ namespace elna::boot { } + variable_declaration::variable_declaration(const struct position position, + std::vector&& identifier, std::shared_ptr 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; diff --git a/boot/parser.yy b/boot/parser.yy index 4e09e53..07fb7a5 100644 --- a/boot/parser.yy +++ b/boot/parser.yy @@ -508,6 +508,12 @@ variable_declaration: std::shared_ptr shared_type{ $3 }; $$ = new boot::variable_declaration( boot::make_position(@2), std::move($1), shared_type); } + | identifier_definitions ":" type_expression ":=" "extern" ";" + { + std::shared_ptr 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 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))); } diff --git a/boot/semantic.cc b/boot/semantic.cc index 25c44ed..e6dd248 100644 --- a/boot/semantic.cc +++ b/boot/semantic.cc @@ -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(this->input_file, declaration->position()); } diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index 779f2fe..5472061 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -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) diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 7da9b53..ad531f4 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -348,12 +348,18 @@ namespace elna::boot variable_declaration(const struct position position, std::vector&& identifier, std::shared_ptr variable_type, expression *body = nullptr); + variable_declaration(const struct position position, + std::vector&& identifier, std::shared_ptr variable_type, + std::monostate); void accept(parser_visitor *visitor) override; + bool has_initializer() const; + const std::vector identifiers; type_expression& variable_type(); - expression *const body; + expression *const body{ nullptr }; + const bool is_extern{ false }; }; /** diff --git a/source/common.elna b/source/common.elna index 1a25444..e7b30ca 100644 --- a/source/common.elna +++ b/source/common.elna @@ -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; diff --git a/source/cstdio.elna b/source/cstdio.elna index a9352e7..c7507ff 100644 --- a/source/cstdio.elna +++ b/source/cstdio.elna @@ -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; diff --git a/source/main.elna b/source/main.elna index 6741eab..dae045b 100644 --- a/source/main.elna +++ b/source/main.elna @@ -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;