bug#41956: [PATCH] ice-9: exceptions: Properly format the error message.

2020-06-25 Thread Bengt Richter
Hi Ricardo et al,

On +2020-06-25 12:04:27 +0200, Ricardo Wurmus wrote:
> 
> Hi Maxim,
> 
> here’s what I did in the REPL:
> 
> --8<---cut here---start->8---
> scheme@(guile-user)> ,m (ice-9 exceptions)
> scheme@(ice-9 exceptions)> (define (my/guile-system-error-converter key args)
>   (apply (case-lambda
>   ((subr msg-args msg errno . rest)
>;; XXX TODO we should return a more specific error
>;; (usually an I/O error) as expected by R6RS programs.
>;; Unfortunately this often requires the 'filename' (or
>;; other?) which is not currently provided by the native
>;; Guile exceptions.
>  (make-exception
>   (make-external-error)
> (make-exception-with-origin subr)
> (apply make-exception-with-message msg)
> (make-exception-with-irritants msg-args)))
>   (_ (guile-external-error-converter key args)))
>  args))
> scheme@(ice-9 exceptions)> (set! guile-exception-converters (acons 
> 'system-error my/guile-system-error-converter guile-exception-converters))
> scheme@(ice-9 exceptions)> ,m (guile-user)
> scheme@(guile-user)> (guard (c ((message-condition? c)
> (format #t "message: ~a~%" (condition-message c
> (canonicalize-path "/doesntexist"))
> message: No such file or directory
> $11 = #t
> scheme@(guile-user)> 
> --8<---cut here---end--->8---
> 
> -- 
> Ricardo

What do you think of using (ice-9 match) to make a universal throwage-formatter,
with the idea of making readable top level code for how exceptions become 
messages on screen?

I started a hack to explore the (throw 'whatever any ...) space, beginning like

--8<---cut here---start->8---
(use-modules (ice-9 match))
(define (make-exception-message key rest)
  (begin
(let*((l (cons key rest)))
  (match l
 (('system-error subr message args data ...)
  ;; e.g. thrown with key 'system-error: ("open-fdes" "~A" ("No 
such file or directory") (2))
  (format #f (string-append "match-1: subr ~s threw '~s " message " 
sterror: ~s") subr key args (strerror (car (car data)

 (('signal   any ...)
  ;; not yet implemented
  (format #f "match-2:  any: ~s" any))
 
 (('keyword-argument-error subr message args data)
  ;; with-crossed-fingers...
  (format #f (string-append "match-3: subr ~s threw '~s " message) 
subr key args))
;; FIXME: string-append formats NAGI not a good idea, see a fix example below
  
 (('wrong-type-arg subr message (args ...) (data ...))
  ;; E.g.,  thrown with key 'wrong-type-arg: ("sqrt" "Wrong type 
argument in position ~A: ~S" (1 x) (x))
  (format #f "match-4: subr ~s threw '~s: ~s" subr key (format #f 
message args data)))
 
 (('out-of-range subr message (lo hi bad1) ((bad2)))
  ;; E.g., thrown with key 'out-of-range: (#f "Value out of range 
~S to ~S: ~S" (0 3 4) (4))
  (format #f "match-5: (internal) threw '~s: ~s" 'out-of-range 
(format #f message lo hi bad2)))

 (('unbound-variable #f message args data)
  ;; E.g. thrown with key 'unbound-variable: (#f "Unbound variable: 
~S" (foo) #f)
  (format #f (string-append "match-6: subr ~s threw '~s " message) 
#f key args)) ;; data))
;; FIXME: string-append formats NAGI
[...]
--8<---cut here---end--->8---

I made a guile hack that I could call from bash so I could type a line and 
(eval-string it) as a source of exceptions,
and found that I could get secondary exceptions from make-exception-message, so 
I wrapped that with a (catch ...)
something like

--8<---cut here---start->8---
(define verbose-exception-handler (lambda (k . rest )
  (begin
(format #t "thrown with key '~s: ~s\n" k rest)
(format #t "catch return=~a\n" (catch #t
(lambda () (make-exception-message  k  
rest))
(lambda (inner-key . inner-rest)
  (format #t "caught by inner handler: 
thrown with key '~s: ~s\n" inner-key inner-rest
;; (format #t "thrown with key '~s: ~s\n" k rest)
(newline)
 [...]
--8<---cut here---end--->8---

And using that like

--8<---cut here---start->8---
(define (wrap-main args)
  (begin
(display (catch #t
(lambda () (apply main-defaults args))
verbose-exception-handler

--8<---cut 

bug#41956: [PATCH] ice-9: exceptions: Properly format the error message.

2020-06-25 Thread Ricardo Wurmus


Hi Maxim,

here’s what I did in the REPL:

--8<---cut here---start->8---
scheme@(guile-user)> ,m (ice-9 exceptions)
scheme@(ice-9 exceptions)> (define (my/guile-system-error-converter key args)
  (apply (case-lambda
  ((subr msg-args msg errno . rest)
   ;; XXX TODO we should return a more specific error
   ;; (usually an I/O error) as expected by R6RS programs.
   ;; Unfortunately this often requires the 'filename' (or
   ;; other?) which is not currently provided by the native
   ;; Guile exceptions.
   (make-exception
(make-external-error)
(make-exception-with-origin subr)
(apply make-exception-with-message msg)
(make-exception-with-irritants msg-args)))
  (_ (guile-external-error-converter key args)))
 args))
scheme@(ice-9 exceptions)> (set! guile-exception-converters (acons 
'system-error my/guile-system-error-converter guile-exception-converters))
scheme@(ice-9 exceptions)> ,m (guile-user)
scheme@(guile-user)> (guard (c ((message-condition? c)
  (format #t "message: ~a~%" (condition-message c
  (canonicalize-path "/doesntexist"))
message: No such file or directory
$11 = #t
scheme@(guile-user)> 
--8<---cut here---end--->8---

-- 
Ricardo