1use std::collections::HashMap;
4use std::fmt;
5
6#[derive(Debug, Clone, PartialEq)]
8pub struct QasmProgram {
9 pub version: String,
11 pub includes: Vec<String>,
13 pub declarations: Vec<Declaration>,
15 pub statements: Vec<QasmStatement>,
17}
18
19#[derive(Debug, Clone, PartialEq)]
21pub enum Declaration {
22 QuantumRegister(QasmRegister),
24 ClassicalRegister(QasmRegister),
26 GateDefinition(GateDefinition),
28 Constant(String, Expression),
30}
31
32#[derive(Debug, Clone, PartialEq, Eq)]
34pub struct QasmRegister {
35 pub name: String,
37 pub size: usize,
39}
40
41#[derive(Debug, Clone, PartialEq)]
43pub struct GateDefinition {
44 pub name: String,
46 pub params: Vec<String>,
48 pub qubits: Vec<String>,
50 pub body: Vec<QasmStatement>,
52}
53
54#[derive(Debug, Clone, PartialEq)]
56pub enum QasmStatement {
57 Gate(QasmGate),
59 Measure(Measurement),
61 Reset(Vec<QubitRef>),
63 Barrier(Vec<QubitRef>),
65 Assignment(String, Expression),
67 If(Condition, Box<Self>),
69 For(ForLoop),
71 While(Condition, Vec<Self>),
73 Call(String, Vec<Expression>),
75 Delay(Expression, Vec<QubitRef>),
77}
78
79#[derive(Debug, Clone, PartialEq)]
81pub struct QasmGate {
82 pub name: String,
84 pub params: Vec<Expression>,
86 pub qubits: Vec<QubitRef>,
88 pub control: Option<usize>,
90 pub inverse: bool,
92 pub power: Option<Expression>,
94}
95
96#[derive(Debug, Clone, PartialEq, Eq)]
98pub enum QubitRef {
99 Single { register: String, index: usize },
101 Slice {
103 register: String,
104 start: usize,
105 end: usize,
106 },
107 Register(String),
109}
110
111#[derive(Debug, Clone, PartialEq, Eq)]
113pub struct Measurement {
114 pub qubits: Vec<QubitRef>,
116 pub targets: Vec<ClassicalRef>,
118}
119
120#[derive(Debug, Clone, PartialEq, Eq)]
122pub enum ClassicalRef {
123 Single { register: String, index: usize },
125 Slice {
127 register: String,
128 start: usize,
129 end: usize,
130 },
131 Register(String),
133}
134
135#[derive(Debug, Clone, PartialEq)]
137pub enum Expression {
138 Literal(Literal),
140 Variable(String),
142 Binary(BinaryOp, Box<Self>, Box<Self>),
144 Unary(UnaryOp, Box<Self>),
146 Function(String, Vec<Self>),
148 Index(String, Box<Self>),
150}
151
152#[derive(Debug, Clone, PartialEq)]
154pub enum Literal {
155 Integer(i64),
157 Float(f64),
159 Bool(bool),
161 String(String),
163 Pi,
165 Euler,
167 Tau,
169}
170
171#[derive(Debug, Clone, Copy, PartialEq, Eq)]
173pub enum BinaryOp {
174 Add,
175 Sub,
176 Mul,
177 Div,
178 Mod,
179 Pow,
180 Eq,
181 Ne,
182 Lt,
183 Le,
184 Gt,
185 Ge,
186 And,
187 Or,
188 Xor,
189 BitAnd,
190 BitOr,
191 BitXor,
192 Shl,
193 Shr,
194}
195
196#[derive(Debug, Clone, Copy, PartialEq, Eq)]
198pub enum UnaryOp {
199 Neg,
200 Not,
201 BitNot,
202 Sin,
203 Cos,
204 Tan,
205 Asin,
206 Acos,
207 Atan,
208 Exp,
209 Ln,
210 Sqrt,
211}
212
213#[derive(Debug, Clone, PartialEq)]
215pub struct Condition {
216 pub left: Expression,
218 pub op: ComparisonOp,
220 pub right: Expression,
222}
223
224#[derive(Debug, Clone, Copy, PartialEq, Eq)]
226pub enum ComparisonOp {
227 Eq,
228 Ne,
229 Lt,
230 Le,
231 Gt,
232 Ge,
233}
234
235#[derive(Debug, Clone, PartialEq)]
237pub struct ForLoop {
238 pub variable: String,
240 pub start: Expression,
242 pub end: Expression,
244 pub step: Option<Expression>,
246 pub body: Vec<QasmStatement>,
248}
249
250impl fmt::Display for QasmProgram {
252 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
253 writeln!(f, "OPENQASM {};", self.version)?;
254
255 for include in &self.includes {
256 writeln!(f, "include \"{include}\";")?;
257 }
258
259 if !self.includes.is_empty() {
260 writeln!(f)?;
261 }
262
263 for decl in &self.declarations {
264 writeln!(f, "{decl}")?;
265 }
266
267 if !self.declarations.is_empty() {
268 writeln!(f)?;
269 }
270
271 for stmt in &self.statements {
272 writeln!(f, "{stmt}")?;
273 }
274
275 Ok(())
276 }
277}
278
279impl fmt::Display for Declaration {
280 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281 match self {
282 Self::QuantumRegister(reg) => write!(f, "qubit[{}] {};", reg.size, reg.name),
283 Self::ClassicalRegister(reg) => write!(f, "bit[{}] {};", reg.size, reg.name),
284 Self::GateDefinition(def) => {
285 write!(f, "gate {}", def.name)?;
286 if !def.params.is_empty() {
287 write!(f, "({})", def.params.join(", "))?;
288 }
289 write!(f, " {}", def.qubits.join(", "))?;
290 writeln!(f, " {{")?;
291 for stmt in &def.body {
292 writeln!(f, " {stmt}")?;
293 }
294 write!(f, "}}")
295 }
296 Self::Constant(name, expr) => write!(f, "const {name} = {expr};"),
297 }
298 }
299}
300
301impl fmt::Display for QasmStatement {
302 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
303 match self {
304 Self::Gate(gate) => write!(f, "{gate}"),
305 Self::Measure(meas) => {
306 write!(f, "measure ")?;
307 for (i, (q, c)) in meas.qubits.iter().zip(&meas.targets).enumerate() {
308 if i > 0 {
309 write!(f, ", ")?;
310 }
311 write!(f, "{q} -> {c}")?;
312 }
313 write!(f, ";")
314 }
315 Self::Reset(qubits) => {
316 write!(f, "reset ")?;
317 for (i, q) in qubits.iter().enumerate() {
318 if i > 0 {
319 write!(f, ", ")?;
320 }
321 write!(f, "{q}")?;
322 }
323 write!(f, ";")
324 }
325 Self::Barrier(qubits) => {
326 write!(f, "barrier")?;
327 if !qubits.is_empty() {
328 write!(f, " ")?;
329 for (i, q) in qubits.iter().enumerate() {
330 if i > 0 {
331 write!(f, ", ")?;
332 }
333 write!(f, "{q}")?;
334 }
335 }
336 write!(f, ";")
337 }
338 Self::Assignment(var, expr) => write!(f, "{var} = {expr};"),
339 Self::If(cond, stmt) => write!(f, "if ({cond}) {stmt}"),
340 Self::For(for_loop) => {
341 writeln!(
342 f,
343 "for {} in [{}:{}] {{",
344 for_loop.variable, for_loop.start, for_loop.end
345 )?;
346 for stmt in &for_loop.body {
347 writeln!(f, " {stmt}")?;
348 }
349 write!(f, "}}")
350 }
351 Self::While(cond, body) => {
352 writeln!(f, "while ({cond}) {{")?;
353 for stmt in body {
354 writeln!(f, " {stmt}")?;
355 }
356 write!(f, "}}")
357 }
358 Self::Call(name, args) => {
359 write!(f, "{name}(")?;
360 for (i, arg) in args.iter().enumerate() {
361 if i > 0 {
362 write!(f, ", ")?;
363 }
364 write!(f, "{arg}")?;
365 }
366 write!(f, ");")
367 }
368 Self::Delay(duration, qubits) => {
369 write!(f, "delay[{duration}]")?;
370 if !qubits.is_empty() {
371 write!(f, " ")?;
372 for (i, q) in qubits.iter().enumerate() {
373 if i > 0 {
374 write!(f, ", ")?;
375 }
376 write!(f, "{q}")?;
377 }
378 }
379 write!(f, ";")
380 }
381 }
382 }
383}
384
385impl fmt::Display for QasmGate {
386 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
387 if let Some(ctrl) = self.control {
388 write!(f, "ctrl({ctrl}) ")?;
389 }
390 if self.inverse {
391 write!(f, "inv ")?;
392 }
393 if let Some(power) = &self.power {
394 write!(f, "pow({power}) ")?;
395 }
396
397 write!(f, "{}", self.name)?;
398
399 if !self.params.is_empty() {
400 write!(f, "(")?;
401 for (i, param) in self.params.iter().enumerate() {
402 if i > 0 {
403 write!(f, ", ")?;
404 }
405 write!(f, "{param}")?;
406 }
407 write!(f, ")")?;
408 }
409
410 write!(f, " ")?;
411 for (i, qubit) in self.qubits.iter().enumerate() {
412 if i > 0 {
413 write!(f, ", ")?;
414 }
415 write!(f, "{qubit}")?;
416 }
417 write!(f, ";")
418 }
419}
420
421impl fmt::Display for QubitRef {
422 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
423 match self {
424 Self::Single { register, index } => write!(f, "{register}[{index}]"),
425 Self::Slice {
426 register,
427 start,
428 end,
429 } => write!(f, "{register}[{start}:{end}]"),
430 Self::Register(name) => write!(f, "{name}"),
431 }
432 }
433}
434
435impl fmt::Display for ClassicalRef {
436 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
437 match self {
438 Self::Single { register, index } => write!(f, "{register}[{index}]"),
439 Self::Slice {
440 register,
441 start,
442 end,
443 } => write!(f, "{register}[{start}:{end}]"),
444 Self::Register(name) => write!(f, "{name}"),
445 }
446 }
447}
448
449impl fmt::Display for Expression {
450 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
451 match self {
452 Self::Literal(lit) => write!(f, "{lit}"),
453 Self::Variable(name) => write!(f, "{name}"),
454 Self::Binary(op, left, right) => write!(f, "({left} {op} {right})"),
455 Self::Unary(op, expr) => write!(f, "({op}{expr})"),
456 Self::Function(name, args) => {
457 write!(f, "{name}(")?;
458 for (i, arg) in args.iter().enumerate() {
459 if i > 0 {
460 write!(f, ", ")?;
461 }
462 write!(f, "{arg}")?;
463 }
464 write!(f, ")")
465 }
466 Self::Index(name, idx) => write!(f, "{name}[{idx}]"),
467 }
468 }
469}
470
471impl fmt::Display for Literal {
472 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
473 match self {
474 Self::Integer(n) => write!(f, "{n}"),
475 Self::Float(x) => write!(f, "{x}"),
476 Self::Bool(b) => write!(f, "{b}"),
477 Self::String(s) => write!(f, "\"{s}\""),
478 Self::Pi => write!(f, "pi"),
479 Self::Euler => write!(f, "e"),
480 Self::Tau => write!(f, "tau"),
481 }
482 }
483}
484
485impl fmt::Display for BinaryOp {
486 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
487 let op = match self {
488 Self::Add => "+",
489 Self::Sub => "-",
490 Self::Mul => "*",
491 Self::Div => "/",
492 Self::Mod => "%",
493 Self::Pow => "**",
494 Self::Eq => "==",
495 Self::Ne => "!=",
496 Self::Lt => "<",
497 Self::Le => "<=",
498 Self::Gt => ">",
499 Self::Ge => ">=",
500 Self::And => "&&",
501 Self::Or => "||",
502 Self::Xor => "^^",
503 Self::BitAnd => "&",
504 Self::BitOr => "|",
505 Self::BitXor => "^",
506 Self::Shl => "<<",
507 Self::Shr => ">>",
508 };
509 write!(f, "{op}")
510 }
511}
512
513impl fmt::Display for UnaryOp {
514 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
515 let op = match self {
516 Self::Neg => "-",
517 Self::Not => "!",
518 Self::BitNot => "~",
519 Self::Sin => "sin",
520 Self::Cos => "cos",
521 Self::Tan => "tan",
522 Self::Asin => "asin",
523 Self::Acos => "acos",
524 Self::Atan => "atan",
525 Self::Exp => "exp",
526 Self::Ln => "ln",
527 Self::Sqrt => "sqrt",
528 };
529 write!(f, "{op}")
530 }
531}
532
533impl fmt::Display for Condition {
534 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
535 write!(f, "{} {} {}", self.left, self.op, self.right)
536 }
537}
538
539impl fmt::Display for ComparisonOp {
540 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
541 let op = match self {
542 Self::Eq => "==",
543 Self::Ne => "!=",
544 Self::Lt => "<",
545 Self::Le => "<=",
546 Self::Gt => ">",
547 Self::Ge => ">=",
548 };
549 write!(f, "{op}")
550 }
551}