| // 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 + " ") + ")"); |
| } |
| } |