function Scope (name) {
  this.setMaxListeners(0);

  this._name = name;
  this._identity = unique_id+'';

  unique_id++;

  this._inputs = [];

  this._outputs = [];
  this._output_field_name_to_computable = {};
  this._computable_identity_to_output_field_name = {};

  this._instances = [];
  this._computables = [];

  this._dependees = [];
  this._dependee_computables = [];

  this._referenced_scopes = [];
  this._referenced_scope_computables = [];

  var _this = this;

  this.on('scope_reference_added', function (scope, computable) {
    var referenced_scope_index = _this._referenced_scopes.indexOf(scope);
    var referenced_scope_computables;

    if (referenced_scope_index !== -1) {
      referenced_scope_computables =  _this._referenced_scope_computables[referenced_scope_index];
    } else {
      _this._referenced_scopes.push(scope);
      referenced_scope_computables = [];
      _this._referenced_scope_computables.push(referenced_scope_computables);
    }
    referenced_scope_computables.push(computable);

    computable.once('destroyed', function () {
      var scope_index = _this._referenced_scopes.indexOf(scope);
      var scope_referenced_scope_computables = _this._referenced_scope_computables[scope_index];

      scope_referenced_scope_computables = scope_referenced_scope_computables.filter(function(item) {
        return item !== computable;
      });

      var computable_index = referenced_scope_computables.indexOf(computable);
      referenced_scope_computables.splice(computable_index, 1);

      if (!referenced_scope_computables.length) {
        _this._referenced_scopes.splice(scope_index, 1);
        _this._referenced_scope_computables.splice(scope_index, 1);
      }
    });
  });

  this.on('instance_added', function (computable) {
    _this._instances.push(computable);

    var containing_scope = computable.get_containing_scope();

    containing_scope.emit('scope_reference_added', _this, computable);

    var dependee_index = _this._dependees.indexOf(containing_scope);
    if (dependee_index === -1) {
      _this._dependees.push(containing_scope);
      _this._dependee_computables.push([computable]);
    } else {
      _this._dependee_computables[dependee_index].push(computable);
    }

    computable.once('destroyed', function () {
      _this._instances = _this._instances.filter(function (item) {
        return item !== computable;
      });

      var dependee_index = _this._dependees.indexOf(containing_scope);
      if (dependee_index !== -1) {
        var dependee_computables = _this._dependee_computables[dependee_index];
        var dependee_computable_index = dependee_computables.indexOf(computable);

        dependee_computables.splice(dependee_computable_index, 1);

        if (!dependee_computables.length) {
          _this._dependees.splice(dependee_index, 1);
          _this._dependee_computables.splice(dependee_index, 1);
        }
      }

      _this.emit('instance_removed', computable);
    });
  });

  this.on('computable_added', function (computable) {
    _this._computables.push(computable);

    computable.once('destroyed', function () {
      var output_index = _this._outputs.indexOf(computable);
      if (output_index !== -1) {
        _this._outputs.splice(output_index, 1);
      }

      var computable_index = _this._computables.indexOf(computable);
      if (computable_index !== -1) {
        _this._computables.splice(computable_index, 1);
        _this.emit('computable_removed', computable);
      }
    });
  });

  this.on('parameter_added', function (computable) {
    if (_this.get_instance_count() > 0 ) {
      throw new Error("Cannot add ScopeParameters for Scopes that have instances");
    }

    _this._inputs.push(computable);

    computable.once('destroyed', function () {
      // TODO: Handle this by removing an input from all the scope instances
    });
  });
}
/**
 * The definition for a Scope which represents a collection of Computables with defined inputs and outputs, that can be referenced by any number of ScopeInstances.
 * @extends EventEmitter
 * @constructor
 */
The definition for a Scope which represents a collection of Computables with defined inputs and outputs, that can be referenced by any number of ScopeInstances.
The definition for a Scope which represents a collection of Computables with defined inputs and outputs that can be referenced by any number of ScopeInstances .
function Scope (name) {
  this.setMaxListeners(0);
  this._name = name;
  this._identity = unique_id+'';
  unique_id++;
  this._inputs = [];
  this._outputs = [];
  this._output_field_name_to_computable = {};
  this._computable_identity_to_output_field_name = {};
  this._instances = [];
  this._computables = [];
  this._dependees = [];
  this._dependee_computables = [];
  this._referenced_scopes = [];
  this._referenced_scope_computables = [];
  var _this = this;
  this.on('scope_reference_added', function (scope, computable) {
    var referenced_scope_index = _this._referenced_scopes.indexOf(scope);
    var referenced_scope_computables;
    if (referenced_scope_index !== -1) {
      referenced_scope_computables =  _this._referenced_scope_computables[referenced_scope_index];
    } else {
      _this._referenced_scopes.push(scope);
      referenced_scope_computables = [];
      _this._referenced_scope_computables.push(referenced_scope_computables);
    }
    referenced_scope_computables.push(computable);
    computable.once('destroyed', function () {
      var scope_index = _this._referenced_scopes.indexOf(scope);
      var scope_referenced_scope_computables = _this._referenced_scope_computables[scope_index];
      scope_referenced_scope_computables = scope_referenced_scope_computables.filter(function(item) {
        return item !== computable;
      });
      var computable_index = referenced_scope_computables.indexOf(computable);
      referenced_scope_computables.splice(computable_index, 1);
      if (!referenced_scope_computables.length) {
        _this._referenced_scopes.splice(scope_index, 1);
        _this._referenced_scope_computables.splice(scope_index, 1);
      }
    });
  });
  this.on('instance_added', function (computable) {
    _this._instances.push(computable);
    var containing_scope = computable.get_containing_scope();
    containing_scope.emit('scope_reference_added', _this, computable);
    var dependee_index = _this._dependees.indexOf(containing_scope);
    if (dependee_index === -1) {
      _this._dependees.push(containing_scope);
      _this._dependee_computables.push([computable]);
    } else {
      _this._dependee_computables[dependee_index].push(computable);
    }
    computable.once('destroyed', function () {
      _this._instances = _this._instances.filter(function (item) {
        return item !== computable;
      });
      var dependee_index = _this._dependees.indexOf(containing_scope);
      if (dependee_index !== -1) {
        var dependee_computables = _this._dependee_computables[dependee_index];
        var dependee_computable_index = dependee_computables.indexOf(computable);
        dependee_computables.splice(dependee_computable_index, 1);
        if (!dependee_computables.length) {
          _this._dependees.splice(dependee_index, 1);
          _this._dependee_computables.splice(dependee_index, 1);
        }
      }
      _this.emit('instance_removed', computable);
    });
  });
  this.on('computable_added', function (computable) {
    _this._computables.push(computable);
    computable.once('destroyed', function () {
      var output_index = _this._outputs.indexOf(computable);
      if (output_index !== -1) {
        _this._outputs.splice(output_index, 1);
      }
      var computable_index = _this._computables.indexOf(computable);
      if (computable_index !== -1) {
        _this._computables.splice(computable_index, 1);
        _this.emit('computable_removed', computable);
      }
    });
  });
  this.on('parameter_added', function (computable) {
    if (_this.get_instance_count() > 0 ) {
      throw new Error("Cannot add ScopeParameters for Scopes that have instances");
    }
    _this._inputs.push(computable);
    computable.once('destroyed', function () {
    });
  });
}
function Scope ( name ) { this . setMaxListeners ( 0 ) ; this . _name = name ; this . _identity = unique_id + '' ; unique_id ++ ; this . _inputs = [ ] ; this . _outputs = [ ] ; this . _output_field_name_to_computable = { } ; this . _computable_identity_to_output_field_name = { } ; this . _instances = [ ] ; this . _computables = [ ] ; this . _dependees = [ ] ; this . _dependee_computables = [ ] ; this . _referenced_scopes = [ ] ; this . _referenced_scope_computables = [ ] ; var _this = this ; this . on ( 'scope_reference_added' , function ( scope , computable ) { var referenced_scope_index = _this . _referenced_scopes . indexOf ( scope ) ; var referenced_scope_computables ; if ( referenced_scope_index !== - 1 ) { referenced_scope_computables = _this . _referenced_scope_computables [ referenced_scope_index ] ; } else { _this . _referenced_scopes . push ( scope ) ; referenced_scope_computables = [ ] ; _this . _referenced_scope_computables . push ( referenced_scope_computables ) ; } referenced_scope_computables . push ( computable ) ; computable . once ( 'destroyed' , function ( ) { var scope_index = _this . _referenced_scopes . indexOf ( scope ) ; var scope_referenced_scope_computables = _this . _referenced_scope_computables [ scope_index ] ; scope_referenced_scope_computables = scope_referenced_scope_computables . filter ( function ( item ) { return item !== computable ; } ) ; var computable_index = referenced_scope_computables . indexOf ( computable ) ; referenced_scope_computables . splice ( computable_index , 1 ) ; if ( ! referenced_scope_computables . length ) { _this . _referenced_scopes . splice ( scope_index , 1 ) ; _this . _referenced_scope_computables . splice ( scope_index , 1 ) ; } } ) ; } ) ; this . on ( 'instance_added' , function ( computable ) { _this . _instances . push ( computable ) ; var containing_scope = computable . get_containing_scope ( ) ; containing_scope . emit ( 'scope_reference_added' , _this , computable ) ; var dependee_index = _this . _dependees . indexOf ( containing_scope ) ; if ( dependee_index === - 1 ) { _this . _dependees . push ( containing_scope ) ; _this . _dependee_computables . push ( [ computable ] ) ; } else { _this . _dependee_computables [ dependee_index ] . push ( computable ) ; } computable . once ( 'destroyed' , function ( ) { _this . _instances = _this . _instances . filter ( function ( item ) { return item !== computable ; } ) ; var dependee_index = _this . _dependees . indexOf ( containing_scope ) ; if ( dependee_index !== - 1 ) { var dependee_computables = _this . _dependee_computables [ dependee_index ] ; var dependee_computable_index = dependee_computables . indexOf ( computable ) ; dependee_computables . splice ( dependee_computable_index , 1 ) ; if ( ! dependee_computables . length ) { _this . _dependees . splice ( dependee_index , 1 ) ; _this . _dependee_computables . splice ( dependee_index , 1 ) ; } } _this . emit ( 'instance_removed' , computable ) ; } ) ; } ) ; this . on ( 'computable_added' , function ( computable ) { _this . _computables . push ( computable ) ; computable . once ( 'destroyed' , function ( ) { var output_index = _this . _outputs . indexOf ( computable ) ; if ( output_index !== - 1 ) { _this . _outputs . splice ( output_index , 1 ) ; } var computable_index = _this . _computables . indexOf ( computable ) ; if ( computable_index !== - 1 ) { _this . _computables . splice ( computable_index , 1 ) ; _this . emit ( 'computable_removed' , computable ) ; } } ) ; } ) ; this . on ( 'parameter_added' , function ( computable ) { if ( _this . get_instance_count ( ) > 0 ) { throw new Error ( "Cannot add ScopeParameters for Scopes that have instances" ) ; } _this . _inputs . push ( computable ) ; computable . once ( 'destroyed' , function ( ) { } ) ; } ) ; }
The definition for a Scope which represents a collection of Computables with defined inputs and outputs, that can be referenced by any number of ScopeInstances.
The definition for a Scope which represents a collection of Computables with defined inputs and outputs that can be referenced by any number of ScopeInstances .
// TODO: Handle this by removing an input from all the scope instances