@ -44,31 +44,48 @@ type reversed
type not_reversed
type not_reversed
type ' rev t =
(* * [Empty] and [Singleton _] can have both directions. We do not attempt to make the representation
canonic , e . g . [ NotReversed \ [| | \ ] ] , [ Reversed \ [| | \ ] ] , and [ Empty ] are all allowed despite
representing the same value . * )
type _ t =
| NotReversed : Sil . instr Array . t -> not_reversed t
| NotReversed : Sil . instr Array . t -> not_reversed t
| Reversed : Sil . instr RevArray . t -> reversed t
| Reversed : Sil . instr RevArray . t -> reversed t
| Empty : _ t
| Singleton : Sil . instr -> _ t
type not_reversed_t = not_reversed t
type not_reversed_t = not_reversed t
(* Some functions are only used on non-reversed arrays, let's specialize them.
(* * {2 Functions on non-reversed arrays}
The argument of the type helps us make sure they can't be used otherwise . * )
(* Functions on non-reversed arrays *)
let of_array instrs = NotReversed instrs
Some functions are only used on non - reversed arrays , let ' s specialize them . The argument of the
type helps us make sure they can't be used otherwise . * )
let get_underlying_not_reversed = function NotReversed instrs -> instrs
let get_underlying_not_reversed = function
| NotReversed instrs ->
instrs
| Empty ->
[| |]
| Singleton instr ->
[| instr |]
let empty = Empty
let empty = of_array [| |]
let singleton instr = Singleton instr
let singleton instr = of_array [| instr |]
let append_list t list =
let instrs = get_underlying_not_reversed t in
NotReversed ( Array . append instrs ( Array . of_list list ) )
let append_list ( NotReversed instrs ) list = NotReversed ( Array . append instrs ( Array . of_list list ) )
let of_list l = NotReversed ( Array . of_list l )
let of_list l = NotReversed ( Array . of_list l )
let of_rev_list l = NotReversed ( Array . of_list_rev l )
let of_rev_list l = NotReversed ( Array . of_list_rev l )
let filter_map ( NotReversed instrs ) ~ f = NotReversed ( Array . filter_map instrs ~ f )
let filter_map t ~ f =
let instrs = get_underlying_not_reversed t in
NotReversed ( Array . filter_map instrs ~ f )
let map_and_fold =
let map_and_fold =
let rec aux_changed arr ~ f current i =
let rec aux_changed arr ~ f current i =
@ -90,17 +107,19 @@ let map_and_fold =
Array . unsafe_set arr i e' ;
Array . unsafe_set arr i e' ;
aux_changed arr ~ f next ( i + 1 )
aux_changed arr ~ f next ( i + 1 )
in
in
fun ( NotReversed instrs as t ) ~ f ~ init ->
fun t ~ f ~ init ->
let instrs = get_underlying_not_reversed t in
let instrs' = aux_unchanged instrs ~ f init 0 in
let instrs' = aux_unchanged instrs ~ f init 0 in
if phys_equal instrs instrs' then t else NotReversed instrs'
if phys_equal instrs instrs' then t else NotReversed instrs'
let map ( NotReversed _ instrs as t ) ~ f =
let map ( t : not_reversed t ) ~ f =
let f () e = ( () , f e ) in
let f () e = ( () , f e ) in
map_and_fold t ~ f ~ init : ()
map_and_fold t ~ f ~ init : ()
let concat_map ( NotReversed instrs as t ) ~ f =
let concat_map t ~ f =
let instrs = get_underlying_not_reversed t in
let instrs' = Array . concat_map ~ f instrs in
let instrs' = Array . concat_map ~ f instrs in
if
if
Int . equal ( Array . length instrs ) ( Array . length instrs' )
Int . equal ( Array . length instrs ) ( Array . length instrs' )
@ -109,12 +128,19 @@ let concat_map (NotReversed instrs as t) ~f =
else NotReversed instrs'
else NotReversed instrs'
let reverse_order ( NotReversed instrs ) = Reversed ( RevArray . of_rev_array instrs )
let reverse_order t =
let instrs = get_underlying_not_reversed t in
Reversed ( RevArray . of_rev_array instrs )
(* Functions on both reversed and non-reversed arrays *)
(* Functions on both reversed and non-reversed arrays *)
let is_empty ( type r ) ( t : r t ) =
let is_empty ( type r ) ( t : r t ) =
match t with
match t with
| Empty ->
true
| Singleton _ ->
false
| NotReversed instrs ->
| NotReversed instrs ->
Array . is_empty instrs
Array . is_empty instrs
| Reversed rev_instrs ->
| Reversed rev_instrs ->
@ -123,6 +149,10 @@ let is_empty (type r) (t : r t) =
let fold ( type r ) ( t : r t ) ~ init ~ f =
let fold ( type r ) ( t : r t ) ~ init ~ f =
match t with
match t with
| Empty ->
init
| Singleton instr ->
f init instr
| NotReversed instrs ->
| NotReversed instrs ->
Array . fold instrs ~ init ~ f
Array . fold instrs ~ init ~ f
| Reversed rev_instrs ->
| Reversed rev_instrs ->
@ -137,6 +167,10 @@ let for_all t ~f = Container.for_all ~iter t ~f
let count ( type r ) ( t : r t ) =
let count ( type r ) ( t : r t ) =
match t with
match t with
| Empty ->
0
| Singleton _ ->
1
| NotReversed instrs ->
| NotReversed instrs ->
Array . length instrs
Array . length instrs
| Reversed rev_instrs ->
| Reversed rev_instrs ->
@ -147,6 +181,10 @@ let nth_exists t index = index < count t
let nth_exn ( type r ) ( t : r t ) index =
let nth_exn ( type r ) ( t : r t ) index =
match t with
match t with
| Empty ->
[| |] . ( index )
| Singleton instr ->
[| instr |] . ( index )
| NotReversed instrs ->
| NotReversed instrs ->
instrs . ( index )
instrs . ( index )
| Reversed rev_instrs ->
| Reversed rev_instrs ->
@ -155,6 +193,10 @@ let nth_exn (type r) (t : r t) index =
let last ( type r ) ( t : r t ) =
let last ( type r ) ( t : r t ) =
match t with
match t with
| Empty ->
None
| Singleton instr ->
Some instr
| NotReversed instrs ->
| NotReversed instrs ->
if is_empty t then None else Some ( Array . last instrs )
if is_empty t then None else Some ( Array . last instrs )
| Reversed rev_instrs ->
| Reversed rev_instrs ->