1use crate::cps_ir::{CpsContinuationId, CpsModule, CpsValueId};
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub struct CpsEnvironmentLayout {
5 pub functions: Vec<CpsFunctionEnvironmentLayout>,
6 pub roots: Vec<CpsFunctionEnvironmentLayout>,
7}
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct CpsFunctionEnvironmentLayout {
11 pub name: String,
12 pub continuations: Vec<CpsContinuationEnvironmentLayout>,
13}
14
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct CpsContinuationEnvironmentLayout {
17 pub continuation: CpsContinuationId,
18 pub slots: Vec<CpsEnvironmentSlot>,
19}
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub struct CpsEnvironmentSlot {
23 pub index: usize,
24 pub value: CpsValueId,
25}
26
27pub fn layout_cps_environments(module: &CpsModule) -> CpsEnvironmentLayout {
28 CpsEnvironmentLayout {
29 functions: module
30 .functions
31 .iter()
32 .map(layout_function_environments)
33 .collect(),
34 roots: module
35 .roots
36 .iter()
37 .map(layout_function_environments)
38 .collect(),
39 }
40}
41
42fn layout_function_environments(
43 function: &crate::cps_ir::CpsFunction,
44) -> CpsFunctionEnvironmentLayout {
45 CpsFunctionEnvironmentLayout {
46 name: function.name.clone(),
47 continuations: function
48 .continuations
49 .iter()
50 .map(|continuation| CpsContinuationEnvironmentLayout {
51 continuation: continuation.id,
52 slots: continuation
53 .captures
54 .iter()
55 .copied()
56 .enumerate()
57 .map(|(index, value)| CpsEnvironmentSlot { index, value })
58 .collect(),
59 })
60 .collect(),
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use crate::cps_ir::{
67 CpsContinuation, CpsContinuationId, CpsFunction, CpsModule, CpsShotKind, CpsTerminator,
68 CpsValueId,
69 };
70
71 use super::*;
72
73 #[test]
74 fn assigns_stable_slots_from_continuation_capture_order() {
75 let module = CpsModule {
76 functions: Vec::new(),
77 roots: vec![CpsFunction {
78 name: "root".to_string(),
79 params: Vec::new(),
80 entry: CpsContinuationId(0),
81 continuations: vec![CpsContinuation {
82 id: CpsContinuationId(0),
83 params: Vec::new(),
84 captures: vec![CpsValueId(4), CpsValueId(2)],
85 shot_kind: CpsShotKind::MultiShot,
86 stmts: Vec::new(),
87 terminator: CpsTerminator::Return(CpsValueId(4)),
88 }],
89 handlers: Vec::new(),
90 }],
91 };
92
93 assert_eq!(
94 layout_cps_environments(&module).roots[0].continuations[0].slots,
95 vec![
96 CpsEnvironmentSlot {
97 index: 0,
98 value: CpsValueId(4),
99 },
100 CpsEnvironmentSlot {
101 index: 1,
102 value: CpsValueId(2),
103 },
104 ]
105 );
106 }
107}