926
926
927
927
type 'row pattern_matching = {
928
928
mutable cases : 'row list ;
929
- args : (lambda * let_kind ) list ;
929
+ args : (lambda * let_kind * layout ) list ;
930
930
(* * args are not just Ident.t in at least the following cases:
931
931
- when matching the arguments of a constructor,
932
932
direct field projections are used (make_field_args)
@@ -1433,7 +1433,7 @@ and precompile_var args cls def k =
1433
1433
If the rest doesn't generate any split, abort and do_not_precompile. *)
1434
1434
match args with
1435
1435
| [] -> assert false
1436
- | _ :: ((Lvar v , _ ) as arg ) :: rargs -> (
1436
+ | _ :: ((Lvar v , _ , _ ) as arg ) :: rargs -> (
1437
1437
(* We will use the name of the head column of the submatrix
1438
1438
we compile, and this is the *second* column of our argument. *)
1439
1439
match cls with
@@ -1451,7 +1451,7 @@ and precompile_var args cls def k =
1451
1451
(* we learned by pattern-matching on [args]
1452
1452
that [p::ps] has at least two arguments,
1453
1453
so [ps] must be non-empty *)
1454
- half_simplify_clause ~arg: (fst arg ) (ps, act))
1454
+ half_simplify_clause ~arg: (Lvar v ) (ps, act))
1455
1455
cls
1456
1456
and var_def = Default_environment. pop_column def in
1457
1457
let { me = first; matrix }, nexts =
@@ -1664,7 +1664,7 @@ let make_line_matching get_expr_args head def = function
1664
1664
}
1665
1665
1666
1666
type 'a division = {
1667
- args : (lambda * let_kind ) list ;
1667
+ args : (lambda * let_kind * layout ) list ;
1668
1668
cells : ('a * cell ) list
1669
1669
}
1670
1670
@@ -1754,7 +1754,7 @@ let get_pat_args_constr p rem =
1754
1754
| { pat_desc = Tpat_construct (_ , _ , args , _ ) } -> args @ rem
1755
1755
| _ -> assert false
1756
1756
1757
- let get_expr_args_constr ~scopes head (arg , _mut ) rem =
1757
+ let get_expr_args_constr ~scopes head (arg , _mut , layout ) rem =
1758
1758
let cstr =
1759
1759
match head.pat_desc with
1760
1760
| Patterns.Head. Construct cstr -> cstr
@@ -1766,19 +1766,19 @@ let get_expr_args_constr ~scopes head (arg, _mut) rem =
1766
1766
if pos > last_pos then
1767
1767
argl
1768
1768
else
1769
- (Lprim (Pfield (pos, Reads_agree ), [ arg ], loc), binding_kind)
1769
+ (Lprim (Pfield (pos, Reads_agree ), [ arg ], loc), binding_kind, layout_field )
1770
1770
:: make_args (pos + 1 )
1771
1771
in
1772
1772
make_args first_pos
1773
1773
in
1774
1774
if cstr.cstr_inlined <> None then
1775
- (arg, Alias ) :: rem
1775
+ (arg, Alias , layout ) :: rem
1776
1776
else
1777
1777
match cstr.cstr_tag with
1778
1778
| Cstr_constant _
1779
1779
| Cstr_block _ ->
1780
1780
make_field_accesses Alias 0 (cstr.cstr_arity - 1 ) rem
1781
- | Cstr_unboxed -> (arg, Alias ) :: rem
1781
+ | Cstr_unboxed -> (arg, Alias , layout ) :: rem
1782
1782
| Cstr_extension _ -> make_field_accesses Alias 1 cstr.cstr_arity rem
1783
1783
1784
1784
let divide_constructor ~scopes ctx pm =
@@ -1796,10 +1796,10 @@ let get_expr_args_variant_constant = drop_expr_arg
1796
1796
let nonconstant_variant_field index =
1797
1797
Lambda. Pfield (index, Reads_agree )
1798
1798
1799
- let get_expr_args_variant_nonconst ~scopes head (arg , _mut ) rem =
1799
+ let get_expr_args_variant_nonconst ~scopes head (arg , _mut , _layout ) rem =
1800
1800
let loc = head_loc ~scopes head in
1801
1801
let field_prim = nonconstant_variant_field 1 in
1802
- (Lprim (field_prim, [ arg ], loc), Alias ) :: rem
1802
+ (Lprim (field_prim, [ arg ], loc), Alias , layout_field ) :: rem
1803
1803
1804
1804
let divide_variant ~scopes row ctx { cases = cl ; args; default = def } =
1805
1805
let rec divide = function
@@ -2006,9 +2006,9 @@ let inline_lazy_force arg pos loc =
2006
2006
tables (~ 250 elts); conditionals are better *)
2007
2007
inline_lazy_force_cond arg pos loc
2008
2008
2009
- let get_expr_args_lazy ~scopes head (arg , _mut ) rem =
2009
+ let get_expr_args_lazy ~scopes head (arg , _mut , _layout ) rem =
2010
2010
let loc = head_loc ~scopes head in
2011
- (inline_lazy_force arg Rc_normal loc, Strict ) :: rem
2011
+ (inline_lazy_force arg Rc_normal loc, Strict , layout_lazy_contents ) :: rem
2012
2012
2013
2013
let divide_lazy ~scopes head ctx pm =
2014
2014
divide_line (Context. specialize head)
@@ -2024,14 +2024,14 @@ let get_pat_args_tuple arity p rem =
2024
2024
| { pat_desc = Tpat_tuple args } -> args @ rem
2025
2025
| _ -> assert false
2026
2026
2027
- let get_expr_args_tuple ~scopes head (arg , _mut ) rem =
2027
+ let get_expr_args_tuple ~scopes head (arg , _mut , _layout ) rem =
2028
2028
let loc = head_loc ~scopes head in
2029
2029
let arity = Patterns.Head. arity head in
2030
2030
let rec make_args pos =
2031
2031
if pos > = arity then
2032
2032
rem
2033
2033
else
2034
- (Lprim (Pfield (pos, Reads_agree ), [ arg ], loc), Alias )
2034
+ (Lprim (Pfield (pos, Reads_agree ), [ arg ], loc), Alias , layout_field )
2035
2035
:: make_args (pos + 1 )
2036
2036
in
2037
2037
make_args 0
@@ -2057,7 +2057,7 @@ let get_pat_args_record num_fields p rem =
2057
2057
record_matching_line num_fields lbl_pat_list @ rem
2058
2058
| _ -> assert false
2059
2059
2060
- let get_expr_args_record ~scopes head (arg , _mut ) rem =
2060
+ let get_expr_args_record ~scopes head (arg , _mut , layout ) rem =
2061
2061
let loc = head_loc ~scopes head in
2062
2062
let all_labels =
2063
2063
let open Patterns.Head in
@@ -2077,24 +2077,25 @@ let get_expr_args_record ~scopes head (arg, _mut) rem =
2077
2077
| Immutable -> Reads_agree
2078
2078
| Mutable -> Reads_vary
2079
2079
in
2080
- let access =
2080
+ let access, layout =
2081
2081
match lbl.lbl_repres with
2082
2082
| Record_regular
2083
2083
| Record_inlined _ ->
2084
- Lprim (Pfield (lbl.lbl_pos, sem), [ arg ], loc)
2085
- | Record_unboxed _ -> arg
2084
+ Lprim (Pfield (lbl.lbl_pos, sem), [ arg ], loc), layout_field
2085
+ | Record_unboxed _ -> arg, layout
2086
2086
| Record_float ->
2087
2087
(* TODO: could optimise to Alloc_local sometimes *)
2088
- Lprim (Pfloatfield (lbl.lbl_pos, sem, alloc_heap), [ arg ], loc)
2088
+ Lprim (Pfloatfield (lbl.lbl_pos, sem, alloc_heap), [ arg ], loc),
2089
+ layout_float
2089
2090
| Record_extension _ ->
2090
- Lprim (Pfield (lbl.lbl_pos + 1 , sem), [ arg ], loc)
2091
+ Lprim (Pfield (lbl.lbl_pos + 1 , sem), [ arg ], loc), layout_field
2091
2092
in
2092
2093
let str =
2093
2094
match lbl.lbl_mut with
2094
2095
| Immutable -> Alias
2095
2096
| Mutable -> StrictOpt
2096
2097
in
2097
- (access, str) :: make_args (pos + 1 )
2098
+ (access, str, layout ) :: make_args (pos + 1 )
2098
2099
in
2099
2100
make_args 0
2100
2101
@@ -2121,7 +2122,7 @@ let get_pat_args_array p rem =
2121
2122
| { pat_desc = Tpat_array (_ , patl ) } -> patl @ rem
2122
2123
| _ -> assert false
2123
2124
2124
- let get_expr_args_array ~scopes kind head (arg , _mut ) rem =
2125
+ let get_expr_args_array ~scopes kind head (arg , _mut , _layout ) rem =
2125
2126
let am, len =
2126
2127
let open Patterns.Head in
2127
2128
match head.pat_desc with
@@ -2133,11 +2134,13 @@ let get_expr_args_array ~scopes kind head (arg, _mut) rem =
2133
2134
if pos > = len then
2134
2135
rem
2135
2136
else
2137
+ (* CR ncourant: could do better than layout_field using kind *)
2136
2138
( Lprim
2137
2139
(Parrayrefu kind, [ arg; Lconst (Const_base (Const_int pos)) ], loc),
2138
- match am with
2140
+ ( match am with
2139
2141
| Mutable -> StrictOpt
2140
- | Immutable -> Alias )
2142
+ | Immutable -> Alias ),
2143
+ layout_field)
2141
2144
:: make_args (pos + 1 )
2142
2145
in
2143
2146
make_args 0
@@ -3276,25 +3279,25 @@ and compile_match_nonempty ~scopes value_kind repr partial ctx
3276
3279
(m : Typedtree.pattern Non_empty_row.t clause pattern_matching )=
3277
3280
match m with
3278
3281
| { cases = [] ; args = [] } -> comp_exit ctx m
3279
- | { args = (arg , str ) :: argl } ->
3282
+ | { args = (arg , str , layout ) :: argl } ->
3280
3283
let v, newarg = arg_to_var arg m.cases in
3281
- let args = (newarg, Alias ) :: argl in
3284
+ let args = (newarg, Alias , layout ) :: argl in
3282
3285
let cases = List. map (half_simplify_nonempty ~arg: newarg) m.cases in
3283
3286
let m = { m with args; cases } in
3284
3287
let first_match, rem =
3285
3288
split_and_precompile_half_simplified ~arg: newarg m in
3286
- combine_handlers ~scopes value_kind repr partial ctx (v, str, Lambda. layout_top , arg) first_match rem
3289
+ combine_handlers ~scopes value_kind repr partial ctx (v, str, layout , arg) first_match rem
3287
3290
| _ -> assert false
3288
3291
3289
3292
and compile_match_simplified ~scopes value_kind repr partial ctx
3290
3293
(m : Simple.clause pattern_matching ) =
3291
3294
match m with
3292
3295
| { cases = [] ; args = [] } -> comp_exit ctx m
3293
- | { args = ((Lvar v as arg ), str ) :: argl } ->
3294
- let args = (arg, Alias ) :: argl in
3296
+ | { args = ((Lvar v as arg ), str , layout ) :: argl } ->
3297
+ let args = (arg, Alias , layout ) :: argl in
3295
3298
let m = { m with args } in
3296
3299
let first_match, rem = split_and_precompile_simplified m in
3297
- combine_handlers value_kind ~scopes repr partial ctx (v, str, Lambda. layout_top , arg)
3300
+ combine_handlers value_kind ~scopes repr partial ctx (v, str, layout , arg)
3298
3301
first_match rem
3299
3302
| _ -> assert false
3300
3303
@@ -3332,7 +3335,7 @@ and do_compile_matching ~scopes value_kind repr partial ctx pmh =
3332
3335
| Pm pm -> (
3333
3336
let arg =
3334
3337
match pm.args with
3335
- | (first_arg , _ ) :: _ -> first_arg
3338
+ | (first_arg , _ , _ ) :: _ -> first_arg
3336
3339
| _ ->
3337
3340
(* We arrive in do_compile_matching from:
3338
3341
- compile_matching
@@ -3556,9 +3559,9 @@ let toplevel_handler ~scopes value_kind loc ~failer partial args cases compile_f
3556
3559
check_total ~scopes value_kind loc ~failer total lam raise_num
3557
3560
end
3558
3561
3559
- let compile_matching ~scopes value_kind loc ~failer repr arg pat_act_list partial =
3562
+ let compile_matching ~scopes value_kind loc ~failer repr ( arg , arg_layout ) pat_act_list partial =
3560
3563
let partial = check_partial pat_act_list partial in
3561
- let args = [ (arg, Strict ) ] in
3564
+ let args = [ (arg, Strict , arg_layout ) ] in
3562
3565
let rows = map_on_rows (fun pat -> (pat, [] )) pat_act_list in
3563
3566
toplevel_handler ~scopes value_kind loc ~failer partial args rows (fun partial pm ->
3564
3567
compile_match_nonempty ~scopes value_kind repr partial (Context. start 1 ) pm)
@@ -3577,11 +3580,11 @@ let for_trywith ~scopes value_kind loc param pat_act_list =
3577
3580
the reraise (hence the [_noloc]) to avoid seeing this
3578
3581
silent reraise in exception backtraces. *)
3579
3582
compile_matching ~scopes value_kind loc ~failer: (Reraise_noloc param)
3580
- None param pat_act_list Partial
3583
+ None ( param, layout_block) pat_act_list Partial
3581
3584
3582
3585
let simple_for_let ~scopes value_kind loc param pat body =
3583
3586
compile_matching ~scopes value_kind loc ~failer: Raise_match_failure
3584
- None param [ (pat, body) ] Partial
3587
+ None ( param, Typeopt. layout pat.pat_env pat.pat_type) [ (pat, body) ] Partial
3585
3588
3586
3589
(* Optimize binding of immediate tuples
3587
3590
@@ -3748,7 +3751,8 @@ let for_let ~scopes loc param pat body_kind body =
3748
3751
(* Easy case since variables are available *)
3749
3752
let for_tupled_function ~scopes loc kind paraml pats_act_list partial =
3750
3753
let partial = check_partial_list pats_act_list partial in
3751
- let args = List. map (fun id -> (Lvar id, Strict )) paraml in
3754
+ (* The arguments of a tupled function are always values since they must be fields *)
3755
+ let args = List. map (fun id -> (Lvar id, Strict , layout_field)) paraml in
3752
3756
let handler =
3753
3757
toplevel_handler ~scopes kind loc ~failer: Raise_match_failure
3754
3758
partial args pats_act_list in
@@ -3839,23 +3843,25 @@ let do_for_multiple_match ~scopes value_kind loc paraml mode pat_act_list partia
3839
3843
let repr = None in
3840
3844
let arg =
3841
3845
let sloc = Scoped_location. of_location ~scopes loc in
3842
- Lprim (Pmakeblock (0 , Immutable , None , mode), paraml, sloc) in
3846
+ (* CR ncourant: this can build a mixed block, but it should never actually be
3847
+ created except if the pattern-matching binds it, in which case it should be
3848
+ rejected by the typing. Do we really trust this case will not happen? *)
3849
+ Lprim (Pmakeblock (0 , Immutable , None , mode), List. map fst paraml, sloc) in
3843
3850
let handler =
3844
3851
let partial = check_partial pat_act_list partial in
3845
3852
let rows = map_on_rows (fun p -> (p, [] )) pat_act_list in
3846
3853
toplevel_handler ~scopes value_kind loc ~failer: Raise_match_failure
3847
- partial [ (arg, Strict ) ] rows in
3854
+ partial [ (arg, Strict , layout_block ) ] rows in
3848
3855
handler (fun partial pm1 ->
3849
3856
let pm1_half =
3850
3857
{ pm1 with cases = List. map (half_simplify_nonempty ~arg ) pm1.cases }
3851
3858
in
3852
3859
let next, nexts = split_and_precompile_half_simplified ~arg pm1_half in
3853
3860
let size = List. length paraml
3854
- and idl = List. map (function
3855
- | Lvar id -> id
3856
- | _ -> Ident. create_local " *match*" ) paraml in
3857
- let idl_with_layouts = List. map (fun id -> (id, Lambda. layout_top)) idl in
3858
- let args = List. map (fun id -> (Lvar id, Alias )) idl in
3861
+ and idl_with_layouts = List. map (function
3862
+ | Lvar id , layout -> id, layout
3863
+ | _ , layout -> Ident. create_local " *match*" , layout) paraml in
3864
+ let args = List. map (fun (id , layout ) -> (Lvar id, Alias , layout)) idl_with_layouts in
3859
3865
let flat_next = flatten_precompiled size args next
3860
3866
and flat_nexts =
3861
3867
List. map (fun (e , pm ) -> (e, flatten_precompiled size args pm)) nexts
@@ -3864,24 +3870,24 @@ let do_for_multiple_match ~scopes value_kind loc paraml mode pat_act_list partia
3864
3870
comp_match_handlers value_kind (compile_flattened ~scopes value_kind repr) partial
3865
3871
(Context. start size) flat_next flat_nexts
3866
3872
in
3867
- List. fold_right2 (bind_with_layout Strict ) idl_with_layouts paraml lam, total
3873
+ List. fold_right2 (bind_with_layout Strict ) idl_with_layouts ( List. map fst paraml) lam, total
3868
3874
)
3869
3875
3870
3876
(* PR#4828: Believe it or not, the 'paraml' argument below
3871
3877
may not be side effect free. *)
3872
3878
3873
- let param_to_var param =
3879
+ let param_to_var ( param , layout ) =
3874
3880
match param with
3875
- | Lvar v -> (v, None )
3876
- | _ -> (Ident. create_local " *match*" , Some param)
3881
+ | Lvar v -> (v, layout, None )
3882
+ | _ -> (Ident. create_local " *match*" , layout, Some param)
3877
3883
3878
- let bind_opt (v , eo ) k =
3884
+ let bind_opt (v , layout , eo ) k =
3879
3885
match eo with
3880
3886
| None -> k
3881
- | Some e -> Lambda. bind_with_layout Strict (v, Lambda. layout_top ) e k
3887
+ | Some e -> Lambda. bind_with_layout Strict (v, layout ) e k
3882
3888
3883
3889
let for_multiple_match ~scopes value_kind loc paraml mode pat_act_list partial =
3884
3890
let v_paraml = List. map param_to_var paraml in
3885
- let paraml = List. map (fun (v , _ ) -> Lvar v) v_paraml in
3891
+ let paraml = List. map (fun (v , layout , _ ) -> ( Lvar v, layout) ) v_paraml in
3886
3892
List. fold_right bind_opt v_paraml
3887
3893
(do_for_multiple_match ~scopes value_kind loc paraml mode pat_act_list partial)
0 commit comments