nifty_interp/machine/
carry.rs1use nifty_check::hir::{Program, StateDef, StructId, Type};
5
6use super::Machine;
7use crate::value::Value;
8
9pub(super) fn kept_value(previous: &Machine, state: &StateDef, next: &Program) -> Option<Value> {
11 let program = &previous.program;
12 let index = program
13 .states
14 .iter()
15 .position(|old| old.name == state.name)?;
16 let mut types = SameTypes {
17 old: program,
18 new: next,
19 assumed: Vec::new(),
20 };
21 types
22 .same(&program.states[index].ty, &state.ty)
23 .then(|| previous.states.borrow()[index].clone())
24}
25
26struct SameTypes<'a> {
28 old: &'a Program,
29 new: &'a Program,
30 assumed: Vec<(StructId, StructId)>,
32}
33
34impl SameTypes<'_> {
35 fn same(&mut self, old: &Type, new: &Type) -> bool {
36 match (old, new) {
37 (Type::Int, Type::Int)
38 | (Type::Float, Type::Float)
39 | (Type::Bool, Type::Bool)
40 | (Type::String, Type::String) => true,
41 (Type::List(old), Type::List(new)) => self.same(old, new),
42 (Type::Struct(old), Type::Struct(new)) => self.same_struct(*old, *new),
43 _ => false,
44 }
45 }
46
47 fn same_struct(&mut self, old_id: StructId, new_id: StructId) -> bool {
48 if self.assumed.contains(&(old_id, new_id)) {
49 return true;
50 }
51 let (old, new) = (self.old, self.new);
52 let old = &old.structs[old_id.0];
53 let new = &new.structs[new_id.0];
54 if old.name != new.name || old.fields.len() != new.fields.len() {
55 return false;
56 }
57 self.assumed.push((old_id, new_id));
58 let same = old
59 .fields
60 .iter()
61 .zip(&new.fields)
62 .all(|(old, new)| old.name == new.name && self.same(&old.ty, &new.ty));
63 self.assumed.pop();
64 same
65 }
66}