NegativeZero.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. var GenerateNegativeZeroScheme = {
  6. Neg: 0,
  7. Mul: 1
  8. };
  9. var IntOperation = {
  10. None: 0,
  11. Incr: 1,
  12. Decr: 2,
  13. Not: 3,
  14. And: 4,
  15. Or: 5,
  16. Xor: 6,
  17. Shl: 7,
  18. Shr: 8,
  19. ShrU: 9
  20. };
  21. var MakeNegativeZeroMatterLocation = {
  22. None: 0,
  23. BeforeIntOperation: 1,
  24. AfterIntOperation: 2
  25. };
  26. var MakeNegativeZeroMatterScheme = {
  27. Div: 0,
  28. Throw: 1,
  29. Ret: 2,
  30. PassToFunction: 3,
  31. SetPropertyInLocalObject: 4,
  32. SetPropertyInNonlocalObjectInScope: 5,
  33. SetNonlocalVariableInScope: 6,
  34. SetArrayElement: 7
  35. };
  36. function makeNegativeZeroMatter(scheme, srcVar) {
  37. var s = "";
  38. if(scheme === MakeNegativeZeroMatterScheme.Div)
  39. s += "throw new Error(1 / c < 0 ? '-0' : '0');";
  40. else if(scheme === MakeNegativeZeroMatterScheme.Throw)
  41. s += "throw c;";
  42. else if(scheme === MakeNegativeZeroMatterScheme.Ret)
  43. s += "return c;";
  44. else if(scheme === MakeNegativeZeroMatterScheme.PassToFunction)
  45. s += "echo(c);";
  46. else if(scheme === MakeNegativeZeroMatterScheme.SetPropertyInLocalObject)
  47. s += "localObj.p = c;";
  48. else if(scheme === MakeNegativeZeroMatterScheme.SetPropertyInNonlocalObjectInScope)
  49. s += "outerObj.p = c;";
  50. else if(scheme === MakeNegativeZeroMatterScheme.SetNonlocalVariableInScope)
  51. s += "outerVar = c;";
  52. else if(scheme === MakeNegativeZeroMatterScheme.SetArrayElement)
  53. s += "localArr[0] = c;";
  54. else
  55. throw new Error("Unknown MakeNegativeZeroMatterScheme");
  56. return s;
  57. }
  58. function generateAndRunTest(
  59. generateNegativeZeroScheme,
  60. intOperation,
  61. makeNegativeZeroMatterLocation,
  62. makeNegativeZeroMatterScheme) {
  63. var f = "(function outer(a, b){";
  64. f += "var outerObj = {p: 0};"
  65. f += "var outerVar = 0;";
  66. f += "return (function test(a, b){";
  67. f += "a >>= 14;";
  68. f += "b &= 0x3fff;";
  69. f += "var localObj = {p: 0};";
  70. f += "var localArr = [0];";
  71. if(generateNegativeZeroScheme == GenerateNegativeZeroScheme.Neg)
  72. f += "var c = -b;";
  73. else if(generateNegativeZeroScheme == GenerateNegativeZeroScheme.Mul)
  74. f += "var c = a * b;";
  75. else
  76. throw new Error("Unknown GenerateNegativeZeroScheme");
  77. if(makeNegativeZeroMatterLocation === MakeNegativeZeroMatterLocation.BeforeIntOperation)
  78. f += makeNegativeZeroMatter(makeNegativeZeroMatterScheme);
  79. if(intOperation === IntOperation.None)
  80. f += "var d = c;";
  81. else if(intOperation === IntOperation.Incr)
  82. f += "var d = ++c;";
  83. else if(intOperation === IntOperation.Decr)
  84. f += "var d = --c;";
  85. else if(intOperation === IntOperation.Not)
  86. f += "var d = ~c;";
  87. else if(intOperation === IntOperation.And)
  88. f += "var d = c & 0xfffffff;";
  89. else if(intOperation === IntOperation.Or)
  90. f += "var d = c | 0xfffffff;";
  91. else if(intOperation === IntOperation.Xor)
  92. f += "var d = c ^ 0xfffffff;";
  93. else if(intOperation === IntOperation.Shl)
  94. f += "var d = c << 1;";
  95. else if(intOperation === IntOperation.Shr)
  96. f += "var d = c >> 1;";
  97. else if(intOperation === IntOperation.ShrU)
  98. f += "var d = c >>> 1;";
  99. else
  100. throw new Error("Unknown IntOperation");
  101. if(makeNegativeZeroMatterLocation === MakeNegativeZeroMatterLocation.AfterIntOperation)
  102. f += makeNegativeZeroMatter(makeNegativeZeroMatterScheme);
  103. f += "return [d & 0xfffffff, localObj.p, localArr[0], outerObj.p, outerVar];";
  104. f += "}).apply(this, arguments);";
  105. f += "});";
  106. f = eval(f);
  107. echo(f.toString());
  108. try {
  109. echo("Returned: ", f(-2 << 14, 0));
  110. } catch(ex) {
  111. echo("Thrown: ", ex);
  112. }
  113. }
  114. for(var generateNegativeZeroSchemeIndex in GenerateNegativeZeroScheme) {
  115. var generateNegativeZeroScheme = GenerateNegativeZeroScheme[generateNegativeZeroSchemeIndex];
  116. for(var intOperationIndex in IntOperation) {
  117. var intOperation = IntOperation[intOperationIndex];
  118. for(var makeNegativeZeroMatterLocationIndex in MakeNegativeZeroMatterLocation) {
  119. var makeNegativeZeroMatterLocation = MakeNegativeZeroMatterLocation[makeNegativeZeroMatterLocationIndex];
  120. if(makeNegativeZeroMatterLocation === MakeNegativeZeroMatterLocation.None) {
  121. var makeNegativeZeroMatterScheme = MakeNegativeZeroMatterScheme[makeNegativeZeroMatterSchemeIndex];
  122. echo("generateAndRunTest(" + intOperationIndex + ", " + makeNegativeZeroMatterLocationIndex + ");");
  123. generateAndRunTest(generateNegativeZeroScheme, intOperation, makeNegativeZeroMatterLocation);
  124. echo();
  125. } else {
  126. for(var makeNegativeZeroMatterSchemeIndex in MakeNegativeZeroMatterScheme) {
  127. var makeNegativeZeroMatterScheme = MakeNegativeZeroMatterScheme[makeNegativeZeroMatterSchemeIndex];
  128. echo(
  129. "generateAndRunTest(" +
  130. intOperationIndex + ", " +
  131. makeNegativeZeroMatterLocationIndex + ", " +
  132. makeNegativeZeroMatterSchemeIndex + ");");
  133. generateAndRunTest(
  134. generateNegativeZeroScheme,
  135. intOperation,
  136. makeNegativeZeroMatterLocation,
  137. makeNegativeZeroMatterScheme);
  138. echo();
  139. }
  140. }
  141. }
  142. }
  143. }
  144. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  145. function myToString(o, quoteStrings) {
  146. switch(o) {
  147. case null:
  148. case undefined:
  149. return "" + o;
  150. }
  151. switch(typeof o) {
  152. case "boolean":
  153. return "" + o;
  154. case "number":
  155. {
  156. if(o === 0 && 1 / o < 0)
  157. return "-0";
  158. var s = "" + o;
  159. var i = s.indexOf("e");
  160. var end = i === -1 ? s.length : e;
  161. i = s.indexOf(".");
  162. var start = i === -1 ? 0 : i + 1;
  163. if(start !== 0) {
  164. if((end - start) % 3 !== 0)
  165. end += 3 - (end - start) % 3;
  166. for(i = end - 3; i > start; i -= 3)
  167. s = s.substring(0, i) + "," + s.substring(i);
  168. end = start - 1;
  169. start = 0;
  170. }
  171. for(i = end - 3; i > start; i -= 3)
  172. s = s.substring(0, i) + "," + s.substring(i);
  173. return s;
  174. }
  175. case "string":
  176. {
  177. var hex = "0123456789abcdef";
  178. var s = "";
  179. for(var i = 0; i < o.length; ++i) {
  180. var c = o.charCodeAt(i);
  181. switch(c) {
  182. case 0x0:
  183. s += "\\0";
  184. continue;
  185. case 0x8:
  186. s += "\\b";
  187. continue;
  188. case 0xb:
  189. s += "\\v";
  190. continue;
  191. case 0xc:
  192. s += "\\f";
  193. continue;
  194. }
  195. if(quoteStrings) {
  196. switch(c) {
  197. case 0x9:
  198. s += "\\t";
  199. continue;
  200. case 0xa:
  201. s += "\\n";
  202. continue;
  203. case 0xd:
  204. s += "\\r";
  205. continue;
  206. case 0x22:
  207. s += "\\\"";
  208. continue;
  209. case 0x5c:
  210. s += "\\\\";
  211. continue;
  212. }
  213. }
  214. if(c >= 0x20 && c < 0x7f)
  215. s += o.charAt(i);
  216. else if(c <= 0xff)
  217. s += "\\x" + hex.charAt((c >> 4) & 0xf) + hex.charAt(c & 0xf);
  218. else
  219. s += "\\u" + hex.charAt((c >> 12) & 0xf) + hex.charAt((c >> 8) & 0xf) + hex.charAt((c >> 4) & 0xf) + hex.charAt(c & 0xf);
  220. }
  221. if(quoteStrings)
  222. s = "\"" + s + "\"";
  223. return s;
  224. }
  225. case "object":
  226. case "function":
  227. break;
  228. default:
  229. return "<unknown type '" + typeof o + "'>";
  230. }
  231. if(o instanceof Array) {
  232. var s = "[";
  233. for(var i = 0; i < o.length; ++i) {
  234. if(i)
  235. s += ", ";
  236. s += myToString(o[i], true);
  237. }
  238. return s + "]";
  239. }
  240. if(o instanceof Error)
  241. return o.name + ": " + o.message;
  242. if(o instanceof RegExp)
  243. return o.toString() + (o.lastIndex === 0 ? "" : " (lastIndex: " + o.lastIndex + ")");
  244. if(o instanceof Object && !(o instanceof Function)) {
  245. var s = "";
  246. for(var p in o)
  247. s += myToString(p) + ": " + myToString(o[p], true) + ", ";
  248. if(s.length !== 0)
  249. s = s.substring(0, s.length - ", ".length);
  250. return "{" + s + "}";
  251. }
  252. return "" + o;
  253. }
  254. function echo() {
  255. var doEcho;
  256. if(this.WScript)
  257. doEcho = function (s) { this.WScript.Echo(s); };
  258. else if(this.document)
  259. doEcho =
  260. function (s) {
  261. s = s
  262. .replace(/&/g, "&&")
  263. .replace(/</g, "&lt;")
  264. .replace(/>/g, "&gt;");
  265. this.document.write(s + "<br/>");
  266. };
  267. else
  268. doEcho = function (s) { this.print(s); };
  269. echo =
  270. function () {
  271. var s = "";
  272. for(var i = 0; i < arguments.length; ++i)
  273. s += myToString(arguments[i]);
  274. doEcho(s);
  275. };
  276. echo.apply(this, arguments);
  277. }
  278. function safeCall(f) {
  279. var args = [];
  280. for(var a = 1; a < arguments.length; ++a)
  281. args.push(arguments[a]);
  282. try {
  283. return f.apply(this, args);
  284. } catch(ex) {
  285. echo(ex);
  286. }
  287. }