Comment [Types]

master
Frederic Bour 2014-04-03 13:09:48 +01:00 committed by Thomas Refis
parent 718d1c998b
commit 9107f14afc
2 changed files with 174 additions and 16 deletions

View File

@ -25,6 +25,7 @@ type rec_flag = Nonrecursive | Recursive
type direction_flag = Upto | Downto
(* Order matters, used in polymorphic comparison *)
type private_flag = Private | Public
type mutable_flag = Immutable | Mutable

View File

@ -10,32 +10,146 @@
(* *)
(***********************************************************************)
(* Representation of types and declarations *)
(** {0 Representation of types and declarations} *)
(** [Types] defines the representation of types and declarations (that is, the
content of module signatures).
CMI files are made of marshalled types.
*)
(** Asttypes exposes basic definitions shared both by Parsetree and Types. *)
open Asttypes
(* Type expressions for the core language *)
(** Type expressions for the core language.
The [type_desc] variant defines all the possible type expressions one can
find in OCaml. [type_expr] wraps this with some annotations.
The [level] field tracks the level of polymorphism associated to a type,
guiding the generalization algorithm.
Put shortly, when referring to a type in a given environment, both the type
and the environment have a level. If the type has an higher level, then it
can be considered fully polymorphic (type variables will be printed as
['a]), otherwise it'll be weakly polymorphic, or non generalized (type
variables printed as ['_a]).
See [http://okmij.org/ftp/ML/generalization.html] for more information.
Note about [type_declaration]: one should not make the confusion between
[type_expr] and [type_declaration].
[type_declaration] refers specifically to the [type] construct in OCaml
language, where you create and name a new type or type alias.
[type_expr] is used when you refer to existing types, e.g. when annotating
the expected type of a value.
Also, as the type system of OCaml is generative, a [type_declaration] can
have the side-effect of introducing a new type constructor, different from
all other known types.
Whereas [type_expr] is a pure construct which allows referring to existing
types.
Note on mutability: TBD.
*)
type type_expr =
{ mutable desc: type_desc;
mutable level: int;
mutable id: int }
and type_desc =
Tvar of string option
| Tarrow of arg_label * type_expr * type_expr * commutable
| Ttuple of type_expr list
| Tconstr of Path.t * type_expr list * abbrev_memo ref
| Tobject of type_expr * (Path.t * type_expr list) option ref
| Tfield of string * field_kind * type_expr * type_expr
| Tnil
| Tlink of type_expr
| Tsubst of type_expr (* for copying *)
| Tvariant of row_desc
| Tunivar of string option
| Tpoly of type_expr * type_expr list
| Tpackage of Path.t * Longident.t list * type_expr list
| Tvar of string option
(** [Tvar (Some "a")] ==> ['a] or ['_a]
[Tvar None] ==> [_] *)
| Tarrow of arg_label * type_expr * type_expr * commutable
(** [Tarrow (Nolabel, e1, e2, c)] ==> [e1 -> e2]
[Tarrow (Labelled "l", e1, e2, c)] ==> [l:e1 -> e2]
[Tarrow (Optional "l", e1, e2, c)] ==> [?l:e1 -> e2]
See [commutable] for the last argument. *)
| Ttuple of type_expr list
(** [Ttuple [t1;...;tn]] ==> [(t1 * ... * tn)] *)
| Tconstr of Path.t * type_expr list * abbrev_memo ref
(** [Tconstr (`A.B.t', [t1;...;tn], _)] ==> [(t1,...,tn) A.B.t]
The last parameter keep tracks of known expansions, see [abbrev_memo]. *)
| Tobject of type_expr * (Path.t * type_expr list) option ref
(** [Tobject (`f1:t1;...;fn: tn', `None')] ==> [< f1: t1; ...; fn: tn >]
f1, fn are represented as a linked list of types using Tfield and Tnil
constructors.
[Tobject (_, `Some (`A.ct', [t1;...;tn]')] ==> [(t1, ..., tn) A.ct].
where A.ct is the type of some class.
There are also special cases for so-called "class-types", cf. [Typeclass]
and [Ctype.set_object_name]:
[Tobject (Tfield(_,_,(Tfield(_,_,rv)), Some(`A.#ct`, [rv;t1;;tn])]
==> [(t1, , tn) #A.ct]
[Tobject (_, Some(`A.#ct`, [Tnil;t1;;tn])] ==> [(t1, , tn) A.ct]
where [rv] is the hidden row variable.
*)
| Tfield of string * field_kind * type_expr * type_expr
(** [Tfield ("foo", Fpresent, t, ts)] ==> [<...; foo : t; ts>] *)
| Tnil
(** [Tnil] ==> [<...; >] *)
| Tlink of type_expr
(** Indirection used by unification engine. *)
| Tsubst of type_expr (* for copying *)
(** [Tsubst] is used temporarily to store information in low-level
functions manipulating representation of types, such as
instantiation or copy.
This constructor should not appear outside of these cases. *)
| Tvariant of row_desc
(** Representation of polymorphic variants, see [row_desc]. *)
| Tunivar of string option
(** Occurrence of a type variable introduced by a
forall quantifier / [Tpoly]. *)
| Tpoly of type_expr * type_expr list
(** [Tpoly (ty,tyl)] ==> ['a1... 'an. ty],
where 'a1 ... 'an are names given to types in tyl
and occurences of those types in ty. *)
| Tpackage of Path.t * Longident.t list * type_expr list
(** Type of a first-class module (a.k.a package). *)
(** [ `X | `Y ] (row_closed = true)
[< `X | `Y ] (row_closed = true)
[> `X | `Y ] (row_closed = false)
[< `X | `Y > `X ] (row_closed = true)
type t = [> `X ] as 'a (row_more = Tvar a)
type t = private [> `X ] (row_more = Tconstr (t#row, [], ref Mnil)
And for:
let f = function `X -> `X -> | `Y -> `X
the type of "f" will be a [Tarrow] whose lhs will (basically) be:
Tvariant { row_fields = [("X", _)];
row_more =
Tvariant { row_fields = [("Y", _)];
row_more =
Tvariant { row_fields = [];
row_more = _;
_ };
_ };
_
}
*)
and row_desc =
{ row_fields: (label * row_field) list;
row_more: type_expr;
@ -52,16 +166,59 @@ and row_field =
is erased later *)
| Rabsent
(** [abbrev_memo] allows one to keep track of different expansions of a type
alias. This is done for performance purposes.
For instance, when defining [type 'a pair = 'a * 'a], when one refers to an
['a pair], it is just a shortcut for the ['a * 'a] type.
This expansion will be stored in the [abbrev_memo] of the corresponding
[Tconstr] node.
In practice, [abbrev_memo] behaves like list of expansions with a mutable
tail.
Note on marshalling: [abbrev_memo] must not appear in saved types.
[Btype], with [cleanup_abbrev] and [memo], takes care of tracking and
removing abbreviations.
*)
and abbrev_memo =
Mnil
| Mnil (** No known abbrevation *)
| Mcons of private_flag * Path.t * type_expr * type_expr * abbrev_memo
(** Found one abbreviation.
A valid abbreviation should be at least as visible and reachable by the
same path.
The first expression is the abbreviation and the second the expansion. *)
| Mlink of abbrev_memo ref
(** Abbreviations can be found after this indirection *)
and field_kind =
Fvar of field_kind option ref
| Fpresent
| Fabsent
(** [commutable] is a flag appended to every arrow type.
When typing an application, if the type of the functional is
known, its type is instantiated with [Cok] arrows, otherwise as
[Clink (ref Cunknown)].
When the type is not known, the application will be used to infer
the actual type. This is fragile in presence of labels where
there is no principal type.
Two incompatible applications relying on [Cunknown] arrows will
trigger an error.
let f g =
g ~a:() ~b:();
g ~b:() ~a:();
Error: This function is applied to arguments
in an order different from other calls.
This is only allowed when the real type is known.
*)
and commutable =
Cok
| Cunknown