-
Notifications
You must be signed in to change notification settings - Fork 211
Syntax Case
The new procedural macros let us define our macros using JavaScript.
macro m {
case {_ ($x) } => {
console.log("I'm in ur macros!");
return #{ $x }
}
}
m (42)
// ---> expands to
42 // logs: I'm in ur macros!
Changes from old design:
- The pattern is now wrapped in a curly brace to prevent ambiguity. Previously
case $x => ...
would matchm 42
but now this is an error. Instead docase {_ $x } => ...
. - Also the macro name is being matched as the first pattern and the wildcard pattern
_
has been added so you can ignore it if you want. - The template form
#{...}
has been added. Any bound pattern variables that are in scope are replaced with their match. - Cases are matched in-order. Previously they were being matched by length first.
- The
...
pattern now matches zero or more. Previously it was one or more.
For constructing new syntax objects we have the following primitive functions that are in scope inside a procedural macro. These loosely correspond to Scheme's datum->syntax
but because JS has different token types we need the different functions. The first argument to each of these functions is used to construct the token and the context is taken from the optional second argument.
makeValue :: (Any, Null or Syntax) -> Syntax
BooleanLiteral
NullLiteral
NumericLiteral
StringLiteral
makeRegex :: (Str, Str, Null or Syntax) -> Syntax
RegexLiteral
// the second argument here is the flags for the regex
makeIdent :: (Str, Null or Syntax) -> Syntax
Identifier
makeKeyword :: (Str, Null or Syntax) -> Syntax
Keyword
makePunc :: (Str, Null or Syntax) -> Syntax
Punctuator
makeDelim :: (Str, [...Syntax], Null or Syntax) -> Syntax
Delimiter
The makeDelim
function is a little odd but to make a delimiter syntax object we can't just pass it literally. So we say what type it is with the first param ("{}"
, "[]"
, or "()"
), its children syntax objects with the second, and the context with the third. Eg: makeDelimiter("{}", [makeValue(42, null)], null)
.
To unwrap the syntax object we have the wonderfully named unwrapSyntax
(similar to Scheme's syntax-e
):
unwrapSyntax :: (Syntax) -> Any
This gives either a flat value (like a number) or a delimiter token with unwrapped syntax objects inside.