diff options
author | Péter Diviánszky <divipp@gmail.com> | 2016-02-12 13:41:13 +0100 |
---|---|---|
committer | Péter Diviánszky <divipp@gmail.com> | 2016-02-12 13:50:51 +0100 |
commit | 7588f4a16f8e72afbb42e0c5365e73a6d0eafa8e (patch) | |
tree | 5246912357b92b58aa8a21d72ff329678221e572 /src/LambdaCube | |
parent | 3376d76a631e5e53118b3d86cbd21a415543f593 (diff) |
refactoring (use RWS)
Diffstat (limited to 'src/LambdaCube')
-rw-r--r-- | src/LambdaCube/Compiler/Lexer.hs | 181 | ||||
-rw-r--r-- | src/LambdaCube/Compiler/Parser.hs | 27 |
2 files changed, 93 insertions, 115 deletions
diff --git a/src/LambdaCube/Compiler/Lexer.hs b/src/LambdaCube/Compiler/Lexer.hs index 9c75c675..2cbef453 100644 --- a/src/LambdaCube/Compiler/Lexer.hs +++ b/src/LambdaCube/Compiler/Lexer.hs | |||
@@ -22,41 +22,17 @@ import qualified Data.Set as Set | |||
22 | import qualified Data.Map as Map | 22 | import qualified Data.Map as Map |
23 | 23 | ||
24 | import Control.Monad.Except | 24 | import Control.Monad.Except |
25 | import Control.Monad.Reader | 25 | import Control.Monad.RWS |
26 | import Control.Monad.Writer | ||
27 | import Control.Arrow hiding ((<+>)) | 26 | import Control.Arrow hiding ((<+>)) |
28 | import Control.Applicative | 27 | import Control.Applicative |
29 | import Control.DeepSeq | 28 | import Control.DeepSeq |
30 | 29 | ||
31 | import LambdaCube.Compiler.Pretty hiding (Doc, braces, parens) | ||
32 | |||
33 | import Control.Monad.State | ||
34 | import Text.Megaparsec | 30 | import Text.Megaparsec |
35 | import Text.Megaparsec.Lexer hiding (lexeme, symbol, space, negate, symbol', indentBlock) | 31 | import Text.Megaparsec.Lexer hiding (lexeme, symbol, space, negate, symbol', indentBlock) |
36 | import Text.Megaparsec as Pr hiding (try, label, Message) | 32 | import Text.Megaparsec as Pr hiding (try, label, Message) |
37 | import Text.Megaparsec.Pos | 33 | import Text.Megaparsec.Pos |
38 | 34 | ||
39 | runParserT'' p f = flip evalStateT (initialPos f) . runParserT p f | 35 | import LambdaCube.Compiler.Pretty hiding (Doc, braces, parens) |
40 | |||
41 | runPT' p st = snd <$> flip evalStateT (initialPos ".....") (runParserT' p st) | ||
42 | |||
43 | type P = ParsecT String (StateT SourcePos InnerP) | ||
44 | |||
45 | indentMany' p = indentMS True p | ||
46 | indentMany s p = reserved s >> indentMS True p | ||
47 | indentSome s p = reserved s >> indentMS False p | ||
48 | |||
49 | indentMS null p = (if null then option [] else id) $ do | ||
50 | checkIndent | ||
51 | lvl <- indentLevel | ||
52 | (if null then many else some) $ do | ||
53 | pos <- getPosition | ||
54 | guard (sourceColumn pos == lvl) | ||
55 | local (second $ const (sourceLine pos, sourceColumn pos)) p | ||
56 | |||
57 | lexeme' sp p = checkIndent *> p <* (getPosition >>= put) <* sp | ||
58 | |||
59 | checkIndent = asks snd >>= \(r, c) -> getPosition >>= \pos -> when (sourceColumn pos <= c && sourceLine pos /= r) $ fail "wrong indentation" | ||
60 | 36 | ||
61 | -------------------------------------------------------------------------------- parser utils | 37 | -------------------------------------------------------------------------------- parser utils |
62 | 38 | ||
@@ -70,7 +46,7 @@ manyNM k n p = (:) <$> p <*> manyNM (k-1) (n-1) p | |||
70 | 46 | ||
71 | -------------------------------------------------------------------------------- parser type | 47 | -------------------------------------------------------------------------------- parser type |
72 | 48 | ||
73 | type InnerP = WriterT [PostponedCheck] (Reader ((DesugarInfo, Namespace), (Int, Int){-indentation level-})) | 49 | type P = ParsecT String (RWS ((DesugarInfo, Namespace), (Int, Int){-indentation level-}) [PostponedCheck] SourcePos) |
74 | 50 | ||
75 | type PostponedCheck = Maybe String | 51 | type PostponedCheck = Maybe String |
76 | 52 | ||
@@ -86,6 +62,11 @@ dsInfo = asks $ fst . fst | |||
86 | namespace :: P Namespace | 62 | namespace :: P Namespace |
87 | namespace = asks $ snd . fst | 63 | namespace = asks $ snd . fst |
88 | 64 | ||
65 | runP_ r f p = (\(a, s, w) -> (a, w)) $ runRWS p (r, (0, 0)) (initialPos f) | ||
66 | |||
67 | runP r f p s = runP_ r f $ runParserT p f s | ||
68 | |||
69 | runP' r f p st = runP_ r f $ runParserT' p st | ||
89 | 70 | ||
90 | -------------------------------------------------------------------------------- literals | 71 | -------------------------------------------------------------------------------- literals |
91 | 72 | ||
@@ -178,7 +159,7 @@ _ `validate` _ = mempty | |||
178 | 159 | ||
179 | sourceNameSI (RangeSI (Range a _)) = sourceName a | 160 | sourceNameSI (RangeSI (Range a _)) = sourceName a |
180 | 161 | ||
181 | sameSource r@(RangeSI {}) q@(RangeSI {}) = sourceNameSI r == sourceNameSI q | 162 | sameSource r@RangeSI{} q@RangeSI{} = sourceNameSI r == sourceNameSI q |
182 | sameSource _ _ = True | 163 | sameSource _ _ = True |
183 | 164 | ||
184 | class SourceInfo si where | 165 | class SourceInfo si where |
@@ -315,6 +296,77 @@ getFixity :: DesugarInfo -> SName -> Fixity | |||
315 | getFixity (fm, _) n = fromMaybe (InfixL, 9) $ Map.lookup n fm | 296 | getFixity (fm, _) n = fromMaybe (InfixL, 9) $ Map.lookup n fm |
316 | 297 | ||
317 | 298 | ||
299 | ----------------------------------------------------------- operators and identifiers | ||
300 | |||
301 | reservedOp name = lexeme $ try $ string name *> notFollowedBy opLetter | ||
302 | |||
303 | reserved name = lexeme $ try $ string name *> notFollowedBy identLetter | ||
304 | |||
305 | expect msg p i = i >>= \n -> if (p n) then unexpected (msg ++ " " ++ show n) else return n | ||
306 | |||
307 | identifier ident = lexeme $ try $ expect "reserved word" (`Set.member` theReservedNames) ident | ||
308 | |||
309 | operator oper = lexeme $ try $ trCons <$> expect "reserved operator" (`Set.member` theReservedOpNames) oper | ||
310 | where | ||
311 | trCons ":" = "Cons" | ||
312 | trCons x = x | ||
313 | |||
314 | theReservedOpNames = Set.fromList ["::","..","=","\\","|","<-","->","@","~","=>"] | ||
315 | |||
316 | theReservedNames = Set.fromList $ | ||
317 | ["let","in","case","of","if","then","else" | ||
318 | ,"data","type" | ||
319 | ,"class","default","deriving","do","import" | ||
320 | ,"infix","infixl","infixr","instance","module" | ||
321 | ,"newtype","where" | ||
322 | ,"primitive" | ||
323 | -- "as","qualified","hiding" | ||
324 | ] ++ | ||
325 | ["foreign","import","export","primitive" | ||
326 | ,"_ccall_","_casm_" | ||
327 | ,"forall" | ||
328 | ] | ||
329 | |||
330 | ----------------------------------------------------------- indentation, white space, symbols | ||
331 | |||
332 | checkIndent = asks snd >>= \(r, c) -> getPosition >>= \pos -> when (sourceColumn pos <= c && sourceLine pos /= r) $ fail "wrong indentation" | ||
333 | |||
334 | indentMS null p = (if null then option [] else id) $ do | ||
335 | checkIndent | ||
336 | lvl <- indentLevel | ||
337 | (if null then many else some) $ do | ||
338 | pos <- getPosition | ||
339 | guard (sourceColumn pos == lvl) | ||
340 | local (second $ const (sourceLine pos, sourceColumn pos)) p | ||
341 | |||
342 | lexeme' sp p = checkIndent *> p <* (getPosition >>= put) <* sp | ||
343 | |||
344 | lexeme = lexeme' whiteSpace | ||
345 | |||
346 | symbol = symbol' whiteSpace | ||
347 | |||
348 | symbol' sp name | ||
349 | = lexeme' sp (string name) | ||
350 | |||
351 | whiteSpace = skipMany (simpleSpace <|> oneLineComment <|> multiLineComment <?> "") | ||
352 | |||
353 | simpleSpace | ||
354 | = skipSome (satisfy isSpace) | ||
355 | |||
356 | oneLineComment | ||
357 | = try (string "--" >> many (char '-') >> notFollowedBy opLetter) | ||
358 | >> skipMany (satisfy (/= '\n')) | ||
359 | |||
360 | multiLineComment = try (string "{-") *> inCommentMulti | ||
361 | |||
362 | inCommentMulti | ||
363 | = try (() <$ string "-}") | ||
364 | <|> multiLineComment *> inCommentMulti | ||
365 | <|> skipSome (noneOf "{}-") *> inCommentMulti | ||
366 | <|> oneOf "{}-" *> inCommentMulti | ||
367 | <?> "end of comment" | ||
368 | |||
369 | |||
318 | ---------------------------------------------------------------------- | 370 | ---------------------------------------------------------------------- |
319 | ---------------------------------------------------------------------- | 371 | ---------------------------------------------------------------------- |
320 | -- modified version of | 372 | -- modified version of |
@@ -491,77 +543,4 @@ parseLit = lexeme $ charLiteral <|> stringLiteral <|> natFloat | |||
491 | ; seq n (return n) | 543 | ; seq n (return n) |
492 | } | 544 | } |
493 | 545 | ||
494 | ----------------------------------------------------------- | ||
495 | -- Operators & reserved ops | ||
496 | ----------------------------------------------------------- | ||
497 | reservedOp name = | ||
498 | lexeme $ try $ | ||
499 | do{ string name | ||
500 | ; notFollowedBy opLetter <?> ("end of " ++ show name) | ||
501 | } | ||
502 | |||
503 | operator oper = | ||
504 | lexeme $ try $ trCons <$> expect "reserved operator" (`Set.member` theReservedOpNames) oper | ||
505 | where | ||
506 | trCons ":" = "Cons" | ||
507 | trCons x = x | ||
508 | |||
509 | theReservedOpNames = Set.fromList ["::","..","=","\\","|","<-","->","@","~","=>"] | ||
510 | |||
511 | expect msg p i = i >>= \n -> if (p n) then unexpected (msg ++ " " ++ show n) else return n | ||
512 | |||
513 | ----------------------------------------------------------- | ||
514 | -- Identifiers & Reserved words | ||
515 | ----------------------------------------------------------- | ||
516 | reserved name = | ||
517 | lexeme $ try $ | ||
518 | do{ string name | ||
519 | ; notFollowedBy identLetter <?> ("end of " ++ show name) | ||
520 | } | ||
521 | |||
522 | identifier ident = | ||
523 | lexeme $ try $ expect "reserved word" (`Set.member` theReservedNames) ident | ||
524 | |||
525 | theReservedNames = Set.fromList $ | ||
526 | ["let","in","case","of","if","then","else" | ||
527 | ,"data","type" | ||
528 | ,"class","default","deriving","do","import" | ||
529 | ,"infix","infixl","infixr","instance","module" | ||
530 | ,"newtype","where" | ||
531 | ,"primitive" | ||
532 | -- "as","qualified","hiding" | ||
533 | ] ++ | ||
534 | ["foreign","import","export","primitive" | ||
535 | ,"_ccall_","_casm_" | ||
536 | ,"forall" | ||
537 | ] | ||
538 | |||
539 | ----------------------------------------------------------- | ||
540 | -- White space & symbols | ||
541 | ----------------------------------------------------------- | ||
542 | |||
543 | lexeme = lexeme' whiteSpace | ||
544 | |||
545 | symbol = symbol' whiteSpace | ||
546 | |||
547 | symbol' sp name | ||
548 | = lexeme' sp (string name) | ||
549 | |||
550 | whiteSpace = skipMany (simpleSpace <|> oneLineComment <|> multiLineComment <?> "") | ||
551 | |||
552 | simpleSpace | ||
553 | = skipSome (satisfy isSpace) | ||
554 | |||
555 | oneLineComment | ||
556 | = try (string "--" >> many (char '-') >> notFollowedBy opLetter) | ||
557 | >> skipMany (satisfy (/= '\n')) | ||
558 | |||
559 | multiLineComment = try (string "{-") *> inCommentMulti | ||
560 | |||
561 | inCommentMulti | ||
562 | = try (() <$ string "-}") | ||
563 | <|> multiLineComment *> inCommentMulti | ||
564 | <|> skipSome (noneOf "{}-") *> inCommentMulti | ||
565 | <|> oneOf "{}-" *> inCommentMulti | ||
566 | <?> "end of comment" | ||
567 | 546 | ||
diff --git a/src/LambdaCube/Compiler/Parser.hs b/src/LambdaCube/Compiler/Parser.hs index 3b2ab687..b69fe7a4 100644 --- a/src/LambdaCube/Compiler/Parser.hs +++ b/src/LambdaCube/Compiler/Parser.hs | |||
@@ -354,8 +354,8 @@ parseTerm prec = withRange setSI $ case prec of | |||
354 | t' <- dbf' fe <$> parseTerm PrecLam | 354 | t' <- dbf' fe <$> parseTerm PrecLam |
355 | ge <- dsInfo | 355 | ge <- dsInfo |
356 | return $ foldr (uncurry (patLam id ge)) t' ts | 356 | return $ foldr (uncurry (patLam id ge)) t' ts |
357 | <|> compileCase <$ reserved "case" <*> dsInfo <*> parseETerm PrecLam <*> do | 357 | <|> compileCase <$ reserved "case" <*> dsInfo <*> parseETerm PrecLam <* reserved "of" <*> do |
358 | indentSome "of" $ do | 358 | indentMS False $ do |
359 | (fe, p) <- longPattern | 359 | (fe, p) <- longPattern |
360 | (,) p <$> parseRHS (dbf' fe) "->" | 360 | (,) p <$> parseRHS (dbf' fe) "->" |
361 | -- <|> compileGuardTree id id <$> dsInfo <*> (Alts <$> parseSomeGuards (const True)) | 361 | -- <|> compileGuardTree id id <$> dsInfo <*> (Alts <$> parseSomeGuards (const True)) |
@@ -383,7 +383,7 @@ parseTerm prec = withRange setSI $ case prec of | |||
383 | ) <|> mkList <$> namespace <*> pure []) | 383 | ) <|> mkList <$> namespace <*> pure []) |
384 | <|> mkTuple <$> namespace <*> parens (commaSep $ parseTerm PrecLam) | 384 | <|> mkTuple <$> namespace <*> parens (commaSep $ parseTerm PrecLam) |
385 | <|> mkRecord <$> braces (commaSep $ (,) <$> lowerCase <* symbol ":" <*> parseTerm PrecLam) | 385 | <|> mkRecord <$> braces (commaSep $ (,) <$> lowerCase <* symbol ":" <*> parseTerm PrecLam) |
386 | <|> mkLets True <$> dsInfo <*> parseDefs xSLabelEnd (indentMany "let") <* reserved "in" <*> parseTerm PrecLam | 386 | <|> mkLets True <$ reserved "let" <*> dsInfo <*> parseDefs xSLabelEnd <* reserved "in" <*> parseTerm PrecLam |
387 | where | 387 | where |
388 | level pr f = parseTerm pr >>= \t -> option t $ f t | 388 | level pr f = parseTerm pr >>= \t -> option t $ f t |
389 | 389 | ||
@@ -758,7 +758,7 @@ parseDef = | |||
758 | ( if mk then Just nps' else Nothing | 758 | ( if mk then Just nps' else Nothing |
759 | , foldr (uncurry SPi) (foldl SAppV (SGlobal x) $ downToS (length ts') $ length ts) ts') | 759 | , foldr (uncurry SPi) (foldl SAppV (SGlobal x) $ downToS (length ts') $ length ts) ts') |
760 | (af, cs) <- option (True, []) $ | 760 | (af, cs) <- option (True, []) $ |
761 | do fmap ((,) True) $ indentMany "where" $ second ((,) Nothing . dbf' npsd) <$> typedIds Nothing | 761 | do fmap ((,) True) $ (reserved "where" >>) $ indentMS True $ second ((,) Nothing . dbf' npsd) <$> typedIds Nothing |
762 | <|> (,) False <$ reservedOp "=" <*> | 762 | <|> (,) False <$ reservedOp "=" <*> |
763 | sepBy1 ((,) <$> (pure <$> parseSIName upperCase) | 763 | sepBy1 ((,) <$> (pure <$> parseSIName upperCase) |
764 | <*> do do braces $ mkConTy True . second (zipWith (\i (v, e) -> (v, dbf_ i npsd e)) [0..]) | 764 | <*> do do braces $ mkConTy True . second (zipWith (\i (v, e) -> (v, dbf_ i npsd e)) [0..]) |
@@ -771,21 +771,21 @@ parseDef = | |||
771 | <|> do indentation (reserved "class") $ do | 771 | <|> do indentation (reserved "class") $ do |
772 | x <- parseSIName $ typeNS upperCase | 772 | x <- parseSIName $ typeNS upperCase |
773 | (nps, ts) <- telescope (Just SType) | 773 | (nps, ts) <- telescope (Just SType) |
774 | cs <- option [] $ indentMany "where" $ typedIds Nothing | 774 | cs <- option [] $ (reserved "where" >>) $ indentMS True $ typedIds Nothing |
775 | return $ pure $ Class x (map snd ts) (concatMap (\(vs, t) -> (,) <$> vs <*> pure (dbf' nps t)) cs) | 775 | return $ pure $ Class x (map snd ts) (concatMap (\(vs, t) -> (,) <$> vs <*> pure (dbf' nps t)) cs) |
776 | <|> do indentation (reserved "instance") $ typeNS $ do | 776 | <|> do indentation (reserved "instance") $ typeNS $ do |
777 | constraints <- option [] $ try "constraint" $ getTTuple' <$> parseTerm PrecOp <* reservedOp "=>" | 777 | constraints <- option [] $ try "constraint" $ getTTuple' <$> parseTerm PrecOp <* reservedOp "=>" |
778 | x <- parseSIName upperCase | 778 | x <- parseSIName upperCase |
779 | (nps, args) <- telescopePat | 779 | (nps, args) <- telescopePat |
780 | checkPattern nps | 780 | checkPattern nps |
781 | cs <- expNS $ option [] $ indentSome "where" $ dbFunAlt nps <$> funAltDef varId | 781 | cs <- expNS $ option [] $ reserved "where" *> indentMS False (dbFunAlt nps <$> funAltDef varId) |
782 | pure . Instance x ({-todo-}map snd args) (dbff (nps <> [x]) <$> constraints) <$> compileFunAlts' id{-TODO-} cs | 782 | pure . Instance x ({-todo-}map snd args) (dbff (nps <> [x]) <$> constraints) <$> compileFunAlts' id{-TODO-} cs |
783 | <|> do indentation (try "type family" $ reserved "type" >> reserved "family") $ typeNS $ do | 783 | <|> do indentation (try "type family" $ reserved "type" >> reserved "family") $ typeNS $ do |
784 | x <- parseSIName upperCase | 784 | x <- parseSIName upperCase |
785 | (nps, ts) <- telescope (Just SType) | 785 | (nps, ts) <- telescope (Just SType) |
786 | t <- dbf' nps <$> parseType (Just SType) | 786 | t <- dbf' nps <$> parseType (Just SType) |
787 | option {-open type family-}[TypeFamily x ts t] $ do | 787 | option {-open type family-}[TypeFamily x ts t] $ do |
788 | cs <- indentMany "where" $ funAltDef $ mfilter (== snd x) upperCase | 788 | cs <- (reserved "where" >>) $ indentMS True $ funAltDef $ mfilter (== snd x) upperCase |
789 | -- closed type family desugared here | 789 | -- closed type family desugared here |
790 | compileFunAlts False id SLabelEnd [TypeAnn x $ addParamsS ts t] cs | 790 | compileFunAlts False id SLabelEnd [TypeAnn x $ addParamsS ts t] cs |
791 | <|> do indentation (try "type instance" $ reserved "type" >> reserved "instance") $ typeNS $ pure <$> funAltDef upperCase | 791 | <|> do indentation (try "type instance" $ reserved "type" >> reserved "instance") $ typeNS $ pure <$> funAltDef upperCase |
@@ -817,10 +817,10 @@ parseRHS fe tok = fmap (fmap (fe *** fe) +++ fe) $ do | |||
817 | <|> do | 817 | <|> do |
818 | reservedOp tok | 818 | reservedOp tok |
819 | rhs <- parseTerm PrecLam | 819 | rhs <- parseTerm PrecLam |
820 | f <- option id $ mkLets True <$> dsInfo <*> parseDefs xSLabelEnd (indentMany "where") | 820 | f <- option id $ mkLets True <$ reserved "where" <*> dsInfo <*> parseDefs xSLabelEnd |
821 | return $ Right $ f rhs | 821 | return $ Right $ f rhs |
822 | 822 | ||
823 | parseDefs lend p = p parseDef >>= compileFunAlts' lend . concat | 823 | parseDefs lend = indentMS True parseDef >>= compileFunAlts' lend . concat |
824 | 824 | ||
825 | funAltDef parseName = do -- todo: use ns to determine parseName | 825 | funAltDef parseName = do -- todo: use ns to determine parseName |
826 | (n, (fee, tss)) <- | 826 | (n, (fee, tss)) <- |
@@ -1084,16 +1084,15 @@ parseModule f str = do | |||
1084 | { extensions = exts | 1084 | { extensions = exts |
1085 | , moduleImports = [("Prelude", ImportAllBut []) | NoImplicitPrelude `notElem` exts] ++ idefs | 1085 | , moduleImports = [("Prelude", ImportAllBut []) | NoImplicitPrelude `notElem` exts] ++ idefs |
1086 | , moduleExports = join $ snd <$> header | 1086 | , moduleExports = join $ snd <$> header |
1087 | , definitions = \ge -> first (show +++ id) $ flip runReader ((ge, ns), (0,0)) . runWriterT $ runPT' (parseDefs SLabelEnd indentMany' <* eof) st | 1087 | , definitions = \ge -> first ((show +++ id) . snd) $ runP' (ge, ns) f (parseDefs SLabelEnd <* eof) st |
1088 | , sourceCode = str | 1088 | , sourceCode = str |
1089 | } | 1089 | } |
1090 | 1090 | ||
1091 | parseLC :: MonadError ErrorMsg m => FilePath -> String -> m Module | 1091 | parseLC :: MonadError ErrorMsg m => FilePath -> String -> m Module |
1092 | parseLC f str | 1092 | parseLC f str |
1093 | = either (throwError . ErrorMsg . show) return | 1093 | = either (throwError . ErrorMsg . show) return |
1094 | . flip runReader ((error "globalenv used", Namespace (Just ExpLevel) True), (0,0)) | 1094 | . fst |
1095 | . fmap fst . runWriterT | 1095 | . runP (error "globalenv used", Namespace (Just ExpLevel) True) f (parseModule f str) |
1096 | . runParserT'' (parseModule f str) f | ||
1097 | $ str | 1096 | $ str |
1098 | 1097 | ||
1099 | -------------------------------------------------------------------------------- pretty print | 1098 | -------------------------------------------------------------------------------- pretty print |