function ScopeParameter (scope, output_type, name, force_invariant) {
  if (scope.get_instance_count() > 0) {
    throw new Error("Can't add ScopeParameters while Scope has ScopeInstances");
  }
  this._is_zone_entry_parameter = scope.is_entry_point();
  if (this._is_zone_entry_parameter) {
    this._force_invariant = typeof force_invariant === 'boolean' ? force_invariant : false;
  } else if (typeof force_invariant === 'boolean') {
    throw new Error('Should not set invariant: true/false for non-zone entry scope parameters');
  }

  var input_computables = [];

  if (!output_type) {
    output_type = new IRAnyType();
  }

  this._name = name;
  this._required_output_type = output_type;

  Computable.call(this, scope, input_computables, output_type);

  scope.emit("parameter_added", this);

  this._instances = [];
  this._unique_instances = [];
  var _this = this;

  _this.on("input_changed", function () {
    _this.set_output_type(calculate_output_type());
  });

  scope.on('instance_added', function (computable) {
    _this._instances.push(computable);
    if (_this._unique_instances.indexOf(computable) === -1) {
      _this._unique_instances.push(computable);
    }

    _this.set_output_type(calculate_output_type());

    // TODO: look at inputs and figure out if any return true for the traits
  });

  scope.on('instance_removed', function (computable) {
    var instance_count = 0;
    var instance_index = -1;
    for (var i = 0; i < _this._instances.length; ++i) {
      if (_this._instances[i] === computable) {
        instance_count++;
        instance_index = i;
      }
    }
    _this._instances.splice(instance_index, 1);

    if (instance_count === 1) {
      var unique_instance_index = _this._unique_instances.indexOf(computable);
      _this._unique_instances.splice(unique_instance_index, 1);
    }

    _this.set_output_type(calculate_output_type());
  });

  function calculate_output_type () {
    var bound_input_computable_output_types = [];

    for (var i = 0; i !== _this._unique_instances.length; ++i) {
      var scope_instance = _this._unique_instances[i];
      var bound_input_computables = scope_instance.get_scope_parameter_bound_input_computables(_this);
      for (var j = 0; j !== bound_input_computables.length; ++j) {
        var bound_input_computable = bound_input_computables[j];
        var bound_input_computable_output_type = bound_input_computable.get_output_type();
        bound_input_computable_output_types.push(bound_input_computable_output_type);
      }
    }

    if (!bound_input_computable_output_types.length) return _this.get_required_output_type();
    else if (bound_input_computable_output_types.length === 1) return bound_input_computable_output_types[0];
    else return new IRUnionType(bound_input_computable_output_types);
  }
}
/**
 * ScopeParameters are Computables that represent an input for a Scope.
 *
 * ScopeParameters always have zero inputs.
 * @constructor
 * @emits Scope#added_parameter
 * @extends Computable
 * @param {Scope} scope The Scope that contains this ScopeParameter.
 * @param {IRType} [output_type] The type that the ScopeParameter requires.  Uses IRAnyType if the ScopeParameter has no specific requirements.
 * @param {string} [name] A name for the parameter
 * @param {boolean} [force_invariant]
 */
ScopeParameters are Computables that represent an input for a Scope.
ScopeParameters always have zero inputs.
@constructor
@emits Scope#added_parameter
@extends Computable
@param {Scope} scope The Scope that contains this ScopeParameter.
ScopeParameters are Computables that represent an input for a Scope . ScopeParameters always have zero inputs . @constructor @emits Scope#added_parameter @extends Computable @param { Scope } scope The Scope that contains this ScopeParameter .
function ScopeParameter (scope, output_type, name, force_invariant) {
  if (scope.get_instance_count() > 0) {
    throw new Error("Can't add ScopeParameters while Scope has ScopeInstances");
  }
  this._is_zone_entry_parameter = scope.is_entry_point();
  if (this._is_zone_entry_parameter) {
    this._force_invariant = typeof force_invariant === 'boolean' ? force_invariant : false;
  } else if (typeof force_invariant === 'boolean') {
    throw new Error('Should not set invariant: true/false for non-zone entry scope parameters');
  }
  var input_computables = [];
  if (!output_type) {
    output_type = new IRAnyType();
  }
  this._name = name;
  this._required_output_type = output_type;
  Computable.call(this, scope, input_computables, output_type);
  scope.emit("parameter_added", this);
  this._instances = [];
  this._unique_instances = [];
  var _this = this;
  _this.on("input_changed", function () {
    _this.set_output_type(calculate_output_type());
  });
  scope.on('instance_added', function (computable) {
    _this._instances.push(computable);
    if (_this._unique_instances.indexOf(computable) === -1) {
      _this._unique_instances.push(computable);
    }
    _this.set_output_type(calculate_output_type());
  });
  scope.on('instance_removed', function (computable) {
    var instance_count = 0;
    var instance_index = -1;
    for (var i = 0; i < _this._instances.length; ++i) {
      if (_this._instances[i] === computable) {
        instance_count++;
        instance_index = i;
      }
    }
    _this._instances.splice(instance_index, 1);
    if (instance_count === 1) {
      var unique_instance_index = _this._unique_instances.indexOf(computable);
      _this._unique_instances.splice(unique_instance_index, 1);
    }
    _this.set_output_type(calculate_output_type());
  });
  function calculate_output_type () {
    var bound_input_computable_output_types = [];
    for (var i = 0; i !== _this._unique_instances.length; ++i) {
      var scope_instance = _this._unique_instances[i];
      var bound_input_computables = scope_instance.get_scope_parameter_bound_input_computables(_this);
      for (var j = 0; j !== bound_input_computables.length; ++j) {
        var bound_input_computable = bound_input_computables[j];
        var bound_input_computable_output_type = bound_input_computable.get_output_type();
        bound_input_computable_output_types.push(bound_input_computable_output_type);
      }
    }
    if (!bound_input_computable_output_types.length) return _this.get_required_output_type();
    else if (bound_input_computable_output_types.length === 1) return bound_input_computable_output_types[0];
    else return new IRUnionType(bound_input_computable_output_types);
  }
}
function ScopeParameter ( scope , output_type , name , force_invariant ) { if ( scope . get_instance_count ( ) > 0 ) { throw new Error ( "Can't add ScopeParameters while Scope has ScopeInstances" ) ; } this . _is_zone_entry_parameter = scope . is_entry_point ( ) ; if ( this . _is_zone_entry_parameter ) { this . _force_invariant = typeof force_invariant === 'boolean' ? force_invariant : false ; } else if ( typeof force_invariant === 'boolean' ) { throw new Error ( 'Should not set invariant: true/false for non-zone entry scope parameters' ) ; } var input_computables = [ ] ; if ( ! output_type ) { output_type = new IRAnyType ( ) ; } this . _name = name ; this . _required_output_type = output_type ; Computable . call ( this , scope , input_computables , output_type ) ; scope . emit ( "parameter_added" , this ) ; this . _instances = [ ] ; this . _unique_instances = [ ] ; var _this = this ; _this . on ( "input_changed" , function ( ) { _this . set_output_type ( calculate_output_type ( ) ) ; } ) ; scope . on ( 'instance_added' , function ( computable ) { _this . _instances . push ( computable ) ; if ( _this . _unique_instances . indexOf ( computable ) === - 1 ) { _this . _unique_instances . push ( computable ) ; } _this . set_output_type ( calculate_output_type ( ) ) ; } ) ; scope . on ( 'instance_removed' , function ( computable ) { var instance_count = 0 ; var instance_index = - 1 ; for ( var i = 0 ; i < _this . _instances . length ; ++ i ) { if ( _this . _instances [ i ] === computable ) { instance_count ++ ; instance_index = i ; } } _this . _instances . splice ( instance_index , 1 ) ; if ( instance_count === 1 ) { var unique_instance_index = _this . _unique_instances . indexOf ( computable ) ; _this . _unique_instances . splice ( unique_instance_index , 1 ) ; } _this . set_output_type ( calculate_output_type ( ) ) ; } ) ; function calculate_output_type ( ) { var bound_input_computable_output_types = [ ] ; for ( var i = 0 ; i !== _this . _unique_instances . length ; ++ i ) { var scope_instance = _this . _unique_instances [ i ] ; var bound_input_computables = scope_instance . get_scope_parameter_bound_input_computables ( _this ) ; for ( var j = 0 ; j !== bound_input_computables . length ; ++ j ) { var bound_input_computable = bound_input_computables [ j ] ; var bound_input_computable_output_type = bound_input_computable . get_output_type ( ) ; bound_input_computable_output_types . push ( bound_input_computable_output_type ) ; } } if ( ! bound_input_computable_output_types . length ) return _this . get_required_output_type ( ) ; else if ( bound_input_computable_output_types . length === 1 ) return bound_input_computable_output_types [ 0 ] ; else return new IRUnionType ( bound_input_computable_output_types ) ; } }
ScopeParameters are Computables that represent an input for a Scope.
ScopeParameters are Computables that represent an input for a Scope .
// TODO: look at inputs and figure out if any return true for the traits