[project @ 2002-04-02 13:56:32 by simonmar]
[ghc-hetmet.git] / ghc / compiler / parser / Parser.y
index 8b2ef62..39f3335 100644 (file)
@@ -1,6 +1,6 @@
 {-                                                             -*-haskell-*-
 -----------------------------------------------------------------------------
-$Id: Parser.y,v 1.88 2002/02/13 14:05:51 simonpj Exp $
+$Id: Parser.y,v 1.95 2002/04/02 13:56:32 simonmar Exp $
 
 Haskell grammar.
 
@@ -9,12 +9,13 @@ Author(s): Simon Marlow, Sven Panne 1997, 1998, 1999
 -}
 
 {
-module Parser ( parseModule, parseStmt, parseIdentifier ) where
+module Parser ( parseModule, parseStmt, parseIdentifier, parseIface ) where
 
 import HsSyn
 import HsTypes         ( mkHsTupCon )
 
 import RdrHsSyn
+import RnMonad         ( ParsedIface(..) )
 import Lex
 import ParseUtil
 import RdrName
@@ -25,9 +26,10 @@ import ForeignCall   ( Safety(..), CExportSpec(..),
                          CCallConv(..), CCallTarget(..), defaultCCallConv,
                        )
 import OccName         ( UserFS, varName, tcName, dataName, tcClsName, tvName )
+import TyCon           ( DataConDetails(..) )
 import SrcLoc          ( SrcLoc )
 import Module
-import CmdLineOpts     ( opt_SccProfilingOn )
+import CmdLineOpts     ( opt_SccProfilingOn, opt_InPackage )
 import Type            ( Kind, mkArrowKind, liftedTypeKind )
 import BasicTypes      ( Boxity(..), Fixity(..), FixityDirection(..), IPName(..),
                          NewOrData(..), StrictnessMark(..), Activation(..) )
@@ -58,6 +60,11 @@ Conflicts: 21 shift/reduce, -=chak[4Feb2]
        (don't know whether to reduce 'a' as a btype or shift the '->'.
         conclusion:  bogus expression anyway, doesn't matter)
 
+1 for ambiguity in '{-# RULES "name" [ ... #-}
+       we don't know whether the '[' starts the activation or not: it
+       might be the start of the declaration with the activation being
+       empty.  --SDM 1/4/2002
+
 1 for ambiguity in '{-# RULES "name" forall = ... #-}' 
        since 'forall' is a valid variable name, we don't know whether
        to treat a forall on the input as the beginning of a quantifier
@@ -66,9 +73,10 @@ Conflicts: 21 shift/reduce, -=chak[4Feb2]
        This saves explicitly defining a grammar for the rule lhs that
        doesn't include 'forall'.
 
-1 for ambiguity in 'x @ Rec{..}'.  
-       Only sensible parse is 'x @ (Rec{..})', which is what resolving
-       to shift gives us.
+1 for ambiguity in 'let ?x ...'
+       the parser can't tell whether the ?x is the lhs of a normal binding or
+       an implicit binding.  Fortunately resolving as shift gives it the only
+       sensible meaning, namely the lhs of an implicit binding.
 
 6 for conflicts between `fdecl' and `fdeclDEPRECATED', which are resolved
   correctly, and moreover, should go away when `fdeclDEPRECATED' is removed.
@@ -110,15 +118,16 @@ Conflicts: 21 shift/reduce, -=chak[4Feb2]
  'label'       { ITlabel } 
  'dynamic'     { ITdynamic }
  'safe'                { ITsafe }
+ 'threadsafe'  { ITthreadsafe }
  'unsafe'      { ITunsafe }
  'with'        { ITwith }
  'stdcall'      { ITstdcallconv }
  'ccall'        { ITccallconv }
  'dotnet'       { ITdotnet }
  '_ccall_'     { ITccall (False, False, PlayRisky) }
- '_ccall_GC_'  { ITccall (False, False, PlaySafe)  }
+ '_ccall_GC_'  { ITccall (False, False, PlaySafe False) }
  '_casm_'      { ITccall (False, True,  PlayRisky) }
- '_casm_GC_'   { ITccall (False, True,  PlaySafe)  }
+ '_casm_GC_'   { ITccall (False, True,  PlaySafe False) }
 
  '{-# SPECIALISE'  { ITspecialise_prag }
  '{-# SOURCE'     { ITsource_prag }
@@ -220,6 +229,7 @@ Conflicts: 21 shift/reduce, -=chak[4Feb2]
 %name parseModule module
 %name parseStmt   maybe_stmt
 %name parseIdentifier  identifier
+%name parseIface iface
 %tokentype { Token }
 %%
 
@@ -256,6 +266,56 @@ cvtopdecls :: { [RdrNameHsDecl] }
        : topdecls                              { cvTopDecls (groupBindings $1)}
 
 -----------------------------------------------------------------------------
+-- Interfaces (.hi-boot files)
+
+iface   :: { ParsedIface }
+       : 'module' modid 'where' ifacebody
+         {         ParsedIface {
+                       pi_mod     = $2,
+                       pi_pkg     = opt_InPackage,
+                       pi_vers    = 1,                 -- Module version
+                       pi_orphan  = False,
+                       pi_exports = (1,[($2,mkIfaceExports $4)]),
+                       pi_usages  = [],
+                       pi_fixity  = [],
+                       pi_insts   = [],
+                       pi_decls   = map (\x -> (1,x)) $4,
+                       pi_rules   = (1,[]),
+                       pi_deprecs = Nothing
+                   }
+          }
+
+ifacebody :: { [RdrNameTyClDecl] }
+       :  '{'            ifacedecls '}'                { $2 }
+       |      layout_on  ifacedecls close              { $2 }
+
+ifacedecls :: { [RdrNameTyClDecl] }
+       : ifacedecl ';' ifacedecls                      { $1 : $3 }
+       | ';' ifacedecls                                { $2 }
+       | ifacedecl                                     { [$1] }
+       | {- empty -}                                   { [] }
+
+ifacedecl :: { RdrNameTyClDecl }
+       : srcloc 'data' tycl_hdr constrs 
+         { mkTyData DataType $3 (DataCons (reverse $4)) Nothing $1 }
+
+       | srcloc 'newtype' tycl_hdr '=' newconstr
+         { mkTyData NewType $3 (DataCons [$5]) Nothing $1 }
+
+       | srcloc 'class' tycl_hdr fds where
+               { let 
+                       (binds,sigs) = cvMonoBindsAndSigs cvClassOpSig 
+                                       (groupBindings $5) 
+                  in
+                  mkClassDecl $3 $4 sigs (Just binds) $1 }
+
+       | srcloc 'type' tycon tv_bndrs '=' ctype        
+         { TySynonym $3 $4 $6 $1 }
+
+       | srcloc var '::' sigtype
+         { IfaceSig $2 $4 [] $1 }
+
+-----------------------------------------------------------------------------
 -- The Export List
 
 maybeexports :: { Maybe [RdrNameIE] }
@@ -357,11 +417,11 @@ topdecl :: { RdrBinding }
 
        | srcloc 'data' tycl_hdr constrs deriving
                {% returnP (RdrHsDecl (TyClD
-                     (mkTyData DataType $3 (reverse $4) (length $4) $5 $1))) }
+                     (mkTyData DataType $3 (DataCons (reverse $4)) $5 $1))) }
 
        | srcloc 'newtype' tycl_hdr '=' newconstr deriving
                {% returnP (RdrHsDecl (TyClD
-                     (mkTyData NewType $3 [$5] 1 $6 $1))) }
+                     (mkTyData NewType $3 (DataCons [$5]) $6 $1))) }
 
        | srcloc 'class' tycl_hdr fds where
                {% let 
@@ -389,15 +449,23 @@ topdecl :: { RdrBinding }
 --     (Eq a, Ord b) => T a b
 -- Rather a lot of inlining here, else we get reduce/reduce errors
 tycl_hdr :: { (RdrNameContext, RdrName, [RdrNameHsTyVar]) }
-       : '(' comma_types1 ')' '=>' gtycon tv_bndrs     {% mapP checkPred $2    `thenP` \ cxt ->
-                                                          returnP (cxt, $5, $6) }
+       : '(' comma_types1 ')' '=>' gtycon tv_bndrs
+               {% mapP checkPred $2    `thenP` \ cxt ->
+                 returnP (cxt, $5, $6) }
+
+       | '(' ')' '=>' gtycon tv_bndrs
+               { ([], $4, $5) }
+
           -- qtycon for the class below name would lead to many s/r conflicts
          --   FIXME: does the renamer pick up all wrong forms and raise an
          --          error 
-       | gtycon atypes1 '=>' gtycon atypes0            {% checkTyVars $5       `thenP` \ tvs ->
-                                                          returnP ([HsClassP $1 $2], $4, tvs) }
-       | gtycon  atypes0                               {% checkTyVars $2       `thenP` \ tvs ->
-                                                          returnP ([], $1, tvs) }
+       | gtycon atypes1 '=>' gtycon atypes0    
+               {% checkTyVars $5       `thenP` \ tvs ->
+                  returnP ([HsClassP $1 $2], $4, tvs) }
+
+       | gtycon  atypes0
+               {% checkTyVars $2       `thenP` \ tvs ->
+                  returnP ([], $1, tvs) }
                -- We have to have qtycon in this production to avoid s/r
                -- conflicts with the previous one.  The renamer will complain
                -- if we use a qualified tycon.
@@ -440,6 +508,11 @@ decllist :: { [RdrBinding] }
        : '{'            decls '}'      { $2 }
        |     layout_on  decls close    { $2 }
 
+letbinds :: { RdrNameHsExpr -> RdrNameHsExpr }
+       : decllist              { HsLet (cvBinds cvValSig (groupBindings $1)) }
+       | '{'            dbinds '}'     { \e -> HsWith e $2 False{-not with-} }
+       |     layout_on  dbinds close   { \e -> HsWith e $2 False{-not with-} }
+
 fixdecl :: { RdrBinding }
        : srcloc infix prec ops         { foldr1 RdrAndBindings
                                            [ RdrSig (FixSig (FixitySig n 
@@ -514,7 +587,7 @@ deprecation :: { RdrBinding }
 --
 fdecl :: { RdrNameHsDecl }
 fdecl : srcloc 'import' callconv safety1 fspec {% mkImport $3 $4       $5 $1 }
-      | srcloc 'import' callconv         fspec {% mkImport $3 PlaySafe $4 $1 }
+      | srcloc 'import' callconv         fspec {% mkImport $3 (PlaySafe False) $4 $1 }
       | srcloc 'export'        callconv         fspec  {% mkExport $3          $4 $1 }
         -- the following syntax is DEPRECATED
       | srcloc fdecl1DEPRECATED                        { ForD ($2 True $1) }
@@ -524,7 +597,7 @@ fdecl1DEPRECATED :: { Bool -> SrcLoc -> ForeignDecl RdrName }
 fdecl1DEPRECATED 
   ----------- DEPRECATED label decls ------------
   : 'label' ext_name varid '::' sigtype
-    { ForeignImport $3 $5 (CImport defaultCCallConv PlaySafe _NIL_ _NIL_ 
+    { ForeignImport $3 $5 (CImport defaultCCallConv (PlaySafe False) _NIL_ _NIL_ 
                                   (CLabel ($2 `orElse` mkExtName $3))) }
 
   ----------- DEPRECATED ccall/stdcall decls ------------
@@ -594,7 +667,7 @@ fdecl1DEPRECATED
     -- DEPRECATED variant #8: use of the special identifier `dynamic' without
     --                       an explicit calling convention (export)
   | 'export' {-no callconv-} 'dynamic' varid '::' sigtype
-    { ForeignImport $3 $5 (CImport defaultCCallConv PlaySafe _NIL_ _NIL_ 
+    { ForeignImport $3 $5 (CImport defaultCCallConv (PlaySafe False) _NIL_ _NIL_ 
                                   CWrapper) }
 
     -- DEPRECATED variant #9: use of the special identifier `dynamic' (export)
@@ -602,7 +675,7 @@ fdecl1DEPRECATED
     {% case $2 of
          DNCall      -> parseError "Illegal format of .NET foreign import"
         CCall cconv -> returnP $
-          ForeignImport $4 $6 (CImport cconv PlaySafe _NIL_ _NIL_ CWrapper) }
+          ForeignImport $4 $6 (CImport cconv (PlaySafe False) _NIL_ _NIL_ CWrapper) }
 
   ----------- DEPRECATED .NET decls ------------
   -- NB: removed the .NET call declaration, as it is entirely subsumed
@@ -623,12 +696,14 @@ callconv :: { CallConv }
 
 safety :: { Safety }
        : 'unsafe'                      { PlayRisky }
-       | 'safe'                        { PlaySafe  }
-       | {- empty -}                   { PlaySafe  }
+       | 'safe'                        { PlaySafe False }
+       | 'threadsafe'                  { PlaySafe True  }
+       | {- empty -}                   { PlaySafe False }
 
 safety1 :: { Safety }
        : 'unsafe'                      { PlayRisky }
-       | 'safe'                        { PlaySafe  }
+       | 'safe'                        { PlaySafe  False }
+       | 'threadsafe'                  { PlaySafe  True }
          -- only needed to avoid conflicts with the DEPRECATED rules
 
 fspec :: { (FAST_STRING, RdrName, RdrNameHsType) }
@@ -874,7 +949,7 @@ gdrh :: { RdrNameGRHS }
 
 exp   :: { RdrNameHsExpr }
        : infixexp '::' sigtype         { (ExprWithTySig $1 $3) }
-       | infixexp 'with' dbinding      { HsWith $1 $3 }
+       | infixexp 'with' dbinding      { HsWith $1 $3 True{-not a let-} }
        | infixexp                      { $1 }
 
 infixexp :: { RdrNameHsExpr }
@@ -888,7 +963,7 @@ exp10 :: { RdrNameHsExpr }
                           returnP (HsLam (Match ps $5 
                                            (GRHSs (unguardedRHS $8 $7) 
                                                   EmptyBinds placeHolderType))) }
-       | 'let' declbinds 'in' exp              { HsLet $2 $4 }
+       | 'let' letbinds 'in' exp               { $2 $4 }
        | 'if' srcloc exp 'then' exp 'else' exp { HsIf $3 $5 $7 $2 }
        | 'case' srcloc exp 'of' altslist       { HsCase $3 $5 $2 }
        | '-' fexp                              { mkHsNegApp $2 }
@@ -896,9 +971,9 @@ exp10 :: { RdrNameHsExpr }
                                                   returnP (HsDo DoExpr stmts $1) }
 
        | '_ccall_'    ccallid aexps0           { HsCCall $2 $3 PlayRisky False placeHolderType }
-       | '_ccall_GC_' ccallid aexps0           { HsCCall $2 $3 PlaySafe  False placeHolderType }
+       | '_ccall_GC_' ccallid aexps0           { HsCCall $2 $3 (PlaySafe False) False placeHolderType }
        | '_casm_'     CLITLIT aexps0           { HsCCall $2 $3 PlayRisky True  placeHolderType }
-       | '_casm_GC_'  CLITLIT aexps0           { HsCCall $2 $3 PlaySafe  True  placeHolderType }
+       | '_casm_GC_'  CLITLIT aexps0           { HsCCall $2 $3 (PlaySafe False) True  placeHolderType }
 
         | scc_annot exp                                { if opt_SccProfilingOn
                                                        then HsSCC $1 $2
@@ -926,16 +1001,21 @@ aexps    :: { [RdrNameHsExpr] }
        | {- empty -}                           { [] }
 
 aexp   :: { RdrNameHsExpr }
+       : qvar '@' aexp                 { EAsPat $1 $3 }
+       | '~' aexp                      { ELazyPat $2 }
+       | aexp1                         { $1 }
+
+aexp1  :: { RdrNameHsExpr }
         : var_or_con '{|' gentype '|}'          { (HsApp $1 (HsType $3)) }
-       | aexp '{' fbinds '}'                   {% (mkRecConstrOrUpdate $1 
+       | aexp1 '{' fbinds '}'                  {% (mkRecConstrOrUpdate $1 
                                                        (reverse $3)) }
-       | aexp1                                 { $1 }
+       | aexp2                                 { $1 }
 
 var_or_con :: { RdrNameHsExpr }
         : qvar                          { HsVar $1 }
         | gcon                          { HsVar $1 }
 
-aexp1  :: { RdrNameHsExpr }
+aexp2  :: { RdrNameHsExpr }
        : ipvar                         { HsIPVar $1 }
        | var_or_con                    { $1 }
        | literal                       { HsLit $1 }
@@ -948,9 +1028,7 @@ aexp1      :: { RdrNameHsExpr }
        | '[:' parr ':]'                { $2 }
        | '(' infixexp qop ')'          { (SectionL $2 (HsVar $3))  }
        | '(' qopm infixexp ')'         { (SectionR $2 $3) }
-       | qvar '@' aexp                 { EAsPat $1 $3 }
        | '_'                           { EWildPat }
-       | '~' aexp1                     { ELazyPat $2 }
 
 texps :: { [RdrNameHsExpr] }
        : texps ',' exp                 { $3 : $1 }
@@ -1112,7 +1190,7 @@ dbinds    :: { [(IPName RdrName, RdrNameHsExpr)] }
        : dbinds ';' dbind              { $3 : $1 }
        | dbinds ';'                    { $1 }
        | dbind                         { [$1] }
-       | {- empty -}                   { [] }
+--     | {- empty -}                   { [] }
 
 dbind  :: { (IPName RdrName, RdrNameHsExpr) }
 dbind  : ipvar '=' exp                 { ($1, $3) }
@@ -1213,31 +1291,35 @@ qvarid :: { RdrName }
 
 varid :: { RdrName }
        : varid_no_unsafe       { $1 }
-       | 'unsafe'              { mkUnqual varName SLIT("unsafe") }
+       | 'unsafe'              { mkUnqual varName FSLIT("unsafe") }
+       | 'safe'                { mkUnqual varName FSLIT("safe") }
+       | 'threadsafe'          { mkUnqual varName FSLIT("threadsafe") }
 
 varid_no_unsafe :: { RdrName }
        : VARID                 { mkUnqual varName $1 }
        | special_id            { mkUnqual varName $1 }
-       | 'forall'              { mkUnqual varName SLIT("forall") }
+       | 'forall'              { mkUnqual varName FSLIT("forall") }
 
 tyvar  :: { RdrName }
        : VARID                 { mkUnqual tvName $1 }
        | special_id            { mkUnqual tvName $1 }
-       | 'unsafe'              { mkUnqual tvName SLIT("unsafe") }
+       | 'unsafe'              { mkUnqual tvName FSLIT("unsafe") }
+       | 'safe'                { mkUnqual tvName FSLIT("safe") }
+       | 'threadsafe'          { mkUnqual tvName FSLIT("threadsafe") }
 
 -- These special_ids are treated as keywords in various places, 
--- but as ordinary ids elsewhere.   A special_id collects all thsee
+-- but as ordinary ids elsewhere.   'special_id' collects all these
 -- except 'unsafe' and 'forall' whose treatment differs depending on context
 special_id :: { UserFS }
 special_id
-       : 'as'                  { SLIT("as") }
-       | 'qualified'           { SLIT("qualified") }
-       | 'hiding'              { SLIT("hiding") }
-       | 'export'              { SLIT("export") }
-       | 'label'               { SLIT("label")  }
-       | 'dynamic'             { SLIT("dynamic") }
-       | 'stdcall'             { SLIT("stdcall") }
-       | 'ccall'               { SLIT("ccall") }
+       : 'as'                  { FSLIT("as") }
+       | 'qualified'           { FSLIT("qualified") }
+       | 'hiding'              { FSLIT("hiding") }
+       | 'export'              { FSLIT("export") }
+       | 'label'               { FSLIT("label")  }
+       | 'dynamic'             { FSLIT("dynamic") }
+       | 'stdcall'             { FSLIT("stdcall") }
+       | 'ccall'               { FSLIT("ccall") }
 
 -----------------------------------------------------------------------------
 -- ConIds
@@ -1275,7 +1357,7 @@ qvarsym1 : QVARSYM                { mkQual varName $1 }
 
 varsym :: { RdrName }
        : varsym_no_minus       { $1 }
-       | '-'                   { mkUnqual varName SLIT("-") }
+       | '-'                   { mkUnqual varName FSLIT("-") }
 
 varsym_no_minus :: { RdrName } -- varsym not including '-'
        : VARSYM                { mkUnqual varName $1 }
@@ -1284,9 +1366,9 @@ varsym_no_minus :: { RdrName } -- varsym not including '-'
 
 -- See comments with special_id
 special_sym :: { UserFS }
-special_sym : '!'      { SLIT("!") }
-           | '.'       { SLIT(".") }
-           | '*'       { SLIT("*") }
+special_sym : '!'      { FSLIT("!") }
+           | '.'       { FSLIT(".") }
+           | '*'       { FSLIT("*") }
 
 -----------------------------------------------------------------------------
 -- Literals