@@ -16,8 +16,10 @@ import Idris.Parser.Helpers
16import Prelude hiding (pi)
16import Prelude hiding (pi)
18import Control.Applicative
18import Control.Applicative
19+import Control.Arrow (first)
19import Control.Monad
20import Control.Monad
20import Control.Monad.State.Strict
21import Control.Monad.State.Strict
22+import Data.Char (isAlpha)
21import Data.List
23import Data.List
22import Text.Parser.Expression
24import Text.Parser.Expression
23import Text.Trifecta hiding (char, charLiteral, natural, span, string,
25import Text.Trifecta hiding (char, charLiteral, natural, span, string,
@@ -29,56 +31,85 @@ table :: [FixDecl] -> OperatorTable IdrisParser PTerm
29table fixes
31table fixes
30 = [[prefix "-" (\fc x -> PApp fc (PRef fc [fc] (sUN "negate")) [pexp x])]] ++
32 = [[prefix "-" (\fc x -> PApp fc (PRef fc [fc] (sUN "negate")) [pexp x])]] ++
31 toTable (reverse fixes) ++
33 toTable (reverse fixes) ++
32− [[backtick],
34+ [[noFixityBacktickOperator],
33− [binary "$" (\fc x y -> flatten $ PApp fc x [pexp y]) AssocRight],
35+ [binary "$" AssocRight $ \fc _ x y -> flatten $ PApp fc x [pexp y]],
34− [binary "=" (\fc x y -> PApp fc (PRef fc [fc] eqTy) [pexp x, pexp y]) AssocLeft],
36+ [binary "=" AssocLeft $ \fc _ x y -> PApp fc (PRef fc [fc] eqTy) [pexp x, pexp y]],
35− [nofixityoperator]]
37+ [noFixityOperator]]
37− flatten :: PTerm -> PTerm -- flatten application
39+ flatten :: PTerm -> PTerm -- flatten application
38 flatten (PApp fc (PApp _ f as) bs) = flatten (PApp fc f (as ++ bs))
40 flatten (PApp fc (PApp _ f as) bs) = flatten (PApp fc f (as ++ bs))
39− flatten t = t
41+ flatten t = t
41−
43+ noFixityBacktickOperator :: Operator IdrisParser PTerm
44+ noFixityBacktickOperator = flip Infix AssocNone $ do
45+ (n, fc) <- backtickOperator
46+ return $ \x y -> PApp fc (PRef fc [fc] n) [pexp x, pexp y]
48+ -- | Operator without fixity (throws an error)
49+ noFixityOperator :: Operator IdrisParser PTerm
50+ noFixityOperator = flip Infix AssocNone $ do
52+ op <- try symbolicOperator
53+ unexpected $ "Operator without known fixity: " ++ op
42−-- | Calculates table for fixity declarations
55+ -- | Calculates table for fixity declarations
43−toTable :: [FixDecl] -> OperatorTable IdrisParser PTerm
56+ toTable :: [FixDecl] -> OperatorTable IdrisParser PTerm
44−toTable fs = map (map toBin)
45− (groupBy (\ (Fix x _) (Fix y _) -> prec x == prec y) fs)
57+ toTable fs = map (map toBin) (groupBy (\ (Fix x _) (Fix y _) -> prec x == prec y) fs)
46− where toBin (Fix (PrefixN _) op) = prefix op
59+ toBin (Fix (PrefixN _) op) = prefix op $ \fc x ->
47− (\fc x -> PApp fc (PRef fc [] (sUN op)) [pexp x])
60+ PApp fc (PRef fc [] (sUN op)) [pexp x]
48− toBin (Fix f op)
61+ toBin (Fix f op) = binary op (assoc f) $ \fc n x y ->
49− = binary op (\fc x y -> PApp fc (PRef fc [] (sUN op)) [pexp x,pexp y]) (assoc f)
62+ PApp fc (PRef fc [] n) [pexp x,pexp y]
50− assoc (Infixl _) = AssocLeft
64+ assoc (Infixl _) = AssocLeft
51− assoc (Infixr _) = AssocRight
65+ assoc (Infixr _) = AssocRight
52− assoc (InfixN _) = AssocNone
66+ assoc (InfixN _) = AssocNone
54−-- | Binary operator
68+ isBacktick :: String -> Bool
69+ isBacktick (c : _) = c == '_' || isAlpha c
55−binary :: String -> (FC -> PTerm -> PTerm -> PTerm) -> Assoc -> Operator IdrisParser PTerm
72+ binary :: String -> Assoc -> (FC -> Name -> PTerm -> PTerm -> PTerm) -> Operator IdrisParser PTerm
56−binary name f = Infix (do indentPropHolds gtProp
73+ binary name assoc f
74+ | isBacktick name = flip Infix assoc $ try $ do
75+ (n, fc) <- backtickOperator
76+ guard $ show (nsroot n) == name
78+ | otherwise = flip Infix assoc $ do
57− fc <- reservedOpFC name
80+ fc <- reservedOpFC name
58− indentPropHolds gtProp
81+ indentGt
59− return (f fc))
82+ return $ f fc (sUN name)
62−prefix :: String -> (FC -> PTerm -> PTerm) -> Operator IdrisParser PTerm
84+ prefix :: String -> (FC -> PTerm -> PTerm) -> Operator IdrisParser PTerm
63−prefix name f = Prefix (do reservedOp name
85+ prefix name f = Prefix (do reservedOp name
64− fc <- getFC
86+ fc <- getFC
65− indentPropHolds gtProp
87+ indentGt
66− return (f fc))
88+ return (f fc))
68−-- | Backtick operator
90+{- | Parses a function used as an operator -- enclosed in backticks
69−backtick :: Operator IdrisParser PTerm
70−backtick = Infix (do indentPropHolds gtProp
71− lchar '`'; (n, fc) <- fnName
73− indentPropHolds gtProp
74− return (\x y -> PApp fc (PRef fc [fc] n) [pexp x, pexp y])) AssocNone
76−-- | Operator without fixity (throws an error)
77−nofixityoperator :: Operator IdrisParser PTerm
78−nofixityoperator = Infix (do indentPropHolds gtProp
80− unexpected $ "Operator without known fixity: " ++ op) AssocNone
98+backtickOperator :: IdrisParser (Name, FC)
99+backtickOperator = between (indentGt *> lchar '`') (indentGt *> lchar '`') name
101+{- | Parses an operator name (either a symbolic name or a backtick-quoted name)
110+operatorName :: IdrisParser (Name, FC)
111+operatorName = first sUN <$> symbolicOperatorFC
112+ <|> backtickOperator
83{- | Parses an operator in function position i.e. enclosed by `()', with an
114{- | Parses an operator in function position i.e. enclosed by `()', with an
84 optional namespace
115 optional namespace
@@ -96,7 +127,7 @@ operatorFront = try (do (FC f (l, c) _) <- getFC
96 op <- lchar '(' *> reservedOp "=" <* lchar ')'
127 op <- lchar '(' *> reservedOp "=" <* lchar ')'
97 return (eqTy, FC f (l, c) (l, c+3)))
128 return (eqTy, FC f (l, c) (l, c+3)))
98 <|> maybeWithNS (do (FC f (l, c) _) <- getFC
129 <|> maybeWithNS (do (FC f (l, c) _) <- getFC
99− op <- lchar '(' *> operator
130+ op <- lchar '(' *> symbolicOperator
100 (FC _ _ (l', c')) <- getFC
131 (FC _ _ (l', c')) <- getFC
101 lchar ')'
132 lchar ')'
102 return (op, (FC f (l, c) (l', c' + 1)))) False []
133 return (op, (FC f (l, c) (l', c' + 1)))) False []
@@ -120,7 +151,7 @@ Fixity ::=
120fixity :: IdrisParser PDecl
151fixity :: IdrisParser PDecl
121fixity = do pushIndent
152fixity = do pushIndent
122 f <- fixityType; i <- fst <$> natural;
153 f <- fixityType; i <- fst <$> natural;
123− ops <- sepBy1 operator (lchar ',')
154+ ops <- sepBy1 (show . nsroot . fst <$> operatorName) (lchar ',')
124 terminator
155 terminator
125 let prec = fromInteger i
156 let prec = fromInteger i
126 istate <- get
157 istate <- get
@@ -137,14 +168,15 @@ fixity = do pushIndent
137 else fail $ concatMap (\(f, (x:xs)) -> "Illegal redeclaration of fixity:\n\t\""
168 else fail $ concatMap (\(f, (x:xs)) -> "Illegal redeclaration of fixity:\n\t\""
138 ++ show f ++ "\" overrides \"" ++ show x ++ "\"") ill
169 ++ show f ++ "\" overrides \"" ++ show x ++ "\"") ill
139 <?> "fixity declaration"
170 <?> "fixity declaration"
140− where alreadyDeclared :: [FixDecl] -> FixDecl -> (FixDecl, [FixDecl])
172+ alreadyDeclared :: [FixDecl] -> FixDecl -> (FixDecl, [FixDecl])
141− alreadyDeclared fs f = (f, filter ((extractName f ==) . extractName) fs)
173+ alreadyDeclared fs f = (f, filter ((extractName f ==) . extractName) fs)
143− checkValidity :: (FixDecl, [FixDecl]) -> Bool
175+ checkValidity :: (FixDecl, [FixDecl]) -> Bool
144− checkValidity (f, fs) = all (== f) fs
176+ checkValidity (f, fs) = all (== f) fs
146− extractName :: FixDecl -> String
178+ extractName :: FixDecl -> String
147− extractName (Fix _ n) = n
179+ extractName (Fix _ n) = n
149-- | Check that a declaration of an operator also has fixity declared
181-- | Check that a declaration of an operator also has fixity declared
150checkDeclFixity :: IdrisParser PDecl -> IdrisParser PDecl
182checkDeclFixity :: IdrisParser PDecl -> IdrisParser PDecl