Skip to content

Instantly share code, notes, and snippets.

@jlapeyre
Created May 16, 2022 15:50
Show Gist options
  • Save jlapeyre/a906b7cec6c556104cd1e06422367a33 to your computer and use it in GitHub Desktop.
Save jlapeyre/a906b7cec6c556104cd1e06422367a33 to your computer and use it in GitHub Desktop.
using MacroTools
using MacroTools: striplines
###
### Macros
###
"""
@qc code
Translate every expression of the form
`f.g(args...)` to `add!(f, g, args...)`.
For example, it translates `circ.cx(i, j)` to `add!(circ, cx, i, j)`.
In case there is code inside the block of this form (i.e. `q.r(args...)`
where `q` is *not* of type `Circ`, we have defined a fallback method for `add!`
to translate back to the meaning of the original syntax.
"""
macro qc(ex)
return _qcirc(ex)
end
"""
@qc circ code
Translate every expression of the form `g(args...)` to `add!(circ,
g, args...)`. For example, it translates `cx(i, j)` to `add!(circ, cx, i, j)`.
"""
macro qc(incirc, ex)
_qcirc(incirc, ex)
end
function _qcirc(ex)
MacroTools.postwalk(ex) do x
(@capture(x, f_.g_(args__))) || return x
return :(add!($f, $g, $(args...)))
end
end
const GateList = (:x, :sx, :y, :z, :h, :cx, :s, :sdg, :t, :tdg, :u, :u3, :rx, :ry, :rz, :rzx, :u4)
function _qcirc(incirc, ex)
MacroTools.postwalk(ex) do x
(@capture(x, f_(args__)) && f in GateList) || return x
return :(add!($incirc, $f, $(args...)))
end
end
###
### Circ: a dummy circuit type
###
struct Circ{T}
data::Vector{T}
end
Circ() = Circ([])
function Base.show(io::IO, m::MIME"text/plain", circ::Circ)
println(io, "Circ with data:")
show(io, m, circ.data)
end
add!(circ::Circ, gate, args...) = (push!(circ.data, gate(args...)); circ)
# Restore original syntax in the generic case
add!(x, y, args...) = x.y(args...)
# Another option is the following
#add!(x, y, args...) = y(x, args...) # standard dot call meaning
for gate in (:x, :h, :cx)
@eval ($gate)(args...) = ($(QuoteNode(gate)), args...)
end
# paramaterized gates
for (gate, nparams) in ((:rz, 1), (:ry, 1))
@eval ($gate)(args...) = (($(QuoteNode(gate)), args[1:$nparams]...), args[$nparams+1:end]...)
end
###
### Examples
###
@show x(1)
@show cx(2, 3)
@show rz(0.5, 1)
circ = Circ()
k = 1
@qc begin
circ.h(k).x(1)
foreach(i -> circ.h(i), 1:3)
foreach(i -> circ.cx(i[1],i[2]), zip(1:2, 2:3))
end
@show circ
i = -1
j = -1
circ = Circ()
@qc circ begin
i = 2
j = 3
x(i)
h(j)
cx(j, i)
end
@show circ
i = -1
j = -1
circ = Circ()
@qc circ begin
x(i)
h(j)
cx(j, i)
end
@show circ
@jlapeyre
Copy link
Author

help?> @qc
  @qc code


  Translate every expression of the form f.g(args...) to add!(f, g, args...). For example, it translates circ.cx(i, j) to add!(circ, cx, i, j).

  In case there is code inside the block of this form (i.e. q.r(args...) where q is not of type Circ, we have defined a fallback method for add!
  to translate back to the meaning of the original syntax.

  ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  @qc circ code


  Translate every expression of the form g(args...) to add!(circ, g, args...). For example, it translates cx(i, j) to add!(circ, cx, i, j).

@jlapeyre
Copy link
Author

Running circmacro_examples.jl gives:

x(1) = (:x, 1)
cx(2, 3) = (:cx, 2, 3)
rz(0.5, 1) = ((:rz, 0.5), 1)
circ = Circ{Any}(Any[(:h, 1), (:x, 1), (:h, 1), (:h, 2), (:h, 3), (:cx, 1, 2), (:cx, 2, 3)])
circ = Circ{Any}(Any[(:x, 2), (:h, 3), (:cx, 3, 2)])
circ = Circ{Any}(Any[(:x, -1), (:h, -1), (:cx, -1, -1)])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment