Nop-Node
This commit is contained in:
+17
-23
@@ -845,32 +845,26 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TForm1.Test1ButtonClick(Sender: TObject);
|
procedure TForm1.Test1ButtonClick(Sender: TObject);
|
||||||
var
|
|
||||||
main, callAst: IAstNode;
|
|
||||||
result: TDataValue;
|
|
||||||
sw: TStopwatch;
|
|
||||||
begin
|
begin
|
||||||
Memo1.Lines.Clear;
|
FCurrUnboundAst :=
|
||||||
Memo1.Lines.Add('--- Simple AST Execution ---');
|
TAst.Block(
|
||||||
sw := TStopwatch.StartNew;
|
[
|
||||||
|
TAst.LambdaExpr(
|
||||||
main :=
|
[],
|
||||||
TAst.LambdaExpr(
|
TAst.Block(
|
||||||
[],
|
[
|
||||||
TAst.Block(
|
TAst.VarDecl(TAst.Identifier('a'), TAst.Nop),
|
||||||
[
|
TAst.VarDecl(
|
||||||
TAst.VarDecl(TAst.Identifier('a'), TAst.Constant(10)),
|
TAst.Identifier('b'),
|
||||||
TAst.VarDecl(TAst.Identifier('b'), TAst.BinaryExpr(TAst.Identifier('a'), TScalar.TBinaryOp.Multiply, TAst.Constant(2))),
|
TAst.BinaryExpr(TAst.Identifier('a'), TScalar.TBinaryOp.Multiply, TAst.Constant(2))
|
||||||
TAst.BinaryExpr(TAst.Identifier('a'), TScalar.TBinaryOp.Add, TAst.Identifier('b'))
|
),
|
||||||
]
|
TAst.BinaryExpr(TAst.Identifier('a'), TScalar.TBinaryOp.Add, TAst.Identifier('b'))
|
||||||
)
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
callAst := TAst.FunctionCall(main, []);
|
|
||||||
result := ExecuteAst(callAst, FGScope);
|
|
||||||
|
|
||||||
sw.Stop;
|
|
||||||
Memo1.Lines.Add(Format('Result: %s (calculated in %d ms)', [result.ToString, sw.ElapsedMilliseconds]));
|
|
||||||
UpdateScript;
|
UpdateScript;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ type
|
|||||||
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAuraNode; override;
|
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TAuraNode; override;
|
||||||
function VisitSeriesLength(const Node: ISeriesLengthNode): TAuraNode; override;
|
function VisitSeriesLength(const Node: ISeriesLengthNode): TAuraNode; override;
|
||||||
function VisitRecurNode(const Node: IRecurNode): TAuraNode; override;
|
function VisitRecurNode(const Node: IRecurNode): TAuraNode; override;
|
||||||
|
function VisitNop(const Node: INopNode): TAuraNode; override;
|
||||||
|
|
||||||
public
|
public
|
||||||
constructor Create(AWorkspace: TAuraWorkspace; AParentControl: TControl; AExprDepth: Integer);
|
constructor Create(AWorkspace: TAuraWorkspace; AParentControl: TControl; AExprDepth: Integer);
|
||||||
@@ -525,6 +526,17 @@ type
|
|||||||
property Node: ISeriesLengthNode read FNode;
|
property Node: ISeriesLengthNode read FNode;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TAuraNopNode = class(TAuraNode)
|
||||||
|
private
|
||||||
|
FNode: INopNode;
|
||||||
|
protected
|
||||||
|
procedure SetupNode; override;
|
||||||
|
public
|
||||||
|
constructor Create(const AVisualizer: IAstVisualizer; const ANode: INopNode);
|
||||||
|
function CreateAst: IAstNode; override;
|
||||||
|
property Node: INopNode read FNode;
|
||||||
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
{ TAstVisualizer }
|
{ TAstVisualizer }
|
||||||
@@ -716,6 +728,11 @@ begin
|
|||||||
Result := TAuraVariableDeclarationNode.Create(Self, Node);
|
Result := TAuraVariableDeclarationNode.Create(Self, Node);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TAstVisualizer.VisitNop(const Node: INopNode): TAuraNode;
|
||||||
|
begin
|
||||||
|
Result := TAuraNopNode.Create(Self, Node);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TAutoFitControl }
|
{ TAutoFitControl }
|
||||||
|
|
||||||
constructor TAutoFitControl.Create(AOwner: TComponent);
|
constructor TAutoFitControl.Create(AOwner: TComponent);
|
||||||
@@ -1039,7 +1056,7 @@ begin
|
|||||||
Canvas.FillRect(TRectF.Create(0, 0, Width, Height), 0, 0, [], 1.0);
|
Canvas.FillRect(TRectF.Create(0, 0, Width, Height), 0, 0, [], 1.0);
|
||||||
Canvas.Stroke.Kind := TBrushKind.Solid;
|
Canvas.Stroke.Kind := TBrushKind.Solid;
|
||||||
Canvas.Stroke.Color := FBorderColor;
|
Canvas.Stroke.Color := FBorderColor;
|
||||||
Canvas.Stroke.Thickness := 1;
|
Canvas.Stroke.Thickness := FBorderWidth;
|
||||||
Canvas.Stroke.Dash := TStrokeDash.Dot;
|
Canvas.Stroke.Dash := TStrokeDash.Dot;
|
||||||
Canvas.DrawRect(TRectF.Create(0, 0, Width, Height), 0, 0, [], 1.0);
|
Canvas.DrawRect(TRectF.Create(0, 0, Width, Height), 0, 0, [], 1.0);
|
||||||
end
|
end
|
||||||
@@ -2222,4 +2239,38 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TAuraNopNode }
|
||||||
|
|
||||||
|
constructor TAuraNopNode.Create(const AVisualizer: IAstVisualizer; const ANode: INopNode);
|
||||||
|
begin
|
||||||
|
inherited Create(AVisualizer);
|
||||||
|
FNode := ANode;
|
||||||
|
|
||||||
|
// Visual style for Nop: Dotted border, minimal size, clear color.
|
||||||
|
Frameless := true;
|
||||||
|
Alignment := TLayoutAlignment.laCenter;
|
||||||
|
Orientation := TLayoutOrientation.loHorizontal;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAuraNopNode.CreateAst: IAstNode;
|
||||||
|
begin
|
||||||
|
// The visual node returns the original Nop node, which the compiler pipeline must reject.
|
||||||
|
Result := FNode;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TAuraNopNode.SetupNode;
|
||||||
|
var
|
||||||
|
lbl: TLabel;
|
||||||
|
begin
|
||||||
|
BeginUpdate;
|
||||||
|
try
|
||||||
|
// Add a placeholder text
|
||||||
|
lbl := AddLabel(Self, '...');
|
||||||
|
lbl.Font.Style := lbl.Font.Style + [TFontStyle.fsBold];
|
||||||
|
lbl.Margins.Rect := TRectF.Create(8, 4, 8, 4);
|
||||||
|
finally
|
||||||
|
EndUpdate;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ type
|
|||||||
procedure VisitCreateSeries(const Node: ICreateSeriesNode); override;
|
procedure VisitCreateSeries(const Node: ICreateSeriesNode); override;
|
||||||
procedure VisitAddSeriesItem(const Node: IAddSeriesItemNode); override;
|
procedure VisitAddSeriesItem(const Node: IAddSeriesItemNode); override;
|
||||||
procedure VisitSeriesLength(const Node: ISeriesLengthNode); override;
|
procedure VisitSeriesLength(const Node: ISeriesLengthNode); override;
|
||||||
|
procedure VisitNop(const Node: INopNode); override;
|
||||||
|
|
||||||
public
|
public
|
||||||
// Creates a new instance of the AST dumper.
|
// Creates a new instance of the AST dumper.
|
||||||
@@ -461,6 +462,11 @@ begin
|
|||||||
Unindent;
|
Unindent;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TAstDumper.VisitNop(const Node: INopNode);
|
||||||
|
begin
|
||||||
|
Log('Nop');
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TAstDumper.VisitSeriesLength(const Node: ISeriesLengthNode);
|
procedure TAstDumper.VisitSeriesLength(const Node: ISeriesLengthNode);
|
||||||
begin
|
begin
|
||||||
Log('SeriesLength');
|
Log('SeriesLength');
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ type
|
|||||||
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; virtual;
|
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue; virtual;
|
||||||
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; virtual;
|
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; virtual;
|
||||||
function VisitRecurNode(const Node: IRecurNode): TDataValue; virtual;
|
function VisitRecurNode(const Node: IRecurNode): TDataValue; virtual;
|
||||||
|
function VisitNop(const Node: INopNode): TDataValue; virtual;
|
||||||
|
|
||||||
function IsTruthy(const AValue: TDataValue): Boolean; inline;
|
function IsTruthy(const AValue: TDataValue): Boolean; inline;
|
||||||
|
|
||||||
@@ -445,6 +446,12 @@ var
|
|||||||
index: Int64;
|
index: Int64;
|
||||||
series: ISeries;
|
series: ISeries;
|
||||||
recSeries: IRecordSeries;
|
recSeries: IRecordSeries;
|
||||||
|
i, fieldCount: Integer;
|
||||||
|
values: TArray<TScalar.TValue>;
|
||||||
|
key: IKeyword;
|
||||||
|
memberSeries: ISeries;
|
||||||
|
scalarValue: TScalar;
|
||||||
|
rec: TScalarRecord;
|
||||||
begin
|
begin
|
||||||
baseValue := Node.Base.Accept(Self);
|
baseValue := Node.Base.Accept(Self);
|
||||||
indexValue := Node.Index.Accept(Self);
|
indexValue := Node.Index.Accept(Self);
|
||||||
@@ -467,12 +474,20 @@ begin
|
|||||||
recSeries := baseValue.AsRecordSeries;
|
recSeries := baseValue.AsRecordSeries;
|
||||||
if (index < 0) or (index >= recSeries.TotalCount) then
|
if (index < 0) or (index >= recSeries.TotalCount) then
|
||||||
raise EArgumentException.CreateFmt('Index %d is out of bounds for series with %d elements.', [index, recSeries.TotalCount]);
|
raise EArgumentException.CreateFmt('Index %d is out of bounds for series with %d elements.', [index, recSeries.TotalCount]);
|
||||||
// Accessing a record series by index materializes the TScalarRecord
|
|
||||||
var rec := TScalarRecord.Create(recSeries.Def, nil); // Nil fields, needs implementation
|
// Materialize the TScalarRecord by accessing each member series by index
|
||||||
// TODO: This path (materializing a record from TScalarRecordSeries) is not fully implemented.
|
fieldCount := Length(recSeries.Def.Fields);
|
||||||
// We need to fetch the underlying TScalar.TValue array slice.
|
SetLength(values, fieldCount);
|
||||||
// For now, returning an empty record shell.
|
|
||||||
raise ENotSupportedException.Create('Indexing a RecordSeries to materialize a Record is not yet implemented.');
|
for i := 0 to fieldCount - 1 do
|
||||||
|
begin
|
||||||
|
key := recSeries.Def.Fields[i].Key;
|
||||||
|
memberSeries := recSeries[key];
|
||||||
|
scalarValue := memberSeries[index];
|
||||||
|
values[i] := scalarValue.Value;
|
||||||
|
end;
|
||||||
|
|
||||||
|
rec := TScalarRecord.Create(recSeries.Def, values);
|
||||||
Result := TDataValue.FromRecord(rec);
|
Result := TDataValue.FromRecord(rec);
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
@@ -646,6 +661,13 @@ begin
|
|||||||
Result := expression.Accept(Self);
|
Result := expression.Accept(Self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TEvaluatorVisitor.VisitNop(const Node: INopNode): TDataValue;
|
||||||
|
begin
|
||||||
|
// This node should be rejected by the Binder/TypeChecker.
|
||||||
|
// If it reaches the evaluator, it's a compiler bug, but we treat it as Void.
|
||||||
|
Result := TDataValue.Void;
|
||||||
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
function TEvaluatorVisitor.VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
||||||
var
|
var
|
||||||
seriesValue: TDataValue;
|
seriesValue: TDataValue;
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ type
|
|||||||
function JsonToCreateSeriesNode(const AObj: TJSONObject): ICreateSeriesNode;
|
function JsonToCreateSeriesNode(const AObj: TJSONObject): ICreateSeriesNode;
|
||||||
function JsonToAddSeriesItemNode(const AObj: TJSONObject): IAddSeriesItemNode;
|
function JsonToAddSeriesItemNode(const AObj: TJSONObject): IAddSeriesItemNode;
|
||||||
function JsonToSeriesLengthNode(const AObj: TJSONObject): ISeriesLengthNode;
|
function JsonToSeriesLengthNode(const AObj: TJSONObject): ISeriesLengthNode;
|
||||||
|
function JsonToNopNode(const AObj: TJSONObject): INopNode;
|
||||||
|
|
||||||
protected
|
protected
|
||||||
// IAstVisitor implementation for serialization (T = TJSONObject)
|
// IAstVisitor implementation for serialization (T = TJSONObject)
|
||||||
function VisitConstant(const Node: IConstantNode): TJSONObject; override;
|
function VisitConstant(const Node: IConstantNode): TJSONObject; override;
|
||||||
@@ -77,6 +79,7 @@ type
|
|||||||
function VisitCreateSeries(const Node: ICreateSeriesNode): TJSONObject; override;
|
function VisitCreateSeries(const Node: ICreateSeriesNode): TJSONObject; override;
|
||||||
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TJSONObject; override;
|
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TJSONObject; override;
|
||||||
function VisitSeriesLength(const Node: ISeriesLengthNode): TJSONObject; override;
|
function VisitSeriesLength(const Node: ISeriesLengthNode): TJSONObject; override;
|
||||||
|
function VisitNop(const Node: INopNode): TJSONObject; override;
|
||||||
|
|
||||||
function Serialize(const RootNode: IAstNode): TJSONObject;
|
function Serialize(const RootNode: IAstNode): TJSONObject;
|
||||||
function Deserialize(const AJson: TJSONObject): IAstNode;
|
function Deserialize(const AJson: TJSONObject): IAstNode;
|
||||||
@@ -456,6 +459,13 @@ begin
|
|||||||
Result.AddPair('Series', seriesObj);
|
Result.AddPair('Series', seriesObj);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TJsonAstConverter.VisitNop(const Node: INopNode): TJSONObject;
|
||||||
|
begin
|
||||||
|
Result := TJSONObject.Create;
|
||||||
|
Result.AddPair('NodeType', TJSONString.Create('Nop'));
|
||||||
|
// No other properties needed, as it is stateless
|
||||||
|
end;
|
||||||
|
|
||||||
{ TJsonAstConverter - Deserialization }
|
{ TJsonAstConverter - Deserialization }
|
||||||
|
|
||||||
function TJsonAstConverter.JsonToDataValue(const AObj: TJSONObject; const AName: string): TDataValue;
|
function TJsonAstConverter.JsonToDataValue(const AObj: TJSONObject; const AName: string): TDataValue;
|
||||||
@@ -761,6 +771,11 @@ begin
|
|||||||
Result := TAst.SeriesLength(JsonToIdentifierNode(AObj.GetValue('Series') as TJSONObject));
|
Result := TAst.SeriesLength(JsonToIdentifierNode(AObj.GetValue('Series') as TJSONObject));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TJsonAstConverter.JsonToNopNode(const AObj: TJSONObject): INopNode;
|
||||||
|
begin
|
||||||
|
Result := TAst.Nop.AsNop;
|
||||||
|
end;
|
||||||
|
|
||||||
function TJsonAstConverter.JsonToNode(const AJson: TJSONValue; const ExpectedType: String = ''): IAstNode;
|
function TJsonAstConverter.JsonToNode(const AJson: TJSONValue; const ExpectedType: String = ''): IAstNode;
|
||||||
var
|
var
|
||||||
obj: TJSONObject;
|
obj: TJSONObject;
|
||||||
@@ -823,6 +838,8 @@ begin
|
|||||||
Result := JsonToAddSeriesItemNode(obj)
|
Result := JsonToAddSeriesItemNode(obj)
|
||||||
else if nodeType = 'SeriesLength' then
|
else if nodeType = 'SeriesLength' then
|
||||||
Result := JsonToSeriesLengthNode(obj)
|
Result := JsonToSeriesLengthNode(obj)
|
||||||
|
else if nodeType = 'Nop' then // Added Nop Deserialization logic
|
||||||
|
Result := JsonToNopNode(obj)
|
||||||
else
|
else
|
||||||
raise ENotSupportedException.CreateFmt('Unsupported NodeType "%s" for JSON deserialization.', [nodeType]);
|
raise ENotSupportedException.CreateFmt('Unsupported NodeType "%s" for JSON deserialization.', [nodeType]);
|
||||||
end;
|
end;
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ type
|
|||||||
IAddSeriesItemNode = interface;
|
IAddSeriesItemNode = interface;
|
||||||
ISeriesLengthNode = interface;
|
ISeriesLengthNode = interface;
|
||||||
IRecurNode = interface;
|
IRecurNode = interface;
|
||||||
|
INopNode = interface; // Added Nop
|
||||||
|
|
||||||
// Defines the concrete kinds of AST nodes
|
// Defines the concrete kinds of AST nodes
|
||||||
TAstNodeKind = (
|
TAstNodeKind = (
|
||||||
@@ -63,7 +64,8 @@ type
|
|||||||
akCreateSeries,
|
akCreateSeries,
|
||||||
akAddSeriesItem,
|
akAddSeriesItem,
|
||||||
akSeriesLength,
|
akSeriesLength,
|
||||||
akRecur
|
akRecur,
|
||||||
|
akNop // Added Nop
|
||||||
);
|
);
|
||||||
|
|
||||||
// --- Concrete Type Definitions ---
|
// --- Concrete Type Definitions ---
|
||||||
@@ -113,6 +115,7 @@ type
|
|||||||
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
|
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
|
||||||
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
||||||
function VisitRecurNode(const Node: IRecurNode): TDataValue;
|
function VisitRecurNode(const Node: IRecurNode): TDataValue;
|
||||||
|
function VisitNop(const Node: INopNode): TDataValue; // Added Nop
|
||||||
end;
|
end;
|
||||||
|
|
||||||
IAstNode = interface(IInterface)
|
IAstNode = interface(IInterface)
|
||||||
@@ -145,10 +148,16 @@ type
|
|||||||
function AsAddSeriesItem: IAddSeriesItemNode;
|
function AsAddSeriesItem: IAddSeriesItemNode;
|
||||||
function AsSeriesLength: ISeriesLengthNode;
|
function AsSeriesLength: ISeriesLengthNode;
|
||||||
function AsRecur: IRecurNode;
|
function AsRecur: IRecurNode;
|
||||||
|
function AsNop: INopNode; // Added Nop
|
||||||
|
|
||||||
property Kind: TAstNodeKind read GetKind;
|
property Kind: TAstNodeKind read GetKind;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
INopNode = interface(IAstNode)
|
||||||
|
// A placeholder node for the UI (e.g., drag target).
|
||||||
|
// This node is illegal during compilation.
|
||||||
|
end;
|
||||||
|
|
||||||
IConstantNode = interface(IAstNode)
|
IConstantNode = interface(IAstNode)
|
||||||
// Represents a constant value in the AST (Scalar, Text, or Void).
|
// Represents a constant value in the AST (Scalar, Text, or Void).
|
||||||
{$region 'private'}
|
{$region 'private'}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ uses
|
|||||||
|
|
||||||
var
|
var
|
||||||
// This BNF should always be kept up to date and valid. It is used to comunicate with LLMs.
|
// This BNF should always be kept up to date and valid. It is used to comunicate with LLMs.
|
||||||
|
// (Nop isn't part of the language syntax.)
|
||||||
|
|
||||||
BNF: String =
|
BNF: String =
|
||||||
'''
|
'''
|
||||||
@@ -221,6 +222,7 @@ type
|
|||||||
procedure VisitAddSeriesItem(const Node: IAddSeriesItemNode); override;
|
procedure VisitAddSeriesItem(const Node: IAddSeriesItemNode); override;
|
||||||
procedure VisitSeriesLength(const Node: ISeriesLengthNode); override;
|
procedure VisitSeriesLength(const Node: ISeriesLengthNode); override;
|
||||||
procedure VisitRecurNode(const Node: IRecurNode); override;
|
procedure VisitRecurNode(const Node: IRecurNode); override;
|
||||||
|
procedure VisitNop(const Node: INopNode); override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TLexer }
|
{ TLexer }
|
||||||
@@ -716,7 +718,24 @@ begin
|
|||||||
end;
|
end;
|
||||||
tkIdentifier:
|
tkIdentifier:
|
||||||
begin
|
begin
|
||||||
Result.Node := TAst.Identifier(FCurrentToken.Text);
|
// Check for the NOP token ('...')
|
||||||
|
if FCurrentToken.Text = '...' then
|
||||||
|
begin
|
||||||
|
// The token '...' represents the Nop node, a non-compilable placeholder used exclusively
|
||||||
|
// for visual representations (e.g., UI drag targets).
|
||||||
|
//
|
||||||
|
// We handle it as a special case of tkIdentifier instead of introducing a dedicated tkNop
|
||||||
|
// TokenKind because of its **unofficial and transient status**.
|
||||||
|
//
|
||||||
|
// This allows the Parser to immediately apply the syntactic policy: mapping this
|
||||||
|
// specific identifier string directly to the non-standard TAst.Nop node, ensuring
|
||||||
|
// it bypasses the regular identifier creation and maintains its "placeholder" identity.
|
||||||
|
Result.Node := TAst.Nop;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Result.Node := TAst.Identifier(FCurrentToken.Text);
|
||||||
|
end;
|
||||||
NextToken;
|
NextToken;
|
||||||
end;
|
end;
|
||||||
tkLeftParen: Result.Node := ParseList;
|
tkLeftParen: Result.Node := ParseList;
|
||||||
@@ -1068,6 +1087,13 @@ begin
|
|||||||
Append(')');
|
Append(')');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TPrettyPrintVisitor.VisitNop(const Node: INopNode);
|
||||||
|
begin
|
||||||
|
// A placeholder node, usually for UI.
|
||||||
|
//TODO Nop soll durch ein spezielles ...-Token repräsentiert werden. Analysiere, ob dies syntaktisch möglich ist. Wenn ja, soll der Parser "inoffiziell" in der Lage sein Nops zu lesen und zu erzeugen.
|
||||||
|
Append('...');
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TPrettyPrintVisitor.VisitSeriesLength(const Node: ISeriesLengthNode);
|
procedure TPrettyPrintVisitor.VisitSeriesLength(const Node: ISeriesLengthNode);
|
||||||
begin
|
begin
|
||||||
Append('(count ');
|
Append('(count ');
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ type
|
|||||||
function IAstVisitor.VisitAddSeriesItem = DoVisitAddSeriesItem;
|
function IAstVisitor.VisitAddSeriesItem = DoVisitAddSeriesItem;
|
||||||
function IAstVisitor.VisitSeriesLength = DoVisitSeriesLength;
|
function IAstVisitor.VisitSeriesLength = DoVisitSeriesLength;
|
||||||
function IAstVisitor.VisitRecurNode = DoVisitRecurNode;
|
function IAstVisitor.VisitRecurNode = DoVisitRecurNode;
|
||||||
|
function IAstVisitor.VisitNop = DoVisitNop; // Added Nop
|
||||||
|
|
||||||
// Private bridge method implementations
|
// Private bridge method implementations
|
||||||
function DoVisitConstant(const Node: IConstantNode): TDataValue;
|
function DoVisitConstant(const Node: IConstantNode): TDataValue;
|
||||||
@@ -63,6 +64,7 @@ type
|
|||||||
function DoVisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
|
function DoVisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
|
||||||
function DoVisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
function DoVisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
||||||
function DoVisitRecurNode(const Node: IRecurNode): TDataValue;
|
function DoVisitRecurNode(const Node: IRecurNode): TDataValue;
|
||||||
|
function DoVisitNop(const Node: INopNode): TDataValue; // Added Nop
|
||||||
|
|
||||||
protected
|
protected
|
||||||
// Visit a node.
|
// Visit a node.
|
||||||
@@ -92,6 +94,7 @@ type
|
|||||||
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): T; virtual; abstract;
|
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): T; virtual; abstract;
|
||||||
function VisitSeriesLength(const Node: ISeriesLengthNode): T; virtual; abstract;
|
function VisitSeriesLength(const Node: ISeriesLengthNode): T; virtual; abstract;
|
||||||
function VisitRecurNode(const Node: IRecurNode): T; virtual; abstract;
|
function VisitRecurNode(const Node: IRecurNode): T; virtual; abstract;
|
||||||
|
function VisitNop(const Node: INopNode): T; virtual; abstract; // Added Nop
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TAstTransformer = class abstract(TAstVisitor<IAstNode>)
|
TAstTransformer = class abstract(TAstVisitor<IAstNode>)
|
||||||
@@ -123,6 +126,7 @@ type
|
|||||||
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): IAstNode; override;
|
function VisitAddSeriesItem(const Node: IAddSeriesItemNode): IAstNode; override;
|
||||||
function VisitSeriesLength(const Node: ISeriesLengthNode): IAstNode; override;
|
function VisitSeriesLength(const Node: ISeriesLengthNode): IAstNode; override;
|
||||||
function VisitRecurNode(const Node: IRecurNode): IAstNode; override;
|
function VisitRecurNode(const Node: IRecurNode): IAstNode; override;
|
||||||
|
function VisitNop(const Node: INopNode): IAstNode; override; // Added Nop
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TAstVisitor = class abstract(TInterfacedObject, IAstVisitor)
|
TAstVisitor = class abstract(TInterfacedObject, IAstVisitor)
|
||||||
@@ -152,6 +156,7 @@ type
|
|||||||
function IAstVisitor.VisitAddSeriesItem = DoVisitAddSeriesItem;
|
function IAstVisitor.VisitAddSeriesItem = DoVisitAddSeriesItem;
|
||||||
function IAstVisitor.VisitSeriesLength = DoVisitSeriesLength;
|
function IAstVisitor.VisitSeriesLength = DoVisitSeriesLength;
|
||||||
function IAstVisitor.VisitRecurNode = DoVisitRecurNode;
|
function IAstVisitor.VisitRecurNode = DoVisitRecurNode;
|
||||||
|
function IAstVisitor.VisitNop = DoVisitNop; // Added Nop
|
||||||
|
|
||||||
// Private bridge method implementations
|
// Private bridge method implementations
|
||||||
function DoVisitConstant(const Node: IConstantNode): TDataValue;
|
function DoVisitConstant(const Node: IConstantNode): TDataValue;
|
||||||
@@ -178,6 +183,7 @@ type
|
|||||||
function DoVisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
|
function DoVisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
|
||||||
function DoVisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
function DoVisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
||||||
function DoVisitRecurNode(const Node: IRecurNode): TDataValue;
|
function DoVisitRecurNode(const Node: IRecurNode): TDataValue;
|
||||||
|
function DoVisitNop(const Node: INopNode): TDataValue; // Added Nop
|
||||||
|
|
||||||
protected
|
protected
|
||||||
// Virtual procedures for descendants (Interpreters/Side-effects) to override
|
// Virtual procedures for descendants (Interpreters/Side-effects) to override
|
||||||
@@ -205,6 +211,7 @@ type
|
|||||||
procedure VisitAddSeriesItem(const Node: IAddSeriesItemNode); virtual; abstract;
|
procedure VisitAddSeriesItem(const Node: IAddSeriesItemNode); virtual; abstract;
|
||||||
procedure VisitSeriesLength(const Node: ISeriesLengthNode); virtual; abstract;
|
procedure VisitSeriesLength(const Node: ISeriesLengthNode); virtual; abstract;
|
||||||
procedure VisitRecurNode(const Node: IRecurNode); virtual; abstract;
|
procedure VisitRecurNode(const Node: IRecurNode); virtual; abstract;
|
||||||
|
procedure VisitNop(const Node: INopNode); virtual; abstract; // Added Nop
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@@ -341,6 +348,12 @@ begin
|
|||||||
Result := TDataValue.FromGeneric<T>(VisitRecurNode(Node));
|
Result := TDataValue.FromGeneric<T>(VisitRecurNode(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TAstVisitor<T>.DoVisitNop(const Node: INopNode): TDataValue;
|
||||||
|
begin
|
||||||
|
// Added Nop implementation
|
||||||
|
Result := TDataValue.FromGeneric<T>(VisitNop(Node));
|
||||||
|
end;
|
||||||
|
|
||||||
function TAstTransformer.AcceptParameters(const Nodes: TArray<IIdentifierNode>): TArray<IIdentifierNode>;
|
function TAstTransformer.AcceptParameters(const Nodes: TArray<IIdentifierNode>): TArray<IIdentifierNode>;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
@@ -418,6 +431,12 @@ begin
|
|||||||
Result := Node; // Leaf node
|
Result := Node; // Leaf node
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TAstTransformer.VisitNop(const Node: INopNode): IAstNode;
|
||||||
|
begin
|
||||||
|
// Added Nop implementation
|
||||||
|
Result := Node; // Leaf node
|
||||||
|
end;
|
||||||
|
|
||||||
function TAstTransformer.VisitBinaryExpression(const Node: IBinaryExpressionNode): IAstNode;
|
function TAstTransformer.VisitBinaryExpression(const Node: IBinaryExpressionNode): IAstNode;
|
||||||
var
|
var
|
||||||
N: TBinaryExpressionNode;
|
N: TBinaryExpressionNode;
|
||||||
@@ -753,4 +772,10 @@ begin
|
|||||||
VisitRecurNode(Node);
|
VisitRecurNode(Node);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TAstVisitor.DoVisitNop(const Node: INopNode): TDataValue;
|
||||||
|
begin
|
||||||
|
// Added Nop implementation
|
||||||
|
VisitNop(Node);
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ type
|
|||||||
class procedure RegisterLibrary(const AProc: TRegisterLibraryProc); static;
|
class procedure RegisterLibrary(const AProc: TRegisterLibraryProc); static;
|
||||||
class function CreateScope(Parent: IExecutionScope; const Descriptor: IScopeDescriptor = nil): IExecutionScope; static;
|
class function CreateScope(Parent: IExecutionScope; const Descriptor: IScopeDescriptor = nil): IExecutionScope; static;
|
||||||
|
|
||||||
|
// A No-Operation node, used as a placeholder/stub (e.g., for UI drop targets).
|
||||||
|
// This node is illegal in the compiler (Binder/TypeChecker will reject it).
|
||||||
|
class function Nop: IAstNode; static;
|
||||||
|
|
||||||
// --- Factory functions ---
|
// --- Factory functions ---
|
||||||
class function Constant(const AValue: TDataValue): IConstantNode; overload; static;
|
class function Constant(const AValue: TDataValue): IConstantNode; overload; static;
|
||||||
class function Constant(const AValue: String): IConstantNode; overload; static;
|
class function Constant(const AValue: String): IConstantNode; overload; static;
|
||||||
@@ -103,6 +107,7 @@ type
|
|||||||
function AsAddSeriesItem: IAddSeriesItemNode; virtual;
|
function AsAddSeriesItem: IAddSeriesItemNode; virtual;
|
||||||
function AsSeriesLength: ISeriesLengthNode; virtual;
|
function AsSeriesLength: ISeriesLengthNode; virtual;
|
||||||
function AsRecur: IRecurNode; virtual;
|
function AsRecur: IRecurNode; virtual;
|
||||||
|
function AsNop: INopNode; virtual; // Added Nop
|
||||||
|
|
||||||
property StaticType: IStaticType read FStaticType write SetStaticType;
|
property StaticType: IStaticType read FStaticType write SetStaticType;
|
||||||
property Kind: TAstNodeKind read GetKind;
|
property Kind: TAstNodeKind read GetKind;
|
||||||
@@ -474,6 +479,17 @@ implementation
|
|||||||
uses
|
uses
|
||||||
System.Generics.Defaults;
|
System.Generics.Defaults;
|
||||||
|
|
||||||
|
// Added Nop
|
||||||
|
type
|
||||||
|
TNopNode = class(TAstNode, INopNode)
|
||||||
|
private
|
||||||
|
function GetKind: TAstNodeKind; override;
|
||||||
|
public
|
||||||
|
constructor Create;
|
||||||
|
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||||
|
function AsNop: INopNode; override;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TAst }
|
{ TAst }
|
||||||
|
|
||||||
class function TAst.CreateScope(Parent: IExecutionScope; const Descriptor: IScopeDescriptor): IExecutionScope;
|
class function TAst.CreateScope(Parent: IExecutionScope; const Descriptor: IScopeDescriptor): IExecutionScope;
|
||||||
@@ -603,6 +619,12 @@ begin
|
|||||||
Result := TMemberAccessNode.Create(ABase, AMember);
|
Result := TMemberAccessNode.Create(ABase, AMember);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
class function TAst.Nop: IAstNode;
|
||||||
|
begin
|
||||||
|
// Factory function for the new Nop node
|
||||||
|
Result := TNopNode.Create;
|
||||||
|
end;
|
||||||
|
|
||||||
class function TAst.Quasiquote(const AExpression: IAstNode): IQuasiquoteNode;
|
class function TAst.Quasiquote(const AExpression: IAstNode): IQuasiquoteNode;
|
||||||
begin
|
begin
|
||||||
Result := TQuasiquoteNode.Create(AExpression);
|
Result := TQuasiquoteNode.Create(AExpression);
|
||||||
@@ -650,6 +672,30 @@ begin
|
|||||||
Result := TVariableDeclarationNode.Create(AIdentifier, AInitializer);
|
Result := TVariableDeclarationNode.Create(AIdentifier, AInitializer);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TNopNode }
|
||||||
|
|
||||||
|
constructor TNopNode.Create;
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
// Nop nodes are 'Void' by default, though TypeChecker will reject them anyway.
|
||||||
|
StaticType := TTypes.Void;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TNopNode.Accept(const Visitor: IAstVisitor): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := Visitor.VisitNop(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TNopNode.AsNop: INopNode;
|
||||||
|
begin
|
||||||
|
Result := Self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TNopNode.GetKind: TAstNodeKind;
|
||||||
|
begin
|
||||||
|
Result := akNop;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TAstNode }
|
{ TAstNode }
|
||||||
|
|
||||||
constructor TAstNode.Create;
|
constructor TAstNode.Create;
|
||||||
@@ -733,6 +779,12 @@ begin
|
|||||||
raise ETypeException.Create('Node is not a MemberAccess');
|
raise ETypeException.Create('Node is not a MemberAccess');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TAstNode.AsNop: INopNode;
|
||||||
|
begin
|
||||||
|
// Added Nop implementation
|
||||||
|
raise ETypeException.Create('Node is not a Nop');
|
||||||
|
end;
|
||||||
|
|
||||||
function TAstNode.AsQuasiquote: IQuasiquoteNode;
|
function TAstNode.AsQuasiquote: IQuasiquoteNode;
|
||||||
begin
|
begin
|
||||||
raise ETypeException.Create('Node is not a Quasiquote');
|
raise ETypeException.Create('Node is not a Quasiquote');
|
||||||
|
|||||||
Reference in New Issue
Block a user