From 3b345acebf53fc5b044718132917fb721a7ae679 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sun, 20 Jun 2021 21:42:13 +0800 Subject: [PATCH 1/3] Impl returns closures. --- src/fn_builtin.rs | 472 +++++++++++++++++++++------------------------- 1 file changed, 218 insertions(+), 254 deletions(-) diff --git a/src/fn_builtin.rs b/src/fn_builtin.rs index 727da5f4..d01e8381 100644 --- a/src/fn_builtin.rs +++ b/src/fn_builtin.rs @@ -76,75 +76,55 @@ pub fn get_builtin_binary_op_fn( let types_pair = (type1, type2); macro_rules! impl_op { - ($xx:ident $op:tt $yy:ident) => { - Some(|_, args| { - let x = &*args[0].read_lock::<$xx>().expect(BUILTIN); - let y = &*args[1].read_lock::<$yy>().expect(BUILTIN); - Ok((x $op y).into()) - }) - }; - ($xx:ident . $func:ident ( $yy:ty )) => { - Some(|_, args| { - let x = &*args[0].read_lock::<$xx>().expect(BUILTIN); - let y = &*args[1].read_lock::<$yy>().expect(BUILTIN); - Ok(x.$func(y).into()) - }) - }; - ($xx:ident . $func:ident ( $yy:ident . $yyy:ident () )) => { - Some(|_, args| { - let x = &*args[0].read_lock::<$xx>().expect(BUILTIN); - let y = &*args[1].read_lock::<$yy>().expect(BUILTIN); - Ok(x.$func(y.$yyy()).into()) - }) - }; - ($func:ident ( $op:tt )) => { - Some(|_, args| { - let (x, y) = $func(args); - Ok((x $op y).into()) - }) - }; - ($base:ty => $xx:ident $op:tt $yy:ident) => { - Some(|_, args| { - let x = args[0].$xx().expect(BUILTIN) as $base; - let y = args[1].$yy().expect(BUILTIN) as $base; - Ok((x $op y).into()) - }) - }; - ($base:ty => $xx:ident . $func:ident ( $yy:ident as $yyy:ty)) => { - Some(|_, args| { - let x = args[0].$xx().expect(BUILTIN) as $base; - let y = args[1].$yy().expect(BUILTIN) as $base; - Ok(x.$func(y as $yyy).into()) - }) - }; - ($base:ty => $func:ident ( $xx:ident, $yy:ident )) => { - Some(|_, args| { - let x = args[0].$xx().expect(BUILTIN) as $base; - let y = args[1].$yy().expect(BUILTIN) as $base; - $func(x, y).map(Into::::into) - }) - }; - (from $base:ty => $xx:ident $op:tt $yy:ident) => { - Some(|_, args| { - let x = <$base>::from(args[0].$xx().expect(BUILTIN)); - let y = <$base>::from(args[1].$yy().expect(BUILTIN)); - Ok((x $op y).into()) - }) - }; - (from $base:ty => $xx:ident . $func:ident ( $yy:ident )) => { - Some(|_, args| { - let x = <$base>::from(args[0].$xx().expect(BUILTIN)); - let y = <$base>::from(args[1].$yy().expect(BUILTIN)); - Ok(x.$func(y).into()) - }) - }; - (from $base:ty => $func:ident ( $xx:ident, $yy:ident )) => { - Some(|_, args| { - let x = <$base>::from(args[0].$xx().expect(BUILTIN)); - let y = <$base>::from(args[1].$yy().expect(BUILTIN)); - $func(x, y).map(Into::::into) - }) - }; + ($xx:ident $op:tt $yy:ident) => { |_, args| { + let x = &*args[0].read_lock::<$xx>().expect(BUILTIN); + let y = &*args[1].read_lock::<$yy>().expect(BUILTIN); + Ok((x $op y).into()) + } }; + ($xx:ident . $func:ident ( $yy:ty )) => { |_, args| { + let x = &*args[0].read_lock::<$xx>().expect(BUILTIN); + let y = &*args[1].read_lock::<$yy>().expect(BUILTIN); + Ok(x.$func(y).into()) + } }; + ($xx:ident . $func:ident ( $yy:ident . $yyy:ident () )) => { |_, args| { + let x = &*args[0].read_lock::<$xx>().expect(BUILTIN); + let y = &*args[1].read_lock::<$yy>().expect(BUILTIN); + Ok(x.$func(y.$yyy()).into()) + } }; + ($func:ident ( $op:tt )) => { |_, args| { + let (x, y) = $func(args); + Ok((x $op y).into()) + } }; + ($base:ty => $xx:ident $op:tt $yy:ident) => { |_, args| { + let x = args[0].$xx().expect(BUILTIN) as $base; + let y = args[1].$yy().expect(BUILTIN) as $base; + Ok((x $op y).into()) + } }; + ($base:ty => $xx:ident . $func:ident ( $yy:ident as $yyy:ty)) => { |_, args| { + let x = args[0].$xx().expect(BUILTIN) as $base; + let y = args[1].$yy().expect(BUILTIN) as $base; + Ok(x.$func(y as $yyy).into()) + } }; + ($base:ty => $func:ident ( $xx:ident, $yy:ident )) => { |_, args| { + let x = args[0].$xx().expect(BUILTIN) as $base; + let y = args[1].$yy().expect(BUILTIN) as $base; + $func(x, y).map(Into::::into) + } }; + (from $base:ty => $xx:ident $op:tt $yy:ident) => { |_, args| { + let x = <$base>::from(args[0].$xx().expect(BUILTIN)); + let y = <$base>::from(args[1].$yy().expect(BUILTIN)); + Ok((x $op y).into()) + } }; + (from $base:ty => $xx:ident . $func:ident ( $yy:ident )) => { |_, args| { + let x = <$base>::from(args[0].$xx().expect(BUILTIN)); + let y = <$base>::from(args[1].$yy().expect(BUILTIN)); + Ok(x.$func(y).into()) + } }; + (from $base:ty => $func:ident ( $xx:ident, $yy:ident )) => { |_, args| { + let x = <$base>::from(args[0].$xx().expect(BUILTIN)); + let y = <$base>::from(args[1].$yy().expect(BUILTIN)); + $func(x, y).map(Into::::into) + } }; } macro_rules! impl_float { @@ -152,18 +132,18 @@ pub fn get_builtin_binary_op_fn( #[cfg(not(feature = "no_float"))] if types_pair == (TypeId::of::<$x>(), TypeId::of::<$y>()) { return match op { - "+" => impl_op!(FLOAT => $xx + $yy), - "-" => impl_op!(FLOAT => $xx - $yy), - "*" => impl_op!(FLOAT => $xx * $yy), - "/" => impl_op!(FLOAT => $xx / $yy), - "%" => impl_op!(FLOAT => $xx % $yy), - "**" => impl_op!(FLOAT => $xx.powf($yy as FLOAT)), - "==" => impl_op!(FLOAT => $xx == $yy), - "!=" => impl_op!(FLOAT => $xx != $yy), - ">" => impl_op!(FLOAT => $xx > $yy), - ">=" => impl_op!(FLOAT => $xx >= $yy), - "<" => impl_op!(FLOAT => $xx < $yy), - "<=" => impl_op!(FLOAT => $xx <= $yy), + "+" => Some(impl_op!(FLOAT => $xx + $yy)), + "-" => Some(impl_op!(FLOAT => $xx - $yy)), + "*" => Some(impl_op!(FLOAT => $xx * $yy)), + "/" => Some(impl_op!(FLOAT => $xx / $yy)), + "%" => Some(impl_op!(FLOAT => $xx % $yy)), + "**" => Some(impl_op!(FLOAT => $xx.powf($yy as FLOAT))), + "==" => Some(impl_op!(FLOAT => $xx == $yy)), + "!=" => Some(impl_op!(FLOAT => $xx != $yy)), + ">" => Some(impl_op!(FLOAT => $xx > $yy)), + ">=" => Some(impl_op!(FLOAT => $xx >= $yy)), + "<" => Some(impl_op!(FLOAT => $xx < $yy)), + "<=" => Some(impl_op!(FLOAT => $xx <= $yy)), _ => None, }; } @@ -183,12 +163,12 @@ pub fn get_builtin_binary_op_fn( #[cfg(not(feature = "unchecked"))] match op { - "+" => return impl_op!(from Decimal => add($xx, $yy)), - "-" => return impl_op!(from Decimal => subtract($xx, $yy)), - "*" => return impl_op!(from Decimal => multiply($xx, $yy)), - "/" => return impl_op!(from Decimal => divide($xx, $yy)), - "%" => return impl_op!(from Decimal => modulo($xx, $yy)), - "**" => return impl_op!(from Decimal => power($xx, $yy)), + "+" => return Some(impl_op!(from Decimal => add($xx, $yy))), + "-" => return Some(impl_op!(from Decimal => subtract($xx, $yy))), + "*" => return Some(impl_op!(from Decimal => multiply($xx, $yy))), + "/" => return Some(impl_op!(from Decimal => divide($xx, $yy))), + "%" => return Some(impl_op!(from Decimal => modulo($xx, $yy))), + "**" => return Some(impl_op!(from Decimal => power($xx, $yy))), _ => () } @@ -197,22 +177,22 @@ pub fn get_builtin_binary_op_fn( #[cfg(feature = "unchecked")] match op { - "+" => return impl_op!(from Decimal => $xx + $yy), - "-" => return impl_op!(from Decimal => $xx - $yy), - "*" => return impl_op!(from Decimal => $xx * $yy), - "/" => return impl_op!(from Decimal => $xx / $yy), - "%" => return impl_op!(from Decimal => $xx % $yy), - "**" => return impl_op!(from Decimal => $xx.powd($yy)), + "+" => return Some(impl_op!(from Decimal => $xx + $yy)), + "-" => return Some(impl_op!(from Decimal => $xx - $yy)), + "*" => return Some(impl_op!(from Decimal => $xx * $yy)), + "/" => return Some(impl_op!(from Decimal => $xx / $yy)), + "%" => return Some(impl_op!(from Decimal => $xx % $yy)), + "**" => return Some(impl_op!(from Decimal => $xx.powd($yy))), _ => () } return match op { - "==" => impl_op!(from Decimal => $xx == $yy), - "!=" => impl_op!(from Decimal => $xx != $yy), - ">" => impl_op!(from Decimal => $xx > $yy), - ">=" => impl_op!(from Decimal => $xx >= $yy), - "<" => impl_op!(from Decimal => $xx < $yy), - "<=" => impl_op!(from Decimal => $xx <= $yy), + "==" => Some(impl_op!(from Decimal => $xx == $yy)), + "!=" => Some(impl_op!(from Decimal => $xx != $yy)), + ">" => Some(impl_op!(from Decimal => $xx > $yy)), + ">=" => Some(impl_op!(from Decimal => $xx >= $yy)), + "<" => Some(impl_op!(from Decimal => $xx < $yy)), + "<=" => Some(impl_op!(from Decimal => $xx <= $yy)), _ => None }; } @@ -241,12 +221,12 @@ pub fn get_builtin_binary_op_fn( let y = &*args[1].read_lock::().expect(BUILTIN); Ok(format!("{}{}", x, y).into()) }), - "==" => impl_op!(get_s1s2(==)), - "!=" => impl_op!(get_s1s2(!=)), - ">" => impl_op!(get_s1s2(>)), - ">=" => impl_op!(get_s1s2(>=)), - "<" => impl_op!(get_s1s2(<)), - "<=" => impl_op!(get_s1s2(<=)), + "==" => Some(impl_op!(get_s1s2(==))), + "!=" => Some(impl_op!(get_s1s2(!=))), + ">" => Some(impl_op!(get_s1s2(>))), + ">=" => Some(impl_op!(get_s1s2(>=))), + "<" => Some(impl_op!(get_s1s2(<))), + "<=" => Some(impl_op!(get_s1s2(<=))), _ => None, }; } @@ -273,12 +253,12 @@ pub fn get_builtin_binary_op_fn( let y = args[1].as_char().expect(BUILTIN); Ok((x - y).into()) }), - "==" => impl_op!(get_s1s2(==)), - "!=" => impl_op!(get_s1s2(!=)), - ">" => impl_op!(get_s1s2(>)), - ">=" => impl_op!(get_s1s2(>=)), - "<" => impl_op!(get_s1s2(<)), - "<=" => impl_op!(get_s1s2(<=)), + "==" => Some(impl_op!(get_s1s2(==))), + "!=" => Some(impl_op!(get_s1s2(!=))), + ">" => Some(impl_op!(get_s1s2(>))), + ">=" => Some(impl_op!(get_s1s2(>=))), + "<" => Some(impl_op!(get_s1s2(<))), + "<=" => Some(impl_op!(get_s1s2(<=))), OP_CONTAINS => Some(|_, args| { let s = &*args[0].read_lock::().expect(BUILTIN); let c = args[1].as_char().expect(BUILTIN); @@ -294,7 +274,7 @@ pub fn get_builtin_binary_op_fn( use crate::Map; return match op { - OP_CONTAINS => impl_op!(Map.contains_key(ImmutableString.as_str())), + OP_CONTAINS => Some(impl_op!(Map.contains_key(ImmutableString.as_str()))), _ => None, }; } @@ -316,69 +296,69 @@ pub fn get_builtin_binary_op_fn( #[cfg(not(feature = "unchecked"))] match op { - "+" => return impl_op!(INT => add(as_int, as_int)), - "-" => return impl_op!(INT => subtract(as_int, as_int)), - "*" => return impl_op!(INT => multiply(as_int, as_int)), - "/" => return impl_op!(INT => divide(as_int, as_int)), - "%" => return impl_op!(INT => modulo(as_int, as_int)), - "**" => return impl_op!(INT => power(as_int, as_int)), - ">>" => return impl_op!(INT => shift_right(as_int, as_int)), - "<<" => return impl_op!(INT => shift_left(as_int, as_int)), + "+" => return Some(impl_op!(INT => add(as_int, as_int))), + "-" => return Some(impl_op!(INT => subtract(as_int, as_int))), + "*" => return Some(impl_op!(INT => multiply(as_int, as_int))), + "/" => return Some(impl_op!(INT => divide(as_int, as_int))), + "%" => return Some(impl_op!(INT => modulo(as_int, as_int))), + "**" => return Some(impl_op!(INT => power(as_int, as_int))), + ">>" => return Some(impl_op!(INT => shift_right(as_int, as_int))), + "<<" => return Some(impl_op!(INT => shift_left(as_int, as_int))), _ => (), } #[cfg(feature = "unchecked")] match op { - "+" => return impl_op!(INT => as_int + as_int), - "-" => return impl_op!(INT => as_int - as_int), - "*" => return impl_op!(INT => as_int * as_int), - "/" => return impl_op!(INT => as_int / as_int), - "%" => return impl_op!(INT => as_int % as_int), - "**" => return impl_op!(INT => as_int.pow(as_int as u32)), - ">>" => return impl_op!(INT => as_int >> as_int), - "<<" => return impl_op!(INT => as_int << as_int), + "+" => return Some(impl_op!(INT => as_int + as_int)), + "-" => return Some(impl_op!(INT => as_int - as_int)), + "*" => return Some(impl_op!(INT => as_int * as_int)), + "/" => return Some(impl_op!(INT => as_int / as_int)), + "%" => return Some(impl_op!(INT => as_int % as_int)), + "**" => return Some(impl_op!(INT => as_int.pow(as_int as u32))), + ">>" => return Some(impl_op!(INT => as_int >> as_int)), + "<<" => return Some(impl_op!(INT => as_int << as_int)), _ => (), } return match op { - "==" => impl_op!(INT => as_int == as_int), - "!=" => impl_op!(INT => as_int != as_int), - ">" => impl_op!(INT => as_int > as_int), - ">=" => impl_op!(INT => as_int >= as_int), - "<" => impl_op!(INT => as_int < as_int), - "<=" => impl_op!(INT => as_int <= as_int), - "&" => impl_op!(INT => as_int & as_int), - "|" => impl_op!(INT => as_int | as_int), - "^" => impl_op!(INT => as_int ^ as_int), + "==" => Some(impl_op!(INT => as_int == as_int)), + "!=" => Some(impl_op!(INT => as_int != as_int)), + ">" => Some(impl_op!(INT => as_int > as_int)), + ">=" => Some(impl_op!(INT => as_int >= as_int)), + "<" => Some(impl_op!(INT => as_int < as_int)), + "<=" => Some(impl_op!(INT => as_int <= as_int)), + "&" => Some(impl_op!(INT => as_int & as_int)), + "|" => Some(impl_op!(INT => as_int | as_int)), + "^" => Some(impl_op!(INT => as_int ^ as_int)), _ => None, }; } if type1 == TypeId::of::() { return match op { - "==" => impl_op!(bool => as_bool == as_bool), - "!=" => impl_op!(bool => as_bool != as_bool), - ">" => impl_op!(bool => as_bool > as_bool), - ">=" => impl_op!(bool => as_bool >= as_bool), - "<" => impl_op!(bool => as_bool < as_bool), - "<=" => impl_op!(bool => as_bool <= as_bool), - "&" => impl_op!(bool => as_bool & as_bool), - "|" => impl_op!(bool => as_bool | as_bool), - "^" => impl_op!(bool => as_bool ^ as_bool), + "==" => Some(impl_op!(bool => as_bool == as_bool)), + "!=" => Some(impl_op!(bool => as_bool != as_bool)), + ">" => Some(impl_op!(bool => as_bool > as_bool)), + ">=" => Some(impl_op!(bool => as_bool >= as_bool)), + "<" => Some(impl_op!(bool => as_bool < as_bool)), + "<=" => Some(impl_op!(bool => as_bool <= as_bool)), + "&" => Some(impl_op!(bool => as_bool & as_bool)), + "|" => Some(impl_op!(bool => as_bool | as_bool)), + "^" => Some(impl_op!(bool => as_bool ^ as_bool)), _ => None, }; } if type1 == TypeId::of::() { return match op { - "+" => impl_op!(ImmutableString + ImmutableString), - "-" => impl_op!(ImmutableString - ImmutableString), - "==" => impl_op!(ImmutableString == ImmutableString), - "!=" => impl_op!(ImmutableString != ImmutableString), - ">" => impl_op!(ImmutableString > ImmutableString), - ">=" => impl_op!(ImmutableString >= ImmutableString), - "<" => impl_op!(ImmutableString < ImmutableString), - "<=" => impl_op!(ImmutableString <= ImmutableString), + "+" => Some(impl_op!(ImmutableString + ImmutableString)), + "-" => Some(impl_op!(ImmutableString - ImmutableString)), + "==" => Some(impl_op!(ImmutableString == ImmutableString)), + "!=" => Some(impl_op!(ImmutableString != ImmutableString)), + ">" => Some(impl_op!(ImmutableString > ImmutableString)), + ">=" => Some(impl_op!(ImmutableString >= ImmutableString)), + "<" => Some(impl_op!(ImmutableString < ImmutableString)), + "<=" => Some(impl_op!(ImmutableString <= ImmutableString)), OP_CONTAINS => Some(|_, args| { let s1 = &*args[0].read_lock::().expect(BUILTIN); let s2 = &*args[1].read_lock::().expect(BUILTIN); @@ -395,12 +375,12 @@ pub fn get_builtin_binary_op_fn( let y = args[1].as_char().expect(BUILTIN); Ok(format!("{}{}", x, y).into()) }), - "==" => impl_op!(char => as_char == as_char), - "!=" => impl_op!(char => as_char != as_char), - ">" => impl_op!(char => as_char > as_char), - ">=" => impl_op!(char => as_char >= as_char), - "<" => impl_op!(char => as_char < as_char), - "<=" => impl_op!(char => as_char <= as_char), + "==" => Some(impl_op!(char => as_char == as_char)), + "!=" => Some(impl_op!(char => as_char != as_char)), + ">" => Some(impl_op!(char => as_char > as_char)), + ">=" => Some(impl_op!(char => as_char >= as_char)), + "<" => Some(impl_op!(char => as_char < as_char)), + "<=" => Some(impl_op!(char => as_char <= as_char)), _ => None, }; } @@ -433,59 +413,43 @@ pub fn get_builtin_op_assignment_fn( let types_pair = (type1, type2); macro_rules! impl_op { - ($x:ty = x $op:tt $yy:ident) => { - Some(|_, args| { - let x = args[0].$yy().expect(BUILTIN); - let y = args[1].$yy().expect(BUILTIN) as $x; - Ok((*args[0].write_lock::<$x>().expect(BUILTIN) = x $op y).into()) - }) - }; - ($x:ident $op:tt $yy:ident) => { - Some(|_, args| { - let y = args[1].$yy().expect(BUILTIN) as $x; - Ok((*args[0].write_lock::<$x>().expect(BUILTIN) $op y).into()) - }) - }; - ($x:ident $op:tt $yy:ident as $yyy:ty) => { - Some(|_, args| { - let y = args[1].$yy().expect(BUILTIN) as $yyy; - Ok((*args[0].write_lock::<$x>().expect(BUILTIN) $op y).into()) - }) - }; - ($x:ty => $xx:ident . $func:ident ( $yy:ident as $yyy:ty )) => { - Some(|_, args| { - let x = args[0].$xx().expect(BUILTIN); - let y = args[1].$yy().expect(BUILTIN) as $x; - Ok((*args[0].write_lock::<$x>().expect(BUILTIN) = x.$func(y as $yyy)).into()) - }) - }; - ($x:ty => $func:ident ( $xx:ident, $yy:ident )) => { - Some(|_, args| { - let x = args[0].$xx().expect(BUILTIN); - let y = args[1].$yy().expect(BUILTIN) as $x; - Ok((*args[0].write_lock().expect(BUILTIN) = $func(x, y)?).into()) - }) - }; - (from $x:ident $op:tt $yy:ident) => { - Some(|_, args| { - let y = <$x>::from(args[1].$yy().expect(BUILTIN)); - Ok((*args[0].write_lock::<$x>().expect(BUILTIN) $op y).into()) - }) - }; - (from $x:ty => $xx:ident . $func:ident ( $yy:ident )) => { - Some(|_, args| { - let x = args[0].$xx().expect(BUILTIN); - let y = <$x>::from(args[1].$yy().expect(BUILTIN)); - Ok((*args[0].write_lock::<$x>().expect(BUILTIN) = x.$func(y)).into()) - }) - }; - (from $x:ty => $func:ident ( $xx:ident, $yy:ident )) => { - Some(|_, args| { - let x = args[0].$xx().expect(BUILTIN); - let y = <$x>::from(args[1].$yy().expect(BUILTIN)); - Ok((*args[0].write_lock().expect(BUILTIN) = $func(x, y)?).into()) - }) - }; + ($x:ty = x $op:tt $yy:ident) => { |_, args| { + let x = args[0].$yy().expect(BUILTIN); + let y = args[1].$yy().expect(BUILTIN) as $x; + Ok((*args[0].write_lock::<$x>().expect(BUILTIN) = x $op y).into()) + } }; + ($x:ident $op:tt $yy:ident) => { |_, args| { + let y = args[1].$yy().expect(BUILTIN) as $x; + Ok((*args[0].write_lock::<$x>().expect(BUILTIN) $op y).into()) + } }; + ($x:ident $op:tt $yy:ident as $yyy:ty) => { |_, args| { + let y = args[1].$yy().expect(BUILTIN) as $yyy; + Ok((*args[0].write_lock::<$x>().expect(BUILTIN) $op y).into()) + } }; + ($x:ty => $xx:ident . $func:ident ( $yy:ident as $yyy:ty )) => { |_, args| { + let x = args[0].$xx().expect(BUILTIN); + let y = args[1].$yy().expect(BUILTIN) as $x; + Ok((*args[0].write_lock::<$x>().expect(BUILTIN) = x.$func(y as $yyy)).into()) + } }; + ($x:ty => $func:ident ( $xx:ident, $yy:ident )) => { |_, args| { + let x = args[0].$xx().expect(BUILTIN); + let y = args[1].$yy().expect(BUILTIN) as $x; + Ok((*args[0].write_lock().expect(BUILTIN) = $func(x, y)?).into()) + } }; + (from $x:ident $op:tt $yy:ident) => { |_, args| { + let y = <$x>::from(args[1].$yy().expect(BUILTIN)); + Ok((*args[0].write_lock::<$x>().expect(BUILTIN) $op y).into()) + } }; + (from $x:ty => $xx:ident . $func:ident ( $yy:ident )) => { |_, args| { + let x = args[0].$xx().expect(BUILTIN); + let y = <$x>::from(args[1].$yy().expect(BUILTIN)); + Ok((*args[0].write_lock::<$x>().expect(BUILTIN) = x.$func(y)).into()) + } }; + (from $x:ty => $func:ident ( $xx:ident, $yy:ident )) => { |_, args| { + let x = args[0].$xx().expect(BUILTIN); + let y = <$x>::from(args[1].$yy().expect(BUILTIN)); + Ok((*args[0].write_lock().expect(BUILTIN) = $func(x, y)?).into()) + } }; } macro_rules! impl_float { @@ -493,12 +457,12 @@ pub fn get_builtin_op_assignment_fn( #[cfg(not(feature = "no_float"))] if types_pair == (TypeId::of::<$x>(), TypeId::of::<$y>()) { return match op { - "+=" => impl_op!($x += $yy), - "-=" => impl_op!($x -= $yy), - "*=" => impl_op!($x *= $yy), - "/=" => impl_op!($x /= $yy), - "%=" => impl_op!($x %= $yy), - "**=" => impl_op!($x => $xx.powf($yy as $x)), + "+=" => Some(impl_op!($x += $yy)), + "-=" => Some(impl_op!($x -= $yy)), + "*=" => Some(impl_op!($x *= $yy)), + "/=" => Some(impl_op!($x /= $yy)), + "%=" => Some(impl_op!($x %= $yy)), + "**=" => Some(impl_op!($x => $xx.powf($yy as $x))), _ => None, }; } @@ -517,12 +481,12 @@ pub fn get_builtin_op_assignment_fn( #[cfg(not(feature = "unchecked"))] return match op { - "+=" => impl_op!(from $x => add($xx, $yy)), - "-=" => impl_op!(from $x => subtract($xx, $yy)), - "*=" => impl_op!(from $x => multiply($xx, $yy)), - "/=" => impl_op!(from $x => divide($xx, $yy)), - "%=" => impl_op!(from $x => modulo($xx, $yy)), - "**=" => impl_op!(from $x => power($xx, $yy)), + "+=" => Some(impl_op!(from $x => add($xx, $yy))), + "-=" => Some(impl_op!(from $x => subtract($xx, $yy))), + "*=" => Some(impl_op!(from $x => multiply($xx, $yy))), + "/=" => Some(impl_op!(from $x => divide($xx, $yy))), + "%=" => Some(impl_op!(from $x => modulo($xx, $yy))), + "**=" => Some(impl_op!(from $x => power($xx, $yy))), _ => None, }; @@ -531,12 +495,12 @@ pub fn get_builtin_op_assignment_fn( #[cfg(feature = "unchecked")] return match op { - "+=" => impl_op!(from $x += $yy), - "-=" => impl_op!(from $x -= $yy), - "*=" => impl_op!(from $x *= $yy), - "/=" => impl_op!(from $x /= $yy), - "%=" => impl_op!(from $x %= $yy), - "**=" => impl_op!(from $x => $xx.powd($yy)), + "+=" => Some(impl_op!(from $x += $yy)), + "-=" => Some(impl_op!(from $x -= $yy)), + "*=" => Some(impl_op!(from $x *= $yy)), + "/=" => Some(impl_op!(from $x /= $yy)), + "%=" => Some(impl_op!(from $x %= $yy)), + "**=" => Some(impl_op!(from $x => $xx.powd($yy))), _ => None, }; } @@ -549,8 +513,8 @@ pub fn get_builtin_op_assignment_fn( // string op= char if types_pair == (TypeId::of::(), TypeId::of::()) { return match op { - "+=" => impl_op!(ImmutableString += as_char as char), - "-=" => impl_op!(ImmutableString -= as_char as char), + "+=" => Some(impl_op!(ImmutableString += as_char as char)), + "-=" => Some(impl_op!(ImmutableString -= as_char as char)), _ => None, }; } @@ -585,42 +549,42 @@ pub fn get_builtin_op_assignment_fn( #[cfg(not(feature = "unchecked"))] match op { - "+=" => return impl_op!(INT => add(as_int, as_int)), - "-=" => return impl_op!(INT => subtract(as_int, as_int)), - "*=" => return impl_op!(INT => multiply(as_int, as_int)), - "/=" => return impl_op!(INT => divide(as_int, as_int)), - "%=" => return impl_op!(INT => modulo(as_int, as_int)), - "**=" => return impl_op!(INT => power(as_int, as_int)), - ">>=" => return impl_op!(INT => shift_right(as_int, as_int)), - "<<=" => return impl_op!(INT => shift_left(as_int, as_int)), + "+=" => return Some(impl_op!(INT => add(as_int, as_int))), + "-=" => return Some(impl_op!(INT => subtract(as_int, as_int))), + "*=" => return Some(impl_op!(INT => multiply(as_int, as_int))), + "/=" => return Some(impl_op!(INT => divide(as_int, as_int))), + "%=" => return Some(impl_op!(INT => modulo(as_int, as_int))), + "**=" => return Some(impl_op!(INT => power(as_int, as_int))), + ">>=" => return Some(impl_op!(INT => shift_right(as_int, as_int))), + "<<=" => return Some(impl_op!(INT => shift_left(as_int, as_int))), _ => (), } #[cfg(feature = "unchecked")] match op { - "+=" => return impl_op!(INT += as_int), - "-=" => return impl_op!(INT -= as_int), - "*=" => return impl_op!(INT *= as_int), - "/=" => return impl_op!(INT /= as_int), - "%=" => return impl_op!(INT %= as_int), - "**=" => return impl_op!(INT => as_int.pow(as_int as u32)), - ">>=" => return impl_op!(INT >>= as_int), - "<<=" => return impl_op!(INT <<= as_int), + "+=" => return Some(impl_op!(INT += as_int)), + "-=" => return Some(impl_op!(INT -= as_int)), + "*=" => return Some(impl_op!(INT *= as_int)), + "/=" => return Some(impl_op!(INT /= as_int)), + "%=" => return Some(impl_op!(INT %= as_int)), + "**=" => return Some(impl_op!(INT => as_int.pow(as_int as u32))), + ">>=" => return Some(impl_op!(INT >>= as_int)), + "<<=" => return Some(impl_op!(INT <<= as_int)), _ => (), } return match op { - "&=" => impl_op!(INT &= as_int), - "|=" => impl_op!(INT |= as_int), - "^=" => impl_op!(INT ^= as_int), + "&=" => Some(impl_op!(INT &= as_int)), + "|=" => Some(impl_op!(INT |= as_int)), + "^=" => Some(impl_op!(INT ^= as_int)), _ => None, }; } if type1 == TypeId::of::() { return match op { - "&=" => impl_op!(bool = x && as_bool), - "|=" => impl_op!(bool = x || as_bool), + "&=" => Some(impl_op!(bool = x && as_bool)), + "|=" => Some(impl_op!(bool = x || as_bool)), _ => None, }; } From 2342777a13d913a0155265ff52c38ba9a28f20b6 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 21 Jun 2021 19:12:28 +0800 Subject: [PATCH 2/3] Iterator reference parameters. --- src/ast.rs | 4 +-- src/engine.rs | 2 +- src/fn_call.rs | 83 ++++++++++++++++---------------------------------- src/parse.rs | 6 ++-- src/scope.rs | 2 +- 5 files changed, 33 insertions(+), 64 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 4414464e..6df1f3c9 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1498,12 +1498,12 @@ impl fmt::Debug for FnCallHashes { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(script) = self.script { if script == self.native { - write!(f, "({}=={})", script, self.native) + fmt::Debug::fmt(&self.native, f) } else { write!(f, "({}, {})", script, self.native) } } else { - write!(f, "{}", self.native) + write!(f, "{} (native only)", self.native) } } } diff --git a/src/engine.rs b/src/engine.rs index 7b0faa6b..a795a1ee 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -95,7 +95,7 @@ impl Imports { .iter() .enumerate() .rev() - .find_map(|(i, key)| if *key == name { Some(i) } else { None }) + .find_map(|(i, key)| if key == name { Some(i) } else { None }) } /// Push an imported [modules][Module] onto the stack. #[inline(always)] diff --git a/src/fn_call.rs b/src/fn_call.rs index 932d0019..a0310c0c 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -142,7 +142,7 @@ impl Engine { .map(|a| if a.is::() { "&str | ImmutableString | String" } else { - self.map_type_name((*a).type_name()) + self.map_type_name(a.type_name()) }) .collect::>() .join(", ") @@ -171,8 +171,10 @@ impl Engine { is_op_assignment: bool, ) -> &'s Option> { let mut hash = args.as_ref().map_or(hash_script, |args| { - let hash_params = calc_fn_params_hash(args.iter().map(|a| a.type_id())); - combine_hashes(hash_script, hash_params) + combine_hashes( + hash_script, + calc_fn_params_hash(args.iter().map(|a| a.type_id())), + ) }); &*state @@ -188,43 +190,17 @@ impl Engine { let mut bitmask = 1usize; // Bitmask of which parameter to replace with `Dynamic` loop { - let func = lib - .iter() - .find_map(|m| { - m.get_fn(hash).cloned().map(|func| { - let source = m.id_raw().cloned(); - FnResolutionCacheEntry { func, source } - }) - }) - .or_else(|| { - self.global_namespace - .get_fn(hash) - .cloned() - .map(|func| FnResolutionCacheEntry { func, source: None }) - }) - .or_else(|| { - self.global_modules.iter().find_map(|m| { - m.get_fn(hash).cloned().map(|func| { - let source = m.id_raw().cloned(); - FnResolutionCacheEntry { func, source } - }) - }) - }) - .or_else(|| { - mods.get_fn(hash).map(|(func, source)| { - let func = func.clone(); - let source = source.cloned(); - FnResolutionCacheEntry { func, source } - }) - }) - .or_else(|| { - self.global_sub_modules.values().find_map(|m| { - m.get_qualified_fn(hash).cloned().map(|func| { - let source = m.id_raw().cloned(); - FnResolutionCacheEntry { func, source } - }) - }) - }); + let func = lib.iter().find_map(|m| m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry { + func, source: m.id_raw().cloned() + })).or_else(|| self.global_namespace.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry { + func, source: None + })).or_else(|| self.global_modules.iter().find_map(|m| m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry { + func, source: m.id_raw().cloned() + }))).or_else(|| mods.get_fn(hash).map(|(func, source)| FnResolutionCacheEntry { + func: func.clone(), source: source.cloned() + })).or_else(|| self.global_sub_modules.values().find_map(|m| m.get_qualified_fn(hash).cloned().map(|func| FnResolutionCacheEntry { + func, source: m.id_raw().cloned() + }))); match func { // Specific version found @@ -239,23 +215,17 @@ impl Engine { return args.and_then(|args| { if !is_op_assignment { get_builtin_binary_op_fn(fn_name, &args[0], &args[1]).map(|f| { - let func = CallableFunction::from_method( + FnResolutionCacheEntry { func: CallableFunction::from_method( Box::new(f) as Box - ); - FnResolutionCacheEntry { func, source: None } + ), source: None } }) } else { let (first, second) = args.split_first() .expect("never fails because an op-assignment must have two arguments"); - get_builtin_op_assignment_fn(fn_name, *first, second[0]).map( - |f| { - let func = CallableFunction::from_method( - Box::new(f) as Box - ); - FnResolutionCacheEntry { func, source: None } - }, - ) + get_builtin_op_assignment_fn(fn_name, *first, second[0]).map(|f| FnResolutionCacheEntry { + func: CallableFunction::from_method(Box::new(f) as Box), source: None + }) } .map(Box::new) }); @@ -437,11 +407,10 @@ impl Engine { } // Raise error - _ => EvalAltResult::ErrorFunctionNotFound( - self.gen_call_signature(None, name, args.as_ref()), - pos, - ) - .into(), + _ => { + EvalAltResult::ErrorFunctionNotFound(self.gen_call_signature(None, name, args), pos) + .into() + } } } @@ -1451,7 +1420,7 @@ impl Engine { Some(f) => unreachable!("unknown function type: {:?}", f), None => EvalAltResult::ErrorFunctionNotFound( - self.gen_call_signature(Some(namespace), fn_name, args.as_ref()), + self.gen_call_signature(Some(namespace), fn_name, &args), pos, ) .into(), diff --git a/src/parse.rs b/src/parse.rs index 890db0cf..ece916a4 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -191,7 +191,7 @@ impl<'e> ParseState<'e> { .iter() .rev() .enumerate() - .find(|&(_, n)| *n == name) + .find(|&(_, n)| n == name) .and_then(|(i, _)| NonZeroUsize::new(i + 1)) } @@ -1070,8 +1070,8 @@ fn parse_primary( let (expr, func) = parse_anon_fn(input, &mut new_state, lib, settings)?; #[cfg(not(feature = "no_closure"))] - new_state.external_vars.iter().for_each(|(closure, pos)| { - state.access_var(closure, *pos); + new_state.external_vars.iter().for_each(|(closure, &pos)| { + state.access_var(closure, pos); }); let hash_script = calc_fn_hash(&func.name, func.params.len()); diff --git a/src/scope.rs b/src/scope.rs index 8f6138eb..513a9e89 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -448,7 +448,7 @@ impl<'a> Scope<'a> { .1 .as_mut() .expect("never fails because the list is initialized"); - if !list.iter().any(|a| &alias == a) { + if !list.iter().any(|a| a == &alias) { list.push(alias); } self From ba0cf80314ce0b3c8ab4ecc8c260e86fd56699eb Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 22 Jun 2021 22:32:50 +0800 Subject: [PATCH 3/3] Prepare for 0.20.3 release. --- CHANGELOG.md | 4 +++- Cargo.toml | 2 +- README.md | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfc3b096..58434e5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ Rhai Release Notes Version 0.20.3 ============== +This version adds support to index into an integer number, treating it as a bit-field. + Bug fixes --------- @@ -13,7 +15,7 @@ Bug fixes Breaking changes ---------------- -* To keep the API consistent, strings are no longer iterable by default. Use the `chars` method to iterator the characters in a string. +* To keep the API consistent, strings are no longer iterable by default. Use the `chars` method to iterate through the characters in a string. * `Dynamic::take_string` and `Dynamic::take_immutable_string` are renamed to `Dynamic::as_string` and `Dynamic::as_immutable_string` respectively. New features diff --git a/Cargo.toml b/Cargo.toml index 3de0c467..eb75503c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ smallvec = { version = "1.6", default-features = false, features = ["union"] } ahash = { version = "0.7", default-features = false } num-traits = { version = "0.2", default-features = false } smartstring = { version = "0.2.6", default-features = false } -rhai_codegen = { version = "0.4.0", path = "codegen", default-features = false } +rhai_codegen = { version = ">=0.4.0", path = "codegen", default-features = false } [features] default = ["smartstring/std", "ahash/std", "num-traits/std"] # remove 'smartstring/std' when smartstring is updated to support no-std diff --git a/README.md b/README.md index f56d179b..e4746f9f 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Standard features * Freely pass Rust values into a script as [variables](https://rhai.rs/book/language/variables.html)/[constants](https://rhai.rs/book/language/constants.html) via an external [`Scope`](https://rhai.rs/book/rust/scope.html) - all clonable Rust types are supported; no need to implement any special trait. Or tap directly into the [variable resolution process](https://rhai.rs/book/engine/var.html). * Built-in support for most common [data types](https://rhai.rs/book/language/values-and-types.html) including booleans, [integers](https://rhai.rs/book/language/numbers.html), [floating-point numbers](https://rhai.rs/book/language/numbers.html) (including [`Decimal`](https://crates.io/crates/rust_decimal)), [strings](https://rhai.rs/book/language/strings-chars.html), [Unicode characters](https://rhai.rs/book/language/strings-chars.html), [arrays](https://rhai.rs/book/language/arrays.html) and [object maps](https://rhai.rs/book/language/object-maps.html). * Easily [call a script-defined function](https://rhai.rs/book/engine/call-fn.html) from Rust. -* Relatively little `unsafe` code (yes there are some for performance reasons), and `unsafe` code is only used for type casting, never to get around the borrow checker. +* Relatively little `unsafe` code (yes there are some for performance reasons). * Few dependencies - currently only [`smallvec`](https://crates.io/crates/smallvec), [`num-traits`](https://crates.io/crates/num-traits), [`ahash`](https://crates.io/crates/ahash) and [`smartstring`](https://crates.io/crates/smartstring). * Re-entrant scripting engine can be made `Send + Sync` (via the `sync` feature). * Compile once to [AST](https://rhai.rs/book/engine/compile.html) form for repeated evaluations.