LeoHorie
LeoHorie

Reputation: 1320

Is it possible to make a sweet.js macro `m` expand to the symbol `m`?

Suppose there's a function somewhere called m, which is invoked like this

//foo.js
m("foo")

I have a sweet.js macro that defines a macro called m which is meant to take foo.js and expand m (basically to run the function at compile time)

In some cases I want to not expand m, because unlike macros, functions can be passed around as first class citizens

doSomething(m) //don't want to expand this as a macro

If I don't have a case that covers this scenario in the macro, sweet.js complains, so I need to have a catch-all rule that just expands to the same symbol.

macro m {
  //simplification to demonstrate a case that recursively expand macro
  case { _ ( $foo, $bar) } => { return #{m($foo)} }
  //does syntax unwrapping in real case
  case { _ ( $foo ) } => { return #{$foo} }

  //**this tries to recursively expand `m`, which is not what I want**
  case { _ } => { return #{m} } 
}

How do I make the m macro expand to the m function, given that other cases of the macro do need to recursively expand m as a macro?

Upvotes: 0

Views: 99

Answers (1)

timdisney
timdisney

Reputation: 5337

You'll want to let bind the macro:

let m = macro {
  case { _ ( $foo, $bar) } => { return #{$foo} }
  case { _ ( $foo ) } => { return #{$foo} }

  // `m` is bound to the surrounding scope, not the macro
  case { _ } => { return #{m} }
}

Edit:

Sorry, didn't read your question fully the first time :)

Here's a better solution, you just need to split it out into two different macros, one that can do the actual recursive work and another to handle the non-recursive base case:

function m() {}
macro m_impl {
  case { _ ( $foo, $bar) } => { return #{m_impl($foo)} }
  case { _ ( $foo ) } => { return #{$foo} }
}

let m = macro {
  case { _ ($foo, $bar) } => { return #{m_impl($foo, $bar)} } 
  case { _ } => { return #{m} } 
}

m (100, 200);
doSomething(m)

Upvotes: 1

Related Questions