diff --git a/TestSuite/records17.pas b/TestSuite/records17.pas new file mode 100644 index 000000000..aa96f0a90 --- /dev/null +++ b/TestSuite/records17.pas @@ -0,0 +1,27 @@ +type + r1 = record + i := 1; + static function f(a: r1): boolean; + begin + Result := a = a; + end; + static function f2(a: r1): boolean; + begin + Result := a <> a; + end; + + {static function operator=(a, b: r1): boolean; + begin + Result := a.i = b.i; + end; + + static function operator<>(a, b: r1): boolean; + begin + Result := a.i <> b.i; + end;} + end; + +begin + assert(r1.f(new r1)); + assert(not r1.f2(new r1)); +end. \ No newline at end of file diff --git a/TestSuite/records18.pas b/TestSuite/records18.pas new file mode 100644 index 000000000..3963eb684 --- /dev/null +++ b/TestSuite/records18.pas @@ -0,0 +1,34 @@ +var flag: boolean; + +type + r1 = record + i := 1; + static function f(a: r1): boolean; + begin + Result := a = a; + end; + static function f2(a: r1): boolean; + begin + Result := a <> a; + end; + + static function operator=(a, b: r1): boolean; + begin + flag := true; + Result := a.i = b.i; + end; + + static function operator<>(a, b: r1): boolean; + begin + flag := true; + Result := a.i <> b.i; + end; + end; + +begin + assert(r1.f(new r1)); + assert(flag); + flag := false; + assert(not r1.f2(new r1)); + assert(flag); +end. \ No newline at end of file diff --git a/TreeConverter/TreeConversion/compilation_context.cs b/TreeConverter/TreeConversion/compilation_context.cs index 0bd348773..c51bd5ff8 100644 --- a/TreeConverter/TreeConversion/compilation_context.cs +++ b/TreeConverter/TreeConversion/compilation_context.cs @@ -1017,22 +1017,42 @@ namespace PascalABCCompiler.TreeConverter private readonly System.Collections.Generic.Stack type_stack = new System.Collections.Generic.Stack(); - private void add_notequal_operator_if_need() + internal void add_notequal_operator_if_need(bool not_add_body= false) { List si_list = _ctn.find_in_type(compiler_string_consts.noteq_name); + common_method_node cmn = null; + common_parameter prm1 = null; + common_parameter prm2 = null; foreach (SymbolInfo si2 in si_list) if (si2.sym_info is common_method_node) - return; + { + cmn = si2.sym_info as common_method_node; + if (cmn.function_code != null) + return; + } SymbolInfo si = si_list[0]; SymbolTable.ClassMethodScope scope = convertion_data_and_alghoritms.symbol_table.CreateClassMethodScope(_ctn.scope, _cmn.scope, null, si.ToString()); - common_method_node cmn = new common_method_node(compiler_string_consts.GetNETOperName(compiler_string_consts.noteq_name),SystemLibrary.SystemLibrary.bool_type,null,_ctn, - SemanticTree.polymorphic_state.ps_static,SemanticTree.field_access_level.fal_public,scope); - cmn.IsOperator = true; - common_parameter prm1 = new common_parameter("a",_ctn,SemanticTree.parameter_type.value,cmn,concrete_parameter_type.cpt_none,null,null); - common_parameter prm2 = new common_parameter("b",_ctn,SemanticTree.parameter_type.value,cmn,concrete_parameter_type.cpt_none,null,null); - cmn.parameters.AddElement(prm1); - cmn.parameters.AddElement(prm2); - statements_list body = new statements_list(null); + if (cmn == null) + { + cmn = new common_method_node(compiler_string_consts.GetNETOperName(compiler_string_consts.noteq_name), SystemLibrary.SystemLibrary.bool_type, null, _ctn, + SemanticTree.polymorphic_state.ps_static, SemanticTree.field_access_level.fal_public, scope); + cmn.IsOperator = true; + prm1 = new common_parameter("a", _ctn, SemanticTree.parameter_type.value, cmn, concrete_parameter_type.cpt_none, null, null); + prm2 = new common_parameter("b", _ctn, SemanticTree.parameter_type.value, cmn, concrete_parameter_type.cpt_none, null, null); + cmn.parameters.AddElement(prm1); + cmn.parameters.AddElement(prm2); + cmn.is_overload = true; + _ctn.methods.AddElement(cmn); + _ctn.Scope.AddSymbol(compiler_string_consts.noteq_name, new SymbolInfo(cmn)); + } + else + { + prm1 = cmn.parameters[0] as common_parameter; + prm2 = cmn.parameters[1] as common_parameter; + } + if (not_add_body) + return; + statements_list body = new statements_list(null); foreach (class_field cf in _ctn.fields) { if (cf.polymorphic_state == SemanticTree.polymorphic_state.ps_static) @@ -1048,26 +1068,45 @@ namespace PascalABCCompiler.TreeConverter } body.statements.AddElement(new return_node(new bool_const_node(false,null),null)); cmn.function_code = body; - cmn.is_overload = true; - _ctn.methods.AddElement(cmn); - _ctn.Scope.AddSymbol(compiler_string_consts.noteq_name,new SymbolInfo(cmn)); + } - private void add_equal_operator_if_need() + internal void add_equal_operator_if_need(bool not_add_body=false) { List si_list = _ctn.find_in_type(compiler_string_consts.eq_name); + common_method_node cmn = null; + common_parameter prm1 = null; + common_parameter prm2 = null; foreach (SymbolInfo si2 in si_list) if (si2.sym_info is common_method_node) - return; + { + cmn = si2.sym_info as common_method_node; + if (cmn.function_code != null) + return; + } + SymbolInfo si = si_list[0]; SymbolTable.ClassMethodScope scope = convertion_data_and_alghoritms.symbol_table.CreateClassMethodScope( _ctn.scope, _cmn.scope, null, si.ToString()); - common_method_node cmn = new common_method_node(compiler_string_consts.GetNETOperName(compiler_string_consts.eq_name),SystemLibrary.SystemLibrary.bool_type,null,_ctn, - SemanticTree.polymorphic_state.ps_static,SemanticTree.field_access_level.fal_public,scope); - cmn.IsOperator = true; - common_parameter prm1 = new common_parameter("a",_ctn,SemanticTree.parameter_type.value,cmn,concrete_parameter_type.cpt_none,null,null); - common_parameter prm2 = new common_parameter("b",_ctn,SemanticTree.parameter_type.value,cmn,concrete_parameter_type.cpt_none,null,null); - cmn.parameters.AddElement(prm1); - cmn.parameters.AddElement(prm2); + if (cmn == null) + { + cmn = new common_method_node(compiler_string_consts.GetNETOperName(compiler_string_consts.eq_name), SystemLibrary.SystemLibrary.bool_type, null, _ctn, + SemanticTree.polymorphic_state.ps_static, SemanticTree.field_access_level.fal_public, scope); + cmn.IsOperator = true; + prm1 = new common_parameter("a", _ctn, SemanticTree.parameter_type.value, cmn, concrete_parameter_type.cpt_none, null, null); + prm2 = new common_parameter("b", _ctn, SemanticTree.parameter_type.value, cmn, concrete_parameter_type.cpt_none, null, null); + cmn.parameters.AddElement(prm1); + cmn.parameters.AddElement(prm2); + cmn.is_overload = true; + _ctn.methods.AddElement(cmn); + _ctn.Scope.AddSymbol(compiler_string_consts.eq_name, new SymbolInfo(cmn)); + } + else + { + prm1 = cmn.parameters[0] as common_parameter; + prm2 = cmn.parameters[1] as common_parameter; + } + if (not_add_body) + return; statements_list body = new statements_list(null); foreach (class_field cf in _ctn.fields) { @@ -1084,9 +1123,7 @@ namespace PascalABCCompiler.TreeConverter } body.statements.AddElement(new return_node(new bool_const_node(true,null),null)); cmn.function_code = body; - cmn.is_overload = true; - _ctn.methods.AddElement(cmn); - _ctn.Scope.AddSymbol(compiler_string_consts.eq_name,new SymbolInfo(cmn)); + } public void leave_record() @@ -1094,8 +1131,8 @@ namespace PascalABCCompiler.TreeConverter check_implement_interfaces(); if (!_ctn.IsEnum) { - add_equal_operator_if_need(); - add_notequal_operator_if_need(); + //add_equal_operator_if_need(); + //add_notequal_operator_if_need(); } if (type_stack.Count != 0) { diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index d97b80bc0..fb08ac26d 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -3918,6 +3918,7 @@ namespace PascalABCCompiler.TreeConverter record_type_name = null; record_is_generic = false; context.converted_type.internal_is_value = true; + if (_class_definition.body == null && (_class_definition.class_parents == null || _class_definition.class_parents.types.Count == 0)) { @@ -3930,6 +3931,7 @@ namespace PascalABCCompiler.TreeConverter } else { + context.converted_type.ForwardDeclarationOnly = false; weak_node_test_and_visit(_class_definition.body); @@ -4051,7 +4053,13 @@ namespace PascalABCCompiler.TreeConverter private void visit_class_member_realizations(SyntaxTree.class_body_list _class_body) { - foreach (SyntaxTree.class_members clmem in _class_body.class_def_blocks) + if (context.converted_type.internal_is_value) + { + context.add_equal_operator_if_need(); + context.add_notequal_operator_if_need(); + } + + foreach (SyntaxTree.class_members clmem in _class_body.class_def_blocks) { foreach (SyntaxTree.declaration sd in clmem.members) {