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

Re: Error context info



I rewrote the program (below) in one way to produce better error
messages by manually propogating source information from the original
program thru the validate macro to the validate-b macro. Another
approach is to combine all of the checking into the `validate' macro
itself and then the more natural approach, with nested syntax-cases,
would probably work out and you wouldn't have to propogate that
information around manually.

Also, FWIW, often one does want the source location that MzScheme
provides in this case, since the `validate' macro was passing along
arguments to other macros without checking that they met the other
macro's specs. If, for example, the `validate' and `validate-b' were
written by two different programmers, the error message that mz
returned might have been considered correct.

Hope that helps.

Robby

(define-struct a (b-exprs))
(define-struct b (c-exprs))
(define-struct c (c-field))

(define-syntax validate
  (lambda (stx)
    (syntax-case stx (a)
      [(_ (a x ...)) 
       (with-syntax ([(lst-args ...)
                      (map 
                       (lambda (x-stx)
                         (datum->syntax-object
                          stx
                          `(validate-b ,x-stx))
                         x-stx)
                       (syntax->list (syntax (x ...))))])
         (syntax (make-a (list lst-args ...))))]))) ; <-- expression on this line is highlighted

(define-syntax validate-b
  (lambda (stx)
    (syntax-case stx (b)
      [(_ (b x ...)) (syntax (make-b (list (validate-c x) ...)))])))

(define-syntax validate-c
  (lambda (stx)
    (syntax-case stx (c)
      [(_ (c c-field))
       (if (string? (syntax-object->datum (syntax c-field)))
           (syntax (make-c c-field))
           (raise-syntax-error 
            #f
            (format "expected string, given: ~a ~a" c-f (syntax-line (syntax c-field)))
            stx))])))

(validate (a (b (c "foo")
                (c "bar")) ;<--- misplaced paren here causes error
                (c "baz")
             (b (c "this")
                (c "is")
                (c "a")
                (c "test"))))