aboutsummaryrefslogtreecommitdiff
path: root/source/type_check.elna
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-10-04 00:51:52 +0200
committerEugen Wissner <belka@caraus.de>2026-10-04 00:51:52 +0200
commit8a6ed3a4ddf9c4e16bb4ddc3b8c5094bb937598b (patch)
tree18198be391a5fd4b10421c1850f1046b3c2e12c4 /source/type_check.elna
parente4ce7f658741a7428597da4872435a1b0bae944c (diff)
downloadelna-8a6ed3a4ddf9c4e16bb4ddc3b8c5094bb937598b.tar.gz
Update the old compiler with the new syntax
Diffstat (limited to 'source/type_check.elna')
-rw-r--r--source/type_check.elna315
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.