Initial import
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
# Task 4 — `CircuitAnalyzer` (AST-based gate listing)
|
||||
|
||||
> **Index:** [README](README.md). **Spec:** [design](../../specs/2026-04-29-quantum-tutor-design.md).
|
||||
|
||||
## Goal
|
||||
|
||||
Expose AST-based gate enumeration as a public utility so `explain_result` (Task 8) and any other consumer can iterate gates without re-parsing or string-matching the QASM source. Wraps the AST traversal already present in `executor::extract_gate_ops`.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Task 0 merged.
|
||||
|
||||
## Files
|
||||
|
||||
- Create: `src/circuit_analyzer.rs`
|
||||
- Modify: `src/executor.rs` (add public `list_gate_calls`)
|
||||
- Modify: `src/lib.rs`
|
||||
|
||||
## Steps
|
||||
|
||||
- [ ] **Step 1: Create `src/circuit_analyzer.rs` with failing tests**
|
||||
|
||||
```rust
|
||||
//! Pure AST-based gate listing for OpenQASM 3.0 circuits.
|
||||
|
||||
use crate::error::BridgeError;
|
||||
use crate::types::CircuitSource;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct GateCallInfo {
|
||||
pub name: String,
|
||||
pub params: Vec<f64>,
|
||||
pub qubits: Vec<usize>,
|
||||
}
|
||||
|
||||
pub struct CircuitAnalyzer;
|
||||
|
||||
impl CircuitAnalyzer {
|
||||
pub fn list_gates(source: &CircuitSource) -> Result<Vec<GateCallInfo>, BridgeError> {
|
||||
crate::executor::list_gate_calls(source)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const BELL: &str = "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc = measure q;";
|
||||
|
||||
#[test]
|
||||
fn list_gates_for_bell_returns_h_then_cx() {
|
||||
let gates = CircuitAnalyzer::list_gates(&CircuitSource(BELL.into())).unwrap();
|
||||
assert_eq!(gates.len(), 2);
|
||||
assert_eq!(gates[0].name, "h");
|
||||
assert_eq!(gates[0].qubits, vec![0]);
|
||||
assert_eq!(gates[1].name, "cx");
|
||||
assert_eq!(gates[1].qubits, vec![0, 1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_gates_ignores_measure() {
|
||||
let gates = CircuitAnalyzer::list_gates(&CircuitSource(BELL.into())).unwrap();
|
||||
assert!(gates.iter().all(|g| g.name != "measure"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_gates_returns_empty_for_circuit_with_no_gates() {
|
||||
let identity = "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[1] q;\nbit[1] c;\nc = measure q;";
|
||||
let gates = CircuitAnalyzer::list_gates(&CircuitSource(identity.into())).unwrap();
|
||||
assert!(gates.is_empty());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Expose `list_gate_calls` in `src/executor.rs`**
|
||||
|
||||
Add the public function near the existing `extract_gate_ops` helper (or below it). Reuses the same parser path as `LocalSimulator::run`.
|
||||
|
||||
```rust
|
||||
use crate::circuit_analyzer::GateCallInfo;
|
||||
|
||||
/// Public AST-based gate enumeration. Reuses the parser path of `run`.
|
||||
pub fn list_gate_calls(source: &CircuitSource) -> Result<Vec<GateCallInfo>, BridgeError> {
|
||||
let parse_result = parse_source_string(&source.0, Some("circuit.qasm"), None::<&[&str]>);
|
||||
if parse_result.any_syntax_errors() {
|
||||
return Err(BridgeError::Simulation("circuit contains syntax errors".into()));
|
||||
}
|
||||
let context = parse_result.take_context();
|
||||
let symbol_table = context.symbol_table();
|
||||
let program = context.program();
|
||||
let (_, register_offsets) = build_register_map(program, symbol_table);
|
||||
let ops = extract_gate_ops(program, symbol_table, ®ister_offsets)?;
|
||||
Ok(ops
|
||||
.into_iter()
|
||||
.map(|(name, params, qubits)| GateCallInfo { name, params, qubits })
|
||||
.collect())
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Register `circuit_analyzer` in `src/lib.rs`**
|
||||
|
||||
```rust
|
||||
pub mod circuit_analyzer;
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Run tests**
|
||||
|
||||
```bash
|
||||
cargo test circuit_analyzer::tests 2>&1 | grep -E "test result|FAILED"
|
||||
```
|
||||
|
||||
Expected: `test result: ok. 3 passed`.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add src/circuit_analyzer.rs src/executor.rs src/lib.rs
|
||||
git commit -m "feat: add CircuitAnalyzer for AST-based gate enumeration"
|
||||
```
|
||||
Reference in New Issue
Block a user