[sledge] Strengthen and simplify canonizer for Extract terms

Summary:
Formulate the canonizer for Extract from Concat terms uniformly as a
concatenation of extracts.

Reviewed By: jvillard

Differential Revision: D20303064

fbshipit-source-id: a45bc45dd
master
Josh Berdine 5 years ago committed by Facebook Github Bot
parent c6237f5f9f
commit 37ddf95a49

@ -101,6 +101,14 @@ let fold_map x ~init ~f =
let s, x = Array.fold_map (a x) ~init ~f in let s, x = Array.fold_map (a x) ~init ~f in
(s, v x) (s, v x)
let fold_map_until xs ~init ~f ~finish =
With_return.with_return (fun {return} ->
finish
(fold_map xs ~init ~f:(fun s x ->
match (f s x : _ Continue_or_stop.t) with
| Continue x -> x
| Stop x -> return x )) )
let concat xs = v (Array.concat (al xs)) let concat xs = v (Array.concat (al xs))
let copy x = v (Array.copy (a x)) let copy x = v (Array.copy (a x))
let sub ~pos ~len x = v (Array.sub ~pos ~len (a x)) let sub ~pos ~len x = v (Array.sub ~pos ~len (a x))

@ -108,6 +108,14 @@ val map_preserving_phys_equal : 'a t -> f:('a -> 'a) -> 'a t
(* val folding_map : 'a t -> init:'b -> f:('b -> 'a -> 'b * 'c) -> 'c t *) (* val folding_map : 'a t -> init:'b -> f:('b -> 'a -> 'b * 'c) -> 'c t *)
(* val folding_mapi : 'a t -> init:'b -> f:(int -> 'b -> 'a -> 'b * 'c) -> (* val folding_mapi : 'a t -> init:'b -> f:(int -> 'b -> 'a -> 'b * 'c) ->
'c t *) 'c t *)
val fold_map_until :
'a t
-> init:'accum
-> f:('accum -> 'a -> ('accum * 'b, 'final) Continue_or_stop.t)
-> finish:('accum * 'b t -> 'final)
-> 'final
val fold_map : 'a t -> init:'b -> f:('b -> 'a -> 'b * 'c) -> 'b * 'c t val fold_map : 'a t -> init:'b -> f:('b -> 'a -> 'b * 'c) -> 'b * 'c t
(* val fold_mapi : (* val fold_mapi :

@ -720,61 +720,45 @@ let rec simp_extract agg off len =
simp_memory len e simp_memory len e
(* ⟨n,a⟩[0,n) ==> ⟨n,a⟩ *) (* ⟨n,a⟩[0,n) ==> ⟨n,a⟩ *)
| Ap2 (Memory, n, _) when equal off zero && equal n len -> agg | Ap2 (Memory, n, _) when equal off zero && equal n len -> agg
(* (α₀^…^αᵢ^…^αⱼ^…) [0+n₀+…+nᵢ₋₁, nᵢ+…+nⱼ) ==> αᵢ^…^αⱼ where nₓ ≡ |αₓ| *) (* For (α₀^α₁)[o,l) there are 3 cases:
| ApN (Concat, na1N) -> *
let n = Vector.length na1N in * ...^...
(* invariant: oI = ∑ᵥ₌₀ⁱ⁻¹ nᵥ *) * [,)
let rec find_off oI i = * o < o+l |α| : (α^α)[o,l) ==> α[o,l) ^ α[0,0)
[%Trace.call fun {pf} -> pf "o_0^%i = %a" i pp oI] *
; * ...^...
( if i = n then Ap3 (Extract, agg, off, len) * [ , )
else * o |α| < o+l : (α^α)[o,l) ==> α[o,|α|-o) ^ α[0,l-(|α|-o))
match Vector.get na1N i with *
| Ap2 (Memory, nI, _) | Ap3 (Extract, _, _, nI) -> ( * ...^...
match (oI, off) with * [,)
| Integer {data= y}, Integer {data= z} when Z.gt y z -> * |α| o : (α^α)[o,l) ==> α[o,0) ^ α[o-|α|,l)
Ap3 (Extract, agg, off, len) *
| _ when not (equal oI off) -> * So in general:
find_off (simp_add2 oI nI) (i + 1) *
| _ -> * (α^α)[o,l) ==> α[o,l) ^ α[o,l-l)
(* invariant: lIJ = ∑ᵥ₌ᵢʲ⁻¹ nᵥ *) * where l = max 0 (min l |α|-o)
let rec find_len lIJ j = * o = max 0 o-|α|
[%Trace.call fun {pf} -> pf "l_%i^%i = %a" i j pp lIJ] *)
; | ApN (Concat, na1N) -> (
( if j = n then find_off (simp_add2 oI nI) (i + 1) match len with
| Integer {data= l} ->
Vector.fold_map_until na1N ~init:(l, off)
~f:(fun (l, oI) naI ->
let nI = agg_size_exn naI in
if Z.equal Z.zero l then
Continue ((l, oI), simp_extract naI oI zero)
else else
match Vector.get na1N j with let oI_nI = simp_sub oI nI in
| Ap2 (Memory, nJ, _) | Ap3 (Extract, _, _, nJ) -> ( match oI_nI with
let lIJ = simp_add2 lIJ nJ in | Integer {data} ->
match (lIJ, len) with let oJ = if Z.sign data <= 0 then zero else oI_nI in
(* (α₀^…^αᵢ^…) [0+n₀+…+nᵢ₋₁, l) ==> (αᵢ^…)[0,l) let lI = Z.(max zero (min l (neg data))) in
where n |α| *) let l = Z.(l - lI) in
| Integer {data= y}, Integer {data= z} Continue ((l, oJ), simp_extract naI oI (integer lI))
when Z.gt y z -> | _ -> Stop (Ap3 (Extract, agg, off, len)) )
let naIN = ~finish:(fun (_, e1N) -> simp_concat e1N)
Vector.sub ~pos:i ~len:(n - i) na1N | _ -> Ap3 (Extract, agg, off, len) )
in
simp_extract (simp_concat naIN) zero len
| Integer {data= y}, Integer {data= z}
when Z.gt y z ->
Ap3 (Extract, agg, off, len)
| _ when not (equal lIJ len) ->
find_len lIJ (j + 1)
| _ ->
let naIJ =
Vector.sub ~pos:i ~len:(j - i + 1) na1N
in
simp_concat naIJ )
| _ -> violates invariant agg )
|>
[%Trace.retn fun {pf} -> pf "%a" pp]
in
find_len zero i )
| _ -> violates invariant agg )
|>
[%Trace.retn fun {pf} -> pf "%a" pp]
in
find_off zero 0
(* α[o,l) *) (* α[o,l) *)
| _ -> Ap3 (Extract, agg, off, len) ) | _ -> Ap3 (Extract, agg, off, len) )
|> |>

Loading…
Cancel
Save