if (!bittype.promotesTo(ot))
if (!ot.promotesTo(inttype))
    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 (!bittype.promotesTo(ot))                                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);                        if (ct == null)                        {                            report (expr,                                    "incompatible types in binary expression");                            return expr;                        }                        // TODO: check to see whether ct is an appropriate                        // type for the operator.                    }                    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 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 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);                }            });    }