diff --git a/ghc/interpreter/Makefile b/ghc/interpreter/Makefile index 45b574be188329cc592782c9ead44750964a600f..0a410a9b31e2497c2551e9694420ccf4c01e13b9 100644 --- a/ghc/interpreter/Makefile +++ b/ghc/interpreter/Makefile @@ -1,6 +1,6 @@ # ----------------------------------------------------------------------------- # -# $Id: Makefile,v 1.8 1999/04/27 10:59:29 sewardj Exp $ # +# $Id: Makefile,v 1.9 1999/06/07 17:22:54 sewardj Exp $ # # ----------------------------------------------------------------------------- # TOP = ../.. @@ -17,6 +17,7 @@ YACC = bison -y %.c: %.y -$(YACC) $< mv y.tab.c $@ + rm -f input.o HS_SRCS = @@ -24,9 +25,9 @@ HS_SRCS = Y_SRCS = parser.y C_SRCS = link.c type.c static.c storage.c derive.c input.c compiler.c subst.c \ translate.c codegen.c lift.c free.c stgSubst.c optimise.c output.c \ - hugs.c dynamic.c stg.c sainteger.c + hugs.c dynamic.c stg.c sainteger.c interface.c -SRC_CC_OPTS = -O2 -g -I$(GHC_DIR)/interpreter -I$(GHC_DIR)/includes -I$(GHC_DIR)/rts -D__HUGS__ -DCOMPILING_RTS -Wall -Wstrict-prototypes -Wno-unused +SRC_CC_OPTS = -g -I$(GHC_DIR)/interpreter -I$(GHC_DIR)/includes -I$(GHC_DIR)/rts -D__HUGS__ -DCOMPILING_RTS -Wall -Wstrict-prototypes -Wno-unused GHC_LIBS_NEEDED = $(TOP)/ghc/rts/libHSrts.a @@ -49,7 +50,7 @@ cleanish: snapshot: /bin/rm -f snapshot.tar - tar cvf snapshot.tar Makefile *.[chy] *-ORIG-* \ + tar cvf snapshot.tar Makefile *.[chy] \ ../rts/Assembler.c ../rts/Evaluator.c ../rts/Disassembler.c \ ../rts/ForeignCall.c ../rts/Printer.c ../rts/QueueTemplate.h \ ../includes/options.h ../includes/Assembler.h nHandle.c \ diff --git a/ghc/interpreter/codegen.c b/ghc/interpreter/codegen.c index ca9b482d3d3c6cf4960cf53479ff1b31183e90f3..32d1ebf55f867aaa8e7e6e8a0926e7a349de02f0 100644 --- a/ghc/interpreter/codegen.c +++ b/ghc/interpreter/codegen.c @@ -7,8 +7,8 @@ * Hugs version 1.4, December 1997 * * $RCSfile: codegen.c,v $ - * $Revision: 1.6 $ - * $Date: 1999/04/27 10:06:48 $ + * $Revision: 1.7 $ + * $Date: 1999/06/07 17:22:53 $ * ------------------------------------------------------------------------*/ #include "prelude.h" @@ -106,15 +106,21 @@ static void cgBind( AsmBCO bco, StgVar v ) static Void pushVar( AsmBCO bco, StgVar v ) { - Cell info = stgVarInfo(v); + Cell info; assert(isStgVar(v)); - if (isPtr(info)) { - asmClosure(bco,ptrOf(info)); - } else if (isInt(info)) { - asmVar(bco,intOf(info),repOf(v)); + + if (isCPtr(v)) { +fprintf ( stderr, "push cptr %p\n", (void*)cptrOf(v) ); } else { - internal("pushVar"); - } + info = stgVarInfo(v); + if (isPtr(info)) { + asmClosure(bco,ptrOf(info)); + } else if (isInt(info)) { + asmVar(bco,intOf(info),repOf(v)); + } else { + internal("pushVar"); + } + } } static Void pushAtom( AsmBCO bco, StgAtom e ) @@ -154,6 +160,9 @@ static Void pushAtom( AsmBCO bco, StgAtom e ) asmClosure(bco,asmStringObj(textToStr(textOf(e)))); #endif break; + case CPTRCELL: + asmConstWord(bco,cptrOf(e)); + break; case PTRCELL: asmConstAddr(bco,ptrOf(e)); break; @@ -483,9 +492,13 @@ static Void build( AsmBCO bco, StgVar v ) if (isName(fun)) { fun = name(fun).stgVar; } - if (nonNull(stgVarBody(fun)) - && whatIs(stgVarBody(fun)) == LAMBDA - && length(stgLambdaArgs(stgVarBody(fun))) > length(args)) { + if (isCPtr(fun) + || + (nonNull(stgVarBody(fun)) + && whatIs(stgVarBody(fun)) == LAMBDA + && length(stgLambdaArgs(stgVarBody(fun))) > length(args) + ) + ) { AsmSp start = asmBeginMkPAP(bco); map1Proc(pushAtom,bco,reverse(args)); pushAtom(bco,fun); diff --git a/ghc/interpreter/compiler.c b/ghc/interpreter/compiler.c index 112ae6d31960b127db77c1c388e6bb4cb506e27e..97e3eef3a0626eaddef1c7857c43c0e03f72fdcf 100644 --- a/ghc/interpreter/compiler.c +++ b/ghc/interpreter/compiler.c @@ -10,8 +10,8 @@ * in the distribution for details. * * $RCSfile: compiler.c,v $ - * $Revision: 1.6 $ - * $Date: 1999/04/27 10:06:48 $ + * $Revision: 1.7 $ + * $Date: 1999/06/07 17:22:46 $ * ------------------------------------------------------------------------*/ #include "prelude.h" @@ -181,7 +181,7 @@ Cell e; { nv)); } - default : internal("translate"); + default : fprintf(stderr, "stuff=%d\n",whatIs(e));internal("translate"); } return e; } diff --git a/ghc/interpreter/connect.h b/ghc/interpreter/connect.h index 3c444bd06d42ca468b9feba919a4aee0c9b999ed..41dc004919a4a13a3291e490747d37346fa282fb 100644 --- a/ghc/interpreter/connect.h +++ b/ghc/interpreter/connect.h @@ -7,8 +7,8 @@ * in the distribution for details. * * $RCSfile: connect.h,v $ - * $Revision: 1.6 $ - * $Date: 1999/04/27 10:06:50 $ + * $Revision: 1.7 $ + * $Date: 1999/06/07 17:22:45 $ * ------------------------------------------------------------------------*/ /* -------------------------------------------------------------------------- @@ -497,4 +497,35 @@ extern List offsetTyvarsIn Args((Type,List)); extern Void optimiseTopBinds Args((List)); extern List cfunSfuns; /* List of (Cfun,[SelectorVar]) */ +extern Void interface Args((Int)); + +extern List typeVarsIn Args((Cell,List,List)); + +extern Void getFileSize Args((String, Long *)); + +extern Void loadInterface Args((String,Long)); + +extern Void openGHCIface Args((Text)); +extern Void loadSharedLib Args((String)); +extern Void addGHCImports Args((Int,Text,List)); +extern Void addGHCExports Args((Cell,List)); +extern Void addGHCVar Args((Int,Text,Type)); +extern Void addGHCSynonym Args((Int,Cell,List,Type)); +extern Void addGHCDataDecl Args((Int,List,Cell,List,List)); +extern Void addGHCNewType Args((Int,List,Cell,List,Cell)); +extern Void addGHCClass Args((Int,List,Cell,List,List)); +extern Void addGHCInstance Args((Int,List,Pair,Text)); +extern Void finishInterfaces Args((Void)); + +extern Void hi_o_namesFromSrcName Args((String,String*,String* oName)); +extern Void parseInterface Args((String,Long)); + + #define SMALL_INLINE_SIZE 9 + + +// nasty hack, but seems an easy to convey the object name +// and size to openGHCIface +char nameObj[FILENAME_MAX+1]; +int sizeObj; + diff --git a/ghc/interpreter/dynamic.c b/ghc/interpreter/dynamic.c index 57653d578f822ec87265bef3b75320d6c3d0aacd..3fb2a615053dd8e0cbe206e253c7e89cd3de6723 100644 --- a/ghc/interpreter/dynamic.c +++ b/ghc/interpreter/dynamic.c @@ -7,8 +7,8 @@ * Hugs version 1.4, December 1997 * * $RCSfile: dynamic.c,v $ - * $Revision: 1.4 $ - * $Date: 1999/03/01 14:46:45 $ + * $Revision: 1.5 $ + * $Date: 1999/06/07 17:22:31 $ * ------------------------------------------------------------------------*/ #include "prelude.h" @@ -21,7 +21,6 @@ #include <stdio.h> #include <dlfcn.h> -#if 0 /* apparently unused */ ObjectFile loadLibrary(fn) String fn; { return dlopen(fn,RTLD_NOW | RTLD_GLOBAL); @@ -32,7 +31,6 @@ ObjectFile file; String symbol; { return dlsym(file,symbol); } -#endif void* getDLLSymbol(dll,symbol) /* load dll and lookup symbol */ String dll; diff --git a/ghc/interpreter/hugs.c b/ghc/interpreter/hugs.c index b9268d6869377e6b8cc2f03fa908eac88f842bd5..2f426c5cdf6f51c1f28176f9d2ea854c74ce640d 100644 --- a/ghc/interpreter/hugs.c +++ b/ghc/interpreter/hugs.c @@ -8,8 +8,8 @@ * in the distribution for details. * * $RCSfile: hugs.c,v $ - * $Revision: 1.6 $ - * $Date: 1999/04/27 10:06:52 $ + * $Revision: 1.7 $ + * $Date: 1999/06/07 17:22:43 $ * ------------------------------------------------------------------------*/ #include <setjmp.h> @@ -77,13 +77,13 @@ static Int local argToInt Args((String)); static Void local loadProject Args((String)); static Void local clearProject Args((Void)); -static Void local addScriptName Args((String,Bool)); -static Bool local addScript Args((String,Long)); +static Bool local addScript Args((Int)); static Void local forgetScriptsFrom Args((Script)); static Void local setLastEdit Args((String,Int)); static Void local failed Args((Void)); static String local strCopy Args((String)); + /* -------------------------------------------------------------------------- * Machine dependent code for Hugs interpreter: * ------------------------------------------------------------------------*/ @@ -101,20 +101,39 @@ static Bool printing = FALSE; /* TRUE => currently printing value*/ static Bool showStats = FALSE; /* TRUE => print stats after eval */ static Bool listScripts = TRUE; /* TRUE => list scripts after loading*/ static Bool addType = FALSE; /* TRUE => print type with value */ -static Bool chaseImports = TRUE; /* TRUE => chase imports on load */ static Bool useDots = RISCOS; /* TRUE => use dots in progress */ static Bool quiet = FALSE; /* TRUE => don't show progress */ Bool preludeLoaded = FALSE; - Bool optimise = TRUE; + Bool optimise = FALSE; + +typedef + struct { + String modName; /* Module name */ + Bool details; /* FALSE => remaining fields are invalid */ + String path; /* Path to module */ + String srcExt; /* ".hs" or ".lhs" if fromSource */ + Time lastChange; /* Time of last change to script */ + Bool fromSource; /* FALSE => load object code */ + Bool postponed; /* Indicates postponed load */ + Bool objLoaded; + Long size; + Long oSize; + } + ScriptInfo; + +static Void local makeStackEntry Args((ScriptInfo*,String)); +static Void local addStackEntry Args((String)); + +static ScriptInfo scriptInfo[NUM_SCRIPTS]; -static String scriptName[NUM_SCRIPTS]; /* Script file names */ -static Time lastChange[NUM_SCRIPTS]; /* Time of last change to script */ -static Bool postponed[NUM_SCRIPTS]; /* Indicates postponed load */ static Int numScripts; /* Number of scripts loaded */ +static Int nextNumScripts; static Int namesUpto; /* Number of script names set */ static Bool needsImports; /* set to TRUE if imports required */ String scriptFile; /* Name of current script (if any) */ + + static Text evalModule = 0; /* Name of module we eval exprs in */ static String currProject = 0; /* Name of current project file */ static Bool projectLoaded = FALSE; /* TRUE => project file loaded */ @@ -131,6 +150,41 @@ static Int hpSize = DEFAULTHEAP; /* Desired heap size */ static Bool disableOutput = FALSE; /* redirect output to buffer? */ #endif +String bool2str ( Bool b ) +{ + if (b) return "Yes"; else return "No "; +} + +void ppSmStack ( String who ) +{ + int i, j; + fflush(stdout);fflush(stderr); + printf ( "\n" ); + printf ( "ppSmStack %s: numScripts = %d namesUpto = %d needsImports = %s\n", + who, numScripts, namesUpto, bool2str(needsImports) ); + assert (namesUpto >= numScripts); + printf ( " Det FrS Pst ObL Module Ext Size ModTime Path\n" ); + for (i = namesUpto-1; i >= 0; i--) { + printf ( "%c%2d: %3s %3s %3s %3s %16s %-4s %5ld %8lx %s\n", + (i==numScripts ? '*' : ' '), + i, bool2str(scriptInfo[i].details), + bool2str(scriptInfo[i].fromSource), + bool2str(scriptInfo[i].postponed), + bool2str(scriptInfo[i].objLoaded), + scriptInfo[i].modName, + scriptInfo[i].fromSource ? scriptInfo[i].srcExt : "", + scriptInfo[i].size, + scriptInfo[i].lastChange, + scriptInfo[i].path + ); + } + // printf ( "\n" ); + fflush(stdout);fflush(stderr); +ppScripts(); +ppModules(); + printf ( "\n" ); +} + /* -------------------------------------------------------------------------- * Hugs entry point: * ------------------------------------------------------------------------*/ @@ -228,6 +282,9 @@ String argv[]; { startupHaskell (argc,argv); argc = prog_argc; argv = prog_argv; + namesUpto = numScripts = 0; + addStackEntry("Prelude"); + for (i=1; i<argc; ++i) { /* process command line arguments */ if (strcmp(argv[i], "--")==0) break; if (strcmp(argv[i],"+")==0 && i+1<argc) { @@ -239,7 +296,7 @@ String argv[]; { } } else if (argv[i] && argv[i][0]/* workaround for /bin/sh silliness*/ && !processOption(argv[i])) { - addScriptName(argv[i],TRUE); + addStackEntry(argv[i]); } } @@ -247,12 +304,15 @@ String argv[]; { DEBUG_LoadSymbols(argv_0_orig); #endif - scriptName[0] = strCopy(findMPathname(NULL,STD_PRELUDE,hugsPath)); + + +#if 0 if (!scriptName[0]) { Printf("Prelude not found on current path: \"%s\"\n", hugsPath ? hugsPath : ""); fatal("Unable to load prelude"); } +#endif if (haskell98) { Printf("Haskell 98 mode: Restart with command line option -98 to enable extensions\n\n"); @@ -655,7 +715,6 @@ struct options toggle[] = { /* List of command line toggles */ {'w', "Always show which modules are loaded", &listScripts}, {'k', "Show kind errors in full", &kindExpert}, {'o', "Allow overlapping instances", &allowOverlap}, - {'i', "Chase imports while loading modules", &chaseImports}, {'O', "Optimise (improve?) generated code", &optimise}, #if DEBUG_CODE {'D', "Debug: show generated code", &debugCode}, @@ -705,7 +764,7 @@ String s; { scriptFile = currProject; forgetScriptsFrom(1); while ((s=readFilename())!=0) - addScriptName(s,TRUE); + addStackEntry(s); if (namesUpto<=1) { ERRMSG(0) "Empty project file" EEND; @@ -724,107 +783,216 @@ static Void local clearProject() { /* clear name for current project */ #endif } -static Void local addScriptName(s,sch) /* Add script to list of scripts */ -String s; /* to be read in ... */ -Bool sch; { /* TRUE => requires pathname search*/ + + +static Void local makeStackEntry ( ScriptInfo* ent, String iname ) +{ + Bool ok, fromObj; + Bool sAvail, iAvail, oAvail; + Time sTime, iTime, oTime; + Long sSize, iSize, oSize; + String path, sExt; + + ok = findFilesForModule ( + iname, + &path, + &sExt, + &sAvail, &sTime, &sSize, + &iAvail, &iTime, &iSize, + &oAvail, &oTime, &oSize + ); + if (!ok) { + ERRMSG(0) + "Can't file source or object+interface for module \"%s\"", + iname + EEND; + } + /* findFilesForModule should enforce this */ + if (!(sAvail || (oAvail && iAvail))) + internal("chase"); + /* Load objects in preference to sources if both are available */ + fromObj = sAvail + ? (oAvail && iAvail && timeEarlier(sTime,oTime)) + : TRUE; + /* ToDo: namesUpto overflow */ + ent->modName = strCopy(iname); + ent->details = TRUE; + ent->path = path; + ent->fromSource = !fromObj; + ent->srcExt = sExt; + ent->postponed = FALSE; + ent->lastChange = sTime; /* ToDo: is this right? */ + ent->size = fromObj ? iSize : sSize; + ent->oSize = fromObj ? oSize : 0; + ent->objLoaded = FALSE; +} + + + +static Void nukeEnding( String s ) +{ + Int l = strlen(s); + if (l > 2 && strncmp(s+l-2,".o" ,3)==0) s[l-2] = 0; else + if (l > 3 && strncmp(s+l-3,".hi" ,3)==0) s[l-3] = 0; else + if (l > 3 && strncmp(s+l-3,".hs" ,3)==0) s[l-3] = 0; else + if (l > 4 && strncmp(s+l-4,".lhs",4)==0) s[l-4] = 0; else + if (l > 4 && strncmp(s+l-4,".dll",4)==0) s[l-4] = 0; else + if (l > 4 && strncmp(s+l-4,".DLL",4)==0) s[l-4] = 0; +} + +static Void local addStackEntry(s) /* Add script to list of scripts */ +String s; { /* to be read in ... */ + String s2; + Bool found; + Int i; + if (namesUpto>=NUM_SCRIPTS) { ERRMSG(0) "Too many module files (maximum of %d allowed)", NUM_SCRIPTS EEND; } - else - scriptName[namesUpto++] = strCopy(sch ? findPathname(NULL,s) : s); + + s = strCopy(s); + nukeEnding(s); + for (s2 = s; *s2; s2++) + if (*s2 == SLASH && *(s2+1)) s = s2+1; + + found = FALSE; + for (i = 0; i < namesUpto; i++) + if (strcmp(scriptInfo[i].modName,s)==0) + found = TRUE; + + if (!found) { + makeStackEntry ( &scriptInfo[namesUpto], strCopy(s) ); + namesUpto++; + } + free(s); } -static Bool local addScript(fname,len) /* read single script file */ -String fname; /* name of script file */ -Long len; { /* length of script file */ - scriptFile = fname; +/* Return TRUE if no imports were needed; FALSE otherwise. */ +static Bool local addScript(stacknum) /* read single file */ +Int stacknum; { + static char name[FILENAME_MAX+1]; + Int len = scriptInfo[stacknum].size; #if HUGS_FOR_WINDOWS /* Set clock cursor while loading */ allowBreak(); SetCursor(LoadCursor(NULL, IDC_WAIT)); #endif - Printf("Reading file \"%s\":\n",fname); - setLastEdit(fname,0); - -#if 0 -ToDo: reinstate - if (isInterfaceFile(fname)) { - loadInterface(fname); - } else -#else - { - needsImports = FALSE; - parseScript(fname,len); /* process script file */ - if (needsImports) - return FALSE; - checkDefns(); - typeCheckDefns(); - compileDefns(); - } -#endif - scriptFile = 0; - preludeLoaded = TRUE; - return TRUE; + // setLastEdit(name,0); + + nameObj[0] = 0; + strcpy(name, scriptInfo[stacknum].path); + strcat(name, scriptInfo[stacknum].modName); + if (scriptInfo[stacknum].fromSource) + strcat(name, scriptInfo[stacknum].srcExt); else + strcat(name, ".hi"); + + scriptFile = name; + + if (scriptInfo[stacknum].fromSource) { + Printf("Reading script \"%s\":\n",name); + needsImports = FALSE; + parseScript(name,len); + if (needsImports) return FALSE; + checkDefns(); + typeCheckDefns(); + compileDefns(); + } else { + Printf("Reading iface \"%s\":\n", name); + scriptFile = name; + needsImports = FALSE; + + // set nameObj for the benefit of openGHCIface + strcpy(nameObj, scriptInfo[stacknum].path); + strcat(nameObj, scriptInfo[stacknum].modName); + strcat(nameObj, DLL_ENDING); + sizeObj = scriptInfo[stacknum].oSize; + + loadInterface(name,len); + scriptFile = 0; + if (needsImports) return FALSE; + } + + scriptFile = 0; + preludeLoaded = TRUE; + return TRUE; } + Bool chase(imps) /* Process list of import requests */ List imps; { - if (chaseImports) { - Int origPos = numScripts; /* keep track of original position */ - String origName = scriptName[origPos]; - for (; nonNull(imps); imps=tl(imps)) { - String iname = findPathname(origName,textToStr(textOf(hd(imps)))); - Int i = 0; - for (; i<namesUpto; i++) - if (pathCmp(scriptName[i],iname)==0) - break; - if (i>=origPos) { /* Neither loaded or queued */ - String theName; - Time theTime; - Bool thePost; - - postponed[origPos] = TRUE; - needsImports = TRUE; - - if (i>=namesUpto) /* Name not found (i==namesUpto) */ - addScriptName(iname,FALSE); - else if (postponed[i]) {/* Check for recursive dependency */ - ERRMSG(0) - "Recursive import dependency between \"%s\" and \"%s\"", - scriptName[origPos], iname - EEND; - } - /* Right rotate section of tables between numScripts and i so - * that i ends up with other imports in front of orig. script - */ - theName = scriptName[i]; - thePost = postponed[i]; - timeSet(theTime,lastChange[i]); - for (; i>numScripts; i--) { - scriptName[i] = scriptName[i-1]; - postponed[i] = postponed[i-1]; - timeSet(lastChange[i],lastChange[i-1]); - } - scriptName[numScripts] = theName; - postponed[numScripts] = thePost; - timeSet(lastChange[numScripts],theTime); - origPos++; + Int dstPosn; + ScriptInfo tmp; + Int origPos = numScripts; /* keep track of original position */ + String origName = scriptInfo[origPos].modName; + for (; nonNull(imps); imps=tl(imps)) { + String iname = textToStr(textOf(hd(imps))); + Int i = 0; + for (; i<namesUpto; i++) + if (strcmp(scriptInfo[i].modName,iname)==0) + break; + //fprintf(stderr, "import name = %s num = %d\n", iname, i ); + + if (i<namesUpto) { + /* We should have filled in the details of each module + the first time we hear about it. + */ + assert(scriptInfo[i].details); + } + + if (i>=origPos) { /* Neither loaded or queued */ + String theName; + Time theTime; + Bool thePost; + Bool theFS; + + needsImports = TRUE; + if (scriptInfo[origPos].fromSource) + scriptInfo[origPos].postponed = TRUE; + + if (i==namesUpto) { /* Name not found (i==namesUpto) */ + /* Find out where it lives, whether source or object, etc */ + makeStackEntry ( &scriptInfo[i], iname ); + namesUpto++; + } + else + if (scriptInfo[i].postponed && scriptInfo[i].fromSource) { + /* Check for recursive dependency */ + ERRMSG(0) + "Recursive import dependency between \"%s\" and \"%s\"", + scriptInfo[origPos].modName, iname + EEND; } + /* Move stack entry i to somewhere below origPos. If i denotes + * an object, destination is immediately below origPos. + * Otherwise, it's underneath the queue of objects below origPos. + */ + dstPosn = origPos-1; + if (scriptInfo[i].fromSource) + while (!scriptInfo[dstPosn].fromSource && dstPosn > 0) + dstPosn--; + + dstPosn++; + tmp = scriptInfo[i]; + for (; i > dstPosn; i--) scriptInfo[i] = scriptInfo[i-1]; + scriptInfo[dstPosn] = tmp; + if (dstPosn < nextNumScripts) nextNumScripts = dstPosn; + origPos++; } - return needsImports; } - return FALSE; + return needsImports; } static Void local forgetScriptsFrom(scno)/* remove scripts from system */ Script scno; { Script i; +#if 0 for (i=scno; i<namesUpto; ++i) if (scriptName[i]) free(scriptName[i]); +#endif dropScriptsFrom(scno-1); namesUpto = scno; if (numScripts>namesUpto) @@ -839,7 +1007,7 @@ static Void local load() { /* read filenames from command line */ String s; /* and add to list of scripts waiting */ /* to be read */ while ((s=readFilename())!=0) - addScriptName(s,TRUE); + addStackEntry(s); readScripts(1); } @@ -868,12 +1036,16 @@ static Void local readScripts(n) /* Reread current list of scripts, */ Int n; { /* loading everything after and */ Time timeStamp; /* including the first script which*/ Long fileSize; /* has been either changed or added*/ + static char name[FILENAME_MAX+1]; + ppSmStack("readscripts-begin"); #if HUGS_FOR_WINDOWS SetCursor(LoadCursor(NULL, IDC_WAIT)); #endif +#if 0 for (; n<numScripts; n++) { /* Scan previously loaded scripts */ + ppSmStack("readscripts-loop1"); getFileInfo(scriptName[n], &timeStamp, &fileSize); if (timeChanged(timeStamp,lastChange[n])) { dropScriptsFrom(n-1); @@ -883,8 +1055,10 @@ Int n; { /* loading everything after and */ } for (; n<NUM_SCRIPTS; n++) /* No scripts have been postponed */ postponed[n] = FALSE; /* at this stage */ + numScripts = 0; while (numScripts<namesUpto) { /* Process any remaining scripts */ + ppSmStack("readscripts-loop2"); getFileInfo(scriptName[numScripts], &timeStamp, &fileSize); timeSet(lastChange[numScripts],timeStamp); if (numScripts>0) /* no new script for prelude */ @@ -894,11 +1068,85 @@ Int n; { /* loading everything after and */ else dropScriptsFrom(numScripts-1); } +#endif + + interface(RESET); + + for (; n<numScripts; n++) { + ppSmStack("readscripts-loop2"); + strcpy(name, scriptInfo[n].path); + strcat(name, scriptInfo[n].modName); + if (scriptInfo[n].fromSource) + strcat(name, scriptInfo[n].srcExt); else + strcat(name, ".hi"); //ToDo: should be .o + getFileInfo(name,&timeStamp, &fileSize); + if (timeChanged(timeStamp,scriptInfo[n].lastChange)) { + dropScriptsFrom(n-1); + numScripts = n; + break; + } + } + for (; n<NUM_SCRIPTS; n++) + scriptInfo[n].postponed = FALSE; + + //numScripts = 0; + + while (numScripts < namesUpto) { +ppSmStack ( "readscripts-loop2" ); + + if (scriptInfo[numScripts].fromSource) { + + if (numScripts>0) + startNewScript(scriptInfo[numScripts].modName); + nextNumScripts = NUM_SCRIPTS; //bogus initialisation + if (addScript(numScripts)) { + numScripts++; +assert(nextNumScripts==NUM_SCRIPTS); + } + else + dropScriptsFrom(numScripts-1); + } else { + + if (scriptInfo[numScripts].objLoaded) { + numScripts++; + } else { + scriptInfo[numScripts].objLoaded = TRUE; + /* new */ + if (numScripts>0) + startNewScript(scriptInfo[numScripts].modName); + /* end */ + nextNumScripts = NUM_SCRIPTS; + if (addScript(numScripts)) { + numScripts++; +assert(nextNumScripts==NUM_SCRIPTS); + } else { + //while (!scriptInfo[numScripts].fromSource && numScripts > 0) + // numScripts--; + //if (scriptInfo[numScripts].fromSource) + // numScripts++; + numScripts = nextNumScripts; +assert(nextNumScripts<NUM_SCRIPTS); + } + } + } +if (numScripts==namesUpto) ppSmStack( "readscripts-final") ; + } + + finishInterfaces(); + + { Int m = namesUpto-1; + Text mtext = findText(scriptInfo[m].modName); + setCurrModule(mtext); + evalModule = mtext; + } + + if (listScripts) whatScripts(); if (numScripts<=1) setLastEdit((String)0, 0); + ppSmStack("readscripts-end "); } static Void local whatScripts() { /* list scripts in current session */ @@ -907,7 +1155,7 @@ static Void local whatScripts() { /* list scripts in current session */ if (projectLoaded) Printf(" (project: %s)",currProject); for (i=0; i<numScripts; ++i) - Printf("\n%s",scriptName[i]); + Printf("\n%s",scriptInfo[i].modName); Putchar('\n'); } @@ -928,6 +1176,9 @@ static Void local editor() { /* interpreter-editor interface */ } static Void local find() { /* edit file containing definition */ +#if 0 +This just plain wont work no more. +ToDo: Fix! String nm = readFilename(); /* of specified name */ if (!nm) { ERRMSG(0) "No name specified" @@ -955,6 +1206,7 @@ static Void local find() { /* edit file containing definition */ EEND; } } +#endif } static Void local runEditor() { /* run editor on script lastEdit */ @@ -1158,7 +1410,7 @@ Cell c; { extern Name nameHw; -static Void local dumpStg() { /* print STG stuff */ +static Void local dumpStg( void ) { /* print STG stuff */ String s; Text t; Name n; @@ -1201,8 +1453,9 @@ static Void local dumpStg() { /* print STG stuff */ if (isNull(name(n).stgVar)) { Printf ( "Doesn't have a STG tree: %s\n", s ); } else { - printf ( "\n{- stgVar of `%s' is id%d -}\n", s, -name(n).stgVar); - Printf ( "{- stgSize of body is %d -}\n\n", stgSize(stgVarBody(name(n).stgVar))); + Printf ( "\n{- stgVar of `%s' is id%d -}\n", s, -name(n).stgVar); + Printf ( "{- stgSize of body is %d -}\n\n", + stgSize(stgVarBody(name(n).stgVar))); printStg(stderr, name(n).stgVar); } } @@ -1222,12 +1475,13 @@ static Void local info() { /* describe objects */ } } + static Void local describe(t) /* describe an object */ Text t; { Tycon tc = findTycon(t); Class cl = findClass(t); Name nm = findName(t); - //Module mod = findEvalModule(); + Module mod = findModule(t); if (nonNull(tc)) { /* as a type constructor */ Type t = tc; @@ -1361,16 +1615,35 @@ Text t; { } else if (isSfun(nm)) { Printf(" -- selector function"); } -#if 0 - ToDo: reinstate - if (name(nm).primDef) { - Printf(" -- primitive"); + Printf("\n\n"); + } + + if (nonNull(mod)) { /* as a module */ + List t; + Printf("-- module\n"); + + Printf("\n-- values\n"); + for (t=module(mod).names; nonNull(t); t=tl(t)) { + Name nm = hd(t); + Printf ( "%s ", textToStr(name(nm).text)); } -#endif + + Printf("\n\n-- type constructors\n"); + for (t=module(mod).tycons; nonNull(t); t=tl(t)) { + Tycon tc = hd(t); + Printf ( "%s ", textToStr(tycon(tc).text)); + } + + Printf("\n\n-- classes\n"); + for (t=module(mod).classes; nonNull(t); t=tl(t)) { + Class cl = hd(t); + Printf ( "%s ", textToStr(cclass(cl).text)); + } + Printf("\n\n"); } - if (isNull(tc) && isNull(cl) && isNull(nm)) { + if (isNull(tc) && isNull(cl) && isNull(nm) && isNull(mod)) { Printf("Unknown reference `%s'\n",textToStr(t)); } } diff --git a/ghc/interpreter/input.c b/ghc/interpreter/input.c index cc11551ff3a45d946c102372ac1327307d6cc26e..afae01fd1f7dac65f59339ac1207342a91a1c00f 100644 --- a/ghc/interpreter/input.c +++ b/ghc/interpreter/input.c @@ -8,8 +8,8 @@ * in the distribution for details. * * $RCSfile: input.c,v $ - * $Revision: 1.5 $ - * $Date: 1999/04/27 10:06:53 $ + * $Revision: 1.6 $ + * $Date: 1999/06/07 17:22:32 $ * ------------------------------------------------------------------------*/ #include "prelude.h" @@ -18,6 +18,7 @@ #include "connect.h" #include "command.h" #include "errors.h" +#include "link.h" #include <ctype.h> #if HAVE_GETDELIM_H #include "getdelim.h" @@ -48,6 +49,7 @@ 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 */ +Bool offsideON = TRUE; /* TRUE => implement offside rule */ String repeatStr = 0; /* Repeat last expr */ @@ -120,9 +122,9 @@ 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, textUnsafe, text__All; Text textNum; /* Num */ Text textPrelude; /* Prelude */ @@ -249,7 +251,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++) +#define nextConsoleChar() \ + (unsigned char)(*nextChar=='\0' ? '\n' : *nextChar++) extern Void add_history Args((String)); extern String readline Args((String)); #else @@ -398,6 +401,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 @@ -449,7 +481,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; @@ -1215,6 +1248,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 +1257,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; } @@ -1298,7 +1334,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 +1355,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 +1382,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 */ @@ -1429,6 +1466,8 @@ 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==textHiding) return HIDING; @@ -1436,6 +1475,7 @@ static Int local yylex() { /* Read next input token ... */ if (it==textAsMod) return ASMOD; if (it==textWildcard) return '_'; if (it==textAll && !haskell98) return ALL; + if (it==text__All) return ALL; if (it==textRepeat && reading==KEYBOARD) return repeatLast(); @@ -1472,7 +1512,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 +1547,9 @@ 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; else + offsideON = TRUE; clearStack(); if (yyparse()) { /* This can only be parser overflow */ @@ -1570,6 +1614,15 @@ Void parseExp() { /* Read an expression to evaluate */ setLastExpr(inputExpr); } +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: * ------------------------------------------------------------------------*/ @@ -1616,12 +1669,16 @@ Int what; { textPrelude = findText("Prelude"); textNum = findText("Num"); textModule = findText("module"); + textInterface = findText("__interface"); + textInstImport = findText("__instimport"); + textExport = findText("__export"); textImport = findText("import"); textHiding = findText("hiding"); textQualified = findText("qualified"); textAsMod = findText("as"); textWildcard = findText("_"); textAll = findText("forall"); + text__All = findText("__forall"); varMinus = mkVar(textMinus); varPlus = mkVar(textPlus); varBang = mkVar(textBang); diff --git a/ghc/interpreter/interface.c b/ghc/interpreter/interface.c new file mode 100644 index 0000000000000000000000000000000000000000..b754bc5a39bf7861a80ee43556a6328476a82ee8 --- /dev/null +++ b/ghc/interpreter/interface.c @@ -0,0 +1,1652 @@ + +/* -------------------------------------------------------------------------- + * GHC interface file processing for Hugs + * + * Copyright (c) The University of Nottingham and Yale University, 1994-1997. + * All rights reserved. See NOTICE for details and conditions of use etc... + * Hugs version 1.4, December 1997 + * + * $RCSfile: interface.c,v $ + * $Revision: 1.4 $ + * $Date: 1999/06/07 17:22:51 $ + * ------------------------------------------------------------------------*/ + +/* ToDo: + * o use Z encoding + * o use vectored CONSTR_entry when appropriate + * o generate export list + * + * Needs GHC changes to generate member selectors, + * superclass selectors, etc + * o instance decls + * o dictionary constructors ? + * + * o Get Hugs/GHC to agree on what interface files look like. + * o figure out how to replace the Hugs Prelude with the GHC Prelude + */ + +#include "prelude.h" +#include "storage.h" +#include "backend.h" +#include "connect.h" +#include "errors.h" +#include "link.h" +#include "Assembler.h" /* for wrapping GHC objects */ +#include "dynamic.h" + +#define DEBUG_IFACE + +/* -------------------------------------------------------------------------- + * The "addGHC*" functions act as "impedence matchers" between GHC + * interface files and Hugs. Their main job is to convert abstract + * syntax trees into Hugs' internal representations. + * + * The main trick here is how we deal with mutually recursive interface + * files: + * + * o As we read an import decl, we add it to a list of required imports + * (unless it's already loaded, of course). + * + * o Processing of declarations is split into two phases: + * + * 1) While reading the interface files, we construct all the Names, + * Tycons, etc declared in the interface file but we don't try to + * resolve references to any entities the declaration mentions. + * + * This is done by the "addGHC*" functions. + * + * 2) After reading all the interface files, we finish processing the + * declarations by resolving any references in the declarations + * and doing any other processing that may be required. + * + * This is done by the "finishGHC*" functions which use the + * "fixup*" functions to assist them. + * + * The interface between these two phases are the "ghc*Decls" which + * contain lists of decls that haven't been completed yet. + * + * ------------------------------------------------------------------------*/ + +/* -------------------------------------------------------------------------- + * local variables: + * ------------------------------------------------------------------------*/ + +static List ghcVarDecls; +static List ghcConstrDecls; +static List ghcSynonymDecls; +static List ghcClassDecls; +static List ghcInstanceDecls; + +/* -------------------------------------------------------------------------- + * local function prototypes: + * ------------------------------------------------------------------------*/ + +static List local addGHCConstrs Args((Int,List,List)); +static Name local addGHCSel Args((Int,Pair)); +static Name local addGHCConstr Args((Int,Int,Triple)); + + +static Void local finishGHCVar Args((Name)); +static Void local finishGHCConstr Args((Name)); +static Void local finishGHCSynonym Args((Tycon)); +static Void local finishGHCClass Args((Class)); +static Void local finishGHCInstance Args((Inst)); +static Void local finishGHCImports Args((Triple)); +static Void local finishGHCExports Args((Pair)); +static Void local finishGHCModule Args((Module)); + +static Void local bindGHCNameTo Args((Name,Text)); +static Kinds local tvsToKind Args((List)); +static Int local arityFromType Args((Type)); + +static List local ifTyvarsIn Args((Type)); + +static Type local tvsToOffsets Args((Int,Type,List)); +static Type local conidcellsToTycons Args((Int,Type)); + +static Void local resolveReferencesInObjectModule Args((Module)); +static Bool local validateOImage Args((void*, Int)); + +static Text text_info; +static Text text_entry; +static Text text_closure; +static Text text_static_closure; +static Text text_static_info; +static Text text_con_info; +static Text text_con_entry; + + +/* -------------------------------------------------------------------------- + * code: + * ------------------------------------------------------------------------*/ + +List ifImports; /* [ConId] -- modules imported by current interface */ + +List ghcImports; /* [(Module, Text, [ConId|VarId])] + each (m1, m2, names) in this list + represents 'module m1 where ... import m2 ( names ) ...' + The list acts as a list of names to fix up in + finishInterfaces(). + */ + +List ghcExports; /* [(ConId, [ConId|VarId])] */ + +List ghcModules; /* [Module] -- modules of the .his loaded in this group */ + +Void addGHCExports(mod,stuff) +Cell mod; +List stuff; { + ghcExports = cons( pair(mod,stuff), ghcExports ); +} + +static Void local finishGHCExports(paire) +Pair paire; { + Text modTxt = textOf(fst(paire)); + List ids = snd(paire); + Module mod = findModule(modTxt); + if (isNull(mod)) { + ERRMSG(0) "Can't find module \"%s\" mentioned in export list", + textToStr(modTxt) + EEND; + } + + for (; nonNull(ids); ids=tl(ids)) { + Cell xs; + Cell id = hd(ids); /* ConId|VarId */ + Bool found = FALSE; + for (xs = module(mod).exports; nonNull(xs); xs=tl(xs)) { + Cell x = hd(xs); + if (isQCon(x)) continue; /* ToDo: fix this right */ + if (textOf(x)==textOf(id)) { found = TRUE; break; } + } + if (!found) { +printf ( "adding %s to exports of %s\n", + identToStr(id), textToStr(modTxt) ); + module(mod).exports = cons ( id, module(mod).exports ); + } + } +} + + +static Void local finishGHCImports(triple) +Triple triple; +{ + Module dstMod = fst3(triple); // the importing module + Text srcTxt = snd3(triple); + List names = thd3(triple); + Module srcMod = findModule ( srcTxt ); + Module tmpCurrentModule = currentModule; + List exps; + Bool found; + Text tnm; + Cell nm; + Cell x; + //fprintf(stderr, "finishGHCImports: dst=%s src=%s\n", + // textToStr(module(dstMod).text), + // textToStr(srcTxt) ); + //print(names, 100); + //printf("\n"); + /* for each nm in names + nm should be in module(src).exports -- if not, error + if nm notElem module(dst).names cons it on + */ + + if (isNull(srcMod)) { + /* I don't think this can actually ever happen, but still ... */ + ERRMSG(0) "Interface for module \"%s\" imports unknown module \"%s\"", + textToStr(module(dstMod).text), + textToStr(srcTxt) + EEND; + } + //printf ( "exports of %s are\n", textToStr(module(srcMod).text) ); + //print( module(srcMod).exports, 100 ); + //printf( "\n" ); + + setCurrModule ( srcMod ); // so that later lookups succeed + + for (; nonNull(names); names=tl(names)) { + nm = hd(names); + /* Check the exporting module really exports it. */ + found = FALSE; + for (exps=module(srcMod).exports; nonNull(exps); exps=tl(exps)) { + Cell c = hd(exps); + //if (isPair(c)) c=fst(c); + assert(whatIs(c)==CONIDCELL || whatIs(c)==VARIDCELL); + assert(whatIs(nm)==CONIDCELL || whatIs(nm)==VARIDCELL); + //printf( " compare `%s' `%s'\n", textToStr(textOf(c)), textToStr(textOf(nm))); + if (textOf(c)==textOf(nm)) { found=TRUE; break; } + } + if (!found) { + ERRMSG(0) "Interface for module \"%s\" imports \"%s\" from\n" + "module \"%s\", but the latter doesn't export it", + textToStr(module(dstMod).text), textToStr(textOf(nm)), + textToStr(module(srcMod).text) + EEND; + } + /* Ok, it's exported. Now figure out what it is we're really + importing. + */ + tnm = textOf(nm); + + x = findName(tnm); + if (nonNull(x)) { + if (!cellIsMember(x,module(dstMod).names)) + module(dstMod).names = cons(x, module(dstMod).names); + continue; + } + + x = findTycon(tnm); + if (nonNull(x)) { + if (!cellIsMember(x,module(dstMod).tycons)) + module(dstMod).tycons = cons(x, module(dstMod).tycons); + continue; + } + + x = findClass(tnm); + if (nonNull(x)) { + if (!cellIsMember(x,module(dstMod).classes)) + module(dstMod).classes = cons(x, module(dstMod).classes); + continue; + } + + fprintf(stderr, "\npanic: Can't figure out what this is in finishGHCImports\n" + "\t%s\n", textToStr(tnm) ); + internal("finishGHCImports"); + } + + setCurrModule(tmpCurrentModule); +} + + +Void loadInterface(String fname, Long fileSize) +{ + ifImports = NIL; + parseInterface(fname,fileSize); + if (nonNull(ifImports)) + chase(ifImports); +} + + +Void finishInterfaces ( void ) +{ + /* the order of these doesn't matter + * (ToDo: unless synonyms have to be eliminated??) + */ + mapProc(finishGHCVar, ghcVarDecls); + mapProc(finishGHCConstr, ghcConstrDecls); + mapProc(finishGHCSynonym, ghcSynonymDecls); + mapProc(finishGHCClass, ghcClassDecls); + mapProc(finishGHCInstance, ghcInstanceDecls); + mapProc(finishGHCExports, ghcExports); + mapProc(finishGHCImports, ghcImports); + mapProc(finishGHCModule, ghcModules); + ghcVarDecls = NIL; + ghcConstrDecls = NIL; + ghcSynonymDecls = NIL; + ghcClassDecls = NIL; + ghcInstanceDecls = NIL; + ghcImports = NIL; + ghcExports = NIL; + ghcModules = NIL; +} + + +static Void local finishGHCModule(mod) +Module mod; { + // do the implicit 'import Prelude' thing + List pxs = module(modulePrelude).exports; + for (; nonNull(pxs); pxs=tl(pxs)) { + Cell px = hd(pxs); + again: + switch (whatIs(px)) { + case AP: + px = fst(px); + goto again; + case NAME: + module(mod).names = cons ( px, module(mod).names ); + break; + case TYCON: + module(mod).tycons = cons ( px, module(mod).tycons ); + break; + case CLASS: + module(mod).classes = cons ( px, module(mod).classes ); + break; + default: + fprintf(stderr, "finishGHCModule: unknown tag %d\n", whatIs(px)); + break; + } + } + + // Last, but by no means least ... + resolveReferencesInObjectModule ( mod ); +} + +Void openGHCIface(t) +Text t; { + FILE* f; + void* img; + Module m = findModule(t); + if (isNull(m)) { + m = newModule(t); +printf ( "new module %s\n", textToStr(t) ); + } else if (m != modulePrelude) { + ERRMSG(0) "Module \"%s\" already loaded", textToStr(t) + EEND; + } + + // sizeObj and nameObj will magically be set to the right + // thing when we arrive here. + // All this crud should be replaced with mmap when we do this + // for real(tm) + img = malloc ( sizeObj ); + if (!img) { + ERRMSG(0) "Can't allocate memory to load object file for module \"%s\"", + textToStr(t) + EEND; + } + f = fopen( nameObj, "rb" ); + if (!f) { + // Really, this shouldn't happen, since makeStackEntry ensures the + // object is available. Nevertheless ... + ERRMSG(0) "Object file \"%s\" can't be opened to read -- oops!", + &(nameObj[0]) + EEND; + } + if (sizeObj != fread ( img, 1, sizeObj, f)) { + ERRMSG(0) "Read of object file \"%s\" failed", nameObj + EEND; + } + if (!validateOImage(img,sizeObj)) { + ERRMSG(0) "Validation of object file \"%s\" failed", nameObj + EEND; + } + + assert(!module(m).oImage); + module(m).oImage = img; + + if (!cellIsMember(m, ghcModules)) + ghcModules = cons(m, ghcModules); + + setCurrModule(m); +} + + +Void addGHCImports(line,mn,syms) +Int line; +Text mn; /* the module to import from */ +List syms; { /* [ConId | VarId] -- the names to import */ + List t; + Bool found; +# ifdef DEBUG_IFACE + printf("\naddGHCImport %s\n", textToStr(mn) ); +# endif + + // Hack to avoid chasing Prel* junk right now + if (strncmp(textToStr(mn), "Prel",4)==0) return; + + found = FALSE; + for (t=ifImports; nonNull(t); t=tl(t)) { + if (textOf(hd(t)) == mn) { + found = TRUE; + break; + } + } + if (!found) { + ifImports = cons(mkCon(mn),ifImports); + ghcImports = cons( triple(currentModule,mn,syms), ghcImports ); + } +} + +void addGHCVar(line,v,ty) +Int line; +Text v; +Type ty; +{ + Name n; + String s; + List tmp, tvs; + /* if this var is the name of a ghc-compiled dictionary, + ie, starts zdfC where C is a capital, + ignore it. + */ + s = textToStr(v); +# ifdef DEBUG_IFACE + printf("\nbegin addGHCVar %s\n", s); +# endif + if (s[0]=='z' && s[1]=='d' && s[2]=='f' && isupper((int)s[3])) { +# ifdef DEBUG_IFACE + printf(" ignoring %s\n", s); +# endif + return; + } + n = findName(v); + if (nonNull(n)) { + ERRMSG(0) "Attempt to redefine variable \"%s\"", textToStr(v) + EEND; + } + n = newName(v,NIL); + bindGHCNameTo(n, text_info); + bindGHCNameTo(n, text_closure); + + tvs = nubList(ifTyvarsIn(ty)); + for (tmp=tvs; nonNull(tmp); tmp=tl(tmp)) + hd(tmp) = pair(hd(tmp),STAR); + if (nonNull(tvs)) + ty = mkPolyType(tvsToKind(tvs),ty); + + ty = tvsToOffsets(line,ty,tvs); + + /* prepare for finishGHCVar */ + name(n).type = ty; + name(n).line = line; + ghcVarDecls = cons(n,ghcVarDecls); +# ifdef DEBUG_IFACE + printf("end addGHCVar %s\n", s); +# endif +} + +static Void local finishGHCVar(Name n) +{ + Int line = name(n).line; + Type ty = name(n).type; +# ifdef DEBUG_IFACE + fprintf(stderr, "\nbegin finishGHCVar %s\n", textToStr(name(n).text) ); +# endif + setCurrModule(name(n).mod); + name(n).type = conidcellsToTycons(line,ty); +# ifdef DEBUG_IFACE + fprintf(stderr, "end finishGHCVar %s\n", textToStr(name(n).text) ); +# endif +} + +Void addGHCSynonym(line,tycon,tvs,ty) +Int line; +Cell tycon; /* ConId */ +List tvs; /* [(VarId,Kind)] */ +Type ty; { + /* ToDo: worry about being given a decl for (->) ? + * and worry about qualidents for () + */ + Text t = textOf(tycon); + if (nonNull(findTycon(t))) { + ERRMSG(line) "Repeated definition of type constructor \"%s\"", + textToStr(t) + EEND; + } else { + Tycon tc = newTycon(t); + tycon(tc).line = line; + tycon(tc).arity = length(tvs); + tycon(tc).what = SYNONYM; + tycon(tc).kind = tvsToKind(tvs); + + /* prepare for finishGHCSynonym */ + tycon(tc).defn = tvsToOffsets(line,ty,tvs); + ghcSynonymDecls = cons(tc,ghcSynonymDecls); + } +} + +static Void local finishGHCSynonym(Tycon tc) +{ + Int line = tycon(tc).line; + + setCurrModule(tycon(tc).mod); + tycon(tc).defn = conidcellsToTycons(line,tycon(tc).defn); + + /* ToDo: can't really do this until I've done all synonyms + * and then I have to do them in order + * tycon(tc).defn = fullExpand(ty); + */ +} + +Void addGHCDataDecl(line,ctx0,tycon,ktyvars,constrs0) +Int line; +List ctx0; /* [(QConId,VarId)] */ +Cell tycon; /* ConId */ +List ktyvars; /* [(VarId,Kind)] */ +List constrs0; /* [(ConId,[(Type,Text)],NIL)] + The NIL will become the constr's type + The Text is an optional field name */ + /* ToDo: worry about being given a decl for (->) ? + * and worry about qualidents for () + */ +{ + Type ty, resTy, selTy, conArgTy; + List tmp, conArgs, sels, constrs, fields, tyvarsMentioned; + List ctx, ctx2; + Triple constr; + Cell conid; + Pair conArg, ctxElem; + Text conArgNm; + + Text t = textOf(tycon); +# ifdef DEBUG_IFACE + fprintf(stderr, "\nbegin addGHCDataDecl %s\n",textToStr(t)); +# endif + if (nonNull(findTycon(t))) { + ERRMSG(line) "Repeated definition of type constructor \"%s\"", + textToStr(t) + EEND; + } else { + Tycon tc = newTycon(t); + tycon(tc).text = t; + tycon(tc).line = line; + tycon(tc).arity = length(ktyvars); + tycon(tc).kind = tvsToKind(ktyvars); + tycon(tc).what = DATATYPE; + + /* a list to accumulate selectors in :: [(VarId,Type)] */ + sels = NIL; + + /* make resTy the result type of the constr, T v1 ... vn */ + resTy = tycon; + for (tmp=ktyvars; nonNull(tmp); tmp=tl(tmp)) + resTy = ap(resTy,fst(hd(tmp))); + + /* for each constructor ... */ + for (constrs=constrs0; nonNull(constrs); constrs=tl(constrs)) { + constr = hd(constrs); + conid = fst3(constr); + fields = snd3(constr); + assert(isNull(thd3(constr))); + + /* Build type of constr and handle any selectors found. + Also collect up tyvars occurring in the constr's arg + types, so we can throw away irrelevant parts of the + context later. + */ + ty = resTy; + tyvarsMentioned = NIL; /* [VarId] */ + conArgs = reverse(fields); + for (; nonNull(conArgs); conArgs=tl(conArgs)) { + conArg = hd(conArgs); /* (Type,Text) */ + conArgTy = fst(conArg); + conArgNm = snd(conArg); + tyvarsMentioned = dupListOnto(ifTyvarsIn(conArgTy), + tyvarsMentioned); + ty = fn(conArgTy,ty); + if (nonNull(conArgNm)) { + /* a field name is mentioned too */ + selTy = fn(resTy,conArgTy); + if (whatIs(tycon(tc).kind) != STAR) + selTy = pair(POLYTYPE,pair(tycon(tc).kind, selTy)); + selTy = tvsToOffsets(line,selTy, ktyvars); + + sels = cons( pair(conArgNm,selTy), sels); + } + } + + /* Now ty is the constructor's type, not including context. + Throw away any parts of the context not mentioned in + tyvarsMentioned, and use it to qualify ty. + */ + ctx2 = NIL; + for (ctx=ctx0; nonNull(ctx); ctx=tl(ctx)) { + ctxElem = hd(ctx); /* (QConId,VarId) */ + if (nonNull(cellIsMember(textOf(snd(ctxElem)),tyvarsMentioned))) + ctx2 = cons(ctxElem, ctx2); + } + if (nonNull(ctx2)) + ty = ap(QUAL,pair(ctx2,ty)); + + /* stick the tycon's kind on, if not simply STAR */ + if (whatIs(tycon(tc).kind) != STAR) + ty = pair(POLYTYPE,pair(tycon(tc).kind, ty)); + + ty = tvsToOffsets(line,ty, ktyvars); + + /* Finally, stick the constructor's type onto it. */ + thd3(hd(constrs)) = ty; + } + + /* Final result is that + constrs :: [(ConId,[(Type,Text)],Type)] + lists the constructors and their types + sels :: [(VarId,Type)] + lists the selectors and their types + */ + tycon(tc).defn = addGHCConstrs(line,constrs0,sels); + } +# ifdef DEBUG_IFACE + fprintf(stderr, "end addGHCDataDecl %s\n",textToStr(t)); +# endif +} + + +static List local addGHCConstrs(line,cons,sels) +Int line; +List cons; /* [(ConId,[(Type,Text)],Type)] */ +List sels; { /* [(VarId,Type)] */ + List cs, ss; + Int conNo = 0; /* or maybe 1? */ + for(cs=cons; nonNull(cs); cs=tl(cs), conNo++) { + Name c = addGHCConstr(line,conNo,hd(cs)); + hd(cs) = c; + } + for(ss=sels; nonNull(ss); ss=tl(ss)) { + hd(ss) = addGHCSel(line,hd(ss)); + } + return appendOnto(cons,sels); +} + +static Name local addGHCSel(line,sel) +Int line; +Pair sel; /* (VarId,Type) */ +{ + Text t = textOf(fst(sel)); + Type type = snd(sel); + + Name n = findName(t); + if (nonNull(n)) { + ERRMSG(line) "Repeated definition for selector \"%s\"", + textToStr(t) + EEND; + } + + n = newName(t,NIL); + name(n).line = line; + name(n).number = SELNAME; + name(n).arity = 1; + name(n).defn = NIL; + + /* prepare for finishGHCVar */ + name(n).type = type; + ghcVarDecls = cons(n,ghcVarDecls); + + return n; +} + +static Name local addGHCConstr(line,conNo,constr) +Int line; +Int conNo; +Triple constr; { /* (ConId,[(Type,Text)],Type) */ + /* ToDo: add rank2 annotation and existential annotation + * these affect how constr can be used. + */ + Text con = textOf(fst3(constr)); + Type type = thd3(constr); + Int arity = arityFromType(type); + Name n = findName(con); /* Allocate constructor fun name */ + if (isNull(n)) { + n = newName(con,NIL); + } else if (name(n).defn!=PREDEFINED) { + ERRMSG(line) "Repeated definition for constructor \"%s\"", + textToStr(con) + EEND; + } + name(n).arity = arity; /* Save constructor fun details */ + name(n).line = line; + name(n).number = cfunNo(conNo); + + if (arity == 0) { + // expect to find the names + // Mod_Con_closure + // Mod_Con_static_closure + // Mod_Con_static_info + bindGHCNameTo(n, text_closure); + bindGHCNameTo(n, text_static_closure); + bindGHCNameTo(n, text_static_info); + } else { + // expect to find the names + // Mod_Con_closure + // Mod_Con_entry + // Mod_Con_info + // Mod_Con_con_info + // Mod_Con_static_info + bindGHCNameTo(n, text_closure); + bindGHCNameTo(n, text_entry); + bindGHCNameTo(n, text_info); + bindGHCNameTo(n, text_con_info); + bindGHCNameTo(n, text_static_info); + } + + /* prepare for finishGHCCon */ + name(n).type = type; + ghcConstrDecls = cons(n,ghcConstrDecls); + + return n; +} + +static Void local finishGHCConstr(Name n) +{ + Int line = name(n).line; + Type ty = name(n).type; + setCurrModule(name(n).mod); +# ifdef DEBUG_IFACE + printf ( "\nbegin finishGHCConstr %s\n", textToStr(name(n).text)); +# endif + name(n).type = conidcellsToTycons(line,ty); +# ifdef DEBUG_IFACE + printf ( "end finishGHCConstr %s\n", textToStr(name(n).text)); +# endif +} + + +Void addGHCNewType(line,ctx0,tycon,tvs,constr) +Int line; +List ctx0; /* [(QConId,VarId)] */ +Cell tycon; /* ConId | QualConId */ +List tvs; /* [(VarId,Kind)] */ +Cell constr; { /* (ConId,Type) */ + /* ToDo: worry about being given a decl for (->) ? + * and worry about qualidents for () + */ + List tmp; + Type resTy; + Text t = textOf(tycon); + if (nonNull(findTycon(t))) { + ERRMSG(line) "Repeated definition of type constructor \"%s\"", + textToStr(t) + EEND; + } else { + Tycon tc = newTycon(t); + tycon(tc).line = line; + tycon(tc).arity = length(tvs); + tycon(tc).what = NEWTYPE; + tycon(tc).kind = tvsToKind(tvs); + /* can't really do this until I've read in all synonyms */ + + assert(nonNull(constr)); + if (isNull(constr)) { + tycon(tc).defn = NIL; + } else { + /* constr :: (ConId,Type) */ + Text con = textOf(fst(constr)); + Type type = snd(constr); + Name n = findName(con); /* Allocate constructor fun name */ + if (isNull(n)) { + n = newName(con,NIL); + } else if (name(n).defn!=PREDEFINED) { + ERRMSG(line) "Repeated definition for constructor \"%s\"", + textToStr(con) + EEND; + } + name(n).arity = 1; /* Save constructor fun details */ + name(n).line = line; + name(n).number = cfunNo(0); + name(n).defn = nameId; + tycon(tc).defn = singleton(n); + + /* prepare for finishGHCCon */ + /* ToDo: we use finishGHCCon instead of finishGHCVar in case + * there's any existential quantification in the newtype - + * but I don't think that's allowed in newtype constrs. + * Still, no harm done by doing it this way... + */ + + /* make resTy the result type of the constr, T v1 ... vn */ + resTy = tycon; + for (tmp=tvs; nonNull(tmp); tmp=tl(tmp)) + resTy = ap(resTy,fst(hd(tmp))); + type = fn(type,resTy); + if (nonNull(ctx0)) + type = ap(QUAL,pair(ctx0,type)); + + type = tvsToOffsets(line,type,tvs); + + name(n).type = type; + ghcConstrDecls = cons(n,ghcConstrDecls); + } + } +} + +Void addGHCClass(line,ctxt,tc_name,tv,mems0) +Int line; +List ctxt; /* [(QConId, VarId)] */ +Cell tc_name; /* ConId */ +Text tv; /* VarId */ +List mems0; { /* [(VarId, Type)] */ + List mems; /* [(VarId, Type)] */ + List tvsInT; /* [VarId] and then [(VarId,Kind)] */ + List tvs; /* [(VarId,Kind)] */ + Text ct = textOf(tc_name); + Pair newCtx = pair(tc_name, tv); +# ifdef DEBUG_IFACE + printf ( "\nbegin addGHCclass %s\n", textToStr(ct) ); +# endif + if (nonNull(findClass(ct))) { + ERRMSG(line) "Repeated definition of class \"%s\"", + textToStr(ct) + EEND; + } else if (nonNull(findTycon(ct))) { + ERRMSG(line) "\"%s\" used as both class and type constructor", + textToStr(ct) + EEND; + } else { + Class nw = newClass(ct); + cclass(nw).text = ct; + cclass(nw).line = line; + cclass(nw).arity = 1; + cclass(nw).head = ap(nw,mkOffset(0)); + cclass(nw).kinds = singleton(STAR); /* absolutely no idea at all */ + cclass(nw).instances = NIL; /* what the kind should be */ + cclass(nw).numSupers = length(ctxt); + + /* Kludge to map the single tyvar in the context to Offset 0. + Need to do something better for multiparam type classes. + */ + cclass(nw).supers = tvsToOffsets(line,ctxt, + singleton(pair(tv,STAR))); + + for (mems=mems0; nonNull(mems); mems=tl(mems)) { + Pair mem = hd(mems); + Type memT = snd(mem); + + /* Stick the new context on the member type */ + if (whatIs(memT)==POLYTYPE) internal("addGHCClass"); + if (whatIs(memT)==QUAL) { + memT = pair(QUAL, + pair(cons(newCtx,fst(snd(memT))),snd(snd(memT)))); + } else { + memT = pair(QUAL, + pair(singleton(newCtx),memT)); + } + + /* Cook up a kind for the type. */ + tvsInT = nubList(ifTyvarsIn(memT)); + + /* ToDo: maximally bogus */ + for (tvs=tvsInT; nonNull(tvs); tvs=tl(tvs)) + hd(tvs) = pair(hd(tvs),STAR); + + memT = mkPolyType(tvsToKind(tvsInT),memT); + memT = tvsToOffsets(line,memT,tvsInT); + + /* Park the type back on the member */ + snd(mem) = memT; + } + + cclass(nw).members = mems0; + cclass(nw).numMembers = length(mems0); + ghcClassDecls = cons(nw,ghcClassDecls); + + /* ToDo: + * cclass(nw).dsels = ?; + * cclass(nw).dbuild = ?; + * cclass(nm).dcon = ?; + * cclass(nm).defaults = ?; + */ + } +# ifdef DEBUG_IFACE + printf ( "end addGHCclass %s\n", textToStr(ct) ); +# endif +} + +static Void local finishGHCClass(Class nw) +{ + List mems; + Int line = cclass(nw).line; + Int ctr = - length(cclass(nw).members); + +# ifdef DEBUG_IFACE + printf ( "\nbegin finishGHCclass %s\n", textToStr(cclass(nw).text) ); +# endif + + setCurrModule(cclass(nw).mod); + + cclass(nw).level = 0; /* ToDo: 1 + max (map level supers) */ + cclass(nw).head = conidcellsToTycons(line,cclass(nw).head); + cclass(nw).supers = conidcellsToTycons(line,cclass(nw).supers); + cclass(nw).members = conidcellsToTycons(line,cclass(nw).members); + + for (mems=cclass(nw).members; nonNull(mems); mems=tl(mems)) { + Pair mem = hd(mems); /* (VarId, Type) */ + Text txt = textOf(fst(mem)); + Type ty = snd(mem); + Name n = findName(txt); + if (nonNull(n)) { + ERRMSG(cclass(nw).line) + "Repeated definition for class method \"%s\"", + textToStr(txt) + EEND; + } + n = newName(txt,NIL); + name(n).line = cclass(nw).line; + name(n).type = ty; + name(n).number = ctr++; + hd(mems) = n; + } +# ifdef DEBUG_IFACE + printf ( "end finishGHCclass %s\n", textToStr(cclass(nw).text) ); +# endif +} + +Void addGHCInstance (line,ctxt0,cls,var) +Int line; +List ctxt0; /* [(QConId, Type)] */ +Pair cls; /* (ConId, [Type]) */ +Text var; { /* Text */ + List tmp, tvs, ks; + Inst in = newInst(); +# ifdef DEBUG_IFACE + printf ( "\nbegin addGHCInstance\n" ); +# endif + + /* Make tvs into a list of tyvars with bogus kinds. */ + tvs = nubList(ifTyvarsIn(snd(cls))); + ks = NIL; + for (tmp = tvs; nonNull(tmp); tmp=tl(tmp)) { + hd(tmp) = pair(hd(tmp),STAR); + ks = cons(STAR,ks); + } + + inst(in).line = line; + inst(in).implements = NIL; + inst(in).kinds = ks; + inst(in).specifics = tvsToOffsets(line,ctxt0,tvs); + inst(in).numSpecifics = length(ctxt0); + inst(in).head = tvsToOffsets(line,cls,tvs); +#if 0 +Is this still needed? + { + Name b = newName(inventText(),NIL); + name(b).line = line; + name(b).arity = length(ctxt); /* unused? */ + name(b).number = DFUNNAME; + inst(in).builder = b; + bindNameToClosure(b, lookupGHCClosure(inst(in).mod,var)); + } +#endif + ghcInstanceDecls = cons(in, ghcInstanceDecls); +# ifdef DEBUG_IFACE + printf ( "end addGHCInstance\n" ); +# endif +} + +static Void local finishGHCInstance(Inst in) +{ + Int line = inst(in).line; + Cell cl = fst(inst(in).head); + Class c; +# ifdef DEBUG_IFACE + printf ( "\nbegin finishGHCInstance\n" ); +# endif + + setCurrModule(inst(in).mod); + c = findClass(textOf(cl)); + if (isNull(c)) { + ERRMSG(line) "Unknown class \"%s\" in instance", + textToStr(textOf(cl)) + EEND; + } + inst(in).head = conidcellsToTycons(line,inst(in).head); + inst(in).specifics = conidcellsToTycons(line,inst(in).specifics); + cclass(c).instances = cons(in,cclass(c).instances); +# ifdef DEBUG_IFACE + printf ( "end finishGHCInstance\n" ); +# endif +} + +/* -------------------------------------------------------------------------- + * Helper fns + * ------------------------------------------------------------------------*/ + +/* This is called from the addGHC* functions. It traverses a structure + and converts varidcells, ie, type variables parsed by the interface + parser, into Offsets, which is how Hugs wants to see them internally. + The Offset for a type variable is determined by its place in the list + passed as the second arg; the associated kinds are irrelevant. +*/ +static Type local tvsToOffsets(line,type,ktyvars) +Int line; +Type type; +List ktyvars; { /* [(VarId|Text,Kind)] */ + switch (whatIs(type)) { + case NIL: + case TUPLE: + case QUALIDENT: + case CONIDCELL: + case TYCON: + return type; + case AP: + return ap( tvsToOffsets(line,fun(type),ktyvars), + tvsToOffsets(line,arg(type),ktyvars) ); + case POLYTYPE: + return mkPolyType ( + polySigOf(type), + tvsToOffsets(line,monotypeOf(type),ktyvars) + ); + break; + case QUAL: + return pair(QUAL,pair(tvsToOffsets(line,fst(snd(type)),ktyvars), + tvsToOffsets(line,snd(snd(type)),ktyvars))); + case VARIDCELL: /* Ha! some real work to do! */ + { Int i = 0; + Text tv = textOf(type); + for (; nonNull(ktyvars); i++,ktyvars=tl(ktyvars)) { + Cell varid = fst(hd(ktyvars)); + Text tt = isVar(varid) ? textOf(varid) : varid; + if (tv == tt) return mkOffset(i); + } + ERRMSG(line) "Undefined type variable \"%s\"", textToStr(tv) + EEND; + break; + } + default: + fprintf(stderr, "tvsToOffsets: unknown stuff %d\n", whatIs(type)); + print(type,20); + fprintf(stderr,"\n"); + assert(0); + } + assert(0); /* NOTREACHED */ +} + + +/* This is called from the finishGHC* functions. It traverses a structure + and converts conidcells, ie, type constructors parsed by the interface + parser, into Tycons (or Classes), which is how Hugs wants to see them + internally. Calls to this fn have to be deferred to the second phase + of interface loading (finishGHC* rather than addGHC*) so that all relevant + Tycons or Classes have been loaded into the symbol tables and can be + looked up. +*/ +static Type local conidcellsToTycons(line,type) +Int line; +Type type; { + switch (whatIs(type)) { + case NIL: + case OFFSET: + case TYCON: + case CLASS: + case VARIDCELL: + return type; + case QUALIDENT: + { List t; + Text m = qmodOf(type); + Text v = qtextOf(type); + Module mod = findModule(m); +printf ( "lookup qualident " ); print(type,100); printf("\n"); + if (isNull(mod)) { + ERRMSG(line) + "Undefined module in qualified name \"%s\"", + identToStr(type) + EEND; + return NIL; + } + for (t=module(mod).tycons; nonNull(t); t=tl(t)) + if (v == tycon(hd(t)).text) return hd(t); + for (t=module(mod).classes; nonNull(t); t=tl(t)) + if (v == cclass(hd(t)).text) return hd(t); + ERRMSG(line) + "Undefined qualified class or type \"%s\"", + identToStr(type) + EEND; + return NIL; + } + case CONIDCELL: + { Tycon tc; + Class cl; + tc = findQualTycon(type); + if (nonNull(tc)) return tc; + cl = findQualClass(type); + if (nonNull(cl)) return cl; + ERRMSG(line) + "Undefined class or type constructor \"%s\"", + identToStr(type) + EEND; + return NIL; + } + case AP: + return ap( conidcellsToTycons(line,fun(type)), + conidcellsToTycons(line,arg(type)) ); + case POLYTYPE: + return mkPolyType ( + polySigOf(type), + conidcellsToTycons(line,monotypeOf(type)) + ); + break; + case QUAL: + return pair(QUAL,pair(conidcellsToTycons(line,fst(snd(type))), + conidcellsToTycons(line,snd(snd(type))))); + default: + fprintf(stderr, "conidcellsToTycons: unknown stuff %d\n", + whatIs(type)); + print(type,20); + fprintf(stderr,"\n"); + assert(0); + } + assert(0); /* NOTREACHED */ +} + + +/* -------------------------------------------------------------------------- + * Utilities + * + * None of these do lookups or require that lookups have been resolved + * so they can be performed while reading interfaces. + * ------------------------------------------------------------------------*/ + +static Kinds local tvsToKind(tvs) +List tvs; { /* [(VarId,Kind)] */ + List rs; + Kinds r = STAR; + for (rs=reverse(tvs); nonNull(rs); rs=tl(rs)) { + r = ap(snd(hd(rs)),r); + } + return r; +} + +/* arity of a constructor with this type */ +static Int local arityFromType(type) +Type type; { + Int arity = 0; + if (isPolyType(type)) { + type = monotypeOf(type); + } + if (whatIs(type) == QUAL) { + type = snd(snd(type)); + } + if (whatIs(type) == EXIST) { + type = snd(snd(type)); + } + if (whatIs(type)==RANK2) { + type = snd(snd(type)); + } + while (isAp(type) && getHead(type)==typeArrow) { + arity++; + type = arg(type); + } + return arity; +} + + +static List local ifTyvarsIn(type) +Type type; { + List vs = typeVarsIn(type,NIL,NIL); + List vs2 = vs; + for (; nonNull(vs2); vs2=tl(vs2)) { + Cell v = hd(vs2); + if (whatIs(v)==VARIDCELL || whatIs(v)==VAROPCELL) { + hd(vs2) = textOf(hd(vs2)); + } else { + internal("ifTyvarsIn"); + } + } + return vs; +} + + +/* -------------------------------------------------------------------------- + * Dynamic loading code (probably shouldn't be here) + * + * o .hi file explicitly says which .so file to load. + * This avoids the need for a 1-to-1 relationship between .hi and .so files. + * + * ToDo: when doing a :reload, we ought to check the modification date + * on the .so file. + * + * o module handles are unloaded (dlclosed) when we call dropScriptsFrom. + * + * ToDo: do the same for foreign functions - but with complication that + * there may be multiple .so files + * ------------------------------------------------------------------------*/ + +typedef struct { char* name; void* addr; } RtsTabEnt; + +/* not really true */ +extern int stg_gc_enter_1; +extern int stg_chk_1; +extern int stg_update_PAP; +extern int __ap_2_upd_info; + +RtsTabEnt rtsTab[] + = { + { "stg_gc_enter_1", &stg_gc_enter_1 }, + { "stg_chk_1", &stg_chk_1 }, + { "stg_update_PAP", &stg_update_PAP }, + { "__ap_2_upd_info", &__ap_2_upd_info }, + {0,0} + }; + +char* strsuffix ( char* s, char* suffix ) +{ + int sl = strlen(s); + int xl = strlen(suffix); + if (xl > sl) return NULL; + if (0 == strcmp(s+sl-xl,suffix)) return s+sl-xl; + return NULL; +} + +char* lookupObjName ( char* nameT ) +{ + Text tm; + Text tn; + Text ts; + Name naam; + char* nm; + char* ty; + char* a; + Int k; + Pair pr; + + if (isupper(((int)(nameT[0])))) { + // name defined in a module, eg Mod_xyz_static_closure + // Place a zero after the module name, and after + // the symbol name proper + // --> Mod\0xyz\0static_closure + nm = strchr(nameT, '_'); + if (!nm) internal ( "lookupObjName"); + *nm = 0; + nm++; + if ((ty=strsuffix(nm, "_static_closure"))) + { *ty = 0; ty++; ts = text_static_closure; } + else + if ((ty=strsuffix(nm, "_static_info" ))) + { *ty = 0; ty++; ts = text_static_info; } + else + if ((ty=strsuffix(nm, "_con_info" ))) + { *ty = 0; ty++; ts = text_con_info; } + else + if ((ty=strsuffix(nm, "_con_entry" ))) + { *ty = 0; ty++; ts = text_con_entry; } + else + if ((ty=strsuffix(nm, "_info" ))) + { *ty = 0; ty++; ts = text_info; } + else + if ((ty=strsuffix(nm, "_entry" ))) + { *ty = 0; ty++; ts = text_entry; } + else + if ((ty=strsuffix(nm, "_closure" ))) + { *ty = 0; ty++; ts = text_closure; } + else { + fprintf(stderr, "lookupObjName: unknown suffix on %s\n", nameT ); + return NULL; + } + tm = findText(nameT); + tn = findText(nm); + //printf ( "\nlooking at mod `%s' var `%s' ext `%s' \n",textToStr(tm),textToStr(tn),textToStr(ts)); + naam = jrsFindQualName(tm,tn); + if (isNull(naam)) goto not_found; + pr = cellAssoc ( ts, name(naam).ghc_names ); + if (isNull(pr)) goto no_info; + return ptrOf(snd(pr)); + } + else { + // name presumably originating from the RTS + a = NULL; + for (k = 0; rtsTab[k].name; k++) { + if (0==strcmp(nameT,rtsTab[k].name)) { + a = rtsTab[k].addr; + break; + } + } + if (!a) goto not_found_rts; + return a; + } + +not_found: + fprintf ( stderr, + "lookupObjName: can't resolve name `%s'\n", + nameT ); + return NULL; +no_info: + fprintf ( stderr, + "lookupObjName: no info for name `%s'\n", + nameT ); + return NULL; +not_found_rts: + fprintf ( stderr, + "lookupObjName: can't resolve RTS name `%s'\n", + nameT ); + return NULL; +} + + +/* -------------------------------------------------------------------------- + * ELF specifics + * ------------------------------------------------------------------------*/ + +#include <elf.h> + +static char* local findElfSection ( void* objImage, Elf32_Word sh_type ) +{ + Int i; + char* ehdrC = (char*)objImage; + Elf32_Ehdr* ehdr = ( Elf32_Ehdr*)ehdrC; + Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff); + char* ptr = NULL; + for (i = 0; i < ehdr->e_shnum; i++) { + if (shdr[i].sh_type == sh_type && + i != ehdr->e_shstrndx) { + ptr = ehdrC + shdr[i].sh_offset; + break; + } + } + return ptr; +} + +static AsmClosure local findObjectSymbol_elfo ( void* objImage, char* name ) +{ + Int i, nent, j; + Elf32_Shdr* shdr; + Elf32_Sym* stab; + char* strtab; + char* ehdrC = (char*)objImage; + Elf32_Ehdr* ehdr = ( Elf32_Ehdr*)ehdrC; + shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff); + + strtab = findElfSection ( objImage, SHT_STRTAB ); + if (!strtab) internal("findObjectSymbol_elfo"); + + for (i = 0; i < ehdr->e_shnum; i++) { + if (shdr[i].sh_type != SHT_SYMTAB) continue; + stab = (Elf32_Sym*) (ehdrC + shdr[i].sh_offset); + nent = shdr[i].sh_size / sizeof(Elf32_Sym); + for (j = 0; j < nent; j++) { + if ( strcmp(strtab + stab[j].st_name, name) == 0 + && ELF32_ST_BIND(stab[j].st_info)==STB_GLOBAL ) { + return ehdrC + stab[j].st_value; + } + } + } + return NULL; +} + +static Void local resolveReferencesInObjectModule_elfo( objImage ) +void* objImage; { + char symbol[1000]; // ToDo + int i, j, k; + Elf32_Sym* stab; + char* strtab; + char* ehdrC = (char*)objImage; + Elf32_Ehdr* ehdr = (Elf32_Ehdr*) ehdrC; + Elf32_Shdr* shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff); + Elf32_Word* targ; + // first find "the" symbol table + //stab = findElfSection ( objImage, SHT_SYMTAB ); + + // also go find the string table + strtab = findElfSection ( objImage, SHT_STRTAB ); + + if (!stab || !strtab) + internal("resolveReferencesInObjectModule_elfo"); + + for (i = 0; i < ehdr->e_shnum; i++) { + if (shdr[i].sh_type == SHT_REL ) { + Elf32_Rel* rtab = (Elf32_Rel*) (ehdrC + shdr[i].sh_offset); + Int nent = shdr[i].sh_size / sizeof(Elf32_Rel); + Int target_shndx = shdr[i].sh_info; + Int symtab_shndx = shdr[i].sh_link; + stab = (Elf32_Sym*) (ehdrC + shdr[ symtab_shndx ].sh_offset); + targ = (Elf32_Word*)(ehdrC + shdr[ target_shndx ].sh_offset); + printf ( "relocations for section %d using symtab %d\n", target_shndx, symtab_shndx ); + for (j = 0; j < nent; j++) { + Elf32_Addr offset = rtab[j].r_offset; + Elf32_Word info = rtab[j].r_info; + + Elf32_Addr P = ((Elf32_Addr)targ) + offset; + Elf32_Word* pP = (Elf32_Word*)P; + Elf32_Addr A = *pP; + Elf32_Addr S; + + printf ("Rel entry %3d is raw(%6p %6p) ", j, (void*)offset, (void*)info ); + if (!info) { + printf ( " ZERO\n" ); + S = 0; + } else { + strcpy ( symbol, strtab+stab[ ELF32_R_SYM(info)].st_name ); + printf ( "`%s' ", symbol ); + if (symbol[0] == 0) { + printf ( "-- ignore?\n" ); + S = 0; + } + else { + S = (Elf32_Addr)lookupObjName ( symbol ); + printf ( "resolves to %p\n", (void*)S ); + } + } + switch (ELF32_R_TYPE(info)) { + case R_386_32: *pP = S + A; break; + case R_386_PC32: *pP = S + A - P; break; + default: fprintf(stderr, + "unhandled ELF relocation type %d\n", + ELF32_R_TYPE(info)); + assert(0); + } + + } + } + else + if (shdr[i].sh_type == SHT_RELA) { + printf ( "RelA " ); + } + } +} + +static Bool local validateOImage_elfo ( void* imgV, Int size ) +{ + Elf32_Shdr* shdr; + Elf32_Sym* stab; + int i, j, nent, nstrtab, nsymtabs; + char* sh_strtab; + char* strtab; + + char* ehdrC = (char*)imgV; + Elf32_Ehdr* ehdr = ( Elf32_Ehdr*)ehdrC; + + if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || + ehdr->e_ident[EI_MAG1] != ELFMAG1 || + ehdr->e_ident[EI_MAG2] != ELFMAG2 || + ehdr->e_ident[EI_MAG3] != ELFMAG3) { + printf ( "Not an ELF header\n" ); + return FALSE; + } + printf ( "Is an ELF header\n" ); + + if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) { + printf ( "Not 32 bit ELF\n" ); + return FALSE; + } + printf ( "Is 32 bit ELF\n" ); + + if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) { + printf ( "Is little-endian\n" ); + } else + if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) { + printf ( "Is big-endian\n" ); + } else { + printf ( "Unknown endiannness\n" ); + return FALSE; + } + + if (ehdr->e_type != ET_REL) { + printf ( "Not a relocatable object (.o) file\n" ); + return FALSE; + } + printf ( "Is a relocatable object (.o) file\n" ); + + printf ( "Architecture is " ); + switch (ehdr->e_machine) { + case EM_386: printf ( "x86\n" ); break; + case EM_SPARC: printf ( "sparc\n" ); break; + default: printf ( "unknown\n" ); return FALSE; + } + + printf ( "\nSection header table: start %d, n_entries %d, ent_size %d\n", + ehdr->e_shoff, ehdr->e_shnum, ehdr->e_shentsize ); + + assert (ehdr->e_shentsize == sizeof(Elf32_Shdr)); + + shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff); + + if (ehdr->e_shstrndx == SHN_UNDEF) { + printf ( "No section header string table\n" ); + sh_strtab = NULL; + } else { + printf ( "Section header string table is section %d\n", + ehdr->e_shstrndx); + sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset; + } + + for (i = 0; i < ehdr->e_shnum; i++) { + printf ( "%2d: ", i ); + printf ( "type=%2d ", shdr[i].sh_type ); + printf ( "size=%4d ", shdr[i].sh_size ); + if (shdr[i].sh_type == SHT_REL ) printf ( "Rel " ); else + if (shdr[i].sh_type == SHT_RELA) printf ( "RelA " ); else + printf ( " " ); + if (sh_strtab) printf ( "sname=%s", sh_strtab + shdr[i].sh_name ); + printf ( "\n" ); + } + + printf ( "\n\nString tables\n" ); + strtab = NULL; + nstrtab = 0; + for (i = 0; i < ehdr->e_shnum; i++) { + if (shdr[i].sh_type == SHT_STRTAB && + i != ehdr->e_shstrndx) { + printf ( " section %d is a normal string table\n", i ); + strtab = ehdrC + shdr[i].sh_offset; + nstrtab++; + } + } + if (nstrtab != 1) + printf ( "WARNING: no string tables, or too many\n" ); + + nsymtabs = 0; + printf ( "\n\nSymbol tables\n" ); + for (i = 0; i < ehdr->e_shnum; i++) { + if (shdr[i].sh_type != SHT_SYMTAB) continue; + printf ( "section %d is a symbol table\n", i ); + nsymtabs++; + stab = (Elf32_Sym*) (ehdrC + shdr[i].sh_offset); + nent = shdr[i].sh_size / sizeof(Elf32_Sym); + printf ( " number of entries is apparently %d (%d rem)\n", + nent, + shdr[i].sh_size % sizeof(Elf32_Sym) + ); + if (0 != shdr[i].sh_size % sizeof(Elf32_Sym)) { + printf ( "non-integral number of symbol table entries\n"); + return FALSE; + } + for (j = 0; j < nent; j++) { + printf ( " %2d ", j ); + printf ( " sec=%-5d size=%-3d val=%-5p ", + (int)stab[j].st_shndx, + (int)stab[j].st_size, + (char*)stab[j].st_value ); + + printf ( "type=" ); + switch (ELF32_ST_TYPE(stab[j].st_info)) { + case STT_NOTYPE: printf ( "notype " ); break; + case STT_OBJECT: printf ( "object " ); break; + case STT_FUNC : printf ( "func " ); break; + case STT_SECTION: printf ( "section" ); break; + case STT_FILE: printf ( "file " ); break; + default: printf ( "? " ); break; + } + printf ( " " ); + + printf ( "bind=" ); + switch (ELF32_ST_BIND(stab[j].st_info)) { + case STB_LOCAL : printf ( "local " ); break; + case STB_GLOBAL: printf ( "global" ); break; + case STB_WEAK : printf ( "weak " ); break; + default: printf ( "? " ); break; + } + printf ( " " ); + + printf ( "name=%s\n", strtab + stab[j].st_name ); + } + } + + if (nsymtabs == 0) { + printf ( "Didn't find any symbol tables\n" ); + return FALSE; + } + + return TRUE; +} + + +/* -------------------------------------------------------------------------- + * Generic lookups + * ------------------------------------------------------------------------*/ + +static Void local bindGHCNameTo ( Name n, Text suffix ) +{ + char symbol[1000]; /* ToDo: arbitrary constants must die */ + AsmClosure res; + sprintf(symbol,"%s_%s_%s", + textToStr(module(currentModule).text), + textToStr(name(n).text),textToStr(suffix)); + // fprintf(stderr, "\nbindGHCNameTo %s ", symbol); + res = findObjectSymbol_elfo ( module(currentModule).oImage, symbol ); + if (!res) { + ERRMSG(0) "Can't find symbol \"%s\" in object for module \"%s\"", + symbol, + textToStr(module(currentModule).text) + EEND; + } + //fprintf(stderr, " = %p\n", res ); + name(n).ghc_names = cons(pair(suffix,mkPtr(res)), name(n).ghc_names); + + // set the stgVar to be a CPTRCELL to the closure label. + // prefer dynamic over static closures if given a choice + if (suffix == text_closure || suffix == text_static_closure) { + if (isNull(name(n).stgVar)) { + // accept any old thing + name(n).stgVar = mkCPtr(res); + } else { + // only accept something more dynamic that what we have now + if (suffix != text_static_closure + && isCPtr(name(n).stgVar) + && cptrOf(name(n).stgVar) != res) + name(n).stgVar = mkCPtr(res); + } + } +} + +static Void local resolveReferencesInObjectModule ( Module m ) +{ +fprintf(stderr, "resolveReferencesInObjectModule %s\n",textToStr(module(m).text)); + resolveReferencesInObjectModule_elfo ( module(m).oImage ); +} + +static Bool local validateOImage(img,size) +void* img; +Int size; { + return validateOImage_elfo ( img, size ); +} + + +/* -------------------------------------------------------------------------- + * Control: + * ------------------------------------------------------------------------*/ + +Void interface(what) +Int what; { + switch (what) { + case INSTALL: + case RESET: + ifImports = NIL; + ghcVarDecls = NIL; + ghcConstrDecls = NIL; + ghcSynonymDecls = NIL; + ghcClassDecls = NIL; + ghcInstanceDecls = NIL; + ghcExports = NIL; + ghcImports = NIL; + ghcModules = NIL; + text_info = findText("info"); + text_entry = findText("entry"); + text_closure = findText("closure"); + text_static_closure = findText("static_closure"); + text_static_info = findText("static_info"); + text_con_info = findText("con_info"); + text_con_entry = findText("con_entry"); + break; + case MARK: + mark(ifImports); + mark(ghcVarDecls); + mark(ghcConstrDecls); + mark(ghcSynonymDecls); + mark(ghcClassDecls); + mark(ghcInstanceDecls); + mark(ghcImports); + mark(ghcExports); + mark(ghcModules); + break; + } +} + +/*-------------------------------------------------------------------------*/ diff --git a/ghc/interpreter/link.h b/ghc/interpreter/link.h index 6caf0e448dbb7b5e4a311274d27a14da808b262e..b87a0e7b25c1ed0e81819b6ba520bc69217f52f8 100644 --- a/ghc/interpreter/link.h +++ b/ghc/interpreter/link.h @@ -130,3 +130,5 @@ extern Cell predFractional;; /* Fractional (mkOffset(0)) extern Cell predIntegral;; /* Integral (mkOffset(0)) */ extern Kind starToStar;; /* Type -> Type */ extern Cell predMonad;; /* Monad (mkOffset(0)) */ + + diff --git a/ghc/interpreter/machdep.c b/ghc/interpreter/machdep.c index ebdf4bb28fe1194b841e343a13d07280a938544b..2847b4141e4d560353d64455666868bad15ab5b0 100644 --- a/ghc/interpreter/machdep.c +++ b/ghc/interpreter/machdep.c @@ -12,8 +12,8 @@ * in the distribution for details. * * $RCSfile: machdep.c,v $ - * $Revision: 1.5 $ - * $Date: 1999/04/27 10:06:55 $ + * $Revision: 1.6 $ + * $Date: 1999/06/07 17:22:37 $ * ------------------------------------------------------------------------*/ #ifdef HAVE_SIGNAL_H @@ -133,14 +133,16 @@ static String local readRegChildStrings Args((HKEY, String, String, Char, String typedef struct { unsigned hi, lo; } Time; #define timeChanged(now,thn) (now.hi!=thn.hi || now.lo!=thn.lo) #define timeSet(var,tm) var.hi = tm.hi; var.lo = tm.lo +error timeEarlier not defined #else typedef time_t Time; -#define timeChanged(now,thn) (now!=thn) -#define timeSet(var,tm) var = tm +#define timeChanged(now,thn) (now!=thn) +#define timeSet(var,tm) var = tm +#define timeEarlier(earlier,now) (earlier < now) #endif -static Void local getFileInfo Args((String, Time *, Long *)); static Bool local readable Args((String)); +static Void local getFileInfo Args((String, Time *, Long *)); static Void local getFileInfo(f,tm,sz) /* find time stamp and size of file*/ String f; @@ -149,10 +151,10 @@ Long *sz; { #if defined HAVE_SYS_STAT_H || defined HAVE_STAT_H || defined HAVE_UNIX_H struct stat scbuf; if (!stat(f,&scbuf)) { - *tm = scbuf.st_mtime; + if (tm) *tm = scbuf.st_mtime; *sz = (Long)(scbuf.st_size); } else { - *tm = 0; + if (tm) *tm = 0; *sz = 0; } #else /* normally just use stat() */ @@ -161,15 +163,20 @@ Long *sz; { r.r[1] = (int)s; os_swi(OS_File, &r); if(r.r[0] == 1 && (r.r[2] & 0xFFF00000) == 0xFFF00000) { - tm->hi = r.r[2] & 0xFF; /* Load address (high byte) */ - tm->lo = r.r[3]; /* Execution address (low 4 bytes) */ + if (tm) tm->hi = r.r[2] & 0xFF; /* Load address (high byte) */ + if (tm) tm->lo = r.r[3]; /* Execution address (low 4 bytes) */ } else { /* Not found, or not time-stamped */ - tm->hi = tm->lo = 0; + if (tm) tm->hi = tm->lo = 0; } *sz = (Long)(r.r[0] == 1 ? r.r[4] : 0); #endif } +Void getFileSize ( String f, Long* sz ) +{ + getFileInfo ( f, NULL, sz ); +} + #if defined HAVE_GETFINFO /* Mac971031 */ /* -------------------------------------------------------------------------- * Define a MacOS version of access(): @@ -210,6 +217,7 @@ String f; { return (0 == access(f,4)); #elif defined HAVE_SYS_STAT_H || defined HAVE_STAT_H struct stat scbuf; + //fprintf(stderr, "readable: %s\n", f ); return ( !stat(f,&scbuf) && (scbuf.st_mode & S_IREAD) /* readable */ && (scbuf.st_mode & S_IFREG) /* regular file */ @@ -255,7 +263,7 @@ static Bool local tryEndings Args((String)); # define SLASH '/' # define isSLASH(c) ((c)==SLASH) # define PATHSEP ':' -# define DLL_ENDING ".so" +# define DLL_ENDING ".o" #endif static String local hugsdir() { /* directory containing lib/Prelude.hs */ @@ -367,9 +375,9 @@ String s; { /* a pathname in some appropriate manner. */ } #if HSCRIPT -static String endings[] = { "", ".hs", ".lhs", ".hsx", ".hash", 0 }; +static String endings[] = { "", ".hi", ".hs", ".lhs", ".hsx", ".hash", 0 }; #else -static String endings[] = { "", ".hs", ".lhs", 0 }; +static String endings[] = { "", ".hi", ".hs", ".lhs", 0 }; #endif static char searchBuf[FILENAME_MAX+1]; static Int searchPos; @@ -413,9 +421,9 @@ String s; { searches the base directory and its direct subdirectories for a file input: searchbuf contains SLASH terminated base directory - argument s contains the (base) filename + argument s contains the (base) filename output: TRUE: searchBuf contains the full filename - FALSE: searchBuf is garbage, file not found + FALSE: searchBuf is garbage, file not found */ @@ -587,6 +595,124 @@ String path; { return (tryEndings(nm) ? normPath(searchBuf) : 0); } +/* -------------------------------------------------------------------------- + * New path handling stuff for the Combined System (tm) + * ------------------------------------------------------------------------*/ + +Bool findFilesForModule ( + String modName, + String* path, + String* sExt, + Bool* sAvail, Time* sTime, Long* sSize, + Bool* iAvail, Time* iTime, Long* iSize, + Bool* oAvail, Time* oTime, Long* oSize + ) +{ + /* Let the module name given be M. + For each path entry P, + a s(rc) file will be P/M.hs or P/M.lhs + an i(nterface) file will be P/M.hi + an o(bject) file will be P/M.o + If there is a s file or (both i and o files) + use P to fill in the path names. + Otherwise, move on to the next path entry. + If all path entries are exhausted, return False. + */ + Int nPath; + Bool literate; + String peStart, peEnd; + String augdPath; /* . and then hugsPath */ + + *path = *sExt = NULL; + *sAvail = *iAvail = *oAvail = FALSE; + *sSize = *iSize = *oSize = 0; + + augdPath = malloc(3+strlen(hugsPath)); + if (!augdPath) + internal("moduleNameToFileNames: malloc failed(2)"); + augdPath[0] = '.'; + augdPath[1] = PATHSEP; + augdPath[2] = 0; + strcat(augdPath,hugsPath); + + peEnd = augdPath-1; + while (1) { + /* Advance peStart and peEnd very paranoically, giving up at + the first sign of mutancy in the path string. + */ + if (peEnd >= augdPath && !(*peEnd)) { free(augdPath); return FALSE; } + peStart = peEnd+1; + peEnd = peStart; + while (*peEnd && *peEnd != PATHSEP) peEnd++; + + /* Now peStart .. peEnd-1 bracket the next path element. */ + nPath = peEnd-peStart; + if (nPath + strlen(modName) + 10 /*slush*/ > FILENAME_MAX) { + ERRMSG(0) "Hugs path \"%s\" contains excessively long component", + hugsPath + EEND; + free(augdPath); + return FALSE; + } + + strncpy(searchBuf, peStart, nPath); + searchBuf[nPath] = 0; + if (nPath > 0 && !isSLASH(searchBuf[nPath-1])) + searchBuf[nPath++] = SLASH; + + strcpy(searchBuf+nPath, modName); + nPath += strlen(modName); + + /* searchBuf now holds 'P/M'. Try out the various endings. */ + *path = *sExt = NULL; + *sAvail = *iAvail = *oAvail = FALSE; + *sSize = *iSize = *oSize = 0; + + strcpy(searchBuf+nPath, DLL_ENDING); + if (readable(searchBuf)) { + *oAvail = TRUE; + getFileInfo(searchBuf, oTime, oSize); + } + + strcpy(searchBuf+nPath, ".hi"); + if (readable(searchBuf)) { + *iAvail = TRUE; + getFileInfo(searchBuf, iTime, iSize); + } + + strcpy(searchBuf+nPath, ".hs"); + if (readable(searchBuf)) { + *sAvail = TRUE; + literate = FALSE; + getFileInfo(searchBuf, sTime, sSize); + *sExt = ".hs"; + } else { + strcpy(searchBuf+nPath, ".lhs"); + if (readable(searchBuf)) { + *sAvail = TRUE; + literate = TRUE; + getFileInfo(searchBuf, sTime, sSize); + *sExt = ".lhs"; + } + } + + /* Success? */ + if (*sAvail || (*oAvail && *iAvail)) { + nPath -= strlen(modName); + *path = malloc(nPath+1); + if (!(*path)) + internal("moduleNameToFileNames: malloc failed(1)"); + strncpy(*path, searchBuf, nPath); + (*path)[nPath] = 0; + free(augdPath); + return TRUE; + } + + } + +} + + /* -------------------------------------------------------------------------- * Substitute old value of path into empty entries in new path * eg substPath("a:b:c::d:e","x:y:z") = "a:b:c:x:y:z:d:e" diff --git a/ghc/interpreter/parser.y b/ghc/interpreter/parser.y index 60e565c6e8a3ec66c0fb510fe72a00d994e1e29d..c746368b9d03696bf60e9b8f316cc47545b4c615 100644 --- a/ghc/interpreter/parser.y +++ b/ghc/interpreter/parser.y @@ -11,8 +11,8 @@ * in the distribution for details. * * $RCSfile: parser.y,v $ - * $Revision: 1.5 $ - * $Date: 1999/04/27 10:06:58 $ + * $Revision: 1.6 $ + * $Date: 1999/06/07 17:22:41 $ * ------------------------------------------------------------------------*/ %{ @@ -28,7 +28,8 @@ #define only(t) ap(ONLY,t) #define letrec(bs,e) (nonNull(bs) ? ap(LETREC,pair(bs,e)) : e) #define qualify(ps,t) (nonNull(ps) ? ap(QUAL,pair(ps,t)) : t) -#define exportSelf() singleton(ap(MODULEENT,mkCon(module(currentModule).text))) +#define exportSelf() singleton(ap(MODULEENT, \ + mkCon(module(currentModule).text))) #define yyerror(s) /* errors handled elsewhere */ #define YYSTYPE Cell @@ -36,6 +37,7 @@ static Cell local gcShadow Args((Int,Cell)); static Void local syntaxError Args((String)); static String local unexpected Args((Void)); static Cell local checkPrec Args((Cell)); +static Void local fixDefn Args((Syntax,Cell,Cell,List)); static Cell local buildTuple Args((List)); static List local checkContext Args((List)); static Cell local checkPred Args((Cell)); @@ -87,17 +89,295 @@ static Void local noTREX Args((String)); %token '!' IMPLIES '(' ',' ')' %token '[' ';' ']' '`' '.' %token TMODULE IMPORT HIDING QUALIFIED ASMOD -%token EXPORT UNSAFE +%token EXPORT INTERFACE REQUIRES UNSAFE INSTIMPORT %% /*- Top level script/module structure -------------------------------------*/ start : EXPR exp wherePart {inputExpr = letrec($3,$2); sp-=2;} | SCRIPT topModule {valDefns = $2; sp-=1;} + | INTERFACE iface {sp-=1;} | error {syntaxError("input");} ; + +/*- GHC interface file parsing: -------------------------------------------*/ + +/* Reading in an interface file is surprisingly like reading + * a normal Haskell module: we read in a bunch of declarations, + * construct symbol table entries, etc. The "only" differences + * are that there's no syntactic sugar to deal with and we don't + * have to read in expressions. + */ + +/*- Top-level interface files -----------------------------*/ +iface : INTERFACE ifName NUMLIT checkVersion WHERE ifDecls + {$$ = gc6(NIL); } + | INTERFACE error {syntaxError("interface file");} + ; +ifDecls: {$$=gc0(NIL);} + | ifDecl ';' ifDecls {$$=gc3(cons($1,$3));} + ; +varid_or_conid + : VARID { $$=gc1($1); } + | CONID { $$=gc1($1); } + ; +opt_bang : '!' {$$=gc1(NIL);} + | {$$=gc0(NIL);} + ; +ifName : CONID {openGHCIface(textOf($1)); + $$ = gc1(NIL);} +checkVersion + : NUMLIT {$$ = gc1(NIL); } + ; +ifDecl + : IMPORT CONID opt_bang NUMLIT COCO version_list_junk + { addGHCImports(intOf($4),textOf($2), + $6); + $$ = gc6(NIL); + } + + | INSTIMPORT CONID {$$=gc2(NIL);} + + | EXPORT CONID ifEntities { addGHCExports($2,$3); + $$=gc3(NIL);} + + | NUMLIT INFIXL optDigit varid_or_conid + {$$ = gc4(fixdecl($2,singleton($4), + LEFT_ASS,$3)); } + | NUMLIT INFIXR optDigit varid_or_conid + {$$ = gc4(fixdecl($2,singleton($4), + RIGHT_ASS,$3)); } + | NUMLIT INFIXN optDigit varid_or_conid + {$$ = gc4(fixdecl($2,singleton($4), + NON_ASS,$3)); } + + | TINSTANCE ifCtxInst ifInstHd '=' ifVar + { addGHCInstance(intOf($1),$2,$3, + textOf($5)); + $$ = gc5(NIL); } + | NUMLIT TYPE ifCon ifKindedTyvarL '=' ifType + { addGHCSynonym(intOf($2),$3,$4,$6); + $$ = gc6(NIL); } + + | NUMLIT DATA ifCtxDecl ifConData ifKindedTyvarL ifConstrs + { addGHCDataDecl(intOf($2), + $3,$4,$5,$6); + $$ = gc6(NIL); } + + | NUMLIT TNEWTYPE ifCtxDecl ifConData ifKindedTyvarL ifNewTypeConstr + { addGHCNewType(intOf($2), + $3,$4,$5,$6); + $$ = gc6(NIL); } + | NUMLIT TCLASS ifCtxDecl ifCon ifTyvar ifCmeths + { addGHCClass(intOf($2),$3,$4,$5,$6); + $$ = gc6(NIL); } + | NUMLIT ifVar COCO ifType + { addGHCVar(intOf($3),textOf($2),$4); + $$ = gc4(NIL); } + | error { syntaxError( + "interface declaration"); } + ; + + +/*- Interface variable and constructor ids ----------------*/ +ifTyvar : VARID {$$ = $1;} + ; +ifVar : VARID {$$ = gc1($1);} + ; +ifCon : CONID {$$ = gc1($1);} + ; +ifQCon : CONID {$$ = gc1($1);} + | QCONID {$$ = gc1($1);} + ; +ifConData : ifCon {$$ = gc1($1);} + | '(' ')' {$$ = gc2(typeUnit);} + | '[' ']' {$$ = gc2(typeList);} + | '(' ARROW ')' {$$ = gc3(typeArrow);} + ; +ifTCName : CONID { $$ = gc1($1); } + | CONOP { $$ = gc1($1); } + | '(' ARROW ')' { $$ = gc3(typeArrow); } + | '[' ']' { $$ = gc1(typeList); } + ; +ifQTCName : ifTCName { $$ = gc1($1); } + | QCONID { $$ = gc1($1); } + | QCONOP { $$ = gc1($1); } + ; + + +/*- Interface contexts ------------------------------------*/ +ifCtxInst /* __forall [a b] {M.C1 a, M.C2 b} => */ + /* :: [(QConId, VarId)] */ + : ALL ifForall ifCtxDecl {$$=gc3($3);} + | ALL ifForall IMPLIES {$$=gc3(NIL);} + | {$$=gc0(NIL);} + ; +ifInstHd /* { Class aType } :: (ConId, Type) */ + : '{' ifCon ifAType '}' {$$=gc4(pair($2,$3));} + ; + +ifCtxDecl /* {M.C1 a, C2 b} :: [(QConId, VarId)] */ + : { $$ = gc0(NIL); } + | '{' ifCtxDeclL '}' IMPLIES { $$ = gc4($2); } + ; +ifCtxDeclT /* {M.C1 a, C2 b} :: [(QConId, VarId)] */ + : { $$ = gc0(NIL); } + | '{' ifCtxDeclL '}' { $$ = gc3($2); } + ; +ifCtxDeclL /* M.C1 a, C2 b :: [(QConId, VarId)] */ + : ifCtxDeclLE ',' ifCtxDeclL {$$=gc3(cons($1,$3));} + | ifCtxDeclLE {$$=gc1(cons($1,NIL));} + | {$$=gc0(NIL);} + ; +ifCtxDeclLE /* M.C1 a :: (QConId,VarId) */ + : ifQCon ifTyvar {$$=gc2(pair($1,$2));} + ; + + +/*- Interface data declarations - constructor lists -------*/ +ifConstrs /* = Con1 | ... | ConN :: [(ConId,[(Type,Text)],NIL)] */ + : {$$ = gc0(NIL);} + | '=' ifConstrL {$$ = gc2($2);} + ; +ifConstrL /* [(ConId,[(Type,Text)],NIL)] */ + : ifConstr {$$ = gc1(singleton($1));} + | ifConstr '|' ifConstrL {$$ = gc3(cons($1,$3));} + ; +ifConstr /* (ConId,[(Type,Text)],NIL) */ + : ifConData ifDataAnonFieldL {$$ = gc2(triple($1,$2,NIL));} + | ifConData '{' ifDataNamedFieldL '}' + {$$ = gc4(triple($1,$3,NIL));} + ; +ifDataAnonFieldL /* [(Type,Text)] */ + : {$$=gc0(NIL);} + | ifDataAnonField ifDataAnonFieldL + {$$=gc2(cons($1,$2));} + ; +ifDataNamedFieldL /* [(Type,Text)] */ + : {$$=gc0(NIL);} + | ifDataNamedField {$$=gc1(cons($1,NIL));} + | ifDataNamedField ',' ifDataNamedFieldL + {$$=gc3(cons($1,$3));} + ; +ifDataAnonField /* (Type,Text) */ + : ifAType {$$=gc1(pair($1,NIL));} + ; +ifDataNamedField /* (Type,Text) */ + : VARID COCO ifAType {$$=gc3(pair($3,$1));} + ; + + +/*- Interface class declarations - methods ----------------*/ +ifCmeths /* [(VarId,Type)] */ + : { $$ = gc0(NIL); } + | WHERE '{' ifCmethL '}' { $$ = gc4($3); } + ; +ifCmethL /* [(VarId,Type)] */ + : ifCmeth { $$ = gc1(singleton($1)); } + | ifCmeth ';' ifCmethL { $$ = gc3(cons($1,$3)); } + ; +ifCmeth /* (VarId,Type) */ + : ifVar COCO ifType { $$ = gc3(pair($1,$3)); } + | ifVar '=' COCO ifType { $$ = gc4(pair($1,$4)); } + /* has default method */ + ; + + +/*- Interface newtype declararions ------------------------*/ +ifNewTypeConstr /* (ConId,Type) */ + : '=' ifCon ifAType { $$ = gc3(pair($2,$3)); } + ; + + +/*- Interface type expressions ----------------------------*/ +ifType : ALL ifForall ifCtxDeclT IMPLIES ifType + { if ($3 == NIL) + $$=gc5($5); else + $$=gc5(pair(QUAL,pair($3,$5))); + } + | ifBType ARROW ifType { $$ = gc3(fn($1,$3)); } + | ifBType { $$ = gc1($1); } + ; +ifForall /* [(VarId,Kind)] */ + : '[' ifKindedTyvarL ']' { $$ = gc3($2); } + ; +ifTypes2 : ifType ',' ifType { $$ = gc3(doubleton($1,$3)); } + | ifType ',' ifTypes2 { $$ = gc3(cons($1,$3)); } + ; +ifBType : ifAType { $$ = gc1($1); } + | ifBType ifAType { $$ = gc2(ap($1,$2)); } + ; +ifAType : ifQTCName { $$ = gc1($1); } + | ifTyvar { $$ = gc1($1); } + | '(' ')' { $$ = gc2(typeUnit); } + | '(' ifTypes2 ')' { $$ = gc3(buildTuple($2)); } + | '[' ifType ']' { $$ = gc3(ap(typeList,$2));} + | '{' ifQTCName ifATypes '}' { $$ = gc4(ap(DICTAP, + pair($2,$3))); } + | '(' ifType ')' { $$ = gc3($2); } + ; +ifATypes : { $$ = gc0(NIL); } + | ifAType ifATypes { $$ = gc2(cons($1,$2)); } + ; + + +/*- Interface kinds ---------------------------------------*/ +ifKindedTyvarL /* [(VarId,Kind)] */ + : { $$ = gc0(NIL); } + | ifKindedTyvar ifKindedTyvarL { $$ = gc2(cons($1,$2)); } + ; +ifKindedTyvar /* (VarId,Kind) */ + : ifTyvar { $$ = gc1(pair($1,STAR)); } + | ifTyvar COCO ifAKind { $$ = gc3(pair($1,$3)); } + ; +ifKind : ifAKind { $$ = gc1($1); } + | ifAKind ARROW ifKind { $$ = gc3(fn($1,$3)); } + ; +ifAKind : VAROP { $$ = gc1(STAR); } + /* should be '*' */ + | '(' ifKind ')' { $$ = gc3($2); } + ; + + +/*- Interface version/export/import stuff -----------------*/ +ifEntities + : { $$ = gc0(NIL); } + | ifEntity ifEntities { $$ = gc2(cons($1,$2)); } + ; +ifEntity + : ifEntityOcc {$$=gc1($1);} + | ifEntityOcc ifStuffInside {$$=gc2($1);} + | ifEntityOcc '|' ifStuffInside {$$=gc3($1);} + /* exporting datacons but not tycon */ + ; +ifEntityOcc + : ifVar { $$ = gc1($1); } + | ifCon { $$ = gc1($1); } + | ARROW { $$ = gc1(typeArrow); } + | '(' ARROW ')' { $$ = gc3(typeArrow); } + /* why allow both? */ + ; +ifStuffInside + : '{' ifValOccs '}' { $$ = gc3($2); } + ; +ifValOccs + : ifValOcc { $$ = gc1(singleton($1)); } + | ifValOcc ifValOccs { $$ = gc2(cons($1,$2)); } + ; +ifValOcc + : ifVar {$$ = gc1($1); } + | ifCon {$$ = gc1($1); } + ; +version_list_junk + : {$$=gc0(NIL);} + | VARID NUMLIT version_list_junk {$$=gc3(cons($1,$3));} + | CONID NUMLIT version_list_junk {$$=gc3(cons($1,$3));} + ; + + /*- Haskell module header/import parsing: ----------------------------------- + * Syntax for Haskell modules (module headers and imports) is parsed but * most of it is ignored. However, module names in import declarations * are used, of course, if import chasing is turned on. @@ -108,7 +388,10 @@ start : EXPR exp wherePart {inputExpr = letrec($3,$2); sp-=2;} * We use the 1.2 header because it breaks much less pre-module code. */ topModule : startMain begin modBody end { - setExportList(singleton(ap(MODULEENT,mkCon(module(currentModule).text)))); + setExportList(singleton( + ap(MODULEENT, + mkCon(module(currentModule).text) + ))); $$ = gc3($3); } | TMODULE modname expspec WHERE '{' modBody end @@ -126,8 +409,11 @@ modname : CONID {startModule($1); $$ = gc1(NIL);} ; modid : CONID {$$ = $1;} | STRINGLIT { extern String scriptFile; - String modName = findPathname(scriptFile,textToStr(textOf($1))); - if (modName) { /* fillin pathname if known */ + String modName + = findPathname(scriptFile, + textToStr(textOf($1))); + if (modName) { + /* fillin pathname if known */ $$ = mkStr(findText(modName)); } else { $$ = $1; @@ -252,7 +538,7 @@ topDecl : TYPE tyLhs '=' type {defTycon(4,$3,$2,$4,SYNONYM);} | TYPE error {syntaxError("type definition");} | DATA btype2 '=' constrs deriving {defTycon(5,$3,checkTyLhs($2), - ap(rev($4),$5),DATATYPE);} + ap(rev($4),$5),DATATYPE);} | DATA context IMPLIES tyLhs '=' constrs deriving {defTycon(7,$5,$4, ap(qualify($2,rev($6)), @@ -280,7 +566,7 @@ invars : invars ',' invar {$$ = gc3(cons($3,$1));} | invar {$$ = gc1(cons($1,NIL));} ; invar : var COCO topType {$$ = gc3(sigdecl($2,singleton($1), - $3));} + $3));} | var {$$ = $1;} ; constrs : constrs '|' pconstr {$$ = gc3(cons($3,$1));} @@ -880,12 +1166,13 @@ varid1 : VARID {$$ = gc1($1);} /*- Tricks to force insertion of leading and closing braces ---------------*/ -begin : error {yyerrok; goOffside(startColumn);} +begin : error {yyerrok; + if (offsideON) goOffside(startColumn);} ; /* deal with trailing semicolon */ end : '}' {$$ = $1;} | error {yyerrok; - if (canUnOffside()) { + if (offsideON && canUnOffside()) { unOffside(); /* insert extra token on stack*/ push(NIL); @@ -910,7 +1197,7 @@ Cell e; { * x1 | ... | xn | la ===> e | la * top() top() * - * Othwerwise, the transformation is: + * Otherwise, the transformation is: * pushed: n-1 0 0 * x1 | ... | xn ===> e * top() top() @@ -962,7 +1249,7 @@ static String local unexpected() { /* find name for unexpected token */ case DEFAULT : keyword("default"); case IMPORT : keyword("import"); case TMODULE : keyword("module"); - case ALL : keyword("forall"); + case ALL : keyword("__forall"); #undef keyword case ARROW : return "`->'"; diff --git a/ghc/interpreter/static.c b/ghc/interpreter/static.c index 7b0e6011d9923c7e7fcaa0c92d2e79c4c746a238..09593821138c282be1b10e6f143b930454ad50c9 100644 --- a/ghc/interpreter/static.c +++ b/ghc/interpreter/static.c @@ -8,8 +8,8 @@ * in the distribution for details. * * $RCSfile: static.c,v $ - * $Revision: 1.6 $ - * $Date: 1999/04/27 10:07:01 $ + * $Revision: 1.7 $ + * $Date: 1999/06/07 17:22:35 $ * ------------------------------------------------------------------------*/ #include "prelude.h" @@ -65,7 +65,6 @@ static List local classBindings Args((String,Class,List)); static Name local memberName Args((Class,Text)); static List local numInsert Args((Int,Cell,List)); -static List local typeVarsIn Args((Cell,List,List)); static List local maybeAppendVar Args((Cell,List)); static Type local checkSigType Args((Int,String,Cell,Type)); @@ -1588,7 +1587,7 @@ List xs; { * occur in the type expression when read from left to right. * ------------------------------------------------------------------------*/ -static List local typeVarsIn(ty,us,vs) /* Calculate list of type variables*/ +List typeVarsIn(ty,us,vs) /* Calculate list of type variables*/ Cell ty; /* used in type expression, reading*/ List us; /* from left to right ignoring any */ List vs; { /* listed in us. */ diff --git a/ghc/interpreter/storage.c b/ghc/interpreter/storage.c index 7495377ad377c871dd3022e7296bd8c3327ba6ce..3d62bc568bbf8726fc0e773d2bb71b3466230984 100644 --- a/ghc/interpreter/storage.c +++ b/ghc/interpreter/storage.c @@ -8,8 +8,8 @@ * in the distribution for details. * * $RCSfile: storage.c,v $ - * $Revision: 1.6 $ - * $Date: 1999/04/27 10:07:05 $ + * $Revision: 1.7 $ + * $Date: 1999/06/07 17:22:49 $ * ------------------------------------------------------------------------*/ #include "prelude.h" @@ -415,6 +415,7 @@ Cell parent; { name(nameHw).type = NIL; name(nameHw).primop = 0; name(nameHw).mod = currentModule; + name(nameHw).ghc_names = NIL; module(currentModule).names=cons(nameHw,module(currentModule).names); name(nameHw).nextNameHash = nameHash[h]; nameHash[h] = nameHw; @@ -443,8 +444,11 @@ Name nm; { /* no clash is caused */ static Void local hashName(nm) /* Insert Name into hash table */ Name nm; { - Text t = name(nm).text; - Int h = nHash(t); + Text t; + Int h; + assert(isName(nm)); + t = name(nm).text; + h = nHash(t); name(nm).nextNameHash = nameHash[h]; nameHash[h] = nm; } @@ -500,6 +504,7 @@ Name nameFromStgVar ( StgVar v ) return NIL; } + /* -------------------------------------------------------------------------- * Primitive functions: * ------------------------------------------------------------------------*/ @@ -743,6 +748,7 @@ Inst newInst() { /* Add new instance to table */ inst(instHw).specifics = NIL; inst(instHw).implements = NIL; inst(instHw).builder = NIL; + inst(instHw).mod = currentModule; return instHw++; } @@ -874,10 +880,24 @@ Text t; { module(moduleHw).tycons = NIL; module(moduleHw).names = NIL; module(moduleHw).classes = NIL; - module(moduleHw).objectFile = 0; + module(moduleHw).oImage = NULL; return moduleHw++; } +void ppModules ( void ) +{ + Int i; + fflush(stderr); fflush(stdout); + printf ( "begin MODULES\n" ); + for (i = moduleHw-1; i >= MODMIN; i--) + printf ( " %2d: %16s\n", + i-MODMIN, textToStr(module(i).text) + ); + printf ( "end MODULES\n" ); + fflush(stderr); fflush(stdout); +} + + Module findModule(t) /* locate Module in module table */ Text t; { Module m; @@ -903,6 +923,7 @@ Cell c; { static local Module findQualifier(t) /* locate Module in import list */ Text t; { Module ms; +printf ( "findQualifier %s\n", textToStr(t)); for (ms=module(currentModule).qualImports; nonNull(ms); ms=tl(ms)) { if (textOf(fst(hd(ms)))==t) return snd(hd(ms)); @@ -929,6 +950,21 @@ Module m; { } } +Name jrsFindQualName ( Text mn, Text sn ) +{ + Module m; + List ns; + + for (m=MODMIN; m<moduleHw; m++) + if (module(m).text == mn) break; + if (m == moduleHw) return NIL; + + for (ns = module(m).names; nonNull(ns); ns=tl(ns)) + if (name(hd(ns)).text == sn) return hd(ns); + + return NIL; +} + /* -------------------------------------------------------------------------- * Script file storage: * @@ -965,6 +1001,25 @@ Int val, mx; { static Script scriptHw; /* next unused script number */ static script scripts[NUM_SCRIPTS]; /* storage for script records */ + +void ppScripts ( void ) +{ + Int i; + fflush(stderr); fflush(stdout); + printf ( "begin SCRIPTS\n" ); + for (i = scriptHw-1; i >= 0; i--) + printf ( " %2d: %16s tH=%d mH=%d yH=%d " + "nH=%d cH=%d iH=%d nnS=%d,%d\n", + i, textToStr(scripts[i].file), + scripts[i].textHw, scripts[i].moduleHw, + scripts[i].tyconHw, scripts[i].nameHw, + scripts[i].classHw, scripts[i].instHw, + scripts[i].nextNewText, scripts[i].nextNewDText + ); + printf ( "end SCRIPTS\n" ); + fflush(stderr); fflush(stdout); +} + Script startNewScript(f) /* start new script, keeping record */ String f; { /* of status for later restoration */ if (scriptHw >= NUM_SCRIPTS) { @@ -1537,6 +1592,10 @@ Int depth; { Printf("Polytype"); print(snd(c),depth-1); break; + case QUAL: + Printf("Qualtype"); + print(snd(c),depth-1); + break; case RANK2: Printf("Rank2("); if (isPair(snd(c)) && isInt(fst(snd(c)))) { @@ -1755,6 +1814,22 @@ Cell c; x.i = snd(c); return x.p; } +Cell mkCPtr(p) +Ptr p; +{ + IntOrPtr x; + x.p = p; + return pair(CPTRCELL,x.i); +} + +Ptr cptrOf(c) +Cell c; +{ + IntOrPtr x; + assert(fst(c) == CPTRCELL); + x.i = snd(c); + return x.p; +} #elif SIZEOF_INTP == 2*SIZEOF_INT typedef union {struct {Int i1; Int i2;} i; Ptr p;} IntOrPtr; Cell mkPtr(p) @@ -1969,7 +2044,7 @@ List xs; { return ys; } -List splitAt(n,xs) /* drop n things from front of list*/ +List splitAt(n,xs) /* drop n things from front of list*/ Int n; List xs; { for(; n>0; --n) { @@ -1978,7 +2053,7 @@ List xs; { return xs; } -Cell nth(n,xs) /* extract n'th element of list */ +Cell nth(n,xs) /* extract n'th element of list */ Int n; List xs; { for(; n>0 && nonNull(xs); --n, xs=tl(xs)) { @@ -2007,6 +2082,16 @@ List xs; { return xs; /* here if element not found */ } +List nubList(xs) /* nuke dups in list */ +List xs; { /* non destructive */ + List outs = NIL; + for (; nonNull(xs); xs=tl(xs)) + if (isNull(cellIsMember(hd(xs),outs))) + outs = cons(hd(xs),outs); + outs = rev(outs); + return outs; +} + /* -------------------------------------------------------------------------- * Operations on applications: * ------------------------------------------------------------------------*/ @@ -2188,6 +2273,7 @@ Int what; { mark(name(i).defn); mark(name(i).stgVar); mark(name(i).type); + mark(name(i).ghc_names); } end("Names", nameHw-NAMEMIN); diff --git a/ghc/interpreter/storage.h b/ghc/interpreter/storage.h index 7cb8c411c557ffcc3532bb4b813103ca57777a19..861bb82b6acdbd5720fed2900b2dcdaa2dc957f6 100644 --- a/ghc/interpreter/storage.h +++ b/ghc/interpreter/storage.h @@ -9,8 +9,8 @@ * in the distribution for details. * * $RCSfile: storage.h,v $ - * $Revision: 1.6 $ - * $Date: 1999/04/27 10:07:06 $ + * $Revision: 1.7 $ + * $Date: 1999/06/07 17:22:47 $ * ------------------------------------------------------------------------*/ /* -------------------------------------------------------------------------- @@ -150,12 +150,33 @@ extern Cell whatIs Args((Cell)); #define BIGCELL 16 /* Integer literal: snd :: Text */ #if PTR_ON_HEAP #define PTRCELL 17 /* C Heap Pointer snd :: Ptr */ +#define CPTRCELL 18 /* Native code pointer snd :: Ptr */ #endif #if TREX -#define EXTCOPY 18 /* Copy of an Ext: snd :: Text */ +#define EXTCOPY 19 /* Copy of an Ext: snd :: Text */ +#endif + +//#define textOf(c) ((Text)(snd(c))) /* c :: (VAR|CON)(ID|OP) */ + +#if 1 +static Text textOf( Cell c ) +{ + Bool ok = + (whatIs(c)==VARIDCELL + || whatIs(c)==CONIDCELL + || whatIs(c)==VAROPCELL + || whatIs(c)==CONOPCELL + || whatIs(c)==STRCELL + || whatIs(c)==DICTVAR + ); + if (!ok) { +fprintf(stderr, "\ntextOf -- tag %d\n",whatIs(c) ); + assert(ok); + } + return snd(c); +} #endif -#define textOf(c) ((Text)(snd(c))) /* c :: (VAR|CON)(ID|OP) */ #define qmodOf(c) (textOf(fst(snd(c)))) /* c :: QUALIDENT */ #define qtextOf(c) (textOf(snd(snd(c)))) /* c :: QUALIDENT */ #define mkVar(t) ap(VARIDCELL,t) @@ -195,6 +216,9 @@ extern String stringNegate Args((String)); #define isPtr(c) (isPair(c) && fst(c)==PTRCELL) extern Cell mkPtr Args((Ptr)); extern Ptr ptrOf Args((Cell)); +#define isCPtr(c) (isPair(c) && fst(c)==CPTRCELL) +extern Cell mkCPtr Args((Ptr)); +extern Ptr cptrOf Args((Cell)); #endif /* -------------------------------------------------------------------------- @@ -265,6 +289,9 @@ extern Ptr ptrOf Args((Cell)); #define ONLY 81 /* ONLY snd :: Exp */ #define NEG 82 /* NEG snd :: Exp */ +/* Used when parsing GHC interface files */ +#define DICTAP 85 /* DICTTYPE snd :: (QClassId,[Type]) */ + #if SIZEOF_INTP != SIZEOF_INT #define PTRCELL 90 /* C Heap Pointer snd :: (Int,Int) */ #endif @@ -392,7 +419,10 @@ struct Module { * evaluating an expression in the context of the current module. */ List qualImports; - ObjectFile objectFile; /* usually unused */ + /* ptr to malloc'd lump of memory holding the obj file */ + void* oImage; + + }; extern Module currentModule; /* Module currently being processed */ @@ -416,16 +446,16 @@ extern Void setCurrModule Args((Module)); #define tycon(n) tabTycon[(n)-TYCMIN] struct strTycon { - Text text; - Int line; + Text text; + Int line; Module mod; /* module that defines it */ - Int arity; - Kind kind; /* kind (includes arity) of Tycon */ - Cell what; /* DATATYPE/SYNONYM/RESTRICTSYN... */ - Cell defn; - Name conToTag; /* used in derived code */ - Name tagToCon; - Tycon nextTyconHash; + Int arity; + Kind kind; /* kind (includes arity) of Tycon */ + Cell what; /* DATATYPE/SYNONYM/RESTRICTSYN... */ + Cell defn; + Name conToTag; /* used in derived code */ + Name tagToCon; + Tycon nextTyconHash; }; extern struct strTycon DECTABLE(tabTycon); @@ -467,6 +497,7 @@ struct strName { Bool simplified; /* TRUE => already simplified */ Bool isDBuilder; /* TRUE => is a dictionary builder */ const void* primop; /* really StgPrim* */ + List ghc_names; /* [(Text,Ptr)] */ Name nextNameHash; }; @@ -511,6 +542,7 @@ extern Name addPrimCfun Args((Text,Int,Int,Cell)); extern Name addPrimCfunREP Args((Text,Int,Int,Int)); extern Int sfunPos Args((Name,Name)); extern Name nameFromStgVar Args((Cell)); +extern Name jrsFindQualName Args((Text,Text)); /* -------------------------------------------------------------------------- * Type class values: @@ -523,15 +555,15 @@ extern Name nameFromStgVar Args((Cell)); #define inst(in) tabInst[(in)-INSTMIN] struct strInst { - Class c; /* class C */ - Int line; - //Module mod; /* module that defines it */ - Kinds kinds; /* Kinds of variables in head */ - Cell head; /* :: Pred */ - List specifics; /* :: [Pred] */ - Int numSpecifics; /* length(specifics) */ - List implements; - Name builder; /* Dictionary constructor function */ + Class c; /* class C */ + Int line; + Module mod; /* module that defines it */ + Kinds kinds; /* Kinds of variables in head */ + Cell head; /* :: Pred */ + List specifics; /* :: [Pred] */ + Int numSpecifics; /* length(specifics) */ + List implements; + Name builder; /* Dictionary constructor function */ }; /* a predicate (an element :: Pred) is an application of a Class to one or @@ -646,6 +678,7 @@ extern List splitAt Args((Int,List)); /* non-destructive */ extern Cell nth Args((Int,List)); extern List removeCell Args((Cell,List)); /* destructive */ extern List dupListOnto Args((List,List)); /* non-destructive */ +extern List nubList Args((List)); /* non-destructive */ /* The following macros provide `inline expansion' of some common ways of * traversing, using and modifying lists: @@ -714,7 +747,7 @@ extern StackPtr sp; chkStack(1); \ onto(c); \ } while (0) -#define onto(c) stack(++sp)=(c) +#define onto(c) stack(++sp)=(c); #define pop() stack(sp--) #define drop() sp-- #define top() stack(sp) diff --git a/ghc/interpreter/type.c b/ghc/interpreter/type.c index d9913e91a8518640b4961d30f14cba6fd42e50af..ff794f734939f79fb867ff04de49fb710d8f3d99 100644 --- a/ghc/interpreter/type.c +++ b/ghc/interpreter/type.c @@ -8,8 +8,8 @@ * in the distribution for details. * * $RCSfile: type.c,v $ - * $Revision: 1.6 $ - * $Date: 1999/04/27 10:07:09 $ + * $Revision: 1.7 $ + * $Date: 1999/06/07 17:22:31 $ * ------------------------------------------------------------------------*/ #include "prelude.h" @@ -724,8 +724,6 @@ Cell e; { /* requires polymorphism, qualified*/ Cell p = NIL; Cell a = e; Int i; - //print(h,1000); - //printf("\n"); switch (whatIs(h)) { case NAME : typeIs = name(h).type; @@ -757,9 +755,6 @@ Cell e; { /* requires polymorphism, qualified*/ } if (isNull(typeIs)) { - //printf("\n NAME " ); - //print(h,1000); - //printf(" TYPE " ); print(typeIs,1000); internal("typeAp1"); } @@ -1709,7 +1704,7 @@ Class c; { /* defaults for class c */ body = ap(LETREC,pair(singleton(locs),body)); name(cclass(c).dbuild).defn = singleton(pair(args,body)); - //--------- Default + name(cclass(c).dbuild).inlineMe = TRUE; genDefns = cons(cclass(c).dbuild,genDefns); cclass(c).defaults = NIL; @@ -1854,7 +1849,7 @@ Inst in; { /* member functions for instance in*/ name(inst(in).builder).defn /* Register builder imp */ = singleton(pair(args,ap(LETREC,pair(singleton(locs),d)))); - //--------- Actual + name(inst(in).builder).inlineMe = TRUE; name(inst(in).builder).isDBuilder = TRUE; genDefns = cons(inst(in).builder,genDefns); @@ -2250,11 +2245,6 @@ Void typeCheckDefns() { /* Type check top level bindings */ static Void local typeDefnGroup(bs) /* type check group of value defns */ List bs; { /* (one top level scc) */ List as; - // printf("\n\n+++ DefnGroup ++++++++++++++++++++++++++++\n"); - //{ List qq; for (qq=bs;nonNull(qq);qq=tl(qq)){ - // print(hd(qq),4); - // printf("\n"); - //}} emptySubstitution(); hd(defnBounds) = NIL;