private static SymbolAtom FigureOutLocalVarName(StackEntry stackEntry, ILocalVar lvar) { Contract.Requires(stackEntry != null); Contract.Requires(lvar != null); // if lvar.Name is explicitly set --> return lvar.Name if (lvar.Name.IsValid) { return(lvar.Name); } // if lvar.Index is less than the number of captured variables in this frame --> look up the name in the parent frame. if (stackEntry.Lambda.Captures > lvar.Index) { while ((stackEntry = stackEntry.Previous) != null) { var localVarInParentFrame = stackEntry.DebugInfo.m_locals[lvar.Index]; if (localVarInParentFrame.Name.IsValid) { return(localVarInParentFrame.Name); } } } // Invalid if all previous efforts failed. return(SymbolAtom.Invalid); }
/// <nodoc /> internal void Link(ref StackEntry current) { Contract.Requires(Previous == null); Depth = current?.Depth + 1 ?? 1; Previous = current; current = this; }
/// <nodoc /> internal static StackEntry Unlink(ref StackEntry current) { Contract.Requires(current != null); var freedStackEntry = current; current = current.Previous; freedStackEntry.Previous = null; return(freedStackEntry); }
/// <summary> /// Returns a list of currently accessible local variables for a given stack entry, respecting variable shadowing inside of lambdas. /// </summary> public static IReadOnlyList <ILocalVar> ComputeCurrentLocals(StackEntry stackEntry) { var debugInfo = stackEntry?.DebugInfo; if (debugInfo == null) { return(CollectionUtilities.EmptyArray <ILocalVar>()); } return(stackEntry.DebugInfo.m_locals .Select(arg => (ILocalVar) new ComputedLocalVar(arg.Index, FigureOutLocalVarName(stackEntry, arg), arg.Value)) .Where(p => p.Name.IsValid) .GroupBy(p => p.Name) .Select(grp => grp.Last()) .ToArray()); }