diff --git a/Configuration/GlobalAssemblyInfo.cs b/Configuration/GlobalAssemblyInfo.cs index 794689682..7689102d4 100644 --- a/Configuration/GlobalAssemblyInfo.cs +++ b/Configuration/GlobalAssemblyInfo.cs @@ -15,7 +15,7 @@ internal static class RevisionClass public const string Major = "3"; public const string Minor = "2"; public const string Build = "0"; - public const string Revision = "1492"; + public const string Revision = "1504"; public const string MainVersion = Major + "." + Minor; public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision; diff --git a/Configuration/Version.defs b/Configuration/Version.defs index de64b317a..e59453269 100644 --- a/Configuration/Version.defs +++ b/Configuration/Version.defs @@ -1,4 +1,4 @@ %MINOR%=2 -%REVISION%=1492 +%REVISION%=1504 %COREVERSION%=0 %MAJOR%=3 diff --git a/ReleaseGenerators/PascalABCNET_version.nsh b/ReleaseGenerators/PascalABCNET_version.nsh index 8c8e67b5e..0f4bb03f7 100644 --- a/ReleaseGenerators/PascalABCNET_version.nsh +++ b/ReleaseGenerators/PascalABCNET_version.nsh @@ -1 +1 @@ -!define VERSION '3.2.0.1492' +!define VERSION '3.2.0.1504' diff --git a/TestSuite/CompilationSamples/PABCSystem.pas b/TestSuite/CompilationSamples/PABCSystem.pas index 420509543..6bd9f50a0 100644 --- a/TestSuite/CompilationSamples/PABCSystem.pas +++ b/TestSuite/CompilationSamples/PABCSystem.pas @@ -551,6 +551,27 @@ procedure Read(var x: boolean); /// Вводит значения a,b,... с клавиатуры и осуществляет переход на следующую строку procedure Readln; +/// Вводит числовое значение x клавиатуры. Возвращает False если при вводе произошла ошибка +function TryRead(var x: integer): boolean; +///-- +function TryRead(var x: real): boolean; +///-- +function TryRead(var x: byte): boolean; +///-- +function TryRead(var x: shortint): boolean; +///-- +function TryRead(var x: smallint): boolean; +///-- +function TryRead(var x: word): boolean; +///-- +function TryRead(var x: longword): boolean; +///-- +function TryRead(var x: int64): boolean; +///-- +function TryRead(var x: uint64): boolean; +///-- +function TryRead(var x: single): boolean; + /// Возвращает значение типа integer, введенное с клавиатуры function ReadInteger: integer; /// Возвращает значение типа real, введенное с клавиатуры @@ -1632,11 +1653,11 @@ procedure Sort(l: List; cmp: (T,T)->integer); procedure Sort(l: List; less: (T,T)->boolean); /// Изменяет порядок элементов в динамическом массиве на противоположный procedure Reverse(a: array of T); -/// Изменяет порядок элементов на противоположный в диапазоне динамического массива длины length начиная с индекса index +/// Изменяет порядок элементов на противоположный в диапазоне динамического массива длины count, начиная с индекса index procedure Reverse(a: array of T; index,count: integer); /// Изменяет порядок элементов в списке на противоположный procedure Reverse(a: List); -/// Изменяет порядок элементов на противоположный в диапазоне списка длины length начиная с индекса index +/// Изменяет порядок элементов на противоположный в диапазоне списка длины count, начиная с индекса index procedure Reverse(a: List; index,count: integer); /// Перемешивает динамический массив случайным образом procedure Shuffle(a: array of T); @@ -2614,9 +2635,9 @@ end; class function TypedSet.operator implicit(s: TypedSet): HashSet; begin var hs := new HashSet(); - foreach key: T in s.ht.Keys do + foreach var key in s.ht.Keys do begin - hs.Add(key); + hs.Add(T(key)); end; Result := hs; end; @@ -4460,7 +4481,7 @@ begin end; end; -procedure read(var x: integer); +procedure Read(var x: integer); begin if input.sr <> nil then read(input, x) @@ -4473,7 +4494,7 @@ begin end; end; -procedure read(var x: real); +procedure Read(var x: real); begin if input.sr <> nil then read(input, x) @@ -4486,7 +4507,7 @@ begin end; end; -procedure read(var x: char); +procedure Read(var x: char); begin if input.sr <> nil then read(input, x) @@ -4499,7 +4520,7 @@ begin end; end; -procedure read(var x: string); +procedure Read(var x: string); begin if input.sr <> nil then read(input, x) @@ -4512,7 +4533,7 @@ begin end; end; -procedure read(var x: byte); +procedure Read(var x: byte); begin if input.sr <> nil then read(input, x) @@ -4525,7 +4546,7 @@ begin end; end; -procedure read(var x: shortint); +procedure Read(var x: shortint); begin if input.sr <> nil then read(input, x) @@ -4538,7 +4559,7 @@ begin end; end; -procedure read(var x: smallint); +procedure Read(var x: smallint); begin if input.sr <> nil then read(input, x) @@ -4551,7 +4572,7 @@ begin end; end; -procedure read(var x: word); +procedure Read(var x: word); begin if input.sr <> nil then read(input, x) @@ -4564,7 +4585,7 @@ begin end; end; -procedure read(var x: longword); +procedure Read(var x: longword); begin if input.sr <> nil then read(input, x) @@ -4577,7 +4598,7 @@ begin end; end; -procedure read(var x: int64); +procedure Read(var x: int64); begin if input.sr <> nil then read(input, x) @@ -4590,7 +4611,7 @@ begin end; end; -procedure read(var x: uint64); +procedure Read(var x: uint64); begin if input.sr <> nil then read(input, x) @@ -4603,7 +4624,7 @@ begin end; end; -procedure read(var x: single); +procedure Read(var x: single); begin if input.sr <> nil then read(input, x) @@ -4616,7 +4637,7 @@ begin end; end; -procedure read(var x: boolean); +procedure Read(var x: boolean); begin if input.sr <> nil then read(input, x) @@ -4629,6 +4650,107 @@ begin end; end; +function TryRead(var x: integer): boolean; +begin + Result := True; + try + Read(x) + except + Result := False; + end +end; + +function TryRead(var x: real): boolean; +begin + Result := True; + try + Read(x) + except + Result := False; + end +end; + +function TryRead(var x: byte): boolean; +begin + Result := True; + try + Read(x) + except + Result := False; + end +end; + +function TryRead(var x: shortint): boolean; +begin + Result := True; + try + Read(x) + except + Result := False; + end +end; + +function TryRead(var x: smallint): boolean; +begin + Result := True; + try + Read(x) + except + Result := False; + end +end; + +function TryRead(var x: word): boolean; +begin + Result := True; + try + Read(x) + except + Result := False; + end +end; + +function TryRead(var x: longword): boolean; +begin + Result := True; + try + Read(x) + except + Result := False; + end +end; + +function TryRead(var x: int64): boolean; +begin + Result := True; + try + Read(x) + except + Result := False; + end +end; + +function TryRead(var x: uint64): boolean; +begin + Result := True; + try + Read(x) + except + Result := False; + end +end; + +function TryRead(var x: single): boolean; +begin + Result := True; + try + Read(x) + except + Result := False; + end +end; + + function ReadInteger: integer; begin var x: integer; @@ -10697,7 +10819,7 @@ begin input := new TextFile(); //var tmp := __CONFIG__; if (Environment.OSVersion.Platform = PlatformID.Unix) or (Environment.OSVersion.Platform = PlatformID.MacOSX) then - foreach listener: System.Diagnostics.TraceListener in System.Diagnostics.Trace.Listeners do + foreach var listener in System.Diagnostics.Trace.Listeners do if listener is System.Diagnostics.DefaultTraceListener then (listener as System.Diagnostics.DefaultTraceListener).AssertUiEnabled := true; end; diff --git a/TestSuite/CompilationSamples/foreach_ArrayList.pas b/TestSuite/CompilationSamples/foreach_ArrayList.pas new file mode 100644 index 000000000..502aa04fb --- /dev/null +++ b/TestSuite/CompilationSamples/foreach_ArrayList.pas @@ -0,0 +1,9 @@ +begin + //var a: array [1..5] of integer := (1,3,5,7,9); + //var a := Arr(1,2,3,4,5); + //var a := Arr(1.0,2.0); + var a := new System.Collections.ArrayList(); + a.Add(2); + foreach x: integer in a do + Print(x); +end. \ No newline at end of file diff --git a/TestSuite/CompilationSamples/foreach_Person_Student.pas b/TestSuite/CompilationSamples/foreach_Person_Student.pas new file mode 100644 index 000000000..3ac04d4bf --- /dev/null +++ b/TestSuite/CompilationSamples/foreach_Person_Student.pas @@ -0,0 +1,14 @@ +type + Person = class + + end; + Student = class(Person) + public + i: integer; + end; + +begin + var persons := Arr(new Student, new Student); + foreach x: Person in persons do + Print(x.GetType); +end. \ No newline at end of file diff --git a/TestSuite/CompilationSamples/foreach_real_int.pas b/TestSuite/CompilationSamples/foreach_real_int.pas new file mode 100644 index 000000000..a519776f7 --- /dev/null +++ b/TestSuite/CompilationSamples/foreach_real_int.pas @@ -0,0 +1,8 @@ +begin + //var a: array [1..5] of integer := (1,3,5,7,9); + var a := Arr(1,2,3,4,5); + //var a := Arr(1.0,2.0); + //var a := new System.Collections.ArrayList(); + foreach x: real in a do + Print(x); +end. \ No newline at end of file diff --git a/TestSuite/errors/err0226.pas b/TestSuite/errors/err0226.pas new file mode 100644 index 000000000..bb3e2c314 --- /dev/null +++ b/TestSuite/errors/err0226.pas @@ -0,0 +1,8 @@ +begin + //var a: array [1..5] of integer := (1,3,5,7,9); + //var a := Arr(1,2,3,4,5); + var a := Arr(1.0,2.0); + //var a := new System.Collections.ArrayList(); + foreach x: integer in a do + Print(x); +end. \ No newline at end of file diff --git a/TestSuite/errors/err0227.pas b/TestSuite/errors/err0227.pas new file mode 100644 index 000000000..ead99492e --- /dev/null +++ b/TestSuite/errors/err0227.pas @@ -0,0 +1,14 @@ +type + Person = class + + end; + Student = class(Person) + public + i: integer; + end; + +begin + var persons := Arr(new Person, new Person); + foreach x: Student in persons do + Print(x.GetType); +end. \ No newline at end of file diff --git a/TreeConverter/LambdaExpressions/Closure/CapturedVariablesTreeBuilder.cs b/TreeConverter/LambdaExpressions/Closure/CapturedVariablesTreeBuilder.cs index 2e3eb79c5..ccfe8715b 100644 --- a/TreeConverter/LambdaExpressions/Closure/CapturedVariablesTreeBuilder.cs +++ b/TreeConverter/LambdaExpressions/Closure/CapturedVariablesTreeBuilder.cs @@ -426,8 +426,8 @@ namespace TreeConverter.LambdaExpressions.Closure type_node elemType = null; if (inWhat.type == null) inWhat = tmp; - - _visitor.FindIEnumerableElementType(/*_foreach_stmt, */inWhat.type, ref elemType); + bool bb; // здесь bb не нужно. Оно нужно в foreach + _visitor.FindIEnumerableElementType(/*_foreach_stmt, */inWhat.type, ref elemType, out bb); if (_foreach_stmt.type_name == null) { diff --git a/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs b/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs index d453626c2..b19cc5446 100644 --- a/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs +++ b/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs @@ -599,7 +599,7 @@ namespace PascalABCCompiler.TreeConverter possible_type_convertions pct = type_table.get_convertions(from, to); if (pct.second != null) throw new TwoTypeConversionsPossibleT(pct.first, pct.second, loc); - if (pct.first == null && !type_table.is_derived(from, to)) + if (pct.first == null /*&& !type_table.is_derived(from, to)*/) throw new CanNotConvertTypes(null, from, to, loc); } diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index 7b6d767ae..77f5bbb40 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -15970,7 +15970,8 @@ namespace PascalABCCompiler.TreeConverter var tt = to.type; type_node elem_type = null; try_convert_typed_expression_to_function_call(ref from); - var b = FindIEnumerableElementType(from.type, ref elem_type); + bool bb; // здесь bb не нужно. Оно нужно в foreach + var b = FindIEnumerableElementType(from.type, ref elem_type, out bb); if (!b) AddError(from.location, "CAN_NOT_EXECUTE_FOREACH_BY_EXPR_OF_TYPE_{0}", from.type.full_name); @@ -16558,8 +16559,9 @@ namespace PascalABCCompiler.TreeConverter return false; } - public bool FindIEnumerableElementType(/*SyntaxTree.foreach_stmt _foreach_stmt, */type_node tn, ref type_node elem_type) + public bool FindIEnumerableElementType(type_node tn, ref type_node elem_type, out bool sys_coll_ienum) { + sys_coll_ienum = false; var IEnstring = "System.Collections.IEnumerable"; compiled_type_node ctn = compiled_type_node.get_type_node(NetHelper.NetHelper.FindType(IEnstring)); if (tn is compiled_type_node || tn is compiled_generic_instance_type_node) // Если этот тип зашит в .NET @@ -16628,6 +16630,7 @@ namespace PascalABCCompiler.TreeConverter if (itn == ctn) { elem_type = SystemLibrary.SystemLibrary.object_type; + sys_coll_ienum = true; return true; } } @@ -16691,6 +16694,7 @@ namespace PascalABCCompiler.TreeConverter if (itn == ctn) { elem_type = SystemLibrary.SystemLibrary.object_type; + sys_coll_ienum = true; return true; } } @@ -16717,7 +16721,7 @@ namespace PascalABCCompiler.TreeConverter expression_node in_what = convert_strong(_foreach_stmt.in_what); // SSM 29.07.16 - если in_what - одномерный массив, то заменить код foreach на for - var is1dimdynarr = false; + /*var is1dimdynarr = false; var comptn = in_what.type as compiled_type_node; if (comptn != null && comptn.type_special_kind == SemanticTree.type_special_kind.array_kind && comptn.rank == 1) { @@ -16775,7 +16779,7 @@ namespace PascalABCCompiler.TreeConverter //visit(fornode); return; - } + }*/ /// SSM 29.07.16 //throw new NotSupportedError(get_location(_foreach_stmt)); @@ -16793,8 +16797,8 @@ namespace PascalABCCompiler.TreeConverter //(in_what.type as common_type_node).internal_type_special_kind == SemanticTree.type_special_kind.array_kind //in_what.type as compiled_type_node - - if (!FindIEnumerableElementType(/*_foreach_stmt, */in_what.type, ref elem_type)) + bool sys_coll_ienum; // bb = true означает, что мы нашли тип object у интерфейса System.Collections.IEnumerable + if (!FindIEnumerableElementType(in_what.type, ref elem_type, out sys_coll_ienum)) //if (!IsGetEnumerator(in_what.type, ref elem_type)) AddError(in_what.location, "CAN_NOT_EXECUTE_FOREACH_BY_EXPR_OF_TYPE_{0}", in_what.type.name); @@ -16829,8 +16833,8 @@ namespace PascalABCCompiler.TreeConverter } //elem_type = vdn.type; - if (!(vdn.type is compiled_generic_instance_type_node)) - convertion_data_and_alghoritms.check_convert_type_with_inheritance(vdn.type, elem_type, get_location(_foreach_stmt.identifier)); + if (!(vdn.type is compiled_generic_instance_type_node) && !sys_coll_ienum) + convertion_data_and_alghoritms.check_convert_type_with_inheritance(elem_type, vdn.type, get_location(_foreach_stmt.identifier)); //if (!convertion_data_and_alghoritms.eq_type_nodes(elem_type, vdn.type)) //AddError(new TypesOfVarAndElementsInForeachMustBeEqual(vdn.type.name,elem_type.name,get_location(_foreach_stmt.identifier))); diff --git a/bin/Lib/PABCRtl.dll b/bin/Lib/PABCRtl.dll index c69994c61..72d58693c 100644 Binary files a/bin/Lib/PABCRtl.dll and b/bin/Lib/PABCRtl.dll differ diff --git a/bin/Lib/PABCSystem.pas b/bin/Lib/PABCSystem.pas index 5ffccc63d..6bd9f50a0 100644 --- a/bin/Lib/PABCSystem.pas +++ b/bin/Lib/PABCSystem.pas @@ -1653,11 +1653,11 @@ procedure Sort(l: List; cmp: (T,T)->integer); procedure Sort(l: List; less: (T,T)->boolean); /// Изменяет порядок элементов в динамическом массиве на противоположный procedure Reverse(a: array of T); -/// Изменяет порядок элементов на противоположный в диапазоне динамического массива длины length начиная с индекса index +/// Изменяет порядок элементов на противоположный в диапазоне динамического массива длины count, начиная с индекса index procedure Reverse(a: array of T; index,count: integer); /// Изменяет порядок элементов в списке на противоположный procedure Reverse(a: List); -/// Изменяет порядок элементов на противоположный в диапазоне списка длины length начиная с индекса index +/// Изменяет порядок элементов на противоположный в диапазоне списка длины count, начиная с индекса index procedure Reverse(a: List; index,count: integer); /// Перемешивает динамический массив случайным образом procedure Shuffle(a: array of T); @@ -2635,9 +2635,9 @@ end; class function TypedSet.operator implicit(s: TypedSet): HashSet; begin var hs := new HashSet(); - foreach key: T in s.ht.Keys do + foreach var key in s.ht.Keys do begin - hs.Add(key); + hs.Add(T(key)); end; Result := hs; end; @@ -10819,7 +10819,7 @@ begin input := new TextFile(); //var tmp := __CONFIG__; if (Environment.OSVersion.Platform = PlatformID.Unix) or (Environment.OSVersion.Platform = PlatformID.MacOSX) then - foreach listener: System.Diagnostics.TraceListener in System.Diagnostics.Trace.Listeners do + foreach var listener in System.Diagnostics.Trace.Listeners do if listener is System.Diagnostics.DefaultTraceListener then (listener as System.Diagnostics.DefaultTraceListener).AssertUiEnabled := true; end; diff --git a/bin/PascalABCNET.chm b/bin/PascalABCNET.chm index fe4c7c4dd..2d41b1323 100644 Binary files a/bin/PascalABCNET.chm and b/bin/PascalABCNET.chm differ