[project @ 2001-01-25 17:47:12 by simonpj]
authorsimonpj <unknown>
Thu, 25 Jan 2001 17:47:14 +0000 (17:47 +0000)
committersimonpj <unknown>
Thu, 25 Jan 2001 17:47:14 +0000 (17:47 +0000)
A big improvement to the way command-line expressions are typechecked.
Now we don't wrap in "print" and hope for the best (the wrong "print"
might be in scope).  Instead we work on the renamed epxression and
do the Right Thing by using the correct "print".

Also do generalisation, so that we get the right type back from
the :t command.

WARNING: it's possible that these files overlap with my fortcoming
Big Commit of typechecker stuff, so you may need to hang on for
a few mins.

ghc/compiler/compMan/CompManager.lhs
ghc/compiler/main/HscMain.lhs
ghc/compiler/prelude/PrelNames.lhs
ghc/compiler/rename/Rename.lhs
ghc/compiler/typecheck/TcModule.lhs

index 43c79e4..d7b2346 100644 (file)
@@ -68,13 +68,13 @@ cmInit gmode
 #ifdef GHCI
 cmGetExpr :: CmState
          -> DynFlags
+         -> Bool       -- True <=> wrap in 'print' to get an IO-typed result
           -> Module
           -> String
-          -> Bool
           -> IO (CmState, Maybe (HValue, PrintUnqualified, Type))
-cmGetExpr cmstate dflags mod expr wrap_print
+cmGetExpr cmstate dflags wrap_io mod expr
    = do (new_pcs, maybe_stuff) <- 
-          hscExpr dflags hst hit pcs mod expr wrap_print
+          hscExpr dflags wrap_io hst hit pcs mod expr
         case maybe_stuff of
           Nothing     -> return (cmstate{ pcs=new_pcs }, Nothing)
           Just (bcos, print_unqual, ty) -> do
index 21da9dc..a49bf45 100644 (file)
@@ -397,16 +397,16 @@ myCoreToStg dflags this_mod tidy_binds env_tc
 #ifdef GHCI
 hscExpr
   :: DynFlags
+  -> Bool                      -- True <=> wrap in 'print' to get a result of IO type
   -> HomeSymbolTable   
   -> HomeIfaceTable
   -> PersistentCompilerState    -- IN: persistent compiler state
   -> Module                    -- Context for compiling
   -> String                    -- The expression
-  -> Bool                      -- Should we wrap print if not IO-typed?
   -> IO ( PersistentCompilerState, 
          Maybe (UnlinkedBCOExpr, PrintUnqualified, Type) )
 
-hscExpr dflags hst hit pcs0 this_module expr wrap_print
+hscExpr dflags wrap_io hst hit pcs0 this_module expr
    = do {
        maybe_parsed <- hscParseExpr dflags expr;
        case maybe_parsed of
@@ -422,28 +422,11 @@ hscExpr dflags hst hit pcs0 this_module expr wrap_print
 
                -- Typecheck it
        maybe_tc_return
-          <- typecheckExpr dflags pcs1 hst print_unqual this_module rn_expr;
+          <- typecheckExpr dflags wrap_io pcs1 hst print_unqual this_module rn_expr;
        case maybe_tc_return of {
                Nothing -> return ({-WAS:pcs1-} pcs0, Nothing);
                Just (pcs2, tc_expr, ty) -> do
 
-       -- if it isn't an IO-typed expression, 
-       -- wrap "print" around it & recompile...
-       let { is_IO_type = case splitTyConApp_maybe ty of {
-                           Just (tycon, _) -> getUnique tycon == ioTyConKey;
-                           Nothing -> False }
-            };
-
-        if (wrap_print && not is_IO_type)
-               then do (new_pcs, maybe_stuff)
-                         <- hscExpr dflags hst hit pcs2 this_module
-                               ("PrelIO.print (" ++ expr ++ ")") False
-                       case maybe_stuff of
-                          Nothing -> return (new_pcs, maybe_stuff)
-                          Just (bcos, _, _) ->
-                             return (new_pcs, Just (bcos, print_unqual, ty))
-               else do
-
                -- Desugar it
        ds_expr <- deSugarExpr dflags pcs2 hst this_module
                        print_unqual tc_expr;
index 4015b8d..91530c6 100644 (file)
@@ -160,7 +160,8 @@ knownKeyNames
        timesIntegerName,
        eqStringName,
        assertName,
-       runSTRepName
+       runSTRepName,
+       printName
     ]
 \end{code}
 
@@ -184,6 +185,7 @@ pREL_TUP_Name     = mkModuleName "PrelTup"
 pREL_PACK_Name    = mkModuleName "PrelPack"
 pREL_CONC_Name    = mkModuleName "PrelConc"
 pREL_IO_BASE_Name = mkModuleName "PrelIOBase"
+pREL_IO_Name     = mkModuleName "PrelIO"
 pREL_ST_Name     = mkModuleName "PrelST"
 pREL_ARR_Name     = mkModuleName "PrelArr"
 pREL_BYTEARR_Name = mkModuleName "PrelByteArr"
@@ -424,6 +426,9 @@ ioDataConName     = dataQual pREL_IO_BASE_Name SLIT("IO") ioDataConKey
 bindIOName       = varQual  pREL_IO_BASE_Name SLIT("bindIO") bindIOIdKey
 returnIOName     = varQual  pREL_IO_BASE_Name SLIT("returnIO") returnIOIdKey
 
+-- IO things
+printName        = varQual pREL_IO_Name SLIT("print") printIdKey
+
 -- Int, Word, and Addr things
 int8TyConName     = tcQual pREL_INT_Name  SLIT("Int8") int8TyConKey
 int16TyConName    = tcQual pREL_INT_Name  SLIT("Int16") int16TyConKey
@@ -791,6 +796,7 @@ newStablePtrIdKey         = mkPreludeMiscIdUnique 39
 getTagIdKey                  = mkPreludeMiscIdUnique 40
 plusIntegerIdKey             = mkPreludeMiscIdUnique 41
 timesIntegerIdKey            = mkPreludeMiscIdUnique 42
+printIdKey                   = mkPreludeMiscIdUnique 43
 \end{code}
 
 Certain class operations from Prelude classes.  They get their own
index af9ccc6..87eb777 100644 (file)
@@ -44,14 +44,14 @@ import Name         ( Name, NamedThing(..), getSrcLoc,
                          nameIsLocalOrFrom, nameOccName, nameModule,
                        )
 import Name            ( mkNameEnv, nameEnvElts, extendNameEnv )
-import RdrName         ( elemRdrEnv, foldRdrEnv, isQual )
+import RdrName         ( foldRdrEnv, isQual )
 import OccName         ( occNameFlavour )
 import NameSet
 import TysWiredIn      ( unitTyCon, intTyCon, boolTyCon )
 import PrelNames       ( mAIN_Name, pREL_MAIN_Name, pRELUDE_Name,
-                         ioTyCon_RDR, main_RDR_Unqual,
-                         unpackCString_RDR, unpackCStringFoldr_RDR, unpackCStringUtf8_RDR,
-                         eqString_RDR
+                         ioTyConName, printName,
+                         unpackCStringName, unpackCStringFoldrName, unpackCStringUtf8Name,
+                         eqStringName
                        )
 import PrelInfo                ( derivingOccurrences )
 import Type            ( funTyCon )
@@ -61,7 +61,7 @@ import Bag            ( bagToList )
 import FiniteMap       ( FiniteMap, fmToList, emptyFM, lookupFM, 
                          addToFM_C, elemFM, addToFM
                        )
-import UniqFM          ( lookupUFM )
+import UniqFM          ( lookupWithDefaultUFM )
 import Maybes          ( maybeToBool, catMaybes )
 import Outputable
 import IO              ( openFile, IOMode(..) )
@@ -136,14 +136,18 @@ renameExpr dflags hit hst pcs this_module expr
                returnRn Nothing
          else
 
-         lookupOrigNames implicit_occs                 `thenRn` \ implicit_names ->
-         slurpImpDecls (fvs `plusFV` implicit_names)   `thenRn` \ decls ->
+         let
+           implicit_fvs = fvs `plusFV` string_names
+                              `plusFV` default_tycon_names
+                              `plusFV` unitFV printName
+                                       -- print :: a -> IO () may be needed later
+         in
+         slurpImpDecls (fvs `plusFV` implicit_fvs)     `thenRn` \ decls ->
 
          doDump e decls  `thenRn_`
          returnRn (Just (print_unqual, (e, decls)))
        }}
   where
-     implicit_occs = string_occs
      doc = text "context for compiling expression"
 
      doDump :: RenamedHsExpr -> [RenamedHsDecl] -> RnMG (Either IOError ())
@@ -222,9 +226,6 @@ rename this_module contents@(HsModule _ _ exports imports local_decls mod_deprec
        -- RENAME THE SOURCE
     rnSourceDecls gbl_env local_fixity_env local_decls `thenRn` \ (rn_local_decls, source_fvs) ->
 
-       -- CHECK THAT main IS DEFINED, IF REQUIRED
-    checkMain this_module local_gbl_env                `thenRn_`
-
        -- EXIT IF ERRORS FOUND
        -- We exit here if there are any errors in the source, *before*
        -- we attempt to slurp the decls from the interfaces, otherwise
@@ -294,57 +295,40 @@ rename this_module contents@(HsModule _ _ exports imports local_decls mod_deprec
     mod_name = moduleName this_module
 \end{code}
 
-Checking that main is defined
-
-\begin{code}
-checkMain :: Module -> GlobalRdrEnv -> RnMG ()
-checkMain this_mod local_env
-  | moduleName this_mod == mAIN_Name 
-  = checkRn (main_RDR_Unqual `elemRdrEnv` local_env) noMainErr
-  | otherwise
-  = returnRn ()
-\end{code}
-
 @implicitFVs@ forces the renamer to slurp in some things which aren't
 mentioned explicitly, but which might be needed by the type checker.
 
 \begin{code}
 implicitFVs mod_name decls
-  = lookupOrigNames implicit_occs                      `thenRn` \ implicit_names ->
-    returnRn (mkNameSet (map getName default_tycons)   `plusFV`
-             implicit_names)
+  = lookupOrigNames deriv_occs         `thenRn` \ deriving_names ->
+    returnRn (default_tycon_names  `plusFV`
+             string_names         `plusFV`
+             deriving_names       `plusFV`
+             implicit_main)
   where
-       -- Add occurrences for Int, and (), because they
-       -- are the types to which ambigious type variables may be defaulted by
-       -- the type checker; so they won't always appear explicitly.
-       -- [The () one is a GHC extension for defaulting CCall results.]
-       -- ALSO: funTyCon, since it occurs implicitly everywhere!
-       --       (we don't want to be bothered with making funTyCon a
-       --        free var at every function application!)
-       -- Double is dealt with separately in getGates
-    default_tycons = [unitTyCon, funTyCon, boolTyCon, intTyCon]
 
        -- Add occurrences for IO or PrimIO
     implicit_main |  mod_name == mAIN_Name
-                 || mod_name == pREL_MAIN_Name = [ioTyCon_RDR]
-                 |  otherwise                  = []
+                 || mod_name == pREL_MAIN_Name = unitFV ioTyConName
+                 |  otherwise                  = emptyFVs
 
-       -- Now add extra "occurrences" for things that
-       -- the deriving mechanism, or defaulting, will later need in order to
-       -- generate code
-    implicit_occs = string_occs ++ foldr ((++) . get) implicit_main decls
-
-
-    get (TyClD (TyData {tcdDerivs = Just deriv_classes})) = concat (map get_deriv deriv_classes)
-    get other                                            = []
-
-    get_deriv cls = case lookupUFM derivingOccurrences cls of
-                       Nothing   -> []
-                       Just occs -> occs
+    deriv_occs = [occ | TyClD (TyData {tcdDerivs = Just deriv_classes}) <- decls,
+                       cls <- deriv_classes,
+                       occ <- lookupWithDefaultUFM derivingOccurrences [] cls ]
 
 -- Virtually every program has error messages in it somewhere
-string_occs = [unpackCString_RDR, unpackCStringFoldr_RDR, 
-              unpackCStringUtf8_RDR, eqString_RDR]
+string_names = mkFVs [unpackCStringName, unpackCStringFoldrName, 
+                     unpackCStringUtf8Name, eqStringName]
+
+-- Add occurrences for Int, and (), because they
+-- are the types to which ambigious type variables may be defaulted by
+-- the type checker; so they won't always appear explicitly.
+-- [The () one is a GHC extension for defaulting CCall results.]
+-- ALSO: funTyCon, since it occurs implicitly everywhere!
+--      (we don't want to be bothered with making funTyCon a
+--       free var at every function application!)
+-- Double is dealt with separately in getGates
+default_tycon_names = mkFVs (map getName [unitTyCon, funTyCon, boolTyCon, intTyCon])
 \end{code}
 
 \begin{code}
@@ -611,16 +595,15 @@ closeIfaceDecls dflags hit hst pcs
        local_names    = foldl add emptyNameSet tycl_decls
        add names decl = addListToNameSet names (map fst (tyClDeclSysNames decl ++ tyClDeclNames decl))
     in
-       -- Record that we have now got declarations for local_names
+
     recordLocalSlurps local_names      `thenRn_`
 
        -- Do the transitive closure
-    lookupOrigNames implicit_occs      `thenRn` \ implicit_names ->
-    closeDecls decls (needed `plusFV` implicit_names) `thenRn` \closed_decls ->
+    closeDecls decls (needed `plusFV` implicit_fvs) `thenRn` \closed_decls ->
     rnDump [] closed_decls `thenRn_`
     returnRn closed_decls
   where
-    implicit_occs = string_occs        -- Data type decls with record selectors,
+    implicit_fvs = string_names        -- Data type decls with record selectors,
                                -- which may appear in the decls, need unpackCString
                                -- and friends. It's easier to just grab them right now.
 \end{code}
@@ -920,10 +903,6 @@ dupFixityDecl rdr_name loc1 loc2
 badDeprec d
   = sep [ptext SLIT("Illegal deprecation when whole module is deprecated"),
         nest 4 (ppr d)]
-
-noMainErr
-  = hsep [ptext SLIT("Module"), quotes (ppr mAIN_Name), 
-         ptext SLIT("must include a definition for"), quotes (ptext SLIT("main"))]
 \end{code}
 
 
index 5c0262d..2789fa8 100644 (file)
@@ -11,10 +11,11 @@ module TcModule (
 #include "HsVersions.h"
 
 import CmdLineOpts     ( DynFlag(..), DynFlags, opt_PprStyle_Debug )
-import HsSyn           ( HsBinds(..), MonoBinds(..), HsDecl(..), 
+import HsSyn           ( HsBinds(..), MonoBinds(..), HsDecl(..), HsExpr(..),
                          isIfaceRuleDecl, nullBinds, andMonoBindList
                        )
 import HsTypes         ( toHsType )
+import PrelNames       ( mAIN_Name, mainName, ioTyConName, printName )
 import RnHsSyn         ( RenamedHsBinds, RenamedHsDecl, RenamedHsExpr )
 import TcHsSyn         ( TypecheckedMonoBinds, TypecheckedHsExpr,
                          TypecheckedForeignDecl, TypecheckedRuleDecl,
@@ -24,27 +25,31 @@ import TcHsSyn              ( TypecheckedMonoBinds, TypecheckedHsExpr,
 
 
 import TcMonad
-import TcType          ( newTyVarTy, zonkTcType )
+import TcType          ( newTyVarTy, zonkTcType, tcInstType )
+import TcUnify         ( unifyTauTy )
 import Inst            ( plusLIE )
+import VarSet          ( varSetElems )
 import TcBinds         ( tcTopBinds )
 import TcClassDcl      ( tcClassDecls2 )
 import TcDefaults      ( tcDefaults, defaultDefaultTys )
 import TcExpr          ( tcMonoExpr )
-import TcEnv           ( TcEnv, InstInfo, tcExtendGlobalValEnv, 
-                         isLocalThing, tcSetEnv, tcSetInstEnv, initTcEnv, getTcGEnv
+import TcEnv           ( TcEnv, InstInfo, tcExtendGlobalValEnv, tcLookup_maybe,
+                         isLocalThing, tcSetEnv, tcSetInstEnv, initTcEnv, getTcGEnv,
+                         TcTyThing(..), tcLookupTyCon
                        )
 import TcRules         ( tcIfaceRules, tcSourceRules )
 import TcForeign       ( tcForeignImports, tcForeignExports )
 import TcIfaceSig      ( tcInterfaceSigs )
 import TcInstDcls      ( tcInstDecls1, tcInstDecls2 )
-import TcSimplify      ( tcSimplifyTop )
+import TcSimplify      ( tcSimplifyTop, tcSimplifyInfer )
 import TcTyClsDecls    ( tcTyAndClassDecls )
 
 import CoreUnfold      ( unfoldingTemplate, hasUnfolding )
-import Type            ( funResultTy, splitForAllTys, openTypeKind )
+import Type            ( funResultTy, splitForAllTys, mkForAllTys, mkFunTys,
+                         liftedTypeKind, openTypeKind, mkTyConApp, tyVarsOfType, tidyType )
 import ErrUtils                ( printErrorsAndWarnings, errorsFound, dumpIfSet_dyn, showPass )
 import Id              ( idType, idName, isLocalId, idUnfolding )
-import Module           ( Module, isHomeModule )
+import Module           ( Module, isHomeModule, moduleName )
 import Name            ( Name, toRdrName, isGlobalName )
 import Name            ( nameEnvElts, lookupNameEnv )
 import TyCon           ( tyConGenInfo )
@@ -99,6 +104,7 @@ typecheckModule dflags pcs hst mod_iface unqual decls
 
 ---------------
 typecheckExpr :: DynFlags
+             -> Bool                   -- True <=> wrap in 'print' to get a result of IO type
              -> PersistentCompilerState
              -> HomeSymbolTable
              -> PrintUnqualified       -- For error printing
@@ -107,7 +113,7 @@ typecheckExpr :: DynFlags
                  [RenamedHsDecl])      -- Plus extra decls it sucked in from interface files
              -> IO (Maybe (PersistentCompilerState, TypecheckedHsExpr, TcType))
 
-typecheckExpr dflags pcs hst unqual this_mod (expr, decls)
+typecheckExpr dflags wrap_io pcs hst unqual this_mod (expr, decls)
   = typecheck dflags pcs hst unqual $
 
         -- use the default default settings, i.e. [Integer, Double]
@@ -116,19 +122,50 @@ typecheckExpr dflags pcs hst unqual this_mod (expr, decls)
     ASSERT( null local_inst_info && nullBinds deriv_binds && null local_rules )
 
     tcSetEnv env                               $
-    newTyVarTy openTypeKind    `thenTc` \ ty ->
-    tcMonoExpr expr ty         `thenTc` \ (expr', lie) ->
-    tcSimplifyTop lie          `thenTc` \ binds ->
-    let all_expr = mkHsLet binds expr' in
-    zonkExpr all_expr          `thenNF_Tc` \ zonked_expr ->
-    zonkTcType ty              `thenNF_Tc` \ zonked_ty ->
+    tc_expr expr                                       `thenTc` \ (expr', lie, expr_ty) ->
+    tcSimplifyInfer smpl_doc 
+       (varSetElems (tyVarsOfType expr_ty)) lie        `thenTc` \ (qtvs, lie_free, dict_binds, dict_ids) ->
+    tcSimplifyTop lie_free                             `thenTc` \ const_binds ->
+    let all_expr = mkHsLet const_binds $
+                  TyLam qtvs           $
+                  DictLam dict_ids     $
+                  mkHsLet dict_binds   $
+                  expr'
+       all_expr_ty = mkForAllTys qtvs (mkFunTys (map idType dict_ids) expr_ty)
+    in
+    zonkExpr all_expr                                  `thenNF_Tc` \ zonked_expr ->
+    zonkTcType all_expr_ty                             `thenNF_Tc` \ zonked_ty ->
     ioToTc (dumpIfSet_dyn dflags 
                Opt_D_dump_tc "Typechecked" (ppr zonked_expr)) `thenNF_Tc_`
     returnTc (new_pcs, zonked_expr, zonked_ty) 
+
   where
     get_fixity :: Name -> Maybe Fixity
     get_fixity n = pprPanic "typecheckExpr" (ppr n)
 
+    smpl_doc = ptext SLIT("main expression")
+
+       -- Typecheck it, wrapping in 'print' if necessary to
+       -- get a result of type IO t.  Returns the result type
+       -- that is free in the result type
+    tc_expr e 
+       | wrap_io   = tryTc_ (tc_io_expr (HsApp (HsVar printName) e))   -- Recovery case
+                            (tc_io_expr e)                             -- Main case
+       | otherwise = newTyVarTy openTypeKind   `thenTc` \ ty ->
+                     tcMonoExpr expr ty        `thenTc` \ (expr', lie) ->
+                     returnTc (expr', lie, ty)
+                     
+       where
+               -- (tc_io_expr e) typechecks 'e' if that gives a result of IO t,
+               -- or 'print e' otherwise.  Either way the result is of type IO t
+         tc_io_expr e = newTyVarTy openTypeKind        `thenTc` \ ty ->
+                        tcLookupTyCon ioTyConName      `thenNF_Tc` \ ioTyCon ->
+                        let
+                           res_ty = mkTyConApp ioTyCon [ty]
+                        in
+                        tcMonoExpr expr res_ty `thenTc` \ (expr', lie) ->
+                        returnTc (expr', lie, res_ty)
+
 ---------------
 typecheck :: DynFlags
          -> PersistentCompilerState
@@ -163,7 +200,11 @@ tcModule :: PersistentCompilerState
 
 tcModule pcs hst get_fixity this_mod decls
   =    -- Type-check the type and class decls, and all imported decls
-    tcImports pcs hst get_fixity this_mod decls        `thenTc` \ (env, new_pcs, local_inst_info, deriv_binds, local_rules) ->
+       -- tcImports recovers internally, but if anything gave rise to
+       -- an error we'd better stop now, to avoid a cascade
+    checkNoErrsTc (
+       tcImports pcs hst get_fixity this_mod decls
+    )                                          `thenTc` \ (env, new_pcs, local_inst_info, deriv_binds, local_rules) ->
 
     tcSetEnv env                               $
 
@@ -206,6 +247,9 @@ tcModule pcs hst get_fixity this_mod decls
                       lie_rules
     in
     tcSimplifyTop lie_alldecls                 `thenTc` \ const_inst_binds ->
+
+       -- CHECK THAT main IS DEFINED WITH RIGHT TYPE, IF REQUIRED
+    tcCheckMain this_mod                       `thenTc_`
     
         -- Backsubstitution.    This must be done last.
         -- Even tcSimplifyTop may do some unification.
@@ -337,6 +381,58 @@ tcImports pcs hst get_fixity this_mod decls
 
 %************************************************************************
 %*                                                                     *
+\subsection{Checking the type of main}
+%*                                                                     *
+%************************************************************************
+
+We must check that in module Main,
+       a) main is defined
+       b) main :: forall a1...an. IO t,  for some type t
+
+If we have
+       main = error "Urk"
+then the type of main will be 
+       main :: forall a. a
+and that should pass the test too.  
+
+So we just instantiate the type and unify with IO t, and declare 
+victory if doing so succeeds.
+
+\begin{code}
+tcCheckMain :: Module -> TcM ()
+tcCheckMain this_mod
+  | not (moduleName this_mod == mAIN_Name )
+  = returnTc ()
+
+  | otherwise
+  =    -- First unify the main_id with IO t, for any old t
+    tcLookup_maybe mainName            `thenNF_Tc` \ maybe_thing ->
+    case maybe_thing of
+       Just (ATcId main_id) -> check_main_ty (idType main_id)
+       other                -> addErrTc noMainErr      
+  where
+    check_main_ty main_ty
+      = tcInstType main_ty             `thenNF_Tc` \ (tvs, theta, main_tau) ->
+       newTyVarTy liftedTypeKind       `thenNF_Tc` \ arg_ty ->
+       tcLookupTyCon ioTyConName       `thenNF_Tc` \ ioTyCon ->
+       tcAddErrCtxtM (mainTypeCtxt main_ty)    $
+       if not (null theta) then 
+               failWithTc empty        -- Context has the error message
+       else
+       unifyTauTy main_tau (mkTyConApp ioTyCon [arg_ty])
+
+mainTypeCtxt main_ty tidy_env 
+  = zonkTcType main_ty         `thenNF_Tc` \ main_ty' ->
+    returnNF_Tc (tidy_env, ptext SLIT("`main' has the illegal type") <+> 
+                                quotes (ppr (tidyType tidy_env main_ty')))
+
+noMainErr = hsep [ptext SLIT("Module") <+> quotes (ppr mAIN_Name), 
+                 ptext SLIT("must include a definition for") <+> quotes (ptext SLIT("main"))]
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
 \subsection{Dumping output}
 %*                                                                     *
 %************************************************************************