(module series_sma

  (data FloatList
    (ctor FNil)
    (ctor FCons (con Float) (con FloatList)))

  (fn sum_window_step
    (type (fn-type
      (params (borrow (con Series (con Float))) (own (con Int)) (own (con Int)) (own (con Float)))
      (ret (own (con Float)))))
    (params s n i acc)
    (body
      (if (app eq i n)
        acc
        (tail-app sum_window_step s n
          (app + i 1)
          (app + acc (app Series.at s i))))))

  (fn emit_if_full
    (type (fn-type
      (params (borrow (con Series (con Float))) (own (con Int)))
      (ret (own (con Unit))) (effects IO)))
    (params s n)
    (body
      (if (app ge (app Series.total_count s) n)
        (seq
          (app print (app /
            (app sum_window_step s n 0 0.0)
            (app int_to_float n)))
          (do io/print_str "\n"))
        (do io/print_str ""))))

  (fn run_stream
    (type (fn-type
      (params (own (con Series (con Float))) (own (con Int)) (own (con FloatList)))
      (ret (own (con Unit))) (effects IO)))
    (params s n input)
    (body
      (match input
        (case (pat-ctor FNil) (do io/print_str ""))
        (case (pat-ctor FCons v rest)
          (let s_new (app Series.push s v)
            (seq (app emit_if_full s_new n)
              (tail-app run_stream s_new n rest)))))))

  (fn main
    (type (fn-type (params) (ret (own (con Unit))) (effects IO)))
    (params)
    (body
      (let s (new Series (con Float) 3)
        (app run_stream s 3
          (term-ctor FloatList FCons 1.0
          (term-ctor FloatList FCons 5.0
          (term-ctor FloatList FCons 3.0
          (term-ctor FloatList FCons 8.0
          (term-ctor FloatList FCons 6.0
          (term-ctor FloatList FCons 2.0
          (term-ctor FloatList FNil))))))))))))
