System.out.println("type check assign");
  public Node typeCheck(TypeChecker tc) throws SemanticException {    Type t = left.type();    Type s = right.type();    TypeSystem ts = tc.typeSystem();    if (! (left instanceof Variable)) {        throw new SemanticException("Target of assignment must be a variable.",                                    position());    }    if (op == ASSIGN) {      if (! ts.isImplicitCastValid(s, t) &&          ! ts.equals(s, t) &&          ! ts.numericConversionValid(t, right.constantValue())) {        throw new SemanticException("Cannot assign " + s + " to " + t + ".",                                    position());      }      return type(t);    }    if (op == ADD_ASSIGN) {      // t += s      if (ts.equals(t, ts.String()) && ts.canCoerceToString(s, tc.context())) {        return type(ts.String());      }      if (t.isNumeric() && s.isNumeric()) {        return type(ts.promote(t, s));      }      throw new SemanticException("The " + op + " operator must have "                                  + "numeric or String operands.",                                  position());    }    if (op == SUB_ASSIGN || op == MUL_ASSIGN ||        op == DIV_ASSIGN || op == MOD_ASSIGN) {      if (t.isNumeric() && s.isNumeric()) {        return type(ts.promote(t, s));      }      throw new SemanticException("The " + op + " operator must have "                                  + "numeric operands.",                                  position());    }    if (op == BIT_AND_ASSIGN || op == BIT_OR_ASSIGN || op == BIT_XOR_ASSIGN) {      if (t.isBoolean() && s.isBoolean()) {        return type(ts.Boolean());      }      if (ts.isImplicitCastValid(t, ts.Long()) &&          ts.isImplicitCastValid(s, ts.Long())) {        return type(ts.promote(t, s));      }      throw new SemanticException("The " + op + " operator must have "                                  + "integral or boolean operands.",                                  position());    }    if (op == SHL_ASSIGN || op == SHR_ASSIGN || op == USHR_ASSIGN) {      if (ts.isImplicitCastValid(t, ts.Long()) &&          ts.isImplicitCastValid(s, ts.Long())) {        // Only promote the left of a shift.        return type(ts.promote(t));      }      throw new SemanticException("The " + op + " operator must have "                                  + "integral operands.",                                  position());    }    throw new InternalCompilerError("Unrecognized assignment operator " +                                    op + ".");  }