Generic Visitors
This commit is contained in:
@@ -16,7 +16,7 @@ uses
|
||||
Myc.Ast.Compiler.Binder;
|
||||
|
||||
type
|
||||
// Exception specific to specialization errors (e.g. internal compilation failures)
|
||||
// Exception specific to specialization errors
|
||||
ESpecializerException = class(EAstException);
|
||||
|
||||
IAstSpecializer = interface(IAstVisitor)
|
||||
@@ -29,7 +29,7 @@ type
|
||||
public
|
||||
Address: TResolvedAddress;
|
||||
ArgTypes: TArray<IStaticType>;
|
||||
Func: TDataValue.TFunc;
|
||||
Func: TDataValue.TFunc; // Usually nil in key, but part of structure if needed
|
||||
constructor Create(const AAddress: TResolvedAddress; const AArgTypes: TArray<IStaticType>);
|
||||
end;
|
||||
|
||||
@@ -39,10 +39,9 @@ type
|
||||
end;
|
||||
|
||||
// This transformer runs *after* TypeChecker.
|
||||
// It specializes all statically resolvable function calls (RTL and user-defined)
|
||||
// by replacing them with nodes that have a direct StaticTarget.
|
||||
// It propagates Purity information but does NOT perform Constant Folding yet.
|
||||
// It specializes all statically resolvable function calls.
|
||||
TStaticSpecializer = class(TAstTransformer, IAstSpecializer)
|
||||
public
|
||||
type
|
||||
TCompileFunc = reference to function(const Node: IFunctionDefinition; const ArgTypes: TArray<IStaticType>): TCompiledFunction;
|
||||
private
|
||||
@@ -52,8 +51,12 @@ type
|
||||
|
||||
function GetStaticRtlFunction(const AName: string; const AArgTypes: TArray<IStaticType>): TSpecializedMethod;
|
||||
|
||||
strict private
|
||||
// Specialization Handler (IAstNode signature)
|
||||
function VisitFunctionCall(const Node: IAstNode): IAstNode;
|
||||
|
||||
protected
|
||||
function VisitFunctionCall(const Node: IFunctionCallNode): IAstNode; override;
|
||||
procedure SetupHandlers; override;
|
||||
|
||||
public
|
||||
constructor Create(
|
||||
@@ -89,13 +92,19 @@ begin
|
||||
raise ESpecializerException.Create('MonomorphCache cannot be nil.');
|
||||
if not Assigned(AFunctionRegistry) then
|
||||
raise ESpecializerException.Create('FunctionRegistry cannot be nil.');
|
||||
// CompileFunc can be nil if no recursion is supported, but usually required.
|
||||
|
||||
FMonomorphCache := AMonomorphCache;
|
||||
FFunctionRegistry := AFunctionRegistry;
|
||||
FCompileFunc := ACompileFunc;
|
||||
end;
|
||||
|
||||
procedure TStaticSpecializer.SetupHandlers;
|
||||
begin
|
||||
inherited SetupHandlers; // Load default transformations
|
||||
// Override FunctionCall logic
|
||||
Register(akFunctionCall, VisitFunctionCall);
|
||||
end;
|
||||
|
||||
class function TStaticSpecializer.Specialize(
|
||||
const RootNode: IAstNode;
|
||||
const AMonomorphCache: IMonomorphCache;
|
||||
@@ -119,8 +128,10 @@ begin
|
||||
Result := TRtlRegistry.GetStaticSpecialization(AName, AArgTypes);
|
||||
end;
|
||||
|
||||
function TStaticSpecializer.VisitFunctionCall(const Node: IFunctionCallNode): IAstNode;
|
||||
function TStaticSpecializer.VisitFunctionCall(const Node: IAstNode): IAstNode;
|
||||
var
|
||||
C: IFunctionCallNode;
|
||||
newCall: IFunctionCallNode;
|
||||
newCallee: IAstNode;
|
||||
newArgsList: IArgumentList;
|
||||
i: Integer;
|
||||
@@ -132,18 +143,18 @@ var
|
||||
specializedMethod: TSpecializedMethod;
|
||||
funcDef: IFunctionDefinition;
|
||||
begin
|
||||
// 1. Specialize children first (bottom-up)
|
||||
newCallee := Accept(Node.Callee);
|
||||
// Arguments are now visited as a List, returning an IArgumentList
|
||||
newArgsList := Accept(Node.Arguments).AsArgumentList;
|
||||
C := Node.AsFunctionCall;
|
||||
|
||||
// 1. Specialize children first (bottom-up) by calling inherited
|
||||
// inherited VisitFunctionCall returns an IAstNode (which is a new IFunctionCallNode if changed)
|
||||
newCall := inherited VisitFunctionCall(Node).AsFunctionCall;
|
||||
newCallee := newCall.Callee;
|
||||
newArgsList := newCall.Arguments;
|
||||
|
||||
// 2. Check if this call is a candidate for specialization
|
||||
if newCallee.Kind <> akIdentifier then
|
||||
begin
|
||||
if (newCallee = Node.Callee) and (newArgsList = Node.Arguments) then
|
||||
Result := Node
|
||||
else
|
||||
Result := TAst.FunctionCall(Node.Identity, newCallee, newArgsList, Node.StaticType, Node.IsTailCall, nil);
|
||||
Result := newCall;
|
||||
exit;
|
||||
end;
|
||||
|
||||
@@ -165,10 +176,7 @@ begin
|
||||
|
||||
if not allTypesKnown then
|
||||
begin
|
||||
if (newCallee = Node.Callee) and (newArgsList = Node.Arguments) then
|
||||
Result := Node
|
||||
else
|
||||
Result := TAst.FunctionCall(Node.Identity, newCallee, newArgsList, Node.StaticType, Node.IsTailCall, nil);
|
||||
Result := newCall;
|
||||
exit;
|
||||
end;
|
||||
|
||||
@@ -186,7 +194,7 @@ begin
|
||||
newCallee,
|
||||
newArgsList,
|
||||
specializedMethod.ReturnType,
|
||||
Node.IsTailCall,
|
||||
C.IsTailCall,
|
||||
specializedMethod.Target,
|
||||
specializedMethod.IsPure
|
||||
);
|
||||
@@ -206,7 +214,7 @@ begin
|
||||
newCallee,
|
||||
newArgsList,
|
||||
specializedMethod.ReturnType,
|
||||
Node.IsTailCall,
|
||||
C.IsTailCall,
|
||||
specializedMethod.Target,
|
||||
specializedMethod.IsPure
|
||||
);
|
||||
@@ -224,7 +232,7 @@ begin
|
||||
var lambdaDef := funcDef.AsLambdaExpression;
|
||||
if (Length(lambdaDef.Upvalues) > 0) or (lambdaDef.HasNestedLambdas) then
|
||||
begin
|
||||
Result := TAst.FunctionCall(Node.Identity, newCallee, newArgsList, Node.StaticType, Node.IsTailCall, nil);
|
||||
Result := newCall;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
@@ -245,15 +253,12 @@ begin
|
||||
FMonomorphCache.Add(key, specializedMethod);
|
||||
|
||||
// 6c. Return the new node
|
||||
Result := TAst.FunctionCall(Node.Identity, newCallee, newArgsList, returnType, Node.IsTailCall, compiled.Func, compiled.IsPure);
|
||||
Result := TAst.FunctionCall(Node.Identity, newCallee, newArgsList, returnType, C.IsTailCall, compiled.Func, compiled.IsPure);
|
||||
exit;
|
||||
end;
|
||||
|
||||
// 7. Fallback: Not RTL, Not User-Code -> Dynamic
|
||||
if (newCallee = Node.Callee) and (newArgsList = Node.Arguments) then
|
||||
Result := Node
|
||||
else
|
||||
Result := TAst.FunctionCall(Node.Identity, newCallee, newArgsList, Node.StaticType, Node.IsTailCall, nil);
|
||||
Result := newCall;
|
||||
end;
|
||||
|
||||
{ TMonoCacheKey }
|
||||
@@ -262,6 +267,7 @@ constructor TMonoCacheKey.Create(const AAddress: TResolvedAddress; const AArgTyp
|
||||
begin
|
||||
Address := AAddress;
|
||||
ArgTypes := AArgTypes;
|
||||
Func := nil;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
Reference in New Issue
Block a user