summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--parsing/longident.ml23
-rw-r--r--parsing/longident.mli2
-rw-r--r--parsing/parser.mly12
-rw-r--r--typing/env.ml35
-rw-r--r--typing/typetexp.ml102
-rw-r--r--typing/typetexp.mli3
6 files changed, 153 insertions, 24 deletions
diff --git a/parsing/longident.ml b/parsing/longident.ml
index 706881af3..bb7778725 100644
--- a/parsing/longident.ml
+++ b/parsing/longident.ml
@@ -39,3 +39,26 @@ let parse s =
[] -> Lident "" (* should not happen, but don't put assert false
so as not to crash the toplevel (see Genprintval) *)
| hd :: tl -> List.fold_left (fun p s -> Ldot(p, s)) (Lident hd) tl
+
+
+
+let rec concat t = function
+ | Lident s -> Ldot (t, s)
+ | Ldot (a, s) -> Ldot (concat t a, s)
+ | _ -> assert false
+
+let is_lident s =
+ match s.[0] with
+ | 'a'..'z' | '_' -> true
+ | _ -> false
+
+let rec split_lident = function
+ | Ldot(t, s) when is_lident (last t) ->
+ Some (t, Lident s)
+ | Ldot(Ldot (t1, s1) as t, s) ->
+ begin match split_lident t with
+ | None -> None
+ | Some (x, y) -> Some (x, Ldot(y, s))
+ end
+ | _ ->
+ None
diff --git a/parsing/longident.mli b/parsing/longident.mli
index 9e7958550..132e46901 100644
--- a/parsing/longident.mli
+++ b/parsing/longident.mli
@@ -20,3 +20,5 @@ type t =
val flatten: t -> string list
val last: t -> string
val parse: string -> t
+val concat: t -> t -> t
+val split_lident: t -> (t * t) option
diff --git a/parsing/parser.mly b/parsing/parser.mly
index f723e5aeb..3da50bd15 100644
--- a/parsing/parser.mly
+++ b/parsing/parser.mly
@@ -1995,12 +1995,22 @@ val_longident:
| mod_longident DOT val_ident { Ldot($1, $3) }
;
constr_longident:
- mod_longident %prec below_DOT { $1 }
+ constr_longident2 %prec below_DOT { $1 }
| LBRACKET RBRACKET { Lident "[]" }
| LPAREN RPAREN { Lident "()" }
| FALSE { Lident "false" }
| TRUE { Lident "true" }
;
+constr_longident2:
+ mod_longident %prec below_DOT { $1 }
+ | mod_longident DOT LIDENT DOT mod_longident %prec below_DOT {
+ Longident.concat (Ldot($1, $3)) $5
+ }
+
+ | LIDENT DOT mod_longident %prec below_DOT {
+ Longident.concat (Lident $1) $3
+ }
+;
label_longident:
LIDENT { Lident $1 }
| mod_longident DOT LIDENT { Ldot($1, $3) }
diff --git a/typing/env.ml b/typing/env.ml
index 5b89b0bd9..fe1eee1cd 100644
--- a/typing/env.ml
+++ b/typing/env.ml
@@ -860,6 +860,41 @@ let lookup_constructor lid env =
use ();
desc
+(*
+let lookup_constructor lid env =
+ match Longident.split_lident lid with
+ | None -> lookup_constructor lid env
+ | Some (ty_id, cstr_id) ->
+ let (ty_path, ty_decl) = lookup_type ty_id env in
+ match ty_decl.type_kind with
+ | Type_variant _ ->
+ let (cstrs, _, _) = find_type_descrs ty_path env in
+ begin match cstr_id with
+ | Lident s ->
+ List.find (fun c -> c.cstr_name = s) cstrs
+ | _ ->
+ failwith "Type %s is a regular variant type: constructor name must be local"
+ end
+ | Type_open ->
+ let cstrs = lookup_all_constructors cstr_id env in
+ let (c, use) =
+ try
+ List.find
+ (fun (c, _) ->
+ match (repr c.cstr_res).desc with
+ | Tconstr(p, _, _) -> Path.same ty_path p
+ | _ -> false
+ )
+ cstrs
+ with Not_found ->
+ failwith "No constructor with qualified name %s found in type %s"
+ in
+ use ();
+ c
+ | _ ->
+ failwith "Type %s is not a variant type"
+*)
+
let is_lident = function
Lident _ -> true
| _ -> false
diff --git a/typing/typetexp.ml b/typing/typetexp.ml
index 739c18c1f..6929614ff 100644
--- a/typing/typetexp.ml
+++ b/typing/typetexp.ml
@@ -49,9 +49,12 @@ type error =
| Unbound_class of Longident.t
| Unbound_modtype of Longident.t
| Unbound_cltype of Longident.t
+ | Unbound_constructor_in_type of Longident.t * Longident.t
| Ill_typed_functor_application of Longident.t
| Illegal_reference_to_recursive_module
| Access_functor_as_structure of Longident.t
+ | Constructor_must_be_local of Longident.t
+ | Not_a_variant_type of Longident.t
exception Error of Location.t * Env.t * error
exception Error_forward of Location.error
@@ -225,29 +228,6 @@ let find_type env loc lid =
let find_constructor =
find_component Env.lookup_constructor (fun lid -> Unbound_constructor lid)
-let find_type env loc lid =
- let s = Longident.last lid in
- match s.[0] with
- | 'A'..'Z' ->
- let cstr = find_constructor env loc lid in
- if not cstr.cstr_inlined then
- failwith (Printf.sprintf
- "Constructor %s does not have an inline record argument"
- s
- );
- begin match cstr.cstr_args with
- | [{desc=Tconstr(path, _, _)}] ->
- let decl =
- try Env.find_type path env
- with Not_found ->
- assert false
- in
- (path, decl)
- | _ -> assert false
- end
- | _ ->
- find_type env loc lid
-
let find_all_constructors =
find_component Env.lookup_all_constructors
(fun lid -> Unbound_constructor lid)
@@ -306,6 +286,70 @@ let unbound_label_error env lid =
narrow_unbound_lid_error env lid.loc lid.txt
(fun lid -> Unbound_label lid)
+let find_constructor_in_type env loc ty_id cstr_id =
+ let err e = raise (Error (loc, env, e)) in
+ let (ty_path, ty_decl) = find_type env loc ty_id in
+ match ty_decl.type_kind with
+ | Type_variant _ ->
+ let (cstrs, _, _) =
+ try Env.find_type_descrs ty_path env
+ with Not_found -> assert false
+ in
+ begin match cstr_id with
+ | Longident.Lident s ->
+ begin try List.find (fun c -> c.cstr_name = s) cstrs
+ with Not_found ->
+ err (Unbound_constructor_in_type (cstr_id, ty_id))
+ end
+ | _ ->
+ err (Constructor_must_be_local ty_id)
+ end
+ | Type_open ->
+ let cstrs = find_all_constructors env loc cstr_id in
+ let has_type (c, _) =
+ match (repr c.cstr_res).desc with
+ | Tconstr(p, _, _) -> Path.same ty_path p
+ | _ -> false
+ in
+ let (c, use) =
+ try List.find has_type cstrs
+ with Not_found ->
+ err (Unbound_constructor_in_type (cstr_id, ty_id))
+ in
+ use ();
+ c
+ | _ ->
+ err (Not_a_variant_type ty_id)
+
+let find_constructor env loc lid =
+ match Longident.split_lident lid with
+ | None -> find_constructor env loc lid
+ | Some (ty_id, cstr_id) -> find_constructor_in_type env loc ty_id cstr_id
+
+let find_type env loc lid =
+ let s = Longident.last lid in
+ match s.[0] with
+ | 'A'..'Z' ->
+ let cstr = find_constructor env loc lid in
+ if not cstr.cstr_inlined then
+ failwith (Printf.sprintf
+ "Constructor %s does not have an inline record argument"
+ s
+ );
+ begin match cstr.cstr_args with
+ | [{desc=Tconstr(path, _, _)}] ->
+ let decl =
+ try Env.find_type path env
+ with Not_found ->
+ assert false
+ in
+ (path, decl)
+ | _ -> assert false
+ end
+ | _ ->
+ find_type env loc lid
+
+
(* Support for first-class modules. *)
let transl_modtype_longident = ref (fun _ -> assert false)
@@ -1021,12 +1065,24 @@ let report_error env ppf = function
| Unbound_cltype lid ->
fprintf ppf "Unbound class type %a" longident lid;
spellcheck ppf Env.fold_cltypes env lid;
+ | Unbound_constructor_in_type (c_lid, t_lid) ->
+ fprintf ppf "Unbound constructor %a in type %a" longident c_lid
+ longident t_lid
| Ill_typed_functor_application lid ->
fprintf ppf "Ill-typed functor application %a" longident lid
| Illegal_reference_to_recursive_module ->
fprintf ppf "Illegal recursive module reference"
| Access_functor_as_structure lid ->
fprintf ppf "The module %a is a functor, not a structure" longident lid
+ | Constructor_must_be_local lid ->
+ fprintf ppf
+ "The type %a is a regular variant type (not an extensible one);@ "
+ longident lid;
+ fprintf ppf "qualified constructors are not allowed"
+ | Not_a_variant_type lid ->
+ fprintf ppf
+ "The type %a is not a variant type"
+ longident lid
let () =
Location.register_error_of_exn
diff --git a/typing/typetexp.mli b/typing/typetexp.mli
index 7bff403f0..a1ae0d694 100644
--- a/typing/typetexp.mli
+++ b/typing/typetexp.mli
@@ -61,9 +61,12 @@ type error =
| Unbound_class of Longident.t
| Unbound_modtype of Longident.t
| Unbound_cltype of Longident.t
+ | Unbound_constructor_in_type of Longident.t * Longident.t
| Ill_typed_functor_application of Longident.t
| Illegal_reference_to_recursive_module
| Access_functor_as_structure of Longident.t
+ | Constructor_must_be_local of Longident.t
+ | Not_a_variant_type of Longident.t
exception Error of Location.t * Env.t * error