GNU bug report logs - #43025
re-export-public-interface fails on Guile 3

Previous Next

Package: guile;

Reported by: Dale Smith <dalepsmith <at> gmail.com>

Date: Mon, 24 Aug 2020 16:12:01 UTC

Severity: normal

Done: Dale Smith <dalepsmith <at> gmail.com>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 43025 in the body.
You can then email your comments to 43025 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-guile <at> gnu.org:
bug#43025; Package guile. (Mon, 24 Aug 2020 16:12:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Dale Smith <dalepsmith <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-guile <at> gnu.org. (Mon, 24 Aug 2020 16:12:01 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Dale Smith <dalepsmith <at> gmail.com>
To: bug-guile <at> gnu.org
Subject: re-export-public-interface fails on Guile 3
Date: Mon, 24 Aug 2020 12:11:37 -0400
This is actually reported by daviid on IRC.

This definition of re-export-public-interface works fine on Guile 2.x,
fails with Guile 3:
(hope this makes it through the mails cleanly)

;;;
;;; re-export-public-interface
;;;

(define-module (modules)
  #:export (re-export-public-interface))

(define-macro (re-export-public-interface . args)
  "Re-export the public interface of a module or modules. Invoked as
@code{(re-export-public-interface (mod1) (mod2)...)}."
  (if (null? args)
      '(if #f #f)
      `(begin
	 ,@(map (lambda (mod)
		  (or (list? mod)
		      (error "Invalid module specification" mod))
		  `(module-use! (module-public-interface (current-module))
				(resolve-interface ',mod)))
		args))))


;;;
;;; A module that uses the above
;;;


(define-module (a)
  #:use-module (srfi srfi-1)
  #:use-module (modules)

  #:export (map-a))


(eval-when (expand load eval)
  (re-export-public-interface (srfi srfi-1)))


(define (map-a)
  (map (lambda (item)
         (display item)
         (display " "))
    (iota 5))
  (newline)
  (values))


;;;
;;; A 3.0.4 repl session
;;;

GNU Guile 3.0.4.3-e076a5
Copyright (C) 1995-2020 Free Software Foundation, Inc.

Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.

Enter `,help' for help.
scheme@(guile-user)> (add-to-load-path "/home/david/alto/projects/g-golf/3.0")
scheme@(guile-user)> ,use (a)
;;; note: source file /home/david/alto/projects/g-golf/3.0/a.scm
;;;       newer than compiled
/home/david/.cache/guile/ccache/3.0-LE-8-4.3/usr/alto/projects/g-golf/3.0/a.scm.go
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;;       or pass the --no-auto-compile argument to disable.
;;; compiling /home/david/alto/projects/g-golf/3.0/a.scm
;;; compiled /home/david/.cache/guile/ccache/3.0-LE-8-4.3/usr/alto/projects/g-golf/3.0/a.scm.go
scheme@(guile-user)> map
WARNING: (guile-user): imported module (a) overrides core binding `map'
WARNING: (guile-user): `map' imported from both (guile) and (a)
WARNING: (guile-user): imported module (a) overrides core binding `map'
WARNING: (guile-user): `map' imported from both (guile) and (a)
;;; <unknown-location>: warning: possibly unbound variable `map'
WARNING: (guile-user): imported module (a) overrides core binding `map'
WARNING: (guile-user): `map' imported from both (guile) and (a)
WARNING: (guile-user): imported module (a) overrides core binding `map'
WARNING: (guile-user): `map' imported from both (guile) and (a)
ice-9/boot-9.scm:1670:16: In procedure raise-exception:
Unbound variable: map

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]>


;;;
;;; Just to compare, a 2.2.7 session
;;; How to achieve the same using 3.0.4 is the
;;; objective ...

Press C-c C-z to bring me back.
GNU Guile 2.2.7.2-a5875-dirty
Copyright (C) 1995-2019 Free Software Foundation, Inc.

Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.

Enter `,help' for help.
scheme@(guile-user)> (add-to-load-path "/home/david/alto/projects/g-golf/3.0")
scheme@(guile-user)> ,use (a)
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;;       or pass the --no-auto-compile argument to disable.
;;; compiling /home/david/alto/projects/g-golf/3.0/a.scm
;;; compiling /home/david/alto/projects/g-golf/3.0/modules.scm
;;; compiled /home/david/.cache/guile/ccache/2.2-LE-8-3.A/usr/alto/projects/g-golf/3.0/modules.scm.go
;;; compiled /home/david/.cache/guile/ccache/2.2-LE-8-3.A/usr/alto/projects/g-golf/3.0/a.scm.go
scheme@(guile-user)> map
$2 = #<procedure map (f l) | (f l1 l2) | (f l1 . rest)>




Information forwarded to bug-guile <at> gnu.org:
bug#43025; Package guile. (Mon, 24 Aug 2020 19:51:01 GMT) Full text and rfc822 format available.

Message #8 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Leo Prikler <leo.prikler <at> student.tugraz.at>
To: Dale Smith <dalepsmith <at> gmail.com>, bug-guile <at> gnu.org
Subject: Re: re-export-public-interface fails on Guile 3
Date: Mon, 24 Aug 2020 21:50:32 +0200
Hi Dale.

Am Montag, den 24.08.2020, 12:11 -0400 schrieb Dale Smith:
> This is actually reported by daviid on IRC.
> 
> This definition of re-export-public-interface works fine on Guile
> 2.x,
> fails with Guile 3:
> (hope this makes it through the mails cleanly)

> ;;;
> ;;; re-export-public-interface
> ;;;
> 
> [...]
I'm going to skip the specifics of the macro here, it is not needed for
an MWE.

> ;;;
> ;;; A module that uses the above
> ;;;
> 
> 
> (define-module (a)
>   #:use-module (srfi srfi-1)
>   #:use-module (modules)
> 
>   #:export (map-a))
> 
> 
> (eval-when (expand load eval)
>   (re-export-public-interface (srfi srfi-1)))
> 
> 
> (define (map-a)
>   (map (lambda (item)
>          (display item)
>          (display " "))
>     (iota 5))
>   (newline)
>   (values))
> 

For the sake of minimalism, I will shorten this to

(define-module (a))

(module-use! (module-public-interface (current-module))
             (resolve-interface '(srfi srfi-1)))

I hope you don't mind.

> [sessions]

My solution for this problem would be to build on some of the module
"intrinsics", which sadly are not all that well documented.

(define-module (a))

(let ((obs (module-obarray (resolve-interface '(srfi srfi-1))))
      (iface (module-public-interface (current-module))))
  (hash-fold
   (lambda (key value seed)
     (module-add! iface key value)
     seed)
   *unspecified*
   obs))

If you want to make this a macro, you really only need to syntax-
unquote a module into the (resolve-interface ...) portion of this
snippet.

Some sessions for reference:

GNU Guile 3.0.4
Copyright (C) 1995-2020 Free Software Foundation, Inc.

Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.

Enter `,help' for help.
scheme@(guile-user)> (add-to-load-path "/tmp")
scheme@(guile-user)> ,use (a)
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;;       or pass the --no-auto-compile argument to disable.
;;; compiling /tmp/a.scm
;;; compiled $HOME/.cache/guile/ccache/3.0-LE-8-4.3/tmp/a.scm.go
scheme@(guile-user)> map
WARNING: (guile-user): imported module (a) overrides core binding `map'
$1 = #<procedure map (f l) | (f l1 l2) | (f l1 . rest)>
scheme@(guile-user)> ,q

GNU Guile 3.0.2
Copyright (C) 1995-2020 Free Software Foundation, Inc.

Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.

Enter `,help' for help.
scheme@(guile-user)> (add-to-load-path "/tmp")
scheme@(guile-user)> ,use (a)
;;; note: source file /tmp/a.scm
;;;       newer than compiled /home/yuri/.cache/guile/ccache/3.0-LE-8-
4.2/tmp/a.scm.go
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;;       or pass the --no-auto-compile argument to disable.
;;; compiling /tmp/a.scm
;;; compiled $HOME/.cache/guile/ccache/3.0-LE-8-4.2/tmp/a.scm.go
scheme@(guile-user)> map
WARNING: (guile-user): imported module (a) overrides core binding `map'
$1 = #<procedure map (f l) | (f l1 l2) | (f l1 . rest)>
scheme@(guile-user)> ,q

GNU Guile 2.2.7
Copyright (C) 1995-2019 Free Software Foundation, Inc.

Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.

Enter `,help' for help.
scheme@(guile-user)> (add-to-load-path "/tmp")
scheme@(guile-user)> ,use (a)
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;;       or pass the --no-auto-compile argument to disable.
;;; compiling /tmp/a.scm
;;; compiled $HOME/.cache/guile/ccache/2.2-LE-8-3.A/tmp/a.scm.go
scheme@(guile-user)> map
$1 = #<procedure map (f l) | (f l1 l2) | (f l1 . rest)>
scheme@(guile-user)> ,q

Interestingly, versions newer than 3.0.2 warn about core override in
this case, as does #:re-export.  If I am not mistaken, this is the way
re-export works for variables normally.  module-use! on the other hand
does not modify the module-obarray, it instead adds the module to a
list of uses, which are handled separately in variable lookup during
`module_imported_variable`.  This C function does look up variables
exported by a module, but does not traverse module-uses recursively.  I
have no idea, how this works for 2.2.7, I only checked the Guile 3 code
here.

Regards,
Leo






Information forwarded to bug-guile <at> gnu.org:
bug#43025; Package guile. (Wed, 26 Aug 2020 16:52:01 GMT) Full text and rfc822 format available.

Message #11 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Dale Smith <dalepsmith <at> gmail.com>
To: Leo Prikler <leo.prikler <at> student.tugraz.at>
Cc: bug-guile <at> gnu.org
Subject: Re: re-export-public-interface fails on Guile 3
Date: Wed, 26 Aug 2020 12:51:18 -0400
On 8/24/20, Leo Prikler <leo.prikler <at> student.tugraz.at> wrote:
> My solution for this problem would be to build on some of the module
> "intrinsics", which sadly are not all that well documented.
>
> (define-module (a))
>
> (let ((obs (module-obarray (resolve-interface '(srfi srfi-1))))
>       (iface (module-public-interface (current-module))))
>   (hash-fold
>    (lambda (key value seed)
>      (module-add! iface key value)
>      seed)
>    *unspecified*
>    obs))
>
> If you want to make this a macro, you really only need to syntax-
> unquote a module into the (resolve-interface ...) portion of this
> snippet.

So with that in mind, how about something like this (currently no
error checking):

(define-syntax re-export-public-interface
  (syntax-rules ()
    ((_ mod ...)
     (let ((iface (module-public-interface (current-module))))
       (module-for-each
	(lambda (sym val)
	  (module-add! iface sym val)
	  (hashq-set! (module-replacements iface) sym #t))
	(resolve-interface 'mod))
       ...))))




Information forwarded to bug-guile <at> gnu.org:
bug#43025; Package guile. (Wed, 26 Aug 2020 17:07:01 GMT) Full text and rfc822 format available.

Message #14 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Leo Prikler <leo.prikler <at> student.tugraz.at>
To: Dale Smith <dalepsmith <at> gmail.com>
Cc: bug-guile <at> gnu.org
Subject: Re: re-export-public-interface fails on Guile 3
Date: Wed, 26 Aug 2020 19:06:00 +0200
Am Mittwoch, den 26.08.2020, 12:51 -0400 schrieb Dale Smith:
> On 8/24/20, Leo Prikler <leo.prikler <at> student.tugraz.at> wrote:
> > My solution for this problem would be to build on some of the
> > module
> > "intrinsics", which sadly are not all that well documented.
> > 
> > (define-module (a))
> > 
> > (let ((obs (module-obarray (resolve-interface '(srfi srfi-1))))
> >       (iface (module-public-interface (current-module))))
> >   (hash-fold
> >    (lambda (key value seed)
> >      (module-add! iface key value)
> >      seed)
> >    *unspecified*
> >    obs))
> > 
> > If you want to make this a macro, you really only need to syntax-
> > unquote a module into the (resolve-interface ...) portion of this
> > snippet.
> 
> So with that in mind, how about something like this (currently no
> error checking):
> 
> (define-syntax re-export-public-interface
>   (syntax-rules ()
>     ((_ mod ...)
>      (let ((iface (module-public-interface (current-module))))
>        (module-for-each
>         (lambda (sym val)
>           (module-add! iface sym val)
>           (hashq-set! (module-replacements iface) sym #t))
>         (resolve-interface 'mod))
>        ...))))
LGTM, but don't forget to test it ;)
Also I'd call it `re-export-public-interface!', or even `re-export-and-
replace-interface!' but that's a personal preference.  





Information forwarded to bug-guile <at> gnu.org:
bug#43025; Package guile. (Thu, 27 Aug 2020 02:22:01 GMT) Full text and rfc822 format available.

Message #17 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Dale Smith <dalepsmith <at> gmail.com>
To: Leo Prikler <leo.prikler <at> student.tugraz.at>
Cc: bug-guile <at> gnu.org
Subject: Re: re-export-public-interface fails on Guile 3
Date: Wed, 26 Aug 2020 22:21:04 -0400
This seems to  work for guile-2.2 and guile-3.
Would be nice if it checked that module names look like lists.

One step closer to g-golf working on guile-3!

(define-syntax re-export-public-interface
  (syntax-rules ()
    "Re-export the public interface of a module or modules. Invoked as
@code{(re-export-public-interface (mod1) (mod2) ...)}."
    ((_ mod mods ...)
     (let ((iface (module-public-interface (current-module))))
       (define (r-e-p-i module)
	 (cond-expand
	  (guile-3
	   (module-for-each
	    (lambda (sym val)
	      (hashq-set! (module-replacements iface) sym #t)
	      (module-add! iface sym val))
	    (resolve-interface module)))
	  (else
	   (module-use! iface (resolve-interface module)))))
       (r-e-p-i 'mod)
       (r-e-p-i 'mods)
       ...))))




Information forwarded to bug-guile <at> gnu.org:
bug#43025; Package guile. (Fri, 28 Aug 2020 00:13:02 GMT) Full text and rfc822 format available.

Message #20 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Dale Smith <dalepsmith <at> gmail.com>
To: Leo Prikler <leo.prikler <at> student.tugraz.at>
Cc: bug-guile <at> gnu.org
Subject: Re: re-export-public-interface fails on Guile 3
Date: Thu, 27 Aug 2020 20:12:35 -0400
And here has some better error handling/reporting.

(define-syntax re-export-public-interface
  (syntax-rules ()
    "Re-export the public interface of a module or modules. Invoked as
@code{(re-export-public-interface (mod1) (mod2) ...)}."
    ((_ (m0 m0* ...) (mn mn* ...) ...)
     (let ((iface (module-public-interface (current-module))))
       (define (r-e-p-i module)
	 (cond-expand
	  (guile-3
	   (module-for-each
	    (lambda (sym val)
	      (hashq-set! (module-replacements iface) sym #t)
	      (module-add! iface sym val))
	    (resolve-interface module)))
	  (else
	   (module-use! iface (resolve-interface module)))))
       (r-e-p-i '(m0 m0* ...))
       (r-e-p-i '(mn mn* ...))
       ...))
    ((_)
     (syntax-violation 're-export-public-interface
		       "must provide one or more module names"
		       '(re-export-public-interface)))
    ((_ m m* ...)
     (syntax-violation 're-export-public-interface
		       "module names must look like lists"
		       '(re-export-public-interface m m* ...)))))




Information forwarded to bug-guile <at> gnu.org:
bug#43025; Package guile. (Fri, 28 Aug 2020 19:23:02 GMT) Full text and rfc822 format available.

Message #23 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Dale Smith <dalepsmith <at> gmail.com>
To: Leo Prikler <leo.prikler <at> student.tugraz.at>
Cc: bug-guile <at> gnu.org
Subject: Re: re-export-public-interface fails on Guile 3
Date: Fri, 28 Aug 2020 15:22:17 -0400
And now using a more standard error reporting function.
I think it's done now.

(define-syntax re-export-public-interface
  (syntax-rules ()
    "Re-export the public interface of a module or modules. Invoked as
@code{(re-export-public-interface (mod1) (mod2) ...)}."
    ((_ (m0 m0* ...) (mn mn* ...) ...)
     (let ((iface (module-public-interface (current-module))))
       (define (r-e-p-i module)
	 (cond-expand
	  (guile-3
	   (module-for-each
	    (lambda (sym val)
	      (hashq-set! (module-replacements iface) sym #t)
	      (module-add! iface sym val))
	    (resolve-interface module)))
	  (else
	   (module-use! iface (resolve-interface module)))))
       (r-e-p-i '(m0 m0* ...))
       (r-e-p-i '(mn mn* ...))
       ...))
    ((_)
     (syntax-error "must provide one or more module names"))
    ((_ m m* ...)
     (syntax-error "module names must look like lists"))))




Reply sent to Dale Smith <dalepsmith <at> gmail.com>:
You have taken responsibility. (Fri, 12 Mar 2021 14:13:01 GMT) Full text and rfc822 format available.

Notification sent to Dale Smith <dalepsmith <at> gmail.com>:
bug acknowledged by developer. (Fri, 12 Mar 2021 14:13:01 GMT) Full text and rfc822 format available.

Message #28 received at 43025-close <at> debbugs.gnu.org (full text, mbox):

From: Dale Smith <dalepsmith <at> gmail.com>
To: 43025-close <at> debbugs.gnu.org
Subject: re-export-public-interface fails on Guile 3
Date: Fri, 12 Mar 2021 09:12:51 -0500
Closing this.  Please see
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=47084  instead
for a better/more accurate report.

-Dale




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Sat, 10 Apr 2021 11:24:06 GMT) Full text and rfc822 format available.

This bug report was last modified 3 years and 29 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.