Skip to content

Commit d04eb58

Browse files
authored
Cleanup of comprehensions and immutable arrays (#127)
* Delete some CRs * [minor] Comment typo * Update `Iarray` to remove `Obj.magic` * Comment update * Mark places attributes are correctly unused * Remove a couple more CRs * Add immutable array copyright headers * Declare comprehensions and immutable arrays no longer experimental * Add new `array_{to,of}_iarray` primitives and prepare to use them * `make alldepend` * Bootstrap * Use new `%array_{to,of}_iarray` primitives
1 parent a45df79 commit d04eb58

Some content is hidden

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

52 files changed

+530
-262
lines changed

.depend

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,6 @@ parsing/extensions.cmx : \
439439
parsing/extensions.cmi : \
440440
parsing/parsetree.cmi \
441441
parsing/location.cmi \
442-
parsing/extensions_parsing.cmi \
443442
parsing/asttypes.cmi
444443
parsing/extensions_parsing.cmo : \
445444
parsing/parsetree.cmi \
@@ -1009,6 +1008,7 @@ typing/mtype.cmx : \
10091008
typing/mtype.cmi
10101009
typing/mtype.cmi : \
10111010
typing/types.cmi \
1011+
typing/subst.cmi \
10121012
typing/path.cmi \
10131013
typing/ident.cmi \
10141014
typing/env.cmi
@@ -1804,6 +1804,7 @@ typing/typemod.cmo : \
18041804
typing/includemod.cmi \
18051805
utils/import_info.cmi \
18061806
typing/ident.cmi \
1807+
parsing/extensions.cmi \
18071808
typing/envaux.cmi \
18081809
typing/env.cmi \
18091810
typing/ctype.cmi \
@@ -1842,6 +1843,7 @@ typing/typemod.cmx : \
18421843
typing/includemod.cmx \
18431844
utils/import_info.cmx \
18441845
typing/ident.cmx \
1846+
parsing/extensions.cmx \
18451847
typing/envaux.cmx \
18461848
typing/env.cmx \
18471849
typing/ctype.cmx \
@@ -1873,6 +1875,7 @@ typing/typemod.cmi : \
18731875
typing/typeopt.cmo : \
18741876
typing/types.cmi \
18751877
typing/typedtree.cmi \
1878+
typing/type_immediacy.cmi \
18761879
typing/predef.cmi \
18771880
typing/path.cmi \
18781881
utils/numbers.cmi \
@@ -1882,11 +1885,13 @@ typing/typeopt.cmo : \
18821885
typing/env.cmi \
18831886
typing/ctype.cmi \
18841887
utils/config.cmi \
1888+
utils/clflags.cmi \
18851889
parsing/asttypes.cmi \
18861890
typing/typeopt.cmi
18871891
typing/typeopt.cmx : \
18881892
typing/types.cmx \
18891893
typing/typedtree.cmx \
1894+
typing/type_immediacy.cmx \
18901895
typing/predef.cmx \
18911896
typing/path.cmx \
18921897
utils/numbers.cmx \
@@ -1896,6 +1901,7 @@ typing/typeopt.cmx : \
18961901
typing/env.cmx \
18971902
typing/ctype.cmx \
18981903
utils/config.cmx \
1904+
utils/clflags.cmx \
18991905
parsing/asttypes.cmi \
19001906
typing/typeopt.cmi
19011907
typing/typeopt.cmi : \

boot/ocamlc

1.75 KB
Binary file not shown.

boot/ocamllex

10 Bytes
Binary file not shown.

bytecomp/bytegen.ml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ let preserve_tailcall_for_prim = function
112112
Popaque | Psequor | Psequand
113113
| Pobj_magic ->
114114
true
115-
| Pbytes_to_string | Pbytes_of_string | Pignore
115+
| Pbytes_to_string | Pbytes_of_string
116+
| Parray_to_iarray | Parray_of_iarray
117+
| Pignore
116118
| Pgetglobal _ | Psetglobal _ | Pgetpredef _
117119
| Pmakeblock _ | Pmakefloatblock _
118120
| Pfield _ | Pfield_computed _ | Psetfield _
@@ -518,6 +520,8 @@ let comp_primitive p args =
518520
| Pint_as_pointer -> Kccall("caml_int_as_pointer", 1)
519521
| Pbytes_to_string -> Kccall("caml_string_of_bytes", 1)
520522
| Pbytes_of_string -> Kccall("caml_bytes_of_string", 1)
523+
| Parray_to_iarray -> Kccall("caml_iarray_of_array", 1)
524+
| Parray_of_iarray -> Kccall("caml_array_of_iarray", 1)
521525
| Pobj_dup -> Kccall("caml_obj_dup", 1)
522526
(* The cases below are handled in [comp_expr] before the [comp_primitive] call
523527
(in the order in which they appear below),

lambda/lambda.ml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ type primitive =
239239
(* Primitives for [Obj] *)
240240
| Pobj_dup
241241
| Pobj_magic
242+
(* Jane Street extensions *)
243+
| Parray_to_iarray
244+
| Parray_of_iarray
242245

243246
and integer_comparison =
244247
Ceq | Cne | Clt | Cgt | Cle | Cge
@@ -1274,7 +1277,9 @@ let mod_setfield pos =
12741277
Psetfield (pos, Pointer, Root_initialization)
12751278

12761279
let primitive_may_allocate : primitive -> alloc_mode option = function
1277-
| Pbytes_to_string | Pbytes_of_string | Pignore -> None
1280+
| Pbytes_to_string | Pbytes_of_string
1281+
| Parray_to_iarray | Parray_of_iarray
1282+
| Pignore -> None
12781283
| Pgetglobal _ | Psetglobal _ | Pgetpredef _ -> None
12791284
| Pmakeblock (_, _, _, m) -> Some m
12801285
| Pmakefloatblock (_, m) -> Some m

lambda/lambda.mli

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ type primitive =
190190
(* Primitives for [Obj] *)
191191
| Pobj_dup
192192
| Pobj_magic
193+
(* Jane Street extensions *)
194+
| Parray_to_iarray (* Unsafely reinterpret a mutable array as an immutable
195+
one; O(1) *)
196+
| Parray_of_iarray (* Unsafely reinterpret an immutable array as a mutable
197+
one; O(1) *)
193198

194199
and integer_comparison =
195200
Ceq | Cne | Clt | Cgt | Cle | Cge

lambda/printlambda.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,9 @@ let primitive ppf = function
442442
| Pobj_dup -> fprintf ppf "obj_dup"
443443
| Pobj_magic -> fprintf ppf "obj_magic"
444444

445+
| Parray_to_iarray -> fprintf ppf "array_to_iarray"
446+
| Parray_of_iarray -> fprintf ppf "array_of_iarray"
447+
445448
let name_of_primitive = function
446449
| Pbytes_of_string -> "Pbytes_of_string"
447450
| Pbytes_to_string -> "Pbytes_to_string"
@@ -549,6 +552,8 @@ let name_of_primitive = function
549552
| Pprobe_is_enabled _ -> "Pprobe_is_enabled"
550553
| Pobj_dup -> "Pobj_dup"
551554
| Pobj_magic -> "Pobj_magic"
555+
| Parray_of_iarray -> "Parray_of_iarray"
556+
| Parray_to_iarray -> "Parray_to_iarray"
552557

553558
let check_attribute ppf check =
554559
let check_property = function

lambda/simplif.ml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,10 @@ let rec emit_tail_infos is_tail lambda =
676676
| Lletrec (bindings, body) ->
677677
List.iter (fun (_, lam) -> emit_tail_infos false lam) bindings;
678678
emit_tail_infos is_tail body
679-
| Lprim ((Pbytes_to_string | Pbytes_of_string), [arg], _) ->
679+
| Lprim ((Pbytes_to_string | Pbytes_of_string |
680+
Parray_to_iarray | Parray_of_iarray),
681+
[arg],
682+
_) ->
680683
emit_tail_infos is_tail arg
681684
| Lprim (Psequand, [arg1; arg2], _)
682685
| Lprim (Psequor, [arg1; arg2], _) ->

lambda/tmc.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,7 @@ let rec choice ctx t =
858858

859859
(* in common cases we just return *)
860860
| Pbytes_to_string | Pbytes_of_string
861+
| Parray_to_iarray | Parray_of_iarray
861862
| Pgetglobal _ | Psetglobal _ | Pgetpredef _
862863
| Pfield _ | Pfield_computed _
863864
| Psetfield _ | Psetfield_computed _

lambda/transl_array_comprehension.ml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ module Precompute_array_size : sig
203203
val safe_product_pos :
204204
?variable_name:string -> loc:scoped_location -> lambda list -> lambda
205205
end = struct
206+
(* Modeled after [Translcore.assert_failed] *)
206207
let raise_overflow_exn ~loc =
207208
let loc' = Debuginfo.Scoped_location.to_location loc in
208209
let slot =
@@ -211,8 +212,11 @@ end = struct
211212
Env.initial_safe_string
212213
Predef.path_invalid_argument
213214
in
214-
(* CR aspectorzabusky: Should I call [Translprim.event_after] here?
215-
[Translcore.asssert_failed] does (via a local intermediary). *)
215+
(* CR-someday aspectorzabusky: We might want to raise an event here for
216+
debug tracing (cf. [Translcore.assert_failed] and
217+
[Translprim.event_after]), but it's not clear what event that would be,
218+
and this isn't a feature we expect to use. We can add it when it seems
219+
important, or when we upstream this change. *)
216220
Lprim(Praise Raise_regular,
217221
[Lprim(Pmakeblock(0, Immutable, None, alloc_heap),
218222
[ slot
@@ -509,7 +513,8 @@ let binding
509513
~scopes
510514
~loc
511515
{ comp_cb_iterator; comp_cb_attributes = _ } =
512-
(* CR aspectorzabusky: What do we do with attributes here? *)
516+
(* No attributes are meaningful here; see the definition of
517+
[comp_cb_attributes]. *)
513518
iterator ~transl_exp ~loc ~scopes comp_cb_iterator
514519

515520
(** Translate the contents of a single [for ... and ...] clause (the contents of
@@ -748,8 +753,6 @@ let body
748753
let set_element_raw elt =
749754
(* array.(index) <- elt *)
750755
Lprim(Parraysetu array_kind, [array.var; index.var; elt], loc)
751-
(* CR aspectorzabusky: Is [array_kind] safe here, since it could be
752-
[Pgenarray]? Do we have to learn which it should be? *)
753756
in
754757
let set_element_in_bounds elt = match array_sizing with
755758
| Fixed_size ->
@@ -835,18 +838,15 @@ let comprehension
835838
(Iterator_bindings.all_let_bindings var_bindings)
836839
(Lifthenelse(Iterator_bindings.Fixed_size_array.are_any_empty
837840
~loc var_bindings,
838-
(* If the array is known to be empty, we short-circuit and return
839-
the empty array *)
841+
(* If the array is known to be empty, we short-circuit and return the
842+
empty array; all empty arrays are identical, so we don't care
843+
about its kind or mutability *)
840844
Lprim(
841845
Pmakearray(Pgenarray, Immutable, Lambda.alloc_heap),
842846
[],
843847
loc),
844848
(* Otherwise, we translate it normally *)
845849
comprehension,
846-
(* CR aspectorzabusky: My understanding is that all empty arrays
847-
are identical, no matter their [array_kind], and that's why I
848-
can use [Pgenarray] to create the empty array above but still
849-
use [array_kind] here. Is that right? *)
850850
(* (And the result has the [value_kind] of the array) *)
851851
(Pvalue (Parrayval array_kind))))
852852
| Dynamic_size_info ->

lambda/transl_array_comprehension.mli

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ open Debuginfo.Scoped_location
44

55
(** Translate array comprehensions; see the .ml file for more details *)
66

7-
(* CR aspectorzabusky: Is it really true that I don't need to pass in array
8-
mutability information here? (Last sentence of the first paragraph.) *)
97
(** Translate an array comprehension ([Typedtree.comprehension], when it's the
108
body of a [Typedtree.Texp_array_comprehension]) into Lambda. This generates
119
more efficient code in the case where the array has a known fixed size, by
@@ -14,7 +12,7 @@ open Debuginfo.Scoped_location
1412
of the resulting array must be provided. We do not need to pass in whether
1513
the resulting array should be mutable or immutable; both sorts of arrays
1614
will be constructed mutably, and the type checker has already enforced that
17-
only mutable arrays are used mutably.
15+
only mutable arrays are actually used mutably.
1816
1917
The only variables this term refers to are those that come from the array
2018
comprehension itself; some C primitives are referenced, but no standard

lambda/transl_comprehension_utils.ml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,6 @@ module Lambda_utils = struct
132132
let prim = c_prim name 3 in
133133
fun ~loc x y z -> Lprim(prim, [x; y; z], loc)
134134

135-
(* CR aspectorzabusky: These primitives are now created unconditionally on
136-
compiler startup. Is that okay? *)
137-
138135
let make_vect =
139136
let make_vect = binary "caml_make_vect" in
140137
fun ~loc ~length ~init -> make_vect ~loc length init

lambda/transl_list_comprehension.ml

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,19 @@ open Lambda_utils.Constants
8484
Nil)
8585
]}
8686
87-
See [CamlinternalComprehension] the types and functions we desugar to, along
88-
with some more documentation. *)
87+
See [CamlinternalComprehension] for the types and functions we desugar to,
88+
along with some more documentation. *)
8989

9090
(** An implementation note: Many of the functions in this file need to translate
9191
expressions from Typedtree to Lambda; to avoid strange dependency ordering,
9292
we parameterize those functions by [Translcore.transl_exp], and pass it in
9393
as a labeled argument, along with the necessary [scopes] labeled argument
9494
that it requires. *)
9595

96-
(* CR aspectorzabusky: I couldn't get this to build if these were run as soon as
97-
this file was processed *)
9896
(** The functions that are required to build the results of list comprehensions;
99-
see the documentation for [CamlinternalComprehension] for more details. *)
97+
see the documentation for [CamlinternalComprehension] for more details.
98+
Because these are being looked up in the environment, we need to wait to
99+
create them until that exists, hence [lazy]. *)
100100
let ( rev_list_to_list
101101
, rev_dlist_concat_map
102102
, rev_dlist_concat_iterate_up
@@ -136,7 +136,9 @@ type translated_iterator =
136136
]}
137137
Once the "iterator arguments", which vary depending on the iterator, are
138138
applied to this function (see [arg_lets]), then it is simply waiting for
139-
the body of the iterator (the final function argument). *)
139+
the body of the iterator (the final function argument). Lazy because it
140+
holds a reference to a primitive, which has to be constructed lazily (see
141+
above). *)
140142
; arg_lets : Let_binding.t list
141143
(** The first-class let bindings that bind the arguments to the [builder]
142144
function that actually does the iteration. These let bindings need to be
@@ -194,8 +196,6 @@ let iterator ~transl_exp ~scopes = function
194196
; element
195197
; element_kind = Typeopt.layout pattern.pat_env pattern.pat_type
196198
; add_bindings =
197-
(* CR aspectorzabusky: This has to be at [value_kind] [Pgenval],
198-
right, since we don't know more specifically? *)
199199
Matching.for_let
200200
~scopes pattern.pat_loc (Lvar element) pattern (Pvalue Pgenval)
201201
}
@@ -208,7 +208,8 @@ let iterator ~transl_exp ~scopes = function
208208
so bindings are just like iterators with a possible annotation. As a
209209
result, this function is essentially the same as [iterator], which see. *)
210210
let binding ~transl_exp ~scopes { comp_cb_iterator; comp_cb_attributes = _ } =
211-
(* CR aspectorzabusky: What do we do with attributes here? *)
211+
(* No attributes are meaningful here; see the definition of
212+
[comp_cb_attributes]. *)
212213
iterator ~transl_exp ~scopes comp_cb_iterator
213214

214215
(** Translate all the bindings of a single [for ... and ...] clause (the

lambda/translcore.ml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,8 +562,6 @@ and transl_exp0 ~in_new_scope ~scopes e =
562562
if Config.flambda2 then
563563
imm_array
564564
else
565-
(* CR aspectorzabusky: Do we construct things correctly in this
566-
case? *)
567565
match kind with
568566
| Paddrarray | Pintarray ->
569567
Lconst(Const_block(0, cl))

lambda/translprim.ml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,8 @@ let lookup_primitive loc poly pos p =
399399
| "%compare" -> Comparison(Compare, Compare_generic)
400400
| "%obj_dup" -> Primitive(Pobj_dup, 1)
401401
| "%obj_magic" -> Primitive(Pobj_magic, 1)
402+
| "%array_to_iarray" -> Primitive (Parray_to_iarray, 1)
403+
| "%array_of_iarray" -> Primitive (Parray_of_iarray, 1)
402404
| s when String.length s > 0 && s.[0] = '%' ->
403405
raise(Error(loc, Unknown_builtin_primitive s))
404406
| _ -> External p
@@ -869,7 +871,9 @@ let lambda_primitive_needs_event_after = function
869871
| Pbigstring_set_16 _ | Pbigstring_set_32 _ | Pbigstring_set_64 _
870872
| Pbbswap _ | Pobj_dup -> true
871873

872-
| Pbytes_to_string | Pbytes_of_string | Pignore | Psetglobal _
874+
| Pbytes_to_string | Pbytes_of_string
875+
| Parray_to_iarray | Parray_of_iarray
876+
| Pignore | Psetglobal _
873877
| Pgetglobal _ | Pgetpredef _ | Pmakeblock _ | Pmakefloatblock _
874878
| Pfield _ | Pfield_computed _ | Psetfield _
875879
| Psetfield_computed _ | Pfloatfield _ | Psetfloatfield _ | Praise _

middle_end/closure/closure.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1321,7 +1321,9 @@ let rec close ({ backend; fenv; cenv ; mutable_vars; kinds; catch_env } as env)
13211321
| Lprim(Pignore, [arg], _loc) ->
13221322
let expr, approx = make_const_int 0 in
13231323
Usequence(fst (close env arg), expr), approx
1324-
| Lprim((Pbytes_to_string | Pbytes_of_string | Pobj_magic),
1324+
| Lprim((Pbytes_to_string | Pbytes_of_string |
1325+
Parray_to_iarray | Parray_of_iarray |
1326+
Pobj_magic),
13251327
[arg], _loc) ->
13261328
close env arg
13271329
| Lprim(Pgetglobal cu, [], loc) ->

middle_end/convert_primitives.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ let convert (prim : Lambda.primitive) : Clambda_primitives.primitive =
162162
| Pgetglobal _
163163
| Psetglobal _
164164
| Pgetpredef _
165+
| Parray_to_iarray
166+
| Parray_of_iarray
165167
->
166168
Misc.fatal_errorf "lambda primitive %a can't be converted to \
167169
clambda primitive"

middle_end/flambda/closure_conversion.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,9 @@ let rec close t env (lam : Lambda.lambda) : Flambda.t =
419419
(If_then_else (cond, arg2, Var const_false, Lambda.layout_int)))
420420
| Lprim ((Psequand | Psequor), _, _) ->
421421
Misc.fatal_error "Psequand / Psequor must have exactly two arguments"
422-
| Lprim ((Pbytes_to_string | Pbytes_of_string | Pobj_magic),
422+
| Lprim ((Pbytes_to_string | Pbytes_of_string |
423+
Parray_to_iarray | Parray_of_iarray |
424+
Pobj_magic),
423425
[arg], _) ->
424426
close t env arg
425427
| Lprim (Pignore, [arg], _) ->

middle_end/internal_variable_names.ml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ let psubint = "Psubint"
174174
let pxorbint = "Pxorbint"
175175
let pxorint = "Pxorint"
176176
let pprobe_is_enabled = "Pprobe_is_enabled"
177+
let parray_of_iarray = "Parray_of_iarray"
178+
let parray_to_iarray = "Parray_to_iarray"
177179
let pabsfloat_arg = "Pabsfloat_arg"
178180
let paddbint_arg = "Paddbint_arg"
179181
let paddfloat_arg = "Paddfloat_arg"
@@ -281,6 +283,8 @@ let psubint_arg = "Psubint_arg"
281283
let pxorbint_arg = "Pxorbint_arg"
282284
let pxorint_arg = "Pxorint_arg"
283285
let pprobe_is_enabled_arg = "Pprobe_is_enabled_arg"
286+
let parray_of_iarray_arg = "Parray_of_iarray_arg"
287+
let parray_to_iarray_arg = "Parray_to_iarray_arg"
284288
let raise = "raise"
285289
let raise_arg = "raise_arg"
286290
let read_mutable = "read_mutable"
@@ -421,6 +425,8 @@ let of_primitive : Lambda.primitive -> string = function
421425
| Pprobe_is_enabled _ -> pprobe_is_enabled
422426
| Pobj_dup -> pobj_dup
423427
| Pobj_magic -> pobj_magic
428+
| Parray_of_iarray -> parray_of_iarray
429+
| Parray_to_iarray -> parray_to_iarray
424430

425431
let of_primitive_arg : Lambda.primitive -> string = function
426432
| Pbytes_of_string -> pbytes_of_string_arg
@@ -529,3 +535,5 @@ let of_primitive_arg : Lambda.primitive -> string = function
529535
| Pprobe_is_enabled _ -> pprobe_is_enabled_arg
530536
| Pobj_dup -> pobj_dup_arg
531537
| Pobj_magic -> pobj_magic_arg
538+
| Parray_of_iarray -> parray_of_iarray_arg
539+
| Parray_to_iarray -> parray_to_iarray_arg

0 commit comments

Comments
 (0)