Add cstr_record

This commit is contained in:
Jeremie Dimino 2017-12-21 19:34:11 +08:00 committed by Rudi Grinberg
parent e06c060121
commit 5d451e7034
2 changed files with 31 additions and 12 deletions

View File

@ -343,20 +343,35 @@ module Of_sexp = struct
let ( @> ) a b = Constructor_args_spec.Cons (a, b) let ( @> ) a b = Constructor_args_spec.Cons (a, b)
module Constructor_spec = struct module Constructor_spec = struct
type ('a, 'b, 'c) unpacked = type ('a, 'b, 'c) tuple =
{ name : string { name : string
; args : ('a, 'b) Constructor_args_spec.t ; args : ('a, 'b) Constructor_args_spec.t
; rest : ('b, 'c) rest ; rest : ('b, 'c) rest
; make : Loc.t -> 'a ; make : Loc.t -> 'a
} }
type 'a t = T : (_, _, 'a) unpacked -> 'a t type 'a record =
{ name : string
; parse : 'a record_parser
}
type 'a t =
| Tuple : (_, _, 'a) tuple -> 'a t
| Record : 'a record -> 'a t
let name = function
| Tuple x -> x.name
| Record x -> x.name
end end
module C = Constructor_spec
let cstr_loc name args make = let cstr_loc name args make =
Constructor_spec.T { name; args; make; rest = No_rest } C.Tuple { name; args; make; rest = No_rest }
let cstr_rest_loc name args rest make = let cstr_rest_loc name args rest make =
Constructor_spec.T { name; args; make; rest = Many rest } C.Tuple { name; args; make; rest = Many rest }
let cstr_record name parse =
C.Record { name; parse }
let cstr name args make = let cstr name args make =
cstr_loc name args (fun _ -> make) cstr_loc name args (fun _ -> make)
@ -368,8 +383,8 @@ module Of_sexp = struct
let find_cstr cstrs sexp name = let find_cstr cstrs sexp name =
match match
List.find cstrs ~f:(fun (Constructor_spec.T cstr) -> List.find cstrs ~f:(fun cstr ->
equal_cstr_name cstr.name name) equal_cstr_name (C.name cstr) name)
with with
| Some cstr -> cstr | Some cstr -> cstr
| None -> | None ->
@ -377,22 +392,24 @@ module Of_sexp = struct
"Unknown constructor %s%s" name "Unknown constructor %s%s" name
(hint (hint
(String.uncapitalize_ascii name) (String.uncapitalize_ascii name)
(List.map cstrs ~f:(fun (Constructor_spec.T c) -> (List.map cstrs ~f:(fun c ->
String.uncapitalize_ascii c.name))) String.uncapitalize_ascii (C.name c))))
let sum cstrs sexp = let sum cstrs sexp =
match sexp with match sexp with
| Atom (loc, s) -> begin | Atom (loc, s) -> begin
let (Constructor_spec.T c) = find_cstr cstrs sexp s in match find_cstr cstrs sexp s with
Constructor_args_spec.convert c.args c.rest sexp [] (c.make loc) | C.Tuple t -> Constructor_args_spec.convert t.args t.rest sexp [] (t.make loc)
| C.Record _ -> of_sexp_error sexp "'%s' expect arguments"
end end
| List (_, []) -> of_sexp_error sexp "non-empty list expected" | List (_, []) -> of_sexp_error sexp "non-empty list expected"
| List (loc, name_sexp :: args) -> | List (loc, name_sexp :: args) ->
match name_sexp with match name_sexp with
| List _ -> of_sexp_error name_sexp "Atom expected" | List _ -> of_sexp_error name_sexp "Atom expected"
| Atom (_, s) -> | Atom (_, s) ->
let (Constructor_spec.T c) = find_cstr cstrs sexp s in match find_cstr cstrs sexp s with
Constructor_args_spec.convert c.args c.rest sexp args (c.make loc) | C.Tuple t -> Constructor_args_spec.convert t.args t.rest sexp args (t.make loc)
| C.Record r -> record r.parse (List (loc, args))
let enum cstrs sexp = let enum cstrs sexp =
match sexp with match sexp with

View File

@ -85,6 +85,8 @@ module Of_sexp : sig
-> 'a -> 'a
-> 'c Constructor_spec.t -> 'c Constructor_spec.t
val cstr_record : string -> 'a record_parser -> 'a Constructor_spec.t
val cstr_loc val cstr_loc
: string : string
-> ('a, 'b) Constructor_args_spec.t -> ('a, 'b) Constructor_args_spec.t