Skip to content

Commit b99d55c

Browse files
committed
Add intermediate structure for printing flow types.
1 parent db4bd22 commit b99d55c

File tree

4 files changed

+117
-44
lines changed

4 files changed

+117
-44
lines changed

jscomp/core.mllib

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ lam_group
4949

5050
j
5151
js_ast_util
52+
flow_tree
53+
flow_print
5254
flow
5355

5456
js_arr

jscomp/flow.ml

Lines changed: 47 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
open Flow_tree
2+
13
type state = {
24
env: Env.t;
35
mutable used_types: string list;
4-
mutable before: string list;
6+
mutable types: decl list;
7+
mutable exports: decl list;
58
}
69

710
let print_id s id = Ident.name id
@@ -12,30 +15,27 @@ let rec print_path s path =
1215
| Path.Pident id -> print_id s id
1316
| Path.Pdot (p, str, _) -> print_path s p ^ "__" ^ str
1417
| Path.Papply _ -> "Dunno_what_Papply_is"
15-
16-
let rec p_sig s (sig_ : Types.signature) =
17-
let lines = List.map (p_sig_item s) sig_ in
18-
let lines = List.filter (fun l -> l <> "") lines in
19-
String.concat "\n\n" lines
20-
21-
and p_sig_item s = function
22-
| Sig_value (id, val_desc) ->
23-
let name = Ident.name id in
24-
let desc = p_type_expr s val_desc.val_type in
25-
"declare export var " ^ name ^ ": " ^ desc ^ ";"
26-
| Sig_type _ -> "" (* Types are declared on demand *)
27-
| Sig_typext _ -> ""
28-
| Sig_module _ -> "" (* Non-toplevel values are not exposed *)
29-
| Sig_modtype _ -> ""
30-
| Sig_class _ -> ""
31-
| Sig_class_type _ -> ""
18+
19+
let rec p_sigs s sigs = List.iter (p_sig s) sigs
20+
21+
and p_sig s = function
22+
| Types.Sig_value (id, val_desc) ->
23+
let decl_name = Ident.name id in
24+
let decl_type = p_type_expr s val_desc.val_type in
25+
s.exports <- {decl_name; decl_type} :: s.exports
26+
| Sig_type _ -> () (* Types are declared on demand *)
27+
| Sig_typext _ -> ()
28+
| Sig_module _ -> () (* Non-toplevel values are not exposed *)
29+
| Sig_modtype _ -> ()
30+
| Sig_class _ -> ()
31+
| Sig_class_type _ -> ()
3232

3333
and p_type_decl s type_decl =
3434
match type_decl.Types.type_kind with
3535
| Type_abstract ->
3636
begin match type_decl.type_manifest with
3737
| Some expr -> p_type_expr s expr
38-
| None -> "/* abstract w/o manifest */ mixed"
38+
| None -> p_any "abstract w/o manifest"
3939
end
4040
| Type_record _ -> p_any "Type_record"
4141
| Type_variant _ -> p_any "Type_variant"
@@ -49,25 +49,26 @@ and p_type_expr s type_expr =
4949
| None -> "-" in
5050
p_any ("Tvar " ^ str)
5151
| Tarrow (label, left, right, c) -> p_arrow s (label, left, right, c)
52-
| Ttuple tl -> "[" ^ (String.concat ", " (List.map (p_type_expr s) tl)) ^ "]"
52+
| Ttuple tl -> T_tuple (List.map (p_type_expr s) tl)
5353
| Tconstr (path, tl, _) ->
5454
let name = Path.name path in
5555
begin match name, tl with
56-
| "unit", _ -> "void"
57-
| "string", _ -> "string"
58-
| "int", _ | "float", _ -> "number"
59-
| "bool", _ -> "any"
60-
| "array", _ -> "Array<" ^ (p_type_expr s (List.hd tl)) ^ ">"
56+
| "unit", _ -> p_named "void"
57+
| "string", _ -> p_named "string"
58+
| "int", _ | "float", _ -> p_named "number"
59+
| "bool", _ -> p_any "bool"
60+
| "array", _ -> p_named ~tl:[p_type_expr s (List.hd tl)] "Array"
6161
| "Js.t", [{desc = Tobject (t, _); _}] ->
6262
p_js_obj s t
6363
| _ ->
64-
let path_ = print_path s path in
65-
if not (List.mem path_ s.used_types) then begin
66-
s.used_types <- path_ :: s.used_types;
67-
let t_def = p_type_decl s (Env.find_type path s.env) in
68-
s.before <- ("type " ^ path_ ^ " = " ^ t_def ^ ";") :: s.before
64+
let decl_name = print_path s path in
65+
if not (List.mem decl_name s.used_types) then begin
66+
s.used_types <- decl_name :: s.used_types;
67+
let decl_type = p_type_decl s (Env.find_type path s.env) in
68+
let decl = {decl_name; decl_type} in
69+
s.types <- decl :: s.types
6970
end;
70-
path_
71+
p_named decl_name
7172
end
7273
| Tobject _ -> p_any "Tobject"
7374
| Tfield _ -> p_any "Tfield" (* Shouldn't ever happen? *)
@@ -87,27 +88,29 @@ and p_arrow s t =
8788
| Tlink right -> collect (label, left, right, c)
8889
| _ -> ([left], right)
8990
in
90-
let (params, result) = collect t in
91-
let params = List.mapi (fun i p ->
92-
"p" ^ (string_of_int i) ^ ": " ^ (p_type_expr s p)
93-
) params in
94-
"(" ^ (String.concat ", " params) ^ ") => " ^ (p_type_expr s result)
91+
let (params, ret) = collect t in
92+
let params = List.map (p_type_expr s) params in
93+
T_fun (params, p_type_expr s ret)
9594

9695
and p_js_obj s t =
9796
let rec loop t acc =
9897
match t.Types.desc with
99-
| Tfield (name, _, left, right) ->
100-
(name ^ ": " ^ (p_type_expr s left)) :: (loop right acc)
98+
| Tfield (field_name, _, left, right) ->
99+
{field_name; field_type=(p_type_expr s left)} :: (loop right acc)
101100
| Tnil -> acc
102101
| _ -> acc
103102
in
104103
let fields = loop t [] in
105-
"{" ^ (String.concat ", " fields) ^ "}"
104+
T_obj fields
105+
106+
and p_any comment = p_named ~comment "any"
106107

107-
and p_any comment = "/* " ^ comment ^ " */any"
108+
and p_named ?(tl=[]) ?comment name = T_name (name, tl, comment)
108109

109110
let print_signature env sigs =
110-
let s = {env; used_types = []; before = []} in
111-
let src = p_sig s sigs in
112-
let before = String.concat "" (List.map (fun x -> x ^ "\n\n") s.before) in
113-
"// @flow\n\n" ^ before ^ src
111+
let s = {env; used_types = []; types = []; exports = []} in
112+
List.iter (p_sig s) sigs;
113+
Flow_print.print {
114+
prog_types = List.rev s.types;
115+
prog_exports = List.rev s.exports;
116+
}

jscomp/flow_print.ml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
open Flow_tree
2+
3+
let rec print_type = function
4+
| T_name (name, tl, comment) ->
5+
let comment = match comment with
6+
| Some comment -> "/* " ^ comment ^ " */"
7+
| None -> ""
8+
in
9+
let args = match List.map print_type tl with
10+
| [] -> ""
11+
| tl -> "<" ^ (String.concat ", " tl) ^ ">"
12+
in
13+
comment ^ name ^ args
14+
| T_fun (args, ret) ->
15+
let args_str = args
16+
|> List.mapi (fun i t -> "p" ^ (string_of_int i) ^ ": " ^ (print_type t))
17+
|> String.concat ", "
18+
in
19+
let ret = print_type ret in
20+
"(" ^ args_str ^ ") => " ^ ret
21+
| T_obj fields ->
22+
let fields_str = fields
23+
|> List.map (fun f -> f.field_name ^ ": " ^ (print_type f.field_type))
24+
|> String.concat ", "
25+
in
26+
"{" ^ fields_str ^ "}"
27+
| T_tuple types ->
28+
let types_str = types |> List.map print_type |> String.concat ", " in
29+
"[" ^ types_str ^ "]"
30+
31+
let print_type_decl decl =
32+
let type_str = print_type decl.decl_type in
33+
"type " ^ decl.decl_name ^ " = " ^ type_str
34+
35+
let print_decl decl =
36+
let type_ = print_type decl.decl_type in
37+
"declare export var " ^ decl.decl_name ^ ": " ^ type_ ^ ";"
38+
39+
let print prog =
40+
let types = List.map print_type_decl prog.prog_types in
41+
let decls = List.map print_decl prog.prog_exports in
42+
"// @flow\n\n" ^
43+
(String.concat "\n\n" types) ^
44+
"\n\n" ^
45+
(String.concat "\n\n" decls) ^
46+
"\n"

jscomp/flow_tree.ml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
type prog = {
2+
prog_types: decl list;
3+
prog_exports: decl list;
4+
}
5+
6+
and decl = {
7+
decl_name: string;
8+
decl_type: type_;
9+
}
10+
11+
and type_ =
12+
| T_name of string * type_ list * string option
13+
| T_fun of arg list * type_
14+
| T_obj of field list
15+
| T_tuple of type_ list
16+
17+
and arg = type_
18+
19+
and field = {
20+
field_name: string;
21+
field_type: type_;
22+
}

0 commit comments

Comments
 (0)