tallyingTest.ml 15.3 KB
Newer Older
1
open OUnit2
2
open Types
3

4
let parse_typ s =
5
  let st = Stream.of_string s in
6
  let astpat = Parser.pat st in
7
  let nodepat = Typer.typ Builtin.env astpat in
8 9 10
  Types.descr nodepat
;;

11
(* the abstract field is ignored in the comparison *)
12
module ESet = OUnitDiff.SetMake (struct
13
  type t = (Var.var * Types.t)
14
  let compare (v1,t1) (v2,t2) =
15 16
    if (v1,t1) == (v2,t2) then 0
    else let c = Var.compare v1 v2 in if c <> 0 then c
17
    else Types.compare t1 t2
18
  let pp_printer ppf (v,t) = Format.fprintf ppf "(%a = %a)" Var.pp v Types.Print.pp_type t
19 20
  let pp_print_sep = OUnitDiff.pp_comma_separator
end)
21

22
module SubStSet = OUnitDiff.SetMake (struct
23 24 25 26 27 28
  type t = ESet.t
  let compare a b = ESet.compare a b
  let pp_printer ppf l = ESet.pp_printer ppf l
  let pp_print_sep = OUnitDiff.pp_comma_separator
end)

29
module MSet = OUnitDiff.SetMake (struct
30
  type t = Tallying.CS.m
31
  let compare = Tallying.CS.M.compare
Pietro Abate's avatar
Pietro Abate committed
32
  let pp_printer = Tallying.CS.pp_m
33 34 35
  let pp_print_sep = OUnitDiff.pp_comma_separator
end)

Pietro Abate's avatar
Pietro Abate committed
36 37 38 39
type pp = P of vv * string | N of string * vv
and vv = V of string

let mk_s ll =
Pietro Abate's avatar
WIP  
Pietro Abate committed
40 41
  let aux l =
    List.fold_left (fun acc -> function
42 43
      |P(V alpha,t) -> Tallying.CS.M.add ((*true,*)Var.mk alpha) (Types.empty,parse_typ t) acc
      |N(t,V alpha) -> Tallying.CS.M.add ((*false,*)Var.mk alpha) (parse_typ t,Types.any) acc
Pietro Abate's avatar
WIP  
Pietro Abate committed
44 45
    ) Tallying.CS.M.empty l
  in
46
  List.fold_left (fun acc l ->
Pietro Abate's avatar
WIP  
Pietro Abate committed
47
    Tallying.CS.S.add (aux l) acc
Pietro Abate's avatar
Pietro Abate committed
48 49
  ) Tallying.CS.S.empty ll

50
let mk_union_res l1 l2 =
51
  let aux l =
52
    List.fold_left (fun acc -> function
53 54
      |P(V v,s) -> Tallying.CS.M.merge acc (Tallying.CS.M.singleton (Var.mk v) (Types.empty, parse_typ s))
      |N(s,V v) -> Tallying.CS.M.merge acc (Tallying.CS.M.singleton (Var.mk v) (parse_typ s, Types.any))
55
    ) Tallying.CS.M.empty l
56
  in
57 58 59 60 61 62
  match l1,l2 with
  |[],[] -> Tallying.CS.sat
  |l1,[] -> (Tallying.CS.S.singleton (aux l1))
  |[],l2 -> (Tallying.CS.S.singleton (aux l2))
  |l1,l2 -> Tallying.CS.S.union (Tallying.CS.S.singleton (aux l1)) (Tallying.CS.S.singleton (aux l2))

Pietro Abate's avatar
Pietro Abate committed
63
(* check invariants on the constraints sets *)
Pietro Abate's avatar
WIP  
Pietro Abate committed
64 65 66 67 68 69 70 71 72 73 74 75
let mk_pp = function
  |P(V alpha,t) -> Tallying.CS.singleton (Tallying.Pos (Var.mk alpha,parse_typ t))
  |N(t,V alpha) -> Tallying.CS.singleton (Tallying.Neg (parse_typ t,Var.mk alpha))

let mk_prod l =
    List.fold_left (fun acc c ->
      Tallying.CS.prod (mk_pp c) acc
    ) Tallying.CS.sat l

let mk_union l1 l2 =
  Tallying.CS.union (mk_prod l1) (mk_prod l2)

Pietro Abate's avatar
Pietro Abate committed
76
let test_constraint_ops () = [
77 78 79 80 81

  "prod pos",mk_prod [P(V "A","Int");P(V "A","Bool")], mk_pp (P(V "A","Int & Bool"));

  "prod neg",mk_prod [N("Int",V "B");N("Bool",V "B")], mk_pp (N("Int | Bool",V "B"));

82
  "prod var",mk_prod [N("'B",V "A");P(V "B","Bool | Int")],
83
      mk_union_res
84
        [N("'B",V "A");P(V "B","Bool | Int")]
85 86 87 88 89 90 91 92 93 94 95 96 97 98
        [];

  "empty", mk_union [P(V "A","Empty")] [P(V "A","Empty")], mk_pp (P(V "A","Empty"));

  "empty <= int 1", mk_union [P(V "A","Int")] [P(V "A","Empty")], mk_pp (P(V "A","Int"));
  "empty <= int 2", mk_union [P(V "A","Empty")] [P(V "A","Int")], mk_pp (P(V "A","Int"));

  "int v bool <= int", mk_union [P(V "A","Int | Bool")] [P(V "A","Int")], mk_pp (P(V "A","Int | Bool"));

  "0 -> 1 <= a -> b", mk_union [P(V "A","Empty -> Any")] [P(V "A","Int -> Bool")], mk_pp (P(V "A","Empty -> Any"));

  "union 1",mk_union [P(V "A","Empty")] [P(V "A","Empty");N("Int",V "B")], mk_pp (P(V "A","Empty"));

  "union 2",mk_union [P(V "A","Empty")] [P(V "A","Int");P(V "A","Bool")],
99
      mk_union_res
100 101 102 103 104 105 106 107 108 109 110 111 112
      [P(V "A","Int & Bool")]
      [P(V "A","Empty")];

  "union 2 comm",mk_union [P(V "A","Int");P(V "A","Bool")] [P(V "A","Empty")],
      mk_union_res
        [P(V "A","Int & Bool")]
        [(P(V "A","Empty"))];

  "union 3",mk_union [P(V "A","Empty")] [P(V "A","Empty");P(V "B","Empty")], mk_pp (P(V "A","Empty"));

  "union 4",mk_union [P(V "A","Empty")] [P(V "A","Empty");P(V "B","Int")], mk_pp (P(V "A","Empty"));

  "union 5",mk_union [P(V "A","Int | Bool");N("Int",V "B");P(V "B","Empty")] [P(V "A","Empty");P(V "B","Empty")],
113
      mk_union_res
114 115 116 117
        [P(V "A","Int | Bool");N("Int",V "B");P(V "B","Empty")]
        [P(V "A","Empty");P(V "B","Empty")];

]
118

119
let test_constraints =
120
  "constraints" >:::
121 122 123 124 125
    List.map (fun (test,result,expected) ->
      test >:: (fun _ ->
        let elem s = (MSet.of_list (Tallying.CS.S.elements s)) in
        MSet.assert_equal (elem expected) (elem result)
      )
Pietro Abate's avatar
Pietro Abate committed
126
    ) (test_constraint_ops ())
127 128 129
;;

(* ^ => & -- v => | *)
Pietro Abate's avatar
Pietro Abate committed
130

Pietro Abate's avatar
Pietro Abate committed
131
let norm_tests () = [
Pietro Abate's avatar
Pietro Abate committed
132 133 134 135
  "Int", "Empty", Tallying.CS.unsat;
  "(Int,Int)", "Empty", Tallying.CS.unsat;
  "Int -> Int", "Empty" , Tallying.CS.unsat;

136
  "Bool -> Bool","Int -> 'A", Tallying.CS.unsat;
Pietro Abate's avatar
Pietro Abate committed
137 138
  "Int", "Bool", Tallying.CS.unsat;
  "Int", "Empty", Tallying.CS.unsat;
139
  "[] -> []","Int -> 'A", Tallying.CS.unsat;
Pietro Abate's avatar
Pietro Abate committed
140 141 142 143

  "Any", "Empty",  Tallying.CS.unsat;
  "Empty", "Empty",  Tallying.CS.sat;

144
  "('A -> Bool)", "('B -> 'B)", mk_s [
Pietro Abate's avatar
Pietro Abate committed
145
    [P(V "B","Empty")];
146
    [N("'B",V "A");N("Bool",V "B")]
Pietro Abate's avatar
Pietro Abate committed
147
  ];
148

149 150 151 152
  "'B", "'A", mk_s [[N("'B",V "A")]];
  "'B", "Empty", mk_s [[P(V "B","Empty")]];
  "Int", "'B", mk_s [[N("Int",V "B")]];
  "Int", "('A | 'B)", mk_s [[N("Int \\ 'B",V "A")]];
153

154
  "(Int -> Bool)", "('A -> 'B)", mk_s [
Pietro Abate's avatar
Pietro Abate committed
155 156 157
    [P(V "A","Empty")];
    [P(V "A","Int");N("Bool",V "B")]
  ];
158

159
  "(Int -> Int) | (Bool -> Bool)", "('A -> 'B)", mk_s [
160 161
     [P(V "A","Empty")];
    (* All these are subsumed as less general then (A <= 0) *)
Pietro Abate's avatar
Pietro Abate committed
162 163 164 165
    [P(V "A","Empty");N("Int",V "B")];
    [P(V "A","Empty");N("Bool",V "B")];
    [P(V "A","Empty");N("Int | Bool",V "B")]
  ];
166

167
  "('A -> 'B)", "(Int -> Int) | (Bool -> Bool)", mk_s [
168 169 170 171
    [P(V "B","Int");N("Int",V "A")];
    [P(V "B","Bool");N("Bool",V "A")];
  ];

Pietro Abate's avatar
Pietro Abate committed
172
  (*
173
  "([0--*] & `true)", "('A | Int) & ((Any \\ 'A) | Bool)",
174
  *)
175

176
  "('A , 'B)","(Int , Bool)", mk_s [
177 178
    [P(V "A","Empty")];
    [P(V "B","Empty")];
Pietro Abate's avatar
Pietro Abate committed
179 180
    [P(V "A","Int");P(V "B","Bool")]
  ];
181

182
  "{a=('A , 'B)}","{a=(Int , Bool)}", mk_s [
Pietro Abate's avatar
Pietro Abate committed
183 184 185 186 187
    [P(V "A","Empty")];
    [P(V "B","Empty")];
    [P(V "A","Int");P(V "B","Bool")]
  ];

188
  "{a=(Int , Bool)}","{a=('A , 'B)}", mk_s [ [N("Int", V "A");N("Bool", V "B")] ];
Pietro Abate's avatar
Pietro Abate committed
189

190 191
  "(Int , Bool)","('A , 'B)", mk_s [ [N("Int", V "A");N("Bool", V "B")] ];
  "(Bool , Bool)","('A , 'B)", mk_s [ [N("Bool", V "A");N("Bool", V "B")] ];
192

193
  "('A | ('B , ('C)))","(Int , Int)", mk_s [
194 195 196 197
    [P(V "A","(Int , Int)"); P(V "B","Empty")];
    [P(V "A","(Int , Int)"); P(V "C","Empty")];
    [P(V "A","(Int , Int)"); P(V "B","Int"); P(V "C","Int")];

Pietro Abate's avatar
Pietro Abate committed
198
  ];
199

200
  "('A , Int) | ('B , Bool))","(Int , (Int | Bool))", mk_s [
Pietro Abate's avatar
Pietro Abate committed
201 202
    [P(V "A","Int");P(V "B","Int")]
  ];
Pietro Abate's avatar
WIP  
Pietro Abate committed
203

204 205
  "('A -> 'B) -> [ 'A ] -> [ 'B ]", "((Int -> Bool) | (('A \\ Int) -> ('B \\ Int))) -> ('Gamma)", mk_s [
    [P(V "A","Empty");N("['A] -> ['B]", V "Gamma")]
Pietro Abate's avatar
Pietro Abate committed
206
  ];
207

208
  "Int -> Bool", "'A", mk_s [[N("Int -> Bool",V "A")]];
209

210
  "(('A , Int) & ('B , Bool))","(Int , (*Int & Bool*) Empty)",Tallying.CS.sat;
Pietro Abate's avatar
Pietro Abate committed
211

212
  "(('A , Int) | ('B , Bool))","(Int , (Int | Bool))", mk_s [
Pietro Abate's avatar
Pietro Abate committed
213 214 215
    [P(V "A","Int");P(V "B","Int")]
  ];

216 217 218
]

let test_norm =
219
  "norm" >:::
220 221 222 223
    List.map (fun (s,t,expected) ->
      (Printf.sprintf " %s \\ %s" s t) >:: (fun _ ->
        let s = parse_typ s in
        let t = parse_typ t in
224
        let result = Tallying.norm Var.Set.empty (diff s t) in
225 226
        let elem s = MSet.of_list (Tallying.CS.S.elements s) in
        MSet.assert_equal (elem expected) (elem result)
227
      )
Pietro Abate's avatar
Pietro Abate committed
228
    ) (norm_tests ())
229 230
;;

Pietro Abate's avatar
Pietro Abate committed
231
let merge_tests () = [
232
  "empty  empty", mk_s [[P(V "A", "Empty");P(V "B", "Empty")]],
233 234 235 236 237 238
    mk_s [
      [P(V "A","Empty");P(V "B","Empty")]
    ];

  "unsat 1", mk_s [[P(V "A", "Int | Bool");N("Int",V "B");P(V "B", "Empty")]], Tallying.CS.unsat;

239
  "unsat 2", mk_s [[N("Bool",V "B"); N("'B", V "A"); P(V "A", "Empty")]], Tallying.CS.unsat;
240

241
  "quad", mk_s [[N("Bool",V "B");N("Int",V "B");N("'B",V "A"); P(V "A", "Int | Bool")]],
242
    mk_s [
243
      [N("'B", V "A");P(V "A","Int | Bool");N("Int | Bool", V "B"); P(V "B","Int | Bool")]
244 245
    ];

246 247
  "add one", mk_s [[N("'B", V "A");P(V "A","Int | Bool")]],
    mk_s [[N("'B", V "A");P(V "A","Int | Bool");P(V "B","Int | Bool")]];
248

249
  "A B", mk_s [[P(V "A", "'B")]], mk_pp (P(V "A","'B"));
250 251 252 253 254 255 256 257

  "", mk_s [[P(V "B", "Empty")]], mk_pp (P(V "B","Empty"));

  "", mk_s [[P(V "A", "Int");P(V "B", "Bool"); P(V "A", "Empty")]],
    mk_s [
      [P(V "A","Empty");P(V "B","Bool")]
    ]
];;
258 259

let test_merge =
260
  "merge" >:::
261 262
    List.map (fun (test,s,expected) ->
      test >:: (fun _ ->
263
        let result =
264
          try
265
            Tallying.CS.S.fold (fun c acc ->
266
              Tallying.CS.union (Tallying.merge Var.Set.empty c) acc
267
            ) s Tallying.CS.S.empty
268
          with Tallying.UnSatConstr _ -> Tallying.CS.unsat
269
        in
270 271
        let elem s = MSet.of_list (Tallying.CS.S.elements s) in
        MSet.assert_equal (elem expected) (elem result)
272
      )
Pietro Abate's avatar
Pietro Abate committed
273
    ) (merge_tests ())
274 275
;;

276 277
let mk_e ll =
  List.map (fun l ->
278
    List.map (fun (V v,t) -> (Var.mk v),(parse_typ t)) l
279 280 281
  ) ll

let tallying_tests = [
282
  [("((Int | Bool) -> Int)", "('A -> 'B)")], mk_e [
Pietro Abate's avatar
Pietro Abate committed
283 284 285 286
    [(V "A","Empty")];
    [(V "A","Int | Bool");(V "B","Int")]
  ];

287
  [("((Int | Bool) -> Int)", "('A -> 'B)"); ("('A -> Bool)","('B -> 'B)")], mk_e [
288 289
    [(V "A","Int | Bool");(V "B","Int | Bool")];
    [(V "A","Empty");(V "B","Empty")]
290
  ];
Pietro Abate's avatar
Pietro Abate committed
291

292
  [("(Int -> Bool)", "('A -> 'B)")], mk_e [
293 294
    [(V "A","Empty")];
    [(V "A","Int");(V "B","Bool")];
Pietro Abate's avatar
Pietro Abate committed
295 296
  ];

297
  [("(Int -> Int) | (Bool -> Bool)", "('A -> 'B)")], mk_e [
298
    [(V "A","Empty")];
299
  ];
Pietro Abate's avatar
Pietro Abate committed
300

301
  [("((Int,Int) , (Int | Bool))","('A,Int) | (('B,Int),Bool)")], mk_e [
302 303
    [(V "A", "(Int,Int)"); (V "B","Int")]
  ];
304
  [("(('A , Int) | ('B , Bool))","(Int , (Int | Bool))")], mk_e [
305 306
    [(V "A","Int");(V "B","Int")]
  ];
307 308
  [("[] -> []","Int -> 'A")], [];
  [("Bool -> Bool","Int -> 'A")], [];
Pietro Abate's avatar
Pietro Abate committed
309

310
  [("(('A , Int) & ('B , Bool))","(Int , (Int & Bool))")], [[]];
311

Pietro Abate's avatar
Pietro Abate committed
312
  (* map even *)
313 314
(*  [("('A -> 'B) -> ['A ] -> ['B ]","((Int -> Bool) & (('A \\ Int) -> ('A \\ Int)))")], [[]];*)
  [("('A -> 'A)", "((Int -> Int) & (Bool -> Bool)) -> ('T)")], mk_e [];
315 316 317

  (* records *)
  [("{a=Int}","Any")], [[]];
318
  [("{a='A}","Any")], [[]];
319
  [("{a=Int}","{a=(Int|Bool)}")], [[]];
Pietro Abate's avatar
Pietro Abate committed
320
  (*
321 322 323
  [("{a=Bool -> Bool}","{b=Int -> 'A}")], [[]];
  [("{a=(Int -> Int) | (Bool -> Bool)}","{b=('A -> 'B)}")], [[]];
  [("{a=Int} -> Int", "{a='A} -> 'A")], [[]];
Pietro Abate's avatar
Pietro Abate committed
324
  *)
325 326
]

Pietro Abate's avatar
Pietro Abate committed
327
(* to test tallying { sigma_i } -- > for all i => s sigma_i <= t sigma_i *)
328 329 330 331
let test_tallying =
  let print_test l =
    String.concat ";" (List.map (fun (s,t) -> Printf.sprintf " %s \\ %s" s t) l)
  in
332
  "tallying" >:::
333 334
    List.map (fun (l,expected) ->
      (print_test l) >:: (fun _ ->
335 336
        try
          let l = List.map (fun (s,t) -> (parse_typ s,parse_typ t)) l in
337
          let sigma = Tallying.tallying l in
338
          List.iter (fun (s,t) ->
Pietro Abate's avatar
Pietro Abate committed
339
            List.iter (fun sigma ->
Pietro Abate's avatar
Pietro Abate committed
340 341
              let s_sigma = Tallying.(s $$ sigma) in
              let t_sigma = Tallying.(t $$ sigma) in
342
              assert_equal ~pp_diff:(fun fmt _ ->
343 344
                  Format.fprintf fmt "s @ sigma_i = %a\n" Types.Print.pp_type s_sigma;
                  Format.fprintf fmt "t @ sigma_i = %a\n" Types.Print.pp_type t_sigma
Pietro Abate's avatar
Pietro Abate committed
345
              ) (Types.subtype s_sigma t_sigma) true
346
            ) sigma
Pietro Abate's avatar
Pietro Abate committed
347
          ) l
348
        with Tallying.Step1Fail -> assert_equal expected []
349 350 351 352
      )
    ) tallying_tests
;;

353 354
let apply_raw_tests = [
  "iter  hd",
355
   "('A -> []) -> [ 'A* ] -> []","[ ('A0)* ] -> ('A0)";
356 357

  "iteri  assoc",
358
   "(Int -> 'A -> []) -> [ 'A* ] -> []","('A1) -> [ (('A1) , ('B1))* ] -> ('B1)";
359 360

  "map  length",
361
   "('A -> 'B) -> [ 'A* ] -> [ 'B* ]","[ ('A3)* ] -> Int";
362 363

  "map  length & hd",
364
   "('A -> 'B) -> [ 'A* ] -> [ 'B* ]","([ ('A3)* ] -> Int) & ([ ('A4)* ] -> ('A4))";
365 366

  "mapi  mem",
367
   "(Int -> 'A -> 'B) -> [ 'A* ] -> [ 'B* ]","('A45) -> [ ('A45)* ] -> Bool";
368 369

  "mapi  mem & memq",
370
   "(Int -> 'A -> 'B) -> [ 'A* ] -> [ 'B* ]","(('A45) -> [ ('A45)* ] -> Bool) & (('A46) -> [ ('A46)* ] -> Bool)";
371 372

  "rev_map  length",
373
   "('A -> 'B) -> [ 'A* ] -> [ 'B* ]","[ ('A53)* ] -> Int";
374 375

  "rev_map  length & hd",
376
   "('A -> 'B) -> [ 'A* ] -> [ 'B* ]","([ ('A53)* ] -> Int) & ([ ('A54)* ] -> ('A54))";
377 378

  "fold_left  append",
379
   "('A -> 'B -> 'A) -> 'A -> [ 'B* ] -> 'A","[ ('A95)* ] -> [ ('A95)* ] -> [ ('A95)* ]";
380 381

  "fold_right  hd",
382
   "('A -> 'B -> 'B) -> [ 'A* ] -> 'B -> 'B","[ ('A103)* ] -> ('A103)";
383 384

  "iter2  hd",
385
   "('A -> 'B -> []) -> [ 'A* ] -> [ 'B* ] -> []","[ ('A117)* ] -> ('A117)";
386 387

  "map2  hd",
388
   "('A -> 'B -> ('C)) -> [ 'A* ] -> [ 'B* ] -> [ ('C)* ]","[ ('A124)* ] -> ('A124)";
389 390

  "rev_map2  hd",
391
   "('A -> 'B -> ('C)) -> [ 'A* ] -> [ 'B* ] -> [ ('C)* ]","[ ('A160)* ] -> ('A160)";
392 393

  "fold_left2  assoc",
394
   "('A -> 'B -> ('C) -> 'A) -> 'A -> [ 'B* ] -> [ ('C)* ] -> 'A","('A196) -> [ (('A196) , ('B196))* ] -> ('B196)";
395 396

  "for_all  hd",
397
   "('A -> Bool) -> [ 'A* ] -> Bool","[ ('A198)* ] -> ('A198)";
398 399

  "exists  hd",
400
   "('A -> Bool) -> [ 'A* ] -> Bool","[ ('A199)* ] -> ('A199)";
401 402

  "for_all2  hd",
403
   "('A -> 'B -> Bool) -> [ 'A* ] -> [ 'B* ] -> Bool","[ ('A200)* ] -> ('A200)";
404 405

  "exists2  hd",
406
   "('A -> 'B -> Bool) -> [ 'A* ] -> [ 'B* ] -> Bool","[ ('A211)* ] -> ('A211)";
407 408

  "mem  length",
409
   "'A -> [ 'A* ] -> Bool","[ ('A222)* ] -> Int";
410 411

  "memq  length",
412
   "'A -> [ 'A* ] -> Bool","[ ('A264)* ] -> Int";
413 414

  "find  hd",
415
   "('A -> Bool) -> [ 'A* ] -> 'A","[ ('A306)* ] -> ('A306)";
416 417

  "filter  hd",
418
   "('A -> Bool) -> [ 'A* ] -> [ 'A* ]","[ ('A307)* ] -> ('A307)";
419 420

  "find_all  hd",
421
   "('A -> Bool) -> [ 'A* ] -> [ 'A* ]","[ ('A308)* ] -> ('A308)";
422 423

  "partition  hd",
424
   "('A -> Bool) -> [ 'A* ] ->( [ 'A* ] , [ 'A* ])","[ ('A309)* ] -> ('A309)";
425 426

  "assoc  length",
427
   "'A -> [ ('A , 'B)* ] -> 'B","[ ('A310)* ] -> Int";
428 429

  "assoc  length & hd",
430
   "'A -> [ ('A , 'B)* ] -> 'B","([ ('A310)* ] -> Int) & ([ ('A311)* ] -> ('A311))";
431 432

  "mem_assoc  length",
433
   "'A -> [ ('A , 'B)* ] -> Bool","[ ('A394)* ] -> Int";
434 435

  "mem_assoc  length & hd",
436
   "'A -> [ ('A , 'B)* ] -> Bool","([ ('A394)* ] -> Int) & ([ ('A395)* ] -> ('A395))";
437 438

  "mem_assq  length",
439
   "'A -> [ ('A , 'B)* ] -> Bool","[ ('A436)* ] -> Int";
440 441

  "mem_assq  length & hd",
442
   "'A -> [ ('A , 'B)* ] -> Bool","([ ('A436)* ] -> Int) & ([ ('A437)* ] -> ('A437))";
443 444

  "remove_assoc  length",
445
   "'A -> [ ('A , 'B)* ] -> [ ('A , 'B)* ]","[ ('A478)* ] -> Int";
446 447

  "remove_assoc  length & hd",
448
   "'A -> [ ('A , 'B)* ] -> [ ('A , 'B)* ]","([ ('A478)* ] -> Int) & ([ ('A479)* ] -> ('A479))";
449 450 451 452 453 454 455 456 457 458 459 460 461 462
]

let test_apply =
  let print_test msg s t = Printf.sprintf "%s : (%s) o (%s)\n" msg s t in
  "apply" >:::
    let sigmacup sl t =
      List.fold_left (fun acc sigma -> 
        Types.cap acc Tallying.(t $$ sigma)
      ) Types.any sl
    in
    List.map (fun (msg,s,t) ->
      (print_test msg s t) >:: (fun _ ->
        try
          let (s,t) = (parse_typ s,parse_typ t) in
Pietro Abate's avatar
Pietro Abate committed
463
          let (sl,s,t,g) = Types.apply_raw Var.Set.empty s t in
464

465 466 467 468
          let gamma = Types.cons (Types.var (Var.mk "Gamma")) in

          let t1 = sigmacup sl s in
          let t2_gamma = sigmacup sl (Types.arrow (Types.cons t) gamma) in
469 470

          assert_equal ~pp_diff:(fun fmt _ ->
471
            Format.fprintf fmt "t1 < 0 -> 1 = %a\n" Types.Print.pp_type t1
472
          ) (Types.subtype t1 (parse_typ "Empty -> Any")) true;
473 474 475

          assert_equal ~pp_diff:(fun fmt _ ->
            Format.fprintf fmt "sl = %a\n" Types.Tallying.CS.pp_sl sl;
476 477
            Format.fprintf fmt "t1 = %a\n" Types.Print.pp_type t1;
            Format.fprintf fmt "t2 -> gamma = %a\n" Types.Print.pp_type t2_gamma;
478
          ) (Types.subtype t1 t2_gamma) true
479 480 481 482 483
        with Tallying.Step1Fail -> assert_equal [] []
      )
    ) apply_raw_tests 
;;

484 485
let suite =
  "tests" >::: [
486
    test_constraints;
487
    test_norm;
488
    test_merge;
489
    test_tallying;
490
    test_apply;
491
  ]
492

493
let main () =
494
  OUnit2.run_test_tt_main suite
495 496
;;

497
main ()