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