|  |  | @ -142,58 +142,56 @@ let rec is_constant e = | 
			
		
	
		
		
			
				
					
					|  |  |  |       Qset.for_all ~f:(fun arg _ -> is_constant arg) args |  |  |  |       Qset.for_all ~f:(fun arg _ -> is_constant arg) args | 
			
		
	
		
		
			
				
					
					|  |  |  |   | Label _ | Float _ | Integer _ -> true |  |  |  |   | Label _ | Float _ | Integer _ -> true | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | let rec solve_ e f s = | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   let extend ~trm ~rep (us, xs, s) = | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     Some (us, xs, Subst.compose1 ~key:trm ~data:rep s) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   in | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   let fresh name (us, xs, s) = | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     let x, us = Var.fresh name ~wrt:us in | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     let xs = Set.add xs x in | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     (Term.var x, (us, xs, s)) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   in | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   let solve_uninterp e f = | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     match ((e : Term.t), (f : Term.t)) with | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     | Integer {data= m}, Integer {data= n} when not (Z.equal m n) -> None | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     | _ -> ( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       match (is_constant e, is_constant f) with | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       (* orient equation to discretionarily prefer term that is constant or | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          compares smaller as class representative *) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       | true, false -> extend ~trm:f ~rep:e s | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       | false, true -> extend ~trm:e ~rep:f s | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       | _ -> | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |           let trm, rep = if Term.compare e f > 0 then (e, f) else (f, e) in | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |           extend ~trm ~rep s ) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   in | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   let concat_size args = | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     Vector.fold_until args ~init:Term.zero | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       ~f:(fun sum m -> | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         match (m : Term.t) with | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         | Ap2 (Memory, siz, _) -> Continue (Term.add siz sum) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         | _ -> Stop None ) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       ~finish:(fun _ -> None) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   in | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   match ((e : Term.t), (f : Term.t)) with | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   | (Add _ | Mul _ | Integer _), _ | _, (Add _ | Mul _ | Integer _) -> ( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       let e_f = Term.sub e f in | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       match Term.solve_zero_eq e_f with | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       | Some (trm, rep) -> extend ~trm ~rep s | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       | None -> solve_uninterp e_f Term.zero ) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   | ApN (Concat, ms), ApN (Concat, ns) -> ( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     match (concat_size ms, concat_size ns) with | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     | Some p, Some q -> solve_uninterp e f >>= solve_ p q | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     | _ -> solve_uninterp e f ) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   | Ap2 (Memory, m, _), ApN (Concat, ns) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |    |ApN (Concat, ns), Ap2 (Memory, m, _) -> ( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     match concat_size ns with | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     | Some p -> solve_uninterp e f >>= solve_ p m | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     | _ -> solve_uninterp e f ) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   | _ -> solve_uninterp e f | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | let solve ~us ~xs e f = |  |  |  | let solve ~us ~xs e f = | 
			
		
	
		
		
			
				
					
					|  |  |  |   [%Trace.call fun {pf} -> pf "%a@ %a" Term.pp e Term.pp f] |  |  |  |   [%Trace.call fun {pf} -> pf "%a@ %a" Term.pp e Term.pp f] | 
			
		
	
		
		
			
				
					
					|  |  |  |   ; |  |  |  |   ; | 
			
		
	
		
		
			
				
					
					|  |  |  |   let rec solve_ e f s = |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     let extend ~trm ~rep (us, xs, s) = |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       Some (us, xs, Subst.compose1 ~key:trm ~data:rep s) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     in |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     let fresh name (us, xs, s) = |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       let x, us = Var.fresh name ~wrt:us in |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       let xs = Set.add xs x in |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       (Term.var x, (us, xs, s)) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     in |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     let solve_uninterp e f = |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       match ((e : Term.t), (f : Term.t)) with |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       | Integer {data= m}, Integer {data= n} when not (Z.equal m n) -> None |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       | _ -> ( |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         match (is_constant e, is_constant f) with |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         (* orient equation to discretionarily prefer term that is constant |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |            or compares smaller as class representative *) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         | true, false -> extend ~trm:f ~rep:e s |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         | false, true -> extend ~trm:e ~rep:f s |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         | _ -> |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             let trm, rep = |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |               if Term.compare e f > 0 then (e, f) else (f, e) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             in |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             extend ~trm ~rep s ) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     in |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     let concat_size args = |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       Vector.fold_until args ~init:Term.zero |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         ~f:(fun sum m -> |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |           match (m : Term.t) with |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |           | Ap2 (Memory, siz, _) -> Continue (Term.add siz sum) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |           | _ -> Stop None ) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         ~finish:(fun _ -> None) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     in |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     match ((e : Term.t), (f : Term.t)) with |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     | (Add _ | Mul _ | Integer _), _ | _, (Add _ | Mul _ | Integer _) -> ( |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         let e_f = Term.sub e f in |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         match Term.solve_zero_eq e_f with |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         | Some (trm, rep) -> extend ~trm ~rep s |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         | None -> solve_uninterp e_f Term.zero ) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     | ApN (Concat, ms), ApN (Concat, ns) -> ( |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       match (concat_size ms, concat_size ns) with |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       | Some p, Some q -> solve_uninterp e f >>= solve_ p q |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       | _ -> solve_uninterp e f ) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     | Ap2 (Memory, m, _), ApN (Concat, ns) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |      |ApN (Concat, ns), Ap2 (Memory, m, _) -> ( |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       match concat_size ns with |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       | Some p -> solve_uninterp e f >>= solve_ p m |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       | _ -> solve_uninterp e f ) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     | _ -> solve_uninterp e f |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   in |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   (solve_ e f (us, xs, Subst.empty) >>| fun (_, xs, s) -> (xs, s)) |  |  |  |   (solve_ e f (us, xs, Subst.empty) >>| fun (_, xs, s) -> (xs, s)) | 
			
		
	
		
		
			
				
					
					|  |  |  |   |> |  |  |  |   |> | 
			
		
	
		
		
			
				
					
					|  |  |  |   [%Trace.retn fun {pf} -> |  |  |  |   [%Trace.retn fun {pf} -> | 
			
		
	
	
		
		
			
				
					|  |  | 
 |