Files
MycLib/Src/Data/Myc.Data.Types.Tuple.pas
T
Michael Schimmel 54d470b2f8 New type system
2025-08-26 15:49:28 +02:00

451 lines
12 KiB
ObjectPascal

unit Myc.Data.Types.Tuple;
interface
uses
System.SysUtils,
Myc.Data.Types;
type
// Implements the singleton tuple data type.
TImplDataTupleType = class(TInterfacedObject, IDataType, IDataTupleType)
strict private
class var
FSingleton: IDataTupleType;
class constructor CreateClass;
private
function GetName: String;
function GetKind: TDataKind;
public
function CreateValue(const AItems: array of IDataValue): IDataTupleValue;
class property Singleton: IDataTupleType read FSingleton;
end;
implementation
type
// Implements the simple tuple data value.
TImplDataTupleValue = class(TInterfacedObject, IDataValue, IDataTupleValue)
private
FItems: TArray<IDataValue>;
function GetDataType: IDataType;
function GetAsString: string;
function GetItemCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
constructor Create(const AItems: array of IDataValue);
end;
// Optimized singleton implementation for a tuple with 0 elements.
TImplDataTupleValue0 = class(TInterfacedObject, IDataValue, IDataTupleValue)
strict private
class var
FSingleton: IDataTupleValue;
class constructor CreateClass;
private
function GetDataType: IDataType;
function GetAsString: string;
function GetItemCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
class property Singleton: IDataTupleValue read FSingleton;
end;
// Optimized implementation for a tuple with 1 element.
TImplDataTupleValue1 = class(TInterfacedObject, IDataValue, IDataTupleValue)
private
FItem0: IDataValue;
function GetDataType: IDataType;
function GetAsString: string;
function GetItemCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
constructor Create(const AItems: array of IDataValue);
end;
// Optimized implementation for a tuple with 2 elements.
TImplDataTupleValue2 = class(TInterfacedObject, IDataValue, IDataTupleValue)
private
FItem0, FItem1: IDataValue;
function GetDataType: IDataType;
function GetAsString: string;
function GetItemCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
constructor Create(const AItems: array of IDataValue);
end;
// Optimized implementation for a tuple with 3 elements.
TImplDataTupleValue3 = class(TInterfacedObject, IDataValue, IDataTupleValue)
private
FItem0, FItem1, FItem2: IDataValue;
function GetDataType: IDataType;
function GetAsString: string;
function GetItemCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
constructor Create(const AItems: array of IDataValue);
end;
// Optimized implementation for a tuple with 4 elements.
TImplDataTupleValue4 = class(TInterfacedObject, IDataValue, IDataTupleValue)
private
FItem0, FItem1, FItem2, FItem3: IDataValue;
function GetDataType: IDataType;
function GetAsString: string;
function GetItemCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
constructor Create(const AItems: array of IDataValue);
end;
// Optimized implementation for a tuple with 5 elements.
TImplDataTupleValue5 = class(TInterfacedObject, IDataValue, IDataTupleValue)
private
FItem0, FItem1, FItem2, FItem3, FItem4: IDataValue;
function GetDataType: IDataType;
function GetAsString: string;
function GetItemCount: Integer;
function GetItem(Idx: Integer): IDataValue;
public
constructor Create(const AItems: array of IDataValue);
end;
{ TImplDataTupleValue (generic implementation for N > 5 elements) }
constructor TImplDataTupleValue.Create(const AItems: array of IDataValue);
var
i: Integer;
begin
inherited Create;
SetLength(FItems, Length(AItems));
for i := 0 to High(AItems) do
FItems[i] := AItems[i];
end;
function TImplDataTupleValue.GetDataType: IDataType;
begin
Result := TImplDataTupleType.Singleton;
end;
function TImplDataTupleValue.GetAsString: string;
var
sb: TStringBuilder;
i: Integer;
begin
sb := TStringBuilder.Create;
try
sb.Append('(');
for i := 0 to High(FItems) do
begin
sb.Append(FItems[i].AsString);
if (i < High(FItems)) then
sb.Append(', ');
end;
sb.Append(')');
Result := sb.ToString;
finally
sb.Free;
end;
end;
function TImplDataTupleValue.GetItem(Idx: Integer): IDataValue;
begin
Result := FItems[Idx];
end;
function TImplDataTupleValue.GetItemCount: Integer;
begin
Result := Length(FItems);
end;
{ TImplDataTupleValue0 }
class constructor TImplDataTupleValue0.CreateClass;
begin
FSingleton := TImplDataTupleValue0.Create;
end;
function TImplDataTupleValue0.GetAsString: string;
begin
Result := '()';
end;
function TImplDataTupleValue0.GetDataType: IDataType;
begin
Result := TImplDataTupleType.Singleton;
end;
function TImplDataTupleValue0.GetItem(Idx: Integer): IDataValue;
begin
raise EArgumentException.Create('Index out of bounds');
end;
function TImplDataTupleValue0.GetItemCount: Integer;
begin
Result := 0;
end;
{ TImplDataTupleValue1 }
constructor TImplDataTupleValue1.Create(const AItems: array of IDataValue);
begin
inherited Create;
FItem0 := AItems[0];
end;
function TImplDataTupleValue1.GetAsString: string;
begin
Result := '(' + FItem0.AsString + ')';
end;
function TImplDataTupleValue1.GetDataType: IDataType;
begin
Result := TImplDataTupleType.Singleton;
end;
function TImplDataTupleValue1.GetItem(Idx: Integer): IDataValue;
begin
case Idx of
0: Result := FItem0;
else
raise EArgumentException.Create('Index out of bounds');
end;
end;
function TImplDataTupleValue1.GetItemCount: Integer;
begin
Result := 1;
end;
{ TImplDataTupleValue2 }
constructor TImplDataTupleValue2.Create(const AItems: array of IDataValue);
begin
inherited Create;
FItem0 := AItems[0];
FItem1 := AItems[1];
end;
function TImplDataTupleValue2.GetAsString: string;
begin
Result := '(' + FItem0.AsString + ', ' + FItem1.AsString + ')';
end;
function TImplDataTupleValue2.GetDataType: IDataType;
begin
Result := TImplDataTupleType.Singleton;
end;
function TImplDataTupleValue2.GetItem(Idx: Integer): IDataValue;
begin
case Idx of
0: Result := FItem0;
1: Result := FItem1;
else
raise EArgumentException.Create('Index out of bounds');
end;
end;
function TImplDataTupleValue2.GetItemCount: Integer;
begin
Result := 2;
end;
{ TImplDataTupleValue3 }
constructor TImplDataTupleValue3.Create(const AItems: array of IDataValue);
begin
inherited Create;
FItem0 := AItems[0];
FItem1 := AItems[1];
FItem2 := AItems[2];
end;
function TImplDataTupleValue3.GetAsString: string;
var
sb: TStringBuilder;
begin
sb := TStringBuilder.Create;
try
sb.Append('(');
sb.Append(FItem0.AsString);
sb.Append(', ');
sb.Append(FItem1.AsString);
sb.Append(', ');
sb.Append(FItem2.AsString);
sb.Append(')');
Result := sb.ToString;
finally
sb.Free;
end;
end;
function TImplDataTupleValue3.GetDataType: IDataType;
begin
Result := TImplDataTupleType.Singleton;
end;
function TImplDataTupleValue3.GetItem(Idx: Integer): IDataValue;
begin
case Idx of
0: Result := FItem0;
1: Result := FItem1;
2: Result := FItem2;
else
raise EArgumentException.Create('Index out of bounds');
end;
end;
function TImplDataTupleValue3.GetItemCount: Integer;
begin
Result := 3;
end;
{ TImplDataTupleValue4 }
constructor TImplDataTupleValue4.Create(const AItems: array of IDataValue);
begin
inherited Create;
FItem0 := AItems[0];
FItem1 := AItems[1];
FItem2 := AItems[2];
FItem3 := AItems[3];
end;
function TImplDataTupleValue4.GetAsString: string;
var
sb: TStringBuilder;
begin
sb := TStringBuilder.Create;
try
sb.Append('(');
sb.Append(FItem0.AsString);
sb.Append(', ');
sb.Append(FItem1.AsString);
sb.Append(', ');
sb.Append(FItem2.AsString);
sb.Append(', ');
sb.Append(FItem3.AsString);
sb.Append(')');
Result := sb.ToString;
finally
sb.Free;
end;
end;
function TImplDataTupleValue4.GetDataType: IDataType;
begin
Result := TImplDataTupleType.Singleton;
end;
function TImplDataTupleValue4.GetItem(Idx: Integer): IDataValue;
begin
case Idx of
0: Result := FItem0;
1: Result := FItem1;
2: Result := FItem2;
3: Result := FItem3;
else
raise EArgumentException.Create('Index out of bounds');
end;
end;
function TImplDataTupleValue4.GetItemCount: Integer;
begin
Result := 4;
end;
{ TImplDataTupleValue5 }
constructor TImplDataTupleValue5.Create(const AItems: array of IDataValue);
begin
inherited Create;
FItem0 := AItems[0];
FItem1 := AItems[1];
FItem2 := AItems[2];
FItem3 := AItems[3];
FItem4 := AItems[4];
end;
function TImplDataTupleValue5.GetAsString: string;
var
sb: TStringBuilder;
begin
sb := TStringBuilder.Create;
try
sb.Append('(');
sb.Append(FItem0.AsString);
sb.Append(', ');
sb.Append(FItem1.AsString);
sb.Append(', ');
sb.Append(FItem2.AsString);
sb.Append(', ');
sb.Append(FItem3.AsString);
sb.Append(', ');
sb.Append(FItem4.AsString);
sb.Append(')');
Result := sb.ToString;
finally
sb.Free;
end;
end;
function TImplDataTupleValue5.GetDataType: IDataType;
begin
Result := TImplDataTupleType.Singleton;
end;
function TImplDataTupleValue5.GetItem(Idx: Integer): IDataValue;
begin
case Idx of
0: Result := FItem0;
1: Result := FItem1;
2: Result := FItem2;
3: Result := FItem3;
4: Result := FItem4;
else
raise EArgumentException.Create('Index out of bounds');
end;
end;
function TImplDataTupleValue5.GetItemCount: Integer;
begin
Result := 5;
end;
{ TImplDataTupleType }
class constructor TImplDataTupleType.CreateClass;
begin
FSingleton := TImplDataTupleType.Create;
end;
function TImplDataTupleType.CreateValue(const AItems: array of IDataValue): IDataTupleValue;
begin
// Use optimized implementations for tuples with 0 to 5 elements.
case Length(AItems) of
0: Result := TImplDataTupleValue0.Singleton;
1: Result := TImplDataTupleValue1.Create(AItems);
2: Result := TImplDataTupleValue2.Create(AItems);
3: Result := TImplDataTupleValue3.Create(AItems);
4: Result := TImplDataTupleValue4.Create(AItems);
5: Result := TImplDataTupleValue5.Create(AItems);
else
// Use the generic implementation for tuples with more than 5 elements.
Result := TImplDataTupleValue.Create(AItems);
end;
end;
function TImplDataTupleType.GetName: String;
begin
Result := 'Tuple';
end;
function TImplDataTupleType.GetKind: TDataKind;
begin
Result := dkTuple;
end;
end.