if (!ot.promotesTo(inttype))
if (!ot.promotesTo(bittype))
    public void checkBasicTyping(Program prog)    {        /* We mostly just need to walk through and check things.         * enqueue statements can be hard, though: if there's a         * feedback loop with void type, we need to find the         * loopback type, which is the output type of the loop         * stream object.  If it's kosher to have enqueue before         * loop, we need an extra pass over statements to find         * the loop type.  The AssignLoopTypes pass could be         * helpful here, but we want to give an error message if         * things fail. */        prog.accept(new SymbolTableVisitor(null) {                // Need to visit everything.  Handily, STV does things                // for us like save streamType when we run across                // streamspecs; the only potentially hard thing is                // the loop type of feedback loops.                //                // Otherwise, assume that the GetExprType pass can                // find the types of things.  This should report                // an error exactly when GET returns null,                // so we can ignore nulls (assume that they type                // check).                public Object visitExprUnary(ExprUnary expr)                {                    Type ot = getType(expr.getExpr());                    if (ot != null)                    {                        Type inttype =                            new TypePrimitive(TypePrimitive.TYPE_INT);                        Type bittype =                            new TypePrimitive(TypePrimitive.TYPE_BIT);                                            switch(expr.getOp())                        {                        case ExprUnary.UNOP_NEG:                            if (!inttype.promotesTo(ot))                                report(expr, "cannot negate " + ot);                            break;                                                    case ExprUnary.UNOP_NOT:                            if (!ot.promotesTo(inttype))                                report(expr, "cannot take boolean not of " +                                       ot);                            break;                                                    case ExprUnary.UNOP_PREDEC:                        case ExprUnary.UNOP_PREINC:                        case ExprUnary.UNOP_POSTDEC:                        case ExprUnary.UNOP_POSTINC:                            if (!inttype.promotesTo(ot))                                report(expr, "cannot perform ++/-- on " + ot);                            break;                        }                    }                                        return super.visitExprUnary(expr);                }                public Object visitExprBinary(ExprBinary expr)                {                    Type lt = getType(expr.getLeft());                    Type rt = getType(expr.getRight());                    if (lt != null && rt != null)                    {                                                Type ct = lt.leastCommonPromotion(rt);                        Type inttype =                            new TypePrimitive(TypePrimitive.TYPE_INT);                        Type bittype =                            new TypePrimitive(TypePrimitive.TYPE_BIT);                        Type cplxtype =                            new TypePrimitive(TypePrimitive.TYPE_COMPLEX);                        Type floattype =                            new TypePrimitive(TypePrimitive.TYPE_FLOAT);                        if (ct == null)                        {                            report (expr,                                    "incompatible types in binary expression");                            return expr;                        }                        // Check whether ct is an appropriate type.                        switch (expr.getOp())                        {                        // Arithmetic operations:                        case ExprBinary.BINOP_ADD:                        case ExprBinary.BINOP_DIV:                        case ExprBinary.BINOP_MUL:                        case ExprBinary.BINOP_SUB:                            if (!ct.promotesTo(cplxtype))                                report(expr,                                       "cannot perform arithmetic on " + ct);                            break;                        // Bitwise and integer operations:                        case ExprBinary.BINOP_BAND:                        case ExprBinary.BINOP_BOR:                        case ExprBinary.BINOP_BXOR:                            if (!ct.promotesTo(inttype))                                report(expr,                                       "cannot perform bitwise operations on "                                       + ct);                            break;                        case ExprBinary.BINOP_MOD:                            if (!ct.promotesTo(inttype))                                report(expr, "cannot perform % on " + ct);                            break;                                                    // Boolean operations:                        case ExprBinary.BINOP_AND:                        case ExprBinary.BINOP_OR:                            if (!ct.promotesTo(bittype))                                report(expr,                                       "cannot perform boolean operations on "                                       + ct);                            break;                        // Comparison operations:                        case ExprBinary.BINOP_GE:                        case ExprBinary.BINOP_GT:                        case ExprBinary.BINOP_LE:                        case ExprBinary.BINOP_LT:                            if (!ct.promotesTo(floattype))                                report(expr,                                       "cannot compare non-real type " + ct);                            break;                                                // Equality, can compare anything:                        case ExprBinary.BINOP_EQ:                        case ExprBinary.BINOP_NEQ:                            break;                                                // And now we should have covered everything.                        default:                            report(expr,                                   "semantic checker missed a binop type");                            break;                        }                        return expr;                    }                    return super.visitExprBinary(expr);                }                public Object visitExprTernary(ExprTernary expr)                {                    Type at = getType(expr.getA());                    Type bt = getType(expr.getB());                    Type ct = getType(expr.getC());                                        if (at != null)                    {                        if (!at.promotesTo                            (new TypePrimitive(TypePrimitive.TYPE_INT)))                            report(expr,                                   "first part of ternary expression "+                                   "must be int");                    }                    if (bt != null && ct != null)                    {                                                Type xt = bt.leastCommonPromotion(ct);                        if (xt == null)                            report(expr,                                   "incompatible second and third types "+                                   "in ternary expression");                    }                                        return super.visitExprTernary(expr);                }                public Object visitExprField(ExprField expr)                {                    Type lt = getType(expr.getLeft());                    // Either lt is complex, or it's a structure                    // type, or it's null, or it's an error.                    if (lt == null)                    {                        // pass                    }                    else if (lt.isComplex())                    {                        String rn = expr.getName();                        if (!rn.equals("real") &&                            !rn.equals("imag"))                            report(expr,                                   "complex variables have only "+                                   "'real' and 'imag' fields");                    }                    else if (lt instanceof TypeStruct)                    {                        TypeStruct ts = (TypeStruct)lt;                        String rn = expr.getName();                        boolean found = false;                        for (int i = 0; i < ts.getNumFields(); i++)                            if (ts.getField(i).equals(rn))                            {                                found = true;                                break;                            }                                                if (!found)                            report(expr,                                   "structure does not have a field named "+                                   "'" + rn + "'");                    }                    else                    {                        report(expr,                               "field reference of a non-structure type");                    }                    return super.visitExprField(expr);                }                public Object visitExprArray(ExprArray expr)                {                    Type bt = getType(expr.getBase());                    Type ot = getType(expr.getOffset());                                        if (bt != null)                    {                        if (!(bt instanceof TypeArray))                            report(expr, "array access with a non-array base");                    }                    if (ot != null)                    {                        if (!ot.promotesTo                            (new TypePrimitive(TypePrimitive.TYPE_INT)))                            report(expr, "array index must be an int");                    }                                        return super.visitExprArray(expr);                }                public Object visitExprArrayInit(ExprArrayInit expr)                {		    // check for uniform length and dimensions among all children.		    List elems = expr.getElements();		    		    // only worry about it if we have elements		    if (elems.size()>0) {			Expression first = (Expression)elems.get(0);			// if one is an array, they should all be			// arrays of the same length and dimensions			if (first instanceof ExprArrayInit) {			    ExprArrayInit firstArr = (ExprArrayInit)first;			    for (int i=1; i<elems.size(); i++) {				ExprArrayInit other = (ExprArrayInit)elems.get(i);				if (firstArr.getDims() != other.getDims()) {				    report(expr, 					   "non-uniform number of array " +					   "dimensions in array initializer");				}				if (firstArr.getElements().size() != other.getElements().size()) {				    report(expr, 					   "two rows of a multi-dimensional " +  					   "array are initialized to different " + 					   "lengths (arrays must be rectangular)");				}			    }			} else {			    // if first element is not array, no other			    // element should be an array			    for (int i=1; i<elems.size(); i++) {				if (elems.get(i) instanceof ExprArrayInit) {				    report(expr, 					   "non-uniform number of array " +					   "dimensions in array initializer");				}			    }			}		    }		                        return super.visitExprArrayInit(expr);                }                public Object visitExprPeek(ExprPeek expr)                {                    Type it = getType(expr.getExpr());                                        if (it != null)                    {                        if (!it.promotesTo                            (new TypePrimitive(TypePrimitive.TYPE_INT)))                            report(expr, "peek index must be an int");                    }                                        return super.visitExprPeek(expr);                                    }		public Object visitFieldDecl(FieldDecl field) {		    // check that array sizes match		    for (int i=0; i<field.getNumFields(); i++) {			Type type = field.getType(i);			Expression init = field.getInit(i);			if (type instanceof TypeArray && init!=null) {			    // check that initializer is array initializer			    // (I guess it could also be conditional expression?  Don't bother.)			    if (!(init instanceof ExprArrayInit)) {				report (field, "array initialized to non-array type");			    } else {				// check that lengths match				Expression lengthExpr = ((TypeArray)type).getLength();				// only check it if we have resolved it				if (lengthExpr instanceof ExprConstInt) {				    int length = ((ExprConstInt)lengthExpr).getVal();				    if (length != ((ExprArrayInit)init).getElements().size()) {					report(field, 					       "declared array length does not match " +					       "array initializer");				    }				}			    }			}		    }		    return super.visitFieldDecl(field);		}                public Object visitStmtPush(StmtPush stmt)                {                    Type xt = getType(stmt.getValue());                                        if (xt != null && streamType != null &&                        streamType.getOut() != null &&                        !(xt.promotesTo(streamType.getOut())))                        report(stmt, "push expression must be of "+                               "output type of filter");                                        return super.visitStmtPush(stmt);                }                public Object visitStmtEnqueue(StmtEnqueue stmt)                {                    Type xt = getType(stmt.getValue());                                        // Punt if, in addition to the normal cases,                    // the input type is void.  (We'd have to                    // determine the loopback type now.)                    if (xt != null && streamType != null)                    {                        Type in = streamType.getIn();                        if (!((in instanceof TypePrimitive) &&                              ((TypePrimitive)in).getType() ==                              TypePrimitive.TYPE_VOID) &&                            !(xt.promotesTo(in)))                        report(stmt, "enqueue expression must be of "+                               "input type of feedback loop");                    }                                        return super.visitStmtEnqueue(stmt);                }                public Object visitStmtAssign(StmtAssign stmt)                {                    Type lt = getType(stmt.getLHS());                    Type rt = getType(stmt.getRHS());                                        if (lt != null && rt != null &&                        !(rt.promotesTo(lt)))                        report(stmt,                               "right-hand side of assignment must "+                               "be promotable to left-hand side's type");                                        return super.visitStmtAssign(stmt);                }            });    }