|  |  | @ -11,72 +11,32 @@ open! Utils | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | module F = Format |  |  |  | module F = Format | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | type base = Var.t * Typ.t |  |  |  | type _array_sensitive_typ = Typ.t | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | let compare__array_sensitive_typ = Typ.array_sensitive_compare | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | type base = Var.t * _array_sensitive_typ [@@deriving compare] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | let equal_base base1 base2 = | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   compare_base base1 base2 = 0 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | type access = |  |  |  | type access = | 
			
		
	
		
		
			
				
					
					|  |  |  |   | FieldAccess of Ident.fieldname * Typ.t |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   | ArrayAccess of Typ.t |  |  |  |   | ArrayAccess of Typ.t | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   | FieldAccess of Ident.fieldname * Typ.t | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | [@@deriving compare] | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | type raw = base * access list |  |  |  | let equal_access access1 access2 = | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |   compare_access access1 access2 = 0 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | type t = |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   | Exact of raw |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   | Abstracted of raw |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | let base_compare ((var1, typ1) as base1) ((var2, typ2) as base2) = |  |  |  | type raw = base * access list [@@deriving compare] | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   if base1 == base2 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   then 0 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   else |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     let n = Var.compare var1 var2 in |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     if n <> 0 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     then n |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     else Typ.array_sensitive_compare typ1 typ2 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | let base_equal base1 base2 = |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   base_compare base1 base2 = 0 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | let access_compare access1 access2 = |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   if access1 == access2 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   then |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     0 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   else |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     match access1, access2 with |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     | FieldAccess (f1, typ1), FieldAccess (f2, typ2) -> |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         let n = Ident.compare_fieldname f1 f2 in |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         if n <> 0 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         then n |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         else Typ.compare typ1 typ2 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     | ArrayAccess typ1, ArrayAccess typ2 -> |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         Typ.compare typ1 typ2 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     | FieldAccess _, _ -> 1 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     | _, FieldAccess _ -> -1 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | let access_equal access1 access2 = |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   access_compare access1 access2 = 0 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | let raw_compare ((base1, accesses1) as ap1) ((base2, accesses2) as ap2) = |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   if ap1 == ap2 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   then 0 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   else |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     let n = base_compare base1 base2 in |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     if n <> 0 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     then n |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     else if accesses1 == accesses2 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     then 0 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     else IList.compare access_compare accesses1 accesses2 |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | let raw_equal ap1 ap2 = |  |  |  | let equal_raw ap1 ap2 = | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   raw_compare ap1 ap2 = 0 |  |  |  |   compare_raw ap1 ap2 = 0 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | let compare ap1 ap2 = |  |  |  | type t = | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   if ap1 == ap2 |  |  |  |   | Abstracted of raw | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   then |  |  |  |   | Exact of raw | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     0 |  |  |  | [@@deriving compare] | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   else |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     match ap1, ap2 with |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     | Exact ap1, Exact ap2 | Abstracted ap1, Abstracted ap2 -> raw_compare ap1 ap2 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     | Exact _, Abstracted _ -> 1 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     | Abstracted _, Exact _ -> (-1) |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | let equal ap1 ap2 = |  |  |  | let equal ap1 ap2 = | 
			
		
	
		
		
			
				
					
					|  |  |  |   compare ap1 ap2 = 0 |  |  |  |   compare ap1 ap2 = 0 | 
			
		
	
	
		
		
			
				
					|  |  | @ -151,13 +111,13 @@ let rec is_prefix_path path1 path2 = | 
			
		
	
		
		
			
				
					
					|  |  |  |     match path1, path2 with |  |  |  |     match path1, path2 with | 
			
		
	
		
		
			
				
					
					|  |  |  |     | [], _ -> true |  |  |  |     | [], _ -> true | 
			
		
	
		
		
			
				
					
					|  |  |  |     | _, [] -> false |  |  |  |     | _, [] -> false | 
			
		
	
		
		
			
				
					
					|  |  |  |     | access1 :: p1, access2 :: p2 -> access_equal access1 access2 && is_prefix_path p1 p2 |  |  |  |     | access1 :: p1, access2 :: p2 -> equal_access access1 access2 && is_prefix_path p1 p2 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | let is_prefix ((base1, path1) as ap1) ((base2, path2) as ap2) = |  |  |  | let is_prefix ((base1, path1) as ap1) ((base2, path2) as ap2) = | 
			
		
	
		
		
			
				
					
					|  |  |  |   if ap1 == ap2 |  |  |  |   if ap1 == ap2 | 
			
		
	
		
		
			
				
					
					|  |  |  |   then true |  |  |  |   then true | 
			
		
	
		
		
			
				
					
					|  |  |  |   else |  |  |  |   else | 
			
		
	
		
		
			
				
					
					|  |  |  |     base_equal base1 base2 && is_prefix_path path1 path2 |  |  |  |     equal_base base1 base2 && is_prefix_path path1 path2 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | let extract = function |  |  |  | let extract = function | 
			
		
	
		
		
			
				
					
					|  |  |  |   | Exact ap | Abstracted ap -> ap |  |  |  |   | Exact ap | Abstracted ap -> ap | 
			
		
	
	
		
		
			
				
					|  |  | @ -169,7 +129,7 @@ let is_exact = function | 
			
		
	
		
		
			
				
					
					|  |  |  | let (<=) ~lhs ~rhs = |  |  |  | let (<=) ~lhs ~rhs = | 
			
		
	
		
		
			
				
					
					|  |  |  |   match lhs, rhs with |  |  |  |   match lhs, rhs with | 
			
		
	
		
		
			
				
					
					|  |  |  |   | Abstracted _, Exact _ -> false |  |  |  |   | Abstracted _, Exact _ -> false | 
			
		
	
		
		
			
				
					
					|  |  |  |   | Exact lhs_ap, Exact rhs_ap -> raw_equal lhs_ap rhs_ap |  |  |  |   | Exact lhs_ap, Exact rhs_ap -> equal_raw lhs_ap rhs_ap | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   | (Exact lhs_ap | Abstracted lhs_ap), Abstracted rhs_ap -> is_prefix rhs_ap lhs_ap |  |  |  |   | (Exact lhs_ap | Abstracted lhs_ap), Abstracted rhs_ap -> is_prefix rhs_ap lhs_ap | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | let pp_base fmt (pvar, _) = |  |  |  | let pp_base fmt (pvar, _) = | 
			
		
	
	
		
		
			
				
					|  |  | @ -193,12 +153,12 @@ let pp fmt = function | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | module BaseMap = PrettyPrintable.MakePPMap(struct |  |  |  | module BaseMap = PrettyPrintable.MakePPMap(struct | 
			
		
	
		
		
			
				
					
					|  |  |  |     type t = base |  |  |  |     type t = base | 
			
		
	
		
		
			
				
					
					|  |  |  |     let compare = base_compare |  |  |  |     let compare = compare_base | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     let pp_key = pp_base |  |  |  |     let pp_key = pp_base | 
			
		
	
		
		
			
				
					
					|  |  |  |   end) |  |  |  |   end) | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | module AccessMap = PrettyPrintable.MakePPMap(struct |  |  |  | module AccessMap = PrettyPrintable.MakePPMap(struct | 
			
		
	
		
		
			
				
					
					|  |  |  |     type t = access |  |  |  |     type t = access | 
			
		
	
		
		
			
				
					
					|  |  |  |     let compare = access_compare |  |  |  |     let compare = compare_access | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     let pp_key = pp_access |  |  |  |     let pp_key = pp_access | 
			
		
	
		
		
			
				
					
					|  |  |  |   end) |  |  |  |   end) | 
			
		
	
	
		
		
			
				
					|  |  | 
 |