Skip to content

Commit 90403c1

Browse files
committed
Migrate to Primitive.t
1 parent 21b76ca commit 90403c1

File tree

6 files changed

+132
-176
lines changed

6 files changed

+132
-176
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
- Union types appearing as argument of function are now emitted in a simpler form: `` [`U1 of t1 | `U2 of t2 | .. ] [@js.union] ``.
1212
- Now you don't have to do `Union.inject_n` on function arguments.
1313
- This is a breaking change.
14+
- Union of primitive types are now represented as `[...] Primitive.t`.
15+
- Use `Primitive.classify` function to convert it to a polymorphic variant, on which you can `match` directly.
16+
- `'a or_XXX` types are removed in this change.
17+
- This is a breaking change.
1418

1519
## [1.4.0-beta.4] - 2022-01-21
1620
- Ts2ocaml now emits builder function `[@js.builder]` for POJO interfaces.

docs/js_of_ocaml.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ Here we list the "safe" types, of which runtime representation is the same both
276276
* Primitive types in the `Ts2ocaml_min` module, such as `any`, `never`, `bigint`, or `symbol`.
277277
* (Non-discriminated) union and intersection types, in the form `[ ... ] Union.t` or `[ ... ] Intersection.t`.
278278
- These modules has `get_n'` or `inject_n'` functions, which takes the conversion function of the contained type.
279-
* `typeof`-able unions, in the form `[ ... ] TypeofableUnion.t`.
279+
* Union of primitive types, in the form `[ ... ] Primitive.t`.
280280
- These modules has `inject'` and `classify'`, which takes the conversion function of the `'other` type.
281281
* Bindings to classes and interfaces.
282282
- It is an alias to `Ojs.t` (or `Ts2ocaml.intf`), which means the runtime representation is
@@ -291,7 +291,7 @@ Here we list the common "unsafe" types, which can cause problem when used as typ
291291
- Use `Ojs.list_to_js` and `Ojs.list_of_js` to explicitly convert these values.
292292
* Bindings to enums.
293293
- Use the `t_to_js` and `t_of_js` functions in the binding module.
294-
* Bindings to discriminated unions, which is represented as a polymorphic variant with `[@js.union]`.
294+
* Bindings to discriminated unions, which is represented as a polymorphic variant with `[@js.union on_field "..."]`.
295295
- Use the `t_to_js` and `t_of_js` functions in the binding module.
296296

297297
Also, with the [`--functor`](#--functor) option (which is enabled by default),

lib/Typer.fs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,20 +1336,29 @@ module ResolvedUnion =
13361336
seq {
13371337
match t with
13381338
| Union { types = types } -> yield! Seq.collect go types
1339-
| Intersection { types = types } -> yield! types |> List.map (go >> Set.ofSeq) |> Set.intersectMany |> Set.toSeq
1339+
| Intersection { types = types } ->
1340+
let cases = types |> List.map (go >> Set.ofSeq) |> Set.intersectMany
1341+
if Set.isEmpty cases then yield Choice2Of2 t
1342+
else yield! cases
13401343
| (Ident ({ loc = loc } & i) & Dummy tyargs)
13411344
| App (AIdent i, tyargs, loc) ->
1342-
for x in i |> Ident.getDefinitions ctx do
1343-
match x with
1345+
let finder = function
13441346
| Definition.TypeAlias a ->
13451347
let bindings = Type.createBindings i.name loc a.typeParams tyargs
1346-
yield! go (a.target |> Type.substTypeVar bindings ())
1348+
go (a.target |> Type.substTypeVar bindings ())
13471349
| Definition.Enum e ->
1348-
for c in e.cases do yield Choice1Of2 (Choice1Of2 (e, c))
1350+
e.cases |> Seq.map (fun c -> Choice1Of2 (Choice1Of2 (e, c)))
13491351
| Definition.EnumCase (c, e) ->
1350-
yield Choice1Of2 (Choice1Of2 (e, c))
1351-
| Definition.Class _ -> yield Choice2Of2 t
1352-
| _ -> ()
1352+
Seq.singleton (Choice1Of2 (Choice1Of2 (e, c)))
1353+
| _ -> Seq.empty
1354+
let result =
1355+
i |> Ident.getDefinitions ctx
1356+
|> List.tryPick (fun d ->
1357+
let e = finder d
1358+
if Seq.isEmpty e then None else Some e)
1359+
match result with
1360+
| Some e -> yield! e
1361+
| None -> yield Choice2Of2 t
13531362
| TypeLiteral l -> yield Choice1Of2 (Choice2Of2 l)
13541363
| _ -> yield Choice2Of2 t
13551364
}
@@ -1496,7 +1505,7 @@ module ResolvedUnion =
14961505
) discriminatables ([], rest)
14971506

14981507
if List.length discriminatables < 2 then
1499-
Map.empty, { u with types = List.distinct u.types }
1508+
Map.empty, u
15001509
else
15011510
let dus =
15021511
discriminatables
@@ -1537,15 +1546,22 @@ module ResolvedUnion =
15371546
let caseArray =
15381547
if List.isEmpty arrayTypes then None
15391548
else Some (Set.ofList arrayTypes)
1540-
let caseEnum, rest =
1549+
let caseEnum, rest' =
15411550
match rest with
15421551
| _ :: _ :: _ -> getEnumFromUnion ctx { types = rest }
15431552
| _ -> Set.empty, { types = rest }
1544-
let discriminatedUnions, rest =
1545-
match rest.types with
1546-
| _ :: _ :: _ -> getDiscriminatedFromUnion ctx rest
1547-
| _ -> Map.empty, rest
1548-
let otherTypes = Set.ofList rest.types
1553+
let discriminatedUnions, rest'' =
1554+
match rest'.types with
1555+
| _ :: _ :: _ -> getDiscriminatedFromUnion ctx rest'
1556+
| _ -> Map.empty, rest'
1557+
let otherTypes = Set.ofList rest''.types
1558+
1559+
if not u'.hasNull && not u'.hasUndefined && Set.isEmpty typeofableTypes && caseArray = None
1560+
&& Set.isEmpty caseEnum && Map.isEmpty discriminatedUnions && Set.isEmpty otherTypes then
1561+
eprintfn "[0] %A" rest
1562+
eprintfn "[1] %A" rest'
1563+
eprintfn "[2] %A" rest''
1564+
failwith "error!!!!!!!!!!!!!"
15491565

15501566
let result =
15511567
{ caseNull = u'.hasNull

src/Targets/JsOfOCaml/Common.fs

Lines changed: 6 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ end
327327
type null = private Ojs.t
328328
val null_of_js: Ojs.t -> null
329329
val null_to_js: null -> Ojs.t
330+
val null: null [@@js.custom let null = Ojs.null]
330331
module Null : sig
331332
type t = null
332333
val t_of_js: Ojs.t -> t
@@ -339,6 +340,7 @@ end
339340
type undefined = private Ojs.t
340341
val undefined_of_js: Ojs.t -> undefined
341342
val undefined_to_js: undefined -> Ojs.t
343+
val undefined: undefined [@@js.custom let undefined = Ojs.unit_to_js ()]
342344
module Undefined : sig
343345
type t = undefined
344346
val t_of_js: Ojs.t -> t
@@ -522,7 +524,7 @@ val union7_of_js: (Ojs.t -> 'a) -> (Ojs.t -> 'b) -> (Ojs.t -> 'c) -> (Ojs.t -> '
522524
val union8_to_js: ('a -> Ojs.t) -> ('b -> Ojs.t) -> ('c -> Ojs.t) -> ('d -> Ojs.t) -> ('e -> Ojs.t) -> ('f -> Ojs.t) -> ('g -> Ojs.t) -> ('h -> Ojs.t) -> ('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h) union8 -> Ojs.t
523525
val union8_of_js: (Ojs.t -> 'a) -> (Ojs.t -> 'b) -> (Ojs.t -> 'c) -> (Ojs.t -> 'd) -> (Ojs.t -> 'e) -> (Ojs.t -> 'f) -> (Ojs.t -> 'g) -> (Ojs.t -> 'h) -> Ojs.t -> ('a, 'b, 'c, 'd, 'e, 'f, 'g, 'h) union8
524526
525-
module TypeofableUnion : sig
527+
module Primitive : sig
526528
[@@@js.stop]
527529
type +'cases t = private Ojs.t
528530
val t_to_js: ('cases -> Ojs.t) -> 'cases t -> Ojs.t
@@ -574,71 +576,11 @@ module TypeofableUnion : sig
574576
| "boolean" -> Obj.magic (`Boolean (Ojs.bool_of_js u))
575577
| "symbol" -> Obj.magic (`Symbol (symbol_of_js u))
576578
| "bigint" -> Obj.magic (`BigInt (bigint_of_js u))
577-
| "null" -> Obj.magic `Null
578579
| "undefined" -> Obj.magic `Undefined
579-
| _ -> Obj.magic (`Other (other_of_js u))
580+
| _ ->
581+
if Ojs.is_null u then Obj.magic `Null
582+
else Obj.magic (`Other (other_of_js u))
580583
let classify c = classify' Obj.magic c
581584
]
582585
end
583-
584-
type 'a or_null = 'a option
585-
val or_null_to_js: ('a -> Ojs.t) -> 'a or_null -> Ojs.t
586-
val or_null_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a or_null
587-
type 'a or_undefined = 'a option
588-
val or_undefined_to_js: ('a -> Ojs.t) -> 'a or_undefined -> Ojs.t
589-
val or_undefined_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a or_undefined
590-
type 'a or_null_or_undefined = 'a option
591-
val or_null_or_undefined_to_js: ('a -> Ojs.t) -> 'a or_null_or_undefined -> Ojs.t
592-
val or_null_or_undefined_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a or_null_or_undefined
593-
594-
type 'a or_string = [`String of string | `Other of 'a] [@@js.custom {
595-
of_js = (fun a_of_js x -> match Ojs.type_of x with "string" -> `String (Ojs.string_of_js x) | _ -> `Other (a_of_js x));
596-
to_js = (fun a_to_js -> function `String x -> Ojs.string_to_js x | `Other x -> a_to_js x)
597-
}]
598-
val or_string_to_js: ('a -> Ojs.t) -> 'a or_string -> Ojs.t
599-
val or_string_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a or_string
600-
type 'a or_number = [`Number of float | `Other of 'a] [@@js.custom {
601-
of_js = (fun a_of_js x -> match Ojs.type_of x with "number" -> `Number (Ojs.float_of_js x) | _ -> `Other (a_of_js x));
602-
to_js = (fun a_to_js -> function `Number x -> Ojs.float_to_js x | `Other x -> a_to_js x)
603-
}]
604-
val or_number_to_js: ('a -> Ojs.t) -> 'a or_number -> Ojs.t
605-
val or_number_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a or_number
606-
type 'a or_boolean = [`Boolean of bool | `Other of 'a] [@@js.custom {
607-
of_js = (fun a_of_js x -> match Ojs.type_of x with "boolean" -> `Boolean (Ojs.bool_of_js x) | _ -> `Other (a_of_js x));
608-
to_js = (fun a_to_js -> function `Boolean x -> Ojs.bool_to_js x | `Other x -> a_to_js x)
609-
}]
610-
val or_boolean_to_js: ('a -> Ojs.t) -> 'a or_boolean -> Ojs.t
611-
val or_boolean_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a or_boolean
612-
type 'a or_symbol = [`Symbol of symbol | `Other of 'a] [@@js.custom {
613-
of_js = (fun a_of_js x -> match Ojs.type_of x with "symbol" -> `Symbol (symbol_of_js x) | _ -> `Other (a_of_js x));
614-
to_js = (fun a_to_js -> function `Symbol x -> symbol_to_js x | `Other x -> a_to_js x)
615-
}]
616-
val or_symbol_to_js: ('a -> Ojs.t) -> 'a or_symbol -> Ojs.t
617-
val or_symbol_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a or_symbol
618-
type 'a or_bigint = [`BigInt of bigint | `Other of 'a] [@@js.custom {
619-
of_js = (fun a_of_js x -> match Ojs.type_of x with "bigint" -> `BigInt (bigint_of_js x) | _ -> `Other (a_of_js x));
620-
to_js = (fun a_to_js -> function `BigInt x -> bigint_to_js x | `Other x -> a_to_js x)
621-
}]
622-
val or_bigint_to_js: ('a -> Ojs.t) -> 'a or_bigint -> Ojs.t
623-
val or_bigint_of_js: (Ojs.t -> 'a) -> Ojs.t -> 'a or_bigint
624-
625-
val is_array: Ojs.t -> bool [@@js.global "Array.isArray"]
626-
627-
type ('a, 't) or_array = [`Array of 't list | `Other of 'a] [@@js.custom {
628-
of_js = (fun a_of_js t_of_js x ->
629-
if is_array x then `Array (Ojs.list_of_js t_of_js x)
630-
else `Other (a_of_js x)
631-
);
632-
to_js = (fun a_to_js t_to_js -> function `Array x -> Ojs.list_to_js t_to_js x | `Other x -> a_to_js x)
633-
}]
634-
val or_array_to_js: ('a -> Ojs.t) -> ('t -> Ojs.t) -> ('a, 't) or_array -> Ojs.t
635-
val or_array_of_js: (Ojs.t -> 'a) -> (Ojs.t -> 't) -> Ojs.t -> ('a, 't) or_array
636-
637-
type ('a, 'cases) or_enum = [`Enum of 'cases | `Other of 'a] [@@js.custom {
638-
of_js = (fun a_of_js cases_of_js x ->
639-
try `Enum (cases_of_js x) with _ -> `Other (a_of_js x));
640-
to_js = (fun a_to_js cases_to_js -> function `Enum cases -> cases_to_js cases | `Other x -> a_to_js x)
641-
}]
642-
val or_enum_to_js: ('a -> Ojs.t) -> ('cases -> Ojs.t) -> ('a, 'cases) or_enum -> Ojs.t
643-
val or_enum_of_js: (Ojs.t -> 'a) -> (Ojs.t -> 'cases) -> Ojs.t -> ('a, 'cases) or_enum
644586
"""

src/Targets/JsOfOCaml/OCamlHelper.fs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -179,18 +179,6 @@ module Type =
179179
// our types
180180
let intf = str "intf"
181181

182-
let null_or t = app (str "or_null") [t]
183-
let undefined_or t = app (str "or_undefined") [t]
184-
let null_or_undefined_or t = app (str "or_null_or_undefined") [t]
185-
let string_or t = app (str "or_string") [t]
186-
let number_or t = app (str "or_number") [t]
187-
let boolean_or t = app (str "or_boolean") [t]
188-
let symbol_or t = app (str "or_symbol") [t]
189-
let bigint_or t = app (str "or_bigint") [t]
190-
191-
let array_or elemT t = app (str "or_array") [t; elemT]
192-
let enum_or cases t = app (str "or_enum") [t; cases]
193-
194182
let rec union = function
195183
| [] -> failwith "union type with zero elements"
196184
| x :: [] -> x

0 commit comments

Comments
 (0)