#line 8 "/home/ubuntu/felix/src/packages/chips.fdoc"
  open class BaseChips
  {
  
  chip writeblock[T]
    connector io
      pin inp : %<T
  {
  }
  
  #line 20 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip readblock[T]
    connector io
      pin out: %>T
  {
  }
  
  
  #line 30 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip sink[T]
    connector io
      pin inp : %<T
  {
    while true do
      var x = read (io.inp);
      C_hack::ignore (x);
    done
  }
  
  #line 43 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip source[T] (a:T)
    connector io
      pin out: %>T
  {
    while true do
      write (io.out, a);
    done
  }
  #line 53 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip value[T] (a:T)
    connector io
      pin out: %>T
  {
    write (io.out, a);
  }
  
  #line 62 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip generator[T] (g: 1->T)
    connector io
      pin out: %>T
    {
      repeat perform write (io.out, g());
    }
  
  #line 71 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip iterate[T] (g: 1->opt[T])
    connector io
      pin out: %>T
    {
      again:>
        var x = g();
        match x with
        | Some v =>
          write (io.out, v);
          goto again;
        | None => ;
        endmatch;
    }
  
  #line 87 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip source_from_list[T] (a:list[T])
    connector io
      pin out: %>T
  {
    for y in a perform write (io.out,y);
  }
  
  chip bound_source_from_list[T] (a:list[T])
    connector io
      pin out: %>opt[T]
  {
    for y in a perform write (io.out,Some y);
    while true perform write (io.out,None[T]);
  }
  
  
  #line 106 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip function[D,C] (f:D->C)
    connector io
      pin inp: %<D
      pin out: %>C
  {
    while true do
      var x = read io.inp;
      var y = f x;
      write (io.out, y);
    done
  }
  
  #line 121 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip procedure[D] (p:D->0)
    connector io
      pin inp: %<D
  {
    while true do
      var x = read io.inp;
      p x;
    done
  }
  
  #line 135 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip filter[D,C] (c:D->bool) (f:D->C)
    connector io
      pin inp: %<D
      pin out: %>C
  {
    while true do
      var x = read io.inp;
      if c x do
         write (io.out, f x);
      done
    done
  }
  
  chip filter[D,C] (f:D->opt[C])
    connector io
      pin inp: %<D
      pin out: %>C
  {
    while true do
      var x = read io.inp;
      match f x with
      | Some y => write (io.out, y);
      | None => ;
      endmatch;
    done
  }
  
  #line 164 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip sink_to_list[T] (p: &list[T])
    connector io
      pin inp : %<T
  {
    while true do
      var x = read (io.inp);
      p <- Cons (x,*p);
    done
  }
  
  #line 176 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip sink_to_unique_list[T with Eq[T]] (p: &list[T])
    connector io
      pin inp : %<T
  {
    while true do
      var x = read (io.inp);
      if not (x in *p) perform
        p <- Cons (x,*p)
      ;
    done
  }
  
  
  
  #line 193 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip buffer [T]
    connector io
      pin inp: %<T
      pin out: %>T
  {
    while true do
      var x = read io.inp;
      write (io.out, x);
    done
  }
  
  chip dup [T]
    connector io
      pin inp: %<T
      pin out1: %>T
      pin out2: %>T
  {
    while true do
      var x = read io.inp;
      write (io.out1, x);
      write (io.out2, x);
    done
  }
  
  
  #line 224 "/home/ubuntu/felix/src/packages/chips.fdoc"
  // two transducers
  chip pipe[T,U,V] (a:iochip_t[T,U],b:iochip_t[U,V])
   connector io
     pin inp: %<T
     pin out: %>V
  {
    circuit
      connect a.out,b.inp
      wire io.inp to a.inp
      wire io.out to b.out
    endcircuit
  }
  
  // source to transducer
  chip pipe[T,U] (a:ochip_t[T],b:iochip_t[T,U])
   connector io
     pin out: %>U
  {
    circuit
      connect a.out,b.inp
      wire io.out to b.out
    endcircuit
  }
  
  // transducer to sink
  chip pipe[T,U] (a:iochip_t[T,U],b:ichip_t[U])
   connector io
     pin inp: %<T
  {
    circuit
      connect a.out,b.inp
      wire io.inp to a.inp
    endcircuit
  }
  
  // source to sink
  proc pipe[T] (a:ochip_t[T],b:ichip_t[T])  ()
  {
    circuit
      connect a.out,b.inp
    endcircuit
  }
  
  
  #line 271 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip debug_buffer [T with Str[T]] (tag:string)
    connector io
      pin inp: %<T
      pin out: %>T
  {
    while true do
      println$ "Debug buffer [" + tag + "] READ";
      var x = read io.inp;
      println$ "Debug buffer [" + tag + "] read " + x.str;
      write (io.out, x);
      println$ "Debug buffer [" + tag + "] written " + x.str;
    done
  }
  
  #line 288 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip oneshot [T]
    connector io
      pin inp: %<T
      pin out: %>T
  {
    var x = read io.inp;
    write (io.out, x);
  }
  
  #line 300 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip store[T] (p:&T)
    connector io
      pin inp: %<T
  {
    while true do
      var x = read io.inp;
      p <- x;
    done
  }
  
  #line 313 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip fetch[T] (p:&T)
    connector io
      pin out: %>T
  {
    while true do
      write (io.out, *p);
    done
  }
  
  #line 326 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip debug_sink [T with Str[T]] (s:string)
    connector io
      pin inp: %<T
  {
    while true do
      var x = read io.inp;
      println$ "Debug sink ["+s+"] "+x.str;
    done
  }
  
  
  #line 342 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip latch[T]
    connector io
      pin inp: %<T
      pin out: %>T
  {
     var x = read io.inp;
     device w = fetch &x;
     device r = store &x;
     circuit
       wire io.inp to r.inp
       wire io.out to w.out
     endcircuit
  }
  
  #line 363 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip serialise_chan_list[T] (a: list[%<T])
   connector io
     pin out: %>T
  {
    while true do
      var current = a;
  next:>
      match current with
      | Cons (h,t) =>
        var x = read h;
        write (io.out, x);
        current = t;
        goto next;
      | Empty => ;
      endmatch;
    done
  }
  
  typedef iopair_t[D,C] = (inp: %<D, out: %>C);
  
  // transducer
  typedef iochip_t[D,C] = iopair_t[D,C] -> 1 -> 0;
  
  // sink
  typedef ichip_t[T] = (inp: %<T) -> 1 -> 0;
  
  // source
  typedef ochip_t[T] = (out: %>T) -> 1 -> 0;
  
  chip pipeline_list[T] (a: list[iochip_t[T,T]])
    connector io
      pin inp: %<T
      pin out: %>T
  {
    proc aux (lst:list[iochip_t[T,T]]) (inp: %<T) {
      match lst with
      | h1 ! h2 ! tail =>
        var inchan,outchan = mk_ioschannel_pair[T]();
        spawn_fthread$  h1 (inp=inp, out=outchan);
        aux (h2!tail) inchan;
      | h1 ! _ =>
        spawn_fthread$  h1 (inp=inp, out=io.out);
      | Empty =>
        spawn_fthread$ buffer (inp=io.inp, out=io.out);
      endmatch;
    }
    aux a io.inp;
  }
  
  // This loops, but only by repeatedly spawning
  // the alternative set. The alternatives are restricted
  // to a single read on each iteration. The chips are
  // respawned because they might be locked up, in which
  // case the whole thing locks up.
  //
  // NOTE: if one of the alternatives starts, and does not
  // read the input, everything locks up. This is because
  // the implementation ACTUALLY progresses serially.
  //
  // this COULD be fixed by adding a buffer to the front of
  // each. Actually better, add a one shot source based
  // on the input.
  chip tryall_list[D,C with Str[D]] (a: list[iochip_t[D,C]])
    connector io
      pin inp: %<D
      pin out: %>C
  {
    while true do
      var x = read io.inp;
      //println$ "Tryall read " + a.len.str + " alternatives: " + x.str;
      //var counter = 1;
      for h in a do
        //println$ "Trying alternative #" + counter.str + "/"+a.len.str;
        var lin,lout = mk_ioschannel_pair[D]();
        spawn_fthread (h (inp=lin, out=io.out));
        //println$ "Tryall_list write " + lout.address.str;
        write (lout,x);
      done
    done
  }
  
  #line 448 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip deref_each_read[D,C] (p:&iochip_t[D,C])
    connector io
      pin inp: %<D
      pin out: %>C
  {
    while true do
      var x = read io.inp;
      var rinp,rout = mk_ioschannel_pair[D]();
      spawn_fthread ((*p) (inp=rinp, out=io.out));
      // println$ "Deref_each_read: write " + io.out.address.str;
      write (rout,x);
    done
  }
  
  chip deref_first_read[D,C] (p:&iochip_t[D,C])
    connector io
      pin inp: %<D
      pin out: %>C
  {
    var x = read io.inp;
    var rinp,rout = mk_ioschannel_pair[D]();
    spawn_fthread ((*p) (inp=rinp, out=io.out));
    write (rout,x);
    while true do
      x = read io.inp;
      write (rout,x);
    done
  }
  #line 480 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip epsilon[T]
    connector io
     pin inp: %<T
     pin out: %>T
  {
    while true do
      var x = read io.inp;
      //println$ "Epsilon: write " + io.out.address.str;
      write (io.out, x);
    done
  }
  #line 496 "/home/ubuntu/felix/src/packages/chips.fdoc"
  chip optional[T] (p:iochip_t[T,T])
    connector io
      pin inp: %<T
      pin out: %>T
  {
    device both = tryall_list ([
      p,
      epsilon[T]
    ]);
    circuit
      wire io.inp to both.inp
      wire io.out to both.out
    endcircuit
  }
  
  #line 513 "/home/ubuntu/felix/src/packages/chips.fdoc"
  
  chip oneormore_matcher[T] (A:iochip_t[T,T])
  connector chans
    pin inp: %<T
    pin out: %>T
  {
   device As = oneormore_matcher A;
   device As2 = pipeline_list (A,As).list;
   device Ass = tryall_list (A, As2).list;
   circuit
     wire chans.inp to Ass.inp
     wire chans.out to Ass.out
   endcircuit
  }
  
  #line 530 "/home/ubuntu/felix/src/packages/chips.fdoc"
  
  chip zeroormore_matcher[T] (A:iochip_t[T,T])
  connector chans
    pin inp: %<T
    pin out: %>T
  {
   device As = oneormore_matcher A;
   device Ass = tryall_list (epsilon[T], As).list;
   circuit
     wire chans.inp to Ass.inp
     wire chans.out to Ass.out
   endcircuit
  }
  #line 546 "/home/ubuntu/felix/src/packages/chips.fdoc"
  } // end class BaseChips