* included in the distribution.
*
* $RCSfile: hugs.c,v $
- * $Revision: 1.51 $
- * $Date: 2000/03/30 12:04:13 $
+ * $Revision: 1.59 $
+ * $Date: 2000/04/05 14:13:58 $
* ------------------------------------------------------------------------*/
#include <setjmp.h>
Bool debugSC = FALSE;
Bool combined = FALSE;
- char* currentFile; /* Name of current file, or NULL */
-static char currentFileName[1000]; /* name is stored here if it exists*/
-
-
-
-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 */
+ Module moduleBeingParsed; /* so the parser (topModule) knows */
+static char* currentFile; /* Name of current file, or NULL */
+static char currentFileName[1000]; /* name is stored here if it exists*/
static Bool autoMain = FALSE;
static String lastEdit = 0; /* Name of script to edit (if any) */
static Int lastEdLine = 0; /* Editor line number (if possible)*/
static String prompt = 0; /* Prompt string */
static Int hpSize = DEFAULTHEAP; /* Desired heap size */
+static Bool disableOutput = FALSE; /* TRUE => quiet */
String hugsEdit = 0; /* String for editor command */
String hugsPath = 0; /* String for file search path */
Int argc;
String argv[]; {
Int i;
- String proj = 0;
char argv_0_orig[1000];
List initialModules;
List prelModules = NIL;
List targetModules = NIL;
+static String modeToString ( Cell mode )
+{
+ switch (mode) {
+ case FM_SOURCE: return "source";
+ case FM_OBJECT: return "object";
+ case FM_EITHER: return "source or object";
+ default: internal("modeToString");
+ }
+}
+
+static Cell childMode ( Cell modeMeRequest, Cell modeMeActual )
+{
+ assert(modeMeActual == FM_SOURCE ||
+ modeMeActual == FM_OBJECT);
+ assert(modeMeRequest == FM_SOURCE ||
+ modeMeRequest == FM_OBJECT ||
+ modeMeRequest == FM_EITHER);
+ if (modeMeRequest == FM_SOURCE) return modeMeRequest;
+ if (modeMeRequest == FM_OBJECT) return modeMeRequest;
+ if (modeMeActual == FM_OBJECT) return FM_OBJECT;
+ if (modeMeActual == FM_SOURCE) return FM_EITHER;
+ internal("childMode");
+}
+
+static Bool compatibleNewMode ( Cell modeNew, Cell modeExisting )
+{
+ if (modeNew == FM_OBJECT && modeExisting == FM_OBJECT) return TRUE;
+ if (modeNew == FM_SOURCE && modeExisting == FM_SOURCE) return TRUE;
+ if (modeNew == FM_EITHER && modeExisting == FM_OBJECT) return TRUE;
+ if (modeNew == FM_EITHER && modeExisting == FM_SOURCE) return TRUE;
+ return FALSE;
+}
+
static void setCurrentFile ( Module mod )
{
assert(isModule(mod));
strncpy(currentFileName, textToStr(module(mod).text), 990);
strcat(currentFileName, textToStr(module(mod).srcExt));
- currentFile = currentFileName;
+ currentFile = currentFileName;
+ moduleBeingParsed = mod;
+}
+
+static void clearCurrentFile ( void )
+{
+ currentFile = NULL;
+ moduleBeingParsed = NIL;
}
static void ppMG ( void )
u = hd(t);
switch (whatIs(u)) {
case GRP_NONREC:
- fprintf ( stderr, " %s\n", textToStr(textOf(snd(u))));
+ FPrintf ( stderr, " %s\n", textToStr(textOf(snd(u))));
break;
case GRP_REC:
- fprintf ( stderr, " {" );
+ FPrintf ( stderr, " {" );
for (v = snd(u); nonNull(v); v=tl(v))
- fprintf ( stderr, "%s ", textToStr(textOf(hd(v))) );
- fprintf ( stderr, "}\n" );
+ FPrintf ( stderr, "%s ", textToStr(textOf(hd(v))) );
+ FPrintf ( stderr, "}\n" );
break;
default:
internal("ppMG");
usesT = NIL;
for (u = module(mod).uses; nonNull(u); u=tl(u))
usesT = cons(textOf(hd(u)),usesT);
- /* artifically give all modules a dependency on Prelude */
- if (mT != textPrelude)
+
+ /* artificially give all modules a dependency on Prelude */
+ if (mT != textPrelude && mT != textPrimPrel)
usesT = cons(textPrelude,usesT);
+
adjList = cons(pair(mT,usesT),adjList);
}
startModule(m);
tree = unap(M_MODULE,module(m).tree);
modNm = zfst3(tree);
- assert(textOf(modNm)==module(m).text); /* wrong, but ... */
+
+ if (textOf(modNm) != module(m).text) {
+ ERRMSG(0) "Module name \"%s\" does not match file name \"%s%s\"",
+ textToStr(textOf(modNm)),
+ textToStr(module(m).text),
+ textToStr(module(m).srcExt)
+ EEND;
+ }
+
setExportList(zsnd3(tree));
topEnts = zthd3(tree);
}
-static Module parseModuleOrInterface ( ConId mc,
- List renewFromSource,
- List renewFromObject )
+static Module parseModuleOrInterface ( ConId mc, Cell modeRequest )
{
/* Allocate a module-table entry. */
/* Parse the entity and fill in the .tree and .uses entries. */
String path;
String sExt;
- Bool sAvail; Time sTime; Long sSize;
- Bool iAvail; Time iTime; Long iSize;
- Bool oAvail; Time oTime; Long oSize;
+ Bool sAvail; Time sTime; Long sSize;
+ Bool oiAvail; Time oiTime; Long oSize; Long iSize;
Bool ok;
Bool useSource;
char name[10000];
textToStr(module(mod).text),
&path,
&sExt,
- &sAvail, &sTime, &sSize,
- &iAvail, &iTime, &iSize,
- &oAvail, &oTime, &oSize
+ &sAvail, &sTime, &sSize,
+ &oiAvail, &oiTime, &oSize, &iSize
);
if (!ok) goto cant_find;
- if (!sAvail && !(iAvail && oAvail)) goto cant_find;
+ if (!sAvail && !oiAvail) goto cant_find;
/* Find out whether to use source or object. */
- if (varIsMember(mt,renewFromSource)) {
- if (!sAvail) goto cant_find;
- useSource = TRUE;
- } else
- if (varIsMember(mt,renewFromObject)) {
- if (!(oAvail && iAvail)) goto cant_find;
- useSource = FALSE;
- } else
- if (sAvail && !(iAvail && oAvail)) {
- useSource = TRUE;
- } else
- if (!sAvail && (iAvail && oAvail)) {
- useSource = FALSE;
- } else {
- useSource = firstTimeIsLater(sTime,whicheverIsLater(oTime,iTime));
+ switch (modeRequest) {
+ case FM_SOURCE:
+ if (!sAvail) goto cant_find;
+ useSource = TRUE;
+ break;
+ case FM_OBJECT:
+ if (!oiAvail) goto cant_find;
+ useSource = FALSE;
+ break;
+ case FM_EITHER:
+ if ( sAvail && !oiAvail) { useSource = TRUE; break; }
+ if (!sAvail && oiAvail) { useSource = FALSE; break; }
+ useSource = firstTimeIsLater ( sTime, oiTime ) ? TRUE : FALSE;
+ break;
+ default:
+ internal("parseModuleOrInterface");
}
- if (!combined && !sAvail) goto cant_find;
- if (!combined) useSource = TRUE;
-
- module(mod).srcExt = findText(sExt);
- setCurrentFile(mod);
/* Actually do the parsing. */
if (useSource) {
+ module(mod).srcExt = findText(sExt);
+ setCurrentFile(mod);
strcpy(name, path);
strcat(name, textToStr(mt));
strcat(name, sExt);
module(mod).tree = parseModule(name,sSize);
module(mod).uses = getModuleImports(module(mod).tree);
- module(mod).fromSrc = TRUE;
+ module(mod).mode = FM_SOURCE;
module(mod).lastStamp = sTime;
} else {
+ module(mod).srcExt = findText(HI_ENDING);
+ setCurrentFile(mod);
strcpy(name, path);
strcat(name, textToStr(mt));
strcat(name, DLL_ENDING);
strcat(name, ".u_hi");
module(mod).tree = parseInterface(name,iSize);
module(mod).uses = getInterfaceImports(module(mod).tree);
- module(mod).fromSrc = FALSE;
- module(mod).lastStamp = whicheverIsLater(oTime,iTime);
+ module(mod).mode = FM_OBJECT;
+ module(mod).lastStamp = oiTime;
}
if (path) free(path);
cant_find:
if (path) free(path);
+ clearCurrentFile();
ERRMSG(0)
- "Can't find source or object+interface for module \"%s\"",
- textToStr(mt)
+ "Can't find %s for module \"%s\"",
+ modeToString(modeRequest), textToStr(mt)
EEND;
}
case GRP_NONREC:
m = findModule(textOf(snd(grp)));
assert(nonNull(m));
- if (module(m).fromSrc) {
+ if (module(m).mode == FM_SOURCE) {
processModule ( m );
} else {
processInterfaces ( singleton(snd(grp)) );
for (t = snd(grp); nonNull(t); t=tl(t)) {
m = findModule(textOf(hd(t)));
assert(nonNull(m));
- if (module(m).fromSrc) {
+ if (module(m).mode == FM_SOURCE) {
ERRMSG(0) "Source module \"%s\" imports itself recursively",
textToStr(textOf(hd(t)))
EEND;
to do EENDs (ie, write error messages). Others should use
EEND_NO_LONGJMP.
*/
-static void achieveTargetModules ( void )
+static void achieveTargetModules ( Bool loadingThePrelude )
{
volatile List ood;
volatile List modgList;
- volatile List renewFromSource;
- volatile List renewFromObject;
volatile List t;
volatile Module mod;
volatile Bool ok;
String path = NULL;
String sExt = NULL;
- Bool sAvail; Time sTime; Long sSize;
- Bool iAvail; Time iTime; Long iSize;
- Bool oAvail; Time oTime; Long oSize;
+ Bool sAvail; Time sTime; Long sSize;
+ Bool oiAvail; Time oiTime; Long oSize; Long iSize;
volatile Time oisTime;
- volatile Time oiTime;
- volatile Bool sourceIsLatest;
volatile Bool out_of_date;
volatile List ood_new;
volatile List us;
ood = NIL;
modgList = listFromMG();
- renewFromSource = renewFromObject = NIL;
-
for (t = modgList; nonNull(t); t=tl(t)) {
if (varIsMember(textOf(hd(t)),prelModules))
mod = findModule(textOf(hd(t)));
if (isNull(mod)) internal("achieveTargetSet(1)");
+ /* In standalone mode, only succeeds for source modules. */
ok = findFilesForModule (
textToStr(module(mod).text),
&path,
&sExt,
- &sAvail, &sTime, &sSize,
- &iAvail, &iTime, &iSize,
- &oAvail, &oTime, &oSize
+ &sAvail, &sTime, &sSize,
+ &oiAvail, &oiTime, &oSize, &iSize
);
+
if (!combined && !sAvail) ok = FALSE;
if (!ok) {
fallBackToPrelModules();
if (path) free(path);
return;
}
- /* findFilesForModule should enforce this */
- if (!(sAvail || (oAvail && iAvail)))
- internal("achieveTargetSet(2)");
- if (!combined) {
+ if (sAvail && oiAvail) {
+ oisTime = whicheverIsLater(sTime,oiTime);
+ }
+ else if (sAvail && !oiAvail) {
oisTime = sTime;
- sourceIsLatest = TRUE;
- } else {
- if (sAvail && !(oAvail && iAvail)) {
- oisTime = sTime;
- sourceIsLatest = TRUE;
- } else
- if (!sAvail && (oAvail && iAvail)) {
- oisTime = whicheverIsLater(oTime,iTime);
- sourceIsLatest = FALSE;
- } else
- if (sAvail && (oAvail && iAvail)) {
- oisTime = whicheverIsLater(oTime,iTime);
- if (firstTimeIsLater(sTime,oisTime)) {
- oisTime = sTime;
- sourceIsLatest = TRUE;
- } else {
- sourceIsLatest = FALSE;
- }
- } else {
- internal("achieveTargetSet(1a)");
- }
+ }
+ else if (!sAvail && oiAvail) {
+ oisTime = oiTime;
}
-
+ else {
+ internal("achieveTargetSet(2)");
+ }
+
out_of_date = firstTimeIsLater(oisTime,module(mod).lastStamp);
if (out_of_date) {
assert(!varIsMember(textOf(hd(t)),ood));
ood = cons(hd(t),ood);
- if (sourceIsLatest)
- renewFromSource = cons(hd(t),renewFromSource); else
- renewFromObject = cons(hd(t),renewFromObject);
}
if (path) { free(path); path = NULL; };
/* Parse modules/interfaces, collecting parse trees and chasing
imports, starting from the target set.
*/
- parsedButNotLoaded = NIL;
toChase = dupList(targetModules);
+ for (t = toChase; nonNull(t); t=tl(t)) {
+ Cell mode = (!combined)
+ ? FM_SOURCE
+ : ( (loadingThePrelude && combined)
+ ? FM_OBJECT
+ : FM_EITHER );
+ hd(t) = zpair(hd(t), mode);
+ }
+
+ /* toChase :: [ ((ConId, {FM_SOURCE|FM_OBJECT|FM_EITHER} )) ] */
+
+ parsedButNotLoaded = NIL;
+
while (nonNull(toChase)) {
- ConId mc = hd(toChase);
- toChase = tl(toChase);
- if (!varIsMember(textOf(mc),modgList)
- && !varIsMember(textOf(mc),parsedButNotLoaded)) {
+ ConId mc = zfst(hd(toChase));
+ Cell mode = zsnd(hd(toChase));
+ toChase = tl(toChase);
+ if (varIsMember(textOf(mc),modgList)
+ || varIsMember(textOf(mc),parsedButNotLoaded)) {
+ /* either exists fully, or is at least parsed */
+ mod = findModule(textOf(mc));
+ assert(nonNull(mod));
+ if (!compatibleNewMode(mode,module(mod).mode)) {
+ clearCurrentFile();
+ ERRMSG(0)
+ "module %s: %s required, but %s is more recent",
+ textToStr(textOf(mc)), modeToString(mode),
+ modeToString(module(mod).mode)
+ EEND_NO_LONGJMP;
+ goto parseException;
+ }
+ } else {
setBreakAction ( HugsLongjmpOnBreak );
if (setjmp(catch_error)==0) {
/* try this; it may throw an exception */
- mod = parseModuleOrInterface (
- mc, renewFromSource, renewFromObject );
+ mod = parseModuleOrInterface ( mc, mode );
} else {
/* here's the exception handler, if parsing fails */
/* A parse error (or similar). Clean up and abort. */
+ parseException:
setBreakAction ( HugsIgnoreBreak );
mod = findModule(textOf(mc));
if (nonNull(mod)) nukeModule(mod);
setBreakAction ( HugsIgnoreBreak );
parsedButNotLoaded = cons(mc, parsedButNotLoaded);
- toChase = dupOnto(module(mod).uses,toChase);
+ for (t = module(mod).uses; nonNull(t); t=tl(t))
+ toChase = cons(
+ zpair( hd(t), childMode(mode,module(mod).mode) ),
+ toChase);
}
}
conPrelude = mkCon(findText("Prelude"));
conPrelHugs = mkCon(findText("PrelHugs"));
targetModules = doubleton(conPrelude,conPrelHugs);
- achieveTargetModules();
+ achieveTargetModules(TRUE);
ok = elemMG(conPrelude) && elemMG(conPrelHugs);
} else {
conPrelude = mkCon(findText("Prelude"));
targetModules = singleton(conPrelude);
- achieveTargetModules();
+ achieveTargetModules(TRUE);
ok = elemMG(conPrelude);
}
}
-static void refreshActions ( ConId nextCurrMod )
+static void refreshActions ( ConId nextCurrMod, Bool cleanAfter )
{
+ List t;
ConId tryFor = mkCon(module(currentModule).text);
- achieveTargetModules();
+ achieveTargetModules(FALSE);
if (nonNull(nextCurrMod))
tryFor = nextCurrMod;
if (!elemMG(tryFor))
if (combined && textOf(tryFor)==findText("PrelHugs"))
tryFor = mkCon(findText("Prelude"));
+ if (cleanAfter) {
+ /* delete any targetModules which didn't actually get loaded */
+ t = targetModules;
+ targetModules = NIL;
+ for (; nonNull(t); t=tl(t))
+ if (elemMG(hd(t)))
+ targetModules = cons(hd(t),targetModules);
+ }
+
setCurrModule ( findModule(textOf(tryFor)) );
Printf("Hugs session for:\n");
ppMG();
targetModules = cons(extra,targetModules);
}
refreshActions ( isNull(extraModules)
- ? NIL
- : hd(reverse(extraModules))
+ ? NIL
+ : hd(reverse(extraModules)),
+ TRUE
);
}
targetModules = cons(load,targetModules);
}
refreshActions ( isNull(loadModules)
- ? NIL
- : hd(reverse(loadModules))
+ ? NIL
+ : hd(reverse(loadModules)),
+ TRUE
);
}
module(evalMod).names = module(currentModule).names;
module(evalMod).tycons = module(currentModule).tycons;
module(evalMod).classes = module(currentModule).classes;
+ module(evalMod).qualImports
+ = singleton(pair(mkCon(textPrelude),modulePrelude));
return evalMod;
}
addActions(modConIds);
modConIds = NIL;
break;
- case RELOAD : refreshActions(NIL);
+ case RELOAD : refreshActions(NIL,FALSE);
break;
case SETMODULE :
setModule();
Cell errAssert(l) /* message to use when raising asserts, etc */
Int l; {
- char tmp[100];
Cell str;
if (currentFile) {
str = mkStr(findText(currentFile));
return NULL;
}
+
/* --------------------------------------------------------------------------
* Compiler output
* We can redirect compiler output (prompts, error messages, etc) by
* tweaking these functions.
* ------------------------------------------------------------------------*/
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+Void hugsEnableOutput(f)
+Bool f; {
+ disableOutput = !f;
+}
+
+#ifdef HAVE_STDARG_H
+Void hugsPrintf(const char *fmt, ...) {
+ va_list ap; /* pointer into argument list */
+ va_start(ap, fmt); /* make ap point to first arg after fmt */
+ if (!disableOutput) {
+ vprintf(fmt, ap);
+ } else {
+ }
+ va_end(ap); /* clean up */
+}
+#else
+Void hugsPrintf(fmt, va_alist)
+const char *fmt;
+va_dcl {
+ va_list ap; /* pointer into argument list */
+ va_start(ap); /* make ap point to first arg after fmt */
+ if (!disableOutput) {
+ vprintf(fmt, ap);
+ } else {
+ }
+ va_end(ap); /* clean up */
+}
+#endif
+
+Void hugsPutchar(c)
+int c; {
+ if (!disableOutput) {
+ putchar(c);
+ } else {
+ }
+}
+
+Void hugsFlushStdout() {
+ if (!disableOutput) {
+ fflush(stdout);
+ }
+}
+
+Void hugsFFlush(fp)
+FILE* fp; {
+ if (!disableOutput) {
+ fflush(fp);
+ }
+}
+
+#ifdef HAVE_STDARG_H
+Void hugsFPrintf(FILE *fp, const char* fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ if (!disableOutput) {
+ vfprintf(fp, fmt, ap);
+ } else {
+ }
+ va_end(ap);
+}
+#else
+Void hugsFPrintf(FILE *fp, const char* fmt, va_list)
+FILE* fp;
+const char* fmt;
+va_dcl {
+ va_list ap;
+ va_start(ap);
+ if (!disableOutput) {
+ vfprintf(fp, fmt, ap);
+ } else {
+ }
+ va_end(ap);
+}
+#endif
+
+Void hugsPutc(c, fp)
+int c;
+FILE* fp; {
+ if (!disableOutput) {
+ putc(c,fp);
+ } else {
+ }
+}
+
/* --------------------------------------------------------------------------
* Send message to each component of system:
* ------------------------------------------------------------------------*/
typeChecker(what);
compiler(what);
codegen(what);
+
+ mark(moduleGraph);
+ mark(prelModules);
+ mark(targetModules);
+ mark(daSccs);
}
/*-------------------------------------------------------------------------*/