Skip to content

Commit c5c6db3

Browse files
authored
Merge pull request #1511 from GaloisInc/coq-primitives
Make scanl a SAWCore primitive
2 parents 295bf13 + d69e14d commit c5c6db3

File tree

12 files changed

+162
-19
lines changed

12 files changed

+162
-19
lines changed

cryptol-saw-core/saw/Cryptol.sawcore

+19
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,16 @@ seqZip a b m n =
403403
n)
404404
m;
405405

406+
zipSame : (a b : isort 0) -> (n : Nat) -> Vec n a -> Vec n b -> Vec n (a * b);
407+
zipSame a b n x y = gen n (a*b) (\ (i : Nat) -> (at n a x i, at n b y i));
408+
409+
seqZipSame : (a b : isort 0) -> (n : Num) -> seq n a -> seq n b -> seq n (a * b);
410+
seqZipSame a b n =
411+
Num#rec
412+
(\ (n : Num) -> seq n a -> seq n b -> seq n (a * b))
413+
(\ (n : Nat) -> zipSame a b n)
414+
(streamMap2 a b (a*b) (\ (x:a) -> \ (y:b) -> (x,y)))
415+
n;
406416

407417
--------------------------------------------------------------------------------
408418
-- Ring and Logic functions
@@ -1560,6 +1570,15 @@ ecFoldlPrime :
15601570
(n : Num) -> (a : sort 0) -> (b : isort 0) -> PEq a -> (a -> b -> a) -> a -> seq n b -> a;
15611571
ecFoldlPrime n a b pa = ecFoldl n a b;
15621572

1573+
-- scanl : {n, a, b} (a -> b -> a) -> a -> [n]b -> [1+n]a
1574+
ecScanl :
1575+
(n : Num) -> (a : sort 0) -> (b : sort 0) -> (a -> b -> a) -> a -> seq n b -> seq (tcAdd (TCNum 1) n) a;
1576+
ecScanl n a b f z =
1577+
Num#rec (\ (n : Num) -> seq n b -> seq (tcAdd (TCNum 1) n) a)
1578+
(\ (n:Nat) -> \ (xs : Vec n b) -> scanl b a n f z xs)
1579+
(\ (xs : Stream b) -> streamScanl b a f z xs)
1580+
n;
1581+
15631582
--------------------------------------------------------------------------------
15641583
-- Floating point primitives (TODO)
15651584

cryptol-saw-core/src/Verifier/SAW/Cryptol.hs

+8-4
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,7 @@ prelPrims =
812812
, ("parmap", flip scGlobalDef "Cryptol.ecParmap") -- {a, b, n} (Eq b, fin n) => (a -> b) -> [n]a -> [n]b
813813
, ("foldl", flip scGlobalDef "Cryptol.ecFoldl") -- {n, a, b} (fin n) => (a -> b -> a) -> a -> [n]b -> a
814814
, ("foldl'", flip scGlobalDef "Cryptol.ecFoldlPrime") -- {n, a, b} (fin n, Eq a) => (a -> b -> a) -> a -> [n]b -> a
815-
815+
, ("scanl", flip scGlobalDef "Cryptol.ecScanl") -- {n, a, b} (a -> b -> a) -> a -> [n]b -> [1+n]a
816816
, ("error", flip scGlobalDef "Cryptol.ecError") -- {at,len} (fin len) => [len][8] -> at -- Run-time error
817817
, ("random", flip scGlobalDef "Cryptol.ecRandom") -- {a} => [32] -> a -- Random values
818818
, ("trace", flip scGlobalDef "Cryptol.ecTrace") -- {n,a,b} [n][8] -> a -> b -> b
@@ -1483,10 +1483,14 @@ importComp sc env lenT elemT expr mss =
14831483
m <- importType sc env len
14841484
a <- importType sc env ty
14851485
(ys, n, b, argss, len') <- zipAll branches
1486-
zs <- scGlobalApply sc "Cryptol.seqZip" [a, b, m, n, xs, ys]
1487-
mn <- scGlobalApply sc "Cryptol.tcMin" [m, n]
14881486
ab <- scTupleType sc [a, b]
1489-
return (zs, mn, ab, args : argss, C.tMin len len')
1487+
if len == len' then
1488+
do zs <- scGlobalApply sc "Cryptol.seqZipSame" [a, b, m, xs, ys]
1489+
return (zs, m, ab, args : argss, len)
1490+
else
1491+
do zs <- scGlobalApply sc "Cryptol.seqZip" [a, b, m, n, xs, ys]
1492+
mn <- scGlobalApply sc "Cryptol.tcMin" [m, n]
1493+
return (zs, mn, ab, args : argss, C.tMin len len')
14901494
(xs, n, a, argss, lenT') <- zipAll mss
14911495
f <- lambdaTuples sc env elemT expr argss
14921496
b <- importType sc env elemT

deps/cryptol

Submodule cryptol updated 44 files

saw-core-coq/coq/generated/CryptolToCoq/CryptolPrimitivesForSAWCore.v

+10
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Import ListNotations.
1010
(** Post-preamble section specified by you *)
1111
From CryptolToCoq Require Import SAWCorePrelude.
1212
Import SAWCorePrelude.
13+
From CryptolToCoq Require Import SAWCorePreludeExtra.
1314

1415

1516
(** Code generated by saw-core-coq *)
@@ -185,6 +186,12 @@ Definition mlet : forall (a : Type), forall {Inh_a : SAWCoreScaffolding.Inhabite
185186
Definition seqZip : forall (a : Type), forall {Inh_a : SAWCoreScaffolding.Inhabited a}, forall (b : Type), forall {Inh_b : SAWCoreScaffolding.Inhabited b}, forall (m : Num), forall (n : Num), seq m a -> seq n b -> seq (tcMin m n) (prod a b) :=
186187
fun (a : Type) {Inh_a : SAWCoreScaffolding.Inhabited a} (b : Type) {Inh_b : SAWCoreScaffolding.Inhabited b} (m : Num) (n : Num) => CryptolPrimitivesForSAWCore.Num_rect (fun (m1 : Num) => seq m1 a -> seq n b -> seq (tcMin m1 n) (prod a b)) (fun (m1 : SAWCoreScaffolding.Nat) => CryptolPrimitivesForSAWCore.Num_rect (fun (n1 : Num) => SAWCoreVectorsAsCoqVectors.Vec m1 a -> seq n1 b -> seq (tcMin (TCNum m1) n1) (prod a b)) (fun (n1 : SAWCoreScaffolding.Nat) => SAWCorePrelude.zip a b m1 n1) (fun (xs : SAWCoreVectorsAsCoqVectors.Vec m1 a) (ys : SAWCorePrelude.Stream b) => SAWCoreVectorsAsCoqVectors.gen m1 (prod a b) (fun (i : SAWCoreScaffolding.Nat) => pair (SAWCorePrelude.sawAt m1 a xs i) (SAWCorePrelude.streamGet b ys i))) n) (CryptolPrimitivesForSAWCore.Num_rect (fun (n1 : Num) => SAWCorePrelude.Stream a -> seq n1 b -> seq (tcMin TCInf n1) (prod a b)) (fun (n1 : SAWCoreScaffolding.Nat) (xs : SAWCorePrelude.Stream a) (ys : SAWCoreVectorsAsCoqVectors.Vec n1 b) => SAWCoreVectorsAsCoqVectors.gen n1 (prod a b) (fun (i : SAWCoreScaffolding.Nat) => pair (SAWCorePrelude.streamGet a xs i) (SAWCorePrelude.sawAt n1 b ys i))) (SAWCorePrelude.streamMap2 a b (prod a b) (fun (x : a) (y : b) => pair x y)) n) m.
187188

189+
Definition zipSame : forall (a : Type), forall {Inh_a : SAWCoreScaffolding.Inhabited a}, forall (b : Type), forall {Inh_b : SAWCoreScaffolding.Inhabited b}, forall (n : SAWCoreScaffolding.Nat), SAWCoreVectorsAsCoqVectors.Vec n a -> SAWCoreVectorsAsCoqVectors.Vec n b -> SAWCoreVectorsAsCoqVectors.Vec n (prod a b) :=
190+
fun (a : Type) {Inh_a : SAWCoreScaffolding.Inhabited a} (b : Type) {Inh_b : SAWCoreScaffolding.Inhabited b} (n : SAWCoreScaffolding.Nat) (x : SAWCoreVectorsAsCoqVectors.Vec n a) (y : SAWCoreVectorsAsCoqVectors.Vec n b) => SAWCoreVectorsAsCoqVectors.gen n (prod a b) (fun (i : SAWCoreScaffolding.Nat) => pair (SAWCorePrelude.sawAt n a x i) (SAWCorePrelude.sawAt n b y i)).
191+
192+
Definition seqZipSame : forall (a : Type), forall {Inh_a : SAWCoreScaffolding.Inhabited a}, forall (b : Type), forall {Inh_b : SAWCoreScaffolding.Inhabited b}, forall (n : Num), seq n a -> seq n b -> seq n (prod a b) :=
193+
fun (a : Type) {Inh_a : SAWCoreScaffolding.Inhabited a} (b : Type) {Inh_b : SAWCoreScaffolding.Inhabited b} (n : Num) => CryptolPrimitivesForSAWCore.Num_rect (fun (n1 : Num) => seq n1 a -> seq n1 b -> seq n1 (prod a b)) (fun (n1 : SAWCoreScaffolding.Nat) => zipSame a b n1) (SAWCorePrelude.streamMap2 a b (prod a b) (fun (x : a) (y : b) => pair x y)) n.
194+
188195
Definition seqBinary : forall (n : Num), forall (a : Type), forall {Inh_a : SAWCoreScaffolding.Inhabited a}, (a -> a -> a) -> seq n a -> seq n a -> seq n a :=
189196
fun (num : Num) (a : Type) {Inh_a : SAWCoreScaffolding.Inhabited a} (f : a -> a -> a) => CryptolPrimitivesForSAWCore.Num_rect (fun (n : Num) => seq n a -> seq n a -> seq n a) (fun (n : SAWCoreScaffolding.Nat) => SAWCorePrelude.zipWith a a a f n) (SAWCorePrelude.streamMap2 a a a f) num.
190197

@@ -677,6 +684,9 @@ Definition ecFoldl : forall (n : Num), forall (a : Type), forall (b : Type), for
677684
Definition ecFoldlPrime : forall (n : Num), forall (a : Type), forall (b : Type), forall {Inh_b : SAWCoreScaffolding.Inhabited b}, PEq a -> (a -> b -> a) -> a -> seq n b -> a :=
678685
fun (n : Num) (a : Type) (b : Type) {Inh_b : SAWCoreScaffolding.Inhabited b} (pa : RecordTypeCons "eq" (a -> a -> SAWCoreScaffolding.Bool) RecordTypeNil) => ecFoldl n a b.
679686

687+
Definition ecScanl : forall (n : Num), forall (a : Type), forall (b : Type), (a -> b -> a) -> a -> seq n b -> seq (tcAdd (TCNum 1) n) a :=
688+
fun (n : Num) (a : Type) (b : Type) (f : a -> b -> a) (z : a) => CryptolPrimitivesForSAWCore.Num_rect (fun (n1 : Num) => seq n1 b -> seq (tcAdd (TCNum 1) n1) a) (fun (n1 : SAWCoreScaffolding.Nat) (xs : SAWCoreVectorsAsCoqVectors.Vec n1 b) => SAWCoreVectorsAsCoqVectors.scanl b a n1 f z xs) (fun (xs : SAWCorePrelude.Stream b) => SAWCorePreludeExtra.streamScanl b a f z xs) n.
689+
680690
Definition TCFloat : Num -> Num -> Type :=
681691
fun (_1 : Num) (_2 : Num) => unit : Type.
682692

saw-core-coq/coq/generated/CryptolToCoq/SAWCorePrelude.v

+8
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,8 @@ Fixpoint zip (a b : sort 0) (m n : Nat) (xs : Vec m a) (ys : Vec n b)
582582

583583
(* Prelude.foldl was skipped *)
584584

585+
(* Prelude.scanl was skipped *)
586+
585587
Definition reverse : forall (n : SAWCoreScaffolding.Nat), forall (a : Type), forall {Inh_a : SAWCoreScaffolding.Inhabited a}, SAWCoreVectorsAsCoqVectors.Vec n a -> SAWCoreVectorsAsCoqVectors.Vec n a :=
586588
fun (n : SAWCoreScaffolding.Nat) (a : Type) {Inh_a : SAWCoreScaffolding.Inhabited a} (xs : SAWCoreVectorsAsCoqVectors.Vec n a) => SAWCoreVectorsAsCoqVectors.gen n a (fun (i : SAWCoreScaffolding.Nat) => SAWCorePrelude.sawAt n a xs (subNat (subNat n 1) i)).
587589

@@ -828,6 +830,8 @@ Definition streamShiftL : forall (a : Type), Stream a -> SAWCoreScaffolding.Nat
828830
Definition streamShiftR : forall (a : Type), a -> Stream a -> SAWCoreScaffolding.Nat -> Stream a :=
829831
fun (a : Type) (z : a) (xs : Stream a) (i : SAWCoreScaffolding.Nat) => streamAppend a i (replicate i a z) xs.
830832

833+
(* Prelude.streamScanl was skipped *)
834+
831835
(* Prelude.Integer was skipped *)
832836

833837
(* Prelude.intAdd was skipped *)
@@ -950,6 +954,10 @@ Definition foldW64List : unfoldedW64List -> W64List :=
950954
either (unit : Type) (prod (@sigT (SAWCoreVectorsAsCoqVectors.Vec 64 SAWCoreScaffolding.Bool) (fun (_1 : SAWCoreVectorsAsCoqVectors.Vec 64 SAWCoreScaffolding.Bool) => unit : Type)) (prod W64List (unit : Type))) W64List (fun (_1 : unit : Type) => W64Nil) (fun (bv_l : prod (@sigT (SAWCoreVectorsAsCoqVectors.Vec 64 SAWCoreScaffolding.Bool) (fun (_1 : SAWCoreVectorsAsCoqVectors.Vec 64 SAWCoreScaffolding.Bool) => unit : Type)) (prod W64List (unit : Type))) => let var__0 := SAWCoreVectorsAsCoqVectors.Vec 64 SAWCoreScaffolding.Bool in
951955
W64Cons (@projT1 var__0 (fun (_1 : var__0) => unit : Type) (SAWCoreScaffolding.fst bv_l)) (SAWCoreScaffolding.fst (SAWCoreScaffolding.snd bv_l))).
952956

957+
(* Prelude.unsafeAssertBVULt was skipped *)
958+
959+
(* Prelude.unsafeAssertBVULe was skipped *)
960+
953961
Axiom bvEqWithProof : forall (n : SAWCoreScaffolding.Nat), forall (v1 : SAWCoreVectorsAsCoqVectors.Vec n SAWCoreScaffolding.Bool), forall (v2 : SAWCoreVectorsAsCoqVectors.Vec n SAWCoreScaffolding.Bool), Maybe (SAWCoreScaffolding.Eq (SAWCoreVectorsAsCoqVectors.Vec n SAWCoreScaffolding.Bool) v1 v2) .
954962

955963
Definition bvultWithProof : forall (n : SAWCoreScaffolding.Nat), forall (v1 : SAWCoreVectorsAsCoqVectors.Vec n SAWCoreScaffolding.Bool), forall (v2 : SAWCoreVectorsAsCoqVectors.Vec n SAWCoreScaffolding.Bool), Maybe (SAWCoreScaffolding.Eq SAWCoreScaffolding.Bool (SAWCoreVectorsAsCoqVectors.bvult n v1 v2) SAWCoreScaffolding.true) :=

saw-core-coq/coq/handwritten/CryptolToCoq/CryptolPrimitivesForSAWCoreExtra.v

+20-6
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,24 @@ Coercion natToNat : nat >-> Nat.
2525
Theorem Eq_TCNum a b : a = b -> Eq _ (TCNum a) (TCNum b).
2626
Proof.
2727
intros EQ.
28-
rewrite EQ.
29-
reflexivity.
30-
Qed.
28+
apply f_equal.
29+
apply EQ.
30+
Defined.
3131

3232
Theorem min_nSn n : min n (S n) = n.
3333
Proof.
3434
induction n; simpl; auto.
35-
Qed.
35+
Defined.
3636

3737
Theorem min_Snn n : min (S n) n = n.
3838
Proof.
3939
induction n; simpl; auto.
40-
Qed.
40+
Defined.
41+
42+
Theorem min_nn n : min n n = n.
43+
Proof.
44+
induction n; simpl; auto.
45+
Defined.
4146

4247
Ltac solveUnsafeAssertStep :=
4348
match goal with
@@ -50,12 +55,21 @@ Ltac solveUnsafeAssertStep :=
5055
| [ n : Num |- _ ] => destruct n
5156
| [ |- Eq Num (TCNum _) (TCNum _) ] => apply Eq_TCNum
5257
| [ |- Eq Num _ _ ] => reflexivity
58+
| [ |- min ?n ?n = _ ] => rewrite (min_nn n)
5359
| [ |- min ?n (S ?n) = _ ] => rewrite (min_nSn n)
5460
| [ |- min (S ?n) ?n = _ ] => rewrite (min_Snn n)
5561
end.
5662

57-
Ltac solveUnsafeAssert := repeat (solveUnsafeAssertStep; simpl; try lia); trivial.
63+
Ltac unfoldLets :=
64+
repeat
65+
match goal with
66+
[ X := _ |- _ ] => progress (cbv delta [X])
67+
end.
5868

69+
Ltac solveUnsafeAssert :=
70+
try (unfoldLets;
71+
repeat (repeat solveUnsafeAssertStep; simpl; try reflexivity; try lia);
72+
trivial).
5973

6074
Fixpoint iterNat {a : Type} (n : nat) (f : a -> a) : a -> a :=
6175
match n with

saw-core-coq/coq/handwritten/CryptolToCoq/SAWCorePreludeExtra.v

+27-5
Original file line numberDiff line numberDiff line change
@@ -18,35 +18,57 @@ Theorem Nat_cases2_match_spec a f1 f2 f3 : forall x y,
1818
Nat_cases2 a f1 f2 f3 x y = Nat_cases2_match a f1 f2 f3 x y.
1919
Proof.
2020
induction x; induction y; simpl; congruence.
21-
Qed.
21+
Defined.
2222

2323
Theorem minNat_min : forall x y, minNat x y = min x y.
2424
Proof.
2525
induction x; induction y; simpl; auto.
26-
Qed.
26+
Defined.
2727

2828
Theorem maxNat_max : forall x y, maxNat x y = max x y.
2929
Proof.
3030
induction x; induction y; simpl; auto.
31-
Qed.
31+
Defined.
3232

3333
Theorem addNat_add : forall x y, addNat x y = x + y.
3434
Proof.
3535
induction x; simpl; auto.
36-
Qed.
36+
Defined.
3737

3838
Theorem subNat_sub : forall x y, subNat x y = x - y.
3939
Proof.
4040
induction x; induction y; simpl; auto.
41-
Qed.
41+
Defined.
4242

4343
Theorem mulNat_mul : forall x y, mulNat x y = x * y.
4444
Proof.
4545
induction x; simpl; intros; auto.
4646
rewrite IHx.
4747
apply addNat_add.
48+
Defined.
49+
50+
Definition streamScanl (a b : sort 0) (f : b -> a -> b) (z:b) (xs:Stream a) : Stream b :=
51+
MkStream b
52+
(fix strm (n:nat) : b :=
53+
match n with
54+
| O => z
55+
| S n' => f (strm n') (streamGet a xs n')
56+
end).
57+
58+
Lemma streamScanl_zero a b f z xs : streamGet b (streamScanl a b f z xs) 0 = z.
59+
Proof.
60+
reflexivity.
61+
Qed.
62+
63+
Lemma streamScanl_succ a b f z xs : forall n,
64+
streamGet b (streamScanl a b f z xs) (S n) =
65+
f (streamGet b (streamScanl a b f z xs) n)
66+
(streamGet a xs n).
67+
Proof.
68+
intro n. reflexivity.
4869
Qed.
4970

71+
5072
Theorem fold_unfold_IRT As Ds D : forall x, foldIRT As Ds D (unfoldIRT As Ds D x) = x.
5173
Proof.
5274
induction x; simpl; unfold uncurry; f_equal; try easy.

saw-core-coq/coq/handwritten/CryptolToCoq/SAWCoreVectorsAsCoqVectors.v

+6
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ Fixpoint foldl (a b : Type) (n : Nat) (f : b -> a -> b) (acc : b) (v : Vec n a)
118118
| Vector.cons hd _ tl => foldl _ _ _ f (f acc hd) tl
119119
end.
120120

121+
Fixpoint scanl (a b : Type) (n : Nat) (f : b -> a -> b) (acc : b) (v : Vec n a) : Vec (S n) b :=
122+
match v in VectorDef.t _ n return Vec (S n) b with
123+
| Vector.nil => [ acc ]
124+
| Vector.cons h n' tl => Vector.cons b acc (S n') (scanl a b n' f (f acc h) tl)
125+
end.
126+
121127
Fixpoint foldl_dep (a : Type) (b : Nat -> Type) (n : Nat)
122128
(f : forall n, b n -> a -> b (S n)) (base : b O) (v : Vec n a) : b n :=
123129
match v with

saw-core-coq/src/Verifier/SAW/Translation/Coq/SpecialTreatment.hs

+9
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ cryptolPrimitivesModule = mkModuleName ["CryptolPrimitivesForSAWCore"]
179179
sawCoreScaffoldingModule :: ModuleName
180180
sawCoreScaffoldingModule = mkModuleName ["SAWCoreScaffolding"]
181181

182+
preludeExtraModule :: ModuleName
183+
preludeExtraModule = mkModuleName ["SAWCorePreludeExtra"]
184+
182185
cryptolPreludeSpecialTreatmentMap :: Map.Map String IdentSpecialTreatment
183186
cryptolPreludeSpecialTreatmentMap = Map.fromList $ []
184187

@@ -344,6 +347,7 @@ sawCorePreludeSpecialTreatmentMap configuration =
344347
, ("eq_Vec", skip)
345348
, ("foldr", mapsTo vectorsModule "foldr")
346349
, ("foldl", mapsTo vectorsModule "foldl")
350+
, ("scanl", mapsTo vectorsModule "scanl")
347351
, ("gen", mapsTo vectorsModule "gen")
348352
, ("rotateL", mapsTo vectorsModule "rotateL")
349353
, ("rotateR", mapsTo vectorsModule "rotateR")
@@ -358,6 +362,11 @@ sawCorePreludeSpecialTreatmentMap configuration =
358362
, ("Vec", mapsTo vectorsModule "Vec")
359363
]
360364

365+
-- Streams
366+
++
367+
[ ("streamScanl", mapsTo preludeExtraModule "streamScanl")
368+
]
369+
361370
-- Integers
362371
++
363372
[ ("Integer", mapsTo sawDefinitionsModule "Integer")

saw-core/prelude/Prelude.sawcore

+24-1
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,7 @@ primitive zip : (a b : sort 0) -> (m n : Nat) -> Vec m a -> Vec n b -> Vec (minN
959959

960960
primitive foldr : (a b : sort 0) -> (n : Nat) -> (a -> b -> b) -> b -> Vec n a -> b;
961961
primitive foldl : (a b : sort 0) -> (n : Nat) -> (b -> a -> b) -> b -> Vec n a -> b;
962+
primitive scanl : (a b : sort 0) -> (n : Nat) -> (b -> a -> b) -> b -> Vec n a -> Vec (addNat 1 n) b;
962963

963964
reverse : (n : Nat) -> (a : isort 0) -> Vec n a -> Vec n a;
964965
reverse n a xs = gen n a (\ (i : Nat) -> at n a xs (subNat (subNat n 1) i));
@@ -1336,6 +1337,28 @@ streamShiftL a xs i = streamDrop a i xs;
13361337
streamShiftR : (a : sort 0) -> a -> Stream a -> Nat -> Stream a;
13371338
streamShiftR a z xs i = streamAppend a i (replicate i a z) xs;
13381339

1340+
-- TODO "streamScanl" should probably be a primitive. However, stream
1341+
-- primitives are complicated to implement because the backends have different
1342+
-- implementations for streams, and there is no uniform place to implement them.
1343+
--
1344+
-- We explicitly use "fix" here to implement sharing in the stream. A naive
1345+
-- implementation that just iterates "f" separate for each index would waste work.
1346+
-- The fixpoint is well founded because each element only refers to elements with
1347+
-- smaller indices.
1348+
--
1349+
-- For Coq support, this definition is replaced with a naive implementation
1350+
-- that performs independent iterations for each location.
1351+
streamScanl : (a b : sort 0) -> (b -> a -> b) -> b -> Stream a -> Stream b;
1352+
streamScanl a b f z as =
1353+
fix (Stream b)
1354+
(\ (bs : Stream b) -> MkStream b
1355+
(natCase (\ (n : Nat) -> b)
1356+
-- zero case
1357+
z
1358+
-- successor case
1359+
(\ (n : Nat) -> f (streamGet b bs n) (streamGet a as n)))
1360+
);
1361+
13391362
--------------------------------------------------------------------------------
13401363
-- Integer values
13411364
-- integer values of unbounded precision
@@ -1643,7 +1666,7 @@ genBVVec : (n : Nat) -> (len : Vec n Bool) -> (a : sort 0) ->
16431666
BVVec n len a;
16441667
genBVVec n len a f =
16451668
genWithProof (bvToNat n len) a
1646-
(\(i:Nat) (pf:IsLtNat i (bvToNat n len)) ->
1669+
(\(i:Nat) (pf:IsLtNat i (bvToNat n len)) ->
16471670
f (bvNat n i) (IsLtNat_to_bvult n len i pf));
16481671

16491672
-- Generate a BVVec from the elements of an existing vector, using a default

saw-core/src/Verifier/SAW/Simulator/Prims.hs

+20-2
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ constMap bp = Map.fromList
354354
, ("Prelude.zip", vZipOp (bpUnpack bp))
355355
, ("Prelude.foldr", foldrOp (bpUnpack bp))
356356
, ("Prelude.foldl", foldlOp (bpUnpack bp))
357+
, ("Prelude.scanl", scanlOp (bpUnpack bp))
357358
, ("Prelude.rotateL", rotateLOp bp)
358359
, ("Prelude.rotateR", rotateROp bp)
359360
, ("Prelude.shiftL", shiftLOp bp)
@@ -521,7 +522,7 @@ coerceOp =
521522

522523
-- | Return the number of bits necessary to represent the given value,
523524
-- which should be a value of type Nat.
524-
natSize :: BasePrims l -> Value l -> Natural
525+
natSize :: HasCallStack => BasePrims l -> Value l -> Natural
525526
natSize _bp val =
526527
case val of
527528
VNat n -> widthNat n
@@ -1074,6 +1075,24 @@ foldlOp unpack =
10741075
xv <- toVector unpack xs
10751076
lift (V.foldl g (force z) xv)
10761077

1078+
-- scanl : (a b : sort 0) -> (n : Nat) -> (b -> a -> b) -> b -> Vec n a -> Vec (addNat n 1) b;
1079+
scanlOp :: forall l. (VMonadLazy l, Show (Extra l)) => Unpack l -> Prim l
1080+
scanlOp unpack =
1081+
constFun $ -- a
1082+
constFun $ -- b
1083+
constFun $ -- n
1084+
strictFun $ \f ->
1085+
primFun $ \z ->
1086+
strictFun $ \xs ->
1087+
PrimExcept $ do
1088+
let g :: Vector (Thunk l) ->
1089+
Thunk l ->
1090+
EvalM l (Vector (Thunk l))
1091+
g bs v = do b <- delay (applyAll f [V.last bs, v])
1092+
return (V.snoc bs b)
1093+
xv <- toVector unpack xs
1094+
lift (VVector <$> V.foldM g (V.singleton z) xv)
1095+
10771096
-- op :: Integer -> Integer;
10781097
intUnOp :: VMonad l => (VInt l -> MInt l) -> Prim l
10791098
intUnOp f =
@@ -1377,4 +1396,3 @@ arrayRangeEqOp bp =
13771396
j' <- toWord (bpPack bp) j
13781397
l' <- toWord (bpPack bp) l
13791398
VBool <$> (bpArrayRangeEq bp) f' i' g' j' l'
1380-

0 commit comments

Comments
 (0)