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
use osiris_data::memory::{MemoryError, MemoryResult};

use crate::operation::Instruction;
use crate::operation::scheme::ArgumentType;

#[derive(Debug)]
pub enum OperationError {
    /// The processor should HALT,
    HaltError,
    /// The processor should HALT and an error message should be displayed,
    Panic(String),
    /// An invalid argument has been provided to an operation call,
    InvalidArgumentType { expected: ArgumentType, provided: ArgumentType },
    /// A memory error occurred during a memory operation,
    MemoryError(MemoryError),
    /// The stack is empty but a pop() had been required,
    CannotReturnFromEmptyStack,
    /// The specified instruction matches no operation.
    MismatchedInstruction(Instruction),
}

pub type OperationResult<T> = Result<T, OperationError>;

/// Some sugar to wrap a [MemoryError] in a [OperationError::MemoryError] or to return a `Ok` value as is :
///
/// ```
/// use osiris_data::memory::{Memory, MemoryError, MemoryResult};
/// use osiris_process::operation::error::{OperationError, promote};
///
/// let mut mem = Memory::with_size(1);
/// let m: MemoryResult<()> = mem.free(2);
/// let o = promote(m);
/// if let Err(OperationError::MemoryError(MemoryError::CannotFree {trying_to_free: 2,memory_len: 1})) = o {
///     assert!(true)
/// } else { assert!(false) }
///
/// let m: MemoryResult<()> = mem.free(1);
/// let o = promote(m);
/// if let Ok(()) = o { assert!(true) } else { assert!(false) }
/// assert!(mem.is_empty());
/// ```
pub fn promote<T>(memory_result: MemoryResult<T>) -> OperationResult<T> {
    match memory_result {
        Ok(ok_value) => Ok(ok_value),
        Err(e) => Err(OperationError::MemoryError(e))
    }
}