@@ -11,9 +11,11 @@ import Control.Monad.Error.Class (MonadError(..))
11import Control.Monad.Supply.Class (MonadSupply)
11import Control.Monad.Supply.Class (MonadSupply)
12import Data.List (foldl', find, sortBy, unzip5)
12import Data.List (foldl', find, sortBy, unzip5)
13import qualified Data.Map as M
13import qualified Data.Map as M
14+import Data.Monoid ((<>))
14import Data.Maybe (fromMaybe, mapMaybe)
15import Data.Maybe (fromMaybe, mapMaybe)
15import Data.Ord (comparing)
16import Data.Ord (comparing)
16import Data.Text (Text)
17import Data.Text (Text)
18+import qualified Data.Text as T
17import Language.PureScript.AST
19import Language.PureScript.AST
18import qualified Language.PureScript.Constants as C
20import qualified Language.PureScript.Constants as C
19import Language.PureScript.Crash
21import Language.PureScript.Crash
@@ -22,6 +24,8 @@ import Language.PureScript.Errors
22import Language.PureScript.Externs
24import Language.PureScript.Externs
23import Language.PureScript.Kinds
25import Language.PureScript.Kinds
24import Language.PureScript.Names
26import Language.PureScript.Names
27+import Language.PureScript.Label (Label(..))
28+import Language.PureScript.PSString (mkString, decodeStringEither)
25import Language.PureScript.Types
29import Language.PureScript.Types
26import Language.PureScript.TypeChecker (checkNewtype)
30import Language.PureScript.TypeChecker (checkNewtype)
27import Language.PureScript.TypeChecker.Synonyms (SynonymMap, replaceAllTypeSynonymsM)
31import Language.PureScript.TypeChecker.Synonyms (SynonymMap, replaceAllTypeSynonymsM)
@@ -207,7 +211,7 @@ deriveGeneric mn syns ds tyConNm dargs = do
207 idents <- replicateM (length tys) freshIdent'
211 idents <- replicateM (length tys) freshIdent'
208 tys' <- mapM (replaceAllTypeSynonymsM syns) tys
212 tys' <- mapM (replaceAllTypeSynonymsM syns) tys
209 let caseResult =
213 let caseResult =
210โ App (prodConstructor (Literal . StringLiteral . showQualified runProperName $ Qualified (Just mn) ctorName))
214+ App (prodConstructor (Literal . StringLiteral . mkString . showQualified runProperName $ Qualified (Just mn) ctorName))
211 . Literal . ArrayLiteral
215 . Literal . ArrayLiteral
212 $ zipWith toSpineFun (map (Var . Qualified Nothing) idents) tys'
216 $ zipWith toSpineFun (map (Var . Qualified Nothing) idents) tys'
213 return $ CaseAlternative [ConstructorBinder (Qualified (Just mn) ctorName) (map VarBinder idents)] (Right caseResult)
217 return $ CaseAlternative [ConstructorBinder (Qualified (Just mn) ctorName) (map VarBinder idents)] (Right caseResult)
@@ -216,7 +220,7 @@ deriveGeneric mn syns ds tyConNm dargs = do
216 toSpineFun i r | Just rec <- objectType r =
220 toSpineFun i r | Just rec <- objectType r =
217 lamNull . recordConstructor . Literal . ArrayLiteral
221 lamNull . recordConstructor . Literal . ArrayLiteral
219โ (\(str,typ) ->
223+ (\((Label str),typ) ->
220 Literal $ ObjectLiteral
224 Literal $ ObjectLiteral
221 [ ("recLabel", Literal (StringLiteral str))
225 [ ("recLabel", Literal (StringLiteral str))
222 , ("recValue", toSpineFun (Accessor str i) typ)
226 , ("recValue", toSpineFun (Accessor str i) typ)
@@ -235,7 +239,7 @@ deriveGeneric mn syns ds tyConNm dargs = do
237 (Constructor (Qualified (Just dataGeneric) (ProperName "SigProd")))
241 (Constructor (Qualified (Just dataGeneric) (ProperName "SigProd")))
238โ (Literal (StringLiteral (showQualified runProperName (Qualified (Just mn) name))))
242+ (Literal (StringLiteral $ mkString (showQualified runProperName (Qualified (Just mn) name))))
240 . Literal
244 . Literal
241 . ArrayLiteral
245 . ArrayLiteral
@@ -249,7 +253,7 @@ deriveGeneric mn syns ds tyConNm dargs = do
249 mkProdClause :: (ProperName 'ConstructorName, [Type]) -> Expr
253 mkProdClause :: (ProperName 'ConstructorName, [Type]) -> Expr
250 mkProdClause (ctorName, tys) =
254 mkProdClause (ctorName, tys) =
251 Literal $ ObjectLiteral
255 Literal $ ObjectLiteral
252โ [ ("sigConstructor", Literal (StringLiteral (showQualified runProperName (Qualified (Just mn) ctorName))))
256+ [ ("sigConstructor", Literal (StringLiteral $ mkString (showQualified runProperName (Qualified (Just mn) ctorName))))
253 , ("sigValues", Literal . ArrayLiteral . map (mkProductSignature . instantiate) $ tys)
257 , ("sigValues", Literal . ArrayLiteral . map (mkProductSignature . instantiate) $ tys)
@@ -260,7 +264,7 @@ deriveGeneric mn syns ds tyConNm dargs = do
260 [ ("recLabel", Literal (StringLiteral str))
264 [ ("recLabel", Literal (StringLiteral str))
261 , ("recValue", mkProductSignature typ)
265 , ("recValue", mkProductSignature typ)
263โ | (str, typ) <- decomposeRec rec
267+ | ((Label str), typ) <- decomposeRec rec
265 mkProductSignature typ = lamNull $ App (mkGenVar (Ident C.toSignature))
269 mkProductSignature typ = lamNull $ App (mkGenVar (Ident C.toSignature))
266 (TypedValue False (mkGenVar (Ident "anyProxy")) (proxy typ))
270 (TypedValue False (mkGenVar (Ident "anyProxy")) (proxy typ))
@@ -291,7 +295,7 @@ deriveGeneric mn syns ds tyConNm dargs = do
292 CaseAlternative
296 CaseAlternative
293 [ prodBinder
297 [ prodBinder
294โ [ LiteralBinder (StringLiteral (showQualified runProperName (Qualified (Just mn) ctorName)))
298+ [ LiteralBinder (StringLiteral $ mkString (showQualified runProperName (Qualified (Just mn) ctorName)))
295 , LiteralBinder (ArrayLiteral (map VarBinder idents))
299 , LiteralBinder (ArrayLiteral (map VarBinder idents))
@@ -314,16 +318,16 @@ deriveGeneric mn syns ds tyConNm dargs = do
314 (App e unitVal)
318 (App e unitVal)
315 fromSpineFun e _ = App (mkGenVar (Ident C.fromSpine)) (App e unitVal)
319 fromSpineFun e _ = App (mkGenVar (Ident C.fromSpine)) (App e unitVal)
317โ mkRecCase :: [(Text, Type)] -> CaseAlternative
321+ mkRecCase :: [(Label, Type)] -> CaseAlternative
318 mkRecCase rs =
322 mkRecCase rs =
319 CaseAlternative
323 CaseAlternative
320โ [ recordBinder [ LiteralBinder (ArrayLiteral (map (VarBinder . Ident . fst) rs)) ] ]
324+ [ recordBinder [ LiteralBinder (ArrayLiteral (map (VarBinder . labelToIdent . fst) rs)) ] ]
322โ $ liftApplicative (mkRecFun rs) (map (\(x, y) -> fromSpineFun (Accessor "recValue" (mkVar (Ident x))) y) rs)
326+ $ liftApplicative (mkRecFun rs) (map (\(x, y) -> fromSpineFun (Accessor "recValue" (mkVar $ labelToIdent x)) y) rs)
324โ mkRecFun :: [(Text, Type)] -> Expr
328+ mkRecFun :: [(Label, Type)] -> Expr
325โ mkRecFun xs = mkJust $ foldr (lam . Ident . fst) recLiteral xs
329+ mkRecFun xs = mkJust $ foldr (lam . labelToIdent . fst) recLiteral xs
326โ where recLiteral = Literal . ObjectLiteral $ map (\(s,_) -> (s, mkVar (Ident s))) xs
330+ where recLiteral = Literal . ObjectLiteral $ map (\(l@(Label s), _) -> (s, mkVar $ labelToIdent l)) xs
327 mkFromSpineFunction (PositionedDeclaration _ _ d) = mkFromSpineFunction d
331 mkFromSpineFunction (PositionedDeclaration _ _ d) = mkFromSpineFunction d
328 mkFromSpineFunction _ = internalError "mkFromSpineFunction: expected DataDeclaration"
332 mkFromSpineFunction _ = internalError "mkFromSpineFunction: expected DataDeclaration"
@@ -405,7 +409,7 @@ deriveGenericRep mn syns ds tyConNm tyConArgs repTy = do
405 args' <- mapM (replaceAllTypeSynonymsM syns) args
409 args' <- mapM (replaceAllTypeSynonymsM syns) args
406 (ctorTy, matchProduct, ctorArgs, matchCtor, mkProduct) <- makeProduct args'
410 (ctorTy, matchProduct, ctorArgs, matchCtor, mkProduct) <- makeProduct args'
407 return ( TypeApp (TypeApp (TypeConstructor constructor)
411 return ( TypeApp (TypeApp (TypeConstructor constructor)
408โ (TypeLevelString (runProperName ctorName)))
412+ (TypeLevelString $ mkString (runProperName ctorName)))
410 , CaseAlternative [ ConstructorBinder constructor [matchProduct] ]
414 , CaseAlternative [ ConstructorBinder constructor [matchProduct] ]
411 (Right (foldl App (Constructor (Qualified (Just mn) ctorName)) ctorArgs))
415 (Right (foldl App (Constructor (Qualified (Just mn) ctorName)) ctorArgs))
@@ -430,19 +434,19 @@ deriveGenericRep mn syns ds tyConNm tyConArgs repTy = do
430 makeArg :: Type -> m (Type, Binder, Expr, Binder, Expr)
434 makeArg :: Type -> m (Type, Binder, Expr, Binder, Expr)
431 makeArg arg | Just rec <- objectType arg = do
435 makeArg arg | Just rec <- objectType arg = do
432 let fields = decomposeRec rec
436 let fields = decomposeRec rec
433โ fieldNames <- traverse freshIdent (map fst fields)
437+ fieldNames <- traverse freshIdent (map (runIdent . labelToIdent . fst) fields)
434 pure ( TypeApp (TypeConstructor record)
438 pure ( TypeApp (TypeConstructor record)
435 (foldr1 (\f -> TypeApp (TypeApp (TypeConstructor productName) f))
439 (foldr1 (\f -> TypeApp (TypeApp (TypeConstructor productName) f))
436โ (map (\(name, ty) ->
440+ (map (\((Label name), ty) ->
437 TypeApp (TypeApp (TypeConstructor field) (TypeLevelString name)) ty) fields))
441 TypeApp (TypeApp (TypeConstructor field) (TypeLevelString name)) ty) fields))
438 , ConstructorBinder record
442 , ConstructorBinder record
439 [ foldr1 (\b1 b2 -> ConstructorBinder productName [b1, b2])
443 [ foldr1 (\b1 b2 -> ConstructorBinder productName [b1, b2])
440 (map (\ident -> ConstructorBinder field [VarBinder ident]) fieldNames)
444 (map (\ident -> ConstructorBinder field [VarBinder ident]) fieldNames)
442 , Literal . ObjectLiteral $
446 , Literal . ObjectLiteral $
443โ zipWith (\(name, _) ident -> (name, Var (Qualified Nothing ident))) fields fieldNames
447+ zipWith (\((Label name), _) ident -> (name, Var (Qualified Nothing ident))) fields fieldNames
444 , LiteralBinder . ObjectLiteral $
448 , LiteralBinder . ObjectLiteral $
445โ zipWith (\(name, _) ident -> (name, VarBinder ident)) fields fieldNames
449+ zipWith (\((Label name), _) ident -> (name, VarBinder ident)) fields fieldNames
446 , record' $
450 , record' $
447 foldr1 (\e1 -> App (App (Constructor productName) e1))
451 foldr1 (\e1 -> App (App (Constructor productName) e1))
448 (map (field' . Var . Qualified Nothing) fieldNames)
452 (map (field' . Var . Qualified Nothing) fieldNames)
@@ -574,7 +578,7 @@ deriveEq mn syns ds tyConNm = do
574 toEqTest :: Expr -> Expr -> Type -> Expr
578 toEqTest :: Expr -> Expr -> Type -> Expr
575 toEqTest l r ty | Just rec <- objectType ty =
579 toEqTest l r ty | Just rec <- objectType ty =
577โ . map (\(str, typ) -> toEqTest (Accessor str l) (Accessor str r) typ)
581+ . map (\((Label str), typ) -> toEqTest (Accessor str l) (Accessor str r) typ)
578 $ decomposeRec rec
582 $ decomposeRec rec
579 toEqTest l r _ = preludeEq l r
583 toEqTest l r _ = preludeEq l r
@@ -661,7 +665,7 @@ deriveOrd mn syns ds tyConNm = do
661 toOrdering :: Expr -> Expr -> Type -> Expr
665 toOrdering :: Expr -> Expr -> Type -> Expr
662 toOrdering l r ty | Just rec <- objectType ty =
666 toOrdering l r ty | Just rec <- objectType ty =
663 appendAll
667 appendAll
664โ . map (\(str, typ) -> toOrdering (Accessor str l) (Accessor str r) typ)
668+ . map (\((Label str), typ) -> toOrdering (Accessor str l) (Accessor str r) typ)
665 $ decomposeRec rec
669 $ decomposeRec rec
666 toOrdering l r _ = ordCompare l r
670 toOrdering l r _ = ordCompare l r
@@ -733,11 +737,22 @@ mkVarMn mn = Var . Qualified mn
733mkVar :: Ident -> Expr
737mkVar :: Ident -> Expr
734mkVar = mkVarMn Nothing
738mkVar = mkVarMn Nothing
740+-- This function may seem a little obtuse, but it's only this way to ensure
741+-- that it is injective. Injectivity is important here; without it, we can end
742+-- up with accidental variable shadowing in the generated code.
743+labelToIdent :: Label -> Ident
745+ Ident . foldMap (either loneSurrogate char) . decodeStringEither . runLabel
748+ char c = T.singleton c
749+ loneSurrogate x = "_" <> T.pack (show x) <> "_"
736objectType :: Type -> Maybe Type
751objectType :: Type -> Maybe Type
737objectType (TypeApp (TypeConstructor (Qualified (Just (ModuleName [ProperName "Prim"])) (ProperName "Record"))) rec) = Just rec
752objectType (TypeApp (TypeConstructor (Qualified (Just (ModuleName [ProperName "Prim"])) (ProperName "Record"))) rec) = Just rec
738objectType _ = Nothing
753objectType _ = Nothing
740โdecomposeRec :: Type -> [(Text, Type)]
755+decomposeRec :: Type -> [(Label, Type)]
741decomposeRec = sortBy (comparing fst) . go
756decomposeRec = sortBy (comparing fst) . go
742 where go (RCons str typ typs) = (str, typ) : decomposeRec typs
757 where go (RCons str typ typs) = (str, typ) : decomposeRec typs
743 go _ = []
758 go _ = []
@@ -790,17 +805,17 @@ deriveFunctor mn syns ds tyConNm = do
790 goType recTy | Just row <- objectType recTy =
805 goType recTy | Just row <- objectType recTy =
791 traverse buildUpdate (decomposeRec row) >>= (traverse buildRecord . justUpdates)
806 traverse buildUpdate (decomposeRec row) >>= (traverse buildRecord . justUpdates)
793โ justUpdates :: [Maybe (Text, Expr)] -> Maybe [(Text, Expr)]
808+ justUpdates :: [Maybe (Label, Expr)] -> Maybe [(Label, Expr)]
794 justUpdates = foldMap (fmap return)
809 justUpdates = foldMap (fmap return)
796โ buildUpdate :: (Text, Type) -> m (Maybe (Text, Expr))
811+ buildUpdate :: (Label, Type) -> m (Maybe (Label, Expr))
797 buildUpdate (lbl, ty) = do upd <- goType ty
812 buildUpdate (lbl, ty) = do upd <- goType ty
798 return ((lbl,) <$> upd)
813 return ((lbl,) <$> upd)
800โ buildRecord :: [(Text, Expr)] -> m Expr
815+ buildRecord :: [(Label, Expr)] -> m Expr
801 buildRecord updates = do arg <- freshIdent "o"
816 buildRecord updates = do arg <- freshIdent "o"
802 let argVar = mkVar arg
817 let argVar = mkVar arg
803โ mkAssignment (l, x) = (l, App x (Accessor l argVar))
818+ mkAssignment ((Label l), x) = (l, App x (Accessor l argVar))
804 return (lam arg (ObjectUpdate argVar (mkAssignment <$> updates)))
819 return (lam arg (ObjectUpdate argVar (mkAssignment <$> updates)))
806 -- under a `* -> *`, just assume functor for now
821 -- under a `* -> *`, just assume functor for now