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

Proposal: make Pervasives.ref abstract type #6994

Closed
vicuna opened this issue Sep 17, 2015 · 7 comments
Closed

Proposal: make Pervasives.ref abstract type #6994

vicuna opened this issue Sep 17, 2015 · 7 comments

Comments

@vicuna
Copy link

vicuna commented Sep 17, 2015

Original bug ID: 6994
Reporter: @bobzhang
Assigned to: @alainfrisch
Status: closed (set by @alainfrisch on 2016-07-13T07:30:10Z)
Resolution: fixed
Priority: normal
Severity: feature
Category: standard library
Monitored by: @diml @ygrek @jmeber @hcarty

Bug description

Current ref is defined as follows

type 'a ref = {mutable contents : 'a }

I suggest we hide its implementation, and change the primitive name for function "ref" and "!" accordingly, so in the lambda layer we know it's a reference or not.

The immediate benefit is that my OCaml to Javascript backend(http://zhanghongbo.me/js-demo/) would not create a block, there is an optimization pass to eliminate ref in lambda layer, but that's not complete, other benefit maybe include avoid unboxing `int ref' etc.

The cost is it might break some existing programs, but the expressivity is not lost.

@vicuna
Copy link
Author

vicuna commented Sep 18, 2015

Comment author: @alainfrisch

A possible direction would be to keep more information in the lambda code: record literals and field updates/access could be identified as such (with an indication of the type definition).

@vicuna
Copy link
Author

vicuna commented Sep 18, 2015

Comment author: @bobzhang

@Frish would you elaborate your solution?

My original proposal is quite easy to implement.

Thinking twice, I think a more general solution (without breaking existing code) is even better

  1. providing a special destruction primitive when the record is only one field

for example

type t = { x : int }

let f u = u.x -> instead of (Pfield 0 x) --> (Pgetonlyfield x)

  1. Generalize it also for variant, when you have only one branch for constant or constructors, introduce special instructions, for example

type 'a option = None | Some of 'a
None -> 0
Some 3 -> [3] (*current [0,3] *)
type 'a list = Nil | Cons of 'a * 'a list
Nil -> 0
Cons (3,Cons (3,Nil)) -> [3,[3,0]] (*current [0,3,[0,3,0]] *)

This solution is definitely much better than my original proposal, but it depends on how much resources you have. What do you think?

@vicuna
Copy link
Author

vicuna commented Sep 18, 2015

Comment author: @alainfrisch

@Frish would you elaborate your solution?

I was thinking about keeping the reference to the type declaration in the lambda representation. As in: (Precordfield 0 r d) with d of type Types.type_declaration. But this is a real departure of the current philosophy for the lambda code, where all type information is erased. (To interpret the type_declaration, we would also need to keep the typing environment.) This would blur the distinction with Typedtree, and at some point, it might just make more sense to base your project on Typedtree (which would give more freedom to map high-level constructions such as pattern matching, functors, objects to more "idiomatic" JS code). Did you consider doing that?

(Pfield 0 x) --> (Pgetonlyfield x)

I'm not sure exactly how you would use that in your project. But a less ad hoc approach would be to annotate Pfield with the size of the block (if known).

introduce special instructions

Breaking the concrete representation of existing types is not possible (think about the C FFI).

@vicuna
Copy link
Author

vicuna commented Sep 18, 2015

Comment author: @bobzhang

I did think about take it from ocaml typedtree, and it might not be that hard, but I also have to maintain the code, there is always a trade off, currently, the output is already pretty good (good enough to guarantee a good FFI)so that I am not strongly motivated to work on `from typedtree'.
FYI, I did use type environment in my project, but it is only used to query some very basic information

Yes, Pfield with size is more general, but it should be sound and complete.

Introducing special instructions will not break existing C FFI, since after lambda layer, nothing is changed, the point is that the datatype representation is tailed for C, the javascript backend does not need follow the same(we loose something like marshal, but there is a way to bring it back in the future)

@vicuna
Copy link
Author

vicuna commented Sep 19, 2015

Comment author: @chambart

By the way I would also be interested in adding more type informations to getfield, but for other reasons. The two main ones would be the size of the original type, and the mutability of the field. The main examples would be optimizing constructions like:

let a = immutable_field 1 x in
let b = immutable_field 1 x in
...

In that case a and b can be safely shared.

match x with
| tag_1 ->
let a_0 = immutable_field 0 x (size 2) in
let a_1 = immutable_field 1 x (size 2) in
makeblock tag_1 [a_0; a_1]

can be simplified to

match x with
| tag_1 -> x

@vicuna
Copy link
Author

vicuna commented Oct 8, 2015

Comment author: @mshinwell

+1 to chambart's suggestions

@vicuna
Copy link
Author

vicuna commented Jul 13, 2016

Comment author: @alainfrisch

It would break too much code to change the definition of ['a ref]. As for adding more type information to Lambda, if this is still relevant, this should be discussed in specific tickets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants