New visualizer

This commit is contained in:
Michael Schimmel
2025-10-30 13:26:50 +01:00
parent f1735e2678
commit b0d87fdc69
5 changed files with 104 additions and 75 deletions
+21 -1
View File
@@ -306,7 +306,27 @@ begin
smaScope := smaDescriptor.CreateScope(Scope);
smaVisitor := CreateEvaluator(smaScope);
Scope.Define('CreateSMA', smaVisitor.Execute(boundSmaAst));
Scope.Define(
'print',
TDataValue(
function(const Args: TArray<TDataValue>): TDataValue
begin
var str := TStringBuilder.Create;
try
for var i := 0 to High(Args) do
begin
if Args[i].Kind = vkText then
str.Append(Args[i].AsText)
else
str.Append(Args[i].ToString);
end;
Memo1.Lines.Add(str.ToString);
finally
str.Free;
end;
end
)
);
end
);
+73 -65
View File
@@ -149,7 +149,6 @@ type
// If true, the node is drawn without a border and with a transparent background.
FFrameless: Boolean;
FVisualizer: IAstVisualizer;
function AddLabel(const Txt: String): TLabel;
procedure SetBackgroundColor(const Value: TAlphaColor);
procedure SetBorderColor(const Value: TAlphaColor);
procedure SetBorderWidth(const Value: Single);
@@ -162,6 +161,11 @@ type
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Single); override;
property Visualizer: IAstVisualizer read FVisualizer;
procedure SetupNode; virtual;
function AddLabel(Parent: TControl; const Txt: String): TLabel;
function AddContainer(Parent: TControl; Orientation: TLayoutOrientation; Alignment: TLayoutAlignment): TAutoFitControl;
function AddExpr(Parent: TControl; const Title: String; const Node: IAstNode): TAuraNode;
public
constructor Create(const AVisualizer: IAstVisualizer); reintroduce;
destructor Destroy; override;
@@ -450,7 +454,6 @@ type
private
FNode: IMemberAccessNode;
FBaseNode: TAuraNode;
// FMemberNode is handled by a label, store Base only
protected
procedure SetupNode; override;
public
@@ -930,10 +933,29 @@ begin
inherited;
end;
function TAuraNode.AddLabel(const Txt: String): TLabel;
function TAuraNode.AddContainer(Parent: TControl; Orientation: TLayoutOrientation; Alignment: TLayoutAlignment): TAutoFitControl;
begin
Result := TAutoFitControl.Create(Self);
Result.Parent := Parent;
Result.Orientation := Orientation;
Result.Alignment := Alignment;
Result.HitTest := False; // Pass clicks to parent
end;
function TAuraNode.AddExpr(Parent: TControl; const Title: String; const Node: IAstNode): TAuraNode;
begin
var cont := AddContainer(Parent, loHorizontal, laCenter);
var lbl := AddLabel(cont, Title);
lbl.Font.Style := lbl.Font.Style + [TFontStyle.fsBold];
Result := FVisualizer.Clone(cont, FVisualizer.ExprDepth + 1).CallAccept(Node);
end;
function TAuraNode.AddLabel(Parent: TControl; const Txt: String): TLabel;
begin
Result := TLabel.Create(Self); // Owner is the node itself
Result.Parent := Self;
Result.Parent := Parent;
Result.Position.Point := TPoint.Create(cNodePadding, cNodePadding);
Result.Margins.Left := cNodePadding;
@@ -1134,7 +1156,7 @@ begin
begin
// Display value directly in a centered label, frameless node
Frameless := true;
AddLabel(valueStr);
AddLabel(Self, valueStr);
end
else
begin
@@ -1142,11 +1164,11 @@ begin
Frameless := False;
Orientation := loVertical;
var titleLabel := AddLabel('Const');
var titleLabel := AddLabel(Self, 'Const');
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
// Value Label
var valueLabel := AddLabel(valueStr);
var valueLabel := AddLabel(Self, valueStr);
valueLabel.AutoSize := False; // ***Important: Disable AutoSize when Align=Client***
valueLabel.WordWrap := True; // Allow wrapping for long text
end;
@@ -1173,7 +1195,7 @@ begin
BeginUpdate;
try
Frameless := true; // Identifiers are frameless
AddLabel(FNode.Name); // Add label with the identifier name
AddLabel(Self, FNode.Name); // Add label with the identifier name
finally
EndUpdate;
end;
@@ -1214,7 +1236,7 @@ begin
visu.CallAccept(FNode.Left);
// 2. Operator Label
AddLabel(FNode.Operator.ToString);
AddLabel(Self, FNode.Operator.ToString);
// 3. RightNode Expression Node (Visited Recursively)
visu.CallAccept(FNode.Right);
@@ -1282,15 +1304,10 @@ begin
if i = High(FNode.Expressions) then
begin
// Last expression: create a horizontal container for "return [expr]"
returnContainer := TAutoFitControl.Create(Self);
returnContainer.Parent := Self; // Parent is the main block node
returnContainer.Orientation := loHorizontal;
returnContainer.Alignment := laCenter; // Center "return" label vertically next to the expression
returnContainer.HitTest := False; // Pass clicks through
returnContainer := AddContainer(Self, loHorizontal, laCenter);
// Add "return" label to the container
titleLabel := AddLabel('return'); // Use AddLabel from TAuraNode (Self)
titleLabel.Parent := returnContainer; // Set parent to the new container
titleLabel := AddLabel(returnContainer, 'return'); // Use AddLabel from TAuraNode (Self)
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
// Create a new visualizer targeting this container
@@ -1339,7 +1356,7 @@ begin
Orientation := loVertical;
// Title
titleLabel := AddLabel('Unary Op: ' + FNode.Operator.ToString);
titleLabel := AddLabel(Self, 'Unary Op: ' + FNode.Operator.ToString);
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
// Child
@@ -1373,24 +1390,18 @@ end;
procedure TAuraIfExpressionNode.SetupNode;
var
visu: IAstVisualizer;
titleLabel: TLabel;
lbl: TLabel;
begin
visu := FVisualizer.Clone(Self, FVisualizer.ExprDepth + 1);
BeginUpdate;
try
Frameless := False;
Orientation := loVertical;
Alignment := laFlush;
titleLabel := AddLabel('if');
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
// Add children
FConditionNode := visu.CallAccept(FNode.Condition);
FThenNode := visu.CallAccept(FNode.ThenBranch);
FConditionNode := AddExpr(Self, 'if', FNode.Condition);
FThenNode := AddExpr(Self, 'then', FNode.ThenBranch);
if Assigned(FNode.ElseBranch) then
FElseNode := visu.CallAccept(FNode.ElseBranch);
FElseNode := AddExpr(Self, 'else', FNode.ElseBranch);
finally
EndUpdate;
end;
@@ -1421,9 +1432,9 @@ begin
Orientation := loHorizontal;
FConditionNode := visu.CallAccept(FNode.Condition);
AddLabel('?');
AddLabel(Self, '?');
FThenNode := visu.CallAccept(FNode.ThenBranch);
AddLabel(':');
AddLabel(Self, ':');
FElseNode := visu.CallAccept(FNode.ElseBranch);
finally
EndUpdate;
@@ -1475,36 +1486,33 @@ begin
BackgroundColor := $090000ff;
// Create a horizontal container for the title/params
titleContainer := TAutoFitControl.Create(Self);
titleContainer.Parent := Self;
titleContainer.Orientation := loHorizontal;
titleContainer.HitTest := False; // Pass clicks to parent
titleContainer := AddContainer(Self, loHorizontal, laCenter);
// 1. Lambda Symbol Label (Title)
paramLabel := AddLabel(WideChar($03BB)); // Lambda
paramLabel := AddLabel(Self, WideChar($03BB)); // Lambda
paramLabel.Parent := titleContainer; // Add to title container
paramLabel.Font.Style := paramLabel.Font.Style + [TFontStyle.fsBold];
// 2. Add Parameters
paramLabel := AddLabel('(');
paramLabel := AddLabel(Self, '(');
paramLabel.Parent := titleContainer;
FParamLabels.Add(paramLabel);
for i := 0 to High(FNode.Parameters) do
begin
paramLabel := AddLabel(FNode.Parameters[i].Name);
paramLabel := AddLabel(Self, FNode.Parameters[i].Name);
paramLabel.Parent := titleContainer;
FParamLabels.Add(paramLabel);
if i < High(FNode.Parameters) then
begin
paramLabel := AddLabel(',');
paramLabel := AddLabel(Self, ',');
paramLabel.Parent := titleContainer;
FParamLabels.Add(paramLabel);
end;
end;
paramLabel := AddLabel(')');
paramLabel := AddLabel(Self, ')');
paramLabel.Parent := titleContainer;
FParamLabels.Add(paramLabel);
@@ -1557,7 +1565,7 @@ begin
Frameless := True; // Horizontal layout
Orientation := loHorizontal;
var callLabel := AddLabel('call ');
var callLabel := AddLabel(Self, 'call ');
callLabel.Font.Style := callLabel.Font.Style + [TFontStyle.fsBold];
// Callee
@@ -1566,7 +1574,7 @@ begin
// Arguments
if Length(FNode.Arguments) > 0 then
begin
AddLabel('(');
AddLabel(Self, '(');
for i := 0 to High(FNode.Arguments) do
begin
@@ -1574,10 +1582,10 @@ begin
FArgumentNodes.Add(argNode);
if i < High(FNode.Arguments) then
AddLabel(',');
AddLabel(Self, ',');
end;
AddLabel(')');
AddLabel(Self, ')');
end;
finally
EndUpdate;
@@ -1611,7 +1619,7 @@ begin
Frameless := False;
Orientation := loVertical;
titleLabel := AddLabel('Macro Expansion');
titleLabel := AddLabel(Self, 'Macro Expansion');
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
FExpandedBodyNode := visu.CallAccept(FNode.ExpandedBody);
@@ -1662,11 +1670,11 @@ begin
Orientation := loHorizontal;
// 1. 'recur' keyword
titleLabel := AddLabel(WideChar($03BB));
titleLabel := AddLabel(Self, WideChar($03BB));
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
// 2. Arguments
AddLabel('(');
AddLabel(Self, '(');
for i := 0 to High(FNode.Arguments) do
begin
@@ -1674,10 +1682,10 @@ begin
FArgumentNodes.Add(argNode);
if i < High(FNode.Arguments) then
AddLabel(',');
AddLabel(Self, ',');
end;
AddLabel(')');
AddLabel(Self, ')');
finally
EndUpdate;
end;
@@ -1717,15 +1725,15 @@ begin
Frameless := True; // Horizontal layout
Orientation := loHorizontal;
varLabel := AddLabel('var');
varLabel := AddLabel(Self, 'var');
varLabel.Font.Style := varLabel.Font.Style + [TFontStyle.fsBold];
// Add identifier name as a label
AddLabel(FNode.Identifier.Name);
AddLabel(Self, FNode.Identifier.Name);
if Assigned(FNode.Initializer) then
begin
AddLabel(':=');
AddLabel(Self, ':=');
FInitializerNode := visu.CallAccept(FNode.Initializer);
end;
finally
@@ -1759,9 +1767,9 @@ begin
Orientation := loHorizontal;
// Add identifier name as a label
AddLabel(FNode.Identifier.Name);
AddLabel(Self, FNode.Identifier.Name);
AddLabel(':=');
AddLabel(Self, ':=');
FValueNode := visu.CallAccept(FNode.Value);
finally
@@ -1811,7 +1819,7 @@ begin
paramStr := paramStr + FNode.Parameters[i].Name;
end;
titleLabel := AddLabel('Macro Def: ' + FNode.Name.Name + ' (' + paramStr + ')');
titleLabel := AddLabel(Self, 'Macro Def: ' + FNode.Name.Name + ' (' + paramStr + ')');
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
FBodyNode := visu.CallAccept(FNode.Body);
@@ -1843,7 +1851,7 @@ begin
try
Frameless := False;
Orientation := loVertical;
titleLabel := AddLabel('Quasiquote');
titleLabel := AddLabel(Self, 'Quasiquote');
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
FExpressionNode := visu.CallAccept(FNode.Expression);
finally
@@ -1874,13 +1882,13 @@ begin
Frameless := True; // Horizontal layout
Orientation := loHorizontal;
var leftBracket := AddLabel('<');
var leftBracket := AddLabel(Self, '<');
leftBracket.Padding.Right := 0;
leftBracket.Margins.Right := 0;
visu.CallAccept(FNode.Expression);
var rightBracket := AddLabel('>');
var rightBracket := AddLabel(Self, '>');
rightBracket.Padding.Left := 0;
rightBracket.Margins.Left := 0;
finally
@@ -1911,7 +1919,7 @@ begin
try
Frameless := False;
Orientation := loVertical;
titleLabel := AddLabel('Unquote-Splicing');
titleLabel := AddLabel(Self, 'Unquote-Splicing');
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
FExpressionNode := visu.CallAccept(FNode.Expression);
finally
@@ -1943,9 +1951,9 @@ begin
Orientation := loHorizontal;
FBaseNode := visu.CallAccept(FNode.Base);
AddLabel('[');
AddLabel(Self, '[');
FIndexNode := visu.CallAccept(FNode.Index);
AddLabel(']');
AddLabel(Self, ']');
finally
EndUpdate;
end;
@@ -1976,10 +1984,10 @@ begin
Orientation := loHorizontal;
FBaseNode := visu.CallAccept(FNode.Base);
AddLabel('.');
AddLabel(Self, '.');
// Add member name as a label
AddLabel(FNode.Member.Name);
AddLabel(Self, FNode.Member.Name);
finally
EndUpdate;
end;
@@ -2006,7 +2014,7 @@ begin
try
Frameless := False; // Leaf node, but framed
Orientation := loVertical;
titleLabel := AddLabel('Create Series: ' + FNode.Definition);
titleLabel := AddLabel(Self, 'Create Series: ' + FNode.Definition);
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
finally
EndUpdate;
@@ -2045,7 +2053,7 @@ begin
Frameless := False;
Orientation := loVertical;
titleLabel := AddLabel('Add Item to: ' + FNode.Series.Name);
titleLabel := AddLabel(Self, 'Add Item to: ' + FNode.Series.Name);
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
FValueNode := visu.CallAccept(FNode.Value);
@@ -2077,7 +2085,7 @@ begin
try
Frameless := False; // Leaf node, but framed
Orientation := loVertical;
titleLabel := AddLabel('Length of: ' + FNode.Series.Name);
titleLabel := AddLabel(Self, 'Length of: ' + FNode.Series.Name);
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
finally
EndUpdate;