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());
|
||||||
}
|
}
|
||||||
|
@@ -108,7 +108,7 @@ namespace elna::gcc
|
|||||||
if (!is_assignable_from(unqualified_field, this->current_expression))
|
if (!is_assignable_from(unqualified_field, this->current_expression))
|
||||||
{
|
{
|
||||||
error_at(argument_location,
|
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(this->current_expression)).c_str(),
|
||||||
print_type(TREE_TYPE(record_fields)).c_str());
|
print_type(TREE_TYPE(record_fields)).c_str());
|
||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
@@ -756,6 +756,7 @@ namespace elna::gcc
|
|||||||
get_identifier(variable_identifier.identifier.c_str()), this->current_expression);
|
get_identifier(variable_identifier.identifier.c_str()), this->current_expression);
|
||||||
bool result = this->symbols->enter(variable_identifier.identifier, declaration_tree);
|
bool result = this->symbols->enter(variable_identifier.identifier, declaration_tree);
|
||||||
|
|
||||||
|
// Set initializer if given.
|
||||||
if (declaration->body != nullptr)
|
if (declaration->body != nullptr)
|
||||||
{
|
{
|
||||||
declaration->body->accept(this);
|
declaration->body->accept(this);
|
||||||
@@ -774,6 +775,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