1use crate::prelude::*;
17struct RestrictProofFlow {
18 restrict_fact: RestrictFact,
20 rhs_fn_set: FnSet,
22 known_fn_body: FnSetBody,
24 forall_params: ParamDefWithType,
26 forall_dom_facts: Vec<Fact>,
28 applied_fn_obj: Obj,
30}
31
32impl Runtime {
33 pub fn verify_restrict_fact_using_its_definition(
34 &mut self,
35 restrict_fact: &RestrictFact,
36 verify_state: &VerifyState,
37 ) -> Result<Option<StmtResult>, RuntimeError> {
38 self.restrict_step_0_verify_input_objects_well_defined(restrict_fact, verify_state)?;
39
40 let flow = match self.restrict_step_2_build_flow_from_env(restrict_fact)? {
41 Some(v) => v,
42 None => return Ok(None),
43 };
44
45 self.restrict_step_1_verify_forall_application_well_defined(&flow, verify_state)?;
46
47 if let Some(success) = self.restrict_step_2_1_try_return_set_shortcut(&flow) {
48 return Ok(Some(success));
49 }
50
51 self.restrict_step_2_2_prove_forall_membership_in_rhs_return_set(flow, verify_state)
52 }
53
54 fn restrict_wrap_verify_runtime_error(
55 restrict_fact: &RestrictFact,
56 cause: RuntimeError,
57 ) -> RuntimeError {
58 RuntimeError::from(VerifyRuntimeError(RuntimeErrorStruct::new(
59 Some(Fact::from(restrict_fact.clone()).into_stmt()),
60 String::new(),
61 restrict_fact.line_file.clone(),
62 Some(cause),
63 vec![],
64 )))
65 }
66
67 fn restrict_step_0_verify_input_objects_well_defined(
68 &mut self,
69 restrict_fact: &RestrictFact,
70 verify_state: &VerifyState,
71 ) -> Result<(), RuntimeError> {
72 self.verify_obj_well_defined_and_store_cache(&restrict_fact.obj, verify_state)
73 .map_err(|e| Self::restrict_wrap_verify_runtime_error(restrict_fact, e))?;
74 self.verify_obj_well_defined_and_store_cache(
75 &restrict_fact.obj_can_restrict_to_fn_set,
76 verify_state,
77 )
78 .map_err(|e| Self::restrict_wrap_verify_runtime_error(restrict_fact, e))?;
79 Ok(())
80 }
81
82 fn restrict_step_2_build_flow_from_env(
83 &mut self,
84 restrict_fact: &RestrictFact,
85 ) -> Result<Option<RestrictProofFlow>, RuntimeError> {
86 let rhs_fn_set = match &restrict_fact.obj_can_restrict_to_fn_set {
87 Obj::FnSet(v) => v.clone(),
88 _ => return Ok(None),
89 };
90
91 let known_fn_body =
92 self.restrict_step_2_get_known_fn_set_info(&restrict_fact.obj, restrict_fact)?;
93
94 let rhs_flat_param_names = self.restrict_collect_flat_param_names(&rhs_fn_set.body);
95 let known_flat_param_names = self.restrict_collect_flat_param_names(&known_fn_body);
96 if rhs_flat_param_names.len() != known_flat_param_names.len() {
97 return Ok(None);
98 }
99
100 let forall_params = self.restrict_build_forall_params_from_rhs(&rhs_fn_set.body);
101 let forall_dom_facts = self.restrict_build_forall_dom_facts_from_rhs(&rhs_fn_set.body);
102
103 let fn_head = match FnObjHead::given_an_atom_return_a_fn_obj_head(restrict_fact.obj.clone())
104 {
105 Some(v) => v,
106 None => return Ok(None),
107 };
108 let applied_fn_obj: Obj = FnObj::new(
109 fn_head,
110 self.restrict_build_full_application_arg_groups(&known_fn_body, &rhs_flat_param_names),
111 )
112 .into();
113
114 Ok(Some(RestrictProofFlow {
115 restrict_fact: restrict_fact.clone(),
116 rhs_fn_set,
117 known_fn_body,
118 forall_params,
119 forall_dom_facts,
120 applied_fn_obj,
121 }))
122 }
123
124 fn restrict_step_2_get_known_fn_set_info(
125 &self,
126 function: &Obj,
127 restrict_fact: &RestrictFact,
128 ) -> Result<FnSetBody, RuntimeError> {
129 match self.get_cloned_object_in_fn_set(function) {
130 Some(v) => Ok(v),
131 None => match self.get_cloned_object_in_fn_set_or_restrict(function) {
132 Some(v) => Ok(v),
133 None => Err(VerifyRuntimeError(RuntimeErrorStruct::new(
134 Some(Fact::from(restrict_fact.clone()).into_stmt()),
135 String::new(),
136 restrict_fact.line_file.clone(),
137 Some(
138 WellDefinedRuntimeError(RuntimeErrorStruct::new(
139 None,
140 format!(
141 "function `{}` belongs to what function set is unknown",
142 function.to_string()
143 ),
144 default_line_file(),
145 None,
146 vec![],
147 ))
148 .into(),
149 ),
150 vec![],
151 ))
152 .into()),
153 },
154 }
155 }
156
157 fn restrict_step_1_verify_forall_application_well_defined(
158 &mut self,
159 flow: &RestrictProofFlow,
160 verify_state: &VerifyState,
161 ) -> Result<(), RuntimeError> {
162 self.restrict_step_1_verify_by_local_param_def(flow, verify_state)?;
163 self.restrict_step_1_verify_under_rhs_dom_facts(flow, verify_state)?;
164 Ok(())
165 }
166
167 fn restrict_step_1_verify_by_local_param_def(
168 &mut self,
169 flow: &RestrictProofFlow,
170 _verify_state: &VerifyState,
171 ) -> Result<(), RuntimeError> {
172 self.verify_obj_well_defined_with_its_local_def(
173 flow.rhs_fn_set.body.params_def_with_set.clone(),
174 ParamObjType::Forall,
175 flow.applied_fn_obj.clone(),
176 )
177 .map_err(|e| Self::restrict_wrap_verify_runtime_error(&flow.restrict_fact, e))
178 }
179
180 fn restrict_step_1_verify_under_rhs_dom_facts(
181 &mut self,
182 flow: &RestrictProofFlow,
183 verify_state: &VerifyState,
184 ) -> Result<(), RuntimeError> {
185 let stub = ForallFact::new(
186 flow.forall_params.clone(),
187 flow.forall_dom_facts.clone(),
188 Vec::new(),
189 flow.restrict_fact.line_file.clone(),
190 )?;
191 self.run_in_local_env(|rt| {
192 rt.forall_assume_params_and_dom_in_current_env(&stub, verify_state)?;
193 rt.verify_obj_well_defined_and_store_cache(&flow.applied_fn_obj, verify_state)
194 })
195 .map_err(|e| Self::restrict_wrap_verify_runtime_error(&flow.restrict_fact, e))
196 }
197
198 fn restrict_step_2_1_try_return_set_shortcut(
199 &self,
200 flow: &RestrictProofFlow,
201 ) -> Option<StmtResult> {
202 if crate::verify::verify_equality_by_builtin_rules::objs_equal_by_display_string(
203 flow.known_fn_body.ret_set.as_ref(),
204 flow.rhs_fn_set.body.ret_set.as_ref(),
205 ) {
206 return Some(
207 (FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
208 flow.restrict_fact.clone().into(),
209 "restrict_fn_in: well-defined on narrowed domain; known fn_set already has same return_set"
210 .to_string(),
211 Vec::new(),
212 ))
213 .into(),
214 );
215 }
216 None
217 }
218
219 fn restrict_step_2_2_prove_forall_membership_in_rhs_return_set(
220 &mut self,
221 flow: RestrictProofFlow,
222 verify_state: &VerifyState,
223 ) -> Result<Option<StmtResult>, RuntimeError> {
224 let then_facts = vec![InFact::new(
225 flow.applied_fn_obj.clone(),
226 (*flow.rhs_fn_set.body.ret_set).clone(),
227 flow.restrict_fact.line_file.clone(),
228 )
229 .into()];
230
231 let forall = ForallFact::new(
232 flow.forall_params,
233 flow.forall_dom_facts,
234 then_facts,
235 flow.restrict_fact.line_file.clone(),
236 )?;
237
238 let forall_result = self.verify_forall_fact(&forall, verify_state)?;
239 if !forall_result.is_true() {
240 return Ok(None);
241 }
242 Ok(Some(
243 (FactualStmtSuccess::new_with_verified_by_builtin_rules_recording_stmt(
244 flow.restrict_fact.clone().into(),
245 "restrict_fn_in: forall on narrowed domain; outputs in stated return set"
246 .to_string(),
247 Vec::new(),
248 ))
249 .into(),
250 ))
251 }
252
253 fn restrict_collect_flat_param_names(&self, body: &FnSetBody) -> Vec<String> {
254 let mut out: Vec<String> = Vec::new();
255 for g in body.params_def_with_set.iter() {
256 for name in g.params.iter() {
257 out.push(name.clone());
258 }
259 }
260 out
261 }
262
263 fn restrict_build_forall_params_from_rhs(&self, rhs_body: &FnSetBody) -> ParamDefWithType {
264 let mut groups: Vec<ParamGroupWithParamType> = Vec::new();
265 for param_def_with_set in &rhs_body.params_def_with_set {
266 let param_type = ParamType::Obj(param_def_with_set.set_obj().clone());
267 groups.push(ParamGroupWithParamType::new(
268 param_def_with_set.params.clone(),
269 param_type,
270 ));
271 }
272 ParamDefWithType::new(groups)
273 }
274
275 fn restrict_build_forall_dom_facts_from_rhs(&self, rhs_body: &FnSetBody) -> Vec<Fact> {
276 let mut out: Vec<Fact> = Vec::new();
277 for dom_fact in rhs_body.dom_facts.iter() {
278 let chain: OrAndChainAtomicFact = dom_fact.clone();
279 out.push(chain.into());
280 }
281 out
282 }
283
284 fn restrict_build_full_application_arg_groups(
285 &self,
286 known_fn_body: &FnSetBody,
287 rhs_flat_param_names: &[String],
288 ) -> Vec<Vec<Box<Obj>>> {
289 let mut all_args: Vec<Box<Obj>> = Vec::new();
290 let mut index: usize = 0;
291 for param_group in known_fn_body.params_def_with_set.iter() {
292 for _ in param_group.params.iter() {
293 let rhs_param_name = rhs_flat_param_names[index].clone();
294 all_args.push(Box::new(obj_for_bound_param_in_scope(
295 rhs_param_name,
296 ParamObjType::Forall,
297 )));
298 index += 1;
299 }
300 }
301 vec![all_args]
302 }
303}