Choose most compact representation when writing PUSH instructions

Can use some testing...
diff --git a/Lib/fontTools/ttLib/tables/ttProgram.py b/Lib/fontTools/ttLib/tables/ttProgram.py
index cc94ae9..ef71f0e 100644
--- a/Lib/fontTools/ttLib/tables/ttProgram.py
+++ b/Lib/fontTools/ttLib/tables/ttProgram.py
@@ -315,26 +315,66 @@
 					args.append(int(number))
 				nArgs = len(args)
 				if mnemonic == "PUSH":
-					if nArgs > 8:
-						mnemonic = "N" + mnemonic
-					if max(args) > 255 or min(args) < 0:
-						mnemonic += "W"
+					# Automatically choose the most compact representation
+					nWords = 0
+					while nArgs:
+						while nWords < nArgs and nWords < 255 and not (0 <= args[nWords] <= 255):
+							nWords += 1
+						nBytes = 0
+						while nWords+nBytes < nArgs and nBytes < 255 and 0 <= args[nWords+nBytes] <= 255:
+							nBytes += 1
+						if nBytes < 3 and nWords + nBytes < 255 and nWords + nBytes != nArgs:
+							# Will write bytes as words
+							nWords += nBytes
+							continue
+
+						# Write words
+						if nWords:
+							if nWords <= 8:
+								op, argBits = streamMnemonicDict["PUSHW"]
+								op = op + nWords - 1
+								push(op)
+							else:
+								op, argBits = streamMnemonicDict["NPUSHW"]
+								push(op)
+								push(nWords)
+							for value in args[:nWords]:
+								assert -32768 <= value < 32768, "PUSH value out of range %d" % value
+								push((value >> 8) & 0xff)
+								push(value & 0xff)
+
+						# Write bytes
+						if nBytes:
+							pass
+							if nBytes <= 8:
+								op, argBits = streamMnemonicDict["PUSHB"]
+								op = op + nBytes - 1
+								push(op)
+							else:
+								op, argBits = streamMnemonicDict["NPUSHB"]
+								push(op)
+								push(nBytes)
+							for value in args[nWords:nWords+nBytes]:
+								push(value)
+
+						nTotal = nWords + nBytes
+						args = args[nTotal:]
+						nArgs -= nTotal
+						nWords = 0
+				else:
+					# Write exactly what we've been asked to
+					words = mnemonic[-1] == "W"
+					op, argBits = streamMnemonicDict[mnemonic]
+					if mnemonic[0] != "N":
+						assert nArgs <= 8, nArgs
+						op = op + nArgs - 1
+						push(op)
 					else:
-						mnemonic += "B"
-
-				words = mnemonic[-1] == "W"
-				op, argBits = streamMnemonicDict[mnemonic]
-				if mnemonic[0] != "N":
-					assert nArgs <= 8, nArgs
-					op = op + nArgs - 1
-
-				while nArgs:
-					push(op)
-					num = min(nArgs, 255)
-					if mnemonic[0] == "N":
-						push(num)
+						assert nArgs < 256
+						push(op)
+						push(nArgs)
 					if words:
-						for value in args[:num]:
+						for value in args:
 							assert -32768 <= value < 32768, "PUSHW value out of range %d" % value
 							push((value >> 8) & 0xff)
 							push(value & 0xff)
@@ -342,8 +382,7 @@
 						for value in args:
 							assert 0 <= value < 256, "PUSHB value out of range %d" % value
 							push(value)
-					args = args[num:]
-					nArgs -= num
+
 			pos = _skipWhite(assembly, pos)
 		
 		if bytecode: