sweet-js / sweet-core

Sweeten your JavaScript.
https://www.sweetjs.org
BSD 2-Clause "Simplified" License
4.58k stars 208 forks source link

Problems returning arrow function expression from macro #684

Open gabejohnson opened 7 years ago

gabejohnson commented 7 years ago

While trying to implement a let expression macro I realized I wasn't taking this into account. So instead of using a IIFE I tried using an [arrow function](http://sweetjs.org/browser/editor.html#import%20%7BisIdentifier,%20isParens,%20isPunctuator%7D%20from%20'sweet.js/helpers'%20for%20syntax;%0A%0Asyntax%20let%20=%20function%20(ctx)%20%7B%0A%20%20let%20params%20=%20ctx.next().value;%0A%20%20%0A%20%20if%20(isIdentifier(params))%20%7B%0A%20%20%20%20return%20#%60let%20$%7Bparams%7D%60;%0A%20%20%7D%20else%20if(!isParens(params))%20%7B%0A%20%20%20%20throw%20Error('Expecting%20an%20identifier%20or%20a%20list%20of%20identifiers.');%0A%20%20%7D%0A%20%20let%20body%20=%20ctx.next().value%20%7C%7C%20#%60%60;%0A%20%20let%20inner%20=%20ctx.contextify(body);%0A%20%20let%20stmts%20=%20#%60%60;%0A%20%20let%20stmt;%0A%20%20%0A%20%20let%20tmpStmts%20=%20%5B%5D;%0A%20%20%0A%20%20while%20(true)%20%7B%0A%20%20%20%20stmt%20=%20inner.expand('stmt');%0A%20%20%20%20if%20(stmt.done)%20break;%0A%20%20%20%20tmpStmts.push(stmt);%0A%20%20%7D%0A%20%20%0A%20%20inner.reset();%0A%20%20for%20(var%20i%20=%200;%20i%20%3C%20tmpStmts.length%20-%201;%20i++)%20%7B%0A%20%20%20%20stmt%20=%20inner.expand('stmt').value;%0A%20%20%20%20stmts%20=%20stmts.concat(#%60$%7Bstmt%7D%60);%0A%20%20%7D%0A%20%20let%20last%20=%20%5B...inner%5D;%0A%20%20if%20(isPunctuator(last%5Blast.length-1%5D,%20';'))%20last.pop();%0A%20%20stmts%20=%20stmts.concat(#%60return%20($%7Blast%7D)%60);%0A%20%20%0A%20%20return%20#%60($%7Bparams%7D%20=%3E%20%7B$%7Bstmts%7D%7D)()%60;%0A%7D;%0A%0Alet%20(a%20=%201,%20b%20=%20a)%20%7B%20a%20+%20b%20%7D%0A):

let (a = 1, b = a) { a + b }

// expected
((a_100 = 1, b_101 = a_100) => { return a_100 + b_101; })()

// actual
  Error: unexpected syntax
=> { return [object Object] }
disnet commented 7 years ago

Here's a minimal repro:

syntax let = function (ctx) {
  let params = ctx.next().value;
  return #`(${params} => 1)`;};

let (a)

Something wrong converting a RawDelimiter to a paren list? Maybe with the template replacement code?

btw, using an arrow will handle this but now you've broken break/continue and return :( Maybe just use a block with a normal let:

let (a = 1, b = a) { a + b }
// -->
{
let a = 1, b = a;
a + b;
}
gabejohnson commented 7 years ago

It's an "expression", so I don't need break/continue. I'm thinking of using it from a ternary:

const foo = n => n > 5 ? n : let(a = 1, b = n) { ...; a + b; };

Was just messing around. I am breaking return though. Can we have shift/reset? 😛