Ast list nodes
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -148,7 +148,8 @@
|
|||||||
},
|
},
|
||||||
"ElseBranch": {
|
"ElseBranch": {
|
||||||
"NodeType": "Block",
|
"NodeType": "Block",
|
||||||
"Expressions": []
|
"Expressions": [
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1095,5 +1096,65 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"test2": {
|
||||||
|
"NodeType": "MacroDef",
|
||||||
|
"Name": {
|
||||||
|
"NodeType": "Identifier",
|
||||||
|
"Name": "test2"
|
||||||
|
},
|
||||||
|
"Parameters": [
|
||||||
|
{
|
||||||
|
"NodeType": "Identifier",
|
||||||
|
"Name": "body"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Body": {
|
||||||
|
"NodeType": "Quasiquote",
|
||||||
|
"Expression": {
|
||||||
|
"NodeType": "LambdaExpr",
|
||||||
|
"Parameters": [
|
||||||
|
],
|
||||||
|
"Body": {
|
||||||
|
"NodeType": "Unquote",
|
||||||
|
"Expression": {
|
||||||
|
"NodeType": "Identifier",
|
||||||
|
"Name": "body"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"debug-mode": {
|
||||||
|
"NodeType": "Keyword",
|
||||||
|
"Name": "true"
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"NodeType": "MacroDef",
|
||||||
|
"Name": {
|
||||||
|
"NodeType": "Identifier",
|
||||||
|
"Name": "test"
|
||||||
|
},
|
||||||
|
"Parameters": [
|
||||||
|
{
|
||||||
|
"NodeType": "Identifier",
|
||||||
|
"Name": "body"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Body": {
|
||||||
|
"NodeType": "Quasiquote",
|
||||||
|
"Expression": {
|
||||||
|
"NodeType": "LambdaExpr",
|
||||||
|
"Parameters": [
|
||||||
|
],
|
||||||
|
"Body": {
|
||||||
|
"NodeType": "Unquote",
|
||||||
|
"Expression": {
|
||||||
|
"NodeType": "Identifier",
|
||||||
|
"Name": "body"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -29,6 +29,13 @@ type
|
|||||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): Boolean; override;
|
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): Boolean; override;
|
||||||
function VisitSeriesLength(const Node: ISeriesLengthNode): Boolean; override;
|
function VisitSeriesLength(const Node: ISeriesLengthNode): Boolean; override;
|
||||||
|
|
||||||
|
// --- List Visitors (New) ---
|
||||||
|
function VisitParameterList(const Node: IParameterList): Boolean; override;
|
||||||
|
function VisitArgumentList(const Node: IArgumentList): Boolean; override;
|
||||||
|
function VisitExpressionList(const Node: IExpressionList): Boolean; override;
|
||||||
|
function VisitRecordFieldList(const Node: IRecordFieldList): Boolean; override;
|
||||||
|
function VisitRecordField(const Node: IRecordFieldNode): Boolean; override;
|
||||||
|
|
||||||
// --- Critical Checks ---
|
// --- Critical Checks ---
|
||||||
function VisitIdentifier(const Node: IIdentifierNode): Boolean; override;
|
function VisitIdentifier(const Node: IIdentifierNode): Boolean; override;
|
||||||
function VisitFunctionCall(const Node: IFunctionCallNode): Boolean; override;
|
function VisitFunctionCall(const Node: IFunctionCallNode): Boolean; override;
|
||||||
@@ -81,6 +88,44 @@ begin
|
|||||||
Result := Node.Accept(Self).AsGeneric<Boolean>;
|
Result := Node.Accept(Self).AsGeneric<Boolean>;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// --- List Visitors ---
|
||||||
|
|
||||||
|
function TPurityAnalyzer.VisitParameterList(const Node: IParameterList): Boolean;
|
||||||
|
begin
|
||||||
|
// Declarations are pure
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPurityAnalyzer.VisitArgumentList(const Node: IArgumentList): Boolean;
|
||||||
|
begin
|
||||||
|
for var item in Node do
|
||||||
|
if not Accept(item) then
|
||||||
|
exit(False);
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPurityAnalyzer.VisitExpressionList(const Node: IExpressionList): Boolean;
|
||||||
|
begin
|
||||||
|
for var item in Node do
|
||||||
|
if not Accept(item) then
|
||||||
|
exit(False);
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPurityAnalyzer.VisitRecordFieldList(const Node: IRecordFieldList): Boolean;
|
||||||
|
begin
|
||||||
|
for var item in Node do
|
||||||
|
if not Accept(item) then
|
||||||
|
exit(False);
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPurityAnalyzer.VisitRecordField(const Node: IRecordFieldNode): Boolean;
|
||||||
|
begin
|
||||||
|
// Key is usually pure (Keyword), check Value
|
||||||
|
Result := Accept(Node.Key) and Accept(Node.Value);
|
||||||
|
end;
|
||||||
|
|
||||||
// --- Safe Leaves ---
|
// --- Safe Leaves ---
|
||||||
|
|
||||||
function TPurityAnalyzer.VisitConstant(const Node: IConstantNode): Boolean;
|
function TPurityAnalyzer.VisitConstant(const Node: IConstantNode): Boolean;
|
||||||
@@ -120,11 +165,8 @@ begin
|
|||||||
exit(False);
|
exit(False);
|
||||||
|
|
||||||
// 2. All arguments must be pure expressions.
|
// 2. All arguments must be pure expressions.
|
||||||
for var arg in Node.Arguments do
|
// Delegate to ArgumentList visitor
|
||||||
if not Accept(arg) then
|
Result := Accept(Node.Arguments);
|
||||||
exit(False);
|
|
||||||
|
|
||||||
Result := True;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- Recursion ---
|
// --- Recursion ---
|
||||||
@@ -132,10 +174,7 @@ end;
|
|||||||
function TPurityAnalyzer.VisitRecurNode(const Node: IRecurNode): Boolean;
|
function TPurityAnalyzer.VisitRecurNode(const Node: IRecurNode): Boolean;
|
||||||
begin
|
begin
|
||||||
// 'recur' is just control flow. It is pure if its arguments are pure.
|
// 'recur' is just control flow. It is pure if its arguments are pure.
|
||||||
for var arg in Node.Arguments do
|
Result := Accept(Node.Arguments);
|
||||||
if not Accept(arg) then
|
|
||||||
exit(False);
|
|
||||||
Result := True;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- Structures: Recursive Checks ---
|
// --- Structures: Recursive Checks ---
|
||||||
@@ -152,10 +191,8 @@ end;
|
|||||||
|
|
||||||
function TPurityAnalyzer.VisitBlockExpression(const Node: IBlockExpressionNode): Boolean;
|
function TPurityAnalyzer.VisitBlockExpression(const Node: IBlockExpressionNode): Boolean;
|
||||||
begin
|
begin
|
||||||
for var expr in Node.Expressions do
|
// Delegate to ExpressionList
|
||||||
if not Accept(expr) then
|
Result := Accept(Node.Expressions);
|
||||||
exit(False);
|
|
||||||
Result := True;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPurityAnalyzer.VisitVariableDeclaration(const Node: IVariableDeclarationNode): Boolean;
|
function TPurityAnalyzer.VisitVariableDeclaration(const Node: IVariableDeclarationNode): Boolean;
|
||||||
@@ -167,10 +204,8 @@ end;
|
|||||||
|
|
||||||
function TPurityAnalyzer.VisitRecordLiteral(const Node: IRecordLiteralNode): Boolean;
|
function TPurityAnalyzer.VisitRecordLiteral(const Node: IRecordLiteralNode): Boolean;
|
||||||
begin
|
begin
|
||||||
for var field in Node.Fields do
|
// Delegate to RecordFieldList
|
||||||
if not Accept(field.Value) then
|
Result := Accept(Node.Fields);
|
||||||
exit(False);
|
|
||||||
Result := True;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPurityAnalyzer.VisitIndexer(const Node: IIndexerNode): Boolean;
|
function TPurityAnalyzer.VisitIndexer(const Node: IIndexerNode): Boolean;
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ begin
|
|||||||
// 2. Register parameters (they mask outer variables)
|
// 2. Register parameters (they mask outer variables)
|
||||||
// We pass 'nil' as the node because we currently don't box parameters,
|
// We pass 'nil' as the node because we currently don't box parameters,
|
||||||
// but we must ensure Resolve() finds them so we don't accidentally box a shadowed variable.
|
// but we must ensure Resolve() finds them so we don't accidentally box a shadowed variable.
|
||||||
for i := 0 to High(Node.Parameters) do
|
for i := 0 to Node.Parameters.Count - 1 do
|
||||||
begin
|
begin
|
||||||
FCurrentScope.Define(Node.Parameters[i].Name, nil);
|
FCurrentScope.Define(Node.Parameters[i].Name, nil);
|
||||||
end;
|
end;
|
||||||
|
|||||||
@@ -342,6 +342,7 @@ var
|
|||||||
startCount: Integer;
|
startCount: Integer;
|
||||||
hasNested: Boolean;
|
hasNested: Boolean;
|
||||||
paramIdentity: INamedIdentity;
|
paramIdentity: INamedIdentity;
|
||||||
|
paramList: IParameterList;
|
||||||
begin
|
begin
|
||||||
startCount := FLambdaCounter;
|
startCount := FLambdaCounter;
|
||||||
Inc(FLambdaCounter);
|
Inc(FLambdaCounter);
|
||||||
@@ -355,8 +356,10 @@ begin
|
|||||||
try
|
try
|
||||||
FCurrentBuilder.Define('<self>');
|
FCurrentBuilder.Define('<self>');
|
||||||
|
|
||||||
SetLength(newParams, Length(Node.Parameters));
|
// Create Array to hold transformed parameters
|
||||||
for i := 0 to High(Node.Parameters) do
|
SetLength(newParams, Node.Parameters.Count);
|
||||||
|
|
||||||
|
for i := 0 to Node.Parameters.Count - 1 do
|
||||||
begin
|
begin
|
||||||
var paramNode := Node.Parameters[i];
|
var paramNode := Node.Parameters[i];
|
||||||
var paramName := paramNode.Name;
|
var paramName := paramNode.Name;
|
||||||
@@ -414,11 +417,15 @@ begin
|
|||||||
|
|
||||||
hasNested := FLambdaCounter > (startCount + 1);
|
hasNested := FLambdaCounter > (startCount + 1);
|
||||||
|
|
||||||
|
// Wrap the array in a List wrapper to satisfy the factory interface
|
||||||
|
// We reuse the identity of the old parameter list
|
||||||
|
paramList := TParameterList.Create(newParams, Node.Parameters.Identity);
|
||||||
|
|
||||||
// Rebuild Lambda using original identity
|
// Rebuild Lambda using original identity
|
||||||
Result :=
|
Result :=
|
||||||
TAst.LambdaExpr(
|
TAst.LambdaExpr(
|
||||||
Node.Identity,
|
Node.Identity,
|
||||||
newParams,
|
paramList,
|
||||||
newBody,
|
newBody,
|
||||||
finalLayout,
|
finalLayout,
|
||||||
nil, // Descriptor is created in TypeChecker
|
nil, // Descriptor is created in TypeChecker
|
||||||
@@ -433,11 +440,21 @@ begin
|
|||||||
if Node.Callee.Kind = akKeyword then
|
if Node.Callee.Kind = akKeyword then
|
||||||
begin
|
begin
|
||||||
// Transform keyword call (:key obj) into member access (.key obj)
|
// Transform keyword call (:key obj) into member access (.key obj)
|
||||||
// Note: The new MemberAccess node gets the identity of the original FunctionCall
|
// Check argument count
|
||||||
// The member keyword retains its own identity.
|
if Node.Arguments.Count <> 1 then
|
||||||
var memberAccess := TAst.MemberAccess(Node.Identity, Accept(Node.Arguments[0]), Node.Callee.AsKeyword);
|
begin
|
||||||
Result := memberAccess;
|
if Assigned(FLog) then
|
||||||
exit;
|
FLog.AddError(Format('Keyword access :%s requires exactly one argument.', [Node.Callee.AsKeyword.Value.Name]), Node);
|
||||||
|
// Fallthrough to standard visit/recreation to avoid crash
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// Note: The new MemberAccess node gets the identity of the original FunctionCall
|
||||||
|
// The member keyword retains its own identity.
|
||||||
|
var memberAccess := TAst.MemberAccess(Node.Identity, Accept(Node.Arguments[0]), Node.Callee.AsKeyword);
|
||||||
|
Result := memberAccess;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
Result := inherited VisitFunctionCall(Node);
|
Result := inherited VisitFunctionCall(Node);
|
||||||
end;
|
end;
|
||||||
|
|||||||
@@ -34,15 +34,20 @@ type
|
|||||||
class var
|
class var
|
||||||
FGensymCounter: Int64;
|
FGensymCounter: Int64;
|
||||||
|
|
||||||
function TransformAndSpliceNodes(const ANodes: TArray<IAstNode>): TArray<IAstNode>;
|
// Helper to handle unquote-splicing (~@) within lists.
|
||||||
|
// Takes a source list (e.g., Arguments) and returns a flattened array for the new node.
|
||||||
|
function TransformAndSpliceNodes(const ANodes: INodeList<IAstNode>): TArray<IAstNode>;
|
||||||
function Gensym(const ABaseName: string): string;
|
function Gensym(const ABaseName: string): string;
|
||||||
protected
|
protected
|
||||||
function VisitUnquote(const Node: IUnquoteNode): IAstNode; override;
|
function VisitUnquote(const Node: IUnquoteNode): IAstNode; override;
|
||||||
function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): IAstNode; override;
|
function VisitUnquoteSplicing(const Node: IUnquoteSplicingNode): IAstNode; override;
|
||||||
|
|
||||||
|
// We override these container visits to handle Splicing manually,
|
||||||
|
// bypassing the standard 1:1 list visitor.
|
||||||
function VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; override;
|
function VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; override;
|
||||||
function VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode; override;
|
function VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode; override;
|
||||||
function VisitRecordLiteral(const Node: IRecordLiteralNode): IAstNode; override;
|
|
||||||
|
|
||||||
|
function VisitRecordLiteral(const Node: IRecordLiteralNode): IAstNode; override;
|
||||||
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode; override;
|
function VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode; override;
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
|
||||||
function VisitIdentifier(const Node: IIdentifierNode): IAstNode; override;
|
function VisitIdentifier(const Node: IIdentifierNode): IAstNode; override;
|
||||||
@@ -169,15 +174,16 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TExpansionVisitor.TransformAndSpliceNodes(const ANodes: TArray<IAstNode>): TArray<IAstNode>;
|
function TExpansionVisitor.TransformAndSpliceNodes(const ANodes: INodeList<IAstNode>): TArray<IAstNode>;
|
||||||
var
|
var
|
||||||
newList: TList<IAstNode>;
|
newList: TList<IAstNode>;
|
||||||
nodeToSplice: IAstNode;
|
nodeToSplice: IAstNode;
|
||||||
transformedNode: IAstNode;
|
transformedNode: IAstNode;
|
||||||
|
node: IAstNode;
|
||||||
begin
|
begin
|
||||||
newList := TList<IAstNode>.Create;
|
newList := TList<IAstNode>.Create;
|
||||||
try
|
try
|
||||||
for var node in ANodes do
|
for node in ANodes do
|
||||||
begin
|
begin
|
||||||
if node.Kind = akUnquoteSplicing then
|
if node.Kind = akUnquoteSplicing then
|
||||||
begin
|
begin
|
||||||
@@ -196,10 +202,30 @@ begin
|
|||||||
if (not evaluatedSpliceValue.IsVoid) and (evaluatedSpliceValue.Kind = vkInterface) then
|
if (not evaluatedSpliceValue.IsVoid) and (evaluatedSpliceValue.Kind = vkInterface) then
|
||||||
begin
|
begin
|
||||||
nodeToSplice := evaluatedSpliceValue.AsIntf<IAstNode>;
|
nodeToSplice := evaluatedSpliceValue.AsIntf<IAstNode>;
|
||||||
if nodeToSplice.Kind = akBlockExpression then
|
|
||||||
newList.AddRange(nodeToSplice.AsBlockExpression.Expressions)
|
// Splicing implies the value must be a list-like AST structure (Block or just a List Node)
|
||||||
|
// If the evaluated value is an IArgumentList, IExpressionList etc., we flatten it.
|
||||||
|
if nodeToSplice.Kind = akExpressionList then
|
||||||
|
begin
|
||||||
|
for var subItem in nodeToSplice.AsExpressionList do
|
||||||
|
newList.Add(subItem);
|
||||||
|
end
|
||||||
|
else if nodeToSplice.Kind = akArgumentList then
|
||||||
|
begin
|
||||||
|
for var subItem in nodeToSplice.AsArgumentList do
|
||||||
|
newList.Add(subItem);
|
||||||
|
end
|
||||||
|
else if nodeToSplice.Kind = akBlockExpression then
|
||||||
|
begin
|
||||||
|
// Splice content of block
|
||||||
|
for var subItem in nodeToSplice.AsBlockExpression.Expressions do
|
||||||
|
newList.Add(subItem);
|
||||||
|
end
|
||||||
else
|
else
|
||||||
|
begin
|
||||||
|
// Treat as single item
|
||||||
newList.Add(nodeToSplice);
|
newList.Add(nodeToSplice);
|
||||||
|
end;
|
||||||
end
|
end
|
||||||
else if (not evaluatedSpliceValue.IsVoid) then
|
else if (not evaluatedSpliceValue.IsVoid) then
|
||||||
begin
|
begin
|
||||||
@@ -261,19 +287,24 @@ var
|
|||||||
newBody: IAstNode;
|
newBody: IAstNode;
|
||||||
newName: string;
|
newName: string;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
|
paramList: IParameterList;
|
||||||
begin
|
begin
|
||||||
SetLength(newParams, Length(Node.Parameters));
|
SetLength(newParams, Node.Parameters.Count);
|
||||||
for i := 0 to High(Node.Parameters) do
|
for i := 0 to Node.Parameters.Count - 1 do
|
||||||
begin
|
begin
|
||||||
newName := Gensym(Node.Parameters[i].Name);
|
var param := Node.Parameters[i];
|
||||||
|
newName := Gensym(param.Name);
|
||||||
// Use location from original param
|
// Use location from original param
|
||||||
newParams[i] := TAst.Identifier(newName, Node.Parameters[i].Identity.Location);
|
newParams[i] := TAst.Identifier(newName, param.Identity.Location);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
newBody := Accept(Node.Body);
|
newBody := Accept(Node.Body);
|
||||||
|
|
||||||
// Rebuild structural lambda
|
// Rebuild: Wrap array in TParameterList with original Identity
|
||||||
Result := TAst.LambdaExpr(Node.Identity, newParams, newBody);
|
paramList := TParameterList.Create(newParams, Node.Parameters.Identity);
|
||||||
|
|
||||||
|
// Use transformation overload
|
||||||
|
Result := TAst.LambdaExpr(Node.Identity, paramList, newBody);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TExpansionVisitor.VisitUnquote(const Node: IUnquoteNode): IAstNode;
|
function TExpansionVisitor.VisitUnquote(const Node: IUnquoteNode): IAstNode;
|
||||||
@@ -284,6 +315,7 @@ var
|
|||||||
begin
|
begin
|
||||||
expr := Node.Expression;
|
expr := Node.Expression;
|
||||||
|
|
||||||
|
// Optimization: If unquote refers to a local macro variable directly, try to get it.
|
||||||
if expr.Kind = akIdentifier then
|
if expr.Kind = akIdentifier then
|
||||||
begin
|
begin
|
||||||
addr := FMacroScope.Resolve(expr.AsIdentifier.Name);
|
addr := FMacroScope.Resolve(expr.AsIdentifier.Name);
|
||||||
@@ -329,22 +361,36 @@ function TExpansionVisitor.VisitFunctionCall(const Node: IFunctionCallNode): IAs
|
|||||||
var
|
var
|
||||||
newArgs: TArray<IAstNode>;
|
newArgs: TArray<IAstNode>;
|
||||||
transformedCallee: IAstNode;
|
transformedCallee: IAstNode;
|
||||||
|
argList: IArgumentList;
|
||||||
begin
|
begin
|
||||||
transformedCallee := Self.Accept(Node.Callee);
|
transformedCallee := Self.Accept(Node.Callee);
|
||||||
|
|
||||||
|
// Use splicing aware transformation for arguments (returns TArray)
|
||||||
newArgs := TransformAndSpliceNodes(Node.Arguments);
|
newArgs := TransformAndSpliceNodes(Node.Arguments);
|
||||||
Result := TAst.FunctionCall(Node.Identity, transformedCallee, newArgs);
|
|
||||||
|
// Wrap in List container to use Transformation overload
|
||||||
|
argList := TArgumentList.Create(newArgs, Node.Arguments.Identity);
|
||||||
|
|
||||||
|
Result := TAst.FunctionCall(Node.Identity, transformedCallee, argList);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TExpansionVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode;
|
function TExpansionVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode;
|
||||||
var
|
var
|
||||||
newExprs: TArray<IAstNode>;
|
newExprs: TArray<IAstNode>;
|
||||||
|
exprList: IExpressionList;
|
||||||
begin
|
begin
|
||||||
|
// Use splicing aware transformation for block expressions
|
||||||
newExprs := TransformAndSpliceNodes(Node.Expressions);
|
newExprs := TransformAndSpliceNodes(Node.Expressions);
|
||||||
Result := TAst.Block(Node.Identity, newExprs);
|
|
||||||
|
// Wrap in List
|
||||||
|
exprList := TExpressionList.Create(newExprs, Node.Expressions.Identity);
|
||||||
|
|
||||||
|
Result := TAst.Block(Node.Identity, exprList);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TExpansionVisitor.VisitRecordLiteral(const Node: IRecordLiteralNode): IAstNode;
|
function TExpansionVisitor.VisitRecordLiteral(const Node: IRecordLiteralNode): IAstNode;
|
||||||
begin
|
begin
|
||||||
|
// For now, standard transformation for records (no splicing key-values yet)
|
||||||
Result := inherited VisitRecordLiteral(Node);
|
Result := inherited VisitRecordLiteral(Node);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -438,10 +484,10 @@ begin
|
|||||||
var expansionScope := TScope.CreateScope(FInitialScope, nil, nil);
|
var expansionScope := TScope.CreateScope(FInitialScope, nil, nil);
|
||||||
|
|
||||||
var params := macroDef.Parameters;
|
var params := macroDef.Parameters;
|
||||||
if Length(Node.Arguments) <> Length(params) then
|
if Node.Arguments.Count <> params.Count then
|
||||||
raise EMacroException.CreateFmt('Macro %s expects %d arguments.', [calleeIdentifier.Name, Length(params)]);
|
raise EMacroException.CreateFmt('Macro %s expects %d arguments.', [calleeIdentifier.Name, params.Count]);
|
||||||
|
|
||||||
for i := 0 to High(params) do
|
for i := 0 to params.Count - 1 do
|
||||||
expansionScope.Define(params[i].Name, TDataValue.FromIntf<IAstNode>(Node.Arguments[i]));
|
expansionScope.Define(params[i].Name, TDataValue.FromIntf<IAstNode>(Node.Arguments[i]));
|
||||||
|
|
||||||
var expandedBody := TExpansionVisitor.Expand(expansionScope, macroDef.Body.AsQuasiquote.Expression, FMacroEvaluator);
|
var expandedBody := TExpansionVisitor.Expand(expansionScope, macroDef.Body.AsQuasiquote.Expression, FMacroEvaluator);
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ end;
|
|||||||
function TStaticSpecializer.VisitFunctionCall(const Node: IFunctionCallNode): IAstNode;
|
function TStaticSpecializer.VisitFunctionCall(const Node: IFunctionCallNode): IAstNode;
|
||||||
var
|
var
|
||||||
newCallee: IAstNode;
|
newCallee: IAstNode;
|
||||||
newArgs: TArray<IAstNode>;
|
newArgsList: IArgumentList;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
calleeIdent: IIdentifierNode;
|
calleeIdent: IIdentifierNode;
|
||||||
argTypes: TArray<IStaticType>;
|
argTypes: TArray<IStaticType>;
|
||||||
@@ -134,15 +134,16 @@ var
|
|||||||
begin
|
begin
|
||||||
// 1. Specialize children first (bottom-up)
|
// 1. Specialize children first (bottom-up)
|
||||||
newCallee := Accept(Node.Callee);
|
newCallee := Accept(Node.Callee);
|
||||||
newArgs := AcceptNodes(Node.Arguments);
|
// Arguments are now visited as a List, returning an IArgumentList
|
||||||
|
newArgsList := Accept(Node.Arguments).AsArgumentList;
|
||||||
|
|
||||||
// 2. Check if this call is a candidate for specialization
|
// 2. Check if this call is a candidate for specialization
|
||||||
if newCallee.Kind <> akIdentifier then
|
if newCallee.Kind <> akIdentifier then
|
||||||
begin
|
begin
|
||||||
if (newCallee = Node.Callee) and (newArgs = Node.Arguments) then
|
if (newCallee = Node.Callee) and (newArgsList = Node.Arguments) then
|
||||||
Result := Node
|
Result := Node
|
||||||
else
|
else
|
||||||
Result := TAst.FunctionCall(Node.Identity, newCallee, newArgs, Node.StaticType, Node.IsTailCall, nil);
|
Result := TAst.FunctionCall(Node.Identity, newCallee, newArgsList, Node.StaticType, Node.IsTailCall, nil);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -151,10 +152,10 @@ begin
|
|||||||
|
|
||||||
// 3. Check if all argument types are statically known
|
// 3. Check if all argument types are statically known
|
||||||
allTypesKnown := True;
|
allTypesKnown := True;
|
||||||
SetLength(argTypes, Length(newArgs));
|
SetLength(argTypes, newArgsList.Count);
|
||||||
for i := 0 to High(newArgs) do
|
for i := 0 to newArgsList.Count - 1 do
|
||||||
begin
|
begin
|
||||||
argTypes[i] := newArgs[i].AsTypedNode.StaticType;
|
argTypes[i] := newArgsList[i].AsTypedNode.StaticType;
|
||||||
if argTypes[i].Kind = stUnknown then
|
if argTypes[i].Kind = stUnknown then
|
||||||
begin
|
begin
|
||||||
allTypesKnown := False;
|
allTypesKnown := False;
|
||||||
@@ -164,10 +165,10 @@ begin
|
|||||||
|
|
||||||
if not allTypesKnown then
|
if not allTypesKnown then
|
||||||
begin
|
begin
|
||||||
if (newCallee = Node.Callee) and (newArgs = Node.Arguments) then
|
if (newCallee = Node.Callee) and (newArgsList = Node.Arguments) then
|
||||||
Result := Node
|
Result := Node
|
||||||
else
|
else
|
||||||
Result := TAst.FunctionCall(Node.Identity, newCallee, newArgs, Node.StaticType, Node.IsTailCall, nil);
|
Result := TAst.FunctionCall(Node.Identity, newCallee, newArgsList, Node.StaticType, Node.IsTailCall, nil);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -183,7 +184,7 @@ begin
|
|||||||
TAst.FunctionCall(
|
TAst.FunctionCall(
|
||||||
Node.Identity,
|
Node.Identity,
|
||||||
newCallee,
|
newCallee,
|
||||||
newArgs,
|
newArgsList,
|
||||||
specializedMethod.ReturnType,
|
specializedMethod.ReturnType,
|
||||||
Node.IsTailCall,
|
Node.IsTailCall,
|
||||||
specializedMethod.Target,
|
specializedMethod.Target,
|
||||||
@@ -203,7 +204,7 @@ begin
|
|||||||
TAst.FunctionCall(
|
TAst.FunctionCall(
|
||||||
Node.Identity,
|
Node.Identity,
|
||||||
newCallee,
|
newCallee,
|
||||||
newArgs,
|
newArgsList,
|
||||||
specializedMethod.ReturnType,
|
specializedMethod.ReturnType,
|
||||||
Node.IsTailCall,
|
Node.IsTailCall,
|
||||||
specializedMethod.Target,
|
specializedMethod.Target,
|
||||||
@@ -223,7 +224,7 @@ begin
|
|||||||
var lambdaDef := funcDef.AsLambdaExpression;
|
var lambdaDef := funcDef.AsLambdaExpression;
|
||||||
if (Length(lambdaDef.Upvalues) > 0) or (lambdaDef.HasNestedLambdas) then
|
if (Length(lambdaDef.Upvalues) > 0) or (lambdaDef.HasNestedLambdas) then
|
||||||
begin
|
begin
|
||||||
Result := TAst.FunctionCall(Node.Identity, newCallee, newArgs, Node.StaticType, Node.IsTailCall, nil);
|
Result := TAst.FunctionCall(Node.Identity, newCallee, newArgsList, Node.StaticType, Node.IsTailCall, nil);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@@ -244,15 +245,15 @@ begin
|
|||||||
FMonomorphCache.Add(key, specializedMethod);
|
FMonomorphCache.Add(key, specializedMethod);
|
||||||
|
|
||||||
// 6c. Return the new node
|
// 6c. Return the new node
|
||||||
Result := TAst.FunctionCall(Node.Identity, newCallee, newArgs, returnType, Node.IsTailCall, compiled.Func, compiled.IsPure);
|
Result := TAst.FunctionCall(Node.Identity, newCallee, newArgsList, returnType, Node.IsTailCall, compiled.Func, compiled.IsPure);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// 7. Fallback: Not RTL, Not User-Code -> Dynamic
|
// 7. Fallback: Not RTL, Not User-Code -> Dynamic
|
||||||
if (newCallee = Node.Callee) and (newArgs = Node.Arguments) then
|
if (newCallee = Node.Callee) and (newArgsList = Node.Arguments) then
|
||||||
Result := Node
|
Result := Node
|
||||||
else
|
else
|
||||||
Result := TAst.FunctionCall(Node.Identity, newCallee, newArgs, Node.StaticType, Node.IsTailCall, nil);
|
Result := TAst.FunctionCall(Node.Identity, newCallee, newArgsList, Node.StaticType, Node.IsTailCall, nil);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TMonoCacheKey }
|
{ TMonoCacheKey }
|
||||||
|
|||||||
@@ -99,26 +99,42 @@ function TAstTCO.VisitBlockExpression(const Node: IBlockExpressionNode): IAstNod
|
|||||||
var
|
var
|
||||||
isContextTail: Boolean;
|
isContextTail: Boolean;
|
||||||
newExprs: TArray<IAstNode>;
|
newExprs: TArray<IAstNode>;
|
||||||
|
exprsList: IExpressionList;
|
||||||
|
i: Integer;
|
||||||
|
item, newItem: IAstNode;
|
||||||
|
hasChanged: Boolean;
|
||||||
begin
|
begin
|
||||||
isContextTail := FIsTailStack.Peek;
|
isContextTail := FIsTailStack.Peek;
|
||||||
|
exprsList := Node.Expressions;
|
||||||
|
|
||||||
var nTail := High(Node.Expressions);
|
SetLength(newExprs, exprsList.Count);
|
||||||
newExprs :=
|
hasChanged := False;
|
||||||
AcceptNodes(
|
|
||||||
Node.Expressions,
|
|
||||||
function(idx: Integer; Node: IAstNode): IAstNode
|
|
||||||
begin
|
|
||||||
// Only the last expression in the block inherits the tail position status
|
|
||||||
FNextIsTail := isContextTail and (idx = nTail);
|
|
||||||
Result := Accept(Node);
|
|
||||||
end
|
|
||||||
);
|
|
||||||
|
|
||||||
if newExprs = Node.Expressions then
|
var nTail := exprsList.Count - 1;
|
||||||
|
|
||||||
|
for i := 0 to nTail do
|
||||||
|
begin
|
||||||
|
item := exprsList[i];
|
||||||
|
|
||||||
|
// Only the last expression in the block inherits the tail position status
|
||||||
|
FNextIsTail := isContextTail and (i = nTail);
|
||||||
|
|
||||||
|
newItem := Accept(item);
|
||||||
|
newExprs[i] := newItem;
|
||||||
|
|
||||||
|
if item <> newItem then
|
||||||
|
hasChanged := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not hasChanged then
|
||||||
Result := Node
|
Result := Node
|
||||||
else
|
else
|
||||||
|
begin
|
||||||
|
// Wrap array in List container
|
||||||
|
var newList := TExpressionList.Create(newExprs, Node.Expressions.Identity);
|
||||||
// CoW: Reuse Identity
|
// CoW: Reuse Identity
|
||||||
Result := TAst.Block(Node.Identity, newExprs, Node.StaticType);
|
Result := TAst.Block(Node.Identity, newList, Node.StaticType);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstTCO.VisitIfExpression(const Node: IIfExpressionNode): IAstNode;
|
function TAstTCO.VisitIfExpression(const Node: IIfExpressionNode): IAstNode;
|
||||||
@@ -169,12 +185,13 @@ end;
|
|||||||
|
|
||||||
function TAstTCO.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
|
function TAstTCO.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
|
||||||
var
|
var
|
||||||
newParams: TArray<IIdentifierNode>;
|
newParams: IParameterList;
|
||||||
newBody: IAstNode;
|
newBody: IAstNode;
|
||||||
begin
|
begin
|
||||||
// Parameters are not in tail position
|
// Parameters are not in tail position
|
||||||
FNextIsTail := False;
|
FNextIsTail := False;
|
||||||
newParams := AcceptParameters(Node.Parameters);
|
// Visit list node to handle potential transformations in children
|
||||||
|
newParams := Accept(Node.Parameters).AsParameterList;
|
||||||
|
|
||||||
// The body of a lambda is *always* a tail position (relative to the lambda execution)
|
// The body of a lambda is *always* a tail position (relative to the lambda execution)
|
||||||
FNextIsTail := True;
|
FNextIsTail := True;
|
||||||
@@ -185,8 +202,7 @@ begin
|
|||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
// Rebuild using factory.
|
// Rebuild using factory.
|
||||||
// IMPORTANT: Pass Layout AND Descriptor (TCO runs after TypeChecker).
|
// CoW: Reuse Identity. Factory expects IParameterList now.
|
||||||
// CoW: Reuse Identity
|
|
||||||
Result :=
|
Result :=
|
||||||
TAst.LambdaExpr(
|
TAst.LambdaExpr(
|
||||||
Node.Identity,
|
Node.Identity,
|
||||||
@@ -204,20 +220,21 @@ end;
|
|||||||
|
|
||||||
function TAstTCO.VisitRecurNode(const Node: IRecurNode): IAstNode;
|
function TAstTCO.VisitRecurNode(const Node: IRecurNode): IAstNode;
|
||||||
var
|
var
|
||||||
newArgs: TArray<IAstNode>;
|
newArgsList: IArgumentList;
|
||||||
begin
|
begin
|
||||||
if not FIsTailStack.Peek then
|
if not FIsTailStack.Peek then
|
||||||
raise EOptimizerException.Create('''recur'' can only be used in a tail position.');
|
raise EOptimizerException.Create('''recur'' can only be used in a tail position.');
|
||||||
|
|
||||||
// Arguments are not in tail position
|
// Arguments are not in tail position
|
||||||
FNextIsTail := False;
|
FNextIsTail := False;
|
||||||
newArgs := AcceptNodes(Node.Arguments);
|
// Visit the list node. Accept() ensures children are visited via TAstTransformer.VisitArgumentList
|
||||||
|
newArgsList := Accept(Node.Arguments).AsArgumentList;
|
||||||
|
|
||||||
if newArgs = Node.Arguments then
|
if newArgsList = Node.Arguments then
|
||||||
Result := Node
|
Result := Node
|
||||||
else
|
else
|
||||||
// CoW: Reuse Identity
|
// CoW: Reuse Identity. Factory expects IArgumentList.
|
||||||
Result := TAst.Recur(Node.Identity, newArgs, Node.StaticType);
|
Result := TAst.Recur(Node.Identity, newArgsList, Node.StaticType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstTCO.VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode;
|
function TAstTCO.VisitMacroExpansionNode(const Node: IMacroExpansionNode): IAstNode;
|
||||||
@@ -239,29 +256,32 @@ function TAstTCO.VisitFunctionCall(const Node: IFunctionCallNode): IAstNode;
|
|||||||
var
|
var
|
||||||
isTailCall: Boolean;
|
isTailCall: Boolean;
|
||||||
newCallee: IAstNode;
|
newCallee: IAstNode;
|
||||||
newArgs: TArray<IAstNode>;
|
newArgsList: IArgumentList;
|
||||||
begin
|
begin
|
||||||
isTailCall := FIsTailStack.Peek;
|
isTailCall := FIsTailStack.Peek;
|
||||||
|
|
||||||
// Callee/Arguments are not in tail position
|
// Callee/Arguments are not in tail position
|
||||||
FNextIsTail := False;
|
FNextIsTail := False;
|
||||||
|
|
||||||
newCallee := Accept(Node.Callee);
|
newCallee := Accept(Node.Callee);
|
||||||
newArgs := AcceptNodes(Node.Arguments);
|
|
||||||
|
// Visit the arguments list
|
||||||
|
newArgsList := Accept(Node.Arguments).AsArgumentList;
|
||||||
|
|
||||||
// CoW check: Create a new node only if children changed OR IsTailCall needs update
|
// CoW check: Create a new node only if children changed OR IsTailCall needs update
|
||||||
if (newCallee = Node.Callee) and (newArgs = Node.Arguments) and (isTailCall = Node.IsTailCall) then
|
if (newCallee = Node.Callee) and (newArgsList = Node.Arguments) and (isTailCall = Node.IsTailCall) then
|
||||||
begin
|
begin
|
||||||
Result := Node;
|
Result := Node;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Use factory to create new node, passing the *new* TCO status
|
// Use factory to create new node, passing the *new* TCO status
|
||||||
// CoW: Reuse Identity
|
// CoW: Reuse Identity. Factory expects IArgumentList.
|
||||||
Result :=
|
Result :=
|
||||||
TAst.FunctionCall(
|
TAst.FunctionCall(
|
||||||
Node.Identity,
|
Node.Identity,
|
||||||
newCallee,
|
newCallee,
|
||||||
newArgs,
|
newArgsList,
|
||||||
Node.StaticType,
|
Node.StaticType,
|
||||||
isTailCall,
|
isTailCall,
|
||||||
Node.StaticTarget, // Preserve the static target from Specializer
|
Node.StaticTarget, // Preserve the static target from Specializer
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ uses
|
|||||||
Myc.Ast.Visitor,
|
Myc.Ast.Visitor,
|
||||||
Myc.Ast.Scope,
|
Myc.Ast.Scope,
|
||||||
Myc.Ast.Types,
|
Myc.Ast.Types,
|
||||||
Myc.Ast.Identities, // Wichtig für Casts (AsNamed etc.)
|
Myc.Ast.Identities,
|
||||||
Myc.Ast;
|
Myc.Ast;
|
||||||
|
|
||||||
type
|
type
|
||||||
@@ -200,17 +200,15 @@ var
|
|||||||
identity: INamedIdentity;
|
identity: INamedIdentity;
|
||||||
begin
|
begin
|
||||||
adr := Node.Address;
|
adr := Node.Address;
|
||||||
identity := Node.Identity.AsNamed; // Extract specific identity
|
identity := Node.Identity.AsNamed;
|
||||||
|
|
||||||
if adr.Kind = akUnresolved then
|
if adr.Kind = akUnresolved then
|
||||||
begin
|
begin
|
||||||
// Propagate identity, set type to Unknown
|
|
||||||
Result := TAst.Identifier(identity, adr, TTypes.Unknown);
|
Result := TAst.Identifier(identity, adr, TTypes.Unknown);
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
typ := FCurrentContext.LookupType(adr);
|
typ := FCurrentContext.LookupType(adr);
|
||||||
// CoW: Reuse Identity
|
|
||||||
Result := TAst.Identifier(identity, adr, typ);
|
Result := TAst.Identifier(identity, adr, typ);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -219,12 +217,13 @@ var
|
|||||||
newArgs: TArray<IAstNode>;
|
newArgs: TArray<IAstNode>;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
SetLength(newArgs, Length(Node.Arguments));
|
SetLength(newArgs, Node.Arguments.Count);
|
||||||
for i := 0 to High(Node.Arguments) do
|
for i := 0 to Node.Arguments.Count - 1 do
|
||||||
newArgs[i] := Accept(Node.Arguments[i]);
|
newArgs[i] := Accept(Node.Arguments[i]);
|
||||||
|
|
||||||
// CoW: Reuse Identity
|
// FIX: Wrap in List
|
||||||
Result := TAst.Recur(Node.Identity, newArgs, TTypes.Void);
|
var argList := TArgumentList.Create(newArgs, Node.Arguments.Identity);
|
||||||
|
Result := TAst.Recur(Node.Identity, argList, TTypes.Void);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TTypeChecker.VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode;
|
function TTypeChecker.VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode;
|
||||||
@@ -256,7 +255,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
lambdaNode := Node.Initializer.AsLambdaExpression;
|
lambdaNode := Node.Initializer.AsLambdaExpression;
|
||||||
var paramTypes: TArray<IStaticType>;
|
var paramTypes: TArray<IStaticType>;
|
||||||
SetLength(paramTypes, Length(lambdaNode.Parameters));
|
SetLength(paramTypes, lambdaNode.Parameters.Count);
|
||||||
for i := 0 to High(paramTypes) do
|
for i := 0 to High(paramTypes) do
|
||||||
paramTypes[i] := TTypes.Unknown;
|
paramTypes[i] := TTypes.Unknown;
|
||||||
|
|
||||||
@@ -278,10 +277,8 @@ begin
|
|||||||
if initType.Kind <> stUnknown then
|
if initType.Kind <> stUnknown then
|
||||||
FCurrentContext.SetType(adr.SlotIndex, initType);
|
FCurrentContext.SetType(adr.SlotIndex, initType);
|
||||||
|
|
||||||
// Reuse Identity for Identifier
|
|
||||||
newIdent := TAst.Identifier(identIdentity, adr, initType);
|
newIdent := TAst.Identifier(identIdentity, adr, initType);
|
||||||
|
|
||||||
// Reuse Identity for VarDecl
|
|
||||||
Result := TAst.VarDecl(Node.Identity, newIdent, newInitializer, initType, Node.IsBoxed);
|
Result := TAst.VarDecl(Node.Identity, newIdent, newInitializer, initType, Node.IsBoxed);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -296,11 +293,10 @@ var
|
|||||||
identNode: IIdentifierNode;
|
identNode: IIdentifierNode;
|
||||||
identIdentity: INamedIdentity;
|
identIdentity: INamedIdentity;
|
||||||
begin
|
begin
|
||||||
// Rebuild Identifier with potential type info updates
|
|
||||||
identNode := Node.Target.AsIdentifier;
|
identNode := Node.Target.AsIdentifier;
|
||||||
identIdentity := identNode.Identity.AsNamed;
|
identIdentity := identNode.Identity.AsNamed;
|
||||||
|
|
||||||
newIdent := Accept(Node.Target); // This visits identifier and might update type from context
|
newIdent := Accept(Node.Target);
|
||||||
targetType := newIdent.AsTypedNode.StaticType;
|
targetType := newIdent.AsTypedNode.StaticType;
|
||||||
adr := identNode.Address;
|
adr := identNode.Address;
|
||||||
|
|
||||||
@@ -318,7 +314,7 @@ begin
|
|||||||
if (targetType.Kind <> stMethod) then
|
if (targetType.Kind <> stMethod) then
|
||||||
begin
|
begin
|
||||||
var paramTypes: TArray<IStaticType>;
|
var paramTypes: TArray<IStaticType>;
|
||||||
SetLength(paramTypes, Length(lambdaNode.Parameters));
|
SetLength(paramTypes, lambdaNode.Parameters.Count);
|
||||||
for i := 0 to High(paramTypes) do
|
for i := 0 to High(paramTypes) do
|
||||||
paramTypes[i] := TTypes.Unknown;
|
paramTypes[i] := TTypes.Unknown;
|
||||||
|
|
||||||
@@ -343,12 +339,10 @@ begin
|
|||||||
if ((targetType.Kind = stUnknown) or Assigned(placeholderType)) and (sourceType.Kind <> stUnknown) then
|
if ((targetType.Kind = stUnknown) or Assigned(placeholderType)) and (sourceType.Kind <> stUnknown) then
|
||||||
begin
|
begin
|
||||||
FCurrentContext.SetType(adr.SlotIndex, sourceType);
|
FCurrentContext.SetType(adr.SlotIndex, sourceType);
|
||||||
// Recreate Identifier with new type and original identity
|
|
||||||
newIdent := TAst.Identifier(identIdentity, adr, sourceType);
|
newIdent := TAst.Identifier(identIdentity, adr, sourceType);
|
||||||
targetType := sourceType;
|
targetType := sourceType;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// CoW: Reuse Assignment Identity
|
|
||||||
Result := TAst.Assign(Node.Identity, newIdent, newValue, targetType);
|
Result := TAst.Assign(Node.Identity, newIdent, newValue, targetType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -372,10 +366,10 @@ begin
|
|||||||
|
|
||||||
FCurrentContext := TTypeContext.Create(FCurrentContext, Node.Layout, upvalueTypes);
|
FCurrentContext := TTypeContext.Create(FCurrentContext, Node.Layout, upvalueTypes);
|
||||||
try
|
try
|
||||||
SetLength(newParams, Length(Node.Parameters));
|
SetLength(newParams, Node.Parameters.Count);
|
||||||
SetLength(paramTypes, Length(Node.Parameters));
|
SetLength(paramTypes, Node.Parameters.Count);
|
||||||
|
|
||||||
for i := 0 to High(Node.Parameters) do
|
for i := 0 to Node.Parameters.Count - 1 do
|
||||||
begin
|
begin
|
||||||
paramIdent := Node.Parameters[i];
|
paramIdent := Node.Parameters[i];
|
||||||
paramIdentity := paramIdent.Identity.AsNamed;
|
paramIdentity := paramIdent.Identity.AsNamed;
|
||||||
@@ -386,7 +380,6 @@ begin
|
|||||||
if paramAdr.Kind <> akUnresolved then
|
if paramAdr.Kind <> akUnresolved then
|
||||||
FCurrentContext.SetType(paramAdr.SlotIndex, paramTypes[i]);
|
FCurrentContext.SetType(paramAdr.SlotIndex, paramTypes[i]);
|
||||||
|
|
||||||
// CoW: Reuse Parameter Identity
|
|
||||||
newParams[i] := TAst.Identifier(paramIdentity, paramAdr, paramTypes[i]);
|
newParams[i] := TAst.Identifier(paramIdentity, paramAdr, paramTypes[i]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -402,11 +395,13 @@ begin
|
|||||||
temp.Free;
|
temp.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// CoW: Reuse Lambda Identity
|
// FIX: Wrap in List
|
||||||
|
var paramList := TParameterList.Create(newParams, Node.Parameters.Identity);
|
||||||
|
|
||||||
Result :=
|
Result :=
|
||||||
TAst.LambdaExpr(
|
TAst.LambdaExpr(
|
||||||
Node.Identity,
|
Node.Identity,
|
||||||
newParams,
|
paramList,
|
||||||
newBody,
|
newBody,
|
||||||
Node.Layout,
|
Node.Layout,
|
||||||
finalDescriptor,
|
finalDescriptor,
|
||||||
@@ -431,11 +426,11 @@ var
|
|||||||
argsStr: string;
|
argsStr: string;
|
||||||
begin
|
begin
|
||||||
newCallee := Accept(Node.Callee);
|
newCallee := Accept(Node.Callee);
|
||||||
SetLength(newArgs, Length(Node.Arguments));
|
SetLength(newArgs, Node.Arguments.Count);
|
||||||
SetLength(argTypes, Length(Node.Arguments));
|
SetLength(argTypes, Node.Arguments.Count);
|
||||||
|
|
||||||
hasUnknownArgs := False;
|
hasUnknownArgs := False;
|
||||||
for i := 0 to High(Node.Arguments) do
|
for i := 0 to Node.Arguments.Count - 1 do
|
||||||
begin
|
begin
|
||||||
newArgs[i] := Accept(Node.Arguments[i]);
|
newArgs[i] := Accept(Node.Arguments[i]);
|
||||||
argTypes[i] := newArgs[i].AsTypedNode.StaticType;
|
argTypes[i] := newArgs[i].AsTypedNode.StaticType;
|
||||||
@@ -498,17 +493,10 @@ begin
|
|||||||
retType := TTypes.Unknown;
|
retType := TTypes.Unknown;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// CoW: Reuse Call Identity
|
// FIX: Wrap in List
|
||||||
Result :=
|
var argList := TArgumentList.Create(newArgs, Node.Arguments.Identity);
|
||||||
TAst.FunctionCall(
|
|
||||||
Node.Identity,
|
Result := TAst.FunctionCall(Node.Identity, newCallee, argList, retType, Node.IsTailCall, nil, False);
|
||||||
newCallee,
|
|
||||||
newArgs,
|
|
||||||
retType,
|
|
||||||
Node.IsTailCall,
|
|
||||||
nil, // StaticTarget set by Specializer
|
|
||||||
False // IsTargetPure set by Specializer
|
|
||||||
);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TTypeChecker.VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode;
|
function TTypeChecker.VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode;
|
||||||
@@ -517,8 +505,8 @@ var
|
|||||||
newExprs: TArray<IAstNode>;
|
newExprs: TArray<IAstNode>;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
SetLength(newExprs, Length(Node.Expressions));
|
SetLength(newExprs, Node.Expressions.Count);
|
||||||
for i := 0 to High(Node.Expressions) do
|
for i := 0 to Node.Expressions.Count - 1 do
|
||||||
newExprs[i] := Accept(Node.Expressions[i]);
|
newExprs[i] := Accept(Node.Expressions[i]);
|
||||||
|
|
||||||
if Length(newExprs) > 0 then
|
if Length(newExprs) > 0 then
|
||||||
@@ -526,8 +514,9 @@ begin
|
|||||||
else
|
else
|
||||||
blockType := TTypes.Void;
|
blockType := TTypes.Void;
|
||||||
|
|
||||||
// CoW: Reuse Block Identity
|
// FIX: Wrap in List
|
||||||
Result := TAst.Block(Node.Identity, newExprs, blockType);
|
var exprList := TExpressionList.Create(newExprs, Node.Expressions.Identity);
|
||||||
|
Result := TAst.Block(Node.Identity, exprList, blockType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TTypeChecker.VisitIfExpression(const Node: IIfExpressionNode): IAstNode;
|
function TTypeChecker.VisitIfExpression(const Node: IIfExpressionNode): IAstNode;
|
||||||
@@ -561,7 +550,6 @@ begin
|
|||||||
resultType := TTypes.Unknown;
|
resultType := TTypes.Unknown;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// CoW: Reuse If Identity
|
|
||||||
Result := TAst.IfExpr(Node.Identity, newCond, newThen, newElse, resultType);
|
Result := TAst.IfExpr(Node.Identity, newCond, newThen, newElse, resultType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -594,7 +582,6 @@ begin
|
|||||||
resultType := TTypes.Unknown;
|
resultType := TTypes.Unknown;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// CoW: Reuse Ternary Identity
|
|
||||||
Result := TAst.TernaryExpr(Node.Identity, newCond, newThen, newElse, resultType);
|
Result := TAst.TernaryExpr(Node.Identity, newCond, newThen, newElse, resultType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -648,7 +635,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// CoW: Reuse MemberAccess Identity
|
|
||||||
Result := TAst.MemberAccess(Node.Identity, newBase, newMember.AsKeyword, elemType);
|
Result := TAst.MemberAccess(Node.Identity, newBase, newMember.AsKeyword, elemType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -686,7 +672,6 @@ begin
|
|||||||
FLog.AddError(Format('Indexer `[]` requires an Ordinal index, but got %s', [indexType.ToString]), Node);
|
FLog.AddError(Format('Indexer `[]` requires an Ordinal index, but got %s', [indexType.ToString]), Node);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// CoW: Reuse Indexer Identity
|
|
||||||
Result := TAst.Indexer(Node.Identity, newBase, newIndex, elemType);
|
Result := TAst.Indexer(Node.Identity, newBase, newIndex, elemType);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -699,13 +684,19 @@ var
|
|||||||
valType: IStaticType;
|
valType: IStaticType;
|
||||||
scalarKind: TScalar.TKind;
|
scalarKind: TScalar.TKind;
|
||||||
allScalar: Boolean;
|
allScalar: Boolean;
|
||||||
newFields: TArray<TRecordFieldLiteral>;
|
newFields: TArray<IRecordFieldNode>;
|
||||||
begin
|
begin
|
||||||
SetLength(newFields, Length(Node.Fields));
|
SetLength(newFields, Node.Fields.Count);
|
||||||
for i := 0 to High(Node.Fields) do
|
for i := 0 to Node.Fields.Count - 1 do
|
||||||
begin
|
begin
|
||||||
newFields[i].Key := Accept(Node.Fields[i].Key).AsKeyword;
|
var field := Node.Fields[i];
|
||||||
newFields[i].Value := Accept(Node.Fields[i].Value);
|
var newKey := Accept(field.Key).AsKeyword;
|
||||||
|
var newValue := Accept(field.Value);
|
||||||
|
|
||||||
|
if (newKey = field.Key) and (newValue = field.Value) then
|
||||||
|
newFields[i] := field
|
||||||
|
else
|
||||||
|
newFields[i] := TAst.RecordField(field.Identity, newKey, newValue);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
SetLength(scalarDefFields, Length(newFields));
|
SetLength(scalarDefFields, Length(newFields));
|
||||||
@@ -735,11 +726,14 @@ begin
|
|||||||
scalarDefFields[i] := TScalarRecordField.Create(newFields[i].Key.Value, scalarKind);
|
scalarDefFields[i] := TScalarRecordField.Create(newFields[i].Key.Value, scalarKind);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// FIX: Wrap in List
|
||||||
|
var fieldList := TRecordFieldList.Create(newFields, Node.Fields.Identity);
|
||||||
|
|
||||||
if allScalar then
|
if allScalar then
|
||||||
begin
|
begin
|
||||||
def := TScalarRecordRegistry.Intern(scalarDefFields);
|
def := TScalarRecordRegistry.Intern(scalarDefFields);
|
||||||
staticType := TTypes.CreateRecord(def);
|
staticType := TTypes.CreateRecord(def);
|
||||||
Result := TAst.RecordLiteral(Node.Identity, newFields, def, nil, staticType);
|
Result := TAst.RecordLiteral(Node.Identity, fieldList, def, nil, staticType);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
@@ -750,7 +744,7 @@ begin
|
|||||||
|
|
||||||
var genDef := TGenericRecordRegistry.Intern(genDefFields);
|
var genDef := TGenericRecordRegistry.Intern(genDefFields);
|
||||||
staticType := TTypes.CreateGenericRecord(genDef);
|
staticType := TTypes.CreateGenericRecord(genDef);
|
||||||
Result := TAst.RecordLiteral(Node.Identity, newFields, nil, genDef, staticType);
|
Result := TAst.RecordLiteral(Node.Identity, fieldList, nil, genDef, staticType);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -760,7 +754,6 @@ var
|
|||||||
defIdentity: IDefinitionIdentity;
|
defIdentity: IDefinitionIdentity;
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
// Use definition from Identity to ensure SSOT
|
|
||||||
defIdentity := Node.Identity.AsDefinition;
|
defIdentity := Node.Identity.AsDefinition;
|
||||||
elemType := TTypes.FromScalarKind(TScalar.StringToKind(defIdentity.Definition));
|
elemType := TTypes.FromScalarKind(TScalar.StringToKind(defIdentity.Definition));
|
||||||
except
|
except
|
||||||
@@ -772,7 +765,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// CoW: Reuse Definition Identity
|
|
||||||
Result := TAst.CreateSeries(defIdentity, TTypes.CreateSeries(elemType));
|
Result := TAst.CreateSeries(defIdentity, TTypes.CreateSeries(elemType));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -818,7 +810,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// CoW: Reuse Add Identity
|
|
||||||
Result := TAst.AddSeriesItem(Node.Identity, newSeries.AsIdentifier, newValue, newLookback, TTypes.Void);
|
Result := TAst.AddSeriesItem(Node.Identity, newSeries.AsIdentifier, newValue, newLookback, TTypes.Void);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -843,7 +834,6 @@ begin
|
|||||||
FLog.AddError(Format('"length" requires a series, but got %s', [seriesType.ToString]), Node);
|
FLog.AddError(Format('"length" requires a series, but got %s', [seriesType.ToString]), Node);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// CoW: Reuse SeriesLength Identity
|
|
||||||
Result := TAst.SeriesLength(Node.Identity, newSeries.AsIdentifier, TTypes.Ordinal);
|
Result := TAst.SeriesLength(Node.Identity, newSeries.AsIdentifier, TTypes.Ordinal);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
@@ -267,6 +267,7 @@ begin
|
|||||||
AppendLine('Block {');
|
AppendLine('Block {');
|
||||||
Indent;
|
Indent;
|
||||||
try
|
try
|
||||||
|
// Delegates to VisitExpressionList via inherited
|
||||||
Result := inherited VisitBlockExpression(Node);
|
Result := inherited VisitBlockExpression(Node);
|
||||||
// Scope might have changed after block execution if vars were defined
|
// Scope might have changed after block execution if vars were defined
|
||||||
ShowScope;
|
ShowScope;
|
||||||
|
|||||||
+57
-10
@@ -30,7 +30,7 @@ type
|
|||||||
function FormatAddress(const Addr: TResolvedAddress): string;
|
function FormatAddress(const Addr: TResolvedAddress): string;
|
||||||
|
|
||||||
protected
|
protected
|
||||||
// Override abstract PROCEDURES from TAstVisitor (not functions!)
|
// Override abstract PROCEDURES from TAstVisitor
|
||||||
procedure VisitConstant(const Node: IConstantNode); override;
|
procedure VisitConstant(const Node: IConstantNode); override;
|
||||||
procedure VisitIdentifier(const Node: IIdentifierNode); override;
|
procedure VisitIdentifier(const Node: IIdentifierNode); override;
|
||||||
procedure VisitKeyword(const Node: IKeywordNode); override;
|
procedure VisitKeyword(const Node: IKeywordNode); override;
|
||||||
@@ -55,6 +55,14 @@ type
|
|||||||
procedure VisitSeriesLength(const Node: ISeriesLengthNode); override;
|
procedure VisitSeriesLength(const Node: ISeriesLengthNode); override;
|
||||||
procedure VisitNop(const Node: INopNode); override;
|
procedure VisitNop(const Node: INopNode); override;
|
||||||
|
|
||||||
|
// List Visitors are handled implicitly by parent node iteration in Dumper,
|
||||||
|
// but we implement them empty/default to satisfy the abstract base class if called directly.
|
||||||
|
procedure VisitParameterList(const Node: IParameterList); override;
|
||||||
|
procedure VisitArgumentList(const Node: IArgumentList); override;
|
||||||
|
procedure VisitExpressionList(const Node: IExpressionList); override;
|
||||||
|
procedure VisitRecordFieldList(const Node: IRecordFieldList); override;
|
||||||
|
procedure VisitRecordField(const Node: IRecordFieldNode); override;
|
||||||
|
|
||||||
public
|
public
|
||||||
constructor Create(const AOutput: TStrings);
|
constructor Create(const AOutput: TStrings);
|
||||||
class procedure Dump(const RootNode: IAstNode; const Output: TStrings);
|
class procedure Dump(const RootNode: IAstNode; const Output: TStrings);
|
||||||
@@ -201,7 +209,6 @@ var
|
|||||||
slot: Integer;
|
slot: Integer;
|
||||||
typ: IStaticType;
|
typ: IStaticType;
|
||||||
begin
|
begin
|
||||||
// (* UPDATED: Added IsPure output *)
|
|
||||||
LogFmt(
|
LogFmt(
|
||||||
'LambdaExpression (HasNested: %s, IsPure: %s)',
|
'LambdaExpression (HasNested: %s, IsPure: %s)',
|
||||||
[Node.HasNestedLambdas.ToString(TUseBoolStrs.True), BoolToStr(Node.IsPure, True)],
|
[Node.HasNestedLambdas.ToString(TUseBoolStrs.True), BoolToStr(Node.IsPure, True)],
|
||||||
@@ -236,6 +243,7 @@ begin
|
|||||||
// 3. Parameters
|
// 3. Parameters
|
||||||
Log('Parameters:');
|
Log('Parameters:');
|
||||||
Indent;
|
Indent;
|
||||||
|
// Iterate over IParameterList
|
||||||
for var param in Node.Parameters do
|
for var param in Node.Parameters do
|
||||||
param.Accept(Self);
|
param.Accept(Self);
|
||||||
Unindent;
|
Unindent;
|
||||||
@@ -266,11 +274,12 @@ var
|
|||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
sigStr := '';
|
sigStr := '';
|
||||||
|
// Note: Node.Arguments is IArgumentList now.
|
||||||
if Assigned(Node.StaticTarget) then
|
if Assigned(Node.StaticTarget) then
|
||||||
begin
|
begin
|
||||||
staticStatus := 'Assigned';
|
staticStatus := 'Assigned';
|
||||||
SetLength(argTypes, Length(Node.Arguments));
|
SetLength(argTypes, Node.Arguments.Count);
|
||||||
for i := 0 to High(Node.Arguments) do
|
for i := 0 to Node.Arguments.Count - 1 do
|
||||||
begin
|
begin
|
||||||
if Node.Arguments[i].IsTyped then
|
if Node.Arguments[i].IsTyped then
|
||||||
argTypes[i] := Node.Arguments[i].AsTypedNode.StaticType.ToString
|
argTypes[i] := Node.Arguments[i].AsTypedNode.StaticType.ToString
|
||||||
@@ -282,7 +291,6 @@ begin
|
|||||||
else
|
else
|
||||||
staticStatus := 'nil';
|
staticStatus := 'nil';
|
||||||
|
|
||||||
// (* UPDATED: Added IsTargetPure output *)
|
|
||||||
LogFmt(
|
LogFmt(
|
||||||
'FunctionCall (IsTailCall: %s, StaticTarget: %s%s, IsTargetPure: %s)',
|
'FunctionCall (IsTailCall: %s, StaticTarget: %s%s, IsTargetPure: %s)',
|
||||||
[Node.IsTailCall.ToString(TUseBoolStrs.True), staticStatus, sigStr, BoolToStr(Node.IsTargetPure, True)],
|
[Node.IsTailCall.ToString(TUseBoolStrs.True), staticStatus, sigStr, BoolToStr(Node.IsTargetPure, True)],
|
||||||
@@ -292,8 +300,9 @@ begin
|
|||||||
Indent;
|
Indent;
|
||||||
Log('Callee:');
|
Log('Callee:');
|
||||||
Node.Callee.Accept(Self);
|
Node.Callee.Accept(Self);
|
||||||
LogFmt('Arguments (%d):', [Length(Node.Arguments)]);
|
LogFmt('Arguments (%d):', [Node.Arguments.Count]);
|
||||||
Indent;
|
Indent;
|
||||||
|
// Iterate over IArgumentList
|
||||||
for arg in Node.Arguments do
|
for arg in Node.Arguments do
|
||||||
arg.Accept(Self);
|
arg.Accept(Self);
|
||||||
Unindent;
|
Unindent;
|
||||||
@@ -311,7 +320,7 @@ begin
|
|||||||
Indent;
|
Indent;
|
||||||
Log('Callee:');
|
Log('Callee:');
|
||||||
Node.CallNode.Callee.Accept(Self);
|
Node.CallNode.Callee.Accept(Self);
|
||||||
LogFmt('Arguments (%d):', [Length(Node.CallNode.Arguments)]);
|
LogFmt('Arguments (%d):', [Node.CallNode.Arguments.Count]);
|
||||||
Indent;
|
Indent;
|
||||||
for arg in Node.CallNode.Arguments do
|
for arg in Node.CallNode.Arguments do
|
||||||
arg.Accept(Self);
|
arg.Accept(Self);
|
||||||
@@ -332,7 +341,7 @@ var
|
|||||||
begin
|
begin
|
||||||
Log('Recur', Node);
|
Log('Recur', Node);
|
||||||
Indent;
|
Indent;
|
||||||
LogFmt('Arguments (%d):', [Length(Node.Arguments)]);
|
LogFmt('Arguments (%d):', [Node.Arguments.Count]);
|
||||||
Indent;
|
Indent;
|
||||||
for arg in Node.Arguments do
|
for arg in Node.Arguments do
|
||||||
arg.Accept(Self);
|
arg.Accept(Self);
|
||||||
@@ -446,10 +455,11 @@ end;
|
|||||||
|
|
||||||
procedure TAstDumper.VisitRecordLiteral(const Node: IRecordLiteralNode);
|
procedure TAstDumper.VisitRecordLiteral(const Node: IRecordLiteralNode);
|
||||||
var
|
var
|
||||||
field: TRecordFieldLiteral;
|
field: IRecordFieldNode;
|
||||||
begin
|
begin
|
||||||
LogFmt('RecordLiteral (%d fields)', [Length(Node.Fields)], Node);
|
LogFmt('RecordLiteral (%d fields)', [Node.Fields.Count], Node);
|
||||||
Indent;
|
Indent;
|
||||||
|
// Iterate over IRecordFieldList
|
||||||
for field in Node.Fields do
|
for field in Node.Fields do
|
||||||
begin
|
begin
|
||||||
LogFmt('Field :%s', [field.Key.Value.Name]);
|
LogFmt('Field :%s', [field.Key.Value.Name]);
|
||||||
@@ -495,4 +505,41 @@ begin
|
|||||||
Log('Nop', Node);
|
Log('Nop', Node);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// --- List Visitors Implementation ---
|
||||||
|
|
||||||
|
procedure TAstDumper.VisitParameterList(const Node: IParameterList);
|
||||||
|
begin
|
||||||
|
// Usually handled by Parent Node iteration (Lambda),
|
||||||
|
// but if visited directly:
|
||||||
|
for var item in Node do
|
||||||
|
item.Accept(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TAstDumper.VisitArgumentList(const Node: IArgumentList);
|
||||||
|
begin
|
||||||
|
for var item in Node do
|
||||||
|
item.Accept(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TAstDumper.VisitExpressionList(const Node: IExpressionList);
|
||||||
|
begin
|
||||||
|
for var item in Node do
|
||||||
|
item.Accept(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TAstDumper.VisitRecordFieldList(const Node: IRecordFieldList);
|
||||||
|
begin
|
||||||
|
for var item in Node do
|
||||||
|
item.Accept(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TAstDumper.VisitRecordField(const Node: IRecordFieldNode);
|
||||||
|
begin
|
||||||
|
// If visited directly (e.g. inside a list)
|
||||||
|
LogFmt('Field :%s', [Node.Key.Value.Name]);
|
||||||
|
Indent;
|
||||||
|
Node.Value.Accept(Self);
|
||||||
|
Unindent;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
@@ -25,6 +25,14 @@ type
|
|||||||
function VisitConstant(const Node: IConstantNode): TDataValue; virtual;
|
function VisitConstant(const Node: IConstantNode): TDataValue; virtual;
|
||||||
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; virtual;
|
function VisitIdentifier(const Node: IIdentifierNode): TDataValue; virtual;
|
||||||
function VisitKeyword(const Node: IKeywordNode): TDataValue; virtual;
|
function VisitKeyword(const Node: IKeywordNode): TDataValue; virtual;
|
||||||
|
|
||||||
|
// List Visitors
|
||||||
|
function VisitParameterList(const Node: IParameterList): TDataValue; virtual;
|
||||||
|
function VisitArgumentList(const Node: IArgumentList): TDataValue; virtual;
|
||||||
|
function VisitExpressionList(const Node: IExpressionList): TDataValue; virtual;
|
||||||
|
function VisitRecordFieldList(const Node: IRecordFieldList): TDataValue; virtual;
|
||||||
|
function VisitRecordField(const Node: IRecordFieldNode): TDataValue; virtual;
|
||||||
|
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; virtual;
|
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue; virtual;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; virtual;
|
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue; virtual;
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; virtual;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue; virtual;
|
||||||
@@ -230,8 +238,8 @@ begin
|
|||||||
i: Integer;
|
i: Integer;
|
||||||
adr: TResolvedAddress;
|
adr: TResolvedAddress;
|
||||||
begin
|
begin
|
||||||
if (Length(ArgValues) <> Length(params)) then
|
if (Length(ArgValues) <> params.Count) then
|
||||||
raise EEvaluatorException.CreateFmt('Argument count mismatch: expected %d, got %d', [Length(params), Length(ArgValues)]);
|
raise EEvaluatorException.CreateFmt('Argument count mismatch: expected %d, got %d', [params.Count, Length(ArgValues)]);
|
||||||
|
|
||||||
// Create the new execution scope for this function call.
|
// Create the new execution scope for this function call.
|
||||||
lambdaScope := TScope.CreateScope(closureScope, descriptor, capturedCells);
|
lambdaScope := TScope.CreateScope(closureScope, descriptor, capturedCells);
|
||||||
@@ -243,7 +251,7 @@ begin
|
|||||||
lambdaScope[adr] := TDataValue(closure);
|
lambdaScope[adr] := TDataValue(closure);
|
||||||
|
|
||||||
// Populate the scope with the actual parameters passed to the function.
|
// Populate the scope with the actual parameters passed to the function.
|
||||||
for i := 0 to High(ArgValues) do
|
for i := 0 to params.Count - 1 do
|
||||||
begin
|
begin
|
||||||
adr := params[i].Address;
|
adr := params[i].Address;
|
||||||
Assert(adr.ScopeDepth = 0);
|
Assert(adr.ScopeDepth = 0);
|
||||||
@@ -283,15 +291,15 @@ var
|
|||||||
calleeValue: TDataValue;
|
calleeValue: TDataValue;
|
||||||
argValues: TArray<TDataValue>;
|
argValues: TArray<TDataValue>;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
argNodes: TArray<IAstNode>;
|
argList: IArgumentList;
|
||||||
begin
|
begin
|
||||||
if Assigned(Node.StaticTarget) then
|
if Assigned(Node.StaticTarget) then
|
||||||
begin
|
begin
|
||||||
// --- Static Path (Optimized) ---
|
// --- Static Path (Optimized) ---
|
||||||
argNodes := Node.Arguments;
|
argList := Node.Arguments;
|
||||||
SetLength(argValues, Length(argNodes));
|
SetLength(argValues, argList.Count);
|
||||||
for i := 0 to High(argNodes) do
|
for i := 0 to argList.Count - 1 do
|
||||||
argValues[i] := argNodes[i].Accept(Self);
|
argValues[i] := argList[i].Accept(Self);
|
||||||
|
|
||||||
// Call static target. Exceptions here are caught by Execute/HandleTCO.
|
// Call static target. Exceptions here are caught by Execute/HandleTCO.
|
||||||
Result := Node.StaticTarget(argValues);
|
Result := Node.StaticTarget(argValues);
|
||||||
@@ -304,10 +312,10 @@ begin
|
|||||||
if calleeValue.Kind <> vkMethod then
|
if calleeValue.Kind <> vkMethod then
|
||||||
raise EEvaluatorException.Create('Expression is not invokable in this context.');
|
raise EEvaluatorException.Create('Expression is not invokable in this context.');
|
||||||
|
|
||||||
argNodes := Node.Arguments;
|
argList := Node.Arguments;
|
||||||
SetLength(argValues, Length(argNodes));
|
SetLength(argValues, argList.Count);
|
||||||
for i := 0 to High(argNodes) do
|
for i := 0 to argList.Count - 1 do
|
||||||
argValues[i] := argNodes[i].Accept(Self);
|
argValues[i] := argList[i].Accept(Self);
|
||||||
|
|
||||||
if Node.IsTailCall then
|
if Node.IsTailCall then
|
||||||
begin
|
begin
|
||||||
@@ -333,8 +341,8 @@ var
|
|||||||
calleeValue: TDataValue;
|
calleeValue: TDataValue;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
SetLength(argValues, Length(Node.Arguments));
|
SetLength(argValues, Node.Arguments.Count);
|
||||||
for i := 0 to High(Node.Arguments) do
|
for i := 0 to Node.Arguments.Count - 1 do
|
||||||
argValues[i] := Node.Arguments[i].Accept(Self);
|
argValues[i] := Node.Arguments[i].Accept(Self);
|
||||||
|
|
||||||
calleeAddress.Kind := akLocalOrParent;
|
calleeAddress.Kind := akLocalOrParent;
|
||||||
@@ -517,11 +525,12 @@ begin
|
|||||||
if Assigned(Node.GenericDefinition) then
|
if Assigned(Node.GenericDefinition) then
|
||||||
begin
|
begin
|
||||||
var genFields: TArray<TPair<IKeyword, TDataValue>>;
|
var genFields: TArray<TPair<IKeyword, TDataValue>>;
|
||||||
SetLength(genFields, Length(Node.Fields));
|
SetLength(genFields, Node.Fields.Count);
|
||||||
|
|
||||||
for i := 0 to High(Node.Fields) do
|
for i := 0 to Node.Fields.Count - 1 do
|
||||||
begin
|
begin
|
||||||
genFields[i] := TPair<IKeyword, TDataValue>.Create(Node.Fields[i].Key.Value, Node.Fields[i].Value.Accept(Self));
|
var field := Node.Fields[i];
|
||||||
|
genFields[i] := TPair<IKeyword, TDataValue>.Create(field.Key.Value, field.Value.Accept(Self));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var dynRec := TDynamicRecord.Create(genFields);
|
var dynRec := TDynamicRecord.Create(genFields);
|
||||||
@@ -530,11 +539,12 @@ begin
|
|||||||
else if Assigned(Node.ScalarDefinition) then
|
else if Assigned(Node.ScalarDefinition) then
|
||||||
begin
|
begin
|
||||||
var values: TArray<TScalar.TValue>;
|
var values: TArray<TScalar.TValue>;
|
||||||
SetLength(values, Length(Node.Fields));
|
SetLength(values, Node.Fields.Count);
|
||||||
|
|
||||||
for i := 0 to High(Node.Fields) do
|
for i := 0 to Node.Fields.Count - 1 do
|
||||||
begin
|
begin
|
||||||
var valData := Node.Fields[i].Value.Accept(Self);
|
var field := Node.Fields[i];
|
||||||
|
var valData := field.Value.Accept(Self);
|
||||||
values[i] := valData.AsScalar.Value;
|
values[i] := valData.AsScalar.Value;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -589,12 +599,18 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
function TEvaluatorVisitor.VisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
||||||
|
begin
|
||||||
|
// Delegate to ExpressionList visitor
|
||||||
|
Result := Node.Expressions.Accept(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TEvaluatorVisitor.VisitExpressionList(const Node: IExpressionList): TDataValue;
|
||||||
var
|
var
|
||||||
expression: IAstNode;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.Void;
|
Result := TDataValue.Void;
|
||||||
for expression in Node.Expressions do
|
for i := 0 to Node.Count - 1 do
|
||||||
Result := expression.Accept(Self);
|
Result := Node[i].Accept(Self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEvaluatorVisitor.VisitNop(const Node: INopNode): TDataValue;
|
function TEvaluatorVisitor.VisitNop(const Node: INopNode): TDataValue;
|
||||||
@@ -620,4 +636,30 @@ begin
|
|||||||
Result := TDataValue(TScalar.FromInt64(len));
|
Result := TDataValue(TScalar.FromInt64(len));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// --- List Visitor Stubs (Mostly Unused directly, but required by Interface) ---
|
||||||
|
|
||||||
|
function TEvaluatorVisitor.VisitParameterList(const Node: IParameterList): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := TDataValue.Void;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TEvaluatorVisitor.VisitArgumentList(const Node: IArgumentList): TDataValue;
|
||||||
|
begin
|
||||||
|
// Could evaluate arguments here and return an array-wrapped TDataValue,
|
||||||
|
// but VisitFunctionCall handles iteration manually for efficiency.
|
||||||
|
Result := TDataValue.Void;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TEvaluatorVisitor.VisitRecordFieldList(const Node: IRecordFieldList): TDataValue;
|
||||||
|
begin
|
||||||
|
// Handled by VisitRecordLiteral
|
||||||
|
Result := TDataValue.Void;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TEvaluatorVisitor.VisitRecordField(const Node: IRecordFieldNode): TDataValue;
|
||||||
|
begin
|
||||||
|
// Handled by manual iteration in VisitRecordLiteral
|
||||||
|
Result := TDataValue.Void;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ type
|
|||||||
IConstantIdentity = interface;
|
IConstantIdentity = interface;
|
||||||
IKeywordIdentity = interface;
|
IKeywordIdentity = interface;
|
||||||
IDefinitionIdentity = interface;
|
IDefinitionIdentity = interface;
|
||||||
|
IListIdentity = interface;
|
||||||
|
|
||||||
// Represents a position in the source code.
|
// Represents a position in the source code.
|
||||||
ISourceLocation = interface
|
ISourceLocation = interface
|
||||||
@@ -29,7 +30,8 @@ type
|
|||||||
ikNamed, // Identifier, MacroDef (Name + Location)
|
ikNamed, // Identifier, MacroDef (Name + Location)
|
||||||
ikConstant, // Literals (Value + Location)
|
ikConstant, // Literals (Value + Location)
|
||||||
ikKeyword, // Keywords (Keyword + Location)
|
ikKeyword, // Keywords (Keyword + Location)
|
||||||
ikDefinition // Complex definitions (DefString + Location)
|
ikDefinition, // Complex definitions (DefString + Location)
|
||||||
|
ikList // Lists (Open/Close Tokens + Separator + Location)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Base interface for the "Green Tree" nodes.
|
// Base interface for the "Green Tree" nodes.
|
||||||
@@ -47,6 +49,7 @@ type
|
|||||||
function AsConstant: IConstantIdentity;
|
function AsConstant: IConstantIdentity;
|
||||||
function AsKeyword: IKeywordIdentity;
|
function AsKeyword: IKeywordIdentity;
|
||||||
function AsDefinition: IDefinitionIdentity;
|
function AsDefinition: IDefinitionIdentity;
|
||||||
|
function AsList: IListIdentity;
|
||||||
|
|
||||||
property Kind: TAstIdentityKind read GetKind;
|
property Kind: TAstIdentityKind read GetKind;
|
||||||
|
|
||||||
@@ -82,6 +85,18 @@ type
|
|||||||
property Definition: string read GetDefinition;
|
property Definition: string read GetDefinition;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Spezifische Identität für Listen
|
||||||
|
IListIdentity = interface(IAstIdentity)
|
||||||
|
{$region 'private'}
|
||||||
|
function GetOpenToken: string;
|
||||||
|
function GetCloseToken: string;
|
||||||
|
function GetSeparator: string;
|
||||||
|
{$endregion}
|
||||||
|
property OpenToken: string read GetOpenToken;
|
||||||
|
property CloseToken: string read GetCloseToken;
|
||||||
|
property Separator: string read GetSeparator;
|
||||||
|
end;
|
||||||
|
|
||||||
// Factory and static access.
|
// Factory and static access.
|
||||||
TIdentities = record
|
TIdentities = record
|
||||||
public
|
public
|
||||||
@@ -92,6 +107,8 @@ type
|
|||||||
class function Constant(const AValue: TDataValue; const ALoc: ISourceLocation = nil): IConstantIdentity; static;
|
class function Constant(const AValue: TDataValue; const ALoc: ISourceLocation = nil): IConstantIdentity; static;
|
||||||
class function Keyword(const AValue: IKeyword; const ALoc: ISourceLocation = nil): IKeywordIdentity; static;
|
class function Keyword(const AValue: IKeyword; const ALoc: ISourceLocation = nil): IKeywordIdentity; static;
|
||||||
class function Definition(const ADef: string; const ALoc: ISourceLocation = nil): IDefinitionIdentity; static;
|
class function Definition(const ADef: string; const ALoc: ISourceLocation = nil): IDefinitionIdentity; static;
|
||||||
|
|
||||||
|
class function List(const AOpen, AClose, ASeparator: string; const ALoc: ISourceLocation = nil): IListIdentity; static;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@@ -121,6 +138,7 @@ type
|
|||||||
function AsConstant: IConstantIdentity; virtual;
|
function AsConstant: IConstantIdentity; virtual;
|
||||||
function AsKeyword: IKeywordIdentity; virtual;
|
function AsKeyword: IKeywordIdentity; virtual;
|
||||||
function AsDefinition: IDefinitionIdentity; virtual;
|
function AsDefinition: IDefinitionIdentity; virtual;
|
||||||
|
function AsList: IListIdentity; virtual;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TStructuralIdentity = class(TAbstractIdentity)
|
TStructuralIdentity = class(TAbstractIdentity)
|
||||||
@@ -176,6 +194,20 @@ type
|
|||||||
function AsDefinition: IDefinitionIdentity; override;
|
function AsDefinition: IDefinitionIdentity; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TListIdentity = class(TAbstractIdentity, IListIdentity)
|
||||||
|
private
|
||||||
|
FOpen, FClose, FSeparator: string;
|
||||||
|
function GetOpenToken: string;
|
||||||
|
function GetCloseToken: string;
|
||||||
|
function GetSeparator: string;
|
||||||
|
protected
|
||||||
|
function GetKind: TAstIdentityKind; override;
|
||||||
|
public
|
||||||
|
constructor Create(const AOpen, AClose, ASeparator: string; const ALoc: ISourceLocation);
|
||||||
|
function ToString: string; override;
|
||||||
|
function AsList: IListIdentity; override;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TSourceLocation }
|
{ TSourceLocation }
|
||||||
|
|
||||||
constructor TSourceLocation.Create(ALine, ACol: Integer);
|
constructor TSourceLocation.Create(ALine, ACol: Integer);
|
||||||
@@ -241,6 +273,11 @@ begin
|
|||||||
raise EInvalidCast.Create('Identity is not a Definition Identity');
|
raise EInvalidCast.Create('Identity is not a Definition Identity');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TAbstractIdentity.AsList: IListIdentity;
|
||||||
|
begin
|
||||||
|
raise EInvalidCast.Create('Identity is not a List Identity');
|
||||||
|
end;
|
||||||
|
|
||||||
{ TStructuralIdentity }
|
{ TStructuralIdentity }
|
||||||
|
|
||||||
function TStructuralIdentity.GetKind: TAstIdentityKind;
|
function TStructuralIdentity.GetKind: TAstIdentityKind;
|
||||||
@@ -360,6 +397,46 @@ begin
|
|||||||
Result := Format('Def: "%s" (%s)', [FDefinition, inherited ToString]);
|
Result := Format('Def: "%s" (%s)', [FDefinition, inherited ToString]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TListIdentity }
|
||||||
|
|
||||||
|
constructor TListIdentity.Create(const AOpen, AClose, ASeparator: string; const ALoc: ISourceLocation);
|
||||||
|
begin
|
||||||
|
inherited Create(ALoc);
|
||||||
|
FOpen := AOpen;
|
||||||
|
FClose := AClose;
|
||||||
|
FSeparator := ASeparator;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TListIdentity.GetKind: TAstIdentityKind;
|
||||||
|
begin
|
||||||
|
Result := ikList;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TListIdentity.GetOpenToken: string;
|
||||||
|
begin
|
||||||
|
Result := FOpen;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TListIdentity.GetCloseToken: string;
|
||||||
|
begin
|
||||||
|
Result := FClose;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TListIdentity.GetSeparator: string;
|
||||||
|
begin
|
||||||
|
Result := FSeparator;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TListIdentity.AsList: IListIdentity;
|
||||||
|
begin
|
||||||
|
Result := Self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TListIdentity.ToString: string;
|
||||||
|
begin
|
||||||
|
Result := Format('List: "%s...%s" (Sep: "%s") (%s)', [FOpen, FClose, FSeparator, inherited ToString]);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TIdentities }
|
{ TIdentities }
|
||||||
|
|
||||||
class function TIdentities.Location(ALine, ACol: Integer): ISourceLocation;
|
class function TIdentities.Location(ALine, ACol: Integer): ISourceLocation;
|
||||||
@@ -392,4 +469,9 @@ begin
|
|||||||
Result := TDefinitionIdentity.Create(ADef, ALoc);
|
Result := TDefinitionIdentity.Create(ADef, ALoc);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
class function TIdentities.List(const AOpen, AClose, ASeparator: string; const ALoc: ISourceLocation): IListIdentity;
|
||||||
|
begin
|
||||||
|
Result := TListIdentity.Create(AOpen, AClose, ASeparator, ALoc);
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
+78
-34
@@ -44,7 +44,7 @@ type
|
|||||||
function JsonToVarDeclNode(const AObj: TJSONObject): IVariableDeclarationNode;
|
function JsonToVarDeclNode(const AObj: TJSONObject): IVariableDeclarationNode;
|
||||||
function JsonToAssignmentNode(const AObj: TJSONObject): IAssignmentNode;
|
function JsonToAssignmentNode(const AObj: TJSONObject): IAssignmentNode;
|
||||||
function JsonToIndexerNode(const AObj: TJSONObject): IIndexerNode;
|
function JsonToIndexerNode(const AObj: TJSONObject): IIndexerNode;
|
||||||
function JsonToMemberAccessNode(const AObj: TJSONObject): IMemberAccessNode;
|
function JsonToMemberAccessNode(const AObj: TJSONObject): IMemberAccessNode; // <--- KORRIGIERT
|
||||||
function JsonToRecordLiteralNode(const AObj: TJSONObject): IRecordLiteralNode;
|
function JsonToRecordLiteralNode(const AObj: TJSONObject): IRecordLiteralNode;
|
||||||
function JsonToCreateSeriesNode(const AObj: TJSONObject): ICreateSeriesNode;
|
function JsonToCreateSeriesNode(const AObj: TJSONObject): ICreateSeriesNode;
|
||||||
function JsonToAddSeriesItemNode(const AObj: TJSONObject): IAddSeriesItemNode;
|
function JsonToAddSeriesItemNode(const AObj: TJSONObject): IAddSeriesItemNode;
|
||||||
@@ -56,6 +56,14 @@ type
|
|||||||
function VisitConstant(const Node: IConstantNode): TJSONObject; override;
|
function VisitConstant(const Node: IConstantNode): TJSONObject; override;
|
||||||
function VisitIdentifier(const Node: IIdentifierNode): TJSONObject; override;
|
function VisitIdentifier(const Node: IIdentifierNode): TJSONObject; override;
|
||||||
function VisitKeyword(const Node: IKeywordNode): TJSONObject; override;
|
function VisitKeyword(const Node: IKeywordNode): TJSONObject; override;
|
||||||
|
|
||||||
|
// List Visitors (stubbed mostly, as parents handle array generation for JSON structure)
|
||||||
|
function VisitParameterList(const Node: IParameterList): TJSONObject; override;
|
||||||
|
function VisitArgumentList(const Node: IArgumentList): TJSONObject; override;
|
||||||
|
function VisitExpressionList(const Node: IExpressionList): TJSONObject; override;
|
||||||
|
function VisitRecordFieldList(const Node: IRecordFieldList): TJSONObject; override;
|
||||||
|
function VisitRecordField(const Node: IRecordFieldNode): TJSONObject; override;
|
||||||
|
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): TJSONObject; override;
|
function VisitIfExpression(const Node: IIfExpressionNode): TJSONObject; override;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TJSONObject; override;
|
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TJSONObject; override;
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TJSONObject; override;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TJSONObject; override;
|
||||||
@@ -197,12 +205,13 @@ function TJsonAstConverter.VisitLambdaExpression(const Node: ILambdaExpressionNo
|
|||||||
var
|
var
|
||||||
bodyObj: TJSONObject;
|
bodyObj: TJSONObject;
|
||||||
paramsArray: TJSONArray;
|
paramsArray: TJSONArray;
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
bodyObj := Accept(Node.Body);
|
bodyObj := Accept(Node.Body);
|
||||||
|
|
||||||
paramsArray := TJSONArray.Create;
|
paramsArray := TJSONArray.Create;
|
||||||
for var param in Node.Parameters do
|
for i := 0 to Node.Parameters.Count - 1 do
|
||||||
paramsArray.Add(Accept(param));
|
paramsArray.Add(Accept(Node.Parameters[i]));
|
||||||
|
|
||||||
Result := TJSONObject.Create;
|
Result := TJSONObject.Create;
|
||||||
Result.AddPair('NodeType', TJSONString.Create('LambdaExpr'));
|
Result.AddPair('NodeType', TJSONString.Create('LambdaExpr'));
|
||||||
@@ -214,13 +223,14 @@ function TJsonAstConverter.VisitMacroDefinition(const Node: IMacroDefinitionNode
|
|||||||
var
|
var
|
||||||
nameObj, bodyObj: TJSONObject;
|
nameObj, bodyObj: TJSONObject;
|
||||||
paramsArray: TJSONArray;
|
paramsArray: TJSONArray;
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
nameObj := Accept(Node.Name);
|
nameObj := Accept(Node.Name);
|
||||||
bodyObj := Accept(Node.Body);
|
bodyObj := Accept(Node.Body);
|
||||||
|
|
||||||
paramsArray := TJSONArray.Create;
|
paramsArray := TJSONArray.Create;
|
||||||
for var param in Node.Parameters do
|
for i := 0 to Node.Parameters.Count - 1 do
|
||||||
paramsArray.Add(Accept(param));
|
paramsArray.Add(Accept(Node.Parameters[i]));
|
||||||
|
|
||||||
Result := TJSONObject.Create;
|
Result := TJSONObject.Create;
|
||||||
Result.AddPair('NodeType', TJSONString.Create('MacroDef'));
|
Result.AddPair('NodeType', TJSONString.Create('MacroDef'));
|
||||||
@@ -254,13 +264,13 @@ function TJsonAstConverter.VisitFunctionCall(const Node: IFunctionCallNode): TJS
|
|||||||
var
|
var
|
||||||
calleeObj: TJSONObject;
|
calleeObj: TJSONObject;
|
||||||
argsArray: TJSONArray;
|
argsArray: TJSONArray;
|
||||||
arg: IAstNode;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
calleeObj := Accept(Node.Callee);
|
calleeObj := Accept(Node.Callee);
|
||||||
|
|
||||||
argsArray := TJSONArray.Create;
|
argsArray := TJSONArray.Create;
|
||||||
for arg in Node.Arguments do
|
for i := 0 to Node.Arguments.Count - 1 do
|
||||||
argsArray.Add(Accept(arg));
|
argsArray.Add(Accept(Node.Arguments[i]));
|
||||||
|
|
||||||
Result := TJSONObject.Create;
|
Result := TJSONObject.Create;
|
||||||
Result.AddPair('NodeType', TJSONString.Create('FunctionCall'));
|
Result.AddPair('NodeType', TJSONString.Create('FunctionCall'));
|
||||||
@@ -272,14 +282,14 @@ function TJsonAstConverter.VisitMacroExpansionNode(const Node: IMacroExpansionNo
|
|||||||
var
|
var
|
||||||
calleeObj, bodyObj: TJSONObject;
|
calleeObj, bodyObj: TJSONObject;
|
||||||
argsArray: TJSONArray;
|
argsArray: TJSONArray;
|
||||||
arg: IAstNode;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
calleeObj := Accept(Node.CallNode.Callee);
|
calleeObj := Accept(Node.CallNode.Callee);
|
||||||
bodyObj := Accept(Node.ExpandedBody);
|
bodyObj := Accept(Node.ExpandedBody);
|
||||||
|
|
||||||
argsArray := TJSONArray.Create;
|
argsArray := TJSONArray.Create;
|
||||||
for arg in Node.CallNode.Arguments do
|
for i := 0 to Node.CallNode.Arguments.Count - 1 do
|
||||||
argsArray.Add(Accept(arg));
|
argsArray.Add(Accept(Node.CallNode.Arguments[i]));
|
||||||
|
|
||||||
Result := TJSONObject.Create;
|
Result := TJSONObject.Create;
|
||||||
Result.AddPair('NodeType', TJSONString.Create('MacroExpansion'));
|
Result.AddPair('NodeType', TJSONString.Create('MacroExpansion'));
|
||||||
@@ -291,11 +301,11 @@ end;
|
|||||||
function TJsonAstConverter.VisitRecurNode(const Node: IRecurNode): TJSONObject;
|
function TJsonAstConverter.VisitRecurNode(const Node: IRecurNode): TJSONObject;
|
||||||
var
|
var
|
||||||
argsArray: TJSONArray;
|
argsArray: TJSONArray;
|
||||||
arg: IAstNode;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
argsArray := TJSONArray.Create;
|
argsArray := TJSONArray.Create;
|
||||||
for arg in Node.Arguments do
|
for i := 0 to Node.Arguments.Count - 1 do
|
||||||
argsArray.Add(Accept(arg));
|
argsArray.Add(Accept(Node.Arguments[i]));
|
||||||
|
|
||||||
Result := TJSONObject.Create;
|
Result := TJSONObject.Create;
|
||||||
Result.AddPair('NodeType', TJSONString.Create('Recur'));
|
Result.AddPair('NodeType', TJSONString.Create('Recur'));
|
||||||
@@ -305,11 +315,11 @@ end;
|
|||||||
function TJsonAstConverter.VisitBlockExpression(const Node: IBlockExpressionNode): TJSONObject;
|
function TJsonAstConverter.VisitBlockExpression(const Node: IBlockExpressionNode): TJSONObject;
|
||||||
var
|
var
|
||||||
exprsArray: TJSONArray;
|
exprsArray: TJSONArray;
|
||||||
expr: IAstNode;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
exprsArray := TJSONArray.Create;
|
exprsArray := TJSONArray.Create;
|
||||||
for expr in Node.Expressions do
|
for i := 0 to Node.Expressions.Count - 1 do
|
||||||
exprsArray.Add(Accept(expr));
|
exprsArray.Add(Accept(Node.Expressions[i]));
|
||||||
|
|
||||||
Result := TJSONObject.Create;
|
Result := TJSONObject.Create;
|
||||||
Result.AddPair('NodeType', TJSONString.Create('Block'));
|
Result.AddPair('NodeType', TJSONString.Create('Block'));
|
||||||
@@ -375,24 +385,28 @@ end;
|
|||||||
function TJsonAstConverter.VisitRecordLiteral(const Node: IRecordLiteralNode): TJSONObject;
|
function TJsonAstConverter.VisitRecordLiteral(const Node: IRecordLiteralNode): TJSONObject;
|
||||||
var
|
var
|
||||||
fieldsArray: TJSONArray;
|
fieldsArray: TJSONArray;
|
||||||
field: TRecordFieldLiteral;
|
i: Integer;
|
||||||
fieldObj: TJSONObject;
|
|
||||||
begin
|
begin
|
||||||
Result := TJSONObject.Create;
|
Result := TJSONObject.Create;
|
||||||
Result.AddPair('NodeType', TJSONString.Create('RecordLiteral'));
|
Result.AddPair('NodeType', TJSONString.Create('RecordLiteral'));
|
||||||
|
|
||||||
fieldsArray := TJSONArray.Create;
|
fieldsArray := TJSONArray.Create;
|
||||||
for field in Node.Fields do
|
for i := 0 to Node.Fields.Count - 1 do
|
||||||
begin
|
begin
|
||||||
fieldObj := TJSONObject.Create;
|
// We visit the RecordFieldNode, which returns a JSON Object
|
||||||
fieldObj.AddPair('Name', TJSONString.Create(field.Key.Value.Name));
|
fieldsArray.Add(Accept(Node.Fields[i]));
|
||||||
fieldObj.AddPair('Value', Accept(field.Value)); // Get TJSONObject
|
|
||||||
fieldsArray.Add(fieldObj);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Result.AddPair('Fields', fieldsArray);
|
Result.AddPair('Fields', fieldsArray);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TJsonAstConverter.VisitRecordField(const Node: IRecordFieldNode): TJSONObject;
|
||||||
|
begin
|
||||||
|
Result := TJSONObject.Create;
|
||||||
|
Result.AddPair('Name', TJSONString.Create(Node.Key.Value.Name));
|
||||||
|
Result.AddPair('Value', Accept(Node.Value));
|
||||||
|
end;
|
||||||
|
|
||||||
function TJsonAstConverter.VisitCreateSeries(const Node: ICreateSeriesNode): TJSONObject;
|
function TJsonAstConverter.VisitCreateSeries(const Node: ICreateSeriesNode): TJSONObject;
|
||||||
begin
|
begin
|
||||||
Result := TJSONObject.Create;
|
Result := TJSONObject.Create;
|
||||||
@@ -436,7 +450,35 @@ begin
|
|||||||
Result.AddPair('NodeType', TJSONString.Create('Nop'));
|
Result.AddPair('NodeType', TJSONString.Create('Nop'));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TJsonAstConverter - Deserialization }
|
// --- List Visitors (Placeholder return) ---
|
||||||
|
// Since we iterate manually in parent nodes to form JSON Arrays, these are technically not used
|
||||||
|
// by the current logic, but required by the interface.
|
||||||
|
// Note: If we wanted strict visitor compliance, VisitFunctionCall would call Accept(List),
|
||||||
|
// which would return TJSONObject wrapping the array. We skip that level of nesting here.
|
||||||
|
|
||||||
|
function TJsonAstConverter.VisitParameterList(const Node: IParameterList): TJSONObject;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TJsonAstConverter.VisitArgumentList(const Node: IArgumentList): TJSONObject;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TJsonAstConverter.VisitExpressionList(const Node: IExpressionList): TJSONObject;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TJsonAstConverter.VisitRecordFieldList(const Node: IRecordFieldList): TJSONObject;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
// Deserialization
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
function TJsonAstConverter.JsonToDataValue(const AObj: TJSONObject; const AName: string): TDataValue;
|
function TJsonAstConverter.JsonToDataValue(const AObj: TJSONObject; const AName: string): TDataValue;
|
||||||
var
|
var
|
||||||
@@ -532,11 +574,10 @@ function TJsonAstConverter.JsonToMacroDefNode(const AObj: TJSONObject): IMacroDe
|
|||||||
var
|
var
|
||||||
name: IIdentifierNode;
|
name: IIdentifierNode;
|
||||||
params: TArray<IIdentifierNode>;
|
params: TArray<IIdentifierNode>;
|
||||||
body: IQuasiquoteNode;
|
body: IAstNode;
|
||||||
paramArray: TJSONArray;
|
paramArray: TJSONArray;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
|
|
||||||
name := JsonToIdentifierNode(AObj.GetValue('Name') as TJSONObject);
|
name := JsonToIdentifierNode(AObj.GetValue('Name') as TJSONObject);
|
||||||
|
|
||||||
paramArray := AObj.GetValue<TJSONArray>('Parameters');
|
paramArray := AObj.GetValue<TJSONArray>('Parameters');
|
||||||
@@ -544,7 +585,7 @@ begin
|
|||||||
for i := 0 to paramArray.Count - 1 do
|
for i := 0 to paramArray.Count - 1 do
|
||||||
params[i] := JsonToIdentifierNode(paramArray.Items[i] as TJSONObject);
|
params[i] := JsonToIdentifierNode(paramArray.Items[i] as TJSONObject);
|
||||||
|
|
||||||
body := IQuasiquoteNode(JsonToNode(AObj.GetValue('Body'), 'Quasiquote'));
|
body := JsonToNode(AObj.GetValue('Body'), 'Quasiquote');
|
||||||
Result := TAst.MacroDef(name, params, body);
|
Result := TAst.MacroDef(name, params, body);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -556,7 +597,6 @@ var
|
|||||||
i: Integer;
|
i: Integer;
|
||||||
tempCallNode: IFunctionCallNode;
|
tempCallNode: IFunctionCallNode;
|
||||||
begin
|
begin
|
||||||
// Recursively deserialize all parts of the macro expansion node
|
|
||||||
callee := JsonToNode(AObj.GetValue('Callee'));
|
callee := JsonToNode(AObj.GetValue('Callee'));
|
||||||
expandedBody := JsonToNode(AObj.GetValue('ExpandedBody'));
|
expandedBody := JsonToNode(AObj.GetValue('ExpandedBody'));
|
||||||
argsArray := AObj.GetValue<TJSONArray>('Arguments');
|
argsArray := AObj.GetValue<TJSONArray>('Arguments');
|
||||||
@@ -564,10 +604,7 @@ begin
|
|||||||
for i := 0 to argsArray.Count - 1 do
|
for i := 0 to argsArray.Count - 1 do
|
||||||
args[i] := JsonToNode(argsArray.Items[i]);
|
args[i] := JsonToNode(argsArray.Items[i]);
|
||||||
|
|
||||||
// Create a temporary IFunctionCallNode to pass to the factory
|
|
||||||
tempCallNode := TAst.FunctionCall(callee, args);
|
tempCallNode := TAst.FunctionCall(callee, args);
|
||||||
|
|
||||||
// Use the new global factory function from the TAst record
|
|
||||||
Result := TAst.MacroExpansionNode(tempCallNode, expandedBody);
|
Result := TAst.MacroExpansionNode(tempCallNode, expandedBody);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -666,18 +703,25 @@ end;
|
|||||||
|
|
||||||
function TJsonAstConverter.JsonToRecordLiteralNode(const AObj: TJSONObject): IRecordLiteralNode;
|
function TJsonAstConverter.JsonToRecordLiteralNode(const AObj: TJSONObject): IRecordLiteralNode;
|
||||||
var
|
var
|
||||||
fields: TArray<TRecordFieldLiteral>;
|
fields: TArray<IRecordFieldNode>;
|
||||||
fieldsArray: TJSONArray;
|
fieldsArray: TJSONArray;
|
||||||
fieldObj: TJSONObject;
|
fieldObj: TJSONObject;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
|
keyNode: IKeywordNode;
|
||||||
|
valueNode: IAstNode;
|
||||||
begin
|
begin
|
||||||
fieldsArray := AObj.GetValue<TJSONArray>('Fields');
|
fieldsArray := AObj.GetValue<TJSONArray>('Fields');
|
||||||
SetLength(fields, fieldsArray.Count);
|
SetLength(fields, fieldsArray.Count);
|
||||||
|
|
||||||
for i := 0 to fieldsArray.Count - 1 do
|
for i := 0 to fieldsArray.Count - 1 do
|
||||||
begin
|
begin
|
||||||
fieldObj := fieldsArray.Items[i] as TJSONObject;
|
fieldObj := fieldsArray.Items[i] as TJSONObject;
|
||||||
fields[i] := TRecordFieldLiteral.Create(TAst.Keyword(fieldObj.GetValue<string>('Name')), JsonToNode(fieldObj.GetValue('Value')));
|
keyNode := TAst.Keyword(fieldObj.GetValue<string>('Name'));
|
||||||
|
valueNode := JsonToNode(fieldObj.GetValue('Value'));
|
||||||
|
|
||||||
|
fields[i] := TAst.RecordField(keyNode, valueNode);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Result := TAst.RecordLiteral(fields);
|
Result := TAst.RecordLiteral(fields);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
+369
-65
@@ -76,9 +76,20 @@ type
|
|||||||
|
|
||||||
IAstVisitor = interface;
|
IAstVisitor = interface;
|
||||||
IAstTypedNode = interface;
|
IAstTypedNode = interface;
|
||||||
|
|
||||||
|
// Core Nodes
|
||||||
IConstantNode = interface;
|
IConstantNode = interface;
|
||||||
IIdentifierNode = interface;
|
IIdentifierNode = interface;
|
||||||
IKeywordNode = interface;
|
IKeywordNode = interface;
|
||||||
|
|
||||||
|
// Lists & Containers
|
||||||
|
IParameterList = interface;
|
||||||
|
IArgumentList = interface;
|
||||||
|
IExpressionList = interface;
|
||||||
|
IRecordFieldList = interface;
|
||||||
|
IRecordFieldNode = interface;
|
||||||
|
|
||||||
|
// Control Flow & Structure
|
||||||
IIfExpressionNode = interface;
|
IIfExpressionNode = interface;
|
||||||
ITernaryExpressionNode = interface;
|
ITernaryExpressionNode = interface;
|
||||||
ILambdaExpressionNode = interface;
|
ILambdaExpressionNode = interface;
|
||||||
@@ -105,6 +116,12 @@ type
|
|||||||
akConstant,
|
akConstant,
|
||||||
akIdentifier,
|
akIdentifier,
|
||||||
akKeyword,
|
akKeyword,
|
||||||
|
// Lists
|
||||||
|
akParameterList,
|
||||||
|
akArgumentList,
|
||||||
|
akExpressionList,
|
||||||
|
akRecordFieldList,
|
||||||
|
akRecordField,
|
||||||
akIfExpression,
|
akIfExpression,
|
||||||
akTernaryExpression,
|
akTernaryExpression,
|
||||||
akLambdaExpression,
|
akLambdaExpression,
|
||||||
@@ -148,6 +165,13 @@ type
|
|||||||
function AsConstant: IConstantNode;
|
function AsConstant: IConstantNode;
|
||||||
function AsIdentifier: IIdentifierNode;
|
function AsIdentifier: IIdentifierNode;
|
||||||
function AsKeyword: IKeywordNode;
|
function AsKeyword: IKeywordNode;
|
||||||
|
|
||||||
|
function AsParameterList: IParameterList;
|
||||||
|
function AsArgumentList: IArgumentList;
|
||||||
|
function AsExpressionList: IExpressionList;
|
||||||
|
function AsRecordFieldList: IRecordFieldList;
|
||||||
|
function AsRecordField: IRecordFieldNode;
|
||||||
|
|
||||||
function AsIfExpression: IIfExpressionNode;
|
function AsIfExpression: IIfExpressionNode;
|
||||||
function AsTernaryExpression: ITernaryExpressionNode;
|
function AsTernaryExpression: ITernaryExpressionNode;
|
||||||
function AsLambdaExpression: ILambdaExpressionNode;
|
function AsLambdaExpression: ILambdaExpressionNode;
|
||||||
@@ -174,6 +198,17 @@ type
|
|||||||
property Identity: IAstIdentity read GetIdentity;
|
property Identity: IAstIdentity read GetIdentity;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
INodeList<T: IAstNode> = interface(IAstNode)
|
||||||
|
{$region 'private'}
|
||||||
|
function GetCount: Integer;
|
||||||
|
function GetItem(Index: Integer): T;
|
||||||
|
{$endregion}
|
||||||
|
function GetEnumerator: TEnumerator<T>;
|
||||||
|
function ToArray: TArray<T>;
|
||||||
|
property Count: Integer read GetCount;
|
||||||
|
property Items[Index: Integer]: T read GetItem; default;
|
||||||
|
end;
|
||||||
|
|
||||||
IAstTypedNode = interface(IAstNode)
|
IAstTypedNode = interface(IAstNode)
|
||||||
{$region 'private'}
|
{$region 'private'}
|
||||||
function GetStaticType: IStaticType;
|
function GetStaticType: IStaticType;
|
||||||
@@ -181,17 +216,29 @@ type
|
|||||||
property StaticType: IStaticType read GetStaticType;
|
property StaticType: IStaticType read GetStaticType;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
IRecordFieldNode = interface(IAstNode)
|
||||||
|
{$region 'private'}
|
||||||
|
function GetKey: IKeywordNode;
|
||||||
|
function GetValue: IAstNode;
|
||||||
|
{$endregion}
|
||||||
|
property Key: IKeywordNode read GetKey;
|
||||||
|
property Value: IAstNode read GetValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
IRecordFieldList = interface(INodeList<IRecordFieldNode>)
|
||||||
|
end;
|
||||||
|
|
||||||
// --- Node Interfaces (Definitions) ---
|
// --- Node Interfaces (Definitions) ---
|
||||||
|
|
||||||
// Function Definition (Lambda)
|
// Function Definition (Lambda)
|
||||||
IFunctionDefinition = interface(IAstTypedNode)
|
IFunctionDefinition = interface(IAstTypedNode)
|
||||||
{$region 'private'}
|
{$region 'private'}
|
||||||
function GetBody: IAstNode;
|
function GetBody: IAstNode;
|
||||||
function GetParameters: TArray<IIdentifierNode>;
|
function GetParameters: IParameterList;
|
||||||
function GetIsPure: Boolean;
|
function GetIsPure: Boolean;
|
||||||
{$endregion}
|
{$endregion}
|
||||||
property Body: IAstNode read GetBody;
|
property Body: IAstNode read GetBody;
|
||||||
property Parameters: TArray<IIdentifierNode> read GetParameters;
|
property Parameters: IParameterList read GetParameters;
|
||||||
property IsPure: Boolean read GetIsPure;
|
property IsPure: Boolean read GetIsPure;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -259,13 +306,13 @@ type
|
|||||||
IFunctionCallNode = interface(IAstTypedNode)
|
IFunctionCallNode = interface(IAstTypedNode)
|
||||||
{$region 'private'}
|
{$region 'private'}
|
||||||
function GetCallee: IAstNode;
|
function GetCallee: IAstNode;
|
||||||
function GetArguments: TArray<IAstNode>;
|
function GetArguments: IArgumentList;
|
||||||
function GetIsTailCall: Boolean;
|
function GetIsTailCall: Boolean;
|
||||||
function GetStaticTarget: TDataValue.TFunc;
|
function GetStaticTarget: TDataValue.TFunc;
|
||||||
function GetIsTargetPure: Boolean;
|
function GetIsTargetPure: Boolean;
|
||||||
{$endregion}
|
{$endregion}
|
||||||
property Callee: IAstNode read GetCallee;
|
property Callee: IAstNode read GetCallee;
|
||||||
property Arguments: TArray<IAstNode> read GetArguments;
|
property Arguments: IArgumentList read GetArguments;
|
||||||
property IsTailCall: Boolean read GetIsTailCall;
|
property IsTailCall: Boolean read GetIsTailCall;
|
||||||
property StaticTarget: TDataValue.TFunc read GetStaticTarget;
|
property StaticTarget: TDataValue.TFunc read GetStaticTarget;
|
||||||
property IsTargetPure: Boolean read GetIsTargetPure;
|
property IsTargetPure: Boolean read GetIsTargetPure;
|
||||||
@@ -282,16 +329,16 @@ type
|
|||||||
|
|
||||||
IRecurNode = interface(IAstTypedNode)
|
IRecurNode = interface(IAstTypedNode)
|
||||||
{$region 'private'}
|
{$region 'private'}
|
||||||
function GetArguments: TArray<IAstNode>;
|
function GetArguments: IArgumentList;
|
||||||
{$endregion}
|
{$endregion}
|
||||||
property Arguments: TArray<IAstNode> read GetArguments;
|
property Arguments: IArgumentList read GetArguments;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
IBlockExpressionNode = interface(IAstTypedNode)
|
IBlockExpressionNode = interface(IAstTypedNode)
|
||||||
{$region 'private'}
|
{$region 'private'}
|
||||||
function GetExpressions: TArray<IAstNode>;
|
function GetExpressions: IExpressionList;
|
||||||
{$endregion}
|
{$endregion}
|
||||||
property Expressions: TArray<IAstNode> read GetExpressions;
|
property Expressions: IExpressionList read GetExpressions;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
IVariableDeclarationNode = interface(IAstTypedNode)
|
IVariableDeclarationNode = interface(IAstTypedNode)
|
||||||
@@ -317,11 +364,11 @@ type
|
|||||||
IMacroDefinitionNode = interface(IAstTypedNode)
|
IMacroDefinitionNode = interface(IAstTypedNode)
|
||||||
{$region 'private'}
|
{$region 'private'}
|
||||||
function GetName: IIdentifierNode;
|
function GetName: IIdentifierNode;
|
||||||
function GetParameters: TArray<IIdentifierNode>;
|
function GetParameters: IParameterList;
|
||||||
function GetBody: IAstNode;
|
function GetBody: IAstNode;
|
||||||
{$endregion}
|
{$endregion}
|
||||||
property Name: IIdentifierNode read GetName;
|
property Name: IIdentifierNode read GetName;
|
||||||
property Parameters: TArray<IIdentifierNode> read GetParameters;
|
property Parameters: IParameterList read GetParameters;
|
||||||
property Body: IAstNode read GetBody;
|
property Body: IAstNode read GetBody;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -364,19 +411,13 @@ type
|
|||||||
property Member: IKeywordNode read GetMember;
|
property Member: IKeywordNode read GetMember;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TRecordFieldLiteral = record
|
|
||||||
Key: IKeywordNode;
|
|
||||||
Value: IAstNode;
|
|
||||||
constructor Create(const AKey: IKeywordNode; const AValue: IAstNode);
|
|
||||||
end;
|
|
||||||
|
|
||||||
IRecordLiteralNode = interface(IAstTypedNode)
|
IRecordLiteralNode = interface(IAstTypedNode)
|
||||||
{$region 'private'}
|
{$region 'private'}
|
||||||
function GetFields: TArray<TRecordFieldLiteral>;
|
function GetFields: IRecordFieldList;
|
||||||
function GetGenericDefinition: IGenericRecordDefinition;
|
function GetGenericDefinition: IGenericRecordDefinition;
|
||||||
function GetScalarDefinition: IScalarRecordDefinition;
|
function GetScalarDefinition: IScalarRecordDefinition;
|
||||||
{$endregion}
|
{$endregion}
|
||||||
property Fields: TArray<TRecordFieldLiteral> read GetFields;
|
property Fields: IRecordFieldList read GetFields;
|
||||||
property GenericDefinition: IGenericRecordDefinition read GetGenericDefinition;
|
property GenericDefinition: IGenericRecordDefinition read GetGenericDefinition;
|
||||||
property ScalarDefinition: IScalarRecordDefinition read GetScalarDefinition;
|
property ScalarDefinition: IScalarRecordDefinition read GetScalarDefinition;
|
||||||
end;
|
end;
|
||||||
@@ -406,10 +447,25 @@ type
|
|||||||
property Series: IIdentifierNode read GetSeries;
|
property Series: IIdentifierNode read GetSeries;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
IParameterList = interface(INodeList<IIdentifierNode>)
|
||||||
|
end;
|
||||||
|
IArgumentList = interface(INodeList<IAstNode>)
|
||||||
|
end;
|
||||||
|
IExpressionList = interface(INodeList<IAstNode>)
|
||||||
|
end;
|
||||||
|
|
||||||
IAstVisitor = interface
|
IAstVisitor = interface
|
||||||
function VisitConstant(const Node: IConstantNode): TDataValue;
|
function VisitConstant(const Node: IConstantNode): TDataValue;
|
||||||
function VisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
function VisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
||||||
function VisitKeyword(const Node: IKeywordNode): TDataValue;
|
function VisitKeyword(const Node: IKeywordNode): TDataValue;
|
||||||
|
|
||||||
|
// List Visits
|
||||||
|
function VisitParameterList(const Node: IParameterList): TDataValue;
|
||||||
|
function VisitArgumentList(const Node: IArgumentList): TDataValue;
|
||||||
|
function VisitExpressionList(const Node: IExpressionList): TDataValue;
|
||||||
|
function VisitRecordFieldList(const Node: IRecordFieldList): TDataValue;
|
||||||
|
function VisitRecordField(const Node: IRecordFieldNode): TDataValue;
|
||||||
|
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
function VisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
||||||
@@ -451,6 +507,13 @@ type
|
|||||||
function AsConstant: IConstantNode; virtual;
|
function AsConstant: IConstantNode; virtual;
|
||||||
function AsIdentifier: IIdentifierNode; virtual;
|
function AsIdentifier: IIdentifierNode; virtual;
|
||||||
function AsKeyword: IKeywordNode; virtual;
|
function AsKeyword: IKeywordNode; virtual;
|
||||||
|
|
||||||
|
function AsParameterList: IParameterList; virtual;
|
||||||
|
function AsArgumentList: IArgumentList; virtual;
|
||||||
|
function AsExpressionList: IExpressionList; virtual;
|
||||||
|
function AsRecordFieldList: IRecordFieldList; virtual;
|
||||||
|
function AsRecordField: IRecordFieldNode; virtual;
|
||||||
|
|
||||||
function AsIfExpression: IIfExpressionNode; virtual;
|
function AsIfExpression: IIfExpressionNode; virtual;
|
||||||
function AsTernaryExpression: ITernaryExpressionNode; virtual;
|
function AsTernaryExpression: ITernaryExpressionNode; virtual;
|
||||||
function AsLambdaExpression: ILambdaExpressionNode; virtual;
|
function AsLambdaExpression: ILambdaExpressionNode; virtual;
|
||||||
@@ -490,6 +553,82 @@ type
|
|||||||
property StaticType: IStaticType read GetStaticType;
|
property StaticType: IStaticType read GetStaticType;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// --- List Implementation Bases ---
|
||||||
|
|
||||||
|
TAstNodeList<T: IAstNode> = class(TAstNode, INodeList<T>)
|
||||||
|
type
|
||||||
|
TEnumerator = class(TEnumerator<T>)
|
||||||
|
private
|
||||||
|
FArray: TArray<T>;
|
||||||
|
FIndex: NativeInt;
|
||||||
|
function GetCurrent: T; inline;
|
||||||
|
protected
|
||||||
|
function DoGetCurrent: T; override;
|
||||||
|
function DoMoveNext: Boolean; override;
|
||||||
|
public
|
||||||
|
constructor Create(const AArray: TArray<T>);
|
||||||
|
function MoveNext: Boolean; inline;
|
||||||
|
property Current: T read GetCurrent;
|
||||||
|
end;
|
||||||
|
private
|
||||||
|
FItems: TArray<T>;
|
||||||
|
function GetCount: Integer;
|
||||||
|
function GetItem(Index: Integer): T;
|
||||||
|
public
|
||||||
|
constructor Create(const AItems: TArray<T>; const AIdentity: IAstIdentity);
|
||||||
|
function GetEnumerator: TEnumerator<T>;
|
||||||
|
function ToArray: TArray<T>;
|
||||||
|
property Count: Integer read GetCount;
|
||||||
|
property Items[Index: Integer]: T read GetItem; default;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TParameterList = class(TAstNodeList<IIdentifierNode>, IParameterList)
|
||||||
|
protected
|
||||||
|
function GetKind: TAstNodeKind; override;
|
||||||
|
public
|
||||||
|
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||||
|
function AsParameterList: IParameterList; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TArgumentList = class(TAstNodeList<IAstNode>, IArgumentList)
|
||||||
|
protected
|
||||||
|
function GetKind: TAstNodeKind; override;
|
||||||
|
public
|
||||||
|
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||||
|
function AsArgumentList: IArgumentList; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TExpressionList = class(TAstNodeList<IAstNode>, IExpressionList)
|
||||||
|
protected
|
||||||
|
function GetKind: TAstNodeKind; override;
|
||||||
|
public
|
||||||
|
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||||
|
function AsExpressionList: IExpressionList; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TRecordFieldNode = class(TAstNode, IRecordFieldNode)
|
||||||
|
private
|
||||||
|
FKey: IKeywordNode;
|
||||||
|
FValue: IAstNode;
|
||||||
|
function GetKey: IKeywordNode;
|
||||||
|
function GetValue: IAstNode;
|
||||||
|
function GetKind: TAstNodeKind; override;
|
||||||
|
public
|
||||||
|
constructor Create(const AKey: IKeywordNode; const AValue: IAstNode; const AIdentity: IAstIdentity);
|
||||||
|
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||||
|
function AsRecordField: IRecordFieldNode; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TRecordFieldList = class(TAstNodeList<IRecordFieldNode>, IRecordFieldList)
|
||||||
|
protected
|
||||||
|
function GetKind: TAstNodeKind; override;
|
||||||
|
public
|
||||||
|
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||||
|
function AsRecordFieldList: IRecordFieldList; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// --- Core Nodes Implementations ---
|
||||||
|
|
||||||
TConstantNode = class(TAstTypedNode, IConstantNode)
|
TConstantNode = class(TAstTypedNode, IConstantNode)
|
||||||
private
|
private
|
||||||
FConstIdentity: IConstantIdentity; // Typed reference for fast access
|
FConstIdentity: IConstantIdentity; // Typed reference for fast access
|
||||||
@@ -574,13 +713,13 @@ type
|
|||||||
|
|
||||||
TLambdaExpressionNode = class(TAstTypedNode, ILambdaExpressionNode, IFunctionDefinition)
|
TLambdaExpressionNode = class(TAstTypedNode, ILambdaExpressionNode, IFunctionDefinition)
|
||||||
private
|
private
|
||||||
FParameters: TArray<IIdentifierNode>;
|
FParameters: IParameterList;
|
||||||
FBody: IAstNode;
|
FBody: IAstNode;
|
||||||
FLayout: IScopeLayout;
|
FLayout: IScopeLayout;
|
||||||
FDescriptor: IScopeDescriptor;
|
FDescriptor: IScopeDescriptor;
|
||||||
FUpvalues: TArray<TResolvedAddress>;
|
FUpvalues: TArray<TResolvedAddress>;
|
||||||
FHasNestedLambdas, FIsPure: Boolean;
|
FHasNestedLambdas, FIsPure: Boolean;
|
||||||
function GetParameters: TArray<IIdentifierNode>;
|
function GetParameters: IParameterList;
|
||||||
function GetBody: IAstNode;
|
function GetBody: IAstNode;
|
||||||
function GetLayout: IScopeLayout;
|
function GetLayout: IScopeLayout;
|
||||||
function GetDescriptor: IScopeDescriptor;
|
function GetDescriptor: IScopeDescriptor;
|
||||||
@@ -590,7 +729,7 @@ type
|
|||||||
function GetKind: TAstNodeKind; override;
|
function GetKind: TAstNodeKind; override;
|
||||||
public
|
public
|
||||||
constructor Create(
|
constructor Create(
|
||||||
const AParameters: TArray<IIdentifierNode>;
|
const AParameters: IParameterList;
|
||||||
const ABody: IAstNode;
|
const ABody: IAstNode;
|
||||||
const AStaticType: IStaticType;
|
const AStaticType: IStaticType;
|
||||||
const ALayout: IScopeLayout;
|
const ALayout: IScopeLayout;
|
||||||
@@ -606,12 +745,12 @@ type
|
|||||||
TFunctionCallNode = class(TAstTypedNode, IFunctionCallNode)
|
TFunctionCallNode = class(TAstTypedNode, IFunctionCallNode)
|
||||||
private
|
private
|
||||||
FCallee: IAstNode;
|
FCallee: IAstNode;
|
||||||
FArguments: TArray<IAstNode>;
|
FArguments: IArgumentList;
|
||||||
FIsTailCall: Boolean;
|
FIsTailCall: Boolean;
|
||||||
FStaticTarget: TDataValue.TFunc;
|
FStaticTarget: TDataValue.TFunc;
|
||||||
FIsTargetPure: Boolean;
|
FIsTargetPure: Boolean;
|
||||||
function GetCallee: IAstNode;
|
function GetCallee: IAstNode;
|
||||||
function GetArguments: TArray<IAstNode>;
|
function GetArguments: IArgumentList;
|
||||||
function GetIsTailCall: Boolean;
|
function GetIsTailCall: Boolean;
|
||||||
function GetStaticTarget: TDataValue.TFunc;
|
function GetStaticTarget: TDataValue.TFunc;
|
||||||
function GetIsTargetPure: Boolean;
|
function GetIsTargetPure: Boolean;
|
||||||
@@ -619,7 +758,7 @@ type
|
|||||||
public
|
public
|
||||||
constructor Create(
|
constructor Create(
|
||||||
const ACallee: IAstNode;
|
const ACallee: IAstNode;
|
||||||
const AArguments: TArray<IAstNode>;
|
const AArguments: IArgumentList;
|
||||||
const AStaticType: IStaticType;
|
const AStaticType: IStaticType;
|
||||||
const AIsTailCall: Boolean;
|
const AIsTailCall: Boolean;
|
||||||
const AStaticTarget: TDataValue.TFunc;
|
const AStaticTarget: TDataValue.TFunc;
|
||||||
@@ -633,16 +772,16 @@ type
|
|||||||
TMacroDefinitionNode = class(TAstTypedNode, IMacroDefinitionNode)
|
TMacroDefinitionNode = class(TAstTypedNode, IMacroDefinitionNode)
|
||||||
private
|
private
|
||||||
FName: IIdentifierNode;
|
FName: IIdentifierNode;
|
||||||
FParameters: TArray<IIdentifierNode>;
|
FParameters: IParameterList;
|
||||||
FBody: IAstNode;
|
FBody: IAstNode;
|
||||||
function GetName: IIdentifierNode;
|
function GetName: IIdentifierNode;
|
||||||
function GetParameters: TArray<IIdentifierNode>;
|
function GetParameters: IParameterList;
|
||||||
function GetBody: IAstNode;
|
function GetBody: IAstNode;
|
||||||
function GetKind: TAstNodeKind; override;
|
function GetKind: TAstNodeKind; override;
|
||||||
public
|
public
|
||||||
constructor Create(
|
constructor Create(
|
||||||
const AName: IIdentifierNode;
|
const AName: IIdentifierNode;
|
||||||
const AParameters: TArray<IIdentifierNode>;
|
const AParameters: IParameterList;
|
||||||
const ABody: IAstNode;
|
const ABody: IAstNode;
|
||||||
const AIdentity: IAstIdentity
|
const AIdentity: IAstIdentity
|
||||||
);
|
);
|
||||||
@@ -698,22 +837,22 @@ type
|
|||||||
|
|
||||||
TRecurNode = class(TAstTypedNode, IRecurNode)
|
TRecurNode = class(TAstTypedNode, IRecurNode)
|
||||||
private
|
private
|
||||||
FArguments: TArray<IAstNode>;
|
FArguments: IArgumentList;
|
||||||
function GetArguments: TArray<IAstNode>;
|
function GetArguments: IArgumentList;
|
||||||
function GetKind: TAstNodeKind; override;
|
function GetKind: TAstNodeKind; override;
|
||||||
public
|
public
|
||||||
constructor Create(const AArguments: TArray<IAstNode>; const AStaticType: IStaticType; const AIdentity: IAstIdentity);
|
constructor Create(const AArguments: IArgumentList; const AStaticType: IStaticType; const AIdentity: IAstIdentity);
|
||||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||||
function AsRecur: IRecurNode; override;
|
function AsRecur: IRecurNode; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TBlockExpressionNode = class(TAstTypedNode, IBlockExpressionNode)
|
TBlockExpressionNode = class(TAstTypedNode, IBlockExpressionNode)
|
||||||
private
|
private
|
||||||
FExpressions: TArray<IAstNode>;
|
FExpressions: IExpressionList;
|
||||||
function GetExpressions: TArray<IAstNode>;
|
function GetExpressions: IExpressionList;
|
||||||
function GetKind: TAstNodeKind; override;
|
function GetKind: TAstNodeKind; override;
|
||||||
public
|
public
|
||||||
constructor Create(const AExpressions: array of IAstNode; const AStaticType: IStaticType; const AIdentity: IAstIdentity);
|
constructor Create(const AExpressions: IExpressionList; const AStaticType: IStaticType; const AIdentity: IAstIdentity);
|
||||||
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
function Accept(const Visitor: IAstVisitor): TDataValue; override;
|
||||||
function AsBlockExpression: IBlockExpressionNode; override;
|
function AsBlockExpression: IBlockExpressionNode; override;
|
||||||
end;
|
end;
|
||||||
@@ -782,16 +921,16 @@ type
|
|||||||
|
|
||||||
TRecordLiteralNode = class(TAstTypedNode, IRecordLiteralNode)
|
TRecordLiteralNode = class(TAstTypedNode, IRecordLiteralNode)
|
||||||
private
|
private
|
||||||
FFields: TArray<TRecordFieldLiteral>;
|
FFields: IRecordFieldList;
|
||||||
FScalarDef: IScalarRecordDefinition;
|
FScalarDef: IScalarRecordDefinition;
|
||||||
FGenericDef: IGenericRecordDefinition;
|
FGenericDef: IGenericRecordDefinition;
|
||||||
function GetFields: TArray<TRecordFieldLiteral>;
|
function GetFields: IRecordFieldList;
|
||||||
function GetGenericDefinition: IGenericRecordDefinition;
|
function GetGenericDefinition: IGenericRecordDefinition;
|
||||||
function GetScalarDefinition: IScalarRecordDefinition;
|
function GetScalarDefinition: IScalarRecordDefinition;
|
||||||
function GetKind: TAstNodeKind; override;
|
function GetKind: TAstNodeKind; override;
|
||||||
public
|
public
|
||||||
constructor Create(
|
constructor Create(
|
||||||
const AFields: TArray<TRecordFieldLiteral>;
|
const AFields: IRecordFieldList;
|
||||||
const AScalarDef: IScalarRecordDefinition;
|
const AScalarDef: IScalarRecordDefinition;
|
||||||
const AGenericDef: IGenericRecordDefinition;
|
const AGenericDef: IGenericRecordDefinition;
|
||||||
const AStaticType: IStaticType;
|
const AStaticType: IStaticType;
|
||||||
@@ -865,14 +1004,6 @@ begin
|
|||||||
Result := Result.Substring(2);
|
Result := Result.Substring(2);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TRecordFieldLiteral }
|
|
||||||
|
|
||||||
constructor TRecordFieldLiteral.Create(const AKey: IKeywordNode; const AValue: IAstNode);
|
|
||||||
begin
|
|
||||||
Key := AKey;
|
|
||||||
Value := AValue;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TCompilerError }
|
{ TCompilerError }
|
||||||
|
|
||||||
constructor TCompilerError.Create(ALevel: TCompilerErrorLevel; const AMessage: string; const ANode: IAstNode);
|
constructor TCompilerError.Create(ALevel: TCompilerErrorLevel; const AMessage: string; const ANode: IAstNode);
|
||||||
@@ -1017,6 +1148,28 @@ function TAstNode.AsKeyword: IKeywordNode;
|
|||||||
begin
|
begin
|
||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TAstNode.AsParameterList: IParameterList;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
function TAstNode.AsArgumentList: IArgumentList;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
function TAstNode.AsExpressionList: IExpressionList;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
function TAstNode.AsRecordFieldList: IRecordFieldList;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
function TAstNode.AsRecordField: IRecordFieldNode;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
function TAstNode.AsIfExpression: IIfExpressionNode;
|
function TAstNode.AsIfExpression: IIfExpressionNode;
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Result := nil;
|
||||||
@@ -1125,6 +1278,136 @@ begin
|
|||||||
Result := Self;
|
Result := Self;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TAstNodeList<T> }
|
||||||
|
|
||||||
|
constructor TAstNodeList<T>.Create(const AItems: TArray<T>; const AIdentity: IAstIdentity);
|
||||||
|
begin
|
||||||
|
inherited Create(AIdentity);
|
||||||
|
FItems := AItems;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstNodeList<T>.GetCount: Integer;
|
||||||
|
begin
|
||||||
|
Result := Length(FItems);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstNodeList<T>.GetEnumerator: TEnumerator<T>;
|
||||||
|
begin
|
||||||
|
Result := TEnumerator.Create(FItems);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstNodeList<T>.GetItem(Index: Integer): T;
|
||||||
|
begin
|
||||||
|
Result := FItems[Index];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstNodeList<T>.ToArray: TArray<T>;
|
||||||
|
begin
|
||||||
|
Result := FItems;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TParameterList }
|
||||||
|
|
||||||
|
function TParameterList.Accept(const Visitor: IAstVisitor): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := Visitor.VisitParameterList(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TParameterList.AsParameterList: IParameterList;
|
||||||
|
begin
|
||||||
|
Result := Self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TParameterList.GetKind: TAstNodeKind;
|
||||||
|
begin
|
||||||
|
Result := akParameterList;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TArgumentList }
|
||||||
|
|
||||||
|
function TArgumentList.Accept(const Visitor: IAstVisitor): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := Visitor.VisitArgumentList(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TArgumentList.AsArgumentList: IArgumentList;
|
||||||
|
begin
|
||||||
|
Result := Self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TArgumentList.GetKind: TAstNodeKind;
|
||||||
|
begin
|
||||||
|
Result := akArgumentList;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TExpressionList }
|
||||||
|
|
||||||
|
function TExpressionList.Accept(const Visitor: IAstVisitor): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := Visitor.VisitExpressionList(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TExpressionList.AsExpressionList: IExpressionList;
|
||||||
|
begin
|
||||||
|
Result := Self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TExpressionList.GetKind: TAstNodeKind;
|
||||||
|
begin
|
||||||
|
Result := akExpressionList;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TRecordFieldNode }
|
||||||
|
|
||||||
|
constructor TRecordFieldNode.Create(const AKey: IKeywordNode; const AValue: IAstNode; const AIdentity: IAstIdentity);
|
||||||
|
begin
|
||||||
|
inherited Create(AIdentity);
|
||||||
|
FKey := AKey;
|
||||||
|
FValue := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRecordFieldNode.Accept(const Visitor: IAstVisitor): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := Visitor.VisitRecordField(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRecordFieldNode.AsRecordField: IRecordFieldNode;
|
||||||
|
begin
|
||||||
|
Result := Self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRecordFieldNode.GetKey: IKeywordNode;
|
||||||
|
begin
|
||||||
|
Result := FKey;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRecordFieldNode.GetKind: TAstNodeKind;
|
||||||
|
begin
|
||||||
|
Result := akRecordField;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRecordFieldNode.GetValue: IAstNode;
|
||||||
|
begin
|
||||||
|
Result := FValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TRecordFieldList }
|
||||||
|
|
||||||
|
function TRecordFieldList.Accept(const Visitor: IAstVisitor): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := Visitor.VisitRecordFieldList(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRecordFieldList.AsRecordFieldList: IRecordFieldList;
|
||||||
|
begin
|
||||||
|
Result := Self;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRecordFieldList.GetKind: TAstNodeKind;
|
||||||
|
begin
|
||||||
|
Result := akRecordFieldList;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TConstantNode }
|
{ TConstantNode }
|
||||||
|
|
||||||
constructor TConstantNode.Create(const AIdentity: IConstantIdentity; const AStaticType: IStaticType);
|
constructor TConstantNode.Create(const AIdentity: IConstantIdentity; const AStaticType: IStaticType);
|
||||||
@@ -1328,7 +1611,7 @@ end;
|
|||||||
{ TLambdaExpressionNode }
|
{ TLambdaExpressionNode }
|
||||||
|
|
||||||
constructor TLambdaExpressionNode.Create(
|
constructor TLambdaExpressionNode.Create(
|
||||||
const AParameters: TArray<IIdentifierNode>;
|
const AParameters: IParameterList;
|
||||||
const ABody: IAstNode;
|
const ABody: IAstNode;
|
||||||
const AStaticType: IStaticType;
|
const AStaticType: IStaticType;
|
||||||
const ALayout: IScopeLayout;
|
const ALayout: IScopeLayout;
|
||||||
@@ -1362,7 +1645,7 @@ function TLambdaExpressionNode.GetBody: IAstNode;
|
|||||||
begin
|
begin
|
||||||
Result := FBody;
|
Result := FBody;
|
||||||
end;
|
end;
|
||||||
function TLambdaExpressionNode.GetParameters: TArray<IIdentifierNode>;
|
function TLambdaExpressionNode.GetParameters: IParameterList;
|
||||||
begin
|
begin
|
||||||
Result := FParameters;
|
Result := FParameters;
|
||||||
end;
|
end;
|
||||||
@@ -1395,7 +1678,7 @@ end;
|
|||||||
|
|
||||||
constructor TFunctionCallNode.Create(
|
constructor TFunctionCallNode.Create(
|
||||||
const ACallee: IAstNode;
|
const ACallee: IAstNode;
|
||||||
const AArguments: TArray<IAstNode>;
|
const AArguments: IArgumentList;
|
||||||
const AStaticType: IStaticType;
|
const AStaticType: IStaticType;
|
||||||
const AIsTailCall: Boolean;
|
const AIsTailCall: Boolean;
|
||||||
const AStaticTarget: TDataValue.TFunc;
|
const AStaticTarget: TDataValue.TFunc;
|
||||||
@@ -1425,7 +1708,7 @@ function TFunctionCallNode.GetCallee: IAstNode;
|
|||||||
begin
|
begin
|
||||||
Result := FCallee;
|
Result := FCallee;
|
||||||
end;
|
end;
|
||||||
function TFunctionCallNode.GetArguments: TArray<IAstNode>;
|
function TFunctionCallNode.GetArguments: IArgumentList;
|
||||||
begin
|
begin
|
||||||
Result := FArguments;
|
Result := FArguments;
|
||||||
end;
|
end;
|
||||||
@@ -1450,7 +1733,7 @@ end;
|
|||||||
|
|
||||||
constructor TMacroDefinitionNode.Create(
|
constructor TMacroDefinitionNode.Create(
|
||||||
const AName: IIdentifierNode;
|
const AName: IIdentifierNode;
|
||||||
const AParameters: TArray<IIdentifierNode>;
|
const AParameters: IParameterList;
|
||||||
const ABody: IAstNode;
|
const ABody: IAstNode;
|
||||||
const AIdentity: IAstIdentity
|
const AIdentity: IAstIdentity
|
||||||
);
|
);
|
||||||
@@ -1475,7 +1758,7 @@ function TMacroDefinitionNode.GetName: IIdentifierNode;
|
|||||||
begin
|
begin
|
||||||
Result := FName;
|
Result := FName;
|
||||||
end;
|
end;
|
||||||
function TMacroDefinitionNode.GetParameters: TArray<IIdentifierNode>;
|
function TMacroDefinitionNode.GetParameters: IParameterList;
|
||||||
begin
|
begin
|
||||||
Result := FParameters;
|
Result := FParameters;
|
||||||
end;
|
end;
|
||||||
@@ -1606,7 +1889,7 @@ end;
|
|||||||
|
|
||||||
{ TRecurNode }
|
{ TRecurNode }
|
||||||
|
|
||||||
constructor TRecurNode.Create(const AArguments: TArray<IAstNode>; const AStaticType: IStaticType; const AIdentity: IAstIdentity);
|
constructor TRecurNode.Create(const AArguments: IArgumentList; const AStaticType: IStaticType; const AIdentity: IAstIdentity);
|
||||||
begin
|
begin
|
||||||
inherited Create(AStaticType, AIdentity);
|
inherited Create(AStaticType, AIdentity);
|
||||||
FArguments := AArguments;
|
FArguments := AArguments;
|
||||||
@@ -1622,7 +1905,7 @@ begin
|
|||||||
Result := Self;
|
Result := Self;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TRecurNode.GetArguments: TArray<IAstNode>;
|
function TRecurNode.GetArguments: IArgumentList;
|
||||||
begin
|
begin
|
||||||
Result := FArguments;
|
Result := FArguments;
|
||||||
end;
|
end;
|
||||||
@@ -1633,18 +1916,10 @@ end;
|
|||||||
|
|
||||||
{ TBlockExpressionNode }
|
{ TBlockExpressionNode }
|
||||||
|
|
||||||
constructor TBlockExpressionNode.Create(
|
constructor TBlockExpressionNode.Create(const AExpressions: IExpressionList; const AStaticType: IStaticType; const AIdentity: IAstIdentity);
|
||||||
const AExpressions: array of IAstNode;
|
|
||||||
const AStaticType: IStaticType;
|
|
||||||
const AIdentity: IAstIdentity
|
|
||||||
);
|
|
||||||
var
|
|
||||||
i: Integer;
|
|
||||||
begin
|
begin
|
||||||
inherited Create(AStaticType, AIdentity);
|
inherited Create(AStaticType, AIdentity);
|
||||||
SetLength(FExpressions, Length(AExpressions));
|
FExpressions := AExpressions;
|
||||||
for i := 0 to High(AExpressions) do
|
|
||||||
FExpressions[i] := AExpressions[i];
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TBlockExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue;
|
function TBlockExpressionNode.Accept(const Visitor: IAstVisitor): TDataValue;
|
||||||
@@ -1657,7 +1932,7 @@ begin
|
|||||||
Result := Self;
|
Result := Self;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TBlockExpressionNode.GetExpressions: TArray<IAstNode>;
|
function TBlockExpressionNode.GetExpressions: IExpressionList;
|
||||||
begin
|
begin
|
||||||
Result := FExpressions;
|
Result := FExpressions;
|
||||||
end;
|
end;
|
||||||
@@ -1813,7 +2088,7 @@ end;
|
|||||||
{ TRecordLiteralNode }
|
{ TRecordLiteralNode }
|
||||||
|
|
||||||
constructor TRecordLiteralNode.Create(
|
constructor TRecordLiteralNode.Create(
|
||||||
const AFields: TArray<TRecordFieldLiteral>;
|
const AFields: IRecordFieldList;
|
||||||
const AScalarDef: IScalarRecordDefinition;
|
const AScalarDef: IScalarRecordDefinition;
|
||||||
const AGenericDef: IGenericRecordDefinition;
|
const AGenericDef: IGenericRecordDefinition;
|
||||||
const AStaticType: IStaticType;
|
const AStaticType: IStaticType;
|
||||||
@@ -1836,7 +2111,7 @@ begin
|
|||||||
Result := Self;
|
Result := Self;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TRecordLiteralNode.GetFields: TArray<TRecordFieldLiteral>;
|
function TRecordLiteralNode.GetFields: IRecordFieldList;
|
||||||
begin
|
begin
|
||||||
Result := FFields;
|
Result := FFields;
|
||||||
end;
|
end;
|
||||||
@@ -1944,4 +2219,33 @@ begin
|
|||||||
Result := akNop;
|
Result := akNop;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
constructor TAstNodeList<T>.TEnumerator.Create(const AArray: TArray<T>);
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FArray := AArray;
|
||||||
|
FIndex := -1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstNodeList<T>.TEnumerator.DoGetCurrent: T;
|
||||||
|
begin
|
||||||
|
Result := Current;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstNodeList<T>.TEnumerator.DoMoveNext: Boolean;
|
||||||
|
begin
|
||||||
|
Result := MoveNext;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstNodeList<T>.TEnumerator.GetCurrent: T;
|
||||||
|
begin
|
||||||
|
Result := FArray[FIndex];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstNodeList<T>.TEnumerator.MoveNext: Boolean;
|
||||||
|
begin
|
||||||
|
Result := FIndex < High(FArray);
|
||||||
|
if Result then
|
||||||
|
Inc(FIndex);
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
+88
-83
@@ -4,6 +4,7 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
System.SysUtils,
|
System.SysUtils,
|
||||||
|
Myc.Data.Value,
|
||||||
Myc.Ast.Nodes,
|
Myc.Ast.Nodes,
|
||||||
Myc.Ast.Visitor;
|
Myc.Ast.Visitor;
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ var
|
|||||||
atom ::= number | string | identifier | keyword
|
atom ::= number | string | identifier | keyword
|
||||||
|
|
||||||
(* ---------------------------------------------------------------------- *)
|
(* ---------------------------------------------------------------------- *)
|
||||||
(* ---- Reader-Macros (Syntactic Sugar) ---- *)
|
(* ---- Reader-Macros (Syntactic Sugar) ---- *)
|
||||||
(* ---------------------------------------------------------------------- *)
|
(* ---------------------------------------------------------------------- *)
|
||||||
reader_macro ::= "'" expression (* (quote ...) *)
|
reader_macro ::= "'" expression (* (quote ...) *)
|
||||||
| "`" expression (* (quasiquote ...) *)
|
| "`" expression (* (quasiquote ...) *)
|
||||||
@@ -43,7 +44,7 @@ var
|
|||||||
| "~@" expression (* (unquote-splicing ...) *)
|
| "~@" expression (* (unquote-splicing ...) *)
|
||||||
|
|
||||||
(* ---------------------------------------------------------------------- *)
|
(* ---------------------------------------------------------------------- *)
|
||||||
(* ---- Lists (S-Expressions) ---- *)
|
(* ---- Lists (S-Expressions) ---- *)
|
||||||
(* ---------------------------------------------------------------------- *)
|
(* ---------------------------------------------------------------------- *)
|
||||||
list ::= "(" list_content ")"
|
list ::= "(" list_content ")"
|
||||||
list_content ::= special_form | function_call
|
list_content ::= special_form | function_call
|
||||||
@@ -62,13 +63,13 @@ var
|
|||||||
function_call ::= expression expression*
|
function_call ::= expression expression*
|
||||||
|
|
||||||
(* ---------------------------------------------------------------------- *)
|
(* ---------------------------------------------------------------------- *)
|
||||||
(* ---- Parameter Lists and Records ---- *)
|
(* ---- Parameter Lists and Records ---- *)
|
||||||
(* ---------------------------------------------------------------------- *)
|
(* ---------------------------------------------------------------------- *)
|
||||||
parameter_list ::= "[" identifier* "]"
|
parameter_list ::= "[" identifier* "]"
|
||||||
record_literal ::= "{" (keyword expression)* "}"
|
record_literal ::= "{" (keyword expression)* "}"
|
||||||
|
|
||||||
(* ---------------------------------------------------------------------- *)
|
(* ---------------------------------------------------------------------- *)
|
||||||
(* ---- Terminals (Lexer Tokens) ---- *)
|
(* ---- Terminals (Lexer Tokens) ---- *)
|
||||||
(* ---------------------------------------------------------------------- *)
|
(* ---------------------------------------------------------------------- *)
|
||||||
number ::= ["-"] digit+ ["." digit+]
|
number ::= ["-"] digit+ ["." digit+]
|
||||||
string ::= '"' ( ? any char except \ or " ? | '\' ( '"' | '\' | 'n' | 'r' | 't' ) )* '"'
|
string ::= '"' ( ? any char except \ or " ? | '\' ( '"' | '\' | 'n' | 'r' | 't' ) )* '"'
|
||||||
@@ -94,7 +95,6 @@ uses
|
|||||||
System.Character,
|
System.Character,
|
||||||
System.Math,
|
System.Math,
|
||||||
Myc.Data.Scalar,
|
Myc.Data.Scalar,
|
||||||
Myc.Data.Value,
|
|
||||||
Myc.Data.Keyword,
|
Myc.Data.Keyword,
|
||||||
Myc.Ast,
|
Myc.Ast,
|
||||||
Myc.Ast.Identities;
|
Myc.Ast.Identities;
|
||||||
@@ -197,6 +197,14 @@ type
|
|||||||
procedure VisitConstant(const Node: IConstantNode); override;
|
procedure VisitConstant(const Node: IConstantNode); override;
|
||||||
procedure VisitIdentifier(const Node: IIdentifierNode); override;
|
procedure VisitIdentifier(const Node: IIdentifierNode); override;
|
||||||
procedure VisitKeyword(const Node: IKeywordNode); override;
|
procedure VisitKeyword(const Node: IKeywordNode); override;
|
||||||
|
|
||||||
|
// List Visitors
|
||||||
|
procedure VisitParameterList(const Node: IParameterList); override;
|
||||||
|
procedure VisitArgumentList(const Node: IArgumentList); override;
|
||||||
|
procedure VisitExpressionList(const Node: IExpressionList); override;
|
||||||
|
procedure VisitRecordFieldList(const Node: IRecordFieldList); override;
|
||||||
|
procedure VisitRecordField(const Node: IRecordFieldNode); override;
|
||||||
|
|
||||||
procedure VisitIfExpression(const Node: IIfExpressionNode); override;
|
procedure VisitIfExpression(const Node: IIfExpressionNode); override;
|
||||||
procedure VisitTernaryExpression(const Node: ITernaryExpressionNode); override;
|
procedure VisitTernaryExpression(const Node: ITernaryExpressionNode); override;
|
||||||
procedure VisitLambdaExpression(const Node: ILambdaExpressionNode); override;
|
procedure VisitLambdaExpression(const Node: ILambdaExpressionNode); override;
|
||||||
@@ -315,7 +323,6 @@ var
|
|||||||
startPos: Integer;
|
startPos: Integer;
|
||||||
begin
|
begin
|
||||||
startPos := FCurrentPos;
|
startPos := FCurrentPos;
|
||||||
// Reader macro characters and comments are now also delimiters for identifiers.
|
|
||||||
while (Peek <> #0) and (not (Peek.IsWhiteSpace or CharInSet(Peek, ['(', ')', '[', ']', '{', '}', '''', '`', '~', ';']))) do
|
while (Peek <> #0) and (not (Peek.IsWhiteSpace or CharInSet(Peek, ['(', ')', '[', ']', '{', '}', '''', '`', '~', ';']))) do
|
||||||
Advance;
|
Advance;
|
||||||
Result := Copy(FSource, startPos, FCurrentPos - startPos);
|
Result := Copy(FSource, startPos, FCurrentPos - startPos);
|
||||||
@@ -544,7 +551,6 @@ begin
|
|||||||
if FCurrentToken.Kind <> tkIdentifier then
|
if FCurrentToken.Kind <> tkIdentifier then
|
||||||
Error('Syntax Error: Expected identifier in parameter list.');
|
Error('Syntax Error: Expected identifier in parameter list.');
|
||||||
|
|
||||||
// Pass Location to Factory
|
|
||||||
params.Add(TAst.Identifier(FCurrentToken.Text, FCurrentToken.GetLocation));
|
params.Add(TAst.Identifier(FCurrentToken.Text, FCurrentToken.GetLocation));
|
||||||
NextToken;
|
NextToken;
|
||||||
end;
|
end;
|
||||||
@@ -557,14 +563,15 @@ end;
|
|||||||
|
|
||||||
function TParser.ParseRecordLiteral: IAstNode;
|
function TParser.ParseRecordLiteral: IAstNode;
|
||||||
var
|
var
|
||||||
fields: TList<TRecordFieldLiteral>;
|
fields: TList<IRecordFieldNode>;
|
||||||
fieldName: string;
|
fieldName: string;
|
||||||
fieldValue: IAstNode;
|
fieldValue: IAstNode;
|
||||||
keyToken: TToken;
|
keyToken: TToken;
|
||||||
|
keyNode: IKeywordNode;
|
||||||
begin
|
begin
|
||||||
var startLoc := FCurrentToken.GetLocation;
|
var startLoc := FCurrentToken.GetLocation;
|
||||||
Consume(tkLeftBrace);
|
Consume(tkLeftBrace);
|
||||||
fields := TList<TRecordFieldLiteral>.Create;
|
fields := TList<IRecordFieldNode>.Create;
|
||||||
try
|
try
|
||||||
while FCurrentToken.Kind <> tkRightBrace do
|
while FCurrentToken.Kind <> tkRightBrace do
|
||||||
begin
|
begin
|
||||||
@@ -576,13 +583,15 @@ begin
|
|||||||
|
|
||||||
keyToken := FCurrentToken;
|
keyToken := FCurrentToken;
|
||||||
fieldName := FCurrentToken.Text;
|
fieldName := FCurrentToken.Text;
|
||||||
|
keyNode := TAst.Keyword(fieldName, keyToken.GetLocation);
|
||||||
NextToken;
|
NextToken;
|
||||||
|
|
||||||
if FCurrentToken.Kind = tkRightBrace then
|
if FCurrentToken.Kind = tkRightBrace then
|
||||||
Error('Syntax Error: Missing value for key ' + fieldName + ' in record literal.');
|
Error('Syntax Error: Missing value for key ' + fieldName + ' in record literal.');
|
||||||
|
|
||||||
fieldValue := ParseExpression.Node;
|
fieldValue := ParseExpression.Node;
|
||||||
|
|
||||||
fields.Add(TRecordFieldLiteral.Create(TAst.Keyword(fieldName, keyToken.GetLocation), fieldValue));
|
fields.Add(TAst.RecordField(keyNode, fieldValue, keyToken.GetLocation));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Result := TAst.RecordLiteral(fields.ToArray, startLoc);
|
Result := TAst.RecordLiteral(fields.ToArray, startLoc);
|
||||||
@@ -863,6 +872,63 @@ begin
|
|||||||
Append(':' + Node.Value.Name);
|
Append(':' + Node.Value.Name);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// --- List Visitors Implementation ---
|
||||||
|
|
||||||
|
procedure TPrettyPrintVisitor.VisitParameterList(const Node: IParameterList);
|
||||||
|
begin
|
||||||
|
Append('[');
|
||||||
|
for var i := 0 to Node.Count - 1 do
|
||||||
|
begin
|
||||||
|
if i > 0 then
|
||||||
|
Append(' ');
|
||||||
|
Node[i].Accept(Self);
|
||||||
|
end;
|
||||||
|
Append(']');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPrettyPrintVisitor.VisitArgumentList(const Node: IArgumentList);
|
||||||
|
begin
|
||||||
|
// Argument list does not have brackets of its own in Lisp call syntax
|
||||||
|
for var i := 0 to Node.Count - 1 do
|
||||||
|
begin
|
||||||
|
Append(' '); // Space before each argument
|
||||||
|
Node[i].Accept(Self);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPrettyPrintVisitor.VisitExpressionList(const Node: IExpressionList);
|
||||||
|
begin
|
||||||
|
Indent;
|
||||||
|
for var item in Node do
|
||||||
|
begin
|
||||||
|
NewLine;
|
||||||
|
item.Accept(Self);
|
||||||
|
end;
|
||||||
|
Unindent;
|
||||||
|
NewLine;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPrettyPrintVisitor.VisitRecordFieldList(const Node: IRecordFieldList);
|
||||||
|
begin
|
||||||
|
Indent;
|
||||||
|
for var item in Node do
|
||||||
|
begin
|
||||||
|
NewLine;
|
||||||
|
item.Accept(Self);
|
||||||
|
end;
|
||||||
|
Unindent;
|
||||||
|
NewLine;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPrettyPrintVisitor.VisitRecordField(const Node: IRecordFieldNode);
|
||||||
|
begin
|
||||||
|
Node.Key.Accept(Self);
|
||||||
|
Append(' ');
|
||||||
|
Node.Value.Accept(Self);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// --- Node Visitors ---
|
||||||
|
|
||||||
procedure TPrettyPrintVisitor.VisitIfExpression(const Node: IIfExpressionNode);
|
procedure TPrettyPrintVisitor.VisitIfExpression(const Node: IIfExpressionNode);
|
||||||
begin
|
begin
|
||||||
Append('(if ');
|
Append('(if ');
|
||||||
@@ -895,21 +961,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPrettyPrintVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode);
|
procedure TPrettyPrintVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode);
|
||||||
var
|
|
||||||
sb: TStringBuilder;
|
|
||||||
begin
|
begin
|
||||||
sb := TStringBuilder.Create;
|
Append('(fn ');
|
||||||
try
|
Node.Parameters.Accept(Self);
|
||||||
for var param in Node.Parameters do
|
|
||||||
sb.Append(param.Name + ' ');
|
|
||||||
if sb.Length > 0 then
|
|
||||||
sb.Remove(sb.Length - 1, 1);
|
|
||||||
|
|
||||||
Append('(fn [' + sb.ToString + ']');
|
|
||||||
finally
|
|
||||||
sb.Free;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Indent;
|
Indent;
|
||||||
NewLine;
|
NewLine;
|
||||||
Node.Body.Accept(Self);
|
Node.Body.Accept(Self);
|
||||||
@@ -919,21 +973,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPrettyPrintVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode);
|
procedure TPrettyPrintVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode);
|
||||||
var
|
|
||||||
sb: TStringBuilder;
|
|
||||||
begin
|
begin
|
||||||
sb := TStringBuilder.Create;
|
Append('(defmacro ');
|
||||||
try
|
Node.Name.Accept(Self);
|
||||||
for var param in Node.Parameters do
|
Append(' ');
|
||||||
sb.Append(param.Name + ' ');
|
Node.Parameters.Accept(Self);
|
||||||
if sb.Length > 0 then
|
|
||||||
sb.Remove(sb.Length - 1, 1);
|
|
||||||
|
|
||||||
Append('(defmacro ' + Node.Name.Name + ' [' + sb.ToString + ']');
|
|
||||||
finally
|
|
||||||
sb.Free;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Indent;
|
Indent;
|
||||||
NewLine;
|
NewLine;
|
||||||
Node.Body.Accept(Self);
|
Node.Body.Accept(Self);
|
||||||
@@ -961,10 +1005,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPrettyPrintVisitor.VisitFunctionCall(const Node: IFunctionCallNode);
|
procedure TPrettyPrintVisitor.VisitFunctionCall(const Node: IFunctionCallNode);
|
||||||
var
|
|
||||||
arg: IAstNode;
|
|
||||||
begin
|
begin
|
||||||
if (Node.Callee.Kind = akIdentifier) and (Node.Callee.AsIdentifier.Name = 'quote') and (Length(Node.Arguments) = 1) then
|
if (Node.Callee.Kind = akIdentifier) and (Node.Callee.AsIdentifier.Name = 'quote') and (Node.Arguments.Count = 1) then
|
||||||
begin
|
begin
|
||||||
Append('''');
|
Append('''');
|
||||||
Node.Arguments[0].Accept(Self);
|
Node.Arguments[0].Accept(Self);
|
||||||
@@ -973,15 +1015,7 @@ begin
|
|||||||
|
|
||||||
Append('(');
|
Append('(');
|
||||||
Node.Callee.Accept(Self);
|
Node.Callee.Accept(Self);
|
||||||
|
Node.Arguments.Accept(Self); // Prints separated by space
|
||||||
Indent;
|
|
||||||
for arg in Node.Arguments do
|
|
||||||
begin
|
|
||||||
Append(' ');
|
|
||||||
arg.Accept(Self);
|
|
||||||
end;
|
|
||||||
Unindent;
|
|
||||||
|
|
||||||
Append(')');
|
Append(')');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -991,34 +1025,16 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPrettyPrintVisitor.VisitRecurNode(const Node: IRecurNode);
|
procedure TPrettyPrintVisitor.VisitRecurNode(const Node: IRecurNode);
|
||||||
var
|
|
||||||
arg: IAstNode;
|
|
||||||
begin
|
begin
|
||||||
Append('(recur');
|
Append('(recur');
|
||||||
Indent;
|
Node.Arguments.Accept(Self);
|
||||||
for arg in Node.Arguments do
|
|
||||||
begin
|
|
||||||
Append(' ');
|
|
||||||
arg.Accept(Self);
|
|
||||||
end;
|
|
||||||
Unindent;
|
|
||||||
|
|
||||||
Append(')');
|
Append(')');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPrettyPrintVisitor.VisitBlockExpression(const Node: IBlockExpressionNode);
|
procedure TPrettyPrintVisitor.VisitBlockExpression(const Node: IBlockExpressionNode);
|
||||||
var
|
|
||||||
expr: IAstNode;
|
|
||||||
begin
|
begin
|
||||||
Append('(do');
|
Append('(do');
|
||||||
Indent;
|
Node.Expressions.Accept(Self);
|
||||||
for expr in Node.Expressions do
|
|
||||||
begin
|
|
||||||
NewLine;
|
|
||||||
expr.Accept(Self);
|
|
||||||
end;
|
|
||||||
Unindent;
|
|
||||||
NewLine;
|
|
||||||
Append(')');
|
Append(')');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -1062,26 +1078,15 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPrettyPrintVisitor.VisitRecordLiteral(const Node: IRecordLiteralNode);
|
procedure TPrettyPrintVisitor.VisitRecordLiteral(const Node: IRecordLiteralNode);
|
||||||
var
|
|
||||||
field: TRecordFieldLiteral;
|
|
||||||
begin
|
begin
|
||||||
if Length(Node.Fields) = 0 then
|
if Node.Fields.Count = 0 then
|
||||||
begin
|
begin
|
||||||
Append('{}');
|
Append('{}');
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Append('{');
|
Append('{');
|
||||||
Indent;
|
Node.Fields.Accept(Self);
|
||||||
for field in Node.Fields do
|
|
||||||
begin
|
|
||||||
NewLine;
|
|
||||||
Append(':' + field.Key.Value.Name);
|
|
||||||
Append(' ');
|
|
||||||
field.Value.Accept(Self);
|
|
||||||
end;
|
|
||||||
Unindent;
|
|
||||||
NewLine;
|
|
||||||
Append('}');
|
Append('}');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
+310
-184
@@ -9,7 +9,7 @@ uses
|
|||||||
Myc.Ast,
|
Myc.Ast,
|
||||||
Myc.Ast.Types,
|
Myc.Ast.Types,
|
||||||
Myc.Ast.Nodes,
|
Myc.Ast.Nodes,
|
||||||
Myc.Ast.Identities; // Needed for identity casting
|
Myc.Ast.Identities;
|
||||||
|
|
||||||
type
|
type
|
||||||
TAstVisitor<T> = class abstract(TInterfacedObject, IAstVisitor)
|
TAstVisitor<T> = class abstract(TInterfacedObject, IAstVisitor)
|
||||||
@@ -18,6 +18,13 @@ type
|
|||||||
function IAstVisitor.VisitConstant = DoVisitConstant;
|
function IAstVisitor.VisitConstant = DoVisitConstant;
|
||||||
function IAstVisitor.VisitIdentifier = DoVisitIdentifier;
|
function IAstVisitor.VisitIdentifier = DoVisitIdentifier;
|
||||||
function IAstVisitor.VisitKeyword = DoVisitKeyword;
|
function IAstVisitor.VisitKeyword = DoVisitKeyword;
|
||||||
|
|
||||||
|
function IAstVisitor.VisitParameterList = DoVisitParameterList;
|
||||||
|
function IAstVisitor.VisitArgumentList = DoVisitArgumentList;
|
||||||
|
function IAstVisitor.VisitExpressionList = DoVisitExpressionList;
|
||||||
|
function IAstVisitor.VisitRecordFieldList = DoVisitRecordFieldList;
|
||||||
|
function IAstVisitor.VisitRecordField = DoVisitRecordField;
|
||||||
|
|
||||||
function IAstVisitor.VisitIfExpression = DoVisitIfExpression;
|
function IAstVisitor.VisitIfExpression = DoVisitIfExpression;
|
||||||
function IAstVisitor.VisitTernaryExpression = DoVisitTernaryExpression;
|
function IAstVisitor.VisitTernaryExpression = DoVisitTernaryExpression;
|
||||||
function IAstVisitor.VisitLambdaExpression = DoVisitLambdaExpression;
|
function IAstVisitor.VisitLambdaExpression = DoVisitLambdaExpression;
|
||||||
@@ -43,6 +50,13 @@ type
|
|||||||
function DoVisitConstant(const Node: IConstantNode): TDataValue;
|
function DoVisitConstant(const Node: IConstantNode): TDataValue;
|
||||||
function DoVisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
function DoVisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
||||||
function DoVisitKeyword(const Node: IKeywordNode): TDataValue;
|
function DoVisitKeyword(const Node: IKeywordNode): TDataValue;
|
||||||
|
|
||||||
|
function DoVisitParameterList(const Node: IParameterList): TDataValue;
|
||||||
|
function DoVisitArgumentList(const Node: IArgumentList): TDataValue;
|
||||||
|
function DoVisitExpressionList(const Node: IExpressionList): TDataValue;
|
||||||
|
function DoVisitRecordFieldList(const Node: IRecordFieldList): TDataValue;
|
||||||
|
function DoVisitRecordField(const Node: IRecordFieldNode): TDataValue;
|
||||||
|
|
||||||
function DoVisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
function DoVisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||||
function DoVisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
function DoVisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
||||||
function DoVisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
function DoVisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
||||||
@@ -71,6 +85,13 @@ type
|
|||||||
function VisitConstant(const Node: IConstantNode): T; virtual; abstract;
|
function VisitConstant(const Node: IConstantNode): T; virtual; abstract;
|
||||||
function VisitIdentifier(const Node: IIdentifierNode): T; virtual; abstract;
|
function VisitIdentifier(const Node: IIdentifierNode): T; virtual; abstract;
|
||||||
function VisitKeyword(const Node: IKeywordNode): T; virtual; abstract;
|
function VisitKeyword(const Node: IKeywordNode): T; virtual; abstract;
|
||||||
|
|
||||||
|
function VisitParameterList(const Node: IParameterList): T; virtual; abstract;
|
||||||
|
function VisitArgumentList(const Node: IArgumentList): T; virtual; abstract;
|
||||||
|
function VisitExpressionList(const Node: IExpressionList): T; virtual; abstract;
|
||||||
|
function VisitRecordFieldList(const Node: IRecordFieldList): T; virtual; abstract;
|
||||||
|
function VisitRecordField(const Node: IRecordFieldNode): T; virtual; abstract;
|
||||||
|
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): T; virtual; abstract;
|
function VisitIfExpression(const Node: IIfExpressionNode): T; virtual; abstract;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): T; virtual; abstract;
|
function VisitTernaryExpression(const Node: ITernaryExpressionNode): T; virtual; abstract;
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): T; virtual; abstract;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): T; virtual; abstract;
|
||||||
@@ -95,12 +116,16 @@ type
|
|||||||
|
|
||||||
TAstTransformer = class abstract(TAstVisitor<IAstNode>)
|
TAstTransformer = class abstract(TAstVisitor<IAstNode>)
|
||||||
protected
|
protected
|
||||||
function AcceptParameters(const Nodes: TArray<IIdentifierNode>): TArray<IIdentifierNode>;
|
|
||||||
function AcceptNodes(const Nodes: TArray<IAstNode>; const AcceptProc: TFunc<Integer, IAstNode, IAstNode> = nil): TArray<IAstNode>;
|
|
||||||
|
|
||||||
function VisitConstant(const Node: IConstantNode): IAstNode; override;
|
function VisitConstant(const Node: IConstantNode): IAstNode; override;
|
||||||
function VisitIdentifier(const Node: IIdentifierNode): IAstNode; override;
|
function VisitIdentifier(const Node: IIdentifierNode): IAstNode; override;
|
||||||
function VisitKeyword(const Node: IKeywordNode): IAstNode; override;
|
function VisitKeyword(const Node: IKeywordNode): IAstNode; override;
|
||||||
|
|
||||||
|
function VisitParameterList(const Node: IParameterList): IAstNode; override;
|
||||||
|
function VisitArgumentList(const Node: IArgumentList): IAstNode; override;
|
||||||
|
function VisitExpressionList(const Node: IExpressionList): IAstNode; override;
|
||||||
|
function VisitRecordFieldList(const Node: IRecordFieldList): IAstNode; override;
|
||||||
|
function VisitRecordField(const Node: IRecordFieldNode): IAstNode; override;
|
||||||
|
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): IAstNode; override;
|
function VisitIfExpression(const Node: IIfExpressionNode): IAstNode; override;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode; override;
|
function VisitTernaryExpression(const Node: ITernaryExpressionNode): IAstNode; override;
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode; override;
|
||||||
@@ -129,6 +154,11 @@ type
|
|||||||
function IAstVisitor.VisitConstant = DoVisitConstant;
|
function IAstVisitor.VisitConstant = DoVisitConstant;
|
||||||
function IAstVisitor.VisitIdentifier = DoVisitIdentifier;
|
function IAstVisitor.VisitIdentifier = DoVisitIdentifier;
|
||||||
function IAstVisitor.VisitKeyword = DoVisitKeyword;
|
function IAstVisitor.VisitKeyword = DoVisitKeyword;
|
||||||
|
function IAstVisitor.VisitParameterList = DoVisitParameterList;
|
||||||
|
function IAstVisitor.VisitArgumentList = DoVisitArgumentList;
|
||||||
|
function IAstVisitor.VisitExpressionList = DoVisitExpressionList;
|
||||||
|
function IAstVisitor.VisitRecordFieldList = DoVisitRecordFieldList;
|
||||||
|
function IAstVisitor.VisitRecordField = DoVisitRecordField;
|
||||||
function IAstVisitor.VisitIfExpression = DoVisitIfExpression;
|
function IAstVisitor.VisitIfExpression = DoVisitIfExpression;
|
||||||
function IAstVisitor.VisitTernaryExpression = DoVisitTernaryExpression;
|
function IAstVisitor.VisitTernaryExpression = DoVisitTernaryExpression;
|
||||||
function IAstVisitor.VisitLambdaExpression = DoVisitLambdaExpression;
|
function IAstVisitor.VisitLambdaExpression = DoVisitLambdaExpression;
|
||||||
@@ -154,6 +184,11 @@ type
|
|||||||
function DoVisitConstant(const Node: IConstantNode): TDataValue;
|
function DoVisitConstant(const Node: IConstantNode): TDataValue;
|
||||||
function DoVisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
function DoVisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
||||||
function DoVisitKeyword(const Node: IKeywordNode): TDataValue;
|
function DoVisitKeyword(const Node: IKeywordNode): TDataValue;
|
||||||
|
function DoVisitParameterList(const Node: IParameterList): TDataValue;
|
||||||
|
function DoVisitArgumentList(const Node: IArgumentList): TDataValue;
|
||||||
|
function DoVisitExpressionList(const Node: IExpressionList): TDataValue;
|
||||||
|
function DoVisitRecordFieldList(const Node: IRecordFieldList): TDataValue;
|
||||||
|
function DoVisitRecordField(const Node: IRecordFieldNode): TDataValue;
|
||||||
function DoVisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
function DoVisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||||
function DoVisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
function DoVisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
||||||
function DoVisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
function DoVisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
||||||
@@ -183,6 +218,13 @@ type
|
|||||||
procedure VisitConstant(const Node: IConstantNode); virtual;
|
procedure VisitConstant(const Node: IConstantNode); virtual;
|
||||||
procedure VisitIdentifier(const Node: IIdentifierNode); virtual;
|
procedure VisitIdentifier(const Node: IIdentifierNode); virtual;
|
||||||
procedure VisitKeyword(const Node: IKeywordNode); virtual;
|
procedure VisitKeyword(const Node: IKeywordNode); virtual;
|
||||||
|
|
||||||
|
procedure VisitParameterList(const Node: IParameterList); virtual;
|
||||||
|
procedure VisitArgumentList(const Node: IArgumentList); virtual;
|
||||||
|
procedure VisitExpressionList(const Node: IExpressionList); virtual;
|
||||||
|
procedure VisitRecordFieldList(const Node: IRecordFieldList); virtual;
|
||||||
|
procedure VisitRecordField(const Node: IRecordFieldNode); virtual;
|
||||||
|
|
||||||
procedure VisitIfExpression(const Node: IIfExpressionNode); virtual;
|
procedure VisitIfExpression(const Node: IIfExpressionNode); virtual;
|
||||||
procedure VisitTernaryExpression(const Node: ITernaryExpressionNode); virtual;
|
procedure VisitTernaryExpression(const Node: ITernaryExpressionNode); virtual;
|
||||||
procedure VisitLambdaExpression(const Node: ILambdaExpressionNode); virtual;
|
procedure VisitLambdaExpression(const Node: ILambdaExpressionNode); virtual;
|
||||||
@@ -207,7 +249,7 @@ type
|
|||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
{ TAstVisitor }
|
{ TAstVisitor<T> }
|
||||||
|
|
||||||
function TAstVisitor<T>.Accept(const Node: IAstNode): T;
|
function TAstVisitor<T>.Accept(const Node: IAstNode): T;
|
||||||
begin
|
begin
|
||||||
@@ -217,205 +259,122 @@ begin
|
|||||||
Result := Default(T);
|
Result := Default(T);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TAstVisitor<T> }
|
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitConstant(const Node: IConstantNode): TDataValue;
|
function TAstVisitor<T>.DoVisitConstant(const Node: IConstantNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitConstant(Node));
|
Result := TDataValue.FromGeneric<T>(VisitConstant(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
function TAstVisitor<T>.DoVisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitIdentifier(Node));
|
Result := TDataValue.FromGeneric<T>(VisitIdentifier(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitKeyword(const Node: IKeywordNode): TDataValue;
|
function TAstVisitor<T>.DoVisitKeyword(const Node: IKeywordNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitKeyword(Node));
|
Result := TDataValue.FromGeneric<T>(VisitKeyword(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TAstVisitor<T>.DoVisitParameterList(const Node: IParameterList): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := TDataValue.FromGeneric<T>(VisitParameterList(Node));
|
||||||
|
end;
|
||||||
|
function TAstVisitor<T>.DoVisitArgumentList(const Node: IArgumentList): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := TDataValue.FromGeneric<T>(VisitArgumentList(Node));
|
||||||
|
end;
|
||||||
|
function TAstVisitor<T>.DoVisitExpressionList(const Node: IExpressionList): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := TDataValue.FromGeneric<T>(VisitExpressionList(Node));
|
||||||
|
end;
|
||||||
|
function TAstVisitor<T>.DoVisitRecordFieldList(const Node: IRecordFieldList): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := TDataValue.FromGeneric<T>(VisitRecordFieldList(Node));
|
||||||
|
end;
|
||||||
|
function TAstVisitor<T>.DoVisitRecordField(const Node: IRecordFieldNode): TDataValue;
|
||||||
|
begin
|
||||||
|
Result := TDataValue.FromGeneric<T>(VisitRecordField(Node));
|
||||||
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
function TAstVisitor<T>.DoVisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitIfExpression(Node));
|
Result := TDataValue.FromGeneric<T>(VisitIfExpression(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
function TAstVisitor<T>.DoVisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitTernaryExpression(Node));
|
Result := TDataValue.FromGeneric<T>(VisitTernaryExpression(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
function TAstVisitor<T>.DoVisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitLambdaExpression(Node));
|
Result := TDataValue.FromGeneric<T>(VisitLambdaExpression(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
function TAstVisitor<T>.DoVisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitFunctionCall(Node));
|
Result := TDataValue.FromGeneric<T>(VisitFunctionCall(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
|
function TAstVisitor<T>.DoVisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitMacroExpansionNode(Node));
|
Result := TDataValue.FromGeneric<T>(VisitMacroExpansionNode(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
function TAstVisitor<T>.DoVisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitBlockExpression(Node));
|
Result := TDataValue.FromGeneric<T>(VisitBlockExpression(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
function TAstVisitor<T>.DoVisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitVariableDeclaration(Node));
|
Result := TDataValue.FromGeneric<T>(VisitVariableDeclaration(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitAssignment(const Node: IAssignmentNode): TDataValue;
|
function TAstVisitor<T>.DoVisitAssignment(const Node: IAssignmentNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitAssignment(Node));
|
Result := TDataValue.FromGeneric<T>(VisitAssignment(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
|
function TAstVisitor<T>.DoVisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitMacroDefinition(Node));
|
Result := TDataValue.FromGeneric<T>(VisitMacroDefinition(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitQuasiquote(const Node: IQuasiquoteNode): TDataValue;
|
function TAstVisitor<T>.DoVisitQuasiquote(const Node: IQuasiquoteNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitQuasiquote(Node));
|
Result := TDataValue.FromGeneric<T>(VisitQuasiquote(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitUnquote(const Node: IUnquoteNode): TDataValue;
|
function TAstVisitor<T>.DoVisitUnquote(const Node: IUnquoteNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitUnquote(Node));
|
Result := TDataValue.FromGeneric<T>(VisitUnquote(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue;
|
function TAstVisitor<T>.DoVisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitUnquoteSplicing(Node));
|
Result := TDataValue.FromGeneric<T>(VisitUnquoteSplicing(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitIndexer(const Node: IIndexerNode): TDataValue;
|
function TAstVisitor<T>.DoVisitIndexer(const Node: IIndexerNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitIndexer(Node));
|
Result := TDataValue.FromGeneric<T>(VisitIndexer(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
|
function TAstVisitor<T>.DoVisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitMemberAccess(Node));
|
Result := TDataValue.FromGeneric<T>(VisitMemberAccess(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue;
|
function TAstVisitor<T>.DoVisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitRecordLiteral(Node));
|
Result := TDataValue.FromGeneric<T>(VisitRecordLiteral(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
|
function TAstVisitor<T>.DoVisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitCreateSeries(Node));
|
Result := TDataValue.FromGeneric<T>(VisitCreateSeries(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
|
function TAstVisitor<T>.DoVisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitAddSeriesItem(Node));
|
Result := TDataValue.FromGeneric<T>(VisitAddSeriesItem(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
function TAstVisitor<T>.DoVisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitSeriesLength(Node));
|
Result := TDataValue.FromGeneric<T>(VisitSeriesLength(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitRecurNode(const Node: IRecurNode): TDataValue;
|
function TAstVisitor<T>.DoVisitRecurNode(const Node: IRecurNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitRecurNode(Node));
|
Result := TDataValue.FromGeneric<T>(VisitRecurNode(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor<T>.DoVisitNop(const Node: INopNode): TDataValue;
|
function TAstVisitor<T>.DoVisitNop(const Node: INopNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
Result := TDataValue.FromGeneric<T>(VisitNop(Node));
|
Result := TDataValue.FromGeneric<T>(VisitNop(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstTransformer.AcceptParameters(const Nodes: TArray<IIdentifierNode>): TArray<IIdentifierNode>;
|
{ TAstTransformer }
|
||||||
var
|
|
||||||
i: Integer;
|
|
||||||
hasChanged: Boolean;
|
|
||||||
newNode: IIdentifierNode;
|
|
||||||
begin
|
|
||||||
hasChanged := False;
|
|
||||||
SetLength(Result, Length(Nodes));
|
|
||||||
|
|
||||||
for i := 0 to High(Nodes) do
|
|
||||||
begin
|
|
||||||
newNode := Accept(Nodes[i]).AsIdentifier;
|
|
||||||
Result[i] := newNode;
|
|
||||||
if newNode <> Nodes[i] then
|
|
||||||
hasChanged := True;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if not hasChanged then
|
|
||||||
Result := Nodes;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TAstTransformer.AcceptNodes(
|
|
||||||
const Nodes: TArray<IAstNode>;
|
|
||||||
const AcceptProc: TFunc<Integer, IAstNode, IAstNode> = nil
|
|
||||||
): TArray<IAstNode>;
|
|
||||||
var
|
|
||||||
i: Integer;
|
|
||||||
newNode: IAstNode;
|
|
||||||
newList: TList<IAstNode>;
|
|
||||||
hasChanged: Boolean;
|
|
||||||
begin
|
|
||||||
hasChanged := False;
|
|
||||||
newList := nil;
|
|
||||||
|
|
||||||
for i := 0 to High(Nodes) do
|
|
||||||
begin
|
|
||||||
if Assigned(AcceptProc) then
|
|
||||||
newNode := AcceptProc(i, Nodes[i])
|
|
||||||
else
|
|
||||||
newNode := Accept(Nodes[i]);
|
|
||||||
|
|
||||||
if not Assigned(newNode) then
|
|
||||||
begin
|
|
||||||
hasChanged := True;
|
|
||||||
if newList = nil then
|
|
||||||
begin
|
|
||||||
newList := TList<IAstNode>.Create;
|
|
||||||
for var j := 0 to i - 1 do
|
|
||||||
newList.Add(Nodes[j]);
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
if newNode <> Nodes[i] then
|
|
||||||
begin
|
|
||||||
hasChanged := True;
|
|
||||||
if newList = nil then
|
|
||||||
begin
|
|
||||||
newList := TList<IAstNode>.Create;
|
|
||||||
for var j := 0 to i - 1 do
|
|
||||||
newList.Add(Nodes[j]);
|
|
||||||
end;
|
|
||||||
newList.Add(newNode);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
if newList <> nil then
|
|
||||||
newList.Add(Nodes[i]);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if not hasChanged then
|
|
||||||
Result := Nodes
|
|
||||||
else if newList <> nil then
|
|
||||||
begin
|
|
||||||
Result := newList.ToArray;
|
|
||||||
newList.Free;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
Result := [];
|
|
||||||
end;
|
|
||||||
|
|
||||||
// --- Base Virtual Implementations ---
|
// --- Base Virtual Implementations ---
|
||||||
|
|
||||||
@@ -423,21 +382,138 @@ function TAstTransformer.VisitConstant(const Node: IConstantNode): IAstNode;
|
|||||||
begin
|
begin
|
||||||
Result := Node;
|
Result := Node;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstTransformer.VisitIdentifier(const Node: IIdentifierNode): IAstNode;
|
function TAstTransformer.VisitIdentifier(const Node: IIdentifierNode): IAstNode;
|
||||||
begin
|
begin
|
||||||
Result := Node;
|
Result := Node;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstTransformer.VisitKeyword(const Node: IKeywordNode): IAstNode;
|
function TAstTransformer.VisitKeyword(const Node: IKeywordNode): IAstNode;
|
||||||
begin
|
begin
|
||||||
Result := Node;
|
Result := Node;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstTransformer.VisitNop(const Node: INopNode): IAstNode;
|
function TAstTransformer.VisitNop(const Node: INopNode): IAstNode;
|
||||||
begin
|
begin
|
||||||
Result := Node;
|
Result := Node;
|
||||||
end;
|
end;
|
||||||
|
function TAstTransformer.VisitCreateSeries(const Node: ICreateSeriesNode): IAstNode;
|
||||||
|
begin
|
||||||
|
Result := Node;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// --- List Transformations ---
|
||||||
|
|
||||||
|
function TAstTransformer.VisitParameterList(const Node: IParameterList): IAstNode;
|
||||||
|
var
|
||||||
|
hasChanged: Boolean;
|
||||||
|
newItems: TArray<IIdentifierNode>;
|
||||||
|
item, newItem: IIdentifierNode;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
hasChanged := False;
|
||||||
|
SetLength(newItems, Node.Count);
|
||||||
|
for i := 0 to Node.Count - 1 do
|
||||||
|
begin
|
||||||
|
item := Node[i];
|
||||||
|
newItem := Accept(item).AsIdentifier;
|
||||||
|
newItems[i] := newItem;
|
||||||
|
if item <> newItem then
|
||||||
|
hasChanged := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not hasChanged then
|
||||||
|
Result := Node
|
||||||
|
else
|
||||||
|
// Manually reconstruct using concrete class to verify transformation
|
||||||
|
Result := TParameterList.Create(newItems, Node.Identity);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstTransformer.VisitArgumentList(const Node: IArgumentList): IAstNode;
|
||||||
|
var
|
||||||
|
hasChanged: Boolean;
|
||||||
|
newItems: TArray<IAstNode>;
|
||||||
|
item, newItem: IAstNode;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
hasChanged := False;
|
||||||
|
SetLength(newItems, Node.Count);
|
||||||
|
for i := 0 to Node.Count - 1 do
|
||||||
|
begin
|
||||||
|
item := Node[i];
|
||||||
|
newItem := Accept(item);
|
||||||
|
newItems[i] := newItem;
|
||||||
|
if item <> newItem then
|
||||||
|
hasChanged := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not hasChanged then
|
||||||
|
Result := Node
|
||||||
|
else
|
||||||
|
Result := TArgumentList.Create(newItems, Node.Identity);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstTransformer.VisitExpressionList(const Node: IExpressionList): IAstNode;
|
||||||
|
var
|
||||||
|
hasChanged: Boolean;
|
||||||
|
newItems: TArray<IAstNode>;
|
||||||
|
item, newItem: IAstNode;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
hasChanged := False;
|
||||||
|
SetLength(newItems, Node.Count);
|
||||||
|
for i := 0 to Node.Count - 1 do
|
||||||
|
begin
|
||||||
|
item := Node[i];
|
||||||
|
newItem := Accept(item);
|
||||||
|
newItems[i] := newItem;
|
||||||
|
if item <> newItem then
|
||||||
|
hasChanged := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not hasChanged then
|
||||||
|
Result := Node
|
||||||
|
else
|
||||||
|
Result := TExpressionList.Create(newItems, Node.Identity);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstTransformer.VisitRecordFieldList(const Node: IRecordFieldList): IAstNode;
|
||||||
|
var
|
||||||
|
hasChanged: Boolean;
|
||||||
|
newItems: TArray<IRecordFieldNode>;
|
||||||
|
item, newItem: IRecordFieldNode;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
hasChanged := False;
|
||||||
|
SetLength(newItems, Node.Count);
|
||||||
|
for i := 0 to Node.Count - 1 do
|
||||||
|
begin
|
||||||
|
item := Node[i];
|
||||||
|
// Ensure we transform the field node itself via Accept to trigger VisitRecordField
|
||||||
|
newItem := Accept(item).AsRecordField;
|
||||||
|
newItems[i] := newItem;
|
||||||
|
if item <> newItem then
|
||||||
|
hasChanged := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not hasChanged then
|
||||||
|
Result := Node
|
||||||
|
else
|
||||||
|
Result := TRecordFieldList.Create(newItems, Node.Identity);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstTransformer.VisitRecordField(const Node: IRecordFieldNode): IAstNode;
|
||||||
|
var
|
||||||
|
newKey: IKeywordNode;
|
||||||
|
newValue: IAstNode;
|
||||||
|
begin
|
||||||
|
newKey := Accept(Node.Key).AsKeyword;
|
||||||
|
newValue := Accept(Node.Value);
|
||||||
|
|
||||||
|
if (newKey = Node.Key) and (newValue = Node.Value) then
|
||||||
|
Result := Node
|
||||||
|
else
|
||||||
|
Result := TAst.RecordField(newKey, newValue, Node.Identity.Location);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// --- Node Transformations ---
|
||||||
|
|
||||||
function TAstTransformer.VisitIfExpression(const Node: IIfExpressionNode): IAstNode;
|
function TAstTransformer.VisitIfExpression(const Node: IIfExpressionNode): IAstNode;
|
||||||
var
|
var
|
||||||
@@ -469,27 +545,29 @@ end;
|
|||||||
|
|
||||||
function TAstTransformer.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
|
function TAstTransformer.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
|
||||||
var
|
var
|
||||||
newParams: TArray<IIdentifierNode>;
|
newParams: IParameterList;
|
||||||
newBody: IAstNode;
|
newBody: IAstNode;
|
||||||
begin
|
begin
|
||||||
newParams := AcceptParameters(Node.Parameters);
|
newParams := Accept(Node.Parameters).AsParameterList;
|
||||||
newBody := Accept(Node.Body);
|
newBody := Accept(Node.Body);
|
||||||
|
|
||||||
if (newParams = Node.Parameters) and (newBody = Node.Body) then
|
if (newParams = Node.Parameters) and (newBody = Node.Body) then
|
||||||
Result := Node
|
Result := Node
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
// Rebuild Lambda via concrete constructor to keep Layout/Descriptor info
|
||||||
|
// TAst factory would reset layout info.
|
||||||
Result :=
|
Result :=
|
||||||
TAst.LambdaExpr(
|
TLambdaExpressionNode.Create(
|
||||||
Node.Identity,
|
|
||||||
newParams,
|
newParams,
|
||||||
newBody,
|
newBody,
|
||||||
|
Node.StaticType,
|
||||||
Node.Layout,
|
Node.Layout,
|
||||||
Node.Descriptor,
|
Node.Descriptor,
|
||||||
Node.Upvalues,
|
Node.Upvalues,
|
||||||
Node.HasNestedLambdas,
|
Node.HasNestedLambdas,
|
||||||
Node.IsPure,
|
Node.IsPure,
|
||||||
Node.StaticType
|
Node.Identity
|
||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@@ -497,17 +575,18 @@ end;
|
|||||||
function TAstTransformer.VisitFunctionCall(const Node: IFunctionCallNode): IAstNode;
|
function TAstTransformer.VisitFunctionCall(const Node: IFunctionCallNode): IAstNode;
|
||||||
var
|
var
|
||||||
newCallee: IAstNode;
|
newCallee: IAstNode;
|
||||||
newArgs: TArray<IAstNode>;
|
newArgs: IArgumentList;
|
||||||
begin
|
begin
|
||||||
newCallee := Accept(Node.Callee);
|
newCallee := Accept(Node.Callee);
|
||||||
newArgs := AcceptNodes(Node.Arguments);
|
newArgs := Accept(Node.Arguments).AsArgumentList;
|
||||||
|
|
||||||
if (newCallee = Node.Callee) and (newArgs = Node.Arguments) then
|
if (newCallee = Node.Callee) and (newArgs = Node.Arguments) then
|
||||||
Result := Node
|
Result := Node
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
Result :=
|
Result :=
|
||||||
TAst.FunctionCall(Node.Identity, newCallee, newArgs, Node.StaticType, Node.IsTailCall, Node.StaticTarget, Node.IsTargetPure);
|
TFunctionCallNode
|
||||||
|
.Create(newCallee, newArgs, Node.StaticType, Node.IsTailCall, Node.StaticTarget, Node.IsTargetPure, Node.Identity);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -519,20 +598,22 @@ begin
|
|||||||
if newBody = Node.ExpandedBody then
|
if newBody = Node.ExpandedBody then
|
||||||
exit(Node);
|
exit(Node);
|
||||||
|
|
||||||
// Macro Expansion Nodes are structural, reuse identity
|
// Macro Expansion Nodes are structural, reuse identity.
|
||||||
|
// Note: We don't visit the CallNode as it is the "source" which doesn't change during this transformation typically
|
||||||
Result := TAst.MacroExpansionNode(Node.Identity, Node.CallNode, newBody);
|
Result := TAst.MacroExpansionNode(Node.Identity, Node.CallNode, newBody);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstTransformer.VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode;
|
function TAstTransformer.VisitBlockExpression(const Node: IBlockExpressionNode): IAstNode;
|
||||||
var
|
var
|
||||||
newExprs: TArray<IAstNode>;
|
newExprs: IExpressionList;
|
||||||
begin
|
begin
|
||||||
newExprs := AcceptNodes(Node.Expressions);
|
newExprs := Accept(Node.Expressions).AsExpressionList;
|
||||||
|
|
||||||
if newExprs = Node.Expressions then
|
if newExprs = Node.Expressions then
|
||||||
Result := Node
|
Result := Node
|
||||||
else
|
else
|
||||||
Result := TAst.Block(Node.Identity, newExprs, Node.StaticType);
|
// Rebuild manually to preserve type
|
||||||
|
Result := TBlockExpressionNode.Create(newExprs, Node.StaticType, Node.Identity);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstTransformer.VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode;
|
function TAstTransformer.VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode;
|
||||||
@@ -598,15 +679,11 @@ function TAstTransformer.VisitUnquoteSplicing(const Node: IUnquoteSplicingNode):
|
|||||||
var
|
var
|
||||||
newExpr: IAstNode;
|
newExpr: IAstNode;
|
||||||
begin
|
begin
|
||||||
// Note: Accept expects IAstNode, IQuasiquoteNode inherits from it.
|
|
||||||
newExpr := Accept(Node.Expression);
|
newExpr := Accept(Node.Expression);
|
||||||
|
|
||||||
if (newExpr = Node.Expression) then
|
if (newExpr = Node.Expression) then
|
||||||
Result := Node
|
Result := Node
|
||||||
else
|
else
|
||||||
// We need to ensure the transformed expression is still a Quasiquote,
|
|
||||||
// or we have to assume the transformer knows what it's doing.
|
|
||||||
// For safety, we cast back. If transformation changed type, this will fail fast.
|
|
||||||
Result := TAst.UnquoteSplicing(Node.Identity, newExpr.AsQuasiquote);
|
Result := TAst.UnquoteSplicing(Node.Identity, newExpr.AsQuasiquote);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -639,35 +716,18 @@ end;
|
|||||||
|
|
||||||
function TAstTransformer.VisitRecordLiteral(const Node: IRecordLiteralNode): IAstNode;
|
function TAstTransformer.VisitRecordLiteral(const Node: IRecordLiteralNode): IAstNode;
|
||||||
var
|
var
|
||||||
i: Integer;
|
newFields: IRecordFieldList;
|
||||||
newFields: TArray<TRecordFieldLiteral>;
|
|
||||||
hasChanged: Boolean;
|
|
||||||
begin
|
begin
|
||||||
SetLength(newFields, Length(Node.Fields));
|
newFields := Accept(Node.Fields).AsRecordFieldList;
|
||||||
hasChanged := False;
|
|
||||||
|
|
||||||
for i := 0 to High(Node.Fields) do
|
if newFields = Node.Fields then
|
||||||
begin
|
|
||||||
// Keys are typically static, but we visit them anyway
|
|
||||||
newFields[i].Key := Accept(Node.Fields[i].Key).AsKeyword;
|
|
||||||
newFields[i].Value := Accept(Node.Fields[i].Value);
|
|
||||||
if (newFields[i].Key <> Node.Fields[i].Key) or (newFields[i].Value <> Node.Fields[i].Value) then
|
|
||||||
hasChanged := True;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if not hasChanged then
|
|
||||||
Result := Node
|
Result := Node
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
Result := TAst.RecordLiteral(Node.Identity, newFields, Node.ScalarDefinition, Node.GenericDefinition, Node.StaticType);
|
Result := TRecordLiteralNode.Create(newFields, Node.ScalarDefinition, Node.GenericDefinition, Node.StaticType, Node.Identity);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstTransformer.VisitCreateSeries(const Node: ICreateSeriesNode): IAstNode;
|
|
||||||
begin
|
|
||||||
Result := Node;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TAstTransformer.VisitAddSeriesItem(const Node: IAddSeriesItemNode): IAstNode;
|
function TAstTransformer.VisitAddSeriesItem(const Node: IAddSeriesItemNode): IAstNode;
|
||||||
var
|
var
|
||||||
newSeries: IIdentifierNode;
|
newSeries: IIdentifierNode;
|
||||||
@@ -697,14 +757,14 @@ end;
|
|||||||
|
|
||||||
function TAstTransformer.VisitRecurNode(const Node: IRecurNode): IAstNode;
|
function TAstTransformer.VisitRecurNode(const Node: IRecurNode): IAstNode;
|
||||||
var
|
var
|
||||||
newArgs: TArray<IAstNode>;
|
newArgs: IArgumentList;
|
||||||
begin
|
begin
|
||||||
newArgs := AcceptNodes(Node.Arguments);
|
newArgs := Accept(Node.Arguments).AsArgumentList;
|
||||||
|
|
||||||
if newArgs = Node.Arguments then
|
if newArgs = Node.Arguments then
|
||||||
Result := Node
|
Result := Node
|
||||||
else
|
else
|
||||||
Result := TAst.Recur(Node.Identity, newArgs, Node.StaticType);
|
Result := TRecurNode.Create(newArgs, Node.StaticType, Node.Identity);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TAstVisitor }
|
{ TAstVisitor }
|
||||||
@@ -717,17 +777,49 @@ end;
|
|||||||
|
|
||||||
procedure TAstVisitor.VisitConstant(const Node: IConstantNode);
|
procedure TAstVisitor.VisitConstant(const Node: IConstantNode);
|
||||||
begin
|
begin
|
||||||
// Leaf node
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TAstVisitor.VisitIdentifier(const Node: IIdentifierNode);
|
procedure TAstVisitor.VisitIdentifier(const Node: IIdentifierNode);
|
||||||
begin
|
begin
|
||||||
// Leaf node
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TAstVisitor.VisitKeyword(const Node: IKeywordNode);
|
procedure TAstVisitor.VisitKeyword(const Node: IKeywordNode);
|
||||||
begin
|
begin
|
||||||
// Leaf node
|
end;
|
||||||
|
procedure TAstVisitor.VisitNop(const Node: INopNode);
|
||||||
|
begin
|
||||||
|
end;
|
||||||
|
procedure TAstVisitor.VisitCreateSeries(const Node: ICreateSeriesNode);
|
||||||
|
begin
|
||||||
|
end;
|
||||||
|
|
||||||
|
// List visitors iterate children by default
|
||||||
|
procedure TAstVisitor.VisitParameterList(const Node: IParameterList);
|
||||||
|
begin
|
||||||
|
for var item in Node do
|
||||||
|
Accept(item);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TAstVisitor.VisitArgumentList(const Node: IArgumentList);
|
||||||
|
begin
|
||||||
|
for var item in Node do
|
||||||
|
Accept(item);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TAstVisitor.VisitExpressionList(const Node: IExpressionList);
|
||||||
|
begin
|
||||||
|
for var item in Node do
|
||||||
|
Accept(item);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TAstVisitor.VisitRecordFieldList(const Node: IRecordFieldList);
|
||||||
|
begin
|
||||||
|
for var item in Node do
|
||||||
|
Accept(item);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TAstVisitor.VisitRecordField(const Node: IRecordFieldNode);
|
||||||
|
begin
|
||||||
|
Accept(Node.Key);
|
||||||
|
Accept(Node.Value);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TAstVisitor.VisitIfExpression(const Node: IIfExpressionNode);
|
procedure TAstVisitor.VisitIfExpression(const Node: IIfExpressionNode);
|
||||||
@@ -746,16 +838,14 @@ end;
|
|||||||
|
|
||||||
procedure TAstVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode);
|
procedure TAstVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode);
|
||||||
begin
|
begin
|
||||||
for var param in Node.Parameters do
|
Accept(Node.Parameters);
|
||||||
Accept(param);
|
|
||||||
Accept(Node.Body);
|
Accept(Node.Body);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TAstVisitor.VisitFunctionCall(const Node: IFunctionCallNode);
|
procedure TAstVisitor.VisitFunctionCall(const Node: IFunctionCallNode);
|
||||||
begin
|
begin
|
||||||
Accept(Node.Callee);
|
Accept(Node.Callee);
|
||||||
for var arg in Node.Arguments do
|
Accept(Node.Arguments);
|
||||||
Accept(arg);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TAstVisitor.VisitMacroExpansionNode(const Node: IMacroExpansionNode);
|
procedure TAstVisitor.VisitMacroExpansionNode(const Node: IMacroExpansionNode);
|
||||||
@@ -766,8 +856,7 @@ end;
|
|||||||
|
|
||||||
procedure TAstVisitor.VisitBlockExpression(const Node: IBlockExpressionNode);
|
procedure TAstVisitor.VisitBlockExpression(const Node: IBlockExpressionNode);
|
||||||
begin
|
begin
|
||||||
for var expr in Node.Expressions do
|
Accept(Node.Expressions);
|
||||||
Accept(expr);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TAstVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode);
|
procedure TAstVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode);
|
||||||
@@ -785,8 +874,7 @@ end;
|
|||||||
procedure TAstVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode);
|
procedure TAstVisitor.VisitMacroDefinition(const Node: IMacroDefinitionNode);
|
||||||
begin
|
begin
|
||||||
Accept(Node.Name);
|
Accept(Node.Name);
|
||||||
for var param in Node.Parameters do
|
Accept(Node.Parameters);
|
||||||
Accept(param);
|
|
||||||
Accept(Node.Body);
|
Accept(Node.Body);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -819,16 +907,7 @@ end;
|
|||||||
|
|
||||||
procedure TAstVisitor.VisitRecordLiteral(const Node: IRecordLiteralNode);
|
procedure TAstVisitor.VisitRecordLiteral(const Node: IRecordLiteralNode);
|
||||||
begin
|
begin
|
||||||
for var field in Node.Fields do
|
Accept(Node.Fields);
|
||||||
begin
|
|
||||||
Accept(field.Key);
|
|
||||||
Accept(field.Value);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TAstVisitor.VisitCreateSeries(const Node: ICreateSeriesNode);
|
|
||||||
begin
|
|
||||||
// Leaf node
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TAstVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode);
|
procedure TAstVisitor.VisitAddSeriesItem(const Node: IAddSeriesItemNode);
|
||||||
@@ -845,130 +924,177 @@ end;
|
|||||||
|
|
||||||
procedure TAstVisitor.VisitRecurNode(const Node: IRecurNode);
|
procedure TAstVisitor.VisitRecurNode(const Node: IRecurNode);
|
||||||
begin
|
begin
|
||||||
for var arg in Node.Arguments do
|
Accept(Node.Arguments);
|
||||||
Accept(arg);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TAstVisitor.VisitNop(const Node: INopNode);
|
// --- TAstVisitor (Non-Generic) Bridge Implementations ---
|
||||||
begin
|
|
||||||
// Leaf node
|
|
||||||
end;
|
|
||||||
|
|
||||||
// ... [Private Bridge Methods implementation remains unchanged] ...
|
|
||||||
|
|
||||||
function TAstVisitor.DoVisitConstant(const Node: IConstantNode): TDataValue;
|
function TAstVisitor.DoVisitConstant(const Node: IConstantNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitConstant(Node);
|
VisitConstant(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
function TAstVisitor.DoVisitIdentifier(const Node: IIdentifierNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitIdentifier(Node);
|
VisitIdentifier(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitKeyword(const Node: IKeywordNode): TDataValue;
|
function TAstVisitor.DoVisitKeyword(const Node: IKeywordNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitKeyword(Node);
|
VisitKeyword(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstVisitor.DoVisitParameterList(const Node: IParameterList): TDataValue;
|
||||||
|
begin
|
||||||
|
VisitParameterList(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstVisitor.DoVisitArgumentList(const Node: IArgumentList): TDataValue;
|
||||||
|
begin
|
||||||
|
VisitArgumentList(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstVisitor.DoVisitExpressionList(const Node: IExpressionList): TDataValue;
|
||||||
|
begin
|
||||||
|
VisitExpressionList(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstVisitor.DoVisitRecordFieldList(const Node: IRecordFieldList): TDataValue;
|
||||||
|
begin
|
||||||
|
VisitRecordFieldList(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstVisitor.DoVisitRecordField(const Node: IRecordFieldNode): TDataValue;
|
||||||
|
begin
|
||||||
|
VisitRecordField(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
function TAstVisitor.DoVisitIfExpression(const Node: IIfExpressionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitIfExpression(Node);
|
VisitIfExpression(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
function TAstVisitor.DoVisitTernaryExpression(const Node: ITernaryExpressionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitTernaryExpression(Node);
|
VisitTernaryExpression(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
function TAstVisitor.DoVisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitLambdaExpression(Node);
|
VisitLambdaExpression(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
function TAstVisitor.DoVisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitFunctionCall(Node);
|
VisitFunctionCall(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
|
function TAstVisitor.DoVisitMacroExpansionNode(const Node: IMacroExpansionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitMacroExpansionNode(Node);
|
VisitMacroExpansionNode(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
function TAstVisitor.DoVisitBlockExpression(const Node: IBlockExpressionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitBlockExpression(Node);
|
VisitBlockExpression(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
function TAstVisitor.DoVisitVariableDeclaration(const Node: IVariableDeclarationNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitVariableDeclaration(Node);
|
VisitVariableDeclaration(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitAssignment(const Node: IAssignmentNode): TDataValue;
|
function TAstVisitor.DoVisitAssignment(const Node: IAssignmentNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitAssignment(Node);
|
VisitAssignment(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
|
function TAstVisitor.DoVisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitMacroDefinition(Node);
|
VisitMacroDefinition(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitQuasiquote(const Node: IQuasiquoteNode): TDataValue;
|
function TAstVisitor.DoVisitQuasiquote(const Node: IQuasiquoteNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitQuasiquote(Node);
|
VisitQuasiquote(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitUnquote(const Node: IUnquoteNode): TDataValue;
|
function TAstVisitor.DoVisitUnquote(const Node: IUnquoteNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitUnquote(Node);
|
VisitUnquote(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue;
|
function TAstVisitor.DoVisitUnquoteSplicing(const Node: IUnquoteSplicingNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitUnquoteSplicing(Node);
|
VisitUnquoteSplicing(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitIndexer(const Node: IIndexerNode): TDataValue;
|
function TAstVisitor.DoVisitIndexer(const Node: IIndexerNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitIndexer(Node);
|
VisitIndexer(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
|
function TAstVisitor.DoVisitMemberAccess(const Node: IMemberAccessNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitMemberAccess(Node);
|
VisitMemberAccess(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue;
|
function TAstVisitor.DoVisitRecordLiteral(const Node: IRecordLiteralNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitRecordLiteral(Node);
|
VisitRecordLiteral(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
|
function TAstVisitor.DoVisitCreateSeries(const Node: ICreateSeriesNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitCreateSeries(Node);
|
VisitCreateSeries(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
|
function TAstVisitor.DoVisitAddSeriesItem(const Node: IAddSeriesItemNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitAddSeriesItem(Node);
|
VisitAddSeriesItem(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
function TAstVisitor.DoVisitSeriesLength(const Node: ISeriesLengthNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitSeriesLength(Node);
|
VisitSeriesLength(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitRecurNode(const Node: IRecurNode): TDataValue;
|
function TAstVisitor.DoVisitRecurNode(const Node: IRecurNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitRecurNode(Node);
|
VisitRecurNode(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TAstVisitor.DoVisitNop(const Node: INopNode): TDataValue;
|
function TAstVisitor.DoVisitNop(const Node: INopNode): TDataValue;
|
||||||
begin
|
begin
|
||||||
VisitNop(Node);
|
VisitNop(Node);
|
||||||
|
Result := TDataValue.Void;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
+71
-79
@@ -124,7 +124,7 @@ type
|
|||||||
|
|
||||||
class function LambdaExpr(
|
class function LambdaExpr(
|
||||||
const Identity: IAstIdentity;
|
const Identity: IAstIdentity;
|
||||||
const AParameters: TArray<IIdentifierNode>;
|
const AParameters: IParameterList;
|
||||||
const ABody: IAstNode;
|
const ABody: IAstNode;
|
||||||
const ALayout: IScopeLayout = nil;
|
const ALayout: IScopeLayout = nil;
|
||||||
const ADescriptor: IScopeDescriptor = nil;
|
const ADescriptor: IScopeDescriptor = nil;
|
||||||
@@ -145,7 +145,7 @@ type
|
|||||||
class function MacroDef(
|
class function MacroDef(
|
||||||
const Identity: IAstIdentity;
|
const Identity: IAstIdentity;
|
||||||
const AName: IIdentifierNode;
|
const AName: IIdentifierNode;
|
||||||
const AParameters: TArray<IIdentifierNode>;
|
const AParameters: IParameterList;
|
||||||
const ABody: IAstNode
|
const ABody: IAstNode
|
||||||
): IMacroDefinitionNode; overload; static;
|
): IMacroDefinitionNode; overload; static;
|
||||||
|
|
||||||
@@ -175,7 +175,7 @@ type
|
|||||||
class function FunctionCall(
|
class function FunctionCall(
|
||||||
const Identity: IAstIdentity;
|
const Identity: IAstIdentity;
|
||||||
const ACallee: IAstNode;
|
const ACallee: IAstNode;
|
||||||
const AArguments: TArray<IAstNode>;
|
const AArguments: IArgumentList;
|
||||||
const AStaticType: IStaticType = nil;
|
const AStaticType: IStaticType = nil;
|
||||||
const AIsTailCall: Boolean = False;
|
const AIsTailCall: Boolean = False;
|
||||||
const AStaticTarget: TDataValue.TFunc = nil;
|
const AStaticTarget: TDataValue.TFunc = nil;
|
||||||
@@ -183,7 +183,6 @@ type
|
|||||||
): IFunctionCallNode; overload; static;
|
): IFunctionCallNode; overload; static;
|
||||||
|
|
||||||
// --- MACRO EXPANSION ---
|
// --- MACRO EXPANSION ---
|
||||||
// Note: MacroExpansion is usually created during transformation, but conceptually it's a new node wrapping the original call.
|
|
||||||
class function MacroExpansionNode(
|
class function MacroExpansionNode(
|
||||||
const AOriginalCallNode: IFunctionCallNode;
|
const AOriginalCallNode: IFunctionCallNode;
|
||||||
const AExpandedBody: IAstNode;
|
const AExpandedBody: IAstNode;
|
||||||
@@ -201,7 +200,7 @@ type
|
|||||||
|
|
||||||
class function Recur(
|
class function Recur(
|
||||||
const Identity: IAstIdentity;
|
const Identity: IAstIdentity;
|
||||||
const AArguments: TArray<IAstNode>;
|
const AArguments: IArgumentList;
|
||||||
const AStaticType: IStaticType = nil
|
const AStaticType: IStaticType = nil
|
||||||
): IRecurNode; overload; static;
|
): IRecurNode; overload; static;
|
||||||
|
|
||||||
@@ -213,7 +212,7 @@ type
|
|||||||
|
|
||||||
class function Block(
|
class function Block(
|
||||||
const Identity: IAstIdentity;
|
const Identity: IAstIdentity;
|
||||||
const AExpressions: TArray<IAstNode>;
|
const AExpressions: IExpressionList;
|
||||||
const AStaticType: IStaticType = nil
|
const AStaticType: IStaticType = nil
|
||||||
): IBlockExpressionNode; overload; static;
|
): IBlockExpressionNode; overload; static;
|
||||||
|
|
||||||
@@ -241,10 +240,6 @@ type
|
|||||||
const AStaticType: IStaticType = nil
|
const AStaticType: IStaticType = nil
|
||||||
): IAssignmentNode; overload; static;
|
): IAssignmentNode; overload; static;
|
||||||
|
|
||||||
// --- ASSIGN RESULT (Helper) ---
|
|
||||||
// Special case: Creates implicit nodes. No explicit "Transformation" overload needed as it maps to Assign.
|
|
||||||
class function AssignResult(const AValue: IAstNode; const Loc: ISourceLocation = nil): IAssignmentNode; static; deprecated;
|
|
||||||
|
|
||||||
// --- INDEXER ---
|
// --- INDEXER ---
|
||||||
class function Indexer(
|
class function Indexer(
|
||||||
const ABase: IAstNode;
|
const ABase: IAstNode;
|
||||||
@@ -273,15 +268,28 @@ type
|
|||||||
const AStaticType: IStaticType = nil
|
const AStaticType: IStaticType = nil
|
||||||
): IMemberAccessNode; overload; static;
|
): IMemberAccessNode; overload; static;
|
||||||
|
|
||||||
// --- RECORD LITERAL ---
|
// --- RECORD FIELD & LITERAL ---
|
||||||
|
class function RecordField(
|
||||||
|
const AKey: IKeywordNode;
|
||||||
|
const AValue: IAstNode;
|
||||||
|
const Loc: ISourceLocation = nil
|
||||||
|
): IRecordFieldNode; overload; static;
|
||||||
|
|
||||||
|
// Neuer Overload für Identitäts-Erhalt
|
||||||
|
class function RecordField(
|
||||||
|
const Identity: IAstIdentity;
|
||||||
|
const AKey: IKeywordNode;
|
||||||
|
const AValue: IAstNode
|
||||||
|
): IRecordFieldNode; overload; static;
|
||||||
|
|
||||||
class function RecordLiteral(
|
class function RecordLiteral(
|
||||||
const AFields: TArray<TRecordFieldLiteral>;
|
const AFields: TArray<IRecordFieldNode>;
|
||||||
const Loc: ISourceLocation = nil
|
const Loc: ISourceLocation = nil
|
||||||
): IRecordLiteralNode; overload; static;
|
): IRecordLiteralNode; overload; static;
|
||||||
|
|
||||||
class function RecordLiteral(
|
class function RecordLiteral(
|
||||||
const Identity: IAstIdentity;
|
const Identity: IAstIdentity;
|
||||||
const AFields: TArray<TRecordFieldLiteral>;
|
const AFields: IRecordFieldList;
|
||||||
const AScalarDefinition: IScalarRecordDefinition = nil;
|
const AScalarDefinition: IScalarRecordDefinition = nil;
|
||||||
const AGenericDefinition: IGenericRecordDefinition = nil;
|
const AGenericDefinition: IGenericRecordDefinition = nil;
|
||||||
const AStaticType: IStaticType = nil
|
const AStaticType: IStaticType = nil
|
||||||
@@ -355,11 +363,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// IMPLEMENTATION: DATA NODES
|
// DATA NODES
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
// --- Identifier ---
|
|
||||||
|
|
||||||
class function TAst.Identifier(const AName: string; const Loc: ISourceLocation): IIdentifierNode;
|
class function TAst.Identifier(const AName: string; const Loc: ISourceLocation): IIdentifierNode;
|
||||||
begin
|
begin
|
||||||
var id := TIdentities.Identifier(AName, Loc);
|
var id := TIdentities.Identifier(AName, Loc);
|
||||||
@@ -381,8 +387,6 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- Constant ---
|
|
||||||
|
|
||||||
class function TAst.Constant(const AValue: TDataValue; const Loc: ISourceLocation): IConstantNode;
|
class function TAst.Constant(const AValue: TDataValue; const Loc: ISourceLocation): IConstantNode;
|
||||||
begin
|
begin
|
||||||
var constType: IStaticType;
|
var constType: IStaticType;
|
||||||
@@ -413,8 +417,6 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- Keyword ---
|
|
||||||
|
|
||||||
class function TAst.Keyword(const AName: string; const Loc: ISourceLocation): IKeywordNode;
|
class function TAst.Keyword(const AName: string; const Loc: ISourceLocation): IKeywordNode;
|
||||||
begin
|
begin
|
||||||
var val := TKeywordRegistry.Intern(AName);
|
var val := TKeywordRegistry.Intern(AName);
|
||||||
@@ -427,8 +429,6 @@ begin
|
|||||||
Result := TKeywordNode.Create(Identity);
|
Result := TKeywordNode.Create(Identity);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- CreateSeries ---
|
|
||||||
|
|
||||||
class function TAst.CreateSeries(const ADefinition: String; const Loc: ISourceLocation): ICreateSeriesNode;
|
class function TAst.CreateSeries(const ADefinition: String; const Loc: ISourceLocation): ICreateSeriesNode;
|
||||||
begin
|
begin
|
||||||
var id := TIdentities.Definition(ADefinition, Loc);
|
var id := TIdentities.Definition(ADefinition, Loc);
|
||||||
@@ -446,11 +446,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// IMPLEMENTATION: STRUCTURAL NODES
|
// STRUCTURAL NODES
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
// --- NOP ---
|
|
||||||
|
|
||||||
class function TAst.Nop(const Loc: ISourceLocation): IAstNode;
|
class function TAst.Nop(const Loc: ISourceLocation): IAstNode;
|
||||||
begin
|
begin
|
||||||
var id := TIdentities.Structural(Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
@@ -467,8 +465,6 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- IfExpr ---
|
|
||||||
|
|
||||||
class function TAst.IfExpr(const ACondition, AThenBranch, AElseBranch: IAstNode; const Loc: ISourceLocation): IIfExpressionNode;
|
class function TAst.IfExpr(const ACondition, AThenBranch, AElseBranch: IAstNode; const Loc: ISourceLocation): IIfExpressionNode;
|
||||||
begin
|
begin
|
||||||
var id := TIdentities.Structural(Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
@@ -492,8 +488,6 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- TernaryExpr ---
|
|
||||||
|
|
||||||
class function TAst.TernaryExpr(const ACondition, AThenBranch, AElseBranch: IAstNode; const Loc: ISourceLocation): ITernaryExpressionNode;
|
class function TAst.TernaryExpr(const ACondition, AThenBranch, AElseBranch: IAstNode; const Loc: ISourceLocation): ITernaryExpressionNode;
|
||||||
begin
|
begin
|
||||||
var id := TIdentities.Structural(Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
@@ -517,21 +511,22 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- LambdaExpr ---
|
|
||||||
|
|
||||||
class function TAst.LambdaExpr(
|
class function TAst.LambdaExpr(
|
||||||
const AParameters: TArray<IIdentifierNode>;
|
const AParameters: TArray<IIdentifierNode>;
|
||||||
const ABody: IAstNode;
|
const ABody: IAstNode;
|
||||||
const Loc: ISourceLocation
|
const Loc: ISourceLocation
|
||||||
): ILambdaExpressionNode;
|
): ILambdaExpressionNode;
|
||||||
begin
|
begin
|
||||||
|
var listId := TIdentities.List('[', ']', ' ', Loc);
|
||||||
|
var paramList := TParameterList.Create(AParameters, listId);
|
||||||
|
|
||||||
var id := TIdentities.Structural(Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
Result := TLambdaExpressionNode.Create(AParameters, ABody, TTypes.Unknown, nil, nil, nil, False, False, id);
|
Result := TLambdaExpressionNode.Create(paramList, ABody, TTypes.Unknown, nil, nil, nil, False, False, id);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TAst.LambdaExpr(
|
class function TAst.LambdaExpr(
|
||||||
const Identity: IAstIdentity;
|
const Identity: IAstIdentity;
|
||||||
const AParameters: TArray<IIdentifierNode>;
|
const AParameters: IParameterList;
|
||||||
const ABody: IAstNode;
|
const ABody: IAstNode;
|
||||||
const ALayout: IScopeLayout;
|
const ALayout: IScopeLayout;
|
||||||
const ADescriptor: IScopeDescriptor;
|
const ADescriptor: IScopeDescriptor;
|
||||||
@@ -555,8 +550,6 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- MacroDef ---
|
|
||||||
|
|
||||||
class function TAst.MacroDef(
|
class function TAst.MacroDef(
|
||||||
const AName: IIdentifierNode;
|
const AName: IIdentifierNode;
|
||||||
const AParameters: TArray<IIdentifierNode>;
|
const AParameters: TArray<IIdentifierNode>;
|
||||||
@@ -564,22 +557,23 @@ class function TAst.MacroDef(
|
|||||||
const Loc: ISourceLocation
|
const Loc: ISourceLocation
|
||||||
): IMacroDefinitionNode;
|
): IMacroDefinitionNode;
|
||||||
begin
|
begin
|
||||||
|
var listId := TIdentities.List('[', ']', ' ', Loc);
|
||||||
|
var paramList := TParameterList.Create(AParameters, listId);
|
||||||
|
|
||||||
var id := TIdentities.Structural(Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
Result := TMacroDefinitionNode.Create(AName, AParameters, ABody, id);
|
Result := TMacroDefinitionNode.Create(AName, paramList, ABody, id);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TAst.MacroDef(
|
class function TAst.MacroDef(
|
||||||
const Identity: IAstIdentity;
|
const Identity: IAstIdentity;
|
||||||
const AName: IIdentifierNode;
|
const AName: IIdentifierNode;
|
||||||
const AParameters: TArray<IIdentifierNode>;
|
const AParameters: IParameterList;
|
||||||
const ABody: IAstNode
|
const ABody: IAstNode
|
||||||
): IMacroDefinitionNode;
|
): IMacroDefinitionNode;
|
||||||
begin
|
begin
|
||||||
Result := TMacroDefinitionNode.Create(AName, AParameters, ABody, Identity);
|
Result := TMacroDefinitionNode.Create(AName, AParameters, ABody, Identity);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- Quotes ---
|
|
||||||
|
|
||||||
class function TAst.Quasiquote(const AExpression: IAstNode; const Loc: ISourceLocation): IQuasiquoteNode;
|
class function TAst.Quasiquote(const AExpression: IAstNode; const Loc: ISourceLocation): IQuasiquoteNode;
|
||||||
begin
|
begin
|
||||||
var id := TIdentities.Structural(Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
@@ -613,22 +607,23 @@ begin
|
|||||||
Result := TUnquoteSplicingNode.Create(AExpression, Identity);
|
Result := TUnquoteSplicingNode.Create(AExpression, Identity);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- FunctionCall ---
|
|
||||||
|
|
||||||
class function TAst.FunctionCall(
|
class function TAst.FunctionCall(
|
||||||
const ACallee: IAstNode;
|
const ACallee: IAstNode;
|
||||||
const AArguments: TArray<IAstNode>;
|
const AArguments: TArray<IAstNode>;
|
||||||
const Loc: ISourceLocation
|
const Loc: ISourceLocation
|
||||||
): IFunctionCallNode;
|
): IFunctionCallNode;
|
||||||
begin
|
begin
|
||||||
|
var listId := TIdentities.List('', '', ' ', Loc);
|
||||||
|
var argList := TArgumentList.Create(AArguments, listId);
|
||||||
|
|
||||||
var id := TIdentities.Structural(Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
Result := TFunctionCallNode.Create(ACallee, AArguments, TTypes.Unknown, False, nil, False, id);
|
Result := TFunctionCallNode.Create(ACallee, argList, TTypes.Unknown, False, nil, False, id);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TAst.FunctionCall(
|
class function TAst.FunctionCall(
|
||||||
const Identity: IAstIdentity;
|
const Identity: IAstIdentity;
|
||||||
const ACallee: IAstNode;
|
const ACallee: IAstNode;
|
||||||
const AArguments: TArray<IAstNode>;
|
const AArguments: IArgumentList;
|
||||||
const AStaticType: IStaticType;
|
const AStaticType: IStaticType;
|
||||||
const AIsTailCall: Boolean;
|
const AIsTailCall: Boolean;
|
||||||
const AStaticTarget: TDataValue.TFunc;
|
const AStaticTarget: TDataValue.TFunc;
|
||||||
@@ -648,8 +643,6 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- MacroExpansion ---
|
|
||||||
|
|
||||||
class function TAst.MacroExpansionNode(
|
class function TAst.MacroExpansionNode(
|
||||||
const AOriginalCallNode: IFunctionCallNode;
|
const AOriginalCallNode: IFunctionCallNode;
|
||||||
const AExpandedBody: IAstNode;
|
const AExpandedBody: IAstNode;
|
||||||
@@ -669,8 +662,6 @@ begin
|
|||||||
Result := TMacroExpansionNode.Create(AOriginalCallNode, AExpandedBody, Identity);
|
Result := TMacroExpansionNode.Create(AOriginalCallNode, AExpandedBody, Identity);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- Recur ---
|
|
||||||
|
|
||||||
class function TAst.Recur(const AArguments: array of IAstNode; const Loc: ISourceLocation): IRecurNode;
|
class function TAst.Recur(const AArguments: array of IAstNode; const Loc: ISourceLocation): IRecurNode;
|
||||||
var
|
var
|
||||||
args: TArray<IAstNode>;
|
args: TArray<IAstNode>;
|
||||||
@@ -679,11 +670,15 @@ begin
|
|||||||
SetLength(args, Length(AArguments));
|
SetLength(args, Length(AArguments));
|
||||||
for i := 0 to High(AArguments) do
|
for i := 0 to High(AArguments) do
|
||||||
args[i] := AArguments[i];
|
args[i] := AArguments[i];
|
||||||
|
|
||||||
|
var listId := TIdentities.List('', '', ' ', Loc);
|
||||||
|
var argList := TArgumentList.Create(args, listId);
|
||||||
|
|
||||||
var id := TIdentities.Structural(Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
Result := TRecurNode.Create(args, TTypes.Void, id);
|
Result := TRecurNode.Create(argList, TTypes.Void, id);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TAst.Recur(const Identity: IAstIdentity; const AArguments: TArray<IAstNode>; const AStaticType: IStaticType): IRecurNode;
|
class function TAst.Recur(const Identity: IAstIdentity; const AArguments: IArgumentList; const AStaticType: IStaticType): IRecurNode;
|
||||||
begin
|
begin
|
||||||
Result :=
|
Result :=
|
||||||
TRecurNode.Create(
|
TRecurNode.Create(
|
||||||
@@ -694,8 +689,6 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- Block ---
|
|
||||||
|
|
||||||
class function TAst.Block(const AExpressions: array of IAstNode; const Loc: ISourceLocation): IBlockExpressionNode;
|
class function TAst.Block(const AExpressions: array of IAstNode; const Loc: ISourceLocation): IBlockExpressionNode;
|
||||||
var
|
var
|
||||||
exprs: TArray<IAstNode>;
|
exprs: TArray<IAstNode>;
|
||||||
@@ -704,13 +697,17 @@ begin
|
|||||||
SetLength(exprs, Length(AExpressions));
|
SetLength(exprs, Length(AExpressions));
|
||||||
for i := 0 to High(AExpressions) do
|
for i := 0 to High(AExpressions) do
|
||||||
exprs[i] := AExpressions[i];
|
exprs[i] := AExpressions[i];
|
||||||
|
|
||||||
|
var listId := TIdentities.List('', '', ' ', Loc);
|
||||||
|
var exprList := TExpressionList.Create(exprs, listId);
|
||||||
|
|
||||||
var id := TIdentities.Structural(Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
Result := TBlockExpressionNode.Create(exprs, TTypes.Unknown, id);
|
Result := TBlockExpressionNode.Create(exprList, TTypes.Unknown, id);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TAst.Block(
|
class function TAst.Block(
|
||||||
const Identity: IAstIdentity;
|
const Identity: IAstIdentity;
|
||||||
const AExpressions: TArray<IAstNode>;
|
const AExpressions: IExpressionList;
|
||||||
const AStaticType: IStaticType
|
const AStaticType: IStaticType
|
||||||
): IBlockExpressionNode;
|
): IBlockExpressionNode;
|
||||||
begin
|
begin
|
||||||
@@ -723,8 +720,6 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- VarDecl ---
|
|
||||||
|
|
||||||
class function TAst.VarDecl(const AIdentifier: IAstNode; AInitializer: IAstNode; const Loc: ISourceLocation): IVariableDeclarationNode;
|
class function TAst.VarDecl(const AIdentifier: IAstNode; AInitializer: IAstNode; const Loc: ISourceLocation): IVariableDeclarationNode;
|
||||||
begin
|
begin
|
||||||
var id := TIdentities.Structural(Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
@@ -750,8 +745,6 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- Assign ---
|
|
||||||
|
|
||||||
class function TAst.Assign(const ATarget, AValue: IAstNode; const Loc: ISourceLocation): IAssignmentNode;
|
class function TAst.Assign(const ATarget, AValue: IAstNode; const Loc: ISourceLocation): IAssignmentNode;
|
||||||
begin
|
begin
|
||||||
var id := TIdentities.Structural(Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
@@ -770,15 +763,6 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TAst.AssignResult(const AValue: IAstNode; const Loc: ISourceLocation): IAssignmentNode;
|
|
||||||
begin
|
|
||||||
// Helper: Creates an implicit Identifier "Result" with new Identity
|
|
||||||
var resultId := TAst.Identifier('Result', Loc);
|
|
||||||
Result := TAst.Assign(resultId, AValue, Loc);
|
|
||||||
end;
|
|
||||||
|
|
||||||
// --- Indexer ---
|
|
||||||
|
|
||||||
class function TAst.Indexer(const ABase, AIndex: IAstNode; const Loc: ISourceLocation): IIndexerNode;
|
class function TAst.Indexer(const ABase, AIndex: IAstNode; const Loc: ISourceLocation): IIndexerNode;
|
||||||
begin
|
begin
|
||||||
var id := TIdentities.Structural(Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
@@ -797,8 +781,6 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- MemberAccess ---
|
|
||||||
|
|
||||||
class function TAst.MemberAccess(const ABase: IAstNode; const AMember: IKeywordNode; const Loc: ISourceLocation): IMemberAccessNode;
|
class function TAst.MemberAccess(const ABase: IAstNode; const AMember: IKeywordNode; const Loc: ISourceLocation): IMemberAccessNode;
|
||||||
begin
|
begin
|
||||||
var id := TIdentities.Structural(Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
@@ -822,17 +804,29 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- RecordLiteral ---
|
class function TAst.RecordField(const AKey: IKeywordNode; const AValue: IAstNode; const Loc: ISourceLocation): IRecordFieldNode;
|
||||||
|
|
||||||
class function TAst.RecordLiteral(const AFields: TArray<TRecordFieldLiteral>; const Loc: ISourceLocation): IRecordLiteralNode;
|
|
||||||
begin
|
begin
|
||||||
var id := TIdentities.Structural(Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
Result := TRecordLiteralNode.Create(AFields, nil, nil, TTypes.Unknown, id);
|
Result := TRecordFieldNode.Create(AKey, AValue, id);
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TAst.RecordField(const Identity: IAstIdentity; const AKey: IKeywordNode; const AValue: IAstNode): IRecordFieldNode;
|
||||||
|
begin
|
||||||
|
Result := TRecordFieldNode.Create(AKey, AValue, Identity);
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TAst.RecordLiteral(const AFields: TArray<IRecordFieldNode>; const Loc: ISourceLocation): IRecordLiteralNode;
|
||||||
|
begin
|
||||||
|
var listId := TIdentities.List('{', '}', ' ', Loc);
|
||||||
|
var fieldList := TRecordFieldList.Create(AFields, listId);
|
||||||
|
|
||||||
|
var id := TIdentities.Structural(Loc);
|
||||||
|
Result := TRecordLiteralNode.Create(fieldList, nil, nil, TTypes.Unknown, id);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TAst.RecordLiteral(
|
class function TAst.RecordLiteral(
|
||||||
const Identity: IAstIdentity;
|
const Identity: IAstIdentity;
|
||||||
const AFields: TArray<TRecordFieldLiteral>;
|
const AFields: IRecordFieldList;
|
||||||
const AScalarDefinition: IScalarRecordDefinition;
|
const AScalarDefinition: IScalarRecordDefinition;
|
||||||
const AGenericDefinition: IGenericRecordDefinition;
|
const AGenericDefinition: IGenericRecordDefinition;
|
||||||
const AStaticType: IStaticType
|
const AStaticType: IStaticType
|
||||||
@@ -849,11 +843,10 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- AddSeriesItem ---
|
|
||||||
|
|
||||||
class function TAst.AddSeriesItem(
|
class function TAst.AddSeriesItem(
|
||||||
const ASeries: IIdentifierNode;
|
const ASeries: IIdentifierNode;
|
||||||
const AValue, ALookback: IAstNode;
|
const AValue: IAstNode;
|
||||||
|
const ALookback: IAstNode;
|
||||||
const Loc: ISourceLocation
|
const Loc: ISourceLocation
|
||||||
): IAddSeriesItemNode;
|
): IAddSeriesItemNode;
|
||||||
begin
|
begin
|
||||||
@@ -864,7 +857,8 @@ end;
|
|||||||
class function TAst.AddSeriesItem(
|
class function TAst.AddSeriesItem(
|
||||||
const Identity: IAstIdentity;
|
const Identity: IAstIdentity;
|
||||||
const ASeries: IIdentifierNode;
|
const ASeries: IIdentifierNode;
|
||||||
const AValue, ALookback: IAstNode;
|
const AValue: IAstNode;
|
||||||
|
const ALookback: IAstNode;
|
||||||
const AStaticType: IStaticType
|
const AStaticType: IStaticType
|
||||||
): IAddSeriesItemNode;
|
): IAddSeriesItemNode;
|
||||||
begin
|
begin
|
||||||
@@ -879,8 +873,6 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- SeriesLength ---
|
|
||||||
|
|
||||||
class function TAst.SeriesLength(const ASeries: IIdentifierNode; const Loc: ISourceLocation): ISeriesLengthNode;
|
class function TAst.SeriesLength(const ASeries: IIdentifierNode; const Loc: ISourceLocation): ISeriesLengthNode;
|
||||||
begin
|
begin
|
||||||
var id := TIdentities.Structural(Loc);
|
var id := TIdentities.Structural(Loc);
|
||||||
|
|||||||
@@ -577,15 +577,22 @@ var
|
|||||||
effBorderWidth: Single;
|
effBorderWidth: Single;
|
||||||
effDash: TStrokeDash;
|
effDash: TStrokeDash;
|
||||||
isHovering: Boolean;
|
isHovering: Boolean;
|
||||||
isBlock: Boolean;
|
shouldIgnoreHover: Boolean;
|
||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
|
|
||||||
// Check if this is a block node (blocks should not highlight on hover)
|
shouldIgnoreHover := False;
|
||||||
isBlock := Assigned(Node) and (Node.Kind = TAstNodeKind.akBlockExpression);
|
if Assigned(Node) then
|
||||||
|
begin
|
||||||
|
case Node.Kind of
|
||||||
|
// Lists and Blocks should generally not be highlighted as a whole on hover
|
||||||
|
// because they are containers for other selectable items.
|
||||||
|
akBlockExpression, akParameterList, akArgumentList, akExpressionList, akRecordFieldList: shouldIgnoreHover := True;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
// Determine hover state: active only if mouse is over AND it is not a block
|
// Determine hover state: active only if mouse is over AND it is not a container type
|
||||||
isHovering := IsMouseOver and (not isBlock);
|
isHovering := IsMouseOver and (not shouldIgnoreHover);
|
||||||
|
|
||||||
// 1. Set base values
|
// 1. Set base values
|
||||||
if FFrameless then
|
if FFrameless then
|
||||||
|
|||||||
@@ -20,7 +20,62 @@ uses
|
|||||||
Myc.Fmx.AstEditor.Core;
|
Myc.Fmx.AstEditor.Core;
|
||||||
|
|
||||||
type
|
type
|
||||||
// --- Basic Handlers ---
|
// --- Abstract List Base ---
|
||||||
|
// Handles layout, brackets (from Identity), and child iteration
|
||||||
|
TNodeListHandler<T: IAstNode> = class(TBaseNodeHandler<INodeList<T>>)
|
||||||
|
protected
|
||||||
|
FChildNodes: TList<TAstViewNode>;
|
||||||
|
function GetOrientation: TLayoutOrientation; virtual; abstract;
|
||||||
|
function GetAlignment: TLayoutAlignment; virtual;
|
||||||
|
public
|
||||||
|
constructor Create(const ANode: INodeList<T>);
|
||||||
|
destructor Destroy; override;
|
||||||
|
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
||||||
|
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; abstract;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// --- Concrete List Handlers ---
|
||||||
|
|
||||||
|
TParameterListHandler = class(TNodeListHandler<IIdentifierNode>)
|
||||||
|
protected
|
||||||
|
function GetOrientation: TLayoutOrientation; override;
|
||||||
|
public
|
||||||
|
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TArgumentListHandler = class(TNodeListHandler<IAstNode>)
|
||||||
|
protected
|
||||||
|
function GetOrientation: TLayoutOrientation; override;
|
||||||
|
public
|
||||||
|
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TExpressionListHandler = class(TNodeListHandler<IAstNode>)
|
||||||
|
protected
|
||||||
|
function GetOrientation: TLayoutOrientation; override;
|
||||||
|
function GetAlignment: TLayoutAlignment; override;
|
||||||
|
public
|
||||||
|
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TRecordFieldListHandler = class(TNodeListHandler<IRecordFieldNode>)
|
||||||
|
protected
|
||||||
|
function GetOrientation: TLayoutOrientation; override;
|
||||||
|
function GetAlignment: TLayoutAlignment; override;
|
||||||
|
public
|
||||||
|
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// --- Node Handlers ---
|
||||||
|
|
||||||
|
TRecordFieldHandler = class(TBaseNodeHandler<IRecordFieldNode>)
|
||||||
|
private
|
||||||
|
FKeyLabel: TLabel;
|
||||||
|
FValueNode: TAstViewNode;
|
||||||
|
public
|
||||||
|
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
||||||
|
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
||||||
|
end;
|
||||||
|
|
||||||
TConstantNodeHandler = class(TBaseNodeHandler<IConstantNode>)
|
TConstantNodeHandler = class(TBaseNodeHandler<IConstantNode>)
|
||||||
public
|
public
|
||||||
@@ -50,10 +105,8 @@ type
|
|||||||
|
|
||||||
TBlockExpressionNodeHandler = class(TBaseNodeHandler<IBlockExpressionNode>)
|
TBlockExpressionNodeHandler = class(TBaseNodeHandler<IBlockExpressionNode>)
|
||||||
private
|
private
|
||||||
FChildNodes: TList<TAstViewNode>;
|
FExpressionsNode: TAstViewNode;
|
||||||
public
|
public
|
||||||
constructor Create(const ANode: IBlockExpressionNode);
|
|
||||||
destructor Destroy; override;
|
|
||||||
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
||||||
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
||||||
end;
|
end;
|
||||||
@@ -82,11 +135,9 @@ type
|
|||||||
|
|
||||||
TLambdaExpressionNodeHandler = class(TBaseNodeHandler<ILambdaExpressionNode>)
|
TLambdaExpressionNodeHandler = class(TBaseNodeHandler<ILambdaExpressionNode>)
|
||||||
private
|
private
|
||||||
|
FParamsNode: TAstViewNode;
|
||||||
FBodyNode: TAstViewNode;
|
FBodyNode: TAstViewNode;
|
||||||
FParamLabels: TList<TLabel>;
|
|
||||||
public
|
public
|
||||||
constructor Create(const ANode: ILambdaExpressionNode);
|
|
||||||
destructor Destroy; override;
|
|
||||||
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
||||||
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
||||||
end;
|
end;
|
||||||
@@ -94,10 +145,8 @@ type
|
|||||||
TFunctionCallNodeHandler = class(TBaseNodeHandler<IFunctionCallNode>)
|
TFunctionCallNodeHandler = class(TBaseNodeHandler<IFunctionCallNode>)
|
||||||
private
|
private
|
||||||
FCalleeNode: TAstViewNode;
|
FCalleeNode: TAstViewNode;
|
||||||
FArgumentNodes: TList<TAstViewNode>;
|
FArgumentsNode: TAstViewNode;
|
||||||
public
|
public
|
||||||
constructor Create(const ANode: IFunctionCallNode);
|
|
||||||
destructor Destroy; override;
|
|
||||||
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
||||||
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
||||||
end;
|
end;
|
||||||
@@ -112,10 +161,8 @@ type
|
|||||||
|
|
||||||
TRecurNodeHandler = class(TBaseNodeHandler<IRecurNode>)
|
TRecurNodeHandler = class(TBaseNodeHandler<IRecurNode>)
|
||||||
private
|
private
|
||||||
FArgumentNodes: TList<TAstViewNode>;
|
FArgumentsNode: TAstViewNode;
|
||||||
public
|
public
|
||||||
constructor Create(const ANode: IRecurNode);
|
|
||||||
destructor Destroy; override;
|
|
||||||
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
||||||
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
||||||
end;
|
end;
|
||||||
@@ -142,6 +189,7 @@ type
|
|||||||
|
|
||||||
TMacroDefinitionNodeHandler = class(TBaseNodeHandler<IMacroDefinitionNode>)
|
TMacroDefinitionNodeHandler = class(TBaseNodeHandler<IMacroDefinitionNode>)
|
||||||
private
|
private
|
||||||
|
FParamsNode: TAstViewNode;
|
||||||
FBodyNode: TAstViewNode;
|
FBodyNode: TAstViewNode;
|
||||||
public
|
public
|
||||||
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
||||||
@@ -195,10 +243,8 @@ type
|
|||||||
|
|
||||||
TRecordLiteralNodeHandler = class(TBaseNodeHandler<IRecordLiteralNode>)
|
TRecordLiteralNodeHandler = class(TBaseNodeHandler<IRecordLiteralNode>)
|
||||||
private
|
private
|
||||||
FFieldNodes: TDictionary<IKeyword, TAstViewNode>;
|
FFieldsNode: TAstViewNode;
|
||||||
public
|
public
|
||||||
constructor Create(const ANode: IRecordLiteralNode);
|
|
||||||
destructor Destroy; override;
|
|
||||||
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
procedure BuildUI(OwnerNode: TAstViewNode); override;
|
||||||
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override;
|
||||||
end;
|
end;
|
||||||
@@ -228,6 +274,200 @@ type
|
|||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
{ TNodeListHandler<T> }
|
||||||
|
|
||||||
|
constructor TNodeListHandler<T>.Create(const ANode: INodeList<T>);
|
||||||
|
begin
|
||||||
|
inherited Create(ANode);
|
||||||
|
FChildNodes := TList<TAstViewNode>.Create;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TNodeListHandler<T>.Destroy;
|
||||||
|
begin
|
||||||
|
FChildNodes.Free;
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TNodeListHandler<T>.GetAlignment: TLayoutAlignment;
|
||||||
|
begin
|
||||||
|
Result := TLayoutAlignment.laCenter;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TNodeListHandler<T>.BuildUI(OwnerNode: TAstViewNode);
|
||||||
|
var
|
||||||
|
visu: IAstVisualizer;
|
||||||
|
i: Integer;
|
||||||
|
childView: TAstViewNode;
|
||||||
|
openTok, closeTok, sep: string;
|
||||||
|
listId: IListIdentity;
|
||||||
|
begin
|
||||||
|
if (FNode.Identity <> nil) and (FNode.Identity.Kind = ikList) then
|
||||||
|
begin
|
||||||
|
listId := FNode.Identity.AsList;
|
||||||
|
openTok := listId.OpenToken;
|
||||||
|
closeTok := listId.CloseToken;
|
||||||
|
sep := listId.Separator;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
openTok := '';
|
||||||
|
closeTok := '';
|
||||||
|
sep := ' ';
|
||||||
|
end;
|
||||||
|
|
||||||
|
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth);
|
||||||
|
|
||||||
|
OwnerNode.BeginUpdate;
|
||||||
|
try
|
||||||
|
OwnerNode.Frameless := True;
|
||||||
|
OwnerNode.Orientation := GetOrientation;
|
||||||
|
OwnerNode.Alignment := GetAlignment;
|
||||||
|
|
||||||
|
if openTok <> '' then
|
||||||
|
OwnerNode.AddLabel(OwnerNode, openTok);
|
||||||
|
|
||||||
|
for i := 0 to FNode.Count - 1 do
|
||||||
|
begin
|
||||||
|
childView := visu.CallAccept(FNode[i]);
|
||||||
|
FChildNodes.Add(childView);
|
||||||
|
|
||||||
|
if (i < FNode.Count - 1) and (sep <> '') and (sep <> ' ') then
|
||||||
|
OwnerNode.AddLabel(OwnerNode, sep);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if closeTok <> '' then
|
||||||
|
OwnerNode.AddLabel(OwnerNode, closeTok);
|
||||||
|
|
||||||
|
if FNode.Count = 0 then
|
||||||
|
begin
|
||||||
|
if (openTok = '') and (closeTok = '') then
|
||||||
|
begin
|
||||||
|
var lbl := OwnerNode.AddLabel(OwnerNode, 'ø');
|
||||||
|
lbl.Opacity := 0.5;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
finally
|
||||||
|
OwnerNode.EndUpdate;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TParameterListHandler }
|
||||||
|
|
||||||
|
function TParameterListHandler.GetOrientation: TLayoutOrientation;
|
||||||
|
begin
|
||||||
|
Result := loHorizontal;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TParameterListHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
|
var
|
||||||
|
arr: TArray<IIdentifierNode>;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
SetLength(arr, FChildNodes.Count);
|
||||||
|
for i := 0 to FChildNodes.Count - 1 do
|
||||||
|
arr[i] := FChildNodes[i].CreateAst.AsIdentifier;
|
||||||
|
|
||||||
|
Result := TParameterList.Create(arr, FNode.Identity);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TArgumentListHandler }
|
||||||
|
|
||||||
|
function TArgumentListHandler.GetOrientation: TLayoutOrientation;
|
||||||
|
begin
|
||||||
|
Result := loHorizontal;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TArgumentListHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
|
var
|
||||||
|
arr: TArray<IAstNode>;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
SetLength(arr, FChildNodes.Count);
|
||||||
|
for i := 0 to FChildNodes.Count - 1 do
|
||||||
|
arr[i] := FChildNodes[i].CreateAst;
|
||||||
|
|
||||||
|
Result := TArgumentList.Create(arr, FNode.Identity);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TExpressionListHandler }
|
||||||
|
|
||||||
|
function TExpressionListHandler.GetOrientation: TLayoutOrientation;
|
||||||
|
begin
|
||||||
|
Result := loVertical;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TExpressionListHandler.GetAlignment: TLayoutAlignment;
|
||||||
|
begin
|
||||||
|
Result := laFlush;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TExpressionListHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
|
var
|
||||||
|
arr: TArray<IAstNode>;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
SetLength(arr, FChildNodes.Count);
|
||||||
|
for i := 0 to FChildNodes.Count - 1 do
|
||||||
|
arr[i] := FChildNodes[i].CreateAst;
|
||||||
|
|
||||||
|
Result := TExpressionList.Create(arr, FNode.Identity);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TRecordFieldListHandler }
|
||||||
|
|
||||||
|
function TRecordFieldListHandler.GetOrientation: TLayoutOrientation;
|
||||||
|
begin
|
||||||
|
Result := loVertical;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRecordFieldListHandler.GetAlignment: TLayoutAlignment;
|
||||||
|
begin
|
||||||
|
Result := laFlush;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRecordFieldListHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
|
var
|
||||||
|
arr: TArray<IRecordFieldNode>;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
SetLength(arr, FChildNodes.Count);
|
||||||
|
for i := 0 to FChildNodes.Count - 1 do
|
||||||
|
arr[i] := FChildNodes[i].CreateAst.AsRecordField;
|
||||||
|
|
||||||
|
Result := TRecordFieldList.Create(arr, FNode.Identity);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TRecordFieldHandler }
|
||||||
|
|
||||||
|
procedure TRecordFieldHandler.BuildUI(OwnerNode: TAstViewNode);
|
||||||
|
var
|
||||||
|
visu: IAstVisualizer;
|
||||||
|
begin
|
||||||
|
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth);
|
||||||
|
OwnerNode.BeginUpdate;
|
||||||
|
try
|
||||||
|
OwnerNode.Frameless := True;
|
||||||
|
OwnerNode.Orientation := loHorizontal;
|
||||||
|
OwnerNode.Alignment := laCenter;
|
||||||
|
|
||||||
|
FKeyLabel := OwnerNode.AddLabel(OwnerNode, ':' + FNode.Key.Value.Name);
|
||||||
|
FKeyLabel.Font.Style := FKeyLabel.Font.Style + [TFontStyle.fsBold];
|
||||||
|
FKeyLabel.StyledSettings := FKeyLabel.StyledSettings - [TStyledSetting.FontColor];
|
||||||
|
FKeyLabel.FontColor := TAlphaColors.Mediumvioletred;
|
||||||
|
|
||||||
|
FValueNode := visu.CallAccept(FNode.Value);
|
||||||
|
finally
|
||||||
|
OwnerNode.EndUpdate;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TRecordFieldHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
|
begin
|
||||||
|
// Updated to use new Factory Overload to preserve Identity
|
||||||
|
Result := TAst.RecordField(FNode.Identity, FNode.Key, FValueNode.CreateAst);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TConstantNodeHandler }
|
{ TConstantNodeHandler }
|
||||||
|
|
||||||
procedure TConstantNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
procedure TConstantNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
||||||
@@ -335,76 +575,31 @@ end;
|
|||||||
|
|
||||||
{ TBlockExpressionNodeHandler }
|
{ TBlockExpressionNodeHandler }
|
||||||
|
|
||||||
constructor TBlockExpressionNodeHandler.Create(const ANode: IBlockExpressionNode);
|
|
||||||
begin
|
|
||||||
inherited Create(ANode);
|
|
||||||
FChildNodes := TList<TAstViewNode>.Create;
|
|
||||||
end;
|
|
||||||
|
|
||||||
destructor TBlockExpressionNodeHandler.Destroy;
|
|
||||||
begin
|
|
||||||
FChildNodes.Free;
|
|
||||||
inherited;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TBlockExpressionNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
procedure TBlockExpressionNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
||||||
var
|
var
|
||||||
visu: IAstVisualizer;
|
visu: IAstVisualizer;
|
||||||
childNode: TAstViewNode;
|
|
||||||
expr: IAstNode;
|
|
||||||
titleLabel: TLabel;
|
titleLabel: TLabel;
|
||||||
i: Integer;
|
|
||||||
returnContainer: TAutoFitControl;
|
|
||||||
visuReturn: IAstVisualizer;
|
|
||||||
begin
|
begin
|
||||||
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
||||||
OwnerNode.BeginUpdate;
|
OwnerNode.BeginUpdate;
|
||||||
try
|
try
|
||||||
OwnerNode.Frameless := True;
|
OwnerNode.Frameless := False;
|
||||||
OwnerNode.Orientation := loVertical;
|
OwnerNode.Orientation := loVertical;
|
||||||
OwnerNode.Alignment := laFlush;
|
OwnerNode.Alignment := laFlush;
|
||||||
|
|
||||||
for i := 0 to High(FNode.Expressions) do
|
titleLabel := OwnerNode.AddLabel(OwnerNode, 'do');
|
||||||
begin
|
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
|
||||||
expr := FNode.Expressions[i];
|
|
||||||
|
|
||||||
if i = High(FNode.Expressions) then
|
FExpressionsNode := visu.CallAccept(FNode.Expressions);
|
||||||
begin
|
FExpressionsNode.Frameless := True;
|
||||||
returnContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
|
|
||||||
titleLabel := OwnerNode.AddLabel(returnContainer, 'return');
|
|
||||||
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
|
|
||||||
visuReturn := OwnerNode.Visualizer.Clone(returnContainer, OwnerNode.Visualizer.ExprDepth + 1);
|
|
||||||
childNode := visuReturn.CallAccept(expr);
|
|
||||||
FChildNodes.Add(childNode);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
childNode := visu.CallAccept(expr);
|
|
||||||
FChildNodes.Add(childNode);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
finally
|
finally
|
||||||
OwnerNode.EndUpdate;
|
OwnerNode.EndUpdate;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TBlockExpressionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
function TBlockExpressionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
var
|
|
||||||
exprs: TArray<IAstNode>;
|
|
||||||
childNode: TAstViewNode;
|
|
||||||
i: Integer;
|
|
||||||
begin
|
begin
|
||||||
SetLength(exprs, FChildNodes.Count);
|
Result := TAst.Block(FNode.Identity, FExpressionsNode.CreateAst.AsExpressionList, FNode.StaticType);
|
||||||
for i := 0 to FChildNodes.Count - 1 do
|
|
||||||
begin
|
|
||||||
childNode := FChildNodes[i];
|
|
||||||
if Assigned(childNode) then
|
|
||||||
exprs[i] := childNode.CreateAst
|
|
||||||
else
|
|
||||||
exprs[i] := TAst.Nop;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Result := TAst.Block(FNode.Identity, exprs, FNode.StaticType);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TIfExpressionNodeHandler }
|
{ TIfExpressionNodeHandler }
|
||||||
@@ -466,24 +661,11 @@ end;
|
|||||||
|
|
||||||
{ TLambdaExpressionNodeHandler }
|
{ TLambdaExpressionNodeHandler }
|
||||||
|
|
||||||
constructor TLambdaExpressionNodeHandler.Create(const ANode: ILambdaExpressionNode);
|
|
||||||
begin
|
|
||||||
inherited Create(ANode);
|
|
||||||
FParamLabels := TList<TLabel>.Create;
|
|
||||||
end;
|
|
||||||
|
|
||||||
destructor TLambdaExpressionNodeHandler.Destroy;
|
|
||||||
begin
|
|
||||||
FParamLabels.Free;
|
|
||||||
inherited;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TLambdaExpressionNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
procedure TLambdaExpressionNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
||||||
var
|
var
|
||||||
visu: IAstVisualizer;
|
visu: IAstVisualizer;
|
||||||
titleContainer: TAutoFitControl;
|
titleContainer: TAutoFitControl;
|
||||||
paramLabel: TLabel;
|
lbl: TLabel;
|
||||||
i: Integer;
|
|
||||||
begin
|
begin
|
||||||
visu := OwnerNode.Visualizer.Clone(OwnerNode, 0);
|
visu := OwnerNode.Visualizer.Clone(OwnerNode, 0);
|
||||||
OwnerNode.BeginUpdate;
|
OwnerNode.BeginUpdate;
|
||||||
@@ -494,32 +676,16 @@ begin
|
|||||||
OwnerNode.BackgroundColor := $090000ff;
|
OwnerNode.BackgroundColor := $090000ff;
|
||||||
|
|
||||||
titleContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
|
titleContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
|
||||||
|
lbl := OwnerNode.AddLabel(titleContainer, 'fn');
|
||||||
|
lbl.Font.Style := lbl.Font.Style + [TFontStyle.fsBold];
|
||||||
|
|
||||||
paramLabel := OwnerNode.AddLabel(titleContainer, 'fn');
|
// Parameters: Delegate to List Handler
|
||||||
paramLabel.Font.Style := paramLabel.Font.Style + [TFontStyle.fsBold];
|
var paramVisu := visu.Clone(titleContainer, 0);
|
||||||
FParamLabels.Add(paramLabel);
|
FParamsNode := paramVisu.CallAccept(FNode.Parameters);
|
||||||
|
|
||||||
paramLabel := OwnerNode.AddLabel(titleContainer, '(');
|
|
||||||
FParamLabels.Add(paramLabel);
|
|
||||||
|
|
||||||
for i := 0 to High(FNode.Parameters) do
|
|
||||||
begin
|
|
||||||
paramLabel := OwnerNode.AddLabel(titleContainer, FNode.Parameters[i].Name);
|
|
||||||
FParamLabels.Add(paramLabel);
|
|
||||||
|
|
||||||
if i < High(FNode.Parameters) then
|
|
||||||
begin
|
|
||||||
paramLabel := OwnerNode.AddLabel(titleContainer, ',');
|
|
||||||
FParamLabels.Add(paramLabel);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
paramLabel := OwnerNode.AddLabel(titleContainer, ')');
|
|
||||||
FParamLabels.Add(paramLabel);
|
|
||||||
|
|
||||||
|
// Body
|
||||||
FBodyNode := visu.CallAccept(FNode.Body);
|
FBodyNode := visu.CallAccept(FNode.Body);
|
||||||
FBodyNode.Frameless := False;
|
FBodyNode.Frameless := False;
|
||||||
|
|
||||||
finally
|
finally
|
||||||
OwnerNode.EndUpdate;
|
OwnerNode.EndUpdate;
|
||||||
end;
|
end;
|
||||||
@@ -530,7 +696,7 @@ begin
|
|||||||
Result :=
|
Result :=
|
||||||
TAst.LambdaExpr(
|
TAst.LambdaExpr(
|
||||||
FNode.Identity,
|
FNode.Identity,
|
||||||
FNode.Parameters,
|
FParamsNode.CreateAst.AsParameterList,
|
||||||
FBodyNode.CreateAst,
|
FBodyNode.CreateAst,
|
||||||
FNode.Layout,
|
FNode.Layout,
|
||||||
FNode.Descriptor,
|
FNode.Descriptor,
|
||||||
@@ -543,23 +709,9 @@ end;
|
|||||||
|
|
||||||
{ TFunctionCallNodeHandler }
|
{ TFunctionCallNodeHandler }
|
||||||
|
|
||||||
constructor TFunctionCallNodeHandler.Create(const ANode: IFunctionCallNode);
|
|
||||||
begin
|
|
||||||
inherited Create(ANode);
|
|
||||||
FArgumentNodes := TList<TAstViewNode>.Create;
|
|
||||||
end;
|
|
||||||
|
|
||||||
destructor TFunctionCallNodeHandler.Destroy;
|
|
||||||
begin
|
|
||||||
FArgumentNodes.Free;
|
|
||||||
inherited;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TFunctionCallNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
procedure TFunctionCallNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
||||||
var
|
var
|
||||||
visu: IAstVisualizer;
|
visu: IAstVisualizer;
|
||||||
i: Integer;
|
|
||||||
argNode: TAstViewNode;
|
|
||||||
callLabel: TLabel;
|
callLabel: TLabel;
|
||||||
begin
|
begin
|
||||||
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
||||||
@@ -573,37 +725,19 @@ begin
|
|||||||
|
|
||||||
FCalleeNode := visu.CallAccept(FNode.Callee);
|
FCalleeNode := visu.CallAccept(FNode.Callee);
|
||||||
|
|
||||||
if Length(FNode.Arguments) > 0 then
|
FArgumentsNode := visu.CallAccept(FNode.Arguments);
|
||||||
begin
|
|
||||||
OwnerNode.AddLabel(OwnerNode, '(');
|
|
||||||
for i := 0 to High(FNode.Arguments) do
|
|
||||||
begin
|
|
||||||
argNode := visu.CallAccept(FNode.Arguments[i]);
|
|
||||||
FArgumentNodes.Add(argNode);
|
|
||||||
if i < High(FNode.Arguments) then
|
|
||||||
OwnerNode.AddLabel(OwnerNode, ',');
|
|
||||||
end;
|
|
||||||
OwnerNode.AddLabel(OwnerNode, ')');
|
|
||||||
end;
|
|
||||||
finally
|
finally
|
||||||
OwnerNode.EndUpdate;
|
OwnerNode.EndUpdate;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFunctionCallNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
function TFunctionCallNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
var
|
|
||||||
args: TArray<IAstNode>;
|
|
||||||
i: Integer;
|
|
||||||
begin
|
begin
|
||||||
SetLength(args, FArgumentNodes.Count);
|
|
||||||
for i := 0 to FArgumentNodes.Count - 1 do
|
|
||||||
args[i] := FArgumentNodes[i].CreateAst;
|
|
||||||
|
|
||||||
Result :=
|
Result :=
|
||||||
TAst.FunctionCall(
|
TAst.FunctionCall(
|
||||||
FNode.Identity,
|
FNode.Identity,
|
||||||
FCalleeNode.CreateAst,
|
FCalleeNode.CreateAst,
|
||||||
args,
|
FArgumentsNode.CreateAst.AsArgumentList,
|
||||||
FNode.StaticType,
|
FNode.StaticType,
|
||||||
FNode.IsTailCall,
|
FNode.IsTailCall,
|
||||||
FNode.StaticTarget,
|
FNode.StaticTarget,
|
||||||
@@ -638,23 +772,9 @@ end;
|
|||||||
|
|
||||||
{ TRecurNodeHandler }
|
{ TRecurNodeHandler }
|
||||||
|
|
||||||
constructor TRecurNodeHandler.Create(const ANode: IRecurNode);
|
|
||||||
begin
|
|
||||||
inherited Create(ANode);
|
|
||||||
FArgumentNodes := TList<TAstViewNode>.Create;
|
|
||||||
end;
|
|
||||||
|
|
||||||
destructor TRecurNodeHandler.Destroy;
|
|
||||||
begin
|
|
||||||
FArgumentNodes.Free;
|
|
||||||
inherited;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TRecurNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
procedure TRecurNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
||||||
var
|
var
|
||||||
visu: IAstVisualizer;
|
visu: IAstVisualizer;
|
||||||
i: Integer;
|
|
||||||
argNode: TAstViewNode;
|
|
||||||
titleLabel: TLabel;
|
titleLabel: TLabel;
|
||||||
begin
|
begin
|
||||||
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
||||||
@@ -666,29 +786,15 @@ begin
|
|||||||
titleLabel := OwnerNode.AddLabel(OwnerNode, 'recur');
|
titleLabel := OwnerNode.AddLabel(OwnerNode, 'recur');
|
||||||
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
|
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
|
||||||
|
|
||||||
OwnerNode.AddLabel(OwnerNode, '(');
|
FArgumentsNode := visu.CallAccept(FNode.Arguments);
|
||||||
for i := 0 to High(FNode.Arguments) do
|
|
||||||
begin
|
|
||||||
argNode := visu.CallAccept(FNode.Arguments[i]);
|
|
||||||
FArgumentNodes.Add(argNode);
|
|
||||||
if i < High(FNode.Arguments) then
|
|
||||||
OwnerNode.AddLabel(OwnerNode, ',');
|
|
||||||
end;
|
|
||||||
OwnerNode.AddLabel(OwnerNode, ')');
|
|
||||||
finally
|
finally
|
||||||
OwnerNode.EndUpdate;
|
OwnerNode.EndUpdate;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TRecurNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
function TRecurNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
var
|
|
||||||
args: TArray<IAstNode>;
|
|
||||||
i: Integer;
|
|
||||||
begin
|
begin
|
||||||
SetLength(args, FArgumentNodes.Count);
|
Result := TAst.Recur(FNode.Identity, FArgumentsNode.CreateAst.AsArgumentList, FNode.StaticType);
|
||||||
for i := 0 to FArgumentNodes.Count - 1 do
|
|
||||||
args[i] := FArgumentNodes[i].CreateAst;
|
|
||||||
Result := TAst.Recur(FNode.Identity, args, FNode.StaticType);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TVariableDeclarationNodeHandler }
|
{ TVariableDeclarationNodeHandler }
|
||||||
@@ -762,8 +868,7 @@ procedure TMacroDefinitionNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
|||||||
var
|
var
|
||||||
visu: IAstVisualizer;
|
visu: IAstVisualizer;
|
||||||
titleLabel: TLabel;
|
titleLabel: TLabel;
|
||||||
paramStr: string;
|
titleContainer: TAutoFitControl;
|
||||||
i: Integer;
|
|
||||||
begin
|
begin
|
||||||
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
||||||
OwnerNode.BeginUpdate;
|
OwnerNode.BeginUpdate;
|
||||||
@@ -771,17 +876,14 @@ begin
|
|||||||
OwnerNode.Frameless := False;
|
OwnerNode.Frameless := False;
|
||||||
OwnerNode.Orientation := loVertical;
|
OwnerNode.Orientation := loVertical;
|
||||||
|
|
||||||
paramStr := '';
|
titleContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
|
||||||
for i := 0 to High(FNode.Parameters) do
|
titleLabel := OwnerNode.AddLabel(titleContainer, 'Macro Def: ' + FNode.Name.Name);
|
||||||
begin
|
|
||||||
if i > 0 then
|
|
||||||
paramStr := paramStr + ', ';
|
|
||||||
paramStr := paramStr + FNode.Parameters[i].Name;
|
|
||||||
end;
|
|
||||||
|
|
||||||
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Macro Def: ' + FNode.Name.Name + ' (' + paramStr + ')');
|
|
||||||
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
|
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
|
||||||
|
|
||||||
|
// Parameters List
|
||||||
|
var paramVisu := visu.Clone(titleContainer, visu.ExprDepth);
|
||||||
|
FParamsNode := paramVisu.CallAccept(FNode.Parameters);
|
||||||
|
|
||||||
FBodyNode := visu.CallAccept(FNode.Body);
|
FBodyNode := visu.CallAccept(FNode.Body);
|
||||||
finally
|
finally
|
||||||
OwnerNode.EndUpdate;
|
OwnerNode.EndUpdate;
|
||||||
@@ -790,7 +892,7 @@ end;
|
|||||||
|
|
||||||
function TMacroDefinitionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
function TMacroDefinitionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
begin
|
begin
|
||||||
Result := TAst.MacroDef(FNode.Identity, FNode.Name, FNode.Parameters, FBodyNode.CreateAst);
|
Result := TAst.MacroDef(FNode.Identity, FNode.Name, FParamsNode.CreateAst.AsParameterList, FBodyNode.CreateAst);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TQuasiquoteNodeHandler }
|
{ TQuasiquoteNodeHandler }
|
||||||
@@ -927,70 +1029,34 @@ end;
|
|||||||
|
|
||||||
{ TRecordLiteralNodeHandler }
|
{ TRecordLiteralNodeHandler }
|
||||||
|
|
||||||
constructor TRecordLiteralNodeHandler.Create(const ANode: IRecordLiteralNode);
|
|
||||||
begin
|
|
||||||
inherited Create(ANode);
|
|
||||||
FFieldNodes := TDictionary<IKeyword, TAstViewNode>.Create;
|
|
||||||
end;
|
|
||||||
|
|
||||||
destructor TRecordLiteralNodeHandler.Destroy;
|
|
||||||
begin
|
|
||||||
FFieldNodes.Free;
|
|
||||||
inherited;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TRecordLiteralNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
procedure TRecordLiteralNodeHandler.BuildUI(OwnerNode: TAstViewNode);
|
||||||
var
|
var
|
||||||
field: TRecordFieldLiteral;
|
visu: IAstVisualizer;
|
||||||
fieldContainer: TAutoFitControl;
|
|
||||||
valueNode: TAstViewNode;
|
|
||||||
keyLabel: TLabel;
|
|
||||||
begin
|
begin
|
||||||
|
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
|
||||||
OwnerNode.BeginUpdate;
|
OwnerNode.BeginUpdate;
|
||||||
try
|
try
|
||||||
OwnerNode.Frameless := False;
|
OwnerNode.Frameless := False;
|
||||||
OwnerNode.Orientation := loVertical;
|
OwnerNode.Orientation := loVertical;
|
||||||
OwnerNode.Alignment := laFlush;
|
OwnerNode.Alignment := laFlush;
|
||||||
|
|
||||||
if Length(FNode.Fields) = 0 then
|
// Delegate to RecordFieldList
|
||||||
begin
|
FFieldsNode := visu.CallAccept(FNode.Fields);
|
||||||
OwnerNode.AddLabel(OwnerNode, '{}');
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
for field in FNode.Fields do
|
|
||||||
begin
|
|
||||||
fieldContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
|
|
||||||
keyLabel := OwnerNode.AddLabel(fieldContainer, ':' + field.Key.Value.Name);
|
|
||||||
keyLabel.Font.Style := keyLabel.Font.Style + [TFontStyle.fsBold];
|
|
||||||
keyLabel.StyledSettings := keyLabel.StyledSettings - [TStyledSetting.FontColor];
|
|
||||||
keyLabel.FontColor := TAlphaColors.Mediumvioletred;
|
|
||||||
|
|
||||||
valueNode := OwnerNode.Visualizer.Clone(fieldContainer, OwnerNode.Visualizer.ExprDepth + 1).CallAccept(field.Value);
|
|
||||||
FFieldNodes.Add(field.Key.Value, valueNode);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
finally
|
finally
|
||||||
OwnerNode.EndUpdate;
|
OwnerNode.EndUpdate;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TRecordLiteralNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
function TRecordLiteralNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
|
||||||
var
|
|
||||||
fields: TArray<TRecordFieldLiteral>;
|
|
||||||
i: Integer;
|
|
||||||
valueNode: TAstViewNode;
|
|
||||||
pair: TPair<IKeyword, TAstViewNode>;
|
|
||||||
begin
|
begin
|
||||||
SetLength(fields, FFieldNodes.Count);
|
Result :=
|
||||||
i := 0;
|
TAst.RecordLiteral(
|
||||||
for pair in FFieldNodes do
|
FNode.Identity,
|
||||||
begin
|
FFieldsNode.CreateAst.AsRecordFieldList,
|
||||||
valueNode := pair.Value;
|
FNode.ScalarDefinition,
|
||||||
fields[i] := TRecordFieldLiteral.Create(TAst.Keyword(pair.Key.Name), valueNode.CreateAst);
|
FNode.GenericDefinition,
|
||||||
inc(i);
|
FNode.StaticType
|
||||||
end;
|
);
|
||||||
Result := TAst.RecordLiteral(FNode.Identity, fields, FNode.ScalarDefinition, FNode.GenericDefinition, FNode.StaticType);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TCreateSeriesNodeHandler }
|
{ TCreateSeriesNodeHandler }
|
||||||
|
|||||||
@@ -31,6 +31,14 @@ type
|
|||||||
function VisitConstant(const Node: IConstantNode): TAstViewNode; override;
|
function VisitConstant(const Node: IConstantNode): TAstViewNode; override;
|
||||||
function VisitIdentifier(const Node: IIdentifierNode): TAstViewNode; override;
|
function VisitIdentifier(const Node: IIdentifierNode): TAstViewNode; override;
|
||||||
function VisitKeyword(const Node: IKeywordNode): TAstViewNode; override;
|
function VisitKeyword(const Node: IKeywordNode): TAstViewNode; override;
|
||||||
|
|
||||||
|
// --- List Visitors (NEW) ---
|
||||||
|
function VisitParameterList(const Node: IParameterList): TAstViewNode; override;
|
||||||
|
function VisitArgumentList(const Node: IArgumentList): TAstViewNode; override;
|
||||||
|
function VisitExpressionList(const Node: IExpressionList): TAstViewNode; override;
|
||||||
|
function VisitRecordFieldList(const Node: IRecordFieldList): TAstViewNode; override;
|
||||||
|
function VisitRecordField(const Node: IRecordFieldNode): TAstViewNode; override;
|
||||||
|
|
||||||
function VisitIfExpression(const Node: IIfExpressionNode): TAstViewNode; override;
|
function VisitIfExpression(const Node: IIfExpressionNode): TAstViewNode; override;
|
||||||
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstViewNode; override;
|
function VisitTernaryExpression(const Node: ITernaryExpressionNode): TAstViewNode; override;
|
||||||
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstViewNode; override;
|
function VisitLambdaExpression(const Node: ILambdaExpressionNode): TAstViewNode; override;
|
||||||
@@ -146,6 +154,35 @@ begin
|
|||||||
Result := TAstViewNode.Create(Self, TKeywordNodeHandler.Create(Node));
|
Result := TAstViewNode.Create(Self, TKeywordNodeHandler.Create(Node));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// --- List Visitors ---
|
||||||
|
|
||||||
|
function TAstVisualizer.VisitParameterList(const Node: IParameterList): TAstViewNode;
|
||||||
|
begin
|
||||||
|
Result := TAstViewNode.Create(Self, TParameterListHandler.Create(Node));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstVisualizer.VisitArgumentList(const Node: IArgumentList): TAstViewNode;
|
||||||
|
begin
|
||||||
|
Result := TAstViewNode.Create(Self, TArgumentListHandler.Create(Node));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstVisualizer.VisitExpressionList(const Node: IExpressionList): TAstViewNode;
|
||||||
|
begin
|
||||||
|
Result := TAstViewNode.Create(Self, TExpressionListHandler.Create(Node));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstVisualizer.VisitRecordFieldList(const Node: IRecordFieldList): TAstViewNode;
|
||||||
|
begin
|
||||||
|
Result := TAstViewNode.Create(Self, TRecordFieldListHandler.Create(Node));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TAstVisualizer.VisitRecordField(const Node: IRecordFieldNode): TAstViewNode;
|
||||||
|
begin
|
||||||
|
Result := TAstViewNode.Create(Self, TRecordFieldHandler.Create(Node));
|
||||||
|
end;
|
||||||
|
|
||||||
|
// --- Node Visitors ---
|
||||||
|
|
||||||
function TAstVisualizer.VisitBlockExpression(const Node: IBlockExpressionNode): TAstViewNode;
|
function TAstVisualizer.VisitBlockExpression(const Node: IBlockExpressionNode): TAstViewNode;
|
||||||
begin
|
begin
|
||||||
Result := TAstViewNode.Create(Self, TBlockExpressionNodeHandler.Create(Node));
|
Result := TAstViewNode.Create(Self, TBlockExpressionNodeHandler.Create(Node));
|
||||||
|
|||||||
@@ -110,6 +110,9 @@ constructor TAstWorkspace.Create(AOwner: TComponent);
|
|||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
FZoom := 1.0;
|
FZoom := 1.0;
|
||||||
|
// Standard-Eigenschaften für einen Arbeitsbereich
|
||||||
|
ClipChildren := True;
|
||||||
|
HitTest := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TAstWorkspace.Build(const RootNode: IAstNode; const Position: TPointF);
|
procedure TAstWorkspace.Build(const RootNode: IAstNode; const Position: TPointF);
|
||||||
@@ -117,10 +120,20 @@ var
|
|||||||
visu: IAstVisualizer;
|
visu: IAstVisualizer;
|
||||||
node: TAstViewNode;
|
node: TAstViewNode;
|
||||||
begin
|
begin
|
||||||
|
// Löscht alle bestehenden visuellen Knoten
|
||||||
|
DeleteChildren;
|
||||||
|
FConnections := nil;
|
||||||
|
|
||||||
|
if not Assigned(RootNode) then
|
||||||
|
Exit;
|
||||||
|
|
||||||
|
// Erstellt den Visualizer mit dem Workspace als Kontext
|
||||||
visu := TAstVisualizer.Create(Self, Self, 0);
|
visu := TAstVisualizer.Create(Self, Self, 0);
|
||||||
node := visu.CallAccept(RootNode);
|
node := visu.CallAccept(RootNode);
|
||||||
if Assigned(node) then
|
if Assigned(node) then
|
||||||
|
begin
|
||||||
node.Position.Point := Position;
|
node.Position.Point := Position;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TAstWorkspace.DoDeleteChildren;
|
procedure TAstWorkspace.DoDeleteChildren;
|
||||||
@@ -204,7 +217,12 @@ end;
|
|||||||
procedure TAstWorkspace.DblClick;
|
procedure TAstWorkspace.DblClick;
|
||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
Zoom(1.0);
|
// Reset Zoom/Pan on double click
|
||||||
|
FZoom := 1.0;
|
||||||
|
FPanning := TSizeF.Create(0, 0);
|
||||||
|
RecalcAbsolute;
|
||||||
|
RecalcUpdateRect;
|
||||||
|
Repaint;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TAstWorkspace.Paint;
|
procedure TAstWorkspace.Paint;
|
||||||
@@ -224,6 +242,13 @@ begin
|
|||||||
|
|
||||||
for connection in FConnections do
|
for connection in FConnections do
|
||||||
begin
|
begin
|
||||||
|
// Safety check if pins are still valid/visible
|
||||||
|
if (connection.OutputPin = nil)
|
||||||
|
or (connection.InputPin = nil)
|
||||||
|
or (connection.OutputPin.Root <> Self.Root)
|
||||||
|
or (connection.InputPin.Root <> Self.Root) then
|
||||||
|
continue;
|
||||||
|
|
||||||
pinCenter := TPointF.Create(connection.OutputPin.Width / 2, connection.OutputPin.Height / 2);
|
pinCenter := TPointF.Create(connection.OutputPin.Width / 2, connection.OutputPin.Height / 2);
|
||||||
absoluteStart := connection.OutputPin.LocalToAbsolute(pinCenter);
|
absoluteStart := connection.OutputPin.LocalToAbsolute(pinCenter);
|
||||||
|
|
||||||
@@ -263,9 +288,13 @@ begin
|
|||||||
begin
|
begin
|
||||||
mousePos := ScreenToLocal(mouseService.GetMousePos);
|
mousePos := ScreenToLocal(mouseService.GetMousePos);
|
||||||
Factor := Max(0.2, Min(3.0, Factor));
|
Factor := Max(0.2, Min(3.0, Factor));
|
||||||
|
|
||||||
|
// Adjust panning to zoom towards mouse position
|
||||||
FPanning.cx := mousePos.X * (1 - Factor / FZoom) + FPanning.cx * (Factor / FZoom);
|
FPanning.cx := mousePos.X * (1 - Factor / FZoom) + FPanning.cx * (Factor / FZoom);
|
||||||
FPanning.cy := mousePos.Y * (1 - Factor / FZoom) + FPanning.cy * (Factor / FZoom);
|
FPanning.cy := mousePos.Y * (1 - Factor / FZoom) + FPanning.cy * (Factor / FZoom);
|
||||||
|
|
||||||
FZoom := Factor;
|
FZoom := Factor;
|
||||||
|
|
||||||
RecalcAbsolute;
|
RecalcAbsolute;
|
||||||
RecalcUpdateRect;
|
RecalcUpdateRect;
|
||||||
Repaint;
|
Repaint;
|
||||||
|
|||||||
@@ -209,7 +209,8 @@ begin
|
|||||||
call := node.AsFunctionCall;
|
call := node.AsFunctionCall;
|
||||||
|
|
||||||
Assert.AreEqual<string>('add', call.Callee.AsIdentifier.Name);
|
Assert.AreEqual<string>('add', call.Callee.AsIdentifier.Name);
|
||||||
Assert.AreEqual<Integer>(2, Length(call.Arguments));
|
// Use Count instead of Length
|
||||||
|
Assert.AreEqual<Integer>(2, call.Arguments.Count);
|
||||||
|
|
||||||
Assert.AreEqual<Int64>(1, call.Arguments[0].AsConstant.Value.AsScalar.Value.AsInt64);
|
Assert.AreEqual<Int64>(1, call.Arguments[0].AsConstant.Value.AsScalar.Value.AsInt64);
|
||||||
Assert.AreEqual<Int64>(2, call.Arguments[1].AsConstant.Value.AsScalar.Value.AsInt64);
|
Assert.AreEqual<Int64>(2, call.Arguments[1].AsConstant.Value.AsScalar.Value.AsInt64);
|
||||||
@@ -225,7 +226,9 @@ begin
|
|||||||
Assert.AreEqual<TAstNodeKind>(TAstNodeKind.akRecordLiteral, node.Kind);
|
Assert.AreEqual<TAstNodeKind>(TAstNodeKind.akRecordLiteral, node.Kind);
|
||||||
rec := node.AsRecordLiteral;
|
rec := node.AsRecordLiteral;
|
||||||
|
|
||||||
Assert.AreEqual<Integer>(2, Length(rec.Fields));
|
Assert.AreEqual<Integer>(2, rec.Fields.Count);
|
||||||
|
|
||||||
|
// Accessing fields via IRecordFieldNode
|
||||||
Assert.AreEqual<string>('a', rec.Fields[0].Key.Value.Name);
|
Assert.AreEqual<string>('a', rec.Fields[0].Key.Value.Name);
|
||||||
Assert.AreEqual<Int64>(1, rec.Fields[0].Value.AsConstant.Value.AsScalar.Value.AsInt64);
|
Assert.AreEqual<Int64>(1, rec.Fields[0].Value.AsConstant.Value.AsScalar.Value.AsInt64);
|
||||||
|
|
||||||
@@ -239,7 +242,7 @@ var
|
|||||||
begin
|
begin
|
||||||
node := Parse('{}');
|
node := Parse('{}');
|
||||||
Assert.AreEqual<TAstNodeKind>(TAstNodeKind.akRecordLiteral, node.Kind);
|
Assert.AreEqual<TAstNodeKind>(TAstNodeKind.akRecordLiteral, node.Kind);
|
||||||
Assert.AreEqual<Integer>(0, Length(node.AsRecordLiteral.Fields));
|
Assert.AreEqual<Integer>(0, node.AsRecordLiteral.Fields.Count);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// --- Special Forms ---
|
// --- Special Forms ---
|
||||||
@@ -268,7 +271,7 @@ begin
|
|||||||
Assert.AreEqual<TAstNodeKind>(TAstNodeKind.akLambdaExpression, node.Kind);
|
Assert.AreEqual<TAstNodeKind>(TAstNodeKind.akLambdaExpression, node.Kind);
|
||||||
lam := node.AsLambdaExpression;
|
lam := node.AsLambdaExpression;
|
||||||
|
|
||||||
Assert.AreEqual<Integer>(2, Length(lam.Parameters));
|
Assert.AreEqual<Integer>(2, lam.Parameters.Count);
|
||||||
Assert.AreEqual<string>('a', lam.Parameters[0].Name);
|
Assert.AreEqual<string>('a', lam.Parameters[0].Name);
|
||||||
Assert.AreEqual<string>('b', lam.Parameters[1].Name);
|
Assert.AreEqual<string>('b', lam.Parameters[1].Name);
|
||||||
|
|
||||||
@@ -317,7 +320,7 @@ begin
|
|||||||
call := node.AsFunctionCall;
|
call := node.AsFunctionCall;
|
||||||
|
|
||||||
Assert.AreEqual<string>('quote', call.Callee.AsIdentifier.Name);
|
Assert.AreEqual<string>('quote', call.Callee.AsIdentifier.Name);
|
||||||
Assert.AreEqual<Integer>(1, Length(call.Arguments));
|
Assert.AreEqual<Integer>(1, call.Arguments.Count);
|
||||||
Assert.AreEqual<string>('foo', call.Arguments[0].AsIdentifier.Name);
|
Assert.AreEqual<string>('foo', call.Arguments[0].AsIdentifier.Name);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -343,8 +346,8 @@ procedure TTestMycAstScript.Parser_UnquoteSplicing_CreatesNode;
|
|||||||
var
|
var
|
||||||
node: IAstNode;
|
node: IAstNode;
|
||||||
begin
|
begin
|
||||||
// ~@x
|
// Note: Parser requires backtick after ~@ currently due to cast in Myc.Ast.Script:
|
||||||
// There's something off here - we'll fix this later
|
// Result.Node := TAst.UnquoteSplicing(expr.Node.AsQuasiquote, startLoc);
|
||||||
node := Parse('~@`x');
|
node := Parse('~@`x');
|
||||||
Assert.AreEqual<TAstNodeKind>(TAstNodeKind.akUnquoteSplicing, node.Kind);
|
Assert.AreEqual<TAstNodeKind>(TAstNodeKind.akUnquoteSplicing, node.Kind);
|
||||||
|
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ end;
|
|||||||
|
|
||||||
function TTestAstBinder.Unwrap(const Node: IAstNode): IAstNode;
|
function TTestAstBinder.Unwrap(const Node: IAstNode): IAstNode;
|
||||||
begin
|
begin
|
||||||
if (Node.Kind = akBlockExpression) and (Length(Node.AsBlockExpression.Expressions) = 1) then
|
if (Node.Kind = akBlockExpression) and (Node.AsBlockExpression.Expressions.Count = 1) then
|
||||||
Result := Node.AsBlockExpression.Expressions[0]
|
Result := Node.AsBlockExpression.Expressions[0]
|
||||||
else
|
else
|
||||||
Result := Node;
|
Result := Node;
|
||||||
@@ -236,6 +236,7 @@ begin
|
|||||||
Assert.IsFalse(log.HasErrors);
|
Assert.IsFalse(log.HasErrors);
|
||||||
|
|
||||||
lambda := bound.AsLambdaExpression;
|
lambda := bound.AsLambdaExpression;
|
||||||
|
// Access parameter list via index
|
||||||
Assert.AreEqual<Integer>(1, lambda.Parameters[0].Address.SlotIndex); // Slot 0 is reserved for <self>
|
Assert.AreEqual<Integer>(1, lambda.Parameters[0].Address.SlotIndex); // Slot 0 is reserved for <self>
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user