cqlib_core/ir/qasm2/ast.rs
1// This code is part of Cqlib.
2//
3// (C) Copyright China Telecom Quantum Group 2026
4//
5// This code is licensed under the Apache License, Version 2.0. You may
6// obtain a copy of this license in the LICENSE.txt file in the root directory
7// of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8//
9// Any modifications or derivative works of this code must retain this
10// copyright notice, and modified files need to carry a notice indicating
11// that they have been altered from the originals.
12
13//! # OpenQASM 2.0 Abstract Syntax Tree (AST)
14//!
15//! This module defines the intermediate representation (IR) for parsing OpenQASM 2.0 quantum
16//! programs. It provides data structures that represent the grammatical elements of the
17//! OpenQASM 2.0 language specification.
18//!
19//! ## Overview
20//!
21//! The AST is structured as a tree of statements that correspond to the quantum circuit
22//! description language defined in the OpenQASM 2.0 specification. Key elements include:
23//!
24//! - **Expressions**: Mathematical expressions for gate parameters (real numbers, integers,
25//! identifiers, binary/ unary operations)
26//! - **Arguments**: Quantum/classical register references (named or indexed)
27//! - **Statements**: Quantum operations, gate declarations, classical operations
28//! - **Program**: Complete OpenQASM program containing version and statements
29//!
30//! ## Example
31//!
32//! ```rust
33//! use cqlib_core::ir::qasm2::ast::{Statement, Argument, Expression};
34//!
35//! // Represents: qreg q[2];
36//! let qreg_stmt = Statement::QReg("q".to_string(), 2);
37//!
38//! // Represents: h q[0];
39//! let h_gate = Statement::CustomGate(
40//! "h".to_string(),
41//! vec![],
42//! vec![Argument::IndexedId("q".to_string(), 0)]
43//! );
44//! ```
45
46/// Represents literal values and expressions in OpenQASM 2.0.
47///
48/// This enum covers all expression types defined in the OpenQASM 2.0 specification:
49/// - Real and integer constants
50/// - Identifier references (variables/parameters)
51/// - Built-in constant `pi`
52/// - Binary operations (arithmetic)
53/// - Unary operations (trigonometric, exponential, etc.)
54#[derive(Debug, Clone, PartialEq)]
55pub enum Expression {
56 /// Real number literal (e.g., `3.14159`, `0.5`)
57 Real(f64),
58 /// Integer literal (e.g., `1`, `2`, `-3`)
59 Integer(i64),
60 /// Identifier reference (parameter name or variable)
61 Id(String),
62 /// Built-in constant pi (π ≈ 3.14159...)
63 Pi,
64 /// Binary operation (e.g., `a + b`, `x * 2`, `pi/2`)
65 BinaryOp(Box<Expression>, OpCode, Box<Expression>),
66 /// Unary operation (e.g., `sin(theta)`, `sqrt(x)`, `-y`)
67 UnaryOp(UnaryOpCode, Box<Expression>),
68}
69
70/// Binary arithmetic operators supported in OpenQASM 2.0 expressions.
71///
72/// These operators follow standard precedence rules and are used within
73/// gate parameter expressions.
74#[derive(Debug, Clone, PartialEq)]
75pub enum OpCode {
76 /// Addition operator (`+`)
77 Add,
78 /// Subtraction operator (`-`)
79 Sub,
80 /// Multiplication operator (`*`)
81 Mul,
82 /// Division operator (`/`)
83 Div,
84 /// Power/exponentiation operator (`^`)
85 Pow,
86}
87
88/// Unary operators (functions) supported in OpenQASM 2.0 expressions.
89///
90/// These include trigonometric functions, exponential/logarithmic functions,
91/// and the negation operator.
92#[derive(Debug, Clone, PartialEq)]
93pub enum UnaryOpCode {
94 /// Sine function: `sin(x)`
95 Sin,
96 /// Cosine function: `cos(x)`
97 Cos,
98 /// Tangent function: `tan(x)`
99 Tan,
100 /// Exponential function: `exp(x)`
101 Exp,
102 /// Natural logarithm: `ln(x)`
103 Ln,
104 /// Square root: `sqrt(x)`
105 Sqrt,
106 /// Arcsine: `asin(x)`
107 Asin,
108 /// Arccosine: `acos(x)`
109 Acos,
110 /// Arctangent: `atan(x)`
111 Atan,
112 /// Negation operator: `-x`
113 Neg,
114}
115
116/// Represents a quantum or classical register argument.
117///
118/// Arguments can be either:
119/// - Named references (entire register): `q` refers to all qubits in register `q`
120/// - Indexed references (single element): `q[0]` refers to the first qubit in register `q`
121#[derive(Debug, Clone, PartialEq)]
122pub enum Argument {
123 /// Named register reference (e.g., `q` in `h q`)
124 Id(String),
125 /// Indexed register reference (e.g., `q[0]` in `cx q[0], q[1]`)
126 IndexedId(String, i64),
127}
128
129/// Top-level statements in an OpenQASM 2.0 program.
130///
131/// Each variant represents a distinct type of statement as defined in the
132/// OpenQASM 2.0 specification, including declarations, quantum operations,
133/// gate definitions, and control flow.
134#[derive(Debug, Clone, PartialEq)]
135pub enum Statement {
136 /// Quantum register declaration: `qreg q[5];`
137 QReg(String, i64),
138 /// Classical register declaration: `creg c[3];`
139 CReg(String, i64),
140 /// Include external file: `include "qelib1.inc";`
141 Include(String),
142 /// Barrier operation: `barrier q[0], q[1];`
143 Barrier(Vec<Argument>),
144 /// Reset operation: `reset q[0];`
145 Reset(Argument),
146 /// Measurement: `measure q[0] -> c[0];`
147 Measure(Argument, Argument),
148 /// Custom gate invocation: `gate_name(params) qubits;`
149 CustomGate(String, Vec<Expression>, Vec<Argument>),
150 /// Opaque gate declaration (no body): `opaque gate_name q;`
151 Opaque(String, Vec<String>, Vec<String>),
152 /// Gate definition with body: `gate gate_name(params) q { ... }`
153 GateDecl(Box<GateDeclData>),
154 /// Conditional execution: `if (c == 1) gate q;`.
155 If(String, i64, Box<Statement>),
156}
157
158/// Data structure holding gate definition content.
159///
160/// This represents the complete gate declaration including:
161/// - Gate name
162/// - Formal parameters (may be empty)
163/// - Formal qubits (the qubits the gate operates on)
164/// - Gate body (sequence of statements)
165#[derive(Debug, Clone, PartialEq)]
166pub struct GateDeclData {
167 /// Name of the gate being defined
168 pub name: String,
169 /// List of parameter names (empty if gate takes no parameters)
170 pub params: Vec<String>,
171 /// List of qubit argument names (the qubits the gate operates on)
172 pub qubits: Vec<String>,
173 /// Gate body: sequence of quantum operations making up the gate
174 pub body: Vec<Statement>,
175}
176
177/// Represents a complete OpenQASM 2.0 program.
178///
179/// This is the root structure containing the version number and
180/// all top-level statements in the program.
181#[derive(Debug, Clone)]
182pub struct OpenQASMProgram {
183 /// OpenQASM version (typically 2.0)
184 pub version: f64,
185 /// List of top-level statements in program order
186 pub statements: Vec<Statement>,
187}