Skip to content

Commit 8c00bc2

Browse files
ihnortonvtjnash
authored andcommitted
pass file and line information as an argument named __source__ to all macros
also emit an explicit push_loc in @generated functions rather than depending on the existence of a LineNumberNode and other lowering heuristics to produce it
1 parent 2496b4e commit 8c00bc2

31 files changed

+408
-223
lines changed

base/boot.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787

8888
#struct LineNumberNode
8989
# line::Int
90+
# file::Any # nominally Union{Symbol,Void}
9091
#end
9192

9293
#struct LabelNode
@@ -281,7 +282,8 @@ _new(:GotoNode, :Int)
281282
_new(:NewvarNode, :SlotNumber)
282283
_new(:QuoteNode, :ANY)
283284
_new(:SSAValue, :Int)
284-
eval(:((::Type{LineNumberNode})(l::Int) = $(Expr(:new, :LineNumberNode, :l))))
285+
eval(:((::Type{LineNumberNode})(l::Int) = $(Expr(:new, :LineNumberNode, :l, nothing))))
286+
eval(:((::Type{LineNumberNode})(l::Int, f::ANY) = $(Expr(:new, :LineNumberNode, :l, :f))))
285287
eval(:((::Type{GlobalRef})(m::Module, s::Symbol) = $(Expr(:new, :GlobalRef, :m, :s))))
286288
eval(:((::Type{SlotNumber})(n::Int) = $(Expr(:new, :SlotNumber, :n))))
287289
eval(:((::Type{TypedSlot})(n::Int, t::ANY) = $(Expr(:new, :TypedSlot, :n, :t))))

base/docs/Docs.jl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,11 @@ function initmeta(m::Module = current_module())
8383
end
8484

8585
function signature!(tv, expr::Expr)
86-
if isexpr(expr, [:call, :macrocall])
86+
is_macrocall = isexpr(expr, :macrocall)
87+
if is_macrocall || isexpr(expr, :call)
8788
sig = :(Union{Tuple{}})
88-
for arg in expr.args[2:end]
89+
first_arg = is_macrocall ? 3 : 2 # skip function arguments
90+
for arg in expr.args[first_arg:end]
8991
isexpr(arg, :parameters) && continue
9092
if isexpr(arg, :kw) # optional arg
9193
push!(sig.args, :(Tuple{$(sig.args[end].args[2:end]...)}))
@@ -592,7 +594,7 @@ function __doc__!(meta, def, define)
592594
# the Base image). We just need to convert each `@__doc__` marker to an `@doc`.
593595
finddoc(def) do each
594596
each.head = :macrocall
595-
each.args = [Symbol("@doc"), meta, each.args[end], define]
597+
each.args = [Symbol("@doc"), nothing, meta, each.args[end], define] # TODO: forward line number info
596598
end
597599
else
598600
# `def` has already been defined during Base image gen so we just need to find and
@@ -635,7 +637,7 @@ const BINDING_HEADS = [:typealias, :const, :global, :(=)] # deprecation: remove
635637
isquotedmacrocall(x) =
636638
isexpr(x, :copyast, 1) &&
637639
isa(x.args[1], QuoteNode) &&
638-
isexpr(x.args[1].value, :macrocall, 1)
640+
isexpr(x.args[1].value, :macrocall, 2)
639641
# Simple expressions / atoms the may be documented.
640642
isbasicdoc(x) = isexpr(x, :.) || isa(x, Union{QuoteNode, Symbol})
641643
is_signature(x) = isexpr(x, :call) || (isexpr(x, :(::), 2) && isexpr(x.args[1], :call)) || isexpr(x, :where)
@@ -723,7 +725,7 @@ function docm(ex)
723725
parsedoc(keywords[ex])
724726
elseif isa(ex, Union{Expr, Symbol})
725727
binding = esc(bindingexpr(namify(ex)))
726-
if isexpr(ex, [:call, :macrocall])
728+
if isexpr(ex, :call) || isexpr(ex, :macrocall)
727729
sig = esc(signature(ex))
728730
:($(doc)($binding, $sig))
729731
else

base/docs/basedocs.jl

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -644,13 +644,6 @@ to be set after construction. See `struct` and the manual for more information.
644644
"""
645645
kw"mutable struct"
646646

647-
"""
648-
@__LINE__ -> Int
649-
650-
`@__LINE__` expands to the line number of the call-site.
651-
"""
652-
kw"@__LINE__"
653-
654647
"""
655648
ans
656649

base/docs/utils.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ function repl(io::IO, s::Symbol)
190190
$(_repl(s))
191191
end
192192
end
193-
isregex(x) = isexpr(x, :macrocall, 2) && x.args[1] === Symbol("@r_str") && !isempty(x.args[2])
193+
isregex(x) = isexpr(x, :macrocall, 3) && x.args[1] === Symbol("@r_str") && !isempty(x.args[3])
194194
repl(io::IO, ex::Expr) = isregex(ex) ? :(apropos($io, $ex)) : _repl(ex)
195195
repl(io::IO, str::AbstractString) = :(apropos($io, $str))
196196
repl(io::IO, other) = :(@doc $(esc(other)))

base/exports.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,7 @@ export
12471247
# parser internal
12481248
@__FILE__,
12491249
@__DIR__,
1250+
@__LINE__,
12501251
@int128_str,
12511252
@uint128_str,
12521253
@big_str,

base/expr.jl

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,9 +276,16 @@ end
276276

277277
remove_linenums!(ex) = ex
278278
function remove_linenums!(ex::Expr)
279-
filter!(x->!((isa(x,Expr) && x.head === :line) || isa(x,LineNumberNode)), ex.args)
279+
if ex.head === :body || ex.head === :block || ex.head === :quote
280+
# remove line number expressions from metadata (not argument literal or inert) position
281+
filter!(ex.args) do x
282+
isa(x, Expr) && x.head === :line && return false
283+
isa(x, LineNumberNode) && return false
284+
return true
285+
end
286+
end
280287
for subex in ex.args
281288
remove_linenums!(subex)
282289
end
283-
ex
290+
return ex
284291
end

base/inference.jl

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4176,39 +4176,38 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
41764176
end
41774177

41784178
do_coverage = coverage_enabled()
4179-
if do_coverage
4180-
line = method.line
4181-
if !isempty(stmts) && isa(stmts[1], LineNumberNode)
4182-
line = (shift!(stmts)::LineNumberNode).line
4179+
line::Int = method.line
4180+
file = method.file
4181+
if !isempty(stmts)
4182+
if !do_coverage && all(inlining_ignore, stmts)
4183+
empty!(stmts)
4184+
elseif isa(stmts[1], LineNumberNode)
4185+
linenode = shift!(stmts)::LineNumberNode
4186+
line = linenode.line
4187+
isa(linenode.file, Symbol) && (file = linenode.file)
41834188
end
4189+
end
4190+
if do_coverage
41844191
# Check if we are switching module, which is necessary to catch user
41854192
# code inlined into `Base` with `--code-coverage=user`.
41864193
# Assume we are inlining directly into `enclosing` instead of another
41874194
# function inlined in it
41884195
mod = method.module
41894196
if mod === sv.mod
4190-
unshift!(stmts, Expr(:meta, :push_loc, method.file,
4197+
unshift!(stmts, Expr(:meta, :push_loc, file,
41914198
method.name, line))
41924199
else
4193-
unshift!(stmts, Expr(:meta, :push_loc, method.file,
4200+
unshift!(stmts, Expr(:meta, :push_loc, file,
41944201
method.name, line, mod))
41954202
end
41964203
push!(stmts, Expr(:meta, :pop_loc))
41974204
elseif !isempty(stmts)
4198-
if all(inlining_ignore, stmts)
4199-
empty!(stmts)
4205+
unshift!(stmts, Expr(:meta, :push_loc, file,
4206+
method.name, line))
4207+
if isa(stmts[end], LineNumberNode)
4208+
stmts[end] = Expr(:meta, :pop_loc)
42004209
else
4201-
line::Int = method.line
4202-
if isa(stmts[1], LineNumberNode)
4203-
line = (shift!(stmts)::LineNumberNode).line
4204-
end
4205-
unshift!(stmts, Expr(:meta, :push_loc, method.file,
4206-
method.name, line))
4207-
if isa(stmts[end], LineNumberNode)
4208-
stmts[end] = Expr(:meta, :pop_loc)
4209-
else
4210-
push!(stmts, Expr(:meta, :pop_loc))
4211-
end
4210+
push!(stmts, Expr(:meta, :pop_loc))
42124211
end
42134212
end
42144213
if !isempty(stmts) && !propagate_inbounds

base/interactiveutil.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ function code_warntype(io::IO, f, t::ANY)
349349
end
350350
code_warntype(f, t::ANY) = code_warntype(STDOUT, f, t)
351351

352-
typesof(args...) = Tuple{map(a->(isa(a,Type) ? Type{a} : typeof(a)), args)...}
352+
typesof(args...) = Tuple{Any[ Core.Typeof(a) for a in args ]...}
353353

354354
gen_call_with_extracted_types(fcn, ex0::Symbol) = Expr(:call, fcn, Meta.quot(ex0))
355355
function gen_call_with_extracted_types(fcn, ex0)
@@ -371,9 +371,9 @@ function gen_call_with_extracted_types(fcn, ex0)
371371
exret = Expr(:none)
372372
is_macro = false
373373
ex = expand(ex0)
374-
if isa(ex0, Expr) && ex0.head == :macrocall # Make @edit @time 1+2 edit the macro
374+
if isa(ex0, Expr) && ex0.head == :macrocall # Make @edit @time 1+2 edit the macro by using the types of the *expressions*
375375
is_macro = true
376-
exret = Expr(:call, fcn, esc(ex0.args[1]), typesof(ex0.args[2:end]...))
376+
exret = Expr(:call, fcn, esc(ex0.args[1]), Tuple{#=__source__=#LineNumberNode, Any[ Core.Typeof(a) for a in ex0.args[3:end] ]...})
377377
elseif !isa(ex, Expr)
378378
exret = Expr(:call, :error, "expression is not a function call or symbol")
379379
elseif ex.head == :call

base/loading.jl

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -521,24 +521,6 @@ function source_dir()
521521
p === nothing ? p : dirname(p)
522522
end
523523

524-
"""
525-
@__FILE__ -> AbstractString
526-
527-
`@__FILE__` expands to a string with the absolute file path of the file containing the
528-
macro. Returns `nothing` if run from a REPL or an empty string if evaluated by
529-
`julia -e <expr>`. Alternatively see [`PROGRAM_FILE`](@ref).
530-
"""
531-
macro __FILE__() source_path() end
532-
533-
"""
534-
@__DIR__ -> AbstractString
535-
536-
`@__DIR__` expands to a string with the directory part of the absolute path of the file
537-
containing the macro. Returns `nothing` if run from a REPL or an empty string if
538-
evaluated by `julia -e <expr>`.
539-
"""
540-
macro __DIR__() source_dir() end
541-
542524
include_from_node1(path::AbstractString) = include_from_node1(String(path))
543525
function include_from_node1(_path::String)
544526
path, prev = _include_dependency(_path)
@@ -806,3 +788,37 @@ function stale_cachefile(modpath::String, cachefile::String)
806788
close(io)
807789
end
808790
end
791+
792+
"""
793+
@__LINE__ -> Int
794+
795+
`@__LINE__` expands to the line number of the location of the macrocall.
796+
Returns `0` if the line number could not be determined.
797+
"""
798+
macro __LINE__()
799+
return __source__.line
800+
end
801+
802+
"""
803+
@__FILE__ -> AbstractString
804+
805+
`@__FILE__` expands to a string with the absolute file path of the file containing the
806+
macrocall. Returns `nothing` if run from a REPL or an empty string if evaluated by
807+
`julia -e <expr>`. Alternatively see [`PROGRAM_FILE`](@ref).
808+
"""
809+
macro __FILE__()
810+
__source__.file === nothing && return nothing
811+
return String(__source__.file)
812+
end
813+
814+
"""
815+
@__DIR__ -> AbstractString
816+
817+
`@__DIR__` expands to a string with the directory part of the absolute path of the file
818+
containing the macrocall. Returns `nothing` if run from a REPL or an empty string if
819+
evaluated by `julia -e <expr>`.
820+
"""
821+
macro __DIR__()
822+
__source__.file === nothing && return nothing
823+
return dirname(String(__source__.file))
824+
end

base/math.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ macro evalpoly(z, p...)
124124
:(s = muladd(x, x, y*y)),
125125
as...,
126126
:(muladd($ai, tt, $b)))
127-
R = Expr(:macrocall, Symbol("@horner"), :tt, map(esc, p)...)
127+
R = Expr(:macrocall, Symbol("@horner"), (), :tt, map(esc, p)...)
128128
:(let tt = $(esc(z))
129129
isa(tt, Complex) ? $C : $R
130130
end)

0 commit comments

Comments
 (0)