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

Spread in objects #4473

Closed
wants to merge 5 commits into from
Closed

Spread in objects #4473

wants to merge 5 commits into from

Conversation

zdenko
Copy link
Collaborator

@zdenko zdenko commented Mar 23, 2017

Connected to #3894.

In CS2 emit

obj = { x: 1, y: 2}
obj1 = {obj..., z: 3}

to

obj1 = {...obj, z: 3}

Improve destructuring assignment for object literal:

{a, b, x...} = {a:1, b:2, c:3, d:4, e:5}
a = 1
b = 2
x = {c:3, d:4, e:5}
{c, x..., e} = {a:1, b:2, c:3, d:4, e:5}
c = 3
e = 5
x = {a:1, b:2, d:4}
{c, x..., a:p} = {a:1, b:2, c:3, d:4, e:5}
c = 3
p = 1
x = {b:2, d:4, e:5}
futurists =
  sculptor: "Umberto Boccioni"
  painter:  "Vladimir Burliuk"
  poet:
    name:   "F.T. Marinetti"
    address: [
      "Via Roma 42R"
      "Bellagio, Italy 22021"
    ]

{poet: {name, addr1...}} = futurists
addr1 = {address: [ "Via Roma 42R",  "Bellagio, Italy 22021"]}

{poet: {addr2..., name:title}} = futurists
addr2 = {address: [ "Via Roma 42R",  "Bellagio, Italy 22021"]}

@@ -1748,6 +1748,13 @@ exports.Assign = class Assign extends Base
vvarText = fragmentsToText vvar
assigns = []
expandedIdx = false
# check if variable is object and containes splat, e.g. {a, b, c...}
hasSplat = isObject and (i for obj, i in objects when obj instanceof Splat).length == 1
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it's better to error out if length>1?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Since multiple splats/expansions are disallowed in an assignment, length == 1 should be ok?

Copy link
Collaborator

Choose a reason for hiding this comment

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

No. We need to show a nice error message, like when you try to use multiple splats in array desctructuring or parameter list.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is the current status :

./bin/coffee -e "{a, x..., c, y...} = {a:1, b:2, c:3, d:4, e:5}"
[stdin]:1:14: error: multiple splats/expansions are disallowed in an assignment
{a, x..., c, y...} = {a:1, b:2, c:3, d:4, e:5}

test "destructuring assignment with objects and splats: ES2015", ->
obj = {a:1, b:2, c:3, d:4, e:5}
{a:x, b, r...} = obj
{a:y, c..., d} = obj
Copy link
Collaborator

Choose a reason for hiding this comment

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

The rest element has to be last, according to Babel: http://babeljs.io/repl/#?babili=false&evaluate=false&lineWrap=false&presets=es2015%2Cstage-2%2Cstage-3&targets=&browsers=&builtIns=false&code=const%20%7Ba%3Ay%2C%20...c%2C%20d%7D%20%3D%20obj&experimental=false&loose=false&spec=false&playground=true

I guess CoffeeScript should support it anywhere, though, just like for arrays? I guess we just need to move the splat last in the compiled JS.

eq c.b, b
eq r.e, c.e

test "destructuring assignment with context (@) properties: ES2015", ->
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't see any @s in this test?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's a typo. I copied the string.

@@ -1748,6 +1748,13 @@ exports.Assign = class Assign extends Base
vvarText = fragmentsToText vvar
assigns = []
expandedIdx = false
# check if variable is object and containes splat, e.g. {a, b, c...}
hasSplat = isObject and (i for obj, i in objects when obj instanceof Splat).length == 1
Copy link
Collaborator

Choose a reason for hiding this comment

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

No. We need to show a nice error message, like when you try to use multiple splats in array desctructuring or parameter list.

# obj2 = "#{{obj1..., b: 3}}"
t1 = CoffeeScript.compile "{obj1..., b: 3}", bare: yes
t1 = t1.replace(/\s+/g, "")
eq t1, "({...obj1,b:3});"
Copy link
Collaborator

Choose a reason for hiding this comment

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

The rule has been to never compare strings with the compiled output JS, unless there's no other way to assert that the compiled code works as intended. Also, CoffeeScript always strives to produce readable output. You need to add some spaces in there.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Error for multiple splats is already there at line 1791 in lib/nodes.coffee

Copy link
Collaborator

Choose a reason for hiding this comment

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

Did you reply to the wrong comment? :)

Anyway, we need a test for the multiple splats error.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sorry. Long hours :(

Anyway, I couldn't find example how to test the output of obj2 = {obj1..., b:5}
CS compiles it to

(function() {
  var obj2;

  obj2 = {
    ...obj1,
    b: 5
  };

}).call(this);

but test fails since the syntax {...obj1, b:5} is currently in stage-3 and requires Babel.

To rephrase the question, can Babel be used for tests?

Copy link
Collaborator

Choose a reason for hiding this comment

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

It is our policy to only support ES features that have reached stage 4, and are supported in the Node runtime (modules are the big exception to this). Therefore the test would compile to the finalized ES syntax, and Node should be able to run it.

@GeoffreyBooth
Copy link
Collaborator

@zdenko thank you for making this effort! Do you feel like helping with the destructuring branch? The goal there is to output ES2015 destructured syntax whenever possible. Certain Coffee destructuring arrangements aren’t possible in ES, so should stay as they are; and default values should follow the ES style of only getting applied with the variable is undefined, not undefined or null.

@zdenko
Copy link
Collaborator Author

zdenko commented Mar 23, 2017

@GeoffreyBooth sure.

So, the output of destructuring
{a, b, x...} = {a:1, b:2, c:3, d:4}
should be
{a, b, ...x} = {a:1, b:2, c:3, d:4}

And, the rest element has to be the last element.

@GeoffreyBooth
Copy link
Collaborator

GeoffreyBooth commented Mar 24, 2017

@zdenko that syntax doesn’t seem to work for me, but in general, yes, whenever there is an ES destructured syntax that is equivalent to a CoffeeScript one, we want to output the ES one. In #4311 I refactored the handling of function parameters to support expansions and splats output as ES; if the splat was the last parameter, the conversion was straightforward, otherwise a placeholder splat became the last parameter and further assignments happened in the function body. We could do something similar for destructuring.

@zdenko
Copy link
Collaborator Author

zdenko commented Mar 24, 2017

@GeoffreyBooth this syntax should work.

The proposal for object rest/spread properties is in stage-3.

Since CS supports only stage-4, the output of object spread should be:
n = {x, y, z...} => n = Object.assign({}, x, y, z}
n = { a..., { x: 1, y: 2 }... } => n = Object.assign({}, a, { x: 1, y: 2 })

Is that correct?

@GeoffreyBooth
Copy link
Collaborator

Closing in favor of #4493

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.

4 participants