@mflatt I think I found a bug in syntax-binding sets:
#lang racket/load
(module m1 racket
(provide m1)
(define-syntax (m1 stx)
#'(begin
(provide m2)
(define-syntax (m2 stx)
#'42))))
(module m2 racket
(require 'm1)
(m1))
(module m3 racket
(require 'm2)
(define-for-syntax this-module
(variable-reference->module-path-index (#%variable-reference)))
(define-for-syntax (forge-identifier modpath sym)
(syntax-binding-set->syntax
(syntax-binding-set-extend (syntax-binding-set) sym 0 modpath)
sym))
(define-syntax (m stx)
(forge-identifier (module-path-index-join ''m2 #f) 'm2))
(m))
(module m3-good racket
(require 'm2)
(m2))
(require 'm3)
;(require 'm3-good)
Namely, they seem to fail when trying to refer to macro introduced macros.
(If, for example, I alter it to refer to m1
instead of m2
, it works.
For reference, the error you get is:
. instantiate-linklet: mismatch;
reference to a variable that is uninitialized;
possibly, bytecode file needs re-compile because dependencies changed
name: m2
exporting instance: 'm2
importing instance: 'm3
@leif A macro-introduced binding (define m ...)
or (define-syntax m ....)
will not have the symbolic name 'm
. Note that (require 'm2)
(println (identifier-binding #'m2))
prints 'm.1
as the second item of the list, where the .1
has been added to help highlight that it’s not just 'm
. It’s an unreadable (but interned) symbol.
The symbolic name 'm
is reserved for a non-macro-introduced definition. Each macro-introduced definition in a module where the syntactic form has a symbol 'm
will bind to a distinct unreadable symbol 'm.1
, 'm.2
, etc.
@mflatt So then why doesn’t the .1
show up when I do (module->exports "m2")
?
module->exports
shows you the symbolic export name, as opposed to the symbolic definition name. It’s essentially the same reason that 'm1
shows up as the fourth result from identifier-binding
. If you change (provide m2)
to (provide (rename-out [m2 other])
, then 'other
will show up in module->exports
or as the fourth result from (identifier-binding #'other)
, but 'm2.1
will still be the second result from (identifier-binding #'other)
.
I see. Which is what makes this work:
#lang racket/load
(module A racket
(define x 5)
(provide (rename-out [x y])))
(module B racket
(define-for-syntax this-module
(variable-reference->module-path-index (#%variable-reference)))
(define-for-syntax (forge-identifier modpath sym)
(syntax-binding-set->syntax
(syntax-binding-set-extend (syntax-binding-set) sym 0 modpath)
sym))
(require 'A)
(define-syntax (m stx)
(forge-identifier (module-path-index-join ''A #f) 'x))
(m))
(require 'B)
So, is there any way I can change syntax-binding-set
s to respect export name rather than the definition name?
Which is (as I understand it) how syntax-local-lift-require
works?
Hi attempts to access the 64bit macos build at https://www.cs.utah.edu/plt/snapshots/current/installers/racket-7.5.0.4-x86_64-macosx.dmg returns ‘Forbidden’
I think an rsync got interrupted, and then the build didn’t complete for a couple of days due to web-server
changes. It should recover tomorrow, and I’ll adjust the script to try rsync
a few times to handle failures.
Not syntax-local-lift-require
because you don’t want to create a module dependency, right? The only idea I have right now is expand
, maybe something like (syntax-case (expand `(module m racket/kernel (#%require 'm2) (quote-syntax m2))) ()
[(mod _ _ (mod-beg _ (q-s id))) (identifier-binding #'id)])
but probably with syntax-shift-phase-level
.
It would make sense for a binding set to support a require
-like operation, I think.
@mflatt Okay, it looks like I can use the #:source-symbol
and #:nominal-source-symbol
arguments to construct a binding set based on the provide binding rather than the define one, such as in:
(identifier-binding
(syntax-binding-set->syntax
(syntax-binding-set-extend (syntax-binding-set) 'renamed 0
(module-path-index-join "a1.rkt" (variable-reference->module-path-index
(#%variable-reference)))
#:source-symbol 'def
#:nominal-symbol 'renamed)
'renamed))
But that leads to this question:
Is it possible to find the definition binding from the provided one?
Ideally without needing to visit the defining module in the first place. At least not until run time.
I don’t think that information is currently available. It could be provided by something like module->exports
, but module->exports
doesn’t.
I see. It seems like that’s needed to forge identifiers from other modules.
Oh, I just noticed that you replied to my previous comment (from a few hours back)
It does look like your snippet might work, although it does require a visit to the module before hand.
(Which is a problem in the case of the ‘self’ module, if that makes any sense?)
Probably the right solution is to expand the result of module->exports
to have the relevant symbol.
On the subject of module->exports
, I find it really, really difficult to understand what data it’s returning, since it’s a bunch of nested lists of lists with irregular shapes. Does anyone else have that problem?
@mflatt Makes sense. Although IIRC, module->export
only works if the module is already loaded into the current namespace, yes?
@notjack Its just two lists of phase-identifier pairs.
The first list is provided ones, and IIRC, the second being reprovided ones.
They’re not phase-identifier pairs, they’re phase-list pairs
And the first list is exported variables, the second is exported syntax
My point is, it’s hard to keep straight :p
raco test
sets current-directory
to the test file’s directory, as documented. This is understandable, but sometimes I really want to know what current directory I am in. For instance, raco test ++args ./foo/bar.txt sub/main.rkt
specifies ./foo/bar.txt
relative to .
, not sub
. Is there a way to retrieve the actual current directory?