diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-10-04 00:51:52 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-10-04 00:51:52 +0200 |
| commit | 8a6ed3a4ddf9c4e16bb4ddc3b8c5094bb937598b (patch) | |
| tree | 18198be391a5fd4b10421c1850f1046b3c2e12c4 /source/type_check.elna | |
| parent | e4ce7f658741a7428597da4872435a1b0bae944c (diff) | |
| download | elna-8a6ed3a4ddf9c4e16bb4ddc3b8c5094bb937598b.tar.gz | |
Update the old compiler with the new syntax
Diffstat (limited to 'source/type_check.elna')
| -rw-r--r-- | source/type_check.elna | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/source/type_check.elna b/source/type_check.elna new file mode 100644 index 0000000..8edc30d --- /dev/null +++ b/source/type_check.elna @@ -0,0 +1,315 @@ +(* This Source Code Form is subject to the terms of the Mozilla Public License, + 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/. *) +module +import common, lexer, ast, symbol, diagnostic + +proc elna_type_is_aggregate*(_type: ^ElnaType) -> Bool +var + result: Bool := false +begin + if _type <> nil then + result := _type^.kind = ElnaTypeKind._record or _type^.kind = ElnaTypeKind.array + end +return result + +proc elna_type_character_literal(parser_node: ^ElnaTreeCharacterLiteral) +begin + parser_node^.type_decoration := char_type +return + +proc elna_type_integer_literal(parser_node: ^ElnaTreeIntegerLiteral) +begin + parser_node^.type_decoration := word_type +return + +proc elna_type_string_literal(parser_node: ^ElnaTreeStringLiteral) +begin + parser_node^.type_decoration := cast(string_type: ^ElnaType) +return + +proc elna_type_boolean_literal(parser_node: ^ElnaTreeBooleanLiteral) +begin + parser_node^.type_decoration := bool_type +return + +proc elna_type_nil_literal(parser_node: ^ElnaTreeNilLiteral) +begin + parser_node^.type_decoration := pointer_type +return + +proc elna_type_variable_expression(parser_node: ^ElnaTreeVariableExpression; symbol_table: ^ElnaSymbolTable) +var + variable_info: ^ElnaSymbolInfo + temporary_info: ^ElnaSymbolTemporaryInfo + procedure_info: ^ElnaSymbolProcedureInfo +begin + variable_info := elna_symbol_table_lookup(symbol_table, parser_node^.name); + if variable_info <> nil then + if variable_info^.kind = ElnaSymbolInfoKind.temporary_info then + temporary_info := cast(variable_info: ^ElnaSymbolTemporaryInfo); + parser_node^.type_decoration := temporary_info^.variable_type + elsif variable_info^.kind = ElnaSymbolInfoKind.procedure_info then + procedure_info := cast(variable_info: ^ElnaSymbolProcedureInfo); + parser_node^.type_decoration := cast(procedure_info^.procedure_type: ^ElnaType) + end + end +return + +proc elna_type_cast_expression(parser_node: ^ElnaTreeCastExpression; symbol_table: ^ElnaSymbolTable; + error_list: ^ElnaList) +begin + elna_type_binary_expression(parser_node^.expression, symbol_table, error_list) +return + +proc elna_type_call(parser_node: ^ElnaTreeCall; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList) +var + argument_tree: ^ElnaTreeExpressionList + procedure_type: ^ElnaTypeProcedure +begin + argument_tree := parser_node^.arguments; + + elna_type_variable_expression(parser_node^.callee, symbol_table); + if parser_node^.callee^.type_decoration <> nil & parser_node^.callee^.type_decoration^.kind = ElnaTypeKind.procedure then + procedure_type := cast(parser_node^.callee^.type_decoration: ^ElnaTypeProcedure); + parser_node^.type_decoration := procedure_type^.return_type + end; + + while argument_tree <> nil do + elna_type_binary_expression(argument_tree^.expression, symbol_table, error_list); + argument_tree := argument_tree^.next + end +return + +proc elna_type_dereference_expression(parser_node: ^ElnaTreeDereferenceExpression; symbol_table: ^ElnaSymbolTable; + error_list: ^ElnaList) +var + base_type: ^ElnaType := nil + pointer_type_node: ^ElnaTypePointer +begin + elna_type_designator(parser_node^.pointer, symbol_table, error_list); + + if parser_node^.pointer^.type_decoration <> nil then + base_type := parser_node^.pointer^.type_decoration; + if base_type^.kind = ElnaTypeKind.pointer then + pointer_type_node := cast(base_type: ^ElnaTypePointer); + base_type := pointer_type_node^.base + end + end; + parser_node^.type_decoration := base_type +return + +proc elna_type_field_access_expression(parser_node: ^ElnaTreeFieldAccessExpression; symbol_table: ^ElnaSymbolTable; + error_list: ^ElnaList) +var + variable_expression: ^ElnaTreeVariableExpression + base_type: ^ElnaType := nil + type_kind: ^ElnaSymbolTypeInfo + symbol_info: ^ElnaSymbolInfo + aggregate_type: ^ElnaTypeRecord + field_count: Word + current_field: ^ElnaTypeField +begin + if parser_node^.aggregate^.kind = ElnaTreeKind.variable_expression then + variable_expression := cast(parser_node^.aggregate: ^ElnaTreeVariableExpression); + symbol_info := elna_symbol_table_lookup(symbol_table_global, variable_expression^.name); + if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.type_info then + type_kind := cast(symbol_info: ^ElnaSymbolTypeInfo); + base_type := type_kind^._type + end + end; + + if base_type = nil then + elna_type_designator(parser_node^.aggregate, symbol_table, error_list); + if parser_node^.aggregate^.type_decoration <> nil & parser_node^.aggregate^.type_decoration^.kind = ElnaTypeKind._record then + aggregate_type := cast(parser_node^.aggregate^.type_decoration: ^ElnaTypeRecord); + field_count := aggregate_type^.length; + current_field := aggregate_type^.members; + + while field_count > 0u & base_type = nil do + if current_field^.name = parser_node^.field then + base_type := current_field^.field_type + else + field_count := field_count - 1u; + current_field := current_field + 1u + end + end + end + end; + + parser_node^.type_decoration := base_type +return + +proc elna_type_array_access_expression(parser_node: ^ElnaTreeArrayAccessExpression; symbol_table: ^ElnaSymbolTable; + error_list: ^ElnaList) +var + aggregate_type: ^ElnaTypeArray +begin + elna_type_designator(parser_node^.array, symbol_table, error_list); + elna_type_binary_expression(parser_node^.index, symbol_table, error_list); + + if parser_node^.array^.type_decoration <> nil & parser_node^.array^.type_decoration^.kind = ElnaTypeKind.array then + aggregate_type := cast(parser_node^.array^.type_decoration: ^ElnaTypeArray); + parser_node^.type_decoration := aggregate_type^.base + end +return + +proc elna_type_simple_expression(parser_node: ^ElnaTreeExpression; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList) +begin + case parser_node^.kind of + ElnaTreeKind.integer_literal: + elna_type_integer_literal(cast(parser_node: ^ElnaTreeIntegerLiteral)) + | ElnaTreeKind.character_literal: + elna_type_character_literal(cast(parser_node: ^ElnaTreeCharacterLiteral)) + | ElnaTreeKind.string_literal: + elna_type_string_literal(cast(parser_node: ^ElnaTreeStringLiteral)) + | ElnaTreeKind.boolean_literal: + elna_type_boolean_literal(cast(parser_node: ^ElnaTreeBooleanLiteral)) + | ElnaTreeKind.null: + elna_type_nil_literal(cast(parser_node: ^ElnaTreeNilLiteral)) + | ElnaTreeKind._cast: + elna_type_cast_expression(cast(parser_node: ^ElnaTreeCastExpression), symbol_table, error_list) + | ElnaTreeKind.variable_expression: + elna_type_variable_expression(cast(parser_node: ^ElnaTreeVariableExpression), symbol_table) + else + end +return + +proc elna_type_designator(parser_node: ^ElnaTreeExpression; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList) +begin + case parser_node^.kind of + ElnaTreeKind.dereference_expression: + elna_type_dereference_expression(cast(parser_node: ^ElnaTreeDereferenceExpression), symbol_table, error_list) + | ElnaTreeKind.field_access_expression: + elna_type_field_access_expression(cast(parser_node: ^ElnaTreeFieldAccessExpression), symbol_table, error_list) + | ElnaTreeKind.array_access_expression: + elna_type_array_access_expression(cast(parser_node: ^ElnaTreeArrayAccessExpression), symbol_table, error_list) + | ElnaTreeKind.call: + elna_type_call(cast(parser_node: ^ElnaTreeCall), symbol_table, error_list) + else + elna_type_simple_expression(parser_node, symbol_table, error_list) + end +return + +proc elna_type_unary_expression(parser_node: ^ElnaTreeExpression; symbol_table: ^ElnaSymbolTable; + error_list: ^ElnaList) +var + unary_node: ^ElnaTreeUnaryExpression +begin + if parser_node^.kind = ElnaTreeKind.unary_expression then + unary_node := cast(parser_node: ^ElnaTreeUnaryExpression); + elna_type_designator(unary_node^.operand, symbol_table, error_list); + parser_node^.type_decoration := unary_node^.operand^.type_decoration + else + elna_type_designator(parser_node, symbol_table, error_list) + end +return + +proc elna_type_binary_expression(parser_node: ^ElnaTreeExpression; symbol_table: ^ElnaSymbolTable; + error_list: ^ElnaList) +var + binary_node: ^ElnaTreeBinaryExpression +begin + if parser_node <> nil then + if parser_node^.kind = ElnaTreeKind.binary_expression then + binary_node := cast(parser_node: ^ElnaTreeBinaryExpression); + elna_type_unary_expression(binary_node^.rhs, symbol_table, error_list); + elna_type_unary_expression(binary_node^.lhs, symbol_table, error_list); + parser_node^.type_decoration := binary_node^.lhs^.type_decoration + else + elna_type_unary_expression(parser_node, symbol_table, error_list) + end + end +return + +proc elna_type_assign_statement(parser_node: ^ElnaTreeAssignStatement; symbol_table: ^ElnaSymbolTable; + error_list: ^ElnaList) +begin + elna_type_designator(parser_node^.assignee, symbol_table, error_list); + elna_type_binary_expression(parser_node^.assignment, symbol_table, error_list) +return + +proc elna_type_conditional_statements(parser_node: ^ElnaTreeConditionalStatements; symbol_table: ^ElnaSymbolTable; + error_list: ^ElnaList) +var + current: ^ElnaTreeConditionalStatements +begin + current := parser_node; + while current <> nil do + elna_type_binary_expression(current^.condition, symbol_table, error_list); + elna_type_statements(current^.statements, symbol_table, error_list); + current := current^.next + end +return + +proc elna_type_if_statement(parser_node: ^ElnaTreeIfStatement; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList) +begin + elna_type_conditional_statements(parser_node^.conditionals, symbol_table, error_list); + if parser_node^._else <> nil then + elna_type_statements(parser_node^._else, symbol_table, error_list) + end +return + +proc elna_type_return_statement(parser_node: ^ElnaTreeReturnStatement; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList) +begin + if parser_node^.returned <> nil then + elna_type_binary_expression(parser_node^.returned, symbol_table, error_list) + end +return + +proc elna_type_statement(parser_node: ^ElnaTreeStatement; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList) +var + call_statement: ^ElnaTreeCallStatement +begin + case parser_node^.kind of + ElnaTreeKind.if_statement: + elna_type_if_statement(cast(parser_node: ^ElnaTreeIfStatement), symbol_table, error_list) + | ElnaTreeKind.return_statement: + elna_type_return_statement(cast(parser_node: ^ElnaTreeReturnStatement), symbol_table, error_list) + | ElnaTreeKind.call_statement: + call_statement := cast(parser_node: ^ElnaTreeCallStatement); + elna_type_call(call_statement^.call, symbol_table, error_list) + | ElnaTreeKind.assign_statement: + elna_type_assign_statement(cast(parser_node: ^ElnaTreeAssignStatement), symbol_table, error_list) + else + end +return + +proc elna_type_statements(parser_node: ^ElnaTreeStatement; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList) +var + current: ^ElnaTreeStatement +begin + current := parser_node; + while current <> nil do + elna_type_statement(current, symbol_table, error_list); + current := current^.next + end +return + +proc elna_type_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration; error_list: ^ElnaList) +var + procedure_info: ^ElnaSymbolProcedureInfo + symbol_info: ^ElnaSymbolInfo +begin + symbol_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name); + if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.procedure_info then + procedure_info := cast(symbol_info: ^ElnaSymbolProcedureInfo); + elna_type_statements(parser_node^.body, procedure_info^.symbol_table, error_list) + end +return + +proc elna_type_module_declaration*(parser_node: ^ElnaTreeModuleDeclaration; error_list: ^ElnaList) +var + current_proc: ^ElnaTreeProcedureDeclaration +begin + current_proc := parser_node^.procedures; + while current_proc <> nil do + elna_type_procedure_declaration(current_proc, error_list); + current_proc := cast(current_proc^.next: ^ElnaTreeProcedureDeclaration) + end; + if parser_node^.body <> nil then + elna_type_statements(parser_node^.body, symbol_table_global, error_list) + end +return + +end. |
