2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 \section[TcGenDeriv]{Generating derived instance declarations}
6 This module is nominally ``subordinate'' to @TcDeriv@, which is the
7 ``official'' interface to deriving-related things.
9 This is where we do all the grimy bindings' generation.
12 #include "HsVersions.h"
23 gen_tag_n_con_monobind,
25 con2tag_RDR, tag2con_RDR, maxtag_RDR,
31 IMPORT_1_3(List(partition,intersperse))
33 import HsSyn ( HsBinds(..), MonoBinds(..), Match(..), GRHSsAndBinds(..),
34 GRHS(..), HsExpr(..), HsLit(..), InPat(..), Stmt(..), DoOrListComp(..),
35 SYN_IE(RecFlag), recursive,
36 ArithSeqInfo, Sig, HsType, FixityDecl, Fixity, Fake )
37 import RdrHsSyn ( RdrName(..), varQual, varUnqual, mkOpApp,
38 SYN_IE(RdrNameMonoBinds), SYN_IE(RdrNameHsExpr), SYN_IE(RdrNamePat)
40 import BasicTypes ( IfaceFlavour(..) )
41 import FieldLabel ( fieldLabelName )
42 import Id ( GenId, isNullaryDataCon, dataConTag,
43 dataConRawArgTys, fIRST_TAG,
44 isDataCon, SYN_IE(DataCon), SYN_IE(ConTag),
45 dataConFieldLabels, SYN_IE(Id) )
46 import Maybes ( maybeToBool )
47 import Name ( getOccString, getOccName, getSrcLoc, occNameString,
48 modAndOcc, OccName, Name )
50 import PrimOp ( PrimOp(..) )
51 import PrelInfo -- Lots of RdrNames
52 import SrcLoc ( mkGeneratedSrcLoc, SrcLoc )
53 import TyCon ( TyCon, isNewTyCon, tyConDataCons, isEnumerationTyCon, maybeTyConSingleCon )
54 import Type ( eqTy, isPrimType, SYN_IE(Type) )
55 import TysPrim ( charPrimTy, intPrimTy, wordPrimTy, addrPrimTy,
56 floatPrimTy, doublePrimTy
58 import Util ( mapAccumL, zipEqual, zipWithEqual,
59 zipWith3Equal, nOfThem, panic, assertPanic )
62 #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 200
63 intersperse :: a -> [a] -> [a]
65 intersperse s [x] = [x]
66 intersperse s (x:xs) = x : s : intersperse s xs
71 %************************************************************************
73 \subsection{Generating code, by derivable class}
75 %************************************************************************
77 %************************************************************************
79 \subsubsection{Generating @Eq@ instance declarations}
81 %************************************************************************
83 Here are the heuristics for the code we generate for @Eq@:
86 Let's assume we have a data type with some (possibly zero) nullary
87 data constructors and some ordinary, non-nullary ones (the rest,
88 also possibly zero of them). Here's an example, with both \tr{N}ullary
89 and \tr{O}rdinary data cons.
91 data Foo ... = N1 | N2 ... | Nn | O1 a b | O2 Int | O3 Double b b | ...
95 For the ordinary constructors (if any), we emit clauses to do The
99 (==) (O1 a1 b1) (O1 a2 b2) = a1 == a2 && b1 == b2
100 (==) (O2 a1) (O2 a2) = a1 == a2
101 (==) (O3 a1 b1 c1) (O3 a2 b2 c2) = a1 == a2 && b1 == b2 && c1 == c2
104 Note: if we're comparing unboxed things, e.g., if \tr{a1} and
105 \tr{a2} are \tr{Float#}s, then we have to generate
107 case (a1 `eqFloat#` a2) of
110 for that particular test.
113 If there are any nullary constructors, we emit a catch-all clause of
117 (==) a b = case (con2tag_Foo a) of { a# ->
118 case (con2tag_Foo b) of { b# ->
119 case (a# ==# b#) of {
124 If there aren't any nullary constructors, we emit a simpler
131 For the @(/=)@ method, we normally just use the default method.
133 If the type is an enumeration type, we could/may/should? generate
134 special code that calls @con2tag_Foo@, much like for @(==)@ shown
138 We thought about doing this: If we're also deriving @Ord@ for this
141 instance ... Eq (Foo ...) where
142 (==) a b = case (compare a b) of { _LT -> False; _EQ -> True ; _GT -> False}
143 (/=) a b = case (compare a b) of { _LT -> True ; _EQ -> False; _GT -> True }
145 However, that requires that \tr{Ord <whatever>} was put in the context
146 for the instance decl, which it probably wasn't, so the decls
147 produced don't get through the typechecker.
151 gen_Eq_binds :: TyCon -> RdrNameMonoBinds
155 tycon_loc = getSrcLoc tycon
156 (nullary_cons, nonnullary_cons)
157 | isNewTyCon tycon = ([], tyConDataCons tycon)
158 | otherwise = partition isNullaryDataCon (tyConDataCons tycon)
161 = if (null nullary_cons) then
162 case maybeTyConSingleCon tycon of
164 Nothing -> -- if cons don't match, then False
165 [([a_Pat, b_Pat], false_Expr)]
166 else -- calc. and compare the tags
168 untag_Expr tycon [(a_RDR,ah_RDR), (b_RDR,bh_RDR)]
169 (cmp_tags_Expr eqH_Int_RDR ah_RDR bh_RDR true_Expr false_Expr))]
171 mk_FunMonoBind tycon_loc eq_RDR ((map pats_etc nonnullary_cons) ++ rest)
173 mk_easy_FunMonoBind tycon_loc ne_RDR [a_Pat, b_Pat] [] (
174 HsApp (HsVar not_RDR) (HsPar (mk_easy_App eq_RDR [a_RDR, b_RDR])))
176 ------------------------------------------------------------------
179 con1_pat = ConPatIn data_con_RDR (map VarPatIn as_needed)
180 con2_pat = ConPatIn data_con_RDR (map VarPatIn bs_needed)
182 data_con_RDR = qual_orig_name data_con
183 con_arity = length tys_needed
184 as_needed = take con_arity as_RDRs
185 bs_needed = take con_arity bs_RDRs
186 tys_needed = dataConRawArgTys data_con
188 ([con1_pat, con2_pat], nested_eq_expr tys_needed as_needed bs_needed)
190 nested_eq_expr [] [] [] = true_Expr
191 nested_eq_expr tys as bs
192 = foldl1 and_Expr (zipWith3Equal "nested_eq" nested_eq tys as bs)
194 nested_eq ty a b = HsPar (eq_Expr ty (HsVar a) (HsVar b))
197 %************************************************************************
199 \subsubsection{Generating @Ord@ instance declarations}
201 %************************************************************************
203 For a derived @Ord@, we concentrate our attentions on @compare@
205 compare :: a -> a -> Ordering
206 data Ordering = LT | EQ | GT deriving ()
209 We will use the same example data type as above:
211 data Foo ... = N1 | N2 ... | Nn | O1 a b | O2 Int | O3 Double b b | ...
216 We do all the other @Ord@ methods with calls to @compare@:
218 instance ... (Ord <wurble> <wurble>) where
219 a < b = case (compare a b) of { LT -> True; EQ -> False; GT -> False }
220 a <= b = case (compare a b) of { LT -> True; EQ -> True; GT -> False }
221 a >= b = case (compare a b) of { LT -> False; EQ -> True; GT -> True }
222 a > b = case (compare a b) of { LT -> False; EQ -> False; GT -> True }
224 max a b = case (compare a b) of { LT -> b; EQ -> a; GT -> a }
225 min a b = case (compare a b) of { LT -> a; EQ -> b; GT -> b }
227 -- compare to come...
231 @compare@ always has two parts. First, we use the compared
232 data-constructors' tags to deal with the case of different
235 compare a b = case (con2tag_Foo a) of { a# ->
236 case (con2tag_Foo b) of { b# ->
237 case (a# ==# b#) of {
239 False -> case (a# <# b#) of
244 cmp_eq = ... to come ...
248 We are only left with the ``help'' function @cmp_eq@, to deal with
249 comparing data constructors with the same tag.
251 For the ordinary constructors (if any), we emit the sorta-obvious
252 compare-style stuff; for our example:
254 cmp_eq (O1 a1 b1) (O1 a2 b2)
255 = case (compare a1 a2) of { LT -> LT; EQ -> compare b1 b2; GT -> GT }
257 cmp_eq (O2 a1) (O2 a2)
260 cmp_eq (O3 a1 b1 c1) (O3 a2 b2 c2)
261 = case (compare a1 a2) of {
264 EQ -> case compare b1 b2 of {
272 Again, we must be careful about unboxed comparisons. For example,
273 if \tr{a1} and \tr{a2} were \tr{Int#}s in the 2nd example above, we'd need to
276 cmp_eq lt eq gt (O2 a1) (O2 a2)
278 -- or maybe the unfolded equivalent
282 For the remaining nullary constructors, we already know that the
289 If there is only one constructor in the Data Type we don't need the WildCard Patern.
293 gen_Ord_binds :: TyCon -> RdrNameMonoBinds
296 = defaulted `AndMonoBinds` compare
298 tycon_loc = getSrcLoc tycon
299 --------------------------------------------------------------------
300 compare = mk_easy_FunMonoBind tycon_loc compare_RDR
303 (if maybeToBool (maybeTyConSingleCon tycon) then
304 cmp_eq_Expr ltTag_Expr eqTag_Expr gtTag_Expr a_Expr b_Expr
306 untag_Expr tycon [(a_RDR, ah_RDR), (b_RDR, bh_RDR)]
307 (cmp_tags_Expr eqH_Int_RDR ah_RDR bh_RDR
308 -- True case; they are equal
309 -- If an enumeration type we are done; else
310 -- recursively compare their components
311 (if isEnumerationTyCon tycon then
314 cmp_eq_Expr ltTag_Expr eqTag_Expr gtTag_Expr a_Expr b_Expr
316 -- False case; they aren't equal
317 -- So we need to do a less-than comparison on the tags
318 (cmp_tags_Expr ltH_Int_RDR ah_RDR bh_RDR ltTag_Expr gtTag_Expr)))
320 (nullary_cons, nonnullary_cons)
321 | isNewTyCon tycon = ([], tyConDataCons tycon)
322 | otherwise = partition isNullaryDataCon (tyConDataCons tycon)
325 = mk_FunMonoBind tycon_loc cmp_eq_RDR (map pats_etc nonnullary_cons ++
326 if ((length nonnullary_cons + length nullary_cons) == 1)
328 else [([WildPatIn, WildPatIn],
332 = ([con1_pat, con2_pat],
333 nested_compare_expr tys_needed as_needed bs_needed)
335 con1_pat = ConPatIn data_con_RDR (map VarPatIn as_needed)
336 con2_pat = ConPatIn data_con_RDR (map VarPatIn bs_needed)
338 data_con_RDR = qual_orig_name data_con
339 con_arity = length tys_needed
340 as_needed = take con_arity as_RDRs
341 bs_needed = take con_arity bs_RDRs
342 tys_needed = dataConRawArgTys data_con
344 nested_compare_expr [ty] [a] [b]
345 = careful_compare_Case ty ltTag_Expr eqTag_Expr gtTag_Expr (HsVar a) (HsVar b)
347 nested_compare_expr (ty:tys) (a:as) (b:bs)
348 = let eq_expr = nested_compare_expr tys as bs
349 in careful_compare_Case ty ltTag_Expr eq_expr gtTag_Expr (HsVar a) (HsVar b)
351 default_rhs | null nullary_cons = impossible_Expr -- Keep desugarer from complaining about
352 -- inexhaustive patterns
353 | otherwise = eqTag_Expr -- Some nullary constructors;
354 -- Tags are equal, no args => return EQ
355 --------------------------------------------------------------------
357 defaulted = foldr1 AndMonoBinds [lt, le, ge, gt, max_, min_]
359 lt = mk_easy_FunMonoBind mkGeneratedSrcLoc lt_RDR [a_Pat, b_Pat] [] (
360 compare_Case true_Expr false_Expr false_Expr a_Expr b_Expr)
361 le = mk_easy_FunMonoBind mkGeneratedSrcLoc le_RDR [a_Pat, b_Pat] [] (
362 compare_Case true_Expr true_Expr false_Expr a_Expr b_Expr)
363 ge = mk_easy_FunMonoBind mkGeneratedSrcLoc ge_RDR [a_Pat, b_Pat] [] (
364 compare_Case false_Expr true_Expr true_Expr a_Expr b_Expr)
365 gt = mk_easy_FunMonoBind mkGeneratedSrcLoc gt_RDR [a_Pat, b_Pat] [] (
366 compare_Case false_Expr false_Expr true_Expr a_Expr b_Expr)
368 max_ = mk_easy_FunMonoBind mkGeneratedSrcLoc max_RDR [a_Pat, b_Pat] [] (
369 compare_Case b_Expr a_Expr a_Expr a_Expr b_Expr)
370 min_ = mk_easy_FunMonoBind mkGeneratedSrcLoc min_RDR [a_Pat, b_Pat] [] (
371 compare_Case a_Expr b_Expr b_Expr a_Expr b_Expr)
374 %************************************************************************
376 \subsubsection{Generating @Enum@ instance declarations}
378 %************************************************************************
380 @Enum@ can only be derived for enumeration types. For a type
382 data Foo ... = N1 | N2 | ... | Nn
385 we use both @con2tag_Foo@ and @tag2con_Foo@ functions, as well as a
386 @maxtag_Foo@ variable (all generated by @gen_tag_n_con_binds@).
389 instance ... Enum (Foo ...) where
390 toEnum i = tag2con_Foo i
392 enumFrom a = map tag2con_Foo [con2tag_Foo a .. maxtag_Foo]
396 = case con2tag_Foo a of
397 a# -> map tag2con_Foo (enumFromTo (I# a#) maxtag_Foo)
400 = map tag2con_Foo [con2tag_Foo a, con2tag_Foo b .. maxtag_Foo]
404 = case con2tag_Foo a of { a# ->
405 case con2tag_Foo b of { b# ->
406 map tag2con_Foo (enumFromThenTo (I# a#) (I# b#) maxtag_Foo)
410 For @enumFromTo@ and @enumFromThenTo@, we use the default methods.
413 gen_Enum_binds :: TyCon -> RdrNameMonoBinds
416 = to_enum `AndMonoBinds`
417 enum_from `AndMonoBinds`
418 enum_from_then `AndMonoBinds`
421 tycon_loc = getSrcLoc tycon
424 = mk_easy_FunMonoBind tycon_loc toEnum_RDR [a_Pat] [] $
425 mk_easy_App (tag2con_RDR tycon) [a_RDR]
428 = mk_easy_FunMonoBind tycon_loc enumFrom_RDR [a_Pat] [] $
429 untag_Expr tycon [(a_RDR, ah_RDR)] $
430 HsApp (mk_easy_App map_RDR [tag2con_RDR tycon]) $
431 HsPar (enum_from_to_Expr
432 (mk_easy_App mkInt_RDR [ah_RDR])
433 (HsVar (maxtag_RDR tycon)))
436 = mk_easy_FunMonoBind tycon_loc enumFromThen_RDR [a_Pat, b_Pat] [] $
437 untag_Expr tycon [(a_RDR, ah_RDR), (b_RDR, bh_RDR)] $
438 HsApp (mk_easy_App map_RDR [tag2con_RDR tycon]) $
439 HsPar (enum_from_then_to_Expr
440 (mk_easy_App mkInt_RDR [ah_RDR])
441 (mk_easy_App mkInt_RDR [bh_RDR])
442 (HsVar (maxtag_RDR tycon)))
445 = mk_easy_FunMonoBind tycon_loc fromEnum_RDR [a_Pat] [] $
446 untag_Expr tycon [(a_RDR, ah_RDR)] $
447 (mk_easy_App mkInt_RDR [ah_RDR])
450 %************************************************************************
452 \subsubsection{Generating @Eval@ instance declarations}
454 %************************************************************************
457 gen_Eval_binds tycon = EmptyMonoBinds
460 %************************************************************************
462 \subsubsection{Generating @Bounded@ instance declarations}
464 %************************************************************************
467 gen_Bounded_binds tycon
468 = if isEnumerationTyCon tycon then
469 min_bound_enum `AndMonoBinds` max_bound_enum
471 ASSERT(length data_cons == 1)
472 min_bound_1con `AndMonoBinds` max_bound_1con
474 data_cons = tyConDataCons tycon
475 tycon_loc = getSrcLoc tycon
477 ----- enum-flavored: ---------------------------
478 min_bound_enum = mk_easy_FunMonoBind tycon_loc minBound_RDR [] [] (HsVar data_con_1_RDR)
479 max_bound_enum = mk_easy_FunMonoBind tycon_loc maxBound_RDR [] [] (HsVar data_con_N_RDR)
481 data_con_1 = head data_cons
482 data_con_N = last data_cons
483 data_con_1_RDR = qual_orig_name data_con_1
484 data_con_N_RDR = qual_orig_name data_con_N
486 ----- single-constructor-flavored: -------------
487 arity = argFieldCount data_con_1
489 min_bound_1con = mk_easy_FunMonoBind tycon_loc minBound_RDR [] [] $
490 mk_easy_App data_con_1_RDR (nOfThem arity minBound_RDR)
491 max_bound_1con = mk_easy_FunMonoBind tycon_loc maxBound_RDR [] [] $
492 mk_easy_App data_con_1_RDR (nOfThem arity maxBound_RDR)
495 %************************************************************************
497 \subsubsection{Generating @Ix@ instance declarations}
499 %************************************************************************
501 Deriving @Ix@ is only possible for enumeration types and
502 single-constructor types. We deal with them in turn.
504 For an enumeration type, e.g.,
506 data Foo ... = N1 | N2 | ... | Nn
508 things go not too differently from @Enum@:
510 instance ... Ix (Foo ...) where
512 = map tag2con_Foo [con2tag_Foo a .. con2tag_Foo b]
516 = case (con2tag_Foo a) of { a# ->
517 case (con2tag_Foo b) of { b# ->
518 map tag2con_Foo (enumFromTo (I# a#) (I# b#))
523 then case (con2tag_Foo d -# con2tag_Foo a) of
525 else error "Ix.Foo.index: out of range"
529 p_tag = con2tag_Foo c
531 p_tag >= con2tag_Foo a && p_tag <= con2tag_Foo b
535 = case (con2tag_Foo a) of { a_tag ->
536 case (con2tag_Foo b) of { b_tag ->
537 case (con2tag_Foo c) of { c_tag ->
538 if (c_tag >=# a_tag) then
544 (modulo suitable case-ification to handle the unboxed tags)
546 For a single-constructor type (NB: this includes all tuples), e.g.,
548 data Foo ... = MkFoo a b Int Double c c
550 we follow the scheme given in Figure~19 of the Haskell~1.2 report
554 gen_Ix_binds :: TyCon -> RdrNameMonoBinds
557 = if isEnumerationTyCon tycon
561 tycon_str = getOccString tycon
562 tycon_loc = getSrcLoc tycon
564 --------------------------------------------------------------
565 enum_ixes = enum_range `AndMonoBinds`
566 enum_index `AndMonoBinds` enum_inRange
569 = mk_easy_FunMonoBind tycon_loc range_RDR [TuplePatIn [a_Pat, b_Pat]] [] $
570 untag_Expr tycon [(a_RDR, ah_RDR)] $
571 untag_Expr tycon [(b_RDR, bh_RDR)] $
572 HsApp (mk_easy_App map_RDR [tag2con_RDR tycon]) $
573 HsPar (enum_from_to_Expr
574 (mk_easy_App mkInt_RDR [ah_RDR])
575 (mk_easy_App mkInt_RDR [bh_RDR]))
578 = mk_easy_FunMonoBind tycon_loc index_RDR [AsPatIn c_RDR (TuplePatIn [a_Pat, b_Pat]), d_Pat] [] (
579 HsIf (HsPar (mk_easy_App inRange_RDR [c_RDR, d_RDR])) (
580 untag_Expr tycon [(a_RDR, ah_RDR)] (
581 untag_Expr tycon [(d_RDR, dh_RDR)] (
583 grhs = [OtherwiseGRHS (mk_easy_App mkInt_RDR [c_RDR]) tycon_loc]
586 (genOpApp (HsVar dh_RDR) minusH_RDR (HsVar ah_RDR))
587 [PatMatch (VarPatIn c_RDR)
588 (GRHSMatch (GRHSsAndBindsIn grhs EmptyBinds))]
592 HsApp (HsVar error_RDR) (HsLit (HsString (_PK_ ("Ix."++tycon_str++".index: out of range\n"))))
597 = mk_easy_FunMonoBind tycon_loc inRange_RDR [TuplePatIn [a_Pat, b_Pat], c_Pat] [] (
598 untag_Expr tycon [(a_RDR, ah_RDR)] (
599 untag_Expr tycon [(b_RDR, bh_RDR)] (
600 untag_Expr tycon [(c_RDR, ch_RDR)] (
601 HsIf (genOpApp (HsVar ch_RDR) geH_RDR (HsVar ah_RDR)) (
602 (genOpApp (HsVar ch_RDR) leH_RDR (HsVar bh_RDR))
607 --------------------------------------------------------------
609 = single_con_range `AndMonoBinds`
610 single_con_index `AndMonoBinds`
614 = case maybeTyConSingleCon tycon of -- just checking...
615 Nothing -> panic "get_Ix_binds"
616 Just dc -> if (any isPrimType (dataConRawArgTys dc)) then
617 error ("ERROR: Can't derive Ix for a single-constructor type with primitive argument types: "++tycon_str)
621 con_arity = argFieldCount data_con
622 data_con_RDR = qual_orig_name data_con
624 as_needed = take con_arity as_RDRs
625 bs_needed = take con_arity bs_RDRs
626 cs_needed = take con_arity cs_RDRs
628 con_pat xs = ConPatIn data_con_RDR (map VarPatIn xs)
629 con_expr = mk_easy_App data_con_RDR cs_needed
631 --------------------------------------------------------------
633 = mk_easy_FunMonoBind tycon_loc range_RDR [TuplePatIn [con_pat as_needed, con_pat bs_needed]] [] $
634 HsDo ListComp stmts tycon_loc
636 stmts = zipWith3Equal "single_con_range" mk_qual as_needed bs_needed cs_needed
638 [ReturnStmt con_expr]
640 mk_qual a b c = BindStmt (VarPatIn c)
641 (HsApp (HsVar range_RDR) (ExplicitTuple [HsVar a, HsVar b]))
646 = mk_easy_FunMonoBind tycon_loc index_RDR [TuplePatIn [con_pat as_needed, con_pat bs_needed], con_pat cs_needed] [range_size] (
647 foldl mk_index (HsLit (HsInt 0)) (zip3 as_needed bs_needed cs_needed))
649 mk_index multiply_by (l, u, i)
651 (HsApp (HsApp (HsVar index_RDR) (ExplicitTuple [HsVar l, HsVar u])) (HsVar i))
654 (HsApp (HsVar rangeSize_RDR) (ExplicitTuple [HsVar l, HsVar u]))
655 ) times_RDR multiply_by
659 = mk_easy_FunMonoBind tycon_loc rangeSize_RDR [TuplePatIn [a_Pat, b_Pat]] [] (
661 (HsApp (HsApp (HsVar index_RDR) (ExplicitTuple [a_Expr, b_Expr])) b_Expr)
662 ) plus_RDR (HsLit (HsInt 1)))
666 = mk_easy_FunMonoBind tycon_loc inRange_RDR
667 [TuplePatIn [con_pat as_needed, con_pat bs_needed], con_pat cs_needed]
669 foldl1 and_Expr (zipWith3Equal "single_con_inRange" in_range as_needed bs_needed cs_needed))
671 in_range a b c = HsApp (HsApp (HsVar inRange_RDR) (ExplicitTuple [HsVar a, HsVar b])) (HsVar c)
674 %************************************************************************
676 \subsubsection{Generating @Read@ instance declarations}
678 %************************************************************************
680 Ignoring all the infix-ery mumbo jumbo (ToDo)
683 gen_Read_binds :: TyCon -> RdrNameMonoBinds
686 = reads_prec `AndMonoBinds` read_list
688 tycon_loc = getSrcLoc tycon
689 -----------------------------------------------------------------------
690 read_list = mk_easy_FunMonoBind tycon_loc readList_RDR [] []
691 (HsApp (HsVar readList___RDR) (HsPar (HsApp (HsVar readsPrec_RDR) (HsLit (HsInt 0)))))
692 -----------------------------------------------------------------------
695 read_con_comprehensions
696 = map read_con (tyConDataCons tycon)
698 mk_easy_FunMonoBind tycon_loc readsPrec_RDR [a_Pat, b_Pat] [] (
699 foldr1 append_Expr read_con_comprehensions
702 read_con data_con -- note: "b" is the string being "read"
704 data_con_RDR = qual_orig_name data_con
705 data_con_str= occNameString (getOccName data_con)
706 con_arity = argFieldCount data_con
707 con_expr = mk_easy_App data_con_RDR as_needed
708 nullary_con = con_arity == 0
709 labels = dataConFieldLabels data_con
710 lab_fields = length labels
712 as_needed = take con_arity as_RDRs
714 | lab_fields == 0 = take con_arity bs_RDRs
715 | otherwise = take (4*lab_fields + 1) bs_RDRs
716 -- (label, '=' and field)*n, (n-1)*',' + '{' + '}'
719 (TuplePatIn [LitPatIn (HsString data_con_str), d_Pat])
720 (HsApp (HsVar lex_RDR) c_Expr)
723 str_qual str res draw_from
725 (TuplePatIn [LitPatIn (HsString str), VarPatIn res])
726 (HsApp (HsVar lex_RDR) draw_from)
730 = let nm = occNameString (getOccName (fieldLabelName f))
732 [str_qual nm, str_qual SLIT("=")]
733 -- There might be spaces between the label and '='
737 snd (mapAccumL mk_qual
739 (zipWithEqual "as_needed"
740 (\ con_field draw_from -> (mk_read_qual con_field,
742 as_needed bs_needed))
745 mapAccumL mk_qual d_Expr
746 (zipEqual "bs_needed"
747 ((str_qual (SLIT("{")):
749 intersperse ([str_qual (_CONS_ ',' _NIL_)]) $
752 (\ as b -> as ++ [b])
754 (map read_label labels)
756 (map mk_read_qual as_needed))) ++ [str_qual (SLIT("}"))])
759 mk_qual draw_from (f, str_left)
760 = (HsVar str_left, -- what to draw from down the line...
761 f str_left draw_from)
763 mk_read_qual con_field res draw_from =
765 (TuplePatIn [VarPatIn con_field, VarPatIn res])
766 (HsApp (HsApp (HsVar readsPrec_RDR) (HsLit (HsInt 10))) draw_from)
769 result_expr = ExplicitTuple [con_expr, if null bs_needed
771 else HsVar (last bs_needed)]
773 stmts = con_qual:field_quals ++ [ReturnStmt result_expr]
776 = if nullary_con then -- must be False (parens are surely optional)
778 else -- parens depend on precedence...
779 HsPar (genOpApp a_Expr gt_RDR (HsLit (HsInt 9)))
782 readParen_Expr read_paren_arg $ HsPar $
783 HsLam (mk_easy_Match tycon_loc [c_Pat] [] $
784 HsDo ListComp stmts tycon_loc)
789 %************************************************************************
791 \subsubsection{Generating @Show@ instance declarations}
793 %************************************************************************
795 Ignoring all the infix-ery mumbo jumbo (ToDo)
798 gen_Show_binds :: TyCon -> RdrNameMonoBinds
801 = shows_prec `AndMonoBinds` show_list
803 tycon_loc = getSrcLoc tycon
804 -----------------------------------------------------------------------
805 show_list = mk_easy_FunMonoBind tycon_loc showList_RDR [] []
806 (HsApp (HsVar showList___RDR) (HsPar (HsApp (HsVar showsPrec_RDR) (HsLit (HsInt 0)))))
807 -----------------------------------------------------------------------
809 = mk_FunMonoBind tycon_loc showsPrec_RDR (map pats_etc (tyConDataCons tycon))
813 data_con_RDR = qual_orig_name data_con
814 con_arity = argFieldCount data_con
815 bs_needed = take con_arity bs_RDRs
816 con_pat = ConPatIn data_con_RDR (map VarPatIn bs_needed)
817 nullary_con = con_arity == 0
818 labels = dataConFieldLabels data_con
819 lab_fields = length labels
822 = let nm = occNameString (getOccName data_con)
824 | nullary_con = _NIL_
825 | lab_fields == 0 = SLIT(" ")
826 | otherwise = SLIT("{")
829 mk_showString_app (nm _APPEND_ space_ocurly_maybe)
834 | lab_fields > 0 = [mk_showString_app (SLIT("}"))]
837 con:fs ++ ccurly_maybe
839 show_thingies = show_all show_con real_show_thingies_with_labs
842 = let nm = occNameString (getOccName (fieldLabelName l))
844 mk_showString_app (nm _APPEND_ SLIT("="))
846 mk_showString_app str = HsApp (HsVar showString_RDR)
847 (HsLit (HsString str))
850 [ HsApp (HsApp (HsVar showsPrec_RDR) (HsLit (HsInt 10))) (HsVar b)
853 real_show_thingies_with_labs
854 | lab_fields == 0 = intersperse (HsVar showSpace_RDR) real_show_thingies
855 | otherwise = --Assumption: no of fields == no of labelled fields
856 -- (and in same order)
858 intersperse ([mk_showString_app (_CONS_ ',' _NIL_ )]) $ -- Using SLIT() is not cool here.
859 zipWithEqual "gen_Show_binds"
861 (map show_label labels)
866 if nullary_con then -- skip the showParen junk...
867 ASSERT(null bs_needed)
868 ([a_Pat, con_pat], show_con)
871 showParen_Expr (HsPar (genOpApp a_Expr ge_RDR (HsLit (HsInt 10))))
872 (HsPar (nested_compose_Expr show_thingies)))
875 %************************************************************************
877 \subsection{Generating extra binds (@con2tag@ and @tag2con@)}
879 %************************************************************************
884 con2tag_Foo :: Foo ... -> Int#
885 tag2con_Foo :: Int -> Foo ... -- easier if Int, not Int#
886 maxtag_Foo :: Int -- ditto (NB: not unboxed)
889 The `tags' here start at zero, hence the @fIRST_TAG@ (currently one)
894 = GenCon2Tag | GenTag2Con | GenMaxTag
896 gen_tag_n_con_monobind
897 :: (RdrName, -- (proto)Name for the thing in question
898 TyCon, -- tycon in question
902 gen_tag_n_con_monobind (rdr_name, tycon, GenCon2Tag)
903 = mk_FunMonoBind (getSrcLoc tycon) rdr_name (map mk_stuff (tyConDataCons tycon))
905 mk_stuff :: DataCon -> ([RdrNamePat], RdrNameHsExpr)
908 = ASSERT(isDataCon var)
909 ([pat], HsLit (HsIntPrim (toInteger ((dataConTag var) - fIRST_TAG))))
911 pat = ConPatIn var_RDR (nOfThem (argFieldCount var) WildPatIn)
912 var_RDR = qual_orig_name var
914 gen_tag_n_con_monobind (rdr_name, tycon, GenTag2Con)
915 = mk_FunMonoBind (getSrcLoc tycon) rdr_name (map mk_stuff (tyConDataCons tycon) ++
916 [([WildPatIn], impossible_Expr)])
918 mk_stuff :: DataCon -> ([RdrNamePat], RdrNameHsExpr)
921 = ASSERT(isDataCon var)
922 ([lit_pat], HsVar var_RDR)
924 lit_pat = ConPatIn mkInt_RDR [LitPatIn (HsIntPrim (toInteger ((dataConTag var) - fIRST_TAG)))]
925 var_RDR = qual_orig_name var
927 gen_tag_n_con_monobind (rdr_name, tycon, GenMaxTag)
928 = mk_easy_FunMonoBind (getSrcLoc tycon)
929 rdr_name [] [] (HsApp (HsVar mkInt_RDR) (HsLit (HsIntPrim max_tag)))
931 max_tag = case (tyConDataCons tycon) of
932 data_cons -> toInteger ((length data_cons) - fIRST_TAG)
936 %************************************************************************
938 \subsection{Utility bits for generating bindings}
940 %************************************************************************
942 @mk_easy_FunMonoBind fun pats binds expr@ generates:
944 fun pat1 pat2 ... patN = expr where binds
947 @mk_FunMonoBind fun [([p1a, p1b, ...], e1), ...]@ is for
948 multi-clause definitions; it generates:
950 fun p1a p1b ... p1N = e1
951 fun p2a p2b ... p2N = e2
953 fun pMa pMb ... pMN = eM
957 mk_easy_FunMonoBind :: SrcLoc -> RdrName -> [RdrNamePat]
958 -> [RdrNameMonoBinds] -> RdrNameHsExpr
961 mk_easy_FunMonoBind loc fun pats binds expr
962 = FunMonoBind fun False{-not infix-} [mk_easy_Match loc pats binds expr] loc
964 mk_easy_Match loc pats binds expr
965 = mk_match loc pats expr (mkbind binds)
967 mkbind [] = EmptyBinds
968 mkbind bs = MonoBind (foldr1 AndMonoBinds bs) [] recursive
969 -- The renamer expects everything in its input to be a
970 -- "recursive" MonoBinds, and it is its job to sort things out
973 mk_FunMonoBind :: SrcLoc -> RdrName
974 -> [([RdrNamePat], RdrNameHsExpr)]
977 mk_FunMonoBind loc fun [] = panic "TcGenDeriv:mk_FunMonoBind"
978 mk_FunMonoBind loc fun pats_and_exprs
979 = FunMonoBind fun False{-not infix-}
980 [ mk_match loc p e EmptyBinds | (p,e) <-pats_and_exprs ]
983 mk_match loc pats expr binds
985 (GRHSMatch (GRHSsAndBindsIn [OtherwiseGRHS expr loc] binds))
988 paren p@(VarPatIn _) = p
989 paren other_p = ParPatIn other_p
993 mk_easy_App f xs = foldl HsApp (HsVar f) (map HsVar xs)
996 ToDo: Better SrcLocs.
999 compare_Case, cmp_eq_Expr ::
1000 RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
1001 -> RdrNameHsExpr -> RdrNameHsExpr
1005 -> RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
1006 -> RdrNameHsExpr -> RdrNameHsExpr
1008 careful_compare_Case :: -- checks for primitive types...
1010 -> RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
1011 -> RdrNameHsExpr -> RdrNameHsExpr
1014 compare_Case = compare_gen_Case compare_RDR
1015 cmp_eq_Expr = compare_gen_Case cmp_eq_RDR
1017 compare_gen_Case fun lt eq gt a b
1018 = HsCase (HsPar (HsApp (HsApp (HsVar fun) a) b)) {-of-}
1019 [PatMatch (ConPatIn ltTag_RDR [])
1020 (GRHSMatch (GRHSsAndBindsIn [OtherwiseGRHS lt mkGeneratedSrcLoc] EmptyBinds)),
1022 PatMatch (ConPatIn eqTag_RDR [])
1023 (GRHSMatch (GRHSsAndBindsIn [OtherwiseGRHS eq mkGeneratedSrcLoc] EmptyBinds)),
1025 PatMatch (ConPatIn gtTag_RDR [])
1026 (GRHSMatch (GRHSsAndBindsIn [OtherwiseGRHS gt mkGeneratedSrcLoc] EmptyBinds))]
1029 careful_compare_Case ty lt eq gt a b
1030 = if not (isPrimType ty) then
1031 compare_gen_Case compare_RDR lt eq gt a b
1033 else -- we have to do something special for primitive things...
1034 HsIf (genOpApp a relevant_eq_op b)
1036 (HsIf (genOpApp a relevant_lt_op b) lt gt mkGeneratedSrcLoc)
1039 relevant_eq_op = assoc_ty_id eq_op_tbl ty
1040 relevant_lt_op = assoc_ty_id lt_op_tbl ty
1042 assoc_ty_id tyids ty
1043 = if null res then panic "assoc_ty"
1046 res = [id | (ty',id) <- tyids, eqTy ty ty']
1049 [(charPrimTy, eqH_Char_RDR)
1050 ,(intPrimTy, eqH_Int_RDR)
1051 ,(wordPrimTy, eqH_Word_RDR)
1052 ,(addrPrimTy, eqH_Addr_RDR)
1053 ,(floatPrimTy, eqH_Float_RDR)
1054 ,(doublePrimTy, eqH_Double_RDR)
1058 [(charPrimTy, ltH_Char_RDR)
1059 ,(intPrimTy, ltH_Int_RDR)
1060 ,(wordPrimTy, ltH_Word_RDR)
1061 ,(addrPrimTy, ltH_Addr_RDR)
1062 ,(floatPrimTy, ltH_Float_RDR)
1063 ,(doublePrimTy, ltH_Double_RDR)
1066 -----------------------------------------------------------------------
1068 and_Expr, append_Expr :: RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
1070 and_Expr a b = genOpApp a and_RDR b
1071 append_Expr a b = genOpApp a append_RDR b
1073 -----------------------------------------------------------------------
1075 eq_Expr :: Type -> RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
1077 = if not (isPrimType ty) then
1079 else -- we have to do something special for primitive things...
1080 genOpApp a relevant_eq_op b
1082 relevant_eq_op = assoc_ty_id eq_op_tbl ty
1086 argFieldCount :: Id -> Int -- Works on data and newtype constructors
1087 argFieldCount con = length (dataConRawArgTys con)
1091 untag_Expr :: TyCon -> [(RdrName, RdrName)] -> RdrNameHsExpr -> RdrNameHsExpr
1092 untag_Expr tycon [] expr = expr
1093 untag_Expr tycon ((untag_this, put_tag_here) : more) expr
1094 = HsCase (HsPar (HsApp (con2tag_Expr tycon) (HsVar untag_this))) {-of-}
1095 [PatMatch (VarPatIn put_tag_here)
1096 (GRHSMatch (GRHSsAndBindsIn grhs EmptyBinds))]
1099 grhs = [OtherwiseGRHS (untag_Expr tycon more expr) mkGeneratedSrcLoc]
1101 cmp_tags_Expr :: RdrName -- Comparison op
1102 -> RdrName -> RdrName -- Things to compare
1103 -> RdrNameHsExpr -- What to return if true
1104 -> RdrNameHsExpr -- What to return if false
1107 cmp_tags_Expr op a b true_case false_case
1108 = HsIf (genOpApp (HsVar a) op (HsVar b)) true_case false_case mkGeneratedSrcLoc
1111 :: RdrNameHsExpr -> RdrNameHsExpr
1113 enum_from_then_to_Expr
1114 :: RdrNameHsExpr -> RdrNameHsExpr -> RdrNameHsExpr
1117 enum_from_to_Expr f t2 = HsApp (HsApp (HsVar enumFromTo_RDR) f) t2
1118 enum_from_then_to_Expr f t t2 = HsApp (HsApp (HsApp (HsVar enumFromThenTo_RDR) f) t) t2
1120 showParen_Expr, readParen_Expr
1121 :: RdrNameHsExpr -> RdrNameHsExpr
1124 showParen_Expr e1 e2 = HsApp (HsApp (HsVar showParen_RDR) e1) e2
1125 readParen_Expr e1 e2 = HsApp (HsApp (HsVar readParen_RDR) e1) e2
1127 nested_compose_Expr :: [RdrNameHsExpr] -> RdrNameHsExpr
1129 nested_compose_Expr [e] = parenify e
1130 nested_compose_Expr (e:es)
1131 = HsApp (HsApp (HsVar compose_RDR) (parenify e)) (nested_compose_Expr es)
1133 -- impossible_Expr is used in case RHSs that should never happen.
1134 -- We generate these to keep the desugarer from complaining that they *might* happen!
1135 impossible_Expr = HsApp (HsVar error_RDR) (HsLit (HsString (_PK_ "Urk! in TcGenDeriv")))
1137 parenify e@(HsVar _) = e
1138 parenify e = HsPar e
1140 -- genOpApp wraps brackets round the operator application, so that the
1141 -- renamer won't subsequently try to re-associate it.
1142 -- For some reason the renamer doesn't reassociate it right, and I can't
1143 -- be bothered to find out why just now.
1145 genOpApp e1 op e2 = mkOpApp e1 op e2
1149 qual_orig_name n = case modAndOcc n of { (m,n) -> Qual m n HiFile }
1151 a_RDR = varUnqual SLIT("a")
1152 b_RDR = varUnqual SLIT("b")
1153 c_RDR = varUnqual SLIT("c")
1154 d_RDR = varUnqual SLIT("d")
1155 ah_RDR = varUnqual SLIT("a#")
1156 bh_RDR = varUnqual SLIT("b#")
1157 ch_RDR = varUnqual SLIT("c#")
1158 dh_RDR = varUnqual SLIT("d#")
1159 cmp_eq_RDR = varUnqual SLIT("cmp_eq")
1160 rangeSize_RDR = varUnqual SLIT("rangeSize")
1162 as_RDRs = [ varUnqual (_PK_ ("a"++show i)) | i <- [(1::Int) .. ] ]
1163 bs_RDRs = [ varUnqual (_PK_ ("b"++show i)) | i <- [(1::Int) .. ] ]
1164 cs_RDRs = [ varUnqual (_PK_ ("c"++show i)) | i <- [(1::Int) .. ] ]
1166 a_Expr = HsVar a_RDR
1167 b_Expr = HsVar b_RDR
1168 c_Expr = HsVar c_RDR
1169 d_Expr = HsVar d_RDR
1170 ltTag_Expr = HsVar ltTag_RDR
1171 eqTag_Expr = HsVar eqTag_RDR
1172 gtTag_Expr = HsVar gtTag_RDR
1173 false_Expr = HsVar false_RDR
1174 true_Expr = HsVar true_RDR
1176 con2tag_Expr tycon = HsVar (con2tag_RDR tycon)
1178 a_Pat = VarPatIn a_RDR
1179 b_Pat = VarPatIn b_RDR
1180 c_Pat = VarPatIn c_RDR
1181 d_Pat = VarPatIn d_RDR
1183 con2tag_RDR, tag2con_RDR, maxtag_RDR :: TyCon -> RdrName
1185 con2tag_RDR tycon = varUnqual (SLIT("con2tag_") _APPEND_ occNameString (getOccName tycon) _APPEND_ SLIT("#"))
1186 tag2con_RDR tycon = varUnqual (SLIT("tag2con_") _APPEND_ occNameString (getOccName tycon) _APPEND_ SLIT("#"))
1187 maxtag_RDR tycon = varUnqual (SLIT("maxtag_") _APPEND_ occNameString (getOccName tycon) _APPEND_ SLIT("#"))