\documentclass[]{article}
\usepackage{amsmath,graphicx,supertabular,hyperref,tabularx,ifthen}
\title{TIP \#211: Add Full Stack Trace Capability}
\date{August 10, 2004}
\author{Robert Seeger, Robert Seeger, Don Porter}
\urlstyle{sf}
\setlength{\parskip}{1ex}
\setlength{\parindent}{0pt}
\def\tipversion$#1${\texttt{\$#1\$}}
\def\tiplangle#1{\ensuremath{<}}
\def\tiprangle#1{\ensuremath{>}}
\def\tipbar#1{\ensuremath{|}}
\def\tipmail#1#2{\(\langle\){\small\expandafter\url{#1@#2}}\(\rangle\)}
\ifx\pdfoutput\undefined
\newcommand{\tipimage}[2]{\typeout{Make sure you download #1.eps}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.eps}}{\includegraphics[width=0.8\textwidth]{#1.eps}}}
\newcommand{\tipxref}[1]{}
\newcommand{\tipxrefend}{}
\else
\newcommand{\tipimage}[2]{\typeout{Make sure you create #1.pdf}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.pdf}}{\includegraphics[width=0.8\textwidth]{#1.pdf}}}
\pdfcatalog{/PageMode /UseOutlines}
\newcommand{\tipxref}[1]{\pdfannotlink attr {/C [0.5 0.5 1.0] /Border [0 0 1]} goto name {#1}}
\newcommand{\tipxrefend}{\pdfendlink}
\fi
\newenvironment{tipabstract}{\begin{abstract}}{\end{abstract}}
\begin{document}\maketitle
\begin{center}\begin{tabularx}{\linewidth}{|r@{: }X|}\hline
\textbf{TIP \#211}&\textbf{Add Full Stack Trace Capability}\\\hline
Author&

Robert Seeger \tipmail{robert_seeger}{users.sourceforge.net}
\par
Robert Seeger \tipmail{rseeger00}{aol.com}
\par
Don Porter \tipmail{dgp}{users.sourceforge.net}
\\
Created&Tuesday, \(\text{10}^{\text{th}}\) August 2004\\
Type&Project\\
Tcl Version&\(8.5\)\\
State&Withdrawn\\
Vote&Pending\\
Version&\tipversion$Revision: 1.6 $\\
Keywords&Tcl\\
Obsoleted By&280\\
Post History&\\
\hline\end{tabularx}\end{center}
\thispagestyle{empty}\pagestyle{empty}
\begin{tipabstract}

This TIP proposes adding a new subcommand to the \textbf{info} command to get a list of all the frames on the current stack, rather than the limited list returned by \textbf{info level}.
\end{tipabstract}
\tableofcontents\setcounter{page}{0}\clearpage\pagestyle{plain}

\section{Rationale}

Currently, there is no way to get a list of all the frames in the current stack managed by \textbf{Tcl\_PushCallFrame()} and \textbf{Tcl\_PopCallFrame()}. The \textbf{info level} command does not contain frames that are callers of \textbf{uplevel}, reporting only the frames that are accessible via another \textbf{uplevel} command. There are times when the lack of information can have a negative impact on code design. The difference in information can be seen with the following code snippets:
\begingroup\small\begin{verbatim}
% proc bob {args} { 
    joe {expand}$args
  }
% proc joe {args} {
    uplevel 1 dave {expand}$args
  }
% proc dave {args} {
    puts "Level: [info level]"
    for {set i [info level]} { $i > 0 } {incr i -1 } {
      puts "${i}: [info level $i]"
    }
  }
% bob x y z
Level: 2
2: dave x y z
1: bob x y z
% proc dave {args} {
    puts "Level: [info frame]" 
    for {set i [info frame]} { $i > 0 } {incr i -1 } {
      puts "${i}: [info frame $i]"
    }
  }
% bob
Level: 3
3: dave x y z
2: joe x y z
1: bob x y z
\end{verbatim}
\endgroup

There are 3 reasons I see for bringing forth this TIP: 
\begin{enumerate}
\item{}
It's an introspection ability that is currently lacking, with no good reason for that lack.
\setcounter{enumi}{1}
\item{}
The more information that is available to the programmer, the easier it is to accomplish a goal in a straightforward, easily maintainable way.
\setcounter{enumi}{2}
\item{}
I have code in which the impact of not having this information available is visible.
\end{enumerate}

\subsection{Use Cases}

There are two cases I have run into where the ability to query all frames on the stack would have been particularly useful.
\begin{enumerate}
\item{}
\textbf{TclTest}

The first case is with Tcltest, where the complete lack of ability to gain access to that information means it is impossible to gain information about a test without modifying the Tcltest code itself. Being able to find out the name of the current test would be very handy, especially in naming test procs and logging information. Currently, there is no way to find out the name of the currently executing test, due to the fact that the code for the test is \textbf{uplevel}ed and, hence, not visible via \textbf{info level}.
\setcounter{enumi}{1}
\item{}
\textbf{TestStubs Package}

The TestStubs package provides the ability to temporarily redefine commands, in particular for stubbing out or replacing functionality in a test case. There is a command in the package called \textbf{chain}, which is used within the code replacing a command (or part of a command) to call the original definition of the command. For example, one could do:
\begingroup\small\begin{verbatim}
stubs::stub ensemble array names {
    return [lsort [uplevel 1 chain names $args]]
}
\end{verbatim}
\endgroup

However, since the \textbf{chain} command is (and should be) limited to only running from within a stub definition, it needs to call \textbf{info level} to find out if its caller is one of the stubbed commands, and what the name of that command is. With \textbf{info level}, it would not have access to the level that is running inside the stubbed procedure. Hence, either it cannot check this constraint, or stubs cannot be allowed to use \textbf{uplevel} when calling it (which means things like the above either cannot work, or need to be rewritten in a considerably less clear manner).
\end{enumerate}

\section{Proposed Change}

I propose to add a new subcommand to the info command with the following syntax:

\begin{quote}
\textbf{info frame} ?\textit{level}?
\end{quote}

The new functionality will provide access to all frames on the stack rather than the current limited subset. The information to do so already exists within the Interp object that all commands are passed, and the code needed to expose it differs in only a few aspects from that of \textbf{info level}.

This TIP does \textit{not} propose to alter \textbf{uplevel} or \textbf{upvar} so that they can see these hidden levels.

\subsection{Child Interps}

The current implementation of \textit{info level} only returns levels up to the top of the stack for the current interpreter. Such an approach puts limitations on what information can be retrieved, but allows for a certain level of \textit{``security''} when running code in child interps, especially safe interps.

Given the security considerations of safe interps, and consistancy with regards to what information is returned across multiple circumstances, the stack trace returned will only return information up to the top level of the current interp, the same limit \textit{info level} is bound by. 

\section{Implementation}

An implementation patch is available on SourceForge [\url{http://sourceforge.net/tracker/?func=detail&aid=1503647&group_id=10894&atid=310894}].

\section{Copyright}

This document has been placed in the public domain.

Please note that any correspondence to the author concerning this TIP is considered in the public domain unless otherwise specifically requested by the individual(s) authoring said correspondence. This is to allow information about the TIP to be placed in a public forum for discussion.

\section{Colophon}

\textit{TIP AutoGenerator --- written by Donal K. Fellows}
\end{document}
