hax_rust_engine/
resugarings.rs1use crate::ast::identifiers::GlobalId;
8use crate::ast::resugared::*;
9use crate::ast::visitors::*;
10use crate::ast::*;
11use crate::printer::*;
12
13#[derive(Copy, Clone, Default)]
17pub struct FunctionsToConstants;
18
19impl AstVisitorMut for FunctionsToConstants {
20 fn enter_item_kind(&mut self, item_kind: &mut ItemKind) {
21 let ItemKind::Fn {
22 name,
23 generics,
24 body,
25 params,
26 safety: SafetyKind::Safe,
27 } = item_kind
28 else {
29 return;
30 };
31 if !params.is_empty() {
32 return;
33 }
34 *item_kind = ItemKind::Resugared(ResugaredItemKind::Constant {
35 name: *name,
36 body: body.clone(),
37 generics: generics.clone(),
38 });
39 }
40 fn enter_impl_item_kind(&mut self, item_kind: &mut ImplItemKind) {
41 if let ImplItemKind::Fn { body, params } = item_kind
42 && params.is_empty()
43 {
44 *item_kind =
45 ImplItemKind::Resugared(ResugaredImplItemKind::Constant { body: body.clone() })
46 }
47 }
48}
49
50impl Resugaring for FunctionsToConstants {
51 fn name(&self) -> String {
52 "functions-to-constants".to_string()
53 }
54}
55
56pub struct Tuples;
59
60impl AstVisitorMut for Tuples {
61 fn enter_expr_kind(&mut self, x: &mut ExprKind) {
62 let (constructor, fields) = match x {
63 ExprKind::Construct {
64 constructor,
65 is_record: false,
66 is_struct: true,
67 base: None,
68 fields,
69 } => (constructor, &fields[..]),
70 ExprKind::GlobalId(constructor) => (constructor, &[][..]),
71 _ => return,
72 };
73 if constructor.expect_tuple().is_some() {
74 let args = fields.iter().map(|(_, e)| e).cloned().collect();
75 *x = ExprKind::Resugared(ResugaredExprKind::Tuple(args))
76 }
77 }
78 fn enter_ty_kind(&mut self, x: &mut TyKind) {
79 let TyKind::App { head, args } = x else {
80 return;
81 };
82 if head.expect_tuple().is_some() {
83 let Some(args) = args
84 .iter()
85 .map(GenericValue::expect_ty)
86 .collect::<Option<Vec<_>>>()
87 else {
88 return;
89 };
90 *x = TyKind::Resugared(ResugaredTyKind::Tuple(args.into_iter().cloned().collect()))
91 }
92 }
93}
94
95impl Resugaring for Tuples {
96 fn name(&self) -> String {
97 "tuples".to_string()
98 }
99}
100
101pub struct LetPure;
104
105impl AstVisitorMut for LetPure {
106 fn enter_expr_kind(&mut self, expr: &mut ExprKind) {
107 const PURE: GlobalId = crate::names::rust_primitives::hax::explicit_monadic::pure;
108 if let ExprKind::Let { lhs, rhs, body } = expr
109 && let ExprKind::App {
110 head,
111 args,
112 generic_args,
113 bounds_impls,
114 trait_: None,
115 } = rhs.kind()
116 && *head.kind() == ExprKind::GlobalId(PURE)
117 && let ([pure_rhs], [], []) = (&args[..], &generic_args[..], &bounds_impls[..])
118 {
119 *expr = ExprKind::Resugared(ResugaredExprKind::LetPure {
120 lhs: lhs.clone(),
121 rhs: pure_rhs.clone(),
122 body: body.clone(),
123 })
124 }
125 }
126}
127
128impl Resugaring for LetPure {
129 fn name(&self) -> String {
130 "let_pure".to_string()
131 }
132}
133
134#[derive(Copy, Clone, Default)]
137pub struct RecursiveFunctions;
138
139struct SelfReferenceChecker {
142 target: GlobalId,
143 found: bool,
144}
145
146impl AstVisitor for SelfReferenceChecker {
147 fn enter_expr_kind(&mut self, kind: &ExprKind) {
148 if let ExprKind::GlobalId(id) = kind
149 && *id == self.target
150 {
151 self.found = true;
152 }
153 }
154}
155
156impl AstVisitorMut for RecursiveFunctions {
157 fn visit_item_kind(&mut self, item_kind: &mut ItemKind) {
158 if let ItemKind::Fn {
159 name,
160 generics,
161 body,
162 params,
163 safety,
164 } = &*item_kind
165 {
166 let mut checker = SelfReferenceChecker {
167 target: *name,
168 found: false,
169 };
170 checker.visit_expr(body);
171 if checker.found {
172 *item_kind = ItemKind::Resugared(ResugaredItemKind::RecursiveFn {
173 name: *name,
174 generics: generics.clone(),
175 body: body.clone(),
176 params: params.clone(),
177 safety: safety.clone(),
178 });
179 }
180 }
181 }
182}
183
184impl Resugaring for RecursiveFunctions {
185 fn name(&self) -> String {
186 "recursive-functions".to_string()
187 }
188}
189
190pub struct RecordEllipsis;
194
195impl AstVisitorMut for RecordEllipsis {
196 fn enter_pat_kind(&mut self, x: &mut PatKind) {
197 let PatKind::Construct {
198 constructor,
199 is_record: true,
200 is_struct,
201 fields,
202 } = x
203 else {
204 return;
205 };
206 let non_wild: Vec<_> = fields
207 .iter()
208 .filter(|(_, pat)| !matches!(&*pat.kind, PatKind::Wild))
209 .cloned()
210 .collect();
211 if non_wild.len() < fields.len() {
212 *x = ResugaredPatKind::ConstructWithEllipsis {
213 constructor: *constructor,
214 is_struct: *is_struct,
215 fields: non_wild,
216 }
217 .into();
218 }
219 }
220}
221
222impl Resugaring for RecordEllipsis {
223 fn name(&self) -> String {
224 "record-ellipsis".to_string()
225 }
226}