From e132148c4460b7292a3e480d03fdff5667f9c127 Mon Sep 17 00:00:00 2001 From: Ivan Bondarev Date: Sun, 23 Jan 2022 12:10:05 +0100 Subject: [PATCH] bug fix #2614 --- Compiler/Compiler.cs | 1 + Compiler/PCU/PCUReader.cs | 32 +++++++++++++++++++++------ TestSuite/units/u_property3.pas | 26 ++++++++++++++++++++++ TestSuite/usesunits/use_property3.pas | 8 +++++++ 4 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 TestSuite/units/u_property3.pas create mode 100644 TestSuite/usesunits/use_property3.pas diff --git a/Compiler/Compiler.cs b/Compiler/Compiler.cs index 7d540b12d..5b276c40b 100644 --- a/Compiler/Compiler.cs +++ b/Compiler/Compiler.cs @@ -2361,6 +2361,7 @@ namespace PascalABCCompiler p.AddInitFinalMethods(); SystemLibrary.SystemLibInitializer.RestoreStandardFunctions(); p.ProcessWaitedToRestoreFields(); + p.RestoreWaitedMethodCodes(); } bool rest = true; for (int i=0; i interf_type_list = new SortedDictionary(); private SortedDictionary impl_type_list = new SortedDictionary(); - + private Dictionary waited_method_codes = new Dictionary(); internal static Dictionary AllReadOrWritedDefinitionNodesOffsets = new Dictionary(); internal void AddMember(definition_node dn, int offset) { @@ -687,8 +687,21 @@ namespace PascalABCCompiler.PCU assemblies[s] = a; } } + + public void AddWaitedMethodCode(common_method_node cmn, int offset) + { + if (!waited_method_codes.ContainsKey(cmn)) + waited_method_codes.Add(cmn, offset); + } + + public void RestoreWaitedMethodCodes() + { + foreach (common_method_node cmn in waited_method_codes.Keys) + cmn.function_code = GetCode(waited_method_codes[cmn]); + } + //получение кода метода - public statement_node GetCode(int offset) + public statement_node GetCode(int offset) { int tmp = (int)br.BaseStream.Position; br.BaseStream.Seek(start_pos+offset,SeekOrigin.Begin); @@ -1649,7 +1662,7 @@ namespace PascalABCCompiler.PCU return ccd; } - private common_method_node CreateInterfaceMethod(string name, int offset) + private common_method_node CreateInterfaceMethod(string name, int offset, bool not_restore_code = false) { definition_node dn = null; if (members.TryGetValue(offset, out dn)) @@ -1705,8 +1718,11 @@ namespace PascalABCCompiler.PCU cmn.functions_nodes_list.AddElement(GetNestedFunction()); //br.ReadInt32();//code; cmn.loc = ReadDebugInfo(); + if (has_overrided_method) cmn.function_code = GetCodeWithOverridedMethod(cmn, br.ReadInt32()); + else if (not_restore_code && cmn.name != "get_val" && cmn.name != "set_val")//ignore pascal array property accessors + AddWaitedMethodCode(cmn, br.ReadInt32()); else cmn.function_code = GetCode(br.ReadInt32()); cmn.cont_type.methods.AddElement(cmn); @@ -1761,7 +1777,7 @@ namespace PascalABCCompiler.PCU //все методы с именем на Get вызываются в процессе восстановления других сущностей //например, когда восст. код ф-ии, в нем вызывается другая ф-я, которая еще не восстановлена - private common_method_node GetClassMethod(int offset) + private common_method_node GetClassMethod(int offset, bool not_restore_code = false) { definition_node dn = null; if (members.TryGetValue(offset, out dn)) @@ -1771,7 +1787,7 @@ namespace PascalABCCompiler.PCU br.BaseStream.Seek(start_pos + offset, SeekOrigin.Begin); br.ReadByte(); - cmn = (common_method_node)CreateInterfaceMethod(null, offset); + cmn = (common_method_node)CreateInterfaceMethod(null, offset, not_restore_code); br.BaseStream.Seek(tmp, SeekOrigin.Begin); return cmn; @@ -1851,9 +1867,11 @@ namespace PascalABCCompiler.PCU int name_ref = br.ReadInt32(); type_node type = GetTypeReference(); common_method_node get_meth = null; - if (br.ReadByte() == 1) get_meth = GetClassMethod(br.ReadInt32()); + if (br.ReadByte() == 1) + get_meth = GetClassMethod(br.ReadInt32(), true); common_method_node set_meth = null; - if (br.ReadByte() == 1) set_meth = GetClassMethod(br.ReadInt32()); + if (br.ReadByte() == 1) + set_meth = GetClassMethod(br.ReadInt32(), true); int num = br.ReadInt32(); parameter_list pl = new parameter_list(); for (int i = 0; i < num; i++) diff --git a/TestSuite/units/u_property3.pas b/TestSuite/units/u_property3.pas new file mode 100644 index 000000000..61158fb43 --- /dev/null +++ b/TestSuite/units/u_property3.pas @@ -0,0 +1,26 @@ +unit u_property3; + +type + t1 = class + public i: integer; + procedure p1(ind: integer); + + // Обязательно default индексное свойство + // Обязательно упомянуть p1, реализованное после объявления t2 + // Не важно как упомянуть + public property Item[ind: byte]: word write p1(ind); default; + + end; + + // Обязательно шаблон + // Обязательно наследовать от t1 + t2 = class(t1) end; + +procedure t1.p1(ind: integer); +begin + // Обязательно упомянуть t2 + var a: t2; + self.i := ind; +end; + +end. \ No newline at end of file diff --git a/TestSuite/usesunits/use_property3.pas b/TestSuite/usesunits/use_property3.pas new file mode 100644 index 000000000..b855e1953 --- /dev/null +++ b/TestSuite/usesunits/use_property3.pas @@ -0,0 +1,8 @@ +uses u_property3; + +begin +var b: t2; +var c: t1 := new t1; +c[2] := 2; +assert(c.i = 2); +end.