-
Notifications
You must be signed in to change notification settings - Fork 465
/
Copy pathTypeVars.ml
113 lines (106 loc) · 3.32 KB
/
TypeVars.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
open GenTypeCommon
let extractFromTypeExpr typeParams =
typeParams
|> List.fold_left
(fun soFar typeExpr ->
match typeExpr with
| {Types.desc = Tvar (Some s)} ->
let typeName = s in
typeName :: soFar
| {Types.desc = Tlink _} ->
(* see if we need to collect more type vars here: t as 'a *)
soFar
| _ -> assert false)
[]
|> List.rev
let extractFromCoreType typeParams =
typeParams
|> List.fold_left
(fun soFar typeExpr ->
match typeExpr.Typedtree.ctyp_desc with
| Ttyp_var s ->
let typeName = s in
typeName :: soFar
| _ -> soFar)
[]
|> List.rev
let rec substitute ~f type0 =
match type0 with
| Array (t, arrayKind) -> Array (t |> substitute ~f, arrayKind)
| Dict type_ -> Dict (type_ |> substitute ~f)
| Function function_ ->
Function
{
function_ with
argTypes =
function_.argTypes
|> List.map (fun {aName; aType = t} ->
{aName; aType = t |> substitute ~f});
}
| GroupOfLabeledArgs fields ->
GroupOfLabeledArgs
(fields
|> List.map (fun field ->
{field with type_ = field.type_ |> substitute ~f}))
| Ident {typeArgs = []} -> type0
| Ident ({typeArgs} as ident) ->
Ident {ident with typeArgs = typeArgs |> List.map (substitute ~f)}
| Null type_ -> Null (type_ |> substitute ~f)
| Nullable type_ -> Nullable (type_ |> substitute ~f)
| Object (closedFlag, fields) ->
Object
( closedFlag,
fields
|> List.map (fun field ->
{field with type_ = field.type_ |> substitute ~f}) )
| Option type_ -> Option (type_ |> substitute ~f)
| Promise type_ -> Promise (type_ |> substitute ~f)
| Tuple innerTypes -> Tuple (innerTypes |> List.map (substitute ~f))
| TypeVar s -> (
match f s with
| None -> type0
| Some type1 -> type1)
| Variant variant ->
Variant
{
variant with
payloads =
variant.payloads
|> List.map (fun payload ->
{payload with t = payload.t |> substitute ~f});
}
let rec free_ type0 : StringSet.t =
match type0 with
| Array (t, _) -> t |> free_
| Function {argTypes; retType; typeVars} ->
StringSet.diff
((argTypes |> freeOfList_) +++ (retType |> free_))
(typeVars |> StringSet.of_list)
| GroupOfLabeledArgs fields | Object (_, fields) ->
fields
|> List.fold_left
(fun s {type_} -> StringSet.union s (type_ |> free_))
StringSet.empty
| Ident {typeArgs} ->
typeArgs
|> List.fold_left
(fun s typeArg -> StringSet.union s (typeArg |> free_))
StringSet.empty
| Dict type_ | Null type_ | Nullable type_ -> type_ |> free_
| Option type_ | Promise type_ -> type_ |> free_
| Tuple innerTypes ->
innerTypes
|> List.fold_left
(fun s typeArg -> StringSet.union s (typeArg |> free_))
StringSet.empty
| TypeVar s -> s |> StringSet.singleton
| Variant {payloads} ->
payloads
|> List.fold_left
(fun s {t} -> StringSet.union s (t |> free_))
StringSet.empty
and freeOfList_ types =
types
|> List.fold_left (fun s {aType} -> s +++ (aType |> free_)) StringSet.empty
and ( +++ ) = StringSet.union
let free type_ = type_ |> free_ |> StringSet.elements