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

Re: Opaque syntax objects



 
 > From: Jens Axel Søgaard <jensaxel@xxxxxxxxxxxx>
 
 
 > So identifiers are represented as a special type. How about atoms?
 > Can I annotate a piece of syntax representing, say, a number?
 
 
 That is the one thing that I can see as being precluded by the current 
 specification.  They would indeed need to be wrapped to give them 
 separate identities, instead of being bare, as they currently are.  
 
 Wrapping constants would be a useful change for the next revision.  
 I think all the primitives for handling them are already there.  
 Given a piece of syntax, one can define:
 
   (constant? stx) == (and (not (pair? stx)
                           (not (vector? stx)
                           (not (identifier? stx))
                           (not (null? stx)))
 
 and one may use datum->syntax-object and syntax-object->datum to go 
 back and forth between constants and syntax representing constants.  
 
 
 > Andre wrote:
 >
 > > it is unlikely that most implementations would keep the location of the 
 > > input subnode ((i e) ...) in the result.
 > 
 > Keeping them makes it possible to give much better error messages.
 > As a quick test this:

 > (define-syntax let2
 >    (lambda (form)
 >      (syntax-case form ()
 >        ((_ ((i e) ...) e1 e2 ...)
 >         (with-syntax (((i1 . _) #'(i ...)))
 >           (display "line: ")
 >           (display (syntax-line #'i1))
 >           (display " col: ")
 >           (display (syntax-column #'i1))
 >           (newline)
 >           #'(let ((i e) ...) e1 e2 ...))))))
 > 
 > (let1 ((x 41))
 >    (+ x 1))
 > 
 > prints  "line: 19 col: 8" and evaluates to 42 in DrScheme.

  
 What I meant is that the node  ((i e) ...)
 in the result discards the original position.  
 
   (syntax-column #'((i e) ...)) ==> not the original position
 
 whereas if you had written the less natural
 
   (define-syntax let3
      (lambda (form)
         (syntax-case form ()
           ((_ bindings e1 e2 ...)
            (syntax-case bindings ()
              (((i e) ...) 
               (syntax (let bindings e1 e2 ...))))))))
               
 then the node |bindings| in the result actually retains the original source 
 position.  
 
 Writing the macro procedurally using car, cadr, ..., one is actually more
 likely to duplicate the functionality of let3 by default, for example
 
   (define-syntax (let4 bindings . body)
     (check-bindings bindings)
     (check-body body)
     (quasisyntax (let ,bindings ,@body))
 
 preserves more information than the pattern matching let2, since
 the pair |bindings| keeps its identity.  
 
 Anyway, this is not important at all.  I'm certainly not advocating against
 syntax-case, which is a really, really useful invention.  I was just noting
 that it is not necessarily superior to the procedural interface for
 accurate source tracking.  
 
 Cheers
 Andre