Skip to main content

r/interpreter/
value.rs

1pub mod buffer;
2pub mod character;
3pub mod complex;
4pub mod double;
5pub mod error;
6pub mod integer;
7pub mod logical;
8pub mod traits;
9pub mod vector;
10
11pub use buffer::NullableBuffer;
12pub use character::Character;
13pub use complex::ComplexVec;
14pub use double::Double;
15pub use error::{
16    get_class, make_condition, make_condition_with_call, ConditionKind, RError, RErrorKind, RFlow,
17    RSignal,
18};
19pub use integer::Integer;
20pub use logical::Logical;
21pub use traits::{
22    coerce_arg, coerce_arg_three_way, find_arg, find_named_arg, Builtin, BuiltinInfo, CoerceArg,
23    Dots, FromArgs, RArg,
24};
25pub use vector::{format_r_complex, format_r_double, Vector};
26
27use std::fmt;
28use std::ops::{Deref, DerefMut};
29
30use indexmap::IndexMap;
31use itertools::Itertools;
32use unicode_width::UnicodeWidthStr;
33
34use crate::interpreter::environment::Environment;
35use crate::interpreter::BuiltinContext;
36use crate::parser::ast::{Arg, Expr, Param};
37
38pub type BuiltinFn = fn(&[RValue], &[(String, RValue)]) -> Result<RValue, RError>;
39pub type InterpreterBuiltinFn =
40    for<'a> fn(&[RValue], &[(String, RValue)], &BuiltinContext<'a>) -> Result<RValue, RError>;
41pub type PreEvalBuiltinFn =
42    for<'a> fn(&[Arg], &Environment, &BuiltinContext<'a>) -> Result<RValue, RError>;
43
44#[derive(Debug, Clone, Copy)]
45pub enum BuiltinImplementation {
46    Eager(BuiltinFn),
47    Interpreter(InterpreterBuiltinFn),
48    PreEval(PreEvalBuiltinFn),
49}
50
51#[derive(Debug, Clone, Copy)]
52pub struct BuiltinDescriptor {
53    pub name: &'static str,
54    pub aliases: &'static [&'static str],
55    pub implementation: BuiltinImplementation,
56    pub min_args: usize,
57    pub max_args: Option<usize>,
58    /// Raw doc string extracted from rustdoc comments (may contain @param/@title tags).
59    pub doc: &'static str,
60    /// Namespace this builtin belongs to (e.g. "base", "stats", "utils", "collections").
61    pub namespace: &'static str,
62    /// Formal parameter names (extracted from @param doc comments).
63    /// Used at dispatch time to reorder positional/named args into canonical order
64    /// so builtins can use `args[i]` regardless of how the user passed the args.
65    /// Empty for variadic (dots) builtins — no reordering is performed.
66    pub formals: &'static [&'static str],
67}
68
69/// Attribute map — every R object can carry named attributes.
70///
71/// Uses `IndexMap` to preserve insertion order, matching R's behavior where
72/// `attributes(x)` returns attributes in the order they were set.
73pub type Attributes = IndexMap<String, RValue>;
74
75/// Unevaluated expression (language object) — returned by quote(), parse().
76///
77/// Wraps a boxed AST node. Derefs to `Expr` for pattern matching.
78#[derive(Debug, Clone)]
79pub struct Language {
80    pub inner: Box<Expr>,
81    pub attrs: Option<Box<Attributes>>,
82}
83
84impl Language {
85    pub fn new(expr: Expr) -> Self {
86        Language {
87            inner: Box::new(expr),
88            attrs: None,
89        }
90    }
91
92    pub fn get_attr(&self, name: &str) -> Option<&RValue> {
93        self.attrs.as_ref().and_then(|a| a.get(name))
94    }
95
96    pub fn set_attr(&mut self, name: String, value: RValue) {
97        self.attrs
98            .get_or_insert_with(|| Box::new(IndexMap::new()))
99            .insert(name, value);
100    }
101
102    pub fn class(&self) -> Option<Vec<String>> {
103        match self.get_attr("class") {
104            Some(RValue::Vector(rv)) => match &rv.inner {
105                Vector::Character(v) => Some(v.iter().filter_map(|s| s.clone()).collect()),
106                _ => None,
107            },
108            _ => None,
109        }
110    }
111
112    /// Return the R-style "length" of this language object.
113    ///
114    /// In R, language objects are list-like:
115    /// - `quote(f(a, b))` has length 3 (function + 2 args)
116    /// - `quote(a + b)` has length 3 (`+`, a, b)
117    /// - `quote(-x)` has length 2 (`-`, x)
118    /// - `quote({a; b})` has length 3 (`{`, a, b)
119    /// - Atomic expressions (symbols, literals) have length 1
120    pub fn language_length(&self) -> usize {
121        match self.inner.as_ref() {
122            Expr::Call { args, .. } => {
123                // Only count args that have a value (filter out empty placeholder args
124                // like the one generated by `f()` which has one Arg{name:None,value:None})
125                1 + args.iter().filter(|a| a.value.is_some()).count()
126            }
127            Expr::BinaryOp { .. } => 3,
128            Expr::UnaryOp { .. } => 2,
129            Expr::Block(exprs) => 1 + exprs.len(),
130            Expr::If { else_body, .. } => {
131                if else_body.is_some() {
132                    4
133                } else {
134                    3
135                }
136            }
137            Expr::For { .. } => 4,
138            Expr::While { .. } => 3,
139            Expr::Repeat { .. } => 2,
140            Expr::Assign { .. } => 3,
141            Expr::Function { .. } => 3,
142            Expr::Index { indices, .. } => 2 + indices.len(),
143            Expr::IndexDouble { indices, .. } => 2 + indices.len(),
144            Expr::Dollar { .. } => 3,
145            Expr::Slot { .. } => 3,
146            Expr::Formula { lhs, rhs } => {
147                1 + usize::from(lhs.is_some()) + usize::from(rhs.is_some())
148            }
149            Expr::Return(Some(_)) => 2,
150            Expr::Return(None) => 1,
151            // Atomic expressions: symbols, literals, etc.
152            _ => 1,
153        }
154    }
155
156    /// Return the i-th element (1-based) of this language object as an `RValue`.
157    ///
158    /// In R, language objects can be indexed with `[[`:
159    /// - Index 1 is the "function" (operator, keyword, etc.)
160    /// - Index 2+ are the arguments/operands
161    ///
162    /// Returns `None` if the index is out of bounds.
163    pub fn language_element(&self, index: usize) -> Option<RValue> {
164        if index == 0 || index > self.language_length() {
165            return None;
166        }
167        match self.inner.as_ref() {
168            Expr::Call { func, args, .. } => {
169                if index == 1 {
170                    Some(expr_to_rvalue(func))
171                } else {
172                    // Skip empty placeholder args (like the one in `f()`)
173                    args.iter()
174                        .filter_map(|arg| arg.value.as_ref())
175                        .nth(index - 2)
176                        .map(expr_to_rvalue)
177                }
178            }
179            Expr::BinaryOp { op, lhs, rhs } => match index {
180                1 => Some(RValue::Language(Language::new(Expr::Symbol(
181                    binary_op_symbol(op),
182                )))),
183                2 => Some(expr_to_rvalue(lhs)),
184                3 => Some(expr_to_rvalue(rhs)),
185                _ => None,
186            },
187            Expr::UnaryOp { op, operand } => match index {
188                1 => Some(RValue::Language(Language::new(Expr::Symbol(
189                    unary_op_symbol(op),
190                )))),
191                2 => Some(expr_to_rvalue(operand)),
192                _ => None,
193            },
194            Expr::Block(exprs) => {
195                if index == 1 {
196                    Some(RValue::Language(Language::new(Expr::Symbol(
197                        "{".to_string(),
198                    ))))
199                } else {
200                    exprs.get(index - 2).map(expr_to_rvalue)
201                }
202            }
203            Expr::If {
204                condition,
205                then_body,
206                else_body,
207            } => match index {
208                1 => Some(RValue::Language(Language::new(Expr::Symbol(
209                    "if".to_string(),
210                )))),
211                2 => Some(expr_to_rvalue(condition)),
212                3 => Some(expr_to_rvalue(then_body)),
213                4 => else_body.as_ref().map(|e| expr_to_rvalue(e)),
214                _ => None,
215            },
216            Expr::For { var, iter, body } => match index {
217                1 => Some(RValue::Language(Language::new(Expr::Symbol(
218                    "for".to_string(),
219                )))),
220                2 => Some(RValue::Language(Language::new(Expr::Symbol(var.clone())))),
221                3 => Some(expr_to_rvalue(iter)),
222                4 => Some(expr_to_rvalue(body)),
223                _ => None,
224            },
225            Expr::While { condition, body } => match index {
226                1 => Some(RValue::Language(Language::new(Expr::Symbol(
227                    "while".to_string(),
228                )))),
229                2 => Some(expr_to_rvalue(condition)),
230                3 => Some(expr_to_rvalue(body)),
231                _ => None,
232            },
233            Expr::Repeat { body } => match index {
234                1 => Some(RValue::Language(Language::new(Expr::Symbol(
235                    "repeat".to_string(),
236                )))),
237                2 => Some(expr_to_rvalue(body)),
238                _ => None,
239            },
240            Expr::Assign { op, target, value } => match index {
241                1 => Some(RValue::Language(Language::new(Expr::Symbol(
242                    assign_op_symbol(op),
243                )))),
244                2 => Some(expr_to_rvalue(target)),
245                3 => Some(expr_to_rvalue(value)),
246                _ => None,
247            },
248            Expr::Function { params, body } => match index {
249                1 => Some(RValue::Language(Language::new(Expr::Symbol(
250                    "function".to_string(),
251                )))),
252                2 => {
253                    // Formals as a pairlist (represented as a named list)
254                    let entries: Vec<(Option<String>, RValue)> = params
255                        .iter()
256                        .map(|p| {
257                            let val = if p.is_dots {
258                                RValue::Language(Language::new(Expr::Dots))
259                            } else if let Some(ref d) = p.default {
260                                expr_to_rvalue(d)
261                            } else {
262                                // Missing default -> empty symbol (R uses this)
263                                RValue::Language(Language::new(Expr::Symbol(String::new())))
264                            };
265                            (Some(p.name.clone()), val)
266                        })
267                        .collect();
268                    Some(RValue::List(RList::new(entries)))
269                }
270                3 => Some(expr_to_rvalue(body)),
271                _ => None,
272            },
273            Expr::Index { object, indices } => {
274                if index == 1 {
275                    Some(RValue::Language(Language::new(Expr::Symbol(
276                        "[".to_string(),
277                    ))))
278                } else if index == 2 {
279                    Some(expr_to_rvalue(object))
280                } else {
281                    indices
282                        .get(index - 3)
283                        .and_then(|arg| arg.value.as_ref())
284                        .map(expr_to_rvalue)
285                }
286            }
287            Expr::IndexDouble { object, indices } => {
288                if index == 1 {
289                    Some(RValue::Language(Language::new(Expr::Symbol(
290                        "[[".to_string(),
291                    ))))
292                } else if index == 2 {
293                    Some(expr_to_rvalue(object))
294                } else {
295                    indices
296                        .get(index - 3)
297                        .and_then(|arg| arg.value.as_ref())
298                        .map(expr_to_rvalue)
299                }
300            }
301            Expr::Dollar { object, member } => match index {
302                1 => Some(RValue::Language(Language::new(Expr::Symbol(
303                    "$".to_string(),
304                )))),
305                2 => Some(expr_to_rvalue(object)),
306                3 => Some(RValue::Language(Language::new(Expr::Symbol(
307                    member.clone(),
308                )))),
309                _ => None,
310            },
311            Expr::Slot { object, member } => match index {
312                1 => Some(RValue::Language(Language::new(Expr::Symbol(
313                    "@".to_string(),
314                )))),
315                2 => Some(expr_to_rvalue(object)),
316                3 => Some(RValue::Language(Language::new(Expr::Symbol(
317                    member.clone(),
318                )))),
319                _ => None,
320            },
321            Expr::Formula { lhs, rhs } => {
322                if index == 1 {
323                    Some(RValue::Language(Language::new(Expr::Symbol(
324                        "~".to_string(),
325                    ))))
326                } else {
327                    // Elements are lhs (if present) then rhs (if present)
328                    let mut elems = Vec::new();
329                    if let Some(l) = lhs {
330                        elems.push(expr_to_rvalue(l));
331                    }
332                    if let Some(r) = rhs {
333                        elems.push(expr_to_rvalue(r));
334                    }
335                    elems.into_iter().nth(index - 2)
336                }
337            }
338            Expr::Return(arg) => match index {
339                1 => Some(RValue::Language(Language::new(Expr::Symbol(
340                    "return".to_string(),
341                )))),
342                2 => arg.as_ref().map(|e| expr_to_rvalue(e)),
343                _ => None,
344            },
345            // Atomic: only index 1 returns the value itself
346            _ => {
347                if index == 1 {
348                    Some(expr_to_rvalue(&self.inner))
349                } else {
350                    None
351                }
352            }
353        }
354    }
355
356    /// Return a new Language with the i-th element (1-based) replaced by `val`.
357    ///
358    /// This is the write-side counterpart to `language_element` — it implements
359    /// `[[<-` on language objects.  Returns `None` if the index is out of bounds.
360    pub fn set_element(&self, index: usize, val: &RValue) -> Option<Language> {
361        if index == 0 || index > self.language_length() {
362            return None;
363        }
364        let new_expr = rvalue_to_expr(val);
365        let mut result = (*self.inner).clone();
366        match &mut result {
367            Expr::Call { func, args, .. } => {
368                if index == 1 {
369                    **func = new_expr;
370                } else {
371                    // Find the (index-2)th arg with a value
372                    let mut count = 0;
373                    for arg in args.iter_mut() {
374                        if arg.value.is_some() {
375                            if count == index - 2 {
376                                arg.value = Some(new_expr);
377                                break;
378                            }
379                            count += 1;
380                        }
381                    }
382                }
383            }
384            Expr::BinaryOp { lhs, rhs, .. } => match index {
385                2 => **lhs = new_expr,
386                3 => **rhs = new_expr,
387                _ => return None,
388            },
389            Expr::UnaryOp { operand, .. } => {
390                if index == 2 {
391                    **operand = new_expr;
392                } else {
393                    return None;
394                }
395            }
396            Expr::Block(exprs) => {
397                if index >= 2 && index - 2 < exprs.len() {
398                    exprs[index - 2] = new_expr;
399                } else {
400                    return None;
401                }
402            }
403            Expr::If {
404                condition,
405                then_body,
406                else_body,
407            } => match index {
408                2 => **condition = new_expr,
409                3 => **then_body = new_expr,
410                4 => *else_body = Some(Box::new(new_expr)),
411                _ => return None,
412            },
413            Expr::For { var, iter, body } => match index {
414                2 => {
415                    if let Expr::Symbol(name) = new_expr {
416                        *var = name;
417                    }
418                }
419                3 => **iter = new_expr,
420                4 => **body = new_expr,
421                _ => return None,
422            },
423            Expr::While { condition, body } => match index {
424                2 => **condition = new_expr,
425                3 => **body = new_expr,
426                _ => return None,
427            },
428            Expr::Repeat { body } => {
429                if index == 2 {
430                    **body = new_expr;
431                } else {
432                    return None;
433                }
434            }
435            Expr::Assign { target, value, .. } => match index {
436                2 => **target = new_expr,
437                3 => **value = new_expr,
438                _ => return None,
439            },
440            Expr::Function { body, .. } => {
441                if index == 3 {
442                    **body = new_expr;
443                } else {
444                    return None;
445                }
446            }
447            Expr::Index { object, indices } | Expr::IndexDouble { object, indices } => {
448                if index == 2 {
449                    **object = new_expr;
450                } else if index >= 3 && index - 3 < indices.len() {
451                    indices[index - 3].value = Some(new_expr);
452                } else {
453                    return None;
454                }
455            }
456            Expr::Dollar { object, member } | Expr::Slot { object, member } => match index {
457                2 => **object = new_expr,
458                3 => {
459                    if let Expr::Symbol(name) = new_expr {
460                        *member = name;
461                    }
462                }
463                _ => return None,
464            },
465            Expr::Formula { lhs, rhs } => {
466                let has_lhs = lhs.is_some();
467                match (index, has_lhs) {
468                    (2, true) => *lhs = Some(Box::new(new_expr)),
469                    (2, false) => *rhs = Some(Box::new(new_expr)),
470                    (3, true) => *rhs = Some(Box::new(new_expr)),
471                    _ => return None,
472                }
473            }
474            Expr::Return(arg) => {
475                if index == 2 {
476                    *arg = Some(Box::new(new_expr));
477                } else {
478                    return None;
479                }
480            }
481            _ => return None,
482        }
483        let mut lang = Language::new(result);
484        if let Some(ref attrs) = self.attrs {
485            lang.attrs = Some(attrs.clone());
486        }
487        Some(lang)
488    }
489}
490
491/// Convert an Expr to an RValue — atomic expressions become symbols/literals,
492/// compound expressions become Language objects.
493fn expr_to_rvalue(expr: &Expr) -> RValue {
494    match expr {
495        // Literals evaluate to their corresponding R values
496        Expr::Null => RValue::Null,
497        Expr::Bool(b) => RValue::vec(Vector::Logical(vec![Some(*b)].into())),
498        Expr::Integer(i) => RValue::vec(Vector::Integer(vec![Some(*i)].into())),
499        Expr::Double(d) => RValue::vec(Vector::Double(vec![Some(*d)].into())),
500        Expr::Complex(d) => RValue::vec(Vector::Complex(
501            vec![Some(num_complex::Complex64::new(0.0, *d))].into(),
502        )),
503        Expr::String(s) => RValue::vec(Vector::Character(vec![Some(s.clone())].into())),
504        Expr::Inf => RValue::vec(Vector::Double(vec![Some(f64::INFINITY)].into())),
505        Expr::NaN => RValue::vec(Vector::Double(vec![Some(f64::NAN)].into())),
506        Expr::Na(na) => match na {
507            NaType::Logical => RValue::vec(Vector::Logical(vec![None].into())),
508            NaType::Integer => RValue::vec(Vector::Integer(vec![None].into())),
509            NaType::Real => RValue::vec(Vector::Double(vec![None].into())),
510            NaType::Character => RValue::vec(Vector::Character(vec![None].into())),
511            NaType::Complex => RValue::vec(Vector::Complex(vec![None].into())),
512        },
513        // Symbols stay as language objects (names in R)
514        Expr::Symbol(_) | Expr::Dots | Expr::DotDot(_) => {
515            RValue::Language(Language::new(expr.clone()))
516        }
517        // Compound expressions become language objects
518        _ => RValue::Language(Language::new(expr.clone())),
519    }
520}
521
522/// Convert an RValue back to an Expr — the inverse of `expr_to_rvalue`.
523///
524/// Used by `Language::set_element` to splice RValues into AST nodes.
525pub(crate) fn rvalue_to_expr(val: &RValue) -> Expr {
526    match val {
527        RValue::Null => Expr::Null,
528        RValue::Language(lang) => (*lang.inner).clone(),
529        RValue::Vector(rv) if rv.inner.len() == 1 => match &rv.inner {
530            Vector::Logical(v) => match v[0] {
531                Some(true) => Expr::Bool(true),
532                Some(false) => Expr::Bool(false),
533                None => Expr::Na(NaType::Logical),
534            },
535            Vector::Integer(v) => match v.get_opt(0) {
536                Some(i) => Expr::Integer(i),
537                None => Expr::Na(NaType::Integer),
538            },
539            Vector::Double(v) => match v.get_opt(0) {
540                Some(d) if d.is_infinite() && d > 0.0 => Expr::Inf,
541                Some(d) if d.is_nan() => Expr::NaN,
542                Some(d) => Expr::Double(d),
543                None => Expr::Na(NaType::Real),
544            },
545            Vector::Character(v) => match &v[0] {
546                Some(s) => Expr::String(s.clone()),
547                None => Expr::Na(NaType::Character),
548            },
549            Vector::Complex(v) => match &v[0] {
550                Some(c) if c.re == 0.0 => Expr::Complex(c.im),
551                Some(c) => {
552                    // a+bi → BinaryOp(Add, Double(a), Complex(b))
553                    Expr::BinaryOp {
554                        op: BinaryOp::Add,
555                        lhs: Box::new(Expr::Double(c.re)),
556                        rhs: Box::new(Expr::Complex(c.im)),
557                    }
558                }
559                None => Expr::Na(NaType::Complex),
560            },
561            Vector::Raw(_) => {
562                // Raw scalars don't have a direct Expr form; wrap as integer
563                Expr::Integer(rv.inner.to_integers()[0].unwrap_or(0))
564            }
565        },
566        // Multi-element vectors: generate c(e1, e2, ...) call expression
567        RValue::Vector(rv) => {
568            let args: Vec<Arg> = (0..rv.inner.len())
569                .map(|i| {
570                    let expr = match &rv.inner {
571                        Vector::Double(v) => match v.get_opt(i) {
572                            Some(d) => Expr::Double(d),
573                            None => Expr::Na(NaType::Real),
574                        },
575                        Vector::Integer(v) => match v.get_opt(i) {
576                            Some(n) => Expr::Integer(n),
577                            None => Expr::Na(NaType::Integer),
578                        },
579                        Vector::Character(v) => match &v[i] {
580                            Some(s) => Expr::String(s.clone()),
581                            None => Expr::Na(NaType::Character),
582                        },
583                        Vector::Logical(v) => match v[i] {
584                            Some(b) => Expr::Bool(b),
585                            None => Expr::Na(NaType::Logical),
586                        },
587                        Vector::Complex(v) => match &v[i] {
588                            Some(c) if c.re == 0.0 => Expr::Complex(c.im),
589                            Some(c) => Expr::BinaryOp {
590                                op: BinaryOp::Add,
591                                lhs: Box::new(Expr::Double(c.re)),
592                                rhs: Box::new(Expr::Complex(c.im)),
593                            },
594                            None => Expr::Na(NaType::Complex),
595                        },
596                        Vector::Raw(v) => Expr::Integer(i64::from(v[i])),
597                    };
598                    Arg {
599                        name: None,
600                        value: Some(expr),
601                    }
602                })
603                .collect();
604            Expr::Call {
605                func: Box::new(Expr::Symbol("c".to_string())),
606                args,
607                span: None,
608            }
609        }
610        // Functions: reconstruct the function expression from closure params/body
611        RValue::Function(f) => match f {
612            RFunction::Closure { params, body, .. } => Expr::Function {
613                params: params.clone(),
614                body: Box::new(body.clone()),
615            },
616            RFunction::Builtin { name, .. } => Expr::Symbol(name.clone()),
617        },
618        // Lists: generate list(k1=v1, k2=v2, ...) call expression
619        RValue::List(list) => {
620            let args: Vec<Arg> = list
621                .values
622                .iter()
623                .map(|(name, val)| Arg {
624                    name: name.clone(),
625                    value: Some(rvalue_to_expr(val)),
626                })
627                .collect();
628            Expr::Call {
629                func: Box::new(Expr::Symbol("list".to_string())),
630                args,
631                span: None,
632            }
633        }
634        // Environments and promises: no meaningful Expr representation
635        _ => Expr::Null,
636    }
637}
638
639/// Map a BinaryOp to its R symbol name.
640fn binary_op_symbol(op: &BinaryOp) -> String {
641    match op {
642        BinaryOp::Add => "+".to_string(),
643        BinaryOp::Sub => "-".to_string(),
644        BinaryOp::Mul => "*".to_string(),
645        BinaryOp::Div => "/".to_string(),
646        BinaryOp::Pow => "^".to_string(),
647        BinaryOp::Mod => "%%".to_string(),
648        BinaryOp::IntDiv => "%/%".to_string(),
649        BinaryOp::Eq => "==".to_string(),
650        BinaryOp::Ne => "!=".to_string(),
651        BinaryOp::Lt => "<".to_string(),
652        BinaryOp::Gt => ">".to_string(),
653        BinaryOp::Le => "<=".to_string(),
654        BinaryOp::Ge => ">=".to_string(),
655        BinaryOp::And => "&".to_string(),
656        BinaryOp::AndScalar => "&&".to_string(),
657        BinaryOp::Or => "|".to_string(),
658        BinaryOp::OrScalar => "||".to_string(),
659        BinaryOp::Range => ":".to_string(),
660        BinaryOp::Pipe => "|>".to_string(),
661        BinaryOp::AssignPipe => "%<>%".to_string(),
662        BinaryOp::TeePipe => "%T>%".to_string(),
663        BinaryOp::ExpoPipe => "%$%".to_string(),
664        BinaryOp::Special(SpecialOp::In) => "%in%".to_string(),
665        BinaryOp::Special(SpecialOp::MatMul) => "%*%".to_string(),
666        BinaryOp::Special(SpecialOp::Kronecker) => "%x%".to_string(),
667        BinaryOp::Special(SpecialOp::Walrus) => ":=".to_string(),
668        BinaryOp::Special(SpecialOp::Other(ref name)) => name.clone(),
669        BinaryOp::Tilde => "~".to_string(),
670        BinaryOp::DoubleTilde => "~~".to_string(),
671    }
672}
673
674/// Map a UnaryOp to its R symbol name.
675fn unary_op_symbol(op: &UnaryOp) -> String {
676    match op {
677        UnaryOp::Neg => "-".to_string(),
678        UnaryOp::Pos => "+".to_string(),
679        UnaryOp::Not => "!".to_string(),
680        UnaryOp::Formula => "~".to_string(),
681    }
682}
683
684/// Map an AssignOp to its R symbol name.
685fn assign_op_symbol(op: &AssignOp) -> String {
686    match op {
687        AssignOp::LeftAssign => "<-".to_string(),
688        AssignOp::SuperAssign => "<<-".to_string(),
689        AssignOp::Equals => "=".to_string(),
690        AssignOp::RightAssign => "->".to_string(),
691        AssignOp::RightSuperAssign => "->>".to_string(),
692    }
693}
694
695impl Deref for Language {
696    type Target = Expr;
697
698    fn deref(&self) -> &Self::Target {
699        &self.inner
700    }
701}
702
703impl DerefMut for Language {
704    fn deref_mut(&mut self) -> &mut Self::Target {
705        &mut self.inner
706    }
707}
708
709/// Lazy promise: wraps an unevaluated expression + its lexical environment.
710///
711/// Created when a closure is called — each argument becomes a promise that is
712/// only evaluated (forced) when its value is actually needed. Once forced, the
713/// result is cached so subsequent accesses return the same value.
714///
715/// The `forcing` flag detects recursive promise evaluation (e.g. `f(x = x)`).
716#[derive(Debug, Clone)]
717pub struct RPromise {
718    pub expr: Expr,
719    pub env: Environment,
720    pub value: Option<RValue>,
721    pub forcing: bool,
722}
723
724impl RPromise {
725    pub fn new(expr: Expr, env: Environment) -> Self {
726        RPromise {
727            expr,
728            env,
729            value: None,
730            forcing: false,
731        }
732    }
733}
734
735/// Shared promise handle — promises are mutable (cached once forced) and may
736/// be referenced from multiple places (e.g. `...` forwarding), so they live
737/// behind `Rc<RefCell<>>`.
738pub type SharedPromise = std::rc::Rc<std::cell::RefCell<RPromise>>;
739
740#[derive(Debug, Clone)]
741pub enum RValue {
742    /// NULL
743    Null,
744    /// Atomic vector (with optional attributes)
745    Vector(RVector),
746    /// List (generic vector)
747    List(RList),
748    /// Function (closure)
749    Function(RFunction),
750    /// Environment reference
751    Environment(Environment),
752    /// Language object (unevaluated expression)
753    Language(Language),
754    /// Lazy promise (unevaluated argument with cached result)
755    Promise(SharedPromise),
756}
757
758/// Atomic vector with optional attributes (names, class, dim, etc.)
759#[derive(Debug, Clone)]
760pub struct RVector {
761    pub inner: Vector,
762    pub attrs: Option<Box<Attributes>>,
763}
764
765impl Deref for RVector {
766    type Target = Vector;
767    fn deref(&self) -> &Vector {
768        &self.inner
769    }
770}
771
772impl DerefMut for RVector {
773    fn deref_mut(&mut self) -> &mut Vector {
774        &mut self.inner
775    }
776}
777
778impl From<Vector> for RVector {
779    fn from(v: Vector) -> Self {
780        RVector {
781            inner: v,
782            attrs: None,
783        }
784    }
785}
786
787impl RVector {
788    pub fn get_attr(&self, name: &str) -> Option<&RValue> {
789        self.attrs.as_ref().and_then(|a| a.get(name))
790    }
791
792    pub fn set_attr(&mut self, name: String, value: RValue) {
793        self.attrs
794            .get_or_insert_with(|| Box::new(IndexMap::new()))
795            .insert(name, value);
796    }
797
798    pub fn class(&self) -> Option<Vec<String>> {
799        match self.get_attr("class") {
800            Some(RValue::Vector(rv)) => match &rv.inner {
801                Vector::Character(v) => Some(v.iter().filter_map(|s| s.clone()).collect()),
802                _ => None,
803            },
804            _ => None,
805        }
806    }
807}
808
809#[derive(Debug, Clone)]
810pub struct RList {
811    pub values: Vec<(Option<String>, RValue)>,
812    pub attrs: Option<Box<Attributes>>,
813}
814
815impl RList {
816    pub fn new(values: Vec<(Option<String>, RValue)>) -> Self {
817        RList {
818            values,
819            attrs: None,
820        }
821    }
822
823    pub fn get_attr(&self, name: &str) -> Option<&RValue> {
824        self.attrs.as_ref().and_then(|a| a.get(name))
825    }
826
827    pub fn set_attr(&mut self, name: String, value: RValue) {
828        self.attrs
829            .get_or_insert_with(|| Box::new(IndexMap::new()))
830            .insert(name, value);
831    }
832
833    #[allow(dead_code)]
834    pub fn class(&self) -> Option<Vec<String>> {
835        match self.get_attr("class") {
836            Some(RValue::Vector(rv)) => match &rv.inner {
837                Vector::Character(v) => Some(v.iter().filter_map(|s| s.clone()).collect()),
838                _ => None,
839            },
840            _ => None,
841        }
842    }
843}
844
845#[derive(Debug, Clone)]
846pub enum RFunction {
847    Closure {
848        params: Vec<Param>,
849        body: Expr,
850        env: Environment,
851    },
852    Builtin {
853        name: String,
854        implementation: BuiltinImplementation,
855        min_args: usize,
856        max_args: Option<usize>,
857        formals: &'static [&'static str],
858    },
859}
860
861// region: From / TryFrom impls
862
863impl From<RVector> for RValue {
864    fn from(rv: RVector) -> Self {
865        RValue::Vector(rv)
866    }
867}
868
869impl From<RList> for RValue {
870    fn from(list: RList) -> Self {
871        RValue::List(list)
872    }
873}
874
875impl<'a> TryFrom<&'a RValue> for &'a RVector {
876    type Error = RError;
877    fn try_from(value: &'a RValue) -> Result<Self, Self::Error> {
878        match value {
879            RValue::Vector(rv) => Ok(rv),
880            other => Err(RError::new(
881                RErrorKind::Type,
882                format!("expected vector, got {}", other.type_name()),
883            )),
884        }
885    }
886}
887
888impl TryFrom<RValue> for RVector {
889    type Error = RError;
890    fn try_from(value: RValue) -> Result<Self, Self::Error> {
891        match value {
892            RValue::Vector(rv) => Ok(rv),
893            other => Err(RError::new(
894                RErrorKind::Type,
895                format!("expected vector, got {}", other.type_name()),
896            )),
897        }
898    }
899}
900
901impl<'a> TryFrom<&'a RValue> for &'a RList {
902    type Error = RError;
903    fn try_from(value: &'a RValue) -> Result<Self, Self::Error> {
904        match value {
905            RValue::List(l) => Ok(l),
906            other => Err(RError::new(
907                RErrorKind::Type,
908                format!("expected list, got {}", other.type_name()),
909            )),
910        }
911    }
912}
913
914impl TryFrom<RValue> for RList {
915    type Error = RError;
916    fn try_from(value: RValue) -> Result<Self, Self::Error> {
917        match value {
918            RValue::List(l) => Ok(l),
919            other => Err(RError::new(
920                RErrorKind::Type,
921                format!("expected list, got {}", other.type_name()),
922            )),
923        }
924    }
925}
926
927// endregion
928
929// region: RValue impls
930
931impl RValue {
932    /// Convenience: wrap an atomic Vector into RValue::Vector with no attributes.
933    pub fn vec(v: Vector) -> Self {
934        RValue::Vector(RVector {
935            inner: v,
936            attrs: None,
937        })
938    }
939
940    /// Create a lazy promise wrapping an unevaluated expression and its lexical env.
941    pub fn promise(expr: Expr, env: Environment) -> Self {
942        RValue::Promise(std::rc::Rc::new(std::cell::RefCell::new(RPromise::new(
943            expr, env,
944        ))))
945    }
946
947    pub fn is_null(&self) -> bool {
948        matches!(self, RValue::Null)
949    }
950
951    pub fn as_vector(&self) -> Option<&Vector> {
952        match self {
953            RValue::Vector(rv) => Some(&rv.inner),
954            _ => None,
955        }
956    }
957
958    #[allow(dead_code)]
959    pub fn into_vector(self) -> Result<Vector, RError> {
960        match self {
961            RValue::Vector(rv) => Ok(rv.inner),
962            RValue::Null => Ok(Vector::Logical(Logical(vec![]))),
963            _ => Err(RError::new(
964                RErrorKind::Type,
965                "cannot coerce to vector".to_string(),
966            )),
967        }
968    }
969
970    pub fn type_name(&self) -> &str {
971        match self {
972            RValue::Null => "NULL",
973            RValue::Vector(rv) => rv.inner.type_name(),
974            RValue::List(_) => "list",
975            RValue::Function(_) => "function",
976            RValue::Environment(_) => "environment",
977            RValue::Language(_) => "language",
978            RValue::Promise(_) => "promise",
979        }
980    }
981
982    pub fn length(&self) -> usize {
983        match self {
984            RValue::Null => 0,
985            RValue::Vector(rv) => rv.inner.len(),
986            RValue::List(l) => l.values.len(),
987            RValue::Function(_) => 1,
988            RValue::Environment(_) => 0,
989            RValue::Language(lang) => lang.language_length(),
990            RValue::Promise(_) => 1,
991        }
992    }
993}
994
995// endregion
996
997// region: Display
998
999impl fmt::Display for RValue {
1000    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1001        match self {
1002            RValue::Null => write!(f, "NULL"),
1003            RValue::Vector(rv) => write!(f, "{}", format_vector(&rv.inner)),
1004            RValue::List(list) => {
1005                for (i, (name, val)) in list.values.iter().enumerate() {
1006                    match name {
1007                        Some(n) => writeln!(f, "${}", n)?,
1008                        None => writeln!(f, "[[{}]]", i + 1)?,
1009                    }
1010                    writeln!(f, "{}", val)?;
1011                }
1012                Ok(())
1013            }
1014            RValue::Function(func) => match func {
1015                RFunction::Closure { .. } => write!(f, "function(...)"),
1016                RFunction::Builtin { name, .. } => write!(f, ".Primitive(\"{}\")", name),
1017            },
1018            RValue::Environment(_env) => write!(f, "<environment>"),
1019            RValue::Language(expr) => write!(f, "{}", deparse_expr(expr)),
1020            RValue::Promise(p) => {
1021                let p = p.borrow();
1022                if let Some(ref val) = p.value {
1023                    write!(f, "{}", val)
1024                } else {
1025                    write!(f, "<promise: {}>", deparse_expr(&p.expr))
1026                }
1027            }
1028        }
1029    }
1030}
1031
1032pub fn format_vector(v: &Vector) -> String {
1033    let len = v.len();
1034    if len == 0 {
1035        return match v {
1036            Vector::Raw(_) => "raw(0)".to_string(),
1037            Vector::Logical(_) => "logical(0)".to_string(),
1038            Vector::Integer(_) => "integer(0)".to_string(),
1039            Vector::Double(_) => "numeric(0)".to_string(),
1040            Vector::Complex(_) => "complex(0)".to_string(),
1041            Vector::Character(_) => "character(0)".to_string(),
1042        };
1043    }
1044
1045    let elements: Vec<String> = match v {
1046        Vector::Raw(vals) => vals.iter().map(|b| format!("{:02x}", b)).collect(),
1047        Vector::Logical(vals) => vals
1048            .iter()
1049            .map(|x| match x {
1050                Some(true) => "TRUE".to_string(),
1051                Some(false) => "FALSE".to_string(),
1052                None => "NA".to_string(),
1053            })
1054            .collect(),
1055        Vector::Integer(vals) => vals
1056            .iter()
1057            .map(|x| match x {
1058                Some(i) => i.to_string(),
1059                None => "NA".to_string(),
1060            })
1061            .collect(),
1062        Vector::Double(vals) => vals
1063            .iter()
1064            .map(|x| match x {
1065                Some(f) => format_r_double(f),
1066                None => "NA".to_string(),
1067            })
1068            .collect(),
1069        Vector::Complex(vals) => vals
1070            .iter()
1071            .map(|x| match x {
1072                Some(c) => format_r_complex(*c),
1073                None => "NA".to_string(),
1074            })
1075            .collect(),
1076        Vector::Character(vals) => vals
1077            .iter()
1078            .map(|x| match x {
1079                Some(s) => format!("\"{}\"", s),
1080                None => "NA".to_string(),
1081            })
1082            .collect(),
1083    };
1084
1085    // Right-align all elements to the width of the widest, matching R's output.
1086    let max_elem_width = elements
1087        .iter()
1088        .map(|e| UnicodeWidthStr::width(e.as_str()))
1089        .max()
1090        .unwrap_or(1);
1091    let padded: Vec<String> = elements
1092        .iter()
1093        .map(|e| format!("{:>width$}", e, width = max_elem_width))
1094        .collect();
1095
1096    if len == 1 {
1097        return format!("[1] {}", padded[0]);
1098    }
1099
1100    // Format with line indices like R does.
1101    // Label width is based on the largest index label.
1102    let max_label = format!("[{}]", len);
1103    let label_pad = UnicodeWidthStr::width(max_label.as_str());
1104    let max_width = 80;
1105    let mut result = String::new();
1106    let mut pos = 0;
1107    let elem_col_width = max_elem_width + 1; // +1 for space between elements
1108
1109    while pos < padded.len() {
1110        let label = format!("[{}]", pos + 1);
1111        let mut line = format!("{:>width$}", label, width = label_pad);
1112        let mut current_width = label_pad;
1113        let line_start = pos;
1114
1115        while pos < padded.len() {
1116            if current_width + elem_col_width > max_width && pos > line_start {
1117                break;
1118            }
1119            line.push(' ');
1120            line.push_str(&padded[pos]);
1121            current_width += elem_col_width;
1122            pos += 1;
1123        }
1124
1125        if !result.is_empty() {
1126            result.push('\n');
1127        }
1128        result.push_str(&line);
1129    }
1130
1131    result
1132}
1133
1134// endregion
1135
1136// region: deparse
1137
1138use crate::parser::ast::{AssignOp, BinaryOp, NaType, SpecialOp, UnaryOp};
1139
1140/// Convert an AST expression back to R source code (deparse).
1141pub fn deparse_expr(expr: &Expr) -> String {
1142    match expr {
1143        Expr::Null => "NULL".to_string(),
1144        Expr::Na(NaType::Logical) => "NA".to_string(),
1145        Expr::Na(NaType::Integer) => "NA_integer_".to_string(),
1146        Expr::Na(NaType::Real) => "NA_real_".to_string(),
1147        Expr::Na(NaType::Character) => "NA_character_".to_string(),
1148        Expr::Na(NaType::Complex) => "NA_complex_".to_string(),
1149        Expr::Inf => "Inf".to_string(),
1150        Expr::NaN => "NaN".to_string(),
1151        Expr::Bool(true) => "TRUE".to_string(),
1152        Expr::Bool(false) => "FALSE".to_string(),
1153        Expr::Integer(i) => format!("{}L", i),
1154        Expr::Double(d) => format_r_double(*d),
1155        Expr::Complex(d) => format!("{}i", d),
1156        Expr::String(s) => format!("\"{}\"", s.replace('\\', "\\\\").replace('"', "\\\"")),
1157        Expr::Symbol(s) => s.clone(),
1158        Expr::Dots => "...".to_string(),
1159        Expr::DotDot(n) => format!("..{}", n),
1160        Expr::UnaryOp { op, operand } => {
1161            let o = deparse_expr(operand);
1162            match op {
1163                UnaryOp::Neg => format!("-{}", o),
1164                UnaryOp::Pos => format!("+{}", o),
1165                UnaryOp::Not => format!("!{}", o),
1166                UnaryOp::Formula => format!("~{}", o),
1167            }
1168        }
1169        Expr::BinaryOp { op, lhs, rhs } => {
1170            let l = deparse_expr(lhs);
1171            let r = deparse_expr(rhs);
1172            let op_str = match op {
1173                BinaryOp::Add => "+",
1174                BinaryOp::Sub => "-",
1175                BinaryOp::Mul => "*",
1176                BinaryOp::Div => "/",
1177                BinaryOp::Pow => "^",
1178                BinaryOp::Mod => "%%",
1179                BinaryOp::IntDiv => "%/%",
1180                BinaryOp::Eq => "==",
1181                BinaryOp::Ne => "!=",
1182                BinaryOp::Lt => "<",
1183                BinaryOp::Gt => ">",
1184                BinaryOp::Le => "<=",
1185                BinaryOp::Ge => ">=",
1186                BinaryOp::And => "&",
1187                BinaryOp::AndScalar => "&&",
1188                BinaryOp::Or => "|",
1189                BinaryOp::OrScalar => "||",
1190                BinaryOp::Range => ":",
1191                BinaryOp::Pipe => "|>",
1192                BinaryOp::AssignPipe => "%<>%",
1193                BinaryOp::TeePipe => "%T>%",
1194                BinaryOp::ExpoPipe => "%$%",
1195                BinaryOp::Special(SpecialOp::In) => "%in%",
1196                BinaryOp::Special(SpecialOp::MatMul) => "%*%",
1197                BinaryOp::Special(SpecialOp::Kronecker) => "%x%",
1198                BinaryOp::Special(SpecialOp::Walrus) => ":=",
1199                BinaryOp::Special(SpecialOp::Other(ref name)) => name.as_str(),
1200                BinaryOp::Tilde => "~",
1201                BinaryOp::DoubleTilde => "~~",
1202            };
1203            format!("{} {} {}", l, op_str, r)
1204        }
1205        Expr::Assign { op, target, value } => {
1206            let t = deparse_expr(target);
1207            let v = deparse_expr(value);
1208            match op {
1209                AssignOp::LeftAssign => format!("{} <- {}", t, v),
1210                AssignOp::SuperAssign => format!("{} <<- {}", t, v),
1211                AssignOp::Equals => format!("{} = {}", t, v),
1212                AssignOp::RightAssign => format!("{} -> {}", v, t),
1213                AssignOp::RightSuperAssign => format!("{} ->> {}", v, t),
1214            }
1215        }
1216        Expr::Call { func, args, .. } => {
1217            let f = deparse_expr(func);
1218            format!("{}({})", f, args.iter().map(deparse_arg).join(", "))
1219        }
1220        Expr::Index { object, indices } => {
1221            let o = deparse_expr(object);
1222            format!("{}[{}]", o, indices.iter().map(deparse_arg).join(", "))
1223        }
1224        Expr::IndexDouble { object, indices } => {
1225            let o = deparse_expr(object);
1226            format!("{}[[{}]]", o, indices.iter().map(deparse_arg).join(", "))
1227        }
1228        Expr::Dollar { object, member } => format!("{}${}", deparse_expr(object), member),
1229        Expr::Slot { object, member } => format!("{}@{}", deparse_expr(object), member),
1230        Expr::NsGet { namespace, name } => format!("{}::{}", deparse_expr(namespace), name),
1231        Expr::NsGetInt { namespace, name } => format!("{}:::{}", deparse_expr(namespace), name),
1232        Expr::Formula { lhs, rhs } => {
1233            let l = lhs.as_ref().map(|e| deparse_expr(e)).unwrap_or_default();
1234            let r = rhs.as_ref().map(|e| deparse_expr(e)).unwrap_or_default();
1235            if l.is_empty() {
1236                format!("~{}", r)
1237            } else {
1238                format!("{} ~ {}", l, r)
1239            }
1240        }
1241        Expr::If {
1242            condition,
1243            then_body,
1244            else_body,
1245        } => {
1246            let c = deparse_expr(condition);
1247            let t = deparse_expr(then_body);
1248            match else_body {
1249                Some(e) => format!("if ({}) {} else {}", c, t, deparse_expr(e)),
1250                None => format!("if ({}) {}", c, t),
1251            }
1252        }
1253        Expr::For { var, iter, body } => {
1254            format!(
1255                "for ({} in {}) {}",
1256                var,
1257                deparse_expr(iter),
1258                deparse_expr(body)
1259            )
1260        }
1261        Expr::While { condition, body } => {
1262            format!("while ({}) {}", deparse_expr(condition), deparse_expr(body))
1263        }
1264        Expr::Repeat { body } => format!("repeat {}", deparse_expr(body)),
1265        Expr::Break => "break".to_string(),
1266        Expr::Next => "next".to_string(),
1267        Expr::Return(Some(e)) => format!("return({})", deparse_expr(e)),
1268        Expr::Return(None) => "return()".to_string(),
1269        Expr::Block(exprs) => {
1270            if exprs.len() == 1 {
1271                deparse_expr(&exprs[0])
1272            } else {
1273                format!(
1274                    "{{\n    {}\n}}",
1275                    exprs.iter().map(deparse_expr).join("\n    ")
1276                )
1277            }
1278        }
1279        Expr::Function { params, body } => {
1280            let p = params
1281                .iter()
1282                .map(|p| {
1283                    if p.is_dots {
1284                        "...".to_string()
1285                    } else if let Some(ref d) = p.default {
1286                        format!("{} = {}", p.name, deparse_expr(d))
1287                    } else {
1288                        p.name.clone()
1289                    }
1290                })
1291                .join(", ");
1292            format!("function({}) {}", p, deparse_expr(body))
1293        }
1294        Expr::Program(exprs) => exprs.iter().map(deparse_expr).join("\n"),
1295    }
1296}
1297
1298fn deparse_arg(arg: &Arg) -> String {
1299    match (&arg.name, &arg.value) {
1300        (Some(n), Some(v)) => format!("{} = {}", n, deparse_expr(v)),
1301        (None, Some(v)) => deparse_expr(v),
1302        (Some(n), None) => format!("{} = ", n),
1303        (None, None) => String::new(),
1304    }
1305}
1306
1307// endregion