gcl-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Gcl-devel] condition system proposal


From: Camm Maguire
Subject: Re: [Gcl-devel] condition system proposal
Date: 01 Nov 2002 00:03:20 -0500

Greetings, Peter, and thanks as always for your thorough ideas and
work!

1) I agree the error system is in a mess.  o/error.c, lsp/serror.lsp
   and clcs/kcl-cond.lisp clcs/conditions.lisp all seem to have been
   added at separate times.

2) We need to find a way to smoothly transition to whatever new
   structure we decide upon without breaking anything in maxima or
   acl2.  GCL now compiles both of these on all 11 Debian
   architectures plus a few other machines, and I'd like to keep it
   this way at all times if possible.

3) Many of Paul's tests have already revolved around this issue, and
   many of my patches thus far have likewise addressed error
   conditions.  If you look through the CVS log on kcl-cond.lisp,
   error.c, and package.d (for example), you can see what's been done
   so far.  In all of this I've attempted to take the minimal steps
   necessary to fix the test without spoiling existing function
   interfaces possibly in use by other code.  This has not always been
   possible, but has in general been achievable as far as I can tell.
   While this approach unfortunately makes for poor overall design, it
   does allow us to focus on getting correct behavior quickly without
   breaking existing functionality, and hopefully leaving us in a
   position to redesign certain items once we've consolidated a bit.

4) The error messages I've put in recently in particular need work.
   I've tried to label such places with a FIXME comment in the code.

5) This having been said, I don't think your proposal is necessarily
   too radical for the above goals.  In fact, its quite similar to
   what we've been doing in general, i.e. replacing all instances of
   FEerror with something more specific.  So in general I like this
   proposal very much.  Here are some thoughts which we might need to
   discuss:  

        a) Do we need 'internal' error subtypes in any/all cases?
        can't we throw the main type where allowed by the spec,
        e.g. package-error? 

        b) we need to make sure the interface allows us to specify
        that the error is correctable.  See the 'specific-error' and
        'specific-correctable-error' hacks in error.c

        c) A lot of existing lisp code calls (error "foo" ...).  So
        does this mean we have to name a function with a fuller syntax
        like (foo :internal-bar-error :correctable "asdasda" ...)(
        something other than 'error'?  I've made this assumption thus
        far.  

        d) Until we standardize on the ansi image (at least), whatever
        we do has to work with the traditional image as well.  clcs
        overwrites the function 'error' defined in error.c for the
        traditional image.  

        e) while we're at it, we should also standardize where a given
        error condition defines what data it takes.  There appears to
        be code to this effect both in conditions.lisp and
        kcl-cond.lisp.  Will every error of the same type have the
        same error string?  I kind of like a dual solution like "Type
        error: ~S is not of type ~S: <specific instance message if
        available>".  Each instance could then pass clarifying
        information -- see the previous error messages that were in
        package.d before I truncated them to conform with the existing
        package-error expectations.

        f) once we agree on a system (and I'd like to hear Paul's and
        hopefully Vadim's comments here), perhaps what we would then
        do is to decide that no one commits any further error fixes
        while you work on your implementation.  Once you've verified
        that all maxima and acl2 tests still pass, we can check it in
        en masse to CVS.  With the current state of gcl, quite a few
        people appear to be using CVS, so I'd really like to not break
        it if possible.


More later...

Take care,


Peter Wood <address@hidden> writes:

> Hi
> 
> First of all, this is a long mail, for which I apologise.  Secondly,
> this proposal entails a fair amount of work, which I am volunteering
> to do.  However, I would appreciate some feedback first:
> 
> Is there anything anyone sees in the following that is
> inadvisable/unworkable/misguided/stupid?
> 
> The error system is not in great shape. Some ansi conditions are
> missing (eg division-by-zero), and more seriously, the conditions
> which get signalled are neither (1) identifiable as ansi conditions,
> nor (2) practically useable by a programmer because their names are
> not predictable from a knowledge of the spec.
> 
> For example: In o/catch.c
> 
>         fr = frs_sch_catch(tag);
>       if (fr == NULL)
>         FEerror("~S is an undefined tag.", 1, tag);
> 
> Creates #<conditions::internal-simple-error.0>
> 
> Which is the identical condition type to _lots_ of quite diverse types
> including the condition signalled by (/ 1 0).
> 
> This means the programmer can't distinguish between the two in a
> handler-bind or handler-case.
> 
> The spec (from my reading) allows us to define new types (like
> 'internal-simple-program-error) but (1) they should be in their own
> package (2) they should be subtypes of appropriate ansi types so that
> a programmer can use them sensibly without knowing in advance what
> they are called.(3) All the standard types must be there and (4) we
> must preserve the standard type hierarchy.
> 
> For eaxample: 
> 
> (bearing in mind that, According To The Spec (ATTS): "The type
> program-error consists of error conditions related to incorrect
> program syntax. The errors that result from naming a go tag or a block
> tag that is not lexically apparent are of type program-error.")
> 
> We can define conditions::internal-simple-program-error to be a
> subtype of program-error and then change the catch.c example above to:
> 
>  fr = frs_sch_catch(tag);
>       if (fr == NULL)
>         UNDEFINED_TAG(tag)
> 
> Where UNDEFINED_TAG(x) looks like this (in a new header file
> 'h/lisp-error.h') which gets #included by "include.h"
> 
> EXTER object Icall_error_handler();
> 
> #define UNTAGMESSAGE make_simple_string("Syntax Error: The tag ~S is 
> undefined.")
> #define UNDEFINED_TAG(x) 
> {Icall_error_handler(sKinternal_simple_program_error,UNTAGMESSAGE,1,(x));}
> 
> We use sKinternal_simple_program_error as the error name because its a
> keyword in its own package and doesn't pollute the COMMON-LISP
> package.
> 
> In clcs/condition-definitions.lisp we define the condition
> internal-simple-program-error (and _not_ export it).  In
> clcs/kcl-cond.lisp we change the internal-error-hash-table to look
> something like this:
> 
> (defparameter *internal-error-list*
>   '((division-by-zero :operands)
>     (arithmetic-error :operation :operands)
>     (unbound-variable :name)
>     (:internal-simple-program-error
> conditions::internal-simple-program-error :format-string
> :format-arguments))) ;;etc
> 
> Where the lookup is done on the car, and if it is a keyword, we set
> the data to the cdr, otherwise it is what gets returned by the lookup.
> All the ansi-standard condition types can be referred to directly
> since the condition name can be a symbol in COMMON-LISP.  
> 
> Ie, in o/num_arith.c in the function number_divide():
> 
>  if(number_zerop(y) == TRUE)
>                   DIVISION_BY_ZERO(x,y)
> 
> Where DIVISION_BY_ZERO is #defined in h/lisp-error.h to be 
> 
> #define DIVZMESSAGE make_simple_string("Division with operands ~S is an 
> error")
> #define DIVISION_BY_ZERO(x,y) 
> {Icall_error_handler(sLdivision_by_zero,DIVZMESSAGE,1,make_cons((x),make_cons((y),
>  Cnil)));}
> 
> and lisp-error.h also gets #included by num_include.h.
> 
> Under this proposal, we will keep FEerror as a fallback, but most
> (all, except for some very primitive calls) calls to FEerror will be
> replaced by appropriate macros.  Some/Most of the other FE<name> calls
> and functions can eventually be dumped, if this works out and proves
> robust.  The ansi-standard conditions will be mostly left just as a
> template, and GCL internal-xyz-errors will inherit from them
> appropriately.
> 
> I have implemented the beginnings of this proposal.  Here's what it
> looks like in practice:
> 
> ============================================================
> >(/ 1 0)
> 
> DIVISION operation with operands (1 0) is an error
> 
> Fast links are on: do (use-fast-links nil) for debugging
> Broken at /.  Type :H for Help.
>  1 (Abort) Return to top level.
> dbl:>>:q
> 
> Top level.
> >(go foo)
> 
> Syntax Error: The tag FOO is undefined.
> 
> Fast links are on: do (use-fast-links nil) for debugging
> Broken at GO.  Type :H for Help.
>  1 (Abort) Return to top level.
> dbl:>>
> 
> >(defmacro tec (ec ef)
>   `(handler-case ,ef (,ec (c) (format t "Gotcha: ~A" c))))
> 
> TEC
> 
> >(tec program-error (go foo))
> Gotcha: Syntax Error: The tag FOO is undefined.
> NIL
> 
> >(tec division-by-zero (/ 1 0))
> Gotcha: DIVISION operation with operands (1 0) is an error
> NIL
> 
> >(tec unbound-variable (cons 1 a))
> Gotcha: The variable A is unbound.
> NIL
> 
> >(tec division-by-zero (go foo))
> 
> Syntax Error: The tag FOO is undefined.
> 
> Fast links are on: do (use-fast-links nil) for debugging
> Broken at GO.  Type :H for Help.
>  1 (Abort) Return to top level.
> dbl:>>:q
> 
> ================================================= etc ===
> 
> I have only tried testing one place in the compiler with a new error
> macro, and it works fine, so far.  
> 
> In cmpnew/cmpcatch.lsp
> 
>   (wt-nl "fr=frs_sch_catch(" loc ");")
> ;  (wt-nl "if(fr==NULL) FEerror(\"The tag ~s is undefined.\",1," loc ");")
>   (wt-nl "if(fr==NULL) UNDEFINED_TAG(" loc ")")
> 
> produces c-code like this:
> 
>       fr=frs_sch_catch(VV[0]);
>       if(fr==NULL) UNDEFINED_TAG(VV[0])
> 
> The following work as expected when compiled with the changed
> compiler:
> 
> (defun test-throw-code-1 ()
>   (catch 'foo
>     (sub)))
> => FOO
> 
> (defun sub ()
>   (throw 'foo 'foo))
> 
> (defun test-throw-code-2 ()
>   (sub))
> => Syntax Error: The tag FOO is undefined.
> 
> The macros get included in cmpinclude.h via protoize.h.  Is there a
> better way to do this? 
> 
> If noone has any objections, I will continue working along these
> lines.  Of course, I won't commit any changes without agreement, but I
> wanted to ask for comments now, since there's quite a bit of work
> here, and I don't want to do it if anyone can already see an
> objection.
> 
> Thanks for your patience.
> 
> Regards,
> Peter
> 
> 
> _______________________________________________
> Gcl-devel mailing list
> address@hidden
> http://mail.gnu.org/mailman/listinfo/gcl-devel
> 
> 

-- 
Camm Maguire                                            address@hidden
==========================================================================
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah




reply via email to

[Prev in Thread] Current Thread [Next in Thread]