home *** CD-ROM | disk | FTP | other *** search
- /*
- * @(#)construct.c 1.5 1/20/89
- */
- #include "assert.h"
- #include "nodes.h"
- #include "keyword.h"
- #include "system.h"
- #include "sequence.h"
- #include "semantics.h"
-
- NodePtr RCONS(list, anElement)
- NodePtr list, anElement;
- {
- register NodePtr newlist;
- register int length;
- if (list == NULL) {
- newlist = F_NewNode(T_SEQUENCE, 4);
- } else if (list->nChildren >= list->maxChildren) {
- length = list->maxChildren;
- newlist = F_NewNode(list->tag, 2 * length);
- bcopy((char *)list, (char *)newlist, NodeSize(list));
- newlist->maxChildren = 2 * length;
- free((char *)list);
- } else {
- newlist = list;
- }
- if (newlist->nChildren == 0 && (int) anElement > 0x200)
- newlist->lineNumber = anElement->lineNumber;
- newlist->b.children[newlist->nChildren] = anElement;
- newlist->nChildren++;
- return(newlist);
- }
-
- NodePtr RAPPEND(list, listOrElement)
- NodePtr list, listOrElement;
- {
- register NodePtr q;
- if (! isASequence(list)) {
- q = F_NewNode(T_SEQUENCE, 4);
- q->nChildren = 1;
- q->b.children[0] = list;
- list = q;
- }
- if (listOrElement == NULL)
- return(list);
- if ((int)listOrElement <= 0x200 || listOrElement->tag != T_SEQUENCE)
- return(RCONS(list, listOrElement));
- Sequence_For(q, listOrElement)
- list = RCONS(list, q);
- Sequence_Next
- free((char *)listOrElement);
- return(list);
- }
-
- /*VARARGS2*/
- NodePtr Construct(t, nargs, therest)
- Tag t;
- int nargs;
- NodePtr therest;
- {
- register NodePtr *args = &therest;
- register NodePtr p;
- register int i;
- int minLineNumber;
-
- p = F_NewNode(t, nargs);
- minLineNumber = p->lineNumber;
- for (i = 0; i < nargs; i++) {
- p->b.children[p->firstChild+i] = args[i];
- if ((int) args[i] > 0x200 && args[i]->lineNumber < minLineNumber)
- minLineNumber = args[i]->lineNumber;
- }
- p->nChildren += nargs;
- p->lineNumber = minLineNumber;
- return (p);
- }
-
- NodePtr makeOpName(p)
- NodePtr p;
- {
- register NodePtr result;
- if ((int) p <= 0x200) {
- result = Construct(P_OPNAME, 0);
- result->b.opname.ident = (int)p - firstKeyword;
- return(result);
- } else if (p->tag == T_IDENT) {
- result = Construct(P_OPNAME, 0);
- result->b.opname.ident = p->b.ident.ident;
- free((char *)p);
- return(result);
- } else {
- assert (p->tag == P_OPNAME);
- return(p);
- }
- }
-
- /*
- * fD1 is a primary, fD2 is a sequence of selections. Each selection is:
- * P_SELECTION NULL opname argumentlist
- * P_FIELDSEL NULL identifier
- * P_SUBSCRIPT NULL expression
- * We want to build the unsugared node, either:
- * P_INVOC rest opname argumentlist
- * P_FIELDSEL rest identifier
- * P_SUBSCRIPT rest expression
- */
- NodePtr buildSelection(fD1, fD2)
- NodePtr fD1, fD2;
- {
- Tag tag;
- register NodePtr result, thisOne, q;
-
- result = fD1;
- Sequence_For(thisOne, fD2)
- tag = thisOne->tag;
- switch (tag) {
- case P_SELECTION:
- q = Construct(P_INVOC, 3, result,
- thisOne->b.selection.opname, thisOne->b.selection.args);
- q->lineNumber = thisOne->lineNumber;
- free((char *) thisOne);
- thisOne = q;
- break;
- case P_FIELDSEL:
- thisOne->b.fieldsel.target = result;
- break;
- case P_SUBSCRIPT:
- thisOne->b.subscript.target = result;
- break;
- default:
- assert(FALSE);
- break;
- }
- result = thisOne;
- Sequence_Next
- Free(fD2);
- return(result);
- }
-
- /*
- * fD1 is a list of operators, fD2 is an expression. We want to build
- * P_INVOC rest opname null
- */
- NodePtr buildExpression1(fD1, fD2)
- NodePtr fD1, fD2;
- {
- NodePtr result, operator;
- if (fD1 == NULL) return (fD2);
- result = fD2;
- Sequence_ReverseFor(operator, fD1)
- if ((int) operator == KLOCATE || (int) operator == KISFIXED ||
- (int) operator == KAWAITING) {
- result = Construct(P_UNARYEXP, 2, operator, result);
- } else {
- result = Construct(P_INVOC, 3, result, makeOpName(operator), NULL);
- }
- Sequence_Next
- Free(fD1);
- return(result);
- }
-
- /*
- * Here there are a couple of cases. If the operation name is one of the
- * funny control flow ones KAND, KOR, OIDENTITY, ONOTIDENTITY, OCONFORMSTO
- * then we want to build a special node. Otherwise we treat it like in
- * buildExpression1.
- * Here fD1 is a sequence of expressions separated by operators.
- */
- NodePtr buildExpression2(fD1)
- NodePtr fD1;
- {
- register int i, maxIndex;
- register NodePtr result, operation, argument;
- Tag tag;
-
- assert(fD1->firstChild == 0);
- result = fD1->b.children[0];
- maxIndex = fD1->nChildren - 1;
- for (i = 1; i <= maxIndex ; i += 2) {
- operation = fD1->b.children[i];
- argument = fD1->b.children[i + 1];
- if ((int) operation == KAND || (int) operation == KOR ||
- (int) operation == OIDENTITY || (int) operation == ONOTIDENTITY ||
- (int) operation == OCONFORMSTO) {
- tag = P_EXP;
- } else {
- tag = P_INVOC;
- operation = makeOpName(operation);
- argument = Construct(T_SEQUENCE, 1, Construct(P_ARG, 1, argument));
- }
- result = Construct(tag, 3, result, operation, argument);
- }
- Free(fD1);
- return(result);
- }
-
- NodePtr Flatten(fSeq)
- NodePtr fSeq;
- {
- register NodePtr q, r, result;
- register int count = 0;
- assert(fSeq->tag == T_SEQUENCE);
- Sequence_For(q, fSeq)
- if (q->tag == T_SEQUENCE) {
- count += q->nChildren;
- } else {
- count ++;
- }
- Sequence_Next
- if (count == fSeq->nChildren) return(fSeq);
-
- result = F_NewNode(T_SEQUENCE, count);
- result->nChildren = count;
- count = 0;
- Sequence_For(q, fSeq)
- if ((int)q >= 0x200 && q->tag == T_SEQUENCE) {
- Sequence_For(r, q)
- result->b.children[count++] = r;
- Sequence_Next
- free((char *)q);
- } else {
- result->b.children[count++] = q;
- }
- Sequence_Next
- assert(count == result->nChildren);
- free((char *)fSeq);
- return(result);
- }
-
- NodePtr Distribute(fTag, fSeq, nArgs, firstArg)
- Tag fTag;
- NodePtr fSeq, firstArg;
- int nArgs;
- {
- register int i, j;
- register NodePtr *args = &firstArg;
-
- register NodePtr result, thisOne;
- assert(fSeq->tag == T_SEQUENCE);
- if (fSeq->nChildren == 1) {
- result = F_NewNode(fTag, nArgs+1);
- result->nChildren += nArgs+1;
- result->b.children[result->firstChild] = fSeq->b.children[0];
- result->lineNumber = fSeq->b.children[0]->lineNumber;
- for (j = 0; j < nArgs; j++)
- result->b.children[result->firstChild+j+1] = args[j];
- free((char *)fSeq);
- } else {
- result = F_NewNode(T_SEQUENCE, fSeq->nChildren);
- result->nChildren = fSeq->nChildren;
- for (i = 0; i < fSeq->nChildren; i++) {
- thisOne = F_NewNode(fTag, nArgs + 1);
- result->b.children[i] = thisOne;
- thisOne->nChildren += nArgs + 1;
- thisOne->b.children[thisOne->firstChild] = fSeq->b.children[i];
- thisOne->lineNumber = fSeq->b.children[i]->lineNumber;
- for (j = 0; j < nArgs; j++)
- thisOne->b.children[thisOne->firstChild+j+1] = args[j];
- }
- result->lineNumber = result->b.children[0]->lineNumber;
- free((char *)fSeq);
- }
- return(result);
- }
-
- NodePtr Copy(fNode)
- register NodePtr fNode;
- {
- register NodePtr result;
- register int i;
- if ((int) fNode <= 0x200) return(fNode);
- else {
- result = F_NewNode(fNode->tag, fNode->nChildren-fNode->firstChild);
- result->nChildren = fNode->nChildren;
- for (i = 0; i < fNode->firstChild; i++) {
- result->b.children[i] = fNode->b.children[i];
- }
- for (i = fNode->firstChild; i < fNode->nChildren; i++) {
- result->b.children[i] = Copy(fNode->b.children[i]);
- }
- return(result);
- }
- }
-
- NodePtr Copy1Node(fNode)
- register NodePtr fNode;
- {
- register NodePtr result;
- if ((int) fNode <= 0x200) return(fNode);
- else {
- result = F_NewNode(fNode->tag, fNode->nChildren-fNode->firstChild);
- bcopy((char *)fNode, (char *)result, NodeSize(fNode));
- return(result);
- }
- }
-
- NodePtr singleArg(n)
- NodePtr n;
- {
- return(Construct(T_SEQUENCE, 1, (Construct(P_ARG, 1, n))));
- }
-
- NodePtr buildString(s)
- char *s;
- {
- NodePtr r;
- r = Construct(P_STRINGLIT, 0);
- r->b.stringlit.string = malloc(strlen(s) + 1);
- strcpy(r->b.stringlit.string, s);
- return(r);
- }
-