git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Add Prim docs to the library, resolves #2494 (#2498)

* Add Prim docs to the library, resolves #2494 * Use 'a' in the Char example * Link to placeholder documentation page

commita1e22ec6d8b5e10d56237b5fcfdbcdd06b03a87c authorHarry Garrood <harry@garrood.me> dateSat 24 Dec 2016, 02:55 (10 years ago) parentc2bd953
7 files changed+259−18
purescript.cabal+2 src/Language/PureScript/Docs.hs+1 src/Language/PureScript/Docs/Convert/Single.hs+1−18 src/Language/PureScript/Docs/Prim.hs+205 src/Language/PureScript/Docs/Types.hs+21 tests/Main.hs+2 tests/TestPrimDocs.hs+27
purescript.cabal+2
@@ -250,6 +250,7 @@ library
250250 Language.PureScript.Docs.Convert
251251 Language.PureScript.Docs.Convert.Single
252252 Language.PureScript.Docs.Convert.ReExports
253+ Language.PureScript.Docs.Prim
253254 Language.PureScript.Docs.Render
254255 Language.PureScript.Docs.Types
255256 Language.PureScript.Docs.RenderedCode
@@ -539,6 +540,7 @@ test-suite tests
539540 other-modules: TestUtils
540541 TestCompiler
541542 TestDocs
543+ TestPrimDocs
542544 TestPscPublish
543545 TestPsci
544546 TestPscIde
src/Language/PureScript/Docs.hs+1
@@ -7,6 +7,7 @@ module Language.PureScript.Docs (
77) where
88
99import Language.PureScript.Docs.Convert as Docs
10+import Language.PureScript.Docs.Prim as Docs
1011import Language.PureScript.Docs.ParseAndBookmark as Docs
1112import Language.PureScript.Docs.Render as Docs
1213import Language.PureScript.Docs.RenderedCode.Render as Docs
src/Language/PureScript/Docs/Convert/Single.hs+1−18
@@ -9,14 +9,12 @@ import Control.Arrow (first)
99import Control.Category ((>>>))
1010import Control.Monad
1111
12−import Data.Bifunctor (bimap)
1312import Data.Either
1413import Data.List (nub)
1514import Data.Maybe (mapMaybe)
1615import Data.Monoid ((<>))
1716import Data.Text (Text)
1817import qualified Data.Text as T
19−import qualified Data.Vector as V
2018
2119import Language.PureScript.Docs.Types
2220import qualified Language.PureScript as P
@@ -132,7 +130,7 @@ convertDeclaration (P.TypeSynonymDeclaration _ args ty) title =
132130convertDeclaration (P.TypeClassDeclaration _ args implies fundeps ds) title =
133131 Just (Right (mkDeclaration title info) { declChildren = children })
134132 where
135− info = TypeClassDeclaration (map (first T.unpack) args) implies (map (bimap (map T.unpack) (map T.unpack)) fundeps')
133+ info = TypeClassDeclaration (map (first T.unpack) args) implies (convertFundepsToStrings args fundeps)
136134 children = map convertClassMember ds
137135 convertClassMember (P.PositionedDeclaration _ _ d) =
138136 convertClassMember d
@@ -140,21 +138,6 @@ convertDeclaration (P.TypeClassDeclaration _ args implies fundeps ds) title =
140138 ChildDeclaration (T.unpack (P.showIdent ident')) Nothing Nothing (ChildTypeClassMember ty)
141139 convertClassMember _ =
142140 P.internalError "convertDeclaration: Invalid argument to convertClassMember."
143− fundeps' = map (\(P.FunctionalDependency from to) -> toArgs from to) fundeps
144− where
145− argsVec = V.fromList (map fst args)
146− getArg i =
147− maybe
148− (P.internalError $ unlines
149− [ "convertDeclaration: Functional dependency index"
150− , show i
151− , "is bigger than arguments list"
152− , show (map fst args)
153− , "Functional dependencies are"
154− , show fundeps
155− ]
156− ) id $ argsVec V.!? i
157− toArgs from to = (map getArg from, map getArg to)
158141convertDeclaration (P.TypeInstanceDeclaration _ constraints className tys _) title =
159142 Just (Left (T.unpack classNameString : map T.unpack typeNameStrings, AugmentChild childDecl))
160143 where
src/Language/PureScript/Docs/Prim.hsnew file+205
@@ -0,0 +1,205 @@
1+-- | This module provides documentation for the builtin Prim module.
2+module Language.PureScript.Docs.Prim (primDocsModule) where
3+
4+import Prelude.Compat hiding (fail)
5+import Control.Arrow (first)
6+import qualified Data.Text as T
7+import qualified Data.Map as Map
8+import Language.PureScript.Docs.Types
9+import qualified Language.PureScript as P
10+
11+primDocsModule :: Module
12+primDocsModule = Module
13+ { modName = P.moduleNameFromString "Prim"
14+ , modComments = Just "The Prim module is embedded in the PureScript compiler in order to provide compiler support for certain types &mdash; for example, value literals, or syntax sugar."
15+ , modDeclarations =
16+ [ function
17+ , array
18+ , record
19+ , number
20+ , int
21+ , string
22+ , char
23+ , boolean
24+ , partial
25+ , fail
26+ , typeConcat
27+ , typeString
28+ ]
29+ , modReExports = []
30+ }
31+
32+unsafeLookup :: forall v (a :: P.ProperNameType).
33+ Map.Map (P.Qualified (P.ProperName a)) v -> String -> String -> v
34+unsafeLookup m errorMsg ty = go ty
35+ where
36+ go = fromJust' . flip Map.lookup m . P.primName . T.pack
37+
38+ fromJust' (Just x) = x
39+ fromJust' _ = P.internalError $ errorMsg ++ ty
40+
41+lookupPrimKind :: String -> P.Kind
42+lookupPrimKind = fst . unsafeLookup P.primTypes "Docs.Prim: No such Prim type: "
43+
44+primType :: String -> String -> Declaration
45+primType title comments = Declaration
46+ { declTitle = title
47+ , declComments = Just comments
48+ , declSourceSpan = Nothing
49+ , declChildren = []
50+ , declInfo = ExternDataDeclaration (lookupPrimKind title)
51+ }
52+
53+-- | Lookup the TypeClassData of a Prim class. This function is specifically
54+-- not exported because it is partial.
55+lookupPrimClass :: String -> P.TypeClassData
56+lookupPrimClass = unsafeLookup P.primClasses "Docs.Prim: No such Prim class: "
57+
58+primClass :: String -> String -> Declaration
59+primClass title comments = Declaration
60+ { declTitle = title
61+ , declComments = Just comments
62+ , declSourceSpan = Nothing
63+ , declChildren = []
64+ , declInfo =
65+ let
66+ tcd = lookupPrimClass title
67+ args = P.typeClassArguments tcd
68+ superclasses = P.typeClassSuperclasses tcd
69+ fundeps = convertFundepsToStrings args (P.typeClassDependencies tcd)
70+ in
71+ TypeClassDeclaration (map (first T.unpack) args) superclasses fundeps
72+ }
73+
74+function :: Declaration
75+function = primType "Function" $ unlines
76+ [ "A function, which takes values of the type specified by the first type"
77+ , "parameter, and returns values of the type specified by the second."
78+ , "In the JavaScript backend, this is a standard JavaScript Function."
79+ , ""
80+ , "The type constructor `(->)` is syntactic sugar for this type constructor."
81+ , "It is recommended to use `(->)` rather than `Function`, where possible."
82+ , ""
83+ , "That is, prefer this:"
84+ , ""
85+ , " f :: Number -> Number"
86+ , ""
87+ , "to either of these:"
88+ , ""
89+ , " f :: Function Number Number"
90+ , " f :: (->) Number Number"
91+ ]
92+
93+array :: Declaration
94+array = primType "Array" $ unlines
95+ [ "An Array: a data structure supporting efficient random access. In"
96+ , "the JavaScript backend, values of this type are represented as JavaScript"
97+ , "Arrays at runtime."
98+ , ""
99+ , "Construct values using literals:"
100+ , ""
101+ , " x = [1,2,3,4,5] :: Array Int"
102+ ]
103+
104+record :: Declaration
105+record = primType "Record" $ unlines
106+ [ "The type of records whose fields are known at compile time. In the"
107+ , "JavaScript backend, values of this type are represented as JavaScript"
108+ , "Objects at runtime."
109+ , ""
110+ , "The type signature here means that the `Record` type constructor takes"
111+ , "a row of concrete types. For example:"
112+ , ""
113+ , " type Person = Record (name :: String, age :: Number)"
114+ , ""
115+ , "The syntactic sugar with curly braces `{ }` is generally preferred, though:"
116+ , ""
117+ , " type Person = { name :: String, age :: Number }"
118+ ]
119+
120+number :: Declaration
121+number = primType "Number" $ unlines
122+ [ "A double precision floating point number (IEEE 754)."
123+ , ""
124+ , "Construct values of this type with literals:"
125+ , ""
126+ , " y = 35.23 :: Number"
127+ , " z = 1.224e6 :: Number"
128+ ]
129+
130+int :: Declaration
131+int = primType "Int" $ unlines
132+ [ "A 32-bit signed integer. See the purescript-integers package for details"
133+ , "of how this is accomplished when compiling to JavaScript."
134+ , ""
135+ , "Construct values of this type with literals:"
136+ , ""
137+ , " x = 23 :: Int"
138+ ]
139+
140+string :: Declaration
141+string = primType "String" $ unlines
142+ [ "A String. As in JavaScript, String values represent sequences of UTF-16"
143+ , "code units, which are not required to form a valid encoding of Unicode"
144+ , "text (for example, lone surrogates are permitted)."
145+ , ""
146+ , "Construct values of this type with literals, using double quotes `\"`:"
147+ , ""
148+ , " x = \"hello, world\" :: String"
149+ , ""
150+ , "Multi-line string literals are also supported with triple quotes (`\"\"\"`)."
151+ ]
152+
153+char :: Declaration
154+char = primType "Char" $ unlines
155+ [ "A single character (UTF-16 code unit). The JavaScript representation is a"
156+ , "normal String, which is guaranteed to contain one code unit. This means"
157+ , "that astral plane characters (i.e. those with code point values greater"
158+ , "than 0xFFFF) cannot be represented as Char values."
159+ , ""
160+ , "Construct values of this type with literals, using single quotes `'`:"
161+ , ""
162+ , " x = 'a' :: Char"
163+ ]
164+
165+boolean :: Declaration
166+boolean = primType "Boolean" $ unlines
167+ [ "A JavaScript Boolean value."
168+ , ""
169+ , "Construct values of this type with the literals `true` and `false`."
170+ ]
171+
172+partial :: Declaration
173+partial = primClass "Partial" $ unlines
174+ [ "The Partial type class is used to indicate that a function is *partial,*"
175+ , "that is, it will throw an error for some inputs. For more information,"
176+ , "see [the Partial type class guide](https://github.com/purescript/documentation/blob/master/guides/The-Partial-type-class.md)."
177+ ]
178+
179+fail :: Declaration
180+fail = primClass "Fail" $ unlines
181+ [ "The Fail type class is part of the custom type errors feature. To provide"
182+ , "a custom type error when someone tries to use a particular instance,"
183+ , "write that instance out with a Fail constraint."
184+ , ""
185+ , "For more information, see"
186+ , "[the Custom Type Errors guide](https://github.com/purescript/documentation/blob/master/guides/Custom-Type-Errors.md)."
187+ ]
188+
189+typeConcat :: Declaration
190+typeConcat = primType "TypeConcat" $ unlines
191+ [ "The TypeConcat type constructor concatenates two Symbols in a custom type"
192+ , "error."
193+ , ""
194+ , "For more information, see"
195+ , "[the Custom Type Errors guide](https://github.com/purescript/documentation/blob/master/guides/Custom-Type-Errors.md)."
196+ ]
197+
198+typeString :: Declaration
199+typeString = primType "TypeString" $ unlines
200+ [ "The TypeString type constructor renders any concrete type into a Symbol"
201+ , "in a custom type error."
202+ , ""
203+ , "For more information, see"
204+ , "[the Custom Type Errors guide](https://github.com/purescript/documentation/blob/master/guides/Custom-Type-Errors.md)."
205+ ]
src/Language/PureScript/Docs/Types.hs+21
@@ -9,6 +9,7 @@ import Prelude.Compat
99import Control.Arrow (first, (***))
1010import Control.Monad (when)
1111
12+import Data.Bifunctor (bimap)
1213import Data.Aeson ((.=))
1314import Data.Aeson.BetterErrors
1415import Data.ByteString.Lazy (ByteString)
@@ -16,6 +17,7 @@ import Data.Either (isLeft, isRight)
1617import Data.Maybe (mapMaybe)
1718import Data.Text (Text)
1819import Data.Version
20+import qualified Data.Vector as V
1921import qualified Data.Aeson as A
2022import qualified Data.Text as T
2123
@@ -132,6 +134,25 @@ data DeclarationInfo
132134 | AliasDeclaration P.Fixity FixityAlias
133135 deriving (Show, Eq, Ord)
134136
137+convertFundepsToStrings :: [(Text, Maybe P.Kind)] -> [P.FunctionalDependency] -> [([String], [String])]
138+convertFundepsToStrings args fundeps =
139+ map (bimap (map T.unpack) (map T.unpack)) fundeps'
140+ where
141+ fundeps' = map (\(P.FunctionalDependency from to) -> toArgs from to) fundeps
142+ argsVec = V.fromList (map fst args)
143+ getArg i =
144+ maybe
145+ (P.internalError $ unlines
146+ [ "convertDeclaration: Functional dependency index"
147+ , show i
148+ , "is bigger than arguments list"
149+ , show (map fst args)
150+ , "Functional dependencies are"
151+ , show fundeps
152+ ]
153+ ) id $ argsVec V.!? i
154+ toArgs from to = (map getArg from, map getArg to)
155+
135156type FixityAlias = P.Qualified (Either (P.ProperName 'P.TypeName) (Either P.Ident (P.ProperName 'P.ConstructorName)))
136157
137158declInfoToString :: DeclarationInfo -> String
tests/Main.hs+2
@@ -13,6 +13,7 @@ import qualified TestDocs
1313import qualified TestPsci
1414import qualified TestPscIde
1515import qualified TestPscPublish
16+import qualified TestPrimDocs
1617import qualified TestUtils
1718
1819import System.IO (hSetEncoding, stdout, stderr, utf8)
@@ -28,6 +29,7 @@ main = do
2829 TestCompiler.main
2930 heading "Documentation test suite"
3031 TestDocs.main
32+ TestPrimDocs.main
3133 heading "psc-publish test suite"
3234 TestPscPublish.main
3335 heading "psci test suite"
tests/TestPrimDocs.hsnew file+27
@@ -0,0 +1,27 @@
1+module TestPrimDocs where
2+
3+import Control.Monad
4+import Data.List ((\\))
5+import qualified Data.Map as Map
6+import qualified Data.Text as T
7+import qualified Language.PureScript as P
8+import qualified Language.PureScript.Docs as D
9+import qualified Language.PureScript.Docs.AsMarkdown as D
10+
11+main :: IO ()
12+main = do
13+ putStrLn "Test that there are no bottoms hiding in primDocsModule"
14+ seq (T.pack (D.runDocs (D.modulesAsMarkdown [D.primDocsModule]))) (return ())
15+
16+ putStrLn "Test that Prim is fully documented"
17+ let actualPrimTypes = map (P.runProperName . P.disqualify . fst) $ Map.toList P.primTypes
18+ let documentedPrimTypes = map (T.pack . D.declTitle) (D.modDeclarations D.primDocsModule)
19+
20+ let undocumentedTypes = actualPrimTypes \\ documentedPrimTypes
21+ let extraTypes = documentedPrimTypes \\ actualPrimTypes
22+
23+ when (not (null undocumentedTypes)) $
24+ error $ "Undocumented Prim types: " ++ show undocumentedTypes
25+
26+ when (not (null extraTypes)) $
27+ error $ "Extra Prim types: " ++ show undocumentedTypes