package travesty

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Module Traversable.HelpersSource

Utility functions for building traversals.

Parameters

module M : Base.Monad.S

Signature

Sourcetype 'a traversal = 'a -> 'a M.t

traversal is shorthand for a traversal function over M.

Variants

Functions beginning proc_variant are useful for building traversable containers on top of Variantslib's map function.

Here's an example where we define a generic traversal function over a variant type using proc_variant1 and proc_variant3, then use it to build a traversable container instance for inspecting and modifying a specific type of data regardless of variant.

  (* This type describes x86 operands: *)
  type t =
    | Location of Location.t
    | Immediate of Disp.t
    | String of string
    | Typ of string
    | Bop of t * operator * t [@@deriving variants]

  (* We use the helpers to build an intermediate mapper... *)
  module Base_map (M : Monad.S) = struct
    module F = Travesty.Traversable.Helpers (M)

    let rec map_m (x : t) ~location ~immediate ~string ~typ ~bop
      : t M.t =
      Variants.map x
        ~location:(F.proc_variant1 location)
        ~immediate:(F.proc_variant1 immediate)
        ~string:(F.proc_variant1 string)
        ~typ:(F.proc_variant1 typ)
        (* Note that this recursively folds down the operands,
           and that the [bop] function only receives the operator. *)
        ~bop:(F.proc_variant3 (fun (l, b, r) ->
            let open M.Let_syntax in
            let%bind l' = map_m ~location ~immediate ~string ~typ ~bop l in
            let%bind b' = bop b in
            let%map  r' = map_m ~location ~immediate ~string ~typ ~bop r in
            (l', b', r')))
    ;;
  end

  (* ...then use it to build a traversable container over all of
     the symbols in an operand. *)
  module On_symbols
    : Travesty.Traversable.S0_container with type t := t
                                         and type elt := string =
    Travesty.Traversable.Make_container0 (struct
      type nonrec t = t
      module Elt = String

      module On_monad (M : Monad.S) = struct
        module B = Base_map (M)
        (* Recursively using other traversables: *)
        module L = Location.On_symbols.On_monad (M)
        module D = Disp.On_symbols.On_monad (M)

        let map_m t ~f =
          B.map_m t
            ~location:(L.map_m ~f)
            ~immediate:(D.map_m ~f)
            (* These don't contain symbols: *)
            ~string:M.return
            ~typ:M.return
            ~bop:M.return
      end
    end)
Sourceval proc_variant0 : Base.unit traversal -> 'cont Base.Variant.t -> 'cont M.t

proc_variant0 f variant lifts a traversal f over a Variantslib nullary variant constructor variant.

Sourceval proc_variant1 : 'a traversal -> ('a -> 'cont) Base.Variant.t -> 'a -> 'cont M.t

proc_variant1 f variant a lifts a traversal f over a Variantslib unary variant constructor variant with argument a.

Sourceval proc_variant2 : ('a * 'b) traversal -> ('a -> 'b -> 'cont) Base.Variant.t -> 'a -> 'b -> 'cont M.t

proc_variant2 f variant a b lifts a traversal f over a Variantslib binary variant constructor variant with arguments a and b.

Sourceval proc_variant3 : ('a * 'b * 'c) traversal -> ('a -> 'b -> 'c -> 'cont) Base.Variant.t -> 'a -> 'b -> 'c -> 'cont M.t

proc_variant3 f variant a b c lifts a traversal f over a Variantslib ternary variant constructor variant with arguments a, b, and c.

Fields

The function proc_field is useful for building traversable containers on top of Fieldslib's fold function.

Here's an example where we define a generic traversal function over a record type using proc_field, then use it to build a traversable container instance for inspecting and modifying a specific type of data inside the record.

  (* Type for holding x86 memory references. *)
  type t =
    { seg    : Reg.t   option (* segment register *)
    ; disp   : Disp.t  option (* displacement *)
    ; base   : Reg.t   option (* base register *)
    ; index  : Index.t option (* index *)
    } [@@deriving fields]

  (* First, build a generic traversal function (this isn't,
     itself, a Traversable)... *)
  module Base_map (M : Monad.S) = struct
    module F = Travesty.Traversable.Helpers (M)
    let map_m indirect ~seg ~disp ~base ~index =
      Fields.fold
        ~init:(M.return indirect)
        ~seg:(F.proc_field seg)
        ~disp:(F.proc_field disp)
        ~base:(F.proc_field base)
        ~index:(F.proc_field index)
  end

  (* Now, we can build a traversable container instance.
       This one extracts symbols from memory references. *)
  module On_symbols
    : Travesty.Traversable.S0_container with type t := t
                                         and type elt := string =
    Travesty.Traversable.Make_container0 (struct
      type nonrec t = t
      module Elt = String
      module Set = String.Set

      module On_monad (M : Monad.S) = struct
        module B = Base_map (M)
        module D = Disp.On_symbols.On_monad (M)
        module O = My_option.On_monad (M)

        let map_m t ~f =
          B.map_m t
            (* Chained monadic traversal. *)
            ~disp:(O.map_m ~f:(D.map_m ~f))
            (* Segments, bases, and indices have no symbols. *)
            ~seg:M.return
            ~base:M.return
            ~index:M.return
      end
    end)
Sourceval proc_field : 'elt traversal -> 'cont M.t -> ([> `Set_and_create ], 'cont, 'elt) Base.Field.t_with_perm -> 'cont M.t

proc_field f state field container original lifts a traversal f to a form comparible with Fieldslib's fold function.

OCaml

Innovation. Community. Security.