1
0
Fork 0
This repository has been archived on 2024-05-03. You can view files and clone it, but cannot push or open issues or pull requests.
unification-pfa/lib/inference.ml

61 lines
2.5 KiB
OCaml
Raw Normal View History

(** Infer the type of a given term and, if exists, returns the type of the term *)
2024-04-13 15:51:57 +02:00
let typeof t =
let rec infer env = function
2024-04-27 12:34:15 +02:00
| Term.Var id -> TypeSubstitution.find id env, env
2024-04-13 15:51:57 +02:00
| Term.IntConst _ -> Some Type.Int, env
| Term.Binop (t1, _, t2) ->
(* Both operands must have type Int *)
(match infer env t1, infer env t2 with
| (Some ty1, _), (Some ty2, _) ->
(match Unification.unify ty1 Type.Int, Unification.unify ty2 Type.Int with
| Some env1, Some env2 -> Some Type.Int, TypeSubstitution.compose env1 env2
| _ -> None, env)
| _, _ -> None, env)
| Term.Pair (t1, t2) ->
(match infer env t1, infer env t2 with
| (Some ty1, _), (Some ty2, _) -> Some (Type.Product (ty1, ty2)), env
| _, _ -> None, env)
| Term.Proj (proj, t) ->
(* Check if the term is a pair *)
(match infer env t with
| Some (Type.Product (ty1, ty2)), _ ->
(match proj with
| Term.First -> Some ty1, env
| Term.Second -> Some ty2, env)
2024-04-30 11:47:21 +02:00
| Some (Type.Var id), env' ->
(* Variable is a product *)
(match TypeSubstitution.find id env' with
| Some ty -> Some ty, env'
| None -> None, env')
2024-04-13 15:51:57 +02:00
| _ -> None, env)
| Term.Fun (id, body) ->
2024-04-27 12:34:15 +02:00
let arg = TypeSubstitution.singleton id (Type.Var id) in
2024-04-30 12:02:14 +02:00
(match infer (TypeSubstitution.compose arg env) body with
2024-04-13 15:51:57 +02:00
| Some ty_body, env' ->
(match infer env' (Term.Var id) with
| Some ty, _ -> Some (Type.Arrow (ty, ty_body)), env'
| None, _ -> Some (Type.Arrow (Type.Var id, ty_body)), env')
| _ -> None, env)
| Term.App (t1, t2) ->
2024-04-14 03:49:59 +02:00
(* Infer the type of t1 and t2 *)
2024-04-13 15:51:57 +02:00
(match infer env t1, infer env t2 with
2024-04-30 12:02:14 +02:00
| (Some (Type.Arrow (ty_param, _)), _), (Some ty_args, _) ->
2024-04-14 03:49:59 +02:00
(* Check if the argument type matches the parameter type *)
2024-04-13 15:51:57 +02:00
(match Unification.unify ty_param ty_args with
2024-04-30 12:02:14 +02:00
| Some env' ->
(* Infer again now that we have some extra typing infos *)
(match infer env' t1 with
| Some (Type.Arrow (_, ty_fn)), env'' -> Some ty_fn, env''
| _ -> None, env)
2024-04-13 15:51:57 +02:00
| None -> None, env)
2024-04-27 12:41:50 +02:00
(* | (Some (Type.Var _ as ty1), _), _ ->
2024-04-27 12:43:37 +02:00
(* On this case we may have a function represented as a variable *)
2024-04-27 12:41:50 +02:00
let ty2 = Type.Arrow (ty1, ty1) in
(match Unification.unify ty1 ty2 with
| Some env' -> Some ty2, env'
| _ -> None, env) *)
2024-04-14 03:49:59 +02:00
| _ -> None, env)
2024-04-13 15:51:57 +02:00
in
fst (infer TypeSubstitution.empty t)
;;