open TypeInference let tests_typeof = let x = Identifier.fresh () in let y = Identifier.fresh () in [ (* Int Const *) "0", Term.IntConst 0, Some Type.Int ; (* Correct function *) ( "fun x -> fun y -> x + y" , Term.(Fun (x, Fun (y, Binop (Var x, Plus, Var y)))) , Some Type.(Arrow (Int, Arrow (Int, Int))) ) ; (* Not typed variable *) "x", Var "x", None ; (* Operation *) "1 + 2", Binop (IntConst 1, Plus, IntConst 2), Some Int ; (* Pair *) "(1, 2)", Pair (IntConst 1, IntConst 2), Some (Product (Int, Int)) ; (* Projection with first *) "fst (1, 2)", Proj (First, Pair (IntConst 1, IntConst 2)), Some Int ; (* Projection with second *) "snd (1, 2)", Proj (Second, Pair (IntConst 1, IntConst 2)), Some Int ; (* Apply (int) into (fun : int -> int) *) ( "(fun x -> x + 1) 5" , App (Fun (x, Binop (Var x, Plus, IntConst 1)), IntConst 5) , Some Type.Int ) ; (* Apply product (int * int) into a not compatible function (fun : int -> int) *) ( "(fun x -> x + 1) (1, 2)" , App (Fun (x, Binop (Var x, Plus, IntConst 1)), Pair (IntConst 1, IntConst 2)) , None ) ] ;; let typeModule = (module Type : Alcotest.TESTABLE with type t = Type.t) let check_typeof term_text term expected_type = let open Alcotest in test_case term_text `Quick (fun () -> check (option typeModule) "Same type" expected_type (Inference.typeof term)) ;; let () = let open Alcotest in run "Inference" [ ( "typeof" , List.map (fun (term_text, term, expected_type) -> check_typeof term_text term expected_type) tests_typeof ) ] ;;