@@ -64,6 +64,73 @@ 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+ | _ -> assert false
104+ and parse_block acc =
105+ match current () with
106+ | ']' ->
107+ next () ;
108+ Block (List. rev acc)
109+ | _ -> (
110+ let x = parse_shape () in
111+ match current () with
112+ | ',' ->
113+ next () ;
114+ parse_block (x :: acc)
115+ | ']' ->
116+ next () ;
117+ Block (List. rev (x :: acc))
118+ | _ -> assert false )
119+ and parse_fun () =
120+ let () = parse_char '(' in
121+ let arity = parse_int 0 in
122+ let () = parse_char ')' in
123+ let pure = parse_char_opt '*' in
124+ match current () with
125+ | '-' ->
126+ next () ;
127+ parse_char '>' ;
128+ let res = parse_shape () in
129+ Function { arity; pure; res }
130+ | _ -> Function { arity; pure; res = Top }
131+ in
132+ parse_shape ()
133+
67134module Store = struct
68135 let ext = " .jsoo-shape"
69136
@@ -82,11 +149,21 @@ module Store = struct
82149 let load' fn =
83150 let ic = open_in_bin fn in
84151 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)
152+ if String. equal m magic
153+ then (
154+ let shapes : (string * shape) list = Marshal. from_channel ic in
155+ close_in ic;
156+ List. iter shapes ~f: (fun (name , shape ) -> set ~name shape))
157+ else (
158+ close_in ic;
159+ let l = file_lines_bin fn in
160+ List. iter l ~f: (fun s ->
161+ match String. drop_prefix ~prefix: " //#shape: " s with
162+ | None -> ()
163+ | Some name_n_shape -> (
164+ match String. lsplit2 name_n_shape ~on: ':' with
165+ | None -> ()
166+ | Some (name , shape ) -> set ~name (of_string shape))))
90167
91168 let load ~name ~paths =
92169 if String.Hashtbl. mem t name
0 commit comments