| // Copyright 2017 the V8 project authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | // Test that n-ary chains of binary ops give an equal result to individual | 
 | // binary op calls. Also test binop chains inside an if condition return | 
 | // the same branch. | 
 |  | 
 | // Generate a function of the form | 
 | // | 
 | // function(init,a0,...,aN) { | 
 | //   return init + a0 + ... + aN; | 
 | // } | 
 | // | 
 | // where + can be any binary operation. | 
 | function generate_chained_op(op, num_ops) { | 
 |     let str = "(function(init"; | 
 |     for (let i = 0; i < num_ops; i++) { | 
 |         str += ",a"+i; | 
 |     } | 
 |     str += "){return (init"; | 
 |     for (let i = 0; i < num_ops; i++) { | 
 |         str += op+"a"+i; | 
 |     } | 
 |     str += ");})"; | 
 |     return eval(str); | 
 | } | 
 |  | 
 | // Generate a function of the form | 
 | // | 
 | // function(init,a0,...,aN) { | 
 | //   var tmp = init; | 
 | //   tmp = tmp + a0; | 
 | //   ... | 
 | //   tmp = tmp + aN; | 
 | //   return tmp; | 
 | // } | 
 | // | 
 | // where + can be any binary operation. | 
 | function generate_nonchained_op(op, num_ops) { | 
 |     let str = "(function(init"; | 
 |     for (let i = 0; i < num_ops; i++) { | 
 |         str += ",a"+i; | 
 |     } | 
 |     str += "){ var tmp=init; "; | 
 |     for (let i = 0; i < num_ops; i++) { | 
 |         str += "tmp=(tmp"+op+"a"+i+");"; | 
 |     } | 
 |     str += "return tmp;})"; | 
 |     return eval(str); | 
 | } | 
 |  | 
 | // Generate a function of the form | 
 | // | 
 | // function(init,a0,...,aN) { | 
 | //   if(init + a0 + ... + aN) return 1; | 
 | //   else return 0; | 
 | // } | 
 | // | 
 | // where + can be any binary operation. | 
 | function generate_chained_op_test(op, num_ops) { | 
 |     let str = "(function(init"; | 
 |     for (let i = 0; i < num_ops; i++) { | 
 |         str += ",a"+i; | 
 |     } | 
 |     str += "){ if(init"; | 
 |     for (let i = 0; i < num_ops; i++) { | 
 |         str += op+"a"+i; | 
 |     } | 
 |     str += ")return 1;else return 0;})"; | 
 |     return eval(str); | 
 | } | 
 |  | 
 | // Generate a function of the form | 
 | // | 
 | // function(init,a0,...,aN) { | 
 | //   var tmp = init; | 
 | //   tmp = tmp + a0; | 
 | //   ... | 
 | //   tmp = tmp + aN; | 
 | //   if(tmp) return 1 | 
 | //  else return 0; | 
 | // } | 
 | // | 
 | // where + can be any binary operation. | 
 | function generate_nonchained_op_test(op, num_ops) { | 
 |     let str = "(function(init"; | 
 |     for (let i = 0; i < num_ops; i++) { | 
 |         str += ",a"+i; | 
 |     } | 
 |     str += "){ var tmp=init; "; | 
 |     for (let i = 0; i < num_ops; i++) { | 
 |         str += "tmp=(tmp"+op+"a"+i+");"; | 
 |     } | 
 |     str += "if(tmp)return 1;else return 0;})"; | 
 |     return eval(str); | 
 | } | 
 |  | 
 | const BINOPS = [ | 
 |     ",", | 
 |     "||", | 
 |     "&&", | 
 |     "|", | 
 |     "^", | 
 |     "&", | 
 |     "<<", | 
 |     ">>", | 
 |     ">>>", | 
 |     "+", | 
 |     "-", | 
 |     "*", | 
 |     "/", | 
 |     "%", | 
 | ]; | 
 |  | 
 | // Test each binop to see if the chained version is equivalent to the non- | 
 | // chained one. | 
 | for (let op of BINOPS) { | 
 |     let chained = generate_chained_op(op, 4); | 
 |     let nonchained = generate_nonchained_op(op, 4); | 
 |     let chained_test = generate_chained_op_test(op, 4); | 
 |     let nonchained_test = generate_nonchained_op_test(op, 4); | 
 |  | 
 |     // With numbers. | 
 |     assertEquals( | 
 |         nonchained(1,2,3,4,5), | 
 |         chained(1,2,3,4,5), | 
 |         "numeric " + op); | 
 |  | 
 |     // With numbers and strings. | 
 |     assertEquals( | 
 |         nonchained(1,"2",3,"4",5), | 
 |         chained(1,"2",3,"4",5), | 
 |         "numeric and string " + op); | 
 |  | 
 |     // Iterate over all possible combinations of 5 numbers that evaluate | 
 |     // to boolean true or false (for testing logical ops). | 
 |     for (var i = 0; i < 32; i++) { | 
 |         var booleanArray = [i & 1, i & 2, i & 4, i & 8, i & 16]; | 
 |         assertEquals( | 
 |             nonchained.apply(this, booleanArray), | 
 |             chained.apply(this, booleanArray), | 
 |             booleanArray.join(" " + op + " ")); | 
 |  | 
 |         assertEquals( | 
 |             nonchained_test.apply(this, booleanArray), | 
 |             chained_test.apply(this, booleanArray), | 
 |             "if (" + booleanArray.join(" " + op + " ") + ")"); | 
 |     } | 
 | } |