2

I'm trying to write a sweet.js macro which needs to generate method call syntax, obj.method(), but the method is passed in to the macro as a literal expression. For example:

mcall(obj, toString().length);
// becomes
obj.toString().length;

I've got something that's close:

macro mcall {
  rule { ($o, $m:expr) } => { $o.$m }
}

mcall(obj, toString().length);

However, this apparently expands to this:

obj . ( toString ( ) . length );

Where are these extra parentheses coming from, and how do I get rid of them? Should I be using case rules and #{}? I tried permutations of that but still couldn't succeed at generating a method call without extra parentheses.

Daniel Buckmaster
  • 7,108
  • 6
  • 39
  • 57

1 Answers1

2

So currently in sweet.js tokens bound to an :expr pattern variable get wrapped in parens to help with getting precedence to work correctly. This is kind of a hack and will get fixed soon (some more discussion here: https://github.com/mozilla/sweet.js/issues/314).

The simple solution for your example is to just not use :expr since you don't really need it:

macro mcall {
  rule { ($o, $m ...) } => { $o.$m ... }
}

Side note: using :expr is technically wrong here since the RHS of a . is not allowed to be an unrestricted expression (eg 2+4 matches $m:expr but obj.2+4 is a syntax error).

timdisney
  • 5,287
  • 9
  • 35
  • 31
  • Thanks heaps! You're right, using an `expr` was technically wrong. I'm using this to [emulate Scala's placeholders](http://stackoverflow.com/questions/24177294/placeholders-for-anonymous-functions-in-javascript/24178372#24178372). – Daniel Buckmaster Jun 14 '14 at 03:07