-
Notifications
You must be signed in to change notification settings - Fork 235
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 for naming scrutinee in dependent pattern matching #2464
Conversation
|
||
TcUtil.bind_cases env t cases guard_x, g, erasable | ||
//c has b free, so substitute it with the scrutinee | ||
let c = SS.subst_comp [NT (b.binder_bv, e1)] c in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is where we compute the type of the match
result by substituting binder with e1
.
let bs, asc = SS.open_ascription [b] asc in | ||
let b = List.hd bs in | ||
//we set the sort of the binder to be the type of e1 | ||
{b with binder_bv={b.binder_bv with sort=c1.res_typ}}, asc in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding the returns binder with sort as the type of e1
, to typecheck the ascription.
| Some (b, asc) -> | ||
let asc = SS.close_ascription [b] asc in | ||
let b = List.hd (SS.close_binders [b]) in | ||
let b = {b with binder_bv={b.binder_bv with sort=tun}} in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While packing the returns annotation back, set the sort to _
. So we don't have to normalize it, instantiate it, compute its fvs etc. etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interesting ... nice trick
asc | ||
|> SS.subst_ascription [NT (scrutinee, norm_pat_exp)] | ||
|> SS.subst_ascription [NT (b.binder_bv, norm_pat_exp)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ascribe the branches before checking them.
@@ -173,6 +173,7 @@ let keywords = | |||
ALWAYS, "let" ,LET(false); | |||
ALWAYS, "logic" ,LOGIC; | |||
ALWAYS, "match" ,MATCH; | |||
ALWAYS, "as" ,AS; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super tiny nit, sorry. But this list of keywords was originally meant to be in alphabetical order. I see there are some deviations from that already, but may be worth restoring at some point.
((p_noSeqTermAndComment false false e) ^/+^ | ||
(match as_opt with | ||
| None -> empty | ||
| Some as_ident -> str " as" ^/+^ (p_ident as_ident)) ^/+^ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need the preceding " " in as
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for noticing! I removed these extra spaces and updated the pretty printing tests.
(str "ret" ^/+^ p_tmIff ret) ^/^ | ||
((match as_opt with | ||
| None -> empty | ||
| Some as_ident -> str " as " ^/^ p_ident as_ident ^/^ str " ") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as below ... do we need the spaces around it?
@@ -1,22 +1,32 @@ | |||
module Match.Returns | |||
|
|||
let test (n: nat) = | |||
match n returns nat with | |||
match n returns nat with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this extra space will disappear with some tuning in ToDocument
match ret_opt with | ||
| None -> "" | ||
| Some (b, asc) -> | ||
(binder_to_string b ^ " ") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing an as
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is simply printing the AST, e.g. Tm_match is already printed as (scrutinee, branches), so I followed the same style (e.g. no returns
as well).
@@ -78,12 +78,12 @@ let indexing' (#a #b: _) (v:view a b) (len_as:nat) (i:nat{i < len_as * View?.n v | |||
let indexing #b vb i = indexing' (get_view vb) (B.length (as_buffer vb)) i | |||
|
|||
let sel' (#a #b: _) (v:view a b) | |||
(as:Seq.seq a) | |||
(i:nat{i / View?.n v < Seq.length as}) | |||
(es:Seq.seq a) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for all the fixes in this file!
_ | ||
_ | ||
(fun _ -> tperm a (Map.upd m i c) (Map.remove borrows i)) with | ||
match Seq.index s (U32.v idx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice
Thanks Aseem.. This looks great! Thanks for all the explanations and code comments in TcTerm too. I left a few minor nit-picky comments. |
Thanks for the review Nik! I incorporated the comments, except the alphabetical sorting of keywords in the lexer(s). I will raise an enhancement issue for that. |
Dependent pattern matching in F*
PR #2256 added support for dependent pattern matching with
returns
annotations onmatch
. E.g., fromulib/Steel.ST.EphemeralHashtbl.fst
:However, it comes with a restriction that the scrutinee expression has to be a name in the presence of a
returns
annotation. As a result, the snippet above has to let-bind the scrutinee expression.This PR
This PR adds support for naming the scrutinee using
as
keyword similar to Coq. E.g. the code above can now be written as:where
y
may appear free in the type/computation type afterreturns
.As an optimization, note that the computation type after
returns
in the first snippet does not containvopt
, so in this case, we can even write:thereby eliminating the unnecessary naming of the scrutinee.
Code changes
AST, syntax, desugaring, resugaring, reflection
In the parser AST, a returns annotation may now optionally have a
ident
. Whereas in the core syntax, the returns annotation is of the form(b, asc)
, whereb
is a binder andasc
is anSyntax.ascription
node.Parser AST returns annotation
(x, t)
desugars to(x_b, asc)
, wherex_b
is a binder forx
andt
desugars toasc
, may be containing the bound variablex_b
.On the other hand, parser AST returns annotation
t
desugars to(uu___ret_, asc)
, i.e. we introduce a new binder. One subtlety here is that, it may be the case that source program does not name the scrutinee, but scrutinee is already a name and occurs free in the returns annotation, e.g.:In this case, when we introduce a new binder
uu___ret_
, we also substitutex
int
withuu___ret_
.That way, core typechecker uniformly works with an explicit binder for the
returns
annotation.When resugaring, we check that if the binder name for the returns annotation is the internal name
uu___ret_
, we do not print it, and appropriately substitute the scrutinee back if necessary. See https://github.com/FStarLang/FStar/blob/aseem_dependent_pattern_matching2/tests/prettyprinting/Match.Returns.fst and https://github.com/FStarLang/FStar/blob/aseem_dependent_pattern_matching2/tests/prettyprinting/Match.Returns.fst.expected for pretty-printing testcases.Reflection AST, embeddings, and unembeddings are also fixed accordingly.
Typechecker
To typecheck
We first typecheck
G |- e : C_e
. Then we typecheckG, x : C_e.t |- C : _
, i.e. extend the environment withx:t
wheret
is the type ofe
and typecheckC
. Then we ascribe each branch ase_i <: C[P_i/x]
, and typecheck the ascribed branch. The final type of thematch
result is computed asC[e/x]
(as usual we later bind it withC_e
).