|
| 1 | +/- |
| 2 | +Copyright (c) 2025 Robert Maxton. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Robert Maxton |
| 5 | +-/ |
| 6 | +module |
| 7 | + |
| 8 | +public import Mathlib.Init |
| 9 | +public meta import Lean.PrettyPrinter.Delaborator.Builtins |
| 10 | + |
| 11 | +/-! Delab checking canonicity. |
| 12 | +
|
| 13 | +Provides a series of monadic functions in `DelabM` for delaborating expressions differently |
| 14 | +if their given instances differ (by definitional equality) with what is synthesized. |
| 15 | +Synthesized instances are considered 'canonical' for this purpose. |
| 16 | +-/ |
| 17 | + |
| 18 | +public meta section |
| 19 | + |
| 20 | +/-- When the delab reader is pointed at an expression for an instance, returns `(true, t)` |
| 21 | +**iff** instance synthesis succeeds and produces a defeq instance; otherwise returns `(false, t)`. |
| 22 | +-/ |
| 23 | +def delabCheckingCanonical : DelabM (Bool × Term) := do |
| 24 | + let instD ← delab |
| 25 | + let inst ← getExpr |
| 26 | + let type ← inferType inst |
| 27 | + -- if there is no synthesized instance, still return `false` |
| 28 | + -- (because `inst` is still non-canonical) |
| 29 | + let .some synthInst ← Meta.trySynthInstance type | return (false, instD) |
| 30 | + return (← Meta.isDefEq inst synthInst, instD) |
| 31 | + |
| 32 | +/-- Delaborate an expression with arity `arity` into a unary notation `mkStx` iff the argument |
| 33 | +`arg` is a non-canonical instance (is not defeq to what is synthesized for its type, or else |
| 34 | +instance synthesis fails). -/ |
| 35 | +def delabUnary (arity arg : ℕ) (mkStx : Term → DelabM Term) : Delab := |
| 36 | + withOverApp arity <| whenPPOption Lean.getPPNotation do |
| 37 | + let (false, instD) ← withNaryArg arg delabCheckingCanonical | failure |
| 38 | + mkStx instD |
| 39 | + |
| 40 | +/-- Delaborate an expression with arity `arity` into a binary notation `mkStx` iff either |
| 41 | +argument `arg₁` or `arg₂` are non-canonical instance (are not defeq to what is synthesized for |
| 42 | +its type, or else instance synthesis fails). -/ |
| 43 | +def delabBinary (arity arg₁ arg₂ : ℕ) (mkStx : Term → Term → DelabM Term) : Delab := |
| 44 | + withOverApp arity <| whenPPOption Lean.getPPNotation do |
| 45 | + let (canonα?, instDα) ← withNaryArg arg₁ delabCheckingCanonical |
| 46 | + let (canonβ?, instDβ) ← withNaryArg arg₂ delabCheckingCanonical |
| 47 | + -- fall through to normal delab if both canonical |
| 48 | + if canonα? && canonβ? then failure |
0 commit comments