[project @ 1999-12-01 11:50:31 by sewardj]
[ghc-hetmet.git] / ghc / interpreter / input.c
index cc11551..501b5c7 100644 (file)
@@ -2,14 +2,15 @@
 /* --------------------------------------------------------------------------
  * Input functions, lexical analysis parsing etc...
  *
- * Hugs 98 is Copyright (c) Mark P Jones, Alastair Reid and the Yale
- * Haskell Group 1994-99, and is distributed as Open Source software
- * under the Artistic License; see the file "Artistic" that is included
- * in the distribution for details.
+ * The Hugs 98 system is Copyright (c) Mark P Jones, Alastair Reid, the
+ * Yale Haskell Group, and the Oregon Graduate Institute of Science and
+ * Technology, 1994-1999, All rights reserved.  It is distributed as
+ * free software under the license in the file "License", which is
+ * included in the distribution.
  *
  * $RCSfile: input.c,v $
- * $Revision: 1.5 $
- * $Date: 1999/04/27 10:06:53 $
+ * $Revision: 1.15 $
+ * $Date: 1999/12/01 11:50:34 $
  * ------------------------------------------------------------------------*/
 
 #include "prelude.h"
 #include "connect.h"
 #include "command.h"
 #include "errors.h"
+#include "link.h"
 #include <ctype.h>
 #if HAVE_GETDELIM_H
 #include "getdelim.h"
 #endif
 
-#if HUGS_FOR_WINDOWS
+#if IS_WIN32
+#include <windows.h>
+#endif
+
+#if IS_WIN32 || HUGS_FOR_WINDOWS
 #undef IN
 #endif
 
+#if HAVE_LIBREADLINE && HAVE_READLINE_READLINE_H && HAVE_READLINE_HISTORY_H
+#define USE_READLINE 1
+#else
+#define USE_READLINE 0
+#endif
+
+#if USE_READLINE
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif
+
+
 /* --------------------------------------------------------------------------
  * Global data:
  * ------------------------------------------------------------------------*/
 
-List tyconDefns      = NIL;             /* type constructor definitions    */
-List typeInDefns     = NIL;             /* type synonym restrictions       */
-List valDefns        = NIL;             /* value definitions in script     */
-List classDefns      = NIL;             /* class defns in script           */
-List instDefns       = NIL;             /* instance defns in script        */
-List selDefns        = NIL;             /* list of selector lists          */
-List genDefns        = NIL;             /* list of generated names         */
-List unqualImports   = NIL;             /* unqualified import list         */
-List foreignImports  = NIL;             /* foreign imports                 */
-List foreignExports  = NIL;             /* foreign exportsd                */
-List defaultDefns    = NIL;             /* default definitions (if any)    */
-Int  defaultLine     = 0;               /* line in which default defs occur*/
-List evalDefaults    = NIL;             /* defaults for evaluator          */
-
-Cell inputExpr       = NIL;             /* input expression                */
-Bool literateScripts = FALSE;           /* TRUE => default to lit scripts  */
-Bool literateErrors  = TRUE;            /* TRUE => report errs in lit scrs */
+List tyconDefns       = NIL;            /* type constructor definitions    */
+List typeInDefns      = NIL;            /* type synonym restrictions       */
+List valDefns         = NIL;            /* value definitions in script     */
+List classDefns       = NIL;            /* class defns in script           */
+List instDefns        = NIL;            /* instance defns in script        */
+List selDefns         = NIL;            /* list of selector lists          */
+List genDefns         = NIL;            /* list of generated names         */
+List unqualImports    = NIL;            /* unqualified import list         */
+List foreignImports   = NIL;            /* foreign imports                 */
+List foreignExports   = NIL;            /* foreign exportsd                */
+List defaultDefns     = NIL;            /* default definitions (if any)    */
+Int  defaultLine      = 0;              /* line in which default defs occur*/
+List evalDefaults     = NIL;            /* defaults for evaluator          */
+
+Cell inputExpr        = NIL;            /* input expression                */
+Cell inputContext     = NIL;            /* input context                   */
+Bool literateScripts  = FALSE;          /* TRUE => default to lit scripts  */
+Bool literateErrors   = TRUE;           /* TRUE => report errs in lit scrs */
+Bool offsideON        = TRUE;           /* TRUE => implement offside rule  */
+Bool readingInterface = FALSE;
 
 String repeatStr     = 0;               /* Repeat last expr                */
 
@@ -114,15 +135,22 @@ static Text textCase,    textOfK,      textData,   textType,   textIf;
 static Text textThen,    textElse,     textWhere,  textLet,    textIn;
 static Text textInfix,   textInfixl,   textInfixr, textForeign, textNewtype;
 static Text textDefault, textDeriving, textDo,     textClass,  textInstance;
+#if IPARAM
+static Text textWith,  textDlet;
+#endif
 
 static Text textCoco,    textEq,       textUpto,   textAs,     textLambda;
 static Text textBar,     textMinus,    textFrom,   textArrow,  textLazy;
 static Text textBang,    textDot,      textAll,    textImplies;
 static Text textWildcard;
 
-static Text textModule,  textImport;
+static Text textModule,  textImport,    textInterface,  textInstImport;
 static Text textHiding,  textQualified, textAsMod;
-static Text textExport,  textUnsafe;
+static Text textExport,  textDynamic,   textUUExport;
+static Text textUnsafe,  textUUAll;
+
+Text   textCcall;                       /* ccall                           */
+Text   textStdcall;                     /* stdcall                         */
 
 Text   textNum;                         /* Num                             */
 Text   textPrelude;                     /* Prelude                         */
@@ -172,7 +200,7 @@ static  unsigned char   ctable[NUM_CHARS];
 #define LARGE           0x04
 #define SYMBOL          0x08
 #define IDAFTER         0x10
-#define SPACE           0x20
+#define ZPACE           0x20
 #define PRINT           0x40
 
 static Void local initCharTab() {       /* Initialize char decode table    */
@@ -204,9 +232,9 @@ static Void local initCharTab() {       /* Initialize char decode table    */
     setChar (IDAFTER,   '\'');          /* Characters in identifier        */
     setCopy (IDAFTER,   (DIGIT|SMALL|LARGE));
 
-    setChar (SPACE,     ' ');           /* ASCII space character           */
-    setChar (SPACE,     160);           /* ISO non breaking space          */
-    setRange(SPACE,     9,13);          /* special whitespace: \t\n\v\f\r  */
+    setChar (ZPACE,     ' ');           /* ASCII space character           */
+    setChar (ZPACE,     160);           /* ISO non breaking space          */
+    setRange(ZPACE,     9,13);          /* special whitespace: \t\n\v\f\r  */
 
     setChars(PRINT,     "(),;[]_`{}");  /* Special characters              */
     setChars(PRINT,     " '\"");        /* Space and quotes                */
@@ -249,9 +277,8 @@ static String nextStringChar;          /* next char in string buffer       */
 #if     USE_READLINE                   /* for command line editors         */
 static  String currentLine;            /* editline or GNU readline         */
 static  String nextChar;
-#define nextConsoleChar() (unsigned char)(*nextChar=='\0' ? '\n' : *nextChar++)
-extern  Void add_history  Args((String));
-extern  String readline   Args((String));
+#define nextConsoleChar() \
+           (unsigned char)(*nextChar=='\0' ? '\n' : *nextChar++)
 #else
 #define nextConsoleChar() getc(stdin)
 #endif
@@ -398,6 +425,35 @@ String nm; {
 }
 
 
+Void hi_o_namesFromSrcName ( String srcName, String* hiName, String* oName )
+{
+   Int len;
+   String dot;
+   len = 1 + strlen ( srcName );
+   *hiName = malloc(len);
+   *oName  = malloc(len);
+   if (!(*hiName && *oName)) internal("hi_o_namesFromSource");
+   (*hiName)[0] = (*oName)[0] = 0;
+   dot = strrchr(srcName, '.');
+   if (!dot) return;
+   if (filenamecmp(dot+1, "hs")==0 &&
+       filenamecmp(dot+1, "lhs")==0 &&
+       filenamecmp(dot+1, "verb")==0) return;
+
+   strcpy(*hiName, srcName);
+   dot = strrchr(*hiName, '.');
+   dot[1] = 'h';
+   dot[2] = 'i';
+   dot[3] = 0;
+
+   strcpy(*oName, srcName);
+   dot = strrchr(*oName, '.');
+   dot[1] = 'o';
+   dot[2] = 0;
+}
+
+
+
 /* This code originally came from Sigbjorn Finne (sof@dcs.gla.ac.uk).
  * I've removed the loop (since newLineSkip contains a loop too) and
  * replaced the warnings with errors. ADR
@@ -423,7 +479,7 @@ String line; {
     if (s[i] != '\0') {                 /* check s `isPrefixOf` line       */
         return FALSE;
     }
-    while (isIn(line[i], SPACE)) {      /* allow whitespace at end of line */
+    while (isIn(line[i], ZPACE)) {      /* allow whitespace at end of line */
         ++i;
     }
     return (line[i] == '\0');
@@ -449,7 +505,8 @@ static Int local nextLine()
     if (lineLength <= 0) { /* EOF / IO error, who knows.. */
         return lineLength;
     }
-    else if (lineLength >= 2 && lineBuffer[0] == '#' && lineBuffer[1] == '!') {
+    else if (lineLength >= 2 && lineBuffer[0] == '#' && 
+             lineBuffer[1] == '!') {
         lineBuffer[0]='\n'; /* pretend it's a blank line */
         lineBuffer[1]='\0';
         lineLength=1;
@@ -511,11 +568,14 @@ static Void local skip() {              /* move forward one char in input  */
                 c1 = EOF;
             else {
                 c1 = nextConsoleChar();
-                /* On Win32, hitting ctrl-C causes the next getchar to
-                 * fail - returning "-1" to indicate an error.
-                 * This is one of the rare cases where "-1" does not mean EOF.
-                 */
-                if (EOF == c1 && !feof(stdin)) {
+#if IS_WIN32 && !HUGS_FOR_WINDOWS
+               Sleep(0);
+#endif
+               /* On Win32, hitting ctrl-C causes the next getchar to
+                * fail - returning "-1" to indicate an error.
+                * This is one of the rare cases where "-1" does not mean EOF.
+                */
+               if (EOF == c1 && (!feof(stdin) || broken==TRUE)) {
                     c1 = ' ';
                 }
             }
@@ -572,7 +632,7 @@ static Void local newlineSkip() {      /* skip `\n' (supports lit scripts) */
                 litLines++;
                 return;
             }
-            while (c0 != '\n' && isIn(c0,SPACE)) /* maybe line is blank?   */
+            while (c0 != '\n' && isIn(c0,ZPACE)) /* maybe line is blank?   */
                 skip();
             if (c0=='\n' || c0==EOF)
                 thisLineIs(BLANKLINE);
@@ -668,7 +728,9 @@ static Text local readIdent() {        /* read identifier                  */
     } while (isISO(c0) && isIn(c0,IDAFTER));
     endToken();
     identType = isIn(tokenStr[0],LARGE) ? CONID : VARID;
-    return findText(tokenStr);
+    if (readingInterface)
+       return unZcodeThenFindText(tokenStr); else
+       return findText(tokenStr);
 }
 
 
@@ -926,7 +988,7 @@ Bool isStrLit; {
                         ERRMSG(row) "Illegal escape sequence"
                         EEND;
                     }
-                    else if (isIn(c0,SPACE)) {
+                    else if (isIn(c0,ZPACE)) {
                         if (isStrLit) {
                             skipGap();
                             return NIL;
@@ -957,7 +1019,7 @@ static Void local skipGap() {          /* skip over gap in string literal  */
             newlineSkip();
         else
             skip();
-    while (isISO(c0) && isIn(c0,SPACE));
+    while (isISO(c0) && isIn(c0,ZPACE));
     if (c0!='\\') {
         ERRMSG(row) "Missing `\\' terminating string literal gap"
         EEND;
@@ -1087,7 +1149,7 @@ String s; {                            /* escapes if any parts need them   */
         String t = s;                  
         Char   c;                      
         while ((c = *t)!=0 && isISO(c)
-                           && isIn(c,PRINT) && c!='"' && !isIn(c,SPACE)) {
+                           && isIn(c,PRINT) && c!='"' && !isIn(c,ZPACE)) {
             t++;                       
         }
         if (*t) {                      
@@ -1131,7 +1193,7 @@ Char   sys; {                          /* character for shell escape       */
         do {                           /* which is empty                   */
             saveTokenChar(c0);
             skip();
-        } while (c0!=EOF && !isIn(c0,SPACE));
+        } while (c0!=EOF && !isIn(c0,ZPACE));
     endToken();
 
     for (; cmds->cmdString; ++cmds)
@@ -1154,7 +1216,7 @@ String readFilename() {                /* Read filename from input (if any)*/
         return 0;
 
     startToken();
-    while (c0!=EOF && !isIn(c0,SPACE)) {
+    while (c0!=EOF && !isIn(c0,ZPACE)) {
         if (c0=='"') {
             skip();
             while (c0!=EOF && c0!='\"') {
@@ -1215,6 +1277,7 @@ static  Int        indentDepth = (-1); /* current indentation nesting      */
 
 static Void local goOffside(col)       /* insert offside marker            */
 Int col; {                             /* for specified column             */
+    assert(offsideON);
     if (indentDepth>=MAXINDENT) {
         ERRMSG(row) "Too many levels of program nesting"
         EEND;
@@ -1223,10 +1286,12 @@ Int col; {                             /* for specified column             */
 }
 
 static Void local unOffside() {        /* leave layout rule area           */
+    assert(offsideON);
     indentDepth--;
 }
 
 static Bool local canUnOffside() {     /* Decide if unoffside permitted    */
+    assert(offsideON);
     return indentDepth>=0 && layout[indentDepth]!=HARD;
 }
 
@@ -1240,7 +1305,7 @@ static Void local skipWhitespace() {   /* Skip over whitespace/comments    */
             return;                    /* report allows ...                */
         else if (c0=='\n')                                                 
             newlineSkip();                                                 
-        else if (isIn(c0,SPACE))                                           
+        else if (isIn(c0,ZPACE))                                           
             skip();                                                        
         else if (c0=='{' && c1=='-') { /* (potentially) nested comment     */
             Int nesting = 1;                                               
@@ -1298,7 +1363,7 @@ static Int local yylex() {             /* Read next input token ...        */
         return firstTokenIs;
     }
 
-    if (insertOpen) {                  /* insert `soft' opening brace      */
+    if (offsideON && insertOpen) {     /* insert `soft' opening brace      */
         insertOpen    = FALSE;
         insertedToken = TRUE;
         goOffside(column);
@@ -1319,7 +1384,7 @@ static Int local yylex() {             /* Read next input token ...        */
         if (insertedToken)             /* avoid inserting multiple `;'s    */
             insertedToken = FALSE;     /* or putting `;' after `{'         */
         else
-        if (layout[indentDepth]!=HARD) {
+        if (offsideON && layout[indentDepth]!=HARD) {
             if (column<layout[indentDepth]) {
                 unOffside();
                 return '}';
@@ -1346,16 +1411,17 @@ static Int local yylex() {             /* Read next input token ...        */
         case '['  : skip(); return '['; 
         case ']'  : skip(); return ']';
         case '`'  : skip(); return '`';
-        case '{'  : goOffside(HARD);
+        case '{'  : if (offsideON) goOffside(HARD);
                     skip();
                     return '{';
-        case '}'  : if (indentDepth<0) {
+        case '}'  : if (offsideON && indentDepth<0) {
                         ERRMSG(row) "Misplaced `}'"
                         EEND;
                     }
-                    if (layout[indentDepth]==HARD)      /* skip over hard }*/
-                        skip();
-                    unOffside();        /* otherwise, we have to insert a }*/
+                    if (!(offsideON && layout[indentDepth]!=HARD))
+                        skip();                         /* skip over hard }*/
+                    if (offsideON) 
+                        unOffside();    /* otherwise, we have to insert a }*/
                     return '}';         /* to (try to) avoid an error...   */
 
         /* Character and string literals                                   */
@@ -1366,6 +1432,15 @@ static Int local yylex() {             /* Read next input token ...        */
                     return STRINGLIT;
     }
 
+#if IPARAM
+    if (c0=='?' && isIn(c1,SMALL) && !haskell98) {
+       Text it;                        /* Look for implicit param name    */
+       skip();
+       it    = readIdent();
+       top() = yylval = ap(IPVAR,it);
+       return identType=IPVARID;
+    }
+#endif
 #if TREX
     if (c0=='#' && isIn(c1,SMALL) && !haskell98) {
         Text it;                        /* Look for record selector name   */
@@ -1429,13 +1504,24 @@ static Int local yylex() {             /* Read next input token ...        */
         if (it==textClass)             return TCLASS;
         if (it==textInstance)          return TINSTANCE;
         if (it==textModule)            return TMODULE;
+        if (it==textInterface)         return INTERFACE;
+        if (it==textInstImport)        return INSTIMPORT;
         if (it==textImport)            return IMPORT;
         if (it==textExport)            return EXPORT;
+        if (it==textDynamic)           return DYNAMIC;
+        if (it==textCcall)             return CCALL;
+        if (it==textStdcall)           return STDKALL;
+        if (it==textUUExport)          return UUEXPORT;
         if (it==textHiding)            return HIDING;
         if (it==textQualified)         return QUALIFIED;
         if (it==textAsMod)             return ASMOD;
         if (it==textWildcard)          return '_';
         if (it==textAll && !haskell98) return ALL;
+#if IPARAM
+       if (it==textWith && !haskell98) lookAhead(WITH);
+       if (it==textDlet && !haskell98) lookAhead(DLET);
+#endif
+        if (it==textUUAll)             return ALL;
         if (it==textRepeat && reading==KEYBOARD)
             return repeatLast();
 
@@ -1472,7 +1558,8 @@ static Int local yylex() {             /* Read next input token ...        */
         return NUMLIT;
     }
 
-    ERRMSG(row) "Unrecognised character `\\%d' in column %d", ((int)c0), column
+    ERRMSG(row) "Unrecognised character `\\%d' in column %d", 
+                ((int)c0), column
     EEND;
     return 0; /*NOTREACHED*/
 }
@@ -1506,6 +1593,11 @@ static Void local parseInput(startWith)/* Parse input with given first tok,*/
 Int startWith; {                       /* determining whether to read a    */
     firstToken   = TRUE;               /* script or an expression          */
     firstTokenIs = startWith;
+    if (startWith==INTERFACE) {
+       offsideON = FALSE; readingInterface = TRUE; 
+    } else {
+       offsideON = TRUE; readingInterface = FALSE;
+    }
 
     clearStack();
     if (yyparse()) {                   /* This can only be parser overflow */
@@ -1570,6 +1662,22 @@ Void parseExp() {                      /* Read an expression to evaluate   */
     setLastExpr(inputExpr);
 }
 
+
+#if EXPLAIN_INSTANCE_RESOLUTION
+Void parseContext() {                  /* Read a context to prove   */
+    parseInput(CONTEXT);
+}
+#endif
+
+Void parseInterface(nm,len)            /* Read a GHC interface file        */
+String nm;
+Long   len; {                          /* Used to set a target for reading */
+    input(RESET);
+    fileInput(nm,len);
+    parseInput(INTERFACE);
+}
+
+
 /* --------------------------------------------------------------------------
  * Input control:
  * ------------------------------------------------------------------------*/
@@ -1598,6 +1706,10 @@ Int what; {
                        textDeriving   = findText("deriving");
                        textDo         = findText("do");
                        textClass      = findText("class");
+#if IPARAM
+                      textWith       = findText("with");
+                      textDlet       = findText("dlet");
+#endif
                        textInstance   = findText("instance");
                        textCoco       = findText("::");
                        textEq         = findText("=");
@@ -1616,12 +1728,20 @@ Int what; {
                        textPrelude    = findText("Prelude");
                        textNum        = findText("Num");
                        textModule     = findText("module");
+                       textInterface  = findText("__interface");
+                       textInstImport = findText("__instimport");
+                       textExport     = findText("export");
+                       textDynamic    = findText("dynamic");
+                       textCcall      = findText("ccall");
+                       textStdcall    = findText("stdcall");
+                       textUUExport   = findText("__export");
                        textImport     = findText("import");
                        textHiding     = findText("hiding");
                        textQualified  = findText("qualified");
                        textAsMod      = findText("as");
                        textWildcard   = findText("_");
                        textAll        = findText("forall");
+                       textUUAll      = findText("__forall");
                        varMinus       = mkVar(textMinus);
                        varPlus        = mkVar(textPlus);
                        varBang        = mkVar(textBang);