Shared Variables In Nested Macros

You’ll need to esc some of the argument names, this, and sym, which should probably reference the right things then:

macro defs(type, body)
    type = esc(type)
    body = esc(body)
    this = esc(:this)
    sym = esc(:sym)
    return quote
        function Base.getproperty(this::$type, sym::Symbol)
            $body
            return getfield(this, sym)
        end
    end
end

macro def(symbol, body)
    symb = string(symbol)
    body = esc(body)
    sym = esc(:sym)
    return quote

        # NOTE: "sym" has been defined in defs !
        if sym === Symbol($symb)
            return $body
        end
    end
end

If @def is never used outside of @defs then maybe don’t even define a @def macro and just do all the processing inside of @defs instead. That would save you some of the headaches of dealing with macro hygiene.

The string to Symbol conversions in @def can be switched to use Meta.quot btw:

macro def(symbol, body)
    body = esc(body)
    sym = esc(:sym)
    return quote
        # NOTE: "sym" has been defined in defs !
        if $sym === $(Meta.quot(symbol))
            return $body
        end
    end
end
2 Likes