{-# OPTIONS --safe --without-K #-}
open import Prelude
module Utils.Reflection.Print where
open import Utils.Reflection.Core
open import Utils.Reflection.Term
open import Utils.Reflection.Eq
open import Utils.Reflection.Tactic
open import Utils.Reflection.Show
infoName = "print"
verbosity = 5
private
variable
A : Set _
pattern space = strErr " "
pattern colon = strErr " : "
paren : Visibility → ErrorParts → ErrorParts
paren v s = case v of λ where
visible → [ strErr "(" ] <> s <> [ strErr ")" ]
hidden → [ strErr "{" ] <> s <> [ strErr "}" ]
instance′ → [ strErr "⦃ "] <> s <> [ strErr " ⦄"]
sep : ErrorParts → ErrorParts
sep [] = []
sep (e ∷ []) = e ∷ []
sep (e ∷ es) = e ∷ space ∷ sep es
record ToErr (A : Set) : Set₀ where
field
toErr : A → ErrorParts
open ToErr ⦃...⦄ public
instance
ArgErr : ⦃ _ : ToErr A ⦄ → ToErr (Arg A)
ArgErr .toErr a = paren (getVisibility a) (toErr (unArg a))
instance
ListErr : ⦃ _ : ToErr A ⦄ → ToErr (List A)
ListErr .toErr = sep ∘ concatMap toErr
TermErr : ToErr Term
TermErr .toErr = [_] ∘ termErr
PattErr : ToErr Pattern
PattErr .toErr = [_] ∘ pattErr
NameErr : ToErr Name
NameErr .toErr = [_] ∘ nameErr
StrErr : ToErr String
StrErr .toErr = [_] ∘ strErr
vcat : List String → String
vcat [] = ""
vcat (msg ∷ []) = msg
vcat (msg ∷ msgs) = msg <> "\n" <> vcat msgs
nest : List String → List String
nest = map (" " <>_)
mergeSpace : ErrorParts → ErrorParts
mergeSpace [] = []
mergeSpace (space ∷ space ∷ msg) = mergeSpace (space ∷ msg)
mergeSpace (err ∷ errs) = err ∷ mergeSpace errs
printArg : (showImplicit : Bool) → String → Arg A → (A → TC ErrorParts) → TC ErrorParts
printArg b s x f = case getVisibility x of λ where
visible → do
err ← f (unArg x)
return $ if elem space err
then paren visible err
else err
v → if b
then (f (unArg x) >>= λ err →
(return $ paren v (strErr (s <> " = ") ∷ err)))
else return []
printTelescope : Telescope → TC ErrorParts → TC ErrorParts
printTelescope [] m = m
printTelescope ((s , x) ∷ []) m = do
ss ← extendContext s x m
s ← extendContext s x (formatErrorParts $ toErr (var₀ 0))
ts ← formatErrorParts $ toErr $ unArg x
return $ paren (getVisibility x) (toErr s <> colon ∷ toErr ts) <> ss
printTelescope ((s , x) ∷ tel) m = do
ss ← extendContext s x $ printTelescope tel m
s ← extendContext s x (formatErrorParts $ toErr (var₀ 0))
ts ← formatErrorParts $ toErr $ unArg x
return $ paren (getVisibility x) (toErr s <> space ∷ toErr ":" <> space ∷ toErr ts) <> space ∷ ss
printDataSignature : (tel : Telescope) → Type → TC ErrorParts
printDataSignature tel a = printTelescope tel do
a ← formatErrorParts $ toErr a
return $ space ∷ toErr ":" <> space ∷ toErr a
printCon : (pars : ℕ) → (c : Name) → TC String
printCon pars c = do
x ← getType c
let a = snd $ splitType pars x
formatErrorParts $ nameErr c ∷ space ∷ strErr ":" ∷ space ∷ termErr a ∷ []
printCons : (pars : ℕ) → (cs : Names) → TC (List String)
printCons pars = mapM (printCon pars)
printData : Name → TC ⊤
printData d = do
pars , cs ← getDataDefinition d
x ← getType d
let tel , a = splitType pars x
sig ← printDataSignature tel a
decl ← formatErrorParts $ mergeSpace $
strErr "data" ∷ space ∷ nameErr d ∷ space ∷ [] <> sig <> space ∷ strErr "where" ∷ []
cons ← vcat ∘ nest <$> extend*Context tel (printCons pars cs)
debugPrint infoName verbosity $ [ strErr (vcat $ decl ∷ cons ∷ []) ]
printConAs : (String × Type) → TC String
printConAs (s , T) = do
formatErrorParts $ strErr s ∷ space ∷ strErr ":" ∷ space ∷ termErr T ∷ []
printConsAs : List (String × Type) → TC (List String)
printConsAs = mapM printConAs
printDataAs : (String × Type × ℕ) → List (String × Type) → TC String
printDataAs (s , T , pars) cs = do
let tel , a = splitType pars T
sig ← printDataSignature tel a
decl ← formatErrorParts $ mergeSpace $
strErr "data" ∷ space ∷ strErr s ∷ space ∷ [] <> sig <> space ∷ strErr "where" ∷ []
cons ← vcat ∘ nest <$> extend*Context tel (printConsAs cs)
return (vcat $ decl ∷ cons ∷ [])
hideDot : Args Pattern → Args Pattern
hideDot = map λ where
(arg i (dot t)) → arg i (dot unknown)
t → t
removeImplicitDot : Args Pattern → Args Pattern
removeImplicitDot = filter λ where
(arg (arg-info hidden _) (dot _)) → false
t → true
printPattern : Pattern → TC ErrorParts
printPattern (con c as@(_ ∷ _)) = return $
paren visible (toErr $ con c (hideDot $ removeImplicitDot as))
printPattern p = return $ toErr p
PVarIsT : Cxt → Term → Pattern → Bool
PVarIsT Γ (var x args) (var y) = x == y + Cxt.len Γ
PVarIsT _ _ _ = false
termHasPat : Term → Pattern → Bool
termHasPat t p = anyVisibleTerm (λ Γ t → PVarIsT Γ t p) (0 , []) t
isUsed : Pattern → Term → Bool
isUsed p t = anyPat (termHasPat t) p
printNecessaryPattern : Term → String → Arg Pattern → TC ErrorParts
printNecessaryPattern t s p = if isUsed (unArg p) t then
printArg true s p printPattern
else
printArg false s p printPattern
printPatterns : Bool → Term → Telescope → Args Pattern → TC ErrorParts
printPatterns b t _ [] = ⦇ [] ⦈
printPatterns b t (n ∷ _) (p ∷ []) = if b then printArg true (fst n) p printPattern
else printNecessaryPattern t (fst n) p
printPatterns b t (n ∷ ns) (p ∷ ps) = do
p ← if b then printArg true (fst n) p printPattern
else printNecessaryPattern t (fst n) p
ps ← printPatterns b t ns ps
return $ p <> space ∷ ps
printPatterns _ _ _ _ = typeError [ strErr "Length of Type and Patterns doesn't match." ]
printClause : Bool → (f : Name) → Telescope → Clause → TC String
printClause b f ns (tel ⊢ ps `= t) = do
tel ← renameUnderscore tel
extend*Context tel do
ps ← mergeSpace ∘ dropWhile (space ==_) <$> printPatterns b t ns ps
formatErrorParts $ (nameErr f ∷ space ∷ ps) <> space ∷ strErr "=" ∷ space ∷ termErr t ∷ []
printClause b f ns (absurd-clause tel ps) = extend*Context tel do
formatErrorParts =<< (λ ps → nameErr f ∷ space ∷ ps) ∘ mergeSpace <$> printPatterns b unknown ns ps
printClauses : Bool → Name → Telescope → Clauses → TC (List String)
printClauses b f tel = mapM (printClause b f tel)
printSig : Name → TC ErrorParts
printSig f = do
a ← getType f
return $ nameErr f ∷ space ∷ strErr ":" ∷ space ∷ termErr a ∷ []
printFunction : Bool → Name → TC ⊤
printFunction b f = do
`A , cs ← getFunction f
a ← ⇑_ <$> getType f
css ← printClauses b f (fst a) cs
debugPrint infoName verbosity =<< printSig f
debugPrint infoName verbosity $ [ strErr (vcat css) ]
return tt
macro
print : Name → Tactic
print d hole = do
`dT ← getType d
caseM getDefinition d of λ where
(function _) → printFunction false d
(data-type pars cs) → printData d
(record-type c fs) → typeError $
strErr "Printing the definition of a record type is currently not supported." ∷ []
_ → printSig d >>= debugPrint infoName verbosity
return tt