diff --git a/Configuration/GlobalAssemblyInfo.cs b/Configuration/GlobalAssemblyInfo.cs
index 3e3d91b34..2332d79fd 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 = "6";
public const string Build = "3";
- public const string Revision = "2519";
+ public const string Revision = "2521";
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 9965c0eda..e4677ddc6 100644
--- a/Configuration/Version.defs
+++ b/Configuration/Version.defs
@@ -1,4 +1,4 @@
%MINOR%=6
-%REVISION%=2519
+%REVISION%=2521
%COREVERSION%=3
%MAJOR%=3
diff --git a/Localization/DefaultLang.resources b/Localization/DefaultLang.resources
index 67f5ba17c..5190ce8d7 100644
Binary files a/Localization/DefaultLang.resources and b/Localization/DefaultLang.resources differ
diff --git a/Parsers/PascalABCParserNewSaushkin/PABC.ymc b/Parsers/PascalABCParserNewSaushkin/PABC.ymc
index 0030c7926..947144bd4 100644
--- a/Parsers/PascalABCParserNewSaushkin/PABC.ymc
+++ b/Parsers/PascalABCParserNewSaushkin/PABC.ymc
@@ -268,6 +268,5 @@ script=
-
diff --git a/Release/pabcversion.txt b/Release/pabcversion.txt
index ef5a51f35..47362058e 100644
--- a/Release/pabcversion.txt
+++ b/Release/pabcversion.txt
@@ -1 +1 @@
-3.6.3.2519
+3.6.3.2521
diff --git a/ReleaseGenerators/PascalABCNET_version.nsh b/ReleaseGenerators/PascalABCNET_version.nsh
index f2157a2e8..97be2b1b1 100644
--- a/ReleaseGenerators/PascalABCNET_version.nsh
+++ b/ReleaseGenerators/PascalABCNET_version.nsh
@@ -1 +1 @@
-!define VERSION '3.6.3.2519'
+!define VERSION '3.6.3.2521'
diff --git a/SyntaxVisitors/SyntaxVisitors.csproj b/SyntaxVisitors/SyntaxVisitors.csproj
index 70c553eb2..b7be77406 100644
--- a/SyntaxVisitors/SyntaxVisitors.csproj
+++ b/SyntaxVisitors/SyntaxVisitors.csproj
@@ -65,7 +65,7 @@
-
+
diff --git a/SyntaxVisitors/YieldVisitors/CapturedLambdaInYieldVisitor.cs b/SyntaxVisitors/YieldVisitors/CapturedLambdaInYieldVisitor.cs
new file mode 100644
index 000000000..205e20cfb
--- /dev/null
+++ b/SyntaxVisitors/YieldVisitors/CapturedLambdaInYieldVisitor.cs
@@ -0,0 +1,77 @@
+// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using PascalABCCompiler;
+using PascalABCCompiler.SyntaxTree;
+
+namespace SyntaxVisitors
+{
+ public class CapturedLambdaInYieldVisitor : BaseChangeVisitor
+ {
+
+ public CapturedLambdaInYieldVisitor()
+ {
+ }
+
+ public static CapturedLambdaInYieldVisitor New
+ {
+ get { return new CapturedLambdaInYieldVisitor(); }
+ }
+
+ public static void Accept(procedure_definition pd)
+ {
+ New.ProcessNode(pd);
+ }
+
+ int ynum = 0;
+ public string CreateNameForLambdaInYield()
+ {
+ ynum += 1;
+ return "@RenLamInYield" + ynum + "$";
+ }
+
+ public override void visit(yield_node yn)
+ {
+ if (yn.ex is function_lambda_definition)
+ {
+ syntax_tree_node sn = yn;
+ do
+ {
+ sn = sn.Parent;
+ } while (sn != null && !(sn is procedure_definition));
+ procedure_definition pd = sn as procedure_definition;
+
+ if (sn == null)
+ {
+ // этого не будет
+ }
+ var fh = pd.proc_header as function_header;
+ if (fh == null)
+ {
+ // этого тоже не будет
+ }
+ var sq = fh.return_type as sequence_type;
+ if (sq == null)
+ {
+ // и этого не будет
+ }
+
+ var lst = new List();
+ var newid = new ident(CreateNameForLambdaInYield(), yn.ex.source_context);
+ var vs = new var_statement(newid, sq.elements_type, yn.ex);
+ vs.source_context = yn.ex.source_context;
+ var newyn = new yield_node(newid, newid.source_context);
+ lst.Add(vs);
+ lst.Add(newyn);
+ ReplaceStatementUsingParent(yn, lst);
+ }
+ }
+
+
+ }
+}
diff --git a/SyntaxVisitors/YieldVisitors/IsVarRenameVisitor.cs b/SyntaxVisitors/YieldVisitors/IsVarRenameVisitor.cs
deleted file mode 100644
index 9b7c86b9f..000000000
--- a/SyntaxVisitors/YieldVisitors/IsVarRenameVisitor.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-using PascalABCCompiler;
-using PascalABCCompiler.SyntaxTree;
-
-namespace SyntaxVisitors
-{
- public class IsVarRenameVisitor : BaseChangeVisitor
- {
-
- public IsVarRenameVisitor()
- {
- }
-
- public static IsVarRenameVisitor New
- {
- get { return new IsVarRenameVisitor(); }
- }
-
- public static void Accept(procedure_definition pd)
- {
- New.ProcessNode(pd);
- }
-
- public override void visit(procedure_header proc_header)
- {
- // DO THIS THING!
- }
- /* public override void visit(desugared_deconstruction dd)
- {
- var l = new List();
- l.Add(dd);
- foreach (var d in dd.variables.definitions)
- {
- foreach (var id in d.vars.idents)
- {
- // добавить после неё кучу объявлений с присваиваниями
- //ReplaceStatement(dd,)
- var newvar = new ident(NewVariableName(id.name),id.source_context);
- var vs = new var_statement(new ident(id.name, id.source_context), newvar, id.source_context);
- l.Add(vs);
- id.name = newvar.name;
- }
- }
- ReplaceStatement(dd, l);
- }*/
-
- private string NewVariableName(string name)
- {
- name = name.ToLower();
- return "$RenIsVarYield$" + name;
- }
- }
-}
diff --git a/SyntaxVisitors/YieldVisitors/ProcessYieldsCapturedVars.cs b/SyntaxVisitors/YieldVisitors/ProcessYieldsCapturedVars.cs
index a2e7238ca..b1d3a05ae 100644
--- a/SyntaxVisitors/YieldVisitors/ProcessYieldsCapturedVars.cs
+++ b/SyntaxVisitors/YieldVisitors/ProcessYieldsCapturedVars.cs
@@ -971,10 +971,9 @@ namespace SyntaxVisitors
pd.visit(checkVarRedefVisitor);
*/
- // Если есть в pd узлы is_pattern_expr, то запустить визитор, добавляющий присваивание временной переменной и заменяющий
- // везде далее имя исходной переменной на имя временной
- // SSM 20/06 - не очень так получается. Сложно
- //IsVarRenameVisitor.Accept(pd);
+
+ // SSM 21/06 - Выносим yield x -> x
+ CapturedLambdaInYieldVisitor.Accept(pd);
// Выносим выражение из yield в отдельную переменную
ReplaceYieldExprByVarVisitor.Accept(pd);
diff --git a/TestSuite/CompilationSamples/BBCMicrobit.pas b/TestSuite/CompilationSamples/BBCMicrobit.pas
new file mode 100644
index 000000000..97039c0e1
--- /dev/null
+++ b/TestSuite/CompilationSamples/BBCMicrobit.pas
@@ -0,0 +1,190 @@
+// BBC Micro:bit communication module
+
+unit BBCMicrobit;
+
+interface
+
+/// Исключение для информирования об отсутствии подключенного устройства
+type
+ NoUBSComPortsException = class(Exception) end;
+ NoBBCBoardFoundException = class(Exception) end;
+
+/// Класс для взаимодействия с устройством BBC Micro:bit
+type
+ Microbit = class(System.IDisposable)
+
+ protected
+ /// Порт для связи с устройством
+ Port: System.IO.Ports.SerialPort;
+
+ /// Обработчик данных от платы. Принимает только строки
+ procedure DataReceivedHandler(sender: object; e: System.IO.Ports.SerialDataReceivedEventArgs);
+
+
+
+ public
+
+ /// Копирование файла прошивки в BBC:Microbit
+ class procedure CopyFile(filename : string);
+
+ public
+ /// Обработчик события распознавания
+ OnReadString: procedure(Message: string);
+
+ /// Список USB COM-портов с идентификаторами Microbit
+ class function GetUsbPortNames: List;
+ begin
+ // Вот такие параметры у каждой платы (по крайней мере сейчас)
+ var pattern := '^VID_0D28.PID_0204';
+ var _rx := new System.Text.RegularExpressions.Regex(pattern, RegexOptions.IgnoreCase);
+ Result := new List;
+ var {Microsoft.Win32.RegistryKey} rk1 := Microsoft.Win32.Registry.LocalMachine;
+ var {Microsoft.Win32.RegistryKey} rk2 := rk1.OpenSubKey('SYSTEM\\CurrentControlSet\\Enum');
+
+ foreach s3: string in rk2.GetSubKeyNames do
+ begin
+ var rk3 := rk2.OpenSubKey(s3);
+ foreach s: string in rk3.GetSubKeyNames do
+ if _rx.Match(s).Success then
+ begin
+ var {RegistryKey} rk4 := rk3.OpenSubKey(s);
+ foreach s2: string in rk4.GetSubKeyNames do
+ begin
+ var {RegistryKey} rk5 := rk4.OpenSubKey(s2);
+ var {RegistryKey} rk6 := rk5.OpenSubKey('Device Parameters');
+ var {string} portName := string(rk6.GetValue('PortName'));
+ if not String.IsNullOrEmpty(portName) and System.IO.Ports.SerialPort.GetPortNames.Contains(portName) then
+ begin
+ Result.Add(string(rk6.GetValue('PortName')));
+ end;
+ end;
+ end;
+ end;
+ end;
+
+ ///
+ /// Конструктор объекта для взаимодействия с Microbit
+ ///
+ /// Процедура-обработчик, вызываемая для каждой принятой строки
+ /// Имя COM-порта, можно не указывать
+ constructor Create(Handler: procedure(s: string) := nil; PortName: string := '');
+ begin
+ OnReadString := Handler;
+ // Инициализируем виртуальный COM-порт, который связан с USB-устройством.
+ Port := new System.IO.Ports.SerialPort;
+
+ if PortName.Length > 0 then
+ // Порт указан явно при создании объекта класса, значит его и используем
+ Port.PortName := PortName
+ else
+ begin
+ // Порт явно не указан, приходится искать самостоятельно
+ // Получаем список всех похожих COM-портов (по VID и PID)
+ var portNames := GetUsbPortNames;
+ // Если подходящих портов нет - выбрасываем исключение
+ if portNames.Count = 0 then
+ raise new NoUBSComPortsException('Не найдено устройство Microbit')
+ else
+ // Берём первый попавшийся. Если устройств несколько, то надо явно указывать
+ Port.PortName := portNames[0];
+ end;
+
+ // Эти параметры зашиты явно, рекомендованы руководством по Microbit
+ Port.BaudRate := 115200; //Указываем скорость.
+ Port.DataBits := 8;
+ Port.Parity := System.IO.Ports.Parity.None;
+ Port.StopBits := System.IO.Ports.StopBits.One;
+ Port.DataReceived += DataReceivedHandler;
+ Port.Open; //Открываем порт
+ end;
+
+ /// Отправка строки на устройство Microbit
+ procedure Send(message: string) := Port.WriteLine(message);
+
+ /// Деструктор - закрывает COM-порт
+ destructor Destroy;
+ begin
+ if Port <> nil then
+ begin
+ Port.Close;
+ Port := nil;
+ end;
+ end;
+
+ procedure Dispose;
+ begin
+ Destroy;
+ end;
+
+ procedure Finalize; override;
+ begin
+ Destroy
+ end;
+ end;
+
+implementation
+
+/// Иногда строки приходят "склеенные" – нужно разбить по служебным символам
+/// Эта функция возвращает первую группу символов из строки, ограниченную
+/// служебными #10 или #13, сама подстрока из строки удаляется.
+function ParseStr(var s : string) : string;
+begin
+ var iStart := 1;
+ var len := s.Length;
+
+ while (iStart<=len) and ((s[iStart] = #10) or (s[iStart] = #13)) do
+ iStart += 1;
+
+ var iEnd := iStart + 1;
+
+ while (iEnd<=len) and (s[iEnd] <> #10) and (s[iEnd] <> #13) do
+ iEnd += 1;
+
+ // Копируем фрагмент, но с проверкой
+ if iEnd-iStart > 0 then
+ Result := copy(s, iStart, iEnd-iStart)
+ else
+ Result := '';
+
+ while (iEnd 0 do
+ begin
+ // Очередная подстрока
+ var block := ParseStr(message).TrimEnd(' ');
+ if (block.Length > 0) and (OnReadString <> nil) then
+ OnReadString(block);
+ end;
+ end;
+
+class procedure MicroBit.CopyFile(filename : string);
+begin
+ var allDrives := System.IO.DriveInfo.GetDrives();
+
+ foreach d: System.IO.DriveInfo in allDrives do
+ begin
+ if d.IsReady then
+ if d.VolumeLabel = 'MICROBIT' then
+ begin
+ var dest : string := d.RootDirectory.ToString + '\\' + System.IO.Path.GetFileName(filename);
+ System.IO.File.Copy(filename, dest);
+ sleep(2000);
+ exit;
+ end;
+ end;
+ raise new NoBBCBoardFoundException('Не найдено устройство Microbit');
+
+end;
+
+end.
\ No newline at end of file
diff --git a/TestSuite/CompilationSamples/SF.pas b/TestSuite/CompilationSamples/SF.pas
new file mode 100644
index 000000000..361ecd3a4
--- /dev/null
+++ b/TestSuite/CompilationSamples/SF.pas
@@ -0,0 +1,91 @@
+unit SF;
+
+procedure Pr(params a: array of object) := Print(a);
+procedure Pr(o: object) := Print(o);
+procedure Pr(s: string) := Print(s);
+procedure Prln(params a: array of object) := Println(a);
+
+function RI := ReadInteger;
+function RBI := ReadBigInteger;
+function RI64 := ReadInt64;
+function RR := ReadReal;
+function RC := ReadChar;
+function RS := ReadString;
+
+function RlnI := ReadlnInteger;
+function RlnBI := ReadlnBigInteger;
+function RlnI64 := ReadlnInt64;
+function RlnR := ReadlnReal;
+function RlnC := ReadlnChar;
+function RlnS := ReadlnString;
+
+function RI2 := ReadInteger2;
+function RR2 := ReadReal2;
+function RC2 := ReadChar2;
+function RS2 := ReadString2;
+
+function RlnI2 := ReadlnInteger2;
+function RlnR2 := ReadlnReal2;
+function RlnC2 := ReadlnChar2;
+function RlnS2 := ReadlnString2;
+
+function RI3 := ReadInteger3;
+function RR3 := ReadReal3;
+function RC3 := ReadChar3;
+function RS3 := ReadString3;
+
+function RlnI3 := ReadInteger3;
+function RlnR3 := ReadlnReal3;
+function RlnC3 := ReadlnChar3;
+function RlnS3 := ReadlnString3;
+
+function RAI(n: integer) := ReadArrInteger(n);
+function RAR(n: integer) := ReadArrReal(n);
+
+function Pr(Self: integer): integer; extensionmethod := Self.Print;
+function Pr(Self: real): real; extensionmethod := Self.Print;
+function Pr(Self: Biginteger): Biginteger; extensionmethod := Self.Print;
+function Pr(Self: char): char; extensionmethod := Self.Print;
+function Pr(Self: boolean): boolean; extensionmethod := Self.Print;
+function Pr(Self: string): string; extensionmethod := Self.Print;
+
+function Prln(Self: integer): integer; extensionmethod := Self.Println;
+function Prln(Self: real): real; extensionmethod := Self.Println;
+function Prln(Self: Biginteger): Biginteger; extensionmethod := Self.Println;
+function Prln(Self: char): char; extensionmethod := Self.Println;
+function Prln(Self: boolean): boolean; extensionmethod := Self.Println;
+function Prln(Self: string): string; extensionmethod := Self.Println;
+
+procedure ReMin(var min: integer; x: integer);
+begin
+ if x < min then
+ min := x
+end;
+
+procedure ReMax(var max: integer; x: integer);
+begin
+ if x > max then
+ max := x
+end;
+
+procedure ReMin(var min: real; x: real);
+begin
+ if x < min then
+ min := x
+end;
+
+procedure ReMax(var max: real; x: real);
+begin
+ if x > max then
+ max := x
+end;
+
+function ToI(Self: string); extensionmethod := Self.ToInteger;
+
+function ToR(Self: string); extensionmethod := Self.ToReal;
+
+function operator-(c,c1: char): integer; extensionmethod := Ord(c) - Ord(c1);
+
+function Len(Self: string): integer; extensionmethod := Self.Length;
+
+end.
\ No newline at end of file
diff --git a/TestSuite/CompilationSamples/School.pas b/TestSuite/CompilationSamples/School.pas
new file mode 100644
index 000000000..29a6dbb8d
--- /dev/null
+++ b/TestSuite/CompilationSamples/School.pas
@@ -0,0 +1,538 @@
+unit School;
+
+interface
+
+/// Перевод десятичного числа в двоичную систему счисления
+function Bin(x: int64): string;
+
+/// Перевод десятичного числа в двоичную систему счисления
+function Bin(x: BigInteger): string;
+
+/// Перевод десятичного числа в восьмеричную систему счисления
+function Oct(x: int64): string;
+
+/// Перевод десятичного числа в восьмеричную систему счисления
+function Oct(x: BigInteger): string;
+
+/// Перевод десятичного числа в шестнадцатиричную систему счисления
+function Hex(x: int64): string;
+
+/// Перевод десятичного числа в шестнадцатиричную систему счисления
+function Hex(x: BigInteger): string;
+
+/// Перевод из системы по основанию base [2..36] в десятичную
+function Dec(s: string; base: integer): int64;
+
+/// Перевод из системы по основанию base [2..36] в десятичную
+function DecBig(s: string; base: integer): BigInteger;
+
+/// Возвращает кортеж из минимума и максимума последовательности s
+function MinMax(s: sequence of int64): (int64, int64);
+
+/// Возвращает кортеж из минимума и максимума последовательности s
+function MinMax(s: sequence of integer): (integer, integer);
+
+/// Ввозвращает НОД и НОК пары чисел
+function НОДНОК(a, b: int64): (int64, int64);
+
+/// Разложение числа на простые множители
+function Factorize(n: int64): List;
+
+/// Рразложение числа на простые множители
+function Factorize(n: integer): List;
+
+/// Простые числа на интервале [2;n]
+function Primes(n: integer): List;
+
+/// Первые n простых чисел
+function FirstPrimes(n: integer): List;
+
+/// Возвращает массив, содержащий цифры числа
+function Digits(n: int64): List;
+
+/// возвращает список делителей натурального числа
+function Divizors(n: int64): List;
+
+/// возвращает список делителей натурального числа
+function Divizors(n: integer): List;
+
+/// Возвращает Sin угла, заданного в градусах
+function SinDegrees(x: real): real;
+
+/// Возвращает Cos угла, заданного в градусах
+function CosDegrees(x: real): real;
+
+/// Возвращает вещественный массив, заполненный случайными значениями
+/// на интервале [a; b) с t знаками в дробной части
+function ArrRandomReal(n: integer; a, b: real; t: integer): array of real;
+
+/// Возвращает вещественную последовательность, заполненную случайными значениями
+/// на интервале [a; b) с t знаками в дробной части
+function SeqRandomReal(n: integer; a, b: real; t: integer): sequence of real;
+
+/// Возвращает вещественную матрицу, заполненную случайными значениями
+/// на интервале [a; b) с t знаками в дробной части
+function MatrRandomReal(m: integer; n: integer; a, b: real; t: integer): array [,] of real;
+
+implementation
+
+type
+ School_BadCharInString = class(Exception)
+ end;
+
+ School_InvalidBase = class(Exception)
+ end;
+
+{$region Bin}
+
+function Bin(x: int64): string;
+begin
+ x := Abs(x);
+ var r := '';
+ while x >= 2 do
+ (r, x) := (x mod 2 + r, x Shr 1);
+ Result := x + r
+end;
+
+function Bin(x: BigInteger): string;
+begin
+ x := Abs(x);
+ var r := '';
+ while x >= 2 do
+ (r, x) := (byte(x mod 2) + r, x div 2);
+ Result := byte(x) + r
+end;
+
+{$endregion}
+
+{$region Oct}
+
+function Oct(x: int64): string;
+begin
+ x := Abs(x);
+ var r := '';
+ while x >= 8 do
+ (r, x) := (x mod 8 + r, x Shr 3);
+ Result := x + r
+end;
+
+function Oct(x: BigInteger): string;
+begin
+ x := Abs(x);
+ var r := '';
+ while x >= 8 do
+ (r, x) := (byte(x mod 8) + r, x div 8);
+ Result := byte(x) + r
+end;
+
+{$endregion}
+
+{$region Hex}
+function Hex(x: int64): string;
+begin
+ x := Abs(x);
+ var s := '0123456789ABCDEF';
+ var r := '';
+ while x >= 16 do
+ (r, x) := (s[x mod 16 + 1] + r, x Shr 4);
+ Result := s[x + 1] + r
+end;
+
+function Hex(x: BigInteger): string;
+begin
+ x := Abs(x);
+ var s := '0123456789ABCDEF';
+ var r := '';
+ while x >= 16 do
+ (r, x) := (s[byte(x mod 16) + 1] + r, x div 16);
+ Result := s[byte(x) + 1] + r
+end;
+
+{$endregion}
+
+{$region Dec}
+
+function Dec(s: string; base: integer): int64;
+begin
+ if not (base in 2..36) then
+ raise new School_InvalidBase
+ ($'ToDecimal: Недопустимое основание {base}');
+ var sb := '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ s := s.ToUpper;
+ var r := s.Except(sb[:base + 1]).JoinToString;
+ if r.Length > 0 then
+ raise new School_BadCharInString
+ ($'ToDecimal: Недопустимый символ "{r}" в строке {s}');
+ var (pa, p) := (BigInteger.One, BigInteger.Zero);
+ foreach var c in s.Reverse do
+ begin
+ var i := Pos(c, sb) - 1;
+ p += pa * i;
+ pa *= base
+ end;
+ Result := int64(p)
+end;
+
+function DecBig(s: string; base: integer): BigInteger;
+begin
+ if not (base in 2..36) then
+ raise new School_InvalidBase
+ ($'ToDecimal: Недопустимое основание {base}');
+ var sb := '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ s := s.ToUpper;
+ var r := s.Except(sb[:base + 1]).JoinToString;
+ if r.Length > 0 then
+ raise new School_BadCharInString
+ ($'ToDecimal: Недопустимый символ "{r}" в строке {s}');
+ var pa := BigInteger.One;
+ Result := BigInteger.Zero;
+ foreach var c in s.Reverse do
+ begin
+ var i := Pos(c, sb) - 1;
+ Result += pa * i;
+ pa *= base
+ end
+end;
+
+{$endregion}
+
+{$region MinMax}
+
+/// Возвращает кортеж из минимума и максимума последовательности s
+function MinMax(s: sequence of int64): (int64, int64);
+begin
+ var (min, max) := (int64.MaxValue, int64.MinValue);
+ foreach var m in s do
+ if m < min then
+ min := m
+ else if m > max then
+ max := m;
+ Result := (min, max)
+end;
+
+/// Возвращает кортеж из минимума и максимума последовательности s
+function MinMax(s: sequence of integer): (integer, integer);
+begin
+ var (min, max) := (integer.MaxValue, integer.MinValue);
+ foreach var m in s do
+ if m < min then
+ min := m
+ else if m > max then
+ max := m;
+ Result := (min, max)
+end;
+
+/// Возвращает кортеж из минимума и максимума последовательности
+function MinMax(Self: sequence of int64): (int64, int64); extensionmethod :=
+ MinMax(Self);
+
+/// Возвращает кортеж из минимума и максимума последовательности
+function MinMax(Self: sequence of integer): (integer, integer);
+ extensionmethod := MinMax(Self);
+
+{$endregion}
+
+{$region НОДНОК}
+
+/// Возвращает НОД и НОК пары чисел
+function НОДНОК(a, b: int64): (int64, int64);
+begin
+ (a, b) := (Abs(a), Abs(b));
+ var (a1, b1) := (a, b);
+ while b <> 0 do
+ (a, b) := (b, a mod b);
+ Result := (a, a1 div a * b1)
+end;
+
+{$endregion}
+
+{$region Factorize}
+
+/// Разложение числа на простые множители
+function Factorize(n: int64): List;
+begin
+ n := Abs(n);
+ var i: int64 := 2;
+ var L := new List;
+ while i * i <= n do
+ if n mod i = 0 then
+ begin
+ L.Add(i);
+ n := n div i;
+ if n < i then
+ break
+ end
+ else
+ i += i = 2 ? 1 : 2;
+ if n > 1 then
+ L.Add(n);
+ Result := L
+end;
+
+/// Разложение числа на простые множители
+function Factorize(n: integer): List;
+begin
+ n := Abs(n);
+ var i := 2;
+ var L := new List;
+ while i * i <= n do
+ if n mod i = 0 then
+ begin
+ L.Add(i);
+ n := n div i;
+ if n < i then
+ break
+ end
+ else
+ i += i = 2 ? 1 : 2;
+ if n > 1 then
+ L.Add(n);
+ Result := L
+end;
+
+/// разложение числа на простые множители
+function Factorize(Self: int64): List; extensionmethod :=
+ Factorize(Self);
+
+/// Разложение числа на простые множители
+function Factorize(Self: integer): List; extensionmethod :=
+ Factorize(Self);
+
+{$endregion}
+
+{$region Primes}
+
+/// Простые числа на интервале [2;n]
+function Primes(n: integer): List;
+// Модифицированное решето Эратосфена на [2;n]
+begin
+ var Mas := ArrFill(n, True);
+ var i := 2;
+ while i * i <= n do
+ begin
+ if Mas[i-1] then
+ begin
+ var k := i*i;
+ while k <= n do
+ begin
+ Mas[k-1] := False;
+ k += i
+ end
+ end;
+ Inc(i)
+ end;
+ n := Mas.Count(t -> t);
+ Result := new List;
+ for var j := 1 to Mas.High do
+ if Mas[j] then Result.Add(j + 1)
+end;
+
+/// Первые n простых чисел
+function FirstPrimes(n: integer): List;
+// Модифицированное решето Эратосфена
+begin
+ var n1 := Trunc(Exp((Ln(n)+1.088)/0.8832));
+ var Mas := ArrFill(n1, True);
+ var i := 2;
+ while i * i <= n1 do
+ begin
+ if Mas[i-1] then
+ begin
+ var k := i*i;
+ while k <= n1 do
+ begin
+ Mas[k-1] := False;
+ k += i
+ end
+ end;
+ Inc(i)
+ end;
+ //n := Mas.Count(t -> t);
+ Result := new List;
+ i := 0;
+ for var j := 1 to Mas.High do
+ if Mas[j] then
+ begin
+ Result.Add(j + 1);
+ Inc(i);
+ if i = n then break
+ end
+end;
+
+/// возвращает True, если число простое и False в противном случае
+function IsPrime(Self: integer): boolean; extensionmethod;
+begin
+ if Self < 2 then
+ begin
+ Result := False;
+ exit
+ end;
+ var i := 2;
+ while i * i <= Self do
+ if Self mod i = 0 then
+ begin
+ Result := False;
+ exit
+ end
+ else
+ i += if i = 2 then 1 else 2;
+ Result := True
+end;
+
+/// возвращает True, если число простое и False в противном случае
+function IsPrime(Self: int64): boolean; extensionmethod;
+begin
+ if Self < 2 then
+ begin
+ Result := False;
+ exit
+ end;
+ var i := int64(2);
+ while i * i <= Self do
+ if Self mod i = 0 then
+ begin
+ Result := False;
+ exit
+ end
+ else
+ i += if i = 2 then 1 else 2;
+ Result := True
+end;
+
+{$endregion}
+
+{$region Digits}
+
+/// Возвращает массив, содержащий цифры числа
+function Digits(n: int64): List;
+begin
+ var St := new Stack;
+ n := Abs(n);
+ if n = 0 then Result.Add(0)
+ else
+ begin
+ while n > 0 do
+ begin
+ St.Push(n mod 10);
+ n := n div 10
+ end;
+ Result := St.ToList
+ end
+end;
+
+/// Возвращает массив, содержащий цифры числа
+function Digits(Self: integer): List;
+ extensionmethod := Digits(Self);
+
+/// возвращает массив, содержащий цифры числа
+function Digits(Self: int64): List;
+ extensionmethod := Digits(Self);
+
+{$endregion}
+
+{$region Divisors}
+
+/// возвращает список всех делителей натурального числа
+function Divizors(n: integer): List;
+begin
+ n := Abs(n); // foolproof
+ var L := new List;
+ L.Add(1);
+ L.Add(n);
+ if n > 3 then
+ begin
+ var k := 2;
+ while (k * k <= n) and (k < 46341) do
+ begin
+ if n mod k = 0 then
+ begin
+ var t := n div k;
+ L.Add(k);
+ if k < t then L.Add(t)
+ else break
+ end;
+ Inc(k)
+ end;
+ L.Sort;
+ end;
+ Result := L
+end;
+
+/// возвращает список всех делителей натурального числа
+function Divizors(n: int64): List;
+begin
+ n := Abs(n); // foolproof
+ var L := new List;
+ L.Add(1);
+ L.Add(n);
+ if n > 3 then
+ begin
+ var k := int64(2);
+ while (k * k <= n) and (k < 3037000500) do
+ begin
+ if n mod k = 0 then
+ begin
+ var t := n div k;
+ L.Add(k);
+ if k < t then L.Add(t)
+ else break
+ end;
+ Inc(k)
+ end;
+ L.Sort;
+ end;
+ Result := L
+end;
+
+/// возвращает список делителей натурального числа
+function Divizors(Self: integer): List; extensionmethod :=
+ Divizors(Self);
+
+/// возвращает список делителей натурального числа
+function Divizors(Self: int64): List; extensionmethod :=
+ Divizors(Self);
+
+{$endregion}
+
+{$region Trig}
+
+function SinDegrees(x: real): real := Sin(DegToRad(x));
+
+function CosDegrees(x: real): real := Cos(DegToRad(x));
+
+function TanDegrees(x: real): real := Tan(DegToRad(x));
+
+{$endregion}
+
+{$region Random}
+
+/// Возвращает вещественный массив, заполненный случайными значениями
+/// на интервале [a; b) с t знаками в дробной части
+function ArrRandomReal(n: integer; a, b: real; t: integer): array of real;
+begin
+ Result := new real[n];
+ for var i := 0 to Result.Length - 1 do
+ Result[i] := Round(Random * (b - a) + a, t);
+end;
+
+/// Возвращает вещественную последовательность, заполненную случайными значениями
+/// на интервале [a; b) с t знаками в дробной части
+function SeqRandomReal(n: integer; a, b: real; t: integer): sequence of real;
+begin
+ loop n do
+ yield Round(Random * (b - a) + a, t)
+end;
+
+/// Возвращает вещественную матрицу, заполненную случайными значениями
+/// на интервале [a; b) с t знаками в дробной части
+function MatrRandomReal(m: integer; n: integer; a, b: real; t: integer): array [,] of real;
+begin
+ Result := new real[m, n];
+ for var i := 0 to Result.RowCount - 1 do
+ for var j := 0 to Result.ColCount - 1 do
+ Result[i, j] := Round(Random * (b - a) + a, t);
+end;
+
+{$endregion}
+
+end.
\ No newline at end of file
diff --git a/TestSuite/formatter_tests/input/PABCSystem1.pas b/TestSuite/formatter_tests/input/PABCSystem1.pas
new file mode 100644
index 000000000..88664edea
--- /dev/null
+++ b/TestSuite/formatter_tests/input/PABCSystem1.pas
@@ -0,0 +1,11468 @@
+// Copyright (c) Ivan Bondarev, Stanislav Mihalkovich (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+/// Стандартный модуль
+/// !! System unit
+unit PABCSystem;
+
+{$define PascalABC}
+
+{$gendoc true}
+
+// Default Application type
+{$apptype console}
+
+{$reference '%GAC%\System.dll'}
+{$reference '%GAC%\mscorlib.dll'}
+{$reference '%GAC%\System.Core.dll'}
+{$reference '%GAC%\System.Numerics.dll'}
+
+interface
+
+uses
+ System.Runtime.InteropServices,
+ System.IO,
+ System.Collections,
+ System.Collections.Generic,
+ System;
+
+//{{{doc: Начало секции стандартных констант для документации }}}
+
+const
+// -----------------------------------------------------
+//>> Стандартные константы # Standard constants
+// -----------------------------------------------------
+ /// Максимальное значение типа shortint
+ MaxShortInt = shortint.MaxValue;
+ /// Максимальное значение типа byte
+ MaxByte = byte.MaxValue;
+ /// Максимальное значение типа smallint
+ MaxSmallInt = smallint.MaxValue;
+ /// Максимальное значение типа word
+ MaxWord = word.MaxValue;
+ /// Максимальное значение типа longword
+ MaxLongWord = longword.MaxValue;
+ /// Максимальное значение типа int64
+ MaxInt64 = int64.MaxValue;
+ /// Максимальное значение типа uint64
+ MaxUInt64 = uint64.MaxValue;
+ /// Максимальное значение типа double
+ MaxDouble = real.MaxValue;
+ /// Минимальное положительное значение типа double
+ MinDouble = real.Epsilon;
+ /// Максимальное значение типа real
+ MaxReal = real.MaxValue;
+ /// Минимальное положительное значение типа real
+ MinReal = real.Epsilon;
+ /// Максимальное значение типа single
+ MaxSingle = single.MaxValue;
+ /// Минимальное положительное значение типа single
+ MinSingle = single.Epsilon;
+ /// Максимальное значение типа integer
+ MaxInt = integer.MaxValue;
+ /// Константа Pi
+ /// !! Pi constant
+ Pi = 3.141592653589793;
+ /// Константа E
+ /// !! E constant
+ E = 2.718281828459045;
+ /// Константа перехода на новую строку
+ /// !! The newline string defined for this environment.
+ NewLine = System.Environment.NewLine;
+//{{{--doc: Конец секции стандартных констант для документации }}}
+
+
+//Маркер того, что это системный модуль
+///--
+const
+ END_OF_LINE_SYMBOL = #10;
+ __IS_SYSTEM_MODULE = true;
+
+//{{{doc: Начало секции стандартных типов для документации }}}
+type
+// -----------------------------------------------------
+//>> Стандартные типы # Standard types
+// -----------------------------------------------------
+ /// Базовый тип объектов
+ Object = System.Object;
+
+ /// Базовый тип исключений
+ Exception = System.Exception;
+
+ /// double = real
+ double = System.Double;
+
+ /// longint = integer
+ longint = System.Int32;
+
+ /// cardinal = longword
+ cardinal = System.UInt32;
+
+ /// Представляет 128-битное вещественное число
+ /// !! Represents a decimal number
+ decimal = System.Decimal;
+
+ /// Представляет произвольно большое целое число
+ BigInteger = System.Numerics.BigInteger;
+
+ /// Представляет дату и время
+ DateTime = System.DateTime;
+
+ /// Представляет комплексное число
+ Complex = System.Numerics.Complex;
+
+ /// Представляет кортеж
+ Tuple = System.Tuple;
+
+ /// Представляет список на базе динамического массива
+ List = System.Collections.Generic.List;
+
+ /// Представляет базовый класс для реализации интерфейса IComparer
+ Comparer = System.Collections.Generic.Comparer;
+
+ /// Представляет базовый класс для реализации интерфейса IComparer
+ IComparable = System.IComparable;
+
+ /// Представляет множество значений, реализованное на базе хеш-таблицы
+ HashSet = System.Collections.Generic.HashSet;
+
+ /// Представляет множество значений, реализованное на базе бинарного дерева поиска
+ SortedSet = System.Collections.Generic.SortedSet;
+
+ /// Представляет ассоциативный массив (набор пар Ключ-Значение), реализованный на базе хеш-таблицы
+ Dictionary = System.Collections.Generic.Dictionary;
+
+ /// Представляет ассоциативный массив, реализованный на базе бинарного дерева поиска
+ SortedDictionary = System.Collections.Generic.SortedDictionary;
+
+ /// Представляет ассоциативный массив (набор пар ключ-значение), реализованный на базе динамического массива пар
+ SortedList = System.Collections.Generic.SortedList;
+
+ /// Представляет пару Ключ-Значение для ассоциативного массива
+ KeyValuePair = System.Collections.Generic.KeyValuePair;
+
+ /// Представляет двусвязный список
+ LinkedList = System.Collections.Generic.LinkedList;
+
+ /// Представляет узел двусвязного списка
+ LinkedListNode = System.Collections.Generic.LinkedListNode;
+
+ /// Представляет очередь - набор элементов, реализованных по принципу "первый вошел-первый вышел"
+ Queue = System.Collections.Generic.Queue;
+
+ /// Представляет стек - набор элементов, реализованных по принципу "последний вошел-первый вышел"
+ Stack = System.Collections.Generic.Stack;
+
+ /// Представляет интерфейс для коллекции
+ ICollection = System.Collections.Generic.ICollection;
+
+ /// Представляет интерфейс для сравнения двух элементов
+ IComparer = System.Collections.Generic.IComparer;
+
+ /// Представляет интерфейс для набора пар Ключ-Значение
+ IDictionary = System.Collections.Generic.IDictionary;
+
+ /// Представляет интерфейс, предоставляющий перечислитель для перебора элементов коллекции
+ IEnumerable = System.Collections.Generic.IEnumerable;
+
+ /// Представляет интерфейс для перебора элементов коллекции
+ IEnumerator = System.Collections.Generic.IEnumerator;
+
+ /// Представляет интерфейс для поддержки сравнения на равенство
+ IEqualityComparer = System.Collections.Generic.IEqualityComparer;
+
+ /// Представляет интерфейс для коллекции с доступом по индексу
+ IList = System.Collections.Generic.IList;
+
+ /// Представляет интерфейс для множества
+ ISet = System.Collections.Generic.ISet;
+
+ /// Представляет изменяемую строку символов
+ StringBuilder = System.Text.StringBuilder;
+
+ /// Тип кодировки символов
+ Encoding = System.Text.Encoding;
+
+ /// Представляет действие без параметров
+ Action0 = System.Action;
+
+ /// Представляет действие с одним параметром
+ Action = System.Action;
+
+ /// Представляет действие с двумя параметрами
+ Action2 = System.Action;
+
+ /// Представляет действие с тремя параметрами
+ Action3 = System.Action;
+
+ /// Представляет функцию без параметров
+ Func0 = System.Func;
+
+ /// Представляет функцию с одним параметром
+ Func = System.Func;
+
+ /// Представляет функцию с двумя параметрами
+ Func2 = System.Func;
+
+ /// Представляет функцию с тремя параметрами
+ Func3 = System.Func;
+
+ /// Представляет функцию с одним параметром целого типа, возвращающую целое
+ IntFunc = Func;
+
+ /// Представляет функцию с одним параметром вещественного типа, возвращающую вещественное
+ RealFunc = Func;
+
+ /// Представляет функцию с одним параметром строкового типа, возвращающую строку
+ StringFunc = Func;
+
+ /// Представляет функцию с одним параметром, возвращающую boolean
+ Predicate = System.Predicate;
+
+ /// Представляет функцию с двумя параметрами, возвращающую boolean
+ Predicate2 = function(x1: T1; x2: T2): boolean;
+
+ /// Представляет функцию с тремя параметрами, возвращающую boolean
+ Predicate3 = function(x1: T1; x2: T2; x3: T3): boolean;
+
+ /// Представляет регулярное выражение
+ Regex = System.Text.RegularExpressions.Regex;
+
+ /// Представляет результаты из отдельного совпадения регулярного выражения
+ &Match = System.Text.RegularExpressions.&Match;
+
+ /// Представляет метод, вызываемый при обнаружении совпадения в Regex.Replace
+ MatchEvaluator = System.Text.RegularExpressions.MatchEvaluator;
+
+ /// Представляет набор успешных совпадений регулярного выражения
+ MatchCollection = System.Text.RegularExpressions.MatchCollection;
+
+ /// Представляет параметры регулярного выражения
+ RegexOptions = System.Text.RegularExpressions.RegexOptions;
+
+ /// Представляет результаты из одной группы при выполнении Regex.Match
+ RegexGroup = System.Text.RegularExpressions.Group;
+
+ /// Представляет результаты из набора групп при выполнении Regex.Match
+ RegexGroupCollection = System.Text.RegularExpressions.GroupCollection;
+
+ /// Представляет тип короткой строки фиксированной длины 255 символов
+ ShortString = string[255];
+
+//{{{--doc: Конец секции стандартных типов для документации }}}
+
+ //------------------------------------------------------------------------------
+ //Pointers
+ //------------------------------------------------------------------------------
+
+ //1 //pointed to
+ PBoolean = ^boolean;//bool
+ PByte = ^byte;//byte
+ PShortint = ^shortint;//sbyte
+ //2
+ PChar = ^char;//char
+ PSmallint = ^smallint;//short
+ PWord = ^word;//ushort
+ //4
+ PPointer = ^pointer;//void*
+ PInteger = ^integer;//int32
+ PLongword = ^longword;//uint32
+ PLongint = ^longint;//int64
+ //8
+ PInt64 = ^int64;
+ PUInt64 = ^uint64;//unit64
+
+ //8
+ PSingle = ^single;//single
+ //16
+ PReal = ^real;//double
+ PDouble = ^double;//double //ошибка, не сохранится, надо исправить
+ //------------------------------------------------------------------------------
+
+// -----------------------------------------------------
+// IOSystem interface & IOStandardSystem implementation
+// -----------------------------------------------------
+type
+ /// Интерфейс подсистемы ввода/вывода
+ IOSystem = interface
+ function peek: integer;
+ function read_symbol: char;
+ procedure read(var x: integer);
+ procedure read(var x: real);
+ procedure read(var x: char);
+ procedure read(var x: string);
+ procedure read(var x: byte);
+ procedure read(var x: shortint);
+ procedure read(var x: smallint);
+ procedure read(var x: word);
+ procedure read(var x: longword);
+ procedure read(var x: int64);
+ procedure read(var x: uint64);
+ procedure read(var x: single);
+ procedure read(var x: boolean);
+ procedure readln;
+ procedure write(obj: object);
+ procedure write(p: pointer);
+ procedure writeln;
+ end;
+
+ /// Стандартная подсистема ввода-вывода
+ IOStandardSystem = class(IOSystem)
+ state := 0; // 0 - нет символа в буфере char, 1 - есть символ в буфере char
+ sym: integer; // буфер в 1 символ для моделирования Peek в консоли
+ public
+ function peek: integer; virtual;// использует state и sym
+ function read_symbol: char; virtual;// использует state и sym
+ procedure read(var x: integer); virtual;
+ procedure read(var x: real); virtual;
+ procedure read(var x: char); virtual;
+ procedure read(var x: string); virtual;
+ procedure read(var x: byte); virtual;
+ procedure read(var x: shortint); virtual;
+ procedure read(var x: smallint); virtual;
+ procedure read(var x: word); virtual;
+ procedure read(var x: longword); virtual;
+ procedure read(var x: int64); virtual;
+ procedure read(var x: uint64); virtual;
+ procedure read(var x: single); virtual;
+ procedure read(var x: boolean); virtual;
+ procedure readln; virtual;
+ procedure write(p: pointer); virtual;
+ procedure write(obj: object); virtual;
+ procedure writeln; virtual;
+ end;
+
+// -----------------------------------------------------
+// Classes for files & typed sets
+// -----------------------------------------------------
+type
+ /// Тип текстового файла
+ Text = class
+ private
+ fi: FileInfo;
+ sr: StreamReader;
+ sw: StreamWriter;
+ public
+ /// Возвращает значение типа integer, введенное из текстового файла
+ function ReadInteger: integer;
+ /// Возвращает значение типа real, введенное из текстового файла
+ function ReadReal: real;
+ /// Возвращает значение типа char, введенное из текстового файла
+ function ReadChar: char;
+ /// Возвращает значение типа string, введенное из текстового файла, без перехода на следующую строку
+ function ReadString: string;
+ /// Возвращает значение типа boolean, введенное из текстового файла
+ function ReadBoolean: boolean;
+ /// Возвращает слово, введенное из текстового файла
+ function ReadWord: string;
+ /// Возвращает значение типа integer, введенное из текстового файла, и переходит на следующую строку
+ function ReadlnInteger: integer;
+ /// Возвращает значение типа real, введенное из текстового файла, и переходит на следующую строку
+ function ReadlnReal: real;
+ /// Возвращает значение типа char, введенное из текстового файла, и переходит на следующую строку
+ function ReadlnChar: char;
+ /// Возвращает значение типа string, введенное из текстового файла, и переходит на следующую строку
+ function ReadlnString: string;
+ /// Возвращает значение типа boolean, введенное из текстового файла, и переходит на следующую строку
+ function ReadlnBoolean: boolean;
+ /// Переходит в файле на следующую строку
+ procedure Readln;
+ /// Записывает в текстовый файл значения
+ procedure Write(params o: array of Object);
+ /// Записывает в текстовый файл значения и переходит на следующую строку
+ procedure Writeln(params o: array of Object);
+ /// Записывает в текстовый файл значения, разделяя их пробелами
+ procedure Print(params o: array of Object);
+ /// Записывает в текстовый файл значения, разделяя их пробелами, и переходит на следующую строку
+ procedure Println(params o: array of Object);
+ /// Возвращает True, если достигнут конец файла, и False в противном случае
+ function Eof: boolean;
+ /// Возвращает True, если достигнут конец строки, и False в противном случае
+ function Eoln: boolean;
+ /// Закрывает файл
+ procedure Close;
+ /// Пропускает пробельные символы, после чего возвращает True, если достигнут конец файла
+ function SeekEof: boolean;
+ /// Пропускает пробельные символы, после чего возвращает True, если достигнут конец строки в файле
+ function SeekEoln: boolean;
+ /// Записывает содержимое буфера файла на диск
+ procedure Flush;
+ /// Удаляет файл
+ procedure Erase;
+ /// Переименовывает файл, давая ему имя newname
+ procedure Rename(newname: string);
+ /// Возвращает имя файла
+ function Name: string;
+ /// Возвращает полное имя файла
+ function FullName: string;
+ /// Возвращает в виде строки содержимое файла от текущего положения до конца
+ function ReadToEnd: string;
+ /// Устанавливает файловый указатель на начало файла
+ procedure Reset;
+ end;
+
+ /// Тип текстового файла
+ TextFile = Text;
+
+type
+ // Вспомогательный тип для диапазонного типа
+ ///--
+ Diapason = record
+ low, high: integer;
+ clow, chigh: object;
+ constructor(_low, _high: integer);
+ constructor(_low, _high: object);
+ end;
+
+ ///--
+ {TypedSetComparer = class(System.Collections.IEqualityComparer)
+ public function Equals(x: System.Object; y: System.Object): boolean;
+ public function GetHashCode(obj: System.Object): integer;
+ end;}
+
+type
+ // Вспомогательный тип для множества
+ ///--
+ TypedSet = class (System.Collections.IEnumerable)
+ private
+ ht: Hashtable;
+ len: integer;
+ //copy_ht: Hashtable;
+ low_bound, upper_bound: object;
+ public
+ constructor Create;
+ constructor Create(len: integer);
+ constructor Create(low_bound, upper_bound: object);
+ constructor Create(vals: array of byte);
+ constructor Create(initValue: TypedSet);
+ constructor Create(low_bound, upper_bound: object; initValue: TypedSet);
+ procedure CreateIfNeed;
+ function UnionSet(s: TypedSet): TypedSet;
+ function SubtractSet(s: TypedSet): TypedSet;
+ function IntersectSet(s: TypedSet): TypedSet;
+ function CloneSet: TypedSet;
+ function GetBytes: array of byte;
+ function IsInDiapason(elem: object): boolean;
+ function Contains(elem: object): boolean;
+ procedure Clip;
+ procedure Clip(len: integer);
+ procedure IncludeElement(elem: object);
+ procedure ExcludeElement(elem: object);
+ procedure Init(params elems: array of object);
+ procedure AssignSetFrom(s: TypedSet);
+ function CompareEquals(s: TypedSet): boolean;
+ function CompareInEquals(s: TypedSet): boolean;
+ function CompareLess(s: TypedSet): boolean;
+ function CompareLessEqual(s: TypedSet): boolean;
+ function CompareGreater(s: TypedSet): boolean;
+ function CompareGreaterEqual(s: TypedSet): boolean;
+ function GetEnumerator: System.Collections.IEnumerator;
+ function ToString: string; override;
+ class function operator implicit(s: TypedSet): HashSet;
+ class function operator implicit(s: HashSet): TypedSet;
+ function Count: integer := ht.Count;
+ procedure Print(delim: string := ' ');
+ procedure Println(delim: string := ' ');
+ end;
+
+type
+ // Base class for typed and binary files
+ ///--
+ AbstractBinaryFile = class
+ private
+ fi: FileInfo;
+ fs: FileStream;
+ br: BinaryReader;
+ bw: BinaryWriter;
+ public
+ /// Закрывает файл
+ procedure Close;
+ /// Усекает двоичный файл, отбрасывая все элементы с позиции файлового указателя
+ procedure Truncate;
+ /// Возвращает True, если достигнут конец файла
+ function Eof: boolean;
+ /// Удаляет файл
+ procedure Erase;
+ /// Переименовывает файл, давая ему имя newname
+ procedure Rename(newname: string);
+ ///- f.Write(a,b,...)
+ /// Выводит значения a,b,... в двоичный файл
+ procedure Write(params vals: array of object);
+ /// Устанавливает файловый указатель на начало файла
+ procedure Reset;
+ /// Возвращает имя файла
+ function Name: string;
+ /// Возвращает полное имя файла
+ function FullName: string;
+ end;
+
+ // Class for typed files
+ ///--
+ TypedFile = sealed class(AbstractBinaryFile)
+ private
+ ElementSize: int64;
+ offset: integer;
+ offsets: array of integer;
+ function GetFilePos: int64;
+ public
+ ElementType: System.Type;
+ constructor Create(ElementType: System.Type);
+ constructor Create(ElementType: System.Type; offs: integer; params offsets: array of integer);
+ function ToString: string; override;
+ /// Возвращает количество элементов в типизированном файле
+ function Size: int64;
+ /// Устанавливает текущую позицию файлового указателя в типизированном файле на элемент с номером n
+ procedure Seek(n: int64);
+ /// Возвращает или устанавливает текущую позицию файлового указателя в типизированном файле
+ property Position: int64 read GetFilePos write Seek;
+ end;
+
+ // Class for binary files
+ ///--
+ BinaryFile = sealed class(AbstractBinaryFile)
+ private
+ function GetFilePos: int64;
+ public
+ function ToString: string; override;
+ /// Возвращает количество байт в бестиповом файле
+ function Size: int64;
+ /// Устанавливает текущую позицию файлового указателя в бестиповом файле на элемент с номером n
+ procedure Seek(n: int64);
+ /// Возвращает или устанавливает текущую позицию файлового указателя в бестиповом файле
+ property Position: int64 read GetFilePos write Seek;
+ end;
+
+//{{{doc: Начало секции интерфейса для документации }}}
+
+// -----------------------------------------------------
+//>> Подпрограммы ввода # Read subroutines
+// -----------------------------------------------------
+///- procedure Read(a,b,...);
+/// Вводит значения a,b,... с клавиатуры
+procedure Read;
+///--
+procedure Read(var x: integer);
+///--
+procedure Read(var x: real);
+///--
+procedure Read(var x: char);
+///--
+procedure Read(var x: string);
+///--
+procedure Read(var x: byte);
+///--
+procedure Read(var x: shortint);
+///--
+procedure Read(var x: smallint);
+///--
+procedure Read(var x: word);
+///--
+procedure Read(var x: longword);
+///--
+procedure Read(var x: int64);
+///--
+procedure Read(var x: uint64);
+///--
+procedure Read(var x: single);
+///--
+procedure Read(var x: boolean);
+///- procedure Readln(a,b,...);
+/// Вводит значения 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, введенное с клавиатуры
+function ReadReal: real;
+/// Возвращает значение типа char, введенное с клавиатуры
+function ReadChar: char;
+/// Возвращает значение типа string, введенное с клавиатуры
+function ReadString: string;
+/// Возвращает значение типа boolean, введенное с клавиатуры
+function ReadBoolean: boolean;
+
+/// Возвращает значение типа integer, введенное с клавиатуры, и переходит на следующую строку ввода
+function ReadlnInteger: integer;
+/// Возвращает значение типа real, введенное с клавиатуры, и переходит на следующую строку ввода
+function ReadlnReal: real;
+/// Возвращает значение типа char, введенное с клавиатуры, и переходит на следующую строку ввода
+function ReadlnChar: char;
+/// Возвращает значение типа string, введенное с клавиатуры, и переходит на следующую строку ввода
+function ReadlnString: string;
+/// Возвращает значение типа boolean, введенное с клавиатуры, и переходит на следующую строку ввода
+function ReadlnBoolean: boolean;
+
+/// Возвращает кортеж из двух значений типа integer, введенных с клавиатуры
+function ReadInteger2: (integer, integer);
+/// Возвращает кортеж из двух значений типа real, введенных с клавиатуры
+function ReadReal2: (real, real);
+/// Возвращает кортеж из двух значений типа char, введенных с клавиатуры
+function ReadChar2: (char, char);
+/// Возвращает кортеж из двух значений типа string, введенных с клавиатуры
+function ReadString2: (string, string);
+/// Возвращает кортеж из двух значений типа integer, введенных с клавиатуры, и переходит на следующую строку ввода
+function ReadlnInteger2: (integer, integer);
+/// Возвращает кортеж из двух значений типа real, введенных с клавиатуры, и переходит на следующую строку ввода
+function ReadlnReal2: (real, real);
+/// Возвращает кортеж из двух значений типа char, введенных с клавиатуры, и переходит на следующую строку ввода
+function ReadlnChar2: (char, char);
+/// Возвращает кортеж из двух значений типа string, введенных с клавиатуры, и переходит на следующую строку ввода
+function ReadlnString2: (string, string);
+
+/// Возвращает кортеж из трёх значений типа integer, введенных с клавиатуры
+function ReadInteger3: (integer, integer, integer);
+/// Возвращает кортеж из трёх значений типа real, введенных с клавиатуры
+function ReadReal3: (real, real, real);
+/// Возвращает кортеж из трёх значений типа char, введенных с клавиатуры
+function ReadChar3: (char, char, char);
+/// Возвращает кортеж из трёх значений типа string, введенных с клавиатуры
+function ReadString3: (string, string, string);
+/// Возвращает кортеж из двух значений типа integer, введенных с клавиатуры, и переходит на следующую строку ввода
+function ReadlnInteger3: (integer, integer, integer);
+/// Возвращает кортеж из двух значений типа real, введенных с клавиатуры, и переходит на следующую строку ввода
+function ReadlnReal3: (real, real, real);
+/// Возвращает кортеж из двух значений типа char, введенных с клавиатуры, и переходит на следующую строку ввода
+function ReadlnChar3: (char, char, char);
+/// Возвращает кортеж из двух значений типа string, введенных с клавиатуры, и переходит на следующую строку ввода
+function ReadlnString3: (string, string, string);
+
+/// Возвращает кортеж из двух значений типа integer, введенных с клавиатуры
+function ReadInteger2(prompt: string): (integer, integer);
+/// Возвращает кортеж из двух значений типа real, введенных с клавиатуры
+function ReadReal2(prompt: string): (real, real);
+/// Возвращает кортеж из двух значений типа char, введенных с клавиатуры
+function ReadChar2(prompt: string): (char, char);
+/// Возвращает кортеж из двух значений типа string, введенных с клавиатуры
+function ReadString2(prompt: string): (string, string);
+/// Возвращает кортеж из двух значений типа integer, введенных с клавиатуры, и переходит на следующую строку ввода
+function ReadlnInteger2(prompt: string): (integer, integer);
+/// Возвращает кортеж из двух значений типа real, введенных с клавиатуры, и переходит на следующую строку ввода
+function ReadlnReal2(prompt: string): (real, real);
+/// Возвращает кортеж из двух значений типа char, введенных с клавиатуры, и переходит на следующую строку ввода
+function ReadlnChar2(prompt: string): (char, char);
+/// Возвращает кортеж из двух значений типа string, введенных с клавиатуры, и переходит на следующую строку ввода
+function ReadlnString2(prompt: string): (string, string);
+
+/// Возвращает кортеж из трёх значений типа integer, введенных с клавиатуры
+function ReadInteger3(prompt: string): (integer, integer, integer);
+/// Возвращает кортеж из трёх значений типа real, введенных с клавиатуры
+function ReadReal3(prompt: string): (real, real, real);
+/// Возвращает кортеж из трёх значений типа char, введенных с клавиатуры
+function ReadChar3(prompt: string): (char, char, char);
+/// Возвращает кортеж из трёх значений типа string, введенных с клавиатуры
+function ReadString3(prompt: string): (string, string, string);
+/// Возвращает кортеж из двух значений типа integer, введенных с клавиатуры, и переходит на следующую строку ввода
+function ReadlnInteger3(prompt: string): (integer, integer, integer);
+/// Возвращает кортеж из двух значений типа real, введенных с клавиатуры, и переходит на следующую строку ввода
+function ReadlnReal3(prompt: string): (real, real, real);
+/// Возвращает кортеж из двух значений типа char, введенных с клавиатуры, и переходит на следующую строку ввода
+function ReadlnChar3(prompt: string): (char, char, char);
+/// Возвращает кортеж из двух значений типа string, введенных с клавиатуры, и переходит на следующую строку ввода
+function ReadlnString3(prompt: string): (string, string, string);
+
+
+/// Выводит приглашение к вводу и возвращает значение типа integer, введенное с клавиатуры
+function ReadInteger(prompt: string): integer;
+/// Выводит приглашение к вводу и возвращает значение типа real, введенное с клавиатуры
+function ReadReal(prompt: string): real;
+/// Выводит приглашение к вводу и возвращает значение типа char, введенное с клавиатуры
+function ReadChar(prompt: string): char;
+/// Выводит приглашение к вводу и возвращает значение типа string, введенное с клавиатуры
+function ReadString(prompt: string): string;
+/// Выводит приглашение к вводу и возвращает значение типа boolean, введенное с клавиатуры
+function ReadBoolean(prompt: string): boolean;
+
+/// Выводит приглашение к вводу и возвращает значение типа integer, введенное с клавиатуры,
+///и осуществляет переход на следующую строку ввода
+function ReadlnInteger(prompt: string): integer;
+/// Выводит приглашение к вводу и возвращает значение типа real, введенное с клавиатуры,
+///и осуществляет переход на следующую строку ввода
+function ReadlnReal(prompt: string): real;
+/// Выводит приглашение к вводу и возвращает значение типа char, введенное с клавиатуры,
+///и осуществляет переход на следующую строку ввода
+function ReadlnChar(prompt: string): char;
+/// Выводит приглашение к вводу и возвращает значение типа string, введенное с клавиатуры,
+///и осуществляет переход на следующую строку ввода
+function ReadlnString(prompt: string): string;
+/// Выводит приглашение к вводу и возвращает значение типа boolean, введенное с клавиатуры,
+///и осуществляет переход на следующую строку ввода
+function ReadlnBoolean(prompt: string): boolean;
+
+
+///--
+procedure ReadShortString(var s: string; n: integer);
+///--
+procedure ReadShortStringFromFile(f: Text; var s: string; n: integer);
+
+///- procedure Read(f: файл; a,b,...);
+/// Вводит значения a,b,... из файла f
+procedure Read(f: Text);
+///--
+procedure Read(f: Text; var x: integer);
+///--
+procedure Read(f: Text; var x: real);
+///--
+procedure Read(f: Text; var x: char);
+///--
+procedure Read(f: Text; var x: string);
+///--
+procedure Read(f: Text; var x: byte);
+///--
+procedure Read(f: Text; var x: shortint);
+///--
+procedure Read(f: Text; var x: smallint);
+///--
+procedure Read(f: Text; var x: word);
+///--
+procedure Read(f: Text; var x: longword);
+///--
+procedure Read(f: Text; var x: int64);
+///--
+procedure Read(f: Text; var x: uint64);
+///--
+procedure Read(f: Text; var x: single);
+///--
+procedure Read(f: Text; var x: boolean);
+
+///- procedure Readln(f: Text; a,b,...);
+/// Вводит значения a,b,... из текстового файла f и осуществляет переход на следующую строку
+procedure Readln(f: Text);
+///--
+procedure Readln(f: Text; var x: string);
+
+/// Возвращает значение типа integer, введенное из текстового файла f
+function ReadInteger(f: Text): integer;
+/// Возвращает значение типа real, введенное из текстового файла f
+function ReadReal(f: Text): real;
+/// Возвращает значение типа char, введенное из текстового файла f
+function ReadChar(f: Text): char;
+/// Возвращает значение типа string, введенное из текстового файла f
+function ReadString(f: Text): string;
+/// Возвращает значение типа boolean, введенное из текстового файла f
+function ReadBoolean(f: Text): boolean;
+
+/// Возвращает значение типа integer, введенное из текстового файла f,
+///и осуществляет переход на следующую строку
+function ReadlnInteger(f: Text): integer;
+/// Возвращает значение типа real, введенное из текстового файла f,
+///и осуществляет переход на следующую строку
+function ReadlnReal(f: Text): real;
+/// Возвращает значение типа char, введенное из текстового файла f,
+///и осуществляет переход на следующую строку
+function ReadlnChar(f: Text): char;
+/// Возвращает значение типа string, введенное из текстового файла f,
+///и осуществляет переход на следующую строку
+function ReadlnString(f: Text): string;
+/// Возвращает значение типа boolean, введенное из текстового файла f,
+///и осуществляет переход на следующую строку
+function ReadlnBoolean(f: Text): boolean;
+
+// -----------------------------------------------------
+//>> Подпрограммы вывода # Write subroutines
+// -----------------------------------------------------
+///- procedure Write(a,b,...);
+/// Выводит значения a,b,... на экран
+procedure Write;
+///--
+procedure Write(obj: object);
+///--
+procedure Write(obj1, obj2: object);
+///--
+procedure Write(params args: array of object);
+
+///- procedure Writeln(a,b,...);
+/// Выводит значения a,b,... на экран и осуществляет переход на новую строку
+///!!- Writeln(a,b,...)
+/// Writes a,b,... to standart output stream and appends newline
+procedure Writeln;
+///--
+procedure Writeln(obj: object);
+///--
+//procedure writeln(ptr: pointer);
+///--
+procedure Writeln(obj1, obj2: object);
+///--
+procedure Writeln(params args: array of object);
+
+///- procedure Write(f: файл; a,b,...);
+/// Выводит значения a,b,... в файл f
+procedure Write(f: Text);
+///--
+procedure Write(f: Text; val: object);
+///--
+procedure Write(f: Text; params args: array of object);
+
+///- procedure Writeln(f: Text; a,b,...);
+/// Выводит значения a,b,... в текстовый файл f и осуществляет переход на новую строку
+procedure Writeln(f: Text);
+///--
+procedure Writeln(f: Text; val: object);
+///--
+procedure Writeln(f: Text; params args: array of object);
+
+/// Выводит значения args согласно форматной строке formatstr
+procedure WriteFormat(formatstr: string; params args: array of object);
+/// Выводит значения args согласно форматной строке formatstr и осуществляет переход на новую строку
+procedure WritelnFormat(formatstr: string; params args: array of object);
+/// Выводит значения args в текстовый файл f согласно форматной строке formatstr
+procedure WriteFormat(f: Text; formatstr: string; params args: array of object);
+/// Выводит значения args в текстовый файл f согласно форматной строке formatstr
+///и осуществляет переход на новую строку
+procedure WritelnFormat(f: Text; formatstr: string; params args: array of object);
+
+///- procedure Print(a,b,...);
+/// Выводит значения a,b,... на экран, после каждого значения выводит пробел
+procedure Print(s: string);
+///--
+procedure Print(params args: array of object);
+///- procedure Print(f: Text; a,b,...);
+/// Выводит значения a,b,... в текстовый файл f, после каждого значения выводит пробел
+procedure Print(f: Text; params args: array of object);
+///- procedure Println(a,b,...);
+/// Выводит значения a,b,... на экран, после каждого значения выводит пробел и переходит на новую строку
+procedure Println(params args: array of object);
+///- procedure Println(f: Text; a,b,...);
+/// Выводит значения a,b,... в текстовый файл f, после каждого значения выводит пробел и переходит на новую строку
+procedure Println(f: Text; params args: array of object);
+
+// -----------------------------------------------------
+//>> Общие подпрограммы для работы с файлами # Common subroutines for files
+// -----------------------------------------------------
+///- procedure Assign(f: файл; name: string);
+/// Связывает файловую переменную с файлом на диске
+procedure Assign(f: AbstractBinaryFile; name: string);
+///- procedure AssignFile(f: файл; name: string);
+/// Связывает файловую переменную с файлом на диске
+procedure AssignFile(f: AbstractBinaryFile; name: string);
+///- procedure Close(f: файл);
+/// Закрывает файл
+procedure Close(f: AbstractBinaryFile);
+///- procedure CloseFile(f: файл);
+/// Закрывает файл
+procedure CloseFile(f: AbstractBinaryFile);
+///- function Eof(f: файл): boolean;
+/// Возвращает True, если достигнут конец файла
+function Eof(f: AbstractBinaryFile): boolean;
+///- procedure Erase(f: файл);
+/// Удаляет файл, связанный с файловой переменной
+procedure Erase(f: AbstractBinaryFile);
+///- procedure Rename(f: файл; newname: string);
+/// Переименовывает файл, связаный с файловой переменной, давая ему имя newname.
+procedure Rename(f: AbstractBinaryFile; newname: string);
+
+// -----------------------------------------------------
+//>> Подпрограммы для работы с текстовыми файлами # Subroutines for text files
+// -----------------------------------------------------
+///--
+procedure Assign(f: Text; name: string);
+///--
+procedure AssignFile(f: Text; name: string);
+///--
+procedure Close(f: Text);
+///--
+procedure CloseFile(f: Text);
+/// Открывает текстовый файл на чтение в кодировке Windows
+procedure Reset(f: Text);
+/// Открывает текстовый файл на чтение в указанной кодировке
+procedure Reset(f: Text; en: Encoding);
+/// Связывает файловую переменную f с именем файла name и открывает текстовый файл на чтение в кодировке Windows
+procedure Reset(f: Text; name: string);
+/// Связывает файловую переменную f с именем файла name и открывает текстовый файл на чтение в указанной кодировке
+procedure Reset(f: Text; name: string; en: Encoding);
+/// Открывает текстовый файл на запись в кодировке Windows.
+///Если файл существовал - он обнуляется, если нет - создается пустой
+procedure Rewrite(f: Text);
+/// Открывает текстовый файл на запись в указанной кодировке.
+///Если файл существовал - он обнуляется, если нет - создается пустой
+procedure Rewrite(f: Text; en: Encoding);
+/// Связывает файловую переменную с именем файла name и открывает текстовый файл f на запись в кодировке Windows.
+///Если файл существовал - он обнуляется, если нет - создается пустой
+procedure Rewrite(f: Text; name: string);
+/// Связывает файловую переменную f с именем файла name и открывает текстовый файл f на запись в указанной кодировке.
+///Если файл существовал - он обнуляется, если нет - создается пустой
+procedure Rewrite(f: Text; name: string; en: Encoding);
+/// Открывает текстовый файл на дополнение в кодировке Windows
+procedure Append(f: Text);
+/// Открывает текстовый файл на дополнение в указанной кодировке
+procedure Append(f: Text; en: Encoding);
+/// Связывает файловую переменную f с именем файла name и открывает текстовый файл на дополнение в кодировке Windows
+procedure Append(f: Text; name: string);
+/// Связывает файловую переменную f с именем файла name и открывает текстовый файл на дополнение в указанной кодировке
+procedure Append(f: Text; name: string; en: Encoding);
+/// Возвращает текстовый файл с именем fname, открытый на чтение в кодировке Windows
+function OpenRead(fname: string): Text;
+/// Возвращает текстовый файл с именем fname, открытый на чтение в указанной кодировке
+function OpenRead(fname: string; en: Encoding): Text;
+/// Возвращает текстовый файл с именем fname, открытый на запись в кодировке Windows
+function OpenWrite(fname: string): Text;
+/// Возвращает текстовый файл с именем fname, открытый на запись в указанной кодировке
+function OpenWrite(fname: string; en: Encoding): Text;
+/// Возвращает текстовый файл с именем fname, открытый на дополнение в кодировке Windows
+function OpenAppend(fname: string): Text;
+/// Возвращает текстовый файл с именем fname, открытый на дополнение в указанной кодировке
+function OpenAppend(fname: string; en: Encoding): Text;
+
+///--
+function Eof(f: Text): boolean;
+/// Возвращает True, если в файле достигнут конец строки
+function Eoln(f: Text): boolean;
+/// Пропускает пробельные символы, после чего возвращает True, если достигнут конец файла
+function SeekEof(f: Text): boolean;
+/// Пропускает пробельные символы, после чего возвращает True, если в файле достигнут конец строки
+function SeekEoln(f: Text): boolean;
+/// Записывает содержимое буфера файла на диск
+procedure Flush(f: Text);
+///--
+procedure Erase(f: Text);
+///--
+procedure Rename(f: Text; newname: string);
+///--
+procedure TextFileInit(var f: Text);
+
+/// Открывает файл, считывает из него строки в кодировке Windows и закрывает файл. В каждый момент в памяти хранится только текущая строка
+function ReadLines(path: string): sequence of string;
+/// Открывает файл, считывает из него строки в указаной кодировке и закрывает файл. В каждый момент в памяти хранится только текущая строка
+function ReadLines(path: string; en: Encoding): sequence of string;
+/// Открывает файл, считывает из него строки в кодировке Windows в виде массива строк, после чего закрывает файл
+function ReadAllLines(path: string): array of string;
+/// Открывает файл, считывает из него строки в указаной кодировке в виде массива строк, после чего закрывает файл
+function ReadAllLines(path: string; en: Encoding): array of string;
+/// Открывает файл, считывает его содержимое в кодировке Windows в виде строки, после чего закрывает файл
+function ReadAllText(path: string): string;
+/// Открывает файл, считывает его содержимое в указаной кодировке в виде строки, после чего закрывает файл
+function ReadAllText(path: string; en: Encoding): string;
+/// Создает новый файл, записывает в него строки из последовательности в кодировке Windows, после чего закрывает файл
+procedure WriteLines(path: string; ss: sequence of string);
+/// Создает новый файл, записывает в него строки из последовательности в указанной кодировке, после чего закрывает файл
+procedure WriteLines(path: string; ss: sequence of string; en: Encoding);
+/// Создает новый файл, записывает в него строки из массива в кодировке Windows, после чего закрывает файл
+procedure WriteAllLines(path: string; ss: array of string);
+/// Создает новый файл, записывает в него строки из массива в указанной кодировке, после чего закрывает файл
+procedure WriteAllLines(path: string; ss: array of string; en: Encoding);
+/// Создает новый файл, записывает в него строку в кодировке Windows, после чего закрывает файл
+procedure WriteAllText(path: string; s: string);
+/// Создает новый файл, записывает в него строку в указанной кодировке, после чего закрывает файл
+procedure WriteAllText(path: string; s: string; en: Encoding);
+
+// -----------------------------------------------------
+//>> Подпрограммы для работы с двоичными файлами # Subroutines for binary files
+// -----------------------------------------------------
+///- procedure Reset(f: двоичный файл);
+/// Открывает двоичный файл на чтение и запись.
+///Двоичный файл - это либо типизированный файл file of T, либо бестиповой файл file
+procedure Reset(f: AbstractBinaryFile);
+///- procedure Reset(f: двоичный файл; name: string);
+/// Связывает файловую переменную f с файлом name на диске и открывает двоичный файл на чтение и запись.
+///Двоичный файл - это либо типизированный файл file of T, либо бестиповой файл file
+procedure Reset(f: AbstractBinaryFile; name: string);
+///- procedure Rewrite(f: двоичный файл);
+/// Открывает двоичный файл на чтение и запись, при этом обнуляя его содержимое. Если файл существовал, он обнуляется.
+///Двоичный файл - это либо типизированный файл file of T, либо бестиповой файл file
+procedure Rewrite(f: AbstractBinaryFile);
+///- procedure Rewrite(f: двоичный файл; name: string);
+/// Связывает файловую переменную f с файлом name на диске и открывает двоичный файл на чтение и запись, при этом обнуляя его содержимое.
+///Двоичный файл - это либо типизированный файл file of T, либо бестиповой файл file
+procedure Rewrite(f: AbstractBinaryFile; name: string);
+///- procedure Truncate(f: двоичный файл);
+/// Усекает двоичный файл, отбрасывая все элементы с позиции файлового указателя.
+///Двоичный файл - это либо типизированный файл file of T, либо бестиповой файл file
+procedure Truncate(f: AbstractBinaryFile);
+
+///--
+procedure Write(f: AbstractBinaryFile; params vals: array of object);
+///--
+procedure Writeln(f: AbstractBinaryFile);
+///--
+procedure Writeln(f: AbstractBinaryFile; val: object);
+///--
+procedure Writeln(f: AbstractBinaryFile; params vals: array of object);
+
+///- function FilePos(f: двоичный файл): int64;
+/// Возвращает текущую позицию файлового указателя в двоичном файле
+function FilePos(f: TypedFile): int64;
+///- function FileSize(f: двоичный файл): int64;
+/// Возвращает количество элементов в двоичном файле
+function FileSize(f: TypedFile): int64;
+///- procedure Seek(f: двоичный файл; n: int64);
+/// Устанавливает текущую позицию файлового указателя в двоичном файле на элемент с данным номером
+procedure Seek(f: TypedFile; n: int64);
+///--
+procedure TypedFileInit(var f: TypedFile; ElementType: System.Type);
+///--
+procedure TypedFileInit(var f: TypedFile; ElementType: System.Type; off: integer; params offs: array of integer);
+///--
+procedure TypedFileInitWithShortString(var f: TypedFile; ElementType: System.Type; off: integer; params offs: array of integer);
+///--
+function TypedFileRead(f: TypedFile): object;
+
+///--
+function FilePos(f: BinaryFile): int64;
+///--
+function FileSize(f: BinaryFile): int64;
+///--
+procedure Seek(f: BinaryFile; n: int64);
+///--
+procedure BinaryFileInit(var f: BinaryFile);
+///--
+function BinaryFileRead(var f: BinaryFile; ElementType: System.Type): object;
+
+// -----------------------------------------------------
+//>> Cистемные подпрограммы # System subroutines
+// -----------------------------------------------------
+/// Возвращает версию PascalABC.NET
+function PascalABCVersion: string;
+/// Возвращает количество параметров командной строки
+function ParamCount: integer;
+/// Возвращает i-тый параметр командной строки
+function ParamStr(i: integer): string;
+/// Возвращает текущий каталог
+function GetDir: string;
+/// Меняет текущий каталог
+procedure ChDir(s: string);
+/// Создает каталог
+procedure MkDir(s: string);
+/// Удаляет каталог
+procedure RmDir(s: string);
+
+/// Создает каталог. Возвращает True, если каталог успешно создан
+function CreateDir(s: string): boolean;
+/// Удаляет файл. Если файл не может быть удален, то возвращает False
+function DeleteFile(s: string): boolean;
+/// Возвращает текущий каталог
+function GetCurrentDir: string;
+/// Удаляет каталог. Возвращает True, если каталог успешно удален
+function RemoveDir(s: string): boolean;
+/// Переименовывает файл name, давая ему новое имя newname. Возвращает True, если файл успешно переименован
+function RenameFile(name, newname: string): boolean;
+/// Устанавливает текущий каталог. Возвращает True, если каталог успешно удален
+function SetCurrentDir(s: string): boolean;
+
+/// Изменяет расширение файла с именем name на newext
+function ChangeFileNameExtension(name, newext: string): string;
+/// Возвращает True, если файл с именем name существует
+function FileExists(name: string): boolean;
+
+/// Выводит в специальном окне стек вызовов подпрограмм если условие не выполняется
+procedure Assert(cond: boolean; sourceFile: string := ''; line: integer := 0);
+/// Выводит в специальном окне диагностическое сообщение и стек вызовов подпрограмм если условие не выполняется
+procedure Assert(cond: boolean; message: string; sourceFile: string := ''; line: integer := 0);
+
+/// Возвращает свободное место в байтах на диске с именем diskname
+function DiskFree(diskname: string): int64;
+/// Возвращает размер в байтах на диске с именем diskname
+function DiskSize(diskname: string): int64;
+/// Возвращает свободное место в байтах на диске disk. disk=0 - текущий диск, disk=1 - диск A: , disk=2 - диск B: и т.д.
+function DiskFree(disk: integer): int64;
+/// Возвращает размер в байтах на диске disk. disk=0 - текущий диск, disk=1 - диск A: , disk=2 - диск B: и т.д.
+function DiskSize(disk: integer): int64;
+/// Возвращает количество миллисекунд с момента начала работы программы
+function Milliseconds: integer;
+/// Возвращает количество миллисекунд с момента последнего вызова Milliseconds или MillisecondsDelta
+function MillisecondsDelta: integer;
+
+/// Завершает работу программы
+procedure Halt;
+/// Завершает работу программы, возвращая код ошибки exitCode
+procedure Halt(exitCode: integer);
+
+/// Делает паузу на ms миллисекунд
+procedure Sleep(ms: integer);
+/// Возващает имя запущенного .exe-файла
+function GetEXEFileName: string;
+/// Преобразует указатель к строковому представлению
+function PointerToString(p: pointer): string;
+
+/// Запускает программу или документ с именем filename
+procedure Exec(filename: string);
+/// Запускает программу или документ с именем filename и параметрами командной строки args
+procedure Exec(filename: string; args: string);
+/// Запускает программу или документ с именем filename
+procedure Execute(filename: string);
+/// Запускает программу или документ с именем filename и параметрами командной строки args
+procedure Execute(filename: string; args: string);
+
+/// Возвращает последовательность имен файлов по заданному пути, соответствующих шаблону поиска
+function EnumerateFiles(path: string; searchPattern: string := '*.*'): sequence of string;
+/// Возвращает последовательность имен файлов по заданному пути, соответствующих шаблону поиска, включая подкаталоги
+function EnumerateAllFiles(path: string; searchPattern: string := '*.*'): sequence of string;
+/// Возвращает последовательность имен каталогов по заданному пути
+function EnumerateDirectories(path: string): sequence of string;
+/// Возвращает последовательность имен каталогов по заданному пути, включая подкаталоги
+function EnumerateAllDirectories(path: string): sequence of string;
+
+///-procedure New(var p: ^T);
+/// Выделяет динамическую память размера sizeof(T) и возвращает в переменной p указатель на нее. Тип T должен быть размерным
+//procedure New(var p: ^T);
+
+///-procedure Dispose(var p: ^T);
+/// Освобождает динамическую память, на которую указывает p
+//procedure Dispose(var p: ^T);
+
+
+// -----------------------------------------------------
+//>> Подпрограммы для работы с именами файлов # Functions for file names
+// -----------------------------------------------------
+/// Выделяет имя файла из полного имени файла fname
+function ExtractFileName(fname: string): string;
+/// Выделяет расширение из полного имени файла fname
+function ExtractFileExt(fname: string): string;
+/// Выделяет путь из полного имени файла fname
+function ExtractFilePath(fname: string): string;
+/// Выделяет имя диска и путь из полного имени файла fname
+function ExtractFileDir(fname: string): string;
+/// Выделяет путь из полного имени файла fname
+function ExtractFileDrive(fname: string): string;
+/// Возвращает полное имя файла fname
+function ExpandFileName(fname: string): string;
+
+// -----------------------------------------------------
+//>> Математические подпрограммы # Math subroutines
+// -----------------------------------------------------
+///-function Sign(x: число): число;
+/// Возвращает знак числа x
+function Sign(x: shortint): integer;
+///--
+function Sign(x: smallint): integer;
+///--
+function Sign(x: integer): integer;
+///--
+function Sign(x: BigInteger): integer;
+///--
+function Sign(x: longword): integer;
+///--
+function Sign(x: int64): integer;
+///--
+function Sign(x: uint64): integer;
+///--
+function Sign(x: real): integer;
+///-function Abs(x: число): число;
+/// Возвращает модуль числа x
+function Abs(x: integer): integer;
+///--
+function Abs(x: shortint): shortint;
+///--
+function Abs(x: smallint): smallint;
+///--
+function Abs(x: BigInteger): BigInteger;
+///--
+function Abs(x: longword): longword;
+///--
+function Abs(x: int64): int64;
+///--
+function Abs(x: uint64): uint64;
+///--
+function Abs(x: real): real;
+///--
+function Abs(x: single): single;
+/// Возвращает синус числа x
+function Sin(x: real): real;
+/// Возвращает гиперболический синус числа x
+function Sinh(x: real): real;
+/// Возвращает косинус числа x
+/// !! Returns the cosine of number x
+function Cos(x: real): real;
+/// Возвращает гиперболический косинус числа x
+function Cosh(x: real): real;
+/// Возвращает тангенс числа x
+function Tan(x: real): real;
+/// Возвращает гиперболический тангенс числа x
+function Tanh(x: real): real;
+/// Возвращает арксинус числа x
+function ArcSin(x: real): real;
+/// Возвращает арккосинус числа x
+function ArcCos(x: real): real;
+/// Возвращает арктангенс числа x
+function ArcTan(x: real): real;
+/// Возвращает экспоненту числа x
+function Exp(x: real): real;
+/// Возвращает натуральный логарифм числа x
+function Ln(x: real): real;
+/// Возвращает натуральный логарифм числа x
+function Log(x: real): real;
+/// Возвращает логарифм числа x по основанию 2
+function Log2(x: real): real;
+/// Возвращает десятичный логарифм числа x
+function Log10(x: real): real;
+/// Возвращает логарифм числа x по основанию base
+function LogN(base, x: real): real;
+/// Возвращает квадратный корень числа x
+function Sqrt(x: real): real;
+///-function Sqr(x: число): число;
+/// Возвращает квадрат числа x
+function Sqr(x: integer): int64;
+///--
+function Sqr(x: shortint): integer;
+///--
+function Sqr(x: smallint): integer;
+///--
+function Sqr(x: BigInteger): BigInteger;
+///--
+function Sqr(x: longword): uint64;
+///--
+function Sqr(x: int64): int64;
+///--
+function Sqr(x: uint64): uint64;
+///--
+function Sqr(x: real): real;
+/// Возвращает x в степени y
+function Power(x, y: real): real;
+/// Возвращает x в целой степени n
+function Power(x: real; n: integer): real;
+/// Возвращает x в степени y
+function Power(x: BigInteger; y: integer): BigInteger;
+/// Возвращает x, округленное до ближайшего целого. Если вещественное находится посередине между двумя целыми,
+///то округление осуществляется к ближайшему четному (банковское округление): Round(2.5)=2, Round(3.5)=4
+function Round(x: real): integer;
+/// Возвращает x, округленное до ближайшего вещественного с digits знаками после десятичной точки
+function Round(x: real; digits: integer): real;
+/// Возвращает x, округленное до ближайшего длинного целого
+function RoundBigInteger(x: real): BigInteger;
+/// Возвращает целую часть вещественного числа x
+function Trunc(x: real): integer;
+/// Возвращает целую часть вещественного числа x как длинное целое
+function TruncBigInteger(x: real): BigInteger;
+/// Возвращает целую часть числа x
+function Int(x: real): real;
+/// Возвращает дробную часть числа x
+function Frac(x: real): real;
+/// Возвращает наибольшее целое <= x
+function Floor(x: real): integer;
+/// Возвращает наименьшее целое >= x
+function Ceil(x: real): integer;
+/// Переводит радианы в градусы
+function RadToDeg(x: real): real;
+/// Переводит градусы в радианы
+function DegToRad(x: real): real;
+
+/// Инициализирует датчик псевдослучайных чисел
+procedure Randomize;
+/// Инициализирует датчик псевдослучайных чисел, используя значение seed. При одном и том же seed генерируются одинаковые псевдослучайные последовательности
+procedure Randomize(seed: integer);
+/// Возвращает случайное целое в диапазоне от 0 до maxValue-1
+function Random(maxValue: integer): integer;
+/// Возвращает случайное вещественное в диапазоне [0,maxValue)
+function Random(maxValue: real): real;
+/// Возвращает случайное целое в диапазоне от a до b
+function Random(a, b: integer): integer;
+/// Возвращает случайное вещественное в диапазоне [a,b)
+function Random(a, b: real): real;
+/// Возвращает случайное вещественное в диапазоне [0..1)
+function Random: real;
+/// Возвращает кортеж из двух случайных целых в диапазоне от 0 до maxValue-1
+function Random2(maxValue: integer): (integer, integer);
+/// Возвращает кортеж из двух случайных вещественных в диапазоне [0,maxValue)
+function Random2(maxValue: real): (real, real);
+/// Возвращает кортеж из двух случайных целых в диапазоне от a до b
+function Random2(a, b: integer): (integer, integer);
+/// Возвращает кортеж из двух случайных вещественных в диапазоне [a,b)
+function Random2(a, b: real): (real, real);
+/// Возвращает кортеж из двух случайных вещественных в диапазоне [0..1)
+function Random2: (real, real);
+/// Возвращает кортеж из трех случайных целых в диапазоне от 0 до maxValue-1
+function Random3(maxValue: integer): (integer, integer, integer);
+/// Возвращает кортеж из трех случайных вещественных в диапазоне [0,maxValue)
+function Random3(maxValue: real): (real, real, real);
+/// Возвращает кортеж из трех случайных целых в диапазоне от a до b
+function Random3(a, b: integer): (integer, integer, integer);
+/// Возвращает кортеж из трех случайных вещественных в диапазоне [a,b)
+function Random3(a, b: real): (real, real, real);
+/// Возвращает кортеж из трех случайных вещественных в диапазоне [0..1)
+function Random3: (real, real, real);
+
+///-function Max(a: число, b: число): число;
+/// Возвращает максимальное из чисел a,b
+function Max(a, b: byte): byte;
+///--
+function Max(a, b: shortint): shortint;
+///--
+function Max(a, b: smallint): smallint;
+///--
+function Max(a, b: word): word;
+///--
+function Max(a, b: integer): integer;
+///--
+function Max(a, b: BigInteger): BigInteger;
+///--
+function Max(a, b: longword): longword;
+///--
+function Max(a, b: int64): int64;
+///--
+function Max(a, b: uint64): uint64;
+///--
+function Max(a, b: real): real;
+///-function Min(a: число, b: число): число;
+/// Возвращает минимальное из чисел a,b
+function Min(a, b: byte): byte;
+///--
+function Min(a, b: shortint): shortint;
+///--
+function Min(a, b: word): word;
+///--
+function Min(a, b: smallint): smallint;
+///--
+function Min(a, b: integer): integer;
+///--
+function Min(a, b: BigInteger): BigInteger;
+///--
+function Min(a, b: longword): longword;
+///--
+function Min(a, b: int64): int64;
+///--
+function Min(a, b: uint64): uint64;
+///--
+function Min(a, b: real): real;
+///-function Odd(i: целое): boolean;
+/// Возвращает True, если i нечетно, и False в противном случае
+function Odd(i: byte): boolean;
+///--
+function Odd(i: shortint): boolean;
+///--
+function Odd(i: word): boolean;
+///--
+function Odd(i: smallint): boolean;
+///--
+function Odd(i: integer): boolean;
+///--
+function Odd(i: BigInteger): boolean;
+///--
+function Odd(i: longword): boolean;
+///--
+function Odd(i: int64): boolean;
+///--
+function Odd(i: uint64): boolean;
+
+// -----------------------------------------------------
+//>> Подпрограммы для работы с комплексными числами # Functions for Complex numbers
+// -----------------------------------------------------
+/// Конструирует комплексное число с вещественной частью re и мнимой частью im
+function Cplx(re, im: real): Complex;
+/// Конструирует комплексное число по полярным координатам
+function CplxFromPolar(magnitude, phase: real): Complex;
+/// Возвращает квадратный корень из комплексного числа
+function Sqrt(c: Complex): Complex;
+/// Возвращает модуль комплексного числа
+function Abs(c: Complex): Complex;
+/// Возвращает комплексно сопряженное число
+function Conjugate(c: Complex): Complex;
+/// Возвращает косинус комплексного числа
+function Cos(c: Complex): Complex;
+/// Возвращает экспоненту комплексного числа
+function Exp(c: Complex): Complex;
+/// Возвращает натуральный логарифм комплексного числа
+function Ln(c: Complex): Complex;
+/// Возвращает натуральный логарифм комплексного числа
+function Log(c: Complex): Complex;
+/// Возвращает десятичный логарифм комплексного числа
+function Log10(c: Complex): Complex;
+/// Возвращает степень комплексного числа
+function Power(c, power: Complex): Complex;
+/// Возвращает синус комплексного числа
+function Sin(c: Complex): Complex;
+
+// -----------------------------------------------------
+//>> Подпрограммы для работы со стандартными множествами # Subroutines for set of T
+// -----------------------------------------------------
+///- procedure Include(var s: set of T; element: T);
+///Добавляет элемент element во множество s
+procedure Include(var s: TypedSet; el: object);
+///- procedure Exclude(var s: set of T; element: T);
+///Удаляет элемент element из множества s
+procedure Exclude(var s: TypedSet; el: object);
+
+// -----------------------------------------------------
+//>> Подпрограммы для работы с символами # Subroutines for char
+// -----------------------------------------------------
+/// Увеличивает код символа c на 1
+procedure Inc(var c: char);
+/// Увеличивает код символа c на n
+procedure Inc(var c: char; n: integer);
+/// Уменьшает код символа c на 1
+procedure Dec(var c: char);
+/// Уменьшает код символа c на n
+procedure Dec(var c: char; n: integer);
+/// Возвращает предшествующий x символ
+function Pred(x: char): char;
+/// Возвращает следующий за x символ
+function Succ(x: char): char;
+/// Преобразует код в символ в кодировке Windows
+function ChrAnsi(a: byte): char;
+/// Преобразует символ в код в кодировке Windows
+function OrdAnsi(a: char): byte;
+/// Преобразует код в символ в кодировке Unicode
+function Chr(a: word): char;
+/// Преобразует символ в код в кодировке Unicode
+function Ord(a: char): word;
+/// Преобразует код в символ в кодировке Unicode
+function ChrUnicode(a: word): char;
+/// Преобразует символ в код в кодировке Unicode
+function OrdUnicode(a: char): word;
+/// Преобразует символ в верхний регистр
+function UpperCase(ch: char): char;
+/// Преобразует символ в нижний регистр
+function LowerCase(ch: char): char;
+/// Преобразует символ в верхний регистр
+function UpCase(ch: char): char;
+/// Преобразует символ в нижний регистр
+function LowCase(ch: char): char;
+
+// -----------------------------------------------------
+//>> Подпрограммы для работы со строками # Subroutines for string
+// -----------------------------------------------------
+///-procedure Str(i: целое; var s: string);
+/// Преобразует целое значение i к строковому представлению и записывает результат в s
+procedure Str(i: integer; var s: string);
+///--
+procedure Str(i: longword; var s: string);
+///--
+procedure Str(i: int64; var s: string);
+///--
+procedure Str(i: uint64; var s: string);
+/// Преобразует вещественное значение r к строковому представлению и записывает результат в s
+procedure Str(r: real; var s: string);
+/// Преобразует вещественное значение r к строковому представлению и записывает результат в s
+procedure Str(r: single; var s: string);
+///--
+procedure Str(s1: string; var s: string);
+
+/// Возвращает позицию подстроки subs в строке s. Если не найдена, возвращает 0
+function Pos(subs, s: string; from: integer := 1): integer;
+/// Возвращает позицию подстроки subs в строке s начиная с позиции from. Если не найдена, возвращает 0
+function PosEx(subs, s: string; from: integer := 1): integer;
+/// Возвращает позицию последнего вхождения подстроки subs в строке s. Если не найдена, возвращает 0
+function LastPos(subs, s: string): integer;
+/// Возвращает позицию последнего вхождения подстроки subs в строке s начиная с позиции from. Если не найдена, возвращает 0
+function LastPos(subs, s: string; from: integer): integer;
+
+/// Возвращает длину строки
+function Length(s: string): integer;
+/// Устанавливает длину строки s равной n
+procedure SetLength(var s: string; n: integer);
+///--
+procedure SetLengthForShortString(var s: string; n, sz: integer);
+/// Вставляет подстроку source в строку s с позиции index
+procedure Insert(source: string; var s: string; index: integer);
+///--
+procedure InsertInShortString(source: string; var s: string; index, n: integer);
+/// Удаляет из строки s count символов с позиции index
+procedure Delete(var s: string; index, count: integer);
+/// Возвращает подстроку строки s длины count с позиции index
+function Copy(s: string; index, count: integer): string;
+///-function Concat(s1,s2,...): string;
+/// Возвращает строку, являющуюся результатом слияния строк s1,s2,...
+function Concat(params strs: array of string): string;
+/// Возвращает строку, являющуюся результатом слияния строк s1 и s2
+function Concat(s1, s2: string): string;
+/// Возвращает строку в нижнем регистре
+function LowerCase(s: string): string;
+/// Возвращает строку в верхнем регистре
+function UpperCase(s: string): string;
+/// Возвращает строку, состоящую из count символов ch
+function StringOfChar(ch: char; count: integer): string;
+/// Возвращает инвертированную строку
+function ReverseString(s: string): string;
+/// Возвращает инвертированную строку в диапазоне длины length начиная с индекса index
+function ReverseString(s: string; index,length: integer): string;
+/// Сравнивает строки. Возвращает значение < 0 если s1 0 если s1>s2 и = 0 если s1=s2
+function CompareStr(s1, s2: string): integer;
+/// Возвращает первые count символов строки s
+function LeftStr(s: string; count: integer): string;
+/// Возвращает последние count символов строки s
+function RightStr(s: string; count: integer): string;
+
+/// Возвращает строку с удаленными начальными и конечными пробелами
+function Trim(s: string): string;
+/// Возвращает строку с удаленными начальными пробелами
+function TrimLeft(s: string): string;
+/// Возвращает строку с удаленными конечными пробелами
+function TrimRight(s: string): string;
+
+/// Преобразует строковое представление целого числа к числовому значению
+function StrToInt(s: string): integer;
+/// Преобразует строковое представление целого числа к числовому значению
+function StrToInt64(s: string): int64;
+/// Преобразует строковое представление вещественного числа к числовому значению
+function StrToFloat(s: string): real;
+/// Преобразует строковое представление вещественного числа к числовому значению
+function StrToReal(s: string): real;
+/// Преобразует строковое представление s целого числа к числовому значению и записывает его в value.
+///При невозможности преобразования возвращается False
+function TryStrToInt(s: string; var value: integer): boolean;
+/// Преобразует строковое представление s целого числа к числовому значению и записывает его в value.
+///При невозможности преобразования возвращается False
+function TryStrToInt64(s: string; var value: int64): boolean;
+/// Преобразует строковое представление s вещественного числа к числовому значению и записывает его в value.
+///При невозможности преобразования возвращается False
+function TryStrToFloat(s: string; var value: real): boolean;
+/// Преобразует строковое представление s вещественного числа к числовому значению и записывает его в value.
+///При невозможности преобразования возвращается False
+function TryStrToFloat(s: string; var value: single): boolean;
+/// Преобразует строковое представление s вещественного числа к числовому значению и записывает его в value.
+///При невозможности преобразования возвращается False
+function TryStrToReal(s: string; var value: real): boolean;
+/// Преобразует строковое представление s вещественного числа к числовому значению и записывает его в value.
+///При невозможности преобразования возвращается False
+function TryStrToSingle(s: string; var value: single): boolean;
+/// Считывает целое из строки начиная с позиции from и устанавливает from за считанным значением
+function ReadIntegerFromString(s: string; var from: integer): integer;
+/// Считывает вещественное из строки начиная с позиции from и устанавливает from за считанным значением
+function ReadRealFromString(s: string; var from: integer): real;
+/// Считывает из строки последовательность символов до пробельного символа начиная с позиции from и устанавливает from за считанным значением
+function ReadWordFromString(s: string; var from: integer): string;
+/// Возвращает True если достигнут конец строки или в строке остались только пробельные символы и False в противном случае
+function StringIsEmpty(s: string; var from: integer): boolean;
+/// Считывает целое из строки начиная с позиции from и устанавливает from за считанным значением.
+///Возвращает True если считывание удачно и False в противном случае
+function TryReadIntegerFromString(s: string; var from: integer; var res: integer): boolean;
+/// Считывает вещественное из строки начиная с позиции from и устанавливает from за считанным значением.
+///Возвращает True если считывание удачно и False в противном случае
+function TryReadRealFromString(s: string; var from: integer; var res: real): boolean;
+
+///-procedure Val(s: string; var value: число; var err: integer);
+/// Преобразует строковое представление s целого числа к числовому значению и записывает его в переменную value.
+///Если преобразование успешно, то err=0, иначе err>0
+procedure Val(s: string; var value: integer; var err: integer);
+///--
+procedure Val(s: string; var value: shortint; var err: integer);
+///--
+procedure Val(s: string; var value: smallint; var err: integer);
+///--
+procedure Val(s: string; var value: int64; var err: integer);
+///--
+procedure Val(s: string; var value: byte; var err: integer);
+///--
+procedure Val(s: string; var value: word; var err: integer);
+///--
+procedure Val(s: string; var value: longword; var err: integer);
+///--
+procedure Val(s: string; var value: uint64; var err: integer);
+///--
+procedure Val(s: string; var value: real; var err: integer);
+///--
+procedure Val(s: string; var value: single; var err: integer);
+
+/// Преобразует целое число к строковому представлению
+function IntToStr(a: integer): string;
+/// Преобразует целое число к строковому представлению
+function IntToStr(a: int64): string;
+/// Преобразует вещественное число к строковому представлению
+function FloatToStr(a: real): string;
+
+/// Возвращает отформатированную строку, построенную по форматной строке и списку форматируемых параметров
+function Format(formatstring: string; params pars: array of object): string;
+
+// -----------------------------------------------------
+//>> Общие подпрограммы # Common subroutines
+// -----------------------------------------------------
+/// Увеличивает значение переменной i на 1
+procedure Inc(var i: integer);
+/// Увеличивает значение переменной i на n
+procedure Inc(var i: integer; n: integer);
+/// Уменьшает значение переменной i на 1
+procedure Dec(var i: integer);
+/// Уменьшает значение переменной i на n
+procedure Dec(var i: integer; n: integer);
+///-procedure Inc(var e: перечислимый тип);
+/// Увеличивает значение перечислимого типа на 1
+procedure Inc(var b: byte);
+///-procedure Inc(var e: перечислимый тип; n: integer);
+/// Увеличивает значение перечислимого типа на n
+procedure Inc(var b: byte; n: integer);
+///-procedure Dec(var e: перечислимый тип);
+/// Уменьшает значение перечислимого типа на 1
+procedure Dec(var b: byte);
+///-procedure Dec(var e: перечислимый тип; n: integer);
+/// Уменьшает значение перечислимого типа на n
+procedure Dec(var b: byte; n: integer);
+///--
+procedure Inc(var f: boolean);
+///--
+procedure Dec(var f: boolean);
+///-function Ord(a: целое): целое;
+/// Возвращает порядковый номер значения a
+function Ord(a: integer): integer;
+///-function Ord(a: перечислимый тип): integer;
+/// Возвращает порядковый номер значения a
+function Ord(a: longword): longword;
+///--
+function Ord(a: int64): int64;
+///--
+function Ord(a: uint64): uint64;
+///--
+function Ord(a: boolean): integer;
+
+///-function Succ(x: целое): целое;
+/// Возвращает следующее за x значение
+function Succ(x: integer): integer;
+///-function Succ(x: перечислимый тип): перечислимый тип;
+/// Возвращает следующее за x значение
+function Succ(x: byte): byte;
+///--
+function Succ(x: shortint): shortint;
+///--
+function Succ(x: smallint): smallint;
+///--
+function Succ(x: word): word;
+///--
+function Succ(x: longword): longword;
+///--
+function Succ(x: int64): int64;
+///--
+function Succ(x: uint64): uint64;
+///--
+function Succ(x: boolean): boolean;
+
+///-function Pred(x: целое): целое;
+/// Возвращает предшествующее x значение
+function Pred(x: integer): integer;
+///-function Pred(x: перечислимый тип): перечислимый тип;
+/// Возвращает предшествующее x значение
+function Pred(x: byte): byte;
+///--
+function Pred(x: shortint): shortint;
+///--
+function Pred(x: smallint): smallint;
+///--
+function Pred(x: word): word;
+///--
+function Pred(x: longword): longword;
+///--
+function Pred(x: int64): int64;
+///--
+function Pred(x: uint64): uint64;
+///--
+function Pred(x: boolean): boolean;
+
+/// Меняет местами значения двух переменных
+procedure Swap(var a, b: T);
+/// Возвращает True, если достигнут конец строки
+function Eoln: boolean;
+/// Возвращает True, если достигнут конец потока ввода
+function Eof: boolean;
+
+// -----------------------------------------------------
+//>> Подпрограммы для работы с динамическими массивами # Subroutines for array of T
+// -----------------------------------------------------
+///- function Low(a: array of T): integer;
+/// Возвращает 0
+function Low(i: System.Array): integer;
+///- function High(a: array of T): integer;
+/// Возвращает верхнюю границу динамического массива
+function High(i: System.Array): integer;
+///- function Length(a: array of T): integer;
+/// Возвращает длину динамического массива
+function Length(a: System.Array): integer;
+///- function Length(a: array of T; dim: integer): integer;
+/// Возвращает длину динамического массива по размерности dim
+function Length(a: System.Array; dim: integer): integer;
+///- procedure SetLength(var a: array of T);
+/// Устанавливает длину одномерного динамического массива. Старое содержимое сохраняется
+//procedure SetLength(var a: System.Array);
+///- procedure SetLength(var a: array of T; n1,n2,...: integer);
+/// Устанавливает размеры n-мерного динамического массива. Старое содержимое сохраняется
+//procedure SetLength(var a: System.Array);
+///- function Copy(a: array of T): array of T;
+/// Создаёт копию динамического массива
+function Copy(a: System.Array): System.Array;
+/// Сортирует динамический массив по возрастанию
+procedure Sort(a: array of T);
+/// Сортирует динамический массив по критерию сортировки, задаваемому функцией сравнения cmp
+procedure Sort(a: array of T; cmp: (T,T)->integer);
+/// Сортирует динамический массив по критерию сортировки, задаваемому функцией сравнения less
+procedure Sort(a: array of T; less: (T,T)->boolean);
+/// Сортирует список по возрастанию
+procedure Sort(l: List);
+/// Сортирует список по критерию сортировки, задаваемому функцией сравнения cmp
+procedure Sort(l: List; cmp: (T,T)->integer);
+/// Сортирует список по критерию сортировки, задаваемому функцией сравнения less
+procedure Sort(l: List; less: (T,T)->boolean);
+/// Изменяет порядок элементов в динамическом массиве на противоположный
+procedure Reverse(a: array of T);
+/// Изменяет порядок элементов на противоположный в диапазоне динамического массива длины count, начиная с индекса index
+procedure Reverse(a: array of T; index, count: integer);
+/// Изменяет порядок элементов в списке на противоположный
+procedure Reverse(a: List);
+/// Изменяет порядок элементов на противоположный в диапазоне списка длины count, начиная с индекса index
+procedure Reverse(a: List; index, count: integer);
+/// Перемешивает динамический массив случайным образом
+procedure Shuffle(a: array of T);
+/// Перемешивает список случайным образом
+procedure Shuffle(l: List);
+
+// -----------------------------------------------------
+//>> Подпрограммы для генерации последовательностей # Subroutines for sequence generation
+// -----------------------------------------------------
+/// Возвращает последовательность целых от a до b
+function Range(a, b: integer): sequence of integer;
+/// Возвращает последовательность символов от c1 до c2
+function Range(c1, c2: char): sequence of char;
+/// Возвращает последовательность вещественных в точках разбиения отрезка [a,b] на n равных частей (Используйте Partition)
+function Range(a, b: real; n: integer): sequence of real;
+/// Возвращает последовательность вещественных в точках разбиения отрезка [a,b] на n равных частей
+function Partition(a, b: real; n: integer): sequence of real;
+/// Возвращает последовательность целых от a до b с шагом step
+function Range(a, b, step: integer): sequence of integer;
+/// Возвращает последовательность указанных элементов
+function Seq(params a: array of T): sequence of T;
+/// Возвращает последовательность из n случайных целых элементов
+function SeqRandom(n: integer := 10; a: integer := 0; b: integer := 100): sequence of integer;
+/// Возвращает последовательность из n случайных целых элементов
+function SeqRandomInteger(n: integer := 10; a: integer := 0; b: integer := 100): sequence of integer;
+/// Возвращает последовательность из n случайных вещественных элементов
+function SeqRandomReal(n: integer := 10; a: real := 0; b: real := 10): sequence of real;
+/// Возвращает последовательность из count элементов, заполненных значениями f(i)
+function SeqGen(count: integer; f: integer->T): sequence of T;
+/// Возвращает последовательность из count элементов, заполненных значениями f(i), начиная с i=from
+function SeqGen(count: integer; f: integer->T; from: integer): sequence of T;
+/// Возвращает последовательность из count элементов, начинающуюся с first, с функцией next перехода от предыдущего к следующему
+function SeqGen(count: integer; first: T; next: T->T): sequence of T;
+/// Возвращает последовательность из count элементов, начинающуюся с first и second,
+///с функцией next перехода от двух предыдущих к следующему
+function SeqGen(count: integer; first, second: T; next: (T,T) ->T): sequence of T;
+/// Возвращает последовательность элементов с начальным значением first,
+///функцией next перехода от предыдущего к следующему и условием pred продолжения последовательности
+function SeqWhile(first: T; next: T->T; pred: T->boolean): sequence of T;
+/// Возвращает последовательность элементов, начинающуюся с first и second,
+///с функцией next перехода от двух предыдущих к следующему и условием pred продолжения последовательности
+function SeqWhile(first, second: T; next: (T,T) ->T; pred: T->boolean): sequence of T;
+/// Возвращает последовательность из count элементов x
+function SeqFill(count: integer; x: T): sequence of T;
+
+/// Возвращает последовательность из n целых, введенных с клавиатуры
+function ReadSeqInteger(n: integer): sequence of integer;
+/// Возвращает последовательность из n вещественных, введенных с клавиатуры
+function ReadSeqReal(n: integer): sequence of real;
+/// Возвращает последовательность из n строк, введенных с клавиатуры
+function ReadSeqString(n: integer): sequence of string;
+
+/// Выводит приглашение к вводу и возвращает последовательность из n целых, введенных с клавиатуры
+function ReadSeqInteger(prompt: string; n: integer): sequence of integer;
+/// Выводит приглашение к вводу и возвращает последовательность из n вещественных, введенных с клавиатуры
+function ReadSeqReal(prompt: string; n: integer): sequence of real;
+/// Выводит приглашение к вводу и возвращает последовательность из n строк, введенных с клавиатуры
+function ReadSeqString(prompt: string; n: integer): sequence of string;
+
+/// Возвращает последовательность целых, вводимых с клавиатуры пока выполняется определенное условие
+function ReadSeqIntegerWhile(cond: integer->boolean): sequence of integer;
+/// Возвращает последовательность вещественных, вводимых с клавиатуры пока выполняется определенное условие
+function ReadSeqRealWhile(cond: real->boolean): sequence of real;
+/// Возвращает последовательность строк, вводимых с клавиатуры пока выполняется определенное условие
+function ReadSeqStringWhile(cond: string->boolean): sequence of string;
+
+/// Выводит приглашение к вводу и возвращает последовательность целых, вводимых с клавиатуры пока выполняется определенное условие
+function ReadSeqIntegerWhile(prompt: string; cond: integer->boolean): sequence of integer;
+/// Выводит приглашение к вводу и возвращает последовательность вещественных, вводимых с клавиатуры пока выполняется определенное условие
+function ReadSeqRealWhile(prompt: string; cond: real->boolean): sequence of real;
+/// Выводит приглашение к вводу и возвращает последовательность строк, вводимых с клавиатуры пока выполняется определенное условие
+function ReadSeqStringWhile(prompt: string; cond: string->boolean): sequence of string;
+
+// -----------------------------------------------------
+//>> Подпрограммы для создания динамических массивов # Subroutines for array of T generation
+// -----------------------------------------------------
+/// Возвращает массив, заполненный указанными значениями
+function Arr(params a: array of T): array of T;
+/// Возвращает массив, заполненный значениями из последовательнсти
+function Arr(a: sequence of T): array of T;
+/// Возвращает массив размера n, заполненный случайными целыми значениями
+function ArrRandom(n: integer := 10; a: integer := 0; b: integer := 100): array of integer;
+/// Возвращает массив размера n, заполненный случайными целыми значениями
+function ArrRandomInteger(n: integer := 10; a: integer := 0; b: integer := 100): array of integer;
+/// Возвращает массив размера n, заполненный случайными вещественными значениями
+function ArrRandomReal(n: integer := 10; a: real := 0; b: real := 10): array of real;
+/// Возвращает массив из count элементов, заполненных значениями gen(i)
+function ArrGen(count: integer; gen: integer->T): array of T;
+/// Возвращает массив из count элементов, заполненных значениями gen(i), начиная с i=from
+function ArrGen(count: integer; gen: integer->T; from: integer): array of T;
+/// Возвращает массив из count элементов, начинающихся с first, с функцией next перехода от предыдущего к следующему
+function ArrGen(count: integer; first: T; next: T->T): array of T;
+/// Возвращает массив из count элементов, начинающихся с first и second, с функцией next перехода от двух предыдущих к следующему
+function ArrGen(count: integer; first, second: T; next: (T,T) ->T): array of T;
+/// Возвращает массив из count элементов x
+function ArrFill(count: integer; x: T): array of T;
+
+/// Возвращает массив из n целых, введенных с клавиатуры
+function ReadArrInteger(n: integer): array of integer;
+/// Возвращает массив из n вещественных, введенных с клавиатуры
+function ReadArrReal(n: integer): array of real;
+/// Возвращает массив из n строк, введенных с клавиатуры
+function ReadArrString(n: integer): array of string;
+
+/// Выводит приглашение к вводу и возвращает массив из n целых, введенных с клавиатуры
+function ReadArrInteger(prompt: string; n: integer): array of integer;
+/// Выводит приглашение к вводу и возвращает массив из n вещественных, введенных с клавиатуры
+function ReadArrReal(prompt: string; n: integer): array of real;
+/// Выводит приглашение к вводу и возвращает массив из n строк, введенных с клавиатуры
+function ReadArrString(prompt: string; n: integer): array of string;
+
+// -----------------------------------------------------
+//>> Подпрограммы для создания двумерных динамических массивов # Subroutines for matrixes
+// -----------------------------------------------------
+/// Возвращает двумерный массив размера m x n, заполненный указанными значениями по строкам
+function Matr(m,n: integer; params data: array of T): array [,] of T;
+/// Возвращает двумерный массив размера m x n, заполненный случайными целыми значениями
+function MatrRandom(m: integer := 5; n: integer := 5; a: integer := 0; b: integer := 100): array [,] of integer;
+/// Возвращает двумерный массив размера m x n, заполненный случайными целыми значениями
+function MatrRandomInteger(m: integer := 5; n: integer := 5; a: integer := 0; b: integer := 100): array [,] of integer;
+/// Возвращает двумерный массив размера m x n, заполненный случайными вещественными значениями
+function MatrRandomReal(m: integer := 5; n: integer := 5; a: real := 0; b: real := 10): array [,] of real;
+/// Возвращает двумерный массив размера m x n, заполненный элементами x
+function MatrFill(m, n: integer; x: T): array [,] of T;
+/// Возвращает двумерный массив размера m x n, заполненный элементами x
+function MatrGen(m, n: integer; gen: (integer,integer)->T): array [,] of T;
+/// Транспонирует двумерный массив
+function Transpose(a: array [,] of T): array [,] of T;
+/// Возвращает матрицу m на n целых, введенных с клавиатуры
+function ReadMatrInteger(m, n: integer): array [,] of integer;
+/// Возвращает матрицу m на n вещественных, введенных с клавиатуры
+function ReadMatrReal(m, n: integer): array [,] of real;
+
+// -----------------------------------------------------
+//>> Подпрограммы для создания кортежей # Subroutines for tuple generation
+// -----------------------------------------------------
+///- function Rec(x1: T1, x2: T2,...): (T1,T2,...);
+/// Возвращает кортеж из элементов разных типов
+function Rec(x1: T1; x2: T2): System.Tuple;
+///--
+function Rec(x1: T1; x2: T2; x3: T3): (T1, T2, T3);
+///--
+function Rec(x1: T1; x2: T2; x3: T3; x4: T4): (T1, T2, T3, T4);
+///--
+function Rec(x1: T1; x2: T2; x3: T3; x4: T4; x5: T5): (T1, T2, T3, T4, T5);
+///--
+function Rec(x1: T1; x2: T2; x3: T3; x4: T4; x5: T5; x6: T6): (T1, T2, T3, T4, T5, T6);
+///--
+function Rec(x1: T1; x2: T2; x3: T3; x4: T4; x5: T5; x6: T6; x7: T7): (T1, T2, T3, T4, T5, T6, T7);
+
+
+// -----------------------------------------------------
+//>> Короткие функции Lst, LLst, HSet, SSet, Dict, KV # Short functions Lst, HSet, SSet, Dict, KV
+// -----------------------------------------------------
+/// Возвращает список, заполненный указанными значениями
+function Lst(params a: array of T): List;
+/// Возвращает список, заполненный значениями из последовательности
+function Lst(a: sequence of T): List;
+/// Возвращает двусвязный список, заполненный указанными значениями
+function LLst(params a: array of T): LinkedList;
+/// Возвращает двусвязный список, заполненный значениями из последовательности
+function LLst(a: sequence of T): LinkedList;
+/// Возвращает множество на базе хеш таблицы, заполненное указанными значениями
+function HSet(params a: array of T): HashSet;
+/// Возвращает множество на базе хеш таблицы, заполненное значениями из последовательности
+function HSet(a: sequence of T): HashSet;
+/// Возвращает множество на базе бинарного дерева поиска, заполненное значениями из последовательности
+function SSet(params a: array of T): SortedSet;
+/// Возвращает множество на базе бинарного дерева поиска, заполненное значениями из последовательности
+function SSet(a: sequence of T): SortedSet;
+/// Возвращает словарь пар элементов (ключ, значение)
+function Dict(params pairs: array of KeyValuePair): Dictionary;
+/// Возвращает словарь пар элементов (ключ, значение)
+function Dict(params pairs: array of (TKey, TVal)): Dictionary;
+/// Возвращает пару элементов (ключ, значение)
+function KV(key: TKey; value: TVal): KeyValuePair;
+
+//{{{--doc: Конец секции интерфейса для документации }}}
+
+// -----------------------------------------------------
+//>> Вспомогательные функции для pattern matching #
+// -----------------------------------------------------
+
+function __TypeCheckAndAssignForIsMatch(obj: object; var res: T): boolean;
+
+// -----------------------------------------------------
+// Стандартные классы исключений
+// -----------------------------------------------------
+type
+ ///Базовый класс для исключений, бросаемых при создании инстанции generic-типа
+ BadGenericInstanceParameterException = class(Exception)
+ protected
+ InstanceType: System.Type;
+ public
+ constructor Create(ActualParameterType: System.Type);
+ end;
+
+ ///Бросается если тип непригоден для указателей
+ CanNotUseTypeForPointersException = class(BadGenericInstanceParameterException)
+ public
+ function ToString: string; override;
+ end;
+
+ ///Бросается если тип непригоден для типизированных файлов
+ CanNotUseTypeForTypedFilesException = class(BadGenericInstanceParameterException)
+ public
+ function ToString: string; override;
+ end;
+
+ ///Бросается если тип непригоден для бинарных файлов
+ CanNotUseTypeForFilesException = class(BadGenericInstanceParameterException)
+ public
+ function ToString: string; override;
+ end;
+
+ RangeException = class(SystemException) end;
+ CommandLineArgumentOutOfRangeException = class(SystemException) end;
+
+
+// -----------------------------------------------------
+// Общедоступные переменные
+// -----------------------------------------------------
+var
+ /// Содержит аргумены командой строки, с которыми была запущена программа
+ CommandLineArgs: array of string;
+ /// Стандартный текстовый файл для вывода. Связывается процедурой Assign с файлом на диске, после чего весь вывод на консоль перенаправляется в этот файл
+ output: TextFile;
+ /// Стандартный текстовый файл для ввода. Связывается процедурой Assign с файлом на диске, после чего весь ввод с консоли перенаправляется из этого файла
+ input: TextFile;
+ /// Определяет текущую систему ввода-вывода
+ CurrentIOSystem: IOSystem;
+ /// Принимает значение True, если приложение имеет консольное окно
+ IsConsoleApplication: boolean;
+ ///--
+ RedirectIOInDebugMode := False;
+ ///--
+ ExecuteBeforeProcessTerminateIn__Mode: procedure(e: Exception);
+ //GCHandlersForReferencePointers := new GCHandlersController;
+ ///--
+ ExitCode := 0; // TODO Сделать возврат в Main
+ ///--
+ DefaultEncoding: Encoding;
+ ///--
+ PrintDelimDefault: string := ' ';
+
+///--
+var
+ __CONFIG__: Dictionary := new Dictionary;
+
+// Вспомогательные подпрограммы. Из раздела интерфейса не убирать!!!
+// -----------------------------------------------------
+// Internal System subprograms
+// -----------------------------------------------------
+///--
+function CopyWithSize(source, dest: &Array): &Array;
+///--
+function check_in_range(val: int64; low, up: int64): int64;
+///--
+function check_in_range_char(val: char; low, up: char): char;
+///--
+function RunTimeSizeOf(t: System.Type): integer;
+///--
+function GetCharInShortString(s: string; ind, n: integer): char;
+///--
+function SetCharInShortString(s: string; ind, n: integer; c: char): string;
+///--
+function ClipShortString(s: string; len: integer): string;
+///--
+function GetResourceStream(ResourceFileName: string): Stream;
+///--
+function FormatValue(value: object; NumOfChars: integer): string;
+///--
+function FormatValue(value: integer; NumOfChars: integer): string;
+///--
+function FormatValue(value: int64; NumOfChars: integer): string;
+///--
+function FormatValue(value: real; NumOfChars: integer): string;
+///--
+function FormatValue(value: real; NumOfChars, NumOfSignesAfterDot: integer): string;
+///--
+procedure StringDefaultPropertySet(var s: string; index: integer; c: char);
+
+//procedure InitShortString(var s: ShortString; Length: integer);
+
+///Проверяет возможность использования указателей на тип T
+procedure CheckCanUsePointerOnType(T: System.Type);
+///Проверяет возможность записи типа T в файл
+procedure CheckCanUseTypeForBinaryFiles(T: System.Type);
+///Проверяет возможность создания file of T
+procedure CheckCanUseTypeForTypedFiles(T: System.Type);
+///Определяет специальные типы
+function RuntimeDetermineType(T: System.Type): byte;
+///Возвращает объект класса в зависимости от значения kind
+function RuntimeInitialize(kind: byte; variable: object): object;
+///Вычисление размера типа на этапе выполнения
+function GetRuntimeSize: integer;
+///Возвращает строку для вывода в write
+function _ObjectToString(o: object): string;
+
+function IsUnix: boolean;
+///--
+function ExecuteAssemlyIsDll: boolean;
+///--
+function __StandardFilesDirectory: string;
+///--
+function __FindFile(filename: string): string;
+
+// -----------------------------------------------------
+// Internal for OpenMPSupport
+// -----------------------------------------------------
+///--
+procedure omp_set_nested(nested: integer);
+///--
+function omp_get_nested: integer;
+///--
+var
+ OMP_NESTED: boolean := false;
+
+// -----------------------------------------------------
+// Internal typed sets operations
+// -----------------------------------------------------
+///--
+function Union(s1, s2: TypedSet): TypedSet;
+///--
+function Subtract(s1, s2: TypedSet): TypedSet;
+///--
+function Intersect(s1, s2: TypedSet): TypedSet;
+///--
+function CreateSet(params elems: array of object): TypedSet;
+///--
+function CreateSet: TypedSet;
+///--
+function CreateBoundedSet(low, high: object): TypedSet;
+///--
+function InSet(obj: object; s: TypedSet): boolean;
+///--
+function CreateDiapason(low, high: integer): Diapason;
+///--
+function CreateObjDiapason(low, high: object): Diapason;
+///--
+function CompareSetEquals(s1, s2: TypedSet): boolean;
+///--
+function CompareSetInEquals(s1, s2: TypedSet): boolean;
+///--
+function CompareSetLess(s1, s2: TypedSet): boolean;
+///--
+function CompareSetGreaterEqual(s1, s2: TypedSet): boolean;
+///--
+function CompareSetLessEqual(s1, s2: TypedSet): boolean;
+///--
+function CompareSetGreater(s1, s2: TypedSet): boolean;
+///--
+procedure ClipSet(var s: TypedSet; low, high: object);
+///--
+procedure AssignSet(var left: TypedSet; right: TypedSet);
+///--
+function ClipSetFunc(s: TypedSet; low, high: object): TypedSet;
+///--
+function ClipShortStringInSet(s: TypedSet; len: integer): TypedSet;
+///--
+procedure ClipShortStringInSetProcedure(var s: TypedSet; len: integer);
+///--
+procedure AssignSetWithBounds(var left: TypedSet; right: TypedSet; low, high: object);
+///--
+procedure TypedSetInit(var st: TypedSet);
+///--
+procedure TypedSetInitWithBounds(var st: TypedSet; low, high: object);
+///--
+procedure TypedSetInitWithShortString(var st: TypedSet; len: integer);
+
+// -----------------------------------------------------
+// Internal classes
+// -----------------------------------------------------
+type
+ ///--
+ GCHandlersController = class(System.Collections.IEnumerable)
+ private
+ Counters, Handlers: Hashtable;
+ public
+ constructor;
+ procedure Add(obj: Object);
+ procedure Remove(obj: Object);
+ function GetCounter(obj: Object): integer;
+ function GetEnumerator: System.Collections.IEnumerator;
+ end;
+
+type
+ ///--
+ PointerOutput = class
+ public
+ p: pointer;
+ function ToString: string; override;
+ constructor(ptr: pointer);
+ end;
+
+type
+ ///--
+ __ConceptSingleton = class where T: constructor;
+ class _instance: T;
+ class inited: boolean := false;
+ public
+ class function Instance: T;
+ begin
+ if inited = false then
+ begin
+ inited := true;
+ _instance := new T;
+ end;
+
+ Result := _instance;
+ end;
+ end;
+
+
+type
+ ///--
+ __TypeclassRestrictedFunctionAttribute = class(Attribute)
+ public
+ constructor;
+ begin
+ end;
+ end;
+
+
+ ///--
+ __TypeclassGenericParameterAttribute = class(Attribute)
+ public
+ constructor(instanceName: string);
+ begin
+ end;
+ end;
+
+ ///--
+ __TypeclassAttribute = class(Attribute)
+ public
+ constructor(typeclassName: string);
+ begin
+ end;
+ end;
+
+ ///--
+ __TypeclassMemberAttribute = class(Attribute)
+ public
+ constructor;
+ begin
+ end;
+ end;
+
+ ///--
+ __TypeclassInstanceAttribute = class(Attribute)
+ public
+ constructor(instanceName: string);
+ begin
+ end;
+ end;
+
+type
+// Смысл полей Num, Width и Fmt соответствует
+// атрибутам форматирования {Num,Width:Fmt}.
+// Поле Comment может интерпретироваться как
+// дополнительная строка, приписываемая слева к свойству.
+// Если для первого атрибута дополнительная строка
+// начинается со скобок или кавычек, то парные символы
+// добавляются в конец итоговой строки.
+/// Класс атрибута форматирования текста
+ PrintAttribute = class(System.Attribute)
+ public
+ Comment: string;
+ Num: integer;
+ Width: integer;
+ Fmt: string;
+ constructor (n: integer) := (Comment, Num, Width, Fmt) := ('', n, 0, '');
+ constructor (n, w: integer) := (Comment, Num, Width, Fmt) := ('', n, w, '');
+ constructor (n: integer; f: string) := (Comment, Num, Width, Fmt) := ('', n, 0, f);
+ constructor (n, w: integer; f: string) := (Comment, Num, Width, Fmt) := ('', n, w, f);
+ constructor (c: string; n: integer) := (Comment, Num, Width, Fmt) := (c, n, 0, '');
+ constructor (c: string; n, w: integer) := (Comment, Num, Width, Fmt) := (c, n, w, '');
+ constructor (c: string; n: integer; f: string) := (Comment, Num, Width, Fmt) := (c, n, 0, f);
+ constructor (c: string; n, w: integer; f: string) := (Comment, Num, Width, Fmt) := (c, n, w, f);
+ end;
+
+
+// -----------------------------------------------------
+// Internal procedures for PABCRTL.dll
+// -----------------------------------------------------
+///--
+procedure __InitModule__;
+///--
+procedure __InitPABCSystem;
+///--
+procedure __FinalizeModule__;
+
+// -----------------------------------------------------
+// DQNToNullable for dot_question_node
+// -----------------------------------------------------
+
+function DQNToNullable(v: T): Nullable; where T: record;
+
+implementation
+
+var
+ rnd := new System.Random;
+ // ENCultureInfo: System.Globalization.CultureInfo;
+ nfi: System.Globalization.NumberFormatInfo;
+ LastReadChar := #0;
+ AnsiOrdChrEncoding := Encoding.GetEncoding(1251);
+ __one_char := new char[1];
+ __one_byte := new byte[1];
+ StartTime: DateTime;// Для Milliseconds
+
+const
+ WRITELN_IN_BINARYFILE_ERROR_MESSAGE = 'Операция Writeln не применима к бинарным файлам!!Writeln is not applicable to binary files';
+ InternalNullBasedArrayName = 'NullBasedArray';
+ FILE_NOT_ASSIGNED = 'Для файловой переменной не вызвана процедура Assign!!File is not assigned';
+ FILE_NOT_OPENED = 'Файл не открыт!!File is not opened';
+ FILE_NOT_OPENED_FOR_READING = 'Файл не открыт на чтение!!File is not opened for reading';
+ FILE_NOT_OPENED_FOR_WRITING = 'Файл не открыт на запись!!File is not opened for writing';
+ READ_LEXEM_AFTER_END_OF_TEXT_FILE = 'Попытка считывания за концом текстового файла!!Read after end of text file';
+ RANGE_ERROR_MESSAGE = 'Выход за границы диапазона!!Out of range';
+ EOF_FOR_TEXT_WRITEOPENED = 'Функция Eof не может быть вызвана для текстового файла, открытого на запись!!Eof function can''t be called for file, opened on writing';
+ EOLN_FOR_TEXT_WRITEOPENED = 'Функция Eoln не может быть вызвана для текстового файла, открытого на запись!!Eoln function can''t be called for file, opened on writing';
+ SEEKEOF_FOR_TEXT_WRITEOPENED = 'Функция SeekEof не может быть вызвана для текстового файла, открытого на запись!!SeekEof function can''t be called for file, opened on writing';
+ SEEKEOLN_FOR_TEXT_WRITEOPENED = 'Функция SeekEoln не может быть вызвана для текстового файла, открытого на запись!!SeekEoln function can''t be called for file, opened on writing';
+ BAD_TYPE_IN_RUNTIMESIZEOF = 'Bad Type in RunTimeSizeOf';
+ PARAMETER_COUNT_MUST_BE_GREATER_0 = 'Параметр count должен быть > 0!!Parameter count must be > 0';
+ PARAMETER_COUNT_MUST_BE_GREATER_1 = 'Параметр count должен быть > 1!!Parameter count must be > 1';
+ PARAMETER_STEP_MUST_BE_NOT_EQUAL_0 = 'Параметр step не может быть равен 0!!The step parameter must be not equal to 0';
+ PARAMETER_STEP_MUST_BE_GREATER_0 = 'Параметр step должен быть > 0!!The step parameter must be not greater than 0';
+ PARAMETER_FROM_OUT_OF_RANGE = 'Параметр from за пределами диапазона!!The from parameter out of bounds';
+ PARAMETER_TO_OUT_OF_RANGE = 'Параметр to за пределами диапазона!!The to parameter out of bounds';
+ ARR_LENGTH_MUST_BE_MATCH_TO_MATR_SIZE = 'Размер одномерного массива не согласован с размером двумерного массива!!The 1-dim array length does not match 2-dim array size';
+ INITELEM_COUNT_MUST_BE_EQUAL_TO_MATRIX_ELEMS_COUNT = 'Количество инициализирующих элементов не совпадает с количеством элементов матрицы!!The number of elements in init list must be equal to the number of elements in matrix';
+
+// -----------------------------------------------------
+// WINAPI
+// -----------------------------------------------------
+
+function WINAPI_AllocConsole: longword; external 'kernel32.dll' name 'AllocConsole';
+
+var
+ console_alloc: boolean := false;
+
+// -----------------------------------------------------
+// Internal functions
+// -----------------------------------------------------
+
+function GetCurrentLocale: string;
+begin
+ var locale: object;
+ if __CONFIG__.TryGetValue('locale', locale) then
+ Result := locale as string
+ else
+ Result := 'ru';
+end;
+
+function GetTranslation(message: string): string;
+begin
+ var cur_locale := GetCurrentLocale();
+ var arr := message.Split(new string[1]('!!'), StringSplitOptions.None);
+ if (cur_locale = 'en') and (arr.Length > 1) then
+ Result := arr[1]
+ else
+ Result := arr[0]
+end;
+
+function IsWDE: boolean;
+begin
+ Result := AppDomain.CurrentDomain.GetData('_RedirectIO_SpecialArgs') <> nil;
+end;
+
+[System.Security.SecuritySafeCriticalAttribute]
+procedure AllocConsole;
+begin
+ if not IsConsoleApplication and (System.Environment.OSVersion.Platform <> PlatformID.Unix) and (AppDomain.CurrentDomain.GetData('_RedirectIO_SpecialArgs') = nil) then
+ WINAPI_AllocConsole;
+ console_alloc := true;
+end;
+
+function GetNullBasedArray(arr: object): System.Array;
+var
+ fi: System.Reflection.FieldInfo;
+begin
+ fi := arr.GetType.GetField(InternalNullBasedArrayName);
+ if fi <> nil then
+ Result := System.Array(fi.GetValue(arr))
+ else
+ Result := nil;
+end;
+
+function FormatFloatNumber(s: string): string;
+begin
+ Result := s.Replace(',', '.');
+end;
+
+procedure ClipSet(var s: TypedSet; low, high: object);
+begin
+ s.low_bound := low;
+ s.upper_bound := high;
+ s.Clip;
+end;
+
+function ClipSetFunc(s: TypedSet; low, high: object): TypedSet;
+begin
+ s.low_bound := low;
+ s.upper_bound := high;
+ s.Clip();
+ Result := s;
+end;
+
+function ClipShortStringInSet(s: TypedSet; len: integer): TypedSet;
+begin
+ s.len := len;
+ s.Clip;
+ Result := s;
+end;
+
+procedure ClipShortStringInSetProcedure(var s: TypedSet; len: integer);
+begin
+ s.len := len;
+ s.Clip;
+end;
+
+procedure AssignSet(var left: TypedSet; right: TypedSet);
+begin
+ left := right.CloneSet();
+end;
+
+procedure AssignSetWithBounds(var left: TypedSet; right: TypedSet; low, high: object);
+begin
+ left := right.CloneSet();
+ left.low_bound := low;
+ right.upper_bound := high;
+end;
+
+procedure TypedSetInit(var st: TypedSet);
+begin
+ if st = nil then
+ st := new TypedSet;
+end;
+
+procedure TypedSetInitWithBounds(var st: TypedSet; low, high: object);
+begin
+ if st = nil then
+ st := new TypedSet(low, high);
+end;
+
+procedure TypedSetInitWithShortString(var st: TypedSet; len: integer);
+begin
+ if st = nil then
+ st := new TypedSet(len);
+end;
+
+// -----------------------------------------------------
+// Diapason
+// -----------------------------------------------------
+constructor Diapason.Create(_low, _high: integer);
+begin
+ low := _low;high := _high;
+end;
+
+constructor Diapason.Create(_low, _high: object);
+begin
+ clow := _low;chigh := _high;
+end;
+
+// -----------------------------------------------------
+// TypedSet
+// -----------------------------------------------------
+///--
+constructor TypedSet.Create;
+begin
+ ht := new Hashtable({new TypedSetComparer()});
+end;
+
+///--
+constructor TypedSet.Create(len: integer);
+begin
+ ht := new Hashtable({new TypedSetComparer()});
+ Self.len := len;
+end;
+
+///--
+constructor TypedSet.Create(low_bound, upper_bound: object);
+begin
+ ht := new Hashtable({new TypedSetComparer()});
+ Self.low_bound := low_bound;
+ Self.upper_bound := upper_bound;
+end;
+
+///--
+constructor TypedSet.Create(initValue: TypedSet);
+begin
+ ht := new Hashtable({new TypedSetComparer()});
+ Self.AssignSetFrom(initValue);
+ Self.len := initValue.len;
+end;
+
+///--
+constructor TypedSet.Create(low_bound, upper_bound: object; initValue: TypedSet);
+begin
+ ht := new Hashtable({new TypedSetComparer()});
+ Self.low_bound := low_bound;
+ Self.upper_bound := upper_bound;
+ Self.AssignSetFrom(initValue);
+end;
+
+///--
+constructor TypedSet.Create(vals: array of byte);
+var
+ i: integer;
+begin
+ ht := new Hashtable({new TypedSetComparer()});
+ i := 0;
+ while i < 256 div 8 do
+ begin
+ if vals[i] and 128 = 128 then ht.Add(i * 8, i * 8);
+ if vals[i] and 64 = 64 then ht.Add(i * 8 + 1, i * 8 + 1);
+ if vals[i] and 32 = 32 then ht.Add(i * 8 + 2, i * 8 + 2);
+ if vals[i] and 16 = 16 then ht.Add(i * 8 + 3, i * 8 + 3);
+ if vals[i] and 8 = 8 then ht.Add(i * 8 + 4, i * 8 + 4);
+ if vals[i] and 4 = 4 then ht.Add(i * 8 + 5, i * 8 + 5);
+ if vals[i] and 2 = 2 then ht.Add(i * 8 + 6, i * 8 + 6);
+ if vals[i] and 1 = 1 then ht.Add(i * 8 + 7, i * 8 + 7);
+ i := i + 1;
+ end;
+end;
+
+///--
+procedure TypedSet.CreateIfNeed;
+begin
+ if ht = nil then ht := new Hashtable({new TypedSetComparer()});
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+function TypedSet.CloneSet: TypedSet;
+begin
+ Result := new TypedSet();
+ Result.ht := ht.Clone() as Hashtable;
+ //Result.copy_ht := ht;
+ Result.low_bound := low_bound;
+ Result.upper_bound := upper_bound;
+end;
+
+///--
+function TypedSet.GetBytes: array of byte;
+var
+ ba: System.Collections.BitArray;
+ i: integer;
+begin
+ ba := new BitArray(256);
+ Result := nil;
+ foreach o: object in ht.Keys do
+ begin
+ try
+ i := Convert.ToInt32(o);
+ if (i < 0) and (i >= -128) and (i <= 127) then
+ ba[i + 128] := true
+ else if (i >= 0) and (i <= 255) then
+ ba[i] := true;
+
+ except
+ on e: System.Exception do
+ begin
+ Result := nil;
+ //Exit;
+ end;
+ end;
+ end;
+ SetLength(Result, 256 div 8);
+ i := 0;
+ while i < 256 div 8 do
+ begin
+ Result[i] := Convert.ToByte(ba[i * 8 + 7]) or (Convert.ToByte(ba[i * 8 + 6]) shl 1) or (Convert.ToByte(ba[i * 8 + 5]) shl 2) or (Convert.ToByte(ba[i * 8 + 4]) shl 3)
+ or (Convert.ToByte(ba[i * 8 + 3]) shl 4) or (Convert.ToByte(ba[i * 8 + 2]) shl 5) or (Convert.ToByte(ba[i * 8 + 1]) shl 6) or (Convert.ToByte(ba[i * 8]) shl 7);
+ i := i + 1;
+ end;
+end;
+
+///--
+function TypedSet.UnionSet(s: TypedSet): TypedSet;
+begin
+ Result := Union(Self, s);
+end;
+
+///--
+function TypedSet.SubtractSet(s: TypedSet): TypedSet;
+begin
+ Result := Subtract(Self, s);
+end;
+
+///--
+function TypedSet.IntersectSet(s: TypedSet): TypedSet;
+begin
+ Result := Intersect(Self, s);
+end;
+
+///--
+function TypedSet.IsInDiapason(elem: object): boolean;
+begin
+ if (low_bound <> nil) and (upper_bound <> nil) and (elem is System.IComparable) then
+ begin
+ case System.Type.GetTypeCode(elem.GetType) of
+ TypeCode.Char:
+ begin
+ if ((elem as System.IComparable).CompareTo(Convert.ToChar(low_bound)) >= 0) and ((elem as System.IComparable).CompareTo(Convert.ToChar(upper_bound)) <= 0) then
+ Result := true
+ else Result := false
+ end;
+ TypeCode.Int32:
+ begin
+ if not (elem is integer) then elem := Convert.ToInt32(elem);
+ if ((elem as System.IComparable).CompareTo(Convert.ToInt32(low_bound)) >= 0) and ((elem as System.IComparable).CompareTo(Convert.ToInt32(upper_bound)) <= 0) then
+ Result := true
+ else Result := false
+ end;
+ TypeCode.Byte:
+ begin
+ if ((elem as System.IComparable).CompareTo(Convert.ToByte(low_bound)) >= 0) and ((elem as System.IComparable).CompareTo(Convert.ToByte(upper_bound)) <= 0) then
+ Result := true
+ else Result := false
+ end;
+ TypeCode.SByte:
+ begin
+ if ((elem as System.IComparable).CompareTo(Convert.ToSByte(low_bound)) >= 0) and ((elem as System.IComparable).CompareTo(Convert.ToSByte(upper_bound)) <= 0) then
+ Result := true
+ else Result := false
+ end;
+ TypeCode.Int16:
+ begin
+ if ((elem as System.IComparable).CompareTo(Convert.ToInt16(low_bound)) >= 0) and ((elem as System.IComparable).CompareTo(Convert.ToInt16(upper_bound)) <= 0) then
+ Result := true
+ else Result := false
+ end;
+ TypeCode.UInt16:
+ begin
+ if ((elem as System.IComparable).CompareTo(Convert.ToUint16(low_bound)) >= 0) and ((elem as System.IComparable).CompareTo(Convert.ToUInt16(upper_bound)) <= 0) then
+ Result := true
+ else Result := false
+ end;
+ TypeCode.UInt32:
+ begin
+ if ((elem as System.IComparable).CompareTo(Convert.ToUInt32(low_bound)) >= 0) and ((elem as System.IComparable).CompareTo(Convert.ToUInt32(upper_bound)) <= 0) then
+ Result := true
+ else Result := false
+ end;
+ TypeCode.Int64:
+ begin
+ if ((elem as System.IComparable).CompareTo(Convert.ToInt64(low_bound)) >= 0) and ((elem as System.IComparable).CompareTo(Convert.ToInt64(upper_bound)) <= 0) then
+ Result := true
+ else Result := false
+ end;
+ TypeCode.UInt64:
+ begin
+ if ((elem as System.IComparable).CompareTo(Convert.ToUInt64(low_bound)) >= 0) and ((elem as System.IComparable).CompareTo(Convert.ToUInt64(upper_bound)) <= 0) then
+ Result := true
+ else Result := false
+ end;
+ else
+ if elem.GetType().IsEnum then
+ begin
+ if ((Convert.ToInt32(elem)).CompareTo(Convert.ToInt32(low_bound)) >= 0) and ((Convert.ToInt32(elem)).CompareTo(Convert.ToInt32(upper_bound)) <= 0) then
+ Result := true
+ else Result := false
+ end
+ else Result := true;
+ end// case
+ end // then
+ else Result := true;
+end;
+
+function convert_elem(obj: object): object;// для TypedSet
+begin
+ var t := obj.GetType;
+ if t.IsEnum then
+ begin
+ Result := obj;
+ exit;
+ end;
+ case System.Type.GetTypeCode(t) of
+ TypeCode.Byte, TypeCode.SByte, TypeCode.Int16, TypeCode.UInt16, TypeCode.Int32:
+ Result := Convert.ToInt32(obj);
+ TypeCode.UInt32:
+ begin
+ var tmp: longword := longword(obj);
+ if tmp <= integer.MaxValue then
+ Result := integer(tmp)
+ else
+ Result := Convert.ToInt64(obj);
+ end;
+ TypeCode.Int64:
+ begin
+ var tmp: int64 := int64(obj);
+ if tmp <= integer.MaxValue then
+ Result := integer(tmp)
+ else
+ Result := obj;
+ end;
+ TypeCode.UInt64:
+ begin
+ var tmp: uint64 := uint64(obj);
+ if tmp <= integer.MaxValue then
+ Result := integer(tmp)
+ else
+ if tmp <= int64.MaxValue then
+ Result := int64(tmp)
+ else
+ Result := obj;
+ end
+ else
+ Result := obj;
+ end;
+end;
+
+///--
+function TypedSet.Contains(elem: object): boolean;
+begin
+ if elem.GetType().IsEnum then
+ begin
+ Result := ht[elem] <> nil
+ end
+ else
+ begin
+ elem := convert_elem(elem);
+ Result := ht.ContainsKey(elem);// <> nil;
+ if not Result and (elem is char) then
+ Result := ht.ContainsKey(Convert.ToString(elem));
+ end;
+end;
+
+///--
+procedure TypedSet.Clip;
+begin
+ if Self.len > 0 then
+ begin
+ Clip(Self.len);
+ exit;
+ end;
+ var tmp_ht := new Hashtable();
+ foreach el: object in ht.Keys do
+ begin
+ if IsInDiapason(el) then
+ begin
+ if (Self.low_bound <> nil) then
+ begin
+ var tmp := convert_elem(el);
+ tmp_ht.Add(tmp, tmp)
+ end
+ else
+ tmp_ht.Add(el, el);
+ end;
+ end;
+ ht := tmp_ht;
+end;
+
+///--
+procedure TypedSet.Clip(len: integer);
+begin
+ var tmp_ht := new Hashtable();
+ foreach el: object in ht.Keys do
+ begin
+ var str_el := Convert.ToString(el);
+ if str_el.Length > len then
+ begin
+ var s := str_el.Substring(0, len);
+ tmp_ht.Add(s, s);
+ end
+ else
+ tmp_ht.Add(str_el, str_el);
+ end;
+ ht := tmp_ht;
+end;
+
+procedure TypedSet.IncludeElement(elem: object);
+var
+ diap: Diapason;
+begin
+ if elem = nil then exit;
+ elem := convert_elem(elem);
+ if not IsInDiapason(elem) then Exit;
+ if elem.GetType().IsEnum then
+ begin
+ ht[elem] := elem;
+ //if copy_ht <> nil then
+ // copy_ht[elem] := elem;
+ end
+ else
+ if not (elem is Diapason) then
+ begin
+ ht[elem] := elem;
+ //if copy_ht <> nil then
+ // copy_ht[elem] := elem;
+ end
+ else
+ begin
+ diap := Diapason(elem);
+ if diap.clow = nil then
+ begin
+ for var i := diap.low to diap.high do
+ begin
+ ht[i] := i;
+ //if copy_ht <> nil then
+ // copy_ht[i] := i;
+ end
+ end
+ else
+ begin
+ if diap.clow is char then
+ begin
+ for var c := char(diap.clow) to char(diap.chigh) do
+ begin
+ ht[c] := c;
+ //if copy_ht <> nil then
+ // copy_ht[c] := c;
+ end
+ end
+ else if diap.clow is boolean then
+ begin
+ for var b := boolean(diap.clow) to boolean(diap.chigh) do
+ ht[b] := b;
+ end
+ else if diap.clow.GetType().IsEnum then
+ begin
+ for var i := integer(diap.clow) to integer(diap.chigh) do
+ begin
+ var obj := Enum.ToObject(diap.clow.GetType(), i);
+ ht[obj] := obj;
+ //if copy_ht <> nil then
+ // copy_ht[obj] := obj;
+ end;
+ end;
+ end;
+ end;
+end;
+
+procedure TypedSet.ExcludeElement(elem: object);
+begin
+ if elem.GetType().IsEnum then
+ begin
+ ht.Remove(elem);
+ end
+ else
+ begin
+ elem := convert_elem(elem);
+ ht.Remove(elem);
+ end
+end;
+
+///--
+procedure TypedSet.Init(params elems: array of object);
+begin
+ for var i := 0 to elems.Length - 1 do
+ ht[elems[i]] := elems[i];
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+procedure TypedSet.AssignSetFrom(s: TypedSet);
+begin
+ ht := s.ht.Clone() as Hashtable;
+ Clip;
+end;
+
+///--
+function TypedSet.GetEnumerator: System.Collections.IEnumerator;
+begin
+ Result := ht.Keys.GetEnumerator;
+end;
+
+function FormatStr(obj: object): string;
+begin
+ if (obj.GetType = typeof(char)) or (obj.GetType = typeof(string)) then
+ Result := '''' + string.Format(System.Globalization.NumberFormatInfo.InvariantInfo, '{0}', new object[](obj)) + ''''
+ else
+ Result := string.Format(System.Globalization.NumberFormatInfo.InvariantInfo, '{0}', new object[](obj))
+end;
+
+///--
+class function TypedSet.operator implicit(s: TypedSet): HashSet;
+begin
+ var hs := new HashSet();
+ foreach var key in s.ht.Keys do
+ begin
+ hs.Add(T(key));
+ end;
+ Result := hs;
+end;
+
+///--
+class function TypedSet.operator implicit(s: HashSet): TypedSet;
+begin
+ var ts := new TypedSet();
+ foreach key: T in s.ToArray() do
+ begin
+ ts.ht[key] := key;
+ end;
+ Result := ts;
+end;
+
+///--
+function TypedSet.ToString: string;
+var
+ i: System.Collections.IEnumerator;
+ lst: ArrayList;
+begin
+ i := GetEnumerator;
+ lst := new ArrayList();
+ var t: &Type;
+ var added := false;
+ if i.MoveNext then
+ if not (i.Current is System.IComparable) then
+ begin
+ result := '' + FormatStr(i.Current) + '';
+ added := true;
+ end
+ else
+ begin
+ lst.Add(i.Current);
+ t := i.Current.GetType;
+ end;
+ while i.MoveNext do
+ if not (i.Current is System.IComparable) then
+ begin
+ result := (added ? result + ',' : '') + FormatStr(i.Current);
+ added := true;
+ end
+ else
+ begin
+ if (t <> nil) and (t <> i.Current.GetType) then
+ begin
+ result := (added ? result + ',' : '') + FormatStr(i.Current);
+ added := true;
+ end
+ else
+ begin
+ t := i.Current.GetType;
+ lst.Add(i.Current);
+ end;
+ end;
+
+ if lst.Count > 0 then
+ begin
+ lst.Sort;
+ var ind := 1;
+ if not added then
+ result := '' + FormatStr(lst[0]) + ''
+ else
+ ind := 0;
+ for j: integer := ind to lst.Count - 1 do
+ begin
+ result := result + ',' + FormatStr(lst[j]);
+ end;
+ end;
+ result := '[' + result + ']';
+end;
+
+{class function TypedSet.operator implicit(hset: HashSet): TypedSet;
+begin
+ Result := new TypedSet();
+ foreach var x in hset do
+ Result.ht[x] := x;
+end;}
+
+///--
+function TypedSet.CompareEquals(s: TypedSet): boolean;
+begin
+ Result := CompareSetEquals(Self, s);
+end;
+
+///--
+function TypedSet.CompareInEquals(s: TypedSet): boolean;
+begin
+ Result := CompareSetInEquals(Self, s);
+end;
+
+///--
+function TypedSet.CompareLess(s: TypedSet): boolean;
+begin
+ Result := CompareSetLess(Self, s);
+end;
+
+///--
+function TypedSet.CompareLessEqual(s: TypedSet): boolean;
+begin
+ Result := CompareSetLessEqual(Self, s);
+end;
+
+///--
+function TypedSet.CompareGreater(s: TypedSet): boolean;
+begin
+ Result := CompareSetGreater(Self, s);
+end;
+
+///--
+function TypedSet.CompareGreaterEqual(s: TypedSet): boolean;
+begin
+ Result := CompareSetGreaterEqual(Self, s);
+end;
+
+procedure TypedSet.Print(delim: string);
+begin
+ foreach var x in ht.Keys do
+ Write(x,delim)
+end;
+
+procedure TypedSet.Println(delim: string);
+begin
+ var fst := True;
+ foreach var x in ht.Keys do
+ begin
+ if fst then
+ begin
+ fst := False;
+ Write(x);
+ end
+ else Write(delim,x);
+ end;
+ Writeln;
+end;
+
+
+// -----------------------------------------------------
+// Typed Set functions
+// -----------------------------------------------------
+[System.Diagnostics.DebuggerStepThrough]
+function CreateSet: TypedSet;
+begin
+ Result := new TypedSet();
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+function CreateBoundedSet(low, high: object): TypedSet;
+begin
+ Result := new TypedSet(low, high);
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+function CreateDiapason(low, high: integer): Diapason;
+begin
+ Result.low := low;
+ Result.high := high;
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+function CreateObjDiapason(low, high: object): Diapason;
+begin
+ Result.clow := low;
+ Result.chigh := high;
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+function CreateSet(params elems: array of object): TypedSet;
+begin
+ Result := new TypedSet();
+ for var i := 0 to elems.Length - 1 do
+ Result.IncludeElement(elems[i]);
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+function Subtract(s1, s2: TypedSet): TypedSet;
+begin
+ Result := s1.CloneSet;
+ var en := s2.ht.GetEnumerator();
+ while en.MoveNext do
+ begin
+ if s1.Contains(en.Key) then
+ Result.ht.Remove(en.Key);
+ end;
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+procedure Include(var s: TypedSet; el: object);
+begin
+ s.IncludeElement(el);
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+procedure Exclude(var s: TypedSet; el: object);
+begin
+ s.ExcludeElement(el);
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+function Union(s1, s2: TypedSet): TypedSet;
+begin
+ Result := s1.CloneSet;
+ var en := s2.ht.GetEnumerator();
+ while en.MoveNext do
+ Result.ht[en.Key] := en.Key;
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+function Intersect(s1, s2: TypedSet): TypedSet;
+var
+ en: System.Collections.IEnumerator;
+begin
+ Result := new TypedSet();
+ en := s1.ht.GetEnumerator();
+ while en.MoveNext do
+ if s2.Contains((en as IDictionaryEnumerator).Key) then
+ Result.ht[(en as IDictionaryEnumerator).Key] := (en as IDictionaryEnumerator).Key;
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+function InSet(obj: object; s: TypedSet): boolean;
+begin
+ {if obj.GetType().IsEnum then
+ Result := s.ht[obj] <> nil
+ else}
+ Result := (obj <> nil) and s.Contains(obj);
+ {Result := (obj <> nil) and (s.ht[obj] <> nil);
+ if not Result and (obj is TypedSet) then
+ Result := s.Contains(obj as TypedSet);}
+ //if Result = true then
+ // Result := s.IsInDiapason(obj);
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+function CompareSetEquals(s1, s2: TypedSet): boolean;
+var
+ en: System.Collections.IEnumerator;
+ equals: boolean := true;
+begin
+ if s1.ht.Count <> s2.ht.Count then
+ begin
+ Result := false;
+ Exit;
+ end;
+ en := s1.ht.GetEnumerator();
+ while en.MoveNext do
+ begin
+ var is_in_s1 := s1.Contains((en as IDictionaryEnumerator).Key);
+ var is_in_s2 := s2.Contains((en as IDictionaryEnumerator).Key);
+ if is_in_s1 and not is_in_s2 then
+ begin
+ equals := false;
+ break;
+ end
+ else if not is_in_s1 and is_in_s2 then
+ begin
+ equals := false;
+ break;
+ end
+ end;
+ if equals <> false then
+ begin
+ en := s2.ht.GetEnumerator();
+ en.Reset();
+ while en.MoveNext do
+ begin
+ var is_in_s1 := s1.Contains((en as IDictionaryEnumerator).Key);
+ var is_in_s2 := s2.Contains((en as IDictionaryEnumerator).Key);
+ if is_in_s2 and not is_in_s1 then
+ begin
+ equals := false;
+ break;
+ end
+ else if not is_in_s2 and is_in_s1 then
+ begin
+ equals := false;
+ break;
+ end
+ end;
+ end;
+ Result := equals;
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+function CompareSetInEquals(s1, s2: TypedSet): boolean;
+begin
+ Result := not CompareSetEquals(s1, s2);
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+function CompareSetLess(s1, s2: TypedSet): boolean;
+var
+ en: System.Collections.IEnumerator;
+ less: boolean := true;
+begin
+ en := s1.ht.GetEnumerator();
+ en.Reset();
+ while en.MoveNext do
+ begin
+ if not s2.Contains((en as IDictionaryEnumerator).Key) then
+ begin
+ less := false;
+ break;
+ end;
+ end;
+ if less <> false then
+ begin
+ en := s2.ht.GetEnumerator();
+ en.Reset();
+ var b: boolean := false;
+ while en.MoveNext do
+ begin
+ if not s1.Contains((en as IDictionaryEnumerator).Key) then
+ begin
+ b := true;
+ break;
+ end;
+ end;
+ less := b;
+ end;
+ Result := less;
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+function CompareSetGreaterEqual(s1, s2: TypedSet): boolean;
+var
+ en: System.Collections.IEnumerator;
+ greater: boolean := true;
+begin
+ en := s2.ht.GetEnumerator();
+ en.Reset();
+ while en.MoveNext do
+ begin
+ if not s1.Contains((en as IDictionaryEnumerator).Key) then
+ begin
+ greater := false;
+ break;
+ end;
+ end;
+ Result := greater;
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+function CompareSetLessEqual(s1, s2: TypedSet): boolean;
+var
+ en: System.Collections.IEnumerator;
+ less: boolean := true;
+begin
+ en := s1.ht.GetEnumerator();
+ en.Reset();
+ while en.MoveNext do
+ begin
+ if not s2.Contains((en as IDictionaryEnumerator).Key) then
+ begin
+ less := false;
+ break;
+ end;
+ end;
+ Result := less;
+end;
+
+[System.Diagnostics.DebuggerStepThrough]
+function CompareSetGreater(s1, s2: TypedSet): boolean;
+var
+ greater: boolean := true;
+ en: System.Collections.IEnumerator;
+begin
+ en := s2.ht.GetEnumerator();
+ en.Reset();
+ while en.MoveNext do
+ begin
+ if not s1.Contains((en as IDictionaryEnumerator).Key) then
+ begin
+ greater := false;
+ break;
+ end;
+ end;
+ if greater <> false then
+ begin
+ en := s1.ht.GetEnumerator();
+ en.Reset();
+ var b: boolean := false;
+ while en.MoveNext do
+ begin
+ if not s2.Contains((en as IDictionaryEnumerator).Key) then
+ begin
+ b := true;
+ break;
+ end;
+ end;
+ greater := b;
+ end;
+ Result := greater;
+end;
+
+// -----------------------------------------------------
+// TypedFile
+// -----------------------------------------------------
+constructor TypedFile.Create(ElementType: System.Type);
+begin
+ Self.ElementType := ElementType;
+ ElementSize := RuntimeSizeOf(ElementType);
+end;
+
+constructor TypedFile.Create(ElementType: System.Type; offs: integer; params offsets: array of integer);
+begin
+ Self.ElementType := ElementType;
+ ElementSize := RuntimeSizeOf(ElementType);
+ Self.offsets := offsets;
+ if offs <> 0 then
+ begin
+ ElementSize := ElementSize + offs{*2};
+ offset := offs{*2};
+ end;
+end;
+
+function TypedFile.ToString := Format('file of {0}', ElementType);
+
+// -----------------------------------------------------
+// BinaryFile
+// -----------------------------------------------------
+function BinaryFile.ToString: string := 'file';
+
+// -----------------------------------------------------
+// GCHandlersController
+// -----------------------------------------------------
+constructor GCHandlersController.Create;
+begin
+ Counters := new Hashtable;
+ Handlers := new Hashtable;
+end;
+
+procedure GCHandlersController.Add(obj: Object);
+begin
+ if obj <> nil then begin
+ if Counters.Contains(obj) then
+ Counters[obj] := integer(Counters[obj]) + 1
+ else begin
+ Counters.Add(obj, 1);
+ Handlers.Add(obj, GCHandle.Alloc(obj, GCHandleType.Pinned));
+ //var ptr := Marshal.AllocHGlobal(Marshal.SizeOf(obj));
+ //Marshal.StructureToPtr(obj, ptr, false);
+ //Handlers.Add(obj, ptr);
+ //GC.KeepAlive(obj);
+ //var ptr:=IntPtr(pointer(@obj));
+ //Handlers.Add(obj,new IntPtr(integer(ptr) or 1));
+ end;
+ end;
+end;
+
+procedure GCHandlersController.Remove(obj: Object);
+begin
+ if obj <> nil then begin
+ if Counters.Contains(obj) then begin
+ var Count := integer(Counters[obj]);
+ if Count > 1 then
+ Counters[obj] := Count - 1
+ else begin
+ Counters.Remove(obj);
+ GCHandle(Handlers[obj]).Free;
+ Handlers.Remove(obj);
+ end;
+ end else
+ raise new SystemException('PABCSystem.GCHandleForPointersController not contains object ' + obj.ToString);
+ end;
+end;
+
+function GCHandlersController.GetCounter(obj: Object): integer;
+begin
+ result := 0;
+ if Counters.Contains(obj) then
+ result := integer(Counters[obj]);
+end;
+
+function GCHandlersController.GetEnumerator: System.Collections.IEnumerator;
+begin
+ result := Counters.Keys.GetEnumerator;
+end;
+
+//------------------------------------------------------------------------------
+// StructuredObjectToString
+//------------------------------------------------------------------------------
+
+// Возвращает переопределенный в последнем потомке ToString или nil если ToString определен в Object
+function RedefinedToString(o: object): System.Reflection.MethodInfo;
+begin
+ var t := o.GetType;
+ var meth: System.Reflection.MethodInfo := nil;
+ while t <> typeof(Object) do
+ begin
+ meth := t.GetMethod('ToString', System.Reflection.BindingFlags.Public or
+ System.Reflection.BindingFlags.Instance or
+ System.Reflection.BindingFlags.DeclaredOnly, nil, new System.Type[0], nil);
+ if meth <> nil then
+ break;
+ t := t.BaseType;
+ end;
+ if (t = typeof(Object)) or (t = typeof(System.ValueType)) then
+ Result := nil
+ else Result := meth;
+end;
+
+function ArrNToString(a: System.Array; indexes: array of integer; i: integer): string; forward;
+
+function StructuredObjectToString(o: Object; n: integer := 0): string;
+const
+ nmax = 100;
+ nmax1 = 30;
+begin
+ if o = nil then
+ Result := 'nil'
+ else if o is System.Reflection.Pointer then
+ Result := PointerToString(System.Reflection.Pointer.Unbox(o))
+ else if (o.GetType = typeof(real)) or (o.GetType = typeof(decimal)) or (o.GetType = typeof(single)) then
+ Result := FormatFloatNumber(o.ToString)
+ else if (o.GetType = typeof(Complex)) then
+ begin
+ var c := Complex(o);
+ Result := '(' + StructuredObjectToString(c.Real) + ',' + StructuredObjectToString(c.Imaginary) + ')';
+ end
+ else if (o.GetType.IsPrimitive) or (o.GetType = typeof(string)) then
+ Result := o.ToString
+ else if o is System.Array then
+ begin
+ var a := o as System.Array;
+ Result := ArrNToString(a, new integer[a.Rank], 0);
+ end
+ else if o is System.Collections.IEnumerable then
+ begin
+ var sb := new StringBuilder();
+ var g := (o as System.Collections.IEnumerable).GetEnumerator();
+
+ var isdictorset := o.GetType.Name.Equals('Dictionary`2') or o.GetType.Name.Equals('SortedDictionary`2') or (o.GetType = typeof(TypedSet)) or o.GetType.Name.Equals('HashSet`1') or o.GetType.Name.Equals('SortedSet`1');
+ if isdictorset then
+ sb.Append('{')
+ else sb.Append('[');
+ if g.MoveNext() then
+ sb.Append(StructuredObjectToString(g.Current, n + 1));
+ var cnt := 1;
+ while g.MoveNext() and (cnt < nmax) do
+ begin
+ sb.Append(',');
+ sb.Append(StructuredObjectToString(g.Current, n + 1));
+ cnt += 1;
+ end;
+ if cnt >= nmax then
+ sb.Append(',...');
+
+ if isdictorset then
+ sb.Append('}')
+ else sb.Append(']');
+ Result := sb.ToString;
+ end
+ else if o.GetType.GetField('NullBasedArray') <> nil then
+ begin
+ var f := o.GetType.GetField('NullBasedArray');
+ Result := StructuredObjectToString(f.GetValue(o));
+ end
+ else
+ begin
+ var q := RedefinedToString(o);
+ var gg := o.GetType.FullName.StartsWith('System.Tuple');
+ var gg1 := o.GetType.Name.StartsWith('KeyValuePair');
+ if (q <> nil) and q.IsVirtual and not gg and not gg1 then
+ Result := o.ToString
+ else
+ begin
+ var t := o.GetType;
+ var sb := new System.Text.StringBuilder();
+ sb.Append('(');
+ if n > nmax1 then
+ sb.Append('....')
+ else
+ while t <> typeof(object) do
+ begin
+ var ff := t.GetFields(System.Reflection.BindingFlags.Public or System.Reflection.BindingFlags.Instance or System.Reflection.BindingFlags.DeclaredOnly);
+ var pp := t.GetProperties(System.Reflection.BindingFlags.Public or System.Reflection.BindingFlags.Instance or System.Reflection.BindingFlags.DeclaredOnly);
+
+ for var i := ff.Length - 1 downto 0 do
+ sb.Insert(1, StructuredObjectToString(ff[i].GetValue(o), n + 1) + ',');
+
+ for var i := pp.Length - 1 downto 0 do
+ if pp[i].GetIndexParameters.Length = 0 then
+ sb.Insert(1, StructuredObjectToString(pp[i].GetValue(o, nil), n + 1) + ',');
+
+ t := t.BaseType;
+ end;
+ if sb.Length > 1 then
+ sb.Length := sb.Length - 1;
+ sb.Append(')');
+ Result := sb.ToString;
+ end;
+ end;
+end;
+
+function ArrNToString(a: System.Array; indexes: array of integer; i: integer): string;
+const
+ nmax = 100;
+begin
+ var sb := new StringBuilder;
+ if i = a.Rank then
+ sb.Append(StructuredObjectToString(a.GetValue(indexes)))
+ else
+ begin
+ sb.Append('[');
+ for var k := 0 to a.GetLength(i) - 1 do
+ begin
+ indexes[i] := k;
+ sb.Append(ArrNToString(a, indexes, i + 1));
+ if (k >= nmax - 1) and (k < a.GetLength(i) - 1) then
+ begin
+ sb.Append(',...');
+ break
+ end
+ else if k < a.GetLength(i) - 1 then
+ sb.Append(',');
+ end;
+ sb.Append(']');
+ end;
+ Result := sb.ToString;
+end;
+
+//------------------------------------------------------------------------------
+// Операции для string и char
+//------------------------------------------------------------------------------
+procedure string.operator+=(var left: string; right: string);
+begin
+ left := left + right;
+end;
+
+function string.operator<(left, right: string) := string.CompareOrdinal(left, right) < 0;
+
+function string.operator<=(left, right: string) := string.CompareOrdinal(left, right) <= 0;
+
+function string.operator>(left, right: string) := string.CompareOrdinal(left, right) > 0;
+
+function string.operator>=(left, right: string) := string.CompareOrdinal(left, right) >= 0;
+
+/// Повторяет строку str n раз
+function string.operator*(str: string; n: integer): string;
+begin
+ var sb := new StringBuilder;
+ loop n do
+ sb.Append(str);
+ Result := sb.ToString;
+end;
+
+/// Повторяет строку str n раз
+function string.operator*(n: integer; str: string): string;
+begin
+ var sb := new StringBuilder;
+ loop n do
+ sb.Append(str);
+ Result := sb.ToString;
+end;
+
+/// Повторяет символ c n раз
+function char.operator*(c: char; n: integer): string;
+begin
+ if n <= 0 then
+ begin
+ Result := '';
+ exit;
+ end;
+ var sb := new StringBuilder(n, n);
+ loop n do
+ sb.Append(c);
+ Result := sb.ToString;
+end;
+
+/// Повторяет символ c n раз
+function char.operator*(n: integer; c: char): string;
+begin
+ if n <= 0 then
+ begin
+ Result := '';
+ exit;
+ end;
+ var sb := new StringBuilder(n, n);
+ loop n do
+ sb.Append(c);
+ Result := sb.ToString;
+end;
+
+/// Добавляет к строке str строковое представление числа n
+function string.operator+(str: string; n: integer) := str + n.ToString;
+
+/// Добавляет к строке str строковое представление числа n
+function string.operator+(n: integer; str: string) := n.ToString + str;
+
+/// Добавляет к строке str строковое представление числа r
+function string.operator+(str: string; r: real) := str + r.ToString(nfi);
+
+/// Добавляет к строке str строковое представление числа r
+function string.operator+(r: real; str: string) := r.ToString(nfi) + str;
+
+procedure string.operator+=(var left: string; right: integer);
+begin
+ left := left + right.ToString;
+end;
+
+procedure string.operator+=(var left: string; right: real);
+begin
+ left := left + right.ToString(nfi);
+end;
+
+procedure string.operator*=(var left: string; n: integer);
+begin
+ var sb := new StringBuilder;
+ loop n do
+ sb.Append(left);
+ left := sb.ToString;
+end;
+
+function string.operator in(substr: string; str: string) := str.Contains(substr);
+
+procedure operator+=(var left: StringBuilder; right: string); extensionmethod := left.Append(right);
+
+function operator implicit(s: string): StringBuilder; extensionmethod := new StringBuilder(s);
+
+//------------------------------------------------------------------------------
+// Операции для array of T
+//------------------------------------------------------------------------------
+/// Объединяет два массива
+function operator+(a, b: array of T): array of T; extensionmethod;
+begin
+ Result := new T[a.Length + b.Length];
+ a.CopyTo(Result, 0);
+ b.CopyTo(Result, a.Length);
+end;
+
+///--
+function operator in(x: T; a: array of T): boolean; extensionmethod := a.Contains(x);
+
+function operator*(a: array of T; n: integer): array of T; extensionmethod;
+begin
+ Result := new T[a.Length * n];
+ for var i := 0 to n - 1 do
+ a.CopyTo(Result, a.Length * i);
+end;
+
+function operator*(n: integer; a: array of T): array of T; extensionmethod := a * n;
+
+//------------------------------------------------------------------------------
+// Операции для List
+//------------------------------------------------------------------------------
+///--
+function operator+=(a, b: List): List; extensionmethod;
+begin
+ a.AddRange(b);
+ Result := a;
+end;
+
+///--
+function operator+(a, b: List): List; extensionmethod;
+begin
+ Result := new List(a);
+ Result.AddRange(b);
+end;
+
+///--
+function operator+=(a: List; x: T): List; extensionmethod;
+begin
+ a.Add(x);
+ Result := a;
+end;
+
+///--
+function List.operator in(x: T; Self: List): boolean;
+begin
+ Result := Self.Contains(x);
+end;
+
+///--
+function operator*(a: List; n: integer): List; extensionmethod;
+begin
+ Result := new List();
+ for var i := 1 to n do
+ Result.AddRange(a);
+end;
+
+///--
+function operator*(n: integer; a: List): List; extensionmethod := a * n;
+
+//------------------------------------------------------------------------------
+// Операции для Stack
+//------------------------------------------------------------------------------
+///--
+function operator+=(s: Stack; x: T): Stack; extensionmethod;
+begin
+ s.Push(x);
+ Result := s;
+end;
+
+//------------------------------------------------------------------------------
+// Операции для Queue
+//------------------------------------------------------------------------------
+///--
+function operator+=(q: Queue; x: T): Queue; extensionmethod;
+begin
+ q.Enqueue(x);
+ Result := q;
+end;
+
+//------------------------------------------------------------------------------
+// Операции для HashSet
+//------------------------------------------------------------------------------
+///--
+function operator in(x: T; Self: HashSet): boolean; extensionmethod := Self.Contains(x);
+
+function operator+=(var Self: HashSet; x: T): HashSet; extensionmethod;
+begin
+ Self.Add(x);
+ Result := Self;
+end;
+
+function operator+=(var Self: HashSet; x: sequence of T): HashSet; extensionmethod;
+begin
+ Self.UnionWith(x);
+ Result := Self;
+end;
+
+function operator-=(var Self: HashSet; x: T): HashSet; extensionmethod;
+begin
+ Self.Remove(x);
+ Result := Self;
+end;
+
+function operator-=(var Self: HashSet; x: sequence of T): HashSet; extensionmethod;
+begin
+ Self.ExceptWith(x);
+ Result := Self;
+end;
+
+function InternalEqual(x,y: HashSet): boolean;
+begin
+ var xn := Object.ReferenceEquals(x,nil);
+ var yn := Object.ReferenceEquals(y,nil);
+ if xn then
+ Result := yn
+ else if yn then
+ Result := xn
+ else Result := x.SetEquals(y);
+end;
+
+function operator=(x,y: HashSet): boolean; extensionmethod := InternalEqual(x,y);
+
+function operator<>(x,y: HashSet); extensionmethod := not InternalEqual(x,y);
+
+function operator-(x, y: HashSet): HashSet; extensionmethod;
+begin
+ var v := new HashSet(x);
+ v.ExceptWith(y);
+ Result := v;
+end;
+
+function operator+(x, y: HashSet): HashSet; extensionmethod;
+begin
+ var v := new HashSet(x);
+ v.UnionWith(y);
+ Result := v;
+end;
+
+function operator+(x: HashSet; y: T): HashSet; extensionmethod;
+begin
+ var v := new HashSet(x);
+ v.Add(y);
+ Result := v;
+end;
+
+function operator-(x: HashSet; y: T): HashSet; extensionmethod;
+begin
+ var v := new HashSet