package owee

  1. Overview
  2. Docs

A module to manually instrument values and implement dynamic services based on the actual type of these values.

The idea is to put a distinguished word, of type t marker in a value of type t. This module implements tools to generate and scan for such word, and execute functions based on the type recovered.

Manipulation of markers should be done with care: if the introspection find any value with the t marker word, it will incorrectly behave as if value was of type t.

The Safe_ functors ease manipulation of markers, at the cost of wrapping values. Use the Unsafe_ ones if you know what you are doing.

Dynamic services

Services are typed queries which can be executed on arbitrary ocaml objects. The query will succeed if:

  • object has a marker
  • this marker implements the type of service being requested.
type 'result service = ..

The extensible type of dynamic services. Add your own services to the list and run queries at runtime without knowledge of the object type.

Think of this as an extensible list of methods (and of markers as a vtable for those methods).

type service +=
  1. | Name : string service
    (*

    A user-friendly label for your object / class of objects

    *)
  2. | Traverse : ((Stdlib.Obj.t -> 'acc -> 'acc) -> 'acc -> 'acc) service
    (*

    Run a fold functions on object leafs, useful to traverse structure which are partially opaque.

    *)
  3. | Locate : Owee_location.t list service
    (*

    Return a list of locations relevant to the object

    *)
type 'a service_result =
  1. | Success of 'a
    (*

    Object implements the service, here is your answer

    *)
  2. | Unsupported_service
    (*

    Service is not supported / unknown, but object is marked

    *)
  3. | Unmanaged_object
    (*

    No marker has been found on the object, you can't run any query on it 

    *)

Possible outcomes for the execution of a service

Manipulating objects

User API to work with marked objects.

type 'a marked

Type of object marked with the safe interface

val get : 'a marked -> 'a
val query_service : 'a -> 'result service -> 'result service_result

Query an object for a service

Cycle detection

User API to work with graph of marked objects.

type cycle

Type storing the state needed of traversal of marked OCaml object graphs

val start_cycle : unit -> cycle

Start a fresh cycle detector

val end_cycle : cycle -> unit

Release all ressources associated to the cycle. The cycle value should not be used after that.

val mark_seen : cycle -> Stdlib.Obj.t -> [ `Already_seen of int | `Now_seen of int | `Unmanaged ]

Mark an object as seen in a cycle. An integer uniquely identifying the object in this cycle is returned.

val seen : cycle -> Stdlib.Obj.t -> [ `Seen of int | `Not_seen | `Unmanaged ]

Was the object already seen during this traversal? If seen, the integer resulting from the call to mark_seen is returned.

val fresh_name : unit -> int

Generate a fresh name, guaranteed not to collide with results of mark_seen.

Marking objects

Implementor API.

module type T0 = sig ... end

The signature that needs to be implemented to add service support to your objects.

Safe api

module Safe0 (M : T0) : sig ... end

Unsafe api

type 'a marker
module Unsafe0 (M : T0) : sig ... end
module type T1 = sig ... end
module type T2 = sig ... end
module type T3 = sig ... end
module Safe1 (M : T1) : sig ... end
module Safe2 (M : T2) : sig ... end
module Safe3 (M : T3) : sig ... end
module Unsafe1 (M : T1) : sig ... end
module Unsafe2 (M : T2) : sig ... end
module Unsafe3 (M : T3) : sig ... end