Skip to main content

exprimo/
lib.rs

1use rslint_parser::{
2    ast::{
3        BinExpr, BinOp, CallExpr, CondExpr, DotExpr, Expr, GroupingExpr, Name, NameRef, UnaryExpr,
4        UnaryOp,
5    }, // Removed ExprOrSpread
6    parse_text,
7    AstNode,
8    SyntaxKind,
9    SyntaxNode,
10};
11use serde_json::Value;
12use std::collections::HashMap;
13use std::fmt::Debug; // For CustomFunction trait
14use std::sync::Arc; // For Arc<dyn CustomFunction>
15use thiserror::Error;
16use tracing::trace; // Assuming this is the correct path to Logger
17
18#[derive(Error, Debug)]
19pub enum CustomFuncError {
20    #[error("Argument error: {0}")]
21    ArgumentError(String),
22    #[error("Generic error: {0}")]
23    Generic(String),
24    #[error("Wrong number of arguments: expected {expected}, got {got}")]
25    ArityError { expected: usize, got: usize },
26}
27
28#[derive(Error, Debug)]
29pub enum EvaluationError {
30    #[error("Node evaluation failed: {0}")]
31    Node(#[from] NodeError),
32    #[error("Custom function execution failed: {0}")]
33    CustomFunction(#[from] CustomFuncError),
34    #[error("Type error: {0}")]
35    TypeError(String),
36}
37
38#[derive(Error, Debug)]
39#[error("Node error {message}, node: {node:?}")]
40pub struct NodeError {
41    message: String,
42    node: Option<SyntaxNode>,
43}
44
45#[derive(Debug, Clone, PartialEq)]
46pub enum BuiltInMethodKind {
47    ArrayIncludes,
48    ObjectHasOwnProperty, // Added
49}
50
51#[derive(Debug, Clone, PartialEq)]
52pub enum ResolvableValue {
53    Json(Value),
54    BuiltInMethod {
55        object: Box<Value>, // The object on which the method is called (e.g., the array)
56        method: BuiltInMethodKind,
57    },
58}
59
60impl ResolvableValue {
61    fn try_into_value(self) -> Result<Value, EvaluationError> {
62        match self {
63            ResolvableValue::Json(val) => Ok(val),
64            ResolvableValue::BuiltInMethod { object, method } => {
65                Err(EvaluationError::TypeError(format!(
66                    "Cannot use built-in method {:?} on {:?} as a value.", // Adjusted error message
67                    method, object
68                )))
69            }
70        }
71    }
72}
73
74pub trait CustomFunction: Debug + Send + Sync {
75    fn call(&self, args: &[Value]) -> Result<Value, CustomFuncError>;
76}
77
78pub struct Evaluator {
79    context: HashMap<String, Value>,
80    custom_functions: HashMap<String, Arc<dyn CustomFunction>>,
81}
82
83impl Evaluator {
84    pub fn new(
85        context: HashMap<String, Value>,
86        custom_functions: HashMap<String, Arc<dyn CustomFunction>>,
87    ) -> Self {
88        Evaluator {
89            context,
90            custom_functions,
91        }
92    }
93
94    pub fn evaluate(&self, expression: &str) -> Result<Value, EvaluationError> {
95        let ast = parse_text(expression, 0).syntax();
96        let untyped_expr_node = match ast.first_child() {
97            Some(node) => node,
98            None => {
99                return Err(EvaluationError::Node(NodeError {
100                    message: "Empty expression".to_string(),
101                    node: None,
102                }));
103            }
104        };
105
106        trace!(
107            "Expression AST:\n\n{:#?}\n-----------------",
108            untyped_expr_node
109        );
110
111        let result = self.evaluate_node(&untyped_expr_node)?;
112
113        trace!("Result: {}", result);
114
115        Ok(result)
116    }
117
118    fn evaluate_node(&self, node: &SyntaxNode) -> Result<Value, EvaluationError> {
119        trace!(
120            "Evaluating NodeKind: {:#?}, {:?}",
121            node.kind(),
122            node.to_string()
123        );
124
125        let res = match node.kind() {
126            SyntaxKind::EXPR_STMT => {
127                let expr = node.first_child().ok_or_else(|| {
128                    EvaluationError::Node(NodeError {
129                        message: "[Empty expression]".to_string(),
130                        node: None,
131                    })
132                })?;
133                self.evaluate_node(&expr)
134            }
135            SyntaxKind::DOT_EXPR => self
136                .evaluate_dot_expr(&DotExpr::cast(node.clone()).unwrap())?
137                .try_into_value(),
138            SyntaxKind::NAME_REF => self
139                .evaluate_name_ref(&NameRef::cast(node.clone()).unwrap())
140                .map_err(EvaluationError::from),
141            SyntaxKind::NAME => self
142                .evaluate_name(&Name::cast(node.clone()).unwrap())
143                .map_err(EvaluationError::from),
144            SyntaxKind::BIN_EXPR => self
145                .evaluate_bin_expr(&BinExpr::cast(node.clone()).unwrap())
146                .map_err(EvaluationError::from),
147            SyntaxKind::LITERAL => self
148                .evaluate_literal(&Expr::cast(node.clone()).unwrap())
149                .map_err(EvaluationError::from),
150            SyntaxKind::COND_EXPR => self
151                .evaluate_cond_expr(&CondExpr::cast(node.clone()).unwrap())
152                .map_err(EvaluationError::from),
153            SyntaxKind::IDENT => self
154                .evaluate_identifier(&Expr::cast(node.clone()).unwrap())
155                .map_err(EvaluationError::from),
156            SyntaxKind::UNARY_EXPR => self
157                .evaluate_prefix_expr(&UnaryExpr::cast(node.clone()).unwrap())
158                .map_err(EvaluationError::from),
159            SyntaxKind::CALL_EXPR => {
160                self.evaluate_call_expr(&CallExpr::cast(node.clone()).unwrap())
161            }
162            SyntaxKind::GROUPING_EXPR => {
163                let grouping_expr = GroupingExpr::cast(node.clone()).unwrap();
164                let inner_expr = grouping_expr.inner().ok_or_else(|| {
165                    EvaluationError::Node(NodeError {
166                        message: "Missing inner expression in grouping expression".to_string(),
167                        node: Some(node.clone()),
168                    })
169                })?;
170                self.evaluate_node(inner_expr.syntax())
171            }
172            // Handle simple array and object literals
173            SyntaxKind::ARRAY_EXPR => {
174                // For now, only support empty array literal []
175                // Complex array literals [1,2,3] would require iterating elements
176                if node.children().count() == 0 {
177                    Ok(Value::Array(vec![]))
178                } else {
179                    Err(EvaluationError::Node(NodeError {
180                        message: "Complex array literals are not yet supported.".to_string(),
181                        node: Some(node.clone()),
182                    }))
183                }
184            }
185            SyntaxKind::OBJECT_EXPR => {
186                // For now, only support empty object literal {}
187                // Complex object literals {a:1} would require parsing properties
188                if node.children().count() == 0 {
189                    Ok(Value::Object(serde_json::Map::new()))
190                } else {
191                    Err(EvaluationError::Node(NodeError {
192                        message: "Complex object literals are not yet supported.".to_string(),
193                        node: Some(node.clone()),
194                    }))
195                }
196            }
197            _ => Err(EvaluationError::Node(NodeError {
198                message: format!("Unsupported syntax kind: {:?}", node.kind()),
199                node: Some(node.clone()),
200            })),
201        };
202
203        trace!("NodeKind: {:?} => {:#?}", node.kind(), res.as_ref());
204
205        res
206    }
207
208    fn evaluate_bin_expr(&self, bin_expr: &BinExpr) -> Result<Value, EvaluationError> {
209        trace!("Evaluating Binary Expression: {:#?}", bin_expr.to_string());
210
211        let left = bin_expr.lhs().ok_or_else(|| NodeError {
212            message: "[Empty BinExpr Left Expression]".to_string(),
213            node: Some(bin_expr.syntax().clone()),
214        })?;
215        let right = bin_expr.rhs().ok_or_else(|| NodeError {
216            message: "[Empty BinExpr Right Expression]".to_string(),
217            node: Some(bin_expr.syntax().clone()),
218        })?;
219
220        let left_value = self.evaluate_node(left.syntax())?;
221        let right_value = self.evaluate_node(right.syntax())?;
222
223        let op = bin_expr.op_details();
224
225        trace!("BinaryOp left_value {:?}", left_value);
226
227        trace!("BinaryOp right_value {:?}", right_value);
228
229        trace!("BinaryOp op_details {:?}", op);
230
231        let result = match op {
232            Some((_, BinOp::Plus)) => self.add_values(left_value, right_value),
233            Some((_, BinOp::Minus)) => self.subtract_values(left_value, right_value),
234            Some((_, BinOp::Times)) => self.multiply_values(left_value, right_value),
235            Some((_, BinOp::Divide)) => self.divide_values(left_value, right_value),
236            Some((_, BinOp::Remainder)) => self.modulo_values(left_value, right_value),
237            Some((_, BinOp::LogicalAnd)) => Ok(Value::Bool(
238                self.to_boolean(&left_value)? && self.to_boolean(&right_value)?,
239            )),
240            Some((_, BinOp::LogicalOr)) => Ok(Value::Bool(
241                self.to_boolean(&left_value)? || self.to_boolean(&right_value)?,
242            )),
243            Some((_, BinOp::Equality)) => Ok(Value::Bool(
244                self.abstract_equality(&left_value, &right_value),
245            )),
246            Some((_, BinOp::Inequality)) => Ok(Value::Bool(
247                !self.abstract_equality(&left_value, &right_value),
248            )),
249            Some((_, BinOp::StrictEquality)) => {
250                Ok(Value::Bool(self.strict_equality(&left_value, &right_value)))
251            }
252            Some((_, BinOp::StrictInequality)) => Ok(Value::Bool(
253                !self.strict_equality(&left_value, &right_value),
254            )),
255            Some((_, BinOp::GreaterThan)) => {
256                self.compare_values(&left_value, &right_value, |a, b| a > b)
257            }
258            Some((_, BinOp::LessThan)) => {
259                self.compare_values(&left_value, &right_value, |a, b| a < b)
260            }
261            Some((_, BinOp::GreaterThanOrEqual)) => {
262                self.compare_values(&left_value, &right_value, |a, b| a >= b)
263            }
264            Some((_, BinOp::LessThanOrEqual)) => {
265                self.compare_values(&left_value, &right_value, |a, b| a <= b)
266            }
267            _ => Err(EvaluationError::Node(NodeError {
268                message: "Unsupported binary operator".to_string(),
269                node: Some(bin_expr.syntax().clone()),
270            })),
271        }?;
272
273        trace!("Binary Result: {:?}", result);
274
275        Ok(result)
276    }
277
278    fn add_values(&self, left: Value, right: Value) -> Result<Value, EvaluationError> {
279        match (left.clone(), right.clone()) {
280            (Value::Number(l), Value::Number(r)) => {
281                let sum = l.as_f64().unwrap() + r.as_f64().unwrap();
282                Ok(self.f64_to_value(sum))
283            }
284            (Value::String(l), Value::String(r)) => Ok(Value::String(l + &r)),
285            (Value::String(l), r) => Ok(Value::String(l + &self.value_to_string(&r))),
286            (l, Value::String(r)) => Ok(Value::String(self.value_to_string(&l) + &r)),
287            _ => {
288                let l_str = self.value_to_string(&left);
289                let r_str = self.value_to_string(&right);
290                Ok(Value::String(l_str + &r_str))
291            }
292        }
293    }
294
295    fn subtract_values(&self, left: Value, right: Value) -> Result<Value, EvaluationError> {
296        let l_num = self.to_number(&left)?;
297        let r_num = self.to_number(&right)?;
298        let result = l_num - r_num;
299        Ok(self.f64_to_value(result))
300    }
301
302    fn multiply_values(&self, left: Value, right: Value) -> Result<Value, EvaluationError> {
303        let l_num = self.to_number(&left)?;
304        let r_num = self.to_number(&right)?;
305        let result = l_num * r_num;
306        Ok(self.f64_to_value(result))
307    }
308
309    fn divide_values(&self, left: Value, right: Value) -> Result<Value, EvaluationError> {
310        let l_num = self.to_number(&left)?;
311        let r_num = self.to_number(&right)?;
312        let result = l_num / r_num;
313        Ok(self.f64_to_value(result))
314    }
315
316    fn modulo_values(&self, left: Value, right: Value) -> Result<Value, EvaluationError> {
317        let l_num = self.to_number(&left)?;
318        let r_num = self.to_number(&right)?;
319        let result = l_num % r_num;
320        Ok(self.f64_to_value(result))
321    }
322
323    fn compare_values<F>(
324        &self,
325        left: &Value,
326        right: &Value,
327        cmp: F,
328    ) -> Result<Value, EvaluationError>
329    where
330        F: Fn(f64, f64) -> bool,
331    {
332        let l_num = self.to_number(left)?;
333        let r_num = self.to_number(right)?;
334        Ok(Value::Bool(cmp(l_num, r_num)))
335    }
336
337    fn evaluate_prefix_expr(&self, prefix_expr: &UnaryExpr) -> Result<Value, EvaluationError> {
338        trace!(
339            "Evaluating Prefix Expression: {:#?}",
340            prefix_expr.to_string()
341        );
342
343        let expr = prefix_expr.expr().ok_or_else(|| NodeError {
344            message: "[Empty PrefixExpr Expression]".to_string(),
345            node: Some(prefix_expr.syntax().clone()),
346        })?;
347        let expr_value = self.evaluate_node(expr.syntax())?;
348
349        let op = prefix_expr.op_details();
350
351        let result = match op {
352            Some((_, UnaryOp::LogicalNot)) => Value::Bool(!self.to_boolean(&expr_value)?),
353            Some((_, UnaryOp::Minus)) => {
354                let num = self.to_number(&expr_value)?;
355                self.f64_to_value(-num)
356            }
357            Some((_, UnaryOp::Plus)) => {
358                let num = self.to_number(&expr_value)?;
359                self.f64_to_value(num)
360            }
361            _ => {
362                return Err(EvaluationError::Node(NodeError {
363                    message: "Unsupported unary operator".to_string(),
364                    node: Some(prefix_expr.syntax().clone()),
365                }))
366            }
367        };
368        trace!("Prefix Result: {:?}", result);
369
370        Ok(result)
371    }
372
373    fn evaluate_cond_expr(&self, cond_expr: &CondExpr) -> Result<Value, EvaluationError> {
374        trace!(
375            "Evaluating Conditional Expression: {:#?}",
376            cond_expr.to_string()
377        );
378        let cond = cond_expr.test().ok_or_else(|| NodeError {
379            message: "[Empty CondExpr Test Expression]".to_string(),
380            node: Some(cond_expr.syntax().clone()),
381        })?;
382        let true_expr = cond_expr.cons().ok_or_else(|| NodeError {
383            message: "[Empty CondExpr Consequent Expression]".to_string(),
384            node: Some(cond_expr.syntax().clone()),
385        })?;
386        let false_expr = cond_expr.alt().ok_or_else(|| NodeError {
387            message: "[Empty CondExpr Alternate Expression]".to_string(),
388            node: Some(cond_expr.syntax().clone()),
389        })?;
390
391        let cond_value = self.evaluate_node(cond.syntax())?; // Returns EvaluationError
392        let cond_bool = self.to_boolean(&cond_value)?; // Returns EvaluationError
393
394        let result = if cond_bool {
395            self.evaluate_node(true_expr.syntax())? // Returns EvaluationError
396        } else {
397            self.evaluate_node(false_expr.syntax())? // Returns EvaluationError
398        };
399
400        trace!("Conditional Result: {:?}", result);
401
402        Ok(result)
403    }
404
405    fn evaluate_dot_expr(&self, dot_expr: &DotExpr) -> Result<ResolvableValue, EvaluationError> {
406        trace!("Evaluating Dot Expression: {:#?}", dot_expr);
407
408        let object_expr = dot_expr.object().ok_or_else(|| {
409            EvaluationError::Node(NodeError {
410                message: "Missing object in dot expression".to_string(),
411                node: Some(dot_expr.syntax().clone()),
412            })
413        })?;
414
415        let prop_name_ident = dot_expr.prop().ok_or_else(|| {
416            EvaluationError::Node(NodeError {
417                message: "Missing property name in dot expression".to_string(),
418                node: Some(dot_expr.syntax().clone()),
419            })
420        })?;
421        // In rslint_parser, prop for DotExpr is an Name rather than NameRef or Ident
422        // So we need to get its text representation.
423        let prop_name = prop_name_ident.syntax().text().to_string();
424
425        // Evaluate the object part of the dot expression
426        let object_value = self.evaluate_node(object_expr.syntax())?;
427
428        trace!(
429            "Dot Expression: object_value={:?}, prop_name='{}'",
430            object_value,
431            prop_name
432        );
433
434        match object_value {
435            Value::Array(arr) => {
436                if prop_name == "length" {
437                    Ok(ResolvableValue::Json(Value::Number(
438                        serde_json::Number::from_f64(arr.len() as f64).unwrap(),
439                    )))
440                } else if prop_name == "includes" {
441                    Ok(ResolvableValue::BuiltInMethod {
442                        object: Box::new(Value::Array(arr.clone())), // Clone the array for the method context
443                        method: BuiltInMethodKind::ArrayIncludes,
444                    })
445                } else {
446                    // Accessing other properties like myArray.foo returns undefined in JS.
447                    Ok(ResolvableValue::Json(Value::Null))
448                }
449            }
450            Value::Object(map) => {
451                if prop_name == "hasOwnProperty" {
452                    Ok(ResolvableValue::BuiltInMethod {
453                        object: Box::new(Value::Object(map.clone())), // Clone the object for the method context
454                        method: BuiltInMethodKind::ObjectHasOwnProperty,
455                    })
456                } else {
457                    Ok(ResolvableValue::Json(
458                        map.get(&prop_name).cloned().unwrap_or(Value::Null),
459                    ))
460                }
461            }
462            _ => {
463                if prop_name == "length" {
464                    // Check for .length on non-array/non-object first
465                    Err(EvaluationError::TypeError(format!(
466                        "Cannot read property 'length' of non-array/non-object value: {}", // Clarified error
467                        self.value_to_string(&object_value)
468                    )))
469                } else {
470                    Err(EvaluationError::TypeError(format!(
471                        "Cannot read properties of null or primitive value: {} (trying to access property: {})",
472                        self.value_to_string(&object_value),
473                        prop_name
474                    )))
475                }
476            }
477        }
478    }
479
480    // Implement abstract equality similar to JavaScript (==)
481    // This includes type coercion
482    fn abstract_equality(&self, left: &Value, right: &Value) -> bool {
483        match (left, right) {
484            // Same type comparisons
485            (Value::Null, Value::Null) => true,
486            (Value::Bool(l), Value::Bool(r)) => l == r,
487            (Value::String(l), Value::String(r)) => l == r,
488            (Value::Number(l), Value::Number(r)) => {
489                let l_num = l.as_f64().unwrap();
490                let r_num = r.as_f64().unwrap();
491                // NaN is never equal to anything, including itself
492                if l_num.is_nan() || r_num.is_nan() {
493                    false
494                } else {
495                    l_num == r_num
496                }
497            }
498
499            // Type coercion cases
500            // null == undefined would go here, but we don't have undefined
501
502            // Number and String: convert string to number
503            (Value::Number(l), Value::String(r)) | (Value::String(r), Value::Number(l)) => {
504                if let Ok(r_num) = self.to_number(&Value::String(r.clone())) {
505                    let l_num = l.as_f64().unwrap();
506                    if l_num.is_nan() || r_num.is_nan() {
507                        false
508                    } else {
509                        l_num == r_num
510                    }
511                } else {
512                    false
513                }
514            }
515
516            // Boolean: convert to number and compare
517            (Value::Bool(b), other) | (other, Value::Bool(b)) => {
518                let bool_num: f64 = if *b { 1.0 } else { 0.0 };
519                if let Ok(other_num) = self.to_number(other) {
520                    if bool_num.is_nan() || other_num.is_nan() {
521                        false
522                    } else {
523                        bool_num == other_num
524                    }
525                } else {
526                    false
527                }
528            }
529
530            // Array/Object comparisons (reference equality, always false for different instances)
531            _ => false,
532        }
533    }
534
535    // Implement strict equality (===)
536    // No type coercion
537    fn strict_equality(&self, left: &Value, right: &Value) -> bool {
538        match (left, right) {
539            (Value::Null, Value::Null) => true,
540            (Value::Bool(l), Value::Bool(r)) => l == r,
541            (Value::String(l), Value::String(r)) => l == r,
542            (Value::Number(l), Value::Number(r)) => {
543                let l_num = l.as_f64().unwrap();
544                let r_num = r.as_f64().unwrap();
545                // NaN is never equal to anything, including itself
546                if l_num.is_nan() || r_num.is_nan() {
547                    false
548                } else {
549                    l_num == r_num
550                }
551            }
552            // Different types are never strictly equal
553            _ => false,
554        }
555    }
556
557    // Implement SameValueZero comparison (used by Array.includes)
558    // Similar to strict equality but NaN equals NaN
559    fn same_value_zero(&self, left: &Value, right: &Value) -> bool {
560        match (left, right) {
561            (Value::Null, Value::Null) => true,
562            (Value::Bool(l), Value::Bool(r)) => l == r,
563            (Value::String(l), Value::String(r)) => l == r,
564            (Value::Number(l), Value::Number(r)) => {
565                let l_num = l.as_f64().unwrap();
566                let r_num = r.as_f64().unwrap();
567                // Special case: NaN equals NaN in SameValueZero
568                if l_num.is_nan() && r_num.is_nan() {
569                    true
570                } else {
571                    l_num == r_num
572                }
573            }
574            // Different types are never equal
575            _ => false,
576        }
577    }
578
579    fn evaluate_by_name(&self, identifier_name: String) -> Result<Value, NodeError> {
580        // Check for special JavaScript identifiers first
581        match identifier_name.as_str() {
582            "Infinity" => {
583                // Note: serde_json doesn't support Infinity in Number type
584                // We represent it as a very large number as a workaround
585                // In a real implementation, you might want a custom Value type
586                return Ok(Value::Number(
587                    serde_json::Number::from_f64(f64::INFINITY).unwrap_or_else(|| {
588                        serde_json::Number::from_f64(1.7976931348623157e308).unwrap()
589                    }),
590                ));
591            }
592            "NaN" => {
593                // Similar issue with NaN
594                return Ok(Value::Number(
595                    serde_json::Number::from_f64(f64::NAN)
596                        .unwrap_or_else(|| serde_json::Number::from_f64(0.0).unwrap()),
597                ));
598            }
599            "undefined" => {
600                // Return null for undefined (closest equivalent in JSON)
601                return Ok(Value::Null);
602            }
603            _ => {}
604        }
605
606        let identifier_value = self.context.get(&identifier_name);
607
608        trace!("Identifier Value: {:#?}", identifier_value);
609
610        match identifier_value {
611            Some(value) => Ok(value.clone()),
612            None => Err(NodeError {
613                message: format!("Identifier '{}' not found in context.", identifier_name),
614                node: None,
615            }),
616        }
617    }
618
619    fn evaluate_name(&self, name: &Name) -> Result<Value, NodeError> {
620        trace!("Evaluating Name: {:#?}", name.to_string());
621        let identifier_name = name
622            .ident_token()
623            .ok_or_else(|| NodeError {
624                message: "[Empty Name]".to_string(),
625                node: Some(name.syntax().clone()),
626            })?
627            .to_string();
628
629        self.evaluate_by_name(identifier_name)
630    }
631
632    fn evaluate_name_ref(&self, name_ref: &NameRef) -> Result<Value, NodeError> {
633        trace!("Evaluating Name Reference: {:#?}", name_ref.to_string());
634        let identifier_name = name_ref
635            .ident_token()
636            .ok_or_else(|| NodeError {
637                message: "[Empty NameRef]".to_string(),
638                node: Some(name_ref.syntax().clone()),
639            })?
640            .to_string();
641
642        self.evaluate_by_name(identifier_name)
643    }
644
645    fn evaluate_identifier(&self, identifier: &Expr) -> Result<Value, NodeError> {
646        trace!("Evaluating Identifier: {:#?}", identifier.to_string());
647        let identifier_name = identifier.to_string();
648
649        self.evaluate_by_name(identifier_name)
650    }
651
652    fn evaluate_literal(&self, literal: &Expr) -> Result<Value, NodeError> {
653        trace!("Evaluating Literal: {:#?}", literal.to_string());
654
655        let literal_str = literal.to_string();
656
657        // Handle numeric literals
658        if let Ok(number) = literal_str.parse::<f64>() {
659            return Ok(Value::Number(serde_json::Number::from_f64(number).unwrap()));
660        }
661
662        // Handle string literals with escape sequences
663        if literal_str.starts_with('"') || literal_str.starts_with('\'') {
664            // Remove only the first and last character (the quotes)
665            let unquoted = if literal_str.len() >= 2 {
666                &literal_str[1..literal_str.len() - 1]
667            } else {
668                ""
669            };
670            // Process escape sequences
671            let processed = self.process_escape_sequences(unquoted);
672            return Ok(Value::String(processed));
673        }
674
675        // Handle boolean literals
676        match literal_str.as_str() {
677            "true" => return Ok(Value::Bool(true)),
678            "false" => return Ok(Value::Bool(false)),
679            "null" => return Ok(Value::Null),
680            _ => {}
681        }
682
683        Err(NodeError {
684            message: format!("Unknown literal type: {}", literal_str),
685            node: Some(literal.syntax().clone()),
686        })
687    }
688
689    fn to_number(&self, value: &Value) -> Result<f64, EvaluationError> {
690        match value {
691            Value::Number(n) => Ok(n.as_f64().unwrap()),
692            Value::String(s) => {
693                // JavaScript behavior: invalid strings convert to NaN, empty string to 0
694                if s.is_empty() {
695                    Ok(0.0)
696                } else if s.trim() == "Infinity" {
697                    Ok(f64::INFINITY)
698                } else if s.trim() == "-Infinity" {
699                    Ok(f64::NEG_INFINITY)
700                } else {
701                    // Try to parse, return NaN if it fails (JavaScript behavior)
702                    Ok(s.trim().parse::<f64>().unwrap_or(f64::NAN))
703                }
704            }
705            Value::Bool(b) => Ok(if *b { 1.0 } else { 0.0 }),
706            Value::Null => Ok(0.0),
707            Value::Array(arr) => {
708                // JavaScript: [] converts to 0, [x] converts to Number(x), otherwise NaN
709                if arr.is_empty() {
710                    Ok(0.0)
711                } else if arr.len() == 1 {
712                    self.to_number(&arr[0])
713                } else {
714                    Ok(f64::NAN)
715                }
716            }
717            Value::Object(_) => Ok(f64::NAN), // JavaScript: objects convert to NaN
718        }
719    }
720
721    fn to_boolean(&self, value: &Value) -> Result<bool, EvaluationError> {
722        let result = match value {
723            Value::Bool(b) => *b,
724            Value::Null => false,
725            Value::Number(n) => {
726                let num = n.as_f64().unwrap();
727                num != 0.0 && !num.is_nan()
728            }
729            Value::String(s) => !s.is_empty(),
730            // JavaScript behavior: all arrays and objects are truthy, even if empty
731            Value::Array(_) => true,
732            Value::Object(_) => true,
733        };
734        Ok(result)
735    }
736
737    fn value_to_string(&self, value: &Value) -> String {
738        match value {
739            Value::String(s) => s.clone(),
740            Value::Number(n) => n.to_string(),
741            Value::Bool(b) => b.to_string(),
742            Value::Null => "null".to_string(),
743            Value::Array(_) => "[Array]".to_string(),
744            Value::Object(_) => "[Object]".to_string(),
745        }
746    }
747
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
768    fn process_escape_sequences(&self, s: &str) -> String {
769        let mut result = String::with_capacity(s.len());
770        let mut chars = s.chars();
771
772        while let Some(ch) = chars.next() {
773            if ch == '\\' {
774                if let Some(next_ch) = chars.next() {
775                    match next_ch {
776                        'n' => result.push('\n'),
777                        't' => result.push('\t'),
778                        'r' => result.push('\r'),
779                        '\\' => result.push('\\'),
780                        '\'' => result.push('\''),
781                        '"' => result.push('"'),
782                        '0' => result.push('\0'),
783                        _ => {
784                            result.push('\\');
785                            result.push(next_ch);
786                        }
787                    }
788                } else {
789                    result.push('\\');
790                }
791            } else {
792                result.push(ch);
793            }
794        }
795        result
796    }
797
798    fn evaluate_call_expr(&self, call_expr: &CallExpr) -> Result<Value, EvaluationError> {
799        let callee_expr_node = call_expr.callee().ok_or_else(|| {
800            EvaluationError::Node(NodeError {
801                message: "Missing callee in call expression".to_string(),
802                node: Some(call_expr.syntax().clone()),
803            })
804        })?;
805
806        let callee_syntax = callee_expr_node.syntax();
807
808        // Evaluate arguments first, as they are needed in both branches
809        let mut evaluated_args = Vec::new();
810        if let Some(arg_list_node) = call_expr.arguments() {
811            for arg_expr in arg_list_node.args() {
812                let arg_val = self.evaluate_node(arg_expr.syntax())?;
813                evaluated_args.push(arg_val);
814            }
815        }
816
817        match callee_syntax.kind() {
818            SyntaxKind::NAME_REF => {
819                // Handle custom functions (e.g., myFunc())
820                let name_ref = NameRef::cast(callee_syntax.clone()).unwrap(); // Should be safe given kind check
821                let func_name = name_ref.syntax().text().to_string();
822                if let Some(func) = self.custom_functions.get(&func_name) {
823                    func.call(&evaluated_args).map_err(EvaluationError::from)
824                } else {
825                    Err(EvaluationError::Node(NodeError {
826                        message: format!("Function '{}' not found.", func_name),
827                        node: Some(callee_syntax.clone()),
828                    }))
829                }
830            }
831            SyntaxKind::DOT_EXPR => {
832                // Handle method calls (e.g., myArray.includes())
833                let dot_expr = DotExpr::cast(callee_syntax.clone()).unwrap(); // Should be safe
834                let resolvable_callee = self.evaluate_dot_expr(&dot_expr)?;
835
836                match resolvable_callee {
837                    ResolvableValue::BuiltInMethod { object, method } => {
838                        match method {
839                            BuiltInMethodKind::ArrayIncludes => {
840                                if evaluated_args.len() != 1 {
841                                    return Err(EvaluationError::CustomFunction(
842                                        CustomFuncError::ArityError {
843                                            expected: 1,
844                                            got: evaluated_args.len(),
845                                        },
846                                    ));
847                                }
848                                if let Value::Array(arr) = *object {
849                                    let target_value = &evaluated_args[0];
850                                    let mut found = false;
851                                    for item in arr.iter() {
852                                        // JavaScript Array.includes uses SameValueZero comparison
853                                        // which is similar to strict equality but treats NaN as equal to NaN
854                                        if self.same_value_zero(item, target_value) {
855                                            found = true;
856                                            break;
857                                        }
858                                    }
859                                    Ok(Value::Bool(found))
860                                } else {
861                                    // This case should ideally be prevented by how BuiltInMethod is constructed in evaluate_dot_expr
862                                    Err(EvaluationError::TypeError("ArrayIncludes method called on a non-array internal object.".to_string()))
863                                }
864                            }
865                            BuiltInMethodKind::ObjectHasOwnProperty => {
866                                if evaluated_args.len() != 1 {
867                                    return Err(EvaluationError::CustomFunction(
868                                        CustomFuncError::ArityError {
869                                            expected: 1,
870                                            got: evaluated_args.len(),
871                                        },
872                                    ));
873                                }
874                                let prop_key_val = &evaluated_args[0];
875                                // Coerce argument to string, similar to JS
876                                let prop_key_str = self.value_to_string(prop_key_val);
877
878                                if let Value::Object(obj_map) = *object {
879                                    // object is the Box<Value>
880                                    Ok(Value::Bool(obj_map.contains_key(&prop_key_str)))
881                                } else {
882                                    // This should not happen if BuiltInMethod is constructed correctly
883                                    Err(EvaluationError::TypeError("ObjectHasOwnProperty method called on a non-object internal object.".to_string()))
884                                }
885                            }
886                        }
887                    }
888                    ResolvableValue::Json(json_val) => Err(EvaluationError::TypeError(format!(
889                        "'{}' (resulting from expression '{}') is not a function.",
890                        self.value_to_string(&json_val),
891                        dot_expr.syntax().text()
892                    ))),
893                }
894            }
895            _ => Err(EvaluationError::Node(NodeError {
896                message: format!(
897                    "Unsupported callee type: {:?}. Expected identifier or member expression.",
898                    callee_syntax.kind()
899                ),
900                node: Some(callee_syntax.clone()),
901            })),
902        }
903    }
904}