jon.recoil.org

Module CamlinternalComprehensionSource

Supporting functions for list comprehensions

Sourcetype 'a rev_list =
  1. | Nil
  2. | Snoc of {
    1. init : 'a rev_list;
    2. last : 'a @@ global;
    }

Backwards snoc lists that can be spine-local but element-global. This allows list comprehensions to build their intermediate data structure on the stack instead of the heap; since list comprehensions build their intermediate lists backwards, we store these as snoc lists instead of cons lists.

Sourcetype 'a rev_dlist = 'a rev_list @ local -> 'a rev_list @ local

List comprehensions are conceptually desugared in terms of difference lists, functions from 'a list -> 'a list, which have been built in reverse; we use rev_list instead of list to keep track of the reversedness and get stack allocation. All rev_dlist values should be local_, as they're all intermediate data structures and can also be stack allocated.

Sourceval rev_list_to_list : 'a rev_list @ local -> 'a list @@ portable

Reverse a local_ snoc list to get a global regular list. To turn a local reversed difference list into a (global, normal, forwards) list, first provide it the empty snoc list (Nil) and then use this function to get the final result.

Sourceval rev_dlist_concat_map : 'a list -> ('a -> 'b rev_dlist @ local) @ local -> 'b rev_dlist @ local @@ portable

rev_dlist_concat_map is concat_map with its arguments swapped for reversed difference lists.

Sourceval rev_dlist_concat_iterate_up : int -> int -> (int -> 'a rev_dlist @ local) @ local -> 'a rev_dlist @ local @@ portable

rev_dlist_concat_iterate_up low high f is the same as rev_dlist_concat_map range f where range is the increasing range from low to high, inclusive.

Sourceval rev_dlist_concat_iterate_down : int -> int -> (int -> 'a rev_dlist @ local) @ local -> 'a rev_dlist @ local @@ portable

rev_dlist_concat_iterate_up high low f is the same as rev_dlist_concat_map range f where range is the decreasing range from high to low, inclusive.

List comprehensions always produce global values right now, but it would be great if they could produce local values, too. (Then they'd be able to/have to iterate over local lists.) That requires either some form of mode polymorphism or code duplication, so it isn't present yet.