# Macro to deduce the filepath of the file that calls a specific function

**URL:** https://discourse.julialang.org/t/macro-to-deduce-the-filepath-of-the-file-that-calls-a-specific-function/23371
**Category:** General Usage
**Created:** [April 21, 2019, 2:24pm UTC](https://discourse.julialang.org/t/macro-to-deduce-the-filepath-of-the-file-that-calls-a-specific-function/23371 "2019-04-21T14:24:05Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)
#### Post date: [April 21, 2019, 2:24pm UTC](https://discourse.julialang.org/t/macro-to-deduce-the-filepath-of-the-file-that-calls-a-specific-function/23371/1 "2019-04-21T14:24:05Z")

</div>

I want to write a macro for the package [DrWatson](https://juliadynamics.github.io/DrWatson.jl/dev/) that does the following:

I define a macro `@m` and a function `f` inside DrWatson. Now, when the function `f` is called in a script somewhere, I want to be able inside `f` to resolve the path of the file that called `f` , using a super magic macro `@m`.

E.g. I have a script `~/test.jl` and inside the script I have

```julia
using DrWatson
f()

```

then `f` should be able to resolve inside it the path `~/test.jl`.

Is this even possible or I am asking for too much magic?

---

<div class="post-metadata">

### Author: ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)
#### Post date: [April 21, 2019, 3:44pm UTC](https://discourse.julialang.org/t/macro-to-deduce-the-filepath-of-the-file-that-calls-a-specific-function/23371/2 "2019-04-21T15:44:55Z")

</div>

```julia
f() = display(stacktrace(backtrace()))

```

should give you some ideas about how to go about extracting this info.

---

<div class="post-metadata">

### Author: ![pfitzseb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pfitzseb/32/45566_2.png) [@pfitzseb](https://discourse.julialang.org/u/pfitzseb)
#### Post date: [April 21, 2019, 3:46pm UTC](https://discourse.julialang.org/t/macro-to-deduce-the-filepath-of-the-file-that-calls-a-specific-function/23371/3 "2019-04-21T15:46:11Z")

</div>

You could also make your user facing API a macro and inspect the (hidden) ` __source__ ` argument.

---

<div class="post-metadata">

### Author: ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)
#### Post date: [April 21, 2019, 4:01pm UTC](https://discourse.julialang.org/t/macro-to-deduce-the-filepath-of-the-file-that-calls-a-specific-function/23371/4 "2019-04-21T16:01:34Z")

</div>

@pfitzseb where can I find information about this argument? Searching the Julia docs didn’t yield anything. ([https://docs.julialang.org/en/latest/search/?q=\_\_source\_\_+](https://docs.julialang.org/en/latest/search/?q= __source__ +) )

---

<div class="post-metadata">

### Author: ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)
#### Post date: [April 21, 2019, 4:15pm UTC](https://discourse.julialang.org/t/macro-to-deduce-the-filepath-of-the-file-that-calls-a-specific-function/23371/5 "2019-04-21T16:15:28Z")

</div>

@tim.holy , even though I would much rather use a normal function than a macro here, I am not so sure I can use your suggestion.

I define in my module the test functions

```julia
function tag2(x)
    a = callerpath()
end

function callerpath()
    a = stacktrace(backtrace())
end

```

and I create a file `test.jl` with contents

```julia
using DrWatson
a = tag2(rand())

```

Regardless if I run this in Juno or in the REPL (using `include`) I get a stack trace that looks like:

```julia
julia> include(raw"C:\Users\datseris\.julia\dev\DrWatson\test\test.jl")
12-element Array{Base.StackTraces.StackFrame,1}:
 callerpath at saving_tools.jl:91 [inlined]
 tag2(::Float64) at saving_tools.jl:87
 top-level scope at none:0
 include at boot.jl:326 [inlined]
 include_relative(::Module, ::String) at loading.jl:1038
 include(::Module, ::String) at sysimg.jl:29
 include(::String) at client.jl:403
 top-level scope at none:0
 eval(::Module, ::Any) at boot.jl:328
 eval_user_input(::Any, ::REPL.REPLBackend) at REPL.jl:85
 macro expansion at REPL.jl:117 [inlined]
 (::getfield(REPL, Symbol("##26#27")){REPL.REPLBackend})() at task.jl:259

```

In both Juno, REPL the third element of the trace (which I would assume to be the filename) is “none” because the execution is done at the top-level scope. Also, notably, `test.jl` is not present in any trace.

---

<div class="post-metadata">

### Author: ![pfitzseb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pfitzseb/32/45566_2.png) [@pfitzseb](https://discourse.julialang.org/u/pfitzseb)
#### Post date: [April 21, 2019, 4:19pm UTC](https://discourse.julialang.org/t/macro-to-deduce-the-filepath-of-the-file-that-calls-a-specific-function/23371/6 "2019-04-21T16:19:50Z")

</div>

Scroll down a bit from [here](https://docs.julialang.org/en/v1.1/manual/metaprogramming/#Macro-invocation-1).

---

<div class="post-metadata">

### Author: ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)
#### Post date: [April 21, 2019, 6:26pm UTC](https://discourse.julialang.org/t/macro-to-deduce-the-filepath-of-the-file-that-calls-a-specific-function/23371/7 "2019-04-21T18:26:36Z")

</div>

So far I have been able to do that using the following definition:

```julia
macro tag!(d, path = projectdir())
    s = QuoteNode( __source__ )
    :(tag!($(esc(d)), $(esc(path)), $s))
end

```

and adding a third argument to my already existing function `tag!`.

I would still appreciate if this can be done using a normal function call instead of the macro, for various reasons (mostly having a cleaner API). If anyone knows a way please let me know.
