Advertisement
gatoatigrado3

Untitled

Feb 20th, 2012
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.16 KB | None | 0 0
  1. -- Copyright 2012 gatoatigrado (nicholas tung) [ntung at ntung]
  2. -- Licensed under the Apache License, Version 2.0 (the "License"); you may
  3. -- not use this file except in compliance with the License. You may obtain a
  4. -- copy of the License at http://www.apache.org/licenses/LICENSE-2.0 .
  5.  
  6. -- enable to remove excess imports {-# OPTIONS_GHC -fwarn-unused-imports #-}
  7. {-# LANGUAGE Arrows,
  8. BangPatterns,
  9. DeriveDataTypeable,
  10. EmptyDataDecls,
  11. FlexibleContexts,
  12. FlexibleInstances,
  13. FunctionalDependencies,
  14. GADTs,
  15. GeneralizedNewtypeDeriving,
  16. ImpredicativeTypes,
  17. MultiParamTypeClasses,
  18. NamedFieldPuns,
  19. NoMonomorphismRestriction,
  20. RankNTypes,
  21. ScopedTypeVariables,
  22. StandaloneDeriving,
  23. TemplateHaskell,
  24. TypeFamilies,
  25. TypeOperators,
  26. TypeSynonymInstances,
  27. UndecidableInstances,
  28. ViewPatterns #-}
  29.  
  30. module Hz2.Preproc where
  31.  
  32. import Prelude hiding (id, (.))
  33. import Control.Arrow
  34. import Control.Category
  35. import Control.Monad
  36. import Control.Monad.Trans.Class
  37.  
  38. import Control.Applicative hiding (many, (<|>))
  39.  
  40. import qualified Data.Map as Map
  41. import qualified Data.List as List
  42. import qualified Data.Text as Text
  43.  
  44. import System.Environment
  45. import System.Exit
  46. import System.IO
  47.  
  48. import Text.Parsec hiding (spaces)
  49. import Text.Parsec.Combinator
  50.  
  51. import qualified Text.Parsec.Token as P
  52. import Text.Parsec.Language (haskellDef)
  53.  
  54. import Text.Printf
  55.  
  56. infixl 4 <++>
  57. (<++>) = liftM2 (++)
  58.  
  59. haskell = P.makeTokenParser haskellDef
  60. ident = P.identifier haskell
  61. parens = P.parens haskell
  62. commaSep = P.commaSep haskell
  63.  
  64. relist = List.intercalate ", " . map ((++ " α") . strip)
  65. strip = Text.unpack . Text.strip . Text.pack
  66. instance_trans_conds [] = ""
  67. instance_trans_conds lst = "(" ++ List.intercalate ", " lst ++ ") => "
  68.  
  69. mk_suitable (strip -> nme) (strip -> cls) (relist -> conds) = "\n\
  70. \data instance Constraints (" ++ cls ++ ") α =\n\
  71. \ (" ++ conds ++ ") => " ++ nme ++ "\n\
  72. \instance (" ++ conds ++ ") => Suitable (" ++ cls ++ ") α where\n\
  73. \ constraints = " ++ nme ++ "\n"
  74.  
  75. mk_e_trans (strip -> name) (strip -> base) conds monad_conds (strip -> newtyp) =
  76. mk_suitable constr_name ("ExprTyp (" ++ name ++ ")") conds ++ "\n\
  77. \instance " ++ mc ++ "HzExprTrans (ExprTyp (" ++ name ++ ")) where\n\
  78. \ type PrimExpr (ExprTyp (" ++ name ++ ")) = " ++ base ++ "\n\
  79. \ e_lift = fmap " ++ newtyp ++ "\n\
  80. \ e_lower = fmap (\\(" ++ newtyp ++ " x) -> x)\n\
  81. \ e_lower_suitably x@(ExprT v) f =\n\
  82. \ withConstraintsOf v $ \\" ++ constr_name ++ " -> f (e_lower x)\n\
  83. \instance " ++ mc ++ "BinaryCmpExpr (ExprTyp (" ++ name ++ "))\n\
  84. \instance " ++ mc ++ "BinaryOpExpr (ExprTyp (" ++ name ++ "))\n\
  85. \instance " ++ mc ++ "SketchConstrExpr (ExprTyp (" ++ name ++ "))\n\
  86. \instance " ++ mc ++ "Arithmetic (ExprTyp (" ++ name ++ "))\n\
  87. \instance " ++ mc ++ "VariablesExpr (ExprTyp (" ++ name ++ "))\n"
  88.  
  89. where constr_name = newtyp ++ "_Constr"
  90. mc = instance_trans_conds monad_conds
  91.  
  92. mk_monad_trans (strip -> nme) (strip -> base) monad_conds (strip -> newtyp) = "\n\
  93. \instance " ++ mc ++ " MonadTrans (" ++ nme ++ ") where\n\
  94. \ type BaseMonad (" ++ nme ++ ") = " ++ base ++ "\n\
  95. \ lift = " ++ newtyp ++ "\n\
  96. \instance " ++ mc ++ " HzMonadUnliftTrans (" ++ nme ++ ") where\n\
  97. \ unlift (" ++ newtyp ++ " x) = x\n"
  98. where
  99. mc = instance_trans_conds monad_conds
  100.  
  101. mk_array_trans
  102. (strip -> monadtyp) -- e.g. StateT 𝔪 α
  103. (strip -> base_array) -- e.g. ArrayTyp 𝔪 α
  104. (strip -> base_alloc) -- e.g. AllocTyp 𝔪 α
  105. conds -- e.g. Suitable (ArrayTyp 𝔪) α
  106. monad_conds -- e.g. HzArrayMonad 𝔪
  107. (strip -> newtyp_base) -- e.g. StateT
  108. = mk_suitable constr_name ("ArrayTyp (" ++ monadtyp ++ ")") conds ++
  109. "\n\
  110. \instance " ++ mc ++ "HzArrayMonad (" ++ monadtyp ++ ") where\n\
  111. \ data AllocTyp (" ++ monadtyp ++ ") α = " ++ alloc_newtyp ++ " ((" ++ base_alloc ++ ") α)\n\
  112. \ data ArrayTyp (" ++ monadtyp ++ ") α = " ++ array_newtyp ++ " ((" ++ base_array ++ ") α)\n\
  113. \ alloc_lower = fmap $ \\(" ++ alloc_newtyp ++ " x) -> x\n\
  114. \ alloc_lift = fmap " ++ alloc_newtyp ++ "\n\
  115. \ array_lower = fmap $ \\(" ++ array_newtyp ++ " x) -> x\n\
  116. \ array_lift = fmap " ++ array_newtyp ++ "\n\
  117. \ array_suitably m f = withConstraintsOf m $ \\" ++ constr_name ++ " -> f\n"
  118. where constr_name = newtyp_base ++ "_Array_Constr"
  119. array_newtyp = newtyp_base ++ "_Array"
  120. alloc_newtyp = newtyp_base ++ "_Alloc"
  121. mc = instance_trans_conds monad_conds
  122.  
  123.  
  124.  
  125.  
  126.  
  127. -- grab any expression within parenthesis
  128. any_parens = pure "(" <++>
  129. parens (nonparen <++> option "" any_parens <++> nonparen) <++> pure ")"
  130. where nonparen = many (noneOf "()")
  131.  
  132. -- way to get spaces
  133. spaces m = many space *> m <* many space
  134.  
  135. -- an entry of a comma-separated list
  136. -- fails for a whitespace-only string
  137. no_comma_ent = do
  138. lookAhead (many space >> notFollowedBy (space <|> char ')'))
  139. List.concat <$> many1 (many1 (noneOf ",()") <|> any_parens)
  140.  
  141. paren_list = parens (commaSep no_comma_ent)
  142.  
  143. -- a comma-separated list of named items
  144. {---------------------------------------------------
  145. -- optlist f = commaSep $ do
  146. -- ident <- spaces ident
  147. -- spaces (char '=')
  148. -- f ident
  149. ----------------------------------------------------}
  150. optlistent isEnd nme f = spaces (string nme) >> spaces (char '=') >> f'
  151. where f' | isEnd = f <* many space
  152. | otherwise = f <* spaces (char ',')
  153.  
  154. suitable_macro = do
  155. name <- ident
  156. spaces (char '=') >> string "SUITABLE" >> many space
  157. -- parens (many space >> return "")
  158. parens $ do
  159. lst <- map List.concat <$>
  160. commaSep (many (many1 (noneOf ",()") <|> any_parens))
  161. return (mk_suitable name (last lst) (init lst))
  162.  
  163. named_macro n f = do
  164. try (spaces (string n))
  165. parens f
  166.  
  167. expr_trans_macro = named_macro "EXPR_TRANS" $ do
  168. name <- optlistent False "name" no_comma_ent
  169. base <- optlistent False "base" no_comma_ent
  170. monad_conds <- optlistent False "monad_conds" paren_list
  171. newtyp <- optlistent True "newtyp" no_comma_ent
  172. return $ mk_e_trans name base
  173. -- replace "extra_conds" with default value
  174. [ ("Suitable (" ++ base ++ ")") ]
  175. monad_conds
  176. newtyp
  177.  
  178. array_trans_macro = named_macro "ARRAY_TRANS" $ do
  179. monadtyp <- optlistent False "monadtyp" no_comma_ent
  180. base_array <- optlistent False "base_array" no_comma_ent
  181. base_alloc <- optlistent False "base_alloc" no_comma_ent
  182. monad_conds <- optlistent False "monad_conds" paren_list
  183. newtyp_base <- optlistent True "newtyp_base" no_comma_ent
  184. return $ mk_array_trans monadtyp base_array base_alloc
  185. -- replace "extra_conds" with default value
  186. [ ("Suitable (" ++ base_array ++ ")") ]
  187. monad_conds
  188. newtyp_base
  189.  
  190. monad_trans_macro = named_macro "MONAD_TRANS" $ do
  191. name <- optlistent False "name" no_comma_ent
  192. base <- optlistent False "base" no_comma_ent
  193. monad_conds <- optlistent False "monad_conds" paren_list
  194. newtyp <- optlistent True "newtyp" no_comma_ent
  195. return $ mk_monad_trans name base monad_conds newtyp
  196.  
  197. hz_trans_macro = named_macro "HZ_TRANS" $ do
  198. name <- optlistent False "name" no_comma_ent
  199. monad_base <- optlistent False "monad_base" no_comma_ent
  200. let expr_base = "ExprTyp (" ++ monad_base ++ ")"
  201. array_base = "ArrayTyp (" ++ monad_base ++ ")"
  202. alloc_base = "AllocTyp (" ++ monad_base ++ ")"
  203. monad_conds <- optlistent False "monad_conds" paren_list
  204. array_monad_cond <- optlistent False "array_monad_cond" no_comma_ent
  205. monad_newtyp <- optlistent False "monad_newtyp" no_comma_ent
  206. expr_newtyp <- optlistent True "expr_newtyp" no_comma_ent
  207. return $
  208. (mk_monad_trans name monad_base monad_conds monad_newtyp) ++
  209. (mk_e_trans name expr_base
  210. [ ("Suitable (" ++ expr_base ++ ")") ]
  211. monad_conds expr_newtyp) ++
  212. (mk_array_trans name array_base alloc_base
  213. [ ("Suitable (" ++ array_base ++ ")") ]
  214. (array_monad_cond : monad_conds) (expr_newtyp ++ "A"))
  215.  
  216. parseMacro = try suitable_macro <|>
  217. expr_trans_macro <|>
  218. array_trans_macro <|>
  219. monad_trans_macro <|>
  220. hz_trans_macro
  221.  
  222. parseMacro' = many space *> parseMacro <* (many space >> string "}}")
  223.  
  224. parseAll = non_lbrace <++>
  225. ( ("" <$ eof) <|>
  226. (try (string "{" <++> non_lbrace1) <++> parseAll) <|>
  227. (string "{{" >> parseMacro' <++> parseAll))
  228. where non_lbrace = many (noneOf "{")
  229. non_lbrace1 = many1 (noneOf "{")
  230.  
  231. preprocessor :: String -> String -> IO ()
  232. preprocessor n = handleErr . parse (parseAll <* eof) n
  233. where handleErr (Right x) = putStrLn x
  234. handleErr (Left y) = do
  235. hPutStrLn stderr "parse error!"
  236. hPutStrLn stderr (show y)
  237. exitWith (ExitFailure 1)
  238.  
  239. main = do
  240. (n:_) <- getArgs
  241. c <- getContents
  242. preprocessor n c
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement