bool_op.ml 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. (**
  2. * The phase applies the transformations shown below. These transformations are
  3. * required because the CiviC VM does not offer instructions that perform these
  4. * operations. Another reason is that conjunction and disjunction require
  5. * short-circuit evaluation. In the examples below, `b1` and `b2` are
  6. * expressions of type boolean, `i` is of type int and `f` is of type float.
  7. *
  8. * > b1 == b2 ==> (int)b1 == (int)b2
  9. * > b1 != b2 ==> (int)b1 != (int)b2
  10. * > b1 && b2 ==> b1 ? b2 : false
  11. * > b1 || b2 ==> b1 ? true : b2
  12. * > b1 + b2 ==> (bool)((int)b1 + (int)b2)
  13. * > b1 * b2 ==> (bool)((int)b1 * (int)b2)
  14. * > (bool)i ==> i != 0
  15. * > (bool)f ==> f != 0.0
  16. * > (int)b1 ==> b1 ? 1 : 0
  17. * > (float)b1 ==> b1 ? 1.0 : 0.0
  18. *)
  19. open Types
  20. open Util
  21. let cast ctype node = TypeCast (ctype, node, [Type ctype])
  22. let boolconst value = Const (BoolVal value, [Type Bool])
  23. let intconst value = Const (IntVal value, [Type Int])
  24. let floatconst value = Const (FloatVal value, [Type Float])
  25. let rec trav_binop = function
  26. | ((Eq | Ne) as op, left, right, loc) ->
  27. Binop (op, cast Int (bool_op left), cast Int (bool_op right), loc)
  28. | (And, left, right, loc) ->
  29. Cond (bool_op left, bool_op right, boolconst false, loc)
  30. | (Or, left, right, loc) ->
  31. Cond (bool_op left, boolconst true, bool_op right, loc)
  32. | ((Add | Mul) as op, left, right, loc) ->
  33. cast Bool (Binop (op, cast Int (bool_op left), cast Int (bool_op right), loc))
  34. | (op, left, right, loc) ->
  35. Binop (op, bool_op left, bool_op right, loc)
  36. and bool_op = function
  37. | Binop (op, left, right, loc) when typeof left = Bool && typeof right = Bool ->
  38. trav_binop (op, left, right, loc)
  39. | TypeCast (Bool, value, loc) when typeof value = Int ->
  40. Binop (Ne, value, intconst 0, loc)
  41. | TypeCast (Bool, value, loc) when typeof value = Float ->
  42. Binop (Ne, value, floatconst 0.0, loc)
  43. | TypeCast (Int, value, loc) when typeof value = Bool ->
  44. Cond (value, intconst 1, intconst 0, loc)
  45. | TypeCast (Float, value, loc) when typeof value = Bool ->
  46. Cond (value, floatconst 1.0, floatconst 0.0, loc)
  47. | node -> transform_children bool_op node
  48. let rec phase input =
  49. log_line 1 "- Convert bool operations";
  50. match input with
  51. | Ast node -> Ast (bool_op node)
  52. | _ -> raise (InvalidInput "bool operations")