[plt-scheme] SXML for R6RS [was: R6RS Interoperability]

From: Derick Eddington (derick.eddington at gmail.com)
Date: Wed Jul 9 08:58:51 EDT 2008

On Tue, 2008-07-08 at 12:19 -0600, Matthew Flatt wrote:
> At Thu, 03 Jul 2008 03:43:02 -0700, Derick Eddington wrote:
> > * SSAX issue: MzScheme does not conform [1] to the R6RS expectation that
> > the initial/default exception handler return for non-&serious
> > conditions [2].  Returning for non-&serious conditions allows you to do
> > things like raise-continuable a &warning condition to let interested
> > clients catch it and do something about it and maybe return, or the
> > default handler will return, and execution can continue.  I made my
> > ssax:warn procedure do this and the SSAX library frequently
> > calls ssax:warn when issues that often can safely be ignored happen. 
> 
> I worry about this implementation of `ssax:warn'. If someone calls into
> SSAX with a context like
> 
>   (guard (exn
> 	  [(serious? exn) "give up"])
>     (with-input-from-file
>       "foo"
>       (lambda ()
>          ... call SSAX ...)))
> 
> then `ssax:warn' will lead to undefined behavior on the "foo" port when
> control escapes to the `guard', even though the exception won't be
> caught by the `guard' handler --- right? (I have in mind R6RS semantics
> of exceptions and `guard', as opposed to the current PLT approximation.)

W.r.t. the "foo" port and control escaping to the `guard' and then the
`guard' re-raising -- I think that's okay for an R6RS-conforming `guard'
-- see the first part of my original response below.

But I realized there's another problem: I realized w.r.t. the
continuable exception aspect, it all hinges on whether `guard' will
re-raise the unhandled exception as a continuable exception if the
original was a continuable exception.  I had been assuming this was the
intent of the R6RS.  However, I note that the R6RS says: "[if none of
the `guard' clauses handle the exception] then `raise' is re-invoked on
the raised object within the dynamic environment of the original call to
`raise' except that the current exception handler is that of the `guard'
expression."  That clearly says `raise', but how can `raise' be
"re-invoked" and how can there be an "original call to `raise'" if it
was not called in the first place because it was `raise-continuable'
that was originally called?  I think I'll take this up on r6rs-discuss.

==== Original Response ===============================================

I think the situation you show above is okay because:

R6RS says of `with-input-from-file': "During the dynamic extent of the
call to [with-input-from-file's] thunk, the obtained port is made the
value returned by [the] current-input-port [procedure]; the previous
default [value is] reinstated when the dynamic extent is exited.  When
thunk returns, the port is closed automatically.  [...]  If an escape
procedure is used to escape back into the call to thunk after thunk is
returned, the behavior is unspecified."  And similarly for the other
`call-with-' procedures -- they only close their port if/when their
`proc' returns.

R6RS says `guard' will re-raise "within the dynamic environment of the
original call to raise except that the current exception handler is that
of the guard expression".  

So, when control escapes to the `guard' implicit cond, the "foo" port
will not be closed and the previous value of `current-input-port' will
be reinstated.  When `guard' re-enters the dynamic environment of the
original call to raise to re-raise the unhandled non-&serious, this
dynamic environment includes that of (with-input-from-file "foo" ---)
so `current-input-port' will be reset to the "foo" port.  If the next
exception handler is the initial/default exception handler which returns
for non-&serious, it will return to the ssax:warn's raise-continuable
and the program continues and everything should be okay.  If the next
exception handler is not the initial one, and it was installed by the
program using `with-exception-handler', it will be called in the same
dynamic extent (minus one more level of exception handler) as the
original raise, and it will be up to it to return and allow the program
to continue or not, and if it does not return so the
`with-input-from-file' thunk can return, then the "foo" port will not
be closed, but this issue always applies to all the "with port"
procedures and exception handlers exiting their dynamic extent.  If the
next exception handler is not the initial one and it was installed by
the program using `guard', then all the above applies about escaping to
the guard's implicit cond and re-entering the dynamic environment of the
original raise if the guard doesn't handle the exception.

At least, that's how I interpret the R6RS design.
======================================================================

-- 
: Derick
----------------------------------------------------------------



Posted on the users mailing list.