AST testing

This commit is contained in:
Michael Schimmel
2025-11-23 00:24:43 +01:00
parent c5167b8550
commit a052dfb20f
23 changed files with 792 additions and 1260 deletions
+71 -5
View File
@@ -87,6 +87,19 @@ type
): IAstNode; static;
end;
TMacroRegistry = class(TInterfacedObject, IMacroRegistry)
private
FParent: IMacroRegistry;
FMacros: TDictionary<string, IMacroDefinitionNode>;
function GetParent: IMacroRegistry;
public
constructor Create(AParent: IMacroRegistry);
destructor Destroy; override;
procedure Define(const Node: IMacroDefinitionNode);
function Find(const Name: string): IMacroDefinitionNode;
function CreateChildRegistry: IMacroRegistry;
end;
implementation
uses
@@ -193,14 +206,23 @@ end;
function TExpansionVisitor.VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode;
var
newTarget, newInit: IAstNode;
newName: string;
newIdent: IIdentifierNode;
newInit: IAstNode;
begin
newInit := Accept(Node.Initializer);
newName := Gensym(Node.Identifier.Name);
newIdent := TAst.Identifier(newName, TTypes.Unknown);
Result := TAst.VarDecl(newIdent, newInit, TTypes.Unknown);
// Check if target is identifier before trying to rename
if Node.Target.Kind = akIdentifier then
begin
newName := Gensym(Node.Target.AsIdentifier.Name);
newTarget := TAst.Identifier(newName, TTypes.Unknown);
end
else
begin
newTarget := Accept(Node.Target); // Recursively expand unquotes in target position!
end;
Result := TAst.VarDecl(newTarget, newInit, TTypes.Unknown);
end;
function TExpansionVisitor.VisitLambdaExpression(const Node: ILambdaExpressionNode): IAstNode;
@@ -438,4 +460,48 @@ begin
raise Exception.Create('Unquote-splicing (`~@`) can only be used inside a quasiquote.');
end;
{ TMacroRegistry }
constructor TMacroRegistry.Create(AParent: IMacroRegistry);
begin
inherited Create;
FParent := AParent;
FMacros := TDictionary<string, IMacroDefinitionNode>.Create;
end;
destructor TMacroRegistry.Destroy;
begin
FMacros.Free;
inherited Destroy;
end;
function TMacroRegistry.GetParent: IMacroRegistry;
begin
Result := FParent;
end;
procedure TMacroRegistry.Define(const Node: IMacroDefinitionNode);
begin
FMacros.AddOrSetValue(Node.Name.Name, Node);
end;
function TMacroRegistry.Find(const Name: string): IMacroDefinitionNode;
var
current: IMacroRegistry;
begin
current := Self;
while Assigned(current) do
begin
if (current as TMacroRegistry).FMacros.TryGetValue(Name, Result) then
exit;
current := current.Parent;
end;
Result := nil;
end;
function TMacroRegistry.CreateChildRegistry: IMacroRegistry;
begin
Result := TMacroRegistry.Create(Self);
end;
end.