New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom operators #296
Custom operators #296
Conversation
|
+1 on the precedence change. I think the numbering on the page is just to order it: numbers that come first bind first. Honestly, I think most people who want to use custom operators are coming from languages that support them already, and it'd be more confusing to do it like the MDN page. |
|
https://github.com/mozilla/sweet.js/blob/f2219ab22ebaf0137de971d65cb4dc276c8ec987/macros/stxcase.js#L743 throws an ellipsis error for |
|
It's also having a hard time with multi-token names comprised of operators: binaryop (|>) 0 left { $left, $right } => #{ $right($left) }
var foo = 1 |> bar |> baz;Seems to just strip the operators. Using something else works fine. |
|
Thanks for catching that. Multi token operators should be working now. |
|
Grouping with parens results in strange errors: binaryop (|>) 0 left { $lhs, $rhs } => #{ $rhs($lhs) }
var a = foo |> (bar |> baz);Looks like the operator is stripped there. Edit: It only errors with multi-token names. |
|
You can't overload operators (ie, both unary and binary): binaryop ! 2 left { $l, $r } => #{ $l.send($r) }
var a = foo ! bar;
var b = !true;The error reporting seems to be goofy, too. It's reporting the line of the macro definition instead of its usage. |
|
Associativity seems a bit broken: binaryop ($$$) 1 left { $l, $r } => #{ dollar($l, $r) }
binaryop (%%%) 1 right { $l, $r } => #{ modulo($l, $r) }
foo $$$ bar $$$ baz;
foo %%% bar %%% baz;dollar(dollar(foo, bar), baz);
modulo(modulo(foo, bar), baz);Shouldn't it be Also a strange bug, if you leave off the semi colons and put the right-associative line first, you get an error, but not the other way around: binaryop ($$$) 1 left { $l, $r } => #{ dollar($l, $r) }
binaryop (%%%) 1 right { $l, $r } => #{ modulo($l, $r) }
foo %%% bar %%% baz
foo $$$ bar $$$ baz |
|
Fixed the grouping and associativity problems for multi token operators. It had to do with the old bug of expanding inside of parens too many times. I seem to remember running into other issues related to that but can't find the issue where we discussed it before. Anyway it should be fixed now, and we might get a small performance boost too. Still looking into the other issues you found. |
We may have just discussed it in IRC. I've run into it a couple of times. If you never mutate source arrays, you'd be ok. But if your code is in a paren expr and you mutate the inner tokens, it would fail the second time around. |
|
Ok, I think I've fixed all the issues you noticed. I've also got defining unary and binary versions of the same operator working. Let me know if you've run into anything else. Also, how are you feeling about the current syntax? |
|
After messing around with it, I think I'm definitely leaning towards a unified declaration of just macro op_assoc {
rule { left }
rule { right }
}
macro op_name {
rule { ($name ...) }
rule { $name } => { ($name) }
}
let operator = macro {
rule {
$name:op_name $prec:lit $assoc:op_assoc { $left:ident, $right:ident } => #{ $body ... }
} => {
binaryop $name $prec $assoc {
macro {
rule { ($left:expr) ($right:expr) } => { $body ... }
}
}
}
rule {
$name:op_name $prec:lit { $op:ident } => #{ $body ... }
} => {
unaryop $name $prec {
macro {
rule { $param:expr } => { $body ... }
}
}
}
}I tried adding a rule for a JS body rather than a template, but I get a hygiene error with |
Custom (honu-style) operator support. Still need to do a little bit of cleaning/testing before I merge. Here's the syntax I'm going with at the moment:
The definition syntax is actually just a macro that desugars down to a primitive form:
One interesting question came up while I was working on this. How should we order precedence? The precedence table on mdn is ordered from highest (0) to lowest (18), which seems a bit backwards since bigger numbers have lower precedence. I've flipped this for sweet.js so 0 binds least tightly and 18 binds most tightly. Is this the right choice or will people be confused because of the mdn page?