Search code examples
sweet.js

Why are case macros not nesting?


Given this sweet.js macro

macro m {
    case { _ ( $a, $b ) } => {
        return #{$a + $b};
    }
    case { _ ( $a ) } => {
        return #{$a};
    }
    case { _ } => {
        return #{no};
    }
}

export m;

And this source code:

m(1, [m(2)]);
m(1, m(2));

How do you create a case that yields this output:

1 + [2];
1 + 2;

Instead of this?

1 + [2];
no(1, 2);

P.S. the actual use case requires case macros, not rule macros.


Solution

  • The basic thing you're running into here is that a pattern variable only matches a single token so in m(1, m(2)) the pattern $b gets bound to m not m(2). This is because the inner m macros don't get expanded before the outer m macro runs.

    The easiest way to fix this is to use ...:

    macro m {
        case { _ ( $a ..., $b ...) } => {
        return #{$a ... + $b ...};
        }
        case { _ ( $a ... ) } => {
        return #{$a ...};
        }
        case { _ } => {
        return #{no};
        }
    }