Skip to content

Commit 6bc791f

Browse files
authored
Merge pull request #3626 from mtzguido/unfold_once
Add an `UnfoldOnce`/`delta_once` normalizer step
2 parents 7ff2d93 + 1f2e2d9 commit 6bc791f

15 files changed

Lines changed: 92 additions & 18 deletions

examples/data_structures/BinomialQueue.fst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ let rec carry_repr (d:pos) (q:forest) (t:tree) (lq lt:ms)
360360
(ms_append (keys_of_tree hd) (keys_of_tree t))
361361
#pop-options
362362

363-
#push-options "--z3rlimit 50 --fuel 1 --ifuel 1"
363+
#push-options "--z3rlimit 75 --fuel 1 --ifuel 1"
364364
let rec join_repr (d:pos) (p q:forest) (c:tree)
365365
(lp lq lc:ms)
366366
: Lemma

examples/doublylinkedlist/DoublyLinkedList.fst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1964,7 +1964,7 @@ let dll_append (#t:Type) (d1 d2:dll t) :
19641964

19651965
#reset-options
19661966

1967-
#set-options "--z3rlimit 40 --max_fuel 2 --max_ifuel 1"
1967+
#set-options "--z3rlimit 60 --max_fuel 2 --max_ifuel 1"
19681968

19691969
let dll_split_using (#t:Type) (d:dll t) (e:pointer (node t)) :
19701970
StackInline (dll t * dll t)

src/parser/FStarC.Parser.Const.fst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ let steps_delta = psconst "delta"
323323
let steps_reify = psconst "reify_"
324324
let steps_norm_debug = psconst "norm_debug"
325325
let steps_unfoldonly = psconst "delta_only"
326+
let steps_unfoldonce = psconst "delta_once"
326327
let steps_unfoldfully = psconst "delta_fully"
327328
let steps_unfoldattr = psconst "delta_attr"
328329
let steps_unfoldqual = psconst "delta_qualifier"

src/syntax/FStarC.Syntax.Embeddings.fst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,7 @@ let steps_Iota = tconst PC.steps_iota
798798
let steps_Reify = tconst PC.steps_reify
799799
let steps_NormDebug = tconst PC.steps_norm_debug
800800
let steps_UnfoldOnly = tconst PC.steps_unfoldonly
801+
let steps_UnfoldOnce = tconst PC.steps_unfoldonce
801802
let steps_UnfoldFully = tconst PC.steps_unfoldonly
802803
let steps_UnfoldAttr = tconst PC.steps_unfoldattr
803804
let steps_UnfoldQual = tconst PC.steps_unfoldqual
@@ -848,6 +849,9 @@ let e_norm_step : embedding Pervasives.norm_step =
848849
| UnfoldOnly l ->
849850
S.mk_Tm_app steps_UnfoldOnly [S.as_arg (embed l rng None norm)]
850851
rng
852+
| UnfoldOnce l ->
853+
S.mk_Tm_app steps_UnfoldOnce [S.as_arg (embed l rng None norm)]
854+
rng
851855
| UnfoldFully l ->
852856
S.mk_Tm_app steps_UnfoldFully [S.as_arg (embed l rng None norm)]
853857
rng
@@ -902,6 +906,9 @@ let e_norm_step : embedding Pervasives.norm_step =
902906
| Tm_fvar fv, [(l, _)] when S.fv_eq_lid fv PC.steps_unfoldonly ->
903907
BU.bind_opt (try_unembed l norm) (fun ss ->
904908
Some <| UnfoldOnly ss)
909+
| Tm_fvar fv, [(l, _)] when S.fv_eq_lid fv PC.steps_unfoldonce ->
910+
BU.bind_opt (try_unembed l norm) (fun ss ->
911+
Some <| UnfoldOnce ss)
905912
| Tm_fvar fv, [(l, _)] when S.fv_eq_lid fv PC.steps_unfoldfully ->
906913
BU.bind_opt (try_unembed l norm) (fun ss ->
907914
Some <| UnfoldFully ss)

src/typechecker/FStarC.TypeChecker.Cfg.fst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ let steps_to_string f =
4646
do_not_unfold_pure_lets = %s;\n\
4747
unfold_until = %s;\n\
4848
unfold_only = %s;\n\
49+
unfold_once = %s;\n\
4950
unfold_fully = %s;\n\
5051
unfold_attr = %s;\n\
5152
unfold_qual = %s;\n\
@@ -78,6 +79,7 @@ let steps_to_string f =
7879
f.do_not_unfold_pure_lets |> show;
7980
f.unfold_until |> show;
8081
f.unfold_only |> show;
82+
f.unfold_once |> show;
8183
f.unfold_fully |> show;
8284
f.unfold_attr |> show;
8385
f.unfold_qual |> show;
@@ -149,6 +151,7 @@ let default_steps : fsteps = {
149151
do_not_unfold_pure_lets = false;
150152
unfold_until = None;
151153
unfold_only = None;
154+
unfold_once = None;
152155
unfold_fully = None;
153156
unfold_attr = None;
154157
unfold_qual = None;
@@ -191,6 +194,7 @@ let fstep_add_one s fs =
191194
| DoNotUnfoldPureLets -> { fs with do_not_unfold_pure_lets = true }
192195
| UnfoldUntil d -> { fs with unfold_until = Some d }
193196
| UnfoldOnly lids -> { fs with unfold_only = Some lids }
197+
| UnfoldOnce lids -> { fs with unfold_once = Some lids }
194198
| UnfoldFully lids -> { fs with unfold_fully = Some lids }
195199
| UnfoldAttr lids -> { fs with unfold_attr = Some lids }
196200
| UnfoldQual strs ->
@@ -459,6 +463,8 @@ let translate_norm_step = function
459463
| Pervasives.NormDebug -> [NormDebug]
460464
| Pervasives.UnfoldOnly names ->
461465
[UnfoldUntil delta_constant; UnfoldOnly (List.map I.lid_of_str names)]
466+
| Pervasives.UnfoldOnce names ->
467+
[UnfoldUntil delta_constant; UnfoldOnce (List.map I.lid_of_str names)]
462468
| Pervasives.UnfoldFully names ->
463469
[UnfoldUntil delta_constant; UnfoldFully (List.map I.lid_of_str names)]
464470
| Pervasives.UnfoldAttr names ->

src/typechecker/FStarC.TypeChecker.Cfg.fsti

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ type fsteps = {
5656
do_not_unfold_pure_lets : bool;
5757
unfold_until : option S.delta_depth;
5858
unfold_only : option (list I.lid);
59+
unfold_once : option (list I.lid);
5960
unfold_fully : option (list I.lid);
6061
unfold_attr : option (list I.lid);
6162
unfold_qual : option (list string);

src/typechecker/FStarC.TypeChecker.Env.fsti

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ type step =
4444
| DoNotUnfoldPureLets
4545
| UnfoldUntil of delta_depth
4646
| UnfoldOnly of list FStarC.Ident.lid
47+
| UnfoldOnce of list FStarC.Ident.lid
4748
| UnfoldFully of list FStarC.Ident.lid
4849
| UnfoldAttr of list FStarC.Ident.lid
4950
| UnfoldQual of list string

src/typechecker/FStarC.TypeChecker.Normalize.Unfolding.fst

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,16 @@ let should_unfold cfg should_reify fv qninfo : should_unfold_res =
3434
| None -> []
3535
| Some quals -> quals
3636
in
37-
(* unfold or not, fully or not, reified or not *)
38-
let yes = true , false , false in
39-
let no = false , false , false in
40-
let fully = true , true , false in
41-
let reif = true , false , true in
37+
(* unfold or not, fully or not, reified or not, only once or not *)
38+
let yes = true , false , false, false in
39+
let no = false , false , false, false in
40+
let fully = true , true , false, false in
41+
let reif = true , false , true, false in
42+
let once = true , false , false, true in
4243

4344
let yesno b = if b then yes else no in
4445
let fullyno b = if b then fully else no in
45-
let comb_or l = List.fold_right (fun (a,b,c) (x,y,z) -> (a||x, b||y, c||z)) l (false, false, false) in
46+
let comb_or l = List.fold_right (fun (a,b,c,d) (x,y,z,w) -> (a||x, b||y, c||z, d||w)) l (false, false, false, false) in
4647

4748
let default_unfolding () =
4849
log_unfolding cfg (fun () -> BU.print3 "should_unfold: Reached a %s with delta_depth = %s\n >> Our delta_level is %s\n"
@@ -57,12 +58,13 @@ let should_unfold cfg should_reify fv qninfo : should_unfold_res =
5758
in
5859
let selective_unfold =
5960
Some? cfg.steps.unfold_only ||
61+
Some? cfg.steps.unfold_once ||
6062
Some? cfg.steps.unfold_fully ||
6163
Some? cfg.steps.unfold_attr ||
6264
Some? cfg.steps.unfold_qual ||
6365
Some? cfg.steps.unfold_namespace
6466
in
65-
let res : bool & bool & bool =
67+
let res : bool & bool & bool & bool =
6668
match qninfo, selective_unfold with
6769
// We unfold dm4f actions if and only if we are reifying
6870
| _ when Env.qninfo_is_action qninfo ->
@@ -83,6 +85,11 @@ let should_unfold cfg should_reify fv qninfo : should_unfold_res =
8385
log_unfolding cfg (fun () -> BU.print_string " >> HasMaskedEffect, not unfolding\n");
8486
no
8587

88+
// Unfoldonce. NB: this is before the zeta case, so we unfold even if zeta is off
89+
| _, true when Some? cfg.steps.unfold_once && BU.for_some (fv_eq_lid fv) (Some?.v cfg.steps.unfold_once) ->
90+
log_unfolding cfg (fun () -> BU.print_string " >> UnfoldOnce\n");
91+
once
92+
8693
// Recursive lets may only be unfolded when Zeta is on
8794
| Some (Inr ({sigquals=qs; sigel=Sig_let {lbs=(is_rec, _)}}, _), _), _ when
8895
is_rec && not cfg.steps.zeta && not cfg.steps.zeta_full ->
@@ -160,10 +167,11 @@ let should_unfold cfg should_reify fv qninfo : should_unfold_res =
160167
);
161168
let r =
162169
match res with
163-
| false, _, _ -> Should_unfold_no
164-
| true, false, false -> Should_unfold_yes
165-
| true, true, false -> Should_unfold_fully
166-
| true, false, true -> Should_unfold_reify
170+
| false, _, _, _ -> Should_unfold_no
171+
| true, false, false, false -> Should_unfold_yes
172+
| true, false, false, true -> Should_unfold_once
173+
| true, true, false, false -> Should_unfold_fully
174+
| true, false, true, false -> Should_unfold_reify
167175
| _ ->
168176
failwith <| BU.format1 "Unexpected unfolding result: %s" (show res)
169177
in

src/typechecker/FStarC.TypeChecker.Normalize.Unfolding.fsti

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ val plugin_unfold_warn_ctr : ref int
1313
type should_unfold_res =
1414
| Should_unfold_no
1515
| Should_unfold_yes
16+
| Should_unfold_once
1617
| Should_unfold_fully
1718
| Should_unfold_reify
1819

src/typechecker/FStarC.TypeChecker.Normalize.fst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,9 +631,19 @@ let decide_unfolding cfg stack fv qninfo (* : option (option cfg * stack) *) =
631631
| Should_unfold_no ->
632632
// No unfolding
633633
None
634+
634635
| Should_unfold_yes ->
635636
// Usual unfolding, no change to cfg or stack
636637
Some (None, stack)
638+
639+
| Should_unfold_once ->
640+
let Some once = cfg.steps.unfold_once in
641+
let cfg' = { cfg with steps = {
642+
cfg.steps with unfold_once =
643+
Some <| List.filter (fun lid -> not (S.fv_eq_lid fv lid)) once } } in
644+
// Unfold only once. Keep the stack, but remove the lid from the step.
645+
Some (Some cfg', stack)
646+
637647
| Should_unfold_fully ->
638648
// Unfolding fully, use new cfg with more steps and keep old one in stack
639649
let cfg' =

0 commit comments

Comments
 (0)