home *** CD-ROM | disk | FTP | other *** search
- /*
- * @(#)depManifest.c 1.8 1/15/88
- */
- #include "assert.h"
- #include "nodes.h"
- #include "map.h"
- #include "sequence.h"
- #include "trace.h"
- #include "semantics.h"
- #include "builtins.h"
- #include "MyParser.h"
- #include "flags.h"
- #include "error.h"
- #include "environment.h"
- #include "system.h"
- #include "typecheck.h"
-
- /*
- * Imported routines.
- */
-
- extern NodePtr
- buildATOfObject(),
- buildOpName(),
- cTree(),
- checkInvocCache(),
- copyTree(),
- evaluateForAT(),
- figureOutAT(),
- findObjectOperation(),
- getExportedATOfObject();
-
- extern void
- resolveGlobal(),
- tryToSetCTInfo(),
- updateInvocCache();
- extern Boolean
- conforms();
- extern OID
- AllocateOID(),
- OIDOf();
-
- /*
- * Imported variables.
- */
-
- extern Map manifestMap;
-
- /*
- * Private types.
- */
-
- typedef enum { IS_Step1, IS_Step2, IS_Step3, IS_Step4 } IS_Step;
-
- typedef struct sManifestSE {
- Map candidates;
- Set manifestThings;
- NodePtr SCstack;
- struct sManifestSE *next;
- } ManifestSE, *ManifestStack;
-
- /*
- * Private variables.
- */
-
- Map dependManifestMap;
- DelayedCheckPtr delayedChecks = NULL;
- static NodePtr objectStack;
- static NodePtr getSignatureOpName = NULL, createOpName = NULL;
- static int count = 0;
- static ManifestStack manStack = NULL;
-
- /*
- * Private definitions
- */
-
- #define literalHasValue(p) ( (p)->b.oblit.f.isManifest || \
- (p)->b.oblit.f.isTypeVariable || \
- (p)->b.oblit.f.dependsOnTypeVariable )
-
- #define symbolHasValue(s) ((s)->isManifest || (s)->hasValue)
- #define NAMEOF(N) (ST_SymbolName((N)->b.symdef.symbol))
- #define min(A, B) ((A) < (B) ? (A) : (B))
- #define TOPOF(S) ((S)->b.children[(S)->nChildren-1])
- #define ATTOPLEVEL (manStack->next == NULL)
- #define OBOIDAssigned(p) ((p)->b.oblit.id != 0 || (p)->b.oblit.codeOID != 0)
- #define ATOIDAssigned(p) ((p)->b.atlit.id != 0)
-
- /*
- * Forward declarations of routines.
- */
- static void
- newFigureObjectTypes();
- void
- doKnowManifests(),
- newAssignTypes();
-
- NodePtr findManifestValue(),
- findTheResultExpression(),
- newExecuteAsAT();
-
- /*
- * fetchMan finds the knowmanifest record for the given node. If isParent
- * is true, then the record must be found in the top entry on the manifest
- * stack, else it can be found anywhere. If it is not found, it is created
- * in the top map.
- */
-
- NodePtr fetchMan(p, isParent)
- NodePtr p;
- Boolean isParent;
- {
- NodePtr answer, lookup;
- register ManifestStack s;
-
- switch (p->tag) {
- case P_GLOBALREF:
- resolveGlobal(p, (ValuePtr)NULL);
- assert(p->b.globalref.value != NN);
- lookup = p->b.globalref.value;
- break;
- case P_SYMREF:
- case P_SYMDEF:
- lookup = (NodePtr) p->b.symref.symbol;
- break;
- default:
- lookup = p;
- break;
- }
- if (isParent) {
- for (s = manStack->next; s != NULL; s = s->next) {
- assert(Map_Lookup(s->candidates, (int)lookup) == NIL);
- }
- }
- answer = (NodePtr) Map_Lookup(dependManifestMap, (int)lookup);
- if ((int) answer != NIL) return(answer);
- answer = Construct(P_KNOWMANIFEST, 3, NN, NN, NN);
- answer->b.knowmanifest.tag = lookup->tag;
- answer->b.knowmanifest.definingThing = lookup;
- Map_Insert(dependManifestMap, (int)lookup, (int)answer);
- Map_Insert(manStack->candidates, (int)lookup, (int)answer);
- return(answer);
- }
-
- static void MAN_AddPrereq(p, c)
- NodePtr p, c;
- {
- NodePtr childStruct, parentStruct;
- assert(c != NN && p != NN);
-
- parentStruct = fetchMan(p, TRUE);
- childStruct = fetchMan(c, FALSE);
- SET_INSERT(parentStruct->b.knowmanifest.dependsOn, childStruct);
- }
-
- NodePtr getGetSignatureResult(p, wantLit)
- NodePtr p;
- Boolean wantLit;
- {
- register NodePtr opdef, opsig, r;
-
- if (getSignatureOpName == NULL)
- getSignatureOpName = buildOpName("getsignature", -1);
- assert(p->tag == P_OBLIT);
- opdef = findObjectOperation(p, getSignatureOpName);
- if (opdef == NULL) return(NULL);
- opsig = opdef->b.opdef.sig;
- if (! opsig->b.opsig.isFunction) return(NULL);
- if (Sequence_Length(opsig->b.opsig.params) != 0) return(NULL);
- if (Sequence_Length(opsig->b.opsig.results) != 1) return(NULL);
- r = opsig->b.opsig.results->b.children[0]->b.param.type;
- if (r->tag != P_BUILTINLIT) return(NULL);
- if (r->b.builtinlit.whichType != KSIGNATURE) return(NULL);
- return(findTheResultExpression(opdef, wantLit));
- }
-
- NodePtr getCreateResult(p, wantLit)
- NodePtr p;
- Boolean wantLit;
- {
- register NodePtr opdef, opsig;
-
- if (createOpName == NULL)
- createOpName = buildOpName("create", -1);
- assert(p->tag == P_OBLIT);
- opdef = findObjectOperation(p, createOpName);
- if (opdef == NULL) return(NULL);
- opsig = opdef->b.opdef.sig;
- if (Sequence_Length(opsig->b.opsig.results) != 1) return(NULL);
- return(findTheResultExpression(opdef, wantLit));
- }
-
- static Boolean isAlwaysTheSame(p)
- NodePtr p;
- {
- if (bflag) {
- return(FALSE);
- }
- return(p->b.oblit.f.immutable);
- }
-
- void MAN_SetImport(p)
- NodePtr p;
- {
- NodePtr q;
- q = fetchMan(p, FALSE);
- assert((int)q != NIL);
- q->b.knowmanifest.isImport = TRUE;
- }
-
- void buildKnowManifestGraph(p, inExecutable)
- register NodePtr p;
- Boolean inExecutable;
- {
- register NodePtr q;
- Boolean doPop = FALSE;
- register NodePtr inhibitedChild = NULL;
- register NodePtr gsr;
- Boolean childInExecutable = inExecutable, childrenDone = FALSE;
-
- if (ISTOKEN(p)) return;
- switch (p->tag) {
- case P_BLOCK:
- childInExecutable = TRUE;
- break;
- case P_SETQ:
- childrenDone = TRUE;
- break;
- case P_OBLIT:
- case P_ATLIT:
- Sequence_Add(&objectStack, p);
- doPop = TRUE;
- inhibitedChild = p->b.oblit.name;
- break;
- default:
- break;
- }
- if (!childrenDone) {
- Sequence_For(q, p)
- if (!ISTOKEN(q) && q != inhibitedChild)
- buildKnowManifestGraph(q, childInExecutable);
- Sequence_Next
- }
- switch (p->tag) {
- case P_INVOC:
- MAN_AddPrereq(p, p->b.invoc.target);
- Sequence_For(q, p->b.invoc.args)
- assert(q->tag == P_ARG);
- q = q->b.arg.exp;
- MAN_AddPrereq(p, q);
- Sequence_Next
- break;
- case P_CONSTDECL:
- if (p->b.constdecl.value != NN)
- MAN_AddPrereq(p->b.constdecl.sym, p->b.constdecl.value);
- if (Sequence_Length(objectStack) != 0 && p->b.constdecl.type != NN)
- MAN_AddPrereq(TOPOF(objectStack), p->b.constdecl.type);
- break;
- case P_VARDECL:
- MAN_AddPrereq(TOPOF(objectStack), p->b.vardecl.type);
- break;
- case P_WHEREWIDGIT:
- MAN_AddPrereq(p->b.wherewidgit.sym, p->b.wherewidgit.type);
- MAN_AddPrereq(TOPOF(objectStack), p->b.wherewidgit.sym);
- break;
- case P_VIEW:
- MAN_AddPrereq(TOPOF(objectStack), p->b.view.type);
- break;
- case P_RESTRICT:
- MAN_AddPrereq(TOPOF(objectStack), p->b.restrict.type);
- break;
- case P_PARAM:
- MAN_AddPrereq(TOPOF(objectStack), p->b.param.type);
- if (p->b.param.constraint != NN) {
- MAN_AddPrereq(p, p->b.param.constraint);
- MAN_AddPrereq(p->b.param.sym, p);
- MAN_AddPrereq(TOPOF(objectStack), p);
- }
- break;
- case P_OBLIT:
- gsr = getGetSignatureResult(p, FALSE);
- if (gsr != NULL) MAN_AddPrereq(p, gsr);
- if (inExecutable && ! isAlwaysTheSame(p)) {
- MAN_AddPrereq(p, Construct(T_NONE, 0));
- }
- /* fall through */
- case P_ATLIT:
- Sequence_For(q, p->b.oblit.setq)
- assert(q->b.setq.inner->tag == P_SYMDEF);
- MAN_AddPrereq(q->b.setq.inner, q->b.setq.outer);
- MAN_AddPrereq(p, q->b.setq.inner);
- MAN_SetImport(q->b.setq.inner);
- Sequence_Next
- MAN_AddPrereq(p->b.oblit.name, p);
- break;
- default:
- break;
- }
- if (doPop) objectStack->nChildren --;
- }
-
- void initializeKnowManifest()
- {
- dependManifestMap = Map_Create();
- }
-
- static char *thingName(t)
- NodePtr t;
- {
- static char buffer[128];
- Tag tag = t->b.knowmanifest.tag;
- NodePtr d = t->b.knowmanifest.definingThing;
-
- if (tag == P_SYMBOL) {
- sprintf(buffer, "0x%08x Symbol %s (0x%08x)", t, ST_SymbolName((Symbol)(d)), d);
- } else if (tag == P_OBLIT || tag == P_ATLIT) {
- sprintf(buffer, "0x%08x %s %s (0x%08x) on line %d",
- t,
- tagNames[(int)tag],
- ST_SymbolName(d->b.oblit.name->b.symdef.symbol),
- d,
- d->lineNumber);
- } else {
- sprintf(buffer, "0x%08x %s (0x%08x) on line %d", t, tagNames[(int)tag],
- d, d->lineNumber);
- }
- return(buffer);
- }
-
- void displayKnowManifestGraph()
- {
- NodePtr thing, theStruct, q;
- IFTRACE(knowmanifest, 4) {
- Map_For(manStack->candidates, thing, theStruct)
- printf("struct %s", thingName(theStruct));
- if (theStruct->b.knowmanifest.isDone) printf(" isDone");
- if (theStruct->b.knowmanifest.isOK) printf(" isOK");
- printf(" depends on:\n");
- Set_For(q, theStruct->b.knowmanifest.dependsOn)
- printf("\t\tstruct %s\n", thingName(q));
- Set_Next
- Map_Next
- }
- }
-
- void fleshOutValue(value)
- Value *value;
- {
- NodePtr p = value->value;
- if (p->tag == P_GLOBALREF) {
- resolveGlobal(p, (ValuePtr)NULL);
- p = p->b.globalref.value;
- }
- if (p->tag == P_ATLIT) {
- value->ATinfo = refToBuiltin(B_INSTAT, SIGNATUREINDEX);
- value->CTinfo = refToBuiltin(B_INSTCT, SIGNATUREINDEX);
- } else if (p->tag == P_OBLIT) {
- assert(p->b.oblit.myat != NN);
- value->ATinfo = p->b.oblit.myat;
- value->CTinfo = p;
- } else {
- assert(FALSE);
- }
- }
-
- NodePtr findManifestValue(p)
- NodePtr p;
- {
- NodePtr result, lookup = p;
- Symbol st;
- if (p->tag == P_SYMREF || p->tag == P_SYMDEF) {
- lookup = (NodePtr) p->b.symref.symbol;
- }
- result = (NodePtr) Map_Lookup(dependManifestMap, (int)lookup);
- if ((int) result != NIL) {
- assert(result->tag == P_KNOWMANIFEST);
- if (result->b.knowmanifest.isOK) {
- assert(result->b.knowmanifest.answer != NULL);
- result = result->b.knowmanifest.answer;
- } else {
- result = NULL;
- }
- } else {
- result = NULL;
- }
- if (result == NULL) {
- switch (p->tag) {
- case P_ATLIT:
- if (literalHasValue(p)) result = p;
- break;
- case P_OBLIT:
- if (literalHasValue(p)) result = p;
- break;
- case P_GLOBALREF:
- resolveGlobal(p, (ValuePtr) NULL);
- result = p->b.globalref.value;
- break;
- case P_BUILTINLIT:
- result = refToBuiltinFromToken(B_IT, p->b.builtinlit.whichType);
- break;
- case P_SYMREF:
- st = p->b.symref.symbol;
- if (symbolHasValue(st)) result = st->value.value;
- break;
- default:
- break;
- }
- }
- return(result);
- }
-
- NodePtr findTheResultExpression(opdef, wantLit)
- NodePtr opdef;
- Boolean wantLit;
- {
- register NodePtr q, r, answer;
- register Symbol resultSym, st;
-
- assert(opdef->tag == P_OPDEF);
- q = opdef->b.opdef.sig;
- assert(q->tag == P_OPSIG);
- if (Sequence_Length(q->b.opsig.results) != 1) return(NN);
- q = q->b.opsig.results->b.children[0];
- assert(q->tag == P_PARAM);
- q = q ->b.param.sym;
- assert(q->tag == P_SYMDEF);
- resultSym = q->b.symdef.symbol;
-
- q = opdef->b.opdef.body;
- assert(q->tag == P_BLOCK);
- if (q->b.block.unavailablehandler != NN) return(NN);
- if (q->b.block.failurehandler != NN) return(NN);
- q = q->b.block.stats;
- if (Sequence_Length(q) != 1) return(NN);
- q = q->b.children[0];
- if (q->tag != P_ASSIGNSTAT) return(NN);
- if (Sequence_Length(q->b.assignstat.left) != 1) return(NN);
- if (Sequence_Length(q->b.assignstat.right) != 1) return(NN);
- r = q->b.assignstat.left->b.children[0];
- if (r->tag != P_SYMREF) return(NN);
- if (r->b.symref.symbol != resultSym) return(NN);
- q = GETVALUE(q->b.assignstat.right->b.children[0]);
- switch (q->tag) {
- case P_OBLIT:
- case P_ATLIT:
- answer = q;
- break;
- case P_SYMREF:
- if (wantLit) {
- st = q->b.symref.symbol;
- if (symbolHasValue(st)) {
- answer = GETVALUE(st->value.value);
- } else {
- answer = NN;
- }
- } else {
- answer = q;
- }
- break;
- default:
- answer = NN;
- break;
- }
- return(answer);
- }
-
- void executeAnInvocation(anElement, whichStep, theNewManifests)
- NodePtr anElement, *theNewManifests;
- IS_Step whichStep;
- {
- NodePtr target, opName, actuals, opdef, formals, actual, formal,
- formalType, dt, result, paramSyms, argValues, aSR, wheres, where,
- newSyms, newValues, q;
- Symbol st;
- DelayedCheckPtr dc;
-
- assert(anElement->tag == P_KNOWMANIFEST);
- assert(anElement->b.knowmanifest.tag == P_INVOC);
- dt = anElement->b.knowmanifest.definingThing;
-
- /*
- * Do the right stuff for this step of the invocation. We should have
- * checked already that it can be done, so assert false if things go
- * wrong.
- */
- target = dt->b.invoc.target;
- opName = dt->b.invoc.opname;
- actuals = dt->b.invoc.args;
- target = findManifestValue(target);
- assert(target != NULL);
- assert(target->tag == P_OBLIT);
- assert(target->b.oblit.f.immutable);
- opdef = findObjectOperation(target, opName);
- assert(opdef != NULL);
- assert(opdef->b.opdef.sig->b.opsig.isFunction);
- formals = opdef->b.opdef.sig->b.opsig.params;
- assert(Sequence_Length(formals) == Sequence_Length(actuals));
- result = findTheResultExpression(opdef, TRUE);
- assert(result->tag == P_ATLIT || result->tag == P_OBLIT);
- switch (whichStep) {
- case IS_Step2:
- /*
- * Allocate the answer node and stick it in anElement.answer.
- */
- anElement->b.knowmanifest.answer = cTree(result, NN, NN, NN);
- break;
- case IS_Step3:
- assert(FALSE);
- break;
- case IS_Step4:
- /*
- * Go into the bodies of the invocations. Record the type checks that
- * we will have to make, and figure out the substitutions that will
- * need to be performed on the result expression. Then copy the tree.
- */
-
- paramSyms = F_NewNode(T_SEQUENCE, Sequence_Length(actuals));
- argValues = F_NewNode(T_SEQUENCE, Sequence_Length(actuals));
- Sequence_For(actual, actuals)
- formal = formals->b.children[z__z];
- assert(actual->tag == P_ARG);
- assert(formal->tag == P_PARAM);
- actual = actual->b.arg.exp;
- actual = findManifestValue(actual);
- assert(actual != NULL);
- formalType = findManifestValue(formal->b.param.type);
- assert(formalType != NULL);
- dc = (DelayedCheckPtr) malloc(sizeof(DelayedCheck));
- dc->invoc = dt;
- dc->expression = actual;
- dc->kind = DC_Conform;
- dc->type = formalType;
- dc->next = delayedChecks;
- delayedChecks = dc;
-
- if (formal->b.param.constraint != NULL) {
- /* we need to do matching */
- st = ST_Fetch(formal->b.param.sym->b.symdef.symbol);
- assert(symbolHasValue(st));
- assert(st->value.value != NULL);
- formalType = figureOutAT(st->value.value);
- assert(formalType != NULL);
- assert(formalType->tag == P_ATLIT);
- assert(formalType->b.atlit.f.isTypeVariable);
- dc = (DelayedCheckPtr) malloc(sizeof(DelayedCheck));
- dc->invoc = dt;
- dc->expression = actual;
- dc->kind = DC_Match;
- dc->type = formalType;
- dc->next = delayedChecks;
- delayedChecks = dc;
- }
- /*
- * Now, figure out the substitutions.
- */
- aSR = formal->b.param.sym;
- assert(aSR != NULL);
- assert(aSR->tag == P_SYMDEF);
- Sequence_Add(¶mSyms, aSR);
- Sequence_Add(&argValues, actual);
- Sequence_Next
- /*
- * We need to deal with the constants declared in the where clause.
- * These should be turned into constants in the body of the newly
- * created thing. We need to do the two pass thing on these, too.
- */
- newSyms = NN;
- newValues = NN;
- wheres = opdef->b.opdef.sig->b.opsig.where;
- Sequence_For(where, wheres)
- assert(where->tag == P_WHEREWIDGIT);
- if (where->b.wherewidgit.op == OCONFORMSTO) {
- /* do nothing */
- } else if (where->b.wherewidgit.op == OIDENTITY) {
- aSR = where->b.wherewidgit.sym;
- assert(aSR->tag == P_SYMDEF);
- Sequence_Add(&newSyms, aSR);
- q = where->b.wherewidgit.type;
- Sequence_Add(&newValues, cTree(q, NN, NN, NN));
- } else {
- assert(FALSE);
- }
- Sequence_Next
-
- paramSyms = RAPPEND(newSyms, paramSyms);
- argValues = RAPPEND(newValues, argValues);
-
- Sequence_For(where, wheres)
- assert(where->tag == P_WHEREWIDGIT);
- if (where->b.wherewidgit.op == OCONFORMSTO) {
- /* do nothing */
- } else if (where->b.wherewidgit.op == OIDENTITY) {
- aSR = where->b.wherewidgit.sym;
- assert(aSR->tag == P_SYMDEF);
- q = where->b.wherewidgit.type;
- argValues->b.children[z__z] =
- cTree(q, argValues->b.children[z__z], paramSyms, argValues);
- Sequence_Add(theNewManifests, argValues->b.children[z__z]);
- } else {
- assert(FALSE);
- }
- Sequence_Next
-
- /*
- * Now that the substitutions have been done, we can flesh out the
- * copy of the resulting expression.
- */
- anElement->b.knowmanifest.answer =
- cTree(result, anElement->b.knowmanifest.answer, paramSyms, argValues);
- Sequence_Add(theNewManifests, anElement->b.knowmanifest.answer);
- break;
- default:
- assert(FALSE);
- break;
- }
- }
-
- void checkDelayedChecks()
- {
- register DelayedCheckPtr dc, tc;
- NodePtr itsType;
- for (dc = delayedChecks; dc; tc = dc->next, free((char *)dc), dc = tc) {
- TRACE3(knowmanifest, 4, "Delayed check (%s) of 0x%08x and 0x%08x",
- dc->kind == DC_Conform ? "conform" : "match",
- dc->expression,
- dc->type);
- if (dc->kind == DC_Conform) {
- itsType = evaluateForAT(dc->expression, TRUE);
- if (!conforms(itsType, dc->type)) {
- ErrorMessage(dc->invoc, "Types do not conform (delayed)");
- }
- } else if (dc->kind == DC_Match) {
- if (!conforms(dc->expression, dc->type)) {
- ErrorMessage(dc->invoc, "Argument does not satisfy constraint (delayed)");
- }
- } else {
- assert(FALSE);
- }
- }
- delayedChecks = NULL;
- }
-
- void assignOIDs(p)
- register NodePtr p;
- {
- register NodePtr gsr, cr;
-
- if (ISTOKEN(p)) return;
- switch (p->tag) {
- case P_KNOWMANIFEST:
- assert(p->b.knowmanifest.answer != p);
- assignOIDs(p->b.knowmanifest.answer);
- break;
- case P_ATLIT:
- if (ATOIDAssigned(p)) {
- TRACE1(knowmanifest, 7, "atlit %s already has a value",
- p->b.atlit.name == NN ? "unknown" :
- ST_SymbolName(p->b.atlit.name->b.symdef.symbol));
- } else {
- p->b.atlit.f.isManifest =
- !(p->b.atlit.f.isTypeVariable || p->b.atlit.f.dependsOnTypeVariable);
- p->b.atlit.f.writeSeparately = p->b.atlit.f.isManifest;
- if (p->b.atlit.f.isManifest) {
- defineGlobal(p, 0);
- } else {
- p->b.atlit.id = AllocateOID();
- OTInsert(p, p->b.atlit.id);
- }
- }
- break;
- case P_OBLIT:
- if (OBOIDAssigned(p)) {
- TRACE1(knowmanifest, 7, "oblit %s already has a value",
- p->b.oblit.name == NN ? "unknown" :
- ST_SymbolName(p->b.oblit.name->b.symdef.symbol));
- } else {
- p->b.oblit.f.isManifest =
- !(p->b.oblit.f.isTypeVariable || p->b.oblit.f.dependsOnTypeVariable);
- p->b.oblit.f.writeSeparately = p->b.oblit.f.isManifest;
- gsr = getGetSignatureResult(p, TRUE);
- if (gsr != NN) {
- p->b.oblit.instat = gsr;
- if (gsr->tag == P_ATLIT && gsr->b.atlit.f.cannotBeConformedTo &&
- gsr->b.atlit.codeOID == 0) {
- TRACE0(knowmanifest, 1, "Found ATLIT that cannotBeConformedTo");
- assert(gsr->b.atlit.f.isVector);
- cr = getCreateResult(p, TRUE);
- assert(cr != NN);
- assert(cr->tag == P_OBLIT);
- if (cr->b.oblit.codeOID == 0) {
- TRACE0(knowmanifest, 3, "Have to assignOIDs to the create result");
- assignOIDs(cr);
- }
- gsr->b.atlit.codeOID = cr->b.oblit.codeOID;
- }
- }
- p->b.oblit.id = AllocateOID();
- if (p->b.oblit.f.isManifest && !p->b.oblit.f.immutable) {
- assert(Zflag);
- p->b.oblit.id &= 0xfeffffff;
- }
- OTInsert(p, p->b.oblit.id);
- if (p->b.oblit.f.isManifest) {
- p->b.oblit.codeOID = AllocateOID();
- OTInsert(p, p->b.oblit.codeOID);
- }
- }
- break;
- default:
- break;
- }
- }
-
- static void newFigureObjectTypes(p)
- register NodePtr p;
- {
- Symbol st;
-
- if (ISTOKEN(p)) return;
- switch (p->tag) {
- case P_KNOWMANIFEST:
- newFigureObjectTypes(p->b.knowmanifest.answer);
- break;
- case P_OBLIT:
- if (p->b.oblit.name == NN) {
- assert(bflag || loadedDummyBuiltins);
- } else if (p->b.oblit.myat == NULL) {
- st = ST_Fetch(p->b.oblit.name->b.symdef.symbol);
- st->value.value = p;
- st->value.CTinfo = p;
- st->value.ATinfo = buildATOfObject(p);
- assert(st->value.ATinfo != NN);
- p->b.oblit.myat = getExportedATOfObject(p, st->value.ATinfo);
- assert(p->b.oblit.myat != NN);
- }
- break;
- default:
- break;
- }
- }
-
- void fleshOutAllSymbols(p)
- NodePtr p;
- {
- NodePtr inhibitedChild = NN, q;
- Boolean done = FALSE;
- Symbol st;
- if (ISTOKEN(p)) return;
- switch (p->tag) {
- case P_SYMBOL:
- st = (Symbol) p;
- if (st->value.ATinfo == NULL && st->value.value != NN) {
- fleshOutValue(&st->value);
- }
- done = TRUE;
- break;
- case P_SYMDEF:
- case P_SYMREF:
- st = p->b.symref.symbol;
- if (st->value.ATinfo == NULL && symbolHasValue(st)) {
-
- fleshOutValue(&st->value);
- }
- break;
- default:
- break;
- }
- if (!done) Sequence_For(q, p)
- if (!ISTOKEN(q) && q != inhibitedChild) fleshOutAllSymbols(q);
- Sequence_Next
- }
-
- void doPropagate(p, secondTime)
- register Set p;
- Boolean secondTime;
- {
- NodePtr anElement, value = NULL, myPrereq, oldValue, dt, km;
- NodePtr oldAT, newAT;
- register Symbol st;
- Boolean doItAgain, madeProgress;
- int nPass3s = 0;
- OID savedID;
- Boolean savedWriteSeparately;
- do {
- nPass3s++;
- TRACE1(knowmanifest, 4, "Doing step 3, pass %d", nPass3s);
- doItAgain = FALSE;
- madeProgress = FALSE;
- Set_For(anElement, p)
- anElement->b.knowmanifest.isDone = TRUE;
- anElement->b.knowmanifest.isOK = TRUE;
- if (anElement->b.knowmanifest.answer != NN) continue;
- dt = anElement->b.knowmanifest.definingThing;
- switch (dt->tag) {
- case P_INVOC:
- executeAnInvocation(anElement, IS_Step2, (NodePtr *)NULL);
- madeProgress = TRUE;
- break;
- case P_BUILTINLIT:
- anElement->b.knowmanifest.answer =
- refToBuiltinFromToken(B_IT, dt->b.builtinlit.whichType);
- madeProgress = TRUE;
- break;
- case P_ATLIT:
- if (!secondTime) {
- assert(! dt->b.atlit.f.dependsOnTypeVariable);
- assert(! dt->b.atlit.f.typesAreAssigned);
- assert(! dt->b.atlit.f.typesHaveBeenChecked);
- assert(! dt->b.atlit.f.isManifest);
- assert(! dt->b.atlit.f.writeSeparately);
- dt->b.atlit.f.dependsOnTypeVariable =
- anElement->b.knowmanifest.dependsOnTypeVariable;
- }
- anElement->b.knowmanifest.answer = dt;
- madeProgress = TRUE;
- break;
- case P_OBLIT:
- if (!secondTime) {
- assert(! dt->b.oblit.f.dependsOnTypeVariable);
- assert(! dt->b.oblit.f.typesAreAssigned);
- assert(! dt->b.oblit.f.typesHaveBeenChecked);
- assert(! dt->b.oblit.f.isManifest);
- assert(! dt->b.oblit.f.writeSeparately);
- dt->b.oblit.f.dependsOnTypeVariable =
- anElement->b.knowmanifest.dependsOnTypeVariable;
- }
- anElement->b.knowmanifest.answer = dt;
- madeProgress = TRUE;
- break;
- case P_SYMBOL:
- if (Set_Size(anElement->b.knowmanifest.dependsOn) == 1) {
- st = (Symbol) dt;
- Set_GetFirst(anElement->b.knowmanifest.dependsOn, myPrereq);
- if (myPrereq->b.knowmanifest.answer == NN) {
- /* this has not been done yet, so arrange another pass 3 */
- doItAgain = TRUE;
- } else {
- anElement->b.knowmanifest.answer = myPrereq->b.knowmanifest.answer;
- st->isManifest = TRUE;
- st->value.value = anElement->b.knowmanifest.answer;
- madeProgress = TRUE;
- }
- } else {
- st = (Symbol) dt;
- assert(symbolHasValue(st));
- assert(st->value.value != NN);
- anElement->b.knowmanifest.answer = st->value.value;
- madeProgress = TRUE;
- }
- break;
- case P_PARAM:
- /*
- * We care if the value is an atlit or a something else. If it is an
- * atlit we modify it to be a typeVariable, otherwise we copy it and
- * then modify the copy.
- */
- assert(Set_Size(anElement->b.knowmanifest.dependsOn) == 1);
-
- Set_GetFirst(anElement->b.knowmanifest.dependsOn, oldValue);
- oldValue = oldValue->b.knowmanifest.answer;
- value = dt->b.param.constraint;
- st = dt->b.param.sym->b.symdef.symbol;
- assert(value != NN && oldValue != NN);
- if (value->tag != P_ATLIT) {
- /* we need to copy it */
- oldAT = newExecuteAsAT(oldValue);
- if (oldAT == NULL) {
- ErrorMessage(value, "Parameter constraints must be types");
- oldAT = refToBuiltin(B_INSTAT, ABSTRACTTYPEINDEX);
- }
- TRACE3(knowmanifest, 3, "copying literal \"%s\" on line %d %s",
- NAMEOF(oldAT->b.atlit.name), value->lineNumber, "");
- savedID = oldAT->b.atlit.id;
- savedWriteSeparately = oldAT->b.atlit.f.writeSeparately;
- oldAT->b.atlit.f.writeSeparately = 0;
- oldAT->b.atlit.id = 0;
- newAT = copyTree(oldAT, TRUE);
- oldAT->b.atlit.f.writeSeparately = savedWriteSeparately;
- oldAT->b.atlit.id = savedID;
- } else {
- assert(oldValue->tag == P_ATLIT);
- assert(oldValue == value);
- newAT = oldValue;
- }
- newAT->b.atlit.f.isTypeVariable = TRUE;
- km = (NodePtr) Map_Lookup(dependManifestMap, (int)newAT);
- if ((int) km == NIL) {
- km = Construct(P_KNOWMANIFEST, 3, NN, NN, NN);
- km->b.knowmanifest.tag = newAT->tag;
- km->b.knowmanifest.definingThing = newAT;
- Map_Insert(dependManifestMap, (int)newAT, (int)km);
- }
- km->b.knowmanifest.isTypeVariable = TRUE;
- km->b.knowmanifest.isDone = TRUE;
- km->b.knowmanifest.isOK = TRUE;
- if (km->b.knowmanifest.answer == NN)
- km->b.knowmanifest.answer = newAT;
- anElement->b.knowmanifest.isTypeVariable = TRUE;
- newAT->b.atlit.f.isManifest = FALSE;
- newAT->b.atlit.f.writeSeparately = FALSE;
- newAT->b.atlit.id = AllocateOID();
- OTInsert(newAT, newAT->b.atlit.id);
- newAT->b.atlit.name->b.symdef.symbol->isManifest = FALSE;
- newAT->b.atlit.name->b.symdef.symbol->hasValue = TRUE;
- st->isManifest = FALSE;
- st->hasValue = TRUE;
- st->value.value = newAT;
- TRACE3(knowmanifest, 2, "made literal \"%s\" on line %d %s",
- NAMEOF(newAT->b.atlit.name), newAT->lineNumber,
- "isTypeVariable");
- anElement->b.knowmanifest.answer = newAT;
- madeProgress = TRUE;
- break;
- default:
- assert(FALSE);
- break;
- }
- Set_Next
- if (!madeProgress) {
- TRACE0(knowmanifest, 1, "Didn't make progress, dying");
- assert(FALSE);
- }
- } while (doItAgain);
- }
-
- void propagateMANInfo()
- {
- register Set p = manStack->manifestThings;
- NodePtr q, anElement, dt, theNewManifests;
- NodePtr an;
- register Symbol st;
- Boolean isManifest = TRUE, isImport;
- Boolean dependsOnTypeVariable = FALSE,
- typeDependsOnTypeVariable = FALSE;
- int setSize, nInvocs, nParams;
-
- nInvocs = 0;
- nParams = 0;
- setSize = Set_Size(p);
-
- if (setSize == 1) {
- TRACE0(knowmanifest, 1, "Progagating to a single element");
- } else {
- TRACE1(knowmanifest, 1, "Progagating to a set of size %d",
- setSize);
- }
- Set_For(anElement, p)
- TRACE1(knowmanifest, 2, "Looking at pre-reqs of %s", thingName(anElement));
- switch (anElement->b.knowmanifest.tag) {
- case P_ATLIT:
- break;
- case P_PARAM:
- nParams++;
- break;
- case P_SYMBOL:
- if (Set_Size(anElement->b.knowmanifest.dependsOn) <= 0) {
- st = (Symbol) anElement->b.knowmanifest.definingThing;
- if (!symbolHasValue(st)) {
- TRACE1(knowmanifest, 3,
- "Symbol %s has no dependents, is not manifest",
- thingName(anElement));
- isManifest = FALSE;
- continue;
- }
- }
- break;
- case P_OBLIT:
- case P_BUILTINLIT:
- break;
- case P_INVOC:
- nInvocs++;
- break;
- default:
- isManifest = FALSE;
- continue;
- /* break; */
- }
- Set_For(q, anElement->b.knowmanifest.dependsOn)
- TRACE1(knowmanifest, 3, "Looking at %s", thingName(q));
- assert(q->tag == P_KNOWMANIFEST);
- if (! q->b.knowmanifest.isDone) continue; /* it is in this set */
- if (!q->b.knowmanifest.isOK) {
- isManifest = FALSE;
- TRACE1(knowmanifest, 4, "%s not ok, give up", thingName(q));
- break;
- }
- switch (anElement->b.knowmanifest.tag) {
- case P_OBLIT:
- case P_ATLIT:
- isImport = q->b.knowmanifest.isImport;
- break;
- default:
- isImport = TRUE;
- break;
- }
- switch(q->b.knowmanifest.tag) {
- case P_ATLIT:
- case P_OBLIT:
- case P_INVOC:
- case P_BUILTINLIT:
- case P_PARAM:
- case P_SYMBOL:
- break;
- case P_SELFLIT:
- assert(FALSE);
- break;
- case P_VECTORLIT:
- case P_BOOLLIT:
- case P_CHARLIT:
- case P_INTLIT:
- case P_REALLIT:
- case P_STRINGLIT:
- case T_NONE:
- default:
- isManifest = FALSE;
- break;
- }
- if (isImport &&
- (q->b.knowmanifest.dependsOnTypeVariable ||
- q->b.knowmanifest.isTypeVariable)) {
- TRACE1(knowmanifest, 3, "%s iTV or dOTV", thingName(q));
- dependsOnTypeVariable =
- dependsOnTypeVariable ||
- isImport && (
- q->b.knowmanifest.dependsOnTypeVariable ||
- q->b.knowmanifest.isTypeVariable);
- typeDependsOnTypeVariable =
- typeDependsOnTypeVariable ||
- q->b.knowmanifest.dependsOnTypeVariable ||
- q->b.knowmanifest.isTypeVariable;
- Set_Next
- }
- if (isManifest && anElement->b.knowmanifest.tag == P_INVOC) {
- #define BAILOUT {isManifest = FALSE; goto bailout; }
- NodePtr target, opName, opdef, formals, actuals, result;
-
- q = anElement->b.knowmanifest.definingThing;
- assert(Map_Lookup(manifestMap, (int) q) == NIL);
-
- /* see if the invocation can be done */
- target = q->b.invoc.target;
- if (target->tag == P_SYMREF) target = (NodePtr) target->b.symref.symbol;
- opName = q->b.invoc.opname;
- actuals = q->b.invoc.args;
- target = findManifestValue(target);
- if (target->tag != P_OBLIT) BAILOUT;
- if (! target->b.oblit.f.immutable) BAILOUT;
- opdef = findObjectOperation(target, opName);
- if (opdef == NULL) BAILOUT;
- if (!opdef->b.opdef.sig->b.opsig.isFunction) BAILOUT;
- formals = opdef->b.opdef.sig->b.opsig.params;
- if (Sequence_Length(formals) != Sequence_Length(actuals)) BAILOUT;
- result = findTheResultExpression(opdef, TRUE);
- if (result == NN) BAILOUT;
-
- bailout: ;
- #undef BAILOUT
- }
- Set_Next
- if (nParams > 0 && setSize != 1) {
- isManifest = FALSE;
- TRACE0(knowmanifest, 1, "I do not know how to deal with params in sets.");
- assert(FALSE);
- }
- if (!isManifest) {
- TRACE0(knowmanifest, 1, "The set is not manifest");
- Set_For(anElement, p)
- anElement->b.knowmanifest.isDone = TRUE;
- anElement->b.knowmanifest.isOK = FALSE;
- anElement->b.knowmanifest.answer = NULL;
- anElement->b.knowmanifest.dependsOnTypeVariable = dependsOnTypeVariable;
- dt = anElement->b.knowmanifest.definingThing;
- switch (dt->tag) {
- case P_OBLIT:
- dt->b.oblit.f.typeDependsOnTypeVariable = typeDependsOnTypeVariable;
- dt->b.oblit.f.dependsOnTypeVariable = dependsOnTypeVariable;
- if (dt->b.oblit.f.dependsOnTypeVariable) {
- dt->b.oblit.codeOID = 0;
- } else {
- assert(dt->b.oblit.codeOID == 0);
- dt->b.oblit.codeOID = AllocateOID();
- OTInsert(dt, dt->b.oblit.codeOID);
- }
- if (dt->b.oblit.name == NN) {
- assert(bflag || loadedDummyBuiltins);
- } else {
- st = dt->b.oblit.name->b.symdef.symbol;
- assert(st->isSelf);
- assert(dt->b.oblit.myat == NULL);
- st->value.value = dt;
- st->value.CTinfo = dt;
- st->value.ATinfo = buildATOfObject(dt);
- dt->b.oblit.myat = getExportedATOfObject(dt, st->value.ATinfo);
- }
- break;
- case P_ATLIT:
- WarningMessage(dt, "This abstract type is not manifest");
- break;
- default:
- break;
- }
- Set_Next
- } else {
- TRACE0(knowmanifest, 1, "The entire set is manifest");
-
- if (setSize == 1) {
- Set_GetFirst(p, anElement);
- assert(anElement->tag == P_KNOWMANIFEST);
- anElement->b.knowmanifest.dependsOnTypeVariable = dependsOnTypeVariable;
- dt = anElement->b.knowmanifest.definingThing;
- if (dt->tag == P_SYMBOL) {
- if (symbolHasValue((Symbol)dt)) {
- TRACE1(knowmanifest, 7, "%s is already manifest", thingName(anElement));
- anElement->b.knowmanifest.isOK = TRUE;
- anElement->b.knowmanifest.isDone = TRUE;
- assert(((Symbol)dt)->value.value != NN);
- anElement->b.knowmanifest.answer = ((Symbol)dt)->value.value;
- return;
- }
- } else if (dt->tag == P_ATLIT || dt->tag == P_OBLIT) {
- if (literalHasValue(dt)) {
- TRACE1(knowmanifest, 7, "%s is already manifest", thingName(anElement));
- anElement->b.knowmanifest.isOK = TRUE;
- anElement->b.knowmanifest.isDone = TRUE;
- anElement->b.knowmanifest.answer = dt;
- return;
- }
- } else if (dt->tag == P_INVOC) {
- NodePtr result;
- /*
- * There is a possibility that we have done this invocation before.
- * Check it out. If we have, just get me the answer, and return.
- */
- result = checkInvocCache(dt);
- if (result != NN) {
- Value value;
- TRACE1(knowmanifest, 7, "%s by previous compilation",
- thingName(anElement));
- anElement->b.knowmanifest.isOK = TRUE;
- anElement->b.knowmanifest.isDone = TRUE;
- anElement->b.knowmanifest.answer = result;
- value.value = anElement->b.knowmanifest.answer;
- fleshOutValue(&value);
- Map_Insert(manifestMap, (int)dt, (int)value.ATinfo);
- Map_Insert(manifestMap, (int)dt+1, (int)value.CTinfo);
- Map_Insert(manifestMap, (int)dt+2, (int)value.value);
- dt->b.invoc.resultTypeOID = OIDOf(value.ATinfo);
- return;
- }
- }
- }
-
- /*
- * Now, we must figure out what all these manifest things are.
- *
- * 1) Merge invocations that are the same. Invocations are the same if
- * they have the same target, operationName, and if their arguments are
- * the same. We only need to do this if the arguments to 2 of the
- * invocations are within this same set, bu they must be or the invocation
- * itself wouldn't be. This is an optimization that attempts to only copy
- * the result tree once. It is currently not done.
- *
- * 2) Create the result nodes for each invocation, storing them in the
- * knowManifest node as the answer. We need to allocate these roots before
- * we do any copying, as the argument to one invocation could be the result
- * of another one.
- *
- * 3) Go through the entire set of manifest things, and set their result
- * pointers, instATs of object literals, values of symbols. Note that
- * this includes the results of invocations, and all the types contained
- * inside of there.
- *
- * 4) Record the need to check the types of each invocation.
- * Fill in the answer roots that were allocated in step 2. Note that
- * this is just for invocation nodes. We copy the tree that is the answer
- * in the invocation, performing substitutions as indicated by the
- * parameter passing and imports. The answer is not the final tree, but
- * type assignment and checking has not yet been done.
- *
- * After this point, no further copying will need to be done.
- *
- * 5) Assign OIDs to the literals. This probably doesn't need to be a
- * separate pass, but what the heck.
- *
- * 6) Assign types.
- *
- * 7) Figure out the ownATs of object literals.
- *
- * 8) Make sure that all manifest symbols have complete information.
- *
- * 9) Type check. Also, check the types that we
- * needed to do in order to do the invocations in the first place.
- */
-
- /*
- * Step 1. Currently not done.
- */
- TRACE0(knowmanifest, 2, "!!NOT!! Doing step 1");
-
- /*
- * Step 2.
- */
- TRACE0(knowmanifest, 2, "Doing step 2 (set type variable info)");
- Set_For(anElement, p)
- anElement->b.knowmanifest.dependsOnTypeVariable = dependsOnTypeVariable;
- dt = anElement->b.knowmanifest.definingThing;
- switch (dt->tag) {
- case P_OBLIT:
- dt->b.oblit.f.typeDependsOnTypeVariable = typeDependsOnTypeVariable;
- break;
- default:
- break;
- }
- Set_Next
-
- /*
- * Step 3.
- */
- TRACE0(knowmanifest, 2, "Doing step 3 (propagating info through symbols)");
- doPropagate(p, FALSE);
-
- Set_For(anElement, p)
- dt = anElement->b.knowmanifest.definingThing;
- if (dt->tag == P_OBLIT) {
- NodePtr gsr;
- gsr = getGetSignatureResult(dt, TRUE);
- if (gsr != NN) {
- dt->b.oblit.instat = gsr;
- }
- }
- Set_Next
-
- /*
- * Step 4.
- */
- TRACE0(knowmanifest, 2, "Doing step 4 (finalizing invocations)");
- theNewManifests = NN;
- Set_For(anElement, p)
- dt = anElement->b.knowmanifest.definingThing;
- if (dt->tag == P_INVOC) {
- executeAnInvocation(anElement, IS_Step4, &theNewManifests);
- }
- Set_Next
- /*
- * We now have the stuff that we need to call doKnowManifests on
- */
- if (theNewManifests != NN) {
- TRACE0(knowmanifest, 1,
- "Calling doKnowManifests to figure the invoc results");
- doKnowManifests(theNewManifests);
- TRACE0(knowmanifest, 1,
- "DoKnowManifests finished figuring the invoc results");
- }
- if (!ATTOPLEVEL) {
- /*
- * If we are not at the top level, we need to merge our answers into
- * the thing at the next level down. We also update the counters.
- */
- ManifestStack next = manStack->next;
- Set_Merge(manStack->manifestThings, next->manifestThings);
- return;
- }
-
- if (nInvocs > 0) {
- TRACE0(knowmanifest, 2, "Finalizing invocations added some new things");
- }
- #ifdef XXXXXX
- Set_For(anElement, p)
- dt = anElement->b.knowmanifest.definingThing;
- if (dt->tag == P_OBLIT) {
- NodePtr gsr;
- if (!dt->b.oblit.f.isTypeVariable &&
- !dt->b.oblit.f.dependsOnTypeVariable) {
- gsr = getGetSignatureResult(dt, TRUE);
- if (gsr != NN) {
- dt->b.oblit.instat = gsr;
- }
- }
- }
- Set_Next
- #endif
-
- /*
- * Step 5. Traverse the manifest things, assigning OIDs to the atlits
- * and oblits. Also, set the isManifest bit in atlits and oblits.
- * Always, isTypeVariable or dependsOnTypeVariable implies not
- * isManifest. Also, set instat's of oblits.
- */
- TRACE0(knowmanifest, 2, "Doing step 5 (assigning OIDs)");
- Set_For(anElement, p)
- assignOIDs(anElement);
- Set_Next
-
- /*
- * Step 7.
- */
-
- TRACE0(knowmanifest, 2, "Doing step 7 (Figuring object types)");
- Set_For(anElement, p)
- an = anElement->b.knowmanifest.answer;
- assert(an != NULL);
- newFigureObjectTypes(an);
- Set_Next
-
- /*
- * Step 8.
- */
- TRACE0(knowmanifest, 2, "Doing step 8 (Finalizing AT and CT info in symbols)");
- Set_For(anElement, p)
- dt = anElement->b.knowmanifest.definingThing;
- fleshOutAllSymbols(dt);
- Set_Next
-
- #ifdef XXXXXX
- TRACE0(knowmanifest, 2, "Doing step 9 (assigning Types)");
- Set_For(anElement, p)
- an = anElement->b.knowmanifest.answer;
- if (an->tag == P_ATLIT || an->tag == P_OBLIT) {
- newAssignTypes(an, 1);
- }
- Set_Next
- #endif
-
- #ifdef XXXXXX
- TRACE0(knowmanifest, 2, "Doing step 9 (checking Types)");
- Set_For(anElement, p)
- an = anElement->b.knowmanifest.answer;
- if (an->tag == P_ATLIT || an->tag == P_OBLIT) {
- typeCheck(an);
- }
- Set_Next
- #endif
- }
-
- Set_For(anElement, p)
- assert(anElement->tag == P_KNOWMANIFEST);
- TRACE5(knowmanifest, 2, "Finalizing %s: %s %s%s0x%08x",
- thingName(anElement),
- anElement->b.knowmanifest.isOK ? "is OK" : "is notOK",
- anElement->b.knowmanifest.isTypeVariable ? "iTV " : "" ,
- anElement->b.knowmanifest.dependsOnTypeVariable ? "dOTV " : "",
- anElement->b.knowmanifest.answer);
- dt = anElement->b.knowmanifest.definingThing;
- if (anElement->b.knowmanifest.isOK && dt->tag == P_INVOC) {
- Value value;
- assert(anElement->b.knowmanifest.answer != NN);
- updateInvocCache(dt, anElement->b.knowmanifest.answer);
- value.value = anElement->b.knowmanifest.answer;
- fleshOutValue(&value);
- Map_Insert(manifestMap, (int)dt, (int)value.ATinfo);
- Map_Insert(manifestMap, (int)dt+1, (int)value.CTinfo);
- Map_Insert(manifestMap, (int)dt+2, (int)value.value);
- dt->b.invoc.resultTypeOID = OIDOf(value.ATinfo);
- }
- Set_Next
- }
-
- static void MAN_SearchC(v)
- register NodePtr v;
- {
- register NodePtr x;
- NodePtr w;
- register Set SCComponent;
-
- v->b.knowmanifest.marked = TRUE;
- v->b.knowmanifest.number = count++;
- v->b.knowmanifest.lowLink = v->b.knowmanifest.number;
- Sequence_Add(&manStack->SCstack, v);
- v->b.knowmanifest.onStack = TRUE;
- Set_For(w, v->b.knowmanifest.dependsOn)
- if (! w->b.knowmanifest.marked) {
- MAN_SearchC(w);
- v->b.knowmanifest.lowLink = min(v->b.knowmanifest.lowLink, w->b.knowmanifest.lowLink);
- } else {
- if (w->b.knowmanifest.number < v->b.knowmanifest.number && w->b.knowmanifest.onStack) {
- v->b.knowmanifest.lowLink = min(w->b.knowmanifest.number, v->b.knowmanifest.lowLink);
- }
- }
- Sequence_Next
- if (v->b.knowmanifest.lowLink == v->b.knowmanifest.number) {
- SCComponent = Set_Create();
- TRACE0(knowmanifest, 1, "------");
- Sequence_ReverseFor(x, manStack->SCstack)
- manStack->SCstack->nChildren --;
- assert(x->b.knowmanifest.onStack);
- x->b.knowmanifest.onStack = FALSE;
- Set_Insert(SCComponent, (int)x);
- TRACE1(knowmanifest, 1, "struct %s", thingName(x));
- if (x == v) break;
- Sequence_Next
- manStack->manifestThings = SCComponent;
- propagateMANInfo();
- assert(SCComponent == manStack->manifestThings);
- Set_Destroy(manStack->manifestThings);
- manStack->manifestThings = NULL;
- }
- }
-
- NodePtr newExecuteAsAT(p)
- register NodePtr p;
- {
- NodePtr exp, type;
-
- exp = findManifestValue(p);
- if (exp == NULL) {
- ErrorMessage(p, "Abstract types must be manifest");
- } else {
- type = figureOutAT(exp);
- if (type == NULL) {
- ErrorMessage(p, "This expression is not a type");
- } else {
- assert(type->tag == P_ATLIT);
- return(type);
- }
- }
- return(refToBuiltin(B_INSTAT, ANYINDEX));
- }
-
- NodePtr tryToExecuteAsAT(p)
- register NodePtr p;
- {
- NodePtr type, value;
-
- value = findManifestValue(p);
- if (value == NULL) {
- return(NULL);
- } else {
- type = figureOutAT(value);
- if (type == NULL) {
- return(NULL);
- } else {
- assert(type->tag == P_ATLIT);
- return(type);
- }
- }
- }
-
- /*
- * newAssignTypes jobs is to traverse the tree in order, and assign types to
- * every identifier. It uses newExecuteAsAT to return the type of an expression
- * in a type position. It stops when it discovers an atlit or oblit that is
- * not manifest.
- */
-
- static void doNewAssignTypes();
-
- void newAssignTypes(p, dL)
- register NodePtr p;
- int dL;
- {
- NodePtr thing, km;
- doNewAssignTypes(p, dL);
- if (p->tag == P_COMP) {
- Map_For(dependManifestMap, thing, km)
- if (km->b.knowmanifest.isOK) {
- doNewAssignTypes(km->b.knowmanifest.answer, dL);
- }
- Map_Next
- }
- }
-
- static void doNewAssignTypes(p, dL)
- register NodePtr p;
- int dL;
- {
- register NodePtr q;
- register Symbol st;
- register NodePtr inhibitedChild = NULL;
- Boolean done = FALSE;
-
- if (ISTOKEN(p)) return;
- switch (p->tag) {
- case P_ATLIT:
- if (p->b.atlit.f.typesAreAssigned) return;
- if (dL <= 0) return;
- dL --;
- p->b.atlit.f.typesAreAssigned = TRUE;
- break;
- case P_OBLIT:
- if (p->b.oblit.f.typesAreAssigned) return;
- if (dL <= 0) return;
- dL --;
- p->b.oblit.f.typesAreAssigned = TRUE;
- if (p->b.oblit.f.isManifest) {
- assert(p->b.oblit.id != 0);
- assert(bflag || p->b.oblit.codeOID != 0);
- } else if (p->b.oblit.f.dependsOnTypeVariable) {
- assert(p->b.oblit.codeOID == 0);
- } else {
- /* just plain not manifest */
- assert(p->b.oblit.id == 0);
- if (p->b.oblit.codeOID == 0) {
- p->b.oblit.codeOID = AllocateOID();
- OTInsert(p, p->b.oblit.codeOID);
- }
- }
- if (p->b.oblit.name == NN) {
- assert(bflag || loadedDummyBuiltins);
- } else {
- assert(p->b.oblit.name->b.symdef.symbol->isSelf);
- p->b.oblit.name->b.symdef.symbol->value.value = p;
- }
- break;
- case P_CONSTDECL:
- q = p->b.constdecl.sym;
- assert(q->tag == P_SYMDEF);
- st = ST_Fetch(q->b.symdef.symbol);
- if (st->isManifest) {
- /*
- * Its type has already been assigned, but we need to assign types to
- * its value, which is not the same as its p->b.constdecl.value.
- */
- doNewAssignTypes(st->value.value, dL);
- done = TRUE;
- } else {
- if (p->b.constdecl.type != NN) {
- st->value.ATinfo = newExecuteAsAT(p->b.constdecl.type);
- } else {
- assert(st->value.value == NULL);
- /*
- * This is not a manifest constant. If we dont have a type field,
- * then we need to figure out the type of the value field.
- */
- st->value.ATinfo = evaluateForAT(p->b.constdecl.value, FALSE);
- if (st->value.ATinfo->tag == T_SEQUENCE) {
- assert(st->value.ATinfo->nChildren == 1);
- st->value.ATinfo = st->value.ATinfo->b.children[0];
- }
- }
- tryToSetCTInfo(st);
- }
- break;
- case P_PARAM:
- q = p->b.param.sym;
- assert(q->tag == P_SYMDEF);
- st = ST_Fetch(q->b.symdef.symbol);
- if (p->b.param.constraint != NN) {
- /*
- * This is a parameter whose type is abstract type and whose value
- * should be a type variable.
- */
- assert(symbolHasValue(st));
- assert(st->value.value != NULL);
- assert(st->value.value->tag == P_ATLIT);
- assert(st->value.value->b.atlit.f.isTypeVariable);
- st->value.ATinfo = refToBuiltin(B_INSTAT, SIGNATUREINDEX);
- st->value.CTinfo = refToBuiltin(B_INSTCT, SIGNATUREINDEX);
- } else {
- st->value.ATinfo = newExecuteAsAT(p->b.param.type);
- tryToSetCTInfo(st);
- }
- break;
- case P_VARDECL:
- q = p->b.vardecl.sym;
- assert(q->tag == P_SYMDEF);
- st = ST_Fetch(q->b.symdef.symbol);
- st->value.ATinfo = newExecuteAsAT(p->b.vardecl.type);
- tryToSetCTInfo(st);
- break;
- case P_WHEREWIDGIT:
- assert(p->b.wherewidgit.op == OIDENTITY);
- q = p->b.wherewidgit.sym;
- assert(q->tag == P_SYMDEF);
- st = ST_Fetch(q->b.symdef.symbol);
- if (!symbolHasValue(st)) {
- ErrorMessage(q,
- "Identifiers introduced in where clauses must have values");
- }
- break;
- case P_SETQ:
- st = p->b.setq.inner->b.symdef.symbol;
- if (symbolHasValue(st)) break;
- q = p->b.setq.outer;
- if (q->tag == P_SYMREF) {
- if (q->b.symref.symbol->value.ATinfo == NULL) {
- ErrorMessage(p, "Imported symbol %s has no type",
- ST_SymbolName(q->b.symref.symbol));
- }
- st->value = q->b.symref.symbol->value;
- } else {
- st->value.value = q;
- fleshOutValue(&st->value);
- }
- break;
- #ifdef COPYSIGS
- case P_SYMDEF:
- case P_SYMREF:
- st = p->b.symdef.symbol;
- if (st->value.ATinfo == NN && symbolHasValue(st)) {
- doNewAssignTypes(st->value.value);
- fleshOutValue(&st->value);
- }
- break;
- #endif
- default:
- break;
- }
- if (!done) Sequence_For(q, p)
- if (!ISTOKEN(q) && q != inhibitedChild) doNewAssignTypes(q, dL);
- Sequence_Next
- }
-
- void MAN_FindAll()
- {
- NodePtr theThing, theStruct;
- Map_For(manStack->candidates, theThing, theStruct)
- if (! theStruct->b.knowmanifest.marked) MAN_SearchC(theStruct);
- Map_Next
- }
-
- void doKnowManifests(p)
- NodePtr p;
- {
- register ManifestStack m;
- m = (ManifestStack) calloc(1, sizeof(ManifestSE));
- m->candidates = Map_Create();
- m->SCstack = NULL;
- m->next = manStack;
- manStack = m;
- buildKnowManifestGraph(p, (Boolean)(bflag ? FALSE : (Zflag ? FALSE : TRUE)));
- displayKnowManifestGraph();
- MAN_FindAll();
- assert(m == manStack);
- manStack = m->next;
- Map_Destroy(m->candidates);
- free((char *)m);
- }
-
- void newEvaluateManifest(p, value)
- NodePtr p;
- Value *value;
- {
- NodePtr answer;
- NodePtr thing, km;
- extern Boolean checkingTypes;
-
- answer = findManifestValue(p);
- if (answer == NN) {
- doKnowManifests(p);
- if (manStack == NULL) {
- /* we called doKnowManifest later */
- newAssignTypes(p);
- Map_For(dependManifestMap, thing, km)
- if (km->b.knowmanifest.isOK) {
- doNewAssignTypes(km->b.knowmanifest.answer, 999);
- }
- Map_Next
- }
- answer = findManifestValue(p);
- }
- if (answer == NN) {
- value->value = NN;
- value->ATinfo = NN;
- value->CTinfo = NN;
- } else {
- value->value = answer;
- fleshOutValue(value);
- }
- }
-