98 lines
2.6 KiB
ObjectPascal
98 lines
2.6 KiB
ObjectPascal
unit Myc.Ast.Scope;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.SysUtils,
|
|
System.Classes,
|
|
System.Generics.Collections,
|
|
Myc.Data.Types;
|
|
|
|
type
|
|
// Manages the scope of execution, holding variables and their values.
|
|
TExecutionScope = class
|
|
private
|
|
FParent: TExecutionScope;
|
|
FVariables: TDictionary<string, IDataValue>;
|
|
// Added for recursive dumping
|
|
procedure DumpScope(const ABuilder: TStringBuilder; AIndent: Integer);
|
|
public
|
|
constructor Create(AParent: TExecutionScope = nil);
|
|
destructor Destroy; override;
|
|
function FindValue(const Name: string; out Value: IDataValue): Boolean;
|
|
procedure SetValue(const Name: string; const Value: IDataValue);
|
|
// Dumps the content of this scope and all parent scopes to a string.
|
|
function Dump: string;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{ TExecutionScope }
|
|
|
|
constructor TExecutionScope.Create(AParent: TExecutionScope = nil);
|
|
begin
|
|
inherited Create;
|
|
FParent := AParent;
|
|
FVariables := TDictionary<string, IDataValue>.Create;
|
|
end;
|
|
|
|
destructor TExecutionScope.Destroy;
|
|
begin
|
|
FVariables.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TExecutionScope.DumpScope(const ABuilder: TStringBuilder; AIndent: Integer);
|
|
var
|
|
pair: TPair<string, IDataValue>;
|
|
indentStr: string;
|
|
begin
|
|
indentStr := ''.PadLeft(AIndent);
|
|
if (FVariables.Count > 0) then
|
|
begin
|
|
for pair in FVariables do
|
|
ABuilder.AppendLine(indentStr + Format(' %s: %s', [pair.Key, pair.Value.AsString]));
|
|
end
|
|
else
|
|
begin
|
|
ABuilder.AppendLine(indentStr + ' (empty)');
|
|
end;
|
|
|
|
if Assigned(FParent) then
|
|
begin
|
|
ABuilder.AppendLine(indentStr + '[Parent Scope]');
|
|
FParent.DumpScope(ABuilder, AIndent + 2);
|
|
end;
|
|
end;
|
|
|
|
function TExecutionScope.Dump: string;
|
|
var
|
|
builder: TStringBuilder;
|
|
begin
|
|
builder := TStringBuilder.Create;
|
|
try
|
|
builder.AppendLine('[Current Scope]');
|
|
DumpScope(builder, 0);
|
|
Result := builder.ToString.TrimRight;
|
|
finally
|
|
builder.Free;
|
|
end;
|
|
end;
|
|
|
|
function TExecutionScope.FindValue(const Name: string; out Value: IDataValue): Boolean;
|
|
begin
|
|
Result := FVariables.TryGetValue(Name, Value);
|
|
if not Result and Assigned(FParent) then
|
|
begin
|
|
Result := FParent.FindValue(Name, Value);
|
|
end;
|
|
end;
|
|
|
|
procedure TExecutionScope.SetValue(const Name: string; const Value: IDataValue);
|
|
begin
|
|
// This defines a variable in the current scope. It can shadow a parent variable.
|
|
FVariables.AddOrSetValue(Name, Value);
|
|
end;
|
|
|
|
end.
|