290 private LiteralNode<?> reduceOneLiteral() { 291 //TODO handle patterns like AND, OR, numeric ops that can be strength reduced but not replaced by a single literal node etc 292 return null; 293 } 294 295 private LiteralNode<?> reduceTwoLiterals() { 296 if (!(parent.lhs() instanceof LiteralNode && parent.rhs() instanceof LiteralNode)) { 297 return null; 298 } 299 300 final LiteralNode<?> lhs = (LiteralNode<?>)parent.lhs(); 301 final LiteralNode<?> rhs = (LiteralNode<?>)parent.rhs(); 302 303 if (lhs instanceof ArrayLiteralNode || rhs instanceof ArrayLiteralNode) { 304 return null; 305 } 306 307 final Type widest = Type.widest(lhs.getType(), rhs.getType()); 308 309 boolean isInteger = widest.isInteger(); 310 boolean isLong = widest.isLong(); 311 312 double value; 313 314 switch (parent.tokenType()) { 315 case DIV: 316 value = lhs.getNumber() / rhs.getNumber(); 317 break; 318 case ADD: 319 if ((lhs.isString() || rhs.isNumeric()) && (rhs.isString() || rhs.isNumeric())) { 320 final Object res = ScriptRuntime.ADD(lhs.getObject(), rhs.getObject()); 321 if (res instanceof Number) { 322 value = ((Number)res).doubleValue(); 323 break; 324 } 325 assert res instanceof CharSequence : res + " was not a CharSequence, it was a " + res.getClass(); 326 return LiteralNode.newInstance(token, finish, res.toString()); 327 } 328 return null; 329 case MUL: 330 value = lhs.getNumber() * rhs.getNumber(); 331 break; 332 case MOD: 333 value = lhs.getNumber() % rhs.getNumber(); 334 break; 335 case SUB: 336 value = lhs.getNumber() - rhs.getNumber(); 337 break; 338 case SHR: 339 return LiteralNode.newInstance(token, finish, JSType.toUint32(lhs.getInt32() >>> rhs.getInt32())); 340 case SAR: 341 return LiteralNode.newInstance(token, finish, lhs.getInt32() >> rhs.getInt32()); 342 case SHL: 343 return LiteralNode.newInstance(token, finish, lhs.getInt32() << rhs.getInt32()); 344 case BIT_XOR: 345 return LiteralNode.newInstance(token, finish, lhs.getInt32() ^ rhs.getInt32()); 346 case BIT_AND: 347 return LiteralNode.newInstance(token, finish, lhs.getInt32() & rhs.getInt32()); 348 case BIT_OR: 349 return LiteralNode.newInstance(token, finish, lhs.getInt32() | rhs.getInt32()); 350 case GE: 351 return LiteralNode.newInstance(token, finish, ScriptRuntime.GE(lhs.getObject(), rhs.getObject())); 352 case LE: 353 return LiteralNode.newInstance(token, finish, ScriptRuntime.LE(lhs.getObject(), rhs.getObject())); 354 case GT: 355 return LiteralNode.newInstance(token, finish, ScriptRuntime.GT(lhs.getObject(), rhs.getObject())); 356 case LT: 357 return LiteralNode.newInstance(token, finish, ScriptRuntime.LT(lhs.getObject(), rhs.getObject())); 358 case NE: 359 return LiteralNode.newInstance(token, finish, ScriptRuntime.NE(lhs.getObject(), rhs.getObject())); 360 case NE_STRICT: 361 return LiteralNode.newInstance(token, finish, ScriptRuntime.NE_STRICT(lhs.getObject(), rhs.getObject())); 362 case EQ: 363 return LiteralNode.newInstance(token, finish, ScriptRuntime.EQ(lhs.getObject(), rhs.getObject())); 364 case EQ_STRICT: 365 return LiteralNode.newInstance(token, finish, ScriptRuntime.EQ_STRICT(lhs.getObject(), rhs.getObject())); 366 default: 367 return null; 368 } 369 370 isInteger &= JSType.isStrictlyRepresentableAsInt(value); 371 isLong &= JSType.isStrictlyRepresentableAsLong(value); 372 373 if (isInteger) { 374 return LiteralNode.newInstance(token, finish, (int)value); 375 } else if (isLong) { 376 return LiteralNode.newInstance(token, finish, (long)value); 377 } 378 379 return LiteralNode.newInstance(token, finish, value); 380 } 381 } 382 } | 290 private LiteralNode<?> reduceOneLiteral() { 291 //TODO handle patterns like AND, OR, numeric ops that can be strength reduced but not replaced by a single literal node etc 292 return null; 293 } 294 295 private LiteralNode<?> reduceTwoLiterals() { 296 if (!(parent.lhs() instanceof LiteralNode && parent.rhs() instanceof LiteralNode)) { 297 return null; 298 } 299 300 final LiteralNode<?> lhs = (LiteralNode<?>)parent.lhs(); 301 final LiteralNode<?> rhs = (LiteralNode<?>)parent.rhs(); 302 303 if (lhs instanceof ArrayLiteralNode || rhs instanceof ArrayLiteralNode) { 304 return null; 305 } 306 307 final Type widest = Type.widest(lhs.getType(), rhs.getType()); 308 309 boolean isInteger = widest.isInteger(); 310 final double value; 311 312 switch (parent.tokenType()) { 313 case DIV: 314 value = lhs.getNumber() / rhs.getNumber(); 315 break; 316 case ADD: 317 if ((lhs.isString() || rhs.isNumeric()) && (rhs.isString() || rhs.isNumeric())) { 318 final Object res = ScriptRuntime.ADD(lhs.getObject(), rhs.getObject()); 319 if (res instanceof Number) { 320 value = ((Number)res).doubleValue(); 321 break; 322 } 323 assert res instanceof CharSequence : res + " was not a CharSequence, it was a " + res.getClass(); 324 return LiteralNode.newInstance(token, finish, res.toString()); 325 } 326 return null; 327 case MUL: 328 value = lhs.getNumber() * rhs.getNumber(); 329 break; 330 case MOD: 331 value = lhs.getNumber() % rhs.getNumber(); 332 break; 333 case SUB: 334 value = lhs.getNumber() - rhs.getNumber(); 335 break; 336 case SHR: 337 final long result = JSType.toUint32(lhs.getInt32() >>> rhs.getInt32()); 338 return LiteralNode.newInstance(token, finish, JSType.isRepresentableAsInt(result) ? (int) result : (double) result); 339 case SAR: 340 return LiteralNode.newInstance(token, finish, lhs.getInt32() >> rhs.getInt32()); 341 case SHL: 342 return LiteralNode.newInstance(token, finish, lhs.getInt32() << rhs.getInt32()); 343 case BIT_XOR: 344 return LiteralNode.newInstance(token, finish, lhs.getInt32() ^ rhs.getInt32()); 345 case BIT_AND: 346 return LiteralNode.newInstance(token, finish, lhs.getInt32() & rhs.getInt32()); 347 case BIT_OR: 348 return LiteralNode.newInstance(token, finish, lhs.getInt32() | rhs.getInt32()); 349 case GE: 350 return LiteralNode.newInstance(token, finish, ScriptRuntime.GE(lhs.getObject(), rhs.getObject())); 351 case LE: 352 return LiteralNode.newInstance(token, finish, ScriptRuntime.LE(lhs.getObject(), rhs.getObject())); 353 case GT: 354 return LiteralNode.newInstance(token, finish, ScriptRuntime.GT(lhs.getObject(), rhs.getObject())); 355 case LT: 356 return LiteralNode.newInstance(token, finish, ScriptRuntime.LT(lhs.getObject(), rhs.getObject())); 357 case NE: 358 return LiteralNode.newInstance(token, finish, ScriptRuntime.NE(lhs.getObject(), rhs.getObject())); 359 case NE_STRICT: 360 return LiteralNode.newInstance(token, finish, ScriptRuntime.NE_STRICT(lhs.getObject(), rhs.getObject())); 361 case EQ: 362 return LiteralNode.newInstance(token, finish, ScriptRuntime.EQ(lhs.getObject(), rhs.getObject())); 363 case EQ_STRICT: 364 return LiteralNode.newInstance(token, finish, ScriptRuntime.EQ_STRICT(lhs.getObject(), rhs.getObject())); 365 default: 366 return null; 367 } 368 369 isInteger &= JSType.isStrictlyRepresentableAsInt(value); 370 371 if (isInteger) { 372 return LiteralNode.newInstance(token, finish, (int)value); 373 } 374 375 return LiteralNode.newInstance(token, finish, value); 376 } 377 } 378 } |