Skip to content

Simple OpenQASM 3.0 expressions and casts #7593

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 336 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 250 commits
Commits
Show all changes
336 commits
Select commit Hold shift + click to select a range
50f106f
Use AnnotatedQueue() to verify execution order
comp-phys-marc May 23, 2025
c2a0c05
Format
comp-phys-marc May 23, 2025
08db20c
Merge branch 'master' into feature/rebased-simple-gates-can-be-executed
comp-phys-marc May 23, 2025
a78d950
Add retrieve_variable() method
comp-phys-marc May 23, 2025
5ad362d
Add dev comment on supported modifier names
comp-phys-marc May 23, 2025
6790579
Add explicit raise for bad modifiers
comp-phys-marc May 23, 2025
8cbb4e8
Clearer NameError message for undeclared vars
comp-phys-marc May 23, 2025
492e1b2
pylint
comp-phys-marc May 23, 2025
314185d
pylint
comp-phys-marc May 23, 2025
267ac8f
Assert instead of raise on bad modifiers
comp-phys-marc May 23, 2025
b3a7dc1
Use an update rather than setting each val in context init
comp-phys-marc May 23, 2025
545ff3a
Remove spy from tests
comp-phys-marc May 23, 2025
4f44322
Merge remote-tracking branch 'origin/feature/rebased-simple-gates-can…
comp-phys-marc May 23, 2025
64fd014
Merge branch 'master' into feature/rebased-simple-gates-can-be-executed
comp-phys-marc May 23, 2025
3bd7808
Import ops
comp-phys-marc May 23, 2025
e280871
Repr qubits using names not ints
comp-phys-marc May 23, 2025
e459523
Run formatter
comp-phys-marc May 23, 2025
2ef8a2c
Use getattr to dispatch handlers
comp-phys-marc May 26, 2025
85ef639
Run formatter
comp-phys-marc May 26, 2025
bfac0fa
PR feedback
comp-phys-marc May 26, 2025
c7d9a93
Support end statements
comp-phys-marc May 26, 2025
e7baeeb
Trigger CI
comp-phys-marc May 26, 2025
61436fd
Variables
comp-phys-marc May 26, 2025
031eb57
Variable declarations, assignments, retrievals
comp-phys-marc May 26, 2025
aa7236c
[WIP] remove pre-compute
comp-phys-marc May 27, 2025
cdfde44
Update docs, tests
comp-phys-marc May 27, 2025
b6b374b
Run formatter
comp-phys-marc May 27, 2025
4dad404
Use functools.singledispatchmethod instead of getattr to dispatch han…
comp-phys-marc May 27, 2025
cd1e498
Run formatter
comp-phys-marc May 27, 2025
2b4ed11
Remove unecessary condition
comp-phys-marc May 27, 2025
09e2497
Revert change
comp-phys-marc May 27, 2025
23809b8
Adopt suggestion to compute number of control wires
comp-phys-marc May 27, 2025
3c72546
Add support for qubit mappings provided by user
comp-phys-marc May 27, 2025
a4e755e
Add integer qubit mapping test
comp-phys-marc May 27, 2025
5599e8d
Support end statements
comp-phys-marc May 27, 2025
7c5f143
Merge remote-tracking branch 'origin/feature/end-statements' into fea…
comp-phys-marc May 27, 2025
fccaf9c
Remove try / catch on import per feedback
comp-phys-marc May 27, 2025
243083b
Support nested modifiers
comp-phys-marc May 27, 2025
bf6d549
Multiple examples of nested mods working
comp-phys-marc May 28, 2025
365a13e
More examples in test of nested mods
comp-phys-marc May 28, 2025
a0e45bd
Qubit label consistency in docs
comp-phys-marc May 28, 2025
d3fb7e0
Remove branch from from_qasm3
comp-phys-marc May 28, 2025
ea82c08
Run formatter
comp-phys-marc May 28, 2025
7144a5d
No longer inherrit from QASMVisitor
comp-phys-marc May 28, 2025
a82c789
Merge branch 'master' into feature/no-pre-compute
comp-phys-marc May 28, 2025
b400a98
pylint
comp-phys-marc May 28, 2025
46ce06e
pylint
comp-phys-marc May 28, 2025
6922c4c
Debug pylint
comp-phys-marc May 28, 2025
de6b9fc
Add support for negctrl
comp-phys-marc May 28, 2025
6c69441
Run formatter
comp-phys-marc May 28, 2025
e6ec23f
Update docstring
comp-phys-marc May 28, 2025
3ae407d
Simplify condition with substr membership check
comp-phys-marc May 28, 2025
38db04c
Simplify condition with substr membership check
comp-phys-marc May 28, 2025
91975ee
Merge branch 'master' into feature/no-pre-compute
comp-phys-marc May 28, 2025
e184762
Merge remote-tracking branch 'origin/feature/no-pre-compute' into fea…
comp-phys-marc May 28, 2025
bd2c94b
Update docstring
comp-phys-marc May 28, 2025
aceda7b
Format
comp-phys-marc May 28, 2025
2875e2f
Make type hint more specific
comp-phys-marc May 28, 2025
024a302
Make type hint more specific
comp-phys-marc May 28, 2025
d569a6b
Make type hint more specific
comp-phys-marc May 28, 2025
e98d3f8
Make type hint more specific
comp-phys-marc May 28, 2025
7accb46
Rename qubit_mapping -> wire_map
comp-phys-marc May 28, 2025
c68d233
Update all refs to qubit_mappings
comp-phys-marc May 28, 2025
2741c93
Raise when an unsupported expression is found
comp-phys-marc May 28, 2025
5a1da57
Update docstring
comp-phys-marc May 28, 2025
b52988f
Break up large expression
comp-phys-marc May 28, 2025
dc31195
Check for specific missing wires
comp-phys-marc May 28, 2025
eca761f
Add usage of wire_map to docs
comp-phys-marc May 28, 2025
3dd22dc
Simplify loop
comp-phys-marc May 28, 2025
47ee8af
Merge branch 'master' into feature/no-pre-compute
comp-phys-marc May 28, 2025
8dc7e85
Merge remote-tracking branch 'origin/feature/no-pre-compute' into fea…
comp-phys-marc May 28, 2025
b578c3c
Repurpose retrieve_variable -> evaluate_argument
comp-phys-marc May 28, 2025
f35e12e
pylint
comp-phys-marc May 28, 2025
83a9403
pylint
comp-phys-marc May 28, 2025
6b7e452
Merge branch 'feature/no-pre-compute' into feature/end-statements
comp-phys-marc May 28, 2025
1d9fac8
Run formatter
comp-phys-marc May 28, 2025
eeee2ad
Split up gate handler
comp-phys-marc May 28, 2025
5c28e3a
Split up gate handler
comp-phys-marc May 28, 2025
2084a72
Merge branch 'master' into feature/no-pre-compute
comp-phys-marc May 28, 2025
6a18692
Merge branch 'feature/no-pre-compute' into feature/end-statements
comp-phys-marc May 28, 2025
7c39931
Variables
comp-phys-marc May 28, 2025
5e655b2
Variable declarations, assignments, retrievals
comp-phys-marc May 28, 2025
f1cb5f2
Merge remote-tracking branch 'origin/feature/variables' into feature/…
comp-phys-marc May 28, 2025
12debf7
Improve test coverage
comp-phys-marc May 28, 2025
304c39f
PR feedback: docs
comp-phys-marc May 28, 2025
01452e9
Merge branch 'master' into feature/no-pre-compute
comp-phys-marc May 28, 2025
faf577a
Update docstring
comp-phys-marc May 28, 2025
74e14b1
pylint
comp-phys-marc May 28, 2025
814e174
Merge branch 'master' into feature/no-pre-compute
comp-phys-marc May 29, 2025
de262fe
Remove dirty state
comp-phys-marc May 29, 2025
607660e
Compute variables on first (and only) pass
comp-phys-marc May 29, 2025
1101c53
Remove second (execution) pass
comp-phys-marc May 29, 2025
051e2c7
Merge branch 'feature/no-pre-compute' into feature/variables
comp-phys-marc May 29, 2025
6f88838
Trigger CI
comp-phys-marc May 29, 2025
3a55fb9
Trigger CI
comp-phys-marc May 29, 2025
0cee688
Harden implementation
comp-phys-marc May 29, 2025
3171c55
Correct import statement for from_qasm3
comp-phys-marc May 29, 2025
a532497
Address feedback on docs
comp-phys-marc May 29, 2025
d0c69f9
Address feedback on docs
comp-phys-marc May 29, 2025
f278d41
Merge remote-tracking branch 'origin/feature/no-pre-compute' into fea…
comp-phys-marc May 29, 2025
738d88a
Adopt one more suggested rewording
comp-phys-marc May 29, 2025
8a26746
Suport for expressions as parameters
comp-phys-marc May 29, 2025
90624e9
Type hint
comp-phys-marc May 29, 2025
9f7ea0d
Simplify logic around modifiers
comp-phys-marc May 29, 2025
7b7c3dc
Add explicit else branch for clarity
comp-phys-marc May 29, 2025
d3e04d1
Add new imports
comp-phys-marc May 29, 2025
227b92e
Merge remote-tracking branch 'origin/feature/no-pre-compute' into fea…
comp-phys-marc May 29, 2025
42b4101
Add pragma: no cover to unreachable branch
comp-phys-marc May 29, 2025
66626a1
Minor cleanup around reviewer changes
comp-phys-marc May 29, 2025
ed86157
Stylistic change from loop -> comprehension
comp-phys-marc May 29, 2025
4200cc9
Merge branch 'master' into feature/no-pre-compute
comp-phys-marc May 29, 2025
fdf3f2e
Merge remote-tracking branch 'origin/feature/no-pre-compute' into fea…
comp-phys-marc May 29, 2025
8da0c44
Type hint
comp-phys-marc May 29, 2025
060695d
Use evaluate_argument in apply_modifier
comp-phys-marc May 29, 2025
0f12c0d
Clean up evaluate_argument
comp-phys-marc May 29, 2025
f63357b
Run formatter
comp-phys-marc May 29, 2025
43aac0d
Add AttriburteError handling for antlr4 runtime
comp-phys-marc May 29, 2025
ebf99f4
Skip coverage of lines dependent on environment
comp-phys-marc May 29, 2025
0a6e16b
pylint
comp-phys-marc May 29, 2025
78bd2e8
Merge branch 'master' into feature/no-pre-compute
comp-phys-marc May 29, 2025
810e49e
Merge branch 'master' into feature/no-pre-compute
comp-phys-marc May 29, 2025
c21cd0e
Merge branch 'feature/no-pre-compute' into feature/end-statements
comp-phys-marc May 29, 2025
65e5a34
Merge branch 'feature/no-pre-compute' into feature/variables
comp-phys-marc May 29, 2025
4dc3ef6
Make example device init into a dev comment
comp-phys-marc May 29, 2025
8d79e52
Make example device init a dev comment
comp-phys-marc May 29, 2025
b8cd2c1
Trigger CI
comp-phys-marc May 29, 2025
e6bcaeb
pylint
comp-phys-marc May 29, 2025
e56247f
Merge branch 'feature/no-pre-compute' into feature/end-statements
comp-phys-marc May 29, 2025
d719646
Merge branch 'feature/no-pre-compute' into feature/variables
comp-phys-marc May 29, 2025
d500ebf
Run formatter
comp-phys-marc May 30, 2025
48528e8
Remove permissive flag
comp-phys-marc May 30, 2025
b07957e
Run formatter
comp-phys-marc May 30, 2025
17bcaa5
Link to pypi install instructions in docs
comp-phys-marc May 30, 2025
0c158bd
Add needed quotes to pypi package option
comp-phys-marc May 30, 2025
893f382
OpenQASM3 -> OpenQASM 3.0
comp-phys-marc May 30, 2025
0180fa7
Link to pypi install instructions in docs
comp-phys-marc May 30, 2025
4e9d700
Add needed quotes to parser option
comp-phys-marc May 30, 2025
0bfd973
Rename qubits -> wires
comp-phys-marc May 30, 2025
c8ad00c
Rename QASM -> QASM 3.0
comp-phys-marc May 30, 2025
93ece37
Remove whitespace
comp-phys-marc May 30, 2025
915a771
Typo
comp-phys-marc May 30, 2025
a2c6b7c
Parse expressions
comp-phys-marc May 30, 2025
4bb9491
Make from_qasm3 available on qml
comp-phys-marc May 30, 2025
9024ab3
Make from_qasm3 available on qml
comp-phys-marc May 30, 2025
9c93b87
Remove unecessary `.io`
comp-phys-marc May 30, 2025
3c721bf
Import from qml in docs
comp-phys-marc May 30, 2025
834bc92
Merge branch 'feature/no-pre-compute' into feature/end-statements
comp-phys-marc May 30, 2025
7c14166
Merge branch 'feature/no-pre-compute' into feature/variables
comp-phys-marc May 30, 2025
61dbbeb
run formatter
comp-phys-marc May 30, 2025
ba72812
Merge remote-tracking branch 'origin/feature/no-pre-compute' into fea…
comp-phys-marc May 30, 2025
5f585df
Debug sphinx build
comp-phys-marc May 30, 2025
ead176e
pylint
comp-phys-marc May 30, 2025
924752a
format
comp-phys-marc May 30, 2025
8a0aa2c
Combine eval_expr with visit
comp-phys-marc May 30, 2025
18c4e61
Cannot register Callable
comp-phys-marc May 30, 2025
269da10
Merge branch 'master' into feature/no-pre-compute
comp-phys-marc May 30, 2025
0d26031
Describe what features are not yet supported
comp-phys-marc May 30, 2025
7e33347
Test alias
comp-phys-marc May 30, 2025
2795e76
Merge branch 'feature/no-pre-compute' into feature/end-statements
comp-phys-marc May 30, 2025
ad87f48
Docstring
comp-phys-marc Jun 2, 2025
6bcf4c4
Refactor index expr and id visit to share helpers
comp-phys-marc Jun 2, 2025
4adf9ea
Correct func signature
comp-phys-marc Jun 2, 2025
d3aaeb4
Merge branch 'master' into feature/variables
comp-phys-marc Jun 2, 2025
f548a19
Merge branch 'master' into feature/end-statements
comp-phys-marc Jun 2, 2025
12908c5
Add test for exprs
comp-phys-marc Jun 2, 2025
faea18f
Use break instead of exception
comp-phys-marc Jun 2, 2025
5d002ec
Use EndError
comp-phys-marc Jun 2, 2025
7f3c659
Just return after EndStatements
comp-phys-marc Jun 2, 2025
7e4d8da
Rename EndError -> EndProgram
comp-phys-marc Jun 2, 2025
ac17c5b
Run formatter
comp-phys-marc Jun 2, 2025
054f1cf
Debug pylint, coverage
comp-phys-marc Jun 2, 2025
684f519
Update changelog
comp-phys-marc Jun 2, 2025
7422d86
Move static helpers out of class
comp-phys-marc Jun 2, 2025
6ec0a16
Run formatter
comp-phys-marc Jun 2, 2025
c03323e
Trigger CI
comp-phys-marc Jun 2, 2025
f337a01
Combine classical declaration cases
comp-phys-marc Jun 2, 2025
85cd9ad
Merge branch 'master' into feature/end-statements
comp-phys-marc Jun 2, 2025
d95017e
Pylint
comp-phys-marc Jun 2, 2025
af8c89d
Pylint tests
comp-phys-marc Jun 2, 2025
92c15d3
Run formatter
comp-phys-marc Jun 2, 2025
85a819b
Move context management into ContextManager class
comp-phys-marc Jun 2, 2025
06aa886
Format, pylint
comp-phys-marc Jun 2, 2025
f713b0d
Backticks around `end`
comp-phys-marc Jun 2, 2025
2dfcfa5
Debug tests in CI
comp-phys-marc Jun 2, 2025
81572c8
Rename Context class per feedback
comp-phys-marc Jun 2, 2025
3f053bb
Merge branch 'feature/end-statements' into feature/variables
comp-phys-marc Jun 2, 2025
776d6c4
Run formatter
comp-phys-marc Jun 2, 2025
afb2969
Pass Context instead of dict
comp-phys-marc Jun 2, 2025
6546d4c
Use dataclass for Variables
comp-phys-marc Jun 2, 2025
b771aa5
Feedback
comp-phys-marc Jun 2, 2025
db29b72
PR Feedback
comp-phys-marc Jun 2, 2025
e7c5c75
Move retrieve_variable into Context
comp-phys-marc Jun 2, 2025
219fe4d
Format
comp-phys-marc Jun 2, 2025
aa0883a
Update docs
comp-phys-marc Jun 2, 2025
2be2c10
Merge branch 'feature/end-statements' into feature/variables
comp-phys-marc Jun 2, 2025
d274a8e
Improve test coverage
comp-phys-marc Jun 3, 2025
6e57e3f
More test coverage
comp-phys-marc Jun 3, 2025
5d5c632
Use set op instead of loop to build wire list
comp-phys-marc Jun 3, 2025
199f46e
PR Feedback
comp-phys-marc Jun 3, 2025
5ece1da
Merge remote-tracking branch 'origin/feature/variables' into feature/…
comp-phys-marc Jun 3, 2025
ac9a5dd
Debug failing regex
comp-phys-marc Jun 3, 2025
0c30fa2
Casting
comp-phys-marc Jun 3, 2025
36e1c11
Improve coverage
comp-phys-marc Jun 3, 2025
b7b98c4
Merge branch 'master' into feature/variables
comp-phys-marc Jun 3, 2025
8c34b18
Move exprs and casts to separate PR
comp-phys-marc Jun 3, 2025
650fdf9
Simple expressions and casts
comp-phys-marc Jun 3, 2025
d8ce679
pylint
comp-phys-marc Jun 3, 2025
c5d1355
pylint
comp-phys-marc Jun 3, 2025
b886aea
Refactor pylint directives
comp-phys-marc Jun 3, 2025
c8c24be
Change TypeError -> NotImplementedError
comp-phys-marc Jun 3, 2025
30a3227
Change TypeError -> NotImplementedError in tests
comp-phys-marc Jun 3, 2025
2ed517a
Merge remote-tracking branch 'origin/feature/variables' into feature/…
comp-phys-marc Jun 3, 2025
6ede81d
PR Feedbback
comp-phys-marc Jun 3, 2025
897bce9
Full file paths for CI
comp-phys-marc Jun 3, 2025
5d2a43e
Format
comp-phys-marc Jun 3, 2025
33c9e04
Trigger CI
comp-phys-marc Jun 4, 2025
a484ea8
Simplify indexing
comp-phys-marc Jun 4, 2025
a6c1cc8
File paths for CI
comp-phys-marc Jun 4, 2025
e804d6b
Handle more general indices
comp-phys-marc Jun 4, 2025
d3b6f76
Merge branch 'feature/variables' into feature/expressions
comp-phys-marc Jun 4, 2025
988c5d1
Implement binary and unary exprs without eval
comp-phys-marc Jun 4, 2025
0b66c1d
pylint
comp-phys-marc Jun 4, 2025
927766f
Improve coverage
comp-phys-marc Jun 4, 2025
e1ee664
Assignment expressions
comp-phys-marc Jun 4, 2025
08d61e0
pylint
comp-phys-marc Jun 4, 2025
33e0aea
pylint
comp-phys-marc Jun 4, 2025
70fa8aa
Test Expressions
comp-phys-marc Jun 4, 2025
30d3180
format
comp-phys-marc Jun 4, 2025
3afd579
Remove redundant logic in retrieve_variable
comp-phys-marc Jun 4, 2025
22d1ba5
Test unary exprs
comp-phys-marc Jun 4, 2025
4d74068
Merge branch 'feature/variables' into feature/expressions
comp-phys-marc Jun 4, 2025
467820b
Roughly equal
comp-phys-marc Jun 5, 2025
59a1248
Switch case
comp-phys-marc Jun 5, 2025
a7353d7
Merge branch 'master' into feature/expressions
comp-phys-marc Jun 6, 2025
0e16fdc
Merge branch 'master', fix switch
comp-phys-marc Jun 6, 2025
4a02d0b
Clean up merge
comp-phys-marc Jun 6, 2025
98a3042
Cleanup tests
comp-phys-marc Jun 6, 2025
fc33e3b
pylint
comp-phys-marc Jun 6, 2025
f5bfd74
Typo in comment
comp-phys-marc Jun 6, 2025
98458c4
PR feedback
comp-phys-marc Jun 6, 2025
ce3b163
Merge remote-tracking branch 'origin' into feature/expressions
comp-phys-marc Jun 6, 2025
10bf4d2
Merge remote-tracking branch 'origin/feature/expressions' into featur…
comp-phys-marc Jun 6, 2025
0fe1c7d
Format
comp-phys-marc Jun 6, 2025
2849bd4
pylint
comp-phys-marc Jun 6, 2025
28ccbf5
File paths for CI
comp-phys-marc Jun 6, 2025
0692899
Improve coverage
comp-phys-marc Jun 9, 2025
51a9975
Format, pylint
comp-phys-marc Jun 9, 2025
1f7fd14
isnumeric doesn't match "."
comp-phys-marc Jun 9, 2025
3733f58
Test organization
comp-phys-marc Jun 9, 2025
391c74d
Format
comp-phys-marc Jun 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
266 changes: 262 additions & 4 deletions pennylane/io/qasm_interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,37 @@
from functools import partial
from typing import Any, Iterable

import numpy as np
from numpy import uint
from openqasm3.ast import (
AliasStatement,
ArrayLiteral,
ArrayType,
BinaryExpression,
BitstringLiteral,
BooleanLiteral,
BoolType,
Cast,
ClassicalAssignment,
ClassicalDeclaration,
ComplexType,
ConstantDeclaration,
DurationLiteral,
EndStatement,
Expression,
ExpressionStatement,
FloatLiteral,
FloatType,
Identifier,
ImaginaryLiteral,
IndexExpression,
IntegerLiteral,
IntType,
QuantumGate,
QubitDeclaration,
RangeDefinition,
UintType,
UnaryExpression,
)
from openqasm3.visitor import QASMNode

Expand Down Expand Up @@ -66,6 +78,64 @@
"CRZ": ops.CRZ,
}

EQUALS = "="
ARROW = "->"
PLUS = "+"
DOUBLE_PLUS = "++"
MINUS = "-"
ASTERISK = "*"
DOUBLE_ASTERISK = "**"
SLASH = "/"
PERCENT = "%"
PIPE = "|"
DOUBLE_PIPE = "||"
AMPERSAND = "&"
DOUBLE_AMPERSAND = "&&"
CARET = "^"
AT = "@"
TILDE = "~"
EXCLAMATION_POINT = "!"
EQUALITY_OPERATORS = ["==", "!=", "~="]
COMPOUND_ASSIGNMENT_OPERATORS = [
"+=",
"-=",
"*=",
"/=",
"&=",
"|=",
"^=",
"<<=",
">>=",
"%=",
"**=",
]
COMPARISON_OPERATORS = [">", "<", ">=", "<="]
BIT_SHIFT_OPERATORS = [">>", "<<"]

NON_ASSIGNMENT_CLASSICAL_OPERATORS = (
EQUALITY_OPERATORS
+ COMPARISON_OPERATORS
+ BIT_SHIFT_OPERATORS
+ [
PLUS,
MINUS,
ASTERISK,
DOUBLE_ASTERISK,
SLASH,
PERCENT,
PIPE,
DOUBLE_PIPE,
AMPERSAND,
DOUBLE_AMPERSAND,
CARET,
AT,
TILDE,
EXCLAMATION_POINT,
]
)

ASSIGNMENT_CLASSICAL_OPERATORS = [EQUALS, DOUBLE_PLUS] + COMPOUND_ASSIGNMENT_OPERATORS


@dataclass
class Variable:
Expand Down Expand Up @@ -130,7 +200,7 @@ def update_var(
value: any,
name: str,
node: QASMNode,
):
): # pylint: disable=too-many-branches
"""
Updates a variable, or raises if it is constant.
Args:
Expand All @@ -144,8 +214,40 @@ def update_var(
f"Attempt to mutate a constant {name} on line {node.span.start_line} that was "
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I don't like it when a function has too many levels of nesting. Maybe you can start with

if name not in self.vars:
    raise TypeError(...)
if self.vars[name].constant:
    raise ValueError(...)

so that the bulk of your logic is not nested

f"defined on line {self.vars[name].line}"
)
self.vars[name].val = value
self.vars[name].line = node.span.start_line
if node.op.name in ASSIGNMENT_CLASSICAL_OPERATORS:
if node.op.name == "=":
self.vars[name].val = value
if node.op.name == "++":
self.vars[name].val = self.vars[name].val + 1
if node.op.name == "+=":
self.vars[name].val += value
if node.op.name == "-=":
self.vars[name].val -= value
if node.op.name == "*=":
self.vars[name].val = self.vars[name].val * value
if node.op.name == "/=":
self.vars[name].val = self.vars[name].val / value
if node.op.name == "&=":
self.vars[name].val = self.vars[name].val & value
if node.op.name == "|=":
self.vars[name].val = self.vars[name].val | value
if node.op.name == "^=":
self.vars[name].val = self.vars[name].val ^ value
if node.op.name == "<<=":
self.vars[name].val = self.vars[name].val << value
if node.op.name == ">>=":
self.vars[name].val = self.vars[name].val >> value
if node.op.name == "%=":
self.vars[name].val = self.vars[name].val % value
if node.op.name == "**=":
self.vars[name].val = self.vars[name].val ** value
self.vars[name].line = node.span.start_line
else:
# we shouldn't ever get thi error if the parser did its job right
raise SyntaxError( # pragma: no cover
f"Invalid operator {node.op.name} encountered in assignment expression "
f"on line {node.span.start_line}."
) # pragma: no cover
else:
raise TypeError(f"Attempt to use undeclared variable {name} in {self.name}")

Expand Down Expand Up @@ -205,6 +307,24 @@ def _resolve_name(node: QASMNode):
return node.name if isinstance(node.name, str) else node.name.name


def preprocess_operands(operand):
"""
Interprets a string operand as an appropriate type.

Args:
operand (str): the string operand to interpret.

Returns:
The interpreted operand as an appropriate type.
"""
if isinstance(operand, str):
if operand.isdigit():
operand = int(operand)
elif operand.isnumeric():
operand = float(operand)
return operand


class EndProgram(Exception):
"""Exception raised when it encounters an end statement in the QASM circuit."""

Expand Down Expand Up @@ -335,7 +455,6 @@ def visit_classical_assignment(self, node: QASMNode, context: Context):
# references to an unresolved value see a func for now
name = _resolve_name(node.lvalue)
res = self.visit(node.rvalue, context)
# TODO: different types of assignments
context.update_var(res, name, node)

@visit.register(AliasStatement)
Expand Down Expand Up @@ -513,6 +632,145 @@ def apply_modifier(self, mod: QuantumGate, previous: Operator, context: Context,

return next, wires

@visit.register(ExpressionStatement)
def visit_expression_statement(self, node: ExpressionStatement, context: Context):
"""
Registers an expression statement.
Args:
node (ExpressionStatement): The expression statement.
context (Context): The current context.
"""
return self.visit(node.expression, context)

@visit.register(Cast)
def visit_cast(self, node: Cast, context: Context):
"""
Registers a Cast expression.

Args:
node (Cast): The Cast expression.
context (Context): The current context.

Returns:
Any: The argument cast to the appropriate type.

Raises:
TypeError: If the cast cannot be made.
"""
arg = self.visit(node.argument, context)
ret = arg
try:
if isinstance(node.type, IntType):
ret = int(arg)
if isinstance(node.type, UintType):
ret = uint(arg)
if isinstance(node.type, FloatType):
ret = float(arg)
if isinstance(node.type, ComplexType):
ret = complex(arg)
if isinstance(node.type, BoolType):
ret = bool(arg)
if isinstance(node.type, ArrayType):
ret = arg.val
# TODO: durations, angles, etc.
except TypeError as e:
raise TypeError(
f"Unable to cast {arg.__class__.__name__} to {node.type.__class__.__name__}: {str(e)}"
) from e
return ret

@visit.register(BinaryExpression)
def visit_binary_expression(
self, node: BinaryExpression, context: Context
): # pylint: disable=too-many-branches
"""
Registers a binary expression.

Args:
node (BinaryExpression): The binary expression.
context (Context): The current context.

Returns:
The result of the evaluated expression.
"""
lhs = preprocess_operands(self.visit(node.lhs, context))
rhs = preprocess_operands(self.visit(node.rhs, context))
ret = None
if node.op.name in NON_ASSIGNMENT_CLASSICAL_OPERATORS:
match node.op.name:
case "==":
ret = lhs == rhs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not

Suggested change
ret = lhs == rhs
return lhs == rhs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a fine suggestion. No problem with that.

case "!=":
ret = lhs != rhs
case "~=":
ret = np.isclose(lhs, rhs)
case ">":
ret = lhs > rhs
case "<":
ret = lhs < rhs
case ">=":
ret = lhs >= rhs
case "<=":
ret = lhs <= rhs
case ">>":
ret = lhs >> rhs
case "<<":
ret = lhs << rhs
case "+":
ret = lhs + rhs
case "-":
ret = lhs - rhs
case "*":
ret = lhs * rhs
case "**":
ret = lhs**rhs
case "/":
ret = lhs / rhs
case "%":
ret = lhs % rhs
case "|":
ret = lhs | rhs
case "||":
ret = lhs or rhs
case "&":
ret = lhs & rhs
case "&&":
ret = lhs and rhs
case "^":
ret = lhs ^ rhs
return ret
# we shouldn't ever get thi error if the parser did its job right
raise SyntaxError( # pragma: no cover
f"Invalid operator {node.op.name} encountered in binary expression "
f"on line {node.span.start_line}."
) # pragma: no cover

@visit.register(UnaryExpression)
def visit_unary_expression(self, node: UnaryExpression, context: Context):
"""
Registers a unary expression.

Args:
node (UnaryExpression): The unary expression.
context (Context): The current context.

Returns:
The result of the evaluated expression.
"""
if node.op.name in NON_ASSIGNMENT_CLASSICAL_OPERATORS:
operand = preprocess_operands(self.visit(node.expression, context))
if node.op.name == "!":
return not operand
if node.op.name == "-":
return -operand
if node.op.name == "~":
return ~operand # pylint: disable=invalid-unary-operand-type
# we shouldn't ever get thi error if the parser did its job right
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# we shouldn't ever get thi error if the parser did its job right
# we shouldn't ever get this error if the parser did its job right

raise SyntaxError( # pragma: no cover
f"Invalid operator {node.op.name} encountered in unary expression "
f"on line {node.span.start_line}."
) # pragma: no cover

@visit.register(IndexExpression)
def visit_index_expression(
self, node: IndexExpression, context: Context, aliasing: bool = False
Expand Down
25 changes: 25 additions & 0 deletions tests/io/qasm_interpreter/assignment.qasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
int a = 0;
int b = 1;
int c = 2;
int d = 3;
int e = 4;
bool f = true;
bool g = true;
bit i = "10";
bit j = "10";
bit k = "11";
int l = 5;
int m = 6;
int n = 2;
a = 1;
b += 2;
c -= 3;
d *= 4;
e /= 5;
f &= true;
g |= false;
i ^= 9;
j <<= 10;
k >>= 1;
l %= 2;
m **= 13;
32 changes: 32 additions & 0 deletions tests/io/qasm_interpreter/binary_expressions.qasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const int lhs = 0;
const int rhs = 1;
bool a = lhs == rhs;
bool b = lhs != rhs;
bool c = lhs > rhs;
bool d = lhs < rhs;
bool e = lhs >= rhs;
bool f = lhs <= rhs;

bit lh = "10";
bit rh = "01";
bit g = lh >> rh;
bit h = lh << rh;
bit i = lh | rh;
bit j = lh ^ rh;
bit k = lh & rh;

int l = 3;
int r = 2;
int m = l + r;
int n = l / r;
int o = l - r;
int p = l * r;
int q = l ** r;
int s = l % r;

bool left = true;
bool right = false;
int t = left || right;
int u = left && right;

bool v = lhs ~= rhs;
Loading
Loading