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