Refactoring
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user