Set expression type for enumeration values

This commit is contained in:
2025-11-25 08:03:05 +01:00
parent c3eff02f8d
commit c20d9b7240
4 changed files with 5692 additions and 66 deletions

View File

@@ -40,43 +40,19 @@ end
desc 'Convert previous stage language into the current stage language' desc 'Convert previous stage language into the current stage language'
task :convert do task :convert do
File.open('boot/stage16.elna', 'w') do |current_stage| File.open('boot/stage17/cl.elna', 'w') do |current_stage|
skip = false File.readlines('boot/stage16/cl.elna').each do |line|
File.readlines('boot/stage15.elna').each do |line|
if line.strip == 'type'
current_stage << <<~SNIP
type
_elna_tac_declaration = record
next: Word;
name: Word;
length: Word;
body: Word
end;
_integer_literal_node = record
kind: Word;
value: Word;
length: Word
end;
SNIP
elsif line.start_with?('proc _elna_tac_declaration_size')
skip = true
elsif line.start_with?('proc _elna_tac_declaration_get_')
skip = true
elsif line.start_with?('proc _elna_tac_declaration_set_')
skip = true
elsif line.start_with?('proc _integer_literal_node_size')
skip = true
elsif line.start_with?('proc _integer_literal_node_get_')
skip = true
elsif line.start_with?('proc _integer_literal_node_set_')
skip = true
elsif line.start_with?('end') && skip
skip = false
elsif !skip
current_stage << line current_stage << line
end
end end
current_stage << <<~STAGE
proc f(x: ElnaTreeExpression);
var
y: Word;
begin
y := x.kind
end;
STAGE
end end
end end

View File

@@ -24,6 +24,10 @@ type
ElnaTreeNode = record ElnaTreeNode = record
kind: Word kind: Word
end; end;
ElnaTreeExpression = record
kind: Word;
type_decoration: Word
end;
ElnaTreeIntegerLiteral = record ElnaTreeIntegerLiteral = record
kind: Word; kind: Word;
type_decoration: Word; type_decoration: Word;
@@ -1581,7 +1585,7 @@ begin
ElnaTreeNode_set_kind(result, ElnaTreeKind.integer_literal); ElnaTreeNode_set_kind(result, ElnaTreeKind.integer_literal);
ElnaTreeIntegerLiteral_set_value(result, integer_token); ElnaTreeIntegerLiteral_set_value(result, integer_token);
ElnaTreeIntegerLiteral_set_length(result, integer_length); ElnaTreeIntegerLiteral_set_length(result, integer_length);
ElnaTreeIntegerLiteral_set_type_decoration(result, nil); ElnaTreeExpression_set_type_decoration(result, nil);
return result return result
end; end;
@@ -1594,7 +1598,7 @@ begin
result := malloc(ElnaTreeNilLiteral_size()); result := malloc(ElnaTreeNilLiteral_size());
ElnaTreeNode_set_kind(result, ElnaTreeKind.null); ElnaTreeNode_set_kind(result, ElnaTreeKind.null);
ElnaTreeIntegerLiteral_set_type_decoration(result, nil); ElnaTreeExpression_set_type_decoration(result, nil);
return result return result
end; end;
@@ -1633,7 +1637,7 @@ begin
ElnaTreeNode_set_kind(result, ElnaTreeKind.character_literal); ElnaTreeNode_set_kind(result, ElnaTreeKind.character_literal);
ElnaTreeIntegerLiteral_set_value(result, character); ElnaTreeIntegerLiteral_set_value(result, character);
ElnaTreeIntegerLiteral_set_length(result, character_length); ElnaTreeIntegerLiteral_set_length(result, character_length);
ElnaTreeIntegerLiteral_set_type_decoration(result, nil); ElnaTreeExpression_set_type_decoration(result, nil);
return result return result
end; end;
@@ -1662,7 +1666,7 @@ begin
ElnaTreeNode_set_kind(result, ElnaTreeKind.variable_expression); ElnaTreeNode_set_kind(result, ElnaTreeKind.variable_expression);
ElnaTreeVariableExpression_set_name(result, name_pointer); ElnaTreeVariableExpression_set_name(result, name_pointer);
ElnaTreeVariableExpression_set_length(result, name_length); ElnaTreeVariableExpression_set_length(result, name_length);
ElnaTreeVariableExpression_set_type_decoration(result, nil); ElnaTreeExpression_set_type_decoration(result, nil);
return result return result
end; end;
@@ -1704,7 +1708,7 @@ begin
ElnaTreeNode_set_kind(result, ElnaTreeKind.string_literal); ElnaTreeNode_set_kind(result, ElnaTreeKind.string_literal);
ElnaTreeStringLiteral_set_value(result, token_start); ElnaTreeStringLiteral_set_value(result, token_start);
ElnaTreeStringLiteral_set_length(result, length); ElnaTreeStringLiteral_set_length(result, length);
ElnaTreeIntegerLiteral_set_type_decoration(result, nil); ElnaTreeExpression_set_type_decoration(result, nil);
return result return result
end; end;
@@ -1767,7 +1771,7 @@ begin
ElnaTreeNode_set_kind(result, ElnaTreeKind.dereference_expression); ElnaTreeNode_set_kind(result, ElnaTreeKind.dereference_expression);
ElnaTreeDereferenceExpression_set_pointer(result, simple_expression); ElnaTreeDereferenceExpression_set_pointer(result, simple_expression);
ElnaTreeDereferenceExpression_set_type_decoration(result, nil); ElnaTreeExpression_set_type_decoration(result, nil);
_elna_lexer_skip_token(); _elna_lexer_skip_token();
return result return result
@@ -1842,7 +1846,7 @@ begin
ElnaTreeNode_set_kind(result, ElnaTreeKind.unary_expression); ElnaTreeNode_set_kind(result, ElnaTreeKind.unary_expression);
ElnaTreeUnaryExpression_set_operand(result, operand); ElnaTreeUnaryExpression_set_operand(result, operand);
ElnaTreeUnaryExpression_set_operator(result, operator); ElnaTreeUnaryExpression_set_operator(result, operator);
ElnaTreeUnaryExpression_set_type_decoration(result, nil) ElnaTreeExpression_set_type_decoration(result, nil)
end; end;
return result return result
@@ -1986,7 +1990,7 @@ begin
ElnaTreeBinaryExpression_set_lhs(result, lhs_node); ElnaTreeBinaryExpression_set_lhs(result, lhs_node);
ElnaTreeBinaryExpression_set_rhs(result, rhs_node); ElnaTreeBinaryExpression_set_rhs(result, rhs_node);
ElnaTreeBinaryExpression_set_operator(result, token_kind); ElnaTreeBinaryExpression_set_operator(result, token_kind);
ElnaTreeBinaryExpression_set_type_decoration(result, nil) ElnaTreeExpression_set_type_decoration(result, nil)
else else
result := lhs_node result := lhs_node
end; end;
@@ -2368,7 +2372,7 @@ begin
operand_value^ := counter; operand_value^ := counter;
operand_length^ := 0 operand_length^ := 0
end; end;
return 0 return nil
end; end;
proc elna_parser_field_access_expression(aggregate: Word); proc elna_parser_field_access_expression(aggregate: Word);
@@ -2392,7 +2396,7 @@ begin
ElnaTreeFieldAccessExpression_set_aggregate(result, aggregate); ElnaTreeFieldAccessExpression_set_aggregate(result, aggregate);
ElnaTreeFieldAccessExpression_set_field(result, name_pointer); ElnaTreeFieldAccessExpression_set_field(result, name_pointer);
ElnaTreeFieldAccessExpression_set_length(result, name_length); ElnaTreeFieldAccessExpression_set_length(result, name_length);
ElnaTreeFieldAccessExpression_set_type_decoration(result, nil); ElnaTreeExpression_set_type_decoration(result, nil);
return result return result
end; end;
@@ -2401,8 +2405,12 @@ proc _elna_tac_designator(parser_node: Word, symbol_table: Word, is_address: Wor
var var
parser_node: Word; parser_node: Word;
node_kind: Word; node_kind: Word;
expression_type: Word;
first_instruction: Word; first_instruction: Word;
last_instruction: Word; last_instruction: Word;
name_pointer: Word;
name_length: Word;
begin begin
node_kind := ElnaTreeNode_get_kind(parser_node); node_kind := ElnaTreeNode_get_kind(parser_node);
@@ -2421,7 +2429,26 @@ begin
is_address^ := 2; is_address^ := 2;
first_instruction := elna_instruction_list_concatenate(first_instruction, last_instruction) first_instruction := elna_instruction_list_concatenate(first_instruction, last_instruction)
elsif node_kind = ElnaTreeKind.field_access_expression then elsif node_kind = ElnaTreeKind.field_access_expression then
first_instruction := _elna_tac_enumeration_value(parser_node, operand_type, operand_value, operand_length); expression_type := ElnaTreeExpression_get_type_decoration(parser_node);
name_pointer := ElnaTreeFieldAccessExpression_get_field(parser_node);
name_length := ElnaTreeFieldAccessExpression_get_length(parser_node);
if expression_type = nil then
(* Stub for record field access. Always generate nil for field access expression until it is implemented. *)
(* Debug. Error stream output.
_syscall(2, name_pointer, name_length, 0, 0, 0, 64);
printf("# there %.*s %i\n\0", name_length, name_pointer, expression_type);
fflush(0); *)
operand_type^ := ElnaTacOperand.immediate;
operand_value^ := 0;
operand_length^ := 0;
first_instruction := nil
else
first_instruction := _elna_tac_enumeration_value(parser_node, operand_type, operand_value, operand_length)
end;
is_address^ := 0 is_address^ := 0
elsif node_kind = ElnaTreeKind.call then elsif node_kind = ElnaTreeKind.call then
first_instruction := _elna_tac_call(parser_node, symbol_table); first_instruction := _elna_tac_call(parser_node, symbol_table);
@@ -3241,8 +3268,9 @@ end;
(** (**
* Parameters: * Parameters:
* parameter_index - Parameter index. * parameter_index - Parameter index.
* parameter_type - Parameter type.
*) *)
proc _parameter_info_create(parameter_index: Word); proc _parameter_info_create(parameter_index: Word, parameter_type: Word);
var var
offset: Word; offset: Word;
result: Word; result: Word;
@@ -3253,6 +3281,7 @@ begin
(* Calculate the stack offset: 104 - (4 * parameter_counter) *) (* Calculate the stack offset: 104 - (4 * parameter_counter) *)
offset := parameter_index * 4; offset := parameter_index * 4;
_parameter_info_set_offset(result, 104 - offset); _parameter_info_set_offset(result, 104 - offset);
_parameter_info_set_variable_type(result, parameter_type);
return result return result
end; end;
@@ -3270,9 +3299,10 @@ end;
(** (**
* Parameters: * Parameters:
* temporary_index - Parameter index. * temporary_index - Local variable index.
* temporary_type - Local variable type.
*) *)
proc _temporary_info_create(temporary_index: Word); proc _temporary_info_create(temporary_index: Word, temporary_type: Word);
var var
result: Word; result: Word;
begin begin
@@ -3281,6 +3311,7 @@ begin
(* Calculate the stack offset: 4 * variable_counter. *) (* Calculate the stack offset: 4 * variable_counter. *)
_temporary_info_set_offset(result, temporary_index * 4); _temporary_info_set_offset(result, temporary_index * 4);
_parameter_info_set_variable_type(result, temporary_type);
return result return result
end; end;
@@ -3309,11 +3340,15 @@ var
name_length: Word; name_length: Word;
info: Word; info: Word;
name_position: Word; name_position: Word;
variable_type: Word;
begin begin
name_position := _declaration_get_name(parser_node); name_position := _declaration_get_name(parser_node);
name_length := _declaration_get_length(parser_node); name_length := _declaration_get_length(parser_node);
info := _parameter_info_create(parameter_index); variable_type := _variable_declaration_get__type(parser_node);
variable_type := elna_name_type_expression(variable_type);
info := _parameter_info_create(parameter_index, variable_type);
_symbol_table_enter(symbol_table, name_position, name_length, info) _symbol_table_enter(symbol_table, name_position, name_length, info)
end; end;
@@ -3326,11 +3361,15 @@ var
name_length: Word; name_length: Word;
info: Word; info: Word;
name_position: Word; name_position: Word;
variable_type: Word;
begin begin
name_position := _declaration_get_name(parser_node); name_position := _declaration_get_name(parser_node);
name_length := _declaration_get_length(parser_node); name_length := _declaration_get_length(parser_node);
info := _temporary_info_create(variable_index); variable_type := _variable_declaration_get__type(parser_node);
variable_type := elna_name_type_expression(variable_type);
info := _temporary_info_create(variable_index, variable_type);
_symbol_table_enter(symbol_table, name_position, name_length, info) _symbol_table_enter(symbol_table, name_position, name_length, info)
end; end;
@@ -4191,7 +4230,7 @@ begin
goto elna_type_if_statement_conditionals goto elna_type_if_statement_conditionals
end; end;
block := _if_statement_get__else(parser_node); block := _if_statement_get__else(parser_node);
if block <> 0 then if block <> nil then
elna_type_statements(block, symbol_table) elna_type_statements(block, symbol_table)
end end
end; end;
@@ -4230,8 +4269,8 @@ begin
lhs := _assign_statement_get_assignee(parser_node); lhs := _assign_statement_get_assignee(parser_node);
rhs := _assign_statement_get_assignment(parser_node); rhs := _assign_statement_get_assignment(parser_node);
elna_type_designator(parser_node, symbol_table); elna_type_designator(lhs, symbol_table);
elna_type_binary_expression(parser_node, symbol_table) elna_type_binary_expression(rhs, symbol_table)
end; end;
proc elna_type_statement(parser_node: Word, symbol_table: Word); proc elna_type_statement(parser_node: Word, symbol_table: Word);
@@ -4271,7 +4310,7 @@ begin
symbol_info := _symbol_table_lookup(@symbol_table_global, "Word", 4); symbol_info := _symbol_table_lookup(@symbol_table_global, "Word", 4);
symbol_type := _type_info_get__type(symbol_info); symbol_type := _type_info_get__type(symbol_info);
ElnaTreeCharacterLiteral_set_type_decoration(parser_node, symbol_type) ElnaTreeExpression_set_type_decoration(parser_node, symbol_type)
end; end;
proc elna_type_integer_literal(parser_node: Word); proc elna_type_integer_literal(parser_node: Word);
@@ -4282,7 +4321,7 @@ begin
symbol_info := _symbol_table_lookup(@symbol_table_global, "Word", 4); symbol_info := _symbol_table_lookup(@symbol_table_global, "Word", 4);
symbol_type := _type_info_get__type(symbol_info); symbol_type := _type_info_get__type(symbol_info);
ElnaTreeIntegerLiteral_set_type_decoration(parser_node, symbol_type) ElnaTreeExpression_set_type_decoration(parser_node, symbol_type)
end; end;
proc elna_type_string_literal(parser_node: Word); proc elna_type_string_literal(parser_node: Word);
@@ -4293,7 +4332,7 @@ begin
symbol_info := _symbol_table_lookup(@symbol_table_global, "Word", 4); symbol_info := _symbol_table_lookup(@symbol_table_global, "Word", 4);
symbol_type := _type_info_get__type(symbol_info); symbol_type := _type_info_get__type(symbol_info);
ElnaTreeStringLiteral_set_type_decoration(parser_node, symbol_type) ElnaTreeExpression_set_type_decoration(parser_node, symbol_type)
end; end;
proc elna_type_nil_literal(parser_node: Word); proc elna_type_nil_literal(parser_node: Word);
@@ -4304,7 +4343,7 @@ begin
symbol_info := _symbol_table_lookup(@symbol_table_global, "Word", 4); symbol_info := _symbol_table_lookup(@symbol_table_global, "Word", 4);
symbol_type := _type_info_get__type(symbol_info); symbol_type := _type_info_get__type(symbol_info);
ElnaTreeNilLiteral_set_type_decoration(parser_node, symbol_type) ElnaTreeExpression_set_type_decoration(parser_node, symbol_type)
end; end;
proc elna_type_variable_expression(parser_node: Word, symbol_table: Word); proc elna_type_variable_expression(parser_node: Word, symbol_table: Word);
@@ -4313,6 +4352,7 @@ var
name_pointer: Word; name_pointer: Word;
name_length: Word; name_length: Word;
variable_kind: Word; variable_kind: Word;
variable_type: Word;
begin begin
name_pointer := ElnaTreeVariableExpression_get_name(parser_node); name_pointer := ElnaTreeVariableExpression_get_name(parser_node);
name_length := ElnaTreeVariableExpression_get_length(parser_node); name_length := ElnaTreeVariableExpression_get_length(parser_node);
@@ -4322,13 +4362,15 @@ begin
if variable_info = nil then if variable_info = nil then
variable_info := _symbol_table_lookup(@symbol_table_global, name_pointer, name_length) variable_info := _symbol_table_lookup(@symbol_table_global, name_pointer, name_length)
end; end;
variable_kind := _info_get_kind(variable_info);
variable_type := nil;
(* Debug. Error stream output. if variable_kind = InfoKind.parameter_info then
_syscall(2, name_pointer, name_length, 0, 0, 0, 64); variable_type := _parameter_info_get_variable_type(variable_info)
printf("# here %p %.*s\n\0", variable_info, name_length, name_pointer); elsif variable_kind = InfoKind.temporary_info then
fflush(0) variable_type := _temporary_info_get_variable_type(variable_info)
end;
variable_kind := _info_get_kind(variable_info) *) ElnaTreeExpression_set_type_decoration(parser_node, variable_type)
end; end;
proc elna_type_simple_expression(parser_node: Word, symbol_table: Word); proc elna_type_simple_expression(parser_node: Word, symbol_table: Word);
@@ -4353,11 +4395,57 @@ end;
proc elna_type_designator(parser_node: Word, symbol_table: Word); proc elna_type_designator(parser_node: Word, symbol_table: Word);
var var
expression_kind: Word; expression_kind: Word;
designator_base: Word;
base_type: Word;
type_kind: Word;
name_pointer: Word;
name_length: Word;
symbol_info: Word;
begin begin
expression_kind := ElnaTreeNode_get_kind(parser_node); expression_kind := ElnaTreeNode_get_kind(parser_node);
if expression_kind = ElnaTreeKind.dereference_expression then if expression_kind = ElnaTreeKind.dereference_expression then
designator_base := ElnaTreeDereferenceExpression_get_pointer(parser_node);
elna_type_simple_expression(designator_base, symbol_table);
base_type := ElnaTreeExpression_get_type_decoration(designator_base);
type_kind := ElnaType_get_kind(base_type);
(* If check for compatibility, should be removed later. *)
if type_kind = TypeKind.pointer then
base_type := ElnaTypePointer_get_base(base_type)
end;
ElnaTreeExpression_set_type_decoration(parser_node, base_type)
elsif expression_kind = ElnaTreeKind.field_access_expression then elsif expression_kind = ElnaTreeKind.field_access_expression then
base_type := nil;
designator_base := ElnaTreeFieldAccessExpression_get_aggregate(parser_node);
(* Check whether the field access is an enumeration value. *)
if ElnaTreeNode_get_kind(designator_base) = ElnaTreeKind.variable_expression then
name_pointer := ElnaTreeVariableExpression_get_name(designator_base);
name_length := ElnaTreeVariableExpression_get_length(designator_base);
symbol_info := _symbol_table_lookup(@symbol_table_global, name_pointer, name_length);
if symbol_info <> nil then
type_kind := _info_get_kind(symbol_info);
if type_kind = InfoKind.type_info then
base_type := _type_info_get__type(symbol_info)
end
end
end;
(* If the base_type is still nil this is record field access. *)
if base_type = nil then
(* elna_type_simple_expression(designator_base, symbol_table);
base_type := ElnaTreeExpression_get_type_decoration(designator_base); *)
else
end;
(* Change my type. *)
ElnaTreeExpression_set_type_decoration(parser_node, base_type)
elsif expression_kind = ElnaTreeKind.call then
elna_type_call(parser_node, symbol_table)
else else
elna_type_simple_expression(parser_node, symbol_table) elna_type_simple_expression(parser_node, symbol_table)
end end
@@ -4366,10 +4454,17 @@ end;
proc elna_type_unary_expression(parser_node: Word, symbol_table: Word); proc elna_type_unary_expression(parser_node: Word, symbol_table: Word);
var var
expression_kind: Word; expression_kind: Word;
unary_operand: Word;
operand_type: Word;
begin begin
expression_kind := ElnaTreeNode_get_kind(parser_node); expression_kind := ElnaTreeNode_get_kind(parser_node);
if expression_kind = ElnaTreeKind.unary_expression then if expression_kind = ElnaTreeKind.unary_expression then
unary_operand := ElnaTreeUnaryExpression_get_operand(parser_node);
elna_type_designator(unary_operand, symbol_table);
operand_type := ElnaTreeExpression_get_type_decoration(unary_operand);
ElnaTreeExpression_set_type_decoration(parser_node, operand_type)
else else
elna_type_designator(parser_node, symbol_table) elna_type_designator(parser_node, symbol_table)
end end
@@ -4378,10 +4473,21 @@ end;
proc elna_type_binary_expression(parser_node: Word, symbol_table: Word); proc elna_type_binary_expression(parser_node: Word, symbol_table: Word);
var var
expression_kind: Word; expression_kind: Word;
binary_operand: Word;
operand_type: Word;
begin begin
expression_kind := ElnaTreeNode_get_kind(parser_node); expression_kind := ElnaTreeNode_get_kind(parser_node);
if expression_kind = ElnaTreeKind.binary_expression then if expression_kind = ElnaTreeKind.binary_expression then
binary_operand := ElnaTreeBinaryExpression_get_rhs(parser_node);
elna_type_unary_expression(binary_operand, symbol_table);
binary_operand := ElnaTreeBinaryExpression_get_lhs(parser_node);
elna_type_unary_expression(binary_operand, symbol_table);
operand_type := ElnaTreeExpression_get_type_decoration(binary_operand);
ElnaTreeExpression_set_type_decoration(parser_node, operand_type)
else else
elna_type_unary_expression(parser_node, symbol_table) elna_type_unary_expression(parser_node, symbol_table)
end end
@@ -4412,16 +4518,23 @@ var
begin begin
current_part := _module_declaration_get_types(parser_node); current_part := _module_declaration_get_types(parser_node);
.elna_name_module_declaration_type; .elna_name_module_declaration_type;
if current_part <> 0 then if current_part <> nil then
elna_name_type_declaration(current_part); elna_name_type_declaration(current_part);
current_part := _declaration_get_next(current_part); current_part := _declaration_get_next(current_part);
goto elna_name_module_declaration_type goto elna_name_module_declaration_type
end; end;
current_part := _module_declaration_get_globals(parser_node);
.elna_name_module_declaration_global;
if current_part <> nil then
elna_name_procedure_temporary(current_part, 0, @symbol_table_global);
current_part := _declaration_get_next(current_part);
goto elna_name_module_declaration_global
end;
current_part := _module_declaration_get_procedures(parser_node); current_part := _module_declaration_get_procedures(parser_node);
.elna_name_module_declaration_procedure; .elna_name_module_declaration_procedure;
if current_part <> 0 then if current_part <> nil then
elna_name_procedure_declaration(current_part); elna_name_procedure_declaration(current_part);
current_part := _declaration_get_next(current_part); current_part := _declaration_get_next(current_part);

5537
boot/stage17/cl.elna Normal file

File diff suppressed because it is too large Load Diff

0
boot/stage17/linker.arg Normal file
View File