Skip to content

Commit 4d0f26a

Browse files
committed
add bitxor
Co-authorized-by: Hyeseong Kim <hey@hyeseong.kim>
1 parent d31cd0c commit 4d0f26a

File tree

18 files changed

+76
-44
lines changed

18 files changed

+76
-44
lines changed

compiler/ml/unified_ops.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ let entries =
163163
};
164164
{
165165
path = builtin "^";
166-
name = "%xor";
166+
name = "%bitxor";
167167
form = Binary;
168168
specialization =
169169
{

compiler/syntax/src/res_diagnostics.ml

+2-8
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

+2-4
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

+11-10
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

+1
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

+3
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

+9-6
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

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ external \"*": ('a, 'a) => 'a = "%mul"
5151
external \"/": ('a, 'a) => 'a = "%div"
5252
external \"%": ('a, 'a) => 'a = "%mod"
5353
external mod: ('a, 'a) => 'a = "%mod"
54-
external \"^": ('a, 'a) => 'a = "%xor"
54+
external \"^": ('a, 'a) => 'a = "%bitxor"
5555

5656
/* Comparisons */
5757
/* Note: Later comparisons will be converted to unified operations too */

runtime/Pervasives_mini.res

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ external \"*": (int, int) => int = "%mulint"
3030
external \"/": (int, int) => int = "%divint"
3131
external \"%": (int, int) => int = "%modint"
3232
external mod: (int, int) => int = "%modint"
33-
external \"^": (int, int) => int = "%xorint"
33+
external \"^": (int, int) => int = "%bitxorint"
3434

3535
/* Comparisons */
3636
/* Note: Later comparisons will be converted to unified operations too */

tests/syntax_tests/data/parsing/errors/pattern/expected/templateLiteral.res.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
6 │ | _ => ()
2121
7 │ }
2222

23-
Not sure what to do with this character.
23+
Not sure what to do with this character "$"
2424

2525

2626
Syntax error!

tests/syntax_tests/data/parsing/errors/scanner/expected/badCharacter.res.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
1 │ let $ = 1
66

7-
Not sure what to do with this character.
7+
Not sure what to do with this character "$"
88

99

1010
Syntax error!
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,23 @@
11

22
Syntax error!
3-
syntax_tests/data/parsing/errors/scanner/oldDerefOp.res:1:50
3+
syntax_tests/data/parsing/errors/scanner/oldDerefOp.res:1:51
44

55
1 │ let newVelocity = velocity +. a *. secondPerFrame^;
66
2 │ let newX = x +. newVelocity *. secondPerFrame^;
77
3 │
88

9-
Not sure what to do with this character.
10-
If you're trying to dereference a mutable value, use `myValue.contents` instead.
11-
To concatenate strings, use `"a" ++ "b"` instead.
9+
Did you forget to write an expression here?
1210

1311

1412
Syntax error!
15-
syntax_tests/data/parsing/errors/scanner/oldDerefOp.res:2:46
13+
syntax_tests/data/parsing/errors/scanner/oldDerefOp.res:2:47
1614

1715
1 │ let newVelocity = velocity +. a *. secondPerFrame^;
1816
2 │ let newX = x +. newVelocity *. secondPerFrame^;
1917
3 │
2018

21-
Not sure what to do with this character.
22-
If you're trying to dereference a mutable value, use `myValue.contents` instead.
23-
To concatenate strings, use `"a" ++ "b"` instead.
19+
Did you forget to write an expression here?
2420

25-
let newVelocity = velocity +. (a *. secondPerFrame)
26-
let newX = x +. (newVelocity *. secondPerFrame)
21+
let newVelocity =
22+
(velocity +. (a *. secondPerFrame)) ^ ([%rescript.exprhole ])
23+
let newX = (x +. (newVelocity *. secondPerFrame)) ^ ([%rescript.exprhole ])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
Syntax error!
3+
syntax_tests/data/parsing/errors/typeDef/nestedRecord.res:3:11-47
4+
5+
1 │ type options = {
6+
2 │ extra?: {
7+
3 │ name: result<{first: bool}, {second: bool}>,
8+
4 │ },
9+
5 │ }
10+
11+
Only one inline record definition is allowed per record field. This defines more than one inline record.
12+
13+
type options.extra = {
14+
name: (options.extra.name, options.extra.name) result }[@@res.inlineRecordDefinition
15+
]
16+
and options.extra.name = {
17+
second: bool }[@@res.inlineRecordDefinition ]
18+
and options.extra.name = {
19+
first: bool }[@@res.inlineRecordDefinition ]
20+
and options = {
21+
extra?: options.extra }

tests/syntax_tests/data/parsing/grammar/expressions/expected/binary.res.txt

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ let x = ((while condition do () done)[@attr ]) z
1414
let x = (a + (-1)) + (-2)
1515
let x = (a + (((-1))[@attr ])) + (((-2))[@attr ])
1616
let x = (a % a) == 0
17+
let x = a ^ (a == 0)
1718
let x = a - b
1819
let x = a -. b
1920
;;Constructor (a, b)

tests/syntax_tests/data/printer/expr/expected/binary.res.txt

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ let () = (print_int: int => unit)((x: int))
8585
x + y / z
8686
x / y + z
8787
x % y * z
88+
x ^ y + z
8889
100 * x / total
8990
2 / 3 * 10 / 2 + 2
9091
let rotateX = (range / rect.height * refY - range / 2) * getXMultiplication(rect.width)

tests/tests/src/belt_int_test.mjs

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Mocha.describe("Belt_int_test", () => {
3636
Test_utils.eq("File \"belt_int_test.res\", line 41, characters 7-14", 6, 6);
3737
Test_utils.eq("File \"belt_int_test.res\", line 42, characters 7-14", 0, 0);
3838
Test_utils.eq("File \"belt_int_test.res\", line 43, characters 7-14", 0, 0);
39+
Test_utils.eq("File \"belt_int_test.res\", line 44, characters 7-14", 1, 1);
3940
});
4041
});
4142

tests/tests/src/unified_ops_test.mjs

+10
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ function odd(n) {
5959
return n % 2 === 1;
6060
}
6161

62+
function bxor_int(a, b) {
63+
return a ^ b;
64+
}
65+
66+
function bxor_bigint(a, b) {
67+
return a ^ b;
68+
}
69+
6270
let int = 3;
6371

6472
export {
@@ -79,5 +87,7 @@ export {
7987
case2,
8088
even,
8189
odd,
90+
bxor_int,
91+
bxor_bigint,
8292
}
8393
/* No side effect */

tests/tests/src/unified_ops_test.res

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ let case2 = (a, b) => a + "test" + b
2121
let even = n => n % 2 == 0
2222
let odd = n => n % 2 == 1
2323

24-
let lxor = (a, b: int) => a ^ b
24+
let bxor_int = (a, b) => a ^ b
25+
let bxor_bigint = (a: bigint, b) => a ^ b

0 commit comments

Comments
 (0)