759 lines
41 KiB
JavaScript
759 lines
41 KiB
JavaScript
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.JoinImplementation = undefined;
|
|
|
|
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; }; }(); /**
|
|
* 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 _errors = require("../errors.js");
|
|
|
|
var _completions = require("../completions.js");
|
|
|
|
var _environment = require("../environment.js");
|
|
|
|
var _index = require("../methods/index.js");
|
|
|
|
var _realm = require("../realm.js");
|
|
|
|
var _generator = require("../utils/generator.js");
|
|
|
|
var _index2 = require("../values/index.js");
|
|
|
|
var _invariant = require("../invariant.js");
|
|
|
|
var _invariant2 = _interopRequireDefault(_invariant);
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
function joinGenerators(realm, joinCondition, generator1, generator2) {
|
|
var result = new _generator.Generator(realm);
|
|
if (!generator1.empty() || !generator2.empty()) {
|
|
result.joinGenerators(joinCondition, generator1, generator2);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function joinArrays(realm, v1, v2, getAbstractValue) {
|
|
var e = v1 && v1[0] || v2 && v2[0];
|
|
if (e instanceof _index2.Value) return joinArraysOfValues(realm, v1, v2, getAbstractValue);else return joinArrayOfsMapEntries(realm, v1, v2, getAbstractValue);
|
|
}
|
|
|
|
function joinArrayOfsMapEntries(realm, a1, a2, getAbstractValue) {
|
|
var empty = realm.intrinsics.empty;
|
|
var n = Math.max(a1 && a1.length || 0, a2 && a2.length || 0);
|
|
var result = [];
|
|
for (var i = 0; i < n; i++) {
|
|
var _ref = a1 && a1[i] || { $Key: empty, $Value: empty },
|
|
key1 = _ref.$Key,
|
|
val1 = _ref.$Value;
|
|
|
|
var _ref2 = a2 && a2[i] || { $Key: empty, $Value: empty },
|
|
key2 = _ref2.$Key,
|
|
val2 = _ref2.$Value;
|
|
|
|
if (key1 === undefined && key2 === undefined) {
|
|
result[i] = { $Key: undefined, $Value: undefined };
|
|
} else {
|
|
var key3 = getAbstractValue(key1, key2);
|
|
var val3 = getAbstractValue(val1, val2);
|
|
result[i] = { $Key: key3, $Value: val3 };
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function joinArraysOfValues(realm, a1, a2, getAbstractValue) {
|
|
var n = Math.max(a1 && a1.length || 0, a2 && a2.length || 0);
|
|
var result = [];
|
|
for (var i = 0; i < n; i++) {
|
|
result[i] = getAbstractValue(a1 && a1[i] || undefined, a2 && a2[i] || undefined);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
var JoinImplementation = exports.JoinImplementation = function () {
|
|
function JoinImplementation() {
|
|
_classCallCheck(this, JoinImplementation);
|
|
}
|
|
|
|
_createClass(JoinImplementation, [{
|
|
key: "stopEffectCaptureJoinApplyAndReturnCompletion",
|
|
value: function stopEffectCaptureJoinApplyAndReturnCompletion(c1, c2, realm) {
|
|
var e = realm.getCapturedEffects(c1);
|
|
(0, _invariant2.default)(e !== undefined);
|
|
realm.stopEffectCaptureAndUndoEffects(c1);
|
|
var joined_effects = this.joinPossiblyNormalCompletionWithAbruptCompletion(realm, c1, c2, e);
|
|
realm.applyEffects(joined_effects);
|
|
var result = joined_effects[0];
|
|
(0, _invariant2.default)(result instanceof _completions.AbruptCompletion);
|
|
return result;
|
|
}
|
|
}, {
|
|
key: "unbundleNormalCompletion",
|
|
value: function unbundleNormalCompletion(completionOrValue) {
|
|
var completion = void 0,
|
|
value = void 0;
|
|
if (completionOrValue instanceof _completions.PossiblyNormalCompletion) {
|
|
completion = completionOrValue;
|
|
value = completionOrValue.value;
|
|
} else {
|
|
(0, _invariant2.default)(completionOrValue instanceof _index2.Value || completionOrValue instanceof _environment.Reference);
|
|
value = completionOrValue;
|
|
}
|
|
return [completion, value];
|
|
}
|
|
}, {
|
|
key: "composeNormalCompletions",
|
|
value: function composeNormalCompletions(leftCompletion, rightCompletion, resultValue, realm) {
|
|
if (leftCompletion instanceof _completions.PossiblyNormalCompletion) {
|
|
if (rightCompletion instanceof _completions.PossiblyNormalCompletion) {
|
|
this.updatePossiblyNormalCompletionWithValue(realm, rightCompletion, resultValue);
|
|
return this.composePossiblyNormalCompletions(realm, leftCompletion, rightCompletion);
|
|
}
|
|
this.updatePossiblyNormalCompletionWithValue(realm, leftCompletion, resultValue);
|
|
return leftCompletion;
|
|
} else if (rightCompletion instanceof _completions.PossiblyNormalCompletion) {
|
|
this.updatePossiblyNormalCompletionWithValue(realm, rightCompletion, resultValue);
|
|
return rightCompletion;
|
|
} else {
|
|
(0, _invariant2.default)(leftCompletion === undefined && rightCompletion === undefined);
|
|
return resultValue;
|
|
}
|
|
}
|
|
}, {
|
|
key: "composePossiblyNormalCompletions",
|
|
value: function composePossiblyNormalCompletions(realm, pnc, c) {
|
|
//merge the two pathConditions
|
|
var composedPath = [];
|
|
composedPath = pnc.pathConditions.concat(c.pathConditions);
|
|
var savedPathConditions = pnc.savedPathConditions;
|
|
if (pnc.consequent instanceof _completions.AbruptCompletion) {
|
|
if (pnc.alternate instanceof _index2.Value) {
|
|
var _pnc$alternateEffects = _slicedToArray(pnc.alternateEffects, 5),
|
|
_g = _pnc$alternateEffects[1],
|
|
_b = _pnc$alternateEffects[2],
|
|
_p = _pnc$alternateEffects[3],
|
|
_o = _pnc$alternateEffects[4];
|
|
|
|
var _newAlternateEffects = [c, _g, _b, _p, _o];
|
|
return new _completions.PossiblyNormalCompletion(c.value, pnc.joinCondition, pnc.consequent, pnc.consequentEffects, c, _newAlternateEffects, composedPath, savedPathConditions, pnc.savedEffects);
|
|
}
|
|
(0, _invariant2.default)(pnc.alternate instanceof _completions.PossiblyNormalCompletion);
|
|
var new_alternate = this.composePossiblyNormalCompletions(realm, pnc.alternate, c);
|
|
|
|
var _pnc$alternateEffects2 = _slicedToArray(pnc.alternateEffects, 5),
|
|
g = _pnc$alternateEffects2[1],
|
|
b = _pnc$alternateEffects2[2],
|
|
p = _pnc$alternateEffects2[3],
|
|
o = _pnc$alternateEffects2[4];
|
|
|
|
var newAlternateEffects = [new_alternate, g, b, p, o];
|
|
return new _completions.PossiblyNormalCompletion(new_alternate.value, pnc.joinCondition, pnc.consequent, pnc.consequentEffects, new_alternate, newAlternateEffects, composedPath, savedPathConditions, pnc.savedEffects);
|
|
} else {
|
|
(0, _invariant2.default)(pnc.alternate instanceof _completions.AbruptCompletion);
|
|
if (pnc.consequent instanceof _index2.Value) {
|
|
var _pnc$consequentEffect = _slicedToArray(pnc.consequentEffects, 5),
|
|
_g3 = _pnc$consequentEffect[1],
|
|
_b3 = _pnc$consequentEffect[2],
|
|
_p3 = _pnc$consequentEffect[3],
|
|
_o3 = _pnc$consequentEffect[4];
|
|
|
|
var _newConsequentEffects = [c, _g3, _b3, _p3, _o3];
|
|
return new _completions.PossiblyNormalCompletion(c.value, pnc.joinCondition, c, _newConsequentEffects, pnc.alternate, pnc.alternateEffects, composedPath, savedPathConditions, pnc.savedEffects);
|
|
}
|
|
(0, _invariant2.default)(pnc.consequent instanceof _completions.PossiblyNormalCompletion);
|
|
var new_consequent = this.composePossiblyNormalCompletions(realm, pnc.consequent, c);
|
|
|
|
var _pnc$consequentEffect2 = _slicedToArray(pnc.consequentEffects, 5),
|
|
_g2 = _pnc$consequentEffect2[1],
|
|
_b2 = _pnc$consequentEffect2[2],
|
|
_p2 = _pnc$consequentEffect2[3],
|
|
_o2 = _pnc$consequentEffect2[4];
|
|
|
|
var newConsequentEffects = [new_consequent, _g2, _b2, _p2, _o2];
|
|
return new _completions.PossiblyNormalCompletion(new_consequent.value, pnc.joinCondition, new_consequent, newConsequentEffects, pnc.alternate, pnc.alternateEffects, composedPath, savedPathConditions, pnc.savedEffects);
|
|
}
|
|
}
|
|
}, {
|
|
key: "updatePossiblyNormalCompletionWithSubsequentEffects",
|
|
value: function updatePossiblyNormalCompletionWithSubsequentEffects(realm, pnc, subsequentEffects) {
|
|
var v = subsequentEffects[0];
|
|
(0, _invariant2.default)(v instanceof _index2.Value);
|
|
pnc.value = v;
|
|
if (pnc.consequent instanceof _completions.AbruptCompletion) {
|
|
if (pnc.alternate instanceof _index2.Value) {
|
|
pnc.alternate = v;
|
|
pnc.alternateEffects = realm.composeEffects(pnc.alternateEffects, subsequentEffects);
|
|
} else {
|
|
(0, _invariant2.default)(pnc.alternate instanceof _completions.PossiblyNormalCompletion);
|
|
this.updatePossiblyNormalCompletionWithSubsequentEffects(realm, pnc.alternate, subsequentEffects);
|
|
}
|
|
} else {
|
|
if (pnc.consequent instanceof _index2.Value) {
|
|
pnc.consequent = v;
|
|
pnc.consequentEffects = realm.composeEffects(pnc.consequentEffects, subsequentEffects);
|
|
} else {
|
|
(0, _invariant2.default)(pnc.consequent instanceof _completions.PossiblyNormalCompletion);
|
|
this.updatePossiblyNormalCompletionWithSubsequentEffects(realm, pnc.consequent, subsequentEffects);
|
|
}
|
|
}
|
|
}
|
|
}, {
|
|
key: "updatePossiblyNormalCompletionWithValue",
|
|
value: function updatePossiblyNormalCompletionWithValue(realm, pnc, v) {
|
|
pnc.value = v;
|
|
if (pnc.consequent instanceof _completions.AbruptCompletion) {
|
|
if (pnc.alternate instanceof _index2.Value) {
|
|
pnc.alternate = v;
|
|
pnc.alternateEffects[0] = v;
|
|
} else {
|
|
(0, _invariant2.default)(pnc.alternate instanceof _completions.PossiblyNormalCompletion);
|
|
this.updatePossiblyNormalCompletionWithValue(realm, pnc.alternate, v);
|
|
}
|
|
} else {
|
|
if (pnc.consequent instanceof _index2.Value) {
|
|
pnc.consequent = v;
|
|
pnc.consequentEffects[0] = v;
|
|
} else {
|
|
(0, _invariant2.default)(pnc.consequent instanceof _completions.PossiblyNormalCompletion);
|
|
this.updatePossiblyNormalCompletionWithValue(realm, pnc.consequent, v);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Returns the joined effects of all of the paths in pnc.
|
|
// The normal path in pnc is modified to become terminated by ac,
|
|
// so the overall completion will always be an instance of JoinedAbruptCompletions
|
|
|
|
}, {
|
|
key: "joinPossiblyNormalCompletionWithAbruptCompletion",
|
|
value: function joinPossiblyNormalCompletionWithAbruptCompletion(realm,
|
|
// a forked path with a non abrupt (normal) component
|
|
pnc,
|
|
// an abrupt completion that completes the normal path
|
|
ac,
|
|
// effects collected after pnc was constructed
|
|
e) {
|
|
// set up e with ac as the completion. It's OK to do this repeatedly since ac is not changed by recursive calls.
|
|
e[0] = ac;
|
|
if (pnc.consequent instanceof _completions.AbruptCompletion) {
|
|
if (pnc.alternate instanceof _index2.Value) {
|
|
return this.joinEffects(realm, pnc.joinCondition, pnc.consequentEffects, realm.composeEffects(pnc.alternateEffects, e));
|
|
}
|
|
(0, _invariant2.default)(pnc.alternate instanceof _completions.PossiblyNormalCompletion);
|
|
var alternate_effects = this.joinPossiblyNormalCompletionWithAbruptCompletion(realm, pnc.alternate, ac, e);
|
|
(0, _invariant2.default)(pnc.consequent instanceof _completions.AbruptCompletion);
|
|
return this.joinEffects(realm, pnc.joinCondition, pnc.consequentEffects, alternate_effects);
|
|
} else {
|
|
(0, _invariant2.default)(pnc.alternate instanceof _completions.AbruptCompletion);
|
|
if (pnc.consequent instanceof _index2.Value) {
|
|
return this.joinEffects(realm, pnc.joinCondition, realm.composeEffects(pnc.consequentEffects, e), pnc.alternateEffects);
|
|
}
|
|
(0, _invariant2.default)(pnc.consequent instanceof _completions.PossiblyNormalCompletion);
|
|
var consequent_effects = this.joinPossiblyNormalCompletionWithAbruptCompletion(realm, pnc.consequent, ac, e);
|
|
(0, _invariant2.default)(pnc.alternate instanceof _completions.AbruptCompletion);
|
|
return this.joinEffects(realm, pnc.joinCondition, consequent_effects, pnc.alternateEffects);
|
|
}
|
|
}
|
|
}, {
|
|
key: "joinPossiblyNormalCompletionWithValue",
|
|
value: function joinPossiblyNormalCompletionWithValue(realm, joinCondition, pnc, v) {
|
|
if (pnc.consequent instanceof _completions.AbruptCompletion) {
|
|
if (pnc.alternate instanceof _index2.Value) {
|
|
pnc.alternate = this.joinValuesAsConditional(realm, joinCondition, pnc.alternate, v);
|
|
} else {
|
|
(0, _invariant2.default)(pnc.alternate instanceof _completions.PossiblyNormalCompletion);
|
|
this.joinPossiblyNormalCompletionWithValue(realm, joinCondition, pnc.alternate, v);
|
|
}
|
|
} else {
|
|
if (pnc.consequent instanceof _index2.Value) {
|
|
pnc.consequent = this.joinValuesAsConditional(realm, joinCondition, pnc.consequent, v);
|
|
} else {
|
|
(0, _invariant2.default)(pnc.consequent instanceof _completions.PossiblyNormalCompletion);
|
|
this.joinPossiblyNormalCompletionWithValue(realm, joinCondition, pnc.consequent, v);
|
|
}
|
|
}
|
|
}
|
|
}, {
|
|
key: "joinValueWithPossiblyNormalCompletion",
|
|
value: function joinValueWithPossiblyNormalCompletion(realm, joinCondition, pnc, v) {
|
|
if (pnc.consequent instanceof _completions.AbruptCompletion) {
|
|
if (pnc.alternate instanceof _index2.Value) {
|
|
pnc.alternate = this.joinValuesAsConditional(realm, joinCondition, v, pnc.alternate);
|
|
} else {
|
|
(0, _invariant2.default)(pnc.alternate instanceof _completions.PossiblyNormalCompletion);
|
|
this.joinValueWithPossiblyNormalCompletion(realm, joinCondition, pnc.alternate, v);
|
|
}
|
|
} else {
|
|
if (pnc.consequent instanceof _index2.Value) {
|
|
pnc.consequent = this.joinValuesAsConditional(realm, joinCondition, v, pnc.consequent);
|
|
} else {
|
|
(0, _invariant2.default)(pnc.consequent instanceof _completions.PossiblyNormalCompletion);
|
|
this.joinValueWithPossiblyNormalCompletion(realm, joinCondition, pnc.consequent, v);
|
|
}
|
|
}
|
|
}
|
|
}, {
|
|
key: "joinAndRemoveNestedReturnCompletions",
|
|
value: function joinAndRemoveNestedReturnCompletions(realm, c) {
|
|
if (c instanceof _completions.ReturnCompletion) {
|
|
return c.value;
|
|
}
|
|
if (c instanceof _completions.JoinedAbruptCompletions) {
|
|
var c1 = this.joinAndRemoveNestedReturnCompletions(realm, c.consequent);
|
|
var c2 = this.joinAndRemoveNestedReturnCompletions(realm, c.alternate);
|
|
c.consequentEffects[0] = c1;
|
|
c.alternateEffects[0] = c2;
|
|
return this.joinResults(realm, c.joinCondition, c1, c2, c.consequentEffects, c.alternateEffects);
|
|
}
|
|
return c;
|
|
}
|
|
}, {
|
|
key: "joinEffectsAndPromoteNestedReturnCompletions",
|
|
value: function joinEffectsAndPromoteNestedReturnCompletions(realm, c, e, nested_effects) {
|
|
if (c instanceof _index2.Value) {
|
|
// If not undefined, the nested effects were captured when evaluating a conditional code block that ended normally.
|
|
// e represent effects that were captured since reaching the join point where the normal and abrupt
|
|
// completions came together into the completion supplied to the outermost call to this recursive function.
|
|
if (nested_effects !== undefined) e = realm.composeEffects(nested_effects, e);
|
|
return e;
|
|
}
|
|
if (c instanceof _completions.AbruptCompletion && !(c instanceof _completions.JoinedAbruptCompletions)) {
|
|
// The nested effects were captured when evaluating a conditional code block that ended abruptly.
|
|
// An abrupt completion does not care about the effects that were collected since the join point.
|
|
(0, _invariant2.default)(nested_effects !== undefined);
|
|
return nested_effects;
|
|
}
|
|
if (c instanceof _completions.PossiblyNormalCompletion) {
|
|
var _e = this.joinEffectsAndPromoteNestedReturnCompletions(realm, c.consequent, e, c.consequentEffects);
|
|
var _e2 = this.joinEffectsAndPromoteNestedReturnCompletions(realm, c.alternate, e, c.alternateEffects);
|
|
if (_e[0] instanceof _completions.AbruptCompletion) {
|
|
if (_e2[0] instanceof _index2.Value) _e2[0] = new _completions.ReturnCompletion(realm.intrinsics.undefined, realm.currentLocation);
|
|
return this.joinEffects(realm, c.joinCondition, _e, _e2);
|
|
} else if (_e2[0] instanceof _completions.AbruptCompletion) {
|
|
if (_e[0] instanceof _index2.Value) _e[0] = new _completions.ReturnCompletion(realm.intrinsics.undefined, realm.currentLocation);
|
|
return this.joinEffects(realm, c.joinCondition, _e, _e2);
|
|
}
|
|
}
|
|
(0, _invariant2.default)(c instanceof _completions.JoinedAbruptCompletions);
|
|
// e will be ignored in the calls below since the branches are all abrupt.
|
|
var e1 = this.joinEffectsAndPromoteNestedReturnCompletions(realm, c.consequent, e, c.consequentEffects);
|
|
var e2 = this.joinEffectsAndPromoteNestedReturnCompletions(realm, c.alternate, e, c.alternateEffects);
|
|
var _ref3 = [e1[0], e2[0]],
|
|
r1 = _ref3[0],
|
|
r2 = _ref3[1];
|
|
|
|
if (r1 instanceof _completions.ReturnCompletion) {
|
|
(0, _invariant2.default)(!(r2 instanceof _completions.ReturnCompletion)); // Otherwise their values should have been joined
|
|
if (r2 instanceof _completions.JoinedAbruptCompletions) {
|
|
if (r2.consequent instanceof _completions.ReturnCompletion) {
|
|
var r1jr2c = this.joinEffects(realm, c.joinCondition, e1, r2.consequentEffects);
|
|
(0, _invariant2.default)(r1jr2c[0] instanceof _completions.ReturnCompletion);
|
|
var or = _index2.AbstractValue.createFromLogicalOp(realm, "||", c.joinCondition, r2.joinCondition);
|
|
(0, _invariant2.default)(or instanceof _index2.AbstractValue);
|
|
return this.joinEffects(realm, or, r1jr2c, r2.alternateEffects);
|
|
}
|
|
if (r2.alternate instanceof _completions.ReturnCompletion) {
|
|
var r1jr2a = this.joinEffects(realm, c.joinCondition, e1, r2.alternateEffects);
|
|
(0, _invariant2.default)(r1jr2a[0] instanceof _completions.ReturnCompletion);
|
|
var notR2jc = _index2.AbstractValue.createFromUnaryOp(realm, "!", r2.joinCondition);
|
|
var _or = _index2.AbstractValue.createFromLogicalOp(realm, "||", c.joinCondition, notR2jc);
|
|
(0, _invariant2.default)(_or instanceof _index2.AbstractValue);
|
|
return this.joinEffects(realm, _or, r1jr2a, r2.consequentEffects);
|
|
}
|
|
}
|
|
} else if (r2 instanceof _completions.ReturnCompletion) {
|
|
(0, _invariant2.default)(!(r1 instanceof _completions.ReturnCompletion)); // Otherwise their values should have been joined
|
|
if (r1 instanceof _completions.JoinedAbruptCompletions) {
|
|
if (r1.consequent instanceof _completions.ReturnCompletion) {
|
|
var r2jr1c = this.joinEffects(realm, c.joinCondition, r1.consequentEffects, e2);
|
|
(0, _invariant2.default)(r2jr1c[0] instanceof _completions.ReturnCompletion);
|
|
var _or2 = _index2.AbstractValue.createFromLogicalOp(realm, "||", c.joinCondition, r1.joinCondition);
|
|
(0, _invariant2.default)(_or2 instanceof _index2.AbstractValue);
|
|
return this.joinEffects(realm, _or2, r2jr1c, r1.alternateEffects);
|
|
}
|
|
if (r1.alternate instanceof _completions.ReturnCompletion) {
|
|
var r2jr1a = this.joinEffects(realm, c.joinCondition, r1.alternateEffects, e2);
|
|
var notR1jc = _index2.AbstractValue.createFromUnaryOp(realm, "!", r1.joinCondition);
|
|
(0, _invariant2.default)(r2jr1a[0] instanceof _completions.ReturnCompletion);
|
|
var _or3 = _index2.AbstractValue.createFromLogicalOp(realm, "||", c.joinCondition, notR1jc);
|
|
(0, _invariant2.default)(_or3 instanceof _index2.AbstractValue);
|
|
return this.joinEffects(realm, _or3, r2jr1a, r1.consequentEffects);
|
|
}
|
|
}
|
|
}
|
|
return this.joinEffects(realm, c.joinCondition, e1, e2);
|
|
}
|
|
}, {
|
|
key: "unbundleReturnCompletion",
|
|
value: function unbundleReturnCompletion(realm, c) {
|
|
var empty_effects = (0, _realm.construct_empty_effects)(realm);
|
|
var v = realm.intrinsics.empty;
|
|
if (c.consequent instanceof _completions.ReturnCompletion) {
|
|
var negation = _index2.AbstractValue.createFromUnaryOp(realm, "!", c.joinCondition);
|
|
// Simply negating the (known to be abstract) join condition should
|
|
// not become a concrete value
|
|
(0, _invariant2.default)(negation instanceof _index2.AbstractValue);
|
|
var pathConditions = [negation];
|
|
var pnc = new _completions.PossiblyNormalCompletion(v, c.joinCondition, v, empty_effects, c.alternate, c.alternateEffects, pathConditions, []);
|
|
return [c.consequentEffects, pnc];
|
|
} else if (c.alternate instanceof _completions.ReturnCompletion) {
|
|
var _pnc = new _completions.PossiblyNormalCompletion(v, c.joinCondition, c.consequent, c.consequentEffects, v, empty_effects, [c.joinCondition], []);
|
|
return [c.alternateEffects, _pnc];
|
|
} else {
|
|
(0, _invariant2.default)(false, "unbundleReturnCompletion needs an argument that contains a non nested return completion");
|
|
}
|
|
}
|
|
}, {
|
|
key: "removeNormalEffects",
|
|
value: function removeNormalEffects(realm, c) {
|
|
if (c.consequent instanceof _completions.AbruptCompletion) {
|
|
if (c.alternate instanceof _index2.Value) {
|
|
var result = c.alternateEffects;
|
|
c.alternateEffects = (0, _realm.construct_empty_effects)(realm);
|
|
return result;
|
|
} else {
|
|
(0, _invariant2.default)(c.alternate instanceof _completions.PossiblyNormalCompletion);
|
|
var _result = realm.composeEffects(c.alternateEffects, this.removeNormalEffects(realm, c.alternate));
|
|
c.alternateEffects = (0, _realm.construct_empty_effects)(realm);
|
|
return _result;
|
|
}
|
|
} else {
|
|
if (c.consequent instanceof _index2.Value) {
|
|
var _result2 = c.consequentEffects;
|
|
c.consequentEffects = (0, _realm.construct_empty_effects)(realm);
|
|
return _result2;
|
|
} else {
|
|
(0, _invariant2.default)(c.consequent instanceof _completions.PossiblyNormalCompletion);
|
|
var _result3 = realm.composeEffects(c.consequentEffects, this.removeNormalEffects(realm, c.consequent));
|
|
c.consequentEffects = (0, _realm.construct_empty_effects)(realm);
|
|
return _result3;
|
|
}
|
|
}
|
|
}
|
|
}, {
|
|
key: "joinEffects",
|
|
value: function joinEffects(realm, joinCondition, e1, e2) {
|
|
var _e3 = _slicedToArray(e1, 5),
|
|
result1 = _e3[0],
|
|
gen1 = _e3[1],
|
|
bindings1 = _e3[2],
|
|
properties1 = _e3[3],
|
|
createdObj1 = _e3[4];
|
|
|
|
var _e4 = _slicedToArray(e2, 5),
|
|
result2 = _e4[0],
|
|
gen2 = _e4[1],
|
|
bindings2 = _e4[2],
|
|
properties2 = _e4[3],
|
|
createdObj2 = _e4[4];
|
|
|
|
var result = this.joinResults(realm, joinCondition, result1, result2, e1, e2);
|
|
if (result1 instanceof _completions.AbruptCompletion) {
|
|
if (!(result2 instanceof _completions.AbruptCompletion)) {
|
|
(0, _invariant2.default)(result instanceof _completions.PossiblyNormalCompletion);
|
|
return [result, gen2, bindings2, properties2, createdObj2];
|
|
}
|
|
} else if (result2 instanceof _completions.AbruptCompletion) {
|
|
(0, _invariant2.default)(result instanceof _completions.PossiblyNormalCompletion);
|
|
return [result, gen1, bindings1, properties1, createdObj1];
|
|
}
|
|
|
|
var bindings = this.joinBindings(realm, joinCondition, bindings1, bindings2);
|
|
var properties = this.joinPropertyBindings(realm, joinCondition, properties1, properties2, createdObj1, createdObj2);
|
|
var createdObjects = new Set();
|
|
createdObj1.forEach(function (o) {
|
|
createdObjects.add(o);
|
|
});
|
|
createdObj2.forEach(function (o) {
|
|
createdObjects.add(o);
|
|
});
|
|
|
|
var generator = joinGenerators(realm, joinCondition, gen1, gen2);
|
|
|
|
return [result, generator, bindings, properties, createdObjects];
|
|
}
|
|
}, {
|
|
key: "joinResults",
|
|
value: function joinResults(realm, joinCondition, result1, result2, e1, e2) {
|
|
var _this = this;
|
|
|
|
var getAbstractValue = function getAbstractValue(v1, v2) {
|
|
return _this.joinValuesAsConditional(realm, joinCondition, v1, v2);
|
|
};
|
|
if (result1 instanceof _environment.Reference || result2 instanceof _environment.Reference) {
|
|
_index2.AbstractValue.reportIntrospectionError(joinCondition);
|
|
throw new _errors.FatalError();
|
|
}
|
|
if (result1 instanceof _completions.BreakCompletion && result2 instanceof _completions.BreakCompletion && result1.target === result2.target) {
|
|
return new _completions.BreakCompletion(realm.intrinsics.empty, joinCondition.expressionLocation, result1.target);
|
|
}
|
|
if (result1 instanceof _completions.ContinueCompletion && result2 instanceof _completions.ContinueCompletion && result1.target === result2.target) {
|
|
return new _completions.ContinueCompletion(realm.intrinsics.empty, joinCondition.expressionLocation, result1.target);
|
|
}
|
|
if (result1 instanceof _completions.ReturnCompletion && result2 instanceof _completions.ReturnCompletion) {
|
|
var val = this.joinValues(realm, result1.value, result2.value, getAbstractValue);
|
|
(0, _invariant2.default)(val instanceof _index2.Value);
|
|
return new _completions.ReturnCompletion(val, joinCondition.expressionLocation);
|
|
}
|
|
if (result1 instanceof _completions.ThrowCompletion && result2 instanceof _completions.ThrowCompletion) {
|
|
var _val = this.joinValues(realm, result1.value, result2.value, getAbstractValue);
|
|
(0, _invariant2.default)(_val instanceof _index2.Value);
|
|
return new _completions.ThrowCompletion(_val, result1.location);
|
|
}
|
|
if (result1 instanceof _completions.AbruptCompletion && result2 instanceof _completions.AbruptCompletion) {
|
|
return new _completions.JoinedAbruptCompletions(realm, joinCondition, result1, e1, result2, e2);
|
|
}
|
|
if (result1 instanceof _index2.Value && result2 instanceof _index2.Value) {
|
|
var _val2 = this.joinValues(realm, result1, result2, getAbstractValue);
|
|
(0, _invariant2.default)(_val2 instanceof _index2.Value);
|
|
return _val2;
|
|
}
|
|
if (result1 instanceof _completions.PossiblyNormalCompletion && result2 instanceof _completions.PossiblyNormalCompletion) {
|
|
return this.composePossiblyNormalCompletions(realm, result1, result2);
|
|
}
|
|
if (result1 instanceof _completions.AbruptCompletion) {
|
|
var value = result2;
|
|
var savedEffects = void 0;
|
|
var pathConditions = void 0;
|
|
var savedPathConditions = [];
|
|
if (result2 instanceof _completions.PossiblyNormalCompletion) {
|
|
value = result2.value;
|
|
savedEffects = result2.savedEffects;
|
|
pathConditions = [joinCondition].concat(result2.pathConditions);
|
|
savedPathConditions = result2.savedPathConditions;
|
|
} else {
|
|
pathConditions = [joinCondition];
|
|
}
|
|
(0, _invariant2.default)(value instanceof _index2.Value);
|
|
return new _completions.PossiblyNormalCompletion(value, joinCondition, result1, e1, result2, e2, pathConditions, savedPathConditions, savedEffects);
|
|
}
|
|
if (result2 instanceof _completions.AbruptCompletion) {
|
|
var _value = result1;
|
|
var _savedEffects = void 0;
|
|
var _pathConditions = void 0;
|
|
var _savedPathConditions = [];
|
|
if (result1 instanceof _completions.PossiblyNormalCompletion) {
|
|
_value = result1.value;
|
|
_savedEffects = result1.savedEffects;
|
|
_pathConditions = [joinCondition].concat(result1.pathConditions);
|
|
_savedPathConditions = result1.savedPathConditions;
|
|
} else {
|
|
_pathConditions = [joinCondition];
|
|
}
|
|
(0, _invariant2.default)(_value instanceof _index2.Value);
|
|
return new _completions.PossiblyNormalCompletion(_value, joinCondition, result1, e1, result2, e2, _pathConditions, _savedPathConditions, _savedEffects);
|
|
}
|
|
if (result1 instanceof _completions.PossiblyNormalCompletion) {
|
|
(0, _invariant2.default)(result2 instanceof _index2.Value);
|
|
this.joinPossiblyNormalCompletionWithValue(realm, joinCondition, result1, result2);
|
|
return result1;
|
|
}
|
|
if (result2 instanceof _completions.PossiblyNormalCompletion) {
|
|
(0, _invariant2.default)(result1 instanceof _index2.Value);
|
|
this.joinValueWithPossiblyNormalCompletion(realm, joinCondition, result2, result1);
|
|
return result2;
|
|
}
|
|
(0, _invariant2.default)(false);
|
|
}
|
|
}, {
|
|
key: "composeGenerators",
|
|
value: function composeGenerators(realm, generator1, generator2) {
|
|
var result = new _generator.Generator(realm);
|
|
if (!generator1.empty() || !generator2.empty()) {
|
|
result.composeGenerators(generator1, generator2);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// Creates a single map that joins together maps m1 and m2 using the given join
|
|
// operator. If an entry is present in one map but not the other, the missing
|
|
// entry is treated as if it were there and its value were undefined.
|
|
|
|
}, {
|
|
key: "joinMaps",
|
|
value: function joinMaps(m1, m2, join) {
|
|
var m3 = new Map();
|
|
m1.forEach(function (val1, key, map1) {
|
|
var val2 = m2.get(key);
|
|
var val3 = join(key, val1, val2);
|
|
m3.set(key, val3);
|
|
});
|
|
m2.forEach(function (val2, key, map2) {
|
|
if (!m1.has(key)) {
|
|
m3.set(key, join(key, undefined, val2));
|
|
}
|
|
});
|
|
return m3;
|
|
}
|
|
|
|
// Creates a single map that has an key, value pair for the union of the key
|
|
// sets of m1 and m2. The value of a pair is the join of m1[key] and m2[key]
|
|
// where the join is defined to be just m1[key] if m1[key] === m2[key] and
|
|
// and abstract value with expression "joinCondition ? m1[key] : m2[key]" if not.
|
|
|
|
}, {
|
|
key: "joinBindings",
|
|
value: function joinBindings(realm, joinCondition, m1, m2) {
|
|
var _this2 = this;
|
|
|
|
var getAbstractValue = function getAbstractValue(v1, v2) {
|
|
return _this2.joinValuesAsConditional(realm, joinCondition, v1, v2);
|
|
};
|
|
var join = function join(b, b1, b2) {
|
|
var l1 = b1 === undefined ? b.hasLeaked : b1.hasLeaked;
|
|
var l2 = b2 === undefined ? b.hasLeaked : b2.hasLeaked;
|
|
var v1 = b1 === undefined ? b.value : b1.value;
|
|
var v2 = b2 === undefined ? b.value : b2.value;
|
|
var hasLeaked = l1 || l2; // If either has leaked, then this binding has leaked.
|
|
var value = _this2.joinValues(realm, v1, v2, getAbstractValue);
|
|
(0, _invariant2.default)(value instanceof _index2.Value);
|
|
return { hasLeaked: hasLeaked, value: value };
|
|
};
|
|
return this.joinMaps(m1, m2, join);
|
|
}
|
|
|
|
// If v1 is known and defined and v1 === v2 return v1,
|
|
// otherwise return getAbstractValue(v1, v2)
|
|
|
|
}, {
|
|
key: "joinValues",
|
|
value: function joinValues(realm, v1, v2, getAbstractValue) {
|
|
if (Array.isArray(v1) || Array.isArray(v2)) {
|
|
(0, _invariant2.default)(v1 === undefined || Array.isArray(v1));
|
|
(0, _invariant2.default)(v2 === undefined || Array.isArray(v2));
|
|
return joinArrays(realm, v1, v2, getAbstractValue);
|
|
}
|
|
(0, _invariant2.default)(v1 === undefined || v1 instanceof _index2.Value);
|
|
(0, _invariant2.default)(v2 === undefined || v2 instanceof _index2.Value);
|
|
if (v1 !== undefined && v2 !== undefined && !(v1 instanceof _index2.AbstractValue) && !(v2 instanceof _index2.AbstractValue) && (0, _index.StrictEqualityComparison)(realm, v1.throwIfNotConcrete(), v2.throwIfNotConcrete())) {
|
|
return v1;
|
|
} else {
|
|
return getAbstractValue(v1, v2);
|
|
}
|
|
}
|
|
}, {
|
|
key: "joinValuesAsConditional",
|
|
value: function joinValuesAsConditional(realm, condition, v1, v2) {
|
|
return _index2.AbstractValue.createFromConditionalOp(realm, condition, v1, v2);
|
|
}
|
|
}, {
|
|
key: "joinPropertyBindings",
|
|
value: function joinPropertyBindings(realm, joinCondition, m1, m2, c1, c2) {
|
|
var _this3 = this;
|
|
|
|
var join = function join(b, d1, d2) {
|
|
// If the PropertyBinding object has been freshly allocated do not join
|
|
if (d1 === undefined) {
|
|
if (b.object instanceof _index2.ObjectValue && c2.has(b.object)) return d2; // no join
|
|
if (b.descriptor !== undefined && m1.has(b)) {
|
|
// property was deleted
|
|
d1 = (0, _index.cloneDescriptor)(b.descriptor);
|
|
(0, _invariant2.default)(d1 !== undefined);
|
|
d1.value = realm.intrinsics.empty;
|
|
} else {
|
|
// no write to property
|
|
d1 = b.descriptor; //Get value of property before the split
|
|
}
|
|
}
|
|
if (d2 === undefined) {
|
|
if (b.object instanceof _index2.ObjectValue && c1.has(b.object)) return d1; // no join
|
|
if (b.descriptor !== undefined && m2.has(b)) {
|
|
// property was deleted
|
|
d2 = (0, _index.cloneDescriptor)(b.descriptor);
|
|
(0, _invariant2.default)(d2 !== undefined);
|
|
d2.value = realm.intrinsics.empty;
|
|
} else {
|
|
// no write to property
|
|
d2 = b.descriptor; //Get value of property before the split
|
|
}
|
|
}
|
|
return _this3.joinDescriptors(realm, joinCondition, d1, d2);
|
|
};
|
|
return this.joinMaps(m1, m2, join);
|
|
}
|
|
}, {
|
|
key: "joinDescriptors",
|
|
value: function joinDescriptors(realm, joinCondition, d1, d2) {
|
|
var _this4 = this;
|
|
|
|
var getAbstractValue = function getAbstractValue(v1, v2) {
|
|
return _this4.joinValuesAsConditional(realm, joinCondition, v1, v2);
|
|
};
|
|
var clone_with_abstract_value = function clone_with_abstract_value(d) {
|
|
if (!(0, _index.IsDataDescriptor)(realm, d)) {
|
|
var d3 = {};
|
|
d3.joinCondition = joinCondition;
|
|
return d3;
|
|
}
|
|
var dc = (0, _index.cloneDescriptor)(d);
|
|
(0, _invariant2.default)(dc !== undefined);
|
|
var dcValue = dc.value;
|
|
if (Array.isArray(dcValue)) {
|
|
(0, _invariant2.default)(dcValue.length > 0);
|
|
var elem0 = dcValue[0];
|
|
if (elem0 instanceof _index2.Value) {
|
|
dc.value = dcValue.map(function (e) {
|
|
return getAbstractValue(e, realm.intrinsics.empty);
|
|
});
|
|
} else {
|
|
dc.value = dcValue.map(function (e) {
|
|
var _ref4 = e,
|
|
key1 = _ref4.$Key,
|
|
val1 = _ref4.$Value;
|
|
|
|
var key3 = getAbstractValue(key1, realm.intrinsics.empty);
|
|
var val3 = getAbstractValue(val1, realm.intrinsics.empty);
|
|
return { $Key: key3, $Value: val3 };
|
|
});
|
|
}
|
|
} else {
|
|
(0, _invariant2.default)(dcValue === undefined || dcValue instanceof _index2.Value);
|
|
dc.value = getAbstractValue(dcValue, realm.intrinsics.empty);
|
|
}
|
|
return dc;
|
|
};
|
|
if (d1 === undefined) {
|
|
if (d2 === undefined) return undefined;
|
|
// d2 is a new property created in only one branch, join with empty
|
|
var d3 = clone_with_abstract_value(d2);
|
|
if (!(0, _index.IsDataDescriptor)(realm, d2)) d3.descriptor2 = d2;
|
|
return d3;
|
|
} else if (d2 === undefined) {
|
|
(0, _invariant2.default)(d1 !== undefined);
|
|
// d1 is a new property created in only one branch, join with empty
|
|
var _d = clone_with_abstract_value(d1);
|
|
if (!(0, _index.IsDataDescriptor)(realm, d1)) _d.descriptor1 = d1;
|
|
return _d;
|
|
} else {
|
|
if ((0, _index.equalDescriptors)(d1, d2) && (0, _index.IsDataDescriptor)(realm, d1)) {
|
|
var dc = (0, _index.cloneDescriptor)(d1);
|
|
(0, _invariant2.default)(dc !== undefined);
|
|
dc.value = this.joinValues(realm, d1.value, d2.value, getAbstractValue);
|
|
return dc;
|
|
}
|
|
var _d2 = {};
|
|
_d2.joinCondition = joinCondition;
|
|
_d2.descriptor1 = d1;
|
|
_d2.descriptor2 = d2;
|
|
return _d2;
|
|
}
|
|
}
|
|
}]);
|
|
|
|
return JoinImplementation;
|
|
}();
|
|
//# sourceMappingURL=join.js.map
|