@ -4,21 +4,26 @@
(* Types. *)
(* We include recursive types [ F TyMu] in the target calculus, not only because
(* We include recursive types [ TyMu] in the target calculus, not only because
we might wish to support them , but also because even if we disallow them ,
they can still arise during unification ( the occurs check is run late ) , so
we must be able to display them as part of a type error message . * )
(* Types mixing ∀ and μ are difficult to compare in general. To simplify
equality checking , we do not allow ∀ under μ .
For instance :
∀ a . μ t . a -> t is allowed
μ t . ∀ a . ( a -> t ) is not allowed
μ t . ( ∀ a . a ) -> t is not allowed * )
(* We also include a type equality witness [TyEq]. *)
(* Nominal or de Bruijn representation of type variables and binders. The
nominal representation is more convenient when translating from ML to F ,
while the de Bruijn representation is more convenient when type - checking
F . * )
type range =
Lexing . position * Lexing . position
let dummy_range : range =
Lexing . ( dummy_pos , dummy_pos )
type loc = Utils . loc
type ( ' a , ' b ) typ =
| TyVar of ' a
@ -27,10 +32,12 @@ type ('a, 'b) typ =
| TyForall of ' b * ( ' a , ' b ) typ
| TyMu of ' b * ( ' a , ' b ) typ
| TyConstr of ( ' a , ' b ) datatype
| TyEq of ( ' a , ' b ) typ * ( ' a , ' b ) typ
and ( ' a , ' b ) datatype = Datatype . tyconstr_id * ( ' a , ' b ) typ list
type tyvar = int
type tyvar =
string * int
type nominal_type =
( tyvar , tyvar ) typ
@ -53,31 +60,56 @@ type debruijn_datatype_env =
(* Nominal representation of term variables and binders. *)
type tevar = string
(* Nominal or de Bruijn representation of type variables and binders. *)
(* We include a term [Refl] that represents a type equality witness.
Note that it has only one type argument but is typed as a witness for
an equality between two possibly distinct types ( see [ TyEq ] above ) .
[ Use ] is a construct that " opens " a type equality . That is , it allows us to
reason in a context where two types are assumed to be equals .
It is supposed to be used with a type equality witness as a left - hand side :
use ( eq : TyEq ( ty1 , ty2 ) ) in
.. . (* here ty1 and ty2 are assumed to be equal *)
Doing this might introduce inconsistent assumptions about types ( this can
occur for example inside a pattern matching ) . That is why we introduce
a construct [ Absurd ] , that can be used as a placeholder in pieces of code
with inconsistent equations in the environment and that are thus
unreachable . * )
type tevar =
string
type ( ' a , ' b ) term =
| Var of range * tevar
| Hole of range * ( ' a , ' b ) typ * ( ' a , ' b ) term list
| Annot of range * ( ' a , ' b ) term * ( ' a , ' b ) typ
| Abs of range * tevar * ( ' a , ' b ) typ * ( ' a , ' b ) term
| App of range * ( ' a , ' b ) term * ( ' a , ' b ) term
| Let of range * tevar * ( ' a , ' b ) term * ( ' a , ' b ) term
| TyAbs of range * ' b * ( ' a , ' b ) term
| TyApp of range * ( ' a , ' b ) term * ( ' a , ' b ) typ
| Tuple of range * ( ' a , ' b ) term list
| Proj of range * int * ( ' a , ' b ) term
| LetProd of range * tevar list * ( ' a , ' b ) term * ( ' a , ' b ) term
| Variant of range * Datatype . label_id * ( ' a , ' b ) datatype * ( ' a , ' b ) term
| Match of range * ( ' a , ' b ) typ * ( ' a , ' b ) term * ( ' a , ' b ) branch list
| Var of loc * tevar
| Hole of loc * ( ' a , ' b ) typ * ( ' a , ' b ) term list
| Annot of loc * ( ' a , ' b ) term * ( ' a , ' b ) typ
| Abs of loc * tevar * ( ' a , ' b ) typ * ( ' a , ' b ) term
| App of loc * ( ' a , ' b ) term * ( ' a , ' b ) term
| Let of loc * rec_status * tevar * ( ' a , ' b ) typ * ( ' a , ' b ) term * ( ' a , ' b ) term
| TyAbs of loc * ' b * ( ' a , ' b ) term
| TyApp of loc * ( ' a , ' b ) term * ( ' a , ' b ) typ
| Tuple of loc * ( ' a , ' b ) term list
| Proj of loc * int * ( ' a , ' b ) term
| LetProd of loc * tevar list * ( ' a , ' b ) term * ( ' a , ' b ) term
| Variant of loc * Datatype . label_id * ( ' a , ' b ) datatype * ( ' a , ' b ) term
| Match of loc * ( ' a , ' b ) typ * ( ' a , ' b ) term * ( ' a , ' b ) branch list
| Absurd of loc * ( ' a , ' b ) typ
| Refl of loc * ( ' a , ' b ) typ
| Use of loc * ( ' a , ' b ) term * ( ' a , ' b ) typ * ( ' a , ' b ) typ * ( ' a , ' b ) term
and rec_status = Recursive | Non_recursive
and ( ' a , ' b ) branch = ( ' a , ' b ) pattern * ( ' a , ' b ) term
and ( ' a , ' b ) pattern =
| PVar of range * tevar
| PAnnot of range * ( ' a , ' b ) pattern * ( ' a , ' b ) typ
| PWildcard of range
| PTuple of range * ( ' a , ' b ) pattern list
| PVariant of range * Datatype . label_id * ( ' a , ' b ) datatype * ( ' a , ' b ) pattern
| PVar of loc * tevar
| PAnnot of loc * ( ' a , ' b ) pattern * ( ' a , ' b ) typ
| PWildcard of loc
| PTuple of loc * ( ' a , ' b ) pattern list
| PVariant of loc * Datatype . label_id * ( ' a , ' b ) datatype * ( ' a , ' b ) pattern
type nominal_term = ( tyvar , tyvar ) term
type nominal_pattern = ( tyvar , tyvar ) pattern
@ -90,10 +122,10 @@ type debruijn_term =
(* Constructors. *)
let ftyabs vs t =
List . fold_right ( fun v t -> TyAbs ( dummy_range , v , t ) ) vs t
let ftyapp t tys =
List . fold_left ( fun t ty -> TyApp ( dummy_range , t , ty ) ) t tys
let ftyabs ~ loc vs t =
List . fold_right ( fun v t -> TyAbs ( loc , v , t ) ) vs t
let ftyapp ~ loc t tys =
List . fold_left ( fun t ty -> TyApp ( loc , t , ty ) ) t tys
(* -------------------------------------------------------------------------- *)
@ -149,7 +181,10 @@ module TypeInType : DeBruijn.TRAVERSE
let env , x = extend env x in
let ty1' = trav env ty1 in
TyMu ( x , ty1' )
| TyEq ( ty1 , ty2 ) ->
let ty1' = trav env ty1 in
let ty2' = trav env ty2 in
TyEq ( ty1' , ty2' )
end
(* -------------------------------------------------------------------------- *)
@ -169,36 +204,39 @@ module TypeInTerm : DeBruijn.TRAVERSE
let rec traverse lookup extend env t =
let trav env = traverse lookup extend env in
let trav_ty env ty =
TypeInType . traverse lookup extend env ty in
match t with
| Var ( pos , x ) ->
Var ( pos , x )
| Hole ( pos , ty , ts ) ->
let ty' = TypeInType . traverse lookup extend env ty in
let ty' = trav_ty env ty in
let ts' = List . map ( trav env ) ts in
Hole ( pos , ty' , ts' )
| Annot ( pos , t , ty ) ->
let t' = trav env t
and ty' = TypeInType . traverse lookup extend env ty in
and ty' = trav_ty env ty in
Annot ( pos , t' , ty' )
| Abs ( pos , x , ty , t ) ->
let ty' = TypeInType . traverse lookup extend env ty
let ty' = trav_ty env ty
and t' = trav env t in
Abs ( pos , x , ty' , t' )
| App ( pos , t1 , t2 ) ->
let t1' = trav env t1
and t2' = trav env t2 in
App ( pos , t1' , t2' )
| Let ( pos , x , t1 , t2 ) ->
| Let ( pos , rec_ , x , ty , t1 , t2 ) ->
let ty' = trav_ty env ty in
let t1' = trav env t1
and t2' = trav env t2 in
Let ( pos , x, t1' , t2' )
Let ( pos , rec_, x, ty' , t1' , t2' )
| TyAbs ( pos , x , t ) ->
let env , x = extend env x in
let t' = trav env t in
TyAbs ( pos , x , t' )
| TyApp ( pos , t , ty ) ->
let t' = trav env t
and ty' = TypeInType . traverse lookup extend env ty in
and ty' = trav_ty env ty in
TyApp ( pos , t' , ty' )
| Tuple ( pos , ts ) ->
let ts' = List . map ( trav env ) ts in
@ -215,10 +253,22 @@ module TypeInTerm : DeBruijn.TRAVERSE
and t' = trav env t in
Variant ( pos , lbl , dty' , t' )
| Match ( pos , ty , t , brs ) ->
let ty' = TypeInType . traverse lookup extend env ty in
let ty' = trav_ty env ty in
let t' = trav env t
and brs' = List . map ( traverse_branch lookup extend env ) brs in
Match ( pos , ty' , t' , brs' )
| Absurd ( pos , ty ) ->
let ty' = trav_ty env ty in
Absurd ( pos , ty' )
| Refl ( pos , ty ) ->
let ty' = trav_ty env ty in
Refl ( pos , ty' )
| Use ( pos , t , ty1 , ty2 , u ) ->
let t' = trav env t in
let ty1' = trav_ty env ty1 in
let ty2' = trav_ty env ty2 in
let u' = trav env u in
Use ( pos , t' , ty1' , ty2' , u' )
and traverse_datatype lookup extend env ( tid , tyargs ) =
( tid , List . map ( TypeInType . traverse lookup extend env ) tyargs )
@ -250,6 +300,11 @@ end
(* -------------------------------------------------------------------------- *)
module TyVar = struct
type t = tyvar
let compare = Stdlib . compare
end
(* Type-in-type weakening and substitution. *)
module Type = struct
@ -257,7 +312,7 @@ module Type = struct
include DeBruijn . MakeSubst ( TypeVar ) ( TypeInType ) ( TypeInType )
include DeBruijn . MakeTranslate ( TypeVar ) ( TypeInType ) ( Int )
include DeBruijn . MakeTranslate ( TypeVar ) ( TypeInType ) ( TyVar )
end
(* -------------------------------------------------------------------------- *)
@ -265,11 +320,11 @@ end
(* Translation of nominal terms to de Bruijn terms. *)
module Term = struct
include DeBruijn . MakeTranslate ( TypeVar ) ( TypeInTerm ) ( Int )
include DeBruijn . MakeTranslate ( TypeVar ) ( TypeInTerm ) ( TyVar )
end
module N2DB = DeBruijn . Nominal2deBruijn ( Int )
module N2DB = DeBruijn . Nominal2deBruijn ( TyVar )
(* Translate a nominal-F datatype description into a De Bruijn version *)
let translate_datatype tdescr =