Implement cast expressions
This commit is contained in:
@@ -46,18 +46,11 @@ task :convert do
|
||||
current_stage << <<~FUN
|
||||
proc f();
|
||||
var
|
||||
x: ElnaLocation;
|
||||
y: ElnaPosition;
|
||||
x: ^ElnaLocation;
|
||||
begin
|
||||
x.line := 5;
|
||||
x.column := 3;
|
||||
y.end_location := x;
|
||||
|
||||
(* y.end_location.line := 5;
|
||||
y.end_location.column := 3;
|
||||
x := y.end_location; *)
|
||||
|
||||
printf("# %i %i %i %i\\n\\0", x.line, x.column, y.end_location.line, y.end_location.column)
|
||||
x := malloc(#size(ElnaLocation));
|
||||
x^.line := 5;
|
||||
x^.column := cast(3: Word)
|
||||
end;
|
||||
|
||||
begin
|
||||
|
||||
+217
-21
@@ -8,6 +8,7 @@ program;
|
||||
(* Stage 21 compiler. *)
|
||||
|
||||
(* - Allow assigning variables refering to aggregates. *)
|
||||
(* - Cast expressions. *)
|
||||
|
||||
type
|
||||
ElnaListNode = record
|
||||
@@ -102,11 +103,15 @@ type
|
||||
array_type_expression,
|
||||
null,
|
||||
trait_expression,
|
||||
array_access_expression
|
||||
array_access_expression,
|
||||
_cast
|
||||
);
|
||||
ElnaTreeNode = record
|
||||
kind: ElnaTreeKind
|
||||
end;
|
||||
ElnaTreeTypeExpression = record
|
||||
kind: ElnaTreeKind
|
||||
end;
|
||||
ElnaTreeExpression = record
|
||||
kind: ElnaTreeKind;
|
||||
type_decoration: ^ElnaType
|
||||
@@ -131,17 +136,23 @@ type
|
||||
type_decoration: ^ElnaType;
|
||||
value: Word
|
||||
end;
|
||||
ElnaTreeStringLiteral = record
|
||||
kind: ElnaTreeKind;
|
||||
type_decoration: ^ElnaType;
|
||||
value: Word;
|
||||
length: Word
|
||||
end;
|
||||
ElnaTreeVariableExpression = record
|
||||
kind: ElnaTreeKind;
|
||||
type_decoration: ^ElnaType;
|
||||
name: Word;
|
||||
length: Word
|
||||
end;
|
||||
ElnaTreeStringLiteral = record
|
||||
ElnaTreeCastExpression = record
|
||||
kind: ElnaTreeKind;
|
||||
type_decoration: ^ElnaType;
|
||||
value: Word;
|
||||
length: Word
|
||||
expression: ^ElnaTreeExpression;
|
||||
type_expression: ^ElnaTreeTypeExpression
|
||||
end;
|
||||
ElnaTreeDereferenceExpression = record
|
||||
kind: ElnaTreeKind;
|
||||
@@ -158,7 +169,7 @@ type
|
||||
ElnaTreeUnaryExpression = record
|
||||
kind: ElnaTreeKind;
|
||||
type_decoration: ^ElnaType;
|
||||
operand: Word;
|
||||
operand: ^ElnaTreeExpression;
|
||||
operator: Word
|
||||
end;
|
||||
|
||||
@@ -225,7 +236,7 @@ type
|
||||
ElnaTreeField = record
|
||||
name: Word;
|
||||
length: Word;
|
||||
type_expression: ^ElnaTreeNode;
|
||||
type_expression: ^ElnaTreeTypeExpression;
|
||||
next: Word
|
||||
end;
|
||||
ElnaTreeRecordTypeExpression = record
|
||||
@@ -240,11 +251,11 @@ type
|
||||
end;
|
||||
ElnaTreePointerTypeExpression = record
|
||||
kind: ElnaTreeKind;
|
||||
base: ^ElnaTreeNode
|
||||
base: ^ElnaTreeTypeExpression
|
||||
end;
|
||||
ElnaTreeArrayTypeExpression = record
|
||||
kind: ElnaTreeKind;
|
||||
base: ^ElnaTreeNode;
|
||||
base: ^ElnaTreeTypeExpression;
|
||||
length: Word
|
||||
end;
|
||||
ElnaTreeTraitExpression = record
|
||||
@@ -276,7 +287,7 @@ type
|
||||
body: ^ElnaTreeStatement;
|
||||
temporaries: Word;
|
||||
parameters: Word;
|
||||
return_type: ^ElnaTreeNode
|
||||
return_type: ^ElnaTreeTypeExpression
|
||||
end;
|
||||
ElnaTreeModuleDeclaration = record
|
||||
kind: ElnaTreeKind;
|
||||
@@ -290,14 +301,14 @@ type
|
||||
next: Word;
|
||||
name: Word;
|
||||
length: Word;
|
||||
_type: Word
|
||||
type_expression: ^ElnaTreeTypeExpression
|
||||
end;
|
||||
ElnaTreeVariableDeclaration = record
|
||||
kind: ElnaTreeKind;
|
||||
next: Word;
|
||||
name: Word;
|
||||
length: Word;
|
||||
_type: Word
|
||||
type_expression: Word
|
||||
end;
|
||||
ElnaTreeExpressionList = record
|
||||
expression: ^ElnaTreeBinaryExpression;
|
||||
@@ -2366,6 +2377,28 @@ begin
|
||||
return result
|
||||
end;
|
||||
|
||||
proc elna_parser_cast_expression(cursor: ^ElnaLexerCursor) -> ^ElnaTreeCastExpression;
|
||||
var
|
||||
result: ^ElnaTreeCastExpression;
|
||||
token: ^ElnaLexerToken;
|
||||
begin
|
||||
result := malloc(#size(ElnaTreeCastExpression));
|
||||
result^.kind := ElnaTreeKind._cast;
|
||||
result^.type_decoration := nil;
|
||||
|
||||
(* Skip the cast keyword and opening paren. *)
|
||||
elna_lexer_read(cursor);
|
||||
elna_lexer_read(cursor);
|
||||
result^.expression := elna_parser_binary_expression(cursor);
|
||||
(* Skip the colon. *)
|
||||
elna_lexer_read(cursor);
|
||||
result^.type_expression := elna_parser_type_expression(cursor);
|
||||
(* Skip the closing paren. *)
|
||||
elna_lexer_read(cursor);
|
||||
|
||||
return result
|
||||
end;
|
||||
|
||||
proc elna_parser_simple_expression(cursor: ^ElnaLexerCursor) -> ^ElnaTreeExpression;
|
||||
var
|
||||
current_character: Word;
|
||||
@@ -2385,6 +2418,8 @@ begin
|
||||
parser_node := elna_parser_boolean_literal(cursor)
|
||||
elsif token^.kind = ElnaLexerKind.null then
|
||||
parser_node := elna_parser_nil_literal(cursor)
|
||||
elsif token^.kind = ElnaLexerKind._cast then
|
||||
parser_node := elna_parser_cast_expression(cursor)
|
||||
elsif token^.kind = ElnaLexerKind.trait then
|
||||
parser_node := elna_parser_trait_expression(cursor)
|
||||
elsif token^.kind = ElnaLexerKind.identifier then
|
||||
@@ -2449,6 +2484,12 @@ begin
|
||||
operand^.length := 0
|
||||
end;
|
||||
|
||||
proc elna_tac_cast_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeCastExpression,
|
||||
symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
|
||||
begin
|
||||
elna_tac_binary_expression(instructions, parser_node^.expression, symbol_table, operand)
|
||||
end;
|
||||
|
||||
proc elna_tac_simple_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeNode,
|
||||
symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
|
||||
begin
|
||||
@@ -2462,6 +2503,8 @@ begin
|
||||
elna_tac_boolean_literal(parser_node, operand)
|
||||
elsif parser_node^.kind = ElnaTreeKind.null then
|
||||
elna_tac_nil_literal(parser_node, operand)
|
||||
elsif parser_node^.kind = ElnaTreeKind._cast then
|
||||
elna_tac_cast_expression(instructions, parser_node, symbol_table, operand)
|
||||
elsif parser_node^.kind = ElnaTreeKind.trait_expression then
|
||||
elna_tac_trait_expression(parser_node, operand)
|
||||
else
|
||||
@@ -3761,7 +3804,7 @@ begin
|
||||
return result
|
||||
end;
|
||||
|
||||
proc type_info_create(type_representation: Word) -> ^ElnaSymbolTypeInfo;
|
||||
proc type_info_create(type_representation: ^ElnaType) -> ^ElnaSymbolTypeInfo;
|
||||
var
|
||||
result: ^ElnaSymbolTypeInfo;
|
||||
begin
|
||||
@@ -3815,7 +3858,7 @@ var
|
||||
info: Word;
|
||||
variable_type: Word;
|
||||
begin
|
||||
variable_type := elna_name_type_expression(parser_node^._type);
|
||||
variable_type := elna_name_type_expression(parser_node^.type_expression);
|
||||
|
||||
info := temporary_info_create(0, variable_type);
|
||||
elna_symbol_table_enter(symbol_table, parser_node^.name, parser_node^.length, info)
|
||||
@@ -4274,7 +4317,7 @@ begin
|
||||
result^.length := token^.length;
|
||||
|
||||
elna_lexer_read(cursor);
|
||||
result^._type := elna_parser_type_expression(cursor);
|
||||
result^.type_expression := elna_parser_type_expression(cursor);
|
||||
|
||||
elna_lexer_read(cursor);
|
||||
|
||||
@@ -4286,7 +4329,7 @@ var
|
||||
symbol_type: ^ElnaType;
|
||||
type_info: ^ElnaSymbolTypeInfo;
|
||||
begin
|
||||
symbol_type := elna_name_type_expression(parser_node^._type);
|
||||
symbol_type := elna_name_type_expression(parser_node^.type_expression);
|
||||
type_info := type_info_create(symbol_type);
|
||||
|
||||
elna_symbol_table_enter(symbol_table_global, parser_node^.name, parser_node^.length, type_info)
|
||||
@@ -4350,7 +4393,7 @@ begin
|
||||
result^.next := nil;
|
||||
result^.name := token^.start;
|
||||
result^.length := token^.length;
|
||||
result^._type := variable_type;
|
||||
result^.type_expression := variable_type;
|
||||
|
||||
return result
|
||||
end;
|
||||
@@ -4539,6 +4582,152 @@ begin
|
||||
return result
|
||||
end;
|
||||
|
||||
proc elna_name_dereference_expression(parser_node: ^ElnaTreeDereferenceExpression);
|
||||
begin
|
||||
elna_name_designator(parser_node^.pointer)
|
||||
end;
|
||||
|
||||
proc elna_name_field_access_expression(parser_node: ^ElnaTreeFieldAccessExpression);
|
||||
begin
|
||||
elna_name_designator(parser_node^.aggregate)
|
||||
end;
|
||||
|
||||
proc elna_name_array_access_expression(parser_node: ^ElnaTreeArrayAccessExpression);
|
||||
begin
|
||||
elna_name_designator(parser_node^.array);
|
||||
elna_name_binary_expression(parser_node^.index)
|
||||
end;
|
||||
|
||||
proc elna_name_cast_expression(parser_node: ^ElnaTreeCastExpression);
|
||||
begin
|
||||
elna_name_binary_expression(parser_node^.expression);
|
||||
parser_node^.type_decoration := elna_name_type_expression(parser_node^.type_expression)
|
||||
end;
|
||||
|
||||
proc elna_name_simple_expression(parser_node: ^ElnaTreeNode);
|
||||
begin
|
||||
(* Not interested in literals and variable expressions. *)
|
||||
if parser_node^.kind = ElnaTreeKind._cast then
|
||||
elna_name_cast_expression(parser_node)
|
||||
end
|
||||
end;
|
||||
|
||||
proc elna_name_call(parser_node: ^ElnaTreeCall);
|
||||
var
|
||||
argument_tree: ^ElnaTreeExpressionList;
|
||||
begin
|
||||
argument_tree := parser_node^.arguments;
|
||||
|
||||
.elna_name_call_argument;
|
||||
if argument_tree <> nil then
|
||||
elna_name_binary_expression(argument_tree^.expression);
|
||||
argument_tree := argument_tree^.next;
|
||||
|
||||
goto elna_name_call_argument
|
||||
end
|
||||
end;
|
||||
|
||||
proc elna_name_designator(parser_node: ^ElnaTreeNode);
|
||||
begin
|
||||
if parser_node^.kind = ElnaTreeKind.dereference_expression then
|
||||
elna_name_dereference_expression(parser_node)
|
||||
elsif parser_node^.kind = ElnaTreeKind.field_access_expression then
|
||||
elna_name_field_access_expression(parser_node)
|
||||
elsif parser_node^.kind = ElnaTreeKind.array_access_expression then
|
||||
elna_name_array_access_expression(parser_node)
|
||||
elsif parser_node^.kind = ElnaTreeKind.call then
|
||||
elna_name_call(parser_node)
|
||||
else
|
||||
elna_name_simple_expression(parser_node)
|
||||
end
|
||||
end;
|
||||
|
||||
proc elna_name_unary_expression(parser_node: ^ElnaTreeUnaryExpression);
|
||||
begin
|
||||
if parser_node^.kind = ElnaTreeKind.unary_expression then
|
||||
elna_name_designator(parser_node^.operand)
|
||||
else
|
||||
elna_name_designator(parser_node)
|
||||
end
|
||||
end;
|
||||
|
||||
proc elna_name_binary_expression(parser_node: ^ElnaTreeBinaryExpression);
|
||||
begin
|
||||
if parser_node^.kind = ElnaTreeKind.binary_expression then
|
||||
elna_name_unary_expression(parser_node^.lhs);
|
||||
elna_name_unary_expression(parser_node^.rhs)
|
||||
else
|
||||
elna_name_unary_expression(parser_node)
|
||||
end
|
||||
end;
|
||||
|
||||
proc elna_name_conditional_statements(parser_node: ^ElnaTreeConditionalStatements);
|
||||
begin
|
||||
.elna_name_conditional_statements_loop;
|
||||
elna_name_binary_expression(parser_node^.condition);
|
||||
elna_name_statements(parser_node^.statements);
|
||||
|
||||
parser_node := parser_node^.next;
|
||||
if parser_node <> nil then
|
||||
goto elna_name_conditional_statements_loop
|
||||
end
|
||||
end;
|
||||
|
||||
proc elna_name_if_statement(parser_node: ^ElnaTreeIfStatement);
|
||||
var
|
||||
block: ^ElnaTreeConditionalStatements;
|
||||
begin
|
||||
block := parser_node^.conditionals;
|
||||
|
||||
.elna_name_if_statement_conditionals;
|
||||
elna_name_conditional_statements(block);
|
||||
|
||||
block := block^.next;
|
||||
if block <> nil then
|
||||
goto elna_name_if_statement_conditionals
|
||||
end;
|
||||
block := parser_node^._else;
|
||||
if block <> nil then
|
||||
elna_name_statements(block)
|
||||
end
|
||||
end;
|
||||
|
||||
proc elna_name_return_statement(parser_node: ^ElnaTreeReturnStatement);
|
||||
begin
|
||||
elna_name_binary_expression(parser_node^.returned)
|
||||
end;
|
||||
|
||||
proc elna_name_assign_statement(parser_node: ^ElnaTreeAssignStatement);
|
||||
begin
|
||||
elna_name_designator(parser_node^.assignee);
|
||||
elna_name_binary_expression(parser_node^.assignment)
|
||||
end;
|
||||
|
||||
proc elna_name_statement(parser_node: ^ElnaTreeStatement);
|
||||
begin
|
||||
(* Skipping goto and label declarations. *)
|
||||
if parser_node^.kind = ElnaTreeKind.if_statement then
|
||||
elna_name_if_statement(parser_node)
|
||||
elsif parser_node^.kind = ElnaTreeKind.return_statement then
|
||||
elna_name_return_statement(parser_node)
|
||||
elsif parser_node^.kind = ElnaTreeKind.call then
|
||||
elna_name_call(parser_node)
|
||||
elsif parser_node^.kind = ElnaTreeKind.assign_statement then
|
||||
elna_name_assign_statement(parser_node)
|
||||
end
|
||||
end;
|
||||
|
||||
proc elna_name_statements(parser_node: ^ElnaTreeStatement);
|
||||
begin
|
||||
.elna_name_statements_loop;
|
||||
if parser_node <> nil then
|
||||
elna_name_statement(parser_node);
|
||||
|
||||
parser_node := parser_node^.next;
|
||||
goto elna_name_statements_loop
|
||||
end
|
||||
end;
|
||||
|
||||
proc elna_name_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration);
|
||||
var
|
||||
new_symbol_table: ^ElnaSymbolTable;
|
||||
@@ -4549,6 +4738,7 @@ begin
|
||||
|
||||
elna_name_procedure_temporaries(parser_node^.parameters, new_symbol_table);
|
||||
elna_name_procedure_temporaries(parser_node^.temporaries, new_symbol_table);
|
||||
elna_name_statements(parser_node^.body);
|
||||
|
||||
elna_symbol_table_enter(symbol_table_global, parser_node^.name, parser_node^.length, symbol_info)
|
||||
end;
|
||||
@@ -4690,6 +4880,11 @@ begin
|
||||
end
|
||||
end;
|
||||
|
||||
proc elna_type_cast_expression(parser_node: ^ElnaTreeCastExpression, symbol_table: ^ElnaSymbolTable);
|
||||
begin
|
||||
elna_type_binary_expression(parser_node^.expression, symbol_table)
|
||||
end;
|
||||
|
||||
proc elna_type_simple_expression(parser_node: ^ElnaTreeNode, symbol_table: ^ElnaSymbolTable);
|
||||
begin
|
||||
if parser_node^.kind = ElnaTreeKind.integer_literal then
|
||||
@@ -4702,6 +4897,8 @@ begin
|
||||
elna_type_boolean_literal(parser_node)
|
||||
elsif parser_node^.kind = ElnaTreeKind.null then
|
||||
elna_type_nil_literal(parser_node)
|
||||
elsif parser_node^.kind = ElnaTreeKind._cast then
|
||||
elna_type_cast_expression(parser_node)
|
||||
elsif parser_node^.kind = ElnaTreeKind.variable_expression then
|
||||
elna_type_variable_expression(parser_node, symbol_table)
|
||||
end
|
||||
@@ -4801,14 +4998,11 @@ begin
|
||||
end;
|
||||
|
||||
proc elna_type_unary_expression(parser_node: ^ElnaTreeUnaryExpression, symbol_table: ^ElnaSymbolTable);
|
||||
var
|
||||
unary_operand: ^ElnaTreeExpression;
|
||||
begin
|
||||
if parser_node^.kind = ElnaTreeKind.unary_expression then
|
||||
unary_operand := parser_node^.operand;
|
||||
elna_type_designator(unary_operand, symbol_table);
|
||||
elna_type_designator(parser_node^.operand, symbol_table);
|
||||
|
||||
parser_node^.type_decoration := unary_operand^.type_decoration
|
||||
parser_node^.type_decoration := parser_node^.operand^.type_decoration
|
||||
else
|
||||
elna_type_designator(parser_node, symbol_table)
|
||||
end
|
||||
@@ -5496,6 +5690,8 @@ begin
|
||||
result^.kind := ElnaLexerKind.boolean
|
||||
elsif string_compare(position_start, result^.length, "false", 5) then
|
||||
result^.kind := ElnaLexerKind.boolean
|
||||
elsif string_compare(position_start, result^.length, "cast", 4) then
|
||||
result^.kind := ElnaLexerKind._cast
|
||||
end;
|
||||
return result
|
||||
end;
|
||||
|
||||
@@ -74,3 +74,11 @@ end
|
||||
file "build/valid/#{STAGES.last}/cl" => 'build/build.ninja' do |t|
|
||||
sh 'ninja', '-f', t.prerequisites.first
|
||||
end
|
||||
|
||||
namespace :ninja do
|
||||
desc 'Forces the regeneration of build/build.ninja'
|
||||
task :build do
|
||||
rm_f 'build/build.ninja'
|
||||
Rake::Task['build/build.ninja'].invoke
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user