From 8baa0cfa129190ed7ea5d1fb440bf43f44189a43 Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Thu, 14 Dec 2023 17:10:02 +0000 Subject: [PATCH 1/5] Support stabilised syntax for OpenQASM 3 `switch` The OpenQASM 3 project made some changes to the preliminary syntax of the `switch` statement, merging the final version in openqasm/openqasm#463. This commit adds support for the new syntax, making it available by default while still supporting the experimental flag to enable the preliminary syntax. Support for the old flag is necessary to allow Qiskit to continue to interoperate with other tooling that still assumes the preliminary format (we know that at least the IBM QSS compiler is in this position right now), and in general should hopefully not be too onerous to continue to support. --- qiskit/qasm3/ast.py | 23 +- qiskit/qasm3/experimental.py | 42 ++- qiskit/qasm3/exporter.py | 55 ++-- qiskit/qasm3/printer.py | 34 +- .../qasm3-stable-switch-61a10036d1587778.yaml | 16 + test/python/qasm3/test_export.py | 299 ++++++++++++++++-- 6 files changed, 421 insertions(+), 48 deletions(-) create mode 100644 releasenotes/notes/qasm3-stable-switch-61a10036d1587778.yaml diff --git a/qiskit/qasm3/ast.py b/qiskit/qasm3/ast.py index e81fcb1d9dd2..7e2f946ce2a3 100644 --- a/qiskit/qasm3/ast.py +++ b/qiskit/qasm3/ast.py @@ -596,11 +596,30 @@ class DefaultCase(Expression): """An object representing the `default` special label in switch statements.""" -class SwitchStatement(Statement): - """AST node for the proposed 'switch-case' extension to OpenQASM 3.""" +class SwitchStatementV1(Statement): + """AST node for the proposed 'switch-case' extension to OpenQASM 3. + + The stabilised form of the syntax instead uses :class:`.SwitchStatement`.""" def __init__( self, target: Expression, cases: Iterable[Tuple[Iterable[Expression], ProgramBlock]] ): self.target = target self.cases = [(tuple(values), case) for values, case in cases] + + +class SwitchStatement(Statement): + """AST node for the stable 'switch' statement of OpenQASM 3. + + The only real difference from an AST form is that the default is required to be separate; it + cannot be joined with other cases (even though that's meaningless, the V1 syntax permitted it).""" + + def __init__( + self, + target: Expression, + cases: Iterable[Tuple[Iterable[Expression], ProgramBlock]], + default: Optional[ProgramBlock] = None, + ): + self.target = target + self.cases = [(tuple(values), case) for values, case in cases] + self.default = default diff --git a/qiskit/qasm3/experimental.py b/qiskit/qasm3/experimental.py index f52bca12c18b..20e51a7b3623 100644 --- a/qiskit/qasm3/experimental.py +++ b/qiskit/qasm3/experimental.py @@ -27,4 +27,44 @@ class ExperimentalFeatures(enum.Flag): SWITCH_CASE_V1 = enum.auto() """Support exporting switch-case statements as proposed by https://github.com/openqasm/openqasm/pull/463 at `commit bfa787aa3078 - `__.""" + `__. + + These have the output format: + + .. code-block:: qasm3 + + switch (i) { + case 0: + case 1: + x $0; + break; + + case 2: { + z $0; + } + break; + + default: { + cx $0, $1; + } + break; + } + + This differs from the syntax of the ``switch`` statement as stabilized. If this flag is not + passed, then the parser will instead output using the stabilized syntax, which would render the + same example above as: + + .. code-block:: qasm3 + + switch (i) { + case 0, 1 { + x $0; + } + case 2 { + z $0; + } + default { + cx $0, $1; + } + } + """ diff --git a/qiskit/qasm3/exporter.py b/qiskit/qasm3/exporter.py index 44e46f9bea80..9ab35a97a8d5 100644 --- a/qiskit/qasm3/exporter.py +++ b/qiskit/qasm3/exporter.py @@ -833,14 +833,6 @@ def build_if_statement(self, instruction: CircuitInstruction) -> ast.BranchingSt def build_switch_statement(self, instruction: CircuitInstruction) -> Iterable[ast.Statement]: """Build a :obj:`.SwitchCaseOp` into a :class:`.ast.SwitchStatement`.""" - if ExperimentalFeatures.SWITCH_CASE_V1 not in self.experimental: - raise QASM3ExporterError( - "'switch' statements are not stabilized in OpenQASM 3 yet." - " To enable experimental support, set the flag" - " 'ExperimentalFeatures.SWITCH_CASE_V1' in the 'experimental' keyword" - " argument of the exporter." - ) - real_target = self.build_expression(expr.lift(instruction.operation.target)) global_scope = self.global_scope() target = self._reserve_variable_name( @@ -850,21 +842,48 @@ def build_switch_statement(self, instruction: CircuitInstruction) -> Iterable[as ast.ClassicalDeclaration(ast.IntType(), target, None) ) - def case(values, case_block): - values = [ - ast.DefaultCase() if v is CASE_DEFAULT else self.build_integer(v) for v in values + if ExperimentalFeatures.SWITCH_CASE_V1 in self.experimental: + # In this case, defaults can be folded in with other cases (useless as that is). + + def case(values, case_block): + values = [ + ast.DefaultCase() if v is CASE_DEFAULT else self.build_integer(v) + for v in values + ] + self.push_scope(case_block, instruction.qubits, instruction.clbits) + case_body = self.build_program_block(case_block.data) + self.pop_scope() + return values, case_body + + return [ + ast.AssignmentStatement(target, real_target), + ast.SwitchStatementV1( + target, + ( + case(values, block) + for values, block in instruction.operation.cases_specifier() + ), + ), ] - self.push_scope(case_block, instruction.qubits, instruction.clbits) - case_body = self.build_program_block(case_block.data) + + # Handle the stabilised syntax. + cases = [] + default = None + for values, block in instruction.operation.cases_specifier(): + self.push_scope(block, instruction.qubits, instruction.clbits) + case_body = self.build_program_block(block.data) self.pop_scope() - return values, case_body + if CASE_DEFAULT in values: + # Even if it's mixed in with other cases, we can skip them and only output the + # `default` since that's valid and execution will be the same; the evaluation of + # case labels can't have side effects. + default = case_body + continue + cases.append(([self.build_integer(value) for value in values], case_body)) return [ ast.AssignmentStatement(target, real_target), - ast.SwitchStatement( - target, - (case(values, block) for values, block in instruction.operation.cases_specifier()), - ), + ast.SwitchStatement(target, cases, default=default), ] def build_while_loop(self, instruction: CircuitInstruction) -> ast.WhileLoopStatement: diff --git a/qiskit/qasm3/printer.py b/qiskit/qasm3/printer.py index fee68824f0c8..cfb2ebdcd549 100644 --- a/qiskit/qasm3/printer.py +++ b/qiskit/qasm3/printer.py @@ -504,13 +504,33 @@ def _visit_WhileLoopStatement(self, node: ast.WhileLoopStatement) -> None: self._end_line() def _visit_SwitchStatement(self, node: ast.SwitchStatement) -> None: - if ExperimentalFeatures.SWITCH_CASE_V1 not in self._experimental: - raise QASM3ExporterError( - "'switch' statements are not stabilised in OpenQASM 3 yet." - " To enable experimental support, set the flag" - " 'ExperimentalFeatures.SWITCH_CASE_V1' in the 'experimental' keyword" - " argument of the printer." - ) + self._start_line() + self.stream.write("switch (") + self.visit(node.target) + self.stream.write(") {") + self._end_line() + self._current_indent += 1 + for labels, case in node.cases: + if not labels: + continue + self._start_line() + self.stream.write("case ") + self._visit_sequence(labels, separator=", ") + self.stream.write(" ") + self.visit(case) + self._end_line() + if node.default is not None: + self._start_line() + self.stream.write("default ") + self.visit(node.default) + self._end_line() + self._current_indent -= 1 + self._start_line() + self.stream.write("}") + self._end_line() + + def _visit_SwitchStatementV1(self, node: ast.SwitchStatementV1) -> None: + # This is the pre-release syntax, which had lots of extra `break` statements in it. self._start_line() self.stream.write("switch (") self.visit(node.target) diff --git a/releasenotes/notes/qasm3-stable-switch-61a10036d1587778.yaml b/releasenotes/notes/qasm3-stable-switch-61a10036d1587778.yaml new file mode 100644 index 000000000000..9cf90556390a --- /dev/null +++ b/releasenotes/notes/qasm3-stable-switch-61a10036d1587778.yaml @@ -0,0 +1,16 @@ +--- +features: + - | + The OpenQASM 3 exporter (see :func:`~.qasm3.dump` and :func:`~.qasm3.dumps` functions in + :mod:`qiskit.qasm3`) now supports the stabilised syntax of the ``switch`` statement in OpenQASM 3 + by default. The pre-certification syntax of the ``switch`` statement is still available by + using the :attr:`.ExperimentalFeatures.SWITCH_CASE_V1` flag in the ``experimental`` argument of + the exporter. There is no feature flag required for the stabilised syntax, but if you are + interfacing with other tooling that is not yet updated, you may need to pass the experimental + flag. + + The syntax of the stabilised form is slightly different with regards to terminating ``break`` + statements (no longer required nor permitted), and multiple cases are now combined into a single + ``case`` line, rather than using C-style fall-through. For more detail, see `the OpenQASM 3 + documentation on the switch-case construct + `__. diff --git a/test/python/qasm3/test_export.py b/test/python/qasm3/test_export.py index 0f64fa6ba12b..505c9f9ec53c 100644 --- a/test/python/qasm3/test_export.py +++ b/test/python/qasm3/test_export.py @@ -2037,22 +2037,279 @@ def test_unusual_conditions(self): }""" self.assertEqual(dumps(qc).strip(), expected.strip()) + def test_switch_clbit(self): + """Test that a switch statement can be constructed with a bit as a condition.""" + qubit = Qubit() + clbit = Clbit() + case1 = QuantumCircuit([qubit, clbit]) + case1.x(0) + case2 = QuantumCircuit([qubit, clbit]) + case2.z(0) + circuit = QuantumCircuit([qubit, clbit]) + circuit.switch(clbit, [(True, case1), (False, case2)], [0], [0]) + + test = dumps(circuit) + expected = """\ +OPENQASM 3; +include "stdgates.inc"; +bit _bit0; +int switch_dummy; +qubit _qubit0; +switch_dummy = _bit0; +switch (switch_dummy) { + case 1 { + x _qubit0; + } + case 0 { + z _qubit0; + } +} +""" + self.assertEqual(test, expected) + + def test_switch_register(self): + """Test that a switch statement can be constructed with a register as a + condition.""" + qubit = Qubit() + creg = ClassicalRegister(2, "c") + case1 = QuantumCircuit([qubit], creg) + case1.x(0) + case2 = QuantumCircuit([qubit], creg) + case2.y(0) + case3 = QuantumCircuit([qubit], creg) + case3.z(0) + + circuit = QuantumCircuit([qubit], creg) + circuit.switch(creg, [(0, case1), (1, case2), (2, case3)], [0], circuit.clbits) + + test = dumps(circuit) + expected = """\ +OPENQASM 3; +include "stdgates.inc"; +bit[2] c; +int switch_dummy; +qubit _qubit0; +switch_dummy = c; +switch (switch_dummy) { + case 0 { + x _qubit0; + } + case 1 { + y _qubit0; + } + case 2 { + z _qubit0; + } +} +""" + self.assertEqual(test, expected) + + def test_switch_with_default(self): + """Test that a switch statement can be constructed with a default case at the + end.""" + qubit = Qubit() + creg = ClassicalRegister(2, "c") + case1 = QuantumCircuit([qubit], creg) + case1.x(0) + case2 = QuantumCircuit([qubit], creg) + case2.y(0) + case3 = QuantumCircuit([qubit], creg) + case3.z(0) + + circuit = QuantumCircuit([qubit], creg) + circuit.switch(creg, [(0, case1), (1, case2), (CASE_DEFAULT, case3)], [0], circuit.clbits) + + test = dumps(circuit) + expected = """\ +OPENQASM 3; +include "stdgates.inc"; +bit[2] c; +int switch_dummy; +qubit _qubit0; +switch_dummy = c; +switch (switch_dummy) { + case 0 { + x _qubit0; + } + case 1 { + y _qubit0; + } + default { + z _qubit0; + } +} +""" + self.assertEqual(test, expected) + + def test_switch_multiple_cases_to_same_block(self): + """Test that it is possible to add multiple cases that apply to the same block, if they are + given as a compound value. This is an allowed special case of block fall-through.""" + qubit = Qubit() + creg = ClassicalRegister(2, "c") + case1 = QuantumCircuit([qubit], creg) + case1.x(0) + case2 = QuantumCircuit([qubit], creg) + case2.y(0) + + circuit = QuantumCircuit([qubit], creg) + circuit.switch(creg, [(0, case1), ((1, 2), case2)], [0], circuit.clbits) + + test = dumps(circuit) + expected = """\ +OPENQASM 3; +include "stdgates.inc"; +bit[2] c; +int switch_dummy; +qubit _qubit0; +switch_dummy = c; +switch (switch_dummy) { + case 0 { + x _qubit0; + } + case 1, 2 { + y _qubit0; + } +} +""" + self.assertEqual(test, expected) + + def test_multiple_switches_dont_clash_on_dummy(self): + """Test that having more than one switch statement in the circuit doesn't cause naming + clashes in the dummy integer value used.""" + qubit = Qubit() + creg = ClassicalRegister(2, "switch_dummy") + case1 = QuantumCircuit([qubit], creg) + case1.x(0) + case2 = QuantumCircuit([qubit], creg) + case2.y(0) + + circuit = QuantumCircuit([qubit], creg) + circuit.switch(creg, [(0, case1), ((1, 2), case2)], [0], circuit.clbits) + circuit.switch(creg, [(0, case1), ((1, 2), case2)], [0], circuit.clbits) + + test = dumps(circuit) + expected = """\ +OPENQASM 3; +include "stdgates.inc"; +bit[2] switch_dummy; +int switch_dummy__generated0; +int switch_dummy__generated1; +qubit _qubit0; +switch_dummy__generated0 = switch_dummy; +switch (switch_dummy__generated0) { + case 0 { + x _qubit0; + } + case 1, 2 { + y _qubit0; + } +} +switch_dummy__generated1 = switch_dummy; +switch (switch_dummy__generated1) { + case 0 { + x _qubit0; + } + case 1, 2 { + y _qubit0; + } +} +""" + self.assertEqual(test, expected) + + def test_switch_nested_in_if(self): + """Test that the switch statement works when in a nested scope, including the dummy + classical variable being declared globally. This isn't necessary in the OQ3 language, but + it is universally valid and the IBM QSS stack prefers that. They're our primary consumers + of OQ3 strings, so it's best to play nicely with them.""" + qubit = Qubit() + creg = ClassicalRegister(2, "c") + case1 = QuantumCircuit([qubit], creg) + case1.x(0) + case2 = QuantumCircuit([qubit], creg) + case2.y(0) + + body = QuantumCircuit([qubit], creg) + body.switch(creg, [(0, case1), ((1, 2), case2)], [0], body.clbits) + + circuit = QuantumCircuit([qubit], creg) + circuit.if_else((creg, 1), body.copy(), body, [0], body.clbits) + + test = dumps(circuit) + expected = """\ +OPENQASM 3; +include "stdgates.inc"; +bit[2] c; +int switch_dummy; +int switch_dummy__generated0; +qubit _qubit0; +if (c == 1) { + switch_dummy = c; + switch (switch_dummy) { + case 0 { + x _qubit0; + } + case 1, 2 { + y _qubit0; + } + } +} else { + switch_dummy__generated0 = c; + switch (switch_dummy__generated0) { + case 0 { + x _qubit0; + } + case 1, 2 { + y _qubit0; + } + } +} +""" + self.assertEqual(test, expected) + + def test_switch_expr_target(self): + """Simple test that the target of `switch` can be `Expr` nodes.""" + bits = [Qubit(), Clbit()] + cr = ClassicalRegister(2, "cr") + case0 = QuantumCircuit(1) + case0.x(0) + case1 = QuantumCircuit(1) + case1.x(0) + qc = QuantumCircuit(bits, cr) + qc.switch(expr.logic_not(bits[1]), [(False, case0)], [0], []) + qc.switch(expr.bit_and(cr, 3), [(3, case1)], [0], []) + + expected = """\ +OPENQASM 3; +include "stdgates.inc"; +bit _bit0; +bit[2] cr; +int switch_dummy; +int switch_dummy__generated0; +qubit _qubit0; +switch_dummy = !_bit0; +switch (switch_dummy) { + case 0 { + x _qubit0; + } +} +switch_dummy__generated0 = cr & 3; +switch (switch_dummy__generated0) { + case 3 { + x _qubit0; + } +} +""" + test = dumps(qc) + self.assertEqual(test, expected) + class TestExperimentalFeatures(QiskitTestCase): """Tests of features that are hidden behind experimental flags.""" maxDiff = None - def test_switch_forbidden_without_flag(self): - """Omitting the feature flag should raise an error.""" - case = QuantumCircuit(1) - circuit = QuantumCircuit(1, 1) - circuit.switch(circuit.clbits[0], [((True, False), case)], [0], []) - with self.assertRaisesRegex(QASM3ExporterError, "'switch' statements are not stabilized"): - dumps(circuit) - - def test_switch_clbit(self): - """Test that a switch statement can be constructed with a bit as a condition.""" + def test_switch_v1_clbit(self): + """Test that a prerelease switch statement can be constructed with a bit as a condition.""" qubit = Qubit() clbit = Clbit() case1 = QuantumCircuit([qubit, clbit]) @@ -2083,8 +2340,9 @@ def test_switch_clbit(self): """ self.assertEqual(test, expected) - def test_switch_register(self): - """Test that a switch statement can be constructed with a register as a condition.""" + def test_switch_v1_register(self): + """Test that a prerelease switch statement can be constructed with a register as a + condition.""" qubit = Qubit() creg = ClassicalRegister(2, "c") case1 = QuantumCircuit([qubit], creg) @@ -2122,8 +2380,9 @@ def test_switch_register(self): """ self.assertEqual(test, expected) - def test_switch_with_default(self): - """Test that a switch statement can be constructed with a default case at the end.""" + def test_switch_v1_with_default(self): + """Test that a prerelease switch statement can be constructed with a default case at the + end.""" qubit = Qubit() creg = ClassicalRegister(2, "c") case1 = QuantumCircuit([qubit], creg) @@ -2161,7 +2420,7 @@ def test_switch_with_default(self): """ self.assertEqual(test, expected) - def test_switch_multiple_cases_to_same_block(self): + def test_switch_v1_multiple_cases_to_same_block(self): """Test that it is possible to add multiple cases that apply to the same block, if they are given as a compound value. This is an allowed special case of block fall-through.""" qubit = Qubit() @@ -2197,8 +2456,8 @@ def test_switch_multiple_cases_to_same_block(self): self.assertEqual(test, expected) def test_multiple_switches_dont_clash_on_dummy(self): - """Test that having more than one switch statement in the circuit doesn't cause naming - clashes in the dummy integer value used.""" + """Test that having more than one prerelease switch statement in the circuit doesn't cause + naming clashes in the dummy integer value used.""" qubit = Qubit() creg = ClassicalRegister(2, "switch_dummy") case1 = QuantumCircuit([qubit], creg) @@ -2245,7 +2504,7 @@ def test_multiple_switches_dont_clash_on_dummy(self): """ self.assertEqual(test, expected) - def test_switch_nested_in_if(self): + def test_switch_v1_nested_in_if(self): """Test that the switch statement works when in a nested scope, including the dummy classical variable being declared globally. This isn't necessary in the OQ3 language, but it is universally valid and the IBM QSS stack prefers that. They're our primary consumers @@ -2301,8 +2560,8 @@ def test_switch_nested_in_if(self): """ self.assertEqual(test, expected) - def test_expr_target(self): - """Simple test that the target of `switch` can be `Expr` nodes.""" + def test_switch_v1_expr_target(self): + """Simple test that the target of prerelease `switch` can be `Expr` nodes.""" bits = [Qubit(), Clbit()] cr = ClassicalRegister(2, "cr") case0 = QuantumCircuit(1) From afd32ae27f569f57e19450f60c975e28cac0d2c7 Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Thu, 14 Dec 2023 17:58:04 +0000 Subject: [PATCH 2/5] Fix lint --- qiskit/qasm3/experimental.py | 4 ++-- qiskit/qasm3/printer.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/qiskit/qasm3/experimental.py b/qiskit/qasm3/experimental.py index 20e51a7b3623..8e925acb5f2f 100644 --- a/qiskit/qasm3/experimental.py +++ b/qiskit/qasm3/experimental.py @@ -31,7 +31,7 @@ class ExperimentalFeatures(enum.Flag): These have the output format: - .. code-block:: qasm3 + .. code-block:: switch (i) { case 0: @@ -54,7 +54,7 @@ class ExperimentalFeatures(enum.Flag): passed, then the parser will instead output using the stabilized syntax, which would render the same example above as: - .. code-block:: qasm3 + .. code-block:: switch (i) { case 0, 1 { diff --git a/qiskit/qasm3/printer.py b/qiskit/qasm3/printer.py index cfb2ebdcd549..bdf1915f1c1a 100644 --- a/qiskit/qasm3/printer.py +++ b/qiskit/qasm3/printer.py @@ -18,7 +18,6 @@ from . import ast from .experimental import ExperimentalFeatures -from .exceptions import QASM3ExporterError # Precedence and associativity table for prefix, postfix and infix operators. The rules are a # lookup table of two-tuples; the "binding power" of the operator to the left and to the right. From 41fdf36e9e8eeeb3fb5e959ba5f621af1c6edbf2 Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Wed, 31 Jan 2024 20:15:15 +0000 Subject: [PATCH 3/5] :us: Co-authored-by: Matthew Treinish --- qiskit/qasm3/ast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/qasm3/ast.py b/qiskit/qasm3/ast.py index 7e2f946ce2a3..97d285df6e68 100644 --- a/qiskit/qasm3/ast.py +++ b/qiskit/qasm3/ast.py @@ -599,7 +599,7 @@ class DefaultCase(Expression): class SwitchStatementV1(Statement): """AST node for the proposed 'switch-case' extension to OpenQASM 3. - The stabilised form of the syntax instead uses :class:`.SwitchStatement`.""" + The stabilized form of the syntax instead uses :class:`.SwitchStatement`.""" def __init__( self, target: Expression, cases: Iterable[Tuple[Iterable[Expression], ProgramBlock]] From 089165901da2c3c8435d19b85797cdd16e82640f Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Wed, 31 Jan 2024 20:17:34 +0000 Subject: [PATCH 4/5] Make AST node more descriptive --- qiskit/qasm3/ast.py | 5 +++-- qiskit/qasm3/exporter.py | 2 +- qiskit/qasm3/printer.py | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/qiskit/qasm3/ast.py b/qiskit/qasm3/ast.py index 97d285df6e68..9b8271ce7fb7 100644 --- a/qiskit/qasm3/ast.py +++ b/qiskit/qasm3/ast.py @@ -596,8 +596,9 @@ class DefaultCase(Expression): """An object representing the `default` special label in switch statements.""" -class SwitchStatementV1(Statement): - """AST node for the proposed 'switch-case' extension to OpenQASM 3. +class SwitchStatementPreview(Statement): + """AST node for the proposed 'switch-case' extension to OpenQASM 3, before the syntax was + stabilized. This corresponds to the :attr:`.ExperimentalFeatures.SWITCH_CASE_V1` logic. The stabilized form of the syntax instead uses :class:`.SwitchStatement`.""" diff --git a/qiskit/qasm3/exporter.py b/qiskit/qasm3/exporter.py index 9ab35a97a8d5..7ae0c321551f 100644 --- a/qiskit/qasm3/exporter.py +++ b/qiskit/qasm3/exporter.py @@ -857,7 +857,7 @@ def case(values, case_block): return [ ast.AssignmentStatement(target, real_target), - ast.SwitchStatementV1( + ast.SwitchStatementPreview( target, ( case(values, block) diff --git a/qiskit/qasm3/printer.py b/qiskit/qasm3/printer.py index bdf1915f1c1a..94d12a7ecff6 100644 --- a/qiskit/qasm3/printer.py +++ b/qiskit/qasm3/printer.py @@ -528,7 +528,7 @@ def _visit_SwitchStatement(self, node: ast.SwitchStatement) -> None: self.stream.write("}") self._end_line() - def _visit_SwitchStatementV1(self, node: ast.SwitchStatementV1) -> None: + def _visit_SwitchStatementPreview(self, node: ast.SwitchStatementPreview) -> None: # This is the pre-release syntax, which had lots of extra `break` statements in it. self._start_line() self.stream.write("switch (") From a54928076ab129883fec9984b08d28ab96778c69 Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Wed, 31 Jan 2024 20:48:25 +0000 Subject: [PATCH 5/5] Use correct version number --- test/python/qasm3/test_export.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/python/qasm3/test_export.py b/test/python/qasm3/test_export.py index 753b8a660148..3bb1667992a1 100644 --- a/test/python/qasm3/test_export.py +++ b/test/python/qasm3/test_export.py @@ -2050,7 +2050,7 @@ def test_switch_clbit(self): test = dumps(circuit) expected = """\ -OPENQASM 3; +OPENQASM 3.0; include "stdgates.inc"; bit _bit0; int switch_dummy; @@ -2084,7 +2084,7 @@ def test_switch_register(self): test = dumps(circuit) expected = """\ -OPENQASM 3; +OPENQASM 3.0; include "stdgates.inc"; bit[2] c; int switch_dummy; @@ -2121,7 +2121,7 @@ def test_switch_with_default(self): test = dumps(circuit) expected = """\ -OPENQASM 3; +OPENQASM 3.0; include "stdgates.inc"; bit[2] c; int switch_dummy; @@ -2156,7 +2156,7 @@ def test_switch_multiple_cases_to_same_block(self): test = dumps(circuit) expected = """\ -OPENQASM 3; +OPENQASM 3.0; include "stdgates.inc"; bit[2] c; int switch_dummy; @@ -2189,7 +2189,7 @@ def test_multiple_switches_dont_clash_on_dummy(self): test = dumps(circuit) expected = """\ -OPENQASM 3; +OPENQASM 3.0; include "stdgates.inc"; bit[2] switch_dummy; int switch_dummy__generated0; @@ -2236,7 +2236,7 @@ def test_switch_nested_in_if(self): test = dumps(circuit) expected = """\ -OPENQASM 3; +OPENQASM 3.0; include "stdgates.inc"; bit[2] c; int switch_dummy; @@ -2279,7 +2279,7 @@ def test_switch_expr_target(self): qc.switch(expr.bit_and(cr, 3), [(3, case1)], [0], []) expected = """\ -OPENQASM 3; +OPENQASM 3.0; include "stdgates.inc"; bit _bit0; bit[2] cr;