1use thiserror::Error;
7
8#[derive(Debug, Error, Clone, PartialEq)]
10#[non_exhaustive]
11pub enum PrismError {
12 #[error("parse error at line {line}: {message}")]
14 Parse { line: usize, message: String },
15
16 #[error("unsupported construct at line {line}: `{construct}`{}", loop_hint(.construct))]
19 UnsupportedConstruct { construct: String, line: usize },
20
21 #[error("invalid qubit index {index} (register size: {register_size})")]
23 InvalidQubit { index: usize, register_size: usize },
24
25 #[error("invalid classical bit index {index} (register size: {register_size})")]
27 InvalidClassicalBit { index: usize, register_size: usize },
28
29 #[error("gate `{gate}`: expected {expected} qubit(s), got {got}")]
31 GateArity {
32 gate: String,
33 expected: usize,
34 got: usize,
35 },
36
37 #[error("backend `{backend}` does not support: {operation}")]
39 BackendUnsupported { backend: String, operation: String },
40
41 #[error("invalid parameter: {message}")]
43 InvalidParameter { message: String },
44
45 #[error("undefined register `{name}` at line {line}")]
47 UndefinedRegister { name: String, line: usize },
48
49 #[error("cannot export instruction {index} to OpenQASM 3.0: {reason}")]
51 ExportUnsupported { index: usize, reason: String },
52
53 #[error("backend `{backend}` is incompatible: {reason}")]
55 IncompatibleBackend { backend: String, reason: String },
56
57 #[error(
60 "dynamic program stopped after {max_steps} steps in {region}; raise the bound with `max_steps` if the loop is meant to run that long"
61 )]
62 StepLimit { region: String, max_steps: u64 },
63
64 #[error("{0}")]
67 ResourceLimit(Box<ResourceLimit>),
68}
69
70#[derive(Debug, Error, Clone, PartialEq)]
73#[error(
74 "backend `{backend}`: {operation} needs {required} {resource}, exceeding the cap of \
75 {limit} on this machine{}",
76 override_hint(.env_var)
77)]
78#[non_exhaustive]
79pub struct ResourceLimit {
80 pub backend: String,
81 pub operation: String,
82 pub resource: ResourceKind,
83 pub required: u128,
84 pub limit: u128,
85 pub env_var: Option<&'static str>,
86}
87
88#[derive(Debug, Clone, Copy, PartialEq, Eq)]
90#[non_exhaustive]
91pub enum ResourceKind {
92 Qubits,
94 Amplitudes,
96 Entries,
98 Elements,
100 DeviceBytes,
101}
102
103impl std::fmt::Display for ResourceKind {
104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105 f.write_str(match self {
106 ResourceKind::Qubits => "qubits",
107 ResourceKind::Amplitudes => "amplitudes",
108 ResourceKind::Entries => "entries",
109 ResourceKind::Elements => "elements",
110 ResourceKind::DeviceBytes => "bytes of device memory",
111 })
112 }
113}
114
115fn loop_hint(construct: &str) -> &'static str {
117 match construct {
118 "while" | "break" | "continue" => {
119 "; `openqasm::parse_dynamic` reads it into a control-flow graph"
120 }
121 _ => "",
122 }
123}
124
125fn override_hint(env_var: &Option<&'static str>) -> String {
126 env_var.map_or_else(String::new, |var| format!(" (set {var} to override)"))
127}
128
129pub type Result<T> = std::result::Result<T, PrismError>;