@@ -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));
@@ -290,18 +333,11 @@ and sub_row env tr1 tr2 ps =
290333 | [] ->
291334 [] , [] , []
292335 | (l , t2 )::tr2' ->
293- Trace. sub (lazy (" [sub_row] l = " ^ l));
294336 let ts1, zs1, f =
295337 try sub_typ env (List. assoc l tr1) t2 ps with
296338 | Not_found -> raise (Sub (Struct (l, Missing )))
297339 | Sub e -> raise (Sub (Struct (l, e)))
298340 in
299- let rec psubst p t =
300- match p with
301- | VarT (a , k ) -> a, t
302- | AppT (p' , ts ) -> psubst p' (LamT (List. map unvarT ts, t))
303- | _ -> assert false
304- in
305341 let su = List. map2 psubst (Lib.List. take (List. length ts1) ps) ts1 in
306342 let ps' = Lib.List. drop (List. length ts1) ps in
307343 let ts2, zs2, fs = sub_row env tr1 (subst_row su tr2') ps' in
@@ -331,3 +367,76 @@ and equal_row env tr1 tr2 ps =
331367 let _, zs2, _ =
332368 try sub_row env tr2 tr1 ps with Sub e -> raise (Sub (Right e)) in
333369 zs1 @ zs2
370+
371+ and match_typ env t1 t2 ps =
372+ let t2 = norm_typ t2 in
373+ Trace. sub (lazy (" [match_typ] t1 = " ^ string_of_norm_typ t1));
374+ Trace. sub (lazy (" [match_typ] t2 = " ^ string_of_typ t2));
375+ Trace. sub (lazy (" [match_typ] ps = " ^
376+ String. concat " , " (List. map string_of_norm_typ ps)));
377+ if not (has_typs_typ ps t2) then [] , [] else
378+ match norm_typ t1, freshen_typ env t2 with
379+ | t1 , FunT (aks21 , t21 , ExT(aks22 , t22 ), Implicit) ->
380+ assert (aks22 = [] );
381+ let su, zs = match_typ (add_typs aks21 env) t1 t22 ps in
382+ List. map (fun (p , t ) -> (p, LamT (aks21, t))) su, lift env zs
383+
384+ | FunT (aks11 , t11 , ExT(aks12 , t12 ), Implicit), t2 ->
385+ assert (aks12 = [] );
386+ let ts1, zs1 = guess_typs (Env. domain_typ env) aks11 in
387+ let t1' = subst_typ (subst aks11 ts1) t12 in
388+ let su, zs2 = match_typ env t1' t2 ps in
389+ su, zs1 @ zs2
390+
391+ | TypT (s1 ), TypT (s2 ) ->
392+ (match s1, s2 with
393+ | ExT (aks1 , t ), ExT ([] , p ) when List. mem p ps ->
394+ if aks1 <> [] || not (! undecidable_flag || is_small_typ t) then
395+ raise (Sub (Mismatch (t1, t2)));
396+ [(p, t)], []
397+ | _ ->
398+ [] , [] )
399+
400+ | StrT (tr1 ), StrT (tr2 ) ->
401+ match_row env tr1 tr2 ps
402+
403+ | FunT (aks1 , t11 , s1 , Explicit p1 ), FunT (aks2 , t21 , s2 , Explicit p2 ) ->
404+ if p1 = Impure && p2 = Pure then raise (Sub (FunEffect (p1, p2)));
405+ if p1 <> Pure || p2 <> Pure then
406+ [] , []
407+ else
408+ let env' = add_typs aks2 env in
409+ let ts1, zs1, f1 =
410+ try sub_typ env' t21 t11 (varTs aks1) with Sub e ->
411+ raise (Sub (FunParam e)) in
412+ let ps' = List. map (fun p -> AppT (p, varTs aks2)) ps in
413+ let su, zs2 =
414+ try match_extyp env' (subst_extyp (subst aks1 ts1) s1) s2 ps'
415+ with Sub e -> raise (Sub (FunResult e)) in
416+ List. map (function (AppT(p , _ ), t ) -> (p, LamT (aks2, t))
417+ | _ -> assert false ) su, lift env (zs1 @ zs2)
418+
419+ | _ ->
420+ [] , []
421+
422+ and match_extyp env s1 s2 ps =
423+ let ExT (aks2, t2) = freshen_extyp env s2 in
424+ let ExT (aks1, t1) = freshen_extyp (add_typs aks2 env) s1 in
425+ match aks1, aks2 with
426+ | [] , [] ->
427+ match_typ env t1 t2 ps
428+ | _ ->
429+ [] , []
430+
431+ and match_row env tr1 tr2 ps =
432+ match tr2 with
433+ | [] ->
434+ [] , []
435+ | (l , t2 )::tr2' ->
436+ let su1, zs1 =
437+ try match_typ env (List. assoc l tr1) t2 ps with
438+ | Not_found -> raise (Sub (Struct (l, Missing )))
439+ | Sub e -> raise (Sub (Struct (l, e)))
440+ in
441+ let su2, zs2 = match_row env tr1 (subst_row (List. map (fun (p , t ) -> psubst p t) su1) tr2') ps in
442+ su1 @ su2, zs1 @ zs2
0 commit comments