diff --git a/src/engine.rs b/src/engine.rs index 0519a4b3..8ae0a694 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -57,10 +57,19 @@ pub const FN_IDX_SET: &str = "index$set$"; pub const FN_ANONYMOUS: &str = "anon$"; /// Standard equality comparison operator. +/// +/// Some standard functions (e.g. searching an [`Array`][crate::Array]) implicitly call this +/// function to compare two [`Dynamic`] values. pub const OP_EQUALS: &str = Token::EqualsTo.literal_syntax(); -/// Standard method function for containment testing. -/// The `in` operator is implemented as a call to this method. +/// Standard concatenation operator. +/// +/// Used primarily to build up interpolated strings. +pub const OP_CONCAT: &str = Token::PlusAssign.literal_syntax(); + +/// Standard containment testing function. +/// +/// The `in` operator is implemented as a call to this function. pub const OP_CONTAINS: &str = "contains"; /// Standard exclusive range operator. @@ -69,9 +78,6 @@ pub const OP_EXCLUSIVE_RANGE: &str = Token::ExclusiveRange.literal_syntax(); /// Standard inclusive range operator. pub const OP_INCLUSIVE_RANGE: &str = Token::InclusiveRange.literal_syntax(); -/// Standard concatenation operator token. -pub const OP_CONCAT: &str = Token::PlusAssign.literal_syntax(); - /// Method of chaining. #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] diff --git a/src/func/args.rs b/src/func/args.rs index 71941ee5..d612ad3f 100644 --- a/src/func/args.rs +++ b/src/func/args.rs @@ -61,7 +61,7 @@ pub trait FuncArgs { impl FuncArgs for Vec { #[inline] fn parse>(self, args: &mut ARGS) { - args.extend(self.into_iter().map(Variant::into_dynamic)); + args.extend(self.into_iter().map(Dynamic::from)); } } @@ -75,7 +75,7 @@ macro_rules! impl_args { #[allow(unused_variables)] fn parse>(self, args: &mut ARGS) { let ($($p,)*) = self; - $(args.extend(Some($p.into_dynamic()));)* + $(args.extend(Some(Dynamic::from($p)));)* } } diff --git a/src/func/register.rs b/src/func/register.rs index d71ca50b..daa93d41 100644 --- a/src/func/register.rs +++ b/src/func/register.rs @@ -135,7 +135,7 @@ macro_rules! def_register { let r = self($($arg),*); // Map the result - Ok(r.into_dynamic()) + Ok(Dynamic::from(r)) }) as Box) } } @@ -163,7 +163,7 @@ macro_rules! def_register { let r = self(ctx, $($arg),*); // Map the result - Ok(r.into_dynamic()) + Ok(Dynamic::from(r)) }) as Box) } } diff --git a/src/lib.rs b/src/lib.rs index 0298da18..b9210006 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -144,9 +144,7 @@ type InclusiveRange = std::ops::RangeInclusive; pub use api::custom_syntax::Expression; pub use ast::{FnAccess, AST}; -pub use engine::{ - Engine, EvalContext, OP_CONTAINS, OP_EQUALS, OP_EXCLUSIVE_RANGE, OP_INCLUSIVE_RANGE, -}; +pub use engine::{Engine, EvalContext, OP_CONTAINS, OP_EQUALS}; pub use func::{NativeCallContext, RegisterNativeFunction}; pub use module::{FnNamespace, Module}; pub use tokenizer::Position; diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 696b05b7..2a86927e 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -1026,7 +1026,7 @@ pub trait InputStream { fn peek_next(&mut self) -> Option; } -/// _(internals)_ Parse a string literal ended by `termination_char`. +/// _(internals)_ Parse a string literal ended by a specified termination character. /// Exported under the `internals` feature only. /// /// Returns the parsed string and a boolean indicating whether the string is @@ -1034,7 +1034,7 @@ pub trait InputStream { /// /// # Returns /// -/// |Type |Return Value |`state.is_within_text_terminated_by`| +/// | Type | Return Value |`state.is_within_text_terminated_by`| /// |---------------------------------|:--------------------------:|:----------------------------------:| /// |`"hello"` |`StringConstant("hello")` |`None` | /// |`"hello`_{LF}_ or _{EOF}_ |`LexError` |`None` | @@ -1061,8 +1061,8 @@ pub fn parse_string_literal( state: &mut TokenizeState, pos: &mut Position, termination_char: char, - continuation: bool, verbatim: bool, + allow_line_continuation: bool, allow_interpolation: bool, ) -> Result<(Box, bool), (LexError, Position)> { let mut result = String::with_capacity(12); @@ -1091,7 +1091,7 @@ pub fn parse_string_literal( pos.advance(); break; } - None if continuation && !escape.is_empty() => { + None if allow_line_continuation && !escape.is_empty() => { assert_eq!(escape, "\\", "unexpected escape {} at end of line", escape); pos.advance(); break; @@ -1211,7 +1211,7 @@ pub fn parse_string_literal( } // Line continuation - '\n' if continuation && !escape.is_empty() => { + '\n' if allow_line_continuation && !escape.is_empty() => { assert_eq!(escape, "\\", "unexpected escape {} at end of line", escape); escape.clear(); pos.new_line(); @@ -1319,7 +1319,7 @@ fn scan_block_comment( level } -/// _(internals)_ Get the next token from the `stream`. +/// _(internals)_ Get the next token from the input stream. /// Exported under the `internals` feature only. #[inline] #[must_use] @@ -1400,7 +1400,7 @@ fn get_next_token_inner( if let Some(ch) = state.is_within_text_terminated_by.take() { let start_pos = *pos; - return parse_string_literal(stream, state, pos, ch, false, true, true).map_or_else( + return parse_string_literal(stream, state, pos, ch, true, false, true).map_or_else( |(err, err_pos)| Some((Token::LexError(err), err_pos)), |(result, interpolated)| { if interpolated { @@ -1584,7 +1584,7 @@ fn get_next_token_inner( // " - string literal ('"', _) => { - return parse_string_literal(stream, state, pos, c, true, false, false) + return parse_string_literal(stream, state, pos, c, false, true, false) .map_or_else( |(err, err_pos)| Some((Token::LexError(err), err_pos)), |(result, _)| Some((Token::StringConstant(result), start_pos)), @@ -1611,7 +1611,7 @@ fn get_next_token_inner( _ => (), } - return parse_string_literal(stream, state, pos, c, false, true, true).map_or_else( + return parse_string_literal(stream, state, pos, c, true, false, true).map_or_else( |(err, err_pos)| Some((Token::LexError(err), err_pos)), |(result, interpolated)| { if interpolated { diff --git a/src/types/dynamic.rs b/src/types/dynamic.rs index 140903a8..eefcc2f4 100644 --- a/src/types/dynamic.rs +++ b/src/types/dynamic.rs @@ -52,7 +52,7 @@ pub trait Variant: Any + private::Sealed { #[must_use] fn as_mut_any(&mut self) -> &mut dyn Any; - /// Convert this [`Variant`] trait object to an [`Any`] trait object. + /// Convert this [`Variant`] trait object to [`Box`]. #[must_use] fn as_box_any(self: Box) -> Box; @@ -60,13 +60,9 @@ pub trait Variant: Any + private::Sealed { #[must_use] fn type_name(&self) -> &'static str; - /// Convert into [`Dynamic`]. + /// Clone this [`Variant`] trait object. #[must_use] - fn into_dynamic(self) -> Dynamic; - - /// Clone into [`Dynamic`]. - #[must_use] - fn clone_into_dynamic(&self) -> Dynamic; + fn clone_object(&self) -> Box; } /// _(internals)_ Trait to represent any type. @@ -83,7 +79,7 @@ pub trait Variant: Any + Send + Sync + private::Sealed { #[must_use] fn as_mut_any(&mut self) -> &mut dyn Any; - /// Convert this [`Variant`] trait object to an [`Any`] trait object. + /// Convert this [`Variant`] trait object to [`Box`]. #[must_use] fn as_box_any(self: Box) -> Box; @@ -91,13 +87,9 @@ pub trait Variant: Any + Send + Sync + private::Sealed { #[must_use] fn type_name(&self) -> &'static str; - /// Convert into [`Dynamic`]. + /// Clone this [`Variant`] trait object. #[must_use] - fn into_dynamic(self) -> Dynamic; - - /// Clone into [`Dynamic`]. - #[must_use] - fn clone_into_dynamic(&self) -> Dynamic; + fn clone_object(&self) -> Box; } impl Variant for T { @@ -118,12 +110,8 @@ impl Variant for T { type_name::() } #[inline(always)] - fn into_dynamic(self) -> Dynamic { - Dynamic::from(self) - } - #[inline(always)] - fn clone_into_dynamic(&self) -> Dynamic { - Dynamic::from(self.clone()) + fn clone_object(&self) -> Box { + Box::new(self.clone()) as Box } } @@ -818,11 +806,11 @@ impl Clone for Dynamic { Self(Union::TimeStamp(value.clone(), tag, ReadWrite)) } - Union::Variant(ref value, tag, _) => { - let mut x = value.as_ref().as_ref().clone_into_dynamic(); - x.set_tag(tag); - x - } + Union::Variant(ref value, tag, _) => Self(Union::Variant( + value.as_ref().as_ref().clone_object().into(), + tag, + ReadWrite, + )), #[cfg(not(feature = "no_closure"))] Union::Shared(ref cell, tag, _) => Self(Union::Shared(cell.clone(), tag, ReadWrite)),