Skip to content

Commit

Permalink
Merge pull request #34 from lumen/is_map_key
Browse files Browse the repository at this point in the history
:erlang.is_map_key/2
  • Loading branch information
bitwalker committed May 21, 2019
2 parents 8df804d + 52d7faf commit 685310a
Show file tree
Hide file tree
Showing 14 changed files with 835 additions and 19 deletions.
38 changes: 38 additions & 0 deletions lumen_runtime/src/binary/heap.rs
@@ -1,4 +1,5 @@
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};

use crate::atom::{self, Existence};
use crate::binary::{
Expand Down Expand Up @@ -121,6 +122,16 @@ impl DebugInProcess for Binary {
}
}

impl Eq for Binary {}

impl Hash for Binary {
fn hash<H: Hasher>(&self, state: &mut H) {
for byte in self.byte_iter() {
byte.hash(state);
}
}
}

pub struct Iter {
pointer: *const u8,
limit: *const u8,
Expand Down Expand Up @@ -191,6 +202,33 @@ impl<'b, 'a: 'b> Part<'a, usize, isize, binary::Binary<'b>> for Binary {
}
}

impl PartialEq for Binary {
fn eq(&self, other: &Binary) -> bool {
match self.header.tagged == other.header.tagged {
true => {
let mut final_eq = true;

for (self_element, other_element) in self.iter().zip(other.iter()) {
match self_element == other_element {
true => continue,
eq => {
final_eq = eq;
break;
}
}
}

final_eq
}
eq => eq,
}
}

fn ne(&self, other: &Binary) -> bool {
!self.eq(other)
}
}

impl PartToList<usize, isize> for Binary {
fn part_to_list(
&self,
Expand Down
33 changes: 33 additions & 0 deletions lumen_runtime/src/binary/sub.rs
@@ -1,4 +1,5 @@
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use std::iter::FusedIterator;

use crate::atom::{self, Existence};
Expand Down Expand Up @@ -160,6 +161,38 @@ impl Binary {
}
}

impl Eq for Binary {}

impl Hash for Binary {
fn hash<H: Hasher>(&self, state: &mut H) {
for byte in self.byte_iter() {
byte.hash(state);
}

for bit in self.bit_count_iter() {
bit.hash(state);
}
}
}

impl PartialEq for Binary {
fn eq(&self, other: &Binary) -> bool {
(self.bit_size() == other.bit_size())
& self
.byte_iter()
.zip(other.byte_iter())
.all(|(self_byte, other_byte)| self_byte == other_byte)
& self
.bit_count_iter()
.zip(other.bit_count_iter())
.all(|(self_bit, other_bit)| self_bit == other_bit)
}

fn ne(&self, other: &Binary) -> bool {
!self.eq(other)
}
}

impl ToTerm for Binary {
fn to_term(&self, options: ToTermOptions, mut process: &mut Process) -> exception::Result {
if self.bit_count == 0 {
Expand Down
51 changes: 38 additions & 13 deletions lumen_runtime/src/exception.rs
Expand Up @@ -48,31 +48,40 @@ macro_rules! assert_bad_argument {
)
}};
($left:expr, $process:expr,) => {{
assert_bad_argument!($left, $process)
}};
}

#[macro_export]
macro_rules! assert_bad_map {
($left:expr, $map:expr, $process:expr) => {{
use crate::atom::Existence::DoNotCare;
use crate::term::Term;

assert_error!(
$left,
Term::str_to_atom("badarg", DoNotCare, $process).unwrap(),
$process
)
let badmap = Term::str_to_atom("badmap", DoNotCare, $process).unwrap();
let reason = Term::slice_to_tuple(&[badmap, $map], $process);

assert_error!($left, reason, $process)
}};
($left:expr, $map:expr, $process:expr,) => {{
assert_bad_map($left, $map, $process)
}};
}

#[macro_export]
macro_rules! assert_error {
($left:expr, $reason:expr, $process:expr) => {{
($left:expr, $reason:expr, $process:expr) => {
assert_eq_in_process!($left, Err(error!($reason)), $process)
}};
($left:expr, $reason:expr, $process:expr,) => {{
};
($left:expr, $reason:expr, $process:expr,) => {
assert_eq_in_process!($left, Err(error!($reason)), $process)
}};
($left:expr, $reason:expr, $arguments:expr, $process:expr) => {{
};
($left:expr, $reason:expr, $arguments:expr, $process:expr) => {
assert_eq_in_process!($left, Err(error!($reason, $arguments)), $process)
}};
($left:expr, $reason:expr, $arguments:expr, $process:expr,) => {{
};
($left:expr, $reason:expr, $arguments:expr, $process:expr,) => {
assert_eq_in_process!($left, Err(error!($reason, $arguments)), $process)
}};
};
}

#[macro_export]
Expand All @@ -85,6 +94,22 @@ macro_rules! bad_argument {
}};
}

#[macro_export]
macro_rules! bad_map {
($map:expr, $process:expr) => {{
use crate::atom::Existence::DoNotCare;
use crate::term::Term;

let badmap = Term::str_to_atom("badmap", DoNotCare, $process).unwrap();
let reason = Term::slice_to_tuple(&[badmap, map], $process);

error!(reason)
}};
($map:expr, $process:expr,) => {{
bad_map!($map, $process)
}};
}

#[macro_export]
macro_rules! error {
($reason:expr) => {{
Expand Down
20 changes: 20 additions & 0 deletions lumen_runtime/src/float.rs
@@ -1,3 +1,5 @@
use std::hash::{Hash, Hasher};

use crate::term::{Tag, Term};

pub struct Float {
Expand All @@ -16,3 +18,21 @@ impl Float {
}
}
}

impl Eq for Float {}

impl Hash for Float {
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner.to_bits().hash(state)
}
}

impl PartialEq for Float {
fn eq(&self, other: &Float) -> bool {
self.inner == other.inner
}

fn ne(&self, other: &Float) -> bool {
!self.eq(other)
}
}
20 changes: 20 additions & 0 deletions lumen_runtime/src/integer/big.rs
@@ -1,3 +1,5 @@
use std::hash::{Hash, Hasher};

use num_bigint::{BigInt, Sign::*};

use crate::exception::Exception;
Expand All @@ -21,6 +23,24 @@ impl Integer {
}
}

impl Eq for Integer {}

impl Hash for Integer {
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner.hash(state)
}
}

impl PartialEq for Integer {
fn eq(&self, other: &Integer) -> bool {
self.inner == other.inner
}

fn ne(&self, other: &Integer) -> bool {
!self.eq(other)
}
}

impl TryFromInProcess<Integer> for usize {
fn try_from_in_process(
integer: Integer,
Expand Down
20 changes: 20 additions & 0 deletions lumen_runtime/src/list.rs
@@ -1,6 +1,7 @@
#![cfg_attr(not(test), allow(dead_code))]

use std::cmp::Ordering;
use std::hash::{Hash, Hasher};

use crate::exception::Exception;
use crate::process::{DebugInProcess, IntoProcess, OrderInProcess, Process, TryIntoInProcess};
Expand Down Expand Up @@ -155,6 +156,15 @@ impl DebugInProcess for Cons {
}
}

impl Eq for Cons {}

impl Hash for Cons {
fn hash<H: Hasher>(&self, state: &mut H) {
self.head.hash(state);
self.tail.hash(state);
}
}

impl OrderInProcess for Cons {
fn cmp_in_process(&self, other: &Cons, process: &Process) -> Ordering {
match self.head.cmp_in_process(&other.head, process) {
Expand All @@ -164,6 +174,16 @@ impl OrderInProcess for Cons {
}
}

impl PartialEq for Cons {
fn eq(&self, other: &Cons) -> bool {
self.head == other.head && self.tail == other.tail
}

fn ne(&self, other: &Cons) -> bool {
!self.eq(other)
}
}

pub trait ToList {
fn to_list(&mut self, process: &mut Process) -> Term;
}
Expand Down
4 changes: 4 additions & 0 deletions lumen_runtime/src/map.rs
Expand Up @@ -33,6 +33,10 @@ impl Map {
inner,
}
}

pub fn is_key(&self, key: Term) -> bool {
self.inner.contains_key(&key)
}
}

impl OrderInProcess for Map {
Expand Down
24 changes: 24 additions & 0 deletions lumen_runtime/src/otp/erlang.rs
Expand Up @@ -14,6 +14,7 @@ use crate::exception::Result;
use crate::float::Float;
use crate::integer::{big, small};
use crate::list::Cons;
use crate::map::Map;
use crate::otp;
use crate::process::{IntoProcess, Process, TryIntoInProcess};
use crate::term::{Tag, Term};
Expand Down Expand Up @@ -518,6 +519,29 @@ pub fn is_map(term: Term, mut process: &mut Process) -> Term {
.into_process(&mut process)
}

pub fn is_map_key(key: Term, map: Term, mut process: &mut Process) -> Result {
match map.tag() {
Tag::Boxed => {
let unboxed_map: &Term = map.unbox_reference();

match unboxed_map.tag() {
Tag::Map => {
let map_map: &Map = map.unbox_reference();
Some(map_map.is_key(key).into_process(&mut process))
}
_ => None,
}
}
_ => None,
}
.ok_or_else(|| {
let badmap = Term::str_to_atom("badmap", Existence::DoNotCare, &mut process).unwrap();
let reason = Term::slice_to_tuple(&[badmap, map], &mut process);

error!(reason)
})
}

pub fn is_pid(term: Term, mut process: &mut Process) -> Term {
match term.tag() {
Tag::LocalPid => true,
Expand Down
1 change: 1 addition & 0 deletions lumen_runtime/src/otp/erlang/tests.rs
Expand Up @@ -32,6 +32,7 @@ mod is_binary;
mod is_integer;
mod is_list;
mod is_map;
mod is_map_key;
mod is_pid;
mod is_tuple;
mod length;
Expand Down

0 comments on commit 685310a

Please sign in to comment.