PageRenderTime 73ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/utils/genprimopcode/Main.hs

http://github.com/ghc/ghc
Haskell | 965 lines | 752 code | 124 blank | 89 comment | 14 complexity | 72fe8f3007d750d33d91760831c6a1f8 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, GPL-3.0
  1. ------------------------------------------------------------------
  2. -- A primop-table mangling program --
  3. --
  4. -- See Note [GHC.Prim] in primops.txt.pp for details.
  5. ------------------------------------------------------------------
  6. module Main where
  7. import Parser
  8. import Syntax
  9. import Data.Char
  10. import Data.List (union, intersperse, intercalate, nub)
  11. import Data.Maybe ( catMaybes )
  12. import System.Environment ( getArgs )
  13. vecOptions :: Entry -> [(String,String,Int)]
  14. vecOptions i =
  15. concat [vecs | OptionVector vecs <- opts i]
  16. desugarVectorSpec :: Entry -> [Entry]
  17. desugarVectorSpec i@(Section {}) = [i]
  18. desugarVectorSpec i = case vecOptions i of
  19. [] -> [i]
  20. vos -> map genVecEntry vos
  21. where
  22. genVecEntry :: (String,String,Int) -> Entry
  23. genVecEntry (con,repCon,n) =
  24. case i of
  25. PrimOpSpec {} ->
  26. PrimVecOpSpec { cons = "(" ++ concat (intersperse " " [cons i, vecCat, show n, vecWidth]) ++ ")"
  27. , name = name'
  28. , prefix = pfx
  29. , veclen = n
  30. , elemrep = con ++ "ElemRep"
  31. , ty = desugarTy (ty i)
  32. , cat = cat i
  33. , desc = desc i
  34. , opts = opts i
  35. }
  36. PrimTypeSpec {} ->
  37. PrimVecTypeSpec { ty = desugarTy (ty i)
  38. , prefix = pfx
  39. , veclen = n
  40. , elemrep = con ++ "ElemRep"
  41. , desc = desc i
  42. , opts = opts i
  43. }
  44. _ ->
  45. error "vector options can only be given for primops and primtypes"
  46. where
  47. vecCons = con++"X"++show n++"#"
  48. vecCat = conCat con
  49. vecWidth = conWidth con
  50. pfx = lowerHead con++"X"++show n
  51. vecTyName = pfx++"PrimTy"
  52. name' | Just pre <- splitSuffix (name i) "Array#" = pre++vec++"Array#"
  53. | Just pre <- splitSuffix (name i) "OffAddr#" = pre++vec++"OffAddr#"
  54. | Just pre <- splitSuffix (name i) "ArrayAs#" = pre++con++"ArrayAs"++vec++"#"
  55. | Just pre <- splitSuffix (name i) "OffAddrAs#" = pre++con++"OffAddrAs"++vec++"#"
  56. | otherwise = init (name i)++vec ++"#"
  57. where
  58. vec = con++"X"++show n
  59. splitSuffix :: Eq a => [a] -> [a] -> Maybe [a]
  60. splitSuffix s suf
  61. | drop len s == suf = Just (take len s)
  62. | otherwise = Nothing
  63. where
  64. len = length s - length suf
  65. lowerHead s = toLower (head s) : tail s
  66. desugarTy :: Ty -> Ty
  67. desugarTy (TyF s d) = TyF (desugarTy s) (desugarTy d)
  68. desugarTy (TyC s d) = TyC (desugarTy s) (desugarTy d)
  69. desugarTy (TyApp SCALAR []) = TyApp (TyCon repCon) []
  70. desugarTy (TyApp VECTOR []) = TyApp (VecTyCon vecCons vecTyName) []
  71. desugarTy (TyApp VECTUPLE []) = TyUTup (replicate n (TyApp (TyCon repCon) []))
  72. desugarTy (TyApp tycon ts) = TyApp tycon (map desugarTy ts)
  73. desugarTy t@(TyVar {}) = t
  74. desugarTy (TyUTup ts) = TyUTup (map desugarTy ts)
  75. conCat :: String -> String
  76. conCat "Int8" = "IntVec"
  77. conCat "Int16" = "IntVec"
  78. conCat "Int32" = "IntVec"
  79. conCat "Int64" = "IntVec"
  80. conCat "Word8" = "WordVec"
  81. conCat "Word16" = "WordVec"
  82. conCat "Word32" = "WordVec"
  83. conCat "Word64" = "WordVec"
  84. conCat "Float" = "FloatVec"
  85. conCat "Double" = "FloatVec"
  86. conCat con = error $ "conCat: unknown type constructor " ++ con ++ "\n"
  87. conWidth :: String -> String
  88. conWidth "Int8" = "W8"
  89. conWidth "Int16" = "W16"
  90. conWidth "Int32" = "W32"
  91. conWidth "Int64" = "W64"
  92. conWidth "Word8" = "W8"
  93. conWidth "Word16" = "W16"
  94. conWidth "Word32" = "W32"
  95. conWidth "Word64" = "W64"
  96. conWidth "Float" = "W32"
  97. conWidth "Double" = "W64"
  98. conWidth con = error $ "conWidth: unknown type constructor " ++ con ++ "\n"
  99. main :: IO ()
  100. main = getArgs >>= \args ->
  101. if length args /= 1 || head args `notElem` known_args
  102. then error ("usage: genprimopcode command < primops.txt > ...\n"
  103. ++ " where command is one of\n"
  104. ++ unlines (map (" "++) known_args)
  105. )
  106. else
  107. do s <- getContents
  108. case parse s of
  109. Left err -> error ("parse error at " ++ (show err))
  110. Right p_o_specs@(Info _ _)
  111. -> seq (sanityTop p_o_specs) (
  112. case head args of
  113. "--data-decl"
  114. -> putStr (gen_data_decl p_o_specs)
  115. "--has-side-effects"
  116. -> putStr (gen_switch_from_attribs
  117. "has_side_effects"
  118. "primOpHasSideEffects" p_o_specs)
  119. "--out-of-line"
  120. -> putStr (gen_switch_from_attribs
  121. "out_of_line"
  122. "primOpOutOfLine" p_o_specs)
  123. "--commutable"
  124. -> putStr (gen_switch_from_attribs
  125. "commutable"
  126. "commutableOp" p_o_specs)
  127. "--code-size"
  128. -> putStr (gen_switch_from_attribs
  129. "code_size"
  130. "primOpCodeSize" p_o_specs)
  131. "--can-fail"
  132. -> putStr (gen_switch_from_attribs
  133. "can_fail"
  134. "primOpCanFail" p_o_specs)
  135. "--strictness"
  136. -> putStr (gen_switch_from_attribs
  137. "strictness"
  138. "primOpStrictness" p_o_specs)
  139. "--fixity"
  140. -> putStr (gen_switch_from_attribs
  141. "fixity"
  142. "primOpFixity" p_o_specs)
  143. "--primop-primop-info"
  144. -> putStr (gen_primop_info p_o_specs)
  145. "--primop-tag"
  146. -> putStr (gen_primop_tag p_o_specs)
  147. "--primop-list"
  148. -> putStr (gen_primop_list p_o_specs)
  149. "--primop-vector-uniques"
  150. -> putStr (gen_primop_vector_uniques p_o_specs)
  151. "--primop-vector-tys"
  152. -> putStr (gen_primop_vector_tys p_o_specs)
  153. "--primop-vector-tys-exports"
  154. -> putStr (gen_primop_vector_tys_exports p_o_specs)
  155. "--primop-vector-tycons"
  156. -> putStr (gen_primop_vector_tycons p_o_specs)
  157. "--make-haskell-wrappers"
  158. -> putStr (gen_wrappers p_o_specs)
  159. "--make-haskell-source"
  160. -> putStr (gen_hs_source p_o_specs)
  161. "--make-latex-doc"
  162. -> putStr (gen_latex_doc p_o_specs)
  163. "--wired-in-docs"
  164. -> putStr (gen_wired_in_docs p_o_specs)
  165. _ -> error "Should not happen, known_args out of sync?"
  166. )
  167. known_args :: [String]
  168. known_args
  169. = [ "--data-decl",
  170. "--has-side-effects",
  171. "--out-of-line",
  172. "--commutable",
  173. "--code-size",
  174. "--can-fail",
  175. "--strictness",
  176. "--fixity",
  177. "--primop-primop-info",
  178. "--primop-tag",
  179. "--primop-list",
  180. "--primop-vector-uniques",
  181. "--primop-vector-tys",
  182. "--primop-vector-tys-exports",
  183. "--primop-vector-tycons",
  184. "--make-haskell-wrappers",
  185. "--make-haskell-source",
  186. "--make-latex-doc",
  187. "--wired-in-docs"
  188. ]
  189. ------------------------------------------------------------------
  190. -- Code generators -----------------------------------------------
  191. ------------------------------------------------------------------
  192. gen_hs_source :: Info -> String
  193. gen_hs_source (Info defaults entries) =
  194. "{-\n"
  195. ++ "This is a generated file (generated by genprimopcode).\n"
  196. ++ "It is not code to actually be used. Its only purpose is to be\n"
  197. ++ "consumed by haddock.\n"
  198. ++ "-}\n"
  199. ++ "\n"
  200. ++ (replicate 77 '-' ++ "\n") -- For 80-col cleanliness
  201. ++ "-- |\n"
  202. ++ "-- Module : GHC.Prim\n"
  203. ++ "-- \n"
  204. ++ "-- Maintainer : ghc-devs@haskell.org\n"
  205. ++ "-- Stability : internal\n"
  206. ++ "-- Portability : non-portable (GHC extensions)\n"
  207. ++ "--\n"
  208. ++ "-- GHC\'s primitive types and operations.\n"
  209. ++ "-- Use GHC.Exts from the base package instead of importing this\n"
  210. ++ "-- module directly.\n"
  211. ++ "--\n"
  212. ++ (replicate 77 '-' ++ "\n") -- For 80-col cleanliness
  213. ++ "{-# LANGUAGE Unsafe #-}\n"
  214. ++ "{-# LANGUAGE MagicHash #-}\n"
  215. ++ "{-# LANGUAGE MultiParamTypeClasses #-}\n"
  216. ++ "{-# LANGUAGE NoImplicitPrelude #-}\n"
  217. ++ "{-# LANGUAGE UnboxedTuples #-}\n"
  218. ++ "{-# LANGUAGE NegativeLiterals #-}\n"
  219. ++ "{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}\n"
  220. -- We generate a binding for coerce, like
  221. -- coerce :: Coercible a b => a -> b
  222. -- coerce = let x = x in x
  223. -- and we don't want a complaint that the constraint is redundant
  224. -- Remember, this silly file is only for Haddock's consumption
  225. ++ "module GHC.Prim (\n"
  226. ++ unlines (map ((" " ++) . hdr) entries')
  227. ++ ") where\n"
  228. ++ "\n"
  229. ++ "{-\n"
  230. ++ unlines (map opt defaults)
  231. ++ "-}\n"
  232. ++ "import GHC.Types (Coercible)\n"
  233. ++ "default ()" -- If we don't say this then the default type include Integer
  234. -- so that runs off and loads modules that are not part of
  235. -- package ghc-prim at all. And that in turn somehow ends up
  236. -- with Declaration for $fEqMaybe:
  237. -- attempting to use module GHC.Classes
  238. -- (libraries/ghc-prim/./GHC/Classes.hs) which is not loaded
  239. -- coming from GHC.Iface.Load.homeModError
  240. -- I'm not sure precisely why; but I *am* sure that we don't need
  241. -- any type-class defaulting; and it's clearly wrong to need
  242. -- the base package when haddocking ghc-prim
  243. -- Now the main payload
  244. ++ "\n" ++ unlines (concatMap ent entries') ++ "\n\n\n"
  245. where entries' = concatMap desugarVectorSpec entries
  246. opt (OptionFalse n) = n ++ " = False"
  247. opt (OptionTrue n) = n ++ " = True"
  248. opt (OptionString n v) = n ++ " = { " ++ v ++ "}"
  249. opt (OptionInteger n v) = n ++ " = " ++ show v
  250. opt (OptionVector _) = ""
  251. opt (OptionFixity mf) = "fixity" ++ " = " ++ show mf
  252. hdr s@(Section {}) = sec s
  253. hdr (PrimOpSpec { name = n }) = wrapOp n ++ ","
  254. hdr (PrimVecOpSpec { name = n }) = wrapOp n ++ ","
  255. hdr (PseudoOpSpec { name = n }) = wrapOp n ++ ","
  256. hdr (PrimTypeSpec { ty = TyApp (TyCon n) _ }) = wrapOp n ++ ","
  257. hdr (PrimTypeSpec {}) = error $ "Illegal type spec"
  258. hdr (PrimVecTypeSpec { ty = TyApp (VecTyCon n _) _ }) = wrapOp n ++ ","
  259. hdr (PrimVecTypeSpec {}) = error $ "Illegal type spec"
  260. sec s = "\n-- * " ++ escape (title s) ++ "\n"
  261. ++ (unlines $ map ("-- " ++ ) $ lines $ unlatex $ escape $ "|" ++ desc s)
  262. ent (Section {}) = []
  263. ent o@(PrimOpSpec {}) = spec o
  264. ent o@(PrimVecOpSpec {}) = spec o
  265. ent o@(PrimTypeSpec {}) = spec o
  266. ent o@(PrimVecTypeSpec {}) = spec o
  267. ent o@(PseudoOpSpec {}) = spec o
  268. spec o = ([ "" ] ++) . concat $
  269. -- Doc comments
  270. [ case unlatex (escape (desc o)) ++ extra (opts o) of
  271. "" -> []
  272. cmmt -> map ("-- " ++) $ lines $ "|" ++ cmmt
  273. -- Deprecations
  274. , [ d | Just n <- [getName o], d <- prim_deprecated (opts o) n ]
  275. -- Fixity
  276. , [ f | Just n <- [getName o], f <- prim_fixity (opts o) n ]
  277. -- Declarations (see Note [Placeholder declarations])
  278. , case o of
  279. PrimOpSpec { name = n, ty = t } -> prim_func n t
  280. PrimVecOpSpec { name = n, ty = t } -> prim_func n t
  281. PseudoOpSpec { name = n, ty = t } -> prim_func n t
  282. PrimTypeSpec { ty = t } -> prim_data t
  283. PrimVecTypeSpec { ty = t } -> prim_data t
  284. Section { } -> error "Section is not an entity"
  285. ]
  286. extra options = case on_llvm_only options ++ can_fail options of
  287. [m1,m2] -> "\n\n__/Warning:/__ this " ++ m1 ++ " and " ++ m2 ++ "."
  288. [m] -> "\n\n__/Warning:/__ this " ++ m ++ "."
  289. _ -> ""
  290. on_llvm_only options
  291. = [ "is only available on LLVM"
  292. | Just (OptionTrue _) <- [lookup_attrib "llvm_only" options] ]
  293. can_fail options
  294. = [ "can fail with an unchecked exception"
  295. | Just (OptionTrue _) <- [lookup_attrib "can_fail" options] ]
  296. prim_deprecated options n
  297. = [ "{-# DEPRECATED " ++ wrapOp n ++ " \"" ++ msg ++ "\" #-}"
  298. | Just (OptionString _ msg)
  299. <- [lookup_attrib "deprecated_msg" options] ]
  300. prim_fixity options n
  301. = [ pprFixityDir d ++ " " ++ show i ++ " " ++ asInfix n
  302. | OptionFixity (Just (Fixity _ i d)) <- options ]
  303. prim_func n t = [ wrapOp n ++ " :: " ++ pprTy t,
  304. wrapOp n ++ " = " ++ funcRhs n ]
  305. funcRhs "tagToEnum#" = "let x = x in x"
  306. funcRhs nm = wrapOp nm
  307. -- Special case for tagToEnum#: see Note [Placeholder declarations]
  308. prim_data t = [ "data " ++ pprTy t ]
  309. escape = concatMap (\c -> if c `elem` special then '\\':c:[] else c:[])
  310. where special = "/'`\"@<"
  311. unlatex :: String -> String
  312. unlatex s = case s of
  313. '\\':'t':'e':'x':'t':'t':'t':'{':cs -> markup "@" "@" cs
  314. '{':'\\':'t':'e':'x':'t':'t':'t':' ':cs -> markup "@" "@" cs
  315. '{':'\\':'t':'t':cs -> markup "@" "@" cs
  316. '{':'\\':'i':'t':cs -> markup "/" "/" cs
  317. '{':'\\':'e':'m':cs -> markup "/" "/" cs
  318. c : cs -> c : unlatex cs
  319. "" -> ""
  320. where markup b e xs = b ++ mk (dropWhile isSpace xs)
  321. where mk "" = e
  322. mk ('\n':cs) = ' ' : mk cs
  323. mk ('}':cs) = e ++ unlatex cs
  324. mk (c:cs) = c : mk cs
  325. -- | Extract a string representation of the name
  326. getName :: Entry -> Maybe String
  327. getName PrimOpSpec{ name = n } = Just n
  328. getName PrimVecOpSpec{ name = n } = Just n
  329. getName PseudoOpSpec{ name = n } = Just n
  330. getName PrimTypeSpec{ ty = TyApp tc _ } = Just (show tc)
  331. getName PrimVecTypeSpec{ ty = TyApp tc _ } = Just (show tc)
  332. getName _ = Nothing
  333. {- Note [Placeholder declarations]
  334. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  335. We are generating fake declarations for things in GHC.Prim, just to
  336. keep GHC's renamer and typechecker happy enough for what Haddock
  337. needs. Our main plan is to say
  338. foo :: <type>
  339. foo = foo
  340. That works for all the primitive functions except tagToEnum#.
  341. If we generate the binding
  342. tagToEnum# = tagToEnum#
  343. GHC will complain about "tagToEnum# must appear applied to one argument".
  344. We could hack GHC to silence this complaint when compiling GHC.Prim,
  345. but it seems easier to generate
  346. tagToEnum# = let x = x in x
  347. We don't do this for *all* bindings because for ones with an unboxed
  348. RHS we would get other complaints (e.g.can't unify "*" with "#").
  349. -}
  350. -- | "Pretty"-print a type
  351. pprTy :: Ty -> String
  352. pprTy = pty
  353. where
  354. pty (TyF t1 t2) = pbty t1 ++ " -> " ++ pty t2
  355. pty (TyC t1 t2) = pbty t1 ++ " => " ++ pty t2
  356. pty t = pbty t
  357. pbty (TyApp tc ts) = unwords (wrapOp (show tc) : map paty ts)
  358. pbty (TyUTup ts) = "(# "
  359. ++ concat (intersperse "," (map pty ts))
  360. ++ " #)"
  361. pbty t = paty t
  362. paty (TyVar tv) = tv
  363. paty t = "(" ++ pty t ++ ")"
  364. -- | Turn an identifier or operator into its prefix form
  365. wrapOp :: String -> String
  366. wrapOp nm | isAlpha (head nm) = nm
  367. | otherwise = "(" ++ nm ++ ")"
  368. -- | Turn an identifier or operator into its infix form
  369. asInfix :: String -> String
  370. asInfix nm | isAlpha (head nm) = "`" ++ nm ++ "`"
  371. | otherwise = nm
  372. gen_latex_doc :: Info -> String
  373. gen_latex_doc (Info defaults entries)
  374. = "\\primopdefaults{"
  375. ++ mk_options defaults
  376. ++ "}\n"
  377. ++ (concat (map mk_entry entries))
  378. where mk_entry (PrimOpSpec {cons=constr,name=n,ty=t,cat=c,desc=d,opts=o}) =
  379. "\\primopdesc{"
  380. ++ latex_encode constr ++ "}{"
  381. ++ latex_encode n ++ "}{"
  382. ++ latex_encode (zencode n) ++ "}{"
  383. ++ latex_encode (show c) ++ "}{"
  384. ++ latex_encode (mk_source_ty t) ++ "}{"
  385. ++ latex_encode (mk_core_ty t) ++ "}{"
  386. ++ d ++ "}{"
  387. ++ mk_options o
  388. ++ "}\n"
  389. mk_entry (PrimVecOpSpec {}) =
  390. ""
  391. mk_entry (Section {title=ti,desc=d}) =
  392. "\\primopsection{"
  393. ++ latex_encode ti ++ "}{"
  394. ++ d ++ "}\n"
  395. mk_entry (PrimTypeSpec {ty=t,desc=d,opts=o}) =
  396. "\\primtypespec{"
  397. ++ latex_encode (mk_source_ty t) ++ "}{"
  398. ++ latex_encode (mk_core_ty t) ++ "}{"
  399. ++ d ++ "}{"
  400. ++ mk_options o
  401. ++ "}\n"
  402. mk_entry (PrimVecTypeSpec {}) =
  403. ""
  404. mk_entry (PseudoOpSpec {name=n,ty=t,desc=d,opts=o}) =
  405. "\\pseudoopspec{"
  406. ++ latex_encode (zencode n) ++ "}{"
  407. ++ latex_encode (mk_source_ty t) ++ "}{"
  408. ++ latex_encode (mk_core_ty t) ++ "}{"
  409. ++ d ++ "}{"
  410. ++ mk_options o
  411. ++ "}\n"
  412. mk_source_ty typ = pty typ
  413. where pty (TyF t1 t2) = pbty t1 ++ " -> " ++ pty t2
  414. pty (TyC t1 t2) = pbty t1 ++ " => " ++ pty t2
  415. pty t = pbty t
  416. pbty (TyApp tc ts) = show tc ++ (concat (map (' ':) (map paty ts)))
  417. pbty (TyUTup ts) = "(# " ++ (concat (intersperse "," (map pty ts))) ++ " #)"
  418. pbty t = paty t
  419. paty (TyVar tv) = tv
  420. paty t = "(" ++ pty t ++ ")"
  421. mk_core_ty typ = foralls ++ (pty typ)
  422. where pty (TyF t1 t2) = pbty t1 ++ " -> " ++ pty t2
  423. pty (TyC t1 t2) = pbty t1 ++ " => " ++ pty t2
  424. pty t = pbty t
  425. pbty (TyApp tc ts) = (zencode (show tc)) ++ (concat (map (' ':) (map paty ts)))
  426. pbty (TyUTup ts) = (zencode (utuplenm (length ts))) ++ (concat ((map (' ':) (map paty ts))))
  427. pbty t = paty t
  428. paty (TyVar tv) = zencode tv
  429. paty (TyApp tc []) = zencode (show tc)
  430. paty t = "(" ++ pty t ++ ")"
  431. utuplenm 1 = "(# #)"
  432. utuplenm n = "(#" ++ (replicate (n-1) ',') ++ "#)"
  433. foralls = if tvars == [] then "" else "%forall " ++ (tbinds tvars)
  434. tvars = tvars_of typ
  435. tbinds [] = ". "
  436. tbinds ("o":tbs) = "(o::?) " ++ (tbinds tbs)
  437. tbinds ("p":tbs) = "(p::?) " ++ (tbinds tbs)
  438. tbinds (tv:tbs) = tv ++ " " ++ (tbinds tbs)
  439. tvars_of (TyF t1 t2) = tvars_of t1 `union` tvars_of t2
  440. tvars_of (TyC t1 t2) = tvars_of t1 `union` tvars_of t2
  441. tvars_of (TyApp _ ts) = foldl union [] (map tvars_of ts)
  442. tvars_of (TyUTup ts) = foldr union [] (map tvars_of ts)
  443. tvars_of (TyVar tv) = [tv]
  444. mk_options o =
  445. "\\primoptions{"
  446. ++ mk_has_side_effects o ++ "}{"
  447. ++ mk_out_of_line o ++ "}{"
  448. ++ mk_commutable o ++ "}{"
  449. ++ mk_needs_wrapper o ++ "}{"
  450. ++ mk_can_fail o ++ "}{"
  451. ++ mk_fixity o ++ "}{"
  452. ++ latex_encode (mk_strictness o) ++ "}{"
  453. ++ "}"
  454. mk_has_side_effects o = mk_bool_opt o "has_side_effects" "Has side effects." "Has no side effects."
  455. mk_out_of_line o = mk_bool_opt o "out_of_line" "Implemented out of line." "Implemented in line."
  456. mk_commutable o = mk_bool_opt o "commutable" "Commutable." "Not commutable."
  457. mk_needs_wrapper o = mk_bool_opt o "needs_wrapper" "Needs wrapper." "Needs no wrapper."
  458. mk_can_fail o = mk_bool_opt o "can_fail" "Can fail." "Cannot fail."
  459. mk_bool_opt o opt_name if_true if_false =
  460. case lookup_attrib opt_name o of
  461. Just (OptionTrue _) -> if_true
  462. Just (OptionFalse _) -> if_false
  463. Just (OptionString _ _) -> error "String value for boolean option"
  464. Just (OptionInteger _ _) -> error "Integer value for boolean option"
  465. Just (OptionFixity _) -> error "Fixity value for boolean option"
  466. Just (OptionVector _) -> error "vector template for boolean option"
  467. Nothing -> ""
  468. mk_strictness o =
  469. case lookup_attrib "strictness" o of
  470. Just (OptionString _ s) -> s -- for now
  471. Just _ -> error "Wrong value for strictness"
  472. Nothing -> ""
  473. mk_fixity o = case lookup_attrib "fixity" o of
  474. Just (OptionFixity (Just (Fixity _ i d)))
  475. -> pprFixityDir d ++ " " ++ show i
  476. _ -> ""
  477. zencode xs =
  478. case maybe_tuple xs of
  479. Just n -> n -- Tuples go to Z2T etc
  480. Nothing -> concat (map encode_ch xs)
  481. where
  482. maybe_tuple "(# #)" = Just("Z1H")
  483. maybe_tuple ('(' : '#' : cs) = case count_commas (0::Int) cs of
  484. (n, '#' : ')' : _) -> Just ('Z' : shows (n+1) "H")
  485. _ -> Nothing
  486. maybe_tuple "()" = Just("Z0T")
  487. maybe_tuple ('(' : cs) = case count_commas (0::Int) cs of
  488. (n, ')' : _) -> Just ('Z' : shows (n+1) "T")
  489. _ -> Nothing
  490. maybe_tuple _ = Nothing
  491. count_commas :: Int -> String -> (Int, String)
  492. count_commas n (',' : cs) = count_commas (n+1) cs
  493. count_commas n cs = (n,cs)
  494. unencodedChar :: Char -> Bool -- True for chars that don't need encoding
  495. unencodedChar 'Z' = False
  496. unencodedChar 'z' = False
  497. unencodedChar c = isAlphaNum c
  498. encode_ch :: Char -> String
  499. encode_ch c | unencodedChar c = [c] -- Common case first
  500. -- Constructors
  501. encode_ch '(' = "ZL" -- Needed for things like (,), and (->)
  502. encode_ch ')' = "ZR" -- For symmetry with (
  503. encode_ch '[' = "ZM"
  504. encode_ch ']' = "ZN"
  505. encode_ch ':' = "ZC"
  506. encode_ch 'Z' = "ZZ"
  507. -- Variables
  508. encode_ch 'z' = "zz"
  509. encode_ch '&' = "za"
  510. encode_ch '|' = "zb"
  511. encode_ch '^' = "zc"
  512. encode_ch '$' = "zd"
  513. encode_ch '=' = "ze"
  514. encode_ch '>' = "zg"
  515. encode_ch '#' = "zh"
  516. encode_ch '.' = "zi"
  517. encode_ch '<' = "zl"
  518. encode_ch '-' = "zm"
  519. encode_ch '!' = "zn"
  520. encode_ch '+' = "zp"
  521. encode_ch '\'' = "zq"
  522. encode_ch '\\' = "zr"
  523. encode_ch '/' = "zs"
  524. encode_ch '*' = "zt"
  525. encode_ch '_' = "zu"
  526. encode_ch '%' = "zv"
  527. encode_ch c = 'z' : shows (ord c) "U"
  528. latex_encode [] = []
  529. latex_encode (c:cs) | c `elem` "#$%&_^{}" = "\\" ++ c:(latex_encode cs)
  530. latex_encode ('~':cs) = "\\verb!~!" ++ (latex_encode cs)
  531. latex_encode ('\\':cs) = "$\\backslash$" ++ (latex_encode cs)
  532. latex_encode (c:cs) = c:(latex_encode cs)
  533. gen_wrappers :: Info -> String
  534. gen_wrappers (Info _ entries)
  535. = "{-# LANGUAGE MagicHash, NoImplicitPrelude, UnboxedTuples #-}\n"
  536. -- Dependencies on Prelude must be explicit in libraries/base, but we
  537. -- don't need the Prelude here so we add NoImplicitPrelude.
  538. ++ "{-# OPTIONS_GHC -Wno-deprecations -O0 #-}\n"
  539. -- No point in optimising this at all.
  540. -- Performing WW on this module is harmful even, two reasons:
  541. -- 1. Inferred strictness signatures are all bottom, which is a lie
  542. -- 2. Doing the worker/wrapper split based on that information will
  543. -- introduce references to absentError,
  544. -- which isn't available at this point.
  545. ++ "module GHC.PrimopWrappers where\n"
  546. ++ "import qualified GHC.Prim\n"
  547. ++ "import GHC.Tuple ()\n"
  548. ++ "import GHC.Prim (" ++ types ++ ")\n"
  549. ++ unlines (concatMap f specs)
  550. where
  551. specs = filter (not.dodgy) $
  552. filter (not.is_llvm_only) $
  553. filter is_primop entries
  554. tycons = foldr union [] $ map (tyconsIn . ty) specs
  555. tycons' = filter (`notElem` [TyCon "()", TyCon "Bool"]) tycons
  556. types = concat $ intersperse ", " $ map show tycons'
  557. f spec = let args = map (\n -> "a" ++ show n) [1 .. arity (ty spec)]
  558. src_name = wrap (name spec)
  559. lhs = src_name ++ " " ++ unwords args
  560. rhs = "(GHC.Prim." ++ name spec ++ ") " ++ unwords args
  561. in ["{-# NOINLINE " ++ src_name ++ " #-}",
  562. src_name ++ " :: " ++ pprTy (ty spec),
  563. lhs ++ " = " ++ rhs]
  564. wrap nm | isLower (head nm) = nm
  565. | otherwise = "(" ++ nm ++ ")"
  566. dodgy spec
  567. = name spec `elem`
  568. [-- tagToEnum# is really magical, and can't have
  569. -- a wrapper since its implementation depends on
  570. -- the type of its result
  571. "tagToEnum#"
  572. ]
  573. is_llvm_only :: Entry -> Bool
  574. is_llvm_only entry =
  575. case lookup_attrib "llvm_only" (opts entry) of
  576. Just (OptionTrue _) -> True
  577. _ -> False
  578. gen_primop_list :: Info -> String
  579. gen_primop_list (Info _ entries)
  580. = unlines (
  581. [ " [" ++ cons first ]
  582. ++
  583. map (\p -> " , " ++ cons p) rest
  584. ++
  585. [ " ]" ]
  586. ) where (first:rest) = concatMap desugarVectorSpec (filter is_primop entries)
  587. mIN_VECTOR_UNIQUE :: Int
  588. mIN_VECTOR_UNIQUE = 300
  589. gen_primop_vector_uniques :: Info -> String
  590. gen_primop_vector_uniques (Info _ entries)
  591. = unlines $
  592. concatMap mkVecUnique (specs `zip` [mIN_VECTOR_UNIQUE..])
  593. where
  594. specs = concatMap desugarVectorSpec (filter is_vector (filter is_primtype entries))
  595. mkVecUnique :: (Entry, Int) -> [String]
  596. mkVecUnique (i, unique) =
  597. [ key_id ++ " :: Unique"
  598. , key_id ++ " = mkPreludeTyConUnique " ++ show unique
  599. ]
  600. where
  601. key_id = prefix i ++ "PrimTyConKey"
  602. gen_primop_vector_tys :: Info -> String
  603. gen_primop_vector_tys (Info _ entries)
  604. = unlines $
  605. concatMap mkVecTypes specs
  606. where
  607. specs = concatMap desugarVectorSpec (filter is_vector (filter is_primtype entries))
  608. mkVecTypes :: Entry -> [String]
  609. mkVecTypes i =
  610. [ name_id ++ " :: Name"
  611. , name_id ++ " = mkPrimTc (fsLit \"" ++ pprTy (ty i) ++ "\") " ++ key_id ++ " " ++ tycon_id
  612. , ty_id ++ " :: Type"
  613. , ty_id ++ " = mkTyConTy " ++ tycon_id
  614. , tycon_id ++ " :: TyCon"
  615. , tycon_id ++ " = pcPrimTyCon0 " ++ name_id ++
  616. " (VecRep " ++ show (veclen i) ++ " " ++ elemrep i ++ ")"
  617. ]
  618. where
  619. key_id = prefix i ++ "PrimTyConKey"
  620. name_id = prefix i ++ "PrimTyConName"
  621. ty_id = prefix i ++ "PrimTy"
  622. tycon_id = prefix i ++ "PrimTyCon"
  623. gen_primop_vector_tys_exports :: Info -> String
  624. gen_primop_vector_tys_exports (Info _ entries)
  625. = unlines $
  626. map mkVecTypes specs
  627. where
  628. specs = concatMap desugarVectorSpec (filter is_vector (filter is_primtype entries))
  629. mkVecTypes :: Entry -> String
  630. mkVecTypes i =
  631. " " ++ ty_id ++ ", " ++ tycon_id ++ ","
  632. where
  633. ty_id = prefix i ++ "PrimTy"
  634. tycon_id = prefix i ++ "PrimTyCon"
  635. gen_primop_vector_tycons :: Info -> String
  636. gen_primop_vector_tycons (Info _ entries)
  637. = unlines $
  638. map mkVecTypes specs
  639. where
  640. specs = concatMap desugarVectorSpec (filter is_vector (filter is_primtype entries))
  641. mkVecTypes :: Entry -> String
  642. mkVecTypes i =
  643. " , " ++ tycon_id
  644. where
  645. tycon_id = prefix i ++ "PrimTyCon"
  646. gen_primop_tag :: Info -> String
  647. gen_primop_tag (Info _ entries)
  648. = unlines (max_def_type : max_def :
  649. tagOf_type : zipWith f primop_entries [1 :: Int ..])
  650. where
  651. primop_entries = concatMap desugarVectorSpec $ filter is_primop entries
  652. tagOf_type = "primOpTag :: PrimOp -> Int"
  653. f i n = "primOpTag " ++ cons i ++ " = " ++ show n
  654. max_def_type = "maxPrimOpTag :: Int"
  655. max_def = "maxPrimOpTag = " ++ show (length primop_entries)
  656. gen_data_decl :: Info -> String
  657. gen_data_decl (Info _ entries) =
  658. "data PrimOp\n = " ++ head conss ++ "\n"
  659. ++ unlines (map (" | "++) (tail conss))
  660. where
  661. conss = map genCons (filter is_primop entries)
  662. genCons :: Entry -> String
  663. genCons entry =
  664. case vecOptions entry of
  665. [] -> cons entry
  666. _ -> cons entry ++ " PrimOpVecCat Length Width"
  667. gen_switch_from_attribs :: String -> String -> Info -> String
  668. gen_switch_from_attribs attrib_name fn_name (Info defaults entries)
  669. = let defv = lookup_attrib attrib_name defaults
  670. alternatives = catMaybes (map mkAlt (filter is_primop entries))
  671. getAltRhs (OptionFalse _) = "False"
  672. getAltRhs (OptionTrue _) = "True"
  673. getAltRhs (OptionInteger _ i) = show i
  674. getAltRhs (OptionString _ s) = s
  675. getAltRhs (OptionVector _) = "True"
  676. getAltRhs (OptionFixity mf) = show mf
  677. mkAlt po
  678. = case lookup_attrib attrib_name (opts po) of
  679. Nothing -> Nothing
  680. Just xx -> case vecOptions po of
  681. [] -> Just (fn_name ++ " " ++ cons po ++ " = " ++ getAltRhs xx)
  682. _ -> Just (fn_name ++ " (" ++ cons po ++ " _ _ _) = " ++ getAltRhs xx)
  683. in
  684. case defv of
  685. Nothing -> error ("gen_switch_from: " ++ attrib_name)
  686. Just xx
  687. -> unlines alternatives
  688. ++ fn_name ++ " _ = " ++ getAltRhs xx ++ "\n"
  689. {-
  690. Note [GHC.Prim Docs]
  691. ~~~~~~~~~~~~~~~~~~~~
  692. For haddocks of GHC.Prim we generate a dummy haskell file (gen_hs_source) that
  693. contains the type signatures and the commends (but no implementations)
  694. specifically for consumption by haddock.
  695. GHCi's :doc command reads directly from ModIface's though, and GHC.Prim has a
  696. wired-in iface that has nothing to do with the above haskell file. The code
  697. below converts primops.txt into an intermediate form that would later be turned
  698. into a proper DeclDocMap.
  699. We output the docs as a list of pairs (name, docs). We use stringy names here
  700. because mapping names to "Name"s is difficult for things like primtypes and
  701. pseudoops.
  702. -}
  703. gen_wired_in_docs :: Info -> String
  704. gen_wired_in_docs (Info _ entries)
  705. = "primOpDocs =\n [ " ++ intercalate "\n , " (catMaybes $ map mkDoc $ concatMap desugarVectorSpec entries) ++ "\n ]\n"
  706. where
  707. mkDoc po | Just poName <- getName po
  708. , not $ null $ desc po = Just $ show (poName, unlatex $ desc po)
  709. | otherwise = Nothing
  710. ------------------------------------------------------------------
  711. -- Create PrimOpInfo text from PrimOpSpecs -----------------------
  712. ------------------------------------------------------------------
  713. gen_primop_info :: Info -> String
  714. gen_primop_info (Info _ entries)
  715. = unlines (map mkPOItext (concatMap desugarVectorSpec (filter is_primop entries)))
  716. mkPOItext :: Entry -> String
  717. mkPOItext i = mkPOI_LHS_text i ++ mkPOI_RHS_text i
  718. mkPOI_LHS_text :: Entry -> String
  719. mkPOI_LHS_text i
  720. = "primOpInfo " ++ cons i ++ " = "
  721. mkPOI_RHS_text :: Entry -> String
  722. mkPOI_RHS_text i
  723. = case cat i of
  724. Compare
  725. -> case ty i of
  726. TyF t1 (TyF _ _)
  727. -> "mkCompare " ++ sl_name i ++ ppType t1
  728. _ -> error "Type error in comparison op"
  729. GenPrimOp
  730. -> let (argTys, resTy) = flatTys (ty i)
  731. tvs = nub (tvsIn (ty i))
  732. in
  733. "mkGenPrimOp " ++ sl_name i ++ " "
  734. ++ listify (map ppTyVar tvs) ++ " "
  735. ++ listify (map ppType argTys) ++ " "
  736. ++ "(" ++ ppType resTy ++ ")"
  737. sl_name :: Entry -> String
  738. sl_name i = "(fsLit \"" ++ name i ++ "\") "
  739. ppTyVar :: String -> String
  740. ppTyVar "a" = "alphaTyVarSpec"
  741. ppTyVar "b" = "betaTyVarSpec"
  742. ppTyVar "c" = "gammaTyVarSpec"
  743. ppTyVar "s" = "deltaTyVarSpec"
  744. ppTyVar "o" = "runtimeRep1TyVarInf, openAlphaTyVarSpec"
  745. ppTyVar "p" = "runtimeRep2TyVarInf, openBetaTyVarSpec"
  746. ppTyVar "v" = "levity1TyVarInf, levPolyAlphaTyVarSpec"
  747. ppTyVar "w" = "levity2TyVarInf, levPolyBetaTyVarSpec"
  748. ppTyVar _ = error "Unknown type var"
  749. -- o, p, v and w have a special meaning. See primops.txt.pp
  750. -- Note [Levity and representation polymorphic primops]
  751. ppType :: Ty -> String
  752. ppType (TyApp (TyCon "Any") []) = "anyTy"
  753. ppType (TyApp (TyCon "Bool") []) = "boolTy"
  754. ppType (TyApp (TyCon "Int#") []) = "intPrimTy"
  755. ppType (TyApp (TyCon "Int8#") []) = "int8PrimTy"
  756. ppType (TyApp (TyCon "Int16#") []) = "int16PrimTy"
  757. ppType (TyApp (TyCon "Int32#") []) = "int32PrimTy"
  758. ppType (TyApp (TyCon "Int64#") []) = "int64PrimTy"
  759. ppType (TyApp (TyCon "Char#") []) = "charPrimTy"
  760. ppType (TyApp (TyCon "Word#") []) = "wordPrimTy"
  761. ppType (TyApp (TyCon "Word8#") []) = "word8PrimTy"
  762. ppType (TyApp (TyCon "Word16#") []) = "word16PrimTy"
  763. ppType (TyApp (TyCon "Word32#") []) = "word32PrimTy"
  764. ppType (TyApp (TyCon "Word64#") []) = "word64PrimTy"
  765. ppType (TyApp (TyCon "Addr#") []) = "addrPrimTy"
  766. ppType (TyApp (TyCon "Float#") []) = "floatPrimTy"
  767. ppType (TyApp (TyCon "Double#") []) = "doublePrimTy"
  768. ppType (TyApp (TyCon "ByteArray#") []) = "byteArrayPrimTy"
  769. ppType (TyApp (TyCon "RealWorld") []) = "realWorldTy"
  770. ppType (TyApp (TyCon "ThreadId#") []) = "threadIdPrimTy"
  771. ppType (TyApp (TyCon "ForeignObj#") []) = "foreignObjPrimTy"
  772. ppType (TyApp (TyCon "BCO") []) = "bcoPrimTy"
  773. ppType (TyApp (TyCon "Compact#") []) = "compactPrimTy"
  774. ppType (TyApp (TyCon "StackSnapshot#") []) = "stackSnapshotPrimTy"
  775. ppType (TyApp (TyCon "()") []) = "unitTy" -- unitTy is GHC.Builtin.Types's name for ()
  776. ppType (TyVar "a") = "alphaTy"
  777. ppType (TyVar "b") = "betaTy"
  778. ppType (TyVar "c") = "gammaTy"
  779. ppType (TyVar "s") = "deltaTy"
  780. ppType (TyVar "o") = "openAlphaTy"
  781. ppType (TyVar "p") = "openBetaTy"
  782. ppType (TyVar "v") = "levPolyAlphaTy"
  783. ppType (TyVar "w") = "levPolyBetaTy"
  784. -- o, p, v and w have a special meaning. See primops.txt.pp
  785. -- Note [Levity and representation polymorphic primops]
  786. ppType (TyApp (TyCon "State#") [x]) = "mkStatePrimTy " ++ ppType x
  787. ppType (TyApp (TyCon "MutVar#") [x,y]) = "mkMutVarPrimTy " ++ ppType x
  788. ++ " " ++ ppType y
  789. ppType (TyApp (TyCon "MutableArray#") [x,y]) = "mkMutableArrayPrimTy " ++ ppType x
  790. ++ " " ++ ppType y
  791. ppType (TyApp (TyCon "MutableArrayArray#") [x]) = "mkMutableArrayArrayPrimTy " ++ ppType x
  792. ppType (TyApp (TyCon "SmallMutableArray#") [x,y]) = "mkSmallMutableArrayPrimTy " ++ ppType x
  793. ++ " " ++ ppType y
  794. ppType (TyApp (TyCon "MutableByteArray#") [x]) = "mkMutableByteArrayPrimTy "
  795. ++ ppType x
  796. ppType (TyApp (TyCon "Array#") [x]) = "mkArrayPrimTy " ++ ppType x
  797. ppType (TyApp (TyCon "ArrayArray#") []) = "mkArrayArrayPrimTy"
  798. ppType (TyApp (TyCon "SmallArray#") [x]) = "mkSmallArrayPrimTy " ++ ppType x
  799. ppType (TyApp (TyCon "Weak#") [x]) = "mkWeakPrimTy " ++ ppType x
  800. ppType (TyApp (TyCon "StablePtr#") [x]) = "mkStablePtrPrimTy " ++ ppType x
  801. ppType (TyApp (TyCon "StableName#") [x]) = "mkStableNamePrimTy " ++ ppType x
  802. ppType (TyApp (TyCon "MVar#") [x,y]) = "mkMVarPrimTy " ++ ppType x
  803. ++ " " ++ ppType y
  804. ppType (TyApp (TyCon "IOPort#") [x,y]) = "mkIOPortPrimTy " ++ ppType x
  805. ++ " " ++ ppType y
  806. ppType (TyApp (TyCon "TVar#") [x,y]) = "mkTVarPrimTy " ++ ppType x
  807. ++ " " ++ ppType y
  808. ppType (TyApp (VecTyCon _ pptc) []) = pptc
  809. ppType (TyUTup ts) = "(mkTupleTy Unboxed "
  810. ++ listify (map ppType ts) ++ ")"
  811. ppType (TyF s d) = "(mkVisFunTyMany (" ++ ppType s ++ ") (" ++ ppType d ++ "))"
  812. ppType (TyC s d) = "(mkInvisFunTyMany (" ++ ppType s ++ ") (" ++ ppType d ++ "))"
  813. ppType other
  814. = error ("ppType: can't handle: " ++ show other ++ "\n")
  815. pprFixityDir :: FixityDirection -> String
  816. pprFixityDir InfixN = "infix"
  817. pprFixityDir InfixL = "infixl"
  818. pprFixityDir InfixR = "infixr"
  819. listify :: [String] -> String
  820. listify ss = "[" ++ concat (intersperse ", " ss) ++ "]"
  821. flatTys :: Ty -> ([Ty],Ty)
  822. flatTys (TyF t1 t2) = case flatTys t2 of (ts,t) -> (t1:ts,t)
  823. flatTys (TyC t1 t2) = case flatTys t2 of (ts,t) -> (t1:ts,t)
  824. flatTys other = ([],other)
  825. tvsIn :: Ty -> [TyVar]
  826. tvsIn (TyF t1 t2) = tvsIn t1 ++ tvsIn t2
  827. tvsIn (TyC t1 t2) = tvsIn t1 ++ tvsIn t2
  828. tvsIn (TyApp _ tys) = concatMap tvsIn tys
  829. tvsIn (TyVar tv) = [tv]
  830. tvsIn (TyUTup tys) = concatMap tvsIn tys
  831. tyconsIn :: Ty -> [TyCon]
  832. tyconsIn (TyF t1 t2) = tyconsIn t1 `union` tyconsIn t2
  833. tyconsIn (TyC t1 t2) = tyconsIn t1 `union` tyconsIn t2
  834. tyconsIn (TyApp tc tys) = foldr union [tc] $ map tyconsIn tys
  835. tyconsIn (TyVar _) = []
  836. tyconsIn (TyUTup tys) = foldr union [] $ map tyconsIn tys
  837. arity :: Ty -> Int
  838. arity = length . fst . flatTys