9 Source Locations
There are two libraries in this collection for dealing with source locations; one for manipulating representations of them, and the other for quoting the location of a particular piece of source code.
9.1 Representations
(require syntax/srcloc) | package: base |
This module defines utilities for manipulating representations of source locations, including both srcloc structures and all the values accepted by datum->syntax’s third argument: syntax objects, lists, vectors, and #f.
procedure
(source-location? x) → boolean?
x : any/c
procedure
x : any/c
procedure
x : any/c
> (source-location? #f) #t
> (source-location? #'here) #t
> (source-location? (make-srcloc 'here 1 0 1 0)) #t
> (source-location? (make-srcloc 'bad 1 #f 1 0)) #f
> (source-location? (list 'here 1 0 1 0)) #t
> (source-location? (list* 'bad 1 0 1 0 'tail)) #f
> (source-location? (vector 'here 1 0 1 0)) #t
> (source-location? (vector 'bad 0 0 0 0)) #f
procedure
(check-source-location! name x) → void?
name : symbol? x : any/c
> (check-source-location! 'this-example #f) > (check-source-location! 'this-example #'here) > (check-source-location! 'this-example (make-srcloc 'here 1 0 1 0)) > (check-source-location! 'this-example (make-srcloc 'bad 1 #f 1 0)) this-example: expected a source location with line number
and column number both numeric or both #f; got 1 and #f
respectively: (srcloc 'bad 1 #f 1 0)
> (check-source-location! 'this-example (list 'here 1 0 1 0)) > (check-source-location! 'this-example (list* 'bad 1 0 1 0 'tail)) this-example: expected a source location (a list of 5
elements); got an improper list: '(bad 1 0 1 0 . tail)
> (check-source-location! 'this-example (vector 'here 1 0 1 0)) > (check-source-location! 'this-example (vector 'bad 0 0 0 0)) this-example: expected a source location with a positive
line number or #f (second element); got line number 0:
'#(bad 0 0 0 0)
procedure
(build-source-location loc ...) → srcloc?
loc : source-location?
procedure
(build-source-location-list loc ...) → source-location-list?
loc : source-location?
procedure
(build-source-location-vector loc ...) → source-location-vector?
loc : source-location?
procedure
(build-source-location-syntax loc ...) → syntax?
loc : source-location?
> (build-source-location) (srcloc #f #f #f #f #f)
> (build-source-location-list) '(#f #f #f #f #f)
> (build-source-location-vector) '#(#f #f #f #f #f)
> (build-source-location-syntax) #<syntax ()>
> (build-source-location #f) (srcloc #f #f #f #f #f)
> (build-source-location-list #f) '(#f #f #f #f #f)
> (build-source-location-vector #f) '#(#f #f #f #f #f)
> (build-source-location-syntax #f) #<syntax ()>
> (build-source-location (list 'here 1 2 3 4)) (srcloc 'here 1 2 3 4)
> (build-source-location-list (make-srcloc 'here 1 2 3 4)) '(here 1 2 3 4)
> (build-source-location-vector (make-srcloc 'here 1 2 3 4)) '#(here 1 2 3 4)
> (build-source-location-syntax (make-srcloc 'here 1 2 3 4)) #<syntax:here:1:2 ()>
> (build-source-location (list 'here 1 2 3 4) (vector 'here 5 6 7 8)) (srcloc 'here 1 2 3 12)
> (build-source-location-list (make-srcloc 'here 1 2 3 4) (vector 'here 5 6 7 8)) '(here 1 2 3 12)
> (build-source-location-vector (make-srcloc 'here 1 2 3 4) (vector 'here 5 6 7 8)) '#(here 1 2 3 12)
> (build-source-location-syntax (make-srcloc 'here 1 2 3 4) (vector 'here 5 6 7 8)) #<syntax:here:1:2 ()>
> (build-source-location (list 'here 1 2 3 4) (vector 'there 5 6 7 8)) (srcloc #f #f #f #f #f)
> (build-source-location-list (make-srcloc 'here 1 2 3 4) (vector 'there 5 6 7 8)) '(#f #f #f #f #f)
> (build-source-location-vector (make-srcloc 'here 1 2 3 4) (vector 'there 5 6 7 8)) '#(#f #f #f #f #f)
> (build-source-location-syntax (make-srcloc 'here 1 2 3 4) (vector 'there 5 6 7 8)) #<syntax ()>
procedure
(source-location-known? loc) → boolean?
loc : source-location?
> (source-location-known? #f) #f
> (source-location-known? (make-srcloc #f #f #f #f #f)) #f
> (source-location-known? (make-srcloc 'source 1 2 3 4)) #t
> (source-location-known? (list #f #f #f #f #f)) #f
> (source-location-known? (vector 'source #f #f #f #f)) #t
> (source-location-known? (datum->syntax #f null #f)) #f
> (source-location-known? (datum->syntax #f null (list 'source #f #f #f #f))) #t
procedure
(source-location-source loc) → any/c
loc : source-location?
procedure
(source-location-line loc) → (or/c exact-positive-integer? #f)
loc : source-location?
procedure
(source-location-column loc)
→ (or/c exact-nonnegative-integer? #f) loc : source-location?
procedure
(source-location-position loc)
→ (or/c exact-positive-integer? #f) loc : source-location?
procedure
(source-location-span loc)
→ (or/c exact-nonnegative-integer? #f) loc : source-location?
> (source-location-source #f) #f
> (source-location-line (make-srcloc 'source 1 2 3 4)) 1
> (source-location-column (list 'source 1 2 3 4)) 2
> (source-location-position (vector 'source 1 2 3 4)) 3
> (source-location-span (datum->syntax #f null (list 'source 1 2 3 4))) 4
procedure
(source-location-end loc)
→ (or/c exact-nonnegative-integer? #f) loc : source-location?
> (source-location-end #f) #f
> (source-location-end (make-srcloc 'source 1 2 3 4)) 7
> (source-location-end (list 'source 1 2 3 #f)) #f
> (source-location-end (vector 'source 1 2 #f 4)) #f
procedure
(update-source-location loc #:source source #:line line #:column column #:position position #:span span) → source-location? loc : source-location? source : any/c line : (or/c exact-nonnegative-integer? #f) column : (or/c exact-positive-integer? #f) position : (or/c exact-nonnegative-integer? #f) span : (or/c exact-positive-integer? #f)
> (update-source-location #f #:source 'here) '(here #f #f #f #f)
> (update-source-location (list 'there 1 2 3 4) #:line 20 #:column 79) '(there 20 79 3 4)
> (update-source-location (vector 'everywhere 1 2 3 4) #:position #f #:span #f) '#(everywhere 1 2 #f #f)
procedure
(source-location->string loc) → string?
loc : source-location?
procedure
(source-location->prefix loc) → string?
loc : source-location?
> (source-location->string (make-srcloc 'here 1 2 3 4)) "here:1.2"
> (source-location->string (make-srcloc 'here #f #f 3 4)) "here::3-7"
> (source-location->string (make-srcloc 'here #f #f #f #f)) "here"
> (source-location->string (make-srcloc #f 1 2 3 4)) ":1.2"
> (source-location->string (make-srcloc #f #f #f 3 4)) "::3-7"
> (source-location->string (make-srcloc #f #f #f #f #f)) ""
> (source-location->prefix (make-srcloc 'here 1 2 3 4)) "here:1.2: "
> (source-location->prefix (make-srcloc 'here #f #f 3 4)) "here::3-7: "
> (source-location->prefix (make-srcloc 'here #f #f #f #f)) "here: "
> (source-location->prefix (make-srcloc #f 1 2 3 4)) ":1.2: "
> (source-location->prefix (make-srcloc #f #f #f 3 4)) "::3-7: "
> (source-location->prefix (make-srcloc #f #f #f #f #f)) ""
9.2 Source Location Utilities
(require syntax/location) | package: base |
procedure
(syntax-source-directory stx) → (or/c path? #f)
stx : syntax?
procedure
(syntax-source-file-name stx) → (or/c path? #f)
stx : syntax?
(define loc (list (build-path "/tmp" "dir" "somewhere.rkt") #f #f #f #f))
(define stx1 (datum->syntax #f 'somewhere loc)) > (syntax-source-directory stx1) #<path:/tmp/dir/>
> (syntax-source-file-name stx1) #<path:somewhere.rkt>
(define stx2 (datum->syntax #f 'nowhere #f)) > (syntax-source-directory stx2) #f
> (syntax-source-directory stx2) #f
Added in version 6.3 of package base.
9.2.1 Quoting
The following macros evaluate to various aspects of their own source location.
Note: The examples below illustrate the use of these macros and the representation of their output. However, due to the mechanism by which they are generated, each example is considered a single character and thus does not have realistic line, column, and character positions.
Furthermore, the examples illustrate the use of source location quoting inside macros, and the difference between quoting the source location of the macro definition itself and quoting the source location of the macro’s arguments.
syntax
(quote-srcloc form) (quote-srcloc form #:module-source expr)
> (quote-srcloc) (srcloc 'eval 2 0 2 1)
> (define-syntax (not-here stx) #'(quote-srcloc)) > (not-here) (srcloc 'eval 3 0 3 1)
> (not-here) (srcloc 'eval 3 0 3 1)
> (define-syntax (here stx) #`(quote-srcloc #,stx)) > (here) (srcloc 'eval 7 0 7 1)
> (here) (srcloc 'eval 8 0 8 1)
syntax
(quote-source-file form)
syntax
(quote-line-number form)
syntax
(quote-column-number form)
syntax
(quote-character-position form)
syntax
(quote-character-span form)
You can achieve an effect similar to __FILE__ from Perl or Ruby and __file__ from Python by using quote-source-file.
Quote various fields of the source location of form, or of the whole macro application if no form is given.
> (list (quote-source-file) (quote-line-number) (quote-column-number) (quote-character-position) (quote-character-span)) '(eval 2 0 2 1)
> (define-syntax (not-here stx) #'(list (quote-source-file) (quote-line-number) (quote-column-number) (quote-character-position) (quote-character-span))) > (not-here) '(eval 3 0 3 1)
> (not-here) '(eval 3 0 3 1)
> (define-syntax (here stx) #`(list (quote-source-file #,stx) (quote-line-number #,stx) (quote-column-number #,stx) (quote-character-position #,stx) (quote-character-span #,stx))) > (here) '(eval 7 0 7 1)
> (here) '(eval 8 0 8 1)
syntax
(quote-srcloc-string form)
syntax
(quote-srcloc-prefix form)
> (list (quote-srcloc-string) (quote-srcloc-prefix)) '("eval:2.0" "eval:2.0: ")
> (define-syntax (not-here stx) #'(list (quote-srcloc-string) (quote-srcloc-prefix))) > (not-here) '("eval:3.0" "eval:3.0: ")
> (not-here) '("eval:3.0" "eval:3.0: ")
> (define-syntax (here stx) #`(list (quote-srcloc-string #,stx) (quote-srcloc-prefix #,stx))) > (here) '("eval:7.0" "eval:7.0: ")
> (here) '("eval:8.0" "eval:8.0: ")
syntax
(quote-module-name submod-path-element ...)
Returns a path, symbol, list, or 'top-level, where 'top-level is produced when used outside of a module. A list corresponds to a submodule in the same format as the result of variable-reference->module-name. Any given submod-path-elements (as in a submod form) are added to form a result submodule path.
To produce a name suitable for use in printed messages, apply path->relative-string/library when the result is a path.
> (module A racket (require syntax/location) (define-syntax-rule (name) (quote-module-name)) (define a-name (name)) (module+ C (require syntax/location) (define c-name (quote-module-name)) (define c-name2 (quote-module-name "..")) (provide c-name c-name2)) (provide (all-defined-out))) > (require 'A) > a-name 'A
> (require (submod 'A C)) > c-name '(A C)
> c-name2 '(A C "..")
> (module B racket (require syntax/location) (require 'A) (define b-name (name)) (provide (all-defined-out))) > (require 'B) > b-name 'B
> (quote-module-name) 'top-level
> (current-namespace (module->namespace ''A)) > (quote-module-name) 'A
syntax
(quote-module-path submod-path-element ...)
Builds the result using quote, a path, submod, or 'top-level, where 'top-level is produced when used outside of a module. Any given submod-path-elements (as in a submod form) are added to form a result submodule path.
> (module A racket (require syntax/location) (define-syntax-rule (path) (quote-module-path)) (define a-path (path)) (module+ C (require syntax/location) (define c-path (quote-module-path)) (define c-path2 (quote-module-path "..")) (provide c-path c-path2)) (provide (all-defined-out))) > (require 'A) > a-path ''A
> (require (submod 'A C)) > c-path '(submod 'A C)
> c-path2 '(submod 'A C "..")
> (module B racket (require syntax/location) (require 'A) (define b-path (path)) (provide (all-defined-out))) > (require 'B) > b-path ''B
> (quote-module-path) 'top-level
> (current-namespace (module->namespace ''A)) > (quote-module-path) ''A