summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boot/stage23/cl.elna514
1 files changed, 243 insertions, 271 deletions
diff --git a/boot/stage23/cl.elna b/boot/stage23/cl.elna
index 18135fc..c528a0e 100644
--- a/boot/stage23/cl.elna
+++ b/boot/stage23/cl.elna
@@ -47,8 +47,7 @@ type
length: Word
end
ElnaTypeField = record
- name: ElnaTypeKind;
- length: Word;
+ name: String;
field_type: ^ElnaType
end
ElnaTypeRecord = record
@@ -121,8 +120,7 @@ type
ElnaTreeCharacterLiteral = record
kind: ElnaTreeKind;
type_decoration: ^ElnaType;
- value: ^Char;
- length: Word
+ value: Char
end
ElnaTreeNilLiteral = record
kind: ElnaTreeKind;
@@ -131,19 +129,17 @@ type
ElnaTreeBooleanLiteral = record
kind: ElnaTreeKind;
type_decoration: ^ElnaType;
- value: Word
+ value: Bool
end
ElnaTreeStringLiteral = record
kind: ElnaTreeKind;
type_decoration: ^ElnaType;
- value: ^Char;
- length: Word
+ value: String
end
ElnaTreeVariableExpression = record
kind: ElnaTreeKind;
type_decoration: ^ElnaType;
- name: Word;
- length: Word
+ name: String
end
ElnaTreeCastExpression = record
kind: ElnaTreeKind;
@@ -187,8 +183,7 @@ type
ElnaTreeGotoStatement = record
kind: ElnaTreeKind;
next: Word;
- label: Word;
- length: Word
+ label: String
end
ElnaTreeAssignStatement = record
kind: ElnaTreeKind;
@@ -204,15 +199,13 @@ type
ElnaTreeLabelDeclaration = record
kind: ElnaTreeKind;
next: Word;
- label: Word;
- length: Word
+ label: String
end
ElnaTreeFieldAccessExpression = record
kind: ElnaTreeKind;
type_decoration: ^ElnaType;
aggregate: Word;
- field: Word;
- length: Word
+ field: String
end
ElnaTreeArrayAccessExpression = record
kind: ElnaTreeKind;
@@ -221,8 +214,7 @@ type
index: ^ElnaTreeExpression
end
ElnaTreeEnumeration = record
- name: Word;
- length: Word;
+ name: String;
next: Word
end
ElnaTreeEnumerationTypeExpression = record
@@ -231,8 +223,7 @@ type
length: Word
end
ElnaTreeField = record
- name: Word;
- length: Word;
+ name: String;
type_expression: ^ElnaTreeTypeExpression;
next: Word
end
@@ -243,8 +234,7 @@ type
end
ElnaTreeNamedTypeExpression = record
kind: ElnaTreeKind;
- name: Word;
- length: Word
+ name: String
end
ElnaTreePointerTypeExpression = record
kind: ElnaTreeKind;
@@ -257,8 +247,7 @@ type
end
ElnaTreeTraitExpression = record
kind: ElnaTreeKind;
- name: Word;
- length: Word;
+ name: String;
argument: Word
end
(**
@@ -273,14 +262,12 @@ type
ElnaTreeDeclaration = record
kind: ElnaTreeKind;
next: Word;
- name: Word;
- length: Word
+ name: String
end
ElnaTreeProcedureDeclaration = record
kind: ElnaTreeKind;
next: Word;
- name: Word;
- length: Word;
+ name: String;
body: ^ElnaTreeStatement;
temporaries: Word;
parameters: Word;
@@ -296,16 +283,14 @@ type
ElnaTreeTypeDeclaration = record
kind: ElnaTreeKind;
next: Word;
- name: Word;
- length: Word;
+ name: String;
type_expression: ^ElnaTreeTypeExpression
end
ElnaTreeVariableDeclaration = record
kind: ElnaTreeKind;
next: Word;
- name: Word;
- length: Word;
- type_expression: Word
+ name: String;
+ type_expression: ^ElnaTreeTypeExpression
end
ElnaTreeExpressionList = record
expression: ^ElnaTreeBinaryExpression;
@@ -416,8 +401,6 @@ type
_then,
_else,
_elsif,
- _while,
- _do,
_extern,
_record,
boolean,
@@ -463,8 +446,7 @@ type
)
ElnaLexerToken = record
kind: ElnaLexerKind;
- start: Word;
- length: Word;
+ start: String;
position: ElnaPosition
end
ElnaLexerCursor = record
@@ -526,8 +508,7 @@ type
end
ElnaTacProcedure = record
next: Word;
- name: Word;
- length: Word;
+ name: String;
body: ElnaList;
parameters: Word;
count: Word;
@@ -535,8 +516,7 @@ type
end
ElnaTacStaticVariable = record
next: Word;
- name: Word;
- length: Word;
+ name: String;
body: Word
end
ElnaTacOperandType = (plain_object, dereferenced_pointer, sub_object)
@@ -584,14 +564,12 @@ type
end
ElnaRtlStaticVariable = record
next: Word;
- name: Word;
- length: Word;
+ name: String;
body: Word
end
ElnaRtlProcedure = record
next: Word;
- name: Word;
- length: Word;
+ name: String;
body: ElnaList;
variable_map: ^ElnaSymbolTable
end
@@ -1576,13 +1554,21 @@ begin
end
end
-proc elna_tac_label(instructions: ^ElnaList, counter: Word, length: Word)
+
+(**
+ * Generates an auto incremented label and returns its name.
+ *)
+proc elna_tac_label() -> String
var
- result: ^ElnaTacInstruction
+ buffer: String
begin
- result := elna_tac_instruction_create(ElnaTacOperator.label);
- elna_tac_instruction_set_operand(result, 1, ElnaTacKind.label, counter, length);
- elna_list_append(instructions, result)
+ buffer.ptr := malloc(7);
+
+ sprintf(buffer.ptr, ".L%i\0".ptr, label_counter);
+ buffer.length := strlen(buffer);
+ label_counter := label_counter + 1;
+
+ return buffer
end
proc elna_riscv_instruction_name(instruction_kind: ElnaRtlOperator,
@@ -1695,11 +1681,7 @@ begin
elna_riscv_register(instruction^.operands[n].value);
_write_c(1, ')')
elsif operand_type = ElnaRtlKind.data then
- if instruction^.operands[n].length = 0 then
- _write_label(instruction^.operands[n].value, 0)
- else
- write(1, instruction^.operands[n].value, instruction^.operands[n].length)
- end
+ write(1, instruction^.operands[n].value, instruction^.operands[n].length)
elsif instruction^.operands[n].length = 0 then (* ElnaRtlKind.immediate *)
_write_i(1, instruction^.operands[n].value)
else
@@ -2077,37 +2059,39 @@ begin
argument_count := 0;
if instruction^.operator = ElnaRtlOperator.label then
- _write_label(instruction^.operands[1].value, instruction^.operands[1].length);
+ write(1, instruction^.operands[1].value, instruction^.operands[1].length);
_write_c(1, ':')
elsif instruction^.operator = ElnaRtlOperator.allocate_stack then
operand_value := instruction^.operands[1].value;
+ fflush(nil);
(* Write the prologue. *)
- printf("\taddi sp, sp, -%i\n\tsw ra, %i(sp)\n\tsw s0, %i(sp)\n\taddi s0, sp, %i\n\0".ptr,
- operand_value, operand_value - 4, operand_value - 8, operand_value)
+ _write_s(1, "\taddi sp, sp, -");
+ _write_i(1, operand_value);
+ _write_s(1, "\n\tsw ra, ");
+ _write_i(1, operand_value - 4);
+ _write_s(1, "(sp)\n\tsw s0, ");
+ _write_i(1, operand_value - 8);
+ _write_s(1, "(sp)\n\taddi s0, sp, ");
+ _write_i(1, operand_value);
+ _write_c(1, '\n')
elsif instruction^.operator = ElnaRtlOperator.ret then
operand_value := instruction^.operands[1].value;
+ fflush(nil);
(* Write the epilogue. *)
- printf("\tlw ra, %i(sp)\n\tlw s0, %i(sp)\n\taddi sp, sp, %i\n\0".ptr,
- operand_value - 4, operand_value - 8, operand_value)
+ _write_s(1, "\tlw ra, ");
+ _write_i(1, operand_value - 4);
+ _write_s(1, "(sp)\n\tlw s0, ");
+ _write_i(1, operand_value - 8);
+ _write_s(1, "(sp)\n\taddi sp, sp, ");
+ _write_i(1, operand_value);
+ _write_c(1, '\n')
elsif instruction^.operator = ElnaRtlOperator.nop then
- operand_value := instruction^.operands[1].kind;
-
- if operand_value = ElnaTacKind.constant then
- printf("\n# copy %i (%i %i) (%i %.*s)\n\0".ptr, instruction^.operands[3].kind,
- instruction^.operands[1].kind, instruction^.operands[1].value,
- instruction^.operands[2].kind, instruction^.operands[2].length, instruction^.operands[2].value)
- else
- printf("\n# copy (%i %.*s) (%i %.*s)\n\0".ptr,
- instruction^.operands[1].kind, instruction^.operands[1].length, instruction^.operands[1].value,
- instruction^.operands[2].kind, instruction^.operands[2].length, instruction^.operands[2].value)
- end
else
argument_count := elna_riscv_instruction_name(instruction^.operator,
instruction^.types[1], instruction^.types[2])
end;
- fflush(nil);
current_argument := 1;
.elna_riscv_instruction_loop;
@@ -2187,10 +2171,13 @@ begin
.elna_riscv_procedure_loop;
(* Write .type _procedure_name, @function. *)
- printf(".type %.*s, @function\n\0".ptr, procedure^.length, procedure^.name);
+ _write_s(1, ".type ");
+ _write_s(1, procedure^.name);
+ _write_s(1, ", @function\n");
(* Write procedure label, _procedure_name: *)
- printf("%.*s:\n\0".ptr, procedure^.length, procedure^.name);
+ _write_s(1, procedure^.name);
+ _write_s(1, ":\n");
elna_riscv_instructions(procedure^.body.first);
fflush(nil);
@@ -2205,10 +2192,16 @@ end
proc elna_riscv_variable(variable: ^ElnaRtlStaticVariable)
begin
.elna_riscv_variable_loop;
- if variable <> 0 then
- printf(".type %.*s, @object\n\0".ptr, variable^.length, variable^.name);
+ if variable <> nil then
+ _write_s(1, ".type ");
+ _write_s(1, variable^.name);
+ _write_s(1, ", @object");
+ _write_c(1, '\n');
+ _write_s(1, variable^.name);
+ _write_s(1, ": .zero ");
+ _write_i(1, variable^.body);
+ _write_c(1, '\n');
- printf("%.*s: .zero %i\n\0".ptr, variable^.length, variable^.name, variable^.body);
variable := variable^.next;
goto elna_riscv_variable_loop
@@ -2344,14 +2337,16 @@ begin
result := malloc(#size(ElnaTreeIntegerLiteral));
token := elna_lexer_read(cursor);
- buffer := malloc(token^.length + 1);
- bzero(buffer, token^.length + 1);
- memcpy(buffer, token^.start, token^.length);
+ buffer := malloc(token^.start.length + 1);
+ bzero(buffer, token^.start.length + 1);
+ memcpy(buffer, token^.start.ptr, token^.start.length);
result^.kind := ElnaTreeKind.integer_literal;
result^.value := atoi(buffer);
result^.type_decoration := nil;
+ free(buffer);
+
return result
end
@@ -2362,7 +2357,7 @@ begin
result := malloc(#size(ElnaTreeBooleanLiteral));
result^.kind := ElnaTreeKind.boolean_literal;
- result^.value := string_compare(cursor^.start, 4, "true".ptr, 4);
+ result^.value := string_compare(cursor^.start, 4, "true");
result^.type_decoration := nil;
elna_lexer_read(cursor);
@@ -2462,9 +2457,8 @@ begin
token := elna_lexer_read(cursor);
result^.kind := ElnaTreeKind.character_literal;
- elna_parser_escape(token^.start + 1, @result^.value);
+ elna_parser_escape(token^.start.ptr + 1, @result^.value);
- result^.length := 0;
result^.type_decoration := nil;
return result
@@ -2472,11 +2466,11 @@ end
proc elna_tac_character_literal(character_literal_node: ^ElnaTreeCharacterLiteral, operand: ^ElnaTacOperand)
var
- next_character: Word
- current_position: ^Char
+ current_position: Word
begin
operand^.kind := ElnaTacKind.constant;
- operand^.value := character_literal_node^.value;
+ current_position := character_literal_node^.value;
+ operand^.value := current_position;
operand^.length := 1
end
@@ -2490,7 +2484,6 @@ begin
result^.kind := ElnaTreeKind.variable_expression;
result^.name := token^.start;
- result^.length := token^.length;
result^.type_decoration := nil;
return result
@@ -2499,8 +2492,8 @@ end
proc elna_tac_variable_expression(variable_expression: ^ElnaTreeVariableExpression, operand: ^ElnaTacOperand)
begin
operand^.kind := ElnaTacKind.variable;
- operand^.value := variable_expression^.name;
- operand^.length := variable_expression^.length
+ operand^.value := variable_expression^.name.ptr;
+ operand^.length := variable_expression^.name.length
end
proc elna_parser_string_literal(cursor: ^ElnaLexerCursor) -> ^ElnaTreeStringLiteral
@@ -2514,13 +2507,12 @@ var
begin
result := malloc(#size(ElnaTreeStringLiteral));
token := elna_lexer_read(cursor);
- target_position := malloc(token^.length - 2);
- current_position := token^.start + 1;
+ target_position := malloc(token^.start.length - 2);
+ current_position := token^.start.ptr + 1;
parsed_total := 2;
result^.kind := ElnaTreeKind.string_literal;
- result^.value := target_position;
- result^.length := 0;
+ result^.value.ptr := target_position;
.elna_parser_escape_loop;
parsed_length := elna_parser_escape(current_position, target_position);
@@ -2528,10 +2520,10 @@ begin
parsed_total := parsed_total + parsed_length;
target_position := target_position + 1;
- if parsed_total < token^.length then
+ if parsed_total < token^.start.length then
goto elna_parser_escape_loop
end;
- result^.length := target_position - result^.value;
+ result^.value.length := target_position - result^.value.ptr;
result^.type_decoration := nil;
return result
@@ -2544,7 +2536,7 @@ var
instruction: ^ElnaTacInstruction
address: ElnaTacOperand
begin
- offset := elna_tac_add_string(string_literal_node^.value, string_literal_node^.length);
+ offset := elna_tac_add_string(string_literal_node^.value.ptr, string_literal_node^.value.length);
elna_tac_make_variable(operand, symbol_table, string_type);
elna_tac_make_variable(@address, symbol_table, word_type);
@@ -2568,7 +2560,7 @@ begin
elna_list_append(instructions, instruction);
instruction := elna_tac_instruction_create(ElnaTacOperator.copy_to_offset);
- elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.constant, string_literal_node^.length, 4);
+ elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.constant, string_literal_node^.value.length, 4);
elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length);
elna_tac_instruction_set_operand(instruction, 3, ElnaTacKind.constant, 4, 4);
elna_list_append(instructions, instruction)
@@ -2585,7 +2577,6 @@ begin
token := elna_lexer_read(cursor);
result^.name := token^.start;
- result^.length := token^.length;
if elna_parser_expect(cursor, ElnaLexerKind.left_paren, error_list) <> nil then
result^.argument := elna_parser_type_expression(cursor, error_list);
@@ -2725,7 +2716,7 @@ var
parser_node: ^ElnaTreeNamedTypeExpression
begin
parser_node := trait_node^.argument;
- symbol := elna_symbol_table_lookup(symbol_table_global, parser_node^.name, parser_node^.length);
+ symbol := elna_symbol_table_lookup(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length);
info_type := symbol^._type;
operand^.kind := ElnaTacKind.constant;
@@ -3134,7 +3125,7 @@ var
begin
parsed_expression := parsed_call^.callee;
arguments_operand := malloc(parsed_call^.count * #size(ElnaTacOperand));
- procedure_info := elna_symbol_table_lookup(symbol_table, parsed_expression^.name, parsed_expression^.length);
+ procedure_info := elna_symbol_table_lookup(symbol_table, parsed_expression^.name.ptr, parsed_expression^.name.length);
(* TODO: procedure_info should never be nil. *)
if procedure_info = nil then
@@ -3146,7 +3137,8 @@ begin
end;
call_instruction := elna_tac_instruction_create(ElnaTacOperator.proc_call);
- elna_tac_instruction_set_operand(call_instruction, 1, ElnaTacKind.label, parsed_expression^.name, parsed_expression^.length);
+ elna_tac_instruction_set_operand(call_instruction, 1, ElnaTacKind.label,
+ parsed_expression^.name.ptr, parsed_expression^.name.length);
elna_tac_instruction_set_operand(call_instruction, 2, ElnaTacKind.list, arguments_operand, parsed_call^.count);
elna_tac_instruction_set_operand(call_instruction, 3, operand^.kind, operand^.value, operand^.length);
@@ -3176,8 +3168,7 @@ begin
result := malloc(#size(ElnaTreeGotoStatement));
result^.kind := ElnaTreeKind.goto_statement;
result^.next := nil;
- result^.label := token^.start;
- result^.length := token^.length
+ result^.label := token^.start
end;
return result
end
@@ -3188,11 +3179,11 @@ var
label_with_dot: ^Char
instruction: ^ElnaTacInstruction
begin
- label_length := parser_node^.length + 1;
+ label_length := parser_node^.label.length + 1;
label_with_dot := malloc(label_length);
label_with_dot^ := '.';
- memcpy(label_with_dot + 1, parser_node^.label, parser_node^.length);
+ memcpy(label_with_dot + 1, parser_node^.label.ptr, parser_node^.label.length);
instruction := elna_tac_instruction_create(ElnaTacOperator.jump);
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.label, label_with_dot, label_length);
@@ -3211,15 +3202,24 @@ begin
result^.kind := ElnaTreeKind.label_declaration;
result^.next := nil;
- result^.label := token^.start;
- result^.length := token^.length;
+ result^.label := token^.start
end;
return result
end
proc elna_tac_label_declaration(instructions: ^ElnaList, parser_node: ^ElnaTreeLabelDeclaration)
+var
+ result: ^ElnaTacInstruction
+ buffer: String
begin
- elna_tac_label(instructions, parser_node^.label, parser_node^.length)
+ buffer.length := parser_node^.label.length + 1;
+ buffer := malloc(buffer.length);
+ buffer.ptr^ := '.';
+ memcpy(buffer.ptr + 1, parser_node^.label.ptr, parser_node^.label.length);
+
+ result := elna_tac_instruction_create(ElnaTacOperator.label);
+ elna_tac_instruction_set_operand(result, 1, ElnaTacKind.label, buffer.ptr, buffer.length);
+ elna_list_append(instructions, result)
end
proc elna_tac_enumeration_value(field_access_expression: ^ElnaTreeFieldAccessExpression, operand: ^ElnaTacOperand)
@@ -3229,14 +3229,14 @@ var
members_length: Word
token_type: Word
symbol_info: ^ElnaSymbolTypeInfo
- member_name: Word
member_length: Word
+ member: String
counter: Word
enumeration_type_name: ^ElnaTreeVariableExpression
begin
enumeration_type_name := field_access_expression^.aggregate;
symbol_info := elna_symbol_table_lookup(symbol_table_global,
- enumeration_type_name^.name, enumeration_type_name^.length);
+ enumeration_type_name^.name.ptr, enumeration_type_name^.name.length);
enumeration_type := symbol_info^._type;
members := enumeration_type^.members;
@@ -3245,11 +3245,11 @@ begin
.elna_tac_enumeration_value_members;
if members_length > 0 then
- member_name := members^;
+ member.ptr := members^;
member_length := members + 4;
- member_length := member_length^;
+ member.length := member_length^;
- if string_compare(field_access_expression^.field, field_access_expression^.length, member_name, member_length) = 0 then
+ if string_compare(field_access_expression^.field.ptr, field_access_expression^.field.length, member) = false then
members_length := members_length - 1;
members := members + 8;
counter := counter + 1;
@@ -3278,7 +3278,6 @@ begin
result^.type_decoration := nil;
result^.aggregate := aggregate;
result^.field := token^.start;
- result^.length := token^.length;
return result
end
@@ -3389,7 +3388,7 @@ begin
.elna_tac_field_access_expression_field;
- if string_compare(field_access_expression^.field, field_access_expression^.length, current_field^.name, current_field^.length) = 0 then
+ if string_compare(field_access_expression^.field.ptr, field_access_expression^.field.length, current_field^.name) = false then
field_type := current_field^.field_type;
field_count := field_count - 1;
current_field := current_field + 1;
@@ -3456,7 +3455,6 @@ end
proc elna_parser_assign_statement(cursor: ^ElnaLexerCursor, assignee: ^ElnaTreeNode, error_list: ^ElnaList) -> ^ElnaTreeAssignStatement
var
result: ^ElnaTreeAssignStatement
- token: ^ElnaLexerToken
begin
result := malloc(#size(ElnaTreeAssignStatement));
@@ -3538,24 +3536,6 @@ begin
elna_list_append(instructions, instruction)
end
-(**
- * Writes a label, .Ln, where n is a unique number.
- *
- * Parameters:
- * counter - Label counter.
- *)
-proc _write_label(counter: Word, length: Word)
-var
- first_byte: Word
-begin
- if length = 0 then
- printf(".L%i\0".ptr, counter)
- else
- printf(".%.*s\0".ptr, length, counter);
- end;
- fflush(nil)
-end
-
proc elna_parser_conditional_statements(cursor: ^ElnaLexerCursor, error_list: ^ElnaList,
block_keyword: ElnaLexerKind) -> ^ElnaTreeConditionalStatements
var
@@ -3583,9 +3563,9 @@ begin
end
proc elna_tac_conditional_statements(instructions: ^ElnaList, parser_node: ^ElnaTreeConditionalStatements,
- after_end_label: Word, symbol_table: ^ElnaSymbolTable)
+ after_end_label: String, symbol_table: ^ElnaSymbolTable)
var
- condition_label: Word
+ condition_label: String
instruction: ^ElnaTacInstruction
operand: ElnaTacOperand
begin
@@ -3593,21 +3573,22 @@ begin
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;
+ condition_label := elna_tac_label(label_counter);
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.label, condition_label, 0);
+ elna_tac_instruction_set_operand(instruction, 2, ElnaTacKind.label, condition_label.ptr, condition_label.length);
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.label, after_end_label, 0);
+ elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.label, after_end_label.ptr, after_end_label.length);
elna_list_append(instructions, instruction);
- elna_tac_label(instructions, condition_label, 0)
+ instruction := elna_tac_instruction_create(ElnaTacOperator.label);
+ elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.label, condition_label.ptr, condition_label.length);
+ elna_list_append(instructions, instruction)
end
proc elna_parser_if_statement(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeIfStatement
@@ -3724,11 +3705,10 @@ end
proc elna_tac_if_statement(instructions: ^ElnaList, parser_node: ^ElnaTreeIfStatement, symbol_table: ^ElnaSymbolTable)
var
current_node: ^ElnaTreeConditionalStatements
- after_end_label: Word
- condition_label: Word
+ after_end_label: String
+ instruction: ^ElnaTacInstruction
begin
- after_end_label := label_counter;
- label_counter := label_counter + 1;
+ after_end_label := elna_tac_label(label_counter);
current_node := parser_node^.conditionals;
elna_tac_conditional_statements(instructions, current_node, after_end_label, symbol_table);
@@ -3745,7 +3725,9 @@ begin
if parser_node^._else <> nil then
elna_tac_statements(instructions, parser_node^._else, symbol_table)
end;
- elna_tac_label(instructions, after_end_label, 0)
+ instruction := elna_tac_instruction_create(ElnaTacOperator.label);
+ elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.label, after_end_label.ptr, after_end_label.length);
+ elna_list_append(instructions, instruction)
end
proc elna_tac_statement(instructions: ^ElnaList, parser_node: ^ElnaTreeNode, symbol_table: ^ElnaSymbolTable)
@@ -3812,7 +3794,6 @@ begin
result^.length := result^.length + 1;
entry^.name := token^.start;
- entry^.length := token^.length;
(* Skip the colon. *)
if elna_parser_expect(cursor, ElnaLexerKind.colon, error_list) = nil then
@@ -3870,7 +3851,6 @@ begin
result^.length := result^.length + 1;
entry^.name := token^.start;
- entry^.length := token^.length;
entry^.next := nil;
if result^.members = nil then
@@ -3915,10 +3895,9 @@ end
proc elna_name_enumeration_type_expression(parser_node: ^ElnaTreeEnumerationTypeExpression) -> ^ElnaTypeEnumeration
var
result: ^ElnaTypeEnumeration
- memory_start: Word
+ memory_start: ^ElnaTreeEnumeration
member_count: Word
- member_array_start: Word
- member_array_current: Word
+ member_array_current: ^String
begin
result := malloc(#size(ElnaTypeEnumeration));
@@ -3926,30 +3905,23 @@ begin
member_count := parser_node^.length;
(* Copy the list of enumeration members into an array of strings. *)
- member_array_start := malloc(member_count * 8);
- member_array_current := member_array_start;
+ result^.members := malloc(member_count * 8);
+ member_array_current := result^.members;
.elna_name_type_enumeration_loop;
if member_count > 0 then
- member_array_current^ := memory_start^;
- member_array_current := member_array_current + 4;
- memory_start := memory_start + 4;
-
- member_array_current^ := memory_start^;
- member_array_current := member_array_current + 4;
- memory_start := memory_start + 4;
+ member_array_current^ := memory_start^.name;
+ member_array_current := member_array_current + 1;
- memory_start := memory_start^;
+ memory_start := memory_start^.next;
member_count := member_count - 1;
goto elna_name_type_enumeration_loop
end;
- member_count := parser_node^.length;
result^.kind := ElnaTypeKind.enumeration;
result^.size := 4;
result^.alignment := 4;
- result^.members := member_array_start;
- result^.length := member_count;
+ result^.length := parser_node^.length;
return result
end
@@ -3992,7 +3964,6 @@ proc elna_name_record_type_expression(parser_node: ^ElnaTreeRecordTypeExpression
var
result: ^ElnaTypeRecord
tree_field: ^ElnaTreeField
- member_array_start: ^ElnaTypeField
member_array_current: ^ElnaTypeField
field_type: ^ElnaType
begin
@@ -4009,7 +3980,6 @@ begin
.elna_name_type_record_loop;
if result^.length < parser_node^.length then
member_array_current^.name := tree_field^.name;
- member_array_current^.length := tree_field^.length;
field_type := elna_name_type_expression(tree_field^.type_expression);
result^.size := result^.size + field_type^.size;
@@ -4038,7 +4008,6 @@ begin
result^.kind := ElnaTreeKind.named_type_expression;
result^.name := token^.start;
- result^.length := token^.length;
return result
end
@@ -4085,7 +4054,7 @@ begin
return result
end
-proc elna_parser_type_expression(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeNode
+proc elna_parser_type_expression(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeTypeExpression
var
result: ^ElnaTreeNode
token: ^ElnaLexerToken
@@ -4127,7 +4096,7 @@ begin
named_type_expression := parser_node;
type_symbol := elna_symbol_table_lookup(symbol_table_global,
- named_type_expression^.name, named_type_expression^.length);
+ named_type_expression^.name.ptr, named_type_expression^.name.length);
result := type_symbol^._type
elsif parser_node^.kind = ElnaTreeKind.enumeration_type_expression then
result := elna_name_enumeration_type_expression(parser_node)
@@ -4200,7 +4169,7 @@ begin
variable_type := elna_name_type_expression(parser_node^.type_expression);
info := temporary_info_create(0, variable_type);
- elna_symbol_table_enter(symbol_table, parser_node^.name, parser_node^.length, info)
+ elna_symbol_table_enter(symbol_table, parser_node^.name.ptr, parser_node^.name.length, info)
end
proc elna_name_procedure_temporaries(parser_node: ^ElnaTreeVariableDeclaration, symbol_table: ^ElnaSymbolTable)
@@ -4214,6 +4183,43 @@ begin
end
end
+proc elna_parser_parameters(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeVariableDeclaration
+var
+ parameters: ^ElnaTreeVariableDeclaration
+ token: ^ElnaLexerToken
+ current_declaration: ^ElnaTreeVariableDeclaration
+ next_declaration: ^ElnaTreeVariableDeclaration
+begin
+ parameters := nil;
+
+ .elna_parser_parameters_loop;
+ token := elna_lexer_peek(cursor);
+
+ if token^.kind <> ElnaLexerKind.right_paren then
+ next_declaration := elna_parser_variable_declaration(cursor, error_list);
+ if next_declaration = nil then
+ parameters := free_and_nil(parameters);
+ goto elna_parser_parameters_end
+ end;
+ if parameters = nil then
+ parameters := next_declaration
+ else
+ current_declaration^.next := next_declaration
+ end;
+ current_declaration := next_declaration;
+
+ token := elna_lexer_peek(cursor);
+
+ if token^.kind = ElnaLexerKind.comma then
+ elna_lexer_read(cursor);
+ goto elna_parser_parameters_loop
+ end
+ end;
+ .elna_parser_parameters_end;
+
+ return parameters
+end
+
proc elna_parser_procedure_declaration(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeProcedureDeclaration
var
next_declaration: ^ElnaTreeDeclaration
@@ -4234,39 +4240,18 @@ begin
result := malloc(#size(ElnaTreeProcedureDeclaration));
result^.kind := ElnaTreeKind.procedure_declaration;
result^.next := nil;
-
result^.name := token^.start;
- result^.length := token^.length;
if elna_parser_expect(cursor, ElnaLexerKind.left_paren, error_list) = nil then
result := free_and_nil(result);
goto elna_parser_procedure_declaration_end
end;
- result^.parameters := nil;
-
- .elna_parser_procedure_declaration_parameter;
- token := elna_lexer_peek(cursor);
-
- if token^.kind <> ElnaLexerKind.right_paren then
- next_declaration := elna_parser_variable_declaration(cursor, error_list);
- if next_declaration = nil then
- result := free_and_nil(result);
- goto elna_parser_procedure_declaration_end
- end;
- if result^.parameters = nil then
- result^.parameters := next_declaration
- else
- current_declaration^.next := next_declaration
- end;
- current_declaration := next_declaration;
-
- token := elna_lexer_peek(cursor);
-
- if token^.kind = ElnaLexerKind.comma then
- elna_lexer_read(cursor);
- goto elna_parser_procedure_declaration_parameter
- end
+ result^.parameters := elna_parser_parameters(cursor, error_list);
+ if elna_list_empty(error_list) = false then
+ result := free_and_nil(result);
+ goto elna_parser_procedure_declaration_end
end;
+
(* Skip close paren. *)
if elna_parser_expect(cursor, ElnaLexerKind.right_paren, error_list) = nil then
result := free_and_nil(result);
@@ -4318,12 +4303,12 @@ begin
return result
end
-proc elna_tac_parameters(ast_list: ^ElnaTreeDeclaration, parameter_count: ^Word) -> ^Word
+proc elna_tac_parameters(ast_list: ^ElnaTreeDeclaration, parameter_count: ^Word) -> ^String
var
ast_parameter: ^ElnaTreeDeclaration
parameter_index: Word
- current_parameter: Word
- parameter_list: Word
+ current_parameter: ^String
+ parameter_list: ^String
begin
ast_parameter := ast_list;
parameter_count^ := 0;
@@ -4336,7 +4321,7 @@ begin
goto elna_tac_parameters_count
end;
(* The parameters are saved as an array of name pointer + name length. *)
- parameter_list := malloc(parameter_count^ * 8);
+ parameter_list := malloc(parameter_count^ * #size(String));
current_parameter := parameter_list;
ast_parameter := ast_list;
@@ -4345,9 +4330,7 @@ begin
.elna_tac_parameters_loop;
if parameter_index < parameter_count^ then
current_parameter^ := ast_parameter^.name;
- current_parameter := current_parameter + 4;
- current_parameter^ := ast_parameter^.length;
- current_parameter := current_parameter + 4;
+ current_parameter := current_parameter + 1;
parameter_index := parameter_index + 1;
ast_parameter := ast_parameter^.next;
@@ -4365,7 +4348,6 @@ begin
result^.next := nil;
result^.name := tac_declaration^.name;
- result^.length := tac_declaration^.length;
result^.body := tac_declaration^.body;
return result
@@ -4518,7 +4500,6 @@ begin
result^.next := nil;
result^.name := tac_declaration^.name;
- result^.length := tac_declaration^.length;
pseudo_counter := 0;
result^.variable_map := elna_symbol_table_create(variable_map_global);
@@ -4566,9 +4547,7 @@ begin
elna_list_initialize(@result^.body);
result^.name := parser_node^.name;
- result^.length := parser_node^.length;
-
- symbol_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name, parser_node^.length);
+ symbol_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length);
result^.symbol_table := symbol_info^.symbol_table;
@@ -4674,7 +4653,7 @@ begin
first_procedure := nil;
.elna_tac_procedures_loop;
- if parser_node = 0 then
+ if parser_node = nil then
goto elna_tac_procedures_end
end;
result := elna_tac_procedure_declaration(parser_node);
@@ -4721,7 +4700,6 @@ begin
result^.kind := ElnaTreeKind.type_declaration;
result^.next := nil;
result^.name := token^.start;
- result^.length := token^.length;
if elna_parser_expect(cursor, ElnaLexerKind.equals, error_list) <> nil then
result^.type_expression := elna_parser_type_expression(cursor, error_list)
@@ -4739,7 +4717,7 @@ begin
symbol_type := elna_name_type_expression(parser_node^.type_expression);
type_info := type_info_create(symbol_type);
- elna_symbol_table_enter(symbol_table_global, parser_node^.name, parser_node^.length, type_info)
+ elna_symbol_table_enter(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length, type_info)
end
proc elna_type_type_declaration(parser_node: Word)
@@ -4801,7 +4779,6 @@ begin
result^.kind := ElnaTreeKind.variable_declaration;
result^.next := nil;
result^.name := token^.start;
- result^.length := token^.length;
result^.type_expression := variable_type
end
end
@@ -4815,11 +4792,10 @@ var
variable_info: ^ElnaSymbolTemporaryInfo
begin
result := malloc(#size(ElnaTacStaticVariable));
- variable_info := elna_symbol_table_lookup(symbol_table_global, parser_tree^.name, parser_tree^.length);
+ variable_info := elna_symbol_table_lookup(symbol_table_global, parser_tree^.name.ptr, parser_tree^.name.length);
result^.next := nil;
result^.name := parser_tree^.name;
- result^.length := parser_tree^.length;
result^.body := variable_info^.variable_type^.size;
return result
@@ -4990,10 +4966,8 @@ begin
elna_list_initialize(@result^.body);
- result^.name := "main".ptr;
- result^.length := 4;
-
- symbol_info := elna_symbol_table_lookup(symbol_table_global, result^.name, result^.length);
+ result^.name := "main";
+ symbol_info := elna_symbol_table_lookup(symbol_table_global, result^.name.ptr, result^.name.length);
result^.symbol_table := symbol_info^.symbol_table;
@@ -5198,7 +5172,7 @@ begin
elna_name_procedure_temporaries(parser_node^.temporaries, new_symbol_table);
elna_name_statements(parser_node^.body);
- elna_symbol_table_enter(symbol_table_global, parser_node^.name, parser_node^.length, symbol_info)
+ elna_symbol_table_enter(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length, symbol_info)
end
proc elna_name_program_body(parser_node: ^ElnaTreeStatement)
@@ -5327,7 +5301,7 @@ var
variable_info: ^ElnaSymbolInfo
temporary_info: ^ElnaSymbolTemporaryInfo
begin
- variable_info := elna_symbol_table_lookup(symbol_table, parser_node^.name, parser_node^.length);
+ variable_info := elna_symbol_table_lookup(symbol_table, parser_node^.name.ptr, parser_node^.name.length);
if variable_info^.kind = ElnaSymbolInfoKind.temporary_info then
temporary_info := variable_info;
@@ -5393,7 +5367,8 @@ begin
(* Check whether the field access is an enumeration value. *)
if variable_expression^.kind = ElnaTreeKind.variable_expression then
- symbol_info := elna_symbol_table_lookup(symbol_table_global, variable_expression^.name, variable_expression^.length);
+ symbol_info := elna_symbol_table_lookup(symbol_table_global,
+ variable_expression^.name.ptr, variable_expression^.name.length);
if symbol_info <> nil then
type_kind := symbol_info;
@@ -5412,7 +5387,7 @@ begin
.elna_type_field_access_expression_field;
- if string_compare(parser_node^.field, parser_node^.length, current_field^.name, current_field^.length) = 0 then
+ if string_compare(parser_node^.field.ptr, parser_node^.field.length, current_field^.name) = false then
field_count := field_count - 1;
current_field := current_field + 1;
goto elna_type_field_access_expression_field
@@ -5483,7 +5458,7 @@ proc elna_type_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration)
var
procedure_info: ^ElnaSymbolProcedureInfo
begin
- procedure_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name, parser_node^.length);
+ procedure_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length);
elna_type_statements(parser_node^.body, procedure_info^.symbol_table)
end
@@ -5527,7 +5502,7 @@ var
begin
current_part := parser_node^.types;
.elna_type_module_declaration_type;
- if current_part <> 0 then
+ if current_part <> nil then
elna_type_type_declaration(current_part);
current_part := current_part^.next;
@@ -5536,7 +5511,7 @@ begin
current_part := parser_node^.procedures;
.elna_type_module_declaration_procedure;
- if current_part <> 0 then
+ if current_part <> nil then
elna_type_procedure_declaration(current_part);
current_part := current_part^.next;
@@ -5568,10 +5543,6 @@ begin
_write_s(2, "\"else\"")
elsif kind = ElnaLexerKind._elsif then
_write_s(2, "\"elsif\"")
- elsif kind = ElnaLexerKind._while then
- _write_s(2, "\"while\"")
- elsif kind = ElnaLexerKind._do then
- _write_s(2, "\"do\"")
elsif kind = ElnaLexerKind._extern then
_write_s(2, "\"extern\"")
elsif kind = ElnaLexerKind._record then
@@ -5646,6 +5617,10 @@ begin
_write_s(2, "COMMENT")
elsif kind = ElnaLexerKind.string then
_write_s(2, "STRING")
+ elsif kind = ElnaLexerKind.character then
+ _write_s(2, "CHARACTER")
+ elsif kind = ElnaLexerKind.integer then
+ _write_s(2, "INTEGER")
else
elna_error_print_token2(kind)
end
@@ -5653,11 +5628,7 @@ end
proc elna_error_print_token2(kind: ElnaLexerKind)
begin
- if kind = ElnaLexerKind.character then
- _write_s(2, "CHARACTER")
- elsif kind = ElnaLexerKind.integer then
- _write_s(2, "INTEGER")
- elsif kind = ElnaLexerKind.word then
+ if kind = ElnaLexerKind.word then
_write_s(2, "WORD")
elsif kind = ElnaLexerKind._goto then
_write_s(2, "\"goto\"")
@@ -5748,7 +5719,7 @@ begin
goto symbol_table_lookup_end
end;
(* If names don't match, try the next entry. *)
- if string_compare(current_entry^.name.ptr, current_entry^.name.length, symbol_name, name_length) = 0 then
+ if string_compare(symbol_name, name_length, current_entry^.name) = false then
goto symbol_table_lookup_repeat
end;
(* Otherwise, the symbol is found. *)
@@ -5827,13 +5798,11 @@ begin
char_pointer^.base := char_type;
current_field := string_type^.members;
- current_field^.name := "ptr".ptr;
- current_field^.length := 3;
+ current_field^.name := "ptr";
current_field^.field_type := char_pointer;
current_field := current_field + 1;
- current_field^.name := "length".ptr;
- current_field^.length := 6;
+ current_field^.name := "length";
current_field^.field_type := word_type
end
@@ -6246,12 +6215,12 @@ begin
end
(* Returns true or false depending whether two strings are equal. *)
-proc string_compare(lhs_pointer: Word, lhs_length: Word, rhs_pointer: Word, rhs_length: Word) -> Bool
+proc string_compare(lhs_pointer: Word, lhs_length: Word, rhs_pointer: String) -> Bool
var
result: Bool
begin
- if lhs_length = rhs_length then
- result := memcmp(lhs_pointer, rhs_pointer, lhs_length) = 0
+ if lhs_length = rhs_pointer.length then
+ result := memcmp(lhs_pointer, rhs_pointer.ptr, lhs_length) = 0
else
result := false
end;
@@ -6272,54 +6241,57 @@ end
proc elna_lexer_classify_keyword(position_start: ^Char, position_end: Word, position: ^ElnaPosition) -> ^ElnaLexerToken
var
result: ^ElnaLexerToken
+ result_length: Word
begin
+ result_length := position_end - position_start;
+
result := elna_lexer_token_create(ElnaLexerKind.identifier, position);
- result^.start := position_start;
- result^.length := position_end - position_start;
+ result^.start.ptr := position_start;
+ result^.start.length := result_length;
if position_start^ = '#' then
result^.kind := ElnaLexerKind.trait
- elsif string_compare(position_start, result^.length, "const".ptr, 5) then
+ elsif string_compare(position_start, result_length, "const") then
result^.kind := ElnaLexerKind._const
- elsif string_compare(position_start, result^.length, "var".ptr, 3) then
+ elsif string_compare(position_start, result_length, "var") then
result^.kind := ElnaLexerKind._var
- elsif string_compare(position_start, result^.length, "proc".ptr, 4) then
+ elsif string_compare(position_start, result_length, "proc") then
result^.kind := ElnaLexerKind._proc
- elsif string_compare(position_start, result^.length, "type".ptr, 4) then
+ elsif string_compare(position_start, result_length, "type") then
result^.kind := ElnaLexerKind._type
- elsif string_compare(position_start, result^.length, "begin".ptr, 5) then
+ elsif string_compare(position_start, result_length, "begin") then
result^.kind := ElnaLexerKind._begin
- elsif string_compare(position_start, result^.length, "end".ptr, 3) then
+ elsif string_compare(position_start, result_length, "end") then
result^.kind := ElnaLexerKind._end
- elsif string_compare(position_start, result^.length, "return".ptr, 6) then
+ elsif string_compare(position_start, result_length, "return") then
result^.kind := ElnaLexerKind._return
- elsif string_compare(position_start, result^.length, "goto".ptr, 4) then
+ elsif string_compare(position_start, result_length, "goto") then
result^.kind := ElnaLexerKind._goto
- elsif string_compare(position_start, result^.length, "if".ptr, 2) then
+ elsif string_compare(position_start, result_length, "if") then
result^.kind := ElnaLexerKind._if
- elsif string_compare(position_start, result^.length, "while".ptr, 5) then
- result^.kind := ElnaLexerKind._while
- elsif string_compare(position_start, result^.length, "then".ptr, 4) then
+ elsif string_compare(position_start, result_length, "extern") then
+ result^.kind := ElnaLexerKind._extern
+ elsif string_compare(position_start, result_length, "then") then
result^.kind := ElnaLexerKind._then
- elsif string_compare(position_start, result^.length, "else".ptr, 4) then
+ elsif string_compare(position_start, result_length, "else") then
result^.kind := ElnaLexerKind._else
- elsif string_compare(position_start, result^.length, "elsif".ptr, 5) then
+ elsif string_compare(position_start, result_length, "elsif") then
result^.kind := ElnaLexerKind._elsif
- elsif string_compare(position_start, result^.length, "record".ptr, 6) then
+ elsif string_compare(position_start, result_length, "record") then
result^.kind := ElnaLexerKind._record
- elsif string_compare(position_start, result^.length, "or".ptr, 2) then
+ elsif string_compare(position_start, result_length, "or") then
result^.kind := ElnaLexerKind._or
- elsif string_compare(position_start, result^.length, "xor".ptr, 3) then
+ elsif string_compare(position_start, result_length, "xor") then
result^.kind := ElnaLexerKind._xor
- elsif string_compare(position_start, result^.length, "program".ptr, 7) then
+ elsif string_compare(position_start, result_length, "program") then
result^.kind := ElnaLexerKind._program
- elsif string_compare(position_start, result^.length, "nil".ptr, 3) then
+ elsif string_compare(position_start, result_length, "nil") then
result^.kind := ElnaLexerKind.null
- elsif string_compare(position_start, result^.length, "true".ptr, 4) then
+ elsif string_compare(position_start, result_length, "true") then
result^.kind := ElnaLexerKind.boolean
- elsif string_compare(position_start, result^.length, "false".ptr, 5) then
+ elsif string_compare(position_start, result_length, "false") then
result^.kind := ElnaLexerKind.boolean
- elsif string_compare(position_start, result^.length, "cast".ptr, 4) then
+ elsif string_compare(position_start, result_length, "cast") then
result^.kind := ElnaLexerKind._cast
end;
return result
@@ -6431,8 +6403,8 @@ begin
elsif delimiter = '"' then
result := elna_lexer_token_create(ElnaLexerKind.string, position)
end;
- result^.start := start_position;
- result^.length := end_position - start_position;
+ result^.start.ptr := start_position;
+ result^.start.length := end_position - start_position;
return result
end
@@ -6442,8 +6414,8 @@ var
result: ^ElnaLexerToken
begin
result := elna_lexer_token_create(ElnaLexerKind.integer, position);
- result^.start := start_position;
- result^.length := end_position - start_position;
+ result^.start.ptr := start_position;
+ result^.start.length := end_position - start_position;
return result
end
@@ -6565,12 +6537,12 @@ begin
(* Read the source from the standard input. *)
offset := source_code;
- .start_read;
+ .read_source_loop;
(* Second argument is buffer size. Modifying update the source_code definition. *)
last_read := read(0, offset, 409600);
if last_read > 0 then
offset := offset + last_read;
- goto start_read
+ goto read_source_loop
end
end