| 253 |
|
|
| 254 |
(* II. Build skeleton *) |
(* II. Build skeleton *) |
| 255 |
|
|
| 256 |
|
module Fv = StringSet |
| 257 |
|
|
| 258 |
let rec expr { loc = loc; descr = d } = |
let rec expr { loc = loc; descr = d } = |
| 259 |
let td = |
let (fv,td) = |
| 260 |
match d with |
match d with |
| 261 |
| Var s -> Typed.Var s |
| Var s -> (Fv.singleton s, Typed.Var s) |
| 262 |
| Apply (e1,e2) -> Typed.Apply (expr e1, expr e2) |
| Apply (e1,e2) -> |
| 263 |
|
let (fv1,e1) = expr e1 and (fv2,e2) = expr e2 in |
| 264 |
|
(Fv.union fv1 fv2, Typed.Apply (e1,e2)) |
| 265 |
| Abstraction a -> |
| Abstraction a -> |
| 266 |
|
let iface = List.map (fun (t1,t2) -> (typ t1, typ t2)) a.fun_iface in |
| 267 |
|
let t = List.fold_left |
| 268 |
|
(fun accu (t1,t2) -> Types.cap accu (Types.arrow t1 t2)) |
| 269 |
|
Types.any iface in |
| 270 |
|
let (fv0,body) = branches a.fun_body in |
| 271 |
|
let fv = match a.fun_name with |
| 272 |
|
| None -> fv0 |
| 273 |
|
| Some f -> Fv.remove f fv0 in |
| 274 |
|
(fv, |
| 275 |
Typed.Abstraction |
Typed.Abstraction |
| 276 |
{ Typed.fun_name = a.fun_name; |
{ Typed.fun_name = a.fun_name; |
| 277 |
Typed.fun_iface = |
Typed.fun_iface = iface; |
| 278 |
List.map (fun (t1,t2) -> (typ t1, typ t2)) a.fun_iface; |
Typed.fun_body = body; |
| 279 |
Typed.fun_body = |
Typed.fun_typ = t; |
| 280 |
branches a.fun_body |
Typed.fun_fv = Fv.elements fv0 |
| 281 |
} |
} |
| 282 |
| Cst c -> Typed.Cst c |
) |
| 283 |
| Pair (e1,e2) -> Typed.Pair (expr e1, expr e2) |
| Cst c -> (Fv.empty, Typed.Cst c) |
| 284 |
| RecordLitt r -> Typed.RecordLitt (List.map (fun (l,e) -> (l, expr e)) r) |
| Pair (e1,e2) -> |
| 285 |
| Op (o,e) -> Typed.Op (o, expr e) |
let (fv1,e1) = expr e1 and (fv2,e2) = expr e2 in |
| 286 |
| Match (e,b) -> Typed.Match (expr e, branches b) |
(Fv.union fv1 fv2, Typed.Pair (e1,e2)) |
| 287 |
| Map (e,b) -> Typed.Map (expr e, branches b) |
| RecordLitt r -> |
| 288 |
|
(* XXX TODO: check that no label appears twice *) |
| 289 |
|
let fv = ref Fv.empty in |
| 290 |
|
let r = List.map |
| 291 |
|
(fun (l,e) -> |
| 292 |
|
let (fv2,e) = expr e in |
| 293 |
|
fv := Fv.union !fv fv2; |
| 294 |
|
(l,e) |
| 295 |
|
) r in |
| 296 |
|
(!fv, Typed.RecordLitt r) |
| 297 |
|
| Op (o,e) -> |
| 298 |
|
let (fv,e) = expr e in (fv, Typed.Op (o,e)) |
| 299 |
|
| Match (e,b) -> |
| 300 |
|
let (fv1,e) = expr e |
| 301 |
|
and (fv2,b) = branches b in |
| 302 |
|
(Fv.union fv1 fv2, Typed.Match (e, b)) |
| 303 |
|
| Map (e,b) -> |
| 304 |
|
let (fv1,e) = expr e |
| 305 |
|
and (fv2,b) = branches b in |
| 306 |
|
(Fv.union fv1 fv2, Typed.Map (e, b)) |
| 307 |
in |
in |
| 308 |
{ Typed.loc = loc; |
fv, |
| 309 |
|
{ Typed.exp_loc = loc; |
| 310 |
Typed.exp_typ = Types.empty; |
Typed.exp_typ = Types.empty; |
| 311 |
Typed.exp_descr = td; |
Typed.exp_descr = td; |
|
Typed.fv = [] (* XXX TODO *) |
|
| 312 |
} |
} |
| 313 |
|
|
| 314 |
and branches b = List.map branch b |
and branches b = |
| 315 |
and branch (p,e) = |
let fv = ref Fv.empty in |
| 316 |
{ Typed.used = false; |
let b = List.map |
| 317 |
|
(fun (p,e) -> |
| 318 |
|
let (fv2,e) = expr e in |
| 319 |
|
fv := Fv.union !fv fv2; |
| 320 |
|
{ Typed.br_used = false; |
| 321 |
Typed.br_typ = Types.empty; |
Typed.br_typ = Types.empty; |
| 322 |
Typed.br_pat = pat p; |
Typed.br_pat = pat p; |
| 323 |
Typed.br_body = expr e } |
Typed.br_body = e } |
| 324 |
|
) b in |
| 325 |
|
(!fv,b) |
| 326 |
|
|
| 327 |
|
module Env = StringMap |
| 328 |
|
|
| 329 |
|
open Typed |
| 330 |
|
|
| 331 |
|
let rec compute_type env e = |
| 332 |
|
let d = compute_type' e.exp_loc env e.exp_descr in |
| 333 |
|
e.exp_typ <- Types.cup e.exp_typ d; |
| 334 |
|
d |
| 335 |
|
|
| 336 |
|
and compute_type' loc env = function |
| 337 |
|
| Var s -> Env.find s env |
| 338 |
|
| Apply (e1,e2) -> |
| 339 |
|
let t1 = compute_type env e1 and t2 = compute_type env e2 in |
| 340 |
|
Types.apply t1 t2 |
| 341 |
|
| Abstraction a -> |
| 342 |
|
let env = match a.fun_name with |
| 343 |
|
| None -> env |
| 344 |
|
| Some f -> Env.add f a.fun_typ env in |
| 345 |
|
List.iter (fun (t1,t2) -> |
| 346 |
|
let t = type_branches env (Types.descr t1) a.fun_body in |
| 347 |
|
if not (Types.subtype t (Types.descr t2)) then |
| 348 |
|
failwith "Constraint not satisfied" |
| 349 |
|
) a.fun_iface; |
| 350 |
|
a.fun_typ |
| 351 |
|
| Cst c -> Types.constant c |
| 352 |
|
| Pair (e1,e2) -> |
| 353 |
|
let t1 = compute_type env e1 and t2 = compute_type env e2 in |
| 354 |
|
let t1 = Types.cons t1 and t2 = Types.cons t2 in |
| 355 |
|
Types.times t1 t2 |
| 356 |
|
| RecordLitt r -> |
| 357 |
|
List.fold_left |
| 358 |
|
(fun accu (l,e) -> |
| 359 |
|
let t = compute_type env e in |
| 360 |
|
let t = Types.record l false (Types.cons t) in |
| 361 |
|
Types.cap accu t |
| 362 |
|
) Types.Record.any r |
| 363 |
|
| Op (op,e) -> assert false |
| 364 |
|
| Match (e,b) -> |
| 365 |
|
let t = compute_type env e in |
| 366 |
|
type_branches env t b |
| 367 |
|
| Map (e,b) -> assert false |
| 368 |
|
|
| 369 |
|
and type_branches env targ branches = |
| 370 |
|
if Types.is_empty targ then Types.empty |
| 371 |
|
else branches_aux env targ Types.empty branches |
| 372 |
|
|
| 373 |
|
and branches_aux env targ tres = function |
| 374 |
|
| [] -> failwith "Non-exhaustive pattern matching" |
| 375 |
|
| b :: rem -> |
| 376 |
|
let p = b.br_pat in |
| 377 |
|
let acc = Types.descr (Patterns.accept p) in |
| 378 |
|
|
| 379 |
|
let targ' = Types.cap targ acc in |
| 380 |
|
if Types.is_empty targ' |
| 381 |
|
then branches_aux env targ tres rem |
| 382 |
|
else |
| 383 |
|
( b.br_used <- true; |
| 384 |
|
let res = Patterns.filter targ' p in |
| 385 |
|
let env' = List.fold_left |
| 386 |
|
(fun env (x,t) -> Env.add x (Types.descr t) env) |
| 387 |
|
env res in |
| 388 |
|
let t = compute_type env' b.br_body in |
| 389 |
|
branches_aux env (Types.diff targ acc) (Types.cup t tres) rem |
| 390 |
|
) |
| 391 |
|
|
| 392 |
|
|
|
let compute_type t = failwith "Not yet implemented" |
|