| 127 |
] |
] |
| 128 |
type result = (capture, source) sm |
type result = (capture, source) sm |
| 129 |
|
|
| 130 |
|
type 'a line = (result * 'a, Types.descr) sm |
| 131 |
type nf = { |
type nf = { |
| 132 |
v : fv; |
v : fv; |
| 133 |
a : Types.descr; |
a : Types.descr; |
| 134 |
basic : (result, Types.descr) sm; |
basic : unit line; |
| 135 |
prod : (result * Types.descr * node sl * node sl) sl; |
prod : (node sl * node sl) line; |
| 136 |
record: (result * Types.descr * (Types.label, node sl) sm) sl; |
record: ((Types.label, node sl) sm) line |
| 137 |
|
} |
| 138 |
|
|
| 139 |
|
type 'a nline = (result * 'a) list |
| 140 |
|
type record = |
| 141 |
|
[ `Success |
| 142 |
|
| `Fail |
| 143 |
|
| `Dispatch of (nf * record) list |
| 144 |
|
| `Label of Types.label * (nf * record) list * record ] |
| 145 |
|
type normal = { |
| 146 |
|
nbasic : Types.descr nline; |
| 147 |
|
nprod : (nf * nf) nline; |
| 148 |
|
nrecord: record nline |
| 149 |
} |
} |
| 150 |
|
|
| 151 |
let empty = { v = []; a = Types.empty; basic = []; prod = []; record = [] } |
let empty = { v = []; a = Types.empty; basic = []; prod = []; record = [] } |
| 153 |
|
|
| 154 |
|
|
| 155 |
let restrict t nf = |
let restrict t nf = |
| 156 |
let map_filter f l = |
let rec filter = function |
| 157 |
let g accu x = match f x with Some y -> y::accu | None -> accu in |
| (key,acc) :: rem -> |
| 158 |
SortedList.from_list (List.fold_left g [] l) in |
let acc = Types.cap t acc in |
| 159 |
|
if Types.is_empty acc then filter rem else (key,acc) :: (filter rem) |
| 160 |
let aux_basic (res,bt) = |
| [] -> [] |
| 161 |
let bt = Types.cap t bt in |
in |
|
if Types.is_empty bt then None else Some (res,bt) in |
|
|
|
|
|
let aux_prod (res,bt,p,q) = |
|
|
let bt = Types.cap t bt in |
|
|
if Types.is_empty bt then None else Some (res,bt,p,q) in |
|
|
|
|
|
let aux_record (res,bt,r) = |
|
|
let bt = Types.cap t bt in |
|
|
if Types.is_empty bt then None else Some (res,bt,r) in |
|
|
|
|
| 162 |
{ v = nf.v; |
{ v = nf.v; |
| 163 |
a = Types.cap t nf.a; |
a = Types.cap t nf.a; |
| 164 |
basic = map_filter aux_basic nf.basic; |
basic = filter nf.basic; |
| 165 |
prod = map_filter aux_prod nf.prod; |
prod = filter nf.prod; |
| 166 |
record = map_filter aux_record nf.record; |
record = filter nf.record; |
| 167 |
} |
} |
| 168 |
|
|
| 169 |
let fus = SortedMap.union_disj |
let fus = SortedMap.union_disj |
| 170 |
let slcup = SortedList.cup |
let slcup = SortedList.cup |
| 171 |
|
|
| 172 |
let cap nf1 nf2 = |
let cap nf1 nf2 = |
| 173 |
let aux f x1 x2 = |
let merge f lines1 lines2 = |
| 174 |
SortedList.from_list |
let m = |
| 175 |
(List.fold_left (fun accu a -> List.fold_left (f a) accu x2) [] x1) in |
List.fold_left |
| 176 |
|
(fun accu ((res1,x1),acc1) -> |
| 177 |
let aux_basic (res1,t1) accu (res2,t2) = |
List.fold_left |
| 178 |
let t = Types.cap t1 t2 in |
(fun accu ((res2,x2),acc2) -> |
| 179 |
if Types.is_empty t then accu |
let acc = Types.cap acc1 acc2 in |
| 180 |
else (fus res1 res2, t)::accu in |
if Types.is_empty acc then accu |
| 181 |
|
else ((fus res1 res2, f x1 x2),acc) :: accu |
| 182 |
let aux_prod (res1,t1,p1,q1) accu (res2,t2,p2,q2) = |
) accu lines2 |
| 183 |
let t = Types.cap t1 t2 in |
) [] lines1 in |
| 184 |
if Types.is_empty t then accu |
SortedMap.from_list Types.cup m |
| 185 |
else (fus res1 res2, t, slcup p1 p2, slcup q1 q2)::accu in |
in |
| 186 |
|
let merge_basic () () = () |
| 187 |
let aux_record (res1,t1,r1) accu (res2,t2,r2) = |
and merge_prod (p1,q1) (p2,q2) = slcup p1 p1, slcup q1 q2 |
| 188 |
let t = Types.cap t1 t2 in |
and merge_record r1 r2 = SortedMap.union slcup r1 r2 in |
|
if Types.is_empty t then accu |
|
|
else (fus res1 res2, t, SortedMap.union slcup r1 r2) |
|
|
::accu in |
|
|
|
|
| 189 |
{ v = SortedList.cup nf1.v nf2.v; |
{ v = SortedList.cup nf1.v nf2.v; |
| 190 |
a = Types.cap nf1.a nf2.a; |
a = Types.cap nf1.a nf2.a; |
| 191 |
basic = SortedMap.from_sorted_list Types.cup |
basic = merge merge_basic nf1.basic nf2.basic; |
| 192 |
(aux aux_basic nf1.basic nf2.basic); |
prod = merge merge_prod nf1.prod nf2.prod; |
| 193 |
prod = aux aux_prod nf1.prod nf2.prod; |
record = merge merge_record nf1.record nf2.record; |
|
record = aux aux_record nf1.record nf2.record; |
|
| 194 |
} |
} |
| 195 |
|
|
| 196 |
|
|
| 197 |
|
|
| 198 |
let cup acc1 nf1 nf2 = |
let cup acc1 nf1 nf2 = |
| 199 |
let nf2 = restrict (Types.neg acc1) nf2 in |
let nf2 = restrict (Types.neg acc1) nf2 in |
| 200 |
{ v = SortedList.cup nf1.v nf2.v; |
{ v = nf1.v; (* = nf2.v *) |
| 201 |
a = Types.cup nf1.a nf2.a; |
a = Types.cup nf1.a nf2.a; |
| 202 |
basic = SortedMap.union Types.cup nf1.basic nf2.basic; |
basic = SortedMap.union Types.cup nf1.basic nf2.basic; |
| 203 |
prod = SortedList.cup nf1.prod nf2.prod; |
prod = SortedMap.union Types.cup nf1.prod nf2.prod; |
| 204 |
record = SortedList.cup nf1.record nf2.record; |
record = SortedMap.union Types.cup nf1.record nf2.record; |
| 205 |
} |
} |
| 206 |
|
|
| 207 |
let times acc p q = |
let times acc p q = |
| 211 |
{ empty with |
{ empty with |
| 212 |
v = SortedList.cup p.fv q.fv; |
v = SortedList.cup p.fv q.fv; |
| 213 |
a = acc; |
a = acc; |
| 214 |
prod = [ src, acc, [p], [q] ] } |
prod = [ (src, ([p], [q])), acc ] } |
| 215 |
|
|
| 216 |
let record acc l p = |
let record acc l p = |
| 217 |
let src = List.map (fun v -> (v, `Field l)) p.fv in |
let src = List.map (fun v -> (v, `Field l)) p.fv in |
| 218 |
{ empty with |
{ empty with |
| 219 |
v = p.fv; |
v = p.fv; |
| 220 |
a = acc; |
a = acc; |
| 221 |
record = [ src, acc, [l,[p]] ] } |
record = [ (src, [l,[p]]), acc ] } |
| 222 |
|
|
| 223 |
let any = |
let any = |
| 224 |
{ v = []; |
{ v = []; |
| 225 |
a = Types.any; |
a = Types.any; |
| 226 |
basic = [ [], any_basic ]; |
basic = [ ([],()), any_basic ]; |
| 227 |
prod = [ [], Types.Product.any,[],[] ]; |
prod = [ ([],([],[])), Types.Product.any ]; |
| 228 |
record = [ [], Types.Record.any,[] ]; |
record = [ ([],[]), Types.Record.any ]; |
| 229 |
} |
} |
| 230 |
|
|
| 231 |
let capture x = |
let capture x = |
| 232 |
let l = [x,`Catch] in |
let l = [x,`Catch] in |
| 233 |
{ v = [x]; |
{ v = [x]; |
| 234 |
a = Types.any; |
a = Types.any; |
| 235 |
basic = [ l, any_basic ]; |
basic = [ (l,()), any_basic ]; |
| 236 |
prod = [ l, Types.Product.any,[],[] ]; |
prod = [ (l,([],[])), Types.Product.any ]; |
| 237 |
record = [ l, Types.Record.any,[] ]; |
record = [ (l,[]), Types.Record.any ]; |
| 238 |
} |
} |
| 239 |
|
|
| 240 |
let constant x c = |
let constant x c = |
| 241 |
let l = [x,`Const c] in |
let l = [x,`Const c] in |
| 242 |
{ v = [x]; |
{ v = [x]; |
| 243 |
a = Types.any; |
a = Types.any; |
| 244 |
basic = [ l, any_basic ]; |
basic = [ (l,()), any_basic ]; |
| 245 |
prod = [ l, Types.Product.any,[],[] ]; |
prod = [ (l,([],[])), Types.Product.any ]; |
| 246 |
record = [ l, Types.Record.any,[] ]; |
record = [ (l,[]), Types.Record.any ]; |
| 247 |
} |
} |
| 248 |
|
|
| 249 |
let constr t = |
let constr t = |
| 250 |
{ v = []; |
{ v = []; |
| 251 |
a = t; |
a = t; |
| 252 |
basic = [ [], Types.cap t any_basic ]; |
basic = [ ([],()), Types.cap t any_basic ]; |
| 253 |
prod = [ [], Types.cap t Types.Product.any,[],[] ]; |
prod = [ ([],([],[])), Types.cap t Types.Product.any ]; |
| 254 |
record = [ [], Types.cap t Types.Record.any,[] ]; |
record = [ ([],[]), Types.cap t Types.Record.any ]; |
| 255 |
} |
} |
| 256 |
|
|
| 257 |
(* Put a pattern in normal form *) |
(* Put a pattern in normal form *) |
| 278 |
masks : (mask * int) list; |
masks : (mask * int) list; |
| 279 |
basic : (Types.descr * (result option list)) list; |
basic : (Types.descr * (result option list)) list; |
| 280 |
prod : prod; |
prod : prod; |
| 281 |
record: record; |
record: record option; |
| 282 |
} |
} |
| 283 |
and prod = disp * (mask * disp * (mask * prod_result) list) list |
and prod = disp * (mask * disp * (mask * prod_result) list) list |
| 284 |
and prod_result = (result * (int * int)) option list |
and prod_result = (result * (int * int)) option list |
| 292 |
and disp = Types.descr * nf SortedList.t |
and disp = Types.descr * nf SortedList.t |
| 293 |
end |
end |
| 294 |
|
|
| 295 |
|
let normal nf = |
| 296 |
|
let basic = |
| 297 |
|
List.map (fun ((res,()),acc) -> (res,acc)) |
| 298 |
|
|
| 299 |
|
and prod = |
| 300 |
|
let line accu (((res,(pl,ql)),acc)) = |
| 301 |
|
let p = bigcap pl and q = bigcap ql in |
| 302 |
|
let aux accu (t1,t2) = (res,(restrict t1 p,restrict t2 q))::accu in |
| 303 |
|
List.fold_left aux accu (Types.Product.normal acc) in |
| 304 |
|
List.fold_left line [] |
| 305 |
|
|
| 306 |
|
and record = |
| 307 |
|
let rec aux nr fields = |
| 308 |
|
match (nr,fields) with |
| 309 |
|
| (`Success, []) -> `Success |
| 310 |
|
| (`Fail,_) -> `Fail |
| 311 |
|
| (`Success, (l2,pl)::fields) -> |
| 312 |
|
`Label (l2, [bigcap pl, aux nr fields], `Fail) |
| 313 |
|
| (`Label (l1, _, _), (l2,pl)::fields) when l2 < l1 -> |
| 314 |
|
`Label (l2, [bigcap pl, aux nr fields], `Fail) |
| 315 |
|
| (`Label (l1, pr, _), (l2,pl)::fields) when l1 = l2 -> |
| 316 |
|
let p = bigcap pl in |
| 317 |
|
let pr = |
| 318 |
|
List.map (fun (t,x) -> (restrict t p, aux x fields)) pr in |
| 319 |
|
`Label (l1, pr, `Fail) |
| 320 |
|
| (`Label (l1, pr, ab),_) -> |
| 321 |
|
let pr = |
| 322 |
|
List.map (fun (t,x) -> (constr t, aux x fields)) pr in |
| 323 |
|
`Label (l1, pr, aux ab fields) |
| 324 |
|
in |
| 325 |
|
|
| 326 |
|
let line accu ((res,fields),acc) = |
| 327 |
|
let nr = Types.Record.normal acc in |
| 328 |
|
let x = aux nr fields in |
| 329 |
|
match x with |
| 330 |
|
| `Fail -> accu |
| 331 |
|
| x -> (res,x) :: accu in |
| 332 |
|
List.fold_left line [] |
| 333 |
|
in |
| 334 |
|
{ nbasic = basic nf.basic; |
| 335 |
|
nprod = prod nf.prod; |
| 336 |
|
nrecord = record nf.record; |
| 337 |
|
} |
| 338 |
|
|
| 339 |
let collect f pp = |
let collect f pp = |
| 340 |
let aux accu (res,x) = (f x) :: accu in |
let aux accu (res,x) = (f x) :: accu in |
| 341 |
SortedList.from_list (List.fold_left (List.fold_left aux) [] pp) |
SortedList.from_list (List.fold_left (List.fold_left aux) [] pp) |
| 368 |
let accu = aux pl accu (Types.diff t ty) rem in |
let accu = aux pl accu (Types.diff t ty) rem in |
| 369 |
accu |
accu |
| 370 |
in |
in |
| 371 |
let pl = List.map (fun p -> p.basic) pl in |
let pl = List.map (fun p -> p.nbasic) pl in |
| 372 |
let tests = collect (fun x -> x) pl in |
let tests = collect (fun x -> x) pl in |
| 373 |
let t = Types.cap any_basic t in |
let t = Types.cap any_basic t in |
| 374 |
aux pl [] t tests |
aux pl [] t tests |
| 383 |
let aux (res,(i,q)) = (res,(i,List.assoc q success)) in |
let aux (res,(i,q)) = (res,(i,List.assoc q success)) in |
| 384 |
List.map (extract_unique aux) |
List.map (extract_unique aux) |
| 385 |
|
|
|
let prepare_prod p = |
|
|
let line accu (res,t,pl,ql) = |
|
|
let p = bigcap pl and q = bigcap ql in |
|
|
let aux accu (t1,t2) = (res,(restrict t1 p,restrict t2 q))::accu in |
|
|
List.fold_left aux accu (Types.Product.normal t) in |
|
|
List.fold_left line [] p.prod |
|
|
|
|
| 386 |
let rec dispatch_prod t pl = |
let rec dispatch_prod t pl = |
| 387 |
let pl = List.map prepare_prod pl in |
let pl = List.map (fun p -> p.nprod) pl in |
| 388 |
let tests = collect (fun (p,_) -> p) pl in |
let tests = collect (fun (p,_) -> p) pl in |
| 389 |
let t = Types.Product.get t in |
let t = Types.Product.get t in |
| 390 |
let disp = aux_prod1 t pl [] [] [] 0 tests in |
let disp = aux_prod1 t pl [] [] [] 0 tests in |
| 427 |
|
|
| 428 |
(* Record types *) |
(* Record types *) |
| 429 |
|
|
|
type record = |
|
|
[ `Success |
|
|
| `Fail |
|
|
| `Dispatch of (nf * record) list |
|
|
| `Label of Types.label * (nf * record) list * record ] |
|
| 430 |
|
|
| 431 |
let map_record f = |
let map_record f = |
| 432 |
let rec aux = function |
let rec aux = function |
| 483 |
| _ -> assert false in |
| _ -> assert false in |
| 484 |
List.map aux |
List.map aux |
| 485 |
|
|
|
let rec cap_record nr fields = |
|
|
match (nr,fields) with |
|
|
| (`Success, []) -> `Success |
|
|
| (`Fail,_) -> `Fail |
|
|
| (`Success, (l2,pl)::fields) -> |
|
|
`Label (l2, [bigcap pl, cap_record nr fields], `Fail) |
|
|
| (`Label (l1, _, _), (l2,pl)::fields) |
|
|
when l2 < l1 -> |
|
|
`Label (l2, [bigcap pl, cap_record nr fields], `Fail) |
|
|
| (`Label (l1, pr, _), (l2,pl)::fields) |
|
|
when l1 = l2 -> |
|
|
let p = bigcap pl in |
|
|
let pr = |
|
|
List.map (fun (t,x) -> (restrict t p, cap_record x fields)) pr in |
|
|
`Label (l1, pr, `Fail) |
|
|
| (`Label (l1, pr, ab),_) -> |
|
|
let pr = |
|
|
List.map (fun (t,x) -> (constr t, cap_record x fields)) pr in |
|
|
`Label (l1, pr, cap_record ab fields) |
|
|
|
|
|
|
|
|
let prepare_record = |
|
|
map_record |
|
|
(function (res,t,fields) -> |
|
|
let nr = Types.Record.normal t in |
|
|
let x = cap_record nr fields in |
|
|
(res, [], x) |
|
|
) |
|
|
|
|
|
|
|
| 486 |
(* combiner les restrict field, ... *) |
(* combiner les restrict field, ... *) |
| 487 |
let rec dispatch_record t pl = |
let rec dispatch_record t pl = |
| 488 |
let pl = prepare_record (List.map (fun p -> p.record) pl) in |
let pl = List.map |
| 489 |
|
(fun p -> List.map (fun (res,r) -> (res,[],r)) p.nrecord |
| 490 |
|
) pl in |
| 491 |
let t = Types.Record.get t in |
let t = Types.Record.get t in |
| 492 |
aux_record1 t pl |
if Types.Record.is_empty t then None else Some (aux_record1 t pl) |
| 493 |
|
|
| 494 |
and aux_record1 t pl = |
and aux_record1 t pl = |
| 495 |
match collect_first_label pl with |
match collect_first_label pl with |
| 529 |
let mask l = List.map (function None -> false | Some _ -> true) l |
let mask l = List.map (function None -> false | Some _ -> true) l |
| 530 |
|
|
| 531 |
let rec dispatch (t : Types.descr) (pl : nf list) = |
let rec dispatch (t : Types.descr) (pl : nf list) = |
| 532 |
let pl = List.map (restrict t) pl in |
let fv = List.map (fun p -> p.v) pl in |
| 533 |
|
let pl = List.map (fun p -> normal (restrict t p)) pl in |
| 534 |
let basic = dispatch_basic t pl |
let basic = dispatch_basic t pl |
| 535 |
and prod = dispatch_prod t pl |
and prod = dispatch_prod t pl |
| 536 |
and record = dispatch_record t pl in |
and record = dispatch_record t pl in |
| 543 |
num 0 (SortedList.from_list !accu) in |
num 0 (SortedList.from_list !accu) in |
| 544 |
|
|
| 545 |
{ |
{ |
| 546 |
Dispatch.fv = List.map (fun p -> p.v) pl; |
Dispatch.fv = fv; |
| 547 |
Dispatch.masks = masks; |
Dispatch.masks = masks; |
| 548 |
Dispatch.basic = basic; |
Dispatch.basic = basic; |
| 549 |
Dispatch.prod = prod; |
Dispatch.prod = prod; |
| 654 |
(no t2 pl2); |
(no t2 pl2); |
| 655 |
List.iter (case_prod2 ppf pl2) cases2 |
List.iter (case_prod2 ppf pl2) cases2 |
| 656 |
|
|
| 657 |
and show_record ppf r = |
and show_record ppf = function |
| 658 |
|
| None -> () |
| 659 |
|
| Some r -> |
| 660 |
Format.fprintf ppf " | Record r -> @\n"; |
Format.fprintf ppf " | Record r -> @\n"; |
| 661 |
Format.fprintf ppf " @[%a@]@\n" show_record_aux r |
Format.fprintf ppf " @[%a@]@\n" show_record_aux r |
| 662 |
|
|
| 744 |
#install_printer Types.Print.print_descr;; |
#install_printer Types.Print.print_descr;; |
| 745 |
let (t,[p1;p2]) = Patterns.NF.get 5;; |
let (t,[p1;p2]) = Patterns.NF.get 5;; |
| 746 |
*) |
*) |
| 747 |
|
|
| 748 |
|
|