From 100646c7d82f18c1f9cd1b22ea1b04f2f215c7c9 Mon Sep 17 00:00:00 2001 From: Michael Schimmel Date: Fri, 5 Sep 2025 12:46:24 +0200 Subject: [PATCH] Scope cells refactoring --- ASTPlayground/MainForm.pas | 6 +- Src/AST/Myc.Ast.Evaluator.pas | 12 ++-- Src/AST/Myc.Ast.Nodes.pas | 26 ++++++-- Src/AST/Myc.Ast.Scope.pas | 114 ++++++++-------------------------- Src/AST/Myc.Ast.pas | 20 ++---- 5 files changed, 61 insertions(+), 117 deletions(-) diff --git a/ASTPlayground/MainForm.pas b/ASTPlayground/MainForm.pas index 10ec06f..5d8d1b1 100644 --- a/ASTPlayground/MainForm.pas +++ b/ASTPlayground/MainForm.pas @@ -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; diff --git a/Src/AST/Myc.Ast.Evaluator.pas b/Src/AST/Myc.Ast.Evaluator.pas index a52f2ed..5bb458d 100644 --- a/Src/AST/Myc.Ast.Evaluator.pas +++ b/Src/AST/Myc.Ast.Evaluator.pas @@ -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)); diff --git a/Src/AST/Myc.Ast.Nodes.pas b/Src/AST/Myc.Ast.Nodes.pas index 9ce284c..68a337c 100644 --- a/Src/AST/Myc.Ast.Nodes.pas +++ b/Src/AST/Myc.Ast.Nodes.pas @@ -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; diff --git a/Src/AST/Myc.Ast.Scope.pas b/Src/AST/Myc.Ast.Scope.pas index 6326e83..a212875 100644 --- a/Src/AST/Myc.Ast.Scope.pas +++ b/Src/AST/Myc.Ast.Scope.pas @@ -17,8 +17,6 @@ type FCapturedUpvalues: TArray; FNameToIndex: TDictionary; 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. diff --git a/Src/AST/Myc.Ast.pas b/Src/AST/Myc.Ast.pas index df4d90c..7e6c2fa 100644 --- a/Src/AST/Myc.Ast.pas +++ b/Src/AST/Myc.Ast.pas @@ -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 }