diff --git a/Compilation/AsyncArrowMoveNextEmitter.ArrowFunctions.cs b/Compilation/AsyncArrowMoveNextEmitter.ArrowFunctions.cs index 1fdba6e8..ae62a051 100644 --- a/Compilation/AsyncArrowMoveNextEmitter.ArrowFunctions.cs +++ b/Compilation/AsyncArrowMoveNextEmitter.ArrowFunctions.cs @@ -66,7 +66,7 @@ private void EmitCapturingArrowInAsyncArrow(Expr.ArrowFunction af, MethodBuilder { _il.Emit(OpCodes.Dup); // Keep display class instance on stack - // Load the captured variable using the same logic as LoadVariable + // Load the captured variable using the capture-population loader LoadVariableForCapture(capturedVar); _il.Emit(OpCodes.Stfld, field); diff --git a/Compilation/AsyncArrowMoveNextEmitter.Variables.cs b/Compilation/AsyncArrowMoveNextEmitter.Variables.cs index d85afae5..857d1c3d 100644 --- a/Compilation/AsyncArrowMoveNextEmitter.Variables.cs +++ b/Compilation/AsyncArrowMoveNextEmitter.Variables.cs @@ -140,89 +140,6 @@ protected override void EmitAssign(Expr.Assign a) protected override void EmitStoreVariable(string name) => StoreVariable(name); - private void LoadVariable(string name) - { - // Check if it's a parameter of this arrow - if (_builder.ParameterFields.TryGetValue(name, out var paramField)) - { - _il.Emit(OpCodes.Ldarg_0); - _il.Emit(OpCodes.Ldfld, paramField); - SetStackUnknown(); - return; - } - - // Check if it's a hoisted local of this arrow - if (_builder.LocalFields.TryGetValue(name, out var localField)) - { - _il.Emit(OpCodes.Ldarg_0); - _il.Emit(OpCodes.Ldfld, localField); - SetStackUnknown(); - return; - } - - // Check if it's captured from outer scope - if (_builder.IsCaptured(name) && _builder.CapturedFieldMap.TryGetValue(name, out var outerField)) - { - // Load through outer reference - // Use Unbox (not Unbox_Any) to get a pointer to the boxed struct, then load field - _il.Emit(OpCodes.Ldarg_0); - _il.Emit(OpCodes.Ldfld, _builder.OuterStateMachineField!); - - // Check if this is a transitive capture (needs extra indirection through parent's outer) - if (_builder.TransitiveCaptures.Contains(name) && - _builder.ParentOuterStateMachineField != null && - _builder.GrandparentStateMachineType != null) - { - // First unbox to parent, then load parent's outer reference - _il.Emit(OpCodes.Unbox, _builder.OuterStateMachineType!); - _il.Emit(OpCodes.Ldfld, _builder.ParentOuterStateMachineField); - _il.Emit(OpCodes.Unbox, _builder.GrandparentStateMachineType); - } - else - { - _il.Emit(OpCodes.Unbox, _builder.OuterStateMachineType!); - } - - _il.Emit(OpCodes.Ldfld, outerField); - SetStackUnknown(); - return; - } - - // Check for non-hoisted local variable - if (_locals.TryGetValue(name, out var local)) - { - _il.Emit(OpCodes.Ldloc, local); - SetStackUnknown(); - return; - } - - // Check if it's an imported value (from another module) - must check BEFORE Functions - // because cross-module function references need to go through the import field - if (_ctx?.TopLevelStaticVars?.TryGetValue(name, out var topLevelField) == true) - { - _il.Emit(OpCodes.Ldsfld, topLevelField); - SetStackUnknown(); - return; - } - - // Check if it's a global function - if (_ctx?.Functions.TryGetValue(_ctx.ResolveFunctionName(name), out var funcMethod) == true) - { - // Load function reference - _il.Emit(OpCodes.Ldnull); - _il.Emit(OpCodes.Ldtoken, funcMethod); - _il.Emit(OpCodes.Call, Types.MethodBaseGetMethodFromHandle); - _il.Emit(OpCodes.Castclass, typeof(MethodInfo)); - _il.Emit(OpCodes.Newobj, _ctx.Runtime!.TSFunctionCtor); - SetStackUnknown(); - return; - } - - // Fallback: null - _il.Emit(OpCodes.Ldnull); - SetStackType(StackType.Null); - } - private void StoreVariable(string name) { // A capture promoted into the enclosing function's display class (#625) is stored through @@ -325,7 +242,7 @@ private void StoreVariable(string name) /// /// Loads a variable value for populating a capture in a non-async arrow's display class. - /// This is similar to LoadVariable but designed for capture population. + /// This is similar to the EmitVariable override but designed for capture population. /// private void LoadVariableForCapture(string name) {