@@ -11,9 +11,11 @@ import Control.Monad.Error.Class (MonadError(..))
1111import Control.Monad.Supply.Class (MonadSupply)
1212import Data.List (foldl', find, sortBy, unzip5)
1313import qualified Data.Map as M
14+import Data.Monoid ((<>))
1415import Data.Maybe (fromMaybe, mapMaybe)
1516import Data.Ord (comparing)
1617import Data.Text (Text)
18+import qualified Data.Text as T
1719import Language.PureScript.AST
1820import qualified Language.PureScript.Constants as C
1921import Language.PureScript.Crash
@@ -22,6 +24,8 @@ import Language.PureScript.Errors
2224import Language.PureScript.Externs
2325import Language.PureScript.Kinds
2426import Language.PureScript.Names
27+import Language.PureScript.Label (Label(..))
28+import Language.PureScript.PSString (mkString, decodeStringEither)
2529import Language.PureScript.Types
2630import Language.PureScript.TypeChecker (checkNewtype)
2731import Language.PureScript.TypeChecker.Synonyms (SynonymMap, replaceAllTypeSynonymsM)
@@ -207,7 +211,7 @@ deriveGeneric mn syns ds tyConNm dargs = do
207211 idents <- replicateM (length tys) freshIdent'
208212 tys' <- mapM (replaceAllTypeSynonymsM syns) tys
209213 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))
211215 . Literal . ArrayLiteral
212216 $ zipWith toSpineFun (map (Var . Qualified Nothing) idents) tys'
213217 return $ CaseAlternative [ConstructorBinder (Qualified (Just mn) ctorName) (map VarBinder idents)] (Right caseResult)
@@ -216,7 +220,7 @@ deriveGeneric mn syns ds tyConNm dargs = do
216220 toSpineFun i r | Just rec <- objectType r =
217221 lamNull . recordConstructor . Literal . ArrayLiteral
218222 . map
219− (\(str,typ) ->
223+ (\((Label str),typ) ->
220224 Literal $ ObjectLiteral
221225 [ ("recLabel", Literal (StringLiteral str))
222226 , ("recValue", toSpineFun (Accessor str i) typ)
@@ -235,7 +239,7 @@ deriveGeneric mn syns ds tyConNm dargs = do
235239 App
236240 (App
237241 (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))))
239243 )
240244 . Literal
241245 . ArrayLiteral
@@ -249,7 +253,7 @@ deriveGeneric mn syns ds tyConNm dargs = do
249253 mkProdClause :: (ProperName 'ConstructorName, [Type]) -> Expr
250254 mkProdClause (ctorName, tys) =
251255 Literal $ ObjectLiteral
252− [ ("sigConstructor", Literal (StringLiteral (showQualified runProperName (Qualified (Just mn) ctorName))))
256+ [ ("sigConstructor", Literal (StringLiteral $ mkString (showQualified runProperName (Qualified (Just mn) ctorName))))
253257 , ("sigValues", Literal . ArrayLiteral . map (mkProductSignature . instantiate) $ tys)
254258 ]
255259
@@ -260,7 +264,7 @@ deriveGeneric mn syns ds tyConNm dargs = do
260264 [ ("recLabel", Literal (StringLiteral str))
261265 , ("recValue", mkProductSignature typ)
262266 ]
263− | (str, typ) <- decomposeRec rec
267+ | ((Label str), typ) <- decomposeRec rec
264268 ]
265269 mkProductSignature typ = lamNull $ App (mkGenVar (Ident C.toSignature))
266270 (TypedValue False (mkGenVar (Ident "anyProxy")) (proxy typ))
@@ -291,7 +295,7 @@ deriveGeneric mn syns ds tyConNm dargs = do
291295 return $
292296 CaseAlternative
293297 [ prodBinder
294− [ LiteralBinder (StringLiteral (showQualified runProperName (Qualified (Just mn) ctorName)))
298+ [ LiteralBinder (StringLiteral $ mkString (showQualified runProperName (Qualified (Just mn) ctorName)))
295299 , LiteralBinder (ArrayLiteral (map VarBinder idents))
296300 ]
297301 ]
@@ -314,16 +318,16 @@ deriveGeneric mn syns ds tyConNm dargs = do
314318 (App e unitVal)
315319 fromSpineFun e _ = App (mkGenVar (Ident C.fromSpine)) (App e unitVal)
316320
317− mkRecCase :: [(Text, Type)] -> CaseAlternative
321+ mkRecCase :: [(Label, Type)] -> CaseAlternative
318322 mkRecCase rs =
319323 CaseAlternative
320− [ recordBinder [ LiteralBinder (ArrayLiteral (map (VarBinder . Ident . fst) rs)) ] ]
324+ [ recordBinder [ LiteralBinder (ArrayLiteral (map (VarBinder . labelToIdent . fst) rs)) ] ]
321325 . Right
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)
323327
324− mkRecFun :: [(Text, Type)] -> Expr
325− mkRecFun xs = mkJust $ foldr (lam . Ident . fst) recLiteral xs
326− where recLiteral = Literal . ObjectLiteral $ map (\(s,_) -> (s, mkVar (Ident s))) xs
328+ mkRecFun :: [(Label, Type)] -> Expr
329+ mkRecFun xs = mkJust $ foldr (lam . labelToIdent . fst) recLiteral xs
330+ where recLiteral = Literal . ObjectLiteral $ map (\(l@(Label s), _) -> (s, mkVar $ labelToIdent l)) xs
327331 mkFromSpineFunction (PositionedDeclaration _ _ d) = mkFromSpineFunction d
328332 mkFromSpineFunction _ = internalError "mkFromSpineFunction: expected DataDeclaration"
329333
@@ -405,7 +409,7 @@ deriveGenericRep mn syns ds tyConNm tyConArgs repTy = do
405409 args' <- mapM (replaceAllTypeSynonymsM syns) args
406410 (ctorTy, matchProduct, ctorArgs, matchCtor, mkProduct) <- makeProduct args'
407411 return ( TypeApp (TypeApp (TypeConstructor constructor)
408− (TypeLevelString (runProperName ctorName)))
412+ (TypeLevelString $ mkString (runProperName ctorName)))
409413 ctorTy
410414 , CaseAlternative [ ConstructorBinder constructor [matchProduct] ]
411415 (Right (foldl App (Constructor (Qualified (Just mn) ctorName)) ctorArgs))
@@ -430,19 +434,19 @@ deriveGenericRep mn syns ds tyConNm tyConArgs repTy = do
430434 makeArg :: Type -> m (Type, Binder, Expr, Binder, Expr)
431435 makeArg arg | Just rec <- objectType arg = do
432436 let fields = decomposeRec rec
433− fieldNames <- traverse freshIdent (map fst fields)
437+ fieldNames <- traverse freshIdent (map (runIdent . labelToIdent . fst) fields)
434438 pure ( TypeApp (TypeConstructor record)
435439 (foldr1 (\f -> TypeApp (TypeApp (TypeConstructor productName) f))
436− (map (\(name, ty) ->
440+ (map (\((Label name), ty) ->
437441 TypeApp (TypeApp (TypeConstructor field) (TypeLevelString name)) ty) fields))
438442 , ConstructorBinder record
439443 [ foldr1 (\b1 b2 -> ConstructorBinder productName [b1, b2])
440444 (map (\ident -> ConstructorBinder field [VarBinder ident]) fieldNames)
441445 ]
442446 , 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
444448 , LiteralBinder . ObjectLiteral $
445− zipWith (\(name, _) ident -> (name, VarBinder ident)) fields fieldNames
449+ zipWith (\((Label name), _) ident -> (name, VarBinder ident)) fields fieldNames
446450 , record' $
447451 foldr1 (\e1 -> App (App (Constructor productName) e1))
448452 (map (field' . Var . Qualified Nothing) fieldNames)
@@ -574,7 +578,7 @@ deriveEq mn syns ds tyConNm = do
574578 toEqTest :: Expr -> Expr -> Type -> Expr
575579 toEqTest l r ty | Just rec <- objectType ty =
576580 conjAll
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)
578582 $ decomposeRec rec
579583 toEqTest l r _ = preludeEq l r
580584
@@ -661,7 +665,7 @@ deriveOrd mn syns ds tyConNm = do
661665 toOrdering :: Expr -> Expr -> Type -> Expr
662666 toOrdering l r ty | Just rec <- objectType ty =
663667 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)
665669 $ decomposeRec rec
666670 toOrdering l r _ = ordCompare l r
667671
@@ -733,11 +737,22 @@ mkVarMn mn = Var . Qualified mn
733737mkVar :: Ident -> Expr
734738mkVar = mkVarMn Nothing
735739
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
744+labelToIdent =
745+ Ident . foldMap (either loneSurrogate char) . decodeStringEither . runLabel
746+ where
747+ char '_' = "__"
748+ char c = T.singleton c
749+ loneSurrogate x = "_" <> T.pack (show x) <> "_"
750+
736751objectType :: Type -> Maybe Type
737752objectType (TypeApp (TypeConstructor (Qualified (Just (ModuleName [ProperName "Prim"])) (ProperName "Record"))) rec) = Just rec
738753objectType _ = Nothing
739754
740−decomposeRec :: Type -> [(Text, Type)]
755+decomposeRec :: Type -> [(Label, Type)]
741756decomposeRec = sortBy (comparing fst) . go
742757 where go (RCons str typ typs) = (str, typ) : decomposeRec typs
743758 go _ = []
@@ -790,17 +805,17 @@ deriveFunctor mn syns ds tyConNm = do
790805 goType recTy | Just row <- objectType recTy =
791806 traverse buildUpdate (decomposeRec row) >>= (traverse buildRecord . justUpdates)
792807 where
793− justUpdates :: [Maybe (Text, Expr)] -> Maybe [(Text, Expr)]
808+ justUpdates :: [Maybe (Label, Expr)] -> Maybe [(Label, Expr)]
794809 justUpdates = foldMap (fmap return)
795810
796− buildUpdate :: (Text, Type) -> m (Maybe (Text, Expr))
811+ buildUpdate :: (Label, Type) -> m (Maybe (Label, Expr))
797812 buildUpdate (lbl, ty) = do upd <- goType ty
798813 return ((lbl,) <$> upd)
799814
800− buildRecord :: [(Text, Expr)] -> m Expr
815+ buildRecord :: [(Label, Expr)] -> m Expr
801816 buildRecord updates = do arg <- freshIdent "o"
802817 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))
804819 return (lam arg (ObjectUpdate argVar (mkAssignment <$> updates)))
805820
806821 -- under a `* -> *`, just assume functor for now