Replaced Count-Node by RTL-Function

This commit is contained in:
Michael Schimmel
2026-01-13 23:17:32 +01:00
parent 1258f79347
commit 2cc5e53394
17 changed files with 27 additions and 213 deletions
-9
View File
@@ -22,7 +22,6 @@ type
function VisitBlockExpression(const Node: IAstNode): Boolean;
function VisitRecordLiteral(const Node: IAstNode): Boolean;
function VisitVariableDeclaration(const Node: IAstNode): Boolean;
function VisitSeriesLength(const Node: IAstNode): Boolean;
// --- Elements ---
function VisitRecordField(const Node: IAstNode): Boolean;
@@ -120,7 +119,6 @@ begin
Register(akRecordLiteral, VisitRecordLiteral);
Register(akCreateSeries, VisitCreateSeries);
Register(akAddSeriesItem, VisitAddSeriesItem);
Register(akSeriesLength, VisitSeriesLength);
Register(akRecur, VisitRecurNode);
Register(akNop, VisitNop);
@@ -257,13 +255,6 @@ begin
Result := IsNodePure(Node.AsMemberAccess.Base);
end;
function TPurityAnalyzer.VisitSeriesLength(const Node: IAstNode): Boolean;
begin
// Querying length is pure.
// The series identifier check happens in VisitIdentifier.
Result := True;
end;
// --- Forbidden (Impure) ---
function TPurityAnalyzer.VisitAssignment(const Node: IAstNode): Boolean;
-7
View File
@@ -64,7 +64,6 @@ type
function VisitMemberAccess(const Node: IAstNode): IAstNode;
function VisitIndexer(const Node: IAstNode): IAstNode;
function VisitCreateSeries(const Node: IAstNode): IAstNode;
function VisitSeriesLength(const Node: IAstNode): IAstNode;
function VisitRecurNode(const Node: IAstNode): IAstNode;
function VisitNop(const Node: IAstNode): IAstNode;
function VisitRecordLiteral(const Node: IAstNode): IAstNode;
@@ -232,7 +231,6 @@ begin
Register(akMemberAccess, VisitMemberAccess);
Register(akIndexer, VisitIndexer);
Register(akCreateSeries, VisitCreateSeries);
Register(akSeriesLength, VisitSeriesLength);
Register(akRecur, VisitRecurNode);
Register(akNop, VisitNop);
Register(akRecordLiteral, VisitRecordLiteral);
@@ -960,11 +958,6 @@ begin
Result := TAst.CreateSeries(Node.Identity, defNode, recDef, resType);
end;
function TTypeChecker.VisitSeriesLength(const Node: IAstNode): IAstNode;
begin
Result := TAst.SeriesLength(Node.Identity, Accept(Node.AsSeriesLength.Series).AsIdentifier, TTypes.Ordinal);
end;
function TTypeChecker.VisitNop(const Node: IAstNode): IAstNode;
begin
Result := TAst.Nop(Node.Identity, TTypes.Void);
-10
View File
@@ -53,7 +53,6 @@ type
function VisitRecordField(const Node: IAstNode): TVoid;
function VisitCreateSeries(const Node: IAstNode): TVoid;
function VisitAddSeriesItem(const Node: IAstNode): TVoid;
function VisitSeriesLength(const Node: IAstNode): TVoid;
function VisitNop(const Node: IAstNode): TVoid;
function VisitTuple(const Node: IAstNode): TVoid;
function VisitPipe(const Node: IAstNode): TVoid;
@@ -122,7 +121,6 @@ begin
Register(akRecordLiteral, VisitRecordLiteral);
Register(akCreateSeries, VisitCreateSeries);
Register(akAddSeriesItem, VisitAddSeriesItem);
Register(akSeriesLength, VisitSeriesLength);
Register(akRecur, VisitRecurNode);
Register(akNop, VisitNop);
Register(akPipe, VisitPipe);
@@ -517,14 +515,6 @@ begin
Unindent;
end;
function TAstDumper.VisitSeriesLength(const Node: IAstNode): TVoid;
begin
Log('SeriesLength', Node);
Indent;
Visit(Node.AsSeriesLength.Series);
Unindent;
end;
function TAstDumper.VisitNop(const Node: IAstNode): TVoid;
begin
Log('Nop', Node);
-11
View File
@@ -43,7 +43,6 @@ type
function VisitRecordLiteral(const N: IRecordLiteralNode): TDataValue; virtual;
function VisitCreateSeries(const N: ICreateSeriesNode): TDataValue; virtual;
function VisitAddSeriesItem(const N: IAddSeriesItemNode): TDataValue; virtual;
function VisitSeriesLength(const N: ISeriesLengthNode): TDataValue; virtual;
function VisitRecurNode(const N: IRecurNode): TDataValue; virtual;
function VisitPipe(const N: IPipeNode): TDataValue; virtual;
@@ -107,7 +106,6 @@ begin
akRecordLiteral: Result := VisitRecordLiteral(Node.AsRecordLiteral);
akCreateSeries: Result := VisitCreateSeries(Node.AsCreateSeries);
akAddSeriesItem: Result := VisitAddSeriesItem(Node.AsAddSeriesItem);
akSeriesLength: Result := VisitSeriesLength(Node.AsSeriesLength);
akRecur: Result := VisitRecurNode(Node.AsRecur);
akPipe: Result := VisitPipe(Node.AsPipe);
akMacroExpansion: Result := Visit(Node.AsMacroExpansion.ExpandedBody);
@@ -546,15 +544,6 @@ begin
Result := TDataValue.Void;
end;
function TEvaluatorVisitor.VisitSeriesLength(const N: ISeriesLengthNode): TDataValue;
begin
var s := FScope[N.Series.Address];
var len :=
if s.Kind = vkSeries then s.AsSeries.Count
else s.AsRecordSeries.RecordCount;
Result := TDataValue(TScalar.FromInt64(len));
end;
function TEvaluatorVisitor.VisitPipe(const N: IPipeNode): TDataValue;
var
i: Integer;
-14
View File
@@ -51,7 +51,6 @@ type
function VisitRecordLiteral(const Node: IAstNode): TJSONValue;
function VisitCreateSeries(const Node: IAstNode): TJSONValue;
function VisitAddSeriesItem(const Node: IAstNode): TJSONValue;
function VisitSeriesLength(const Node: IAstNode): TJSONValue;
function VisitNop(const Node: IAstNode): TJSONValue;
function VisitPipe(const Node: IAstNode): TJSONValue;
@@ -101,7 +100,6 @@ begin
Register(akRecordLiteral, VisitRecordLiteral);
Register(akCreateSeries, VisitCreateSeries);
Register(akAddSeriesItem, VisitAddSeriesItem);
Register(akSeriesLength, VisitSeriesLength);
Register(akRecur, VisitRecurNode);
Register(akNop, VisitNop);
Register(akPipe, VisitPipe);
@@ -421,16 +419,6 @@ begin
Result := arr;
end;
function TJsonAstConverter.VisitSeriesLength(const Node: IAstNode): TJSONValue;
var
arr: TJSONArray;
begin
arr := TJSONArray.Create;
arr.Add('Count');
arr.AddElement(Visit(Node.AsSeriesLength.Series));
Result := arr;
end;
function TJsonAstConverter.VisitRecurNode(const Node: IAstNode): TJSONValue;
var
arr: TJSONArray;
@@ -623,8 +611,6 @@ begin
exit(TAst.MemberAccess(JsonToNode(arr.Items[1]), JsonToNode(arr.Items[2]).AsKeyword));
if kind = 'Series' then
exit(TAst.CreateSeries(JsonToNode(arr.Items[1])));
if kind = 'Count' then
exit(TAst.SeriesLength(JsonToNode(arr.Items[1]).AsIdentifier));
if kind = 'Pipe' then
exit(TAst.Pipe(JsonToNode(arr.Items[1]).AsTuple, JsonToNode(arr.Items[2]).AsLambdaExpression));
-51
View File
@@ -102,7 +102,6 @@ type
IRecordLiteralNode = interface;
ICreateSeriesNode = interface;
IAddSeriesItemNode = interface;
ISeriesLengthNode = interface;
IRecurNode = interface;
INopNode = interface;
IPipeNode = interface;
@@ -130,7 +129,6 @@ type
akRecordLiteral,
akCreateSeries,
akAddSeriesItem,
akSeriesLength,
akRecur,
akNop,
akPipe
@@ -178,7 +176,6 @@ type
function AsRecordLiteral: IRecordLiteralNode;
function AsCreateSeries: ICreateSeriesNode;
function AsAddSeriesItem: IAddSeriesItemNode;
function AsSeriesLength: ISeriesLengthNode;
function AsRecur: IRecurNode;
function AsNop: INopNode;
function AsPipe: IPipeNode;
@@ -532,17 +529,6 @@ type
property Lookback: IAstNode read GetLookback;
end;
[AstTag('Count')]
[AstDoc('Returns the current number of elements in a series.')]
[AstScriptExample('(count prices)')]
[AstField(0, 'series', fkNode)]
ISeriesLengthNode = interface(IAstTypedNode)
{$region 'private'}
function GetSeries: IIdentifierNode;
{$endregion}
property Series: IIdentifierNode read GetSeries;
end;
[AstTag('Recur')]
[AstDoc('Tail-recursive call to the current function.')]
[AstScriptExample('(recur (- n 1))')]
@@ -623,7 +609,6 @@ type
function AsRecordLiteral: IRecordLiteralNode; virtual;
function AsCreateSeries: ICreateSeriesNode; virtual;
function AsAddSeriesItem: IAddSeriesItemNode; virtual;
function AsSeriesLength: ISeriesLengthNode; virtual;
function AsRecur: IRecurNode; virtual;
function AsNop: INopNode; virtual;
function AsPipe: IPipeNode; virtual;
@@ -996,17 +981,6 @@ type
function AsAddSeriesItem: IAddSeriesItemNode; override;
end;
TSeriesLengthNode = class(TAstTypedNode, ISeriesLengthNode)
private
FSeries: IIdentifierNode;
function GetSeries: IIdentifierNode;
protected
function GetKind: TAstNodeKind; override;
public
constructor Create(const ASeries: IIdentifierNode; const AStaticType: IStaticType; const AIdentity: IAstIdentity);
function AsSeriesLength: ISeriesLengthNode; override;
end;
TRecurNode = class(TAstTypedNode, IRecurNode)
private
FArguments: ITupleNode;
@@ -1288,10 +1262,6 @@ function TAstNode.AsAddSeriesItem: IAddSeriesItemNode;
begin
Result := nil;
end;
function TAstNode.AsSeriesLength: ISeriesLengthNode;
begin
Result := nil;
end;
function TAstNode.AsRecur: IRecurNode;
begin
Result := nil;
@@ -1992,27 +1962,6 @@ begin
Result := Self;
end;
{ TSeriesLengthNode }
constructor TSeriesLengthNode.Create(const ASeries: IIdentifierNode; const AStaticType: IStaticType; const AIdentity: IAstIdentity);
begin
inherited Create(AStaticType, AIdentity);
FSeries := ASeries;
end;
function TSeriesLengthNode.GetKind: TAstNodeKind;
begin
Result := akSeriesLength;
end;
function TSeriesLengthNode.GetSeries: IIdentifierNode;
begin
Result := FSeries;
end;
function TSeriesLengthNode.AsSeriesLength: ISeriesLengthNode;
begin
Result := Self;
end;
{ TRecurNode }
constructor TRecurNode.Create(const AArguments: ITupleNode; const AStaticType: IStaticType; const AIdentity: IAstIdentity);
+21
View File
@@ -39,6 +39,12 @@ type
[AstDoc('Returns true if at least one element satisfies the predicate.')]
[AstSignature('(series, (any) -> boolean) -> boolean')]
class function Any(const Args: TArray<TDataValue>): TDataValue; static;
[TRtlExport('count', Pure)]
[AstDoc('Returns the current number of elements in a series.')]
[AstSignature('(series) -> number')]
[AstScriptExample('(count prices)')]
class function Count(const Args: TArray<TDataValue>): TDataValue; static;
end;
implementation
@@ -244,4 +250,19 @@ begin
Result := TScalar.FromBoolean(False);
end;
class function TRtlSeriesFunctions.Count(const Args: TArray<TDataValue>): TDataValue;
begin
if Length(Args) <> 1 then
raise EArgumentException.Create('Count requires one argument: a series.');
var sourceArg := Args[0];
case sourceArg.Kind of
vkSeries: Result := sourceArg.AsSeries.Count;
vkRecordSeries: Result := sourceArg.AsRecordSeries.Count;
else
raise EArgumentException.Create('The argument to Count must be a series.');
end;
end;
end.
-9
View File
@@ -49,7 +49,6 @@ type
function VisitRecordLiteral(const N: IAstNode): TVoid;
function VisitCreateSeries(const N: IAstNode): TVoid;
function VisitAddSeriesItem(const N: IAstNode): TVoid;
function VisitSeriesLength(const N: IAstNode): TVoid;
function VisitRecurNode(const N: IAstNode): TVoid;
function VisitNop(const N: IAstNode): TVoid;
@@ -108,7 +107,6 @@ begin
Register(akRecordLiteral, VisitRecordLiteral);
Register(akCreateSeries, VisitCreateSeries);
Register(akAddSeriesItem, VisitAddSeriesItem);
Register(akSeriesLength, VisitSeriesLength);
Register(akRecur, VisitRecurNode);
Register(akNop, VisitNop);
@@ -480,11 +478,4 @@ begin
Append(')');
end;
function TPrettyPrintVisitor.VisitSeriesLength(const N: IAstNode): TVoid;
begin
Append('(count ');
Visit(N.AsSeriesLength.Series);
Append(')');
end;
end.
-14
View File
@@ -224,9 +224,6 @@ type
[Ebnf('form-add ::= "add-item" expression expression [ expression ]')]
function ParseAddItem: IAstNode;
[Ebnf('form-count ::= "count" expression')]
function ParseCount: IAstNode;
[Ebnf('form-get ::= "get" expression expression')]
function ParseGet: IAstNode;
@@ -510,7 +507,6 @@ begin
FSpecialForms.Add('pipe', ParsePipe);
FSpecialForms.Add('new-series', ParseNewSeries);
FSpecialForms.Add('add-item', ParseAddItem);
FSpecialForms.Add('count', ParseCount);
FSpecialForms.Add('get', ParseGet);
NextToken;
end;
@@ -995,16 +991,6 @@ begin
Result := TAst.AddSeriesItem(s.AsIdentifier, v, lb);
end;
function TParser.ParseCount: IAstNode;
var
s: IAstNode;
begin
s := ParseExpression;
if s.Kind <> akIdentifier then
Error('Count argument must be an identifier');
Result := TAst.SeriesLength(s.AsIdentifier);
end;
function TParser.ParseGet: IAstNode;
var
base, idx: IAstNode;
+3 -3
View File
@@ -55,9 +55,6 @@ type
function GetHashCode: Integer;
end;
IGenericRecordDefinition = IKeywordMapping<IStaticType>;
TGenericRecordRegistry = TKeywordMappingRegistry<IStaticType>;
IScalarRecordDefinition = Myc.Data.Scalar.IScalarRecordDefinition;
// Base Interface
@@ -137,6 +134,9 @@ type
property Definition: IScalarRecordDefinition read GetDefinition;
end;
IGenericRecordDefinition = IKeywordMapping<IStaticType>;
TGenericRecordRegistry = TKeywordMappingRegistry<IStaticType>;
IGenericRecordType = interface(IStaticType)
{$region 'private'}
function GetGenericDefinition: IGenericRecordDefinition;
-22
View File
@@ -76,7 +76,6 @@ type
function VisitMemberAccess(const N: IAstNode): IAstNode;
function VisitRecordLiteral(const N: IAstNode): IAstNode;
function VisitAddSeriesItem(const N: IAstNode): IAstNode;
function VisitSeriesLength(const N: IAstNode): IAstNode;
function VisitRecurNode(const N: IAstNode): IAstNode;
// Unified List Type
@@ -114,7 +113,6 @@ type
function WalkMemberAccess(const N: IAstNode): TVoid;
function WalkRecordLiteral(const N: IAstNode): TVoid;
function WalkAddSeriesItem(const N: IAstNode): TVoid;
function WalkSeriesLength(const N: IAstNode): TVoid;
function WalkRecurNode(const N: IAstNode): TVoid;
function WalkTuple(const N: IAstNode): TVoid;
@@ -220,7 +218,6 @@ begin
Register(akMemberAccess, VisitMemberAccess);
Register(akRecordLiteral, VisitRecordLiteral);
Register(akAddSeriesItem, VisitAddSeriesItem);
Register(akSeriesLength, VisitSeriesLength);
Register(akRecur, VisitRecurNode);
// Unified List Type
@@ -487,19 +484,6 @@ begin
Result := TAst.AddSeriesItem(N.Identity, s.AsIdentifier, v, l, A.StaticType);
end;
function TAstTransformer.VisitSeriesLength(const N: IAstNode): IAstNode;
var
S: ISeriesLengthNode;
series: IAstNode;
begin
S := N.AsSeriesLength;
series := Visit(S.Series);
if series = S.Series then
Result := N
else
Result := TAst.SeriesLength(N.Identity, series.AsIdentifier, S.StaticType);
end;
function TAstTransformer.VisitRecurNode(const N: IAstNode): IAstNode;
var
R: IRecurNode;
@@ -593,7 +577,6 @@ begin
Register(akMemberAccess, WalkMemberAccess);
Register(akRecordLiteral, WalkRecordLiteral);
Register(akAddSeriesItem, WalkAddSeriesItem);
Register(akSeriesLength, WalkSeriesLength);
Register(akRecur, WalkRecurNode);
Register(akTuple, WalkTuple);
@@ -716,11 +699,6 @@ begin
Visit(A.Lookback);
end;
function TAstVisitor.WalkSeriesLength(const N: IAstNode): TVoid;
begin
Visit(N.AsSeriesLength.Series);
end;
function TAstVisitor.WalkRecurNode(const N: IAstNode): TVoid;
begin
Visit(N.AsRecur.Arguments);
-28
View File
@@ -262,13 +262,6 @@ type
const AStaticType: IStaticType = nil
): IAddSeriesItemNode; overload; static;
class function SeriesLength(const ASeries: IIdentifierNode; const Loc: ISourceLocation = nil): ISeriesLengthNode; overload; static;
class function SeriesLength(
const Identity: IAstIdentity;
const ASeries: IIdentifierNode;
const AStaticType: IStaticType = nil
): ISeriesLengthNode; overload; static;
// --- PIPES ---
class function Pipe(
@@ -871,27 +864,6 @@ begin
);
end;
class function TAst.SeriesLength(const ASeries: IIdentifierNode; const Loc: ISourceLocation): ISeriesLengthNode;
begin
var id := TIdentities.Structural(Loc);
Result := TSeriesLengthNode.Create(ASeries, TTypes.Ordinal, id);
end;
class function TAst.SeriesLength(
const Identity: IAstIdentity;
const ASeries: IIdentifierNode;
const AStaticType: IStaticType
): ISeriesLengthNode;
begin
Result :=
TSeriesLengthNode.Create(
ASeries,
if AStaticType <> nil then AStaticType
else TTypes.Ordinal,
Identity
);
end;
// --- PIPES ---
class function TAst.Pipe(const AInputs: ITupleNode; const ATransformation: ILambdaExpressionNode; const Loc: ISourceLocation): IPipeNode;
@@ -113,12 +113,6 @@ type
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
end;
TSeriesLengthNodeHandler = class(TBaseNodeHandler<ISeriesLengthNode>)
public
procedure BuildUI(OwnerNode: TAstViewNode); override;
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
end;
implementation
{ TVariableDeclarationNodeHandler }
@@ -420,21 +414,4 @@ begin
);
end;
{ TSeriesLengthNodeHandler }
procedure TSeriesLengthNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
titleLabel: TTextNode;
begin
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'count ' + FNode.Series.Name);
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
end;
function TSeriesLengthNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
begin
Result := TAst.SeriesLength(FNode.Identity, FNode.Series, FNode.StaticType);
end;
end.
-8
View File
@@ -74,8 +74,6 @@ type
// Series
function VisitCreateSeries(const Node: IAstNode): TAstViewNode;
function VisitAddSeriesItem(const Node: IAstNode): TAstViewNode;
function VisitSeriesLength(const Node: IAstNode): TAstViewNode;
// Pipes
function VisitPipe(const Node: IAstNode): TAstViewNode;
@@ -161,7 +159,6 @@ begin
// Series
Register(akCreateSeries, VisitCreateSeries);
Register(akAddSeriesItem, VisitAddSeriesItem);
Register(akSeriesLength, VisitSeriesLength);
// Pipes (Simplified)
Register(akPipe, VisitPipe);
@@ -345,11 +342,6 @@ begin
Result := TAstViewNode.Create(Self, TAddSeriesItemNodeHandler.Create(Node.AsAddSeriesItem));
end;
function TAstVisualizer.VisitSeriesLength(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TSeriesLengthNodeHandler.Create(Node.AsSeriesLength));
end;
function TAstVisualizer.VisitPipe(const Node: IAstNode): TAstViewNode;
begin
Result := TAstViewNode.Create(Self, TPipeNodeHandler.Create(Node.AsPipe));