diff --git a/Src/AST/Myc.Ast.RTL.Core.pas b/Src/AST/Myc.Ast.RTL.Core.pas index adf8515..77a1fd3 100644 --- a/Src/AST/Myc.Ast.RTL.Core.pas +++ b/Src/AST/Myc.Ast.RTL.Core.pas @@ -130,7 +130,9 @@ begin if Args[0].Kind <> vkMethod then raise EArgumentException.Create('The argument to Memoize must be a function.'); - var cCache: TManaged> := TDictionary.Create; + // create a managed dictionary + var cCache: TDataValue := TDictionary.Create; + funcToMemoize := Args[0].AsMethod(); memoizedFunc := @@ -151,7 +153,7 @@ begin else key := argScalar.Value.AsInt64; - var cache: TDictionary := cCache; + var cache := cCache.AsObject as TDictionary; if cache.TryGetValue(key, Result) then exit; diff --git a/Src/Data/Myc.Data.Value.pas b/Src/Data/Myc.Data.Value.pas index ede6052..b5c78a5 100644 --- a/Src/Data/Myc.Data.Value.pas +++ b/Src/Data/Myc.Data.Value.pas @@ -4,11 +4,12 @@ interface uses System.SysUtils, + Myc.Utils, Myc.Data.Scalar, Myc.Data.Series; type - TDataValueKind = (vkVoid, vkScalar, vkText, vkSeries, vkRecordSeries, vkRecord, vkMethod, vkGeneric); + TDataValueKind = (vkVoid, vkScalar, vkText, vkSeries, vkRecordSeries, vkRecord, vkManagedObject, vkMethod, vkGeneric); TDataValue = record type @@ -24,6 +25,10 @@ type constructor Create(const AValue: T); end; + TObjVal = class(TVal) + destructor Destroy; override; + end; + ILazy = interface function GetKind: TDataValueKind; function GetValue: TDataValue; @@ -50,6 +55,7 @@ type class operator Implicit(const AValue: TScalar): TDataValue; overload; inline; class operator Implicit(const AValue: String): TDataValue; overload; inline; class operator Implicit(const AValue: TDataValue.TFunc): TDataValue; overload; inline; + class operator Implicit(const AValue: TObject): TDataValue; overload; inline; class function FromGeneric(const [ref] AValue: T): TDataValue; static; inline; function AsGeneric: T; inline; @@ -68,6 +74,7 @@ type function AsRecordSeries: IRecordSeries; inline; function AsRecord: TScalarRecord; inline; function AsSeries: ISeries; inline; + function AsObject: TObject; overload; inline; function ToString: String; property IsVoid: Boolean read GetIsVoid; @@ -214,6 +221,15 @@ begin Result := TVal(FInterface).Value; end; +function TDataValue.AsObject: TObject; +begin + if FKind = Ord(vkLazy) then + exit(AsLazy.Value.AsObject); + if (FKind <> Ord(vkManagedObject)) then + raise EInvalidCast.Create('Cannot read value as object.'); + Result := (FInterface as TObjVal).Value; +end; + function TDataValue.AsRecord: TScalarRecord; begin if FKind = Ord(vkLazy) then @@ -413,6 +429,12 @@ begin TFunc(Result.FInterface) := AValue; end; +class operator TDataValue.Implicit(const AValue: TObject): TDataValue; +begin + Result.FKind := Ord(vkManagedObject); + Result.FInterface := TObjVal.Create(AValue); +end; + { TDataValueKindHelper } function TDataValueKindHelper.ToString: string; @@ -466,4 +488,10 @@ begin Result := mappedValue.AsScalar; end; +destructor TDataValue.TObjVal.Destroy; +begin + Value.Free; + inherited; +end; + end.