unit Myc.Data.Value; interface uses System.SysUtils, Myc.Data.Scalar, Myc.Data.Series, Myc.Data.Decimal; type TDataValueKind = (vkVoid, vkScalar, vkCallable, vkText, vkSeries, vkRecordSeries, vkRecord, vkMemberSeries); TDataValue = record public type ICallable = interface function GetArity: Integer; function Invoke(const AVisitor: IInterface; const ASelf: TDataValue; const AArgs: TArray): TDataValue; property Arity: Integer read GetArity; end; TVal = class(TInterfacedObject) Value: T; constructor Create(const AValue: T); end; private var FKind: TDataValueKind; FScalar: TScalar; FInterface: IInterface; function GetKind: TDataValueKind; inline; function GetIsVoid: Boolean; inline; public class operator Initialize(out Dest: TDataValue); 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 function FromSeries(const [ref] AValue: TScalarSeries): TDataValue; static; inline; class function FromRecordSeries(const [ref] AValue: TScalarRecordSeries): TDataValue; static; inline; class function FromRecord(const [ref] AValue: TScalarRecord): TDataValue; static; inline; class function FromMemberSeries(const [ref] AValue: TScalarMemberSeries): TDataValue; static; inline; function AsScalar: TScalar; inline; function AsCallable: ICallable; inline; function AsText: String; inline; function AsRecordSeries: TVal; inline; function AsRecord: TVal; inline; function AsMemberSeries: TVal; inline; function AsSeries: TVal; inline; function ToString: String; property IsVoid: Boolean read GetIsVoid; property Kind: TDataValueKind read GetKind; end; implementation { TDataValue.TVal } constructor TDataValue.TVal.Create(const AValue: T); begin inherited Create; Value := AValue; end; { TDataValue } class operator TDataValue.Initialize(out Dest: TDataValue); begin Dest.FKind := vkVoid; // Geändert Dest.FInterface := nil; end; function TDataValue.AsCallable: ICallable; begin if (FKind <> vkCallable) then raise EInvalidCast.Create('Cannot read value as a Callable.'); Result := ICallable(FInterface); end; function TDataValue.AsMemberSeries: TVal; begin if (FKind <> vkMemberSeries) then raise EInvalidCast.Create('Cannot read value as MemberSeries.'); Result := TVal(FInterface); end; function TDataValue.AsRecord: TVal; begin if (FKind <> vkRecord) then raise EInvalidCast.Create('Cannot read value as Record.'); Result := (FInterface as TVal); end; function TDataValue.AsRecordSeries: TVal; begin if (FKind <> vkRecordSeries) then raise EInvalidCast.Create('Cannot read value as RecordSeries.'); Result := TVal(FInterface); end; function TDataValue.AsScalar: TScalar; begin if (FKind <> vkScalar) then raise EInvalidCast.Create('Cannot read value as a Scalar.'); Result := FScalar; end; function TDataValue.AsSeries: TVal; begin if (FKind <> vkSeries) then raise EInvalidCast.Create('Cannot read value as Series.'); Result := TVal(FInterface); end; function TDataValue.AsText: String; begin if (FKind <> vkText) then raise EInvalidCast.Create('Cannot read value as Text.'); Result := (FInterface as TVal).Value; end; class function TDataValue.FromMemberSeries(const [ref] AValue: TScalarMemberSeries): TDataValue; begin Result.FKind := vkMemberSeries; Result.FInterface := TVal.Create(AValue); Result.FScalar := Default(TScalar); end; class function TDataValue.FromRecord(const [ref] AValue: TScalarRecord): TDataValue; begin Result.FKind := vkRecord; Result.FInterface := TVal.Create(AValue); Result.FScalar := Default(TScalar); end; class function TDataValue.FromRecordSeries(const [ref] AValue: TScalarRecordSeries): TDataValue; begin Result.FKind := vkRecordSeries; Result.FInterface := TVal.Create(AValue); Result.FScalar := Default(TScalar); end; class function TDataValue.FromSeries(const [ref] AValue: TScalarSeries): TDataValue; begin Result.FKind := vkSeries; Result.FInterface := TVal.Create(AValue); Result.FScalar := Default(TScalar); end; class operator TDataValue.Implicit(const AValue: ICallable): TDataValue; begin Result.FKind := vkCallable; Result.FInterface := AValue; Result.FScalar := Default(TScalar); end; class operator TDataValue.Implicit(const AValue: TScalar): TDataValue; begin Result.FKind := vkScalar; Result.FScalar := AValue; Result.FInterface := nil; end; class operator TDataValue.Implicit(const AValue: String): TDataValue; begin Result.FKind := vkText; Result.FInterface := TVal.Create(AValue); Result.FScalar := Default(TScalar); end; function TDataValue.GetIsVoid: Boolean; begin Result := FKind = vkVoid; // Geändert end; function TDataValue.GetKind: TDataValueKind; begin Result := FKind; end; function TDataValue.ToString: String; begin case FKind of vkScalar: Result := FScalar.ToString; vkCallable: Result := ''; vkText: Result := AsText; vkSeries: Result := ''; vkRecordSeries: Result := ''; vkRecord: Result := ''; vkMemberSeries: Result := ''; vkVoid: Result := ''; // Geändert else Result := '[Unknown DataValue]'; end; end; class function TDataValue.Void: TDataValue; begin Result := Default(TDataValue); end; end.