1 | "use strict";
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | exports.default = void 0;
|
7 |
|
8 | var _errors = require("../errors.js");
|
9 |
|
10 | var _generator = require("../utils/generator.js");
|
11 |
|
12 | var _PreludeGenerator = require("../utils/PreludeGenerator.js");
|
13 |
|
14 | var _builder = _interopRequireDefault(require("../utils/builder.js"));
|
15 |
|
16 | var _index = require("./index.js");
|
17 |
|
18 | var _index2 = require("../methods/index.js");
|
19 |
|
20 | var _index3 = require("../domains/index.js");
|
21 |
|
22 | var _invariant = _interopRequireDefault(require("../invariant.js"));
|
23 |
|
24 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 | class 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);
|
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;
|
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 | }
|
156 |
|
157 |
|
158 | implies(val) {
|
159 | this._checkAbstractValueImpliesCounter();
|
160 |
|
161 | if (this.equals(val)) return true;
|
162 |
|
163 | if (!this.mightNotBeFalse()) return true;
|
164 |
|
165 | if (!val.mightNotBeTrue()) return true;
|
166 |
|
167 | if (val instanceof AbstractValue) {
|
168 |
|
169 |
|
170 | if (val.kind === "||") {
|
171 | let [x, y] = val.args;
|
172 | return this.implies(x) || this.implies(y);
|
173 | }
|
174 |
|
175 |
|
176 | if (val.kind === "!") {
|
177 | let [y] = val.args;
|
178 | (0, _invariant.default)(y instanceof AbstractValue);
|
179 | return y.impliesNot(this);
|
180 | }
|
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 | }
|
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;
|
203 |
|
204 | if (!x.mightNotBeTrue() && !y.mightNotBeFalse()) {
|
205 | return c.equals(val);
|
206 | }
|
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 | }
|
220 |
|
221 |
|
222 | if (!y.mightNotBeFalse()) {
|
223 | if (c.implies(val)) return true;
|
224 | if (x.implies(val)) return true;
|
225 | }
|
226 | }
|
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 |
|
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 | }
|
251 |
|
252 |
|
253 | impliesNot(val) {
|
254 | if (this.equals(val)) return false;
|
255 |
|
256 | if (!this.mightNotBeFalse()) return true;
|
257 |
|
258 | if (!val.mightNotBeFalse()) return true;
|
259 |
|
260 | if (val instanceof AbstractValue) {
|
261 |
|
262 | if (this.kind === "!") {
|
263 | let [x] = this.args;
|
264 | (0, _invariant.default)(x instanceof AbstractValue);
|
265 |
|
266 | if (x.kind === "!") {
|
267 |
|
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;
|
275 |
|
276 | return val.implies(x);
|
277 | }
|
278 |
|
279 | if (this.kind === "conditional") {
|
280 | let [c, x, y] = this.args;
|
281 |
|
282 | if (!x.mightNotBeFalse() && !y.mightNotBeTrue()) {
|
283 | return c.equals(val);
|
284 | }
|
285 | }
|
286 | }
|
287 |
|
288 | return false;
|
289 | }
|
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 !== "--");
|
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 | |
652 |
|
653 |
|
654 |
|
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 | |
686 |
|
687 |
|
688 |
|
689 |
|
690 |
|
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 | }
|
727 |
|
728 |
|
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 |
|
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());
|
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 |
|
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 |
|
896 | exports.default = AbstractValue;
|
897 |
|
\ | No newline at end of file |