Module Ocaml_typing.Shape

Shapes are an abstract representation of modules' implementations which allow the tracking of definitions through functor applications and other module-level operations.

The Shape of a compilation unit is elaborated during typing, partially reduced (without loading external shapes) and written to the cmt file.

External tools can retrieve the definition of any value (or type, or module, etc) by following this procedure:

See:

module Layout = Jkind_types.Sort.Const
type base_layout = Jkind_types.Sort.base
module Uid : sig ... end

A Uid.t is associated to every declaration in signatures and implementations. They uniquely identify bindings in the program. When associated with these bindings' locations they are useful to external tools when trying to jump to an identifier's declaration or definition. They are stored to that effect in the uid_to_decl table of cmt files.

module DeBruijn_index : sig ... end

We use de Bruijn indices for some binders in Shape.t below to increase sharing. That is, de Bruijn indices ensure that alpha-equivalent terms are actually equal. This reduces redundancy when we emit shape information into the debug information in later stages of the compiler (see dwarf_type.ml), since equal shapes produce the same debug information.

module Sig_component_kind : sig ... end
module Item : sig ... end

Shape's items are elements of a structure or, in the case of constructors and labels, elements of a record or variants definition seen as a structure. These structures model module components and nested types' constructors and labels.

module Predef : sig ... end
type var = Ident.t
type t = private {
  1. hash : int;
  2. uid : Uid.t option;
  3. desc : desc;
  4. approximated : bool;
}
and desc =
  1. | Var of var
  2. | Abs of var * t
  3. | App of t * t
  4. | Struct of t Item.Map.t
  5. | Alias of t
  6. | Leaf
  7. | Proj of t * Item.t
  8. | Comp_unit of string
  9. | Error of string
  10. | Constr of Ident.t * t list
  11. | Tuple of t list
  12. | Unboxed_tuple of t list
  13. | Predef of Predef.t * t list
  14. | Arrow
  15. | Poly_variant of t poly_variant_constructors
  16. | Mu of t
    (*

    Mu t represents a binder for a recursive type with body t. Its variables are Rec_var n below, where n is a DeBruijn-index to maximize sharing between alpha-equivalent shapes.

    *)
  17. | Rec_var of DeBruijn_index.t
  18. | Variant of (t * Layout.t) complex_constructors
  19. | Variant_unboxed of {
    1. name : string;
    2. variant_uid : Uid.t option;
    3. arg_name : string option;
      (*

      if this is None, we are looking at a singleton tuple; otherwise, it is a singleton record.

      *)
    4. arg_uid : Uid.t option;
    5. arg_shape : t;
    6. arg_layout : Layout.t;
    }
    (*

    An unboxed variant corresponds to the @@unboxed annotation. It must have a single, complex constructor.

    *)
  20. | Record of {
    1. fields : (string * Uid.t option * t * Layout.t) list;
    2. kind : record_kind;
    }
  21. | Mutrec of t Ident.Map.t
    (*

    Mutrec m represents a map of (potentially mutually-recursive) declarations. Declarations with type variables are represented as abstractions inside. To project out a declaration, Proj_decl can be used.

    *)
  22. | Proj_decl of t * Ident.t

For DWARF type emission to work as expected, we store the layouts in the declaration alongside the shapes in those cases where the layout "expands" again such as variant constructors, which themselves are values but point to blocks in memory. Here, layouts are stored for the individual fields.

and 'a poly_variant_constructors = 'a poly_variant_constructor list
and 'a poly_variant_constructor = {
  1. pv_constr_name : string;
  2. pv_constr_args : 'a list;
}
and record_kind =
  1. | Record_unboxed
    (*

    Record_unboxed is the case for single-field records declared with @@unboxed, whose runtime representation is simply its contents without any indirection.

    *)
  2. | Record_unboxed_product
    (*

    Record_unboxed_product is the truly unboxed record that corresponds to #{ ... }.

    *)
  3. | Record_boxed
  4. | Record_mixed of mixed_product_shape
  5. | Record_floats
    (*

    Basically the same as Record_mixed, but we don't reorder the fields.

    *)
and 'a complex_constructors = 'a complex_constructor list
and 'a complex_constructor = {
  1. name : string;
  2. constr_uid : Uid.t option;
  3. kind : constructor_representation;
  4. args : 'a complex_constructor_argument list;
}
and 'a complex_constructor_argument = {
  1. field_name : string option;
  2. field_uid : Uid.t option;
  3. field_value : 'a;
}
and constructor_representation = mixed_product_shape
and mixed_product_shape = Layout.t array
val print : Format.formatter -> t -> unit
val strip_head_aliases : t -> t
val equal : t -> t -> bool
val equal_record_kind : record_kind -> record_kind -> bool
val equal_complex_constructor : ('a -> 'a -> bool) -> 'a complex_constructor -> 'a complex_constructor -> bool
val for_unnamed_functor_param : var
val fresh_var : ?name:string -> Uid.t -> var * t
val var : Uid.t -> Ident.t -> t
val var' : Uid.t option -> Ident.t -> t
val abs : ?uid:Uid.t -> var -> t -> t
val app : ?uid:Uid.t -> t -> arg:t -> t
val str : ?uid:Uid.t -> t Item.Map.t -> t
val alias : ?uid:Uid.t -> t -> t
val error : ?uid:Uid.t -> string -> t
val proj : ?uid:Uid.t -> t -> Item.t -> t
val leaf : Uid.t -> t
val leaf' : Uid.t option -> t
val comp_unit : ?uid:Uid.t -> string -> t
val constr : ?uid:Uid.t -> Ident.t -> t list -> t
val tuple : ?uid:Uid.t -> t list -> t
val unboxed_tuple : ?uid:Uid.t -> t list -> t
val predef : ?uid:Uid.t -> Predef.t -> t list -> t
val arrow : ?uid:Uid.t -> unit -> t
val poly_variant : ?uid:Uid.t -> t poly_variant_constructors -> t
val mu : ?uid:Uid.t -> t -> t
val rec_var : ?uid:Uid.t -> DeBruijn_index.t -> t
val variant : ?uid:Uid.t -> (t * Layout.t) complex_constructors -> t
val variant_unboxed : ?uid:Uid.t -> variant_uid:Uid.t option -> arg_uid:Uid.t option -> string -> string option -> t -> Layout.t -> t
val record : ?uid:Uid.t -> record_kind -> (string * Uid.t option * t * Layout.t) list -> t
val mutrec : ?uid:Uid.t -> t Ident.Map.t -> t
val proj_decl : ?uid:Uid.t -> t -> Ident.t -> t
val set_approximated : approximated:bool -> t -> t
val app_list : t -> t list -> t
val abs_list : t -> Ident.t list -> t
val decompose_abs : t -> (var * t) option
val for_persistent_unit : string -> t
val leaf_for_unpack : t
val poly_variant_constructors_map : ('a -> 'b) -> 'a poly_variant_constructors -> 'b poly_variant_constructors
val complex_constructor_map : ('a -> 'b) -> 'a complex_constructor -> 'b complex_constructor
val complex_constructors_map : ('a -> 'b) -> 'a complex_constructors -> 'b complex_constructors
module Map : sig ... end
val dummy_mod : t
val of_path : find_shape:(Sig_component_kind.t -> Ident.t -> t) -> namespace:Sig_component_kind.t -> Path.t -> t

This function returns the shape corresponding to a given path. It requires a callback to find shapes in the environment. It is generally more useful to rely directly on the Env.shape_of_path function to get the shape associated with a given path.

val set_uid_if_none : t -> Uid.t -> t
module Cache : Hashtbl.S with type key = t
module DeBruijn_env : sig ... end

DeBruijn Environment for working with the recursive binders.