2Module : Idris.Parser.Ops
3Description : Parser for operators and fixity declarations.
6Maintainer : The Idris Community.
8{-# LANGUAGE GeneralizedNewtypeDeriving, ConstraintKinds, PatternGuards #-}
9module Idris.Parser.Ops where
11import Prelude hiding (pi)
13import Text.Trifecta.Delta
14import Text.Trifecta hiding (span, stringLiteral, charLiteral, natural, symbol, char, string, whiteSpace)
15import Text.Parser.LookAhead
16import Text.Parser.Expression
17import qualified Text.Parser.Token as Tok
18import qualified Text.Parser.Char as Chr
19import qualified Text.Parser.Token.Highlight as Hi
22import Idris.Parser.Helpers
26import Control.Applicative
28import Control.Monad.State.Strict
31import qualified Data.List.Split as Spl
35import qualified Data.HashSet as HS
36import qualified Data.Text as T
37import qualified Data.ByteString.UTF8 as UTF8
41-- | Creates table for fixity declarations to build expression parser
42-- using pre-build and user-defined operator/fixity declarations
43table :: [FixDecl] -> OperatorTable IdrisParser PTerm
45 = [[prefix "-" (\fc x -> PApp fc (PRef fc [fc] (sUN "negate")) [pexp x])]] ++
46 toTable (reverse fixes) ++
48 [binary "$" (\fc x y -> flatten $ PApp fc x [pexp y]) AssocRight],
49 [binary "=" (\fc x y -> PApp fc (PRef fc [fc] eqTy) [pexp x, pexp y]) AssocLeft],
52 flatten :: PTerm -> PTerm -- flatten application
53 flatten (PApp fc (PApp _ f as) bs) = flatten (PApp fc f (as ++ bs))
57-- | Calculates table for fixity declarations
58toTable :: [FixDecl] -> OperatorTable IdrisParser PTerm
59toTable fs = map (map toBin)
60 (groupBy (\ (Fix x _) (Fix y _) -> prec x == prec y) fs)
61 where toBin (Fix (PrefixN _) op) = prefix op
62 (\fc x -> PApp fc (PRef fc [] (sUN op)) [pexp x])
64 = binary op (\fc x y -> PApp fc (PRef fc [] (sUN op)) [pexp x,pexp y]) (assoc f)
65 assoc (Infixl _) = AssocLeft
66 assoc (Infixr _) = AssocRight
67 assoc (InfixN _) = AssocNone
70binary :: String -> (FC -> PTerm -> PTerm -> PTerm) -> Assoc -> Operator IdrisParser PTerm
71binary name f = Infix (do indentPropHolds gtProp
72 fc <- reservedOpFC name
73 indentPropHolds gtProp
77prefix :: String -> (FC -> PTerm -> PTerm) -> Operator IdrisParser PTerm
78prefix name f = Prefix (do reservedOp name
80 indentPropHolds gtProp
84backtick :: Operator IdrisParser PTerm
85backtick = Infix (do indentPropHolds gtProp
86 lchar '`'; (n, fc) <- fnName
88 indentPropHolds gtProp
89 return (\x y -> PApp fc (PRef fc [fc] n) [pexp x, pexp y])) AssocNone
91-- | Operator without fixity (throws an error)
92nofixityoperator :: Operator IdrisParser PTerm
93nofixityoperator = Infix (do indentPropHolds gtProp
95 unexpected $ "Operator without known fixity: " ++ op) AssocNone
98{- | Parses an operator in function position i.e. enclosed by `()', with an
104 | (Identifier_t '.')? '(' Operator_t ')'
109operatorFront :: IdrisParser (Name, FC)
110operatorFront = try (do (FC f (l, c) _) <- getFC
111 op <- lchar '(' *> reservedOp "=" <* lchar ')'
112 return (eqTy, FC f (l, c) (l, c+3)))
113 <|> maybeWithNS (do (FC f (l, c) _) <- getFC
114 op <- lchar '(' *> operator
115 (FC _ _ (l', c')) <- getFC
117 return (op, (FC f (l, c) (l', c' + 1)))) False []
119{- | Parses a function (either normal name or operator)
122 FnName ::= Name | OperatorFront;
125fnName :: IdrisParser (Name, FC)
126fnName = try operatorFront <|> name <?> "function name"
128{- | Parses a fixity declaration
131 FixityType Natural_t OperatorList Terminator
135fixity :: IdrisParser PDecl
136fixity = do pushIndent
137 f <- fixityType; i <- fst <$> natural;
138 ops <- sepBy1 operator (lchar ',')
140 let prec = fromInteger i
142 let infixes = idris_infixes istate
143 let fs = map (Fix (f prec)) ops
144 let redecls = map (alreadyDeclared infixes) fs
145 let ill = filter (not . checkValidity) redecls
147 then do put (istate { idris_infixes = nub $ sort (fs ++ infixes)
148 , ibc_write = map IBCFix fs ++ ibc_write istate
151 return (PFix fc (f prec) ops)
152 else fail $ concatMap (\(f, (x:xs)) -> "Illegal redeclaration of fixity:\n\t\""
153 ++ show f ++ "\" overrides \"" ++ show x ++ "\"") ill
154 <?> "fixity declaration"
155 where alreadyDeclared :: [FixDecl] -> FixDecl -> (FixDecl, [FixDecl])
156 alreadyDeclared fs f = (f, filter ((extractName f ==) . extractName) fs)
158 checkValidity :: (FixDecl, [FixDecl]) -> Bool
159 checkValidity (f, fs) = all (== f) fs
161 extractName :: FixDecl -> String
162 extractName (Fix _ n) = n
164{- | Parses a fixity declaration type (i.e. infix or prefix, associtavity)
174fixityType :: IdrisParser (Int -> Fixity)
175fixityType = do reserved "infixl"; return Infixl
176 <|> do reserved "infixr"; return Infixr
177 <|> do reserved "infix"; return InfixN
178 <|> do reserved "prefix"; return PrefixN
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list