/** * This routine is called to determine if the right type is assignment compatible with the * left-hand side. When this is called, we already know that there is a non-undefined type on the * left-hand side. Now we need to make sure that the right-hand side is compatible with it, as * described in the semantics notes in the Dijkstra specification. * * @param left * @param right */ void checkAssignCompatible(LatteAST left, LatteAST right) { boolean assignOK = false; LatteType leftType = left.getNodeType(); LatteType rightType = right.getNodeType(); switch (leftType) { case tINT: case tFLOAT: case tNUM: assignOK = rightType == tINT || rightType == tFLOAT || rightType == tNUM; break; case tBOOLEAN: assignOK = rightType == tBOOLEAN; break; case tCHAR: assignOK = rightType == tCHAR; break; } if (!assignOK) { throw new LatteException( "Incompatible assignment types: (" + leftType + "," + rightType + ")"); } }
/** * Set the node's type and also update the binding, if there is one (if the new type is not * undefined). * * @param node the AST node * @param type the type to assign to the node and binding */ void setNodeTypeAndMaybeBinding(LatteAST node, LatteType type) { node.setNodeType(type); if (type != tUNDEFINED && node.getBinding() != null) { node.getBinding().setType(type); } }
/** * This is an imperitive command to set the node type and its binding to the specified type. * Calling this method means that the caller assumes the responsibility for ensuring that there is * a binding corresponding to the node and that the type there is appropriate. This is used mainly * for declarations where there is no doubt about the types. * * @param node the AST node * @param type the type to assign to the node and binding */ void setNodeTypeAndBinding(LatteAST node, LatteType type) { node.setNodeType(type); node.getBinding().setType(type); }