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