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 | 
