Making AST node inmmutable - WIP

This commit is contained in:
Michael Schimmel
2025-11-04 20:12:12 +01:00
parent 48ccb23060
commit d82a75aba6
6 changed files with 123 additions and 56 deletions
+48 -34
View File
@@ -284,13 +284,17 @@ begin
// Define parameters
for i := 0 to High(N.Parameters) do
begin
var paramNode := N.Parameters[i];
var paramNode := N.Parameters[i]; // This is a TIdentifierNode
var slotIndex := FCurrentDescriptor.Define(paramNode.Name, TTypes.Unknown);
adr := TResolvedAddress.Create(akLocalOrParent, 0, slotIndex);
// Mutate the parameter node with its address
(paramNode as TIdentifierNode).Address := adr;
(paramNode as TAstNode).StaticType := TTypes.Unknown;
// --- Replace Node ---
// Create a new TBoundIdentifierNode (implementation is in Myc.Ast)
var boundParamNode := TBoundIdentifierNode.Create(paramNode.Name, adr);
// Set its type
(boundParamNode as TAstNode).StaticType := TTypes.Unknown;
// Replace it in the parameter array
N.Parameters[i] := boundParamNode;
end;
// Visit the body *within the new scope*
@@ -342,42 +346,50 @@ var
symbol: TResolvedSymbol;
adr: TResolvedAddress;
begin
symbol := FCurrentDescriptor.FindSymbol(Node.Name);
adr := symbol.Address;
if adr.Kind = akLocalOrParent then
// We only bind nodes that are the base parser type.
if Node.Kind = akIdentifier then
begin
if (adr.ScopeDepth > 0) and (FUpvalueStack.Count > 0) then
begin
// --- Handle Upvalue ---
var upvalueMap := FUpvalueStack.Peek;
// Adjust address to be relative to the captured scope
dec(adr.ScopeDepth);
symbol := FCurrentDescriptor.FindSymbol(Node.Name);
adr := symbol.Address;
var upvalueIndex: Integer;
if not upvalueMap.TryGetValue(adr, upvalueIndex) then
if adr.Kind = akUnresolved then
raise Exception.CreateFmt('Undefined identifier: "%s"', [Node.Name]);
if adr.Kind = akLocalOrParent then
begin
if (adr.ScopeDepth > 0) and (FUpvalueStack.Count > 0) then
begin
// This is a new upvalue for this lambda
upvalueIndex := upvalueMap.Count;
upvalueMap.Add(adr, upvalueIndex);
// --- Handle Upvalue ---
var upvalueMap := FUpvalueStack.Peek;
// Adjust address to be relative to the captured scope
dec(adr.ScopeDepth);
var upvalueIndex: Integer;
if not upvalueMap.TryGetValue(adr, upvalueIndex) then
begin
// This is a new upvalue for this lambda
upvalueIndex := upvalueMap.Count;
upvalueMap.Add(adr, upvalueIndex);
end;
// Create final upvalue address
adr := TResolvedAddress.Create(akUpvalue, 0, upvalueIndex);
end;
// Mutate the node to point to the Upvalue slot
(Node as TIdentifierNode).Address := TResolvedAddress.Create(akUpvalue, 0, upvalueIndex);
end
else
begin
// --- Handle LocalOrParent ---
// Mutate the node to point to the Local/Parent slot
(Node as TIdentifierNode).Address := adr;
// else: It's a local (ScopeDepth=0), adr is already correct.
end;
// else: It was already an upvalue (e.g. nested lambda), adr is correct.
(Node as TAstNode).StaticType := symbol.StaticType; // Set type from scope
// --- Replace Node ---
// Create the new TBoundIdentifierNode (implementation is in Myc.Ast)
Result := TBoundIdentifierNode.Create(Node.Name, adr);
// Copy static type from scope to the new node
(Result as TAstNode).StaticType := symbol.StaticType;
end
else
raise Exception.CreateFmt('Undefined identifier: "%s"', [Node.Name]);
Result := Node;
begin
// It's already an akBoundIdentifier (or other specialized type), just return it.
Result := Node;
end;
end;
function TAstBinder.VisitVariableDeclaration(const Node: IVariableDeclarationNode): IAstNode;
@@ -399,8 +411,10 @@ begin
slotIndex := FCurrentDescriptor.Define(N.Identifier.Name, TTypes.Unknown);
address := TResolvedAddress.Create(akLocalOrParent, 0, slotIndex);
// 3. Mutate the Identifier node (which is NOT visited by inherited call)
(N.Identifier as TIdentifierNode).Address := address;
// 3. --- Replace Node ---
// Replace the TIdentifierNode with a new TBoundIdentifierNode
N.Identifier := TBoundIdentifierNode.Create(N.Identifier.Name, address);
// Set static type (Unknown) on the *new* node
(N.Identifier as TAstNode).StaticType := TTypes.Unknown; // TypeChecker will set this
// 4. Mutate this declaration node