let rec gettype_binop op t1 t2 = match (op,t1,t2) with
(Ast.SynBinopAnd, TyBool, TyBool) -> TyBool
| (Ast.SynBinopOr, TyBool, TyBool) -> TyBool
| (Ast.SynBinopAdd, TyInt, TyInt) -> TyInt
| (Ast.SynBinopSub, TyInt, TyInt) -> TyInt
| (Ast.SynBinopMul, TyInt, TyInt) -> TyInt
| (Ast.SynBinopDiv, TyInt, TyInt) -> TyFloat
| (Ast.SynBinopIDiv, TyInt, TyInt) -> TyInt
| (Ast.SynBinopMod, TyInt, TyInt) -> TyInt
| (Ast.SynBinopAdd, (TyInt | TyFloat), TyFloat) -> TyFloat
| (Ast.SynBinopAdd, TyFloat, TyInt) -> TyFloat
| (Ast.SynBinopSub, (TyInt | TyFloat), TyFloat) -> TyFloat
| (Ast.SynBinopSub, TyFloat, TyInt) -> TyFloat
| (Ast.SynBinopMul, (TyInt | TyFloat), TyFloat) -> TyFloat
| (Ast.SynBinopMul, TyFloat, TyInt) -> TyFloat
| (Ast.SynBinopDiv, (TyInt | TyFloat), TyFloat) -> TyFloat
| (Ast.SynBinopDiv, TyFloat, TyInt) -> TyFloat
| (Ast.SynBinopConcat, TyString, TyString) -> TyString
| (Ast.SynBinopConcat, TyList t_list1, TyList t_list2) when (t_list1 = t_list2) -> TyList t_list1
| (Ast.SynBinopCons, t_item, TyList t_list) when (t_item = t_list) -> TyList t_list
| (Ast.SynCompLt, (TyInt | TyFloat), (TyInt | TyFloat)) -> TyBool
| (Ast.SynCompGt, (TyInt | TyFloat), (TyInt | TyFloat)) -> TyBool
| (Ast.SynCompLte, (TyInt | TyFloat), (TyInt | TyFloat)) -> TyBool
| (Ast.SynCompGte, (TyInt | TyFloat), (TyInt | TyFloat)) -> TyBool
| (Ast.SynCompEq, (TyInt | TyFloat), (TyInt | TyFloat)) -> TyBool
| (Ast.SynCompNeq, (TyInt | TyFloat), (TyInt | TyFloat)) -> TyBool
| (Ast.SynCompEq, x, y) when (x = y) -> TyBool
| (Ast.SynCompNeq, x, y) when (x = y) -> TyBool
| _ -> raise_type_error ["Attempted to perform an invalid binary operation ";Ast.string_of_binop op;" on values of type ";string_of_type t1;" and ";string_of_type t2]