quantrs2_circuit/qasm/
ast.rs

1//! Abstract Syntax Tree for `OpenQASM` 3.0
2
3use std::collections::HashMap;
4use std::fmt;
5
6/// Represents a complete QASM program
7#[derive(Debug, Clone, PartialEq)]
8pub struct QasmProgram {
9    /// Version declaration
10    pub version: String,
11    /// Include statements
12    pub includes: Vec<String>,
13    /// Global declarations
14    pub declarations: Vec<Declaration>,
15    /// Statements in the program
16    pub statements: Vec<QasmStatement>,
17}
18
19/// Declaration types
20#[derive(Debug, Clone, PartialEq)]
21pub enum Declaration {
22    /// Quantum register declaration
23    QuantumRegister(QasmRegister),
24    /// Classical register declaration
25    ClassicalRegister(QasmRegister),
26    /// Gate definition
27    GateDefinition(GateDefinition),
28    /// Constant declaration
29    Constant(String, Expression),
30}
31
32/// Register declaration
33#[derive(Debug, Clone, PartialEq, Eq)]
34pub struct QasmRegister {
35    /// Register name
36    pub name: String,
37    /// Size of the register
38    pub size: usize,
39}
40
41/// Custom gate definition
42#[derive(Debug, Clone, PartialEq)]
43pub struct GateDefinition {
44    /// Gate name
45    pub name: String,
46    /// Parameter names
47    pub params: Vec<String>,
48    /// Qubit arguments
49    pub qubits: Vec<String>,
50    /// Gate body
51    pub body: Vec<QasmStatement>,
52}
53
54/// QASM statement types
55#[derive(Debug, Clone, PartialEq)]
56pub enum QasmStatement {
57    /// Gate application
58    Gate(QasmGate),
59    /// Measurement
60    Measure(Measurement),
61    /// Reset operation
62    Reset(Vec<QubitRef>),
63    /// Barrier
64    Barrier(Vec<QubitRef>),
65    /// Classical assignment
66    Assignment(String, Expression),
67    /// If statement
68    If(Condition, Box<Self>),
69    /// For loop
70    For(ForLoop),
71    /// While loop
72    While(Condition, Vec<Self>),
73    /// Function call
74    Call(String, Vec<Expression>),
75    /// Delay
76    Delay(Expression, Vec<QubitRef>),
77}
78
79/// Gate application
80#[derive(Debug, Clone, PartialEq)]
81pub struct QasmGate {
82    /// Gate name
83    pub name: String,
84    /// Parameters (angles, etc.)
85    pub params: Vec<Expression>,
86    /// Qubit operands
87    pub qubits: Vec<QubitRef>,
88    /// Control modifier
89    pub control: Option<usize>,
90    /// Inverse modifier
91    pub inverse: bool,
92    /// Power modifier
93    pub power: Option<Expression>,
94}
95
96/// Qubit reference
97#[derive(Debug, Clone, PartialEq, Eq)]
98pub enum QubitRef {
99    /// Single qubit: reg\[index\]
100    Single { register: String, index: usize },
101    /// Register slice: reg\[start:end\]
102    Slice {
103        register: String,
104        start: usize,
105        end: usize,
106    },
107    /// Entire register: reg
108    Register(String),
109}
110
111/// Measurement operation
112#[derive(Debug, Clone, PartialEq, Eq)]
113pub struct Measurement {
114    /// Qubits to measure
115    pub qubits: Vec<QubitRef>,
116    /// Classical bits to store results
117    pub targets: Vec<ClassicalRef>,
118}
119
120/// Classical bit reference
121#[derive(Debug, Clone, PartialEq, Eq)]
122pub enum ClassicalRef {
123    /// Single bit: reg\[index\]
124    Single { register: String, index: usize },
125    /// Register slice: reg\[start:end\]
126    Slice {
127        register: String,
128        start: usize,
129        end: usize,
130    },
131    /// Entire register: reg
132    Register(String),
133}
134
135/// Expression types
136#[derive(Debug, Clone, PartialEq)]
137pub enum Expression {
138    /// Literal value
139    Literal(Literal),
140    /// Variable reference
141    Variable(String),
142    /// Binary operation
143    Binary(BinaryOp, Box<Self>, Box<Self>),
144    /// Unary operation
145    Unary(UnaryOp, Box<Self>),
146    /// Function call
147    Function(String, Vec<Self>),
148    /// Array index
149    Index(String, Box<Self>),
150}
151
152/// Literal values
153#[derive(Debug, Clone, PartialEq)]
154pub enum Literal {
155    /// Integer
156    Integer(i64),
157    /// Floating point
158    Float(f64),
159    /// Boolean
160    Bool(bool),
161    /// String
162    String(String),
163    /// Pi constant
164    Pi,
165    /// Euler's number
166    Euler,
167    /// Tau (2*pi)
168    Tau,
169}
170
171/// Binary operators
172#[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/// Unary operators
197#[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/// Condition for control flow
214#[derive(Debug, Clone, PartialEq)]
215pub struct Condition {
216    /// Left operand
217    pub left: Expression,
218    /// Comparison operator
219    pub op: ComparisonOp,
220    /// Right operand
221    pub right: Expression,
222}
223
224/// Comparison operators
225#[derive(Debug, Clone, Copy, PartialEq, Eq)]
226pub enum ComparisonOp {
227    Eq,
228    Ne,
229    Lt,
230    Le,
231    Gt,
232    Ge,
233}
234
235/// For loop structure
236#[derive(Debug, Clone, PartialEq)]
237pub struct ForLoop {
238    /// Loop variable
239    pub variable: String,
240    /// Start value
241    pub start: Expression,
242    /// End value
243    pub end: Expression,
244    /// Step value (optional)
245    pub step: Option<Expression>,
246    /// Loop body
247    pub body: Vec<QasmStatement>,
248}
249
250// Display implementations for pretty printing
251impl 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}