1419 lines
54 KiB
Plaintext
1419 lines
54 KiB
Plaintext
Index: parsing/lexer.mll
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/parsing/lexer.mll,v
|
|
retrieving revision 1.73
|
|
diff -u -r1.73 lexer.mll
|
|
--- parsing/lexer.mll 11 Apr 2005 16:44:26 -0000 1.73
|
|
+++ parsing/lexer.mll 2 Feb 2006 06:28:32 -0000
|
|
@@ -63,6 +63,8 @@
|
|
"match", MATCH;
|
|
"method", METHOD;
|
|
"module", MODULE;
|
|
+ "multifun", MULTIFUN;
|
|
+ "multimatch", MULTIMATCH;
|
|
"mutable", MUTABLE;
|
|
"new", NEW;
|
|
"object", OBJECT;
|
|
Index: parsing/parser.mly
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/parsing/parser.mly,v
|
|
retrieving revision 1.123
|
|
diff -u -r1.123 parser.mly
|
|
--- parsing/parser.mly 23 Mar 2005 03:08:37 -0000 1.123
|
|
+++ parsing/parser.mly 2 Feb 2006 06:28:32 -0000
|
|
@@ -257,6 +257,8 @@
|
|
%token MINUSDOT
|
|
%token MINUSGREATER
|
|
%token MODULE
|
|
+%token MULTIFUN
|
|
+%token MULTIMATCH
|
|
%token MUTABLE
|
|
%token <nativeint> NATIVEINT
|
|
%token NEW
|
|
@@ -325,7 +327,7 @@
|
|
%nonassoc SEMI /* below EQUAL ({lbl=...; lbl=...}) */
|
|
%nonassoc LET /* above SEMI ( ...; let ... in ...) */
|
|
%nonassoc below_WITH
|
|
-%nonassoc FUNCTION WITH /* below BAR (match ... with ...) */
|
|
+%nonassoc FUNCTION WITH MULTIFUN /* below BAR (match ... with ...) */
|
|
%nonassoc AND /* above WITH (module rec A: SIG with ... and ...) */
|
|
%nonassoc THEN /* below ELSE (if ... then ...) */
|
|
%nonassoc ELSE /* (if ... then ... else ...) */
|
|
@@ -804,8 +806,12 @@
|
|
{ mkexp(Pexp_function("", None, List.rev $3)) }
|
|
| FUN labeled_simple_pattern fun_def
|
|
{ let (l,o,p) = $2 in mkexp(Pexp_function(l, o, [p, $3])) }
|
|
+ | MULTIFUN opt_bar match_cases
|
|
+ { mkexp(Pexp_multifun(List.rev $3)) }
|
|
| MATCH seq_expr WITH opt_bar match_cases
|
|
- { mkexp(Pexp_match($2, List.rev $5)) }
|
|
+ { mkexp(Pexp_match($2, List.rev $5, false)) }
|
|
+ | MULTIMATCH seq_expr WITH opt_bar match_cases
|
|
+ { mkexp(Pexp_match($2, List.rev $5, true)) }
|
|
| TRY seq_expr WITH opt_bar match_cases
|
|
{ mkexp(Pexp_try($2, List.rev $5)) }
|
|
| TRY seq_expr WITH error
|
|
@@ -1318,10 +1324,10 @@
|
|
| simple_core_type2 { Rinherit $1 }
|
|
;
|
|
tag_field:
|
|
- name_tag OF opt_ampersand amper_type_list
|
|
- { Rtag ($1, $3, List.rev $4) }
|
|
- | name_tag
|
|
- { Rtag ($1, true, []) }
|
|
+ name_tag OF opt_ampersand amper_type_list amper_type_pair_list
|
|
+ { Rtag ($1, $3, List.rev $4, $5) }
|
|
+ | name_tag amper_type_pair_list
|
|
+ { Rtag ($1, true, [], $2) }
|
|
;
|
|
opt_ampersand:
|
|
AMPERSAND { true }
|
|
@@ -1331,6 +1337,11 @@
|
|
core_type { [$1] }
|
|
| amper_type_list AMPERSAND core_type { $3 :: $1 }
|
|
;
|
|
+amper_type_pair_list:
|
|
+ AMPERSAND core_type EQUAL core_type amper_type_pair_list
|
|
+ { ($2, $4) :: $5 }
|
|
+ | /* empty */
|
|
+ { [] }
|
|
opt_present:
|
|
LBRACKETGREATER name_tag_list RBRACKET { List.rev $2 }
|
|
| /* empty */ { [] }
|
|
Index: parsing/parsetree.mli
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/parsing/parsetree.mli,v
|
|
retrieving revision 1.42
|
|
diff -u -r1.42 parsetree.mli
|
|
--- parsing/parsetree.mli 23 Mar 2005 03:08:37 -0000 1.42
|
|
+++ parsing/parsetree.mli 2 Feb 2006 06:28:32 -0000
|
|
@@ -43,7 +43,7 @@
|
|
| Pfield_var
|
|
|
|
and row_field =
|
|
- Rtag of label * bool * core_type list
|
|
+ Rtag of label * bool * core_type list * (core_type * core_type) list
|
|
| Rinherit of core_type
|
|
|
|
(* XXX Type expressions for the class language *)
|
|
@@ -86,7 +86,7 @@
|
|
| Pexp_let of rec_flag * (pattern * expression) list * expression
|
|
| Pexp_function of label * expression option * (pattern * expression) list
|
|
| Pexp_apply of expression * (label * expression) list
|
|
- | Pexp_match of expression * (pattern * expression) list
|
|
+ | Pexp_match of expression * (pattern * expression) list * bool
|
|
| Pexp_try of expression * (pattern * expression) list
|
|
| Pexp_tuple of expression list
|
|
| Pexp_construct of Longident.t * expression option * bool
|
|
@@ -111,6 +111,7 @@
|
|
| Pexp_lazy of expression
|
|
| Pexp_poly of expression * core_type option
|
|
| Pexp_object of class_structure
|
|
+ | Pexp_multifun of (pattern * expression) list
|
|
|
|
(* Value descriptions *)
|
|
|
|
Index: parsing/printast.ml
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/parsing/printast.ml,v
|
|
retrieving revision 1.29
|
|
diff -u -r1.29 printast.ml
|
|
--- parsing/printast.ml 4 Jan 2006 16:55:50 -0000 1.29
|
|
+++ parsing/printast.ml 2 Feb 2006 06:28:32 -0000
|
|
@@ -205,10 +205,14 @@
|
|
line i ppf "Pexp_apply\n";
|
|
expression i ppf e;
|
|
list i label_x_expression ppf l;
|
|
- | Pexp_match (e, l) ->
|
|
+ | Pexp_match (e, l, b) ->
|
|
line i ppf "Pexp_match\n";
|
|
expression i ppf e;
|
|
list i pattern_x_expression_case ppf l;
|
|
+ bool i ppf b
|
|
+ | Pexp_multifun l ->
|
|
+ line i ppf "Pexp_multifun\n";
|
|
+ list i pattern_x_expression_case ppf l;
|
|
| Pexp_try (e, l) ->
|
|
line i ppf "Pexp_try\n";
|
|
expression i ppf e;
|
|
@@ -653,7 +657,7 @@
|
|
|
|
and label_x_bool_x_core_type_list i ppf x =
|
|
match x with
|
|
- Rtag (l, b, ctl) ->
|
|
+ Rtag (l, b, ctl, cstr) ->
|
|
line i ppf "Rtag \"%s\" %s\n" l (string_of_bool b);
|
|
list (i+1) core_type ppf ctl
|
|
| Rinherit (ct) ->
|
|
Index: typing/btype.ml
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/typing/btype.ml,v
|
|
retrieving revision 1.38
|
|
diff -u -r1.38 btype.ml
|
|
--- typing/btype.ml 4 Jan 2006 16:55:50 -0000 1.38
|
|
+++ typing/btype.ml 2 Feb 2006 06:28:32 -0000
|
|
@@ -66,16 +66,16 @@
|
|
Clink r when !r <> Cunknown -> commu_repr !r
|
|
| c -> c
|
|
|
|
-let rec row_field_repr_aux tl = function
|
|
- Reither(_, tl', _, {contents = Some fi}) ->
|
|
- row_field_repr_aux (tl@tl') fi
|
|
- | Reither(c, tl', m, r) ->
|
|
- Reither(c, tl@tl', m, r)
|
|
+let rec row_field_repr_aux tl tl2 = function
|
|
+ Reither(_, tl', _, tl2', {contents = Some fi}) ->
|
|
+ row_field_repr_aux (tl@tl') (tl2@tl2') fi
|
|
+ | Reither(c, tl', m, tl2', r) ->
|
|
+ Reither(c, tl@tl', m, tl2@tl2', r)
|
|
| Rpresent (Some _) when tl <> [] ->
|
|
Rpresent (Some (List.hd tl))
|
|
| fi -> fi
|
|
|
|
-let row_field_repr fi = row_field_repr_aux [] fi
|
|
+let row_field_repr fi = row_field_repr_aux [] [] fi
|
|
|
|
let rec rev_concat l ll =
|
|
match ll with
|
|
@@ -170,7 +170,8 @@
|
|
(fun (_, fi) ->
|
|
match row_field_repr fi with
|
|
| Rpresent(Some ty) -> f ty
|
|
- | Reither(_, tl, _, _) -> List.iter f tl
|
|
+ | Reither(_, tl, _, tl2, _) ->
|
|
+ List.iter f tl; List.iter (fun (t1,t2) -> f t1; f t2) tl2
|
|
| _ -> ())
|
|
row.row_fields;
|
|
match (repr row.row_more).desc with
|
|
@@ -208,15 +209,17 @@
|
|
(fun (l, fi) -> l,
|
|
match row_field_repr fi with
|
|
| Rpresent(Some ty) -> Rpresent(Some(f ty))
|
|
- | Reither(c, tl, m, e) ->
|
|
+ | Reither(c, tl, m, tpl, e) ->
|
|
let e = if keep then e else ref None in
|
|
let m = if row.row_fixed then fixed else m in
|
|
let tl = List.map f tl in
|
|
+ let tl1 = List.map (fun (t1,_) -> repr (f t1)) tpl
|
|
+ and tl2 = List.map (fun (_,t2) -> repr (f t2)) tpl in
|
|
bound := List.filter
|
|
(function {desc=Tconstr(_,[],_)} -> false | _ -> true)
|
|
- (List.map repr tl)
|
|
+ (List.map repr tl @ tl1 @ tl2)
|
|
@ !bound;
|
|
- Reither(c, tl, m, e)
|
|
+ Reither(c, tl, m, List.combine tl1 tl2, e)
|
|
| _ -> fi)
|
|
row.row_fields in
|
|
let name =
|
|
Index: typing/ctype.ml
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/typing/ctype.ml,v
|
|
retrieving revision 1.200
|
|
diff -u -r1.200 ctype.ml
|
|
--- typing/ctype.ml 6 Jan 2006 02:16:24 -0000 1.200
|
|
+++ typing/ctype.ml 2 Feb 2006 06:28:32 -0000
|
|
@@ -340,7 +340,7 @@
|
|
let fi = filter_row_fields erase fi in
|
|
match row_field_repr f with
|
|
Rabsent -> fi
|
|
- | Reither(_,_,false,e) when erase -> set_row_field e Rabsent; fi
|
|
+ | Reither(_,_,false,_,e) when erase -> set_row_field e Rabsent; fi
|
|
| _ -> p :: fi
|
|
|
|
(**************************************)
|
|
@@ -1286,6 +1286,10 @@
|
|
|
|
module TypeMap = Map.Make (TypeOps)
|
|
|
|
+
|
|
+(* A list of univars which may appear free in a type, but only if generic *)
|
|
+let allowed_univars = ref TypeSet.empty
|
|
+
|
|
(* Test the occurence of free univars in a type *)
|
|
(* that's way too expansive. Must do some kind of cacheing *)
|
|
let occur_univar env ty =
|
|
@@ -1307,7 +1311,12 @@
|
|
then
|
|
match ty.desc with
|
|
Tunivar ->
|
|
- if not (TypeSet.mem ty bound) then raise (Unify [ty, newgenvar()])
|
|
+ if TypeSet.mem ty bound then () else
|
|
+ if TypeSet.mem ty !allowed_univars &&
|
|
+ (ty.level = generic_level ||
|
|
+ ty.level = pivot_level - generic_level)
|
|
+ then ()
|
|
+ else raise (Unify [ty, newgenvar()])
|
|
| Tpoly (ty, tyl) ->
|
|
let bound = List.fold_right TypeSet.add (List.map repr tyl) bound in
|
|
occur_rec bound ty
|
|
@@ -1393,6 +1402,7 @@
|
|
with exn -> univar_pairs := old_univars; raise exn
|
|
|
|
let univar_pairs = ref []
|
|
+let delayed_conditionals = ref []
|
|
|
|
|
|
(*****************)
|
|
@@ -1691,9 +1701,11 @@
|
|
with Not_found -> (h,l)::hl)
|
|
(List.map (fun (l,_) -> (hash_variant l, l)) row1.row_fields)
|
|
(List.map fst r2));
|
|
+ let fixed1 = row1.row_fixed || rm1.desc <> Tvar
|
|
+ and fixed2 = row2.row_fixed || rm2.desc <> Tvar in
|
|
let more =
|
|
- if row1.row_fixed then rm1 else
|
|
- if row2.row_fixed then rm2 else
|
|
+ if fixed1 then rm1 else
|
|
+ if fixed2 then rm2 else
|
|
newgenvar ()
|
|
in update_level env (min rm1.level rm2.level) more;
|
|
let fixed = row1.row_fixed || row2.row_fixed
|
|
@@ -1726,18 +1738,18 @@
|
|
let bound = row1.row_bound @ row2.row_bound in
|
|
let row0 = {row_fields = []; row_more = more; row_bound = bound;
|
|
row_closed = closed; row_fixed = fixed; row_name = name} in
|
|
- let set_more row rest =
|
|
+ let set_more row row_fixed rest =
|
|
let rest =
|
|
if closed then
|
|
filter_row_fields row.row_closed rest
|
|
else rest in
|
|
- if rest <> [] && (row.row_closed || row.row_fixed)
|
|
- || closed && row.row_fixed && not row.row_closed then begin
|
|
+ if rest <> [] && (row.row_closed || row_fixed)
|
|
+ || closed && row_fixed && not row.row_closed then begin
|
|
let t1 = mkvariant [] true and t2 = mkvariant rest false in
|
|
raise (Unify [if row == row1 then (t1,t2) else (t2,t1)])
|
|
end;
|
|
let rm = row_more row in
|
|
- if row.row_fixed then
|
|
+ if row_fixed then
|
|
if row0.row_more == rm then () else
|
|
if rm.desc = Tvar then link_type rm row0.row_more else
|
|
unify env rm row0.row_more
|
|
@@ -1748,11 +1760,11 @@
|
|
in
|
|
let md1 = rm1.desc and md2 = rm2.desc in
|
|
begin try
|
|
- set_more row1 r2;
|
|
- set_more row2 r1;
|
|
+ set_more row1 fixed1 r2;
|
|
+ set_more row2 fixed2 r1;
|
|
List.iter
|
|
(fun (l,f1,f2) ->
|
|
- try unify_row_field env row1.row_fixed row2.row_fixed l f1 f2
|
|
+ try unify_row_field env fixed1 fixed2 row1 row2 l f1 f2
|
|
with Unify trace ->
|
|
raise (Unify ((mkvariant [l,f1] true,
|
|
mkvariant [l,f2] true) :: trace)))
|
|
@@ -1761,13 +1773,13 @@
|
|
log_type rm1; rm1.desc <- md1; log_type rm2; rm2.desc <- md2; raise exn
|
|
end
|
|
|
|
-and unify_row_field env fixed1 fixed2 l f1 f2 =
|
|
+and unify_row_field env fixed1 fixed2 row1 row2 l f1 f2 =
|
|
let f1 = row_field_repr f1 and f2 = row_field_repr f2 in
|
|
if f1 == f2 then () else
|
|
match f1, f2 with
|
|
Rpresent(Some t1), Rpresent(Some t2) -> unify env t1 t2
|
|
| Rpresent None, Rpresent None -> ()
|
|
- | Reither(c1, tl1, m1, e1), Reither(c2, tl2, m2, e2) ->
|
|
+ | Reither(c1, tl1, m1, tp1, e1), Reither(c2, tl2, m2, tp2, e2) ->
|
|
if e1 == e2 then () else
|
|
let redo =
|
|
(m1 || m2) &&
|
|
@@ -1777,32 +1789,70 @@
|
|
List.iter (unify env t1) tl;
|
|
!e1 <> None || !e2 <> None
|
|
end in
|
|
- if redo then unify_row_field env fixed1 fixed2 l f1 f2 else
|
|
+ let redo =
|
|
+ redo || begin
|
|
+ if tp1 = [] && fixed1 then unify_pairs env tp2;
|
|
+ if tp2 = [] && fixed2 then unify_pairs env tp1;
|
|
+ !e1 <> None || !e2 <> None
|
|
+ end
|
|
+ in
|
|
+ if redo then unify_row_field env fixed1 fixed2 row1 row2 l f1 f2 else
|
|
let tl1 = List.map repr tl1 and tl2 = List.map repr tl2 in
|
|
let rec remq tl = function [] -> []
|
|
| ty :: tl' ->
|
|
if List.memq ty tl then remq tl tl' else ty :: remq tl tl'
|
|
in
|
|
let tl2' = remq tl2 tl1 and tl1' = remq tl1 tl2 in
|
|
+ let repr_pairs = List.map (fun (t1,t2) -> repr t1, repr t2) in
|
|
+ let tp1 = repr_pairs tp1 and tp2 = repr_pairs tp2 in
|
|
+ let rec rempq tp = function [] -> []
|
|
+ | (t1,t2 as p) :: tp' ->
|
|
+ if List.exists (fun (t1',t2') -> t1==t1' && t2==t2') (tp@tp') then
|
|
+ rempq tp tp'
|
|
+ else p :: rempq tp tp'
|
|
+ in
|
|
+ let tp1' =
|
|
+ if fixed2 then begin
|
|
+ delayed_conditionals :=
|
|
+ (!univar_pairs, tp1, l, row2) :: !delayed_conditionals;
|
|
+ []
|
|
+ end else rempq tp2 tp1
|
|
+ and tp2' =
|
|
+ if fixed1 then begin
|
|
+ delayed_conditionals :=
|
|
+ (!univar_pairs, tp2, l, row1) :: !delayed_conditionals;
|
|
+ []
|
|
+ end else rempq tp1 tp2
|
|
+ in
|
|
let e = ref None in
|
|
- let f1' = Reither(c1 || c2, tl1', m1 || m2, e)
|
|
- and f2' = Reither(c1 || c2, tl2', m1 || m2, e) in
|
|
- set_row_field e1 f1'; set_row_field e2 f2';
|
|
- | Reither(_, _, false, e1), Rabsent -> set_row_field e1 f2
|
|
- | Rabsent, Reither(_, _, false, e2) -> set_row_field e2 f1
|
|
+ let f1' = Reither(c1 || c2, tl1', m1 || m2, tp2', e)
|
|
+ and f2' = Reither(c1 || c2, tl2', m1 || m2, tp1', e) in
|
|
+ set_row_field e1 f1'; set_row_field e2 f2'
|
|
+ | Reither(_, _, false, _, e1), Rabsent -> set_row_field e1 f2
|
|
+ | Rabsent, Reither(_, _, false, _, e2) -> set_row_field e2 f1
|
|
| Rabsent, Rabsent -> ()
|
|
- | Reither(false, tl, _, e1), Rpresent(Some t2) when not fixed1 ->
|
|
+ | Reither(false, tl, _, tp, e1), Rpresent(Some t2) when not fixed1 ->
|
|
set_row_field e1 f2;
|
|
- (try List.iter (fun t1 -> unify env t1 t2) tl
|
|
+ begin try
|
|
+ List.iter (fun t1 -> unify env t1 t2) tl;
|
|
+ List.iter (fun (t1,t2) -> unify env t1 t2) tp
|
|
+ with exn -> e1 := None; raise exn
|
|
+ end
|
|
+ | Rpresent(Some t1), Reither(false, tl, _, tp, e2) when not fixed2 ->
|
|
+ set_row_field e2 f1;
|
|
+ begin try
|
|
+ List.iter (unify env t1) tl;
|
|
+ List.iter (fun (t1,t2) -> unify env t1 t2) tp
|
|
+ with exn -> e2 := None; raise exn
|
|
+ end
|
|
+ | Reither(true, [], _, tpl, e1), Rpresent None when not fixed1 ->
|
|
+ set_row_field e1 f2;
|
|
+ (try List.iter (fun (t1,t2) -> unify env t1 t2) tpl
|
|
with exn -> e1 := None; raise exn)
|
|
- | Rpresent(Some t1), Reither(false, tl, _, e2) when not fixed2 ->
|
|
+ | Rpresent None, Reither(true, [], _, tpl, e2) when not fixed2 ->
|
|
set_row_field e2 f1;
|
|
- (try List.iter (unify env t1) tl
|
|
+ (try List.iter (fun (t1,t2) -> unify env t1 t2) tpl
|
|
with exn -> e2 := None; raise exn)
|
|
- | Reither(true, [], _, e1), Rpresent None when not fixed1 ->
|
|
- set_row_field e1 f2
|
|
- | Rpresent None, Reither(true, [], _, e2) when not fixed2 ->
|
|
- set_row_field e2 f1
|
|
| _ -> raise (Unify [])
|
|
|
|
|
|
@@ -1920,6 +1970,166 @@
|
|
(* Matching between type schemes *)
|
|
(***********************************)
|
|
|
|
+(* Forward declaration (order should be reversed...) *)
|
|
+let equal' = ref (fun _ -> failwith "Ctype.equal'")
|
|
+
|
|
+let make_generics_univars tyl =
|
|
+ let polyvars = ref TypeSet.empty in
|
|
+ let rec make_rec ty =
|
|
+ let ty = repr ty in
|
|
+ if ty.level = generic_level then begin
|
|
+ if ty.desc = Tvar then begin
|
|
+ log_type ty;
|
|
+ ty.desc <- Tunivar;
|
|
+ polyvars := TypeSet.add ty !polyvars
|
|
+ end
|
|
+ else if ty.desc = Tunivar then set_level ty (generic_level - 1);
|
|
+ ty.level <- pivot_level - generic_level;
|
|
+ iter_type_expr make_rec ty
|
|
+ end
|
|
+ in
|
|
+ List.iter make_rec tyl;
|
|
+ List.iter unmark_type tyl;
|
|
+ !polyvars
|
|
+
|
|
+(* New version of moregeneral, using unification *)
|
|
+
|
|
+let copy_cond (p,tpl,l,row) =
|
|
+ let row =
|
|
+ match repr (copy (newgenty (Tvariant row))) with
|
|
+ {desc=Tvariant row} -> row
|
|
+ | _ -> assert false
|
|
+ and pairs =
|
|
+ List.map (fun (t1,t2) -> copy t1, copy t2) tpl in
|
|
+ (p, pairs, l, row)
|
|
+
|
|
+let get_row_field l row =
|
|
+ try row_field_repr (List.assoc l (row_repr row).row_fields)
|
|
+ with Not_found -> Rabsent
|
|
+
|
|
+let rec check_conditional_list env cdtls pattvars tpls =
|
|
+ match cdtls with
|
|
+ [] ->
|
|
+ let finished =
|
|
+ List.for_all (fun (_,t1,t2) -> !equal' env false [t1] [t2]) tpls in
|
|
+ if not finished then begin
|
|
+ let polyvars = make_generics_univars pattvars in
|
|
+ delayed_conditionals := [];
|
|
+ allowed_univars := polyvars;
|
|
+ List.iter (fun (pairs, ty1, ty2) -> unify_pairs env ty1 ty2 pairs)
|
|
+ tpls;
|
|
+ check_conditionals env polyvars !delayed_conditionals
|
|
+ end
|
|
+ | (pairs, tpl1, l, row2 as cond) :: cdtls ->
|
|
+ let cont = check_conditional_list env cdtls pattvars in
|
|
+ let tpl1 =
|
|
+ List.filter (fun (t1,t2) -> not (!equal' env false [t1] [t2])) tpl1 in
|
|
+ let included =
|
|
+ List.for_all
|
|
+ (fun (t1,t2) ->
|
|
+ List.exists
|
|
+ (fun (_,t1',t2') -> !equal' env false [t1;t2] [t1';t2'])
|
|
+ tpls)
|
|
+ tpl1 in
|
|
+ if included then cont tpls else
|
|
+ match get_row_field l row2 with
|
|
+ Rpresent _ ->
|
|
+ cont (List.map (fun (t1,t2) -> (pairs,t1,t2)) tpl1 @ tpls)
|
|
+ | Rabsent -> cont tpls
|
|
+ | Reither (c, tl2, _, _, _) ->
|
|
+ cont tpls;
|
|
+ if c && tl2 <> [] then () (* cannot succeed *) else
|
|
+ let (pairs, tpl1, l, row2) = copy_cond cond
|
|
+ and tpls = List.map (fun (p,t1,t2) -> p, copy t1, copy t2) tpls
|
|
+ and pattvars = List.map copy pattvars
|
|
+ and cdtls = List.map copy_cond cdtls in
|
|
+ cleanup_types ();
|
|
+ let tl2, tpl2, e2 =
|
|
+ match get_row_field l row2 with
|
|
+ Reither (c, tl2, _, tpl2, e2) -> tl2, tpl2, e2
|
|
+ | _ -> assert false
|
|
+ in
|
|
+ let snap = Btype.snapshot () in
|
|
+ let ok =
|
|
+ try
|
|
+ begin match tl2 with
|
|
+ [] ->
|
|
+ set_row_field e2 (Rpresent None)
|
|
+ | t::tl ->
|
|
+ set_row_field e2 (Rpresent (Some t));
|
|
+ List.iter (unify env t) tl
|
|
+ end;
|
|
+ List.iter (fun (t1,t2) -> unify_pairs env t1 t2 pairs) tpl2;
|
|
+ true
|
|
+ with exn ->
|
|
+ Btype.backtrack snap;
|
|
+ false
|
|
+ in
|
|
+ (* This is not [cont] : types have been copied *)
|
|
+ if ok then
|
|
+ check_conditional_list env cdtls pattvars
|
|
+ (List.map (fun (t1,t2) -> (pairs,t1,t2)) tpl1 @ tpls)
|
|
+
|
|
+and check_conditionals env polyvars cdtls =
|
|
+ let cdtls = List.map copy_cond cdtls in
|
|
+ let pattvars = ref [] in
|
|
+ TypeSet.iter
|
|
+ (fun ty ->
|
|
+ let ty = repr ty in
|
|
+ match ty.desc with
|
|
+ Tsubst ty ->
|
|
+ let ty = repr ty in
|
|
+ begin match ty.desc with
|
|
+ Tunivar ->
|
|
+ log_type ty;
|
|
+ ty.desc <- Tvar;
|
|
+ pattvars := ty :: !pattvars
|
|
+ | Ttuple [tv;_] ->
|
|
+ if tv.desc = Tunivar then
|
|
+ (log_type tv; tv.desc <- Tvar; pattvars := ty :: !pattvars)
|
|
+ else if tv.desc <> Tvar then assert false
|
|
+ | Tvar -> ()
|
|
+ | _ -> assert false
|
|
+ end
|
|
+ | _ -> ())
|
|
+ polyvars;
|
|
+ cleanup_types ();
|
|
+ check_conditional_list env cdtls !pattvars []
|
|
+
|
|
+
|
|
+(* Must empty univar_pairs first *)
|
|
+let unify_poly env polyvars subj patt =
|
|
+ let old_level = !current_level in
|
|
+ current_level := generic_level;
|
|
+ delayed_conditionals := [];
|
|
+ allowed_univars := polyvars;
|
|
+ try
|
|
+ unify env subj patt;
|
|
+ check_conditionals env polyvars !delayed_conditionals;
|
|
+ current_level := old_level;
|
|
+ allowed_univars := TypeSet.empty;
|
|
+ delayed_conditionals := []
|
|
+ with exn ->
|
|
+ current_level := old_level;
|
|
+ allowed_univars := TypeSet.empty;
|
|
+ delayed_conditionals := [];
|
|
+ raise exn
|
|
+
|
|
+let moregeneral env _ subj patt =
|
|
+ let old_level = !current_level in
|
|
+ current_level := generic_level;
|
|
+ let subj = instance subj
|
|
+ and patt = instance patt in
|
|
+ let polyvars = make_generics_univars [patt] in
|
|
+ current_level := old_level;
|
|
+ let snap = Btype.snapshot () in
|
|
+ try
|
|
+ unify_poly env polyvars subj patt;
|
|
+ true
|
|
+ with Unify _ ->
|
|
+ Btype.backtrack snap;
|
|
+ false
|
|
+
|
|
(*
|
|
Update the level of [ty]. First check that the levels of generic
|
|
variables from the subject are not lowered.
|
|
@@ -2072,35 +2282,101 @@
|
|
Rpresent(Some t1), Rpresent(Some t2) ->
|
|
moregen inst_nongen type_pairs env t1 t2
|
|
| Rpresent None, Rpresent None -> ()
|
|
- | Reither(false, tl1, _, e1), Rpresent(Some t2) when not univ ->
|
|
+ | Reither(false, tl1, _, [], e1), Rpresent(Some t2) when not univ ->
|
|
set_row_field e1 f2;
|
|
List.iter (fun t1 -> moregen inst_nongen type_pairs env t1 t2) tl1
|
|
- | Reither(c1, tl1, _, e1), Reither(c2, tl2, m2, e2) ->
|
|
+ | Reither(c1, tl1, _, tpl1, e1), Reither(c2, tl2, m2, tpl2, e2) ->
|
|
if e1 != e2 then begin
|
|
if c1 && not c2 then raise(Unify []);
|
|
- set_row_field e1 (Reither (c2, [], m2, e2));
|
|
- if List.length tl1 = List.length tl2 then
|
|
- List.iter2 (moregen inst_nongen type_pairs env) tl1 tl2
|
|
- else match tl2 with
|
|
- t2 :: _ ->
|
|
+ let tpl' = if tpl1 = [] then tpl2 else [] in
|
|
+ set_row_field e1 (Reither (c2, [], m2, tpl', e2));
|
|
+ begin match tl2 with
|
|
+ [t2] ->
|
|
List.iter (fun t1 -> moregen inst_nongen type_pairs env t1 t2)
|
|
tl1
|
|
- | [] ->
|
|
- if tl1 <> [] then raise (Unify [])
|
|
+ | _ ->
|
|
+ if List.length tl1 <> List.length tl2 then raise (Unify []);
|
|
+ List.iter2 (moregen inst_nongen type_pairs env) tl1 tl2
|
|
+ end;
|
|
+ if tpl1 <> [] then
|
|
+ delayed_conditionals :=
|
|
+ (!univar_pairs, tpl1, l, row2) :: !delayed_conditionals
|
|
end
|
|
- | Reither(true, [], _, e1), Rpresent None when not univ ->
|
|
+ | Reither(true, [], _, [], e1), Rpresent None when not univ ->
|
|
set_row_field e1 f2
|
|
- | Reither(_, _, _, e1), Rabsent when not univ ->
|
|
+ | Reither(_, _, _, [], e1), Rabsent when not univ ->
|
|
set_row_field e1 f2
|
|
| Rabsent, Rabsent -> ()
|
|
| _ -> raise (Unify []))
|
|
pairs
|
|
|
|
+let check_conditional env (pairs, tpl1, l, row2) tpls cont =
|
|
+ let tpl1 =
|
|
+ List.filter (fun (t1,t2) -> not (!equal' env false [t1] [t2])) tpl1 in
|
|
+ let included =
|
|
+ List.for_all
|
|
+ (fun (t1,t2) ->
|
|
+ List.exists (fun (t1',t2') -> !equal' env false [t1;t2] [t1';t2'])
|
|
+ tpls)
|
|
+ tpl1 in
|
|
+ if tpl1 = [] || included then cont tpls else
|
|
+ match get_row_field l row2 with
|
|
+ Rpresent _ -> cont (tpl1 @ tpls)
|
|
+ | Rabsent -> cont tpls
|
|
+ | Reither (c, tl2, _, tpl2, e2) ->
|
|
+ if not c || tl2 = [] then begin
|
|
+ let snap = Btype.snapshot () in
|
|
+ let ok =
|
|
+ try
|
|
+ begin match tl2 with
|
|
+ [] ->
|
|
+ set_row_field e2 (Rpresent None)
|
|
+ | t::tl ->
|
|
+ set_row_field e2 (Rpresent (Some t));
|
|
+ List.iter (unify env t) tl
|
|
+ end;
|
|
+ List.iter (fun (t1,t2) -> unify_pairs env t1 t2 pairs) tpl2;
|
|
+ true
|
|
+ with Unify _ -> false
|
|
+ in
|
|
+ if ok then cont (tpl1 @ tpls);
|
|
+ Btype.backtrack snap
|
|
+ end;
|
|
+ cont tpls
|
|
+
|
|
+let rec check_conditionals inst_nongen env cdtls tpls =
|
|
+ match cdtls with
|
|
+ [] ->
|
|
+ let tpls =
|
|
+ List.filter (fun (t1,t2) -> not (!equal' env false [t1] [t2])) tpls in
|
|
+ if tpls = [] then () else begin
|
|
+ delayed_conditionals := [];
|
|
+ let tl1, tl2 = List.split tpls in
|
|
+ let type_pairs = TypePairs.create 13 in
|
|
+ List.iter2 (moregen false type_pairs env) tl2 tl1;
|
|
+ check_conditionals inst_nongen env !delayed_conditionals []
|
|
+ end
|
|
+ | cdtl :: cdtls ->
|
|
+ check_conditional env cdtl tpls
|
|
+ (check_conditionals inst_nongen env cdtls)
|
|
+
|
|
+
|
|
(* Must empty univar_pairs first *)
|
|
let moregen inst_nongen type_pairs env patt subj =
|
|
univar_pairs := [];
|
|
- moregen inst_nongen type_pairs env patt subj
|
|
+ delayed_conditionals := [];
|
|
+ try
|
|
+ moregen inst_nongen type_pairs env patt subj;
|
|
+ check_conditionals inst_nongen env !delayed_conditionals [];
|
|
+ univar_pairs := [];
|
|
+ delayed_conditionals := []
|
|
+ with exn ->
|
|
+ univar_pairs := [];
|
|
+ delayed_conditionals := [];
|
|
+ raise exn
|
|
+
|
|
|
|
+(* old implementation
|
|
(*
|
|
Non-generic variable can be instanciated only if [inst_nongen] is
|
|
true. So, [inst_nongen] should be set to false if the subject might
|
|
@@ -2128,6 +2404,7 @@
|
|
in
|
|
current_level := old_level;
|
|
res
|
|
+*)
|
|
|
|
|
|
(* Alternative approach: "rigidify" a type scheme,
|
|
@@ -2296,30 +2573,36 @@
|
|
{desc=Tvariant row2} -> eqtype_row rename type_pairs subst env row1 row2
|
|
| _ -> raise Cannot_expand
|
|
with Cannot_expand ->
|
|
+ let eqtype_rec = eqtype rename type_pairs subst env in
|
|
let row1 = row_repr row1 and row2 = row_repr row2 in
|
|
let r1, r2, pairs = merge_row_fields row1.row_fields row2.row_fields in
|
|
if row1.row_closed <> row2.row_closed
|
|
|| not row1.row_closed && (r1 <> [] || r2 <> [])
|
|
|| filter_row_fields false (r1 @ r2) <> []
|
|
then raise (Unify []);
|
|
- if not (static_row row1) then
|
|
- eqtype rename type_pairs subst env row1.row_more row2.row_more;
|
|
+ if not (static_row row1) then eqtype_rec row1.row_more row2.row_more;
|
|
List.iter
|
|
(fun (_,f1,f2) ->
|
|
match row_field_repr f1, row_field_repr f2 with
|
|
Rpresent(Some t1), Rpresent(Some t2) ->
|
|
- eqtype rename type_pairs subst env t1 t2
|
|
- | Reither(true, [], _, _), Reither(true, [], _, _) ->
|
|
- ()
|
|
- | Reither(false, t1::tl1, _, _), Reither(false, t2::tl2, _, _) ->
|
|
- eqtype rename type_pairs subst env t1 t2;
|
|
+ eqtype_rec t1 t2
|
|
+ | Reither(true, [], _, tp1, _), Reither(true, [], _, tp2, _) ->
|
|
+ List.iter2
|
|
+ (fun (t1,t1') (t2,t2') -> eqtype_rec t1 t2; eqtype_rec t1' t2')
|
|
+ tp1 tp2
|
|
+ | Reither(false, t1::tl1, _, tpl1, _),
|
|
+ Reither(false, t2::tl2, _, tpl2, _) ->
|
|
+ eqtype_rec t1 t2;
|
|
+ List.iter2
|
|
+ (fun (t1,t1') (t2,t2') -> eqtype_rec t1 t2; eqtype_rec t1' t2')
|
|
+ tpl1 tpl2;
|
|
if List.length tl1 = List.length tl2 then
|
|
(* if same length allow different types (meaning?) *)
|
|
- List.iter2 (eqtype rename type_pairs subst env) tl1 tl2
|
|
+ List.iter2 eqtype_rec tl1 tl2
|
|
else begin
|
|
(* otherwise everything must be equal *)
|
|
- List.iter (eqtype rename type_pairs subst env t1) tl2;
|
|
- List.iter (fun t1 -> eqtype rename type_pairs subst env t1 t2) tl1
|
|
+ List.iter (eqtype_rec t1) tl2;
|
|
+ List.iter (fun t1 -> eqtype_rec t1 t2) tl1
|
|
end
|
|
| Rpresent None, Rpresent None -> ()
|
|
| Rabsent, Rabsent -> ()
|
|
@@ -2334,6 +2617,8 @@
|
|
with
|
|
Unify _ -> false
|
|
|
|
+let () = equal' := equal
|
|
+
|
|
(* Must empty univar_pairs first *)
|
|
let eqtype rename type_pairs subst env t1 t2 =
|
|
univar_pairs := [];
|
|
@@ -2770,14 +3055,14 @@
|
|
(fun (l,f as orig) -> match row_field_repr f with
|
|
Rpresent None ->
|
|
if posi then
|
|
- (l, Reither(true, [], false, ref None)), Unchanged
|
|
+ (l, Reither(true, [], false, [], ref None)), Unchanged
|
|
else
|
|
orig, Unchanged
|
|
| Rpresent(Some t) ->
|
|
let (t', c) = build_subtype env visited loops posi level' t in
|
|
if posi && level > 0 then begin
|
|
bound := t' :: !bound;
|
|
- (l, Reither(false, [t'], false, ref None)), c
|
|
+ (l, Reither(false, [t'], false, [], ref None)), c
|
|
end else
|
|
(l, Rpresent(Some t')), c
|
|
| _ -> assert false)
|
|
@@ -2960,11 +3245,11 @@
|
|
List.fold_left
|
|
(fun cstrs (_,f1,f2) ->
|
|
match row_field_repr f1, row_field_repr f2 with
|
|
- (Rpresent None|Reither(true,_,_,_)), Rpresent None ->
|
|
+ (Rpresent None|Reither(true,_,_,[],_)), Rpresent None ->
|
|
cstrs
|
|
| Rpresent(Some t1), Rpresent(Some t2) ->
|
|
subtype_rec env ((t1, t2)::trace) t1 t2 cstrs
|
|
- | Reither(false, t1::_, _, _), Rpresent(Some t2) ->
|
|
+ | Reither(false, t1::_, _, [], _), Rpresent(Some t2) ->
|
|
subtype_rec env ((t1, t2)::trace) t1 t2 cstrs
|
|
| Rabsent, _ -> cstrs
|
|
| _ -> raise Exit)
|
|
@@ -2977,11 +3262,11 @@
|
|
(fun cstrs (_,f1,f2) ->
|
|
match row_field_repr f1, row_field_repr f2 with
|
|
Rpresent None, Rpresent None
|
|
- | Reither(true,[],_,_), Reither(true,[],_,_)
|
|
+ | Reither(true,[],_,[],_), Reither(true,[],_,[],_)
|
|
| Rabsent, Rabsent ->
|
|
cstrs
|
|
| Rpresent(Some t1), Rpresent(Some t2)
|
|
- | Reither(false,[t1],_,_), Reither(false,[t2],_,_) ->
|
|
+ | Reither(false,[t1],_,[],_), Reither(false,[t2],_,[],_) ->
|
|
subtype_rec env ((t1, t2)::trace) t1 t2 cstrs
|
|
| _ -> raise Exit)
|
|
cstrs pairs
|
|
@@ -3079,16 +3364,26 @@
|
|
let fields = List.map
|
|
(fun (l,f) ->
|
|
let f = row_field_repr f in l,
|
|
- match f with Reither(b, ty::(_::_ as tyl), m, e) ->
|
|
- let tyl' =
|
|
- List.fold_left
|
|
- (fun tyl ty ->
|
|
- if List.exists (fun ty' -> equal env false [ty] [ty']) tyl
|
|
- then tyl else ty::tyl)
|
|
- [ty] tyl
|
|
+ match f with Reither(b, tyl, m, tp, e) ->
|
|
+ let rem_dbl eq l =
|
|
+ List.rev
|
|
+ (List.fold_left
|
|
+ (fun xs x -> if List.exists (eq x) xs then xs else x::xs)
|
|
+ [] l)
|
|
+ in
|
|
+ let tyl' = rem_dbl (fun t1 t2 -> equal env false [t1] [t2]) tyl
|
|
+ and tp' =
|
|
+ List.filter
|
|
+ (fun (ty1,ty2) -> not (equal env false [ty1] [ty2])) tp
|
|
+ in
|
|
+ let tp' =
|
|
+ rem_dbl
|
|
+ (fun (t1,t2) (t1',t2') -> equal env false [t1;t2] [t1';t2'])
|
|
+ tp'
|
|
in
|
|
- if List.length tyl' <= List.length tyl then
|
|
- let f = Reither(b, List.rev tyl', m, ref None) in
|
|
+ if List.length tyl' < List.length tyl
|
|
+ || List.length tp' < List.length tp then
|
|
+ let f = Reither(b, tyl', m, tp', ref None) in
|
|
set_row_field e f;
|
|
f
|
|
else f
|
|
@@ -3344,9 +3639,9 @@
|
|
List.iter
|
|
(fun (l,fi) ->
|
|
match row_field_repr fi with
|
|
- Reither (c, t1::(_::_ as tl), m, e) ->
|
|
+ Reither (c, t1::(_::_ as tl), m, tp, e) ->
|
|
List.iter (unify env t1) tl;
|
|
- set_row_field e (Reither (c, [t1], m, ref None))
|
|
+ set_row_field e (Reither (c, [t1], m, tp, ref None))
|
|
| _ ->
|
|
())
|
|
row.row_fields;
|
|
Index: typing/includecore.ml
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/typing/includecore.ml,v
|
|
retrieving revision 1.32
|
|
diff -u -r1.32 includecore.ml
|
|
--- typing/includecore.ml 8 Aug 2005 05:40:52 -0000 1.32
|
|
+++ typing/includecore.ml 2 Feb 2006 06:28:32 -0000
|
|
@@ -71,10 +71,10 @@
|
|
(fun (_, f1, f2) ->
|
|
match Btype.row_field_repr f1, Btype.row_field_repr f2 with
|
|
Rpresent(Some t1),
|
|
- (Rpresent(Some t2) | Reither(false, [t2], _, _)) ->
|
|
+ (Rpresent(Some t2) | Reither(false,[t2],_,[],_)) ->
|
|
to_equal := (t1,t2) :: !to_equal; true
|
|
- | Rpresent None, (Rpresent None | Reither(true, [], _, _)) -> true
|
|
- | Reither(c1,tl1,_,_), Reither(c2,tl2,_,_)
|
|
+ | Rpresent None, (Rpresent None | Reither(true,[],_,[],_)) -> true
|
|
+ | Reither(c1,tl1,_,[],_), Reither(c2,tl2,_,[],_)
|
|
when List.length tl1 = List.length tl2 && c1 = c2 ->
|
|
to_equal := List.combine tl1 tl2 @ !to_equal; true
|
|
| Rabsent, (Reither _ | Rabsent) -> true
|
|
Index: typing/oprint.ml
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/typing/oprint.ml,v
|
|
retrieving revision 1.22
|
|
diff -u -r1.22 oprint.ml
|
|
--- typing/oprint.ml 23 Mar 2005 03:08:37 -0000 1.22
|
|
+++ typing/oprint.ml 2 Feb 2006 06:28:33 -0000
|
|
@@ -223,14 +223,18 @@
|
|
print_fields rest ppf []
|
|
| (s, t) :: l ->
|
|
fprintf ppf "%s : %a;@ %a" s print_out_type t (print_fields rest) l
|
|
-and print_row_field ppf (l, opt_amp, tyl) =
|
|
+and print_row_field ppf (l, opt_amp, tyl, tpl) =
|
|
let pr_of ppf =
|
|
if opt_amp then fprintf ppf " of@ &@ "
|
|
else if tyl <> [] then fprintf ppf " of@ "
|
|
- else fprintf ppf ""
|
|
- in
|
|
- fprintf ppf "@[<hv 2>`%s%t%a@]" l pr_of (print_typlist print_out_type " &")
|
|
- tyl
|
|
+ and pr_tp ppf (t1,t2) =
|
|
+ fprintf ppf "@[<hv 2>%a =@ %a@]"
|
|
+ print_out_type t1
|
|
+ print_out_type t2
|
|
+ in
|
|
+ fprintf ppf "@[<hv 2>`%s%t%a%a@]" l pr_of
|
|
+ (print_typlist print_out_type " &") tyl
|
|
+ (print_list_init pr_tp (fun ppf -> fprintf ppf " &@ ")) tpl
|
|
and print_typlist print_elem sep ppf =
|
|
function
|
|
[] -> ()
|
|
Index: typing/outcometree.mli
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/typing/outcometree.mli,v
|
|
retrieving revision 1.14
|
|
diff -u -r1.14 outcometree.mli
|
|
--- typing/outcometree.mli 23 Mar 2005 03:08:37 -0000 1.14
|
|
+++ typing/outcometree.mli 2 Feb 2006 06:28:33 -0000
|
|
@@ -61,7 +61,8 @@
|
|
bool * out_variant * bool * (string list) option
|
|
| Otyp_poly of string list * out_type
|
|
and out_variant =
|
|
- | Ovar_fields of (string * bool * out_type list) list
|
|
+ | Ovar_fields of
|
|
+ (string * bool * out_type list * (out_type * out_type) list ) list
|
|
| Ovar_name of out_ident * out_type list
|
|
|
|
type out_class_type =
|
|
Index: typing/parmatch.ml
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/typing/parmatch.ml,v
|
|
retrieving revision 1.70
|
|
diff -u -r1.70 parmatch.ml
|
|
--- typing/parmatch.ml 24 Mar 2005 17:20:54 -0000 1.70
|
|
+++ typing/parmatch.ml 2 Feb 2006 06:28:33 -0000
|
|
@@ -568,11 +568,11 @@
|
|
List.fold_left
|
|
(fun nm (tag,f) ->
|
|
match Btype.row_field_repr f with
|
|
- | Reither(_, _, false, e) ->
|
|
+ | Reither(_, _, false, _, e) ->
|
|
(* m=false means that this tag is not explicitly matched *)
|
|
Btype.set_row_field e Rabsent;
|
|
None
|
|
- | Rabsent | Reither (_, _, true, _) | Rpresent _ -> nm)
|
|
+ | Rabsent | Reither (_, _, true, _, _) | Rpresent _ -> nm)
|
|
row.row_name row.row_fields in
|
|
if not row.row_closed || nm != row.row_name then begin
|
|
(* this unification cannot fail *)
|
|
@@ -605,8 +605,8 @@
|
|
List.for_all
|
|
(fun (tag,f) ->
|
|
match Btype.row_field_repr f with
|
|
- Rabsent | Reither(_, _, false, _) -> true
|
|
- | Reither (_, _, true, _)
|
|
+ Rabsent | Reither(_, _, false, _, _) -> true
|
|
+ | Reither (_, _, true, _, _)
|
|
(* m=true, do not discard matched tags, rather warn *)
|
|
| Rpresent _ -> List.mem tag fields)
|
|
row.row_fields
|
|
@@ -739,7 +739,7 @@
|
|
match Btype.row_field_repr f with
|
|
Rabsent (* | Reither _ *) -> others
|
|
(* This one is called after erasing pattern info *)
|
|
- | Reither (c, _, _, _) -> make_other_pat tag c :: others
|
|
+ | Reither (c, _, _, _, _) -> make_other_pat tag c :: others
|
|
| Rpresent arg -> make_other_pat tag (arg = None) :: others)
|
|
[] row.row_fields
|
|
with
|
|
Index: typing/printtyp.ml
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/typing/printtyp.ml,v
|
|
retrieving revision 1.140
|
|
diff -u -r1.140 printtyp.ml
|
|
--- typing/printtyp.ml 4 Jan 2006 16:55:50 -0000 1.140
|
|
+++ typing/printtyp.ml 2 Feb 2006 06:28:33 -0000
|
|
@@ -157,9 +157,12 @@
|
|
and raw_field ppf = function
|
|
Rpresent None -> fprintf ppf "Rpresent None"
|
|
| Rpresent (Some t) -> fprintf ppf "@[<1>Rpresent(Some@,%a)@]" raw_type t
|
|
- | Reither (c,tl,m,e) ->
|
|
- fprintf ppf "@[<hov1>Reither(%b,@,%a,@,%b,@,@[<1>ref%t@])@]" c
|
|
- raw_type_list tl m
|
|
+ | Reither (c,tl,m,tpl,e) ->
|
|
+ fprintf ppf "@[<hov1>Reither(%b,@,%a,@,%b,@,%a,@,@[<1>ref%t@])@]"
|
|
+ c raw_type_list tl m
|
|
+ (raw_list
|
|
+ (fun ppf (t1,t2) ->
|
|
+ fprintf ppf "@[%a,@,%a@]" raw_type t1 raw_type t2)) tpl
|
|
(fun ppf ->
|
|
match !e with None -> fprintf ppf " None"
|
|
| Some f -> fprintf ppf "@,@[<1>(%a)@]" raw_field f)
|
|
@@ -219,8 +222,9 @@
|
|
List.for_all
|
|
(fun (_, f) ->
|
|
match row_field_repr f with
|
|
- | Reither(c, l, _, _) ->
|
|
- row.row_closed && if c then l = [] else List.length l = 1
|
|
+ | Reither(c, l, _, pl, _) ->
|
|
+ row.row_closed && pl = [] &&
|
|
+ if c then l = [] else List.length l = 1
|
|
| _ -> true)
|
|
row.row_fields
|
|
|
|
@@ -392,13 +396,16 @@
|
|
|
|
and tree_of_row_field sch (l, f) =
|
|
match row_field_repr f with
|
|
- | Rpresent None | Reither(true, [], _, _) -> (l, false, [])
|
|
- | Rpresent(Some ty) -> (l, false, [tree_of_typexp sch ty])
|
|
- | Reither(c, tyl, _, _) ->
|
|
- if c (* contradiction: un constructeur constant qui a un argument *)
|
|
- then (l, true, tree_of_typlist sch tyl)
|
|
- else (l, false, tree_of_typlist sch tyl)
|
|
- | Rabsent -> (l, false, [] (* une erreur, en fait *))
|
|
+ | Rpresent None | Reither(true, [], _, [], _) -> (l, false, [], [])
|
|
+ | Rpresent(Some ty) -> (l, false, [tree_of_typexp sch ty], [])
|
|
+ | Reither(c, tyl, _, tpl, _) ->
|
|
+ let ttpl =
|
|
+ List.map
|
|
+ (fun (t1,t2) -> tree_of_typexp sch t1, tree_of_typexp sch t2)
|
|
+ tpl
|
|
+ in
|
|
+ (l, c && tpl = [], tree_of_typlist sch tyl, ttpl)
|
|
+ | Rabsent -> (l, false, [], [] (* une erreur, en fait *))
|
|
|
|
and tree_of_typlist sch tyl =
|
|
List.map (tree_of_typexp sch) tyl
|
|
Index: typing/typeclass.ml
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/typing/typeclass.ml,v
|
|
retrieving revision 1.85
|
|
diff -u -r1.85 typeclass.ml
|
|
--- typing/typeclass.ml 22 Jul 2005 06:42:36 -0000 1.85
|
|
+++ typing/typeclass.ml 2 Feb 2006 06:28:33 -0000
|
|
@@ -727,7 +727,7 @@
|
|
{pexp_loc = loc; pexp_desc =
|
|
Pexp_match({pexp_loc = loc; pexp_desc =
|
|
Pexp_ident(Longident.Lident"*opt*")},
|
|
- scases)} in
|
|
+ scases, false)} in
|
|
let sfun =
|
|
{pcl_loc = scl.pcl_loc; pcl_desc =
|
|
Pcl_fun(l, None, {ppat_loc = loc; ppat_desc = Ppat_var"*opt*"},
|
|
Index: typing/typecore.ml
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/typing/typecore.ml,v
|
|
retrieving revision 1.178
|
|
diff -u -r1.178 typecore.ml
|
|
--- typing/typecore.ml 6 Jan 2006 02:25:37 -0000 1.178
|
|
+++ typing/typecore.ml 2 Feb 2006 06:28:33 -0000
|
|
@@ -156,15 +156,21 @@
|
|
let field = row_field tag row in
|
|
begin match field with
|
|
| Rabsent -> assert false
|
|
- | Reither (true, [], _, e) when not row.row_closed ->
|
|
- set_row_field e (Rpresent None)
|
|
- | Reither (false, ty::tl, _, e) when not row.row_closed ->
|
|
+ | Reither (true, [], _, tpl, e) when not row.row_closed ->
|
|
+ set_row_field e (Rpresent None);
|
|
+ List.iter
|
|
+ (fun (t1,t2) -> unify_pat pat.pat_env {pat with pat_type=t1} t2)
|
|
+ tpl
|
|
+ | Reither (false, ty::tl, _, tpl, e) when not row.row_closed ->
|
|
set_row_field e (Rpresent (Some ty));
|
|
+ List.iter
|
|
+ (fun (t1,t2) -> unify_pat pat.pat_env {pat with pat_type=t1} t2)
|
|
+ tpl;
|
|
begin match opat with None -> assert false
|
|
| Some pat -> List.iter (unify_pat pat.pat_env pat) (ty::tl)
|
|
end
|
|
- | Reither (c, l, true, e) when not row.row_fixed ->
|
|
- set_row_field e (Reither (c, [], false, ref None))
|
|
+ | Reither (c, l, true, tpl, e) when not row.row_fixed ->
|
|
+ set_row_field e (Reither (c, [], false, [], ref None))
|
|
| _ -> ()
|
|
end;
|
|
(* Force check of well-formedness *)
|
|
@@ -307,13 +313,13 @@
|
|
match row_field_repr f with
|
|
Rpresent None ->
|
|
(l,None) :: pats,
|
|
- (l, Reither(true,[], true, ref None)) :: fields
|
|
+ (l, Reither(true,[], true, [], ref None)) :: fields
|
|
| Rpresent (Some ty) ->
|
|
bound := ty :: !bound;
|
|
(l, Some {pat_desc=Tpat_any; pat_loc=Location.none; pat_env=env;
|
|
pat_type=ty})
|
|
:: pats,
|
|
- (l, Reither(false, [ty], true, ref None)) :: fields
|
|
+ (l, Reither(false, [ty], true, [], ref None)) :: fields
|
|
| _ -> pats, fields)
|
|
([],[]) fields in
|
|
let row =
|
|
@@ -337,6 +343,18 @@
|
|
pat pats in
|
|
rp { r with pat_loc = loc }
|
|
|
|
+let rec flatten_or_pat pat =
|
|
+ match pat.pat_desc with
|
|
+ Tpat_or (p1, p2, _) ->
|
|
+ flatten_or_pat p1 @ flatten_or_pat p2
|
|
+ | _ ->
|
|
+ [pat]
|
|
+
|
|
+let all_variants pat =
|
|
+ List.for_all
|
|
+ (function {pat_desc=Tpat_variant _} -> true | _ -> false)
|
|
+ (flatten_or_pat pat)
|
|
+
|
|
let rec find_record_qual = function
|
|
| [] -> None
|
|
| (Longident.Ldot (modname, _), _) :: _ -> Some modname
|
|
@@ -423,7 +441,7 @@
|
|
let arg = may_map (type_pat env) sarg in
|
|
let arg_type = match arg with None -> [] | Some arg -> [arg.pat_type] in
|
|
let row = { row_fields =
|
|
- [l, Reither(arg = None, arg_type, true, ref None)];
|
|
+ [l, Reither(arg = None, arg_type, true, [], ref None)];
|
|
row_bound = arg_type;
|
|
row_closed = false;
|
|
row_more = newvar ();
|
|
@@ -788,7 +806,7 @@
|
|
newty (Tarrow(p, type_option (newvar ()), type_approx env e, Cok))
|
|
| Pexp_function (p,_,(_,e)::_) ->
|
|
newty (Tarrow(p, newvar (), type_approx env e, Cok))
|
|
- | Pexp_match (_, (_,e)::_) -> type_approx env e
|
|
+ | Pexp_match (_, (_,e)::_, false) -> type_approx env e
|
|
| Pexp_try (e, _) -> type_approx env e
|
|
| Pexp_tuple l -> newty (Ttuple(List.map (type_approx env) l))
|
|
| Pexp_ifthenelse (_,e,_) -> type_approx env e
|
|
@@ -939,17 +957,26 @@
|
|
exp_loc = sexp.pexp_loc;
|
|
exp_type = ty_res;
|
|
exp_env = env }
|
|
- | Pexp_match(sarg, caselist) ->
|
|
+ | Pexp_match(sarg, caselist, multi) ->
|
|
let arg = type_exp env sarg in
|
|
let ty_res = newvar() in
|
|
let cases, partial =
|
|
- type_cases env arg.exp_type ty_res (Some sexp.pexp_loc) caselist
|
|
+ type_cases env arg.exp_type ty_res (Some sexp.pexp_loc) caselist ~multi
|
|
in
|
|
re {
|
|
exp_desc = Texp_match(arg, cases, partial);
|
|
exp_loc = sexp.pexp_loc;
|
|
exp_type = ty_res;
|
|
exp_env = env }
|
|
+ | Pexp_multifun caselist ->
|
|
+ let ty_arg = newvar() and ty_res = newvar() in
|
|
+ let cases, partial =
|
|
+ type_cases env ty_arg ty_res (Some sexp.pexp_loc) caselist ~multi:true
|
|
+ in
|
|
+ { exp_desc = Texp_function (cases, partial);
|
|
+ exp_loc = sexp.pexp_loc;
|
|
+ exp_type = newty (Tarrow ("", ty_arg, ty_res, Cok));
|
|
+ exp_env = env }
|
|
| Pexp_try(sbody, caselist) ->
|
|
let body = type_exp env sbody in
|
|
let cases, _ =
|
|
@@ -1758,7 +1785,7 @@
|
|
{pexp_loc = loc; pexp_desc =
|
|
Pexp_match({pexp_loc = loc; pexp_desc =
|
|
Pexp_ident(Longident.Lident"*opt*")},
|
|
- scases)} in
|
|
+ scases, false)} in
|
|
let sfun =
|
|
{pexp_loc = sexp.pexp_loc; pexp_desc =
|
|
Pexp_function(l, None,[{ppat_loc = loc; ppat_desc = Ppat_var"*opt*"},
|
|
@@ -1864,7 +1891,8 @@
|
|
|
|
(* Typing of match cases *)
|
|
|
|
-and type_cases ?in_function env ty_arg ty_res partial_loc caselist =
|
|
+and type_cases ?in_function ?(multi=false)
|
|
+ env ty_arg ty_res partial_loc caselist =
|
|
let ty_arg' = newvar () in
|
|
let pattern_force = ref [] in
|
|
let pat_env_list =
|
|
@@ -1898,10 +1926,64 @@
|
|
let cases =
|
|
List.map2
|
|
(fun (pat, ext_env) (spat, sexp) ->
|
|
- let exp = type_expect ?in_function ext_env sexp ty_res in
|
|
- (pat, exp))
|
|
- pat_env_list caselist
|
|
- in
|
|
+ let add_variant_case lab row ty_res ty_res' =
|
|
+ let fi = List.assoc lab (row_repr row).row_fields in
|
|
+ begin match row_field_repr fi with
|
|
+ Reither (c, _, m, _, e) ->
|
|
+ let row' =
|
|
+ { row_fields =
|
|
+ [lab, Reither(c,[],false,[ty_res,ty_res'], ref None)];
|
|
+ row_more = newvar (); row_bound = [ty_res; ty_res'];
|
|
+ row_closed = false; row_fixed = false; row_name = None }
|
|
+ in
|
|
+ unify_pat ext_env {pat with pat_type= newty (Tvariant row)}
|
|
+ (newty (Tvariant row'))
|
|
+ | _ ->
|
|
+ unify_exp ext_env
|
|
+ { exp_desc = Texp_tuple []; exp_type = ty_res;
|
|
+ exp_env = ext_env; exp_loc = sexp.pexp_loc }
|
|
+ ty_res'
|
|
+ end
|
|
+ in
|
|
+ pat,
|
|
+ match pat.pat_desc with
|
|
+ _ when multi && all_variants pat ->
|
|
+ let ty_res' = newvar () in
|
|
+ List.iter
|
|
+ (function {pat_desc=Tpat_variant(lab,_,row)} ->
|
|
+ add_variant_case lab row ty_res ty_res'
|
|
+ | _ -> assert false)
|
|
+ (flatten_or_pat pat);
|
|
+ type_expect ?in_function ext_env sexp ty_res'
|
|
+ | Tpat_alias (p, id) when multi && all_variants p ->
|
|
+ let vd = Env.find_value (Path.Pident id) ext_env in
|
|
+ let row' =
|
|
+ match repr vd.val_type with
|
|
+ {desc=Tvariant row'} -> row'
|
|
+ | _ -> assert false
|
|
+ in
|
|
+ begin_def ();
|
|
+ let tv = newvar () in
|
|
+ let env = Env.add_value id {vd with val_type=tv} ext_env in
|
|
+ let exp = type_exp env sexp in
|
|
+ end_def ();
|
|
+ generalize exp.exp_type;
|
|
+ generalize tv;
|
|
+ List.iter
|
|
+ (function {pat_desc=Tpat_variant(lab,_,row)}, [tv'; ty'] ->
|
|
+ let fi' = List.assoc lab (row_repr row').row_fields in
|
|
+ let row' =
|
|
+ {row' with row_fields=[lab,fi']; row_more=newvar()} in
|
|
+ unify_pat ext_env {pat with pat_type=tv'}
|
|
+ (newty (Tvariant row'));
|
|
+ add_variant_case lab row ty_res ty'
|
|
+ | _ -> assert false)
|
|
+ (List.map (fun p -> p, instance_list [tv; exp.exp_type])
|
|
+ (flatten_or_pat p));
|
|
+ {exp with exp_type = instance exp.exp_type}
|
|
+ | _ ->
|
|
+ type_expect ?in_function ext_env sexp ty_res)
|
|
+ pat_env_list caselist in
|
|
let partial =
|
|
match partial_loc with None -> Partial
|
|
| Some loc -> Parmatch.check_partial loc cases
|
|
Index: typing/typedecl.ml
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/typing/typedecl.ml,v
|
|
retrieving revision 1.75
|
|
diff -u -r1.75 typedecl.ml
|
|
--- typing/typedecl.ml 16 Aug 2005 00:48:56 -0000 1.75
|
|
+++ typing/typedecl.ml 2 Feb 2006 06:28:33 -0000
|
|
@@ -432,8 +432,10 @@
|
|
match Btype.row_field_repr f with
|
|
Rpresent (Some ty) ->
|
|
compute_same ty
|
|
- | Reither (_, tyl, _, _) ->
|
|
- List.iter compute_same tyl
|
|
+ | Reither (_, tyl, _, tpl, _) ->
|
|
+ List.iter compute_same tyl;
|
|
+ List.iter (compute_variance_rec true true true)
|
|
+ (List.map fst tpl @ List.map snd tpl)
|
|
| _ -> ())
|
|
row.row_fields;
|
|
compute_same row.row_more
|
|
@@ -856,8 +858,8 @@
|
|
explain row.row_fields
|
|
(fun (l,f) -> match Btype.row_field_repr f with
|
|
Rpresent (Some t) -> t
|
|
- | Reither (_,[t],_,_) -> t
|
|
- | Reither (_,tl,_,_) -> Btype.newgenty (Ttuple tl)
|
|
+ | Reither (_,[t],_,_,_) -> t
|
|
+ | Reither (_,tl,_,_,_) -> Btype.newgenty (Ttuple tl)
|
|
| _ -> Btype.newgenty (Ttuple[]))
|
|
"case" (fun (lab,_) -> "`" ^ lab ^ " of ")
|
|
| _ -> trivial ty'
|
|
Index: typing/types.ml
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/typing/types.ml,v
|
|
retrieving revision 1.25
|
|
diff -u -r1.25 types.ml
|
|
--- typing/types.ml 9 Dec 2004 12:40:53 -0000 1.25
|
|
+++ typing/types.ml 2 Feb 2006 06:28:33 -0000
|
|
@@ -48,7 +48,9 @@
|
|
|
|
and row_field =
|
|
Rpresent of type_expr option
|
|
- | Reither of bool * type_expr list * bool * row_field option ref
|
|
+ | Reither of
|
|
+ bool * type_expr list * bool *
|
|
+ (type_expr * type_expr) list * row_field option ref
|
|
| Rabsent
|
|
|
|
and abbrev_memo =
|
|
Index: typing/types.mli
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/typing/types.mli,v
|
|
retrieving revision 1.25
|
|
diff -u -r1.25 types.mli
|
|
--- typing/types.mli 9 Dec 2004 12:40:53 -0000 1.25
|
|
+++ typing/types.mli 2 Feb 2006 06:28:33 -0000
|
|
@@ -47,7 +47,9 @@
|
|
|
|
and row_field =
|
|
Rpresent of type_expr option
|
|
- | Reither of bool * type_expr list * bool * row_field option ref
|
|
+ | Reither of
|
|
+ bool * type_expr list * bool *
|
|
+ (type_expr * type_expr) list * row_field option ref
|
|
(* 1st true denotes a constant constructor *)
|
|
(* 2nd true denotes a tag in a pattern matching, and
|
|
is erased later *)
|
|
Index: typing/typetexp.ml
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/typing/typetexp.ml,v
|
|
retrieving revision 1.54
|
|
diff -u -r1.54 typetexp.ml
|
|
--- typing/typetexp.ml 22 Jul 2005 06:42:36 -0000 1.54
|
|
+++ typing/typetexp.ml 2 Feb 2006 06:28:33 -0000
|
|
@@ -207,9 +207,9 @@
|
|
match Btype.row_field_repr f with
|
|
| Rpresent (Some ty) ->
|
|
bound := ty :: !bound;
|
|
- Reither(false, [ty], false, ref None)
|
|
+ Reither(false, [ty], false, [], ref None)
|
|
| Rpresent None ->
|
|
- Reither (true, [], false, ref None)
|
|
+ Reither (true, [], false, [], ref None)
|
|
| _ -> f)
|
|
row.row_fields
|
|
in
|
|
@@ -273,13 +273,16 @@
|
|
(l, f) :: fields
|
|
in
|
|
let rec add_field fields = function
|
|
- Rtag (l, c, stl) ->
|
|
+ Rtag (l, c, stl, stpl) ->
|
|
name := None;
|
|
let f = match present with
|
|
Some present when not (List.mem l present) ->
|
|
- let tl = List.map (transl_type env policy) stl in
|
|
- bound := tl @ !bound;
|
|
- Reither(c, tl, false, ref None)
|
|
+ let transl_list = List.map (transl_type env policy) in
|
|
+ let tl = transl_list stl in
|
|
+ let stpl1, stpl2 = List.split stpl in
|
|
+ let tpl1 = transl_list stpl1 and tpl2 = transl_list stpl2 in
|
|
+ bound := tl @ tpl1 @ tpl2 @ !bound;
|
|
+ Reither(c, tl, false, List.combine tpl1 tpl2, ref None)
|
|
| _ ->
|
|
if List.length stl > 1 || c && stl <> [] then
|
|
raise(Error(styp.ptyp_loc, Present_has_conjunction l));
|
|
@@ -311,9 +314,9 @@
|
|
begin match f with
|
|
Rpresent(Some ty) ->
|
|
bound := ty :: !bound;
|
|
- Reither(false, [ty], false, ref None)
|
|
+ Reither(false, [ty], false, [], ref None)
|
|
| Rpresent None ->
|
|
- Reither(true, [], false, ref None)
|
|
+ Reither(true, [], false, [], ref None)
|
|
| _ ->
|
|
assert false
|
|
end
|
|
@@ -406,7 +409,8 @@
|
|
{row with row_fixed=true;
|
|
row_fields = List.map
|
|
(fun (s,f as p) -> match Btype.row_field_repr f with
|
|
- Reither (c, tl, m, r) -> s, Reither (c, tl, true, r)
|
|
+ Reither (c, tl, m, tpl, r) ->
|
|
+ s, Reither (c, tl, true, tpl, r)
|
|
| _ -> p)
|
|
row.row_fields};
|
|
Btype.iter_row make_fixed_univars row
|
|
Index: typing/unused_var.ml
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/typing/unused_var.ml,v
|
|
retrieving revision 1.5
|
|
diff -u -r1.5 unused_var.ml
|
|
--- typing/unused_var.ml 4 Jan 2006 16:55:50 -0000 1.5
|
|
+++ typing/unused_var.ml 2 Feb 2006 06:28:33 -0000
|
|
@@ -122,9 +122,11 @@
|
|
| Pexp_apply (e, lel) ->
|
|
expression ppf tbl e;
|
|
List.iter (fun (_, e) -> expression ppf tbl e) lel;
|
|
- | Pexp_match (e, pel) ->
|
|
+ | Pexp_match (e, pel, _) ->
|
|
expression ppf tbl e;
|
|
match_pel ppf tbl pel;
|
|
+ | Pexp_multifun pel ->
|
|
+ match_pel ppf tbl pel;
|
|
| Pexp_try (e, pel) ->
|
|
expression ppf tbl e;
|
|
match_pel ppf tbl pel;
|
|
Index: bytecomp/matching.ml
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/bytecomp/matching.ml,v
|
|
retrieving revision 1.67
|
|
diff -u -r1.67 matching.ml
|
|
--- bytecomp/matching.ml 7 Sep 2005 16:07:48 -0000 1.67
|
|
+++ bytecomp/matching.ml 2 Feb 2006 06:28:33 -0000
|
|
@@ -1991,7 +1991,7 @@
|
|
List.iter
|
|
(fun (_, f) ->
|
|
match Btype.row_field_repr f with
|
|
- Rabsent | Reither(true, _::_, _, _) -> ()
|
|
+ Rabsent | Reither(true, _::_, _, _, _) -> ()
|
|
| _ -> incr num_constr)
|
|
row.row_fields
|
|
else
|
|
Index: toplevel/genprintval.ml
|
|
===================================================================
|
|
RCS file: /net/yquem/devel/caml/repository/csl/toplevel/genprintval.ml,v
|
|
retrieving revision 1.38
|
|
diff -u -r1.38 genprintval.ml
|
|
--- toplevel/genprintval.ml 13 Jun 2005 04:55:53 -0000 1.38
|
|
+++ toplevel/genprintval.ml 2 Feb 2006 06:28:33 -0000
|
|
@@ -293,7 +293,7 @@
|
|
| (l, f) :: fields ->
|
|
if Btype.hash_variant l = tag then
|
|
match Btype.row_field_repr f with
|
|
- | Rpresent(Some ty) | Reither(_,[ty],_,_) ->
|
|
+ | Rpresent(Some ty) | Reither(_,[ty],_,_,_) ->
|
|
let args =
|
|
tree_of_val (depth - 1) (O.field obj 1) ty in
|
|
Oval_variant (l, Some args)
|