(.using
  [library
   [lux {"-" if loop}
    ["$" documentation {"+" documentation:}]
    [data
     [text {"+" \n}
      ["%" format {"+" format}]]]
    [macro
     ["[0]" template]]]]
  [\\library
   ["[0]" /]])

(documentation: /.new>
  "Ignores the piped argument, and begins a new pipe."
  [(n.= 1
        (|> 20
            (n.* 3)
            (n.+ 4)
            (new> 0 [++])))])

(documentation: /.let>
  "Gives a name to the piped-argument, within the given expression."
  [(n.= 10
        (|> 5
            (let> x (n.+ x x))))])

(documentation: /.cond>
  (format "Branching for pipes."
          \n "Both the tests and the bodies are piped-code, and must be given inside a tuple.")
  [(|> +5
       (cond> [i.even?] [(i.* +2)]
              [i.odd?] [(i.* +3)]
              [(new> -1 [])]))])

(documentation: /.if>
  "If-branching."
  [(same? (if (n.even? sample)
            "even"
            "odd")
          (|> sample
              (if> [n.even?]
                   [(new> "even" [])]
                   [(new> "odd" [])])))])

(documentation: /.when>
  "Only execute the body when the test passes."
  [(same? (if (n.even? sample)
            (n.* 2 sample)
            sample)
          (|> sample
              (when> [n.even?]
                     [(n.* 2)])))])

(documentation: /.loop>
  (format "Loops for pipes."
          \n "Both the testing and calculating steps are pipes and must be given inside tuples.")
  [(|> +1
       (loop> [(i.< +10)]
              [++]))])

(documentation: /.do>
  (format "Monadic pipes."
          \n "Each steps in the monadic computation is a pipe and must be given inside a tuple.")
  [(|> +5
       (do> identity.monad
            [(i.* +3)]
            [(i.+ +4)]
            [++]))])

(documentation: /.exec>
  (format "Non-updating pipes."
          \n "Will generate piped computations, but their results will not be used in the larger scope.")
  [(|> +5
       (exec> [.nat %n log!])
       (i.* +10))])

(documentation: /.tuple>
  (format "Parallel branching for pipes."
          \n "Allows to run multiple pipelines for a value and gives you a tuple of the outputs.")
  [(|> +5
       (tuple> [(i.* +10)]
               [-- (i./ +2)]
               [i#encoded]))
   "=>"
   [+50 +2 "+5"]])

(documentation: /.case>
  (format "Pattern-matching for pipes."
          \n "The bodies of each branch are NOT pipes; just regular values.")
  [(|> +5
       (case> +0 "zero"
              +1 "one"
              +2 "two"
              +3 "three"
              +4 "four"
              +5 "five"
              +6 "six"
              +7 "seven"
              +8 "eight"
              +9 "nine"
              _ "???"))])

(.def: .public documentation
  (.List $.Module)
  ($.module /._
            "Composable extensions to the piping macros (|> and <|) that enhance them with various abilities."
            [..new>
             ..let>
             ..cond>
             ..if>
             ..when>
             ..loop>
             ..do>
             ..exec>
             ..tuple>
             ..case>]
            []))
