"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.PossiblyNormalCompletion = exports.JoinedAbruptCompletions = exports.ReturnCompletion = exports.BreakCompletion = exports.ContinueCompletion = exports.ThrowCompletion = exports.AbruptCompletion = exports.NormalCompletion = exports.Completion = undefined;

var _invariant = require("./invariant.js");

var _invariant2 = _interopRequireDefault(_invariant);

var _index = require("./values/index.js");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

class Completion {
  constructor(value, location, target) {
    this.value = value;
    this.target = target;
    this.location = location;
  }

}

exports.Completion = Completion; // Normal completions are returned just like spec completions
/**
 * 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.
 */

class NormalCompletion extends Completion {}

exports.NormalCompletion = NormalCompletion; // Abrupt completions are thrown as exeptions, to make it a easier
// to quickly get to the matching high level construct.

class AbruptCompletion extends Completion {}

exports.AbruptCompletion = AbruptCompletion;
class ThrowCompletion extends AbruptCompletion {
  constructor(value, location, nativeStack) {
    super(value, location);
    this.nativeStack = nativeStack || new Error().stack;
  }

}
exports.ThrowCompletion = ThrowCompletion;
class ContinueCompletion extends AbruptCompletion {
  constructor(value, location, target) {
    super(value, location, target);
  }
}

exports.ContinueCompletion = ContinueCompletion;
class BreakCompletion extends AbruptCompletion {
  constructor(value, location, target) {
    super(value, location, target);
  }
}

exports.BreakCompletion = BreakCompletion;
class ReturnCompletion extends AbruptCompletion {
  constructor(value, location) {
    super(value, location);
  }
}

exports.ReturnCompletion = ReturnCompletion;
class JoinedAbruptCompletions extends AbruptCompletion {
  constructor(realm, joinCondition, consequent, consequentEffects, alternate, alternateEffects) {
    super(realm.intrinsics.empty, consequent.location);
    this.joinCondition = joinCondition;
    this.consequent = consequent;
    this.consequentEffects = consequentEffects;
    this.alternate = alternate;
    this.alternateEffects = alternateEffects;
  }

  containsBreakOrContinue() {
    if (this.consequent instanceof BreakCompletion || this.consequent instanceof ContinueCompletion) return true;
    if (this.alternate instanceof BreakCompletion || this.alternate instanceof ContinueCompletion) return true;
    if (this.consequent instanceof JoinedAbruptCompletions) {
      if (this.consequent.containsBreakOrContinue()) return true;
    }
    if (this.alternate instanceof JoinedAbruptCompletions) {
      if (this.alternate.containsBreakOrContinue()) return true;
    }
    return false;
  }
}

exports.JoinedAbruptCompletions = JoinedAbruptCompletions; // Possibly normal completions have to be treated like normal completions
// and are thus never thrown. At the end of a try block or loop body, however,
// action must be taken to deal with the possibly abrupt case of the completion.

class PossiblyNormalCompletion extends NormalCompletion {
  constructor(value, joinCondition, consequent, consequentEffects, alternate, alternateEffects, savedPathConditions, savedEffects = undefined) {
    (0, _invariant2.default)(consequent === consequentEffects[0]);
    (0, _invariant2.default)(alternate === alternateEffects[0]);
    (0, _invariant2.default)(consequent instanceof NormalCompletion || consequent instanceof _index.Value || alternate instanceof NormalCompletion || alternate instanceof _index.Value);
    (0, _invariant2.default)(consequent instanceof AbruptCompletion || alternate instanceof AbruptCompletion);
    (0, _invariant2.default)(value === consequent || consequent instanceof AbruptCompletion || consequent instanceof NormalCompletion && value === consequent.value);
    (0, _invariant2.default)(value === alternate || alternate instanceof AbruptCompletion || alternate instanceof NormalCompletion && value === alternate.value);
    let loc = consequent instanceof AbruptCompletion ? consequent.location : alternate instanceof Completion ? alternate.location : alternate.expressionLocation;
    super(value, loc);
    this.joinCondition = joinCondition;
    this.consequent = consequent;
    this.consequentEffects = consequentEffects;
    this.alternate = alternate;
    this.alternateEffects = alternateEffects;
    this.savedEffects = savedEffects;
    this.savedPathConditions = savedPathConditions;
  }
  // The path conditions that applied at the time of the oldest fork that caused this completion to arise.


  containsBreakOrContinue() {
    if (this.consequent instanceof BreakCompletion || this.consequent instanceof ContinueCompletion) return true;
    if (this.alternate instanceof BreakCompletion || this.alternate instanceof ContinueCompletion) return true;
    if (this.consequent instanceof JoinedAbruptCompletions || this.consequent instanceof PossiblyNormalCompletion) {
      if (this.consequent.containsBreakOrContinue()) return true;
    }
    if (this.alternate instanceof JoinedAbruptCompletions || this.alternate instanceof PossiblyNormalCompletion) {
      if (this.alternate.containsBreakOrContinue()) return true;
    }
    return false;
  }
}
exports.PossiblyNormalCompletion = PossiblyNormalCompletion;
//# sourceMappingURL=completions.js.map