Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support mutually recursive let bindings in sigelt_view #2291

Merged

Conversation

antoniolocascio
Copy link
Contributor

@antoniolocascio antoniolocascio commented May 10, 2021

Context

The module FStar.Reflection.Data defines the data type sigelt_view, which is used for inspecting the signature of a declaration. As of right now, its definition is:

type sigelt_view =
    | Sg_Let of bool * fv * list<univ_name> * typ * term
    | Sg_Inductive of name * list<univ_name> * list<binder> * typ * list<ctor> 
    | Sg_Val of name * list<univ_name> * typ
    | Unk

The problem is that there’s no way of inspecting mutually recursive let bindings, as the first constructor can only represent a single standalone let. In contrast, the sigelt datatype's Sig_let constructor has a list of let bindings to accommodate mutually recursive lets.

Implemented solution

In this PR I provide a workaround to this, which involves adding a new constructor to sigelt_view to represent mutually recursive lets:

  | Sg_MLet of list<lb_view>

where lb_view is a type that packs the same information as in Sg_Let, and is defined as:

type lb_view = {
    lb_r : bool;
    lb_fv : fv;
    lb_us : list<univ_name>;
    lb_typ : typ;
    lb_def : term;
}

I chose to add a new constructor to make sure this worked without having to fix every use of Sg_Let, but I believe the two could well be unified. This is something I need in the project I'm currently working on, so I would be happy to hear you opinion on this issue and make any changes to its solution.

@antoniolocascio antoniolocascio force-pushed the antoniolocascio_mlet_sigelt_view branch 2 times, most recently from 3911ee5 to d6758e6 Compare May 11, 2021 11:31
@antoniolocascio antoniolocascio force-pushed the antoniolocascio_mlet_sigelt_view branch from d6758e6 to 838559a Compare May 31, 2021 09:36
@antoniolocascio antoniolocascio marked this pull request as ready for review June 4, 2021 15:21
@antoniolocascio
Copy link
Contributor Author

Following a discussion with @aseemr and @nikswamy, I've changed the implementation of this PR to generalize Sg_Let. Now, this constructor is defined as:

  | Sg_MLet of bool * list<letbinding>

Where the boolean value flags whether the binding is recursive, and letbinding is the record type defined in Syntax.Syntax.

I also defined the lb_view type, an abstraction that hides the internal representation of let bindings, together with inspection and packing functions.

@antoniolocascio
Copy link
Contributor Author

Fixed the errors caused by this PR in HACL* in hacl-star#471

@antoniolocascio antoniolocascio force-pushed the antoniolocascio_mlet_sigelt_view branch 2 times, most recently from e085403 to c289d4c Compare July 27, 2021 12:07
BU.bind_opt (unembed (e_list e_letbinding) cb lbs) (fun lbs ->
Some <| Sg_Let (r, lbs)))

| Construct (fv, _, [(t, _); (us, _); (nm, _)]) when S.fv_eq_lid fv ref_Sg_Val.lid ->
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this code fixing the unembedding of Sg_val? Was it a bug in the previous code? (Asking only because doesn't seem directly related to the change that this PR is doing.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's fixing the Sg_Val case. I really can’t remember now, but I'm almost positive it was a bug.

@@ -673,22 +733,6 @@ let e_exp =

let e_binder_view = e_tuple2 e_bv (e_tuple2 e_aqualv (e_list e_term))

let e_attribute = e_term
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to remove these? I am guessing these functions are not used currently but still any harm in keeping them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These aren’t removed, they're moved a little earlier in the module (l.625).

@aseemr
Copy link
Collaborator

aseemr commented Aug 19, 2021

Thanks Antonio! Looks good to me, left a couple of comments.

Since this is a breaking change, can you add an entry to CHANGES.md, summarizing the change, and pointing to a representative example of how to fix the code that breaks? You can see other entries in CHANGES.md for examples.

Thanks again, this is a nice enhancement to the reflection API that would definitely be useful for others too.

@antoniolocascio
Copy link
Contributor Author

Hi @aseemr, thank you so much for the review. I've updated the CHANGES.md file.

@aseemr aseemr merged commit 63ba918 into FStarLang:master Aug 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants