Skip to content

Commit ed1b5c3

Browse files
authored
Merge pull request #3810 from BuckleScript/names_of_constructors
Track the names of constructors when compiling switch statements.
2 parents 813df3f + 6b8c0dd commit ed1b5c3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+6694
-6215
lines changed

jscomp/core/j.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ and 'a case_clause = {
329329
switch_case : 'a ;
330330
switch_body : block ;
331331
should_break : bool ; (* true means break *)
332+
comment : string option ;
332333
}
333334

334335
(* TODO: For efficency: block should not be a list, it should be able to

jscomp/core/js_dump.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,12 +499,13 @@ and pp_function is_method
499499
and pp_one_case_clause : 'a .
500500
_ -> P.t -> (P.t -> 'a -> unit) -> 'a J.case_clause -> _
501501
= fun cxt f pp_cond
502-
({switch_case; switch_body ; should_break } : _ J.case_clause) ->
502+
({switch_case; switch_body ; should_break; comment; } : _ J.case_clause) ->
503503
let cxt =
504504
P.group f 1 (fun _ ->
505505
P.group f 1 (fun _ ->
506506
P.string f L.case;
507507
P.space f ;
508+
pp_comment_option f comment;
508509
pp_cond f switch_case; (* could be integer or string *)
509510
P.space f ;
510511
P.string f L.colon );

jscomp/core/js_map.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,12 +444,12 @@ class virtual map =
444444
*)
445445
'a 'a_out.
446446
('self_type -> 'a -> 'a_out) -> 'a case_clause -> 'a_out case_clause =
447-
fun _f_a { switch_case = _x; switch_body = _x_i1; should_break = _x_i2
447+
fun _f_a { switch_case = _x; switch_body = _x_i1; should_break = _x_i2; comment
448448
} ->
449449
let _x = _f_a o _x in
450450
let _x_i1 = o#block _x_i1 in
451451
let _x_i2 = o#bool _x_i2
452-
in { switch_case = _x; switch_body = _x_i1; should_break = _x_i2; }
452+
in { switch_case = _x; switch_body = _x_i1; should_break = _x_i2; comment }
453453
method block : block -> block = (* true means break *)
454454
(* TODO: For efficency: block should not be a list, it should be able to
455455
be concatenated in both ways

jscomp/core/js_of_lam_variant.ml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ let eval (arg : J.expression) (dispatches : (int * string) list ) : E.t =
4242
(Ext_list.map dispatches (fun (i,r) ->
4343
{J.switch_case = i ;
4444
switch_body = [S.return_stmt (E.str r)];
45-
should_break = false (* FIXME: if true, still print break*)
45+
should_break = false; (* FIXME: if true, still print break*)
46+
comment = None;
4647
})))]
4748

4849
(** invariant: optional is not allowed in this case *)
@@ -61,7 +62,8 @@ let eval_as_event (arg : J.expression) (dispatches : (int * string) list ) =
6162
(Ext_list.map dispatches (fun (i,r) ->
6263
{J.switch_case = i ;
6364
switch_body = [S.return_stmt (E.str r)];
64-
should_break = false (* FIXME: if true, still print break*)
65+
should_break = false; (* FIXME: if true, still print break*)
66+
comment = None;
6567
}) ))]
6668
, (* TODO: improve, one dispatch later,
6769
the problem is that we can not create bindings
@@ -89,7 +91,8 @@ let eval_as_int (arg : J.expression) (dispatches : (int * int) list ) : E.t =
8991
(Ext_list.map dispatches (fun (i,r) ->
9092
{J.switch_case = i ;
9193
switch_body = [S.return_stmt (E.int (Int32.of_int r))];
92-
should_break = false (* FIXME: if true, still print break*)
94+
should_break = false; (* FIXME: if true, still print break*)
95+
comment = None;
9396
}) ))]
9497

9598
let eval_as_unwrap (arg : J.expression) : E.t =

jscomp/core/lam.ml

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@ type apply_status =
3131

3232

3333
module Types = struct
34-
type switch =
34+
35+
type lambda_switch =
3536
{ sw_numconsts: bool; (* TODO: refine its representation *)
3637
sw_consts: (int * t) list;
3738
sw_numblocks: bool;
3839
sw_blocks: (int * t) list;
39-
sw_failaction : t option}
40+
sw_failaction : t option;
41+
sw_names : Lambda.switch_names option }
4042
(*
4143
Invariant:
4244
length (sw_consts) <= sw_numconsts
@@ -92,7 +94,7 @@ module Types = struct
9294
| Llet of Lam_compat.let_kind * ident * t * t
9395
| Lletrec of (ident * t) list * t
9496
| Lprim of prim_info
95-
| Lswitch of t * switch
97+
| Lswitch of t * lambda_switch
9698
| Lstringswitch of t * (string * t) list * t option
9799
| Lstaticraise of int * t list
98100
| Lstaticcatch of t * (int * ident list) * t
@@ -106,14 +108,16 @@ module Types = struct
106108
end
107109

108110
module X = struct
109-
type switch
110-
= Types.switch
111+
112+
type lambda_switch
113+
= Types.lambda_switch
111114
=
112115
{ sw_numconsts: bool;
113116
sw_consts: (int * t) list;
114117
sw_numblocks: bool;
115118
sw_blocks: (int * t) list;
116-
sw_failaction : t option}
119+
sw_failaction: t option;
120+
sw_names: Lambda.switch_names option }
117121
and prim_info
118122
= Types.prim_info
119123
=
@@ -148,7 +152,7 @@ module X = struct
148152
| Llet of Lam_compat.let_kind * ident * t * t
149153
| Lletrec of (ident * t) list * t
150154
| Lprim of prim_info
151-
| Lswitch of t * switch
155+
| Lswitch of t * lambda_switch
152156
| Lstringswitch of t * (string * t) list * t option
153157
| Lstaticraise of int * t list
154158
| Lstaticcatch of t * (int * ident list) * t
@@ -192,12 +196,12 @@ let inner_map
192196
let args = Ext_list.map args f in
193197
Lprim { args; primitive; loc}
194198

195-
| Lswitch(arg, {sw_consts; sw_numconsts; sw_blocks; sw_numblocks; sw_failaction}) ->
199+
| Lswitch(arg, {sw_consts; sw_numconsts; sw_blocks; sw_numblocks; sw_failaction; sw_names}) ->
196200
let arg = f arg in
197201
let sw_consts = Ext_list.map_snd sw_consts f in
198202
let sw_blocks = Ext_list.map_snd sw_blocks f in
199203
let sw_failaction = Ext_option.map sw_failaction f in
200-
Lswitch(arg, { sw_consts; sw_blocks; sw_failaction; sw_numblocks; sw_numconsts})
204+
Lswitch(arg, { sw_consts; sw_blocks; sw_failaction; sw_numblocks; sw_numconsts; sw_names})
201205
| Lstringswitch (arg,cases,default) ->
202206
let arg = f arg in
203207
let cases = Ext_list.map_snd cases f in
@@ -382,7 +386,7 @@ and eq_approx_list ls ls1 = Ext_list.for_all2_no_exn ls ls1 eq_approx
382386

383387

384388

385-
let switch lam (lam_switch : switch) : t =
389+
let switch lam (lam_switch : lambda_switch) : t =
386390
match lam with
387391
| Lconst ((Const_pointer (i,_) | (Const_int i)))
388392
->
@@ -733,7 +737,7 @@ let if_ (a : t) (b : t) (c : t) : t =
733737
&& complete_range sw_consts ~start:0 ~finish:range
734738
->
735739
Lswitch(switch_arg,
736-
{ body with sw_failaction = Some b; sw_numconsts = false })
740+
{ body with sw_failaction = Some b; sw_numconsts = false; })
737741
| _ -> Lifthenelse(a,b,c)
738742
end
739743
| _ -> Lifthenelse (a,b,c))

jscomp/core/lam.mli

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@
2828

2929
type ident = Ident.t
3030

31-
32-
type switch =
31+
type lambda_switch =
3332
{ sw_numconsts: bool;
3433
sw_consts: (int * t) list;
3534
sw_numblocks: bool;
3635
sw_blocks: (int * t) list;
37-
sw_failaction : t option}
36+
sw_failaction: t option;
37+
sw_names: Lambda.switch_names option }
3838
and apply_status =
3939
| App_na
4040
| App_ml_full
@@ -65,7 +65,7 @@ and t = private
6565
| Llet of Lam_compat.let_kind * ident * t * t
6666
| Lletrec of (ident * t) list * t
6767
| Lprim of prim_info
68-
| Lswitch of t * switch
68+
| Lswitch of t * lambda_switch
6969
| Lstringswitch of t * (string * t) list * t option
7070
| Lstaticraise of int * t list
7171
| Lstaticcatch of t * (int * ident list) * t
@@ -115,7 +115,7 @@ val letrec : (ident * t) list -> t -> t
115115
val if_ : t -> t -> t -> t
116116

117117
(** constant folding*)
118-
val switch : t -> switch -> t
118+
val switch : t -> lambda_switch -> t
119119
(** constant folding*)
120120
val stringswitch : t -> (string * t) list -> t option -> t
121121

jscomp/core/lam_analysis.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ let rec size (lam : Lam.t) =
302302
args; _} -> size_lams (size fn) args
303303
(* | Lfunction(_, params, l) -> really_big () *)
304304
| Lfunction {body} -> size body
305-
| Lswitch(_, _) -> really_big ()
305+
| Lswitch _ -> really_big ()
306306
| Lstringswitch(_,_,_) -> really_big ()
307307
| Lstaticraise (i,ls) ->
308308
Ext_list.fold_left ls 1 (fun acc x -> size x + acc)

jscomp/core/lam_bounded_vars.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ let rewrite (map : _ Ident_hashtbl.t)
120120
sw_blocks;
121121
sw_numblocks;
122122
sw_numconsts;
123+
sw_names;
123124
}) ->
124125
let l = aux l in
125126
Lam.switch l
@@ -128,7 +129,8 @@ let rewrite (map : _ Ident_hashtbl.t)
128129
sw_blocks = Ext_list.map_snd sw_blocks aux;
129130
sw_numconsts = sw_numconsts;
130131
sw_numblocks = sw_numblocks;
131-
sw_failaction = option_map sw_failaction
132+
sw_failaction = option_map sw_failaction;
133+
sw_names;
132134
}
133135
| Lstringswitch(l, sw, d) ->
134136
let l = aux l in

jscomp/core/lam_compile.ml

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,38 @@ type default_case =
9393
let no_effects_const = lazy true
9494
let has_effects_const = lazy false
9595

96+
let names_from_construct_pattern (pat: Typedtree.pattern) =
97+
let names_from_type_variant cstrs =
98+
let (consts, blocks) = List.fold_left
99+
(fun (consts, blocks) cstr ->
100+
if cstr.Types.cd_args = []
101+
then (Ident.name cstr.Types.cd_id :: consts, blocks)
102+
else (consts, Ident.name cstr.Types.cd_id :: blocks))
103+
([], []) cstrs in
104+
Some {Lambda.consts = consts |> List.rev |> Array.of_list;
105+
blocks = blocks |> List.rev |> Array.of_list } in
106+
107+
let rec resolve_path n path =
108+
match Env.find_type path pat.pat_env with
109+
| {type_kind = Type_variant cstrs} ->
110+
names_from_type_variant cstrs
111+
| {type_kind = Type_abstract; type_manifest = Some t} ->
112+
( match (Ctype.unalias t).desc with
113+
| Tconstr (pathn, _, _) ->
114+
(* Format.eprintf "XXX path%d:%s path%d:%s@." n (Path.name path) (n+1) (Path.name pathn); *)
115+
resolve_path (n+1) pathn
116+
| _ -> None)
117+
| {type_kind = Type_abstract; type_manifest = None} ->
118+
None
119+
| {type_kind = Type_record _ | Type_open (* Exceptions *) } ->
120+
None in
121+
122+
match (Btype.repr pat.pat_type).desc with
123+
| Tconstr (path, _, _) -> resolve_path 0 path
124+
| _ -> assert false
125+
126+
let () = Matching.names_from_construct_pattern := names_from_construct_pattern
127+
96128
(** We drop the ability of cross-compiling
97129
the compiler has to be the same running
98130
*)
@@ -412,6 +444,7 @@ and compile_recursive_lets cxt id_args : Js_output.t =
412444
and compile_general_cases
413445
:
414446
'a .
447+
('a -> string option) ->
415448
('a -> J.expression) ->
416449
(J.expression -> J.expression -> J.expression) ->
417450
Lam_compile_context.t ->
@@ -421,6 +454,7 @@ and compile_general_cases
421454
_ ->
422455
('a * Lam.t) list -> default_case -> J.block
423456
= fun
457+
(make_comment : _ -> string option)
424458
(make_exp : _ -> J.expression)
425459
(eq_exp : J.expression -> J.expression -> J.expression)
426460
(cxt : Lam_compile_context.t)
@@ -499,10 +533,11 @@ and compile_general_cases
499533
should_break && Lam_exit_code.has_exit lam in
500534
{J.switch_case ;
501535
switch_body;
502-
should_break
536+
should_break;
537+
comment = make_comment switch_case;
503538
}
504539
else
505-
{ switch_case; switch_body = []; should_break = false }
540+
{ switch_case; switch_body = []; should_break = false; comment = make_comment switch_case; }
506541
)
507542

508543
(* TODO: we should also group default *)
@@ -512,9 +547,10 @@ and compile_general_cases
512547
[switch ?default ?declaration switch_exp body]
513548
)
514549

515-
and compile_cases cxt switch_exp table default =
550+
and compile_cases cxt switch_exp table default get_name =
516551
compile_general_cases
517-
E.small_int
552+
get_name
553+
(fun i -> {(E.small_int i) with comment = get_name i})
518554
E.int_equal
519555
cxt
520556
(fun ?default ?declaration e clauses ->
@@ -534,7 +570,8 @@ and compile_switch switch_arg sw (lambda_cxt : Lam_compile_context.t) =
534570
sw_consts;
535571
sw_numblocks;
536572
sw_blocks;
537-
sw_failaction } : Lam.switch) = sw in
573+
sw_failaction;
574+
sw_names } : Lam.lambda_switch) = sw in
538575
let sw_num_default =
539576
match sw_failaction with
540577
| None -> Complete
@@ -549,6 +586,11 @@ and compile_switch switch_arg sw (lambda_cxt : Lam_compile_context.t) =
549586
if sw_numblocks
550587
then Complete
551588
else Default x in
589+
let get_name is_const i =
590+
match sw_names with
591+
| None -> None
592+
| Some {blocks; consts} ->
593+
Some (if is_const then consts.(i) else blocks.(i)) in
552594
let compile_whole (cxt : Lam_compile_context.t ) =
553595
match compile_lambda
554596
{cxt with continuation = NeedValue Not_tail}
@@ -558,20 +600,20 @@ and compile_switch switch_arg sw (lambda_cxt : Lam_compile_context.t) =
558600
| { block; value = Some e } ->
559601
block @
560602
(if sw_numconsts && sw_consts = [] then
561-
compile_cases cxt (E.tag e) sw_blocks sw_blocks_default
603+
compile_cases cxt (E.tag e) sw_blocks sw_blocks_default (get_name false)
562604
else if sw_numblocks && sw_blocks = [] then
563-
compile_cases cxt e sw_consts sw_num_default
605+
compile_cases cxt e sw_consts sw_num_default (get_name true)
564606
else
565607
(* [e] will be used twice *)
566608
let dispatch e =
567609
S.if_
568610
(E.is_type_number e )
569-
(compile_cases cxt e sw_consts sw_num_default
611+
(compile_cases cxt e sw_consts sw_num_default (get_name true)
570612
)
571613
(* default still needed, could simplified*)
572614
~else_:
573-
(compile_cases cxt (E.tag e ) sw_blocks
574-
sw_blocks_default) in
615+
(compile_cases cxt (E.tag e ) sw_blocks
616+
sw_blocks_default (get_name false)) in
575617
match e.expression_desc with
576618
| J.Var _ -> [ dispatch e]
577619
| _ ->
@@ -597,6 +639,7 @@ and compile_switch switch_arg sw (lambda_cxt : Lam_compile_context.t) =
597639

598640
and compile_string_cases cxt switch_exp table default =
599641
compile_general_cases
642+
(fun s -> None)
600643
E.str
601644
E.string_equal
602645
cxt
@@ -752,15 +795,15 @@ and compile_staticcatch (lam : Lam.t) (lambda_cxt : Lam_compile_context.t)=
752795
Js_output.append_output
753796
(Js_output.make (S.declare_variable ~kind:Variable v :: declares) )
754797
(Js_output.append_output lbody (Js_output.make (
755-
compile_cases new_cxt exit_expr handlers NonComplete) ~value:(E.var v )))
798+
compile_cases new_cxt exit_expr handlers NonComplete (fun _ -> None)) ~value:(E.var v )))
756799
| Declare (kind, id)
757800
(* declare first this we will do branching*) ->
758801
let declares = S.declare_variable ~kind id :: declares in
759802
let new_cxt = {lambda_cxt with jmp_table = jmp_table; continuation = Assign id } in
760803
let lbody = compile_lambda new_cxt body in
761804
Js_output.append_output (Js_output.make declares)
762805
(Js_output.append_output lbody
763-
(Js_output.make (compile_cases new_cxt exit_expr handlers NonComplete)))
806+
(Js_output.make (compile_cases new_cxt exit_expr handlers NonComplete (fun _ -> None))))
764807
(* place holder -- tell the compiler that
765808
we don't know if it's complete
766809
*)
@@ -769,13 +812,13 @@ and compile_staticcatch (lam : Lam.t) (lambda_cxt : Lam_compile_context.t)=
769812
let lbody = compile_lambda new_cxt body in
770813
Js_output.append_output (Js_output.make declares)
771814
(Js_output.append_output lbody
772-
(Js_output.make (compile_cases new_cxt exit_expr handlers NonComplete)))
815+
(Js_output.make (compile_cases new_cxt exit_expr handlers NonComplete (fun _ -> None))))
773816
| Assign _ ->
774817
let new_cxt = {lambda_cxt with jmp_table = jmp_table } in
775818
let lbody = compile_lambda new_cxt body in
776819
Js_output.append_output (Js_output.make declares)
777820
(Js_output.append_output lbody
778-
(Js_output.make (compile_cases new_cxt exit_expr handlers NonComplete)))
821+
(Js_output.make (compile_cases new_cxt exit_expr handlers NonComplete (fun _ -> None))))
779822

780823
and compile_sequand
781824
(l : Lam.t) (r : Lam.t) (lambda_cxt : Lam_compile_context.t) =
@@ -1588,7 +1631,7 @@ and compile_lambda
15881631
| Lstringswitch(l, cases, default) ->
15891632
compile_stringswitch l cases default lambda_cxt
15901633
| Lswitch(switch_arg, sw) ->
1591-
compile_switch switch_arg sw lambda_cxt
1634+
compile_switch switch_arg sw lambda_cxt
15921635
| Lstaticraise(i, largs) ->
15931636
compile_staticraise i largs lambda_cxt
15941637
| Lstaticcatch _ ->

0 commit comments

Comments
 (0)