EDIT: After reviewing the docs, it seems that syntax-position
is one-based with respect to the code read from the file. Not sure why the syntax-position
in the macro definition appears to be zero-based. Also: edited this message to resemble separate Discord thread.
The below program has two preconditions.
- It must be saved to disk
- The user must start the process in the same directory as the saved file.
(module anon racket/base
(require (for-syntax racket/base) racket/format mzlib/etc)
(define (find-form form at)
(let/ec return
(let loop ([suspect form] [breadcrumbs null])
(if (<= (abs (- at (syntax-position suspect))) 1)
(return (reverse breadcrumbs))
(let ([e (syntax-e suspect)])
(when (list? e)
(for ([(x i) (in-indexed (in-list e))])
(loop x (cons i breadcrumbs)))))))
#f))
(define source
(call-with-input-file (this-expression-file-name)
(λ (i) (read-syntax (object-name i) i))))
(define-syntax (find-me stx)
(syntax-case stx ()
[(i x) #`(find-form source #,(syntax-position stx))]))
(let ([result (find-me 1)])
(and (list? result)
(for/fold ([x (syntax->datum source)])
([i (in-list result)])
(list-ref x i)))))
find-me
searches for its own call site. Notice my condition using abs
... The syntax-position
of the call site always differs from the read call site by exactly one. Concretely, I was expecting to use (zero? (- at (syntax-position suspect)))
, not (<= (abs (- at (syntax-position suspect))) 1)
Where does the off-by-one error come from?
There is no UTF-8 BOM. The root cause seems to be one-based positions. (displayln (syntax-position source))
prints 1
.