From 9107f14afc868a1da0682b2cef65f125c775b115 Mon Sep 17 00:00:00 2001 From: Frederic Bour Date: Thu, 3 Apr 2014 13:09:48 +0100 Subject: [PATCH] Comment [Types] --- parsing/asttypes.mli | 1 + typing/types.mli | 189 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 174 insertions(+), 16 deletions(-) diff --git a/parsing/asttypes.mli b/parsing/asttypes.mli index a0d636162..4b5fa4651 100644 --- a/parsing/asttypes.mli +++ b/parsing/asttypes.mli @@ -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 diff --git a/typing/types.mli b/typing/types.mli index 84131ccda..f452929ea 100644 --- a/typing/types.mli +++ b/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