Scope cells refactoring
This commit is contained in:
@@ -394,7 +394,7 @@ end;
|
||||
|
||||
procedure TForm1.OHLCButtonClick(Sender: TObject);
|
||||
const
|
||||
numRecs = 100;
|
||||
numRecs = 1000;
|
||||
lookback = 50;
|
||||
smaSlowLength = 20;
|
||||
smaFastLength = 10;
|
||||
@@ -561,12 +561,12 @@ begin
|
||||
if series.AsRecordSeries.Value.TotalCount >= smaSlowLength then
|
||||
begin
|
||||
// Update the 'current_series' value in the scope using the FAST index-based assignment
|
||||
scope[seriesAddress] := series;
|
||||
scope[seriesAddress].Value := series;
|
||||
|
||||
// Execute the PRE-BOUND call AST
|
||||
var resultValue := callAst.Accept(visitor);
|
||||
|
||||
if i < smaSlowLength + 50 then
|
||||
if i mod 50 = 0 then
|
||||
begin
|
||||
Memo1.Lines.Add(Format('Tick %d/%d: Close = %.2f, Signal = %s', [i, numRecs, ohlcvRec.Close, resultValue.ToString]));
|
||||
Application.ProcessMessages;
|
||||
|
||||
@@ -309,7 +309,7 @@ var
|
||||
lookback: Int64;
|
||||
begin
|
||||
// The target series must have been resolved by the binder.
|
||||
seriesVar := FScope[Node.Series.Address];
|
||||
seriesVar := FScope[Node.Series.Address].Value;
|
||||
itemValue := Node.Value.Accept(Self);
|
||||
lookback := -1;
|
||||
|
||||
@@ -360,7 +360,7 @@ end;
|
||||
function TEvaluatorVisitor.VisitAssignment(const Node: IAssignmentNode): TAstValue;
|
||||
begin
|
||||
Result := Node.Value.Accept(Self);
|
||||
FScope[Node.Identifier.Address] := Result;
|
||||
FScope[Node.Identifier.Address].Value := Result;
|
||||
end;
|
||||
|
||||
function TEvaluatorVisitor.VisitConstant(const Node: IConstantNode): TAstValue;
|
||||
@@ -393,7 +393,7 @@ end;
|
||||
|
||||
function TEvaluatorVisitor.VisitIdentifier(const Node: IIdentifierNode): TAstValue;
|
||||
begin
|
||||
Result := FScope[Node.Address];
|
||||
Result := FScope[Node.Address].Value;
|
||||
end;
|
||||
|
||||
function TEvaluatorVisitor.VisitIndexer(const Node: IIndexerNode): TAstValue;
|
||||
@@ -490,7 +490,7 @@ begin
|
||||
else
|
||||
value := TAstValue.Void;
|
||||
|
||||
FScope[Node.Identifier.Address] := value;
|
||||
FScope[Node.Identifier.Address].Value := value;
|
||||
|
||||
Result := value;
|
||||
end;
|
||||
@@ -559,12 +559,12 @@ begin
|
||||
|
||||
// Slot 0 is 'Self'.
|
||||
adr.SlotIndex := 0;
|
||||
callScope.Values[adr] := calleeValue;
|
||||
callScope[adr].Value := calleeValue;
|
||||
|
||||
for i := 0 to Node.Arguments.Count - 1 do
|
||||
begin
|
||||
adr.SlotIndex := closure.Parameters[i].Address.SlotIndex;
|
||||
callScope.Values[adr] := Node.Arguments[i].Accept(Self);
|
||||
callScope[adr].Value := Node.Arguments[i].Accept(Self);
|
||||
end;
|
||||
|
||||
Result := closure.Body.Accept(CreateVisitorForScope(callScope));
|
||||
|
||||
@@ -116,13 +116,14 @@ type
|
||||
Kind: TAddressKind;
|
||||
ScopeDepth: Integer;
|
||||
SlotIndex: Integer;
|
||||
Name: String;
|
||||
constructor Create(AKind: TAddressKind; AScopeDepth, ASlotIndex: Integer; const AName: String);
|
||||
class operator Initialize(out Dest: TResolvedAddress);
|
||||
end;
|
||||
|
||||
IExecutionScope = interface
|
||||
{$region 'private'}
|
||||
function GetParent: IExecutionScope;
|
||||
function GetValues(const Address: TResolvedAddress): TAstValue;
|
||||
procedure SetValues(const Address: TResolvedAddress; const Value: TAstValue);
|
||||
function GetCell(const Address: TResolvedAddress): IValueCell;
|
||||
{$endregion}
|
||||
|
||||
@@ -130,8 +131,7 @@ type
|
||||
function Dump: string;
|
||||
procedure Clear;
|
||||
|
||||
property Cell[const Address: TResolvedAddress]: IValueCell read GetCell;
|
||||
property Values[const Address: TResolvedAddress]: TAstValue read GetValues write SetValues; default;
|
||||
property Cell[const Address: TResolvedAddress]: IValueCell read GetCell; default;
|
||||
|
||||
property Parent: IExecutionScope read GetParent;
|
||||
end;
|
||||
@@ -484,6 +484,24 @@ begin
|
||||
Result := Default(TAstValue);
|
||||
end;
|
||||
|
||||
{ TResolvedAddress }
|
||||
|
||||
constructor TResolvedAddress.Create(AKind: TAddressKind; AScopeDepth, ASlotIndex: Integer; const AName: String);
|
||||
begin
|
||||
Kind := AKind;
|
||||
ScopeDepth := AScopeDepth;
|
||||
SlotIndex := ASlotIndex;
|
||||
Name := AName;
|
||||
end;
|
||||
|
||||
class operator TResolvedAddress.Initialize(out Dest: TResolvedAddress);
|
||||
begin
|
||||
Dest.Kind := akUnresolved;
|
||||
Dest.ScopeDepth := -1;
|
||||
Dest.SlotIndex := -1;
|
||||
Dest.Name := 'unresolved';
|
||||
end;
|
||||
|
||||
{ TBinaryOperatorHelper }
|
||||
|
||||
function TBinaryOperatorHelper.ToString: string;
|
||||
|
||||
+26
-88
@@ -17,8 +17,6 @@ type
|
||||
FCapturedUpvalues: TArray<IValueCell>;
|
||||
FNameToIndex: TDictionary<string, Integer>;
|
||||
procedure DumpScope(const ABuilder: TStringBuilder; AIndent: Integer);
|
||||
function GetValues(const Address: TResolvedAddress): TAstValue;
|
||||
procedure SetValues(const Address: TResolvedAddress; const Value: TAstValue);
|
||||
function GetParent: IExecutionScope;
|
||||
function GetCell(const Address: TResolvedAddress): IValueCell;
|
||||
public
|
||||
@@ -63,8 +61,6 @@ end;
|
||||
|
||||
{ TExecutionScope }
|
||||
|
||||
{ TExecutionScope }
|
||||
|
||||
constructor TExecutionScope.Create(
|
||||
AParent: IExecutionScope;
|
||||
const ADescriptor: IScopeDescriptor;
|
||||
@@ -99,23 +95,34 @@ begin
|
||||
end;
|
||||
|
||||
function TExecutionScope.GetCell(const Address: TResolvedAddress): IValueCell;
|
||||
var
|
||||
targetScope: TExecutionScope;
|
||||
i: Integer;
|
||||
begin
|
||||
// Cells can only be retrieved from local/parent scopes.
|
||||
if Address.Kind <> akLocalOrParent then
|
||||
raise EInvalidOpException.Create('Cannot get a cell for a non-local address.');
|
||||
|
||||
targetScope := Self;
|
||||
for i := 1 to Address.ScopeDepth do
|
||||
begin
|
||||
targetScope := targetScope.Parent as TExecutionScope;
|
||||
Assert(Assigned(targetScope), 'Invalid scope depth during cell retrieval.');
|
||||
case Address.Kind of
|
||||
akUpvalue:
|
||||
begin
|
||||
Assert(Assigned(FCapturedUpvalues), 'Attempt to access an upvalue in a scope with no closure context.');
|
||||
Assert(
|
||||
(Address.SlotIndex >= 0) and (Address.SlotIndex < Length(FCapturedUpvalues)),
|
||||
'Invalid upvalue index during value retrieval.'
|
||||
);
|
||||
Result := FCapturedUpvalues[Address.SlotIndex];
|
||||
end;
|
||||
akLocalOrParent:
|
||||
begin
|
||||
var targetScope := Self;
|
||||
for var i := 1 to Address.ScopeDepth do
|
||||
begin
|
||||
targetScope := targetScope.Parent as TExecutionScope;
|
||||
Assert(Assigned(targetScope), 'Invalid scope depth during value retrieval.');
|
||||
end;
|
||||
Assert(
|
||||
(Address.SlotIndex >= 0) and (Address.SlotIndex < Length(targetScope.Values)),
|
||||
'Invalid scope index during value retrieval.'
|
||||
);
|
||||
Result := targetScope.Values[Address.SlotIndex];
|
||||
end;
|
||||
else
|
||||
raise EInvalidOpException.Create('Cannot get value for an unresolved address.');
|
||||
end;
|
||||
|
||||
Assert((Address.SlotIndex >= 0) and (Address.SlotIndex < Length(targetScope.FValues)), 'Invalid scope index during cell retrieval.');
|
||||
Result := targetScope.FValues[Address.SlotIndex];
|
||||
end;
|
||||
|
||||
function TExecutionScope.GetParent: IExecutionScope;
|
||||
@@ -189,73 +196,4 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TExecutionScope.GetValues(const Address: TResolvedAddress): TAstValue;
|
||||
var
|
||||
targetScope: TExecutionScope;
|
||||
i: Integer;
|
||||
begin
|
||||
case Address.Kind of
|
||||
akUpvalue:
|
||||
begin
|
||||
Assert(Assigned(FCapturedUpvalues), 'Attempt to access an upvalue in a scope with no closure context.');
|
||||
Assert(
|
||||
(Address.SlotIndex >= 0) and (Address.SlotIndex < Length(FCapturedUpvalues)),
|
||||
'Invalid upvalue index during value retrieval.'
|
||||
);
|
||||
Result := FCapturedUpvalues[Address.SlotIndex].Value;
|
||||
end;
|
||||
akLocalOrParent:
|
||||
begin
|
||||
targetScope := Self;
|
||||
for i := 1 to Address.ScopeDepth do
|
||||
begin
|
||||
targetScope := targetScope.Parent as TExecutionScope;
|
||||
Assert(Assigned(targetScope), 'Invalid scope depth during value retrieval.');
|
||||
end;
|
||||
Assert(
|
||||
(Address.SlotIndex >= 0) and (Address.SlotIndex < Length(targetScope.Values)),
|
||||
'Invalid scope index during value retrieval.'
|
||||
);
|
||||
Result := targetScope.Values[Address.SlotIndex].Value;
|
||||
end;
|
||||
else
|
||||
raise EInvalidOpException.Create('Cannot get value for an unresolved address.');
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TExecutionScope.SetValues(const Address: TResolvedAddress; const Value: TAstValue);
|
||||
var
|
||||
targetScope: IExecutionScope;
|
||||
i: Integer;
|
||||
begin
|
||||
case Address.Kind of
|
||||
akUpvalue:
|
||||
begin
|
||||
Assert(Assigned(FCapturedUpvalues), 'Attempt to access an upvalue in a scope with no closure context.');
|
||||
Assert(
|
||||
(Address.SlotIndex >= 0) and (Address.SlotIndex < Length(FCapturedUpvalues)),
|
||||
'Invalid upvalue index during value assignment.'
|
||||
);
|
||||
FCapturedUpvalues[Address.SlotIndex].Value := Value;
|
||||
end;
|
||||
akLocalOrParent:
|
||||
begin
|
||||
targetScope := Self;
|
||||
for i := 0 to Address.ScopeDepth - 1 do
|
||||
begin
|
||||
if Assigned(targetScope) then
|
||||
targetScope := targetScope.Parent
|
||||
else
|
||||
raise EInvalidOpException.Create('Invalid scope depth during assignment.');
|
||||
end;
|
||||
|
||||
if Address.SlotIndex >= Length((targetScope as TExecutionScope).Values) then
|
||||
raise EInvalidOpException.Create('Invalid scope index during assignment.');
|
||||
(targetScope as TExecutionScope).Values[Address.SlotIndex].Value := Value;
|
||||
end;
|
||||
else
|
||||
raise EInvalidOpException.Create('Cannot set value for an unresolved address.');
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
+4
-16
@@ -436,10 +436,6 @@ constructor TIdentifierNode.Create(AName: string);
|
||||
begin
|
||||
inherited Create;
|
||||
FName := AName;
|
||||
// Default to unresolved.
|
||||
FResolvedAddress.Kind := akUnresolved;
|
||||
FResolvedAddress.ScopeDepth := -1;
|
||||
FResolvedAddress.SlotIndex := -1;
|
||||
end;
|
||||
|
||||
function TIdentifierNode.Accept(const Visitor: IAstVisitor): TAstValue;
|
||||
@@ -904,9 +900,7 @@ begin
|
||||
upvalueMap := FUpvalueMapStack.Peek;
|
||||
upvalueNodes := FUpvalueNodesStack.Peek;
|
||||
|
||||
originalAddress.Kind := akLocalOrParent;
|
||||
originalAddress.ScopeDepth := originalDepth;
|
||||
originalAddress.SlotIndex := originalIndex;
|
||||
originalAddress.Create(akLocalOrParent, originalDepth, originalIndex, identNode.Name);
|
||||
|
||||
if not upvalueMap.TryGetValue(originalAddress, upvalueIndex) then
|
||||
begin
|
||||
@@ -915,15 +909,11 @@ begin
|
||||
upvalueNodes.Add(identNode);
|
||||
end;
|
||||
|
||||
identNode.FResolvedAddress.Kind := akUpvalue;
|
||||
identNode.FResolvedAddress.SlotIndex := upvalueIndex;
|
||||
identNode.FResolvedAddress.ScopeDepth := 0;
|
||||
identNode.FResolvedAddress.Create(akUpvalue, 0, upvalueIndex, identNode.Name);
|
||||
end
|
||||
else
|
||||
begin
|
||||
identNode.FResolvedAddress.Kind := akLocalOrParent;
|
||||
identNode.FResolvedAddress.ScopeDepth := originalDepth;
|
||||
identNode.FResolvedAddress.SlotIndex := originalIndex;
|
||||
identNode.FResolvedAddress.Create(akLocalOrParent, originalDepth, originalIndex, identNode.Name);
|
||||
end;
|
||||
end
|
||||
else
|
||||
@@ -989,9 +979,7 @@ begin
|
||||
Node.Initializer.Accept(Self);
|
||||
|
||||
slotIndex := (FCurrentDescriptor as TScopeDescriptor).Define(Node.Identifier.Name);
|
||||
identNode.FResolvedAddress.Kind := akLocalOrParent;
|
||||
identNode.FResolvedAddress.ScopeDepth := 0;
|
||||
identNode.FResolvedAddress.SlotIndex := slotIndex;
|
||||
identNode.FResolvedAddress.Create(akLocalOrParent, 0, slotIndex, Node.Identifier.Name);
|
||||
end;
|
||||
|
||||
{ TAst }
|
||||
|
||||
Reference in New Issue
Block a user