   @STREAM_RETURN = 'streamReturn'
   @AGGREGATE_RETURN = 'aggregateReturn'
 
+  Invalid = '__INVALID__'
+
   isRxObservable = (func) -> typeof func.subscribe == 'function'
   returnsStream = (func) -> func.kind == SheetRunner.STREAM or func.kind == SheetRunner.TRANSFORM_STREAM or func.returnKind == SheetRunner.STREAM_RETURN or func.returnKind == SheetRunner.SEQUENCE_RETURN
   returnsAggregate = (func) -> func.returnKind == SheetRunner.AGGREGATE_RETURN

    @inputStreams = {}
    @inputCompleteSubject = new Rx.Subject()
    @bufferedValueChanges = bufferedValueChangeStream @valueChanges, @inputCompleteSubject

    @sheet = _.assign {}, @providedFunctions, {
      operations: new Operations("a function", @_inputItem)
      stored: {}
      storedUpToDate: {}
    }


# TODO  rationalise this zoo of add...Functions

      @valueChanges.onNext [name, value]
    subj

  _invalidateDependents: (name) -> @slots[n] = Invalid for n in @_functionsUsing name

  _functionsUsing: (name) -> (n for n, f of @userFunctions when _.includes @functionsUsedBy(n), name)

  _recalculate: ->
    for name, subj of @userFunctionSubjects
      subj.onNext @_sheetValue name

  _sheetValue: (name) -> @sheet[name].apply @sheet, []

  _allFunction: (name) ->
    runner = this
