Extend ElnaErrorList to a generic ElnaList

This commit is contained in:
2026-02-22 23:39:50 +01:00
parent b987dd741a
commit c3d4449fc7

View File

@@ -8,12 +8,17 @@ program;
(* Stage 20 compiler. *)
type
ElnaListNode = record
next: Word
end;
ElnaList = record
first: ^ElnaListNode;
last: ^ElnaListNode
end;
(**
* List of intermediate representation items.
*)
ElnaInstructionList = record
next: Word
end;
ElnaInstructionModule = record
data: Word;
code: Word
@@ -308,10 +313,6 @@ type
symbol_table: ^ElnaSymbolTable
end;
ElnaErrorList = record
first: Word;
last: Word
end;
ElnaError = record
next: Word
end;
@@ -475,8 +476,7 @@ type
ElnaTacOperand = record
kind: ElnaTacKind;
value: Word;
length: Word;
offset: Word
length: Word
end;
ElnaTacInstruction = record
next: Word;
@@ -487,7 +487,7 @@ type
next: Word;
name: Word;
length: Word;
body: Word;
body: ElnaList;
parameters: Word;
count: Word;
symbol_table: ^ElnaSymbolTable
@@ -532,8 +532,7 @@ type
ElnaRtlOperand = record
kind: ElnaRtlKind;
value: Word;
length: Word;
offset: Word
length: Word
end;
ElnaRtlStaticVariable = record
next: Word;
@@ -758,6 +757,32 @@ proc _is_alnum(character: Word);
return _is_alpha(character) or isdigit(character)
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);
var
buffer: Word;
@@ -776,7 +801,7 @@ begin
elna_symbol_table_enter(symbol_table, buffer, operand_length^, temporary_info)
end;
proc elna_instruction_list_concatenate(this: ^ElnaInstructionList, value: Word);
proc elna_instruction_list_concatenate(this: ^ElnaListNode, value: Word);
var
start: Word;
begin
@@ -812,7 +837,7 @@ begin
result := malloc(#size(ElnaTacInstruction));
result^.operator := kind;
elna_instruction_list_concatenate(result, nil);
result^.next := nil;
return result
end;
@@ -1261,15 +1286,13 @@ begin
return result
end;
proc elna_tac_label(counter: Word, length: Word);
proc elna_tac_label(instructions: ^ElnaList, counter: Word, length: Word);
var
result: Word;
begin
result := elna_tac_instruction_create(ElnaTacOperator.label);
elna_tac_instruction_set_operand(result, 1, ElnaTacKind.symbol, counter, length);
return result
elna_list_append(instructions, result)
end;
proc elna_riscv_instruction_name(instruction_kind: Word);
@@ -1809,27 +1832,21 @@ proc elna_tac_integer_literal(integer_literal_node: ^ElnaTreeIntegerLiteral, ope
begin
operand^.kind := ElnaTacKind.immediate;
operand^.value := integer_literal_node^.value;
operand^.length := 0;
return nil
operand^.length := 0
end;
proc elna_tac_boolean_literal(boolean_literal_node: ^ElnaTreeBooleanLiteral, operand: ^ElnaTacOperand);
begin
operand^.kind := ElnaTacKind.immediate;
operand^.value := boolean_literal_node^.value;
operand^.length := 0;
return nil
operand^.length := 0
end;
proc elna_tac_nil_literal(nil_node: Word, operand: ^ElnaTacOperand);
begin
operand^.kind := ElnaTacKind.immediate;
operand^.value := 0;
operand^.length := 0;
return nil
operand^.length := 0
end;
proc elna_parser_character_literal();
@@ -1851,9 +1868,7 @@ proc elna_tac_character_literal(character_literal_node: ^ElnaTreeCharacterLitera
begin
operand^.kind := ElnaTacKind.immediate;
operand^.value := character_literal_node^.value;
operand^.length := character_literal_node^.length;
return nil
operand^.length := character_literal_node^.length
end;
proc elna_parser_variable_expression();
@@ -1887,8 +1902,7 @@ begin
operand^.kind := ElnaTacKind.symbol;
operand^.value := variable_expression^.name;
operand^.length := variable_expression^.length
end;
return nil
end
end;
proc elna_parser_string_literal();
@@ -1907,28 +1921,27 @@ begin
return result
end;
proc elna_tac_string_literal(string_literal_node: ^ElnaTreeStringLiteral,
proc elna_tac_string_literal(instructions: ^ElnaList, string_literal_node: ^ElnaTreeStringLiteral,
symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
var
offset: Word;
first_instruction: Word;
next_instruction: Word;
instruction: Word;
begin
offset := _add_string(string_literal_node^.value);
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
first_instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
elna_tac_instruction_set_operand(first_instruction, 1, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(first_instruction, 2, ElnaTacKind.symbol, "strings", 7);
instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.symbol, "strings", 7);
elna_list_append(instructions, instruction);
(* Add offset to the string block pointer. *)
next_instruction := elna_tac_instruction_create(ElnaTacOperator.add);
elna_tac_instruction_set_operand(next_instruction, 1, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(next_instruction, 2, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(next_instruction, 3, ElnaTacKind.immediate, offset, 0);
return elna_instruction_list_concatenate(first_instruction, next_instruction)
instruction := elna_tac_instruction_create(ElnaTacOperator.add);
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(instruction, 3, ElnaTacKind.immediate, offset, 0);
elna_list_append(instructions, instruction)
end;
proc elna_parser_trait_expression();
@@ -2033,31 +2046,27 @@ begin
operand^.kind := ElnaTacKind.immediate;
operand^.value := info_type^.size;
operand^.length := 0;
return nil
operand^.length := 0
end;
proc elna_tac_simple_expression(parser_node: ^ElnaTreeNode, symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
var
instruction: Word;
proc elna_tac_simple_expression(instructions: ^ElnaList, parser_node: ^ElnaTreeNode,
symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
begin
if parser_node^.kind = ElnaTreeKind.character_literal then
instruction := elna_tac_character_literal(parser_node, operand)
elna_tac_character_literal(parser_node, operand)
elsif parser_node^.kind = ElnaTreeKind.string_literal then
instruction := elna_tac_string_literal(parser_node, symbol_table, operand)
elna_tac_string_literal(instructions, parser_node, symbol_table, operand)
elsif parser_node^.kind = ElnaTreeKind.integer_literal then
instruction := elna_tac_integer_literal(parser_node, operand)
elna_tac_integer_literal(parser_node, operand)
elsif parser_node^.kind = ElnaTreeKind.boolean_literal then
instruction := elna_tac_boolean_literal(parser_node, operand)
elna_tac_boolean_literal(parser_node, operand)
elsif parser_node^.kind = ElnaTreeKind.null then
instruction := elna_tac_nil_literal(parser_node, operand)
elna_tac_nil_literal(parser_node, operand)
elsif parser_node^.kind = ElnaTreeKind.trait_expression then
instruction := elna_tac_trait_expression(parser_node, operand)
elna_tac_trait_expression(parser_node, operand)
else
instruction := elna_tac_variable_expression(parser_node, symbol_table, operand)
end;
return instruction
elna_tac_variable_expression(parser_node, symbol_table, operand)
end
end;
proc elna_parser_unary_expression();
@@ -2095,7 +2104,7 @@ begin
return result
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(instructions: ^ElnaList, is_address: Word, from: ^ElnaTacOperand, to: ^ElnaTacOperand);
var
instruction: Word;
begin
@@ -2104,23 +2113,21 @@ begin
else
instruction := elna_tac_instruction_create(ElnaTacOperator.get_address)
end;
elna_tac_instruction_set_operand(instruction, 1, to_type, to_value, to_length);
elna_tac_instruction_set_operand(instruction, 2, from_type, from_value, from_length);
elna_tac_instruction_set_operand(instruction, 1, to^.kind, to^.value, to^.length);
elna_tac_instruction_set_operand(instruction, 2, from^.kind, from^.value, from^.length);
return instruction
elna_list_append(instructions, instruction)
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
token_kind: Word;
operator: Word;
unary_operand: ^ElnaTreeExpression;
is_address: Word;
first_instruction: Word;
instruction: Word;
base: ElnaTacOperand;
begin
instruction := nil;
if parser_node^.kind = ElnaTreeKind.unary_expression then
operator := parser_node^.operator;
unary_operand := parser_node^.operand
@@ -2128,31 +2135,33 @@ begin
operator := 0;
unary_operand := parser_node
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);
if operator = '@' then
instruction := elna_tac_copy_address(is_address, base.kind, base.value, base.length,
operand^.kind, operand^.value, operand^.length)
elna_tac_copy_address(instructions, is_address, @base, operand)
elsif operator = '-' then
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, 2, base.kind, base.value, base.length)
elna_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length);
elna_list_append(instructions, instruction)
elsif operator = '~' then
instruction := elna_tac_instruction_create(ElnaTacOperator.complement);
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);
elna_list_append(instructions, instruction)
elsif is_address then
instruction := elna_tac_instruction_create(ElnaTacOperator.load);
elna_tac_instruction_set_operand(instruction, 1, base.kind, base.value, base.length);
elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length)
elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length);
elna_list_append(instructions, instruction)
else
instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
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)
end;
return elna_instruction_list_concatenate(first_instruction, instruction)
elna_tac_instruction_set_operand(instruction, 2, base.kind, base.value, base.length);
elna_list_append(instructions, instruction)
end
end;
proc elna_parser_binary_expression();
@@ -2223,7 +2232,7 @@ begin
return result
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
first_instruction: Word;
instruction: Word;
@@ -2231,11 +2240,10 @@ var
rhs: ElnaTacOperand;
begin
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
first_instruction := elna_tac_unary_expression(parser_node^.lhs, symbol_table, @lhs);
instruction := elna_tac_unary_expression(parser_node^.rhs, symbol_table, @rhs);
first_instruction := elna_instruction_list_concatenate(first_instruction, instruction);
elna_tac_unary_expression(instructions, parser_node^.lhs, symbol_table, @lhs);
elna_tac_unary_expression(instructions, parser_node^.rhs, symbol_table, @rhs);
if parser_node^.operator = ElnaLexerKind.plus then
instruction := elna_tac_instruction_create(ElnaTacOperator.add)
@@ -2272,9 +2280,9 @@ begin
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);
first_instruction := elna_instruction_list_concatenate(first_instruction, instruction)
elna_list_append(instructions, instruction)
end;
return first_instruction
return instructions^.first
end;
proc elna_parser_call(callee: Word);
@@ -2327,18 +2335,14 @@ begin
return result
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
parsed_expression: ^ElnaTreeVariableExpression;
instruction: Word;
first_instruction: Word;
current_instruction: Word;
arguments_operand: ^ElnaTacOperand;
call_instruction: Word;
argument_entry: ^ElnaTreeExpressionList;
begin
parsed_expression := parsed_call^.callee;
first_instruction := nil;
arguments_operand := malloc(parsed_call^.count * #size(ElnaTacOperand));
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
@@ -2352,26 +2356,13 @@ begin
.elna_tac_call_loop;
if argument_entry <> nil then
instruction := elna_tac_binary_expression(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;
elna_tac_binary_expression(instructions, argument_entry^.expression, symbol_table, arguments_operand);
arguments_operand := arguments_operand + #size(ElnaTacOperand);
argument_entry := argument_entry^.next;
goto elna_tac_call_loop
end;
if first_instruction = nil then
first_instruction := call_instruction
else
elna_instruction_list_concatenate(current_instruction, call_instruction)
end;
return first_instruction
elna_list_append(instructions, call_instruction)
end;
proc elna_parser_goto_statement();
@@ -2393,21 +2384,21 @@ begin
return result
end;
proc elna_tac_goto_statement(parser_node: ^ElnaTreeGotoStatement);
proc elna_tac_goto_statement(instructions: ^ElnaList, parser_node: ^ElnaTreeGotoStatement);
var
label_length1: Word;
label_with_dot1: Word;
instruction1: Word;
label_length: Word;
label_with_dot: Word;
instruction: Word;
begin
label_length1 := parser_node^.length + 1;
label_with_dot1 := malloc(label_length1);
label_length := parser_node^.length + 1;
label_with_dot := malloc(label_length);
_store_byte('.', label_with_dot1);
memcpy(label_with_dot1 + 1, parser_node^.label, parser_node^.length);
_store_byte('.', label_with_dot);
memcpy(label_with_dot + 1, parser_node^.label, parser_node^.length);
instruction1 := elna_tac_instruction_create(ElnaTacOperator.jump);
elna_tac_instruction_set_operand(instruction1, 1, ElnaTacKind.symbol, label_with_dot1, label_length1);
return instruction1
instruction := elna_tac_instruction_create(ElnaTacOperator.jump);
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.symbol, label_with_dot, label_length);
elna_list_append(instructions, instruction)
end;
proc elna_parser_label_declaration();
@@ -2430,8 +2421,9 @@ begin
return result
end;
proc elna_tac_label_declaration(parser_node: ^ElnaTreeLabelDeclaration);
return elna_tac_label(parser_node^.label, parser_node^.length)
proc elna_tac_label_declaration(instructions: ^ElnaList, parser_node: ^ElnaTreeLabelDeclaration);
begin
elna_tac_label(instructions, parser_node^.label, parser_node^.length)
end;
proc elna_tac_enumeration_value(field_access_expression: ^ElnaTreeFieldAccessExpression, operand: ^ElnaTacOperand);
@@ -2473,8 +2465,7 @@ begin
operand^.kind := ElnaTacKind.immediate;
operand^.value := counter;
operand^.length := 0
end;
return nil
end
end;
proc elna_parser_field_access_expression(aggregate: Word);
@@ -2519,64 +2510,59 @@ begin
return result
end;
proc elna_tac_dereference_expression(dereference_expression: ^ElnaTreeDereferenceExpression,
proc elna_tac_dereference_expression(instructions: ^ElnaList, dereference_expression: ^ElnaTreeDereferenceExpression,
symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
var
result_instructions: Word;
load_instruction: Word;
is_address: Word;
begin
result_instructions := elna_tac_designator(dereference_expression^.pointer, symbol_table, @is_address, operand);
elna_tac_designator(instructions, dereference_expression^.pointer, symbol_table, @is_address, operand);
if is_address = true then
load_instruction := elna_tac_instruction_create(ElnaTacOperator.load);
elna_tac_instruction_set_operand(load_instruction, 1, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(load_instruction, 2, operand^.kind, operand^.value, operand^.length);
result_instructions := elna_instruction_list_concatenate(result_instructions, load_instruction)
end;
return result_instructions
elna_list_append(instructions, load_instruction)
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
field_access_expression: ^ElnaTreeFieldAccessExpression;
result_instructions: Word;
designator_base: ^ElnaTreeExpression;
begin
if parser_node^.kind = ElnaTreeKind.dereference_expression then
result_instructions := elna_tac_dereference_expression(parser_node, symbol_table, operand);
elna_tac_dereference_expression(instructions, parser_node, symbol_table, operand);
is_address^ := true
elsif parser_node^.kind = ElnaTreeKind.field_access_expression then
field_access_expression := parser_node;
designator_base := field_access_expression^.aggregate;
if designator_base^.type_decoration = nil then
result_instructions := elna_tac_enumeration_value(field_access_expression, operand);
elna_tac_enumeration_value(field_access_expression, operand);
is_address^ := false
else
result_instructions := elna_tac_field_access_expression(field_access_expression, symbol_table, operand);
elna_tac_field_access_expression(instructions, field_access_expression, symbol_table, operand);
is_address^ := true
end;
end
elsif parser_node^.kind = ElnaTreeKind.array_access_expression then
result_instructions := elna_tac_array_access_expression(parser_node, symbol_table, operand);
elna_tac_array_access_expression(instructions, parser_node, symbol_table, operand);
is_address^ := true
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
else
result_instructions := elna_tac_simple_expression(parser_node, symbol_table, operand);
elna_tac_simple_expression(instructions, parser_node, symbol_table, operand);
is_address^ := false
end;
return result_instructions
end
end;
proc elna_tac_field_access_expression(field_access_expression: ^ElnaTreeFieldAccessExpression,
proc elna_tac_field_access_expression(instructions: ^ElnaList, field_access_expression: ^ElnaTreeFieldAccessExpression,
symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
var
field_type: ^ElnaType;
first_instruction: Word;
last_instruction: Word;
instruction: Word;
designator_base: ^ElnaTreeExpression;
aggregate_type: ^ElnaTypeRecord;
field_count: Word;
@@ -2588,7 +2574,7 @@ begin
designator_base := field_access_expression^.aggregate;
aggregate_type := designator_base^.type_decoration;
first_instruction := elna_tac_designator(designator_base, symbol_table, @is_address, @base);
elna_tac_designator(instructions, designator_base, symbol_table, @is_address, @base);
field_count := aggregate_type^.length;
current_field := aggregate_type^.members;
@@ -2604,25 +2590,19 @@ begin
goto elna_tac_field_access_expression_field
end;
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
elna_tac_copy_address(instructions, is_address, @base, operand);
last_instruction := elna_tac_copy_address(is_address, base.kind, base.value, base.length, operand^.kind, operand^.value, operand^.length);
first_instruction := elna_instruction_list_concatenate(first_instruction, last_instruction);
last_instruction := elna_tac_instruction_create(ElnaTacOperator.add);
elna_tac_instruction_set_operand(last_instruction, 1, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(last_instruction, 2, ElnaTacKind.immediate, field_offset, 0);
elna_tac_instruction_set_operand(last_instruction, 3, operand^.kind, operand^.value, operand^.length);
return elna_instruction_list_concatenate(first_instruction, last_instruction)
instruction := elna_tac_instruction_create(ElnaTacOperator.add);
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.immediate, field_offset, 0);
elna_tac_instruction_set_operand(instruction, 3, operand^.kind, operand^.value, operand^.length);
elna_list_append(instructions, instruction)
end;
proc elna_tac_array_access_expression(array_access_expression: ^ElnaTreeArrayAccessExpression,
proc elna_tac_array_access_expression(instructions: ^ElnaList, array_access_expression: ^ElnaTreeArrayAccessExpression,
symbol_table: ^ElnaSymbolTable, operand: ^ElnaTacOperand);
var
array_instructions: Word;
index_instructions: Word;
offset_instruction: Word;
add_instruction: Word;
instruction: Word;
is_address: Word;
inter_operand: ElnaTacOperand;
index_type: Word;
@@ -2636,36 +2616,32 @@ begin
aggregate_type := designator_base^.type_decoration;
element_type := aggregate_type^.base;
index_instructions := elna_tac_binary_expression(array_access_expression^.index, symbol_table, @inter_operand);
elna_tac_binary_expression(instructions, array_access_expression^.index, symbol_table, @inter_operand);
elna_tac_generate_pseudo(@index_type, @index_value, @index_length, symbol_table);
add_instruction := elna_tac_instruction_create(ElnaTacOperator.subtract);
elna_tac_instruction_set_operand(add_instruction, 1, index_type, index_value, index_length);
elna_tac_instruction_set_operand(add_instruction, 2, inter_operand.kind, inter_operand.value, inter_operand.length);
elna_tac_instruction_set_operand(add_instruction, 3, ElnaTacKind.immediate, 1, 0);
instruction := elna_tac_instruction_create(ElnaTacOperator.subtract);
elna_tac_instruction_set_operand(instruction, 1, index_type, index_value, index_length);
elna_tac_instruction_set_operand(instruction, 2, inter_operand.kind, inter_operand.value, inter_operand.length);
elna_tac_instruction_set_operand(instruction, 3, ElnaTacKind.immediate, 1, 0);
elna_list_append(instructions, instruction);
offset_instruction := elna_tac_instruction_create(ElnaTacOperator.multiply);
elna_tac_instruction_set_operand(offset_instruction, 1, index_type, index_value, index_length);
elna_tac_instruction_set_operand(offset_instruction, 2, index_type, index_value, index_length);
elna_tac_instruction_set_operand(offset_instruction, 3, ElnaTacKind.immediate, element_type^.size, 0);
instruction := elna_tac_instruction_create(ElnaTacOperator.multiply);
elna_tac_instruction_set_operand(instruction, 1, index_type, index_value, index_length);
elna_tac_instruction_set_operand(instruction, 2, index_type, index_value, index_length);
elna_tac_instruction_set_operand(instruction, 3, ElnaTacKind.immediate, element_type^.size, 0);
elna_list_append(instructions, instruction);
elna_instruction_list_concatenate(add_instruction, offset_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_tac_designator(instructions, array_access_expression^.array, symbol_table, @is_address, @inter_operand);
elna_tac_generate_pseudo(@operand^.kind, @operand^.value, @operand^.length, symbol_table);
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,
operand^.kind, operand^.value, operand^.length);
elna_instruction_list_concatenate(offset_instruction, array_instructions);
elna_tac_copy_address(instructions, is_address, @inter_operand, operand);
add_instruction := elna_tac_instruction_create(ElnaTacOperator.add);
elna_tac_instruction_set_operand(add_instruction, 1, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(add_instruction, 2, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(add_instruction, 3, index_type, index_value, index_length);
instruction := elna_tac_instruction_create(ElnaTacOperator.add);
elna_tac_instruction_set_operand(instruction, 1, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(instruction, 3, index_type, index_value, index_length);
return elna_instruction_list_concatenate(index_instructions, add_instruction)
elna_list_append(instructions, instruction)
end;
proc elna_parser_assign_statement(assignee: Word);
@@ -2688,70 +2664,60 @@ begin
return result
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
is_address: Word;
first_instruction: Word;
instruction: Word;
current_instruction: Word;
operand_type: Word;
operand_value: Word;
operand_length: Word;
assignment_operand: ElnaTacOperand;
assignee: ElnaTacOperand;
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. *)
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
current_instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
if is_address then
elna_tac_generate_pseudo(@operand_type, @operand_value, @operand_length, symbol_table);
(* 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(current_instruction, 2, assignee.kind, assignee.value, assignee.length);
first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction);
elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length);
elna_tac_instruction_set_operand(instruction, 2, assignee.kind, assignee.value, assignee.length);
if instruction <> nil then
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction
end;
elna_list_append(instructions, instruction);
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, 2, operand_type, operand_value, operand_length);
elna_instruction_list_concatenate(current_instruction, instruction)
elna_list_append(instructions, instruction)
else
elna_tac_instruction_set_operand(current_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, 1, assignee.kind, assignee.value, assignee.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
else
elna_tac_generate_pseudo(@operand_type, @operand_value, @operand_length, symbol_table);
(* Save the assignee address on the stack. *)
current_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(current_instruction, 2, assignee.kind, assignee.value, assignee.length);
first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction);
instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
elna_tac_instruction_set_operand(instruction, 1, operand_type, operand_value, operand_length);
elna_tac_instruction_set_operand(instruction, 2, assignee.kind, assignee.value, assignee.length);
if instruction <> nil then
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction
end;
elna_list_append(instructions, instruction);
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, 2, operand_type, operand_value, operand_length);
elna_instruction_list_concatenate(current_instruction, instruction)
end;
return first_instruction
elna_list_append(instructions, instruction)
end
end;
proc elna_parser_return_statement();
@@ -2775,18 +2741,16 @@ begin
return result
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
first_instruction: Word;
instruction: Word;
operand: ElnaTacOperand;
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);
elna_tac_instruction_set_operand(instruction, 1, operand.kind, operand.value, operand.length);
return elna_instruction_list_concatenate(first_instruction, instruction)
elna_list_append(instructions, instruction)
end;
(**
@@ -2828,41 +2792,32 @@ begin
return result
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
condition_label: Word;
instruction: Word;
current_instruction: Word;
first_instruction: Word;
operand: ElnaTacOperand;
begin
(* 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 := label_counter;
label_counter := label_counter + 1;
current_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(current_instruction, 2, ElnaTacKind.symbol, condition_label, 0);
instruction := elna_tac_instruction_create(ElnaTacOperator.jump_if_zero);
elna_tac_instruction_set_operand(instruction, 1, operand.kind, operand.value, operand.length);
elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.symbol, condition_label, 0);
first_instruction := elna_instruction_list_concatenate(first_instruction, current_instruction);
instruction := elna_tac_statements(parser_node^.statements, symbol_table);
if instruction <> nil then
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction
end;
elna_list_append(instructions, instruction);
elna_tac_statements(instructions, parser_node^.statements, symbol_table);
instruction := elna_tac_instruction_create(ElnaTacOperator.jump);
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_instruction_list_concatenate(instruction, current_instruction);
return first_instruction
elna_tac_label(instructions, condition_label, 0)
end;
proc elna_parser_if_statement();
@@ -2961,94 +2916,63 @@ begin
return first_statement
end;
proc elna_tac_statements(current_statement: ^ElnaTreeStatement, symbol_table: ^ElnaSymbolTable);
var
instruction: Word;
first_instruction: Word;
current_instruction: Word;
proc elna_tac_statements(instructions: ^ElnaList, current_statement: ^ElnaTreeStatement, symbol_table: ^ElnaSymbolTable);
begin
first_instruction := nil;
.elna_tac_statements_loop;
pseudo_counter := 0;
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;
if instruction = 0 then
goto elna_tac_statements_loop
end;
if first_instruction = nil then
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
current_node: ^ElnaTreeConditionalStatements;
after_end_label: Word;
condition_label: Word;
first_instruction: Word;
instruction: Word;
current_instruction: Word;
begin
after_end_label := label_counter;
label_counter := label_counter + 1;
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;
current_node := current_node^.next;
if current_node <> nil then
instruction := elna_tac_conditional_statements(current_node, after_end_label, symbol_table);
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction;
elna_tac_conditional_statements(instructions, current_node, after_end_label, symbol_table);
goto elna_tac_if_statement_loop
end;
current_node := parser_node^._else;
if parser_node^._else <> nil then
instruction := elna_tac_statements(parser_node^._else, symbol_table);
if instruction <> 0 then
elna_instruction_list_concatenate(current_instruction, instruction);
current_instruction := instruction
end
elna_tac_statements(instructions, parser_node^._else, symbol_table)
end;
instruction := elna_tac_label(after_end_label, 0);
elna_instruction_list_concatenate(current_instruction, instruction);
return first_instruction
elna_tac_label(instructions, after_end_label, 0)
end;
proc elna_tac_statement(parser_node: ^ElnaTreeNode, symbol_table: ^ElnaSymbolTable);
proc elna_tac_statement(instructions: ElnaList, parser_node: ^ElnaTreeNode, symbol_table: ^ElnaSymbolTable);
var
instruction: Word;
operand: ElnaTacOperand;
begin
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
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
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
instruction := elna_tac_label_declaration(parser_node)
elna_tac_label_declaration(instructions, parser_node)
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
instruction := elna_tac_assign_statement(parser_node, symbol_table)
else
instruction := nil
end;
return instruction
elna_tac_assign_statement(instructions, parser_node, symbol_table)
end
end;
(**
@@ -3738,10 +3662,13 @@ var
symbol_info: ^ElnaSymbolProcedureInfo;
result: ^ElnaTacProcedure;
parameter_count: Word;
body: ElnaList;
begin
result := malloc(#size(ElnaTacProcedure));
result^.next := nil;
elna_list_initialize(@result^.body);
result^.name := parser_node^.name;
result^.length := parser_node^.length;
@@ -3751,7 +3678,7 @@ begin
result^.parameters := elna_tac_parameters(parser_node^.parameters, @parameter_count);
result^.count := parameter_count;
result^.body := elna_tac_statements(parser_node^.body, symbol_info^.symbol_table);
elna_tac_statements(@result^.body, parser_node^.body, symbol_info^.symbol_table);
return result
end;
@@ -4087,7 +4014,7 @@ begin
return first_variable
end;
proc elna_parser_module_declaration(error_list: ^ElnaErrorList);
proc elna_parser_module_declaration(error_list: ^ElnaList);
var
parser_node: Word;
result: ^ElnaTreeModuleDeclaration;
@@ -4480,15 +4407,13 @@ var
parser_node: Word;
tac: Word;
rtl: Word;
error_list: ^ElnaErrorList;
error_list: ElnaList;
compiled: Word;
begin
error_list := malloc(#size(ElnaErrorList));
error_list^.first := nil;
error_list^.last := nil;
elna_list_initialize(@error_list);
parser_node := elna_parser_module_declaration(error_list);
compiled := error_list^.first = nil;
parser_node := elna_parser_module_declaration(@error_list);
compiled := error_list.first = nil;
if compiled then
elna_name_module_declaration(parser_node);