1use std::collections::HashMap;
6use std::collections::{HashSet, VecDeque};
7use std::fmt::Write as FmtWrite;
8
9#[derive(Debug, Clone, PartialEq)]
11pub struct RFunction {
12 pub name: String,
14 pub formals: Vec<RFormal>,
16 pub body: Vec<RStmt>,
18 pub is_generic: bool,
20 pub s3_methods: Vec<(String, RFunction)>,
22 pub doc: Option<String>,
24}
25impl RFunction {
26 pub fn new(name: &str, formals: Vec<RFormal>, body: Vec<RStmt>) -> Self {
27 RFunction {
28 name: name.to_string(),
29 formals,
30 body,
31 is_generic: false,
32 s3_methods: Vec::new(),
33 doc: None,
34 }
35 }
36 pub fn generic(mut self) -> Self {
37 self.is_generic = true;
38 self
39 }
40 pub fn with_doc(mut self, doc: &str) -> Self {
41 self.doc = Some(doc.to_string());
42 self
43 }
44 pub fn add_s3_method(&mut self, class: &str, method: RFunction) {
45 self.s3_methods.push((class.to_string(), method));
46 }
47}
48#[allow(dead_code)]
49#[derive(Debug, Clone)]
50pub struct RLangDepGraph {
51 pub(super) nodes: Vec<u32>,
52 pub(super) edges: Vec<(u32, u32)>,
53}
54impl RLangDepGraph {
55 #[allow(dead_code)]
56 pub fn new() -> Self {
57 RLangDepGraph {
58 nodes: Vec::new(),
59 edges: Vec::new(),
60 }
61 }
62 #[allow(dead_code)]
63 pub fn add_node(&mut self, id: u32) {
64 if !self.nodes.contains(&id) {
65 self.nodes.push(id);
66 }
67 }
68 #[allow(dead_code)]
69 pub fn add_dep(&mut self, dep: u32, dependent: u32) {
70 self.add_node(dep);
71 self.add_node(dependent);
72 self.edges.push((dep, dependent));
73 }
74 #[allow(dead_code)]
75 pub fn dependents_of(&self, node: u32) -> Vec<u32> {
76 self.edges
77 .iter()
78 .filter(|(d, _)| *d == node)
79 .map(|(_, dep)| *dep)
80 .collect()
81 }
82 #[allow(dead_code)]
83 pub fn dependencies_of(&self, node: u32) -> Vec<u32> {
84 self.edges
85 .iter()
86 .filter(|(_, dep)| *dep == node)
87 .map(|(d, _)| *d)
88 .collect()
89 }
90 #[allow(dead_code)]
91 pub fn topological_sort(&self) -> Vec<u32> {
92 let mut in_degree: std::collections::HashMap<u32, u32> = std::collections::HashMap::new();
93 for &n in &self.nodes {
94 in_degree.insert(n, 0);
95 }
96 for (_, dep) in &self.edges {
97 *in_degree.entry(*dep).or_insert(0) += 1;
98 }
99 let mut queue: std::collections::VecDeque<u32> = self
100 .nodes
101 .iter()
102 .filter(|&&n| in_degree[&n] == 0)
103 .copied()
104 .collect();
105 let mut result = Vec::new();
106 while let Some(node) = queue.pop_front() {
107 result.push(node);
108 for dep in self.dependents_of(node) {
109 let cnt = in_degree.entry(dep).or_insert(0);
110 *cnt = cnt.saturating_sub(1);
111 if *cnt == 0 {
112 queue.push_back(dep);
113 }
114 }
115 }
116 result
117 }
118 #[allow(dead_code)]
119 pub fn has_cycle(&self) -> bool {
120 self.topological_sort().len() < self.nodes.len()
121 }
122}
123#[derive(Debug, Clone, PartialEq, Eq)]
125pub enum ApplyVariant {
126 Sapply,
127 Vapply,
128 Lapply,
129 Apply,
130 Tapply,
131 Mapply,
132}
133#[allow(dead_code)]
134#[derive(Debug, Clone)]
135pub struct RLangDominatorTree {
136 pub idom: Vec<Option<u32>>,
137 pub dom_children: Vec<Vec<u32>>,
138 pub dom_depth: Vec<u32>,
139}
140impl RLangDominatorTree {
141 #[allow(dead_code)]
142 pub fn new(size: usize) -> Self {
143 RLangDominatorTree {
144 idom: vec![None; size],
145 dom_children: vec![Vec::new(); size],
146 dom_depth: vec![0; size],
147 }
148 }
149 #[allow(dead_code)]
150 pub fn set_idom(&mut self, node: usize, idom: u32) {
151 self.idom[node] = Some(idom);
152 }
153 #[allow(dead_code)]
154 pub fn dominates(&self, a: usize, b: usize) -> bool {
155 if a == b {
156 return true;
157 }
158 let mut cur = b;
159 loop {
160 match self.idom[cur] {
161 Some(parent) if parent as usize == a => return true,
162 Some(parent) if parent as usize == cur => return false,
163 Some(parent) => cur = parent as usize,
164 None => return false,
165 }
166 }
167 }
168 #[allow(dead_code)]
169 pub fn depth(&self, node: usize) -> u32 {
170 self.dom_depth.get(node).copied().unwrap_or(0)
171 }
172}
173#[derive(Debug, Clone, PartialEq)]
175pub struct RFormal {
176 pub name: String,
177 pub default: Option<RExpr>,
178}
179impl RFormal {
180 pub fn required(name: &str) -> Self {
181 RFormal {
182 name: name.to_string(),
183 default: None,
184 }
185 }
186 pub fn with_default(name: &str, default: RExpr) -> Self {
187 RFormal {
188 name: name.to_string(),
189 default: Some(default),
190 }
191 }
192}
193#[derive(Debug, Clone)]
195pub struct RFile {
196 pub imports: Vec<String>,
198 pub functions: Vec<RFunction>,
200 pub scripts: Vec<RStmt>,
202 pub data_objects: Vec<RDataObject>,
204 pub header_comment: Option<String>,
206 pub shebang: Option<String>,
208}
209impl RFile {
210 pub fn new() -> Self {
211 RFile {
212 imports: Vec::new(),
213 functions: Vec::new(),
214 scripts: Vec::new(),
215 data_objects: Vec::new(),
216 header_comment: None,
217 shebang: None,
218 }
219 }
220 pub fn with_header(mut self, comment: &str) -> Self {
221 self.header_comment = Some(comment.to_string());
222 self
223 }
224 pub fn add_import(&mut self, pkg: &str) {
225 if !self.imports.contains(&pkg.to_string()) {
226 self.imports.push(pkg.to_string());
227 }
228 }
229 pub fn add_function(&mut self, fun: RFunction) {
230 self.functions.push(fun);
231 }
232 pub fn add_script_stmt(&mut self, stmt: RStmt) {
233 self.scripts.push(stmt);
234 }
235 pub fn add_data(&mut self, obj: RDataObject) {
236 self.data_objects.push(obj);
237 }
238}
239#[derive(Debug, Clone, PartialEq)]
241pub enum RLiteral {
242 Integer(i64),
244 Numeric(f64),
246 Logical(bool),
248 Character(String),
250 Complex(f64, f64),
252 Null,
254 Na,
256 NaInteger,
258 NaReal,
260 NaCharacter,
262 NaComplex,
264 Inf,
266 NaN,
268}
269#[derive(Debug, Clone, PartialEq, Eq)]
271pub enum RAssignOp {
272 LeftArrow,
274 SuperArrow,
276 Equals,
278 RightArrow,
280}
281#[derive(Debug, Clone, PartialEq)]
283pub enum RType {
284 Numeric,
286 Integer,
288 Logical,
290 Character,
292 Complex,
294 Raw,
296 List,
298 DataFrame,
300 Matrix(Box<RType>),
302 Array(Box<RType>, Vec<usize>),
304 Function,
306 Environment,
308 S3(String),
310 S4(String),
312 R5(String),
314 R6(String),
316 Null,
318 Na,
320 Vector(Box<RType>),
322 Named(String),
324}
325#[allow(dead_code)]
326#[derive(Debug, Clone, Default)]
327pub struct RLangPassStats {
328 pub total_runs: u32,
329 pub successful_runs: u32,
330 pub total_changes: u64,
331 pub time_ms: u64,
332 pub iterations_used: u32,
333}
334impl RLangPassStats {
335 #[allow(dead_code)]
336 pub fn new() -> Self {
337 Self::default()
338 }
339 #[allow(dead_code)]
340 pub fn record_run(&mut self, changes: u64, time_ms: u64, iterations: u32) {
341 self.total_runs += 1;
342 self.successful_runs += 1;
343 self.total_changes += changes;
344 self.time_ms += time_ms;
345 self.iterations_used = iterations;
346 }
347 #[allow(dead_code)]
348 pub fn average_changes_per_run(&self) -> f64 {
349 if self.total_runs == 0 {
350 return 0.0;
351 }
352 self.total_changes as f64 / self.total_runs as f64
353 }
354 #[allow(dead_code)]
355 pub fn success_rate(&self) -> f64 {
356 if self.total_runs == 0 {
357 return 0.0;
358 }
359 self.successful_runs as f64 / self.total_runs as f64
360 }
361 #[allow(dead_code)]
362 pub fn format_summary(&self) -> String {
363 format!(
364 "Runs: {}/{}, Changes: {}, Time: {}ms",
365 self.successful_runs, self.total_runs, self.total_changes, self.time_ms
366 )
367 }
368}
369#[allow(dead_code)]
371#[derive(Debug, Clone)]
372pub struct RLangExtDomTree {
373 pub(super) idom: Vec<Option<usize>>,
374 pub(super) children: Vec<Vec<usize>>,
375 pub(super) depth: Vec<usize>,
376}
377impl RLangExtDomTree {
378 #[allow(dead_code)]
379 pub fn new(n: usize) -> Self {
380 Self {
381 idom: vec![None; n],
382 children: vec![Vec::new(); n],
383 depth: vec![0; n],
384 }
385 }
386 #[allow(dead_code)]
387 pub fn set_idom(&mut self, node: usize, dom: usize) {
388 if node < self.idom.len() {
389 self.idom[node] = Some(dom);
390 if dom < self.children.len() {
391 self.children[dom].push(node);
392 }
393 self.depth[node] = if dom < self.depth.len() {
394 self.depth[dom] + 1
395 } else {
396 1
397 };
398 }
399 }
400 #[allow(dead_code)]
401 pub fn dominates(&self, a: usize, mut b: usize) -> bool {
402 if a == b {
403 return true;
404 }
405 let n = self.idom.len();
406 for _ in 0..n {
407 match self.idom.get(b).copied().flatten() {
408 None => return false,
409 Some(p) if p == a => return true,
410 Some(p) if p == b => return false,
411 Some(p) => b = p,
412 }
413 }
414 false
415 }
416 #[allow(dead_code)]
417 pub fn children_of(&self, n: usize) -> &[usize] {
418 self.children.get(n).map(|v| v.as_slice()).unwrap_or(&[])
419 }
420 #[allow(dead_code)]
421 pub fn depth_of(&self, n: usize) -> usize {
422 self.depth.get(n).copied().unwrap_or(0)
423 }
424 #[allow(dead_code)]
425 pub fn lca(&self, mut a: usize, mut b: usize) -> usize {
426 let n = self.idom.len();
427 for _ in 0..(2 * n) {
428 if a == b {
429 return a;
430 }
431 if self.depth_of(a) > self.depth_of(b) {
432 a = self.idom.get(a).and_then(|x| *x).unwrap_or(a);
433 } else {
434 b = self.idom.get(b).and_then(|x| *x).unwrap_or(b);
435 }
436 }
437 0
438 }
439}
440#[allow(dead_code)]
441#[derive(Debug, Clone)]
442pub struct RLangPassConfig {
443 pub phase: RLangPassPhase,
444 pub enabled: bool,
445 pub max_iterations: u32,
446 pub debug_output: bool,
447 pub pass_name: String,
448}
449impl RLangPassConfig {
450 #[allow(dead_code)]
451 pub fn new(name: impl Into<String>, phase: RLangPassPhase) -> Self {
452 RLangPassConfig {
453 phase,
454 enabled: true,
455 max_iterations: 10,
456 debug_output: false,
457 pass_name: name.into(),
458 }
459 }
460 #[allow(dead_code)]
461 pub fn disabled(mut self) -> Self {
462 self.enabled = false;
463 self
464 }
465 #[allow(dead_code)]
466 pub fn with_debug(mut self) -> Self {
467 self.debug_output = true;
468 self
469 }
470 #[allow(dead_code)]
471 pub fn max_iter(mut self, n: u32) -> Self {
472 self.max_iterations = n;
473 self
474 }
475}
476#[derive(Debug, Clone, PartialEq)]
478pub struct RArg {
479 pub name: Option<String>,
480 pub value: RExpr,
481}
482impl RArg {
483 pub fn positional(value: RExpr) -> Self {
484 RArg { name: None, value }
485 }
486 pub fn named(name: &str, value: RExpr) -> Self {
487 RArg {
488 name: Some(name.to_string()),
489 value,
490 }
491 }
492}
493#[allow(dead_code)]
494#[derive(Debug, Clone)]
495pub struct RLangWorklist {
496 pub(super) items: std::collections::VecDeque<u32>,
497 pub(super) in_worklist: std::collections::HashSet<u32>,
498}
499impl RLangWorklist {
500 #[allow(dead_code)]
501 pub fn new() -> Self {
502 RLangWorklist {
503 items: std::collections::VecDeque::new(),
504 in_worklist: std::collections::HashSet::new(),
505 }
506 }
507 #[allow(dead_code)]
508 pub fn push(&mut self, item: u32) -> bool {
509 if self.in_worklist.insert(item) {
510 self.items.push_back(item);
511 true
512 } else {
513 false
514 }
515 }
516 #[allow(dead_code)]
517 pub fn pop(&mut self) -> Option<u32> {
518 let item = self.items.pop_front()?;
519 self.in_worklist.remove(&item);
520 Some(item)
521 }
522 #[allow(dead_code)]
523 pub fn is_empty(&self) -> bool {
524 self.items.is_empty()
525 }
526 #[allow(dead_code)]
527 pub fn len(&self) -> usize {
528 self.items.len()
529 }
530 #[allow(dead_code)]
531 pub fn contains(&self, item: u32) -> bool {
532 self.in_worklist.contains(&item)
533 }
534}
535#[derive(Debug, Clone, PartialEq)]
537pub struct VectorizedOp {
538 pub op: String,
540 pub needs_vectorize: bool,
542 pub use_apply_family: Option<ApplyVariant>,
544 pub uses_recycling: bool,
546}
547impl VectorizedOp {
548 pub fn element_wise(op: &str) -> Self {
549 VectorizedOp {
550 op: op.to_string(),
551 needs_vectorize: false,
552 use_apply_family: None,
553 uses_recycling: true,
554 }
555 }
556 pub fn with_sapply(op: &str) -> Self {
557 VectorizedOp {
558 op: op.to_string(),
559 needs_vectorize: false,
560 use_apply_family: Some(ApplyVariant::Sapply),
561 uses_recycling: false,
562 }
563 }
564 pub fn with_vectorize(op: &str) -> Self {
565 VectorizedOp {
566 op: op.to_string(),
567 needs_vectorize: true,
568 use_apply_family: None,
569 uses_recycling: false,
570 }
571 }
572}
573#[allow(dead_code)]
575#[derive(Debug, Clone)]
576pub struct RLangExtPassConfig {
577 pub name: String,
578 pub phase: RLangExtPassPhase,
579 pub enabled: bool,
580 pub max_iterations: usize,
581 pub debug: u32,
582 pub timeout_ms: Option<u64>,
583}
584impl RLangExtPassConfig {
585 #[allow(dead_code)]
586 pub fn new(name: impl Into<String>) -> Self {
587 Self {
588 name: name.into(),
589 phase: RLangExtPassPhase::Middle,
590 enabled: true,
591 max_iterations: 100,
592 debug: 0,
593 timeout_ms: None,
594 }
595 }
596 #[allow(dead_code)]
597 pub fn with_phase(mut self, phase: RLangExtPassPhase) -> Self {
598 self.phase = phase;
599 self
600 }
601 #[allow(dead_code)]
602 pub fn with_max_iter(mut self, n: usize) -> Self {
603 self.max_iterations = n;
604 self
605 }
606 #[allow(dead_code)]
607 pub fn with_debug(mut self, d: u32) -> Self {
608 self.debug = d;
609 self
610 }
611 #[allow(dead_code)]
612 pub fn disabled(mut self) -> Self {
613 self.enabled = false;
614 self
615 }
616 #[allow(dead_code)]
617 pub fn with_timeout(mut self, ms: u64) -> Self {
618 self.timeout_ms = Some(ms);
619 self
620 }
621 #[allow(dead_code)]
622 pub fn is_debug_enabled(&self) -> bool {
623 self.debug > 0
624 }
625}
626#[allow(dead_code)]
627pub struct RLangPassRegistry {
628 pub(super) configs: Vec<RLangPassConfig>,
629 pub(super) stats: std::collections::HashMap<String, RLangPassStats>,
630}
631impl RLangPassRegistry {
632 #[allow(dead_code)]
633 pub fn new() -> Self {
634 RLangPassRegistry {
635 configs: Vec::new(),
636 stats: std::collections::HashMap::new(),
637 }
638 }
639 #[allow(dead_code)]
640 pub fn register(&mut self, config: RLangPassConfig) {
641 self.stats
642 .insert(config.pass_name.clone(), RLangPassStats::new());
643 self.configs.push(config);
644 }
645 #[allow(dead_code)]
646 pub fn enabled_passes(&self) -> Vec<&RLangPassConfig> {
647 self.configs.iter().filter(|c| c.enabled).collect()
648 }
649 #[allow(dead_code)]
650 pub fn get_stats(&self, name: &str) -> Option<&RLangPassStats> {
651 self.stats.get(name)
652 }
653 #[allow(dead_code)]
654 pub fn total_passes(&self) -> usize {
655 self.configs.len()
656 }
657 #[allow(dead_code)]
658 pub fn enabled_count(&self) -> usize {
659 self.enabled_passes().len()
660 }
661 #[allow(dead_code)]
662 pub fn update_stats(&mut self, name: &str, changes: u64, time_ms: u64, iter: u32) {
663 if let Some(stats) = self.stats.get_mut(name) {
664 stats.record_run(changes, time_ms, iter);
665 }
666 }
667}
668pub struct RBackend {
670 pub(super) output: String,
672 pub(super) indent: usize,
674 pub(super) indent_str: String,
676 pub(super) s4_classes: HashMap<String, Vec<(String, RType)>>,
678 pub(super) s3_generics: Vec<String>,
680 pub(super) vectorized_ops: HashMap<String, VectorizedOp>,
682}
683impl RBackend {
684 pub fn new() -> Self {
686 RBackend {
687 output: String::new(),
688 indent: 0,
689 indent_str: " ".to_string(),
690 s4_classes: HashMap::new(),
691 s3_generics: Vec::new(),
692 vectorized_ops: HashMap::new(),
693 }
694 }
695 pub fn take_output(&mut self) -> String {
697 std::mem::take(&mut self.output)
698 }
699 pub fn register_vectorized(&mut self, name: &str, op: VectorizedOp) {
701 self.vectorized_ops.insert(name.to_string(), op);
702 }
703 pub(super) fn current_indent(&self) -> String {
704 self.indent_str.repeat(self.indent)
705 }
706 pub(super) fn emit_line(&mut self, line: &str) {
707 let indent = self.current_indent();
708 let _ = writeln!(self.output, "{}{}", indent, line);
709 }
710 pub(super) fn emit_raw(&mut self, s: &str) {
711 self.output.push_str(s);
712 }
713 pub(super) fn indent_up(&mut self) {
714 self.indent += 1;
715 }
716 pub(super) fn indent_down(&mut self) {
717 if self.indent > 0 {
718 self.indent -= 1;
719 }
720 }
721 pub fn emit_file(&mut self, file: &RFile) {
723 if let Some(shebang) = &file.shebang {
724 self.emit_line(shebang);
725 }
726 if let Some(header) = &file.header_comment {
727 for line in header.lines() {
728 self.emit_line(&format!("# {}", line));
729 }
730 self.emit_line("");
731 }
732 for pkg in &file.imports {
733 self.emit_line(&format!("library({})", pkg));
734 }
735 if !file.imports.is_empty() {
736 self.emit_line("");
737 }
738 for obj in &file.data_objects {
739 self.emit_data_object(obj);
740 }
741 if !file.data_objects.is_empty() {
742 self.emit_line("");
743 }
744 for fun in &file.functions {
745 self.emit_function(fun);
746 self.emit_line("");
747 }
748 for stmt in &file.scripts {
749 self.emit_stmt(stmt);
750 }
751 }
752 pub(super) fn emit_data_object(&mut self, obj: &RDataObject) {
753 if let Some(comment) = &obj.comment {
754 self.emit_line(&format!("# {}", comment));
755 }
756 let value_str = self.emit_expr(&obj.value);
757 self.emit_line(&format!("{} <- {}", obj.name, value_str));
758 }
759 pub fn emit_function(&mut self, fun: &RFunction) {
761 if let Some(doc) = &fun.doc {
762 for line in doc.lines() {
763 self.emit_line(&format!("#' {}", line));
764 }
765 }
766 let formals_str = self.emit_formals(&fun.formals);
767 self.emit_line(&format!("{} <- function({}) {{", fun.name, formals_str));
768 self.indent_up();
769 if fun.is_generic {
770 self.emit_line(&format!("UseMethod(\"{}\")", fun.name));
771 } else {
772 for stmt in &fun.body {
773 self.emit_stmt(stmt);
774 }
775 }
776 self.indent_down();
777 self.emit_line("}");
778 for (class, method) in &fun.s3_methods {
779 let method_name = format!("{}.{}", fun.name, class);
780 let formals_str2 = self.emit_formals(&method.formals);
781 self.emit_line(&format!("{} <- function({}) {{", method_name, formals_str2));
782 self.indent_up();
783 for stmt in &method.body {
784 self.emit_stmt(stmt);
785 }
786 self.indent_down();
787 self.emit_line("}");
788 }
789 }
790 pub(super) fn emit_formals(&self, formals: &[RFormal]) -> String {
791 let mut parts = Vec::new();
792 for formal in formals {
793 if let Some(default) = &formal.default {
794 let default_str = self.emit_expr_pure(default);
795 parts.push(format!("{} = {}", formal.name, default_str));
796 } else {
797 parts.push(formal.name.clone());
798 }
799 }
800 parts.join(", ")
801 }
802 pub fn emit_stmt(&mut self, stmt: &RStmt) {
804 match stmt {
805 RStmt::Assign(op, lhs, rhs) => {
806 let rhs_str = self.emit_expr(rhs);
807 self.emit_line(&format!("{} {} {}", lhs, op, rhs_str));
808 }
809 RStmt::AssignLhs(op, lhs, rhs) => {
810 let lhs_str = self.emit_expr(lhs);
811 let rhs_str = self.emit_expr(rhs);
812 self.emit_line(&format!("{} {} {}", lhs_str, op, rhs_str));
813 }
814 RStmt::ForLoop { var, seq, body } => {
815 let seq_str = self.emit_expr(seq);
816 self.emit_line(&format!("for ({} in {}) {{", var, seq_str));
817 self.indent_up();
818 for s in body {
819 self.emit_stmt(s);
820 }
821 self.indent_down();
822 self.emit_line("}");
823 }
824 RStmt::WhileLoop { cond, body } => {
825 let cond_str = self.emit_expr(cond);
826 self.emit_line(&format!("while ({}) {{", cond_str));
827 self.indent_up();
828 for s in body {
829 self.emit_stmt(s);
830 }
831 self.indent_down();
832 self.emit_line("}");
833 }
834 RStmt::Repeat(body) => {
835 self.emit_line("repeat {");
836 self.indent_up();
837 for s in body {
838 self.emit_stmt(s);
839 }
840 self.indent_down();
841 self.emit_line("}");
842 }
843 RStmt::IfElse {
844 cond,
845 then_body,
846 else_if_branches,
847 else_body,
848 } => {
849 let cond_str = self.emit_expr(cond);
850 self.emit_line(&format!("if ({}) {{", cond_str));
851 self.indent_up();
852 for s in then_body {
853 self.emit_stmt(s);
854 }
855 self.indent_down();
856 for (elif_cond, elif_body) in else_if_branches {
857 let elif_cond_str = self.emit_expr(elif_cond);
858 self.emit_line(&format!("}} else if ({}) {{", elif_cond_str));
859 self.indent_up();
860 for s in elif_body {
861 self.emit_stmt(s);
862 }
863 self.indent_down();
864 }
865 if let Some(else_stmts) = else_body {
866 self.emit_line("} else {");
867 self.indent_up();
868 for s in else_stmts {
869 self.emit_stmt(s);
870 }
871 self.indent_down();
872 }
873 self.emit_line("}");
874 }
875 RStmt::Return(expr) => {
876 if let Some(e) = expr {
877 let e_str = self.emit_expr(e);
878 self.emit_line(&format!("return({})", e_str));
879 } else {
880 self.emit_line("return(invisible(NULL))");
881 }
882 }
883 RStmt::Next => {
884 self.emit_line("next");
885 }
886 RStmt::Break => {
887 self.emit_line("break");
888 }
889 RStmt::FunctionDef(fun) => {
890 self.emit_function(fun);
891 }
892 RStmt::Library { pkg, use_require } => {
893 if *use_require {
894 self.emit_line(&format!("require({}, quietly = TRUE)", pkg));
895 } else {
896 self.emit_line(&format!("library({})", pkg));
897 }
898 }
899 RStmt::Source(path) => {
900 self.emit_line(&format!("source(\"{}\")", path));
901 }
902 RStmt::Expr(expr) => {
903 let e_str = self.emit_expr(expr);
904 self.emit_line(&e_str);
905 }
906 RStmt::Comment(text) => {
907 for line in text.lines() {
908 self.emit_line(&format!("# {}", line));
909 }
910 }
911 RStmt::Stopifnot(conds) => {
912 let conds_str: Vec<String> = conds.iter().map(|c| self.emit_expr_pure(c)).collect();
913 self.emit_line(&format!("stopifnot({})", conds_str.join(", ")));
914 }
915 RStmt::TryCatch {
916 body,
917 handlers,
918 finally,
919 } => {
920 self.emit_line("tryCatch({");
921 self.indent_up();
922 for s in body {
923 self.emit_stmt(s);
924 }
925 self.indent_down();
926 self.emit_raw(&self.current_indent());
927 self.emit_raw("}");
928 for (condition, formal, handler_body) in handlers {
929 self.emit_raw(&format!(
930 ",\n{}{} = function({}) {{\n",
931 self.current_indent(),
932 condition,
933 formal.name
934 ));
935 self.indent_up();
936 let handler_stmts: Vec<String> = handler_body
937 .iter()
938 .map(|s| {
939 let mut tmp = RBackend::new();
940 tmp.indent = self.indent;
941 tmp.emit_stmt(s);
942 tmp.take_output()
943 })
944 .collect();
945 for h in handler_stmts {
946 self.emit_raw(&h);
947 }
948 self.indent_down();
949 self.emit_raw(&format!("{}}}", self.current_indent()));
950 }
951 if let Some(fin) = finally {
952 self.emit_raw(",\nfinally = {\n");
953 self.indent_up();
954 for s in fin {
955 self.emit_stmt(s);
956 }
957 self.indent_down();
958 self.emit_raw(&format!("{}}}", self.current_indent()));
959 }
960 self.emit_raw(")\n");
961 }
962 RStmt::SetMethod {
963 generic,
964 signature,
965 fun,
966 } => {
967 let sig_str: Vec<String> = signature.iter().map(|s| format!("\"{}\"", s)).collect();
968 let formals_str = self.emit_formals(&fun.formals);
969 self.emit_line(&format!(
970 "setMethod(\"{}\", signature({}), function({}) {{",
971 generic,
972 sig_str.join(", "),
973 formals_str
974 ));
975 self.indent_up();
976 for s in &fun.body {
977 self.emit_stmt(s);
978 }
979 self.indent_down();
980 self.emit_line("})");
981 }
982 RStmt::SetClass {
983 class,
984 contains,
985 slots,
986 } => {
987 let slots_str: Vec<String> = slots
988 .iter()
989 .map(|(name, ty)| format!("{} = \"{}\"", name, ty))
990 .collect();
991 let contains_str = if let Some(parent) = contains {
992 format!(", contains = \"{}\"", parent)
993 } else {
994 String::new()
995 };
996 self.emit_line(&format!(
997 "setClass(\"{}\", slots = c({}){}) ",
998 class,
999 slots_str.join(", "),
1000 contains_str
1001 ));
1002 }
1003 }
1004 }
1005 pub fn emit_expr(&mut self, expr: &RExpr) -> String {
1007 self.emit_expr_pure(expr)
1008 }
1009 pub fn emit_expr_pure(&self, expr: &RExpr) -> String {
1011 match expr {
1012 RExpr::Lit(lit) => self.emit_literal(lit),
1013 RExpr::Var(name) => name.clone(),
1014 RExpr::Call(func, args) => {
1015 let func_str = self.emit_expr_pure(func);
1016 let args_str: Vec<String> = args.iter().map(|a| self.emit_arg(a)).collect();
1017 format!("{}({})", func_str, args_str.join(", "))
1018 }
1019 RExpr::InfixOp(op, lhs, rhs) => {
1020 let lhs_str = self.emit_expr_pure(lhs);
1021 let rhs_str = self.emit_expr_pure(rhs);
1022 format!("{} {} {}", lhs_str, op, rhs_str)
1023 }
1024 RExpr::UnaryOp(op, operand) => {
1025 let operand_str = self.emit_expr_pure(operand);
1026 if op == "!" || op == "-" || op == "+" {
1027 format!("{}{}", op, operand_str)
1028 } else {
1029 format!("{}({})", op, operand_str)
1030 }
1031 }
1032 RExpr::IndexSingle(obj, indices) => {
1033 let obj_str = self.emit_expr_pure(obj);
1034 let idx_str: Vec<String> = indices.iter().map(|i| self.emit_expr_pure(i)).collect();
1035 format!("{}[{}]", obj_str, idx_str.join(", "))
1036 }
1037 RExpr::IndexDouble(obj, index) => {
1038 let obj_str = self.emit_expr_pure(obj);
1039 let idx_str = self.emit_expr_pure(index);
1040 format!("{}[[{}]]", obj_str, idx_str)
1041 }
1042 RExpr::DollarAccess(obj, field) => {
1043 let obj_str = self.emit_expr_pure(obj);
1044 format!("{}${}", obj_str, field)
1045 }
1046 RExpr::AtAccess(obj, slot) => {
1047 let obj_str = self.emit_expr_pure(obj);
1048 format!("{}@{}", obj_str, slot)
1049 }
1050 RExpr::Formula(lhs, rhs) => {
1051 let rhs_str = self.emit_expr_pure(rhs);
1052 if let Some(lhs_expr) = lhs {
1053 let lhs_str = self.emit_expr_pure(lhs_expr);
1054 format!("{} ~ {}", lhs_str, rhs_str)
1055 } else {
1056 format!("~ {}", rhs_str)
1057 }
1058 }
1059 RExpr::IfElse(cond, then_expr, else_expr) => {
1060 let cond_str = self.emit_expr_pure(cond);
1061 let then_str = self.emit_expr_pure(then_expr);
1062 if let Some(else_e) = else_expr {
1063 let else_str = self.emit_expr_pure(else_e);
1064 format!("if ({}) {} else {}", cond_str, then_str, else_str)
1065 } else {
1066 format!("if ({}) {}", cond_str, then_str)
1067 }
1068 }
1069 RExpr::Lambda(formals, body) => {
1070 let formals_str = self.emit_formals(formals);
1071 let body_str = self.emit_expr_pure(body);
1072 format!("function({}) {}", formals_str, body_str)
1073 }
1074 RExpr::Pipe(lhs, rhs) => {
1075 let lhs_str = self.emit_expr_pure(lhs);
1076 let rhs_str = self.emit_expr_pure(rhs);
1077 format!("{} |> {}", lhs_str, rhs_str)
1078 }
1079 RExpr::MagrittrPipe(lhs, rhs) => {
1080 let lhs_str = self.emit_expr_pure(lhs);
1081 let rhs_str = self.emit_expr_pure(rhs);
1082 format!("{} %>% {}", lhs_str, rhs_str)
1083 }
1084 RExpr::Seq(start, end) => {
1085 let start_str = self.emit_expr_pure(start);
1086 let end_str = self.emit_expr_pure(end);
1087 format!("{}:{}", start_str, end_str)
1088 }
1089 RExpr::CVec(elems) => {
1090 let elems_str: Vec<String> = elems.iter().map(|e| self.emit_expr_pure(e)).collect();
1091 format!("c({})", elems_str.join(", "))
1092 }
1093 RExpr::ListExpr(args) => {
1094 let args_str: Vec<String> = args.iter().map(|a| self.emit_arg(a)).collect();
1095 format!("list({})", args_str.join(", "))
1096 }
1097 RExpr::Block(stmts) => {
1098 if stmts.is_empty() {
1099 return "{}".to_string();
1100 }
1101 let mut inner = RBackend::new();
1102 inner.indent = self.indent + 1;
1103 for s in stmts {
1104 inner.emit_stmt(s);
1105 }
1106 let inner_out = inner.take_output();
1107 format!("{{\n{}{}}}", inner_out, self.current_indent())
1108 }
1109 RExpr::Namespace(pkg, func) => format!("{}::{}", pkg, func),
1110 RExpr::NamespaceInternal(pkg, func) => format!("{}:::{}", pkg, func),
1111 }
1112 }
1113 pub(super) fn emit_literal(&self, lit: &RLiteral) -> String {
1114 match lit {
1115 RLiteral::Integer(n) => format!("{}L", n),
1116 RLiteral::Numeric(f) => {
1117 if f.fract() == 0.0 && f.abs() < 1e15 {
1118 format!("{:.1}", f)
1119 } else {
1120 format!("{}", f)
1121 }
1122 }
1123 RLiteral::Logical(b) => {
1124 if *b {
1125 "TRUE".to_string()
1126 } else {
1127 "FALSE".to_string()
1128 }
1129 }
1130 RLiteral::Character(s) => format!("\"{}\"", s.replace('"', "\\\"")),
1131 RLiteral::Complex(re, im) => {
1132 if *im >= 0.0 {
1133 format!("{}+{}i", re, im)
1134 } else {
1135 format!("{}{}i", re, im)
1136 }
1137 }
1138 RLiteral::Null => "NULL".to_string(),
1139 RLiteral::Na => "NA".to_string(),
1140 RLiteral::NaInteger => "NA_integer_".to_string(),
1141 RLiteral::NaReal => "NA_real_".to_string(),
1142 RLiteral::NaCharacter => "NA_character_".to_string(),
1143 RLiteral::NaComplex => "NA_complex_".to_string(),
1144 RLiteral::Inf => "Inf".to_string(),
1145 RLiteral::NaN => "NaN".to_string(),
1146 }
1147 }
1148 pub(super) fn emit_arg(&self, arg: &RArg) -> String {
1149 let val_str = self.emit_expr_pure(&arg.value);
1150 if let Some(name) = &arg.name {
1151 format!("{} = {}", name, val_str)
1152 } else {
1153 val_str
1154 }
1155 }
1156 pub fn emit_vectorized(
1158 &self,
1159 op: &VectorizedOp,
1160 vec_expr: &RExpr,
1161 extra_args: &[RArg],
1162 ) -> String {
1163 let vec_str = self.emit_expr_pure(vec_expr);
1164 if let Some(apply_fn) = &op.use_apply_family {
1165 let func_expr = RExpr::Var(op.op.clone());
1166 let func_str = self.emit_expr_pure(&func_expr);
1167 let mut args_str = format!("{}, {}", vec_str, func_str);
1168 for a in extra_args {
1169 args_str.push_str(", ");
1170 args_str.push_str(&self.emit_arg(a));
1171 }
1172 format!("{}({})", apply_fn, args_str)
1173 } else if op.needs_vectorize {
1174 let func_str = op.op.clone();
1175 let extra: Vec<String> = extra_args.iter().map(|a| self.emit_arg(a)).collect();
1176 if extra.is_empty() {
1177 format!("Vectorize({})({})", func_str, vec_str)
1178 } else {
1179 format!("Vectorize({})({}{})", func_str, vec_str, extra.join(", "))
1180 }
1181 } else {
1182 let mut args_str = vec_str;
1183 for a in extra_args {
1184 args_str.push_str(", ");
1185 args_str.push_str(&self.emit_arg(a));
1186 }
1187 format!("{}({})", op.op, args_str)
1188 }
1189 }
1190}
1191#[derive(Debug, Clone, PartialEq)]
1193pub struct RDataObject {
1194 pub name: String,
1196 pub value: RExpr,
1198 pub comment: Option<String>,
1200}
1201#[allow(dead_code)]
1202#[derive(Debug, Clone)]
1203pub struct RLangLivenessInfo {
1204 pub live_in: Vec<std::collections::HashSet<u32>>,
1205 pub live_out: Vec<std::collections::HashSet<u32>>,
1206 pub defs: Vec<std::collections::HashSet<u32>>,
1207 pub uses: Vec<std::collections::HashSet<u32>>,
1208}
1209impl RLangLivenessInfo {
1210 #[allow(dead_code)]
1211 pub fn new(block_count: usize) -> Self {
1212 RLangLivenessInfo {
1213 live_in: vec![std::collections::HashSet::new(); block_count],
1214 live_out: vec![std::collections::HashSet::new(); block_count],
1215 defs: vec![std::collections::HashSet::new(); block_count],
1216 uses: vec![std::collections::HashSet::new(); block_count],
1217 }
1218 }
1219 #[allow(dead_code)]
1220 pub fn add_def(&mut self, block: usize, var: u32) {
1221 if block < self.defs.len() {
1222 self.defs[block].insert(var);
1223 }
1224 }
1225 #[allow(dead_code)]
1226 pub fn add_use(&mut self, block: usize, var: u32) {
1227 if block < self.uses.len() {
1228 self.uses[block].insert(var);
1229 }
1230 }
1231 #[allow(dead_code)]
1232 pub fn is_live_in(&self, block: usize, var: u32) -> bool {
1233 self.live_in
1234 .get(block)
1235 .map(|s| s.contains(&var))
1236 .unwrap_or(false)
1237 }
1238 #[allow(dead_code)]
1239 pub fn is_live_out(&self, block: usize, var: u32) -> bool {
1240 self.live_out
1241 .get(block)
1242 .map(|s| s.contains(&var))
1243 .unwrap_or(false)
1244 }
1245}
1246#[allow(dead_code)]
1247pub struct RLangConstantFoldingHelper;
1248impl RLangConstantFoldingHelper {
1249 #[allow(dead_code)]
1250 pub fn fold_add_i64(a: i64, b: i64) -> Option<i64> {
1251 a.checked_add(b)
1252 }
1253 #[allow(dead_code)]
1254 pub fn fold_sub_i64(a: i64, b: i64) -> Option<i64> {
1255 a.checked_sub(b)
1256 }
1257 #[allow(dead_code)]
1258 pub fn fold_mul_i64(a: i64, b: i64) -> Option<i64> {
1259 a.checked_mul(b)
1260 }
1261 #[allow(dead_code)]
1262 pub fn fold_div_i64(a: i64, b: i64) -> Option<i64> {
1263 if b == 0 {
1264 None
1265 } else {
1266 a.checked_div(b)
1267 }
1268 }
1269 #[allow(dead_code)]
1270 pub fn fold_add_f64(a: f64, b: f64) -> f64 {
1271 a + b
1272 }
1273 #[allow(dead_code)]
1274 pub fn fold_mul_f64(a: f64, b: f64) -> f64 {
1275 a * b
1276 }
1277 #[allow(dead_code)]
1278 pub fn fold_neg_i64(a: i64) -> Option<i64> {
1279 a.checked_neg()
1280 }
1281 #[allow(dead_code)]
1282 pub fn fold_not_bool(a: bool) -> bool {
1283 !a
1284 }
1285 #[allow(dead_code)]
1286 pub fn fold_and_bool(a: bool, b: bool) -> bool {
1287 a && b
1288 }
1289 #[allow(dead_code)]
1290 pub fn fold_or_bool(a: bool, b: bool) -> bool {
1291 a || b
1292 }
1293 #[allow(dead_code)]
1294 pub fn fold_shl_i64(a: i64, b: u32) -> Option<i64> {
1295 a.checked_shl(b)
1296 }
1297 #[allow(dead_code)]
1298 pub fn fold_shr_i64(a: i64, b: u32) -> Option<i64> {
1299 a.checked_shr(b)
1300 }
1301 #[allow(dead_code)]
1302 pub fn fold_rem_i64(a: i64, b: i64) -> Option<i64> {
1303 if b == 0 {
1304 None
1305 } else {
1306 Some(a % b)
1307 }
1308 }
1309 #[allow(dead_code)]
1310 pub fn fold_bitand_i64(a: i64, b: i64) -> i64 {
1311 a & b
1312 }
1313 #[allow(dead_code)]
1314 pub fn fold_bitor_i64(a: i64, b: i64) -> i64 {
1315 a | b
1316 }
1317 #[allow(dead_code)]
1318 pub fn fold_bitxor_i64(a: i64, b: i64) -> i64 {
1319 a ^ b
1320 }
1321 #[allow(dead_code)]
1322 pub fn fold_bitnot_i64(a: i64) -> i64 {
1323 !a
1324 }
1325}
1326#[allow(dead_code)]
1328#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1329pub enum RLangExtPassPhase {
1330 Early,
1331 Middle,
1332 Late,
1333 Finalize,
1334}
1335impl RLangExtPassPhase {
1336 #[allow(dead_code)]
1337 pub fn is_early(&self) -> bool {
1338 matches!(self, Self::Early)
1339 }
1340 #[allow(dead_code)]
1341 pub fn is_middle(&self) -> bool {
1342 matches!(self, Self::Middle)
1343 }
1344 #[allow(dead_code)]
1345 pub fn is_late(&self) -> bool {
1346 matches!(self, Self::Late)
1347 }
1348 #[allow(dead_code)]
1349 pub fn is_finalize(&self) -> bool {
1350 matches!(self, Self::Finalize)
1351 }
1352 #[allow(dead_code)]
1353 pub fn order(&self) -> u32 {
1354 match self {
1355 Self::Early => 0,
1356 Self::Middle => 1,
1357 Self::Late => 2,
1358 Self::Finalize => 3,
1359 }
1360 }
1361 #[allow(dead_code)]
1362 pub fn from_order(n: u32) -> Option<Self> {
1363 match n {
1364 0 => Some(Self::Early),
1365 1 => Some(Self::Middle),
1366 2 => Some(Self::Late),
1367 3 => Some(Self::Finalize),
1368 _ => None,
1369 }
1370 }
1371}
1372#[allow(dead_code)]
1374#[derive(Debug, Clone, Default)]
1375pub struct RLangExtLiveness {
1376 pub live_in: Vec<Vec<usize>>,
1377 pub live_out: Vec<Vec<usize>>,
1378 pub defs: Vec<Vec<usize>>,
1379 pub uses: Vec<Vec<usize>>,
1380}
1381impl RLangExtLiveness {
1382 #[allow(dead_code)]
1383 pub fn new(n: usize) -> Self {
1384 Self {
1385 live_in: vec![Vec::new(); n],
1386 live_out: vec![Vec::new(); n],
1387 defs: vec![Vec::new(); n],
1388 uses: vec![Vec::new(); n],
1389 }
1390 }
1391 #[allow(dead_code)]
1392 pub fn live_in(&self, b: usize, v: usize) -> bool {
1393 self.live_in.get(b).map(|s| s.contains(&v)).unwrap_or(false)
1394 }
1395 #[allow(dead_code)]
1396 pub fn live_out(&self, b: usize, v: usize) -> bool {
1397 self.live_out
1398 .get(b)
1399 .map(|s| s.contains(&v))
1400 .unwrap_or(false)
1401 }
1402 #[allow(dead_code)]
1403 pub fn add_def(&mut self, b: usize, v: usize) {
1404 if let Some(s) = self.defs.get_mut(b) {
1405 if !s.contains(&v) {
1406 s.push(v);
1407 }
1408 }
1409 }
1410 #[allow(dead_code)]
1411 pub fn add_use(&mut self, b: usize, v: usize) {
1412 if let Some(s) = self.uses.get_mut(b) {
1413 if !s.contains(&v) {
1414 s.push(v);
1415 }
1416 }
1417 }
1418 #[allow(dead_code)]
1419 pub fn var_is_used_in_block(&self, b: usize, v: usize) -> bool {
1420 self.uses.get(b).map(|s| s.contains(&v)).unwrap_or(false)
1421 }
1422 #[allow(dead_code)]
1423 pub fn var_is_def_in_block(&self, b: usize, v: usize) -> bool {
1424 self.defs.get(b).map(|s| s.contains(&v)).unwrap_or(false)
1425 }
1426}
1427#[allow(dead_code)]
1429#[derive(Debug, Default)]
1430pub struct RLangExtPassRegistry {
1431 pub(super) configs: Vec<RLangExtPassConfig>,
1432 pub(super) stats: Vec<RLangExtPassStats>,
1433}
1434impl RLangExtPassRegistry {
1435 #[allow(dead_code)]
1436 pub fn new() -> Self {
1437 Self::default()
1438 }
1439 #[allow(dead_code)]
1440 pub fn register(&mut self, c: RLangExtPassConfig) {
1441 self.stats.push(RLangExtPassStats::new());
1442 self.configs.push(c);
1443 }
1444 #[allow(dead_code)]
1445 pub fn len(&self) -> usize {
1446 self.configs.len()
1447 }
1448 #[allow(dead_code)]
1449 pub fn is_empty(&self) -> bool {
1450 self.configs.is_empty()
1451 }
1452 #[allow(dead_code)]
1453 pub fn get(&self, i: usize) -> Option<&RLangExtPassConfig> {
1454 self.configs.get(i)
1455 }
1456 #[allow(dead_code)]
1457 pub fn get_stats(&self, i: usize) -> Option<&RLangExtPassStats> {
1458 self.stats.get(i)
1459 }
1460 #[allow(dead_code)]
1461 pub fn enabled_passes(&self) -> Vec<&RLangExtPassConfig> {
1462 self.configs.iter().filter(|c| c.enabled).collect()
1463 }
1464 #[allow(dead_code)]
1465 pub fn passes_in_phase(&self, ph: &RLangExtPassPhase) -> Vec<&RLangExtPassConfig> {
1466 self.configs
1467 .iter()
1468 .filter(|c| c.enabled && &c.phase == ph)
1469 .collect()
1470 }
1471 #[allow(dead_code)]
1472 pub fn total_nodes_visited(&self) -> usize {
1473 self.stats.iter().map(|s| s.nodes_visited).sum()
1474 }
1475 #[allow(dead_code)]
1476 pub fn any_changed(&self) -> bool {
1477 self.stats.iter().any(|s| s.changed)
1478 }
1479}
1480#[allow(dead_code)]
1481#[derive(Debug, Clone)]
1482pub struct RLangAnalysisCache {
1483 pub(super) entries: std::collections::HashMap<String, RLangCacheEntry>,
1484 pub(super) max_size: usize,
1485 pub(super) hits: u64,
1486 pub(super) misses: u64,
1487}
1488impl RLangAnalysisCache {
1489 #[allow(dead_code)]
1490 pub fn new(max_size: usize) -> Self {
1491 RLangAnalysisCache {
1492 entries: std::collections::HashMap::new(),
1493 max_size,
1494 hits: 0,
1495 misses: 0,
1496 }
1497 }
1498 #[allow(dead_code)]
1499 pub fn get(&mut self, key: &str) -> Option<&RLangCacheEntry> {
1500 if self.entries.contains_key(key) {
1501 self.hits += 1;
1502 self.entries.get(key)
1503 } else {
1504 self.misses += 1;
1505 None
1506 }
1507 }
1508 #[allow(dead_code)]
1509 pub fn insert(&mut self, key: String, data: Vec<u8>) {
1510 if self.entries.len() >= self.max_size {
1511 if let Some(oldest) = self.entries.keys().next().cloned() {
1512 self.entries.remove(&oldest);
1513 }
1514 }
1515 self.entries.insert(
1516 key.clone(),
1517 RLangCacheEntry {
1518 key,
1519 data,
1520 timestamp: 0,
1521 valid: true,
1522 },
1523 );
1524 }
1525 #[allow(dead_code)]
1526 pub fn invalidate(&mut self, key: &str) {
1527 if let Some(entry) = self.entries.get_mut(key) {
1528 entry.valid = false;
1529 }
1530 }
1531 #[allow(dead_code)]
1532 pub fn clear(&mut self) {
1533 self.entries.clear();
1534 }
1535 #[allow(dead_code)]
1536 pub fn hit_rate(&self) -> f64 {
1537 let total = self.hits + self.misses;
1538 if total == 0 {
1539 return 0.0;
1540 }
1541 self.hits as f64 / total as f64
1542 }
1543 #[allow(dead_code)]
1544 pub fn size(&self) -> usize {
1545 self.entries.len()
1546 }
1547}
1548#[derive(Debug, Clone, PartialEq)]
1550pub enum RStmt {
1551 Assign(RAssignOp, String, RExpr),
1553 AssignLhs(RAssignOp, RExpr, RExpr),
1555 ForLoop {
1557 var: String,
1558 seq: RExpr,
1559 body: Vec<RStmt>,
1560 },
1561 WhileLoop { cond: RExpr, body: Vec<RStmt> },
1563 Repeat(Vec<RStmt>),
1565 IfElse {
1567 cond: RExpr,
1568 then_body: Vec<RStmt>,
1569 else_if_branches: Vec<(RExpr, Vec<RStmt>)>,
1570 else_body: Option<Vec<RStmt>>,
1571 },
1572 Return(Option<RExpr>),
1574 Next,
1576 Break,
1578 FunctionDef(RFunction),
1580 Library { pkg: String, use_require: bool },
1582 Source(String),
1584 Expr(RExpr),
1586 Comment(String),
1588 Stopifnot(Vec<RExpr>),
1590 TryCatch {
1592 body: Vec<RStmt>,
1593 handlers: Vec<(String, RFormal, Vec<RStmt>)>,
1594 finally: Option<Vec<RStmt>>,
1595 },
1596 SetMethod {
1598 generic: String,
1599 signature: Vec<String>,
1600 fun: RFunction,
1601 },
1602 SetClass {
1604 class: String,
1605 contains: Option<String>,
1606 slots: Vec<(String, RType)>,
1607 },
1608}
1609#[allow(dead_code)]
1611#[derive(Debug)]
1612pub struct RLangExtCache {
1613 pub(super) entries: Vec<(u64, Vec<u8>, bool, u32)>,
1614 pub(super) cap: usize,
1615 pub(super) total_hits: u64,
1616 pub(super) total_misses: u64,
1617}
1618impl RLangExtCache {
1619 #[allow(dead_code)]
1620 pub fn new(cap: usize) -> Self {
1621 Self {
1622 entries: Vec::new(),
1623 cap,
1624 total_hits: 0,
1625 total_misses: 0,
1626 }
1627 }
1628 #[allow(dead_code)]
1629 pub fn get(&mut self, key: u64) -> Option<&[u8]> {
1630 for e in self.entries.iter_mut() {
1631 if e.0 == key && e.2 {
1632 e.3 += 1;
1633 self.total_hits += 1;
1634 return Some(&e.1);
1635 }
1636 }
1637 self.total_misses += 1;
1638 None
1639 }
1640 #[allow(dead_code)]
1641 pub fn put(&mut self, key: u64, data: Vec<u8>) {
1642 if self.entries.len() >= self.cap {
1643 self.entries.retain(|e| e.2);
1644 if self.entries.len() >= self.cap {
1645 self.entries.remove(0);
1646 }
1647 }
1648 self.entries.push((key, data, true, 0));
1649 }
1650 #[allow(dead_code)]
1651 pub fn invalidate(&mut self) {
1652 for e in self.entries.iter_mut() {
1653 e.2 = false;
1654 }
1655 }
1656 #[allow(dead_code)]
1657 pub fn hit_rate(&self) -> f64 {
1658 let t = self.total_hits + self.total_misses;
1659 if t == 0 {
1660 0.0
1661 } else {
1662 self.total_hits as f64 / t as f64
1663 }
1664 }
1665 #[allow(dead_code)]
1666 pub fn live_count(&self) -> usize {
1667 self.entries.iter().filter(|e| e.2).count()
1668 }
1669}
1670#[allow(dead_code)]
1672#[derive(Debug, Clone, Default)]
1673pub struct RLangExtPassStats {
1674 pub iterations: usize,
1675 pub changed: bool,
1676 pub nodes_visited: usize,
1677 pub nodes_modified: usize,
1678 pub time_ms: u64,
1679 pub memory_bytes: usize,
1680 pub errors: usize,
1681}
1682impl RLangExtPassStats {
1683 #[allow(dead_code)]
1684 pub fn new() -> Self {
1685 Self::default()
1686 }
1687 #[allow(dead_code)]
1688 pub fn visit(&mut self) {
1689 self.nodes_visited += 1;
1690 }
1691 #[allow(dead_code)]
1692 pub fn modify(&mut self) {
1693 self.nodes_modified += 1;
1694 self.changed = true;
1695 }
1696 #[allow(dead_code)]
1697 pub fn iterate(&mut self) {
1698 self.iterations += 1;
1699 }
1700 #[allow(dead_code)]
1701 pub fn error(&mut self) {
1702 self.errors += 1;
1703 }
1704 #[allow(dead_code)]
1705 pub fn efficiency(&self) -> f64 {
1706 if self.nodes_visited == 0 {
1707 0.0
1708 } else {
1709 self.nodes_modified as f64 / self.nodes_visited as f64
1710 }
1711 }
1712 #[allow(dead_code)]
1713 pub fn merge(&mut self, o: &RLangExtPassStats) {
1714 self.iterations += o.iterations;
1715 self.changed |= o.changed;
1716 self.nodes_visited += o.nodes_visited;
1717 self.nodes_modified += o.nodes_modified;
1718 self.time_ms += o.time_ms;
1719 self.memory_bytes = self.memory_bytes.max(o.memory_bytes);
1720 self.errors += o.errors;
1721 }
1722}
1723#[allow(dead_code)]
1725#[derive(Debug, Clone)]
1726pub struct RLangExtWorklist {
1727 pub(super) items: std::collections::VecDeque<usize>,
1728 pub(super) present: Vec<bool>,
1729}
1730impl RLangExtWorklist {
1731 #[allow(dead_code)]
1732 pub fn new(capacity: usize) -> Self {
1733 Self {
1734 items: std::collections::VecDeque::new(),
1735 present: vec![false; capacity],
1736 }
1737 }
1738 #[allow(dead_code)]
1739 pub fn push(&mut self, id: usize) {
1740 if id < self.present.len() && !self.present[id] {
1741 self.present[id] = true;
1742 self.items.push_back(id);
1743 }
1744 }
1745 #[allow(dead_code)]
1746 pub fn push_front(&mut self, id: usize) {
1747 if id < self.present.len() && !self.present[id] {
1748 self.present[id] = true;
1749 self.items.push_front(id);
1750 }
1751 }
1752 #[allow(dead_code)]
1753 pub fn pop(&mut self) -> Option<usize> {
1754 let id = self.items.pop_front()?;
1755 if id < self.present.len() {
1756 self.present[id] = false;
1757 }
1758 Some(id)
1759 }
1760 #[allow(dead_code)]
1761 pub fn is_empty(&self) -> bool {
1762 self.items.is_empty()
1763 }
1764 #[allow(dead_code)]
1765 pub fn len(&self) -> usize {
1766 self.items.len()
1767 }
1768 #[allow(dead_code)]
1769 pub fn contains(&self, id: usize) -> bool {
1770 id < self.present.len() && self.present[id]
1771 }
1772 #[allow(dead_code)]
1773 pub fn drain_all(&mut self) -> Vec<usize> {
1774 let v: Vec<usize> = self.items.drain(..).collect();
1775 for &id in &v {
1776 if id < self.present.len() {
1777 self.present[id] = false;
1778 }
1779 }
1780 v
1781 }
1782}
1783#[allow(dead_code)]
1785#[derive(Debug, Clone, Default)]
1786pub struct RLangExtConstFolder {
1787 pub(super) folds: usize,
1788 pub(super) failures: usize,
1789 pub(super) enabled: bool,
1790}
1791impl RLangExtConstFolder {
1792 #[allow(dead_code)]
1793 pub fn new() -> Self {
1794 Self {
1795 folds: 0,
1796 failures: 0,
1797 enabled: true,
1798 }
1799 }
1800 #[allow(dead_code)]
1801 pub fn add_i64(&mut self, a: i64, b: i64) -> Option<i64> {
1802 self.folds += 1;
1803 a.checked_add(b)
1804 }
1805 #[allow(dead_code)]
1806 pub fn sub_i64(&mut self, a: i64, b: i64) -> Option<i64> {
1807 self.folds += 1;
1808 a.checked_sub(b)
1809 }
1810 #[allow(dead_code)]
1811 pub fn mul_i64(&mut self, a: i64, b: i64) -> Option<i64> {
1812 self.folds += 1;
1813 a.checked_mul(b)
1814 }
1815 #[allow(dead_code)]
1816 pub fn div_i64(&mut self, a: i64, b: i64) -> Option<i64> {
1817 if b == 0 {
1818 self.failures += 1;
1819 None
1820 } else {
1821 self.folds += 1;
1822 a.checked_div(b)
1823 }
1824 }
1825 #[allow(dead_code)]
1826 pub fn rem_i64(&mut self, a: i64, b: i64) -> Option<i64> {
1827 if b == 0 {
1828 self.failures += 1;
1829 None
1830 } else {
1831 self.folds += 1;
1832 a.checked_rem(b)
1833 }
1834 }
1835 #[allow(dead_code)]
1836 pub fn neg_i64(&mut self, a: i64) -> Option<i64> {
1837 self.folds += 1;
1838 a.checked_neg()
1839 }
1840 #[allow(dead_code)]
1841 pub fn shl_i64(&mut self, a: i64, s: u32) -> Option<i64> {
1842 if s >= 64 {
1843 self.failures += 1;
1844 None
1845 } else {
1846 self.folds += 1;
1847 a.checked_shl(s)
1848 }
1849 }
1850 #[allow(dead_code)]
1851 pub fn shr_i64(&mut self, a: i64, s: u32) -> Option<i64> {
1852 if s >= 64 {
1853 self.failures += 1;
1854 None
1855 } else {
1856 self.folds += 1;
1857 a.checked_shr(s)
1858 }
1859 }
1860 #[allow(dead_code)]
1861 pub fn and_i64(&mut self, a: i64, b: i64) -> i64 {
1862 self.folds += 1;
1863 a & b
1864 }
1865 #[allow(dead_code)]
1866 pub fn or_i64(&mut self, a: i64, b: i64) -> i64 {
1867 self.folds += 1;
1868 a | b
1869 }
1870 #[allow(dead_code)]
1871 pub fn xor_i64(&mut self, a: i64, b: i64) -> i64 {
1872 self.folds += 1;
1873 a ^ b
1874 }
1875 #[allow(dead_code)]
1876 pub fn not_i64(&mut self, a: i64) -> i64 {
1877 self.folds += 1;
1878 !a
1879 }
1880 #[allow(dead_code)]
1881 pub fn fold_count(&self) -> usize {
1882 self.folds
1883 }
1884 #[allow(dead_code)]
1885 pub fn failure_count(&self) -> usize {
1886 self.failures
1887 }
1888 #[allow(dead_code)]
1889 pub fn enable(&mut self) {
1890 self.enabled = true;
1891 }
1892 #[allow(dead_code)]
1893 pub fn disable(&mut self) {
1894 self.enabled = false;
1895 }
1896 #[allow(dead_code)]
1897 pub fn is_enabled(&self) -> bool {
1898 self.enabled
1899 }
1900}
1901#[allow(dead_code)]
1902#[derive(Debug, Clone, PartialEq)]
1903pub enum RLangPassPhase {
1904 Analysis,
1905 Transformation,
1906 Verification,
1907 Cleanup,
1908}
1909impl RLangPassPhase {
1910 #[allow(dead_code)]
1911 pub fn name(&self) -> &str {
1912 match self {
1913 RLangPassPhase::Analysis => "analysis",
1914 RLangPassPhase::Transformation => "transformation",
1915 RLangPassPhase::Verification => "verification",
1916 RLangPassPhase::Cleanup => "cleanup",
1917 }
1918 }
1919 #[allow(dead_code)]
1920 pub fn is_modifying(&self) -> bool {
1921 matches!(
1922 self,
1923 RLangPassPhase::Transformation | RLangPassPhase::Cleanup
1924 )
1925 }
1926}
1927#[allow(dead_code)]
1929#[derive(Debug, Clone)]
1930pub struct RLangExtDepGraph {
1931 pub(super) n: usize,
1932 pub(super) adj: Vec<Vec<usize>>,
1933 pub(super) rev: Vec<Vec<usize>>,
1934 pub(super) edge_count: usize,
1935}
1936impl RLangExtDepGraph {
1937 #[allow(dead_code)]
1938 pub fn new(n: usize) -> Self {
1939 Self {
1940 n,
1941 adj: vec![Vec::new(); n],
1942 rev: vec![Vec::new(); n],
1943 edge_count: 0,
1944 }
1945 }
1946 #[allow(dead_code)]
1947 pub fn add_edge(&mut self, from: usize, to: usize) {
1948 if from < self.n && to < self.n {
1949 if !self.adj[from].contains(&to) {
1950 self.adj[from].push(to);
1951 self.rev[to].push(from);
1952 self.edge_count += 1;
1953 }
1954 }
1955 }
1956 #[allow(dead_code)]
1957 pub fn succs(&self, n: usize) -> &[usize] {
1958 self.adj.get(n).map(|v| v.as_slice()).unwrap_or(&[])
1959 }
1960 #[allow(dead_code)]
1961 pub fn preds(&self, n: usize) -> &[usize] {
1962 self.rev.get(n).map(|v| v.as_slice()).unwrap_or(&[])
1963 }
1964 #[allow(dead_code)]
1965 pub fn topo_sort(&self) -> Option<Vec<usize>> {
1966 let mut deg: Vec<usize> = (0..self.n).map(|i| self.rev[i].len()).collect();
1967 let mut q: std::collections::VecDeque<usize> =
1968 (0..self.n).filter(|&i| deg[i] == 0).collect();
1969 let mut out = Vec::with_capacity(self.n);
1970 while let Some(u) = q.pop_front() {
1971 out.push(u);
1972 for &v in &self.adj[u] {
1973 deg[v] -= 1;
1974 if deg[v] == 0 {
1975 q.push_back(v);
1976 }
1977 }
1978 }
1979 if out.len() == self.n {
1980 Some(out)
1981 } else {
1982 None
1983 }
1984 }
1985 #[allow(dead_code)]
1986 pub fn has_cycle(&self) -> bool {
1987 self.topo_sort().is_none()
1988 }
1989 #[allow(dead_code)]
1990 pub fn reachable(&self, start: usize) -> Vec<usize> {
1991 let mut vis = vec![false; self.n];
1992 let mut stk = vec![start];
1993 let mut out = Vec::new();
1994 while let Some(u) = stk.pop() {
1995 if u < self.n && !vis[u] {
1996 vis[u] = true;
1997 out.push(u);
1998 for &v in &self.adj[u] {
1999 if !vis[v] {
2000 stk.push(v);
2001 }
2002 }
2003 }
2004 }
2005 out
2006 }
2007 #[allow(dead_code)]
2008 pub fn scc(&self) -> Vec<Vec<usize>> {
2009 let mut visited = vec![false; self.n];
2010 let mut order = Vec::new();
2011 for i in 0..self.n {
2012 if !visited[i] {
2013 let mut stk = vec![(i, 0usize)];
2014 while let Some((u, idx)) = stk.last_mut() {
2015 if !visited[*u] {
2016 visited[*u] = true;
2017 }
2018 if *idx < self.adj[*u].len() {
2019 let v = self.adj[*u][*idx];
2020 *idx += 1;
2021 if !visited[v] {
2022 stk.push((v, 0));
2023 }
2024 } else {
2025 order.push(*u);
2026 stk.pop();
2027 }
2028 }
2029 }
2030 }
2031 let mut comp = vec![usize::MAX; self.n];
2032 let mut components: Vec<Vec<usize>> = Vec::new();
2033 for &start in order.iter().rev() {
2034 if comp[start] == usize::MAX {
2035 let cid = components.len();
2036 let mut component = Vec::new();
2037 let mut stk = vec![start];
2038 while let Some(u) = stk.pop() {
2039 if comp[u] == usize::MAX {
2040 comp[u] = cid;
2041 component.push(u);
2042 for &v in &self.rev[u] {
2043 if comp[v] == usize::MAX {
2044 stk.push(v);
2045 }
2046 }
2047 }
2048 }
2049 components.push(component);
2050 }
2051 }
2052 components
2053 }
2054 #[allow(dead_code)]
2055 pub fn node_count(&self) -> usize {
2056 self.n
2057 }
2058 #[allow(dead_code)]
2059 pub fn edge_count(&self) -> usize {
2060 self.edge_count
2061 }
2062}
2063#[allow(dead_code)]
2064#[derive(Debug, Clone)]
2065pub struct RLangCacheEntry {
2066 pub key: String,
2067 pub data: Vec<u8>,
2068 pub timestamp: u64,
2069 pub valid: bool,
2070}
2071#[derive(Debug, Clone, PartialEq)]
2073pub enum RExpr {
2074 Lit(RLiteral),
2076 Var(String),
2078 Call(Box<RExpr>, Vec<RArg>),
2080 InfixOp(String, Box<RExpr>, Box<RExpr>),
2082 UnaryOp(String, Box<RExpr>),
2084 IndexSingle(Box<RExpr>, Vec<RExpr>),
2086 IndexDouble(Box<RExpr>, Box<RExpr>),
2088 DollarAccess(Box<RExpr>, String),
2090 AtAccess(Box<RExpr>, String),
2092 Formula(Option<Box<RExpr>>, Box<RExpr>),
2094 IfElse(Box<RExpr>, Box<RExpr>, Option<Box<RExpr>>),
2096 Lambda(Vec<RFormal>, Box<RExpr>),
2098 Pipe(Box<RExpr>, Box<RExpr>),
2100 MagrittrPipe(Box<RExpr>, Box<RExpr>),
2102 Seq(Box<RExpr>, Box<RExpr>),
2104 CVec(Vec<RExpr>),
2106 ListExpr(Vec<RArg>),
2108 Block(Vec<RStmt>),
2110 Namespace(String, String),
2112 NamespaceInternal(String, String),
2114}