Performs an in-order traversal of the AST, assigning identifiers as it goes.
(
relation: &MirRelationExpr,
remap: &mut BTreeMap<LocalId, LocalId>,
id_gen: &mut IdGen,
)
| 959 | |
| 960 | /// Performs an in-order traversal of the AST, assigning identifiers as it goes. |
| 961 | fn determine( |
| 962 | relation: &MirRelationExpr, |
| 963 | remap: &mut BTreeMap<LocalId, LocalId>, |
| 964 | id_gen: &mut IdGen, |
| 965 | ) -> Result<(), crate::TransformError> { |
| 966 | // The stack contains pending work as `Result<LocalId, &MirRelationExpr>`, where |
| 967 | // 1. 'Ok(id)` means the identifier `id` is ready for renumbering, |
| 968 | // 2. `Err(expr)` means that the expression `expr` needs to be further processed. |
| 969 | let mut stack: Vec<Result<LocalId, _>> = vec![Err(relation)]; |
| 970 | while let Some(action) = stack.pop() { |
| 971 | match action { |
| 972 | Ok(id) => { |
| 973 | if remap.contains_key(&id) { |
| 974 | Err(crate::TransformError::Internal(format!( |
| 975 | "Shadowing of let binding for {:?}", |
| 976 | id |
| 977 | )))?; |
| 978 | } else { |
| 979 | remap.insert(id, LocalId::new(id_gen.allocate_id())); |
| 980 | } |
| 981 | } |
| 982 | Err(expr) => match expr { |
| 983 | MirRelationExpr::Let { id, value, body } => { |
| 984 | stack.push(Err(body)); |
| 985 | stack.push(Ok(*id)); |
| 986 | stack.push(Err(value)); |
| 987 | } |
| 988 | MirRelationExpr::LetRec { |
| 989 | ids, |
| 990 | values, |
| 991 | limits: _, |
| 992 | body, |
| 993 | } => { |
| 994 | stack.push(Err(body)); |
| 995 | for (id, value) in ids.iter().rev().zip_eq(values.iter().rev()) { |
| 996 | stack.push(Ok(*id)); |
| 997 | stack.push(Err(value)); |
| 998 | } |
| 999 | } |
| 1000 | _ => { |
| 1001 | stack.extend(expr.children().rev().map(Err)); |
| 1002 | } |
| 1003 | }, |
| 1004 | } |
| 1005 | } |
| 1006 | Ok(()) |
| 1007 | } |
| 1008 | |
| 1009 | fn implement( |
| 1010 | relation: &mut MirRelationExpr, |
no test coverage detected