2

I want to expand a token to a string. For example, I have this macro:

macro String {
  rule {
    $x
  } => {
    "$x"
  }
}

I would expect String 1 to expand to "1", however it expands to just 1;

How can I accomplish this?

EDIT: This seems imposible to do with a declarative approach, but should be possible with an imperative approach (see this comment):

macro String {
  case {_ $x } => {        
    return #{"$x"}
  }
}

But that still expands with quotes.

locks
  • 6,537
  • 32
  • 39
jviotti
  • 17,881
  • 26
  • 89
  • 148
  • Hav you tried with toString() ? – felipekm Jan 09 '14 at 16:17
  • @FelipeKM That will just expand `toString()` in the result. The quotes should be added by the macro. – jviotti Jan 09 '14 at 16:22
  • @jviotti I found this issue on Sweet.js's Github: https://github.com/mozilla/sweet.js/issues/45 Seems to be exactly what you want but it was closed without any mention of how to actually do it. – ToastyMallows Jan 09 '14 at 18:04
  • 1
    @ToastyMallows exactly what I was looking for. In this comment (https://github.com/mozilla/sweet.js/issues/45#issuecomment-9761435) disnet says it's impossible to do with a declarative approach, but can be done with the imperative one. That issue is a year old and imperative approach has already been implemented. However still can't figure it out with that approach. – jviotti Jan 09 '14 at 18:29
  • @jviotti You and me both, I've been trying for an hour! If no one answered by tonight I'm going to install sweet.js and try to figure it out on my computer at home. – ToastyMallows Jan 09 '14 at 18:38
  • @ToastyMallows No need to install! You can try it live at http://sweetjs.org/browser/editor.html. – jviotti Jan 09 '14 at 18:41
  • @jviotti I know but the `#{}` syntax doesn't seem to be working properly. It keeps underlining `#{$x}` in red but it seems to be valid syntax according to sweetjs.org – ToastyMallows Jan 09 '14 at 18:42
  • @ToastyMallows the imperative example in the bottom of my question is working for me on the web editor. – jviotti Jan 09 '14 at 18:54
  • @jviotti Hmm ok, I'll keep working at it. – ToastyMallows Jan 09 '14 at 19:02

2 Answers2

4

As noted in this issue thread, you can do it with an imperative approach, but it's a bit awkward and not well-documented. Basically, you do it like this:

macro String {
  case {_ $x} => {
    var pattern = #{$x};
    var tokenString = pattern[0].token.value.toString();
    var stringValue = makeValue(tokenString, #{$here});
    return withSyntax($val = [stringValue]) {
      return #{$val};
    }
  }
}

BTW, I wouldn't call this macro "String" — it conflicts with the existing String that's natively part of JavaScript.

Chuck
  • 234,037
  • 30
  • 302
  • 389
  • http://sweetjs.org/browser/editor.html#macro%20makeString%20%7B%0A%20%20case%20%7B_%20$x%7D%20=%3E%20%7B%0A%20%20%20%20var%20pattern%20=%20#%7B$x%7D;%0A%20%20%20%20var%20tokenString%20=%20pattern%5B0%5D.token.value;%0A%20%20%20%20var%20stringValue%20=%20makeValue(tokenString,%20#%7B$here%7D);%0A%20%20%20%20return%20withSyntax($val%20=%20%5BstringValue%5D)%20%7B%0A%20%20%20%20%20%20return%20#%7B$val%7D;%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%0AmakeString%204 I'm still getting just `4`, not `"4"`. – ToastyMallows Jan 09 '14 at 20:01
  • Works for nonnumbers. `String ! = "!"`, String something = `something`. Still numbers remain unquoted. – jviotti Jan 09 '14 at 21:55
  • 1
    @jviotti: Good point. I think we can just stringify it, though. Updated and it seems to work in the Sweet.js editor with all types. – Chuck Jan 09 '14 at 23:50
3

While you still need to use a case macro, it can be more terse than Chuck's answer using unwrapSyntax and letstx:

macro makeStr1 {
  case {_ $x} => {
    var pattern = #{$x};
    var asStr = unwrapSyntax(pattern).toString();
    letstx $xStr = [makeValue(asStr, pattern)];
    return #{$xStr};
  }
}

We can do better, though. How about macros in macros?

macro syntaxToStr {
  rule {$x} => {
    [makeValue(unwrapSyntax($x).toString(), $x)]
  }
}

macro makeStr {
  case {_ $x} => {
    letstx $xStr = syntaxToStr(#{$x});
    return #{$xStr}
  }
}
ShawnFumo
  • 2,108
  • 1
  • 25
  • 14