Provide record initialization syntax
This commit is contained in:
parent
62d9398772
commit
c564847c6b
3
Rakefile
3
Rakefile
@ -69,6 +69,9 @@ namespace :boot do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
desc 'Build the bootstrap compiler'
|
||||||
|
task boot: %w[boot:configure boot:make]
|
||||||
|
|
||||||
file (TMP + 'elna').to_path => ['source.elna']
|
file (TMP + 'elna').to_path => ['source.elna']
|
||||||
file (TMP + 'elna').to_path => [(HOST_INSTALL + 'bin/gelna').to_path] do |task|
|
file (TMP + 'elna').to_path => [(HOST_INSTALL + 'bin/gelna').to_path] do |task|
|
||||||
sh (HOST_INSTALL + 'bin/gelna').to_path, '-o', task.name, task.prerequisites.first
|
sh (HOST_INSTALL + 'bin/gelna').to_path, '-o', task.name, task.prerequisites.first
|
||||||
|
@ -444,7 +444,7 @@ variable_declarations:
|
|||||||
variable_part:
|
variable_part:
|
||||||
/* no variable declarations */ {}
|
/* no variable declarations */ {}
|
||||||
| VAR variable_declarations SEMICOLON { std::swap($$, $2); }
|
| VAR variable_declarations SEMICOLON { std::swap($$, $2); }
|
||||||
constant_definition: identifier_definition EQUALS literal SEMICOLON
|
constant_definition: identifier_definition EQUALS literal
|
||||||
{
|
{
|
||||||
$$ = new elna::boot::constant_definition(elna::boot::make_position(@1), $1.first, $1.second, $3);
|
$$ = new elna::boot::constant_definition(elna::boot::make_position(@1), $1.first, $1.second, $3);
|
||||||
}
|
}
|
||||||
@ -464,15 +464,16 @@ type_definition: identifier_definition EQUALS type_expression
|
|||||||
$$ = new elna::boot::type_definition(elna::boot::make_position(@1), $1.first, $1.second, $3);
|
$$ = new elna::boot::type_definition(elna::boot::make_position(@1), $1.first, $1.second, $3);
|
||||||
}
|
}
|
||||||
type_definitions:
|
type_definitions:
|
||||||
type_definition COMMA type_definitions
|
type_definition type_definitions
|
||||||
{
|
{
|
||||||
std::swap($$, $3);
|
std::swap($$, $2);
|
||||||
$$.emplace($$.cbegin(), std::move($1));
|
$$.emplace($$.cbegin(), std::move($1));
|
||||||
}
|
}
|
||||||
| type_definition { $$.emplace_back(std::move($1)); }
|
| type_definition { $$.emplace_back(std::move($1)); }
|
||||||
type_part:
|
type_part:
|
||||||
/* no type definitions */ {}
|
/* no type definitions */ {}
|
||||||
| TYPE type_definitions SEMICOLON { std::swap($$, $2); }
|
| TYPE {}
|
||||||
|
| TYPE type_definitions { std::swap($$, $2); }
|
||||||
formal_parameter_list:
|
formal_parameter_list:
|
||||||
LEFT_PAREN RIGHT_PAREN {}
|
LEFT_PAREN RIGHT_PAREN {}
|
||||||
| LEFT_PAREN variable_declarations RIGHT_PAREN { std::swap($$, $2); }
|
| LEFT_PAREN variable_declarations RIGHT_PAREN { std::swap($$, $2); }
|
||||||
|
@ -56,20 +56,17 @@ namespace gcc
|
|||||||
}
|
}
|
||||||
else if (DECL_P(symbol) && is_procedure_type(TREE_TYPE(symbol)))
|
else if (DECL_P(symbol) && is_procedure_type(TREE_TYPE(symbol)))
|
||||||
{
|
{
|
||||||
tree return_type = TREE_TYPE(TREE_TYPE(symbol));
|
vec<tree, va_gc> *arguments = nullptr;
|
||||||
tree fndecl_type = build_function_type(return_type, TYPE_ARG_TYPES(symbol));
|
|
||||||
tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol);
|
|
||||||
|
|
||||||
std::vector<tree> arguments(expression->arguments().size());
|
vec_alloc(arguments, expression->arguments().size());
|
||||||
for (std::size_t i = 0; i < expression->arguments().size(); ++i)
|
for (boot::expression *const argument : expression->arguments())
|
||||||
{
|
{
|
||||||
expression->arguments().at(i)->accept(this);
|
argument->accept(this);
|
||||||
arguments[i] = this->current_expression;
|
arguments->quick_push(this->current_expression);
|
||||||
}
|
}
|
||||||
tree stmt = build_call_array_loc(get_location(&expression->position()),
|
tree stmt = build_call_expr_loc_vec(get_location(&expression->position()), symbol, arguments);
|
||||||
return_type, printf_fn, arguments.size(), arguments.data());
|
|
||||||
|
|
||||||
if (return_type == void_type_node)
|
if (TREE_TYPE(TREE_TYPE(symbol)) == void_type_node)
|
||||||
{
|
{
|
||||||
append_statement(stmt);
|
append_statement(stmt);
|
||||||
this->current_expression = NULL_TREE;
|
this->current_expression = NULL_TREE;
|
||||||
@ -79,6 +76,18 @@ namespace gcc
|
|||||||
this->current_expression = stmt;
|
this->current_expression = stmt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (TYPE_P(symbol) && is_record_type(symbol))
|
||||||
|
{
|
||||||
|
vec<constructor_elt, va_gc> *arguments = nullptr;
|
||||||
|
tree record_fields = TYPE_FIELDS(symbol);
|
||||||
|
for (boot::expression *const argument : expression->arguments())
|
||||||
|
{
|
||||||
|
argument->accept(this);
|
||||||
|
CONSTRUCTOR_APPEND_ELT(arguments, record_fields, this->current_expression);
|
||||||
|
record_fields = TREE_CHAIN(record_fields);
|
||||||
|
}
|
||||||
|
this->current_expression = build_constructor(symbol, arguments);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error_at(call_location, "'%s' cannot be called, it is neither a procedure nor record",
|
error_at(call_location, "'%s' cannot be called, it is neither a procedure nor record",
|
||||||
@ -360,7 +369,7 @@ namespace gcc
|
|||||||
string_literal, integer_zero_node, NULL_TREE, NULL_TREE);
|
string_literal, integer_zero_node, NULL_TREE, NULL_TREE);
|
||||||
string_literal = build1(ADDR_EXPR, string_type, string_literal);
|
string_literal = build1(ADDR_EXPR, string_type, string_literal);
|
||||||
|
|
||||||
vec<constructor_elt, va_gc> *elms = NULL;
|
vec<constructor_elt, va_gc> *elms = nullptr;
|
||||||
CONSTRUCTOR_APPEND_ELT(elms, elna_string_ptr_field_node, string_literal);
|
CONSTRUCTOR_APPEND_ELT(elms, elna_string_ptr_field_node, string_literal);
|
||||||
CONSTRUCTOR_APPEND_ELT(elms, elna_string_length_field_node, index_constant);
|
CONSTRUCTOR_APPEND_ELT(elms, elna_string_length_field_node, index_constant);
|
||||||
|
|
||||||
@ -851,7 +860,7 @@ namespace gcc
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
error_at(statement_location,
|
error_at(statement_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(lvalue)).c_str());
|
print_type(TREE_TYPE(lvalue)).c_str());
|
||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
|
@ -62,6 +62,11 @@ namespace gcc
|
|||||||
return type == NULL_TREE || type == void_type_node;
|
return type == NULL_TREE || type == void_type_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_record_type(tree type)
|
||||||
|
{
|
||||||
|
return TREE_CODE(type) == RECORD_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
bool are_compatible_pointers(tree lhs, tree rhs)
|
bool are_compatible_pointers(tree lhs, tree rhs)
|
||||||
{
|
{
|
||||||
tree lhs_type = TREE_TYPE(lhs);
|
tree lhs_type = TREE_TYPE(lhs);
|
||||||
|
@ -39,6 +39,7 @@ namespace gcc
|
|||||||
bool is_array_type(tree type);
|
bool is_array_type(tree type);
|
||||||
bool is_procedure_type(tree type);
|
bool is_procedure_type(tree type);
|
||||||
bool is_void_type(tree type);
|
bool is_void_type(tree type);
|
||||||
|
bool is_record_type(tree type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \param lhs Left hand value.
|
* \param lhs Left hand value.
|
||||||
|
116
source.elna
116
source.elna
@ -1,68 +1,113 @@
|
|||||||
const
|
const
|
||||||
SEEK_SET* = 0; SEEK_CUR* = 1; SEEK_END* = 2;
|
SEEK_SET* = 0
|
||||||
|
SEEK_CUR* = 1
|
||||||
|
SEEK_END* = 2
|
||||||
|
|
||||||
TOKEN_IDENTIFIER* = 1; TOKEN_IF* = 2; TOKEN_THEN* = 3; TOKEN_ELSE* = 4; TOKEN_ELSIF* = 5;
|
TOKEN_IDENTIFIER* = 1
|
||||||
TOKEN_WHILE* = 6; TOKEN_DO* = 7; TOKEN_PROC* = 8; TOKEN_BEGIN* = 9; TOKEN_END* = 10;
|
TOKEN_IF* = 2
|
||||||
TOKEN_EXTERN* = 11; TOKEN_CONST* = 12; TOKEN_VAR* = 13; TOKEN_ARRAY* = 14; TOKEN_OF* = 15;
|
TOKEN_THEN* = 3
|
||||||
TOKEN_TYPE* = 16; TOKEN_RECORD* = 17; TOKEN_UNION* = 18; TOKEN_POINTER* = 19; TOKEN_TO* = 20;
|
TOKEN_ELSE* = 4
|
||||||
TOKEN_BOOLEAN* = 21; TOKEN_NIL* = 22; TOKEN_AND* = 23; TOKEN_OR* = 24; TOKEN_NOT* = 25;
|
TOKEN_ELSIF* = 5
|
||||||
TOKEN_RETURN* = 26; TOKEN_CAST* = 27; TOKEN_AS* = 28; TOKEN_SIZEOF* = 29;
|
TOKEN_WHILE* = 6
|
||||||
TOKEN_LEFT_PAREN* = 30; TOKEN_RIGHT_PAREN* = 31; TOKEN_LEFT_SQUARE* = 32;
|
TOKEN_DO* = 7
|
||||||
TOKEN_RIGHT_SQUARE* = 33; TOKEN_GREATER_EQUAL* = 34; TOKEN_LESS_EQUAL* = 35;
|
TOKEN_PROC* = 8
|
||||||
TOKEN_GREATER_THAN* = 36; TOKEN_LESS_THAN* = 37; TOKEN_NOT_EQUAL* = 38; TOKEN_EQUAL* = 39;
|
TOKEN_BEGIN* = 9
|
||||||
TOKEN_SEMICOLON* = 40; TOKEN_DOT* = 41; TOKEN_COMMA* = 42;
|
TOKEN_END* = 10
|
||||||
TOKEN_PLUS* = 43; TOKEN_MINUS* = 44; TOKEN_MULTIPLICATION* = 45; TOKEN_DIVISION* = 46;
|
TOKEN_EXTERN* = 11
|
||||||
TOKEN_REMAINDER* = 47; TOKEN_ASSIGNMENT* = 48; TOKEN_COLON* = 49; TOKEN_HAT* = 50;
|
TOKEN_CONST* = 12
|
||||||
TOKEN_AT* = 51; TOKEN_COMMENT* = 52; TOKEN_INTEGER* = 53; TOKEN_WORD* = 54;
|
TOKEN_VAR* = 13
|
||||||
TOKEN_CHARACTER* = 55; TOKEN_STRING* = 56; TOKEN_DEFER* = 57;
|
TOKEN_ARRAY* = 14
|
||||||
|
TOKEN_OF* = 15
|
||||||
|
TOKEN_TYPE* = 16
|
||||||
|
TOKEN_RECORD* = 17
|
||||||
|
TOKEN_UNION* = 18
|
||||||
|
TOKEN_POINTER* = 19
|
||||||
|
TOKEN_TO* = 20
|
||||||
|
TOKEN_BOOLEAN* = 21
|
||||||
|
TOKEN_NIL* = 22
|
||||||
|
TOKEN_AND* = 23
|
||||||
|
TOKEN_OR* = 24
|
||||||
|
TOKEN_NOT* = 25
|
||||||
|
TOKEN_RETURN* = 26
|
||||||
|
TOKEN_CAST* = 27
|
||||||
|
TOKEN_AS* = 28
|
||||||
|
TOKEN_SIZEOF* = 29
|
||||||
|
TOKEN_LEFT_PAREN* = 30
|
||||||
|
TOKEN_RIGHT_PAREN* = 31
|
||||||
|
TOKEN_LEFT_SQUARE* = 32
|
||||||
|
TOKEN_RIGHT_SQUARE* = 33
|
||||||
|
TOKEN_GREATER_EQUAL* = 34
|
||||||
|
TOKEN_LESS_EQUAL* = 35
|
||||||
|
TOKEN_GREATER_THAN* = 36
|
||||||
|
TOKEN_LESS_THAN* = 37
|
||||||
|
TOKEN_NOT_EQUAL* = 38
|
||||||
|
TOKEN_EQUAL* = 39
|
||||||
|
TOKEN_SEMICOLON* = 40
|
||||||
|
TOKEN_DOT* = 41
|
||||||
|
TOKEN_COMMA* = 42
|
||||||
|
TOKEN_PLUS* = 43
|
||||||
|
TOKEN_MINUS* = 44
|
||||||
|
TOKEN_MULTIPLICATION* = 45
|
||||||
|
TOKEN_DIVISION* = 46
|
||||||
|
TOKEN_REMAINDER* = 47
|
||||||
|
TOKEN_ASSIGNMENT* = 48
|
||||||
|
TOKEN_COLON* = 49
|
||||||
|
TOKEN_HAT* = 50
|
||||||
|
TOKEN_AT* = 51
|
||||||
|
TOKEN_COMMENT* = 52
|
||||||
|
TOKEN_INTEGER* = 53
|
||||||
|
TOKEN_WORD* = 54
|
||||||
|
TOKEN_CHARACTER* = 55
|
||||||
|
TOKEN_STRING* = 56
|
||||||
|
TOKEN_DEFER* = 57
|
||||||
|
|
||||||
type
|
type
|
||||||
Position* = record
|
Position* = record
|
||||||
line: Word;
|
line: Word;
|
||||||
column: Word
|
column: Word
|
||||||
end,
|
end
|
||||||
Location* = record
|
Location* = record
|
||||||
first: Position;
|
first: Position;
|
||||||
last: Position
|
last: Position
|
||||||
end,
|
end
|
||||||
SourceCode = record
|
SourceCode = record
|
||||||
position: Position;
|
position: Position;
|
||||||
text: String
|
text: String
|
||||||
end,
|
end
|
||||||
TokenValue* = union
|
TokenValue* = union
|
||||||
int_value: Int;
|
int_value: Int;
|
||||||
string_value: pointer to Char;
|
string_value: pointer to Char;
|
||||||
string: String;
|
string: String;
|
||||||
boolean_value: Bool;
|
boolean_value: Bool;
|
||||||
char_value: Char
|
char_value: Char
|
||||||
end,
|
end
|
||||||
Token* = record
|
Token* = record
|
||||||
kind: Int;
|
kind: Int;
|
||||||
value: TokenValue;
|
value: TokenValue;
|
||||||
location: Location
|
location: Location
|
||||||
end,
|
end
|
||||||
FILE* = record
|
FILE* = record
|
||||||
dummy: Int
|
dummy: Int
|
||||||
end,
|
end
|
||||||
CommandLine* = record
|
CommandLine* = record
|
||||||
input: pointer to Char;
|
input: pointer to Char;
|
||||||
tokenize: Bool;
|
tokenize: Bool;
|
||||||
syntax_tree: Bool
|
syntax_tree: Bool
|
||||||
end,
|
end
|
||||||
Literal* = record
|
Literal* = record
|
||||||
value: Int
|
value: Int
|
||||||
end,
|
end
|
||||||
ConstantDefinition* = record
|
ConstantDefinition* = record
|
||||||
name: pointer to Char;
|
name: pointer to Char;
|
||||||
body: pointer to Literal
|
body: pointer to Literal
|
||||||
end,
|
end
|
||||||
ConstantPart* = record
|
ConstantPart* = record
|
||||||
elements: pointer to pointer to ConstantDefinition;
|
elements: pointer to pointer to ConstantDefinition;
|
||||||
count: Word
|
count: Word
|
||||||
end,
|
end
|
||||||
Program* = record
|
Program* = record
|
||||||
constants: ConstantPart
|
constants: ConstantPart
|
||||||
end;
|
end
|
||||||
|
|
||||||
(*
|
(*
|
||||||
External procedures.
|
External procedures.
|
||||||
@ -173,18 +218,14 @@ begin
|
|||||||
return c = ' ' or c = '\n' or c = '\t'
|
return c = ' ' or c = '\n' or c = '\t'
|
||||||
end
|
end
|
||||||
|
|
||||||
proc open_substring(string: String, start: Word) -> String;
|
|
||||||
begin
|
|
||||||
string.ptr := string.ptr + start;
|
|
||||||
string.length := string.length - start;
|
|
||||||
return string
|
|
||||||
end
|
|
||||||
|
|
||||||
proc substring(string: String, start: Word, count: Word) -> String;
|
proc substring(string: String, start: Word, count: Word) -> String;
|
||||||
begin
|
begin
|
||||||
string.ptr := string.ptr + start;
|
return String(string.ptr + start, count)
|
||||||
string.length := count;
|
end
|
||||||
return string
|
|
||||||
|
proc open_substring(string: String, start: Word) -> String;
|
||||||
|
begin
|
||||||
|
return substring(string, start, string.length - start)
|
||||||
end
|
end
|
||||||
|
|
||||||
proc string_dup(origin: String) -> String;
|
proc string_dup(origin: String) -> String;
|
||||||
@ -193,9 +234,8 @@ var
|
|||||||
begin
|
begin
|
||||||
copy := cast(malloc(origin.length) as pointer to Char);
|
copy := cast(malloc(origin.length) as pointer to Char);
|
||||||
strncpy(copy, origin.ptr, origin.length);
|
strncpy(copy, origin.ptr, origin.length);
|
||||||
origin.ptr := copy;
|
|
||||||
|
|
||||||
return origin
|
return String(copy, origin.length)
|
||||||
end
|
end
|
||||||
|
|
||||||
(*
|
(*
|
||||||
|
@ -15,7 +15,7 @@ class BuildTarget
|
|||||||
attr_accessor(:build, :gcc, :sysroot, :tmp)
|
attr_accessor(:build, :gcc, :sysroot, :tmp)
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@sysroot = '/'
|
@sysroot = Pathname.new '/'
|
||||||
end
|
end
|
||||||
|
|
||||||
def gxx
|
def gxx
|
||||||
@ -55,7 +55,7 @@ def find_build_target(gcc_version)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
result.tmp = TMP
|
result.tmp = TMP
|
||||||
result.sysroot = sdk
|
result.sysroot = sdk unless sdk.nil?
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user