@@ -91,6 +91,25 @@ let lift_warn at t env zs =
9191
9292(* Subtyping *)
9393
94+ let rec has_typs_typ ps = function
95+ | VarT (_ ) -> false
96+ | PrimT (_ ) -> false
97+ | StrT (tr ) -> List. exists (fun (_ , t ) -> has_typs_typ ps t) tr
98+ | FunT (aks , td , ExT(_ , tr ), e ) ->
99+ (match e with
100+ | Implicit | Explicit Pure ->
101+ has_typs_typ (List. map (fun p -> AppT (p, varTs aks)) ps) tr
102+ | Explicit Impure -> false )
103+ | TypT (ExT(_ , p )) -> List. mem p ps
104+ | WrapT (_ ) -> false
105+ | LamT (_ ) -> false
106+ | AppT (_ ) -> false
107+ | TupT (_ ) -> false
108+ | DotT (_ ) -> false
109+ | RecT (_ ) -> false
110+ | InferT (_ ) -> false
111+
112+
94113let resolve_typ z t =
95114 Trace. sub (lazy (" [resolve_typ] z = " ^ string_of_norm_typ (InferT (z))));
96115 Trace. sub (lazy (" [resolve_typ] t = " ^ string_of_norm_typ t));
@@ -101,12 +120,36 @@ let unify_typ t1 t2 =
101120 Trace. sub (lazy (" [unify_typ] t2 = " ^ string_of_norm_typ t2));
102121 unify_typ t1 t2
103122
123+ let rec psubst p t =
124+ match p with
125+ | VarT (a , k ) -> a, t
126+ | AppT (p' , ts ) -> psubst p' (LamT (List. map unvarT ts, t))
127+ | _ -> assert false
128+
104129
105130let rec sub_typ env t1 t2 ps =
106131 Trace. sub (lazy (" [sub_typ] t1 = " ^ string_of_norm_typ t1));
107132 Trace. sub (lazy (" [sub_typ] t2 = " ^ string_of_norm_typ t2));
108133 Trace. sub (lazy (" [sub_typ] ps = " ^
109134 String. concat " , " (List. map string_of_norm_typ ps)));
135+ let ts', zs', t2, ps =
136+ if ps <> [] then
137+ let su, zs' = match_typ env t1 t2 ps in
138+ Trace. sub (lazy (" [sub_typ] su = " ^
139+ String. concat " , " (List. map (fun (p , t ) -> Printf. sprintf " [= %s] - [= %s]\n " (string_of_typ p) (string_of_typ t)) su)));
140+ let t2 = subst_typ (List. map (fun (p , t ) -> psubst p t) su) t2 in
141+ let ps' = List. filter (fun p -> List. mem_assoc p su) ps in
142+ let ts' = List. map (fun p -> List. assoc p su) ps' in
143+ let ps = List. filter (fun p -> not (List. mem_assoc p su)) ps in
144+ if ps <> [] then begin
145+ Trace. sub (lazy (" [sub_typ] unmatched ps = " ^
146+ String. concat " , " (List. map string_of_norm_typ ps)));
147+ raise Not_found
148+ end ;
149+ ts', zs', t2, ps
150+ else
151+ [] , [] , t2, ps
152+ in
110153 let e1 = IL. VarE (" x" ) in
111154 let ts, zs, e =
112155 match norm_typ t1, freshen_typ env (norm_typ t2) with
@@ -267,7 +310,7 @@ let rec sub_typ env t1 t2 ps =
267310 Trace. sub (lazy (" [sub_typ] done ts = " ^
268311 String. concat " , " (List. map string_of_norm_typ ts)));
269312 Trace. sub (lazy (" [sub_typ] done x -> " ^ IL. string_of_exp e));
270- ts, zs, IL. LamE (" x" , erase_typ t1, e)
313+ ts' @ ts, zs' @ zs, IL. LamE (" x" , erase_typ t1, e)
271314
272315and sub_extyp env s1 s2 ps =
273316 Trace. sub (lazy (" [sub_extyp] s1 = " ^ string_of_norm_extyp s1));
@@ -306,12 +349,6 @@ and sub_row env tr1 tr2 ps =
306349 try sub_typ env t1 t2 ps with
307350 | Sub e -> raise (Sub (Struct (l, e)))
308351 in
309- let rec psubst p t =
310- match p with
311- | VarT (a , k ) -> a, t
312- | AppT (p' , ts ) -> psubst p' (LamT (List. map unvarT ts, t))
313- | _ -> assert false
314- in
315352 let su = List. map2 psubst (Lib.List. take (List. length ts1) ps) ts1 in
316353 let ps' = Lib.List. drop (List. length ts1) ps in
317354 let ts2, zs2, fs = sub_row env tr1 (subst_row su tr2') ps' in
@@ -341,3 +378,86 @@ and equal_row env tr1 tr2 ps =
341378 let _, zs2, _ =
342379 try sub_row env tr2 tr1 ps with Sub e -> raise (Sub (Right e)) in
343380 zs1 @ zs2
381+
382+ and match_typ env t1 t2 ps =
383+ let t2 = norm_typ t2 in
384+ Trace. sub (lazy (" [match_typ] t1 = " ^ string_of_norm_typ t1));
385+ Trace. sub (lazy (" [match_typ] t2 = " ^ string_of_typ t2));
386+ Trace. sub (lazy (" [match_typ] ps = " ^
387+ String. concat " , " (List. map string_of_norm_typ ps)));
388+ if not (has_typs_typ ps t2) then [] , [] else
389+ match norm_typ t1, freshen_typ env t2 with
390+ | t1 , FunT (aks21 , t21 , ExT(aks22 , t22 ), Implicit) ->
391+ assert (aks22 = [] );
392+ let su, zs = match_typ (add_typs aks21 env) t1 t22 ps in
393+ List. map (fun (p , t ) -> (p, LamT (aks21, t))) su, lift env zs
394+
395+ | FunT (aks11 , t11 , ExT(aks12 , t12 ), Implicit), t2 ->
396+ assert (aks12 = [] );
397+ let ts1, zs1 = guess_typs (Env. domain_typ env) aks11 in
398+ let t1' = subst_typ (subst aks11 ts1) t12 in
399+ let su, zs2 = match_typ env t1' t2 ps in
400+ su, zs1 @ zs2
401+
402+ | TypT (s1 ), TypT (s2 ) ->
403+ (match s1, s2 with
404+ | ExT (aks1 , t ), ExT ([] , p ) when List. mem p ps ->
405+ if aks1 <> [] || not (! undecidable_flag || is_small_typ t) then
406+ raise (Sub (Mismatch (t1, t2)));
407+ [(p, t)], []
408+ | _ ->
409+ [] , [] )
410+
411+ | StrT (tr1 ), StrT (tr2 ) ->
412+ match_row env tr1 tr2 ps
413+
414+ | FunT (aks1 , t11 , s1 , Explicit p1 ), FunT (aks2 , t21 , s2 , Explicit p2 ) ->
415+ if p1 = Impure && p2 = Pure then raise (Sub (FunEffect (p1, p2)));
416+ if p1 <> Pure || p2 <> Pure then
417+ [] , []
418+ else
419+ let env' = add_typs aks2 env in
420+ let ts1, zs1, f1 =
421+ try sub_typ env' t21 t11 (varTs aks1) with Sub e ->
422+ raise (Sub (FunParam e)) in
423+ let ps' = List. map (fun p -> AppT (p, varTs aks2)) ps in
424+ let su, zs2 =
425+ try match_extyp env' (subst_extyp (subst aks1 ts1) s1) s2 ps'
426+ with Sub e -> raise (Sub (FunResult e)) in
427+ List. map (function (AppT(p , _ ), t ) -> (p, LamT (aks2, t))
428+ | _ -> assert false ) su, lift env (zs1 @ zs2)
429+
430+ | _ ->
431+ [] , []
432+
433+ and match_extyp env s1 s2 ps =
434+ let ExT (aks2, t2) = freshen_extyp env s2 in
435+ let ExT (aks1, t1) = freshen_extyp (add_typs aks2 env) s1 in
436+ match aks1, aks2 with
437+ | [] , [] ->
438+ match_typ env t1 t2 ps
439+ | _ ->
440+ [] , []
441+
442+ and match_row env tr1 tr2 ps =
443+ match tr2 with
444+ | [] ->
445+ [] , []
446+ | (l , t2 )::tr2' ->
447+ let t1, zs, app =
448+ try List. assoc l tr1, [] , fun f l x -> IL. AppE (f, IL. DotE (x, l)) with
449+ | Not_found ->
450+ if is_base_typ t2 && is_small_typ t2
451+ then
452+ let t, zs = guess_typ (Env. domain_typ env) BaseK in
453+ let s = ExT ([] , t) in
454+ TypT (s), zs, fun f _ _ -> IL. AppE (f, IL. LamE (" _" , erase_extyp s, IL. TupE [] ))
455+ else
456+ raise (Sub (Struct (l, Missing )));
457+ in
458+ let su1, zs1 =
459+ try match_typ env t1 t2 ps with
460+ | Sub e -> raise (Sub (Struct (l, e)))
461+ in
462+ let su2, zs2 = match_row env tr1 (subst_row (List. map (fun (p , t ) -> psubst p t) su1) tr2') ps in
463+ su1 @ su2, zs @ zs1 @ zs2
0 commit comments