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