import { Lambda1 , Lambda1_deps , Lambda1_toFunction , Lambda2 , Lambda2_deps , Lambda2_toFunction , Lambda3 , Lambda3_deps , Lambda3_toFunction , Lambda4 , Lambda4_deps , Lambda4_toFunction , Lambda5 , Lambda5_deps , Lambda5_toFunction , Lambda6 , Lambda6_deps , Lambda6_toFunction , toSources } from "./Lambda" ; import { Source , Vertex } from "./Vertex" ; import { Transaction } from "./Transaction" ; import { CoalesceHandler } from "./CoalesceHandler" ; import { Cell } from "./Cell" ; import { Listener } from "./Listener" ; import { Tuple2 } from "./Tuple2" ; import { Lazy } from "./Lazy" ; import { LazyCell } from "./LazyCell" ; import * as Z from "sanctuary-type-classes" ; class MergeState < A > { constructor ( ) { } left : A = null ; left_present : boolean = false ; right : A = null ; right_present : boolean = false ; } export class Stream < A > { constructor ( vertex ? ) { this . vertex = vertex ? vertex : new Vertex ( "Stream" , 0 , [ ] ) ; } getVertex__ ( ) { return this . vertex ; } protected vertex : Vertex ; protected listeners : Array < Listener < A > > = [ ] ; protected firings : A [ ] = [ ] ; param f Function to apply to convert the values. It may construct FRP logic or use
     *     Cell in which case it is equivalent to  Stream ing the
     *    cell. Apart from this the function must be <em>referentially transparent</em>.
      map < B > ( f ) { const out = new StreamWithSend < B > ( null ) ; const ff = Lambda1_toFunction ( f ) ; out . vertex = new Vertex ( "map" , 0 , [ new Source ( this . vertex , ( ) => { return this . listen_ ( out . vertex , ( a ) => { out . send_ ( ff ( a ) ) ; } , false ) ; } ) ] . concat ( toSources ( Lambda1_deps ( f ) ) ) ) ; return out ; } param b mapTo < B > ( b ) { const out = new StreamWithSend < B > ( null ) ; out . vertex = new Vertex ( "mapTo" , 0 , [ new Source ( this . vertex , ( ) => { return this . listen_ ( out . vertex , ( a ) => { out . send_ ( b ) ; } , false ) ; } ) ] ) ; return out ; } /**
     * Variant of  Stream that merges two streams and will drop an event
     * in the simultaneous case.
     * <p>
     * In the case where two events are simultaneous (i.e. both
     * within the same transaction), the event from <em>this</em> will take precedence, and
     * the event from <em>s</em> will be dropped.
     * If you want to specify your own combining function, use  Stream .
     * s1.orElse(s2) is equivalent to s1.merge(s2, (l, r) -&gt; l).
     * <p>
     * The name orElse() is used instead of merge() to make it really clear that care should
     * be taken, because events can be dropped.
      orElse ( s ) { return this . merge ( s , ( left , right ) => { return left ; } ) ; } param f Function to combine the values. It may construct FRP logic or use
     *     Cell . Apart from this the function must be <em>referentially transparent</em>.
      merge ( s , f ) { const ff = Lambda2_toFunction ( f ) ; const mergeState = new MergeState < A > ( ) ; let pumping = false ; const out = new StreamWithSend < A > ( null ) ; const pump = ( ) => { if ( pumping ) { return ; } pumping = true ; Transaction . currentTransaction . prioritized ( out . getVertex__ ( ) , ( ) => { if ( mergeState . left_present && mergeState . right_present ) { out . send_ ( ff ( mergeState . left , mergeState . right ) ) ; } else if ( mergeState . left_present ) { out . send_ ( mergeState . left ) ; } else if ( mergeState . right_present ) { out . send_ ( mergeState . right ) ; } mergeState . left = null ; mergeState . left_present = false ; mergeState . right = null ; mergeState . right_present = false ; pumping = false ; } ) ; } ; const vertex = new Vertex ( "merge" , 0 , [ new Source ( this . vertex , ( ) => this . listen_ ( out . vertex , ( a ) => { mergeState . left = a ; mergeState . left_present = true ; pump ( ) ; } , false ) ) , new Source ( s . vertex , ( ) => s . listen_ ( out . vertex , ( a ) => { mergeState . right = a ; mergeState . right_present = true ; pump ( ) ; } , false ) ) ] . concat ( toSources ( Lambda2_deps ( f ) ) ) ) ; out . vertex = vertex ; return out ; } /**
     * Return a stream that only outputs events for which the predicate returns true.
     */ filter ( f ) { const out = new StreamWithSend < A > ( null ) ; const ff = Lambda1_toFunction ( f ) ; out . vertex = new Vertex ( "filter" , 0 , [ new Source ( this . vertex , ( ) => { return this . listen_ ( out . vertex , ( a ) => { if ( ff ( a ) ) out . send_ ( a ) ; } , false ) ; } ) ] . concat ( toSources ( Lambda1_deps ( f ) ) ) ) ; return out ; } /**
     * Return a stream that only outputs events that have present
     * values, discarding null values.
     */ filterNotNull ( ) { const out = new StreamWithSend < A > ( null ) ; out . vertex = new Vertex ( "filterNotNull" , 0 , [ new Source ( this . vertex , ( ) => { return this . listen_ ( out . vertex , ( a ) => { if ( a !== null ) out . send_ ( a ) ; } , false ) ; } ) ] ) ; return out ; } /**
     * Return a stream that only outputs events from the input stream
     * when the specified cell's value is true.
     */ gate ( c ) { return this . snapshot ( c , ( a , pred ) => { return pred ? a : null ; } ) . filterNotNull ( ) ; } /**
     * Variant of  snapshot that captures the cell's value
     * at the time of the event firing, ignoring the stream's value.
      snapshot1 < B > ( c ) { const out = new StreamWithSend < B > ( null ) ; out . vertex = new Vertex ( "snapshot1" , 0 , [ new Source ( this . vertex , ( ) => { return this . listen_ ( out . vertex , ( a ) => { out . send_ ( c . sampleNoTrans__ ( ) ) ; } , false ) ; } ) , new Source ( c . getVertex__ ( ) , null ) ] ) ; return out ; } /**
     * Return a stream whose events are the result of the combination using the specified
     * function of the input stream's event value and the value of the cell at that time.
     * <P>
     * There is an implicit delay: State updates caused by event firings being held with
     *  Stream don't become visible as the cell's current value until
     * the following transaction. To put this another way,  Stream * always sees the value of a cell as it was before any state changes from the current
     * transaction.
      snapshot < B , C > ( b , f_ ) { const out = new StreamWithSend < C > ( null ) ; const ff = Lambda2_toFunction ( f_ ) ; out . vertex = new Vertex ( "snapshot" , 0 , [ new Source ( this . vertex , ( ) => { return this . listen_ ( out . vertex , ( a ) => { out . send_ ( ff ( a , b . sampleNoTrans__ ( ) ) ) ; } , false ) ; } ) , new Source ( b . getVertex__ ( ) , null ) ] . concat ( toSources ( Lambda2_deps ( f_ ) ) ) ) ; return out ; } /**
     * Return a stream whose events are the result of the combination using the specified
     * function of the input stream's event value and the value of the cells at that time.
     * <P>
     * There is an implicit delay: State updates caused by event firings being held with
     *  Stream don't become visible as the cell's current value until
     * the following transaction. To put this another way, snapshot()
     * always sees the value of a cell as it was before any state changes from the current
     * transaction.
      snapshot3 < B , C , D > ( b , c , f_ ) { const out = new StreamWithSend < D > ( null ) ; const ff = Lambda3_toFunction ( f_ ) ; out . vertex = new Vertex ( "snapshot" , 0 , [ new Source ( this . vertex , ( ) => { return this . listen_ ( out . vertex , ( a ) => { out . send_ ( ff ( a , b . sampleNoTrans__ ( ) , c . sampleNoTrans__ ( ) ) ) ; } , false ) ; } ) , new Source ( b . getVertex__ ( ) , null ) , new Source ( c . getVertex__ ( ) , null ) ] . concat ( toSources ( Lambda3_deps ( f_ ) ) ) ) ; return out ; } /**
     * Return a stream whose events are the result of the combination using the specified
     * function of the input stream's event value and the value of the cells at that time.
     * <P>
     * There is an implicit delay: State updates caused by event firings being held with
     *  Stream don't become visible as the cell's current value until
     * the following transaction. To put this another way, snapshot()
     * always sees the value of a cell as it was before any state changes from the current
     * transaction.
      snapshot4 < B , C , D , E > ( b , c , d , f_ ) { const out = new StreamWithSend < E > ( null ) ; const ff = Lambda4_toFunction ( f_ ) ; out . vertex = new Vertex ( "snapshot" , 0 , [ new Source ( this . vertex , ( ) => { return this . listen_ ( out . vertex , ( a ) => { out . send_ ( ff ( a , b . sampleNoTrans__ ( ) , c . sampleNoTrans__ ( ) , d . sampleNoTrans__ ( ) ) ) ; } , false ) ; } ) , new Source ( b . getVertex__ ( ) , null ) , new Source ( c . getVertex__ ( ) , null ) , new Source ( d . getVertex__ ( ) , null ) ] . concat ( toSources ( Lambda4_deps ( f_ ) ) ) ) ; return out ; } /**
     * Return a stream whose events are the result of the combination using the specified
     * function of the input stream's event value and the value of the cells at that time.
     * <P>
     * There is an implicit delay: State updates caused by event firings being held with
     *  Stream don't become visible as the cell's current value until
     * the following transaction. To put this another way, snapshot()
     * always sees the value of a cell as it was before any state changes from the current
     * transaction.
      snapshot5 < B , C , D , E , F > ( b , c , d , e , f_ ) { const out = new StreamWithSend < F > ( null ) ; const ff = Lambda5_toFunction ( f_ ) ; out . vertex = new Vertex ( "snapshot" , 0 , [ new Source ( this . vertex , ( ) => { return this . listen_ ( out . vertex , ( a ) => { out . send_ ( ff ( a , b . sampleNoTrans__ ( ) , c . sampleNoTrans__ ( ) , d . sampleNoTrans__ ( ) , e . sampleNoTrans__ ( ) ) ) ; } , false ) ; } ) , new Source ( b . getVertex__ ( ) , null ) , new Source ( c . getVertex__ ( ) , null ) , new Source ( d . getVertex__ ( ) , null ) , new Source ( e . getVertex__ ( ) , null ) ] . concat ( toSources ( Lambda5_deps ( f_ ) ) ) ) ; return out ; } /**
     * Return a stream whose events are the result of the combination using the specified
     * function of the input stream's event value and the value of the cells at that time.
     * <P>
     * There is an implicit delay: State updates caused by event firings being held with
     *  Stream don't become visible as the cell's current value until
     * the following transaction. To put this another way, snapshot()
     * always sees the value of a cell as it was before any state changes from the current
     * transaction.
      snapshot6 < B , C , D , E , F , G > ( b , c , d , e , f , f_ ) { const out = new StreamWithSend < G > ( null ) ; const ff = Lambda6_toFunction ( f_ ) ; out . vertex = new Vertex ( "snapshot" , 0 , [ new Source ( this . vertex , ( ) => { return this . listen_ ( out . vertex , ( a ) => { out . send_ ( ff ( a , b . sampleNoTrans__ ( ) , c . sampleNoTrans__ ( ) , d . sampleNoTrans__ ( ) , e . sampleNoTrans__ ( ) , f . sampleNoTrans__ ( ) ) ) ; } , false ) ; } ) , new Source ( b . getVertex__ ( ) , null ) , new Source ( c . getVertex__ ( ) , null ) , new Source ( d . getVertex__ ( ) , null ) , new Source ( e . getVertex__ ( ) , null ) , new Source ( f . getVertex__ ( ) , null ) ] . concat ( toSources ( Lambda6_deps ( f_ ) ) ) ) ; return out ; } /**
     * Create a  Cell with the specified initial value, that is updated
     * by this stream's event values.
     * <p>
     * There is an implicit delay: State updates caused by event firings don't become
     * visible as the cell's current value as viewed by  Stream * until the following transaction. To put this another way,
     *  Stream always sees the value of a cell as it was before
     * any state changes from the current transaction.
      hold ( initValue ) { return new Cell < A > ( initValue , this ) ; } /**
     * A variant of  hold with an initial value captured by  Cell .
      holdLazy ( initValue ) { return new LazyCell < A > ( initValue , this ) ; } param f Function to apply to update the state. It may construct FRP logic or use
     *     Cell in which case it is equivalent to  Stream ing the
     *    cell. Apart from this the function must be <em>referentially transparent</em>.
      collect < B , S > ( initState , f ) { return this . collectLazy ( new Lazy < S > ( ( ) => { return initState ; } ) , f ) ; } /**
     * A variant of  collect that takes an initial state returned by
     *  Cell .
      collectLazy < B , S > ( initState , f ) { const ea = this ; return Transaction . run ( ( ) => { const es = new StreamLoop < S > ( ) , s = es . holdLazy ( initState ) , ebs = ea . snapshot ( s , f ) , eb = ebs . map ( ( bs ) => { return bs . a ; } ) , es_out = ebs . map ( ( bs ) => { return bs . b ; } ) ; es . loop ( es_out ) ; return eb ; } ) ; } param f Function to apply to update the state. It may construct FRP logic or use
     *     Cell in which case it is equivalent to  Stream ing the
     *    cell. Apart from this the function must be <em>referentially transparent</em>.
      accum < S > ( initState , f ) { return this . accumLazy ( new Lazy < S > ( ( ) => { return initState ; } ) , f ) ; } /**
     * A variant of  accum that takes an initial state returned by
     *  Cell .
      accumLazy < S > ( initState , f ) { const ea = this ; return Transaction . run ( ( ) => { const es = new StreamLoop < S > ( ) , s = es . holdLazy ( initState ) , es_out = ea . snapshot ( s , f ) ; es . loop ( es_out ) ; return es_out . holdLazy ( initState ) ; } ) ; } /**
     * Return a stream that outputs only one value: the next event of the
     * input stream, starting from the transaction in which once() was invoked.
     */ once ( ) { const me = this ; return Transaction . run ( ( ) => me . gate ( me . mapTo ( false ) . hold ( true ) ) ) ; } listen ( h ) { return Transaction . run < ( ) => void > ( ( ) => { return this . listen_ ( Vertex . NULL , h , false ) ; } ) ; } listen_ ( target , h , suppressEarlierFirings ) { if ( this . vertex . register ( target ) ) Transaction . currentTransaction . requestRegen ( ) ; const listener = new Listener < A > ( h , target ) ; this . listeners . push ( listener ) ; if ( ! suppressEarlierFirings && this . firings . length != 0 ) { const firings = this . firings . slice ( ) ; Transaction . currentTransaction . prioritized ( target , ( ) => { for ( let i = 0 ; i < firings . length ; i ++ ) h ( firings [ i ] ) ; } ) ; } return ( ) => { let removed = false ; for ( let i = 0 ; i < this . listeners . length ; i ++ ) { if ( this . listeners [ i ] == listener ) { this . listeners . splice ( i , 1 ) ; removed = true ; break ; } } if ( removed ) this . vertex . deregister ( target ) ; } ; } see https for more info
      'fantasy-land/map' < B > ( f ) { return this . map ( f ) ; } 'fantasy-land/concat' ( a ) { return this . merge ( a , ( left , right ) => { return ( Z . Semigroup . test ( left ) ) ? Z . concat ( left , right ) : left ; } ) ; } 'fantasy-land/empty' ( ) { return new Stream < A > ( ) ; } } export class StreamWithSend < A > extends Stream < A > { constructor ( vertex ? ) { super ( vertex ) ; } setVertex__ ( vertex ) { this . vertex = vertex ; } send_ ( a ) { if ( this . firings . length == 0 ) Transaction . currentTransaction . last ( ( ) => { this . firings = [ ] ; } ) ; this . firings . push ( a ) ; const listeners = this . listeners . slice ( ) ; for ( let i = 0 ; i < listeners . length ; i ++ ) { const h = listeners [ i ] . h ; Transaction . currentTransaction . prioritized ( listeners [ i ] . target , ( ) => { Transaction . currentTransaction . inCallback ++ ; try { h ( a ) ; Transaction . currentTransaction . inCallback -- ; } catch ( err ) { Transaction . currentTransaction . inCallback -- ; throw err ; } } ) ; } } } /**
 * A forward reference for a  Stream equivalent to the Stream that is referenced.
  export class StreamLoop < A > extends StreamWithSend < A > { assigned__ : boolean = false ; constructor ( ) { super ( ) ; this . vertex . name = "StreamLoop" ; if ( Transaction . currentTransaction === null ) throw new Error ( "StreamLoop/CellLoop must be used within an explicit transaction" ) ; } /**
     * Resolve the loop to specify what the StreamLoop was a forward reference to. It
     * must be invoked inside the same transaction as the place where the StreamLoop is used.
     * This requires you to create an explicit transaction with  Transaction * or  Transaction .
      loop ( sa_out ) { if ( this . assigned__ ) throw new Error ( "StreamLoop looped more than once" ) ; this . assigned__ = true ; this . vertex . addSource ( new Source ( sa_out . getVertex__ ( ) , ( ) => { return sa_out . listen_ ( this . vertex , ( a ) => { this . send_ ( a ) ; } , false ) ; } ) ) ; } }