From a00f0d57b843736d603d749fc269d0208cec4e76 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Fri, 30 Jan 2026 23:21:19 +0100 Subject: [PATCH] Lower global static array and record access --- Rakefile | 45 +-- boot/stage18/cl.elna | 53 ++-- boot/stage19/cl.elna | 687 ++++++++++++++++++------------------------- 3 files changed, 323 insertions(+), 462 deletions(-) diff --git a/Rakefile b/Rakefile index ae7f27f..4ea6030 100644 --- a/Rakefile +++ b/Rakefile @@ -38,47 +38,14 @@ end desc 'Convert previous stage language into the current stage language' task :convert do - File.open('boot/stage19/cl.elna', 'w') do |current_stage| - File.readlines('boot/stage18/cl.elna').each do |line| - current_stage << "\tf();\n" if line.include? "if _compile() then" + File.open('boot/stage20/cl.elna', 'w') do |current_stage| + File.readlines('boot/stage19/cl.elna').each do |line| + if line.include? "_assign_at(@classification, 1, ElnaLexerClass.eof)" + current_stage << "\tclassification[1] := ElnaLexerClass.eof;\n" + else current_stage << line - if line == "type\n" - current_stage << <<-RECORD - Pair = record - first: Word; - second: Word - end; - R1 = record - field1: Word; - field2: [4]Word; - field3: Word - end; - R2 = record - field1: Word; - field3: Word; - field4: Word; - field5: Word; - field6: Word; - field2: Word - end; - - RECORD - end + end end - current_stage << <<~EPILOGUE - - proc f(); - var - v1: Word; - r: ^R1; - begin - r := malloc(#size(R1)); - - v1 := r^.field2[2]; - - printf("# %i\\n\\0", v1) - end; - EPILOGUE end end diff --git a/boot/stage18/cl.elna b/boot/stage18/cl.elna index dc9fdb5..f520e1d 100644 --- a/boot/stage18/cl.elna +++ b/boot/stage18/cl.elna @@ -7,8 +7,9 @@ program; (* Stage 18 compiler. *) -(* - Record fields can be aggregates themselves *) +(* - Record fields can be aggregates themselves. *) (* - Static arrays. *) +(* - Global variables can have any valid type. *) type (** @@ -2799,10 +2800,21 @@ begin field_offset := field_offset + field_type^.size; goto elna_tac_field_access_expression_field end; + if is_address then + last_instruction := _elna_tac_instruction_create(ElnaTacOperator.copy); + _elna_tac_instruction_set_operand(last_instruction, 1, ElnaTacOperand.pseudo, "$unary", 6); + _elna_tac_instruction_set_operand(last_instruction, 2, operand_type^, operand_value^, operand_length^) + else + last_instruction := _elna_tac_instruction_create(ElnaTacOperator.get_address); + _elna_tac_instruction_set_operand(last_instruction, 1, ElnaTacOperand.pseudo, "$unary", 6); + _elna_tac_instruction_set_operand(last_instruction, 2, operand_type^, operand_value^, operand_length^) + end; + 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, ElnaTacOperand.pseudo, "$unary", 6); _elna_tac_instruction_set_operand(last_instruction, 2, ElnaTacOperand.immediate, field_offset, 0); - _elna_tac_instruction_set_operand(last_instruction, 3, operand_type^, operand_value^, operand_length^); + _elna_tac_instruction_set_operand(last_instruction, 3, ElnaTacOperand.pseudo, "$unary", 6); operand_type^ := ElnaTacOperand.pseudo; operand_value^ := "$unary"; @@ -2845,14 +2857,27 @@ begin index_instructions := elna_instruction_list_concatenate(index_instructions, add_instruction); array_instructions := elna_tac_designator(array_access_expression^.array, symbol_table, @is_address, operand_type, operand_value, operand_length); + elna_instruction_list_concatenate(offset_instruction, array_instructions); + if is_address then + array_instructions := _elna_tac_instruction_create(ElnaTacOperator.copy); + _elna_tac_instruction_set_operand(array_instructions, 1, ElnaTacOperand.pseudo, "$unary", 6); + _elna_tac_instruction_set_operand(array_instructions, 2, operand_type^, operand_value^, operand_length^) + else + array_instructions := _elna_tac_instruction_create(ElnaTacOperator.get_address); + _elna_tac_instruction_set_operand(array_instructions, 1, ElnaTacOperand.pseudo, "$unary", 6); + _elna_tac_instruction_set_operand(array_instructions, 2, operand_type^, operand_value^, operand_length^) + end; + elna_instruction_list_concatenate(offset_instruction, array_instructions); + + operand_type^ := ElnaTacOperand.pseudo; + operand_value^ := "$unary"; + operand_length^ := 6; add_instruction := _elna_tac_instruction_create(ElnaTacOperator.add); _elna_tac_instruction_set_operand(add_instruction, 1, operand_type^, operand_value^, operand_length^); _elna_tac_instruction_set_operand(add_instruction, 2, operand_type^, operand_value^, operand_length^); _elna_tac_instruction_set_operand(add_instruction, 3, ElnaTacOperand.pseudo, "$lhs", 4); - elna_instruction_list_concatenate(offset_instruction, array_instructions); - return elna_instruction_list_concatenate(index_instructions, add_instruction) end; @@ -4171,29 +4196,21 @@ proc elna_tac_variable_declaration(parser_tree: ^ElnaTreeVariableDeclaration); var name: Word; name_length: Word; - variable_type: ^ElnaTreeNamedTypeExpression; + variable_type: ^ElnaType; result: ^ElnaInstructionDeclaration; + variable_info: ^ElnaSymbolTemporaryInfo; begin result := malloc(#size(ElnaInstructionDeclaration)); - - result^.next := nil; - name := parser_tree^.name; name_length := parser_tree^.length; - variable_type := parser_tree^._type; + variable_info := _symbol_table_lookup(@symbol_table_global, name, name_length); + variable_type := variable_info^.variable_type; + result^.next := nil; result^.name := name; result^.length := name_length; + result^.body := variable_type^.size; - name := variable_type^.name; - name_length := variable_type^.length; - - if string_compare("Array", 5, name, name_length) then - (* Else we assume this is a zeroed 4096 bytes big array. *) - result^.body := 4096 - else - result^.body := 4 - end; return result end; diff --git a/boot/stage19/cl.elna b/boot/stage19/cl.elna index e035020..49fbbed 100644 --- a/boot/stage19/cl.elna +++ b/boot/stage19/cl.elna @@ -299,7 +299,7 @@ type ElnaSymbolTemporaryInfo = record kind: ElnaSymbolInfoKind; offset: Word; - variable_type: Word + variable_type: ^ElnaType end; ElnaSymbolProcedureInfo = record kind: ElnaSymbolInfoKind; @@ -436,6 +436,12 @@ type _goto, eof ); + ElnaLexerCursor = record + state: ElnaLexerState; + start: Word; + finish: Word + end; + ElnaTacOperator = ( get_address, add, @@ -464,7 +470,7 @@ type label, _return ); - ElnaTacKind = (list, immediate, symbol, pseudo, pseudo_mem); + ElnaTacKind = (list, immediate, symbol, pseudo); ElnaTacOperand = record kind: ElnaTacKind; value: Word; @@ -475,6 +481,21 @@ type operator: ElnaTacOperator; operands: [3]ElnaTacOperand end; + ElnaTacProcedure = record + next: Word; + name: Word; + length: Word; + body: Word; + stack: Word; + parameters: Word; + count: Word + end; + ElnaTacStaticVariable = record + next: Word; + name: Word; + length: Word; + body: Word + end; ElnaRtlOperator = ( li, @@ -505,7 +526,7 @@ type allocate_stack, ret ); - ElnaRtlKind = (register, immediate, symbol, pseudo, offset); + ElnaRtlKind = (register, immediate, symbol, pseudo, offset, pseudo_mem); ElnaRtlOperand = record kind: ElnaRtlKind; value: Word; @@ -555,10 +576,18 @@ type end; var - symbol_table_global: Array; - compiler_strings: Array; - classification: Array; - variable_map: Array; + symbol_table_global: [1024]Word; + variable_map: [1024]Word; + compiler_strings: [1024]Word; + + classification: [256]Word; + (** + * Lexer state is saved after the transition tables. + * Each transition table entry is 8 bytes long. The table has 19 rows (transition states) + * and 23 columns (character classes), so 3496 = 8 * 19 * 23. + *) + transition_table: [874]Word; + lexer_state: ElnaLexerCursor; source_code: Word; compiler_strings_position: Word; @@ -1695,20 +1724,17 @@ end; proc elna_parser_integer_literal(); var - integer_token: Word; integer_length: Word; result: ^ElnaTreeIntegerLiteral; buffer: Word; begin result := malloc(#size(ElnaTreeIntegerLiteral)); + integer_length := lexer_state.finish - lexer_state.start; - integer_token := _elna_lexer_global_get_start(); - integer_length := _elna_lexer_global_get_end() - integer_token; - - _elna_lexer_skip_token(); buffer := malloc(integer_length + 1); bzero(buffer, integer_length + 1); - memcpy(buffer, integer_token, integer_length); + memcpy(buffer, lexer_state.start, integer_length); + _elna_lexer_skip_token(); result^.kind := ElnaTreeKind.integer_literal; result^.value := atoi(buffer); @@ -1719,18 +1745,16 @@ end; proc elna_parser_boolean_literal(); var - boolean_token: Word; result: ^ElnaTreeBooleanLiteral; begin result := malloc(#size(ElnaTreeBooleanLiteral)); - boolean_token := _elna_lexer_global_get_start(); - _elna_lexer_skip_token(); - result^.kind := ElnaTreeKind.boolean_literal; - result^.value := string_compare(boolean_token, 4, "true", 4); + result^.value := string_compare(lexer_state.start, 4, "true", 4); result^.type_decoration := nil; + _elna_lexer_skip_token(); + return result end; @@ -1776,21 +1800,15 @@ end; proc elna_parser_character_literal(); var - character: Word; - character_length: Word; result: ^ElnaTreeCharacterLiteral; begin result := malloc(#size(ElnaTreeCharacterLiteral)); - character := _elna_lexer_global_get_start(); - character_length := _elna_lexer_global_get_end(); - character_length := character_length - character; - _elna_lexer_skip_token(); - result^.kind := ElnaTreeKind.character_literal; - result^.value := character; - result^.length := character_length; + result^.value := lexer_state.start; + result^.length := lexer_state.finish - lexer_state.start; result^.type_decoration := nil; + _elna_lexer_skip_token(); return result end; @@ -1806,21 +1824,17 @@ end; proc elna_parser_variable_expression(); var - name_pointer: Word; - name_length: Word; result: ^ElnaTreeVariableExpression; begin - name_pointer := _elna_lexer_global_get_start(); - name_length := _elna_lexer_global_get_end() - name_pointer; - _elna_lexer_skip_token(); - result := malloc(#size(ElnaTreeVariableExpression)); result^.kind := ElnaTreeKind.variable_expression; - result^.name := name_pointer; - result^.length := name_length; + result^.name := lexer_state.start; + result^.length := lexer_state.finish - lexer_state.start; result^.type_decoration := nil; + _elna_lexer_skip_token(); + return result end; @@ -1844,21 +1858,17 @@ end; proc elna_parser_string_literal(); var - length: Word; - token_start: Word; result: ^ElnaTreeStringLiteral; begin result := malloc(#size(ElnaTreeStringLiteral)); - token_start := _elna_lexer_global_get_start(); - length := _string_length(token_start); - _elna_lexer_skip_token(); - result^.kind := ElnaTreeKind.string_literal; - result^.value := token_start; - result^.length := length; + result^.value := lexer_state.start; + result^.length := lexer_state.finish - lexer_state.start; result^.type_decoration := nil; + _elna_lexer_skip_token(); + return result end; @@ -1893,8 +1903,8 @@ begin result := malloc(#size(ElnaTreeTraitExpression)); result^.kind := ElnaTreeKind.trait_expression; - result^.name := _elna_lexer_global_get_start(); - result^.length := _elna_lexer_global_get_end() - result^.name; + result^.name := lexer_state.start; + result^.length := lexer_state.finish - lexer_state.start; _elna_lexer_skip_token(); _elna_lexer_read_token(@token_kind); @@ -2049,6 +2059,21 @@ 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); +var + instruction: Word; +begin + if is_address then + instruction := elna_tac_instruction_create(ElnaTacOperator.copy) + 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); + + return instruction +end; + proc elna_tac_unary_expression(parser_node: ^ElnaTreeUnaryExpression, symbol_table: Word, operand_type: Word, operand_value: Word, operand_length: Word); var token_kind: Word; @@ -2074,15 +2099,8 @@ begin elna_tac_generate_pseudo(operand_type, operand_value, operand_length); if operator = '@' then - if is_address then - instruction := elna_tac_instruction_create(ElnaTacOperator.copy); - elna_tac_instruction_set_operand(instruction, 1, operand_type^, operand_value^, operand_length^); - elna_tac_instruction_set_operand(instruction, 2, base_type, base_value, base_length) - else - 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, base_type, base_value, base_length) - end + instruction := elna_tac_copy_address(is_address, base_type, base_value, base_length, + operand_type^, operand_value^, operand_length^) elsif operator = '-' then instruction := elna_tac_instruction_create(ElnaTacOperator.negate); elna_tac_instruction_set_operand(instruction, 1, operand_type^, operand_value^, operand_length^); @@ -2345,8 +2363,8 @@ begin result := malloc(#size(ElnaTreeGotoStatement)); result^.kind := ElnaTreeKind.goto_statement; result^.next := nil; - result^.label := _elna_lexer_global_get_start(); - result^.length := _elna_lexer_global_get_end() - result^.label; + result^.label := lexer_state.start; + result^.length := lexer_state.finish - lexer_state.start; _elna_lexer_skip_token(); @@ -2373,23 +2391,19 @@ end; proc elna_parser_label_declaration(); var token_kind: Word; - label_name: Word; - label_length: Word; result: ^ElnaTreeGotoStatement; begin _elna_lexer_skip_token(); _elna_lexer_read_token(@token_kind); - label_name := _elna_lexer_global_get_start(); - label_length := _elna_lexer_global_get_end() - label_name; - _elna_lexer_skip_token(); - result := malloc(#size(ElnaTreeLabelDeclaration)); result^.kind := ElnaTreeKind.label_declaration; result^.next := nil; - result^.label := label_name; - result^.length := label_length; + result^.label := lexer_state.start; + result^.length := lexer_state.finish - lexer_state.start; + + _elna_lexer_skip_token(); return result end; @@ -2454,8 +2468,8 @@ begin result^.kind := ElnaTreeKind.field_access_expression; result^.type_decoration := nil; result^.aggregate := aggregate; - result^.field := _elna_lexer_global_get_start(); - result^.length := _elna_lexer_global_get_end() - result^.field; + result^.field := lexer_state.start; + result^.length := lexer_state.finish - lexer_state.start; _elna_lexer_skip_token(); @@ -2567,10 +2581,13 @@ begin end; elna_tac_generate_pseudo(operand_type, operand_value, operand_length); + last_instruction := elna_tac_copy_address(is_address, base_type, base_value, base_length, operand_type^, 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_type^, 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, base_type, base_value, base_length); + elna_tac_instruction_set_operand(last_instruction, 3, operand_type^, operand_value^, operand_length^); return elna_instruction_list_concatenate(first_instruction, last_instruction) end; @@ -2585,6 +2602,9 @@ var inter_type: Word; inter_value: Word; inter_length: Word; + index_type: Word; + index_value: Word; + index_length: Word; aggregate_type: ^ElnaTypeArray; designator_base: ^ElnaTreeExpression; element_type: ^ElnaType; @@ -2594,29 +2614,33 @@ begin element_type := aggregate_type^.base; index_instructions := elna_tac_binary_expression(array_access_expression^.index, symbol_table, @inter_type, @inter_value, @inter_length); - elna_tac_generate_pseudo(operand_type, operand_value, operand_length); + elna_tac_generate_pseudo(@index_type, @index_value, @index_length); add_instruction := elna_tac_instruction_create(ElnaTacOperator.subtract); - elna_tac_instruction_set_operand(add_instruction, 1, operand_type^, operand_value^, operand_length^); + elna_tac_instruction_set_operand(add_instruction, 1, index_type, index_value, index_length); elna_tac_instruction_set_operand(add_instruction, 2, inter_type, inter_value, inter_length); elna_tac_instruction_set_operand(add_instruction, 3, ElnaTacKind.immediate, 1, 0); offset_instruction := elna_tac_instruction_create(ElnaTacOperator.multiply); - elna_tac_instruction_set_operand(offset_instruction, 1, operand_type^, operand_value^, operand_length^); - elna_tac_instruction_set_operand(offset_instruction, 2, operand_type^, operand_value^, operand_length^); + 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); 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_type, @inter_value, @inter_length); + elna_tac_generate_pseudo(operand_type, operand_value, operand_length); + elna_instruction_list_concatenate(offset_instruction, array_instructions); + + array_instructions := elna_tac_copy_address(is_address, inter_type, inter_value, inter_length, + operand_type^, operand_value^, operand_length^); + elna_instruction_list_concatenate(offset_instruction, array_instructions); add_instruction := elna_tac_instruction_create(ElnaTacOperator.add); elna_tac_instruction_set_operand(add_instruction, 1, operand_type^, operand_value^, operand_length^); - elna_tac_instruction_set_operand(add_instruction, 2, inter_type, inter_value, inter_length); - elna_tac_instruction_set_operand(add_instruction, 3, operand_type^, operand_value^, operand_length^); - - elna_instruction_list_concatenate(offset_instruction, array_instructions); + elna_tac_instruction_set_operand(add_instruction, 2, operand_type^, operand_value^, operand_length^); + elna_tac_instruction_set_operand(add_instruction, 3, index_type, index_value, index_length); return elna_instruction_list_concatenate(index_instructions, add_instruction) end; @@ -3042,8 +3066,6 @@ var entry: Word; member_count: Word; memory_start: Word; - field_name: Word; - field_length: Word; field_type: Word; token_kind: Word; result: ^ElnaTreeEnumerationTypeExpression; @@ -3061,13 +3083,10 @@ begin entry := malloc(16); member_count := member_count + 1; - field_name := _elna_lexer_global_get_start(); - field_length := _elna_lexer_global_get_end() - field_name; - - entry^ := field_name; + entry^ := lexer_state.start; entry := entry + 4; - entry^ := field_length; + entry^ := lexer_state.finish - lexer_state.start; entry := entry + 4; (* Skip the identifier. *) @@ -3110,8 +3129,6 @@ end; proc elna_parser_enumeration_type_expression(); var token_kind: Word; - enumeration_name: Word; - name_length: Word; memory_start: Word; member_count: Word; result: ^ElnaTreeEnumerationTypeExpression; @@ -3130,13 +3147,10 @@ begin entry := malloc(12); member_count := member_count + 1; - enumeration_name := _elna_lexer_global_get_start(); - name_length := _elna_lexer_global_get_end() - enumeration_name; - - entry^ := enumeration_name; + entry^ := lexer_state.start; entry := entry + 4; - entry^ := name_length; + entry^ := lexer_state.finish - lexer_state.start; entry := entry + 4; entry^ := 0; @@ -3308,8 +3322,8 @@ begin result := malloc(#size(ElnaTreeNamedTypeExpression)); result^.kind := ElnaTreeKind.named_type_expression; - result^.name := _elna_lexer_global_get_start(); - result^.length := _elna_lexer_global_get_end() - result^.name; + result^.name := lexer_state.start; + result^.length := lexer_state.finish - lexer_state.start; _elna_lexer_skip_token(); return result @@ -3446,11 +3460,11 @@ end; proc elna_name_procedure_temporary(parser_node: ^ElnaTreeVariableDeclaration, variable_index: Word, symbol_table: Word); var info: Word; - variable_type1: Word; + variable_type: Word; begin - variable_type1 := elna_name_type_expression(parser_node^._type); + variable_type := elna_name_type_expression(parser_node^._type); - info := _temporary_info_create(variable_index, variable_type1); + info := _temporary_info_create(variable_index, variable_type); _symbol_table_enter(symbol_table, parser_node^.name, parser_node^.length, info) end; @@ -3488,8 +3502,8 @@ begin _elna_lexer_read_token(@token_kind); - result^.name := _elna_lexer_global_get_start(); - result^.length := _elna_lexer_global_get_end() - result^.name; + result^.name := lexer_state.start; + result^.length := lexer_state.finish - lexer_state.start; (* Skip procedure name. *) _elna_lexer_skip_token(); @@ -3584,13 +3598,13 @@ begin return parameter_list end; -proc elna_rtl_global_declaration(tac_declaration: ^ElnaInstructionDeclaration); +proc elna_rtl_global_declaration(tac_declaration: ^ElnaTacStaticVariable); var result: ^ElnaInstructionDeclaration; begin result := malloc(#size(ElnaInstructionDeclaration)); - result^.next := 0; + result^.next := nil; result^.name := tac_declaration^.name; result^.length := tac_declaration^.length; result^.body := tac_declaration^.body; @@ -3709,13 +3723,13 @@ begin return result end; -proc elna_rtl_globals(tac_procedure: ^ElnaInstructionDeclaration); +proc elna_rtl_globals(tac_procedure: ^ElnaTacStaticVariable); var current_copy: ^ElnaInstructionDeclaration; next_copy: ^ElnaInstructionDeclaration; first_copy: ^ElnaInstructionDeclaration; begin - if tac_procedure <> 0 then + if tac_procedure <> nil then first_copy := elna_rtl_global_declaration(tac_procedure); tac_procedure := tac_procedure^.next else @@ -3725,7 +3739,7 @@ begin .elna_rtl_globals_start; - if tac_procedure <> 0 then + if tac_procedure <> nil then next_copy := elna_rtl_global_declaration(tac_procedure); tac_procedure := tac_procedure^.next; @@ -3817,8 +3831,8 @@ var result: ^ElnaTreeTypeDeclaration; begin _elna_lexer_read_token(@token_kind); - type_name := _elna_lexer_global_get_start(); - name_length := _elna_lexer_global_get_end() - type_name; + type_name := lexer_state.start; + name_length := lexer_state.finish - lexer_state.start; _elna_lexer_skip_token(); _elna_lexer_read_token(@token_kind); @@ -3899,50 +3913,44 @@ var token_kind: Word; name: Word; name_length: Word; - variable_type1: Word; + variable_type: Word; result: ^ElnaTreeVariableDeclaration; begin _elna_lexer_read_token(@token_kind); - name := _elna_lexer_global_get_start(); - name_length := _elna_lexer_global_get_end() - name; + name := lexer_state.start; + name_length := lexer_state.finish - lexer_state.start; (* Skip the variable name and colon with the type. *) _elna_lexer_skip_token(); _elna_lexer_read_token(@token_kind); _elna_lexer_skip_token(); - variable_type1 := elna_parser_type_expression(); + variable_type := elna_parser_type_expression(); result := malloc(#size(ElnaTreeVariableDeclaration)); result^.kind := ElnaTreeKind.variable_declaration; result^.next := nil; result^.name := name; result^.length := name_length; - result^._type := variable_type1; + result^._type := variable_type; return result end; proc elna_tac_variable_declaration(parser_tree: ^ElnaTreeVariableDeclaration); var - variable_type: ^ElnaTreeNamedTypeExpression; - result: ^ElnaInstructionDeclaration; + result: ^ElnaTacStaticVariable; + variable_info: ^ElnaSymbolTemporaryInfo; begin - result := malloc(#size(ElnaInstructionDeclaration)); + result := malloc(#size(ElnaTacStaticVariable)); + variable_info := _symbol_table_lookup(@symbol_table_global, parser_tree^.name, parser_tree^.length); result^.next := nil; - variable_type := parser_tree^._type; - result^.name := parser_tree^.name; result^.length := parser_tree^.length; + result^.body := variable_info^.variable_type^.size; - if string_compare("Array", 5, variable_type^.name, variable_type^.length) then - (* Else we assume this is a zeroed 4096 bytes big array. *) - result^.body := 4096 - else - result^.body := 4 - end; return result end; @@ -3988,9 +3996,9 @@ end; proc elna_tac_var_part(parser_node: ^ElnaTreeDeclaration); var - node: ^ElnaInstructionDeclaration; - current_variable: ^ElnaInstructionDeclaration; - first_variable: ^ElnaInstructionDeclaration; + node: ^ElnaTacStaticVariable; + current_variable: ^ElnaTacStaticVariable; + first_variable: ^ElnaTacStaticVariable; begin first_variable := 0; if parser_node = 0 then @@ -4052,7 +4060,7 @@ end; *) proc elna_tac_module_declaration(parser_node: ^ElnaTreeModuleDeclaration); var - data_part: Word; + data_part: ^ElnaTacStaticVariable; code_part: Word; begin data_part := elna_tac_var_part(parser_node^.globals); @@ -4585,42 +4593,6 @@ begin current_type^.size := 1; current_info := _type_info_create(current_type); _symbol_table_enter(@symbol_table_global, "Bool", 4, current_info); - - current_type := malloc(#size(ElnaType)); - current_type^.kind := ElnaTypeKind.primitive; - current_type^.size := 4096; - current_info := _type_info_create(current_type); - _symbol_table_enter(@symbol_table_global, "Array", 5, current_info) -end; - -(** - * Assigns some value to at array index. - * - * Parameters: - * array - Array pointer. - * index - Index (word offset into the array). - * data - Data to assign. - *) -proc _assign_at(array: Word, index: Word, data: Word); -var - target: Word; -begin - target := index - 1; - target := target * 4; - target := array + target; - - target^ := data -end; - -proc _get_at(array: Word, index: Word); -var - target: Word; -begin - target := index - 1; - target := target * 4; - target := array + target; - - return target^ end; (** @@ -4630,140 +4602,140 @@ proc _elna_lexer_classifications(); var code: Word; begin - _assign_at(@classification, 1, ElnaLexerClass.eof); - _assign_at(@classification, 2, ElnaLexerClass.invalid); - _assign_at(@classification, 3, ElnaLexerClass.invalid); - _assign_at(@classification, 4, ElnaLexerClass.invalid); - _assign_at(@classification, 5, ElnaLexerClass.invalid); - _assign_at(@classification, 6, ElnaLexerClass.invalid); - _assign_at(@classification, 7, ElnaLexerClass.invalid); - _assign_at(@classification, 8, ElnaLexerClass.invalid); - _assign_at(@classification, 9, ElnaLexerClass.invalid); - _assign_at(@classification, 10, ElnaLexerClass.space); - _assign_at(@classification, 11, ElnaLexerClass.space); - _assign_at(@classification, 12, ElnaLexerClass.invalid); - _assign_at(@classification, 13, ElnaLexerClass.invalid); - _assign_at(@classification, 14, ElnaLexerClass.space); - _assign_at(@classification, 15, ElnaLexerClass.invalid); - _assign_at(@classification, 16, ElnaLexerClass.invalid); - _assign_at(@classification, 17, ElnaLexerClass.invalid); - _assign_at(@classification, 18, ElnaLexerClass.invalid); - _assign_at(@classification, 19, ElnaLexerClass.invalid); - _assign_at(@classification, 20, ElnaLexerClass.invalid); - _assign_at(@classification, 21, ElnaLexerClass.invalid); - _assign_at(@classification, 22, ElnaLexerClass.invalid); - _assign_at(@classification, 23, ElnaLexerClass.invalid); - _assign_at(@classification, 24, ElnaLexerClass.invalid); - _assign_at(@classification, 25, ElnaLexerClass.invalid); - _assign_at(@classification, 26, ElnaLexerClass.invalid); - _assign_at(@classification, 27, ElnaLexerClass.invalid); - _assign_at(@classification, 28, ElnaLexerClass.invalid); - _assign_at(@classification, 29, ElnaLexerClass.invalid); - _assign_at(@classification, 30, ElnaLexerClass.invalid); - _assign_at(@classification, 31, ElnaLexerClass.invalid); - _assign_at(@classification, 32, ElnaLexerClass.invalid); - _assign_at(@classification, 33, ElnaLexerClass.space); - _assign_at(@classification, 34, ElnaLexerClass.single); - _assign_at(@classification, 35, ElnaLexerClass.double_quote); - _assign_at(@classification, 36, ElnaLexerClass.number_sign); - _assign_at(@classification, 37, ElnaLexerClass.other); - _assign_at(@classification, 38, ElnaLexerClass.single); - _assign_at(@classification, 39, ElnaLexerClass.single); - _assign_at(@classification, 40, ElnaLexerClass.single_quote); - _assign_at(@classification, 41, ElnaLexerClass.left_paren); - _assign_at(@classification, 42, ElnaLexerClass.right_paren); - _assign_at(@classification, 43, ElnaLexerClass.asterisk); - _assign_at(@classification, 44, ElnaLexerClass.single); - _assign_at(@classification, 45, ElnaLexerClass.single); - _assign_at(@classification, 46, ElnaLexerClass.minus); - _assign_at(@classification, 47, ElnaLexerClass.dot); - _assign_at(@classification, 48, ElnaLexerClass.single); - _assign_at(@classification, 49, ElnaLexerClass.zero); - _assign_at(@classification, 50, ElnaLexerClass.digit); - _assign_at(@classification, 51, ElnaLexerClass.digit); - _assign_at(@classification, 52, ElnaLexerClass.digit); - _assign_at(@classification, 53, ElnaLexerClass.digit); - _assign_at(@classification, 54, ElnaLexerClass.digit); - _assign_at(@classification, 55, ElnaLexerClass.digit); - _assign_at(@classification, 56, ElnaLexerClass.digit); - _assign_at(@classification, 57, ElnaLexerClass.digit); - _assign_at(@classification, 58, ElnaLexerClass.digit); - _assign_at(@classification, 59, ElnaLexerClass.colon); - _assign_at(@classification, 60, ElnaLexerClass.single); - _assign_at(@classification, 61, ElnaLexerClass.less); - _assign_at(@classification, 62, ElnaLexerClass.equals); - _assign_at(@classification, 63, ElnaLexerClass.greater); - _assign_at(@classification, 64, ElnaLexerClass.other); - _assign_at(@classification, 65, ElnaLexerClass.single); - _assign_at(@classification, 66, ElnaLexerClass.alpha); - _assign_at(@classification, 67, ElnaLexerClass.alpha); - _assign_at(@classification, 68, ElnaLexerClass.alpha); - _assign_at(@classification, 69, ElnaLexerClass.alpha); - _assign_at(@classification, 70, ElnaLexerClass.alpha); - _assign_at(@classification, 71, ElnaLexerClass.alpha); - _assign_at(@classification, 72, ElnaLexerClass.alpha); - _assign_at(@classification, 73, ElnaLexerClass.alpha); - _assign_at(@classification, 74, ElnaLexerClass.alpha); - _assign_at(@classification, 75, ElnaLexerClass.alpha); - _assign_at(@classification, 76, ElnaLexerClass.alpha); - _assign_at(@classification, 77, ElnaLexerClass.alpha); - _assign_at(@classification, 78, ElnaLexerClass.alpha); - _assign_at(@classification, 79, ElnaLexerClass.alpha); - _assign_at(@classification, 80, ElnaLexerClass.alpha); - _assign_at(@classification, 81, ElnaLexerClass.alpha); - _assign_at(@classification, 82, ElnaLexerClass.alpha); - _assign_at(@classification, 83, ElnaLexerClass.alpha); - _assign_at(@classification, 84, ElnaLexerClass.alpha); - _assign_at(@classification, 85, ElnaLexerClass.alpha); - _assign_at(@classification, 86, ElnaLexerClass.alpha); - _assign_at(@classification, 87, ElnaLexerClass.alpha); - _assign_at(@classification, 88, ElnaLexerClass.alpha); - _assign_at(@classification, 89, ElnaLexerClass.alpha); - _assign_at(@classification, 90, ElnaLexerClass.alpha); - _assign_at(@classification, 91, ElnaLexerClass.alpha); - _assign_at(@classification, 92, ElnaLexerClass.single); - _assign_at(@classification, 93, ElnaLexerClass.backslash); - _assign_at(@classification, 94, ElnaLexerClass.single); - _assign_at(@classification, 95, ElnaLexerClass.single); - _assign_at(@classification, 96, ElnaLexerClass.alpha); - _assign_at(@classification, 97, ElnaLexerClass.other); - _assign_at(@classification, 98, ElnaLexerClass.hex); - _assign_at(@classification, 99, ElnaLexerClass.hex); - _assign_at(@classification, 100, ElnaLexerClass.hex); - _assign_at(@classification, 101, ElnaLexerClass.hex); - _assign_at(@classification, 102, ElnaLexerClass.hex); - _assign_at(@classification, 103, ElnaLexerClass.hex); - _assign_at(@classification, 104, ElnaLexerClass.alpha); - _assign_at(@classification, 105, ElnaLexerClass.alpha); - _assign_at(@classification, 106, ElnaLexerClass.alpha); - _assign_at(@classification, 107, ElnaLexerClass.alpha); - _assign_at(@classification, 108, ElnaLexerClass.alpha); - _assign_at(@classification, 109, ElnaLexerClass.alpha); - _assign_at(@classification, 110, ElnaLexerClass.alpha); - _assign_at(@classification, 111, ElnaLexerClass.alpha); - _assign_at(@classification, 112, ElnaLexerClass.alpha); - _assign_at(@classification, 113, ElnaLexerClass.alpha); - _assign_at(@classification, 114, ElnaLexerClass.alpha); - _assign_at(@classification, 115, ElnaLexerClass.alpha); - _assign_at(@classification, 116, ElnaLexerClass.alpha); - _assign_at(@classification, 117, ElnaLexerClass.alpha); - _assign_at(@classification, 118, ElnaLexerClass.alpha); - _assign_at(@classification, 119, ElnaLexerClass.alpha); - _assign_at(@classification, 120, ElnaLexerClass.alpha); - _assign_at(@classification, 121, ElnaLexerClass.x); - _assign_at(@classification, 122, ElnaLexerClass.alpha); - _assign_at(@classification, 123, ElnaLexerClass.alpha); - _assign_at(@classification, 124, ElnaLexerClass.other); - _assign_at(@classification, 125, ElnaLexerClass.single); - _assign_at(@classification, 126, ElnaLexerClass.other); - _assign_at(@classification, 127, ElnaLexerClass.single); - _assign_at(@classification, 128, ElnaLexerClass.invalid); + classification[1] := ElnaLexerClass.eof; + classification[2] := ElnaLexerClass.invalid; + classification[3] := ElnaLexerClass.invalid; + classification[4] := ElnaLexerClass.invalid; + classification[5] := ElnaLexerClass.invalid; + classification[6] := ElnaLexerClass.invalid; + classification[7] := ElnaLexerClass.invalid; + classification[8] := ElnaLexerClass.invalid; + classification[9] := ElnaLexerClass.invalid; + classification[10] := ElnaLexerClass.space; + classification[11] := ElnaLexerClass.space; + classification[12] := ElnaLexerClass.invalid; + classification[13] := ElnaLexerClass.invalid; + classification[14] := ElnaLexerClass.space; + classification[15] := ElnaLexerClass.invalid; + classification[16] := ElnaLexerClass.invalid; + classification[17] := ElnaLexerClass.invalid; + classification[18] := ElnaLexerClass.invalid; + classification[19] := ElnaLexerClass.invalid; + classification[20] := ElnaLexerClass.invalid; + classification[21] := ElnaLexerClass.invalid; + classification[22] := ElnaLexerClass.invalid; + classification[23] := ElnaLexerClass.invalid; + classification[24] := ElnaLexerClass.invalid; + classification[25] := ElnaLexerClass.invalid; + classification[26] := ElnaLexerClass.invalid; + classification[27] := ElnaLexerClass.invalid; + classification[28] := ElnaLexerClass.invalid; + classification[29] := ElnaLexerClass.invalid; + classification[30] := ElnaLexerClass.invalid; + classification[31] := ElnaLexerClass.invalid; + classification[32] := ElnaLexerClass.invalid; + classification[33] := ElnaLexerClass.space; + classification[34] := ElnaLexerClass.single; + classification[35] := ElnaLexerClass.double_quote; + classification[36] := ElnaLexerClass.number_sign; + classification[37] := ElnaLexerClass.other; + classification[38] := ElnaLexerClass.single; + classification[39] := ElnaLexerClass.single; + classification[40] := ElnaLexerClass.single_quote; + classification[41] := ElnaLexerClass.left_paren; + classification[42] := ElnaLexerClass.right_paren; + classification[43] := ElnaLexerClass.asterisk; + classification[44] := ElnaLexerClass.single; + classification[45] := ElnaLexerClass.single; + classification[46] := ElnaLexerClass.minus; + classification[47] := ElnaLexerClass.dot; + classification[48] := ElnaLexerClass.single; + classification[49] := ElnaLexerClass.zero; + classification[50] := ElnaLexerClass.digit; + classification[51] := ElnaLexerClass.digit; + classification[52] := ElnaLexerClass.digit; + classification[53] := ElnaLexerClass.digit; + classification[54] := ElnaLexerClass.digit; + classification[55] := ElnaLexerClass.digit; + classification[56] := ElnaLexerClass.digit; + classification[57] := ElnaLexerClass.digit; + classification[58] := ElnaLexerClass.digit; + classification[59] := ElnaLexerClass.colon; + classification[60] := ElnaLexerClass.single; + classification[61] := ElnaLexerClass.less; + classification[62] := ElnaLexerClass.equals; + classification[63] := ElnaLexerClass.greater; + classification[64] := ElnaLexerClass.other; + classification[65] := ElnaLexerClass.single; + classification[66] := ElnaLexerClass.alpha; + classification[67] := ElnaLexerClass.alpha; + classification[68] := ElnaLexerClass.alpha; + classification[69] := ElnaLexerClass.alpha; + classification[70] := ElnaLexerClass.alpha; + classification[71] := ElnaLexerClass.alpha; + classification[72] := ElnaLexerClass.alpha; + classification[73] := ElnaLexerClass.alpha; + classification[74] := ElnaLexerClass.alpha; + classification[75] := ElnaLexerClass.alpha; + classification[76] := ElnaLexerClass.alpha; + classification[77] := ElnaLexerClass.alpha; + classification[78] := ElnaLexerClass.alpha; + classification[79] := ElnaLexerClass.alpha; + classification[80] := ElnaLexerClass.alpha; + classification[81] := ElnaLexerClass.alpha; + classification[82] := ElnaLexerClass.alpha; + classification[83] := ElnaLexerClass.alpha; + classification[84] := ElnaLexerClass.alpha; + classification[85] := ElnaLexerClass.alpha; + classification[86] := ElnaLexerClass.alpha; + classification[87] := ElnaLexerClass.alpha; + classification[88] := ElnaLexerClass.alpha; + classification[89] := ElnaLexerClass.alpha; + classification[90] := ElnaLexerClass.alpha; + classification[91] := ElnaLexerClass.alpha; + classification[92] := ElnaLexerClass.single; + classification[93] := ElnaLexerClass.backslash; + classification[94] := ElnaLexerClass.single; + classification[95] := ElnaLexerClass.single; + classification[96] := ElnaLexerClass.alpha; + classification[97] := ElnaLexerClass.other; + classification[98] := ElnaLexerClass.hex; + classification[99] := ElnaLexerClass.hex; + classification[100] := ElnaLexerClass.hex; + classification[101] := ElnaLexerClass.hex; + classification[102] := ElnaLexerClass.hex; + classification[103] := ElnaLexerClass.hex; + classification[104] := ElnaLexerClass.alpha; + classification[105] := ElnaLexerClass.alpha; + classification[106] := ElnaLexerClass.alpha; + classification[107] := ElnaLexerClass.alpha; + classification[108] := ElnaLexerClass.alpha; + classification[109] := ElnaLexerClass.alpha; + classification[110] := ElnaLexerClass.alpha; + classification[111] := ElnaLexerClass.alpha; + classification[112] := ElnaLexerClass.alpha; + classification[113] := ElnaLexerClass.alpha; + classification[114] := ElnaLexerClass.alpha; + classification[115] := ElnaLexerClass.alpha; + classification[116] := ElnaLexerClass.alpha; + classification[117] := ElnaLexerClass.alpha; + classification[118] := ElnaLexerClass.alpha; + classification[119] := ElnaLexerClass.alpha; + classification[120] := ElnaLexerClass.alpha; + classification[121] := ElnaLexerClass.x; + classification[122] := ElnaLexerClass.alpha; + classification[123] := ElnaLexerClass.alpha; + classification[124] := ElnaLexerClass.other; + classification[125] := ElnaLexerClass.single; + classification[126] := ElnaLexerClass.other; + classification[127] := ElnaLexerClass.single; + classification[128] := ElnaLexerClass.invalid; code := 129; (* Set the remaining 129 - 256 bytes to transitionClassOther. *) .create_classification_loop; - _assign_at(@classification, code, ElnaLexerClass.other); + classification[code] := ElnaLexerClass.other; code := code + 1; if code < 257 then @@ -4773,7 +4745,6 @@ end; proc _elna_lexer_get_transition(current_state: Word, character_class: Word); var - transition_table: Word; row_position: Word; column_position: Word; target: Word; @@ -4786,7 +4757,7 @@ begin column_position := character_class - 1; column_position := column_position * 8; - target := _elna_lexer_get_transition_table(); + target := @transition_table; target := target + row_position; return target + column_position @@ -4979,72 +4950,6 @@ begin _elna_lexer_set_transition(ElnaLexerState.trait, ElnaLexerClass.x, ElnaLexerAction.accumulate, ElnaLexerState.trait) end; -(** - * Transition table is saved after character classification table. - * Each character entry is 1 word long and there are 256 characters. - * 1024 = 256 * 4 - *) -proc _elna_lexer_get_transition_table(); - return @classification + 1024 -end; - -(** - * Lexer state is saved after the transition tables. - * Each transition table entry is 8 bytes long. The table has 19 rows (transition states) - * and 23 columns (character classes), so 3496 = 8 * 19 * 23. - *) -proc _elna_lexer_global_state(); -var - result: Word; -begin - result := _elna_lexer_get_transition_table(); - return result + 3496 -end; - -(** - * Gets pointer to the token start. - *) -proc _elna_lexer_global_get_start(); -var - target: Word; -begin - target := _elna_lexer_global_state() + 4; - return target^ -end; - -(** - * Sets pointer to the token start. - *) -proc _elna_lexer_global_set_start(new_start: Word); -var - target: Word; -begin - target := _elna_lexer_global_state() + 4; - target^ := new_start -end; - -(** - * Gets pointer to the token end. - *) -proc _elna_lexer_global_get_end(); -var - target: Word; -begin - target := _elna_lexer_global_state() + 8; - return target^ -end; - -(** - * Sets pointer to the token end. - *) -proc _elna_lexer_global_set_end(new_start: Word); -var - target: Word; -begin - target := _elna_lexer_global_state() + 8; - target^ := new_start -end; - proc _elna_lexer_transition_get_action(this: Word); return this^ end; @@ -5070,15 +4975,10 @@ end; * Resets the lexer state for reading the next token. *) proc _elna_lexer_reset(); -var - state: Word; begin (* Transition start state is 1. *) - state := _elna_lexer_global_state(); - state^ := ElnaLexerState.start; - - state := _elna_lexer_global_get_start(); - _elna_lexer_global_set_end(state) + lexer_state.state := ElnaLexerState.start; + lexer_state.finish := lexer_state.start end; (** @@ -5089,25 +4989,17 @@ begin _elna_lexer_classifications(); _elna_lexer_transitions(); - _elna_lexer_global_set_start(code_pointer); - _elna_lexer_global_set_end(code_pointer) + lexer_state.start := code_pointer; + lexer_state.finish := code_pointer end; proc _elna_lexer_next_transition(); var current_character: Word; - character_class: Word; - current_state: Word; begin - current_character := _elna_lexer_global_get_end(); - current_character := _load_byte(current_character); + current_character := _load_byte(lexer_state.finish); - character_class := _get_at(@classification, current_character + 1); - - current_state := _elna_lexer_global_state(); - current_state := current_state^; - - return _elna_lexer_get_transition(current_state, character_class) + return _elna_lexer_get_transition(lexer_state.state, classification[current_character + 1]) end; proc string_compare(lhs_pointer: Word, lhs_length: Word, rhs_pointer: Word, rhs_length: Word); @@ -5296,45 +5188,40 @@ end; proc _elna_lexer_execute_action(action_to_perform: Word, kind: Word); var - position_start: Word; - position_end: Word; intermediate: Word; begin - position_start := _elna_lexer_global_get_start(); - position_end := _elna_lexer_global_get_end(); - if action_to_perform = ElnaLexerAction.none then elsif action_to_perform = ElnaLexerAction.accumulate then - _elna_lexer_global_set_end(position_end + 1) + lexer_state.finish := lexer_state.finish + 1 elsif action_to_perform = ElnaLexerAction.skip then - _elna_lexer_global_set_start(position_start + 1); - _elna_lexer_global_set_end(position_end + 1) + lexer_state.start := lexer_state.start + 1; + lexer_state.finish := lexer_state.finish + 1 elsif action_to_perform = ElnaLexerAction.single then - _elna_lexer_global_set_end(position_end + 1); + lexer_state.finish := lexer_state.finish + 1; - intermediate := _elna_lexer_classify_single(position_start); + intermediate := _elna_lexer_classify_single(lexer_state.start); kind^ := intermediate elsif action_to_perform = ElnaLexerAction.eof then intermediate := ElnaLexerKind.eof; kind^ := intermediate elsif action_to_perform = ElnaLexerAction.finalize then - intermediate := _elna_lexer_classify_finalize(position_start); + intermediate := _elna_lexer_classify_finalize(lexer_state.start); kind^ := intermediate elsif action_to_perform = ElnaLexerAction.composite then - _elna_lexer_global_set_end(position_end + 1); + intermediate := _elna_lexer_classify_composite(lexer_state.start, lexer_state.finish); + kind^ := intermediate; - intermediate := _elna_lexer_classify_composite(position_start, position_end); - kind^ := intermediate + lexer_state.finish := lexer_state.finish + 1 elsif action_to_perform = ElnaLexerAction.key_id then - intermediate := _elna_lexer_classify_keyword(position_start, position_end); + intermediate := _elna_lexer_classify_keyword(lexer_state.start, lexer_state.finish); kind^ := intermediate elsif action_to_perform = ElnaLexerAction.integer then - intermediate := _elna_lexer_classify_integer(position_start, position_end); + intermediate := _elna_lexer_classify_integer(lexer_state.start, lexer_state.finish); kind^ := intermediate elsif action_to_perform = ElnaLexerAction.delimited then - _elna_lexer_global_set_end(position_end + 1); + lexer_state.finish := lexer_state.finish + 1; - intermediate := _elna_lexer_classify_delimited(position_start, position_end + 1); + intermediate := _elna_lexer_classify_delimited(lexer_state.start, lexer_state.finish); kind^ := intermediate end end; @@ -5350,7 +5237,7 @@ begin next_state := _elna_lexer_transition_get_state(next_transition); action_to_perform := _elna_lexer_transition_get_action(next_transition); - global_state := _elna_lexer_global_state(); + global_state := @lexer_state; global_state^ := next_state; _elna_lexer_execute_action(action_to_perform, kind); @@ -5381,11 +5268,8 @@ end; * Advances the token stream past the last read token. *) proc _elna_lexer_skip_token(); -var - old_end: Word; begin - old_end := _elna_lexer_global_get_end(); - _elna_lexer_global_set_start(old_end) + lexer_state.start := lexer_state.finish end; proc _initialize_global_state(); @@ -5423,10 +5307,3 @@ begin exit(4) end; end; - -proc f(); -var - a: Word; -begin - return a -end;