Skip to content

Commit

Permalink
Better handling for invalid QASM register names (#1100)
Browse files Browse the repository at this point in the history
* Better handling for invalid QASM register names

* Wrap long lines

* wrap long lines

* Fix type error
  • Loading branch information
yao-cqc authored Oct 27, 2023
1 parent 054a624 commit 0fc99a5
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 1 deletion.
24 changes: 23 additions & 1 deletion pytket/pytket/qasm/qasm.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,11 +223,19 @@ class QASMUnsupportedError(Exception):
}

unit_regex = re.compile(r"([a-z][a-zA-Z0-9_]*)\[([\d]+)\]")
regname_regex = re.compile(r"^[a-z][a-zA-Z0-9_]*$")


def _extract_reg(var: Token) -> Tuple[str, int]:
match = unit_regex.match(var.value)
assert match is not None
if match is None:
raise QASMParseError(
f"Invalid register definition '{var.value}'. Register definitions "
"must follow the pattern '<name> [<size in integer>]'. "
"For example, 'q [5]'. QASM register names must begin with a "
"lowercase letter and may only contain lowercase and uppercase "
"letters, numbers, and underscores."
)
return match.group(1), int(match.group(2))


Expand Down Expand Up @@ -1256,8 +1264,22 @@ def __init__(
self.qregs = _retrieve_registers(cast(list[UnitID], qubits), QubitRegister)
self.cregs = _retrieve_registers(cast(list[UnitID], bits), BitRegister)
for reg in self.qregs.values():
if regname_regex.match(reg.name) is None:
raise QASMUnsupportedError(
f"Invalid register name '{reg.name}'. QASM register names must "
"begin with a lowercase letter and may only contain lowercase "
"and uppercase letters, numbers, and underscores. "
"Try renaming the register with `rename_units` first."
)
self.strings.add_string(f"qreg {reg.name}[{reg.size}];\n")
for bit_reg in self.cregs.values():
if regname_regex.match(bit_reg.name) is None:
raise QASMUnsupportedError(
f"Invalid register name '{bit_reg.name}'. QASM register names "
"must begin with a lowercase letter and may only contain "
"lowercase and uppercase letters, numbers, and underscores. "
"Try renaming the register with `rename_units` first."
)
self.strings.add_string(f"creg {bit_reg.name}[{bit_reg.size}];\n")
else:
# gate definition, no header necessary for file
Expand Down
24 changes: 24 additions & 0 deletions pytket/tests/qasm_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,29 @@ def test_classical_expbox_arg_order() -> None:
arg_index += 1


def test_register_name_check() -> None:
# register names must have the expression [a-z][a-zA-Z0-9_]*
qasm = """
OPENQASM 2.0;
include "hqslib1.inc";
qreg Q[1];
"""
with pytest.raises(QASMParseError) as e:
circ = circuit_from_qasm_str(qasm)
err_msg = "Invalid register definition 'Q[1]'"
assert err_msg in str(e.value)

c = Circuit()
qb = Qubit("Q", 0)
c.add_qubit(qb)
c.H(qb)
with pytest.raises(QASMUnsupportedError) as e2:
qasm = circuit_to_qasm_str(c)
err_msg = "Invalid register name 'Q'"
assert err_msg in str(e2.value)


if __name__ == "__main__":
test_qasm_correct()
test_qasm_qubit()
Expand Down Expand Up @@ -901,3 +924,4 @@ def test_classical_expbox_arg_order() -> None:
test_tk2_definition()
test_rxxyyzz_conversion()
test_classical_expbox_arg_order()
test_register_name_check()

0 comments on commit 0fc99a5

Please sign in to comment.