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

Add extract_as attribute. #3466

Merged
merged 5 commits into from
Sep 26, 2024
Merged

Add extract_as attribute. #3466

merged 5 commits into from
Sep 26, 2024

Conversation

gebner
Copy link
Contributor

@gebner gebner commented Sep 11, 2024

To quote the documentation for the attribute:

(** Replaces the annotated definition
    by the specified implementation during extraction.
    There are no checks whether the implementation
    has the same semantics, or even the same type.

    For example, if you have:

    [@@extract_as (`(fun (x: nat) -> "not a number"))]
    let add_one (x: nat) : nat = x + 42

    Then `add_one` will extract to `let add_one x = "not a number"`,
    and most likely cause the extracted program to crash.

    Note that the argument needs to be a literal quotation.
 *)

@W95Psp
Copy link
Contributor

W95Psp commented Sep 24, 2024

That looks pretty cool, I'm thinking: this kind of lightweight OCaml "FFI" directly in the compiler F* sources would be kind of awesome, right? 😃

@gebner
Copy link
Contributor Author

gebner commented Sep 24, 2024

To be clear: this attribute does not replace F* by OCaml. It replaces F* by some other F* code. This is mainly useful when you have a type with extra structure that you want to forget during extraction; in Pulse we have the stt type which comes with extra separation logic pre- and postconditions and we just want to forget about the separation logic stuff during extraction.

For backend-specific implementations, you'd want a different attribute. Maybe something like [@@inline_asm_for "OCaml" "fun x -> \"not a number\""]. Where the code in the second string is actual OCaml code (which can then refer to whatever OCaml libraries you'd like).

@gebner gebner requested a review from mtzguido September 26, 2024 17:44
@gebner
Copy link
Contributor Author

gebner commented Sep 26, 2024

@mtzguido Do you have any thoughts on this?

Copy link
Member

@mtzguido mtzguido left a comment

Choose a reason for hiding this comment

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

Thanks Gabriel, this looks good, just wondering about that true boolean.

More high-level I was wondering if we could have implemented this by using Syntax.Visit.visit_tm to just replace each fvar by its extract_as just before extracting, but that will not interact well with normalization. If we did extraction into OCaml incrementally, and did inlining over the OCaml AST, I think that would work and be easier, but that's for another day : ).

let fixup_sigelt_extract_as se =
match se.sigel, find_map se.sigattrs N.is_extract_as_attr with
| Sig_let {lids; lbs=(_, [lb])}, Some impl ->
{se with sigel = Sig_let {lids; lbs=(true, [{lb with lbdef = impl}])}}
Copy link
Member

Choose a reason for hiding this comment

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

The true is interesting here, so we always mark it recursive? Can it really be so since the term that is the argument to extract_as cannot mention the name of this sigelt (without pack_fv trickery)?

Copy link
Member

Choose a reason for hiding this comment

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

In any case it's not a big deal, but maybe worth a comment in the attribute's doc and/or here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As mentioned offline, the implementation can indeed be recursive. This is for example the case with recursive Pulse functions.

I have added a comment to both the attribute and the fixup function here.

| Tm_uinst({n=Tm_fvar fv}, [u]), [_; (t, _)]
when Syntax.fv_eq_lid fv PC.extract_as_lid ->
Some t
| Tm_fvar fv, [t, _] when Syntax.fv_eq_lid fv PC.extract_as_lid ->
Copy link
Member

Choose a reason for hiding this comment

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

Not a big deal but probably better to avoid these back-and-forth changes within a PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was going by the contribution guidelines. We should probably update them now.

@mtzguido
Copy link
Member

mtzguido commented Sep 26, 2024

I rebased this btw. If we add a comment about the recursive bit being set then I'm happy merging.

Also: check-world run https://github.com/FStarLang/FStar/actions/runs/11058160723

@gebner gebner enabled auto-merge September 26, 2024 21:33
@gebner gebner merged commit d848e89 into master Sep 26, 2024
3 checks passed
@gebner gebner deleted the gebner_extract_as branch September 26, 2024 21:47
@kant2002
Copy link
Contributor

kant2002 commented Oct 2, 2024

I definitely would like to see [@@inline_asm_for "FSharp" "fun x -> \"not a number\""]

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.

4 participants