| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- (**
- * The phase applies the transformations shown below. These transformations are
- * required because the CiviC VM does not offer instructions that perform these
- * operations. Another reason is that conjunction and disjunction require
- * short-circuit evaluation. In the examples below, `b1` and `b2` are
- * expressions of type boolean, `i` is of type int and `f` is of type float.
- *
- * > b1 == b2 ==> (int)b1 == (int)b2
- * > b1 != b2 ==> (int)b1 != (int)b2
- * > b1 && b2 ==> b1 ? b2 : false
- * > b1 || b2 ==> b1 ? true : b2
- * > b1 + b2 ==> (bool)((int)b1 + (int)b2)
- * > b1 * b2 ==> (bool)((int)b1 * (int)b2)
- * > (bool)i ==> i != 0
- * > (bool)f ==> f != 0.0
- * > (int)b1 ==> b1 ? 1 : 0
- * > (float)b1 ==> b1 ? 1.0 : 0.0
- *)
- open Types
- open Util
- let cast ctype node = TypeCast (ctype, node, [Type ctype])
- let boolconst value = BoolConst (value, [Type Bool])
- let intconst value = IntConst (value, [Type Int])
- let floatconst value = FloatConst (value, [Type Float])
- let rec trav_binop = function
- | ((Eq | Ne) as op, left, right, loc) ->
- Binop (op, cast Int left, cast Int right, loc)
- | (And, left, right, loc) ->
- Cond (left, right, boolconst false, loc)
- | (Or, left, right, loc) ->
- Cond (left, boolconst true, right, loc)
- | ((Add | Mul) as op, left, right, loc) ->
- cast Bool (Binop (op, cast Int left, cast Int right, loc))
- | (op, left, right, loc) ->
- Binop (op, left, right, loc)
- and bool_op = function
- | Binop (op, left, right, loc) when typeof left = Bool && typeof right = Bool ->
- trav_binop (op, left, right, loc)
- | TypeCast (Bool, value, loc) when typeof value = Int ->
- Binop (Ne, value, intconst 0, loc)
- | TypeCast (Bool, value, loc) when typeof value = Float ->
- Binop (Ne, value, floatconst 0.0, loc)
- | TypeCast (Int, value, loc) when typeof value = Bool ->
- Cond (value, intconst 1, intconst 0, loc)
- | TypeCast (Float, value, loc) when typeof value = Bool ->
- Cond (value, floatconst 1.0, floatconst 0.0, loc)
- | node -> transform_children bool_op node
- let rec phase input =
- log_line 2 "- Convert bool operations";
- match input with
- | Types node -> Types (bool_op node)
- | _ -> raise (InvalidInput "bool operations")
|