@@ -32,13 +32,6 @@ module State =
32
32
type Context = TyperContext< Options, State>
33
33
module Context = TyperContext
34
34
35
- type Variance = Covariant | Contravariant | Invariant with
36
- static member (~-) ( v : Variance ) =
37
- match v with
38
- | Covariant -> Contravariant
39
- | Contravariant -> Covariant
40
- | Invariant -> Invariant
41
-
42
35
type Label =
43
36
| Case of text * text list
44
37
| TagType of text * text list
@@ -52,9 +45,7 @@ type [<RequireQualifiedAccess>] External =
52
45
type EmitTypeFlags = {
53
46
resolveUnion: bool
54
47
needParen: bool
55
- variance: Variance
56
48
external: External
57
- simplifyContravariantUnion: bool
58
49
avoidTheseArgumentNames: Set < string >
59
50
}
60
51
@@ -63,17 +54,14 @@ module EmitTypeFlags =
63
54
{
64
55
resolveUnion = true
65
56
needParen = false
66
- variance = Covariant
67
57
external = External.None
68
- simplifyContravariantUnion = false
69
58
avoidTheseArgumentNames = Set.empty
70
59
}
71
60
72
61
let noExternal flags =
73
62
{ flags with external = External.None }
74
63
let ofFuncArg isVariadic flags =
75
64
{ flags with
76
- variance = - flags.variance
77
65
external =
78
66
match flags.external with
79
67
| External.Root _ -> External.Argument isVariadic
@@ -347,18 +335,130 @@ and emitFuncType (flags: EmitTypeFlags) (overrideFunc: OverrideFunc) (ctx: Conte
347
335
| _ -> Type.curriedArrow ( args ()) ( retTy flags) |> paren
348
336
349
337
and emitUnion ( flags : EmitTypeFlags ) ( overrideFunc : OverrideFunc ) ( ctx : Context ) ( u : UnionType ) : text =
350
- // TODO: more classification
351
- let u = ResolvedUnion.checkNullOrUndefined u
352
- let rest =
353
- let rest = u.rest |> List.map ( emitTypeImpl ( EmitTypeFlags.noExternal flags) overrideFunc ctx)
354
- if List.isEmpty rest then Type.never
355
- else Type.union rest
356
- match u.hasNull, u.hasUndefined with
357
- | true , _ | _, true when flags.external = External.Return true -> Type.option rest
358
- | true , true -> Type.null_ or_ undefined_ or rest
359
- | true , false -> Type.null_ or rest
360
- | false , true -> Type.undefined_ or rest
361
- | false , false -> rest
338
+ if flags.resolveUnion = false then
339
+ u.types
340
+ |> List.distinct
341
+ |> List.map ( emitTypeImpl ( EmitTypeFlags.noExternal flags) overrideFunc ctx)
342
+ |> Type.union
343
+ else if flags.external = External.Return true then
344
+ let u = ResolvedUnion.checkNullOrUndefined u
345
+ let rest =
346
+ if List.isEmpty u.rest then Type.never
347
+ else
348
+ let t = Union { types = u.rest }
349
+ emitTypeImpl ( EmitTypeFlags.noExternal flags) overrideFunc ctx t
350
+ match u.hasNull, u.hasUndefined with
351
+ | true , _ | _, true -> Type.option rest
352
+ | false , false -> rest
353
+ else
354
+ let u = ResolvedUnion.resolve ctx u
355
+
356
+ let treatEnum ( cases : Set < Choice < Enum * EnumCase * Type , Literal >>) =
357
+ let handleLiteral l attr ty =
358
+ match l with
359
+ | LString s -> Choice1Of2 {| name = Choice1Of2 s; value = None; attr = attr |}
360
+ | LInt i -> Choice1Of2 {| name = Choice2Of2 i; value = None; attr = attr |}
361
+ | LFloat _ -> Choice2Of2 ( ty |? Type.float)
362
+ | LBool _ -> Choice2Of2 ( ty |? Type.boolean)
363
+ let cases = [
364
+ for c in cases do
365
+ match c with
366
+ | Choice1Of2 (_, _, ty) ->
367
+ let ty = emitTypeImpl ( EmitTypeFlags.noExternal flags) overrideFunc ctx ty
368
+ yield Choice2Of2 ty
369
+ | Choice2Of2 l -> yield handleLiteral l None None
370
+ ]
371
+ let cases , rest = List.splitChoice2 cases
372
+ [
373
+ if List.isEmpty cases |> not then
374
+ yield Type.polyVariant cases
375
+ yield ! rest
376
+ ]
377
+
378
+ let treatArray ( ts : Set < Type >) =
379
+ // TODO: think how to map multiple array cases properly
380
+ let elemT =
381
+ let elemT =
382
+ match Set.toList ts with
383
+ | [ t] -> t
384
+ | ts -> Union { types = ts }
385
+ emitTypeImpl ( EmitTypeFlags.noExternal flags) overrideFunc ctx elemT
386
+ Type.app Type.array [ elemT]
387
+
388
+ let treatDUMany du =
389
+ // TODO: anonymous DU?
390
+ let types =
391
+ du
392
+ |> Map.toList
393
+ |> List.collect ( fun ( _ , cases ) -> Map.toList cases)
394
+ |> List.map ( fun ( _ , t ) -> t)
395
+ types
396
+ |> List.map ( emitTypeImpl ( EmitTypeFlags.noExternal { flags with resolveUnion = false }) overrideFunc ctx)
397
+ |> List.distinct
398
+
399
+ let baseTypes = [
400
+ if not ( Set.isEmpty u.caseEnum) then
401
+ yield ! treatEnum u.caseEnum
402
+ if not ( Map.isEmpty u.discriminatedUnions) then
403
+ yield ! treatDUMany u.discriminatedUnions
404
+ match u.caseArray with
405
+ | Some ts -> yield treatArray ts
406
+ | None -> ()
407
+ for t in u.otherTypes do
408
+ yield emitTypeImpl ( EmitTypeFlags.noExternal { flags with resolveUnion = false }) overrideFunc ctx t
409
+ ]
410
+
411
+ let case name value = {| name = Choice1Of2 name; value = value; attr = None |}
412
+ let genPoly unwrap =
413
+ let cases = [
414
+ for t in u.typeofableTypes do
415
+ match t with
416
+ | Typeofable.String -> yield case " String" ( Some Type.string)
417
+ | Typeofable.Number -> yield case " Number" ( Some ( Type.number ctx.options))
418
+ | Typeofable.Boolean -> yield case " Boolean" ( Some Type.boolean)
419
+ | Typeofable.Symbol -> yield case " Symbol" ( Some Type.symbol)
420
+ | Typeofable.BigInt -> yield case " BigInt" ( Some Type.bigint)
421
+
422
+ if u.caseNull then
423
+ yield case " Null" ( if unwrap then Some Type.null_ else None)
424
+ if u.caseUndefined then
425
+ yield case " Undefined" ( if unwrap then Some Type.undefined else None)
426
+
427
+ match List.distinct baseTypes with
428
+ | [] -> ()
429
+ | ts ->
430
+ if unwrap then
431
+ for i, t in ts |> List.indexed do
432
+ yield case ( sprintf " U%d " ( i+ 1 )) ( Some t)
433
+ else
434
+ yield case " Other" ( Some ( Type.union ts))
435
+ ]
436
+ Type.polyVariant cases
437
+
438
+ let createNullable isNull isUndefined t =
439
+ match isNull, isUndefined with
440
+ | false , false -> t
441
+ | true , false -> Type.null_ or t
442
+ | false , true -> Type.undefined_ or t
443
+ | true , true -> Type.null_ or_ undefined_ or t
444
+
445
+ let emitTypeofableType t = emitTypeImpl flags overrideFunc ctx ( TypeofableType.toType t)
446
+
447
+ let isExternalArg = match flags.external with External.Argument _ -> true | _ -> false
448
+
449
+ match baseTypes, Set.toList u.typeofableTypes, u.caseNull, u.caseUndefined with
450
+ | [], [], false , false -> impossible " emitUnion_empty_union"
451
+ | [], [], true , false -> Type.null_
452
+ | [], [], false , true -> Type.undefined
453
+ | [], [], true , true -> Type.null_ or_ undefined_ or Type.never
454
+ | [ t], [], isNull, isUndefined -> createNullable isNull isUndefined t
455
+ | ts, [], isNull, isUndefined when not isExternalArg ->
456
+ createNullable isNull isUndefined ( Type.union ts)
457
+ | [], [ t], isNull, isUndefined -> createNullable isNull isUndefined ( emitTypeofableType t)
458
+ | _, _, _, _ ->
459
+ match flags.external with
460
+ | External.Argument _ -> Attr.PolyVariant.unwrap +@ " " + genPoly true
461
+ | _ -> Type.app ( str " Primitive.t" ) [ genPoly false ]
362
462
363
463
/// `[ #A | #B | ... ]`
364
464
and emitLabels ( ctx : Context ) labels =
@@ -621,7 +721,6 @@ let extValue flags overrideFunc ctx (t: Type) =
621
721
ty, attr
622
722
623
723
let rec emitMembers flags overrideFunc ctx ( selfTy : Type ) ( isExportDefaultClass : bool ) ( ma : MemberAttribute ) m =
624
- let flags = { flags with simplifyContravariantUnion = true }
625
724
let emitType_ = emitTypeImpl flags overrideFunc
626
725
627
726
let comments = emitComments ma.comments
@@ -1052,7 +1151,7 @@ let rec emitClass flags overrideFunc (ctx: Context) (current: StructuredText) (c
1052
1151
1053
1152
let builder =
1054
1153
let emitType_ ctx ty =
1055
- emitTypeImpl { flags with needParen = true ; variance = Contravariant } overrideFunc ctx ty
1154
+ emitTypeImpl { flags with needParen = true } overrideFunc ctx ty
1056
1155
if not c.isPOJO then []
1057
1156
else
1058
1157
let field ( fl : FieldLike ) =
@@ -1362,7 +1461,6 @@ let createStructuredText (rootCtx: Context) (stmts: Statement list) : Structured
1362
1461
1363
1462
/// convert interface members to appropriate statements
1364
1463
let intfToStmts ( moduleIntf : Class < _ >) ctx flags overrideFunc =
1365
- let flags = { flags with simplifyContravariantUnion = true }
1366
1464
let inline extFunc ft = extFunc flags overrideFunc ctx ft
1367
1465
let inline func ft = func flags overrideFunc ctx ft
1368
1466
let inline newableFunc ft = newableFunc flags overrideFunc ctx ft
0 commit comments