AST Identities
This commit is contained in:
@@ -21,6 +21,7 @@ uses
|
||||
Myc.Data.Keyword,
|
||||
Myc.Ast.Nodes,
|
||||
Myc.Ast.Visitor,
|
||||
Myc.Ast.Identities, // NEU: Für Casts
|
||||
Myc.Ast,
|
||||
Myc.Fmx.AstEditor.Workspace;
|
||||
|
||||
@@ -597,7 +598,6 @@ begin
|
||||
end;
|
||||
|
||||
// --- Visitor Implementations ---
|
||||
// *** CHANGED: All visitor methods now create a Handler and inject it into a generic TAuraNode ***
|
||||
|
||||
function TAstVisualizer.VisitConstant(const Node: IConstantNode): TAuraNode;
|
||||
var
|
||||
@@ -1298,7 +1298,8 @@ end;
|
||||
|
||||
function TConstantNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
|
||||
begin
|
||||
Result := FNode; // Literals are immutable
|
||||
// Reuse Identity: FNode.Identity.AsConstant
|
||||
Result := TAst.Constant(FNode.Identity.AsConstant, FNode.StaticType);
|
||||
end;
|
||||
|
||||
{ TIdentifierNodeHandler }
|
||||
@@ -1327,9 +1328,8 @@ end;
|
||||
|
||||
function TIdentifierNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
|
||||
begin
|
||||
// Find the label text if needed, but for now, re-use FNode's data
|
||||
// In a real editor, you'd fetch text from the TEdit/TLabel
|
||||
Result := TAst.Identifier(FNode.Name);
|
||||
// Reusing identity guarantees the same name and source location
|
||||
Result := TAst.Identifier(FNode.Identity.AsNamed, FNode.Address, FNode.StaticType);
|
||||
end;
|
||||
|
||||
{ TKeywordNodeHandler }
|
||||
@@ -1360,7 +1360,7 @@ end;
|
||||
|
||||
function TKeywordNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
|
||||
begin
|
||||
Result := FNode; // Keywords are literals
|
||||
Result := TAst.Keyword(FNode.Identity.AsKeyword);
|
||||
end;
|
||||
|
||||
{ TBlockExpressionNodeHandler }
|
||||
@@ -1439,7 +1439,9 @@ begin
|
||||
else
|
||||
exprs[i] := TAst.Nop; // Use Nop as placeholder
|
||||
end;
|
||||
Result := TAst.Block(exprs);
|
||||
|
||||
// Reuse structural identity
|
||||
Result := TAst.Block(FNode.Identity, exprs, FNode.StaticType);
|
||||
end;
|
||||
|
||||
{ TIfExpressionNodeHandler }
|
||||
@@ -1482,7 +1484,7 @@ begin
|
||||
else
|
||||
elseAst := nil;
|
||||
|
||||
Result := TAst.IfExpr(FConditionNode.CreateAst, FThenNode.CreateAst, elseAst);
|
||||
Result := TAst.IfExpr(FNode.Identity, FConditionNode.CreateAst, FThenNode.CreateAst, elseAst, FNode.StaticType);
|
||||
end;
|
||||
|
||||
{ TTernaryExpressionNodeHandler }
|
||||
@@ -1519,7 +1521,7 @@ end;
|
||||
|
||||
function TTernaryExpressionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
|
||||
begin
|
||||
Result := TAst.TernaryExpr(FConditionNode.CreateAst, FThenNode.CreateAst, FElseNode.CreateAst);
|
||||
Result := TAst.TernaryExpr(FNode.Identity, FConditionNode.CreateAst, FThenNode.CreateAst, FElseNode.CreateAst, FNode.StaticType);
|
||||
end;
|
||||
|
||||
{ TLambdaExpressionNodeHandler }
|
||||
@@ -1592,7 +1594,19 @@ end;
|
||||
function TLambdaExpressionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
|
||||
begin
|
||||
// Params are read from FNode (assuming they are not editable via UI labels for now)
|
||||
Result := TAst.LambdaExpr(FNode.Parameters, FBodyNode.CreateAst);
|
||||
// Reuse Identity & Metadata
|
||||
Result :=
|
||||
TAst.LambdaExpr(
|
||||
FNode.Identity,
|
||||
FNode.Parameters,
|
||||
FBodyNode.CreateAst,
|
||||
FNode.Layout,
|
||||
FNode.Descriptor,
|
||||
FNode.Upvalues,
|
||||
FNode.HasNestedLambdas,
|
||||
FNode.IsPure,
|
||||
FNode.StaticType
|
||||
);
|
||||
end;
|
||||
|
||||
{ TFunctionCallNodeHandler }
|
||||
@@ -1658,7 +1672,16 @@ begin
|
||||
for i := 0 to FArgumentNodes.Count - 1 do
|
||||
args[i] := FArgumentNodes[i].CreateAst;
|
||||
|
||||
Result := TAst.FunctionCall(FCalleeNode.CreateAst, args);
|
||||
Result :=
|
||||
TAst.FunctionCall(
|
||||
FNode.Identity,
|
||||
FCalleeNode.CreateAst,
|
||||
args,
|
||||
FNode.StaticType,
|
||||
FNode.IsTailCall,
|
||||
FNode.StaticTarget,
|
||||
FNode.IsTargetPure
|
||||
);
|
||||
end;
|
||||
|
||||
{ TMacroExpansionNodeHandler }
|
||||
@@ -1694,7 +1717,12 @@ end;
|
||||
|
||||
function TMacroExpansionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
|
||||
begin
|
||||
Result := TAst.MacroExpansionNode(FNode.CallNode, FExpandedBodyNode.CreateAst.AsTypedNode);
|
||||
Result :=
|
||||
TAst.MacroExpansionNode(
|
||||
FNode.Identity,
|
||||
FNode.CallNode,
|
||||
FExpandedBodyNode.CreateAst.AsTypedNode // TODO: Check if AsTypedNode is correct/safe
|
||||
);
|
||||
end;
|
||||
|
||||
{ TRecurNodeHandler }
|
||||
@@ -1755,7 +1783,7 @@ begin
|
||||
SetLength(args, FArgumentNodes.Count);
|
||||
for i := 0 to FArgumentNodes.Count - 1 do
|
||||
args[i] := FArgumentNodes[i].CreateAst;
|
||||
Result := TAst.Recur(args);
|
||||
Result := TAst.Recur(FNode.Identity, args, FNode.StaticType);
|
||||
end;
|
||||
|
||||
{ TVariableDeclarationNodeHandler }
|
||||
@@ -1806,7 +1834,7 @@ begin
|
||||
initAst := FInitializerNode.CreateAst
|
||||
else
|
||||
initAst := nil;
|
||||
Result := TAst.VarDecl(FTargetNode.CreateAst, initAst);
|
||||
Result := TAst.VarDecl(FNode.Identity, FTargetNode.CreateAst, initAst, FNode.StaticType, FNode.IsBoxed);
|
||||
end;
|
||||
|
||||
{ TAssignmentNodeHandler }
|
||||
@@ -1841,7 +1869,7 @@ end;
|
||||
|
||||
function TAssignmentNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
|
||||
begin
|
||||
Result := TAst.Assign(FTargetNode.CreateAst, FValueNode.CreateAst);
|
||||
Result := TAst.Assign(FNode.Identity, FTargetNode.CreateAst, FValueNode.CreateAst, FNode.StaticType);
|
||||
end;
|
||||
|
||||
{ TMacroDefinitionNodeHandler }
|
||||
@@ -1889,7 +1917,16 @@ end;
|
||||
|
||||
function TMacroDefinitionNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
|
||||
begin
|
||||
Result := TAst.MacroDef(TAst.Identifier(FNode.Name.Name), FNode.Parameters, FBodyNode.CreateAst);
|
||||
// Note: Identifier is recreated from raw name here, losing Location if we don't be careful.
|
||||
// Ideally FNode.Name would be reused.
|
||||
// For now, we reconstruct the MacroDef using the original identity and parameters.
|
||||
Result :=
|
||||
TAst.MacroDef(
|
||||
FNode.Identity,
|
||||
FNode.Name, // Reuse Identifier Node
|
||||
FNode.Parameters, // Reuse Parameters
|
||||
FBodyNode.CreateAst
|
||||
);
|
||||
end;
|
||||
|
||||
{ TQuasiquoteNodeHandler }
|
||||
@@ -1925,7 +1962,7 @@ end;
|
||||
|
||||
function TQuasiquoteNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
|
||||
begin
|
||||
Result := TAst.Quasiquote(FExpressionNode.CreateAst);
|
||||
Result := TAst.Quasiquote(FNode.Identity, FExpressionNode.CreateAst);
|
||||
end;
|
||||
|
||||
{ TUnquoteNodeHandler }
|
||||
@@ -1967,7 +2004,7 @@ end;
|
||||
|
||||
function TUnquoteNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
|
||||
begin
|
||||
Result := TAst.Unquote(FExpressionNode.CreateAst);
|
||||
Result := TAst.Unquote(FNode.Identity, FExpressionNode.CreateAst);
|
||||
end;
|
||||
|
||||
{ TUnquoteSplicingNodeHandler }
|
||||
@@ -1995,6 +2032,7 @@ begin
|
||||
OwnerNode.Orientation := loVertical;
|
||||
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Unquote-Splicing');
|
||||
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
|
||||
// Note: FNode.Expression is a IQuasiquoteNode
|
||||
FExpressionNode := visu.CallAccept(FNode.Expression);
|
||||
finally
|
||||
OwnerNode.EndUpdate;
|
||||
@@ -2003,7 +2041,9 @@ end;
|
||||
|
||||
function TUnquoteSplicingNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
|
||||
begin
|
||||
Result := TAst.UnquoteSplicing(FExpressionNode.CreateAst.AsQuasiquote);
|
||||
// Note: We assume the child node is still a QuasiquoteNode. If user changed it to something else,
|
||||
// this cast might fail or we need validation logic.
|
||||
Result := TAst.UnquoteSplicing(FNode.Identity, FExpressionNode.CreateAst.AsQuasiquote);
|
||||
end;
|
||||
|
||||
{ TIndexerNodeHandler }
|
||||
@@ -2039,7 +2079,7 @@ end;
|
||||
|
||||
function TIndexerNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
|
||||
begin
|
||||
Result := TAst.Indexer(FBaseNode.CreateAst, FIndexNode.CreateAst);
|
||||
Result := TAst.Indexer(FNode.Identity, FBaseNode.CreateAst, FIndexNode.CreateAst, FNode.StaticType);
|
||||
end;
|
||||
|
||||
{ TMemberAccessNodeHandler }
|
||||
@@ -2074,7 +2114,8 @@ end;
|
||||
|
||||
function TMemberAccessNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
|
||||
begin
|
||||
Result := TAst.MemberAccess(FBaseNode.CreateAst, TAst.Keyword(FNode.Member.Value.Name));
|
||||
// Reuse Identifier, Reuse Member Keyword (via TAst.Keyword with Identity)
|
||||
Result := TAst.MemberAccess(FNode.Identity, FBaseNode.CreateAst, TAst.Keyword(FNode.Member.Identity.AsKeyword), FNode.StaticType);
|
||||
end;
|
||||
|
||||
{ TRecordLiteralNodeHandler }
|
||||
@@ -2145,10 +2186,12 @@ begin
|
||||
for pair in FFieldNodes do
|
||||
begin
|
||||
valueNode := pair.Value;
|
||||
// Note: We construct a new keyword node here for the key, losing location unless we stored it.
|
||||
// For simplicity, we use Creation Path for the Key, but Reuse Identity for the RecordLiteral itself.
|
||||
fields[i] := TRecordFieldLiteral.Create(TAst.Keyword(pair.Key.Name), valueNode.CreateAst);
|
||||
inc(i);
|
||||
end;
|
||||
Result := TAst.RecordLiteral(fields);
|
||||
Result := TAst.RecordLiteral(FNode.Identity, fields, FNode.ScalarDefinition, FNode.GenericDefinition, FNode.StaticType);
|
||||
end;
|
||||
|
||||
{ TCreateSeriesNodeHandler }
|
||||
@@ -2181,7 +2224,8 @@ end;
|
||||
|
||||
function TCreateSeriesNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
|
||||
begin
|
||||
Result := TAst.CreateSeries(FNode.Definition);
|
||||
// Identity.AsDefinition check needed? Or trust CreateSeries overload
|
||||
Result := TAst.CreateSeries(FNode.Identity.AsDefinition, FNode.StaticType);
|
||||
end;
|
||||
|
||||
{ TAddSeriesItemNodeHandler }
|
||||
@@ -2229,7 +2273,21 @@ begin
|
||||
else
|
||||
lookbackAst := nil;
|
||||
|
||||
Result := TAst.AddSeriesItem(TAst.Identifier(FNode.Series.Name), FValueNode.CreateAst, lookbackAst);
|
||||
// Reusing identifier identity requires access to it.
|
||||
// Here we create a new identifier with same name but lose location of series ident.
|
||||
// Optimization: FNode.Series is available, we can reuse it!
|
||||
|
||||
// Wait, TAst.AddSeriesItem takes IIdentifierNode. We can just reuse FNode.Series?
|
||||
// Yes, if the series name is not editable in UI.
|
||||
|
||||
Result :=
|
||||
TAst.AddSeriesItem(
|
||||
FNode.Identity,
|
||||
FNode.Series, // Reuse original Series Identifier Node
|
||||
FValueNode.CreateAst,
|
||||
lookbackAst,
|
||||
FNode.StaticType
|
||||
);
|
||||
end;
|
||||
|
||||
{ TSeriesLengthNodeHandler }
|
||||
@@ -2262,7 +2320,7 @@ end;
|
||||
|
||||
function TSeriesLengthNodeHandler.ReconstructAst(OwnerNode: TAuraNode): IAstNode;
|
||||
begin
|
||||
Result := TAst.SeriesLength(TAst.Identifier(FNode.Series.Name));
|
||||
Result := TAst.SeriesLength(FNode.Identity, FNode.Series, FNode.StaticType);
|
||||
end;
|
||||
|
||||
{ TNopNodeHandler }
|
||||
|
||||
Reference in New Issue
Block a user