Line number of calling site

question
juno

#1

Is there a way to get the line number of the calling function?

I would like to encode the filename and the line number of a type.
so for example if I have

 type foo
   line::Int32
   fname::String
 end

what should be in the constructor so if I have

a = foo() in file “temp.jl” and in line 100 , this information will be present within the instance of foo stored in a.

This is meant as a way to provide better error messages for async tasks.


#2

I accept any trickery using stacktraces or backtraces …
Maybe the Juno guys have an idea?


#3

Check out the backtrace and StackTraces.lookup:

julia> bt = backtrace()
21-element Array{Ptr{Void},1}:
 Ptr{Void} @0x00007fc2a2cbeb38
 Ptr{Void} @0x00007fc29d1c8c7c
 Ptr{Void} @0x00007fc29d1c8c89
 Ptr{Void} @0x00007fc2a2c7b990
 Ptr{Void} @0x00007fc2a2c9067e
 Ptr{Void} @0x00007fc2a2c8f75e
 Ptr{Void} @0x00007fc2a2c90d29
 Ptr{Void} @0x00007fc2a2c9114f
 Ptr{Void} @0x00007fc2a2caae5d
 Ptr{Void} @0x00007fc2a2c8b27c
 Ptr{Void} @0x00007fc29cf8009a
 Ptr{Void} @0x00007fc29cf800b0
 Ptr{Void} @0x00007fc2a2c7b990
 Ptr{Void} @0x00007fc08d88edb7
 Ptr{Void} @0x00007fc08d88f017
 Ptr{Void} @0x00007fc2a2c7b990
 Ptr{Void} @0x00007fc08d88bbff
 Ptr{Void} @0x00007fc08d88bf10
 Ptr{Void} @0x00007fc2a2c7b990
 Ptr{Void} @0x00007fc2a2c9969f
 Ptr{Void} @0x0000000000000000

julia> StackTraces.lookup.(bt)
21-element Array{Array{StackFrame,1},1}:
 StackFrame[ in jl_backtrace_from_here at stackwalk.c:105]                                                              
 StackFrame[ in backtrace() at error.jl:26]                                                                             
 StackFrame[ in backtrace() at sys.so:?]                                                                                
 StackFrame[ in jl_call_method_internal at julia_internal.h:189 [inlined], in jl_apply_generic at gf.c:1945]            
 StackFrame[ in do_call at interpreter.c:66]                                                                            
 StackFrame[ in eval at interpreter.c:190]                                                                              
 StackFrame[ in eval_body at interpreter.c:469]                                                                         
 StackFrame[ in jl_interpret_call at interpreter.c:573]                                                                 
 StackFrame[ in jl_toplevel_eval_flex at toplevel.c:572 [inlined], in jl_toplevel_eval at toplevel.c:580]               
 StackFrame[ in jl_toplevel_eval_in_warn at builtins.c:590]                                                             
 StackFrame[ in eval(::Module, ::Any) at boot.jl:234]                                                                   
 StackFrame[ in eval(::Module, ::Any) at sys.so:?]                                                                      
 StackFrame[ in jl_call_method_internal at julia_internal.h:189 [inlined], in jl_apply_generic at gf.c:1945]            
 StackFrame[ in eval_user_input(::Any, ::Base.REPL.REPLBackend) at REPL.jl:64]                                          
 StackFrame[ in ip:0x7fc08d88f016]                                                                                      
 StackFrame[ in jl_call_method_internal at julia_internal.h:189 [inlined], in jl_apply_generic at gf.c:1945]            
 StackFrame[ in macro expansion at REPL.jl:95 [inlined], in (::Base.REPL.##3#4{Base.REPL.REPLBackend})() at event.jl:68]
 StackFrame[ in ip:0x7fc08d88bf0f]                                                                                      
 StackFrame[ in jl_call_method_internal at julia_internal.h:189 [inlined], in jl_apply_generic at gf.c:1945]            
 StackFrame[ in jl_apply at julia.h:1392 [inlined], in start_task at task.c:253]                                        
 StackFrame[ in ip:0xffffffffffffffff]                                                                                  

#4

The stacktrace function works if the calling was done from within some function … then in that case
stacktrace[2] is the calling function.

However if the call is not wrapped in function then I am left with
include_from_node1(::String) at loading.jl:488
as the calling file and line…

So I am wondering whether it is possible to infer the calling line and file name even if the code is not wrapped
in a function … for example in scripts.


#5

I’m not sure this is currently possible. You could create a special inner constructor and the caller could use Foo(line, fname, file=@__FILE__, line=@__LINE__). As long as it’s the caller that’s using @__FILE__ and @__LINE__ then I think you’ll get the information you need. Painful, I know.