summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2021-09-07 21:19:11 +0200
committerLudovic Courtès <ludo@gnu.org>2021-09-13 12:31:10 +0200
commit8531997d2a1e10d574a6e9ab70bc86ade6af4733 (patch)
tree5c1cdaff85b4cba539fe84ba5c3c87fb9217408e
parent10c981b1355df694b277a812cd8beb7cd60d1ea6 (diff)
packages: Add 'package-definition-location'.
Suggested by Maxime Devos <maximedevos@telenet.be>. * guix/packages.scm (current-definition-location): New syntax parameter. (define-public*): New macro. (<package>)[definition-location]: New field. (package-definition-location): New procedure. * tests/packages.scm ("package-definition-location"): New test.
-rw-r--r--guix/packages.scm48
-rw-r--r--tests/packages.scm11
2 files changed, 58 insertions, 1 deletions
diff --git a/guix/packages.scm b/guix/packages.scm
index 01de50ebd73..ad7937b4fb7 100644
--- a/guix/packages.scm
+++ b/guix/packages.scm
@@ -52,6 +52,7 @@
52 #:re-export (%current-system 52 #:re-export (%current-system
53 %current-target-system 53 %current-target-system
54 search-path-specification) ;for convenience 54 search-path-specification) ;for convenience
55 #:replace ((define-public* . define-public))
55 #:export (content-hash 56 #:export (content-hash
56 content-hash? 57 content-hash?
57 content-hash-algorithm 58 content-hash-algorithm
@@ -99,6 +100,7 @@
99 package-supported-systems 100 package-supported-systems
100 package-properties 101 package-properties
101 package-location 102 package-location
103 package-definition-location
102 hidden-package 104 hidden-package
103 hidden-package? 105 hidden-package?
104 package-superseded 106 package-superseded
@@ -385,6 +387,35 @@ one-indexed line numbers."
385 (location-line loc) 387 (location-line loc)
386 (location-column loc))))) 388 (location-column loc)))))
387 389
390(define-syntax-parameter current-definition-location
391 ;; Location of the encompassing 'define-public'.
392 (const #f))
393
394(define-syntax define-public*
395 (lambda (s)
396 "Like 'define-public' but set 'current-definition-location' for the
397lexical scope of its body."
398 (define location
399 (match (syntax-source s)
400 (#f #f)
401 (properties
402 (let ((line (assq-ref properties 'line))
403 (column (assq-ref properties 'column)))
404 ;; Don't repeat the file name since it's redundant with 'location'.
405 ;; Encode the whole thing so that it fits in a fixnum on 32-bit
406 ;; platforms, which leaves us 29 bits: 7 bits for COLUMN (which is
407 ;; almost always zero), and 22 bits for LINE.
408 (and line column
409 (logior (ash (logand #x7f column) 22)
410 (logand (- (expt 2 22) 1) (+ 1 line))))))))
411
412 (syntax-case s ()
413 ((_ prototype body ...)
414 #`(define-public prototype
415 (syntax-parameterize ((current-definition-location
416 (lambda (s) #,location)))
417 body ...))))))
418
388;; A package. 419;; A package.
389(define-record-type* <package> 420(define-record-type* <package>
390 package make-package 421 package make-package
@@ -430,7 +461,10 @@ one-indexed line numbers."
430 461
431 (location package-location-vector 462 (location package-location-vector
432 (default (current-location-vector)) 463 (default (current-location-vector))
433 (innate) (sanitize sanitize-location))) 464 (innate) (sanitize sanitize-location))
465 (definition-location package-definition-location-code
466 (default (current-definition-location))
467 (innate)))
434 468
435(set-record-type-printer! <package> 469(set-record-type-printer! <package>
436 (lambda (package port) 470 (lambda (package port)
@@ -455,6 +489,18 @@ it is not known."
455 (#f #f) 489 (#f #f)
456 (#(file line column) (location file line column)))) 490 (#(file line column) (location file line column))))
457 491
492(define (package-definition-location package)
493 "Like 'package-location', but return the location of the definition
494itself--i.e., that of the enclosing 'define-public' form, if any, or #f."
495 (match (package-definition-location-code package)
496 (#f #f)
497 (code
498 (let ((column (bit-extract code 22 29))
499 (line (bit-extract code 0 21)))
500 (match (package-location-vector package)
501 (#f #f)
502 (#(file _ _) (location file line column)))))))
503
458(define-syntax-rule (package/inherit p overrides ...) 504(define-syntax-rule (package/inherit p overrides ...)
459 "Like (package (inherit P) OVERRIDES ...), except that the same 505 "Like (package (inherit P) OVERRIDES ...), except that the same
460transformation is done to the package P's replacement, if any. P must be a bare 506transformation is done to the package P's replacement, if any. P must be a bare
diff --git a/tests/packages.scm b/tests/packages.scm
index 2a290bc3539..3756877270e 100644
--- a/tests/packages.scm
+++ b/tests/packages.scm
@@ -236,6 +236,17 @@
236 (eq? item new))) 236 (eq? item new)))
237 (null? (manifest-transaction-remove tx))))))) 237 (null? (manifest-transaction-remove tx)))))))
238 238
239(test-assert "package-definition-location"
240 (let ((location (package-location hello))
241 (definition (package-definition-location hello)))
242 ;; Check for the usual layout of (define-public hello (package ...)).
243 (and (string=? (location-file location)
244 (location-file definition))
245 (= 0 (location-column definition))
246 (= 2 (location-column location))
247 (= (location-line definition)
248 (- (location-line location) 1)))))
249
239(test-assert "package-field-location" 250(test-assert "package-field-location"
240 (let () 251 (let ()
241 (define (goto port line column) 252 (define (goto port line column)