Refactoring

This commit is contained in:
Michael Schimmel
2025-11-01 13:00:22 +01:00
parent df12db2595
commit 3869c98652
3 changed files with 32 additions and 30 deletions
+3 -3
View File
@@ -646,7 +646,7 @@ begin
var isTailCall := FIsTailStack.Peek;
FNextIsTail := False;
callee := Accept(Node.Callee).AsIntf<IAstNode>;
args := TransformNodes<IAstNode>(Node.Arguments);
args := AcceptNodes<IAstNode>(Node.Arguments);
var retType: IStaticType := TTypes.Unknown;
calleeType := (callee as TAstNode).StaticType;
@@ -680,7 +680,7 @@ var
newMacroNode: IMacroExpansionNode;
begin
boundCallee := Accept(Node.Callee).AsIntf<IAstNode>;
boundArgs := TransformNodes<IAstNode>(Node.Arguments);
boundArgs := AcceptNodes<IAstNode>(Node.Arguments);
boundExpandedBody := Accept(Node.ExpandedBody).AsIntf<IAstNode>;
boundOriginalCall := TAst.FunctionCall(boundCallee, boundArgs);
newMacroNode := TMacroExpansionNode.Create(boundOriginalCall, boundExpandedBody);
@@ -1130,7 +1130,7 @@ begin
// 'recur' itself doesn't evaluate to a value, it jumps.
// We set its type to Void.
var boundNode := TAst.Recur(TransformNodes<IAstNode>(Node.Arguments));
var boundNode := TAst.Recur(AcceptNodes<IAstNode>(Node.Arguments));
Result := SetType(TDataValue.FromIntf<IRecurNode>(boundNode), TTypes.Void);
end;
+5 -2
View File
@@ -555,6 +555,7 @@ end;
class function TTypeRules.CanAssign(const Target, Source: IStaticType): Boolean;
begin
// Basic nil-check for safety.
if (not Assigned(Target)) or (not Assigned(Source)) then
exit(False);
@@ -562,6 +563,7 @@ begin
if (Target.Kind = stUnknown) or (Source.Kind = stUnknown) then
exit(True);
// Types are always assignable to themselves (identity).
if Target.IsEqual(Source) then
exit(True);
@@ -569,17 +571,18 @@ begin
if (Target.Kind = stFloat) and (Source.Kind = stOrdinal) then
exit(True);
// Allow discarding the return value of a method (e.g., in a 'do' block).
if (Target.Kind = stVoid) and (Source.Kind = stMethod) then
exit(True);
// Allow implicit conversion from Keyword (internally an index) to Ordinal.
if (Target.Kind = stOrdinal) and (Source.Kind = stKeyword) then
exit(True);
// TODO: Implement full assignment compatibility rules (e.g., for records/series)
// Allow assigning a scalar record to a generic record? (Maybe later)
// Allow assigning a generic record to a scalar record? (If fields match)
// Default: Assignment is not allowed if no specific rule matches.
Result := False;
end;
+24 -25
View File
@@ -76,10 +76,9 @@ type
function VisitSeriesLength(const Node: ISeriesLengthNode): TDataValue; override;
function VisitRecurNode(const Node: IRecurNode): TDataValue; override;
// Helper to transform an array of nodes.
function TransformNodes<T: IAstNode>(const Nodes: TArray<T>): TArray<T>;
function Accept(const Node: IAstNode): TDataValue; virtual;
// Helper to transform an array of nodes.
function AcceptNodes<T: IAstNode>(const Nodes: TArray<T>): TArray<T>;
property Done: Boolean read FDone write FDone;
public
@@ -114,6 +113,23 @@ begin
Result := Node.Accept(Self);
end;
function TAstTransformer.AcceptNodes<T>(const Nodes: TArray<T>): TArray<T>;
var
i: Integer;
hasChanged: boolean;
begin
hasChanged := False;
SetLength(Result, Length(Nodes));
for i := 0 to High(Nodes) do
begin
Result[i] := Accept(Nodes[i]).AsIntf<T>;
if Result[i] <> Nodes[i] then
hasChanged := True;
end;
if not hasChanged then
Result := Nodes;
end;
function TAstTransformer.Execute(const RootNode: IAstNode): IAstNode;
begin
Result := Accept(RootNode).AsIntf<IAstNode>;
@@ -183,7 +199,7 @@ end;
function TAstTransformer.VisitLambdaExpression(const Node: ILambdaExpressionNode): TDataValue;
begin
var parameters := TransformNodes<IIdentifierNode>(Node.Parameters);
var parameters := AcceptNodes<IIdentifierNode>(Node.Parameters);
var body := Accept(Node.Body).AsIntf<IAstNode>;
if (parameters = Node.Parameters) and (body = Node.Body) then
Result := TDataValue.FromIntf<ILambdaExpressionNode>(Node)
@@ -194,7 +210,7 @@ end;
function TAstTransformer.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue;
begin
var callee := Accept(Node.Callee).AsIntf<IAstNode>;
var args := TransformNodes<IAstNode>(Node.Arguments);
var args := AcceptNodes<IAstNode>(Node.Arguments);
if (callee = Node.Callee) and (args = Node.Arguments) then
Result := TDataValue.FromIntf<IFunctionCallNode>(Node)
else
@@ -209,7 +225,7 @@ var
begin
// Transform all children of the node
callee := Accept(Node.Callee).AsIntf<IAstNode>;
args := TransformNodes<IAstNode>(Node.Arguments);
args := AcceptNodes<IAstNode>(Node.Arguments);
expandedBody := Accept(Node.ExpandedBody).AsIntf<IAstNode>;
if (callee = Node.Callee) and (args = Node.Arguments) and (expandedBody = Node.ExpandedBody) then
@@ -271,7 +287,7 @@ end;
function TAstTransformer.VisitMacroDefinition(const Node: IMacroDefinitionNode): TDataValue;
begin
var name := Accept(Node.Name).AsIntf<IIdentifierNode>;
var parameters := TransformNodes<IIdentifierNode>(Node.Parameters);
var parameters := AcceptNodes<IIdentifierNode>(Node.Parameters);
var body := Accept(Node.Body).AsIntf<IQuasiquoteNode>;
if (name = Node.Name) and (parameters = Node.Parameters) and (body = Node.Body) then
Result := TDataValue.FromIntf<IMacroDefinitionNode>(Node)
@@ -381,30 +397,13 @@ end;
function TAstTransformer.VisitRecurNode(const Node: IRecurNode): TDataValue;
begin
var args := TransformNodes<IAstNode>(Node.Arguments);
var args := AcceptNodes<IAstNode>(Node.Arguments);
if args = Node.Arguments then
Result := TDataValue.FromIntf<IRecurNode>(Node)
else
Result := TDataValue.FromIntf<IRecurNode>(TAst.Recur(args));
end;
function TAstTransformer.TransformNodes<T>(const Nodes: TArray<T>): TArray<T>;
var
i: Integer;
hasChanged: boolean;
begin
hasChanged := False;
SetLength(Result, Length(Nodes));
for i := 0 to High(Nodes) do
begin
Result[i] := Accept(Nodes[i]).AsIntf<T>;
if Result[i] <> Nodes[i] then
hasChanged := True;
end;
if not hasChanged then
Result := Nodes;
end;
{ TAstTraverser<T> }
constructor TAstTraverser<T>.Create;