UNPKG

34.2 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = void 0;
7
8var _errors = require("../errors.js");
9
10var _generator = require("../utils/generator.js");
11
12var _PreludeGenerator = require("../utils/PreludeGenerator.js");
13
14var _builder = _interopRequireDefault(require("../utils/builder.js"));
15
16var _index = require("./index.js");
17
18var _index2 = require("../methods/index.js");
19
20var _index3 = require("../domains/index.js");
21
22var _invariant = _interopRequireDefault(require("../invariant.js"));
23
24function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
26/**
27 * Copyright (c) 2017-present, Facebook, Inc.
28 * All rights reserved.
29 *
30 * This source code is licensed under the BSD-style license found in the
31 * LICENSE file in the root directory of this source tree. An additional grant
32 * of patent rights can be found in the PATENTS file in the same directory.
33 */
34class AbstractValue extends _index.Value {
35 constructor(realm, types, values, hashValue, args, operationDescriptor, optionalArgs) {
36 (0, _invariant.default)(realm.useAbstractInterpretation);
37 super(realm, optionalArgs ? optionalArgs.intrinsicName : undefined);
38 (0, _invariant.default)(!_index.Value.isTypeCompatibleWith(types.getType(), _index.ObjectValue) || this instanceof _index.AbstractObjectValue);
39 (0, _invariant.default)(types.getType() !== _index.NullValue && types.getType() !== _index.UndefinedValue);
40 this.types = types;
41 this.values = values;
42 this.mightBeEmpty = false;
43 this.operationDescriptor = operationDescriptor;
44 this.args = args;
45 this.hashValue = hashValue;
46 this.kind = optionalArgs ? optionalArgs.kind : undefined;
47 this.shape = optionalArgs ? optionalArgs.shape : undefined;
48 }
49
50 toDisplayString() {
51 return "[Abstract " + this.hashValue.toString() + "]";
52 }
53
54 addSourceLocationsTo(locations, seenValues = new Set()) {
55 if (seenValues.has(this)) return;
56 seenValues.add(this);
57
58 for (let val of this.args) {
59 if (val instanceof AbstractValue) val.addSourceLocationsTo(locations, seenValues);
60 }
61 }
62
63 addSourceNamesTo(names, visited = new Set()) {
64 if (visited.has(this)) return;
65 visited.add(this);
66 let realm = this.$Realm;
67
68 function add_intrinsic(name) {
69 if (name.startsWith("_$")) {
70 let temporalOperationEntryArgs = realm.derivedIds.get(name);
71 (0, _invariant.default)(temporalOperationEntryArgs !== undefined);
72 add_args(temporalOperationEntryArgs.args);
73 } else if (names.indexOf(name) < 0) {
74 names.push(name);
75 }
76 }
77
78 function add_args(args) {
79 if (args === undefined) return;
80
81 for (let val of args) {
82 if (val.intrinsicName) {
83 add_intrinsic(val.intrinsicName);
84 } else if (val instanceof AbstractValue) {
85 val.addSourceNamesTo(names, visited);
86 } else if (val instanceof _index.StringValue) {
87 if (val.value.startsWith("__")) {
88 names.push(val.value.slice(2));
89 }
90 }
91 }
92 }
93
94 if (this.intrinsicName) {
95 add_intrinsic(this.intrinsicName);
96 }
97
98 add_args(this.args);
99 }
100
101 equals(x) {
102 if (x instanceof _index.ConcreteValue) return false;
103 let thisArgs = this.args;
104 let n = thisArgs.length;
105
106 let argsAreEqual = () => {
107 (0, _invariant.default)(x instanceof AbstractValue);
108 let xArgs = x.args;
109 let m = xArgs.length;
110 (0, _invariant.default)(n === m); // Will be true if kinds are the same. Caller should see to it.
111
112 for (let i = 0; i < n; i++) {
113 let a = thisArgs[i];
114 let b = xArgs[i];
115 if (!a.equals(b)) return false;
116 }
117
118 return true;
119 };
120
121 return this === x || x instanceof AbstractValue && this.kind === x.kind && this.hashValue === x.hashValue && (this.intrinsicName && this.intrinsicName.length > 0 && this.intrinsicName === x.intrinsicName || n > 0 && argsAreEqual());
122 }
123
124 getHash() {
125 return this.hashValue;
126 }
127
128 getType() {
129 return this.types.getType();
130 }
131
132 getIdentifier() {
133 (0, _invariant.default)(this.hasIdentifier());
134 (0, _invariant.default)(this.operationDescriptor !== undefined);
135 let {
136 id
137 } = this.operationDescriptor.data;
138 (0, _invariant.default)(id !== undefined);
139 return id;
140 }
141
142 hasIdentifier() {
143 return this.operationDescriptor ? this.operationDescriptor.type === "IDENTIFIER" : false;
144 }
145
146 _checkAbstractValueImpliesCounter() {
147 let realm = this.$Realm;
148 let abstractValueImpliesMax = realm.abstractValueImpliesMax; // if abstractValueImpliesMax is 0, then the counter is disabled
149
150 if (abstractValueImpliesMax !== 0 && realm.abstractValueImpliesCounter++ > abstractValueImpliesMax) {
151 realm.abstractValueImpliesCounter = 0;
152 let diagnostic = new _errors.CompilerDiagnostic(`the implies counter has exceeded the maximum value when trying to simplify abstract values`, realm.currentLocation, "PP0029", "FatalError");
153 realm.handleError(diagnostic);
154 }
155 } // this => val. A false value does not imply that !(this => val).
156
157
158 implies(val) {
159 this._checkAbstractValueImpliesCounter();
160
161 if (this.equals(val)) return true; // x => x regardless of its value
162
163 if (!this.mightNotBeFalse()) return true; // false => val
164
165 if (!val.mightNotBeTrue()) return true; // x => true regardless of the value of x
166
167 if (val instanceof AbstractValue) {
168 // Neither this (x) nor val (y) is a known value, so we need to do some reasoning based on the structure
169 // x => x || y
170 if (val.kind === "||") {
171 let [x, y] = val.args;
172 return this.implies(x) || this.implies(y);
173 } // x => !y if y => !x
174
175
176 if (val.kind === "!") {
177 let [y] = val.args;
178 (0, _invariant.default)(y instanceof AbstractValue);
179 return y.impliesNot(this);
180 } // x => x !== null && x !== undefined
181
182
183 if (val.kind === "!==") {
184 let [x, y] = val.args;
185 if (this.implies(x)) return y instanceof _index.NullValue || y instanceof _index.UndefinedValue;
186 if (this.implies(y)) return x instanceof _index.NullValue || x instanceof _index.UndefinedValue;
187 } // !!x => y if x => y
188
189
190 if (this.kind === "!") {
191 let [nx] = this.args;
192 (0, _invariant.default)(nx instanceof AbstractValue);
193
194 if (nx.kind === "!") {
195 let [x] = nx.args;
196 (0, _invariant.default)(x instanceof AbstractValue);
197 return x.implies(val);
198 }
199 }
200
201 if (this.kind === "conditional") {
202 let [c, x, y] = this.args; // (c ? x : y) => val if x is true and y is false and c = val
203
204 if (!x.mightNotBeTrue() && !y.mightNotBeFalse()) {
205 return c.equals(val);
206 } // (c ? false : y) => y !== undefined && y !== null && y !== f
207
208
209 if (val.kind === "!==") {
210 let [vx, vy] = val.args;
211
212 if (!x.mightNotBeFalse()) {
213 if (y.implies(vx)) return vy instanceof _index.NullValue || vy instanceof _index.UndefinedValue;
214 if (y.implies(vy)) return vx instanceof _index.NullValue || vx instanceof _index.UndefinedValue;
215 } else if (!y.mightNotBeFalse()) {
216 if (x.implies(vx)) return vy instanceof _index.NullValue || vy instanceof _index.UndefinedValue;
217 if (x.implies(vy)) return vx instanceof _index.NullValue || vx instanceof _index.UndefinedValue;
218 }
219 } // (c ? x : false) => c && x (if c or x were falsy, (c ? x : false) could not be true)
220
221
222 if (!y.mightNotBeFalse()) {
223 if (c.implies(val)) return true;
224 if (x.implies(val)) return true;
225 }
226 } // (0 !== x) => x since undefined, null, false, 0, NaN and "" are excluded by the !== and all other values are thruthy
227
228
229 if (this.kind === "!==") {
230 let [x, y] = this.args;
231 if (x instanceof _index.NumberValue && x.value === 0) return y.equals(val);
232 if (y instanceof _index.NumberValue && y.value === 0) return x.equals(val);
233 }
234
235 if (this.kind === "===" && val.kind === "==") {
236 // x === undefined/null => y == undefined/null
237 let [x, y] = val.args;
238
239 if (x instanceof _index.NullValue || x instanceof _index.UndefinedValue || y instanceof _index.NullValue || y instanceof _index.UndefinedValue) {
240 let [vx, vy] = val.args;
241
242 if (vx instanceof _index.NullValue || vx instanceof _index.UndefinedValue || vy instanceof _index.NullValue || vy instanceof _index.UndefinedValue) {
243 return true;
244 }
245 }
246 }
247 }
248
249 return false;
250 } // this => !val. A false value does not imply that !(this => !val).
251
252
253 impliesNot(val) {
254 if (this.equals(val)) return false; // x => x regardless of its value, hence x => !val is false
255
256 if (!this.mightNotBeFalse()) return true; // false => !val
257
258 if (!val.mightNotBeFalse()) return true; // x => !false regardless of the value of x
259
260 if (val instanceof AbstractValue) {
261 // !x => !y if y => x
262 if (this.kind === "!") {
263 let [x] = this.args;
264 (0, _invariant.default)(x instanceof AbstractValue);
265
266 if (x.kind === "!") {
267 // !!x => !y if y => !x
268 (0, _invariant.default)(x instanceof AbstractValue);
269 let [xx] = x.args;
270 (0, _invariant.default)(xx instanceof AbstractValue);
271 return xx.impliesNot(val);
272 }
273
274 if (x.kind === "abstractConcreteUnion") return false; // can't use two valued logic for this.
275
276 return val.implies(x);
277 }
278
279 if (this.kind === "conditional") {
280 let [c, x, y] = this.args; // (c ? x : y) => !val if x is false and y is true and c = val
281
282 if (!x.mightNotBeFalse() && !y.mightNotBeTrue()) {
283 return c.equals(val);
284 }
285 }
286 }
287
288 return false;
289 } // todo: abstract values should never be of type UndefinedValue or NullValue, assert this
290
291
292 mightBeFalse() {
293 let valueType = this.getType();
294 if (valueType === _index.UndefinedValue) return true;
295 if (valueType === _index.NullValue) return true;
296 if (valueType === _index.SymbolValue) return false;
297 if (_index.Value.isTypeCompatibleWith(valueType, _index.ObjectValue)) return false;
298
299 if (this.kind === "abstractConcreteUnion") {
300 for (let arg of this.args) if (arg.mightBeFalse()) return true;
301
302 return false;
303 }
304
305 if (this.values.isTop()) return true;
306 return this.values.mightBeFalse();
307 }
308
309 mightNotBeFalse() {
310 let valueType = this.getType();
311 if (valueType === _index.UndefinedValue) return false;
312 if (valueType === _index.NullValue) return false;
313 if (valueType === _index.SymbolValue) return true;
314 if (_index.Value.isTypeCompatibleWith(valueType, _index.ObjectValue)) return true;
315
316 if (this.kind === "abstractConcreteUnion") {
317 for (let arg of this.args) if (arg.mightNotBeFalse()) return true;
318
319 return false;
320 }
321
322 if (this.values.isTop()) return true;
323 return this.values.mightNotBeFalse();
324 }
325
326 mightBeNull() {
327 let valueType = this.getType();
328 if (valueType === _index.NullValue) return true;
329 if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return false;
330
331 if (this.kind === "abstractConcreteUnion") {
332 for (let arg of this.args) if (arg.mightBeNull()) return true;
333
334 return false;
335 }
336
337 if (this.values.isTop()) return true;
338 return this.values.includesValueOfType(_index.NullValue);
339 }
340
341 mightNotBeNull() {
342 let valueType = this.getType();
343 if (valueType === _index.NullValue) return false;
344 if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return true;
345
346 if (this.kind === "abstractConcreteUnion") {
347 for (let arg of this.args) if (arg.mightNotBeNull()) return true;
348
349 return false;
350 }
351
352 if (this.values.isTop()) return true;
353 return this.values.includesValueNotOfType(_index.NullValue);
354 }
355
356 mightBeNumber() {
357 let valueType = this.getType();
358 if (_index.Value.isTypeCompatibleWith(valueType, _index.NumberValue)) return true;
359 if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return false;
360
361 if (this.kind === "abstractConcreteUnion") {
362 for (let arg of this.args) if (arg.mightBeNumber()) return true;
363
364 return false;
365 }
366
367 if (this.values.isTop()) return true;
368 return this.values.includesValueOfType(_index.NumberValue);
369 }
370
371 mightNotBeNumber() {
372 let valueType = this.getType();
373 if (_index.Value.isTypeCompatibleWith(valueType, _index.NumberValue)) return false;
374 if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return true;
375
376 if (this.kind === "abstractConcreteUnion") {
377 for (let arg of this.args) if (arg.mightNotBeNumber()) return true;
378
379 return false;
380 }
381
382 if (this.values.isTop()) return true;
383 return this.values.includesValueNotOfType(_index.NumberValue);
384 }
385
386 mightNotBeObject() {
387 let valueType = this.getType();
388 if (_index.Value.isTypeCompatibleWith(valueType, _index.PrimitiveValue)) return true;
389 if (_index.Value.isTypeCompatibleWith(valueType, _index.ObjectValue)) return false;
390
391 if (this.kind === "abstractConcreteUnion") {
392 for (let arg of this.args) if (arg.mightNotBeObject()) return true;
393
394 return false;
395 }
396
397 if (this.values.isTop()) return true;
398 return this.values.includesValueNotOfType(_index.ObjectValue);
399 }
400
401 mightBeObject() {
402 let valueType = this.getType();
403 if (_index.Value.isTypeCompatibleWith(valueType, _index.PrimitiveValue)) return false;
404 if (_index.Value.isTypeCompatibleWith(valueType, _index.ObjectValue)) return true;
405
406 if (this.kind === "abstractConcreteUnion") {
407 for (let arg of this.args) if (arg.mightBeObject()) return true;
408
409 return false;
410 }
411
412 if (this.values.isTop()) return true;
413 return this.values.includesValueOfType(_index.ObjectValue);
414 }
415
416 mightBeString() {
417 let valueType = this.getType();
418 if (valueType === _index.StringValue) return true;
419 if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return false;
420
421 if (this.kind === "abstractConcreteUnion") {
422 for (let arg of this.args) if (arg.mightBeString()) return true;
423
424 return false;
425 }
426
427 if (this.values.isTop()) return true;
428 return this.values.includesValueOfType(_index.StringValue);
429 }
430
431 mightNotBeString() {
432 let valueType = this.getType();
433 if (valueType === _index.StringValue) return false;
434 if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return true;
435
436 if (this.kind === "abstractConcreteUnion") {
437 for (let arg of this.args) if (arg.mightNotBeString()) return true;
438
439 return false;
440 }
441
442 if (this.values.isTop()) return true;
443 return this.values.includesValueNotOfType(_index.StringValue);
444 }
445
446 mightBeUndefined() {
447 let valueType = this.getType();
448 if (valueType === _index.UndefinedValue) return true;
449 if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return false;
450
451 if (this.kind === "abstractConcreteUnion") {
452 for (let arg of this.args) if (arg.mightBeUndefined()) return true;
453
454 return false;
455 }
456
457 if (this.values.isTop()) return true;
458 return this.values.includesValueOfType(_index.UndefinedValue);
459 }
460
461 mightNotBeUndefined() {
462 let valueType = this.getType();
463 if (valueType === _index.UndefinedValue) return false;
464 if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return true;
465
466 if (this.kind === "abstractConcreteUnion") {
467 for (let arg of this.args) if (arg.mightNotBeUndefined()) return true;
468
469 return false;
470 }
471
472 if (this.values.isTop()) return true;
473 return this.values.includesValueNotOfType(_index.UndefinedValue);
474 }
475
476 mightHaveBeenDeleted() {
477 return this.mightBeEmpty;
478 }
479
480 promoteEmptyToUndefined() {
481 if (this.values.isTop()) return this;
482 if (!this.mightBeEmpty) return this;
483 let cond = AbstractValue.createFromBinaryOp(this.$Realm, "===", this, this.$Realm.intrinsics.empty);
484 let result = AbstractValue.createFromConditionalOp(this.$Realm, cond, this.$Realm.intrinsics.undefined, this);
485 if (result instanceof AbstractValue) result.values = this.values.promoteEmptyToUndefined();
486 return result;
487 }
488
489 throwIfNotConcrete() {
490 AbstractValue.reportIntrospectionError(this);
491 throw new _errors.FatalError();
492 }
493
494 throwIfNotConcreteNumber() {
495 AbstractValue.reportIntrospectionError(this);
496 throw new _errors.FatalError();
497 }
498
499 throwIfNotConcreteString() {
500 AbstractValue.reportIntrospectionError(this);
501 throw new _errors.FatalError();
502 }
503
504 throwIfNotConcreteBoolean() {
505 AbstractValue.reportIntrospectionError(this);
506 throw new _errors.FatalError();
507 }
508
509 throwIfNotConcreteSymbol() {
510 AbstractValue.reportIntrospectionError(this);
511 throw new _errors.FatalError();
512 }
513
514 throwIfNotConcreteObject() {
515 AbstractValue.reportIntrospectionError(this);
516 throw new _errors.FatalError();
517 }
518
519 throwIfNotConcretePrimitive() {
520 AbstractValue.reportIntrospectionError(this);
521 throw new _errors.FatalError();
522 }
523
524 throwIfNotObject() {
525 (0, _invariant.default)(!(this instanceof _index.AbstractObjectValue));
526 AbstractValue.reportIntrospectionError(this);
527 throw new _errors.FatalError();
528 }
529
530 static createFromBinaryOp(realm, op, left, right, loc, kind, isCondition, doNotSimplify) {
531 let leftTypes, leftValues;
532
533 if (left instanceof AbstractValue) {
534 leftTypes = left.types;
535 leftValues = left.values;
536 } else {
537 leftTypes = new _index3.TypesDomain(left.getType());
538 (0, _invariant.default)(left instanceof _index.ConcreteValue);
539 leftValues = new _index3.ValuesDomain(left);
540 }
541
542 let rightTypes, rightValues;
543
544 if (right instanceof AbstractValue) {
545 rightTypes = right.types;
546 rightValues = right.values;
547 } else {
548 rightTypes = new _index3.TypesDomain(right.getType());
549 (0, _invariant.default)(right instanceof _index.ConcreteValue);
550 rightValues = new _index3.ValuesDomain(right);
551 }
552
553 let resultTypes = _index3.TypesDomain.binaryOp(op, leftTypes, rightTypes);
554
555 let resultValues = kind === "template for property name condition" ? _index3.ValuesDomain.topVal : _index3.ValuesDomain.binaryOp(realm, op, leftValues, rightValues);
556 let [hash, args] = kind === undefined ? (0, _index2.hashBinary)(op, left, right) : (0, _index2.hashCall)(kind, left, right);
557 let operationDescriptor = (0, _generator.createOperationDescriptor)("BINARY_EXPRESSION", {
558 op
559 });
560 let result = new AbstractValue(realm, resultTypes, resultValues, hash, args, operationDescriptor);
561 result.kind = kind || op;
562 result.expressionLocation = loc;
563 if (doNotSimplify) return result;
564 return isCondition ? realm.simplifyAndRefineAbstractCondition(result) : realm.simplifyAndRefineAbstractValue(result);
565 }
566
567 static createFromLogicalOp(realm, op, left, right, loc, isCondition, doNotSimplify) {
568 let leftTypes, leftValues;
569
570 if (left instanceof AbstractValue) {
571 leftTypes = left.types;
572 leftValues = left.values;
573 } else {
574 leftTypes = new _index3.TypesDomain(left.getType());
575 (0, _invariant.default)(left instanceof _index.ConcreteValue);
576 leftValues = new _index3.ValuesDomain(left);
577 }
578
579 let rightTypes, rightValues;
580
581 if (right instanceof AbstractValue) {
582 rightTypes = right.types;
583 rightValues = right.values;
584 } else {
585 rightTypes = new _index3.TypesDomain(right.getType());
586 (0, _invariant.default)(right instanceof _index.ConcreteValue);
587 rightValues = new _index3.ValuesDomain(right);
588 }
589
590 let resultTypes = _index3.TypesDomain.logicalOp(op, leftTypes, rightTypes);
591
592 let resultValues = _index3.ValuesDomain.logicalOp(realm, op, leftValues, rightValues);
593
594 let [hash, args] = (0, _index2.hashCall)(op, left, right);
595 let Constructor = _index.Value.isTypeCompatibleWith(resultTypes.getType(), _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue;
596 let operationDescriptor = (0, _generator.createOperationDescriptor)("LOGICAL_EXPRESSION", {
597 op
598 });
599 let result = new Constructor(realm, resultTypes, resultValues, hash, args, operationDescriptor);
600 result.kind = op;
601 result.expressionLocation = loc;
602 if (doNotSimplify) return result;
603 return isCondition ? realm.simplifyAndRefineAbstractCondition(result) : realm.simplifyAndRefineAbstractValue(result);
604 }
605
606 static createFromConditionalOp(realm, condition, left, right, loc, isCondition, doNotSimplify) {
607 if (left === right) {
608 return left || realm.intrinsics.undefined;
609 }
610
611 if (!condition.mightNotBeTrue()) return left || realm.intrinsics.undefined;
612 if (!condition.mightNotBeFalse()) return right || realm.intrinsics.undefined;
613
614 let types = _index3.TypesDomain.joinValues(left, right);
615
616 if (types.getType() === _index.NullValue) return realm.intrinsics.null;
617 if (types.getType() === _index.UndefinedValue) return realm.intrinsics.undefined;
618
619 let values = _index3.ValuesDomain.joinValues(realm, left, right);
620
621 let [hash, args] = (0, _index2.hashTernary)(condition, left || realm.intrinsics.undefined, right || realm.intrinsics.undefined);
622 let Constructor = _index.Value.isTypeCompatibleWith(types.getType(), _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue;
623 let operationDescriptor = (0, _generator.createOperationDescriptor)("CONDITIONAL_EXPRESSION");
624 let result = new Constructor(realm, types, values, hash, args, operationDescriptor, {
625 kind: "conditional"
626 });
627 result.expressionLocation = loc;
628 if (left) result.mightBeEmpty = left.mightHaveBeenDeleted();
629 if (right && !result.mightBeEmpty) result.mightBeEmpty = right.mightHaveBeenDeleted();
630 if (doNotSimplify || result.mightBeEmpty) return result;
631 return isCondition ? realm.simplifyAndRefineAbstractCondition(result) : realm.simplifyAndRefineAbstractValue(result);
632 }
633
634 static createFromUnaryOp(realm, op, operand, prefix, loc, isCondition, doNotSimplify) {
635 (0, _invariant.default)(op !== "delete" && op !== "++" && op !== "--"); // The operation must be pure
636
637 let resultTypes = _index3.TypesDomain.unaryOp(op, new _index3.TypesDomain(operand.getType()));
638
639 let resultValues = _index3.ValuesDomain.unaryOp(realm, op, operand.values);
640
641 let operationDescriptor = (0, _generator.createOperationDescriptor)("UNARY_EXPRESSION", {
642 op,
643 prefix
644 });
645 let result = new AbstractValue(realm, resultTypes, resultValues, (0, _index2.hashUnary)(op, operand), [operand], operationDescriptor);
646 result.kind = op;
647 result.expressionLocation = loc;
648 if (doNotSimplify) return result;
649 return isCondition ? realm.simplifyAndRefineAbstractCondition(result) : realm.simplifyAndRefineAbstractValue(result);
650 }
651 /* Note that the template is parameterized by the names A, B, C and so on.
652 When the abstract value is serialized, the serialized operations are substituted
653 for the corresponding parameters and the resulting template is parsed into an AST subtree
654 that is incorporated into the AST produced by the serializer. */
655
656
657 static createFromTemplate(realm, template, resultType, operands, kindSuffix, loc) {
658 let kind = AbstractValue.makeKind("template", kindSuffix);
659 let resultTypes = new _index3.TypesDomain(resultType);
660 let resultValues = _index3.ValuesDomain.topVal;
661 let hash;
662 [hash, operands] = (0, _index2.hashCall)(kind, ...operands);
663 let Constructor = _index.Value.isTypeCompatibleWith(resultType, _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue;
664 let labels = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
665 (0, _invariant.default)(labels.length >= operands.length);
666 let operationDescriptor = (0, _generator.createOperationDescriptor)("ABSTRACT_FROM_TEMPLATE", {
667 template
668 });
669 let result = new Constructor(realm, resultTypes, resultValues, hash, operands, operationDescriptor);
670 result.kind = kind;
671 result.expressionLocation = loc || realm.currentLocation;
672 return result;
673 }
674
675 static createFromType(realm, resultType, kind, operands) {
676 let types = new _index3.TypesDomain(resultType);
677 let Constructor = _index.Value.isTypeCompatibleWith(resultType, _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue;
678 let [hash, args] = (0, _index2.hashCall)(resultType.name + (kind || ""), ...(operands || []));
679 if (resultType === _index.ObjectValue) hash = ++realm.objectCount;
680 let result = new Constructor(realm, types, _index3.ValuesDomain.topVal, hash, args);
681 if (kind) result.kind = kind;
682 result.expressionLocation = realm.currentLocation;
683 return result;
684 }
685 /* Emits a declaration for an identifier into the generator at the current point in time
686 and initializes it with an expression constructed from the given template.
687 Returns an abstract value that refers to the newly declared identifier.
688 Note that the template must generate an expression which has no side-effects
689 on the prepack state. It is assumed, however, that there could be side-effects
690 on the native state unless the isPure option is specified. */
691
692
693 static createTemporalFromTemplate(realm, template, resultType, operands, optionalArgs) {
694 (0, _invariant.default)(resultType !== _index.UndefinedValue);
695 let temp = AbstractValue.createFromTemplate(realm, template, resultType, operands, "");
696 let types = temp.types;
697 let values = temp.values;
698 let args = temp.args;
699 (0, _invariant.default)(realm.generator !== undefined);
700 (0, _invariant.default)(temp.operationDescriptor !== undefined);
701 return realm.generator.deriveAbstract(types, values, args, temp.operationDescriptor, optionalArgs);
702 }
703
704 static createFromBuildFunction(realm, resultType, args, operationDescriptor, optionalArgs) {
705 let types = new _index3.TypesDomain(resultType);
706 let values = _index3.ValuesDomain.topVal;
707 let Constructor = _index.Value.isTypeCompatibleWith(resultType, _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue;
708 let kind = optionalArgs && optionalArgs.kind || "build function";
709 let hash;
710 [hash, args] = (0, _index2.hashCall)(kind, ...args);
711 let result = new Constructor(realm, types, values, hash, args, operationDescriptor);
712 result.kind = kind;
713 return result;
714 }
715
716 static createTemporalFromBuildFunction(realm, resultType, args, operationDescriptor, optionalArgs) {
717 let types = new _index3.TypesDomain(resultType);
718 let values = _index3.ValuesDomain.topVal;
719 (0, _invariant.default)(realm.generator !== undefined);
720
721 if (resultType === _index.UndefinedValue) {
722 return realm.generator.emitVoidExpression(types, values, args, operationDescriptor);
723 } else {
724 return realm.generator.deriveAbstract(types, values, args, operationDescriptor, optionalArgs);
725 }
726 } // Creates a union of an abstract value with one or more concrete values.
727 // The operation descriptor for the abstract values becomes the operation descriptor for the union.
728 // Use this only to allow instrinsic abstract objects to be null and/or undefined.
729
730
731 static createAbstractConcreteUnion(realm, ...elements) {
732 let concreteValues = elements.filter(e => e instanceof _index.ConcreteValue);
733 (0, _invariant.default)(concreteValues.length > 0 && concreteValues.length === elements.length - 1);
734 let concreteSet = new Set(concreteValues);
735 let abstractValue = elements.find(e => e instanceof AbstractValue);
736 (0, _invariant.default)(abstractValue instanceof AbstractValue);
737 let values;
738
739 if (!abstractValue.values.isTop()) {
740 abstractValue.values.getElements().forEach(v => concreteSet.add(v));
741 values = new _index3.ValuesDomain(concreteSet);
742 } else {
743 values = _index3.ValuesDomain.topVal;
744 }
745
746 let types = _index3.TypesDomain.topVal;
747 let [hash, operands] = (0, _index2.hashCall)("abstractConcreteUnion", abstractValue, ...concreteValues);
748 let result = new AbstractValue(realm, types, values, hash, operands, (0, _generator.createOperationDescriptor)("SINGLE_ARG"), {
749 kind: "abstractConcreteUnion"
750 });
751 result.expressionLocation = realm.currentLocation;
752 return result;
753 }
754
755 static createFromWidenedProperty(realm, resultTemplate, args, operationDescriptor) {
756 let types = resultTemplate.types;
757 let values = resultTemplate.values;
758 let [hash] = (0, _index2.hashCall)("widened property", ...args);
759 let Constructor = _index.Value.isTypeCompatibleWith(types.getType(), _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue;
760 let result = new Constructor(realm, types, values, hash, args, operationDescriptor);
761 result.kind = "widened property";
762 result.mightBeEmpty = resultTemplate.mightBeEmpty;
763 result.expressionLocation = resultTemplate.expressionLocation;
764 return result;
765 }
766
767 static createFromWidening(realm, value1, value2) {
768 // todo: #1174 look at kind and figure out much narrower widenings
769 let types = _index3.TypesDomain.joinValues(value1, value2);
770
771 let values = _index3.ValuesDomain.topVal;
772 let [hash] = (0, _index2.hashCall)("widened");
773 let Constructor = _index.Value.isTypeCompatibleWith(types.getType(), _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue;
774 let result = new Constructor(realm, types, values, hash, []);
775 result.kind = "widened";
776 result.mightBeEmpty = value1.mightHaveBeenDeleted() || value2.mightHaveBeenDeleted();
777 result.expressionLocation = value1.expressionLocation;
778 return result;
779 }
780
781 static createAbstractArgument(realm, name, location, type = _index.Value, shape = undefined) {
782 if (!realm.useAbstractInterpretation) {
783 throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "realm is not partial");
784 }
785
786 let realmPreludeGenerator = realm.preludeGenerator;
787 (0, _invariant.default)(realmPreludeGenerator);
788 let types = new _index3.TypesDomain(type);
789 let values = _index3.ValuesDomain.topVal;
790 let Constructor = _index.Value.isTypeCompatibleWith(type, _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue;
791 let operationDescriptor = (0, _generator.createOperationDescriptor)("IDENTIFIER", {
792 id: name
793 });
794 let result = new Constructor(realm, types, values, 943586754858 + (0, _index2.hashString)(name), [], operationDescriptor);
795 result.kind = AbstractValue.makeKind("abstractCounted", (realm.objectCount++).toString()); // need not be an object, but must be unique
796
797 result.expressionLocation = location;
798 result.shape = shape;
799 return result;
800 }
801
802 static generateErrorInformationForAbstractVal(val) {
803 let names = [];
804 val.addSourceNamesTo(names);
805 return `abstract value${names.length > 1 ? "s" : ""} ${names.join(" and ")}`;
806 }
807
808 static describe(val, propertyName) {
809 let realm = val.$Realm;
810 let identity;
811 if (val === realm.$GlobalObject) identity = "global";else if (val instanceof AbstractValue) {
812 identity = this.generateErrorInformationForAbstractVal(val);
813 } else identity = val.intrinsicName || "(some value)";
814 let source_locations = [];
815 if (val instanceof AbstractValue) val.addSourceLocationsTo(source_locations);
816 let location;
817
818 if (propertyName instanceof _index.SymbolValue) {
819 let desc = propertyName.$Description;
820
821 if (desc) {
822 location = `at symbol [${desc.throwIfNotConcreteString().value}]`;
823 } else {
824 location = `at symbol [${"(no description)"}]`;
825 }
826 } else if (propertyName instanceof _index.StringValue) location = `at ${propertyName.value}`;else if (typeof propertyName === "string") location = `at ${propertyName}`;else location = source_locations.length === 0 ? "" : `at ${source_locations.join("\n")}`;
827
828 return `${identity} ${location}`;
829 }
830
831 static reportIntrospectionError(val, propertyName) {
832 let message = "";
833 if (!val.$Realm.suppressDiagnostics) message = `This operation is not yet supported on ${AbstractValue.describe(val, propertyName)}`;
834 let realm = val.$Realm;
835 return realm.reportIntrospectionError(message);
836 }
837
838 static createAbstractObject(realm, name, templateOrShape) {
839 let value;
840
841 if (templateOrShape === undefined) {
842 templateOrShape = new _index.ObjectValue(realm, realm.intrinsics.ObjectPrototype);
843 }
844
845 value = AbstractValue.createFromTemplate(realm, (0, _builder.default)(name), _index.ObjectValue, [], name);
846
847 if (!realm.isNameStringUnique(name)) {
848 value.hashValue = ++realm.objectCount;
849 } else {
850 realm.saveNameString(name);
851 }
852
853 value.intrinsicName = name;
854
855 if (templateOrShape instanceof _index.ObjectValue) {
856 templateOrShape.makePartial();
857 templateOrShape.makeSimple();
858 value.values = new _index3.ValuesDomain(new Set([templateOrShape]));
859 realm.rebuildNestedProperties(value, name);
860 } else {
861 value.shape = templateOrShape;
862 }
863
864 (0, _invariant.default)(value instanceof _index.AbstractObjectValue);
865 return value;
866 }
867
868 static makeKind(prefix, suffix) {
869 return `${prefix}:${suffix}`;
870 }
871
872 static createTemporalObjectAssign(realm, to, sources) {
873 // Tell serializer that it may add properties to to only after temporalTo has been emitted
874 let temporalArgs = [to, ...sources];
875 let preludeGenerator = realm.preludeGenerator;
876 (0, _invariant.default)(preludeGenerator !== undefined);
877 let temporalTo = AbstractValue.createTemporalFromBuildFunction(realm, _index.ObjectValue, temporalArgs, (0, _generator.createOperationDescriptor)("OBJECT_ASSIGN"), {
878 skipInvariant: true,
879 mutatesOnly: [to]
880 });
881 (0, _invariant.default)(temporalTo instanceof _index.AbstractObjectValue);
882
883 if (to instanceof _index.AbstractObjectValue) {
884 temporalTo.values = to.values;
885 } else {
886 (0, _invariant.default)(to instanceof _index.ObjectValue);
887 temporalTo.values = new _index3.ValuesDomain(to);
888 }
889
890 to.temporalAlias = temporalTo;
891 return temporalTo;
892 }
893
894}
895
896exports.default = AbstractValue;
897//# sourceMappingURL=AbstractValue.js.map
\No newline at end of file