[R6RS] Safe/unsafe mode

dyb at cs.indiana.edu dyb at cs.indiana.edu
Wed Jul 12 23:18:07 EDT 2006


Here's a revised safety proposal, with answers to Will's questions.

Kent

--------

Scoping:

 * A declaration appearing in a <library body> or <body> associates the
   specified safe, priority with the code appearing within the
   <library body> or <body>, except where the declaration is shadowed by a
   conflicting declaration.

 * If the declare keyword of a declaration is introduced into the output
   of a macro, the declaration affects only the code introduced by
   the macro.  Similarly, code introduced by the macro is
   affected only by such declarations and declarations whose scope
   includes the macro definition.

Semantics:

 * An application associated with safe priority 0 or a syntactic form
   whose identifying keyword is imported from a standard R6RS library and
   associated with safe priority 0 has unspecified behavior if a situation
   for which the implementation is allowed or required to raise an
   exception arises directly from the use of the syntactic form.

 * A procedure obtained via reference to a variable that is imported
   from a standard R6RS library and associated with safe priority 0
   has unspecified behavior if a situation for which the implementation is
   required to raise an exception arises directly from the use
   of the procedure, including exceptions arising from constraints on
   the number, type, and compatibility of its arguments.

 * A procedure created by a standard define, lambda, or case-lambda
   whose identifying keyword is associated with safe priority 0 has
   unspecified behavior if the procedure receives a number of arguments
   for which an exception would ordinarily be raised.

--------

Here's how this proposal addresses each of Will's questions. 

> ; my-library exports my-name, my-memq, and my-memq-macro.
> ; my-name is a string.
> ; my-memq is like memq except it doesn't detect cyclic lists.
> ; my-memq-macro is a macro that expands into a call to my-memq.
> 
> (import "my-library")
> 
> ; Must the call to my-name raise an exception?
> 
> (define (bug1 x y z)
>   (declare unsafe)
>   (my-name x y z))

No.  The application is associated with safe priority 0, so an exception
need not be raised if my-name does not evaluate to a procedure.

> ; Must the call to my-memq raise an exception?
> 
> (define (bug2 x y z)
>   (declare unsafe)
>   (my-memq x y z))

If the procedure value of my-memq was created by a keyword (e.g., define
or lambda) that was imported from a standard R6RS library and associated
with safe priority 0, then no, otherwise yes.

> ; Must the call to my-memq in the macro-expanded code
> ; raise an exception?
> 
> (define (bug3 x y z)
>   (declare unsafe)
>   (my-memq-macro x y z))

See bug2.

> ; Should this code execute in constant space?
> 
> (define (bug4 x y)
>   (declare unsafe)
>   (define (loop x y n)
>     (if (> n 0)
>         (let* ((y2 (vector->list (list->vector y)))
>                (y3 (my-memq x y2)))
>           (if (not y3)
>               (loop x y2 (- n 1)))
>           y3)))
>   (loop x y (length y)))

As far as I know, R6RS will not require this to run in constant space even
without the declaration.  Whether it does or does not is implementation
dependent.  The implementation may or may not take into account the fact
that the definition of loop is within the scope of an unsafe declaration,
and it may or may not take into account how the procedure value of my-memq
was created.

> ; Should this code execute in constant space?
> 
> (define (bug5 x y)
>   (declare unsafe)
>   (define (loop x y n)
>     (if (> n 0)
>         (let* ((y2 (vector->list (list->vector y)))
>                (y3 (my-memq-macro x y2)))
>           (if (not y3)
>               (loop x y2 (- n 1)))
>           y3)))
>   (loop x y (length y)))

See bug4.

> ; Should this code be nicely interruptible?
> 
> (define (bug6 x y)
>   (declare unsafe)
>   (define (loop x y n)
>     (if (> n 0)
>         (if (not (my-memq x y))
>             (loop x y n))
>         y))
>   (loop x y (length y)))

R6RS says nothing about whether code should be interruptible, so this is
implementation dependent.  An implementation can certainly choose to treat
the code above differently in this respect from code that does not include
the unsafe declaration.

The answer might depend on how the procedure value of my-memq was created,
as with bug2.

> ; Should this code be nicely interruptible?
> 
> (define (bug7 x y)
>   (declare unsafe)
>   (define (loop x y n)
>     (if (> n 0)
>         (if (not (my-memq-macro x y))
>             (loop x y n))
>         y))
>   (loop x y (length y)))

See bug6.

> ; Should this code be nicely interruptible?
> 
> (define (bug8 x y)
>   (declare unsafe)
>   (define (loop x y n)
>     (if (> n 0)
>         (if (not (my-memq x y))
>             (loop x y (- n 1)))
>         y))
>   (set-cdr! y y)
>   (loop x y (length y)))

See bug6.

> ; Should this code be nicely interruptible?
> 
> (define (bug9 x y)
>   (declare unsafe)
>   (define (loop x y n)
>     (if (> n 0)
>         (if (not (my-memq-macro x y))
>             (loop x y (- n 1)))
>         y))
>   (set-cdr! y y)
>   (loop x y (length y)))

See bug6.



More information about the R6RS mailing list