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

DrScheme version with source location tracking

This page is part of the web mail archives of SRFI 72 from before July 7th, 2015. The new archives for SRFI 72 contain all messages, not just those from before July 7th, 2015.

As proof of concept, I have integrated the macro system
of this SRFI with the MzScheme source location tracking mechanism.

Examples can now be run in DrScheme 299.100 and both runtime and syntax
errors will be correctly highlighted.  The implementation is at:


The integration works by replacing current-eval and the native expansion mechanism with that of the current SRFI, which harvests the native source locations from the input and keeps track of these in a weak hashtable. This is done for compound syntax objects only. Errors in atoms are referred to the nearest enclosing expression. In most examples, errors are pinpointed with great accuracy. The implementation of the source tracking mechanism was really simple.

A couple of examples from the file simple-location-tests.scm
at the above link:

In the following, the subexpression (2 3) will be highlighted:

(cons 1 (

In the following, a runtime error will cause (set ,y t) to be

(let-syntax ((main (lambda (form)

                     (define (make-swap x y)
                        (let ((t ,x))
                          (set! ,x ,y)
                          (set ,y t))))

                      (let ((s 1)
                            (t 2))
                        ,(make-swap (syntax s) (syntax t))
                        (list s t))))))

In the following, a syntax error will highlight the inner let-expression:

(let ((a 1))
  (let ((b 3))
    (define a 1)
    (let ((temp 1)
          (temp 2))

Finally, given the following definition for case:

(define-syntax case
  (lambda (x)
    (syntax-case x ()
      ((_ e c1 c2 ...)
        (let ((t e))
          ,(let f ((c1 (syntax c1)) (cmore (syntax (c2 ...))))
             (if (null? cmore)
                 (syntax-case c1 (else)
                   ((else e1 e2 ...)    (syntax (beginn e1 e2 ...)))
                   (((k ...) e1 e2 ...) (syntax (if (memv t '(k ...))
                                                    (begin e1 e2 ...)))))
                 (syntax-case c1 ()
                   (((k ...) e1 e2 ...)
                     (if (memv t '(k ...))
                         (begin e1 e2 ...)
                         ,(f (car cmore) (cdr cmore))))))))))))))

the syntax error in the following will highlight the case expression:

(let ((x 1))
  (let ((y 2))
    (case 'a
      ((x y) 'no)
      (z u 'yes))))

While a runtime error in the following will highlight the error
(beginn e1 e2 ...) in the macro above:

(case 'a
  ((b c) 'd)
  (else e))