-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Syntax proposal: let punning #10013
Syntax proposal: let punning #10013
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -458,6 +458,7 @@ let extra_rhs_core_type ct ~pos = | |
type let_binding = | ||
{ lb_pattern: pattern; | ||
lb_expression: expression; | ||
lb_is_pun: bool; | ||
lb_attributes: attributes; | ||
lb_docs: docs Lazy.t; | ||
lb_text: text Lazy.t; | ||
|
@@ -469,27 +470,30 @@ type let_bindings = | |
lbs_extension: string Asttypes.loc option; | ||
lbs_loc: Location.t } | ||
|
||
let mklb first ~loc (p, e) attrs = | ||
let mklb first ~loc (p, e, is_pun) attrs = | ||
{ | ||
lb_pattern = p; | ||
lb_expression = e; | ||
lb_is_pun = is_pun; | ||
lb_attributes = attrs; | ||
lb_docs = symbol_docs_lazy loc; | ||
lb_text = (if first then empty_text_lazy | ||
else symbol_text_lazy (fst loc)); | ||
lb_loc = make_loc loc; | ||
} | ||
|
||
let addlb lbs lb = | ||
if lb.lb_is_pun && lbs.lbs_extension = None then syntax_error (); | ||
{ lbs with lbs_bindings = lb :: lbs.lbs_bindings } | ||
gasche marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
let mklbs ~loc ext rf lb = | ||
{ | ||
lbs_bindings = [lb]; | ||
let lbs = { | ||
lbs_bindings = []; | ||
lbs_rec = rf; | ||
lbs_extension = ext ; | ||
lbs_loc = make_loc loc; | ||
} | ||
|
||
let addlb lbs lb = | ||
{ lbs with lbs_bindings = lb :: lbs.lbs_bindings } | ||
} in | ||
addlb lbs lb | ||
|
||
let val_of_let_bindings ~loc lbs = | ||
let bindings = | ||
|
@@ -2418,7 +2422,7 @@ labeled_simple_expr: | |
%inline let_ident: | ||
val_ident { mkpatvar ~loc:$sloc $1 } | ||
; | ||
let_binding_body: | ||
let_binding_body_no_punning: | ||
let_ident strict_binding | ||
{ ($1, $2) } | ||
| let_ident type_constraint EQUAL seq_expr | ||
|
@@ -2454,6 +2458,12 @@ let_binding_body: | |
{ let loc = ($startpos($1), $endpos($3)) in | ||
(ghpat ~loc (Ppat_constraint($1, $3)), $5) } | ||
; | ||
let_binding_body: | ||
| let_binding_body_no_punning | ||
{ let p,e = $1 in (p,e,false) } | ||
| val_ident %prec below_HASH | ||
{ (mkpatvar ~loc:$loc $1, mkexpvar ~loc:$loc $1, true) } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nitpick: I suspect that if you had used a |
||
; | ||
(* The formal parameter EXT can be instantiated with ext or no_ext | ||
so as to indicate whether an extension is allowed or disallowed. *) | ||
let_bindings(EXT): | ||
|
@@ -2485,6 +2495,9 @@ and_let_binding: | |
letop_binding_body: | ||
pat = let_ident exp = strict_binding | ||
{ (pat, exp) } | ||
| val_ident | ||
(* Let-punning *) | ||
{ (mkpatvar ~loc:$loc $1, mkexpvar ~loc:$loc $1) } | ||
| pat = simple_pattern COLON typ = core_type EQUAL exp = seq_expr | ||
{ let loc = ($startpos(pat), $endpos(typ)) in | ||
(ghpat ~loc (Ppat_constraint(pat, typ)), exp) } | ||
|
@@ -2495,7 +2508,7 @@ letop_bindings: | |
body = letop_binding_body | ||
{ let let_pat, let_exp = body in | ||
let_pat, let_exp, [] } | ||
| bindings = letop_bindings pbop_op = mkrhs(ANDOP) body = let_binding_body | ||
| bindings = letop_bindings pbop_op = mkrhs(ANDOP) body = letop_binding_body | ||
{ let let_pat, let_exp, rev_ands = bindings in | ||
let pbop_pat, pbop_exp = body in | ||
let pbop_loc = make_loc $sloc in | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1314,8 +1314,14 @@ and bindings ctxt f (rf,l) = | |
(list ~sep:"@," (binding "and" Nonrecursive)) xs | ||
|
||
and binding_op ctxt f x = | ||
pp f "@[<2>%s %a@;=@;%a@]" | ||
x.pbop_op.txt (pattern ctxt) x.pbop_pat (expression ctxt) x.pbop_exp | ||
match x.pbop_pat, x.pbop_exp with | ||
| {ppat_desc = Ppat_var { txt=pvar; _ }; ppat_attributes = []; _}, | ||
{pexp_desc = Pexp_ident { txt=Lident evar; _}; pexp_attributes = []; _} | ||
when pvar = evar -> | ||
pp f "@[<2>%s %s@]" x.pbop_op.txt evar | ||
| pat, exp -> | ||
pp f "@[<2>%s %a@;=@;%a@]" | ||
x.pbop_op.txt (pattern ctxt) pat (expression ctxt) exp | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remark: if I understand correctly, we have pretty-printing support for the binding operator form, but not for the extension form. This is just fine as far as I am concerned. |
||
|
||
and structure_item ctxt f x = | ||
match x.pstr_desc 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 we are going to have this wart in the codebase, let's turn it into a strength that will make ocamlformat people happy: use it also for binding operators, and use this boolean when reprinting the AST.
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'm not quite sure what you're suggesting here? The type
let_binding
is not part of the AST, but rather a temporary structure used byparser.mly
to share code between various constructs that have similar syntax.