namespace imp open tactic @[reducible] def uname := string inductive aexp | val : nat → aexp | var : uname → aexp | plus : aexp → aexp → aexp | times : aexp → aexp → aexp instance : decidable_eq aexp := by mk_dec_eq_instance @[reducible] def value := nat def state := uname → value open aexp def aval : aexp → state → value | (val n) s := n | (var x) s := s x | (plus a₁ a₂) s := aval a₁ s + aval a₂ s | (times a₁ a₂) s := aval a₁ s * aval a₂ s example : aval (plus (val 3) (var "x")) (λ x, 0) = 3 := rfl def updt (s : state) (x : uname) (v : value) : state := λ y, if x = y then v else s y def asimp_const : aexp → aexp | (val n) := val n | (var x) := var x | (plus a₁ a₂) := match asimp_const a₁, asimp_const a₂ with | val n₁, val n₂ := val (n₁ + n₂) | b₁, b₂ := plus b₁ b₂ end | (times a₁ a₂) := match asimp_const a₁, asimp_const a₂ with | val n₁, val n₂ := val (n₁ * n₂) | b₁, b₂ := times b₁ b₂ end example : asimp_const (plus (plus (val 2) (val 3)) (var "x")) = plus (val 5) (var "x") := rfl attribute [ematch] asimp_const aval -- set_option trace.smt.ematch true meta def not_done : tactic unit := fail_if_success now lemma aval_asimp_const (a : aexp) (s : state) : aval (asimp_const a) s = aval a s := begin [smt] induction a, all_goals {destruct (asimp_const a_1), all_goals {destruct (asimp_const a_2), eblast}} end lemma ex2 (a : aexp) (s : state) : aval (asimp_const a) s = aval a s := begin [smt] induction a, all_goals {destruct (asimp_const a_1), all_goals {destruct (asimp_const a_2), eblast_using [asimp_const, aval]}} end end imp