From b891573bbc7c0a42f6cf46f320ec54e089580631 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sun, 21 Jun 2026 23:15:51 +0200 Subject: [PATCH] Collect declarations before doing name analysis --- boot/stage23/cl.elna | 424 ++++++++++++++++++++++++++----------------- boot/stage24/cl.elna | 392 ++++++++++++++++++++++----------------- 2 files changed, 488 insertions(+), 328 deletions(-) diff --git a/boot/stage23/cl.elna b/boot/stage23/cl.elna index caebd84..2ea751b 100644 --- a/boot/stage23/cl.elna +++ b/boot/stage23/cl.elna @@ -3,11 +3,15 @@ * v. 2.0. If a copy of the MPL was not distributed with this file, You can * obtain one at https://mozilla.org/MPL/2.0/. *) + program; (* Stage 23 compiler. *) (* - Support extern procedure declarations. *) +(* - Do not require program keyword in the beginning of a module. *) +(* - Support records refencing themselves in their fields. *) +(* - Types can be referenced even if they are declared later. *) type ElnaListNode = record @@ -35,12 +39,18 @@ type end (* Type representation. *) - ElnaTypeKind = (primitive, enumeration, _record, pointer, array) + ElnaTypeKind = (primitive, enumeration, _record, pointer, array, alias) ElnaType = record kind: ElnaTypeKind; size: Word; alignment: Word end + ElnaTypeAlias = record + kind: ElnaTypeKind; + size: Word; + alignment: Word; + base: ^ElnaType + end ElnaTypeEnumeration = record kind: ElnaTypeKind; size: Word; @@ -333,7 +343,8 @@ type ElnaSymbolProcedureInfo = record kind: ElnaSymbolInfoKind; symbol_table: ^ElnaSymbolTable; - return_type: ^ElnaType + return_type: ^ElnaType; + is_extern: Bool end ElnaLexerAction = (none, accumulate, skip, single, eof, finalize, composite, key_id, integer, delimited) @@ -865,7 +876,7 @@ begin operand^.value := buffer; operand^.length := strlen(buffer); - temporary_info := temporary_info_create(1, variable_type); + temporary_info := elna_symbol_temporary_info_create(1, variable_type); elna_symbol_table_enter(symbol_table, buffer, operand^.length, temporary_info) end @@ -3897,15 +3908,13 @@ end * * Returns enumeration type description. *) -proc elna_name_enumeration_type_expression(parser_node: ^ElnaTreeEnumerationTypeExpression) -> ^ElnaTypeEnumeration +proc elna_name_enumeration_type_expression(parser_node: ^ElnaTreeEnumerationTypeExpression, + result: ^ElnaTypeEnumeration) var - result: ^ElnaTypeEnumeration memory_start: ^ElnaTreeEnumeration member_count: Word member_array_current: ^String begin - result := malloc(#size(ElnaTypeEnumeration)); - memory_start := parser_node^.members; member_count := parser_node^.length; @@ -3922,58 +3931,43 @@ begin member_count := member_count - 1; goto elna_name_type_enumeration_loop end; - - result^.kind := ElnaTypeKind.enumeration; result^.size := 4; result^.alignment := 4; - result^.length := parser_node^.length; - - return result + result^.length := parser_node^.length end -proc elna_name_pointer_type_expression(parser_node: ^ElnaTreePointerTypeExpression) -> ^ElnaTypePointer -var - result: ^ElnaTypePointer +proc elna_name_pointer_type_expression(parser_node: ^ElnaTreePointerTypeExpression, + result: ^ElnaTypePointer) begin - result := malloc(#size(ElnaTypePointer)); - - result^.kind := ElnaTypeKind.pointer; result^.size := 4; result^.alignment := 4; - result^.base := elna_name_type_expression(parser_node^.base); - - return result + result^.base := elna_name_type_expression(parser_node^.base) end -proc elna_name_array_type_expression(parser_node: ^ElnaTreeArrayTypeExpression) -> ^ElnaTypeArray +proc elna_name_array_type_expression(parser_node: ^ElnaTreeArrayTypeExpression, + result: ^ElnaTypeArray) var base: ^ElnaType - result: ^ElnaTypeArray length: ^ElnaTreeIntegerLiteral begin - result := malloc(#size(ElnaTypeArray)); base := elna_name_type_expression(parser_node^.base); length := parser_node^.length; - result^.kind := ElnaTypeKind.array; (* Array size in bytes. *) result^.size := base^.size * length^.value; result^.alignment := base^.alignment; result^.base := base; - result^.length := length^.value; - - return result + result^.length := length^.value end -proc elna_name_record_type_expression(parser_node: ^ElnaTreeRecordTypeExpression) -> ^ElnaTypeRecord +proc elna_name_record_type_expression(parser_node: ^ElnaTreeRecordTypeExpression, + result: ^ElnaTypeRecord) var result: ^ElnaTypeRecord tree_field: ^ElnaTreeField member_array_current: ^ElnaTypeField field_type: ^ElnaType begin - result := malloc(#size(ElnaTypeRecord)); - result^.kind := ElnaTypeKind._record; result^.size := 0; result^.alignment := 0; result^.length := 0; @@ -3998,9 +3992,7 @@ begin tree_field := tree_field^.next; result^.length := result^.length + 1; goto elna_name_type_record_loop - end; - - return result + end end proc elna_parser_named_type_expression(cursor: ^ElnaLexerCursor) -> ^ElnaTreeNamedTypeExpression @@ -4091,7 +4083,21 @@ begin return result end -proc elna_name_type_expression(parser_node: ^ElnaTreeNode) -> ^ElnaType +proc elna_name_alias_type_expression(parser_node: ^ElnaTreeNamedTypeExpression, result: ^ElnaTypeAlias) +var + type_symbol: ^ElnaSymbolTypeInfo + aliased_type: ^ElnaType +begin + type_symbol := elna_symbol_table_lookup(symbol_table_global, + parser_node^.name.ptr, parser_node^.name.length); + aliased_type := type_symbol^._type; + + result^.size := aliased_type^.size; + result^.alignment := aliased_type^.alignment; + result^.base := aliased_type +end + +proc elna_name_type_expression(parser_node: ^ElnaTreeTypeExpression) -> ^ElnaType var named_type_expression: ^ElnaTreeNamedTypeExpression type_symbol: ^ElnaSymbolTypeInfo @@ -4104,19 +4110,31 @@ begin 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) + result := malloc(#size(ElnaTypeEnumeration)); + result^.kind := ElnaTypeKind.enumeration; + + elna_name_enumeration_type_expression(parser_node, result) elsif parser_node^.kind = ElnaTreeKind.record_type_expression then - result := elna_name_record_type_expression(parser_node) + result := malloc(#size(ElnaTypeRecord)); + result^.kind := ElnaTypeKind._record; + + elna_name_record_type_expression(parser_node, result) elsif parser_node^.kind = ElnaTreeKind.pointer_type_expression then - result := elna_name_pointer_type_expression(parser_node) + result := malloc(#size(ElnaTypePointer)); + result^.kind := ElnaTypeKind.pointer; + + elna_name_pointer_type_expression(parser_node, result) elsif parser_node^.kind = ElnaTreeKind.array_type_expression then - result := elna_name_array_type_expression(parser_node) + result := malloc(#size(ElnaTypeArray)); + result^.kind := ElnaTypeKind.array; + + elna_name_array_type_expression(parser_node, result) end; return result end -proc type_info_create(type_representation: ^ElnaType) -> ^ElnaSymbolTypeInfo +proc elna_symbol_type_info_create(type_representation: ^ElnaType) -> ^ElnaSymbolTypeInfo var result: ^ElnaSymbolTypeInfo begin @@ -4132,7 +4150,7 @@ end * attr - Local variable attributes. * temporary_type - Local variable type. *) -proc temporary_info_create(attr: Word, temporary_type: ^ElnaType) -> ^ElnaSymbolTemporaryInfo +proc elna_symbol_temporary_info_create(attr: Word, temporary_type: ^ElnaType) -> ^ElnaSymbolTemporaryInfo var result: ^ElnaSymbolTemporaryInfo begin @@ -4150,14 +4168,14 @@ end * Parameters: * symbol_table - Local symbol table. *) -proc procedure_info_create(symbol_table: ^ElnaSymbolTable, return_type: ^ElnaRtlType) -> ^ElnaSymbolProcedureInfo +proc elna_symbol_procedure_info_create(return_type: ^ElnaRtlType, is_extern: Bool) -> ^ElnaSymbolProcedureInfo var result: ^ElnaSymbolProcedureInfo begin result := malloc(#size(ElnaSymbolProcedureInfo)); result^.kind := ElnaSymbolInfoKind.procedure_info; - result^.symbol_table := symbol_table; result^.return_type := return_type; + result^.is_extern := is_extern; return result end @@ -4168,12 +4186,12 @@ end *) proc elna_name_procedure_temporary(parser_node: ^ElnaTreeVariableDeclaration, symbol_table: ^ElnaSymbolTable) var - info: Word - variable_type: Word + info: ^ElnaSymbolTemporaryInfo + variable_type: ^ElnaType begin variable_type := elna_name_type_expression(parser_node^.type_expression); - info := temporary_info_create(0, variable_type); + info := elna_symbol_temporary_info_create(0, variable_type); elna_symbol_table_enter(symbol_table, parser_node^.name.ptr, parser_node^.name.length, info) end @@ -4725,17 +4743,25 @@ end proc elna_name_type_declaration(parser_node: ^ElnaTreeTypeDeclaration) var - symbol_type: ^ElnaType type_info: ^ElnaSymbolTypeInfo + type_stub: ^ElnaType + type_expression: ^ElnaTreeTypeExpression begin - symbol_type := elna_name_type_expression(parser_node^.type_expression); - type_info := type_info_create(symbol_type); + type_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length); + type_stub := type_info^._type; + type_expression := parser_node^.type_expression; - 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) -begin + if type_stub^.kind = ElnaTypeKind.alias then + elna_name_alias_type_expression(type_expression, type_stub) + elsif type_stub^.kind = ElnaTypeKind.enumeration then + elna_name_enumeration_type_expression(type_expression, type_stub) + elsif type_stub^.kind = ElnaTypeKind._record then + elna_name_record_type_expression(type_expression, type_stub) + elsif type_stub^.kind = ElnaTypeKind.pointer then + elna_name_pointer_type_expression(type_expression, type_stub) + elsif type_stub^.kind = ElnaTypeKind.array then + elna_name_array_type_expression(type_expression, type_stub) + end end proc elna_parser_type_part(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeDeclaration @@ -4935,37 +4961,40 @@ end proc elna_parser_module_declaration(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeModuleDeclaration var + token: ^ElnaLexerToken result: ^ElnaTreeModuleDeclaration begin - result := nil; - if elna_parser_expect(cursor, ElnaLexerKind._program, error_list) <> nil then - if elna_parser_expect(cursor, ElnaLexerKind.semicolon, error_list) <> nil then - result := malloc(#size(ElnaTreeModuleDeclaration)); - result^.kind := ElnaTreeKind.module_declaration; + elna_lexer_skip_empty_lines(cursor); + token := elna_lexer_peek(cursor); + if token^.kind = ElnaLexerKind._program then + elna_lexer_read(cursor); + elna_lexer_read(cursor) + end; - result^.types := elna_parser_type_part(cursor, error_list); - if elna_list_empty(error_list) = false then - result := free_and_nil(result) - end; - if result <> nil then - result^.globals := elna_parser_var_part(cursor, error_list); - end; - if elna_list_empty(error_list) = false then - result := free_and_nil(result) - end; - if result <> nil then - result^.procedures := elna_parser_procedures(cursor, error_list); - end; - if elna_list_empty(error_list) = false then - result := free_and_nil(result) - end; - if result <> nil then - result^.body := elna_parser_program_body(cursor, error_list) - end; - if elna_list_empty(error_list) = false then - result := free_and_nil(result) - end - end + result := malloc(#size(ElnaTreeModuleDeclaration)); + result^.kind := ElnaTreeKind.module_declaration; + + result^.types := elna_parser_type_part(cursor, error_list); + if elna_list_empty(error_list) = false then + result := free_and_nil(result) + end; + if result <> nil then + result^.globals := elna_parser_var_part(cursor, error_list); + end; + if elna_list_empty(error_list) = false then + result := free_and_nil(result) + end; + if result <> nil then + result^.procedures := elna_parser_procedures(cursor, error_list); + end; + if elna_list_empty(error_list) = false then + result := free_and_nil(result) + end; + if result <> nil then + result^.body := elna_parser_program_body(cursor, error_list) + end; + if elna_list_empty(error_list) = false then + result := free_and_nil(result) end; return result end @@ -5022,90 +5051,104 @@ begin return result end -proc elna_name_dereference_expression(parser_node: ^ElnaTreeDereferenceExpression) +proc elna_name_dereference_expression(parser_node: ^ElnaTreeDereferenceExpression, symbol_table: ^ElnaSymbolTable) begin - elna_name_designator(parser_node^.pointer) + elna_name_designator(parser_node^.pointer, symbol_table) end -proc elna_name_field_access_expression(parser_node: ^ElnaTreeFieldAccessExpression) +proc elna_name_field_access_expression(parser_node: ^ElnaTreeFieldAccessExpression, symbol_table: ^ElnaSymbolTable) begin - elna_name_designator(parser_node^.aggregate) + elna_name_designator(parser_node^.aggregate, symbol_table) end -proc elna_name_array_access_expression(parser_node: ^ElnaTreeArrayAccessExpression) +proc elna_name_array_access_expression(parser_node: ^ElnaTreeArrayAccessExpression, symbol_table: ^ElnaSymbolTable) begin - elna_name_designator(parser_node^.array); - elna_name_binary_expression(parser_node^.index) + elna_name_designator(parser_node^.array, symbol_table); + elna_name_binary_expression(parser_node^.index, symbol_table) end -proc elna_name_cast_expression(parser_node: ^ElnaTreeCastExpression) +proc elna_name_cast_expression(parser_node: ^ElnaTreeCastExpression, symbol_table: ^ElnaSymbolTable) begin elna_name_binary_expression(parser_node^.expression); parser_node^.type_decoration := elna_name_type_expression(parser_node^.type_expression) end -proc elna_name_simple_expression(parser_node: ^ElnaTreeNode) +proc elna_name_variable_expression(parser_node: ^ElnaTreeVariableExpression, symbol_table: ^ElnaSymbolTable) begin - (* Not interested in literals and variable expressions. *) +end + +proc elna_name_simple_expression(parser_node: ^ElnaTreeNode, symbol_table: ^ElnaSymbolTable) +begin + (* Not interested in literals. *) if parser_node^.kind = ElnaTreeKind._cast then - elna_name_cast_expression(parser_node) + elna_name_cast_expression(parser_node, symbol_table) + elsif parser_node^.kind = ElnaTreeKind.variable_expression then + elna_name_variable_expression(parser_node, symbol_table) end end -proc elna_name_call(parser_node: ^ElnaTreeCall) +proc elna_name_call(parser_node: ^ElnaTreeCall, symbol_table: ^ElnaSymbolTable) var argument_tree: ^ElnaTreeExpressionList + callee_symbol: ^ElnaSymbolProcedureInfo begin + callee_symbol := elna_symbol_table_lookup(symbol_table_global, parser_node^.callee^.name.ptr, parser_node^.callee^.name.length); + if callee_symbol = nil then + (* DEBUG *) + _write_s(stdout, "# Undefined symbol "); + _write_s(stdout, parser_node^.callee^.name); + _write_s(stdout, ".\n") + end; argument_tree := parser_node^.arguments; .elna_name_call_argument; if argument_tree <> nil then - elna_name_binary_expression(argument_tree^.expression); + elna_name_binary_expression(argument_tree^.expression, symbol_table); argument_tree := argument_tree^.next; goto elna_name_call_argument end end -proc elna_name_designator(parser_node: ^ElnaTreeNode) +proc elna_name_designator(parser_node: ^ElnaTreeNode, symbol_table: ^ElnaSymbolTable) begin if parser_node^.kind = ElnaTreeKind.dereference_expression then - elna_name_dereference_expression(parser_node) + elna_name_dereference_expression(parser_node, symbol_table) elsif parser_node^.kind = ElnaTreeKind.field_access_expression then - elna_name_field_access_expression(parser_node) + elna_name_field_access_expression(parser_node, symbol_table) elsif parser_node^.kind = ElnaTreeKind.array_access_expression then - elna_name_array_access_expression(parser_node) + elna_name_array_access_expression(parser_node, symbol_table) elsif parser_node^.kind = ElnaTreeKind.call then - elna_name_call(parser_node) + elna_name_call(parser_node, symbol_table) else - elna_name_simple_expression(parser_node) + elna_name_simple_expression(parser_node, symbol_table) end end -proc elna_name_unary_expression(parser_node: ^ElnaTreeUnaryExpression) +proc elna_name_unary_expression(parser_node: ^ElnaTreeUnaryExpression, symbol_table: ^ElnaSymbolTable) begin if parser_node^.kind = ElnaTreeKind.unary_expression then - elna_name_designator(parser_node^.operand) + elna_name_designator(parser_node^.operand, symbol_table) else - elna_name_designator(parser_node) + elna_name_designator(parser_node, symbol_table) end end -proc elna_name_binary_expression(parser_node: ^ElnaTreeBinaryExpression) +proc elna_name_binary_expression(parser_node: ^ElnaTreeBinaryExpression, symbol_table: ^ElnaSymbolTable) begin if parser_node^.kind = ElnaTreeKind.binary_expression then - elna_name_unary_expression(parser_node^.lhs); - elna_name_unary_expression(parser_node^.rhs) + elna_name_unary_expression(parser_node^.lhs, symbol_table); + elna_name_unary_expression(parser_node^.rhs, symbol_table) else - elna_name_unary_expression(parser_node) + elna_name_unary_expression(parser_node, symbol_table) end end -proc elna_name_conditional_statements(parser_node: ^ElnaTreeConditionalStatements) +proc elna_name_conditional_statements(parser_node: ^ElnaTreeConditionalStatements, symbol_table: ^ElnaSymbolTable) begin .elna_name_conditional_statements_loop; - elna_name_binary_expression(parser_node^.condition); - elna_name_statements(parser_node^.statements); + elna_name_binary_expression(parser_node^.condition, symbol_table); + elna_name_statements(parser_node^.statements, symbol_table); parser_node := parser_node^.next; if parser_node <> nil then @@ -5113,14 +5156,14 @@ begin end end -proc elna_name_if_statement(parser_node: ^ElnaTreeIfStatement) +proc elna_name_if_statement(parser_node: ^ElnaTreeIfStatement, symbol_table: ^ElnaSymbolTable) var block: ^ElnaTreeConditionalStatements begin block := parser_node^.conditionals; .elna_name_if_statement_conditionals; - elna_name_conditional_statements(block); + elna_name_conditional_statements(block, symbol_table); block := block^.next; if block <> nil then @@ -5128,40 +5171,40 @@ begin end; block := parser_node^._else; if block <> nil then - elna_name_statements(block) + elna_name_statements(block, symbol_table) end end -proc elna_name_return_statement(parser_node: ^ElnaTreeReturnStatement) +proc elna_name_return_statement(parser_node: ^ElnaTreeReturnStatement, symbol_table: ^ElnaSymbolTable) begin - elna_name_binary_expression(parser_node^.returned) + elna_name_binary_expression(parser_node^.returned, symbol_table) end -proc elna_name_assign_statement(parser_node: ^ElnaTreeAssignStatement) +proc elna_name_assign_statement(parser_node: ^ElnaTreeAssignStatement, symbol_table: ^ElnaSymbolTable) begin - elna_name_designator(parser_node^.assignee); - elna_name_binary_expression(parser_node^.assignment) + elna_name_designator(parser_node^.assignee, symbol_table); + elna_name_binary_expression(parser_node^.assignment, symbol_table) end -proc elna_name_statement(parser_node: ^ElnaTreeStatement) +proc elna_name_statement(parser_node: ^ElnaTreeStatement, symbol_table: ^ElnaSymbolTable) begin (* Skipping goto and label declarations. *) if parser_node^.kind = ElnaTreeKind.if_statement then - elna_name_if_statement(parser_node) + elna_name_if_statement(parser_node, symbol_table) elsif parser_node^.kind = ElnaTreeKind.return_statement then - elna_name_return_statement(parser_node) + elna_name_return_statement(parser_node, symbol_table) elsif parser_node^.kind = ElnaTreeKind.call then - elna_name_call(parser_node) + elna_name_call(parser_node, symbol_table) elsif parser_node^.kind = ElnaTreeKind.assign_statement then - elna_name_assign_statement(parser_node) + elna_name_assign_statement(parser_node, symbol_table) end end -proc elna_name_statements(parser_node: ^ElnaTreeStatement) +proc elna_name_statements(parser_node: ^ElnaTreeStatement, symbol_table: ^ElnaSymbolTable) begin .elna_name_statements_loop; if parser_node <> nil then - elna_name_statement(parser_node); + elna_name_statement(parser_node, symbol_table); parser_node := parser_node^.next; goto elna_name_statements_loop @@ -5174,28 +5217,23 @@ var symbol_info: ^ElnaSymbolProcedureInfo return_type: ^ElnaType begin - if parser_node^.return_type = nil then - return_type := nil - else - return_type := elna_name_type_expression(parser_node^.return_type); - end; - new_symbol_table := elna_symbol_table_create(symbol_table_global); - symbol_info := procedure_info_create(new_symbol_table, return_type); + symbol_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length); + if symbol_info^.is_extern = false then + new_symbol_table := elna_symbol_table_create(symbol_table_global); + symbol_info^.symbol_table := new_symbol_table; - elna_name_procedure_temporaries(parser_node^.parameters, new_symbol_table); - 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.ptr, parser_node^.name.length, symbol_info) + elna_name_procedure_temporaries(parser_node^.parameters, new_symbol_table); + elna_name_procedure_temporaries(parser_node^.temporaries, new_symbol_table); + elna_name_statements(parser_node^.body, new_symbol_table) + end end proc elna_name_program_body(parser_node: ^ElnaTreeStatement) var - new_symbol_table: ^ElnaSymbolTable - symbol_info: Word + symbol_info: ^ElnaSymbolProcedureInfo begin - new_symbol_table := elna_symbol_table_create(symbol_table_global); - symbol_info := procedure_info_create(new_symbol_table); + symbol_info := elna_symbol_procedure_info_create(nil, false); + symbol_info^.symbol_table := elna_symbol_table_create(symbol_table_global); elna_symbol_table_enter(symbol_table_global, "main".ptr, 4, symbol_info) end @@ -5514,15 +5552,6 @@ proc elna_type_module_declaration(parser_node: ^ElnaTreeModuleDeclaration) var current_part: ^ElnaTreeDeclaration begin - current_part := parser_node^.types; - .elna_type_module_declaration_type; - if current_part <> nil then - elna_type_type_declaration(current_part); - current_part := current_part^.next; - - goto elna_type_module_declaration_type - end; - current_part := parser_node^.procedures; .elna_type_module_declaration_procedure; if current_part <> nil then @@ -5533,6 +5562,74 @@ begin end end +proc elna_declaration_type_declaration(parser_node: ^ElnaTreeTypeDeclaration) +var + type_info: ^ElnaSymbolTypeInfo + result: ^ElnaType + type_expression: ^ElnaTreeTypeExpression +begin + type_expression := parser_node^.type_expression; + + if type_expression^.kind = ElnaTreeKind.named_type_expression then + result := malloc(#size(ElnaTypeAlias)); + result^.kind := ElnaTypeKind.alias + elsif type_expression^.kind = ElnaTreeKind.enumeration_type_expression then + result := malloc(#size(ElnaTypeEnumeration)); + result^.kind := ElnaTypeKind.enumeration + elsif type_expression^.kind = ElnaTreeKind.record_type_expression then + result := malloc(#size(ElnaTypeRecord)); + result^.kind := ElnaTypeKind._record + elsif type_expression^.kind = ElnaTreeKind.pointer_type_expression then + result := malloc(#size(ElnaTypePointer)); + result^.kind := ElnaTypeKind.pointer + elsif type_expression^.kind = ElnaTreeKind.array_type_expression then + result := malloc(#size(ElnaTypeArray)); + result^.kind := ElnaTypeKind.array + end; + type_info := elna_symbol_type_info_create(result); + + elna_symbol_table_enter(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length, type_info) +end + +proc elna_declaration_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration) +var + symbol_info: ^ElnaSymbolProcedureInfo + return_type: ^ElnaType +begin + if parser_node^.return_type = nil then + return_type := nil + else + return_type := elna_name_type_expression(parser_node^.return_type); + end; + symbol_info := elna_symbol_procedure_info_create(return_type, parser_node^.is_extern); + symbol_info^.symbol_table := elna_symbol_table_create(symbol_table_global); + + elna_symbol_table_enter(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length, symbol_info) +end + +proc elna_declaration_module_declaration(parser_node: ^ElnaTreeModuleDeclaration) +var + current_part: ^ElnaTreeDeclaration +begin + current_part := parser_node^.types; + .elna_declaration_module_declaration_type; + if current_part <> nil then + elna_declaration_type_declaration(current_part); + current_part := current_part^.next; + + goto elna_declaration_module_declaration_type + end; + + current_part := parser_node^.procedures; + .elna_declaration_module_declaration_procedure; + if current_part <> nil then + elna_declaration_procedure_declaration(current_part); + current_part := current_part^.next; + + goto elna_declaration_module_declaration_procedure + end +end + proc elna_error_print_token1(kind: ElnaLexerKind) begin if kind = ElnaLexerKind.identifier then @@ -5575,8 +5672,6 @@ begin _write_s(stderr, "\"~\"") elsif kind = ElnaLexerKind._return then _write_s(stderr, "\"return\"") - elsif kind = ElnaLexerKind._program then - _write_s(stderr, "\"program\"") elsif kind = ElnaLexerKind._cast then _write_s(stderr, "\"cast\"") elsif kind = ElnaLexerKind.trait then @@ -5635,6 +5730,8 @@ begin _write_s(stderr, "CHARACTER") elsif kind = ElnaLexerKind.integer then _write_s(stderr, "INTEGER") + elsif kind = ElnaLexerKind.word then + _write_s(stderr, "WORD") else elna_error_print_token2(kind) end @@ -5642,9 +5739,7 @@ end proc elna_error_print_token2(kind: ElnaLexerKind) begin - if kind = ElnaLexerKind.word then - _write_s(stderr, "WORD") - elsif kind = ElnaLexerKind._goto then + if kind = ElnaLexerKind._goto then _write_s(stderr, "\"goto\"") elsif kind = ElnaLexerKind.eof then _write_s(stderr, "EOF") @@ -5688,6 +5783,7 @@ begin compiled := elna_list_empty(@error_list); if compiled then + elna_declaration_module_declaration(parser_node); elna_name_module_declaration(parser_node); elna_type_module_declaration(parser_node); tac := elna_tac_module_declaration(parser_node); @@ -5713,9 +5809,9 @@ end * * Returns the symbol pointer or nil. *) -proc elna_symbol_table_lookup(symbol_table: ^ElnaSymbolTable, symbol_name: Word, name_length: Word) +proc elna_symbol_table_lookup(symbol_table: ^ElnaSymbolTable, symbol_name: ^Char, name_length: Word) -> Pointer var - result: Word + result: Pointer symbol_table_length: Word current_entry: ^ElnaSymbolEntry begin @@ -5832,39 +5928,39 @@ begin word_type^.kind := ElnaTypeKind.primitive; word_type^.size := 4; word_type^.alignment := 4; - current_info := type_info_create(word_type); + current_info := elna_symbol_type_info_create(word_type); elna_symbol_table_enter(symbol_table_global, "Word".ptr, 4, current_info); int_type := malloc(#size(ElnaType)); int_type^.kind := ElnaTypeKind.primitive; int_type^.size := 4; int_type^.alignment := 4; - current_info := type_info_create(int_type); + current_info := elna_symbol_type_info_create(int_type); elna_symbol_table_enter(symbol_table_global, "Int".ptr, 3, current_info); current_type := malloc(#size(ElnaType)); current_type^.kind := ElnaTypeKind.primitive; current_type^.size := 4; current_type^.alignment := 4; - current_info := type_info_create(current_type); + current_info := elna_symbol_type_info_create(current_type); elna_symbol_table_enter(symbol_table_global, "Pointer".ptr, 7, current_info); bool_type := malloc(#size(ElnaType)); bool_type^.kind := ElnaTypeKind.primitive; bool_type^.size := 1; bool_type^.alignment := 1; - current_info := type_info_create(bool_type); + current_info := elna_symbol_type_info_create(bool_type); elna_symbol_table_enter(symbol_table_global, "Bool".ptr, 4, current_info); char_type := malloc(#size(ElnaType)); char_type^.kind := ElnaTypeKind.primitive; char_type^.size := 1; char_type^.alignment := 1; - current_info := type_info_create(char_type); + current_info := elna_symbol_type_info_create(char_type); elna_symbol_table_enter(symbol_table_global, "Char".ptr, 4, current_info); elna_symbol_string_build(); - current_info := type_info_create(string_type); + current_info := elna_symbol_type_info_create(string_type); elna_symbol_table_enter(symbol_table_global, "String".ptr, 6, current_info) end diff --git a/boot/stage24/cl.elna b/boot/stage24/cl.elna index af4fb9e..c828366 100644 --- a/boot/stage24/cl.elna +++ b/boot/stage24/cl.elna @@ -3,15 +3,14 @@ * v. 2.0. If a copy of the MPL was not distributed with this file, You can * obtain one at https://mozilla.org/MPL/2.0/. *) -program; -(* Stage 23 compiler. *) +(* Stage 24 compiler. *) -(* - Support extern procedure declarations. *) +(* - Support records refencing themselves in their fields. *) type ElnaListNode = record - next: Word + next: ^ElnaListNode end ElnaList = record first: ^ElnaListNode; @@ -35,12 +34,18 @@ type end (* Type representation. *) - ElnaTypeKind = (primitive, enumeration, _record, pointer, array) + ElnaTypeKind = (primitive, enumeration, _record, pointer, array, alias) ElnaType = record kind: ElnaTypeKind; size: Word; alignment: Word end + ElnaTypeAlias = record + kind: ElnaTypeKind; + size: Word; + alignment: Word; + base: ^ElnaType + end ElnaTypeEnumeration = record kind: ElnaTypeKind; size: Word; @@ -174,33 +179,42 @@ type *) ElnaTreeStatement = record kind: ElnaTreeKind; - next: Word + next: ^ElnaTreeStatement + end + (** + * Conditional statements is a list of pairs: condition and statements. + * Used for example to represent if and elsif blocks with beloning statements. + *) + ElnaTreeConditionalStatements = record + condition: ^ElnaTreeExpression; + statements: ^ElnaTreeStatement; + next: ^ElnaTreeConditionalStatements end ElnaTreeIfStatement = record kind: ElnaTreeKind; - next: Word; - conditionals: Word; + next: ^ElnaTreeStatement; + conditionals: ^ElnaTreeConditionalStatements; _else: ^ElnaTreeStatement end ElnaTreeGotoStatement = record kind: ElnaTreeKind; - next: Word; + next: ^ElnaTreeStatement; label: String end ElnaTreeAssignStatement = record kind: ElnaTreeKind; - next: Word; + next: ^ElnaTreeStatement; assignee: Word; assignment: ^ElnaTreeExpression end ElnaTreeReturnStatement = record kind: ElnaTreeKind; - next: Word; + next: ^ElnaTreeStatement; returned: ^ElnaTreeExpression end ElnaTreeLabelDeclaration = record kind: ElnaTreeKind; - next: Word; + next: ^ElnaTreeStatement; label: String end ElnaTreeFieldAccessExpression = record @@ -217,17 +231,17 @@ type end ElnaTreeEnumeration = record name: String; - next: Word + next: ^ElnaTreeEnumeration end ElnaTreeEnumerationTypeExpression = record kind: ElnaTreeKind; - members: Word; + members: ^ElnaTreeEnumeration; length: Word end ElnaTreeField = record name: String; type_expression: ^ElnaTreeTypeExpression; - next: Word + next: ^ElnaTreeField end ElnaTreeRecordTypeExpression = record kind: ElnaTreeKind; @@ -250,31 +264,22 @@ type ElnaTreeTraitExpression = record kind: ElnaTreeKind; name: String; - argument: Word - end - (** - * Conditional statements is a list of pairs: condition and statements. - * Used for example to represent if and elsif blocks with beloning statements. - *) - ElnaTreeConditionalStatements = record - condition: ^ElnaTreeExpression; - statements: ^ElnaTreeStatement; - next: Word + argument: ^ElnaTreeTypeExpression end ElnaTreeDeclaration = record kind: ElnaTreeKind; - next: Word; + next: ^ElnaTreeDeclaration; name: String end ElnaTreeVariableDeclaration = record kind: ElnaTreeKind; - next: Word; + next: ^ElnaTreeDeclaration; name: String; type_expression: ^ElnaTreeTypeExpression end ElnaTreeProcedureDeclaration = record kind: ElnaTreeKind; - next: Word; + next: ^ElnaTreeDeclaration; name: String; body: ^ElnaTreeStatement; temporaries: ^ElnaTreeVariableDeclaration; @@ -284,24 +289,24 @@ type end ElnaTreeModuleDeclaration = record kind: ElnaTreeKind; - types: Word; - globals: Word; + types: ^ElnaTreeDeclaration; + globals: ^ElnaTreeVariableDeclaration; procedures: ^ElnaTreeProcedureDeclaration; body: ^ElnaTreeStatement end ElnaTreeTypeDeclaration = record kind: ElnaTreeKind; - next: Word; + next: ^ElnaTreeDeclaration; name: String; type_expression: ^ElnaTreeTypeExpression end ElnaTreeExpressionList = record expression: ^ElnaTreeBinaryExpression; - next: Word + next: ^ElnaTreeExpressionList end ElnaTreeCall = record kind: ElnaTreeKind; - next: Word; + next: ^ElnaTreeStatement; callee: ^ElnaTreeVariableExpression; arguments: ^ElnaTreeExpressionList; count: Word @@ -310,11 +315,11 @@ type (* Symbol table information. *) ElnaSymbolEntry = record name: String; - symbol_info: Word + symbol_info: ^ElnaSymbolInfo end ElnaSymbolTable = record count: Word; - parent: Word; + parent: ^ElnaSymbolTable; symbols: ^ElnaSymbolEntry end ElnaSymbolInfoKind = (type_info, temporary_info, procedure_info) @@ -414,7 +419,6 @@ type _xor, not, _return, - _program, _cast, trait, left_paren, @@ -506,20 +510,20 @@ type length: Word end ElnaTacInstruction = record - next: Word; + next: ^ElnaListNode; operator: ElnaTacOperator; operands: [4]ElnaTacOperand end ElnaTacProcedure = record - next: Word; + next: ^ElnaTacProcedure; name: String; body: ElnaList; - parameters: Word; + parameters: ^String; count: Word; symbol_table: ^ElnaSymbolTable end ElnaTacStaticVariable = record - next: Word; + next: ^ElnaTacStaticVariable; name: String; body: Word end @@ -567,12 +571,12 @@ type offset: Word end ElnaRtlStaticVariable = record - next: Word; + next: ^ElnaRtlStaticVariable; name: String; body: Word end ElnaRtlProcedure = record - next: Word; + next: ^ElnaRtlProcedure; name: String; body: ElnaList; variable_map: ^ElnaSymbolTable @@ -590,7 +594,7 @@ type alignment: Word end ElnaRtlInstruction = record - next: Word; + next: ^ElnaListNode; operator: ElnaRtlOperator; operands: [3]ElnaRtlOperand; types: [2]^ElnaRtlType @@ -646,12 +650,12 @@ type ElnaErrorKind = (unexpected_token) ElnaError = record - next: Word; + next: ^ElnaListNode; kind: ElnaErrorKind; position: ElnaPosition end ElnaErrorUnexpectedToken = record - next: Word; + next: ^ElnaListNode; kind: ElnaErrorKind; position: ElnaPosition; expected: ^ElnaLexerKind; @@ -905,7 +909,7 @@ begin operand^.value := buffer; operand^.length := strlen(buffer); - temporary_info := temporary_info_create(1, variable_type); + temporary_info := elna_symbol_temporary_info_create(1, variable_type); elna_symbol_table_enter(symbol_table, buffer, operand^.length, temporary_info) end @@ -3937,15 +3941,13 @@ end * * Returns enumeration type description. *) -proc elna_name_enumeration_type_expression(parser_node: ^ElnaTreeEnumerationTypeExpression) -> ^ElnaTypeEnumeration +proc elna_name_enumeration_type_expression(parser_node: ^ElnaTreeEnumerationTypeExpression, + result: ^ElnaTypeEnumeration) var - result: ^ElnaTypeEnumeration memory_start: ^ElnaTreeEnumeration member_count: Word member_array_current: ^String begin - result := malloc(#size(ElnaTypeEnumeration)); - memory_start := parser_node^.members; member_count := parser_node^.length; @@ -3962,58 +3964,43 @@ begin member_count := member_count - 1; goto elna_name_type_enumeration_loop end; - - result^.kind := ElnaTypeKind.enumeration; result^.size := 4; result^.alignment := 4; - result^.length := parser_node^.length; - - return result + result^.length := parser_node^.length end -proc elna_name_pointer_type_expression(parser_node: ^ElnaTreePointerTypeExpression) -> ^ElnaTypePointer -var - result: ^ElnaTypePointer +proc elna_name_pointer_type_expression(parser_node: ^ElnaTreePointerTypeExpression, + result: ^ElnaTypePointer) begin - result := malloc(#size(ElnaTypePointer)); - - result^.kind := ElnaTypeKind.pointer; result^.size := 4; result^.alignment := 4; - result^.base := elna_name_type_expression(parser_node^.base); - - return result + result^.base := elna_name_type_expression(parser_node^.base) end -proc elna_name_array_type_expression(parser_node: ^ElnaTreeArrayTypeExpression) -> ^ElnaTypeArray +proc elna_name_array_type_expression(parser_node: ^ElnaTreeArrayTypeExpression, + result: ^ElnaTypeArray) var base: ^ElnaType - result: ^ElnaTypeArray length: ^ElnaTreeIntegerLiteral begin - result := malloc(#size(ElnaTypeArray)); base := elna_name_type_expression(parser_node^.base); length := parser_node^.length; - result^.kind := ElnaTypeKind.array; (* Array size in bytes. *) result^.size := base^.size * length^.value; result^.alignment := base^.alignment; result^.base := base; - result^.length := length^.value; - - return result + result^.length := length^.value end -proc elna_name_record_type_expression(parser_node: ^ElnaTreeRecordTypeExpression) -> ^ElnaTypeRecord +proc elna_name_record_type_expression(parser_node: ^ElnaTreeRecordTypeExpression, + result: ^ElnaTypeRecord) var result: ^ElnaTypeRecord tree_field: ^ElnaTreeField member_array_current: ^ElnaTypeField field_type: ^ElnaType begin - result := malloc(#size(ElnaTypeRecord)); - result^.kind := ElnaTypeKind._record; result^.size := 0; result^.alignment := 0; result^.length := 0; @@ -4038,9 +4025,7 @@ begin tree_field := tree_field^.next; result^.length := result^.length + 1; goto elna_name_type_record_loop - end; - - return result + end end proc elna_parser_named_type_expression(cursor: ^ElnaLexerCursor) -> ^ElnaTreeNamedTypeExpression @@ -4131,7 +4116,21 @@ begin return result end -proc elna_name_type_expression(parser_node: ^ElnaTreeNode) -> ^ElnaType +proc elna_name_alias_type_expression(parser_node: ^ElnaTreeNamedTypeExpression, result: ^ElnaTypeAlias) +var + type_symbol: ^ElnaSymbolTypeInfo + aliased_type: ^ElnaType +begin + type_symbol := elna_symbol_table_lookup(symbol_table_global, + parser_node^.name.ptr, parser_node^.name.length); + aliased_type := type_symbol^._type; + + result^.size := aliased_type^.size; + result^.alignment := aliased_type^.alignment; + result^.base := aliased_type +end + +proc elna_name_type_expression(parser_node: ^ElnaTreeTypeExpression) -> ^ElnaType var named_type_expression: ^ElnaTreeNamedTypeExpression type_symbol: ^ElnaSymbolTypeInfo @@ -4144,19 +4143,31 @@ begin 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) + result := malloc(#size(ElnaTypeEnumeration)); + result^.kind := ElnaTypeKind.enumeration; + + elna_name_enumeration_type_expression(parser_node, result) elsif parser_node^.kind = ElnaTreeKind.record_type_expression then - result := elna_name_record_type_expression(parser_node) + result := malloc(#size(ElnaTypeRecord)); + result^.kind := ElnaTypeKind._record; + + elna_name_record_type_expression(parser_node, result) elsif parser_node^.kind = ElnaTreeKind.pointer_type_expression then - result := elna_name_pointer_type_expression(parser_node) + result := malloc(#size(ElnaTypePointer)); + result^.kind := ElnaTypeKind.pointer; + + elna_name_pointer_type_expression(parser_node, result) elsif parser_node^.kind = ElnaTreeKind.array_type_expression then - result := elna_name_array_type_expression(parser_node) + result := malloc(#size(ElnaTypeArray)); + result^.kind := ElnaTypeKind.array; + + elna_name_array_type_expression(parser_node, result) end; return result end -proc type_info_create(type_representation: ^ElnaType) -> ^ElnaSymbolTypeInfo +proc elna_symbol_type_info_create(type_representation: ^ElnaType) -> ^ElnaSymbolTypeInfo var result: ^ElnaSymbolTypeInfo begin @@ -4172,7 +4183,7 @@ end * attr - Local variable attributes. * temporary_type - Local variable type. *) -proc temporary_info_create(attr: Word, temporary_type: ^ElnaType) -> ^ElnaSymbolTemporaryInfo +proc elna_symbol_temporary_info_create(attr: Word, temporary_type: ^ElnaType) -> ^ElnaSymbolTemporaryInfo var result: ^ElnaSymbolTemporaryInfo begin @@ -4190,14 +4201,12 @@ end * Parameters: * symbol_table - Local symbol table. *) -proc procedure_info_create(symbol_table: ^ElnaSymbolTable, return_type: ^ElnaRtlType, - is_extern: Bool) -> ^ElnaSymbolProcedureInfo +proc elna_symbol_procedure_info_create(return_type: ^ElnaRtlType, is_extern: Bool) -> ^ElnaSymbolProcedureInfo var result: ^ElnaSymbolProcedureInfo begin result := malloc(#size(ElnaSymbolProcedureInfo)); result^.kind := ElnaSymbolInfoKind.procedure_info; - result^.symbol_table := symbol_table; result^.return_type := return_type; result^.is_extern := is_extern; @@ -4210,12 +4219,12 @@ end *) proc elna_name_procedure_temporary(parser_node: ^ElnaTreeVariableDeclaration, symbol_table: ^ElnaSymbolTable) var - info: Word - variable_type: Word + info: ^ElnaSymbolTemporaryInfo + variable_type: ^ElnaType begin variable_type := elna_name_type_expression(parser_node^.type_expression); - info := temporary_info_create(0, variable_type); + info := elna_symbol_temporary_info_create(0, variable_type); elna_symbol_table_enter(symbol_table, parser_node^.name.ptr, parser_node^.name.length, info) end @@ -4767,17 +4776,25 @@ end proc elna_name_type_declaration(parser_node: ^ElnaTreeTypeDeclaration) var - symbol_type: ^ElnaType type_info: ^ElnaSymbolTypeInfo + type_stub: ^ElnaType + type_expression: ^ElnaTreeTypeExpression begin - symbol_type := elna_name_type_expression(parser_node^.type_expression); - type_info := type_info_create(symbol_type); + type_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length); + type_stub := type_info^._type; + type_expression := parser_node^.type_expression; - 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) -begin + if type_stub^.kind = ElnaTypeKind.alias then + elna_name_alias_type_expression(type_expression, type_stub) + elsif type_stub^.kind = ElnaTypeKind.enumeration then + elna_name_enumeration_type_expression(type_expression, type_stub) + elsif type_stub^.kind = ElnaTypeKind._record then + elna_name_record_type_expression(type_expression, type_stub) + elsif type_stub^.kind = ElnaTypeKind.pointer then + elna_name_pointer_type_expression(type_expression, type_stub) + elsif type_stub^.kind = ElnaTypeKind.array then + elna_name_array_type_expression(type_expression, type_stub) + end end proc elna_parser_type_part(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeDeclaration @@ -4979,35 +4996,30 @@ proc elna_parser_module_declaration(cursor: ^ElnaLexerCursor, error_list: ^ElnaL var result: ^ElnaTreeModuleDeclaration begin - result := nil; - if elna_parser_expect(cursor, ElnaLexerKind._program, error_list) <> nil then - if elna_parser_expect(cursor, ElnaLexerKind.semicolon, error_list) <> nil then - result := malloc(#size(ElnaTreeModuleDeclaration)); - result^.kind := ElnaTreeKind.module_declaration; + result := malloc(#size(ElnaTreeModuleDeclaration)); + result^.kind := ElnaTreeKind.module_declaration; - result^.types := elna_parser_type_part(cursor, error_list); - if elna_list_empty(error_list) = false then - result := free_and_nil(result) - end; - if result <> nil then - result^.globals := elna_parser_var_part(cursor, error_list); - end; - if elna_list_empty(error_list) = false then - result := free_and_nil(result) - end; - if result <> nil then - result^.procedures := elna_parser_procedures(cursor, error_list); - end; - if elna_list_empty(error_list) = false then - result := free_and_nil(result) - end; - if result <> nil then - result^.body := elna_parser_program_body(cursor, error_list) - end; - if elna_list_empty(error_list) = false then - result := free_and_nil(result) - end - end + result^.types := elna_parser_type_part(cursor, error_list); + if elna_list_empty(error_list) = false then + result := free_and_nil(result) + end; + if result <> nil then + result^.globals := elna_parser_var_part(cursor, error_list); + end; + if elna_list_empty(error_list) = false then + result := free_and_nil(result) + end; + if result <> nil then + result^.procedures := elna_parser_procedures(cursor, error_list); + end; + if elna_list_empty(error_list) = false then + result := free_and_nil(result) + end; + if result <> nil then + result^.body := elna_parser_program_body(cursor, error_list) + end; + if elna_list_empty(error_list) = false then + result := free_and_nil(result) end; return result end @@ -5107,6 +5119,7 @@ var begin callee_symbol := elna_symbol_table_lookup(symbol_table_global, parser_node^.callee^.name.ptr, parser_node^.callee^.name.length); if callee_symbol = nil then + (* DEBUG *) _write_s(stdout, "# Undefined symbol "); _write_s(stdout, parser_node^.callee^.name); _write_s(stdout, ".\n") @@ -5229,28 +5242,23 @@ var symbol_info: ^ElnaSymbolProcedureInfo return_type: ^ElnaType begin - if parser_node^.return_type = nil then - return_type := nil - else - return_type := elna_name_type_expression(parser_node^.return_type); - end; - new_symbol_table := elna_symbol_table_create(symbol_table_global); - symbol_info := procedure_info_create(new_symbol_table, return_type, parser_node^.is_extern); + symbol_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length); + if symbol_info^.is_extern = false then + new_symbol_table := elna_symbol_table_create(symbol_table_global); + symbol_info^.symbol_table := new_symbol_table; - elna_name_procedure_temporaries(parser_node^.parameters, new_symbol_table); - elna_name_procedure_temporaries(parser_node^.temporaries, new_symbol_table); - elna_name_statements(parser_node^.body, new_symbol_table); - - elna_symbol_table_enter(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length, symbol_info) + elna_name_procedure_temporaries(parser_node^.parameters, new_symbol_table); + elna_name_procedure_temporaries(parser_node^.temporaries, new_symbol_table); + elna_name_statements(parser_node^.body, new_symbol_table) + end end proc elna_name_program_body(parser_node: ^ElnaTreeStatement) var - new_symbol_table: ^ElnaSymbolTable - symbol_info: Word + symbol_info: ^ElnaSymbolProcedureInfo begin - new_symbol_table := elna_symbol_table_create(symbol_table_global); - symbol_info := procedure_info_create(new_symbol_table, nil, false); + symbol_info := elna_symbol_procedure_info_create(nil, false); + symbol_info^.symbol_table := elna_symbol_table_create(symbol_table_global); elna_symbol_table_enter(symbol_table_global, "main".ptr, 4, symbol_info) end @@ -5569,15 +5577,6 @@ proc elna_type_module_declaration(parser_node: ^ElnaTreeModuleDeclaration) var current_part: ^ElnaTreeDeclaration begin - current_part := parser_node^.types; - .elna_type_module_declaration_type; - if current_part <> nil then - elna_type_type_declaration(current_part); - current_part := current_part^.next; - - goto elna_type_module_declaration_type - end; - current_part := parser_node^.procedures; .elna_type_module_declaration_procedure; if current_part <> nil then @@ -5588,6 +5587,74 @@ begin end end +proc elna_declaration_type_declaration(parser_node: ^ElnaTreeTypeDeclaration) +var + type_info: ^ElnaSymbolTypeInfo + result: ^ElnaType + type_expression: ^ElnaTreeTypeExpression +begin + type_expression := parser_node^.type_expression; + + if type_expression^.kind = ElnaTreeKind.named_type_expression then + result := malloc(#size(ElnaTypeAlias)); + result^.kind := ElnaTypeKind.alias + elsif type_expression^.kind = ElnaTreeKind.enumeration_type_expression then + result := malloc(#size(ElnaTypeEnumeration)); + result^.kind := ElnaTypeKind.enumeration + elsif type_expression^.kind = ElnaTreeKind.record_type_expression then + result := malloc(#size(ElnaTypeRecord)); + result^.kind := ElnaTypeKind._record + elsif type_expression^.kind = ElnaTreeKind.pointer_type_expression then + result := malloc(#size(ElnaTypePointer)); + result^.kind := ElnaTypeKind.pointer + elsif type_expression^.kind = ElnaTreeKind.array_type_expression then + result := malloc(#size(ElnaTypeArray)); + result^.kind := ElnaTypeKind.array + end; + type_info := elna_symbol_type_info_create(result); + + elna_symbol_table_enter(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length, type_info) +end + +proc elna_declaration_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration) +var + symbol_info: ^ElnaSymbolProcedureInfo + return_type: ^ElnaType +begin + if parser_node^.return_type = nil then + return_type := nil + else + return_type := elna_name_type_expression(parser_node^.return_type); + end; + symbol_info := elna_symbol_procedure_info_create(return_type, parser_node^.is_extern); + symbol_info^.symbol_table := elna_symbol_table_create(symbol_table_global); + + elna_symbol_table_enter(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length, symbol_info) +end + +proc elna_declaration_module_declaration(parser_node: ^ElnaTreeModuleDeclaration) +var + current_part: ^ElnaTreeDeclaration +begin + current_part := parser_node^.types; + .elna_declaration_module_declaration_type; + if current_part <> nil then + elna_declaration_type_declaration(current_part); + current_part := current_part^.next; + + goto elna_declaration_module_declaration_type + end; + + current_part := parser_node^.procedures; + .elna_declaration_module_declaration_procedure; + if current_part <> nil then + elna_declaration_procedure_declaration(current_part); + current_part := current_part^.next; + + goto elna_declaration_module_declaration_procedure + end +end + proc elna_error_print_token1(kind: ElnaLexerKind) begin if kind = ElnaLexerKind.identifier then @@ -5630,8 +5697,6 @@ begin _write_s(stderr, "\"~\"") elsif kind = ElnaLexerKind._return then _write_s(stderr, "\"return\"") - elsif kind = ElnaLexerKind._program then - _write_s(stderr, "\"program\"") elsif kind = ElnaLexerKind._cast then _write_s(stderr, "\"cast\"") elsif kind = ElnaLexerKind.trait then @@ -5690,6 +5755,8 @@ begin _write_s(stderr, "CHARACTER") elsif kind = ElnaLexerKind.integer then _write_s(stderr, "INTEGER") + elsif kind = ElnaLexerKind.word then + _write_s(stderr, "WORD") else elna_error_print_token2(kind) end @@ -5697,9 +5764,7 @@ end proc elna_error_print_token2(kind: ElnaLexerKind) begin - if kind = ElnaLexerKind.word then - _write_s(stderr, "WORD") - elsif kind = ElnaLexerKind._goto then + if kind = ElnaLexerKind._goto then _write_s(stderr, "\"goto\"") elsif kind = ElnaLexerKind.eof then _write_s(stderr, "EOF") @@ -5743,6 +5808,7 @@ begin compiled := elna_list_empty(@error_list); if compiled then + elna_declaration_module_declaration(parser_node); elna_name_module_declaration(parser_node); elna_type_module_declaration(parser_node); tac := elna_tac_module_declaration(parser_node); @@ -5887,39 +5953,39 @@ begin word_type^.kind := ElnaTypeKind.primitive; word_type^.size := 4; word_type^.alignment := 4; - current_info := type_info_create(word_type); + current_info := elna_symbol_type_info_create(word_type); elna_symbol_table_enter(symbol_table_global, "Word".ptr, 4, current_info); int_type := malloc(#size(ElnaType)); int_type^.kind := ElnaTypeKind.primitive; int_type^.size := 4; int_type^.alignment := 4; - current_info := type_info_create(int_type); + current_info := elna_symbol_type_info_create(int_type); elna_symbol_table_enter(symbol_table_global, "Int".ptr, 3, current_info); current_type := malloc(#size(ElnaType)); current_type^.kind := ElnaTypeKind.primitive; current_type^.size := 4; current_type^.alignment := 4; - current_info := type_info_create(current_type); + current_info := elna_symbol_type_info_create(current_type); elna_symbol_table_enter(symbol_table_global, "Pointer".ptr, 7, current_info); bool_type := malloc(#size(ElnaType)); bool_type^.kind := ElnaTypeKind.primitive; bool_type^.size := 1; bool_type^.alignment := 1; - current_info := type_info_create(bool_type); + current_info := elna_symbol_type_info_create(bool_type); elna_symbol_table_enter(symbol_table_global, "Bool".ptr, 4, current_info); char_type := malloc(#size(ElnaType)); char_type^.kind := ElnaTypeKind.primitive; char_type^.size := 1; char_type^.alignment := 1; - current_info := type_info_create(char_type); + current_info := elna_symbol_type_info_create(char_type); elna_symbol_table_enter(symbol_table_global, "Char".ptr, 4, current_info); elna_symbol_string_build(); - current_info := type_info_create(string_type); + current_info := elna_symbol_type_info_create(string_type); elna_symbol_table_enter(symbol_table_global, "String".ptr, 6, current_info) end @@ -6359,8 +6425,6 @@ begin result^.kind := ElnaLexerKind._or elsif string_compare(position_start, result_length, "xor") then result^.kind := ElnaLexerKind._xor - elsif string_compare(position_start, result_length, "program") then - result^.kind := ElnaLexerKind._program elsif string_compare(position_start, result_length, "nil") then result^.kind := ElnaLexerKind.null elsif string_compare(position_start, result_length, "true") then