Comment [Types]
parent
718d1c998b
commit
9107f14afc
|
@ -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
|
||||
|
|
189
typing/types.mli
189
typing/types.mli
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue