Skip to content

Commit a7d34c7

Browse files
MiryangJungcometkimcknitt
authored
add bitxor (^) unified operator (#7216)
* add add lxor (^) unified operator * add bitxor Co-authored-by: Hyeseong Kim <hey@hyeseong.kim> * Update compiler/syntax/src/res_diagnostics.ml Co-authored-by: Christoph Knittel <christoph@knittel.cc> * update the test output * CHANGELOG: Add unified bitwise (`^`) operator to the list of changes * Update CHANGELOG.md --------- Co-authored-by: Hyeseong Kim <hey@hyeseong.kim> Co-authored-by: Christoph Knittel <christoph@knittel.cc>
1 parent 6654cb2 commit a7d34c7

File tree

21 files changed

+72
-40
lines changed

21 files changed

+72
-40
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
- Experimental: Support nested/inline record types - records defined inside of other records, without needing explicit separate type definitions. https://github.com/rescript-lang/rescript/pull/7241
2424
- Add unified exponentiation (`**`) operator for numeric types using ES7 `**`. https://github.com/rescript-lang/rescript-compiler/pull/7153
2525
- Rename `raise` to `throw` to align with JavaScript vocabulary. `raise` has been deprecated. https://github.com/rescript-lang/rescript/pull/7346
26+
- Add unified bitwise (`^`) operator. https://github.com/rescript-lang/rescript/pull/7216
2627

2728
#### :boom: Breaking Change
2829

compiler/ml/unified_ops.ml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,19 @@ let entries =
174174
string = None;
175175
};
176176
};
177+
{
178+
path = builtin "^";
179+
name = "%bitxor";
180+
form = Binary;
181+
specialization =
182+
{
183+
int = Pxorint;
184+
bool = None;
185+
float = None;
186+
bigint = Some Pxorbigint;
187+
string = None;
188+
};
189+
};
177190
|]
178191

179192
let index_by_path =

compiler/syntax/src/res_diagnostics.ml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,8 @@ let explain t =
6565
| UnclosedTemplate ->
6666
"Did you forget to close this template expression with a backtick?"
6767
| UnclosedComment -> "This comment seems to be missing a closing `*/`"
68-
| UnknownUchar uchar -> (
69-
match uchar with
70-
| '^' ->
71-
"Not sure what to do with this character.\n"
72-
^ " If you're trying to dereference a mutable value, use \
73-
`myValue.contents` instead.\n"
74-
^ " To concatenate strings, use `\"a\" ++ \"b\"` instead."
75-
| _ -> "Not sure what to do with this character.")
68+
| UnknownUchar uchar ->
69+
"Not sure what to do with this character: \"" ^ Char.escaped uchar ^ "\"."
7670
| Expected {context; token = t} ->
7771
let hint =
7872
match context with

compiler/syntax/src/res_parens.ml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,7 @@ let rhs_binary_expr_operand parent_operator rhs =
162162
};
163163
args = [(_, _left); (_, _right)];
164164
}
165-
when ParsetreeViewer.is_binary_operator operator
166-
&& not (operator_loc.loc_ghost && operator = "++") ->
165+
when ParsetreeViewer.not_ghost_operator operator operator_loc ->
167166
let prec_parent = ParsetreeViewer.operator_precedence parent_operator in
168167
let prec_child = ParsetreeViewer.operator_precedence operator in
169168
prec_parent == prec_child
@@ -180,8 +179,7 @@ let flatten_operand_rhs parent_operator rhs =
180179
};
181180
args = [(_, _left); (_, _right)];
182181
}
183-
when ParsetreeViewer.is_binary_operator operator
184-
&& not (operator_loc.loc_ghost && operator = "++") ->
182+
when ParsetreeViewer.not_ghost_operator operator operator_loc ->
185183
let prec_parent = ParsetreeViewer.operator_precedence parent_operator in
186184
let prec_child = ParsetreeViewer.operator_precedence operator in
187185
prec_parent >= prec_child || rhs.pexp_attributes <> []

compiler/syntax/src/res_parsetree_viewer.ml

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -272,11 +272,12 @@ let operator_precedence operator =
272272
| ":=" -> 1
273273
| "||" -> 2
274274
| "&&" -> 3
275-
| "==" | "===" | "<" | ">" | "!=" | "<>" | "!==" | "<=" | ">=" | "|>" -> 4
276-
| "+" | "+." | "-" | "-." | "++" -> 5
277-
| "*" | "*." | "/" | "/." | "%" -> 6
278-
| "**" -> 7
279-
| "#" | "##" | "->" -> 8
275+
| "^" -> 4
276+
| "==" | "===" | "<" | ">" | "!=" | "<>" | "!==" | "<=" | ">=" | "|>" -> 5
277+
| "+" | "+." | "-" | "-." | "++" -> 6
278+
| "*" | "*." | "/" | "/." | "%" -> 7
279+
| "**" -> 8
280+
| "#" | "##" | "->" -> 9
280281
| _ -> 0
281282

282283
let is_unary_operator operator =
@@ -295,15 +296,17 @@ let is_unary_expression expr =
295296
true
296297
| _ -> false
297298

298-
(* TODO: tweak this to check for ghost ^ as template literal *)
299299
let is_binary_operator operator =
300300
match operator with
301301
| ":=" | "||" | "&&" | "==" | "===" | "<" | ">" | "!=" | "!==" | "<=" | ">="
302302
| "|>" | "+" | "+." | "-" | "-." | "++" | "*" | "*." | "/" | "/." | "**"
303-
| "->" | "<>" | "%" ->
303+
| "->" | "<>" | "%" | "^" ->
304304
true
305305
| _ -> false
306306

307+
let not_ghost_operator operator (loc : Location.t) =
308+
is_binary_operator operator && not (loc.loc_ghost && operator = "++")
309+
307310
let is_binary_expression expr =
308311
match expr.pexp_desc with
309312
| Pexp_apply
@@ -315,9 +318,7 @@ let is_binary_expression expr =
315318
};
316319
args = [(Nolabel, _operand1); (Nolabel, _operand2)];
317320
}
318-
when is_binary_operator operator
319-
&& not (operator_loc.loc_ghost && operator = "++")
320-
(* template literal *) ->
321+
when not_ghost_operator operator operator_loc ->
321322
true
322323
| _ -> false
323324

compiler/syntax/src/res_parsetree_viewer.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ val is_huggable_rhs : Parsetree.expression -> bool
6565

6666
val operator_precedence : string -> int
6767

68+
val not_ghost_operator : string -> Location.t -> bool
6869
val is_unary_expression : Parsetree.expression -> bool
6970
val is_binary_operator : string -> bool
7071
val is_binary_expression : Parsetree.expression -> bool

compiler/syntax/src/res_scanner.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,9 @@ let rec scan scanner =
834834
| _ ->
835835
next scanner;
836836
Token.Band)
837+
| '^' ->
838+
next scanner;
839+
Token.Caret
837840
| ':' -> (
838841
match peek scanner with
839842
| '=' ->

compiler/syntax/src/res_token.ml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ type t =
7878
| Land
7979
| Lor
8080
| Band (* Bitwise and: & *)
81+
| Caret
8182
| BangEqual
8283
| BangEqualEqual
8384
| LessEqual
@@ -102,14 +103,15 @@ let precedence = function
102103
| HashEqual | ColonEqual -> 1
103104
| Lor -> 2
104105
| Land -> 3
106+
| Caret -> 4
105107
| Equal | EqualEqual | EqualEqualEqual | LessThan | GreaterThan | BangEqual
106108
| BangEqualEqual | LessEqual | GreaterEqual | BarGreater ->
107-
4
108-
| Plus | PlusDot | Minus | MinusDot | PlusPlus -> 5
109-
| Asterisk | AsteriskDot | Forwardslash | ForwardslashDot | Percent -> 6
110-
| Exponentiation -> 7
111-
| MinusGreater -> 8
112-
| Dot -> 9
109+
5
110+
| Plus | PlusDot | Minus | MinusDot | PlusPlus -> 6
111+
| Asterisk | AsteriskDot | Forwardslash | ForwardslashDot | Percent -> 7
112+
| Exponentiation -> 8
113+
| MinusGreater -> 9
114+
| Dot -> 10
113115
| _ -> 0
114116

115117
let to_string = function
@@ -189,6 +191,7 @@ let to_string = function
189191
| Of -> "of"
190192
| Lor -> "||"
191193
| Band -> "&"
194+
| Caret -> "^"
192195
| Land -> "&&"
193196
| BangEqual -> "!="
194197
| BangEqualEqual -> "!=="

runtime/Pervasives.res

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ external \"/": ('a, 'a) => 'a = "%div"
6363
external \"%": ('a, 'a) => 'a = "%mod"
6464
external mod: ('a, 'a) => 'a = "%mod"
6565
external \"**": ('a, 'a) => 'a = "%pow"
66+
external \"^": ('a, 'a) => 'a = "%bitxor"
6667

6768
/* Comparisons */
6869
/* Note: Later comparisons will be converted to unified operations too */

runtime/Pervasives_mini.res

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ external \"/": (int, int) => int = "%divint"
3131
external \"%": (int, int) => int = "%modint"
3232
external mod: (int, int) => int = "%modint"
3333
external \"**": (int, int) => int = "%powint"
34+
external \"^": (int, int) => int = "%bitxorint"
3435

3536
/* Comparisons */
3637
/* Note: Later comparisons will be converted to unified operations too */

0 commit comments

Comments
 (0)