Skip to content

Commit

Permalink
exit/1
Browse files Browse the repository at this point in the history
  • Loading branch information
KronicDeth committed Apr 1, 2019
1 parent 9e4a83a commit da2ae28
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 53 deletions.
6 changes: 6 additions & 0 deletions lumen_runtime/src/binary/sub.rs
Expand Up @@ -348,6 +348,12 @@ impl DoubleEndedIterator for ByteIter {

impl FusedIterator for ByteIter {}

impl Ord for Binary {
fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(other).unwrap()
}
}

impl PartialEq<heap::Binary> for Binary {
/// > * Bitstrings are compared byte by byte, incomplete bytes are compared bit by bit.
/// > -- https://hexdocs.pm/elixir/operators.html#term-ordering
Expand Down
89 changes: 50 additions & 39 deletions lumen_runtime/src/exception.rs
@@ -1,47 +1,28 @@
use std::fmt::{self, Debug};

use crate::term::Term;

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Class {
Error,
Error { arguments: Option<Term> },
Exit,
Throw,
}

#[derive(Debug)]
pub struct Exception {
pub class: Class,
pub reason: Term,
pub arguments: Option<Term>,
pub file: &'static str,
pub line: u32,
pub column: u32,
}

// Needed to support `std::result::Result.unwrap`
impl Debug for Exception {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(
formatter,
"Exception {{ class: {:?}, reason: Term {{ tagged: {:#b} }}, file: {:?}, line: {:?}, column: {:?} }}",
self.class,
self.reason.tagged,
self.file,
self.line,
self.column
)
}
}

impl Eq for Exception {}

impl PartialEq for Exception {
/// `file`, `line`, and `column` don't count for equality as they are for `Debug` only to help
/// track down exceptions.
fn eq(&self, other: &Exception) -> bool {
(self.class == other.class)
& (self.reason == other.reason)
& (self.arguments == other.arguments)
(self.class == other.class) & (self.reason == other.reason)
}
}

Expand Down Expand Up @@ -105,6 +86,16 @@ macro_rules! assert_error {
};
}

#[macro_export]
macro_rules! assert_exit {
($left:expr, $reason:expr) => {
assert_eq!($left, Err(exit!($reason)))
};
($left:expr, $reason:expr,) => {
assert_exit($left, $reason)
};
}

#[macro_export]
macro_rules! bad_argument {
() => {{
Expand Down Expand Up @@ -134,31 +125,45 @@ macro_rules! bad_map {
#[macro_export]
macro_rules! error {
($reason:expr) => {{
use crate::exception::{Class::Error, Exception};

Exception {
class: Error,
reason: $reason,
arguments: None,
file: file!(),
line: line!(),
column: column!(),
}
error!($reason, None)
}};
($reason:expr, $arguments:expr) => {{
use crate::exception::{Class::Error, Exception};

exception!(
Error {
arguments: $arguments
},
$reason
)
}};
($reason:expr, $arguments:expr,) => {{
error!($reason, $arguments)
}};
}

#[macro_export]
macro_rules! exception {
($class:expr, $reason:expr) => {{
Exception {
class: Error,
class: $class,
reason: $reason,
arguments: Some($arguments),
file: file!(),
line: line!(),
column: column!(),
}
}};
($reason:expr, $arguments:expr,) => {{
error!($reason, $arguments)
($class:expr, $reason:expr,) => {{
exception!($class, $reason)
}};
}

#[macro_export]
macro_rules! exit {
($reason:expr) => {{
use crate::exception::{Class::Exit, Exception};

exception!(Exit, $reason)
}};
}

Expand All @@ -167,6 +172,7 @@ mod tests {
use super::*;

mod error {
use super::Class::*;
use super::*;

use crate::atom::Existence::DoNotCare;
Expand All @@ -178,18 +184,23 @@ mod tests {
let error = error!(reason);

assert_eq!(error.reason, reason);
assert_eq!(error.arguments, None);
assert_eq!(error.class, Error { arguments: None });
}

#[test]
fn without_arguments_stores_some() {
let reason = Term::str_to_atom("badarg", DoNotCare).unwrap();
let arguments = Term::EMPTY_LIST;

let error = error!(reason, arguments);
let error = error!(reason, Some(arguments));

assert_eq!(error.reason, reason);
assert_eq!(error.arguments, Some(arguments));
assert_eq!(
error.class,
Error {
arguments: Some(arguments)
}
);
}
}
}
6 changes: 5 additions & 1 deletion lumen_runtime/src/otp/erlang.rs
Expand Up @@ -440,7 +440,11 @@ pub fn error_1(reason: Term) -> Result {
}

pub fn error_2(reason: Term, arguments: Term) -> Result {
Err(error!(reason, arguments))
Err(error!(reason, Some(arguments)))
}

pub fn exit_1(reason: Term) -> Result {
Err(exit!(reason))
}

pub fn hd_1(list: Term) -> Result {
Expand Down
1 change: 1 addition & 0 deletions lumen_runtime/src/otp/erlang/tests.rs
Expand Up @@ -30,6 +30,7 @@ mod delete_element_2;
mod element_2;
mod error_1;
mod error_2;
mod exit_1;
mod hd_1;
mod insert_element_3;
mod is_atom_1;
Expand Down
26 changes: 13 additions & 13 deletions lumen_runtime/src/otp/erlang/tests/error_2.rs
Expand Up @@ -19,7 +19,7 @@ fn with_atom_errors_with_atom_reason() {
&mut process,
);

assert_error!(erlang::error_2(reason, arguments), reason, arguments,);
assert_error!(erlang::error_2(reason, arguments), reason, Some(arguments));
}

#[test]
Expand All @@ -30,15 +30,15 @@ fn with_list_reference_errors_with_list_reference_reason() {
let reason = Term::local_reference(&mut process);
let arguments = Term::EMPTY_LIST;

assert_error!(erlang::error_2(reason, arguments), reason, arguments);
assert_error!(erlang::error_2(reason, arguments), reason, Some(arguments));
}

#[test]
fn with_empty_list_errors_with_empty_list_reason() {
let reason = Term::EMPTY_LIST;
let arguments = Term::EMPTY_LIST;

assert_error!(erlang::error_2(reason, arguments), reason, arguments);
assert_error!(erlang::error_2(reason, arguments), reason, Some(arguments));
}

#[test]
Expand All @@ -49,7 +49,7 @@ fn with_list_errors_with_list_reason() {
let reason = list_term(&mut process);
let arguments = Term::cons(list_term(&mut process), Term::EMPTY_LIST, &mut process);

assert_error!(erlang::error_2(reason, arguments), reason, arguments);
assert_error!(erlang::error_2(reason, arguments), reason, Some(arguments));
}

#[test]
Expand All @@ -60,7 +60,7 @@ fn with_small_integer_errors_with_small_integer_reason() {
let reason = 0usize.into_process(&mut process);
let arguments = Term::cons(1.into_process(&mut process), Term::EMPTY_LIST, &mut process);

assert_error!(erlang::error_2(reason, arguments), reason, arguments);
assert_error!(erlang::error_2(reason, arguments), reason, Some(arguments));
}

#[test]
Expand All @@ -79,7 +79,7 @@ fn with_big_integer_errors_with_big_integer_reason() {
&mut process,
);

assert_error!(erlang::error_2(reason, arguments), reason, arguments);
assert_error!(erlang::error_2(reason, arguments), reason, Some(arguments));
}

#[test]
Expand All @@ -94,7 +94,7 @@ fn with_float_errors_with_float_reason() {
&mut process,
);

assert_error!(erlang::error_2(reason, arguments), reason, arguments);
assert_error!(erlang::error_2(reason, arguments), reason, Some(arguments));
}

#[test]
Expand All @@ -109,7 +109,7 @@ fn with_local_pid_errors_with_local_pid_reason() {
&mut process,
);

assert_error!(erlang::error_2(reason, arguments), reason, arguments);
assert_error!(erlang::error_2(reason, arguments), reason, Some(arguments));
}

#[test]
Expand All @@ -124,7 +124,7 @@ fn with_external_pid_errors_with_external_pid_reason() {
&mut process,
);

assert_error!(erlang::error_2(reason, arguments), reason, arguments);
assert_error!(erlang::error_2(reason, arguments), reason, Some(arguments));
}

#[test]
Expand All @@ -139,7 +139,7 @@ fn with_tuple_errors_with_tuple_reason() {
&mut process,
);

assert_error!(erlang::error_2(reason, arguments), reason, arguments);
assert_error!(erlang::error_2(reason, arguments), reason, Some(arguments));
}

#[test]
Expand All @@ -166,7 +166,7 @@ fn with_map_errors_with_map_reason() {
&mut process,
);

assert_error!(erlang::error_2(reason, arguments), reason, arguments);
assert_error!(erlang::error_2(reason, arguments), reason, Some(arguments));
}

#[test]
Expand All @@ -181,7 +181,7 @@ fn with_heap_binary_errors_with_heap_binary_reason() {
&mut process,
);

assert_error!(erlang::error_2(reason, arguments), reason, arguments);
assert_error!(erlang::error_2(reason, arguments), reason, Some(arguments));
}

#[test]
Expand All @@ -199,5 +199,5 @@ fn with_subbinary_errors_with_subbinary_reason() {
let argument = Term::subbinary(argument_original, 0, 2, 1, 0, &mut process);
let arguments = Term::cons(argument, Term::EMPTY_LIST, &mut process);

assert_error!(erlang::error_2(reason, arguments), reason, arguments);
assert_error!(erlang::error_2(reason, arguments), reason, Some(arguments));
}

0 comments on commit da2ae28

Please sign in to comment.