diff options
Diffstat (limited to 'ghc/compiler/rename/RenameBinds4.lhs')
-rw-r--r-- | ghc/compiler/rename/RenameBinds4.lhs | 652 |
1 files changed, 652 insertions, 0 deletions
diff --git a/ghc/compiler/rename/RenameBinds4.lhs b/ghc/compiler/rename/RenameBinds4.lhs new file mode 100644 index 0000000000..fe4149539a --- /dev/null +++ b/ghc/compiler/rename/RenameBinds4.lhs @@ -0,0 +1,652 @@ +% +% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995 +% +\section[RenameBinds4]{Renaming and dependency analysis of bindings} + +This module does renaming and dependency analysis on value bindings in +@AbsSyntax@ programs. It does {\em not} do cycle-checks on class or +type-synonym declarations; those cannot be done at this stage because +they may be affected by renaming (which isn't fully worked out yet). + +\begin{code} +#include "HsVersions.h" + +module RenameBinds4 ( + rnTopBinds4, rnMethodBinds4, + rnBinds4, + FreeVars(..), DefinedVars(..), + + -- and to make the interface self-sufficient... + Bag, Binds, MonoBinds, InPat, Name, ProtoName, + GlobalNameFun(..), Maybe, UniqSet(..), UniqFM, SrcLoc, Unique, + SplitUniqSupply, Error(..), Pretty(..), PprStyle, + PrettyRep + ) where + +import AbsSyn +import CmdLineOpts ( GlobalSwitch(..) ) +import Digraph ( stronglyConnComp {- MOVED HERE: , isCyclic -} ) +import Errors -- ( unknownSigDeclErr, dupSigDeclErr, methodBindErr ) +import HsPragmas -- ****** NEED TO SEE CONSTRUCTORS ****** +import Maybes ( catMaybes, Maybe(..) ) +import Name ( eqName, cmpName, isUnboundName ) +import ProtoName ( elemByLocalNames, eqByLocalName ) +import Rename4 ( rnPolyType4, rnGenPragmas4 ) +import RenameAuxFuns ( GlobalNameFuns(..) ) +import RenameMonad4 +import RenameExpr4 ( rnMatch4, rnGRHSsAndBinds4, rnPat4 ) +import UniqSet +import Util +\end{code} + +-- ToDo: Put the annotations into the monad, so that they arrive in the proper +-- place and can be used when complaining. + +The code tree received by the function @rnBinds4@ contains definitions +in where-clauses which are all apparently mutually recursive, but which may +not really depend upon each other. For example, in the top level program +\begin{verbatim} +f x = y where a = x + y = x +\end{verbatim} +the definitions of @a@ and @y@ do not depend on each other at all. +Unfortunately, the typechecker cannot always check such definitions. +\footnote{Mycroft, A. 1984. Polymorphic type schemes and recursive +definitions. In Proceedings of the International Symposium on Programming, +Toulouse, pp. 217-39. LNCS 167. Springer Verlag.} +However, the typechecker usually can check definitions in which only the +strongly connected components have been collected into recursive bindings. +This is precisely what the function @rnBinds4@ does. + +ToDo: deal with case where a single monobinds binds the same variable +twice. + +Sets of variable names are represented as sets explicitly, rather than lists. + +\begin{code} +type DefinedVars = UniqSet Name +type FreeVars = UniqSet Name +\end{code} + +i.e., binders. + +The vertag tag is a unique @Int@; the tags only need to be unique +within one @MonoBinds@, so that unique-Int plumbing is done explicitly +(heavy monad machinery not needed). + +\begin{code} +type VertexTag = Int +type Cycle = [VertexTag] +type Edge = (VertexTag, VertexTag) +\end{code} + +%************************************************************************ +%* * +%* naming conventions * +%* * +%************************************************************************ +\subsection[name-conventions]{Name conventions} + +The basic algorithm involves walking over the tree and returning a tuple +containing the new tree plus its free variables. Some functions, such +as those walking polymorphic bindings (Binds) and qualifier lists in +list comprehensions (@Quals@), return the variables bound in local +environments. These are then used to calculate the free variables of the +expression evaluated in these environments. + +Conventions for variable names are as follows: +\begin{itemize} +\item +new code is given a prime to distinguish it from the old. + +\item +a set of variables defined in @Exp@ is written @dvExp@ + +\item +a set of variables free in @Exp@ is written @fvExp@ +\end{itemize} + +%************************************************************************ +%* * +%* analysing polymorphic bindings (Binds, Bind, MonoBinds) * +%* * +%************************************************************************ +\subsubsection[dep-Binds]{Polymorphic bindings} + +Non-recursive expressions are reconstructed without any changes at top +level, although their component expressions may have to be altered. +However, non-recursive expressions are currently not expected as +\Haskell{} programs, and this code should not be executed. + +Monomorphic bindings contain information that is returned in a tuple +(a @FlatMonoBindsInfo@) containing: + +\begin{enumerate} +\item +a unique @Int@ that serves as the ``vertex tag'' for this binding. + +\item +the name of a function or the names in a pattern. These are a set +referred to as @dvLhs@, the defined variables of the left hand side. + +\item +the free variables of the body. These are referred to as @fvBody@. + +\item +the definition's actual code. This is referred to as just @code@. +\end{enumerate} + +The function @nonRecDvFv@ returns two sets of variables. The first is +the set of variables defined in the set of monomorphic bindings, while the +second is the set of free variables in those bindings. + +The set of variables defined in a non-recursive binding is just the +union of all of them, as @union@ removes duplicates. However, the +free variables in each successive set of cumulative bindings is the +union of those in the previous set plus those of the newest binding after +the defined variables of the previous set have been removed. + +@rnMethodBinds4@ deals only with the declarations in class and +instance declarations. It expects only to see @FunMonoBind@s, and +it expects the global environment to contain bindings for the binders +(which are all class operations). + +\begin{code} +rnTopBinds4 :: ProtoNameBinds -> Rn4M RenamedBinds +rnMethodBinds4 :: Name{-class-} -> ProtoNameMonoBinds -> Rn4M RenamedMonoBinds +rnBinds4 :: ProtoNameBinds -> Rn4M (RenamedBinds, FreeVars, [Name]) + +rnTopBinds4 EmptyBinds = returnRn4 EmptyBinds +rnTopBinds4 (SingleBind (RecBind bind)) = rnTopMonoBinds4 bind [] +rnTopBinds4 (BindWith (RecBind bind) sigs) = rnTopMonoBinds4 bind sigs + -- the parser doesn't produce other forms + +-- ******************************************************************** + +rnMethodBinds4 class_name EmptyMonoBinds = returnRn4 EmptyMonoBinds + +rnMethodBinds4 class_name (AndMonoBinds mb1 mb2) + = andRn4 AndMonoBinds (rnMethodBinds4 class_name mb1) + (rnMethodBinds4 class_name mb2) + +rnMethodBinds4 class_name (FunMonoBind pname matches locn) + = pushSrcLocRn4 locn ( + lookupClassOp class_name pname `thenRn4` \ op_name -> + mapAndUnzipRn4 rnMatch4 matches `thenRn4` \ (new_matches, _) -> + returnRn4 (FunMonoBind op_name new_matches locn) + ) + +rnMethodBinds4 class_name (PatMonoBind (VarPatIn pname) grhss_and_binds locn) + = pushSrcLocRn4 locn ( + lookupClassOp class_name pname `thenRn4` \ op_name -> + rnGRHSsAndBinds4 grhss_and_binds `thenRn4` \ (grhss_and_binds', _) -> + returnRn4 (PatMonoBind (VarPatIn op_name) grhss_and_binds' locn) + ) + +-- Can't handle method pattern-bindings which bind multiple methods. +rnMethodBinds4 _ mbind@(PatMonoBind other_pat _ locn) + = failButContinueRn4 EmptyMonoBinds (methodBindErr mbind locn) + +-- ******************************************************************** + +rnBinds4 EmptyBinds = returnRn4 (EmptyBinds,emptyUniqSet,[]) +rnBinds4 (SingleBind (RecBind bind)) = rnNestedMonoBinds4 bind [] +rnBinds4 (BindWith (RecBind bind) sigs) = rnNestedMonoBinds4 bind sigs + -- the parser doesn't produce other forms +\end{code} + +@rnNestedMonoBinds4@ + - collects up the binders for this declaration group, + - checkes that they form a set + - extends the environment to bind them to new local names + - calls @rnMonoBinds4@ to do the real work + +In contrast, @rnTopMonoBinds4@ doesn't extend the environment, because that's +already done in pass3. All it does is call @rnMonoBinds4@ and discards +the free var info. + +\begin{code} +rnTopMonoBinds4 :: ProtoNameMonoBinds -> [ProtoNameSig] -> Rn4M RenamedBinds + +rnTopMonoBinds4 EmptyMonoBinds sigs = returnRn4 EmptyBinds + +rnTopMonoBinds4 mbs sigs + = rnBindSigs4 True{-top-level-} (collectMonoBinders mbs) sigs `thenRn4` \ siglist -> + rnMonoBinds4 mbs siglist `thenRn4` \ (new_binds, fv_set) -> + returnRn4 new_binds + + +rnNestedMonoBinds4 :: ProtoNameMonoBinds -> [ProtoNameSig] + -> Rn4M (RenamedBinds, FreeVars, [Name]) + +rnNestedMonoBinds4 EmptyMonoBinds sigs + = returnRn4 (EmptyBinds, emptyUniqSet, []) + +rnNestedMonoBinds4 mbinds sigs -- Non-empty monobinds + = + -- Extract all the binders in this group, + -- and extend current scope, inventing new names for the new binders + -- This also checks that the names form a set + let + mbinders_w_srclocs = collectMonoBindersAndLocs mbinds + mbinders = map fst mbinders_w_srclocs + in + namesFromProtoNames + "variable" -- in binding group + mbinders_w_srclocs `thenRn4` \ new_mbinders -> + + extendSS2 new_mbinders ( + rnBindSigs4 False{-not top- level-} mbinders sigs `thenRn4` \ siglist -> + rnMonoBinds4 mbinds siglist + ) `thenRn4` \ (new_binds, fv_set) -> + returnRn4 (new_binds, fv_set, new_mbinders) +\end{code} + +@rnMonoBinds4@ is used by *both* top-level and nested bindings. It +assumes that all variables bound in this group are already in scope. +This is done *either* by pass 3 (for the top-level bindings), +*or* by @rnNestedMonoBinds4@ (for the nested ones). + +\begin{code} +rnMonoBinds4 :: ProtoNameMonoBinds + -> [RenamedSig] -- Signatures attached to this group + -> Rn4M (RenamedBinds, FreeVars) + +rnMonoBinds4 mbinds siglist + = + -- Rename the bindings, returning a MonoBindsInfo + -- which is a list of indivisible vertices so far as + -- the SCC analysis is concerned + flattenMonoBinds 0 siglist mbinds `thenRn4` \ (_, mbinds_info) -> + + -- Do the SCC analysis + let vertices = mkVertices mbinds_info + edges = mkEdges vertices mbinds_info + + scc_result = stronglyConnComp (==) edges vertices + + -- Deal with bound and free-var calculation + rhs_free_vars = foldr f emptyUniqSet mbinds_info + + final_binds = reconstructRec scc_result edges mbinds_info + + happy_answer = returnRn4 (final_binds, rhs_free_vars) + in + case (inline_sigs_in_recursive_binds final_binds) of + Nothing -> happy_answer + Just names_n_locns -> + addErrRn4 (inlineInRecursiveBindsErr names_n_locns) `thenRn4_` + {-not so-}happy_answer + where + f :: (a,b, FreeVars, c,d) -> FreeVars -> FreeVars + + f (_, _, fvs_body, _, _) fvs_sofar = fvs_sofar `unionUniqSets` fvs_body + + inline_sigs_in_recursive_binds (BindWith (RecBind _) sigs) + = case [(n, locn) | (InlineSig n _ locn) <- sigs ] of + [] -> Nothing + sigh -> +#if OMIT_DEFORESTER + Just sigh +#else + -- Allow INLINEd recursive functions if they are + -- designated DEFORESTable too. + case [(n, locn) | (DeforestSig n locn) <- sigs ] of + [] -> Just sigh + sigh -> Nothing +#endif + + inline_sigs_in_recursive_binds (ThenBinds b1 b2) + = case (inline_sigs_in_recursive_binds b1) of + Nothing -> inline_sigs_in_recursive_binds b2 + Just x -> Just x -- NB: won't report error(s) in b2 + + inline_sigs_in_recursive_binds anything_else = Nothing +\end{code} + +@flattenMonoBinds@ is ever-so-slightly magical in that it sticks +unique ``vertex tags'' on its output; minor plumbing required. + +\begin{code} +flattenMonoBinds :: Int -- Next free vertex tag + -> [RenamedSig] -- Signatures + -> ProtoNameMonoBinds + -> Rn4M (Int, FlatMonoBindsInfo) + +flattenMonoBinds uniq sigs EmptyMonoBinds = returnRn4 (uniq, []) + +flattenMonoBinds uniq sigs (AndMonoBinds mB1 mB2) + = flattenMonoBinds uniq sigs mB1 `thenRn4` \ (uniq1, flat1) -> + flattenMonoBinds uniq1 sigs mB2 `thenRn4` \ (uniq2, flat2) -> + returnRn4 (uniq2, flat1 ++ flat2) + +flattenMonoBinds uniq sigs (PatMonoBind pat grhss_and_binds locn) + = pushSrcLocRn4 locn ( + rnPat4 pat `thenRn4` \ pat' -> + rnGRHSsAndBinds4 grhss_and_binds `thenRn4` \ (grhss_and_binds', fvs) -> + + -- Find which things are bound in this group + let + names_bound_here = collectPatBinders pat' + + sigs_etc_for_here = foldl (sig_for_here (\ n -> n `is_elem` names_bound_here)) + [] sigs + + sigs_fvs = foldr sig_fv emptyUniqSet sigs_etc_for_here + + is_elem = isIn "flattenMonoBinds" + in + returnRn4 ( + uniq + 1, + [(uniq, + mkUniqSet names_bound_here, + fvs `unionUniqSets` sigs_fvs, + PatMonoBind pat' grhss_and_binds' locn, + sigs_etc_for_here + )] + )) + +flattenMonoBinds uniq sigs (FunMonoBind name matches locn) + = pushSrcLocRn4 locn ( + lookupValue name `thenRn4` \ name' -> + mapAndUnzipRn4 rnMatch4 matches `thenRn4` \ (new_matches, fv_lists) -> + let + fvs = unionManyUniqSets fv_lists + + sigs_for_me = foldl (sig_for_here (\ n -> n `eqName` name')) [] sigs + + sigs_fvs = foldr sig_fv emptyUniqSet sigs_for_me + in + returnRn4 ( + uniq + 1, + [(uniq, + singletonUniqSet name', + fvs `unionUniqSets` sigs_fvs, + FunMonoBind name' new_matches locn, + sigs_for_me + )] + )) +\end{code} + +Grab type-signatures/user-pragmas of interest: +\begin{code} +sig_for_here want_me acc s@(Sig n _ _ _) | want_me n = s:acc +sig_for_here want_me acc s@(InlineSig n _ _) | want_me n = s:acc +sig_for_here want_me acc s@(DeforestSig n _) | want_me n = s:acc +sig_for_here want_me acc s@(SpecSig n _ _ _) | want_me n = s:acc +sig_for_here want_me acc s@(MagicUnfoldingSig n _ _) + | want_me n = s:acc +sig_for_here want_me acc other_wise = acc + +-- If a SPECIALIZE pragma is of the "... = blah" form, +-- then we'd better make sure "blah" is taken into +-- acct in the dependency analysis (or we get an +-- unexpected out-of-scope error)! WDP 95/07 + +sig_fv (SpecSig _ _ (Just blah) _) acc = acc `unionUniqSets` singletonUniqSet blah +sig_fv _ acc = acc +\end{code} + +%************************************************************************ +%* * +\subsection[reconstruct-deps]{Reconstructing dependencies} +%* * +%************************************************************************ + +This @MonoBinds@- and @ClassDecls@-specific code is segregated here, +as the two cases are similar. + +\begin{code} +reconstructRec :: [Cycle] -- Result of SCC analysis; at least one + -> [Edge] -- Original edges + -> FlatMonoBindsInfo + -> RenamedBinds + +reconstructRec cycles edges mbi + = foldr1 ThenBinds (map (reconstructCycle mbi) cycles) + where + reconstructCycle :: FlatMonoBindsInfo -> Cycle -> RenamedBinds + + reconstructCycle mbi2 cycle + = BIND [(binds,sigs) | (vertex, _, _, binds, sigs) <- mbi2, vertex `is_elem` cycle] + _TO_ relevant_binds_and_sigs -> + + BIND (unzip relevant_binds_and_sigs) _TO_ (binds, sig_lists) -> + + BIND (foldr AndMonoBinds EmptyMonoBinds binds) _TO_ this_gp_binds -> + let + this_gp_sigs = foldr1 (++) sig_lists + have_sigs = not (null sig_lists) + -- ToDo: this might not be the right + -- thing to call this predicate; + -- e.g. "have_sigs [[], [], []]" ??????????? + in + mk_binds this_gp_binds this_gp_sigs (isCyclic edges cycle) have_sigs + BEND BEND BEND + where + is_elem = isIn "reconstructRec" + + mk_binds :: RenamedMonoBinds -> [RenamedSig] + -> Bool -> Bool -> RenamedBinds + + mk_binds bs ss True False = SingleBind (RecBind bs) + mk_binds bs ss True True{-have sigs-} = BindWith (RecBind bs) ss + mk_binds bs ss False False = SingleBind (NonRecBind bs) + mk_binds bs ss False True{-have sigs-} = BindWith (NonRecBind bs) ss + + -- moved from Digraph, as this is the only use here + -- (avoid overloading cost). We have to use elem + -- (not FiniteMaps or whatever), because there may be + -- many edges out of one vertex. We give it its own + -- "elem" just for speed. + + isCyclic es [] = panic "isCyclic: empty component" + isCyclic es [v] = (v,v) `elem` es + isCyclic es vs = True + + elem _ [] = False + elem x (y:ys) = x==y || elem x ys +\end{code} + +%************************************************************************ +%* * +%* Manipulating FlatMonoBindInfo * +%* * +%************************************************************************ + +During analysis a @MonoBinds@ is flattened to a @FlatMonoBindsInfo@. +The @RenamedMonoBinds@ is always an empty bind, a pattern binding or +a function binding, and has itself been dependency-analysed and +renamed. + +\begin{code} +type FlatMonoBindsInfo + = [(VertexTag, -- Identifies the vertex + UniqSet Name, -- Set of names defined in this vertex + UniqSet Name, -- Set of names used in this vertex + RenamedMonoBinds, -- Binding for this vertex (always just one binding, either fun or pat) + [RenamedSig]) -- Signatures, if any, for this vertex + ] + +mkVertices :: FlatMonoBindsInfo -> [VertexTag] +mkVertices info = [ vertex | (vertex,_,_,_,_) <- info] + +mkEdges :: [VertexTag] -> FlatMonoBindsInfo -> [Edge] + +mkEdges vertices flat_info + -- An edge (v,v') indicates that v depends on v' + = [ (source_vertex, target_vertex) + | (source_vertex, _, used_names, _, _) <- flat_info, + target_name <- uniqSetToList used_names, + target_vertex <- vertices_defining target_name flat_info + ] + where + -- If each name only has one binding in this group, then + -- vertices_defining will always return the empty list, or a + -- singleton. The case when there is more than one binding (an + -- error) needs more thought. + + vertices_defining name flat_info2 + = [ vertex | (vertex, names_defined, _, _, _) <- flat_info2, + name `elementOfUniqSet` names_defined + ] +\end{code} + + +%************************************************************************ +%* * +\subsubsection[dep-Sigs]{Signatures (and user-pragmas for values)} +%* * +%************************************************************************ + +@rnBindSigs4@ checks for: (a)~more than one sig for one thing; +(b)~signatures given for things not bound here; (c)~with suitably +flaggery, that all top-level things have type signatures. + +\begin{code} +rnBindSigs4 :: Bool -- True <=> top-level binders + -> [ProtoName] -- Binders for this decl group + -> [ProtoNameSig] + -> Rn4M [RenamedSig] -- List of Sig constructors + +rnBindSigs4 is_toplev binder_pnames sigs + = + -- Rename the signatures + -- Will complain about sigs for variables not in this group + mapRn4 rename_sig sigs `thenRn4` \ sigs_maybe -> + let + sigs' = catMaybes sigs_maybe + + -- Discard unbound ones we've already complained about, so we + -- complain about duplicate ones. + + (goodies, dups) = removeDups cmp (filter not_unbound sigs') + in + mapRn4 (addErrRn4 . dupSigDeclErr) dups `thenRn4_` + + getSwitchCheckerRn4 `thenRn4` \ sw_chkr -> + getSrcLocRn4 `thenRn4` \ locn -> + + (if (is_toplev && sw_chkr SigsRequired) then + let + sig_frees = catMaybes (map (sig_free sigs) binder_pnames) + in + mapRn4 (addErrRn4 . missingSigErr locn) sig_frees + else + returnRn4 [] + ) `thenRn4_` + + returnRn4 sigs' -- bad ones and all: + -- we need bindings of *some* sort for every name + where + rename_sig (Sig v ty pragma src_loc) + = pushSrcLocRn4 src_loc ( + + if not (v `elemByLocalNames` binder_pnames) then + addErrRn4 (unknownSigDeclErr "type signature" v src_loc) `thenRn4_` + returnRn4 Nothing + else + lookupValue v `thenRn4` \ new_v -> + rnPolyType4 False True nullTyVarNamesEnv ty `thenRn4` \ new_ty -> + recoverQuietlyRn4 NoGenPragmas ( + rnGenPragmas4 pragma + ) `thenRn4` \ new_pragma -> + returnRn4 (Just (Sig new_v new_ty new_pragma src_loc)) + ) + + -- and now, the various flavours of value-modifying user-pragmas: + + rename_sig (SpecSig v ty using src_loc) + = pushSrcLocRn4 src_loc ( + + if not (v `elemByLocalNames` binder_pnames) then + addErrRn4 (unknownSigDeclErr "SPECIALIZE pragma" v src_loc) `thenRn4_` + returnRn4 Nothing + else + lookupValue v `thenRn4` \ new_v -> + rnPolyType4 False True nullTyVarNamesEnv ty `thenRn4` \ new_ty -> + rn_using using `thenRn4` \ new_using -> + returnRn4 (Just (SpecSig new_v new_ty new_using src_loc)) + ) + where + rn_using Nothing = returnRn4 Nothing + rn_using (Just x) = lookupValue x `thenRn4` \ new_x -> + returnRn4 (Just new_x) + + rename_sig (InlineSig v howto src_loc) + = pushSrcLocRn4 src_loc ( + + if not (v `elemByLocalNames` binder_pnames) then + addErrRn4 (unknownSigDeclErr "INLINE pragma" v src_loc) `thenRn4_` + returnRn4 Nothing + else + lookupValue v `thenRn4` \ new_v -> + returnRn4 (Just (InlineSig new_v howto src_loc)) + ) + + rename_sig (DeforestSig v src_loc) + = pushSrcLocRn4 src_loc ( + + if not (v `elemByLocalNames` binder_pnames) then + addErrRn4 (unknownSigDeclErr "DEFOREST pragma" v src_loc) `thenRn4_` + returnRn4 Nothing + else + lookupValue v `thenRn4` \ new_v -> + returnRn4 (Just (DeforestSig new_v src_loc)) + ) + + rename_sig (MagicUnfoldingSig v str src_loc) + = pushSrcLocRn4 src_loc ( + + if not (v `elemByLocalNames` binder_pnames) then + addErrRn4 (unknownSigDeclErr "MAGIC_UNFOLDING pragma" v src_loc) `thenRn4_` + returnRn4 Nothing + else + lookupValue v `thenRn4` \ new_v -> + returnRn4 (Just (MagicUnfoldingSig new_v str src_loc)) + ) + + not_unbound :: RenamedSig -> Bool + + not_unbound (Sig n _ _ _) = not (isUnboundName n) + not_unbound (SpecSig n _ _ _) = not (isUnboundName n) + not_unbound (InlineSig n _ _) = not (isUnboundName n) + not_unbound (DeforestSig n _) = not (isUnboundName n) + not_unbound (MagicUnfoldingSig n _ _) = not (isUnboundName n) + + ------------------------------------- + sig_free :: [ProtoNameSig] -> ProtoName -> Maybe ProtoName + -- Return "Just x" if "x" has no type signature in + -- sigs. Nothing, otherwise. + + sig_free [] ny = Just ny + sig_free (Sig nx _ _ _ : rest) ny + = if (nx `eqByLocalName` ny) then Nothing else sig_free rest ny + sig_free (_ : rest) ny = sig_free rest ny + + ------------------------------------- + cmp :: RenamedSig -> RenamedSig -> TAG_ + + cmp (Sig n1 _ _ _) (Sig n2 _ _ _) = n1 `cmpName` n2 + cmp (InlineSig n1 _ _) (InlineSig n2 _ _) = n1 `cmpName` n2 + cmp (MagicUnfoldingSig n1 _ _) (MagicUnfoldingSig n2 _ _) = n1 `cmpName` n2 + cmp (SpecSig n1 ty1 _ _) (SpecSig n2 ty2 _ _) + = -- may have many specialisations for one value; + -- but not ones that are exactly the same... + case (n1 `cmpName` n2) of + EQ_ -> cmpPolyType cmpName ty1 ty2 + other -> other + + cmp other_1 other_2 -- tags *must* be different + = let tag1 = tag other_1 + tag2 = tag other_2 + in + if tag1 _LT_ tag2 then LT_ else GT_ + + tag (Sig n1 _ _ _) = (ILIT(1) :: FAST_INT) + tag (SpecSig n1 _ _ _) = ILIT(2) + tag (InlineSig n1 _ _) = ILIT(3) + tag (MagicUnfoldingSig n1 _ _) = ILIT(4) + tag (DeforestSig n1 _) = ILIT(5) + tag _ = case (panic "tag(RenameBinds4)") of { s -> tag s } -- BUG avoidance +\end{code} |