(** * 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 Ast open Util let cast ctype node = Type (TypeCast (ctype, node, noloc), ctype) let boolconst value = Type (BoolConst (value, noloc), Bool) let intconst value = Type (IntConst (value, noloc), Int) let floatconst value = Type (FloatConst (value, noloc), 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, (Type (_, Bool) as left), (Type (_, Bool) as right), loc) -> trav_binop (op, left, right, loc) | TypeCast (Bool, (Type (_, Int) as value), loc) -> Binop (Ne, value, intconst 0, loc) | TypeCast (Bool, (Type (_, Float) as value), loc) -> Binop (Ne, value, floatconst 0.0, loc) | TypeCast (Int, (Type (_, Bool) as value), loc) -> Cond (value, intconst 1, intconst 0, loc) | TypeCast (Float, (Type (_, Bool) as value), loc) -> Cond (value, floatconst 1.0, floatconst 0.0, loc) | node -> transform_children bool_op node let rec phase input = prerr_endline "- Convert bool operations"; match input with | Ast node -> Ast (bool_op node) | _ -> raise (InvalidInput "bool operations")