diff --git a/ghc/compiler/typecheck/TcGenDeriv.lhs b/ghc/compiler/typecheck/TcGenDeriv.lhs index d317f105fd6f10d0ddc081f471539e64eeb7a66e..14cf7a0e651ab35fd1a65df734b3c7984df2267a 100644 --- a/ghc/compiler/typecheck/TcGenDeriv.lhs +++ b/ghc/compiler/typecheck/TcGenDeriv.lhs @@ -28,7 +28,7 @@ module TcGenDeriv ( ) where IMP_Ubiq() -IMPORT_1_3(List(partition)) +IMPORT_1_3(List(partition,intersperse)) import HsSyn ( HsBinds(..), MonoBinds(..), Match(..), GRHSsAndBinds(..), GRHS(..), HsExpr(..), HsLit(..), InPat(..), Stmt(..), DoOrListComp(..), @@ -38,12 +38,14 @@ import RdrHsSyn ( RdrName(..), varQual, varUnqual, mkOpApp, SYN_IE(RdrNameMonoBinds), SYN_IE(RdrNameHsExpr), SYN_IE(RdrNamePat) ) import BasicTypes ( IfaceFlavour(..) ) +import FieldLabel ( fieldLabelName ) import Id ( GenId, isNullaryDataCon, dataConTag, dataConRawArgTys, fIRST_TAG, isDataCon, SYN_IE(DataCon), SYN_IE(ConTag), - SYN_IE(Id) ) + dataConFieldLabels, SYN_IE(Id) ) import Maybes ( maybeToBool ) -import Name ( getOccString, getOccName, getSrcLoc, occNameString, modAndOcc, OccName, Name ) +import Name ( getOccString, getOccName, getSrcLoc, occNameString, + modAndOcc, OccName, Name ) import PrimOp ( PrimOp(..) ) import PrelInfo -- Lots of RdrNames @@ -53,7 +55,17 @@ import Type ( eqTy, isPrimType, SYN_IE(Type) ) import TysPrim ( charPrimTy, intPrimTy, wordPrimTy, addrPrimTy, floatPrimTy, doublePrimTy ) -import Util ( mapAccumL, zipEqual, zipWith3Equal, nOfThem, panic, assertPanic ) +import Util ( mapAccumL, zipEqual, zipWithEqual, + zipWith3Equal, nOfThem, panic, assertPanic ) + + +#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 200 +intersperse :: a -> [a] -> [a] +intersperse s [] = [] +intersperse s [x] = [x] +intersperse s (x:xs) = x : s : intersperse s xs +#endif + \end{code} %************************************************************************ @@ -587,8 +599,10 @@ gen_Ix_binds tycon ) tycon_loc)))) -------------------------------------------------------------- - single_con_ixes = single_con_range `AndMonoBinds` - single_con_index `AndMonoBinds` single_con_inRange + single_con_ixes + = single_con_range `AndMonoBinds` + single_con_index `AndMonoBinds` + single_con_inRange data_con = case maybeTyConSingleCon tycon of -- just checking... @@ -598,15 +612,16 @@ gen_Ix_binds tycon else dc - con_arity = argFieldCount data_con + con_arity = argFieldCount data_con data_con_RDR = qual_orig_name data_con - con_pat xs = ConPatIn data_con_RDR (map VarPatIn xs) - con_expr xs = mk_easy_App data_con_RDR xs as_needed = take con_arity as_RDRs bs_needed = take con_arity bs_RDRs cs_needed = take con_arity cs_RDRs + con_pat xs = ConPatIn data_con_RDR (map VarPatIn xs) + con_expr = mk_easy_App data_con_RDR cs_needed + -------------------------------------------------------------- single_con_range = mk_easy_FunMonoBind tycon_loc range_RDR [TuplePatIn [con_pat as_needed, con_pat bs_needed]] [] $ @@ -614,7 +629,7 @@ gen_Ix_binds tycon where stmts = zipWith3Equal "single_con_range" mk_qual as_needed bs_needed cs_needed ++ - [ReturnStmt (con_expr cs_needed)] + [ReturnStmt con_expr] mk_qual a b c = BindStmt (VarPatIn c) (HsApp (HsVar range_RDR) (ExplicitTuple [HsVar a, HsVar b])) @@ -625,6 +640,8 @@ gen_Ix_binds tycon = mk_easy_FunMonoBind tycon_loc index_RDR [TuplePatIn [con_pat as_needed, con_pat bs_needed], con_pat cs_needed] [range_size] ( foldl mk_index (HsLit (HsInt 0)) (zip3 as_needed bs_needed cs_needed)) where + mk_index (HsLit (HsInt 0)) (l, u, i) -- optim. + = HsApp (HsApp (HsVar index_RDR) (ExplicitTuple [HsVar l, HsVar u])) (HsVar i) mk_index multiply_by (l, u, i) = genOpApp ( (HsApp (HsApp (HsVar index_RDR) (ExplicitTuple [HsVar l, HsVar u])) (HsVar i)) @@ -683,33 +700,74 @@ gen_Read_binds tycon data_con_RDR = qual_orig_name data_con data_con_str= occNameString (getOccName data_con) con_arity = argFieldCount data_con - as_needed = take con_arity as_RDRs - bs_needed = take con_arity bs_RDRs con_expr = mk_easy_App data_con_RDR as_needed nullary_con = con_arity == 0 + labels = dataConFieldLabels data_con + lab_fields = length labels + as_needed = take con_arity as_RDRs + bs_needed + | lab_fields == 0 = take con_arity bs_RDRs + | otherwise = take (4*lab_fields + 1) bs_RDRs + -- (label, '=' and field)*n, (n-1)*',' + '{' + '}' con_qual - = BindStmt - (TuplePatIn [LitPatIn (HsString data_con_str), d_Pat]) - (HsApp (HsVar lex_RDR) c_Expr) - tycon_loc - - field_quals = snd (mapAccumL mk_qual d_Expr (zipEqual "as_needed" as_needed bs_needed)) - mk_qual draw_from (con_field, str_left) + = BindStmt + (TuplePatIn [LitPatIn (HsString data_con_str), d_Pat]) + (HsApp (HsVar lex_RDR) c_Expr) + tycon_loc + + str_qual str res draw_from + = BindStmt + (TuplePatIn [LitPatIn (HsString str), VarPatIn res]) + (HsApp (HsVar lex_RDR) draw_from) + tycon_loc + + read_label f + = let nm = occNameString (getOccName (fieldLabelName f)) + in + [str_qual nm, str_qual SLIT("=")] + -- There might be spaces between the label and '=' + + field_quals + | lab_fields == 0 = + snd (mapAccumL mk_qual + d_Expr + (zipWithEqual "as_needed" + (\ con_field draw_from -> (mk_read_qual con_field, + draw_from)) + as_needed bs_needed)) + | otherwise = + snd $ + mapAccumL mk_qual d_Expr + (zipEqual "bs_needed" + ((str_qual (SLIT("{")): + concat ( + intersperse ([str_qual SLIT(",")]) $ + zipWithEqual + "field_quals" + (\ as b -> as ++ [b]) + -- The labels + (map read_label labels) + -- The fields + (map mk_read_qual as_needed))) ++ [str_qual (SLIT("}"))]) + bs_needed) + + mk_qual draw_from (f, str_left) = (HsVar str_left, -- what to draw from down the line... - BindStmt - (TuplePatIn [VarPatIn con_field, VarPatIn str_left]) - (HsApp (HsApp (HsVar readsPrec_RDR) (HsLit (HsInt 10))) draw_from) - tycon_loc - ) + f str_left draw_from) + + mk_read_qual con_field res draw_from = + BindStmt + (TuplePatIn [VarPatIn con_field, VarPatIn res]) + (HsApp (HsApp (HsVar readsPrec_RDR) (HsLit (HsInt 10))) draw_from) + tycon_loc result_expr = ExplicitTuple [con_expr, if null bs_needed then d_Expr else HsVar (last bs_needed)] - stmts = (con_qual : field_quals) ++ [ReturnStmt result_expr] + stmts = con_qual:field_quals ++ [ReturnStmt result_expr] - read_paren_arg = if nullary_con then -- must be False (parens are surely optional) false_Expr @@ -721,6 +779,7 @@ gen_Read_binds tycon HsLam (mk_easy_Match tycon_loc [c_Pat] [] $ HsDo ListComp stmts tycon_loc) ) (HsVar b_RDR) + \end{code} %************************************************************************ @@ -748,22 +807,57 @@ gen_Show_binds tycon pats_etc data_con = let data_con_RDR = qual_orig_name data_con - con_arity = argFieldCount data_con - bs_needed = take con_arity bs_RDRs - con_pat = ConPatIn data_con_RDR (map VarPatIn bs_needed) - nullary_con = con_arity == 0 + con_arity = argFieldCount data_con + bs_needed = take con_arity bs_RDRs + con_pat = ConPatIn data_con_RDR (map VarPatIn bs_needed) + nullary_con = con_arity == 0 + labels = dataConFieldLabels data_con + lab_fields = length labels show_con = let nm = occNameString (getOccName data_con) - space_maybe = if nullary_con then _NIL_ else SLIT(" ") + space_ocurly_maybe + | nullary_con = _NIL_ + | lab_fields == 0 = SLIT(" ") + | otherwise = SLIT("{") + in - HsApp (HsVar showString_RDR) (HsLit (HsString (nm _APPEND_ space_maybe))) + mk_showString_app (nm _APPEND_ space_ocurly_maybe) - show_thingies = show_con : (spacified real_show_thingies) + show_all con fs + = let + ccurly_maybe + | lab_fields > 0 = [mk_showString_app (SLIT("}"))] + | otherwise = [] + in + con:fs ++ ccurly_maybe + + show_thingies = show_all show_con real_show_thingies_with_labs + + show_label l + = let nm = occNameString (getOccName (fieldLabelName l)) + in + mk_showString_app (nm _APPEND_ SLIT("=")) + + mk_showString_app str = HsApp (HsVar showString_RDR) + (HsLit (HsString str)) + + real_show_thingies = + [ HsApp (HsApp (HsVar showsPrec_RDR) (HsLit (HsInt 10))) (HsVar b) + | b <- bs_needed ] + + real_show_thingies_with_labs + | lab_fields == 0 = intersperse (HsVar showSpace_RDR) real_show_thingies + | otherwise = --Assumption: no of fields == no of labelled fields + -- (and in same order) + concat $ + intersperse ([mk_showString_app (_CONS_ ',' _NIL_ )]) $ -- Using SLIT() is not cool here. + zipWithEqual "gen_Show_binds" + (\ a b -> [a,b]) + (map show_label labels) + real_show_thingies + - real_show_thingies - = [ HsApp (HsApp (HsVar showsPrec_RDR) (HsLit (HsInt 10))) (HsVar b) - | b <- bs_needed ] in if nullary_con then -- skip the showParen junk... ASSERT(null bs_needed) @@ -772,10 +866,6 @@ gen_Show_binds tycon ([a_Pat, con_pat], showParen_Expr (HsPar (genOpApp a_Expr ge_RDR (HsLit (HsInt 10)))) (HsPar (nested_compose_Expr show_thingies))) - where - spacified [] = [] - spacified [x] = [x] - spacified (x:xs) = (x : (HsVar showSpace_RDR) : spacified xs) \end{code} %************************************************************************