[project @ 2002-07-29 12:22:37 by simonpj]
[ghc-hetmet.git] / ghc / compiler / rename / RnEnv.lhs
index c2c6762..3e8dd5b 100644 (file)
@@ -8,13 +8,14 @@ module RnEnv where            -- Export everything
 
 #include "HsVersions.h"
 
 
 #include "HsVersions.h"
 
-import {-# SOURCE #-} RnHiFiles
+import {-# SOURCE #-} RnHiFiles( loadInterface )
 
 import FlattenInfo      ( namesNeededForFlattening )
 import HsSyn
 
 import FlattenInfo      ( namesNeededForFlattening )
 import HsSyn
-import RdrHsSyn                ( RdrNameIE, RdrNameHsType, extractHsTyRdrTyVars )
+import RnHsSyn         ( RenamedFixitySig )
+import RdrHsSyn                ( RdrNameIE, RdrNameHsType, RdrNameFixitySig, extractHsTyRdrTyVars )
 import RdrName         ( RdrName, rdrNameModule, rdrNameOcc, isQual, isUnqual, isOrig,
 import RdrName         ( RdrName, rdrNameModule, rdrNameOcc, isQual, isUnqual, isOrig,
-                         mkRdrUnqual, mkRdrQual, 
+                         mkRdrUnqual, mkRdrQual, setRdrNameOcc,
                          lookupRdrEnv, foldRdrEnv, rdrEnvToList, elemRdrEnv,
                          unqualifyRdrName
                        )
                          lookupRdrEnv, foldRdrEnv, rdrEnvToList, elemRdrEnv,
                          unqualifyRdrName
                        )
@@ -24,24 +25,25 @@ import HscTypes             ( Provenance(..), pprNameProvenance, hasBetterProv,
                          AvailInfo, Avails, GenAvailInfo(..), NameSupply(..), 
                          ModIface(..), GhciMode(..),
                          Deprecations(..), lookupDeprec,
                          AvailInfo, Avails, GenAvailInfo(..), NameSupply(..), 
                          ModIface(..), GhciMode(..),
                          Deprecations(..), lookupDeprec,
-                         extendLocalRdrEnv
+                         extendLocalRdrEnv, lookupFixity
                        )
 import RnMonad
 import Name            ( Name, 
                          getSrcLoc, nameIsLocalOrFrom,
                          mkInternalName, mkExternalName,
                          mkIPName, nameOccName, nameModule_maybe,
                        )
 import RnMonad
 import Name            ( Name, 
                          getSrcLoc, nameIsLocalOrFrom,
                          mkInternalName, mkExternalName,
                          mkIPName, nameOccName, nameModule_maybe,
-                         setNameModuleAndLoc
+                         setNameModuleAndLoc, nameModule
                        )
 import NameEnv
 import NameSet
                        )
 import NameEnv
 import NameSet
-import OccName         ( OccName, occNameUserString, occNameFlavour )
+import OccName         ( OccName, occNameUserString, occNameFlavour, 
+                         isDataSymOcc, setOccNameSpace, tcName )
 import Module          ( ModuleName, moduleName, mkVanillaModule, 
                          mkSysModuleNameFS, moduleNameFS, WhereFrom(..) )
 import PrelNames       ( mkUnboundName, 
                          derivingOccurrences,
                          mAIN_Name, main_RDR_Unqual,
 import Module          ( ModuleName, moduleName, mkVanillaModule, 
                          mkSysModuleNameFS, moduleNameFS, WhereFrom(..) )
 import PrelNames       ( mkUnboundName, 
                          derivingOccurrences,
                          mAIN_Name, main_RDR_Unqual,
-                         runMainName, intTyConName, 
+                         runIOName, intTyConName, 
                          boolTyConName, funTyConName,
                          unpackCStringName, unpackCStringFoldrName, unpackCStringUtf8Name,
                          eqStringName, printName, 
                          boolTyConName, funTyConName,
                          unpackCStringName, unpackCStringFoldrName, unpackCStringUtf8Name,
                          eqStringName, printName, 
@@ -54,10 +56,11 @@ import SrcLoc               ( SrcLoc, noSrcLoc )
 import Outputable
 import ListSetOps      ( removeDups, equivClasses )
 import Util            ( sortLt )
 import Outputable
 import ListSetOps      ( removeDups, equivClasses )
 import Util            ( sortLt )
-import BasicTypes      ( mapIPName )
+import BasicTypes      ( mapIPName, defaultFixity )
 import List            ( nub )
 import UniqFM          ( lookupWithDefaultUFM )
 import Maybe           ( mapMaybe )
 import List            ( nub )
 import UniqFM          ( lookupWithDefaultUFM )
 import Maybe           ( mapMaybe )
+import Maybes          ( orElse, catMaybes )
 import CmdLineOpts
 import FastString      ( FastString )
 \end{code}
 import CmdLineOpts
 import FastString      ( FastString )
 \end{code}
@@ -211,7 +214,16 @@ lookupTopBndrRn rdr_name
        -- The parser reads the special syntax and returns an Orig RdrName
        -- But the global_env contains only Qual RdrNames, so we won't
        -- find it there; instead just get the name via the Orig route
        -- The parser reads the special syntax and returns an Orig RdrName
        -- But the global_env contains only Qual RdrNames, so we won't
        -- find it there; instead just get the name via the Orig route
-  = lookupOrigName rdr_name
+       --
+  =    -- This is a binding site for the name, so check first that it 
+       -- the current module is the correct one; otherwise GHC can get
+       -- very confused indeed.  This test rejects code like
+       --      data T = (,) Int Int
+       -- unless we are in GHC.Tup
+    getModuleRn                                `thenRn` \ mod -> 
+    checkRn (moduleName mod == rdrNameModule rdr_name)
+           (badOrigBinding rdr_name)   `thenRn_`
+    lookupOrigName rdr_name
 
   | otherwise
   = getModeRn  `thenRn` \ mode ->
 
   | otherwise
   = getModeRn  `thenRn` \ mode ->
@@ -231,9 +243,9 @@ lookupTopBndrRn rdr_name
        Just name -> returnRn name
        Nothing   -> failWithRn (mkUnboundName rdr_name)
                                (unknownNameErr rdr_name)
        Just name -> returnRn name
        Nothing   -> failWithRn (mkUnboundName rdr_name)
                                (unknownNameErr rdr_name)
-  where
-    lookup_local mod global_env rdr_name
-      = case lookupRdrEnv global_env rdr_name of
+
+lookup_local mod global_env rdr_name
+  = case lookupRdrEnv global_env rdr_name of
          Nothing   -> Nothing
          Just gres -> case [n | GRE n _ _ <- gres, nameIsLocalOrFrom mod n] of
                         []     -> Nothing
          Nothing   -> Nothing
          Just gres -> case [n | GRE n _ _ <- gres, nameIsLocalOrFrom mod n] of
                         []     -> Nothing
@@ -411,6 +423,104 @@ lookupSysBinder rdr_name
 
 %*********************************************************
 %*                                                     *
 
 %*********************************************************
 %*                                                     *
+\subsection{Looking up fixities}
+%*                                                     *
+%*********************************************************
+
+lookupFixity is a bit strange.  
+
+* Nested local fixity decls are put in the local fixity env, which we
+  find with getFixtyEnv
+
+* Imported fixities are found in the HIT or PIT
+
+* Top-level fixity decls in this module may be for Names that are
+    either  Global        (constructors, class operations)
+    or             Local/Exported (everything else)
+  (See notes with RnNames.getLocalDeclBinders for why we have this split.)
+  We put them all in the local fixity environment
+
+\begin{code}
+lookupFixityRn :: Name -> RnMS Fixity
+lookupFixityRn name
+  = getModuleRn                                `thenRn` \ this_mod ->
+    if nameIsLocalOrFrom this_mod name
+    then       -- It's defined in this module
+       getFixityEnv                    `thenRn` \ local_fix_env ->
+       returnRn (lookupLocalFixity local_fix_env name)
+
+    else       -- It's imported
+      -- For imported names, we have to get their fixities by doing a
+      -- loadHomeInterface, and consulting the Ifaces that comes back
+      -- from that, because the interface file for the Name might not
+      -- have been loaded yet.  Why not?  Suppose you import module A,
+      -- which exports a function 'f', thus;
+      --        module CurrentModule where
+      --         import A( f )
+      --       module A( f ) where
+      --         import B( f )
+      -- Then B isn't loaded right away (after all, it's possible that
+      -- nothing from B will be used).  When we come across a use of
+      -- 'f', we need to know its fixity, and it's then, and only
+      -- then, that we load B.hi.  That is what's happening here.
+        loadInterface doc name_mod ImportBySystem      `thenRn` \ iface ->
+       returnRn (lookupFixity (mi_fixities iface) name)
+  where
+    doc      = ptext SLIT("Checking fixity for") <+> ppr name
+    name_mod = moduleName (nameModule name)
+
+--------------------------------
+lookupLocalFixity :: LocalFixityEnv -> Name -> Fixity
+lookupLocalFixity env name
+  = case lookupNameEnv env name of 
+       Just (FixitySig _ fix _) -> fix
+       Nothing                  -> defaultFixity
+
+extendNestedFixityEnv :: [(Name, RenamedFixitySig)] -> RnMS a -> RnMS a
+-- Used for nested fixity decls
+-- No need to worry about type constructors here,
+-- Should check for duplicates but we don't
+extendNestedFixityEnv fixes enclosed_scope
+  = getFixityEnv       `thenRn` \ fix_env ->
+    let
+       new_fix_env = extendNameEnvList fix_env fixes
+    in
+    setFixityEnv new_fix_env enclosed_scope
+
+mkTopFixityEnv :: GlobalRdrEnv -> [RdrNameFixitySig] -> RnMG LocalFixityEnv
+mkTopFixityEnv gbl_env fix_sigs 
+  = getModuleRn                                `thenRn` \ mod -> 
+    let
+               -- GHC extension: look up both the tycon and data con 
+               -- for con-like things
+               -- If neither are in scope, report an error; otherwise
+               -- add both to the fixity env
+       go fix_env (FixitySig rdr_name fixity loc)
+         = case catMaybes (map (lookup_local mod gbl_env) rdr_names) of
+                 [] -> pushSrcLocRn loc                        $
+                       addErrRn (unknownNameErr rdr_name)      `thenRn_`
+                       returnRn fix_env
+                 ns -> foldlRn add fix_env ns
+
+         where
+           add fix_env name 
+             = case lookupNameEnv fix_env name of
+                 Just (FixitySig _ _ loc') -> addErrRn (dupFixityDecl rdr_name loc loc')       `thenRn_`
+                                              returnRn fix_env
+                 Nothing -> returnRn (extendNameEnv fix_env name (FixitySig name fixity loc))
+           
+           rdr_names | isDataSymOcc occ = [rdr_name, rdr_name_tc]
+                     | otherwise            = [rdr_name]
+
+           occ         = rdrNameOcc rdr_name
+           rdr_name_tc = setRdrNameOcc rdr_name (setOccNameSpace occ tcName)
+    in
+    foldlRn go emptyLocalFixityEnv fix_sigs
+\end{code}
+
+
+%*********************************************************
+%*                                                     *
 \subsection{Implicit free vars and sugar names}
 %*                                                     *
 %*********************************************************
 \subsection{Implicit free vars and sugar names}
 %*                                                     *
 %*********************************************************
@@ -457,7 +567,7 @@ ubiquitousNames
 checkMain ghci_mode mod_name gbl_env
        -- LOOKUP main IF WE'RE IN MODULE Main
        -- The main point of this is to drag in the declaration for 'main',
 checkMain ghci_mode mod_name gbl_env
        -- LOOKUP main IF WE'RE IN MODULE Main
        -- The main point of this is to drag in the declaration for 'main',
-       -- its in another module, and for the Prelude function 'runMain',
+       -- its in another module, and for the Prelude function 'runIO',
        -- so that the type checker will find them
        --
        -- We have to return the main_name separately, because it's a
        -- so that the type checker will find them
        --
        -- We have to return the main_name separately, because it's a
@@ -472,7 +582,7 @@ checkMain ghci_mode mod_name gbl_env
 
   | otherwise
   = lookupSrcName gbl_env main_RDR_Unqual      `thenRn` \ main_name ->
 
   | otherwise
   = lookupSrcName gbl_env main_RDR_Unqual      `thenRn` \ main_name ->
-    returnRn (Just main_name, unitFV main_name, unitFV runMainName)
+    returnRn (Just main_name, unitFV main_name, unitFV runIOName)
 
   where
     complain_no_main | ghci_mode == Interactive = addWarnRn noMainMsg
 
   where
     complain_no_main | ghci_mode == Interactive = addWarnRn noMainMsg
@@ -499,28 +609,38 @@ At the moment this just happens for
   * fromInteger, fromRational on literals (in expressions and patterns)
   * negate (in expressions)
   * minus  (arising from n+k patterns)
   * fromInteger, fromRational on literals (in expressions and patterns)
   * negate (in expressions)
   * minus  (arising from n+k patterns)
+  * "do" notation
 
 We store the relevant Name in the HsSyn tree, in 
   * HsIntegral/HsFractional    
   * NegApp
   * NPlusKPatIn
 
 We store the relevant Name in the HsSyn tree, in 
   * HsIntegral/HsFractional    
   * NegApp
   * NPlusKPatIn
+  * HsDo
 respectively.  Initially, we just store the "standard" name (PrelNames.fromIntegralName,
 fromRationalName etc), but the renamer changes this to the appropriate user
 name if Opt_NoImplicitPrelude is on.  That is what lookupSyntaxName does.
 
 respectively.  Initially, we just store the "standard" name (PrelNames.fromIntegralName,
 fromRationalName etc), but the renamer changes this to the appropriate user
 name if Opt_NoImplicitPrelude is on.  That is what lookupSyntaxName does.
 
+We treat the orignal (standard) names as free-vars too, because the type checker
+checks the type of the user thing against the type of the standard thing.
+
 \begin{code}
 \begin{code}
-lookupSyntaxName :: Name       -- The standard name
-                -> RnMS Name   -- Possibly a non-standard name
+lookupSyntaxName :: Name                       -- The standard name
+                -> RnMS (Name, FreeVars)       -- Possibly a non-standard name
 lookupSyntaxName std_name
 lookupSyntaxName std_name
-  = doptRn Opt_NoImplicitPrelude       `thenRn` \ no_prelude -> 
+  = getModeRn                          `thenRn` \ mode ->
+    case mode of {
+       InterfaceMode -> returnRn (std_name, unitFV std_name) ;
+                               -- Happens for 'derived' code
+                               -- where we don't want to rebind
+       other ->
+
+    doptRn Opt_NoImplicitPrelude       `thenRn` \ no_prelude -> 
     if not no_prelude then
     if not no_prelude then
-       returnRn std_name       -- Normal case
+       returnRn (std_name, unitFV std_name)    -- Normal case
     else
     else
-    let
-       rdr_name = mkRdrUnqual (nameOccName std_name)
        -- Get the similarly named thing from the local environment
        -- Get the similarly named thing from the local environment
-    in
-    lookupOccRn rdr_name
+    lookupOccRn (mkRdrUnqual (nameOccName std_name)) `thenRn` \ usr_name ->
+    returnRn (usr_name, mkFVs [usr_name, std_name]) }
 \end{code}
 
 
 \end{code}
 
 
@@ -1050,6 +1170,10 @@ unknownNameErr name
   where
     flavour = occNameFlavour (rdrNameOcc name)
 
   where
     flavour = occNameFlavour (rdrNameOcc name)
 
+badOrigBinding name
+  = ptext SLIT("Illegal binding of built-in syntax:") <+> ppr (rdrNameOcc name)
+       -- The rdrNameOcc is because we don't want to print Prelude.(,)
+
 qualNameErr descriptor (name,loc)
   = pushSrcLocRn loc $
     addErrRn (vcat [ ptext SLIT("Invalid use of qualified name") <+> quotes (ppr name),
 qualNameErr descriptor (name,loc)
   = pushSrcLocRn loc $
     addErrRn (vcat [ ptext SLIT("Invalid use of qualified name") <+> quotes (ppr name),
@@ -1067,5 +1191,10 @@ warnDeprec name txt
     addWarnRn (sep [ text (occNameFlavour (nameOccName name)) <+> 
                     quotes (ppr name) <+> text "is deprecated:", 
                     nest 4 (ppr txt) ])
     addWarnRn (sep [ text (occNameFlavour (nameOccName name)) <+> 
                     quotes (ppr name) <+> text "is deprecated:", 
                     nest 4 (ppr txt) ])
+
+dupFixityDecl rdr_name loc1 loc2
+  = vcat [ptext SLIT("Multiple fixity declarations for") <+> quotes (ppr rdr_name),
+         ptext SLIT("at ") <+> ppr loc1,
+         ptext SLIT("and") <+> ppr loc2]
 \end{code}
 
 \end{code}