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

Syntax proposal: let punning #10013

Merged
merged 3 commits into from Dec 8, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions Changes
Expand Up @@ -3,6 +3,9 @@ Working version

### Language features:

- #??: Let-punning
(Stephen Dolan, review by ??)
Copy link
Member

Choose a reason for hiding this comment

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

I guess we need to refine this to "binding-operator punning". Could you include an actual example (and its desugaring)?

Copy link
Member

Choose a reason for hiding this comment

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

Also, are you sure that it is let-punning not let-prunning?

Copy link
Member

Choose a reason for hiding this comment

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

The name we use really is "punning". I think of it as a "pun" in that we use something for something else (the name of a declaration as its definition). The naming "record field punning" is well-established and more or less (well, remotely) consistent with type punning for example.

Copy link
Member

Choose a reason for hiding this comment

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

haha, I was always under impression that I was using type pruning)) Good day I have learned something new)


### Runtime system:

### Code generation and optimizations:
Expand Down
13 changes: 9 additions & 4 deletions boot/menhir/menhirLib.ml
Expand Up @@ -43,7 +43,7 @@ let rec uniq1 cmp x ys =
[]
| y :: ys ->
if cmp x y = 0 then
uniq1 compare x ys
uniq1 cmp x ys
else
y :: uniq1 cmp y ys

Expand Down Expand Up @@ -85,7 +85,6 @@ let rec foldr f xs accu =
accu
| Cons (x, xs) ->
f x (foldr f xs accu)

end
module Convert = struct
(******************************************************************************)
Expand Down Expand Up @@ -3133,8 +3132,14 @@ module Make
type item =
int * int

let low_bits =
10

let low_limit =
1 lsl low_bits

let export t : item =
(t lsr 7, t mod 128)
(t lsr low_bits, t mod low_limit)

let items s =
(* Map [s] to its LR(0) core. *)
Expand Down Expand Up @@ -3513,5 +3518,5 @@ module MakeEngineTable (T : TableFormat.TABLES) = struct
end
end
module StaticVersion = struct
let require_20190924 = ()
let require_20200624 = ()
end
2 changes: 1 addition & 1 deletion boot/menhir/menhirLib.mli
Expand Up @@ -1701,5 +1701,5 @@ module MakeEngineTable
and type nonterminal = int
end
module StaticVersion : sig
val require_20190924 : unit
val require_20200624: unit
end
5,860 changes: 2,858 additions & 3,002 deletions boot/menhir/parser.ml

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion parsing/parser.mly
Expand Up @@ -2485,6 +2485,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) }
Expand All @@ -2495,7 +2498,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
Expand Down
10 changes: 8 additions & 2 deletions parsing/pprintast.ml
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The 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
Expand Down
9 changes: 9 additions & 0 deletions testsuite/tests/parsetree/source.ml
Expand Up @@ -7414,3 +7414,12 @@ let test = function

let test = function
| (`A | `B) as x | `C -> ()

(* Let-punning *)
module M = struct
let (let*) x f = f x
let (and*) a b = (a, b)
let x = 1 and y = 2 and z = 3
let p =
let* x and* y and* z in (x,y,z)
end