new-Series with tuple record def
This commit is contained in:
File diff suppressed because one or more lines are too long
+462
-1044
File diff suppressed because it is too large
Load Diff
@@ -816,17 +816,88 @@ end;
|
|||||||
function TTypeChecker.VisitCreateSeries(const Node: IAstNode): IAstNode;
|
function TTypeChecker.VisitCreateSeries(const Node: IAstNode): IAstNode;
|
||||||
var
|
var
|
||||||
C: ICreateSeriesNode;
|
C: ICreateSeriesNode;
|
||||||
elemType: IStaticType;
|
defNode: IAstNode;
|
||||||
def: string;
|
recDef: IScalarRecordDefinition;
|
||||||
|
resType: IStaticType;
|
||||||
|
elemKind: TScalar.TKind;
|
||||||
|
fields: TArray<TPair<IKeyword, TScalar.TKind>>;
|
||||||
|
tuple: ITupleNode;
|
||||||
|
elements: TArray<IAstNode>;
|
||||||
|
fieldTuple: ITupleNode;
|
||||||
|
keyNode: IKeywordNode;
|
||||||
|
typeNode: IKeywordNode;
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
C := Node.AsCreateSeries;
|
C := Node.AsCreateSeries;
|
||||||
def := C.Definition;
|
// The definition node comes from the parser and is likely raw (untyped keywords/tuples).
|
||||||
if def.StartsWith('[') then
|
// We don't necessarily need to "Visit" it for type checking children,
|
||||||
elemType := TTypes.CreateRecord(nil)
|
// but we need to analyze its structure.
|
||||||
else
|
defNode := C.DefinitionNode;
|
||||||
elemType := TTypes.FromScalarKind(TScalar.StringToKind(def));
|
|
||||||
|
|
||||||
Result := TAst.CreateSeries(Node.Identity.AsDefinition, TTypes.CreateSeries(elemType));
|
recDef := nil;
|
||||||
|
resType := TTypes.Unknown;
|
||||||
|
|
||||||
|
case defNode.Kind of
|
||||||
|
akKeyword:
|
||||||
|
begin
|
||||||
|
// Case 1: Simple Series, e.g. (new-series :Float)
|
||||||
|
// DefinitionNode is a single Keyword
|
||||||
|
elemKind := TScalar.StringToKind(defNode.AsKeyword.Value.Name);
|
||||||
|
resType := TTypes.CreateSeries(TTypes.FromScalarKind(elemKind));
|
||||||
|
end;
|
||||||
|
akTuple:
|
||||||
|
begin
|
||||||
|
// Case 2: Record Series, e.g. (new-series [[:Price :Float] [:Vol :Ordinal]])
|
||||||
|
tuple := defNode.AsTuple;
|
||||||
|
elements := tuple.Elements;
|
||||||
|
SetLength(fields, Length(elements));
|
||||||
|
|
||||||
|
for i := 0 to High(elements) do
|
||||||
|
begin
|
||||||
|
if elements[i].Kind <> akTuple then
|
||||||
|
begin
|
||||||
|
if Assigned(FLog) then
|
||||||
|
FLog.AddError('Record definition elements must be vectors [Key Type]', elements[i]);
|
||||||
|
continue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
fieldTuple := elements[i].AsTuple;
|
||||||
|
if Length(fieldTuple.Elements) <> 2 then
|
||||||
|
begin
|
||||||
|
if Assigned(FLog) then
|
||||||
|
FLog.AddError('Record definition entry must have exactly 2 elements [Key Type]', fieldTuple);
|
||||||
|
continue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (fieldTuple.Elements[0].Kind <> akKeyword) or (fieldTuple.Elements[1].Kind <> akKeyword) then
|
||||||
|
begin
|
||||||
|
if Assigned(FLog) then
|
||||||
|
FLog.AddError('Record definition keys and types must be keywords', fieldTuple);
|
||||||
|
continue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
keyNode := fieldTuple.Elements[0].AsKeyword;
|
||||||
|
typeNode := fieldTuple.Elements[1].AsKeyword;
|
||||||
|
|
||||||
|
elemKind := TScalar.StringToKind(typeNode.Value.Name);
|
||||||
|
fields[i] := TPair<IKeyword, TScalar.TKind>.Create(keyNode.Value, elemKind);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if Length(fields) > 0 then
|
||||||
|
begin
|
||||||
|
recDef := TKeywordMappingRegistry<TScalar.TKind>.Intern(fields);
|
||||||
|
resType := TTypes.CreateRecordSeries(recDef);
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if Assigned(FLog) then
|
||||||
|
FLog.AddError('Invalid series definition format. Expected :Type or [[:Key :Type] ...]', defNode);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Return updated node with RecordDefinition (if any) and StaticType
|
||||||
|
Result := TAst.CreateSeries(Node.Identity, defNode, recDef, resType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TTypeChecker.VisitSeriesLength(const Node: IAstNode): IAstNode;
|
function TTypeChecker.VisitSeriesLength(const Node: IAstNode): IAstNode;
|
||||||
|
|||||||
@@ -490,7 +490,12 @@ end;
|
|||||||
|
|
||||||
function TAstDumper.VisitCreateSeries(const Node: IAstNode): TVoid;
|
function TAstDumper.VisitCreateSeries(const Node: IAstNode): TVoid;
|
||||||
begin
|
begin
|
||||||
LogFmt('CreateSeries: %s', [Node.AsCreateSeries.Definition], Node);
|
// REFACTORED: Log the structure of the definition
|
||||||
|
Log('CreateSeries', Node);
|
||||||
|
Indent;
|
||||||
|
Log('Definition:');
|
||||||
|
Visit(Node.AsCreateSeries.DefinitionNode);
|
||||||
|
Unindent;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstDumper.VisitAddSeriesItem(const Node: IAstNode): TVoid;
|
function TAstDumper.VisitAddSeriesItem(const Node: IAstNode): TVoid;
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ uses
|
|||||||
Myc.Data.Series,
|
Myc.Data.Series,
|
||||||
Myc.Data.Stream,
|
Myc.Data.Stream,
|
||||||
Myc.Data.Stream.Pipes,
|
Myc.Data.Stream.Pipes,
|
||||||
Myc.Data.Scalar.JSON,
|
|
||||||
Myc.Ast.Types;
|
Myc.Ast.Types;
|
||||||
|
|
||||||
type
|
type
|
||||||
@@ -359,7 +358,7 @@ begin
|
|||||||
vkSeries:
|
vkSeries:
|
||||||
begin
|
begin
|
||||||
var i: Integer := idx.AsScalar.Value.AsInt64;
|
var i: Integer := idx.AsScalar.Value.AsInt64;
|
||||||
Result := base.AsSeries.Items[i];
|
Result := base.AsSeries[i];
|
||||||
end;
|
end;
|
||||||
vkRecordSeries:
|
vkRecordSeries:
|
||||||
begin
|
begin
|
||||||
@@ -432,11 +431,59 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitCreateSeries(const N: ICreateSeriesNode): TDataValue;
|
function TEvaluatorVisitor.VisitCreateSeries(const N: ICreateSeriesNode): TDataValue;
|
||||||
|
var
|
||||||
|
defNode: IAstNode;
|
||||||
|
kind: TScalar.TKind;
|
||||||
|
fields: TArray<TPair<IKeyword, TScalar.TKind>>;
|
||||||
|
i: Integer;
|
||||||
|
tupleElements: TArray<IAstNode>;
|
||||||
|
entry: TArray<IAstNode>;
|
||||||
|
k: IKeyword;
|
||||||
|
t: TScalar.TKind;
|
||||||
begin
|
begin
|
||||||
if N.Definition.Trim.StartsWith('[') then
|
// 1. If TypeChecker ran, we have the Definition ready (Fast Path)
|
||||||
Result := TScalarRecordSeries.Create(TRttiAstHelper.JsonToRecordDefinition(N.Definition))
|
if Assigned(N.RecordDefinition) then
|
||||||
else
|
Exit(TScalarRecordSeries.Create(N.RecordDefinition));
|
||||||
Result := TScalarSeries.Create(TScalar.StringToKind(N.Definition));
|
|
||||||
|
defNode := N.DefinitionNode;
|
||||||
|
|
||||||
|
// 2. Simple Series (Keyword) e.g. (new-series :Float)
|
||||||
|
if defNode.Kind = akKeyword then
|
||||||
|
begin
|
||||||
|
kind := TScalar.StringToKind(defNode.AsKeyword.Value.Name);
|
||||||
|
Exit(TScalarSeries.Create(kind));
|
||||||
|
end;
|
||||||
|
|
||||||
|
// 3. Record Series (Tuple of [Key Type]) - Dynamic Parsing Fallback
|
||||||
|
// e.g. (new-series [[:Price :Float] [:Vol :Ordinal]])
|
||||||
|
if defNode.Kind = akTuple then
|
||||||
|
begin
|
||||||
|
tupleElements := defNode.AsTuple.Elements;
|
||||||
|
SetLength(fields, Length(tupleElements));
|
||||||
|
|
||||||
|
for i := 0 to High(tupleElements) do
|
||||||
|
begin
|
||||||
|
// Each element MUST be a tuple of 2 elements [Key, Type]
|
||||||
|
if tupleElements[i].Kind <> akTuple then
|
||||||
|
raise EEvaluatorException.Create('Invalid record definition: Expected vector [Key Type].');
|
||||||
|
|
||||||
|
entry := tupleElements[i].AsTuple.Elements;
|
||||||
|
if Length(entry) <> 2 then
|
||||||
|
raise EEvaluatorException.Create('Invalid record definition entry: Expected 2 elements.');
|
||||||
|
|
||||||
|
if (entry[0].Kind <> akKeyword) or (entry[1].Kind <> akKeyword) then
|
||||||
|
raise EEvaluatorException.Create('Invalid record definition: Key and Type must be keywords.');
|
||||||
|
|
||||||
|
k := entry[0].AsKeyword.Value;
|
||||||
|
t := TScalar.StringToKind(entry[1].AsKeyword.Value.Name);
|
||||||
|
fields[i] := TPair<IKeyword, TScalar.TKind>.Create(k, t);
|
||||||
|
end;
|
||||||
|
|
||||||
|
var def := TKeywordMappingRegistry<TScalar.TKind>.Intern(fields);
|
||||||
|
Exit(TScalarRecordSeries.Create(def));
|
||||||
|
end;
|
||||||
|
|
||||||
|
raise EEvaluatorException.Create('Invalid CreateSeries definition node.');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitAddSeriesItem(const N: IAddSeriesItemNode): TDataValue;
|
function TEvaluatorVisitor.VisitAddSeriesItem(const N: IAddSeriesItemNode): TDataValue;
|
||||||
@@ -515,6 +562,12 @@ begin
|
|||||||
// Compile the transformation function
|
// Compile the transformation function
|
||||||
lambdaFunc := Visit(N.Transformation).AsMethod();
|
lambdaFunc := Visit(N.Transformation).AsMethod();
|
||||||
|
|
||||||
|
// WARNING: If this is executing dynamically (without TypeChecker), StaticType is Unknown.
|
||||||
|
// Pipe creation REQUIRES the output definition.
|
||||||
|
// Fixed: Allow both stRecord and stRecordSeries (as TypeChecker correctly assigns stRecordSeries for Pipe nodes)
|
||||||
|
if (N.StaticType.Kind <> stRecordSeries) and (N.StaticType.Kind <> stRecord) then
|
||||||
|
raise EEvaluatorException.Create('Pipe requires Type Checking to determine output structure (RecordDefinition).');
|
||||||
|
|
||||||
var outputDef := N.StaticType.AsRecord.Definition;
|
var outputDef := N.StaticType.AsRecord.Definition;
|
||||||
|
|
||||||
var pipeAdapter: TPipeStream.TPipeLambda :=
|
var pipeAdapter: TPipeStream.TPipeLambda :=
|
||||||
|
|||||||
@@ -209,7 +209,6 @@ begin
|
|||||||
Result.AddPair('NodeType', TJSONString.Create('Tuple'));
|
Result.AddPair('NodeType', TJSONString.Create('Tuple'));
|
||||||
elemsArray := TJSONArray.Create;
|
elemsArray := TJSONArray.Create;
|
||||||
|
|
||||||
// Updated: Use Elements array directly
|
|
||||||
elements := T.Elements;
|
elements := T.Elements;
|
||||||
for i := 0 to High(elements) do
|
for i := 0 to High(elements) do
|
||||||
elemsArray.Add(Visit(elements[i]));
|
elemsArray.Add(Visit(elements[i]));
|
||||||
@@ -412,7 +411,8 @@ function TJsonAstConverter.VisitCreateSeries(const Node: IAstNode): TJSONObject;
|
|||||||
begin
|
begin
|
||||||
Result := TJSONObject.Create;
|
Result := TJSONObject.Create;
|
||||||
Result.AddPair('NodeType', TJSONString.Create('CreateSeries'));
|
Result.AddPair('NodeType', TJSONString.Create('CreateSeries'));
|
||||||
Result.AddPair('Definition', TJSONString.Create(Node.AsCreateSeries.Definition));
|
// REFACTORED: Now serialize the DefinitionNode structure instead of a raw string
|
||||||
|
Result.AddPair('DefinitionNode', Visit(Node.AsCreateSeries.DefinitionNode));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TJsonAstConverter.VisitAddSeriesItem(const Node: IAstNode): TJSONObject;
|
function TJsonAstConverter.VisitAddSeriesItem(const Node: IAstNode): TJSONObject;
|
||||||
@@ -616,7 +616,6 @@ var
|
|||||||
begin
|
begin
|
||||||
identNodes := TList<IIdentifierNode>.Create;
|
identNodes := TList<IIdentifierNode>.Create;
|
||||||
try
|
try
|
||||||
// Updated: Use Elements instead of ToArray (or iterate if ToArray is missing)
|
|
||||||
for node in JsonToNode(AObj.GetValue('Parameters')).AsTuple.Elements do
|
for node in JsonToNode(AObj.GetValue('Parameters')).AsTuple.Elements do
|
||||||
identNodes.Add(node.AsIdentifier);
|
identNodes.Add(node.AsIdentifier);
|
||||||
Result := TAst.LambdaExpr(identNodes.ToArray, JsonToNode(AObj.GetValue('Body')));
|
Result := TAst.LambdaExpr(identNodes.ToArray, JsonToNode(AObj.GetValue('Body')));
|
||||||
@@ -632,7 +631,6 @@ var
|
|||||||
begin
|
begin
|
||||||
identNodes := TList<IIdentifierNode>.Create;
|
identNodes := TList<IIdentifierNode>.Create;
|
||||||
try
|
try
|
||||||
// Updated: Use Elements
|
|
||||||
for node in JsonToNode(AObj.GetValue('Parameters')).AsTuple.Elements do
|
for node in JsonToNode(AObj.GetValue('Parameters')).AsTuple.Elements do
|
||||||
identNodes.Add(node.AsIdentifier);
|
identNodes.Add(node.AsIdentifier);
|
||||||
Result :=
|
Result :=
|
||||||
@@ -663,7 +661,6 @@ end;
|
|||||||
|
|
||||||
function TJsonAstConverter.JsonToFunctionCallNode(const AObj: TJSONObject): IFunctionCallNode;
|
function TJsonAstConverter.JsonToFunctionCallNode(const AObj: TJSONObject): IFunctionCallNode;
|
||||||
begin
|
begin
|
||||||
// Updated: Use Elements
|
|
||||||
Result := TAst.FunctionCall(JsonToNode(AObj.GetValue('Callee')), JsonToNode(AObj.GetValue('Arguments')).AsTuple.Elements);
|
Result := TAst.FunctionCall(JsonToNode(AObj.GetValue('Callee')), JsonToNode(AObj.GetValue('Arguments')).AsTuple.Elements);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -675,19 +672,16 @@ begin
|
|||||||
callee := JsonToNode(AObj.GetValue('Callee'));
|
callee := JsonToNode(AObj.GetValue('Callee'));
|
||||||
expandedBody := JsonToNode(AObj.GetValue('ExpandedBody'));
|
expandedBody := JsonToNode(AObj.GetValue('ExpandedBody'));
|
||||||
argsTuple := JsonToNode(AObj.GetValue('Arguments')).AsTuple;
|
argsTuple := JsonToNode(AObj.GetValue('Arguments')).AsTuple;
|
||||||
// Updated: Use Elements
|
|
||||||
Result := TAst.MacroExpansionNode(TAst.FunctionCall(callee, argsTuple.Elements), expandedBody);
|
Result := TAst.MacroExpansionNode(TAst.FunctionCall(callee, argsTuple.Elements), expandedBody);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TJsonAstConverter.JsonToRecurNode(const AObj: TJSONObject): IRecurNode;
|
function TJsonAstConverter.JsonToRecurNode(const AObj: TJSONObject): IRecurNode;
|
||||||
begin
|
begin
|
||||||
// Updated: Use Elements
|
|
||||||
Result := TAst.Recur(JsonToNode(AObj.GetValue('Arguments')).AsTuple.Elements);
|
Result := TAst.Recur(JsonToNode(AObj.GetValue('Arguments')).AsTuple.Elements);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TJsonAstConverter.JsonToBlockNode(const AObj: TJSONObject): IBlockExpressionNode;
|
function TJsonAstConverter.JsonToBlockNode(const AObj: TJSONObject): IBlockExpressionNode;
|
||||||
begin
|
begin
|
||||||
// Updated: Use Elements
|
|
||||||
Result := TAst.Block(JsonToNode(AObj.GetValue('Expressions')).AsTuple.Elements);
|
Result := TAst.Block(JsonToNode(AObj.GetValue('Expressions')).AsTuple.Elements);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -739,7 +733,8 @@ end;
|
|||||||
|
|
||||||
function TJsonAstConverter.JsonToCreateSeriesNode(const AObj: TJSONObject): ICreateSeriesNode;
|
function TJsonAstConverter.JsonToCreateSeriesNode(const AObj: TJSONObject): ICreateSeriesNode;
|
||||||
begin
|
begin
|
||||||
Result := TAst.CreateSeries(AObj.GetValue<string>('Definition'));
|
// REFACTORED: Use the definition node from JSON
|
||||||
|
Result := TAst.CreateSeries(JsonToNode(AObj.GetValue('DefinitionNode')));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TJsonAstConverter.JsonToAddSeriesItemNode(const AObj: TJSONObject): IAddSeriesItemNode;
|
function TJsonAstConverter.JsonToAddSeriesItemNode(const AObj: TJSONObject): IAddSeriesItemNode;
|
||||||
|
|||||||
@@ -422,9 +422,11 @@ type
|
|||||||
|
|
||||||
ICreateSeriesNode = interface(IAstTypedNode)
|
ICreateSeriesNode = interface(IAstTypedNode)
|
||||||
{$region 'private'}
|
{$region 'private'}
|
||||||
function GetDefinition: String;
|
function GetDefinitionNode: IAstNode;
|
||||||
|
function GetRecordDefinition: IScalarRecordDefinition;
|
||||||
{$endregion}
|
{$endregion}
|
||||||
property Definition: String read GetDefinition;
|
property DefinitionNode: IAstNode read GetDefinitionNode;
|
||||||
|
property RecordDefinition: IScalarRecordDefinition read GetRecordDefinition;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
IAddSeriesItemNode = interface(IAstTypedNode)
|
IAddSeriesItemNode = interface(IAstTypedNode)
|
||||||
@@ -589,12 +591,19 @@ type
|
|||||||
|
|
||||||
TCreateSeriesNode = class(TAstTypedNode, ICreateSeriesNode)
|
TCreateSeriesNode = class(TAstTypedNode, ICreateSeriesNode)
|
||||||
private
|
private
|
||||||
FDefIdentity: IDefinitionIdentity;
|
FDefinitionNode: IAstNode;
|
||||||
function GetDefinition: String;
|
FRecordDefinition: IScalarRecordDefinition;
|
||||||
|
function GetDefinitionNode: IAstNode;
|
||||||
|
function GetRecordDefinition: IScalarRecordDefinition;
|
||||||
protected
|
protected
|
||||||
function GetKind: TAstNodeKind; override;
|
function GetKind: TAstNodeKind; override;
|
||||||
public
|
public
|
||||||
constructor Create(const AIdentity: IDefinitionIdentity; const AStaticType: IStaticType);
|
constructor Create(
|
||||||
|
const ADefinitionNode: IAstNode;
|
||||||
|
const ARecordDefinition: IScalarRecordDefinition;
|
||||||
|
const AStaticType: IStaticType;
|
||||||
|
const AIdentity: IAstIdentity
|
||||||
|
);
|
||||||
function AsCreateSeries: ICreateSeriesNode; override;
|
function AsCreateSeries: ICreateSeriesNode; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -1379,10 +1388,16 @@ end;
|
|||||||
|
|
||||||
{ TCreateSeriesNode }
|
{ TCreateSeriesNode }
|
||||||
|
|
||||||
constructor TCreateSeriesNode.Create(const AIdentity: IDefinitionIdentity; const AStaticType: IStaticType);
|
constructor TCreateSeriesNode.Create(
|
||||||
|
const ADefinitionNode: IAstNode;
|
||||||
|
const ARecordDefinition: IScalarRecordDefinition;
|
||||||
|
const AStaticType: IStaticType;
|
||||||
|
const AIdentity: IAstIdentity
|
||||||
|
);
|
||||||
begin
|
begin
|
||||||
inherited Create(AStaticType, AIdentity);
|
inherited Create(AStaticType, AIdentity);
|
||||||
FDefIdentity := AIdentity;
|
FDefinitionNode := ADefinitionNode;
|
||||||
|
FRecordDefinition := ARecordDefinition;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCreateSeriesNode.AsCreateSeries: ICreateSeriesNode;
|
function TCreateSeriesNode.AsCreateSeries: ICreateSeriesNode;
|
||||||
@@ -1390,9 +1405,14 @@ begin
|
|||||||
Result := Self;
|
Result := Self;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCreateSeriesNode.GetDefinition: String;
|
function TCreateSeriesNode.GetDefinitionNode: IAstNode;
|
||||||
begin
|
begin
|
||||||
Result := FDefIdentity.Definition;
|
Result := FDefinitionNode;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TCreateSeriesNode.GetRecordDefinition: IScalarRecordDefinition;
|
||||||
|
begin
|
||||||
|
Result := FRecordDefinition;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCreateSeriesNode.GetKind: TAstNodeKind;
|
function TCreateSeriesNode.GetKind: TAstNodeKind;
|
||||||
|
|||||||
@@ -458,7 +458,9 @@ end;
|
|||||||
|
|
||||||
function TPrettyPrintVisitor.VisitCreateSeries(const N: IAstNode): TVoid;
|
function TPrettyPrintVisitor.VisitCreateSeries(const N: IAstNode): TVoid;
|
||||||
begin
|
begin
|
||||||
Append(Format('(new-series "%s")', [N.AsCreateSeries.Definition]));
|
Append('(new-series ');
|
||||||
|
Visit(N.AsCreateSeries.DefinitionNode);
|
||||||
|
Append(')');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPrettyPrintVisitor.VisitAddSeriesItem(const N: IAstNode): TVoid;
|
function TPrettyPrintVisitor.VisitAddSeriesItem(const N: IAstNode): TVoid;
|
||||||
|
|||||||
@@ -612,10 +612,11 @@ begin
|
|||||||
end
|
end
|
||||||
else if SameText(head.Token.Text, 'new-series') then
|
else if SameText(head.Token.Text, 'new-series') then
|
||||||
begin
|
begin
|
||||||
if (tailNodes[0].Kind = akConstant) and (tailNodes[0].AsConstant.Value.Kind = vkText) then
|
if Length(tailNodes) <> 1 then
|
||||||
Result := TAst.CreateSeries(tailNodes[0].AsConstant.Value.AsText, startLoc)
|
Error('Syntax Error: ''new-series'' requires exactly one argument (the definition vector).');
|
||||||
else
|
|
||||||
Error('Syntax Error: ''new-series'' argument must be a string literal.');
|
// UPDATED: Accept any node (usually a vector) as definition
|
||||||
|
Result := TAst.CreateSeries(tailNodes[0], startLoc);
|
||||||
end
|
end
|
||||||
else if SameText(head.Token.Text, 'add-item') then
|
else if SameText(head.Token.Text, 'add-item') then
|
||||||
begin
|
begin
|
||||||
|
|||||||
+18
-8
@@ -54,9 +54,11 @@ type
|
|||||||
const AStaticType: IStaticType = nil
|
const AStaticType: IStaticType = nil
|
||||||
): ITupleNode; overload; static;
|
): ITupleNode; overload; static;
|
||||||
|
|
||||||
class function CreateSeries(const ADefinition: String; const Loc: ISourceLocation = nil): ICreateSeriesNode; overload; static;
|
class function CreateSeries(const ADefinitionNode: IAstNode; const Loc: ISourceLocation = nil): ICreateSeriesNode; overload; static;
|
||||||
class function CreateSeries(
|
class function CreateSeries(
|
||||||
const Identity: IDefinitionIdentity;
|
const Identity: IAstIdentity;
|
||||||
|
const ADefinitionNode: IAstNode;
|
||||||
|
const ARecordDefinition: IScalarRecordDefinition = nil;
|
||||||
const AStaticType: IStaticType = nil
|
const AStaticType: IStaticType = nil
|
||||||
): ICreateSeriesNode; overload; static;
|
): ICreateSeriesNode; overload; static;
|
||||||
|
|
||||||
@@ -402,19 +404,27 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TAst.CreateSeries(const ADefinition: String; const Loc: ISourceLocation): ICreateSeriesNode;
|
class function TAst.CreateSeries(const ADefinitionNode: IAstNode; const Loc: ISourceLocation): ICreateSeriesNode;
|
||||||
begin
|
begin
|
||||||
var id := TIdentities.Definition(ADefinition, Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
Result := TCreateSeriesNode.Create(id, TTypes.Unknown);
|
// RecordDefinition is nil initially, populated by TypeChecker
|
||||||
|
Result := TCreateSeriesNode.Create(ADefinitionNode, nil, TTypes.Unknown, id);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TAst.CreateSeries(const Identity: IDefinitionIdentity; const AStaticType: IStaticType): ICreateSeriesNode;
|
class function TAst.CreateSeries(
|
||||||
|
const Identity: IAstIdentity;
|
||||||
|
const ADefinitionNode: IAstNode;
|
||||||
|
const ARecordDefinition: IScalarRecordDefinition;
|
||||||
|
const AStaticType: IStaticType
|
||||||
|
): ICreateSeriesNode;
|
||||||
begin
|
begin
|
||||||
Result :=
|
Result :=
|
||||||
TCreateSeriesNode.Create(
|
TCreateSeriesNode.Create(
|
||||||
Identity,
|
ADefinitionNode,
|
||||||
|
ARecordDefinition,
|
||||||
if AStaticType <> nil then AStaticType
|
if AStaticType <> nil then AStaticType
|
||||||
else TTypes.Unknown
|
else TTypes.Unknown,
|
||||||
|
Identity
|
||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,8 @@ type
|
|||||||
// --- Series Operations ---
|
// --- Series Operations ---
|
||||||
|
|
||||||
TCreateSeriesNodeHandler = class(TBaseNodeHandler<ICreateSeriesNode>)
|
TCreateSeriesNodeHandler = class(TBaseNodeHandler<ICreateSeriesNode>)
|
||||||
|
private
|
||||||
|
FDefNode: TAstViewNode;
|
||||||
public
|
public
|
||||||
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
||||||
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
||||||
@@ -131,14 +133,15 @@ begin
|
|||||||
OwnerNode.Frameless := True;
|
OwnerNode.Frameless := True;
|
||||||
OwnerNode.Orientation := loHorizontal;
|
OwnerNode.Orientation := loHorizontal;
|
||||||
|
|
||||||
varLabel := OwnerNode.AddLabel(OwnerNode, 'var');
|
varLabel := OwnerNode.AddLabel(OwnerNode, 'def'); // Changed 'var' to 'def' to match syntax
|
||||||
|
|
||||||
varLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
varLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
||||||
FTargetNode := visu.CallAccept(FNode.Target);
|
FTargetNode := visu.CallAccept(FNode.Target);
|
||||||
|
|
||||||
if Assigned(FNode.Initializer) then
|
if Assigned(FNode.Initializer) then
|
||||||
begin
|
begin
|
||||||
OwnerNode.AddLabel(OwnerNode, ':=');
|
// Space before value
|
||||||
|
OwnerNode.AddLabel(OwnerNode, ' ');
|
||||||
FInitializerNode := visu.CallAccept(FNode.Initializer);
|
FInitializerNode := visu.CallAccept(FNode.Initializer);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -166,8 +169,9 @@ begin
|
|||||||
|
|
||||||
OwnerNode.Frameless := True;
|
OwnerNode.Frameless := True;
|
||||||
OwnerNode.Orientation := loHorizontal;
|
OwnerNode.Orientation := loHorizontal;
|
||||||
|
OwnerNode.AddLabel(OwnerNode, 'assign ');
|
||||||
FTargetNode := visu.CallAccept(FNode.Target);
|
FTargetNode := visu.CallAccept(FNode.Target);
|
||||||
OwnerNode.AddLabel(OwnerNode, ':=');
|
OwnerNode.AddLabel(OwnerNode, ' ');
|
||||||
FValueNode := visu.CallAccept(FNode.Value);
|
FValueNode := visu.CallAccept(FNode.Value);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -185,9 +189,9 @@ var
|
|||||||
begin
|
begin
|
||||||
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
||||||
|
|
||||||
OwnerNode.Frameless := False;
|
OwnerNode.Frameless := True;
|
||||||
OwnerNode.Orientation := loVertical;
|
OwnerNode.Orientation := loHorizontal;
|
||||||
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Quasiquote');
|
titleLabel := OwnerNode.AddLabel(OwnerNode, '`');
|
||||||
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
||||||
FExpressionNode := visu.CallAccept(FNode.Expression);
|
FExpressionNode := visu.CallAccept(FNode.Expression);
|
||||||
end;
|
end;
|
||||||
@@ -202,25 +206,19 @@ end;
|
|||||||
procedure TUnquoteNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
procedure TUnquoteNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
||||||
var
|
var
|
||||||
visu: IAstVisualizer;
|
visu: IAstVisualizer;
|
||||||
leftBracket, rightBracket: TTextNode;
|
leftBracket: TTextNode;
|
||||||
begin
|
begin
|
||||||
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
||||||
|
|
||||||
OwnerNode.Frameless := True;
|
OwnerNode.Frameless := True;
|
||||||
OwnerNode.Orientation := loHorizontal;
|
OwnerNode.Orientation := loHorizontal;
|
||||||
|
|
||||||
leftBracket := OwnerNode.AddLabel(OwnerNode, '<');
|
leftBracket := OwnerNode.AddLabel(OwnerNode, '~');
|
||||||
// We cannot assign to fields of record properties directly.
|
leftBracket.FontSettings.Font.Style := [TFontStyle.fsBold];
|
||||||
// Replace the entire margin record.
|
// Remove right margin to stick to expression
|
||||||
// Default from AddLabel is (cNodePadding, cTitleTopPadding, cNodePadding, cTitleBottomPadding)
|
|
||||||
// We want Right Margin = 0.
|
|
||||||
leftBracket.Margins := TMarginRect.Create(cNodePadding, cTitleTopPadding, 0, cTitleBottomPadding);
|
leftBracket.Margins := TMarginRect.Create(cNodePadding, cTitleTopPadding, 0, cTitleBottomPadding);
|
||||||
|
|
||||||
FExpressionNode := visu.CallAccept(FNode.Expression);
|
FExpressionNode := visu.CallAccept(FNode.Expression);
|
||||||
|
|
||||||
rightBracket := OwnerNode.AddLabel(OwnerNode, '>');
|
|
||||||
// We want Left Margin = 0.
|
|
||||||
rightBracket.Margins := TMarginRect.Create(0, cTitleTopPadding, cNodePadding, cTitleBottomPadding);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TUnquoteNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
function TUnquoteNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
@@ -237,10 +235,13 @@ var
|
|||||||
begin
|
begin
|
||||||
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
||||||
|
|
||||||
OwnerNode.Frameless := False;
|
OwnerNode.Frameless := True;
|
||||||
OwnerNode.Orientation := loVertical;
|
OwnerNode.Orientation := loHorizontal;
|
||||||
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Unquote-Splicing');
|
titleLabel := OwnerNode.AddLabel(OwnerNode, '~@');
|
||||||
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
||||||
|
// Remove right margin
|
||||||
|
titleLabel.Margins := TMarginRect.Create(cNodePadding, cTitleTopPadding, 0, cTitleBottomPadding);
|
||||||
|
|
||||||
FExpressionNode := visu.CallAccept(FNode.Expression);
|
FExpressionNode := visu.CallAccept(FNode.Expression);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -259,10 +260,10 @@ begin
|
|||||||
|
|
||||||
OwnerNode.Frameless := True;
|
OwnerNode.Frameless := True;
|
||||||
OwnerNode.Orientation := loHorizontal;
|
OwnerNode.Orientation := loHorizontal;
|
||||||
|
OwnerNode.AddLabel(OwnerNode, 'get ');
|
||||||
FBaseNode := visu.CallAccept(FNode.Base);
|
FBaseNode := visu.CallAccept(FNode.Base);
|
||||||
OwnerNode.AddLabel(OwnerNode, '[');
|
OwnerNode.AddLabel(OwnerNode, ' ');
|
||||||
FIndexNode := visu.CallAccept(FNode.Index);
|
FIndexNode := visu.CallAccept(FNode.Index);
|
||||||
OwnerNode.AddLabel(OwnerNode, ']');
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TIndexerNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
function TIndexerNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
@@ -280,9 +281,10 @@ begin
|
|||||||
|
|
||||||
OwnerNode.Frameless := True;
|
OwnerNode.Frameless := True;
|
||||||
OwnerNode.Orientation := loHorizontal;
|
OwnerNode.Orientation := loHorizontal;
|
||||||
FBaseNode := visu.CallAccept(FNode.Base);
|
|
||||||
OwnerNode.AddLabel(OwnerNode, '.');
|
OwnerNode.AddLabel(OwnerNode, '.');
|
||||||
OwnerNode.AddLabel(OwnerNode, FNode.Member.Value.Name);
|
OwnerNode.AddLabel(OwnerNode, FNode.Member.Value.Name);
|
||||||
|
OwnerNode.AddLabel(OwnerNode, ' ');
|
||||||
|
FBaseNode := visu.CallAccept(FNode.Base);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMemberAccessNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
function TMemberAccessNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
@@ -306,6 +308,7 @@ begin
|
|||||||
FKeyLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
FKeyLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
||||||
FKeyLabel.Color := TAlphaColors.Mediumvioletred;
|
FKeyLabel.Color := TAlphaColors.Mediumvioletred;
|
||||||
|
|
||||||
|
OwnerNode.AddLabel(OwnerNode, ' ');
|
||||||
FValueNode := visu.CallAccept(FNode.Value);
|
FValueNode := visu.CallAccept(FNode.Value);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -319,15 +322,22 @@ end;
|
|||||||
procedure TRecordLiteralNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
procedure TRecordLiteralNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
||||||
var
|
var
|
||||||
visu: IAstVisualizer;
|
visu: IAstVisualizer;
|
||||||
|
braceL: TTextNode;
|
||||||
begin
|
begin
|
||||||
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
||||||
|
|
||||||
OwnerNode.Frameless := False;
|
OwnerNode.Frameless := False;
|
||||||
OwnerNode.Orientation := loVertical;
|
OwnerNode.Orientation := loVertical;
|
||||||
OwnerNode.Alignment := laFlush;
|
OwnerNode.Alignment := laFlush; // Align left
|
||||||
|
|
||||||
|
// Visual hint: Curly braces for record
|
||||||
|
braceL := OwnerNode.AddLabel(OwnerNode, '{');
|
||||||
|
braceL.FontSettings.Font.Style := [TFontStyle.fsBold];
|
||||||
|
|
||||||
// Delegate to Fields Tuple (previously RecordFieldList)
|
// Delegate to Fields Tuple (previously RecordFieldList)
|
||||||
FFieldsNode := visu.CallAccept(FNode.Fields);
|
FFieldsNode := visu.CallAccept(FNode.Fields);
|
||||||
|
|
||||||
|
OwnerNode.AddLabel(OwnerNode, '}');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TRecordLiteralNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
function TRecordLiteralNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
@@ -346,17 +356,24 @@ end;
|
|||||||
|
|
||||||
procedure TCreateSeriesNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
procedure TCreateSeriesNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
||||||
var
|
var
|
||||||
|
visu: IAstVisualizer;
|
||||||
titleLabel: TTextNode;
|
titleLabel: TTextNode;
|
||||||
begin
|
begin
|
||||||
|
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
||||||
|
|
||||||
OwnerNode.Frameless := False;
|
OwnerNode.Frameless := False;
|
||||||
OwnerNode.Orientation := loVertical;
|
OwnerNode.Orientation := loVertical;
|
||||||
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Create Series: ' + FNode.Definition);
|
|
||||||
|
titleLabel := OwnerNode.AddLabel(OwnerNode, 'new-series');
|
||||||
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
||||||
|
|
||||||
|
// Now visualize the definition node (likely a Tuple or Keyword)
|
||||||
|
FDefNode := visu.CallAccept(FNode.DefinitionNode);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCreateSeriesNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
function TCreateSeriesNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
begin
|
begin
|
||||||
Result := TAst.CreateSeries(FNode.Identity.AsDefinition, FNode.StaticType);
|
Result := TAst.CreateSeries(FNode.Identity, FDefNode.CreateAst, FNode.RecordDefinition, FNode.StaticType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TAddSeriesItemNodeHandler }
|
{ TAddSeriesItemNodeHandler }
|
||||||
@@ -371,12 +388,15 @@ begin
|
|||||||
OwnerNode.Frameless := False;
|
OwnerNode.Frameless := False;
|
||||||
OwnerNode.Orientation := loVertical;
|
OwnerNode.Orientation := loVertical;
|
||||||
|
|
||||||
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Add Item to: ' + FNode.Series.Name);
|
titleLabel := OwnerNode.AddLabel(OwnerNode, 'add-item: ' + FNode.Series.Name);
|
||||||
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
||||||
|
|
||||||
FValueNode := visu.CallAccept(FNode.Value);
|
FValueNode := visu.CallAccept(FNode.Value);
|
||||||
if Assigned(FNode.Lookback) then
|
if Assigned(FNode.Lookback) then
|
||||||
FLookbackNode := visu.CallAccept(FNode.Lookback)
|
begin
|
||||||
|
OwnerNode.AddLabel(OwnerNode, 'Lookback:');
|
||||||
|
FLookbackNode := visu.CallAccept(FNode.Lookback);
|
||||||
|
end
|
||||||
else
|
else
|
||||||
FLookbackNode := nil;
|
FLookbackNode := nil;
|
||||||
end;
|
end;
|
||||||
@@ -406,9 +426,9 @@ procedure TSeriesLengthNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
|||||||
var
|
var
|
||||||
titleLabel: TTextNode;
|
titleLabel: TTextNode;
|
||||||
begin
|
begin
|
||||||
OwnerNode.Frameless := False;
|
OwnerNode.Frameless := True;
|
||||||
OwnerNode.Orientation := loVertical;
|
OwnerNode.Orientation := loHorizontal;
|
||||||
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Length of: ' + FNode.Series.Name);
|
titleLabel := OwnerNode.AddLabel(OwnerNode, 'count ' + FNode.Series.Name);
|
||||||
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,8 @@ var
|
|||||||
resultVal: TDataValue;
|
resultVal: TDataValue;
|
||||||
begin
|
begin
|
||||||
// Chained Access: (get (.data (if false ...)) 0)
|
// Chained Access: (get (.data (if false ...)) 0)
|
||||||
script := '(do ' + ' (def root (if false {:data (new-series "ordinal")}))' + ' (get (.data root) 0)' + ')';
|
// Updated: Use :Ordinal instead of "ordinal"
|
||||||
|
script := '(do ' + ' (def root (if false {:data (new-series :Ordinal)}))' + ' (get (.data root) 0)' + ')';
|
||||||
|
|
||||||
resultVal := FEnv.Run(TAstScript.Parse(script));
|
resultVal := FEnv.Run(TAstScript.Parse(script));
|
||||||
|
|
||||||
@@ -103,7 +104,8 @@ var
|
|||||||
begin
|
begin
|
||||||
// 1. Define 's' as Optional<Series>
|
// 1. Define 's' as Optional<Series>
|
||||||
// 2. Access via Indexer
|
// 2. Access via Indexer
|
||||||
script := '(do ' + ' (def s (if false (new-series "ordinal")))' + ' (get s 42)' + ')';
|
// Updated: Use :Ordinal instead of "ordinal"
|
||||||
|
script := '(do ' + ' (def s (if false (new-series :Ordinal)))' + ' (get s 42)' + ')';
|
||||||
|
|
||||||
// FIX: Parse String to AST Node
|
// FIX: Parse String to AST Node
|
||||||
resultVal := FEnv.Run(TAstScript.Parse(script));
|
resultVal := FEnv.Run(TAstScript.Parse(script));
|
||||||
@@ -120,11 +122,11 @@ begin
|
|||||||
FEnv.Run(
|
FEnv.Run(
|
||||||
TAstScript.Parse(
|
TAstScript.Parse(
|
||||||
'''
|
'''
|
||||||
(do
|
(do
|
||||||
(def a (if true 10)) ; a is Optional<Ordinal>
|
(def a (if true 10)) ; a is Optional<Ordinal>
|
||||||
(+ a 5) ; Error: Operator + not defined for Optional
|
(+ a 5) ; Error: Operator + not defined for Optional
|
||||||
)
|
)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
end,
|
end,
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ type
|
|||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
|
||||||
// Manual trigger
|
// Manual trigger
|
||||||
procedure Emit(CycleID: Integer);
|
procedure Emit(CycleID: Int64);
|
||||||
|
|
||||||
// IStream implementation
|
// IStream implementation
|
||||||
function Subscribe(const Observer: IStreamObserver): TSubscriptionTag;
|
function Subscribe(const Observer: IStreamObserver): TSubscriptionTag;
|
||||||
@@ -122,7 +122,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestStream.Emit(CycleID: Integer);
|
procedure TTestStream.Emit(CycleID: Int64);
|
||||||
var
|
var
|
||||||
obs: IStreamObserver;
|
obs: IStreamObserver;
|
||||||
observersCopy: TArray<IStreamObserver>;
|
observersCopy: TArray<IStreamObserver>;
|
||||||
@@ -227,7 +227,8 @@ begin
|
|||||||
|
|
||||||
FEnv.RootScope.Define('src', mockStream, TTypes.CreateRecordSeries(source.Def));
|
FEnv.RootScope.Define('src', mockStream, TTypes.CreateRecordSeries(source.Def));
|
||||||
|
|
||||||
script := '(pipe [src [:non_existent]] (fn [x] {:res x}))';
|
// Notice double bracket [[ ... ]] to correctly form the input vector
|
||||||
|
script := '(pipe [[src [:non_existent]]] (fn [x] {:res x}))';
|
||||||
|
|
||||||
Assert.WillRaise(procedure begin FEnv.Run(TAstScript.Parse(script)); end, ECompilationFailed);
|
Assert.WillRaise(procedure begin FEnv.Run(TAstScript.Parse(script)); end, ECompilationFailed);
|
||||||
end;
|
end;
|
||||||
|
|||||||
Reference in New Issue
Block a user