TDataValue as new global variant type
This commit is contained in:
+40
-20
@@ -9,22 +9,15 @@ uses
|
||||
Myc.Data.Decimal;
|
||||
|
||||
type
|
||||
TDataValueKind = (vkVoid, vkScalar, vkCallable, vkText, vkSeries, vkRecordSeries, vkRecord, vkMemberSeries);
|
||||
TDataValueKind = (vkVoid, vkScalar, vkInterface, vkText, vkSeries, vkRecordSeries, vkRecord, vkMemberSeries, vkGeneric);
|
||||
|
||||
TDataValue = record
|
||||
public
|
||||
type
|
||||
ICallable = interface
|
||||
function GetArity: Integer;
|
||||
function Invoke(const AVisitor: IInterface; const ASelf: TDataValue; const AArgs: TArray<TDataValue>): TDataValue;
|
||||
property Arity: Integer read GetArity;
|
||||
end;
|
||||
|
||||
TVal<T> = class(TInterfacedObject)
|
||||
Value: T;
|
||||
constructor Create(const AValue: T);
|
||||
end;
|
||||
|
||||
private
|
||||
var
|
||||
FKind: TDataValueKind;
|
||||
@@ -37,8 +30,11 @@ type
|
||||
class function Void: TDataValue; inline; static;
|
||||
|
||||
class operator Implicit(const AValue: TScalar): TDataValue; overload; inline;
|
||||
class operator Implicit(const AValue: ICallable): TDataValue; overload; inline;
|
||||
class operator Implicit(const AValue: String): TDataValue; overload; inline;
|
||||
class operator Implicit(const AValue: IInterface): TDataValue; overload; inline;
|
||||
|
||||
class function From<T: record>(const [ref] AValue: T): TDataValue; static; inline;
|
||||
function AsVal<T: record>: TVal<T>; inline;
|
||||
|
||||
class function FromSeries(const [ref] AValue: TScalarSeries): TDataValue; static; inline;
|
||||
class function FromRecordSeries(const [ref] AValue: TScalarRecordSeries): TDataValue; static; inline;
|
||||
@@ -46,13 +42,15 @@ type
|
||||
class function FromMemberSeries(const [ref] AValue: TScalarMemberSeries): TDataValue; static; inline;
|
||||
|
||||
function AsScalar: TScalar; inline;
|
||||
function AsCallable: ICallable; inline;
|
||||
function AsInterface: IInterface; inline;
|
||||
function AsText: String; inline;
|
||||
function AsRecordSeries: TVal<TScalarRecordSeries>; inline;
|
||||
function AsRecord: TVal<TScalarRecord>; inline;
|
||||
function AsMemberSeries: TVal<TScalarMemberSeries>; inline;
|
||||
function AsSeries: TVal<TScalarSeries>; inline;
|
||||
|
||||
procedure SetVoid;
|
||||
|
||||
function ToString: String;
|
||||
property IsVoid: Boolean read GetIsVoid;
|
||||
property Kind: TDataValueKind read GetKind;
|
||||
@@ -60,6 +58,9 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
TypInfo;
|
||||
|
||||
{ TDataValue.TVal<T> }
|
||||
|
||||
constructor TDataValue.TVal<T>.Create(const AValue: T);
|
||||
@@ -72,15 +73,15 @@ end;
|
||||
|
||||
class operator TDataValue.Initialize(out Dest: TDataValue);
|
||||
begin
|
||||
Dest.FKind := vkVoid; // Geändert
|
||||
Dest.FKind := vkVoid;
|
||||
Dest.FInterface := nil;
|
||||
end;
|
||||
|
||||
function TDataValue.AsCallable: ICallable;
|
||||
function TDataValue.AsInterface: IInterface;
|
||||
begin
|
||||
if (FKind <> vkCallable) then
|
||||
raise EInvalidCast.Create('Cannot read value as a Callable.');
|
||||
Result := ICallable(FInterface);
|
||||
if (FKind <> vkInterface) then
|
||||
raise EInvalidCast.Create('Cannot read value as an Interface.');
|
||||
Result := FInterface;
|
||||
end;
|
||||
|
||||
function TDataValue.AsMemberSeries: TVal<TScalarMemberSeries>;
|
||||
@@ -90,6 +91,13 @@ begin
|
||||
Result := TVal<TScalarMemberSeries>(FInterface);
|
||||
end;
|
||||
|
||||
function TDataValue.AsVal<T>: TVal<T>;
|
||||
begin
|
||||
if (FKind <> vkGeneric) then
|
||||
raise EInvalidCast.Create('Cannot read value as ' + PTypeInfo(TypeInfo(T)).Name + '.');
|
||||
Result := TVal<T>(FInterface);
|
||||
end;
|
||||
|
||||
function TDataValue.AsRecord: TVal<TScalarRecord>;
|
||||
begin
|
||||
if (FKind <> vkRecord) then
|
||||
@@ -125,6 +133,12 @@ begin
|
||||
Result := (FInterface as TVal<String>).Value;
|
||||
end;
|
||||
|
||||
class function TDataValue.From<T>(const [ref] AValue: T): TDataValue;
|
||||
begin
|
||||
Result.FKind := vkGeneric;
|
||||
Result.FInterface := TVal<T>.Create(AValue);
|
||||
end;
|
||||
|
||||
class function TDataValue.FromMemberSeries(const [ref] AValue: TScalarMemberSeries): TDataValue;
|
||||
begin
|
||||
Result.FKind := vkMemberSeries;
|
||||
@@ -153,9 +167,9 @@ begin
|
||||
Result.FScalar := Default(TScalar);
|
||||
end;
|
||||
|
||||
class operator TDataValue.Implicit(const AValue: ICallable): TDataValue;
|
||||
class operator TDataValue.Implicit(const AValue: IInterface): TDataValue;
|
||||
begin
|
||||
Result.FKind := vkCallable;
|
||||
Result.FKind := vkInterface;
|
||||
Result.FInterface := AValue;
|
||||
Result.FScalar := Default(TScalar);
|
||||
end;
|
||||
@@ -176,7 +190,7 @@ end;
|
||||
|
||||
function TDataValue.GetIsVoid: Boolean;
|
||||
begin
|
||||
Result := FKind = vkVoid; // Geändert
|
||||
Result := FKind = vkVoid;
|
||||
end;
|
||||
|
||||
function TDataValue.GetKind: TDataValueKind;
|
||||
@@ -184,17 +198,23 @@ begin
|
||||
Result := FKind;
|
||||
end;
|
||||
|
||||
procedure TDataValue.SetVoid;
|
||||
begin
|
||||
FKind := vkVoid;
|
||||
FInterface := nil;
|
||||
end;
|
||||
|
||||
function TDataValue.ToString: String;
|
||||
begin
|
||||
case FKind of
|
||||
vkScalar: Result := FScalar.ToString;
|
||||
vkCallable: Result := '<callable>';
|
||||
vkInterface: Result := '<interface>';
|
||||
vkText: Result := AsText;
|
||||
vkSeries: Result := '<series>';
|
||||
vkRecordSeries: Result := '<record_series>';
|
||||
vkRecord: Result := '<record>';
|
||||
vkMemberSeries: Result := '<member_series>';
|
||||
vkVoid: Result := '<void>'; // Geändert
|
||||
vkVoid: Result := '<void>';
|
||||
else
|
||||
Result := '[Unknown DataValue]';
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user