|
63 | 63 | type directive = Directive.Processed.t |
64 | 64 |
|
65 | 65 | module Sexp = struct |
66 | | - type t = Atom of string | List of t list |
| 66 | + type t = Csexp.t = Atom of string | List of t list |
67 | 67 |
|
68 | 68 | let atoms_of_strings = List.map ~f:(fun s -> Atom s) |
69 | 69 |
|
@@ -127,39 +127,94 @@ module Sexp = struct |
127 | 127 | List (List.map ~f directives) |
128 | 128 | end |
129 | 129 |
|
130 | | -module Csexp = Csexp.Make (Sexp) |
| 130 | +type read_error = |
| 131 | + | Unexpected_output of string |
| 132 | + | Csexp_parse_error of string |
| 133 | + |
| 134 | +type command = File of string | Halt | Unknown |
| 135 | + |
| 136 | +module type S = sig |
| 137 | + type 'a io |
| 138 | + type in_chan |
| 139 | + type out_chan |
131 | 140 |
|
132 | | -module Commands = struct |
133 | | - type t = File of string | Halt | Unknown |
| 141 | + (** [read] reads one csexp from the channel and returns the list of |
| 142 | + directives it represents *) |
| 143 | + val read : |
| 144 | + in_chan -> (directive list, read_error) Merlin_utils.Std.Result.t io |
134 | 145 |
|
135 | | - let read_input in_channel = |
136 | | - let open Sexp in |
137 | | - match Csexp.input in_channel with |
138 | | - | Ok (List [Atom "File"; Atom path]) -> File path |
139 | | - | Ok (Atom "Halt") -> Halt |
140 | | - | Ok _ -> Unknown |
141 | | - | Error _msg -> Halt |
| 146 | + val write : out_chan -> directive list -> unit io |
142 | 147 |
|
143 | | - let send_file ~out_channel path = |
144 | | - Sexp.(List [Atom "File"; Atom path]) |
145 | | - |> Csexp.to_channel out_channel |
| 148 | + module Commands : sig |
| 149 | + val read_input : in_chan -> command io |
| 150 | + |
| 151 | + val send_file : out_chan -> string -> unit io |
| 152 | + |
| 153 | + val halt : out_chan -> unit io |
| 154 | + end |
146 | 155 | end |
147 | 156 |
|
148 | | -type read_error = |
149 | | - | Unexpected_output of string |
150 | | - | Csexp_parse_error of string |
| 157 | +module Make (IO : sig |
| 158 | + type 'a t |
151 | 159 |
|
152 | | -let read ~in_channel = |
153 | | - match Csexp.input in_channel with |
154 | | - | Ok (Sexp.List directives) -> |
155 | | - Ok (List.map directives ~f:Sexp.to_directive) |
156 | | - | Ok sexp -> |
157 | | - let msg = Printf.sprintf |
158 | | - "A list of directives was expected, instead got: \"%s\"" |
159 | | - (Sexp.to_string sexp) |
160 | | - in |
161 | | - Error (Unexpected_output msg) |
162 | | - | Error msg -> Error (Csexp_parse_error msg) |
| 160 | + module O : sig |
| 161 | + val ( let+ ) : 'a t -> ('a -> 'b) -> 'b t |
| 162 | + end |
| 163 | +end) (Chan : sig |
| 164 | + type in_chan |
| 165 | + type out_chan |
| 166 | + |
| 167 | + val read : in_chan -> (Csexp.t, string) result IO.t |
| 168 | + |
| 169 | + val write : out_chan -> Csexp.t -> unit IO.t |
| 170 | +end) = |
| 171 | +struct |
| 172 | + type 'a io = 'a IO.t |
| 173 | + type in_chan = Chan.in_chan |
| 174 | + type out_chan = Chan.out_chan |
| 175 | + |
| 176 | + module Commands = struct |
| 177 | + let read_input chan = |
| 178 | + let open Sexp in |
| 179 | + let open IO.O in |
| 180 | + let+ input = Chan.read chan in |
| 181 | + match input with |
| 182 | + | Ok (List [Atom "File"; Atom path]) -> File path |
| 183 | + | Ok (Atom "Halt") -> Halt |
| 184 | + | Ok _ -> Unknown |
| 185 | + | Error _ -> Halt |
| 186 | + |
| 187 | + let send_file chan path = |
| 188 | + Chan.write chan Sexp.(List [Atom "File"; Atom path]) |
| 189 | + |
| 190 | + let halt chan = Chan.write chan (Sexp.Atom "Halt") |
| 191 | + end |
| 192 | + |
| 193 | + let read chan = |
| 194 | + let open IO.O in |
| 195 | + let+ res = Chan.read chan in |
| 196 | + match res with |
| 197 | + | Ok (Sexp.List directives) -> Ok (List.map directives ~f:Sexp.to_directive) |
| 198 | + | Ok sexp -> |
| 199 | + let msg = |
| 200 | + Printf.sprintf "A list of directives was expected, instead got: \"%s\"" |
| 201 | + (Sexp.to_string sexp) |
| 202 | + in |
| 203 | + Error (Unexpected_output msg) |
| 204 | + | Error msg -> Error (Csexp_parse_error msg) |
| 205 | + |
| 206 | + let write out_chan (directives : directive list) = |
| 207 | + directives |> Sexp.from_directives |> Chan.write out_chan |
| 208 | +end |
163 | 209 |
|
164 | | -let write ~out_channel (directives : directive list) = |
165 | | - directives |> Sexp.from_directives |> Csexp.to_channel out_channel |
| 210 | +module Blocking = |
| 211 | + Make (struct |
| 212 | + type 'a t = 'a |
| 213 | + module O = struct let ( let+ ) x f = f x end |
| 214 | + end) |
| 215 | + (struct |
| 216 | + type in_chan = in_channel |
| 217 | + type out_chan = out_channel |
| 218 | + let read = Csexp.input |
| 219 | + let write = Csexp.to_channel |
| 220 | + end) |
0 commit comments