TDataValue as new global variant type
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
<ProjectVersion>20.3</ProjectVersion>
|
<ProjectVersion>20.3</ProjectVersion>
|
||||||
<FrameworkType>FMX</FrameworkType>
|
<FrameworkType>FMX</FrameworkType>
|
||||||
<Base>True</Base>
|
<Base>True</Base>
|
||||||
<Config Condition="'$(Config)'==''">Release</Config>
|
<Config Condition="'$(Config)'==''">Debug</Config>
|
||||||
<Platform Condition="'$(Platform)'==''">Win64</Platform>
|
<Platform Condition="'$(Platform)'==''">Win64</Platform>
|
||||||
<ProjectName Condition="'$(ProjectName)'==''">ASTPlayground</ProjectName>
|
<ProjectName Condition="'$(ProjectName)'==''">ASTPlayground</ProjectName>
|
||||||
<TargetedPlatforms>2</TargetedPlatforms>
|
<TargetedPlatforms>2</TargetedPlatforms>
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ uses
|
|||||||
Myc.Ast;
|
Myc.Ast;
|
||||||
|
|
||||||
type
|
type
|
||||||
// TEvaluatorVisitor is the base implementation for evaluating an AST.
|
|
||||||
TEvaluatorVisitor = class(TInterfacedObject, IAstVisitor)
|
TEvaluatorVisitor = class(TInterfacedObject, IAstVisitor)
|
||||||
private
|
private
|
||||||
FScope: IExecutionScope;
|
FScope: IExecutionScope;
|
||||||
@@ -40,7 +39,6 @@ type
|
|||||||
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; virtual;
|
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; virtual;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// TDebugEvaluatorVisitor now overrides all visit methods for full tracing
|
|
||||||
TDebugEvaluatorVisitor = class(TEvaluatorVisitor)
|
TDebugEvaluatorVisitor = class(TEvaluatorVisitor)
|
||||||
private
|
private
|
||||||
FLog: TStrings;
|
FLog: TStrings;
|
||||||
@@ -73,7 +71,6 @@ type
|
|||||||
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override;
|
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Registers all native core functions in the given scope.
|
|
||||||
procedure RegisterNativeFunctions(const AScope: IExecutionScope);
|
procedure RegisterNativeFunctions(const AScope: IExecutionScope);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@@ -87,10 +84,18 @@ uses
|
|||||||
Myc.Data.Scalar.JSON;
|
Myc.Data.Scalar.JSON;
|
||||||
|
|
||||||
type
|
type
|
||||||
// The signature for a native Delphi function callable from the script.
|
|
||||||
TNativeFunction = function(const Args: TArray<TDataValue>): TDataValue;
|
TNativeFunction = function(const Args: TArray<TDataValue>): TDataValue;
|
||||||
|
|
||||||
TClosureValue = class(TInterfacedObject, TDataValue.ICallable)
|
TClosure = class(TInterfacedObject)
|
||||||
|
function GetArity: Integer; virtual; abstract;
|
||||||
|
function Invoke(
|
||||||
|
const AVisitor: IAstVisitor;
|
||||||
|
const ASelf: TDataValue;
|
||||||
|
const AArgNodes: TList<IAstNode>
|
||||||
|
): TDataValue; virtual; abstract;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TClosureValue = class(TClosure)
|
||||||
private
|
private
|
||||||
FLambdaNode: ILambdaExpressionNode;
|
FLambdaNode: ILambdaExpressionNode;
|
||||||
FClosureScope: IExecutionScope;
|
FClosureScope: IExecutionScope;
|
||||||
@@ -101,22 +106,18 @@ type
|
|||||||
const AClosureScope: IExecutionScope;
|
const AClosureScope: IExecutionScope;
|
||||||
const AUpvalues: TArray<IValueCell>
|
const AUpvalues: TArray<IValueCell>
|
||||||
);
|
);
|
||||||
// ICallable implementation (the generic, slower path)
|
function GetArity: Integer; override;
|
||||||
function GetArity: Integer;
|
function Invoke(const AVisitor: IAstVisitor; const ASelf: TDataValue; const AArgNodes: TList<IAstNode>): TDataValue; override;
|
||||||
function Invoke(const AVisitor: IInterface; const ASelf: TDataValue; const AArgs: TArray<TDataValue>): TDataValue;
|
|
||||||
// Fast Path
|
|
||||||
function InvokeFast(const AVisitor: IAstVisitor; const ASelf: TDataValue; const AArgNodes: TList<IAstNode>): TDataValue;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TNativeClosure = class(TInterfacedObject, TDataValue.ICallable)
|
TNativeClosure = class(TClosure)
|
||||||
private
|
private
|
||||||
FMethod: TNativeFunction;
|
FMethod: TNativeFunction;
|
||||||
FArity: Integer;
|
FArity: Integer;
|
||||||
public
|
public
|
||||||
constructor Create(const AMethod: TNativeFunction; AArity: Integer);
|
constructor Create(const AMethod: TNativeFunction; AArity: Integer);
|
||||||
// ICallable implementation
|
function GetArity: Integer; override;
|
||||||
function GetArity: Integer;
|
function Invoke(const AVisitor: IAstVisitor; const ASelf: TDataValue; const AArgNodes: TList<IAstNode>): TDataValue; override;
|
||||||
function Invoke(const AVisitor: IInterface; const ASelf: TDataValue; const AArgs: TArray<TDataValue>): TDataValue;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- Native Functions Implementation ---
|
// --- Native Functions Implementation ---
|
||||||
@@ -169,15 +170,16 @@ begin
|
|||||||
Result := Length(FLambdaNode.Parameters);
|
Result := Length(FLambdaNode.Parameters);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// This is the generic, slightly slower path, kept for compatibility with ICallable.
|
function TClosureValue.Invoke(const AVisitor: IAstVisitor; const ASelf: TDataValue; const AArgNodes: TList<IAstNode>): TDataValue;
|
||||||
function TClosureValue.Invoke(const AVisitor: IInterface; const ASelf: TDataValue; const AArgs: TArray<TDataValue>): TDataValue;
|
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
descriptor: IScopeDescriptor;
|
descriptor: IScopeDescriptor;
|
||||||
callScope: IExecutionScope;
|
callScope: IExecutionScope;
|
||||||
adr: TResolvedAddress;
|
adr: TResolvedAddress;
|
||||||
callVisitor: IAstVisitor;
|
|
||||||
begin
|
begin
|
||||||
|
if (AArgNodes.Count <> GetArity) then
|
||||||
|
raise EArgumentException.CreateFmt('Argument count mismatch: expected %d, got %d', [GetArity, AArgNodes.Count]);
|
||||||
|
|
||||||
descriptor := FLambdaNode.ScopeDescriptor;
|
descriptor := FLambdaNode.ScopeDescriptor;
|
||||||
if not Assigned(descriptor) then
|
if not Assigned(descriptor) then
|
||||||
raise EParserError.Create('Lambda has no scope descriptor. Did the binder run?');
|
raise EParserError.Create('Lambda has no scope descriptor. Did the binder run?');
|
||||||
@@ -189,52 +191,12 @@ begin
|
|||||||
adr.SlotIndex := 0;
|
adr.SlotIndex := 0;
|
||||||
callScope[adr].Value := ASelf;
|
callScope[adr].Value := ASelf;
|
||||||
|
|
||||||
for i := 0 to High(AArgs) do
|
|
||||||
begin
|
|
||||||
adr.SlotIndex := FLambdaNode.Parameters[i].Address.SlotIndex;
|
|
||||||
callScope[adr].Value := AArgs[i];
|
|
||||||
end;
|
|
||||||
|
|
||||||
callVisitor := (AVisitor as TEvaluatorVisitor).CreateVisitorForScope(callScope);
|
|
||||||
Result := FLambdaNode.Body.Accept(callVisitor);
|
|
||||||
end;
|
|
||||||
|
|
||||||
// This is the new, optimized method that evaluates argument nodes directly.
|
|
||||||
function TClosureValue.InvokeFast(const AVisitor: IAstVisitor; const ASelf: TDataValue; const AArgNodes: TList<IAstNode>): TDataValue;
|
|
||||||
var
|
|
||||||
i: Integer;
|
|
||||||
descriptor: IScopeDescriptor;
|
|
||||||
callScope: IExecutionScope;
|
|
||||||
adr: TResolvedAddress;
|
|
||||||
begin
|
|
||||||
// Arity check
|
|
||||||
if (AArgNodes.Count <> Length(FLambdaNode.Parameters)) then
|
|
||||||
raise EArgumentException
|
|
||||||
.CreateFmt('Argument count mismatch: expected %d, got %d', [Length(FLambdaNode.Parameters), AArgNodes.Count]);
|
|
||||||
|
|
||||||
descriptor := FLambdaNode.ScopeDescriptor;
|
|
||||||
if not Assigned(descriptor) then
|
|
||||||
raise EParserError.Create('Lambda has no scope descriptor. Did the binder run?');
|
|
||||||
|
|
||||||
// Create the scope for the call directly
|
|
||||||
callScope := TExecutionScope.Create(FClosureScope, descriptor, FUpvalues);
|
|
||||||
|
|
||||||
adr.Kind := akLocalOrParent;
|
|
||||||
adr.ScopeDepth := 0;
|
|
||||||
|
|
||||||
// Set the 'Self' variable
|
|
||||||
adr.SlotIndex := 0;
|
|
||||||
callScope[adr].Value := ASelf;
|
|
||||||
|
|
||||||
// Evaluate arguments DIRECTLY into the new scope (no temporary array!)
|
|
||||||
for i := 0 to AArgNodes.Count - 1 do
|
for i := 0 to AArgNodes.Count - 1 do
|
||||||
begin
|
begin
|
||||||
adr.SlotIndex := FLambdaNode.Parameters[i].Address.SlotIndex;
|
adr.SlotIndex := FLambdaNode.Parameters[i].Address.SlotIndex;
|
||||||
// Evaluate in CALLER'S scope (AVisitor), place in CALLEE'S scope (callScope)
|
|
||||||
callScope[adr].Value := AArgNodes[i].Accept(AVisitor);
|
callScope[adr].Value := AArgNodes[i].Accept(AVisitor);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Execute the body with a new visitor for the new scope
|
|
||||||
Result := FLambdaNode.Body.Accept((AVisitor as TEvaluatorVisitor).CreateVisitorForScope(callScope));
|
Result := FLambdaNode.Body.Accept((AVisitor as TEvaluatorVisitor).CreateVisitorForScope(callScope));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -252,14 +214,20 @@ begin
|
|||||||
Result := FArity;
|
Result := FArity;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TNativeClosure.Invoke(const AVisitor: IInterface; const ASelf: TDataValue; const AArgs: TArray<TDataValue>): TDataValue;
|
function TNativeClosure.Invoke(const AVisitor: IAstVisitor; const ASelf: TDataValue; const AArgNodes: TList<IAstNode>): TDataValue;
|
||||||
|
var
|
||||||
|
argValues: TArray<TDataValue>;
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
// Arity check
|
if (FArity <> -1) and (AArgNodes.Count <> FArity) then
|
||||||
if (FArity <> -1) and (Length(AArgs) <> FArity) then
|
raise EArgumentException.CreateFmt('Argument count mismatch: expected %d, got %d', [FArity, AArgNodes.Count]);
|
||||||
raise EArgumentException.CreateFmt('Argument count mismatch: expected %d, got %d', [FArity, Length(AArgs)]);
|
|
||||||
|
|
||||||
// AVisitor and ASelf are ignored for native calls.
|
// Evaluate argument nodes to get values for the native function
|
||||||
Result := FMethod(AArgs);
|
SetLength(argValues, AArgNodes.Count);
|
||||||
|
for i := 0 to AArgNodes.Count - 1 do
|
||||||
|
argValues[i] := AArgNodes[i].Accept(AVisitor);
|
||||||
|
|
||||||
|
Result := FMethod(argValues);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TEvaluatorVisitor }
|
{ TEvaluatorVisitor }
|
||||||
@@ -296,36 +264,16 @@ end;
|
|||||||
function TEvaluatorVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
function TEvaluatorVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
||||||
var
|
var
|
||||||
calleeValue: TDataValue;
|
calleeValue: TDataValue;
|
||||||
callable: TDataValue.ICallable;
|
|
||||||
i: Integer;
|
|
||||||
begin
|
begin
|
||||||
calleeValue := Node.Callee.Accept(Self);
|
calleeValue := Node.Callee.Accept(Self);
|
||||||
|
|
||||||
if calleeValue.Kind <> vkCallable then
|
// Check if the value holds an interface and if that interface supports our invocation contract.
|
||||||
raise EArgumentException.Create('Expression is not a callable value.');
|
if (calleeValue.Kind <> vkInterface) or not (calleeValue.AsInterface is TClosure) then
|
||||||
|
raise EArgumentException.Create('Expression is not invokable in this context.');
|
||||||
|
|
||||||
callable := calleeValue.AsCallable;
|
// "Tell, Don't Ask": Simply tell the object to invoke itself.
|
||||||
|
Result := (calleeValue.AsInterface as TClosure).Invoke(Self, calleeValue, Node.Arguments);
|
||||||
if callable is TClosureValue then
|
|
||||||
begin
|
|
||||||
// "Fast Path": Call the optimized method directly.
|
|
||||||
Result := (callable as TClosureValue).InvokeFast(Self, calleeValue, Node.Arguments);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
// "Generic Path": For other ICallable types (e.g., TNativeClosure).
|
|
||||||
// Evaluate arguments into a temporary array first.
|
|
||||||
var argValues: TArray<TDataValue>;
|
|
||||||
SetLength(argValues, Node.Arguments.Count);
|
|
||||||
for i := 0 to Node.Arguments.Count - 1 do
|
|
||||||
argValues[i] := Node.Arguments[i].Accept(Self);
|
|
||||||
|
|
||||||
// Call the generic Invoke method.
|
|
||||||
Result := callable.Invoke(Self, calleeValue, argValues);
|
|
||||||
end;
|
end;
|
||||||
end;
|
|
||||||
|
|
||||||
{ TEvaluatorVisitor }
|
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
|
function TEvaluatorVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
|
||||||
var
|
var
|
||||||
@@ -531,7 +479,7 @@ begin
|
|||||||
for i := 0 to High(sourceAddresses) do
|
for i := 0 to High(sourceAddresses) do
|
||||||
capturedCells[i] := FScope.GetCell(sourceAddresses[i]);
|
capturedCells[i] := FScope.GetCell(sourceAddresses[i]);
|
||||||
|
|
||||||
Result := TClosureValue.Create(Node, FScope, capturedCells);
|
Result := TClosureValue.Create(Node, FScope, capturedCells) as IInterface;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
|
function TEvaluatorVisitor.VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
unit Myc.Data.Types;
|
unit Myc.Data.Types deprecated;
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
|
|||||||
+40
-20
@@ -9,22 +9,15 @@ uses
|
|||||||
Myc.Data.Decimal;
|
Myc.Data.Decimal;
|
||||||
|
|
||||||
type
|
type
|
||||||
TDataValueKind = (vkVoid, vkScalar, vkCallable, vkText, vkSeries, vkRecordSeries, vkRecord, vkMemberSeries);
|
TDataValueKind = (vkVoid, vkScalar, vkInterface, vkText, vkSeries, vkRecordSeries, vkRecord, vkMemberSeries, vkGeneric);
|
||||||
|
|
||||||
TDataValue = record
|
TDataValue = record
|
||||||
public
|
public
|
||||||
type
|
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)
|
TVal<T> = class(TInterfacedObject)
|
||||||
Value: T;
|
Value: T;
|
||||||
constructor Create(const AValue: T);
|
constructor Create(const AValue: T);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
private
|
private
|
||||||
var
|
var
|
||||||
FKind: TDataValueKind;
|
FKind: TDataValueKind;
|
||||||
@@ -37,8 +30,11 @@ type
|
|||||||
class function Void: TDataValue; inline; static;
|
class function Void: TDataValue; inline; static;
|
||||||
|
|
||||||
class operator Implicit(const AValue: TScalar): TDataValue; overload; inline;
|
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: 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 FromSeries(const [ref] AValue: TScalarSeries): TDataValue; static; inline;
|
||||||
class function FromRecordSeries(const [ref] AValue: TScalarRecordSeries): 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;
|
class function FromMemberSeries(const [ref] AValue: TScalarMemberSeries): TDataValue; static; inline;
|
||||||
|
|
||||||
function AsScalar: TScalar; inline;
|
function AsScalar: TScalar; inline;
|
||||||
function AsCallable: ICallable; inline;
|
function AsInterface: IInterface; inline;
|
||||||
function AsText: String; inline;
|
function AsText: String; inline;
|
||||||
function AsRecordSeries: TVal<TScalarRecordSeries>; inline;
|
function AsRecordSeries: TVal<TScalarRecordSeries>; inline;
|
||||||
function AsRecord: TVal<TScalarRecord>; inline;
|
function AsRecord: TVal<TScalarRecord>; inline;
|
||||||
function AsMemberSeries: TVal<TScalarMemberSeries>; inline;
|
function AsMemberSeries: TVal<TScalarMemberSeries>; inline;
|
||||||
function AsSeries: TVal<TScalarSeries>; inline;
|
function AsSeries: TVal<TScalarSeries>; inline;
|
||||||
|
|
||||||
|
procedure SetVoid;
|
||||||
|
|
||||||
function ToString: String;
|
function ToString: String;
|
||||||
property IsVoid: Boolean read GetIsVoid;
|
property IsVoid: Boolean read GetIsVoid;
|
||||||
property Kind: TDataValueKind read GetKind;
|
property Kind: TDataValueKind read GetKind;
|
||||||
@@ -60,6 +58,9 @@ type
|
|||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
TypInfo;
|
||||||
|
|
||||||
{ TDataValue.TVal<T> }
|
{ TDataValue.TVal<T> }
|
||||||
|
|
||||||
constructor TDataValue.TVal<T>.Create(const AValue: T);
|
constructor TDataValue.TVal<T>.Create(const AValue: T);
|
||||||
@@ -72,15 +73,15 @@ end;
|
|||||||
|
|
||||||
class operator TDataValue.Initialize(out Dest: TDataValue);
|
class operator TDataValue.Initialize(out Dest: TDataValue);
|
||||||
begin
|
begin
|
||||||
Dest.FKind := vkVoid; // Geändert
|
Dest.FKind := vkVoid;
|
||||||
Dest.FInterface := nil;
|
Dest.FInterface := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDataValue.AsCallable: ICallable;
|
function TDataValue.AsInterface: IInterface;
|
||||||
begin
|
begin
|
||||||
if (FKind <> vkCallable) then
|
if (FKind <> vkInterface) then
|
||||||
raise EInvalidCast.Create('Cannot read value as a Callable.');
|
raise EInvalidCast.Create('Cannot read value as an Interface.');
|
||||||
Result := ICallable(FInterface);
|
Result := FInterface;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDataValue.AsMemberSeries: TVal<TScalarMemberSeries>;
|
function TDataValue.AsMemberSeries: TVal<TScalarMemberSeries>;
|
||||||
@@ -90,6 +91,13 @@ begin
|
|||||||
Result := TVal<TScalarMemberSeries>(FInterface);
|
Result := TVal<TScalarMemberSeries>(FInterface);
|
||||||
end;
|
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>;
|
function TDataValue.AsRecord: TVal<TScalarRecord>;
|
||||||
begin
|
begin
|
||||||
if (FKind <> vkRecord) then
|
if (FKind <> vkRecord) then
|
||||||
@@ -125,6 +133,12 @@ begin
|
|||||||
Result := (FInterface as TVal<String>).Value;
|
Result := (FInterface as TVal<String>).Value;
|
||||||
end;
|
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;
|
class function TDataValue.FromMemberSeries(const [ref] AValue: TScalarMemberSeries): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result.FKind := vkMemberSeries;
|
Result.FKind := vkMemberSeries;
|
||||||
@@ -153,9 +167,9 @@ begin
|
|||||||
Result.FScalar := Default(TScalar);
|
Result.FScalar := Default(TScalar);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class operator TDataValue.Implicit(const AValue: ICallable): TDataValue;
|
class operator TDataValue.Implicit(const AValue: IInterface): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result.FKind := vkCallable;
|
Result.FKind := vkInterface;
|
||||||
Result.FInterface := AValue;
|
Result.FInterface := AValue;
|
||||||
Result.FScalar := Default(TScalar);
|
Result.FScalar := Default(TScalar);
|
||||||
end;
|
end;
|
||||||
@@ -176,7 +190,7 @@ end;
|
|||||||
|
|
||||||
function TDataValue.GetIsVoid: Boolean;
|
function TDataValue.GetIsVoid: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := FKind = vkVoid; // Geändert
|
Result := FKind = vkVoid;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDataValue.GetKind: TDataValueKind;
|
function TDataValue.GetKind: TDataValueKind;
|
||||||
@@ -184,17 +198,23 @@ begin
|
|||||||
Result := FKind;
|
Result := FKind;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TDataValue.SetVoid;
|
||||||
|
begin
|
||||||
|
FKind := vkVoid;
|
||||||
|
FInterface := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
function TDataValue.ToString: String;
|
function TDataValue.ToString: String;
|
||||||
begin
|
begin
|
||||||
case FKind of
|
case FKind of
|
||||||
vkScalar: Result := FScalar.ToString;
|
vkScalar: Result := FScalar.ToString;
|
||||||
vkCallable: Result := '<callable>';
|
vkInterface: Result := '<interface>';
|
||||||
vkText: Result := AsText;
|
vkText: Result := AsText;
|
||||||
vkSeries: Result := '<series>';
|
vkSeries: Result := '<series>';
|
||||||
vkRecordSeries: Result := '<record_series>';
|
vkRecordSeries: Result := '<record_series>';
|
||||||
vkRecord: Result := '<record>';
|
vkRecord: Result := '<record>';
|
||||||
vkMemberSeries: Result := '<member_series>';
|
vkMemberSeries: Result := '<member_series>';
|
||||||
vkVoid: Result := '<void>'; // Geändert
|
vkVoid: Result := '<void>';
|
||||||
else
|
else
|
||||||
Result := '[Unknown DataValue]';
|
Result := '[Unknown DataValue]';
|
||||||
end;
|
end;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ uses
|
|||||||
Myc.Data.Pipeline,
|
Myc.Data.Pipeline,
|
||||||
Myc.Data.Series,
|
Myc.Data.Series,
|
||||||
Myc.Data.Types,
|
Myc.Data.Types,
|
||||||
|
Myc.Data.Value,
|
||||||
Myc.Trade.Types,
|
Myc.Trade.Types,
|
||||||
Myc.Trade.Indicators;
|
Myc.Trade.Indicators;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user