From b58f8a8c45a7a456b44f28ec33ffb113adba06ca Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 17 Jun 2026 10:34:59 +0200 Subject: [PATCH] Generate automatic label during the TAC pass --- boot/stage23/cl.elna | 514 ++++++++++++++++++++----------------------- 1 file 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^.name; + member_array_current := member_array_current + 1; - member_array_current^ := memory_start^; - member_array_current := member_array_current + 4; - memory_start := memory_start + 4; - - 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