2024-03-11 09:31:56 +01:00
|
|
|
open TypeInference
|
|
|
|
|
2024-03-11 15:18:02 +01:00
|
|
|
let tests_typeof =
|
2024-03-11 09:31:56 +01:00
|
|
|
let x = Identifier.fresh () in
|
|
|
|
let y = Identifier.fresh () in
|
2024-04-27 12:34:21 +02:00
|
|
|
let z = Identifier.fresh () in
|
2024-03-28 19:20:37 +01:00
|
|
|
[ (* IntConst *)
|
2024-03-28 17:17:16 +01:00
|
|
|
"0", Term.IntConst 0, Some Type.Int
|
2024-03-28 19:20:37 +01:00
|
|
|
; (* int -> int -> int = <fun> *)
|
2024-03-28 17:17:16 +01:00
|
|
|
( "fun x -> fun y -> x + y"
|
2024-03-11 15:18:02 +01:00
|
|
|
, Term.(Fun (x, Fun (y, Binop (Var x, Plus, Var y))))
|
|
|
|
, Some Type.(Arrow (Int, Arrow (Int, Int))) )
|
2024-03-28 17:17:16 +01:00
|
|
|
; (* Not typed variable *)
|
2024-04-27 12:34:21 +02:00
|
|
|
"x", Term.(Var "x"), None
|
2024-03-28 19:20:37 +01:00
|
|
|
; (* Binary operation *)
|
|
|
|
"1 + 2", Term.(Binop (IntConst 1, Plus, IntConst 2)), Some Type.Int
|
2024-03-28 17:17:16 +01:00
|
|
|
; (* Pair *)
|
2024-03-28 19:20:37 +01:00
|
|
|
"(1, 2)", Term.(Pair (IntConst 1, IntConst 2)), Some Type.(Product (Int, Int))
|
2024-03-28 17:17:16 +01:00
|
|
|
; (* Projection with first *)
|
2024-03-28 19:20:37 +01:00
|
|
|
"fst (1, 2)", Term.(Proj (First, Pair (IntConst 1, IntConst 2))), Some Type.Int
|
2024-03-28 17:17:16 +01:00
|
|
|
; (* Projection with second *)
|
2024-03-28 19:20:37 +01:00
|
|
|
"snd (1, 2)", Term.(Proj (Second, Pair (IntConst 1, IntConst 2))), Some Type.Int
|
2024-03-28 17:17:16 +01:00
|
|
|
; (* Apply (int) into (fun : int -> int) *)
|
|
|
|
( "(fun x -> x + 1) 5"
|
2024-03-28 19:20:37 +01:00
|
|
|
, Term.(App (Fun (x, Binop (Var x, Plus, IntConst 1)), IntConst 5))
|
2024-03-28 17:17:16 +01:00
|
|
|
, Some Type.Int )
|
|
|
|
; (* Apply product (int * int) into a not compatible function (fun : int -> int) *)
|
|
|
|
( "(fun x -> x + 1) (1, 2)"
|
2024-03-28 19:20:37 +01:00
|
|
|
, Term.(App (Fun (x, Binop (Var x, Plus, IntConst 1)), Pair (IntConst 1, IntConst 2)))
|
2024-03-28 17:17:16 +01:00
|
|
|
, None )
|
2024-04-27 12:34:21 +02:00
|
|
|
; (* int -> int -> int = <fun> *)
|
|
|
|
( "fun x -> fun y -> x * y"
|
|
|
|
, Term.(Fun (x, Fun (y, Binop (Var x, Times, Var y))))
|
|
|
|
, Some Type.(Arrow (Int, Arrow (Int, Int))) )
|
|
|
|
; (* int -> int -> int = <fun> *)
|
|
|
|
( "fun x -> fun y -> x - y"
|
|
|
|
, Term.(Fun (x, Fun (y, Binop (Var x, Minus, Var y))))
|
|
|
|
, Some Type.(Arrow (Int, Arrow (Int, Int))) )
|
|
|
|
; (* int -> int -> int = <fun> *)
|
|
|
|
( "fun x -> fun y -> y / x"
|
|
|
|
, Term.(Fun (x, Fun (y, Binop (Var y, Div, Var x))))
|
|
|
|
, Some Type.(Arrow (Int, Arrow (Int, Int))) )
|
|
|
|
; (* Use of a non declared variable *)
|
|
|
|
"fun x -> fun y -> y / z", Term.(Fun (x, Fun (y, Binop (Var y, Div, Var z)))), None
|
2024-04-30 11:12:41 +02:00
|
|
|
(* Type mismatch between argument and function *)
|
|
|
|
; ( "(fun x -> x + 1) true"
|
|
|
|
, Term.(App (Fun (x, Binop (Var x, Plus, IntConst 1)), Var x))
|
|
|
|
, None )
|
2024-04-30 11:16:16 +02:00
|
|
|
; (* Nested functions *)
|
|
|
|
( "(fun x -> fun y -> x + y) 3 4"
|
|
|
|
, Term.(
|
|
|
|
App (App (Fun (x, Fun (y, Binop (Var x, Plus, Var y))), IntConst 3), IntConst 4))
|
|
|
|
, Some Type.Int )
|
2024-04-30 13:36:12 +02:00
|
|
|
; (* Function with nested pair *)
|
|
|
|
( "(fun x -> fst x) (1, 2)"
|
|
|
|
, Term.(App (Fun (x, Proj (First, Var x)), Pair (IntConst 1, IntConst 2)))
|
|
|
|
, Some Type.Int )
|
|
|
|
; (* Function application with nested pair and projection *)
|
|
|
|
( "(fun x -> fst (snd x)) ((1, 2), 3)"
|
|
|
|
, Term.(
|
|
|
|
App
|
|
|
|
( Fun (x, Proj (First, Proj (Second, Var x)))
|
|
|
|
, Pair (Pair (IntConst 1, IntConst 2), IntConst 3) ))
|
|
|
|
, Some Type.Int )
|
2024-03-11 15:18:02 +01:00
|
|
|
]
|
|
|
|
;;
|
2024-03-11 14:25:40 +01:00
|
|
|
|
2024-03-11 09:31:56 +01:00
|
|
|
let typeModule = (module Type : Alcotest.TESTABLE with type t = Type.t)
|
|
|
|
|
|
|
|
let check_typeof term_text term expected_type =
|
|
|
|
let open Alcotest in
|
2024-03-11 15:18:02 +01:00
|
|
|
test_case term_text `Quick (fun () ->
|
|
|
|
check (option typeModule) "Same type" expected_type (Inference.typeof term))
|
|
|
|
;;
|
2024-03-11 09:31:56 +01:00
|
|
|
|
|
|
|
let () =
|
|
|
|
let open Alcotest in
|
2024-03-11 15:18:02 +01:00
|
|
|
run
|
|
|
|
"Inference"
|
|
|
|
[ ( "typeof"
|
|
|
|
, List.map
|
|
|
|
(fun (term_text, term, expected_type) ->
|
|
|
|
check_typeof term_text term expected_type)
|
|
|
|
tests_typeof )
|
2024-03-11 09:31:56 +01:00
|
|
|
]
|
2024-03-11 15:18:02 +01:00
|
|
|
;;
|