blob: 58951671aa5b4eb0f6f2d71cacc841afce6b96f1 [file] [edit]
import Std
open Std
open Lean
inductive BoolExpr where
| var (name : String)
| val (b : Bool)
| or (p q : BoolExpr)
| not (p : BoolExpr)
deriving Repr, BEq, DecidableEq
def BoolExpr.isValue : BoolExpr → Bool
| val _ => true
| _ => false
instance : Inhabited BoolExpr where
default := BoolExpr.val false
namespace BoolExpr
deriving instance DecidableEq for BoolExpr
#eval decide (BoolExpr.val true = BoolExpr.val false)
#check (a b : BoolExpr) → Decidable (a = b)
abbrev Context := AssocList String Bool
def denote (ctx : Context) : BoolExpr → Bool
| BoolExpr.or p q => denote ctx p || denote ctx q
| BoolExpr.not p => !denote ctx p
| BoolExpr.val b => b
| BoolExpr.var x => if let some b := ctx.find? x then b else false
def simplify : BoolExpr → BoolExpr
| or p q => mkOr (simplify p) (simplify q)
| not p => mkNot (simplify p)
| e => e
where
mkOr : BoolExpr → BoolExpr → BoolExpr
| p, val true => val true
| p, val false => p
| val true, p => val true
| val false, p => p
| p, q => or p q
mkNot : BoolExpr → BoolExpr
| val b => val (!b)
| p => not p
@[simp] theorem denote_not_Eq (ctx : Context) (p : BoolExpr) : denote ctx (not p) = !denote ctx p := rfl
@[simp] theorem denote_or_Eq (ctx : Context) (p q : BoolExpr) : denote ctx (or p q) = (denote ctx p || denote ctx q) := rfl
@[simp] theorem denote_val_Eq (ctx : Context) (b : Bool) : denote ctx (val b) = b := rfl
@[simp] theorem denote_mkNot_Eq (ctx : Context) (p : BoolExpr) : denote ctx (simplify.mkNot p) = denote ctx (not p) := by
cases p <;> rfl
@[simp] theorem mkOr_p_true (p : BoolExpr) : simplify.mkOr p (val true) = val true := by
cases p with
| val x => cases x <;> rfl
| _ => rfl
@[simp] theorem mkOr_p_false (p : BoolExpr) : simplify.mkOr p (val false) = p := by
cases p with
| val x => cases x <;> rfl
| _ => rfl
@[simp] theorem mkOr_true_p (p : BoolExpr) : simplify.mkOr (val true) p = val true := by
cases p with
| val x => cases x <;> rfl
| _ => rfl
@[simp] theorem mkOr_false_p (p : BoolExpr) : simplify.mkOr (val false) p = p := by
cases p with
| val x => cases x <;> rfl
| _ => rfl
@[simp] theorem denote_mkOr (ctx : Context) (p q : BoolExpr) : denote ctx (simplify.mkOr p q) = denote ctx (or p q) := by
cases p with
| val x => cases q with
| val y => cases x <;> cases y <;> simp
| _ => cases x <;> simp
| _ => cases q with
| val y => cases y <;> simp
| _ => rfl
@[simp] theorem simplify_not (p : BoolExpr) : simplify (not p) = simplify.mkNot (simplify p) := rfl
@[simp] theorem simplify_or (p q : BoolExpr) : simplify (or p q) = simplify.mkOr (simplify p) (simplify q) := rfl
def denote_simplify_eq (ctx : Context) (b : BoolExpr) : denote ctx (simplify b) = denote ctx b :=
by induction b with
| or p q ih₁ ih₂ => simp [ih₁, ih₂]
| not p ih => simp [ih]
| _ => rfl
syntax "`[BExpr|" term "]" : term
macro_rules
| `(`[BExpr| true]) => `(val true)
| `(`[BExpr| false]) => `(val false)
| `(`[BExpr| $x:ident]) => `(var $(quote x.getId.toString))
| `(`[BExpr| $p ∨ $q]) => `(or `[BExpr| $p] `[BExpr| $q])
| `(`[BExpr| ¬ $p]) => `(not `[BExpr| $p])
#check `[BExpr| ¬ p ∨ q]
syntax entry := ident " ↦ " term:max
syntax entry,* "⊢" term : term
macro_rules
| `( $[$xs:ident ↦ $vs:term],* ⊢ $p:term ) =>
let xs := xs.map fun x => quote x.getId.toString
`(denote (List.toAssocList [$[( $xs , $vs )],*]) `[BExpr| $p])
#check b ↦ true ⊢ b ∨ b
#eval a ↦ false, b ↦ false ⊢ b ∨ a