TDataValue as new global variant type
This commit is contained in:
+24
-230
@@ -5,7 +5,8 @@ interface
|
||||
uses
|
||||
System.SysUtils,
|
||||
System.Generics.Collections,
|
||||
Myc.Data.Scalar;
|
||||
Myc.Data.Scalar,
|
||||
Myc.Data.Value;
|
||||
|
||||
type
|
||||
// Operators and helpers
|
||||
@@ -20,10 +21,6 @@ type
|
||||
function ToString: string;
|
||||
end;
|
||||
|
||||
// Added avkMemberSeries to represent a TScalarMemberSeries value.
|
||||
// Added avkSeries to represent a TScalarSeries value.
|
||||
TAstValueKind = (avkUndefined, avkScalar, avkClosure, avkText, avkSeries, avkRecordSeries, avkRecord, avkMemberSeries);
|
||||
|
||||
// --- Forward Declarations to break cycles ---
|
||||
IAstVisitor = interface;
|
||||
IAstNode = interface;
|
||||
@@ -49,63 +46,14 @@ type
|
||||
|
||||
// --- Concrete Type Definitions ---
|
||||
|
||||
TAstValue = record
|
||||
type
|
||||
IClosure = interface
|
||||
{$region 'private'}
|
||||
function GetBody: IAstNode;
|
||||
function GetClosureScope: IExecutionScope;
|
||||
function GetParameters: TArray<IIdentifierNode>;
|
||||
function GetUpvalues: TArray<IValueCell>;
|
||||
{$endregion}
|
||||
property Body: IAstNode read GetBody;
|
||||
property ClosureScope: IExecutionScope read GetClosureScope;
|
||||
property Parameters: TArray<IIdentifierNode> read GetParameters;
|
||||
property Upvalues: TArray<IValueCell> read GetUpvalues;
|
||||
end;
|
||||
|
||||
TVal<T> = class(TInterfacedObject)
|
||||
Value: T;
|
||||
constructor Create(const AValue: T);
|
||||
end;
|
||||
|
||||
private
|
||||
var
|
||||
FKind: TAstValueKind;
|
||||
FScalar: TScalar;
|
||||
FInterface: IInterface;
|
||||
function GetKind: TAstValueKind; inline;
|
||||
function GetIsVoid: Boolean; inline;
|
||||
public
|
||||
class operator Initialize(out Dest: TAstValue);
|
||||
class function Void: TAstValue; inline; static;
|
||||
class operator Implicit(const AValue: TScalar): TAstValue; overload; inline;
|
||||
class operator Implicit(const AValue: TAstValue.IClosure): TAstValue; overload; inline;
|
||||
class operator Implicit(const AValue: String): TAstValue; overload; inline;
|
||||
class function FromSeries(const [ref] AValue: TScalarSeries): TAstValue; static; inline;
|
||||
class function FromRecordSeries(const [ref] AValue: TScalarRecordSeries): TAstValue; static; inline;
|
||||
class function FromRecord(const [ref] AValue: TScalarRecord): TAstValue; static; inline;
|
||||
class function FromMemberSeries(const [ref] AValue: TScalarMemberSeries): TAstValue; static; inline;
|
||||
function AsScalar: TScalar; inline;
|
||||
function AsClosure: TAstValue.IClosure; 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;
|
||||
function ToString: String;
|
||||
property IsVoid: Boolean read GetIsVoid;
|
||||
property Kind: TAstValueKind read GetKind;
|
||||
end;
|
||||
|
||||
// A managed, reference-counted cell that holds a TAstValue,
|
||||
// A managed, reference-counted cell that holds a TDataValue,
|
||||
// allowing it to be shared by reference between scopes (for closures).
|
||||
IValueCell = interface
|
||||
{$region 'private'}
|
||||
function GetValue: TAstValue;
|
||||
procedure SetValue(const AValue: TAstValue);
|
||||
function GetValue: TDataValue;
|
||||
procedure SetValue(const AValue: TDataValue);
|
||||
{$endregion}
|
||||
property Value: TAstValue read GetValue write SetValue;
|
||||
property Value: TDataValue read GetValue write SetValue;
|
||||
end;
|
||||
|
||||
// Defines how an identifier's address was resolved.
|
||||
@@ -125,12 +73,11 @@ type
|
||||
function GetCell(const Address: TResolvedAddress): IValueCell;
|
||||
{$endregion}
|
||||
|
||||
procedure Define(const Name: string; const Value: TAstValue);
|
||||
procedure Define(const Name: string; const Value: TDataValue);
|
||||
function Dump: string;
|
||||
procedure Clear;
|
||||
|
||||
property Cell[const Address: TResolvedAddress]: IValueCell read GetCell; default;
|
||||
|
||||
property Parent: IExecutionScope read GetParent;
|
||||
end;
|
||||
|
||||
@@ -147,26 +94,26 @@ type
|
||||
end;
|
||||
|
||||
IAstVisitor = interface
|
||||
function VisitConstant(const Node: IConstantNode): TAstValue;
|
||||
function VisitIdentifier(const Node: IIdentifierNode): TAstValue;
|
||||
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TAstValue;
|
||||
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TAstValue;
|
||||
function VisitIfExpression(const Node: IIfExpressionNode): TAstValue;
|
||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstValue;
|
||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstValue;
|
||||
function VisitFunctionCall(const Node: IFunctionCallNode): TAstValue;
|
||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TAstValue;
|
||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TAstValue;
|
||||
function VisitAssignment(const Node: IAssignmentNode): TAstValue;
|
||||
function VisitIndexer(const Node: IIndexerNode): TAstValue;
|
||||
function VisitMemberAccess(const Node: IMemberAccessNode): TAstValue;
|
||||
function VisitCreateSeries(const Node: ICreateSeriesNode): TAstValue;
|
||||
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAstValue;
|
||||
function VisitSeriesLength(const Node: ISeriesLengthNode): TAstValue;
|
||||
function VisitConstant(const Node: IConstantNode): TDataValue;
|
||||
function VisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
||||
function VisitBinaryExpression(const Node: IBinaryExpressionNode): TDataValue;
|
||||
function VisitUnaryExpression(const Node: IUnaryExpressionNode): TDataValue;
|
||||
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
||||
function VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
||||
function VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
||||
function VisitAssignment(const Node: IAssignmentNode): TDataValue;
|
||||
function VisitIndexer(const Node: IIndexerNode): TDataValue;
|
||||
function VisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
|
||||
function VisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
|
||||
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
|
||||
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
||||
end;
|
||||
|
||||
IAstNode = interface(IInterface)
|
||||
function Accept(const Visitor: IAstVisitor): TAstValue;
|
||||
function Accept(const Visitor: IAstVisitor): TDataValue;
|
||||
end;
|
||||
|
||||
IConstantNode = interface(IAstNode)
|
||||
@@ -207,7 +154,6 @@ type
|
||||
property Right: IAstNode read GetRight;
|
||||
end;
|
||||
|
||||
// Represents an if-statement for control flow.
|
||||
IIfExpressionNode = interface(IAstNode)
|
||||
{$region 'private'}
|
||||
function GetCondition: IAstNode;
|
||||
@@ -219,7 +165,6 @@ type
|
||||
property ElseBranch: IAstNode read GetElseBranch;
|
||||
end;
|
||||
|
||||
// Represents a ternary expression (e.g., condition ? true_expr : false_expr) for value selection.
|
||||
ITernaryExpressionNode = interface(IAstNode)
|
||||
{$region 'private'}
|
||||
function GetCondition: IAstNode;
|
||||
@@ -278,7 +223,6 @@ type
|
||||
property Value: IAstNode read GetValue;
|
||||
end;
|
||||
|
||||
// Represents an index access expression (e.g., series[index]).
|
||||
IIndexerNode = interface(IAstNode)
|
||||
{$region 'private'}
|
||||
function GetBase: IAstNode;
|
||||
@@ -288,7 +232,6 @@ type
|
||||
property Index: IAstNode read GetIndex;
|
||||
end;
|
||||
|
||||
// Represents a member access expression (e.g., series.field or record.field).
|
||||
IMemberAccessNode = interface(IAstNode)
|
||||
{$region 'private'}
|
||||
function GetBase: IAstNode;
|
||||
@@ -298,7 +241,6 @@ type
|
||||
property Member: IIdentifierNode read GetMember;
|
||||
end;
|
||||
|
||||
// Represents creating a new, empty series (e.g., new series(int)).
|
||||
ICreateSeriesNode = interface(IAstNode)
|
||||
{$region 'private'}
|
||||
function GetDefinition: String;
|
||||
@@ -306,7 +248,6 @@ type
|
||||
property Definition: String read GetDefinition;
|
||||
end;
|
||||
|
||||
// Represents adding a value to a series (e.g., my_series.add(value, 100)).
|
||||
IAddSeriesItemNode = interface(IAstNode)
|
||||
{$region 'private'}
|
||||
function GetSeries: IIdentifierNode;
|
||||
@@ -330,153 +271,6 @@ implementation
|
||||
uses
|
||||
System.Classes;
|
||||
|
||||
{ TAstValue }
|
||||
|
||||
constructor TAstValue.TVal<T>.Create(const AValue: T);
|
||||
begin
|
||||
inherited Create;
|
||||
Value := AValue;
|
||||
end;
|
||||
|
||||
{ TAstValue }
|
||||
|
||||
class operator TAstValue.Initialize(out Dest: TAstValue);
|
||||
begin
|
||||
Dest.FKind := avkUndefined;
|
||||
Dest.FInterface := nil;
|
||||
end;
|
||||
|
||||
function TAstValue.AsClosure: TAstValue.IClosure;
|
||||
begin
|
||||
if (FKind <> avkClosure) then
|
||||
raise EInvalidCast.Create('Cannot read value as a Closure.');
|
||||
Result := TAstValue.IClosure(FInterface);
|
||||
end;
|
||||
|
||||
function TAstValue.AsMemberSeries: TVal<TScalarMemberSeries>;
|
||||
begin
|
||||
if (FKind <> avkMemberSeries) then
|
||||
raise EInvalidCast.Create('Cannot read value as MemberSeries.');
|
||||
Result := TVal<TScalarMemberSeries>(FInterface);
|
||||
end;
|
||||
|
||||
function TAstValue.AsRecord: TVal<TScalarRecord>;
|
||||
begin
|
||||
if (FKind <> avkRecord) then
|
||||
raise EInvalidCast.Create('Cannot read value as Record.');
|
||||
Result := (FInterface as TVal<TScalarRecord>);
|
||||
end;
|
||||
|
||||
function TAstValue.AsRecordSeries: TVal<TScalarRecordSeries>;
|
||||
begin
|
||||
if (FKind <> avkRecordSeries) then
|
||||
raise EInvalidCast.Create('Cannot read value as RecordSeries.');
|
||||
Result := TVal<TScalarRecordSeries>(FInterface);
|
||||
end;
|
||||
|
||||
function TAstValue.AsScalar: TScalar;
|
||||
begin
|
||||
if (FKind <> avkScalar) then
|
||||
raise EInvalidCast.Create('Cannot read value as a Scalar.');
|
||||
Result := FScalar;
|
||||
end;
|
||||
|
||||
// Added support for TScalarSeries
|
||||
function TAstValue.AsSeries: TVal<TScalarSeries>;
|
||||
begin
|
||||
if (FKind <> avkSeries) then
|
||||
raise EInvalidCast.Create('Cannot read value as Series.');
|
||||
Result := TVal<TScalarSeries>(FInterface);
|
||||
end;
|
||||
|
||||
function TAstValue.AsText: String;
|
||||
begin
|
||||
if (FKind <> avkText) then
|
||||
raise EInvalidCast.Create('Cannot read value as Text.');
|
||||
|
||||
Result := (FInterface as TVal<String>).Value;
|
||||
end;
|
||||
|
||||
class operator TAstValue.Implicit(const AValue: TAstValue.IClosure): TAstValue;
|
||||
begin
|
||||
Result.FKind := avkClosure;
|
||||
Result.FInterface := AValue;
|
||||
Result.FScalar := Default(TScalar);
|
||||
end;
|
||||
|
||||
class function TAstValue.FromMemberSeries(const [ref] AValue: TScalarMemberSeries): TAstValue;
|
||||
begin
|
||||
Result.FKind := avkMemberSeries;
|
||||
Result.FInterface := TVal<TScalarMemberSeries>.Create(AValue);
|
||||
Result.FScalar := Default(TScalar);
|
||||
end;
|
||||
|
||||
class function TAstValue.FromRecord(const [ref] AValue: TScalarRecord): TAstValue;
|
||||
begin
|
||||
Result.FKind := avkRecord;
|
||||
Result.FInterface := TVal<TScalarRecord>.Create(AValue);
|
||||
Result.FScalar := Default(TScalar);
|
||||
end;
|
||||
|
||||
class function TAstValue.FromRecordSeries(const [ref] AValue: TScalarRecordSeries): TAstValue;
|
||||
begin
|
||||
Result.FKind := avkRecordSeries;
|
||||
Result.FInterface := TVal<TScalarRecordSeries>.Create(AValue);
|
||||
Result.FScalar := Default(TScalar);
|
||||
end;
|
||||
|
||||
class operator TAstValue.Implicit(const AValue: TScalar): TAstValue;
|
||||
begin
|
||||
Result.FKind := avkScalar;
|
||||
Result.FScalar := AValue;
|
||||
Result.FInterface := nil;
|
||||
end;
|
||||
|
||||
class function TAstValue.FromSeries(const [ref] AValue: TScalarSeries): TAstValue;
|
||||
begin
|
||||
Result.FKind := avkSeries;
|
||||
Result.FInterface := TVal<TScalarSeries>.Create(AValue);
|
||||
Result.FScalar := Default(TScalar);
|
||||
end;
|
||||
|
||||
class operator TAstValue.Implicit(const AValue: String): TAstValue;
|
||||
begin
|
||||
Result.FKind := avkText;
|
||||
Result.FInterface := TVal<String>.Create(AValue);
|
||||
Result.FScalar := Default(TScalar);
|
||||
end;
|
||||
|
||||
function TAstValue.GetIsVoid: Boolean;
|
||||
begin
|
||||
Result := FKind = avkUndefined;
|
||||
end;
|
||||
|
||||
function TAstValue.GetKind: TAstValueKind;
|
||||
begin
|
||||
Result := FKind;
|
||||
end;
|
||||
|
||||
function TAstValue.ToString: String;
|
||||
begin
|
||||
case FKind of
|
||||
avkScalar: Result := FScalar.ToString;
|
||||
avkClosure: Result := '<closure>';
|
||||
avkText: Result := AsText;
|
||||
avkSeries: Result := '<series>';
|
||||
avkRecordSeries: Result := '<record_series>';
|
||||
avkRecord: Result := '<record>';
|
||||
avkMemberSeries: Result := '<member_series>';
|
||||
avkUndefined: Result := '<void>';
|
||||
else
|
||||
Result := '[Unknown AstValue]';
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TAstValue.Void: TAstValue;
|
||||
begin
|
||||
Result := Default(TAstValue);
|
||||
end;
|
||||
|
||||
{ TResolvedAddress }
|
||||
|
||||
constructor TResolvedAddress.Create(AKind: TAddressKind; AScopeDepth, ASlotIndex: Integer);
|
||||
|
||||
Reference in New Issue
Block a user