Macro to crate a struct and its external constructor

@macroexpand is very helpful in debugging macro code. Invoking your macro yields

julia> @macroexpand @definePathDT FnaP
quote
    #= REPL[1]:3 =#
    struct FnaP <: Main.PathsDT
        #= REPL[1]:4 =#
        p::Main.String
        #= REPL[1]:5 =#
        ext::Main.String
    end
    #= REPL[1]:8 =#
    function var"#41#FnaP"(var"#43#p"::Main.String)
        #= REPL[1]:8 =#
        #= REPL[1]:9 =#
        var"#42#ext" = Main.getFileExtention(var"#43#p")
        #= REPL[1]:10 =#
        if Main.ispresent(var"#42#ext", Main.ALLOWED_EXT["FnaP"])
            #= REPL[1]:11 =#
            return var"#41#FnaP"(var"#43#p", var"#42#ext")
        else
            #= REPL[1]:13 =#
            Main.error("The file '\$p' is not a valid $(Main.string(Main.name)) file.")
        end
    end
end

Look at the mangled variable names. The macro hygiene pass has converted all function and variable names into generic ones to avoid clashing with existing ones, e.g. a function $name might already exist in the evaluating module.
This shouldn’t pose a problem here.

To prevent macro hygiene, enclose the returned expression with esc(...).

macro definePathDT(name::Symbol)#, allowed_ext::String)
    esc(quote
        struct $name <: PathsDT
            p::String
            ext::String
        end

        function $name(p::String)
            ext = getFileExtention(p)
            if ispresent(ext, ALLOWED_EXT[$(string(name))]) #CLM_General.
                return $name(p, ext)
            else    
                error("The file '\$p' is not a valid $(string(name)) file.")
            end
        end
    end)
end
julia> abstract type PathsDT end

julia> @definePathDT FnaP
FnaP

julia> methods(FnaP)
# 3 methods for type constructor:
 [1] FnaP(p::String)
     @ REPL[6]:8
 [2] FnaP(p::String, ext::String)
     @ REPL[6]:4
 [3] FnaP(p, ext)
     @ REPL[6]:4
3 Likes