2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
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"
45 gen_tag_n_con_monobind,
59 IMPORT_Trace -- ToDo:rm debugging
63 import AbsSyn -- the stuff being typechecked
65 import AbsPrel {-( trueDataCon, falseDataCon, intDataCon, eRROR_ID,
66 ltPrimDataCon, eqPrimDataCon, gtPrimDataCon,
67 charPrimTy, intPrimTy, wordPrimTy, addrPrimTy,
68 floatPrimTy, doublePrimTy
70 import PrimOps -- *********** ditto
72 import AbsUniType ( getTyConDataCons, isEnumerationTyCon,
73 maybeSingleConstructorTyCon, --UNUSED: preludeClassDerivedFor,
74 -- UNUSED: isEnumerationTyConMostly,
76 TauType(..), TyVarTemplate, ThetaType(..)
77 IF_ATTACK_PRAGMAS(COMMA cmpUniType)
79 import Id ( getDataConArity, getDataConTag,
80 getDataConSig, isNullaryDataCon, fIRST_TAG,
81 isDataCon, DataCon(..), ConTag(..), Id
83 import Maybes ( maybeToBool, Maybe(..) )
84 import Name ( Name(..) )
85 import ProtoName ( ProtoName(..) )
86 import RenameAuxFuns -- why not? take all of it...
87 import RenameMonad4 -- initRn4, etc.
88 import SrcLoc ( mkGeneratedSrcLoc )
89 import TcDeriv ( con2tag_PN, tag2con_PN, maxtag_PN,
90 TagThingWanted(..), DerivEqn(..)
92 import Unique -- some ClassKey stuff
96 %************************************************************************
98 \subsection[TcGenDeriv-classes]{Generating code, by derivable class}
100 %************************************************************************
102 %************************************************************************
104 \subsubsection[TcGenDeriv-Eq]{Generating @Eq@ instance declarations}
106 %************************************************************************
108 Here are the heuristics for the code we generate for @Eq@:
111 Let's assume we have a data type with some (possibly zero) nullary
112 data constructors and some ordinary, non-nullary ones (the rest,
113 also possibly zero of them). Here's an example, with both \tr{N}ullary
114 and \tr{O}rdinary data cons.
116 data Foo ... = N1 | N2 ... | Nn | O1 a b | O2 Int | O3 Double b b | ...
120 For the ordinary constructors (if any), we emit clauses to do The
124 (==) (O1 a1 b1) (O1 a2 b2) = a1 == a2 && b1 == b2
125 (==) (O2 a1) (O2 a2) = a1 == a2
126 (==) (O3 a1 b1 c1) (O3 a2 b2 c2) = a1 == a2 && b1 == b2 && c1 == c2
129 Note: if we're comparing unboxed things, e.g., if \tr{a1} and
130 \tr{a2} are \tr{Float#}s, then we have to generate
132 case (a1 `eqFloat#` a2) of
135 for that particular test.
138 If there are any nullary constructors, we emit a catch-all clause of
142 (==) a b = case (con2tag_Foo a) of { a# ->
143 case (con2tag_Foo b) of { b# ->
144 case (a# ==# b#) of {
149 If there aren't any nullary constructors, we emit a simpler
156 For the @(/=)@ method, we normally just use the default method.
158 If the type is an enumeration type, we could/may/should? generate
159 special code that calls @con2tag_Foo@, much like for @(==)@ shown
163 We thought about doing this: If we're also deriving @Ord@ for this
166 instance ... Eq (Foo ...) where
167 (==) a b = case (tagCmp a b) of { _LT -> False; _EQ -> True ; _GT -> False}
168 (/=) a b = case (tagCmp a b) of { _LT -> True ; _EQ -> False; _GT -> True }
170 However, that requires that \tr{Ord <whatever>} was put in the context
171 for the instance decl, which it probably wasn't, so the decls
172 produced don't get through the typechecker.
176 gen_Eq_binds :: TyCon -> ProtoNameMonoBinds
179 = case (partition isNullaryDataCon (getTyConDataCons tycon))
180 of { (nullary_cons, nonnullary_cons) ->
183 = if null nullary_cons then
184 case maybeSingleConstructorTyCon tycon of
186 Nothing -> -- if cons don't match, then False
187 [([a_Pat, b_Pat], false_Expr)]
188 else -- calc. and compare the tags
190 untag_Expr tycon [(a_PN,ah_PN), (b_PN,bh_PN)]
191 (cmp_tags_Expr eqH_PN ah_PN bh_PN true_Expr false_Expr))]
193 mk_FunMonoBind eq_PN ((map pats_etc nonnullary_cons) ++ rest)
194 `AndMonoBinds` boring_ne_method
197 ------------------------------------------------------------------
200 con1_pat = ConPatIn data_con_PN (map VarPatIn as_needed)
201 con2_pat = ConPatIn data_con_PN (map VarPatIn bs_needed)
203 data_con_PN = Prel (WiredInVal data_con)
204 as_needed = take (getDataConArity data_con) as_PNs
205 bs_needed = take (getDataConArity data_con) bs_PNs
206 tys_needed = case (getDataConSig data_con) of
207 (_,_, arg_tys, _) -> arg_tys
209 ([con1_pat, con2_pat], nested_eq_expr tys_needed as_needed bs_needed)
211 nested_eq_expr [] [] [] = true_Expr
212 nested_eq_expr [ty] [a] [b] = eq_Expr ty (Var a) (Var b)
213 nested_eq_expr (t:ts) (a:as) (b:bs)
215 rest_expr = nested_eq_expr ts as bs
217 and_Expr (eq_Expr t (Var a) (Var b)) rest_expr
220 = mk_easy_FunMonoBind ne_PN [a_Pat, b_Pat] [] (
221 App (Var not_PN) (App (App (Var eq_PN) a_Expr) b_Expr)
225 %************************************************************************
227 \subsubsection[TcGenDeriv-Ord]{Generating @Ord@ instance declarations}
229 %************************************************************************
231 For a derived @Ord@, we concentrate our attentions on the non-standard
232 @_tagCmp@ method, which type:
234 _tagCmp :: a -> a -> _CMP_TAG
236 -- and the builtin tag type is:
238 data _CMP_TAG = _LT | _EQ | _GT deriving ()
241 (All this @_tagCmp@ stuff is due to the sterling analysis by Julian
244 We will use the same example data type as above:
246 data Foo ... = N1 | N2 ... | Nn | O1 a b | O2 Int | O3 Double b b | ...
251 We do all the other @Ord@ methods with calls to @_tagCmp@:
253 instance ... (Ord <wurble> <wurble>) where
254 a < b = case _tagCmp a b of { _LT -> True; _EQ -> False; _GT -> False }
255 a <= b = case _tagCmp a b of { _LT -> True; _EQ -> True; _GT -> False }
256 a >= b = case _tagCmp a b of { _LT -> False; _EQ -> True; _GT -> True }
257 a > b = case _tagCmp a b of { _LT -> False; _EQ -> False; _GT -> True }
259 max a b = case _tagCmp a b of { _LT -> b; _EQ -> a; _GT -> a }
260 min a b = case _tagCmp a b of { _LT -> a; _EQ -> a; _GT -> b }
262 -- _tagCmp to come...
266 @_tagCmp@ always has two parts. First, we use the compared
267 data-constructors' tags to deal with the case of different
270 _tagCmp a b = case (con2tag_Foo a) of { a# ->
271 case (con2tag_Foo b) of { b# ->
272 case (a# ==# b#) of {
274 False -> case (a# <# b#) of
279 cmp_eq = ... to come ...
283 We are only left with the ``help'' function @cmp_eq@, to deal with
284 comparing data constructors with the same tag.
286 For the ordinary constructors (if any), we emit the sorta-obvious
287 tagCmp-style stuff; for our example:
289 cmp_eq (O1 a1 b1) (O1 a2 b2)
290 = case (_tagCmp a1 a2) of { _LT -> _LT; _EQ -> _tagCmp b1 b2; _GT -> _GT }
292 cmp_eq (O2 a1) (O2 a2)
295 cmp_eq (O3 a1 b1 c1) (O3 a2 b2 c2)
296 = case (_tagCmp a1 a2) of {
299 _EQ -> case _tagCmp b1 b2 of {
307 Again, we must be careful about unboxed comparisons. For example,
308 if \tr{a1} and \tr{a2} were \tr{Int#}s in the 2nd example above, we'd need to
311 cmp_eq lt eq gt (O2 a1) (O2 a2)
313 -- or maybe the unfolded equivalent
317 For the remaining nullary constructors, we already know that the
325 gen_Ord_binds :: TyCon -> ProtoNameMonoBinds
328 = defaulted `AndMonoBinds` tagCmp
330 --------------------------------------------------------------------
331 tagCmp = mk_easy_FunMonoBind tagCmp_PN
334 (if maybeToBool (maybeSingleConstructorTyCon tycon) then
335 cmp_eq_Expr lt_TAG_Expr eq_TAG_Expr gt_TAG_Expr a_Expr b_Expr
337 untag_Expr tycon [(a_PN, ah_PN), (b_PN, bh_PN)]
338 (cmp_tags_Expr eqH_PN ah_PN bh_PN
339 -- True case; they are equal
340 -- If an enumeration type we are done; else
341 -- recursively compare their components
342 (if isEnumerationTyCon tycon then
345 cmp_eq_Expr lt_TAG_Expr eq_TAG_Expr gt_TAG_Expr a_Expr b_Expr
347 -- False case; they aren't equal
348 -- So we need to do a less-than comparison on the tags
349 (cmp_tags_Expr ltH_PN ah_PN bh_PN lt_TAG_Expr gt_TAG_Expr)))
351 (nullary_cons, nonnullary_cons)
352 = partition isNullaryDataCon (getTyConDataCons tycon)
355 = mk_FunMonoBind cmp_eq_PN (map pats_etc nonnullary_cons ++ deflt_pats_etc)
358 = ([con1_pat, con2_pat],
359 nested_tagCmp_expr tys_needed as_needed bs_needed)
361 con1_pat = ConPatIn data_con_PN (map VarPatIn as_needed)
362 con2_pat = ConPatIn data_con_PN (map VarPatIn bs_needed)
364 data_con_PN = Prel (WiredInVal data_con)
365 as_needed = take (getDataConArity data_con) as_PNs
366 bs_needed = take (getDataConArity data_con) bs_PNs
367 tys_needed = case (getDataConSig data_con) of
368 (_,_, arg_tys, _) -> arg_tys
370 nested_tagCmp_expr [ty] [a] [b]
371 = careful_tagCmp_Case ty lt_TAG_Expr eq_TAG_Expr gt_TAG_Expr (Var a) (Var b)
373 nested_tagCmp_expr (ty:tys) (a:as) (b:bs)
374 = let eq_expr = nested_tagCmp_expr tys as bs
375 in careful_tagCmp_Case ty lt_TAG_Expr eq_expr gt_TAG_Expr (Var a) (Var b)
378 = if null nullary_cons
380 else [([a_Pat, b_Pat], eq_TAG_Expr)]
381 --------------------------------------------------------------------
383 defaulted = foldr1 AndMonoBinds [lt, le, ge, gt, max_, min_]
385 lt = mk_easy_FunMonoBind lt_PN [a_Pat, b_Pat] [] (
386 tagCmp_Case true_Expr false_Expr false_Expr a_Expr b_Expr)
387 le = mk_easy_FunMonoBind le_PN [a_Pat, b_Pat] [] (
388 tagCmp_Case true_Expr true_Expr false_Expr a_Expr b_Expr)
389 ge = mk_easy_FunMonoBind ge_PN [a_Pat, b_Pat] [] (
390 tagCmp_Case false_Expr true_Expr true_Expr a_Expr b_Expr)
391 gt = mk_easy_FunMonoBind gt_PN [a_Pat, b_Pat] [] (
392 tagCmp_Case false_Expr false_Expr true_Expr a_Expr b_Expr)
394 max_ = mk_easy_FunMonoBind max_PN [a_Pat, b_Pat] [] (
395 tagCmp_Case b_Expr a_Expr a_Expr a_Expr b_Expr)
396 min_ = mk_easy_FunMonoBind min_PN [a_Pat, b_Pat] [] (
397 tagCmp_Case a_Expr a_Expr b_Expr a_Expr b_Expr)
400 %************************************************************************
402 \subsubsection[TcGenDeriv-Enum]{Generating @Enum@ instance declarations}
404 %************************************************************************
406 @Enum@ can only be derived for enumeration types. For a type
408 data Foo ... = N1 | N2 | ... | Nn
411 we use both @con2tag_Foo@ and @tag2con_Foo@ functions, as well as a
412 @maxtag_Foo@ variable (all generated by @gen_tag_n_con_binds@).
415 instance ... Enum (Foo ...) where
416 enumFrom a = map tag2con_Foo [con2tag_Foo a .. maxtag_Foo]
420 = case con2tag_Foo a of
421 a# -> map tag2con_Foo (enumFromTo (I# a#) maxtag_Foo)
424 = map tag2con_Foo [con2tag_Foo a, con2tag_Foo b .. maxtag_Foo]
428 = case con2tag_Foo a of { a# ->
429 case con2tag_Foo b of { b# ->
430 map tag2con_Foo (enumFromThenTo (I# a#) (I# b#) maxtag_Foo)
434 For @enumFromTo@ and @enumFromThenTo@, we use the default methods.
437 gen_Enum_binds :: TyCon -> ProtoNameMonoBinds
440 = enum_from `AndMonoBinds` enum_from_then
443 = mk_easy_FunMonoBind enumFrom_PN [a_Pat] [] (
444 untag_Expr tycon [(a_PN, ah_PN)] (
445 App (App (Var map_PN) (Var (tag2con_PN tycon))) (
447 (App (Var mkInt_PN) (Var ah_PN))
448 (Var (maxtag_PN tycon)))))
451 = mk_easy_FunMonoBind enumFromThen_PN [a_Pat, b_Pat] [] (
452 untag_Expr tycon [(a_PN, ah_PN), (b_PN, bh_PN)] (
453 App (App (Var map_PN) (Var (tag2con_PN tycon))) (
454 enum_from_then_to_Expr
455 (App (Var mkInt_PN) (Var ah_PN))
456 (App (Var mkInt_PN) (Var bh_PN))
457 (Var (maxtag_PN tycon)))))
460 %************************************************************************
462 \subsubsection[TcGenDeriv-Ix]{Generating @Ix@ instance declarations}
464 %************************************************************************
466 Deriving @Ix@ is only possible for enumeration types and
467 single-constructor types. We deal with them in turn.
469 For an enumeration type, e.g.,
471 data Foo ... = N1 | N2 | ... | Nn
473 things go not too differently from @Enum@:
475 instance ... Ix (Foo ...) where
477 = map tag2con_Foo [con2tag_Foo a .. con2tag_Foo b]
481 = case (con2tag_Foo a) of { a# ->
482 case (con2tag_Foo b) of { b# ->
483 map tag2con_Foo (enumFromTo (I# a#) (I# b#))
488 then case (con2tag_Foo d -# con2tag_Foo a) of
490 else error "Ix.Foo.index: out of range"
494 p_tag = con2tag_Foo c
496 p_tag >= con2tag_Foo a && p_tag <= con2tag_Foo b
500 = case (con2tag_Foo a) of { a_tag ->
501 case (con2tag_Foo b) of { b_tag ->
502 case (con2tag_Foo c) of { c_tag ->
503 if (c_tag >=# a_tag) then
509 (modulo suitable case-ification to handle the unboxed tags)
511 For a single-constructor type (NB: this includes all tuples), e.g.,
513 data Foo ... = MkFoo a b Int Double c c
515 we follow the scheme given in Figure~19 of the Haskell~1.2 report
519 gen_Ix_binds :: TyCon -> ProtoNameMonoBinds
522 = if isEnumerationTyCon tycon
526 tycon_str = _UNPK_ (snd (getOrigName tycon))
528 --------------------------------------------------------------
529 enum_ixes = enum_range `AndMonoBinds`
530 enum_index `AndMonoBinds` enum_inRange
533 = mk_easy_FunMonoBind range_PN [TuplePatIn [a_Pat, b_Pat]] [] (
534 untag_Expr tycon [(a_PN, ah_PN)] (
535 untag_Expr tycon [(b_PN, bh_PN)] (
536 App (App (Var map_PN) (Var (tag2con_PN tycon))) (
538 (App (Var mkInt_PN) (Var ah_PN))
539 (App (Var mkInt_PN) (Var bh_PN))
543 = mk_easy_FunMonoBind index_PN [AsPatIn c_PN (TuplePatIn [a_Pat, b_Pat]), d_Pat] [] (
544 If (App (App (Var inRange_PN) c_Expr) d_Expr) (
545 untag_Expr tycon [(a_PN, ah_PN)] (
546 untag_Expr tycon [(d_PN, dh_PN)] (
548 grhs = [OtherwiseGRHS (App (Var mkInt_PN) (Var c_PN)) mkGeneratedSrcLoc]
550 Case (OpApp (Var dh_PN) (Var minusH_PN) (Var ah_PN)) {-of-}
551 [PatMatch (VarPatIn c_PN)
552 (GRHSMatch (GRHSsAndBindsIn grhs EmptyBinds))]
555 App (Var error_PN) (Lit (StringLit (_PK_ ("Ix."++tycon_str++".index: out of range\n"))))
560 = mk_easy_FunMonoBind inRange_PN [TuplePatIn [a_Pat, b_Pat], c_Pat] [] (
561 untag_Expr tycon [(a_PN, ah_PN)] (
562 untag_Expr tycon [(b_PN, bh_PN)] (
563 untag_Expr tycon [(c_PN, ch_PN)] (
564 If (OpApp (Var ch_PN) (Var geH_PN) (Var ah_PN)) (
565 (OpApp (Var ch_PN) (Var leH_PN) (Var bh_PN))
570 --------------------------------------------------------------
571 single_con_ixes = single_con_range `AndMonoBinds`
572 single_con_index `AndMonoBinds` single_con_inRange
575 = case maybeSingleConstructorTyCon tycon of -- just checking...
576 Nothing -> panic "get_Ix_binds"
578 (_, _, arg_tys, _) = getDataConSig dc
580 if any isPrimType arg_tys then
581 error ("ERROR: Can't derive Ix for a single-constructor type with primitive argument types: "++tycon_str)
585 con_arity = getDataConArity data_con
586 data_con_PN = Prel (WiredInVal data_con)
587 con_pat xs = ConPatIn data_con_PN (map VarPatIn xs)
588 con_expr xs = foldl App (Var data_con_PN) (map Var xs)
590 as_needed = take (getDataConArity data_con) as_PNs
591 bs_needed = take (getDataConArity data_con) bs_PNs
592 cs_needed = take (getDataConArity data_con) cs_PNs
594 --------------------------------------------------------------
596 = mk_easy_FunMonoBind range_PN [TuplePatIn [con_pat as_needed, con_pat bs_needed]] [] (
597 ListComp (con_expr cs_needed) (zipWith3 mk_qual as_needed bs_needed cs_needed)
600 mk_qual a b c = GeneratorQual (VarPatIn c)
601 (App (Var range_PN) (ExplicitTuple [Var a, Var b]))
605 = mk_easy_FunMonoBind index_PN [TuplePatIn [con_pat as_needed, con_pat bs_needed], con_pat cs_needed] [range_size] (
606 foldl mk_index (Lit (IntLit 0)) (zip3 as_needed bs_needed cs_needed))
608 mk_index multiply_by (l, u, i)
610 (App (App (Var index_PN) (ExplicitTuple [Var l, Var u])) (Var i))
613 (App (Var rangeSize_PN) (ExplicitTuple [Var l, Var u]))
614 ) (Var times_PN) multiply_by
618 = mk_easy_FunMonoBind rangeSize_PN [TuplePatIn [a_Pat, b_Pat]] [] (
620 (App (App (Var index_PN) (ExplicitTuple [a_Expr, b_Expr])) b_Expr)
621 ) (Var plus_PN) (Lit (IntLit 1)))
625 = mk_easy_FunMonoBind inRange_PN [TuplePatIn [con_pat as_needed, con_pat bs_needed], con_pat cs_needed] [] (
626 foldl1 and_Expr (zipWith3 in_range as_needed bs_needed cs_needed))
628 in_range a b c = App (App (Var inRange_PN) (ExplicitTuple [Var a, Var b])) (Var c)
631 %************************************************************************
633 \subsubsection[TcGenDeriv-Text]{Generating @Text@ instance declarations}
635 %************************************************************************
637 Deriving @Text@ is a pain. @show@ is commonly used; @read@ is rarely
638 used---but we're supposed to generate massive amounts of code for it
639 anyway. We provide a command-line flag to say ``Don't bother''
642 We just use the default methods for @showList@ and @readList@.
644 Also: ignoring all the infix-ery mumbo jumbo (ToDo)
646 The part of the Haskell report that deals with this (pages~147--151,
647 1.2~version) is an adequate guide to what needs to be done. Note that
648 this is where we may (eventually) use the fixity info that's been
652 gen_Text_binds :: [RenamedFixityDecl] -> Bool -> TyCon -> ProtoNameMonoBinds
654 gen_Text_binds fixities omit_derived_read tycon
655 = if omit_derived_read
657 else shows_prec `AndMonoBinds` reads_prec
659 -----------------------------------------------------------------------
661 = mk_FunMonoBind showsPrec_PN (map pats_etc (getTyConDataCons tycon))
665 data_con_PN = Prel (WiredInVal data_con)
666 bs_needed = take (getDataConArity data_con) bs_PNs
667 con_pat = ConPatIn data_con_PN (map VarPatIn bs_needed)
670 = let (mod, nm) = getOrigName data_con
671 space_maybe = if isNullaryDataCon data_con then _NIL_ else SLIT(" ")
673 App (Var showString_PN) (Lit (StringLit (nm _APPEND_ space_maybe)))
675 show_thingies = show_con : (spacified real_show_thingies)
678 = [ App (App (Var showsPrec_PN) (Lit (IntLit 10))) (Var b)
682 showParen_Expr (OpApp a_Expr (Var ge_PN) (Lit (IntLit 10)))
683 (nested_compose_Expr show_thingies))
687 spacified (x:xs) = (x : (Var showSpace_PN) : spacified xs)
689 -----------------------------------------------------------------------
690 reads_prec -- ignore the infix game altogether
692 read_con_comprehensions
693 = map read_con (getTyConDataCons tycon)
695 mk_easy_FunMonoBind readsPrec_PN [a_Pat] [] (
696 readParen_Expr (OpApp a_Expr (Var gt_PN) (Lit (IntLit 9))) (
697 Lam (mk_easy_Match [b_Pat] [] (
698 foldl1 append_Expr read_con_comprehensions
701 read_con data_con -- note: "b" is the string being "read"
703 data_con_PN = Prel (WiredInVal data_con)
704 data_con_str= snd (getOrigName data_con)
705 as_needed = take (getDataConArity data_con) as_PNs
706 bs_needed = take (getDataConArity data_con) bs_PNs
707 con_expr = foldl App (Var data_con_PN) (map Var as_needed)
711 (TuplePatIn [LitPatIn (StringLit data_con_str), c_Pat])
712 (App (Var lex_PN) b_Expr)
714 field_quals = snd (mapAccumL mk_qual c_Expr (as_needed `zip` bs_needed))
716 ListComp (ExplicitTuple [con_expr,
717 if null bs_needed then c_Expr else Var (last bs_needed)])
718 (con_qual : field_quals)
720 mk_qual draw_from (con_field, str_left)
721 = (Var str_left, -- what to draw from down the line...
723 (TuplePatIn [VarPatIn con_field, VarPatIn str_left])
724 (App (App (Var readsPrec_PN) (Lit (IntLit 10))) draw_from))
727 %************************************************************************
729 \subsubsection[TcGenDeriv-Binary]{Generating @Binary@ instance declarations}
731 %************************************************************************
736 gen_Binary_binds :: TyCon -> ProtoNameMonoBinds
738 gen_Binary_binds tycon
739 = panic "gen_Binary_binds"
742 %************************************************************************
744 \subsection[TcGenDeriv-con2tag-tag2con]{Generating extra binds (@con2tag@ and @tag2con@)}
746 %************************************************************************
751 con2tag_Foo :: Foo ... -> Int#
752 tag2con_Foo :: Int -> Foo ... -- easier if Int, not Int#
753 maxtag_Foo :: Int -- ditto (NB: not unboxed)
756 The `tags' here start at zero, hence the @fIRST_TAG@ (currently one)
760 gen_tag_n_con_monobind
761 :: (ProtoName, Name, -- (proto)Name for the thing in question
762 TyCon, -- tycon in question
764 -> ProtoNameMonoBinds
766 gen_tag_n_con_monobind (pn, _, tycon, GenCon2Tag)
767 = mk_FunMonoBind pn (map mk_stuff (getTyConDataCons tycon))
769 mk_stuff :: DataCon -> ([ProtoNamePat], ProtoNameExpr)
772 = ASSERT(isDataCon var)
773 ([pat], Lit (IntPrimLit (toInteger ((getDataConTag var) - fIRST_TAG))))
775 pat = ConPatIn var_PN (nOfThem (getDataConArity var) WildPatIn)
776 var_PN = Prel (WiredInVal var)
778 gen_tag_n_con_monobind (pn, _, tycon, GenTag2Con)
779 = mk_FunMonoBind pn (map mk_stuff (getTyConDataCons tycon))
781 mk_stuff :: DataCon -> ([ProtoNamePat], ProtoNameExpr)
784 = ASSERT(isDataCon var)
785 ([lit_pat], Var var_PN)
787 lit_pat = ConPatIn mkInt_PN [LitPatIn (IntPrimLit (toInteger ((getDataConTag var) - fIRST_TAG)))]
788 var_PN = Prel (WiredInVal var)
790 gen_tag_n_con_monobind (pn, _, tycon, GenMaxTag)
791 = mk_easy_FunMonoBind pn [] [] (App (Var mkInt_PN) (Lit (IntPrimLit max_tag)))
793 max_tag = case (getTyConDataCons tycon) of
794 data_cons -> toInteger ((length data_cons) - fIRST_TAG)
797 %************************************************************************
799 \subsection[TcGenDeriv-bind-utils]{Utility bits for generating bindings}
801 %************************************************************************
803 @mk_easy_FunMonoBind fun pats binds expr@ generates:
805 fun pat1 pat2 ... patN = expr where binds
808 @mk_FunMonoBind fun [([p1a, p1b, ...], e1), ...]@ is for
809 multi-clause definitions; it generates:
811 fun p1a p1b ... p1N = e1
812 fun p2a p2b ... p2N = e2
814 fun pMa pMb ... pMN = eM
818 mk_easy_FunMonoBind :: ProtoName -> [ProtoNamePat]
819 -> [ProtoNameMonoBinds] -> ProtoNameExpr
820 -> ProtoNameMonoBinds
822 mk_easy_FunMonoBind fun pats binds expr
823 = FunMonoBind fun [mk_easy_Match pats binds expr] mkGeneratedSrcLoc
825 mk_easy_Match pats binds expr
827 (GRHSMatch (GRHSsAndBindsIn [OtherwiseGRHS expr mkGeneratedSrcLoc] (mkbind binds)))
830 mkbind [] = EmptyBinds
831 mkbind bs = SingleBind (RecBind (foldr1 AndMonoBinds bs))
832 -- The renamer expects everything in its input to be a
833 -- "recursive" MonoBinds, and it is its job to sort things out
836 mk_FunMonoBind :: ProtoName
837 -> [([ProtoNamePat], ProtoNameExpr)]
838 -> ProtoNameMonoBinds
840 mk_FunMonoBind fun [] = panic "TcGenDeriv:mk_FunMonoBind"
841 mk_FunMonoBind fun pats_and_exprs
842 = FunMonoBind fun (map mk_match pats_and_exprs) mkGeneratedSrcLoc
844 mk_match (pats, expr)
846 (GRHSMatch (GRHSsAndBindsIn [OtherwiseGRHS expr mkGeneratedSrcLoc] EmptyBinds))
851 tagCmp_Case, cmp_eq_Expr ::
852 ProtoNameExpr -> ProtoNameExpr -> ProtoNameExpr
853 -> ProtoNameExpr -> ProtoNameExpr
857 -> ProtoNameExpr -> ProtoNameExpr -> ProtoNameExpr
858 -> ProtoNameExpr -> ProtoNameExpr
860 careful_tagCmp_Case :: -- checks for primitive types...
862 -> ProtoNameExpr -> ProtoNameExpr -> ProtoNameExpr
863 -> ProtoNameExpr -> ProtoNameExpr
866 tagCmp_Case = tagCmp_gen_Case tagCmp_PN
867 cmp_eq_Expr = tagCmp_gen_Case cmp_eq_PN
869 tagCmp_gen_Case fun lt eq gt a b
870 = Case (App (App (Var fun) a) b) {-of-}
871 [PatMatch (ConPatIn lt_TAG_PN [])
872 (GRHSMatch (GRHSsAndBindsIn [OtherwiseGRHS lt mkGeneratedSrcLoc] EmptyBinds)),
874 PatMatch (ConPatIn eq_TAG_PN [])
875 (GRHSMatch (GRHSsAndBindsIn [OtherwiseGRHS eq mkGeneratedSrcLoc] EmptyBinds)),
877 PatMatch (ConPatIn gt_TAG_PN [])
878 (GRHSMatch (GRHSsAndBindsIn [OtherwiseGRHS gt mkGeneratedSrcLoc] EmptyBinds))]
880 careful_tagCmp_Case ty lt eq gt a b
881 = if not (isPrimType ty) then
882 tagCmp_gen_Case tagCmp_PN lt eq gt a b
884 else -- we have to do something special for primitive things...
885 If (OpApp a (Var relevant_eq_op) b)
887 (If (OpApp a (Var relevant_lt_op) b) lt gt)
889 relevant_eq_op = assoc "careful_tagCmp_Case" eq_op_tbl ty
890 relevant_lt_op = assoc "careful_tagCmp_Case" lt_op_tbl ty
893 (charPrimTy, Prel (WiredInVal (primOpId CharEqOp))),
894 (intPrimTy, Prel (WiredInVal (primOpId IntEqOp))),
895 (wordPrimTy, Prel (WiredInVal (primOpId WordEqOp))),
896 (addrPrimTy, Prel (WiredInVal (primOpId AddrEqOp))),
897 (floatPrimTy, Prel (WiredInVal (primOpId FloatEqOp))),
898 (doublePrimTy, Prel (WiredInVal (primOpId DoubleEqOp))) ]
901 (charPrimTy, Prel (WiredInVal (primOpId CharLtOp))),
902 (intPrimTy, Prel (WiredInVal (primOpId IntLtOp))),
903 (wordPrimTy, Prel (WiredInVal (primOpId WordLtOp))),
904 (addrPrimTy, Prel (WiredInVal (primOpId AddrLtOp))),
905 (floatPrimTy, Prel (WiredInVal (primOpId FloatLtOp))),
906 (doublePrimTy, Prel (WiredInVal (primOpId DoubleLtOp))) ]
908 -----------------------------------------------------------------------
910 and_Expr, append_Expr :: ProtoNameExpr -> ProtoNameExpr -> ProtoNameExpr
912 and_Expr a b = OpApp a (Var and_PN) b
913 append_Expr a b = OpApp a (Var append_PN) b
915 -----------------------------------------------------------------------
917 eq_Expr :: UniType -> ProtoNameExpr -> ProtoNameExpr -> ProtoNameExpr
919 = if not (isPrimType ty) then
920 OpApp a (Var eq_PN) b
921 else -- we have to do something special for primitive things...
922 OpApp a (Var relevant_eq_op) b
924 relevant_eq_op = assoc "eq_Expr" eq_op_tbl ty
928 untag_Expr :: TyCon -> [(ProtoName, ProtoName)] -> ProtoNameExpr -> ProtoNameExpr
929 untag_Expr tycon [] expr = expr
930 untag_Expr tycon ((untag_this, put_tag_here) : more) expr
931 = Case (App (con2tag_Expr tycon) (Var untag_this)) {-of-}
932 [PatMatch (VarPatIn put_tag_here)
933 (GRHSMatch (GRHSsAndBindsIn grhs EmptyBinds))]
935 grhs = [OtherwiseGRHS (untag_Expr tycon more expr) mkGeneratedSrcLoc]
937 cmp_tags_Expr :: ProtoName -- Comparison op
938 -> ProtoName -> ProtoName -- Things to compare
939 -> ProtoNameExpr -- What to return if true
940 -> ProtoNameExpr -- What to return if false
943 cmp_tags_Expr op a b true_case false_case
944 = If (OpApp (Var a) (Var op) (Var b)) true_case false_case
947 :: ProtoNameExpr -> ProtoNameExpr
949 enum_from_then_to_Expr
950 :: ProtoNameExpr -> ProtoNameExpr -> ProtoNameExpr
953 enum_from_to_Expr f t2 = App (App (Var enumFromTo_PN) f) t2
954 enum_from_then_to_Expr f t t2 = App (App (App (Var enumFromThenTo_PN) f) t) t2
956 showParen_Expr, readParen_Expr
957 :: ProtoNameExpr -> ProtoNameExpr
960 showParen_Expr e1 e2 = App (App (Var showParen_PN) e1) e2
961 readParen_Expr e1 e2 = App (App (Var readParen_PN) e1) e2
963 nested_compose_Expr :: [ProtoNameExpr] -> ProtoNameExpr
965 nested_compose_Expr [e] = e
966 nested_compose_Expr (e:es)
967 = App (App (Var compose_PN) e) (nested_compose_Expr es)
975 ah_PN = Unk SLIT("a#")
976 bh_PN = Unk SLIT("b#")
977 ch_PN = Unk SLIT("c#")
978 dh_PN = Unk SLIT("d#")
979 cmp_eq_PN = Unk SLIT("cmp_eq")
980 rangeSize_PN = Unk SLIT("rangeSize")
982 as_PNs = [ Unk (_PK_ ("a"++show i)) | i <- [(1::Int) .. ] ]
983 bs_PNs = [ Unk (_PK_ ("b"++show i)) | i <- [(1::Int) .. ] ]
984 cs_PNs = [ Unk (_PK_ ("c"++show i)) | i <- [(1::Int) .. ] ]
986 eq_PN = prelude_method SLIT("Eq") SLIT("==")
987 ne_PN = prelude_method SLIT("Eq") SLIT("/=")
988 le_PN = prelude_method SLIT("Ord") SLIT("<=")
989 lt_PN = prelude_method SLIT("Ord") SLIT("<")
990 ge_PN = prelude_method SLIT("Ord") SLIT(">=")
991 gt_PN = prelude_method SLIT("Ord") SLIT(">")
992 max_PN = prelude_method SLIT("Ord") SLIT("max")
993 min_PN = prelude_method SLIT("Ord") SLIT("min")
994 tagCmp_PN = prelude_method SLIT("Ord") SLIT("_tagCmp")
995 lt_TAG_PN = Prel (WiredInVal ltPrimDataCon)
996 eq_TAG_PN = Prel (WiredInVal eqPrimDataCon)
997 gt_TAG_PN = Prel (WiredInVal gtPrimDataCon)
998 enumFrom_PN = prelude_method SLIT("Enum") SLIT("enumFrom")
999 enumFromTo_PN = prelude_method SLIT("Enum") SLIT("enumFromTo")
1000 enumFromThen_PN = prelude_method SLIT("Enum") SLIT("enumFromThen")
1001 enumFromThenTo_PN= prelude_method SLIT("Enum") SLIT("enumFromThenTo")
1002 range_PN = prelude_method SLIT("Ix") SLIT("range")
1003 index_PN = prelude_method SLIT("Ix") SLIT("index")
1004 inRange_PN = prelude_method SLIT("Ix") SLIT("inRange")
1005 readsPrec_PN = prelude_method SLIT("Text") SLIT("readsPrec")
1006 showsPrec_PN = prelude_method SLIT("Text") SLIT("showsPrec")
1007 plus_PN = prelude_method SLIT("Num") SLIT("+")
1008 times_PN = prelude_method SLIT("Num") SLIT("*")
1010 false_PN = Prel (WiredInVal falseDataCon)
1011 true_PN = Prel (WiredInVal trueDataCon)
1012 eqH_PN = Prel (WiredInVal (primOpId IntEqOp))
1013 geH_PN = Prel (WiredInVal (primOpId IntGeOp))
1014 leH_PN = Prel (WiredInVal (primOpId IntLeOp))
1015 ltH_PN = Prel (WiredInVal (primOpId IntLtOp))
1016 minusH_PN = Prel (WiredInVal (primOpId IntSubOp))
1017 and_PN = prelude_val pRELUDE SLIT("&&")
1018 not_PN = prelude_val pRELUDE SLIT("not")
1019 append_PN = prelude_val pRELUDE_LIST SLIT("++")
1020 map_PN = prelude_val pRELUDE_LIST SLIT("map")
1021 compose_PN = prelude_val pRELUDE SLIT(".")
1022 mkInt_PN = Prel (WiredInVal intDataCon)
1023 error_PN = Prel (WiredInVal eRROR_ID)
1024 showSpace_PN = prelude_val pRELUDE_TEXT SLIT("showSpace__") -- not quite std
1025 showString_PN = prelude_val pRELUDE_TEXT SLIT("showString")
1026 showParen_PN = prelude_val pRELUDE_TEXT SLIT("showParen")
1027 readParen_PN = prelude_val pRELUDE_TEXT SLIT("readParen")
1028 lex_PN = prelude_val pRELUDE_TEXT SLIT("lex")
1030 prelude_val m s = Imp m s [m] s
1031 prelude_method c o = Imp pRELUDE_CORE o [pRELUDE_CORE] o -- class not used...
1037 lt_TAG_Expr = Var lt_TAG_PN
1038 eq_TAG_Expr = Var eq_TAG_PN
1039 gt_TAG_Expr = Var gt_TAG_PN
1040 false_Expr = Var false_PN
1041 true_Expr = Var true_PN
1043 con2tag_Expr tycon = Var (con2tag_PN tycon)
1045 a_Pat = VarPatIn a_PN
1046 b_Pat = VarPatIn b_PN
1047 c_Pat = VarPatIn c_PN
1048 d_Pat = VarPatIn d_PN
1051 %************************************************************************
1053 \subsection[TcGenDeriv-misc-utils]{Miscellaneous utility bits for deriving}
1055 %************************************************************************
1059 hasCon2TagFun :: TyCon -> Bool
1061 = preludeClassDerivedFor ordClassKey tycon
1062 || isEnumerationTyConMostly tycon
1064 hasTag2ConFun :: TyCon -> Bool
1066 = isEnumerationTyCon tycon
1067 && (preludeClassDerivedFor ixClassKey tycon
1068 || preludeClassDerivedFor enumClassKey tycon)