1use rslint_parser::{
2 ast::{
3 BinExpr, BinOp, CallExpr, CondExpr, DotExpr, Expr, GroupingExpr, Name, NameRef, UnaryExpr,
4 UnaryOp,
5 }, parse_text,
7 AstNode,
8 SyntaxKind,
9 SyntaxNode,
10};
11use serde_json::Value;
12use std::collections::HashMap;
13use std::fmt::Debug; use std::sync::Arc; use thiserror::Error;
16use tracing::trace; #[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, }
50
51#[derive(Debug, Clone, PartialEq)]
52pub enum ResolvableValue {
53 Json(Value),
54 BuiltInMethod {
55 object: Box<Value>, 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.", 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 SyntaxKind::ARRAY_EXPR => {
174 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 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())?; let cond_bool = self.to_boolean(&cond_value)?; let result = if cond_bool {
395 self.evaluate_node(true_expr.syntax())? } else {
397 self.evaluate_node(false_expr.syntax())? };
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 let prop_name = prop_name_ident.syntax().text().to_string();
424
425 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())), method: BuiltInMethodKind::ArrayIncludes,
444 })
445 } else {
446 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())), 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 Err(EvaluationError::TypeError(format!(
466 "Cannot read property 'length' of non-array/non-object value: {}", 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 fn abstract_equality(&self, left: &Value, right: &Value) -> bool {
483 match (left, right) {
484 (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 if l_num.is_nan() || r_num.is_nan() {
493 false
494 } else {
495 l_num == r_num
496 }
497 }
498
499 (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 (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 _ => false,
532 }
533 }
534
535 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 if l_num.is_nan() || r_num.is_nan() {
547 false
548 } else {
549 l_num == r_num
550 }
551 }
552 _ => false,
554 }
555 }
556
557 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 if l_num.is_nan() && r_num.is_nan() {
569 true
570 } else {
571 l_num == r_num
572 }
573 }
574 _ => false,
576 }
577 }
578
579 fn evaluate_by_name(&self, identifier_name: String) -> Result<Value, NodeError> {
580 match identifier_name.as_str() {
582 "Infinity" => {
583 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 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 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 if let Ok(number) = literal_str.parse::<f64>() {
659 return Ok(Value::Number(serde_json::Number::from_f64(number).unwrap()));
660 }
661
662 if literal_str.starts_with('"') || literal_str.starts_with('\'') {
664 let unquoted = if literal_str.len() >= 2 {
666 &literal_str[1..literal_str.len() - 1]
667 } else {
668 ""
669 };
670 let processed = self.process_escape_sequences(unquoted);
672 return Ok(Value::String(processed));
673 }
674
675 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 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 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 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), }
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 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 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 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 let name_ref = NameRef::cast(callee_syntax.clone()).unwrap(); 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 let dot_expr = DotExpr::cast(callee_syntax.clone()).unwrap(); 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 if self.same_value_zero(item, target_value) {
855 found = true;
856 break;
857 }
858 }
859 Ok(Value::Bool(found))
860 } else {
861 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 let prop_key_str = self.value_to_string(prop_key_val);
877
878 if let Value::Object(obj_map) = *object {
879 Ok(Value::Bool(obj_map.contains_key(&prop_key_str)))
881 } else {
882 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}