Skip to content

Commit bd32cf1

Browse files
committed
Allow GlobalRef and module qualified names in macro definitions (#53535)
The following is currently an error: ``` julia> module MyMacroModule macro mymacro end end Main.MyMacroModule julia> macro MyMacroModule.mymacro() 1 end ERROR: syntax: invalid macro definition around REPL[2]:1 Stacktrace: [1] top-level scope @ REPL[2]:1 ``` Discussing with Jeff, we didn't think there was any good reason not to allow this, just a missing case in lowering. It's probably not particularly useful (unlike the corresponding case for functions that is used all the time), but it came up in writing a test case for #53515.
1 parent 558f3bd commit bd32cf1

File tree

3 files changed

+30
-6
lines changed

3 files changed

+30
-6
lines changed

src/julia-parser.scm

+10-2
Original file line numberDiff line numberDiff line change
@@ -2610,15 +2610,23 @@
26102610

26112611
(define (valid-modref? e)
26122612
(and (length= e 3) (eq? (car e) '|.|) (pair? (caddr e))
2613-
(eq? (car (caddr e)) 'quote) (symbol? (cadr (caddr e)))
2613+
(or (eq? (car (caddr e)) 'quote)
2614+
(eq? (car (caddr e)) 'inert))
2615+
(symbol? (cadr (caddr e)))
26142616
(or (symbol? (cadr e))
26152617
(valid-modref? (cadr e)))))
26162618

26172619
(define (macroify-name e . suffixes)
26182620
(cond ((symbol? e) (symbol (apply string #\@ e suffixes)))
2621+
((and (pair? e) (eq? (car e) 'quote))
2622+
`(quote ,(apply macroify-name (cadr e) suffixes)))
2623+
((and (pair? e) (eq? (car e) 'inert))
2624+
`(inert ,(apply macroify-name (cadr e) suffixes)))
2625+
((globalref? e)
2626+
`(globalref ,(cadr e) ,(apply macroify-name (caddr e) suffixes)))
26192627
((valid-modref? e)
26202628
`(|.| ,(cadr e)
2621-
(quote ,(apply macroify-name (cadr (caddr e)) suffixes))))
2629+
,(apply macroify-name (caddr e) suffixes)))
26222630
(else (error (string "invalid macro usage \"@(" (deparse e) ")\"" )))))
26232631

26242632
(define (macroify-call s call startloc)

src/julia-syntax.scm

+7-4
Original file line numberDiff line numberDiff line change
@@ -1347,15 +1347,18 @@
13471347
(else (error "invalid let syntax"))))
13481348
(else (error "invalid let syntax")))))))))
13491349

1350+
(define (valid-macro-def-name? e)
1351+
(or (symbol? e) (valid-modref? e) (globalref? e)))
1352+
13501353
(define (expand-macro-def e)
13511354
(cond ((and (pair? (cadr e))
13521355
(eq? (car (cadr e)) 'call)
1353-
(symbol? (cadr (cadr e))))
1356+
(valid-macro-def-name? (cadr (cadr e))))
13541357
(let ((anames (remove-empty-parameters (cddr (cadr e)))))
13551358
(if (has-parameters? anames)
13561359
(error "macros cannot accept keyword arguments"))
13571360
(expand-forms
1358-
`(function (call ,(symbol (string #\@ (cadr (cadr e))))
1361+
`(function (call ,(macroify-name (cadr (cadr e)))
13591362
(|::| __source__ (core LineNumberNode))
13601363
(|::| __module__ (core Module))
13611364
,@(map (lambda (v)
@@ -1364,8 +1367,8 @@
13641367
v))
13651368
anames))
13661369
,@(cddr e)))))
1367-
((and (length= e 2) (symbol? (cadr e)))
1368-
(expand-forms `(function ,(symbol (string #\@ (cadr e))))))
1370+
((and (length= e 2) (valid-macro-def-name? (cadr e)))
1371+
(expand-forms `(function ,(macroify-name (cadr e)))))
13691372
(else
13701373
(error "invalid macro definition"))))
13711374

test/syntax.jl

+13
Original file line numberDiff line numberDiff line change
@@ -3637,3 +3637,16 @@ end
36373637
@test array == [7]
36383638
@test execs == 4
36393639
end
3640+
3641+
# Allow GlobalRefs in macro definition
3642+
module MyMacroModule
3643+
macro mymacro end
3644+
end
3645+
macro MyMacroModule.mymacro()
3646+
1
3647+
end
3648+
@eval macro $(GlobalRef(MyMacroModule, :mymacro))(x)
3649+
2
3650+
end
3651+
@test (@MyMacroModule.mymacro) == 1
3652+
@test (@MyMacroModule.mymacro(a)) == 2

0 commit comments

Comments
 (0)