[project @ 1998-12-02 13:17:09 by simonm]
[ghc-hetmet.git] / ghc / compiler / parser / hsparser.y
index 5e9018b..4a6e126 100644 (file)
@@ -47,6 +47,7 @@ static char *the_module_name;
 static maybe module_exports;
 
 extern list Lnil;
+extern list reverse_list();
 extern tree root;
 
 /* For FN, PREVPATT and SAMEFN macros */
@@ -74,8 +75,8 @@ static int Fixity = 0, Precedence = 0;
 char *ineg PROTO((char *));
 
 long    source_version = 0;
+BOOLEAN pat_check=TRUE;
 
-BOOLEAN inpat;
 %}
 
 %union {
@@ -124,9 +125,10 @@ BOOLEAN inpat;
 *                                                                     *
 **********************************************************************/
 
-%token OCURLY          CCURLY          VCCURLY         SEMI
-%token OBRACK          CBRACK          OPAREN          CPAREN
-%token COMMA           BQUOTE
+%token OCURLY          CCURLY          VCCURLY 
+%token  COMMA          SEMI            OBRACK          CBRACK
+%token WILDCARD        BQUOTE          OPAREN          CPAREN
+%token  OUNBOXPAREN     CUNBOXPAREN
 
 
 /**********************************************************************
@@ -137,9 +139,9 @@ BOOLEAN inpat;
 *                                                                     *
 **********************************************************************/
 
-%token DOTDOT          DCOLON          EQUAL
-%token LAMBDA          VBAR            RARROW
-%token         LARROW          MINUS
+%token DOTDOT          DCOLON          EQUAL           LAMBDA          
+%token VBAR            RARROW          LARROW
+%token AT              LAZY            DARROW
 
 
 /**********************************************************************
@@ -161,16 +163,19 @@ BOOLEAN inpat;
 %token  SCC
 %token CCALL           CCALL_GC        CASM            CASM_GC
 
+%token DOT             FORALL
+%token  EXPORT          UNSAFE          STDCALL                C_CALL   LABEL
+%token  PASCAL         FASTCALL        FOREIGN         DYNAMIC
 
 /**********************************************************************
 *                                                                     *
 *                                                                     *
-*     Valid symbols/identifiers which need to be recognised           *
+*     Special symbols/identifiers which need to be recognised         *
 *                                                                     *
 *                                                                     *
 **********************************************************************/
 
-%token WILDCARD        AT              LAZY            BANG
+%token MINUS           BANG            PLUS
 %token         AS              HIDING          QUALIFIED
 
 
@@ -183,8 +188,9 @@ BOOLEAN inpat;
 **********************************************************************/
 
 %token  INTERFACE_UPRAGMA SPECIALISE_UPRAGMA
-%token  INLINE_UPRAGMA MAGIC_UNFOLDING_UPRAGMA
-%token  DEFOREST_UPRAGMA END_UPRAGMA
+%token  INLINE_UPRAGMA NOINLINE_UPRAGMA MAGIC_UNFOLDING_UPRAGMA
+%token  END_UPRAGMA 
+%token  SOURCE_UPRAGMA
 
 /**********************************************************************
 *                                                                     *
@@ -200,7 +206,7 @@ BOOLEAN inpat;
        SCC     CASM    CCALL   CASM_GC CCALL_GC
 
 %left  VARSYM  CONSYM  QVARSYM QCONSYM
-       MINUS   BQUOTE  BANG    DARROW
+       MINUS   BQUOTE  BANG    DARROW  PLUS
 
 %left  DCOLON
 
@@ -223,59 +229,62 @@ BOOLEAN inpat;
 
 %type <ulist>   caserest alts alt quals
                dorest stmts stmt
-               rbinds rpats list_exps 
+               rbinds rbinds1 rpats rpats1 list_exps list_rest
                qvarsk qvars_list
-               constrs constr1 fields 
-               types atypes batypes
+               constrs constr1 fields conargatypes
+               tautypes atypes
                types_and_maybe_ids
-               pats context context_list tyvar_list
+               pats simple_context simple_context_list 
                export_list enames
                import_list inames
                impdecls maybeimpdecls impdecl
                maybefixes fixes fix ops
                dtyclses dtycls_list
                gdrhs gdpat valrhs
-               lampats cexps
+               lampats cexps gd texps
+               tyvars1 constr_context forall
 
-%type <umaybe>  maybeexports impas maybeimpspec deriving
-
-%type <ueither> impspec  
+%type <umaybe>  maybeexports impspec deriving 
+               ext_name
 
 %type <uliteral> lit_constant
 
-%type <utree>  exp oexp dexp kexp fexp aexp rbind texps
+%type <utree>  exp oexp dexp kexp fexp aexp rbind
                expL oexpL kexpL expLno oexpLno dexpLno kexpLno
-               vallhs funlhs qual gd leftexp
-               pat bpat apat apatc conpat rpat
-               patk bpatk apatck conpatk
+               vallhs funlhs qual leftexp
+               pat cpat bpat apat apatc conpat rpat
+                       patk bpatk apatck conpatk
 
 
-%type <uid>    MINUS DARROW AS LAZY
+%type <uid>    MINUS PLUS DARROW AS LAZY
                VARID CONID VARSYM CONSYM 
                var con varop conop op
                vark varid varsym varsym_nominus
-               tycon modid impmod ccallid
+               tycon modid ccallid tyvar
+               varid_noforall
 
 %type <uqid>   QVARID QCONID QVARSYM QCONSYM 
                qvarid qconid qvarsym qconsym
                qvar qcon qvarop qconop qop
                qvark qconk qtycon qtycls
-               gcon gconk gtycon qop1 qvarop1 
-               ename iname 
+               gcon gconk gtycon itycon qop1 qvarop1 
+               ename iname
 
 %type <ubinding>  topdecl topdecls letdecls
-                 typed datad newtd classd instd defaultd
+                 typed datad newtd classd instd defaultd foreignd
                  decl decls valdef instdef instdefs
                  maybe_where cbody rinst type_and_maybe_id
 
 %type <upbinding> valrhs1 altrest
 
-%type <uttype>    simple ctype type atype btype
-                 gtyconapp ntyconapp ntycon gtyconvars
-                 bbtype batype btyconapp
-                 class restrict_inst general_inst tyvar
+%type <uttype>    polytype
+                 conargatype conapptype
+                 tautype
+                 apptype
+                 atype polyatype
+                 simple_con_app simple_con_app1 inst_type
 
-%type <uconstr>          constr field
+%type <uconstr>          constr constr_after_context field
 
 %type <ustring>   FLOAT INTEGER INTPRIM
                  FLOATPRIM DOUBLEPRIM CLITLIT
@@ -284,7 +293,8 @@ BOOLEAN inpat;
 
 %type <uentid>   export import
 
-%type <ulong>     commas impqual
+%type <ulong>     commas importkey get_line_no
+                 unsafe_flag callconv
 
 /**********************************************************************
 *                                                                     *
@@ -380,32 +390,22 @@ impdecls:  impdecl                                { $$ = $1; }
        ;
 
 
-impdecl        :  importkey impqual impmod impas maybeimpspec
-               { 
-                 $$ = lsing(mkimport($3,$2,$4,$5,startlineno));
-               }
-       ;
-
-impmod  : modid                                        { $$ = $1; }
-       ;
-
-impqual :  /* noqual */                                { $$ = 0; }
-       |  QUALIFIED                            { $$ = 1; }
-       ;
-
-impas   :  /* noas */                          { $$ = mknothing(); }
-       |  AS modid                             { $$ = mkjust($2);  }
+impdecl        :  importkey modid impspec
+               { $$ = lsing(mkimport($2,0,mknothing(),$3,$1,startlineno)); }
+       |  importkey QUALIFIED modid impspec
+               { $$ = lsing(mkimport($3,1,mknothing(),$4,$1,startlineno)); }
+       |  importkey QUALIFIED modid AS modid impspec
+               { $$ = lsing(mkimport($3,1,mkjust($5),$6,$1,startlineno)); }
+       |  importkey modid AS modid impspec
+               { $$ = lsing(mkimport($3,1,mkjust($4),$5,$1,startlineno)); }
        ;
 
-maybeimpspec : /* empty */                     { $$ = mknothing(); }
-       |  impspec                              { $$ = mkjust($1);  }
-       ;
-
-impspec        :  OPAREN CPAREN                          { $$ = mkleft(Lnil); }
-       |  OPAREN import_list CPAREN              { $$ = mkleft($2);   }
-       |  OPAREN import_list COMMA CPAREN        { $$ = mkleft($2);   }
-       |  HIDING OPAREN import_list CPAREN       { $$ = mkright($3);  }
-       |  HIDING OPAREN import_list COMMA CPAREN { $$ = mkright($3);  }
+impspec        :  /* empty */                            { $$ = mknothing(); }
+       |  OPAREN CPAREN                          { $$ = mkjust(mkleft(Lnil)); }
+       |  OPAREN import_list CPAREN              { $$ = mkjust(mkleft($2));   }
+       |  OPAREN import_list COMMA CPAREN        { $$ = mkjust(mkleft($2));   }
+       |  HIDING OPAREN import_list CPAREN       { $$ = mkjust(mkright($3));  }
+       |  HIDING OPAREN import_list COMMA CPAREN { $$ = mkjust(mkright($3));  }
        ;
 
 import_list:
@@ -414,10 +414,16 @@ import_list:
        ;
 
 import :  var                                  { $$ = mkentid(mknoqual($1)); }
-       |  tycon                                { $$ = mkenttype(mknoqual($1)); }
-       |  tycon OPAREN DOTDOT CPAREN           { $$ = mkenttypeall(mknoqual($1)); }
-       |  tycon OPAREN CPAREN                  { $$ = mkenttypenamed(mknoqual($1),Lnil); }
-       |  tycon OPAREN inames CPAREN           { $$ = mkenttypenamed(mknoqual($1),$3); }
+       |  itycon                               { $$ = mkenttype($1); }
+       |  itycon OPAREN DOTDOT CPAREN          { $$ = mkenttypeall($1); }
+       |  itycon OPAREN CPAREN                 { $$ = mkenttypenamed($1,Lnil);}
+       |  itycon OPAREN inames CPAREN          { $$ = mkenttypenamed($1,$3); }
+       ;
+
+itycon :  tycon                                { $$ = mknoqual($1); }
+       |  OBRACK CBRACK                        { $$ = creategid(NILGID); }
+       |  OPAREN CPAREN                        { $$ = creategid(UNITGID); }         
+       |  OPAREN commas CPAREN                 { $$ = creategid($2); }
        ;
 
 inames  :  iname                               { $$ = lsing($1); }
@@ -457,8 +463,8 @@ fix :  INFIXL INTEGER       { Precedence = checkfixity($2); Fixity = INFIXL; }
           ops                  { $$ = $3; }
        ;
 
-ops    :  op            { $$ = lsing(mkfixop(mknoqual($1),infixint(Fixity),Precedence)); }
-       |  ops COMMA op  { $$ = lapp($1,mkfixop(mknoqual($3),infixint(Fixity),Precedence)); }
+ops    :  op            { $$ = lsing(mkfixop(mknoqual($1),infixint(Fixity),Precedence,startlineno)); }
+       |  ops COMMA op  { $$ = lapp($1,mkfixop(mknoqual($3),infixint(Fixity),Precedence,startlineno)); }
        ;
 
 topdecls:  topdecl
@@ -481,28 +487,29 @@ topdecls:  topdecl
                }
         ;
 
-topdecl        :  typed                                { $$ = $1; }
-       |  datad                                { $$ = $1; }
-       |  newtd                                { $$ = $1; }
-       |  classd                               { $$ = $1; }
-       |  instd                                { $$ = $1; }
-       |  defaultd                             { $$ = $1; }
+topdecl        :  typed                                { $$ = $1; FN = NULL; SAMEFN = 0; }
+       |  datad                                { $$ = $1; FN = NULL; SAMEFN = 0; }
+       |  newtd                                { $$ = $1; FN = NULL; SAMEFN = 0; }
+       |  classd                               { $$ = $1; FN = NULL; SAMEFN = 0; }
+       |  instd                                { $$ = $1; FN = NULL; SAMEFN = 0; }
+       |  defaultd                             { $$ = $1; FN = NULL; SAMEFN = 0; }
+       |  foreignd                             { $$ = $1; FN = NULL; SAMEFN = 0; }
        |  decl                                 { $$ = $1; }
        ;
 
-typed  :  typekey simple EQUAL type            { $$ = mknbind($2,$4,startlineno); }
+typed  :  typekey simple_con_app EQUAL tautype         { $$ = mknbind($2,$4,startlineno); }
        ;
 
 
-datad  :  datakey simple EQUAL constrs deriving
+datad  :  datakey simple_con_app EQUAL constrs deriving
                { $$ = mktbind(Lnil,$2,$4,$5,startlineno); }
-       |  datakey context DARROW simple EQUAL constrs deriving
+       |  datakey simple_context DARROW simple_con_app EQUAL constrs deriving
                { $$ = mktbind($2,$4,$6,$7,startlineno); }
        ;
 
-newtd  :  newtypekey simple EQUAL constr1 deriving
+newtd  :  newtypekey simple_con_app EQUAL constr1 deriving
                { $$ = mkntbind(Lnil,$2,$4,$5,startlineno); }
-       |  newtypekey context DARROW simple EQUAL constr1 deriving
+       |  newtypekey simple_context DARROW simple_con_app EQUAL constr1 deriving
                { $$ = mkntbind($2,$4,$6,$7,startlineno); }
        ;
 
@@ -510,10 +517,14 @@ deriving: /* empty */                             { $$ = mknothing(); }
         | DERIVING dtyclses                     { $$ = mkjust($2); }
        ;
 
-classd :  classkey context DARROW class cbody
-               { $$ = mkcbind($2,$4,$5,startlineno); }
-       |  classkey class cbody                 
-               { $$ = mkcbind(Lnil,$2,$3,startlineno); }
+classd :  classkey apptype DARROW simple_con_app1 cbody
+               /* Context can now be more than simple_context */
+               { $$ = mkcbind(type2context($2),$4,$5,startlineno); }
+       |  classkey apptype cbody
+               /* We have to say apptype rather than simple_con_app1, else
+                  we get reduce/reduce errs */
+               { check_class_decl_head($2);
+                 $$ = mkcbind(Lnil,$2,$3,startlineno); }
        ;
 
 cbody  :  /* empty */                          { $$ = mknullbind(); }
@@ -521,35 +532,52 @@ cbody     :  /* empty */                          { $$ = mknullbind(); }
        |  WHERE vocurly decls vccurly          { checkorder($3); $$ = $3; }
        ;
 
-instd  :  instkey context DARROW gtycon restrict_inst rinst
-               { $$ = mkibind($2,$4,$5,$6,startlineno); }
-       |  instkey gtycon general_inst rinst
-               { $$ = mkibind(Lnil,$2,$3,$4,startlineno); }
+instd  :  instkey inst_type rinst              { $$ = mkibind($2,$3,startlineno); }
        ;
 
+/* Compare polytype */
+/* [July 98: first production was tautype DARROW tautype, but I can't see why.] */
+inst_type : apptype DARROW apptype             { is_context_format( $3, 0 );   /* Check the instance head */
+                                                 $$ = mkforall(Lnil,type2context($1),$3); }
+         | apptype                             { is_context_format( $1, 0 );   /* Check the instance head */
+                                                 $$ = $1; }
+         ;
+
+
 rinst  :  /* empty */                                          { $$ = mknullbind(); }
        |  WHERE ocurly  instdefs ccurly                        { $$ = $3; }
        |  WHERE vocurly instdefs vccurly                       { $$ = $3; }
        ;
 
-restrict_inst : gtycon                         { $$ = mktname($1); }
-       |  OPAREN gtyconvars CPAREN             { $$ = $2; }
-       |  OPAREN tyvar COMMA tyvar_list CPAREN { $$ = mkttuple(mklcons($2,$4)); }
-       |  OBRACK tyvar CBRACK                  { $$ = mktllist($2); }
-       |  OPAREN tyvar RARROW tyvar CPAREN     { $$ = mktfun($2,$4); }
+defaultd:  defaultkey OPAREN tautypes CPAREN       { $$ = mkdbind($3,startlineno); }
+       |  defaultkey OPAREN CPAREN             { $$ = mkdbind(Lnil,startlineno); }
        ;
 
-general_inst : gtycon                          { $$ = mktname($1); }
-       |  OPAREN gtyconapp CPAREN              { $$ = $2; }
-       |  OPAREN type COMMA types CPAREN       { $$ = mkttuple(mklcons($2,$4)); }
-       |  OBRACK type CBRACK                   { $$ = mktllist($2); }
-       |  OPAREN btype RARROW type CPAREN      { $$ = mktfun($2,$4); }
+/* FFI primitive declarations - GHC/Hugs specific */
+foreignd:  foreignkey IMPORT callconv ext_name unsafe_flag qvarid DCOLON tautype { $$ = mkfobind($6,$8,$4,$5,$3,FOREIGN_IMPORT,startlineno); }
+        |  foreignkey EXPORT callconv ext_name qvarid DCOLON tautype             { $$ = mkfobind($5,$7,$4,0,$3,FOREIGN_EXPORT,startlineno); }
+       ;
+        |  foreignkey LABEL ext_name qvarid DCOLON tautype                       { $$ = mkfobind($4,$6,$3,0,-1,FOREIGN_LABEL,startlineno); }
        ;
 
-defaultd:  defaultkey OPAREN types CPAREN       { $$ = mkdbind($3,startlineno); }
-       |  defaultkey OPAREN CPAREN             { $$ = mkdbind(Lnil,startlineno); }
+callconv: STDCALL      { $$ = CALLCONV_STDCALL;  }
+       | C_CALL        { $$ = CALLCONV_CCALL;    }
+       | PASCAL        { $$ = CALLCONV_PASCAL;   }
+       | FASTCALL      { $$ = CALLCONV_FASTCALL; }
+/* If you leave out the specification of a calling convention, you'll (probably) get C's. */
+        | /*empty*/     { $$ = CALLCONV_NONE;    }
        ;
 
+ext_name: STRING       { $$ = mkjust(lsing($1)); }
+       | STRING STRING { $$ = mkjust(mklcons ($1,lsing($2))); }
+        | DYNAMIC       { $$ = mknothing();   }
+
+unsafe_flag: UNSAFE    { $$ = 1; }
+          | /*empty*/  { $$ = 0; }
+          ;
+
+
+
 decls  : decl
        | decls SEMI decl
                {
@@ -569,7 +597,7 @@ decls       : decl
     to real mischief (ugly, but likely to work).
 */
 
-decl   : qvarsk DCOLON ctype
+decl   : qvarsk DCOLON polytype
                { $$ = mksbind($1,$3,startlineno);
                  PREVPATT = NULL; FN = NULL; SAMEFN = 0;
                }
@@ -587,7 +615,7 @@ decl        : qvarsk DCOLON ctype
                  PREVPATT = NULL; FN = NULL; SAMEFN = 0;
                }
 
-       |  SPECIALISE_UPRAGMA INSTANCE gtycon general_inst END_UPRAGMA
+       |  SPECIALISE_UPRAGMA INSTANCE gtycon atype END_UPRAGMA
                {
                  $$ = mkispec_uprag($3, $4, startlineno);
                  PREVPATT = NULL; FN = NULL; SAMEFN = 0;
@@ -605,16 +633,16 @@ decl      : qvarsk DCOLON ctype
                  PREVPATT = NULL; FN = NULL; SAMEFN = 0;
                }
 
-       |  MAGIC_UNFOLDING_UPRAGMA qvark vark END_UPRAGMA
+       |  NOINLINE_UPRAGMA qvark END_UPRAGMA
                {
-                 $$ = mkmagicuf_uprag($2, $3, startlineno);
+                 $$ = mknoinline_uprag($2, startlineno);
                  PREVPATT = NULL; FN = NULL; SAMEFN = 0;
                }
 
-        |  DEFOREST_UPRAGMA qvark END_UPRAGMA
-                {
-                 $$ = mkdeforest_uprag($2, startlineno);
-                 PREVPATT = NULL; FN = NULL; SAMEFN = 0;
+       |  MAGIC_UNFOLDING_UPRAGMA qvark vark END_UPRAGMA
+               {
+                 $$ = mkmagicuf_uprag($2, $3, startlineno);
+                 PREVPATT = NULL; FN = NULL; SAMEFN = 0;
                }
 
        /* end of user-specified pragmas */
@@ -637,8 +665,8 @@ types_and_maybe_ids :
        ;
 
 type_and_maybe_id :
-          type                                 { $$ = mkvspec_ty_and_id($1,mknothing()); }
-       |  type EQUAL qvark                     { $$ = mkvspec_ty_and_id($1,mkjust($3)); }
+          tautype                              { $$ = mkvspec_ty_and_id($1,mknothing()); }
+       |  tautype EQUAL qvark                  { $$ = mkvspec_ty_and_id($1,mkjust($3)); }
 
 
 /**********************************************************************
@@ -649,65 +677,75 @@ type_and_maybe_id :
 *                                                                     *
 **********************************************************************/
 
-/*  "DCOLON context => type" vs "DCOLON type" is a problem,
+/*  "DCOLON context => tautype" vs "DCOLON tautype" is a problem,
     because you can't distinguish between
 
        foo :: (Baz a, Baz a)
        bar :: (Baz a, Baz a) => [a] -> [a] -> [a]
 
-    with one token of lookahead.  The HACK is to have "DCOLON ttype"
-    [tuple type] in the first case, then check that it has the right
+    with one token of lookahead.  The HACK is to have "DCOLON apptype"
+    in the first case, then check that it has the right
     form C a, or (C1 a, C2 b, ... Cn z) and convert it into a
     context.  Blaach!
 */
 
-       /* 1 S/R conflict at DARROW -> shift */
-ctype   : type DARROW type                     { $$ = mkcontext(type2context($1),$3); }
-       | type
-       ;
+/* --------------------------- */
 
-       /* 1 S/R conflict at RARROW -> shift */
-type   :  btype                                { $$ = $1; }
-       |  btype RARROW type                    { $$ = mktfun($1,$3); }
-       ;
+polyatype : atype
+          ;
 
-/* btype is split so we can parse gtyconapp without S/R conflicts */
-btype  :  gtyconapp                            { $$ = $1; }
-       |  ntyconapp                            { $$ = $1; }
-       ;
+polytype : FORALL tyvars1 DOT
+                  apptype DARROW tautype       { $$ = mkforall($2,   type2context($4), $6); }
+         | FORALL tyvars1 DOT tautype           { $$ = mkforall($2,   Lnil,             $4); }
+         |        apptype DARROW tautype       { $$ = mkforall(Lnil, type2context($1), $3); }
+         | tautype
+        ;
 
-ntyconapp: ntycon                              { $$ = $1; }
-       |  ntyconapp atype                      { $$ = mktapp($1,$2); }
-       ;
+/* --------------------------- */
+/* tautype is just a monomorphic type.
+   But it may have nested for-alls if we're in a rank-2 type */
 
-gtyconapp: gtycon                              { $$ = mktname($1); }
-       |  gtyconapp atype                      { $$ = mktapp($1,$2); }
+tautype :  apptype RARROW tautype              { $$ = mktfun($1,$3); }
+       |  apptype                              { $$ = $1; }
        ;
 
+tautypes :  tautype                            { $$ = lsing($1); }
+        |  tautypes COMMA tautype              { $$ = lapp($1,$3); }
+        ;
 
-atype          :  gtycon                               { $$ = mktname($1); }
-       |  ntycon                               { $$ = $1; }
+/* --------------------------- */
+/* apptype: type application */
+
+apptype        :  apptype atype                        { $$ = mktapp($1,$2); }
+       |  atype                                { $$ = $1; }
        ;
 
-ntycon :  tyvar                                { $$ = $1; }
-       |  OPAREN type COMMA types CPAREN       { $$ = mkttuple(mklcons($2,$4)); }
-       |  OBRACK type CBRACK                   { $$ = mktllist($2); }
-       |  OPAREN type CPAREN                   { $$ = $2; }
-        ;
+/* --------------------------- */
+/* atype: an atomic or bracketed type: T, x, [ty], tuple ty */
 
-gtycon :  qtycon
-       |  OPAREN RARROW CPAREN                 { $$ = creategid(-2); }
-       |  OBRACK CBRACK                        { $$ = creategid(-1); }         
-       |  OPAREN CPAREN                        { $$ = creategid(0); }         
-       |  OPAREN commas CPAREN                 { $$ = creategid($2); }
-       ;
+atypes :  atype                                        { $$ = lsing($1); }
+         |  atype atypes                       { $$ = mklcons($1,$2); }
+         ;
+
+atype   :  gtycon                              { $$ = mktname($1); }
+       |  tyvar                                { $$ = mknamedtvar($1); }
 
-atypes :  atype                                { $$ = lsing($1); }
-       |  atypes atype                         { $$ = lapp($1,$2); }
+       |  OPAREN tautype COMMA
+                 tautypes CPAREN               { $$ = mkttuple(mklcons($2,$4)); }
+
+       |  OUNBOXPAREN tautype COMMA 
+                      tautypes CUNBOXPAREN     { $$ = mktutuple(mklcons($2,$4)); }
+
+       |  OBRACK tautype CBRACK                { $$ = mktllist($2); }
+        |  OPAREN polytype CPAREN              { $$ = $2; }
        ;
 
-types  :  type                                 { $$ = lsing($1); }
-       |  types COMMA type                     { $$ = lapp($1,$3); }
+/* --------------------------- */
+gtycon :  qtycon
+       |  OPAREN RARROW CPAREN                 { $$ = creategid(ARROWGID); }
+       |  OBRACK CBRACK                        { $$ = creategid(NILGID); }         
+       |  OPAREN CPAREN                        { $$ = creategid(UNITGID); }         
+       |  OPAREN commas CPAREN                 { $$ = creategid($2); }
        ;
 
 commas : COMMA                                 { $$ = 1; }
@@ -722,69 +760,94 @@ commas    : COMMA                                 { $$ = 1; }
 *                                                                     *
 **********************************************************************/
 
-simple :  gtycon                               { $$ = mktname($1); }
-       |  gtyconvars                           { $$ = $1; }
+/* C a b c, where a,b,c are type variables */
+/* C can be a class or tycon */
+simple_con_app: gtycon                          { $$ = mktname($1); }
+        |  simple_con_app1                      { $$ = $1; }
+       ;
+   
+simple_con_app1:  gtycon tyvar                 { $$ = mktapp(mktname($1),mknamedtvar($2)); }
+       |  simple_con_app tyvar                 { $$ = mktapp($1, mknamedtvar($2)); } 
        ;
 
-gtyconvars: gtycon tyvar                       { $$ = mktapp(mktname($1),$2); }
-       |  gtyconvars tyvar                     { $$ = mktapp($1,$2); }
+simple_context :  OPAREN simple_context_list CPAREN            { $$ = $2; }
+       |  simple_con_app1                                      { $$ = lsing($1); }
        ;
 
-context        :  OPAREN context_list CPAREN           { $$ = $2; }
-       |  class                                { $$ = lsing($1); }
+simple_context_list:  simple_con_app1                          { $$ = lsing($1); }
+       |  simple_context_list COMMA simple_con_app1            { $$ = lapp($1,$3); }
        ;
 
-context_list:  class                           { $$ = lsing($1); }
-       |  context_list COMMA class             { $$ = lapp($1,$3); }
+constrs        :  constr                               { $$ = lsing($1); }
+       |  constrs VBAR constr                  { $$ = lapp($1,$3); }
        ;
 
-class  :  gtycon tyvar                         { $$ = mktapp(mktname($1),$2); }
+constr :  forall constr_context DARROW constr_after_context    { $$ = mkconstrex ( $1, $2, $4 ); }
+        |  forall constr_after_context                         { $$ = mkconstrex ( $1, Lnil, $2 ); }
        ;
 
-constrs        :  constr                               { $$ = lsing($1); }
-       |  constrs VBAR constr                  { $$ = lapp($1,$3); }
+forall :                                                { $$ = Lnil }
+       | FORALL tyvars1 DOT                             { $$ = $2; }
+       ;
+
+constr_context
+       : conapptype conargatype        { $$ = type2context( mktapp($1,$2) ); }
+       | conargatype                   { $$ = type2context( $1 ); }
        ;
 
-constr :  btyconapp                            { qid tyc; list tys;
+constr_after_context :
+
+       /* We have to parse the constructor application as a *type*, else we get
+          into terrible ambiguity problems.  Consider the difference between
+
+               data T = S Int Int Int `R` Int
+          and
+               data T = S Int Int Int
+       
+          It isn't till we get to the operator that we discover that the "S" is
+          part of a type in the first, but part of a constructor application in the
+          second.
+       */
+
+/* Con !Int (Tree a) */
+          conapptype                           { qid tyc; list tys;
                                                  splittyconapp($1, &tyc, &tys);
                                                  $$ = mkconstrpre(tyc,tys,hsplineno); }
-       |  OPAREN qconsym CPAREN                { $$ = mkconstrpre($2,Lnil,hsplineno); }
-       |  OPAREN qconsym CPAREN batypes        { $$ = mkconstrpre($2,$4,hsplineno); }
-       |  btyconapp qconop bbtype              { checknobangs($1);
-                                                 $$ = mkconstrinf($1,$2,$3,hsplineno); }
-       |  ntyconapp qconop bbtype              { $$ = mkconstrinf($1,$2,$3,hsplineno); }
-       |  BANG atype qconop bbtype             { $$ = mkconstrinf(mktbang($2),$3,$4,hsplineno); }
 
-       /* 1 S/R conflict on OCURLY -> shift */
-       |  gtycon OCURLY fields CCURLY          { $$ = mkconstrrec($1,$3,hsplineno); }
-       ;
+/* (::) (Tree a) Int */
+       |  OPAREN qconsym CPAREN conargatypes   { $$ = mkconstrpre($2,$4,hsplineno); }
 
-btyconapp: gtycon                              { $$ = mktname($1); }
-       |  btyconapp batype                     { $$ = mktapp($1,$2); }
-       ;
+/* !Int `Con` Tree a */
+       |  conargatype qconop conargatype       { $$ = mkconstrinf($1,$2,$3,hsplineno); }
 
-bbtype :  btype                                { $$ = $1; }
-       |  BANG atype                           { $$ = mktbang($2); }
+/* Con { op1 :: Int } */
+       | qtycon OCURLY fields CCURLY           { $$ = mkconstrrec($1,$3,hsplineno); }
+       | OPAREN qconsym CPAREN OCURLY fields CCURLY { $$ = mkconstrrec($2,$5,hsplineno); }
        ;
+               /* 1 S/R conflict on OCURLY -> shift */
 
-batype :  atype                                { $$ = $1; }
-       |  BANG atype                           { $$ = mktbang($2); }
-       ;
 
-batypes        :  batype                               { $$ = lsing($1); }
-       |  batypes batype                       { $$ = lapp($1,$2); }
-       ;
+conapptype : gtycon                            { $$ = mktname($1); }
+          | conapptype conargatype             { $$ = mktapp($1, $2); }
+          ;
 
+conargatype : polyatype                                { $$ = $1; }
+           | BANG polyatype                    { $$ = mktbang( $2 ); }
+           ;
+
+conargatypes :                                 { $$ = Lnil; }
+         |  conargatype conargatypes           { $$ = mklcons($1,$2); }
+         ;
 
 fields : field                                 { $$ = lsing($1); }
        | fields COMMA field                    { $$ = lapp($1,$3); }
        ;
 
-field  :  qvars_list DCOLON type               { $$ = mkfield($1,$3); }
-       |  qvars_list DCOLON BANG atype         { $$ = mkfield($1,mktbang($4)); }
+field  :  qvars_list DCOLON polytype           { $$ = mkfield($1,$3); }
+       |  qvars_list DCOLON BANG polyatype     { $$ = mkfield($1,mktbang($4)); }
        ; 
 
-constr1 :  gtycon atype                                { $$ = lsing(mkconstrnew($1,$2,hsplineno)); }
+constr1 :  gtycon conargatype                  { $$ = lsing(mkconstrnew($1,$2,hsplineno)); }
        ;
 
 
@@ -825,6 +888,12 @@ instdef :
                  PREVPATT = NULL; FN = NULL; SAMEFN = 0;
                }
 
+       |  NOINLINE_UPRAGMA qvark END_UPRAGMA
+               {
+                 $$ = mknoinline_uprag($2, startlineno);
+                 PREVPATT = NULL; FN = NULL; SAMEFN = 0;
+               }
+
        |  MAGIC_UNFOLDING_UPRAGMA qvark vark END_UPRAGMA
                {
                  $$ = mkmagicuf_uprag($2, $3, startlineno);
@@ -836,6 +905,7 @@ instdef :
 
 
 valdef :  vallhs
+
                {
                  tree fn = function($1);
                  PREVPATT = $1;
@@ -860,22 +930,27 @@ valdef    :  vallhs
 #else
                    fprintf(stderr,"%u\tvaldef\n",startlineno);
 #endif
-               }
+               }       
+
+          get_line_no
           valrhs
                {
                  if ( lhs_is_patt($1) )
                    {
-                     $$ = mkpbind($3, startlineno);
+                     $$ = mkpbind($4, $3);
                      FN = NULL;
                      SAMEFN = 0;
                    }
                  else
-                   $$ = mkfbind($3,startlineno);
+                   $$ = mkfbind($4, $3);
 
                  PREVPATT = NULL;
                }
        ;
 
+get_line_no :                                  { $$ = startlineno; }
+           ;
+
 vallhs  : patk                                 { $$ = $1; }
        | patk qvarop pat                       { $$ = mkinfixap($2,$1,$3); }
        | funlhs                                { $$ = $1; }
@@ -900,10 +975,12 @@ gdrhs     :  gd EQUAL exp                         { $$ = lsing(mkpgdexp($1,$3)); }
 maybe_where:
           WHERE ocurly decls ccurly            { $$ = $3; }
        |  WHERE vocurly decls vccurly          { $$ = $3; }
+           /* A where containing no decls is OK */
+       |  WHERE SEMI                           { $$ = mknullbind(); }
        |  /* empty */                          { $$ = mknullbind(); }
        ;
 
-gd     :  VBAR oexp                            { $$ = $2; }
+gd     :  VBAR quals                           { $$ = $2; }
        ;
 
 
@@ -915,7 +992,7 @@ gd  :  VBAR oexp                            { $$ = $2; }
 *                                                                     *
 **********************************************************************/
 
-exp    :  oexp DCOLON ctype                    { $$ = mkrestr($1,$3); }
+exp    :  oexp DCOLON polytype                 { $$ = mkrestr($1,$3); }
        |  oexp
        ;
 
@@ -923,7 +1000,7 @@ exp        :  oexp DCOLON ctype                    { $$ = mkrestr($1,$3); }
   Operators must be left-associative at the same precedence for
   precedence parsing to work.
 */
-       /* 9 S/R conflicts on qop -> shift */
+       /* 8 S/R conflicts on qop -> shift */
 oexp   :  oexp qop oexp %prec MINUS            { $$ = mkinfixap($2,$1,$3); }
        |  dexp
        ;
@@ -938,10 +1015,10 @@ dexp     :  MINUS kexp                           { $$ = mknegate($2); }
 
 /*
   We need to factor out a leading let expression so we can set
-  inpat=TRUE when parsing (non let) expressions inside stmts and quals
+  pat_check=FALSE when parsing (non let) expressions inside stmts and quals
 */
-expLno         :  oexpLno DCOLON ctype                 { $$ = mkrestr($1,$3); }
-       |  oexpLno
+expLno         : oexpLno DCOLON polytype               { $$ = mkrestr($1,$3); }
+       | oexpLno
        ;
 oexpLno        :  oexpLno qop oexp %prec MINUS         { $$ = mkinfixap($2,$1,$3); }
        |  dexpLno
@@ -950,7 +1027,7 @@ dexpLno    :  MINUS kexp                           { $$ = mknegate($2); }
        |  kexpLno
        ;
 
-expL   :  oexpL DCOLON ctype                   { $$ = mkrestr($1,$3); }
+expL   :  oexpL DCOLON polytype                { $$ = mkrestr($1,$3); }
        |  oexpL
        ;
 oexpL  :  oexpL qop oexp %prec MINUS           { $$ = mkinfixap($2,$1,$3); }
@@ -965,9 +1042,11 @@ kexp      :  kexpL
        |  kexpLno
        ;
 
+/* kexpL = a let expression */
 kexpL  :  letdecls IN exp                      { $$ = mklet($1,$3); }
        ;
 
+/* kexpLno = any other expression more tightly binding than operator application */
 kexpLno        :  LAMBDA
                { hsincindent();        /* push new context for FN = NULL;        */
                  FN = NULL;            /* not actually concerned about indenting */
@@ -1006,7 +1085,17 @@ kexpLno  :  LAMBDA
        /* SCC Expression */
        |  SCC STRING exp
                { if (ignoreSCC) {
-                   $$ = $3;
+                   if (warnSCC) {
+                       fprintf(stderr,
+                               "\"%s\":%d: _scc_ (`set [profiling] cost centre') ignored\n",
+                               input_filename, hsplineno);
+                   }
+                   $$ = mkpar($3);     /* Note the mkpar().  If we don't have it, then
+                                          (x >> _scc_ y >> z) parses as (x >> (y >> z)),
+                                          right associated.  But the precedence reorganiser expects
+                                          the parser to *left* associate all operators unless there
+                                          are explicit parens.  The _scc_ acts like an explicit paren,
+                                          so if we omit it we'd better add explicit parens instead. */
                  } else {
                    $$ = mkscc($2, $3);
                  }
@@ -1023,16 +1112,15 @@ aexp    :  qvar                                 { $$ = mkident($1); }
        |  gcon                                 { $$ = mkident($1); }
        |  lit_constant                         { $$ = mklit($1); }
        |  OPAREN exp CPAREN                    { $$ = mkpar($2); }         /* mkpar: stop infix parsing at ()'s */
-       |  qcon OCURLY CCURLY                   { $$ = mkrecord($1,Lnil); }
        |  qcon OCURLY rbinds CCURLY            { $$ = mkrecord($1,$3); }   /* 1 S/R conflict on OCURLY -> shift */
        |  OBRACK list_exps CBRACK              { $$ = mkllist($2); }
-       |  OPAREN exp COMMA texps CPAREN        { if (ttree($4) == tuple)
-                                                    $$ = mktuple(mklcons($2, gtuplelist((struct Stuple *) $4)));
-                                                 else
-                                                    $$ = mktuple(ldub($2, $4)); }
+       |  OPAREN exp COMMA texps CPAREN        { $$ = mktuple(mklcons($2,$4)); }
+        /* unboxed tuples */
+       |  OUNBOXPAREN exp COMMA texps CUNBOXPAREN 
+                                               { $$ = mkutuple(mklcons($2,$4)); }
 
        /* only in expressions ... */
-       |  aexp OCURLY rbinds CCURLY            { $$ = mkrupdate($1,$3); }
+       |  aexp OCURLY rbinds1 CCURLY           { $$ = mkrupdate($1,$3); }
        |  OBRACK exp VBAR quals CBRACK         { $$ = mkcomprh($2,$4); }
        |  OBRACK exp COMMA exp DOTDOT exp CBRACK {$$= mkeenum($2,mkjust($4),mkjust($6)); }
        |  OBRACK exp COMMA exp DOTDOT CBRACK   { $$ = mkeenum($2,mkjust($4),mknothing()); }
@@ -1056,34 +1144,43 @@ cexps   :  cexps aexp                           { $$ = lapp($1,$2); }
 caserest:  ocurly alts ccurly                  { $$ = $2; }
        |  vocurly alts vccurly                 { $$ = $2; }
 
-dorest  :  ocurly stmts ccurly                 { checkdostmts($2); $$ = $2; }
+dorest  :  ocurly stmts ccurly                 { checkdostmts($2); $$ = $2; }
        |  vocurly stmts vccurly                { checkdostmts($2); $$ = $2; }
        ;
 
-rbinds :  rbind                                { $$ = lsing($1); }
-       |  rbinds COMMA rbind                   { $$ = lapp($1,$3); }
+rbinds :  /* empty */                          { $$ = Lnil; }
+       |  rbinds1
+       ;
+
+rbinds1        :  rbind                                { $$ = lsing($1); }
+       |  rbinds1 COMMA rbind                  { $$ = lapp($1,$3); }
        ;
 
 rbind          :  qvar                                 { $$ = mkrbind($1,mknothing()); }
        |  qvar EQUAL exp                       { $$ = mkrbind($1,mkjust($3)); }
-       ;
+;      
 
-texps  :  exp  { $$ = mkpar($1); }     /* mkpar: so we don't flatten last element in tuple */
-       |  exp COMMA texps
-               { if (ttree($3) == tuple)
-                   $$ = mktuple(mklcons($1, gtuplelist((struct Stuple *) $3)));
-                 else if (ttree($3) == par)
-                   $$ = mktuple(ldub($1, gpare((struct Spar *) $3)));
-                 else
-                   hsperror("hsparser:texps: panic");
-               }
+texps  :  exp                                  { $$ = lsing($1); }
+       |  exp COMMA texps                      { $$ = mklcons($1, $3) }
        /* right recursion? WDP */
        ;
 
-
 list_exps :
           exp                                  { $$ = lsing($1); }
+       |  exp COMMA exp                        { $$ = mklcons( $1, lsing($3) ); }
+       |  exp COMMA exp COMMA list_rest        { $$ = mklcons( $1, mklcons( $3, reverse_list( $5 ))); }
+       ;
+
+/* Use left recusion for list_rest, because we sometimes get programs with
+   very long explicit lists. */
+list_rest :    exp                             { $$ = lsing($1); }
+         | list_rest COMMA exp                 { $$ = mklcons( $3, $1 ); }
+         ;
+
+/* 
+          exp                                  { $$ = lsing($1); }
        |  exp COMMA list_exps          { $$ = mklcons($1, $3); }
+*/
        /* right recursion? (WDP)
 
           It has to be this way, though, otherwise you
@@ -1095,27 +1192,57 @@ list_exps :
           (In fact, if you change the grammar and throw yacc/bison
           at it, it *will* do the wrong thing [WDP 94/06])
        */
-       ;
 
-letdecls:  LET ocurly decls ccurly             { $$ = $3 }
-       |  LET vocurly decls vccurly            { $$ = $3 }
+letdecls:  LET { pat_check = TRUE; } ocurly decls ccurly               { $$ = $4; }
+       |  LET { pat_check = TRUE; } vocurly decls vccurly              { $$ = $4; }
        ;
 
-quals  :  qual                                 { $$ = lsing($1); }
-       |  quals COMMA qual                     { $$ = lapp($1,$3); }
+/*
+ When parsing patterns inside do stmt blocks or quals, we have
+ to tentatively parse them as expressions, since we don't know at
+ the time of parsing `p' whether it will be part of "p <- e" (pat)
+ or "p" (expr). When we eventually can tell the difference, the parse
+ of `p' is examined to see if it consitutes a syntactically legal pattern
+ or expression.
+
+ The expr rule used to parse the pattern/expression do contain
+ pattern-special productions (e.g., _ , a@pat, etc.), which are
+ illegal in expressions. Since we don't know whether what
+ we're parsing is an expression rather than a pattern, we turn off
+ the check and instead do it later.
+ The rather clumsy way that this check is turned on/off is there
+ to work around a Bison feature/shortcoming. Turning the flag 
+ on/off just around the relevant nonterminal by decorating it
+ with simple semantic actions, e.g.,
+
+    {pat_check = FALSE; } expLNo { pat_check = TRUE; }
+
+ causes Bison to generate a parser where in one state it either
+ has to reduce/perform a semantic action ( { pat_check = FALSE; })
+ or reduce an error (the error production used to implement
+ vccurly.) Bison picks the semantic action, which it ideally shouldn't.
+ The work around is to lift out the setting of { pat_check = FALSE; }
+ and then later reset pat_check. Not pretty.
+
+*/
+
+
+quals  :  { pat_check = FALSE;} qual              { pat_check = TRUE; $$ = lsing($2); }
+       |  quals COMMA { pat_check = FALSE; } qual { pat_check = TRUE; $$ = lapp($1,$4); }
        ;
 
-qual   :  letdecls                             { $$ = mkseqlet($1); }
-       |  expL                                 { $$ = $1; }
-       |  {inpat=TRUE;} expLno {inpat=FALSE;}leftexp
-               { if ($4 == NULL) {
-                     expORpat(LEGIT_EXPR,$2);
-                     $$ = mkguard($2);
-                 } else {
-                     expORpat(LEGIT_PATT,$2);
-                     $$ = mkqual($2,$4);
-                 }
-               }
+qual   :  letdecls                             { $$ = mkseqlet($1); }
+       |  expL                                 { expORpat(LEGIT_EXPR,$1); $$ = $1; }
+       |  expLno { pat_check = TRUE; } leftexp
+                                               { if ($3 == NULL) {
+                                                    expORpat(LEGIT_EXPR,$1);
+                                                    $$ = mkguard($1);
+                                                 } else {
+                                                    expORpat(LEGIT_PATT,$1);
+                                                    $$ = mkqual($1,$3);
+                                                 }
+                                               }
        ;
 
 alts   :  alt                                  { $$ = $1; }
@@ -1134,24 +1261,25 @@ gdpat   :  gd RARROW exp                        { $$ = lsing(mkpgdexp($1,$3)); }
        |  gd RARROW exp gdpat                  { $$ = mklcons(mkpgdexp($1,$3),$4);  }
        ;
 
-stmts  :  stmt                                 { $$ = $1; }
-       |  stmts SEMI stmt                      { $$ = lconc($1,$3); }
+stmts  :  {pat_check = FALSE;} stmt          {pat_check=TRUE; $$ = $2; }
+       |  stmts SEMI {pat_check=FALSE;} stmt {pat_check=TRUE; $$ = lconc($1,$4); }
        ;
 
-stmt   :  /* empty */                          { $$ = Lnil; }
-       |  letdecls                             { $$ = lsing(mkseqlet($1)); }
-       |  expL                                 { $$ = lsing($1); }
-       |  {inpat=TRUE;} expLno {inpat=FALSE;} leftexp
-               { if ($4 == NULL) {
-                     expORpat(LEGIT_EXPR,$2);
-                     $$ = lsing(mkdoexp($2,endlineno));
-                 } else {
-                     expORpat(LEGIT_PATT,$2);
-                     $$ = lsing(mkdobind($2,$4,endlineno));
-                 }
-               }
+stmt   : /* empty */                           { $$ = Lnil; } 
+       | letdecls                              { $$ = lsing(mkseqlet($1)); }
+       | expL                                  { expORpat(LEGIT_EXPR,$1); $$ = lsing(mkdoexp($1,hsplineno)); }
+       | expLno {pat_check=TRUE;} leftexp
+                                               { if ($3 == NULL) {
+                                                    expORpat(LEGIT_EXPR,$1);
+                                                    $$ = lsing(mkdoexp($1,endlineno));
+                                                 } else {
+                                                    expORpat(LEGIT_PATT,$1);
+                                                    $$ = lsing(mkdobind($1,$3,endlineno));
+                                                 }
+                                               }
        ;
 
+
 leftexp        :  LARROW exp                           { $$ = $2; }
         |  /* empty */                         { $$ = NULL; }
        ;
@@ -1164,13 +1292,17 @@ leftexp :  LARROW exp                           { $$ = $2; }
 *                                                                     *
 **********************************************************************/
 
-pat    :  pat qconop bpat                      { $$ = mkinfixap($2,$1,$3); }
+pat    :  qvar PLUS INTEGER                    { $$ = mkplusp($1, mkinteger($3)); }
+       |  cpat
+       ;
+
+cpat   :  cpat qconop bpat                     { $$ = mkinfixap($2,$1,$3); }
        |  bpat
        ;
 
 bpat   :  apatc
        |  conpat
-       |  qcon OCURLY rpats CCURLY             { $$ = mkrecord($1,$3); }
+       |  qcon OCURLY rpats CCURLY             { $$ = mkrecord($1,$3); }
        |  MINUS INTEGER                        { $$ = mknegate(mklit(mkinteger($2))); }
        |  MINUS FLOAT                          { $$ = mknegate(mklit(mkfloatr($2))); }
        ;
@@ -1190,6 +1322,7 @@ apatc     :  qvar                                 { $$ = mkident($1); }
        |  WILDCARD                             { $$ = mkwildp(); }
        |  OPAREN pat CPAREN                    { $$ = mkpar($2); }
        |  OPAREN pat COMMA pats CPAREN         { $$ = mktuple(mklcons($2,$4)); }
+       |  OUNBOXPAREN pat COMMA pats CUNBOXPAREN { $$ = mkutuple(mklcons($2,$4)); }
        |  OBRACK pats CBRACK                   { $$ = mkllist($2); }
        |  LAZY apat                            { $$ = mklazyp($2); }
        ;
@@ -1217,8 +1350,12 @@ pats     :  pat COMMA pats                       { $$ = mklcons($1, $3); }
        /* right recursion? (WDP) */
        ;
 
-rpats  : rpat                                  { $$ = lsing($1); }
-       | rpats COMMA rpat                      { $$ = lapp($1,$3); }
+rpats  : /* empty */                           { $$ = Lnil; }
+       | rpats1
+       ;
+
+rpats1 : rpat                                  { $$ = lsing($1); }
+       | rpats1 COMMA rpat                     { $$ = lapp($1,$3); }
        ;
 
 rpat   :  qvar                                 { $$ = mkrbind($1,mknothing()); }
@@ -1247,20 +1384,22 @@ apatck  :  qvark                                { $$ = mkident($1); }
        |  WILDCARD                             { $$ = mkwildp(); setstartlineno(); }
        |  oparenkey pat CPAREN                 { $$ = mkpar($2); }
        |  oparenkey pat COMMA pats CPAREN      { $$ = mktuple(mklcons($2,$4)); }
+       |  ounboxparenkey pat COMMA pats CUNBOXPAREN
+                                               { $$ = mkutuple(mklcons($2,$4)); }
        |  obrackkey pats CBRACK                { $$ = mkllist($2); }
        |  lazykey apat                         { $$ = mklazyp($2); }
        ;
 
 
 gcon   :  qcon
-       |  OBRACK CBRACK                        { $$ = creategid(-1); }
-       |  OPAREN CPAREN                        { $$ = creategid(0); }
+       |  OBRACK CBRACK                        { $$ = creategid(NILGID); }
+       |  OPAREN CPAREN                        { $$ = creategid(UNITGID); }
        |  OPAREN commas CPAREN                 { $$ = creategid($2); }
        ;
 
 gconk  :  qconk
-       |  obrackkey CBRACK                     { $$ = creategid(-1); }
-       |  oparenkey CPAREN                     { $$ = creategid(0); }
+       |  obrackkey CBRACK                     { $$ = creategid(NILGID); }
+       |  oparenkey CPAREN                     { $$ = creategid(UNITGID); }
        |  oparenkey commas CPAREN              { $$ = creategid($2); }
        ;
 
@@ -1272,7 +1411,8 @@ gconk     :  qconk
 *                                                                     *
 **********************************************************************/
 
-importkey:  IMPORT     { setstartlineno(); }
+importkey: IMPORT               { setstartlineno(); $$ = 0; }
+        |  IMPORT SOURCE_UPRAGMA { setstartlineno(); $$ = 1; }
        ;
 
 datakey        :   DATA        { setstartlineno();
@@ -1319,6 +1459,9 @@ instkey   :   INSTANCE    { setstartlineno();
 defaultkey: DEFAULT    { setstartlineno(); }
        ;
 
+foreignkey: FOREIGN             { setstartlineno();  }
+         ;
+
 classkey:   CLASS      { setstartlineno();
                          if(etags)
 #if 1/*etags*/
@@ -1342,6 +1485,9 @@ modulekey:  MODULE        { setstartlineno();
 oparenkey:  OPAREN     { setstartlineno(); }
        ;
 
+ounboxparenkey: OUNBOXPAREN { setstartlineno(); }
+        ;
+
 obrackkey:  OBRACK     { setstartlineno(); }
        ;
 
@@ -1437,32 +1583,49 @@ varsym  :  varsym_nominus
        |  MINUS                        { $$ = install_literal("-"); }
        ;
 
+/* PLUS, BANG are valid varsyms */
+varsym_nominus : VARSYM
+       |  PLUS                         { $$ = install_literal("+"); }
+       |  BANG                         { $$ = install_literal("!"); }  
+       |  DOT                          { $$ = install_literal("."); }
+       ;
+
 /* AS HIDING QUALIFIED are valid varids */
-varid   :  VARID
+varid   :  varid_noforall
+        |  FORALL                       { $$ = install_literal("forall"); }
+       ;
+
+varid_noforall
+       :  VARID
        |  AS                           { $$ = install_literal("as"); }
        |  HIDING                       { $$ = install_literal("hiding"); }
        |  QUALIFIED                    { $$ = install_literal("qualified"); }
-       ;
-
-/* DARROW BANG are valid varsyms */
-varsym_nominus : VARSYM
-       |  DARROW                       { $$ = install_literal("=>"); }
-       |  BANG                         { $$ = install_literal("!"); }  
+/* The rest of these guys are used by the FFI decls, a ghc (and hugs) extension. */
+       |  EXPORT                       { $$ = install_literal("export"); }
+       |  UNSAFE                       { $$ = install_literal("unsafe"); }
+       |  DYNAMIC                      { $$ = install_literal("dynamic"); }
+       |  LABEL                        { $$ = install_literal("label"); }
+       |  C_CALL                       { $$ = install_literal("ccall"); }
+       |  STDCALL                      { $$ = install_literal("stdcall"); }
+       |  PASCAL                       { $$ = install_literal("pascal"); }
        ;
 
 ccallid        :  VARID
        |  CONID
        ;
 
-tyvar  :  varid                        { $$ = mknamedtvar(mknoqual($1)); }
-       ;
 tycon  :  CONID
        ;
 modid  :  CONID
        ;
 
-tyvar_list: tyvar                      { $$ = lsing($1); }
-       |  tyvar_list COMMA tyvar       { $$ = lapp($1,$3); }
+/* ---------------------------------------------- */
+tyvar  :  varid_noforall               { $$ = $1; }
+       ;
+
+/* tyvars1: At least one tyvar */
+tyvars1 : tyvar                                { $$ = lsing($1); }
+       | tyvar tyvars1                 { $$ = mklcons($1,$2); }
        ;
 
 /**********************************************************************
@@ -1504,7 +1667,7 @@ vccurly1:
                  FN = NULL; SAMEFN = 0; PREVPATT = NULL;
                  hsendindent();
                }
-       ;
+       ;
 
 %%
 
@@ -1516,14 +1679,14 @@ vccurly1:
 *                                                                     *
 **********************************************************************/
 
+
 void
 checkinpat()
 {
-  if(!inpat)
+  if(pat_check)
     hsperror("pattern syntax used in expression");
 }
 
-
 /* The parser calls "hsperror" when it sees a
    `report this and die' error.  It sets the stage
    and calls "yyerror".
@@ -1559,11 +1722,11 @@ yyerror(s)
     /* We want to be able to distinguish 'error'-raised yyerrors
        from yyerrors explicitly coded by the parser hacker.
     */
-    if (expect_ccurly && ! error_and_I_mean_it ) {
+    if ( expect_ccurly && ! error_and_I_mean_it ) {
        /*NOTHING*/;
 
     } else {
-       fprintf(stderr, "\"%s\", line %d, column %d: %s on input: ",
+       fprintf(stderr, "%s:%d:%d: %s on input: ",
          input_filename, hsplineno, hspcolno + 1, s);
 
        if (yyleng == 1 && *yytext == '\0')