(define $SH.gen-input
  (lambda [$sopts $copts]
    (if (io (eof?))
      {}
      (let {[$x (io (TSV.read-line sopts copts))]}
        (seq x {x @(SH.gen-input sopts copts)})))))

(define $TSV.read-line
  (lambda [$sopts $copts]
    (do {[$line (read-line)]}
      (let {[$fs (S.split "\t" line)]}
        (letrec {[$fn-s (match-lambda [(list (list integer)) (list string)]
                          {[[<nil> $fs] fs]
                           [[<cons <cons $m <nil>> $opts'>
                             <join (& $hs ?(lambda [$hs] (eq? (- m 1) (length hs))))
                                   $ts>]
                            (fn-s opts' {@hs @(map (lambda [$t] (S.concat {"\"" t "\""})) ts)})]
                           [[<cons <cons $m <cons ,m <nil>>> $opts'>
                             <join (& $hs ?(lambda [$hs] (eq? (- m 1) (length hs))))
                                   <cons $mf $ts>>]
                            (fn-s opts' {@hs (S.concat {"\"" mf "\""}) @ts})]
                           [[<cons <cons $m <cons $n <nil>>> $opts'>
                             <join (& $hs ?(lambda [$hs] (eq? (- m 1) (length hs))))
                                   <join (& $ms ?(lambda [$ms] (eq? (+ (- n m) 1) (length ms))))
                                         $ts>>]
                            (fn-s opts' {@hs @(map (lambda [$m] (S.concat {"\"" m "\""})) ms) @ts})]
                           [[<cons <cons $m <cons _ <nil>>> $opts'>
                             _]
                            (fn-s {{m} @opts'} fs)]
                           [[_ _] fs]
                           })]
                 [$fn-c (match-lambda [(list (list integer)) (list string)]
                          {[[<nil> $fs] fs]
                           [[<cons <cons $m <nil>> $opts'>
                             <join (& $hs ?(lambda [$hs] (eq? (- m 1) (length hs))))
                                   <cons $mf <nil>>>]
                            (fn-c opts' {@hs (S.concat {"{" mf "}"})})]
                           [[<cons <cons $m <nil>> $opts'>
                             <join (& $hs ?(lambda [$hs] (eq? (- m 1) (length hs))))
                                   <cons $mf <snoc $tf $ms>>>]
                            (fn-c opts' {@hs (S.append "{" mf) @ms (S.append tf "}")})]
                           [[<cons <cons $m <cons ,m <nil>>> $opts'>
                             <join (& $hs ?(lambda [$hs] (eq? (- m 1) (length hs))))
                                   <cons $mf $ts>>]
                            (fn-c opts' {@hs (S.concat {"{" mf "}"}) @ts})]
                           [[<cons <cons $m <cons $n <nil>>> $opts'>
                             <join (& $hs ?(lambda [$hs] (eq? (- m 1) (length hs))))
                                   <cons $mf <join (& $ms ?(lambda [$ms] (eq? (- n m 1) (length ms))))
                                                   <cons $nf $ts>>>>]
                            (fn-c opts' {@hs (S.append "{" mf) @ms (S.append nf "}") @ts})]
                           [[<cons <cons $m <cons _ <nil>>> $opts'>
                             _]
                            (fn-c {{m} @opts'} fs)]
                           [[_ _] fs]
                           })]}
          (return (read-tsv (S.intercalate "\t" (fn-c copts (fn-s sopts fs))))))))))

(define $TSV.show show-tsv)