diff --git a/base/client.jl b/base/client.jl index aa0739eaed0fe..40c4b77a0476b 100644 --- a/base/client.jl +++ b/base/client.jl @@ -599,7 +599,7 @@ The `@main` macro may be used standalone or as part of the function definition, case, parentheses are required. In particular, the following are equivalent: ``` -function (@main)(args) +function @main(args) println("Hello World") end ``` @@ -618,7 +618,7 @@ imported into `Main`, it will be treated as an entrypoint in `Main`: ``` module MyApp export main - (@main)(args) = println("Hello World") + @main(args) = println("Hello World") end using .MyApp # `julia` Will execute MyApp.main at the conclusion of script execution @@ -628,7 +628,7 @@ Note that in particular, the semantics do not attach to the method or the name: ``` module MyApp - (@main)(args) = println("Hello World") + @main(args) = println("Hello World") end const main = MyApp.main # `julia` Will *NOT* execute MyApp.main unless there is a separate `@main` annotation in `Main` @@ -638,9 +638,6 @@ const main = MyApp.main This macro is new in Julia 1.11. At present, the precise semantics of `@main` are still subject to change. """ macro main(args...) - if !isempty(args) - error("`@main` is expected to be used as `(@main)` without macro arguments.") - end if isdefined(__module__, :main) if Base.binding_module(__module__, :main) !== __module__ error("Symbol `main` is already a resolved import in module $(__module__). `@main` must be used in the defining module.") @@ -651,5 +648,9 @@ macro main(args...) global main global var"#__main_is_entrypoint__#"::Bool = true end) - esc(:main) + if !isempty(args) + Expr(:call, esc(:main), map(esc, args)...) + else + esc(:main) + end end diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 891a26bb0ea49..631078432b5d2 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -1329,13 +1329,12 @@ (define (valid-func-sig? paren sig) (and (pair? sig) - (or (eq? (car sig) 'call) - (eq? (car sig) 'tuple) + (or (memq (car sig) '(macrocall call tuple)) (and paren (eq? (car sig) 'block)) (and paren (eq? (car sig) '...)) (and (eq? (car sig) '|::|) (pair? (cadr sig)) - (eq? (car (cadr sig)) 'call)) + (memq (car (cadr sig)) '(call macrocall))) (and (eq? (car sig) 'where) (valid-func-sig? paren (cadr sig)))))) diff --git a/test/syntax.jl b/test/syntax.jl index 0855c643e1423..f4b2807d82407 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -3904,3 +3904,31 @@ module ExtendedIsDefined @test !$(Expr(:isdefined, GlobalRef(@__MODULE__, :x4), false)) end end + +# PR# 55040 - Macrocall as function sig +@test :(function @f()() end) == :(function (@f)() end) + +function callme end +macro callmemacro(args...) + Expr(:call, esc(:callme), map(esc, args)...) +end +function @callmemacro(a::Int) + return 1 +end +@callmemacro(b::Float64) = 2 +function @callmemacro(a::T, b::T) where T <: Int64 + return 3 +end +function @callmemacro(a::Int, b::Int, c::Int)::Float64 + return 4 +end +function @callmemacro(d::String) + (a, b, c) + # ^ Should not be accidentally parsed as an argument list + return 4 +end + +@test callme(1) === 1 +@test callme(2.0) === 2 +@test callme(3, 3) === 3 +@test callme(4, 4, 4) === 4.0