1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/tests/js1_5/extensions/regress-350531.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,156 @@ 1.4 +// |reftest| skip -- slow 1.5 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +//----------------------------------------------------------------------------- 1.11 +var BUGNUMBER = 350531; 1.12 +var summary = 'exhaustively test parenthesization of binary operator subsets'; 1.13 +var actual = ''; 1.14 +var expect = ''; 1.15 + 1.16 + 1.17 +//----------------------------------------------------------------------------- 1.18 +test(); 1.19 +//----------------------------------------------------------------------------- 1.20 + 1.21 +function test() 1.22 +{ 1.23 + enterFunc ('test'); 1.24 + printBugNumber(BUGNUMBER); 1.25 + printStatus (summary); 1.26 + 1.27 +// Translated from permcomb.py, found at 1.28 +// http://biotech.embl-ebi.ac.uk:8400/sw/common/share/python/examples/dstruct/classics/permcomb.py 1.29 +// by searching for "permcomb.py". 1.30 +// 1.31 +// This shows bugs, gaps, and verbosities in JS compared to Python: 1.32 +// 1. Lack of range([start, ] end[, step]). 1.33 +// 2. ![] => false, indeed !<any-object> => false. 1.34 +// 3. Missing append or push for strings (if append, then we'd want append for 1.35 +// arrays too). 1.36 +// 4. Missing slice operator syntax s[i:j]. 1.37 +// 5. Lack of + for array concatenation. 1.38 + 1.39 + String.prototype.push = function (str) { return this + str; }; 1.40 + 1.41 + function permute(list) { 1.42 + if (!list.length) // shuffle any sequence 1.43 + return [list]; // empty sequence 1.44 + var res = []; 1.45 + for (var i = 0, n = list.length; i < n; i++) { // delete current node 1.46 + var rest = list.slice(0, i).concat(list.slice(i+1)); 1.47 + for each (var x in permute(rest)) // permute the others 1.48 + res.push(list.slice(i, i+1).concat(x)); // add node at front 1.49 + } 1.50 + return res; 1.51 + } 1.52 + 1.53 + function subset(list, size) { 1.54 + if (size == 0 || !list.length) // order matters here 1.55 + return [list.slice(0, 0)]; // an empty sequence 1.56 + var result = []; 1.57 + for (var i = 0, n = list.length; i < n; i++) { 1.58 + var pick = list.slice(i, i+1); // sequence slice 1.59 + var rest = list.slice(0, i).concat(list.slice(i+1)); // keep [:i] part 1.60 + for each (var x in subset(rest, size-1)) 1.61 + result.push(pick.concat(x)); 1.62 + } 1.63 + return result; 1.64 + } 1.65 + 1.66 + function combo(list, size) { 1.67 + if (size == 0 || !list.length) // order doesn't matter 1.68 + return [list.slice(0, 0)]; // xyz == yzx 1.69 + var result = []; 1.70 + for (var i = 0, n = (list.length - size) + 1; i < n; i++) { 1.71 + // iff enough left 1.72 + var pick = list.slice(i, i+1); 1.73 + var rest = list.slice(i+1); // drop [:i] part 1.74 + for each (var x in combo(rest, size - 1)) 1.75 + result.push(pick.concat(x)); 1.76 + } 1.77 + return result; 1.78 + } 1.79 + 1.80 + 1.81 +// Generate all subsets of distinct binary operators and join them from left 1.82 +// to right, parenthesizing minimally. Decompile, recompile, compress spaces 1.83 +// and compare to test correct parenthesization. 1.84 + 1.85 +// load("permcomb.js"); 1.86 + 1.87 + var bops = [ 1.88 + ["=", "|=", "^=", "&=", "<<=", ">>=", ">>>=", "+=", "-=", "*=", "/=", "%="], 1.89 + ["||"], 1.90 + ["&&"], 1.91 + ["|"], 1.92 + ["^"], 1.93 + ["&"], 1.94 + ["==", "!=", "===", "!=="], 1.95 + ["<", "<=", ">=", ">", "in", "instanceof"], 1.96 + ["<<", ">>", ">>>"], 1.97 + ["+", "-"], 1.98 + ["*", "/", "%"], 1.99 + ]; 1.100 + 1.101 + var prec = {}; 1.102 + var aops = []; 1.103 + 1.104 + for (var i = 0; i < bops.length; i++) { 1.105 + for (var j = 0; j < bops[i].length; j++) { 1.106 + var k = bops[i][j]; 1.107 + prec[k] = i; 1.108 + aops.push(k); 1.109 + } 1.110 + } 1.111 + 1.112 +// Theoretically all subsets of size 2 should be enough to test, but in case 1.113 +// there's some large-scale bug, try up to 5 (or higher? The cost in memory is 1.114 +// factorially explosive). 1.115 +next_subset: 1.116 + for (i = 2; i < 5; i++) { 1.117 + var sets = subset(aops, i); 1.118 + gc(); 1.119 + 1.120 + for each (var set in sets) { 1.121 + //print('for each set in sets: ' + (uneval(set)) ); 1.122 + var src = "(function () {"; 1.123 + for (j in set) { 1.124 + var op = set[j], op2 = set[j-1]; 1.125 + 1.126 + // Precedence 0 is for assignment ops, which are right- 1.127 + // associative, so don't force left associativity using 1.128 + // parentheses. 1.129 + if (prec[op] && prec[op] < prec[op2]) 1.130 + src += "("; 1.131 + } 1.132 + src += "x "; 1.133 + for (j in set) { 1.134 + var op = set[j], op2 = set[j+1]; 1.135 + 1.136 + // Parenthesize only if not right-associative (precedence 0) and 1.137 + // the next op is higher precedence than current. 1.138 + var term = (prec[op] && prec[op] < prec[op2]) ? " x)" : " x"; 1.139 + 1.140 + src += op + term; 1.141 + if (j < set.length - 1) 1.142 + src += " "; 1.143 + } 1.144 + src += ";})"; 1.145 + try { 1.146 + var ref = uneval(eval(src)).replace(/\s+/g, ' '); 1.147 + if (ref != src) { 1.148 + actual += "BROKEN! input: " + src + " output: " + ref + " "; 1.149 + print("BROKEN! input: " + src + " output: " + ref); 1.150 + break next_subset; 1.151 + } 1.152 + } catch (e) {} 1.153 + } 1.154 + } 1.155 + 1.156 + reportCompare(expect, actual, summary); 1.157 + 1.158 + exitFunc ('test'); 1.159 +}