Extend ElnaErrorList to a generic ElnaList

This commit is contained in:
2026-02-22 23:39:50 +01:00
parent b987dd741a
commit 713eff8de1
+151 -183
View File
@@ -8,12 +8,17 @@ program;
(* Stage 20 compiler. *) (* Stage 20 compiler. *)
type type
ElnaListNode = record
next: Word
end;
ElnaList = record
first: ^ElnaListNode;
last: ^ElnaListNode
end;
(** (**
* List of intermediate representation items. * List of intermediate representation items.
*) *)
ElnaInstructionList = record
next: Word
end;
ElnaInstructionModule = record ElnaInstructionModule = record
data: Word; data: Word;
code: Word code: Word
@@ -308,10 +313,6 @@ type
symbol_table: ^ElnaSymbolTable symbol_table: ^ElnaSymbolTable
end; end;
ElnaErrorList = record
first: Word;
last: Word
end;
ElnaError = record ElnaError = record
next: Word next: Word
end; end;
@@ -475,8 +476,7 @@ type
ElnaTacOperand = record ElnaTacOperand = record
kind: ElnaTacKind; kind: ElnaTacKind;
value: Word; value: Word;
length: Word; length: Word
offset: Word
end; end;
ElnaTacInstruction = record ElnaTacInstruction = record
next: Word; next: Word;
@@ -532,8 +532,7 @@ type
ElnaRtlOperand = record ElnaRtlOperand = record
kind: ElnaRtlKind; kind: ElnaRtlKind;
value: Word; value: Word;
length: Word; length: Word
offset: Word
end; end;
ElnaRtlStaticVariable = record ElnaRtlStaticVariable = record
next: Word; next: Word;
@@ -758,6 +757,32 @@ proc _is_alnum(character: Word);
return _is_alpha(character) or isdigit(character) return _is_alpha(character) or isdigit(character)
end; end;
proc elna_list_initialize(list: ^ElnaList);
begin
list^.first := nil;
list^.last := nil
end;
proc elna_list_append(list: ^ElnaList, element: ^ElnaListNode);
begin
if element <> nil then
if list^.first = nil then
list^.first := element
else
list^.last^.next := element
end;
(* TODO: This is a temporary solution for the migration from the old lists. *)
.elna_list_append_loop;
if element^.next = nil then
list^.last := element
else
element := element^.next;
goto elna_list_append_loop
end
end;
return element
end;
proc elna_tac_generate_pseudo(operand_type: Word, operand_value: Word, operand_length: Word, symbol_table: ^ElnaSymbolTable); proc elna_tac_generate_pseudo(operand_type: Word, operand_value: Word, operand_length: Word, symbol_table: ^ElnaSymbolTable);
var var
buffer: Word; buffer: Word;
@@ -776,7 +801,7 @@ begin
elna_symbol_table_enter(symbol_table, buffer, operand_length^, temporary_info) elna_symbol_table_enter(symbol_table, buffer, operand_length^, temporary_info)
end; end;
proc elna_instruction_list_concatenate(this: ^ElnaInstructionList, value: Word); proc elna_instruction_list_concatenate(this: ^ElnaListNode, value: Word);
var var
start: Word; start: Word;
begin begin
@@ -1261,15 +1286,13 @@ begin
return result return result
end; end;
proc elna_tac_label(counter: Word, length: Word); proc elna_tac_label(instructions: ^ElnaList, counter: Word, length: Word);
var var
result: Word; result: Word;
begin begin
result := elna_tac_instruction_create(ElnaTacOperator.label); result := elna_tac_instruction_create(ElnaTacOperator.label);
elna_tac_instruction_set_operand(result, 1, ElnaTacKind.symbol, counter, length); elna_tac_instruction_set_operand(result, 1, ElnaTacKind.symbol, counter, length);
elna_list_append(instructions, result)
return result
end; end;
proc elna_riscv_instruction_name(instruction_kind: Word); proc elna_riscv_instruction_name(instruction_kind: Word);
@@ -2095,7 +2118,7 @@ begin
return result return result
end; end;
proc elna_tac_copy_address(is_address: Word, from_type: Word, from_value: Word, from_length: Word, to_type: Word, to_value: Word, to_length: Word); proc elna_tac_copy_address(is_address: Word, from: ^ElnaTacOperand, to: ^ElnaTacOperand);
var var
instruction: Word; instruction: Word;
begin begin
@@ -2104,23 +2127,21 @@ begin
else else
instruction := elna_tac_instruction_create(ElnaTacOperator.get_address) instruction := elna_tac_instruction_create(ElnaTacOperator.get_address)
end; end;
elna_tac_instruction_set_operand(instruction, 1, to_type, to_value, to_length); elna_tac_instruction_set_operand(instruction, 1, to^.kind, to^.value, to^.length);
elna_tac_instruction_set_operand(instruction, 2, from_type, from_value, from_length); elna_tac_instruction_set_operand(instruction, 2, from^.kind, from^.value, from^.length);
return instruction return instruction
end; end;
proc elna_tac_unary_expression(parser_node: ^ElnaTreeUnaryExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); proc elna_tac_unary_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeUnaryExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
var var
token_kind: Word; token_kind: Word;
operator: Word; operator: Word;
unary_operand: ^ElnaTreeExpression; unary_operand: ^ElnaTreeExpression;
is_address: Word; is_address: Word;
first_instruction: Word;
instruction: Word; instruction: Word;
base: ElnaTacOperand; base: ElnaTacOperand;
begin begin
instruction := nil;
if parser_node^.kind = ElnaTreeKind.unary_expression then if parser_node^.kind = ElnaTreeKind.unary_expression then
operator := parser_node^.operator; operator := parser_node^.operator;
unary_operand := parser_node^.operand unary_operand := parser_node^.operand
@@ -2128,13 +2149,12 @@ begin
operator := 0; operator := 0;
unary_operand := parser_node unary_operand := parser_node
end; end;
first_instruction := elna_tac_designator(unary_operand, symbol_table, @is_address, @base); elna_tac_designator(instructions, unary_operand, symbol_table, @is_address, @base);
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
if operator = '@' then if operator = '@' then
instruction := elna_tac_copy_address(is_address, base.kind, base.value, base.length, instruction := elna_tac_copy_address(is_address, @base, operand)
operand^.kind, operand^.value, operand^.length)
elsif operator = '-' then elsif operator = '-' then
instruction := elna_tac_instruction_create(ElnaTacOperator.negate); instruction := elna_tac_instruction_create(ElnaTacOperator.negate);
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length); elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
@@ -2152,7 +2172,7 @@ begin
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length); elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length) elna_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length)
end; end;
return elna_instruction_list_concatenate(first_instruction, instruction) elna_list_append(instructions, instruction)
end; end;
proc elna_parser_binary_expression(); proc elna_parser_binary_expression();
@@ -2223,7 +2243,7 @@ begin
return result return result
end; end;
proc elna_tac_binary_expression(parser_node: ^ElnaTreeBinaryExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); proc elna_tac_binary_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeBinaryExpression, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
var var
first_instruction: Word; first_instruction: Word;
instruction: Word; instruction: Word;
@@ -2231,11 +2251,10 @@ var
rhs: ElnaTacOperand; rhs: ElnaTacOperand;
begin begin
if parser_node^.kind <> ElnaTreeKind.binary_expression then if parser_node^.kind <> ElnaTreeKind.binary_expression then
first_instruction := elna_tac_unary_expression(parser_node, symbol_table, operand) elna_tac_unary_expression(instructions, parser_node, symbol_table, operand)
else else
first_instruction := elna_tac_unary_expression(parser_node^.lhs, symbol_table, @lhs); elna_tac_unary_expression(instructions, parser_node^.lhs, symbol_table, @lhs);
instruction := elna_tac_unary_expression(parser_node^.rhs, symbol_table, @rhs); elna_tac_unary_expression(instructions, parser_node^.rhs, symbol_table, @rhs);
first_instruction := elna_instruction_list_concatenate(first_instruction, instruction);
if parser_node^.operator = ElnaLexerKind.plus then if parser_node^.operator = ElnaLexerKind.plus then
instruction := elna_tac_instruction_create(ElnaTacOperator.add) instruction := elna_tac_instruction_create(ElnaTacOperator.add)
@@ -2272,9 +2291,9 @@ begin
elna_tac_instruction_set_operand(instruction, 2, lhs.kind, lhs.value, lhs.length); elna_tac_instruction_set_operand(instruction, 2, lhs.kind, lhs.value, lhs.length);
elna_tac_instruction_set_operand(instruction, 3, rhs.kind, rhs.value, rhs.length); elna_tac_instruction_set_operand(instruction, 3, rhs.kind, rhs.value, rhs.length);
first_instruction := elna_instruction_list_concatenate(first_instruction, instruction) elna_list_append(instructions, instruction)
end; end;
return first_instruction return instructions^.first
end; end;
proc elna_parser_call(callee: Word); proc elna_parser_call(callee: Word);
@@ -2327,18 +2346,15 @@ begin
return result return result
end; end;
proc elna_tac_call(parsed_call: ^ElnaTreeCall, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand); proc elna_tac_call(instructions: ^ElnaList, parsed_call: ^ElnaTreeCall, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
var var
parsed_expression: ^ElnaTreeVariableExpression; parsed_expression: ^ElnaTreeVariableExpression;
instruction: Word; instruction: Word;
first_instruction: Word;
current_instruction: Word;
arguments_operand: ^ElnaTacOperand; arguments_operand: ^ElnaTacOperand;
call_instruction: Word; call_instruction: Word;
argument_entry: ^ElnaTreeExpressionList; argument_entry: ^ElnaTreeExpressionList;
begin begin
parsed_expression := parsed_call^.callee; parsed_expression := parsed_call^.callee;
first_instruction := nil;
arguments_operand := malloc(parsed_call^.count * #size(ElnaTacOperand)); arguments_operand := malloc(parsed_call^.count * #size(ElnaTacOperand));
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
@@ -2352,26 +2368,13 @@ begin
.elna_tac_call_loop; .elna_tac_call_loop;
if argument_entry <> nil then if argument_entry <> nil then
instruction := elna_tac_binary_expression(argument_entry^.expression, symbol_table, arguments_operand); instruction := elna_tac_binary_expression(instructions, argument_entry^.expression, symbol_table, arguments_operand);
if first_instruction = nil then
first_instruction := instruction
else
elna_instruction_list_concatenate(current_instruction, instruction)
end;
if instruction <> nil then
current_instruction := instruction
end;
arguments_operand := arguments_operand + #size(ElnaTacOperand); arguments_operand := arguments_operand + #size(ElnaTacOperand);
argument_entry := argument_entry^.next; argument_entry := argument_entry^.next;
goto elna_tac_call_loop goto elna_tac_call_loop
end; end;
if first_instruction = nil then elna_list_append(instructions, call_instruction)
first_instruction := call_instruction
else
elna_instruction_list_concatenate(current_instruction, call_instruction)
end;
return first_instruction
end; end;
proc elna_parser_goto_statement(); proc elna_parser_goto_statement();
@@ -2393,21 +2396,21 @@ begin
return result return result
end; end;
proc elna_tac_goto_statement(parser_node: ^ElnaTreeGotoStatement); proc elna_tac_goto_statement(instructions: ^ElnaList, parser_node: ^ElnaTreeGotoStatement);
var var
label_length1: Word; label_length: Word;
label_with_dot1: Word; label_with_dot: Word;
instruction1: Word; instruction: Word;
begin begin
label_length1 := parser_node^.length + 1; label_length := parser_node^.length + 1;
label_with_dot1 := malloc(label_length1); label_with_dot := malloc(label_length);
_store_byte('.', label_with_dot1); _store_byte('.', label_with_dot);
memcpy(label_with_dot1 + 1, parser_node^.label, parser_node^.length); memcpy(label_with_dot + 1, parser_node^.label, parser_node^.length);
instruction1 := elna_tac_instruction_create(ElnaTacOperator.jump); instruction := elna_tac_instruction_create(ElnaTacOperator.jump);
elna_tac_instruction_set_operand(instruction1, 1, ElnaTacKind.symbol, label_with_dot1, label_length1); elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.symbol, label_with_dot, label_length);
return instruction1 elna_list_append(instructions, instruction)
end; end;
proc elna_parser_label_declaration(); proc elna_parser_label_declaration();
@@ -2430,8 +2433,9 @@ begin
return result return result
end; end;
proc elna_tac_label_declaration(parser_node: ^ElnaTreeLabelDeclaration); proc elna_tac_label_declaration(instructions: ^ElnaList, parser_node: ^ElnaTreeLabelDeclaration);
return elna_tac_label(parser_node^.label, parser_node^.length) begin
elna_tac_label(instructions, parser_node^.label, parser_node^.length)
end; end;
proc elna_tac_enumeration_value(field_access_expression: ^ElnaTreeFieldAccessExpression, operand: ^ElnaTacOperand); proc elna_tac_enumeration_value(field_access_expression: ^ElnaTreeFieldAccessExpression, operand: ^ElnaTacOperand);
@@ -2525,8 +2529,11 @@ var
result_instructions: Word; result_instructions: Word;
load_instruction: Word; load_instruction: Word;
is_address: Word; is_address: Word;
body: ElnaList;
begin begin
result_instructions := elna_tac_designator(dereference_expression^.pointer, symbol_table, @is_address, operand); elna_list_initialize(@body);
elna_tac_designator(@body, dereference_expression^.pointer, symbol_table, @is_address, operand);
result_instructions := body.first;
if is_address = true then if is_address = true then
load_instruction := elna_tac_instruction_create(ElnaTacOperator.load); load_instruction := elna_tac_instruction_create(ElnaTacOperator.load);
@@ -2538,7 +2545,7 @@ begin
return result_instructions return result_instructions
end; end;
proc elna_tac_designator(parser_node: ^ElnaTreeExpression, symbol_table: ElnaSymbolTable, is_address: Word, operand: ^ElnaTacOperand); proc elna_tac_designator(instructions: ^ElnaList, parser_node: ^ElnaTreeExpression, symbol_table: ElnaSymbolTable, is_address: Word, operand: ^ElnaTacOperand);
var var
field_access_expression: ^ElnaTreeFieldAccessExpression; field_access_expression: ^ElnaTreeFieldAccessExpression;
result_instructions: Word; result_instructions: Word;
@@ -2546,6 +2553,7 @@ var
begin begin
if parser_node^.kind = ElnaTreeKind.dereference_expression then if parser_node^.kind = ElnaTreeKind.dereference_expression then
result_instructions := elna_tac_dereference_expression(parser_node, symbol_table, operand); result_instructions := elna_tac_dereference_expression(parser_node, symbol_table, operand);
elna_list_append(instructions, result_instructions);
is_address^ := true is_address^ := true
elsif parser_node^.kind = ElnaTreeKind.field_access_expression then elsif parser_node^.kind = ElnaTreeKind.field_access_expression then
field_access_expression := parser_node; field_access_expression := parser_node;
@@ -2558,17 +2566,19 @@ begin
result_instructions := elna_tac_field_access_expression(field_access_expression, symbol_table, operand); result_instructions := elna_tac_field_access_expression(field_access_expression, symbol_table, operand);
is_address^ := true is_address^ := true
end; end;
elna_list_append(instructions, result_instructions)
elsif parser_node^.kind = ElnaTreeKind.array_access_expression then elsif parser_node^.kind = ElnaTreeKind.array_access_expression then
result_instructions := elna_tac_array_access_expression(parser_node, symbol_table, operand); result_instructions := elna_tac_array_access_expression(parser_node, symbol_table, operand);
elna_list_append(instructions, result_instructions);
is_address^ := true is_address^ := true
elsif parser_node^.kind = ElnaTreeKind.call then elsif parser_node^.kind = ElnaTreeKind.call then
result_instructions := elna_tac_call(parser_node, symbol_table, operand); elna_tac_call(instructions, parser_node, symbol_table, operand);
is_address^ := false is_address^ := false
else else
result_instructions := elna_tac_simple_expression(parser_node, symbol_table, operand); result_instructions := elna_tac_simple_expression(parser_node, symbol_table, operand);
elna_list_append(instructions, result_instructions);
is_address^ := false is_address^ := false
end; end
return result_instructions
end; end;
proc elna_tac_field_access_expression(field_access_expression: ^ElnaTreeFieldAccessExpression, proc elna_tac_field_access_expression(field_access_expression: ^ElnaTreeFieldAccessExpression,
@@ -2584,11 +2594,14 @@ var
field_offset: Word; field_offset: Word;
is_address: Word; is_address: Word;
base: ElnaTacOperand; base: ElnaTacOperand;
body: ElnaList;
begin begin
designator_base := field_access_expression^.aggregate; designator_base := field_access_expression^.aggregate;
aggregate_type := designator_base^.type_decoration; aggregate_type := designator_base^.type_decoration;
first_instruction := elna_tac_designator(designator_base, symbol_table, @is_address, @base); elna_list_initialize(@body);
elna_tac_designator(@body, designator_base, symbol_table, @is_address, @base);
first_instruction := body.first;
field_count := aggregate_type^.length; field_count := aggregate_type^.length;
current_field := aggregate_type^.members; current_field := aggregate_type^.members;
@@ -2605,7 +2618,7 @@ begin
end; end;
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
last_instruction := elna_tac_copy_address(is_address, base.kind, base.value, base.length, operand^.kind, operand^.value, operand^.length); last_instruction := elna_tac_copy_address(is_address, @base, operand);
first_instruction := elna_instruction_list_concatenate(first_instruction, last_instruction); first_instruction := elna_instruction_list_concatenate(first_instruction, last_instruction);
last_instruction := elna_tac_instruction_create(ElnaTacOperator.add); last_instruction := elna_tac_instruction_create(ElnaTacOperator.add);
@@ -2631,12 +2644,14 @@ var
aggregate_type: ^ElnaTypeArray; aggregate_type: ^ElnaTypeArray;
designator_base: ^ElnaTreeExpression; designator_base: ^ElnaTreeExpression;
element_type: ^ElnaType; element_type: ^ElnaType;
body: ElnaList;
begin begin
designator_base := array_access_expression^.array; designator_base := array_access_expression^.array;
aggregate_type := designator_base^.type_decoration; aggregate_type := designator_base^.type_decoration;
element_type := aggregate_type^.base; element_type := aggregate_type^.base;
index_instructions := elna_tac_binary_expression(array_access_expression^.index, symbol_table, @inter_operand); elna_list_initialize(@body);
index_instructions := elna_tac_binary_expression(@body, array_access_expression^.index, symbol_table, @inter_operand);
elna_tac_generate_pseudo(@index_type, @index_value, @index_length, symbol_table); elna_tac_generate_pseudo(@index_type, @index_value, @index_length, symbol_table);
add_instruction := elna_tac_instruction_create(ElnaTacOperator.subtract); add_instruction := elna_tac_instruction_create(ElnaTacOperator.subtract);
@@ -2652,12 +2667,13 @@ begin
elna_instruction_list_concatenate(add_instruction, offset_instruction); elna_instruction_list_concatenate(add_instruction, offset_instruction);
index_instructions := elna_instruction_list_concatenate(index_instructions, add_instruction); index_instructions := elna_instruction_list_concatenate(index_instructions, add_instruction);
array_instructions := elna_tac_designator(array_access_expression^.array, symbol_table, @is_address, @inter_operand); elna_list_initialize(@body);
elna_tac_designator(@body, array_access_expression^.array, symbol_table, @is_address, @inter_operand);
array_instructions := body.first;
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table); elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
elna_instruction_list_concatenate(offset_instruction, array_instructions); elna_instruction_list_concatenate(offset_instruction, array_instructions);
array_instructions := elna_tac_copy_address(is_address, inter_operand.kind, inter_operand.value, inter_operand.length, array_instructions := elna_tac_copy_address(is_address, @inter_operand, operand);
operand^.kind, operand^.value, operand^.length);
elna_instruction_list_concatenate(offset_instruction, array_instructions); elna_instruction_list_concatenate(offset_instruction, array_instructions);
add_instruction := elna_tac_instruction_create(ElnaTacOperator.add); add_instruction := elna_tac_instruction_create(ElnaTacOperator.add);
@@ -2688,70 +2704,60 @@ begin
return result return result
end; end;
proc elna_tac_assign_statement(parser_tree: ^ElnaTreeAssignStatement, symbol_table: ^ElnaSymbolTable); proc elna_tac_assign_statement(instructions: ^ElnaList, parser_tree: ^ElnaTreeAssignStatement, symbol_table: ^ElnaSymbolTable);
var var
is_address: Word; is_address: Word;
first_instruction: Word;
instruction: Word; instruction: Word;
current_instruction: Word;
operand_type: Word; operand_type: Word;
operand_value: Word; operand_value: Word;
operand_length: Word; operand_length: Word;
assignment_operand: ElnaTacOperand; assignment_operand: ElnaTacOperand;
assignee: ElnaTacOperand; assignee: ElnaTacOperand;
begin begin
first_instruction := elna_tac_designator(parser_tree^.assignee, symbol_table, @is_address, @assignee); elna_tac_designator(instructions, parser_tree^.assignee, symbol_table, @is_address, @assignee);
(* Compile the assignment. *) (* Compile the assignment. *)
instruction := elna_tac_binary_expression(parser_tree^.assignment, symbol_table, @assignment_operand); instruction := elna_tac_binary_expression(instructions, parser_tree^.assignment, symbol_table, @assignment_operand);
if assignee.kind = ElnaTacKind.pseudo then if assignee.kind = ElnaTacKind.pseudo then
current_instruction := elna_tac_instruction_create(ElnaTacOperator.copy); instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
if is_address then if is_address then
elna_tac_generate_pseudo(@operand_type, @operand_value, @operand_length, symbol_table); elna_tac_generate_pseudo(@operand_type, @operand_value, @operand_length, symbol_table);
(* Save the assignee address on the stack. *) (* Save the assignee address on the stack. *)
elna_tac_instruction_set_operand(current_instruction, 1, operand_type, operand_value, operand_length); elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length);
elna_tac_instruction_set_operand(current_instruction, 2, assignee.kind, assignee.value, assignee.length); elna_tac_instruction_set_operand(instruction, 2, assignee.kind, assignee.value, assignee.length);
first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction);
if instruction <> nil then elna_list_append(instructions, instruction);
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction
end;
instruction := elna_tac_instruction_create(ElnaTacOperator.store); instruction := elna_tac_instruction_create(ElnaTacOperator.store);
elna_tac_instruction_set_operand(instruction, 1, assignment_operand.kind, assignment_operand.value, assignment_operand.length); elna_tac_instruction_set_operand(instruction, 1, assignment_operand.kind, assignment_operand.value, assignment_operand.length);
elna_tac_instruction_set_operand(instruction, 2, operand_type, operand_value, operand_length); elna_tac_instruction_set_operand(instruction, 2, operand_type, operand_value, operand_length);
elna_instruction_list_concatenate(current_instruction, instruction) elna_list_append(instructions, instruction)
else else
elna_tac_instruction_set_operand(current_instruction, 1, assignee.kind, assignee.value, assignee.length); elna_tac_instruction_set_operand(instruction, 1, assignee.kind, assignee.value, assignee.length);
elna_tac_instruction_set_operand(current_instruction, 2, assignment_operand.kind, assignment_operand.value, assignment_operand.length); elna_tac_instruction_set_operand(instruction, 2, assignment_operand.kind, assignment_operand.value, assignment_operand.length);
first_instruction := elna_instruction_list_concatenate(instruction, current_instruction) elna_list_append(instructions, instruction)
end end
else else
elna_tac_generate_pseudo(@operand_type, @operand_value, @operand_length, symbol_table); elna_tac_generate_pseudo(@operand_type, @operand_value, @operand_length, symbol_table);
(* Save the assignee address on the stack. *) (* Save the assignee address on the stack. *)
current_instruction := elna_tac_instruction_create(ElnaTacOperator.get_address); instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
elna_tac_instruction_set_operand(current_instruction, 1, operand_type, operand_value, operand_length); elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length);
elna_tac_instruction_set_operand(current_instruction, 2, assignee.kind, assignee.value, assignee.length); elna_tac_instruction_set_operand(instruction, 2, assignee.kind, assignee.value, assignee.length);
first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction);
if instruction <> nil then elna_list_append(instructions, instruction);
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction
end;
instruction := elna_tac_instruction_create(ElnaTacOperator.store); instruction := elna_tac_instruction_create(ElnaTacOperator.store);
elna_tac_instruction_set_operand(instruction, 1, assignment_operand.kind, assignment_operand.value, assignment_operand.length); elna_tac_instruction_set_operand(instruction, 1, assignment_operand.kind, assignment_operand.value, assignment_operand.length);
elna_tac_instruction_set_operand(instruction, 2, operand_type, operand_value, operand_length); elna_tac_instruction_set_operand(instruction, 2, operand_type, operand_value, operand_length);
elna_instruction_list_concatenate(current_instruction, instruction) elna_list_append(instructions, instruction)
end; end
return first_instruction
end; end;
proc elna_parser_return_statement(); proc elna_parser_return_statement();
@@ -2775,18 +2781,16 @@ begin
return result return result
end; end;
proc elna_tac_return_statement(parser_node: ^ElnaTreeReturnStatement, symbol_table: ^ElnaSymbolTable); proc elna_tac_return_statement(instructions: ^ElnaList, parser_node: ^ElnaTreeReturnStatement, symbol_table: ^ElnaSymbolTable);
var var
first_instruction: Word;
instruction: Word; instruction: Word;
operand: ElnaTacOperand; operand: ElnaTacOperand;
begin begin
first_instruction := elna_tac_binary_expression(parser_node^.returned, symbol_table, @operand); instruction := elna_tac_binary_expression(instructions, parser_node^.returned, symbol_table, @operand);
instruction := elna_tac_instruction_create(ElnaTacOperator._return); instruction := elna_tac_instruction_create(ElnaTacOperator._return);
elna_tac_instruction_set_operand(instruction, 1, operand.kind, operand.value, operand.length); elna_tac_instruction_set_operand(instruction, 1, operand.kind, operand.value, operand.length);
elna_list_append(instructions, instruction)
return elna_instruction_list_concatenate(first_instruction, instruction)
end; end;
(** (**
@@ -2828,41 +2832,32 @@ begin
return result return result
end; end;
proc elna_tac_conditional_statements(parser_node: ^ElnaTreeConditionalStatements, after_end_label: Word, symbol_table: ^ElnaSymbolTable); proc elna_tac_conditional_statements(instructions: ^ElnaList, parser_node: ^ElnaTreeConditionalStatements,
after_end_label: Word, symbol_table: ^ElnaSymbolTable);
var var
condition_label: Word; condition_label: Word;
instruction: Word; instruction: Word;
current_instruction: Word;
first_instruction: Word;
operand: ElnaTacOperand; operand: ElnaTacOperand;
begin begin
(* Compile condition. *) (* Compile condition. *)
first_instruction := elna_tac_binary_expression(parser_node^.condition, symbol_table, @operand); instruction := elna_tac_binary_expression(instructions, parser_node^.condition, symbol_table, @operand);
(* condition_label is the label in front of the next elsif condition or end. *) (* condition_label is the label in front of the next elsif condition or end. *)
condition_label := label_counter; condition_label := label_counter;
label_counter := label_counter + 1; label_counter := label_counter + 1;
current_instruction := elna_tac_instruction_create(ElnaTacOperator.jump_if_zero); instruction := elna_tac_instruction_create(ElnaTacOperator.jump_if_zero);
elna_tac_instruction_set_operand(current_instruction, 1, operand.kind, operand.value, operand.length); elna_tac_instruction_set_operand(instruction, 1, operand.kind, operand.value, operand.length);
elna_tac_instruction_set_operand(current_instruction, 2, ElnaTacKind.symbol, condition_label, 0); elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.symbol, condition_label, 0);
first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction); elna_list_append(instructions, instruction);
elna_tac_statements(instructions, parser_node^.statements, symbol_table);
instruction := elna_tac_statements(parser_node^.statements, symbol_table);
if instruction <> nil then
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction
end;
instruction := elna_tac_instruction_create(ElnaTacOperator.jump); instruction := elna_tac_instruction_create(ElnaTacOperator.jump);
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.symbol, after_end_label, 0); elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.symbol, after_end_label, 0);
elna_instruction_list_concatenate(current_instruction, instruction); elna_list_append(instructions, instruction);
current_instruction := elna_tac_label(condition_label, 0); elna_tac_label(instructions, condition_label, 0)
elna_instruction_list_concatenate(instruction, current_instruction);
return first_instruction
end; end;
proc elna_parser_if_statement(); proc elna_parser_if_statement();
@@ -2961,94 +2956,66 @@ begin
return first_statement return first_statement
end; end;
proc elna_tac_statements(current_statement: ^ElnaTreeStatement, symbol_table: ^ElnaSymbolTable); proc elna_tac_statements(instructions: ^ElnaList, current_statement: ^ElnaTreeStatement, symbol_table: ^ElnaSymbolTable);
var var
instruction: Word; instruction: Word;
first_instruction: Word;
current_instruction: Word;
begin begin
first_instruction := nil;
.elna_tac_statements_loop; .elna_tac_statements_loop;
pseudo_counter := 0; pseudo_counter := 0;
if current_statement <> nil then if current_statement <> nil then
instruction := elna_tac_statement(current_statement, symbol_table); elna_tac_statement(instructions, current_statement, symbol_table);
current_statement := current_statement^.next; current_statement := current_statement^.next;
if instruction = 0 then
goto elna_tac_statements_loop goto elna_tac_statements_loop
end; end;
if first_instruction = nil then return instructions^.first
first_instruction := instruction
else
elna_instruction_list_concatenate(current_instruction, instruction)
end;
current_instruction := instruction;
goto elna_tac_statements_loop
end;
return first_instruction
end; end;
proc elna_tac_if_statement(parser_node: ^ElnaTreeIfStatement, symbol_table: ^ElnaSymbolTable); proc elna_tac_if_statement(instructions: ElnaList, parser_node: ^ElnaTreeIfStatement, symbol_table: ^ElnaSymbolTable);
var var
current_node: ^ElnaTreeConditionalStatements; current_node: ^ElnaTreeConditionalStatements;
after_end_label: Word; after_end_label: Word;
condition_label: Word; condition_label: Word;
first_instruction: Word;
instruction: Word;
current_instruction: Word;
begin begin
after_end_label := label_counter; after_end_label := label_counter;
label_counter := label_counter + 1; label_counter := label_counter + 1;
current_node := parser_node^.conditionals; current_node := parser_node^.conditionals;
first_instruction := elna_tac_conditional_statements(current_node, after_end_label, symbol_table);
current_instruction := first_instruction; elna_tac_conditional_statements(instructions, current_node, after_end_label, symbol_table);
.elna_tac_if_statement_loop; .elna_tac_if_statement_loop;
current_node := current_node^.next; current_node := current_node^.next;
if current_node <> nil then if current_node <> nil then
instruction := elna_tac_conditional_statements(current_node, after_end_label, symbol_table); elna_tac_conditional_statements(instructions, current_node, after_end_label, symbol_table);
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction;
goto elna_tac_if_statement_loop goto elna_tac_if_statement_loop
end; end;
current_node := parser_node^._else; current_node := parser_node^._else;
if parser_node^._else <> nil then if parser_node^._else <> nil then
instruction := elna_tac_statements(parser_node^._else, symbol_table); elna_tac_statements(instructions, parser_node^._else, symbol_table)
if instruction <> 0 then
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction
end
end; end;
instruction := elna_tac_label(after_end_label, 0); elna_tac_label(instructions, after_end_label, 0)
elna_instruction_list_concatenate(current_instruction, instruction);
return first_instruction
end; end;
proc elna_tac_statement(parser_node: ^ElnaTreeNode, symbol_table: ^ElnaSymbolTable); proc elna_tac_statement(instructions: ElnaList, parser_node: ^ElnaTreeNode, symbol_table: ^ElnaSymbolTable);
var var
instruction: Word;
operand: ElnaTacOperand; operand: ElnaTacOperand;
begin begin
if parser_node^.kind = ElnaTreeKind.goto_statement then if parser_node^.kind = ElnaTreeKind.goto_statement then
instruction := elna_tac_goto_statement(parser_node) elna_tac_goto_statement(instructions, parser_node)
elsif parser_node^.kind = ElnaTreeKind.if_statement then elsif parser_node^.kind = ElnaTreeKind.if_statement then
instruction := elna_tac_if_statement(parser_node, symbol_table) elna_tac_if_statement(instructions, parser_node, symbol_table)
elsif parser_node^.kind = ElnaTreeKind.return_statement then elsif parser_node^.kind = ElnaTreeKind.return_statement then
instruction := elna_tac_return_statement(parser_node, symbol_table) elna_tac_return_statement(instructions, parser_node, symbol_table)
elsif parser_node^.kind = ElnaTreeKind.label_declaration then elsif parser_node^.kind = ElnaTreeKind.label_declaration then
instruction := elna_tac_label_declaration(parser_node) elna_tac_label_declaration(instructions, parser_node)
elsif parser_node^.kind = ElnaTreeKind.call then elsif parser_node^.kind = ElnaTreeKind.call then
instruction := elna_tac_call(parser_node, symbol_table, @operand) elna_tac_call(instructions, parser_node, symbol_table, @operand)
elsif parser_node^.kind = ElnaTreeKind.assign_statement then elsif parser_node^.kind = ElnaTreeKind.assign_statement then
instruction := elna_tac_assign_statement(parser_node, symbol_table) elna_tac_assign_statement(instructions, parser_node, symbol_table)
else end
instruction := nil
end;
return instruction
end; end;
(** (**
@@ -3738,10 +3705,13 @@ var
symbol_info: ^ElnaSymbolProcedureInfo; symbol_info: ^ElnaSymbolProcedureInfo;
result: ^ElnaTacProcedure; result: ^ElnaTacProcedure;
parameter_count: Word; parameter_count: Word;
body: ElnaList;
begin begin
result := malloc(#size(ElnaTacProcedure)); result := malloc(#size(ElnaTacProcedure));
result^.next := nil; result^.next := nil;
elna_list_initialize(@body);
result^.name := parser_node^.name; result^.name := parser_node^.name;
result^.length := parser_node^.length; result^.length := parser_node^.length;
@@ -3751,7 +3721,7 @@ begin
result^.parameters := elna_tac_parameters(parser_node^.parameters, @parameter_count); result^.parameters := elna_tac_parameters(parser_node^.parameters, @parameter_count);
result^.count := parameter_count; result^.count := parameter_count;
result^.body := elna_tac_statements(parser_node^.body, symbol_info^.symbol_table); result^.body := elna_tac_statements(@body, parser_node^.body, symbol_info^.symbol_table);
return result return result
end; end;
@@ -4087,7 +4057,7 @@ begin
return first_variable return first_variable
end; end;
proc elna_parser_module_declaration(error_list: ^ElnaErrorList); proc elna_parser_module_declaration(error_list: ^ElnaList);
var var
parser_node: Word; parser_node: Word;
result: ^ElnaTreeModuleDeclaration; result: ^ElnaTreeModuleDeclaration;
@@ -4480,15 +4450,13 @@ var
parser_node: Word; parser_node: Word;
tac: Word; tac: Word;
rtl: Word; rtl: Word;
error_list: ^ElnaErrorList; error_list: ElnaList;
compiled: Word; compiled: Word;
begin begin
error_list := malloc(#size(ElnaErrorList)); elna_list_initialize(@error_list);
error_list^.first := nil;
error_list^.last := nil;
parser_node := elna_parser_module_declaration(error_list); parser_node := elna_parser_module_declaration(@error_list);
compiled := error_list^.first = nil; compiled := error_list.first = nil;
if compiled then if compiled then
elna_name_module_declaration(parser_node); elna_name_module_declaration(parser_node);