unofficial mirror of guix-patches@gnu.org 
 help / color / mirror / code / Atom feed
From: "Ludovic Courtès" <ludo@gnu.org>
To: Maxime Devos <maximedevos@telenet.be>
Cc: iskarian@mgsn.dev, 50286@debbugs.gnu.org
Subject: [bug#50286] [RFC PATCH] Let 'package-location' returns location of surrounding 'let'.
Date: Tue, 07 Sep 2021 21:27:35 +0200	[thread overview]
Message-ID: <875yvc4254.fsf_-_@gnu.org> (raw)
In-Reply-To: <87o89681br.fsf@gnu.org> ("Ludovic Courtès"'s message of "Mon, 06 Sep 2021 12:07:04 +0200")

[-- Attachment #1: Type: text/plain, Size: 2146 bytes --]

Hi Maxime & Sarah,

Ludovic Courtès <ludo@gnu.org> skribis:

> Hmm, thinking out loud, what about this: use the same trick as you did,
> but replace ‘define-public’ instead of ‘let’ & co., so as to be less
> intrusive.
>
>   (define-syntax-parameter current-definition-location
>     (identifier-syntax #f))
>
>   (define-syntax define-public*
>     (syntax-rules ()
>       ((_ prototype body)
>        (define-public prototype
>          (syntax-parameterize ((current-definition-location
>                                 (identifier-syntax (current-source-location))))
>            body)))))
>
> Since there’s code that assumes ‘package-location’ returns the location
> of the (package …) sexp, we could add a ‘definition-location’ field in
> <package>, defaulting to ‘current-definition-location’, or tweak
> ‘location’ to include both.

Below is an attempt at doing this.  As discussed on IRC, the first patch
switches the ‘location’ field to a more compact format that may reduce
load time by a tiny bit, though it’s hard to measure.  The second patch
introduces an extra field for the definition location; that means that
<package> records now occupy an extra word, which is not great, but
unfortunately OTOH location is slightly smaller.

Example:

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> ,use(gnu packages base)
scheme@(guile-user)> ,use(gnu packages accessibility)
scheme@(guile-user)> ,use(guix)
scheme@(guile-user)> (package-location footswitch)
$1 = #<<location> file: "gnu/packages/accessibility.scm" line: 257 column: 4>
scheme@(guile-user)> (package-definition-location footswitch)
$2 = #<<location> file: "gnu/packages/accessibility.scm" line: 254 column: 0>
scheme@(guile-user)> (package-location hello)
$3 = #<<location> file: "gnu/packages/base.scm" line: 79 column: 2>
scheme@(guile-user)> (package-definition-location hello)
$4 = #<<location> file: "gnu/packages/base.scm" line: 78 column: 0>
--8<---------------cut here---------------end--------------->8---

Thoughts?

Thanks,
Ludo’.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: the patch --]
[-- Type: text/x-patch, Size: 3116 bytes --]

From 758ca5c95b97f3fd2b08a2828e21c45a86393d59 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@gnu.org>
Date: Tue, 7 Sep 2021 18:04:21 +0200
Subject: [PATCH 1/2] packages: Store 'location' field as a literal vector.

This is slightly more efficient than storing an alist in terms of .go
file size (< 1% smaller) and load time.

* guix/packages.scm (current-location-vector): New macro.
(sanitize-location): New procedure.
(<package>)[location]: Change 'default' and add 'sanitize'.
(package-location): New procedure.
---
 guix/packages.scm | 38 ++++++++++++++++++++++++++++++++++----
 1 file changed, 34 insertions(+), 4 deletions(-)

diff --git a/guix/packages.scm b/guix/packages.scm
index c825f427d8..01de50ebd7 100644
--- a/guix/packages.scm
+++ b/guix/packages.scm
@@ -360,6 +360,30 @@ name of its URI."
   ;; <https://lists.gnu.org/archive/html/guix-devel/2017-03/msg00790.html>.
   (fold delete %supported-systems '("mips64el-linux")))
 
+(define-syntax current-location-vector
+  (lambda (s)
+    "Like 'current-source-location' but expand to a literal vector with
+one-indexed line numbers."
+    ;; Storing a literal vector in .go files is more efficient than storing an
+    ;; alist: less initialization code, fewer relocations, etc.
+    (syntax-case s ()
+      ((_)
+       (match (syntax-source s)
+         (#f #f)
+         (properties
+          (let ((file   (assq-ref properties 'filename))
+                (line   (assq-ref properties 'line))
+                (column (assq-ref properties 'column)))
+            (and file line column
+                 #`#(#,file #,(+ 1 line) #,column)))))))))
+
+(define-inlinable (sanitize-location loc)
+  ;; Convert LOC to a vector or to #f.
+  (cond ((vector? loc) loc)
+        ((not loc) loc)
+        (else (vector (location-file loc)
+                      (location-line loc)
+                      (location-column loc)))))
 
 ;; A package.
 (define-record-type* <package>
@@ -404,10 +428,9 @@ name of its URI."
 
   (properties package-properties (default '()))   ; alist for anything else
 
-  (location package-location
-            (default (and=> (current-source-location)
-                            source-properties->location))
-            (innate)))
+  (location package-location-vector
+            (default (current-location-vector))
+            (innate) (sanitize sanitize-location)))
 
 (set-record-type-printer! <package>
                           (lambda (package port)
@@ -425,6 +448,13 @@ name of its URI."
                                                        package)
                                                       16)))))
 
+(define (package-location package)
+  "Return the source code location of PACKAGE as a <location> record, or #f if
+it is not known."
+  (match (package-location-vector package)
+    (#f #f)
+    (#(file line column) (location file line column))))
+
 (define-syntax-rule (package/inherit p overrides ...)
   "Like (package (inherit P) OVERRIDES ...), except that the same
 transformation is done to the package P's replacement, if any.  P must be a bare
-- 
2.33.0


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: the second one --]
[-- Type: text/x-patch, Size: 4552 bytes --]

From bc2d7144bb9ef0ea74f9ef5922d568291818de32 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@gnu.org>
Date: Tue, 7 Sep 2021 21:19:11 +0200
Subject: [PATCH 2/2] packages: Add 'package-definition-location'.

Suggested by Maxime Devos <maximedevos@telenet.be>.

* guix/packages.scm (current-definition-location-vector): 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.
---
 guix/packages.scm  | 42 +++++++++++++++++++++++++++++++++++++++++-
 tests/packages.scm | 11 +++++++++++
 2 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/guix/packages.scm b/guix/packages.scm
index 01de50ebd7..2f70ec9c64 100644
--- a/guix/packages.scm
+++ b/guix/packages.scm
@@ -52,6 +52,7 @@
   #:re-export (%current-system
                %current-target-system
                search-path-specification)         ;for convenience
+  #:replace ((define-public* . define-public))
   #:export (content-hash
             content-hash?
             content-hash-algorithm
@@ -99,6 +100,7 @@
             package-supported-systems
             package-properties
             package-location
+            package-definition-location
             hidden-package
             hidden-package?
             package-superseded
@@ -385,6 +387,31 @@ one-indexed line numbers."
                       (location-line loc)
                       (location-column loc)))))
 
+(define-syntax-parameter current-definition-location-vector
+  ;; Location of the encompassing 'define-public'.
+  (const #f))
+
+(define-syntax define-public*
+  (lambda (s)
+    "Like 'define-public' but set 'current-definition-location' for the
+lexical scope of its body."
+    (define location
+      (match (syntax-source s)
+        (#f #f)
+        (properties
+         (let ((line   (assq-ref properties 'line))
+               (column (assq-ref properties 'column)))
+           ;; Don't repeat the file name since it's redundant with 'location'.
+           (and line column
+                #`#(#,(+ 1 line) #,column))))))
+
+    (syntax-case s ()
+      ((_ prototype body ...)
+       #`(define-public prototype
+           (syntax-parameterize ((current-definition-location-vector
+                                  (lambda (s) #,location)))
+             body ...))))))
+
 ;; A package.
 (define-record-type* <package>
   package make-package
@@ -430,7 +457,10 @@ one-indexed line numbers."
 
   (location package-location-vector
             (default (current-location-vector))
-            (innate) (sanitize sanitize-location)))
+            (innate) (sanitize sanitize-location))
+  (definition-location package-definition-location-vector
+                       (default (current-definition-location-vector))
+                       (innate)))
 
 (set-record-type-printer! <package>
                           (lambda (package port)
@@ -455,6 +485,16 @@ it is not known."
     (#f #f)
     (#(file line column) (location file line column))))
 
+(define (package-definition-location package)
+  "Like 'package-location', but return the location of the definition
+itself--i.e., that of the enclosing 'define-public' form, if any, or #f."
+  (match (package-definition-location-vector package)
+    (#f #f)
+    (#(line column)
+     (match (package-location-vector package)
+       (#f #f)
+       (#(file _ _) (location file line column))))))
+
 (define-syntax-rule (package/inherit p overrides ...)
   "Like (package (inherit P) OVERRIDES ...), except that the same
 transformation 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 2a290bc353..3756877270 100644
--- a/tests/packages.scm
+++ b/tests/packages.scm
@@ -236,6 +236,17 @@
                 (eq? item new)))
              (null? (manifest-transaction-remove tx)))))))
 
+(test-assert "package-definition-location"
+  (let ((location   (package-location hello))
+        (definition (package-definition-location hello)))
+    ;; Check for the usual layout of (define-public hello (package ...)).
+    (and (string=? (location-file location)
+                   (location-file definition))
+         (= 0 (location-column definition))
+         (= 2 (location-column location))
+         (= (location-line definition)
+            (- (location-line location) 1)))))
+
 (test-assert "package-field-location"
   (let ()
     (define (goto port line column)
-- 
2.33.0


  reply	other threads:[~2021-09-07 19:28 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-30 21:26 [bug#50286] [RFC PATCH] Let 'package-location' returns location of surrounding 'let' Maxime Devos
2021-09-06 10:07 ` Ludovic Courtès
2021-09-07 19:27   ` Ludovic Courtès [this message]
2021-09-07 20:15     ` Sarah Morgensen
2021-09-08 13:45       ` Ludovic Courtès
2021-09-07 20:30     ` Maxime Devos
2021-09-08 13:38       ` Ludovic Courtès
2021-09-13 10:37         ` bug#50286: " Ludovic Courtès

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://guix.gnu.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=875yvc4254.fsf_-_@gnu.org \
    --to=ludo@gnu.org \
    --cc=50286@debbugs.gnu.org \
    --cc=iskarian@mgsn.dev \
    --cc=maximedevos@telenet.be \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).