home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************************
- *
- * Semantic Tree manipulation module.
- *
- ***********************************************************************/
-
- /***********************************************************************
- *
- * Copyright (C) 1990, 1991 Free Software Foundation, Inc.
- * Written by Steve Byrne.
- *
- * This file is part of GNU Smalltalk.
- *
- * GNU Smalltalk is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 1, or (at your option) any later
- * version.
- *
- * GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * GNU Smalltalk; see the file COPYING. If not, write to the Free Software
- * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ***********************************************************************/
-
-
- /*
- * Change Log
- * ============================================================================
- * Author Date Change
- * sbyrne 30 Dec 88 Created.
- *
- */
-
-
- #include "mst.h"
- #include "mstsym.h"
- #include "msttree.h"
- #include <stdio.h>
-
- char *nilName = "(nil)"; /* how to print nil */
-
- Boolean hadError = false;
-
- static TreeNode makeMethodNode(), makeListNode(), makeExprNode();
- static TreeNode makeTreeNode();
- static OOP makeUnarySelector(), makeBinarySelector();
- static void freeNode(), freeMethodNode(), freeExprNode(), freeListNode(),
- freeConstNode();
- static void printMethodNode(), printExprNode(), printListNode(),
- printConstNode(), printNodeType(), indent(), printSelector();
-
- static OOP *binopSymbols[] = { /* indexed by binop */
- &nilSymbol, /* there is no zeroth entry */
- &plusSymbol,
- &minusSymbol,
- ×Symbol,
- ÷Symbol,
- &lessThanSymbol,
- &greaterThanSymbol,
- &equalSymbol,
- ¬EqualSymbol,
- &lessEqualSymbol,
- &greaterEqualSymbol,
- &integerDivideSymbol,
- &remainderSymbol,
- &sameObjectSymbol,
- ¬SameObjectSymbol,
- &orSymbol,
- &andSymbol
- };
-
- /* Used only for printing tree node names when debugging */
- static char *nodeTypeNames[] = {
- "methodNodeType", /* methodNodeType */
- "unaryExprType", /* unaryExprType */
- "binaryExprType", /* binaryExprType */
- "keywordExprType", /* keywordExprType */
- "variableNodeType", /* variableNodeType */
- "keywordListType", /* keywordListType */
- "variableListType", /* variableListType */
- "statementListType", /* statementListType */
- "returnExprType", /* returnExprType */
- "assignExprType", /* assignExprType */
- "constExprType", /* constExprType */
- "symbolNodeType", /* symbolNodeType */
- "arrayEltListType", /* arrayEltListType */
- "blockNodeType", /* blockNodeType */
- "cascadedMessageNodeType", /* cascadedMessageNodeType */
- "messageListType" /* messageListType */
- };
-
-
-
- /*
- * TreeNode makeArrayElt(elt)
- *
- * Description
- *
- * Create an element of an array constant, which is a list type object.
- * Return the element with the next field NILed out.
- *
- * Inputs
- *
- * elt : TreeNode array element to use
- *
- * Outputs
- *
- * TreeNode of type arrayEltListType that contains "elt".
- */
- TreeNode makeArrayElt(elt)
- TreeNode elt;
- {
- return (makeListNode(arrayEltListType, nil, elt));
- }
-
-
- /*
- * TreeNode makeMethod(selectorExpr, temporaries, primitiveIndex,
- * statements)
- *
- * Description
- *
- * Create a method node. The method will be invoked by a selector dervied
- * from "selectorExpr", it has (possibly nil) "temporaries" variables,
- * and contains "statements". If the method has a primitive associated
- * with it, then "primitiveIndex" is non-zero.
- *
- * Inputs
- *
- * selectorExpr:
- * Expression that's to be the selector for this method.
- * temporaries:
- * Possibly nil list of temporary variable names.
- * primitiveIndex:
- * Integer. If non-zero, this method has associated with it
- * a primitive with index "primitiveIndex".
- * statements:
- * List of statements that comprise the procedural part of this
- * method.
- *
- * Outputs
- *
- * TreeNode of type methodNodeType.
- */
- TreeNode makeMethod(selectorExpr, temporaries, primitiveIndex, statements)
- TreeNode selectorExpr, temporaries, statements;
- int primitiveIndex;
- {
- return (makeMethodNode(methodNodeType, selectorExpr,
- temporaries, primitiveIndex, statements));
- }
-
-
- /*
- * TreeNode makeCascadedMessage(messageExpr, cascadedMessages)
- *
- * Description
- *
- * Creates a node for holding a list of cascaded messages (basically an
- * Expr node that isn't using its symbol. "messageExpr" is the expression
- * invoke first as it computes the receiver. Then the remaining cascaded
- * messages are sent to that receiver.
- *
- * Inputs
- *
- * messageExpr:
- * Evaluates to the receiver of the cascaded messages
- * cascadedMessages:
- * List of the cascaded messages to send to the receiver.
- *
- * Outputs
- *
- * TreeNode of type cascadedMessageTypeNode.
- */
- TreeNode makeCascadedMessage(messageExpr, cascadedMessages)
- TreeNode messageExpr, cascadedMessages;
- {
- return (makeExprNode(cascadedMessageNodeType, messageExpr, nil,
- cascadedMessages));
- }
-
-
- TreeNode makeUnaryExpr(receiver, unarySelectorExpr)
- TreeNode receiver;
- char *unarySelectorExpr;
- {
- OOP selector;
-
- selector = makeUnarySelector(unarySelectorExpr);
- return (makeExprNode(unaryExprType, receiver, selector, nil));
- }
-
- TreeNode internBinOP(binaryOp)
- char *binaryOp;
- {
- return (makeExprNode(symbolNodeType, nil, makeBinarySelector(binaryOp),
- nil));
- }
-
- TreeNode internIdent(ident)
- char *ident;
- {
- return (makeExprNode(symbolNodeType, nil, internString(ident), nil));
- }
-
- TreeNode makeStatementList(expression, statements)
- TreeNode expression, statements;
- {
- return (makeExprNode(statementListType, expression, nilOOP, statements));
- }
-
- TreeNode makeReturn(expression)
- TreeNode expression;
- {
- return (makeExprNode(returnExprType, expression, nilOOP, nil));
- }
-
- TreeNode makeKeywordExpr(receiver, keywordMessage)
- TreeNode receiver, keywordMessage;
- {
- return (makeExprNode(keywordExprType, receiver, nilOOP, keywordMessage));
- }
-
- TreeNode makeAssign(variables, expression)
- TreeNode variables, expression;
- {
- return (makeExprNode(assignExprType, variables, nilOOP, expression));
- }
-
- TreeNode makeKeywordList(keyword, expression)
- char *keyword;
- TreeNode expression;
- {
- return (makeListNode(keywordListType, keyword, expression));
- }
-
- /*
- * TreeNode makeVariableList(variable)
- *
- * Description
- *
- * Given a variable tree node, this routine returns a variable list tree
- * node with a nil next link. Actually, we rely on the fact that a
- * variable is represented as a tree node of type ListNode, so all we do
- * is change the node tag to variableListType.
- *
- * Inputs
- *
- * variable:
- * Name of variable that's to be part of the list, TreeNode.
- *
- * Outputs
- *
- * New TreeNode.
- */
- TreeNode makeVariableList(variable)
- TreeNode variable;
- {
- variable->nodeType = variableListType;
- return (variable);
- }
-
-
- TreeNode makeBinaryExpr(receiver, binaryOp, argument)
- TreeNode receiver, argument;
- char *binaryOp;
- {
- OOP selector;
-
- selector = makeBinarySelector(binaryOp);
- return (makeExprNode(binaryExprType, receiver, selector, argument));
- }
-
- TreeNode makeMessageList(messageElt)
- TreeNode messageElt;
- {
- return (makeListNode(messageListType, nil, messageElt));
- }
-
- /*
- * TreeNode makeBlock(temporaries, statements)
- *
- * Description
- *
- * Creates a block tree node and returns it.
- *
- * Inputs
- *
- * temporaries:
- * Possibly nil list of temporary variable names to use for this
- * block
- * statements:
- * List of statements that are the procedure part of this block.
- *
- * Outputs
- *
- * New tree node.
- */
- TreeNode makeBlock(temporaries, statements)
- TreeNode temporaries, statements;
- {
- return (makeMethodNode(blockNodeType, nil, temporaries, 0, statements));
- }
-
- TreeNode makeVariable(name)
- char *name;
- {
- return (makeListNode(variableNodeType, name, nil));
- }
-
-
- TreeNode makeIntConstant(ival)
- long ival;
- {
- TreeNode result;
-
- result = makeTreeNode(constExprType);
- result->vConst.constType = intConst;
- result->vConst.val.iVal = ival;
-
- return (result);
- }
-
- TreeNode makeFloatConstant(fval)
- double fval;
- {
- TreeNode result;
-
- result = makeTreeNode(constExprType);
- result->vConst.constType = floatConst;
- result->vConst.val.fVal = fval;
-
- return (result);
- }
-
- TreeNode makeCharConstant(cval)
- char cval;
- {
- TreeNode result;
-
- result = makeTreeNode(constExprType);
- result->vConst.constType = charConst;
- result->vConst.val.cVal = cval;
-
- return (result);
- }
-
- TreeNode makeStringConstant(sval)
- char *sval;
- {
- TreeNode result;
-
- result = makeTreeNode(constExprType);
- result->vConst.constType = stringConst;
- result->vConst.val.sVal = sval;
-
- return (result);
- }
-
- TreeNode makeSymbolConstant(symbolNode)
- TreeNode symbolNode;
- {
- TreeNode result;
-
- result = makeTreeNode(constExprType);
- result->vConst.constType = symbolConst;
- if (symbolNode) {
- result->vConst.val.symVal = symbolNode->vExpr.selector;
- freeNode(symbolNode);
- } else {
- result->vConst.val.symVal = nilOOP;
- }
-
- return (result);
- }
-
- TreeNode makeArrayConstant(aval)
- TreeNode aval;
- {
- TreeNode result;
-
- result = makeTreeNode(constExprType);
- result->vConst.constType = arrayConst;
- result->vConst.val.aVal = aval;
-
- return (result);
- }
-
-
- /*
- * void addNode(n1, n2)
- *
- * Description
- *
- * adds node "n2" onto a list of nodes headed by "n1". "n1" contains
- * the address of the last "next" field in the chain, so storing "n2" into
- * there indirectly and then making that "next" field point to "n2"'s
- * "next" field works properly.
- *
- * Inputs
- *
- * n1 : head of list of nodes, of type listNode.
- * n2 : node to be added, of type listNode.
- *
- */
- void addNode(n1, n2)
- TreeNode n1, n2;
- {
- *(n1->vList.nextAddr) = n2;
- n1->vList.nextAddr = n2->vList.nextAddr; /* since they're all created this
- * way anyway, we might as well
- * use it to our advantage */
- }
-
- void freeTree(tree)
- TreeNode tree;
- {
- if (tree == nil) {
- return;
- }
-
- switch (tree->nodeType) {
- case methodNodeType:
- case blockNodeType:
- freeMethodNode(tree);
- break;
-
- case symbolNodeType:
- case unaryExprType:
- case binaryExprType:
- case keywordExprType:
- case cascadedMessageNodeType:
- case statementListType:
- case returnExprType:
- case assignExprType:
- freeExprNode(tree);
- break;
-
- case variableNodeType:
- case keywordListType:
- case variableListType:
- case arrayEltListType:
- case messageListType:
- freeListNode(tree);
- break;
-
- case constExprType:
- freeConstNode(tree);
- break;
-
- }
- }
-
-
-
- /***********************************************************************
- *
- * Internal tree construction routines.
- *
- ***********************************************************************/
-
-
- static TreeNode makeMethodNode(nodeType, selectorExpr, temporaries,
- primitiveIndex, statements)
- NodeType nodeType;
- TreeNode selectorExpr, temporaries, statements;
- int primitiveIndex;
- {
- TreeNode result;
-
- result = makeTreeNode(nodeType);
- result->vMethod.selectorExpr = selectorExpr;
- result->vMethod.temporaries = temporaries;
- result->vMethod.primitiveIndex = primitiveIndex;
- result->vMethod.statements = statements;
- return (result);
- }
-
- static TreeNode makeListNode(nodeType, name, value)
- NodeType nodeType;
- char *name;
- TreeNode value;
- {
- TreeNode result;
-
- result = makeTreeNode(nodeType);
- result->vList.name = name;
- result->vList.value = value;
- result->vList.next = nil;
- result->vList.nextAddr = &result->vList.next;
- return (result);
- }
-
- static TreeNode makeExprNode(nodeType, receiver, selector, expression)
- NodeType nodeType;
- TreeNode receiver, expression;
- OOP selector;
- {
- TreeNode result;
-
- result = makeTreeNode(nodeType);
- result->vExpr.receiver = receiver;
- result->vExpr.selector = selector;
- result->vExpr.expression = expression;
- return (result);
- }
-
- static TreeNode makeTreeNode(nodeType)
- NodeType nodeType;
- {
- TreeNode result;
-
- result = (TreeNode)malloc(sizeof(struct TreeNodeStruct));
- result->nodeType = nodeType;
- return (result);
- }
-
- /* ### these should probably be moved over into the symbol table module, yes?*/
-
- static OOP makeUnarySelector(name)
- char *name;
- {
- return (internString(name));
- }
-
- static OOP makeBinarySelector(binaryOp)
- char *binaryOp;
- {
- return (internString(binaryOp));
- }
-
- /***********************************************************************
- *
- * Internal tree destruction routines.
- *
- ***********************************************************************/
-
- static void freeMethodNode(node)
- TreeNode node;
- {
- freeTree(node->vMethod.selectorExpr);
- freeTree(node->vMethod.temporaries);
- freeTree(node->vMethod.statements);
- freeNode(node);
- }
-
- static void freeExprNode(node)
- TreeNode node;
- {
- freeTree(node->vExpr.receiver);
- freeTree(node->vExpr.expression);
- freeNode(node);
- }
-
- static void freeListNode(node)
- TreeNode node;
- {
- freeTree(node->vList.value);
- freeTree(node->vList.next);
- if (node->vList.name) {
- free(node->vList.name);
- }
-
- freeNode(node);
- }
-
- static void freeConstNode(node)
- TreeNode node;
- {
- switch (node->vConst.constType) {
- case intConst:
- case floatConst:
- case charConst:
- case symbolConst:
- /* these have no storage of their own */
- break;
-
- case stringConst:
- if (node->vConst.val.sVal) {
- free(node->vConst.val.sVal);
- } else {
- errorf("Internal error: badly formed tree for string constant");
- }
- break;
-
- case arrayConst:
- freeTree(node->vConst.val.aVal);
- break;
-
- default:
- errorf("Internal error: corrupted tree structure");
- }
-
- freeNode(node);
- }
-
-
- static void freeNode(node)
- TreeNode node;
- {
- free(node);
- }
-
-
- /***********************************************************************
- *
- * Printing routines.
- *
- ***********************************************************************/
-
-
- void printTree(node, level)
- TreeNode node;
- int level;
- {
- if (node == nil) {
- indent(level);
- printf("%s\n", nilName);
- return;
- }
-
- switch (node->nodeType) {
- case methodNodeType:
- case blockNodeType:
- printMethodNode(node, level);
- break;
-
- case symbolNodeType:
- case unaryExprType:
- case binaryExprType:
- case keywordExprType:
- case cascadedMessageNodeType:
- case statementListType:
- case returnExprType:
- case assignExprType:
- printExprNode(node, level);
- break;
-
- case variableNodeType:
- case keywordListType:
- case variableListType:
- case arrayEltListType:
- case messageListType:
- printListNode(node, level);
- break;
-
- case constExprType:
- printConstNode(node, level);
- break;
-
- default:
- errorf("Unknown tree note type %d\n", node->nodeType);
- }
- }
-
-
- static void printListNode(node, level)
- TreeNode node;
- int level;
- {
- printNodeType(node, level);
- indent(level+1);
- printf("name: %s\n", node->vList.name ? node->vList.name : nilName);
- indent(level+1);
- printf("value:\n");
- printTree(node->vList.value, level+2);
- indent(level+1);
- printf("next:\n");
- printTree(node->vList.next, level);
- }
-
- static void printExprNode(node, level)
- TreeNode node;
- int level;
- {
- printNodeType(node, level);
- indent(level+1);
- printf("selector: ");
- if (!isNil(node->vExpr.selector)) {
- printSelector(node->vExpr.selector);
- } else {
- printf("%s", nilName);
- }
- printf("\n");
-
- indent(level+1);
- printf("receiver:\n");
- printTree(node->vExpr.receiver, level+2);
- /* ??? don't print the expression for unary type things, and don't print
- the receiver for symbol nodes */
- indent(level+1);
- printf("expression:\n");
- printTree(node->vExpr.expression, level+2);
- }
-
- static void printMethodNode(node, level)
- TreeNode node;
- int level;
- {
- printNodeType(node, level);
- indent(level+1);
- printf("selectorExpr: ");
- printTree(node->vMethod.selectorExpr, level+2);
- indent(level+1);
- /* ??? don't print the temporaries label if there are no temporaries */
- printf("temporaries:\n");
- printTree(node->vMethod.temporaries, level+2);
- indent(level+1);
- printf("statements:\n");
- printTree(node->vMethod.statements, level+2);
- }
-
- static void printConstNode(node, level)
- TreeNode node;
- int level;
- {
- indent(level);
- switch (node->vConst.constType) {
- case intConst:
- printf("int: %ld\n", node->vConst.val.iVal);
- break;
-
- case floatConst:
- printf("float: %g\n", node->vConst.val.fVal);
- break;
-
- case charConst:
- printf("char: %c\n", node->vConst.val.cVal);
- break;
-
- case stringConst:
- printf("string: \"%s\"\n", node->vConst.val.sVal);
- break;
-
- case symbolConst:
- printf("symbol: ");
- printSymbol(node->vConst.val.symVal);
- printf("\n");
- break;
-
- case arrayConst:
- printf("array:\n");
- printTree(node->vConst.val.aVal, level+1);
- break;
-
- default:
- errorf("Unknown constant type %d", node->vConst.constType);
- }
- }
-
-
- static void printNodeType(node, level)
- TreeNode node;
- int level;
- {
- indent(level);
- printf("%s\n", nodeTypeNames[ENUM_INT(node->nodeType)]);
- }
-
- /*
- * static void indent(level)
- *
- * Description
- *
- * Indent the output by level*2 spaces.
- *
- * Inputs
- *
- * level : Indentation level. C integer.
- *
- */
- static void indent(level)
- int level;
- {
- for (; level > 0; level--) {
- printf(" ");
- }
- }
-
- static void printSelector(selector)
- OOP selector;
- {
- printSymbol(selector);
- }
-
-