1use super::sexp::{self, Sexp, SexpRec};
10use crate::interpreter::value::*;
11
12pub fn rvalue_to_sexp(val: &RValue) -> Sexp {
19 match val {
20 RValue::Null => sexp::mk_null(),
21 RValue::Vector(rv) => {
22 let s = vector_to_sexp(&rv.inner);
23 if let Some(attrs) = &rv.attrs {
24 apply_attrs_to_sexp(s, attrs);
25 }
26 s
27 }
28 RValue::List(list) => list_to_sexp(list),
29 RValue::Environment(env) => env_to_sexp(env),
30 RValue::Language(lang) => language_to_sexp(lang),
31 RValue::Function(_) | RValue::Promise(_) => sexp::mk_null(),
33 }
34}
35
36fn vector_to_sexp(vec: &Vector) -> Sexp {
37 match vec {
38 Vector::Double(d) => double_to_sexp(d),
39 Vector::Integer(i) => integer_to_sexp(i),
40 Vector::Logical(l) => logical_to_sexp(l),
41 Vector::Character(c) => character_to_sexp(c),
42 Vector::Raw(r) => raw_to_sexp(r),
43 Vector::Complex(c) => complex_to_sexp(c),
44 }
45}
46
47fn double_to_sexp(d: &Double) -> Sexp {
48 let len = d.len();
49 let s = sexp::alloc_vector(sexp::REALSXP, len as i32);
50 unsafe {
51 let ptr = sexp::real_ptr(s);
52 for i in 0..len {
53 *ptr.add(i) = d.get_opt(i).unwrap_or(sexp::NA_REAL);
54 }
55 }
56 s
57}
58
59fn integer_to_sexp(int: &Integer) -> Sexp {
60 let len = int.len();
61 let s = sexp::alloc_vector(sexp::INTSXP, len as i32);
62 unsafe {
63 let ptr = sexp::integer_ptr(s);
64 for i in 0..len {
65 *ptr.add(i) = match int.get_opt(i) {
66 Some(v) => i32::try_from(v).unwrap_or(sexp::NA_INTEGER),
67 None => sexp::NA_INTEGER,
68 };
69 }
70 }
71 s
72}
73
74fn logical_to_sexp(l: &Logical) -> Sexp {
75 let len = l.len();
76 let s = sexp::alloc_vector(sexp::LGLSXP, len as i32);
77 unsafe {
78 let ptr = sexp::logical_ptr(s);
79 for i in 0..len {
80 *ptr.add(i) = match l[i] {
81 Some(true) => 1,
82 Some(false) => 0,
83 None => sexp::NA_LOGICAL,
84 };
85 }
86 }
87 s
88}
89
90fn character_to_sexp(c: &Character) -> Sexp {
91 let len = c.len();
92 let s = sexp::alloc_vector(sexp::STRSXP, len as i32);
93 unsafe {
94 let elts = (*s).data as *mut Sexp;
95 for i in 0..len {
96 *elts.add(i) = match &c[i] {
97 Some(st) => sexp::mk_char(st),
98 None => sexp::mk_char("NA"), };
100 }
101 }
102 s
103}
104
105fn complex_to_sexp(c: &ComplexVec) -> Sexp {
106 let len = c.len();
107 let s = sexp::alloc_vector(sexp::CPLXSXP, len as i32);
108 unsafe {
109 let ptr = (*s).data as *mut [f64; 2];
111 for i in 0..len {
112 match c[i] {
113 Some(z) => {
114 (*ptr.add(i))[0] = z.re;
115 (*ptr.add(i))[1] = z.im;
116 }
117 None => {
118 (*ptr.add(i))[0] = sexp::NA_REAL;
119 (*ptr.add(i))[1] = sexp::NA_REAL;
120 }
121 }
122 }
123 }
124 s
125}
126
127fn raw_to_sexp(r: &[u8]) -> Sexp {
128 let len = r.len();
129 let s = sexp::alloc_vector(sexp::RAWSXP, len as i32);
130 if len > 0 {
131 unsafe {
132 std::ptr::copy_nonoverlapping(r.as_ptr(), (*s).data, len);
133 }
134 }
135 s
136}
137
138fn list_to_sexp(list: &RList) -> Sexp {
139 if let Some(attrs) = &list.attrs {
141 if let Some(ptr_val) = attrs.get(".sexp_ptr") {
142 if let Some(addr) = ptr_val.as_vector().and_then(|v| v.as_double_scalar()) {
143 return addr as usize as Sexp;
145 }
146 }
147 }
148
149 let len = list.values.len();
150 let s = sexp::alloc_vector(sexp::VECSXP, len as i32);
151 unsafe {
152 let elts = (*s).data as *mut Sexp;
153 for (i, (_, val)) in list.values.iter().enumerate() {
154 *elts.add(i) = rvalue_to_sexp(val);
155 }
156 }
157
158 let has_names = list.values.iter().any(|(n, _)| n.is_some());
160 if has_names {
161 let names: Vec<Option<String>> = list.values.iter().map(|(n, _)| n.clone()).collect();
162 let names_sexp = character_to_sexp(&Character(names));
163 super::runtime::Rf_setAttrib(s, unsafe { super::runtime::R_NamesSymbol }, names_sexp);
164 }
165
166 if let Some(attrs) = &list.attrs {
168 apply_attrs_to_sexp(s, attrs);
169 }
170 s
171}
172
173fn language_to_sexp(lang: &crate::interpreter::value::Language) -> Sexp {
178 use crate::parser::ast::Expr;
179
180 match lang.inner.as_ref() {
181 Expr::Call { func, args, .. } => {
182 let func_sexp = expr_to_sexp(func);
184 let mut arg_list = unsafe { super::runtime::R_NilValue };
186 for arg in args.iter().rev() {
187 let val_sexp = match &arg.value {
188 Some(expr) => expr_to_sexp(expr),
189 None => unsafe { super::runtime::R_NilValue },
190 };
191 let node = super::runtime::Rf_cons(val_sexp, arg_list);
192 if let Some(name) = &arg.name {
194 let tag = super::runtime::Rf_install(
195 std::ffi::CString::new(name.as_str())
196 .unwrap_or_default()
197 .as_ptr(),
198 );
199 unsafe {
200 let pd = (*node).data as *mut sexp::PairlistData;
201 if !pd.is_null() {
202 (*pd).tag = tag;
203 }
204 }
205 }
206 arg_list = node;
207 }
208 super::runtime::Rf_lcons(func_sexp, arg_list)
209 }
210 _ => {
212 let idx = super::runtime::stash_rvalue(RValue::Language(lang.clone()));
213 let s = sexp::alloc_vector(sexp::LANGSXP, 0);
214 unsafe {
215 (*s).length = -1; (*s).data = idx as *mut u8;
217 }
218 super::runtime::track(s);
219 s
220 }
221 }
222}
223
224fn expr_to_sexp(expr: &crate::parser::ast::Expr) -> Sexp {
226 use crate::parser::ast::Expr;
227 match expr {
228 Expr::Symbol(name) => super::runtime::Rf_install(
229 std::ffi::CString::new(name.as_str())
230 .unwrap_or_default()
231 .as_ptr(),
232 ),
233 Expr::Null => unsafe { super::runtime::R_NilValue },
234 Expr::Bool(true) => super::runtime::Rf_ScalarLogical(1),
235 Expr::Bool(false) => super::runtime::Rf_ScalarLogical(0),
236 Expr::Integer(i) => super::runtime::Rf_ScalarInteger(*i as std::os::raw::c_int),
237 Expr::Double(d) => super::runtime::Rf_ScalarReal(*d),
238 Expr::String(s) => super::runtime::Rf_mkString(
239 std::ffi::CString::new(s.as_str())
240 .unwrap_or_default()
241 .as_ptr(),
242 ),
243 Expr::Call { .. } => {
244 let lang = crate::interpreter::value::Language::new(expr.clone());
246 language_to_sexp(&lang)
247 }
248 _ => unsafe { super::runtime::R_NilValue },
249 }
250}
251
252fn env_to_sexp(env: &crate::interpreter::environment::Environment) -> Sexp {
258 let boxed = Box::new(env.clone());
259 let ptr = Box::into_raw(boxed);
260 unsafe {
261 let s = sexp::alloc_vector(sexp::ENVSXP, 0);
262 (*s).data = ptr as *mut u8;
263 s
264 }
265}
266
267pub unsafe fn env_from_sexp(s: Sexp) -> Option<crate::interpreter::environment::Environment> {
272 if s.is_null() {
273 return None;
274 }
275 unsafe {
276 if (*s).stype != sexp::ENVSXP || (*s).data.is_null() {
277 return None;
278 }
279 let env_ptr = (*s).data as *const crate::interpreter::environment::Environment;
280 Some((*env_ptr).clone())
281 }
282}
283
284fn apply_attrs_to_sexp(s: Sexp, attrs: &indexmap::IndexMap<String, RValue>) {
286 use super::runtime;
287 for (key, val) in attrs {
288 let attr_sexp = rvalue_to_sexp(val);
289 let name_sym = match key.as_str() {
290 "dim" => unsafe { runtime::R_DimSymbol },
291 "names" => unsafe { runtime::R_NamesSymbol },
292 "dimnames" => unsafe { runtime::R_DimNamesSymbol },
293 "class" => unsafe { runtime::R_ClassSymbol },
294 _ => runtime::Rf_install(
295 std::ffi::CString::new(key.as_str())
296 .unwrap_or_default()
297 .as_ptr(),
298 ),
299 };
300 runtime::Rf_setAttrib(s, name_sym, attr_sexp);
301 }
302}
303
304pub unsafe fn sexp_to_rvalue(s: Sexp) -> RValue {
314 if s.is_null() {
315 return RValue::Null;
316 }
317 let rec: &SexpRec = &*s;
318 let mut result = match rec.stype {
319 sexp::NILSXP => return RValue::Null,
320 sexp::REALSXP => sexp_real_to_rvalue(rec),
321 sexp::INTSXP => sexp_int_to_rvalue(rec),
322 sexp::LGLSXP => sexp_lgl_to_rvalue(rec),
323 sexp::STRSXP => sexp_str_to_rvalue(rec),
324 sexp::VECSXP => sexp_vec_to_rvalue(rec),
325 sexp::RAWSXP => sexp_raw_to_rvalue(rec),
326 sexp::CPLXSXP => sexp_complex_to_rvalue(rec),
327 sexp::CHARSXP => {
328 let st = sexp::char_data(s);
329 RValue::vec(Vector::Character(vec![Some(st.to_string())].into()))
330 }
331 sexp::ENVSXP => {
332 if let Some(env) = env_from_sexp(s) {
333 return RValue::Environment(env);
334 }
335 return RValue::Null;
336 }
337 22 => {
341 let addr = s as usize;
343 let mut list = RList::new(vec![]);
344 let mut attrs = indexmap::IndexMap::new();
345 attrs.insert(
346 ".sexp_ptr".to_string(),
347 RValue::vec(Vector::Double(vec![Some(addr as f64)].into())),
348 );
349 attrs.insert(
350 "class".to_string(),
351 RValue::vec(Vector::Character(
352 vec![Some("externalptr".to_string())].into(),
353 )),
354 );
355 list.attrs = Some(Box::new(attrs));
356 return RValue::List(list);
357 }
358 _ => return RValue::Null,
359 };
360
361 if !rec.attrib.is_null() {
363 read_sexp_attrs(rec.attrib, &mut result);
364 }
365
366 result
367}
368
369unsafe fn read_sexp_attrs(mut attr: Sexp, result: &mut RValue) {
371 while !attr.is_null() && (*attr).stype == sexp::LISTSXP {
373 let pairlist_data = (*attr).data as *const sexp::PairlistData;
374 if pairlist_data.is_null() {
375 break;
376 }
377 let tag = (*pairlist_data).tag;
378 let car = (*pairlist_data).car;
379 let cdr = (*pairlist_data).cdr;
380
381 if !tag.is_null() && (*tag).stype == sexp::SYMSXP && !(*tag).data.is_null() {
383 let name = sexp::char_data(tag); let value = sexp_to_rvalue(car);
385
386 match result {
387 RValue::Vector(rv) => {
388 rv.set_attr(name.to_string(), value);
389 }
390 RValue::List(list) => {
391 list.attrs
392 .get_or_insert_with(|| Box::new(indexmap::IndexMap::new()))
393 .insert(name.to_string(), value);
394 }
395 _ => {}
396 }
397 }
398
399 attr = cdr;
400 }
401}
402
403unsafe fn sexp_real_to_rvalue(rec: &SexpRec) -> RValue {
404 let len = rec.length.max(0) as usize;
405 let ptr = rec.data as *const f64;
406 let mut vals = Vec::with_capacity(len);
407 for i in 0..len {
408 let v = *ptr.add(i);
409 if sexp::is_na_real(v) {
410 vals.push(None);
411 } else {
412 vals.push(Some(v));
413 }
414 }
415 RValue::vec(Vector::Double(vals.into()))
416}
417
418unsafe fn sexp_int_to_rvalue(rec: &SexpRec) -> RValue {
419 let len = rec.length.max(0) as usize;
420 let ptr = rec.data as *const i32;
421 let mut vals = Vec::with_capacity(len);
422 for i in 0..len {
423 let v = *ptr.add(i);
424 if v == sexp::NA_INTEGER {
425 vals.push(None);
426 } else {
427 vals.push(Some(i64::from(v)));
428 }
429 }
430 RValue::vec(Vector::Integer(vals.into()))
431}
432
433unsafe fn sexp_lgl_to_rvalue(rec: &SexpRec) -> RValue {
434 let len = rec.length.max(0) as usize;
435 let ptr = rec.data as *const i32;
436 let mut vals = Vec::with_capacity(len);
437 for i in 0..len {
438 let v = *ptr.add(i);
439 if v == sexp::NA_LOGICAL {
440 vals.push(None);
441 } else {
442 vals.push(Some(v != 0));
443 }
444 }
445 RValue::vec(Vector::Logical(vals.into()))
446}
447
448unsafe fn sexp_str_to_rvalue(rec: &SexpRec) -> RValue {
449 let len = rec.length.max(0) as usize;
450 let elts = rec.data as *const Sexp;
451 let mut vals = Vec::with_capacity(len);
452 for i in 0..len {
453 let elt = *elts.add(i);
454 if elt.is_null() {
455 vals.push(None);
456 } else {
457 vals.push(Some(sexp::char_data(elt).to_string()));
458 }
459 }
460 RValue::vec(Vector::Character(vals.into()))
461}
462
463unsafe fn sexp_vec_to_rvalue(rec: &SexpRec) -> RValue {
464 let len = rec.length.max(0) as usize;
465 let elts = rec.data as *const Sexp;
466 let mut vals = Vec::with_capacity(len);
467 for i in 0..len {
468 let elt = *elts.add(i);
469 vals.push((None, sexp_to_rvalue(elt)));
470 }
471 RValue::List(RList::new(vals))
472}
473
474unsafe fn sexp_raw_to_rvalue(rec: &SexpRec) -> RValue {
475 let len = rec.length.max(0) as usize;
476 let mut buf = vec![0u8; len];
477 if len > 0 {
478 std::ptr::copy_nonoverlapping(rec.data, buf.as_mut_ptr(), len);
479 }
480 RValue::vec(Vector::Raw(buf))
481}
482
483unsafe fn sexp_complex_to_rvalue(rec: &SexpRec) -> RValue {
484 let len = rec.length.max(0) as usize;
485 let ptr = rec.data as *const [f64; 2]; let mut vals = Vec::with_capacity(len);
487 for i in 0..len {
488 let pair = &*ptr.add(i);
489 if sexp::is_na_real(pair[0]) {
490 vals.push(None);
491 } else {
492 vals.push(Some(num_complex::Complex64::new(pair[0], pair[1])));
493 }
494 }
495 RValue::vec(Vector::Complex(vals.into()))
496}
497
498