namespace Blink.Blink
open Stdlib
open UnityPeripherals.Lowlevel

type 'a expr = 'a Asyncseq.expr

type coord =
{ roll: int; pitch: int }

type coord with
interface serializable<(int expr * int expr), coord> with
static member lit ((roll, pitch)) =
("%d", "%d"), Varargs.make2 roll pitch

interface evaluate<coord> with
static member eval (o: objnode) =
let roll, pitch =
int <| o.["Item1"].GetValue<string>(),
int <| o.["Item2"].GetValue<string>()
{ roll = roll; pitch = pitch }

open Stdlib.Syntax
open UnityPeripherals
open UnityPeripherals.Syntax
open UnityPeripherals.Lowlevel
open UnityPeripherals.Lowlevel.Math
open UnityPeripherals.Lowlevel.Math.Double.Syntax

type editor_app() =
inherit editor_os<coord>()

let rec seq' env () = (seq+async) {
let to_led, clock = env
let led x = Io.bit_write to_led (lit x)
let ( .. ) setter value = async {
let delay = Async.sleep clock (lit 1003)
let! () = setter value in do! delay
return lit () }
do! ( .. ) led true
yield int 1, int 2
do! ( .. ) led false
yield! seq' env }

override __.seq with get () =
let clock = Stdenv.clock ()
UnityPeripherals.Seq.append base.seq @@
Io.with_open Io.led_builtin @@ fun p ->
seq' (p, clock) ()

namespace Blink.Main

open Stdlib.Asyncseq

let main' () =
let seq = Task.start <Blink.Blink.editor_app, _> ()
seq |> Seq.Task.iter @@ fun { roll; pitch } ->
printfn "roll: %d; pitch: %d" roll pitch
10

[<EntryPoint>]
let main _ =
main' (); 0