1use std::collections::BTreeSet;
6
7use crate::interpreter::environment::Environment;
8use crate::interpreter::value::*;
9use crate::interpreter::BuiltinContext;
10use crate::parser::ast::{Arg, Expr};
11use itertools::Itertools;
12use minir_macros::pre_eval_builtin;
13
14#[derive(Clone)]
15struct DataFrameColumn {
16 name: String,
17 value: RValue,
18 row_count: usize,
19 row_names: Option<RowNames>,
20}
21
22type RowNames = Vec<Option<String>>;
23
24fn is_data_frame_control_arg(name: &str) -> bool {
25 matches!(
26 name,
27 "row.names" | "stringsAsFactors" | "check.rows" | "check.names" | "fix.empty.names"
28 )
29}
30
31fn sanitize_data_frame_name(source: &str) -> String {
32 let mut out = String::new();
33 for ch in source.chars() {
34 if ch.is_ascii_alphanumeric() || ch == '.' || ch == '_' {
35 out.push(ch);
36 } else {
37 out.push('.');
38 }
39 }
40
41 if out.is_empty() || out == "." {
42 out = "X".to_string();
43 }
44
45 if out
46 .chars()
47 .next()
48 .is_some_and(|ch| !(ch.is_ascii_alphabetic() || ch == '.'))
49 {
50 out.insert(0, 'X');
51 }
52
53 out
54}
55
56fn default_data_frame_name(expr: Option<&Expr>, index: usize) -> String {
57 expr.map(|expr| sanitize_data_frame_name(&deparse_expr(expr)))
58 .unwrap_or_else(|| format!("V{}", index))
59}
60
61fn row_names_to_strings(value: &RValue) -> Option<RowNames> {
62 match value {
63 RValue::Vector(rv) => match &rv.inner {
64 Vector::Character(values) => Some(values.to_vec()),
65 Vector::Integer(values) => Some(
66 values
67 .iter_opt()
68 .map(|v| v.map(|v| v.to_string()))
69 .collect(),
70 ),
71 Vector::Double(values) => {
72 Some(values.iter_opt().map(|v| v.map(format_r_double)).collect())
73 }
74 _ => None,
75 },
76 _ => None,
77 }
78}
79
80fn vector_names(rv: &RVector) -> Option<RowNames> {
81 rv.get_attr("names").and_then(row_names_to_strings)
82}
83
84fn expr_vector_names(expr: &Expr) -> Option<RowNames> {
85 let Expr::Call { func, args, .. } = expr else {
86 return None;
87 };
88 let Expr::Symbol(name) = func.as_ref() else {
89 return None;
90 };
91 if name != "c" || !args.iter().any(|arg| arg.name.is_some()) {
92 return None;
93 }
94 Some(args.iter().map(|arg| arg.name.clone()).collect())
95}
96
97fn matrix_dimnames(rv: &RVector) -> (Option<RowNames>, Option<RowNames>) {
98 let Some(RValue::List(dimnames)) = rv.get_attr("dimnames") else {
99 return (None, None);
100 };
101
102 let row_names = dimnames
103 .values
104 .first()
105 .and_then(|(_, value)| row_names_to_strings(value));
106 let col_names = dimnames
107 .values
108 .get(1)
109 .and_then(|(_, value)| row_names_to_strings(value));
110
111 (row_names, col_names)
112}
113
114fn factorize_character_vector(values: Vec<Option<String>>) -> Result<RValue, RError> {
115 let levels: Vec<String> = values.iter().flatten().unique().sorted().cloned().collect();
116
117 let codes: Vec<Option<i64>> = values
118 .iter()
119 .map(|value| match value {
120 Some(value) => levels
121 .iter()
122 .position(|level| level == value)
123 .map(|idx| i64::try_from(idx + 1))
124 .transpose(),
125 None => Ok(None),
126 })
127 .collect::<Result<_, _>>()?;
128
129 let mut rv = RVector::from(Vector::Integer(codes.into()));
130 rv.set_attr(
131 "levels".to_string(),
132 RValue::vec(Vector::Character(
133 levels.into_iter().map(Some).collect::<Vec<_>>().into(),
134 )),
135 );
136 rv.set_attr(
137 "class".to_string(),
138 RValue::vec(Vector::Character(vec![Some("factor".to_string())].into())),
139 );
140 Ok(RValue::Vector(rv))
141}
142
143fn maybe_factorize_strings(value: RValue, strings_as_factors: bool) -> Result<RValue, RError> {
144 if !strings_as_factors {
145 return Ok(value);
146 }
147
148 match value {
149 RValue::Vector(rv)
150 if matches!(rv.inner, Vector::Character(_)) && rv.get_attr("class").is_none() =>
151 {
152 let Vector::Character(values) = rv.inner else {
153 unreachable!();
154 };
155 factorize_character_vector(values.to_vec())
156 }
157 other => Ok(other),
158 }
159}
160
161fn strip_names_attr(value: &mut RValue) {
162 match value {
163 RValue::Vector(rv) => {
164 rv.attrs.as_mut().map(|attrs| attrs.shift_remove("names"));
165 }
166 RValue::List(list) => {
167 list.attrs.as_mut().map(|attrs| attrs.shift_remove("names"));
168 }
169 _ => {}
170 }
171}
172
173pub(super) fn recycle_value(value: &RValue, target_len: usize) -> Result<RValue, RError> {
174 match value {
175 RValue::Vector(rv) => {
176 let mut recycled = rv.clone();
177 recycled.inner = match &rv.inner {
178 Vector::Raw(values) => Vector::Raw(
179 (0..target_len)
180 .map(|idx| values[idx % values.len()])
181 .collect::<Vec<_>>(),
182 ),
183 Vector::Logical(values) => Vector::Logical(
184 (0..target_len)
185 .map(|idx| values[idx % values.len()])
186 .collect::<Vec<_>>()
187 .into(),
188 ),
189 Vector::Integer(values) => Vector::Integer(
190 (0..target_len)
191 .map(|idx| values.get_opt(idx % values.len()))
192 .collect::<Vec<_>>()
193 .into(),
194 ),
195 Vector::Double(values) => Vector::Double(
196 (0..target_len)
197 .map(|idx| values.get_opt(idx % values.len()))
198 .collect::<Vec<_>>()
199 .into(),
200 ),
201 Vector::Complex(values) => Vector::Complex(
202 (0..target_len)
203 .map(|idx| values[idx % values.len()])
204 .collect::<Vec<_>>()
205 .into(),
206 ),
207 Vector::Character(values) => Vector::Character(
208 (0..target_len)
209 .map(|idx| values[idx % values.len()].clone())
210 .collect::<Vec<_>>()
211 .into(),
212 ),
213 };
214 Ok(RValue::Vector(recycled))
215 }
216 RValue::List(list) => {
217 let mut recycled = list.clone();
218 recycled.values = (0..target_len)
219 .map(|idx| {
220 let (name, value) = &list.values[idx % list.values.len()];
221 (name.clone(), value.clone())
222 })
223 .collect();
224 Ok(RValue::List(recycled))
225 }
226 other if target_len == 1 => Ok(other.clone()),
227 other if other.length() == 1 => Ok(other.clone()),
228 other => Err(RError::other(format!(
229 "cannot recycle {} to {} rows",
230 other.type_name(),
231 target_len
232 ))),
233 }
234}
235
236fn matrix_columns(
237 rv: &RVector,
238 explicit_name: Option<&str>,
239) -> Result<Vec<DataFrameColumn>, RError> {
240 let Some(dims) = super::get_dim_ints(rv.get_attr("dim")) else {
241 return Ok(Vec::new());
242 };
243 if dims.len() < 2 {
244 return Ok(Vec::new());
245 }
246
247 let nrow = usize::try_from(dims[0].unwrap_or(0))?;
248 let ncol = usize::try_from(dims[1].unwrap_or(0))?;
249 let (row_names, col_names) = matrix_dimnames(rv);
250
251 let columns = match &rv.inner {
252 Vector::Raw(values) => (0..ncol)
253 .map(|col_idx| {
254 let start = col_idx * nrow;
255 DataFrameColumn {
256 name: match (
257 explicit_name,
258 col_names
259 .as_ref()
260 .and_then(|n| n.get(col_idx))
261 .cloned()
262 .flatten(),
263 ) {
264 (Some(prefix), Some(name)) => format!("{}.{}", prefix, name),
265 (Some(prefix), None) => format!("{}.{}", prefix, col_idx + 1),
266 (None, Some(name)) => name,
267 (None, None) => format!("X{}", col_idx + 1),
268 },
269 value: RValue::vec(Vector::Raw(values[start..start + nrow].to_vec())),
270 row_count: nrow,
271 row_names: row_names.clone(),
272 }
273 })
274 .collect(),
275 Vector::Logical(values) => (0..ncol)
276 .map(|col_idx| {
277 let start = col_idx * nrow;
278 DataFrameColumn {
279 name: match (
280 explicit_name,
281 col_names
282 .as_ref()
283 .and_then(|n| n.get(col_idx))
284 .cloned()
285 .flatten(),
286 ) {
287 (Some(prefix), Some(name)) => format!("{}.{}", prefix, name),
288 (Some(prefix), None) => format!("{}.{}", prefix, col_idx + 1),
289 (None, Some(name)) => name,
290 (None, None) => format!("X{}", col_idx + 1),
291 },
292 value: RValue::vec(Vector::Logical(
293 values[start..start + nrow].to_vec().into(),
294 )),
295 row_count: nrow,
296 row_names: row_names.clone(),
297 }
298 })
299 .collect(),
300 Vector::Integer(values) => (0..ncol)
301 .map(|col_idx| {
302 let start = col_idx * nrow;
303 DataFrameColumn {
304 name: match (
305 explicit_name,
306 col_names
307 .as_ref()
308 .and_then(|n| n.get(col_idx))
309 .cloned()
310 .flatten(),
311 ) {
312 (Some(prefix), Some(name)) => format!("{}.{}", prefix, name),
313 (Some(prefix), None) => format!("{}.{}", prefix, col_idx + 1),
314 (None, Some(name)) => name,
315 (None, None) => format!("X{}", col_idx + 1),
316 },
317 value: RValue::vec(Vector::Integer(values.slice(start, nrow))),
318 row_count: nrow,
319 row_names: row_names.clone(),
320 }
321 })
322 .collect(),
323 Vector::Double(values) => (0..ncol)
324 .map(|col_idx| {
325 let start = col_idx * nrow;
326 DataFrameColumn {
327 name: match (
328 explicit_name,
329 col_names
330 .as_ref()
331 .and_then(|n| n.get(col_idx))
332 .cloned()
333 .flatten(),
334 ) {
335 (Some(prefix), Some(name)) => format!("{}.{}", prefix, name),
336 (Some(prefix), None) => format!("{}.{}", prefix, col_idx + 1),
337 (None, Some(name)) => name,
338 (None, None) => format!("X{}", col_idx + 1),
339 },
340 value: RValue::vec(Vector::Double(values.slice(start, nrow))),
341 row_count: nrow,
342 row_names: row_names.clone(),
343 }
344 })
345 .collect(),
346 Vector::Complex(values) => (0..ncol)
347 .map(|col_idx| {
348 let start = col_idx * nrow;
349 DataFrameColumn {
350 name: match (
351 explicit_name,
352 col_names
353 .as_ref()
354 .and_then(|n| n.get(col_idx))
355 .cloned()
356 .flatten(),
357 ) {
358 (Some(prefix), Some(name)) => format!("{}.{}", prefix, name),
359 (Some(prefix), None) => format!("{}.{}", prefix, col_idx + 1),
360 (None, Some(name)) => name,
361 (None, None) => format!("X{}", col_idx + 1),
362 },
363 value: RValue::vec(Vector::Complex(
364 values[start..start + nrow].to_vec().into(),
365 )),
366 row_count: nrow,
367 row_names: row_names.clone(),
368 }
369 })
370 .collect(),
371 Vector::Character(values) => (0..ncol)
372 .map(|col_idx| {
373 let start = col_idx * nrow;
374 DataFrameColumn {
375 name: match (
376 explicit_name,
377 col_names
378 .as_ref()
379 .and_then(|n| n.get(col_idx))
380 .cloned()
381 .flatten(),
382 ) {
383 (Some(prefix), Some(name)) => format!("{}.{}", prefix, name),
384 (Some(prefix), None) => format!("{}.{}", prefix, col_idx + 1),
385 (None, Some(name)) => name,
386 (None, None) => format!("X{}", col_idx + 1),
387 },
388 value: RValue::vec(Vector::Character(
389 values[start..start + nrow].to_vec().into(),
390 )),
391 row_count: nrow,
392 row_names: row_names.clone(),
393 }
394 })
395 .collect(),
396 };
397
398 Ok(columns)
399}
400
401fn expand_data_frame_value(
402 value: &RValue,
403 explicit_name: Option<&str>,
404 default_name: &str,
405 fallback_row_names: Option<RowNames>,
406 strings_as_factors: bool,
407) -> Result<Vec<DataFrameColumn>, RError> {
408 match value {
409 RValue::Null => Ok(Vec::new()),
410 RValue::List(list) => {
411 let source_row_names = if get_class(value)
412 .iter()
413 .any(|class_name| class_name == "data.frame")
414 {
415 list.get_attr("row.names").and_then(row_names_to_strings)
416 } else {
417 None
418 };
419
420 let mut columns = Vec::new();
421 for (idx, (name, column_value)) in list.values.iter().enumerate() {
422 let column_name = match (explicit_name, name.as_deref()) {
423 (Some(prefix), Some(name)) => format!("{}.{}", prefix, name),
424 (Some(prefix), None) => format!("{}.{}", prefix, idx + 1),
425 (None, Some(name)) => name.to_string(),
426 (None, None) => format!("{}.{}", default_name, idx + 1),
427 };
428 let row_names = source_row_names.clone().or_else(|| match column_value {
429 RValue::Vector(rv) => vector_names(rv),
430 _ => None,
431 });
432 let value = maybe_factorize_strings(column_value.clone(), strings_as_factors)?;
433 columns.push(DataFrameColumn {
434 name: column_name,
435 row_count: column_value.length(),
436 value,
437 row_names,
438 });
439 }
440 Ok(columns)
441 }
442 RValue::Vector(rv) if super::get_dim_ints(rv.get_attr("dim")).is_some() => {
443 let mut columns = matrix_columns(rv, explicit_name)?;
444 for column in &mut columns {
445 column.value = maybe_factorize_strings(column.value.clone(), strings_as_factors)?;
446 }
447 Ok(columns)
448 }
449 _ => Ok(vec![DataFrameColumn {
450 name: explicit_name.unwrap_or(default_name).to_string(),
451 row_count: value.length(),
452 row_names: match value {
453 RValue::Vector(rv) => vector_names(rv).or(fallback_row_names),
454 _ => None,
455 },
456 value: maybe_factorize_strings(value.clone(), strings_as_factors)?,
457 }]),
458 }
459}
460
461fn automatic_row_names(count: usize) -> RValue {
462 RValue::vec(Vector::Integer(
463 (1..=i64::try_from(count).unwrap_or(0))
464 .map(Some)
465 .collect::<Vec<_>>()
466 .into(),
467 ))
468}
469
470#[pre_eval_builtin(name = "data.frame")]
477fn pre_eval_data_frame(
478 args: &[Arg],
479 env: &Environment,
480 context: &BuiltinContext,
481) -> Result<RValue, RError> {
482 let mut explicit_row_names = None;
483 let mut strings_as_factors = false;
484 let mut columns = Vec::new();
485 let mut unnamed_index = 0usize;
486
487 context.with_interpreter(|interp| {
488 for arg in args {
489 let Some(name) = arg.name.as_deref() else {
490 continue;
491 };
492 if !is_data_frame_control_arg(name) {
493 continue;
494 }
495 let Some(expr) = arg.value.as_ref() else {
496 continue;
497 };
498 let value = interp.eval_in(expr, env).map_err(RError::from)?;
499 match name {
500 "row.names" => explicit_row_names = Some(value),
501 "stringsAsFactors" => {
502 strings_as_factors = value
503 .as_vector()
504 .and_then(Vector::as_logical_scalar)
505 .unwrap_or(false);
506 }
507 _ => {}
508 }
509 }
510
511 let df_env = Environment::new_child(env);
516 for arg in args {
517 let Some(expr) = arg.value.as_ref() else {
518 continue;
519 };
520 if arg.name.as_deref().is_some_and(is_data_frame_control_arg) {
521 continue;
522 }
523
524 unnamed_index += 1;
525 let value = interp.eval_in(expr, &df_env).map_err(RError::from)?;
526
527 if let Some(col_name) = arg.name.as_deref() {
529 df_env.set(col_name.to_string(), value.clone());
530 }
531
532 let default_name = default_data_frame_name(
533 if arg.name.is_none() { Some(expr) } else { None },
534 unnamed_index,
535 );
536 columns.extend(expand_data_frame_value(
537 &value,
538 arg.name.as_deref(),
539 &default_name,
540 expr_vector_names(expr),
541 strings_as_factors,
542 )?);
543 }
544 Ok::<(), RError>(())
545 })?;
546
547 let mut lengths = BTreeSet::new();
548 for column in &columns {
549 lengths.insert(column.row_count);
550 }
551
552 let target_rows = match explicit_row_names.as_ref() {
553 Some(RValue::Null) => lengths.iter().copied().max().unwrap_or(0),
554 Some(value) => value.length(),
555 None => lengths.iter().copied().max().unwrap_or(0),
556 };
557
558 if let Some(row_names) = explicit_row_names.as_ref() {
559 if !matches!(row_names, RValue::Null) && !columns.is_empty() {
560 let valid = columns.iter().all(|column| column.row_count == target_rows);
561 if !valid {
562 return Err(RError::other(
563 "row names supplied are of the wrong length".to_string(),
564 ));
565 }
566 }
567 }
568
569 let invalid_lengths: Vec<usize> = columns
570 .iter()
571 .filter_map(|column| {
572 if column.row_count == target_rows {
573 None
574 } else if column.row_count == 0 || target_rows % column.row_count != 0 {
575 Some(column.row_count)
576 } else {
577 None
578 }
579 })
580 .collect();
581
582 if !invalid_lengths.is_empty() {
583 let mut all_lengths = lengths;
584 all_lengths.insert(target_rows);
585 return Err(RError::other(format!(
586 "arguments imply differing number of rows: {}",
587 all_lengths
588 .iter()
589 .map(|length| length.to_string())
590 .join(", ")
591 )));
592 }
593
594 let row_names_attr = match explicit_row_names {
595 Some(RValue::Null) => automatic_row_names(target_rows),
596 Some(value) => value,
597 None => columns
598 .iter()
599 .find(|column| column.row_count == target_rows)
600 .and_then(|column| column.row_names.clone())
601 .map(|names| RValue::vec(Vector::Character(names.into())))
602 .unwrap_or_else(|| automatic_row_names(target_rows)),
603 };
604
605 let mut output_columns = Vec::new();
606 for mut column in columns {
607 if column.row_count != target_rows {
608 column.value = recycle_value(&column.value, target_rows)?;
609 }
610 strip_names_attr(&mut column.value);
611 output_columns.push((Some(column.name), column.value));
612 }
613
614 let mut list = RList::new(output_columns);
615 let names: Vec<Option<String>> = list.values.iter().map(|(name, _)| name.clone()).collect();
616 list.set_attr(
617 "class".to_string(),
618 RValue::vec(Vector::Character(
619 vec![Some("data.frame".to_string())].into(),
620 )),
621 );
622 list.set_attr(
623 "names".to_string(),
624 RValue::vec(Vector::Character(names.into())),
625 );
626 list.set_attr("row.names".to_string(), row_names_attr);
627 Ok(RValue::List(list))
628}
629
630#[pre_eval_builtin(name = "tryCatch", min_args = 1)]
639fn pre_eval_try_catch(
640 args: &[Arg],
641 env: &Environment,
642 context: &BuiltinContext,
643) -> Result<RValue, RError> {
644 use crate::interpreter::ConditionHandler;
645
646 let expr = args
648 .iter()
649 .find(|a| a.name.is_none())
650 .or_else(|| args.iter().find(|a| a.name.as_deref() == Some("expr")))
651 .and_then(|a| a.value.as_ref());
652
653 let mut handlers: Vec<(String, RValue)> = Vec::new();
655 let mut finally_expr = None;
656 context.with_interpreter(|interp| {
657 for arg in args {
658 match arg.name.as_deref() {
659 Some("finally") => {
660 finally_expr = arg.value.clone();
661 }
662 Some("expr") => {} Some(class) => {
664 if let Some(ref val_expr) = arg.value {
665 let handler = interp.eval_in(val_expr, env)?;
666 handlers.push((class.to_string(), handler));
667 }
668 }
669 None => {} }
671 }
672 Ok::<(), RError>(())
673 })?;
674
675 let non_error_classes: Vec<String> = handlers
678 .iter()
679 .filter(|(c, _)| c != "error")
680 .map(|(c, _)| c.clone())
681 .collect();
682
683 let unwind_handlers: Vec<ConditionHandler> = non_error_classes
684 .iter()
685 .map(|class| ConditionHandler {
686 class: class.clone(),
687 handler: RValue::Function(RFunction::Builtin {
688 name: "tryCatch_unwinder".to_string(),
689 implementation: BuiltinImplementation::Eager(|args, _named| {
690 let condition = args.first().cloned().unwrap_or(RValue::Null);
692 let cond_classes = get_class(&condition);
693 let kind = if cond_classes.iter().any(|c| c == "warning") {
694 ConditionKind::Warning
695 } else if cond_classes.iter().any(|c| c == "message") {
696 ConditionKind::Message
697 } else {
698 ConditionKind::Error
699 };
700 Err(RError::Condition { condition, kind })
701 }),
702 min_args: 0,
703 max_args: None,
704 formals: &[],
705 }),
706 env: env.clone(),
707 })
708 .collect();
709
710 let result = context.with_interpreter(|interp| {
712 if !unwind_handlers.is_empty() {
713 interp.condition_handlers.borrow_mut().push(unwind_handlers);
714 }
715 let eval_result = match expr {
716 Some(e) => interp.eval_in(e, env).map_err(RError::from),
717 None => Ok(RValue::Null),
718 };
719 if !non_error_classes.is_empty() {
720 interp.condition_handlers.borrow_mut().pop();
721 }
722
723 match eval_result {
724 Ok(val) => Ok(val),
725 Err(RError::Condition { condition, kind }) => {
726 let cond_classes = get_class(&condition);
728 for (handler_class, handler) in &handlers {
729 if cond_classes.iter().any(|c| c == handler_class) {
730 return interp
731 .call_function(handler, std::slice::from_ref(&condition), &[], env)
732 .map_err(RError::from);
733 }
734 }
735 Err(RError::Condition { condition, kind })
737 }
738 Err(other) => {
739 if let Some((_, handler)) = handlers.iter().find(|(c, _)| c == "error") {
741 let err_msg = other.message();
742 let condition =
743 make_condition(&err_msg, &["simpleError", "error", "condition"]);
744 interp.eval_depth.set(0);
747 interp
748 .call_function(handler, &[condition], &[], env)
749 .map_err(RError::from)
750 } else {
751 Err(other)
752 }
753 }
754 }
755 });
756
757 if let Some(ref fin) = finally_expr {
759 context.with_interpreter(|interp| interp.eval_in(fin, env).map_err(RError::from))?;
760 }
761
762 result
763}
764
765#[pre_eval_builtin(name = "try", min_args = 1)]
770fn pre_eval_try(
771 args: &[Arg],
772 env: &Environment,
773 context: &BuiltinContext,
774) -> Result<RValue, RError> {
775 let expr = args
776 .iter()
777 .find(|a| a.name.is_none())
778 .and_then(|a| a.value.as_ref());
779 context.with_interpreter(|interp| match expr {
780 Some(e) => match interp.eval_in(e, env).map_err(RError::from) {
781 Ok(val) => Ok(val),
782 Err(err) => {
783 interp.eval_depth.set(0); let msg = format!("{}", err);
785 interp.write_stderr(&format!("Error in try : {}\n", msg));
786 Ok(RValue::vec(Vector::Character(vec![Some(msg)].into())))
787 }
788 },
789 None => Ok(RValue::Null),
790 })
791}
792
793#[pre_eval_builtin(name = "withCallingHandlers", min_args = 1)]
802fn pre_eval_with_calling_handlers(
803 args: &[Arg],
804 env: &Environment,
805 context: &BuiltinContext,
806) -> Result<RValue, RError> {
807 use crate::interpreter::ConditionHandler;
808
809 let expr = args
810 .iter()
811 .find(|a| a.name.is_none())
812 .or_else(|| args.iter().find(|a| a.name.as_deref() == Some("expr")))
813 .and_then(|a| a.value.as_ref());
814
815 let mut handler_set: Vec<ConditionHandler> = Vec::new();
817 context.with_interpreter(|interp| {
818 for arg in args {
819 match arg.name.as_deref() {
820 Some("expr") => {} Some(class) => {
822 if let Some(ref val_expr) = arg.value {
823 let handler = interp.eval_in(val_expr, env).map_err(RError::from)?;
824 handler_set.push(ConditionHandler {
825 class: class.to_string(),
826 handler,
827 env: env.clone(),
828 });
829 }
830 }
831 None => {} }
833 }
834 Ok::<(), RError>(())
835 })?;
836
837 context.with_interpreter(|interp| {
839 interp.condition_handlers.borrow_mut().push(handler_set);
840 let result = match expr {
841 Some(e) => interp.eval_in(e, env).map_err(RError::from),
842 None => Ok(RValue::Null),
843 };
844 interp.condition_handlers.borrow_mut().pop();
845 result
846 })
847}
848
849#[pre_eval_builtin(name = "suppressWarnings", min_args = 1)]
854fn pre_eval_suppress_warnings(
855 args: &[Arg],
856 env: &Environment,
857 context: &BuiltinContext,
858) -> Result<RValue, RError> {
859 use crate::interpreter::ConditionHandler;
860
861 let expr = args
862 .first()
863 .and_then(|a| a.value.as_ref())
864 .ok_or_else(|| RError::new(RErrorKind::Argument, "argument is missing".to_string()))?;
865
866 let muffle_handler = RValue::Function(RFunction::Builtin {
868 name: "suppressWarnings_handler".to_string(),
869 implementation: BuiltinImplementation::Eager(|_args, _named| {
870 Err(RError::other("muffleWarning".to_string()))
871 }),
872 min_args: 0,
873 max_args: None,
874 formals: &[],
875 });
876
877 let handler_set = vec![ConditionHandler {
878 class: "warning".to_string(),
879 handler: muffle_handler,
880 env: env.clone(),
881 }];
882
883 context.with_interpreter(|interp| {
884 interp.condition_handlers.borrow_mut().push(handler_set);
885 let result = interp.eval_in(expr, env).map_err(RError::from);
886 interp.condition_handlers.borrow_mut().pop();
887 result
888 })
889}
890
891#[pre_eval_builtin(name = "suppressMessages", min_args = 1)]
896fn pre_eval_suppress_messages(
897 args: &[Arg],
898 env: &Environment,
899 context: &BuiltinContext,
900) -> Result<RValue, RError> {
901 use crate::interpreter::ConditionHandler;
902
903 let expr = args
904 .first()
905 .and_then(|a| a.value.as_ref())
906 .ok_or_else(|| RError::new(RErrorKind::Argument, "argument is missing".to_string()))?;
907
908 let muffle_handler = RValue::Function(RFunction::Builtin {
909 name: "suppressMessages_handler".to_string(),
910 implementation: BuiltinImplementation::Eager(|_args, _named| {
911 Err(RError::other("muffleMessage".to_string()))
912 }),
913 min_args: 0,
914 max_args: None,
915 formals: &[],
916 });
917
918 let handler_set = vec![ConditionHandler {
919 class: "message".to_string(),
920 handler: muffle_handler,
921 env: env.clone(),
922 }];
923
924 context.with_interpreter(|interp| {
925 interp.condition_handlers.borrow_mut().push(handler_set);
926 let result = interp.eval_in(expr, env).map_err(RError::from);
927 interp.condition_handlers.borrow_mut().pop();
928 result
929 })
930}
931
932#[pre_eval_builtin(name = "on.exit")]
939fn pre_eval_on_exit(
940 args: &[Arg],
941 env: &Environment,
942 context: &BuiltinContext,
943) -> Result<RValue, RError> {
944 let expr = args.first().and_then(|a| a.value.as_ref()).cloned();
945
946 let (add, after) = context.with_interpreter(|interp| -> Result<(bool, bool), RError> {
948 let mut add = false;
949 let mut after = true;
950
951 for arg in args.iter().skip(1) {
952 match arg.name.as_deref() {
953 Some("add") => {
954 if let Some(ref val_expr) = arg.value {
955 let val = interp.eval_in(val_expr, env)?;
956 add = val
957 .as_vector()
958 .and_then(|v| v.as_logical_scalar())
959 .unwrap_or(false);
960 }
961 }
962 Some("after") => {
963 if let Some(ref val_expr) = arg.value {
964 let val = interp.eval_in(val_expr, env)?;
965 after = val
966 .as_vector()
967 .and_then(|v| v.as_logical_scalar())
968 .unwrap_or(true);
969 }
970 }
971 _ => {}
972 }
973 }
974
975 let has_named_add = args
977 .iter()
978 .skip(1)
979 .any(|a| a.name.as_deref() == Some("add"));
980 let has_named_after = args
981 .iter()
982 .skip(1)
983 .any(|a| a.name.as_deref() == Some("after"));
984
985 if !has_named_add {
986 if let Some(arg) = args.get(1) {
987 if arg.name.is_none() {
988 if let Some(ref val_expr) = arg.value {
989 let val = interp.eval_in(val_expr, env)?;
990 add = val
991 .as_vector()
992 .and_then(|v| v.as_logical_scalar())
993 .unwrap_or(false);
994 }
995 }
996 }
997 }
998
999 if !has_named_after {
1000 if let Some(arg) = args.get(2) {
1001 if arg.name.is_none() {
1002 if let Some(ref val_expr) = arg.value {
1003 let val = interp.eval_in(val_expr, env)?;
1004 after = val
1005 .as_vector()
1006 .and_then(|v| v.as_logical_scalar())
1007 .unwrap_or(true);
1008 }
1009 }
1010 }
1011 }
1012
1013 Ok((add, after))
1014 })?;
1015
1016 match expr {
1017 Some(e) => env.push_on_exit(e, add, after),
1018 None => {
1019 env.take_on_exit();
1021 }
1022 }
1023
1024 Ok(RValue::Null)
1025}
1026
1027#[pre_eval_builtin(name = "missing", min_args = 1)]
1032fn pre_eval_missing(
1033 args: &[Arg],
1034 _env: &Environment,
1035 context: &BuiltinContext,
1036) -> Result<RValue, RError> {
1037 let expr = args
1038 .first()
1039 .and_then(|a| a.value.as_ref())
1040 .ok_or_else(|| RError::other("'missing(x)' did not find an argument".to_string()))?;
1041
1042 let is_missing = context.with_interpreter(|interp| {
1043 let frame = interp
1044 .current_call_frame()
1045 .ok_or_else(|| RError::other("'missing(x)' did not find an argument".to_string()))?;
1046
1047 match expr {
1048 Expr::Symbol(name) => {
1049 if !frame.formal_args.contains(name) {
1050 return Err(RError::other(format!(
1051 "'missing({})' did not find an argument",
1052 name
1053 )));
1054 }
1055 Ok(!frame.supplied_args.contains(name))
1056 }
1057 Expr::Dots => {
1058 if !frame.formal_args.contains("...") {
1059 return Err(RError::other("'missing(...)' did not find an argument"));
1060 }
1061 let dots_len = match frame.env.get("...") {
1062 Some(RValue::List(list)) => list.values.len(),
1063 _ => 0,
1064 };
1065 Ok(dots_len == 0)
1066 }
1067 Expr::DotDot(n) => {
1068 if !frame.formal_args.contains("...") {
1069 return Err(RError::other("'missing(...)' did not find an argument"));
1070 }
1071 let dots_len = match frame.env.get("...") {
1072 Some(RValue::List(list)) => list.values.len(),
1073 _ => 0,
1074 };
1075 Ok(dots_len < usize::try_from(*n).unwrap_or(0))
1076 }
1077 _ => Err(RError::other("invalid use of 'missing'".to_string())),
1078 }
1079 })?;
1080
1081 Ok(RValue::vec(Vector::Logical(vec![Some(is_missing)].into())))
1082}
1083
1084#[pre_eval_builtin(name = "alist")]
1093fn pre_eval_alist(
1094 args: &[Arg],
1095 _env: &Environment,
1096 _context: &BuiltinContext,
1097) -> Result<RValue, RError> {
1098 let entries: Vec<(Option<String>, RValue)> = args
1099 .iter()
1100 .map(|arg| {
1101 let name = arg.name.clone();
1102 let value = match &arg.value {
1103 Some(expr) => RValue::Language(Language::new(expr.clone())),
1104 None => RValue::Language(Language::new(Expr::Symbol(String::new()))),
1105 };
1106 (name, value)
1107 })
1108 .collect();
1109 Ok(RValue::List(RList::new(entries)))
1110}
1111
1112#[pre_eval_builtin(name = "quote", min_args = 1)]
1117fn pre_eval_quote(
1118 args: &[Arg],
1119 _env: &Environment,
1120 _context: &BuiltinContext,
1121) -> Result<RValue, RError> {
1122 match args.first().and_then(|a| a.value.as_ref()) {
1123 Some(expr) => Ok(RValue::Language(Language::new(expr.clone()))),
1124 None => Ok(RValue::Null),
1125 }
1126}
1127
1128#[pre_eval_builtin(name = "substitute", min_args = 1)]
1133fn pre_eval_substitute(
1134 args: &[Arg],
1135 env: &Environment,
1136 _context: &BuiltinContext,
1137) -> Result<RValue, RError> {
1138 let expr = match args.first().and_then(|a| a.value.as_ref()) {
1139 Some(e) => e.clone(),
1140 None => return Ok(RValue::Null),
1141 };
1142 let substituted = substitute_expr(&expr, env);
1144 Ok(RValue::Language(Language::new(substituted)))
1145}
1146
1147fn substitute_expr(expr: &Expr, env: &Environment) -> Expr {
1154 match expr {
1155 Expr::Symbol(name) => {
1156 if let Some(val) = env.get(name) {
1160 if let RValue::Promise(p) = &val {
1161 return p.borrow().expr.clone();
1162 }
1163 if let Some(promise_expr) = env.get_promise_expr(name) {
1165 return promise_expr;
1166 }
1167 rvalue_to_expr(&val)
1168 } else {
1169 expr.clone()
1170 }
1171 }
1172 Expr::Call { func, args, .. } => Expr::Call {
1173 func: Box::new(substitute_expr(func, env)),
1174 span: None,
1175 args: args
1176 .iter()
1177 .map(|a| Arg {
1178 name: a.name.clone(),
1179 value: a.value.as_ref().map(|v| substitute_expr(v, env)),
1180 })
1181 .collect(),
1182 },
1183 Expr::BinaryOp { op, lhs, rhs } => Expr::BinaryOp {
1184 op: op.clone(),
1185 lhs: Box::new(substitute_expr(lhs, env)),
1186 rhs: Box::new(substitute_expr(rhs, env)),
1187 },
1188 Expr::UnaryOp { op, operand } => Expr::UnaryOp {
1189 op: *op,
1190 operand: Box::new(substitute_expr(operand, env)),
1191 },
1192 Expr::If {
1193 condition,
1194 then_body,
1195 else_body,
1196 } => Expr::If {
1197 condition: Box::new(substitute_expr(condition, env)),
1198 then_body: Box::new(substitute_expr(then_body, env)),
1199 else_body: else_body
1200 .as_ref()
1201 .map(|e| Box::new(substitute_expr(e, env))),
1202 },
1203 Expr::Block(exprs) => Expr::Block(exprs.iter().map(|e| substitute_expr(e, env)).collect()),
1204 _ => expr.clone(),
1206 }
1207}
1208
1209#[pre_eval_builtin(name = "evalq", min_args = 1)]
1218fn pre_eval_evalq(
1219 args: &[Arg],
1220 env: &Environment,
1221 context: &BuiltinContext,
1222) -> Result<RValue, RError> {
1223 let expr = match args.first().and_then(|a| a.value.as_ref()) {
1226 Some(e) => e,
1227 None => return Ok(RValue::Null),
1228 };
1229
1230 let eval_env = context.with_interpreter(|interp| -> Result<Option<Environment>, RError> {
1232 for arg in args.iter().skip(1) {
1234 if arg.name.as_deref() == Some("envir") {
1235 if let Some(ref val_expr) = arg.value {
1236 let val = interp.eval_in(val_expr, env)?;
1237 if let RValue::Environment(e) = val {
1238 return Ok(Some(e));
1239 }
1240 }
1241 }
1242 }
1243 if let Some(arg) = args.get(1) {
1245 if arg.name.is_none() {
1246 if let Some(ref val_expr) = arg.value {
1247 let val = interp.eval_in(val_expr, env)?;
1248 if let RValue::Environment(e) = val {
1249 return Ok(Some(e));
1250 }
1251 }
1252 }
1253 }
1254 Ok(None)
1255 })?;
1256
1257 let target_env = eval_env.unwrap_or_else(|| env.clone());
1258 context
1259 .with_interpreter(|interp| interp.eval_in(expr, &target_env))
1260 .map_err(RError::from)
1261}
1262
1263#[pre_eval_builtin(name = "bquote", min_args = 1)]
1268fn pre_eval_bquote(
1269 args: &[Arg],
1270 env: &Environment,
1271 context: &BuiltinContext,
1272) -> Result<RValue, RError> {
1273 let expr = match args.first().and_then(|a| a.value.as_ref()) {
1275 Some(e) => e.clone(),
1276 None => return Ok(RValue::Null),
1277 };
1278 let interp = context.interpreter();
1279 let result = bquote_expr(&expr, env, interp)?;
1280 Ok(RValue::Language(Language::new(result)))
1281}
1282
1283fn bquote_expr(
1285 expr: &Expr,
1286 env: &Environment,
1287 interp: &crate::interpreter::Interpreter,
1288) -> Result<Expr, RError> {
1289 match expr {
1290 Expr::Call { func, args, .. } => {
1292 if let Expr::Symbol(name) = func.as_ref() {
1293 if name == "." && args.len() == 1 {
1294 if let Some(ref inner) = args[0].value {
1296 let val = interp.eval_in(inner, env).map_err(RError::from)?;
1297 return Ok(rvalue_to_expr(&val));
1298 }
1299 }
1300 }
1301 let new_func = Box::new(bquote_expr(func, env, interp)?);
1303 let new_args: Result<Vec<Arg>, RError> = args
1304 .iter()
1305 .map(|a| {
1306 Ok(Arg {
1307 name: a.name.clone(),
1308 value: match &a.value {
1309 Some(v) => Some(bquote_expr(v, env, interp)?),
1310 None => None,
1311 },
1312 })
1313 })
1314 .collect();
1315 Ok(Expr::Call {
1316 func: new_func,
1317 args: new_args?,
1318 span: None,
1319 })
1320 }
1321 Expr::BinaryOp { op, lhs, rhs } => Ok(Expr::BinaryOp {
1322 op: op.clone(),
1323 lhs: Box::new(bquote_expr(lhs, env, interp)?),
1324 rhs: Box::new(bquote_expr(rhs, env, interp)?),
1325 }),
1326 Expr::UnaryOp { op, operand } => Ok(Expr::UnaryOp {
1327 op: *op,
1328 operand: Box::new(bquote_expr(operand, env, interp)?),
1329 }),
1330 Expr::If {
1331 condition,
1332 then_body,
1333 else_body,
1334 } => Ok(Expr::If {
1335 condition: Box::new(bquote_expr(condition, env, interp)?),
1336 then_body: Box::new(bquote_expr(then_body, env, interp)?),
1337 else_body: match else_body {
1338 Some(e) => Some(Box::new(bquote_expr(e, env, interp)?)),
1339 None => None,
1340 },
1341 }),
1342 Expr::Block(exprs) => {
1343 let new_exprs: Result<Vec<Expr>, RError> =
1344 exprs.iter().map(|e| bquote_expr(e, env, interp)).collect();
1345 Ok(Expr::Block(new_exprs?))
1346 }
1347 _ => Ok(expr.clone()),
1349 }
1350}
1351
1352#[pre_eval_builtin(name = "withVisible", min_args = 1)]
1357fn pre_eval_with_visible(
1358 args: &[Arg],
1359 env: &Environment,
1360 context: &BuiltinContext,
1361) -> Result<RValue, RError> {
1362 let expr = args
1363 .first()
1364 .and_then(|a| a.value.as_ref())
1365 .ok_or_else(|| RError::new(RErrorKind::Argument, "argument 'x' is missing".to_string()))?;
1366
1367 let value = context.with_interpreter(|interp| interp.eval_in(expr, env))?;
1368
1369 Ok(RValue::List(RList::new(vec![
1371 (Some("value".to_string()), value),
1372 (
1373 Some("visible".to_string()),
1374 RValue::vec(Vector::Logical(vec![Some(true)].into())),
1375 ),
1376 ])))
1377}
1378
1379#[pre_eval_builtin(name = "expression")]
1382fn pre_eval_expression(
1383 args: &[Arg],
1384 _env: &Environment,
1385 _context: &BuiltinContext,
1386) -> Result<RValue, RError> {
1387 let entries: Vec<(Option<String>, RValue)> = args
1388 .iter()
1389 .filter_map(|a| {
1390 a.value
1391 .as_ref()
1392 .map(|expr| (None, RValue::Language(Language::new(expr.clone()))))
1393 })
1394 .collect();
1395 let mut list = RList::new(entries);
1396 list.set_attr(
1397 "class".to_string(),
1398 RValue::vec(Vector::Character(
1399 vec![Some("expression".to_string())].into(),
1400 )),
1401 );
1402 Ok(RValue::List(list))
1403}
1404
1405#[pre_eval_builtin(name = "system.time", min_args = 1)]
1413fn pre_eval_system_time(
1414 args: &[Arg],
1415 env: &Environment,
1416 context: &BuiltinContext,
1417) -> Result<RValue, RError> {
1418 let expr = args
1419 .first()
1420 .and_then(|a| a.value.as_ref())
1421 .ok_or_else(|| RError::new(RErrorKind::Argument, "argument is missing".to_string()))?;
1422 let start = std::time::Instant::now();
1423 context.with_interpreter(|interp| interp.eval_in(expr, env))?;
1425 let elapsed = start.elapsed().as_secs_f64();
1426 Ok(super::system::make_proc_time(0.0, 0.0, elapsed))
1427}
1428
1429#[pre_eval_builtin(name = "local", min_args = 1)]
1439fn pre_eval_local(
1440 args: &[Arg],
1441 env: &Environment,
1442 context: &BuiltinContext,
1443) -> Result<RValue, RError> {
1444 let expr = match args.first().and_then(|a| a.value.as_ref()) {
1445 Some(e) => e,
1446 None => return Ok(RValue::Null),
1447 };
1448
1449 let parent_env = context.with_interpreter(|interp| -> Result<Option<Environment>, RError> {
1451 for arg in args.iter().skip(1) {
1452 if arg.name.as_deref() == Some("envir") {
1453 if let Some(ref val_expr) = arg.value {
1454 let val = interp.eval_in(val_expr, env)?;
1455 if let RValue::Environment(e) = val {
1456 return Ok(Some(e));
1457 }
1458 }
1459 }
1460 }
1461 if let Some(arg) = args.get(1) {
1462 if arg.name.is_none() {
1463 if let Some(ref val_expr) = arg.value {
1464 let val = interp.eval_in(val_expr, env)?;
1465 if let RValue::Environment(e) = val {
1466 return Ok(Some(e));
1467 }
1468 }
1469 }
1470 }
1471 Ok(None)
1472 })?;
1473
1474 let parent = parent_env.unwrap_or_else(|| env.clone());
1475 let local_env = Environment::new_child(&parent);
1476 context
1477 .with_interpreter(|interp| interp.eval_in(expr, &local_env))
1478 .map_err(RError::from)
1479}
1480
1481#[pre_eval_builtin(name = "rm", names = ["remove"])]
1492fn pre_eval_rm(
1493 args: &[Arg],
1494 env: &Environment,
1495 context: &BuiltinContext,
1496) -> Result<RValue, RError> {
1497 let mut names_to_remove: Vec<String> = Vec::new();
1498 let mut target_env: Option<Environment> = None;
1499
1500 for arg in args {
1501 match (&arg.name, &arg.value) {
1502 (Some(name), Some(expr)) if name == "envir" => {
1504 let val = context.with_interpreter(|interp| interp.eval_in(expr, env))?;
1505 match val {
1506 RValue::Environment(e) => target_env = Some(e),
1507 _ => {
1508 return Err(RError::new(
1509 RErrorKind::Argument,
1510 "invalid 'envir' argument".to_string(),
1511 ))
1512 }
1513 }
1514 }
1515 (Some(name), Some(expr)) if name == "list" => {
1517 let val = context.with_interpreter(|interp| interp.eval_in(expr, env))?;
1518 if let Some(Vector::Character(c)) = val.as_vector() {
1519 for s in c.iter().flatten() {
1520 names_to_remove.push(s.clone());
1521 }
1522 }
1523 }
1524 (None, Some(Expr::Symbol(name))) => {
1526 names_to_remove.push(name.clone());
1527 }
1528 (None, Some(Expr::String(s))) => {
1530 names_to_remove.push(s.clone());
1531 }
1532 (None, Some(expr)) => {
1534 let val = context.with_interpreter(|interp| interp.eval_in(expr, env))?;
1535 match val.as_vector() {
1536 Some(Vector::Character(c)) => {
1537 for s in c.iter().flatten() {
1538 names_to_remove.push(s.clone());
1539 }
1540 }
1541 _ => {
1542 return Err(RError::new(
1543 RErrorKind::Argument,
1544 format!(
1545 "rm() expects names of objects to remove, got {}",
1546 val.type_name()
1547 ),
1548 ));
1549 }
1550 }
1551 }
1552 _ => {}
1553 }
1554 }
1555
1556 let target = target_env.unwrap_or_else(|| env.clone());
1557 for name in &names_to_remove {
1558 target.remove(name);
1559 }
1560
1561 Ok(RValue::Null)
1562}
1563
1564fn rvalue_to_expr(val: &RValue) -> Expr {
1566 match val {
1567 RValue::Language(expr) => *expr.inner.clone(),
1568 RValue::Null => Expr::Null,
1569 RValue::Vector(rv) => match &rv.inner {
1570 Vector::Double(d) if d.len() == 1 => match d.get_opt(0) {
1571 Some(v) => Expr::Double(v),
1572 None => Expr::Na(crate::parser::ast::NaType::Real),
1573 },
1574 Vector::Integer(i) if i.len() == 1 => match i.get_opt(0) {
1575 Some(v) => Expr::Integer(v),
1576 None => Expr::Na(crate::parser::ast::NaType::Integer),
1577 },
1578 Vector::Logical(l) if l.len() == 1 => match l[0] {
1579 Some(v) => Expr::Bool(v),
1580 None => Expr::Na(crate::parser::ast::NaType::Logical),
1581 },
1582 Vector::Character(c) if c.len() == 1 => match &c[0] {
1583 Some(v) => Expr::String(v.clone()),
1584 None => Expr::Na(crate::parser::ast::NaType::Character),
1585 },
1586 _ => Expr::Symbol(format!("{}", val)),
1587 },
1588 _ => Expr::Symbol(format!("{}", val)),
1589 }
1590}
1591
1592fn extract_package_name_nse(
1597 args: &[Arg],
1598 env: &Environment,
1599 context: &BuiltinContext,
1600) -> Result<String, RError> {
1601 let first_arg = args.first().and_then(|a| a.value.as_ref()).ok_or_else(|| {
1602 RError::new(
1603 RErrorKind::Argument,
1604 "library/require requires a package name".to_string(),
1605 )
1606 })?;
1607
1608 let character_only = args
1612 .iter()
1613 .find(|a| a.name.as_deref() == Some("character.only"))
1614 .and_then(|a| a.value.as_ref())
1615 .map(|expr| match expr {
1616 Expr::Bool(b) => *b,
1617 other => context
1618 .with_interpreter(|interp| interp.eval_in(other, env))
1619 .ok()
1620 .and_then(|v| v.as_vector().and_then(|v| v.as_logical_scalar()))
1621 .unwrap_or(false),
1622 })
1623 .unwrap_or(false);
1624
1625 if character_only {
1626 let val = context
1627 .with_interpreter(|interp| interp.eval_in(first_arg, env).map_err(RError::from))?;
1628 return val
1629 .as_vector()
1630 .and_then(|v| v.as_character_scalar())
1631 .ok_or_else(|| {
1632 RError::new(
1633 RErrorKind::Argument,
1634 "invalid package name argument".to_string(),
1635 )
1636 });
1637 }
1638
1639 match first_arg {
1640 Expr::Symbol(name) => Ok(name.clone()),
1642 Expr::String(s) => Ok(s.clone()),
1644 other => {
1646 let val = context
1647 .with_interpreter(|interp| interp.eval_in(other, env).map_err(RError::from))?;
1648 val.as_vector()
1649 .and_then(|v| v.as_character_scalar())
1650 .ok_or_else(|| {
1651 RError::new(
1652 RErrorKind::Argument,
1653 "invalid package name argument".to_string(),
1654 )
1655 })
1656 }
1657 }
1658}
1659
1660#[pre_eval_builtin(name = "library", min_args = 1)]
1669fn pre_eval_library(
1670 args: &[Arg],
1671 env: &Environment,
1672 context: &BuiltinContext,
1673) -> Result<RValue, RError> {
1674 let pkg = extract_package_name_nse(args, env, context)?;
1675
1676 context.with_interpreter(|interp| {
1677 interp.load_namespace(&pkg)?;
1678 interp.attach_package(&pkg)?;
1679 Ok(RValue::vec(Vector::Character(vec![Some(pkg)].into())))
1680 })
1681}
1682
1683#[pre_eval_builtin(name = "require", min_args = 1)]
1692fn pre_eval_require(
1693 args: &[Arg],
1694 env: &Environment,
1695 context: &BuiltinContext,
1696) -> Result<RValue, RError> {
1697 let pkg = extract_package_name_nse(args, env, context)?;
1698
1699 let quietly = args.iter().any(|a| {
1701 a.name.as_deref() == Some("quietly")
1702 && a.value
1703 .as_ref()
1704 .is_some_and(|e| matches!(e, Expr::Bool(true)))
1705 });
1706
1707 let result = context.with_interpreter(|interp| match interp.load_namespace(&pkg) {
1708 Ok(_) => {
1709 interp.attach_package(&pkg)?;
1710 Ok(RValue::vec(Vector::Logical(vec![Some(true)].into())))
1711 }
1712 Err(_) => Ok(RValue::vec(Vector::Logical(vec![Some(false)].into()))),
1713 });
1714
1715 if let Ok(RValue::Vector(rv)) = &result {
1716 if rv.as_logical_scalar() == Some(false) && !quietly {
1717 context.write_err(&format!(
1718 "Warning message:\nthere is no package called '{}'\n",
1719 pkg
1720 ));
1721 }
1722 }
1723 result
1724}
1725
1726#[pre_eval_builtin(name = "switch")]
1740fn pre_eval_switch(
1741 args: &[Arg],
1742 env: &Environment,
1743 context: &BuiltinContext,
1744) -> Result<RValue, RError> {
1745 if args.is_empty() {
1746 return Err(RError::new(
1747 RErrorKind::Argument,
1748 "'EXPR' is missing".to_string(),
1749 ));
1750 }
1751
1752 let expr_val = context.with_interpreter(|interp| {
1754 args[0]
1755 .value
1756 .as_ref()
1757 .map(|e| interp.eval_in(e, env))
1758 .transpose()
1759 .map_err(RError::from)
1760 })?;
1761 let expr_val = expr_val.unwrap_or(RValue::Null);
1762
1763 let is_character =
1764 matches!(&expr_val, RValue::Vector(rv) if matches!(rv.inner, Vector::Character(_)));
1765
1766 if is_character {
1767 let s = expr_val
1768 .as_vector()
1769 .and_then(|v| v.as_character_scalar())
1770 .unwrap_or_default();
1771
1772 let named_args: Vec<_> = args[1..].iter().filter(|a| a.name.is_some()).collect();
1775 let default_arg = args[1..].iter().find(|a| a.name.is_none());
1776
1777 let mut found = false;
1778 for arg in &named_args {
1779 let name = arg.name.as_deref().unwrap_or("");
1780 if name == s {
1781 found = true;
1782 if let Some(ref expr) = arg.value {
1784 return context.with_interpreter(|interp| {
1785 interp.eval_in(expr, env).map_err(RError::from)
1786 });
1787 }
1788 } else if found {
1790 if let Some(ref expr) = arg.value {
1791 return context.with_interpreter(|interp| {
1792 interp.eval_in(expr, env).map_err(RError::from)
1793 });
1794 }
1795 }
1796 }
1797
1798 if let Some(arg) = default_arg {
1800 if let Some(ref expr) = arg.value {
1801 return context
1802 .with_interpreter(|interp| interp.eval_in(expr, env).map_err(RError::from));
1803 }
1804 }
1805
1806 Ok(RValue::Null)
1807 } else {
1808 let idx = expr_val.as_vector().and_then(|v| v.as_integer_scalar());
1810 match idx {
1811 Some(i) if i >= 1 => {
1812 let remaining: Vec<_> = args[1..].iter().collect();
1813 if let Some(arg) = remaining.get(usize::try_from(i - 1)?) {
1814 if let Some(ref expr) = arg.value {
1815 return context.with_interpreter(|interp| {
1816 interp.eval_in(expr, env).map_err(RError::from)
1817 });
1818 }
1819 }
1820 Ok(RValue::Null)
1821 }
1822 _ => Ok(RValue::Null),
1823 }
1824 }
1825}
1826
1827#[pre_eval_builtin(name = "delayedAssign", min_args = 2)]
1845fn pre_eval_delayed_assign(
1846 args: &[Arg],
1847 env: &Environment,
1848 context: &BuiltinContext,
1849) -> Result<RValue, RError> {
1850 let name = args.first().and_then(|a| a.value.as_ref()).ok_or_else(|| {
1852 RError::new(
1853 RErrorKind::Argument,
1854 "delayedAssign requires a variable name",
1855 )
1856 })?;
1857 let name = context.with_interpreter(|interp| interp.eval_in(name, env))?;
1858 let name = name
1859 .as_vector()
1860 .and_then(|v| v.as_character_scalar())
1861 .ok_or_else(|| {
1862 RError::new(
1863 RErrorKind::Argument,
1864 "first argument must be a character string",
1865 )
1866 })?;
1867
1868 let value_expr = args
1870 .get(1)
1871 .and_then(|a| a.value.as_ref())
1872 .cloned()
1873 .unwrap_or(Expr::Null);
1874
1875 let eval_env = if let Some(arg) = args.get(2).and_then(|a| a.value.as_ref()) {
1877 match context.with_interpreter(|interp| interp.eval_in(arg, env))? {
1878 RValue::Environment(e) => e,
1879 _ => env.clone(),
1880 }
1881 } else {
1882 env.clone()
1883 };
1884
1885 let assign_env = if let Some(arg) = args.get(3).and_then(|a| a.value.as_ref()) {
1887 match context.with_interpreter(|interp| interp.eval_in(arg, env))? {
1888 RValue::Environment(e) => e,
1889 _ => env.clone(),
1890 }
1891 } else {
1892 env.clone()
1893 };
1894
1895 let promise = RValue::Promise(std::rc::Rc::new(std::cell::RefCell::new(RPromise::new(
1897 value_expr, eval_env,
1898 ))));
1899 assign_env.set(name, promise);
1900
1901 Ok(RValue::Null)
1902}
1903
1904