[project @ 1999-01-26 11:12:41 by simonm]
[ghc-hetmet.git] / ghc / compiler / parser / syntax.c
index fec0ae8..244e694 100644 (file)
@@ -13,6 +13,7 @@
 #include "constants.h"
 #include "utils.h"
 #include "tree.h"
+#include "list.h"
 
 #include "hsparser.tab.h"
 
@@ -62,17 +63,37 @@ checkfixity(vals)
 
 
 /*
-  Check Previous Pattern usage
+  We've found a function definition.  See if it defines the
+  same function as the previous definition (at this indentation level).
+  If so, set SAMEFN.
+  Set FN to the name of the function.
 */
 
 void
-checksamefn(fn)
-  qid fn;
+checksamefn(lhs)
+  tree lhs;
 {
-  char *this = qid_to_string(fn);
-  char *was  = (FN==NULL) ? NULL : qid_to_string(FN);
+  tree fn;
+  qid  fn_id;
+  char *this, *was;
+
+  fn = function(lhs);
+
+  if (ttree(fn) == ident) {
+      fn_id = gident((struct Sident *) fn);
+  }
+  else if (ttree(fn) == infixap)  {
+      fn_id = ginffun((struct Sinfixap *) fn); 
+  }
+  else {
+    fprintf( stderr, "Wierd funlhs" );
+    return;
+  }
 
+  this   = qid_to_string(fn_id);
+  was    = (FN==NULL) ? NULL : qid_to_string(FN);
   SAMEFN = (was != NULL && strcmp(this,was) == 0);
+  FN     = fn_id;
 
   if(!SAMEFN && etags)
 #if 1/*etags*/
@@ -108,6 +129,9 @@ expORpat(int wanted, tree e)
        expORpat(wanted, glazyp(e));
        break;
 
+      case plusp:
+       break;
+
       case lit:
        switch (tliteral(glit(e))) {
          case integer:
@@ -123,6 +147,7 @@ expORpat(int wanted, tree e)
 
          case clitlit:
            error_if_patt_wanted(wanted, "``literal-literal'' in pattern");
+           break;
 
          default: /* the others only occur in pragmas */
            hsperror("not a valid literal pattern or expression");
@@ -192,6 +217,15 @@ expORpat(int wanted, tree e)
        }
        break;
 
+      case utuple:
+       {
+         list tup;
+         for (tup = gutuplelist(e); tlist(tup) == lcons; tup = ltl(tup)) {
+             expORpat(wanted, lhd(tup));
+         }
+       }
+       break;
+
       case llist:
        {
          list l;
@@ -201,11 +235,14 @@ expORpat(int wanted, tree e)
        }
        break;
 
+      case restr: /* type sig */
+        expORpat(wanted, grestre(e));
+        break;
+
       case par: /* parenthesised */
        expORpat(wanted, gpare(e));
        break;
 
-      case restr:
       case lambda:
       case let:
       case casee:
@@ -284,6 +321,7 @@ error_if_patt_wanted(int wanted, char *msg)
 
 /* ---------------------------------------------------------------------- */
 
+
 BOOLEAN /* return TRUE if LHS is a pattern */
 lhs_is_patt(tree e)
 {
@@ -313,6 +351,7 @@ lhs_is_patt(tree e)
       case llist:
       case tuple:
       case negate:
+      case record:
        expORpat(LEGIT_PATT, e);
        return TRUE;
 
@@ -322,13 +361,17 @@ lhs_is_patt(tree e)
       case ap:
        {
          tree f = function(e);
-         tree a = garg(e);       /* do not "unparen", otherwise the error
-                                      fromInteger ((x,y) {-no comma-} z)
-                                    will be missed.
-                                 */
 
-         /* definitions must have pattern arguments */
+/*  These lines appear to duplicate what's in function(e).
+    Nuked SLPJ May 97
+       
+         tree a = garg(e);       -- do not "unparen", otherwise the error
+                                 --     fromInteger ((x,y) {-no comma-} z)
+                                 --   will be missed.
+
+         -- definitions must have pattern arguments
          expORpat(LEGIT_PATT, a);
+*/
 
          if(ttree(f) == ident)
            return(isconstr(qid_to_string(gident(f))));
@@ -337,7 +380,7 @@ lhs_is_patt(tree e)
            return(lhs_is_patt(f));
 
          else
-           hsperror("Not a legal pattern binding in LHS");
+           hsperror("Syntax error: not a legal pattern binding in LHS");
        }
 
       case infixap:
@@ -358,7 +401,7 @@ lhs_is_patt(tree e)
 
       /* Anything else must be an illegal LHS */
       default:
-       hsperror("Not a valid LHS");
+       hsperror("Syntax error: not a valid LHS");
       }
 
   abort(); /* should never get here */
@@ -367,7 +410,8 @@ lhs_is_patt(tree e)
 
 
 /*
-  Return the function at the root of a series of applications.
+  Return the function at the root of a series of applications,
+  checking on the way that the arguments are patterns.
 */
 
 tree
@@ -413,28 +457,15 @@ binding rule;
   if(tbinding(bind) == abind)
     bind = gabindsnd(bind);
 
-  if(tbinding(bind) == pbind)
+  /*   if(tbinding(bind) == pbind)
     gpbindl(bind) = lconc(gpbindl(bind), gpbindl(rule));
-  else if(tbinding(bind) == fbind)
-    gfbindl(bind) = lconc(gfbindl(bind), gfbindl(rule));
-  else
-    fprintf(stderr,"bind error in decl (%d)\n",tbinding(bind));
-}
-
+  
+    else */
 
-pbinding
-createpat(guards,where)
-  pbinding guards;
-  binding where;
-{
-  qid func;
-
-  if(FN != NULL)
-    func = FN;
+  if(tbinding(bind) == fbind)
+    gfbindm(bind) = lconc(gfbindm(bind), gfbindm(rule));
   else
-    func = mknoqual(install_literal(""));
-
-  return(mkpgrhs(PREVPATT,guards,where,func,endlineno));
+    fprintf(stderr,"bind error in decl (%d)\n",tbinding(bind));
 }
 
 
@@ -529,9 +560,49 @@ checknobangs(app)
        hsperror("syntax error: unexpected ! in type");
 
       checknobangs(gtapp((struct Stapp *)app));
-    }    
+    }
+}
+
+/* Check that a type is of the form
+       C a1 a2 .. an
+   where n>=1, and the ai are all type variables
+   This is used to check that a class decl is well formed.
+*/
+void
+check_class_decl_head_help( app, n )
+  ttype app;
+  int n;       /* Number of args so far */
+{
+  switch (tttype(app)) {
+    case tapp:
+       /* Check the arg is a type variable */
+       switch (tttype (gtarg((struct Stapp *) app))) {
+               case namedtvar: break;
+               default: hsperror("Class declaration head must use only type variables");
+       }
+
+       /* Check the fun part */
+       check_class_decl_head_help( gtapp((struct Stapp *) app), n+1 );
+       break;
+
+    case tname:
+       /* Class name; check there is at least one argument */
+      if (n==0) {
+           hsperror("Class must have at least one argument");
+      }
+      break;
+
+    default:
+       hsperror("Illegal syntax in class declaration head");
+  }
 }
 
+void
+check_class_decl_head( app )
+  ttype app;
+{ check_class_decl_head_help( app, 0 ); }
+
+       
 
 /*
   Splits a tycon application into its constructor and a list of types.
@@ -543,19 +614,20 @@ splittyconapp(app, tyc, tys)
   qid *tyc;
   list *tys;
 {
-  if(tttype(app) == tapp) 
-    {
+  switch (tttype(app)) {
+    case tapp:
       splittyconapp(gtapp((struct Stapp *)app), tyc, tys);
       *tys = lapp(*tys, gtarg((struct Stapp *)app));
-    }
-  else if(tttype(app) == tname)
-    {
+      break;
+
+    case tname:
+    case namedtvar:
       *tyc = gtypeid((struct Stname *)app);
       *tys = Lnil;
-    }
-  else
-    {
-      hsperror("panic: splittyconap: bad tycon application (no tycon)");
+      break;
+
+    default:
+      hsperror("bad left argument to constructor op");
     }
 }
 
@@ -700,3 +772,20 @@ checkprec(exp,qfn,right)
 
 #endif /* 0 */
 
+
+
+/* Reverse a list, in place */
+
+list reverse_list( l )
+  list l;
+{
+  list temp, acc = Lnil;
+
+  while (tlist( l ) != lnil) {
+       temp = ltl( l );
+       ltl( l ) = acc;
+       acc = l;
+       l = temp;
+  }
+  return( acc );
+}