index.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.print = print;
  6. var _ast = require("@webassemblyjs/ast");
  7. var _long = _interopRequireDefault(require("@xtuc/long"));
  8. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
  9. function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
  10. function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
  11. function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
  12. function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
  13. function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
  14. function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
  15. function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
  16. var compact = false;
  17. var space = " ";
  18. var quote = function quote(str) {
  19. return "\"".concat(str, "\"");
  20. };
  21. function indent(nb) {
  22. return Array(nb).fill(space + space).join("");
  23. } // TODO(sven): allow arbitrary ast nodes
  24. function print(n) {
  25. if (n.type === "Program") {
  26. return printProgram(n, 0);
  27. } else {
  28. throw new Error("Unsupported node in print of type: " + String(n.type));
  29. }
  30. }
  31. function printProgram(n, depth) {
  32. return n.body.reduce(function (acc, child) {
  33. if (child.type === "Module") {
  34. acc += printModule(child, depth + 1);
  35. }
  36. if (child.type === "Func") {
  37. acc += printFunc(child, depth + 1);
  38. }
  39. if (child.type === "BlockComment") {
  40. acc += printBlockComment(child);
  41. }
  42. if (child.type === "LeadingComment") {
  43. acc += printLeadingComment(child);
  44. }
  45. if (compact === false) {
  46. acc += "\n";
  47. }
  48. return acc;
  49. }, "");
  50. }
  51. function printTypeInstruction(n) {
  52. var out = "";
  53. out += "(";
  54. out += "type";
  55. out += space;
  56. if (n.id != null) {
  57. out += printIndex(n.id);
  58. out += space;
  59. }
  60. out += "(";
  61. out += "func";
  62. n.functype.params.forEach(function (param) {
  63. out += space;
  64. out += "(";
  65. out += "param";
  66. out += space;
  67. out += printFuncParam(param);
  68. out += ")";
  69. });
  70. n.functype.results.forEach(function (result) {
  71. out += space;
  72. out += "(";
  73. out += "result";
  74. out += space;
  75. out += result;
  76. out += ")";
  77. });
  78. out += ")"; // func
  79. out += ")";
  80. return out;
  81. }
  82. function printModule(n, depth) {
  83. var out = "(";
  84. out += "module";
  85. if (typeof n.id === "string") {
  86. out += space;
  87. out += n.id;
  88. }
  89. if (compact === false) {
  90. out += "\n";
  91. } else {
  92. out += space;
  93. }
  94. n.fields.forEach(function (field) {
  95. if (compact === false) {
  96. out += indent(depth);
  97. }
  98. switch (field.type) {
  99. case "Func":
  100. {
  101. out += printFunc(field, depth + 1);
  102. break;
  103. }
  104. case "TypeInstruction":
  105. {
  106. out += printTypeInstruction(field);
  107. break;
  108. }
  109. case "Table":
  110. {
  111. out += printTable(field);
  112. break;
  113. }
  114. case "Global":
  115. {
  116. out += printGlobal(field, depth + 1);
  117. break;
  118. }
  119. case "ModuleExport":
  120. {
  121. out += printModuleExport(field);
  122. break;
  123. }
  124. case "ModuleImport":
  125. {
  126. out += printModuleImport(field);
  127. break;
  128. }
  129. case "Memory":
  130. {
  131. out += printMemory(field);
  132. break;
  133. }
  134. case "BlockComment":
  135. {
  136. out += printBlockComment(field);
  137. break;
  138. }
  139. case "LeadingComment":
  140. {
  141. out += printLeadingComment(field);
  142. break;
  143. }
  144. case "Start":
  145. {
  146. out += printStart(field);
  147. break;
  148. }
  149. case "Elem":
  150. {
  151. out += printElem(field, depth);
  152. break;
  153. }
  154. case "Data":
  155. {
  156. out += printData(field, depth);
  157. break;
  158. }
  159. default:
  160. throw new Error("Unsupported node in printModule: " + String(field.type));
  161. }
  162. if (compact === false) {
  163. out += "\n";
  164. }
  165. });
  166. out += ")";
  167. return out;
  168. }
  169. function printData(n, depth) {
  170. var out = "";
  171. out += "(";
  172. out += "data";
  173. out += space;
  174. out += printIndex(n.memoryIndex);
  175. out += space;
  176. out += printInstruction(n.offset, depth);
  177. out += space;
  178. out += '"';
  179. n.init.values.forEach(function (_byte) {
  180. // Avoid non-displayable characters
  181. if (_byte <= 31 || _byte == 34 || _byte == 92 || _byte >= 127) {
  182. out += "\\";
  183. out += ("00" + _byte.toString(16)).substr(-2);
  184. } else if (_byte > 255) {
  185. throw new Error("Unsupported byte in data segment: " + _byte);
  186. } else {
  187. out += String.fromCharCode(_byte);
  188. }
  189. });
  190. out += '"';
  191. out += ")";
  192. return out;
  193. }
  194. function printElem(n, depth) {
  195. var out = "";
  196. out += "(";
  197. out += "elem";
  198. out += space;
  199. out += printIndex(n.table);
  200. var _n$offset = _slicedToArray(n.offset, 1),
  201. firstOffset = _n$offset[0];
  202. out += space;
  203. out += "(";
  204. out += "offset";
  205. out += space;
  206. out += printInstruction(firstOffset, depth);
  207. out += ")";
  208. n.funcs.forEach(function (func) {
  209. out += space;
  210. out += printIndex(func);
  211. });
  212. out += ")";
  213. return out;
  214. }
  215. function printStart(n) {
  216. var out = "";
  217. out += "(";
  218. out += "start";
  219. out += space;
  220. out += printIndex(n.index);
  221. out += ")";
  222. return out;
  223. }
  224. function printLeadingComment(n) {
  225. // Don't print leading comments in compact mode
  226. if (compact === true) {
  227. return "";
  228. }
  229. var out = "";
  230. out += ";;";
  231. out += n.value;
  232. out += "\n";
  233. return out;
  234. }
  235. function printBlockComment(n) {
  236. // Don't print block comments in compact mode
  237. if (compact === true) {
  238. return "";
  239. }
  240. var out = "";
  241. out += "(;";
  242. out += n.value;
  243. out += ";)";
  244. out += "\n";
  245. return out;
  246. }
  247. function printSignature(n) {
  248. var out = "";
  249. n.params.forEach(function (param) {
  250. out += space;
  251. out += "(";
  252. out += "param";
  253. out += space;
  254. out += printFuncParam(param);
  255. out += ")";
  256. });
  257. n.results.forEach(function (result) {
  258. out += space;
  259. out += "(";
  260. out += "result";
  261. out += space;
  262. out += result;
  263. out += ")";
  264. });
  265. return out;
  266. }
  267. function printModuleImportDescr(n) {
  268. var out = "";
  269. if (n.type === "FuncImportDescr") {
  270. out += "(";
  271. out += "func";
  272. if ((0, _ast.isAnonymous)(n.id) === false) {
  273. out += space;
  274. out += printIdentifier(n.id);
  275. }
  276. out += printSignature(n.signature);
  277. out += ")";
  278. }
  279. if (n.type === "GlobalType") {
  280. out += "(";
  281. out += "global";
  282. out += space;
  283. out += printGlobalType(n);
  284. out += ")";
  285. }
  286. if (n.type === "Table") {
  287. out += printTable(n);
  288. }
  289. return out;
  290. }
  291. function printModuleImport(n) {
  292. var out = "";
  293. out += "(";
  294. out += "import";
  295. out += space;
  296. out += quote(n.module);
  297. out += space;
  298. out += quote(n.name);
  299. out += space;
  300. out += printModuleImportDescr(n.descr);
  301. out += ")";
  302. return out;
  303. }
  304. function printGlobalType(n) {
  305. var out = "";
  306. if (n.mutability === "var") {
  307. out += "(";
  308. out += "mut";
  309. out += space;
  310. out += n.valtype;
  311. out += ")";
  312. } else {
  313. out += n.valtype;
  314. }
  315. return out;
  316. }
  317. function printGlobal(n, depth) {
  318. var out = "";
  319. out += "(";
  320. out += "global";
  321. out += space;
  322. if (n.name != null && (0, _ast.isAnonymous)(n.name) === false) {
  323. out += printIdentifier(n.name);
  324. out += space;
  325. }
  326. out += printGlobalType(n.globalType);
  327. out += space;
  328. n.init.forEach(function (i) {
  329. out += printInstruction(i, depth + 1);
  330. });
  331. out += ")";
  332. return out;
  333. }
  334. function printTable(n) {
  335. var out = "";
  336. out += "(";
  337. out += "table";
  338. out += space;
  339. if (n.name != null && (0, _ast.isAnonymous)(n.name) === false) {
  340. out += printIdentifier(n.name);
  341. out += space;
  342. }
  343. out += printLimit(n.limits);
  344. out += space;
  345. out += n.elementType;
  346. out += ")";
  347. return out;
  348. }
  349. function printFuncParam(n) {
  350. var out = "";
  351. if (typeof n.id === "string") {
  352. out += "$" + n.id;
  353. out += space;
  354. }
  355. out += n.valtype;
  356. return out;
  357. }
  358. function printFunc(n, depth) {
  359. var out = "";
  360. out += "(";
  361. out += "func";
  362. if (n.name != null) {
  363. if (n.name.type === "Identifier" && (0, _ast.isAnonymous)(n.name) === false) {
  364. out += space;
  365. out += printIdentifier(n.name);
  366. }
  367. }
  368. if (n.signature.type === "Signature") {
  369. out += printSignature(n.signature);
  370. } else {
  371. var index = n.signature;
  372. out += space;
  373. out += "(";
  374. out += "type";
  375. out += space;
  376. out += printIndex(index);
  377. out += ")";
  378. }
  379. if (n.body.length > 0) {
  380. // func is empty since we ignore the default end instruction
  381. if (n.body.length === 1 && n.body[0].id === "end") {
  382. out += ")";
  383. return out;
  384. }
  385. if (compact === false) {
  386. out += "\n";
  387. }
  388. n.body.forEach(function (i) {
  389. if (i.id !== "end") {
  390. out += indent(depth);
  391. out += printInstruction(i, depth);
  392. if (compact === false) {
  393. out += "\n";
  394. }
  395. }
  396. });
  397. out += indent(depth - 1) + ")";
  398. } else {
  399. out += ")";
  400. }
  401. return out;
  402. }
  403. function printInstruction(n, depth) {
  404. switch (n.type) {
  405. case "Instr":
  406. // $FlowIgnore
  407. return printGenericInstruction(n, depth + 1);
  408. case "BlockInstruction":
  409. // $FlowIgnore
  410. return printBlockInstruction(n, depth + 1);
  411. case "IfInstruction":
  412. // $FlowIgnore
  413. return printIfInstruction(n, depth + 1);
  414. case "CallInstruction":
  415. // $FlowIgnore
  416. return printCallInstruction(n, depth + 1);
  417. case "CallIndirectInstruction":
  418. // $FlowIgnore
  419. return printCallIndirectIntruction(n, depth + 1);
  420. case "LoopInstruction":
  421. // $FlowIgnore
  422. return printLoopInstruction(n, depth + 1);
  423. default:
  424. throw new Error("Unsupported instruction: " + JSON.stringify(n.type));
  425. }
  426. }
  427. function printCallIndirectIntruction(n, depth) {
  428. var out = "";
  429. out += "(";
  430. out += "call_indirect";
  431. if (n.signature.type === "Signature") {
  432. out += printSignature(n.signature);
  433. } else if (n.signature.type === "Identifier") {
  434. out += space;
  435. out += "(";
  436. out += "type";
  437. out += space;
  438. out += printIdentifier(n.signature);
  439. out += ")";
  440. } else {
  441. throw new Error("CallIndirectInstruction: unsupported signature " + JSON.stringify(n.signature.type));
  442. }
  443. out += space;
  444. if (n.intrs != null) {
  445. // $FlowIgnore
  446. n.intrs.forEach(function (i, index) {
  447. // $FlowIgnore
  448. out += printInstruction(i, depth + 1); // $FlowIgnore
  449. if (index !== n.intrs.length - 1) {
  450. out += space;
  451. }
  452. });
  453. }
  454. out += ")";
  455. return out;
  456. }
  457. function printLoopInstruction(n, depth) {
  458. var out = "";
  459. out += "(";
  460. out += "loop";
  461. if (n.label != null && (0, _ast.isAnonymous)(n.label) === false) {
  462. out += space;
  463. out += printIdentifier(n.label);
  464. }
  465. if (typeof n.resulttype === "string") {
  466. out += space;
  467. out += "(";
  468. out += "result";
  469. out += space;
  470. out += n.resulttype;
  471. out += ")";
  472. }
  473. if (n.instr.length > 0) {
  474. n.instr.forEach(function (e) {
  475. if (compact === false) {
  476. out += "\n";
  477. }
  478. out += indent(depth);
  479. out += printInstruction(e, depth + 1);
  480. });
  481. if (compact === false) {
  482. out += "\n";
  483. out += indent(depth - 1);
  484. }
  485. }
  486. out += ")";
  487. return out;
  488. }
  489. function printCallInstruction(n, depth) {
  490. var out = "";
  491. out += "(";
  492. out += "call";
  493. out += space;
  494. out += printIndex(n.index);
  495. if (_typeof(n.instrArgs) === "object") {
  496. // $FlowIgnore
  497. n.instrArgs.forEach(function (arg) {
  498. out += space;
  499. out += printFuncInstructionArg(arg, depth + 1);
  500. });
  501. }
  502. out += ")";
  503. return out;
  504. }
  505. function printIfInstruction(n, depth) {
  506. var out = "";
  507. out += "(";
  508. out += "if";
  509. if (n.testLabel != null && (0, _ast.isAnonymous)(n.testLabel) === false) {
  510. out += space;
  511. out += printIdentifier(n.testLabel);
  512. }
  513. if (typeof n.result === "string") {
  514. out += space;
  515. out += "(";
  516. out += "result";
  517. out += space;
  518. out += n.result;
  519. out += ")";
  520. }
  521. if (n.test.length > 0) {
  522. out += space;
  523. n.test.forEach(function (i) {
  524. out += printInstruction(i, depth + 1);
  525. });
  526. }
  527. if (n.consequent.length > 0) {
  528. if (compact === false) {
  529. out += "\n";
  530. }
  531. out += indent(depth);
  532. out += "(";
  533. out += "then";
  534. depth++;
  535. n.consequent.forEach(function (i) {
  536. if (compact === false) {
  537. out += "\n";
  538. }
  539. out += indent(depth);
  540. out += printInstruction(i, depth + 1);
  541. });
  542. depth--;
  543. if (compact === false) {
  544. out += "\n";
  545. out += indent(depth);
  546. }
  547. out += ")";
  548. } else {
  549. if (compact === false) {
  550. out += "\n";
  551. out += indent(depth);
  552. }
  553. out += "(";
  554. out += "then";
  555. out += ")";
  556. }
  557. if (n.alternate.length > 0) {
  558. if (compact === false) {
  559. out += "\n";
  560. }
  561. out += indent(depth);
  562. out += "(";
  563. out += "else";
  564. depth++;
  565. n.alternate.forEach(function (i) {
  566. if (compact === false) {
  567. out += "\n";
  568. }
  569. out += indent(depth);
  570. out += printInstruction(i, depth + 1);
  571. });
  572. depth--;
  573. if (compact === false) {
  574. out += "\n";
  575. out += indent(depth);
  576. }
  577. out += ")";
  578. } else {
  579. if (compact === false) {
  580. out += "\n";
  581. out += indent(depth);
  582. }
  583. out += "(";
  584. out += "else";
  585. out += ")";
  586. }
  587. if (compact === false) {
  588. out += "\n";
  589. out += indent(depth - 1);
  590. }
  591. out += ")";
  592. return out;
  593. }
  594. function printBlockInstruction(n, depth) {
  595. var out = "";
  596. out += "(";
  597. out += "block";
  598. if (n.label != null && (0, _ast.isAnonymous)(n.label) === false) {
  599. out += space;
  600. out += printIdentifier(n.label);
  601. }
  602. if (typeof n.result === "string") {
  603. out += space;
  604. out += "(";
  605. out += "result";
  606. out += space;
  607. out += n.result;
  608. out += ")";
  609. }
  610. if (n.instr.length > 0) {
  611. n.instr.forEach(function (i) {
  612. if (compact === false) {
  613. out += "\n";
  614. }
  615. out += indent(depth);
  616. out += printInstruction(i, depth + 1);
  617. });
  618. if (compact === false) {
  619. out += "\n";
  620. }
  621. out += indent(depth - 1);
  622. out += ")";
  623. } else {
  624. out += ")";
  625. }
  626. return out;
  627. }
  628. function printGenericInstruction(n, depth) {
  629. var out = "";
  630. out += "(";
  631. if (typeof n.object === "string") {
  632. out += n.object;
  633. out += ".";
  634. }
  635. out += n.id;
  636. n.args.forEach(function (arg) {
  637. out += space;
  638. out += printFuncInstructionArg(arg, depth + 1);
  639. });
  640. if (n.namedArgs !== undefined) {
  641. for (var key in n.namedArgs) {
  642. out += space + key + "=";
  643. out += printFuncInstructionArg(n.namedArgs[key], depth + 1);
  644. }
  645. }
  646. out += ")";
  647. return out;
  648. }
  649. function printLongNumberLiteral(n) {
  650. if (typeof n.raw === "string") {
  651. return n.raw;
  652. }
  653. var _n$value = n.value,
  654. low = _n$value.low,
  655. high = _n$value.high;
  656. var v = new _long["default"](low, high);
  657. return v.toString();
  658. }
  659. function printFloatLiteral(n) {
  660. if (typeof n.raw === "string") {
  661. return n.raw;
  662. }
  663. return String(n.value);
  664. }
  665. function printFuncInstructionArg(n, depth) {
  666. var out = "";
  667. if (n.type === "NumberLiteral") {
  668. out += printNumberLiteral(n);
  669. }
  670. if (n.type === "LongNumberLiteral") {
  671. out += printLongNumberLiteral(n);
  672. }
  673. if (n.type === "Identifier" && (0, _ast.isAnonymous)(n) === false) {
  674. out += printIdentifier(n);
  675. }
  676. if (n.type === "ValtypeLiteral") {
  677. out += n.name;
  678. }
  679. if (n.type === "FloatLiteral") {
  680. out += printFloatLiteral(n);
  681. }
  682. if ((0, _ast.isInstruction)(n)) {
  683. out += printInstruction(n, depth + 1);
  684. }
  685. return out;
  686. }
  687. function printNumberLiteral(n) {
  688. if (typeof n.raw === "string") {
  689. return n.raw;
  690. }
  691. return String(n.value);
  692. }
  693. function printModuleExport(n) {
  694. var out = "";
  695. out += "(";
  696. out += "export";
  697. out += space;
  698. out += quote(n.name);
  699. if (n.descr.exportType === "Func") {
  700. out += space;
  701. out += "(";
  702. out += "func";
  703. out += space;
  704. out += printIndex(n.descr.id);
  705. out += ")";
  706. } else if (n.descr.exportType === "Global") {
  707. out += space;
  708. out += "(";
  709. out += "global";
  710. out += space;
  711. out += printIndex(n.descr.id);
  712. out += ")";
  713. } else if (n.descr.exportType === "Memory") {
  714. out += space;
  715. out += "(";
  716. out += "memory";
  717. out += space;
  718. out += printIndex(n.descr.id);
  719. out += ")";
  720. } else if (n.descr.exportType === "Table") {
  721. out += space;
  722. out += "(";
  723. out += "table";
  724. out += space;
  725. out += printIndex(n.descr.id);
  726. out += ")";
  727. } else {
  728. throw new Error("printModuleExport: unknown type: " + n.descr.exportType);
  729. }
  730. out += ")";
  731. return out;
  732. }
  733. function printIdentifier(n) {
  734. return "$" + n.value;
  735. }
  736. function printIndex(n) {
  737. if (n.type === "Identifier") {
  738. return printIdentifier(n);
  739. } else if (n.type === "NumberLiteral") {
  740. return printNumberLiteral(n);
  741. } else {
  742. throw new Error("Unsupported index: " + n.type);
  743. }
  744. }
  745. function printMemory(n) {
  746. var out = "";
  747. out += "(";
  748. out += "memory";
  749. if (n.id != null) {
  750. out += space;
  751. out += printIndex(n.id);
  752. out += space;
  753. }
  754. out += printLimit(n.limits);
  755. out += ")";
  756. return out;
  757. }
  758. function printLimit(n) {
  759. var out = "";
  760. out += n.min + "";
  761. if (n.max != null) {
  762. out += space;
  763. out += String(n.max);
  764. if (n.shared === true) {
  765. out += " shared";
  766. }
  767. }
  768. return out;
  769. }