diff --git a/Configuration/GlobalAssemblyInfo.cs b/Configuration/GlobalAssemblyInfo.cs index 79a38c4a5..9797aebe7 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 = "9"; public const string Build = "0"; - public const string Revision = "3351"; + public const string Revision = "3358"; 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 c21ec1d20..09746ef90 100644 --- a/Configuration/Version.defs +++ b/Configuration/Version.defs @@ -1,4 +1,4 @@ -%MINOR%=9 -%REVISION%=3351 %COREVERSION%=0 +%REVISION%=3358 +%MINOR%=9 %MAJOR%=3 diff --git a/Release/pabcversion.txt b/Release/pabcversion.txt index 27ac1bf27..6848b9de1 100644 --- a/Release/pabcversion.txt +++ b/Release/pabcversion.txt @@ -1 +1 @@ -3.9.0.3351 +3.9.0.3358 diff --git a/ReleaseGenerators/PascalABCNET_version.nsh b/ReleaseGenerators/PascalABCNET_version.nsh index 95bb6535c..157d2b09a 100644 --- a/ReleaseGenerators/PascalABCNET_version.nsh +++ b/ReleaseGenerators/PascalABCNET_version.nsh @@ -1 +1 @@ -!define VERSION '3.9.0.3351' +!define VERSION '3.9.0.3358' diff --git a/TestSuite/CompilationSamples/School.pas b/TestSuite/CompilationSamples/School.pas index 50c6d18b4..590143161 100644 --- a/TestSuite/CompilationSamples/School.pas +++ b/TestSuite/CompilationSamples/School.pas @@ -1,49 +1,59 @@ -/// Учебный модуль, реализующий базовые алгоритмы информатики. +/// Учебный модуль, реализующий базовые алгоритмы информатики (09.10.2023) unit School; interface /// Перевод десятичного числа в двоичную систему счисления -function Bin(Число: int64): string; +function Bin(number: int64): string; /// Перевод десятичного числа в двоичную систему счисления -function Bin(Число: BigInteger): string; +function Bin(number: BigInteger): string; + +/// Перевод десятичного числа в двоичную систему счисления с форматированием. +/// bytes - требуемая длина в байтах, автоматически увеличивается, если недостаточна +/// split - разделитель байтов, можено задать пустое значение '' +function BinFormat(number: BigInteger; bytes: integer := 0; split: string := ' '): string; + +/// Перевод десятичного числа в двоичную систему счисления с форматированием. +/// bytes - требуемая длина в байтах, автоматически увеличивается, если недостаточна +/// split - разделитель байтов, можено задать пустое значение '' +function BinFormat(number: int64; bytes: integer := 0; split: string := ' '): string; /// Перевод десятичного числа в восьмеричную систему счисления -function Oct(Число: int64): string; +function Oct(number: int64): string; /// Перевод десятичного числа в восьмеричную систему счисления -function Oct(Число: BigInteger): string; +function Oct(number: BigInteger): string; /// Перевод десятичного числа в шестнадцатиричную систему счисления -function Hex(Число: int64): string; +function Hex(number: int64): string; /// Перевод десятичного числа в шестнадцатиричную систему счисления -function Hex(Число: BigInteger): string; +function Hex(number: BigInteger): string; /// Перевод из системы по основанию base [2..36] в десятичную -function Dec(СтроковоеПредставление: string; Основание: integer): int64; +function Dec(str: string; base: integer): int64; /// Перевод из системы по основанию base [2..36] в десятичную -function DecBig(СтроковоеПредставление: string; Основание: integer): BigInteger; +function DecBig(str: string; base: integer): BigInteger; /// Перевод BigInteger в систему счисления по основанию base (2..36) -function ToBase(Число: BigInteger; Основание: integer): string; +function ToBase(number: BigInteger; base: integer): string; /// Перевод десятичного числа в систему счисления по основанию base (2..36) -function ToBase(СтроковоеПредставление: string; Основание: integer): string; +function ToBase(str: string; base: integer): string; /// Возвращает кортеж из минимума и максимума последовательности -function MinMax(Последовательность: sequence of int64): (int64, int64); +function MinMax(seq: sequence of int64): (int64, int64); /// Возвращает кортеж из минимума и максимума последовательности -function MinMax(Последовательность: sequence of integer): (integer, integer); +function MinMax(seq: sequence of integer): (integer, integer); /// Возвращает кортеж из минимума и максимума последовательности -function MinMax(Последовательность: sequence of real): (real, real); +function MinMax(seq: sequence of real): (real, real); /// Возвращает кортеж из минимума и максимума последовательности -function MinMax(Последовательность: sequence of BigInteger): (BigInteger, BigInteger); +function MinMax(seq: sequence of BigInteger): (BigInteger, BigInteger); /// Возвращает НОД пары чисел function НОД(a, b: int64): int64; @@ -140,7 +150,7 @@ function TrueTable(f: function(a, b, c, d, e: boolean): boolean): procedure TrueTablePrint(a: array[,] of boolean; f: integer := 2; s: string := 'abcde'); /// Заменяет последнее вхождение подстроки в строку -procedure ReplaceLast(var Строка: string; ЧтоЗаменить, ЧемЗаменить: string); +procedure ReplaceLast(var s: string; source, target: string); /// Множественная замена символов в строке s /// Каждый символ source[i] заменяется во всей строке s символом target[i] @@ -170,249 +180,263 @@ School_InvalidBase = class(Exception) {$region Bin} -function Bin(Число: int64): string; +function Bin(number: int64): string; begin - Число := Abs(Число); + if number < 0 then number := -number; Result := ''; - while Число >= 2 do + while number >= 2 do begin - Result += Число mod 2; - Число := Число div 2 + Result += number mod 2; + number := number div 2 end; - Result += Число; + Result += number; Result := Result.Inverse end; -function Bin(Число: BigInteger): string; +function Bin(number: BigInteger): string; begin - Число := Abs(Число); + if number < 0 then number := -number; Result := ''; - while Число >= 2 do + while number >= 2 do begin - Result += byte(Число mod 2); - Число := Число div 2 + Result += byte(number mod 2); + number := number div 2 end; - Result += byte(Число); + Result += byte(number); Result := Result.Inverse end; +function BinFormat(number: BigInteger; bytes: integer; split: string): string; +begin + if number < 0 then number := -number; + var a := number = 0 ? |byte(0)| : number.ToByteArray; + var len := a.Length; + if (number > 0) and (a[^1] = 0) then Dec(len); + SetLength(a, Max(bytes, len)); + Result := a.Reverse.Select(t -> (Convert.ToString(t, 2)).PadLeft(8, '0')).JoinToString(split) +end; + +function BinFormat(number: int64; bytes: integer; split: string): string := + BinFormat(BigInteger(number), bytes, split); + {$endregion} {$region Oct} -function Oct(Число: int64): string; +function Oct(number: int64): string; begin - Число := Abs(Число); + if number < 0 then number := -number; Result := ''; - while Число >= 8 do + while number >= 8 do begin - Result += Число mod 8; - Число := Число div 8 + Result += number mod 8; + number := number div 8 end; - Result += Число; - Result := Result.Inverse + Result += number; + Result := Result.Inverse; end; -function Oct(Число: BigInteger): string; +function Oct(number: BigInteger): string; begin - Число := Abs(Число); + if number < 0 then number := -number; Result := ''; - while Число >= 8 do + while number >= 2 do begin - Result += byte(Число mod 8); - Число := Число div 8 + Result += byte(number mod 8); + number := number div 8 end; - Result += byte(Число); - Result := Result.Inverse + Result += byte(number); + Result := Result.Inverse; end; {$endregion} {$region Hex} -function Hex(Число: int64): string; + +function Hex(number: int64): string; begin - Число := Abs(Число); - var ШестнадцатиричныеЦифры := '0123456789ABCDEF'; + if number < 0 then number := -number; + var hex_nums := '0123456789ABCDEF'; Result := ''; - while Число >= 16 do + while number >= 16 do begin - Result += ШестнадцатиричныеЦифры[Число mod 16 + 1]; - Число := Число div 16 + Result += hex_nums[number mod 16 + 1]; + number := number div 16 end; - Result += ШестнадцатиричныеЦифры[Число + 1]; - Result := Result.Inverse + Result += hex_nums[number + 1]; + Result := Result.Inverse; end; -function Hex(Число: BigInteger): string; +function Hex(number: BigInteger): string; begin - Число := Abs(Число); - var ШестнадцатиричныеЦифры := '0123456789ABCDEF'; + if number < 0 then number := -number; + var hex_nums := '0123456789ABCDEF'; Result := ''; - while Число >= 16 do + while number >= 16 do begin - Result += ШестнадцатиричныеЦифры[byte(Число mod 16) + 1]; - Число := Число div 16 + Result += hex_nums[byte(number mod 16 + 1)]; + number := number div 16 end; - Result += ШестнадцатиричныеЦифры[byte(Число) + 1]; - Result := Result.Inverse + Result += hex_nums[byte(number + 1)]; + Result := Result.Inverse; end; {$endregion} const - ДопустимыеСимволы = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + valid_chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; {$region Dec} -function Dec(СтроковоеПредставление: string; Основание: integer): int64; +function Dec(str: string; base: integer): int64; begin - if not (Основание in 2..36) then + if not (base in 2..36) then raise new School_InvalidBase - ($'ToDecimal: Недопустимое основание {Основание}'); - СтроковоеПредставление := СтроковоеПредставление.ToUpper; - var НедопустимыеСимволы := - СтроковоеПредставление.Except(ДопустимыеСимволы[:Основание + 1]).JoinToString; - if НедопустимыеСимволы.Length > 0 then + ($'ToDecimal: Недопустимое основание {base}'); + str := str.ToUpper; + var invalid_chars := + str.Except(valid_chars[:base + 1]).JoinToString; + if invalid_chars.Length > 0 then raise new School_BadCharInString - ($'ToDecimal: Недопустимые символы "{НедопустимыеСимволы}"'); - var ВесРазряда := 1bi; - var Результат := 0bi; - foreach var Символ in СтроковоеПредставление.Reverse do + ($'ToDecimal: Недопустимые символы "{invalid_chars}"'); + var rank_weight := 1bi; + var res := 0bi; + foreach var char in str.Reverse do begin - var ЗначениеРазряда := Pos(Символ, ДопустимыеСимволы) - 1; - Результат += ВесРазряда * ЗначениеРазряда; - ВесРазряда *= Основание + var rank_value := Pos(char, valid_chars) - 1; + res += rank_weight * rank_value; + rank_weight *= base end; - Result := int64(Результат) + Result := int64(res) end; -function DecBig(СтроковоеПредставление: string; Основание: integer): BigInteger; +function DecBig(str: string; base: integer): BigInteger; begin - if not (Основание in 2..36) then + if not (base in 2..36) then raise new School_InvalidBase - ($'ToDecimal: Недопустимое основание {Основание}'); - СтроковоеПредставление := СтроковоеПредставление.ToUpper; - var НедопустимыеСимволы := - СтроковоеПредставление.Except(ДопустимыеСимволы[:Основание + 1]).JoinToString; - if НедопустимыеСимволы.Length > 0 then + ($'ToDecimal: Недопустимое основание {base}'); + str := str.ToUpper; + var invalid_chars := + str.Except(valid_chars[:base + 1]).JoinToString; + if invalid_chars.Length > 0 then raise new School_BadCharInString - ($'ToDecimal: Недопустимые символы "{НедопустимыеСимволы}"'); - var ВесРазряда := 1bi; + ($'ToDecimal: Недопустимые символы "{invalid_chars}"'); + var rank_weight := 1bi; Result := 0bi; - foreach var Символ in СтроковоеПредставление.Reverse do + foreach var char in str.Reverse do begin - var ЗначениеРазряда := Pos(Символ, ДопустимыеСимволы) - 1; - Result += ВесРазряда * ЗначениеРазряда; - ВесРазряда *= Основание + var rank_value := Pos(char, valid_chars) - 1; + Result += rank_weight * rank_value; + rank_weight *= base end end; + {$endregion} {$region ToBase} /// Перевод BigInteger в систему счисления по основанию base (2..36) -function ToBase(Число: BigInteger; Основание: integer): string; +function ToBase(number: BigInteger; base: integer): string; begin - if not (Основание in 2..36) then + if not (base in 2..36) then raise new School_InvalidBase - ($'ToDecimal: Недопустимое основание {Основание}'); - var СтроковоеПредставление := new System.Text.StringBuilder(''); - while Число > 0 do + ($'ToDecimal: Недопустимое основание {base}'); + var sb := new System.Text.StringBuilder(''); + while number > 0 do begin - СтроковоеПредставление.Insert(0, ДопустимыеСимволы[integer(Число mod Основание) + 1]); - Число := Число div Основание + sb.Insert(0, valid_chars[integer(number mod base) + 1]); + number := number div base end; - Result := if СтроковоеПредставление.Length = 0 then '0' - else СтроковоеПредставление.ToString + Result := if sb.Length = 0 then '0' + else sb.ToString end; /// Перевод BigInteger в систему счисления по основанию base (2..36) -function ToBase(Self: BigInteger; Основание: integer): string; extensionmethod := -ToBase(Self, Основание); +function ToBase(Self: BigInteger; base: integer): string; extensionmethod := +ToBase(Self, base); /// Перевод десятичного числа в систему счисления по основанию base (2..36) -function ToBase(СтроковоеПредставление: string; Основание: integer): string; +function ToBase(str: string; base: integer): string; begin - if not (Основание in 2..36) then + if not (base in 2..36) then raise new School_InvalidBase - ($'ToDecimal: Недопустимое основание {Основание}'); - var Число: BigInteger; - if BigInteger.TryParse(СтроковоеПредставление, Число) then - Result := ToBase(Число, Основание) + ($'ToDecimal: Недопустимое основание {base}'); + var number: BigInteger; + if BigInteger.TryParse(str, number) then + Result := ToBase(number, base) end; /// Перевод десятичного числа в систему счисления по основанию base (2..36) -function ToBase(Self: string; Основание: integer): string; extensionmethod := -ToBase(Self, Основание); +function ToBase(Self: string; base: integer): string; extensionmethod := +ToBase(Self, base); {$endregion} {$region MinMax} /// Возвращает кортеж из минимума и максимума последовательности -function MinMax(Последовательность: sequence of int64): (int64, int64); +function MinMax(seq: sequence of int64): (int64, int64); begin var min := int64.MaxValue; var max := int64.MinValue; - foreach var Элемент in Последовательность do + foreach var elem in seq do begin - if Элемент < min then - min := Элемент; - if Элемент > max then - max := Элемент + if elem < min then + min := elem; + if elem > max then + max := elem end; Result := (min, max) end; /// Возвращает кортеж из минимума и максимума последовательности -function MinMax(Последовательность: sequence of integer): (integer, integer); +function MinMax(seq: sequence of integer): (integer, integer); begin var min := integer.MaxValue; var max := integer.MinValue; - foreach var Элемент in Последовательность do + foreach var elem in seq do begin - if Элемент < min then - min := Элемент; - if Элемент > max then - max := Элемент + if elem < min then + min := elem; + if elem > max then + max := elem end; Result := (min, max) end; /// Возвращает кортеж из минимума и максимума последовательности s -function MinMax(Последовательность: sequence of real): (real, real); +function MinMax(seq: sequence of real): (real, real); begin var min := real.MaxValue; - var max := real.MinValue; - foreach var Элемент in Последовательность do + var max := -real.MaxValue; + foreach var elem in seq do begin - if Элемент < min then - min := Элемент; - if Элемент > max then - max := Элемент + if elem < min then + min := elem; + if elem > max then + max := elem end; Result := (min, max) end; /// Возвращает кортеж из минимума и максимума последовательности s -function MinMax(Последовательность: sequence of BigInteger): (BigInteger, BigInteger); +function MinMax(seq: sequence of BigInteger): (BigInteger, BigInteger); begin var min, max: BigInteger; - var ЭтоПервыйЭлемент := True; - foreach var Элемент in Последовательность do - if ЭтоПервыйЭлемент then + var is_first := True; + foreach var elem in seq do + if is_first then begin - min := Элемент; - max := Элемент; - ЭтоПервыйЭлемент := False + (min, max) := (elem, elem); + is_first := False end else begin - if Элемент < min then - min := Элемент; - if Элемент > max then - max := Элемент - end; + if elem < min then + min := elem; + if elem > max then + max := elem + end; Result := (min, max) end; @@ -574,10 +598,10 @@ function IsPrime(Self: integer): boolean; extensionmethod; else begin Result := True; - foreach var Простое in LPrimes do - if Sqr(Простое) > Self then + foreach var prime in LPrimes do + if Sqr(prime) > Self then break - else if Self mod Простое = 0 then + else if Self mod prime = 0 then begin Result := False; break @@ -931,13 +955,13 @@ procedure TrueTablePrint(a: array[,] of boolean; f: integer; s: string); {$region String} /// Заменяет последнее вхождение подстроки в строку -procedure ReplaceLast(var Строка: string; ЧтоЗаменить, ЧемЗаменить: string); +procedure ReplaceLast(var s: string; source, target: string); begin - var Позиция := LastPos(ЧтоЗаменить, Строка); - if Позиция > 0 then + var position := LastPos(source, s); + if position > 0 then begin - Delete(Строка, Позиция, ЧтоЗаменить.Length); - Insert(ЧемЗаменить, Строка, Позиция) + Delete(s, position, source.Length); + Insert(target, s, position) end end; diff --git a/TestSuite/SingleReal.pas b/TestSuite/SingleReal.pas new file mode 100644 index 000000000..da58a651f --- /dev/null +++ b/TestSuite/SingleReal.pas @@ -0,0 +1,3 @@ +begin + Assert(Arr(1.0,2.0).Sum(x -> x*x).GetType = typeof(real)) +end. \ No newline at end of file diff --git a/TestSuite/check_sequence.pas b/TestSuite/check_sequence.pas new file mode 100644 index 000000000..fa0032b5f --- /dev/null +++ b/TestSuite/check_sequence.pas @@ -0,0 +1,11 @@ +procedure CheckOutputSeq(a: sequence of integer); +begin +end; + +procedure CheckOutputSeq(a: sequence of object); +begin +end; + +begin + CheckOutputSeq(Arr(1,2,3)); +end. \ No newline at end of file diff --git a/TreeConverter/TreeRealization/type_table.cs b/TreeConverter/TreeRealization/type_table.cs index a69c7fe3f..a67dbbdae 100644 --- a/TreeConverter/TreeRealization/type_table.cs +++ b/TreeConverter/TreeRealization/type_table.cs @@ -575,8 +575,8 @@ public static bool is_derived(type_node base_class, type_node derived_class, boo // Но без этой строчки не работает преобразование sequence of Student к sequence of Person и sequence of object // SSM 19/07/23 - снова раскомментировал - теперь не работало // CheckOutputSeq(a); в Tasks где var a: array of char - if (tnode.IsInterface) - ImplementingInterfaces.Add(tnode); + //if (tnode.IsInterface) // SSM закомментировал опять 17.09.23 - single - неточные вычисления! + // ImplementingInterfaces.Add(tnode); foreach (var interf in ImplementingInterfaces) { var ctn = interf as compiled_type_node; @@ -809,6 +809,18 @@ public static type_compare compare_types_in_specific_order(type_node left, type_ public static type_compare compare_types(type_node left, type_node right) { type_compare ret = get_table_type_compare(left, right); + // SSM 18.09.23 исправление #2872 (частное!!! только первый параметр!) + var ctnl = left as compiled_type_node; + var ctnr = right as compiled_type_node; + if (ctnl != null && ctnr != null && ctnl.original_generic == ctnr.original_generic + && ctnl.compiled_type.IsInterface && ctnl.generic_params != null && ctnl.generic_params.Count == 1) + { + var interf_compiled_type = (ctnr.original_generic as compiled_type_node).compiled_type; + if ((interf_compiled_type.GetGenericArguments()[0].GenericParameterAttributes & System.Reflection.GenericParameterAttributes.Covariant) != 0) + return compare_types(ctnl.generic_params[0], ctnr.generic_params[0]); + } + // IEnumerable д.б. < IEnumerable + // Проверить, что оба - IEnumerable. И если object < integer, то вернуть type_compare.less_type if (ret != type_compare.non_comparable_type) { return ret; diff --git a/VisualPascalABCNETLinux/IB/Debugger/Debugger.cs b/VisualPascalABCNETLinux/IB/Debugger/Debugger.cs index 4122f718c..b4011b82e 100644 --- a/VisualPascalABCNETLinux/IB/Debugger/Debugger.cs +++ b/VisualPascalABCNETLinux/IB/Debugger/Debugger.cs @@ -1097,7 +1097,6 @@ private void JumpToCurrentLine(bool fromBreakpoint = false) bool in_comm = false; bool beg = false; bool in_str = false; - Console.WriteLine("2 jump to " + stackFrame.SourceLocation.FileName + ":" + stackFrame.SourceLocation.Line); for (int i = 0; i < lseg.Words.Count; i++) { diff --git a/VisualPascalABCNETLinux/IB/Debugger/ExpressionEvaluation.cs b/VisualPascalABCNETLinux/IB/Debugger/ExpressionEvaluation.cs index f84d833e3..49fe5f432 100644 --- a/VisualPascalABCNETLinux/IB/Debugger/ExpressionEvaluation.cs +++ b/VisualPascalABCNETLinux/IB/Debugger/ExpressionEvaluation.cs @@ -6298,37 +6298,42 @@ public override void visit(indexer _indexer) names.Add("]"); if (rv.monoValue != null) { - if (rv.obj_val is MemberValue && (rv.obj_val as MemberValue).MemberInfo is PropertyInfo) + + RetValue res = new RetValue(); + Type type = AssemblyHelper.GetType(rv.monoValue.TypeName); + if (type != null && type.GetField("NullBasedArray") != null) { - PropertyInfo pi = (rv.obj_val as MemberValue).MemberInfo as PropertyInfo; - Type t = AssemblyHelper.GetType(last_obj.Type.FullName); - System.Reflection.PropertyInfo rpi = t.GetProperty(pi.Name, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Instance); - /*System.Reflection.MemberInfo[] props = t.GetMembers(System.Reflection.BindingFlags.NonPublic|System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Static|System.Reflection.BindingFlags.CreateInstance); - System.Reflection.PropertyInfo rpi = null; - foreach (System.Reflection.MemberInfo p in props) - if (p is System.Reflection.PropertyInfo && p.Name == pi.Name) + int low_bound = 0; + System.Reflection.FieldInfo fi = type.GetField("LowerIndex"); + low_bound = Convert.ToInt32(fi.GetRawConstantValue()); + int[] tmp_indices = new int[1]; + int j = 0; + try { - rpi = p as System.Reflection.PropertyInfo; - break; - }*/ - RetValue res = new RetValue(); - res.obj_val = ((rv.obj_val as MemberValue).MemberInfo as PropertyInfo).GetValue(last_obj, - get_val_arr(indices, false, rpi.GetGetMethod(true))); - eval_stack.Push(res); - return; - } - if (true) - { - - RetValue res = new RetValue(); - Type type = AssemblyHelper.GetType(rv.monoValue.TypeName); - if (type != null && type.GetField("NullBasedArray") != null) + object obj = indices[j++]; + int v = 0; + if (obj is Value && DebugUtils.IsEnum(obj as Value, out v)) + tmp_indices[0] = v - low_bound; + else + tmp_indices[0] = Convert.ToInt32(obj) - low_bound; + } + catch (System.FormatException) { - int low_bound = 0; - System.Reflection.FieldInfo fi = type.GetField("LowerIndex"); - low_bound = Convert.ToInt32(fi.GetRawConstantValue()); - int[] tmp_indices = new int[1]; - int j = 0; + throw new WrongTypeInIndexer(); + } + catch (System.InvalidCastException) + { + throw new WrongTypeInIndexer(); + } + //res.obj_val = cur_mi.Invoke(rv.obj_val,indices.ToArray()) as NamedValue; + var nv = rv.monoValue.GetChild("NullBasedArray"); + res.monoValue = nv.GetRangeOfChildren(tmp_indices[0], 1)[0]; + check_for_out_of_range(res.obj_val); + nv = res.monoValue.GetChild("NullBasedArray"); + while (nv != null && j < indices.Count) + { + System.Reflection.FieldInfo tmp_fi = AssemblyHelper.GetType(res.monoValue.TypeName).GetField("LowerIndex"); + low_bound = Convert.ToInt32(tmp_fi.GetRawConstantValue()); try { object obj = indices[j++]; @@ -6346,162 +6351,36 @@ public override void visit(indexer _indexer) { throw new WrongTypeInIndexer(); } - //res.obj_val = cur_mi.Invoke(rv.obj_val,indices.ToArray()) as NamedValue; - var nv = rv.monoValue.GetChild("NullBasedArray"); res.monoValue = nv.GetRangeOfChildren(tmp_indices[0], 1)[0]; check_for_out_of_range(res.obj_val); nv = res.monoValue.GetChild("NullBasedArray"); - while (nv != null && j < indices.Count) - { - System.Reflection.FieldInfo tmp_fi = AssemblyHelper.GetType(res.monoValue.TypeName).GetField("LowerIndex"); - low_bound = Convert.ToInt32(tmp_fi.GetRawConstantValue()); - try - { - object obj = indices[j++]; - int v = 0; - if (obj is Value && DebugUtils.IsEnum(obj as Value, out v)) - tmp_indices[0] = v - low_bound; - else - tmp_indices[0] = Convert.ToInt32(obj) - low_bound; - } - catch (System.FormatException) - { - throw new WrongTypeInIndexer(); - } - catch (System.InvalidCastException) - { - throw new WrongTypeInIndexer(); - } - res.monoValue = nv.GetRangeOfChildren(tmp_indices[0], 1)[0]; - check_for_out_of_range(res.obj_val); - nv = res.monoValue.GetChild("NullBasedArray"); - } - if (j < indices.Count) - throw new WrongIndexersNumber(); - eval_stack.Push(res); } - else - res.monoValue = rv.monoValue.GetRangeOfChildren(conv_to_int_arr(indices)[0], 1)[0]; - //check_for_out_of_range(res.monoValue); + if (j < indices.Count) + throw new WrongIndexersNumber(); eval_stack.Push(res); - } else { - IList mis = rv.obj_val.Type.GetMember("get_val", BindingFlags.All); - if (mis.Count > 0) + var tm = rv.monoValue.Type as Mono.Debugger.Soft.TypeMirror; + var mi = tm.GetMethod("get_Item"); + if (mi != null) { - MethodInfo cur_mi = null; - int low_bound = 0; - foreach (MemberInfo mi in mis) + List ind_list = new List(); + foreach (var ind in indices) { - if (mi is MethodInfo) - { - cur_mi = mi as MethodInfo; - //FieldInfo fi = rv.obj_val.Type.GetMember("LowerIndex",BindingFlags.All)[0] as FieldInfo; - System.Reflection.FieldInfo fi = AssemblyHelper.GetType(rv.obj_val.Type.FullName).GetField("LowerIndex"); - low_bound = Convert.ToInt32(fi.GetRawConstantValue()); - } + ind_list.Add(DebugUtils.MakeMonoValue(ind)); } - RetValue res = new RetValue(); - uint[] tmp_indices = new uint[1]; - int j = 0; - try - { - object obj = indices[j++]; - int v = 0; - if (obj is Value && DebugUtils.IsEnum(obj as Value, out v)) - tmp_indices[0] = (uint)(v - low_bound); - else - tmp_indices[0] = (uint)(Convert.ToInt32(obj) - low_bound); - } - catch (System.FormatException) - { - throw new WrongTypeInIndexer(); - } - catch (System.InvalidCastException) - { - throw new WrongTypeInIndexer(); - } - //res.obj_val = cur_mi.Invoke(rv.obj_val,indices.ToArray()) as NamedValue; - Value nv = rv.obj_val.GetMember("NullBasedArray"); - res.obj_val = nv.GetArrayElement(tmp_indices); - check_for_out_of_range(res.obj_val); - nv = res.obj_val.GetMember("NullBasedArray"); - while (nv != null && j < indices.Count) - { - System.Reflection.FieldInfo tmp_fi = AssemblyHelper.GetType(res.obj_val.Type.FullName).GetField("LowerIndex"); - low_bound = Convert.ToInt32(tmp_fi.GetRawConstantValue()); - try - { - object obj = indices[j++]; - int v = 0; - if (obj is Value && DebugUtils.IsEnum(obj as Value, out v)) - tmp_indices[0] = (uint)(v - low_bound); - else - tmp_indices[0] = (uint)(Convert.ToInt32(obj) - low_bound); - } - catch (System.FormatException) - { - throw new WrongTypeInIndexer(); - } - catch (System.InvalidCastException) - { - throw new WrongTypeInIndexer(); - } - res.obj_val = nv.GetArrayElement(tmp_indices); - check_for_out_of_range(res.obj_val); - nv = res.obj_val.GetMember("NullBasedArray"); - - } - if (j < indices.Count) - throw new WrongIndexersNumber(); - eval_stack.Push(res); + res.monoValue = InvokeMethod(tm, mi, rv.monoValue, ind_list.ToArray()); } else - { - string name = get_type_name(rv.obj_val.Type); - Type t = AssemblyHelper.GetType(name); - if (t == null && declaringType != null) - t = AssemblyHelper.GetType(declaringType.FullName + "+" + name); - DebugType[] gen_args = rv.obj_val.Type.GetGenericArguments(); - if (gen_args.Length > 0) - { - List gens = new List(); - for (int i = 0; i < gen_args.Length; i++) - gens.Add(AssemblyHelper.GetType(get_type_name(gen_args[i]))); - t = t.MakeGenericType(gens.ToArray()); - } - System.Reflection.MemberInfo[] def_members = t.GetDefaultMembers(); - System.Reflection.PropertyInfo _default_property = null; - if (def_members != null && def_members.Length > 0) - { - foreach (System.Reflection.MemberInfo mi in def_members) - { - System.Reflection.PropertyInfo pi = mi as System.Reflection.PropertyInfo; - if (pi != null) - { - _default_property = pi; - break; - } - } - } - if (_default_property != null) - { - if (_default_property.GetGetMethod().GetParameters().Length != indices.Count) - throw new WrongIndexersNumber(); - MethodInfo mi2 = rv.obj_val.Type.GetMember(_default_property.GetGetMethod().Name, Debugger.BindingFlags.All)[0] as MethodInfo; - RetValue res = new RetValue(); - res.obj_val = mi2.Invoke(rv.obj_val, get_val_arr(indices, _default_property.DeclaringType == typeof(string), _default_property.GetGetMethod())); - check_for_out_of_range(res.obj_val); - eval_stack.Push(res); - } - else - throw new NoIndexerProperty(); - - } + res.monoValue = rv.monoValue.GetRangeOfChildren(conv_to_int_arr(indices)[0], 1)[0]; } + + //check_for_out_of_range(res.monoValue); + eval_stack.Push(res); + + } } diff --git a/VisualPascalABCNETLinux/MonoDebugging/Client/ObjectValue.cs b/VisualPascalABCNETLinux/MonoDebugging/Client/ObjectValue.cs index f9efbb7f2..dd9c288bd 100644 --- a/VisualPascalABCNETLinux/MonoDebugging/Client/ObjectValue.cs +++ b/VisualPascalABCNETLinux/MonoDebugging/Client/ObjectValue.cs @@ -67,11 +67,29 @@ public class ObjectValue [NonSerialized] StackFrame parentFrame; - - static ObjectValue Create (IObjectValueSource source, ObjectPath path, string typeName) + + static ObjectValue Create(IObjectValueSource source, ObjectPath path, string typeName) { - var val = new ObjectValue (); + var val = new ObjectValue(); val.typeName = typeName; + int ptr_ind = val.typeName.IndexOf('*'); + string ptr = ""; + if (ptr_ind != -1) + ptr = val.typeName.Substring(ptr_ind).Replace('*', '^'); + switch (val.typeName.Replace("*","")) + { + case "int": val.typeName = "integer"; break; + case "double": val.typeName = "real"; break; + case "float": val.typeName = "single"; break; + case "uint": val.typeName = "longword"; break; + case "long": val.typeName = "int64"; break; + case "ulong": val.typeName = "uint64"; break; + case "short": val.typeName = "smallint"; break; + case "ushort": val.typeName = "word"; break; + case "sbyte": val.typeName = "shortint"; break; + case "bool": val.typeName = "boolean"; break; + } + val.typeName = ptr+val.typeName.Replace("*", ""); val.source = source; val.path = path; return val; diff --git a/VisualPascalABCNETLinux/MonoDebugging/Debugger/Connection.cs b/VisualPascalABCNETLinux/MonoDebugging/Debugger/Connection.cs index 3033f34ce..e537445b6 100644 --- a/VisualPascalABCNETLinux/MonoDebugging/Debugger/Connection.cs +++ b/VisualPascalABCNETLinux/MonoDebugging/Debugger/Connection.cs @@ -1875,36 +1875,40 @@ CattrInfo[] ReadCattrs (PacketReader r) { return res; } - static ElementType TypeCodeToElementType (TypeCode c, Type t) { - switch (c) { - case TypeCode.Boolean: - return ElementType.Boolean; - case TypeCode.Char: - return ElementType.Char; - case TypeCode.SByte: - return ElementType.I1; - case TypeCode.Byte: - return ElementType.U1; - case TypeCode.Int16: - return ElementType.I2; - case TypeCode.UInt16: - return ElementType.U2; - case TypeCode.Int32: - return ElementType.I4; - case TypeCode.UInt32: - return ElementType.U4; - case TypeCode.Int64: - return ElementType.I8; - case TypeCode.UInt64: - return ElementType.U8; - case TypeCode.Single: - return ElementType.R4; - case TypeCode.Double: - return ElementType.R8; - case TypeCode.Object: - return TypeCodeToElementType(Type.GetTypeCode (t.GetElementType()), t.GetElementType()); - default: - throw new NotImplementedException (); + static ElementType TypeCodeToElementType(TypeCode c, Type t) + { + switch (c) + { + case TypeCode.Boolean: + return ElementType.Boolean; + case TypeCode.Char: + return ElementType.Char; + case TypeCode.SByte: + return ElementType.I1; + case TypeCode.Byte: + return ElementType.U1; + case TypeCode.Int16: + return ElementType.I2; + case TypeCode.UInt16: + return ElementType.U2; + case TypeCode.Int32: + return ElementType.I4; + case TypeCode.UInt32: + return ElementType.U4; + case TypeCode.Int64: + return ElementType.I8; + case TypeCode.UInt64: + return ElementType.U8; + case TypeCode.Single: + return ElementType.R4; + case TypeCode.Double: + return ElementType.R8; + case TypeCode.String: + return ElementType.String; + case TypeCode.Object: + return TypeCodeToElementType(Type.GetTypeCode(t.GetElementType()), t.GetElementType()); + default: + throw new NotImplementedException(); } } diff --git a/bin/Lib/School.pas b/bin/Lib/School.pas index 50c6d18b4..590143161 100644 --- a/bin/Lib/School.pas +++ b/bin/Lib/School.pas @@ -1,49 +1,59 @@ -/// Учебный модуль, реализующий базовые алгоритмы информатики. +/// Учебный модуль, реализующий базовые алгоритмы информатики (09.10.2023) unit School; interface /// Перевод десятичного числа в двоичную систему счисления -function Bin(Число: int64): string; +function Bin(number: int64): string; /// Перевод десятичного числа в двоичную систему счисления -function Bin(Число: BigInteger): string; +function Bin(number: BigInteger): string; + +/// Перевод десятичного числа в двоичную систему счисления с форматированием. +/// bytes - требуемая длина в байтах, автоматически увеличивается, если недостаточна +/// split - разделитель байтов, можено задать пустое значение '' +function BinFormat(number: BigInteger; bytes: integer := 0; split: string := ' '): string; + +/// Перевод десятичного числа в двоичную систему счисления с форматированием. +/// bytes - требуемая длина в байтах, автоматически увеличивается, если недостаточна +/// split - разделитель байтов, можено задать пустое значение '' +function BinFormat(number: int64; bytes: integer := 0; split: string := ' '): string; /// Перевод десятичного числа в восьмеричную систему счисления -function Oct(Число: int64): string; +function Oct(number: int64): string; /// Перевод десятичного числа в восьмеричную систему счисления -function Oct(Число: BigInteger): string; +function Oct(number: BigInteger): string; /// Перевод десятичного числа в шестнадцатиричную систему счисления -function Hex(Число: int64): string; +function Hex(number: int64): string; /// Перевод десятичного числа в шестнадцатиричную систему счисления -function Hex(Число: BigInteger): string; +function Hex(number: BigInteger): string; /// Перевод из системы по основанию base [2..36] в десятичную -function Dec(СтроковоеПредставление: string; Основание: integer): int64; +function Dec(str: string; base: integer): int64; /// Перевод из системы по основанию base [2..36] в десятичную -function DecBig(СтроковоеПредставление: string; Основание: integer): BigInteger; +function DecBig(str: string; base: integer): BigInteger; /// Перевод BigInteger в систему счисления по основанию base (2..36) -function ToBase(Число: BigInteger; Основание: integer): string; +function ToBase(number: BigInteger; base: integer): string; /// Перевод десятичного числа в систему счисления по основанию base (2..36) -function ToBase(СтроковоеПредставление: string; Основание: integer): string; +function ToBase(str: string; base: integer): string; /// Возвращает кортеж из минимума и максимума последовательности -function MinMax(Последовательность: sequence of int64): (int64, int64); +function MinMax(seq: sequence of int64): (int64, int64); /// Возвращает кортеж из минимума и максимума последовательности -function MinMax(Последовательность: sequence of integer): (integer, integer); +function MinMax(seq: sequence of integer): (integer, integer); /// Возвращает кортеж из минимума и максимума последовательности -function MinMax(Последовательность: sequence of real): (real, real); +function MinMax(seq: sequence of real): (real, real); /// Возвращает кортеж из минимума и максимума последовательности -function MinMax(Последовательность: sequence of BigInteger): (BigInteger, BigInteger); +function MinMax(seq: sequence of BigInteger): (BigInteger, BigInteger); /// Возвращает НОД пары чисел function НОД(a, b: int64): int64; @@ -140,7 +150,7 @@ function TrueTable(f: function(a, b, c, d, e: boolean): boolean): procedure TrueTablePrint(a: array[,] of boolean; f: integer := 2; s: string := 'abcde'); /// Заменяет последнее вхождение подстроки в строку -procedure ReplaceLast(var Строка: string; ЧтоЗаменить, ЧемЗаменить: string); +procedure ReplaceLast(var s: string; source, target: string); /// Множественная замена символов в строке s /// Каждый символ source[i] заменяется во всей строке s символом target[i] @@ -170,249 +180,263 @@ School_InvalidBase = class(Exception) {$region Bin} -function Bin(Число: int64): string; +function Bin(number: int64): string; begin - Число := Abs(Число); + if number < 0 then number := -number; Result := ''; - while Число >= 2 do + while number >= 2 do begin - Result += Число mod 2; - Число := Число div 2 + Result += number mod 2; + number := number div 2 end; - Result += Число; + Result += number; Result := Result.Inverse end; -function Bin(Число: BigInteger): string; +function Bin(number: BigInteger): string; begin - Число := Abs(Число); + if number < 0 then number := -number; Result := ''; - while Число >= 2 do + while number >= 2 do begin - Result += byte(Число mod 2); - Число := Число div 2 + Result += byte(number mod 2); + number := number div 2 end; - Result += byte(Число); + Result += byte(number); Result := Result.Inverse end; +function BinFormat(number: BigInteger; bytes: integer; split: string): string; +begin + if number < 0 then number := -number; + var a := number = 0 ? |byte(0)| : number.ToByteArray; + var len := a.Length; + if (number > 0) and (a[^1] = 0) then Dec(len); + SetLength(a, Max(bytes, len)); + Result := a.Reverse.Select(t -> (Convert.ToString(t, 2)).PadLeft(8, '0')).JoinToString(split) +end; + +function BinFormat(number: int64; bytes: integer; split: string): string := + BinFormat(BigInteger(number), bytes, split); + {$endregion} {$region Oct} -function Oct(Число: int64): string; +function Oct(number: int64): string; begin - Число := Abs(Число); + if number < 0 then number := -number; Result := ''; - while Число >= 8 do + while number >= 8 do begin - Result += Число mod 8; - Число := Число div 8 + Result += number mod 8; + number := number div 8 end; - Result += Число; - Result := Result.Inverse + Result += number; + Result := Result.Inverse; end; -function Oct(Число: BigInteger): string; +function Oct(number: BigInteger): string; begin - Число := Abs(Число); + if number < 0 then number := -number; Result := ''; - while Число >= 8 do + while number >= 2 do begin - Result += byte(Число mod 8); - Число := Число div 8 + Result += byte(number mod 8); + number := number div 8 end; - Result += byte(Число); - Result := Result.Inverse + Result += byte(number); + Result := Result.Inverse; end; {$endregion} {$region Hex} -function Hex(Число: int64): string; + +function Hex(number: int64): string; begin - Число := Abs(Число); - var ШестнадцатиричныеЦифры := '0123456789ABCDEF'; + if number < 0 then number := -number; + var hex_nums := '0123456789ABCDEF'; Result := ''; - while Число >= 16 do + while number >= 16 do begin - Result += ШестнадцатиричныеЦифры[Число mod 16 + 1]; - Число := Число div 16 + Result += hex_nums[number mod 16 + 1]; + number := number div 16 end; - Result += ШестнадцатиричныеЦифры[Число + 1]; - Result := Result.Inverse + Result += hex_nums[number + 1]; + Result := Result.Inverse; end; -function Hex(Число: BigInteger): string; +function Hex(number: BigInteger): string; begin - Число := Abs(Число); - var ШестнадцатиричныеЦифры := '0123456789ABCDEF'; + if number < 0 then number := -number; + var hex_nums := '0123456789ABCDEF'; Result := ''; - while Число >= 16 do + while number >= 16 do begin - Result += ШестнадцатиричныеЦифры[byte(Число mod 16) + 1]; - Число := Число div 16 + Result += hex_nums[byte(number mod 16 + 1)]; + number := number div 16 end; - Result += ШестнадцатиричныеЦифры[byte(Число) + 1]; - Result := Result.Inverse + Result += hex_nums[byte(number + 1)]; + Result := Result.Inverse; end; {$endregion} const - ДопустимыеСимволы = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + valid_chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; {$region Dec} -function Dec(СтроковоеПредставление: string; Основание: integer): int64; +function Dec(str: string; base: integer): int64; begin - if not (Основание in 2..36) then + if not (base in 2..36) then raise new School_InvalidBase - ($'ToDecimal: Недопустимое основание {Основание}'); - СтроковоеПредставление := СтроковоеПредставление.ToUpper; - var НедопустимыеСимволы := - СтроковоеПредставление.Except(ДопустимыеСимволы[:Основание + 1]).JoinToString; - if НедопустимыеСимволы.Length > 0 then + ($'ToDecimal: Недопустимое основание {base}'); + str := str.ToUpper; + var invalid_chars := + str.Except(valid_chars[:base + 1]).JoinToString; + if invalid_chars.Length > 0 then raise new School_BadCharInString - ($'ToDecimal: Недопустимые символы "{НедопустимыеСимволы}"'); - var ВесРазряда := 1bi; - var Результат := 0bi; - foreach var Символ in СтроковоеПредставление.Reverse do + ($'ToDecimal: Недопустимые символы "{invalid_chars}"'); + var rank_weight := 1bi; + var res := 0bi; + foreach var char in str.Reverse do begin - var ЗначениеРазряда := Pos(Символ, ДопустимыеСимволы) - 1; - Результат += ВесРазряда * ЗначениеРазряда; - ВесРазряда *= Основание + var rank_value := Pos(char, valid_chars) - 1; + res += rank_weight * rank_value; + rank_weight *= base end; - Result := int64(Результат) + Result := int64(res) end; -function DecBig(СтроковоеПредставление: string; Основание: integer): BigInteger; +function DecBig(str: string; base: integer): BigInteger; begin - if not (Основание in 2..36) then + if not (base in 2..36) then raise new School_InvalidBase - ($'ToDecimal: Недопустимое основание {Основание}'); - СтроковоеПредставление := СтроковоеПредставление.ToUpper; - var НедопустимыеСимволы := - СтроковоеПредставление.Except(ДопустимыеСимволы[:Основание + 1]).JoinToString; - if НедопустимыеСимволы.Length > 0 then + ($'ToDecimal: Недопустимое основание {base}'); + str := str.ToUpper; + var invalid_chars := + str.Except(valid_chars[:base + 1]).JoinToString; + if invalid_chars.Length > 0 then raise new School_BadCharInString - ($'ToDecimal: Недопустимые символы "{НедопустимыеСимволы}"'); - var ВесРазряда := 1bi; + ($'ToDecimal: Недопустимые символы "{invalid_chars}"'); + var rank_weight := 1bi; Result := 0bi; - foreach var Символ in СтроковоеПредставление.Reverse do + foreach var char in str.Reverse do begin - var ЗначениеРазряда := Pos(Символ, ДопустимыеСимволы) - 1; - Result += ВесРазряда * ЗначениеРазряда; - ВесРазряда *= Основание + var rank_value := Pos(char, valid_chars) - 1; + Result += rank_weight * rank_value; + rank_weight *= base end end; + {$endregion} {$region ToBase} /// Перевод BigInteger в систему счисления по основанию base (2..36) -function ToBase(Число: BigInteger; Основание: integer): string; +function ToBase(number: BigInteger; base: integer): string; begin - if not (Основание in 2..36) then + if not (base in 2..36) then raise new School_InvalidBase - ($'ToDecimal: Недопустимое основание {Основание}'); - var СтроковоеПредставление := new System.Text.StringBuilder(''); - while Число > 0 do + ($'ToDecimal: Недопустимое основание {base}'); + var sb := new System.Text.StringBuilder(''); + while number > 0 do begin - СтроковоеПредставление.Insert(0, ДопустимыеСимволы[integer(Число mod Основание) + 1]); - Число := Число div Основание + sb.Insert(0, valid_chars[integer(number mod base) + 1]); + number := number div base end; - Result := if СтроковоеПредставление.Length = 0 then '0' - else СтроковоеПредставление.ToString + Result := if sb.Length = 0 then '0' + else sb.ToString end; /// Перевод BigInteger в систему счисления по основанию base (2..36) -function ToBase(Self: BigInteger; Основание: integer): string; extensionmethod := -ToBase(Self, Основание); +function ToBase(Self: BigInteger; base: integer): string; extensionmethod := +ToBase(Self, base); /// Перевод десятичного числа в систему счисления по основанию base (2..36) -function ToBase(СтроковоеПредставление: string; Основание: integer): string; +function ToBase(str: string; base: integer): string; begin - if not (Основание in 2..36) then + if not (base in 2..36) then raise new School_InvalidBase - ($'ToDecimal: Недопустимое основание {Основание}'); - var Число: BigInteger; - if BigInteger.TryParse(СтроковоеПредставление, Число) then - Result := ToBase(Число, Основание) + ($'ToDecimal: Недопустимое основание {base}'); + var number: BigInteger; + if BigInteger.TryParse(str, number) then + Result := ToBase(number, base) end; /// Перевод десятичного числа в систему счисления по основанию base (2..36) -function ToBase(Self: string; Основание: integer): string; extensionmethod := -ToBase(Self, Основание); +function ToBase(Self: string; base: integer): string; extensionmethod := +ToBase(Self, base); {$endregion} {$region MinMax} /// Возвращает кортеж из минимума и максимума последовательности -function MinMax(Последовательность: sequence of int64): (int64, int64); +function MinMax(seq: sequence of int64): (int64, int64); begin var min := int64.MaxValue; var max := int64.MinValue; - foreach var Элемент in Последовательность do + foreach var elem in seq do begin - if Элемент < min then - min := Элемент; - if Элемент > max then - max := Элемент + if elem < min then + min := elem; + if elem > max then + max := elem end; Result := (min, max) end; /// Возвращает кортеж из минимума и максимума последовательности -function MinMax(Последовательность: sequence of integer): (integer, integer); +function MinMax(seq: sequence of integer): (integer, integer); begin var min := integer.MaxValue; var max := integer.MinValue; - foreach var Элемент in Последовательность do + foreach var elem in seq do begin - if Элемент < min then - min := Элемент; - if Элемент > max then - max := Элемент + if elem < min then + min := elem; + if elem > max then + max := elem end; Result := (min, max) end; /// Возвращает кортеж из минимума и максимума последовательности s -function MinMax(Последовательность: sequence of real): (real, real); +function MinMax(seq: sequence of real): (real, real); begin var min := real.MaxValue; - var max := real.MinValue; - foreach var Элемент in Последовательность do + var max := -real.MaxValue; + foreach var elem in seq do begin - if Элемент < min then - min := Элемент; - if Элемент > max then - max := Элемент + if elem < min then + min := elem; + if elem > max then + max := elem end; Result := (min, max) end; /// Возвращает кортеж из минимума и максимума последовательности s -function MinMax(Последовательность: sequence of BigInteger): (BigInteger, BigInteger); +function MinMax(seq: sequence of BigInteger): (BigInteger, BigInteger); begin var min, max: BigInteger; - var ЭтоПервыйЭлемент := True; - foreach var Элемент in Последовательность do - if ЭтоПервыйЭлемент then + var is_first := True; + foreach var elem in seq do + if is_first then begin - min := Элемент; - max := Элемент; - ЭтоПервыйЭлемент := False + (min, max) := (elem, elem); + is_first := False end else begin - if Элемент < min then - min := Элемент; - if Элемент > max then - max := Элемент - end; + if elem < min then + min := elem; + if elem > max then + max := elem + end; Result := (min, max) end; @@ -574,10 +598,10 @@ function IsPrime(Self: integer): boolean; extensionmethod; else begin Result := True; - foreach var Простое in LPrimes do - if Sqr(Простое) > Self then + foreach var prime in LPrimes do + if Sqr(prime) > Self then break - else if Self mod Простое = 0 then + else if Self mod prime = 0 then begin Result := False; break @@ -931,13 +955,13 @@ procedure TrueTablePrint(a: array[,] of boolean; f: integer; s: string); {$region String} /// Заменяет последнее вхождение подстроки в строку -procedure ReplaceLast(var Строка: string; ЧтоЗаменить, ЧемЗаменить: string); +procedure ReplaceLast(var s: string; source, target: string); begin - var Позиция := LastPos(ЧтоЗаменить, Строка); - if Позиция > 0 then + var position := LastPos(source, s); + if position > 0 then begin - Delete(Строка, Позиция, ЧтоЗаменить.Length); - Insert(ЧемЗаменить, Строка, Позиция) + Delete(s, position, source.Length); + Insert(target, s, position) end end;