@@ -64,6 +64,68 @@ let rec to_string (shape : t) =
6464 | Top -> " "
6565 | _ -> " ->" ^ to_string res)
6666
67+ let of_string (s : string ) =
68+ let pos = ref 0 in
69+ let current () = s.[! pos] in
70+ let next () = incr pos in
71+ let parse_char c =
72+ let c' = current () in
73+ if Char. equal c c' then next () else assert false
74+ in
75+ let parse_char_opt c =
76+ let c' = current () in
77+ if Char. equal c c'
78+ then (
79+ next () ;
80+ true )
81+ else false
82+ in
83+ let rec parse_int acc =
84+ match current () with
85+ | '0' .. '9' as c ->
86+ let d = Char. code c - Char. code '0' in
87+ let acc = (acc * 10 ) + d in
88+ next () ;
89+ parse_int acc
90+ | _ -> acc
91+ in
92+ let rec parse_shape () =
93+ match current () with
94+ | '[' ->
95+ next () ;
96+ parse_block []
97+ | 'N' ->
98+ next () ;
99+ Top
100+ | 'F' ->
101+ next () ;
102+ parse_fun ()
103+ | c -> failwith (String. make 1 c)
104+ and parse_block acc =
105+ let x = parse_shape () in
106+ match current () with
107+ | ',' ->
108+ next () ;
109+ parse_block (x :: acc)
110+ | ']' ->
111+ next () ;
112+ Block (List. rev (x :: acc))
113+ | _ -> assert false
114+ and parse_fun () =
115+ let () = parse_char '(' in
116+ let arity = parse_int 0 in
117+ let () = parse_char ')' in
118+ let pure = parse_char_opt '*' in
119+ match current () with
120+ | '-' ->
121+ next () ;
122+ parse_char '>' ;
123+ let res = parse_shape () in
124+ Function { arity; pure; res }
125+ | _ -> Function { arity; pure; res = Top }
126+ in
127+ parse_shape ()
128+
67129module Store = struct
68130 let ext = " .jsoo-shape"
69131
@@ -82,11 +144,21 @@ module Store = struct
82144 let load' fn =
83145 let ic = open_in_bin fn in
84146 let m = really_input_string ic (String. length magic) in
85- if not (String. equal m magic)
86- then failwith (Printf. sprintf " Invalid magic number for shape file %s" fn);
87- let shapes : (string * shape) list = Marshal. from_channel ic in
88- close_in ic;
89- List. iter shapes ~f: (fun (name , shape ) -> set ~name shape)
147+ if String. equal m magic
148+ then (
149+ let shapes : (string * shape) list = Marshal. from_channel ic in
150+ close_in ic;
151+ List. iter shapes ~f: (fun (name , shape ) -> set ~name shape))
152+ else (
153+ close_in ic;
154+ let l = file_lines_bin fn in
155+ List. iter l ~f: (fun s ->
156+ match String. drop_prefix ~prefix: " //#shape: " s with
157+ | None -> ()
158+ | Some name_n_shape -> (
159+ match String. lsplit2 name_n_shape ~on: ':' with
160+ | None -> ()
161+ | Some (name , shape ) -> set ~name (of_string shape))))
90162
91163 let load ~name ~paths =
92164 if String.Hashtbl. mem t name
0 commit comments