Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

Commit 9bc2c79

Browse files
IwanKaramazowchenglou
authored andcommitted
Numeric poly variant support (#349)
* Extend grammar of poly variants with integers * Implement printer support for numeric poly var * Add extra test cases for numeric poly variants with payloads. * Implement numeric poly var printing for outcome printer
1 parent fe7b9e6 commit 9bc2c79

File tree

17 files changed

+175
-26
lines changed

17 files changed

+175
-26
lines changed

src/res_core.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,9 @@ let parseHashIdent ~startPos p =
673673
Parser.next p;
674674
let text = if p.mode = ParseForTypeChecker then parseStringLiteral text else text in
675675
(text, mkLoc startPos p.prevEndPos)
676+
| Int {i} ->
677+
Parser.next p;
678+
(i, mkLoc startPos p.prevEndPos)
676679
| _ ->
677680
parseIdent ~startPos ~msg:ErrorMessages.variantIdent p
678681

@@ -1176,6 +1179,9 @@ let rec parsePattern ?(alias=true) ?(or_=true) p =
11761179
Parser.next p;
11771180
let text = if p.mode = ParseForTypeChecker then parseStringLiteral text else text in
11781181
(text, mkLoc startPos p.prevEndPos)
1182+
| Int {i} ->
1183+
Parser.next p;
1184+
(i, mkLoc startPos p.prevEndPos)
11791185
| _ ->
11801186
parseIdent ~msg:ErrorMessages.variantIdent ~startPos p
11811187
in

src/res_outcome_printer.ml

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,28 @@
1010
module Doc = Res_doc
1111
module Token = Res_token
1212

13+
let rec unsafe_for_all_range s ~start ~finish p =
14+
start > finish ||
15+
p (String.unsafe_get s start) &&
16+
unsafe_for_all_range s ~start:(start + 1) ~finish p
17+
18+
let for_all_from s start p =
19+
let len = String.length s in
20+
unsafe_for_all_range s ~start ~finish:(len - 1) p
21+
22+
(* See https://github.com/rescript-lang/rescript-compiler/blob/726cfa534314b586e5b5734471bc2023ad99ebd9/jscomp/ext/ext_string.ml#L510 *)
23+
let isValidNumericPolyvarNumber (x : string) =
24+
let len = String.length x in
25+
len > 0 && (
26+
let a = Char.code (String.unsafe_get x 0) in
27+
a <= 57 &&
28+
(if len > 1 then
29+
a > 48 &&
30+
for_all_from x 1 (function '0' .. '9' -> true | _ -> false)
31+
else
32+
a >= 48 )
33+
)
34+
1335
(* checks if ident contains "arity", like in "arity1", "arity2", "arity3" etc. *)
1436
let isArityIdent ident =
1537
if String.length ident >= 6 then
@@ -57,13 +79,17 @@ let printIdentLike ~allowUident txt =
5779
| NormalIdent -> Doc.text txt
5880

5981
let printPolyVarIdent txt =
60-
match classifyIdentContent ~allowUident:true txt with
61-
| ExoticIdent -> Doc.concat [
62-
Doc.text "\"";
63-
Doc.text txt;
64-
Doc.text"\""
65-
]
66-
| NormalIdent -> Doc.text txt
82+
(* numeric poly-vars don't need quotes: #644 *)
83+
if isValidNumericPolyvarNumber txt then
84+
Doc.text txt
85+
else
86+
match classifyIdentContent ~allowUident:true txt with
87+
| ExoticIdent -> Doc.concat [
88+
Doc.text "\"";
89+
Doc.text txt;
90+
Doc.text"\""
91+
]
92+
| NormalIdent -> Doc.text txt
6793

6894
(* ReScript doesn't have parenthesized identifiers.
6995
* We don't support custom operators. *)

src/res_printer.ml

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -425,15 +425,41 @@ let printIdentLike ?allowUident txt =
425425
]
426426
| NormalIdent -> Doc.text txt
427427

428+
let rec unsafe_for_all_range s ~start ~finish p =
429+
start > finish ||
430+
p (String.unsafe_get s start) &&
431+
unsafe_for_all_range s ~start:(start + 1) ~finish p
432+
433+
let for_all_from s start p =
434+
let len = String.length s in
435+
unsafe_for_all_range s ~start ~finish:(len - 1) p
436+
437+
(* See https://github.com/rescript-lang/rescript-compiler/blob/726cfa534314b586e5b5734471bc2023ad99ebd9/jscomp/ext/ext_string.ml#L510 *)
438+
let isValidNumericPolyvarNumber (x : string) =
439+
let len = String.length x in
440+
len > 0 && (
441+
let a = Char.code (String.unsafe_get x 0) in
442+
a <= 57 &&
443+
(if len > 1 then
444+
a > 48 &&
445+
for_all_from x 1 (function '0' .. '9' -> true | _ -> false)
446+
else
447+
a >= 48 )
448+
)
449+
428450
(* Exotic identifiers in poly-vars have a "lighter" syntax: #"ease-in" *)
429451
let printPolyVarIdent txt =
430-
match classifyIdentContent ~allowUident:true txt with
431-
| ExoticIdent -> Doc.concat [
432-
Doc.text "\"";
433-
Doc.text txt;
434-
Doc.text"\""
435-
]
436-
| NormalIdent -> Doc.text txt
452+
(* numeric poly-vars don't need quotes: #644 *)
453+
if isValidNumericPolyvarNumber txt then
454+
Doc.text txt
455+
else
456+
match classifyIdentContent ~allowUident:true txt with
457+
| ExoticIdent -> Doc.concat [
458+
Doc.text "\"";
459+
Doc.text txt;
460+
Doc.text"\""
461+
]
462+
| NormalIdent -> Doc.text txt
437463

438464

439465
let printLident l = match l with

tests/oprint/oprint.res

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,3 +279,18 @@ type multiSpreadedCoordinate = {
279279
}
280280

281281
type dotdotObjectCoordinate<'a> = {.. "suuuuuuuuuuuperLooooooooooooongFieldNaaaaaaaaaaaame": float, "suuuuuuuuuuuperLooooooooooooongFieldNaaaaaaaaaaaame2222222222222": float} as 'a
282+
283+
type permissions = [
284+
| #777
285+
| #644
286+
]
287+
288+
type numericPolyVarWithPayload = [
289+
| #1(string)
290+
| #2(int, string)
291+
]
292+
293+
let numericPolyVarMatch = switch #644 {
294+
| #777 => #1("payload")
295+
| #644 => #2(42, "test")
296+
}

tests/oprint/oprint.res.snapshot

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ type t21 = [#"va r ia nt"]
147147
type t22 = [#"Variant ⛰"]
148148
type \"let" = int
149149
type \"type" = [#"Point🗿"(\"let", float)]
150-
type t23 = [#"1" | #"10space" | #"123"]
150+
type t23 = [#1 | #"10space" | #123]
151151
type exoticUser = {\"let": string, \"type": float}
152152
module Js = {
153153
type t<'a> = 'a
@@ -437,4 +437,7 @@ type dotdotObjectCoordinate<'a> = 'a
437437
constraint 'a = {..
438438
"suuuuuuuuuuuperLooooooooooooongFieldNaaaaaaaaaaaame": float,
439439
"suuuuuuuuuuuperLooooooooooooongFieldNaaaaaaaaaaaame2222222222222": float,
440-
}
440+
}
441+
type permissions = [#644 | #777]
442+
type numericPolyVarWithPayload = [#1(string) | #2(int, string)]
443+
let numericPolyVarMatch: [> #1(string) | #2(int, string)]
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
let x = `Red
22
let z = `Rgb ()
33
let v = `Vertex (1., 2., 3., 4.)
4-
let animation = `ease-in
4+
let animation = `ease-in
5+
let one = `1
6+
let fortyTwo = `42
7+
let long = `42444
8+
let oneString = `1 "payload"
9+
let twoIntString = `2 (3, "payload")

tests/parsing/grammar/expressions/polyvariant.res

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,10 @@ let z = #Rgb()
66
let v = #Vertex(1., 2., 3., 4.)
77

88
let animation = #"ease-in"
9+
10+
let one = #1
11+
let fortyTwo = #42
12+
let long = #42444
13+
14+
let oneString = #1("payload")
15+
let twoIntString = #2(3, "payload")

tests/parsing/grammar/pattern/expected/variants.res.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,9 @@ let f (`Instance (comp : Component.t) : React.t) = ()
6161
;;for `Point { x; y; z } = x to y do () done
6262
;;for `Point { x; y; z } = x to y do () done
6363
;;for `Point { x; y; z } as p = x to y do () done
64-
;;match x with | #typeVar -> () | `lowercase -> ()
64+
;;match x with | #typeVar -> () | `lowercase -> ()
65+
;;match numericPolyVar with
66+
| `1 -> ()
67+
| `42 -> ()
68+
| `42444 -> ()
69+
| `3 (x, y, z) -> Js.log3 x y z

tests/parsing/grammar/pattern/variants.res

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,10 @@ switch x {
8282
| #...typeVar => ()
8383
| #lowercase => ()
8484
}
85+
86+
switch numericPolyVar {
87+
| #1 => ()
88+
| #42 => ()
89+
| #42444 => ()
90+
| #3(x, y, z) => Js.log3(x, y, z)
91+
}

tests/parsing/grammar/typexpr/expected/polyVariant.res.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@ module type Conjunctive =
1010
-> unit
1111
end
1212
type nonrec t = [ s]
13-
type nonrec t = [ ListStyleType.t]
13+
type nonrec t = [ ListStyleType.t]
14+
type nonrec number = [ `1 | `42 | `4244 ]
15+
type nonrec complexNumbericPolyVar = [ `1 of string | `2 of (int * string) ]

tests/parsing/grammar/typexpr/polyVariant.res

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,14 @@ module type Conjunctive = {
1515

1616
type t = [s]
1717
type t = [ListStyleType.t];
18+
19+
type number = [
20+
| #1
21+
| #42
22+
| #4244
23+
]
24+
25+
type complexNumbericPolyVar = [
26+
| #1(string)
27+
| #2(int, string)
28+
]

tests/printer/expr/expected/polyvariant.res.txt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,12 @@ let r = #lident(a, b)
108108
let r = #"exotic lident"
109109
let r = #"exotic lident"(a, b)
110110

111-
let x = #"1"
112-
let x = #"123"
111+
let x = #1
112+
let x = #123
113113
let x = #"10space"
114114
let x = #space10
115115

116-
let a = #"1"
116+
let a = #1
117117
let b = #"1a"
118118
let c = #a2
119119
let d = #abcd
@@ -140,3 +140,6 @@ external openSync: (
140140

141141
let x = #a()
142142
let x = #a()
143+
144+
let oneString = #1("payload")
145+
let twoIntString = #2(3, "payload")

tests/printer/expr/polyvariant.res

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,6 @@ external openSync: (
135135

136136
let x = #a(())
137137
let x = #a()
138+
139+
let oneString = #1("payload")
140+
let twoIntString = #2(3, "payload")

tests/printer/pattern/expected/variant.res.txt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ let #Shape = x
33
let #"type" = x
44
let #"test 🏚" = x
55
let #"Shape✅" = x
6-
let #"1" = x
7-
let #"123" = x
6+
let #1 = x
7+
let #123 = x
88
let #"10space" = x
99

1010
let #space10 = x
@@ -27,8 +27,8 @@ let cmp = (selectedChoice, value) =>
2727
| (#...a: typ) => true
2828
| lazy #...a => true
2929
| exception #...a => true
30-
| #"1" => true
31-
| #"123" => true
30+
| #1 => true
31+
| #123 => true
3232
| #"10space" => x
3333
| #space10 => x
3434
| _ => false
@@ -38,3 +38,8 @@ switch x {
3838
| #a() => ()
3939
| #a() => ()
4040
}
41+
42+
switch numericPolyVar {
43+
| #42 => ()
44+
| #3(x, y, z) => Js.log3(x, y, z)
45+
}

tests/printer/pattern/variant.res

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,8 @@ switch x {
3838
| #a(()) => ()
3939
| #a() => ()
4040
}
41+
42+
switch numericPolyVar {
43+
| #42 => ()
44+
| #3(x, y, z) => Js.log3(x, y, z)
45+
}

tests/printer/typexpr/expected/variant.res.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,13 @@ type currencyPoly = [
102102

103103
type t = [s]
104104
type t = [ListStyleType.t]
105+
106+
type permissions = [
107+
| #777
108+
| #644
109+
]
110+
111+
type t = [
112+
| #1(string)
113+
| #2(int, string)
114+
]

tests/printer/typexpr/variant.res

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,13 @@ type currencyPoly = [#UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUSD | #CAAA
9696

9797
type t = [s]
9898
type t = [ListStyleType.t];
99+
100+
type permissions = [
101+
| #777
102+
| #644
103+
]
104+
105+
type t = [
106+
| #1(string)
107+
| #2(int, string)
108+
]

0 commit comments

Comments
 (0)