Why can this program not find its own macro call site?

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.

  1. It must be saved to disk
  2. 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 .

The position information does not use the same units in each control path. Run this program, then run it again after changing the lambda characters to just dashes (or some other ASCII-compatible character)

(module anon racket/base
  ;λλλ
  (require (for-syntax racket/base))  
  (define-syntax (beacon stx)
    (displayln (syntax-position stx))
    #`(beacon-from-file #,(syntax-source stx)))
  (define (beacon-from-file path)
    (call-with-input-file path
      (lambda (i)
        (syntax-case (read-syntax (object-name i) i) ()
          [(_ _ _ _ _ _ b)
           (displayln (syntax-position #'b))]))))
  (beacon))

With ASCII characters, the output will be 406 and 406, indicating agreement on position. With the lambdas, the output is 406 and 409.

So... my root cause is the sole λ character in the OP. Inserting a port-count-lines! seems to make both control paths count characters in syntax-position.