tidepool_codegen/
datacon_env.rs1use tidepool_repr::{CoreExpr, CoreFrame, DataConTable, TreeBuilder, VarId};
2
3pub fn wrap_with_datacon_env(expr: &CoreExpr, table: &DataConTable) -> CoreExpr {
14 let mut b = TreeBuilder::new();
15
16 let mut src = TreeBuilder::new();
18 for node in &expr.nodes {
19 src.push(node.clone());
20 }
21 let base = b.push_tree(src);
22 let root = base + expr.nodes.len() - 1;
23
24 let mut datacons: Vec<_> = table.iter().collect();
26 datacons.sort_by_key(|dc| dc.id.0);
27
28 let mut body = root;
29
30 for dc in &datacons {
31 let binder = VarId(dc.id.0);
32 let arity = dc.rep_arity as usize;
33
34 if arity == 0 {
35 let con = b.push(CoreFrame::Con {
37 tag: dc.id,
38 fields: vec![],
39 });
40 body = b.push(CoreFrame::LetNonRec {
41 binder,
42 rhs: con,
43 body,
44 });
45 } else {
46 let fresh_base = dc.id.0.wrapping_mul(0x517cc1b727220a95).wrapping_add(0xFFFF_0000_0000_0000);
49 let fresh_vars: Vec<VarId> = (0..arity)
50 .map(|i| VarId(fresh_base.wrapping_add(i as u64)))
51 .collect();
52
53 let var_indices: Vec<usize> = fresh_vars
55 .iter()
56 .map(|v| b.push(CoreFrame::Var(*v)))
57 .collect();
58 let mut inner = b.push(CoreFrame::Con {
59 tag: dc.id,
60 fields: var_indices,
61 });
62
63 for v in fresh_vars.iter().rev() {
65 inner = b.push(CoreFrame::Lam {
66 binder: *v,
67 body: inner,
68 });
69 }
70
71 body = b.push(CoreFrame::LetNonRec {
72 binder,
73 rhs: inner,
74 body,
75 });
76 }
77 }
78
79 b.build()
80}