1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// Copyright 2019 Q1t BV
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/// Enumeration for errors relating to the export of circuits
#[derive(Debug, PartialEq)]
pub enum ExportError
{
    /// Trying to export a peek into the quantum state
    ExportPeekInvalid(&'static str),
    /// Classical registers not available in c-Qasm
    NoClassicalRegister,
    /// Not using a full condition register in OpenQasm export
    IncompleteConditionRegister,
    /// Unable to create condition operation in c-Qasm
    InvalidConditionalOp(String),
    /// Trying to export in a format for which no export function was written
    NotImplemented(&'static str, String),
    /// Trying to close a loop where none is open in LaTeX export
    CantCloseLoop,
    /// Trying to reserve range in LaTeX export, but previous reservation is open
    RangeAlreadyOpen
}

impl ::std::fmt::Display for ExportError
{
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result
    {
        match *self
        {
            ExportError::ExportPeekInvalid(method) => {
                write!(f, "Peeking into the quantum state is not a physical operation, and is not supported in {}", method)
            },
            ExportError::NoClassicalRegister => {
                write!(f, "In cQasm, no classical registers can be specified. Measurements must be made to a classical bit with the same index as the qubit")
            },
            ExportError::IncompleteConditionRegister => {
                write!(f, "OpenQasm can only perform conditional operations based on a complete classical register")
            },
            ExportError::InvalidConditionalOp(ref qasm) => {
                write!(f, "Unable to find gate name or argument in \"{}\"", qasm)
            },
            ExportError::NotImplemented(method, ref desc) => {
                write!(f, "Export to {} was not implemented for \"{}\"", method, desc)
            },
            ExportError::CantCloseLoop => {
                write!(f, "Unable to close loop, because no loop is currently open")
            },
            ExportError::RangeAlreadyOpen => {
                write!(f, "Trying to reserve range of bits, but a previous reservation is still open")
            }
        }
    }
}

/// Type alias for a result with an export error
pub type ExportResult<T> = ::std::result::Result<T, ExportError>;

/// Structure for errors encountered while parsing a composite gate description
#[derive(Debug, PartialEq)]
pub enum ParseError
{
    /// Gate name not recognised
    UnknownGate(String),
    /// No gate name found
    NoGateName(String),
    /// Wrong number of arguments to gate
    InvalidNrArguments(usize, usize, String),
    /// Invalid number of qubits to operate on
    InvalidNrBits(usize, usize, String),
    /// Unable to parse argument to gate
    InvalidArgument(String),
    /// Unable to find bit numbers on which the gate operates
    NoBits(String),
    /// Unable to parse bit number
    InvalidBit(String),
    /// Text occurs after a gate description
    TrailingText(String),
    /// Unclosed parentheses in argument expression
    UnclosedParentheses(String),
}

impl ::std::fmt::Display for ParseError
{
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result
    {
        match *self
        {
            ParseError::UnknownGate(ref name) => {
                write!(f, "Unknown gate \"{}\"", name)
            },
            ParseError::NoGateName(ref text) => {
                write!(f, "Failed to find gate name in \"{}\"", text)
            },
            ParseError::InvalidNrArguments(actual, expected, ref name) => {
                write!(f, "Expected {} arguments to \"{}\" gate, got {}", expected, name, actual)
            },
            ParseError::InvalidNrBits(actual, expected, ref name) => {
                write!(f, "Expected {} bits for \"{}\" gate, got {}", expected, name, actual)
            },
            ParseError::InvalidArgument(ref text) => {
                write!(f, "Failed to parse argument \"{}\"", text)
            },
            ParseError::NoBits(ref name) => {
                write!(f, "Unable to find the bits gate {} operates on", name)
            },
            ParseError::InvalidBit(ref text) => {
                write!(f, "Failed to parse bit number in \"{}\"", text)
            },
            ParseError::TrailingText(ref text) => {
                write!(f, "Trailing text after gate description: \"{}\"", text)
            },
            ParseError::UnclosedParentheses(ref text) => {
                write!(f, "Unclosed parentheses in expression: \"{}\"", text)
            }
        }
    }
}

/// Type alias for a result with a parse error
pub type ParseResult<T> = ::std::result::Result<T, ParseError>;

/// Enumeration for errors in the use of q1tsim
#[derive(Debug, PartialEq)]
pub enum Error
{
    /// Number of bits passed does not match gate
    InvalidNrBits(usize, usize, String),
    /// Invalid index for quantum bit
    InvalidQBit(usize),
    /// Invalid index for classical bit
    InvalidCBit(usize),
    /// Results asked for circuit that has not been run yet
    NotExecuted,
    /// Other errors that should not occur
    InternalError(String),
    /// Error reating to the export of a circuit
    ExportError(ExportError),
    /// Error in parsing a composite gate description
    ParseError(ParseError)
}

impl From<ExportError> for Error
{
    fn from(err: ExportError) -> Self
    {
        Error::ExportError(err)
    }
}

impl From<ParseError> for Error
{
    fn from(err: ParseError) -> Self
    {
        Error::ParseError(err)
    }
}

impl ::std::fmt::Display for Error
{
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result
    {
        match *self
        {
            Error::InvalidNrBits(actual, expected, ref desc) => {
                write!(f, "Expected {} bits for \"{}\", got {}", expected, desc, actual)
            },
            Error::InvalidQBit(bit) => {
                write!(f, "Invalid index {} for a quantum bit", bit)
            },
            Error::InvalidCBit(bit) => {
                write!(f, "Invalid index {} for a classical bit", bit)
            },
            Error::NotExecuted => {
                write!(f, "The circuit has not been executed yet")
            },
            Error::InternalError(ref err) => {
                write!(f, "Internal error: {}", err)
            },
            Error::ExportError(ref err) => {
                write!(f, "{}", err)
            },
            Error::ParseError(ref err) => {
                write!(f, "{}", err)
            }
        }
    }
}

/// Type alias for a result with a q1tsim error
pub type Result<T> = ::std::result::Result<T, Error>;