pretty printing
This commit is contained in:
parent
21465b897f
commit
0f39cb7fa3
4 changed files with 80 additions and 0 deletions
|
|
@ -44,3 +44,65 @@ let rec occurs t = function
|
||||||
| Iff (phi, psi) -> occurs t phi || occurs t psi
|
| Iff (phi, psi) -> occurs t phi || occurs t psi
|
||||||
| Forall phi -> occurs (Term.inc_var t) phi
|
| Forall phi -> occurs (Term.inc_var t) phi
|
||||||
| Exists phi -> occurs (Term.inc_var t) phi
|
| Exists phi -> occurs (Term.inc_var t) phi
|
||||||
|
|
||||||
|
type precedence =
|
||||||
|
| Atomic
|
||||||
|
| Negation
|
||||||
|
| Conjunction
|
||||||
|
| Disjunction
|
||||||
|
| Implication
|
||||||
|
| Biconditional
|
||||||
|
| Quantifier
|
||||||
|
|
||||||
|
let precedence_of = function
|
||||||
|
| Relation _ | Equal _ | Bottom -> Atomic
|
||||||
|
| Neg _ -> Negation
|
||||||
|
| Conj _ -> Conjunction
|
||||||
|
| Disj _ -> Disjunction
|
||||||
|
| Impl _ -> Implication
|
||||||
|
| Iff _ -> Biconditional
|
||||||
|
| Forall _ | Exists _ -> Quantifier
|
||||||
|
|
||||||
|
open Format
|
||||||
|
|
||||||
|
let fresh_var_name used_names =
|
||||||
|
let base_names = [ "x"; "y"; "z"; "w"; "u"; "v" ] in
|
||||||
|
let rec find_name i =
|
||||||
|
let name =
|
||||||
|
if i < List.length base_names then List.nth base_names i
|
||||||
|
else sprintf "x%d" (i - List.length base_names + 1)
|
||||||
|
in
|
||||||
|
if List.mem name used_names then find_name (i + 1) else name
|
||||||
|
in
|
||||||
|
find_name 0
|
||||||
|
|
||||||
|
let to_string formula =
|
||||||
|
let rec aux depth binders parent_precedence formula =
|
||||||
|
let current_precedence = precedence_of formula in
|
||||||
|
let step = aux depth binders current_precedence in
|
||||||
|
|
||||||
|
let inner_string =
|
||||||
|
match formula with
|
||||||
|
| Relation (r, terms) ->
|
||||||
|
sprintf "%s(%s)" r
|
||||||
|
(String.concat ", " (List.map (Term.to_string ~binders) terms))
|
||||||
|
| Equal (t1, t2) ->
|
||||||
|
sprintf "%s = %s"
|
||||||
|
(Term.to_string ~binders t1)
|
||||||
|
(Term.to_string ~binders t2)
|
||||||
|
| Bottom -> "⊥"
|
||||||
|
| Neg f -> sprintf "¬%s" (aux depth binders Negation f)
|
||||||
|
| Conj (f1, f2) -> sprintf "%s ∧ %s" (step f1) (step f2)
|
||||||
|
| Disj (f1, f2) -> sprintf "%s ∨ %s" (step f1) (step f2)
|
||||||
|
| Impl (f1, f2) -> sprintf "%s → %s" (step f1) (step f2)
|
||||||
|
| Iff (f1, f2) -> sprintf "%s ↔ %s" (step f1) (step f2)
|
||||||
|
| Forall f | Exists f ->
|
||||||
|
let new_var = fresh_var_name binders in
|
||||||
|
let quantifier = if Forall f = formula then "∀" else "∃" in
|
||||||
|
sprintf "%s%s.%s" quantifier new_var
|
||||||
|
(aux (depth + 1) (new_var :: binders) Quantifier f)
|
||||||
|
in
|
||||||
|
if parent_precedence < current_precedence then "(" ^ inner_string ^ ")"
|
||||||
|
else inner_string
|
||||||
|
in
|
||||||
|
aux 0 [] Quantifier formula
|
||||||
|
|
|
||||||
|
|
@ -12,3 +12,4 @@ type t =
|
||||||
|
|
||||||
val match_term : Term.t -> t -> t -> Term.match_result
|
val match_term : Term.t -> t -> t -> Term.match_result
|
||||||
val occurs : Term.t -> t -> bool
|
val occurs : Term.t -> t -> bool
|
||||||
|
val to_string : t -> string
|
||||||
|
|
|
||||||
13
lib/term.ml
13
lib/term.ml
|
|
@ -40,3 +40,16 @@ let rec inc_var = function
|
||||||
let rec occurs t = function
|
let rec occurs t = function
|
||||||
| Function (_, ts) -> List.exists (occurs t) ts
|
| Function (_, ts) -> List.exists (occurs t) ts
|
||||||
| s -> t = s
|
| s -> t = s
|
||||||
|
|
||||||
|
exception UnboundVariable
|
||||||
|
|
||||||
|
let to_string ~binders =
|
||||||
|
let open Format in
|
||||||
|
let rec aux = function
|
||||||
|
| Var v -> ( try List.nth binders v with _ -> raise UnboundVariable)
|
||||||
|
| Const c -> c
|
||||||
|
| Free f -> f
|
||||||
|
| Function (f, args) ->
|
||||||
|
sprintf "%s(%s)" f (String.concat ", " (List.map aux args))
|
||||||
|
in
|
||||||
|
aux
|
||||||
|
|
|
||||||
|
|
@ -12,3 +12,7 @@ val merge_result : match_result -> match_result -> match_result
|
||||||
val match_term : t -> t -> t -> match_result
|
val match_term : t -> t -> t -> match_result
|
||||||
val inc_var : t -> t
|
val inc_var : t -> t
|
||||||
val occurs : t -> t -> bool
|
val occurs : t -> t -> bool
|
||||||
|
|
||||||
|
exception UnboundVariable
|
||||||
|
|
||||||
|
val to_string : binders:string list -> t -> string
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue