Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

and/2 infix operator #84

Merged
merged 1 commit into from May 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions lumen_runtime/src/atom.rs
Expand Up @@ -7,6 +7,16 @@ use std::sync::{Arc, RwLock};

use crate::exception::Exception;

macro_rules! boolean_infix_operator {
($left:ident, $right:ident, $operator:tt) => {{
let left_bool: bool = $left.try_into()?;
let right_bool: bool = $right.try_into()?;
let output_bool = left_bool $operator right_bool;

Ok(output_bool.into())
}};
}

pub enum Encoding {
Latin1,
Unicode,
Expand Down
3 changes: 2 additions & 1 deletion lumen_runtime/src/lib.rs
Expand Up @@ -26,6 +26,8 @@ mod process;
#[macro_use]
mod exception;
#[macro_use]
mod atom;
#[macro_use]
mod binary;
#[macro_use]
mod integer;
Expand All @@ -34,7 +36,6 @@ mod number;
#[macro_use]
mod support;

mod atom;
mod config;
mod environment;
mod float;
Expand Down
7 changes: 7 additions & 0 deletions lumen_runtime/src/otp/erlang.rs
Expand Up @@ -86,6 +86,13 @@ pub fn add_2(augend: Term, addend: Term, mut process: &mut Process) -> Result {
number_infix_operator!(augend, addend, process, checked_add, +)
}

/// `and/2` infix operator.
///
/// **NOTE: NOT SHORT-CIRCUITING!**
pub fn and_2(left_boolean: Term, right_boolean: Term) -> Result {
boolean_infix_operator!(left_boolean, right_boolean, &)
}

pub fn append_element_2(tuple: Term, element: Term, mut process: &mut Process) -> Result {
let internal: &Tuple = tuple.try_into_in_process(&mut process)?;
let new_tuple = internal.append_element(element, &mut process.term_arena);
Expand Down
1 change: 1 addition & 0 deletions lumen_runtime/src/otp/erlang/tests.rs
Expand Up @@ -8,6 +8,7 @@ use crate::otp::erlang;

mod abs_1;
mod add_2;
mod and_2;
mod append_element_2;
mod atom_to_binary_2;
mod atom_to_list_1;
Expand Down
77 changes: 77 additions & 0 deletions lumen_runtime/src/otp/erlang/tests/and_2.rs
@@ -0,0 +1,77 @@
use super::*;

mod with_false_left;
mod with_true_left;

#[test]
fn with_atom_left_errors_badarg() {
with_left_errors_badarg(|_| Term::str_to_atom("left", DoNotCare).unwrap());
}

#[test]
fn with_local_reference_left_errors_badarg() {
with_left_errors_badarg(|mut process| Term::local_reference(&mut process));
}

#[test]
fn with_empty_list_left_errors_badarg() {
with_left_errors_badarg(|_| Term::EMPTY_LIST);
}

#[test]
fn with_list_left_errors_badarg() {
with_left_errors_badarg(|mut process| {
Term::cons(
0.into_process(&mut process),
1.into_process(&mut process),
&mut process,
)
});
}

#[test]
fn with_float_errors_badarg() {
with_left_errors_badarg(|mut process| 1.0.into_process(&mut process));
}

#[test]
fn with_local_pid_left_errors_badarg() {
with_left_errors_badarg(|_| Term::local_pid(0, 1).unwrap());
}

#[test]
fn with_external_pid_left_errors_badarg() {
with_left_errors_badarg(|mut process| Term::external_pid(1, 2, 3, &mut process).unwrap());
}

#[test]
fn with_tuple_left_errors_badarg() {
with_left_errors_badarg(|mut process| Term::slice_to_tuple(&[], &mut process));
}

#[test]
fn with_map_is_left_errors_badarg() {
with_left_errors_badarg(|mut process| Term::slice_to_map(&[], &mut process));
}

#[test]
fn with_heap_binary_left_errors_badarg() {
with_left_errors_badarg(|mut process| Term::slice_to_binary(&[], &mut process));
}

#[test]
fn with_subbinary_left_errors_badarg() {
with_left_errors_badarg(|mut process| bitstring!(1 ::1, &mut process));
}

fn with_left_errors_badarg<L>(left: L)
where
L: FnOnce(&mut Process) -> Term,
{
super::errors_badarg(|mut process| {
let left = left(&mut process);
let right = 0.into_process(&mut process);

erlang::and_2(left, right)
});
}
111 changes: 111 additions & 0 deletions lumen_runtime/src/otp/erlang/tests/and_2/with_false_left.rs
@@ -0,0 +1,111 @@
use super::*;

#[test]
fn with_atom_right_errors_badarg() {
with_right_errors_badarg(|_| Term::str_to_atom("right", DoNotCare).unwrap());
}

#[test]
fn with_false_right_returns_false() {
with(|left, _| {
assert_eq!(erlang::and_2(left, false.into()), Ok(false.into()));
});
}

#[test]
fn with_true_right_returns_false() {
with(|left, _| {
assert_eq!(erlang::and_2(left, true.into()), Ok(false.into()));
});
}

#[test]
fn with_local_reference_right_errors_badarg() {
with_right_errors_badarg(|mut process| Term::local_reference(&mut process));
}

#[test]
fn with_empty_list_right_errors_badarg() {
with_right_errors_badarg(|_| Term::EMPTY_LIST);
}

#[test]
fn with_list_right_errors_badarg() {
with_right_errors_badarg(|mut process| {
Term::cons(
0.into_process(&mut process),
1.into_process(&mut process),
&mut process,
)
});
}

#[test]
fn with_small_integer_right_errors_badarg() {
with_right_errors_badarg(|mut process| 1.into_process(&mut process))
}

#[test]
fn with_big_integer_right_errors_badarg() {
with_right_errors_badarg(|mut process| {
(crate::integer::small::MAX + 1).into_process(&mut process)
})
}

#[test]
fn with_float_right_errors_badarg() {
with_right_errors_badarg(|mut process| 1.0.into_process(&mut process));
}

#[test]
fn with_local_pid_right_errors_badarg() {
with_right_errors_badarg(|_| Term::local_pid(0, 1).unwrap());
}

#[test]
fn with_external_pid_right_errors_badarg() {
with_right_errors_badarg(|mut process| Term::external_pid(1, 2, 3, &mut process).unwrap());
}

#[test]
fn with_tuple_right_errors_badarg() {
with_right_errors_badarg(|mut process| Term::slice_to_tuple(&[], &mut process));
}

#[test]
fn with_map_is_right_errors_badarg() {
with_right_errors_badarg(|mut process| Term::slice_to_map(&[], &mut process));
}

#[test]
fn with_heap_binary_right_errors_badarg() {
with_right_errors_badarg(|mut process| Term::slice_to_binary(&[], &mut process));
}

#[test]
fn with_subbinary_right_errors_badarg() {
with_right_errors_badarg(|mut process| bitstring!(1 :: 1, &mut process));
}

fn with<F>(f: F)
where
F: FnOnce(Term, &mut Process) -> (),
{
with_process(|mut process| {
let left = false.into();

f(left, &mut process)
})
}

fn with_right_errors_badarg<M>(right: M)
where
M: FnOnce(&mut Process) -> Term,
{
super::errors_badarg(|mut process| {
let left = false.into();
let right = right(&mut process);

erlang::and_2(left, right)
});
}
111 changes: 111 additions & 0 deletions lumen_runtime/src/otp/erlang/tests/and_2/with_true_left.rs
@@ -0,0 +1,111 @@
use super::*;

#[test]
fn with_atom_right_errors_badarg() {
with_right_errors_badarg(|_| Term::str_to_atom("right", DoNotCare).unwrap());
}

#[test]
fn with_false_right_returns_false() {
with(|left, _| {
assert_eq!(erlang::and_2(left, false.into()), Ok(false.into()));
});
}

#[test]
fn with_true_right_returns_true() {
with(|left, _| {
assert_eq!(erlang::and_2(left, true.into()), Ok(true.into()));
});
}

#[test]
fn with_local_reference_right_errors_badarg() {
with_right_errors_badarg(|mut process| Term::local_reference(&mut process));
}

#[test]
fn with_empty_list_right_errors_badarg() {
with_right_errors_badarg(|_| Term::EMPTY_LIST);
}

#[test]
fn with_list_right_errors_badarg() {
with_right_errors_badarg(|mut process| {
Term::cons(
0.into_process(&mut process),
1.into_process(&mut process),
&mut process,
)
});
}

#[test]
fn with_small_integer_right_errors_badarg() {
with_right_errors_badarg(|mut process| 1.into_process(&mut process))
}

#[test]
fn with_big_integer_right_errors_badarg() {
with_right_errors_badarg(|mut process| {
(crate::integer::small::MAX + 1).into_process(&mut process)
})
}

#[test]
fn with_float_right_errors_badarg() {
with_right_errors_badarg(|mut process| 1.0.into_process(&mut process));
}

#[test]
fn with_local_pid_right_errors_badarg() {
with_right_errors_badarg(|_| Term::local_pid(0, 1).unwrap());
}

#[test]
fn with_external_pid_right_errors_badarg() {
with_right_errors_badarg(|mut process| Term::external_pid(1, 2, 3, &mut process).unwrap());
}

#[test]
fn with_tuple_right_errors_badarg() {
with_right_errors_badarg(|mut process| Term::slice_to_tuple(&[], &mut process));
}

#[test]
fn with_map_is_right_errors_badarg() {
with_right_errors_badarg(|mut process| Term::slice_to_map(&[], &mut process));
}

#[test]
fn with_heap_binary_right_errors_badarg() {
with_right_errors_badarg(|mut process| Term::slice_to_binary(&[], &mut process));
}

#[test]
fn with_subbinary_right_errors_badarg() {
with_right_errors_badarg(|mut process| bitstring!(1 :: 1, &mut process));
}

fn with<F>(f: F)
where
F: FnOnce(Term, &mut Process) -> (),
{
with_process(|mut process| {
let left = true.into();

f(left, &mut process)
})
}

fn with_right_errors_badarg<M>(right: M)
where
M: FnOnce(&mut Process) -> Term,
{
super::errors_badarg(|mut process| {
let left = true.into();
let right = right(&mut process);

erlang::and_2(left, right)
});
}
15 changes: 15 additions & 0 deletions lumen_runtime/src/term.rs
Expand Up @@ -1220,6 +1220,21 @@ impl TryFrom<Term> for Class {
}
}

impl TryFrom<Term> for bool {
type Error = Exception;

fn try_from(term: Term) -> Result<bool, Exception> {
match term.tag() {
Atom => match unsafe { term.atom_to_string() }.as_ref().as_ref() {
"false" => Ok(false),
"true" => Ok(true),
_ => Err(badarg!()),
},
_ => Err(badarg!()),
}
}
}

impl TryFrom<Term> for char {
type Error = Exception;

Expand Down