Use record's for ranges and SystemIndex

This commit is contained in:
Sun Serega 2023-11-07 13:33:19 +02:00
parent 36c606fe4c
commit 4ed748de2e
2 changed files with 150 additions and 203 deletions

View file

@ -1,6 +0,0 @@
begin
var r := 1..2;
assert(r <> nil);
r := nil;
assert(r = nil);
end.

View file

@ -619,238 +619,209 @@ type
type
/// Тип диапазона целых
IntRange = class(IEnumerable<integer>)
private
l,h: integer;
function GetCount: integer;
begin
Result := h-l+1;
if Result<0 then
Result := 0;
end;
public
IntRange = record(ICollection<integer>, IReadOnlyCollection<integer>, IEquatable<IntRange>)
private
l,h: integer;
public
constructor(l,h: integer);
begin
Self.l := l;
Self.h := h;
end;
property Low: integer read l;
property High: integer read h;
//property Count: integer read GetCount;
static function operator in(x: integer; r: IntRange): boolean := (x >= r.l) and (x <= r.h);
static function operator in(x: real; r: IntRange): boolean := (x >= r.l) and (x <= r.h);
static function operator=(r1,r2: IntRange): boolean;
property Count: integer read System.Math.Max(0,h-l+1);
property ICollection<integer>.IsReadOnly: boolean read boolean(true);
procedure ICollection<integer>.Add(item: integer) := raise new System.InvalidOperationException;
function ICollection<integer>.Remove(item: integer): boolean;
begin
var o1: object := r1;
var o2: object := r2;
if (o1 = nil) and (o2 = nil) then
Result := true
else if (o1 <> nil) and (o2 = nil) then
Result := false
else if (o1 = nil) and (o2 <> nil) then
Result := false
else
Result := (r1.l = r2.l) and (r1.h = r2.h);
Result := false;
raise new System.InvalidOperationException;
end;
procedure ICollection<integer>.Clear := raise new System.InvalidOperationException;
static function operator in(x: integer; r: IntRange): boolean := (x >= r.l) and (x <= r.h);
static function operator in(x: real; r: IntRange): boolean := (x >= r.l) and (x <= r.h);
public function Contains(x: integer) := x in self;
public function Contains(x: real) := x in self;
static function operator=(r1,r2: IntRange) :=
(r1.l = r2.l) and (r1.h = r2.h);
static function operator<>(r1,r2: IntRange) := not(r1=r2);
function Equals(other: IntRange) := self=other;
function Equals(o: object): boolean; override;
begin
Result := false;
if not(o is IntRange) then exit;
if self <> IntRange(o) then exit;
Result := true;
end;
/// Возвращает True если диапазон пуст
function IsEmpty: boolean := l>h;
function Step(n: integer): sequence of integer;
function Reverse: sequence of integer;
function GetEnumerator(): IEnumerator<integer>;
function GetEnumerator: IEnumerator<integer>;
function System.Collections.IEnumerable.GetEnumerator: System.Collections.IEnumerator := Self.GetEnumerator;
function ToString: string; override := $'{l}..{h}';
function Equals(o: Object): boolean; override;
begin
var r2 := IntRange(o);
Result := (l = r2.l) and (h = r2.h);
end;
function GetHashCode: integer; override := l.GetHashCode xor h.GetHashCode;
{function ToArray: array of integer;
function GetHashCode: integer; override :=
ValueTuple.Create(l,h).GetHashCode;
function ToArray: array of integer;
begin
Result := new integer[Count];
var x := l;
for var i := 0 to Result.Length - 1 do
begin
Result[i] := x;
x += 1;
end;
end;
function ToList: List<integer>;
begin
Result := new List<integer>(Count);
var x := l;
loop Count do
begin
Result.Add(x);
x += 1;
end;
end;}
function ToLinkedList: LinkedList<integer>;
begin
Result := new LinkedList<integer>(System.Linq.Enumerable.Range(l,GetCount));
end;
function ToHashSet: HashSet<integer>;
begin
Result := new HashSet<integer>(System.Linq.Enumerable.Range(l,GetCount));
end;
function ToSortedSet: SortedSet<integer>;
begin
Result := new SortedSet<integer>(System.Linq.Enumerable.Range(l,GetCount));
Result[i] := l+i;
end;
// .ToList, .ToLinkedList, .ToHashSet, .ToSortedSet:
// Эти же методы последовательностей уже проверяют "is ICollection" и затем используют свойство .Count
// Только .ToArray перевыделяет память 1 лишний раз:
// https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,783a052330e7d48d,references
public procedure CopyTo(a: array of integer; arrayIndex: integer) :=
for var i := 0 to System.Math.Min(self.Count, a.Length-arrayIndex) do
a[i+arrayIndex] := l+i;
end;
/// Тип диапазона символов
CharRange = class(IEnumerable<char>)
private
l,h: char;
function GetCount: integer;
begin
Result := integer(h) - integer(l)+1;
if Result<0 then
Result := 0;
end;
public
CharRange = record(ICollection<char>, IReadOnlyCollection<char>, IEquatable<CharRange>)
private
l,h: char;
public
constructor(l,h: char);
begin
Self.l := l;
Self.h := h;
end;
property Low: char read l;
property High: char read h;
//property Count: integer read GetCount;
static function operator in(x: char; r: CharRange): boolean := (x >= r.l) and (x <= r.h);
static function operator=(r1,r2: CharRange): boolean := (r1.l = r2.l) and (r1.h = r2.h);
property Count: integer read System.Math.Max(0, integer(h)-integer(l)+1);
property ICollection<char>.IsReadOnly: boolean read boolean(true);
procedure ICollection<char>.Add(item: char) := raise new System.InvalidOperationException;
function ICollection<char>.Remove(item: char): boolean;
begin
Result := false;
raise new System.InvalidOperationException;
end;
procedure ICollection<char>.Clear := raise new System.InvalidOperationException;
static function operator in(x: char; r: CharRange): boolean := (x >= r.l) and (x <= r.h);
public function Contains(x: char) := x in self;
static function operator=(r1,r2: CharRange) :=
(r1.l = r2.l) and (r1.h = r2.h);
static function operator<>(r1,r2: CharRange) := not(r1=r2);
function Equals(other: CharRange) := self=other;
function Equals(o: object): boolean; override;
begin
Result := false;
if not(o is CharRange) then exit;
if self <> CharRange(o) then exit;
Result := true;
end;
/// Возвращает True если диапазон пуст
function IsEmpty: boolean := l>h;
function Step(n: integer): sequence of char;
function Reverse: sequence of char;
function GetEnumerator(): IEnumerator<char>;
function System.Collections.IEnumerable.GetEnumerator: System.Collections.IEnumerator := GetEnumerator;
function ToString: string; override := $'{l}..{h}';
function Equals(o: Object): boolean; override;
begin
var r2 := CharRange(o);
Result := (l = r2.l) and (h = r2.h);
end;
function GetHashCode: integer; override := l.GetHashCode xor h.GetHashCode;
{function ToArray: array of char;
function GetEnumerator: IEnumerator<char>;
function System.Collections.IEnumerable.GetEnumerator: System.Collections.IEnumerator := GetEnumerator;
function ToString: string; override := $'''{l}''..''{h}''';
function GetHashCode: integer; override :=
ValueTuple.Create(l,h).GetHashCode;
function ToArray: array of char;
begin
Result := new char[Count];
var x := l;
for var i := 0 to Result.Length - 1 do
begin
Result[i] := x;
x := char(integer(x) + 1);
end;
end;
function ToList: List<char>;
begin
Result := new List<char>;
var x := l;
loop Count do
begin
Result.Add(x);
x := char(integer(x) + 1);
end;
end;}
function ToLinkedList: LinkedList<char>;
begin
Result := new LinkedList<char>(System.Linq.Enumerable.Range(integer(l),GetCount).Select(i -> char(i)));
end;
function ToHashSet: HashSet<char>;
begin
Result := new HashSet<char>(System.Linq.Enumerable.Range(integer(l),GetCount).Select(i -> char(i)));
end;
function ToSortedSet: SortedSet<char>;
begin
Result := new SortedSet<char>(System.Linq.Enumerable.Range(integer(l),GetCount).Select(i -> char(i)));
Result[i] := char(integer(l)+i);
end;
public procedure CopyTo(a: array of char; arrayIndex: integer) :=
for var i := 0 to System.Math.Min(self.Count, a.Length-arrayIndex) do
a[i+arrayIndex] := char(integer(l)+i);
end;
/// Тип диапазона вещественных
RealRange = class
private
l,h: real;
public
RealRange = record(IEquatable<RealRange>)
private
l,h: real;
public
constructor(l,h: real);
begin
Self.l := l;
Self.h := h;
end;
property Low: real read l;
property High: real read h;
static function operator in(x: real; r: RealRange): boolean := (x >= r.l) and (x <= r.h);
static function operator=(r1,r2: RealRange): boolean := (r1.l = r2.l) and (r1.h = r2.h);
property Size: real read h-l;
static function operator in(x: real; r: RealRange): boolean := (x >= r.l) and (x <= r.h);
static function operator=(r1,r2: RealRange) :=
(r1.l = r2.l) and (r1.h = r2.h);
static function operator<>(r1,r2: RealRange) := not(r1=r2);
function Equals(other: RealRange) := self=other;
function Equals(o: object): boolean; override;
begin
Result := false;
if not(o is RealRange) then exit;
if self <> RealRange(o) then exit;
Result := true;
end;
/// Возвращает True если диапазон пуст
function IsEmpty: boolean := l>h;
function ToString: string; override := $'{l}..{h}';
function Equals(o: Object): boolean; override;
begin
var r2 := RealRange(o);
Result := (l = r2.l) and (h = r2.h);
end;
function GetHashCode: integer; override := l.GetHashCode xor h.GetHashCode;
end;
///Тип для представления индекса
SystemIndex = class
private
val: integer;
inverted: boolean;
public
property IndexValue: integer read val write val;
property IsInverted: boolean read inverted;
constructor(val: integer; inverted: boolean);
begin
Self.val := val;
Self.inverted := inverted;
end;
static function operator implicit(i: integer): SystemIndex;
begin
Result := new SystemIndex(i, false);
end;
function Reverse<T>(list: List<T>): integer;
begin
Result := list.Count - IndexValue;
end;
function Reverse<T>(arr: array of T): integer;
begin
Result := arr.Length - IndexValue;
end;
function Reverse(str: string): integer;
begin
Result := str.Length - IndexValue + 1;
end;
function Reverse0(str: string): integer;
begin
Result := str.Length - IndexValue;
end;
function Reverse(arr: System.Array; dim: integer): integer;
begin
Result := arr.GetLength(dim) - IndexValue;
end;
SystemIndex = record
private
val: integer;
inverted: boolean;
public
property IndexValue: integer read val write val;
property IsInverted: boolean read inverted;
constructor(val: integer; inverted: boolean);
begin
Self.val := val;
Self.inverted := inverted;
end;
static function operator implicit(i: integer): SystemIndex := new SystemIndex(i, false);
function Reverse<T>(list: List<T>): integer := list.Count - IndexValue;
function Reverse<T>(arr: array of T): integer := arr.Length - IndexValue;
function Reverse0(str: string) := str.Length - IndexValue;
function Reverse(str: string) := str.Length - IndexValue + 1;
function Reverse(arr: System.Array; dim: integer): integer := arr.GetLength(dim) - IndexValue;
end;
//{{{doc: Начало секции интерфейса для документации }}}
// -----------------------------------------------------
@ -2454,10 +2425,6 @@ function LstInt(params a: array of integer): List<integer>;
function LLst<T>(params a: array of T): LinkedList<T>;
/// Возвращает двусвязный список, заполненный значениями из последовательности
function LLst<T>(a: sequence of T): LinkedList<T>;
/// Возвращает двусвязный список, заполненный диапазоном значений
function LLst(a: IntRange): LinkedList<integer>;
/// Возвращает двусвязный список, заполненный диапазоном значений
function LLst(a: CharRange): LinkedList<char>;
/// Возвращает множество на базе хеш таблицы, заполненное указанными значениями
function HSet<T>(params a: array of T): HashSet<T>;
@ -2476,10 +2443,6 @@ function HSetStr(params a: array of string): HashSet<string>;
function SSet<T>(params a: array of T): SortedSet<T>;
/// Возвращает множество на базе бинарного дерева поиска, заполненное значениями из последовательности
function SSet<T>(a: sequence of T): SortedSet<T>;
/// Возвращает множество на базе бинарного дерева поиска, заполненное диапазоном значений
function SSet(a: IntRange): SortedSet<integer>;
/// Возвращает множество на базе бинарного дерева поиска, заполненное диапазоном значений
function SSet(a: CharRange): SortedSet<char>;
/// Возвращает множество на базе бинарного дерева поиска, заполненное целыми значениями
function SSetInt(params a: array of integer): SortedSet<integer>;
/// Возвращает множество на базе бинарного дерева поиска, заполненное строковыми значениями
@ -4197,13 +4160,13 @@ begin
Result := sb.ToString;
end;
function IntRange.GetEnumerator(): IEnumerator<integer> := Range(l,h).GetEnumerator;
function IntRange.GetEnumerator: IEnumerator<integer> := Range(l,h).GetEnumerator;
function IntRange.Step(n: integer): sequence of integer := Range(l,h,n);
function IntRange.Reverse: sequence of integer := Range(l,h).Reverse;
function IntRange.Reverse: sequence of integer := Range(h,l, -1);
function CharRange.GetEnumerator(): IEnumerator<char> := Range(l,h).GetEnumerator;
function CharRange.GetEnumerator: IEnumerator<char> := Range(l,h).GetEnumerator;
function CharRange.Step(n: integer): sequence of char := Range(l,h,n);
function CharRange.Reverse: sequence of char := Range(l,h).Reverse;
function CharRange.Reverse: sequence of char := Range(h,l, -1);
//------------------------------------------------------------------------------
// Операции для string и char
@ -5215,10 +5178,6 @@ function LLst<T>(params a: array of T): LinkedList<T> := new LinkedList<T>(a);
function LLst<T>(a: sequence of T): LinkedList<T> := new LinkedList<T>(a);
function LLst(a: IntRange): LinkedList<integer> := a.ToLinkedList;
function LLst(a: CharRange): LinkedList<char> := a.ToLinkedList;
function HSet<T>(params a: array of T): HashSet<T> := new HashSet<T>(a);
@ -5241,12 +5200,6 @@ function HSet(a: IntRange): HashSet<integer> := a.ToHashSet;
function HSet(a: CharRange): HashSet<char> := a.ToHashSet;
function SSet(a: IntRange): SortedSet<integer> := a.ToSortedSet;
function SSet(a: CharRange): SortedSet<char> := a.ToSortedSet;
function Dict<TKey, TVal>(params pairs: array of KeyValuePair<TKey, TVal>): Dictionary<TKey, TVal>;
begin
Result := new Dictionary<TKey, TVal>();