first commit
This commit is contained in:
812
build/node_modules/prepack/lib/values/AbstractValue.js
generated
vendored
Normal file
812
build/node_modules/prepack/lib/values/AbstractValue.js
generated
vendored
Normal file
@@ -0,0 +1,812 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
||||
|
||||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
||||
|
||||
var _errors = require("../errors.js");
|
||||
|
||||
var _generator = require("../utils/generator.js");
|
||||
|
||||
var _index = require("./index.js");
|
||||
|
||||
var _index2 = require("../methods/index.js");
|
||||
|
||||
var _index3 = require("../domains/index.js");
|
||||
|
||||
var _invariant = require("../invariant.js");
|
||||
|
||||
var _invariant2 = _interopRequireDefault(_invariant);
|
||||
|
||||
var _babelTypes = require("babel-types");
|
||||
|
||||
var t = _interopRequireWildcard(_babelTypes);
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
||||
|
||||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
|
||||
* Copyright (c) 2017-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
var AbstractValue = function (_Value) {
|
||||
_inherits(AbstractValue, _Value);
|
||||
|
||||
function AbstractValue(realm, types, values, hashValue, args, buildNode, optionalArgs) {
|
||||
_classCallCheck(this, AbstractValue);
|
||||
|
||||
(0, _invariant2.default)(realm.useAbstractInterpretation);
|
||||
|
||||
var _this = _possibleConstructorReturn(this, (AbstractValue.__proto__ || Object.getPrototypeOf(AbstractValue)).call(this, realm, optionalArgs ? optionalArgs.intrinsicName : undefined));
|
||||
|
||||
(0, _invariant2.default)(buildNode instanceof Function || args.length === 0);
|
||||
(0, _invariant2.default)(!_index.Value.isTypeCompatibleWith(types.getType(), _index.ObjectValue) || _this instanceof _index.AbstractObjectValue);
|
||||
(0, _invariant2.default)(types.getType() !== _index.NullValue && types.getType() !== _index.UndefinedValue);
|
||||
_this.types = types;
|
||||
_this.values = values;
|
||||
_this.mightBeEmpty = false;
|
||||
_this._buildNode = buildNode;
|
||||
_this.args = args;
|
||||
_this.hashValue = hashValue;
|
||||
_this.kind = optionalArgs ? optionalArgs.kind : undefined;
|
||||
return _this;
|
||||
}
|
||||
|
||||
_createClass(AbstractValue, [{
|
||||
key: "addSourceLocationsTo",
|
||||
value: function addSourceLocationsTo(locations) {
|
||||
var seenValues = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Set();
|
||||
|
||||
if (seenValues.has(this)) return;
|
||||
seenValues.add(this);
|
||||
if (this._buildNode && !(this._buildNode instanceof Function)) {
|
||||
if (this._buildNode.loc) locations.push(this._buildNode.loc);
|
||||
}
|
||||
var _iteratorNormalCompletion = true;
|
||||
var _didIteratorError = false;
|
||||
var _iteratorError = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator = this.args[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||
var val = _step.value;
|
||||
|
||||
if (val instanceof AbstractValue) val.addSourceLocationsTo(locations, seenValues);
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError = true;
|
||||
_iteratorError = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion && _iterator.return) {
|
||||
_iterator.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError) {
|
||||
throw _iteratorError;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
key: "addSourceNamesTo",
|
||||
value: function addSourceNamesTo(names) {
|
||||
var gen = this.$Realm.preludeGenerator;
|
||||
function add_intrinsic(name) {
|
||||
if (name.startsWith("_$")) {
|
||||
if (gen === undefined) return;
|
||||
add_args(gen.derivedIds.get(name));
|
||||
} else if (names.indexOf(name) < 0) {
|
||||
names.push(name);
|
||||
}
|
||||
}
|
||||
function add_args(args) {
|
||||
if (args === undefined) return;
|
||||
var _iteratorNormalCompletion2 = true;
|
||||
var _didIteratorError2 = false;
|
||||
var _iteratorError2 = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator2 = args[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
||||
var val = _step2.value;
|
||||
|
||||
if (val.intrinsicName) {
|
||||
add_intrinsic(val.intrinsicName);
|
||||
} else if (val instanceof AbstractValue) {
|
||||
val.addSourceNamesTo(names);
|
||||
} else if (val instanceof _index.StringValue) {
|
||||
if (val.value.startsWith("__")) {
|
||||
names.push(val.value.slice(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError2 = true;
|
||||
_iteratorError2 = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion2 && _iterator2.return) {
|
||||
_iterator2.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError2) {
|
||||
throw _iteratorError2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.intrinsicName) {
|
||||
add_intrinsic(this.intrinsicName);
|
||||
}
|
||||
add_args(this.args);
|
||||
}
|
||||
}, {
|
||||
key: "buildNode",
|
||||
value: function buildNode(args) {
|
||||
var buildNode = this.getBuildNode();
|
||||
return buildNode instanceof Function ? buildNode(args) : buildNode;
|
||||
}
|
||||
}, {
|
||||
key: "equals",
|
||||
value: function equals(x) {
|
||||
if (x instanceof _index.ConcreteValue) return false;
|
||||
var thisArgs = this.args;
|
||||
var n = thisArgs.length;
|
||||
|
||||
var argsAreEqual = function argsAreEqual() {
|
||||
(0, _invariant2.default)(x instanceof AbstractValue);
|
||||
var xArgs = x.args;
|
||||
var m = xArgs.length;
|
||||
(0, _invariant2.default)(n === m); // Will be true if kinds are the same. Caller should see to it.
|
||||
for (var i = 0; i < n; i++) {
|
||||
var a = thisArgs[i];
|
||||
var b = xArgs[i];
|
||||
if (!a.equals(b)) return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
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());
|
||||
}
|
||||
}, {
|
||||
key: "getBuildNode",
|
||||
value: function getBuildNode() {
|
||||
(0, _invariant2.default)(this._buildNode);
|
||||
return this._buildNode;
|
||||
}
|
||||
}, {
|
||||
key: "getHash",
|
||||
value: function getHash() {
|
||||
return this.hashValue;
|
||||
}
|
||||
}, {
|
||||
key: "getType",
|
||||
value: function getType() {
|
||||
return this.types.getType();
|
||||
}
|
||||
}, {
|
||||
key: "getIdentifier",
|
||||
value: function getIdentifier() {
|
||||
(0, _invariant2.default)(this.hasIdentifier());
|
||||
return this._buildNode;
|
||||
}
|
||||
}, {
|
||||
key: "hasIdentifier",
|
||||
value: function hasIdentifier() {
|
||||
return this._buildNode && this._buildNode.type === "Identifier";
|
||||
}
|
||||
|
||||
// this => val. A false value does not imply that !(this => val).
|
||||
|
||||
}, {
|
||||
key: "implies",
|
||||
value: function implies(val) {
|
||||
if (this.equals(val)) return true; // x => x regardless of its value
|
||||
if (!this.mightNotBeFalse()) return true; // false => val
|
||||
if (!val.mightNotBeTrue()) return true; // x => true regardless of the value of x
|
||||
if (val instanceof AbstractValue) {
|
||||
// Neither this (x) nor val (y) is a known value, so we need to do some reasoning based on the structure
|
||||
// x => !y if y => !x
|
||||
if (val.kind === "!") {
|
||||
var _val$args = _slicedToArray(val.args, 1),
|
||||
y = _val$args[0];
|
||||
|
||||
(0, _invariant2.default)(y instanceof AbstractValue);
|
||||
return y.impliesNot(this);
|
||||
}
|
||||
// x => x !== null && x !== undefined
|
||||
if (val.kind === "!==") {
|
||||
var _val$args2 = _slicedToArray(val.args, 2),
|
||||
x = _val$args2[0],
|
||||
_y = _val$args2[1];
|
||||
|
||||
if (this.implies(x)) return _y instanceof _index.NullValue || _y instanceof _index.UndefinedValue;
|
||||
if (this.implies(_y)) return x instanceof _index.NullValue || x instanceof _index.UndefinedValue;
|
||||
}
|
||||
// !!x => x
|
||||
if (this.kind === "!") {
|
||||
var _args = _slicedToArray(this.args, 1),
|
||||
nx = _args[0];
|
||||
|
||||
(0, _invariant2.default)(nx instanceof AbstractValue);
|
||||
if (nx.kind === "!") {
|
||||
var _nx$args = _slicedToArray(nx.args, 1),
|
||||
_x2 = _nx$args[0];
|
||||
|
||||
(0, _invariant2.default)(_x2 instanceof AbstractValue);
|
||||
return _x2.equals(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// this => !val. A false value does not imply that !(this => !val).
|
||||
|
||||
}, {
|
||||
key: "impliesNot",
|
||||
value: function impliesNot(val) {
|
||||
if (this.equals(val)) return false; // x => x regardless of its value, hence x => !val is false
|
||||
if (!this.mightNotBeFalse()) return true; // false => !val
|
||||
if (!val.mightNotBeFalse()) return true; // x => !false regardless of the value of x
|
||||
if (val instanceof AbstractValue) {
|
||||
// !x => !y if y => x
|
||||
if (this.kind === "!") {
|
||||
var _args2 = _slicedToArray(this.args, 1),
|
||||
x = _args2[0];
|
||||
|
||||
return val.implies(x);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// todo: abstract values should never be of type UndefinedValue or NullValue, assert this
|
||||
|
||||
}, {
|
||||
key: "mightBeFalse",
|
||||
value: function mightBeFalse() {
|
||||
var valueType = this.getType();
|
||||
if (valueType === _index.UndefinedValue) return true;
|
||||
if (valueType === _index.NullValue) return true;
|
||||
if (valueType === _index.SymbolValue) return false;
|
||||
if (_index.Value.isTypeCompatibleWith(valueType, _index.ObjectValue)) return false;
|
||||
if (this.values.isTop()) return true;
|
||||
return this.values.mightBeFalse();
|
||||
}
|
||||
}, {
|
||||
key: "mightNotBeFalse",
|
||||
value: function mightNotBeFalse() {
|
||||
var valueType = this.getType();
|
||||
if (valueType === _index.UndefinedValue) return false;
|
||||
if (valueType === _index.NullValue) return false;
|
||||
if (valueType === _index.SymbolValue) return true;
|
||||
if (_index.Value.isTypeCompatibleWith(valueType, _index.ObjectValue)) return true;
|
||||
if (this.values.isTop()) return true;
|
||||
return this.values.mightNotBeFalse();
|
||||
}
|
||||
}, {
|
||||
key: "mightBeNull",
|
||||
value: function mightBeNull() {
|
||||
var valueType = this.getType();
|
||||
if (valueType === _index.NullValue) return true;
|
||||
if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return false;
|
||||
if (this.values.isTop()) return true;
|
||||
return this.values.includesValueOfType(_index.NullValue);
|
||||
}
|
||||
}, {
|
||||
key: "mightNotBeNull",
|
||||
value: function mightNotBeNull() {
|
||||
var valueType = this.getType();
|
||||
if (valueType === _index.NullValue) return false;
|
||||
if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return true;
|
||||
if (this.values.isTop()) return true;
|
||||
return this.values.includesValueNotOfType(_index.NullValue);
|
||||
}
|
||||
}, {
|
||||
key: "mightBeNumber",
|
||||
value: function mightBeNumber() {
|
||||
var valueType = this.getType();
|
||||
if (_index.Value.isTypeCompatibleWith(valueType, _index.NumberValue)) return true;
|
||||
if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return false;
|
||||
if (this.values.isTop()) return true;
|
||||
return this.values.includesValueOfType(_index.NumberValue);
|
||||
}
|
||||
}, {
|
||||
key: "mightNotBeNumber",
|
||||
value: function mightNotBeNumber() {
|
||||
var valueType = this.getType();
|
||||
if (_index.Value.isTypeCompatibleWith(valueType, _index.NumberValue)) return false;
|
||||
if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return true;
|
||||
if (this.values.isTop()) return true;
|
||||
return this.values.includesValueNotOfType(_index.NumberValue);
|
||||
}
|
||||
}, {
|
||||
key: "mightNotBeObject",
|
||||
value: function mightNotBeObject() {
|
||||
var valueType = this.getType();
|
||||
if (_index.Value.isTypeCompatibleWith(valueType, _index.PrimitiveValue)) return true;
|
||||
if (_index.Value.isTypeCompatibleWith(valueType, _index.ObjectValue)) return false;
|
||||
if (this.values.isTop()) return true;
|
||||
return this.values.includesValueNotOfType(_index.ObjectValue);
|
||||
}
|
||||
}, {
|
||||
key: "mightBeObject",
|
||||
value: function mightBeObject() {
|
||||
var valueType = this.getType();
|
||||
if (_index.Value.isTypeCompatibleWith(valueType, _index.PrimitiveValue)) return false;
|
||||
if (_index.Value.isTypeCompatibleWith(valueType, _index.ObjectValue)) return true;
|
||||
if (this.values.isTop()) return true;
|
||||
return this.values.includesValueOfType(_index.ObjectValue);
|
||||
}
|
||||
}, {
|
||||
key: "mightBeString",
|
||||
value: function mightBeString() {
|
||||
var valueType = this.getType();
|
||||
if (valueType === _index.StringValue) return true;
|
||||
if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return false;
|
||||
if (this.values.isTop()) return true;
|
||||
return this.values.includesValueOfType(_index.StringValue);
|
||||
}
|
||||
}, {
|
||||
key: "mightNotBeString",
|
||||
value: function mightNotBeString() {
|
||||
var valueType = this.getType();
|
||||
if (valueType === _index.StringValue) return false;
|
||||
if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return true;
|
||||
if (this.values.isTop()) return true;
|
||||
return this.values.includesValueNotOfType(_index.StringValue);
|
||||
}
|
||||
}, {
|
||||
key: "mightBeUndefined",
|
||||
value: function mightBeUndefined() {
|
||||
var valueType = this.getType();
|
||||
if (valueType === _index.UndefinedValue) return true;
|
||||
if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return false;
|
||||
if (this.values.isTop()) return true;
|
||||
return this.values.includesValueOfType(_index.UndefinedValue);
|
||||
}
|
||||
}, {
|
||||
key: "mightNotBeUndefined",
|
||||
value: function mightNotBeUndefined() {
|
||||
var valueType = this.getType();
|
||||
if (valueType === _index.UndefinedValue) return false;
|
||||
if (valueType !== _index.PrimitiveValue && valueType !== _index.Value) return true;
|
||||
if (this.values.isTop()) return true;
|
||||
return this.values.includesValueNotOfType(_index.UndefinedValue);
|
||||
}
|
||||
}, {
|
||||
key: "mightHaveBeenDeleted",
|
||||
value: function mightHaveBeenDeleted() {
|
||||
return this.mightBeEmpty;
|
||||
}
|
||||
}, {
|
||||
key: "promoteEmptyToUndefined",
|
||||
value: function promoteEmptyToUndefined() {
|
||||
if (this.values.isTop()) return this;
|
||||
if (!this.mightBeEmpty) return this;
|
||||
var cond = AbstractValue.createFromBinaryOp(this.$Realm, "===", this, this.$Realm.intrinsics.empty);
|
||||
var result = AbstractValue.createFromConditionalOp(this.$Realm, cond, this.$Realm.intrinsics.undefined, this);
|
||||
if (result instanceof AbstractValue) result.values = this.values.promoteEmptyToUndefined();
|
||||
return result;
|
||||
}
|
||||
}, {
|
||||
key: "throwIfNotConcrete",
|
||||
value: function throwIfNotConcrete() {
|
||||
AbstractValue.reportIntrospectionError(this);
|
||||
throw new _errors.FatalError();
|
||||
}
|
||||
}, {
|
||||
key: "throwIfNotConcreteNumber",
|
||||
value: function throwIfNotConcreteNumber() {
|
||||
AbstractValue.reportIntrospectionError(this);
|
||||
throw new _errors.FatalError();
|
||||
}
|
||||
}, {
|
||||
key: "throwIfNotConcreteString",
|
||||
value: function throwIfNotConcreteString() {
|
||||
AbstractValue.reportIntrospectionError(this);
|
||||
throw new _errors.FatalError();
|
||||
}
|
||||
}, {
|
||||
key: "throwIfNotConcreteBoolean",
|
||||
value: function throwIfNotConcreteBoolean() {
|
||||
AbstractValue.reportIntrospectionError(this);
|
||||
throw new _errors.FatalError();
|
||||
}
|
||||
}, {
|
||||
key: "throwIfNotConcreteSymbol",
|
||||
value: function throwIfNotConcreteSymbol() {
|
||||
AbstractValue.reportIntrospectionError(this);
|
||||
throw new _errors.FatalError();
|
||||
}
|
||||
}, {
|
||||
key: "throwIfNotConcreteObject",
|
||||
value: function throwIfNotConcreteObject() {
|
||||
AbstractValue.reportIntrospectionError(this);
|
||||
throw new _errors.FatalError();
|
||||
}
|
||||
}, {
|
||||
key: "throwIfNotConcretePrimitive",
|
||||
value: function throwIfNotConcretePrimitive() {
|
||||
AbstractValue.reportIntrospectionError(this);
|
||||
throw new _errors.FatalError();
|
||||
}
|
||||
}, {
|
||||
key: "throwIfNotObject",
|
||||
value: function throwIfNotObject() {
|
||||
(0, _invariant2.default)(!(this instanceof _index.AbstractObjectValue));
|
||||
AbstractValue.reportIntrospectionError(this);
|
||||
throw new _errors.FatalError();
|
||||
}
|
||||
}], [{
|
||||
key: "createFromBinaryOp",
|
||||
value: function createFromBinaryOp(realm, op, left, right, loc, kind) {
|
||||
var leftTypes = void 0,
|
||||
leftValues = void 0;
|
||||
if (left instanceof AbstractValue) {
|
||||
leftTypes = left.types;
|
||||
leftValues = left.values;
|
||||
} else {
|
||||
leftTypes = new _index3.TypesDomain(left.getType());
|
||||
(0, _invariant2.default)(left instanceof _index.ConcreteValue);
|
||||
leftValues = new _index3.ValuesDomain(left);
|
||||
}
|
||||
|
||||
var rightTypes = void 0,
|
||||
rightValues = void 0;
|
||||
if (right instanceof AbstractValue) {
|
||||
rightTypes = right.types;
|
||||
rightValues = right.values;
|
||||
} else {
|
||||
rightTypes = new _index3.TypesDomain(right.getType());
|
||||
(0, _invariant2.default)(right instanceof _index.ConcreteValue);
|
||||
rightValues = new _index3.ValuesDomain(right);
|
||||
}
|
||||
|
||||
var resultTypes = _index3.TypesDomain.binaryOp(op, leftTypes, rightTypes);
|
||||
var resultValues = kind === "template for property name condition" ? _index3.ValuesDomain.topVal : _index3.ValuesDomain.binaryOp(realm, op, leftValues, rightValues);
|
||||
|
||||
var _ref = kind === undefined ? (0, _index2.hashBinary)(op, left, right) : (0, _index2.hashCall)(kind, left, right),
|
||||
_ref2 = _slicedToArray(_ref, 2),
|
||||
hash = _ref2[0],
|
||||
args = _ref2[1];
|
||||
|
||||
var result = new AbstractValue(realm, resultTypes, resultValues, hash, args, function (_ref3) {
|
||||
var _ref4 = _slicedToArray(_ref3, 2),
|
||||
x = _ref4[0],
|
||||
y = _ref4[1];
|
||||
|
||||
return t.binaryExpression(op, x, y);
|
||||
});
|
||||
result.kind = kind || op;
|
||||
result.expressionLocation = loc;
|
||||
return result;
|
||||
}
|
||||
}, {
|
||||
key: "createFromLogicalOp",
|
||||
value: function createFromLogicalOp(realm, op, left, right, loc) {
|
||||
var leftTypes = void 0,
|
||||
leftValues = void 0;
|
||||
if (left instanceof AbstractValue) {
|
||||
leftTypes = left.types;
|
||||
leftValues = left.values;
|
||||
} else {
|
||||
leftTypes = new _index3.TypesDomain(left.getType());
|
||||
(0, _invariant2.default)(left instanceof _index.ConcreteValue);
|
||||
leftValues = new _index3.ValuesDomain(left);
|
||||
}
|
||||
|
||||
var rightTypes = void 0,
|
||||
rightValues = void 0;
|
||||
if (right instanceof AbstractValue) {
|
||||
rightTypes = right.types;
|
||||
rightValues = right.values;
|
||||
} else {
|
||||
rightTypes = new _index3.TypesDomain(right.getType());
|
||||
(0, _invariant2.default)(right instanceof _index.ConcreteValue);
|
||||
rightValues = new _index3.ValuesDomain(right);
|
||||
}
|
||||
|
||||
var resultTypes = _index3.TypesDomain.logicalOp(op, leftTypes, rightTypes);
|
||||
var resultValues = _index3.ValuesDomain.logicalOp(realm, op, leftValues, rightValues);
|
||||
|
||||
var _hashCall = (0, _index2.hashCall)(op, left, right),
|
||||
_hashCall2 = _slicedToArray(_hashCall, 2),
|
||||
hash = _hashCall2[0],
|
||||
args = _hashCall2[1];
|
||||
|
||||
var Constructor = _index.Value.isTypeCompatibleWith(resultTypes.getType(), _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue;
|
||||
var result = new Constructor(realm, resultTypes, resultValues, hash, args, function (_ref5) {
|
||||
var _ref6 = _slicedToArray(_ref5, 2),
|
||||
x = _ref6[0],
|
||||
y = _ref6[1];
|
||||
|
||||
return t.logicalExpression(op, x, y);
|
||||
});
|
||||
result.kind = op;
|
||||
result.expressionLocation = loc;
|
||||
return realm.simplifyAndRefineAbstractValue(result);
|
||||
}
|
||||
}, {
|
||||
key: "createFromConditionalOp",
|
||||
value: function createFromConditionalOp(realm, condition, left, right, loc) {
|
||||
var types = _index3.TypesDomain.joinValues(left, right);
|
||||
if (types.getType() === _index.NullValue) return realm.intrinsics.null;
|
||||
if (types.getType() === _index.UndefinedValue) return realm.intrinsics.undefined;
|
||||
var values = _index3.ValuesDomain.joinValues(realm, left, right);
|
||||
|
||||
var _hashTernary = (0, _index2.hashTernary)(condition, left || realm.intrinsics.undefined, right || realm.intrinsics.undefined),
|
||||
_hashTernary2 = _slicedToArray(_hashTernary, 2),
|
||||
hash = _hashTernary2[0],
|
||||
args = _hashTernary2[1];
|
||||
|
||||
var Constructor = _index.Value.isTypeCompatibleWith(types.getType(), _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue;
|
||||
var result = new Constructor(realm, types, values, hash, args, function (_ref7) {
|
||||
var _ref8 = _slicedToArray(_ref7, 3),
|
||||
c = _ref8[0],
|
||||
x = _ref8[1],
|
||||
y = _ref8[2];
|
||||
|
||||
return t.conditionalExpression(c, x, y);
|
||||
}, {
|
||||
kind: "conditional"
|
||||
});
|
||||
result.expressionLocation = loc;
|
||||
if (left) result.mightBeEmpty = left.mightHaveBeenDeleted();
|
||||
if (right && !result.mightBeEmpty) result.mightBeEmpty = right.mightHaveBeenDeleted();
|
||||
if (result.mightBeEmpty) return result;
|
||||
return realm.simplifyAndRefineAbstractValue(result);
|
||||
}
|
||||
}, {
|
||||
key: "createFromUnaryOp",
|
||||
value: function createFromUnaryOp(realm, op, operand, prefix, loc) {
|
||||
var resultTypes = _index3.TypesDomain.unaryOp(op);
|
||||
var resultValues = _index3.ValuesDomain.unaryOp(realm, op, operand.values);
|
||||
var result = new AbstractValue(realm, resultTypes, resultValues, (0, _index2.hashUnary)(op, operand), [operand], function (_ref9) {
|
||||
var _ref10 = _slicedToArray(_ref9, 1),
|
||||
x = _ref10[0];
|
||||
|
||||
return t.unaryExpression(op, x, prefix);
|
||||
});
|
||||
result.kind = op;
|
||||
result.expressionLocation = loc;
|
||||
return realm.simplifyAndRefineAbstractValue(result);
|
||||
}
|
||||
|
||||
/* Note that the template is parameterized by the names A, B, C and so on.
|
||||
When the abstract value is serialized, the serialized operations are substituted
|
||||
for the corresponding parameters and the resulting template is parsed into an AST subtree
|
||||
that is incorporated into the AST produced by the serializer. */
|
||||
|
||||
}, {
|
||||
key: "createFromTemplate",
|
||||
value: function createFromTemplate(realm, template, resultType, operands, kind, loc) {
|
||||
var resultTypes = new _index3.TypesDomain(resultType);
|
||||
var resultValues = _index3.ValuesDomain.topVal;
|
||||
var hash = void 0;
|
||||
|
||||
var _hashCall3 = _index2.hashCall.apply(undefined, [kind].concat(_toConsumableArray(operands)));
|
||||
|
||||
var _hashCall4 = _slicedToArray(_hashCall3, 2);
|
||||
|
||||
hash = _hashCall4[0];
|
||||
operands = _hashCall4[1];
|
||||
|
||||
var Constructor = _index.Value.isTypeCompatibleWith(resultType, _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue;
|
||||
var labels = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
(0, _invariant2.default)(labels.length >= operands.length);
|
||||
var result = new Constructor(realm, resultTypes, resultValues, hash, operands, function (args) {
|
||||
(0, _invariant2.default)(realm.preludeGenerator !== undefined);
|
||||
var generatorArgs = {};
|
||||
var i = 0;
|
||||
var _iteratorNormalCompletion3 = true;
|
||||
var _didIteratorError3 = false;
|
||||
var _iteratorError3 = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator3 = args[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
|
||||
var arg = _step3.value;
|
||||
generatorArgs[labels.charAt(i++)] = arg;
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError3 = true;
|
||||
_iteratorError3 = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion3 && _iterator3.return) {
|
||||
_iterator3.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError3) {
|
||||
throw _iteratorError3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return template(realm.preludeGenerator)(generatorArgs);
|
||||
});
|
||||
result.kind = kind;
|
||||
result.expressionLocation = loc || realm.currentLocation;
|
||||
return result;
|
||||
}
|
||||
}, {
|
||||
key: "createFromType",
|
||||
value: function createFromType(realm, resultType, kind) {
|
||||
var types = new _index3.TypesDomain(resultType);
|
||||
var Constructor = _index.Value.isTypeCompatibleWith(resultType, _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue;
|
||||
var hash = (0, _index2.hashString)(resultType.name + (kind || ""));
|
||||
var result = new Constructor(realm, types, _index3.ValuesDomain.topVal, hash, []);
|
||||
if (kind) result.kind = kind;
|
||||
result.expressionLocation = realm.currentLocation;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Emits a declaration for an identifier into the generator at the current point in time
|
||||
and initializes it with an expression constructed from the given template.
|
||||
Returns an abstract value that refers to the newly declared identifier.
|
||||
Note that the template must generate an expression which has no side-effects
|
||||
on the prepack state. It is assumed, however, that there could be side-effects
|
||||
on the native state unless the isPure option is specified. */
|
||||
|
||||
}, {
|
||||
key: "createTemporalFromTemplate",
|
||||
value: function createTemporalFromTemplate(realm, template, resultType, operands, optionalArgs) {
|
||||
(0, _invariant2.default)(resultType !== _index.UndefinedValue);
|
||||
var temp = AbstractValue.createFromTemplate(realm, template, resultType, operands, "");
|
||||
var types = temp.types;
|
||||
var values = temp.values;
|
||||
var args = temp.args;
|
||||
var buildNode_ = temp.getBuildNode();
|
||||
(0, _invariant2.default)(realm.generator !== undefined);
|
||||
return realm.generator.derive(types, values, args, buildNode_, optionalArgs);
|
||||
}
|
||||
}, {
|
||||
key: "createTemporalFromBuildFunction",
|
||||
value: function createTemporalFromBuildFunction(realm, resultType, args, buildFunction, optionalArgs) {
|
||||
var types = new _index3.TypesDomain(resultType);
|
||||
var values = _index3.ValuesDomain.topVal;
|
||||
(0, _invariant2.default)(realm.generator !== undefined);
|
||||
if (resultType === _index.UndefinedValue) {
|
||||
return realm.generator.emitVoidExpression(types, values, args, buildFunction);
|
||||
} else {
|
||||
return realm.generator.derive(types, values, args, buildFunction, optionalArgs);
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a union of an abstract value with one or more concrete values.
|
||||
// The build node for the abstract values becomes the build node for the union.
|
||||
// Use this only to allow instrinsic abstract objects to be null and/or undefined.
|
||||
|
||||
}, {
|
||||
key: "createAbstractConcreteUnion",
|
||||
value: function createAbstractConcreteUnion(realm) {
|
||||
for (var _len = arguments.length, elements = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
||||
elements[_key - 1] = arguments[_key];
|
||||
}
|
||||
|
||||
var concreteValues = elements.filter(function (e) {
|
||||
return e instanceof _index.ConcreteValue;
|
||||
});
|
||||
(0, _invariant2.default)(concreteValues.length > 0 && concreteValues.length === elements.length - 1);
|
||||
var concreteSet = new Set(concreteValues);
|
||||
var abstractValue = elements.find(function (e) {
|
||||
return e instanceof AbstractValue;
|
||||
});
|
||||
(0, _invariant2.default)(abstractValue instanceof AbstractValue);
|
||||
var values = void 0;
|
||||
if (!abstractValue.values.isTop()) {
|
||||
abstractValue.values.getElements().forEach(function (v) {
|
||||
return concreteSet.add(v);
|
||||
});
|
||||
values = new _index3.ValuesDomain(concreteSet);
|
||||
} else {
|
||||
values = _index3.ValuesDomain.topVal;
|
||||
}
|
||||
var types = _index3.TypesDomain.topVal;
|
||||
|
||||
var _hashCall5 = _index2.hashCall.apply(undefined, ["abstractConcreteUnion"].concat(elements)),
|
||||
_hashCall6 = _slicedToArray(_hashCall5, 2),
|
||||
hash = _hashCall6[0],
|
||||
operands = _hashCall6[1];
|
||||
|
||||
var result = new AbstractValue(realm, types, values, hash, operands, abstractValue._buildNode, {
|
||||
kind: "abstractConcreteUnion"
|
||||
});
|
||||
result.expressionLocation = realm.currentLocation;
|
||||
return result;
|
||||
}
|
||||
}, {
|
||||
key: "createFromWidenedProperty",
|
||||
value: function createFromWidenedProperty(realm, resultTemplate, args, buildFunction) {
|
||||
var types = resultTemplate.types;
|
||||
var values = resultTemplate.values;
|
||||
|
||||
var _hashCall7 = _index2.hashCall.apply(undefined, ["widened property"].concat(_toConsumableArray(args))),
|
||||
_hashCall8 = _slicedToArray(_hashCall7, 1),
|
||||
hash = _hashCall8[0];
|
||||
|
||||
var Constructor = _index.Value.isTypeCompatibleWith(types.getType(), _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue;
|
||||
var result = new Constructor(realm, types, values, hash, args, buildFunction);
|
||||
result.kind = "widened property";
|
||||
result.mightBeEmpty = resultTemplate.mightBeEmpty;
|
||||
result.expressionLocation = resultTemplate.expressionLocation;
|
||||
return result;
|
||||
}
|
||||
}, {
|
||||
key: "createFromWidening",
|
||||
value: function createFromWidening(realm, value1, value2) {
|
||||
// todo: #1174 look at kind and figure out much narrower widenings
|
||||
var types = _index3.TypesDomain.joinValues(value1, value2);
|
||||
var values = _index3.ValuesDomain.topVal;
|
||||
|
||||
var _hashCall9 = (0, _index2.hashCall)("widened"),
|
||||
_hashCall10 = _slicedToArray(_hashCall9, 1),
|
||||
hash = _hashCall10[0];
|
||||
|
||||
var Constructor = _index.Value.isTypeCompatibleWith(types.getType(), _index.ObjectValue) ? _index.AbstractObjectValue : AbstractValue;
|
||||
var result = new Constructor(realm, types, values, hash, []);
|
||||
result.kind = "widened";
|
||||
result.mightBeEmpty = value1.mightHaveBeenDeleted() || value2.mightHaveBeenDeleted();
|
||||
result.expressionLocation = value1.expressionLocation;
|
||||
return result;
|
||||
}
|
||||
}, {
|
||||
key: "generateErrorInformationForAbstractVal",
|
||||
value: function generateErrorInformationForAbstractVal(val) {
|
||||
var names = [];
|
||||
val.addSourceNamesTo(names);
|
||||
if (names.length === 0) {
|
||||
val.addSourceNamesTo(names);
|
||||
}
|
||||
return "abstract value" + (names.length > 1 ? "s" : "") + " " + names.join(" and ");
|
||||
}
|
||||
}, {
|
||||
key: "reportIntrospectionError",
|
||||
value: function reportIntrospectionError(val, propertyName) {
|
||||
var realm = val.$Realm;
|
||||
|
||||
var identity = void 0;
|
||||
if (val === realm.$GlobalObject) identity = "global";else if (val instanceof AbstractValue) {
|
||||
identity = this.generateErrorInformationForAbstractVal(val);
|
||||
} else identity = val.intrinsicName || "(some value)";
|
||||
|
||||
var source_locations = [];
|
||||
if (val instanceof AbstractValue) val.addSourceLocationsTo(source_locations);
|
||||
|
||||
var location = void 0;
|
||||
if (propertyName instanceof _index.SymbolValue) {
|
||||
var desc = propertyName.$Description;
|
||||
if (desc) {
|
||||
location = "at symbol [" + desc.throwIfNotConcreteString().value + "]";
|
||||
} else {
|
||||
location = "at symbol [" + "(no description)" + "]";
|
||||
}
|
||||
} 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");
|
||||
|
||||
var message = "This operation is not yet supported on " + identity + " " + location;
|
||||
|
||||
return realm.reportIntrospectionError(message);
|
||||
}
|
||||
}]);
|
||||
|
||||
return AbstractValue;
|
||||
}(_index.Value);
|
||||
|
||||
exports.default = AbstractValue;
|
||||
//# sourceMappingURL=AbstractValue.js.map
|
||||
Reference in New Issue
Block a user