diff options
author | Greg Brown <greg.brown01@ed.ac.uk> | 2023-01-01 12:11:50 +0000 |
---|---|---|
committer | Greg Brown <greg.brown01@ed.ac.uk> | 2023-01-01 12:11:50 +0000 |
commit | 7e184c20d545afb55f6e962b8bfea882b23699fa (patch) | |
tree | 8eb3a3dbf230ef959ffc77019127cf5d78a2aada | |
parent | 34c8ab97457d3c727947635fbb3ae36545908867 (diff) |
Index normal forms with relevance.
- Remove container types.
- Replace sum types with booleans.
- Remove type annotation from absurd.
- Add original type as argument to cast.
- Make if (was case) take a lambda for the return type.
-rw-r--r-- | obs.ipkg | 1 | ||||
-rw-r--r-- | src/Obs/Abstract.idr | 60 | ||||
-rw-r--r-- | src/Obs/Logging.idr | 106 | ||||
-rw-r--r-- | src/Obs/Main.idr | 2 | ||||
-rw-r--r-- | src/Obs/NormalForm.idr | 404 | ||||
-rw-r--r-- | src/Obs/NormalForm/Normalise.idr | 631 | ||||
-rw-r--r-- | src/Obs/Parser.idr | 116 | ||||
-rw-r--r-- | src/Obs/Substitution.idr | 90 | ||||
-rw-r--r-- | src/Obs/Syntax.idr | 153 | ||||
-rw-r--r-- | src/Obs/Term.idr | 168 | ||||
-rw-r--r-- | src/Obs/Typing.idr | 578 | ||||
-rw-r--r-- | src/Obs/Typing/Context.idr | 108 | ||||
-rw-r--r-- | src/Obs/Typing/Conversion.idr | 259 |
13 files changed, 1299 insertions, 1377 deletions
@@ -19,4 +19,5 @@ modules , Obs.Syntax , Obs.Term , Obs.Typing + , Obs.Typing.Context , Obs.Typing.Conversion diff --git a/src/Obs/Abstract.idr b/src/Obs/Abstract.idr index 48709c1..b32af2d 100644 --- a/src/Obs/Abstract.idr +++ b/src/Obs/Abstract.idr @@ -51,54 +51,21 @@ abstractSyntax ctx (Fst t) = do abstractSyntax ctx (Snd t) = do t <- abstractSyntaxBounds ctx t pure (Snd t) -abstractSyntax ctx (Sum a b) = do - a <- abstractSyntaxBounds ctx a - b <- abstractSyntaxBounds ctx b - pure (Sum a b) -abstractSyntax ctx (Left t) = do - t <- abstractSyntaxBounds ctx t - pure (Left t) -abstractSyntax ctx (Right t) = do +abstractSyntax ctx Bool = pure Bool +abstractSyntax ctx True = pure True +abstractSyntax ctx False = pure False +abstractSyntax ctx (If var a t f g) = do + a <- abstractSyntaxBounds (bind ctx var.val) a t <- abstractSyntaxBounds ctx t - pure (Right t) -abstractSyntax ctx (Case t s b f g) = do - t <- abstractSyntaxBounds ctx t - s <- abstractSyntaxBounds ctx s - b <- abstractSyntaxBounds ctx b f <- abstractSyntaxBounds ctx f g <- abstractSyntaxBounds ctx g - pure (Case t s b f g) -abstractSyntax ctx (Container a s s') = do - a <- abstractSyntaxBounds ctx a - s <- abstractSyntaxBounds ctx s - s' <- abstractSyntaxBounds ctx s' - pure (Container a s s') -abstractSyntax ctx (MkContainer t p f) = do - t <- abstractSyntaxBounds ctx t - p <- abstractSyntaxBounds ctx p - f <- abstractSyntaxBounds ctx f - pure (MkContainer t p f) -abstractSyntax ctx (Tag t) = do - t <- abstractSyntaxBounds ctx t - pure (Tag t) -abstractSyntax ctx (Position t) = do - t <- abstractSyntaxBounds ctx t - pure (Position t) -abstractSyntax ctx (Next t) = do - t <- abstractSyntaxBounds ctx t - pure (Next t) -abstractSyntax ctx (Sem s a t) = do - s <- abstractSyntaxBounds ctx s - a <- abstractSyntaxBounds ctx a - t <- abstractSyntaxBounds ctx t - pure (Sem s a t) + pure (If var a t f g) abstractSyntax ctx Top = pure Top abstractSyntax ctx Point = pure Point abstractSyntax ctx Bottom = pure Bottom -abstractSyntax ctx (Absurd a t) = do - a <- abstractSyntaxBounds ctx a +abstractSyntax ctx (Absurd t) = do t <- abstractSyntaxBounds ctx t - pure (Absurd a t) + pure (Absurd t) abstractSyntax ctx (Equal t u) = do t <- abstractSyntaxBounds ctx t u <- abstractSyntaxBounds ctx u @@ -106,18 +73,19 @@ abstractSyntax ctx (Equal t u) = do abstractSyntax ctx (Refl t) = do t <- abstractSyntaxBounds ctx t pure (Refl t) -abstractSyntax ctx (Transp t b u t' e) = do +abstractSyntax ctx (Transp a t u t' e) = do + a <- abstractSyntaxBounds ctx a t <- abstractSyntaxBounds ctx t - b <- abstractSyntaxBounds ctx b u <- abstractSyntaxBounds ctx u t' <- abstractSyntaxBounds ctx t' e <- abstractSyntaxBounds ctx e - pure (Transp t b u t' e) -abstractSyntax ctx (Cast b e t) = do + pure (Transp a t u t' e) +abstractSyntax ctx (Cast a b e t) = do + a <- abstractSyntaxBounds ctx a b <- abstractSyntaxBounds ctx b e <- abstractSyntaxBounds ctx e t <- abstractSyntaxBounds ctx t - pure (Cast b e t) + pure (Cast a b e t) abstractSyntax ctx (CastId t) = do t <- abstractSyntaxBounds ctx t pure (CastId t) diff --git a/src/Obs/Logging.idr b/src/Obs/Logging.idr index 0761775..ef0bae6 100644 --- a/src/Obs/Logging.idr +++ b/src/Obs/Logging.idr @@ -1,7 +1,5 @@ module Obs.Logging -import Data.List.Lazy - import System import Text.Bounded @@ -40,60 +38,96 @@ Ord Level where record Message (ann : Type) where constructor MkMessage - lvl : Level - msg : Doc ann + lvl : Level + msg : Doc ann + bounds : Maybe Bounds tags : List String pretty : Message ann -> Doc ann pretty msg = - hsep $ - [ fill 6 (pretty (show msg.lvl) <+> colon) ] ++ - reverse (map (\s => pretty s <+> colon) msg.tags) ++ - [ align msg.msg ] + let leader = + hsep $ + [ fill 6 (pretty (show msg.lvl) <+> colon) ] ++ + [ Doc.pretty $ concat {t = List} $ + case msg.bounds of + Nothing => [] + Just bounds => + [ show (1 + bounds.startLine) + , ":" + , show bounds.startCol + , "--" + , show (1 + bounds.endLine) + , ":" + , show bounds.endCol + , ":" + ] + ] ++ + map (\s => pretty s <+> colon) msg.tags + in group $ width (group leader <+> line) (\width => group $ indent (2 - width) msg.msg) -- Logging Monad --------------------------------------------------------------- export -record Logging (ann, t : Type) where - constructor MkLogging - out : Maybe t - msgs : LazyList (Message ann) +data Logging : (ann, t : Type) -> Type where + Cont : (msg : Message ann) -> (l : Lazy (Logging ann t)) -> Logging ann t + Abort : Logging ann t + End : (v : t) -> Logging ann t + +%name Logging l, l' export Functor (Logging ann) where - map f = {out $= map f} + map f (Cont msg l) = Cont msg (map f l) + map f Abort = Abort + map f (End v) = End (f v) export Applicative (Logging ann) where - pure v = MkLogging {out = pure v, msgs = []} - f <*> v = MkLogging {out = f.out <*> v.out, msgs = f.msgs ++ v.msgs} + pure = End + (Cont msg f) <*> v = Cont msg (f <*> v) + Abort <*> v = Abort + (End f) <*> (Cont msg v) = Cont msg (End f <*> v) + (End f) <*> Abort = Abort + (End f) <*> (End v) = End (f v) export Monad (Logging ann) where - (MkLogging Nothing msgs) >>= f = MkLogging Nothing msgs - (MkLogging (Just v) msgs) >>= f = {msgs $= (msgs ++)} (f v) + join (Cont msg l) = Cont msg (join l) + join Abort = Abort + join (End v) = v --- -- Eliminators ----------------------------------------------------------------- +-- Eliminators ----------------------------------------------------------------- export discard : Logging ann a -> Maybe a -discard = out +discard (Cont msg l) = discard l +discard Abort = Nothing +discard (End v) = Just v export logToTerminal : Level -> Logging AnsiStyle a -> IO a -logToTerminal lvl log = do - Lazy.for_ (filter (\msg => msg.lvl <= lvl) log.msgs) (putDoc . pretty) - case log.out of - Just v => pure v - Nothing => exitFailure +logToTerminal lvl (Cont msg l) = do + () <- if msg.lvl <= lvl then putDoc (pretty msg) else pure () + logToTerminal lvl l +logToTerminal lvl Abort = exitFailure +logToTerminal lvl (End v) = pure v export abort : Logging ann a -abort = MkLogging Nothing [] +abort = Abort + +mapMsg : (Message ann -> Message ann') -> Logging ann a -> Logging ann' a +mapMsg f (Cont msg l) = Cont (f msg) (mapMsg f l) +mapMsg f Abort = Abort +mapMsg f (End v) = End v export inScope : (tag : String) -> Logging ann a -> Logging ann a -inScope tag = {msgs $= map {tags $= (tag ::)}} +inScope tag = mapMsg {tags $= (tag ::)} + +export +inBounds : Bounds -> Logging ann a -> Logging ann a +inBounds bounds = mapMsg {bounds $= maybe (Just bounds) Just} public export interface Loggable (0 ann, ty : Type) where @@ -122,27 +156,11 @@ error = log Error export fatal : Loggable ann ty => ty -> Logging ann a fatal msg = do error msg; abort - + export Loggable ann (Doc ann) where - log lvl msg = MkLogging (pure ()) [MkMessage lvl msg []] + log lvl msg = Cont (MkMessage lvl msg Nothing []) $ End () export Pretty x => Loggable ann x where log lvl msg = log lvl $ pretty {ann = ann} msg - -export -Loggable ann x => Loggable ann (WithBounds x) where - log lvl msg = - let f : Logging ann () -> Logging ann () - f = case msg.isIrrelevant of - True => id - False => inScope $ - show (1 + msg.bounds.startLine) ++ - ":" ++ - show msg.bounds.startCol ++ - "--" ++ - show (1 + msg.bounds.endLine) ++ - ":" ++ - show msg.bounds.endCol - in f (log lvl msg.val) diff --git a/src/Obs/Main.idr b/src/Obs/Main.idr index fc7140a..4d7c856 100644 --- a/src/Obs/Main.idr +++ b/src/Obs/Main.idr @@ -54,7 +54,7 @@ main' : (input: String) -> Logging AnsiStyle (Exists NormalForm.Context) main' input = do defs <- parse input blk <- abstractBlock defs - ctx <- checkBlock blk + (_ ** (ctx, _)) <- checkBlock blk pure (Evidence _ ctx) partial diff --git a/src/Obs/NormalForm.idr b/src/Obs/NormalForm.idr index cf5bb61..a756728 100644 --- a/src/Obs/NormalForm.idr +++ b/src/Obs/NormalForm.idr @@ -1,6 +1,7 @@ module Obs.NormalForm -import Data.Fin +import Data.List.Elem +import Data.So import Obs.Sort import Obs.Substitution @@ -12,328 +13,245 @@ import Text.PrettyPrint.Prettyprinter -- Definition ------------------------------------------------------------------ -data Constructor : Nat -> Type -data Neutral : Nat -> Type -data NormalForm : Nat -> Type +data NormalForm : Sorted.Family Bool public export -data Constructor : Nat -> Type where - Sort : Sort -> Constructor n - Pi : Sort -> Sort -> String -> NormalForm n -> NormalForm (S n) -> Constructor n - Lambda : String -> NormalForm (S n) -> Constructor n - Sigma : Sort -> Sort -> String -> NormalForm n -> NormalForm (S n) -> Constructor n - Pair : NormalForm n -> NormalForm n -> Constructor n - Sum : Sort -> Sort -> NormalForm n -> NormalForm n -> Constructor n - Left : NormalForm n -> Constructor n - Right : NormalForm n -> Constructor n - Container : Sort -> NormalForm n -> Sort -> Sort -> Constructor n - MkContainer : NormalForm n -> NormalForm n -> NormalForm n -> Constructor n - Top : Constructor n - Bottom : Constructor n +data Constructor : Unsorted.Family Bool where + Sort : (s : Sort) -> Constructor ctx + Pi : (s, s' : Sort) + -> (var : String) + -> (a : NormalForm True ctx) + -> (b : NormalForm True (isSet s :: ctx)) + -> Constructor ctx + Lambda : (s : Sort) + -> (var : String) + -> NormalForm True (isSet s :: ctx) + -> Constructor ctx + Sigma : (s, s' : Sort) + -> (var : String) + -> (a : NormalForm True ctx) + -> (b : NormalForm True (isSet s :: ctx)) + -> Constructor ctx + Pair : (s, s' : Sort) + -> (prf : So (isSet (max s s'))) + -> NormalForm (isSet s) ctx + -> NormalForm (isSet s') ctx + -> Constructor ctx + Bool : Constructor ctx + True : Constructor ctx + False : Constructor ctx + Top : Constructor ctx + Bottom : Constructor ctx public export -data Neutral : Nat -> Type where - Var : String -> Fin n -> Neutral n - App : Neutral n -> NormalForm n -> Neutral n - Fst : Neutral n -> Neutral n - Snd : Neutral n -> Neutral n - Case : Neutral n -> NormalForm n -> NormalForm n -> Neutral n - Tag : Neutral n -> Neutral n - Position : Neutral n -> Neutral n - Next : Neutral n -> Neutral n - Absurd : Neutral n - Equal : Neutral n -> NormalForm n -> NormalForm n -> Neutral n - EqualL : Nat -> Neutral n -> NormalForm n -> Neutral n - EqualR : Nat -> Constructor n -> Neutral n -> Neutral n - EqualU : Nat -> Constructor n -> Constructor n -> Neutral n - CastL : Neutral n -> NormalForm n -> NormalForm n -> Neutral n - CastR : Constructor n -> Neutral n -> NormalForm n -> Neutral n - CastU : Constructor n -> Constructor n -> NormalForm n -> Neutral n +data Neutral : Unsorted.Family Bool where + Var : (var : String) + -> (sort : Sort) + -> (prf : So (isSet sort)) + -> (i : Elem True ctx) + -> Neutral ctx + App : (b : Bool) -> Neutral ctx -> NormalForm b ctx -> Neutral ctx + Fst : (b : Bool) -> Neutral ctx -> Neutral ctx + Snd : (b : Bool) -> Neutral ctx -> Neutral ctx + If : Neutral ctx -> (f, g : NormalForm True ctx) -> Neutral ctx + Absurd : Neutral ctx + Equal : Neutral ctx -> NormalForm True ctx -> NormalForm True ctx -> Neutral ctx + EqualL : (a : Neutral ctx) -> (b : NormalForm True ctx) -> Neutral ctx + EqualR : (a : Constructor ctx) -> (b : Neutral ctx) -> Neutral ctx + EqualStuck : (a, b : Constructor ctx) -> Neutral ctx + CastL : (a : Neutral ctx) -> + (b : NormalForm True ctx) -> + NormalForm True ctx -> + Neutral ctx + CastR : (a : Constructor ctx) -> (b : Neutral ctx) -> NormalForm True ctx -> Neutral ctx + CastStuck : (a, b : Constructor ctx) -> NormalForm True ctx -> Neutral ctx public export -data NormalForm : Nat -> Type where - Ntrl : Neutral n -> NormalForm n - Cnstr : Constructor n -> NormalForm n - Irrel : NormalForm n +data NormalForm : Sorted.Family Bool where + Ntrl : Neutral ~|> NormalForm True + Cnstr : Constructor ~|> NormalForm True + Irrel : NormalForm False ctx + +%name Constructor t, u, v +%name Neutral t, u, v +%name NormalForm t, u, v public export -record Definition (n : Nat) where +record Definition (ctx : List Bool) where constructor MkDefinition - name : WithBounds String - sort : Sort - ty : NormalForm n - tm : NormalForm n + name : WithBounds String + sort : Sort + ty : NormalForm True ctx + tm : NormalForm (isSet sort) ctx public export -data Context : Nat -> Type where - Nil : Context 0 - (:<) : Context n -> Definition n -> Context (S n) - --- Interfaces ------------------------------------------------------------------ - --- Naive equality tests -eqCnstr : Constructor n -> Constructor n -> Bool -eqNtrl : Neutral n -> Neutral n -> Bool -eqWhnf : NormalForm n -> NormalForm n -> Bool - -eqCnstr (Sort s) (Sort s') = s == s' -eqCnstr (Pi s s' _ a b) (Pi l l' _ a' b') = s == l && s' == l' && eqWhnf a a' && eqWhnf b b' -eqCnstr (Lambda _ t) (Lambda _ u) = eqWhnf t u -eqCnstr (Sigma s s' _ a b) (Sigma l l' _ a' b') = s == l && s' == l' && eqWhnf a a' && eqWhnf b b' -eqCnstr (Pair t u) (Pair t' u') = eqWhnf t t' && eqWhnf u u' -eqCnstr (Sum s s' a b) (Sum l l' a' b') = s == l && s' == l' && eqWhnf a a' && eqWhnf b b' -eqCnstr (Left t) (Left t') = eqWhnf t t' -eqCnstr (Right t) (Right t') = eqWhnf t t' -eqCnstr (Container s a s' s'') (Container l a' l' l'') = s == l && eqWhnf a a' && s' == l' && s'' == l'' -eqCnstr (MkContainer t p f) (MkContainer t' p' f') = eqWhnf t t' && eqWhnf p p' && eqWhnf f f' -eqCnstr Top Top = True -eqCnstr Bottom Bottom = True -eqCnstr _ _ = False - -eqNtrl (Var _ i) (Var _ j) = i == j -eqNtrl (App t u) (App t' u') = eqNtrl t t' && eqWhnf u u' -eqNtrl (Fst t) (Fst t') = eqNtrl t t' -eqNtrl (Snd t) (Snd t') = eqNtrl t t' -eqNtrl (Case t f g) (Case t' f' g') = eqNtrl t t' && eqWhnf f f' && eqWhnf g g' -eqNtrl (Tag t) (Tag t') = eqNtrl t t' -eqNtrl (Position t) (Position t') = eqNtrl t t' -eqNtrl (Next t) (Next t') = eqNtrl t t' -eqNtrl Absurd Absurd = True -eqNtrl (Equal a t u) (Equal a' t' u') = eqNtrl a a' && eqWhnf t t' && eqWhnf u u' -eqNtrl (EqualL i t u) (EqualL j t' u') = i == j && eqNtrl t t' && eqWhnf u u' -eqNtrl (EqualR i t u) (EqualR j t' u') = i == j && eqCnstr t t' && eqNtrl u u' -eqNtrl (EqualU i t u) (EqualU j t' u') = i == j && eqCnstr t t' && eqCnstr u u' -eqNtrl (CastL a b t) (CastL a' b' t') = eqNtrl a a' && eqWhnf b b' && eqWhnf t t' -eqNtrl (CastR a b t) (CastR a' b' t') = eqCnstr a a' && eqNtrl b b' && eqWhnf t t' -eqNtrl (CastU a b t) (CastU a' b' t') = eqCnstr a a' && eqCnstr b b' && eqWhnf t t' -eqNtrl _ _ = False - -eqWhnf (Ntrl t) (Ntrl u) = eqNtrl t u -eqWhnf (Cnstr t) (Cnstr u) = eqCnstr t u -eqWhnf Irrel Irrel = True -eqWhnf _ _ = False - -export -Eq (Constructor n) where - t == u = eqCnstr t u +data Context : List Bool -> Type where + Nil : Context [] + (:<) : Context ctx -> (def : Definition ctx) -> Context (isSet def.sort :: ctx) -export -Eq (Neutral n) where - t == u = eqNtrl t u +%name Context ctx, ctx', ctx'' -export -Eq (NormalForm n) where - t == u = eqWhnf t u +-- Convenience Casts ----------------------------------------------------------- -export -Cast Sort (Constructor n) where - cast = Sort +public export +Cast Sort (Constructor ctx) where + cast s = Sort s -export -Cast Sort (NormalForm n) where - cast = Cnstr . cast +public export +Cast Sort (NormalForm True ctx) where + cast s = Cnstr $ cast s -- Pretty Print ---------------------------------------------------------------- -prettyPrecCnstr : Prec -> Constructor n -> Doc ann -prettyPrecNtrl : Prec -> Neutral n -> Doc ann -prettyPrecWhnf : Prec -> NormalForm n -> Doc ann +prettyPrec : Prec -> NormalForm b ctx -> Doc ann +prettyPrecCnstr : Prec -> Constructor ctx -> Doc ann prettyPrecCnstr d (Sort s) = prettyPrec d s -prettyPrecCnstr d (Pi _ _ var a b) = +prettyPrecCnstr d (Pi s s' var a b) = + let lhs = case var of + "" => align (prettyPrec App a) + _ => parens (pretty var <++> colon <+> softline <+> align (prettyPrec Open a)) + in parenthesise (d > Open) $ group $ - parens (pretty var <++> colon <+> softline <+> prettyPrecWhnf Open a) <++> - pretty "->" <+> softline <+> - prettyPrecWhnf Open b -prettyPrecCnstr d (Lambda var t) = + lhs <++> pretty "->" <+> line <+> align (prettyPrec Open b) +prettyPrecCnstr d (Lambda _ var t) = parenthesise (d > Open) $ group $ backslash <+> pretty var <++> - pretty "=>" <+> softline <+> - prettyPrecWhnf Open t -prettyPrecCnstr d (Sigma _ _ var a b) = + pretty "=>" <+> line <+> + align (prettyPrec Open t) +prettyPrecCnstr d (Sigma s s' var a b) = + let lhs = case var of + "" => align (prettyPrec App a) + _ => parens (pretty var <++> colon <+> softline <+> align (prettyPrec Open a)) + in parenthesise (d > Open) $ group $ - parens (pretty var <++> colon <+> softline <+> prettyPrecWhnf Open a) <++> - pretty "**" <+> softline <+> - prettyPrecWhnf Open b -prettyPrecCnstr d (Pair t u) = + lhs <++> pretty "**" <+> line <+> align (prettyPrec Open b) +prettyPrecCnstr d (Pair s s' prf t u) = angles $ group $ - neutral <++> prettyPrecWhnf Open t <+> comma <+> softline <+> prettyPrecWhnf Open u <++> neutral -prettyPrecCnstr d (Sum _ _ a b) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "Either", prettyPrecWhnf App a, prettyPrecWhnf App b] -prettyPrecCnstr d (Left t) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "Left", prettyPrecWhnf App t] -prettyPrecCnstr d (Right t) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "Right", prettyPrecWhnf App t] -prettyPrecCnstr d (Container s a s' s'') = - parenthesise (d >= App) $ - group $ - fillSep [pretty "Container", prettyPrecWhnf App a, prettyPrec App s', prettyPrec App s''] -prettyPrecCnstr d (MkContainer t p f) = - parenthesise (d >= User 0) $ - group $ - fillSep - [ prettyPrecWhnf (User 0) t <++> pretty "<|" - , prettyPrecWhnf (User 0) p <++> pretty "/" - , prettyPrecWhnf (User 0) f - ] + neutral <++> prettyPrec Open t <+> comma <+> line <+> prettyPrec Open u <++> neutral +prettyPrecCnstr d Bool = pretty "Bool" +prettyPrecCnstr d True = pretty "True" +prettyPrecCnstr d False = pretty "False" prettyPrecCnstr d Top = pretty "()" prettyPrecCnstr d Bottom = pretty "Void" -prettyPrecNtrl d (Var var i) = pretty "\{show var}@\{show i}" -prettyPrecNtrl d (App t u) = - parenthesise (d >= App) $ - group $ - fillSep [prettyPrecNtrl Open t, prettyPrecWhnf App u] -prettyPrecNtrl d (Fst t) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "fst", prettyPrecNtrl App t] -prettyPrecNtrl d (Snd t) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "snd", prettyPrecNtrl App t] -prettyPrecNtrl d (Case t f g) = +prettyPrecNtrl : Prec -> Neutral ctx -> Doc ann +prettyPrecNtrl d (Var var sort prf i) = pretty "\{var}@\{show $ elemToNat i}" +prettyPrecNtrl d (App _ t u) = parenthesise (d >= App) $ group $ - fillSep [pretty "case", prettyPrecNtrl App t, prettyPrecWhnf App f, prettyPrecWhnf App g] -prettyPrecNtrl d (Tag t) = + vsep [prettyPrecNtrl Open t, prettyPrec App u] +prettyPrecNtrl d (Fst _ t) = parenthesise (d >= App) $ group $ - fillSep [pretty "tag", prettyPrecNtrl App t] -prettyPrecNtrl d (Position t) = + vsep [pretty "fst", prettyPrecNtrl App t] +prettyPrecNtrl d (Snd _ t) = parenthesise (d >= App) $ group $ - fillSep [pretty "position", prettyPrecNtrl App t] -prettyPrecNtrl d (Next t) = + vsep [pretty "snd", prettyPrecNtrl App t] +prettyPrecNtrl d (If t f g) = parenthesise (d >= App) $ group $ - fillSep [pretty "next", prettyPrecNtrl App t] + vsep [pretty "if", prettyPrecNtrl App t, prettyPrec App f, prettyPrec App g] prettyPrecNtrl d Absurd = pretty "absurd" -prettyPrecNtrl d (Equal _ t u) = +prettyPrecNtrl d (Equal a t u) = parenthesise (d >= Equal) $ group $ - prettyPrecWhnf Equal t <++> pretty "~" <+> softline <+> prettyPrecWhnf Equal u -prettyPrecNtrl d (EqualL _ t u) = + prettyPrec Equal t <++> pretty "~" <+> line <+> prettyPrec Equal u +prettyPrecNtrl d (EqualL a b) = parenthesise (d >= Equal) $ group $ - prettyPrecNtrl Equal t <++> pretty "~" <+> softline <+> prettyPrecWhnf Equal u -prettyPrecNtrl d (EqualR _ t u) = + prettyPrecNtrl Equal a <++> pretty "~" <+> line <+> prettyPrec Equal b +prettyPrecNtrl d (EqualR a b) = parenthesise (d >= Equal) $ group $ - prettyPrecCnstr Equal t <++> pretty "~" <+> softline <+> prettyPrecNtrl Equal u -prettyPrecNtrl d (EqualU _ t u) = + prettyPrecCnstr Equal a <++> pretty "~" <+> line <+> prettyPrecNtrl Equal b +prettyPrecNtrl d (EqualStuck a b) = parenthesise (d >= Equal) $ group $ - prettyPrecCnstr Equal t <++> pretty "~" <+> softline <+> prettyPrecCnstr Equal u + prettyPrecCnstr Equal a <++> pretty "~" <+> line <+> prettyPrecCnstr Equal b prettyPrecNtrl d (CastL a b t) = parenthesise (d >= App) $ group $ - fillSep [pretty "cast", prettyPrecNtrl App a, prettyPrecWhnf App b, prettyPrecWhnf App t] + vsep [pretty "cast", prettyPrecNtrl App a, prettyPrec App b, prettyPrec App t] prettyPrecNtrl d (CastR a b t) = parenthesise (d >= App) $ group $ - fillSep [pretty "cast", prettyPrecCnstr App a, prettyPrecNtrl App b, prettyPrecWhnf App t] -prettyPrecNtrl d (CastU a b t) = + vsep [pretty "cast", prettyPrecCnstr App a, prettyPrecNtrl App b, prettyPrec App t] +prettyPrecNtrl d (CastStuck a b t) = parenthesise (d >= App) $ group $ - fillSep [pretty "cast", prettyPrecCnstr App a, prettyPrecCnstr App b, prettyPrecWhnf App t] + vsep [pretty "cast", prettyPrecCnstr App a, prettyPrecCnstr App b, prettyPrec App t] -prettyPrecWhnf d (Ntrl t) = prettyPrecNtrl d t -prettyPrecWhnf d (Cnstr t) = prettyPrecCnstr d t -prettyPrecWhnf d Irrel = pretty "_" +prettyPrec d (Ntrl t) = prettyPrecNtrl d t +prettyPrec d (Cnstr t) = prettyPrecCnstr d t +prettyPrec d Irrel = pretty "_" export -Pretty (Constructor n) where +Pretty (Constructor ctx) where prettyPrec = prettyPrecCnstr export -Pretty (Neutral n) where +Pretty (Neutral ctx) where prettyPrec = prettyPrecNtrl export -Pretty (NormalForm n) where - prettyPrec = prettyPrecWhnf +Pretty (NormalForm b ctx) where + prettyPrec = NormalForm.prettyPrec -export -Pretty (Definition n) where - pretty def = group $ - pretty def.name.val <++> colon <+> softline <+> pretty def.ty <+> softline <+> colon <++> pretty def.sort <+> hardline <+> - pretty def.name.val <++> equals <+> softline <+> pretty def.tm - -export -Pretty (Context n) where - pretty [] = neutral - pretty ([] :< def) = pretty def - pretty (ctx :< def) = pretty ctx <+> hardline <+> hardline <+> pretty def - --- Operations ------------------------------------------------------------------ +-- Renaming -------------------------------------------------------------------- --- Renaming - -renameCnstr : Constructor n -> (Fin n -> Fin m) -> Constructor m -renameNtrl : Neutral n -> (Fin n -> Fin m) -> Neutral m -renameWhnf : NormalForm n -> (Fin n -> Fin m) -> NormalForm m +rename : NormalForm ~|> Hom Elem NormalForm +renameCnstr : Constructor ~|> Hom Elem Constructor renameCnstr (Sort s) f = Sort s -renameCnstr (Pi s s' var a b) f = Pi s s' var (renameWhnf a f) (renameWhnf b $ lift 1 f) -renameCnstr (Lambda var t) f = Lambda var (renameWhnf t $ lift 1 f) -renameCnstr (Sigma s s' var a b) f = Sigma s s' var (renameWhnf a f) (renameWhnf b $ lift 1 f) -renameCnstr (Pair t u) f = Pair (renameWhnf t f) (renameWhnf u f) -renameCnstr (Sum s s' a b) f = Sum s s' (renameWhnf a f) (renameWhnf b f) -renameCnstr (Left t) f = Left (renameWhnf t f) -renameCnstr (Right t) f = Right (renameWhnf t f) -renameCnstr (Container s a s' s'') f = Container s (renameWhnf a f) s' s'' -renameCnstr (MkContainer t p u) f = MkContainer (renameWhnf t f) (renameWhnf p f) (renameWhnf u f) +renameCnstr (Pi s s' var a b) f = Pi s s' var (rename a f) (rename b (lift [(_ ** ())] f)) +renameCnstr (Lambda s var t) f = Lambda s var (rename t (lift [(_ ** ())] f)) +renameCnstr (Sigma s s' var a b) f = + Sigma s s' var (rename a f) (rename b (lift [(_ ** ())] f)) +renameCnstr (Pair s s' prf t u) f = Pair s s' prf (rename t f) (rename u f) +renameCnstr Bool f = Bool +renameCnstr True f = True +renameCnstr False f = False renameCnstr Top f = Top renameCnstr Bottom f = Bottom -renameNtrl (Var var i) f = Var var (f i) -renameNtrl (App t u) f = App (renameNtrl t f) (renameWhnf u f) -renameNtrl (Fst t) f = Fst (renameNtrl t f) -renameNtrl (Snd t) f = Snd (renameNtrl t f) -renameNtrl (Case t u t') f = Case (renameNtrl t f) (renameWhnf u f) (renameWhnf t' f) -renameNtrl (Tag t) f = Tag (renameNtrl t f) -renameNtrl (Position t) f = Position (renameNtrl t f) -renameNtrl (Next t) f = Next (renameNtrl t f) +renameNtrl : Neutral ~|> Hom Elem Neutral +renameNtrl (Var var sort prf i) f = Var var sort prf (f i) +renameNtrl (App b t u) f = App b (renameNtrl t f) (rename u f) +renameNtrl (Fst b t) f = Fst b (renameNtrl t f) +renameNtrl (Snd b t) f = Snd b (renameNtrl t f) +renameNtrl (If t u v) f = If (renameNtrl t f) (rename u f) (rename v f) renameNtrl Absurd f = Absurd -renameNtrl (Equal a t u) f = Equal (renameNtrl a f) (renameWhnf t f) (renameWhnf u f) -renameNtrl (EqualL i t u) f = EqualL i (renameNtrl t f) (renameWhnf u f) -renameNtrl (EqualR i t u) f = EqualR i (renameCnstr t f) (renameNtrl u f) -renameNtrl (EqualU i t u) f = EqualU i (renameCnstr t f) (renameCnstr u f) -renameNtrl (CastL a b t) f = CastL (renameNtrl a f) (renameWhnf b f) (renameWhnf t f) -renameNtrl (CastR a b t) f = CastR (renameCnstr a f) (renameNtrl b f) (renameWhnf t f) -renameNtrl (CastU a b t) f = CastU (renameCnstr a f) (renameCnstr b f) (renameWhnf t f) - -renameWhnf (Ntrl t) f = Ntrl $ renameNtrl t f -renameWhnf (Cnstr t) f = Cnstr $ renameCnstr t f -renameWhnf Irrel f = Irrel +renameNtrl (Equal a t u) f = Equal (renameNtrl a f) (rename t f) (rename u f) +renameNtrl (EqualL a b) f = EqualL (renameNtrl a f) (rename b f) +renameNtrl (EqualR a b) f = EqualR (renameCnstr a f) (renameNtrl b f) +renameNtrl (EqualStuck a b) f = EqualStuck (renameCnstr a f) (renameCnstr b f) +renameNtrl (CastL a b t) f = CastL (renameNtrl a f) (rename b f) (rename t f) +renameNtrl (CastR a b t) f = CastR (renameCnstr a f) (renameNtrl b f) (rename t f) +renameNtrl (CastStuck a b t) f = CastStuck (renameCnstr a f) (renameCnstr b f) (rename t f) + +rename (Ntrl t) f = Ntrl $ renameNtrl t f +rename (Cnstr t) f = Cnstr $ renameCnstr t f +rename Irrel f = Irrel export -Rename Constructor where +Unsorted.Rename Bool Constructor where rename = renameCnstr export -Rename Neutral where +Unsorted.Rename Bool Neutral where rename = renameNtrl - -export -Rename NormalForm where - rename = renameWhnf - + export -PointedRename Neutral where - point = Var "" +Sorted.Rename Bool NormalForm where + rename = NormalForm.rename export -PointedRename NormalForm where - point = Ntrl . point +PointedRename Bool (\b => (String, (s : Sort ** isSet s = b))) NormalForm where + point {s = False} _ _ = Irrel + point {s = True} (var, (s ** prf)) i = Ntrl (Var var s (eqToSo prf) i) diff --git a/src/Obs/NormalForm/Normalise.idr b/src/Obs/NormalForm/Normalise.idr index b50b520..82e84b9 100644 --- a/src/Obs/NormalForm/Normalise.idr +++ b/src/Obs/NormalForm/Normalise.idr @@ -1,400 +1,309 @@ module Obs.NormalForm.Normalise -import Data.Vect +import Data.Bool +import Data.So + +import Decidable.Equality import Obs.Logging import Obs.NormalForm import Obs.Sort import Obs.Substitution --- Utilities ------------------------------------------------------------------- +import Text.PrettyPrint.Prettyprinter + +%default total + +-- Aliases --------------------------------------------------------------------- + +public export 0 +LogConstructor : Type -> Unsorted.Family Bool +LogConstructor ann ctx = Logging ann (Constructor ctx) + +public export 0 +LogNormalForm : Type -> Sorted.Family Bool +LogNormalForm ann b ctx = Logging ann (NormalForm b ctx) + +0 +LogNormalForm' : Type -> Sorted.Family Bool +LogNormalForm' ann b ctx = Either (Logging ann (NormalForm b ctx)) (Elem b ctx) -mergeName : String -> String -> String -mergeName "" s' = s' -mergeName "_" s' = s' -mergeName s s' = s +-- Copied and specialised from Obs.Substitution +lift : (ctx : List (b ** (String, (s ** isSet s = b)))) + -> Map ctx' (LogNormalForm' ann) ctx'' + -> Map (map DPair.fst ctx ++ ctx') (LogNormalForm' ann) (map DPair.fst ctx ++ ctx'') +lift [] f = f +lift ((s ** y) :: ctx) f = add (LogNormalForm' ann) + (Left $ pure $ point y Here) + (\i => bimap (\t => pure (rename !t There)) There (lift ctx f i)) -wkn : Vect k String -> (Fin n -> Logging ann (NormalForm m)) -> Fin (k + n) -> Logging ann (NormalForm (k + m)) -wkn [] f = f -wkn (var :: vars) f = - add - (Logging ann . NormalForm) - (pure $ Ntrl $ Var var FZ) - (\i => pure $ rename !(wkn vars f i) FS) +-- Normalisation --------------------------------------------------------------- + +subst' : NormalForm ~|> Hom (LogNormalForm' ann) (LogNormalForm ann) + +export +doApp : {b' : _} -> NormalForm b ctx -> NormalForm b' ctx -> LogNormalForm ann b ctx +doApp (Ntrl t) u = pure (Ntrl $ App _ t u) +doApp (Cnstr (Lambda s var t)) u = inScope "doApp" $ do + trace $ pretty {ann} "substituting" <++> pretty u <+> softline <+> pretty "for \{var} in" <++> pretty t + let Yes Refl = decEq b' (isSet s) + | No _ => fatal "internal sort mismatch" + subst' t (add (LogNormalForm' ann) (Left $ pure u) Right) +doApp (Cnstr t) u = inScope "wrong constructor for apply" $ fatal t +doApp Irrel u = pure Irrel export -expandContainerTy : Sort -> NormalForm n -> Sort -> Sort -> Constructor n -expandContainerTy s a s' s'' = - let tagTy : Constructor n - tagTy = Pi s (suc s') "i" a (cast s') - in - let posTy : Constructor (S n) - posTy = - Pi s (s' ~> suc s'') "i" - (weaken 1 a) - (Cnstr $ Pi s' (suc s'') "t" - (Ntrl $ App (Var "tag" 1) (Ntrl $ Var "i" 0)) - (cast s'')) - in - let nextTy : Constructor (2 + n) - nextTy = - Pi s (s' ~> suc s'' ~> s) "i" - (weaken 2 a) - (Cnstr $ Pi s' (suc s'' ~> s) "t" - (Ntrl $ App (Var "tag" 2) (Ntrl $ Var "i" 0)) - (Cnstr $ Pi (suc s'') s "p" - (Ntrl $ App (App (Var "pos" 2) (Ntrl $ Var "i" 1)) (Ntrl $ Var "p" 0)) - (weaken 5 a))) - in - Sigma (s ~> suc s') (lub (s ~> s' ~> suc s'') (s ~> s' ~> s'' ~> s)) "tag" - (Cnstr tagTy) $ - Cnstr $ Sigma (s ~> s' ~> suc s'') (s ~> s' ~> s'' ~> s) "pos" - (Cnstr posTy) - (Cnstr nextTy) +doFst : (b, b' : _) -> NormalForm (b || b') ctx -> LogNormalForm ann b ctx +doFst False b' t = pure Irrel +doFst True b' (Ntrl t) = pure (Ntrl $ Fst b' t) +doFst True b' (Cnstr (Pair (Set _) s' prf t u)) = pure t +doFst True b' (Cnstr t) = inScope "wrong constructor for fst" $ fatal t --- Substitution ---------------------------------------------------------------- +export +doSnd : (b, b' : _) -> NormalForm (b || b') ctx -> LogNormalForm ann b' ctx +doSnd b False t = pure Irrel +doSnd b True t = + let t' : NormalForm True ctx + t' = rewrite sym $ orTrueTrue b in t + in case t' of + Ntrl t => pure (Ntrl $ Snd b t) + Cnstr (Pair _ (Set _) prf t u) => pure u + Cnstr t => inScope "wrong constructor for snd" $ fatal t -partial -substCnstr : Constructor n -> (Fin n -> Logging ann (NormalForm m)) -> Logging ann (Constructor m) -partial -substNtrl : Neutral n -> (Fin n -> Logging ann (NormalForm m)) -> Logging ann (NormalForm m) -partial export -subst : NormalForm n -> (Fin n -> Logging ann (NormalForm m)) -> Logging ann (NormalForm m) -partial export -subst1 : NormalForm n -> NormalForm (S n) -> Logging ann (NormalForm n) -partial export -doApp : NormalForm n -> NormalForm n -> Logging ann (NormalForm n) -partial export -doFst : NormalForm n -> Logging ann (NormalForm n) -partial export -doSnd : NormalForm n -> Logging ann (NormalForm n) -partial export -doCase : NormalForm n -> NormalForm n -> NormalForm n -> Logging ann (NormalForm n) -partial export -doTag : NormalForm n -> Logging ann (NormalForm n) -partial export -doPosition : NormalForm n -> Logging ann (NormalForm n) -partial export -doNext : NormalForm n -> Logging ann (NormalForm n) -partial export -doEqual : NormalForm n -> NormalForm n -> NormalForm n -> Logging ann (NormalForm n) -partial -doEqualL : Nat -> NormalForm n -> NormalForm n -> Logging ann (NormalForm n) -partial -doEqualR : Nat -> Constructor n -> NormalForm n -> Logging ann (NormalForm n) -partial -doEqualU : Nat -> Constructor n -> Constructor n -> Logging ann (NormalForm n) -partial export -doCastL : NormalForm n -> NormalForm n -> NormalForm n -> Logging ann (NormalForm n) -partial -doCastR : Constructor n -> NormalForm n -> NormalForm n -> Logging ann (NormalForm n) -partial -doCastU : Constructor n -> Constructor n -> NormalForm n -> Logging ann (NormalForm n) -partial export -expandContainer : NormalForm n -> Logging ann (Constructor n) -partial export -contractContainer : NormalForm n -> Logging ann (Constructor n) +export +doIf : {b : _} -> + NormalForm True ctx -> + NormalForm b ctx -> + NormalForm b ctx -> + LogNormalForm ann b ctx +doIf {b = False} t u v = pure Irrel +doIf {b = True} (Ntrl t) u v = pure (Ntrl $ If t u v) +doIf {b = True} (Cnstr True) u v = pure u +doIf {b = True} (Cnstr False) u v = pure v +doIf {b = True} (Cnstr t) u v = inScope "wrong constructor for case" $ fatal t -substCnstr (Sort s) f = pure $ Sort s +export +doAbsurd : (b : _) -> NormalForm b ctx +doAbsurd False = Irrel +doAbsurd True = Ntrl Absurd + +export +doCast : (b' : _) -> (a, b : NormalForm True ctx) -> NormalForm b' ctx -> LogNormalForm ann b' ctx + +doCastR : (a : Constructor ctx) -> + (b : NormalForm True ctx) -> + NormalForm True ctx -> + LogNormalForm ann True ctx +doCastR a (Ntrl b) t = pure (Ntrl $ CastR a b t) +doCastR (Sort _) (Cnstr (Sort _)) t = pure t +doCastR ty@(Pi s s'@(Set _) var a b) (Cnstr ty'@(Pi l l' _ a' b')) t = + let y : NormalForm (isSet s) (isSet s :: ctx) + y = point (var, (s ** Refl)) Here + in do + let Yes Refl = decEq (s, s') (l, l') + | No _ => pure (Ntrl $ CastStuck ty ty' t) + x <- assert_total (doCast (isSet s) (weaken [isSet s] a') (weaken [isSet s] a) y) + b <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure x) (Right . There))) + b' <- assert_total (subst' b' (add (LogNormalForm' ann) (Left $ pure y) (Right . There))) + t <- assert_total (doApp (Sorted.weaken [isSet s] t) x) + t <- assert_total (doCast True b b' t) + pure (Cnstr $ Lambda s var t) +doCastR ty@(Sigma s@(Set k) s' var a b) (Cnstr ty'@(Sigma l l' _ a' b')) t = do + let Yes Refl = decEq (s, s') (l, l') + | No _ => pure (Ntrl $ CastStuck ty ty' t) + t1 <- doFst True (isSet s') t + u1 <- assert_total (doCast True a a' t) + b <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure t1) Right)) + b' <- assert_total (subst' b' (add (LogNormalForm' ann) (Left $ pure u1) Right)) + t2 <- doSnd True (isSet s') t + u2 <- assert_total (doCast (isSet s') b b' t2) + pure (Cnstr $ Pair (Set k) s' Oh u1 u2) +doCastR ty@(Sigma Prop s'@(Set k) var a b) (Cnstr ty'@(Sigma Prop l' _ a' b')) t = do + let Yes Refl = decEq s' l' + | No _ => pure (Ntrl $ CastStuck ty ty' t) + b <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure Irrel) Right)) + b' <- assert_total (subst' b' (add (LogNormalForm' ann) (Left $ pure Irrel) Right)) + t2 <- doSnd False True t + u2 <- assert_total (doCast True b b' t2) + pure (Cnstr $ Pair Prop (Set k) Oh Irrel u2) +doCastR Bool (Cnstr Bool) t = pure t +doCastR a (Cnstr b) t = pure (Ntrl $ CastStuck a b t) + +doCast False a b t = pure Irrel +doCast True (Ntrl a) b t = pure (Ntrl $ CastL a b t) +doCast True (Cnstr a) b t = doCastR a b t + +export +doEqual : (b : _) -> + (a : NormalForm True ctx) -> + NormalForm b ctx -> + NormalForm b ctx -> + LogNormalForm ann True ctx + +-- Relies heavily on typing +doEqualR : (a : Constructor ctx) -> (b : NormalForm True ctx) -> LogNormalForm ann True ctx +doEqualR a (Ntrl b) = pure (Ntrl $ EqualR a b) +doEqualR (Sort _) (Cnstr (Sort s)) = pure (Cnstr Top) +doEqualR ty@(Pi s s' var a b) (Cnstr ty'@(Pi l l' _ a' b')) = + let u : NormalForm (isSet s) (isSet s :: ctx) + u = point (var, (s ** Refl)) Here + in do + let Yes Refl = decEq (s, s') (l, l') + | No _ => pure (Ntrl $ EqualStuck ty ty') + eq1 <- assert_total (doEqual True (cast s) a' a) + t <- doCast (isSet s) (weaken [isSet s] a') (weaken [isSet s] a) u + b <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure t) (Right . There))) + b' <- assert_total (subst' b' (add (LogNormalForm' ann) (Left $ pure u) (Right . There))) + eq2 <- assert_total (doEqual True (cast s') b b') + pure (Cnstr $ Sigma Prop Prop "_" eq1 (Cnstr $ Unsorted.weaken [False] $ Pi s Prop var a eq2)) +doEqualR ty@(Sigma s s' var a b) (Cnstr ty'@(Sigma l l' _ a' b')) = + let t : NormalForm (isSet s) (isSet s :: ctx) + t = point (var, (s ** Refl)) Here + in do + let Yes Refl = decEq (s, s') (l, l') + | No _ => pure (Ntrl $ EqualStuck ty ty') + eq1 <- assert_total (doEqual True (cast s) a a') + u <- doCast (isSet s) (weaken [isSet s] a) (weaken [isSet s] a') t + b <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure t) (Right . There))) + b' <- assert_total (subst' b' (add (LogNormalForm' ann) (Left $ pure u) (Right . There))) + eq2 <- assert_total (doEqual True (cast s') b b') + pure (Cnstr $ Sigma Prop Prop "_" eq1 (Cnstr $ Unsorted.weaken [False] $ Pi s Prop var a eq2)) +doEqualR Bool (Cnstr Bool) = pure (Cnstr Top) +doEqualR Top (Cnstr Top) = pure (Cnstr Top) +doEqualR Bottom (Cnstr Bottom) = pure (Cnstr Top) +doEqualR a (Cnstr b) = pure (Ntrl $ EqualStuck a b) + +export +doEqualSet : (a, b : NormalForm True ctx) -> LogNormalForm ann True ctx +doEqualSet (Ntrl a) b = pure (Ntrl $ EqualL a b) +doEqualSet (Cnstr a) b = doEqualR a b + +doEqual False a t u = pure (Cnstr Top) +doEqual True (Ntrl a) t u = pure (Ntrl $ Equal a t u) +doEqual True (Cnstr (Sort Prop)) t u = do + pure (Cnstr $ Sigma Prop Prop "" + (Cnstr $ Pi Prop Prop "" t (Sorted.weaken [False] u)) + (Cnstr $ Unsorted.weaken [False] $ Pi Prop Prop "" u (Sorted.weaken [False] t))) +doEqual True (Cnstr (Sort (Set _))) t u = doEqualSet t u +doEqual True (Cnstr (Pi s (Set k) var a b)) t u = + let x : NormalForm (isSet s) (isSet s :: ctx) + x = point (var, (s ** Refl)) Here + in do + t <- assert_total (doApp (weaken [isSet s] t) x) + u <- assert_total (doApp (weaken [isSet s] u) x) + eq <- doEqual True b t u + pure (Cnstr $ Pi s Prop var a eq) +doEqual True (Cnstr (Sigma s@(Set _) s' var a b)) t u = do + t1 <- doFst True (isSet s') t + u1 <- doFst True (isSet s') u + t2 <- doSnd True (isSet s') t + u2 <- doSnd True (isSet s') u + eq1 <- doEqual True a t1 u1 + bt1 <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure t1) Right)) + bu1 <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure u1) Right)) + t2' <- doCast (isSet s') bt1 bu1 t2 + eq2 <- doEqual (isSet s') (assert_smaller b bu1) t2' u2 + pure (Cnstr $ Sigma Prop Prop "_" eq1 (Sorted.weaken [False] eq2)) +doEqual True (Cnstr (Sigma Prop (Set k) var a b)) t u = do + t2 <- doSnd False True t + u2 <- doSnd False True u + bt1 <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure $ Irrel) Right)) + bu1 <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure $ Irrel) Right)) + t2' <- doCast True bt1 bu1 t2 + eq2 <- doEqual True (assert_smaller b bu1) t2' u2 + pure (Cnstr $ Sigma Prop Prop "_" (Cnstr Top) (Sorted.weaken [False] eq2)) +doEqual True (Cnstr Bool) t u = do + true <- doIf u (Cnstr Top) (Cnstr Bottom) + false <- doIf u (Cnstr Bottom) (Cnstr Top) + doIf t true false +doEqual True (Cnstr a) t u = inScope "wrong constructor for equal" $ fatal a + +substCnstr : Constructor ~|> Hom (LogNormalForm' ann) (LogConstructor ann) +substCnstr (Sort s) f = pure (Sort s) substCnstr (Pi s s' var a b) f = do - a <- subst a f - b <- subst b (wkn [var] f) + a <- subst' a f + b <- subst' b (lift [(_ ** (var, (s ** Refl)))] f) pure (Pi s s' var a b) -substCnstr (Lambda var t) f = do - t <- subst t (wkn [var] f) - pure (Lambda var t) +substCnstr (Lambda s var t) f = do + t <- subst' t (lift [(_ ** (var, (s ** Refl)))] f) + pure (Lambda s var t) substCnstr (Sigma s s' var a b) f = do - a <- subst a f - b <- subst b (wkn [var] f) + a <- subst' a f + b <- subst' b (lift [(_ ** (var, (s ** Refl)))] f) pure (Sigma s s' var a b) -substCnstr (Pair t u) f = do - t <- subst t f - u <- subst u f - pure (Pair t u) -substCnstr (Sum s s' a b) f = do - a <- subst a f - b <- subst b f - pure (Sum s s' a b) -substCnstr (Left t) f = do - t <- subst t f - pure (Left t) -substCnstr (Right t) f = do - t <- subst t f - pure (Right t) -substCnstr (Container s a s' s'') f = do - a <- subst a f - pure (Container s a s' s'') -substCnstr (MkContainer t p u) f = do - t <- subst t f - p <- subst p f - u <- subst u f - pure (MkContainer t p u) -substCnstr Top f = pure $ Top -substCnstr Bottom f = pure $ Bottom - -substNtrl (Var var i) f = do - Ntrl (Var var' j) <- f i - | t => pure t - pure (Ntrl (Var (mergeName var' var) j)) -substNtrl (App t u) f = do - t <- substNtrl t f - u <- subst u f - doApp t u -substNtrl (Fst t) f = do - t <- substNtrl t f - doFst t -substNtrl (Snd t) f = do +substCnstr (Pair s s' prf t u) f = do + t <- subst' t f + u <- subst' u f + pure (Pair s s' prf t u) +substCnstr Bool f = pure Bool +substCnstr True f = pure True +substCnstr False f = pure False +substCnstr Top f = pure Top +substCnstr Bottom f = pure Bottom + +substNtrl : Neutral ~|> Hom (LogNormalForm' ann) (LogNormalForm ann True) +substNtrl (Var var sort prf i) f = case f i of + Left t => t + Right j => pure (Ntrl $ Var var sort prf j) +substNtrl (App b t u) f = do t <- substNtrl t f - doSnd t -substNtrl (Case t u t') f = do + u <- subst' u f + assert_total (doApp t u) +substNtrl (Fst b t) f = do t <- substNtrl t f - u <- subst u f - t' <- subst t' f - doCase t u t' -substNtrl (Tag t) f = do + doFst True b t +substNtrl (Snd b t) f = do t <- substNtrl t f - doTag t -substNtrl (Position t) f = do + doSnd b True $ rewrite orTrueTrue b in t +substNtrl (If t u v) f = do t <- substNtrl t f - doPosition t -substNtrl (Next t) f = do - t <- substNtrl t f - doNext t -substNtrl Absurd f = pure $ Ntrl Absurd + u <- subst' u f + v <- subst' v f + doIf t u v +substNtrl Absurd f = pure (doAbsurd True) substNtrl (Equal a t u) f = do a <- substNtrl a f - t <- subst t f - u <- subst u f - doEqual a t u -substNtrl (EqualL i t u) f = do - t <- substNtrl t f - u <- subst u f - doEqualL i t u -substNtrl (EqualR i t u) f = do - t <- substCnstr t f - u <- substNtrl u f - doEqualR i t u -substNtrl (EqualU i t u) f = do - t <- substCnstr t f - u <- substCnstr u f - doEqualU i t u + t <- subst' t f + u <- subst' u f + doEqual _ a t u +substNtrl (EqualL a b) f = do + a <- substNtrl a f + b <- subst' b f + doEqualSet a b +substNtrl (EqualR a b) f = do + a <- substCnstr a f + b <- substNtrl b f + doEqualR a b +substNtrl (EqualStuck a b) f = do + a <- substCnstr a f + b <- substCnstr b f + pure (Ntrl $ EqualStuck a b) substNtrl (CastL a b t) f = do a <- substNtrl a f - b <- subst b f - t <- subst t f - doCastL a b t + b <- subst' b f + t <- subst' t f + doCast _ a b t substNtrl (CastR a b t) f = do a <- substCnstr a f b <- substNtrl b f - t <- subst t f + t <- subst' t f doCastR a b t -substNtrl (CastU a b t) f = do +substNtrl (CastStuck a b t) f = do a <- substCnstr a f b <- substCnstr b f - t <- subst t f - doCastU a b t - -subst (Ntrl t) f = substNtrl t f -subst (Cnstr t) f = map Cnstr $ substCnstr t f -subst Irrel f = pure Irrel - -subst1 t u = subst u (add (Logging ann . NormalForm) (pure t) (pure . point)) - -doApp (Ntrl t) u = pure $ Ntrl (App t u) -doApp Irrel u = pure $ Irrel -doApp (Cnstr (Lambda var t)) u = subst t (add (Logging ann . NormalForm) (pure u) (pure . point)) -doApp (Cnstr t) u = inScope "bug" $ inScope "wrong constructor in apply" $ fatal t - -doFst (Ntrl t) = pure $ Ntrl (Fst t) -doFst Irrel = pure $ Irrel -doFst (Cnstr (Pair t u)) = pure $ t -doFst (Cnstr t) = inScope "bug" $ inScope "wrong constructor in fst" $ fatal t - -doSnd (Ntrl t) = pure $ Ntrl (Snd t) -doSnd Irrel = pure $ Irrel -doSnd (Cnstr (Pair t u)) = pure $ u -doSnd (Cnstr t) = inScope "bug" $ inScope "wrong constructor in snd" $ fatal t - -doCase (Ntrl t) f g = pure $ Ntrl (Case t f g) -doCase Irrel f g = inScope "bug" $ inScope "wrong constructor in case" $ fatal "Irrel" -doCase (Cnstr (Left t)) f g = doApp f t -doCase (Cnstr (Right t)) f g = doApp g t -doCase (Cnstr t) f g = inScope "bug" $ inScope "wrong constructor in case" $ fatal t - -doTag (Ntrl t) = pure $ Ntrl (Tag t) -doTag Irrel = pure $ Irrel -doTag (Cnstr (MkContainer t p f)) = pure t -doTag (Cnstr t) = inScope "bug" $ inScope "wrong constructor in tag" $ fatal t - -doPosition (Ntrl t) = pure $ Ntrl (Position t) -doPosition Irrel = pure $ Irrel -doPosition (Cnstr (MkContainer t p f)) = pure p -doPosition (Cnstr t) = inScope "bug" $ inScope "wrong constructor in position" $ fatal t + t <- subst' t f + pure (Ntrl $ CastStuck a b t) -doNext (Ntrl t) = pure $ Ntrl (Next t) -doNext Irrel = pure $ Irrel -doNext (Cnstr (MkContainer t p f)) = pure f -doNext (Cnstr t) = inScope "bug" $ inScope "wrong constructor in next" $ fatal t - -doEqual (Ntrl a) t u = pure $ Ntrl (Equal a t u) -doEqual Irrel t u = inScope "bug" $ inScope "wrong type over equal" $ fatal "Irrel" -doEqual (Cnstr (Sort Prop)) t u = - pure $ - Cnstr (Sigma Prop Prop "_" - (Cnstr $ Pi Prop Prop "_" t (weaken 1 u)) - (weaken 1 $ Cnstr $ Pi Prop Prop "_" u (weaken 1 t))) -doEqual (Cnstr (Sort (Set k))) t u = doEqualL k t u -doEqual (Cnstr (Pi s s' var a b)) t u = do - eqLhs <- doApp (weaken 1 t) (Ntrl $ Var var FZ) - eqRhs <- doApp (weaken 1 u) (Ntrl $ Var var FZ) - eq <- doEqual b eqLhs eqRhs -- b in Set because Pi in Set. - pure $ Cnstr (Pi s Prop var a eq) -doEqual (Cnstr (Sigma s s' var a b)) t u = do - t1 <- doFst t - u1 <- doFst u - eq1 <- case s of - Prop => pure $ Cnstr Top - (Set i) => doEqual a t1 u1 - eq2 <- case s' of - Prop => pure $ Cnstr Top - (Set i) => do - bt <- subst1 t1 b - bu <- subst1 u1 b - t2 <- doSnd t - t2 <- doCastL bt bu t2 - u2 <- doSnd u - doEqual bu t2 u2 - pure $ Cnstr (Sigma Prop Prop "_" eq1 (weaken 1 eq2)) -doEqual (Cnstr (Sum s s' a b)) t u = do - let x = Ntrl $ Var "x" 1 - let y = Ntrl $ Var "y" 0 - ll <- doEqual (weaken 2 a) x y - lr <- pure $ Cnstr Bottom - rl <- pure $ Cnstr Bottom - rr <- doEqual (weaken 2 b) x y - fBody <- doCase (weaken 1 u) (Cnstr (Lambda "y" ll)) (Cnstr (Lambda "y" lr)) - gBody <- doCase (weaken 1 u) (Cnstr (Lambda "y" rl)) (Cnstr (Lambda "y" rr)) - doCase t (Cnstr (Lambda "x" fBody)) (Cnstr (Lambda "x" gBody)) -doEqual (Cnstr (Container s a s' s'')) t u = do - let containerTy = expandContainerTy s a s' s'' - t <- expandContainer t - u <- expandContainer u - doEqual (Cnstr containerTy) (Cnstr t) (Cnstr u) -doEqual (Cnstr Top) t u = pure $ Cnstr Top -doEqual (Cnstr Bottom) t u = pure $ Cnstr Top -doEqual (Cnstr a) t u = inScope "bug" $ inScope "wrong type under equal" $ fatal a - -doEqualL i (Ntrl t) u = pure $ Ntrl (EqualL i t u) -doEqualL i Irrel u = inScope "bug" $ inScope "wrong type under equalL" $ fatal "Irrel" -doEqualL i (Cnstr t) u = doEqualR i t u - -doEqualR i t (Ntrl u) = pure $ Ntrl (EqualR i t u) -doEqualR i t Irrel = inScope "bug" $ inScope "wrong type under equalR" $ fatal "Irrel" -doEqualR i t (Cnstr u) = doEqualU i t u - -doEqualU i (Sort s) (Sort s') = pure $ Cnstr Top -- have suc s = i = suc s', and suc injective -doEqualU i (Pi s s' _ a b) (Pi l l' var a' b') = case (s == s' && l == l') of - False => pure $ Cnstr Bottom - True => do - eqLhs <- doEqual (cast s) a' a - let x = Ntrl $ Var var FZ - b <- subst b (add (Logging ann . NormalForm) (doCastL (weaken 1 a') (weaken 1 a) x) (pure . Ntrl . Var "" . FS)) - eqRhs <- doEqual (cast s') b b' - pure $ Cnstr (Sigma Prop Prop "" eqLhs $ weaken 1 $ Cnstr (Pi s Prop var a' eqRhs)) -doEqualU i (Sigma s s' _ a b) (Sigma l l' var a' b') = case (s == s' && l == l') of - False => pure $ Cnstr Bottom - True => do - eqLhs <- doEqual (cast s) a' a - let x = Ntrl $ Var var FZ - b <- subst b (add (Logging ann . NormalForm) (doCastL (weaken 1 a') (weaken 1 a) x) (pure . Ntrl . Var "" . FS)) - eqRhs <- doEqual (cast s') b b' - pure $ Cnstr (Sigma Prop Prop "" eqLhs $ weaken 1 $ Cnstr (Pi s Prop var a' eqRhs)) -doEqualU i (Sum s s' a b) (Sum l l' a' b') = case (s == l && s' == l') of - False => pure $ Cnstr Bottom - True => do - eqLhs <- doEqual (cast s) a a' - eqRhs <- doEqual (cast s) b b' - pure $ Cnstr (Sigma Prop Prop "" eqLhs (weaken 1 eqRhs)) -doEqualU i (Container s a s' s'') (Container l a' l' l'') = case (s == l && s' == l' && s'' == l'') of - False => pure $ Cnstr Bottom - True => doEqual (cast s) a a' -doEqualU i t u = pure $ Ntrl (EqualU i t u) -- assumption: only logical values reach this far - -doCastL (Ntrl a) b t = pure $ Ntrl (CastL a b t) -doCastL Irrel b t = inScope "bug" $ inScope "wrong type for cast" $ fatal "Irrel" -doCastL (Cnstr a) b t = doCastR a b t - -doCastR a (Ntrl b) t = pure $ Ntrl (CastR a b t) -doCastR a Irrel t = inScope "bug" $ inScope "wrong type for cast" $ fatal "Irrel" -doCastR a (Cnstr b) t = doCastU a b t - -doCastU (Sort s) (Sort s') t = pure t -doCastU (Pi s s' _ a b) (Pi l l' var a' b') t = do - let x' = Ntrl $ Var var FZ - let x = doCastL (weaken 1 a') (weaken 1 a) x' - b <- subst b (add (Logging ann . NormalForm) x (pure . Ntrl . Var "" . FS)) - b' <- subst b' (add (Logging ann . NormalForm) (pure x') (pure . Ntrl . Var "" . FS)) - fx <- doApp (weaken 1 t) !x - cast <- doCastL b b' fx - pure $ Cnstr (Lambda var cast) -doCastU (Sigma s s' _ a b) (Sigma l l' var a' b') t = do - t1 <- doFst t - t2 <- doSnd t - t1' <- doCastL a a' t1 - b <- subst1 t1 b - b' <- subst1 t1' b' - t2' <- doCastL b b' t2 - pure $ Cnstr (Pair t1' t2') -doCastU (Sum s s' a b) (Sum l l' a' b') t = do - let x = Ntrl $ Var "x" 0 - castL <- doCastL (weaken 1 a) (weaken 1 a') x - castR <- doCastL (weaken 1 b) (weaken 1 b') x - doCase t (Cnstr (Lambda "x" (Cnstr (Left castL)))) (Cnstr (Lambda "x" (Cnstr (Right castR)))) -doCastU (Container s a s' s'') (Container l b l' l'') t = do - t <- expandContainer t - let a = expandContainerTy s a s' s'' - let b = expandContainerTy l b l' l'' - t <- doCastU a b (Cnstr t) - t <- contractContainer t - pure $ Cnstr t -doCastU Top Top t = pure Irrel -doCastU Bottom Bottom t = pure Irrel -doCastU a b t = pure $ Ntrl (CastU a b t) - -expandContainer t = do - tag <- doTag t - pos <- doPosition t - next <- doNext t - pure $ Pair tag (Cnstr $ Pair pos next) - -contractContainer t = do - tag <- doFst t - t <- doSnd t - pos <- doFst t - next <- doSnd t - pure $ MkContainer tag pos next - --- More utilities -------------------------------------------------------------- +subst' (Ntrl t) f = substNtrl t f +subst' (Cnstr t) f = pure $ Cnstr !(substCnstr t f) +subst' Irrel f = pure Irrel export -tagTy : Sort -> NormalForm n -> Sort -> Constructor n -tagTy s a s' = Pi s (suc s') "i" a (cast s') +subst : NormalForm ~|> Hom (LogNormalForm ann) (LogNormalForm ann) +subst t f = subst' t (Left . f) -export -positionTy : Sort -> NormalForm n -> Sort -> NormalForm n -> Sort -> Logging ann (Constructor n) -positionTy s a s' tag s'' = do - let i = Var "i" 0 - tagI <- doApp (weaken 1 tag) (Ntrl i) - pure $ Pi s (s' ~> suc s'') "i" a (Cnstr $ Pi s' (suc s'') "t" tagI (cast s'')) +-- Utilities ------------------------------------------------------------------- export -nextTy : Sort -> NormalForm n -> Sort -> NormalForm n -> Sort -> NormalForm n -> Logging ann (Constructor n) -nextTy s a s' tag s'' pos = do - let i = Var "i" 0 - tagI <- doApp (weaken 1 tag) (Ntrl i) - let t = Var "t" 0 - posI <- doApp (weaken 1 pos) (Ntrl i) - posIT <- doApp (weaken 1 posI) (Ntrl t) - pure $ Pi s (s' ~> s'' ~> s) "i" a $ - Cnstr $ Pi s' (s'' ~> s) "t" tagI $ - Cnstr $ Pi s'' s "p" posIT (weaken 3 a) +subst1 : {s' : _} -> NormalForm s ctx -> NormalForm s' (s :: ctx) -> LogNormalForm ann s' ctx +subst1 t u = subst' u (add (LogNormalForm' ann) (Left $ pure t) Right) diff --git a/src/Obs/Parser.idr b/src/Obs/Parser.idr index 7ce31c4..758b019 100644 --- a/src/Obs/Parser.idr +++ b/src/Obs/Parser.idr @@ -25,10 +25,10 @@ data ObsTokenKind | OTNat | OTFst | OTSnd - | OTEither - | OTLeft - | OTRight - | OTCase + | OTBool + | OTTrue + | OTFalse + | OTIf | OTContainer | OTTag | OTPosition @@ -70,10 +70,10 @@ Eq ObsTokenKind where OTNat == OTNat = True OTFst == OTFst = True OTSnd == OTSnd = True - OTEither == OTEither = True - OTLeft == OTLeft = True - OTRight == OTRight = True - OTCase == OTCase = True + OTBool == OTBool = True + OTTrue == OTTrue = True + OTFalse == OTFalse = True + OTIf == OTIf = True OTContainer == OTContainer = True OTTag == OTTag = True OTPosition == OTPosition = True @@ -117,10 +117,10 @@ TokenKind ObsTokenKind where tokValue OTNat s = stringToNatOrZ s tokValue OTFst s = () tokValue OTSnd s = () - tokValue OTEither s = () - tokValue OTLeft s = () - tokValue OTRight s = () - tokValue OTCase s = () + tokValue OTBool s = () + tokValue OTTrue s = () + tokValue OTFalse s = () + tokValue OTIf s = () tokValue OTContainer s = () tokValue OTTag s = () tokValue OTPosition s = () @@ -162,10 +162,10 @@ Show ObsToken where show (Tok OTNat s) = s show (Tok OTFst s) = "fst" show (Tok OTSnd s) = "snd" - show (Tok OTEither s) = "Either" - show (Tok OTLeft s) = "Left" - show (Tok OTRight s) = "Right" - show (Tok OTCase s) = "case" + show (Tok OTBool s) = "Bool" + show (Tok OTTrue s) = "True" + show (Tok OTFalse s) = "False" + show (Tok OTIf s) = "if" show (Tok OTContainer s) = "Container" show (Tok OTTag s) = "tag" show (Tok OTPosition s) = "position" @@ -204,10 +204,10 @@ keywords = , ("Prop", OTProp) , ("fst", OTFst) , ("snd", OTSnd) - , ("Either", OTEither) - , ("Left", OTLeft) - , ("Right", OTRight) - , ("case", OTCase) + , ("Bool", OTBool) + , ("True", OTTrue) + , ("False", OTFalse) + , ("if", OTIf) , ("Container", OTContainer) , ("tag", OTTag) , ("position", OTPosition) @@ -256,7 +256,10 @@ uncurry (S n) f (x :: xs) = uncurry n (f x) xs termForms : List (ObsTokenKind, Syntax) termForms = - [ (OTPoint, Point) + [ (OTBool, Bool) + , (OTTrue, True) + , (OTFalse, False) + , (OTPoint, Point) , (OTVoid, Bottom) , (OTUnit, Top) ] @@ -265,22 +268,18 @@ headForms : List (ObsTokenKind, (n ** (Vect (S n) (WithBounds Syntax) -> Syntax) headForms = [ (OTFst, (0 ** uncurry 1 Fst)) , (OTSnd, (0 ** uncurry 1 Snd)) - , (OTEither, (1 ** uncurry 2 Sum)) - , (OTLeft, (0 ** uncurry 1 Left)) - , (OTRight, (0 ** uncurry 1 Right)) - , (OTCase, (4 ** uncurry 5 Case)) - , (OTContainer, (2 ** uncurry 3 Container)) - , (OTTag, (0 ** uncurry 1 Tag)) - , (OTPosition, (0 ** uncurry 1 Position)) - , (OTNext, (0 ** uncurry 1 Next)) - , (OTSem, (2 ** uncurry 3 Sem)) - , (OTAbsurd, (1 ** uncurry 2 Absurd)) + , (OTAbsurd, (0 ** uncurry 1 Absurd)) , (OTRefl, (0 ** uncurry 1 Refl)) - , (OTTransp, (4 ** uncurry 5 Transp)) - , (OTCast, (2 ** uncurry 3 Cast)) + , (OTTransp, (4 ** (uncurry 5 Transp))) + , (OTCast, (3 ** uncurry 4 Cast)) , (OTCastRefl, (0 ** uncurry 1 CastId)) ] +headLambdaForms : List (ObsTokenKind, (n ** ((WithBounds String, WithBounds Syntax) -> Vect n (WithBounds Syntax) -> Syntax))) +headLambdaForms = + [ (OTIf, (3 ** (uncurry 3 . uncurry If))) + ] + declForms : List (ObsTokenKind, (WithBounds String -> op (WithBounds Syntax) Syntax 2)) declForms = [(OTThinArrow, Pi), (OTProduct, Sigma)] @@ -321,6 +320,11 @@ pair p = (optional whitespace *> p <* optional whitespace) |] <* match OTAClose <* commit +lambda : Lazy (Grammar state ObsToken True a) -> Grammar state ObsToken True (WithBounds String, a) +lambda p = + match OTBackslash *> commit *> + [| MkPair (ident <* whitespace <* match OTFatArrow <* whitespace) p |] + partial noSortsTerm : Grammar state ObsToken True (WithBounds Syntax) partial @@ -349,30 +353,25 @@ head = map (map Sort) sort <|> bounds (choiceMap + (\(hd, (n ** f)) => match hd *> commit *> + [| f (whitespace *> parens (lambda exp)) (count n (whitespace *> term))|]) + headLambdaForms) <|> + bounds + (choiceMap (\(hd, (n ** f)) => match hd *> commit *> [| f (count (S n) (whitespace *> term)) |]) headForms) spine = map (uncurry $ foldl (\t, u => joinBounds (map (\_ => map (\_ => App t u) u) t))) $ [| MkPair head (many (whitespace *> term)) |] -container = - map (\bounds@(MkBounded (t, u) _ _) => case u of - Nothing => t - Just (p, f) => map (\_ => MkContainer t p f) bounds) $ - bounds $ - [| MkPair spine - (optional - [| MkPair - (whitespace *> match OTTriangle *> commit *> whitespace *> spine) - (whitespace *> match OTSlash *> commit *> whitespace *> spine) - |]) - |] +container = spine equals = map (\(t, u) => maybe t (\u => joinBounds (map (\_ => map (\_ => Equal t u) u) t)) u) $ [| MkPair container (optional (whitespace *> match OTTilde *> commit *> whitespace *> container)) |] exp = equals <|> + bounds (map (uncurry Lambda) $ lambda exp) <|> bounds (map (\((var, a), (b, f)) => f var a b) $ [| MkPair @@ -380,11 +379,7 @@ exp = (choiceMap (\(op, f) => match op *> commit *> whitespace *> [| MkPair exp (pure f) |]) declForms) - |]) <|> - bounds - (map (uncurry Lambda) $ - match OTBackslash *> commit *> - [| MkPair (ident <* whitespace <* match OTFatArrow <* whitespace) exp |]) + |]) partial def : Grammar state ObsToken True (WithBounds String, WithBounds Syntax) @@ -404,8 +399,8 @@ partial file : Grammar state ObsToken False (List Definition) file = optional (whitespace *> match OTNewlines) *> - sepEndBy (optional whitespace *> match OTNewlines) (fullDef <* commit) <* - eof + sepEndBy (optional whitespace *> match OTNewlines) (fullDef <* commit) + -- <* eof whitespaceIrrelevant : WithBounds ObsToken -> WithBounds ObsToken whitespaceIrrelevant a = case (a.val.kind) of @@ -429,12 +424,7 @@ castErr : Either (List1 (ParsingError tok)) a -> Logging ann a castErr (Right x) = pure x castErr (Left errs) = do for_ {b = ()} errs - (\(Error msg bounds) => - error $ - maybe - (irrelevantBounds $ msg) - (\bounds => MkBounded msg False bounds) $ - bounds) + (\(Error msg bounds) => maybe id inBounds bounds $ error msg) abort partial @@ -442,8 +432,14 @@ export parse : String -> Logging ann (List Definition) parse str = do let (toks, _, _, "") = lex obsTokenMap str - | (_, l, c, rem) => inScope "lex" $ fatal "failed to lex input" + | (toks, l, c, rem) => inScope "lex" $ do + error "failed to lex input" + trace (map (\tok => show tok.val) toks) + trace (show rem) + abort let toks = preprocess toks (defs, []) <- inScope "parse" $ castErr $ parse file $ toks - | (_, ts) => inScope "parse" $ fatal "unparsed tokens" + | (_, ts) => inScope "parse" $ do + trace (map (show . val) ts) + fatal "unparsed tokens" pure defs diff --git a/src/Obs/Substitution.idr b/src/Obs/Substitution.idr index 340afff..22a7272 100644 --- a/src/Obs/Substitution.idr +++ b/src/Obs/Substitution.idr @@ -1,43 +1,83 @@ module Obs.Substitution -import Data.Fin +import public Data.List.Elem %default total -public export -interface Rename (0 x : Nat -> Type) where - rename : forall m, n . x n -> (Fin n -> Fin m) -> x m +infix 5 ~|> -public export -interface Rename x => PointedRename x where - point : forall n . Fin n -> x n +namespace Sorted + public export 0 + Family : Type -> Type + Family a = a -> List a -> Type -public export -interface Subst (0 x, y, z : Nat -> Type) where - subst : forall m, n . x n -> (Fin n -> y m) -> z m + public export 0 + Map : List a -> Family a -> List a -> Type + Map ctx x ctx' = {s : a} -> Elem s ctx -> x s ctx' -public export -Rename x => Subst x Fin x where - subst = rename + public export 0 + Hom : Family a -> Family a -> Family a + Hom x y s ctx = forall ctx' . Map ctx x ctx' -> y s ctx' + + public export 0 + (~|>) : Family a -> Family a -> Type + x ~|> y = forall ctx . {s : a} -> x s ctx -> y s ctx + + public export + interface Rename (0 a : _) (0 x : Family a) | x where + rename : x ~|> Hom Elem x + + public export + interface Rename a x => PointedRename a (0 b : a -> Type) x | x where + point : forall ctx . {s : a} -> b s -> Elem s ctx -> x s ctx + +namespace Unsorted + public export 0 + Family : Type -> Type + Family a = List a -> Type + + public export 0 + Hom : Sorted.Family a -> Unsorted.Family a -> Unsorted.Family a + Hom x y ctx = forall ctx' . Map ctx x ctx' -> y ctx' + + public export 0 + (~|>) : Unsorted.Family a -> Unsorted.Family a -> Type + x ~|> y = forall ctx . x ctx -> y ctx + + public export + interface Rename (0 a : _) (0 x : Unsorted.Family a) | x where + rename : x ~|> Hom Elem x public export -Rename Fin where +Sorted.Rename a Elem where rename i f = f i public export -PointedRename Fin where - point = id +PointedRename a (const ()) Elem where + point _ = id public export -add : (0 x : _) -> x n -> (Fin m -> x n) -> Fin (S m) -> x n -add x v f FZ = v -add x v f (FS i) = f i +add : (0 x : Sorted.Family a) -> x s' ctx' -> Map ctx x ctx' -> Map (s' :: ctx) x ctx' +add x v f Here = v +add x v f (There i) = f i public export -lift : PointedRename x => (k : _) -> (Fin m -> x n) -> Fin (k + m) -> x (k + n) -lift 0 f = f -lift (S k) f = add x (point FZ) (\i => rename (lift k f i) FS) +lift : PointedRename a b x => (ctx : List (s ** b s)) + -> Map ctx' x ctx'' + -> Map (map DPair.fst ctx ++ ctx') x (map DPair.fst ctx ++ ctx'') +lift [] f = f +lift ((s ** y) :: ctx) f = add x (point y Here) (\i => rename (lift ctx f i) There) -public export -weaken : Rename x => (m : _) -> x n -> x (m + n) -weaken m t = rename t (shift m) +elemAppRight : (xs : List a) -> (0 ys : List a) -> Elem x ys -> Elem.Elem x (xs ++ ys) +elemAppRight [] _ = id +elemAppRight (x :: xs) ys = There . elemAppRight xs ys + +namespace Sorted + export + weaken : Sorted.Rename a x => (ctx : _) -> x ~|> (\s, ctx' => x s (ctx ++ ctx')) + weaken ctx t = rename t (elemAppRight ctx _) + +namespace Unsorted + export + weaken : Unsorted.Rename a x => (ctx : _) -> x ~|> (\ctx' => x (ctx ++ ctx')) + weaken ctx t = rename t (elemAppRight ctx _) diff --git a/src/Obs/Syntax.idr b/src/Obs/Syntax.idr index d21569a..7bf4b61 100644 --- a/src/Obs/Syntax.idr +++ b/src/Obs/Syntax.idr @@ -2,6 +2,7 @@ module Obs.Syntax import Obs.Sort + import Text.Bounded import Text.PrettyPrint.Prettyprinter @@ -11,41 +12,34 @@ import Text.PrettyPrint.Prettyprinter public export data Syntax : Type where - Var : String -> Syntax + Var : String -> Syntax -- Sorts - Sort : Sort -> Syntax + Sort : Sort -> Syntax -- Dependent Products - Pi : WithBounds String -> WithBounds Syntax -> WithBounds Syntax -> Syntax + Pi : WithBounds String -> WithBounds Syntax -> WithBounds Syntax -> Syntax Lambda : WithBounds String -> WithBounds Syntax -> Syntax - App : WithBounds Syntax -> WithBounds Syntax -> Syntax + App : WithBounds Syntax -> WithBounds Syntax -> Syntax -- Dependent Sums - Sigma : WithBounds String -> WithBounds Syntax -> WithBounds Syntax -> Syntax - Pair : WithBounds Syntax -> WithBounds Syntax -> Syntax - Fst : WithBounds Syntax -> Syntax - Snd : WithBounds Syntax -> Syntax - -- Disjoint Coproducts - Sum : WithBounds Syntax -> WithBounds Syntax -> Syntax - Left : WithBounds Syntax -> Syntax - Right : WithBounds Syntax -> Syntax - Case : WithBounds Syntax -> WithBounds Syntax -> WithBounds Syntax -> WithBounds Syntax -> WithBounds Syntax -> Syntax - -- Containers - Container : WithBounds Syntax -> WithBounds Syntax -> WithBounds Syntax -> Syntax - MkContainer : WithBounds Syntax -> WithBounds Syntax -> WithBounds Syntax -> Syntax - Tag : WithBounds Syntax -> Syntax - Position : WithBounds Syntax -> Syntax - Next : WithBounds Syntax -> Syntax - Sem : WithBounds Syntax -> WithBounds Syntax -> WithBounds Syntax -> Syntax + Sigma : WithBounds String -> WithBounds Syntax -> WithBounds Syntax -> Syntax + Pair : WithBounds Syntax -> WithBounds Syntax -> Syntax + Fst : WithBounds Syntax -> Syntax + Snd : WithBounds Syntax -> Syntax + -- Booleans + Bool : Syntax + True : Syntax + False : Syntax + If : WithBounds String -> WithBounds Syntax -> WithBounds Syntax -> WithBounds Syntax -> WithBounds Syntax -> Syntax -- True - Top : Syntax - Point : Syntax + Top : Syntax + Point : Syntax -- False Bottom : Syntax - Absurd : WithBounds Syntax -> WithBounds Syntax -> Syntax + Absurd : WithBounds Syntax -> Syntax -- Equality - Equal : WithBounds Syntax -> WithBounds Syntax -> Syntax - Refl : WithBounds Syntax -> Syntax + Equal : WithBounds Syntax -> WithBounds Syntax -> Syntax + Refl : WithBounds Syntax -> Syntax Transp : WithBounds Syntax -> WithBounds Syntax -> WithBounds Syntax -> WithBounds Syntax -> WithBounds Syntax -> Syntax - Cast : WithBounds Syntax -> WithBounds Syntax -> WithBounds Syntax -> Syntax + Cast : WithBounds Syntax -> WithBounds Syntax -> WithBounds Syntax -> WithBounds Syntax -> Syntax CastId : WithBounds Syntax -> Syntax public export @@ -65,115 +59,94 @@ prettyPrec d (Sort s) = prettyPrec d s prettyPrec d (Pi var a b) = parenthesise (d > Open) $ group $ - parens (pretty var.val <++> colon <+> softline <+> prettyPrecBounds Open a) <++> - pretty "->" <+> softline <+> - prettyPrecBounds Open b + parens (pretty var.val <++> colon <+> softline <+> align (prettyPrecBounds Open a)) <++> + pretty "->" <+> line <+> + align (prettyPrecBounds Open b) prettyPrec d (Lambda var t) = parenthesise (d > Open) $ group $ backslash <+> pretty var.val <++> - pretty "=>" <+> softline <+> - prettyPrecBounds Open t + pretty "=>" <+> line <+> + align (prettyPrecBounds Open t) prettyPrec d (App t u) = parenthesise (d >= App) $ group $ - fillSep [prettyPrecBounds Open t, prettyPrecBounds App u] + vsep [prettyPrecBounds Open t, prettyPrecBounds App u] prettyPrec d (Sigma var a b) = parenthesise (d >= App) $ group $ - parens (pretty var.val <++> colon <+> softline <+> prettyPrecBounds Open a) <++> - pretty "**" <+> softline <+> - prettyPrecBounds Open b + parens (pretty var.val <++> colon <+> softline <+> align (prettyPrecBounds Open a)) <++> + pretty "**" <+> line <+> + align (prettyPrecBounds Open b) prettyPrec d (Pair t u) = angles $ group $ - neutral <++> prettyPrecBounds Open t <+> comma <+> softline <+> prettyPrecBounds Open u <++> neutral + neutral <++> prettyPrecBounds Open t <+> comma <+> line <+> prettyPrecBounds Open u <++> neutral prettyPrec d (Fst t) = parenthesise (d >= App) $ group $ - fillSep [pretty "fst", prettyPrecBounds App t] + vsep [pretty "fst", prettyPrecBounds App t] prettyPrec d (Snd t) = parenthesise (d >= App) $ group $ - fillSep [pretty "snd", prettyPrecBounds App t] -prettyPrec d (Sum a b) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "Either", prettyPrecBounds App a, prettyPrecBounds App b] -prettyPrec d (Left t) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "Left", prettyPrecBounds App t] -prettyPrec d (Right t) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "Right", prettyPrecBounds App t] -prettyPrec d (Case t s b f g) = + vsep [pretty "snd", prettyPrecBounds App t] +prettyPrec d Bool = pretty "Bool" +prettyPrec d True = pretty "True" +prettyPrec d False = pretty "False" +prettyPrec d (If var a t f g) = parenthesise (d >= App) $ group $ - fillSep [pretty "case", prettyPrecBounds App t, prettyPrecBounds App s, prettyPrecBounds App b, prettyPrecBounds App f, prettyPrecBounds App g] -prettyPrec d (Container a s s') = - parenthesise (d >= App) $ - group $ - fillSep [pretty "Container", prettyPrecBounds App a, prettyPrecBounds App s, prettyPrecBounds App s'] -prettyPrec d (MkContainer t p f) = - parenthesise (d >= User 0) $ - group $ - fillSep - [ prettyPrecBounds (User 0) t <++> pretty "<|" - , prettyPrecBounds (User 0) p <++> pretty "/" - , prettyPrecBounds (User 0) f - ] -prettyPrec d (Tag t) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "tag", prettyPrecBounds App t] -prettyPrec d (Position t) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "position", prettyPrecBounds App t] -prettyPrec d (Next t) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "next", prettyPrecBounds App t] -prettyPrec d (Sem s a t) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "sem", prettyPrecBounds App s, prettyPrecBounds App a, prettyPrecBounds App t] + vsep $ + [ pretty "if" + , parens $ + group $ + backslash <+> pretty var.val <++> + pretty "=>" <+> line <+> + align (prettyPrecBounds Open a) + , prettyPrecBounds App t + , prettyPrecBounds App f + , prettyPrecBounds App g + ] prettyPrec d Top = pretty "()" prettyPrec d Point = pretty "tt" prettyPrec d Bottom = pretty "Void" -prettyPrec d (Absurd a t) = +prettyPrec d (Absurd t) = parenthesise (d >= App) $ group $ - fillSep [pretty "absurd", prettyPrecBounds App a, prettyPrecBounds App t] + vsep [pretty "absurd", prettyPrecBounds App t] prettyPrec d (Equal t u) = parenthesise (d >= Equal) $ group $ - prettyPrecBounds Equal t <++> pretty "~" <+> softline <+> prettyPrecBounds Equal u + prettyPrecBounds Equal t <++> pretty "~" <+> line <+> prettyPrecBounds Equal u prettyPrec d (Refl t) = parenthesise (d >= App) $ group $ - fillSep [pretty "refl", prettyPrecBounds App t] -prettyPrec d (Transp t b u t' e) = + vsep [pretty "refl", prettyPrecBounds App t] +prettyPrec d (Transp a t u t' e) = parenthesise (d >= App) $ group $ - fillSep $ + vsep $ [ pretty "transp" + , prettyPrecBounds App a , prettyPrecBounds App t - , prettyPrecBounds App b , prettyPrecBounds App u , prettyPrecBounds App t' , prettyPrecBounds App e ] -prettyPrec d (Cast b e t) = +prettyPrec d (Cast a b e t) = parenthesise (d >= App) $ group $ - fillSep [pretty "cast", prettyPrecBounds App b, prettyPrecBounds App e, prettyPrecBounds App t] + vsep $ + [ pretty "cast" + , prettyPrecBounds App a + , prettyPrecBounds App b + , prettyPrecBounds App e + , prettyPrecBounds App t + ] prettyPrec d (CastId t) = parenthesise (d >= App) $ group $ - fillSep [pretty "castRefl", prettyPrecBounds App t] + vsep [pretty "castRefl", prettyPrecBounds App t] prettyPrecBounds d (MkBounded val _ _) = prettyPrec d val diff --git a/src/Obs/Term.idr b/src/Obs/Term.idr index 10f2129..422af87 100644 --- a/src/Obs/Term.idr +++ b/src/Obs/Term.idr @@ -12,41 +12,48 @@ import Text.PrettyPrint.Prettyprinter public export data Term : Nat -> Type where - Var : String -> Fin n -> Term n + Var : String -> Fin n -> Term n -- Sorts - Sort : Sort -> Term n + Sort : Sort -> Term n -- Dependent Product - Pi : WithBounds String -> WithBounds (Term n) -> WithBounds (Term (S n)) -> Term n + Pi : WithBounds String -> WithBounds (Term n) -> WithBounds (Term (S n)) -> Term n Lambda : WithBounds String -> WithBounds (Term (S n)) -> Term n - App : WithBounds (Term n) -> WithBounds (Term n) -> Term n + App : WithBounds (Term n) -> WithBounds (Term n) -> Term n -- Dependent Sums - Sigma : WithBounds String -> WithBounds (Term n) -> WithBounds (Term (S n)) -> Term n - Pair : WithBounds (Term n) -> WithBounds (Term n) -> Term n - Fst : WithBounds (Term n) -> Term n - Snd : WithBounds (Term n) -> Term n - -- Disjoint Coproducts - Sum : WithBounds (Term n) -> WithBounds (Term n) -> Term n - Left : WithBounds (Term n) -> Term n - Right : WithBounds (Term n) -> Term n - Case : WithBounds (Term n) -> WithBounds (Term n) -> WithBounds (Term n) -> WithBounds (Term n) -> WithBounds (Term n) -> Term n - -- Containers - Container : WithBounds (Term n) -> WithBounds (Term n) -> WithBounds (Term n) -> Term n - MkContainer : WithBounds (Term n) -> WithBounds (Term n) -> WithBounds (Term n) -> Term n - Tag : WithBounds (Term n) -> Term n - Position : WithBounds (Term n) -> Term n - Next : WithBounds (Term n) -> Term n - Sem : WithBounds (Term n) -> WithBounds (Term n) -> WithBounds (Term n) -> Term n + Sigma : WithBounds String -> WithBounds (Term n) -> WithBounds (Term (S n)) -> Term n + Pair : WithBounds (Term n) -> WithBounds (Term n) -> Term n + Fst : WithBounds (Term n) -> Term n + Snd : WithBounds (Term n) -> Term n + -- Booleans + Bool : Term n + True : Term n + False : Term n + If : WithBounds String -> + WithBounds (Term (S n)) -> + WithBounds (Term n) -> + WithBounds (Term n) -> + WithBounds (Term n) -> + Term n -- True - Top : Term n - Point : Term n + Top : Term n + Point : Term n -- False Bottom : Term n - Absurd : WithBounds (Term n) -> WithBounds (Term n) -> Term n + Absurd : WithBounds (Term n) -> Term n -- Equality - Equal : WithBounds (Term n) -> WithBounds (Term n) -> Term n - Refl : WithBounds (Term n) -> Term n - Transp : WithBounds (Term n) -> WithBounds (Term n) -> WithBounds (Term n) -> WithBounds (Term n) -> WithBounds (Term n) -> Term n - Cast : WithBounds (Term n) -> WithBounds (Term n) -> WithBounds (Term n) -> Term n + Equal : WithBounds (Term n) -> WithBounds (Term n) -> Term n + Refl : WithBounds (Term n) -> Term n + Transp : WithBounds (Term n) -> + WithBounds (Term n) -> + WithBounds (Term n) -> + WithBounds (Term n) -> + WithBounds (Term n) -> + Term n + Cast : WithBounds (Term n) -> + WithBounds (Term n) -> + WithBounds (Term n) -> + WithBounds (Term n) -> + Term n CastId : WithBounds (Term n) -> Term n public export @@ -71,115 +78,94 @@ prettyPrec d (Sort s) = prettyPrec d s prettyPrec d (Pi var a b) = parenthesise (d > Open) $ group $ - parens (pretty var.val <++> colon <+> softline <+> prettyPrecBounds Open a) <++> - pretty "->" <+> softline <+> - prettyPrecBounds Open b + parens (pretty var.val <++> colon <+> softline <+> align (prettyPrecBounds Open a)) <++> + pretty "->" <+> line <+> + align (prettyPrecBounds Open b) prettyPrec d (Lambda var t) = parenthesise (d > Open) $ group $ backslash <+> pretty var.val <++> - pretty "=>" <+> softline <+> - prettyPrecBounds Open t + pretty "=>" <+> line <+> + align (prettyPrecBounds Open t) prettyPrec d (App t u) = parenthesise (d >= App) $ group $ - fillSep [prettyPrecBounds Open t, prettyPrecBounds App u] + vsep [prettyPrecBounds Open t, prettyPrecBounds App u] prettyPrec d (Sigma var a b) = parenthesise (d >= App) $ group $ - parens (pretty var.val <++> colon <+> softline <+> prettyPrecBounds Open a) <++> - pretty "**" <+> softline <+> - prettyPrecBounds Open b + parens (pretty var.val <++> colon <+> softline <+> align (prettyPrecBounds Open a)) <++> + pretty "**" <+> line <+> + align (prettyPrecBounds Open b) prettyPrec d (Pair t u) = angles $ group $ - neutral <++> prettyPrecBounds Open t <+> comma <+> softline <+> prettyPrecBounds Open u <++> neutral + neutral <++> prettyPrecBounds Open t <+> comma <+> line <+> prettyPrecBounds Open u <++> neutral prettyPrec d (Fst t) = parenthesise (d >= App) $ group $ - fillSep [pretty "fst", prettyPrecBounds App t] + vsep [pretty "fst", prettyPrecBounds App t] prettyPrec d (Snd t) = parenthesise (d >= App) $ group $ - fillSep [pretty "snd", prettyPrecBounds App t] -prettyPrec d (Sum a b) = + vsep [pretty "snd", prettyPrecBounds App t] +prettyPrec d Bool = pretty "Bool" +prettyPrec d True = pretty "True" +prettyPrec d False = pretty "False" +prettyPrec d (If var a t f g) = parenthesise (d >= App) $ group $ - fillSep [pretty "Either", prettyPrecBounds App a, prettyPrecBounds App b] -prettyPrec d (Left t) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "Left", prettyPrecBounds App t] -prettyPrec d (Right t) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "Right", prettyPrecBounds App t] -prettyPrec d (Case t s b f g) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "case", prettyPrecBounds App t, prettyPrecBounds App s, prettyPrecBounds App b, prettyPrecBounds App f, prettyPrecBounds App g] -prettyPrec d (Container a s s') = - parenthesise (d >= App) $ - group $ - fillSep [pretty "Container", prettyPrecBounds App a, prettyPrecBounds App s, prettyPrecBounds App s'] -prettyPrec d (MkContainer t p f) = - parenthesise (d >= User 0) $ - group $ - fillSep - [ prettyPrecBounds (User 0) t <++> pretty "<|" - , prettyPrecBounds (User 0) p <++> pretty "/" - , prettyPrecBounds (User 0) f - ] -prettyPrec d (Tag t) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "tag", prettyPrecBounds App t] -prettyPrec d (Position t) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "position", prettyPrecBounds App t] -prettyPrec d (Next t) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "next", prettyPrecBounds App t] -prettyPrec d (Sem s a t) = - parenthesise (d >= App) $ - group $ - fillSep [pretty "sem", prettyPrecBounds App s, prettyPrecBounds App a, prettyPrecBounds App t] + vsep $ + [ pretty "if" + , parens $ + group $ + backslash <+> pretty var.val <++> + pretty "=>" <+> line <+> + align (prettyPrecBounds Open a) + , prettyPrecBounds App t + , prettyPrecBounds App f + , prettyPrecBounds App g + ] prettyPrec d Top = pretty "()" prettyPrec d Point = pretty "tt" prettyPrec d Bottom = pretty "Void" -prettyPrec d (Absurd a t) = +prettyPrec d (Absurd t) = parenthesise (d > Open) $ group $ - fillSep [pretty "absurd", prettyPrecBounds App a, prettyPrecBounds App t] + vsep [pretty "absurd", prettyPrecBounds App t] prettyPrec d (Equal t u) = parenthesise (d >= Equal) $ group $ - prettyPrecBounds Equal t <++> pretty "~" <+> softline <+> prettyPrecBounds Equal u + prettyPrecBounds Equal t <++> pretty "~" <+> line <+> prettyPrecBounds Equal u prettyPrec d (Refl t) = parenthesise (d >= App) $ group $ - fillSep [pretty "refl", prettyPrecBounds App t] -prettyPrec d (Transp t b u t' e) = + vsep [pretty "refl", prettyPrecBounds App t] +prettyPrec d (Transp a t u t' e) = parenthesise (d >= App) $ group $ - fillSep $ + vsep $ [ pretty "transp" + , prettyPrecBounds App a , prettyPrecBounds App t - , prettyPrecBounds App b , prettyPrecBounds App u , prettyPrecBounds App t' , prettyPrecBounds App e ] -prettyPrec d (Cast b e t) = +prettyPrec d (Cast a b e t) = parenthesise (d >= App) $ group $ - fillSep [pretty "cast", prettyPrecBounds App b, prettyPrecBounds App e, prettyPrecBounds App t] + vsep $ + [ pretty "cast" + , prettyPrecBounds App a + , prettyPrecBounds App b + , prettyPrecBounds App e + , prettyPrecBounds App t + ] prettyPrec d (CastId t) = parenthesise (d >= App) $ group $ - fillSep [pretty "castRefl", prettyPrecBounds App t] + vsep [pretty "castRefl", prettyPrecBounds App t] prettyPrecBounds d (MkBounded v _ _) = prettyPrec d v diff --git a/src/Obs/Typing.idr b/src/Obs/Typing.idr index f814f93..4cc6d8e 100644 --- a/src/Obs/Typing.idr +++ b/src/Obs/Typing.idr @@ -1,6 +1,10 @@ module Obs.Typing -import Data.Vect +import Control.Monad.Maybe + +import Data.Nat + +import Decidable.Equality import Obs.Logging import Obs.NormalForm @@ -8,6 +12,7 @@ import Obs.NormalForm.Normalise import Obs.Sort import Obs.Substitution import Obs.Term +import Obs.Typing.Context import Obs.Typing.Conversion import System @@ -20,384 +25,255 @@ import Text.PrettyPrint.Prettyprinter.Render.Terminal -- Loggings ---------------------------------------------------------------------- -Rename (Logging ann . NormalForm) where - rename t f = pure $ rename !t f - -mismatch : Bounds -> Doc ann -> Doc ann -> Logging ann a -mismatch bounds lhs rhs = fatal $ - MkBounded - (pretty "expected" <++> lhs <+> comma <+> softline <+> pretty "got" <++> rhs) - False - bounds - -typeMismatch : Bounds -> Doc ann -> Doc ann -> Logging ann a -typeMismatch bounds lhs rhs = inScope "type mismatch" $ mismatch bounds lhs rhs - -sortMismatch : Bounds -> Doc ann -> Doc ann -> Logging ann a -sortMismatch bounds lhs rhs = inScope "sort mismatch" $ mismatch bounds lhs rhs +mismatch : (expected, got : Doc ann) -> Logging ann a +mismatch lhs rhs = fatal $ + hang 2 (pretty "expected" <+> line <+> lhs) <+> comma <+> line <+> + hang 2 (pretty "got" <+> line <+> align rhs) --- Typing Contexts ------------------------------------------------------------- +typeMismatch : Doc ann -> Doc ann -> Logging ann a +typeMismatch lhs rhs = inScope "type mismatch" $ mismatch lhs rhs -infix 5 ::< +sortMismatch : Doc ann -> Doc ann -> Logging ann a +sortMismatch lhs rhs = inScope "sort mismatch" $ mismatch lhs rhs -data TyContext : Nat -> Nat -> Type where - Nil : TyContext 0 0 - (:<) : TyContext m n -> NormalForm.Definition n -> TyContext m (S n) - (::<) : TyContext m n -> (String, NormalForm n, Sort) -> TyContext (S m) (S n) +-- Utilities ------------------------------------------------------------------- -fromContext : Context n -> TyContext 0 n -fromContext [] = [] -fromContext (ctx :< def) = fromContext ctx :< def +MkPair : (s, s' : Sort) + -> NormalForm (isSet s) ctx + -> NormalForm (isSet s') ctx + -> NormalForm (isSet (max s s')) ctx +MkPair Prop Prop t u = u +MkPair Prop s'@(Set _) t u = Cnstr $ Pair Prop s' Oh t u +MkPair s@(Set _) s' t u = Cnstr $ Pair s s' Oh t u -countVars : TyContext m n -> Fin (S n) -countVars [] = FZ -countVars (ctx :< y) = weaken $ countVars ctx -countVars (ctx ::< y) = FS $ countVars ctx +-- Checking and Inference ------------------------------------------------------ -index : TyContext m n -> Fin n -> (NormalForm n, NormalForm n, Sort) -index (ctx :< def) FZ = (weaken 1 def.tm, weaken 1 def.ty, def.sort) -index (ctx ::< (var, ty, Prop)) FZ = (Irrel, weaken 1 ty, Prop) -index (ctx ::< (var, ty, s)) FZ = (Ntrl $ Var var FZ, weaken 1 ty, s) -index (ctx :< _) (FS i) = bimap (weaken 1) (mapFst (weaken 1)) $ index ctx i -index (ctx ::< _) (FS i) = bimap (weaken 1) (mapFst (weaken 1)) $ index ctx i +check : (tyCtx : TyContext ctx) + -> (s : Sort) + -> NormalForm True ctx + -> WithBounds (Term (length ctx)) + -> Logging ann (NormalForm (isSet s) ctx) -partial -asSubst : (ctx : TyContext m n) -> Fin n -> Logging ann (NormalForm m) -asSubst (ctx :< def) FZ = subst def.tm (asSubst ctx) -asSubst (ctx ::< (var, _, Prop)) FZ = pure Irrel -asSubst (ctx ::< (var, _, _)) FZ = pure $ Ntrl (Var var FZ) -asSubst (ctx :< def) (FS i) = asSubst ctx i -asSubst (ctx ::< _) (FS i) = map (weaken 1) (asSubst ctx i) +checkType : (tyCtx : TyContext ctx) + -> (s : Sort) + -> WithBounds (Term (length ctx)) + -> Logging ann (NormalForm True ctx) +checkType ctx s tm = check ctx (suc s) (cast s) tm --- Checking and Inference ------------------------------------------------------ +infer : (tyCtx : TyContext ctx) + -> WithBounds (Term (length ctx)) + -> Logging ann (s ** (NormalForm True ctx, NormalForm (isSet s) ctx)) -partial -check : TyContext m n -> WithBounds (Term n) -> NormalForm n -> Sort -> Logging ann (NormalForm n) -partial -infer : TyContext m n -> WithBounds (Term n) -> Logging ann (NormalForm n, NormalForm n, Sort) -partial -inferType : {default typeMismatch tag : forall a . Bounds -> Doc ann -> Doc ann -> Logging ann a} - -> TyContext m n -> WithBounds (Term n) -> Logging ann (NormalForm n, Sort) -partial -inferSort : TyContext m n -> WithBounds (Term n) -> Logging ann Sort +inferType : {default typeMismatch tag : forall a . Doc ann -> Doc ann -> Logging ann a} + -> (tyCtx : TyContext ctx) + -> WithBounds (Term (length ctx)) + -> Logging ann (Sort, NormalForm True ctx) +inferType ctx tm = inBounds tm.bounds $ do + (Set _ ** (Cnstr (Sort s), a)) <- infer ctx tm + | (_ ** (a, t)) => tag (pretty "sort") (pretty a) + pure (s, a) -check ctx tm ty s = case (tm.val, ty) of - (Lambda _ t, Cnstr (Pi s s' var a b)) => do - inScope "check" $ trace $ map (\_ => pretty {ann} "checking under lambda with type" <++> pretty a) tm - inScope "check" $ trace $ map (\_ => "binding new variable to \{var}") tm - inScope "check" $ trace $ map (\_ => pretty {ann} "checking for type" <++> pretty b) tm - t <- check (ctx ::< (var, a, s)) t b s' - case s' of - Prop => pure Irrel - _ => pure (Cnstr $ Lambda var t) - (Lambda _ _, ty) => typeMismatch tm.bounds (pretty "pi") (pretty ty) - (Pair t u, Cnstr (Sigma s s' var a b)) => do - inScope "check" $ trace $ map (\_ => "checking pair") tm - inScope "check" $ trace $ map (\_ => pretty {ann} "checking first for type" <++> pretty a) tm - t <- check ctx t a s +check ctx s ty tm = inBounds tm.bounds $ case (ty, tm.val) of + (Cnstr (Pi l l' _ a b), Lambda var t) => do + info "encountered lambda" + trace $ pretty {ann} "checking body has type" <++> pretty b + t <- check (ctx ::< MkFreeVar l a var.val) l' b (assert_smaller tm t) + let Yes Refl = decEq s (l ~> l') + | No _ => fatal "internal sort mismatch" + pure $ case l' of + Prop => Irrel + Set _ => Cnstr (Lambda l var.val t) + (_, Lambda var t) => typeMismatch (pretty "function") (pretty ty) + (Cnstr (Sigma l l' var a b), Pair t u) => do + info "encountered pair" + trace $ pretty {ann} "checking first has type" <++> pretty a + t <- check ctx l a (assert_smaller tm t) b <- subst1 t b - inScope "check" $ trace $ map (\_ => pretty {ann} "checking second for type" <++> pretty b) tm - u <- check ctx u b s' - inScope "check" $ trace $ map (\_ => pretty {ann} "pair is well typed") tm - case (s, s') of - (Prop, Prop) => pure Irrel - _ => pure (Cnstr $ Pair t u) - (Pair _ _, ty) => typeMismatch tm.bounds (pretty "sigma") (pretty ty) - (Left t, Cnstr (Sum s s' a b)) => do - inScope "check" $ trace $ map (\_ => "checking left injection") tm - inScope "check" $ trace $ map (\_ => pretty {ann} "checking subterm for type" <++> pretty a) tm - t <- check ctx t a s - inScope "check" $ trace $ map (\_ => " subterm is well typed") tm - pure (Cnstr $ Left t) - (Left _, ty) => typeMismatch tm.bounds (pretty "sum") (pretty ty) - (Right t, Cnstr (Sum s s' a b)) => do - inScope "check" $ trace $ map (\_ => "checking right injection") tm - inScope "check" $ trace $ map (\_ => pretty {ann} "checking subterm for type" <++> pretty b) tm - t <- check ctx t b s' - inScope "check" $ trace $ map (\_ => " subterm is well typed") tm - pure (Cnstr $ Right t) - (Right _, ty) => typeMismatch tm.bounds (pretty "sum") (pretty ty) - (MkContainer t p f, Cnstr (Container s a s' s'')) => do - inScope "check" $ trace $ map (\_ => "checking container constructor") tm - let tagTy = tagTy s a s' - inScope "check" $ trace $ map (\_ => pretty {ann} "checking tag for type" <++> pretty tagTy) tm - t <- check ctx t (Cnstr tagTy) (s ~> suc s') - inScope "check" $ trace $ map (\_ => "tag is well typed") tm - positionTy <- positionTy s a s' t s'' - inScope "check" $ trace $ map (\_ => pretty {ann} "checking position for type" <++> pretty positionTy) tm - p <- check ctx p (Cnstr positionTy) (s ~> s' ~> suc s'') - inScope "check" $ trace $ map (\_ => "position is well typed") tm - nextTy <- nextTy s a s' t s'' p - inScope "check" $ trace $ map (\_ => pretty {ann} "checking next for type" <++> pretty nextTy) tm - f <- check ctx f (Cnstr nextTy) (s ~> s' ~> s'' ~> s) - inScope "check" $ trace $ map (\_ => "next is well typed") tm - pure (Cnstr $ MkContainer t p f) - (MkContainer t p f, ty) => typeMismatch tm.bounds (pretty "container") (pretty ty) - (_, _) => do - inScope "check" $ trace $ map (\_ => "checking has fallen through") tm - (v, a, s') <- infer ctx tm - inScope "check" $ trace $ map (\_ => pretty {ann} "inferred type is" <++> pretty a) tm - let True = s == s' - | False => sortMismatch tm.bounds (pretty s) (pretty s') - True <- convert !(subst ty $ asSubst ctx) !(subst a $ asSubst ctx) (cast s) (suc s) - | False => typeMismatch tm.bounds (pretty ty) (pretty a) - inScope "check" $ trace $ map (\_ => pretty {ann} "converted" <++> pretty a <+> softline <+> pretty "to" <++> pretty ty) tm - pure v + trace $ pretty {ann} "checking second has type" <++> pretty b + u <- check ctx l' b (assert_smaller tm u) + let Yes Refl = decEq s (max l l') + | No _ => fatal "internal sort mismatch" + pure $ MkPair l l' t u + (_, Pair t u) => typeMismatch (pretty "pair type") (pretty ty) + (_, Absurd t) => do + info "encountered absurd" + trace "checking proof of contradiction" + Irrel <- check ctx Prop (Cnstr Bottom) (assert_smaller tm t) + pure $ doAbsurd _ + (a, t) => do + info "falling through to inference" + (l ** (b, t)) <- infer ctx tm + trace $ pretty {ann} "inferred type is" <++> pretty b + let Yes Refl = decEq s l + | No _ => typeMismatch (pretty a) (pretty b) + a' <- subst a (reduce ctx) + b' <- subst b (reduce ctx) + Just _ <- inScope "convert" $ runMaybeT $ convert (suc s) (cast s) a' b' + | Nothing => inScope "conversion failed" $ mismatch (pretty a) (pretty b) + pure t -infer ctx tm = case tm.val of +infer ctx tm = inBounds tm.bounds $ case tm.val of (Var var i) => do - inScope "infer" $ trace $ map (\_ => "encountered variable \{var}@\{show i}") tm - let (t, a, s) = index ctx i - inScope "infer" $ trace $ map (\_ => pretty {ann} "variable has type" <++> pretty a) tm - pure (t, a, s) - (Sort s) => pure (cast s, cast (suc s), suc (suc s)) + info $ pretty {ann} "encountered variable" <++> pretty tm.val + let def = index' ctx i + pure (def.sort ** (def.ty, def.tm)) + (Sort s) => do + info $ pretty {ann} "encountered sort" <++> pretty tm.val + pure (suc (suc s) ** (cast (suc s), cast s)) (Pi var a b) => do - inScope "infer" $ trace $ map (\_ => "encountered Pi type") tm - (a, s) <- inferType ctx a - inScope "infer" $ trace $ map (\_ => pretty {ann} "argument has type" <++> pretty a) tm - (b, s') <- inferType (ctx ::< (var.val, a, s)) b - inScope "infer" $ trace $ map (\_ => pretty {ann} "result has type" <++> pretty b <+> comma <+> softline <+> pretty "so Pi type has type" <++> pretty (s ~> s')) tm - pure (Cnstr (Pi s s' var.val a b), cast (s ~> s'), suc (s ~> s')) - (Lambda _ _) => inScope "cannot infer type" $ fatal tm + info "encountered pi" + (s, a) <- inferType ctx (assert_smaller tm a) + trace $ pretty {ann} "domain type is" <++> pretty a + (s', b) <- inferType (ctx ::< MkFreeVar s a var.val) (assert_smaller tm b) + trace $ pretty {ann} "codomain type is" <++> pretty b + pure (suc (s ~> s') ** (cast (s ~> s'), Cnstr (Pi s s' var.val a b))) + (Lambda var t) => fatal "cannot infer type of lambda" (App t u) => do - inScope "infer" $ trace $ map (\_ => "encountered application") tm - (t, ty@(Cnstr (Pi s s' _ a b)), _) <- infer ctx t - | (_, ty, _) => inScope "wrong type to apply" $ fatal (map (\_ => ty) tm) - inScope "infer" $ trace $ map (\_ => pretty {ann} "function has type" <++> pretty ty) tm - inScope "infer" $ trace $ map (\_ => pretty {ann} "checking argument has type" <++> pretty a) tm - u <- check ctx u a s - inScope "infer" $ trace $ map (\_ => "argument is well typed") tm - res <- doApp t u + info "encountered application" + (s ** (ty@(Cnstr (Pi l l' _ a b)), t)) <- infer ctx (assert_smaller tm t) + | (_ ** (ty, _)) => inBounds t.bounds $ typeMismatch (pretty "function") (pretty ty) + trace $ pretty {ann} "function has type" <++> pretty ty + trace $ pretty {ann} "checking argument has type" <++> pretty a + u <- check ctx l a (assert_smaller tm u) + trace $ pretty {ann} "argument is well typed" + let Yes Refl = decEq s (l ~> l') + | No _ => fatal "internal sort mismatch" ty <- subst1 u b - inScope "infer" $ trace $ map (\_ => pretty {ann} "final result is" <++> pretty res <+> softline <+> pretty "of type" <++> pretty ty) tm - pure (res, ty, s') + tm <- doApp t u + pure (l' ** (ty, rewrite sym $ impredicative l l' in tm)) (Sigma var a b) => do - inScope "infer" $ trace $ map (\_ => "encountered Sigma type") tm - (a, s) <- inferType ctx a - inScope "infer" $ trace $ map (\_ => pretty {ann} "first has type" <++> pretty a) tm - (b, s') <- inferType (ctx ::< (var.val, a, s)) b - inScope "infer" $ trace $ map (\_ => pretty {ann} "second has type" <++> pretty b <+> comma <+> softline <+> pretty "so Sigma type has type" <++> pretty (lub s s')) tm - pure (Cnstr (Sigma s s' var.val a b), cast (lub s s'), suc (lub s s')) - (Pair _ _) => inScope "cannot infer type" $ fatal tm + info "encountered sigma" + (s, a) <- inferType ctx (assert_smaller tm a) + trace $ pretty {ann} "first type is" <++> pretty a + (s', b) <- inferType (ctx ::< MkFreeVar s a var.val) (assert_smaller tm b) + trace $ pretty {ann} "second type is" <++> pretty b + pure (suc (max s s') ** (cast (max s s'), Cnstr (Sigma s s' var.val a b))) + (Pair t u) => fatal "cannot infer type of pair" (Fst t) => do - inScope "infer" $ trace $ map (\_ => "encountered first projection") tm - (t, ty@(Cnstr (Sigma s s' _ a b)), _) <- infer ctx t - | (_, ty, _) => inScope "wrong type to fst" $ fatal (map (\_ => ty) tm) - inScope "infer" $ trace $ map (\_ => pretty {ann} "pair has type" <++> pretty ty) tm - res <- doFst t - inScope "infer" $ trace $ map (\_ => pretty {ann} "final result is" <++> pretty res <+> softline <+> pretty "of type" <++> pretty a) tm - pure (res, a, s) + info "encountered first" + (s ** (ty@(Cnstr (Sigma l l' _ a b)), t)) <- infer ctx (assert_smaller tm t) + | (_ ** (ty, _)) => inBounds t.bounds $ typeMismatch (pretty "pair type") (pretty ty) + trace $ pretty {ann} "pair has type" <++> pretty ty + let Yes Refl = decEq s (max l l') + | No _ => fatal "internal sort mismatch" + let ty = a + tm <- doFst (isSet l) (isSet l') (rewrite sym $ maxIsSet l l' in t) + pure (l ** (ty, tm)) (Snd t) => do - inScope "infer" $ trace $ map (\_ => "encountered first projection") tm - (t, ty@(Cnstr (Sigma s s' _ a b)), _) <- infer ctx t - | (_, ty, _) => inScope "wrong type to snd" $ fatal (map (\_ => ty) tm) - inScope "infer" $ trace $ map (\_ => pretty {ann} "pair has type" <++> pretty ty) tm - t1 <- doFst t - res <- doSnd t - b <- subst1 t1 b - inScope "infer" $ trace $ map (\_ => pretty {ann} "final result is" <++> pretty res <+> softline <+> pretty "of type" <++> pretty b) tm - pure (res, b, s') - (Sum a b) => do - inScope "infer" $ trace $ map (\_ => "encountered sum type") tm - (a, s) <- inferType ctx a - inScope "infer" $ trace $ map (\_ => pretty {ann} "left has type" <++> pretty a) tm - (b, s') <- inferType ctx b - inScope "infer" $ trace $ map (\_ => pretty {ann} "right has type" <++> pretty b) tm - pure (Cnstr (Sum s s' a b), cast (ensureSet (lub s s')), suc (ensureSet (lub s s'))) - (Left _) => inScope "cannot infer type" $ fatal tm - (Right _) => inScope "cannot infer type" $ fatal tm - (Case t l out f g) => do - inScope "infer" $ trace $ map (\_ => "encountered case") tm - (t, ty@(Cnstr (Sum s s' a b)), s'') <- infer ctx t - | (_, ty, _) => inScope "wrong type to case" $ fatal (map (\_ => ty) tm) - inScope "infer" $ trace $ map (\_ => pretty {ann} "sum has type" <++> pretty ty) tm - l <- inferSort ctx l - inScope "infer" $ trace $ map (\_ => pretty {ann} "output has sort" <++> pretty l) tm - let ty' = Cnstr (Pi s'' (suc l) "x" ty (cast l)) - inScope "infer" $ trace $ map (\_ => pretty {ann} "checking output has type" <++> pretty ty') tm - out <- check ctx out ty' (s'' ~> suc l) - inScope "infer" $ trace $ map (\_ => "output is well typed") tm - outL <- doApp (weaken 1 out) (Cnstr (Left (Ntrl (Var "x" 0)))) - let fTy = Cnstr (Pi s l "x" a outL) - inScope "infer" $ trace $ map (\_ => pretty {ann} "checking left branch has type" <++> pretty fTy) tm - f <- check ctx f fTy (s ~> l) - inScope "infer" $ trace $ map (\_ => "left branch is well typed") tm - outR <- doApp (weaken 1 out) (Cnstr (Right (Ntrl (Var "x" 0)))) - let gTy = Cnstr (Pi s' l "x" b outR) - inScope "infer" $ trace $ map (\_ => pretty {ann} "checking right branch has type" <++> pretty gTy) tm - g <- check ctx g gTy (s' ~> l) - inScope "infer" $ trace $ map (\_ => "right branch is well typed") tm - res <- doCase t f g - out <- doApp out t - inScope "infer" $ trace $ map (\_ => pretty {ann} "final result is" <++> pretty res <+> softline <+> pretty "of type" <++> pretty out) tm - pure (res, out, l) - (Container a s' s'') => do - inScope "infer" $ trace $ map (\_ => "encountered container") tm - (a, s) <- inferType ctx a - inScope "infer" $ trace $ map (\_ => pretty {ann} "index has type" <++> pretty a) tm - s' <- inferSort ctx s' - inScope "infer" $ trace $ map (\_ => pretty {ann} "tag has sort" <++> pretty s') tm - s'' <- inferSort ctx s'' - inScope "infer" $ trace $ map (\_ => pretty {ann} "position has sort" <++> pretty s'') tm - pure (Cnstr (Container s a s' s''), cast (lub s (suc $ lub s' s'')), suc (lub s (suc $ lub s' s''))) - (MkContainer _ _ _) => inScope "cannot infer type" $ fatal tm - (Tag t) => do - inScope "infer" $ trace $ map (\_ => "encountered tag") tm - (t, ty@(Cnstr (Container s a s' s'')), _) <- infer ctx t - | (_, ty, _) => typeMismatch t.bounds (pretty "container") (pretty ty) - inScope "infer" $ trace $ map (\_ => pretty {ann} "deconstructing a container" <++> pretty ty) tm - tag <- doTag t - let out = tagTy s a s' - pure (tag, Cnstr out, s ~> suc s') - (Position t) => do - inScope "infer" $ trace $ map (\_ => "encountered position") tm - (t, ty@(Cnstr (Container s a s' s'')), _) <- infer ctx t - | (_, ty, _) => typeMismatch t.bounds (pretty "container") (pretty ty) - inScope "infer" $ trace $ map (\_ => pretty {ann} "deconstructing a container" <++> pretty ty) tm - tag <- doTag t - pos <- doPosition t - out <- positionTy s a s' tag s'' - pure (pos, Cnstr out, s ~> s' ~> suc s'') - (Next t) => do - inScope "infer" $ trace $ map (\_ => "encountered next") tm - (t, ty@(Cnstr (Container s a s' s'')), _) <- infer ctx t - | (_, ty, _) => typeMismatch t.bounds (pretty "container") (pretty ty) - inScope "infer" $ trace $ map (\_ => pretty {ann} "deconstructing a container" <++> pretty ty) tm - tag <- doTag t - pos <- doPosition t - next <- doNext t - out <- nextTy s a s' tag s'' pos - pure (next, Cnstr out, s ~> s' ~> s'' ~> s) - (Sem l b t) => do - inScope "infer" $ trace $ map (\_ => "encountered sem") tm - (t, ty@(Cnstr (Container s a s' s'')), _) <- infer ctx t - | (_, ty, _) => typeMismatch t.bounds (pretty "container") (pretty ty) - inScope "infer" $ trace $ map (\_ => pretty {ann} "interpretting a container" <++> pretty ty) tm - l <- inferSort ctx l - inScope "infer" $ trace $ map (\_ => pretty {ann} "output has sort" <++> pretty l) tm - let outTy = Cnstr (Pi s (suc l) "i" a (cast l)) - inScope "infer" $ trace $ map (\_ => pretty {ann} "checking output has type" <++> pretty outTy) tm - b <- check ctx b outTy (s ~> suc l) - inScope "infer" $ trace $ map (\_ => "output is well typed") tm - tag <- doTag t - pos <- doPosition t - next <- doNext t - let i = Ntrl (Var "i" 0) - tag <- doApp (weaken 1 tag) i - pos <- doApp (weaken 1 pos) i - next <- doApp (weaken 1 next) i - let t = Ntrl (Var "t" 0) - pos <- doApp (weaken 1 pos) t - next <- doApp (weaken 1 next) t - let p = Ntrl (Var "p" 0) - next <- doApp (weaken 1 next) p - out <- doApp (weaken 3 b) next - let out = Cnstr $ Lambda "i" $ - Cnstr $ Sigma s' (s'' ~> l) "t" tag $ - Cnstr $ Pi s'' l "p" pos out - let ty = Cnstr $ Pi s (suc (lub s' (s'' ~> l))) "i" a (cast (lub s' (s'' ~> l))) - pure (out, ty, suc (s ~> suc (lub s' (s'' ~> l)))) - Top => pure $ (Cnstr Top, cast Prop, Set 0) - Point => pure $ (Irrel, Cnstr Top, Prop) - Bottom => pure $ (Cnstr Bottom, cast Prop, Set 0) - (Absurd a t) => do - inScope "infer" $ trace $ map (\_ => "encountered absurd") tm - (a, s) <- inferType ctx a - inScope "infer" $ trace $ map (\_ => pretty {ann} "will fudge to type" <++> pretty a) tm - inScope "infer" $ trace $ map (\_ => pretty {ann} "checking for proof of false") tm - _ <- check ctx t (Cnstr Bottom) Prop - inScope "infer" $ trace $ map (\_ => "proof of false is well typed") tm - pure (Ntrl Absurd, a, s) + info "encountered second" + (s ** (ty@(Cnstr (Sigma l l' _ a b)), t)) <- infer ctx (assert_smaller tm t) + | (_ ** (ty, _)) => inBounds t.bounds $ typeMismatch (pretty "pair type") (pretty ty) + trace $ pretty {ann} "pair has type" <++> pretty ty + let Yes Refl = decEq s (max l l') + | No _ => fatal "internal sort mismatch" + let t = rewrite sym $ maxIsSet l l' in t + fst <- doFst (isSet l) (isSet l') t + ty <- subst1 fst b + tm <- doSnd (isSet l) (isSet l') t + pure (l' ** (ty, tm)) + Bool => do + info "encountered bool" + pure (Set 1 ** (cast (Set 0), Cnstr Bool)) + True => do + info "encountered true" + pure (Set 0 ** (Cnstr Bool, Cnstr True)) + False => do + info "encountered false" + pure (Set 0 ** (Cnstr Bool, Cnstr False)) + (If var a t u v) => do + info "encountered if" + trace "checking discriminant is bool" + t <- check ctx (Set 0) (Cnstr Bool) (assert_smaller tm t) + trace "discriminant is well typed" + (s, a) <- inferType (ctx ::< MkFreeVar (Set 0) (Cnstr Bool) var.val) (assert_smaller tm a) + ty <- subst1 (Cnstr True) a + trace $ pretty {ann} "checking true branch has type" <++> pretty ty + u <- check ctx s ty (assert_smaller tm u) + ty <- subst1 (Cnstr False) a + trace $ pretty {ann} "checking false branch has type" <++> pretty ty + v <- check ctx s ty (assert_smaller tm v) + ty <- subst1 t a + tm <- doIf t u v + pure (s ** (ty, tm)) + Top => do + info "encountered top" + pure (Set 0 ** (cast Prop, Cnstr Top)) + Point => do + info "encountered point" + pure (Prop ** (Cnstr Top, Irrel)) + Bottom => do + info "encountered bottom" + pure (Set 0 ** (cast Prop, Cnstr Bottom)) + (Absurd t) => fatal "cannot infer type of absurd" (Equal t u) => do - inScope "infer" $ trace $ map (\_ => "encountered equal") tm - (t, a, s) <- infer ctx t - inScope "infer" $ trace $ map (\_ => pretty {ann} "lhs has type" <++> pretty a) tm - inScope "infer" $ trace $ map (\_ => "checking rhs has same type") tm - u <- check ctx u a s - inScope "infer" $ trace $ map (\_ => "rhs is well typed") tm - res <- doEqual a t u - inScope "infer" $ trace $ map (\_ => pretty {ann} "equality computes to" <++> pretty res) tm - pure (res, cast Prop, Set 0) + info "encountered equal" + (s ** (a, t)) <- infer ctx (assert_smaller tm t) + trace $ pretty {ann} "left side has type" <++> pretty a + u <- check ctx s a (assert_smaller tm u) + trace "right side is well typed" + eq <- doEqual (isSet s) a t u + pure (Set 0 ** (cast Prop, eq)) (Refl t) => do - inScope "infer" $ trace $ map (\_ => "encountered refl") tm - (t, a, s) <- infer ctx t - inScope "infer" $ trace $ map (\_ => pretty {ann} "term has type" <++> pretty a) tm - ty <- doEqual a t t - inScope "infer" $ trace $ map (\_ => pretty {ann} "equality computes to" <++> pretty ty) tm - pure (Irrel, ty, Prop) - (Transp t b u t' e) => do - inScope "infer" $ trace $ map (\_ => "encountered transp") tm - (t, a, s) <- infer ctx t - inScope "infer" $ trace $ map (\_ => pretty {ann} "start index has type" <++> pretty a) tm - inScope "infer" $ trace $ map (\_ => "checking end index has same type") tm - t' <- check ctx t' a s - inScope "infer" $ trace $ map (\_ => "end index is well typed") tm - let ty = Cnstr (Pi s (Set 0) "_" a (cast Prop)) - inScope "infer" $ trace $ map (\_ => pretty {ann} "checkout output is in" <++> pretty ty) tm - b <- check ctx b ty s - inScope "infer" $ trace $ map (\_ => pretty {ann} "output is well typed") tm - inScope "infer" $ trace $ map (\_ => "checking equality type") tm - eq <- doEqual a t t' - _ <- check ctx e eq Prop - inScope "infer" $ trace $ map (\_ => "equality is well typed") tm - inScope "infer" $ trace $ map (\_ => "checking transformed value") tm - inTy <- doApp b t - _ <- check ctx u inTy Prop - inScope "infer" $ trace $ map (\_ => "transformed value is well typed") tm - outTy <- doApp b t' - inScope "infer" $ trace $ map (\_ => pretty {ann} "producing value of type" <++> pretty outTy) tm - pure (Irrel, outTy, Prop) - (Cast b e t) => do - inScope "infer" $ trace $ map (\_ => "encountered cast") tm - (t, a, s) <- infer ctx t - inScope "infer" $ trace $ map (\_ => pretty {ann} "input has type" <++> pretty a) tm - inScope "infer" $ trace $ map (\_ => "checking output has same sort") tm - b <- check ctx b (cast s) (suc s) - inScope "infer" $ trace $ map (\_ => "output is well sorted") tm - inScope "infer" $ trace $ map (\_ => "checking equality type") tm - eq <- doEqual (cast s) a b - _ <- check ctx e eq Prop - inScope "infer" $ trace $ map (\_ => "equality is well typed") tm - inScope "infer" $ trace $ map (\_ => pretty {ann} "producing value of type" <++> pretty b) tm - res <- doCastL a b t - pure (res, b, s) + info "encountered refl" + (s ** (a, t)) <- infer ctx (assert_smaller tm t) + trace "argument is well typed" + eq <- doEqual (isSet s) a t t + pure (Prop ** (eq, Irrel)) + (Transp b t u t' e) => do + info "encountered transp" + (s ** (a, t)) <- infer ctx (assert_smaller tm t) + trace $ pretty {ann} "index type is" <++> pretty a + t' <- check ctx s a (assert_smaller tm t') + trace "new index is well typed" + b <- check ctx (s ~> Set 0) (Cnstr $ Pi s (Set 0) "" a (cast Prop)) (assert_smaller tm b) + trace "transporting in Prop" + oldB <- doApp b t + u <- check ctx Prop oldB (assert_smaller tm u) + trace "old-indexed proposition is well typed" + eq <- doEqual (isSet s) a t t' + trace $ pretty {ann} "checking equality has type" <++> pretty eq + e <- check ctx Prop eq (assert_smaller tm e) + trace "equality is well typed" + newB <- doApp b t' + pure (Prop ** (newB, Irrel)) + (Cast a b e t) => do + info "encountered cast" + (s, a) <- inferType ctx (assert_smaller tm a) + trace $ pretty {ann} "old type is" <++> pretty a + b <- checkType ctx s (assert_smaller tm b) + trace $ pretty {ann} "new type is" <++> pretty b + eq <- doEqual True (cast s) a b + e <- check ctx Prop eq (assert_smaller tm e) + trace "equality is well typed" + t <- check ctx s a (assert_smaller tm t) + trace "value is well typed" + tm <- doCast (isSet s) a b t + pure (s ** (b, tm)) (CastId t) => do - inScope "infer" $ trace $ map (\_ => "encountered cast identity proof") tm - (t, a, s) <- infer ctx t - inScope "infer" $ trace $ map (\_ => pretty {ann} "term has type" <++> pretty a) tm - cast <- doCastL a a t - eq <- doEqual a cast t - inScope "infer" $ trace $ map (\_ => pretty {ann} "producing equality type" <++> pretty eq) tm - pure (Irrel, eq, Prop) - -inferType ctx a = do - (a, Cnstr (Sort s), _) <- infer ctx a - | (_, ty, _) => tag a.bounds (pretty "sort") (pretty ty) - pure (a, s) - -inferSort ctx a = do - (Cnstr (Sort s), _, _) <- infer ctx a - | (t, _, _) => inScope "infer" $ typeMismatch a.bounds (pretty "sort") (pretty t) - pure s + info "encountered castRefl" + (s ** (a, t)) <- infer ctx (assert_smaller tm t) + trace $ pretty {ann} "argument has type" <++> pretty a + lhs <- doCast (isSet s) a a t + ret <- doEqual (isSet s) a lhs t + pure (Prop ** (ret, Irrel)) -- Checking Definitions and Blocks --------------------------------------------- -partial -checkDef : Context n -> Term.Definition n -> Logging ann (NormalForm.Definition n) -checkDef ctx def = do - (ty, sort) <- - inferType {tag = \bounds, lhs, rhs => inScope "invalid declaration" $ mismatch bounds lhs rhs} +checkDef : Context ctx -> Term.Definition (length ctx) -> Logging ann (NormalForm.Definition ctx) +checkDef ctx def = inBounds def.name.bounds $ inScope "check" $ do + debug $ "inferring type of \{def.name.val}" + (sort, ty) <- + inferType {tag = \lhs, rhs => inScope "invalid declaration" $ mismatch lhs rhs} (fromContext ctx) def.ty - inScope "check" $ debug $ map (\name => pretty {ann} "\{name} has type" <++> pretty ty) def.name - tm <- check (fromContext ctx) def.tm ty sort - inScope "check" $ debug $ map (\name => pretty {ann} "\{name} is well typed with value" <++> pretty tm) def.name + debug $ pretty {ann} "\{def.name.val} has type" <++> pretty ty + tm <- check (fromContext ctx) sort ty def.tm + debug $ pretty {ann} "\{def.name.val} is well typed with value" <++> pretty tm pure $ MkDefinition {name = def.name, ty, tm, sort} -partial export -checkBlock : Block n -> Logging ann (Context n) -checkBlock [] = pure [] +checkBlock : Block n -> Logging ann (ctx ** (Context ctx, length ctx = n)) +checkBlock [] = pure ([] ** ([], Refl)) checkBlock (blk :< def) = do - ctx <- checkBlock blk + (_ ** (ctx, Refl)) <- checkBlock blk def <- checkDef ctx def - pure (ctx :< def) + pure (_ ** (ctx :< def, Refl)) diff --git a/src/Obs/Typing/Context.idr b/src/Obs/Typing/Context.idr new file mode 100644 index 0000000..636c9f2 --- /dev/null +++ b/src/Obs/Typing/Context.idr @@ -0,0 +1,108 @@ +module Obs.Typing.Context + +import Data.Fin +import public Data.List +import Data.List.Elem + +import Obs.Logging +import Obs.NormalForm +import Obs.NormalForm.Normalise +import Obs.Substitution +import Obs.Sort + +import Text.Bounded + +-- Definitions ----------------------------------------------------------------- + +infix 5 ::< + +public export +record FreeVar (ctx : List Bool) where + constructor MkFreeVar + sort : Sort + ty : NormalForm True ctx + name : String + +public export +record TyDef (b : Bool) (ctx : List Bool) where + constructor MkDefinition + name : String + sort : Sort + ty : NormalForm True ctx + tm : NormalForm (isSet sort) ctx + correct : isSet sort = b + +public export +data TyContext : Unsorted.Family Bool where + Nil : TyContext [] + (:<) : TyContext ctx -> (def : Definition ctx) -> TyContext (isSet def.sort :: ctx) + (::<) : TyContext ctx -> (var : FreeVar ctx) -> TyContext (isSet var.sort :: ctx) + +-- Properties ------------------------------------------------------------------ + +freeVars : TyContext ctx -> List Bool +freeVars [] = [] +freeVars (ctx :< def) = freeVars ctx +freeVars (ctx ::< var) = isSet var.sort :: freeVars ctx + +Sorted.Rename Bool TyDef where + rename def f = {ty := rename def.ty f, tm := rename def.tm f} def + +-- Construction ---------------------------------------------------------------- + +fromDef : (def : Definition ctx) -> TyDef (isSet def.sort) ctx +fromDef def = MkDefinition + { name = def.name.val + , sort = def.sort + , ty = def.ty + , tm = def.tm + , correct = Refl + } + +fromVar : (var : FreeVar ctx) -> TyDef (isSet var.sort) (isSet var.sort :: ctx) +fromVar var = MkDefinition + { name = var.name + , sort = var.sort + , ty = weaken [isSet var.sort] var.ty + , tm = point (var.name, (var.sort ** Refl)) Here + , correct = Refl + } + +export +fromContext : Context ctx -> TyContext ctx +fromContext [] = [] +fromContext (ctx :< def) = fromContext ctx :< def + +-- Destruction ----------------------------------------------------------------- + +export +getContext : TyContext ctx -> (ctx' ** ctx = ctx') +getContext [] = ([] ** Refl) +getContext (ctx :< def) = + let (ctx' ** prf) = getContext ctx in + (isSet def.sort :: ctx' ** cong (isSet def.sort ::) prf) +getContext (ctx ::< var) = + let (ctx' ** prf) = getContext ctx in + (isSet var.sort :: ctx' ** cong (isSet var.sort ::) prf) + +export +index : TyContext ctx -> Map ctx TyDef ctx +index [] = absurd +index (ctx :< def) = weaken [_] . add TyDef (fromDef def) (index ctx) +index (ctx ::< var) = add TyDef (fromVar var) (weaken [_] . index ctx) + +finToElem : {xs : List a} -> (i : Fin (length xs)) -> Elem (index' xs i) xs +finToElem {xs = (x :: xs)} FZ = Here +finToElem {xs = (x :: xs)} (FS i) = There (finToElem i) + +export +index' : TyContext ctx -> (i : Fin (length ctx)) -> TyDef (index' ctx i) ctx +index' ctx i = let (ctx' ** Refl) = getContext ctx in index ctx (finToElem i) + +export +reduce : (tyCtx : TyContext ctx) -> Map ctx (LogNormalForm ann) (freeVars tyCtx) +reduce [] = absurd +reduce (ctx :< def) = add (LogNormalForm ann) (subst def.tm (reduce ctx)) (reduce ctx) +reduce (ctx ::< var) = add (LogNormalForm ann) + (pure $ point (var.name, (var.sort ** Refl)) Here) + (\i => pure $ weaken [_] $ !(reduce ctx i)) diff --git a/src/Obs/Typing/Conversion.idr b/src/Obs/Typing/Conversion.idr index 37bdf67..d5dc86a 100644 --- a/src/Obs/Typing/Conversion.idr +++ b/src/Obs/Typing/Conversion.idr @@ -1,6 +1,12 @@ module Obs.Typing.Conversion -import Data.Fin +import Control.Monad.Maybe +import Control.Monad.Trans + +import Data.Bool +import Data.So + +import Decidable.Equality import Obs.Logging import Obs.NormalForm @@ -8,71 +14,194 @@ import Obs.NormalForm.Normalise import Obs.Sort import Obs.Substitution --- Conversion ------------------------------------------------------------------ +%default total --- invariant: all definitions fully expanded --- invariant: m |- t, u <- a : s -partial export -convert : (t, u, a : NormalForm n) -> Sort -> Logging ann Bool -partial -convertSet : (t, u : NormalForm n) -> Logging ann Bool -partial -convertSum : (t, u : NormalForm n) -> (s, s' : Sort) -> (a, b : NormalForm n) -> Logging ann Bool +-- Conversion ------------------------------------------------------------------ --- In sort Prop -convert Irrel Irrel a Prop = pure True --- In unknown type in set -convert t u (Ntrl _) (Set k) = pure $ t == u --- In type Set -convert t u (Cnstr (Sort _)) (Set _) = convertSet t u --- In type Pi -convert t u (Cnstr (Pi s s' var a b)) (Set k) = do - t <- doApp (weaken 1 t) (Ntrl $ Var var FZ) - u <- doApp (weaken 1 u) (Ntrl $ Var var FZ) - convert t u b s' --- In type Sigma -convert t u (Cnstr (Sigma s s' var a b)) (Set k) = do - t1 <- doFst t - u1 <- doFst t - True <- convert t1 u1 a s - | False => pure False - b <- subst1 t1 b - t2 <- doSnd t - u2 <- doSnd t - convert t2 u2 b s' --- In type Sum (manually expanding definition of doCase) -convert t u (Cnstr (Sum s s' a b)) (Set _) = convertSum t u s s' a b --- In type Container -convert t u (Cnstr (Container s a s' s'')) (Set l) = do - t <- expandContainer t - u <- expandContainer u - convert (Cnstr t) (Cnstr u) (Cnstr (expandContainerTy s a s' s'')) (Set l) --- Default -convert t u a s = - inScope "invalid conversion" $ fatal $ - fillSep {ann} [prettyPrec App t, prettyPrec App u, prettyPrec App a, prettyPrec App s] +export +convert : (s : Sort) + -> (a : NormalForm True ctx) + -> (t, u : NormalForm (isSet s) ctx) + -> MaybeT (Logging ann) (NormalForm (isSet s) ctx) -convertSet (Cnstr (Sort s')) (Cnstr (Sort s'')) = pure $ s' == s'' -convertSet (Cnstr (Pi s s' _ a b)) (Cnstr (Pi l l' _ a' b')) = - pure $ - s == l && s' == l' && !(convertSet a a') && !(convertSet b b') -convertSet (Cnstr (Sigma s s' _ a b)) (Cnstr (Sigma l l' _ a' b')) = - pure $ - s == l && s' == l' && !(convertSet a a') && !(convertSet b b') -convertSet (Cnstr (Sum s s' a b)) (Cnstr (Sum l l' a' b')) = - pure $ - s == l && s' == l' && !(convertSet a a') && !(convertSet b b') -convertSet (Cnstr (Container s a s' s'')) (Cnstr (Container l a' l' l'')) = - pure $ - s == l && s' == l' && s'' == l'' && !(convertSet a a') -convertSet (Cnstr Top) (Cnstr Top) = pure True -convertSet (Cnstr Bottom) (Cnstr Bottom) = pure True -convertSet (Ntrl t) u = pure (Ntrl t == u) -convertSet t (Ntrl u) = pure (t == Ntrl u) -convertSet t u = pure $ False +untypedConvert : (t, u : NormalForm True ctx) -> MaybeT (Logging ann) (NormalForm True ctx) +-- Diagonals +untypedConvert (Cnstr (Sort s)) (Cnstr (Sort s')) = + if s == s' then pure (Cnstr (Sort s)) else nothing +untypedConvert (Cnstr (Pi s s' var a b)) (Cnstr (Pi l l' _ a' b')) = do + let Yes Refl = decEq s l + | No _ => nothing + lift $ trace "going back to type-directed conversion" + a <- assert_total (convert (suc s) (cast s) a a') + b <- assert_total (convert (suc s') (cast s') b b') + pure (Cnstr $ Pi s s' var a b) +untypedConvert (Cnstr (Lambda s var t)) (Cnstr (Lambda s' _ u)) = do + let Yes Refl = decEq s s' + | No _ => nothing + lift $ trace "converting under lambda" + t <- untypedConvert t u + pure (Cnstr $ Lambda s var t) +untypedConvert (Cnstr (Sigma s s' var a b)) (Cnstr (Sigma l l' _ a' b')) = do + let Yes Refl = decEq s l + | No _ => nothing + lift $ trace "going back to type-directed conversion" + a <- assert_total (convert (suc s) (cast s) a a') + b <- assert_total (convert (suc s') (cast s') b b') + pure (Cnstr $ Sigma s s' var a b) +untypedConvert (Cnstr (Pair s@(Set _) s'@(Set _) prf t u)) (Cnstr (Pair l l' prf' t' u')) = do + let Yes Refl = decEq (s, s') (l, l') + | No _ => nothing + lift $ trace "converting pair pointwise" + t <- untypedConvert t t' + u <- untypedConvert u u' + pure (Cnstr $ Pair l l' Oh t u) +untypedConvert (Cnstr (Pair s@(Set _) Prop prf t u)) (Cnstr (Pair l Prop prf' t' u')) = do + let Yes Refl = decEq s l + | No _ => nothing + lift $ trace "converting pair pointwise" + t <- untypedConvert t t' + pure (Cnstr $ Pair l Prop Oh t Irrel) +untypedConvert (Cnstr (Pair Prop s'@(Set _) prf t u)) (Cnstr (Pair Prop l' prf' t' u')) = do + let Yes Refl = decEq s' l' + | No _ => nothing + lift $ trace "converting pair pointwise" + u <- untypedConvert u u' + pure (Cnstr $ Pair Prop l' Oh Irrel u) +untypedConvert (Cnstr Bool) (Cnstr Bool) = pure (Cnstr Bool) +untypedConvert (Cnstr True) (Cnstr True) = pure (Cnstr True) +untypedConvert (Cnstr False) (Cnstr False) = pure (Cnstr False) +untypedConvert (Cnstr Top) (Cnstr Top) = pure (Cnstr Top) +untypedConvert (Cnstr Bottom) (Cnstr Bottom) = pure (Cnstr Bottom) +untypedConvert t@(Ntrl (Var _ _ _ i)) (Ntrl (Var _ _ _ j)) = + if elemToNat i == elemToNat j then pure t else nothing +untypedConvert lhs@(Ntrl (App b t u)) rhs@(Ntrl (App b' t' u')) = do + let Yes Refl = decEq b b' + | No _ => nothing + lift $ trace "checking parts of a spine" + t <- untypedConvert (assert_smaller lhs (Ntrl t)) (assert_smaller rhs (Ntrl t')) + let True = b' + | False => lift $ doApp t Irrel + u <- untypedConvert u u' + lift $ doApp t u +untypedConvert lhs@(Ntrl (Fst b t)) rhs@(Ntrl (Fst b' t')) = do + lift $ trace "checking full pair for fst" + t <- untypedConvert (assert_smaller lhs (Ntrl t)) (assert_smaller rhs (Ntrl t')) + lift $ doFst True b t +untypedConvert lhs@(Ntrl (Snd b t)) rhs@(Ntrl (Snd b' t')) = do + lift $ trace "checking full pair for snd" + t <- untypedConvert (assert_smaller lhs (Ntrl t)) (assert_smaller rhs (Ntrl t')) + lift $ doSnd b True (rewrite orTrueTrue b in t) +untypedConvert lhs@(Ntrl (If t f g)) rhs@(Ntrl (If t' f' g')) = do + lift $ trace "checking all branches of if" + t <- untypedConvert (assert_smaller lhs (Ntrl t)) (assert_smaller rhs (Ntrl t')) + f <- untypedConvert f f' + g <- untypedConvert g g' + lift $ doIf t f g +untypedConvert (Ntrl Absurd) (Ntrl Absurd) = pure (Ntrl Absurd) +untypedConvert lhs@(Ntrl (Equal a t u)) rhs@(Ntrl (Equal a' t' u')) = do + lift $ trace "checking equal (stuck on type)" + a <- untypedConvert (assert_smaller lhs (Ntrl a)) (assert_smaller rhs (Ntrl a')) + t <- untypedConvert t t' + u <- untypedConvert u u' + lift $ doEqual _ a t u +untypedConvert lhs@(Ntrl (EqualL t u)) rhs@(Ntrl (EqualL t' u')) = do + lift $ trace "checking equal (stuck on left)" + t <- untypedConvert (assert_smaller lhs (Ntrl t)) (assert_smaller rhs (Ntrl t')) + u <- untypedConvert u u' + lift $ doEqualSet t u +untypedConvert lhs@(Ntrl (EqualR t u)) rhs@(Ntrl (EqualR t' u')) = do + lift $ trace "checking equal (stuck on right)" + t <- untypedConvert (assert_smaller lhs (Cnstr t)) (assert_smaller rhs (Cnstr t')) + u <- untypedConvert (assert_smaller lhs (Ntrl u)) (assert_smaller rhs (Ntrl u')) + lift $ doEqualSet t u +untypedConvert lhs@(Ntrl (EqualStuck t u)) rhs@(Ntrl (EqualStuck t' u')) = do + lift $ trace "checking equal (head mismatch)" + t <- untypedConvert (assert_smaller lhs (Cnstr t)) (assert_smaller rhs (Cnstr t')) + u <- untypedConvert (assert_smaller lhs (Cnstr u)) (assert_smaller rhs (Cnstr u')) + lift $ doEqualSet t u +untypedConvert lhs@(Ntrl (CastL a b t)) rhs@(Ntrl (CastL a' b' t')) = do + lift $ trace "checking cast (stuck on left)" + a <- untypedConvert (assert_smaller lhs (Ntrl a)) (assert_smaller rhs (Ntrl a')) + b <- untypedConvert b b' + t <- untypedConvert t t' + lift $ doCast _ a b t +untypedConvert lhs@(Ntrl (CastR a b t)) rhs@(Ntrl (CastR a' b' t')) = do + lift $ trace "checking cast (stuck on right)" + a <- untypedConvert (assert_smaller lhs (Cnstr a)) (assert_smaller rhs (Cnstr a')) + b <- untypedConvert (assert_smaller lhs (Ntrl b)) (assert_smaller rhs (Ntrl b')) + t <- untypedConvert t t' + lift $ doCast _ a b t +untypedConvert lhs@(Ntrl (CastStuck a b t)) rhs@(Ntrl (CastStuck a' b' t')) = do + lift $ trace "checking cast (stuck on left)" + a <- untypedConvert (assert_smaller lhs (Cnstr a)) (assert_smaller rhs (Cnstr a')) + b <- untypedConvert (assert_smaller lhs (Cnstr b)) (assert_smaller rhs (Cnstr b')) + t <- untypedConvert t t' + lift $ doCast _ a b t +-- Pi types +untypedConvert t@(Cnstr (Lambda s var _)) (Ntrl u) = do + u <- lift $ doApp (Ntrl $ weaken [isSet s] u) (point (var, (s ** Refl)) Here) + assert_total (untypedConvert t (Cnstr (Lambda s var u))) +untypedConvert (Ntrl t) u@(Cnstr (Lambda s var _)) = do + t <- lift $ doApp (Ntrl $ weaken [isSet s] t) (point (var, (s ** Refl)) Here) + assert_total (untypedConvert (Cnstr (Lambda s var t)) u) +-- Sigma types +untypedConvert t@(Cnstr (Pair s s' prf _ _)) t'@(Ntrl _) = + let t'' : NormalForm (isSet s || isSet s') ctx + t'' = rewrite trans (sym $ maxIsSet s s') (soToEq prf) in t' + in do + t' <- lift $ doFst (isSet s) (isSet s') t'' + u' <- lift $ doSnd (isSet s) (isSet s') t'' + assert_total (untypedConvert t (Cnstr (Pair s s' prf t' u'))) +untypedConvert t@(Ntrl _) t'@(Cnstr (Pair s s' prf _ _)) = + let t'' : NormalForm (isSet s || isSet s') ctx + t'' = rewrite trans (sym $ maxIsSet s s') (soToEq prf) in t + in do + t <- lift $ doFst (isSet s) (isSet s') t'' + u <- lift $ doSnd (isSet s) (isSet s') t'' + assert_total (untypedConvert (Cnstr (Pair s s' prf t u)) t') +-- Bools +-- no cases because diagonals complete +-- Fallback +untypedConvert _ _ = nothing -convertSum (Cnstr (Left t)) (Cnstr (Left u)) s s' a b = convert t u a s -convertSum (Cnstr (Right t)) (Cnstr (Right u)) s s' a b = convert t u b s' -convertSum (Ntrl t) u s s' a b = pure (Ntrl t == u) -convertSum t (Ntrl u) s s' a b = pure (t == Ntrl u) -convertSum t u s s' a b = pure False +convert Prop a Irrel Irrel = pure Irrel +convert (Set k) (Ntrl a) t u = do + lift $ trace $ pretty {ann} "cannot do type-directed conversion on" <++> pretty a + untypedConvert t u +convert (Set k) (Cnstr (Sort s)) t u = do + lift $ trace $ pretty {ann} "converting in type" <++> pretty s + untypedConvert t u +convert (Set k) (Cnstr (Pi s s'@(Set _) var a b)) t u = do + -- s' must be Set, otherwise ty is in Prop + lift $ trace "converting pi type" + t' <- lift $ doApp (Sorted.weaken [isSet s] t) (point (var, (s ** Refl)) Here) + u' <- lift $ doApp (Sorted.weaken [isSet s] u) (point (var, (s ** Refl)) Here) + t <- convert s' b t' u' + pure (Cnstr $ Lambda s var t) +convert (Set k) ty@(Cnstr (Sigma s@(Set j) s' var a b)) t u = do + lift $ trace "converting sigma type" + t1 <- lift $ doFst True (isSet s') t + u1 <- lift $ doFst True (isSet s') u + t1 <- convert s a t1 u1 + t2 <- lift $ doSnd True (isSet s') t + u2 <- lift $ doSnd True (isSet s') u + b <- lift $ subst1 t1 b + t2 <- convert s' (assert_smaller ty b) t2 u2 + pure (Cnstr $ Pair s s' Oh t1 t2) +convert (Set k) ty@(Cnstr (Sigma Prop s'@(Set _) var a b)) t u = do + lift $ trace "converting sigma type (snd only)" + t2 <- lift $ doSnd False True t + u2 <- lift $ doSnd False True u + b <- lift $ subst1 Irrel b + t2 <- convert s' (assert_smaller ty b) t2 u2 + pure (Cnstr $ Pair Prop s' Oh Irrel t2) +convert (Set 0) (Cnstr Bool) (Cnstr True) (Cnstr True) = do + lift $ trace "converting bool (true)" + pure (Cnstr True) +convert (Set 0) (Cnstr Bool) (Cnstr False) (Cnstr False) = do + lift $ trace "converting bool (false)" + pure (Cnstr False) +convert (Set k) (Cnstr Bool) t@(Ntrl _) u@(Ntrl _) = do + lift $ trace "converting bool (neutral)" + untypedConvert t u +convert (Set k) (Cnstr a) t u = lift $ inScope "bad type constructor" $ fatal a |