Created by: levjj
In the following example, $a
gets bound to the second token, throwing away the first binding:
macro foo {
rule { $a $a } => { alert($a); }
}
foo "hello" "world"
// expands to
alert('world');
As a reference, if you do the same thing in Racket, it will fail at compile time:
(define-syntax foo
(syntax-rules ()
((_ a a)
(printf "~a\n" (list a)))))
;; ERROR: syntax-rules: variable used twice in pattern in: a
The behavior in Racket is definitely more intuitive than the current behavior in sweet.js. However, I would actually propose that repeating a variable in a pattern should not throw an error but should actually try to match with the current binding. The idea is that if you repeat a variable, you also want the matched tokens to repeat.
foo "hello" "world" // would not match
foo "hello" "hello" // expands to alert('hello')
It is possible that somebody uses the current behavior in order to overwrite previous assigned tokens in pattern. In that case, this change would actually break things. Additionally, there might be complicated edge cases with named bindings, etc. which produce unintuitive behavior. However, it would probably be still an improvement over the current confusing behavior.
On a side note, the proposed behavior roughly corresponds to the pattern matching in Racket's Redex system:
If it is a non-terminal, it matches any of the right-hand sides of that non-terminal. If the non-terminal appears twice in a single pattern, then the match is constrained to expressions that are the same
I would appreciate any feedback on this. If there are no serious concerns with this proposal, I would be open to implement this and create a pull request.