@@ -279,18 +279,12 @@ impl Evaluator {
279279 match ( left. clone ( ) , right. clone ( ) ) {
280280 ( Value :: Number ( l) , Value :: Number ( r) ) => {
281281 let sum = l. as_f64 ( ) . unwrap ( ) + r. as_f64 ( ) . unwrap ( ) ;
282- Ok ( Value :: Number ( serde_json :: Number :: from_f64 ( sum ) . unwrap ( ) ) )
282+ Ok ( self . f64_to_value ( sum ) )
283283 }
284284 ( Value :: String ( l) , Value :: String ( r) ) => Ok ( Value :: String ( l + & r) ) ,
285285 ( Value :: String ( l) , r) => Ok ( Value :: String ( l + & self . value_to_string ( & r) ) ) ,
286286 ( l, Value :: String ( r) ) => Ok ( Value :: String ( self . value_to_string ( & l) + & r) ) ,
287287 _ => {
288- // Type coercion similar to JavaScript
289- // This branch might need to use to_number if we want it to behave like JS '+' with mixed types that coerce to number first.
290- // However, current implementation coerces to string.
291- // If numeric conversion is desired for non-string/non-number types,
292- // to_number should be used, and it returns EvaluationError.
293- // For now, sticking to string concatenation for non-numeric types.
294288 let l_str = self . value_to_string ( & left) ;
295289 let r_str = self . value_to_string ( & right) ;
296290 Ok ( Value :: String ( l_str + & r_str) )
@@ -302,45 +296,28 @@ impl Evaluator {
302296 let l_num = self . to_number ( & left) ?;
303297 let r_num = self . to_number ( & right) ?;
304298 let result = l_num - r_num;
305- Ok ( Value :: Number (
306- serde_json:: Number :: from_f64 ( result)
307- . unwrap_or_else ( || serde_json:: Number :: from_f64 ( 0.0 ) . unwrap ( ) ) ,
308- ) )
299+ Ok ( self . f64_to_value ( result) )
309300 }
310301
311302 fn multiply_values ( & self , left : Value , right : Value ) -> Result < Value , EvaluationError > {
312303 let l_num = self . to_number ( & left) ?;
313304 let r_num = self . to_number ( & right) ?;
314305 let result = l_num * r_num;
315- Ok ( Value :: Number (
316- serde_json:: Number :: from_f64 ( result)
317- . unwrap_or_else ( || serde_json:: Number :: from_f64 ( 0.0 ) . unwrap ( ) ) ,
318- ) )
306+ Ok ( self . f64_to_value ( result) )
319307 }
320308
321309 fn divide_values ( & self , left : Value , right : Value ) -> Result < Value , EvaluationError > {
322310 let l_num = self . to_number ( & left) ?;
323311 let r_num = self . to_number ( & right) ?;
324- // JavaScript behavior: division by zero returns Infinity, -Infinity, or NaN
325312 let result = l_num / r_num;
326- Ok ( Value :: Number (
327- serde_json:: Number :: from_f64 ( result) . unwrap_or_else ( || {
328- // Handle NaN, Infinity, -Infinity by converting to null
329- // Note: serde_json doesn't support NaN/Infinity in Number type
330- // We'll use a special representation
331- serde_json:: Number :: from_f64 ( 0.0 ) . unwrap ( )
332- } ) ,
333- ) )
313+ Ok ( self . f64_to_value ( result) )
334314 }
335315
336316 fn modulo_values ( & self , left : Value , right : Value ) -> Result < Value , EvaluationError > {
337317 let l_num = self . to_number ( & left) ?;
338318 let r_num = self . to_number ( & right) ?;
339319 let result = l_num % r_num;
340- Ok ( Value :: Number (
341- serde_json:: Number :: from_f64 ( result)
342- . unwrap_or_else ( || serde_json:: Number :: from_f64 ( 0.0 ) . unwrap ( ) ) ,
343- ) )
320+ Ok ( self . f64_to_value ( result) )
344321 }
345322
346323 fn compare_values < F > (
@@ -375,11 +352,11 @@ impl Evaluator {
375352 Some ( ( _, UnaryOp :: LogicalNot ) ) => Value :: Bool ( !self . to_boolean ( & expr_value) ?) ,
376353 Some ( ( _, UnaryOp :: Minus ) ) => {
377354 let num = self . to_number ( & expr_value) ?;
378- Value :: Number ( serde_json :: Number :: from_f64 ( -num) . unwrap ( ) )
355+ self . f64_to_value ( -num)
379356 }
380357 Some ( ( _, UnaryOp :: Plus ) ) => {
381358 let num = self . to_number ( & expr_value) ?;
382- Value :: Number ( serde_json :: Number :: from_f64 ( num ) . unwrap ( ) )
359+ self . f64_to_value ( num )
383360 }
384361 _ => {
385362 return Err ( EvaluationError :: Node ( NodeError {
@@ -684,7 +661,6 @@ impl Evaluator {
684661
685662 // Handle string literals with escape sequences
686663 if literal_str. starts_with ( '"' ) || literal_str. starts_with ( '\'' ) {
687- let quote_char = literal_str. chars ( ) . next ( ) . unwrap ( ) ;
688664 // Remove only the first and last character (the quotes)
689665 let unquoted = if literal_str. len ( ) >= 2 {
690666 & literal_str[ 1 ..literal_str. len ( ) - 1 ]
@@ -769,8 +745,28 @@ impl Evaluator {
769745 }
770746 }
771747
748+ fn f64_to_value ( & self , num : f64 ) -> Value {
749+ if let Some ( n) = serde_json:: Number :: from_f64 ( num) {
750+ Value :: Number ( n)
751+ } else if num. is_nan ( ) {
752+ Value :: Null
753+ } else if num. is_infinite ( ) {
754+ // Represent Infinity as max f64 as checked in evaluate_by_name
755+ Value :: Number (
756+ serde_json:: Number :: from_f64 ( if num. is_sign_positive ( ) {
757+ f64:: MAX
758+ } else {
759+ f64:: MIN
760+ } )
761+ . unwrap ( ) ,
762+ )
763+ } else {
764+ Value :: Null
765+ }
766+ }
767+
772768 fn process_escape_sequences ( & self , s : & str ) -> String {
773- let mut result = String :: new ( ) ;
769+ let mut result = String :: with_capacity ( s . len ( ) ) ;
774770 let mut chars = s. chars ( ) ;
775771
776772 while let Some ( ch) = chars. next ( ) {
@@ -784,8 +780,6 @@ impl Evaluator {
784780 '\'' => result. push ( '\'' ) ,
785781 '"' => result. push ( '"' ) ,
786782 '0' => result. push ( '\0' ) ,
787- // For simplicity, we don't handle \uXXXX or \xXX here
788- // Just pass through the escaped character
789783 _ => {
790784 result. push ( '\\' ) ;
791785 result. push ( next_ch) ;
@@ -798,7 +792,6 @@ impl Evaluator {
798792 result. push ( ch) ;
799793 }
800794 }
801-
802795 result
803796 }
804797
0 commit comments