Making AST node inmmutable - WIP
This commit is contained in:
+48
-34
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user