▼ |  | Syntax: Meta-Programming Helpers

1 | Parsing and Specifying Syntax
2 | Syntax Object Helpers
3 | Datum Pattern Matching
4 | Module-Processing Helpers
5 | Macro Transformer Helpers
6 | Reader Helpers
7 | Parsing for Bodies
8 | Unsafe for Clause Transforms
9 | Source Locations
10 | Preserving Source Locations
11 | Non-Module Compilation And Expansion
12 | Trusting Standard Recertifying Transformers
13 | Attaching Documentation to Exports
14 | Contracts for Macro Subexpressions
15 | Macro Testing
16 | Internal-Definition Context Helpers
| Index

► | 9 | Source Locations

9.1 | Representations
9.2 | Source Location Utilities

On this page:

9.1`` Representations
source-location?
source-location-list?
source-location-vector?
check-source-location!
build-source-location
build-source-location-list
build-source-location-vector
build-source-location-syntax
source-location-known?
source-location-source
source-location-line
source-location-column
source-location-position
source-location-span
source-location-end
update-source-location
source-location->string
source-location->prefix
9.2`` Source Location Utilities
syntax-source-directory
syntax-source-file-name
9.2.1`` Quoting
quote-srcloc
quote-source-file
quote-line-number
quote-column-number
quote-character-position
quote-character-span
quote-srcloc-string
quote-srcloc-prefix
quote-module-name
quote-module-path

6.8
top ← prev up next →

### 9`` Source Locations

Carl Eastlund <cce@ccs.neu.edu>

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 (source-location-list? x) → boolean?
> x : any/c
> procedure (source-location-vector? x) → boolean?
> x : any/c

These functions recognize valid source location representations. The first, source-location?, recognizes srcloc structures, syntax objects, lists, and vectors with appropriate structure, as well as #f. The latter predicates recognize only valid lists and vectors, respectively.

Examples:

> > (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

This procedure checks that its input is a valid source location. If it is, the procedure returns (void). If it is not, check-source-location! raises a detailed error message in terms of name and the problem with x.

Examples:

> > (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?

These procedures combine multiple (zero or more) source locations, merging locations within the same source and reporting #f for locations that span sources. They also convert the result to the desired representation: srcloc, list, vector, or syntax object, respectively.

Examples:

> > (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: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: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?

This predicate reports whether a given source location contains more information than simply #f.

Examples:

> > (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 orexact-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?

These accessors extract the fields of a source location.

Examples:

> > (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?

This accessor produces the end position of a source location (the sum of its position and span, if both are numbers) or #f.

Examples:

> > (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)

Produces a modified version of loc, replacing its fields with source, line, column, position, and/or span, if given.

Examples:

> > (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?

These procedures convert source locations to strings for use in error messages. The first produces a string describing the source location; the second appends ": " to the string if it is non-empty.

Examples:

> > (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?

These produce the directory and file name, respectively, of the path with which stx is associated, or #f if stx is not associated with a path.

Examples:

> (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)
> (quote-srcloc form)
> (quote-srcloc form #:module-source expr)

Quotes the source location of form as a srcloc structure, using the location of the whole (quote-srcloc) expression if no expr is given. Uses relative directories for paths found within the collections tree, the user’s collections directory, or the PLaneT cache.

Examples:

> > (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)
> (quote-source-file form)
> syntax (quote-line-number)
> (quote-line-number form)
> syntax (quote-column-number)
> (quote-column-number form)
> syntax (quote-character-position)
> (quote-character-position form)
> syntax (quote-character-span)
> (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.

Examples:

> > (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)
> (quote-srcloc-string form)
> syntax (quote-srcloc-prefix)
> (quote-srcloc-prefix form)

Quote the result of source-location->string or source-location->prefix, respectively, applied to the source location of form, or of the whole macro application if no form is given.

Examples:

> > (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 ...)

Quotes the name of the module in a form suitable for printing, but not necessarily as a valid module path. See quote-module-path for constructing quoted module paths.

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.

Examples:

> > (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 ...)

Quotes the name of the module in which the form is compiled. When possible, the result is a valid module path suitable for use by dynamic-require and similar functions.

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.

Examples:

> > (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

top ← prev up next →