|
From: Alexandre F. <ale...@gm...> - 2009-10-10 22:20:49
|
On 10/9/09, Joe English <jen...@fl...> wrote:
>
> Alexandre Ferrieux wrote:
>
> > Of course I have no objection regarding the API. It is trivial to
> > expose it through the [info] or [interp] ensembles rather than
> > variables. I'm just surprised to see this as a strong showstopper,
> > because I seem to recall some of you saying that the ::tcl namespace
> > was okay for the job.
>
> > Now to proceed is:
> > info errorstack --> gives the list
> > info errorstack <boolean> --> enables/disables the feature
>
> > Minor variations:
> > - "interp" ensemble instead of "info"
> > - boolean replaced or extended by "enable/disable"
>
>
>
> Where this really belongs is in the return options dictionary:
>
> catch $script result options
> dict get $options -errorstack
The only concern is that the value will then need to be built all the
time (a dict member cannot have traces), while it might be faster to
build an internal form that is not directly the errorstack Tcl value,
see below.
> Of course to be truly useful the error stack *also*
> needs to be accessible via [info] or [interp],
> for the benefit of those who neglected to catch
> the return options before making an error :-)
>
> I'd suggest: [info errorstack ?interp?], where ?interp?
> defaults to the calling interpreter if omitted.
OK, will do that shortly.
> As for how to turn it on and off -- I think it'd be OK,
> preferable even, to just leave this enabled all the time.
> The feature doesn't cost anything under normal operations,
> the only additional work done is during error propagation,
> which is not a time-critical part of any reasonable program.
>
> Also, that way users don't need to remember to turn the feature
> on before making a mistake that they will want to debug.
Yes, I feel sympathetic with that last remark, as I follow this
strategy all the time (no "debug level", always log, and delete the
logs if nothing went wrong)... as long as it doesn't hamper
performance. Here the overhead is slight but nonzero, so I'm ready to
work a little bit more on optimizing it, if we decide to leave the
feature on by default.
I believe the measured overhead comes from the ckalloc-ed element
arrays of the small lists built to contain argslist at each level; the
"backbone" list costs much less, because careful steps are taken to
modify it in-place whenever possible.
I can see two options to speed this up:
(1) grow a flat list instead of a list of lists, inserting integer
counts of arguments before each argslist: {3 foo a b 1 bar 2 baz
gnats} and transform it into a true error stack only on final [info
errorstack] request: {{foo a b} bar {baz gnats}}
(2) grow a Lisp-like nested linked list based on Tcl_Obj's which are
Cons cells (one car + one cdr). This has the advantage of relying
exclusively on the Tcl_Obj allocator. On final request, it must also
be transformed back into a true Tcl list (2a) , or (2b) at least have
a string representation identical to that of the wanted list (just
like dicts look like lists on strep examination).
If the constraint of landing in the options dict holds, then (2b) is
the way to go.
Please give me your preference.
> (BTW: I've since had a chance to look at the actual patch,
> and agree that the basic mechanism is minimally intrusive;
> I think it'd be OK for 8.6 (once amended).)
Thank you very much. Indeed I would find it very long to wait for 8.7
for a feature that's both really handy and really simple to implement.
-Alex
|