You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

types.js 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. "use strict";
  2. var __extends = (this && this.__extends) || (function () {
  3. var extendStatics = function (d, b) {
  4. extendStatics = Object.setPrototypeOf ||
  5. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  6. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  7. return extendStatics(d, b);
  8. };
  9. return function (d, b) {
  10. extendStatics(d, b);
  11. function __() { this.constructor = d; }
  12. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  13. };
  14. })();
  15. Object.defineProperty(exports, "__esModule", { value: true });
  16. var Op = Object.prototype;
  17. var objToStr = Op.toString;
  18. var hasOwn = Op.hasOwnProperty;
  19. var BaseType = /** @class */ (function () {
  20. function BaseType() {
  21. }
  22. BaseType.prototype.assert = function (value, deep) {
  23. if (!this.check(value, deep)) {
  24. var str = shallowStringify(value);
  25. throw new Error(str + " does not match type " + this);
  26. }
  27. return true;
  28. };
  29. BaseType.prototype.arrayOf = function () {
  30. var elemType = this;
  31. return new ArrayType(elemType);
  32. };
  33. return BaseType;
  34. }());
  35. var ArrayType = /** @class */ (function (_super) {
  36. __extends(ArrayType, _super);
  37. function ArrayType(elemType) {
  38. var _this = _super.call(this) || this;
  39. _this.elemType = elemType;
  40. _this.kind = "ArrayType";
  41. return _this;
  42. }
  43. ArrayType.prototype.toString = function () {
  44. return "[" + this.elemType + "]";
  45. };
  46. ArrayType.prototype.check = function (value, deep) {
  47. var _this = this;
  48. return Array.isArray(value) && value.every(function (elem) { return _this.elemType.check(elem, deep); });
  49. };
  50. return ArrayType;
  51. }(BaseType));
  52. var IdentityType = /** @class */ (function (_super) {
  53. __extends(IdentityType, _super);
  54. function IdentityType(value) {
  55. var _this = _super.call(this) || this;
  56. _this.value = value;
  57. _this.kind = "IdentityType";
  58. return _this;
  59. }
  60. IdentityType.prototype.toString = function () {
  61. return String(this.value);
  62. };
  63. IdentityType.prototype.check = function (value, deep) {
  64. var result = value === this.value;
  65. if (!result && typeof deep === "function") {
  66. deep(this, value);
  67. }
  68. return result;
  69. };
  70. return IdentityType;
  71. }(BaseType));
  72. var ObjectType = /** @class */ (function (_super) {
  73. __extends(ObjectType, _super);
  74. function ObjectType(fields) {
  75. var _this = _super.call(this) || this;
  76. _this.fields = fields;
  77. _this.kind = "ObjectType";
  78. return _this;
  79. }
  80. ObjectType.prototype.toString = function () {
  81. return "{ " + this.fields.join(", ") + " }";
  82. };
  83. ObjectType.prototype.check = function (value, deep) {
  84. return (objToStr.call(value) === objToStr.call({}) &&
  85. this.fields.every(function (field) {
  86. return field.type.check(value[field.name], deep);
  87. }));
  88. };
  89. return ObjectType;
  90. }(BaseType));
  91. var OrType = /** @class */ (function (_super) {
  92. __extends(OrType, _super);
  93. function OrType(types) {
  94. var _this = _super.call(this) || this;
  95. _this.types = types;
  96. _this.kind = "OrType";
  97. return _this;
  98. }
  99. OrType.prototype.toString = function () {
  100. return this.types.join(" | ");
  101. };
  102. OrType.prototype.check = function (value, deep) {
  103. return this.types.some(function (type) {
  104. return type.check(value, deep);
  105. });
  106. };
  107. return OrType;
  108. }(BaseType));
  109. var PredicateType = /** @class */ (function (_super) {
  110. __extends(PredicateType, _super);
  111. function PredicateType(name, predicate) {
  112. var _this = _super.call(this) || this;
  113. _this.name = name;
  114. _this.predicate = predicate;
  115. _this.kind = "PredicateType";
  116. return _this;
  117. }
  118. PredicateType.prototype.toString = function () {
  119. return this.name;
  120. };
  121. PredicateType.prototype.check = function (value, deep) {
  122. var result = this.predicate(value, deep);
  123. if (!result && typeof deep === "function") {
  124. deep(this, value);
  125. }
  126. return result;
  127. };
  128. return PredicateType;
  129. }(BaseType));
  130. var Def = /** @class */ (function () {
  131. function Def(type, typeName) {
  132. this.type = type;
  133. this.typeName = typeName;
  134. this.baseNames = [];
  135. this.ownFields = Object.create(null);
  136. // Includes own typeName. Populated during finalization.
  137. this.allSupertypes = Object.create(null);
  138. // Linear inheritance hierarchy. Populated during finalization.
  139. this.supertypeList = [];
  140. // Includes inherited fields.
  141. this.allFields = Object.create(null);
  142. // Non-hidden keys of allFields.
  143. this.fieldNames = [];
  144. // This property will be overridden as true by individual Def instances
  145. // when they are finalized.
  146. this.finalized = false;
  147. // False by default until .build(...) is called on an instance.
  148. this.buildable = false;
  149. this.buildParams = [];
  150. }
  151. Def.prototype.isSupertypeOf = function (that) {
  152. if (that instanceof Def) {
  153. if (this.finalized !== true ||
  154. that.finalized !== true) {
  155. throw new Error("");
  156. }
  157. return hasOwn.call(that.allSupertypes, this.typeName);
  158. }
  159. else {
  160. throw new Error(that + " is not a Def");
  161. }
  162. };
  163. Def.prototype.checkAllFields = function (value, deep) {
  164. var allFields = this.allFields;
  165. if (this.finalized !== true) {
  166. throw new Error("" + this.typeName);
  167. }
  168. function checkFieldByName(name) {
  169. var field = allFields[name];
  170. var type = field.type;
  171. var child = field.getValue(value);
  172. return type.check(child, deep);
  173. }
  174. return value !== null &&
  175. typeof value === "object" &&
  176. Object.keys(allFields).every(checkFieldByName);
  177. };
  178. Def.prototype.bases = function () {
  179. var supertypeNames = [];
  180. for (var _i = 0; _i < arguments.length; _i++) {
  181. supertypeNames[_i] = arguments[_i];
  182. }
  183. var bases = this.baseNames;
  184. if (this.finalized) {
  185. if (supertypeNames.length !== bases.length) {
  186. throw new Error("");
  187. }
  188. for (var i = 0; i < supertypeNames.length; i++) {
  189. if (supertypeNames[i] !== bases[i]) {
  190. throw new Error("");
  191. }
  192. }
  193. return this;
  194. }
  195. supertypeNames.forEach(function (baseName) {
  196. // This indexOf lookup may be O(n), but the typical number of base
  197. // names is very small, and indexOf is a native Array method.
  198. if (bases.indexOf(baseName) < 0) {
  199. bases.push(baseName);
  200. }
  201. });
  202. return this; // For chaining.
  203. };
  204. return Def;
  205. }());
  206. exports.Def = Def;
  207. var Field = /** @class */ (function () {
  208. function Field(name, type, defaultFn, hidden) {
  209. this.name = name;
  210. this.type = type;
  211. this.defaultFn = defaultFn;
  212. this.hidden = !!hidden;
  213. }
  214. Field.prototype.toString = function () {
  215. return JSON.stringify(this.name) + ": " + this.type;
  216. };
  217. Field.prototype.getValue = function (obj) {
  218. var value = obj[this.name];
  219. if (typeof value !== "undefined") {
  220. return value;
  221. }
  222. if (typeof this.defaultFn === "function") {
  223. value = this.defaultFn.call(obj);
  224. }
  225. return value;
  226. };
  227. return Field;
  228. }());
  229. function shallowStringify(value) {
  230. if (Array.isArray(value)) {
  231. return "[" + value.map(shallowStringify).join(", ") + "]";
  232. }
  233. if (value && typeof value === "object") {
  234. return "{ " + Object.keys(value).map(function (key) {
  235. return key + ": " + value[key];
  236. }).join(", ") + " }";
  237. }
  238. return JSON.stringify(value);
  239. }
  240. function typesPlugin(_fork) {
  241. var Type = {
  242. or: function () {
  243. var types = [];
  244. for (var _i = 0; _i < arguments.length; _i++) {
  245. types[_i] = arguments[_i];
  246. }
  247. return new OrType(types.map(function (type) { return Type.from(type); }));
  248. },
  249. from: function (value, name) {
  250. if (value instanceof ArrayType ||
  251. value instanceof IdentityType ||
  252. value instanceof ObjectType ||
  253. value instanceof OrType ||
  254. value instanceof PredicateType) {
  255. return value;
  256. }
  257. // The Def type is used as a helper for constructing compound
  258. // interface types for AST nodes.
  259. if (value instanceof Def) {
  260. return value.type;
  261. }
  262. // Support [ElemType] syntax.
  263. if (isArray.check(value)) {
  264. if (value.length !== 1) {
  265. throw new Error("only one element type is permitted for typed arrays");
  266. }
  267. return new ArrayType(Type.from(value[0]));
  268. }
  269. // Support { someField: FieldType, ... } syntax.
  270. if (isObject.check(value)) {
  271. return new ObjectType(Object.keys(value).map(function (name) {
  272. return new Field(name, Type.from(value[name], name));
  273. }));
  274. }
  275. if (typeof value === "function") {
  276. var bicfIndex = builtInCtorFns.indexOf(value);
  277. if (bicfIndex >= 0) {
  278. return builtInCtorTypes[bicfIndex];
  279. }
  280. if (typeof name !== "string") {
  281. throw new Error("missing name");
  282. }
  283. return new PredicateType(name, value);
  284. }
  285. // As a last resort, toType returns a type that matches any value that
  286. // is === from. This is primarily useful for literal values like
  287. // toType(null), but it has the additional advantage of allowing
  288. // toType to be a total function.
  289. return new IdentityType(value);
  290. },
  291. // Define a type whose name is registered in a namespace (the defCache) so
  292. // that future definitions will return the same type given the same name.
  293. // In particular, this system allows for circular and forward definitions.
  294. // The Def object d returned from Type.def may be used to configure the
  295. // type d.type by calling methods such as d.bases, d.build, and d.field.
  296. def: function (typeName) {
  297. return hasOwn.call(defCache, typeName)
  298. ? defCache[typeName]
  299. : defCache[typeName] = new DefImpl(typeName);
  300. },
  301. hasDef: function (typeName) {
  302. return hasOwn.call(defCache, typeName);
  303. }
  304. };
  305. var builtInCtorFns = [];
  306. var builtInCtorTypes = [];
  307. var builtInTypes = {};
  308. function defBuiltInType(example, name) {
  309. var objStr = objToStr.call(example);
  310. var type = new PredicateType(name, function (value) { return objToStr.call(value) === objStr; });
  311. builtInTypes[name] = type;
  312. if (example && typeof example.constructor === "function") {
  313. builtInCtorFns.push(example.constructor);
  314. builtInCtorTypes.push(type);
  315. }
  316. return type;
  317. }
  318. // These types check the underlying [[Class]] attribute of the given
  319. // value, rather than using the problematic typeof operator. Note however
  320. // that no subtyping is considered; so, for instance, isObject.check
  321. // returns false for [], /./, new Date, and null.
  322. var isString = defBuiltInType("truthy", "string");
  323. var isFunction = defBuiltInType(function () { }, "function");
  324. var isArray = defBuiltInType([], "array");
  325. var isObject = defBuiltInType({}, "object");
  326. var isRegExp = defBuiltInType(/./, "RegExp");
  327. var isDate = defBuiltInType(new Date, "Date");
  328. var isNumber = defBuiltInType(3, "number");
  329. var isBoolean = defBuiltInType(true, "boolean");
  330. var isNull = defBuiltInType(null, "null");
  331. var isUndefined = defBuiltInType(void 0, "undefined");
  332. // In order to return the same Def instance every time Type.def is called
  333. // with a particular name, those instances need to be stored in a cache.
  334. var defCache = Object.create(null);
  335. function defFromValue(value) {
  336. if (value && typeof value === "object") {
  337. var type = value.type;
  338. if (typeof type === "string" &&
  339. hasOwn.call(defCache, type)) {
  340. var d = defCache[type];
  341. if (d.finalized) {
  342. return d;
  343. }
  344. }
  345. }
  346. return null;
  347. }
  348. var DefImpl = /** @class */ (function (_super) {
  349. __extends(DefImpl, _super);
  350. function DefImpl(typeName) {
  351. var _this = _super.call(this, new PredicateType(typeName, function (value, deep) { return _this.check(value, deep); }), typeName) || this;
  352. return _this;
  353. }
  354. DefImpl.prototype.check = function (value, deep) {
  355. if (this.finalized !== true) {
  356. throw new Error("prematurely checking unfinalized type " + this.typeName);
  357. }
  358. // A Def type can only match an object value.
  359. if (value === null || typeof value !== "object") {
  360. return false;
  361. }
  362. var vDef = defFromValue(value);
  363. if (!vDef) {
  364. // If we couldn't infer the Def associated with the given value,
  365. // and we expected it to be a SourceLocation or a Position, it was
  366. // probably just missing a "type" field (because Esprima does not
  367. // assign a type property to such nodes). Be optimistic and let
  368. // this.checkAllFields make the final decision.
  369. if (this.typeName === "SourceLocation" ||
  370. this.typeName === "Position") {
  371. return this.checkAllFields(value, deep);
  372. }
  373. // Calling this.checkAllFields for any other type of node is both
  374. // bad for performance and way too forgiving.
  375. return false;
  376. }
  377. // If checking deeply and vDef === this, then we only need to call
  378. // checkAllFields once. Calling checkAllFields is too strict when deep
  379. // is false, because then we only care about this.isSupertypeOf(vDef).
  380. if (deep && vDef === this) {
  381. return this.checkAllFields(value, deep);
  382. }
  383. // In most cases we rely exclusively on isSupertypeOf to make O(1)
  384. // subtyping determinations. This suffices in most situations outside
  385. // of unit tests, since interface conformance is checked whenever new
  386. // instances are created using builder functions.
  387. if (!this.isSupertypeOf(vDef)) {
  388. return false;
  389. }
  390. // The exception is when deep is true; then, we recursively check all
  391. // fields.
  392. if (!deep) {
  393. return true;
  394. }
  395. // Use the more specific Def (vDef) to perform the deep check, but
  396. // shallow-check fields defined by the less specific Def (this).
  397. return vDef.checkAllFields(value, deep)
  398. && this.checkAllFields(value, false);
  399. };
  400. DefImpl.prototype.build = function () {
  401. var _this = this;
  402. var buildParams = [];
  403. for (var _i = 0; _i < arguments.length; _i++) {
  404. buildParams[_i] = arguments[_i];
  405. }
  406. // Calling Def.prototype.build multiple times has the effect of merely
  407. // redefining this property.
  408. this.buildParams = buildParams;
  409. if (this.buildable) {
  410. // If this Def is already buildable, update self.buildParams and
  411. // continue using the old builder function.
  412. return this;
  413. }
  414. // Every buildable type will have its "type" field filled in
  415. // automatically. This includes types that are not subtypes of Node,
  416. // like SourceLocation, but that seems harmless (TODO?).
  417. this.field("type", String, function () { return _this.typeName; });
  418. // Override Dp.buildable for this Def instance.
  419. this.buildable = true;
  420. var addParam = function (built, param, arg, isArgAvailable) {
  421. if (hasOwn.call(built, param))
  422. return;
  423. var all = _this.allFields;
  424. if (!hasOwn.call(all, param)) {
  425. throw new Error("" + param);
  426. }
  427. var field = all[param];
  428. var type = field.type;
  429. var value;
  430. if (isArgAvailable) {
  431. value = arg;
  432. }
  433. else if (field.defaultFn) {
  434. // Expose the partially-built object to the default
  435. // function as its `this` object.
  436. value = field.defaultFn.call(built);
  437. }
  438. else {
  439. var message = "no value or default function given for field " +
  440. JSON.stringify(param) + " of " + _this.typeName + "(" +
  441. _this.buildParams.map(function (name) {
  442. return all[name];
  443. }).join(", ") + ")";
  444. throw new Error(message);
  445. }
  446. if (!type.check(value)) {
  447. throw new Error(shallowStringify(value) +
  448. " does not match field " + field +
  449. " of type " + _this.typeName);
  450. }
  451. built[param] = value;
  452. };
  453. // Calling the builder function will construct an instance of the Def,
  454. // with positional arguments mapped to the fields original passed to .build.
  455. // If not enough arguments are provided, the default value for the remaining fields
  456. // will be used.
  457. var builder = function () {
  458. var args = [];
  459. for (var _i = 0; _i < arguments.length; _i++) {
  460. args[_i] = arguments[_i];
  461. }
  462. var argc = args.length;
  463. if (!_this.finalized) {
  464. throw new Error("attempting to instantiate unfinalized type " +
  465. _this.typeName);
  466. }
  467. var built = Object.create(nodePrototype);
  468. _this.buildParams.forEach(function (param, i) {
  469. if (i < argc) {
  470. addParam(built, param, args[i], true);
  471. }
  472. else {
  473. addParam(built, param, null, false);
  474. }
  475. });
  476. Object.keys(_this.allFields).forEach(function (param) {
  477. // Use the default value.
  478. addParam(built, param, null, false);
  479. });
  480. // Make sure that the "type" field was filled automatically.
  481. if (built.type !== _this.typeName) {
  482. throw new Error("");
  483. }
  484. return built;
  485. };
  486. // Calling .from on the builder function will construct an instance of the Def,
  487. // using field values from the passed object. For fields missing from the passed object,
  488. // their default value will be used.
  489. builder.from = function (obj) {
  490. if (!_this.finalized) {
  491. throw new Error("attempting to instantiate unfinalized type " +
  492. _this.typeName);
  493. }
  494. var built = Object.create(nodePrototype);
  495. Object.keys(_this.allFields).forEach(function (param) {
  496. if (hasOwn.call(obj, param)) {
  497. addParam(built, param, obj[param], true);
  498. }
  499. else {
  500. addParam(built, param, null, false);
  501. }
  502. });
  503. // Make sure that the "type" field was filled automatically.
  504. if (built.type !== _this.typeName) {
  505. throw new Error("");
  506. }
  507. return built;
  508. };
  509. Object.defineProperty(builders, getBuilderName(this.typeName), {
  510. enumerable: true,
  511. value: builder
  512. });
  513. return this;
  514. };
  515. // The reason fields are specified using .field(...) instead of an object
  516. // literal syntax is somewhat subtle: the object literal syntax would
  517. // support only one key and one value, but with .field(...) we can pass
  518. // any number of arguments to specify the field.
  519. DefImpl.prototype.field = function (name, type, defaultFn, hidden) {
  520. if (this.finalized) {
  521. console.error("Ignoring attempt to redefine field " +
  522. JSON.stringify(name) + " of finalized type " +
  523. JSON.stringify(this.typeName));
  524. return this;
  525. }
  526. this.ownFields[name] = new Field(name, Type.from(type), defaultFn, hidden);
  527. return this; // For chaining.
  528. };
  529. DefImpl.prototype.finalize = function () {
  530. var _this = this;
  531. // It's not an error to finalize a type more than once, but only the
  532. // first call to .finalize does anything.
  533. if (!this.finalized) {
  534. var allFields = this.allFields;
  535. var allSupertypes = this.allSupertypes;
  536. this.baseNames.forEach(function (name) {
  537. var def = defCache[name];
  538. if (def instanceof Def) {
  539. def.finalize();
  540. extend(allFields, def.allFields);
  541. extend(allSupertypes, def.allSupertypes);
  542. }
  543. else {
  544. var message = "unknown supertype name " +
  545. JSON.stringify(name) +
  546. " for subtype " +
  547. JSON.stringify(_this.typeName);
  548. throw new Error(message);
  549. }
  550. });
  551. // TODO Warn if fields are overridden with incompatible types.
  552. extend(allFields, this.ownFields);
  553. allSupertypes[this.typeName] = this;
  554. this.fieldNames.length = 0;
  555. for (var fieldName in allFields) {
  556. if (hasOwn.call(allFields, fieldName) &&
  557. !allFields[fieldName].hidden) {
  558. this.fieldNames.push(fieldName);
  559. }
  560. }
  561. // Types are exported only once they have been finalized.
  562. Object.defineProperty(namedTypes, this.typeName, {
  563. enumerable: true,
  564. value: this.type
  565. });
  566. this.finalized = true;
  567. // A linearization of the inheritance hierarchy.
  568. populateSupertypeList(this.typeName, this.supertypeList);
  569. if (this.buildable &&
  570. this.supertypeList.lastIndexOf("Expression") >= 0) {
  571. wrapExpressionBuilderWithStatement(this.typeName);
  572. }
  573. }
  574. };
  575. return DefImpl;
  576. }(Def));
  577. // Note that the list returned by this function is a copy of the internal
  578. // supertypeList, *without* the typeName itself as the first element.
  579. function getSupertypeNames(typeName) {
  580. if (!hasOwn.call(defCache, typeName)) {
  581. throw new Error("");
  582. }
  583. var d = defCache[typeName];
  584. if (d.finalized !== true) {
  585. throw new Error("");
  586. }
  587. return d.supertypeList.slice(1);
  588. }
  589. // Returns an object mapping from every known type in the defCache to the
  590. // most specific supertype whose name is an own property of the candidates
  591. // object.
  592. function computeSupertypeLookupTable(candidates) {
  593. var table = {};
  594. var typeNames = Object.keys(defCache);
  595. var typeNameCount = typeNames.length;
  596. for (var i = 0; i < typeNameCount; ++i) {
  597. var typeName = typeNames[i];
  598. var d = defCache[typeName];
  599. if (d.finalized !== true) {
  600. throw new Error("" + typeName);
  601. }
  602. for (var j = 0; j < d.supertypeList.length; ++j) {
  603. var superTypeName = d.supertypeList[j];
  604. if (hasOwn.call(candidates, superTypeName)) {
  605. table[typeName] = superTypeName;
  606. break;
  607. }
  608. }
  609. }
  610. return table;
  611. }
  612. var builders = Object.create(null);
  613. // This object is used as prototype for any node created by a builder.
  614. var nodePrototype = {};
  615. // Call this function to define a new method to be shared by all AST
  616. // nodes. The replaced method (if any) is returned for easy wrapping.
  617. function defineMethod(name, func) {
  618. var old = nodePrototype[name];
  619. // Pass undefined as func to delete nodePrototype[name].
  620. if (isUndefined.check(func)) {
  621. delete nodePrototype[name];
  622. }
  623. else {
  624. isFunction.assert(func);
  625. Object.defineProperty(nodePrototype, name, {
  626. enumerable: true,
  627. configurable: true,
  628. value: func
  629. });
  630. }
  631. return old;
  632. }
  633. function getBuilderName(typeName) {
  634. return typeName.replace(/^[A-Z]+/, function (upperCasePrefix) {
  635. var len = upperCasePrefix.length;
  636. switch (len) {
  637. case 0: return "";
  638. // If there's only one initial capital letter, just lower-case it.
  639. case 1: return upperCasePrefix.toLowerCase();
  640. default:
  641. // If there's more than one initial capital letter, lower-case
  642. // all but the last one, so that XMLDefaultDeclaration (for
  643. // example) becomes xmlDefaultDeclaration.
  644. return upperCasePrefix.slice(0, len - 1).toLowerCase() +
  645. upperCasePrefix.charAt(len - 1);
  646. }
  647. });
  648. }
  649. function getStatementBuilderName(typeName) {
  650. typeName = getBuilderName(typeName);
  651. return typeName.replace(/(Expression)?$/, "Statement");
  652. }
  653. var namedTypes = {};
  654. // Like Object.keys, but aware of what fields each AST type should have.
  655. function getFieldNames(object) {
  656. var d = defFromValue(object);
  657. if (d) {
  658. return d.fieldNames.slice(0);
  659. }
  660. if ("type" in object) {
  661. throw new Error("did not recognize object of type " +
  662. JSON.stringify(object.type));
  663. }
  664. return Object.keys(object);
  665. }
  666. // Get the value of an object property, taking object.type and default
  667. // functions into account.
  668. function getFieldValue(object, fieldName) {
  669. var d = defFromValue(object);
  670. if (d) {
  671. var field = d.allFields[fieldName];
  672. if (field) {
  673. return field.getValue(object);
  674. }
  675. }
  676. return object && object[fieldName];
  677. }
  678. // Iterate over all defined fields of an object, including those missing
  679. // or undefined, passing each field name and effective value (as returned
  680. // by getFieldValue) to the callback. If the object has no corresponding
  681. // Def, the callback will never be called.
  682. function eachField(object, callback, context) {
  683. getFieldNames(object).forEach(function (name) {
  684. callback.call(this, name, getFieldValue(object, name));
  685. }, context);
  686. }
  687. // Similar to eachField, except that iteration stops as soon as the
  688. // callback returns a truthy value. Like Array.prototype.some, the final
  689. // result is either true or false to indicates whether the callback
  690. // returned true for any element or not.
  691. function someField(object, callback, context) {
  692. return getFieldNames(object).some(function (name) {
  693. return callback.call(this, name, getFieldValue(object, name));
  694. }, context);
  695. }
  696. // Adds an additional builder for Expression subtypes
  697. // that wraps the built Expression in an ExpressionStatements.
  698. function wrapExpressionBuilderWithStatement(typeName) {
  699. var wrapperName = getStatementBuilderName(typeName);
  700. // skip if the builder already exists
  701. if (builders[wrapperName])
  702. return;
  703. // the builder function to wrap with builders.ExpressionStatement
  704. var wrapped = builders[getBuilderName(typeName)];
  705. // skip if there is nothing to wrap
  706. if (!wrapped)
  707. return;
  708. var builder = function () {
  709. var args = [];
  710. for (var _i = 0; _i < arguments.length; _i++) {
  711. args[_i] = arguments[_i];
  712. }
  713. return builders.expressionStatement(wrapped.apply(builders, args));
  714. };
  715. builder.from = function () {
  716. var args = [];
  717. for (var _i = 0; _i < arguments.length; _i++) {
  718. args[_i] = arguments[_i];
  719. }
  720. return builders.expressionStatement(wrapped.from.apply(builders, args));
  721. };
  722. builders[wrapperName] = builder;
  723. }
  724. function populateSupertypeList(typeName, list) {
  725. list.length = 0;
  726. list.push(typeName);
  727. var lastSeen = Object.create(null);
  728. for (var pos = 0; pos < list.length; ++pos) {
  729. typeName = list[pos];
  730. var d = defCache[typeName];
  731. if (d.finalized !== true) {
  732. throw new Error("");
  733. }
  734. // If we saw typeName earlier in the breadth-first traversal,
  735. // delete the last-seen occurrence.
  736. if (hasOwn.call(lastSeen, typeName)) {
  737. delete list[lastSeen[typeName]];
  738. }
  739. // Record the new index of the last-seen occurrence of typeName.
  740. lastSeen[typeName] = pos;
  741. // Enqueue the base names of this type.
  742. list.push.apply(list, d.baseNames);
  743. }
  744. // Compaction loop to remove array holes.
  745. for (var to = 0, from = to, len = list.length; from < len; ++from) {
  746. if (hasOwn.call(list, from)) {
  747. list[to++] = list[from];
  748. }
  749. }
  750. list.length = to;
  751. }
  752. function extend(into, from) {
  753. Object.keys(from).forEach(function (name) {
  754. into[name] = from[name];
  755. });
  756. return into;
  757. }
  758. function finalize() {
  759. Object.keys(defCache).forEach(function (name) {
  760. defCache[name].finalize();
  761. });
  762. }
  763. return {
  764. Type: Type,
  765. builtInTypes: builtInTypes,
  766. getSupertypeNames: getSupertypeNames,
  767. computeSupertypeLookupTable: computeSupertypeLookupTable,
  768. builders: builders,
  769. defineMethod: defineMethod,
  770. getBuilderName: getBuilderName,
  771. getStatementBuilderName: getStatementBuilderName,
  772. namedTypes: namedTypes,
  773. getFieldNames: getFieldNames,
  774. getFieldValue: getFieldValue,
  775. eachField: eachField,
  776. someField: someField,
  777. finalize: finalize,
  778. };
  779. }
  780. exports.default = typesPlugin;
  781. ;