summaryrefslogblamecommitdiff
path: root/minijazz/src/global/static_utils.ml
blob: f95ce304fa73fdf4b589e2f0999f17b2ba522495 (plain) (tree)











































































                                                                          
open Static

let pow a n =
  let rec g p x = function
  | 0 -> x
  | i ->
      g (p * p) (if i mod 2 = 1 then p * x else x) (i/2)
  in
  g a 1 n
;;


let fun_of_op op = match op with
  | SAdd -> (+) | SMinus -> (-)
  | SMult -> (fun i1 i2 -> i1 * i2)
  | SDiv -> (/)
  | SPower -> pow
  | _ -> assert false

let fun_of_comp_op op = match op with
  | SEqual -> (=) | SLeq -> (<=)  | SLess -> (<)
  | _ -> assert false

let rec simplify env se = match se.se_desc with
  | SInt _ | SBool _ -> se
  | SVar n ->
      (try
         let se = NameEnv.find n env in
         simplify env se
        with
          | Not_found -> se)
  | SBinOp(op, se1, se2) ->
      let se1 = simplify env se1 in
      let se2 = simplify env se2 in
      let desc =
        match op, se1.se_desc, se2.se_desc with
          | (SAdd | SMinus | SDiv  | SMult | SPower), SInt i1, SInt i2 ->
              let f = fun_of_op op in
              SInt (f i1 i2)
        | (SEqual | SLess | SLeq | SGreater | SGeq), SInt i1, SInt i2 ->
            let f = fun_of_comp_op op in
            SBool (f i1 i2)
        | _, _, _ -> SBinOp(op, se1, se2)
      in
      { se with se_desc = desc }
  | SIf(c, se1, se2) ->
      let c = simplify env c in
      let se1 = simplify env se1 in
      let se2 = simplify env se2 in
      (match c.se_desc, se1.se_desc, se2.se_desc with
        | SBool true, _, _ -> se1
        | SBool false, _, _ -> se2
        | _, sed1, sed2 when sed1 = sed2 -> { se with se_desc = sed1 }
        | _, _, _ -> { se with se_desc = SIf(c, se1, se2) })

let rec subst env se = match se.se_desc with
  | SInt _ | SBool _ -> se
  | SVar n ->
      (try
          NameEnv.find n env
        with
          | Not_found -> se)
  | SBinOp(op, se1, se2) ->
      { se with se_desc = SBinOp(op, subst env se1, subst env se2) }
  | SIf(c, se1, se2) ->
      { se with se_desc = SIf(subst env c, subst env se1, subst env se2) }

exception Unsatisfiable of static_exp
let check_true env cl =
  let check_one c =
    let res = simplify env c in
    match res.se_desc with
      | SBool true -> ()
      | _ -> raise (Unsatisfiable c)
  in
  List.iter check_one cl