let evaluate_op value1 value2 operator =
let string_of_operator = function
| Plus -> "+"
| Minus -> "-"
| Times -> "*"
| Divide -> "/"
| Modulo -> "%"
| Or -> "||"
| And -> "&&"
in let string_op s1 s2 =
(match operator with
| Plus -> RStringValue(s1 ^ s2)
| _ -> raise (EInvalidOperation (string_of_operator operator,"string"))
)
in let float_op f1 f2 = (let f = (match operator with
| Plus -> f1 +. f2
| Minus -> f1 -. f2
| Times -> f1 *. f2
| Divide -> f1 /. f2
| _ -> raise (EInvalidOperation (string_of_operator operator,"float"))) in
RFloatValue(f)
)
in match (value1, value2) with
| (RIntegerValue(i1), RIntegerValue(i2)) ->
(match operator with
| Plus -> RIntegerValue( i1 + i2 )
| Minus -> RIntegerValue( i1 - i2)
| Times -> RIntegerValue( i1 * i2)
| Divide -> RIntegerValue( i1 / i2)
| Modulo -> RIntegerValue( i1 mod i2)
| _ -> raise (EInvalidOperation (string_of_operator operator,"integer"))
)
| (RBooleanValue(b1), RBooleanValue(b2)) ->
(match operator with
| And -> RBooleanValue(b1 && b2)
| Or -> RBooleanValue(b1 || b2)
| _ -> raise (EInvalidOperation (string_of_operator operator,"boolean"))
)
| (RFloatValue(f1), RFloatValue(f2)) -> float_op f1 f2
| (RFloatValue(f1), RIntegerValue(i2)) -> float_op f1 (float_of_int i2)
| (RIntegerValue(i1), RFloatValue(f2)) -> float_op (float_of_int i1) f2
| (RStringValue(s1), RStringValue(s2)) -> string_op s1 s2
| (RStringValue(s1), v2) -> string_op s1 (string_of_value v2)
| (v1, RStringValue(s2)) -> string_op (string_of_value v1) s2
| (value1, value2) -> raise (EIncompatibleTypes(string_of_value_type value1, string_of_value_type value2))