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 empty record declaration #1536

Closed
wants to merge 21 commits into from
Closed

Conversation

objmagic
Copy link
Contributor

@objmagic objmagic commented Dec 18, 2017

This PR adds support of empty record declaration.

Support empty record declaration can

  1. bring more consistency in the language
  2. solve some practical issues. For example, ocaml-pb can generate proper code for empty protobuf message.

See Mantis #7583 for more details.

Implementation in this PR might be inefficient during type-checking phase because we will search empty record declaration in environment in linear time complexity (instead of other find- methods in env.ml which will use Path.t to do search in a AVL tree). That said, another approach is to allow {} as user-defined constructor as we did in #234

Signed-off-by: Runhang Li <marklrh@gmail.com>
Signed-off-by: Runhang Li <marklrh@gmail.com>
Signed-off-by: Runhang Li <marklrh@gmail.com>
Signed-off-by: Runhang Li <marklrh@gmail.com>
Signed-off-by: Runhang Li <marklrh@gmail.com>
Signed-off-by: Runhang Li <marklrh@gmail.com>
Signed-off-by: Runhang Li <marklrh@gmail.com>
@@ -1284,7 +1284,11 @@ and transl_record loc env fields repres opt_init_expr =
match repres with
| Record_regular -> Lconst(Const_block(0, cl))
| Record_inlined tag -> Lconst(Const_block(tag, cl))
| Record_unboxed _ -> Lconst(match cl with [v] -> v | _ -> assert false)
| Record_unboxed _ -> Lconst(
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the point of "unboxing" an empty record type, since the representation ends up being the same as the regular representation?

@@ -1397,8 +1398,11 @@ and type_declaration ctxt f x =
in
match x.ptype_kind with
| Ptype_variant xs ->
pp f "%t%t@\n%a" intro priv
(list ~sep:"@\n" constructor_declaration) xs
if xs = [] then
Copy link
Contributor

Choose a reason for hiding this comment

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

This is about empty variants, not empty records.

typing/oprint.ml Outdated
fprintf ppf " =%a@;<1 2>%a"
print_private td.otype_private
(print_list print_out_constr (fun ppf -> fprintf ppf "@ | ")) constrs
if constrs = [] then
Copy link
Contributor

Choose a reason for hiding this comment

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

Also for empty variants, not records.

None -> newvar (), None
| None ->
if lid_sexp_list = [] then begin
match Env.find_empty_record env with
Copy link
Contributor

Choose a reason for hiding this comment

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

This part could be shared with the similar addition type type_pat.

@@ -1707,7 +1707,8 @@ expr_comma_list:
| expr COMMA expr { [$3; $1] }
;
record_expr:
simple_expr WITH lbl_expr_list { (Some $1, $3) }
{ (None, []) }
Copy link
Contributor

Choose a reason for hiding this comment

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

Empty rules usually have /* empty */ in parser.mly.

@objmagic
Copy link
Contributor Author

@alainfrisch There are some changes about empty variants that I forgot to clean up. I will remove then address your comments next morning when I get up.

@@ -407,9 +407,7 @@ and type_declaration =
and type_kind =
| Ptype_abstract
| Ptype_variant of constructor_declaration list
(* Invariant: non-empty list *)
Copy link
Contributor

Choose a reason for hiding this comment

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

The comment related to Ptype_variant shouldn't be removed.

@objmagic objmagic force-pushed the empty-record branch 2 times, most recently from 6ebbda6 to 07b4a17 Compare December 19, 2017 06:26
@xavierleroy
Copy link
Contributor

At the last developers's meeting, there was consensus to support empty sum types, but empty record types were controversial. Have we really decided to support empty record types? Could we get a decision before spending more time reviewing and polishing this GPR?

@objmagic
Copy link
Contributor Author

@xavierleroy

Hi, Xavier. I understand empty record is controversial but I'd like to open a PR just for some initial discussion. As for empty sum type, I noticed some cases my implementation does not handle. I am going to fix the problem soon.

@garrigue
Copy link
Contributor

Ok, then I suppose that we should have a discussion.

Basically, I see at least 2 ways to handle empty records without adding anything to the language:

  • Have your code generator emit () rather than {}. Doesn't seem too difficult.
    We could even make {} an alias for (), but some are going to complain that this is a waste of syntactic resources...

  • If you want the thing to be nominal, make it a singleton variant type: type t = Empty_t.
    This even gives you a way to use the constructor without ambiguity.

Honestly I think that the first solution is sufficient: I cannot really imagine why you would want to make your empty record nominally distinct, as anyway it has no semantical contents.

Regularity is nice, when it is really regular. Adding empty records as records requires modifications to the way we handle records that make me think that they are not regular records.

@yallop
Copy link
Member

yallop commented Dec 28, 2017

The following code is already valid OCaml (and introduces isomorphic/nominally-distinct types):

    type s = []
    type t = []

so it seems reasonable to allow the essentially equivalent code:

    type s = {}
    type t = {}

But since there are plenty of workarounds and a clear lack of enthusiasm it doesn't seem worth spending much more time on this.

@objmagic
Copy link
Contributor Author

close this PR as it is deemed controversial

@objmagic objmagic closed this Dec 31, 2017
EmileTrotignon pushed a commit to EmileTrotignon/ocaml that referenced this pull request Jan 12, 2024
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

6 participants