1use quil_rs::instruction::{
2 ArithmeticOperand, Declaration, Load, MemoryReference, Offset, ScalarType, Sharing, Store,
3 Vector,
4};
5
6use super::PyArithmeticOperand;
7use crate::{impl_copy_for_instruction, impl_eq, impl_pickle_for_instruction, impl_to_quil};
8
9use rigetti_pyo3::{
10 impl_from_str, impl_hash, impl_parse, impl_repr, py_wrap_data_struct, py_wrap_error,
11 py_wrap_simple_enum,
12 pyo3::{
13 exceptions::PyValueError,
14 pymethods,
15 types::{PyInt, PyString},
16 Py, PyResult, Python,
17 },
18 wrap_error, PyTryFrom,
19};
20
21wrap_error!(RustParseMemoryReferenceError(quil_rs::program::SyntaxError<MemoryReference>));
22py_wrap_error!(
23 quil,
24 RustParseMemoryReferenceError,
25 ParseMemoryReferenceError,
26 PyValueError
27);
28
29py_wrap_simple_enum! {
30 PyScalarType(ScalarType) as "ScalarType" {
31 Bit,
32 Integer,
33 Octet,
34 Real
35 }
36}
37impl_repr!(PyScalarType);
38impl_to_quil!(PyScalarType);
39impl_hash!(PyScalarType);
40
41impl rigetti_pyo3::PyTryFrom<pyo3::PyAny> for PyScalarType {
42 fn py_try_from(_py: Python, item: &pyo3::PyAny) -> PyResult<Self> {
43 let item = item.extract::<String>()?;
44 match item.as_str() {
45 "BIT" => Ok(Self::Bit),
46 "INTEGER" => Ok(Self::Integer),
47 "OCTET" => Ok(Self::Octet),
48 "REAL" => Ok(Self::Real),
49 _ => Err(PyValueError::new_err(format!(
50 "Invalid value for ScalarType: {item}"
51 ))),
52 }
53 }
54}
55
56py_wrap_data_struct! {
57 #[derive(Debug, Hash, PartialEq, Eq)]
58 #[pyo3(subclass)]
59 PyVector(Vector) as "Vector" {
60 data_type: ScalarType => PyScalarType,
61 length: u64 => Py<PyInt>
62 }
63}
64impl_repr!(PyVector);
65impl_to_quil!(PyVector);
66impl_hash!(PyVector);
67impl_eq!(PyVector);
68
69#[pymethods]
70impl PyVector {
71 #[new]
72 pub fn new(py: Python<'_>, data_type: PyScalarType, length: u64) -> PyResult<Self> {
73 Ok(Self(Vector::new(
74 ScalarType::py_try_from(py, &data_type)?,
75 length,
76 )))
77 }
78}
79
80py_wrap_data_struct! {
81 #[derive(Debug, PartialEq, Eq, Hash)]
82 #[pyo3(subclass)]
83 PyOffset(Offset) as "Offset" {
84 offset: u64 => Py<PyInt>,
85 data_type: ScalarType => PyScalarType
86 }
87}
88impl_repr!(PyOffset);
89impl_to_quil!(PyOffset);
90impl_hash!(PyOffset);
91impl_eq!(PyOffset);
92
93#[pymethods]
94impl PyOffset {
95 #[new]
96 pub fn new(py: Python<'_>, offset: u64, data_type: PyScalarType) -> PyResult<Self> {
97 Ok(Self(Offset::new(
98 offset,
99 ScalarType::py_try_from(py, &data_type)?,
100 )))
101 }
102}
103
104py_wrap_data_struct! {
105 #[derive(Debug, PartialEq, Eq, Hash)]
106 #[pyo3(subclass)]
107 PySharing(Sharing) as "Sharing" {
108 name: String => Py<PyString>,
109 offsets: Vec<Offset> => Vec<PyOffset>
110 }
111}
112impl_repr!(PySharing);
113impl_hash!(PySharing);
114impl_eq!(PySharing);
115
116#[pymethods]
117impl PySharing {
118 #[new]
119 pub fn new(py: Python<'_>, name: String, offsets: Vec<PyOffset>) -> PyResult<Self> {
120 Ok(Self(Sharing::new(
121 name,
122 Vec::<Offset>::py_try_from(py, &offsets)?,
123 )))
124 }
125}
126
127py_wrap_data_struct! {
128 #[derive(Debug, PartialEq, Eq)]
129 #[pyo3(subclass, module = "quil.instructions")]
130 PyDeclaration(Declaration) as "Declaration" {
131 name: String => Py<PyString>,
132 size: Vector => PyVector,
133 sharing: Option<Sharing> => Option<PySharing>
134 }
135}
136impl_repr!(PyDeclaration);
137impl_to_quil!(PyDeclaration);
138impl_copy_for_instruction!(PyDeclaration);
139impl_hash!(PyDeclaration);
140impl_eq!(PyDeclaration);
141impl_pickle_for_instruction!(PyDeclaration);
142
143#[pymethods]
144impl PyDeclaration {
145 #[new]
146 pub fn new(
147 py: Python<'_>,
148 name: String,
149 size: PyVector,
150 sharing: Option<PySharing>,
151 ) -> PyResult<Self> {
152 Ok(Self(Declaration::new(
153 name,
154 Vector::py_try_from(py, &size)?,
155 Option::<Sharing>::py_try_from(py, &sharing)?,
156 )))
157 }
158}
159
160py_wrap_data_struct! {
161 #[derive(Debug, Hash, PartialEq)]
162 #[pyo3(subclass)]
163 PyMemoryReference(MemoryReference) as "MemoryReference" {
164 name: String => Py<PyString>,
165 index: u64 => Py<PyInt>
166 }
167}
168impl_hash!(PyMemoryReference);
169impl_repr!(PyMemoryReference);
170impl_to_quil!(PyMemoryReference);
171impl_from_str!(PyMemoryReference, RustParseMemoryReferenceError);
172impl_parse!(PyMemoryReference);
173impl_eq!(PyMemoryReference);
174
175#[pymethods]
176impl PyMemoryReference {
177 #[new]
178 pub fn new(name: String, index: u64) -> Self {
179 Self(MemoryReference::new(name, index))
180 }
181}
182
183py_wrap_data_struct! {
184 #[derive(Debug, PartialEq, Eq)]
185 #[pyo3(subclass, module = "quil.instructions")]
186 PyLoad(Load) as "Load" {
187 destination: MemoryReference => PyMemoryReference,
188 source: String => Py<PyString>,
189 offset: MemoryReference => PyMemoryReference
190 }
191}
192impl_repr!(PyLoad);
193impl_to_quil!(PyLoad);
194impl_copy_for_instruction!(PyLoad);
195impl_hash!(PyLoad);
196impl_eq!(PyLoad);
197impl_pickle_for_instruction!(PyLoad);
198
199#[pymethods]
200impl PyLoad {
201 #[new]
202 pub fn new(
203 py: Python<'_>,
204 destination: PyMemoryReference,
205 source: String,
206 offset: PyMemoryReference,
207 ) -> PyResult<Self> {
208 Ok(Self(Load::new(
209 MemoryReference::py_try_from(py, &destination)?,
210 source,
211 MemoryReference::py_try_from(py, &offset)?,
212 )))
213 }
214}
215
216py_wrap_data_struct! {
217 #[derive(Debug, PartialEq)]
218 #[pyo3(subclass, module = "quil.instructions")]
219 PyStore(Store) as "Store" {
220 destination: String => Py<PyString>,
221 offset: MemoryReference => PyMemoryReference,
222 source: ArithmeticOperand => PyArithmeticOperand
223 }
224}
225impl_repr!(PyStore);
226impl_to_quil!(PyStore);
227impl_copy_for_instruction!(PyStore);
228impl_hash!(PyStore);
229impl_eq!(PyStore);
230impl_pickle_for_instruction!(PyStore);
231
232#[pymethods]
233impl PyStore {
234 #[new]
235 pub fn new(
236 py: Python<'_>,
237 destination: String,
238 offset: PyMemoryReference,
239 source: PyArithmeticOperand,
240 ) -> PyResult<Self> {
241 Ok(Self(Store::new(
242 destination,
243 MemoryReference::py_try_from(py, &offset)?,
244 ArithmeticOperand::py_try_from(py, &source)?,
245 )))
246 }
247}