Ast environments
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user