type 'control action = | Send of Transport.t | Wait_ms of int | Control of 'control type 'control t = 'control action Nonempty.t let valid_action = function | Wait_ms milliseconds when milliseconds < 0 -> Error "program wait must not be negative" | Send _ | Wait_ms _ | Control _ -> Ok () let rec validate = function | [] -> Ok () | action :: actions -> ( match valid_action action with | Error _ as error -> error | Ok () -> validate actions) let of_list actions = match validate actions with | Error _ as error -> error | Ok () -> Nonempty.of_list actions let to_list = Nonempty.to_list let compile ~send ~wait_ms ~control program = let rec loop acc = function | [] -> Ok (List.concat (List.rev acc)) | Send transport :: actions -> ( match send transport with | Error _ as error -> error | Ok compiled -> loop (compiled :: acc) actions) | Wait_ms milliseconds :: actions -> loop ([ wait_ms milliseconds ] :: acc) actions | Control action :: actions -> loop ([ control action ] :: acc) actions in loop [] (to_list program)