Module Rtt_untype

module Rtt_untype: sig .. end
Core runtime support for RTT.

This module implement the basic primitives required to exploit run-time types. Its interface is compiled with RTT, while its implementation is hand-coded to manipulate the additional rtt_type parameters directly, and uses Obj to bypass the type-checking based on the assumptions that the RTT transformation is correct.

Specific functionality such as pretty-printting (see Rtt_ops) can be implemented "safely" on top of this module, and compiled normally with RTT.

Manipulating values together with their dynamic type

type untyped 
A type for manipulating any value, ignoring its static type, but with the dynamic type embedded.
val untype : 'a -> untyped
Forget the static type of a value, and embedd its dynamic type.
val typeof : 'a -> Rtt_type.rttype
Return the dynamic type of a value.
val type_of_untyped : untyped -> Rtt_type.rttype
Return the type of an untyped value
val equalp_untyped : untyped -> untyped -> bool
Test physical equalities between untyped values. This function is less strict that Pervasives.( == ), as equalp_untyped (untype x) (untype x) is true.

Generic matching of values

type value_kind = 
| Kfun
| Ktuple of untyped list
| Kconstr of string * untyped list
| Krecord of (string * untyped) list
| Kprimitive of primitive_value
| Kvariant of string * untyped option
| Kunknown (*generated by stubbing*)
The type of the decomposition returned by Rtt_untype.destruct.
type primitive_value = 
| Vint of int
| Vchar of char
| Vstring of string
| Vfloat of float
| Vbool of bool
| Vunit
| Vexn of exn
| Varray of untyped array
| Vformat6 of string
| Vnativeint of nativeint
| Vint32 of int32
| Vint64 of int64
| Vlazy of untyped lazy_t
The type of untyped primitive values
val destruct : untyped -> value_kind
Perform one level of matching on an untyped value

Safe casting of untyped values

val cast : untyped -> 'a option
Safely cast an untyped value to an expected type, or return None if the dynamic type is not an instance of the expected type. The expected type is the dynamic type of this particular call to cast, it may be more precise than the static type, depending on the call context. Free variables in the (dynamic) expected type are considered as universal, which mean that they will only match a free type variable. Values whose dynamic type contain free type variables are for example: [] (the empty list) and
val cast_map : ('a -> 'b) -> untyped -> 'b option
Same as Rtt_untype.cast, but apply a function to the value before returning it. Type variables occuring in the type 'a but not in 'b are treated as existential, which means that they can match any type. For example, cast_map ignore will always succeed. Type variables occuring in both 'a and 'b' are treated as universal (see the description of Rtt_untype.cast). This also means that cast_map identity will always fail, if identity has the type 'a -> 'a which is not refined by the context.
val map_untyped : (untype:('c -> untyped) -> 'a -> 'b) ->
untyped -> 'b option
This cast function is similar to Rtt_untype.cast_map, but the argument function receives an additional argument untype, which serves the same purpose as the above function Rtt_untype.untype, but is more precise, because if the type 'c shares type variables with 'a, then they will be instantiated in 'c with their value in the dynamic type of 'a. For example map_untyped (fun ~untype l -> untype (List.hd l) will return the head of a list of any type, as an untyped value.

Run-time types manipulations

val substitute : Rtt_type.type_declaration ->
Rtt_type.rttype list -> Rtt_type.rttype -> Rtt_type.rttype
substitute decl args t substitute the list of types args for the parameters of the type declaration decl in a type t, which is typically the manifest of decl or the type of its fields or constructors. Note that the matching is performed (and an exception raised if the number of arguments does not match) as soon as the function is applied to decl and args.
val expand_abstract_with_manifest : Rtt_type.rttype -> Rtt_type.rttype
If the argument type is of the form Tconstr (decl, args) with decl being a type abbreviation, then it is (recursively) expanded. Otherwise, the same type is returned.
val declaration_equal : Rtt_type.type_declaration -> Rtt_type.type_declaration -> bool
Test if two type declarations represent the same type constructor, by comparing their name, persistent module name, and dynamic time stamp. So, for example, applying the same functor twice will always produce types that are distinct according to this function (which is differs from an applicative semantics for functors).

Physical equality would provide almost the same result, except for stubbed persistent structures, because the stubbing is repeated and stubbed types would be considered different. Structural equality should not be use because it would generally not terminate, and would consider isomorphic types equal.