0 | module Idris.Parser
   1 |
   2 | import Core.Metadata
   3 | import Idris.Syntax
   4 | import Idris.Syntax.Traversals
   5 | import public Parser.Source
   6 | import TTImp.TTImp
   7 |
   8 | import public Libraries.Text.Parser
   9 | import Data.Either
  10 | import Libraries.Data.IMaybe
  11 | import Data.List.Quantifiers
  12 | import Data.List1
  13 | import Data.Maybe
  14 | import Data.Nat
  15 | import Data.String
  16 | import Libraries.Utils.String
  17 | import Libraries.Data.WithDefault
  18 |
  19 | import Idris.Parser.Let
  20 |
  21 | %default covering
  22 |
  23 | fcBounds : OriginDesc => Rule a -> Rule (WithFC a)
  24 | fcBounds a = (.withFC) <$> bounds a
  25 |
  26 | addFCBounds : OriginDesc => Rule (WithData ls a) -> Rule (WithData (FC' :: ls) a)
  27 | addFCBounds a = (.addFC) <$> bounds a
  28 |
  29 | decorate : {a : Type} -> OriginDesc -> Decoration -> Rule a -> Rule a
  30 | decorate fname decor rule = do
  31 |   res <- bounds rule
  32 |   actD (decorationFromBounded fname decor res)
  33 |   pure res.val
  34 |
  35 | dependentDecorate : {a : Type} -> OriginDesc -> Rule a -> (a -> Decoration) -> Rule a
  36 | dependentDecorate fname rule decor = do
  37 |   res <- bounds rule
  38 |   actD (decorationFromBounded fname (decor res.val) res)
  39 |   pure res.val
  40 |
  41 | decoratedKeyword : OriginDesc -> String -> Rule ()
  42 | decoratedKeyword fname kwd = decorate fname Keyword (keyword kwd)
  43 |
  44 | decorateKeywords : {a : Type} -> OriginDesc -> List (WithBounds a) -> EmptyRule ()
  45 | decorateKeywords fname xs
  46 |   = act $ MkState (cast (map (decorationFromBounded fname Keyword) xs)) []
  47 |
  48 | decoratedPragma : OriginDesc -> String -> Rule ()
  49 | decoratedPragma fname prg = decorate fname Keyword (pragma prg)
  50 |
  51 | decoratedSymbol : OriginDesc -> String -> Rule ()
  52 | decoratedSymbol fname smb = decorate fname Keyword (symbol smb)
  53 |
  54 | decoratedNamespacedSymbol : OriginDesc -> String -> Rule (Maybe Namespace)
  55 | decoratedNamespacedSymbol fname smb =
  56 |   decorate fname Keyword $ namespacedSymbol smb
  57 |
  58 | parens : {b : _} -> OriginDesc -> BRule b a -> Rule a
  59 | parens fname p
  60 |   = pure id <* decoratedSymbol fname "("
  61 |             <*> p
  62 |             <* decoratedSymbol fname ")"
  63 |
  64 | curly : {b : _} -> OriginDesc -> BRule b a -> Rule a
  65 | curly fname p
  66 |   = pure id <* decoratedSymbol fname "{"
  67 |             <*> p
  68 |             <* decoratedSymbol fname "}"
  69 |
  70 | decoratedDataTypeName : OriginDesc -> Rule Name
  71 | decoratedDataTypeName fname = decorate fname Typ dataTypeName
  72 |
  73 | decoratedDataConstructorName : OriginDesc -> Rule Name
  74 | decoratedDataConstructorName fname = decorate fname Data dataConstructorName
  75 |
  76 | decoratedSimpleBinderUName : OriginDesc -> Rule Name
  77 | decoratedSimpleBinderUName fname = decorate fname Bound userName
  78 |
  79 | decoratedSimpleNamedArg : OriginDesc -> Rule String
  80 | decoratedSimpleNamedArg fname
  81 |   = decorate fname Bound unqualifiedName
  82 |   <|> parens fname (decorate fname Bound unqualifiedOperatorName)
  83 |
  84 | -- Forward declare since they're used in the parser
  85 | topDecl : OriginDesc -> IndentInfo -> Rule PDecl
  86 | collectDefs : List PDecl -> List PDecl
  87 |
  88 | -- Some context for the parser
  89 | public export
  90 | record ParseOpts where
  91 |   constructor MkParseOpts
  92 |   eqOK : Bool -- = operator is parseable
  93 |   withOK : Bool -- = with applications are parseable
  94 |
  95 | peq : ParseOpts -> ParseOpts
  96 | peq = { eqOK := True }
  97 |
  98 | pnoeq : ParseOpts -> ParseOpts
  99 | pnoeq = { eqOK := False }
 100 |
 101 | export
 102 | pdef : ParseOpts
 103 | pdef = MkParseOpts {eqOK = True, withOK = True}
 104 |
 105 | pnowith : ParseOpts
 106 | pnowith = MkParseOpts {eqOK = True, withOK = False}
 107 |
 108 | export
 109 | plhs : ParseOpts
 110 | plhs = MkParseOpts {eqOK = False, withOK = False}
 111 |
 112 | %hide Prelude.(>>)
 113 | %hide Prelude.(>>=)
 114 | %hide Core.Core.(>>)
 115 | %hide Core.Core.(>>=)
 116 | %hide Prelude.pure
 117 | %hide Core.Core.pure
 118 | %hide Prelude.(<*>)
 119 | %hide Core.Core.(<*>)
 120 |
 121 | atom : OriginDesc -> Rule PTerm
 122 | atom fname
 123 |     = do x <- bounds $ decorate fname Typ $ exactIdent "Type"
 124 |          pure (PType (boundToFC fname x))
 125 |   <|> do x <- bounds $ name
 126 |          pure (PRef (boundToFC fname x) x.val)
 127 |   <|> do x <- bounds $ dependentDecorate fname constant $ \c =>
 128 |                        if isPrimType c
 129 |                        then Typ
 130 |                        else Data
 131 |          pure (PPrimVal (boundToFC fname x) x.val)
 132 |   <|> do x <- bounds $ decoratedSymbol fname "_"
 133 |          pure (PImplicit (boundToFC fname x))
 134 |   <|> do x <- bounds $ symbol "?"
 135 |          pure (PInfer (boundToFC fname x))
 136 |   <|> do x <- bounds $ holeName
 137 |          actH x.val -- record the hole name in the parser
 138 |          pure (PHole (boundToFC fname x) False x.val)
 139 |   <|> do x <- bounds $ decorate fname Data $ pragma "MkWorld"
 140 |          pure (PPrimVal (boundToFC fname x) WorldVal)
 141 |   <|> do x <- bounds $ decorate fname Typ  $ pragma "World"
 142 |          pure (PPrimVal (boundToFC fname x) $ PrT WorldType)
 143 |   <|> do x <- bounds $ decoratedPragma fname "search"
 144 |          pure (PSearch (boundToFC fname x) 50)
 145 |
 146 | whereBlock : OriginDesc -> Int -> Rule (List PDecl)
 147 | whereBlock fname col
 148 |     = do decoratedKeyword fname "where"
 149 |          ds <- blockAfter col (topDecl fname)
 150 |          pure (collectDefs ds)
 151 |
 152 | -- Expect a keyword, but if we get anything else it's a fatal error
 153 | commitKeyword : OriginDesc -> IndentInfo -> String -> Rule ()
 154 | commitKeyword fname indents req
 155 |     = do mustContinue indents (Just req)
 156 |          decoratedKeyword fname req
 157 |           <|> the (Rule ()) (fatalError ("Expected '" ++ req ++ "'"))
 158 |          mustContinue indents Nothing
 159 |
 160 | commitSymbol : OriginDesc -> String -> Rule ()
 161 | commitSymbol fname req
 162 |     = decoratedSymbol fname req
 163 |        <|> fatalError ("Expected '" ++ req ++ "'")
 164 |
 165 | continueWithDecorated : OriginDesc -> IndentInfo -> String -> Rule ()
 166 | continueWithDecorated fname indents req
 167 |     = mustContinue indents (Just req) *> decoratedSymbol fname req
 168 |
 169 |
 170 | continueWith : IndentInfo -> String -> Rule ()
 171 | continueWith indents req
 172 |     = mustContinue indents (Just req) *> symbol req
 173 |
 174 | iOperator : Rule OpStr
 175 | iOperator
 176 |     = OpSymbols <$> operator
 177 |   <|> Backticked <$> (symbol "`" *> name <* symbol "`")
 178 |
 179 | data ArgType
 180 |     = UnnamedExpArg PTerm
 181 |     | UnnamedAutoArg PTerm
 182 |     | NamedArg Name PTerm
 183 |     | WithArg PTerm
 184 |
 185 | argTerm : ArgType -> PTerm
 186 | argTerm (UnnamedExpArg t) = t
 187 | argTerm (UnnamedAutoArg t) = t
 188 | argTerm (NamedArg _ t) = t
 189 | argTerm (WithArg t) = t
 190 |
 191 | export
 192 | debugString : OriginDesc -> Rule PTerm
 193 | debugString fname = do
 194 |   di <- bounds debugInfo
 195 |   pure $ PPrimVal (boundToFC fname di) $ Str $ case di.val of
 196 |     DebugLoc =>
 197 |       let bnds = di.bounds in
 198 |       joinBy ", "
 199 |       [ "File \{show fname}"
 200 |       , "line \{show (startLine bnds)}"
 201 |       , "characters \{show (startCol bnds)}\{
 202 |            ifThenElse (startLine bnds == endLine bnds)
 203 |             ("-\{show (endCol bnds)}")
 204 |             ""
 205 |         }"
 206 |       ]
 207 |     DebugFile => "\{show fname}"
 208 |     DebugLine => "\{show (startLine di.bounds)}"
 209 |     DebugCol => "\{show (startCol di.bounds)}"
 210 |
 211 | totalityOpt : OriginDesc -> Rule TotalReq
 212 | totalityOpt fname
 213 |     = (decoratedKeyword fname "partial" $> PartialOK)
 214 |   <|> (decoratedKeyword fname "total" $> Total)
 215 |   <|> (decoratedKeyword fname "covering" $> CoveringOnly)
 216 |
 217 | fnOpt : OriginDesc -> Rule PFnOpt
 218 | fnOpt fname
 219 |       = do x <- totalityOpt fname
 220 |            pure $ IFnOpt (Totality x)
 221 |
 222 | mutual
 223 |   appExpr : ParseOpts -> OriginDesc -> IndentInfo -> Rule PTerm
 224 |   appExpr q fname indents
 225 |       = case_ fname indents
 226 |     <|> doBlock fname indents
 227 |     <|> lam fname indents
 228 |     <|> lazy fname indents
 229 |     <|> if_ fname indents
 230 |     <|> with_ fname indents
 231 |     <|> do b <- bounds (MkPair <$> simpleExpr fname indents <*> many (argExpr q fname indents))
 232 |            (f, args) <- pure b.val
 233 |            pure (applyExpImp (start b) (end b) f (concat args))
 234 |     <|> do b <- fcBounds (MkPair <$> fcBounds iOperator <*> expr pdef fname indents)
 235 |            (op, arg) <- pure b.val
 236 |            pure (PPrefixOp b.fc op arg)
 237 |     <|> fail "Expected 'case', 'if', 'do', application or operator expression"
 238 |     where
 239 |       applyExpImp : FilePos -> FilePos -> PTerm ->
 240 |                     List ArgType ->
 241 |                     PTerm
 242 |       applyExpImp start end f [] = f
 243 |       applyExpImp start end f (UnnamedExpArg exp :: args)
 244 |           = applyExpImp start end (PApp (MkFC fname start end) f exp) args
 245 |       applyExpImp start end f (UnnamedAutoArg imp :: args)
 246 |           = applyExpImp start end (PAutoApp (MkFC fname start end) f imp) args
 247 |       applyExpImp start end f (NamedArg n imp :: args)
 248 |           = let fc = MkFC fname start end in
 249 |             applyExpImp start end (PNamedApp fc f n imp) args
 250 |       applyExpImp start end f (WithArg exp :: args)
 251 |           = applyExpImp start end (PWithApp (MkFC fname start end) f exp) args
 252 |
 253 |   argExpr : ParseOpts -> OriginDesc -> IndentInfo -> Rule (List ArgType)
 254 |   argExpr q fname indents
 255 |       = do continue indents
 256 |            arg <- simpleExpr fname indents
 257 |            the (EmptyRule _) $ case arg of
 258 |                 PHole loc _ n => pure [UnnamedExpArg (PHole loc True n)]
 259 |                 t => pure [UnnamedExpArg t]
 260 |     <|> do continue indents
 261 |            braceArgs fname indents
 262 |     <|> if withOK q
 263 |            then do continue indents
 264 |                    decoratedSymbol fname "|"
 265 |                    arg <- expr ({withOK := False} q) fname indents
 266 |                    pure [WithArg arg]
 267 |            else fail "| not allowed here"
 268 |     where
 269 |       underscore : FC -> ArgType
 270 |       underscore fc = NamedArg (UN Underscore) (PImplicit fc)
 271 |
 272 |       braceArgs : OriginDesc -> IndentInfo -> Rule (List ArgType)
 273 |       braceArgs fname indents
 274 |         = do start <- bounds (decoratedSymbol fname "{")
 275 |              mustWork $ do
 276 |                list <- sepBy (decoratedSymbol fname ",")
 277 |                         $ do x <- bounds (UN . Basic <$> decoratedSimpleNamedArg fname)
 278 |                              let fc = boundToFC fname x
 279 |                              option (NamedArg x.val $ PRef fc x.val)
 280 |                               $ do tm <- decoratedSymbol fname "=" *> typeExpr pdef fname indents
 281 |                                    pure (NamedArg x.val tm)
 282 |                matchAny <- option [] (if isCons list then
 283 |                                          do decoratedSymbol fname ","
 284 |                                             x <- bounds (decoratedSymbol fname "_")
 285 |                                             pure [underscore (boundToFC fname x)]
 286 |                                       else fail "non-empty list required")
 287 |                end <- bounds (decoratedSymbol fname "}")
 288 |                matchAny <- do let fc = boundToFC fname (mergeBounds start end)
 289 |                               pure $ if isNil list
 290 |                                 then [underscore fc]
 291 |                                 else matchAny
 292 |                pure $ matchAny ++ list
 293 |
 294 |         <|> do decoratedSymbol fname "@{"
 295 |                commit
 296 |                tm <- typeExpr pdef fname indents
 297 |                decoratedSymbol fname "}"
 298 |                pure [UnnamedAutoArg tm]
 299 |
 300 |   with_ : OriginDesc -> IndentInfo -> Rule PTerm
 301 |   with_ fname indents
 302 |       = do b <- bounds (do decoratedKeyword fname "with"
 303 |                            commit
 304 |                            ns <- singleName <|> nameList
 305 |                            end <- location
 306 |                            rhs <- expr pdef fname indents
 307 |                            pure (ns, rhs))
 308 |            (ns, rhs) <- pure b.val
 309 |            pure (PWithUnambigNames (boundToFC fname b) ns rhs)
 310 |     where
 311 |       singleName : Rule (List (FC, Name))
 312 |       singleName = do
 313 |         n <- bounds name
 314 |         pure [(boundToFC fname n, n.val)]
 315 |
 316 |       nameList : Rule (List (FC, Name))
 317 |       nameList = do
 318 |         decoratedSymbol fname "["
 319 |         commit
 320 |         ns <- sepBy1 (decoratedSymbol fname ",") (bounds name)
 321 |         decoratedSymbol fname "]"
 322 |         pure (map (\ n => (boundToFC fname n, n.val)) $ forget ns)
 323 |
 324 |   -- The different kinds of operator bindings `x : ty` for typebind
 325 |   -- x <- e and x : ty <- e for autobind
 326 |   opBinderTypes : OriginDesc -> IndentInfo -> WithBounds PTerm -> Rule (OperatorLHSInfo PTerm)
 327 |   opBinderTypes fname indents boundName =
 328 |            do decoratedSymbol fname ":"
 329 |               ty <- typeExpr pdef fname indents
 330 |               decoratedSymbol fname "<-"
 331 |               exp <- expr pdef fname indents
 332 |               pure (BindExplicitType boundName.val ty exp)
 333 |        <|> do decoratedSymbol fname "<-"
 334 |               exp <- expr pdef fname indents
 335 |               pure (BindExpr boundName.val exp)
 336 |        <|> do decoratedSymbol fname ":"
 337 |               ty <- typeExpr pdef fname indents
 338 |               pure (BindType boundName.val ty)
 339 |
 340 |   opBinder : OriginDesc -> IndentInfo -> Rule (OperatorLHSInfo PTerm)
 341 |   opBinder fname indents
 342 |       = do boundName <- bounds (expr plhs fname indents)
 343 |            opBinderTypes fname indents boundName
 344 |
 345 |   autobindOp : ParseOpts -> OriginDesc -> IndentInfo -> Rule PTerm
 346 |   autobindOp q fname indents
 347 |       = do b <- fcBounds $ do
 348 |              binder <- fcBounds $ parens fname (opBinder fname indents)
 349 |              continue indents
 350 |              op <- fcBounds iOperator
 351 |              commit
 352 |              e <- expr q fname indents
 353 |              pure (binder, op, e)
 354 |            pure (POp b.fc (fst b.val) (fst (snd b.val)) (snd (snd b.val)))
 355 |
 356 |   opExprBase : ParseOpts -> OriginDesc -> IndentInfo -> Rule PTerm
 357 |   opExprBase q fname indents
 358 |       = do l <- bounds (appExpr q fname indents)
 359 |            (if eqOK q
 360 |                then do r <- bounds (continue indents
 361 |                                 *> decoratedSymbol fname "="
 362 |                                 *> opExprBase q fname indents)
 363 |                        pure $
 364 |                          let fc = boundToFC fname (mergeBounds l r)
 365 |                              opFC = virtualiseFC fc -- already been highlighted: we don't care
 366 |                          in POp fc (map NoBinder l.withFC)
 367 |                                    (MkFCVal opFC (OpSymbols $ UN $ Basic "="))
 368 |                                    r.val
 369 |                else fail "= not allowed")
 370 |              <|>
 371 |              (do b <- bounds $ do
 372 |                         continue indents
 373 |                         op <- fcBounds iOperator
 374 |                         e <- case op.val of
 375 |                                OpSymbols (UN (Basic "$")) => typeExpr q fname indents
 376 |                                _ => expr q fname indents
 377 |                         pure (op, e)
 378 |                  (op, r) <- pure b.val
 379 |                  let fc = boundToFC fname (mergeBounds l b)
 380 |                  pure (POp fc (map NoBinder l.withFC) op r))
 381 |                <|> pure l.val
 382 |
 383 |   opExpr : ParseOpts -> OriginDesc -> IndentInfo -> Rule PTerm
 384 |   opExpr q fname indents = autobindOp q fname indents
 385 |                        <|> opExprBase q fname indents
 386 |
 387 |   dpairType : OriginDesc -> WithBounds t -> IndentInfo -> Rule PTerm
 388 |   dpairType fname start indents
 389 |       = do loc <- bounds (do x <- decoratedSimpleBinderUName fname
 390 |                              decoratedSymbol fname ":"
 391 |                              ty <- typeExpr pdef fname indents
 392 |                              pure (x, ty))
 393 |            (x, ty) <- pure loc.val
 394 |            op <- bounds (symbol "**")
 395 |            rest <- bounds (nestedDpair fname loc indents <|> typeExpr pdef fname indents)
 396 |            pure (PDPair (boundToFC fname (mergeBounds start rest))
 397 |                         (boundToFC fname op)
 398 |                         (PRef (boundToFC fname loc) x)
 399 |                         ty
 400 |                         rest.val)
 401 |
 402 |   nestedDpair : OriginDesc -> WithBounds t -> IndentInfo -> Rule PTerm
 403 |   nestedDpair fname start indents
 404 |       = dpairType fname start indents
 405 |     <|> do l <- expr pdef fname indents
 406 |            loc <- bounds (symbol "**")
 407 |            rest <- bounds (nestedDpair fname loc indents <|> expr pdef fname indents)
 408 |            pure (PDPair (boundToFC fname (mergeBounds start rest))
 409 |                         (boundToFC fname loc)
 410 |                         l
 411 |                         (PImplicit (boundToFC fname (mergeBounds start rest)))
 412 |                         rest.val)
 413 |
 414 |   bracketedExpr : OriginDesc -> WithBounds t -> IndentInfo -> Rule PTerm
 415 |   bracketedExpr fname s indents
 416 |       -- left section. This may also be a prefix operator, but we'll sort
 417 |       -- that out when desugaring: if the operator is infix, treat it as a
 418 |       -- section otherwise treat it as prefix
 419 |       = do b <- bounds (do op <- fcBounds iOperator
 420 |                            e <- expr pdef fname indents
 421 |                            continueWithDecorated fname indents ")"
 422 |                            pure (op, e))
 423 |            (op, e) <- pure b.val
 424 |            actD (toNonEmptyFC $ boundToFC fname s, Keyword, Nothing)
 425 |            let fc = boundToFC fname (mergeBounds s b)
 426 |            pure (PSectionL fc op e)
 427 |     <|> do  -- (.y.z)  -- section of projection (chain)
 428 |            b <- bounds $ forget <$> some (bounds postfixProj)
 429 |            decoratedSymbol fname ")"
 430 |            actD (toNonEmptyFC $ boundToFC fname s, Keyword, Nothing)
 431 |            let projs = map (\ proj => (boundToFC fname proj, proj.val)) b.val
 432 |            pure $ PPostfixAppPartial (boundToFC fname b) projs
 433 |       -- unit type/value
 434 |     <|> do b <- bounds (continueWith indents ")")
 435 |            pure (PUnit (boundToFC fname (mergeBounds s b)))
 436 |       -- dependent pairs with type annotation (so, the type form)
 437 |     <|> do dpairType fname s indents <* (decorate fname Typ $ symbol ")")
 438 |                                      <* actD (toNonEmptyFC $ boundToFC fname s, Typ, Nothing)
 439 |     <|> do e <- bounds (typeExpr pdef fname indents)
 440 |            -- dependent pairs with no type annotation
 441 |            (do loc <- bounds (symbol "**")
 442 |                rest <- bounds ((nestedDpair fname loc indents <|> expr pdef fname indents) <* symbol ")")
 443 |                pure (PDPair (boundToFC fname (mergeBounds s rest))
 444 |                             (boundToFC fname loc)
 445 |                             e.val
 446 |                             (PImplicit (boundToFC fname (mergeBounds s rest)))
 447 |                             rest.val)) <|>
 448 |              -- right sections
 449 |              ((do op <- bounds (fcBounds iOperator <* decoratedSymbol fname ")")
 450 |                   actD (toNonEmptyFC $ boundToFC fname s, Keyword, Nothing)
 451 |                   let fc = boundToFC fname (mergeBounds s op)
 452 |                   pure (PSectionR fc e.val op.val)
 453 |                <|>
 454 |               -- all the other bracketed expressions
 455 |               tuple fname s indents e.val))
 456 |     <|> do here <- location
 457 |            let fc = MkFC fname here here
 458 |            let var = PRef fc (MN "__leftTupleSection" 0)
 459 |            ts <- bounds (nonEmptyTuple fname s indents var)
 460 |            pure (PLam fc top Explicit var (PInfer fc) ts.val)
 461 |
 462 |   getInitRange : List (WithBounds PTerm) -> EmptyRule (PTerm, Maybe PTerm)
 463 |   getInitRange [x] = pure (x.val, Nothing)
 464 |   getInitRange [x,y] = pure (x.val, Just y.val)
 465 |   getInitRange _ = fatalError "Invalid list range syntax"
 466 |
 467 |   listRange : OriginDesc -> WithBounds t -> IndentInfo -> List (WithBounds PTerm) -> Rule PTerm
 468 |   listRange fname s indents xs
 469 |       = do b <- bounds (decoratedSymbol fname "]")
 470 |            let fc = boundToFC fname (mergeBounds s b)
 471 |            rstate <- getInitRange xs
 472 |            decorateKeywords fname xs
 473 |            pure (PRangeStream fc (fst rstate) (snd rstate))
 474 |     <|> do y <- bounds (expr pdef fname indents <* decoratedSymbol fname "]")
 475 |            let fc = boundToFC fname (mergeBounds s y)
 476 |            rstate <- getInitRange xs
 477 |            decorateKeywords fname xs
 478 |            pure (PRange fc (fst rstate) (snd rstate) y.val)
 479 |
 480 |   listExpr : OriginDesc -> WithBounds () -> IndentInfo -> Rule PTerm
 481 |   listExpr fname s indents
 482 |       = do b <- bounds (do ret <- expr pnowith fname indents
 483 |                            decoratedSymbol fname "|"
 484 |                            conds <- sepBy1 (decoratedSymbol fname ",") (doAct fname indents)
 485 |                            decoratedSymbol fname "]"
 486 |                            pure (ret, conds))
 487 |            (ret, conds) <- pure b.val
 488 |            pure (PComprehension (boundToFC fname (mergeBounds s b)) ret (concat conds))
 489 |     <|> do xs <- option [] $ do
 490 |                      hd <- expr pdef fname indents
 491 |                      tl <- many $ do b <- bounds (symbol ",")
 492 |                                      x <- mustWork $ expr pdef fname indents
 493 |                                      pure (x <$ b)
 494 |                      pure ((hd <$ s) :: tl)
 495 |            (do decoratedSymbol fname ".."
 496 |                listRange fname s indents xs)
 497 |              <|> (do b <- bounds (symbol "]")
 498 |                      pure $
 499 |                        let fc = boundToFC fname (mergeBounds s b)
 500 |                            nilFC = if null xs then fc else boundToFC fname b
 501 |                        in PList fc nilFC (cast (map (\ t => (boundToFC fname t, t.val)) xs)))
 502 |
 503 |   snocListExpr : OriginDesc -> WithBounds () -> IndentInfo -> Rule PTerm
 504 |   snocListExpr fname s indents
 505 |       = {- TODO: comprehension -}
 506 |         do mHeadTail <- optional $ do
 507 |              hd <- many $ do x <- expr pdef fname indents
 508 |                              b <- bounds (symbol ",")
 509 |                              pure (x <$ b)
 510 |              tl <- expr pdef fname indents
 511 |              pure (hd, tl)
 512 |            {- TODO: reverse ranges -}
 513 |            b <- bounds (symbol "]")
 514 |            pure $
 515 |              let xs : SnocList (WithBounds PTerm)
 516 |                     = case mHeadTail of
 517 |                         Nothing      => [<]
 518 |                         Just (hd,tl) => ([<] <>< hd) :< (tl <$ b)
 519 |                  fc = boundToFC fname (mergeBounds s b)
 520 |                  nilFC = ifThenElse (null xs) fc (boundToFC fname s)
 521 |              in PSnocList fc nilFC (map (\ t => (boundToFC fname t, t.val)) xs) --)
 522 |
 523 |   nonEmptyTuple : OriginDesc -> WithBounds t -> IndentInfo -> PTerm -> Rule PTerm
 524 |   nonEmptyTuple fname s indents e
 525 |       = do vals <- some $ do b <- bounds (symbol ",")
 526 |                              exp <- optional (typeExpr pdef fname indents)
 527 |                              pure (boundToFC fname b, exp)
 528 |            end <- continueWithDecorated fname indents ")"
 529 |            actD (toNonEmptyFC (boundToFC fname s), Keyword, Nothing)
 530 |            pure $ let (start ::: rest) = vals in
 531 |                   buildOutput (fst start) (mergePairs 0 start rest)
 532 |     where
 533 |
 534 |       lams : List (FC, PTerm) -> PTerm -> PTerm
 535 |       lams [] e = e
 536 |       lams ((fc, var) :: vars) e
 537 |         = let vfc = virtualiseFC fc in
 538 |           PLam vfc top Explicit var (PInfer vfc) $ lams vars e
 539 |
 540 |       buildOutput : FC -> (List (FC, PTerm), PTerm) -> PTerm
 541 |       buildOutput fc (vars, scope) = lams vars $ PPair fc e scope
 542 |
 543 |       optionalPair : Int ->
 544 |                      (FC, Maybe PTerm) -> (Int, (List (FC, PTerm), PTerm))
 545 |       optionalPair i (fc, Just e)  = (i, ([], e))
 546 |       optionalPair i (fc, Nothing) =
 547 |         let var = PRef fc (MN "__infixTupleSection" i) in
 548 |         (i+1, ([(fc, var)], var))
 549 |
 550 |       mergePairs : Int -> (FC, Maybe PTerm) ->
 551 |                    List (FC, Maybe PTerm) -> (List (FC, PTerm), PTerm)
 552 |       mergePairs i hd [] = snd (optionalPair i hd)
 553 |       mergePairs i hd (exp :: rest)
 554 |           = let (j, (var, t)) = optionalPair i hd in
 555 |             let (vars, ts)    = mergePairs j exp rest in
 556 |             (var ++ vars, PPair (fst exp) t ts)
 557 |
 558 |   -- A pair, dependent pair, or just a single expression
 559 |   tuple : OriginDesc -> WithBounds t -> IndentInfo -> PTerm -> Rule PTerm
 560 |   tuple fname s indents e
 561 |      =   nonEmptyTuple fname s indents e
 562 |      <|> do end <- bounds (continueWithDecorated fname indents ")")
 563 |             actD (toNonEmptyFC $ boundToFC fname s, Keyword, Nothing)
 564 |             pure (PBracketed (boundToFC fname (mergeBounds s end)) e)
 565 |
 566 |   simpleExpr : OriginDesc -> IndentInfo -> Rule PTerm
 567 |   simpleExpr fname indents
 568 |     = do  -- x.y.z
 569 |           b <- bounds (do root <- simplerExpr fname indents
 570 |                           projs <- many (bounds postfixProj)
 571 |                           pure (root, projs))
 572 |           (root, projs) <- pure b.val
 573 |           let projs = map (\ proj => (boundToFC fname proj, proj.val)) projs
 574 |           pure $ case projs of
 575 |             [] => root
 576 |             _  => PPostfixApp (boundToFC fname b) root projs
 577 |     <|> debugString fname
 578 |     <|> do b <- bounds (forget <$> some (bounds postfixProj))
 579 |            pure $ let projs = map (\ proj => (boundToFC fname proj, proj.val)) b.val in
 580 |                   PPostfixAppPartial (boundToFC fname b) projs
 581 |
 582 |   simplerExpr : OriginDesc -> IndentInfo -> Rule PTerm
 583 |   simplerExpr fname indents
 584 |       = do b <- bounds (do x <- bounds (decoratedSimpleBinderUName fname)
 585 |                            decoratedSymbol fname "@"
 586 |                            commit
 587 |                            expr <- simpleExpr fname indents
 588 |                            pure (x, expr))
 589 |            (x, expr) <- pure b.val
 590 |            pure (PAs (boundToFC fname b) (boundToFC fname x) x.val expr)
 591 |     <|> do b <- bounds $ do
 592 |                   mns <- decoratedNamespacedSymbol fname "[|"
 593 |                   t   <- expr pdef fname indents
 594 |                   decoratedSymbol fname "|]"
 595 |                   pure (t, mns)
 596 |            pure (PIdiom (boundToFC fname b) (snd b.val) (fst b.val))
 597 |     <|> atom fname
 598 |     <|> record_ fname indents
 599 |     <|> singlelineStr pdef fname indents
 600 |     <|> multilineStr pdef fname indents
 601 |     <|> do b <- bounds $ do
 602 |                   decoratedSymbol fname ".("
 603 |                   commit
 604 |                   t <- typeExpr pdef fname indents
 605 |                   decoratedSymbol fname ")"
 606 |                   pure t
 607 |            pure (PDotted (boundToFC fname b) b.val)
 608 |     <|> do b <- bounds $ do
 609 |                   decoratedSymbol fname "`("
 610 |                   t <- typeExpr pdef fname indents
 611 |                   decoratedSymbol fname ")"
 612 |                   pure t
 613 |            pure (PQuote (boundToFC fname b) b.val)
 614 |     <|> do b <- bounds $ do
 615 |                   decoratedSymbol fname "`{"
 616 |                   t <- name
 617 |                   decoratedSymbol fname "}"
 618 |                   pure t
 619 |            pure (PQuoteName (boundToFC fname b) b.val)
 620 |     <|> do b <- bounds $ do
 621 |                   decoratedSymbol fname "`["
 622 |                   ts <- nonEmptyBlock (topDecl fname)
 623 |                   decoratedSymbol fname "]"
 624 |                   pure ts
 625 |            pure (PQuoteDecl (boundToFC fname b) (collectDefs (forget b.val)))
 626 |     <|> do b <- bounds (decoratedSymbol fname "~" *> simplerExpr fname indents)
 627 |            pure (PUnquote (boundToFC fname b) b.val)
 628 |     <|> do start <- bounds (symbol "(")
 629 |            bracketedExpr fname start indents
 630 |     <|> do start <- bounds (symbol "[<")
 631 |            snocListExpr fname start indents
 632 |     <|> do start <- bounds (symbol "[>" <|> symbol "[")
 633 |            listExpr fname start indents
 634 |     <|> do b <- bounds (decoratedSymbol fname "!" *> simpleExpr fname indents)
 635 |            pure (PBang (virtualiseFC $ boundToFC fname b) b.val)
 636 |     <|> do b <- bounds $ do decoratedPragma fname "logging"
 637 |                             topic <- optional (split (('.') ==) <$> simpleStr)
 638 |                             lvl   <- intLit
 639 |                             e     <- expr pdef fname indents
 640 |                             pure (MkPair (mkLogLevel' topic (integerToNat lvl)) e)
 641 |            (lvl, e) <- pure b.val
 642 |            pure (PUnifyLog (boundToFC fname b) lvl e)
 643 |     <|> withWarning "DEPRECATED: trailing lambda. Use a $ or parens"
 644 |         (lam fname indents)
 645 |
 646 |   multiplicity : OriginDesc -> EmptyRule RigCount
 647 |   multiplicity fname
 648 |       = case !(optional $ decorate fname Keyword intLit) of
 649 |           (Just 0) => pure erased
 650 |           (Just 1) => pure linear
 651 |           Nothing => pure top
 652 |           _ => fail "Invalid multiplicity (must be 0 or 1)"
 653 |
 654 |   bindList : OriginDesc -> IndentInfo ->
 655 |              Rule (List (RigCount, WithBounds PTerm, PTerm, PiInfo PTerm))
 656 |   bindList fname indents
 657 |       = forget <$> sepBy1 (decoratedSymbol fname ",") (explicitBind <|> implicitBind)
 658 |     where
 659 |       explicitBind : Rule (RigCount, WithBounds PTerm, PTerm, PiInfo PTerm)
 660 |       explicitBind = do
 661 |         rig <- multiplicity fname
 662 |         pat <- bounds (simpleExpr fname indents)
 663 |         ty <- option
 664 |            (PInfer (boundToFC fname pat))
 665 |            (decoratedSymbol fname ":" *> opExpr pdef fname indents)
 666 |         pure (rig, pat, ty, Explicit)
 667 |
 668 |       implicitBind : Rule (RigCount, WithBounds PTerm, PTerm, PiInfo PTerm)
 669 |       implicitBind = curly fname $ do
 670 |         rig <- multiplicity fname
 671 |         pat <- bounds (simpleExpr fname indents)
 672 |         ty <- option
 673 |            (PInfer (boundToFC fname pat))
 674 |            (decoratedSymbol fname ":" *> opExpr pdef fname indents)
 675 |         pure (rig, pat, ty, Implicit)
 676 |
 677 |   ||| A list of names bound to the same type
 678 |   ||| BNF:
 679 |   ||| pibindListName := qty name (, name)* ':' typeExpr
 680 |   pibindListName : OriginDesc -> IndentInfo ->
 681 |                    Rule BasicMultiBinder
 682 |   pibindListName fname indents
 683 |        = do rig <- multiplicity fname
 684 |             ns <- sepBy1 (decoratedSymbol fname ",")
 685 |                          (fcBounds binderName)
 686 |             decoratedSymbol fname ":"
 687 |             ty <- typeExpr pdef fname indents
 688 |             atEnd indents
 689 |             pure (MkBasicMultiBinder rig ns ty)
 690 |     where
 691 |       -- _ gets treated specially here, it means "I don't care about the name"
 692 |       binderName : Rule Name
 693 |       binderName = decoratedSimpleBinderUName fname
 694 |                <|> decorate fname Bound (UN <$> symbol "_" $> Underscore)
 695 |
 696 |   ||| The arrow used after an explicit binder
 697 |   ||| BNF:
 698 |   ||| bindSymbol := '->' | '=>'
 699 |   bindSymbol : OriginDesc -> Rule (PiInfo PTerm)
 700 |   bindSymbol fname
 701 |       = (decoratedSymbol fname "->" $> Explicit)
 702 |     <|> (decoratedSymbol fname "=>" $> AutoImplicit)
 703 |
 704 |   ||| An explicit pi-type
 705 |   ||| BNF:
 706 |   ||| explicitPi := '(' pibindListName ')' bindSymbol typeExpr
 707 |   explicitPi : OriginDesc -> IndentInfo -> Rule PTerm
 708 |   explicitPi fname indents
 709 |       = NewPi <$> fcBounds (do
 710 |            b <- bounds $ parens fname $ pibindListName fname indents
 711 |            exp <- mustWorkBecause b.bounds "Cannot return a named argument"
 712 |                     $ bindSymbol fname
 713 |            scope <- mustWork $ typeExpr pdef fname indents
 714 |            pure (MkPBinderScope (MkPBinder exp b.val) scope))
 715 |
 716 |   ||| An auto-implicit pi-type
 717 |   ||| BNF:
 718 |   ||| autoImplicitPi := '{' 'auto' pibindListName '}' '->' typeExpr
 719 |   autoImplicitPi : OriginDesc -> IndentInfo -> Rule PTerm
 720 |   autoImplicitPi fname indents
 721 |       = NewPi <$> fcBounds (do
 722 |            b <- bounds $ curly fname $ do
 723 |                   decoratedKeyword fname "auto"
 724 |                   commit
 725 |                   binders <- pibindListName fname indents
 726 |                   pure binders
 727 |            mustWorkBecause b.bounds "Cannot return an auto implicit argument"
 728 |              $ decoratedSymbol fname "->"
 729 |            scope <- mustWork $ typeExpr pdef fname indents
 730 |            pure (MkPBinderScope (MkPBinder AutoImplicit b.val) scope)
 731 |            )
 732 |
 733 |   ||| An default implicit pi-type
 734 |   ||| BNF:
 735 |   ||| defaultImplicitPi := '{' 'default' simpleExpr pibindListName '}' '->' typeExpr
 736 |   defaultImplicitPi : OriginDesc -> IndentInfo -> Rule PTerm
 737 |   defaultImplicitPi fname indents
 738 |       = NewPi <$> fcBounds (do
 739 |            b <- bounds $ curly fname $ do
 740 |                   decoratedKeyword fname "default"
 741 |                   commit
 742 |                   t <- simpleExpr fname indents
 743 |                   binders <- pibindListName fname indents
 744 |                   pure (MkPBinder (DefImplicit t) binders)
 745 |            mustWorkBecause b.bounds "Cannot return a default implicit argument"
 746 |              $ decoratedSymbol fname "->"
 747 |            scope <- mustWork $ typeExpr pdef fname indents
 748 |            pure (MkPBinderScope b.val scope)
 749 |            )
 750 |
 751 |   ||| Forall definition that automatically binds the names
 752 |   ||| BNF:
 753 |   ||| forall_ := 'forall' name (, name)* '.' typeExpr
 754 |   forall_ : OriginDesc -> IndentInfo -> Rule PTerm
 755 |   forall_ fname indents
 756 |       = Forall <$> fcBounds (do
 757 |            b <- bounds $ do
 758 |                   decoratedKeyword fname "forall"
 759 |                   commit
 760 |                   ns <- sepBy1 (decoratedSymbol fname ",")
 761 |                                (fcBounds (decoratedSimpleBinderUName fname))
 762 |                   pure ns
 763 |            b' <- bounds peek
 764 |            mustWorkBecause b'.bounds "Expected ',' or '.'"
 765 |              $ decoratedSymbol fname "."
 766 |            scope <- mustWork $ typeExpr pdef fname indents
 767 |            pure (b.val, scope))
 768 |
 769 |   ||| implicit pi-type
 770 |   ||| BNF:
 771 |   ||| implicitPi := '{' pibindListName '}' '->' typeExpr
 772 |   implicitPi : OriginDesc -> IndentInfo -> Rule PTerm
 773 |   implicitPi fname indents
 774 |       = NewPi <$> fcBounds (do
 775 |            b <- bounds $ curly fname $ pibindListName fname indents
 776 |            mustWorkBecause b.bounds "Cannot return an implicit argument"
 777 |             $ decoratedSymbol fname "->"
 778 |            scope <- mustWork $ typeExpr pdef fname indents
 779 |            pure (MkPBinderScope (MkPBinder Implicit b.val) scope)
 780 |            )
 781 |
 782 |   lam : OriginDesc -> IndentInfo -> Rule PTerm
 783 |   lam fname indents
 784 |       = do decoratedSymbol fname "\\"
 785 |            commit
 786 |            switch <- optional (bounds $ decoratedKeyword fname "case")
 787 |            case switch of
 788 |              Nothing => continueLamImpossible <|> continueLam
 789 |              Just r  => continueLamCase r
 790 |
 791 |      where
 792 |        continueLamImpossible : Rule PTerm
 793 |        continueLamImpossible = do
 794 |            lhs <- bounds (opExpr plhs fname indents)
 795 |            end <- bounds (decoratedKeyword fname "impossible")
 796 |            pure (
 797 |              let fc = boundToFC fname (mergeBounds lhs end)
 798 |                  alt = (MkImpossible fc lhs.val)
 799 |                  fcCase = boundToFC fname lhs
 800 |                  n = MN "lcase" 0 in
 801 |              (PLam fcCase top Explicit (PRef fcCase n) (PInfer fcCase) $
 802 |                  PCase (virtualiseFC fc) [] (PRef fcCase n) [alt]))
 803 |
 804 |        bindAll : List (RigCount, WithBounds PTerm, PTerm, PiInfo PTerm) -> PTerm -> PTerm
 805 |        bindAll [] scope = scope
 806 |        bindAll ((rig, pat, ty, icit) :: rest) scope
 807 |            = PLam (boundToFC fname pat) rig icit pat.val ty
 808 |                   (bindAll rest scope)
 809 |
 810 |        continueLam : Rule PTerm
 811 |        continueLam = do
 812 |            binders <- bindList fname indents
 813 |            commitSymbol fname "=>"
 814 |            mustContinue indents Nothing
 815 |            scope <- typeExpr pdef fname indents
 816 |            pure (bindAll binders scope)
 817 |
 818 |        continueLamCase : WithBounds () -> Rule PTerm
 819 |        continueLamCase endCase = do
 820 |            b <- bounds (forget <$> nonEmptyBlock (caseAlt fname))
 821 |            pure
 822 |             (let fc = boundToFC fname b
 823 |                  fcCase = virtualiseFC $ boundToFC fname endCase
 824 |                  n = MN "lcase" 0 in
 825 |               PLam fcCase top Explicit (PRef fcCase n) (PInfer fcCase) $
 826 |                 PCase (virtualiseFC fc) [] (PRef fcCase n) b.val)
 827 |
 828 |   letBlock : OriginDesc -> IndentInfo -> Rule (WithBounds (Either LetBinder LetDecl))
 829 |   letBlock fname indents = bounds (letBinder <||> letDecl) where
 830 |
 831 |     letBinder : Rule LetBinder
 832 |     letBinder = do s <- bounds (MkPair <$> multiplicity fname <*> expr plhs fname indents)
 833 |                    (rig, pat) <- pure s.val
 834 |                    ty <- option (PImplicit (virtualiseFC $ boundToFC fname s))
 835 |                                 (decoratedSymbol fname ":" *> typeExpr (pnoeq pdef) fname indents)
 836 |                    (decoratedSymbol fname "=" <|> decoratedSymbol fname ":=")
 837 |                    val <- typeExpr pnowith fname indents
 838 |                    alts <- block (patAlt fname)
 839 |                    pure (MkLetBinder rig pat ty val alts)
 840 |
 841 |     letDecl : Rule LetDecl
 842 |     letDecl = collectDefs . forget <$> nonEmptyBlock (try . topDecl fname)
 843 |
 844 |   let_ : OriginDesc -> IndentInfo -> Rule PTerm
 845 |   let_ fname indents
 846 |       = do decoratedKeyword fname "let"
 847 |            commit
 848 |            res <- nonEmptyBlock (letBlock fname)
 849 |            commitKeyword fname indents "in"
 850 |            scope <- typeExpr pdef fname indents
 851 |            pure (mkLets fname res scope)
 852 |
 853 |   case_ : OriginDesc -> IndentInfo -> Rule PTerm
 854 |   case_ fname indents
 855 |       = do opts <- many (fnDirectOpt fname)
 856 |            b <- bounds (do decoratedKeyword fname "case"
 857 |                            scr <- expr pdef fname indents
 858 |                            mustWork (commitKeyword fname indents "of")
 859 |                            alts <- block (caseAlt fname)
 860 |                            pure (scr, alts))
 861 |            (scr, alts) <- pure b.val
 862 |            pure (PCase (virtualiseFC $ boundToFC fname b) opts scr alts)
 863 |
 864 |
 865 |   caseAlt : OriginDesc -> IndentInfo -> Rule PClause
 866 |   caseAlt fname indents
 867 |       = do lhs <- bounds (opExpr plhs fname indents)
 868 |            caseRHS fname lhs indents lhs.val
 869 |
 870 |   caseRHS : OriginDesc -> WithBounds t -> IndentInfo -> PTerm -> Rule PClause
 871 |   caseRHS fname start indents lhs
 872 |       = do rhs <- bounds $ do
 873 |                     decoratedSymbol fname "=>"
 874 |                     mustContinue indents Nothing
 875 |                     typeExpr pdef fname indents
 876 |            atEnd indents
 877 |            let fc = boundToFC fname (mergeBounds start rhs)
 878 |            pure (MkPatClause fc lhs rhs.val [])
 879 |     <|> do end <- bounds (decoratedKeyword fname "impossible")
 880 |            atEnd indents
 881 |            pure (MkImpossible (boundToFC fname (mergeBounds start end)) lhs)
 882 |     <|> fatalError ("Expected '=>' or 'impossible'")
 883 |
 884 |   if_ : OriginDesc -> IndentInfo -> Rule PTerm
 885 |   if_ fname indents
 886 |       = do b <- bounds (do decoratedKeyword fname "if"
 887 |                            commit
 888 |                            x <- expr pdef fname indents
 889 |                            commitKeyword fname indents "then"
 890 |                            t <- typeExpr pdef fname indents
 891 |                            commitKeyword fname indents "else"
 892 |                            e <- typeExpr pdef fname indents
 893 |                            pure (x, t, e))
 894 |            mustWork $ atEnd indents
 895 |            (x, t, e) <- pure b.val
 896 |            pure (PIfThenElse (boundToFC fname b) x t e)
 897 |
 898 |   record_ : OriginDesc -> IndentInfo -> Rule PTerm
 899 |   record_ fname indents
 900 |       = do
 901 |            b <- (
 902 |                withWarning oldSyntaxWarning (
 903 |                  bounds (do
 904 |                    decoratedKeyword fname "record"
 905 |                    commit
 906 |                    body True
 907 |                  ))
 908 |              <|>
 909 |                bounds (body False))
 910 |            pure (PUpdate (boundToFC fname b) (forget b.val))
 911 |     where
 912 |       oldSyntaxWarning : String
 913 |       oldSyntaxWarning = unlines
 914 |         [ "DEPRECATED: old record update syntax."
 915 |         , #"  Use "{ f := v } p" instead of "record { f = v } p""#
 916 |         , #"  and "{ f $= v } p" instead of "record { f $= v } p""#
 917 |         ]
 918 |
 919 |       body : Bool -> Rule (List1 PFieldUpdate)
 920 |       body kw = curly fname $ do
 921 |         commit
 922 |         sepBy1 (decoratedSymbol fname ",") (field kw fname indents)
 923 |
 924 |   field : Bool -> OriginDesc -> IndentInfo -> Rule PFieldUpdate
 925 |   field kw fname indents
 926 |       = do path <- map fieldName <$> [| decorate fname Function name :: many recFieldCompat |]
 927 |            upd <- (ifThenElse kw (decoratedSymbol fname "=") (decoratedSymbol fname ":=") $> PSetField)
 928 |                       <|>
 929 |                   (decoratedSymbol fname "$=" $> PSetFieldApp)
 930 |            val <- typeExpr plhs fname indents
 931 |            pure (upd path val)
 932 |     where
 933 |       fieldName : Name -> String
 934 |       fieldName (UN (Basic s)) = s
 935 |       fieldName (UN (Field s)) = s
 936 |       fieldName _ = "_impossible"
 937 |
 938 |       -- this allows the dotted syntax .field
 939 |       -- but also the arrowed syntax ->field for compatibility with Idris 1
 940 |       recFieldCompat : Rule Name
 941 |       recFieldCompat = decorate fname Function postfixProj
 942 |                   <|> (decoratedSymbol fname "->"
 943 |                        *> decorate fname Function name)
 944 |
 945 |   rewrite_ : OriginDesc -> IndentInfo -> Rule PTerm
 946 |   rewrite_ fname indents
 947 |       = do b <- bounds (do decoratedKeyword fname "rewrite"
 948 |                            rule <- expr pdef fname indents
 949 |                            commitKeyword fname indents "in"
 950 |                            tm <- typeExpr pdef fname indents
 951 |                            pure (rule, tm))
 952 |            (rule, tm) <- pure b.val
 953 |            pure (PRewrite (boundToFC fname b) rule tm)
 954 |
 955 |   doBlock : OriginDesc -> IndentInfo -> Rule PTerm
 956 |   doBlock fname indents
 957 |       = do b <- bounds $ decoratedKeyword fname "do" *> block (doAct fname)
 958 |            commit
 959 |            pure (PDoBlock (virtualiseFC $ boundToFC fname b) Nothing (concat b.val))
 960 |     <|> do nsdo <- bounds namespacedIdent
 961 |            -- TODO: need to attach metadata correctly here
 962 |            the (EmptyRule PTerm) $ case nsdo.val of
 963 |                 (ns, "do") =>
 964 |                    do commit
 965 |                       actions <- Core.bounds (block (doAct fname))
 966 |                       let fc = virtualiseFC $
 967 |                                boundToFC fname (mergeBounds nsdo actions)
 968 |                       pure (PDoBlock fc ns (concat actions.val))
 969 |                 _ => fail "Not a namespaced 'do'"
 970 |
 971 |   validPatternVar : Name -> EmptyRule ()
 972 |   validPatternVar (UN Underscore) = pure ()
 973 |   validPatternVar (UN (Basic n))
 974 |       = unless (lowerFirst n) $
 975 |           fail "Not a pattern variable"
 976 |   validPatternVar _ = fail "Not a pattern variable"
 977 |
 978 |   doAct : OriginDesc -> IndentInfo -> Rule (List PDo)
 979 |   doAct fname indents
 980 |       = do b <- bounds (do rig <- multiplicity fname
 981 |                            n <- bounds (name <|> UN Underscore <$ symbol "_")
 982 |                            -- If the name doesn't begin with a lower case letter, we should
 983 |                            -- treat this as a pattern, so fail
 984 |                            validPatternVar n.val
 985 |                            ty <- optional (decoratedSymbol fname ":" *> typeExpr (pnoeq pdef) fname indents)
 986 |                            decoratedSymbol fname "<-"
 987 |                            val <- expr pdef fname indents
 988 |                            pure (n, rig, ty, val))
 989 |            atEnd indents
 990 |            let (n, rig, ty, val) = b.val
 991 |            pure [DoBind (boundToFC fname b) (boundToFC fname n) n.val rig ty val]
 992 |     <|> do decoratedKeyword fname "let"
 993 |            commit
 994 |            res <- nonEmptyBlock (letBlock fname)
 995 |            do b <- bounds (decoratedKeyword fname "in")
 996 |               fatalLoc {c = True} b.bounds "Let-in not supported in do block. Did you mean (let ... in ...)?"
 997 |              <|>
 998 |            do atEnd indents
 999 |               pure (mkDoLets fname res)
1000 |     <|> do b <- bounds (decoratedKeyword fname "rewrite" *> expr pdef fname indents)
1001 |            atEnd indents
1002 |            pure [DoRewrite (boundToFC fname b) b.val]
1003 |     <|> do e <- bounds (expr plhs fname indents)
1004 |            (atEnd indents $> [DoExp (virtualiseFC $ boundToFC fname e) e.val])
1005 |              <|> (do ty <- optional (decoratedSymbol fname ":" *> typeExpr (pnoeq pdef) fname indents)
1006 |                      b <- bounds $ decoratedSymbol fname "<-" *> [| (expr pnowith fname indents, block (patAlt fname)) |]
1007 |                      atEnd indents
1008 |                      let (v, alts) = b.val
1009 |                      let fc = virtualiseFC $ boundToFC fname (mergeBounds e b)
1010 |                      pure [DoBindPat fc e.val ty v alts])
1011 |
1012 |   patAlt : OriginDesc -> IndentInfo -> Rule PClause
1013 |   patAlt fname indents
1014 |       = do decoratedSymbol fname "|"
1015 |            caseAlt fname indents
1016 |
1017 |   lazy : OriginDesc -> IndentInfo -> Rule PTerm
1018 |   lazy fname indents
1019 |       = do tm <- bounds (decorate fname Typ (exactIdent "Lazy")
1020 |                          *> simpleExpr fname indents
1021 |                          <* mustFailBecause "Lazy only takes one argument" (continue indents >> simpleExpr fname indents))
1022 |            pure (PDelayed (boundToFC fname tm) LLazy tm.val)
1023 |     <|> do tm <- bounds (decorate fname Typ (exactIdent "Inf")
1024 |                          *> simpleExpr fname indents
1025 |                          <* mustFailBecause "Inf only takes one argument" (continue indents >> simpleExpr fname indents))
1026 |            pure (PDelayed (boundToFC fname tm) LInf tm.val)
1027 |     <|> do tm <- bounds (decorate fname Data (exactIdent "Delay")
1028 |                          *> simpleExpr fname indents
1029 |                          <* mustFailBecause "Delay only takes one argument" (continue indents >> simpleExpr fname indents))
1030 |            pure (PDelay (boundToFC fname tm) tm.val)
1031 |     <|> do tm <- bounds (decorate fname Data (exactIdent "Force")
1032 |                          *> simpleExpr fname indents
1033 |                          <* mustFailBecause "Force only takes one argument" (continue indents >> simpleExpr fname indents))
1034 |            pure (PForce (boundToFC fname tm) tm.val)
1035 |
1036 |   binder : OriginDesc -> IndentInfo -> Rule PTerm
1037 |   binder fname indents
1038 |       = autoImplicitPi fname indents
1039 |     <|> defaultImplicitPi fname indents
1040 |     <|> forall_ fname indents
1041 |     <|> implicitPi fname indents
1042 |     <|> autobindOp pdef fname indents
1043 |     <|> explicitPi fname indents
1044 |     <|> lam fname indents
1045 |
1046 |   typeExpr : ParseOpts -> OriginDesc -> IndentInfo -> Rule PTerm
1047 |   typeExpr q fname indents
1048 |       = binder fname indents
1049 |     <|> ((bounds $ do
1050 |             arg <- expr q fname indents
1051 |             mscope <- optional $ do
1052 |                 continue indents
1053 |                 bd <- bindSymbol fname
1054 |                 scope <- mustWork $ typeExpr q fname indents
1055 |                 pure (bd, scope)
1056 |             pure (arg, mscope))
1057 |         <&> \arg_mscope =>
1058 |             let fc = boundToFC fname arg_mscope
1059 |                 (arg, mscope) = arg_mscope.val
1060 |              in mkPi fc arg mscope)
1061 |
1062 |     where
1063 |       mkPi : FC -> PTerm -> Maybe (PiInfo PTerm, PTerm) -> PTerm
1064 |       mkPi _ arg Nothing = arg
1065 |       mkPi fc arg (Just (exp, a))
1066 |         = PPi fc top exp Nothing arg a
1067 |
1068 |   export
1069 |   expr : ParseOpts -> OriginDesc -> IndentInfo -> Rule PTerm
1070 |   expr q fname indents
1071 |        = let_ fname indents
1072 |      <|> rewrite_ fname indents
1073 |      <|> do b <- bounds $
1074 |                    do decoratedPragma fname "runElab"
1075 |                       expr pdef fname indents
1076 |             pure (PRunElab (boundToFC fname b) b.val)
1077 |      <|> opExpr q fname indents
1078 |
1079 |   interpBlock : ParseOpts -> OriginDesc -> IndentInfo -> Rule PTerm
1080 |   interpBlock q fname idents = interpBegin *> (mustWork $ expr q fname idents <* interpEnd)
1081 |
1082 |   export
1083 |   singlelineStr : ParseOpts -> OriginDesc -> IndentInfo -> Rule PTerm
1084 |   singlelineStr q fname idents
1085 |       = decorate fname Data $
1086 |         do b <- bounds $ do begin <- bounds strBegin
1087 |                             commit
1088 |                             xs <- many $ bounds $ (interpBlock q fname idents) <||> strLitLines
1089 |                             pstrs <- case traverse toPStr xs of
1090 |                                           Left err => fatalLoc begin.bounds err
1091 |                                           Right pstrs => pure $ pstrs
1092 |                             strEnd
1093 |                             pure (begin.val, pstrs)
1094 |            pure $ let (hashtag, str) = b.val in
1095 |                       PString (boundToFC fname b) hashtag str
1096 |     where
1097 |       toPStr : (WithBounds $ Either PTerm (List1 String)) -> Either String PStr
1098 |       toPStr x = case x.val of
1099 |                       Right (str:::[]) => Right $ StrLiteral (boundToFC fname x) str
1100 |                       Right (_:::strs) => Left "Multi-line string is expected to begin with \"\"\""
1101 |                       Left tm => Right $ StrInterp (boundToFC fname x) tm
1102 |
1103 |   export
1104 |   multilineStr : ParseOpts -> OriginDesc -> IndentInfo -> Rule PTerm
1105 |   multilineStr q fname idents
1106 |       = decorate fname Data $
1107 |         do b <- bounds $ do hashtag <- multilineBegin
1108 |                             commit
1109 |                             xs <- many $ bounds $ (interpBlock q fname idents) <||> strLitLines
1110 |                             endloc <- location
1111 |                             strEnd
1112 |                             pure (hashtag, endloc, toLines xs [<] [<])
1113 |            pure $ let (hashtag, (_, col), xs) = b.val in
1114 |                       PMultiline (boundToFC fname b) hashtag (fromInteger $ cast col) xs
1115 |     where
1116 |       toLines : List (WithBounds $ Either PTerm (List1 String)) ->
1117 |                 SnocList PStr -> SnocList (List PStr) -> List (List PStr)
1118 |       toLines [] line acc = acc <>> [line <>> []]
1119 |       toLines (x::xs) line acc = case x.val of
1120 |         Left tm =>
1121 |           toLines xs (line :< StrInterp (boundToFC fname x) tm) acc
1122 |         Right (str:::[]) =>
1123 |           toLines xs (line :< StrLiteral (boundToFC fname x) str) acc
1124 |         Right (str:::strs@(_::_)) =>
1125 |           let fc = boundToFC fname x in
1126 |           toLines xs [< StrLiteral fc (last strs)]
1127 |             $ acc :< (line <>> [StrLiteral fc str])
1128 |             <>< map (\str => [StrLiteral fc str]) (init strs)
1129 |
1130 |   fnDirectOpt : OriginDesc -> Rule PFnOpt
1131 |   fnDirectOpt fname
1132 |       = do decoratedPragma fname "hint"
1133 |            pure $ IFnOpt (Hint True)
1134 |     <|> do decoratedPragma fname "globalhint"
1135 |            pure $ IFnOpt (GlobalHint False)
1136 |     <|> do decoratedPragma fname "defaulthint"
1137 |            pure $ IFnOpt (GlobalHint True)
1138 |     <|> do decoratedPragma fname "inline"
1139 |            commit
1140 |            pure $ IFnOpt Inline
1141 |     <|> do decoratedPragma fname "unsafe"
1142 |            commit
1143 |            pure $ IFnOpt Unsafe
1144 |     <|> do decoratedPragma fname "noinline"
1145 |            commit
1146 |            pure $ IFnOpt NoInline
1147 |     <|> do decoratedPragma fname "deprecate"
1148 |            commit
1149 |            pure $ IFnOpt Deprecate
1150 |     <|> do decoratedPragma fname "tcinline"
1151 |            commit
1152 |            pure $ IFnOpt TCInline
1153 |     <|> do decoratedPragma fname "extern"
1154 |            pure $ IFnOpt ExternFn
1155 |     <|> do decoratedPragma fname "macro"
1156 |            pure $ IFnOpt Macro
1157 |     <|> do decoratedPragma fname "spec"
1158 |            ns <- sepBy (decoratedSymbol fname ",") name
1159 |            pure $ IFnOpt (SpecArgs ns)
1160 |     <|> do decoratedPragma fname "foreign"
1161 |            cs <- block (expr pdef fname)
1162 |            pure $ PForeign cs
1163 |     <|> do (decoratedPragma fname "export"
1164 |             <|> withWarning noMangleWarning
1165 |                 (decoratedPragma fname "nomangle"))
1166 |            cs <- block (expr pdef fname)
1167 |            pure $ PForeignExport cs
1168 |     where
1169 |       noMangleWarning : String
1170 |       noMangleWarning = """
1171 |       DEPRECATED: "%nomangle".
1172 |         Use "%export" instead
1173 |       """
1174 |
1175 |
1176 | visOption : OriginDesc ->  Rule Visibility
1177 | visOption fname
1178 |     = (decoratedKeyword fname "public" *> decoratedKeyword fname "export" $> Public)
1179 |     -- If "public export" failed then we try to parse just "public" and emit an error message saying
1180 |     -- the user should use "public export"
1181 |   <|> (bounds (decoratedKeyword fname "public") >>= \x : WithBounds ()
1182 |     => the (Rule Visibility) (fatalLoc x.bounds
1183 |            #""public" keyword by itself is not an export modifier, did you mean "public export"?"#))
1184 |   <|> (decoratedKeyword fname "export" $> Export)
1185 |   <|> (decoratedKeyword fname "private" $> Private)
1186 |
1187 |
1188 | visibility : OriginDesc -> EmptyRule (WithDefault Visibility Private)
1189 | visibility fname
1190 |     = (specified <$> visOption fname)
1191 |   <|> pure defaulted
1192 |
1193 | exportVisibility : OriginDesc -> EmptyRule (WithDefault Visibility Export)
1194 | exportVisibility fname
1195 |     = (specified <$> visOption fname)
1196 |   <|> pure defaulted
1197 |
1198 | ||| A binder with only one name and one type
1199 | ||| BNF:
1200 | ||| plainBinder := name ':' typeExpr
1201 | plainBinder : (fname : OriginDesc) => (indents : IndentInfo) => Rule PlainBinder
1202 | plainBinder = do name <- fcBounds (decoratedSimpleBinderUName fname)
1203 |                  decoratedSymbol fname ":"
1204 |                  ty <- typeExpr pdef fname indents
1205 |                  pure $ Mk [name] ty
1206 |
1207 | ||| A binder with multiple names and one type
1208 | ||| BNF:
1209 | ||| basicMultiBinder := name (, name)* ':' typeExpr
1210 | basicMultiBinder : (fname : OriginDesc) => (indents : IndentInfo) => Rule BasicMultiBinder
1211 | basicMultiBinder
1212 |   = do rig <- multiplicity fname
1213 |        names <- sepBy1 (decoratedSymbol fname ",")
1214 |                      $ fcBounds (decoratedSimpleBinderUName fname)
1215 |        decoratedSymbol fname ":"
1216 |        ty <- typeExpr pdef fname indents
1217 |        pure $ MkBasicMultiBinder rig names ty
1218 |
1219 | tyDecls : Rule Name -> String -> OriginDesc -> IndentInfo -> Rule PTypeDecl
1220 | tyDecls declName predoc fname indents
1221 |     = do bs <- bounds $ do
1222 |                   docns <- sepBy1 (decoratedSymbol fname ",")
1223 |                                   [| (optDocumentation fname, fcBounds declName) |]
1224 |                   b <- bounds $ decoratedSymbol fname ":"
1225 |                   mustWorkBecause b.bounds "Expected a type declaration" $ do
1226 |                     ty <- the (Rule PTerm) (typeExpr pdef fname indents)
1227 |                     pure $ MkPTy docns predoc ty
1228 |          atEnd indents
1229 |          pure $ bs.withFC
1230 |
1231 | withFlags : OriginDesc -> EmptyRule (List WithFlag)
1232 | withFlags fname
1233 |     = (do decoratedPragma fname "syntactic"
1234 |           (Syntactic ::) <$> withFlags fname)
1235 |   <|> pure []
1236 |
1237 |
1238 | withProblem : OriginDesc -> Int -> IndentInfo -> Rule PWithProblem
1239 | withProblem fname col indents
1240 |   = do rig <- multiplicity fname
1241 |        start <- mustWork $ bounds (decoratedSymbol fname "(")
1242 |        wval <- bracketedExpr fname start indents
1243 |        prf <- optional $ do
1244 |                 decoratedKeyword fname "proof"
1245 |                 pure (!(multiplicity fname), !(decoratedSimpleBinderUName fname))
1246 |        pure (MkPWithProblem rig wval prf)
1247 |
1248 | mutual
1249 |   parseRHS : (withArgs : Nat) ->
1250 |              OriginDesc -> WithBounds t -> Int ->
1251 |              IndentInfo -> (lhs : (PTerm, List (FC, PTerm))) -> Rule PClause
1252 |   parseRHS withArgs fname start col indents lhs
1253 |        = do b <- bounds $ do
1254 |                    decoratedSymbol fname "="
1255 |                    mustWork $ do
1256 |                      continue indents
1257 |                      rhs <- typeExpr pdef fname indents
1258 |                      ws <- option [] $ whereBlock fname col
1259 |                      pure (rhs, ws)
1260 |             b' <- bounds peek
1261 |             mustWorkBecause b'.bounds "Not the end of a block entry, check indentation" $ atEnd indents
1262 |             (rhs, ws) <- pure b.val
1263 |             let fc = boundToFC fname (mergeBounds start b)
1264 |             pure (MkPatClause fc (uncurry applyWithArgs lhs) rhs ws)
1265 |      <|> do b <- bounds $ do
1266 |                    decoratedKeyword fname "with"
1267 |                    commit
1268 |                    flags <- withFlags fname
1269 |                    wps <- sepBy1 (decoratedSymbol fname "|") (withProblem fname col indents)
1270 |                    ws <- mustWork $ nonEmptyBlockAfter col
1271 |                                   $ clause (S (length wps.tail) + withArgs) (Just lhs) fname
1272 |                    pure (flags, wps, forget ws)
1273 |             (flags, wps, ws) <- pure b.val
1274 |             let fc = boundToFC fname (mergeBounds start b)
1275 |             pure (MkWithClause fc (uncurry applyWithArgs lhs) wps flags ws)
1276 |      <|> do end <- bounds (decoratedKeyword fname "impossible")
1277 |             atEnd indents
1278 |             pure $ let fc = boundToFC fname (mergeBounds start end) in
1279 |                    MkImpossible fc (uncurry applyWithArgs lhs)
1280 |
1281 |   clause : (withArgs : Nat) ->
1282 |            IMaybe (isSucc withArgs) (PTerm, List (FC, PTerm)) ->
1283 |            OriginDesc -> IndentInfo -> Rule PClause
1284 |   clause withArgs mlhs fname indents
1285 |       = do b <- bounds (do col   <- column
1286 |                            lhsws <- clauseLHS fname indents mlhs
1287 |                            extra <- many parseWithArg
1288 |                            pure (col, mapSnd (++ extra) lhsws))
1289 |            let col = Builtin.fst b.val
1290 |            let lhs = Builtin.snd b.val
1291 |            let extra = Builtin.snd lhs
1292 |            -- Can't have the dependent 'if' here since we won't be able
1293 |            -- to infer the termination status of the rule
1294 |            ifThenElse (withArgs /= length extra)
1295 |               (fatalError $ "Wrong number of 'with' arguments:"
1296 |                          ++ " expected " ++ show withArgs
1297 |                          ++ " but got " ++ show (length extra))
1298 |               (parseRHS withArgs fname b col indents lhs)
1299 |     where
1300 |
1301 |       clauseLHS : OriginDesc -> IndentInfo ->
1302 |                   IMaybe b (PTerm, List (FC, PTerm)) ->
1303 |                   Rule (PTerm, List (FC, PTerm))
1304 |       -- we aren't in a `with` so there is nothing to skip
1305 |       clauseLHS fname indent Nothing
1306 |         = (,[]) <$> opExpr plhs fname indents
1307 |       -- in a with clause, give a different meaning to a `_` lhs
1308 |       clauseLHS fname indent (Just lhs)
1309 |         = do e <- opExpr plhs fname indents
1310 |              pure $ case e of
1311 |                PImplicit fc =>
1312 |                  let vfc = virtualiseFC fc in
1313 |                  bimap (substFC vfc) (map (map $ substFC vfc)) lhs
1314 |                _ => (e, [])
1315 |
1316 |       parseWithArg : Rule (FC, PTerm)
1317 |       parseWithArg
1318 |           = do decoratedSymbol fname "|"
1319 |                tm <- bounds (expr plhs fname indents)
1320 |                pure (boundToFC fname tm, tm.val)
1321 |
1322 | mkTyConType : OriginDesc -> FC -> List (WithBounds Name) -> PTerm
1323 | mkTyConType fname fc [] = PType (virtualiseFC fc)
1324 | mkTyConType fname fc (x :: xs)
1325 |    = let bfc = boundToFC fname x in
1326 |      PPi bfc top Explicit Nothing (PType (virtualiseFC fc))
1327 |      $ mkTyConType fname fc xs
1328 |
1329 | mkDataConType : PTerm -> List (WithFC ArgType) -> Maybe PTerm
1330 | mkDataConType ret [] = Just ret
1331 | mkDataConType ret (con@(MkWithData _ (UnnamedExpArg x)) :: xs)
1332 |     = PPi con.fc top Explicit Nothing x <$> mkDataConType ret xs
1333 | mkDataConType ret (con@(MkWithData _ (UnnamedAutoArg x)) :: xs)
1334 |     = PPi con.fc top AutoImplicit Nothing x <$> mkDataConType ret xs
1335 | mkDataConType _ _ -- with and named applications not allowed in simple ADTs
1336 |     = Nothing
1337 |
1338 | simpleCon : OriginDesc -> PTerm -> IndentInfo -> Rule PTypeDecl
1339 | simpleCon fname ret indents
1340 |     = do b <- bounds (do cdoc   <- optDocumentation fname
1341 |                          cname  <- fcBounds $ decoratedDataConstructorName fname
1342 |                          params <- the (EmptyRule $ List $ WithFC $ List ArgType)
1343 |                                      $ many (fcBounds $ argExpr plhs fname indents)
1344 |                          let conType = the (Maybe PTerm) (mkDataConType ret
1345 |                                                             (concat (map distribData params)))
1346 |                          fromMaybe (fatalError "Named arguments not allowed in ADT constructors")
1347 |                                    (pure . MkPTy (singleton ("", cname)) cdoc <$> conType)
1348 |                          )
1349 |          atEnd indents
1350 |          pure b.withFC
1351 |
1352 | simpleData : OriginDesc -> WithBounds t ->
1353 |              WithBounds Name -> IndentInfo -> Rule PDataDecl
1354 | simpleData fname start tyName indents
1355 |     = do b <- bounds (do params <- many (bounds $ decorate fname Bound name)
1356 |                          tyend <- bounds (decoratedSymbol fname "=")
1357 |                          mustWork $ do
1358 |                            let tyfc = boundToFC fname (mergeBounds start tyend)
1359 |                            let tyCon = PRef (boundToFC fname tyName) tyName.val
1360 |                            let toPRef = \ t => PRef (boundToFC fname t) t.val
1361 |                            let conRetTy = papply tyfc tyCon (map toPRef params)
1362 |                            cons <- sepBy1 (decoratedSymbol fname "|") (simpleCon fname conRetTy indents)
1363 |                            pure (params, tyfc, forget cons))
1364 |          (params, tyfc, cons) <- pure b.val
1365 |          pure (MkPData (boundToFC fname (mergeBounds start b)) tyName.val
1366 |                        (Just (mkTyConType fname tyfc params)) [] cons)
1367 |
1368 | dataOpt : OriginDesc -> Rule DataOpt
1369 | dataOpt fname
1370 |     = (decorate fname Keyword (exactIdent "noHints") $> NoHints)
1371 |   <|> (decorate fname Keyword (exactIdent "uniqueSearch") $> UniqueSearch)
1372 |   <|> (do b   <- bounds $ decorate fname Keyword (exactIdent "search")
1373 |           det <- mustWorkBecause b.bounds "Expected list of determining parameters" $
1374 |                    some (decorate fname Bound name)
1375 |           pure $ SearchBy det)
1376 |   <|> (decorate fname Keyword (exactIdent "external") $> External)
1377 |   <|> (decorate fname Keyword (exactIdent "noNewtype") $> NoNewtype)
1378 |
1379 | dataOpts : OriginDesc -> EmptyRule (List DataOpt)
1380 | dataOpts fname = option [] $ do
1381 |   decoratedSymbol fname "["
1382 |   opts <- sepBy1 (decoratedSymbol fname ",") (dataOpt fname)
1383 |   decoratedSymbol fname "]"
1384 |   pure (forget opts)
1385 |
1386 | dataBody : OriginDesc -> Int -> WithBounds t -> Name -> IndentInfo -> Maybe PTerm ->
1387 |           EmptyRule PDataDecl
1388 | dataBody fname mincol start n indents ty
1389 |     = do ty <- maybe (fail "Telescope is not optional in forward declaration") pure ty
1390 |          atEndIndent indents
1391 |          pure (MkPLater (boundToFC fname start) n ty)
1392 |   <|> do b <- bounds (do (mustWork $ decoratedKeyword fname "where")
1393 |                          opts <- dataOpts fname
1394 |                          cs <- blockAfter mincol (tyDecls (mustWork $ decoratedDataConstructorName fname) "" fname)
1395 |                          pure (opts, cs))
1396 |          (opts, cs) <- pure b.val
1397 |          pure (MkPData (boundToFC fname (mergeBounds start b)) n ty opts cs)
1398 |
1399 | gadtData : OriginDesc -> Int -> WithBounds t ->
1400 |            WithBounds Name -> IndentInfo -> EmptyRule PDataDecl
1401 | gadtData fname mincol start tyName indents
1402 |     = do ty <- optional $
1403 |                  do decoratedSymbol fname ":"
1404 |                     commit
1405 |                     typeExpr pdef fname indents
1406 |          dataBody fname mincol start tyName.val indents ty
1407 |
1408 | dataDeclBody : OriginDesc -> IndentInfo -> Rule PDataDecl
1409 | dataDeclBody fname indents
1410 |     = do b <- bounds (do col <- column
1411 |                          decoratedKeyword fname "data"
1412 |                          n <- mustWork (bounds $ decoratedDataTypeName fname)
1413 |                          pure (col, n))
1414 |          (col, n) <- pure b.val
1415 |          simpleData fname b n indents <|> gadtData fname col b n indents
1416 |
1417 | -- a data declaration can have a visibility and an optional totality (#1404)
1418 | dataVisOpt : OriginDesc -> EmptyRule (WithDefault Visibility Private, Maybe TotalReq)
1419 | dataVisOpt fname
1420 |     = do { vis <- visOption   fname ; mbtot <- optional (totalityOpt fname) ; pure (specified vis, mbtot) }
1421 |   <|> do { tot <- totalityOpt fname ; vis <- visibility fname ; pure (vis, Just tot) }
1422 |   <|> pure (defaulted, Nothing)
1423 |
1424 | dataDecl : (fname : OriginDesc) => (indents : IndentInfo) => Rule PDeclNoFC
1425 | dataDecl
1426 |     = do doc         <- optDocumentation fname
1427 |          (vis,mbTot) <- dataVisOpt fname
1428 |          dat         <- dataDeclBody fname indents
1429 |          pure (PData doc vis mbTot dat)
1430 |
1431 | stripBraces : String -> String
1432 | stripBraces str = pack (drop '{' (reverse (drop '}' (reverse (unpack str)))))
1433 |   where
1434 |     drop : Char -> List Char -> List Char
1435 |     drop c [] = []
1436 |     drop c (c' :: xs) = if c == c' then drop c xs else c' :: xs
1437 |
1438 | onoff : Rule Bool
1439 | onoff
1440 |    = (exactIdent "on" $> True)
1441 |  <|> (exactIdent "off" $> False)
1442 |  <|> fail "expected 'on' or 'off'"
1443 |
1444 | extension : Rule LangExt
1445 | extension
1446 |     = (exactIdent "ElabReflection" $> ElabReflection)
1447 |   <|> fail "expected 'ElabReflection'"
1448 |
1449 | logLevel : OriginDesc -> Rule (Maybe LogLevel)
1450 | logLevel fname
1451 |   = (Nothing <$ decorate fname Keyword (exactIdent "off"))
1452 |     <|> do topic <- optional (split ('.' ==) <$> simpleStr)
1453 |            lvl <- intLit
1454 |            pure (Just (mkLogLevel' topic (fromInteger lvl)))
1455 |     <|> fail "expected a log level"
1456 |
1457 | directive : (fname : OriginDesc) => (indents : IndentInfo) => Rule Directive
1458 | directive
1459 |     = do decoratedPragma fname "hide"
1460 |          n <- (fixityNS <|> (HideName <$> name))
1461 |          atEnd indents
1462 |          pure (Hide n)
1463 |   <|> do decoratedPragma fname "unhide"
1464 |          n <- name
1465 |          atEnd indents
1466 |          pure (Unhide n)
1467 |   <|> do decoratedPragma fname "foreign_impl"
1468 |          n <- name
1469 |          cs <- block (expr pdef fname)
1470 |          atEnd indents
1471 |          pure (ForeignImpl n cs)
1472 | --   <|> do pragma "hide_export"
1473 | --          n <- name
1474 | --          atEnd indents
1475 | --          pure (Hide True n)
1476 |   <|> do decoratedPragma fname "logging"
1477 |          lvl <- logLevel fname
1478 |          atEnd indents
1479 |          pure (Logging lvl)
1480 |   <|> do decoratedPragma fname "auto_lazy"
1481 |          b <- onoff
1482 |          atEnd indents
1483 |          pure (LazyOn b)
1484 |   <|> do decoratedPragma fname "unbound_implicits"
1485 |          b <- onoff
1486 |          atEnd indents
1487 |          pure (UnboundImplicits b)
1488 |   <|> do decoratedPragma fname "prefix_record_projections"
1489 |          b <- onoff
1490 |          atEnd indents
1491 |          pure (PrefixRecordProjections b)
1492 |   <|> do decoratedPragma fname "totality_depth"
1493 |          lvl <- decorate fname Keyword $ intLit
1494 |          atEnd indents
1495 |          pure (TotalityDepth (fromInteger lvl))
1496 |   <|> do decoratedPragma fname "ambiguity_depth"
1497 |          lvl <- decorate fname Keyword $ intLit
1498 |          atEnd indents
1499 |          pure (AmbigDepth (fromInteger lvl))
1500 |   <|> do decoratedPragma fname "auto_implicit_depth"
1501 |          dpt <- decorate fname Keyword $ intLit
1502 |          atEnd indents
1503 |          pure (AutoImplicitDepth (fromInteger dpt))
1504 |   <|> do decoratedPragma fname "nf_metavar_threshold"
1505 |          dpt <- decorate fname Keyword $ intLit
1506 |          atEnd indents
1507 |          pure (NFMetavarThreshold (fromInteger dpt))
1508 |   <|> do decoratedPragma fname "search_timeout"
1509 |          t <- decorate fname Keyword $ intLit
1510 |          atEnd indents
1511 |          pure (SearchTimeout t)
1512 |   <|> do decoratedPragma fname "pair"
1513 |          ty <- name
1514 |          f <- name
1515 |          s <- name
1516 |          atEnd indents
1517 |          pure (PairNames ty f s)
1518 |   <|> do decoratedPragma fname "rewrite"
1519 |          eq <- name
1520 |          rw <- name
1521 |          atEnd indents
1522 |          pure (RewriteName eq rw)
1523 |   <|> do decoratedPragma fname "integerLit"
1524 |          n <- name
1525 |          atEnd indents
1526 |          pure (PrimInteger n)
1527 |   <|> do decoratedPragma fname "stringLit"
1528 |          n <- name
1529 |          atEnd indents
1530 |          pure (PrimString n)
1531 |   <|> do decoratedPragma fname "charLit"
1532 |          n <- name
1533 |          atEnd indents
1534 |          pure (PrimChar n)
1535 |   <|> do decoratedPragma fname "doubleLit"
1536 |          n <- name
1537 |          atEnd indents
1538 |          pure (PrimDouble n)
1539 |   <|> do decoratedPragma fname "TTImpLit"
1540 |          n <- name
1541 |          atEnd indents
1542 |          pure (PrimTTImp n)
1543 |   <|> do decoratedPragma fname "nameLit"
1544 |          n <- name
1545 |          atEnd indents
1546 |          pure (PrimName n)
1547 |   <|> do decoratedPragma fname "declsLit"
1548 |          n <- name
1549 |          atEnd indents
1550 |          pure (PrimDecls n)
1551 |   <|> do decoratedPragma fname "name"
1552 |          n <- name
1553 |          ns <- sepBy1 (decoratedSymbol fname ",")
1554 |                       (decoratedSimpleBinderUName fname)
1555 |          atEnd indents
1556 |          pure (Names n (forget (map nameRoot ns)))
1557 |   <|> do decoratedPragma fname "start"
1558 |          e <- expr pdef fname indents
1559 |          atEnd indents
1560 |          pure (StartExpr e)
1561 |   <|> do decoratedPragma fname "allow_overloads"
1562 |          n <- name
1563 |          atEnd indents
1564 |          pure (Overloadable n)
1565 |   <|> do decoratedPragma fname "language"
1566 |          e <- mustWork extension
1567 |          atEnd indents
1568 |          pure (Extension e)
1569 |   <|> do decoratedPragma fname "default"
1570 |          tot <- totalityOpt fname
1571 |          atEnd indents
1572 |          pure (DefaultTotality tot)
1573 |
1574 | fix : Rule Fixity
1575 | fix
1576 |     = (keyword "infixl" $> InfixL)
1577 |   <|> (keyword "infixr" $> InfixR)
1578 |   <|> (keyword "infix"  $> Infix)
1579 |   <|> (keyword "prefix" $> Prefix)
1580 |
1581 | namespaceHead : OriginDesc -> Rule Namespace
1582 | namespaceHead fname
1583 |   = do decoratedKeyword fname "namespace"
1584 |        decorate fname Namespace $ mustWork namespaceId
1585 |
1586 | parameters {auto fname : OriginDesc} {auto indents : IndentInfo}
1587 |   namespaceDecl : Rule PDeclNoFC
1588 |   namespaceDecl
1589 |       = do doc <- optDocumentation fname -- documentation is not recoded???
1590 |            col <- column
1591 |            ns  <- namespaceHead fname
1592 |            ds  <- blockAfter col (topDecl fname)
1593 |            pure (PNamespace ns (collectDefs ds))
1594 |
1595 |   transformDecl : Rule PDeclNoFC
1596 |   transformDecl
1597 |       = do decoratedPragma fname "transform"
1598 |            n <- simpleStr
1599 |            lhs <- expr plhs fname indents
1600 |            decoratedSymbol fname "="
1601 |            rhs <- expr pnowith fname indents
1602 |            pure (PTransform n lhs rhs)
1603 |
1604 |   runElabDecl : Rule PDeclNoFC
1605 |   runElabDecl
1606 |       = do
1607 |            decoratedPragma fname "runElab"
1608 |            tm <- expr pnowith fname indents
1609 |            pure (PRunElabDecl tm)
1610 |
1611 |   ||| failDecls := 'failing' simpleStr? nonEmptyBlock
1612 |   failDecls : Rule PDeclNoFC
1613 |   failDecls
1614 |       = do
1615 |            col <- column
1616 |            decoratedKeyword fname "failing"
1617 |            commit
1618 |            msg <- optional (decorate fname Data (simpleMultiStr <|> simpleStr ))
1619 |            ds <- nonEmptyBlockAfter col (topDecl fname)
1620 |            pure $ PFail msg (collectDefs $ forget ds)
1621 |
1622 |   ||| mutualDecls := 'mutual' nonEmptyBlock
1623 |   mutualDecls : Rule PDeclNoFC
1624 |   mutualDecls
1625 |       = do
1626 |            col <- column
1627 |            decoratedKeyword fname "mutual"
1628 |            commit
1629 |            ds <- nonEmptyBlockAfter col (topDecl fname)
1630 |            pure (PMutual (forget ds))
1631 |
1632 |   usingDecls : Rule PDeclNoFC
1633 |   usingDecls
1634 |       = do col <- column
1635 |            decoratedKeyword fname "using"
1636 |            commit
1637 |            decoratedSymbol fname "("
1638 |            us <- sepBy (decoratedSymbol fname ",")
1639 |                        (do n <- optional $ userName <* decoratedSymbol fname ":"
1640 |                            ty <- typeExpr pdef fname indents
1641 |                            pure (n, ty))
1642 |            decoratedSymbol fname ")"
1643 |            ds <- nonEmptyBlockAfter col (topDecl fname)
1644 |            pure (PUsing us (collectDefs (forget ds)))
1645 |
1646 |   ||| builtinDecl := 'builtin' builtinType name
1647 |   builtinDecl : Rule PDeclNoFC
1648 |   builtinDecl
1649 |       = do decoratedPragma fname "builtin"
1650 |            commit
1651 |            t <- builtinType
1652 |            n <- name
1653 |            pure $ PBuiltin t n
1654 |
1655 | visOpt : OriginDesc -> Rule (Either Visibility PFnOpt)
1656 | visOpt fname
1657 |     = do vis <- visOption fname
1658 |          pure (Left vis)
1659 |   <|> do tot <- fnOpt fname
1660 |          pure (Right tot)
1661 |   <|> do opt <- fnDirectOpt fname
1662 |          pure (Right opt)
1663 |
1664 | getVisibility : Maybe Visibility -> List (Either Visibility PFnOpt) ->
1665 |                 EmptyRule Visibility
1666 | getVisibility Nothing [] = pure Private
1667 | getVisibility (Just vis) [] = pure vis
1668 | getVisibility Nothing (Left x :: xs) = getVisibility (Just x) xs
1669 | getVisibility (Just vis) (Left x :: xs)
1670 |    = fatalError "Multiple visibility modifiers"
1671 | getVisibility v (_ :: xs) = getVisibility v xs
1672 |
1673 | recordConstructor : OriginDesc -> Rule (WithDoc $ AddFC Name)
1674 | recordConstructor fname
1675 |   = do doc <- optDocumentation fname
1676 |        decorate fname Keyword $ exactIdent "constructor"
1677 |        n <- fcBounds $ mustWork $ decoratedDataConstructorName fname
1678 |        pure (doc :+ n)
1679 |
1680 | autoImplicitField : OriginDesc -> IndentInfo -> Rule (PiInfo t)
1681 | autoImplicitField fname _ = AutoImplicit <$ decoratedKeyword fname "auto"
1682 |
1683 | defImplicitField : OriginDesc -> IndentInfo -> Rule (PiInfo PTerm)
1684 | defImplicitField fname indents = do
1685 |   decoratedKeyword fname "default"
1686 |   commit
1687 |   t <- simpleExpr fname indents
1688 |   pure (DefImplicit t)
1689 |
1690 | constraints : OriginDesc -> IndentInfo -> EmptyRule (List (Maybe Name, PTerm))
1691 | constraints fname indents
1692 |     = do tm <- appExpr pdef fname indents
1693 |          decoratedSymbol fname "=>"
1694 |          more <- constraints fname indents
1695 |          pure ((Nothing, tm) :: more)
1696 |   <|> do decoratedSymbol fname "("
1697 |          n <- decorate fname Bound name
1698 |          decoratedSymbol fname ":"
1699 |          tm <- typeExpr pdef fname indents
1700 |          decoratedSymbol fname ")"
1701 |          decoratedSymbol fname "=>"
1702 |          more <- constraints fname indents
1703 |          pure ((Just n, tm) :: more)
1704 |   <|> pure []
1705 |
1706 | implBinds : OriginDesc -> IndentInfo -> (namedImpl : Bool) ->
1707 |             EmptyRule (List (AddFC (ImpParameter' PTerm)))
1708 | implBinds fname indents namedImpl = concatMap (map adjust) <$> go where
1709 |
1710 |   adjust : ImpParameter' PTerm -> AddFC (ImpParameter' PTerm)
1711 |   adjust param = virtualiseFC param.name.fc :+ param
1712 |
1713 |   isDefaultImplicit : PiInfo a -> Bool
1714 |   isDefaultImplicit (DefImplicit _) = True
1715 |   isDefaultImplicit _               = False
1716 |
1717 |   go : EmptyRule (List (List (ImpParameter' PTerm)))
1718 |   go = do decoratedSymbol fname "{"
1719 |           piInfo <- bounds $ option Implicit $ defImplicitField fname indents
1720 |           when (not namedImpl && isDefaultImplicit piInfo.val) $
1721 |             fatalLoc piInfo.bounds "Default implicits are allowed only for named implementations"
1722 |           ns <- map (\case (MkBasicMultiBinder rig names type) => map (\nm => Mk [rig, nm] (MkPiBindData piInfo.val type)) (forget names))
1723 |                     (pibindListName fname indents)
1724 |           let ns = the (List (ImpParameter' PTerm)) ns
1725 |           commitSymbol fname "}"
1726 |           commitSymbol fname "->"
1727 |           more <- go
1728 |           pure (ns :: more)
1729 |     <|> pure []
1730 |
1731 | fieldDecl : (fname : OriginDesc) => IndentInfo -> Rule PField
1732 | fieldDecl indents
1733 |       = do doc <- optDocumentation fname
1734 |            decoratedSymbol fname "{"
1735 |            commit
1736 |            impl <- option Implicit (autoImplicitField fname indents <|> defImplicitField fname indents)
1737 |            fs <- addFCBounds (fieldBody doc impl)
1738 |            decoratedSymbol fname "}"
1739 |            atEnd indents
1740 |            pure fs
1741 |     <|> do doc <- optDocumentation fname
1742 |            fs <- addFCBounds (fieldBody doc Explicit)
1743 |            atEnd indents
1744 |            pure fs
1745 |   where
1746 |     fieldBody : String -> PiInfo PTerm -> Rule (RecordField' Name)
1747 |     fieldBody doc p
1748 |         = do rig <- multiplicity fname
1749 |              ns <- sepBy1 (decoratedSymbol fname ",")
1750 |                      (fcBounds (decorate fname Function name
1751 |                         <|> (do b <- bounds (symbol "_")
1752 |                                 fatalLoc {c = True} b.bounds "Fields have to be named")))
1753 |              decoratedSymbol fname ":"
1754 |              ty <- typeExpr pdef fname indents
1755 |              pure (Mk [doc, rig, forget ns] (MkPiBindData p ty))
1756 |
1757 | parameters {auto fname : OriginDesc} {auto indents : IndentInfo}
1758 |
1759 |   ifaceParam : Rule BasicMultiBinder
1760 |   ifaceParam
1761 |       = parens fname basicMultiBinder
1762 |     <|> do n <- fcBounds (decorate fname Bound name)
1763 |            pure (MkBasicMultiBinder erased (singleton n) (PInfer n.fc))
1764 |
1765 |   ifaceDecl : Rule PDeclNoFC
1766 |   ifaceDecl
1767 |       = do  doc   <- optDocumentation fname
1768 |             vis   <- visibility fname
1769 |             col   <- column
1770 |             decoratedKeyword fname "interface"
1771 |             commit
1772 |             cons   <- constraints fname indents
1773 |             n      <- decorate fname Typ name
1774 |             params <- many ifaceParam
1775 |             det    <- optional $ do
1776 |               b <- bounds $ decoratedSymbol fname "|"
1777 |               mustWorkBecause b.bounds "Expected list of determining parameters" $
1778 |                 sepBy1 (decoratedSymbol fname ",") (decorate fname Bound name)
1779 |             decoratedKeyword fname "where"
1780 |             dc <- optional (recordConstructor fname)
1781 |             body <- blockAfter col (topDecl fname)
1782 |             pure (PInterface
1783 |                          vis cons n doc params det dc (collectDefs body))
1784 |
1785 |   implDecl : Rule PDeclNoFC
1786 |   implDecl
1787 |       = do doc     <- optDocumentation fname
1788 |            visOpts <- many (visOpt fname)
1789 |            vis     <- getVisibility Nothing visOpts
1790 |            let opts = mapMaybe getRight visOpts
1791 |            col <- column
1792 |            option () (decoratedKeyword fname "implementation")
1793 |            iname  <- optional $ decoratedSymbol fname "["
1794 |                              *> decorate fname Function name
1795 |                              <* decoratedSymbol fname "]"
1796 |            impls  <- implBinds fname indents (isJust iname)
1797 |            cons   <- constraints fname indents
1798 |            n      <- decorate fname Typ name
1799 |            params <- many (continue indents *> simpleExpr fname indents)
1800 |            nusing <- option [] $ decoratedKeyword fname "using"
1801 |                               *> forget <$> some (decorate fname Function name)
1802 |            body <- optional $ decoratedKeyword fname "where" *> blockAfter col (topDecl fname)
1803 |            atEnd indents
1804 |            pure $
1805 |               PImplementation vis opts Single impls cons n params iname nusing
1806 |                                (map collectDefs body)
1807 |
1808 |   localClaim : Rule PClaimData
1809 |   localClaim
1810 |       = do doc     <- optDocumentation fname
1811 |            visOpts <- many (visOpt fname)
1812 |            vis     <- getVisibility Nothing visOpts
1813 |            let opts = mapMaybe getRight visOpts
1814 |            rig  <- multiplicity fname
1815 |            cls  <- tyDecls (decorate fname Function name)
1816 |                            doc fname indents
1817 |            pure $ MkPClaim rig vis opts cls
1818 |
1819 |
1820 |   -- A Single binder with multiple names
1821 |   typedArg : Rule PBinder
1822 |   typedArg
1823 |       = do params <- parens fname $ pibindListName fname indents
1824 |            pure $ MkPBinder Explicit params
1825 |     <|> do decoratedSymbol fname "{"
1826 |            commit
1827 |            info <-
1828 |                     (pure  AutoImplicit <* decoratedKeyword fname "auto"
1829 |                 <|> (decoratedKeyword fname "default" *> DefImplicit <$> simpleExpr fname indents)
1830 |                 <|> pure      Implicit)
1831 |            params <- pibindListName fname indents
1832 |            decoratedSymbol fname "}"
1833 |            pure $ MkPBinder info params
1834 |
1835 |   ||| Record parameter, can be either a typed binder or a name
1836 |   ||| BNF:
1837 |   ||| recordParam := typedArg | name
1838 |   recordParam : Rule PBinder
1839 |   recordParam
1840 |       = typedArg
1841 |     <|> do n <- fcBounds (decoratedSimpleBinderUName fname)
1842 |            pure (MkFullBinder Explicit top n $ PInfer n.fc)
1843 |
1844 |   -- A record without a where is a forward declaration
1845 |   recordBody : String -> WithDefault Visibility Private ->
1846 |                Maybe TotalReq ->
1847 |                Int ->
1848 |                Name ->
1849 |                List PBinder ->
1850 |                EmptyRule PDeclNoFC
1851 |   recordBody doc vis mbtot col n params
1852 |       = do atEndIndent indents
1853 |            pure (PRecord doc vis mbtot (MkPRecordLater n params))
1854 |     <|> do mustWork $ decoratedKeyword fname "where"
1855 |            opts <- dataOpts fname
1856 |            dcflds <- blockWithOptHeaderAfter col
1857 |                        (\ idt => recordConstructor fname <* atEnd idt)
1858 |                        fieldDecl
1859 |            pure (PRecord doc vis mbtot
1860 |                   (MkPRecord n params opts (fst dcflds) (snd dcflds)))
1861 |
1862 |   recordDecl : Rule PDeclNoFC
1863 |   recordDecl
1864 |       = do doc         <- optDocumentation fname
1865 |            (vis,mbtot) <- dataVisOpt fname
1866 |            col         <- column
1867 |            decoratedKeyword fname "record"
1868 |            n       <- mustWork (decoratedDataTypeName fname)
1869 |            paramss <- many (continue indents >> recordParam)
1870 |            recordBody doc vis mbtot col n paramss
1871 |
1872 |   ||| Parameter blocks
1873 |   ||| BNF:
1874 |   ||| paramDecls := 'parameters' (oldParamDecls | newParamDecls) indentBlockDefs
1875 |   paramDecls : Rule PDeclNoFC
1876 |   paramDecls = do
1877 |            startCol <- column
1878 |            b1 <- decoratedKeyword fname "parameters"
1879 |            commit
1880 |            args <- Right <$> newParamDecls
1881 |                <|> Left <$> withWarning "DEPRECATED: old parameter syntax https://github.com/idris-lang/Idris2/issues/3447" oldParamDecls
1882 |            commit
1883 |            declarations <- nonEmptyBlockAfter startCol (topDecl fname)
1884 |            pure (PParameters args
1885 |                     (collectDefs (forget declarations)))
1886 |
1887 |     where
1888 |       oldParamDecls : Rule (List1 PlainBinder)
1889 |       oldParamDecls
1890 |           = parens fname $ sepBy1 (decoratedSymbol fname ",") plainBinder
1891 |
1892 |       newParamDecls : Rule (List1 PBinder)
1893 |       newParamDecls = some typedArg
1894 |
1895 |
1896 |   definition : Rule PDeclNoFC
1897 |   definition
1898 |       = do nd <- clause 0 Nothing fname indents
1899 |            pure (PDef (singleton nd))
1900 |
1901 |   operatorBindingKeyword : EmptyRule BindingModifier
1902 |   operatorBindingKeyword
1903 |     =   (decoratedKeyword fname "autobind" >> pure Autobind)
1904 |     <|> (decoratedKeyword fname "typebind" >> pure Typebind)
1905 |     <|> pure NotBinding
1906 |
1907 |   fixDecl : Rule PDecl
1908 |   fixDecl
1909 |       = do vis <- exportVisibility fname
1910 |            binding <- operatorBindingKeyword
1911 |            b <- fcBounds (do fixity <- decorate fname Keyword $ fix
1912 |                              commit
1913 |                              prec <- decorate fname Keyword $ intLit
1914 |                              ops <- sepBy1 (decoratedSymbol fname ",") iOperator
1915 |                              pure (MkPFixityData vis binding fixity (fromInteger prec) ops)
1916 |                        )
1917 |            pure (map PFixity b)
1918 |
1919 | -- The compiler cannot infer the values for c1 and c2 so I had to write it
1920 | -- this way.
1921 | -- - Andre
1922 | cgDirectiveDecl : Rule PDeclNoFC
1923 | cgDirectiveDecl
1924 |   = (>>=) {c1 = True, c2 = False} cgDirective $ \dir =>
1925 |       let (cg1, cg2) = span isAlphaNum dir
1926 |       in the (EmptyRule PDeclNoFC) $ pure $
1927 |             PDirective (CGAction cg1 (stripBraces (trim cg2)))
1928 |
1929 | -- Declared at the top
1930 | -- topDecl : OriginDesc -> IndentInfo -> Rule (List PDecl)
1931 | topDecl fname indents
1932 |       -- Specifically check if the user has attempted to use a reserved identifier to begin their declaration to give improved error messages.
1933 |       -- i.e. the claim "String : Type" is a parse error, but the underlying reason may not be clear to new users.
1934 |     = do id <- anyReservedIdent
1935 |          the (Rule PDecl) $ fatalLoc id.bounds "Cannot begin a declaration with a reserved identifier"
1936 |   <|> fcBounds dataDecl
1937 |   <|> fcBounds (PClaim <$> localClaim)
1938 |   <|> fcBounds (PDirective <$> directive)
1939 |   <|> fcBounds implDecl
1940 |   <|> fcBounds definition
1941 |   <|> fixDecl
1942 |   <|> fcBounds ifaceDecl
1943 |   <|> fcBounds recordDecl
1944 |   <|> fcBounds namespaceDecl
1945 |   <|> fcBounds failDecls
1946 |   <|> fcBounds mutualDecls
1947 |   <|> fcBounds paramDecls
1948 |   <|> fcBounds usingDecls
1949 |   <|> fcBounds builtinDecl
1950 |   <|> fcBounds runElabDecl
1951 |   <|> fcBounds transformDecl
1952 |   <|> fcBounds cgDirectiveDecl
1953 |       -- If the user tries to add import after some declarations, then show a more informative error.
1954 |   <|> do kw <- bounds $ keyword "import"
1955 |          the (Rule PDecl) $ fatalLoc kw.bounds "Imports must go before any declarations or directives"
1956 |       -- If the user tried to begin a declaration with any other keyword, then show a more informative error.
1957 |   <|> do kw <- bounds anyKeyword
1958 |          the (Rule PDecl) $ fatalLoc kw.bounds "Keyword '\{kw.val}' is not a valid start to a declaration"
1959 |   <|> fatalError "Couldn't parse declaration"
1960 |
1961 | -- All the clauses get parsed as one-clause definitions. Collect any
1962 | -- neighbouring clauses into one definition. This might mean merging two
1963 | -- functions which are different, if there are forward declarations,
1964 | -- but we'll split them in Desugar.idr. We can't do this now, because we
1965 | -- haven't resolved operator precedences yet.
1966 | -- Declared at the top.
1967 | -- collectDefs : List PDecl -> List PDecl
1968 | collectDefs [] = []
1969 | collectDefs (def@(MkWithData _ (PDef cs)) :: ds)
1970 |     = let (csWithFC, rest) = spanBy isPDef ds
1971 |           cs' = cs ++ concat (map val csWithFC)
1972 |           annot' = foldr {t=List}
1973 |                    (\fc1, fc2 => fromMaybe EmptyFC (mergeFC fc1 fc2))
1974 |                    def.fc
1975 |                    (map (.fc) csWithFC)
1976 |       in
1977 |           MkFCVal annot' (PDef cs') :: assert_total (collectDefs rest)
1978 | collectDefs (MkWithData annot (PNamespace ns nds) :: ds)
1979 |     = MkWithData annot (PNamespace ns (collectDefs nds)) :: collectDefs ds
1980 | collectDefs (MkWithData fc (PMutual nds) :: ds)
1981 |     = MkWithData fc (PMutual (collectDefs nds)) :: collectDefs ds
1982 | collectDefs (d :: ds)
1983 |     = d :: collectDefs ds
1984 |
1985 | export
1986 | import_ : OriginDesc -> IndentInfo -> Rule Import
1987 | import_ fname indents
1988 |     = do b <- bounds (do decoratedKeyword fname "import"
1989 |                          reexp <- option False (decoratedKeyword fname "public" $> True)
1990 |                          ns <- decorate fname Module $ mustWork moduleIdent
1991 |                          nsAs <- option (miAsNamespace ns)
1992 |                                         (do decorate fname Keyword $ exactIdent "as"
1993 |                                             decorate fname Namespace $ mustWork namespaceId)
1994 |                          pure (reexp, ns, nsAs))
1995 |          atEnd indents
1996 |          (reexp, ns, nsAs) <- pure b.val
1997 |          pure (MkImport (boundToFC fname b) reexp ns nsAs)
1998 |
1999 | export
2000 | progHdr : OriginDesc -> EmptyRule Module
2001 | progHdr fname
2002 |     = do b <- bounds (do doc    <- optDocumentation fname
2003 |                          nspace <- option (nsAsModuleIdent mainNS)
2004 |                                      (do decoratedKeyword fname "module"
2005 |                                          decorate fname Module $ mustWork moduleIdent)
2006 |                          imports <- block (import_ fname)
2007 |                          pure (doc, nspace, imports))
2008 |          (doc, nspace, imports) <- pure b.val
2009 |          pure (MkModule (boundToFC fname b)
2010 |                         nspace imports doc [])
2011 |
2012 | export
2013 | prog : OriginDesc -> EmptyRule Module
2014 | prog fname
2015 |     = do mod <- progHdr fname
2016 |          ds <- block (topDecl fname)
2017 |          pure $ { decls := collectDefs ds} mod
2018 |
2019 | parseMode : Rule REPLEval
2020 | parseMode
2021 |      = do exactIdent "typecheck"
2022 |           pure EvalTC
2023 |    <|> do exactIdent "tc"
2024 |           pure EvalTC
2025 |    <|> do exactIdent "normalise"
2026 |           pure NormaliseAll
2027 |    <|> do exactIdent "default"
2028 |           pure NormaliseAll
2029 |    <|> do exactIdent "normal"
2030 |           pure NormaliseAll
2031 |    <|> do exactIdent "normalize" -- oh alright then
2032 |           pure NormaliseAll
2033 |    <|> do exactIdent "execute"
2034 |           pure Execute
2035 |    <|> do exactIdent "exec"
2036 |           pure Execute
2037 |    <|> do exactIdent "scheme"
2038 |           pure Scheme
2039 |
2040 | setVarOption : Rule REPLOpt
2041 | setVarOption
2042 |     = do exactIdent "eval"
2043 |          mode <- option NormaliseAll parseMode
2044 |          pure (EvalMode mode)
2045 |   <|> do exactIdent "editor"
2046 |          e <- unqualifiedName
2047 |          pure (Editor e)
2048 |   <|> do exactIdent "cg"
2049 |          c <- unqualifiedName
2050 |          pure (CG c)
2051 |
2052 | setOption : Bool -> Rule REPLOpt
2053 | setOption set
2054 |     = do exactIdent "showimplicits"
2055 |          pure (ShowImplicits set)
2056 |   <|> do exactIdent "shownamespace"
2057 |          pure (ShowNamespace set)
2058 |   <|> do exactIdent "showmachinenames"
2059 |          pure (ShowMachineNames set)
2060 |   <|> do exactIdent "showtypes"
2061 |          pure (ShowTypes set)
2062 |   <|> do exactIdent "profile"
2063 |          pure (Profile set)
2064 |   <|> do exactIdent "evaltiming"
2065 |          pure (EvalTiming set)
2066 |   <|> if set then setVarOption else fatalError "Unrecognised option"
2067 |
2068 | replCmd : List String -> Rule ()
2069 | replCmd [] = fail "Unrecognised command"
2070 | replCmd (c :: cs)
2071 |     = exactIdent c
2072 |   <|> symbol c
2073 |   <|> replCmd cs
2074 |
2075 | cmdName : String -> Rule String
2076 | cmdName str = do
2077 |   _ <- optional (symbol ":")
2078 |   terminal ("Unrecognised REPL command '" ++ str ++ "'") $
2079 |            \case
2080 |               (Ident s)       => if s == str then Just s else Nothing
2081 |               (Keyword kw)    => if kw == str then Just kw else Nothing
2082 |               (Symbol "?")    => Just "?"
2083 |               (Symbol ":?")   => Just "?"   -- `:help :?` is a special case
2084 |               _ => Nothing
2085 |
2086 | export
2087 | data CmdArg : Type where
2088 |      ||| The command takes no arguments.
2089 |      NoArg : CmdArg
2090 |
2091 |      ||| The command takes a name.
2092 |      NameArg : CmdArg
2093 |
2094 |      ||| The command takes an expression.
2095 |      ExprArg : CmdArg
2096 |
2097 |      ||| The command takes a documentation directive.
2098 |      DocArg : CmdArg
2099 |
2100 |      ||| The command takes a list of declarations
2101 |      DeclsArg : CmdArg
2102 |
2103 |      ||| The command takes a number.
2104 |      NumberArg : CmdArg
2105 |
2106 |      ||| The command takes a number or auto.
2107 |      AutoNumberArg : CmdArg
2108 |
2109 |      ||| The command takes an option.
2110 |      OptionArg : CmdArg
2111 |
2112 |      ||| The command takes a file.
2113 |      FileArg : CmdArg
2114 |
2115 |      ||| The command takes a module.
2116 |      ModuleArg : CmdArg
2117 |
2118 |      ||| The command takes a string
2119 |      StringArg : CmdArg
2120 |
2121 |      ||| The command takes a on or off.
2122 |      OnOffArg : CmdArg
2123 |
2124 |      ||| The command takes an argument documenting its name
2125 |      NamedCmdArg : String -> CmdArg -> CmdArg
2126 |
2127 |      ||| The command takes an argument documenting its default value
2128 |      WithDefaultArg : String -> CmdArg -> CmdArg
2129 |
2130 |      ||| The command takes arguments separated by commas
2131 |      CSVArg : CmdArg -> CmdArg
2132 |
2133 |      ||| The command takes multiple arguments.
2134 |      Args : List CmdArg -> CmdArg
2135 |
2136 | mutual
2137 |   covering
2138 |   showCmdArg : CmdArg -> String
2139 |   showCmdArg NoArg = ""
2140 |   showCmdArg NameArg = "name"
2141 |   showCmdArg ExprArg = "expr"
2142 |   showCmdArg DocArg = "keyword|expr"
2143 |   showCmdArg DeclsArg = "decls"
2144 |   showCmdArg NumberArg = "number"
2145 |   showCmdArg AutoNumberArg = "number|auto"
2146 |   showCmdArg OptionArg = "option"
2147 |   showCmdArg FileArg = "file"
2148 |   showCmdArg ModuleArg = "module"
2149 |   showCmdArg StringArg = "string"
2150 |   showCmdArg OnOffArg = "(on|off)"
2151 |   showCmdArg (CSVArg arg) = "[" ++ showCmdArg arg ++ "]"
2152 |   showCmdArg (WithDefaultArg value arg) = showCmdArg arg ++ "|" ++ value
2153 |   showCmdArg (NamedCmdArg name arg) = name ++ ":" ++ showCmdArg arg
2154 |   showCmdArg args@(Args _) = show args
2155 |
2156 |   export
2157 |   covering
2158 |   Show CmdArg where
2159 |     show NoArg = ""
2160 |     show OnOffArg = "(on|off)"
2161 |     show (Args args) = showSep " " (map show args)
2162 |     show arg = "<" ++ showCmdArg arg ++ ">"
2163 |
2164 | public export
2165 | knownCommands : List (String, String)
2166 | knownCommands =
2167 |   explain ["t", "type"] "Check the type of an expression" ++
2168 |   [ ("ti", "Check the type of an expression, showing implicit arguments")
2169 |   , ("printdef", "Show the definition of a pattern-matching function")
2170 |   ] ++
2171 |   explain ["s", "search"] "Search for values by type" ++
2172 |   [ ("di", "Show debugging information for a name")
2173 |   ] ++
2174 |   explain ["module", "import"] "Import an extra module" ++
2175 |   [ ("package", "Import every module of the package")
2176 |   ] ++
2177 |   explain ["q", "quit", "exit"] "Exit the Idris system" ++
2178 |   [ ("cwd", "Displays the current working directory")
2179 |   , ("cd", "Change the current working directory")
2180 |   , ("sh", "Run a shell command")
2181 |   , ("set"
2182 |     , unlines   -- FIXME: this should be a multiline string (see #2087)
2183 |       [ "Set an option"
2184 |       , "  eval                specify what evaluation mode to use:"
2185 |       , "                        typecheck|tc"
2186 |       , "                        normalise|normalize|normal"
2187 |       , "                        execute|exec"
2188 |       , "                        scheme"
2189 |       , ""
2190 |       , "  editor              specify the name of the editor command"
2191 |       , ""
2192 |       , "  cg                  specify the codegen/backend to use"
2193 |       , "                      builtin codegens are:"
2194 |       , "                        chez"
2195 |       , "                        racket"
2196 |       , "                        refc"
2197 |       , "                        node"
2198 |       , ""
2199 |       , "  showimplicits       enable displaying implicit arguments as part of the"
2200 |       , "                      output"
2201 |       , ""
2202 |       , "  shownamespace       enable displaying namespaces as part of the output"
2203 |       , ""
2204 |       , "  showmachinenames    enable displaying machine names as part of the"
2205 |       , "                      output"
2206 |       , ""
2207 |       , "  showtypes           enable displaying the type of the term as part of"
2208 |       , "                      the output"
2209 |       , ""
2210 |       , "  profile"
2211 |       , ""
2212 |       , "  evaltiming          enable timing how long evaluation takes and"
2213 |       , "                      displaying this before the printing of the output"
2214 |       ]
2215 |     )
2216 |   , ("unset", "Unset an option")
2217 |   , ("opts", "Show current options settings")
2218 |   ] ++
2219 |   explain ["c", "compile"] "Compile to an executable" ++
2220 |   [ ("exec", "Compile to an executable and run")
2221 |   , ("directive", "Set a codegen-specific directive")
2222 |   ] ++
2223 |   explain ["l", "load"] "Load a file" ++
2224 |   explain ["r", "reload"] "Reload current file" ++
2225 |   explain ["e", "edit"] "Edit current file using $EDITOR or $VISUAL" ++
2226 |   explain ["miss", "missing"] "Show missing clauses" ++
2227 |   [ ("total", "Check the totality of a name")
2228 |   , ("doc", "Show documentation for a keyword, a name, or a primitive")
2229 |   , ("browse", "Browse contents of a namespace")
2230 |   ] ++
2231 |   explain ["log", "logging"] "Set logging level" ++
2232 |   [ ("consolewidth", "Set the width of the console output (0 for unbounded) (auto by default)")
2233 |   ] ++
2234 |   explain ["colour", "color"] "Whether to use colour for the console output (enabled by default)" ++
2235 |   explain ["m", "metavars"] "Show remaining proof obligations (metavariables or holes)" ++
2236 |   [ ("typeat", "Show type of term <n> defined on line <l> and column <c>")
2237 |   ] ++
2238 |   explain ["cs", "casesplit"] "Case split term <n> defined on line <l> and column <c>" ++
2239 |   explain ["ac", "addclause"] "Add clause to term <n> defined on line <l>" ++
2240 |   explain ["ml", "makelemma"] "Make lemma for term <n> defined on line <l>" ++
2241 |   explain ["mc", "makecase"] "Make case on term <n> defined on line <l>" ++
2242 |   explain ["mw", "makewith"] "Add with expression on term <n> defined on line <l>" ++
2243 |   [ ("intro", "Introduce unambiguous constructor in hole <n> defined on line <l>")
2244 |   , ("refine", "Refine hole <h> with identifier <n> on line <l>")
2245 |   ] ++
2246 |   explain ["ps", "proofsearch"] "Search for a proof" ++
2247 |   [ ("psnext", "Show next proof")
2248 |   , ("gd", "Try to generate a definition using proof-search")
2249 |   , ("gdnext", "Show next definition")
2250 |   , ("version", "Display the Idris version")
2251 |   ] ++
2252 |   explain ["?", "h", "help"] (unlines     -- FIXME: this should be a multiline string (see #2087)
2253 |         [ "Display help text, optionally of a specific command.\n"
2254 |         , "If run without arguments, lists all the REPL commands along with their"
2255 |         , "initial line of help text.\n"
2256 |         , "More detailed help can then be obtained by running the :help command"
2257 |         , "with another command as an argument, e.g."
2258 |         , "  > :help :help"
2259 |         , "  > :help :set"
2260 |         , "(the leading ':' in the command argument is optional)"
2261 |         ] ) ++
2262 |   [ ( "let"
2263 |     , """
2264 |       Define a new value.
2265 |
2266 |       First, declare the type of your new value, e.g.
2267 |         :let myValue : List Nat
2268 |
2269 |       Then, define the value:
2270 |         :let myValue = [1, 2, 3]
2271 |
2272 |       Now the value is in scope at the REPL:
2273 |         > map (+ 2) myValue
2274 |         [3, 4, 5]
2275 |       """
2276 |     )
2277 |   ] ++
2278 |   explain ["fs", "fsearch"] """
2279 |     Search for global definitions by sketching the names distribution of the wanted type(s).
2280 |
2281 |     The parameter must be in one of the forms A -> B, A -> _, or B, where A and B are space-delimited lists of global names.
2282 |
2283 |     Idris will return all of the entries in the context that have all of the names in A
2284 |     in some argument and all of the names in B within the return type.
2285 |
2286 |     For example:
2287 |
2288 |       :fs List Maybe -> List
2289 |
2290 |     will match (among other things):
2291 |
2292 |       Prelude.List.mapMaybe : (a -> Maybe b) -> List a -> List b
2293 |
2294 |     Note that the query 'List Nat -> String' does not describe the type 'List Nat',
2295 |     rather it describes both 'List a' and 'Nat' in the arguments.
2296 |
2297 |     """
2298 |   where
2299 |     explain : List String -> String -> List (String, String)
2300 |     explain cmds expl = map (\s => (s, expl)) cmds
2301 |
2302 | public export
2303 | KnownCommand : String -> Type
2304 | KnownCommand cmd = IsJust (lookup cmd knownCommands)
2305 |
2306 | export
2307 | data ParseCmd : Type where
2308 |      ParseREPLCmd :  (cmds : List String)
2309 |                   -> {auto 0 _ : All KnownCommand cmds}
2310 |                   -> ParseCmd
2311 |
2312 |      ParseKeywordCmd :  (cmds : List String)
2313 |                      -> {auto 0 _ : All KnownCommand cmds}
2314 |                      -> ParseCmd
2315 |
2316 |      ParseIdentCmd :  (cmd : String)
2317 |                    -> {auto 0 _ : KnownCommand cmd}
2318 |                    -> ParseCmd
2319 |
2320 | public export
2321 | CommandDefinition : Type
2322 | CommandDefinition = (List String, CmdArg, String, Rule REPLCmd)
2323 |
2324 | public export
2325 | CommandTable : Type
2326 | CommandTable = List CommandDefinition
2327 |
2328 | extractNames : ParseCmd -> List String
2329 | extractNames (ParseREPLCmd names) = names
2330 | extractNames (ParseKeywordCmd keywords) = keywords
2331 | extractNames (ParseIdentCmd ident) = [ident]
2332 |
2333 | runParseCmd : ParseCmd -> Rule ()
2334 | runParseCmd (ParseREPLCmd names) = replCmd names
2335 | runParseCmd (ParseKeywordCmd keywords) = choice $ map keyword keywords
2336 | runParseCmd (ParseIdentCmd ident) = exactIdent ident
2337 |
2338 |
2339 | noArgCmd : ParseCmd -> REPLCmd -> String -> CommandDefinition
2340 | noArgCmd parseCmd command doc = (names, NoArg, doc, parse)
2341 |   where
2342 |     names : List String
2343 |     names = extractNames parseCmd
2344 |
2345 |     parse : Rule REPLCmd
2346 |     parse = do
2347 |       symbol ":"
2348 |       runParseCmd parseCmd
2349 |       pure command
2350 |
2351 | nameArgCmd : ParseCmd -> (Name -> REPLCmd) -> String -> CommandDefinition
2352 | nameArgCmd parseCmd command doc = (names, NameArg, doc, parse)
2353 |   where
2354 |     names : List String
2355 |     names = extractNames parseCmd
2356 |
2357 |     parse : Rule REPLCmd
2358 |     parse = do
2359 |       symbol ":"
2360 |       runParseCmd parseCmd
2361 |       n <- mustWork name
2362 |       pure (command n)
2363 |
2364 | stringArgCmd : ParseCmd -> (String -> REPLCmd) -> String -> CommandDefinition
2365 | stringArgCmd parseCmd command doc = (names, StringArg, doc, parse)
2366 |   where
2367 |     names : List String
2368 |     names = extractNames parseCmd
2369 |
2370 |     parse : Rule REPLCmd
2371 |     parse = do
2372 |       symbol ":"
2373 |       runParseCmd parseCmd
2374 |       s <- mustWork simpleStr
2375 |       pure (command s)
2376 |
2377 | getHelpType : EmptyRule HelpType
2378 | getHelpType = do
2379 |   optCmd <- optional $ choice $ (cmdName . fst) <$> knownCommands
2380 |   pure $
2381 |     case optCmd of
2382 |          Nothing => GenericHelp
2383 |          Just cmd => DetailedHelp $ fromMaybe "Unrecognised command '\{cmd}'"
2384 |                                   $ lookup cmd knownCommands
2385 |
2386 | helpCmd :  ParseCmd
2387 |         -> (HelpType -> REPLCmd)
2388 |         -> String
2389 |         -> CommandDefinition
2390 | helpCmd parseCmd command doc = (names, StringArg, doc, parse)
2391 |   where
2392 |     names : List String
2393 |     names = extractNames parseCmd
2394 |
2395 |     parse : Rule REPLCmd
2396 |     parse = do
2397 |       symbol ":"
2398 |       runParseCmd parseCmd
2399 |       helpType <- getHelpType
2400 |       pure (command helpType)
2401 |
2402 | moduleArgCmd : ParseCmd -> (ModuleIdent -> REPLCmd) -> String -> CommandDefinition
2403 | moduleArgCmd parseCmd command doc = (names, ModuleArg, doc, parse)
2404 |   where
2405 |     names : List String
2406 |     names = extractNames parseCmd
2407 |
2408 |     parse : Rule REPLCmd
2409 |     parse = do
2410 |       symbol ":"
2411 |       runParseCmd parseCmd
2412 |       n <- mustWork moduleIdent
2413 |       pure (command n)
2414 |
2415 | exprArgCmd : ParseCmd -> (PTerm -> REPLCmd) -> String -> CommandDefinition
2416 | exprArgCmd parseCmd command doc = (names, ExprArg, doc, parse)
2417 |   where
2418 |     names : List String
2419 |     names = extractNames parseCmd
2420 |
2421 |     parse : Rule REPLCmd
2422 |     parse = do
2423 |       symbol ":"
2424 |       runParseCmd parseCmd
2425 |       tm <- mustWork $ typeExpr pdef (Virtual Interactive) init
2426 |       pure (command tm)
2427 |
2428 | docArgCmd : ParseCmd -> (DocDirective -> REPLCmd) -> String -> CommandDefinition
2429 | docArgCmd parseCmd command doc = (names, DocArg, doc, parse)
2430 |   where
2431 |     names : List String
2432 |     names = extractNames parseCmd
2433 |
2434 |     -- by default, lazy primitives must be followed by a simpleExpr, so we have
2435 |     -- this custom parser for the doc case
2436 |     docLazyPrim : Rule PTerm
2437 |     docLazyPrim =
2438 |       let placeholeder : PTerm' Name
2439 |           placeholeder = PHole EmptyFC False "lazyDocPlaceholeder"
2440 |       in  do exactIdent "Lazy"    -- v
2441 |              pure (PDelayed EmptyFC LLazy placeholeder)
2442 |       <|> do exactIdent "Inf"     -- v
2443 |              pure (PDelayed EmptyFC LInf placeholeder)
2444 |       <|> do exactIdent "Delay"
2445 |              pure (PDelay EmptyFC placeholeder)
2446 |       <|> do exactIdent "Force"
2447 |              pure (PForce EmptyFC placeholeder)
2448 |
2449 |     parse : Rule REPLCmd
2450 |     parse = do
2451 |       symbol ":"
2452 |       runParseCmd parseCmd
2453 |       dir <- mustWork $
2454 |         AModule <$ keyword "module" <*> moduleIdent -- must be before Keyword to not be captured
2455 |         <|> Keyword <$> anyKeyword
2456 |         <|> Symbol <$> (anyReservedSymbol <* eoi
2457 |                        <|> parens (Virtual Interactive) anyReservedSymbol <* eoi)
2458 |         <|> Bracket <$> (
2459 |               IdiomBrackets <$ symbol "[|" <* symbol "|]"
2460 |               <|> NameQuote <$ symbol "`{" <* symbol "}"
2461 |               <|> TermQuote <$ symbol "`(" <* symbol ")"
2462 |               <|> DeclQuote <$ symbol "`[" <* symbol "]"
2463 |               )
2464 |         <|> APTerm <$> (
2465 |               docLazyPrim
2466 |               <|> typeExpr pdef (Virtual Interactive) init
2467 |               )
2468 |       pure (command dir)
2469 |
2470 | declsArgCmd : ParseCmd -> (List PDecl -> REPLCmd) -> String -> CommandDefinition
2471 | declsArgCmd parseCmd command doc = (names, DeclsArg, doc, parse)
2472 |   where
2473 |     names : List String
2474 |     names = extractNames parseCmd
2475 |     parse : Rule REPLCmd
2476 |     parse = do
2477 |       symbol ":"
2478 |       runParseCmd parseCmd
2479 |       tm <- mustWork $ topDecl (Virtual Interactive) init
2480 |       pure (command [tm])
2481 |
2482 | optArgCmd : ParseCmd -> (REPLOpt -> REPLCmd) -> Bool -> String -> CommandDefinition
2483 | optArgCmd parseCmd command set doc = (names, OptionArg, doc, parse)
2484 |   where
2485 |     names : List String
2486 |     names = extractNames parseCmd
2487 |
2488 |     parse : Rule REPLCmd
2489 |     parse = do
2490 |       symbol ":"
2491 |       runParseCmd parseCmd
2492 |       opt <- mustWork $ setOption set
2493 |       pure (command opt)
2494 |
2495 | numberArgCmd : ParseCmd -> (Nat -> REPLCmd) -> String -> CommandDefinition
2496 | numberArgCmd parseCmd command doc = (names, NumberArg, doc, parse)
2497 |   where
2498 |     names : List String
2499 |     names = extractNames parseCmd
2500 |
2501 |     parse : Rule REPLCmd
2502 |     parse = do
2503 |       symbol ":"
2504 |       runParseCmd parseCmd
2505 |       i <- mustWork intLit
2506 |       pure (command (fromInteger i))
2507 |
2508 | autoNumberArgCmd : ParseCmd -> (Maybe Nat -> REPLCmd) -> String -> CommandDefinition
2509 | autoNumberArgCmd parseCmd command doc = (names, AutoNumberArg, doc, parse)
2510 |   where
2511 |     names : List String
2512 |     names = extractNames parseCmd
2513 |
2514 |     autoNumber : Rule (Maybe Nat)
2515 |     autoNumber = Nothing <$ keyword "auto"
2516 |              <|> Just . fromInteger <$> intLit
2517 |
2518 |     parse : Rule REPLCmd
2519 |     parse = do
2520 |       symbol ":"
2521 |       runParseCmd parseCmd
2522 |       mi <- mustWork autoNumber
2523 |       pure (command mi)
2524 |
2525 | onOffArgCmd : ParseCmd -> (Bool -> REPLCmd) -> String -> CommandDefinition
2526 | onOffArgCmd parseCmd command doc = (names, OnOffArg, doc, parse)
2527 |   where
2528 |     names : List String
2529 |     names = extractNames parseCmd
2530 |
2531 |     parse : Rule REPLCmd
2532 |     parse = do
2533 |       symbol ":"
2534 |       runParseCmd parseCmd
2535 |       i <- mustWork onOffLit
2536 |       pure (command i)
2537 |
2538 | compileArgsCmd : ParseCmd -> (PTerm -> String -> REPLCmd) -> String -> CommandDefinition
2539 | compileArgsCmd parseCmd command doc
2540 |     = (names, Args [FileArg, ExprArg], doc, parse)
2541 |   where
2542 |     names : List String
2543 |     names = extractNames parseCmd
2544 |
2545 |     parse : Rule REPLCmd
2546 |     parse = do
2547 |       symbol ":"
2548 |       runParseCmd parseCmd
2549 |       n <- mustWork unqualifiedName
2550 |       tm <- mustWork $ expr pdef (Virtual Interactive) init
2551 |       pure (command tm n)
2552 |
2553 | loggingArgCmd : ParseCmd -> (Maybe LogLevel -> REPLCmd) -> String -> CommandDefinition
2554 | loggingArgCmd parseCmd command doc = (names, Args [StringArg, NumberArg], doc, parse) where
2555 |
2556 |   names : List String
2557 |   names = extractNames parseCmd
2558 |
2559 |   parse : Rule REPLCmd
2560 |   parse = do
2561 |     symbol ":"
2562 |     runParseCmd parseCmd
2563 |     lvl <- mustWork $ logLevel (Virtual Interactive)
2564 |     pure (command lvl)
2565 |
2566 | editLineNameArgCmd : ParseCmd -> (Bool -> Int -> Name -> EditCmd) -> String -> CommandDefinition
2567 | editLineNameArgCmd parseCmd command doc = (names, Args [NamedCmdArg "l" NumberArg, NamedCmdArg "n" StringArg], doc, parse) where
2568 |
2569 |   names : List String
2570 |   names = extractNames parseCmd
2571 |
2572 |   parse : Rule REPLCmd
2573 |   parse = do
2574 |     symbol ":"
2575 |     runParseCmd parseCmd
2576 |     upd <- option False (symbol "!" $> True)
2577 |     line <- fromInteger <$> mustWork intLit
2578 |     n <- mustWork name
2579 |     pure (Editing $ command upd line n)
2580 |
2581 | editLineColNameArgCmd : ParseCmd -> (Bool -> Int -> Int -> Name -> EditCmd) -> String -> CommandDefinition
2582 | editLineColNameArgCmd parseCmd command doc =
2583 |   ( names
2584 |   , Args [ NamedCmdArg "l" NumberArg
2585 |          , NamedCmdArg "c" NumberArg
2586 |          , NamedCmdArg "n" StringArg
2587 |          ]
2588 |   , doc
2589 |   , parse
2590 |   ) where
2591 |
2592 |   names : List String
2593 |   names = extractNames parseCmd
2594 |
2595 |   parse : Rule REPLCmd
2596 |   parse = do
2597 |     symbol ":"
2598 |     runParseCmd parseCmd
2599 |     upd <- option False (symbol "!" $> True)
2600 |     line <- fromInteger <$> mustWork intLit
2601 |     col <- fromInteger <$> mustWork intLit
2602 |     n <- mustWork name
2603 |     pure (Editing $ command upd line col n)
2604 |
2605 | editLineNamePTermArgCmd : ParseCmd -> (Bool -> Int -> Name -> PTerm -> EditCmd) -> String -> CommandDefinition
2606 | editLineNamePTermArgCmd parseCmd command doc =
2607 |   ( names
2608 |   , Args [ NamedCmdArg "l" NumberArg
2609 |          , NamedCmdArg "h" StringArg
2610 |          , NamedCmdArg "e" ExprArg
2611 |          ]
2612 |   , doc
2613 |   , parse
2614 |   ) where
2615 |
2616 |   names : List String
2617 |   names = extractNames parseCmd
2618 |
2619 |   parse : Rule REPLCmd
2620 |   parse = do
2621 |     symbol ":"
2622 |     runParseCmd parseCmd
2623 |     upd <- option False (symbol "!" $> True)
2624 |     line <- fromInteger <$> mustWork intLit
2625 |     h <- mustWork name
2626 |     n <- mustWork $ typeExpr pdef (Virtual Interactive) init
2627 |     pure (Editing $ command upd line h n)
2628 |
2629 | editLineNameCSVArgCmd : ParseCmd
2630 |                        -> (Bool -> Int -> Name -> List Name -> EditCmd)
2631 |                        -> String
2632 |                        -> CommandDefinition
2633 | editLineNameCSVArgCmd parseCmd command doc =
2634 |   ( names
2635 |   , Args [ NamedCmdArg "l" NumberArg
2636 |          , NamedCmdArg "n" StringArg
2637 |          , NamedCmdArg "h" (CSVArg NameArg)
2638 |          ]
2639 |   , doc
2640 |   , parse
2641 |   ) where
2642 |
2643 |   names : List String
2644 |   names = extractNames parseCmd
2645 |
2646 |   parse : Rule REPLCmd
2647 |   parse = do
2648 |     symbol ":"
2649 |     runParseCmd parseCmd
2650 |     upd <- option False (symbol "!" $> True)
2651 |     line <- fromInteger <$> mustWork intLit
2652 |     n <- mustWork name
2653 |     hints <- mustWork $ sepBy (symbol ",") name
2654 |     pure (Editing $ command upd line n hints)
2655 |
2656 | editLineNameOptionArgCmd : ParseCmd
2657 |                         -> (Bool -> Int -> Name -> Nat -> EditCmd)
2658 |                         -> String
2659 |                         -> CommandDefinition
2660 | editLineNameOptionArgCmd parseCmd command doc =
2661 |   ( names
2662 |   , Args [ NamedCmdArg "l" NumberArg
2663 |          , NamedCmdArg "n" StringArg
2664 |          , NamedCmdArg "r" (WithDefaultArg "0" NumberArg)
2665 |          ]
2666 |   , doc
2667 |   , parse
2668 |   ) where
2669 |
2670 |   names : List String
2671 |   names = extractNames parseCmd
2672 |
2673 |   parse : Rule REPLCmd
2674 |   parse = do
2675 |     symbol ":"
2676 |     runParseCmd parseCmd
2677 |     upd <- option False (symbol "!" $> True)
2678 |     line <- fromInteger <$> mustWork intLit
2679 |     n <- mustWork name
2680 |     nreject <- fromInteger <$> option 0 intLit
2681 |     pure (Editing $ command upd line n nreject)
2682 |
2683 | firstHelpLine : (cmd : String) -> {auto 0 _ : KnownCommand cmd} -> String
2684 | firstHelpLine cmd =
2685 |   head . (split ((==) '\n')) $
2686 |   fromMaybe "Failed to look up '\{cmd}' (SHOULDN'T HAPPEN!)" $
2687 |   lookup cmd knownCommands
2688 |
2689 | export
2690 | parserCommandsForHelp : CommandTable
2691 | parserCommandsForHelp =
2692 |   [ exprArgCmd (ParseREPLCmd ["t", "type"]) Check (firstHelpLine "t")
2693 |   , exprArgCmd (ParseREPLCmd ["ti"]) CheckWithImplicits (firstHelpLine "ti")
2694 |   , exprArgCmd (ParseREPLCmd ["printdef"]) PrintDef (firstHelpLine "printdef")
2695 |   , exprArgCmd (ParseREPLCmd ["s", "search"]) TypeSearch (firstHelpLine "s")
2696 |   , nameArgCmd (ParseIdentCmd "di") DebugInfo (firstHelpLine "di")
2697 |   , moduleArgCmd (ParseKeywordCmd ["module", "import"]) ImportMod (firstHelpLine "module")
2698 |   , stringArgCmd (ParseREPLCmd ["package"]) ImportPackage (firstHelpLine "package")
2699 |   , noArgCmd (ParseREPLCmd ["q", "quit", "exit"]) Quit (firstHelpLine "q")
2700 |   , noArgCmd (ParseREPLCmd ["cwd"]) CWD (firstHelpLine "cwd")
2701 |   , stringArgCmd (ParseREPLCmd ["cd"]) CD (firstHelpLine "cd")
2702 |   , stringArgCmd (ParseREPLCmd ["sh"]) RunShellCommand (firstHelpLine "sh")
2703 |   , optArgCmd (ParseIdentCmd "set") SetOpt True (firstHelpLine "set")
2704 |   , optArgCmd (ParseIdentCmd "unset") SetOpt False (firstHelpLine "unset")
2705 |   , noArgCmd (ParseREPLCmd ["opts"]) GetOpts (firstHelpLine "opts")
2706 |   , compileArgsCmd (ParseREPLCmd ["c", "compile"]) Compile (firstHelpLine "c")
2707 |   , exprArgCmd (ParseIdentCmd "exec") Exec (firstHelpLine "exec")
2708 |   , stringArgCmd (ParseIdentCmd "directive") CGDirective (firstHelpLine "directive")
2709 |   , stringArgCmd (ParseREPLCmd ["l", "load"]) Load (firstHelpLine "l")
2710 |   , noArgCmd (ParseREPLCmd ["r", "reload"]) Reload (firstHelpLine "r")
2711 |   , noArgCmd (ParseREPLCmd ["e", "edit"]) Edit (firstHelpLine "e")
2712 |   , nameArgCmd (ParseREPLCmd ["miss", "missing"]) Missing (firstHelpLine "miss")
2713 |   , nameArgCmd (ParseKeywordCmd ["total"]) Total (firstHelpLine "total")
2714 |   , docArgCmd (ParseIdentCmd "doc") Doc (firstHelpLine "doc")
2715 |   , moduleArgCmd (ParseIdentCmd "browse") (Browse . miAsNamespace) (firstHelpLine "browse")
2716 |   , loggingArgCmd (ParseREPLCmd ["log", "logging"]) SetLog (firstHelpLine "log")
2717 |   , autoNumberArgCmd (ParseREPLCmd ["consolewidth"]) SetConsoleWidth (firstHelpLine "consolewidth")
2718 |   , onOffArgCmd (ParseREPLCmd ["colour", "color"]) SetColor (firstHelpLine "colour")
2719 |   , noArgCmd (ParseREPLCmd ["m", "metavars"]) Metavars (firstHelpLine "m")
2720 |   , editLineColNameArgCmd (ParseREPLCmd ["typeat"]) (const TypeAt) (firstHelpLine "typeat")
2721 |   , editLineColNameArgCmd (ParseREPLCmd ["cs", "casesplit"]) CaseSplit (firstHelpLine "cs")
2722 |   , editLineNameArgCmd (ParseREPLCmd ["ac", "addclause"]) AddClause (firstHelpLine "ac")
2723 |   , editLineNameArgCmd (ParseREPLCmd ["ml", "makelemma"]) MakeLemma (firstHelpLine "ml")
2724 |   , editLineNameArgCmd (ParseREPLCmd ["mc", "makecase"]) MakeCase (firstHelpLine "mc")
2725 |   , editLineNameArgCmd (ParseREPLCmd ["mw", "makewith"]) MakeWith (firstHelpLine "mw")
2726 |   , editLineNameArgCmd (ParseREPLCmd ["intro"]) Intro (firstHelpLine "intro")
2727 |   , editLineNamePTermArgCmd (ParseREPLCmd ["refine"]) Refine (firstHelpLine "refine")
2728 |   , editLineNameCSVArgCmd (ParseREPLCmd ["ps", "proofsearch"]) ExprSearch (firstHelpLine "ps")
2729 |   , noArgCmd (ParseREPLCmd ["psnext"]) (Editing ExprSearchNext) (firstHelpLine "psnext")
2730 |   , editLineNameOptionArgCmd (ParseREPLCmd ["gd"]) GenerateDef (firstHelpLine "gd")
2731 |   , noArgCmd (ParseREPLCmd ["gdnext"]) (Editing GenerateDefNext) (firstHelpLine "gdnext")
2732 |   , noArgCmd (ParseREPLCmd ["version"]) ShowVersion (firstHelpLine "version")
2733 |   , helpCmd (ParseREPLCmd ["?", "h", "help"]) Help (firstHelpLine "?")
2734 |   , declsArgCmd (ParseKeywordCmd ["let"]) NewDefn (firstHelpLine "let")
2735 |   , exprArgCmd (ParseREPLCmd ["fs", "fsearch"]) FuzzyTypeSearch (firstHelpLine "fs")
2736 |   ]
2737 |
2738 | export
2739 | help : List (List String, CmdArg, String)
2740 | help = (["<expr>"], NoArg, "Evaluate an expression") ::
2741 |          map (\ (names, args, text, _) =>
2742 |                (map (":" ++) names, args, text)) parserCommandsForHelp
2743 |
2744 | nonEmptyCommand : Rule REPLCmd
2745 | nonEmptyCommand =
2746 |   choice (map (\ (_, _, _, parser) => parser) parserCommandsForHelp)
2747 |
2748 | eval : Rule REPLCmd
2749 | eval = do
2750 |   tm <- typeExpr pdef (Virtual Interactive) init
2751 |   pure (Eval tm)
2752 |
2753 | export
2754 | aPTerm : Rule PTerm
2755 | aPTerm = typeExpr pdef (Virtual Interactive) init
2756 |
2757 | export
2758 | command : EmptyRule REPLCmd
2759 | command
2760 |     = eoi $> NOP
2761 |   <|> nonEmptyCommand
2762 |   <|> (do symbol ":?" -- special case, :? doesn't fit into above scheme
2763 |           helpType <- getHelpType
2764 |           pure $ Help helpType)
2765 |   <|> eval
2766 |