@@ -1,12 +1,15 @@
1−{-# LANGUAGE TemplateHaskell #-}
3module Language.PureScript.Kinds where
1module Language.PureScript.Kinds where
5import Prelude.Compat
3import Prelude.Compat
5+import Data.Text (Text)
7−import qualified Data.Aeson.TH as A
6+import qualified Data.Text as T
7+import Data.Aeson.BetterErrors (Parse, key, asText, asIntegral, nth, fromAesonParser, toAesonParser, throwCustomError)
8+import Data.Aeson ((.=))
9+import qualified Data.Aeson as A
9import Language.PureScript.Names
11import Language.PureScript.Names
12+import qualified Language.PureScript.Constants as C
11-- | The data type of kinds
14-- | The data type of kinds
@@ -20,7 +23,66 @@ data Kind
20 | NamedKind (Qualified (ProperName 'KindName))
23 | NamedKind (Qualified (ProperName 'KindName))
21 deriving (Show, Eq, Ord)
24 deriving (Show, Eq, Ord)
23−$(A.deriveJSON A.defaultOptions ''Kind)
26+-- This is equivalent to the derived Aeson ToJSON instance, except that we
27+-- write it out manually so that we can define a parser which is
28+-- backwards-compatible.
29+instance A.ToJSON Kind where
30+ toJSON kind = case kind of
36+ obj "FunKind" [k1, k2]
40+ obj :: A.ToJSON a => Text -> a -> A.Value
42+ A.object [ "tag" .= tag, "contents" .= contents ]
44+-- This is equivalent to the derived Aeson FromJSON instance, except that it
45+-- also handles JSON generated by compilers up to 0.10.3 and maps them to the
46+-- new representations (i.e. NamedKinds which are defined in the Prim module).
47+kindFromJSON :: Parse Text Kind
49+ t <- key "tag" asText
52+ KUnknown <$> key "contents" (nth 0 asIntegral)
58+ Row <$> key "contents" kindFromJSON
61+ kindAt n = key "contents" (nth n kindFromJSON)
63+ FunKind <$> kindAt 0 <*> kindAt 1
67+ NamedKind <$> key "contents" fromAesonParser
69+ throwCustomError (T.append "Unrecognised tag: " other)
72+ -- The following are copied from Environment and reimplemented to avoid
73+ -- circular dependencies.
74+ primName :: Text -> Qualified (ProperName a)
75+ primName = Qualified (Just $ ModuleName [ProperName C.prim]) . ProperName
77+ primKind :: Text -> Kind
78+ primKind = NamedKind . primName
80+ kindType = primKind "Type"
81+ kindEffect = primKind "Effect"
82+ kindSymbol = primKind "Symbol"
84+instance A.FromJSON Kind where
85+ parseJSON = toAesonParser id kindFromJSON
25everywhereOnKinds :: (Kind -> Kind) -> Kind -> Kind
87everywhereOnKinds :: (Kind -> Kind) -> Kind -> Kind
26everywhereOnKinds f = go
88everywhereOnKinds f = go