Ast environments

This commit is contained in:
Michael Schimmel
2025-11-07 19:40:35 +01:00
parent 4ccf3bb5fd
commit c0f871ce02
12 changed files with 722 additions and 364 deletions
+48 -3
View File
@@ -49,7 +49,8 @@ type
procedure SetValues(const Address: TResolvedAddress; const Value: TDataValue);
{$endregion}
procedure Define(const Name: string; const Value: TDataValue);
// Defines a symbol and returns its runtime address
function Define(const Name: string; const Value: TDataValue): TResolvedAddress;
// Defines a variable at a given address and stores it directly in a shared cell (boxing).
procedure DefineBoxed(SlotIndex: Integer; const Value: TDataValue);
@@ -59,6 +60,8 @@ type
function Capture(const Address: TResolvedAddress): IValueCell;
function GetNameID(const Name: String): Integer;
// Resolves a name to an address by searching the runtime scope chain.
function Resolve(const Name: string): TResolvedAddress;
function CreateDescriptor: IScopeDescriptor;
@@ -143,8 +146,9 @@ type
destructor Destroy; override;
procedure Clear;
function GetNameID(const Name: String): Integer;
function Resolve(const Name: string): TResolvedAddress;
function Dump: string;
procedure Define(const Name: string; const Value: TDataValue);
function Define(const Name: string; const Value: TDataValue): TResolvedAddress;
procedure DefineBoxed(SlotIndex: Integer; const Value: TDataValue);
function Capture(const Address: TResolvedAddress): IValueCell;
function CreateDescriptor: IScopeDescriptor;
@@ -336,7 +340,7 @@ begin
Result := TScopeDescriptor.CreateDescriptor(Self);
end;
procedure TExecutionScope.Define(const Name: string; const Value: TDataValue);
function TExecutionScope.Define(const Name: string; const Value: TDataValue): TResolvedAddress;
var
id: Integer;
index: Integer;
@@ -351,6 +355,11 @@ begin
FValues[index].Value := Value;
FValues[index].IsBoxed := False;
FNameToIndex.Add(id, index);
// Return the address
Result.Kind := akLocalOrParent;
Result.ScopeDepth := 0;
Result.SlotIndex := index;
end;
procedure TExecutionScope.DefineBoxed(SlotIndex: Integer; const Value: TDataValue);
@@ -480,6 +489,42 @@ begin
end;
end;
function TExecutionScope.Resolve(const Name: string): TResolvedAddress;
var
nameID: Integer;
slotIndex: Integer;
currentScope: IExecutionScope;
depth: Integer;
begin
currentScope := Self;
depth := 0;
// GetNameID is shared (or recreated) across the scope chain
nameID := GetNameID(Name);
while Assigned(currentScope) do
begin
// We must cast to the implementation class to access 'NameToIndex'
var execScopeImpl := (currentScope as TExecutionScope);
// Accessing .NameToIndex property ensures NeedNameToIndex is called
if execScopeImpl.NameToIndex.TryGetValue(nameID, slotIndex) then
begin
// Found in this scope
Result.Kind := akLocalOrParent;
Result.ScopeDepth := depth;
Result.SlotIndex := slotIndex;
exit;
end;
// Not found, go to parent
inc(depth);
currentScope := currentScope.Parent;
end;
// Not found in the entire chain
Result := Default(TResolvedAddress); // Kind = akUnresolved
end;
procedure TExecutionScope.SetValues(const Address: TResolvedAddress; const Value: TDataValue);
var
targetScope: TExecutionScope;